diff --git a/.idea/.gitignore b/.idea/.gitignore index 10b731c518c79596ed8690544cfbc87a98cf7e36..35410cacdc5e87f985c93a96520f5e11a5c822e4 100644 --- a/.idea/.gitignore +++ b/.idea/.gitignore @@ -3,3 +3,6 @@ /workspace.xml # 基于编辑器的 HTTP 客户端请求 /httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/ingenious.iml b/.idea/ingenious.iml index 4777ee26ad9450ec39a91baed8f6d0cdeb548ebd..100d017a0f285a0b303fdb50e188c1a2d2335a8e 100644 --- a/.idea/ingenious.iml +++ b/.idea/ingenious.iml @@ -5,9 +5,6 @@ - - - diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 9f63fbe872420835eb2ab71f4d41c0c2d9219337..fad58132ff0b1e079c5b621885ba2fc5e94530c6 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -1,14 +1,7 @@ \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7f4cb416c083d265558da75d457237d671..35eb1ddfbbc029bcab630581847471d7f238ec53 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 8da0a65340087c5dfa497a4917c43664cc636897..0000000000000000000000000000000000000000 --- a/LICENSE +++ /dev/null @@ -1,8 +0,0 @@ -# ingenious 许可条款 1.0 - -1. 免责声明:任何情况下根据任何法律,本作者不对用户因使用ingenious产生的侵权、数据损坏丢失、软硬件故障和违法犯罪等问题承担任何责任; -2. 禁止任何用户对ingenious进行简单包装后,即声称为自己的产品、销售源码获利; -3. ingenious为开源项目,获取到源代码的用户可自由修改源码供自身开发使用,可分发build构建后的库代码,也可分发ingenious源代码(需保留文件头部的作者声明),本作者保留ingenious的原始著作权; -4. 个人或公司用户均可将ingenious项目应用于商业项目开发,为支持本项目持续开发,请尽量购买ingeniousPRO版源码订阅更新服务; -5. 如果你不同意本许可条款,请勿使用ingenious;任何情况下,一旦实际使用ingenious,则代表你已确定完全同意本许可条款; -6. 条款内容结束。 \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 901e9b6e517b994c0c9740cadc4ae75c5c453f6e..0000000000000000000000000000000000000000 --- a/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# Ingenious 工作流引擎 - -#### 介绍 -工作流引擎自动化的核心工具,它具备流程建模、执行控制、任务分配、通知提醒、数据管理以及监控分析等功能。通过可视化设计工具,用户可以轻松定义和优化业务流程,确保任务按规则高效执行。引擎自动分配任务,实时通知相关人员,并提供数据管理和实时监控,助力企业全面掌控业务流程。工作流引擎的应用,显著提高了工作效率,降低了运营成本,为企业实现高效、智能的业务管理提供了有力支持。 - - - - -## ⭐交流群 - -交流群①:321796659 - -手册:http://flow.doc.ingenstream.cn/#/zh-cn/ 【付费】 - - - - - -## ⏰ 安装 -* 安装Composer -* composer require ingen/ingenious -* 开源不易,知识付费 详细教程请购买文档 [购买](https://pc.fenchuan8.com/#/index?forum=69121&yqm=M9RJ) - - - - - -## ㊙️ 链接 - ---- - -> 官方: -http://www.ingenstream.cn/ - -> 演示站点: -http://layui.flow.webman.ingenstream.cn/ -http://layui.flow.thinkphp.ingenstream.cn/ - -> 工作流手册: -http://flow.doc.ingenstream.cn/#/zh-cn/ 【付费】 - ---- - - -~~~ -对您有帮助的话,你可以在下方赞助我们,让我们更好的维护开发,谢谢! -特别声明:坚决打击网络诈骗行为,严禁将本插件集成在任何违法违规的程序上。 -~~~ - -如果对您有帮助,您可以点右上角 💘Star💘支持 diff --git a/composer.json b/composer.json index da02f593143021bf26a68e043ce430eaa0fccaf3..d66ed4135f014e7251b7a9fe65a2e6efda836e9f 100644 --- a/composer.json +++ b/composer.json @@ -1,24 +1,24 @@ -{ - "name": "ingen/ingenious", - "type": "library", - "license": "MIT", - "description": "a php work flow engine base on ingenious-php", - "autoload": { - "psr-4": { - "ingenious\\": "src" - } - }, - "authors": [ - { - "name": "Mr.April", - "homepage": "https://gitee.com/ingenstream", - "email": "405784684@qq.com" - } - ], - "require": { - "php": ">=8.0", - "ext-redis": "*", - "kphoen/rulerz": "^0.21.1", - "monolog/monolog": "*" - } -} +{ + "name": "ingen/ingenious", + "type": "library", + "license": "Apache-2.0", + "description": "a php work flow engine base on ingenious-php", + "autoload": { + "psr-4": { + "ingenious\\": "src" + } + }, + "authors": [ + { + "name": "Mr.April", + "homepage": "https://gitee.com/ingenstream", + "email": "405784684@qq.com" + } + ], + "require": { + "php": ">=8.0", + "ext-redis": "*", + "kphoen/rulerz": "^0.21.1", + "monolog/monolog": "*" + } +} diff --git a/demo/thinkphp/README.en.md b/demo/thinkphp/README.en.md new file mode 100644 index 0000000000000000000000000000000000000000..c3e48786304493320130f6523f0d6b21f011088f --- /dev/null +++ b/demo/thinkphp/README.en.md @@ -0,0 +1,36 @@ +# ingen_flow + +#### Description +引擎流tp后端 layuiUi前端 + +#### Software Architecture +Software architecture description + +#### Installation + +1. xxxx +2. xxxx +3. xxxx + +#### Instructions + +1. xxxx +2. xxxx +3. xxxx + +#### Contribution + +1. Fork the repository +2. Create Feat_xxx branch +3. Commit your code +4. Create Pull Request + + +#### Gitee Feature + +1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md +2. Gitee blog [blog.gitee.com](https://blog.gitee.com) +3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) +4. The most valuable open source project [GVP](https://gitee.com/gvp) +5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) +6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/demo/thinkphp/README.md b/demo/thinkphp/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c090d20ee62e3f57538028ea196d72e6fca7916a --- /dev/null +++ b/demo/thinkphp/README.md @@ -0,0 +1,37 @@ +# ingen_flow + +#### 介绍 +引擎流tp后端 layuiUi前端 + +#### 软件架构 +软件架构说明 + + +#### 安装教程 + +1. xxxx +2. xxxx +3. xxxx + +#### 使用说明 + +1. xxxx +2. xxxx +3. xxxx + +#### 参与贡献 + +1. Fork 本仓库 +2. 新建 Feat_xxx 分支 +3. 提交代码 +4. 新建 Pull Request + + +#### 特技 + +1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md +2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) +3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 +4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 +5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) +6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/demo/thinkphp/backend/.gitignore b/demo/thinkphp/backend/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5054a67e564790fb2303e60414d251eef5847227 --- /dev/null +++ b/demo/thinkphp/backend/.gitignore @@ -0,0 +1,12 @@ +*.log +.env +composer.phar +composer.lock +.DS_Store +Thumbs.db +/.idea +/.vscode +/vendor +/.settings +/.buildpath +/.project \ No newline at end of file diff --git a/demo/thinkphp/backend/.phpstorm.meta.php b/demo/thinkphp/backend/.phpstorm.meta.php new file mode 100644 index 0000000000000000000000000000000000000000..db3c0bea8b8b87540cd4b6b066c8302773e441ac --- /dev/null +++ b/demo/thinkphp/backend/.phpstorm.meta.php @@ -0,0 +1,21 @@ + \phoenix\utils\Json::class + ]) + ); + + override( + \think\Container::make(), + map([ + '' => '@' + ]) + ); +} diff --git a/demo/thinkphp/backend/.travis.yml b/demo/thinkphp/backend/.travis.yml new file mode 100644 index 0000000000000000000000000000000000000000..36f7b6f90dafe374d0eca306886df83f09ff13a9 --- /dev/null +++ b/demo/thinkphp/backend/.travis.yml @@ -0,0 +1,42 @@ +sudo: false + +language: php + +branches: + only: + - stable + +cache: + directories: + - $HOME/.composer/cache + +before_install: + - composer self-update + +install: + - composer install --no-dev --no-interaction --ignore-platform-reqs + - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip . + - composer require --update-no-dev --no-interaction "topthink/think-image:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0" + - composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0" + - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip . + +script: + - php think unit + +deploy: + provider: releases + api_key: + secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw= + file: + - ThinkPHP_Core.zip + - ThinkPHP_Full.zip + skip_cleanup: true + on: + tags: true diff --git a/demo/thinkphp/backend/LICENSE.txt b/demo/thinkphp/backend/LICENSE.txt new file mode 100644 index 0000000000000000000000000000000000000000..3dcd79ff46417196f8a72665c137e0aab6575bc8 --- /dev/null +++ b/demo/thinkphp/backend/LICENSE.txt @@ -0,0 +1,32 @@ + +ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 +版权所有Copyright © 2006-2023 by ThinkPHP (http://thinkphp.cn) +All rights reserved。 +ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 + +Apache Licence是著名的非盈利开源组织Apache采用的协议。 +该协议和BSD类似,鼓励代码共享和尊重原作者的著作权, +允许代码修改,再作为开源或商业软件发布。需要满足 +的条件: +1. 需要给代码的用户一份Apache Licence ; +2. 如果你修改了代码,需要在被修改的文件中说明; +3. 在延伸的代码中(修改和有源代码衍生的代码中)需要 +带有原来代码中的协议,商标,专利声明和其他原来作者规 +定需要包含的说明; +4. 如果再发布的产品中包含一个Notice文件,则在Notice文 +件中需要带有本协议内容。你可以在Notice中增加自己的 +许可,但不可以表现为对Apache Licence构成更改。 +具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0 + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/demo/thinkphp/backend/README.md b/demo/thinkphp/backend/README.md new file mode 100644 index 0000000000000000000000000000000000000000..1d554ff5c58e0e1dc3698a5e469c97408900fe09 --- /dev/null +++ b/demo/thinkphp/backend/README.md @@ -0,0 +1,388 @@ +# WorkingFlower 2.0 Demo 基于ThinkPHP8 +PearAdmin+LogicFlow流程设计器 + +## WorkingFloer 介绍 + +⭐⭐PHP WorkingFlower是一个基于ThinkPHP 8.0的开源工作流引擎,适用于企业应用中常见的业务流程。它以轻量、简单、灵巧为理念设计,致力于成为简单集成的多环境支持工作流引擎。以下是WorkingFlower引擎流的详细介绍: + +轻量级:WorkingFlower具有强大的扩展性。非常适合在资源有限的环境中使用。 +简单性:WorkingFlower的表设计简单,流程组件也十分简洁,包括start、end、task、custom、subprocess、decision、fork、join等元素,易于理解和使用。同时,2.0版本基于ThinkPHP 框架 ORM实现。 +灵巧性:WorkingFlower暴露了大量的可扩展接口,支持流程设计器、流程引擎的组件模型自定义,如节点自定义、属性自定义、表单自定义等。这意味着用户可以根据自己的需求来扩展和定制流程功能。 +数据持久层面支持:1.0版本为jdbc数据库支持有限 2.0版本采用thinkORM实现持久 解决支持多类型数据库,目前支持的数据库有sqlite pgsql oracle、mysql、sqlserver mongo等。 +总的来说,WorkingFloer是一个功能强大且易于集成的开源工作流引擎,适用于各种企业应用的业务流程。它以轻量、简单、灵巧为理念,旨在提高工作效率、降低生产成本并提升企业竞争力。 + + + + +## 设计器图集 + +![属性面板](https://foruda.gitee.com/images/1700640532197373837/078d3d7c_5445832.png "屏幕截图") + +![输入图片说明](https://foruda.gitee.com/images/1700640649760547121/97c6960a_5445832.png "屏幕截图") + +![输入图片说明](https://foruda.gitee.com/images/1700640698723935222/0173386d_5445832.png "屏幕截图") + +![输入图片说明](https://foruda.gitee.com/images/1700640729129530289/9e9d2aa5_5445832.png "屏幕截图") + +![输入图片说明](https://foruda.gitee.com/images/1700640774784152296/3087f6aa_5445832.png "屏幕截图") +![输入图片说明](https://foruda.gitee.com/images/1700640829904705712/ac7b6b1f_5445832.png "屏幕截图") +![输入图片说明](https://foruda.gitee.com/images/1700640872676949260/ad86f05d_5445832.png "屏幕截图") + + +## 引擎样列数据 + + +``` +{ + "name": "main01", + "display_name": "主流程含(请款子流程)", + "expire_time": "", + "instance_url": "leaveForm", + "instance_no_class": "", + "type": "workingflower:process", + "nodes": [ + { + "id": "189dfefa-6603-46f2-89e4-23ec52eaeb32", + "type": "workingflower:wfSubProcess", + "x": 340, + "y": 420, + "properties": { + "form": "leaveForm", + "color": "#000000", + "theme": "#FFFFFF", + "width": "182", + "height": "48", + "stroke": "#1c4573", + "version": "1.0", + "process_name": "test04", + "stroke_width": "2" + }, + "text": { + "x": 340, + "y": 420, + "value": "子流程-请款" + } + }, + { + "id": "1238cc65-5757-484c-b31d-bd039645ceae", + "type": "workingflower:start", + "x": 180, + "y": 180, + "properties": [], + "text": { + "x": 180, + "y": 220, + "value": "开始" + } + }, + { + "id": "3e517bac-d721-49e6-97d6-4e82debc8609", + "type": "workingflower:task", + "x": 340, + "y": 180, + "properties": { + "color": "#000000", + "field": [], + "scope": "5", + "theme": "#FFFFFF", + "width": "120", + "height": "40", + "stroke": "#000000", + "assignee": "", + "task_type": "Major", + "perform_type": "ANY", + "stroke_width": "2", + "back_permission": "1" + }, + "text": { + "x": 340, + "y": 180, + "value": "申请人" + } + }, + { + "id": "1fdcfa3b-29d0-4929-b6ae-9905982d75b4", + "type": "workingflower:decision", + "x": 340, + "y": 280, + "properties": [] + }, + { + "id": "ac2dbf64-a4cb-40bd-8e5b-59d514edf2d6", + "type": "workingflower:task", + "x": 560, + "y": 280, + "properties": { + "color": "#000000", + "field": [], + "scope": "1", + "theme": "#FFFFFF", + "width": "120", + "height": "40", + "stroke": "#000000", + "assignee": "admin", + "task_type": "Major", + "perform_type": "ANY", + "stroke_width": "2", + "back_permission": "1" + }, + "text": { + "x": 560, + "y": 280, + "value": "经理审批" + } + }, + { + "id": "8aa0debf-4213-4aee-a5f8-19dfcc1cf152", + "type": "workingflower:end", + "x": 760, + "y": 280, + "properties": [], + "text": { + "x": 760, + "y": 320, + "value": "结束节点" + } + } + ], + "edges": [ + { + "id": "b628c46c-544f-4dc0-9881-fbccfa684ce0", + "type": "workingflower:transition", + "sourceNodeId": "1238cc65-5757-484c-b31d-bd039645ceae", + "targetNodeId": "3e517bac-d721-49e6-97d6-4e82debc8609", + "startPoint": { + "x": 198, + "y": 180 + }, + "endPoint": { + "x": 280, + "y": 180 + }, + "properties": [], + "pointsList": [ + { + "x": 198, + "y": 180 + }, + { + "x": 280, + "y": 180 + } + ] + }, + { + "id": "868c2422-3120-41bf-99ae-4d400a88210e", + "type": "workingflower:transition", + "sourceNodeId": "3e517bac-d721-49e6-97d6-4e82debc8609", + "targetNodeId": "1fdcfa3b-29d0-4929-b6ae-9905982d75b4", + "startPoint": { + "x": 340, + "y": 200 + }, + "endPoint": { + "x": 340, + "y": 255 + }, + "properties": [], + "pointsList": [ + { + "x": 340, + "y": 200 + }, + { + "x": 340, + "y": 230 + }, + { + "x": 340, + "y": 230 + }, + { + "x": 340, + "y": 225 + }, + { + "x": 340, + "y": 225 + }, + { + "x": 340, + "y": 255 + } + ] + }, + { + "id": "ec67871c-4efe-4a6b-b714-86a4a06742d4", + "type": "workingflower:transition", + "sourceNodeId": "1fdcfa3b-29d0-4929-b6ae-9905982d75b4", + "targetNodeId": "ac2dbf64-a4cb-40bd-8e5b-59d514edf2d6", + "startPoint": { + "x": 365, + "y": 280 + }, + "endPoint": { + "x": 500, + "y": 280 + }, + "properties": { + "expr": "f_day < 1000" + }, + "text": { + "x": 432.5, + "y": 280, + "value": "小于1000万" + }, + "pointsList": [ + { + "x": 365, + "y": 280 + }, + { + "x": 500, + "y": 280 + } + ] + }, + { + "id": "f5644192-adfd-45a7-9e82-d708b3d6a94e", + "type": "workingflower:transition", + "sourceNodeId": "1fdcfa3b-29d0-4929-b6ae-9905982d75b4", + "targetNodeId": "189dfefa-6603-46f2-89e4-23ec52eaeb32", + "startPoint": { + "x": 340, + "y": 305 + }, + "endPoint": { + "x": 340, + "y": 400 + }, + "properties": { + "expr": "f_day > 1000" + }, + "text": { + "x": 340, + "y": 352.5, + "value": "大于1000万" + }, + "pointsList": [ + { + "x": 340, + "y": 305 + }, + { + "x": 340, + "y": 400 + } + ] + }, + { + "id": "4858f4e7-09dd-46d7-8012-17236de45c11", + "type": "workingflower:transition", + "sourceNodeId": "189dfefa-6603-46f2-89e4-23ec52eaeb32", + "targetNodeId": "ac2dbf64-a4cb-40bd-8e5b-59d514edf2d6", + "startPoint": { + "x": 400, + "y": 420 + }, + "endPoint": { + "x": 560, + "y": 300 + }, + "properties": [], + "pointsList": [ + { + "x": 400, + "y": 420 + }, + { + "x": 560, + "y": 420 + }, + { + "x": 560, + "y": 300 + } + ] + }, + { + "id": "8eb2d863-d5ca-4b7a-be3c-ab72d971f57a", + "type": "workingflower:transition", + "sourceNodeId": "ac2dbf64-a4cb-40bd-8e5b-59d514edf2d6", + "targetNodeId": "8aa0debf-4213-4aee-a5f8-19dfcc1cf152", + "startPoint": { + "x": 620, + "y": 280 + }, + "endPoint": { + "x": 742, + "y": 280 + }, + "properties": [], + "pointsList": [ + { + "x": 620, + "y": 280 + }, + { + "x": 742, + "y": 280 + } + ] + } + ] +} +``` + + + + +## 安装教程 + +1. composer install +2. 修改前端配置lms_admin/ims/confing 对应url +3. 前端访问地址访问ip/lms_admin/index +4. 账号admin 密码123456 其他账号密码均为123456 + + + +## 伪静态 + +``` + + Options +FollowSymlinks -Multiviews + RewriteEngine On + + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L] + +``` + + + + + +## ⭐交流群 +QQ 321796659 + + +## 使用案例 +[后端工程] (http://43.138.153.216:8005/lms_admin/index.html) + +[前端工程 vue设计器] (http://43.138.153.216:8003) + + + +## ✨ 鸣谢 Thanks + +- 感谢 [JetBrains](https://www.jetbrains.com) 提供生产力巨高的 `PHPStorm`和`WebStorm` +> 排名不分先后 + +- [top-think/think](https://github.com/top-think/think) +- [Layui](https://www.layui.com) +- [Senaker 国内最优秀的开源流程引擎Java](https://gitee.com/mldong) +- [logicFlow 优秀的表单设计器,流程引擎](https://site.logic-flow.cn/docs/#/zh/guide/start) +- [pearadmin pearadmin便捷高效的快速建站,后台开发框架](http://www.pearadmin.com/ + + + diff --git a/demo/thinkphp/backend/app/.htaccess b/demo/thinkphp/backend/app/.htaccess new file mode 100644 index 0000000000000000000000000000000000000000..3418e55a68383c1cbc687c52a2994d1e8ed83800 --- /dev/null +++ b/demo/thinkphp/backend/app/.htaccess @@ -0,0 +1 @@ +deny from all \ No newline at end of file diff --git a/demo/thinkphp/backend/app/AppService.php b/demo/thinkphp/backend/app/AppService.php new file mode 100644 index 0000000000000000000000000000000000000000..641b90539773955fb9277a8d5ccf8a9679cab9d2 --- /dev/null +++ b/demo/thinkphp/backend/app/AppService.php @@ -0,0 +1,27 @@ + Json::class, + 'sysConfig' => SystemConfigService::class, + 'sysGroupData' => GroupDataService::class, + ]; + + public function boot() + { + // 服务启动 + defined('DS') || define('DS', DIRECTORY_SEPARATOR); + } +} diff --git a/demo/thinkphp/backend/app/ExceptionHandle.php b/demo/thinkphp/backend/app/ExceptionHandle.php new file mode 100644 index 0000000000000000000000000000000000000000..453d1260ecae632f8edf14955ae6561842ac0e04 --- /dev/null +++ b/demo/thinkphp/backend/app/ExceptionHandle.php @@ -0,0 +1,58 @@ + +// +---------------------------------------------------------------------- + +namespace app; + +use Spatie\Macroable\Macroable; + +/** + * Class Request + * + * @package app + * @method tokenData() 获取token信息 + * @method user(string $key = null) 获取用户信息 + * @method uid() 获取用户uid + * @method isAdminLogin() 后台登陆状态 + * @method adminId() 后台管理员id + * @method adminInfo() 后台管理信息 + * @method kefuId() 客服id + * @method kefuInfo() 客服信息 + */ +class Request extends \think\Request +{ + use Macroable; + + /** + * 不过滤变量名 + * + * @var array + */ + protected array $except = ['menu_path', 'api_url', 'unique_auth', 'description', 'custom_form', 'content']; + + /** + * 获取请求的数据 + * + * @param array $params + * @param bool $suffix + * @param bool $filter + * + * @return array + */ + public function more(array $params, bool $suffix = false, bool $filter = true): array + { + $p = []; + $i = 0; + foreach ($params as $param) { + if (!is_array($param)) { + $p[$suffix == true ? $i++ : $param] = $this->filterWord(is_string($this->param($param)) ? trim($this->param($param)) : $this->param($param), $filter && !in_array($param, $this->except)); + } else { + if (!isset($param[1])) $param[1] = null; + if (!isset($param[2])) $param[2] = ''; + if (is_array($param[0])) { + $name = is_array($param[1]) ? $param[0][0] . '/a' : $param[0][0] . '/' . $param[0][1]; + $keyName = $param[0][0]; + } else { + $name = is_array($param[1]) ? $param[0] . '/a' : $param[0]; + $keyName = $param[0]; + } + $p[$suffix == true ? $i++ : ($param[3] ?? $keyName)] = $this->filterWord(is_string($this->param($name, $param[1], $param[2])) ? trim($this->param($name, $param[1], $param[2])) : $this->param($name, $param[1], $param[2]), $filter && !in_array($keyName, $this->except)); + } + } + return $p; + } + + /** + * 过滤接受的参数 + * + * @param $str + * @param bool $filter + * + * @return array|mixed|string|string[] + */ + public function filterWord($str, bool $filter = true) + { + if (!$str || !$filter) return $str; + // 把数据过滤 + $farr = [ + "/<(\\/?)(script|i?frame|style|html|body|title|link|meta|object|\\?|\\%)([^>]*?)>/isU", + "/(<[^>]*)on[a-zA-Z]+\s*=([^>]*>)/isU", + '/phar/is', + "/select|join|where|drop|like|modify|rename|insert|update|table|database|alter|truncate|\'|\/\*|\.\.\/|\.\/|union|into|load_file|outfile/is", + ]; + if (is_array($str)) { + foreach ($str as &$v) { + if (is_array($v)) { + foreach ($v as &$vv) { + if (!is_array($vv)) $vv = preg_replace($farr, '', $vv); + } + } else { + $v = preg_replace($farr, '', $v); + } + } + } else { + $str = preg_replace($farr, '', $str); + } + return $str; + } + + /** + * 获取get参数 + * + * @param array $params + * @param bool $suffix + * @param bool $filter + * + * @return array + */ + public function getMore(array $params, bool $suffix = false, bool $filter = true): array + { + return $this->more($params, $suffix, $filter); + } + + /** + * 获取post参数 + * + * @param array $params + * @param bool $suffix + * @param bool $filter + * + * @return array + */ + public function postMore(array $params, bool $suffix = false, bool $filter = true): array + { + return $this->more($params, $suffix, $filter); + } + + /** + * 获取请求的数据 + * 获取额外参数和值; + *   type为 1、2 表示 索引数组(1为 Value 的一维数组,2为key、Value的二维数组),0表示 关联数组 + * 每条数据组成: + * 数组/字符串 + * 如果是数组: + * $param[0]:要获取的Key + * 可以为数组:0为key,1为变量修饰符 + * $param[1]:默认值;!!!注意,如果默认值为数组,则这个项的值也会转为数组(索引)!!! + * $param[2]:过滤函数 + * $param[3]:替换的新key + * 已修改为:如果没有 $param 且没有缺省值,则跳过这个; + * 感觉还可以修改 变量修饰符 那部分(去掉 增加变量修饰) + * 返回: + * 索引:二维数组:[[key, 值], [key, 值]。。。],适用于where + * 一维数组[值, 值, 。。。] + * 关联:一维关联数组 + * + * @param array $params + * @param int $type + * + * @return array + */ + public function getParams(array $params, int $type = 0): array + { + $p = []; + $i = 0; + foreach ($params as $param) { + if (!is_array($param)) //如果不是数组 + { + //原来的索引数组没有key + //$p[$suffix == true ? $i++ : $param] = $this->param($param); + if ($type == 0) + $p[$param] = $this->param($param); + else if ($type == 1) + $p[$i++] = $this->param($param); + else { + //修改为 [key, 值] + $p[$i++] = [$param, $this->param($param)]; + } + } else { + //if (!isset($param[1])) $param[1] = null; + if (!isset($param[2])) $param[2] = ''; + if (is_array($param[0])) //如果是数组 + { + if (!array_key_exists('1', $param)) //如果没有默认值 + { + if (!$this->has($param[0][0])) //如果request中没有 + continue; + + $param[1] = null; + } + + //如果默认值为数组,则给param加上变量修饰符(/a);否则手动连接修饰符 + $name = is_array($param[1]) ? $param[0][0] . '/a' : $param[0][0] . '/' . $param[0][1]; + $keyName = $param[0][0]; + } else { + if (!array_key_exists('1', $param)) //如果没有默认值 + { + if (!$this->has($param[0])) //如果request中没有 + continue; + + $param[1] = null; + } + + //如果默认值为数组,则给param加上变量修饰符(/a) + $name = is_array($param[1]) ? $param[0] . '/a' : $param[0]; + $keyName = $param[0]; + } + + //原来的索引数组没有key + //$p[$suffix == true ? $i++ : (isset($param[3]) ? $param[3] : $keyName)] = $this->param($name, $param[1], $param[2]); + if ($type == 0) + $p[(isset($param[3]) ? $param[3] : $keyName)] = $this->param($name, $param[1], $param[2]); + else if ($type == 1) + $p[$i++] = $this->param($name, $param[1], $param[2]); + else { + //修改为 [key, 值] + $p[$i++] = [isset($param[3]) ? $param[3] : $keyName, $this->param($name, $param[1], $param[2])]; + } + } + } + return $p; + } + + /** + * 获取用户访问端 + * + * @return array|string|null + */ + public function getFromType() + { + return $this->header('Form-type', ''); + } + + /** + * 当前访问端 + * + * @param string $terminal + * + * @return bool + */ + public function isTerminal(string $terminal) + { + return strtolower($this->getFromType()) === $terminal; + } + + /** + * 是否是H5端 + * + * @return bool + */ + public function isH5() + { + return $this->isTerminal('h5'); + } + + /** + * 是否是微信端 + * + * @return bool + */ + public function isWechat() + { + return $this->isTerminal('wechat'); + } + + /** + * 是否是小程序端 + * + * @return bool + */ + public function isRoutine() + { + return $this->isTerminal('routine'); + } + + /** + * 是否是app端 + * + * @return bool + */ + public function isApp() + { + return $this->isTerminal('app'); + } + + /** + * 是否是app端 + * + * @return bool + */ + public function isPc() + { + return $this->isTerminal('pc'); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/AdminApiExceptionHandle.php b/demo/thinkphp/backend/app/adminapi/AdminApiExceptionHandle.php new file mode 100644 index 0000000000000000000000000000000000000000..835fb1f9f3b7f8f0a262228edb4848ad4ecd0d80 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/AdminApiExceptionHandle.php @@ -0,0 +1,105 @@ + +// +---------------------------------------------------------------------- + +namespace app\adminapi; + +use phoenix\exceptions\AdminException; +use phoenix\exceptions\ApiException; +use phoenix\exceptions\AuthException; +use think\Container; +use think\db\exception\DbException; +use think\exception\Handle; +use think\exception\ValidateException; +use think\facade\Env; +use think\facade\Log; +use think\Response; +use Throwable; + +class AdminApiExceptionHandle extends Handle +{ + + + /** + * 不需要记录信息(日志)的异常类列表 + * @var array + */ + protected $ignoreReport = [ + ValidateException::class, + AuthException::class, + AdminException::class, + ApiException::class, + ]; + + /** + * 记录异常信息(包括日志或者其它方式记录) + * @access public + * @param Throwable $exception + * @return void + */ + public function report(Throwable $exception): void + { + if (!$this->isIgnoreReport($exception)) { + try { + $data = [ + 'file' => $exception->getFile(), + 'line' => $exception->getLine(), + 'message' => $this->getMessage($exception), + 'code' => $this->getCode($exception), + ]; + + //日志内容 + $log = [ + request()->adminId(), //管理员ID + request()->ip(), //客户ip + ceil(msectime() - (request()->time(true) * 1000)), //耗时(毫秒) + request()->rule()->getMethod(), //请求类型 + str_replace("/", "", request()->rootUrl()), //应用 + request()->baseUrl(), //路由 + json_encode(request()->param(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),//请求参数 + json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), //报错数据 + + ]; + Log::write(implode("|", $log), "error"); + } catch (\Throwable $e) { + Log::write($e->getMessage(), "error"); + } + } + } + + /** + * Render an exception into an HTTP response. + * + * @access public + * + * @param \think\Request $request + * @param Throwable $e + * + * @return Response + */ + public function render(\think\Request $request, Throwable $e): Response + { + $massageData = Env::get('app_debug', false) ? [ + 'message' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'trace' => $e->getTrace(), + 'previous' => $e->getPrevious(), + ] : []; + $message = $e->getMessage(); + // 添加自定义异常处理机制 + if ($e instanceof AuthException || $e instanceof AdminException || $e instanceof ApiException || $e instanceof ValidateException) { + return app('json')->make($e->getCode() ?: 400, $message, $massageData); + } else { + return app('json')->fail($message, $massageData); + } + } + +} diff --git a/demo/thinkphp/backend/app/adminapi/common.php b/demo/thinkphp/backend/app/adminapi/common.php new file mode 100644 index 0000000000000000000000000000000000000000..26f1cbe00e99d18b0fd0507a8475ac2e751cd77c --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/common.php @@ -0,0 +1,165 @@ + +// +---------------------------------------------------------------------- + +if (!function_exists('get_this_class_methods')) { + + /**获取当前类方法 + * + * @param $class + * @param array $unarray + * + * @return array + */ + function get_this_class_methods($class, array $unarray = []): array + { + $arrayall = get_class_methods($class); + if ($parent_class = get_parent_class($class)) { + $arrayparent = get_class_methods($parent_class); + $arraynow = array_diff($arrayall, $arrayparent);//去除父级的 + } else { + $arraynow = $arrayall; + } + return array_diff($arraynow, $unarray);//去除无用的 + } +} + + +if (!function_exists('setconfig')) { + /** + * 修改config的函数 + * + * @param $name + * @param $pat + * @param $rep + * + * @return bool 返回状态 + */ + function setconfig($name, $pat, $rep): bool + { + /** + * 原理就是 打开config配置文件 然后使用正则查找替换 然后在保存文件. 不能修改值为数组的配置 + * 传递的参数为2个数组 前面的为配置 后面的为数值. 正则的匹配为单引号 如果你的是分号 请自行修改为分号 + * $pat[0] = 参数前缀; 例: default_return_type + * $rep[0] = 要替换的内容; 例: json + */ + $pats = $reps = []; + if (is_array($pat) && is_array($rep)) { + for ($i = 0; $i < count($pat); $i++) { + $pats[$i] = '/\'' . $pat[$i] . '\'(.*?),/'; + $reps[$i] = "'" . $pat[$i] . "'" . "=>" . "'" . $rep[$i] . "',"; + } + $fileurl = app()->getConfigPath() . $name . ".php"; + $string = file_get_contents($fileurl); //加载配置文件 + $string = preg_replace($pats, $reps, $string); // 正则查找然后替换 + @file_put_contents($fileurl, $string); // 写入配置文件 + return true; + } else if (is_string($pat) && is_string($rep)) { + $pats = '/\'' . $pat . '\'(.*?),/'; + if (substr_count($rep, '[')) { + $reps = "'" . $pat . "'" . "=>" . $rep . ","; + } else { + $rep = str_replace('\'', "", $rep); + $reps = "'" . $pat . "'" . "=>" . "'" . $rep . "',"; + } + $fileurl = app()->getConfigPath() . $name . ".php"; + $string = file_get_contents($fileurl); //加载配置文件 + $string = preg_replace($pats, $reps, $string); // 正则查找然后替换 + @file_put_contents($fileurl, $string); // 写入配置文件 + return true; + } else { + return false; + + } + } +} +if (!function_exists('arrayToText')) { + /** + * 修改config的函数 + * @param $array + * @return string + */ + function arrayToText($array): string + { + $config = print_r($array, true); + $config = str_replace('[', "\"", $config); + $config = str_replace(']', "\"", $config); + $input = explode("\n", $config); + foreach ($input as $k => $v) { + if (empty($v) || strpos($v, 'Array') !== false || strpos($v, '(') !== false || strpos($v, ')') !== false) { + continue; + } + $tmpValArr = explode('=>', $v); + if (count($tmpValArr) == 2) { + $input[$k] = $tmpValArr[0] . '=> \'' . trim($tmpValArr[1]) . '\','; + } + } + $config = implode("\n", $input); + $config = str_replace('Array', "", $config); + $config = str_replace('(', "[", $config); + $config = str_replace(')', "],", $config); + $config = rtrim($config, "\n"); + $config = rtrim($config, ","); + $config = "getConfigPath() ."templates.php"; +// @file_put_contents($fileurl, $config); // 写入配置文件 + return $config; + } +} +if (!function_exists('attr_format')) { + /** + * 格式化属性 + * @param $arr + * @return array + */ + function attr_format($arr): array + { + $len = count($arr); + $title = array_column($arr, 'value'); + $result = []; + + if ($len > 0) { + if ($len > 1) { + $result = $arr[0]['detail']; + for ($i = 0; $i < $len - 1; $i++) { + $temp = $result; + $result = []; + foreach ($temp as $item) { + foreach ($arr[$i + 1]['detail'] as $datum) { + $result[] = trim($item) . ',' . trim($datum); + } + } + } + } else { + foreach ($arr[0]['detail'] as $item) { + $result[] = trim($item); + } + } + } + return [$result, $title]; + } +} + +if (!function_exists('verify_domain')) { + + /** + * 验证域名是否合法 + * @param string $domain + * @return bool + */ + function verify_domain(string $domain): bool + { + $res = "/^(?=^.{3,255}$)(http(s)?:\/\/)(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+\.\w+)*$/"; + if (preg_match($res, $domain)) + return true; + else + return false; + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/AuthController.php b/demo/thinkphp/backend/app/adminapi/controller/AuthController.php new file mode 100644 index 0000000000000000000000000000000000000000..95e73b7a596a340f8d402d70f06372c2a3c03871 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/AuthController.php @@ -0,0 +1,97 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller; + +use phoenix\basic\BaseController; +use think\Validate; +use think\exception\ValidateException; + +/** + * 基类 所有控制器继承的类 + * Class AuthController + * + * @package app\adminapi\controller + */ +class AuthController extends BaseController +{ + /** + * 当前登陆管理员信息 + * + * @var + */ + protected $adminInfo; + + /** + * 当前登陆管理员ID + * + * @var + */ + protected string $adminId; + + /** + * 当前管理员权限 + * + * @var array + */ + protected array $auth = []; + + /** + * 初始化 + */ + protected function initialize() + { + $this->adminId = $this->request->adminId(); + $this->adminInfo = $this->request->adminInfo(); + $this->auth = $this->request->adminInfo['rules'] ?? []; + } + + /** + * 验证数据 + * + * @param array $data + * @param array|string|object $validate + * @param string|array $message + * @param bool $batch + * + * @return bool + */ + final protected function validate(array $data, array|string|object $validate, string|array $message = [], bool $batch = false): bool + { + + if (is_array($validate)) { + $v = new Validate(); + $v->rule($validate); + } else { + if (strpos($validate, '.')) { + // 支持场景 + list($validate, $scene) = explode('.', $validate); + } + $class = str_contains($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate); + $v = new $class(); + if (!empty($scene)) { + $v->scene($scene); + } + if (is_string($message) && empty($scene)) { + $v->scene($message); + } + } + + if (is_array($message)) { + $v->message($message); + } + + // 是否批量验证 + if ($batch) { + $v->batch(true); + } + return $v->failException(true)->check($data); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/Login.php b/demo/thinkphp/backend/app/adminapi/controller/Login.php new file mode 100644 index 0000000000000000000000000000000000000000..69123e8b912afbb68da73cfec9fcc9d79e6a969e --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/Login.php @@ -0,0 +1,147 @@ +services = $services; + } + + protected function initialize() + { + } + + /** + * 验证码 + * + * @return $this|\think\Response + * @throws \Exception + */ + public function captcha(): \think\Response|static + { + return app()->make(Captcha::class)->create(); + } + + /** + * @return mixed + */ + public function ajcaptcha() + { + $captchaType = $this->request->get('captcha_type'); + return app('json')->success(aj_captcha_create($captchaType)); + } + + /** + * 一次验证 + * + * @return mixed + */ + public function ajcheck(): mixed + { + [$token, $pointJson, $captchaType] = $this->request->postMore([ + ['token', ''], + ['pointJson', ''], + ['captchaType', ''], + ], true); + try { + aj_captcha_check_one($captchaType, $token, $pointJson); + return app('json')->success(); + } catch (\Throwable $e) { + return app('json')->fail('验证码错误'); + } + } + + /** + * @throws \think\db\exception\DataNotFoundException + * @throws \ReflectionException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\db\exception\DbException + * @throws \Psr\SimpleCache\InvalidArgumentException + * @throws \think\Exception + */ + public function login(Request $request) + { + [$account, $password, $key, $captchaVerification, $captchaType] = $request->postMore([ + 'account', + 'pwd', + ['key', ''], + ['captchaVerification', ''], + ['captchaType', ''], + ], true); + + if ($captchaVerification != '') { + try { + aj_captcha_check_two($captchaType, $captchaVerification); + } catch (\Throwable $e) { + return app('json')->fail(400336); + } + } + if (strlen(trim($password)) < 6 || strlen(trim($password)) > 32) { + return app('json')->fail(400762); + } + + $this->validate(['account' => $account, 'pwd' => $password], \app\adminapi\validate\setting\SystemAdminValidata::class, 'get'); + + $result = $this->services->login($account, $password, 'admin', $key); + if (!$result) { + return app('json')->fail(400140, ['login_captcha' => 1]); + } + return app('json')->success($result); + } + + public function demoUser(Request $request) + { + $where = $this->request->getMore([ + ['name', '', '', 'account_like'], + ['delete_time', null], + ['status', ''], + // ['not_account', 'admin'], + ]); + $result = $this->services->getAdministratorsList($where); + //对密码进行销毁 + foreach ($result['list'] as $key => $value) { + unset($result['list'][$key]['pwd']); + } + return app('json')->success($result); + + } + + public function actUser(Request $request) + { + $account = $request->param('account'); + if ($account === 'admin') { +// return app('json')->fail('无法扮演超级管理员', ['login_captcha' => 1]); + } + if (empty($account)) { + return app('json')->fail('传入用户不存在', ['login_captcha' => 1]); + } + + $result = $this->services->login($account, md5('123456'), 'admin', '', false); + if (!$result) { + return app('json')->fail(400140, ['login_captcha' => 1]); + } + return app('json')->success($result); + } + + //文档密钥验证 + public function verificationKey(Request $request){ + $password="0bc3330a-5d10-4697-8ce4-c1afdeceadaf"; + $pwd= $request->param('password'); + if($password!==$pwd){ + return app('json')->fail('无效密钥'); + } + return app('json')->success('验证成功'); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/file/SystemAttachment.php b/demo/thinkphp/backend/app/adminapi/controller/v1/file/SystemAttachment.php new file mode 100644 index 0000000000000000000000000000000000000000..da7569156a4077763c0d8c4486d49fea1f4e5530 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/file/SystemAttachment.php @@ -0,0 +1,223 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\v1\file; + +use app\adminapi\controller\AuthController; +use app\services\system\attachment\SystemAttachmentServices; +use phoenix\services\CacheService; +use think\App; + +/** + * 附件管理类 + * Class SystemAttachment + * + * @package app\adminapi\controller\v1\file + */ +class SystemAttachment extends AuthController +{ + /** + * @var SystemAttachmentServices + */ + protected SystemAttachmentServices $service; + + /** + * @param App $app + * @param SystemAttachmentServices $service + */ + public function __construct(App $app, SystemAttachmentServices $service) + { + parent::__construct($app); + $this->service = $service; + } + + /** + * 显示列表 + */ + public function index(): \think\Response\Json + { + $where = $this->request->getMore([ + ['pid', 0], + ['real_name', ''], + ]); + return app('json')->success($this->service->getImageList($where)); + } + + /** + * 删除指定资源 + * + * @return \think\Response\Json + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function delete(): \think\Response\Json + { + [$ids] = $this->request->postMore([ + ['ids', ''], + ], true); + $this->service->del($ids); + return app('json')->success(100002); + } + + /** + * 图片上传 + * + * @param int $upload_type + * @param int $type + * + * @return mixed + */ + public function upload(int $upload_type = 0, int $type = 0): \think\Response\Json + { + [$pid, $file, $menuName] = $this->request->postMore([ + ['pid', '-1'], + ['file', 'file'], + ['name', ''], + ], true); + $res = $this->service->upload($pid, $file, $upload_type, $type, $menuName); + return app('json')->success(100032, ['src' => $res]); + } + + /** + * 移动图片 + * + * @return mixed + */ + public function moveImageCate() + { + $data = $this->request->postMore([ + ['pid', 0], + ['images', ''], + ]); + $this->service->move($data); + return app('json')->success(100034); + } + + /** + * 修改文件名 + * + * @param $id + * + * @return mixed + */ + public function update($id):\think\Response\Json + { + $realName = $this->request->post('real_name', ''); + $category = $this->request->post('pid', ''); + if (!$realName) { + return app('json')->fail(400104); + } + $data = ['real_name' => $realName]; + if ($category) { + $data['pid'] = $category; + } + $this->service->update($id, $data); + return app('json')->success(100001); + } + + /** + * 获取上传类型 + * + * @return mixed + */ + public function uploadType() + { + $data['upload_type'] = (string)sys_config('upload_type', 1); + return app('json')->success($data); + } + + /** + * 视频分片上传 + * + * @return mixed + */ + public function videoUpload() + { + $data = $this->request->postMore([ + ['chunkNumber', 0],//第几分片 + ['currentChunkSize', 0],//分片大小 + ['chunkSize', 0],//总大小 + ['totalChunks', 0],//分片总数 + ['file', 'file'],//文件 + ['md5', ''],//MD5 + ['filename', ''],//文件名称 + ]); + $res = $this->service->videoUpload($data, $_FILES['file']); + return app('json')->success($res); + } + + /** + * 获取扫码上传页面链接以及参数 + * + * @return \think\Response + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/06/13 + */ + public function scanUploadQrcode() + { + [$pid] = $this->request->getMore([ + ['pid', 0], + ], true); + $uploadToken = md5(time()); + CacheService::set('scan_upload', $uploadToken, 600); + $url = sys_config('site_url') . '/app/upload?pid=' . $pid . '&token=' . $uploadToken; + return app('json')->success(['url' => $url]); + } + + /** + * 删除二维码 + * + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/6/26 + */ + public function removeUploadQrcode() + { + CacheService::delete('scan_upload'); + return app('json')->success(); + } + + /** + * 获取扫码上传的图片数据 + * + * @param $scan_token + * + * @return \think\Response + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/06/13 + */ + public function scanUploadImage($scan_token) + { + return app('json')->success($this->service->scanUploadImage($scan_token)); + } + + /** + * 网络图片上传 + * + * @return \think\Response + * @throws \Exception + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/06/13 + */ + public function onlineUpload() + { + $data = $this->request->postMore([ + ['pid', 0], + ['images', []], + ]); + $this->service->onlineUpload($data); + return app('json')->success(100032); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/file/SystemAttachmentCategory.php b/demo/thinkphp/backend/app/adminapi/controller/v1/file/SystemAttachmentCategory.php new file mode 100644 index 0000000000000000000000000000000000000000..c8ad5c5a21306060f27ff5571d838ba0a42c309e --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/file/SystemAttachmentCategory.php @@ -0,0 +1,136 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\v1\file; + +use app\adminapi\controller\AuthController; +use app\services\system\attachment\SystemAttachmentCategoryServices; +use think\App; + +/** + * 附件分类管理类 + * + * @author Mr.April + * @since 1.0 + */ +class SystemAttachmentCategory extends AuthController +{ + /** + * @var SystemAttachmentCategoryServices + */ + protected $service; + + /** + * @param App $app + * @param SystemAttachmentCategoryServices $service + */ + public function __construct(App $app, SystemAttachmentCategoryServices $service) + { + parent::__construct($app); + $this->service = $service; + } + + /** + * 显示资源列表 + * + * @return \think\Response + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index(): \think\Response + { + $where = $this->request->getMore([ + ['name', ''], + ['pid', 0], + ['all', 0], + ]); + if ($where['name'] != '' || $where['all'] == 1) $where['pid'] = ''; + return app('json')->success($this->service->getAll($where)); + } + + /** + * 保存新增 + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function save(): \think\Response + { + $data = $this->request->postMore([ + ['pid', '-1'], + ['name', ''], + ['sort', 10], + ['remarks'], + ]); + if (!$data['name']) { + return app('json')->fail(400100); + } + $this->service->save($data); + return app('json')->success(100021); + } + + /** + * 获取资源详情 + * + * @param $id + * + * @return \think\Response + */ + public function read($id): \think\Response + { + return app('json')->success($this->service->get($id)->toArray()); + } + + /** + * 保存更新的资源 + * + * @param $id + * + * @return \think\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function update($id): \think\Response + { + $data = $this->request->postMore([ + ['pid', '-1'], + ['name', ''], + ['sort', 10], + ['remarks', ''], + ]); + if (is_array($data['pid'])) $data['pid'] = end($data['pid']); + if (!$data['name']) { + return app('json')->fail(400100); + } + $info = $this->service->get($id); + $count = $this->service->count(['pid' => $id]); + if ($count && $info['pid'] != $data['pid']) return app('json')->fail(400105); + $this->service->update($id, $data); + return app('json')->success(100001); + } + + /** + * 删除指定资源 + * + * @param string $id + * + * @return \think\Response + */ + public function delete(string $id): \think\Response + { + $this->service->del($id); + return app('json')->success(100002); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/LangCode.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/LangCode.php new file mode 100644 index 0000000000000000000000000000000000000000..87f6675dd780c3d26e2b0a6a040e4509df4bb84f --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/LangCode.php @@ -0,0 +1,139 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\v1\setting; + +use app\adminapi\controller\AuthController; +use app\Request; +use app\services\system\lang\LangCodeServices; +use think\App; + +class LangCode extends AuthController +{ + /** + * @param App $app + * @param LangCodeServices $services + */ + public function __construct(App $app, LangCodeServices $services) + { + parent::__construct($app); + $this->services = $services; + } + + /** + * 获取语言列表 + * + * @return mixed + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function langCodeList(): mixed + { + $where = $this->request->getMore([ + ['is_admin', 0], + ['type_id', 0], + ['code', ''], + ['remarks', ''], + ]); + return app('json')->success($this->services->langCodeList($where)); + } + + public function langCodeType() + { + return app('json')->success($this->services->langCodeType()); + } + + /** + * 获取语言详情 + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function langCodeInfo() + { + [$code] = $this->request->getMore([ + ['code', ''], + ], true); + return app('json')->success($this->services->langCodeInfo($code)); + } + + /** + * 新增语言 + * + * @return mixed + * @throws \Exception + */ + public function langCodeSave(): mixed + { + $data = $this->request->postMore([ + ['is_admin', 0], + ['code', ''], + ['remarks', ''], + ['edit', 0], + ['list', []], + ]); + $this->services->langCodeSave($data); + return app('json')->success(100000); + } + + /** + * 修改语言 + * + * @return mixed + * @throws \Exception + */ + public function langCodeUpdate(): mixed + { + $data = $this->request->postMore([ + ['is_admin', 0], + ['code', ''], + ['remarks', ''], + ['edit', 1], + ['list', []], + ]); + $this->services->langCodeSave($data); + return app('json')->success(100000); + } + + /** + * 删除语言 + * + * @param $id + * + * @return mixed + */ + public function langCodeDel($id): mixed + { + + $this->services->langCodeDel($id); + return app('json')->success(100002); + } + + /** + * 机器翻译 + * + * @param \app\Request $request + * + * @return mixed + * @throws \Throwable + */ + public function langCodeTranslate(Request $request): mixed + { + [$text] = $request->postMore([ + ['text', ''], + ], true); + if ($text == '') return app('json')->fail(100100); + return app('json')->success($this->services->langCodeTranslate($text)); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/LangCountry.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/LangCountry.php new file mode 100644 index 0000000000000000000000000000000000000000..58197dcc643b8bb072e37165bdb42003ce0c6435 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/LangCountry.php @@ -0,0 +1,94 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\v1\setting; + +use app\adminapi\controller\AuthController; +use app\Request; +use app\services\system\lang\LangCountryServices; +use think\App; + +/** + * 地区列表 + * + * @author Mr.April + * @since 1.0 + */ +class LangCountry extends AuthController +{ + /** + * @param App $app + * @param LangCountryServices $services + */ + public function __construct(App $app, LangCountryServices $services) + { + parent::__construct($app); + $this->services = $services; + } + + /** + * 国家语言列表 + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function langCountryList(): mixed + { + $where = $this->request->getMore([ + ['keyword', ''], + ]); + return app('json')->success($this->services->langCountryList($where)); + } + + /** + * 获取地区详情 + * + * @param \app\Request $request + * + * @return mixed + */ + public function langCountryDetail(Request $request): mixed + { + return app('json')->success($this->services->get($request['id'])->toArray()); + } + + /** + * 地区语言修改 + * + * @param \app\Request $request + * + * @return mixed + */ + public function langCountrySave($id): mixed + { + $data = $this->request->postMore([ + ['name', ''], + ['code', ''], + ['type_id', 0], + ]); + $this->services->langCountrySave($id, $data); + return app('json')->success(100000); + } + + /** + * 地区语言删除 + * + * @param $id + * + * @return mixed + */ + public function langCountryDel($id): mixed + { + $this->services->langCountryDel($id); + return app('json')->success(100002); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/LangType.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/LangType.php new file mode 100644 index 0000000000000000000000000000000000000000..e5bc027a57b01e925e208e332fafaeedb10b36a7 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/LangType.php @@ -0,0 +1,110 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\v1\setting; + +use app\adminapi\controller\AuthController; +use app\Request; +use app\services\system\lang\LangTypeServices; +use phoenix\services\CacheService; +use think\App; + +class LangType extends AuthController +{ + /** + * @param App $app + * @param LangTypeServices $services + */ + public function __construct(App $app, LangTypeServices $services) + { + parent::__construct($app); + $this->services = $services; + } + + /** + * 获取语言类型列表 + * + * @param \app\Request $request + * + * @return mixed + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function langTypeList(Request $request): mixed + { + $where = $this->request->getMore([ + ['language_name', ''], + ['file_name', ''], + ]); + return app('json')->success($this->services->langTypeList($where)); + } + + /** + * 添加语言类型详情 + * + * @param \app\Request $request + * + * @return mixed + */ + public function langTypeDetail(Request $request): mixed + { + $data = $request->getMore([['id']]); + return app('json')->success($this->services->get($data['id'])->toArray()); + } + + /** + * 保存语言类型 + * + * @return mixed + */ + public function langTypeSave(): mixed + { + $data = $this->request->postMore([ + ['id', 0], + ['language_name', ''], + ['file_name', ''], + ['is_default', 0], + ['status', 0], + ]); + $this->services->langTypeSave($data); + CacheService::delete('lang_type_data'); + return app('json')->success(100000); + } + + /** + * 修改语言类型状态 + * + * @param \app\Request $request + * + * @return mixed + */ + public function langTypeStatus(Request $request): mixed + { + $data = $request->getParams([['id'], ['status']]); + $this->services->langTypeStatus($data['id'], $data['status']); + return app('json')->success(100014); + } + + /** + * 删除语言类型 + * + * @param $id + * + * @return mixed + */ + public function langTypeDel($id): mixed + { + $this->services->langTypeDel($id); + CacheService::delete('lang_type_data'); + return app('json')->success(100002); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemAdmin.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemAdmin.php new file mode 100644 index 0000000000000000000000000000000000000000..fb7974564cc80df418a2f28fbbdc86650212ed0f --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemAdmin.php @@ -0,0 +1,292 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\v1\setting; + +use app\adminapi\controller\AuthController; +use app\Request; +use app\services\system\admin\SystemAdminServices; +use phoenix\services\CacheService; +use think\App; + +/** + * Class SystemAdmin + * + * @package app\adminapi\controller\v1\setting + */ +class SystemAdmin extends AuthController +{ + /** + * SystemAdmin constructor. + * + * @param App $app + * @param SystemAdminServices $services + */ + public function __construct(App $app, SystemAdminServices $services) + { + parent::__construct($app); + $this->services = $services; + } + + /** + * 显示管理员资源列表 + * + * @return \think\Response + */ + public function index(): \think\Response + { + $where = $this->request->getMore([ + ['name', '', '', 'account_like'], + ['delete_time', null], + ['status', ''], + ]); + return app('json')->success($this->services->getAdminList($where)); + } + + /** + * 显示创建表单页 + */ + public function create() + { + + } + + /** + * 保存管理员 + * + * @return \think\Response + * @throws \ReflectionException + */ + public function save(): \think\Response + { + $data = $this->request->postMore([ + ['account', ''], + ['conf_pwd', ''], + ['pwd', ''], + ['real_name', ''], + ['status', 0], + ['address', ''], + ['cell_phone_number', ''], + ['email', ''], + ['sex', 0], + ['remark', ''], + ]); + if (!empty($data['pwd'])) { + $data['conf_pwd'] = $data['pwd']; + } + $this->validate($data, \app\adminapi\validate\setting\SystemAdminValidata::class); +// $data['level'] = $this->adminInfo['level'] + 1; + $this->services->create($data); + return app('json')->success(100000); + } + + /** + * 获取管理员详情 + * + * @param string $id + * + * @return \think\Response + */ + public function read(string $id): \think\Response + { + $ret = $this->services->find($id); + if ($ret) { + unset($ret['pwd']); + return app('json')->success($ret); + } else { + return app('json')->fail($ret); + } + } + + /** + * 修改管理员信息 + * + * @param $id + * + * @return \think\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function update($id): \think\Response + { + $data = $this->request->postMore([ + ['account', ''], + ['conf_pwd', ''], + ['pwd', ''], + ['real_name', ''], + ['status', 0], + ['address', ''], + ['cell_phone_number', ''], + ['email', ''], + ['sex', 1], + ['remark', ''], + ]); + if (!empty($data['pwd'])) { + $data['conf_pwd'] = $data['pwd']; + } + $this->validate($data, \app\adminapi\validate\setting\SystemAdminValidata::class, 'update'); + if ($this->services->save($id, $data)) { + return app('json')->success(100001); + } else { + return app('json')->fail(100007); + } + } + + /** + * 删除管理员 + * + * @param $id + * + * @return \think\Response + */ + public function delete($id): \think\Response + { + if (!$id) return app('json')->fail(100100); + if ($this->services->update($id, ['delete_time' => time(), 'status' => 0])) + return app('json')->success(100002); + else + return app('json')->fail(100008); + } + + /** + * 批量删除管理员 + * + * @return \think\Response + */ + public function batchUpdate(): \think\Response + { + $data = $this->request->post('data'); + if (empty($data)) { + return app('json')->fail(100100); + } + if ($this->services->batchUpdate(explode(',', $data), ['delete_time' => time(), 'status' => 0], 'id')) { + return app('json')->success(100002); + } else { + return app('json')->fail(100008); + } + } + + /** + * 修改状态 + * + * @param $id + * @param $status + * + * @return \think\Response + */ + public function set_status($id, $status): \think\Response + { + if ($this->services->update($id, ['status' => $status])) { + return app('json')->success(100014); + } else { + return app('json')->fail(100007); + } + } + + public function setPosition($id): \think\Response + { + $data = $this->request->postMore([ + ['account'], + ['dept_id'], + ['dept_name'], + ['post_id'], + ['post_name'], + ['real_name'], + ]); + $this->services->setPosition($id, $data); + return app('json')->success(100014); + } + + /** + * 获取当前登陆管理员的信息 + * + * @return \think\Response + */ + public function info(): \think\Response + { + $result = $this->services->get($this->adminInfo['id'], ['*'])->toArray(); + unset($result['pwd']); + return app('json')->success($result); + } + + /** + * 修改当前登陆admin信息 + * + * @return \think\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function update_admin(): \think\Response + { + $data = $this->request->postMore([ + ['real_name', ''], + ['head_pic', ''], + ['address', ''], + ['email', ''], + ['pwd', ''], + ['cell_phone_number', ''], + ['remarks', ''], + ['sex', '1'], + ['new_pwd', ''], + ['conf_pwd', ''], + ]); + + if ($data['pwd']) { + if (!preg_match('/^(?![^a-zA-Z]+$)(?!\D+$).{6,}$/', $data['new_pwd'])) { + return app('json')->fail(400183); + } + } + + if ($this->services->updateAdmin($this->adminId, $data)) { + $this->services->cacheDriver()->clear(); + return app('json')->success(100001); + } else { + return app('json')->fail(100007); + } + } + + /** + * 修改当前登陆admin的文件管理密码 + * + * @return \think\Response + */ + public function set_file_password(): \think\Response + { + $data = $this->request->postMore([ + ['file_pwd', ''], + ['conf_file_pwd', ''], + ]); + if (!preg_match('/^(?![^a-zA-Z]+$)(?!\D+$).{6,}$/', $data['file_pwd'])) { + return app('json')->fail(400183); + } + if ($this->services->setFilePassword($this->adminId, $data)) { + $this->services->cacheDriver()->clear(); + return app('json')->success(100001); + } else { + return app('json')->fail(100007); + } + } + + /** + * 退出登陆 + * + * @return \think\Response + */ + public function logout(): \think\Response + { + $key = trim(ltrim($this->request->header(Config::get('cookie.token_name')), 'Bearer')); + CacheService::delete(md5($key)); + return app('json')->success(); + } + + +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemConfig.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemConfig.php new file mode 100644 index 0000000000000000000000000000000000000000..9da5a24911d3cdc69e40b10860e858488ebda273 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemConfig.php @@ -0,0 +1,461 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\v1\setting; + +use app\adminapi\controller\AuthController; +use app\Request; +use app\services\system\config\SystemConfigServices; +use app\services\system\config\SystemConfigTabServices; +use phoenix\services\CacheService; +use crmeb\services\easywechat\orderShipping\MiniOrderService; +use think\App; + +/** + * 系统配置 + * + * @author Mr.April + * @since 1.0 + */ +class SystemConfig extends AuthController +{ + + /** + * 构造函数 + * + * @param \think\App $app + * @param \app\services\system\config\SystemConfigServices $services + */ + public function __construct(App $app, SystemConfigServices $services) + { + parent::__construct($app); + $this->services = $services; + } + + /** + * 显示资源列表 + * + * @return \think\Response\Json + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index(): \think\Response\Json + { + $where = $this->request->getMore([ + ['tab_id', ''], + ['status', -1], + ['info', ''], + ]); + if ($where['status'] == -1) { + unset($where['status']); + } + return app('json')->success($this->services->getConfigList($where)); + } + + /** + * 显示创建资源表单页. + * + * @return \think\Response + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ +// public function create() +// { +// [$type, $tabId] = $this->request->getMore([ +// [['type', 'd'], ''], +// [['tab_id', 'd'], 1], +// ], true); +// return app('json')->success($this->services->createFormRule($type, $tabId)); +// } + + /** + * 保存新建的资源 + * + * @return \think\response\Json + */ + public function save(): \think\response\Json + { + $data = $this->request->postMore([ + ['menu_name', ''], + ['type', ''], + ['input_type', 'input'], + ['config_tab_id', 0], + ['parameter', ''], + ['upload_type', 1], + ['required', ''], + ['width', 0], + ['high', 0], + ['value', ''], + ['info', ''], + ['desc', ''], + ['sort', 0], + ['status', 0], + ]); + if (is_array($data['config_tab_id'])) $data['config_tab_id'] = end($data['config_tab_id']); + if (!$data['info']) return app('json')->fail(400274); + if (!$data['menu_name']) return app('json')->fail(400275); + if (!$data['desc']) return app('json')->fail(400276); + if ($data['sort'] < 0) { + $data['sort'] = 0; + } + if ($data['type'] == 'text') { + if (!$data['width']) return app('json')->fail(400277); + if ($data['width'] <= 0) return app('json')->fail(400278); + } + if ($data['type'] == 'textarea') { + if (!$data['width']) return app('json')->fail(400279); + if (!$data['high']) return app('json')->fail(400280); + if ($data['width'] < 0) return app('json')->fail(400281); + if ($data['high'] < 0) return app('json')->fail(400282); + } + if ($data['type'] == 'radio' || $data['type'] == 'checkbox') { + if (!$data['parameter']) return app('json')->fail(400283); + $this->services->valiDateRadioAndCheckbox($data); + } + $data['value'] = json_encode($data['value']); + $config = $this->services->getOne(['menu_name' => $data['menu_name']]); + if ($config) { + $this->services->update($config['id'], $data, 'id'); + } else { + $this->services->save($data); + } + CacheService::clear(); + return app('json')->success(400284); + } + + /** + * 显示指定的资源 + * + * @param $id + * + * @return \think\response\Json + */ + public function read($id): \think\response\Json + { + if (!$id) { + return app('json')->fail(100100); + } + $data = $this->services->get($id)->toArray(); + return app('json')->success($data); + } + + /** + * 显示编辑资源表单页. + * + * @param int $id + * + * @return \think\Response + */ +// public function edit($id) +// { +// return app('json')->success($this->services->editConfigForm((int)$id)); +// } + + /** + * 保存更新的资源 + * + * @param $id + * + * @return \think\response\Json + */ + public function update($id): \think\response\Json + { + $type = request()->post('type'); + if ($type == 'text' || $type == 'textarea' || $type == 'radio' || ($type == 'upload' && (request()->post('upload_type') == 1 || request()->post('upload_type') == 3))) { + $value = request()->post('value'); + } else { + $value = request()->post('value/a'); + } + if (!$value) $value = request()->post(request()->post('menu_name')); + $data = $this->request->postMore([ + ['menu_name', ''], + ['type', ''], + ['input_type', 'input'], + ['config_tab_id', 0], + ['parameter', ''], + ['upload_type', 1], + ['required', ''], + ['width', 0], + ['high', 0], + ['value', $value], + ['info', ''], + ['desc', ''], + ['sort', 0], + ['status', 0], + ]); + if (is_array($data['config_tab_id'])) $data['config_tab_id'] = end($data['config_tab_id']); + if (!$this->services->get($id)) { + return app('json')->fail(100026); + } + $data['value'] = json_encode($data['value']); + $this->services->update($id, $data); + CacheService::clear(); + return app('json')->success(100001); + } + + /** + * 删除指定资源 + * + * @param int $id + * + * @return \think\response\Json + */ + public function delete($id): \think\response\Json + { + if (!$this->services->delete($id)) + return app('json')->fail(100008); + else { + CacheService::clear(); + return app('json')->success(100002); + } + } + + /** + * 修改状态 + * + * @param $id + * @param $status + * + * @return \think\response\Json + */ + public function set_status($id, $status): \think\response\Json + { + if ($status == '' || $id == 0) { + return app('json')->fail(100100); + } + $this->services->update($id, ['status' => $status]); + CacheService::clear(); + return app('json')->success(100014); + } + + /** + * 批量删除 + * + * @param \app\Request $request + * + * @return \think\response\Json + */ + public function batch_delete(Request $request): \think\response\Json + { + $data = $request->post('data',[]); + if (empty($data)) { + return app('json')->fail(100100); + } + + foreach ($data as $key => $value) { + $this->services->delete($value); + } + CacheService::clear(); + return app('json')->success(100002); + } + + /** + * 基础配置 + * */ + public function edit_basics(Request $request) + { + $tabId = $this->request->param('tab_id', 1); + if (!$tabId) { + return app('json')->fail(100100); + } + $url = $request->baseUrl(); + return app('json')->success($this->services->getConfigForm($url, $tabId)); + } + + /** + * 保存数据 true + * */ +// public function save_basics(Request $request) +// { +// $post = $this->request->post(); +// foreach ($post as $k => $v) { +// if (is_array($v)) { +// $res = $this->services->getUploadTypeList($k); +// foreach ($res as $kk => $vv) { +// if ($kk == 'upload') { +// if ($vv == 1 || $vv == 3) { +// $post[$k] = $v[0]; +// } +// } +// } +// } +// } +// $this->validate($post, \app\adminapi\validate\setting\SystemConfigValidata::class); +// if (isset($post['upload_type'])) { +// $this->services->checkThumbParam($post); +// } +// if (isset($post['extract_type']) && !count($post['extract_type'])) { +// return app('json')->fail(400753); +// } +// if (isset($post['store_brokerage_binding_status'])) { +// $this->services->checkBrokerageBinding($post); +// } +// if (isset($post['store_brokerage_ratio']) && isset($post['store_brokerage_two'])) { +// $num = $post['store_brokerage_ratio'] + $post['store_brokerage_two']; +// if ($num > 100) { +// return app('json')->fail(400285); +// } +// } +// if (isset($post['spread_banner'])) { +// $num = count($post['spread_banner']); +// if ($num > 5) { +// return app('json')->fail(400286); +// } +// } +// if (isset($post['user_extract_min_price'])) { +// if (!preg_match('/[0-9]$/', $post['user_extract_min_price'])) { +// return app('json')->fail(400287); +// } +// } +// if (isset($post['wss_open'])) { +// $this->services->saveSslFilePath((int)$post['wss_open'], $post['wss_local_pk'] ?? '', $post['wss_local_cert'] ?? ''); +// } +// if (isset($post['store_brokerage_price']) && $post['store_brokerage_statu'] == 3) { +// if ($post['store_brokerage_price'] === '') { +// return app('json')->fail(400288); +// } +// if ($post['store_brokerage_price'] < 0) { +// return app('json')->fail(400289); +// } +// } +// if (isset($post['store_brokerage_binding_time']) && $post['store_brokerage_binding_status'] == 2) { +// if (!preg_match("/^[0-9][0-9]*$/", $post['store_brokerage_binding_time'])) { +// return app('json')->fail(400290); +// } +// } +// if (isset($post['uni_brokerage_price']) && $post['uni_brokerage_price'] < 0) { +// return app('json')->fail(400756); +// } +// if (isset($post['day_brokerage_price_upper']) && $post['day_brokerage_price_upper'] < -1) { +// return app('json')->fail(400757); +// } +// if (isset($post['pay_new_weixin_open']) && (bool)$post['pay_new_weixin_open']) { +// if (empty($post['pay_new_weixin_mchid'])) { +// return app('json')->fail(400763); +// } +// } +// if (isset($post['uni_brokerage_price']) && preg_match('/\.[0-9]{2,}[1-9][0-9]*$/', (string)$post['uni_brokerage_price']) > 0) { +// return app('json')->fail(500029); +// } +// +// if (isset($post['weixin_ckeck_file'])) { +// $from = public_path() . $post['weixin_ckeck_file']; +// $to = public_path() . array_reverse(explode('/', $post['weixin_ckeck_file']))[0]; +// @copy($from, $to); +// } +// if (isset($post['ico_path'])) { +// $from = public_path() . $post['ico_path']; +// $toAdmin = public_path('admin') . 'favicon.ico'; +// $toHome = public_path('home') . 'favicon.ico'; +// $toPublic = public_path() . 'favicon.ico'; +// @copy($from, $toAdmin); +// @copy($from, $toHome); +// @copy($from, $toPublic); +// } +// if (isset($post['reward_integral']) || isset($post['reward_money'])) { +// if ($post['reward_money'] < 0) return app('json')->fail('赠送余额不能小于0元'); +// if ($post['reward_integral'] < 0) return app('json')->fail('赠送积分不能小于0'); +// } +// +// if (isset($post['sign_give_point'])) { +// if (!is_int($post['sign_give_point']) || $post['sign_give_point'] < 0) return app('json')->fail('签到赠送积分请填写大于等于0的整数'); +// } +// if (isset($post['sign_give_exp'])) { +// if (!is_int($post['sign_give_exp']) || $post['sign_give_exp'] < 0) return app('json')->fail('签到赠送经验请填写大于等于0的整数'); +// } +// if (isset($post['integral_frozen'])) { +// if (!ctype_digit($post['integral_frozen']) || $post['integral_frozen'] < 0) return app('json')->fail('积分冻结天数请填写大于等于0的整数'); +// } +// if (isset($post['store_free_postage'])) { +// if (!is_int($post['store_free_postage']) || $post['store_free_postage'] < 0) return app('json')->fail('满额包邮请填写大于等于0的整数'); +// } +// if (isset($post['withdrawal_fee'])) { +// if ($post['withdrawal_fee'] < 0 || $post['withdrawal_fee'] > 100) return app('json')->fail('提现手续费范围在0-100之间'); +// } +// if (isset($post['routine_auth_type']) && count($post['routine_auth_type']) == 0) return app('json')->fail('微信和手机号登录开关至少开启一个'); +// if (isset($post['integral_max_num'])) { +// if (!ctype_digit($post['integral_max_num']) || $post['integral_max_num'] < 0) return app('json')->fail('积分抵扣上限请填写大于等于0的整数'); +// } +// if (isset($post['customer_phone'])) { +// if (!ctype_digit($post['customer_phone']) || strlen($post['customer_phone']) > 11) return app('json')->fail('客服手机号为11位数字'); +// } +// +// foreach ($post as $k => $v) { +// $config_one = $this->services->getOne(['menu_name' => $k]); +// if ($config_one) { +// $config_one['value'] = $v; +// $this->services->valiDateValue($config_one); +// $this->services->update($k, ['value' => json_encode($v)], 'menu_name'); +// } +// } +// CacheService::clear(); +// return app('json')->success(100001); +// +// } + + /** + * 获取系统设置头部分类 + * + * @param SystemConfigTabServices $services + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function header_basics(SystemConfigTabServices $services) + { + [$type, $pid] = $this->request->getMore([ + [['type', 'd'], 0], + [['pid', 'd'], 0], + ], true); + if ($type == 3) {//其它分类 + $config_tab = []; + } else { + $config_tab = $services->getConfigTab($pid); + if (empty($config_tab)) $config_tab[] = $services->get($pid, ['id', 'id as value', 'title as label', 'pid', 'icon', 'type']); + } + return app('json')->success(compact('config_tab')); + } + + /** + * 获取单个配置的值 + * + * @param $name + * + * @return \think\response\Json + */ + public function get_system($name): \think\response\Json + { + $value = sys_config($name); + return app('json')->success(compact('value')); + } + + /** + * 获取某个分类下的所有配置 + * + * @param $tabId + * + * @return \think\response\Json + */ + public function get_config_list($tabId): \think\response\Json + { + $list = $this->services->getConfigTabAllList($tabId); + $data = []; + foreach ($list as $item) { + $data[$item['menu_name']] = json_decode($item['value']); + } + return app('json')->success($data); + } + +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemConfigTab.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemConfigTab.php new file mode 100644 index 0000000000000000000000000000000000000000..a6835fbc924f4561361fa5fe72d3045ab18eb5a1 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemConfigTab.php @@ -0,0 +1,149 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\v1\setting; + +use app\adminapi\controller\AuthController; +use app\services\system\config\SystemConfigServices; +use app\services\system\config\SystemConfigTabServices; +use think\App; + +/** + * 系统配置分类 + * + * @author Mr.April + * @since 1.0 + */ +class SystemConfigTab extends AuthController +{ + /** + * g构造方法 + * SystemConfigTab constructor. + * + * @param App $app + * @param SystemConfigTabServices $services + */ + public function __construct(App $app, SystemConfigTabServices $services) + { + parent::__construct($app); + $this->services = $services; + } + + /** + * 显示资源列表 + * + * @return \think\response\Json + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index(): \think\response\Json + { + $where = $this->request->getMore([ + ['status', ''], + ['title', ''], + ]); + return app('json')->success($this->services->getConfgTabList($where)); + } + + /** + * 显示指定资源 + * @param $id + * + * @return \think\response\Json + */ + public function read($id): \think\response\Json + { + return app('json')->success($this->services->get($id)->toArray()); + } + + /** + * 保存新建的资源 + * + * @return \think\response\Json + */ + public function save(): \think\response\Json + { + $data = $this->request->postMore([ + 'eng_title', + 'status', + 'title', + 'icon', + ['type', 0], + ['sort', 0], + ['pid', 0], + ]); + if (is_array($data['pid'])) $data['pid'] = end($data['pid']); + if (!$data['title']) return app('json')->fail(400291); + $this->services->save($data); + return app('json')->success(400292); + } + + /** + * 保存更新的资源 + * + * @param int $id + * + * @return \think\response\Json + */ + public function update($id): \think\response\Json + { + $data = $this->request->postMore([ + 'title', + 'status', + 'eng_title', + 'icon', + ['type', 0], + ['sort', 0], + ['pid', 0], + ]); + if (is_array($data['pid'])) $data['pid'] = end($data['pid']); + if (!$data['title']) return app('json')->fail(400291); + if (!$data['eng_title']) return app('json')->fail(400275); + $this->services->update($id, $data); + return app('json')->success(100001); + } + + /** + * 删除指定资源 + * + * @param \app\services\system\config\SystemConfigServices $services + * @param int $id + * + * @return \think\response\Json + */ + public function delete(SystemConfigServices $services, $id): \think\response\Json + { + if ($services->count(['tab_id' => $id])) { + return app('json')->fail(400293); + } + if (!$this->services->delete($id)) + return app('json')->fail(100008); + else + return app('json')->success(100002); + } + + /** + * 修改状态 + * + * @param $id + * @param $status + * + * @return mixed + */ + public function set_status($id, $status): \think\response\Json + { + if ($status == '' || $id == 0) { + return app('json')->fail(100100); + } + $this->services->update($id, ['status' => $status]); + return app('json')->success(100014); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemDept.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemDept.php new file mode 100644 index 0000000000000000000000000000000000000000..0f2bd122bbb585056b9df3e8d1f32e9d7ff3be90 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemDept.php @@ -0,0 +1,180 @@ +services = $services; + } + + /** + * 显示资源列表 + * + * @return \think\response\Json + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index(): \think\response\Json + { + $where = $this->request->getMore([ + ['status', ''], + ['keyword', ''], + ['dept_type', ''], + ]); + return app('json')->success($this->services->getList($where, ['*'])); + + } + + /** + * 获取一条信息 + * + * @param string $id + * + * @return \think\Response + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function read(string $id): \think\Response + { + if (!$id) { + return app('json')->fail(100026); + } + return app('json')->success($this->services->find($id)); + } + + /** + * 保存新建的资源 + * + * @return \think\response\Json + */ + public function save(): \think\response\Json + { + $data = $this->request->postMore([ + ['dept_code'], + ['dept_name'], + ['dept_type', 1], + ['pid', '-1'], + ['icon', ''], + ['remarks', ''], + ['sort', 10], + ['status', 0], + ]); + + $message = [ + 'dept_name' => '部门名称不能为空', + ]; + + $this->validate($data, [ + 'dept_name' => 'require', + ], $message, true); + + if (!$this->services->save($data)) return app('json')->fail(100006); + $this->services->cacheDriver()->clear(); + return app('json')->success(100000); + + } + + /** + * 删除指定资源 + * + * @param $id + * + * @return mixed + * @throws \ReflectionException + */ + public function delete($id): \think\response\Json + { + if (!$id) { + return app('json')->fail(100100); + } + if (!$this->services->delete($id)) { + return app('json')->fail(100008); + } else { + $this->services->cacheDriver()->clear(); + return app('json')->success(100002); + } + } + + /** + * 修改部门 + * + * @param $id + * + * @return \think\response\Json + */ + public function update($id): \think\response\Json + { + if (!$id || !($role = $this->services->get($id))) { + return app('json')->fail(100026); + } + $data = $this->request->postMore([ + ['dept_code'], + ['dept_name'], + ['dept_type', 1], + ['pid', '-1'], + ['icon', ''], + ['remarks', ''], + ['sort', 10], + ['status', 0], + ]); + + $message = [ + 'dept_name' => '部门名称不能为空', + ]; + + $this->validate($data, [ + 'dept_name' => 'require', + ], $message, true); + + if ($this->services->update($id, $data)) { + return app('json')->success(100001); + } else { + return app('json')->fail(100007); + } + } + + /** + * 修改状态 + * + * @param $id + * @param $status + * + * @return mixed + */ + public function set_status($id, $status): \think\response\Json + { + if (!$id) { + return app('json')->fail(100100); + } + $role = $this->services->get($id); + if (!$role) { + return app('json')->fail(400199); + } + $role->status = $status; + if ($role->save()) { + $this->services->cacheDriver()->clear(); + return app('json')->success(100001); + } else { + return app('json')->fail(100007); + } + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemMenus.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemMenus.php new file mode 100644 index 0000000000000000000000000000000000000000..32ecdd48914b50abdfb4d415ecf33e4bce4b2836 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemMenus.php @@ -0,0 +1,370 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\v1\setting; + +use app\adminapi\controller\AuthController; +use app\services\system\admin\SystemMenusServices; +use app\services\system\route\SystemRouteCateServices; +use app\services\system\route\SystemRouteServices; +use think\App; + +/** + * 菜单权限 + * Class SystemMenus + * + * @package app\adminapi\controller\v1\setting + */ +class SystemMenus extends AuthController +{ + /** + * SystemMenus constructor. + * + * @param App $app + * @param SystemMenusServices $services + */ + public function __construct(App $app, SystemMenusServices $services) + { + parent::__construct($app); + $this->services = $services; + $this->request->filter(['addslashes', 'trim']); + } + + /** + * 菜单展示列表 + * + * @return \think\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/05/06 + */ + public function index(): \think\Response + { + $where = $this->request->getMore([ + ['is_show', ''], + ['keyword', ''], + ['auth_type', ''], + ]); + return app('json')->success($this->services->getList($where, ['*'])); + } + + /** + * @return \think\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/14 + */ + public function unique() + { + $adminInfo = $this->request->adminInfo(); + [$menus, $uniqueAuth] = app()->make(SystemMenusServices::class)->getMenusList($adminInfo['roles'], (int)$adminInfo['level']); + return app('json')->success(compact('menus', 'uniqueAuth')); + } + + /** + * 菜单获取 + * + * @return \think\Response + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function permission() + { + $adminInfo = $this->request->adminInfo(); + $roles = ['00f2cf25-61c2-4265-bab9-fc60569b40c6', '03c5a106-ed45-42d2-9467-e3448ed369b3', '08580779-066d-4b3b-9985-124df63625a4', '0a4aff69-ad1d-42b2-8634-00dc3e52360b', '0db53e02-4829-4413-ad96-00ff34fbfd2d', '0efa9244-f4b0-45a6-8781-cac2fff19abe', '0f690e32-1e73-4190-9f87-e349f129451b', '120640c4-6c67-4166-9a7b-8e08e4018cc1', '16a335ef-abea-4581-8de0-1f03d669792e', '170320e1-d592-4809-9447-f40b27fc7aa9', '18e6af3d-e99b-4b1c-be28-2a9547cf6eef', '1d244ec5-cf4e-445a-9374-aaddcb4d84f9', '1e52ad08-670a-4425-9e72-3925ba871dcf', '21abf252-b962-4379-bc19-381749e2cb80', '22900032-1fa4-4a53-bb04-f8b535ea9793', '22d89696-2c65-4925-bf5e-d1b253f9ec17', '25f880bd-856f-49fa-b59c-3f76b7d389c7', '2ac1fd8d-2ca4-4eea-bd1c-f3989096eea2', '2ace6826-3984-4718-9497-ab0dd463bbcb', '2b3e6ae9-7509-4be9-a669-26047ee2e769', '2b433461-3e8c-498d-85a0-33aafade3365', '2b84ae82-4c4a-49ac-8471-a3233b0703db', '2d1f9c58-f0bf-43ff-a729-fabadabd3b8c', '2e79d53d-3a7d-4e17-8944-bdd0b0f63df0', '30dd2e7c-3233-45d3-b538-c2985f9a6ce7', '31d43b76-ae60-4ce5-a04e-2d1d1ec2604b', '366472c2-cb67-4dd9-a8bb-2ae9f045b5c4', '382c1114-59db-4594-b870-da3ce1a29c56', '388b4b2f-5ca8-4cd5-804d-1716b8e02cd0', '3907df96-3152-4aba-9e23-a44575cc7251', '39c763a5-b3d7-4292-99d2-c07f3a04d62f', '3a07101c-46ac-4ad7-824d-b2bf0de65b90', '3b7afea6-ddd5-4532-8a3f-9c2e126e731a', '3d5e3491-7546-4046-acb3-d7b34fda210c', '3e2df7be-9e8c-4ce2-9ddb-61f13d3142bf', '3e74a70e-fb39-41d6-b3f1-abd93ca56014', '3eb2a028-3398-4e62-abe3-0c295a795065', '3f9e4f79-1b00-4ce7-9187-62bd91ace077', '428ee06e-c350-4c9e-8c29-1e59a9e97570', '4474d199-7089-4efb-bc68-b638a7aef300', '4811a205-a4ec-499a-ba85-30ca5ab95feb', '4a26ba61-676b-4842-a087-743eb0354203', '4c0175ac-5b37-4ef5-a2dc-c14caa7b6e42', '4dd18197-2477-421a-8e42-238c6298c7c9', '54480923-4b9e-4c85-90c8-19712b709bb2', '57f79696-1bd2-43f5-a411-75080735b700', '588383d3-d8fe-4023-b9e7-220baac09a0d', '59ca4011-f611-4514-a7ac-a404228e2e73', '5a22017d-6f19-41e8-936b-f70d405639dd', '5f4d2ab0-0cde-4bd3-829f-5a11d96b6440', '60fea859-c085-4b37-8d7a-d03e81afe73a', '63a64d73-40df-4275-af16-c7c0fd382bf2', '64308d28-674e-4e61-8700-b8b508162c5d', '67cfcfe5-7441-44fd-bc61-3e9dc3059362', '6b674c34-7d23-4a27-9a05-688ed3e9c38e', '6ee2d444-cd5f-45ca-a880-11976d16c210', '73aebdf5-fae6-4aa9-a319-8fcc48b6351b', '75300596-9c65-4e63-87c3-19c974e7bf1e', '7a5eaccc-0019-4064-8f83-7c564c431a7c', '7c259013-7919-4235-ab8c-bfcda9b51184', '7e72c463-d80a-4b83-937d-eb20d63a9636', '7ee73260-eaaf-463a-84ff-ac285055e0c1', '7fb96c9d-9eae-4701-af3c-4b41271a8aaf', '817c3d6e-2f2a-4af9-9b84-97e76029302d', '857bd274-30f4-429a-8004-a2e6d0ccb6de', '88cab609-0d7f-4394-a00e-ad24bd2c5ae5', '8b55c722-256a-40b3-ae27-1fdf99164094', '8c3e3149-4438-4b1c-b32c-10978b1a54ef', '91c5a906-911d-4222-b534-df2e5041e0dd', '92158f89-3eb8-462a-85c9-f9586075e274', '92bfab0f-88e6-47ee-b2f2-5d0916f11ef1', '94d4cd83-3d89-493d-97ba-27ded6503a8f', '982ac136-2353-47b2-9c81-c6b9dd5684c0', '99f5f7b2-d584-44f0-b93d-aee0b8030649', '9f1161f9-a3bb-42c8-9b8f-19b12aecf708', '9fb603da-e232-4beb-ad9b-2351e0274029', 'a16b6f89-bd60-4ffd-b833-337ccd8fed36', 'a51a3e37-c890-40b2-adf4-ca7f3856fd84', 'aaf1c674-956f-4349-8f61-b1d8d3285e20', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', 'ac72da18-cd39-4a6c-baf7-d2f75ca7b4b7', 'b21c5ea2-3eb9-4d4e-8244-bdb3caf7ee80', 'b30dce1f-89e8-4563-b52c-5e85a836ebb1', 'b4c85694-38b6-4332-a62c-260cd597f257', 'b7ae5925-9e84-403e-b8a2-eb4528b11d89', 'ba789614-2967-4b16-99d0-b14f9ec98818', 'baa9d8a3-0ea0-4689-9489-0a5ca387409c', 'bad80eed-ef69-4e42-8d36-ceea6df674d1', 'bc9ac16f-c3bb-43a1-bd05-bbda718513ef', 'bd3fbcde-13b8-4c76-9293-755d349b3873', 'bdd9f5be-2460-41b9-8212-044bfae1a568', 'beb61b71-362f-4a59-ba8c-aba8135602a0', 'bec0e802-1606-4d96-a2a1-7a3bc68852d8', 'cb38b36a-c7ad-4899-bcbc-eee2d4291f69', 'd4538387-432c-4422-9618-3ffbedf83473', 'd65fe5a4-b207-4afa-8a88-7ca21dd7df7a', 'd6744062-bdbb-4f75-a83e-51cdb9d96f5a', 'd6872382-8bba-40be-953c-b999b1b5387c', 'd6c3dc71-a5a4-4468-bd6c-4c92c24d098b', 'd8884521-f21e-4468-a50b-b3978022cef2', 'd9579432-b71c-4b71-9f9d-606a7317446a', 'd97843a4-c154-4943-b8fa-0bbac76706cb', 'da6b2620-828d-49e1-82d2-dda9217b0f6f', 'db010262-fa5b-494b-a961-3e6a40ceaf71', 'dc147005-906d-4373-90a0-c331cbc07b79', 'dd097886-0cee-4731-bc9a-da48eacece91', 'e0db89ff-5832-4057-83a1-afb3af069b5e', 'e16554a1-0325-407f-9ec4-5a5b60138730', 'e19558fc-2a31-440b-b356-05a3c9af9804', 'e6c8ca0f-a219-41fe-9289-b07957104e7a', 'ec8940c7-5a43-460a-8778-6d85f0172c2b', 'ecdfd3a9-17b4-4f5d-bb8c-ebc1f189aa49', 'ee6010ce-a330-4217-9674-07435ce22833', 'f28e981b-07b1-40cd-9071-aea501269627', 'f478742b-8060-41ae-9162-4a08c18e28ea', 'f77a8ac8-6395-481d-a31e-c46b9f9b35c5', 'f858a70c-65e8-4edb-9e24-0d94c337b0d0', 'fc6c26c2-2abf-48d1-81d5-16e20c341b92', 'fcabee71-1473-4020-84d8-6f7eaa9ebfe5'];; +// [$menus, $uniqueAuth] = app()->make(SystemMenusServices::class)->getMenusList($adminInfo['roles'] , (int)$adminInfo['level']); + [$menus, $uniqueAuth] = app()->make(SystemMenusServices::class)->getMenusList($roles); + return app('json')->success($menus); + } + + /** + * 保存菜单权限 + */ + public function save() + { + $data = $this->request->getMore([ + ['menu_name', ''], + ['controller', ''], + ['module', 'admin'], + ['action', ''], + ['icon', ''], + ['params', ''], + ['path', []], + ['menu_path', ''], + ['api_url', ''], + ['methods', ''], + ['unique_auth', ''], + ['header', ''], + ['is_header', 0], + ['pid', 0], + ['sort', 0], + ['auth_type', 0], + ['access', 1], + ['is_show', 0], + ['is_show_path', 0], + ]); + $data['is_show_path'] = $data['is_show']; + if (!$data['menu_name']) + return app('json')->fail(400198); + $data['path'] = implode('/', $data['path']); + if ($this->services->save($data)) { + return app('json')->success(100021); + } else { + return app('json')->fail(100022); + } + } + + /** + * 批量保存权限 + * + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/11 + */ + public function batchSave(): \think\Response + { + $menus = $this->request->post('menus', []); + if (!$menus) { + return app('json')->fail(100026); + } + $data = []; + + $uniqueAuthAll = $this->services->getColumn(['delete_time' => null, 'is_show' => 1], 'unique_auth'); + $uniqueAuthAll = array_filter($uniqueAuthAll, function ($item) { + return !!$item; + }); + $uniqueAuthAll = array_unique($uniqueAuthAll); + + $uniqueFn = function ($path) use ($uniqueAuthAll) { + $attPath = explode('/', $path); + $uniqueAuth = ''; + if ($attPath) { + $pathData = []; + foreach ($attPath as $vv) { + if (!str_contains($vv, '<')) { + $pathData[] = $vv; + } + } + $uniqueAuth = implode('-', $pathData); + } + + if (in_array($uniqueAuth, $uniqueAuthAll)) { + $uniqueAuth .= '-' . uniqid(); + } + + $uniqueAuthAll[] = $uniqueAuth; + + return $uniqueAuth; + }; + + foreach ($menus as $menu) { + if (empty($menu['menu_name'])) { + return app('json')->fail(400198); + } + if (isset($menu['unique_auth']) && $menu['unique_auth']) { + $menu['unique_auth'] = explode('/', $menu['api_url']); + } + $data[] = [ + 'methods' => $menu['method'], + 'menu_name' => $menu['menu_name'], + 'unique_auth' => !empty($menu['unique_auth']) ? $menu['unique_auth'] : $uniqueFn($menu['api_url']), + 'api_url' => $menu['api_url'], + 'pid' => $menu['path'], + 'auth_type' => 2, + 'is_show' => 1, + 'is_show_path' => 1, + ]; + } + $this->services->saveAll($data); + return app('json')->success(100021); + } + + /** + * 获取一条菜单权限信息 + * + * @param int $id + * + * @return \think\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function read(string $id): \think\Response + { + if (!$id) { + return app('json')->fail(100026); + } + return app('json')->success($this->services->find($id)); + } + + /** + * 修改菜单权限表单获取 + * + * @param int $id + * + * @return \think\Response + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function edit($id): \think\Response + { + if (!$id) { + return app('json')->fail(100100); + } + return app('json')->success($this->services->updateMenus((int)$id)); + } + + /** + * 修改菜单 + * + * @param $id + * + * @return mixed + */ + public function update($id): mixed + { + if (!$id || !($menu = $this->services->get($id))) + return app('json')->fail(100026); + $data = $this->request->postMore([ + 'menu_name', + 'controller', + ['module', 'admin'], + 'action', + 'params', + ['icon', ''], + ['menu_path', ''], + ['api_url', ''], + ['methods', ''], + ['unique_auth', ''], + ['path', []], + ['sort', 0], + ['pid', 0], + ['is_header', 0], + ['header', ''], + ['auth_type', 0], + ['access', 1], + ['is_show', 0], + ['is_show_path', 0], + ]); + if (!$data['menu_name']) + return app('json')->fail(400198); + $data['path'] = implode('/', $data['path']); + if ($this->services->update($id, $data)) + return app('json')->success(100001); + else + return app('json')->fail(100007); + } + + /** + * 删除指定资源 + * + * @param int $id + * + * @return \think\Response + */ + public function delete($id): \think\Response + { + if (!$id) { + return app('json')->fail(100100); + } + + if (!$this->services->delete($id)) { + return app('json')->fail(100008); + } else { + return app('json')->success(100002); + } + } + + /** + * 权限的开启和关闭,显示和隐藏 + * + * @param $id + * + * @return mixed + */ + public function show($id) + { + if (!$id) { + return app('json')->fail(100100); + } + + [$isShow, $isShowPath] = $this->request->postMore([['is_show', 0], ['is_show_path', 0]], true); + if ($isShow == -1) { + $res = $this->services->update($id, ['is_show_path' => $isShowPath]); + } else { + $res = $this->services->update($id, ['is_show' => $isShow, 'is_show_path' => $isShow]); + } + + if ($res) { + return app('json')->success(100001); + } else { + return app('json')->fail(100007); + } + } + + /** + * 获取菜单数据 + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function menus(): mixed + { + [$menus, $unique] = $this->services->getMenusList($this->adminInfo['roles'], (int)$this->adminInfo['level']); + return app('json')->success(['menus' => $menus, 'unique' => $unique]); + } + + /** + * 获取路由分类 + * + * @param SystemRouteCateServices $service + * + * @return \think\Response + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/25 + */ + public function ruleCate(SystemRouteCateServices $service): \think\Response + { + return app('json')->success($service->getAllList('adminapi')); + } + + /** + * 获取接口列表 + * + * @param \app\services\system\route\SystemRouteServices $services + * + * @return \think\Response + */ + public function ruleList(SystemRouteServices $services): \think\Response + { + $cateId = request()->get('cate_id', 0); + //获取所有的路由 + $ruleList = $services->selectList(['cate_id' => $cateId, 'app_name' => 'adminapi'])->toArray(); + return app('json')->success($ruleList); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemMessage.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemMessage.php new file mode 100644 index 0000000000000000000000000000000000000000..10601352cea8f6ca244552c6c1e17f2fbf495121 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemMessage.php @@ -0,0 +1,35 @@ +getRootPath() . 'public/lms_admin/admin/data/message.json'); + $ret = !empty($data) ? json_decode($data, 1) : []; + return app('json')->success('Success',$ret); + } + +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemPost.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemPost.php new file mode 100644 index 0000000000000000000000000000000000000000..0980ec3ae648703187ee3edcb07a0b8626423b38 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemPost.php @@ -0,0 +1,157 @@ +services = $services; + } + + /** + * 显示资源列表 + * + * @return \think\response\Json + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index(): \think\response\Json + { + $where = $this->request->getMore([ + ['dept_id',''], + ['post_code', ''], + ['post_name', ''], + ]); + return app('json')->success($this->services->getList($where, ['*'])); + + } + + /** + * 获取一条信息 + * + * @param string $id + * + * @return \think\Response + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function read(string $id): \think\Response + { + if (!$id) { + return app('json')->fail(100026); + } + return app('json')->success($this->services->find($id)); + } + + /** + * 保存新建的资源 + * + * @return \think\response\Json + */ + public function save(): \think\response\Json + { + $data = $this->request->postMore([ + 'post_code', + 'post_name', + ['dept_id'], + ['pid', '-1'], + ['icon', ''], + ['remarks', ''], + ['sort', 10], + ]); + + $message = [ + 'post_name' => '400187', + 'dept_id' => '所属部门不能为空', + ]; + + $this->validate($data, [ + 'dept_id' => 'require', + 'post_name' => 'require', + ], $message, true); + if (!$this->services->save($data)) { + return app('json')->fail(100006); + } + $this->services->cacheDriver()->clear(); + return app('json')->success(100000); + + } + + /** + * 修改角色 + * + * @param $id + * + * @return \think\response\Json + */ + public function update($id): \think\response\Json + { + if (!$id || !($role = $this->services->get($id))) { + return app('json')->fail(100026); + } + $data = $this->request->postMore([ + 'post_code', + 'post_name', + 'dept_id', + ['pid', '-1'], + ['icon', ''], + ['remarks', ''], + ['sort', 10], + ]); + $message = [ + 'post_name' => '400187', + 'dept_id' => '所属部门不能为空', + ]; + + $this->validate($data, [ + 'dept_id' => 'require', + 'post_name' => 'require', + ], $message, true); + + if ($this->services->update($id, $data)) { + return app('json')->success(100001); + } else { + return app('json')->fail(100007); + } + } + + /** + * 删除指定资源 + * + * @param $id + * + * @return \think\response\Json + * @throws \ReflectionException + */ + public function delete($id): \think\response\Json + { + if (!$id) { + return app('json')->fail(100100); + } + if (!$this->services->delete($id)) { + return app('json')->fail(100008); + } else { + $this->services->cacheDriver()->clear(); + return app('json')->success(100002); + } + } + +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemRole.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemRole.php new file mode 100644 index 0000000000000000000000000000000000000000..5d917969c756870370fcc2b5f66421e12c30f06c --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemRole.php @@ -0,0 +1,176 @@ +services = $services; + } + + /** + * 显示资源列表 + * + * @return \think\response\Json + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index(): \think\response\Json + { + $where = $this->request->getMore([ + ['status', ''], + ['role_name', ''], + ]); + return app('json')->success($this->services->getRoleList($where)); + } + + /** + * 获取一条角色信息 + * + * @param string $id + * + * @return \think\Response + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function read(string $id): \think\Response + { + if (!$id) { + return app('json')->fail(100026); + } + return app('json')->success($this->services->find($id)); + } + + /** + * 保存新建的资源 + * + * @return \think\response\Json + */ + public function save(): \think\response\Json + { + $data = $this->request->postMore([ + 'role_code', + 'role_name', + ['pid', '-1'], + ['icon', ''], + ['remarks', ''], + ['sort', 10], + ['status', 0], + ]); + + $message = [ + 'role_name' => '400220', + ]; + + $this->validate($data, [ + 'role_name' => 'require', + ], $message, true); + + if (!$this->services->save($data)) return app('json')->fail(400223); + $this->services->cacheDriver()->clear(); + return app('json')->success(400222); + + } + + /** + * 删除指定资源 + * + * @param $id + * + * @return mixed + * @throws \ReflectionException + */ + public function delete($id): \think\response\Json + { + if (!$id) { + return app('json')->fail(100100); + } + if (!$this->services->delete($id)) { + return app('json')->fail(100008); + } else { + $this->services->cacheDriver()->clear(); + return app('json')->success(100002); + } + } + + /** + * 修改角色 + * + * @param $id + * + * @return \think\response\Json + */ + public function update($id): \think\response\Json + { + if (!$id || !($role = $this->services->get($id))) { + return app('json')->fail(100026); + } + $data = $this->request->postMore([ + 'role_code', + 'role_name', + ['pid', '-1'], + ['icon', ''], + ['remarks', ''], + ['sort', 10], + ['status', 0], + ]); + if (!$data['role_name']) { + return app('json')->fail(400220); + } + if ($this->services->update($id, $data)) { + return app('json')->success(100001); + } else { + return app('json')->fail(100007); + } + } + + /** + * 修改状态 + * + * @param $id + * @param $status + * + * @return mixed + */ + public function set_status($id, $status): \think\response\Json + { + if (!$id) { + return app('json')->fail(100100); + } + $role = $this->services->get($id); + if (!$role) { + return app('json')->fail(400199); + } + $role->status = $status; + if ($role->save()) { + $this->services->cacheDriver()->clear(); + return app('json')->success(100001); + } else { + return app('json')->fail(100007); + } + } + + public function menuList(SystemMenusServices $services) + { + $menus = $services->getMenus($this->adminInfo['level'] == 0 ? [] : $this->adminInfo['role_id']); + return app('json')->success($menus); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemRoleDept.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemRoleDept.php new file mode 100644 index 0000000000000000000000000000000000000000..d21a6e0ec1c5bd1267e5afb8f383a808f41b1068 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemRoleDept.php @@ -0,0 +1,50 @@ +services = $services; + } + + /** + * 保存新建的资源 + * + * @return \think\response\Json + */ + public function save(): \think\response\Json + { + $data = $this->request->postMore([ + 'role_id', + 'role_name', + ['checked_dept', []], + ]); + + $message = [ + 'role_id' => '100100', + ]; + + $this->validate($data, [ + 'role_id' => 'require', + ], $message, true); + + if (!$this->services->create($data)) return app('json')->fail(400223); + $this->services->cacheDriver()->clear(); + return app('json')->success(400222); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemRoleMenu.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemRoleMenu.php new file mode 100644 index 0000000000000000000000000000000000000000..26394595a27eee45330976febad174eec0678f04 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemRoleMenu.php @@ -0,0 +1,50 @@ +services = $services; + } + + /** + * 保存新建的资源 + * + * @return \think\response\Json + */ + public function save(): \think\response\Json + { + $data = $this->request->postMore([ + 'role_id', + 'role_name', + ['checked_menus', []], + ]); + + $message = [ + 'role_id' => '100100', + ]; + + $this->validate($data, [ + 'role_id' => 'require', + ], $message, true); + + if (!$this->services->create($data)) return app('json')->fail(400223); + $this->services->cacheDriver()->clear(); + return app('json')->success(400222); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemRolePost.php b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemRolePost.php new file mode 100644 index 0000000000000000000000000000000000000000..7f38e21be09bbb2dcb55002316a69ab50f73ce82 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/setting/SystemRolePost.php @@ -0,0 +1,50 @@ +services = $services; + } + + /** + * 保存新建的资源 + * + * @return \think\response\Json + * @throws \Exception + */ + public function save(): \think\response\Json + { + $data = $this->request->postMore([ + 'role_id', + 'role_name', + ['checked_post', []], + ]); + $message = [ + 'role_id' => '100100', + ]; + + $this->validate($data, [ + 'role_id' => 'require', + ], $message, true); + + if (!$this->services->create($data)) return app('json')->fail(400223); + $this->services->cacheDriver()->clear(); + return app('json')->success(400222); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/system/Clear.php b/demo/thinkphp/backend/app/adminapi/controller/v1/system/Clear.php new file mode 100644 index 0000000000000000000000000000000000000000..1746b3946fc19418087eecb689db483bb5b5ce2d --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/system/Clear.php @@ -0,0 +1,51 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\v1\system; + +use think\App; +use app\services\system\log\ClearServices; +use app\adminapi\controller\AuthController; + +/** + * + * 缓存控制类 + * @author Mr.April + * @since 1.0 + */ +class Clear extends AuthController +{ + public function __construct(App $app, ClearServices $services) + { + parent::__construct($app); + $this->services = $services; + } + + /** + * 刷新数据缓存 + */ + public function refresh_cache() + { + $this->services->refresCache(); + return app('json')->success(400302); + } + + + /** + * 删除日志 + */ + public function delete_log() + { + $this->services->deleteLog(); + return app('json')->success(100002); + } +} + + diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemCrontab.php b/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemCrontab.php new file mode 100644 index 0000000000000000000000000000000000000000..4feb44d045d45d8be3900f74832bdae71b39ae89 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemCrontab.php @@ -0,0 +1,114 @@ +services = $services; + } + + /** + * 获取定时任务列表 + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function getTimerList(): \think\response\Json + { + + $where = ['delete_time' => null]; + return app('json')->success($this->services->getTimerList($where)); + } + + /** + * 获取定时任务详情 + * + * @param $id + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getTimerInfo($id): \think\response\Json + { + return app('json')->success($this->services->getTimerInfo($id)); + } + + /** + * 获取定时任务类型 + * + * @return mixed + */ + public function getMarkList(): \think\response\Json + { + return app('json')->success($this->services->getMarkList()); + } + + /** + * 保存更新定时任务 + * + * @return mixed + */ + public function saveTimer(): \think\response\Json + { + $data = $this->request->postMore([ + ['id', 0], + ['name', ''], + ['mark', ''], + ['content', ''], + ['type', 0], + ['is_open', 0], + ['week', 0], + ['day', 0], + ['hour', 0], + ['minute', 0], + ['second', 0], + ]); + $this->services->saveTimer($data); + return app('json')->success(100000); + } + + /** + * 删除定时任务 + * + * @param $id + * + * @return \think\response\Json + */ + public function delTimer($id): \think\response\Json + { + $this->services->delTimer($id); + return app('json')->success(100002); + } + + /** + * 设置定时任务状态 + * + * @param $id + * @param $is_open + * + * @return mixed + */ + public function setTimerStatus($id, $is_open): \think\response\Json + { + $this->services->setTimerStatus($id, $is_open); + return app('json')->success(100014); + } + +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemDatabackup.php b/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemDatabackup.php new file mode 100644 index 0000000000000000000000000000000000000000..312ca5420efba75438b66171e343be4482709f4b --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemDatabackup.php @@ -0,0 +1,187 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\v1\system; + +use think\App; +use think\facade\Db; +use think\facade\Session; +use app\adminapi\controller\AuthController; +use app\services\system\databackup\SystemDatabackupServices; + +/** + * 数据备份 + * Class SystemDatabackup + * + * @package app\admin\controller\system + */ +class SystemDatabackup extends AuthController +{ + /** + * 构造方法 + * SystemDatabackup constructor. + * + * @param App $app + * @param SystemDatabackupServices $services + */ + public function __construct(App $app, SystemDatabackupServices $services) + { + parent::__construct($app); + $this->services = $services; + } + + /** + * 获取数据库表 + */ + public function index() + { + return app('json')->success($this->services->getDataList()); + } + + /** + * 查看表结构 详情 + */ + public function read() + { + $tablename = request()->param('tablename', '', 'htmlspecialchars'); + return app('json')->success($this->services->getRead($tablename)); + } + + /** + * 更新数据表或者表字段备注 + * + * @return \think\Response + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/04/11 + */ + public function updateMark() + { + [$table, $field, $type, $mark, $is_field] = $this->request->postMore([ + ['table', ''], + ['field', ''], + ['type', ''], + ['mark', ''], + ['is_field', 0], + ], true); + if ($is_field == 0) { + $sql = "ALTER TABLE $table COMMENT '$mark'"; + } else { + $sql = "ALTER TABLE $table MODIFY COLUMN $field $type COMMENT '$mark'"; + } + Db::execute($sql); + return app('json')->success(100024); + } + + /** + * 优化表 + */ + public function optimize() + { + $tables = $this->request->param('tables', '', 'htmlspecialchars'); + $res = $this->services->getDbBackup()->optimize($tables); + return app('json')->success($res ? 100047 : 100048); + } + + /** + * 修复表 + */ + public function repair() + { + $tables = $this->request->param('tables', '', 'htmlspecialchars'); + $res = $this->services->getDbBackup()->repair($tables); + return app('json')->success($res ? 100049 : 100050); + } + + /** + * 备份表 + */ + public function backup() + { + $tables = $this->request->param('tables', '', 'htmlspecialchars'); + $data = $this->services->backup($tables); + return app('json')->success(100051); + } + + /** + * 获取备份记录表 + */ + public function fileList() + { + return app('json')->success($this->services->getBackup()); + } + + /** + * 删除备份记录表 + */ + public function delFile() + { + $filename = intval(request()->post('filename')); + $files = $this->services->getDbBackup()->delFile($filename); + return app('json')->success(100002); + } + + /** + * 导入备份记录表 + */ + public function import() + { + [$part, $start, $time] = $this->request->postMore([ + [['part', 'd'], 0], + [['start', 'd'], 0], + [['time', 'd'], 0], + ], true); + $db = $this->services->getDbBackup(); + if (is_numeric($time) && !$start) { + $list = $db->getFile('timeverif', $time); + if (is_array($list)) { + session::set('backup_list', $list); + return app('json')->success(400307, array('part' => 1, 'start' => 0)); + } else { + return app('json')->fail(400308); + } + } else if (is_numeric($part) && is_numeric($start) && $part && $start) { + $list = session::get('backup_list'); + $start = $db->setFile($list)->import($start); + if (false === $start) { + return app('json')->fail(400309); + } elseif (0 === $start) { + if (isset($list[++$part])) { + $data = array('part' => $part, 'start' => 0); + return app('json')->success(400310, $data); + } else { + session::delete('backup_list'); + return app('json')->success(400311); + } + } else { + $data = array('part' => $part, 'start' => $start[0]); + if ($start[1]) { + $rate = floor(100 * ($start[0] / $start[1])); + return app('json')->success(400310, $data); + } else { + $data['gz'] = 1; + return app('json')->success(400310, $data); + } + } + } else { + return app('json')->fail(100100); + } + } + + /** + * 下载备份记录表 + */ + public function downloadFile() + { + $time = intval(request()->param('time')); + return app('json')->success(['key' => $this->services->getDbBackup()->downloadFile($time, 0, true)]); + } + +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemDict.php b/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemDict.php new file mode 100644 index 0000000000000000000000000000000000000000..7302a2c3c11553495f75b70870be84ddc286be39 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemDict.php @@ -0,0 +1,188 @@ +services = $services; + } + + /** + * index + * + * @param \app\Request $request + * + * @return \think\response\Json + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index(Request $request): \think\response\Json + { + $where = $request->getMore([['name', '']]); + return app('json')->success($this->services->getDictList($where)); + } + + /** + * 添加字典 + * + * @param \app\Request $request + * + * @return \think\response\Json + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function save(Request $request): \think\response\Json + { + $data = $request->postMore([ + ['name', ''], + ['value', ''], + ]); + + $message = [ + 'name' => '400220', + ]; + $this->validate($data, [ + 'name' => 'require', + ], $message, true); + if ($this->services->saveDict($data['name'], $data['value'])) { + return app('json')->success(100000); + } else { + return app('json')->fail(100006); + } + } + + /** + * 获取详情 + * + * @param $id + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function read($id): \think\response\Json + { + if (empty($id)) { + return app('json')->fail(100100); + } + return app('json')->success($this->services->read($id)); + } + + /** + * 更新 + * + * @param \app\Request $request + * @param $id + * + * @return \think\response\Json + */ + public function update(Request $request, $id): \think\response\Json + { + if (empty($id)) { + return app('json')->fail(100100); + } + $data = $request->postMore([ + ['name', ''], + ['value', ''], + ]); + + $message = [ + 'name' => '400220', + ]; + $this->validate($data, [ + 'name' => 'require', + ], $message, true); + + if ($this->services->updateDict($id, $data)) { + return app('json')->success(100000); + } else { + return app('json')->fail(100006); + } + + } + + /** + * 删除字典 + * + * @param \app\Request $request + * @param $id + * + * @return \think\response\Json + */ + public function delete(Request $request, $id): \think\response\Json + { + if (empty($id)) { + return app('json')->fail(100100); + } + if ($this->services->delete($id, 'id')) { + return app('json')->success(100002); + } else { + return app('json')->fail(100008); + } + } + + /** + * 批量删除 + * + * @param \app\Request $request + * + * @return \think\response\Json + */ + public function batchDelete(Request $request): \think\response\Json + { + $data = $request->post('data', []); + if (empty($data)) { + return app('json')->fail(100100); + } + foreach ($data as $value) { + $this->services->delete($value, 'id'); + } + return app('json')->success(100002); + } + + /** + * 获取字典详情 + * + * @param $name + * + * @return \think\response\Json + */ + public function get($name): \think\response\Json + { + $data = $this->services->getName($this->services->dictNameToOptionName($name)); + $data['value'] = json_decode($data['value']); + return app('json')->success($data); + } + +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemLog.php b/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemLog.php new file mode 100644 index 0000000000000000000000000000000000000000..951e7525deffa651fc98465ebf776791aa83843d --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemLog.php @@ -0,0 +1,62 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\v1\system; + +use app\services\system\admin\SystemAdminServices; +use think\App; +use app\adminapi\controller\AuthController; +use app\services\system\log\SystemLogServices; + +/** + * 管理员操作记录 + * + * @author Mr.April + * @since 1.0 + */ +class SystemLog extends AuthController +{ + /** + * 构造方法 + * SystemLog constructor. + * + * @param App $app + * @param SystemLogServices $services + */ + public function __construct(App $app, SystemLogServices $services) + { + parent::__construct($app); + $this->services = $services; + $this->services->deleteLog(); + } + + /** + * 显示操作记录 + */ + public function index() + { + $where = $this->request->getMore([ + ['pages', ''], + ['path', ''], + ['ip', ''], + ['admin_id', ''], + ['data', '', '', 'time'], + ]); + return app('json')->success($this->services->getLogList($where, (int)$this->adminInfo['level'])); + } + + public function search_admin(SystemAdminServices $services): \think\response\Json + { + $info = $services->getOrdAdmin('id,real_name', $this->adminInfo['level']); + return app('json')->success(compact('info')); + } + +} + diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemRoute.php b/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemRoute.php new file mode 100644 index 0000000000000000000000000000000000000000..d7adb11d62d0f05e8a3465b2aae535d199de59eb --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemRoute.php @@ -0,0 +1,168 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\adminapi\controller\v1\system; + + +use app\adminapi\controller\AuthController; +use app\services\system\route\SystemRouteServices; +use think\App; + +/** + * Class SystemRoute + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + * @package app\adminapi\controller\v1\setting + */ +class SystemRoute extends AuthController +{ + + /** + * SystemRoute constructor. + * @param App $app + * @param SystemRouteServices $services + */ + public function __construct(App $app, SystemRouteServices $services) + { + parent::__construct($app); + $this->services = $services; + } + + /** + * 同步路由权限 + * @param string $appName + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function syncRoute(string $appName = 'adminapi') + { + $this->services->syncRoute($appName); + + return app('json')->success(100038); + } + + /** + * 列表数据 + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function index() + { + $where = $this->request->getMore([ + ['name_like', ''], + ['app_name', 'adminapi'] + ]); + + return app('json')->success($this->services->getList($where)); + } + + /** + * tree数据 + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function tree(): \think\Response + { + [$name, $appName] = $this->request->getMore([ + ['name_like', ''], + ['app_name', 'adminapi'] + ], true); + + return app('json')->success($this->services->getTreeList($appName, $name)); + } + + + /** + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function save($id = 0) + { + $data = $this->request->postMore([ + ['cate_id', 0], + ['name', ''], + ['path', ''], + ['method', ''], + ['type', 0], + ['app_name', ''], + ['request', []], + ['response', []], + ['request_example', []], + ['response_example', []], + ['describe', ''], + ]); + +// if (!$data['name']) { +// return app('json')->fail(500031); +// } +// if (!$data['path']) { +// return app('json')->fail(500032); +// } +// if (!$data['method']) { +// return app('json')->fail(500033); +// } +// if (!$data['app_name']) { +// return app('json')->fail(500034); +// } + if ($id) { + $this->services->update($id, $data); + } else { + $data['add_time'] = date('Y-m-d H:i:s'); + $this->services->save($data); + } + $this->services->cacheDriver()->clear(); + + return app('json')->success($id ? 100001 : 100021); + } + + /** + * @param $id + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function read($id) + { + return app('json')->success($this->services->getInfo((int)$id)); + } + + /** + * @param $id + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function delete($id) + { + if (!$id) { + return app('json')->fail(500035); + } + + $this->services->destroy($id); + + return app('json')->success(100002); + } + + +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemRouteCate.php b/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemRouteCate.php new file mode 100644 index 0000000000000000000000000000000000000000..b67946baf0b887e40cb1d2107c322afa9921d16f --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/system/SystemRouteCate.php @@ -0,0 +1,156 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\adminapi\controller\v1\system; + +use app\adminapi\controller\AuthController; +use app\services\system\route\SystemRouteCateServices; +use think\App; +use think\Request; + +/** + * Class SystemRouteCate + * + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + * @package app\adminapi\controller\v1\setting + */ +class SystemRouteCate extends AuthController +{ + + /** + * SystemRouteCate constructor. + * + * @param App $app + * @param SystemRouteCateServices $services + */ + public function __construct(App $app, SystemRouteCateServices $services) + { + parent::__construct($app); + $this->services = $services; + } + + /** + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function index() + { + return app('json')->success($this->services->getAllList()); + } + + /** + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function create(): \think\Response + { + return app('json')->success($this->services->getFrom(0, $this->request->get('app_name', 'adminapi'))); + } + + /** + * @param Request $request + * + * @return \think\Response + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function save(Request $request): \think\Response + { + $data = $request->postMore([ + ['path', []], + ['name', ''], + ['sort', 0], + ['app_name', ''], + ]); + + if (!$data['name']) { + return app('json')->fail(500037); + } + + $data['add_time'] = time(); + $data['pid'] = $data['path'][count($data['path']) - 1] ?? 0; + $this->services->save($data); + + return app('json')->success(100000); + + } + + /** + * @param $id + * + * @return \think\Response + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function edit($id) + { + return app('json')->success($this->services->getFrom($id, $this->request->get('app_name', 'adminapi'))); + } + + /** + * @param Request $request + * @param $id + * + * @return \think\Response + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function update(Request $request, $id): \think\Response + { + $data = $request->postMore([ + ['path', []], + ['name', ''], + ['sort', 0], + ['app_name', ''], + ]); + + if (!$data['name']) { + return app('json')->fail(500037); + } + + $data['pid'] = $data['path'][count($data['path']) - 1] ?? 0; + $this->services->update($id, $data); + + return app('json')->success(100001); + } + + /** + * @param SystemRouteServices $service + * @param $id + * + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function delete(SystemRouteServices $service, $id): \think\Response + { + if (!$id) { + return app('json')->fail(500035); + } + + if ($service->count(['cate_id' => $id])) { + return app('json')->fail(500038); + } + + $this->services->delete($id); + + return app('json')->success(100002); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/wf/Category.php b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/Category.php new file mode 100644 index 0000000000000000000000000000000000000000..63337f7ec9ce961af228d8367875346a363ecbb4 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/Category.php @@ -0,0 +1,134 @@ +service = new ProcessEngines(new ConfigurationRewrite($config)); + } + + public function index(): \think\response\Json + { + $param = $this->request->getMore([ + ['status', ''], + ['name', ''], + ['is_del', 0], + ['page', 1], + ['limit', 15], + ]); + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processTypesService()->page((object)$param); + return app('json')->success($result); + } + + public function read(string $id): \think\Response\Json + { + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processTypesService()->findById($id); + if ($result) { + return app('json')->success($result->toArray()); + } else { + return app('json')->fail('参数错误'); + } + } + + public function save(Request $request): \think\Response\Json + { + $ingeniousEngines = $this->service; + $data = $this->request->postMore([ + ['name', ''], + ['pid', '0'], + ['icon', ''], + ['remark', ''], + ['sort', 10], + ['create_user', $request->adminId()], + ]); + if (empty($data['name'])) { + return app('json')->fail('名称不能为空'); + } + if ($ingeniousEngines->processTypesService()->create((object)$data)) { + return app('json')->success('创建成功'); + } else { + return app('json')->fail('创建失败'); + } + } + + public function delete(string $id): \think\Response\Json + { + $ingeniousEngines = $this->service; + if (!$id) return app('json')->fail('参数ID不能为空'); + try { + $ingeniousEngines->processTypesService()->del($id); + return app('json')->success('删除成功'); + } catch (LFlowException $e) { + return app('json')->fail('删除失败' . $e->getMessage()); + } + } + + public function batchRemove(): \think\Response\Json + { + $ids = $this->request->post('data'); + if (!$ids) return app('json')->fail('参数ID不能为空'); + $ingeniousEngines = $this->service; + try { + $ingeniousEngines->processTypesService()->del(explode(',', $ids)); + return app('json')->success('删除成功'); + } catch (LFlowException $e) { + return app('json')->fail('删除失败' . $e->getMessage()); + } + } + + public function update(Request $request, string $id): \think\Response\Json + { + $ingeniousEngines = $this->service; + if (!$id || !($ingeniousEngines->processTypesService()->findById($id))) { + return app('json')->fail('资源不存在'); + } + $data = $this->request->postMore([ + ['id', $id], + ['name', ''], + ['icon', ''], + ['pid', '0'], + ['remark', ''], + ['sort', 10], + ['user_id', $request->adminId()], + ]); + if ($ingeniousEngines->processTypesService()->update((object)$data)) { + return app('json')->success('更新成功'); + } else { + return app('json')->fail('更新失败'); + } + } + + + public function typeTree() + { + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processTypesService()->selectTree((object)[]); + return app('json')->success($result); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/wf/Define.php b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/Define.php new file mode 100644 index 0000000000000000000000000000000000000000..56038ad4a5fc23a922062747ebab32604f08e6c5 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/Define.php @@ -0,0 +1,180 @@ + new LoginUserHolder($request), + 'findUserApi' => new UserProcessingApi(), + ]; + + $this->service = new ProcessEngines(new ConfigurationRewrite($config)); + } + + public function index(Request $request): \think\response\Json + { + $args = $this->request->getMore([ + ['id', ''], + ['type_id', ''], + ['name', ''], + ['display_name', ''], + ['instance_url', ''], + ['state', ''],//默认全部 + ['version', ''], + ['creator', ''], + ['page', 0], + ['limit', 0], + ]); + $favoriteParam = [ + 'user_id' => $request->adminId(), + 'favorite' => 1, + 'page' => 0, + 'limit' => 0, + ]; + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processDefineService()->page((object)$args); + $favorite = $ingeniousEngines->processDefineService()->favoritePage((object)$favoriteParam); + $favoriteData = isset($favorite['list']) && !empty($favorite['list']) ? $favorite['list'] : []; + + //匹配是否为收藏的流程 + foreach ($result['list'] as $key => $value) { + foreach ($favoriteData as $val) { + $result['list'][$key]['favorite'] = 0; + $result['list'][$key]['process_define_favorite_id'] = ''; + if ($value['id'] === $val['process_define_id']) { + $result['list'][$key]['favorite'] = 1; + $result['list'][$key]['process_define_favorite_id'] = $val['id']; + continue; + } + } + } + return app('json')->success($result); + } + + public function read(string $id): \think\Response\Json + { + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processDefineService()->findById($id); + if ($result != null) { + return app('json')->success($result->toArray()); + } else { + return app('json')->fail('参数错误'); + } + } + + public function setStatus(Request $request) + { + try { + $ingeniousEngines = $this->service; + $id = $request->param('id'); + $state = $request->param('state'); + $ingeniousEngines->processDefineService()->updateState($id, $state, $request->adminId()); + return app('json')->success('操作成功'); + } catch (LFlowException $e) { + return app('json')->fail($e->getMessage()); + } + } + + public function startAndExecute(Request $request) + { + Db::startTrans(); + try { + $args = ProcessFlowUtils::variableToDict($request->param()); + $args->put(ProcessConst::USER_USER_ID, $request->adminId()); + $processDefineId = $request->param(ProcessConst::PROCESS_DEFINE_ID_KEY); + if (empty($processDefineId)) { + return app('json')->fail(ProcessConst::PROCESS_DEFINE_ID_KEY + '必须参数不能为空'); + } + $ingeniousEngines = $this->service; + $ingeniousEngines->processInstanceService()->startAndExecute($processDefineId, $args); + Db::commit(); + return app('json')->success('发起成功'); + } catch (LFlowException $e) { + Db::rollback(); + return app('json')->fail($e->getMessage()); + } + + } + + public function delete(string $id): \think\Response\Json + { + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processDefineService()->del($id); + if (!$result) { + return app('json')->fail('操作失败'); + } + return app('json')->success('删除成功'); + } + + public function processFavorite(Request $request) + { + $ingeniousEngines = $this->service; + $param = $request->postMore([ + ['user_id', $request->adminId()], + ['process_define_id'], + ['favorite', 1], + ]); + $result = $ingeniousEngines->processDefineService()->definitionFavorite((object)$param); + if (!$result) { + return app('json')->fail('收藏失败'); + } + return app('json')->success('收藏成功'); + } + + public function favoritePage(Request $request): \think\Response\Json + { + $ingeniousEngines = $this->service; + $param = $request->postMore([ + ['user_id', $request->adminId()], + ['process_define_id', ''], + ['favorite', 1], + ['page', 0], + ['limit', 0], + ]); + $result = $ingeniousEngines->processDefineService()->favoritePage((object)$param); + return app('json')->success($result); + } + + public function favoriteDelete(Request $request): \think\Response\Json + { + $ingeniousEngines = $this->service; + $data = $request->param('data', []); + $result = $ingeniousEngines->processDefineService()->favoriteDel($data); + if (!$result) { + return app('json')->fail('操作失败'); + } + return app('json')->success('操作成功'); + } + +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/wf/Designer.php b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/Designer.php new file mode 100644 index 0000000000000000000000000000000000000000..87df03810b25fc65881e4c62f126a9dc3b2ad75d --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/Designer.php @@ -0,0 +1,177 @@ +service = new ProcessEngines(new ConfigurationRewrite($config)); + } + + public function index(): \think\response\Json + { + $param = $this->request->getMore([ + ['id', ''], + ['model_key', ''], + ['model_name', ''], + ['model_group_id', ''], + ['page',1], + ['limit',10] + ]); + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processDesignService()->page((object)$param); + return app('json')->success($result); + } + + public function read(string $id): \think\Response\Json + { + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processDesignService()->findById($id); + if ($result != null) { + return app('json')->success($result->toArray()); + } else { + return app('json')->fail('参数错误'); + } + } + + public function save(Request $request): \think\Response\Json + { + $ingeniousEngines = $this->service; + $data = $this->request->postMore([ + ['name', ''], + ['display_name', ''], + ['description', ''], + ['type_id', ''], + ['icon', ''], + ['remark', ''], + ['create_user', $request->adminId()], + ]); + if (empty($data['name'])) { + return app('json')->fail('唯一编码不能为空'); + } + if (empty($data['display_name'])) { + return app('json')->fail('显示名称不能为空'); + } + if ($ingeniousEngines->processDesignService()->create((object)$data)) { + return app('json')->success('添加成功'); + } else { + return app('json')->fail('添加失败'); + } + } + + public function updateDefine(): \think\Response\Json + { + $data = $this->request->param(); + $data[ProcessConst::CREATE_USER] = \request()->adminId();//追加用户id + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processDesignService()->updateDefine((object)$data); + if ($result) { + return app('json')->success('保存成功'); + } else { + return app('json')->fail('保存失败'); + } + } + + public function delete(string $id): \think\Response\Json + { + $ingeniousEngines = $this->service; + if (!($ingeniousEngines->processDesignService()->del($id))) { + return app('json')->fail(100008); + } + return app('json')->success('删除成功'); + } + + public function batchRemove(): \think\Response\Json + { + $data = $this->request->post('data'); + $ingeniousEngines = $this->service; + $error = []; + foreach (explode(',', $data) as $key => $value) { + $ret = $ingeniousEngines->processDesignService()->del($value); + if (!$ret) { + $error[] = $value . '删除失败'; + } + } + if (count($error) > 0) { + return app('json')->fail(import(',', $error)); + } + return app('json')->success('删除成功'); + } + + public function update(Request $request, string $id): \think\Response\Json + { + $ingeniousEngines = $this->service; + $data = $this->request->postMore([ + ['id', $id], + ['name', ''], + ['display_name', ''], + ['description', ''], + ['type_id', ''], + ['icon', ''], + ['remark', ''], + ['update_user', $request->adminId()], + ]); + if ($ingeniousEngines->processDesignService()->update((object)$data)) { + return app('json')->success('更新成功'); + } else { + return app('json')->fail('更新失败'); + } + } + + public function deploy(Request $request) + { + Db::startTrans(); + try { + $processDesignid = $request->param('id'); + $ingeniousEngines = $this->service; + $ingeniousEngines->processDesignService()->deploy($processDesignid, $request->adminId()); + Db::commit(); + return app('json')->success('部署成功'); + } catch (LFlowException $e) { + Db::rollback(); + return app('json')->fail($e->getMessage()); + } + + } + + public function redeploy(Request $request) + { + Db::startTrans(); + try { + $processDesignid = $request->param('id'); + $ingeniousEngines = $this->service; + $ingeniousEngines->processDesignService()->redeploy($processDesignid, $request->adminId()); + Db::commit(); + return app('json')->success('重新部署成功'); + } catch (LFlowException $e) { + Db::rollback(); + return app('json')->fail($e->getMessage()); + } + + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/wf/Instance.php b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/Instance.php new file mode 100644 index 0000000000000000000000000000000000000000..88cc9f27481d220c94dcea51e983f2cd541985b7 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/Instance.php @@ -0,0 +1,138 @@ +service = new ProcessEngines(new ConfigurationRewrite($config)); + } + + public function index(Request $request): \think\response\Json + { + $args = $this->request->getMore([ + ['operator', $request->adminId()], + ['business_no', ''], + ['display_name', ''], + ['page', 0], + ['limit', 0], + ]); + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processInstanceService()->page((object)$args); + return app('json')->success($result); + } + + public function management(Request $request) + { + $args = $this->request->getMore([ + ['business_no', ''], + ['display_name', ''], + ['page', 0], + ['limit', 0], + ]); + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processInstanceService()->page((object)$args); + return app('json')->success($result); + } + + public function detail(Request $request): \think\Response\Json + { + + $ingeniousEngine = $this->service; + $id = $request->param('id'); + $result = $ingeniousEngine->processInstanceService()->findById($id); + if ($result == null) { + return app('json')->fail('实例不存在或被删除'); + } + return app('json')->success($result->toArray()); + } + + public function withdraw(Request $request) + { + Db::startTrans(); + try { + $ingeniousEngine = $this->service; + $id = $request->param('id', ''); + foreach (explode(',', $id) as $value) { + $ingeniousEngine->processInstanceService()->withdraw($value, $request->adminId()); + } + Db::commit(); + return app('json')->success('撤回成功'); + } catch (LFlowException $e) { + Db::rollback(); + return app('json')->fail($e->getMessage()); + } + } + + public function cascadeDelete(Request $request) + { + Db::startTrans(); + try { + $ingeniousEngine = $this->service; + $id = $request->param('id', ''); + $ingeniousEngine->processInstanceService()->cascadeDelete($id, $request->adminId()); + Db::commit(); + return app('json')->success('删除成功'); + } catch (LFlowException $e) { + Db::rollback(); + return app('json')->fail($e->getMessage()); + } + } + + public function highLightData(Request $request) + { + $ingeniousEngine = $this->service; + $id = $request->param('id'); + $result = $ingeniousEngine->processInstanceService()->highLight($id); + return app('json')->success($result); + } + + public function approvalRecord(Request $request) + { + $ingeniousEngine = $this->service; + $id = $request->param('id'); + $result = $ingeniousEngine->processInstanceService()->approvalRecord($id); + return app('json')->success($result); + } + + /*流程实例抄送******************************************************************************************************/ + public function ccList(Request $request) + { + $args = $this->request->getMore([ + ['actor_id', $request->adminId()], + ['name', ''], + ['display_name', ''], + ['business_no', ''], + ['page', 0], + ['limit', 0], + ]); + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processInstanceService()->ccInstancePage((object)$args); + return app('json')->success($result); + } + +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/wf/OtherHandle.php b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/OtherHandle.php new file mode 100644 index 0000000000000000000000000000000000000000..173144f8ca0b64f52b17ed8dae73bdef34a6ddd3 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/OtherHandle.php @@ -0,0 +1,131 @@ + new LoginUserHolder($request), + 'findUserApi' => new UserProcessingApi(), + ]; + + $this->service = new ProcessEngines(new ConfigurationRewrite($config)); + } + + public function candidatePage(Request $request) + { + $ingeniousEngine = $this->service; + $params = $request->getMore(['process_task_id', 'limit', 'page']); + $result = $ingeniousEngine->processTaskService()->candidatePage(ProcessFlowUtils::variableToDict($params)); + return app('json')->success($result); + } + + public function carbonPage(Request $request) + { + $where = $request->getMore([['search', '']]); + $page = $request->param('page', 0); + $limit = $request->param('limit', 0); + $result = []; + $systemAdmin = new SystemAdminServices(new SystemAdminDao()); + $result['list'] = $systemAdmin->selectList($where, '*', $page, $limit, '', [], true)->toArray(); + $result['count'] = $systemAdmin->count($where); + return app('json')->success($result); + } + + public function userList(Request $request) + { + $param = $this->request->param('search', ''); + $systemAdminServices = app()->make(SystemAdminServices::class); + $result = $systemAdminServices->getAdministratorsList(['account_like' => $param]); + $data = []; + foreach ($result['list'] as $key => $value) { + $data['list'][$key]['name'] = $value['real_name']; + $data['list'][$key]['value'] = $value['id']; + } + $data['count'] = $result['count']; + return app('json')->success($data); + } + + public function userInfo(Request $request) + { + $param = $this->request->param('search', ''); + if (empty($param)) { + return app('json')->success([]); + } + $systemAdminServices = app()->make(SystemAdminServices::class); + $result = $systemAdminServices->getAdminList(['id_in' => $param]); + $data = []; + foreach ($result['list'] as $key => $value) { + $data['list'][$key]['name'] = $value['real_name']; + $data['list'][$key]['value'] = $value['id']; + } + $data['count'] = $result['count']; + return app('json')->success($data); + } + + /** + * 提供设计器对应的参与类 + * + * @return array[] + */ + public function assignmentHandler(): array + { + return [ + [ + 'label' => '直属主管',//注册类的对应名称 + 'value' => AssignmentDirectManager::class, + ], + ]; + } + + /** + * 模拟表单列表 vue 获取html 可以根据自己来操作 + * + * @return \think\Response + */ + public function formHandler(): \think\Response + { + $data = [ + [ + 'label' => '请假申请单', + 'value' => 'leaveForm.html', + ], + [ + 'label' => '补卡申请单', + 'value' => 'reissueForm.html', + ], + [ + 'label' => '测试申请单', + 'value' => 'test.html', + ], + ]; + return app('json')->success($data); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/wf/ProcessUser.php b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/ProcessUser.php new file mode 100644 index 0000000000000000000000000000000000000000..0d256e9fc8d3503b95be3cd9fd9be45d5441a81a --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/ProcessUser.php @@ -0,0 +1,41 @@ + new LoginUserHolder($request), + 'findUserApi' => new UserProcessingApi(), + ]; + + $this->service = new ProcessEngines(new ConfigurationRewrite($config)); + } + + public function doneList(Request $request): \think\Response\Json + { + $ingeniousEngine = $this->service; + $param = $this->request->getMore([ + ['actor_id', $request->adminId()], + ['display_name', ''], + ['process_define_display_name', ''], + ['page', 0], + ['limit', 0], + ['business_no', ''], + ]); + $result = $ingeniousEngine->processTaskService()->doneList((object)$param); + return app('json')->success('获取成功', $result); + } + + //我的代办 + public function todoList(Request $request): \think\Response\Json + { + $ingeniousEngine = $this->service; + $where = $this->request->getMore([ + ['actor_id', $request->adminId()], + ['display_name', ''], + ['business_no', ''], + ]); + $result = $ingeniousEngine->processTaskService()->todoList((object)$where); + return app('json')->success('获取成功', $result); + } + + public function execute(Request $request): \think\Response\Json + { + Db::startTrans(); + try { + $ingeniousEngine = $this->service; + $scene = $request->param(ProcessConst::SUBMIT_TYPE); + $processTaskId = $request->param(ProcessConst::PROCESS_TASK_ID_KEY); + $args = ProcessFlowUtils::variableToDict((object)$request->param()); + $operator = $request->adminId(); + switch ($scene) { + case ProcessSubmitTypeEnum::AGREE[0]: + //同意申请 + $ingeniousEngine->executeProcessTask($processTaskId, $operator, $args); + break; + case ProcessSubmitTypeEnum::REJECT[0]: + //拒绝申请 + $ingeniousEngine->executeAndJumpToEnd($processTaskId, $operator, $args); + break; + case ProcessSubmitTypeEnum::ROLLBACK[0]: + //退回上一步 + $ingeniousEngine->executeAndJumpTask($processTaskId, $operator, $args); + break; + case ProcessSubmitTypeEnum::JUMP[0]: + // 跳转到指定节点 + $taskName = $args->get(ProcessConst::TASK_NAME); + $ingeniousEngine->executeAndJumpTask($processTaskId, $operator, $args, $taskName); + break; + case ProcessSubmitTypeEnum::ROLLBACK_TO_OPERATOR[0]: + //退回申请人 + $ingeniousEngine->executeAndJumpToFirstTaskNode($processTaskId, $operator, $args); + break; + case ProcessSubmitTypeEnum::COUNTERSIGN_DISAGREE[0]: + //会签不同意 追加不同意标识 + $args->put(ProcessConst::COUNTERSIGN_DISAGREE_FLAG, 1); + $ingeniousEngine->executeProcessTask($processTaskId, $operator, $args); + break; + default: + //默认执行 + $ingeniousEngine->executeProcessTask($processTaskId, $operator, $args); + break; + } + + // 存在抄送 + $ccUserIds = $args->get(ProcessConst::CC_ACTORS); + if (!empty($ccUserIds)) { + $processInstanceId = $args->get(ProcessConst::PROCESS_INSTANCE_ID_KEY); + if (is_array($ccUserIds)) { + $ccUserIds = implode(',', $ccUserIds); + } + //创建抄送列表 + $ingeniousEngine->processInstanceService()->createCCInstance($processInstanceId, $operator, $ccUserIds); + } + Db::commit(); + return app('json')->success('操作成功'); + } catch (LFlowException $e) { + Db::rollback(); + return app('json')->fail($e->getMessage()); + } + } + + public function jumpAbleTaskNameList(Request $request) + { + $processInstanceId = $request->param(ProcessConst::PROCESS_INSTANCE_ID_KEY); + $ingeniousEngine = $this->service; + $result = $ingeniousEngine->processTaskService()->jumpAbleTaskNameList($processInstanceId); + return app('json')->success($result); + } + + + + public function userList(Request $request) + { + $where = $request->getMore([['name', '', '', 'account_like']]); + $systemAdminServices = new SystemAdminServices(new SystemAdminDao()); + $result = $systemAdminServices->getAdminList($where); + return app('json')->success($result); + } + + public function surrogate(Request $request) + { + try { + $ingeniousEngine = $this->service; + $processTaskId = $request->param('process_task_id'); + $actors = $request->param('actor_ids'); + $ingeniousEngine->processTaskService()->addTaskActor($processTaskId, $actors); + return app('json')->success('操作成功'); + } catch (LFlowException $e) { + return app('json')->fail($e->getMessage()); + } + } + + public function detail(Request $request) + { + $ingeniousEngine = $this->service; + $id = $request->param('id'); + $result = $ingeniousEngine->processTaskService()->findById($id); + if ($result == null) { + return app('json')->fail('实例不存在或被删除'); + } + return app('json')->success($result->toArray()); + } + +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/wf/api/AssignmentDirectManager.php b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/api/AssignmentDirectManager.php new file mode 100644 index 0000000000000000000000000000000000000000..df536a0a3c81f202ba68cf6081320f0ddb0e31df --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/api/AssignmentDirectManager.php @@ -0,0 +1,53 @@ +getProcessInstance();//流程实列 + $operator = $processInstance->getData('operator');//申请人ID + $variable = $processInstance->getData('variable');//流程实列变量 + $ext = ProcessFlowUtils::variableToDict($variable); + $deptId = $ext->get(ProcessConst::USER_DEPT_ID, ''); + if (empty($deptId)) { + //如果没有部门id 在此实现逻辑通过发起人找上级部门 待优化 + return $result; + } + $deptServices = new SystemDeptServices(new SystemDeptDao()); + $deptData = $deptServices->get($deptId); + if ($deptData == null) { + return []; + } + $result[] = $deptData->getData('manager_id'); + return $result; + } +} \ No newline at end of file diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/wf/api/LoginUserHolder.php b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/api/LoginUserHolder.php new file mode 100644 index 0000000000000000000000000000000000000000..4fde6d34d7eca0a89192127bb64114b932dfd51f --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/api/LoginUserHolder.php @@ -0,0 +1,51 @@ +request = $request; + } + + public function getUserId(): string|int + { + return $this->request->adminId() ?? '0'; + } + + public function getUserName(): string + { + $userInfo = $this->request->adminInfo(); + return $userInfo['account'] ?? ''; + } + + public function getRealName(): string + { + $userInfo = $this->request->adminInfo(); + return $userInfo['real_name'] ?? ''; + } + +} diff --git a/demo/thinkphp/backend/app/adminapi/controller/v1/wf/api/UserProcessingApi.php b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/api/UserProcessingApi.php new file mode 100644 index 0000000000000000000000000000000000000000..91ed41c8e12c16e1be6bd5bb81dda4b16d35153d --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/api/UserProcessingApi.php @@ -0,0 +1,72 @@ +services = new SystemAdminServices(new SystemAdminDao()); + } + + /** + * 引擎用户API实现类 + * + * @param string|int $id + * + * @return object|null + */ + public function findUser(string|int $id): ?object + { + $result = $this->services->get(['id' => $id], ['id', 'account as user_name', 'real_name'], ['departments', 'positions']); + if (empty($result)) { + return null; + } + $deptList = $result->getData('departments'); + $postList = $result->getData('positions'); + $dept_id = []; + $dept_name = []; + $post_id = []; + $post_name = []; + if (!empty($deptList)) { + foreach ($deptList as $dept) { + $dept_name[] = $dept->getData('dept_name'); + $dept_id[] = $dept->getData('dept_id'); + } + } + if (!empty($postList)) { + foreach ($postList as $post) { + $post_name[] = $post->getData('post_name'); + $post_id[] = $post->getData('post_id'); + } + } + $result->set('dept_name', implode(',', $dept_name)); + $result->set('post_name', implode(',', $post_name)); + $result->set('dept_id', implode(',', $dept_id)); + $result->set('post_id', implode(',', $post_id)); + return (object)$result->hidden(['departments', 'positions'])->toArray(); + } +} diff --git a/src/cfg/Configuration.php b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/config/ConfigurationRewrite.php similarity index 59% rename from src/cfg/Configuration.php rename to demo/thinkphp/backend/app/adminapi/controller/v1/wf/config/ConfigurationRewrite.php index f0d9c5ec63edce2d6b88f75c6ac15967885de799..2bb251cd1c39916fd8a99274fb1429fe2d19aa0f 100644 --- a/src/cfg/Configuration.php +++ b/demo/thinkphp/backend/app/adminapi/controller/v1/wf/config/ConfigurationRewrite.php @@ -1,22 +1,21 @@ adminId() || !$request->adminInfo()) { + throw new AuthException(100100); + } + //非超级管理员进行权限验证 + if ($request->adminInfo()['level'] !== 0) { + /** @var SystemRoleServices $systemRoleServices */ + $systemRoleServices = app()->make(SystemRoleServices::class); + $systemRoleServices->verifyAuth($request); + } + return $next($request); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/middleware/AdminAuthTokenMiddleware.php b/demo/thinkphp/backend/app/adminapi/middleware/AdminAuthTokenMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..862ed7234969c8bbf9b9905ffe1056728c710830 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/middleware/AdminAuthTokenMiddleware.php @@ -0,0 +1,41 @@ +header(Config::get('cookie.token_name', 'Authori-zation')), 'Bearer')); + if (!$token) { + $token = trim(ltrim($request->get('token'))); + } + + /** @var SystemAuthServices $service */ + $service = app()->make(SystemAuthServices::class); + $adminInfo = $service->parseToken($token); + + $request->macro('isAdminLogin', function () use (&$adminInfo) { + return !is_null($adminInfo); + }); + $request->macro('adminId', function () use (&$adminInfo) { + return $adminInfo['id'] ?? ''; + }); + + $request->macro('adminInfo', function () use (&$adminInfo) { + return $adminInfo; + }); + + return $next($request); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/middleware/AdminEditorTokenMiddleware.php b/demo/thinkphp/backend/app/adminapi/middleware/AdminEditorTokenMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..00578fa1b61da948333f28028d5f6cc24278ce3a --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/middleware/AdminEditorTokenMiddleware.php @@ -0,0 +1,36 @@ + +// +---------------------------------------------------------------------- + +namespace app\adminapi\middleware; + + +use app\Request; +use phoenix\interfaces\MiddlewareInterface; +use think\facade\Config; + +/** + * 后台登陆验证中间件 + * Class AdminAuthTokenMiddleware + * @package app\adminapi\middleware + */ +class AdminEditorTokenMiddleware implements MiddlewareInterface +{ + public function handle(Request $request, \Closure $next) + { + $token = CacheService::get(trim($request->get('fileToken'))); + + /** @var SystemFileServices $service */ + $service = app()->make(SystemFileServices::class); + $service->parseToken($token); + + return $next($request); + } +} diff --git a/demo/thinkphp/backend/app/adminapi/middleware/AdminLogMiddleware.php b/demo/thinkphp/backend/app/adminapi/middleware/AdminLogMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..5b5f6dd814344835b40f21eca486496ce56e8aea --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/middleware/AdminLogMiddleware.php @@ -0,0 +1,44 @@ + +// +---------------------------------------------------------------------- + +namespace app\adminapi\middleware; + +use app\Request; +use app\services\system\log\SystemLogServices; + +/** + * 日志中間件 + * Class AdminLogMiddleware + * + * @package app\adminapi\middleware + */ +class AdminLogMiddleware +{ + /** + * @param Request $request + * @param \Closure $next + * + * @return mixed + */ + public function handle(Request $request, \Closure $next): mixed + { + $response = $next($request); + try { + /** @var SystemLogServices $services */ + $services = app()->make(SystemLogServices::class); + $services->recordAdminLog($request->adminId(), $request->adminInfo()['real_name'], $request->adminInfo()['type']); + } catch (\Throwable $e) { + echo($e); + } + return $response; + } + +} diff --git a/demo/thinkphp/backend/app/adminapi/provider.php b/demo/thinkphp/backend/app/adminapi/provider.php new file mode 100644 index 0000000000000000000000000000000000000000..cd02380bf36d7d877f462f3eb4bbc04abe93bc18 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/provider.php @@ -0,0 +1,15 @@ + +// +---------------------------------------------------------------------- + +// 容器Provider定义文件 +return [ + 'think\exception\Handle' => \app\adminapi\AdminApiExceptionHandle::class, +]; diff --git a/demo/thinkphp/backend/app/adminapi/route/file.php b/demo/thinkphp/backend/app/adminapi/route/file.php new file mode 100644 index 0000000000000000000000000000000000000000..a16ef5c0176181f598371b6dae81a41881364917 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/route/file.php @@ -0,0 +1,57 @@ + +// +---------------------------------------------------------------------- +use think\facade\Route; + +/** + * 附件相关路由 + */ +Route::group('file', function () { + //附件列表 + Route::get('file', 'v1.file.SystemAttachment/index')->option(['real_name' => '图片附件列表']); + //删除图片和数据记录 + Route::post('file/delete', 'v1.file.SystemAttachment/delete')->option(['real_name' => '删除图片']); + //移动图片分来表单 + Route::get('file/move', 'v1.file.SystemAttachment/move')->option(['real_name' => '移动图片分类表单']); + //移动图片分类 + Route::put('file/do_move', 'v1.file.SystemAttachment/moveImageCate')->option(['real_name' => '移动图片分类']); + //修改图片名称 + Route::put('file/update/:id', 'v1.file.SystemAttachment/update')->option(['real_name' => '修改图片名称']); + //上传图片 + Route::post('upload/[:upload_type]', 'v1.file.SystemAttachment/upload')->option(['real_name' => '上传图片']); + //附件分类管理资源路由 + Route::resource('category', 'v1.file.SystemAttachmentCategory')->except(['create', 'edit'])->option([ + 'real_name' => [ + 'index' => '获取附件分类管理列表', + 'save' => '保存附件分类管理', + 'update' => '修改附件分类管理', + 'delete' => '删除附件分类管理', + ], + + ]); + //获取上传类型 + Route::get('upload_type', 'v1.file.SystemAttachment/uploadType')->option(['real_name' => '上传类型']); + //分片上传本地视频 + Route::post('video_upload', 'v1.file.SystemAttachment/videoUpload')->option(['real_name' => '分片上传本地视频']); + + //获取扫码上传页面链接以及参数 + Route::get('scan_upload/qrcode', 'v1.file.SystemAttachment/scanUploadQrcode')->option(['real_name' => '扫码上传页面链接']); + //删除扫码上传token + Route::delete('scan_upload/qrcode', 'v1.file.SystemAttachment/removeUploadQrcode')->option(['real_name' => '删除扫码上传页面链接']); + //获取扫码上传的图片数据 + Route::get('scan_upload/image/:scan_token', 'v1.file.SystemAttachment/scanUploadImage')->option(['real_name' => '获取扫码上传的图片数据']); + //网络图片上传 + Route::post('online_upload', 'v1.file.SystemAttachment/onlineUpload')->option(['real_name' => '网络图片上传']); +})->middleware([ + \phoenix\middleware\AllowCrossOriginMiddleware::class, + \app\adminapi\middleware\AdminAuthTokenMiddleware::class, + \app\adminapi\middleware\AdminAuthPermissionMiddleware::class, + \app\adminapi\middleware\AdminLogMiddleware::class, +])->option(['mark' => 'file', 'mark_name' => '上传管理']); diff --git a/demo/thinkphp/backend/app/adminapi/route/route.php b/demo/thinkphp/backend/app/adminapi/route/route.php new file mode 100644 index 0000000000000000000000000000000000000000..bef0dc1ac9248b80463ae12690d436c155394891 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/route/route.php @@ -0,0 +1,37 @@ +name('Test')->option(['real_name' => '测试']); + Route::post('login', 'Login/login')->name('AdminLogin')->option(['real_name' => '下载表备份记录']); + Route::get('login/info', 'Login/info')->option(['real_name' => '登录信息']); + Route::get('captcha_pro', 'Login/captcha')->name('')->option(['real_name' => '获取验证码']); + Route::get('ajcaptcha', 'Login/ajcaptcha')->name('ajcaptcha')->option(['real_name' => '获取验证码']); + Route::post('ajcheck', 'Login/ajcheck')->name('ajcheck')->option(['real_name' => '一次验证']); + Route::get('demo/user/page', 'Login/demoUser')->name('AdminDemoUser')->option(['real_name' => '演示用户列表']); + Route::post('demo/user/act', 'Login/actUser')->name('AdminActUser')->option(['real_name' => '用户扮演']); + Route::post('doc/verification_key', 'Login/verificationKey')->name('AdminActUser')->option(['real_name' => '文档密钥验证']); +})->allowCrossDomain([ + 'Access-Control-Allow-Origin' => '*', + 'Access-Control-Allow-Credentials' => 'true', + 'Access-Control-Max-Age' => 600, + ]); +// ->middleware([\phoenix\middleware\AllowCrossOriginMiddleware::class])->option(['mark' => 'login', 'mark_name' => '登录相关']); + +/** + * miss 路由 + */ +Route::miss(function () { + if (app()->request->isOptions()) { + $header = Config::get('cookie.header'); + $header['Access-Control-Allow-Origin'] = app()->request->header('origin'); + return Response::create('ok')->code(200)->header($header); + } else + return Response::create()->code(404); +}); diff --git a/demo/thinkphp/backend/app/adminapi/route/setting.php b/demo/thinkphp/backend/app/adminapi/route/setting.php new file mode 100644 index 0000000000000000000000000000000000000000..6a2edb75e5980e221490cacd4217b194d22cd319 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/route/setting.php @@ -0,0 +1,464 @@ +name('SystemAdminActAdmin')->option(['real_name' => '扮演用户']); + + //批量删除 + Route::put('admin/batch_remove', 'v1.setting.SystemAdmin/batchUpdate')->name('SystemAdminDeleteAdmin')->option(['real_name' => '批量删除管理员']); + //管理员资源路由 + Route::resource('admin', 'v1.setting.SystemAdmin')->except(['edit', 'create'])->option([ + 'real_name' => [ + 'index' => '获取管理员列表', + 'save' => '保存管理员', + 'read' => '获取详情', + 'update' => '修改管理员', + 'delete' => '删除管理员', + ], + ]); + + //退出登陆 + Route::get('admin/logout', 'v1.setting.SystemAdmin/logout')->name('SystemAdminLogout')->option(['real_name' => '退出登陆']); + //修改状态 + Route::put('set_status/:id/:status', 'v1.setting.SystemAdmin/set_status')->name('SystemAdminSetStatus')->option(['real_name' => '修改管理员状态']); + //获取当前管理员信息 + Route::get('info', 'v1.setting.SystemAdmin/info')->name('SystemAdminInfo')->option(['real_name' => '获取当前管理员信息']); + //修改当前管理员信息 + Route::put('update_admin', 'v1.setting.SystemAdmin/update_admin')->name('SystemAdminUpdateAdmin')->option(['real_name' => '修改当前管理员信息']); + //设置文件管理密码 + Route::put('set_file_password', 'v1.setting.SystemAdmin/set_file_password')->name('SystemAdminSetFilePassword')->option(['real_name' => '设置当前文件管理密码']); + //管理员设置部门职位 + Route::put('set_admin_position/:id', 'v1.setting.SystemAdmin/setPosition')->name('SystemAdminSetPosition')->option(['real_name' => '设置管理员职位']); + })->option(['parent' => 'setting', 'cate_name' => '管理员']); + + /** 权限菜单 */ + Route::group(function () { + //获取菜单 + Route::get('permission', 'v1.setting.SystemMenus/permission')->name('SystemMenusUnique')->option(['real_name' => '获取菜单']); + //获取菜单权限和权限标识 + Route::get('menus/unique', 'v1.setting.SystemMenus/unique')->name('SystemMenusUnique')->option(['real_name' => '获取菜单权限和权限标识']); + //批量保存权限 + Route::post('menus/batch', 'v1.setting.SystemMenus/batchSave')->name('SystemMenusBatchSave')->option(['real_name' => '批量保存权限']); + //权限菜单资源路由 + Route::resource('menus', 'v1.setting.SystemMenus')->option([ + 'real_name' => [ + 'index' => '获取权限菜单列表', + 'create' => '获取权限菜单表单', + 'save' => '保存权限菜单', + 'edit' => '获取修改权限菜单表单', + 'read' => '查看权限菜单信息', + 'update' => '修改权限菜单', + 'delete' => '删除权限菜单', + ], + ]); + //未添加的权限规则列表 + Route::get('ruleList', 'v1.setting.SystemMenus/ruleList')->option(['real_name' => '权限规则列表']); + //权限规则分类 + Route::get('rule_cate', 'v1.setting.SystemMenus/ruleCate')->option(['real_name' => '权限规则分类']); + //修改显示 + Route::put('menus/show/:id', 'v1.setting.SystemMenus/show')->name('SystemMenusShow')->option(['real_name' => '修改权限规格显示状态']); + })->option(['parent' => 'setting', 'cate_name' => '权限菜单']); + + /** 角色管理 */ + Route::group(function () { + //身份列表 +// Route::get('role', 'v1.setting.SystemRole/index')->option(['real_name' => '管理员身份列表']); +// //身份权限列表 +// Route::get('role/create', 'v1.setting.SystemRole/create')->option(['real_name' => '管理员身份权限列表']); +// //编辑详情 +// Route::get('role/:id/edit', 'v1.setting.SystemRole/edit')->option(['real_name' => '编辑管理员详情']); +// //保存新建或编辑 +// Route::post('role/:id', 'v1.setting.SystemRole/save')->option(['real_name' => '新建或编辑管理员']); +// //修改身份状态 +// Route::put('role/set_status/:id/:status', 'v1.setting.SystemRole/set_status')->option(['real_name' => '修改管理员身份状态']); +// //删除身份 +// Route::delete('role/:id', 'v1.setting.SystemRole/delete')->option(['real_name' => '删除管理员身份']); + + //修改状态 + Route::put('role/set_status/:id/:status', 'v1.setting.SystemRole/set_status')->name('SystemAdminSetStatus')->option(['real_name' => '修改角色状态']); + //权限菜单资源路由 + Route::resource('role', 'v1.setting.SystemRole')->except(['edit', 'create'])->option([ + 'real_name' => [ + 'index' => '获取角色列表', + 'save' => '保存角色', + 'read' => '查看角色信息', + 'update' => '修改角色', + 'delete' => '删除角色', + ], + ]); + //角色分配权限 + Route::post('role_menu', 'v1.setting.SystemRoleMenu/save')->name('SystemRoleMenuSave')->option(['real_name' => '角色分配权限']); + //角色分配组织 + Route::post('role_dept', 'v1.setting.SystemRoleDept/save')->name('SystemRoleDeptSave')->option(['real_name' => '角色分配组织']); + //角色分配职位 + Route::post('role_post', 'v1.setting.SystemRolePost/save')->name('SystemRolePostSave')->option(['real_name' => '角色分配职位']); + //获取菜单详情 + Route::get('menu_list', 'v1.setting.SystemRole/menuList')->name('SystemRoleMenuList')->option(['real_name' => '角色分配职位']); + + })->option(['parent' => 'setting', 'cate_name' => '管理员身份']); + + /** 组织管理 */ + Route::group(function () { + //修改状态 + Route::put('dept/set_status/:id/:status', 'v1.setting.SystemDept/set_status')->name('SystemDeptSetStatus')->option(['real_name' => '修改角色状态']); + //组织资源路由 + Route::resource('dept', 'v1.setting.SystemDept')->except(['edit', 'create'])->option([ + 'real_name' => [ + 'index' => '获取列表', + 'save' => '保存组织', + 'read' => '查看详情', + 'update' => '修改组织', + 'delete' => '删除组织', + ], + ]); + })->option(['parent' => 'setting', 'cate_name' => '组织管理']); + + /** 职位管理 */ + Route::group(function () { + //组织资源路由 + Route::resource('post', 'v1.setting.SystemPost')->except(['edit', 'create'])->option([ + 'real_name' => [ + 'index' => '获取列表', + 'save' => '保存职位', + 'read' => '查看详情', + 'update' => '修改职位', + 'delete' => '删除职位', + ], + ]); + })->option(['parent' => 'setting', 'cate_name' => '职位管理']); + +// +// /** 系统配置 */ +// Route::group(function () { +// //配置分类资源路由 +// Route::resource('config_class', 'v1.setting.SystemConfigTab')->except(['read'])->option([ +// 'real_name' => [ +// 'index' => '获取系统配置分类列表', +// 'create' => '获取系统配置分类表单', +// 'save' => '保存系统配置分类', +// 'edit' => '获取修改系统配置分类表单', +// 'update' => '修改系统配置分类', +// 'delete' => '删除系统配置分类', +// ], +// ]); +// //修改配置分类状态 +// Route::put('config_class/set_status/:id/:status', 'v1.setting.SystemConfigTab/set_status')->option(['real_name' => '修改配置分类状态']); +// //配置资源路由 +// Route::resource('config', 'v1.setting.SystemConfig')->except(['read'])->option([ +// 'real_name' => [ +// 'index' => '获取系统配置列表', +// 'create' => '获取系统配置表单', +// 'save' => '保存系统配置', +// 'edit' => '获取修改系统配置表单', +// 'update' => '修改系统配置', +// 'delete' => '删除系统配置', +// ], +// ]); +// //修改配置状态 +// Route::put('config/set_status/:id/:status', 'v1.setting.SystemConfig/set_status')->option(['real_name' => '修改配置状态']); +// //基本配置编辑表单 +// Route::get('config/header_basics', 'v1.setting.SystemConfig/header_basics')->option(['real_name' => '基本配置编辑头部数据']); +// //基本配置编辑表单 +// Route::get('config/edit_basics', 'v1.setting.SystemConfig/edit_basics')->option(['real_name' => '基本配置编辑表单']); +// //基本配置保存数据 +// Route::post('config/save_basics', 'v1.setting.SystemConfig/save_basics')->option(['real_name' => '基本配置保存数据']); +// //基本配置上传文件 +// Route::post('config/upload', 'v1.setting.SystemConfig/file_upload')->option(['real_name' => '基本配置上传文件']); +// //获取单个配置值 +// Route::get('config/get_system/:name', 'v1.setting.SystemConfig/get_system')->option(['real_name' => '基本配置编辑表单']); +// //获取某个分类下的所有配置信息 +// Route::get('config_list/:tabId', 'v1.setting.SystemConfig/get_config_list')->option(['real_name' => '获取某个分类下的所有配置信息']); +// })->option(['parent' => 'setting', 'cate_name' => '系统配置']); +// +// /** 组合数据 */ +// Route::group(function () { +// //组合数据资源路由 +// Route::resource('group', 'v1.setting.SystemGroup')->option([ +// 'real_name' => [ +// 'index' => '获取组合数据列表', +// 'create' => '获取组合数据表单', +// 'save' => '保存组合数据', +// 'edit' => '获取修改组合数据表单', +// 'update' => '修改组合数据', +// 'delete' => '删除组合数据', +// ], +// ]); +// //组合数据全部 +// Route::get('group_all', 'v1.setting.SystemGroup/getGroup')->option(['real_name' => '组合数据全部']); +// //组合数据子数据资源路由 +// Route::resource('group_data', 'v1.setting.SystemGroupData')->except(['read'])->option([ +// 'real_name' => [ +// 'index' => '获取组合数据子数据列表', +// 'create' => '获取组合数据子数据表单', +// 'save' => '保存组合数据子数据', +// 'edit' => '获取修改组合数据子数据表单', +// 'update' => '修改组合数据子数据', +// 'delete' => '删除组合数据子数据', +// ], +// ]); +// //修改数据状态 +// Route::get('group_data/header', 'v1.setting.SystemGroupData/header')->option(['real_name' => '组合数据头部']); +// //修改数据状态 +// Route::put('group_data/set_status/:id/:status', 'v1.setting.SystemGroupData/set_status')->option(['real_name' => '修改组合数据状态']); +// //数据配置保存 +// Route::post('group_data/save_all', 'v1.setting.SystemGroupData/saveAll')->option(['real_name' => '提交数据配置']); +// //获取客服广告 +// Route::get('get_kf_adv', 'v1.setting.SystemGroupData/getKfAdv')->option(['real_name' => '获取客服广告']); +// //设置客服广告 +// Route::post('set_kf_adv', 'v1.setting.SystemGroupData/setKfAdv')->option(['real_name' => '设置客服广告']); +// //签到天数配置资源 +// Route::resource('sign_data', 'v1.setting.SystemGroupData')->except(['read'])->option([ +// 'real_name' => [ +// 'index' => '获取签到天数配置列表', +// 'create' => '获取签到天数配置表单', +// 'save' => '保存签到天数配置', +// 'edit' => '获取修改签到天数配置表单', +// 'update' => '修改签到天数配置', +// 'delete' => '删除签到天数配置', +// ], +// ]); +// //签到数据字段 +// Route::get('sign_data/header', 'v1.setting.SystemGroupData/header')->option(['real_name' => '签到数据头部']); +// //修改签到数据状态 +// Route::put('sign_data/set_status/:id/:status', 'v1.setting.SystemGroupData/set_status')->option(['real_name' => '修改签到数据状态']); +// //订单详情动态图配置资源 +// Route::resource('order_data', 'v1.setting.SystemGroupData')->except(['read'])->option([ +// 'real_name' => [ +// 'index' => '获取订单详情动态图列表', +// 'create' => '获取订单详情动态图表单', +// 'save' => '保存订单详情动态图', +// 'edit' => '获取修改订单详情动态图表单', +// 'update' => '修改订单详情动态图', +// 'delete' => '删除订单详情动态图', +// ], +// ]); +// //订单数据字段 +// Route::get('order_data/header', 'v1.setting.SystemGroupData/header')->option(['real_name' => '订单数据字段']); +// //订单数据状态 +// Route::put('order_data/set_status/:id/:status', 'v1.setting.SystemGroupData/set_status')->option(['real_name' => '订单数据状态']); +// //个人中心菜单配置资源 +// Route::resource('usermenu_data', 'v1.setting.SystemGroupData')->except(['read'])->option([ +// 'real_name' => [ +// 'index' => '获取个人中心菜单列表', +// 'create' => '获取个人中心菜单表单', +// 'save' => '保存个人中心菜单', +// 'edit' => '获取修改个人中心菜单表单', +// 'update' => '修改个人中心菜单', +// 'delete' => '删除个人中心菜单', +// ], +// ]); +// //个人中心菜单数据字段 +// Route::get('usermenu_data/header', 'v1.setting.SystemGroupData/header')->option(['real_name' => '个人中心菜单数据字段']); +// //个人中心菜单数据状态 +// Route::put('usermenu_data/set_status/:id/:status', 'v1.setting.SystemGroupData/set_status')->option(['real_name' => '个人中心菜单数据状态']); +// //分享海报配置资源 +// Route::resource('poster_data', 'v1.setting.SystemGroupData')->except(['read'])->option([ +// 'real_name' => [ +// 'index' => '获取分享海报列表', +// 'create' => '获取分享海报表单', +// 'save' => '保存分享海报', +// 'edit' => '获取修改分享海报表单', +// 'update' => '修改分享海报', +// 'delete' => '删除分享海报', +// ], +// ]); +// //分享海报数据字段 +// Route::get('poster_data/header', 'v1.setting.SystemGroupData/header')->option(['real_name' => '分享海报数据字段']); +// //分享海报数据状态 +// Route::put('poster_data/set_status/:id/:status', 'v1.setting.SystemGroupData/set_status')->option(['real_name' => '分享海报数据状态']); +// //秒杀配置资源 +// Route::resource('seckill_data', 'v1.setting.SystemGroupData')->except(['read'])->option([ +// 'real_name' => [ +// 'index' => '获取分秒杀配置列表', +// 'create' => '获取秒杀配置表单', +// 'save' => '保存秒杀配置', +// 'edit' => '获取修改秒杀配置表单', +// 'update' => '修改秒杀配置', +// 'delete' => '删除秒杀配置', +// ], +// ]); +// //秒杀数据字段 +// Route::get('seckill_data/header', 'v1.setting.SystemGroupData/header')->option(['real_name' => '秒杀数据字段']); +// //秒杀数据状态 +// Route::put('seckill_data/set_status/:id/:status', 'v1.setting.SystemGroupData/set_status')->option(['real_name' => '秒杀数据状态']); +// //获取隐私协议 +// Route::get('get_user_agreement', 'v1.setting.SystemGroupData/getUserAgreement')->option(['real_name' => '获取隐私协议']); +// //设置隐私协议 +// Route::post('set_user_agreement', 'v1.setting.SystemGroupData/setUserAgreement')->option(['real_name' => '设置隐私协议']); +// })->option(['parent' => 'setting', 'cate_name' => '组合数据']); +// +// /** 城市数据 */ +// Route::group(function () { +// //获取城市数据完整列表 +// Route::get('city/full_list', 'v1.setting.SystemCity/fullList')->option(['real_name' => '获取城市数据完整列表']); +// //获取城市数据列表 +// Route::get('city/list/:parent_id', 'v1.setting.SystemCity/index')->option(['real_name' => '获取城市数据列表']); +// //添加城市数据表单 +// Route::get('city/add/:parent_id', 'v1.setting.SystemCity/add')->option(['real_name' => '添加城市数据表单']); +// //修改城市数据表单 +// Route::get('city/:id/edit', 'v1.setting.SystemCity/edit')->option(['real_name' => '修改城市数据表单']); +// //新增/修改城市数据 +// Route::post('city/save', 'v1.setting.SystemCity/save')->option(['real_name' => '新增/修改城市数据']); +// //修改城市数据表单 +// Route::delete('city/del/:city_id', 'v1.setting.SystemCity/delete')->option(['real_name' => '删除城市数据']); +// //清除城市数据缓存 +// Route::get('city/clean_cache', 'v1.setting.SystemCity/clean_cache')->option(['real_name' => '清除城市数据缓存']); +// })->option(['parent' => 'setting', 'cate_name' => '城市数据']); +// +// /** 运费模版 */ +// Route::group(function () { +// //运费模板列表 +// Route::get('shipping_templates/list', 'v1.setting.ShippingTemplates/temp_list')->option(['real_name' => '运费模板列表']); +// //修改运费模板数据 +// Route::get('shipping_templates/:id/edit', 'v1.setting.ShippingTemplates/edit')->option(['real_name' => '修改运费模板数据']); +// //保存新增修改 +// Route::post('shipping_templates/save/:id', 'v1.setting.ShippingTemplates/save')->option(['real_name' => '新增或修改运费模版']); +// //删除运费模板 +// Route::delete('shipping_templates/del/:id', 'v1.setting.ShippingTemplates/delete')->option(['real_name' => '删除运费模板']); +// //城市数据接口 +// Route::get('shipping_templates/city_list', 'v1.setting.ShippingTemplates/city_list')->option(['real_name' => '城市数据接口']); +// })->option(['parent' => 'setting', 'cate_name' => '运费模版']); +// +// /** 系统通知 */ +// Route::group(function () { +// //系统通知列表 +// Route::get('notification/index', 'v1.setting.SystemNotification/index')->option(['real_name' => '系统通知列表']); +// //获取单条数据 +// Route::get('notification/info', 'v1.setting.SystemNotification/info')->option(['real_name' => '获取单条通知数据']); +// //保存通知设置 +// Route::post('notification/save', 'v1.setting.SystemNotification/save')->option(['real_name' => '保存通知设置']); +// //修改消息状态 +// Route::put('notification/set_status/:type/:status/:id', 'v1.setting.SystemNotification/set_status')->option(['real_name' => '修改消息状态']); +// })->option(['parent' => 'setting', 'cate_name' => '系统通知']); +// +// /** 协议版权 */ +// Route::group(function () { +// //协议设置 +// Route::get('get_agreement/:type', 'v1.setting.SystemAgreement/getAgreement')->option(['real_name' => '获取协议内容']); +// Route::post('save_agreement', 'v1.setting.SystemAgreement/saveAgreement')->option(['real_name' => '设置协议内容']); +// //获取版权信息 +// Route::get('get_version', 'v1.setting.SystemConfig/getVersion')->option(['real_name' => '获取版权信息']); +// })->option(['parent' => 'setting', 'cate_name' => '协议版权']); +// +// /** 对外接口 */ +// Route::group(function () { +// //对外接口账号信息 +// Route::get('system_out_account/index', 'v1.setting.SystemOutAccount/index')->option(['real_name' => '对外接口账号信息']); +// //对外接口账号添加 +// Route::post('system_out_account/save', 'v1.setting.SystemOutAccount/save')->option(['real_name' => '对外接口账号添加']); +// //对外接口账号修改 +// Route::post('system_out_account/update/:id', 'v1.setting.SystemOutAccount/update')->option(['real_name' => '对外接口账号修改']); +// //设置账号是否禁用 +// Route::put('system_out_account/set_status/:id/:status', 'v1.setting.SystemOutAccount/set_status')->option(['real_name' => '设置账号是否禁用']); +// //设置账号推送接口 +// Route::put('system_out_account/set_up/:id', 'v1.setting.SystemOutAccount/outSetUpSave')->option(['real_name' => '设置账号推送接口']); +// //删除账号 +// Route::delete('system_out_account/:id', 'v1.setting.SystemOutAccount/delete')->option(['real_name' => '删除账号']); +// //测试获取token接口 +// Route::post('system_out_account/text_out_url', 'v1.setting.SystemOutAccount/textOutUrl')->option(['real_name' => '测试获取token接口']); +// +// //对外接口列表 +// Route::get('system_out_interface/list', 'v1.setting.SystemOutAccount/outInterfaceList')->option(['real_name' => '对外接口列表']); +// //新增修改对外接口 +// Route::post('system_out_interface/save/:id', 'v1.setting.SystemOutAccount/saveInterface')->option(['real_name' => '新增修改对外接口']); +// //对外接口信息 +// Route::get('system_out_interface/info/:id', 'v1.setting.SystemOutAccount/interfaceInfo')->option(['real_name' => '对外接口信息']); +// //修改接口名称 +// Route::put('system_out_interface/edit_name', 'v1.setting.SystemOutAccount/editInterfaceName')->option(['real_name' => '修改接口名称']); +// //删除接口 +// Route::delete('system_out_interface/del/:id', 'v1.setting.SystemOutAccount/delInterface')->option(['real_name' => '删除接口']); +// })->option(['parent' => 'setting', 'cate_name' => '对外接口']); +// + /** 多语言 */ + Route::group(function () { + //语言国家列表 + Route::get('lang_country/list', 'v1.setting.LangCountry/langCountryList')->option(['real_name' => '语言国家列表']); + //语言地区详情 + Route::get('lang_country/:id', 'v1.setting.LangCountry/langCountryDetail')->option(['real_name' => '语言地区详情']); + //保存语言地区 + Route::post('lang_country/save/:id', 'v1.setting.LangCountry/langCountrySave')->option(['real_name' => '保存语言地区']); + //删除语言地区 + Route::delete('lang_country/del/:id', 'v1.setting.LangCountry/langCountryDel')->option(['real_name' => '删除语言地区']); + + //语言类型列表 + Route::get('lang_type/list', 'v1.setting.LangType/langTypeList')->option(['real_name' => '语言类型列表']); + //语言详情 + Route::get('lang_type/get', 'v1.setting.LangType/langTypeDetail')->option(['real_name' => '类型详情']); + //新增语言 + Route::post('lang_type/save/:id', 'v1.setting.LangType/langTypeSave')->option(['real_name' => '新增语言']); + //删除语言 + Route::delete('lang_type/del/:id', 'v1.setting.LangType/langTypeDel')->option(['real_name' => '删除语言']); + //修改语言类型状态 + Route::put('lang_type/status/:id/:status', 'v1.setting.LangType/langTypeStatus')->option(['real_name' => '修改语言类型状态']); + + //获取语言分类 + Route::get('lang_code/type', 'v1.setting.LangCode/langCodeType')->option(['real_name' => '语言类型']); + //获取语言列表 + Route::get('lang_code/list', 'v1.setting.LangCode/langCodeList')->option(['real_name' => '语言列表']); + //获取语言信息 + Route::get('lang_code/info', 'v1.setting.LangCode/langCodeInfo')->option(['real_name' => '语言详情']); + //保存语言 + Route::post('lang_code/save/:id', 'v1.setting.LangCode/langCodeSave')->option(['real_name' => '保存语言']); + //删除语言 + Route::delete('lang_code/del/:id', 'v1.setting.LangCode/langCodeDel')->option(['real_name' => '删除语言']); + //机器翻译 + Route::post('lang_code/translate', 'v1.setting.LangCode/langCodeTranslate')->option(['real_name' => '机器翻译']); + })->option(['parent' => 'setting', 'cate_name' => '语言设置']); + + /** 系统配置 */ + Route::group(function () { + //配置分类资源路由 + Route::resource('config_class', 'v1.setting.SystemConfigTab')->except(['create', 'edit'])->option([ + 'real_name' => [ + 'index' => '获取系统配置分类列表', + 'save' => '保存系统配置分类', + 'update' => '修改系统配置分类', + 'delete' => '删除系统配置分类', + 'read' => '获取系统配置分类详情', + ], + ]); + //修改配置分类状态 + Route::put('config_class/set_status/:id/:status', 'v1.setting.SystemConfigTab/set_status')->option(['real_name' => '修改配置分类状态']); + + //配置资源路由 + Route::resource('config', 'v1.setting.SystemConfig')->except(['create', 'edit'])->option([ + 'real_name' => [ + 'index' => '获取系统配置列表', + 'read' => '获取系统配置详情', + 'save' => '保存系统配置', + 'update' => '修改系统配置', + 'delete' => '删除系统配置', + ], + ]); + //批量删除 + Route::put('config/batch/delete', 'v1.setting.SystemConfig/batch_delete')->option(['real_name' => '批量删除系统配置']); + //修改配置状态 + Route::put('config/set_status/:id/:status', 'v1.setting.SystemConfig/set_status')->option(['real_name' => '修改配置状态']); + //基本配置编辑表单 + Route::get('config/header_basics', 'v1.setting.SystemConfig/header_basics')->option(['real_name' => '基本配置编辑头部数据']); + //基本配置编辑表单 + Route::get('config/edit_basics', 'v1.setting.SystemConfig/edit_basics')->option(['real_name' => '基本配置编辑表单']); + //基本配置保存数据 + Route::post('config/save_basics', 'v1.setting.SystemConfig/save_basics')->option(['real_name' => '基本配置保存数据']); + //基本配置上传文件 + Route::post('config/upload', 'v1.setting.SystemConfig/file_upload')->option(['real_name' => '基本配置上传文件']); + //获取单个配置值 + Route::get('config/get_system/:name', 'v1.setting.SystemConfig/get_system')->option(['real_name' => '基本配置编辑表单']); + //获取某个分类下的所有配置信息 + Route::get('config_list/:tabId', 'v1.setting.SystemConfig/get_config_list')->option(['real_name' => '获取某个分类下的所有配置信息']); + })->option(['parent' => 'setting', 'cate_name' => '系统配置']); + +})->middleware([ + \phoenix\middleware\AllowCrossOriginMiddleware::class, +// \app\adminapi\middleware\AdminAuthTokenMiddleware::class, +// \app\adminapi\middleware\AdminAuthPermissionMiddleware::class, +// \app\adminapi\middleware\AdminLogMiddleware::class, +])->option(['mark' => 'setting', 'mark_name' => '系统设置']); diff --git a/demo/thinkphp/backend/app/adminapi/route/system.php b/demo/thinkphp/backend/app/adminapi/route/system.php new file mode 100644 index 0000000000000000000000000000000000000000..3a09764696f1d59f3bc174d7382a26d053282714 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/route/system.php @@ -0,0 +1,113 @@ +name('SystemLog')->option(['real_name' => '系统日志']); + //系统日志管理员搜索条件 + Route::get('log/search_admin', 'v1.system.SystemLog/search_admin')->option(['real_name' => '系统日志管理员搜索条件']); + //文件校验 + Route::get('file', 'v1.system.SystemFile/index')->name('SystemFile')->option(['real_name' => '文件校验']); + })->option(['parent' => 'system', 'cate_name' => '系统日志']); + + /** 数据清除 */ + Route::group(function () { + //清除缓存 + Route::get('refresh_cache/cache', 'v1.system.Clear/refresh_cache')->option(['real_name' => '清除系统缓存']); + //清除日志 + Route::get('refresh_cache/log', 'v1.system.Clear/delete_log')->option(['real_name' => '清除系统日志']); + })->option(['parent' => 'system', 'cate_name' => '数据清除']); + + /** 数据备份 */ + Route::group(function () { + //数据所有表 + Route::get('backup/select', 'v1.system.SystemDatabackup/index')->option(['real_name' => '数据库所有表']); + //数据备份详情 + Route::get('backup/read', 'v1.system.SystemDatabackup/read')->option(['real_name' => '数据备份详情']); + //更新数据表或者表字段备注 + Route::post('database/update_mark', 'v1.system.SystemDatabackup/updateMark')->option(['real_name' => '更新数据表或者表字段备注']); + //数据备份 优化表 + Route::put('backup/optimize', 'v1.system.SystemDatabackup/optimize')->option(['real_name' => '数据备份优化表']); + //数据备份 修复表 + Route::put('backup/repair', 'v1.system.SystemDatabackup/repair')->option(['real_name' => '数据备份修复表']); + //数据备份 备份表 + Route::put('backup/backup', 'v1.system.SystemDatabackup/backup')->option(['real_name' => '数据备份备份表']); + //备份记录 + Route::get('backup/file_list', 'v1.system.SystemDatabackup/fileList')->option(['real_name' => '数据库备份记录']); + //删除备份记录 + Route::delete('backup/del_file', 'v1.system.SystemDatabackup/delFile')->option(['real_name' => '删除数据库备份记录']); + //导入备份记录表 + Route::post('backup/import', 'v1.system.SystemDatabackup/import')->option(['real_name' => '导入数据库备份记录']); + //下载备份记录表 +// Route::get('backup/download', 'v1.system.SystemDatabackup/downloadFile'); + })->option(['parent' => 'system', 'cate_name' => '数据备份']); + + /** 系统路由 */ + Route::group(function () { + //同步路由接口 + Route::get('route/sync_route/[:appName]', 'v1.system.SystemRoute/syncRoute')->option(['real_name' => '同步路由']); + //获取路由tree行数据 + Route::get('route/tree', 'v1.system.SystemRoute/tree')->option(['real_name' => '获取路由tree']); + //权限路由 + Route::delete('route/:id', 'v1.system.SystemRoute/delete')->option(['real_name' => '删除路由权限']); + //查看路由权限 + Route::get('route/:id', 'v1.system.SystemRoute/read')->option(['real_name' => '查看路由权限']); + //保存路由权限 + Route::post('route/:id', 'v1.system.SystemRoute/save')->option(['real_name' => '保存路由权限']); + //路由分类 + Route::resource('route_cate', 'v1.system.SystemRouteCate')->except(['read'])->option([ + 'real_name' => [ + 'index' => '获取路由分类列表', + 'create' => '获取创建路由分类表单', + 'save' => '保存路由分类', + 'edit' => '获取修改路由分类表单', + 'update' => '修改路由分类', + 'delete' => '删除路由分类', + ], + ]); + })->option(['parent' => 'system', 'cate_name' => '系统路由']); + + /** 定时任务 */ + Route::group(function () { + //定时任务列表 + Route::get('crontab/list', 'v1.system.SystemCrontab/getTimerList')->option(['real_name' => '定时任务列表']); + //定时任务类型 + Route::get('crontab/mark', 'v1.system.SystemCrontab/getMarkList')->option(['real_name' => '定时任务类型']); + //定时任务详情 + Route::get('crontab/info/:id', 'v1.system.SystemCrontab/getTimerInfo')->option(['real_name' => '定时任务详情']); + //定时任务添加编辑 + Route::post('crontab/save', 'v1.system.SystemCrontab/saveTimer')->option(['real_name' => '定时任务添加编辑']); + //删除定时任务 + Route::delete('crontab/del/:id', 'v1.system.SystemCrontab/delTimer')->option(['real_name' => '删除定时任务']); + //定时任务是否开启开关 + Route::get('crontab/set_open/:id/:is_open', 'v1.system.SystemCrontab/setTimerStatus')->option(['real_name' => '定时任务是否开启开关']); + })->option(['parent' => 'system', 'cate_name' => '定时任务']); + + /**字典**/ + Route::group(function () { + Route::get('dict/:name/name', 'v1.system.SystemDict/get')->option(['real_name' => '字典获取']); + Route::put('dict/batch/delete', 'v1.system.SystemDict/batchDelete')->option(['real_name' => '批量删除']); + Route::resource('dict', 'v1.system.SystemDict')->except(['edit', 'create'])->option([ + 'real_name' => [ + 'index' => '获取列表', + 'read' => '字典详情', + 'save' => '保存字典', + 'update' => '更新字典', + 'delete' => '删除字典', + ], + ]); + })->option(['parent' => 'system', 'cate_name' => '字典管理']); + + +})->middleware([ + \phoenix\middleware\AllowCrossOriginMiddleware::class, + \app\adminapi\middleware\AdminAuthTokenMiddleware::class, + \app\adminapi\middleware\AdminAuthPermissionMiddleware::class, + \app\adminapi\middleware\AdminLogMiddleware::class, +])->option(['mark' => 'system', 'mark_name' => '系统维护']);; diff --git a/demo/thinkphp/backend/app/adminapi/route/wf.php b/demo/thinkphp/backend/app/adminapi/route/wf.php new file mode 100644 index 0000000000000000000000000000000000000000..5d87bfc67baae2098ba07804b8767716949ef0d6 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/route/wf.php @@ -0,0 +1,125 @@ + +// +---------------------------------------------------------------------- +use think\facade\Route; + +/** + * 审批流相关路由 + */ +Route::group('wf', function () { + /**流程分类**/ + Route::group(function () { + Route::get('category/select_tree', 'v1.wf.Category/typeTree')->option(['real_name' => '获取分类树']); + Route::get('category/page', 'v1.wf.Category/index')->option(['real_name' => '获取列表']); + Route::get('category/detail', 'v1.wf.Category/read')->option(['real_name' => '获取详情']); + Route::post('category/save', 'v1.wf.Category/save')->option(['real_name' => '保存分类']); + Route::post('category/update', 'v1.wf.Category/update')->option(['real_name' => '保存分类']); + Route::post('category/delete', 'v1.wf.Category/delete')->option(['real_name' => '删除分类']); + Route::post('category/remove', 'v1.wf.Category/batchRemove')->option(['real_name' => '批量删除模型分类']); + })->option(['parent' => 'wf', 'cate_name' => '模型分类']); + + /**流程设计**/ + Route::group(function () { + Route::post('designer/batch_remove', 'v1.wf.Designer/batchRemove')->option(['real_name' => '批量删除模型']); + Route::post('designer/update_define', 'v1.wf.Designer/updateDefine')->option(['real_name' => '保存模型定义']); + Route::post('designer/deploy', 'v1.wf.Designer/deploy')->option(['real_name' => '流程部署']); + Route::post('designer/redeploy', 'v1.wf.Designer/redeploy')->option(['real_name' => '流程重新部署']); + + Route::get('designer/page', 'v1.wf.Designer/index')->option(['real_name' => '获取列表']); + Route::get('designer/detail', 'v1.wf.Designer/read')->option(['real_name' => '获取详情']); + Route::post('designer/save', 'v1.wf.Designer/save')->option(['real_name' => '保存设计']); + Route::post('designer/update', 'v1.wf.Designer/update')->option(['real_name' => '更新设计']); + Route::post('designer/delete', 'v1.wf.Designer/delete')->option(['real_name' => '删除设计']); + Route::post('designer/remove', 'v1.wf.Designer/batchRemove')->option(['real_name' => '批量删除模型设计']); + +// Route::resource('designer', 'v1.wf.Designer')->except(['create', 'edit'])->option([ +// 'real_name' => [ +// 'index' => '获取模型列表', +// 'save' => '保存模型', +// 'update' => '修改模型', +// 'delete' => '删除模型', +// ], +// ]); + })->option(['parent' => 'wf', 'cate_name' => '模型设计']); + + /**流程定义**/ + Route::group(function () { + Route::post('process_define/set_status', 'v1.wf.Define/setStatus')->option(['real_name' => '更新流程状态']); + Route::post('process_define/start_and_execute', 'v1.wf.Define/startAndExecute')->option(['real_name' => '启动流程']); + //流程定义收藏 + Route::get('process_define/favorite/page', 'v1.wf.Define/favoritePage')->option(['real_name' => '收藏列表']); + Route::post('process_define/favorite/setting', 'v1.wf.Define/processFavorite')->option(['real_name' => '流程收藏']); + Route::post('process_define/favorite/remove', 'v1.wf.Define/favoriteDelete')->option(['real_name' => '收藏删除']); + //流程定义 + Route::get('process_define/page', 'v1.wf.Define/index')->option(['real_name' => '获取列表']); + Route::get('process_define/detail', 'v1.wf.Define/read')->option(['real_name' => '获取详情']); + Route::post('process_define/save', 'v1.wf.Define/save')->option(['real_name' => '保存分类']); + Route::post('process_define/update', 'v1.wf.Define/update')->option(['real_name' => '保存分类']); + Route::post('process_define/delete', 'v1.wf.Define/delete')->option(['real_name' => '删除分类']); + Route::post('process_define/remove', 'v1.wf.Define/batchRemove')->option(['real_name' => '批量删除模型分类']); + })->option(['parent' => 'wf', 'cate_name' => '流程定义']); + + /**流程实例**/ + Route::group(function () { + Route::get('process_instance/highlight', 'v1.wf.Instance/highLightData')->option(['real_name' => '获取高亮数据']); + Route::get('process_instance/approval_record', 'v1.wf.Instance/approvalRecord')->option(['real_name' => '获取记录']); + Route::post('process_instance/withdraw', 'v1.wf.Instance/withdraw')->option(['real_name' => '撤回流程']); + Route::post('process_instance/undo', 'v1.wf.Instance/undo')->option(['real_name' => '作废流程']); + Route::post('process_instance/cascade_delete', 'v1.wf.Instance/cascadeDelete')->option(['real_name' => '级联删除流程定义']); + Route::get('process_instance/cc_list', 'v1.wf.Instance/ccList')->option(['real_name' => '获取抄送列表']); + + //我发起的申请 + Route::get('process_instance/management', 'v1.wf.Instance/management')->option(['real_name' => '流程追踪列表']); + Route::get('process_instance/page', 'v1.wf.Instance/index')->option(['real_name' => '获取列表']); + Route::get('process_instance/detail', 'v1.wf.Instance/detail')->option(['real_name' => '获取详情']); + Route::post('process_instance/save', 'v1.wf.Instance/save')->option(['real_name' => '保存实例']); + Route::post('process_instance/update', 'v1.wf.Instance/update')->option(['real_name' => '更新实例']); + Route::post('process_instance/delete', 'v1.wf.Instance/cascadeDelete')->option(['real_name' => '删除实例']); + Route::post('process_instance/remove', 'v1.wf.Instance/batchCascadeDelete')->option(['real_name' => '批量删除模型实例']); + +// Route::resource('process_instance', 'v1.wf.Instance')->except(['create', 'edit'])->option([ +// 'real_name' => [ +// 'index' => '获取实例列表', +// 'save' => '保存实例定义', +// 'update' => '修改流程定义', +// 'delete' => '删除流程定义', +// ], +// ]); + })->option(['parent' => 'wf', 'cate_name' => '流程实例']); + + /**流程任务**/ + Route::group('process_task', function () { + Route::get('done/page', 'v1.wf.Task/doneList')->option(['real_name' => '我的代办']); + Route::get('todo/page', 'v1.wf.Task/todoList')->option(['real_name' => '我的已办']); + Route::get('user', 'v1.wf.Task/userList')->option(['real_name' => '获取用户列表']); + Route::post('execute', 'v1.wf.Task/execute')->option(['real_name' => '执行任务']); + Route::post('backoff', 'v1.wf.Task/backOff')->option(['real_name' => '任务驳回']); + Route::post('surrogate', 'v1.wf.Task/surrogate')->option(['real_name' => '委托代理']); + Route::get('detail', 'v1.wf.Task/detail')->option(['real_name' => '获取任务详情']); + Route::post('jump_able_task_name_list', 'v1.wf.Task/jumpAbleTaskNameList')->option(['real_name' => '获取跳转节点']); + Route::post('listHisByOrderId', 'v1.wf.Task/listHisByOrderId')->option(['real_name' => '获取实例历史记录']); + })->option(['parent' => 'wf', 'cate_name' => '流程任务']); + + Route::group('other', function () { + Route::get('user/list', 'v1.wf.OtherHandle/userList')->option(['real_name' => '审批人列表']); + Route::get('user/info', 'v1.wf.OtherHandle/userInfo')->option(['real_name' => '审批人详情']); + Route::get('assignment_handler', 'v1.wf.OtherHandle/assignmentHandler')->option(['real_name' => '处理类列表']); + Route::get('form/option', 'v1.wf.OtherHandle/formHandler')->option(['real_name' => '获取表单实例url']); + Route::get('candidate_page', 'v1.wf.OtherHandle/candidatePage')->option(['real_name' => '获取候选人列表']); + Route::get('carbon_page', 'v1.wf.OtherHandle/carbonPage')->option(['real_name' => '获取候选人列表']); + + }); + +})->middleware([ + \phoenix\middleware\AllowCrossOriginMiddleware::class, + \app\adminapi\middleware\AdminAuthTokenMiddleware::class, + \app\adminapi\middleware\AdminAuthPermissionMiddleware::class, + \app\adminapi\middleware\AdminLogMiddleware::class, +])->option(['mark' => 'wf', 'mark_name' => '工作流程']); diff --git a/demo/thinkphp/backend/app/adminapi/validate/setting/SystemAdminValidata.php b/demo/thinkphp/backend/app/adminapi/validate/setting/SystemAdminValidata.php new file mode 100644 index 0000000000000000000000000000000000000000..0bcf1842a636251c4f2f2c652c62d0655d7c9cc1 --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/validate/setting/SystemAdminValidata.php @@ -0,0 +1,42 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'account' => ['require', 'alphaDash'], + 'conf_pwd' => 'require', + 'pwd' => 'require', + 'real_name' => 'require', + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = [ + 'account.require' => '400033', + 'account.alphaDash' => '400034', + 'conf_pwd.require' => '400263', + 'pwd.require' => '400256', + 'real_name.require' => '400035', + ]; + + protected $scene = [ + 'get' => ['account', 'pwd'], + 'update' => ['account'], + ]; + +} diff --git a/demo/thinkphp/backend/app/adminapi/validate/setting/SystemUserValidata.php b/demo/thinkphp/backend/app/adminapi/validate/setting/SystemUserValidata.php new file mode 100644 index 0000000000000000000000000000000000000000..30efbfb615b016e67722f91d9d59ca958f2d516c --- /dev/null +++ b/demo/thinkphp/backend/app/adminapi/validate/setting/SystemUserValidata.php @@ -0,0 +1,42 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'account' => ['require', 'alphaDash'], + 'password' => 'require', + 'captcha' => 'require', + 'cid' => 'require', + 'captcha_type' => ['require', 'array'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = [ + 'account.require' => '400033', + 'account.alphaDash' => '400034', + 'conf_pwd.require' => '400263', + 'password.require' => '400256', + 'user_name.require' => '400035', + ]; + + protected $scene = [ + 'get' => ['user_id'], + 'update' => ['account','user_id'], + ]; + +} diff --git a/demo/thinkphp/backend/app/api/common.php b/demo/thinkphp/backend/app/api/common.php new file mode 100644 index 0000000000000000000000000000000000000000..124361568ff89529382ad44b04b53d6fd7543152 --- /dev/null +++ b/demo/thinkphp/backend/app/api/common.php @@ -0,0 +1,2 @@ +fail('您好!这是一个[api]示例应用'); + return '您好!这是一个[api]示例应用'; + } +} diff --git a/demo/thinkphp/backend/app/api/event.php b/demo/thinkphp/backend/app/api/event.php new file mode 100644 index 0000000000000000000000000000000000000000..4eff8908bd643cd6072b9fde6ee38ca4ad6f04ad --- /dev/null +++ b/demo/thinkphp/backend/app/api/event.php @@ -0,0 +1,5 @@ + +// +---------------------------------------------------------------------- +/** + * 创建模块配置 + * php think build model_name + */ +return [ + // 需要自动创建的文件 + '__file__' => ['.htaccess','ExecptionHandle.php'], + // 需要自动创建的目录 + '__dir__' => ['controller/v1','config','lang','validates/login/','route'], + // 需要自动控制器类 + 'controller' => ['Index'], + // 需要自动创建的表单验证 + 'validates' => ['Index'], + // 需要自动创建的路由 + 'route' => ['route'], + // 需要自动创建配置文件 + 'config' => ['route'], + // 需要自动创建的多语言配置文件 + 'lang' => ['zh-CN','en-US'], + // 需要自动创建的模板 +// 'view' => ['index/index'], +]; diff --git a/demo/thinkphp/backend/app/common.php b/demo/thinkphp/backend/app/common.php new file mode 100644 index 0000000000000000000000000000000000000000..7ed9a05c1a00721b4548e1bb77b9474967cedc5d --- /dev/null +++ b/demo/thinkphp/backend/app/common.php @@ -0,0 +1,1095 @@ + +// +---------------------------------------------------------------------- + +// 应用公共文件 +use app\services\pay\PayServices; +use phoenix\services\CacheService; +use phoenix\services\HttpService; +use think\exception\ValidateException; +use phoenix\services\FormBuilder as Form; +use app\services\other\UploadService; +use Fastknife\Service\BlockPuzzleCaptchaService; +use app\services\system\lang\LangTypeServices; +use app\services\system\lang\LangCodeServices; +use app\services\system\lang\LangCountryServices; +use think\facade\Config; +use think\facade\Log; + +if (!function_exists('crmebLog')) { + /** + * CRMEB Log 日志 + * @param $msg + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/03 + */ + function crmebLog($msg) + { + Log::write($msg, 'crmeb'); + } +} + +if (!function_exists('getWorkerManUrl')) { + + /** + * 获取客服数据 + * @return mixed + */ + function getWorkerManUrl() + { + $ws = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'wss://' : 'ws://'; + $host = $_SERVER['HTTP_HOST']; + $data['admin'] = $ws . $host . '/notice'; + $data['chat'] = $ws . $host . '/msg'; + return $data; + } +} +if (!function_exists('object2array')) { + + /** + * 对象转数组 + * @param $object + * @return array|mixed + */ + function object2array($object) + { + $array = []; + if (is_object($object)) { + foreach ($object as $key => $value) { + $array[$key] = $value; + } + } else { + $array = $object; + } + return $array; + } +} + +if (!function_exists('exception')) { + /** + * 抛出异常处理 + * @param $msg + * @param int $code + * @param string $exception + * @throws \think\Exception + */ + function exception($msg, $code = 0, $exception = '') + { + $e = $exception ?: '\think\Exception'; + throw new $e($msg, $code); + } +} + +if (!function_exists('sys_config')) { + /** + * 获取系统单个配置 + * @param string $name + * @param string $default + * @return string + */ + function sys_config(string $name, string|int $default = '') + { + if (empty($name)) + return $default; + $sysConfig = app('sysConfig')->get($name); + if (is_array($sysConfig)) { + foreach ($sysConfig as &$item) { + if (strpos($item, '/uploads/system/') !== false || strpos($item, '/statics/system_images/') !== false) $item = set_file_url($item); + } + } else { + if (strpos($sysConfig, '/uploads/system/') !== false || strpos($sysConfig, '/statics/system_images/') !== false) $sysConfig = set_file_url($sysConfig); + } + $config = is_array($sysConfig) ? $sysConfig : trim($sysConfig); + if ($config === '' || $config === false) { + return $default; + } else { + return $config; + } + } +} + +if (!function_exists('sys_data')) { + /** + * 获取系统单个配置 + * @param string $name + * @return string + */ + function sys_data(string $name, int $limit = 0) + { + return app('sysGroupData')->getData($name, $limit); + } +} + +if (!function_exists('filter_emoji')) { + + // 过滤掉emoji表情 + function filter_emoji($str) + { + $str = preg_replace_callback( //执行一个正则表达式搜索并且使用一个回调进行替换 + '/./u', + function (array $match) { + return strlen($match[0]) >= 4 ? '' : $match[0]; + }, + $str); + return $str; + } +} + + +if (!function_exists('str_middle_replace')) { + /** TODO 系统未使用 + * @param string $string 需要替换的字符串 + * @param int $start 开始的保留几位 + * @param int $end 最后保留几位 + * @return string + */ + function str_middle_replace($string, $start, $end) + { + $strlen = mb_strlen($string, 'UTF-8');//获取字符串长度 + $firstStr = mb_substr($string, 0, $start, 'UTF-8');//获取第一位 + $lastStr = mb_substr($string, -1, $end, 'UTF-8');//获取最后一位 + return $strlen == 2 ? $firstStr . str_repeat('*', mb_strlen($string, 'utf-8') - 1) : $firstStr . str_repeat("*", $strlen - 2) . $lastStr; + + } +} + + +if (!function_exists('sensitive_words_filter')) { + + /** + * 敏感词过滤 + * + * @param string + * @return string + */ + function sensitive_words_filter($str) + { + if (!$str) return ''; + $file = app()->getAppPath() . 'public/statics/plug/censorwords/CensorWords'; + $words = file($file); + foreach ($words as $word) { + $word = str_replace(array("\r\n", "\r", "\n", "/", "<", ">", "=", " "), '', $word); + if (!$word) continue; + + $ret = preg_match("/$word/", $str, $match); + if ($ret) { + return $match[0]; + } + } + return ''; + } +} + +if (!function_exists('make_path')) { + + /** + * 上传路径转化,默认路径 + * + * @param $path + * @param int $type + * @param bool $force + * + * @return string + * @throws \Exception + */ + function make_path($path, int $type = 2, bool $force = false): string + { + $path = DS . ltrim(rtrim($path)); + switch ($type) { + case 1: + $path .= DS . date('Y'); + break; + case 2: + $path .= DS . date('Y') . DS . date('m'); + break; + case 3: + $path .= DS . date('Y') . DS . date('m') . DS . date('d'); + break; + } + try { + if (is_dir(app()->getRootPath() . 'public' . DS . 'uploads' . $path) || mkdir(app()->getRootPath() . 'public' . DS . 'uploads' . $path, 0777, true)) { + return trim(str_replace(DS, '/', $path), '.'); + } else return ''; + } catch (\Exception $e) { + if ($force) + throw new \Exception($e->getMessage()); + return '无法创建文件夹,请检查您的上传目录权限:' . app()->getRootPath() . 'public' . DS . 'uploads' . DS . 'attach' . DS; + } + + } +} + + +if (!function_exists('curl_file_exist')) { + /** + * CURL 检测远程文件是否在 + * @param $url + * @return bool + */ + function curl_file_exist($url) + { + $ch = curl_init(); + try { + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); + $contents = curl_exec($ch); + if (preg_match("/404/", $contents)) return false; + if (preg_match("/403/", $contents)) return false; + return true; + } catch (\Exception $e) { + return false; + } + } +} +if (!function_exists('set_file_url')) { + /** + * 设置附加路径 + * @param $url + * @return bool + */ + function set_file_url($image, $siteUrl = '') + { + if (!strlen(trim($siteUrl))) $siteUrl = sys_config('site_url'); + if (!$image) return $image; + if (is_array($image)) { + foreach ($image as &$item) { + $domainTop1 = substr($item, 0, 4); + $domainTop2 = substr($item, 0, 2); + if ($domainTop1 != 'http' && $domainTop2 != '//') + $item = $siteUrl . str_replace('\\', '/', $item); + } + } else { + $domainTop1 = substr($image, 0, 4); + $domainTop2 = substr($image, 0, 2); + if ($domainTop1 != 'http' && $domainTop2 != '//') + $image = $siteUrl . str_replace('\\', '/', $image); + } + return $image; + } +} + +if (!function_exists('set_http_type')) { + /** + * 修改 https 和 http + * @param $url $url 域名 + * @param int $type 0 返回https 1 返回 http + * @return string + */ + function set_http_type($url, $type = 0) + { + $domainTop = substr($url, 0, 5); + if ($type) { + if ($domainTop == 'https') $url = 'http' . substr($url, 5, strlen($url)); + } else { + if ($domainTop != 'https') $url = 'https:' . substr($url, 5, strlen($url)); + } + return $url; + } + +} + +if (!function_exists('check_card')) { + /** + * 身份证验证 + * @param $card + * @return bool + */ + function check_card($card) + { + $city = [11 => "北京", 12 => "天津", 13 => "河北", 14 => "山西", 15 => "内蒙古", 21 => "辽宁", 22 => "吉林", 23 => "黑龙江 ", 31 => "上海", 32 => "江苏", 33 => "浙江", 34 => "安徽", 35 => "福建", 36 => "江西", 37 => "山东", 41 => "河南", 42 => "湖北 ", 43 => "湖南", 44 => "广东", 45 => "广西", 46 => "海南", 50 => "重庆", 51 => "四川", 52 => "贵州", 53 => "云南", 54 => "西藏 ", 61 => "陕西", 62 => "甘肃", 63 => "青海", 64 => "宁夏", 65 => "新疆", 71 => "台湾", 81 => "香港", 82 => "澳门", 91 => "国外 "]; + $tip = ""; + $match = "/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/"; + $pass = true; + if (!$card || !preg_match($match, $card)) { + //身份证格式错误 + $pass = false; + } else if (!$city[substr($card, 0, 2)]) { + //地址错误 + $pass = false; + } else { + //18位身份证需要验证最后一位校验位 + if (strlen($card) == 18) { + $card = str_split($card); + //∑(ai×Wi)(mod 11) + //加权因子 + $factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; + //校验位 + $parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]; + $sum = 0; + $ai = 0; + $wi = 0; + for ($i = 0; $i < 17; $i++) { + $ai = $card[$i]; + $wi = $factor[$i]; + $sum += $ai * $wi; + } + $last = $parity[$sum % 11]; + if ($parity[$sum % 11] != $card[17]) { + // $tip = "校验位错误"; + $pass = false; + } + } else { + $pass = false; + } + } + if (!$pass) return false;/* 身份证格式错误*/ + return true;/* 身份证格式正确*/ + } +} +if (!function_exists('check_link')) { + /** + * 地址验证 + * @param string $link + * @return false|int + */ + function check_link(string $link) + { + return preg_match("/^(http|https|ftp):\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+[\/=\?%\-&_~`@[\]\’:+!]*([^<>\”])*$/", $link); + } +} +if (!function_exists('check_phone')) { + /** + * 手机号验证 + * @param $phone + * @return false|int + */ + function check_phone($phone) + { + return preg_match("/^1[3456789]\d{9}$/", $phone); + } +} +if (!function_exists('anonymity')) { + /** + * 匿名处理处理用户昵称 + * @param $name + * @return string + */ + function anonymity($name, $type = 1) + { + if ($type == 1) { + return mb_substr($name, 0, 1, 'UTF-8') . '**' . mb_substr($name, -1, 1, 'UTF-8'); + } else { + $strLen = mb_strlen($name, 'UTF-8'); + $min = 3; + if ($strLen <= 1) + return '*'; + if ($strLen <= $min) + return mb_substr($name, 0, 1, 'UTF-8') . str_repeat('*', $min - 1); + else + return mb_substr($name, 0, 1, 'UTF-8') . str_repeat('*', $strLen - 1) . mb_substr($name, -1, 1, 'UTF-8'); + } + } +} +if (!function_exists('sort_list_tier')) { + /** + * 分级排序 + * @param $data + * @param int $pid + * @param string $field + * @param string $pk + * @param string $html + * @param int $level + * @param bool $clear + * @return array + */ + function sort_list_tier($data, $pid = 0, $field = 'pid', $pk = 'id', $html = '|-----', $level = 1, $clear = true) + { + static $list = []; + if ($clear) $list = []; + foreach ($data as $k => $res) { + if ($res[$field] == $pid) { + $res['html'] = str_repeat($html, $level); + $list[] = $res; + unset($data[$k]); + sort_list_tier($data, $res[$pk], $field, $pk, $html, $level + 1, false); + } + } + return $list; + } +} + +if (!function_exists('sort_city_tier')) { + /** + * 城市数据整理 + * @param $data + * @param int $pid + * @param string $field + * @param string $pk + * @param string $html + * @param int $level + * @param bool $clear + * @return array + */ + function sort_city_tier($data, $pid = 0, $navList = []) + { + foreach ($data as $k => $menu) { + if ($menu['parent_id'] == $pid) { + unset($menu['parent_id']); + unset($data[$k]); + $menu['c'] = sort_city_tier($data, $menu['v']); + $navList[] = $menu; + } + } + return $navList; + } +} + +if (!function_exists('time_tran')) { + /** + * 时间戳人性化转化 + * @param $time + * @return string + */ + function time_tran($time) + { + $t = time() - $time; + $f = array( + '31536000' => '年', + '2592000' => '个月', + '604800' => '星期', + '86400' => '天', + '3600' => '小时', + '60' => '分钟', + '1' => '秒' + ); + foreach ($f as $k => $v) { + if (0 != $c = floor($t / (int)$k)) { + return $c . $v . '前'; + } + } + } +} + +if (!function_exists('url_to_path')) { + /** + * url转换路径 + * @param $url + * @return string + */ + function url_to_path($url) + { + $path = trim(str_replace('/', DS, $url), DS); + if (0 !== strripos($path, 'public')) + $path = 'public' . DS . $path; + return app()->getRootPath() . $path; + } +} + +if (!function_exists('path_to_url')) { + /** + * 路径转url路径 + * @param $path + * @return string + */ + function path_to_url($path) + { + return trim(str_replace(DS, '/', $path), '.'); + } +} + +if (!function_exists('image_to_base64')) { + /** + * 获取图片转为base64 + * @param string $avatar + * @return bool|string + */ + function image_to_base64($avatar = '', $timeout = 9) + { + $avatar = str_replace('https', 'http', $avatar); + try { + $url = parse_url($avatar); + $url = $url['host']; + $header = [ + 'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:45.0) Gecko/20100101 Firefox/45.0', + 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3', + 'Accept-Encoding: gzip, deflate, br', + 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', + 'Host:' . $url + ]; + $dir = pathinfo($url); + $host = $dir['dirname']; + $refer = $host . '/'; + $curl = curl_init(); + curl_setopt($curl, CURLOPT_REFERER, $refer); + curl_setopt($curl, CURLOPT_URL, $avatar); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($curl, CURLOPT_ENCODING, 'gzip'); + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $timeout); + curl_setopt($curl, CURLOPT_HTTPHEADER, $header); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); + $data = curl_exec($curl); + $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); + curl_close($curl); + if ($code == 200) { + return "data:image/jpeg;base64," . base64_encode($data); + } else { + return false; + } + } catch (\Exception $e) { + return false; + } + } +} + +if (!function_exists('put_image')) { + /** + * 获取图片转为base64 + * @param string $avatar + * @return bool|string + */ + function put_image($url, $filename = '') + { + + if ($url == '') { + return false; + } + try { + if ($filename == '') { + + $ext = pathinfo($url); + if ($ext['extension'] != "jpg" && $ext['extension'] != "png" && $ext['extension'] != "jpeg") { + return false; + } + $filename = time() . "." . $ext['extension']; + } + + //文件保存路径 + ob_start(); + $url = str_replace('phar://', '', $url); + readfile($url); + $img = ob_get_contents(); + ob_end_clean(); + $path = 'uploads/qrcode'; + $fp2 = fopen($path . '/' . $filename, 'a'); + fwrite($fp2, $img); + fclose($fp2); + return $path . '/' . $filename; + } catch (\Exception $e) { + return false; + } + } +} + + +if (!function_exists('debug_file')) { + /** + * 文件调试 + * @param $content + */ + function debug_file($content, string $fileName = 'error', string $ext = 'txt') + { + $msg = '[' . date('Y-m-d H:i:s', time()) . '] [ DEBUG ] '; + $pach = app()->getRuntimePath(); + file_put_contents($pach . $fileName . '.' . $ext, $msg . print_r($content, true) . "\r\n", FILE_APPEND); + } +} + + +if (!function_exists('sql_filter')) { + /** + * sql 参数过滤 + * @param string $str + * @return mixed + */ + function sql_filter(string $str) + { + $filter = ['select ', 'insert ', 'update ', 'delete ', 'drop', 'truncate ', 'declare', 'xp_cmdshell', '/add', ' or ', 'exec', 'create', 'chr', 'mid', ' and ', 'execute']; + $toupper = array_map(function ($str) { + return strtoupper($str); + }, $filter); + return str_replace(array_merge($filter, $toupper, ['%20']), '', $str); + } +} + +if (!function_exists('is_brokerage_statu')) { + + /** + * 是否能成为推广人 + * @param float $price + * @return bool + */ + function is_brokerage_statu(float $price) + { + if (!sys_config('brokerage_func_status')) { + return false; + } + $storeBrokerageStatus = sys_config('store_brokerage_statu', 1); + if ($storeBrokerageStatus == 1) { + return false; + } else if ($storeBrokerageStatus == 2) { + return false; + } else { + $storeBrokeragePrice = sys_config('store_brokerage_price', 0); + return $price >= $storeBrokeragePrice; + } + } +} + +if (!function_exists('array_unique_fb')) { + /** + * 二维数组去掉重复值 + * @param $array + * @return array + */ + function array_unique_fb($array) + { + $out = array(); + foreach ($array as $key => $value) { + if (!in_array($value, $out)) { + $out[$key] = $value; + } + } + $out = array_values($out); + return $out; + } +} + + +if (!function_exists('get_phoenix_version')) { + /** + * 获取系统版本号 + * @param string $default + * @return string + */ + function get_phoenix_version(string $default = 'v1.0.0'): string + { + try { + $version = parse_ini_file(app()->getRootPath() . '.version'); + return $version['version'] ?? $default; + } catch (\Throwable $e) { + return $default; + } + } +} + +if (!function_exists('get_file_link')) { + /** + * 获取文件带域名的完整路径 + * @param string $link + * @return string + */ + function get_file_link(string $link) + { + if (!$link) { + return ''; + } + if (strstr('http', $link) === false) { + return app()->request->domain() . $link; + } else { + return $link; + } + } +} + +if (!function_exists('tidy_tree')) { + /** + * 格式化分类 + * @param $menusList + * @param int $pid + * @param array $navList + * @return array + */ + function tidy_tree($menusList, $pid = 0, $navList = []) + { + foreach ($menusList as $k => $menu) { + if ($menu['parent_id'] == $pid) { + unset($menusList[$k]); + $menu['children'] = tidy_tree($menusList, $menu['id']); + if ($menu['children']) $menu['expand'] = true; + $navList[] = $menu; + } + } + return $navList; + } +} + +if (!function_exists('create_form')) { + /** + * 表单生成方法 + * @param string $title + * @param array $field + * @param $url + * @param string $method + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + function create_form(string $title, array $field, $url, string $method = 'POST') + { + $form = Form::createForm((string)$url);//提交地址 + $form->setMethod($method);//提交方式 + $form->setRule($field);//表单字段 + $form->setTitle($title);//表单标题 + $rules = $form->formRule(); + $title = $form->getTitle(); + $action = $form->getAction(); + $method = $form->getMethod(); + $info = ''; + $status = true; + $methodData = ['POST', 'PUT', 'GET', 'DELETE']; + if (!in_array(strtoupper($method), $methodData)) { + throw new ValidateException('请求方式有误'); + } + return compact('rules', 'title', 'action', 'method', 'info', 'status'); + } +} + +if (!function_exists('msectime')) { + /** + * 获取毫秒数 + * @return float + */ + function msectime() + { + list($msec, $sec) = explode(' ', microtime()); + return (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000); + } +} + + +if (!function_exists('array_bc_sum')) { + /** + * 获取一维数组的总合高精度 + * @param array $data + * @return string + */ + function array_bc_sum(array $data) + { + $sum = '0'; + foreach ($data as $item) { + $sum = bcadd($sum, (string)$item, 2); + } + return $sum; + } +} + +if (!function_exists('get_tree_children')) { + /** + * tree 子菜单 + * @param array $data 数据 + * @param string $childrenname 子数据名 + * @param string $keyName 数据key名 + * @param string $pidName 数据上级key名 + * @return array + */ + function get_tree_children(array $data, string $childrenname = 'children', string $keyName = 'id', string $pidName = 'pid'): array + { + $list = array(); + foreach ($data as $value) { + $list[$value[$keyName]] = $value; + } + static $tree = array(); //格式化好的树 + foreach ($list as $item) { + if (isset($list[$item[$pidName]])) { + $list[$item[$pidName]][$childrenname][] = &$list[$item[$keyName]]; + } else { + $tree[] = &$list[$item[$keyName]]; + } + } + return $tree; + } +} + +if (!function_exists('get_tree_children_value')) { + + function get_tree_children_value(array $data, $value, string $childrenname = 'children', string $keyName = 'id') + { + static $childrenValue = []; + foreach ($data as $item) { + $childrenData = $item[$childrenname] ?? []; + if (count($childrenData)) { + return get_tree_children_value($childrenData, $childrenname, $keyName); + } else { + if ($item[$keyName] == $value) { + $childrenValue[] = $item['value']; + } + } + } + return $childrenValue; + } +} + + +if (!function_exists('get_tree_value')) { + /** + * 获取 + * @param array $data + * @param int|string $value + * @return array + */ + function get_tree_value(array $data, $value) + { + static $childrenValue = []; + foreach ($data as &$item) { + if ($item['value'] == $value) { + $childrenValue[] = $item['value']; + if ($item['pid']) { + $value = $item['pid']; + unset($item); + return get_tree_value($data, $value); + } + } + } + return $childrenValue; + } +} + +if (!function_exists('get_image_thumb')) { + /** + * 获取缩略图 + * @param $filePath + * @param string $type all|big|mid|small + * @param bool $is_remote_down + * @return mixed|string|string[] + */ + function get_image_thumb($filePath, string $type = 'all', bool $is_remote_down = false) + { + if (!$filePath || !is_string($filePath) || strpos($filePath, '?') !== false) return $filePath; + try { + $upload = UploadService::getOssInit($filePath, $is_remote_down); + $fileArr = explode('/', $filePath); + $data = $upload->thumb($filePath, end($fileArr), $type); + $image = $type == 'all' ? $data : $data[$type] ?? $filePath; + } catch (\Throwable $e) { + $image = $filePath; + \think\facade\Log::error('获取缩略图失败,原因:' . $e->getMessage() . '----' . $e->getFile() . '----' . $e->getLine() . '----' . $filePath); + } + $data = parse_url($image); + if (!isset($data['host']) && (substr($image, 0, 2) == './' || substr($image, 0, 1) == '/')) {//不是完整地址 + $image = sys_config('site_url') . $image; + } + //请求是https 图片是http 需要改变图片地址 + if (strpos(request()->domain(), 'https:') !== false && strpos($image, 'https:') === false) { + $image = str_replace('http:', 'https:', $image); + } + return $image; + } +} + +if (!function_exists('get_thumb_water')) { + /** + * 处理数组获取缩略图、水印 + * @param $list + * @param string $type + * @param array|string[] $field 1、['image','images'] type 取值参数:type 2、['small'=>'image','mid'=>'images'] type 取field数组的key + * @param bool $is_remote_down + * @return array|mixed|string|string[] + */ + function get_thumb_water($list, string $type = 'small', array $field = ['image'], bool $is_remote_down = false) + { + if (!$list || !$field) return $list; + $baseType = $type; + $data = $list; + if (is_string($list)) { + $field = [$type => 'image']; + $data = ['image' => $list]; + } + if (is_array($data)) { + foreach ($field as $type => $key) { + if (is_integer($type)) {//索引数组,默认type + $type = $baseType; + } + //一维数组 + if (isset($data[$key])) { + if (is_array($data[$key])) { + $path_data = []; + foreach ($data[$key] as $k => $path) { + $path_data[] = get_image_thumb($path, $type, $is_remote_down); + } + $data[$key] = $path_data; + } else { + $data[$key] = get_image_thumb($data[$key], $type, $is_remote_down); + } + } else { + foreach ($data as &$item) { + if (!isset($item[$key])) + continue; + if (is_array($item[$key])) { + $path_data = []; + foreach ($item[$key] as $k => $path) { + $path_data[] = get_image_thumb($path, $type, $is_remote_down); + } + $item[$key] = $path_data; + } else { + $item[$key] = get_image_thumb($item[$key], $type, $is_remote_down); + } + } + } + } + } + return is_string($list) ? ($data['image'] ?? '') : $data; + } +} + + +if (!function_exists('getLang')) { + /** + * 多语言 + * @param $code + * @param array $replace + * @return array|string|string[] + */ + function getLang($code, array $replace = []): array|string + { + //确保获取语言的时候不会报错 + try { + /** @var LangCountryServices $langCountryServices */ + $langCountryServices = app()->make(LangCountryServices::class); + /** @var LangTypeServices $langTypeServices */ + $langTypeServices = app()->make(LangTypeServices::class); + /** @var LangCodeServices $langCodeServices */ + $langCodeServices = app()->make(LangCodeServices::class); + $request = app()->request; + //获取接口传入的语言类型 + if (!$range = $request->header('cb-lang')) { + //没有传入则使用系统默认语言显示 + $range = $langTypeServices->cacheDriver()->remember('range_name', function () use ($langTypeServices) { + return $langTypeServices->value(['is_default' => 1], 'file_name'); + }); + + if (!$range) { + //系统没有设置默认语言的话,根据浏览器语言显示,如果浏览器语言在库中找不到,则使用简体中文 + if ($request->header('accept-language') !== null) { + $range = explode(',', $request->header('accept-language'))[0]; + } else { + $range = 'zh-CN'; + } + } + } + + // 获取type_id + $typeId = $langCountryServices->cacheDriver()->remember('type_id_' . $range, function () use ($langCountryServices, $range) { + return $langCountryServices->value(['code' => $range], 'type_id') ?: 1; + }, 3600); + + // 获取类型 + $langData = CacheService::remember('lang_type_data', function () use ($langTypeServices) { + return $langTypeServices->getColumn(['status' => 1, 'delete_time' => null], 'file_name', 'id'); + }, 3600); + + // 获取缓存key + $langStr = 'lang_' . str_replace('-', '_', $langData[$typeId]); + + //读取当前语言的语言包 + $lang = CacheService::remember($langStr, function () use ($typeId, $range, $langCodeServices) { + return $langCodeServices->getColumn(['type_id' => $typeId, 'is_admin' => 1], 'lang_explain', 'code'); + }, 3600); + + //获取返回文字 + $message = (string)($lang[$code] ?? 'Code Error'); + + //替换变量 + if (!empty($replace) && is_array($replace)) { + // 关联索引解析 + $key = array_keys($replace); + foreach ($key as &$v) { + $v = "{:{$v}}"; + } + $message = str_replace($key, $replace, $message); + } + + return $message; + } catch (\Throwable $e) { + Log::error('获取语言code:' . $code . '发成错误,错误原因是:' . json_encode([ + 'file' => $e->getFile(), + 'message' => $e->getMessage(), + 'line' => $e->getLine() + ])); + return $code; + } + } +} + +if (!function_exists('aj_captcha_check_one')) { + /** + * 验证滑块1次验证 + * @param string $token + * @param string $pointJson + * @return bool + */ + function aj_captcha_check_one(string $captchaType, string $token, string $pointJson) + { + aj_get_serevice($captchaType)->check($token, $pointJson); + return true; + } +} + +if (!function_exists('aj_captcha_check_two')) { + /** + * 验证滑块2次验证 + * @param string $token + * @param string $pointJson + * @return bool + */ + function aj_captcha_check_two(string $captchaType, string $captchaVerification) + { + aj_get_serevice($captchaType)->verificationByEncryptCode($captchaVerification); + return true; + } +} + + +if (!function_exists('aj_captcha_create')) { + /** + * 创建验证码 + * @return array + */ + function aj_captcha_create(string $captchaType) + { + return aj_get_serevice($captchaType)->get(); + } +} + +if (!function_exists('aj_get_serevice')) { + + /** + * @param string $captchaType + * @return ClickWordCaptchaService|BlockPuzzleCaptchaService + */ + function aj_get_serevice(string $captchaType) + { + $config = Config::get('ajcaptcha'); + switch ($captchaType) { + case "clickWord": + $service = new ClickWordCaptchaService($config); + break; + case "blockPuzzle": + $service = new BlockPuzzleCaptchaService($config); + break; + default: + throw new ValidateException('captchaType参数不正确!'); + } + return $service; + } +} + +if (!function_exists('out_push')) { + /** + * 默认数据推送 + * @param string $pushUrl + * @param array $data + * @param string $tip + * @return bool + */ + function out_push(string $pushUrl, array $data, string $tip = ''): bool + { + $param = json_encode($data, JSON_UNESCAPED_UNICODE); + $res = HttpService::postRequest($pushUrl, $param, ['Content-Type:application/json', 'Content-Length:' . strlen($param)]); + $res = $res ? json_decode($res, true) : []; + if (!$res || !isset($res['code']) || $res['code'] != 0) { + \think\facade\Log::error(['msg' => $tip . '推送失败', 'data' => $res]); + return false; + } + return true; + } +} diff --git a/demo/thinkphp/backend/app/dao/BaseDao.php b/demo/thinkphp/backend/app/dao/BaseDao.php new file mode 100644 index 0000000000000000000000000000000000000000..e082363d4a5ffb2cbf4886b69ea949787a2772f8 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/BaseDao.php @@ -0,0 +1,658 @@ +search($where, $search)->count(); + } + + /** + * 获取某些条件数据 + * + * @param array $where + * @param string $field + * @param int $page + * @param int $limit + * @param string $order + * @param bool $search + * + * @return \think\Collection + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function selectList(array $where, string $field = '*', int $page = 0, int $limit = 0, string $order = '', array $with = [], bool $search = false) + { + return $this->selectModel($where, $field, $page, $limit, $order, $with, $search)->select(); + } + + /** + * @param array $where + * @param string $field + * @param int $page + * @param int $limit + * @param string $order + * @param array $with + * @param bool $search + * + * @return BaseModel + * @throws \ReflectionException + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/14 + */ + public function selectModel(array $where, string $field = '*', int $page = 0, int $limit = 0, string $order = '', array $with = [], bool $search = false) + { + if ($search) { + $model = $this->search($where); + } else { + $model = $this->getModel()->where($where); + } + return $model->field($field)->when($page && $limit, function ($query) use ($page, $limit) { + $query->page($page, $limit); + })->when($order !== '', function ($query) use ($order) { + $query->order($order); + })->when($with, function ($query) use ($with) { + $query->with($with); + }); + } + + /** + * 获取某些条件总数 + * + * @param array $where + * + * @return int + */ + public function getCount(array $where) + { + return $this->getModel()->where($where)->count(); + } + + /** + * 获取某些条件去重总数 + * + * @param array $where + * @param $field + * @param bool $search + * + * @return int|mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getDistinctCount(array $where, $field, bool $search = true) + { + if ($search) { + return $this->search($where)->field('COUNT(distinct(' . $field . ')) as count')->select()->toArray()[0]['count'] ?? 0; + } else { + return $this->getModel()->where($where)->field('COUNT(distinct(' . $field . ')) as count')->select()->toArray()[0]['count'] ?? 0; + } + } + + /** + * 获取模型 + * + * @return BaseModel + */ + protected function getModel() + { + return app()->make($this->setModel()); + } + + /** + * 获取主键 + * + * @return array|string + */ + protected function getPk() + { + return $this->getModel()->getPk(); + } + + /** + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/8 + */ + public function getTableName() + { + return $this->getModel()->getName(); + } + + /** + * 获取一条数据 + * + * @param $id + * @param array|null $field + * @param array|null $with + * @param string $order + * + * @return array|Model|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function get($id, ?array $field = [], ?array $with = [], string $order = ''):mixed + { + if (is_array($id)) { + $where = $id; + } else { + $where = [$this->getPk() => $id]; + } + return $this->getModel()->where($where)->when(count($with), function ($query) use ($with) { + $query->with($with); + })->when($order !== '', function ($query) use ($order) { + $query->order($order); + })->field($field ?? ['*'])->find(); + } + + /** + * 查询一条数据是否存在 + * + * @param $map + * @param string $field + * + * @return bool 是否存在 + */ + public function be($map, string $field = '') + { + if (!is_array($map) && empty($field)) $field = $this->getPk(); + $map = !is_array($map) ? [$field => $map] : $map; + return 0 < $this->getModel()->where($map)->count(); + } + + /** + * 根据条件获取一条数据 + * + * @param array $where + * @param string|null $field + * @param array $with + * + * @return array|Model|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getOne(array $where, ?string $field = '*', array $with = []) + { + $field = explode(',', $field); + return $this->get($where, $field, $with); + } + + /** + * 获取单个字段值 + * + * @param $where + * @param string|null $field + * + * @return mixed + */ + public function value($where, ?string $field = '') + { + $pk = $this->getPk(); + return $this->search($this->setWhere($where))->value($field ?: $pk); + } + + /** + * 获取某个字段数组 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + */ + public function getColumn(array $where, string $field, string $key = '') + { + return $this->getModel()->where($where)->column($field, $key); + } + + /** + * 删除 + * + * @param int|string|array $id + * + * @return mixed + */ + public function delete($id, ?string $key = null) + { + if (is_array($id)) { + $where = $id; + } else { + $where = [is_null($key) ? $this->getPk() : $key => $id]; + } + return $this->getModel()->where($where)->delete(); + } + + /** + * 删除记录 + * + * @param int|string $id + * @param bool $force + * + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/15 + */ + public function destroy(mixed $id, bool $force = false): bool + { + return $this->getModel()->destroy($id, $force); + } + + /** + * 更新数据 + * + * @param int|string|array $id + * @param array $data + * @param string|null $key + * + * @return BaseModel + */ + public function update(string|int|array $id, array $data, ?string $key = null): mixed + { + if (is_array($id)) { + $where = $id; + } else { + $where = [is_null($key) ? $this->getPk() : $key => $id]; + } + return $this->getModel()::update($data, $where); + } + + /** + * @param $where + * + * @return array|mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + protected function setWhere($where, ?string $key = null) + { + if (!is_array($where)) { + $where = [is_null($key) ? $this->getPk() : $key => $where]; + } + return $where; + } + + /** + * 批量更新数据 + * + * @param array $ids + * @param array $data + * @param string|null $key + * + * @return mixed + */ + public function batchUpdate(array $ids, array $data, ?string $key = null): mixed + { + return $this->getModel()->whereIn(is_null($key) ? $this->getPk() : $key, $ids)->update($data); + } + + /** + * 插入数据 + * + * @param array $data + * + * @return mixed + */ + public function save(array $data): mixed + { + return $this->getModel()::create($data); + } + + /** + * 插入数据 + * + * @param array $data + * + * @return \think\Collection + * @throws \Exception + */ + public function saveAll(array $data): \think\Collection + { + return $this->getModel()->saveAll($data); + } + + /** + * 获取某个字段内的值 + * + * @param $value + * @param string $filed + * @param string|null $valueKey + * @param array|string[] $where + * + * @return mixed + */ + public function getFieldValue($value, string $filed, ?string $valueKey = '', ?array $where = []) + { + return $this->getModel()->getFieldValue($value, $filed, $valueKey, $where); + } + + /** + * 获取搜索器和搜索条件key,以及不在搜索器的条件数组 + * + * @param array $where + * + * @return array[] + * @throws \ReflectionException + */ + private function getSearchData(array $where): array + { + $with = []; + $otherWhere = []; + $responses = new \ReflectionClass($this->setModel()); + foreach ($where as $key => $value) { + $method = 'search' . Str::studly($key) . 'Attr'; + if ($responses->hasMethod($method)) { + $with[] = $key; + } else { + if (!in_array($key, ['timeKey', 'store_stock', 'integral_time'])) { + if (!is_array($value)) { + $otherWhere[] = [$key, '=', $value]; + } else if (count($value) === 3) { + $otherWhere[] = $value; + } + } + } + } + return [$with, $otherWhere]; + } + + /** + * 根据搜索器获取搜索内容 + * + * @param $where + * @param $search + * + * @return BaseModel + * @throws \ReflectionException + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/18 + */ + protected function withSearchSelect($where, $search) + { + [$with, $otherWhere] = $this->getSearchData($where); + return $this->getModel()->withSearch($with, $where)->when($search, function ($query) use ($otherWhere) { + $query->where($this->filterWhere($otherWhere)); + }); + } + + /** + * 过滤数据表中不存在的where条件字段 + * + * @param array $where + * + * @return array + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/04/11 + */ + protected function filterWhere(array $where = []) + { + $fields = $this->getModel()->getTableFields(); + foreach ($where as $key => $item) { + if (!in_array($item[0], $fields)) { + unset($where[$key]); + } + } + return $where; + } + + /** + * 搜索 + * + * @param array $where + * @param bool $search + * + * @return BaseModel + * @throws \ReflectionException + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/18 + */ + public function search(array $where = [], bool $search = true) + { + if ($where) { + return $this->withSearchSelect($where, $search); + } else { + return $this->getModel(); + } + } + + /** + * 求和 + * + * @param array $where + * @param string $field + * @param bool $search + * + * @return float + * @throws \ReflectionException + */ + public function sum(array $where, string $field, bool $search = false) + { + if ($search) { + return $this->search($where)->sum($field); + } else { + return $this->getModel()->where($where)->sum($field); + } + } + + /** + * 高精度加法 + * + * @param $key + * @param string $incField + * @param string $inc + * @param string|null $keyField + * @param int $acc + * + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function bcInc($key, string $incField, string $inc, string $keyField = null, int $acc = 2) + { + return $this->bc($key, $incField, $inc, $keyField, 1); + } + + /** + * 高精度 减法 + * + * @param $key + * @param string $decField + * @param string $dec + * @param string|null $keyField + * @param int $acc + * + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function bcDec($key, string $decField, string $dec, string $keyField = null, int $acc = 2) + { + return $this->bc($key, $decField, $dec, $keyField, 2); + } + + /** + * 高精度计算并保存 + * + * @param $key + * @param string $incField + * @param string $inc + * @param string|null $keyField + * @param int $type + * @param int $acc + * + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function bc($key, string $incField, string $inc, string $keyField = null, int $type = 1, int $acc = 2) + { + if ($keyField === null) { + $result = $this->get($key); + } else { + $result = $this->getOne([$keyField => $key]); + } + if (!$result) return false; + $new = 0; + if ($type === 1) { + $new = bcadd($result[$incField], $inc, $acc); + } else if ($type === 2) { + if ($result[$incField] < $inc) return false; + $new = bcsub($result[$incField], $inc, $acc); + } + $result->{$incField} = $new; + return false !== $result->save(); + } + + /** + * 减库存加销量 + * + * @param array $where + * @param int $num + * @param string $stock + * @param string $sales + * + * @return false + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function decStockIncSales(array $where, int $num, string $stock = 'stock', string $sales = 'sales') + { + $isQuota = false; + if (isset($where['type']) && $where['type']) { + $isQuota = true; + if (count($where) == 2) { + unset($where['type']); + } + } + $field = $isQuota ? 'stock,quota' : 'stock'; + $product = $this->getModel()->where($where)->field($field)->find(); + if ($product) { + return $this->getModel()->where($where)->when($isQuota, function ($query) use ($num) { + $query->dec('quota', $num); + })->dec($stock, $num)->inc($sales, $num)->update(); + } + return false; + } + + /** + * 加库存减销量 + * + * @param array $where + * @param int $num + * @param string $stock + * @param string $sales + * + * @return mixed + */ + public function incStockDecSales(array $where, int $num, string $stock = 'stock', string $sales = 'sales') + { + $isQuota = false; + if (isset($where['type']) && $where['type']) { + $isQuota = true; + if (count($where) == 2) { + unset($where['type']); + } + } + $salesOne = $this->getModel()->where($where)->value($sales); + if ($salesOne) { + $salesNum = $num; + if ($num > $salesOne) { + $salesNum = $salesOne; + } + return $this->getModel()->where($where)->when($isQuota, function ($query) use ($num) { + $query->inc('quota', $num); + })->inc($stock, $num)->dec($sales, $salesNum)->update(); + } + return true; + } + + /** + * 获取条件数据中的某个值的最大值 + * + * @param array $where + * @param string $field + * + * @return mixed + */ + public function getMax(array $where = [], string $field = '') + { + return $this->getModel()->where($where)->max($field); + } + + /** + * 获取条件数据中的某个值的最小值 + * + * @param array $where + * @param string $field + * + * @return mixed + */ + public function getMin(array $where = [], string $field = '') + { + return $this->getModel()->where($where)->min($field); + } +} diff --git a/demo/thinkphp/backend/app/dao/system/admin/AdminAuthDao.php b/demo/thinkphp/backend/app/dao/system/admin/AdminAuthDao.php new file mode 100644 index 0000000000000000000000000000000000000000..199ce5e1cfb18b1b32b56fa72dd67a14702d1def --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/admin/AdminAuthDao.php @@ -0,0 +1,30 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemAdmin; + +/** + * + * + * @author Mr.April + * @since 1.0 + */ +class AdminAuthDao extends BaseDao +{ + protected function setModel(): string + { + return SystemAdmin::class; + } + +} diff --git a/demo/thinkphp/backend/app/dao/system/admin/SystemAdminDao.php b/demo/thinkphp/backend/app/dao/system/admin/SystemAdminDao.php new file mode 100644 index 0000000000000000000000000000000000000000..6ab3bd724dcfff19b195c05235dd6a079dd69b38 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/admin/SystemAdminDao.php @@ -0,0 +1,121 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemAdmin; + +/** + * Class SystemAdminDao + * + * @package app\dao\system\admin + */ +class SystemAdminDao extends BaseDao +{ + protected function setModel(): string + { + return SystemAdmin::class; + } + + /** + * 获取管理员列表 + * + * @param array $where + * @param int $page + * @param int $limit + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where, int $page, int $limit): array + { + return $this->search($where)->page($page, $limit)->select()->toArray(); + } + + /** + * 用管理员名查找管理员信息 + * + * @param string $account + * + * @return array|\think\Model|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function accountByAdmin(string $account): array|\think\Model|null + { + return $this->search(['account' => $account, 'delete_time' => null])->find(); + } + + /** + * 当前账号是否可用 + * + * ./ + * @param string $account + * @param string $id + * + * @return int + * @throws \ReflectionException + * @throws \think\db\exception\DbException + */ + public function isAccountUsable(string $account, string $id) + { + return $this->search(['account' => $account, 'delete_time' => null])->where('id', '<>', $id)->count(); + } + + /** + * 获取adminid + * + * @param int $level + * + * @return array + */ + public function getAdminIds(int $level) + { + return $this->getModel()->where('level', '>=', $level)->column('id', 'id'); + } + + /** + * 获取低于等级的管理员名称和id + * + * @param string $field + * @param int $level + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getOrdAdmin(string $field = 'real_name,id', int $level = 0): array + { + return $this->getModel()->where('level', '>=', $level)->field($field)->select()->toArray(); + } + + /** + * 条件获取管理员数据 + * + * @param $where + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo($where): mixed + { + return $this->getModel()->where($where)->find(); + } + +} diff --git a/demo/thinkphp/backend/app/dao/system/admin/SystemAdminDeptDao.php b/demo/thinkphp/backend/app/dao/system/admin/SystemAdminDeptDao.php new file mode 100644 index 0000000000000000000000000000000000000000..28424f796abf3470e9ad4b6cd8b7f2eb8f80229f --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/admin/SystemAdminDeptDao.php @@ -0,0 +1,49 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemAdminDept; + +/** + * 管理员关联-部门 + * + * @author Mr.April + * @since 1.0 + */ +class SystemAdminDeptDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemAdminDept::class; + } + + /** + * 指定条件获取某些角色权限的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } +} diff --git a/demo/thinkphp/backend/app/dao/system/admin/SystemAdminPostDao.php b/demo/thinkphp/backend/app/dao/system/admin/SystemAdminPostDao.php new file mode 100644 index 0000000000000000000000000000000000000000..fee88fee1decbde506a9f33c6eab1e155a8c5cb5 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/admin/SystemAdminPostDao.php @@ -0,0 +1,49 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemAdminPost; + +/** + * 管理员关联-职位 + * + * @author Mr.April + * @since 1.0 + */ +class SystemAdminPostDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemAdminPost::class; + } + + /** + * 指定条件获取某些角色权限的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } +} diff --git a/demo/thinkphp/backend/app/dao/system/admin/SystemDeptDao.php b/demo/thinkphp/backend/app/dao/system/admin/SystemDeptDao.php new file mode 100644 index 0000000000000000000000000000000000000000..3a100f7e1c9b4cf27227fcbfe466f657cb67d028 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/admin/SystemDeptDao.php @@ -0,0 +1,68 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemDept; + +/** + * 角色管理Dao层 + * + * @author Mr.April + * @since 1.0 + */ +class SystemDeptDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemDept::class; + } + + /** + * 获取组织列表 + * + * @param array $where + * @param int $page + * @param int $limit + * @param string $sort + * + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getDeptList(array $where, int $page, int $limit, string $sort = 'sort asc'): \think\Collection|array + { + return $this->search($where)->page($page, $limit)->order($sort)->select(); + } + + /** + * 指定条件获取某些组织的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + +} diff --git a/demo/thinkphp/backend/app/dao/system/admin/SystemMenusDao.php b/demo/thinkphp/backend/app/dao/system/admin/SystemMenusDao.php new file mode 100644 index 0000000000000000000000000000000000000000..b426215a79d31fdf16a76334289f34b22e9d8030 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/admin/SystemMenusDao.php @@ -0,0 +1,183 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemMenus; + +/** + * + * 菜单Dao层 + * @author Mr.April + * @since 1.0 + */ +class SystemMenusDao extends BaseDao +{ + + /** + * 设置模型 + * @return string + */ + protected function setModel(): string + { + return SystemMenus::class; + } + + /** + * + * @param array $menusIds + * + * @return bool + */ + public function deleteMenus(array $menusIds): bool + { + return $this->getModel()->whereIn('id', $menusIds)->delete(); + } + + /** + * 获取菜单列表 + * + * @param array $where + * @param array|null $field + * + * @return \think\Collection + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getMenusRoule(array $where, ?array $field = []): \think\Collection + { + if (!$field) { + $field = ['id', 'menu_name', 'icon', 'pid', 'sort', 'menu_path', 'auth_type','is_show', 'header', 'is_header', 'is_show_path', 'is_show']; + } + return $this->search($where)->field($field)->order('sort ASC')->failException(false)->select(); + } + + /** + * 获取菜单中的唯一权限 + * + * @param array $where + * + * @return array + * @throws \ReflectionException + */ + public function getMenusUnique(array $where): array + { + return $this->search($where)->where('unique_auth', '<>', '')->column('unique_auth', ''); + } + + /** + * 根据访问地址获得菜单名 + * + * @param string $rule + * + * @return mixed + * @throws \ReflectionException + */ + public function getVisitName(string $rule): mixed + { + return $this->search(['url' => $rule])->value('menu_name'); + } + + /** + * 获取后台菜单列表并分页 + * + * @param array $where + * @param array $field + * + * @return \think\Collection + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getMenusList(array $where, array $field = ['*']): \think\Collection + { + $where = array_merge($where, ['delete_time' => null]); + return $this->search($where)->field($field)->order('sort DESC,id ASC')->select(); + } + + /** + * 菜单总数 + * + * @param array $where + * + * @return int + * @throws \ReflectionException + */ + public function countMenus(array $where): int + { + $where = array_merge($where, ['delete' => null]); + return $this->count($where); + } + + /** + * 指定条件获取某些菜单的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + + /**菜单列表 + * + * @param array $where + * @param int $type + * + * @return \think\Collection + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function menusSelect(array $where, $type = 1): \think\Collection + { + if ($type == 1) { + return $this->search($where)->field('id,pid,menu_name,menu_path,unique_auth,sort')->order('sort DESC,id DESC')->select(); + } else { + return $this->search($where)->group('pid')->column('pid'); + } + } + + /** + * 搜索列表 + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function getSearchList(): \think\Collection|array + { + return $this->search(['is_show' => 1, 'auth_type' => 1, 'delete_time' => null, 'is_show_path' => 0]) + ->field('id,pid,menu_name,menu_path,unique_auth,sort')->order('sort DESC,id DESC')->select(); + } + + + /** + * + * @param string $path + * @param string $method + * + * @return bool + */ + public function deleteMenu(string $path, string $method): bool + { + return $this->getModel()->where('api_url', $path)->where('methods', $method)->delete(); + } +} diff --git a/demo/thinkphp/backend/app/dao/system/admin/SystemPostDao.php b/demo/thinkphp/backend/app/dao/system/admin/SystemPostDao.php new file mode 100644 index 0000000000000000000000000000000000000000..5ad9faba96ac046ce639a6d1bca193d2bc7c70e4 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/admin/SystemPostDao.php @@ -0,0 +1,67 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemPost; + +/** + * 角色管理Dao层 + * + * @author Mr.April + * @since 1.0 + */ +class SystemPostDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemPost::class; + } + + /** + * 获取职位列表 + * + * @param array $where + * @param int $page + * @param int $limit + * @param string $sort + * + * @return \think\Collection|array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getPostList(array $where, int $page, int $limit, string $sort = 'sort asc'): \think\Collection|array + { + return $this->search($where)->page($page, $limit)->order($sort)->select(); + } + + /** + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + +} diff --git a/demo/thinkphp/backend/app/dao/system/admin/SystemRoleDao.php b/demo/thinkphp/backend/app/dao/system/admin/SystemRoleDao.php new file mode 100644 index 0000000000000000000000000000000000000000..b6d37392b6d7a826f4c83b080f6abf3a4fde1493 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/admin/SystemRoleDao.php @@ -0,0 +1,69 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemRole; + +/** + * 角色管理Dao层 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRoleDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemRole::class; + } + + /** + * 获取身份列表 + * + * @param array $where + * @param int $page + * @param int $limit + * @param string $sort + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getRouleList(array $where, int $page, int $limit, string $sort = 'sort asc') + { + return $this->search($where)->page($page, $limit)->order($sort)->select()->toArray(); + } + + /** + * 指定条件获取某些角色的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + +} diff --git a/demo/thinkphp/backend/app/dao/system/admin/SystemRoleDeptDao.php b/demo/thinkphp/backend/app/dao/system/admin/SystemRoleDeptDao.php new file mode 100644 index 0000000000000000000000000000000000000000..2e212d860bfe6c55add0059b6e71b5604c38689c --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/admin/SystemRoleDeptDao.php @@ -0,0 +1,50 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemRoleDept; + +/** + * 角色权限 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRoleDeptDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemRoleDept::class; + } + + /** + * 指定条件获取某些角色权限的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + +} diff --git a/demo/thinkphp/backend/app/dao/system/admin/SystemRoleMenuDao.php b/demo/thinkphp/backend/app/dao/system/admin/SystemRoleMenuDao.php new file mode 100644 index 0000000000000000000000000000000000000000..bda152963dc6a4a323566cfdfdd0d2a0e8fcce50 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/admin/SystemRoleMenuDao.php @@ -0,0 +1,50 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemRoleMenu; + +/** + * 角色权限 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRoleMenuDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemRoleMenu::class; + } + + /** + * 指定条件获取某些角色权限的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + +} diff --git a/demo/thinkphp/backend/app/dao/system/admin/SystemRolePostDao.php b/demo/thinkphp/backend/app/dao/system/admin/SystemRolePostDao.php new file mode 100644 index 0000000000000000000000000000000000000000..bbba6706aef1e2f887fe2f865ddceba7daa06b77 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/admin/SystemRolePostDao.php @@ -0,0 +1,50 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemRolePost; + +/** + * 角色关系表职位 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRolePostDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemRolePost::class; + } + + /** + * + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + +} diff --git a/demo/thinkphp/backend/app/dao/system/attachment/SystemAttachmentCategoryDao.php b/demo/thinkphp/backend/app/dao/system/attachment/SystemAttachmentCategoryDao.php new file mode 100644 index 0000000000000000000000000000000000000000..f5d657a4591022e3eded75ddac259065805879a0 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/attachment/SystemAttachmentCategoryDao.php @@ -0,0 +1,72 @@ + +// +---------------------------------------------------------------------- +declare (strict_types=1); + +namespace app\dao\system\attachment; + +use app\dao\BaseDao; +use app\model\system\attachment\SystemAttachmentCategory; + +/** + * + * 附件分类Dao + * @author Mr.April + * @since 1.0 + */ +class SystemAttachmentCategoryDao extends BaseDao +{ + + /** + * 设置模型 + * @return string + */ + protected function setModel(): string + { + return SystemAttachmentCategory::class; + } + + /** + * 获取列表 + * @param array $where + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where) + { + return $this->search($where)->select()->toArray(); + } + + /** + * 获取数量 + * @param array $where + * @return int + */ + public function getCount(array $where) + { + return $this->search($where)->count(); + } + + /** + * 搜索附件分类search + * @param array $where + * @param bool $search + * @return \crmeb\basic\BaseModel|mixed|\think\Model + * @throws \ReflectionException + */ + public function search(array $where = [], bool $search = false) + { + return parent::search($where, $search)->when(isset($where['id']), function ($query) use ($where) { + $query->whereIn('id', $where['id']); + }); + } +} diff --git a/demo/thinkphp/backend/app/dao/system/attachment/SystemAttachmentDao.php b/demo/thinkphp/backend/app/dao/system/attachment/SystemAttachmentDao.php new file mode 100644 index 0000000000000000000000000000000000000000..561fec633fcdfbe136a57e922e6e74d454e45c4d --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/attachment/SystemAttachmentDao.php @@ -0,0 +1,111 @@ + +// +---------------------------------------------------------------------- +declare (strict_types=1); + +namespace app\dao\system\attachment; + +use app\dao\BaseDao; +use app\model\system\attachment\SystemAttachment; + +/** + * + * Class SystemAttachmentDao + * @package app\dao\attachment + */ +class SystemAttachmentDao extends BaseDao +{ + + /** + * 设置模型 + * @return string + */ + protected function setModel(): string + { + return SystemAttachment::class; + } + + /** + * 获取图片列表 + * @param array $where + * @param int $page + * @param int $limit + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where, int $page, int $limit) + { + return $this->search($where)->where('module_type', 1)->page($page, $limit)->order('att_id DESC')->select()->toArray(); + } + + /** + * 移动图片 + * @param array $data + * @return \crmeb\basic\BaseModel + */ + public function move(array $data) + { + return $this->getModel()->whereIn('att_id', $data['images'])->update(['pid' => $data['pid']]); + } + + /** + * 获取名称 + * @param array $where + * @param int $page + * @param int $limit + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getLikeNameList(array $where, int $page, int $limit) + { + return $this->search($where)->page($page, $limit)->order('att_id desc')->select()->toArray(); + } + + /** + * 获取昨日系统生成 + * @return \think\Collection + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getYesterday() + { + return $this->getModel()->whereTime('time', 'yesterday')->where('module_type', 2)->field(['name', 'att_dir', 'att_id', 'image_type'])->select(); + } + + /** + * 删除昨日生成海报 + * @throws \Exception + */ + public function delYesterday() + { + $this->getModel()->whereTime('time', 'yesterday')->where('module_type', 2)->delete(); + } + + /** + * 获取扫码上传的图片数据 + * @param $scan_token + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/06/13 + */ + public function scanUploadImage($scan_token) + { + return $this->getModel()->where('scan_token', $scan_token)->field('att_dir,att_id')->select()->toArray(); + } +} diff --git a/demo/thinkphp/backend/app/dao/system/config/SystemConfigDao.php b/demo/thinkphp/backend/app/dao/system/config/SystemConfigDao.php new file mode 100644 index 0000000000000000000000000000000000000000..5a8466230f82ed7a1299b17019a62863cc2c8179 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/config/SystemConfigDao.php @@ -0,0 +1,100 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\config; + +use app\dao\BaseDao; +use app\model\system\config\SystemConfig; + +/** + * 系统配置 + * Class SystemConfigDao + * @package app\dao\system\config + */ +class SystemConfigDao extends BaseDao +{ + /** + * 设置模型 + * @return string + */ + protected function setModel(): string + { + return SystemConfig::class; + } + + /** + * 获取某个系统配置 + * @param string $configNmae + * @return mixed + * @throws \ReflectionException + */ + public function getConfigValue(string $configNmae) + { + return $this->search(['menu_name' => $configNmae])->value('value'); + } + + /** + * 获取所有配置 + * @param array $configName + * @return array + * @throws \ReflectionException + */ + public function getConfigAll(array $configName = []) + { + if ($configName) { + return $this->search(['menu_name' => $configName])->column('value', 'menu_name'); + } else { + return $this->getModel()->column('value', 'menu_name'); + } + } + + /** + * 获取配置列表分页 + * @param array $where + * @param int $page + * @param int $limit + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfigList(array $where, int $page, int $limit) + { + return $this->search($where)->page($page, $limit)->order('sort desc')->select()->toArray(); + } + + /** + * 获取某些分类配置下的配置列表 + * @param int $tabId + * @param int $status + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfigTabAllList(int $tabId, int $status = 1) + { + $where['tab_id'] = $tabId; + if ($status == 1) $where['status'] = $status; + return $this->search($where)->order('sort desc,id ASC')->select()->toArray(); + } + + /** + * 获取上传配置中的上传类型 + * @param string $configName + * @return array + * @throws \ReflectionException + */ + public function getUploadTypeList(string $configName) + { + return $this->search(['menu_name' => $configName])->column('upload_type', 'type'); + } +} diff --git a/demo/thinkphp/backend/app/dao/system/config/SystemConfigTabDao.php b/demo/thinkphp/backend/app/dao/system/config/SystemConfigTabDao.php new file mode 100644 index 0000000000000000000000000000000000000000..3cfc197203fac12f567a1bc7b6a5a4b63ee08fee --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/config/SystemConfigTabDao.php @@ -0,0 +1,65 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\config; + + +use app\dao\BaseDao; +use app\model\system\config\SystemConfigTab; + +/** + * 配置分类 + * Class SystemConfigTabDao + * @package app\dao\system\config + */ +class SystemConfigTabDao extends BaseDao +{ + /** + * 设置模型 + * @return string + */ + protected function setModel(): string + { + return SystemConfigTab::class; + } + + /** + * 获取配置分类 + * @param array $where + * @param array $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfigTabAll(array $searchWhere, array $field = ['*'], array $where = []) + { + return $this->search($searchWhere)->when(count($where), function ($query) use ($where) { + $query->where($where); + })->field($field)->order('sort desc,id asc')->select()->toArray(); + } + + /** + * 配置分类列表 + * @param array $where + * @param int $page + * @param int $limit + * @return \think\Collection + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfgTabList(array $where, int $page, int $limit) + { + return $this->search($where)->order('sort desc,id asc')->select(); + } + +} diff --git a/demo/thinkphp/backend/app/dao/system/config/SystemGroupDao.php b/demo/thinkphp/backend/app/dao/system/config/SystemGroupDao.php new file mode 100644 index 0000000000000000000000000000000000000000..8739fb74e276f6401cf0fced5dc519559f0cae01 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/config/SystemGroupDao.php @@ -0,0 +1,57 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\config; + +use app\dao\BaseDao; +use app\model\system\config\SystemGroup; + +/** + * Class SystemGroupDao + * @package app\dao\system\config + */ +class SystemGroupDao extends BaseDao +{ + /** + * @return string + */ + protected function setModel(): string + { + return SystemGroup::class; + } + + /** + * 获取组合数据分页列表 + * @param array $where + * @param int $page + * @param int $limit + * @return \think\Collection + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGroupList(array $where, array $field = ['*'], int $page = 0, int $limit = 0) + { + return $this->search($where)->field($field)->when($page && $limit, function ($query) use ($page, $limit) { + $query->page($page, $limit); + })->select()->toArray(); + } + + /** + * 根据配置名称获取配置id + * @param string $configName + * @return mixed + */ + public function getConfigNameId(string $configName) + { + return $this->value(['config_name' => $configName]); + } +} diff --git a/demo/thinkphp/backend/app/dao/system/config/SystemGroupDataDao.php b/demo/thinkphp/backend/app/dao/system/config/SystemGroupDataDao.php new file mode 100644 index 0000000000000000000000000000000000000000..48be28e2241624a7e12b1fb8a4f00e3da10c5002 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/config/SystemGroupDataDao.php @@ -0,0 +1,97 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\config; + +use app\dao\BaseDao; +use app\model\system\config\SystemGroupData; + +/** + * 组合数据 + * Class SystemGroupDataDao + * @package app\dao\system\config + */ +class SystemGroupDataDao extends BaseDao +{ + /** + * 设置模型 + * @return string + */ + protected function setModel(): string + { + return SystemGroupData::class; + } + + /** + * 获取组合数据列表 + * @param array $where + * @param int $page + * @param int $limit + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGroupDataList(array $where, int $page, int $limit) + { + return $this->search($where)->page($page, $limit)->order('sort desc,id DESC')->select()->toArray(); + } + + /** + * 获取某个gid下的组合数据 + * @param int $gid + * @param int $limit + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGroupDate(int $gid, int $limit = 0) + { + return $this->search(['gid' => $gid, 'status' => 1])->when($limit, function ($query) use ($limit) { + $query->limit($limit); + })->field('value,id')->order('sort DESC,id DESC')->select()->toArray(); + } + + /** + * 根据id获取秒杀数据 + * @param array $ids + * @param string $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function idByGroupList(array $ids, string $field) + { + return $this->getModel()->whereIn('id', $ids)->field($field)->select()->toArray(); + } + + /** + * 根据gid删除组合数据 + * @param int $gid + * @return bool + */ + public function delGroupDate(int $gid) + { + return $this->getModel()->where('gid', $gid)->delete(); + } + + /** + * 批量保存 + * @param array $data + * @return mixed|\think\Collection + * @throws \Exception + */ + public function saveAll(array $data) + { + return $this->getModel()->saveAll($data); + } +} diff --git a/demo/thinkphp/backend/app/dao/system/config/SystemStorageDao.php b/demo/thinkphp/backend/app/dao/system/config/SystemStorageDao.php new file mode 100644 index 0000000000000000000000000000000000000000..3cf199110a78998fe3770ec5dee048b23d82a76a --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/config/SystemStorageDao.php @@ -0,0 +1,81 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\config; + + +use app\dao\BaseDao; +use app\model\system\config\SystemStorage; + +/** + * Class SystemStorageDao + * @package app\dao\system\config + */ +class SystemStorageDao extends BaseDao +{ + + /** + * @return string + */ + protected function setModel(): string + { + return SystemStorage::class; + } + + /** + * 获取列表 + * @param array $where + * @param array|string[] $field + * @param int $page + * @param int $limit + * @param null $sort + * @param array $with + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where = [], array $field = ['*'], int $page = 0, int $limit = 0, $sort = null, array $with = []) + { + return $this->search($where)->field($field)->when($page && $limit, function ($query) use ($page, $limit) { + $query->page($page, $limit); + })->when($sort, function ($query) use ($sort) { + if (is_array($sort)) { + foreach ($sort as $v => $k) { + if (is_numeric($v)) { + $query->order($k, 'desc'); + } else { + $query->order($v, $k); + } + } + } else { + $query->order($sort, 'desc'); + } + })->with($with)->select()->toArray(); + } + + /** + * @param array $where + * @param bool $search + * @return \crmeb\basic\BaseModel|mixed|\think\Model + * @throws \ReflectionException + */ + public function search(array $where = [], bool $search = false) + { + return parent::search($where, $search)->when(isset($where['type']), function ($query) use ($where) { + $query->where('type', $where['type']); + })->where('is_delete', 0)->when(isset($where['access_key']), function ($query) use ($where) { + $query->where('access_key', $where['access_key']); + })->when(!empty($where['id']), function ($query) use ($where) { + $query->where('id', $where['id']); + }); + } +} diff --git a/demo/thinkphp/backend/app/dao/system/crontab/SystemCrontabDao.php b/demo/thinkphp/backend/app/dao/system/crontab/SystemCrontabDao.php new file mode 100644 index 0000000000000000000000000000000000000000..3eddc90e862f9f9c513ee0ba363e5c78684f774c --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/crontab/SystemCrontabDao.php @@ -0,0 +1,24 @@ +getModel()->where('name', $name)->find(); + } +} diff --git a/demo/thinkphp/backend/app/dao/system/lang/LangCodeDao.php b/demo/thinkphp/backend/app/dao/system/lang/LangCodeDao.php new file mode 100644 index 0000000000000000000000000000000000000000..f5253381fa90c2f1a8c13699dfae4e9e1c79c230 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/lang/LangCodeDao.php @@ -0,0 +1,18 @@ +getModel()->where('create_time', '<', time() - 7776000)->delete(); + } + + /** + * 获取系统日志列表 + * + * @param array $where + * @param int $page + * @param int $limit + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getLogList(array $where, int $page, int $limit): array + { + return $this->search($where)->page($page, $limit)->order('create_time DESC')->select()->toArray(); + } + +} diff --git a/demo/thinkphp/backend/app/dao/system/route/SystemRouteCateDao.php b/demo/thinkphp/backend/app/dao/system/route/SystemRouteCateDao.php new file mode 100644 index 0000000000000000000000000000000000000000..67b83b8caf24b2bf7f1f465ce2e41dcb5be5e23f --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/route/SystemRouteCateDao.php @@ -0,0 +1,40 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\dao\system\route; + + +use app\dao\BaseDao; +use app\model\system\route\SystemRouteCate; + +/** + * Class SystemRouteCateDao + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + * @package app\dao\system + */ +class SystemRouteCateDao extends BaseDao +{ + + /** + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + protected function setModel(): string + { + return SystemRouteCate::class; + } +} diff --git a/demo/thinkphp/backend/app/dao/system/route/SystemRouteDao.php b/demo/thinkphp/backend/app/dao/system/route/SystemRouteDao.php new file mode 100644 index 0000000000000000000000000000000000000000..398ab02d43b2cb3ad4c4e97876ee4c45c941df73 --- /dev/null +++ b/demo/thinkphp/backend/app/dao/system/route/SystemRouteDao.php @@ -0,0 +1,55 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\dao\system\route; + + +use app\dao\BaseDao; +use app\model\system\route\SystemRoute; + + +/** + * Class SystemRouteDao + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + * @package app\dao\system + */ +class SystemRouteDao extends BaseDao +{ + + /** + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + protected function setModel(): string + { + return SystemRoute::class; + } + + /** + * @param array $ids + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/23 + */ + public function deleteRoutes(array $ids) + { + return $this->getModel()::destroy(function ($q) use ($ids) { + $q->whereIn('id', $ids); + }, true); + } +} diff --git a/demo/thinkphp/backend/app/event.php b/demo/thinkphp/backend/app/event.php new file mode 100644 index 0000000000000000000000000000000000000000..08fee227e284e77d4aedcf204e24945e82767f6c --- /dev/null +++ b/demo/thinkphp/backend/app/event.php @@ -0,0 +1,18 @@ + [ + ], + + 'listen' => [ + 'AppInit' => [], + 'HttpRun' => [], + 'HttpEnd' => [], + 'LogLevel' => [], + 'LogWrite' => [], + 'CrontabListener' => [\app\listener\crontab\SystemCrontabListener::class],//定时任务事件 + ], + + 'subscribe' => [ + ], +]; diff --git a/demo/thinkphp/backend/app/jobs/TestJob.php b/demo/thinkphp/backend/app/jobs/TestJob.php new file mode 100644 index 0000000000000000000000000000000000000000..8bd314fb946f16c8619d2ec9ef9f25fa7fe83039 --- /dev/null +++ b/demo/thinkphp/backend/app/jobs/TestJob.php @@ -0,0 +1,43 @@ + +// +---------------------------------------------------------------------- + +namespace app\jobs\notice; + +use app\services\message\notice\EnterpriseWechatService; +use phoenix\basic\BaseJobs; +use phoenix\traits\QueueTrait; +use think\facade\Log; + +class EnterpriseWechatJob extends BaseJobs +{ + use QueueTrait; + + /** + * 给企业微信群发送消息 + * @param $data + * @return bool + */ + public function doJob($data): bool + { + try { + /** @var EnterpriseWechatService $enterpriseWechatService */ + $enterpriseWechatService = app()->make(EnterpriseWechatService::class); + $enterpriseWechatService->weComSend($data); + return true; + } catch (\Exception $e) { + Log::error('发送企业群消息失败,失败原因:' . $e->getMessage()); + } + } +} diff --git a/demo/thinkphp/backend/app/jobs/notice/SmsJob.php b/demo/thinkphp/backend/app/jobs/notice/SmsJob.php new file mode 100644 index 0000000000000000000000000000000000000000..6196b87bbd21b2593260d5682bc1b5ebe0cb862b --- /dev/null +++ b/demo/thinkphp/backend/app/jobs/notice/SmsJob.php @@ -0,0 +1,45 @@ + +// +---------------------------------------------------------------------- + +namespace app\jobs\notice; + +use app\services\message\notice\SmsService; +use phoenix\basic\BaseJobs; +use phoenix\traits\QueueTrait; +use think\facade\Log; + + +class SmsJob extends BaseJobs +{ + use QueueTrait; + + /** + * 发送短信 + * + * @param $phone + * @param array $data + * @param string $template + * + * @return bool + */ + public function doJob($phone, array $data, string $template): bool + { + + try{ + /** @var SmsService $smsServices */ + $smsServices = app()->make(SmsService::class); + $smsServices->send(true, $phone, $data, $template); + return true; + }catch (\Throwable $e) { + Log::error('发送短信失败,失败原因:' . $e->getMessage()); + } + } +} diff --git a/demo/thinkphp/backend/app/lang/en_us.php b/demo/thinkphp/backend/app/lang/en_us.php new file mode 100644 index 0000000000000000000000000000000000000000..3621af93dca3c89f9d50ef12e51d2dec35347c0f --- /dev/null +++ b/demo/thinkphp/backend/app/lang/en_us.php @@ -0,0 +1,78 @@ + +// +---------------------------------------------------------------------- +return [ + 100000 => 'Saved succeeded', + 100001 => 'Modification successful', + 100002 => 'Deletion succeeded', + 100003 => 'Display successful', + 100004 => 'Hidden successfully', + 100005 => 'operation failed', + 100006 => 'Save failed', + 100007 => 'Modification failed', + 100008 => 'Delete failed', + 100009 => 'Picture uploaded successfully', + 100010 => 'Operation successful', + 100011 => 'No data', + 100012 => 'Update successful', + 100013 => 'Update failed', + 100014 => 'Set successfully', + 100015 => 'Setting failed', + 100016 => 'Get failed', + 100017 => 'Submitted successfully', + 100018 => 'Submit failed', + 100019 => 'Cancellation succeeded', + 100020 => 'Cancel failed', + 100021 => 'Successfully added', + 100022 => 'Add failed', + 100023 => 'Failed to save token', + 100024 => 'Remarks successful', + 100025 => 'Remarks failed', + 100026 => 'Data does not exist', + 100027 => 'Successful application', + 100028 => 'Application failed', + 100029 => 'No such method', + 100030 => 'Sent successfully', + 100031 => 'fail in send', + 100032 => 'Upload successful', + 100033 => 'Upload failed', + 100034 => 'Move successful', + 100035 => 'Move failed', + 100036 => 'Refund successful', + 100037 => 'Refund failed', + 100038 => 'Synchronization succeeded', + 100039 => 'Synchronization failed', + 100040 => 'recovery was successful', + 100041 => 'restore failed', + 100042 => 'Exit successful', + 100043 => 'Exit failed', + 100044 => 'Successfully opened', + 100045 => 'Failed to open', + 100046 => 'Data cleared successfully', + 100047 => 'Optimization succeeded', + 100048 => 'Optimization failed', + 100049 => 'Repair successful', + 100050 => 'Repair failed', + 100051 => 'Backup successful', + 100052 => 'Backup failed', + 100100 => 'Parameter error', + 100101 => 'Illegal operation', + 100102 => 'Data acquisition failed', + 100103 => 'Site upgrade in progress, please visit later', + 100104 => 'Missing Code', + + // 处理特殊状态码 + 110000 => 'You do not have access right for the time being', + 110001 => 'The interface is not authorized and you cannot access it', + //用户登录特殊 + 110002 => 'Please login', + 110003 => 'Login has expired, please login again', + 110004 => 'Login status error, please login again', +]; diff --git a/demo/thinkphp/backend/app/lang/zh_cn.php b/demo/thinkphp/backend/app/lang/zh_cn.php new file mode 100644 index 0000000000000000000000000000000000000000..9599cedcbd41244531c673f86bb9756e28f24ff5 --- /dev/null +++ b/demo/thinkphp/backend/app/lang/zh_cn.php @@ -0,0 +1,78 @@ + +// +---------------------------------------------------------------------- +return [ + 100000 => '保存成功', + 100001 => '修改成功', + 100002 => '删除成功', + 100003 => '显示成功', + 100004 => '隐藏成功', + 100005 => '操作失败', + 100006 => '保存失败', + 100007 => '修改失败', + 100008 => '删除失败', + 100009 => '图片上传成功', + 100010 => '操作成功', + 100011 => '暂无数据', + 100012 => '更新成功', + 100013 => '更新失败', + 100014 => '设置成功', + 100015 => '设置失败', + 100016 => '获取失败', + 100017 => '提交成功', + 100018 => '提交失败', + 100019 => '取消成功', + 100020 => '取消失败', + 100021 => '添加成功', + 100022 => '添加失败', + 100023 => '保存token失败', + 100024 => '备注成功', + 100025 => '备注失败', + 100026 => '数据不存在', + 100027 => '申请成功', + 100028 => '申请失败', + 100029 => '暂无此方法', + 100030 => '发送成功', + 100031 => '发送失败', + 100032 => '上传成功', + 100033 => '上传失败', + 100034 => '移动成功', + 100035 => '移动失败', + 100036 => '退款成功', + 100037 => '退款失败', + 100038 => '同步成功', + 100039 => '同步失败', + 100040 => '恢复成功', + 100041 => '恢复失败', + 100042 => '退出成功', + 100043 => '退出失败', + 100044 => '开通成功', + 100045 => '开通失败', + 100046 => '清除数据成功', + 100047 => '优化成功', + 100048 => '优化失败', + 100049 => '修复成功', + 100050 => '修复失败', + 100051 => '备份成功', + 100052 => '备份失败', + 100100 => '参数错误', + 100101 => '非法操作', + 100102 => '数据获取失败', + 100103 => '站点升级中,请稍候访问', + 100104 => '缺少code', + + // 处理特殊状态码 + 110000 => '您暂时没有访问权限', + 110001 => '接口未授权,您无法访问', + //用户登录特殊 + 110002 => '请登录', + 110003 => '登录已过期,请重新登录', + 110004 => '登录状态有误,请重新登录', +]; diff --git a/demo/thinkphp/backend/app/listener/crontab/SystemCrontabListener.php b/demo/thinkphp/backend/app/listener/crontab/SystemCrontabListener.php new file mode 100644 index 0000000000000000000000000000000000000000..b97d8bb1d48a234abb4cbf7ec666571937f1c277 --- /dev/null +++ b/demo/thinkphp/backend/app/listener/crontab/SystemCrontabListener.php @@ -0,0 +1,83 @@ +make(SystemCrontabServices::class); + $crontabRunServices = app()->make(CrontabRunServices::class); + + //自动写入文件方便检测是否启动定时任务命令 + new Crontab('*/6 * * * * *', function () { + file_put_contents(root_path() . 'runtime/.timer', time()); + }); + + $list = $systemCrontabServices->selectList(['delete_time' => null, 'is_open' => 1])->toArray(); + + foreach ($list as &$item) { + //转化小驼峰 + $functionName = Str::camel($item['mark']); + + //获取定时任务时间字符串 + $timeStr = $this->getTimerStr($item); + new Crontab($timeStr, function () use ($crontabRunServices, $functionName) { + $crontabRunServices->$functionName(); + }); + } + } + + /** + * 获取定时任务时间表达式 + * 0 1 2 3 4 5 + * | | | | | | + * | | | | | +------ day of week (0 - 6) (Sunday=0) + * | | | | +------ month (1 - 12) + * | | | +-------- day of month (1 - 31) + * | | +---------- hour (0 - 23) + * | +------------ min (0 - 59) + * +-------------- sec (0-59)[可省略,如果没有0位,则最小时间粒度是分钟] + * + * @param $data + * + * @return string + */ + public function getTimerStr($data): string + { + $timeStr = ''; + switch ($data['type']) { + case 1:// 每隔几秒 + $timeStr = '*/' . $data['second'] . ' * * * * *'; + break; + case 2:// 每隔几分 + $timeStr = '0 */' . $data['minute'] . ' * * * *'; + break; + case 3:// 每隔几时第几分钟执行 + $timeStr = '0 ' . $data['minute'] . ' */' . $data['hour'] . ' * * *'; + break; + case 4:// 每隔几日第几小时第几分钟执行 + $timeStr = '0 ' . $data['minute'] . ' ' . $data['hour'] . ' */' . $data['day'] . ' * *'; + break; + case 5:// 每日几时几分几秒 + $timeStr = $data['second'] . ' ' . $data['minute'] . ' ' . $data['hour'] . ' * * *'; + break; + case 6:// 每周周几几时几分几秒 + $timeStr = $data['second'] . ' ' . $data['minute'] . ' ' . $data['hour'] . ' * * ' . ($data['week'] == 7 ? 0 : $data['week']); + break; + case 7:// 每月几日几时几分几秒 + $timeStr = $data['second'] . ' ' . $data['minute'] . ' ' . $data['hour'] . ' ' . $data['day'] . ' * *'; + break; + } + return $timeStr; + } +} diff --git a/demo/thinkphp/backend/app/middleware.php b/demo/thinkphp/backend/app/middleware.php new file mode 100644 index 0000000000000000000000000000000000000000..04c53e47eedc24ef9bfb50339891e3b608f07ec7 --- /dev/null +++ b/demo/thinkphp/backend/app/middleware.php @@ -0,0 +1,18 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use phoenix\basic\BaseModel; +use phoenix\traits\JwtAuthModelTrait; +use phoenix\traits\ModelTrait; +use phoenix\utils\Str; +use think\db\Query; +use think\Model; + +/** + * 管理员模型 + * Class SystemAdmin + * + * @package app\model\system\admin + */ +class SystemAdmin extends BaseModel +{ + use ModelTrait; + use JwtAuthModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_admin'; + + protected array $insert = ['create_time', 'update_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + 'last_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * inID搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIdInAttr(Query $query, $value) + { + if (!empty($value)) { + $query->whereIn('id', $value); + } + } + + /** + * 管理员级别搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchLevelAttr(Query $query, $value) + { + if (is_array($value)) { + $query->where('level', $value[0], $value[1]); + } else { + $query->where('level', $value); + } + } + + /** + * 管理员账号和姓名搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchAccountLikeAttr(Query $query, $value) + { + if ($value) { + $query->whereLike('account|real_name', '%' . $value . '%'); + } + } + + public function searchNotAccountAttr(Query $query, $value) + { + if ($value) { + $query->where('account', '<>', $value); + } + } + + /** + * 管理员账号搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchAccountAttr(Query $query, $value) + { + if ($value) { + $query->where('account', $value); + } + } + + /** + * 管理员账号搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchInAccountAttr(Query $query, $value) + { + if ($value) { + $query->whereIn('account', $value); + } + } + + /** + * 是否删除搜索器 + * + * @param \think\db\Query $query + */ + public function searchIsDelAttr(Query $query) + { + $query->where('delete_time', null); + } + + /** + * 状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + if ($value != '' && $value != null) { + $query->where('status', $value); + } + } + + /** + * 定义多对多远程关联部门模型 + * + * @return \think\model\relation\HasManyThrough + */ + public function departments(): \think\model\relation\HasManyThrough + { + //目标模型 中间模型 关联中间模型字段 关联最终模型字段 当前模型关联中间模型字段 最终模型关联字段 + return $this->hasManyThrough(SystemDept::class, SystemAdminDept::class, 'admin_id', 'dept_id', 'id', 'dept_id'); + } + + /** + * 定义多对多远程关联职位 + */ + public function positions(): \think\model\relation\HasManyThrough + { + return $this->hasManyThrough(SystemPost::class, SystemAdminPost::class, 'admin_id', 'post_id', 'id', 'post_id'); + } + +} diff --git a/demo/thinkphp/backend/app/model/system/admin/SystemAdminDept.php b/demo/thinkphp/backend/app/model/system/admin/SystemAdminDept.php new file mode 100644 index 0000000000000000000000000000000000000000..3b87c95c8974412a6faf84bfdeccce038d6ae52c --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/admin/SystemAdminDept.php @@ -0,0 +1,67 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use think\db\Query; +use think\Model; + +/** + * 管理员关联组织 + * + * @author Mr.April + * @since 1.0 + */ +class SystemAdminDept extends BaseModel +{ + use ModelTrait; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_admin_dept'; + + /** + * adminId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchAdminIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('admin_id', $value); + } else { + $query->where('admin_id', $value); + } + } + + /** + * deptId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchDeptIdAttr(Query $query, $value) + { + if ($value) { + if (is_array($value)) { + $query->whereIn('dept_id', $value); + } else { + $query->where('dept_id', $value); + } + } + } +} diff --git a/demo/thinkphp/backend/app/model/system/admin/SystemAdminPost.php b/demo/thinkphp/backend/app/model/system/admin/SystemAdminPost.php new file mode 100644 index 0000000000000000000000000000000000000000..83783ce96aa8d14e25975441f325683ceb71f24e --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/admin/SystemAdminPost.php @@ -0,0 +1,68 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use think\db\Query; +use think\Model; + +/** + * 管理员关联-职位 + * + * @author Mr.April + * @since 1.0 + */ +class SystemAdminPost extends BaseModel +{ + use ModelTrait; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_admin_post'; + + /** + * adminId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchAdminIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('admin_id', $value); + } else { + $query->where('admin_id', $value); + } + } + + /** + * menuId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPostIdAttr(Query $query, $value) + { + if ($value) { + if (is_array($value)) { + $query->whereIn('post_id', $value); + } else { + $query->where('post_id', $value); + } + } + } + +} diff --git a/demo/thinkphp/backend/app/model/system/admin/SystemDept.php b/demo/thinkphp/backend/app/model/system/admin/SystemDept.php new file mode 100644 index 0000000000000000000000000000000000000000..68a3e2630bbcd31aa0afbd2475ed4d1531cc3770 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/admin/SystemDept.php @@ -0,0 +1,130 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use phoenix\utils\Str; +use think\db\Query; +use think\Model; + +/** + * 组织管理 + * + * @author Mr.April + * @since 1.0 + */ +class SystemDept extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'dept_id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_dept'; + + protected array $insert = ['create_time', 'update_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + 'delete_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 生成字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 权限规格状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + if ($value != '') { + $query->where('status', $value ?: 1); + } + } + + /** + * id搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('role_id', $value); + } else { + $query->where('role_id', $value); + } + } + + /** + * 身份管理搜索 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchDeptNameAttr(Query $query, $value) + { + if ($value) { + $query->whereLike('dept_name', '%' . $value . '%'); + } + } + + /** + * Pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + $query->where('pid', $value ?? '-1'); + } + + /** + * Type搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchDeptTypeAttr(Query $query, $value) + { + if (!empty($value)) { + $query->where('dept_type', $value); + } + } + +} diff --git a/demo/thinkphp/backend/app/model/system/admin/SystemMenus.php b/demo/thinkphp/backend/app/model/system/admin/SystemMenus.php new file mode 100644 index 0000000000000000000000000000000000000000..df8163151868c4bfe6d4f7021878ad76921289e9 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/admin/SystemMenus.php @@ -0,0 +1,289 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use phoenix\utils\Str; +use think\db\Query; + +/** + * 菜单规则模型 + * Class SystemMenus + * + * @package app\model\system + */ +class SystemMenus extends BaseModel +{ + use ModelTrait; + + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + protected string $pkType = 'string'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_menus'; + + protected array $insert = ['create_time', 'update_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 参数修改器 + * + * @param $value + * + * @return false|string + */ + public function setParamsAttr($value): bool|string + { + $value = $value ? explode('/', $value) : []; + $params = array_chunk($value, 2); + $data = []; + foreach ($params as $param) { + if (isset($param[0]) && isset($param[1])) $data[$param[0]] = $param[1]; + } + return json_encode($data); + } + + /** + * 参数获取器 + * + * @param $_value + * + * @return mixed + */ + public function getParamsAttr($_value): mixed + { + return json_decode($_value, true); + } + + /** + * pid获取器 + * + * @param $value + * + * @return mixed|string + */ + public function getPidStrAttr($value): mixed + { + return !$value ? '顶级' : $this->where('pid', $value)->value('menu_name'); + } + + /** + * 默认条件查询器 + * + * @param \think\db\Query $query + */ + public function searchDefaultAttr(Query $query) + { + $query->where(['is_show' => 1, 'access' => 1]); + } + + /** + * 是否显示搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIsShowAttr(Query $query, $value) + { + if ($value != '') { + $query->where('is_show', $value); + } + } + + /** + * 是否删除搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIsDelAttr(Query $query, $value) + { + $query->where('delete_time', $value); + } + + /** + * Pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + $query->where('pid', $value ?? '-1'); + } + + /** + * 规格搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRuleAttr(Query $query, $value) + { + $query->whereIn('id', $value)->where('delete_time', null); + } + + /** + * 搜索菜单 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchKeywordAttr(Query $query, $value) + { + if ($value != '') { + $query->whereLike('menu_name|id|pid', "%$value%"); + } + } + + /** + * 方法搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchActionAttr(Query $query, $value) + { + $query->where('action', $value); + } + + /** + * 控制器搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchControllerAttr(Query $query, $value) + { + $query->where('controller', lcfirst($value)); + } + + /** + * 访问地址搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchUrlAttr(Query $query, $value) + { + $query->where('api_url', $value); + } + + /** + * 参数搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchParamsAttr(Query $query, $value) + { + $query->where(function ($query) use ($value) { + $query->where('params', $value)->whereOr('params', "'[]'"); + }); + } + + /** + * 权限标识搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchUniqueAttr(Query $query, $value) + { + $query->where('delete_time', null); + if ($value) { + $query->whereIn('id', $value); + } + } + + /** + * 菜单规格搜索 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRouteAttr(Query $query, $value) + { + $query->where('auth_type', 1)->where('delete_time', null); + if ($value) { + $query->whereIn('id', $value); + } + } + + /** + * Id搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIdAttr(Query $query, $value) + { + $query->whereIn('id', $value); + } + + /** + * is_show_path + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIsShowPathAttr(Query $query, $value) + { + $query->where('is_show_path', $value); + } + + /** + * auth_type + * + * @param \think\db\Query $query + * @param $value + */ + public function searchAuthTypeAttr(Query $query, $value) + { + if ($value !== '') { + if ($value == 3) { + $query->whereIn('auth_type', [1, 3]); + } else { + $query->where('auth_type', $value); + } + } + } +} diff --git a/demo/thinkphp/backend/app/model/system/admin/SystemPost.php b/demo/thinkphp/backend/app/model/system/admin/SystemPost.php new file mode 100644 index 0000000000000000000000000000000000000000..994473cd6fa0b4b2e4728e3255173fec71092c3f --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/admin/SystemPost.php @@ -0,0 +1,127 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use phoenix\utils\Str; +use think\db\Query; +use think\Model; + +/** + * 职位管理 + * + * @author Mr.April + * @since 1.0 + */ +class SystemPost extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'post_id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_post'; + + protected array $insert = ['create_time', 'update_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + 'delete_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 生成字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 权限规格状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + if ($value != '') { + $query->where('status', $value ?: 1); + } + } + + /** + * post_code搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPostCodeAttr(Query $query, $value) + { + if (!empty($value)) { + $query->whereLike('post_code', '%' . $value . '%'); + } + } + + /** + * post_name搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPostNameAttr(Query $query, $value) + { + if (!empty($value)) { + $query->whereLike('post_name', '%' . $value . '%'); + } + } + + /** + * 关联部门搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchDeptIdAttr(Query $query, $value) + { + if (!empty($value)) { + $query->where('dept_id', $value); + } + } + + /** + * Pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + $query->where('pid', $value ?? '-1'); + } +} diff --git a/demo/thinkphp/backend/app/model/system/admin/SystemRole.php b/demo/thinkphp/backend/app/model/system/admin/SystemRole.php new file mode 100644 index 0000000000000000000000000000000000000000..9a87389ff6005aec32104c98a4ead4c9ff7c730c --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/admin/SystemRole.php @@ -0,0 +1,117 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use phoenix\utils\Str; +use think\db\Query; +use think\Model; + +/** + * 管理员权限规则 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRole extends BaseModel +{ + use ModelTrait; + + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'role_id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_role'; + + protected array $insert = ['create_time', 'update_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + 'delete_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 生成字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 权限规格状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + if ($value != '') { + $query->where('status', $value ?: 1); + } + } + + /** + * id搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('role_id', $value); + } else { + $query->where('role_id', $value); + } + } + + /** + * 身份管理搜索 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRoleNameAttr(Query $query, $value) + { + if ($value) { + $query->whereLike('role_name', '%' . $value . '%'); + } + } + + /** + * Pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + $query->where('pid', $value ?? '-1'); + } +} diff --git a/demo/thinkphp/backend/app/model/system/admin/SystemRoleDept.php b/demo/thinkphp/backend/app/model/system/admin/SystemRoleDept.php new file mode 100644 index 0000000000000000000000000000000000000000..1ef337befae4e38d7fc316871c9d2ab8f5713648 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/admin/SystemRoleDept.php @@ -0,0 +1,68 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use think\db\Query; + + +/** + * 角色关联组织 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRoleDept extends BaseModel +{ + use ModelTrait; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_role_dept'; + + + /** + * roleId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRoleIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('role_id', $value); + } else { + $query->where('role_id', $value); + } + } + + /** + * menuId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchDeptIdAttr(Query $query, $value) + { + if ($value) { + if (is_array($value)) { + $query->whereIn('dept_id', $value); + } else { + $query->where('dept_id', $value); + } + } + } +} diff --git a/demo/thinkphp/backend/app/model/system/admin/SystemRoleMenu.php b/demo/thinkphp/backend/app/model/system/admin/SystemRoleMenu.php new file mode 100644 index 0000000000000000000000000000000000000000..94e11acc4baf9f2cf49d514abce7e1b50aa010e6 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/admin/SystemRoleMenu.php @@ -0,0 +1,69 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use think\db\Query; + + +/** + * 管理员权限规则 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRoleMenu extends BaseModel +{ + use ModelTrait; + + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_role_menu'; + + + /** + * roleId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRoleIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('role_id', $value); + } else { + $query->where('role_id', $value); + } + } + + /** + * menuId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchMenuIdAttr(Query $query, $value) + { + if ($value) { + if (is_array($value)) { + $query->whereIn('menu_id', $value); + } else { + $query->where('menu_id', $value); + } + } + } +} diff --git a/demo/thinkphp/backend/app/model/system/admin/SystemRolePost.php b/demo/thinkphp/backend/app/model/system/admin/SystemRolePost.php new file mode 100644 index 0000000000000000000000000000000000000000..2b38ad11e1a78ec1b4c8c2d06fbfa816581e89e3 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/admin/SystemRolePost.php @@ -0,0 +1,69 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use think\db\Query; + + +/** + * 角色关联组织 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRolePost extends BaseModel +{ + use ModelTrait; + + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_role_post'; + + + /** + * roleId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRoleIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('role_id', $value); + } else { + $query->where('role_id', $value); + } + } + + /** + * menuId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPostIdAttr(Query $query, $value) + { + if ($value) { + if (is_array($value)) { + $query->whereIn('post_id', $value); + } else { + $query->where('post_id', $value); + } + } + } +} diff --git a/demo/thinkphp/backend/app/model/system/attachment/SystemAttachment.php b/demo/thinkphp/backend/app/model/system/attachment/SystemAttachment.php new file mode 100644 index 0000000000000000000000000000000000000000..1de24bafff6225cb8ba6000b10ad12aa4bbef015 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/attachment/SystemAttachment.php @@ -0,0 +1,100 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\attachment; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use phoenix\utils\Str; +use think\db\Query; +use think\Model; + +/** + * 附件管理模型 + * + * @author Mr.April + * @since 1.0 + */ +class SystemAttachment extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'att_id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_attachment'; + + /** + * ID 生成 + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 图片类型搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchModuleTypeAttr(Query $query, $value) + { + $query->where('module_type', $value ?: 1); + } + + /** + * pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + if ($value) $query->where('pid', $value); + } + + /** + * name模糊搜索 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchLikeNameAttr(Query $query, $value) + { + if ($value) $query->where('name', 'LIKE', "$value%"); + } + + /** + * real_name模糊搜索 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRealNameAttr(Query $query, $value) + { + if ($value != '') $query->where('real_name', 'LIKE', "%$value%"); + } +} diff --git a/demo/thinkphp/backend/app/model/system/attachment/SystemAttachmentCategory.php b/demo/thinkphp/backend/app/model/system/attachment/SystemAttachmentCategory.php new file mode 100644 index 0000000000000000000000000000000000000000..282196ae7b089504834e355944469e3c961a3a1f --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/attachment/SystemAttachmentCategory.php @@ -0,0 +1,79 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\attachment; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use phoenix\utils\Str; +use think\db\Query; +use think\Model; + +/** + * + * 附件管理分类模型 + * @author Mr.April + * @since 1.0 + */ +class SystemAttachmentCategory extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_attachment_category'; + + /** + * ID 生成 + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 附件分类昵称搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchNameAttr(Query $query, $value) + { + if ($value != '') $query->where('name', 'like', '%' . $value . '%'); + } + + /** + * pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + if ($value !== '') $query->where('pid', $value); + } + +} diff --git a/demo/thinkphp/backend/app/model/system/config/SystemConfig.php b/demo/thinkphp/backend/app/model/system/config/SystemConfig.php new file mode 100644 index 0000000000000000000000000000000000000000..5cad4c3f94e1d695314114c1319377c2241f290e --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/config/SystemConfig.php @@ -0,0 +1,119 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\config; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use phoenix\utils\Str; +use think\db\Query; + +/** + * 系统配置模型 + * + * @author Mr.April + * @since 1.0 + */ +class SystemConfig extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_config'; + + /** + * 模型ID触发器 + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 菜单名搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchMenuNameAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('menu_name', $value); + } else { + if (!empty($value)) { + $query->where('menu_name', $value); + } + } + } + + /** + * Info搜索 + * @param \think\db\Query $query + * @param $value + */ + public function searchInfoAttr(Query $query, $value) + { + if (!empty($value)) { + $query->whereLike('info', $value . '%'); + } + } + + /** + * tab id 搜索 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchTabIdAttr(Query $query, $value) + { + if (!empty($value)) { + $query->where('config_tab_id', $value); + } + } + + /** + * 状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + $query->where('status', $value ?: 1); + } + + /** + * value搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchValueAttr(Query $query, $value) + { + $query->where('value', $value); + } +} diff --git a/demo/thinkphp/backend/app/model/system/config/SystemConfigTab.php b/demo/thinkphp/backend/app/model/system/config/SystemConfigTab.php new file mode 100644 index 0000000000000000000000000000000000000000..c7e50028845a1001ccddeb284963a5777282bfe9 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/config/SystemConfigTab.php @@ -0,0 +1,111 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\config; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use phoenix\utils\Str; +use think\db\Query; +use think\Model; + + +/** + * + * 配置分类模型 + * @author Mr.April + * @since 1.0 + */ +class SystemConfigTab extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_config_tab'; + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + if ($value != '') { + $query->where('status', $value); + } + } + + /** + * pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('pid', $value); + } else { + $value && $query->where('pid', $value); + } + } + + /** + * 类型搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchTypeAttr(Query $query, $value) + { + $query->where('status', 1); + if ($value > -1) { + $query->where(['type' => $value, 'pid' => 0]); + } + } + + /** + * 分类名称搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchTitleAttr(Query $query, $value) + { + $query->whereLike('title', '%' . $value . '%'); + } + +} diff --git a/demo/thinkphp/backend/app/model/system/config/SystemGroup.php b/demo/thinkphp/backend/app/model/system/config/SystemGroup.php new file mode 100644 index 0000000000000000000000000000000000000000..1c0c2f78a239c4cfb20c0708e0e8b0a380d09d34 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/config/SystemGroup.php @@ -0,0 +1,69 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\config; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use think\Model; + +/** + * 组合数据配置模型 + * Class SystemGroup + * @package app\model\system\config + */ +class SystemGroup extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * @var string + */ + protected $name = 'system_group'; + + /** + * 配置名搜索器 + * @param Model $query + * @param $value + */ + public function searchConfigNameAttr($query, $value) + { + $query->where('config_name', $value); + } + + /** + * @param Model $query + * @param $value + */ + public function searchTitleAttr($query, $value) + { + if ($value != '') { + $query->whereLIke('id|name|info|config_name', "%$value%"); + } + } + + /** + * 查询分类 + * @param Model $query + * @param $value + */ + public function searchCateIdAttr($query, $value) + { + $query->where('cate_id', $value); + } +} diff --git a/demo/thinkphp/backend/app/model/system/config/SystemGroupData.php b/demo/thinkphp/backend/app/model/system/config/SystemGroupData.php new file mode 100644 index 0000000000000000000000000000000000000000..5ac1122fe8ec25e1850cb218c6d688cdd59a1a53 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/config/SystemGroupData.php @@ -0,0 +1,64 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\config; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use think\Model; + +/** + * 组合数据数据列表模型 + * Class SystemGroupData + * @package app\model\system\config + */ +class SystemGroupData extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * @var string + */ + protected $name = 'system_group_data'; + + /** + * 状态搜索器 + * @param $query + * @param $value + */ + public function searchStatusAttr($query, $value) + { + if ($value != '') { + $query->where('status', $value); + } + } + + /** + * Gid搜索器 + * @param Model $query + * @param $value + */ + public function searchGidAttr($query, $value) + { + if (is_array($value)) { + $query->whereIn('gid', $value); + } else { + $query->where('gid', $value); + } + } +} diff --git a/demo/thinkphp/backend/app/model/system/config/SystemStorage.php b/demo/thinkphp/backend/app/model/system/config/SystemStorage.php new file mode 100644 index 0000000000000000000000000000000000000000..c30cd6665c1478ba0ae70e60aa745c5175441fb1 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/config/SystemStorage.php @@ -0,0 +1,69 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\config; + + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; + +/** + * 云存储 + * Class SystemStorage + * @package app\model\system\config + */ +class SystemStorage extends BaseModel +{ + + /** + * @var string + */ + protected $name = 'system_storage'; + + /** + * @var string + */ + protected $pk = 'id'; + + /** + * @var bool + */ + protected $autoWriteTimestamp = false; + + /** + * @param $query + * @param $value + */ + public function searchNameAttr($query, $value) + { + $query->where('name', $value); + } + + /** + * 类型搜索器 + * @param $query + * @param $value + */ + public function searchTypeAttr($query, $value) + { + if ($value) $query->where('type', $value); + } + + /** + * 状态搜索器 + * @param $query + * @param $value + */ + public function searchStatusAttr($query, $value) + { + if ($value !== '') $query->where('status', $value); + } +} diff --git a/demo/thinkphp/backend/app/model/system/crontab/SystemCrontab.php b/demo/thinkphp/backend/app/model/system/crontab/SystemCrontab.php new file mode 100644 index 0000000000000000000000000000000000000000..f1a7a67a1aca0106f8fb0990ae2f35325f4ba9f3 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/crontab/SystemCrontab.php @@ -0,0 +1,51 @@ + 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + 'delete_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + +} diff --git a/demo/thinkphp/backend/app/model/system/dict/SystemDict.php b/demo/thinkphp/backend/app/model/system/dict/SystemDict.php new file mode 100644 index 0000000000000000000000000000000000000000..e0e15c346cd05c97c1b61a7affd6ce998eeca956 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/dict/SystemDict.php @@ -0,0 +1,126 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\dict; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use phoenix\utils\Str; +use think\db\Query; +use think\Model; + +/** + * 字典选项模型 + * Class SystemLog + * + * @package app\model\system\log + */ +class SystemDict extends BaseModel +{ + use ModelTrait; + + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_options'; + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + protected array $insert = ['create_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + ]; + + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + protected function setCreateTimeAttr(): int + { + return time(); + } + + /** + * name搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchNameAttr(Query $query, $value) + { + if ($value !== '') { + $query->whereLike('name', $value . '%'); + } + } + + /** + * Id搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIdAttr(Query $query, $value) + { + if ($value !== '') { + if (in_array($value)) { + $query->whereIn('id', $value); + + } else { + $query->where('id', $value); + } + } + } + + /** + * ip搜索器 + * + * @param Model $query + * @param $value + */ + public function searchIpAttr($query, $value) + { + if ($value !== '') { + $query->where('ip', 'LIKE', "%$value%"); + } + } + + /** + * 管理员id搜索器 + * + * @param Model $query + * @param $value + */ + public function searchAdminIdAttr($query, $value) + { + if (!empty($value)) { + $query->whereIn('admin_id', $value); + } + } +} diff --git a/demo/thinkphp/backend/app/model/system/lang/LangCode.php b/demo/thinkphp/backend/app/model/system/lang/LangCode.php new file mode 100644 index 0000000000000000000000000000000000000000..02b8e9daff756de85a798e7e8773137546672ef0 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/lang/LangCode.php @@ -0,0 +1,84 @@ +{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * type_id搜索器 + * + * @param $query + * @param $value + */ + public function searchTypeIdAttr($query, $value) + { + if ($value !== '' && $value !== 0) $query->where('type_id', $value); + } + + /** + * code搜索器 + * + * @param $query + * @param $value + */ + public function searchCodeAttr($query, $value) + { + if ($value !== '') $query->where('code', 'like', '%' . $value . '%'); + } + + /** + * remarks搜索器 + * + * @param $query + * @param $value + */ + public function searchRemarksAttr($query, $value) + { + if ($value !== '') $query->where('remarks|code|lang_explain', 'like', '%' . $value . '%'); + } + + /** + * is_admin搜索器 + * + * @param $query + * @param $value + */ + public function searchIsAdminAttr($query, $value) + { + if ($value !== '') $query->where('is_admin', $value); + } +} diff --git a/demo/thinkphp/backend/app/model/system/lang/LangCountry.php b/demo/thinkphp/backend/app/model/system/lang/LangCountry.php new file mode 100644 index 0000000000000000000000000000000000000000..bcdaa8c415844fd2054a09bab5ae4f1904c058fd --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/lang/LangCountry.php @@ -0,0 +1,62 @@ +{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * type_id搜索器 + * + * @param $query + * @param $value + */ + public function searchTypeIdAttr($query, $value) + { + if ($value !== '') $query->where('type_id', $value); + } + + /** + * code/name搜索器 + * + * @param $query + * @param $value + */ + public function searchKeywordAttr($query, $value) + { + if ($value !== '') $query->where('name|code', 'like', '%' . $value . '%'); + } +} diff --git a/demo/thinkphp/backend/app/model/system/lang/LangType.php b/demo/thinkphp/backend/app/model/system/lang/LangType.php new file mode 100644 index 0000000000000000000000000000000000000000..861d237f01f62e5cb8095a5a8ac7cc1f2d816529 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/lang/LangType.php @@ -0,0 +1,94 @@ + 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * is_del搜索器 + * + * @param $query + * @param $value + */ + public function searchIsDelAttr($query, $value) + { + if ($value !== '') $query->where('is_del', $value); + } + + /** + * status搜索器 + * + * @param $query + * @param $value + */ + public function searchStatusAttr($query, $value) + { + if ($value !== '') $query->where('status', $value); + } + + /** + * language-name搜索器 + * + * @param $query + * @param $value + */ + public function searchLanguageNameAttr($query, $value) + { + if ($value !== '') $query->where('language_name', 'like', $value . '%'); + } + + /** + * file_name 搜索器 + * + * @param $query + * @param $value + */ + public function searchFileNameAttr($query, $value) + { + if ($value !== '') $query->where('file_name', $value); + } + +} diff --git a/demo/thinkphp/backend/app/model/system/log/SystemFile.php b/demo/thinkphp/backend/app/model/system/log/SystemFile.php new file mode 100644 index 0000000000000000000000000000000000000000..c87e93eae29e3ecc1d46d8fea3fe7f3ad85ba247 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/log/SystemFile.php @@ -0,0 +1,38 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\log; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; + +/** + * 文件校验模型 + * Class SystemFile + * @package app\model\system\log + */ +class SystemFile extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * @var string + */ + protected $name = 'system_file'; + +} diff --git a/demo/thinkphp/backend/app/model/system/log/SystemFileInfo.php b/demo/thinkphp/backend/app/model/system/log/SystemFileInfo.php new file mode 100644 index 0000000000000000000000000000000000000000..5323efe533c27be9aa61f77a52db608047f9abda --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/log/SystemFileInfo.php @@ -0,0 +1,28 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\log; + +use phoenix\basic\BaseModel; +use phoenix\traits\ModelTrait; +use phoenix\utils\Str; +use think\Model; + +/** + * 日志模型 + * Class SystemLog + * + * @package app\model\system\log + */ +class SystemLog extends BaseModel +{ + use ModelTrait; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_log'; + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + protected array $insert = ['create_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + protected function setCreateTimeAttr(): int + { + return time(); + } + + /** + * 访问方式搜索器 + * + * @param Model $query + * @param $value + */ + public function searchPagesAttr($query, $value) + { + if ($value !== '') { + $query->whereLike('page', '%' . $value . '%'); + } + } + + /** + * 访问路径搜索器 + * + * @param Model $query + * @param $value + */ + public function searchPathAttr($query, $value) + { + if ($value !== '') { + $query->whereLike('path', '%' . $value . '%'); + } + } + + /** + * ip搜索器 + * + * @param Model $query + * @param $value + */ + public function searchIpAttr($query, $value) + { + if ($value !== '') { + $query->where('ip', 'LIKE', "%$value%"); + } + } + + /** + * 管理员id搜索器 + * + * @param Model $query + * @param $value + */ + public function searchAdminIdAttr($query, $value) + { + if (!empty($value)) { + $query->whereIn('admin_id', $value); + } + } +} diff --git a/demo/thinkphp/backend/app/model/system/route/SystemRoute.php b/demo/thinkphp/backend/app/model/system/route/SystemRoute.php new file mode 100644 index 0000000000000000000000000000000000000000..54ec5ca60ebb6808d7a0c32917222775554d4281 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/route/SystemRoute.php @@ -0,0 +1,89 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\model\system\route; + + +use phoenix\basic\BaseModel; +use think\model\concern\SoftDelete; + +/** + * Class SystemRoute + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + * @package app\model\system + */ +class SystemRoute extends BaseModel +{ + + use SoftDelete; + + /** + * @var string + */ + protected $name = 'system_route'; + + /** + * @var string + */ + protected $key = 'id'; + + public function searchNameLikeAttr($query, $value) + { + if ('' !== $value) { + $query->where('name|path', 'LIKE', '%' . $value . '%'); + } + } + + public function setRequestAttr($value): bool|string + { + return json_encode($value); + } + + public function getRequestAttr($value) + { + return json_decode($value, true); + } + + public function setResponseAttr($value): bool|string + { + return json_encode($value); + } + + public function getResponseAttr($value) + { + return json_decode($value, true); + } + + public function setRequestExampleAttr($value): bool|string + { + return json_encode($value); + } + + public function getRequestExampleAttr($value) + { + return json_decode($value, true); + } + + + public function setResponseExampleAttr($value): bool|string + { + return json_encode($value); + } + + public function getResponseExampleAttr($value) + { + return json_decode($value, true); + } +} diff --git a/demo/thinkphp/backend/app/model/system/route/SystemRouteCate.php b/demo/thinkphp/backend/app/model/system/route/SystemRouteCate.php new file mode 100644 index 0000000000000000000000000000000000000000..1d51f1674b32d2fe52e137e0a9e0ce721b21e1f4 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/route/SystemRouteCate.php @@ -0,0 +1,44 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\model\system\route; + + +use phoenix\basic\BaseModel; + +class SystemRouteCate extends BaseModel +{ + + /** + * @var string + */ + protected $name = 'system_route_cate'; + + /** + * @var string + */ + protected $pk = 'id'; + + protected $autoWriteTimestamp = false; + + /** + * @return \think\model\relation\HasMany + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function children() + { + return $this->hasMany(SystemRoute::class, 'cate_id', 'id')->field(['id', 'type', 'cate_id', 'name', 'name as real_name', 'path', 'method'])->order('create_time desc'); + } +} diff --git a/demo/thinkphp/backend/app/model/system/setting/SystemConfig.php b/demo/thinkphp/backend/app/model/system/setting/SystemConfig.php new file mode 100644 index 0000000000000000000000000000000000000000..85857357d0c19f20e78d5dbe19fbbe0946f2dfb1 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/setting/SystemConfig.php @@ -0,0 +1,47 @@ +whereLike('name', $value . '%'); + + } + } +} diff --git a/demo/thinkphp/backend/app/model/system/setting/SystemOrganization.php b/demo/thinkphp/backend/app/model/system/setting/SystemOrganization.php new file mode 100644 index 0000000000000000000000000000000000000000..1c3304422425bc1415ada80c69427aac50face3e --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/setting/SystemOrganization.php @@ -0,0 +1,73 @@ +hasMany(SystemUserPost::class, 'org_id'); + } + + /** + * 新增前添加字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Uuid::uuid4()->toString(); + $model->{$model->pk} = $uuid; + } + + /** + * 部门Aidin搜索器 + * + * @param $query + * @param $value + * @param $data + */ + public function searchOrgIdInAttr($query, $value, $data) + { + if (!empty($value)) { + $query->whereIn('org_id', 'in', $value); + } + } +} diff --git a/demo/thinkphp/backend/app/model/system/setting/SystemPermission.php b/demo/thinkphp/backend/app/model/system/setting/SystemPermission.php new file mode 100644 index 0000000000000000000000000000000000000000..8636db936410c96f1546fdfa4dc4cdc9560c690f --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/setting/SystemPermission.php @@ -0,0 +1,281 @@ +where('parent_id', $menuId)->select(); + foreach ($subMenus as $subMenu) { + $this->deleteSubMenu($subMenu['id']); + $subMenu->delete(); + } + } + + /** + * 参数修改器 + * + * @param $value + * + * @return false|string + */ + public function setParamsAttr($value) + { + $value = $value ? explode('/', $value) : []; + $params = array_chunk($value, 2); + $data = []; + foreach ($params as $param) { + if (isset($param[0]) && isset($param[1])) $data[$param[0]] = $param[1]; + } + return json_encode($data); + } + + /** + * 参数获取器 + * + * @param $_value + * + * @return mixed + */ + public function getParamsAttr($_value) + { + return json_decode($_value, true); + } + + /** + * pid获取器 + * + * @param $value + * + * @return mixed|string + */ + public function getPidStrAttr($value) + { + return !$value ? '顶级' : $this->where('parent_id', $value)->value('menu_name'); + } + + /** + * 默认条件查询器 + * + * @param Model $query + * @param $value + */ + public function searchDefaultAttr($query) + { + $query->where(['is_show' => 1, 'status' => 1]); + } + + /** + * 是否显示搜索器 + * + * @param Model $query + * @param $value + */ + public function searchIsShowAttr($query, $value) + { + if ($value != '') { + $query->where('is_show', $value); + } + } + + /** + * 是否删除搜索器 + * + * @param Model $query + * @param $value + */ + public function searchIsDelAttr($query, $value) + { + $query->where('delete_time', $value); + } + + /** + * Pid搜索器 + * + * @param Model $query + * @param $value + */ + public function searchPidAttr($query, $value) + { + $query->where('parent_id', $value ?? '-1'); + } + + /** + * 规格搜索器 + * + * @param Model $query + * @param $value + */ + public function searchRuleAttr($query, $value) + { + $query->whereIn('permission_id', $value)->where('delete_time', null)->whereOr('parent_id', '-1'); + } + + /** + * 搜索菜单 + * + * @param Model $query + * @param $value + */ + public function searchKeywordAttr($query, $value) + { + if ($value != '') { + $query->whereLike('menu_name|permission_id|parent_id', "%$value%"); + } + } + + /** + * 方法搜索器 + * + * @param Model $query + * @param $value + */ + public function searchActionAttr($query, $value) + { + $query->where('action', $value); + } + + /** + * 控制器搜索器 + * + * @param Model $query + * @param $value + */ + public function searchControllerAttr($query, $value) + { + $query->where('controller', lcfirst($value)); + } + + /** + * 访问地址搜索器 + * + * @param Model $query + * @param $value + */ + public function searchUrlAttr($query, $value) + { + $query->where('api_path', $value); + } + + /** + * 参数搜索器 + * + * @param Model $query + * @param $value + */ + public function searchParamsAttr($query, $value) + { + $query->where(function ($query) use ($value) { + $query->where('params', $value)->whereOr('params', "'[]'"); + }); + } + + /** + * 权限标识搜索器 + * + * @param Model $query + * @param $value + */ + public function searchUniqueAttr($query, $value) + { + $query->where('delete_time', null); + if ($value) { + $query->whereIn('permission_id', $value); + } + } + + /** + * 菜单规格搜索 + * + * @param Model $query + * @param $value + */ + public function searchRouteAttr($query, $value) + { + $query->where('auth_type', 1);//菜单 + if ($value) { + $query->whereIn('permission_id', $value); + } + } + + /** + * Id搜索器 + * + * @param Model $query + * @param $value + */ + public function searchIdAttr($query, $value) + { + $query->whereIn('permission_id', $value); + } + + /** + * is_show_path + * + * @param Model $query + * @param $value + */ + public function searchIsShowPathAttr($query, $value) + { + $query->where('is_show_path', $value); + } + + /** + * auth_type + * + * @param Model $query + * @param $value + */ + public function searchAuthTypeAttr($query, $value) + { + if ($value !== '') { + if ($value == 3) { + $query->whereIn('auth_type', [1, 3]); + } else { + $query->where('auth_type', $value); + } + } + } + +} diff --git a/src/libs/traits/UuidAutoModelTrait.php b/demo/thinkphp/backend/app/model/system/setting/SystemPost.php similarity index 33% rename from src/libs/traits/UuidAutoModelTrait.php rename to demo/thinkphp/backend/app/model/system/setting/SystemPost.php index 30642e410c8bfd6634e9490f4d7f9eff3dc16253..ca55b0c15f08102a3430be199eef53d71e5ca4bb 100644 --- a/src/libs/traits/UuidAutoModelTrait.php +++ b/demo/thinkphp/backend/app/model/system/setting/SystemPost.php @@ -1,25 +1,34 @@ {$model->pk} = $uuid; } + /** + * 定义与UserPost模型的一对多关联关系0808 + * + * @return \think\model\relation\HasMany + */ + public function userPosts(): HasMany + { + return $this->hasMany(SystemUserPost::class, 'post_id'); + } + } diff --git a/demo/thinkphp/backend/app/model/system/setting/SystemRoleOrganization.php b/demo/thinkphp/backend/app/model/system/setting/SystemRoleOrganization.php new file mode 100644 index 0000000000000000000000000000000000000000..8022e41cd894b66dd29a068551ffa723a7bd52ea --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/setting/SystemRoleOrganization.php @@ -0,0 +1,27 @@ +whereIn('role_id', $value); + } + } + +} diff --git a/demo/thinkphp/backend/app/model/system/setting/SystemRolePost.php b/demo/thinkphp/backend/app/model/system/setting/SystemRolePost.php new file mode 100644 index 0000000000000000000000000000000000000000..beeaf1fa85da0856892aa7be711cd93dd7abeb0d --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/setting/SystemRolePost.php @@ -0,0 +1,29 @@ +whereIn('post_id',$value); + } + } + +} diff --git a/demo/thinkphp/backend/app/model/system/setting/SystemRoles.php b/demo/thinkphp/backend/app/model/system/setting/SystemRoles.php new file mode 100644 index 0000000000000000000000000000000000000000..a08838e095524b0b685bd82abfae71512badf24c --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/setting/SystemRoles.php @@ -0,0 +1,77 @@ + 'string', + 'role_name' => 'string', + 'role_code' => 'int', + 'parent_id' => 'string', + 'status' => 'int', + 'weight' => 'int', + 'icon' => 'string', + 'is_super' => 'int', + 'create_time' => 'datetime', + 'update_time' => 'datetime', + 'remarks' => 'string', + ]; + + // 设置字段自动转换类型 + protected $type = []; + + // 设置废弃字段 + protected $disuse = []; + + /** + * 新增前添加字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Uuid::uuid4()->toString(); + $model->{$model->pk} = $uuid; + } + +} diff --git a/demo/thinkphp/backend/app/model/system/setting/SystemUser.php b/demo/thinkphp/backend/app/model/system/setting/SystemUser.php new file mode 100644 index 0000000000000000000000000000000000000000..90375e19f14876c50c16ed2f74a5838858685a49 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/setting/SystemUser.php @@ -0,0 +1,180 @@ +{$model->pk}) ? $model->{$model->pk} : Uuid::uuid4()->toString(); + $model->{$model->pk} = $uuid; + } + + /** + * UserPost模型的一对多关联关系 + * + * @return \think\model\relation\HasMany + */ + public function userPosts(): HasMany + { + return $this->hasMany(SystemUserPost::class, 'user_id'); + } + + /** + * UserOrganization 模型的一对多关联关系 + * + * @return \think\model\relation\HasMany + */ + public function userOrgz(): HasMany + { + return $this->hasMany(SystemUserOrganization::class, 'user_id'); + } + + /** + * 用户账号搜索器 + * + * @param \think\db\Query $query + * @param $value + * @param $data + */ + public function searchAccountAttr(Query $query, $value, $data) + { + if (!empty($value)) { + $query->where('account', 'like', $value . '%'); + } + } + + /** + * 用户名搜索器 + * + * @param \think\db\Query $query + * @param $value + * @param $data + */ + public function searchNameAttr(Query $query, $value, $data) + { + if (!empty($value)) { + $query->where('user_name', 'like', $value . '%'); + } + } + + /** + * 权限数据 + * + * @param $value + * + * @return false|string[] + */ + public static function getRolesAttr($value): array|bool + { + return explode(',', $value); + } + + /** + * 管理员级别搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchLevelAttr(Query $query, $value) + { + if (is_array($value)) { + $query->where('level', $value[0], $value[1]); + } else { + $query->where('level', $value); + } + } + + /** + * 管理员账号和姓名搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchAccountLikeAttr(Query $query, $value) + { + if ($value) { + $query->whereLike('account|user_name', '%' . $value . '%'); + } + } + + /** + * 管理员权限搜索器 + * + * @param \think\db\Query $query + * @param $roles + */ + public function searchRolesAttr(Query $query, $roles) + { + if ($roles) { + $query->where("CONCAT(',',roles,',') LIKE '%,$roles,%'"); + } + } + + /** + * 是否删除搜索器 + * + * @param \think\db\Query $query + */ + public function searchIsDelAttr(Query $query) + { + $query->where('delete_time', null); + } + + /** + * 状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + if ($value != '' && $value != null) { + $query->where('is_enable', $value); + } + } + + /** + * 手机号搜索器 + * @param $query + * @param $value + * @param $data + */ + public function searchPhoneAttr($query, $value, $data) + { + if ($value != '' && $value != null) { + $query->where('cell_phone_number', $value); + } + } +} diff --git a/demo/thinkphp/backend/app/model/system/setting/SystemUserOrganization.php b/demo/thinkphp/backend/app/model/system/setting/SystemUserOrganization.php new file mode 100644 index 0000000000000000000000000000000000000000..db59853536c925a15fa8e50fdd4fbbe42f424377 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/setting/SystemUserOrganization.php @@ -0,0 +1,26 @@ +belongsTo(SystemOrganization::class, 'org_id'); + } + +} diff --git a/demo/thinkphp/backend/app/model/system/setting/SystemUserPost.php b/demo/thinkphp/backend/app/model/system/setting/SystemUserPost.php new file mode 100644 index 0000000000000000000000000000000000000000..0951643d6bfe1e35700fb71c13733bb66fe2f4b7 --- /dev/null +++ b/demo/thinkphp/backend/app/model/system/setting/SystemUserPost.php @@ -0,0 +1,25 @@ +belongsTo(SystemPost::class, 'post_id'); + } +} diff --git a/demo/thinkphp/backend/app/provider.php b/demo/thinkphp/backend/app/provider.php new file mode 100644 index 0000000000000000000000000000000000000000..73d99fadbc81a77e413f9ab797daa9a8b92afbe0 --- /dev/null +++ b/demo/thinkphp/backend/app/provider.php @@ -0,0 +1,9 @@ + Request::class, + 'think\exception\Handle' => ExceptionHandle::class, +]; diff --git a/demo/thinkphp/backend/app/service.php b/demo/thinkphp/backend/app/service.php new file mode 100644 index 0000000000000000000000000000000000000000..db1ee6a89fadf0adec23808a3272bb3724a412e5 --- /dev/null +++ b/demo/thinkphp/backend/app/service.php @@ -0,0 +1,9 @@ + +// +---------------------------------------------------------------------- + +namespace app\services; + +use phoenix\utils\JwtAuth; +use think\facade\Config; +use think\facade\Db; +use think\facade\Route as Url; +use think\Model; + +/** + * Class BaseServices + * + * @package app\services + * @method array|Model|null get($id, ?array $field = []) 获取一条数据 + * @method array|Model|null getOne(array $where, ?string $field = '*') 获取一条数据(不走搜素器) + * @method string|null batchUpdate(array $ids, array $data, ?string $key = null) 批量修改 + * @method float sum(array $where, string $field, bool $search = false) 求和 + * @method mixed update($id, array $data, ?string $field = '') 修改数据 + * @method bool be($map, string $field = '') 查询一条数据是否存在 + * @method mixed value(array $where, string $field) 获取指定条件下的数据 + * @method int count(array $where = []) 读取数据条数 + * @method int getCount(array $where = []) 获取某些条件总数(不走搜素器) + * @method array getColumn(array $where, string $field, string $key = '') 获取某个字段数组(不走搜素器) + * @method mixed delete($id, ?string $key = null) 删除 + * @method mixed save(array $data) 保存数据 + * @method mixed saveAll(array $data) 批量保存数据 + * @method Model selectList(array $where, string $field = '*', int $page = 0, int $limit = 0, string $order = '', array $with = [], bool $search = false) 获取列表 + * @method bool bcInc($key, string $incField, string $inc, string $keyField = null, int $acc = 2) 高精度加法 + * @method bool bcDec($key, string $decField, string $dec, string $keyField = null, int $acc = 2) 高精度 减法 + * @method mixed decStockIncSales(array $where, int $num, string $stock = 'stock', string $sales = 'sales') 减库存加销量 + * @method mixed incStockDecSales(array $where, int $num, string $stock = 'stock', string $sales = 'sales') 加库存减销量 + */ +abstract class BaseServices +{ + + /** + * 模型注入 + * + * @var object + */ + protected object $dao; + + /** + * @return \phoenix\utils\Cache + */ + public function cacheDriver(): \phoenix\utils\Cache + { + return new \phoenix\utils\Cache($this->dao->getTableName()); + } + + /** + * 获取分页配置 + * + * @param bool $isPage + * @param bool $isRelieve + * + * @return int[] + */ + public function getPageValue(bool $isPage = true, bool $isRelieve = true): array + { + $page = $limit = 0; + if ($isPage) { + $page = app()->request->param(Config::get('database.page.pageKey', 'page') . '/d', 0); + $limit = app()->request->param(Config::get('database.page.limitKey', 'limit') . '/d', 0); + } + $limitMax = Config::get('database.page.limitMax'); + $defaultLimit = Config::get('database.page.defaultLimit', 10); + if ($limit > $limitMax && $isRelieve) { + $limit = $limitMax; + } + return [(int)$page, (int)$limit, (int)$defaultLimit,(int)$limitMax]; + } + + /** + * 数据库事务操作 + * + * @param callable $closure + * @param bool $isTran + * + * @return mixed + */ + public function transaction(callable $closure, bool $isTran = true): mixed + { + return $isTran ? DB::transaction($closure) : $closure(); + } + + /** + * 创建token + * + * @param int|string $id + * @param string $type + * @param string $pwd + * + * @return array + */ + public function createToken(int|string $id, string $type, string $pwd = ''): array + { + /** @var JwtAuth $jwtAuth */ + $jwtAuth = app()->make(JwtAuth::class); + return $jwtAuth->createToken($id, $type, ['pwd' => md5($pwd)]); + } + + /** + * 获取路由地址 + * + * @param string $path + * @param array $params + * @param bool $suffix + * @param bool $isDomain + * + * @return \think\route\Url + */ + public function url(string $path, array $params = [], bool $suffix = false, bool $isDomain = false): \think\route\Url + { + return Url::buildUrl($path, $params)->suffix($suffix)->domain($isDomain)->build(); + } + + /** + * 密码hash加密 + * + * @param string $password + * + * @return false|string|null + */ + public function passwordHash(string $password) + { + return password_hash($password, PASSWORD_BCRYPT); + } + + /** + * @param $name + * @param $arguments + * + * @return mixed + */ + public function __call($name, $arguments) + { + // TODO: Implement __call() method. + return call_user_func_array([$this->dao, $name], $arguments); + } +} diff --git a/demo/thinkphp/backend/app/services/other/CacheServices.php b/demo/thinkphp/backend/app/services/other/CacheServices.php new file mode 100644 index 0000000000000000000000000000000000000000..78681537a575332aba0c61a5985d727adfd58f9a --- /dev/null +++ b/demo/thinkphp/backend/app/services/other/CacheServices.php @@ -0,0 +1,103 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\other; + + +use app\dao\other\CacheDao; +use app\services\BaseServices; + +/** + * 数据库表缓存 + * Class CacheServices + * @package app\services\other + * @method delectDeOverdueDbCache() 删除过期缓存 + */ +class CacheServices extends BaseServices +{ + + public function __construct(CacheDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取数据缓存 + * @param string $key + * @param $default 默认值不存在则写入 + * @param int $expire + * @return mixed|null + */ + public function getDbCache(string $key, $default, int $expire = 0) + { + $this->delectDeOverdueDbCache(); + $result = $this->dao->value(['key' => $key], 'result'); + if ($result) { + return json_decode($result, true); + } else { + if ($default instanceof \Closure) { + // 获取缓存数据 + $value = $default(); + if ($value) { + $this->setDbCache($key, $value, $expire); + return $value; + } + } else { + $this->setDbCache($key, $default, $expire); + return $default; + } + return null; + } + + } + + /** + * 设置数据缓存存在则更新,没有则写入 + * @param string $key + * @param string | array $result + * @param int $expire + * @return void + */ + public function setDbCache(string $key, $result, $expire = 0) + { + $this->delectDeOverdueDbCache(); + $addTime = $expire ? time() + $expire : 0; + if ($this->dao->count(['key' => $key])) { + return $this->dao->update($key, [ + 'result' => json_encode($result), + 'expire_time' => $addTime, + 'add_time' => time() + ], 'key'); + } else { + return $this->dao->save([ + 'key' => $key, + 'result' => json_encode($result), + 'expire_time' => $addTime, + 'add_time' => time() + ]); + } + } + + + /** + * 删除某个缓存 + * @param string $key + * @return false|mixed + */ + public function delectDbCache(string $key = '') + { + if ($key) + return $this->dao->delete($key, 'key'); + else + return false; + } + +} diff --git a/demo/thinkphp/backend/app/services/other/UploadService.php b/demo/thinkphp/backend/app/services/other/UploadService.php new file mode 100644 index 0000000000000000000000000000000000000000..f6ffecefd5d12bae79f1e224c1595577ccb90015 --- /dev/null +++ b/demo/thinkphp/backend/app/services/other/UploadService.php @@ -0,0 +1,160 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\other; + +use app\services\system\config\SystemStorageServices; +use phoenix\exceptions\UploadException; +use phoenix\services\CacheService; +use phoenix\services\SystemConfigService; +use phoenix\services\upload\Upload; +use phoenix\utils\DownloadImage; + +/** + * Class UploadService + * @package crmeb\services + */ +class UploadService +{ + + /** + * @var array + */ + protected static $upload = []; + + /** + * @param null $type + * @return Upload|mixed + */ + public static function init($type = null) + { + if (is_null($type)) { + $type = (int)sys_config('upload_type', 1); + } + if (isset(self::$upload['upload_' . $type])) { + return self::$upload['upload_' . $type]; + } + $type = (int)$type; + $config = []; + switch ($type) { + case 2://七牛 + $config = [ + 'accessKey' => sys_config('qiniu_accessKey'), + 'secretKey' => sys_config('qiniu_secretKey'), + ]; + break; + case 3:// oss 阿里云 + $config = [ + 'accessKey' => sys_config('accessKey'), + 'secretKey' => sys_config('secretKey'), + ]; + break; + case 4:// cos 腾讯云 + $config = [ + 'accessKey' => sys_config('tengxun_accessKey'), + 'secretKey' => sys_config('tengxun_secretKey'), + 'appid' => sys_config('tengxun_appid'), + ]; + break; + case 5://京东云 + $config = [ + 'accessKey' => sys_config('jd_accessKey'), + 'secretKey' => sys_config('jd_secretKey'), + 'storageRegion' => sys_config('jd_storageRegion'), + ]; + break; + case 6://华为云 + $config = [ + 'accessKey' => sys_config('hw_accessKey'), + 'secretKey' => sys_config('hw_secretKey'), + ]; + break; + case 7://天翼云 + $config = [ + 'accessKey' => sys_config('ty_accessKey'), + 'secretKey' => sys_config('ty_secretKey'), + ]; + break; + case 1: + break; + default: + throw new UploadException(400733); + } + + //除了本地存储其他都去获取配置信息 + if (1 !== $type) { + /** @var SystemStorageServices $make */ + $make = app()->make(SystemStorageServices::class); + $res = $make->getConfig($type); + $config['uploadUrl'] = $res['domain']; + $config['storageName'] = $res['name']; + if (5 !== $type) $config['storageRegion'] = $res['region']; + $config['cdn'] = $res['cdn']; + } + + $thumb = SystemConfigService::more(['thumb_big_height', 'thumb_big_width', 'thumb_mid_height', 'thumb_mid_width', 'thumb_small_height', 'thumb_small_width',]); + $water = SystemConfigService::more([ + 'image_watermark_status', + 'watermark_type', + 'watermark_image', + 'watermark_opacity', + 'watermark_position', + 'watermark_rotate', + 'watermark_text', + 'watermark_text_angle', + 'watermark_text_color', + 'watermark_text_size', + 'watermark_x', + 'watermark_y']); + $config = array_merge($config, ['thumb' => $thumb], ['water' => $water]); + return self::$upload['upload_' . $type] = new Upload($type, $config); + } + + /** + * 生辰缩略图水印实例化 + * @param string $filePath + * @param bool $is_remote_down + * @return Upload + */ + public static function getOssInit(string $filePath, bool $is_remote_down = false) + { + //本地 + $uploadUrl = sys_config('site_url'); + if ($uploadUrl && strpos($filePath, $uploadUrl) !== false) { + $filePath = explode($uploadUrl, $filePath)[1] ?? ''; + return self::init(1)->setFilepath($filePath); + } + $fileArr = parse_url($filePath); + $fileHost = $fileArr['scheme'] . '://' . $fileArr['host']; + /** @var SystemStorageServices $storageServices */ + $storageServices = app()->make(SystemStorageServices::class); + $storageArr = CacheService::remember('storage_list', function () use ($storageServices) { + return $storageServices->selectList([], 'domain,type')->toArray(); + }); + foreach ($storageArr as $item) { + if ($fileHost == $item['domain']) { + return self::init($item['type'])->setFilepath($filePath); + } + } + //远程图片 下载到本地处理 + if ($is_remote_down) { + try { + /** @var DownloadImage $down */ + $down = app()->make(DownloadImage::class); + $data = $down->path('thumb_water')->downloadImage($filePath); + $filePath = $data['path'] ?? ''; + } catch (\Throwable $e) { + //下载失败 传入原地址 + } + } + return self::init(1)->setFilepath($filePath); + } +} diff --git a/demo/thinkphp/backend/app/services/system/admin/SystemAdminDeptServices.php b/demo/thinkphp/backend/app/services/system/admin/SystemAdminDeptServices.php new file mode 100644 index 0000000000000000000000000000000000000000..eba564396ca1be623c6a25ec7d1ea0290c96acd5 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/admin/SystemAdminDeptServices.php @@ -0,0 +1,45 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\SystemAdminDeptDao; +use app\Request; +use app\services\BaseServices; +use phoenix\exceptions\AdminException; +use phoenix\exceptions\AuthException; + +/** + * Class SystemRoleServices + * + * @package app\services\system\admin + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取数据 + */ +class SystemAdminDeptServices extends BaseServices +{ + + /** + * 当前管理员权限缓存前缀 + */ + const ADMIN_RULES_LEVEL = 'Admin_admin_dept_level_'; + + /** + * SystemRoleServices constructor. + * + * @param \app\dao\system\admin\SystemAdminDeptDao $dao + */ + public function __construct(SystemAdminDeptDao $dao) + { + $this->dao = $dao; + } +} diff --git a/demo/thinkphp/backend/app/services/system/admin/SystemAdminPostServices.php b/demo/thinkphp/backend/app/services/system/admin/SystemAdminPostServices.php new file mode 100644 index 0000000000000000000000000000000000000000..4872f80c93a773b5a6ed233350a375b0cac0ad8f --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/admin/SystemAdminPostServices.php @@ -0,0 +1,46 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\SystemAdminPostDao; +use app\Request; +use app\services\BaseServices; +use phoenix\exceptions\AdminException; +use phoenix\exceptions\AuthException; + +/** + * Class SystemRoleServices + * + * @package app\services\system\admin + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取数据 + */ +class SystemAdminPostServices extends BaseServices +{ + + /** + * 当前管理员权限缓存前缀 + */ + const ADMIN_RULES_LEVEL = 'Admin_admin_post_level_'; + + /** + * SystemRoleServices constructor. + * + * @param \app\dao\system\admin\SystemAdminPostDao $dao + */ + public function __construct(SystemAdminPostDao $dao) + { + $this->dao = $dao; + } + +} diff --git a/demo/thinkphp/backend/app/services/system/admin/SystemAdminServices.php b/demo/thinkphp/backend/app/services/system/admin/SystemAdminServices.php new file mode 100644 index 0000000000000000000000000000000000000000..9b074bdc5a2c09967f12ddd9600d394ede8f2c5d --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/admin/SystemAdminServices.php @@ -0,0 +1,614 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +//use app\jobs\CheckQueueJob; +//use app\services\BaseServices; +//use app\services\order\StoreOrderServices; +//use app\services\product\product\StoreProductReplyServices; +//use app\services\product\product\StoreProductServices; +//use app\services\user\UserExtractServices; +use app\dao\system\admin\SystemAdminDao; +use app\services\BaseServices; +use phoenix\exceptions\AdminException; +use phoenix\services\CacheService; +use phoenix\services\FormBuilder; +use phoenix\services\workerman\ChannelService; +use think\facade\Config; +use think\facade\Event; +use think\Model; + +/** + * 管理员service + * Class SystemAdminServices + * + * @package app\services\system\admin + * @method getAdminIds(int $level) 根据管理员等级获取管理员id + * @method getOrdAdmin(string $field, int $level) 获取低于等级的管理员名称和id + */ +class SystemAdminServices extends BaseServices +{ + + /** + * SystemAdminServices constructor. + * + * @param SystemAdminDao $dao + */ + public function __construct(SystemAdminDao $dao) + { + $this->dao = $dao; + + } + + /** + * 获取管理员详情 + * + * @param string $id + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function find(string $id): array + { + $adminInfo = $this->dao->get($id); + if (!$adminInfo) { + throw new AdminException(100026); + } + + /** @var SystemAdminDeptServices $systemAdminDeptServices */ + $systemAdminDeptServices = app()->make(SystemAdminDeptServices::class); + $adminInfo->dept_id = $systemAdminDeptServices->column(['admin_id' => $id], 'dept_id')[0] ?? ''; + + /** @var SystemAdminPostServices $systemAdminPostServices */ + $systemAdminPostServices = app()->make(SystemAdminPostServices::class); + $adminInfo->post_id = $systemAdminPostServices->column(['admin_id' => $id], 'post_id')[0] ?? ''; + + return $adminInfo->getData(); + } + + /** + * 管理员登陆 + * + * @param string $account + * @param string $password + * + * @return array|bool|Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function verifyLogin(string $account, string $password, $isPwd = true): bool|array|Model + { + $adminInfo = $this->dao->accountByAdmin($account); + if (!$adminInfo) return false; + if ($isPwd) { + if (!password_verify($password, $adminInfo->pwd)) return false; + } + if (!$adminInfo->status) { + throw new AdminException(400595); + } + /** @var SystemAdminDeptServices $systemAdminDeptServices */ + $systemAdminDeptServices = app()->make(SystemAdminDeptServices::class); + $adminInfo->dept_id = $systemAdminDeptServices->column(['admin_id' => $adminInfo->id], 'dept_id')[0] ?? ''; + + /** @var SystemAdminPostServices $systemAdminPostServices */ + $systemAdminPostServices = app()->make(SystemAdminPostServices::class); + $adminInfo->post_id = $systemAdminPostServices->column(['admin_id' => $adminInfo->id], 'post_id')[0] ?? ''; + + if (!empty($adminInfo->dept_id)) { + /** @var SystemRoleDeptServices $systemRoleDeptServices */ + $systemRoleDeptServices = app()->make(SystemRoleDeptServices::class); + $deptRoleId = $systemRoleDeptServices->column(['dept_id' => $adminInfo->dept_id], 'role_id'); + } + + if (!empty($adminInfo->post_id)) { + /** @var SystemRolePostServices $systemRolePostServices */ + $systemRolePostServices = app()->make(SystemRolePostServices::class); + $postRoleId = $systemRolePostServices->column(['post_id' => $adminInfo->post_id], 'role_id'); + } + + $adminInfo->role_id = array_merge_recursive($deptRoleId ?? [], $postRoleId ?? []); + + /** @var SystemRoleMenuServices $systemRoleMenuServices */ + $systemRoleMenuServices = app()->make(SystemRoleMenuServices::class); + $adminInfo->roles = $systemRoleMenuServices->column(['role_id' => $adminInfo->role_id], 'menu_id'); + + $adminInfo->last_time = time(); + $adminInfo->last_ip = app('request')->ip(); + $adminInfo->login_count++; + $adminInfo->save(); + return $adminInfo; + } + + /** + * 文件管理员登陆 + * + * @param string $account + * @param string $password + * + * @return array|Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function verifyFileLogin(string $account, string $password) + { + $adminInfo = $this->dao->accountByAdmin($account); + if (!$adminInfo) { + throw new AdminException(400594); + } + if (!$adminInfo->status) { + throw new AdminException(400595); + } + if (!password_verify($password, $adminInfo->file_pwd)) { + throw new AdminException(400140); + } + $adminInfo->last_time = time(); + $adminInfo->last_ip = app('request')->ip(); + $adminInfo->login_count++; + $adminInfo->save(); + return $adminInfo; + } + + /** + * 后台登陆获取菜单获取token + * + * @param string $account + * @param string $password + * @param string $type + * @param string $key + * + * @return array|bool + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function login(string $account, string $password, string $type, string $key = '', $isPwd = true) + { + $adminInfo = $this->verifyLogin($account, $password, $isPwd); + if (!$adminInfo) return false; + $tokenInfo = $this->createToken($adminInfo->id, $type, $adminInfo->pwd); + + /** @var SystemMenusServices $services */ + $services = app()->make(SystemMenusServices::class); + [$menus, $uniqueAuth] = $services->getMenusList($adminInfo->roles, (int)$adminInfo->level); + + //获取队列状态 + $remind = Config::get('app.console_remind', false); + if ($remind) { + [$queue, $timer] = Event::until('AdminLoginListener', [$key]); + } + return [ + 'token' => $tokenInfo['token'], + 'expires_time' => $tokenInfo['params']['exp'], + 'menus' => $menus, + 'unique_auth' => $uniqueAuth, + 'user_info' => [ + 'id' => $adminInfo->getData('id'), + 'account' => $adminInfo->getData('account'), + 'head_pic' => get_file_link($adminInfo->getData('head_pic')), + 'level' => $adminInfo->getData('level'), + 'real_name' => $adminInfo->getData('real_name'), + ], + 'logo' => sys_config('site_logo'), + 'logo_square' => sys_config('site_logo_square'), + 'version' => get_phoenix_version(), + 'newOrderAudioLink' => get_file_link(sys_config('new_order_audio_link', '')), + 'queue' => $queue ?? true, + 'timer' => $timer ?? true, + 'site_name' => sys_config('site_name'), + ]; + } + + /** + * 获取登陆前的login等信息 + * + * @return array + */ + public function getLoginInfo() + { + $key = uniqid(); + CheckQueueJob::dispatch([$key]); + $data = [ + 'slide' => sys_data('admin_login_slide') ?? [], + 'logo_square' => sys_config('site_logo_square'),//透明 + 'logo_rectangle' => sys_config('site_logo'),//方形 + 'login_logo' => sys_config('login_logo'),//登陆 + 'site_name' => sys_config('site_name'), + 'copyright' => sys_config('nncnL_crmeb_copyright', ''), + 'version' => get_crmeb_version(), + 'key' => $key, + 'login_captcha' => 0, + ]; + if (CacheService::get('login_captcha', 1) > 1) { + $data['login_captcha'] = 1; + } + return $data; + } + + /** + * 管理员列表 + * + * @param array $where + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAdminList(array $where) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getList($where, $page, $limit); + $count = $this->dao->count($where); +// /** @var SystemRoleServices $service */ +// $service = app()->make(SystemRoleServices::class); +// $allRole = $service->getRoleArray(); +// foreach ($list as &$item) { +// if ($item['roles']) { +// $roles = []; +// foreach ($item['roles'] as $id) { +// if (isset($allRole[$id])) $roles[] = $allRole[$id]; +// } +// if ($roles) { +// $item['roles'] = implode(',', $roles); +// } else { +// $item['roles'] = ''; +// } +// } +// $item['_add_time'] = date('Y-m-d H:i:s', $item['add_time']); +// $item['_last_time'] = $item['last_time'] ? date('Y-m-d H:i:s', $item['last_time']) : ''; +// } + return compact('list', 'count'); + } + + /** + * 创建管理员表单 + * + * @param int $level + * @param array $formData + * + * @return mixed + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createAdminForm(int $level, array $formData = []) + { + $f[] = $this->builder->input('account', '管理员账号', $formData['account'] ?? '')->required('请填写管理员账号'); + $f[] = $this->builder->input('pwd', '管理员密码')->type('password')->required('请填写管理员密码'); + $f[] = $this->builder->input('conf_pwd', '确认密码')->type('password')->required('请输入确认密码'); + $f[] = $this->builder->input('real_name', '管理员姓名', $formData['real_name'] ?? '')->required('请输入管理员姓名'); + + /** @var SystemRoleServices $service */ + $service = app()->make(SystemRoleServices::class); + $options = $service->getRoleFormSelect($level); + if (isset($formData['roles'])) { + foreach ($formData['roles'] as &$item) { + $item = intval($item); + } + } + $f[] = $this->builder->select('roles', '管理员身份', $formData['roles'] ?? [])->setOptions(FormBuilder::setOptions($options))->multiple(true)->required('请选择管理员身份'); + $f[] = $this->builder->radio('status', '状态', $formData['status'] ?? 1)->options([['label' => '开启', 'value' => 1], ['label' => '关闭', 'value' => 0]]); + return $f; + } + + /** + * 添加管理员form表单获取 + * + * @param int $level + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createForm(int $level) + { + return create_form('管理员添加', $this->createAdminForm($level), $this->url('/setting/admin')); + } + + /** + * 创建管理员 + * + * @param array $data + * + * @return bool + * @throws \ReflectionException + */ + public function create(array $data): bool + { + if ($data['conf_pwd'] != $data['pwd']) { + throw new AdminException(400264); + } + unset($data['conf_pwd']); + + if (strlen(trim($data['pwd'])) < 6 || strlen(trim($data['pwd'])) > 32) { + throw new AdminException(400762); + } + + if ($this->dao->count(['account' => $data['account'], 'is_del' => 0])) { + throw new AdminException(400596); + } + + $data['pwd'] = $this->passwordHash($data['pwd']); + $data['create_time'] = time(); + $data['head_pic'] = '/statics/system_images/admin_head_pic.png'; + + return $this->transaction(function () use ($data) { + if ($this->dao->save($data)) { + CacheService::clear(); + return true; + } else { + throw new AdminException(100022); + } + }); + } + + /** + * 修改管理员表单 + * + * @param int $level + * @param int $id + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function updateForm(int $level, int $id) + { + $adminInfo = $this->dao->get($id); + if (!$adminInfo) { + throw new AdminException(400594); + } + if ($adminInfo->is_del) { + throw new AdminException(400452); + } + return create_form('管理员修改', $this->createAdminForm($level, $adminInfo->toArray()), $this->url('/setting/admin/' . $id), 'PUT'); + } + + /** + * 修改管理员 + * + * @param string $id + * @param array $data + * + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function save(string $id, array $data): bool + { + if (!$adminInfo = $this->dao->get($id)) { + throw new AdminException(400594); + } + if ($adminInfo->delete_time) { + throw new AdminException(400452); + } + //修改密码 + if ($data['pwd']) { + + if (!$data['conf_pwd']) { + throw new AdminException(400263); + } + + if ($data['conf_pwd'] != $data['pwd']) { + throw new AdminException(400264); + } + + if (strlen(trim($data['pwd'])) < 6 || strlen(trim($data['pwd'])) > 32) { + throw new AdminException(400762); + } + + $adminInfo->pwd = $this->passwordHash($data['pwd']); + } + //修改账号 + if (isset($data['account']) && $data['account'] != $adminInfo->account && $this->dao->isAccountUsable($data['account'], $id)) { + throw new AdminException(400596); + } + $adminInfo->real_name = $data['real_name'] ?? $adminInfo->real_name; + $adminInfo->account = $data['account'] ?? $adminInfo->account; + $adminInfo->status = $data['status']; + $adminInfo->remark = $data['remark']; + $adminInfo->cell_phone_number = $data['cell_phone_number']; + $adminInfo->email = $data['email']; + $adminInfo->sex = $data['sex']; + $adminInfo->address = $data['address']; + if ($adminInfo->save()) { + return true; + } else { + return false; + } + } + + /** + * 设置管理员-部门/职位 + * + * @param string $id + * @param array $data + * + * @return true + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function setPosition(string $id, array $data = []): bool + { + $adminInfo = $this->dao->get($id); + if (!$adminInfo) { + throw new AdminException(400451); + } + if ($adminInfo->delete_time) { + throw new AdminException(400452); + } + $adminInfo->dept_id = $data['dept_id'] ?? ''; + $adminInfo->post_id = $data['post_id'] ?? ''; + + /** @var SystemAdminDeptServices $systemAdminDeptServices */ + $systemAdminDeptServices = app()->make(SystemAdminDeptServices::class); + $systemAdminDeptServices->delete($adminInfo->id, 'admin_id'); + if ($adminInfo->dept_id) { + $systemAdminDeptServices->save(['dept_id' => $adminInfo->dept_id, 'admin_id' => $adminInfo->id]); + } + /** @var SystemAdminPostServices $systemAdminPostServices */ + $systemAdminPostServices = app()->make(SystemAdminPostServices::class); + $systemAdminPostServices->delete($adminInfo->id, 'admin_id'); + if ($adminInfo->post_id) { + $systemAdminPostServices->save(['post_id' => $adminInfo->post_id, 'admin_id' => $adminInfo->id]); + } + return true; + } + + /** + * 修改当前管理员信息 + * + * @param int $id + * @param array $data + * + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function updateAdmin(string $id, array $data): bool + { + $adminInfo = $this->dao->get($id); + if (!$adminInfo) + throw new AdminException(400451); + if ($adminInfo->delete_time) { + throw new AdminException(400452); + } + if (!empty($data['real_name'])) { + $adminInfo->real_name = $data['real_name']; + } + if ($data['pwd']) { + if (!password_verify($data['pwd'], $adminInfo['pwd'])) + throw new AdminException(400597); + if (!$data['new_pwd']) + throw new AdminException(400598); + if (!$data['conf_pwd']) + throw new AdminException(400263); + if ($data['new_pwd'] != $data['conf_pwd']) + throw new AdminException(400264); + $adminInfo->pwd = $this->passwordHash($data['new_pwd']); + } + if (!empty($data['head_pic'])) { + $adminInfo->head_pic = $data['head_pic']; + } + $adminInfo->remarks = $data['remarks']; + $adminInfo->cell_phone_number = $data['cell_phone_number']; + $adminInfo->email = $data['email']; + $adminInfo->sex = $data['sex']; + $adminInfo->address = $data['address']; + + if ($adminInfo->save()) { + CacheService::clear(); + return true; + } else { + return false; + } + } + + /** + * 设置当前管理员文件管理密码 + * + * @param int $id + * @param array $data + * + * @return bool + */ + public function setFilePassword(int $id, array $data) + { + $adminInfo = $this->dao->get($id); + if (!$adminInfo) + throw new AdminException(400451); + if ($adminInfo->is_del) { + throw new AdminException(400452); + } + if ($data['file_pwd']) { + if ($adminInfo->level != 0) throw new AdminException(400611); + if (!$data['conf_file_pwd']) + throw new AdminException(400263); + if ($data['file_pwd'] != $data['conf_file_pwd']) + throw new AdminException(400264); + $adminInfo->file_pwd = $this->passwordHash($data['file_pwd']); + } + if ($adminInfo->save()) + return true; + else + return false; + } + + /** 后台订单下单,评论,支付成功,后台消息提醒 + * + * @param $event + */ + public function adminNewPush() + { + try { + /** @var StoreOrderServices $orderServices */ + $orderServices = app()->make(StoreOrderServices::class); + $data['ordernum'] = $orderServices->count(['is_del' => 0, 'status' => 1, 'shipping_type' => 1]); + /** @var StoreProductServices $productServices */ + $productServices = app()->make(StoreProductServices::class); + $data['inventory'] = $productServices->count(['type' => 5]); + /** @var StoreProductReplyServices $replyServices */ + $replyServices = app()->make(StoreProductReplyServices::class); + $data['commentnum'] = $replyServices->count(['is_reply' => 0]); + /** @var UserExtractServices $extractServices */ + $extractServices = app()->make(UserExtractServices::class); + $data['reflectnum'] = $extractServices->getCount(['status' => 0]);//提现 + $data['msgcount'] = intval($data['ordernum']) + intval($data['inventory']) + intval($data['commentnum']) + intval($data['reflectnum']); + ChannelService::instance()->send('ADMIN_NEW_PUSH', $data); + } catch (\Exception $e) { + } + } + + public function getAdministratorsList(array $where): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->selectList($where, '*', $page, $limit, '', ['departments', 'positions'], true); + foreach ($list as $value) { + $deptList = $value->getData('departments'); + $postList = $value->getData('positions'); + $dept_id = []; + $dept_name = []; + $post_id = []; + $post_name = []; + if (!empty($deptList)) { + foreach ($deptList as $dept) { + $dept_name[] = $dept->getData('dept_name'); + $dept_id[] = $dept->getData('dept_id'); + } + } + if (!empty($postList)) { + foreach ($postList as $post) { + $post_name[] = $post->getData('post_name'); + $post_id[] = $post->getData('post_id'); + } + } + $value->set('dept_name', implode(',', $dept_name)); + $value->set('post_name', implode(',', $post_name)); + $value->set('dept_id', implode(',', $dept_id)); + $value->set('post_id', implode(',', $post_id)); + } + if ($list != null) { + $list->hidden(['pwd']); + $list = $list->toArray(); + } else { + $list = []; + } + $count = $this->dao->count($where); + return compact('list', 'count'); + + } +} diff --git a/demo/thinkphp/backend/app/services/system/admin/SystemAuthServices.php b/demo/thinkphp/backend/app/services/system/admin/SystemAuthServices.php new file mode 100644 index 0000000000000000000000000000000000000000..f86b6148ec474b5fa8b98b4f4ee100f1c85b25f0 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/admin/SystemAuthServices.php @@ -0,0 +1,172 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\AdminAuthDao; +use app\services\BaseServices; +use app\services\system\setting\CacheServices; +use phoenix\exceptions\AuthException; +use phoenix\services\CacheService; +use phoenix\utils\JwtAuth; + +/** + * admin授权service + * Class AdminAuthServices + * + * @package app\services\system\admin + */ +class SystemAuthServices extends BaseServices +{ + + public function __construct(AdminAuthDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取Admin授权信息 + * + * @param string $token + * @param int $code + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function parseToken(string $token, int $code = 110003): array + { + /** @var CacheService $cacheService */ + $cacheService = app()->make(CacheService::class); + if (!$token || $token === 'undefined') { + throw new AuthException($code); + } + /** @var JwtAuth $jwtAuth */ + $jwtAuth = app()->make(JwtAuth::class); + //设置解析token + [$id, $type, $pwd, $exp] = $jwtAuth->parseToken($token); + + //检测token是否过期 + $md5Token = md5($token); + if (!$cacheService->has($md5Token) || !$cacheService->get($md5Token, '', NULL, $type)) { + $this->authFailAfter($id, $type); + throw new AuthException($code); + } + //验证token + try { + $jwtAuth->verifyToken(); + } catch (\Throwable $e) { + if (!request()->isCli()) { + $cacheService->delete($md5Token); + } + $this->authFailAfter($id, $type); + throw new AuthException($code); + } + + //获取管理员信息 + $validTime = $this->timestamp_diff(time(), $exp); + $adminInfo = $this->cacheDriver()->remember($md5Token, $this->infoAdmin($id), $validTime + 60); + if (!$adminInfo || !$adminInfo->id) { + if (!request()->isCli()) { + $cacheService->delete($md5Token); + } + $this->authFailAfter($id, $type); + throw new AuthException($code); + } + $adminInfo->type = $type; + return $adminInfo->hidden(['pwd', 'delete_time', 'status'])->toArray(); + } + + /** + * token验证失败后事件 + */ + protected function authFailAfter($id, $type) + { + try { + //token 验证失败后处理事件 + } catch (\Throwable $e) { + } + } + + /** + * 保存提交数据 + * + * @param $adminId + * @param $postData + */ + protected function saveProduct($adminId, $postData) + { + /** @var CacheServices $cacheService */ + $cacheService = app()->make(CacheServices::class); + $cacheService->setDbCache($adminId . '_product_data', $postData, 68400); + } + + /** + * 获取管理员信息 + * + * @param string|int $id + * + * @return array|\think\Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function infoAdmin(string|int $id): array|\think\Model + { + $adminInfo = $this->get($id); + if (!$adminInfo) { + throw new AuthException(400595); + } + if (!$adminInfo->status) { + throw new AuthException(400595); + } + /** @var SystemAdminDeptServices $systemAdminDeptServices */ + $systemAdminDeptServices = app()->make(SystemAdminDeptServices::class); + $adminInfo->dept_id = $systemAdminDeptServices->column(['admin_id' => $adminInfo->id], 'dept_id')[0] ?? ''; + + /** @var SystemAdminPostServices $systemAdminPostServices */ + $systemAdminPostServices = app()->make(SystemAdminPostServices::class); + $adminInfo->post_id = $systemAdminPostServices->column(['admin_id' => $adminInfo->id], 'post_id')[0] ?? ''; + + if (!empty($adminInfo->dept_id)) { + /** @var SystemRoleDeptServices $systemRoleDeptServices */ + $systemRoleDeptServices = app()->make(SystemRoleDeptServices::class); + $deptRoleId = $systemRoleDeptServices->column(['dept_id' => $adminInfo->dept_id], 'role_id'); + } + + if (!empty($adminInfo->post_id)) { + /** @var SystemRolePostServices $systemRolePostServices */ + $systemRolePostServices = app()->make(SystemRolePostServices::class); + $postRoleId = $systemRolePostServices->column(['post_id' => $adminInfo->post_id], 'role_id'); + } + $adminInfo->role_id = array_merge_recursive($deptRoleId ?? [], $postRoleId ?? []); + + /** @var SystemRoleMenuServices $systemRoleMenuServices */ + $systemRoleMenuServices = app()->make(SystemRoleMenuServices::class); + $adminInfo->roles = $systemRoleMenuServices->column(['role_id' => $adminInfo->role_id], 'menu_id'); + return $adminInfo; + } + + /** + * 有效时间 + * + * @param int $timestamp1 + * @param int $timestamp2 + * + * @return int + */ + private function timestamp_diff(int $timestamp1, int $timestamp2): int + { + $diff = $timestamp2 - $timestamp1; + return max(0, $diff); + } +} diff --git a/demo/thinkphp/backend/app/services/system/admin/SystemDeptServices.php b/demo/thinkphp/backend/app/services/system/admin/SystemDeptServices.php new file mode 100644 index 0000000000000000000000000000000000000000..95af81d0a05af6f7981afcaec239e1c8ae3a3986 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/admin/SystemDeptServices.php @@ -0,0 +1,128 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\SystemDeptDao; +use app\Request; +use app\services\BaseServices; +use phoenix\exceptions\AdminException; +use phoenix\exceptions\AuthException; + +/** + * Class SystemRoleServices + * + * @package app\services\system\admin + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取数据 + */ +class SystemDeptServices extends BaseServices +{ + + /** + * 当前管理员权限缓存前缀 + */ + const ADMIN_RULES_LEVEL = 'Admin_dept_level_'; + + /** + * SystemRoleServices constructor. + * + * @param SystemDeptDao $dao + */ + public function __construct(SystemDeptDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取后台菜单树型结构列表 + * + * @param array $where + * @param array $field + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where, array $field = ['*']): array + { + [$page, $limit] = $this->getPageValue(false); + $deptList = $this->dao->getDeptList($where, $page, $limit); + $deptList = $this->getDeptsData($deptList); + return get_tree_children($deptList, 'children', 'dept_id', 'pid'); + } + + /** + * 获取一条数据 + * + * @param string $id + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function find(string $id): mixed + { + $roleInfo = $this->dao->get($id); + if (!$roleInfo) { + throw new AdminException(100026); + } + /** @var StoreOrderServices $orderServices */ +// $systemRoleMenu = app()->make(SystemRoleMenuServices::class); +// $roleInfo->rules = $systemRoleMenu->column(['role_id' => $id], 'menu_id'); + return $roleInfo->getData(); + } + + /** + * 删除部门 + * + * @param string $id + * + * @return mixed + * @throws \ReflectionException + */ + public function delete(string $id): mixed + { + $ids = $this->dao->column(['pid' => $id], 'dept_id'); + if (count($ids)) { + foreach ($ids as $value) { + $this->delete($value); + } + } + return $this->dao->delete($id); + } + + /** + * 获取组织没有被修改器修改的数据 + * + * @param $deptList + * + * @return array + */ + private function getDeptsData($deptList): array + { + + $data = []; + foreach ($deptList as $item) { + $item = $item->getData(); +// if (isset($item['menu_path'])) { +// $item['menu_path'] = '/' . config('app.admin_prefix', 'admin') . $item['menu_path']; +// } + $data[] = $item; + } + + return $data; + } +} diff --git a/demo/thinkphp/backend/app/services/system/admin/SystemMenusServices.php b/demo/thinkphp/backend/app/services/system/admin/SystemMenusServices.php new file mode 100644 index 0000000000000000000000000000000000000000..28d998e70ca6670a0bc7ce3103561cca40e49f4b --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/admin/SystemMenusServices.php @@ -0,0 +1,277 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\SystemMenusDao; +use app\services\BaseServices; +use app\services\system\setting\SystemRoleServices; +use phoenix\exceptions\AdminException; +use phoenix\utils\Arr; + +/** + * 权限菜单 + * Class SystemMenusServices + * + * @package app\services\system + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取数据 + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method getSearchList() 主页搜索 + * @method getColumn(array $where, string $field, ?string $key = '') 主页搜索 + * @method getVisitName(string $rule) 根据访问地址获得菜单名 + */ +class SystemMenusServices extends BaseServices +{ + + /** + * 初始化 + * SystemMenusServices constructor. + * + * @param SystemMenusDao $dao + */ + public function __construct(SystemMenusDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取菜单没有被修改器修改的数据 + * + * @param $menusList + * + * @return array + */ + public function getMenusData($menusList): array + { + $data = []; + foreach ($menusList as $item) { + $item = $item->getData(); +// if (isset($item['menu_path'])) { +// $item['menu_path'] = '/' . config('app.admin_prefix', 'admin') . $item['menu_path']; +// } + $data[] = $item; + } + + return $data; + } + + /** + * 获取后台权限菜单和权限 + * + * @param array|string $menuId + * @param int $level + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getMenusList(array|string $menuId, int $level = 1): array + { + /** @var SystemRoleServices $systemRoleServices */ + $menusList = $this->dao->getMenusRoule(['route' => $level != 0 ? $menuId : '', 'is_show' => 1]); + $unique = $this->dao->getMenusUnique(['unique' => $level != 0 ? $menuId : '']); + return [Arr::getMenuLayuiViewList($this->getMenusData($menusList)), $unique]; + + } + + /** + * 获取后台菜单树型结构列表 + * + * @param array $where + * @param array $field + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where, array $field = ['*']): array + { + $menusList = $this->dao->getMenusList($where, $field); + $menusList = $this->getMenusData($menusList); + return get_tree_children($menusList); + } + + /** + * 获取form表单所需要的所要的菜单列表 + * + * @return array[] + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + protected function getFormSelectMenus(): array + { + $menuList = $this->dao->getMenusRoule(['delete_time' => null], ['id', 'pid', 'menu_name']); + $list = sort_list_tier($this->getMenusData($menuList), '0', 'pid', 'id'); + $menus = [['value' => 0, 'label' => '顶级按钮']]; + foreach ($list as $menu) { + $menus[] = ['value' => $menu['id'], 'label' => $menu['html'] . $menu['menu_name']]; + } + return $menus; + } + + /** + * @param string $value + * @param int $auth_type + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + protected function getFormCascaderMenus(string $value = '-1', int $auth_type = 0): array + { + $where = ['delete_time' => null]; + $menuList = $this->dao->getMenusRoule($where, ['id as value', 'pid', 'menu_name as label']); + $menuList = $this->getMenusData($menuList); + if ($value) { + $data = get_tree_value($menuList, $value); + } else { + $data = []; + } + return [get_tree_children($menuList, 'children', 'value'), array_reverse($data)]; + } + + /** + * 修改权限菜单 + * + * @param string $id + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function updateMenus(string $id): array + { + $menusInfo = $this->dao->get($id); + if (!$menusInfo) { + throw new AdminException(100026); + } + return create_form('修改权限', $this->createMenusForm($menusInfo->getData()), $this->url('/setting/update/' . $id), 'PUT'); + } + + /** + * 获取一条数据 + * + * @param string $id + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function find(string $id): mixed + { + $menusInfo = $this->dao->get($id); + if (!$menusInfo) { + throw new AdminException(100026); + } + $menu = $menusInfo->getData(); + $menu['pid'] = $menu['pid']; + $menu['auth_type'] = (int)$menu['auth_type']; + $menu['is_header'] = (int)$menu['is_header']; + $menu['is_show'] = (int)$menu['is_show']; + $menu['is_show_path'] = (int)$menu['is_show_path']; + if (!$menu['path']) { + [$menuList, $data] = $this->getFormCascaderMenus($menu['pid']); + $menu['path'] = $data; + } else { + $menu['path'] = explode('/', $menu['path']); + if (is_array($menu['path'])) { + $menu['path'] = array_map(function ($item) { + return (int)$item; + }, $menu['path']); + } + } + return $menu; + } + + /** + * 删除菜单 + * + * @param string $id + * + * @return mixed + * @throws \ReflectionException + */ + public function delete(string $id): mixed + { + $ids = $this->dao->column(['pid' => $id], 'id'); + if (count($ids)) { + foreach ($ids as $value) { + $this->delete($value); + } + } + return $this->dao->delete($id); + } + + /** + * 获取添加身份规格 + * + * @param $roleId + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getMenus($roleId): array + { + $field = ['menu_name', 'pid', 'id']; + $where = ['delete_time' => null, 'is_show' => 1]; + if (!$roleId) { + $menus = $this->dao->getMenusRoule($where, $field); + } else { + /** @var SystemRoleServices $service */ + $service = app()->make(SystemRoleMenuServices::class); + $roles = is_string($roleId) ? explode(',', $roleId) : $roleId; + $ids = $service->getRoleIds($roles); + $menus = $this->dao->getMenusRoule(['rule' => $ids] + $where, $field); + } + return $this->tidyMenuTier(false, $menus); + } + + /** + * 组合菜单数据 + * + * @param bool $adminFilter + * @param array|object $menusList + * @param string $pid + * @param array $navList + * + * @return array + */ + public function tidyMenuTier(bool $adminFilter = false, array|object $menusList = [], string $pid = '-1', array $navList = []): array + { + foreach ($menusList as $k => $menu) { + $menu = $menu->getData(); + $menu['title'] = $menu['menu_name']; + unset($menu['menu_name']); + if ($menu['pid'] == $pid) { + unset($menusList[$k]); + $menu['children'] = $this->tidyMenuTier($adminFilter, $menusList, $menu['id']); + if ($pid == 0 && !count($menu['children'])) continue; + if ($menu['children']) $menu['expand'] = true; + $navList[] = $menu; + } + } + return $navList; + } +} diff --git a/demo/thinkphp/backend/app/services/system/admin/SystemPostServices.php b/demo/thinkphp/backend/app/services/system/admin/SystemPostServices.php new file mode 100644 index 0000000000000000000000000000000000000000..b2946080eac1c1a3c35aea12b850a28d2396e577 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/admin/SystemPostServices.php @@ -0,0 +1,128 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\SystemPostDao; +use app\Request; +use app\services\BaseServices; +use phoenix\exceptions\AdminException; +use phoenix\exceptions\AuthException; + +/** + * Class SystemRoleServices + * + * @package app\services\system\admin + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取数据 + */ +class SystemPostServices extends BaseServices +{ + + /** + * 当前管理员权限缓存前缀 + */ + const ADMIN_RULES_LEVEL = 'Admin_post_level_'; + + /** + * SystemRoleServices constructor. + * + * @param SystemPostDao $dao + */ + public function __construct(SystemPostDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取职位树型结构列表 + * + * @param array $where + * @param array $field + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where, array $field = ['*']): array + { + [$page, $limit,$defaultLimit,$limitMax] = $this->getPageValue(false); + $deptList = $this->dao->getPostList($where, $page,$limitMax); + $deptList = $this->getPostsData($deptList); + return get_tree_children($deptList, 'children', 'post_id', 'pid'); + } + + /** + * 获取一条数据 + * + * @param string $id + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function find(string $id): mixed + { + $roleInfo = $this->dao->get($id); + if (!$roleInfo) { + throw new AdminException(100026); + } + /** @var StoreOrderServices $orderServices */ +// $systemRoleMenu = app()->make(SystemRoleMenuServices::class); +// $roleInfo->rules = $systemRoleMenu->column(['role_id' => $id], 'menu_id'); + return $roleInfo->getData(); + } + + /** + * 删除职位 + * + * @param string $id + * + * @return mixed + * @throws \ReflectionException + */ + public function delete(string $id): mixed + { + $ids = $this->dao->column(['pid' => $id], 'post_id'); + if (count($ids)) { + foreach ($ids as $value) { + $this->delete($value); + } + } + return $this->dao->delete($id); + } + + /** + * 获取组织没有被修改器修改的数据 + * + * @param $deptList + * + * @return array + */ + private function getPostsData($deptList): array + { + + $data = []; + foreach ($deptList as $item) { + $item = $item->getData(); +// if (isset($item['menu_path'])) { +// $item['menu_path'] = '/' . config('app.admin_prefix', 'admin') . $item['menu_path']; +// } + $data[] = $item; + } + + return $data; + } +} diff --git a/demo/thinkphp/backend/app/services/system/admin/SystemRoleDeptServices.php b/demo/thinkphp/backend/app/services/system/admin/SystemRoleDeptServices.php new file mode 100644 index 0000000000000000000000000000000000000000..532d61a4f0eac8c83354a7f9e7f24e15c0eaea57 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/admin/SystemRoleDeptServices.php @@ -0,0 +1,56 @@ +dao = $dao; + } + + + /** + * 角色分配组织 + * @param array $data + * + * @return mixed + * @throws \Exception + */ + public function create(array $data) + { + return $this->transaction(function () use ($data) { + + $this->delete($data['role_id'], 'role_id'); + if (empty($data['checked_dept'])) { + return true; + } + $list = []; + foreach ($data['checked_dept'] as $key => $value) { + $list[$key]['role_id'] = $data['role_id']; + $list[$key]['dept_id'] = $value; + } + if ($this->dao->saveAll($list)) { + CacheService::clear(); + return true; + } else { + throw new AdminException(100022); + } + }); + } +} diff --git a/demo/thinkphp/backend/app/services/system/admin/SystemRoleMenuServices.php b/demo/thinkphp/backend/app/services/system/admin/SystemRoleMenuServices.php new file mode 100644 index 0000000000000000000000000000000000000000..54657a39c80709cd31e93545e4f3bf7e13111750 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/admin/SystemRoleMenuServices.php @@ -0,0 +1,69 @@ +dao = $dao; + } + + /** + * 添加角色规则 + * + * @param array $data + * + * @return mixed + * @throws \Exception + */ + public function create(array $data) + { + return $this->transaction(function () use ($data) { + + $this->delete($data['role_id'], 'role_id'); + if (empty($data['checked_menus'])) { + return true; + } + $list = []; + foreach ($data['checked_menus'] as $key => $value) { + $list[$key]['role_id'] = $data['role_id']; + $list[$key]['menu_id'] = $value; + } + if ($this->dao->saveAll($list)) { + CacheService::clear(); + return true; + } else { + throw new AdminException(100022); + } + }); + } + + /** + * 获取权限id + * + * @param array $rules 角色Id + * + * @return array + */ + public function getRoleIds(array $rules): array + { + $result = $this->dao->getColumn([['role_id', 'IN', $rules]], 'menu_id'); + return array_unique($result); + } +} diff --git a/demo/thinkphp/backend/app/services/system/admin/SystemRolePostServices.php b/demo/thinkphp/backend/app/services/system/admin/SystemRolePostServices.php new file mode 100644 index 0000000000000000000000000000000000000000..fb18dbe05704a06a0f8a6304297fec6c342bef79 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/admin/SystemRolePostServices.php @@ -0,0 +1,56 @@ +dao = $dao; + } + + + /** + * 角色分配组织 + * @param array $data + * + * @return mixed + * @throws \Exception + */ + public function create(array $data) + { + return $this->transaction(function () use ($data) { + + $this->delete($data['role_id'], 'role_id'); + if (empty($data['checked_post'])) { + return true; + } + $list = []; + foreach ($data['checked_post'] as $key => $value) { + $list[$key]['role_id'] = $data['role_id']; + $list[$key]['post_id'] = $value; + } + if ($this->dao->saveAll($list)) { + CacheService::clear(); + return true; + } else { + throw new AdminException(100022); + } + }); + } +} diff --git a/demo/thinkphp/backend/app/services/system/admin/SystemRoleServices.php b/demo/thinkphp/backend/app/services/system/admin/SystemRoleServices.php new file mode 100644 index 0000000000000000000000000000000000000000..5a0038b149cf501f4f500ea505bd2f38d390ff5c --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/admin/SystemRoleServices.php @@ -0,0 +1,231 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\SystemRoleDao; +use app\Request; +use app\services\BaseServices; +use phoenix\exceptions\AdminException; +use phoenix\exceptions\AuthException; +use phoenix\utils\Arr; + +/** + * Class SystemRoleServices + * + * @package app\services\system\admin + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取数据 + */ +class SystemRoleServices extends BaseServices +{ + + /** + * 当前管理员权限缓存前缀 + */ + const ADMIN_RULES_LEVEL = 'Admin_rules_level_'; + + /** + * SystemRoleServices constructor. + * + * @param SystemRoleDao $dao + */ + public function __construct(SystemRoleDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取一条数据 + * + * @param string $id + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function find(string $id): mixed + { + $roleInfo = $this->dao->get($id); + if (!$roleInfo) { + throw new AdminException(100026); + } + + /** @var SystemRoleMenuServices $systemRoleMenu */ + $systemRoleMenu = app()->make(SystemRoleMenuServices::class); + $roleInfo->rules = $systemRoleMenu->column(['role_id' => $id], 'menu_id'); + + /** @var SystemRoleDeptServices $systemRoleDept */ + $systemRoleDept = app()->make(SystemRoleDeptServices::class); + $roleInfo->depts = $systemRoleDept->column(['role_id' => $id], 'dept_id'); + + /** @var SystemRolePostServices $systemRolePost */ + $systemRolePost = app()->make(SystemRolePostServices::class); + $roleInfo->posts = $systemRolePost->column(['role_id' => $id], 'post_id'); + return $roleInfo->getData(); + } + + /** + * 获取权限 + * + * @return mixed + */ + public function getRoleArray(array $where = [], string $field = '', string $key = '') + { + return $this->dao->getRoule($where, $field, $key); + } + + /** + * 获取表单所需的权限名称列表 + * + * @param int $level + * + * @return array + */ + public function getRoleFormSelect(int $level) + { + $list = $this->getRoleArray(['level' => $level, 'status' => 1]); + $options = []; + foreach ($list as $id => $roleName) { + $options[] = ['label' => $roleName, 'value' => $id]; + } + return $options; + } + + /** + * 身份管理列表 + * + * @param array $where + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getRoleList(array $where): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getRouleList($where, $page, $limit); + $count = $this->dao->count($where); + return compact('count', 'list'); + } + + /** + * 后台验证权限 + * + * @param Request $request + * + * @return bool + * @throws \throwable + */ + public function verifyAuth(Request $request): bool + { + // 获取当前的接口于接口类型 + $rule = trim(strtolower($request->rule()->getRule())); + $method = trim(strtolower($request->method())); + + // 判断接口是一下两种的时候放行 + if (in_array($rule, ['setting/admin/logout', 'menuslist'])) { + return true; + } + + // 获取所有接口类型以及对应的接口 + $allAuth = $this->cacheDriver()->remember('all_auth', function () { + /** @var SystemMenusServices $menusService */ + $menusService = app()->make(SystemMenusServices::class); + $allList = $menusService->getColumn([['api_url', '<>', ''], ['auth_type', '=', 2]], 'api_url,methods'); + $allAuth = []; + foreach ($allList as $item) { + $allAuth[trim(strtolower($item['methods']))][] = trim(strtolower(str_replace(' ', '', $item['api_url']))); + } + return $allAuth; + }); + + // 权限菜单未添加时放行 + if (!in_array($rule, $allAuth[$method]??[])) return true; + + // 获取管理员的接口权限列表,存在时放行 + $auth = $this->getRolesByAuth($request->adminInfo()['role_id'], 2); + if (isset($auth[$method]) && in_array($rule, $auth[$method])) { + return true; + } else { + throw new AuthException(110000); + } + } + + /** + * 获取指定权限 + * + * @param array $rules + * @param int $type + * @param string $cachePrefix + * + * @return array|mixed + * @throws \throwable + */ + public function getRolesByAuth(array $rules, int $type = 1, string $cachePrefix = self::ADMIN_RULES_LEVEL): mixed + { + if (empty($rules)) return []; + $authAll = []; + foreach ($rules as $value) { + $cacheName = md5($cachePrefix . '_' . $type . '_' . $value); + $rolesAuth = $this->cacheDriver()->remember($cacheName, function () use ($value, $type) { + $menusService = app()->make(SystemMenusServices::class); + $authList = $menusService->getColumn([['auth_type', '=', $type]], 'api_url,methods'); + $rolesAuth = []; + foreach ($authList as $item) { + $rolesAuth[trim(strtolower($item['methods']))][] = trim(strtolower(str_replace(' ', '', $item['api_url']))); + } + return $rolesAuth; + }); + $authAll = array_merge($authAll, $rolesAuth); + } + return Arr::uniqueArrayValues($authAll); + } + + /** + * 删除角色 + * + * @param string $id + * + * @return mixed + * @throws \ReflectionException + */ + public + function delete(string $id): mixed + { + $ids = $this->dao->column(['pid' => $id], 'role_id'); + if (count($ids)) { + foreach ($ids as $value) { + $this->delete($value); + } + } + return $this->dao->delete($id); + } + + /** + * 获取权限id + * + * @param string $rules + * + * @return array + */ + public + function getRoleIds(string $rules): array + { + $systemRoleMenuService = app()->make(SystemRoleMenuServices::class); + $rules = $systemRoleMenuService->dao->getColumn([['role_id', '=', $rules]], 'menu_id'); + return array_unique(explode(',', implode(',', $rules))); + } +} diff --git a/demo/thinkphp/backend/app/services/system/attachment/SystemAttachmentCategoryServices.php b/demo/thinkphp/backend/app/services/system/attachment/SystemAttachmentCategoryServices.php new file mode 100644 index 0000000000000000000000000000000000000000..cc86dbb6bd0640a58c8a53e1b3d8009b54955606 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/attachment/SystemAttachmentCategoryServices.php @@ -0,0 +1,168 @@ + +// +---------------------------------------------------------------------- +declare (strict_types=1); + +namespace app\services\system\attachment; + +use app\services\BaseServices; +use app\dao\system\attachment\SystemAttachmentCategoryDao; +use phoenix\exceptions\AdminException; + + +/** + * SystemAttachmentCategoryServices + * + * @author Mr.April + * @since 1.0 + * @method get($id) 获取一条数据 + * @method count($where) 获取条件下数据总数 + */ +class SystemAttachmentCategoryServices extends BaseServices +{ + + /** + * SystemAttachmentCategoryServices constructor. + * + * @param SystemAttachmentCategoryDao $dao + */ + public function __construct(SystemAttachmentCategoryDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取分类列表 + * + * @param array $where + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAll(array $where): array + { + $list = $this->dao->getList($where); + if ($where['all'] == 1) { + $list = $this->tidyMenuTier($list); + } else { + foreach ($list as &$item) { + $item['title'] = $item['name']; + if ($where['name'] == '' && $this->dao->count(['pid' => $item['id']])) { + $item['loading'] = false; + $item['children'] = []; + } + } + } + return compact('list'); + } + + /** + * 格式化列表 + * + * @param $menusList + * @param string $pid + * @param array $navList + * + * @return array + */ + public function tidyMenuTier($menusList, string $pid = '-1', array $navList = []): array + { + foreach ($menusList as $k => $menu) { + $menu['title'] = $menu['name']; + if ($menu['pid'] == $pid) { + unset($menusList[$k]); + $menu['children'] = $this->tidyMenuTier($menusList, $menu['id']); + if (count($menu['children'])) { + $menu['expand'] = true; + } else { + unset($menu['children']); + } + $navList[] = $menu; + } + } + return $navList; + } + + /** + * 保存新建的资源 + * + * @param array $data + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function save(array $data): mixed + { + if ($this->dao->getOne(['name' => $data['name']])) { + throw new AdminException(400101); + } + $res = $this->dao->save($data); + if (!$res) throw new AdminException(100022); + return $res; + } + + /** + * 保存修改的资源 + * + * @param string $id + * @param array $data + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function update(string $id, array $data) + { + $attachment = $this->dao->getOne(['name' => $data['name']]); + if ($attachment && $attachment['id'] != $id) { + throw new AdminException(400101); + } + $res = $this->dao->update($id, $data); + if (!$res) { + throw new AdminException(100007); + } + } + + /** + * 删除分类 + * + * @param string $id + */ + public function del(string $id): void + { + $count = $this->dao->getCount(['pid' => $id]); + if ($count) { + throw new AdminException(400102); + } else { + $res = $this->dao->delete($id); + if (!$res) throw new AdminException(400102); + } + } + + /** + * 获取一条数据 + * + * @param $where + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getOne($where) + { + return $this->dao->getOne($where); + } +} diff --git a/demo/thinkphp/backend/app/services/system/attachment/SystemAttachmentServices.php b/demo/thinkphp/backend/app/services/system/attachment/SystemAttachmentServices.php new file mode 100644 index 0000000000000000000000000000000000000000..1b38c4af38c7d26178171b065f61aafb9d909170 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/attachment/SystemAttachmentServices.php @@ -0,0 +1,368 @@ + +// +---------------------------------------------------------------------- +declare (strict_types=1); + +namespace app\services\system\attachment; + +use app\services\BaseServices; +use app\dao\system\attachment\SystemAttachmentDao; +use app\services\product\product\CopyTaobaoServices; +use phoenix\exceptions\AdminException; +use phoenix\exceptions\ApiException; +use app\services\other\UploadService; +use phoenix\exceptions\UploadException; + +/** + * Class SystemAttachmentServices + * + * @package app\services\attachment + * @method getYesterday() 获取昨日生成数据 + * @method delYesterday() 删除昨日生成数据 + * @method scanUploadImage($scan_token) 获取扫码上传的图片数据 + */ +class SystemAttachmentServices extends BaseServices +{ + + /** + * SystemAttachmentServices constructor. + * + * @param SystemAttachmentDao $dao + */ + public function __construct(SystemAttachmentDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取单个资源 + * + * @param array $where + * @param string $field + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo(array $where, string $field = '*') + { + return $this->dao->getOne($where, $field); + } + + /** + * 获取图片列表 + * + * @param array $where + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getImageList(array $where) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getList($where, $page, $limit); + $site_url = sys_config('site_url'); + foreach ($list as &$item) { + if ($site_url) { + $item['satt_dir'] = (str_contains($item['satt_dir'], $site_url) || str_contains($item['satt_dir'], 'http')) ? $item['satt_dir'] : $site_url . $item['satt_dir']; + $item['att_dir'] = (str_contains($item['att_dir'], $site_url) || str_contains($item['att_dir'], 'http')) ? $item['satt_dir'] : $site_url . $item['att_dir']; + $item['time'] = date('Y-m-d H:i:s', $item['time']); + } + } + $where['module_type'] = 1; + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * 删除图片 + * + * @param string $ids + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function del(string $ids) + { + $ids = explode(',', $ids); + if (empty($ids)) throw new AdminException(400599); + foreach ($ids as $v) { + $attinfo = $this->dao->get($v); + if ($attinfo) { + try { + $upload = UploadService::init($attinfo['image_type']); + if ($attinfo['image_type'] == 1) { + if (strpos($attinfo['att_dir'], '/') == 0) { + $attinfo['att_dir'] = substr($attinfo['att_dir'], 1); + } + if ($attinfo['att_dir']) $upload->delete($attinfo['att_dir']); + } else { + if ($attinfo['name']) $upload->delete($attinfo['name']); + } + } catch (\Throwable $e) { + } + $this->dao->delete($v); + } + } + } + + /** + * 图片上传 + * + * @param int $pid + * @param string $file + * @param int $upload_type + * @param int $type + * @param $menuName + * @param string $uploadToken + * + * @return mixed + */ + public function upload(string $pid, string $file, int $upload_type, int $type, $menuName, string $uploadToken = ''): mixed + { + $realName = false; + if ($upload_type == 0) { + $upload_type = sys_config('upload_type', 1); + } + if ($menuName == 'weixin_ckeck_file' || $menuName == 'ico_path') { + $upload_type = 1; + $realName = true; + } + try { + $path = make_path('attach', 2, true); + $upload = UploadService::init($upload_type); + $res = $upload->to($path)->validate()->move($file, $realName); + if ($res === false) { + throw new UploadException($upload->getError()); + } else { + $fileInfo = $upload->getUploadInfo(); + $fileType = pathinfo($fileInfo['name'], PATHINFO_EXTENSION); +// if ($fileInfo && $type == 0 && !in_array($fileType, ['xlsx', 'xls', 'mp4'])) { + if ($fileInfo && $type == 0) { + $data['name'] = $fileInfo['name']; + $data['real_name'] = $fileInfo['real_name']; + $data['att_dir'] = $fileInfo['dir']; + $data['satt_dir'] = $fileInfo['thumb_path']; + $data['att_size'] = $fileInfo['size']; + $data['att_type'] = $fileInfo['type']; + $data['ext'] = $fileInfo['ext']; + $data['image_type'] = $upload_type; + $data['module_type'] = 1; + $data['time'] = $fileInfo['time'] ?? time(); + $data['pid'] = $pid; + $data['scan_token'] = $uploadToken; + $this->dao->save($data); + } + return $res->filePath; + } + } catch (\Exception $e) { + throw new UploadException($e->getMessage()); + } + } + + /** + * @param array $data + * + * @return \crmeb\basic\BaseModel + */ + public function move(array $data) + { + $this->dao->move($data); + } + + /** + * 添加信息 + * + * @param array $data + */ + public function save(array $data) + { + $this->dao->save($data); + } + + /** + * TODO 添加附件记录 + * + * @param $name + * @param $att_size + * @param $att_type + * @param $att_dir + * @param string $satt_dir + * @param int $pid + * @param int $imageType + * @param int $time + * + * @return SystemAttachment + */ + public function attachmentAdd($name, $att_size, $att_type, $att_dir, $satt_dir = '', $pid = 0, $imageType = 1, $time = 0, $module_type = 1) + { + $data['name'] = $name; + $data['att_dir'] = $att_dir; + $data['satt_dir'] = $satt_dir; + $data['att_size'] = $att_size; + $data['att_type'] = $att_type; + $data['image_type'] = $imageType; + $data['module_type'] = $module_type; + $data['time'] = $time ?: time(); + $data['pid'] = $pid; + if (!$this->dao->save($data)) { + throw new ApiException(100022); + } + return true; + } + + /** + * 推广名片生成 + * + * @param $name + */ + public function getLikeNameList($name) + { + return $this->dao->getLikeNameList(['like_name' => $name], 0, 0); + } + + /** + * 清除昨日海报 + * + * @return bool + * @throws \Exception + */ + public function emptyYesterdayAttachment(): bool + { + try { + $list = $this->dao->getYesterday(); + foreach ($list as $key => $item) { + $upload = UploadService::init((int)$item['image_type']); + if ($item['image_type'] == 1) { + $att_dir = $item['att_dir']; + if ($att_dir && strstr($att_dir, 'uploads') !== false) { + if (strstr($att_dir, 'http') === false) + $upload->delete($att_dir); + else { + $filedir = substr($att_dir, strpos($att_dir, 'uploads')); + if ($filedir) $upload->delete($filedir); + } + } + } else { + if ($item['name']) $upload->delete($item['name']); + } + } + $this->dao->delYesterday(); + return true; + } catch (\Exception $e) { + $this->dao->delYesterday(); + return true; + } + } + + /** + * 视频分片上传 + * + * @param $data + * @param $file + * + * @return mixed + */ + public function videoUpload($data, $file) + { + $pathinfo = pathinfo($data['filename']); + if (isset($pathinfo['extension']) && !in_array($pathinfo['extension'], ['avi', 'mp4', 'wmv', 'rm', 'mpg', 'mpeg', 'mov', 'flv', 'swf'])) { + throw new AdminException(400558); + } + $public_dir = app()->getRootPath() . 'public'; + $dir = '/uploads/attach/' . date('Y') . DIRECTORY_SEPARATOR . date('m') . DIRECTORY_SEPARATOR . date('d'); + $all_dir = $public_dir . $dir; + if (!is_dir($all_dir)) mkdir($all_dir, 0777, true); + $filename = $all_dir . '/' . $data['filename'] . '__' . $data['chunkNumber']; + move_uploaded_file($file['tmp_name'], $filename); + $res['code'] = 0; + $res['msg'] = 'error'; + $res['file_path'] = ''; + if ($data['chunkNumber'] == $data['totalChunks']) { + $blob = ''; + for ($i = 1; $i <= $data['totalChunks']; $i++) { + $blob .= file_get_contents($all_dir . '/' . $data['filename'] . '__' . $i); + } + file_put_contents($all_dir . '/' . $data['filename'], $blob); + for ($i = 1; $i <= $data['totalChunks']; $i++) { + @unlink($all_dir . '/' . $data['filename'] . '__' . $i); + } + if (file_exists($all_dir . '/' . $data['filename'])) { + $res['code'] = 2; + $res['msg'] = 'success'; + $res['file_path'] = sys_config('site_url') . $dir . '/' . $data['filename']; + } + } else { + if (file_exists($all_dir . '/' . $data['filename'] . '__' . $data['chunkNumber'])) { + $res['code'] = 1; + $res['msg'] = 'waiting'; + $res['file_path'] = ''; + } + } + return $res; + } + + /** + * 网络图片上传 + * + * @param $data + * + * @return bool + * @throws \Exception + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/06/13 + */ + public function onlineUpload($data) + { + //生成附件目录 + if (make_path('attach', 3, true) === '') { + throw new AdminException(400555); + } + + //上传图片 + /** @var SystemAttachmentServices $systemAttachmentService */ + $systemAttachmentService = app()->make(SystemAttachmentServices::class); + $siteUrl = sys_config('site_url'); + + foreach ($data['images'] as $image) { + $uploadValue = app()->make(CopyTaobaoServices::class)->downloadImage($image); + if (is_array($uploadValue)) { + //TODO 拼接图片地址 + if ($uploadValue['image_type'] == 1) { + $imagePath = $siteUrl . $uploadValue['path']; + } else { + $imagePath = $uploadValue['path']; + } + //写入数据库 + if (!$uploadValue['is_exists']) { + $systemAttachmentService->save([ + 'name' => $uploadValue['name'], + 'real_name' => $uploadValue['name'], + 'att_dir' => $imagePath, + 'satt_dir' => $imagePath, + 'att_size' => $uploadValue['size'], + 'att_type' => $uploadValue['mime'], + 'image_type' => $uploadValue['image_type'], + 'module_type' => 1, + 'time' => time(), + 'pid' => $data['pid'], + ]); + } + } + } + return true; + } +} diff --git a/demo/thinkphp/backend/app/services/system/config/SystemConfigServices.php b/demo/thinkphp/backend/app/services/system/config/SystemConfigServices.php new file mode 100644 index 0000000000000000000000000000000000000000..29ef24370943b7ac9d5eb3692b81af4792e06b76 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/config/SystemConfigServices.php @@ -0,0 +1,1262 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\config; + + +use app\dao\system\config\SystemConfigDao; +use app\services\agent\AgentManageServices; +use app\services\BaseServices; +use phoenix\exceptions\AdminException; +use phoenix\services\FileService; +use phoenix\services\FormBuilder; +use think\facade\Log; + +/** + * 系统配置 + * Class SystemConfigServices + * @package app\services\system\config + * @method count(array $where = []) 获取指定条件下的count + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取一条数据 + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method delete(int $id, ?string $key = null) 删除数据 + * @method getUploadTypeList(string $configName) 获取上传配置中的上传类型 + */ +class SystemConfigServices extends BaseServices +{ + /** + * form表单句柄 + * @var FormBuilder + */ + protected $builder; + + /** + * 表单数据切割符号 + * @var string + */ + protected string $cuttingStr = '=>'; + + /** + * 表单提交url + * @var string[] + */ + protected array $postUrl = [ + 'setting' => [ + 'url' => '/setting/config/save_basics', + 'auth' => [], + ], + 'serve' => [ + 'url' => '/serve/sms_config/save_basics', + 'auth' => ['short_letter_switch'], + ], + 'freight' => [ + 'url' => '/freight/config/save_basics', + 'auth' => ['express'], + ], + 'agent' => [ + 'url' => '/agent/config/save_basics', + 'auth' => ['fenxiao'], + ], + 'marketing' => [ + 'url' => '/marketing/integral_config/save_basics', + 'auth' => ['point'], + ] + ]; + + /** + * 子集控制规则 + * @var array[] + */ + protected array $relatedRule = [ + 'brokerage_func_status' => [ + 'son_type' => [ + 'store_brokerage_statu' => [ + 'son_type' => ['store_brokerage_price' => ''], + 'show_value' => 3 + ], + 'brokerage_bindind' => '', + 'store_brokerage_binding_status' => [ + 'son_type' => ['store_brokerage_binding_time' => ''], + 'show_value' => 2 + ], + 'spread_banner' => '', + 'brokerage_level' => '', + 'division_status' => '', + ], + 'show_value' => 1 + ], + 'brokerage_user_status' => [ + 'son_type' => [ + 'uni_brokerage_price' => '', + 'day_brokerage_price_upper' => '', + ], + 'show_value' => 1 + ], + 'invoice_func_status' => [ + 'son_type' => [ + 'special_invoice_status' => '', + ], + 'show_value' => 1 + ], + 'member_func_status' => [ + 'son_type' => [ + 'order_give_exp' => '', + 'sign_give_exp' => '', + 'invite_user_exp' => '' + ], + 'show_value' => 1 + ], + 'balance_func_status' => [ + 'son_type' => [ + 'recharge_attention' => '', + 'recharge_switch' => '', + 'store_user_min_recharge' => '', + ], + 'show_value' => 1 + ], + 'pay_wechat_type' => [ + 'son_type' => [ + 'pay_weixin_key' => '', + ], + 'show_value' => 0 + ], + 'pay_wechat_type@' => [ + 'son_type' => [ + 'pay_weixin_serial_no' => '', + 'pay_weixin_key_v3' => '' + ], + 'show_value' => 1 + ], + 'image_watermark_status' => [ + 'son_type' => [ + 'watermark_type' => [ + 'son_type' => [ + 'watermark_image' => '', + 'watermark_opacity' => '', + 'watermark_rotate' => '', + ], + 'show_value' => 1 + ], + 'watermark_position' => '', + 'watermark_x' => '', + 'watermark_y' => '', + 'watermark_type@' => [ + 'son_type' => [ + 'watermark_text' => '', + 'watermark_text_size' => '', + 'watermark_text_color' => '', + 'watermark_text_angle' => '' + ], + 'show_value' => 2 + ], + ], + 'show_value' => 1 + ], + 'customer_type' => [ + 'son_type' => [ + 'customer_phone' => '', + ], + 'show_value' => 1 + ], + 'customer_type@' => [ + 'son_type' => [ + 'customer_url' => '', + 'customer_corpId' => '', + ], + 'show_value' => 2 + ], + 'pay_new_weixin_open' => [ + 'son_type' => [ + 'pay_new_weixin_mchid' => '' + ], + 'show_value' => 1 + ] + ]; + + public function __construct(SystemConfigDao $dao, FormBuilder $builder) + { + $this->dao = $dao; + $this->builder = $builder; + } + + /** + * @return array|int[]|string[] + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/04/12 + */ + public function getSonConfig(): array + { + $sonConfig = []; + $rolateRule = $this->relatedRule; + if ($rolateRule) { + foreach ($rolateRule as $key => $value) { + $sonConfig = array_merge($sonConfig, array_keys($value['son_type'])); + foreach ($value['son_type'] as $k => $v) { + if (isset($v['son_type'])) { + $sonConfig = array_merge($sonConfig, array_keys($v['son_type'])); + } + } + } + } + return $sonConfig; + } + + /** + * 获取单个系统配置 + * @param string $configName + * @param null $default + * @return mixed|null + * @throws \ReflectionException + */ + public function getConfigValue(string $configName, $default = null): mixed + { + $value = $this->dao->getConfigValue($configName); + return is_null($value) ? $default : json_decode($value, true); + } + + /** + * 获取全部配置 + * @param array $configName + * @return array + * @throws \ReflectionException + */ + public function getConfigAll(array $configName = []) + { + return array_map(function ($item) { + return json_decode($item, true); + }, $this->dao->getConfigAll($configName)); + } + + /** + * 获取配置并分页 + * + * @param array $where + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function getConfigList(array $where): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getConfigList($where, $page, $limit); + $count = $this->dao->count($where); + $tidy_srr = []; + foreach ($list as &$item) { + $item['value'] = $item['value'] ? json_decode($item['value'], true) ?: '' : ''; + if ($item['type'] == 'radio' || $item['type'] == 'checkbox') { + $item['value'] = $this->getRadioOrCheckboxValueInfo($item['menu_name'], $item['value']); + } + if ($item['type'] == 'upload' && !empty($item['value'])) { + if ($item['upload_type'] == 1 || $item['upload_type'] == 3) { + $item['value'] = [set_file_url($item['value'])]; + } elseif ($item['upload_type'] == 2) { + $item['value'] = set_file_url($item['value']); + } + foreach ($item['value'] as $key => $value) { + $tidy_srr[$key]['filepath'] = $value; + $tidy_srr[$key]['filename'] = basename($value); + } + $item['value'] = $tidy_srr; + } + } + return compact('count', 'list'); + } + + /** + * 获取单选按钮或者多选按钮的显示值 + * + * @param $menu_name + * @param $value + * + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException|\think\db\exception\DbException + */ + public function getRadioOrCheckboxValueInfo(string $menu_name, $value): string + { + $option = []; + $config_one = $this->dao->getOne(['menu_name' => $menu_name]); + if (!$config_one) { + return ''; + } + $parameter = explode("\n", $config_one['parameter']); + foreach ($parameter as $k => $v) { + if (isset($v) && strlen($v) > 0) { + $data = explode('=>', $v); + $option[$data[0]] = $data[1]; + } + } + $str = ''; + if (is_array($value)) { + foreach ($value as $v) { + $str .= $option[$v] . ','; + } + } else { + $str .= !empty($value) ? $option[$value] ?? '' : $option[0] ?? ''; + } + return $str; + } + + /** + * 获取系统配置信息 + * @param int $tabId + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getReadList($tabId): array + { + $info = $this->dao->getConfigTabAllList($tabId); + foreach ($info as $k => $v) { + if (!is_null(json_decode($v['value']))) + $info[$k]['value'] = json_decode($v['value'], true); + if ($v['type'] == 'upload' && !empty($v['value'])) { + if ($v['upload_type'] == 1 || $v['upload_type'] == 3) $info[$k]['value'] = explode(',', $v['value']); + } + } + return $info; + } + + /** + * 创建单行表单 + * @param string $type + * @param array $data + * @return array + */ + public function createTextForm(string $type, array $data): array + { + $formbuider = []; + switch ($type) { + case 'number': + $data['value'] = isset($data['value']) ? json_decode($data['value'], true) : 0; + $formbuider[] = $this->builder->number($data['menu_name'], $data['info'], (float)$data['value'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ]); + break; + case 'dateTime': + $formbuider[] = $this->builder->dateTime($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ]); + break; + case 'color': + $data['value'] = isset($data['value']) ? json_decode($data['value'], true) : ''; + $formbuider[] = $this->builder->color($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ]); + break; + default: + $data['value'] = isset($data['value']) ? json_decode($data['value'], true) : ''; + if ($data['menu_name'] == 'api') { + $formbuider[] = $this->builder->input($data['menu_name'], $data['info'], strpos($data['value'], 'http') === false ? sys_config('site_url') . $data['value'] : $data['value'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ])->col(13)->readonly(true); + } else { + $formbuider[] = $this->builder->input($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ])->col(13); + } + break; + } + return $formbuider; + } + + /** + * 创建多行文本框 + * @param array $data + * @return mixed + */ + public function createTextareaForm(array $data): mixed + { + $data['value'] = json_decode($data['value'], true) ?: ''; + $formbuider[] = $this->builder->textarea($data['menu_name'], $data['info'], $data['value'])->placeholder($data['desc'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ])->rows(6)->col(13); + return $formbuider; + } + + /** + * 创建当选表单 + * @param array $data + * @param array $control + * @param array $control_two + * @return array + */ + public function createRadioForm(array $data, $control = [], $control_two = []): array + { + $formbuider = []; + $data['value'] = json_decode($data['value'], true) ?: '0'; + $parameter = explode("\n", $data['parameter']); + $options = []; + if ($parameter) { + foreach ($parameter as $v) { + if (strstr($v, $this->cuttingStr) !== false) { + $pdata = explode($this->cuttingStr, $v); + $res = preg_match('/^[0-9]$/', $pdata[0]); + $options[] = ['label' => $pdata[1], 'value' => $res ? (int)$pdata[0] : $pdata[0]]; + } + } + $res = preg_match('/^[0-9]$/', $data['value']); + $formbuider[] = $radio = $this->builder->radio($data['menu_name'], $data['info'], $res ? (int)$data['value'] : $data['value'])->options($options)->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ])->col(13); + if ($control) { + $radio->appendControl($data['show_value'] ?? 1, is_array($control) ? $control : [$control]); + } + if ($control_two && isset($data['show_value2'])) { + $radio->appendControl($data['show_value2'] ?? 2, is_array($control_two) ? $control_two : [$control_two]); + } + return $formbuider; + } + } + + /** + * 创建上传组件表单 + * @param int $type + * @param array $data + * @return array + */ + public function createUploadForm(int $type, array $data): array + { + $formbuider = []; + switch ($type) { + case 1: + $data['value'] = json_decode($data['value'], true) ?: ''; + if ($data['value'] != '') $data['value'] = set_file_url($data['value']); + $formbuider[] = $this->builder->frameImage($data['menu_name'], $data['info'], $this->url(config('app.admin_prefix', 'admin') . '/widget.images/index', ['fodder' => $data['menu_name']], true), $data['value']) + ->icon('ios-image')->width('950px')->height('560px')->modal(['footer-hide' => true])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ])->col(13); + break; + case 2: + $data['value'] = json_decode($data['value'], true) ?: []; + if ($data['value']) + $data['value'] = set_file_url($data['value']); + $formbuider[] = $this->builder->frameImages($data['menu_name'], $data['info'], $this->url(config('app.admin_prefix', 'admin') . '/widget.images/index', ['fodder' => $data['menu_name'], 'type' => 'many', 'maxLength' => 5], true), $data['value']) + ->maxLength(5)->icon('ios-images')->width('950px')->height('560px')->modal(['footer-hide' => true]) + ->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ])->col(13); + break; + case 3: + $data['value'] = json_decode($data['value'], true) ?: ''; + if ($data['value'] != '') $data['value'] = set_file_url($data['value']); + $formbuider[] = $this->builder->uploadFile($data['menu_name'], $data['info'], $this->url('/adminapi/file/upload/1', ['type' => 1], false, true), $data['value']) + ->name('file')->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ])->col(13)->data(['menu_name' => $data['menu_name']])->headers([ + 'Authori-zation' => app()->request->header('Authori-zation'), + ]); + break; + } + return $formbuider; + } + + /** + * 创建单选框 + * @param array $data + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createCheckboxForm(array $data): array + { + $formbuider = []; + $data['value'] = json_decode($data['value'], true) ?: []; + $parameter = explode("\n", $data['parameter']); + $options = []; + if ($parameter) { + foreach ($parameter as $v) { + if (strstr($v, $this->cuttingStr) !== false) { + $pdata = explode($this->cuttingStr, $v); + $options[] = ['label' => $pdata[1], 'value' => $pdata[0]]; + } + } + $formbuider[] = $this->builder->checkbox($data['menu_name'], $data['info'], $data['value'])->options($options)->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ])->col(13); + } + return $formbuider; + } + + /** + * 创建选择框表单 + * @param array $data + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createSelectForm(array $data): array + { + $formbuider = []; + $data['value'] = json_decode($data['value'], true) ?: []; + $parameter = explode("\n", $data['parameter']); + $options = []; + if ($parameter) { + foreach ($parameter as $v) { + if (strstr($v, $this->cuttingStr) !== false) { + $pdata = explode($this->cuttingStr, $v); + $options[] = ['label' => $pdata[1], 'value' => $pdata[0]]; + } + } + $formbuider[] = $this->builder->select($data['menu_name'], $data['info'], $data['value'])->options($options)->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ])->col(13); + } + return $formbuider; + } + + /** + * 创建颜色选择器 + * @param array $data + * @return mixed + */ + public function createColorForm(array $data): mixed + { + $data['value'] = json_decode($data['value'], true) ?: ''; + $formbuider[] = $this->builder->color($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']] + ])->col(13); + return $formbuider; + } + + public function bindBuilderData($data, $relatedRule): bool|array + { + if (!$data) return false; + $p_list = array(); + foreach ($relatedRule as $rk => $rv) { + $p_list[$rk] = $data[$rk]; + if (isset($rv['son_type']) && is_array($rv['son_type'])) { + foreach ($rv['son_type'] as $sk => $sv) { + if (is_array($sv) && isset($sv['son_type'])) { + foreach ($sv['son_type'] as $ssk => $ssv) { + $tmp = $data[$sk]; + $tmp['console'] = $data[$ssk]; + $p_list[$rk]['console'][] = $tmp; + } + } else { + $p_list[$rk]['console'][] = $data[$sk]; + } + } + } + + } + return array_values($p_list); + } + + /** + * 获取系统配置表单 + * @param $data + * @param bool $control + * @param array $controle_two + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function formTypeShine($data, $control = false, $controle_two = []): array + { + + switch ($data['type']) { + case 'text'://文本框 + return $this->createTextForm($data['input_type'], $data); + case 'radio'://单选框 + return $this->createRadioForm($data, $control, $controle_two); + case 'textarea'://多行文本框 + return $this->createTextareaForm($data); + case 'upload'://文件上传 + return $this->createUploadForm((int)$data['upload_type'], $data); + case 'checkbox'://多选框 + return $this->createCheckboxForm($data); + case 'select'://多选框 + return $this->createSelectForm($data); + case 'color': + return $this->createColorForm($data); + } + } + + /** + * @param int $tabId + * @param array $formData + * @param array $relatedRule + * @return array|bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function createConfigForm(int $tabId, array $relatedRule): bool|array + { + $list = $this->dao->getConfigTabAllList($tabId); + if (!$relatedRule) { + $formbuider = $this->createNoCrontrolForm($list); + } else { + $formbuider = $this->createBindCrontrolForm($list, $relatedRule); + } + return $formbuider; + } + + /** + * 创建 + * @param array $list + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function createForm(array $list): array + { + if (!$list) return []; + $list = array_combine(array_column($list, 'menu_name'), $list); + $formbuider = []; + $relateRule = $this->relatedRule; + $sonConfig = $this->getSonConfig(); + foreach ($list as $key => $data) { + if (in_array($key, $sonConfig)) { + continue; + } + switch ($data['type']) { + case 'text'://文本框 + $formbuider = array_merge($formbuider, $this->createTextForm($data['input_type'], $data)); + break; + case 'radio'://单选框 + $builder = []; + if (isset($relateRule[$key])) { + $role = $relateRule[$key]; + $data['show_value'] = $role['show_value']; + foreach ($role['son_type'] as $sk => $sv) { + if (isset($list[$sk])) { + $son_data = $list[$sk]; + $son_data['show_value'] = $role['show_value']; + $son_build = []; + if (isset($sv['son_type'])) { + foreach ($sv['son_type'] as $ssk => $ssv) { + $son_data['show_value'] = $sv['show_value']; + $son_build[] = $this->formTypeShine($list[$ssk])[0]; + unset($list[$ssk]); + } + } + $son_build_two = []; + if (isset($role['son_type'][$sk . '@'])) { + $son_type_two = $role['son_type'][$sk . '@']; + $son_data['show_value2'] = $son_type_two['show_value']; + if (isset($son_type_two['son_type'])) { + foreach ($son_type_two['son_type'] as $ssk => $ssv) { + if (isset($list[$ssk]['menu_name']) && $list[$ssk]['menu_name'] == 'watermark_text_color') $list[$ssk]['type'] = 'color'; + $son_build_two[] = $this->formTypeShine($list[$ssk])[0]; + unset($list[$ssk]); + } + } + } + $builder[] = $this->formTypeShine($son_data, $son_build, $son_build_two)[0]; + unset($list[$sk]); + } + } + $data['show_value'] = $role['show_value']; + } + $builder_two = []; + if (isset($relateRule[$key . '@'])) { + $role = $relateRule[$key . '@']; + $data['show_value2'] = $role['show_value']; + foreach ($role['son_type'] as $sk => $sv) { + $son_data = $list[$sk]; + $son_data['show_value'] = $role['show_value']; + $builder_two[] = $this->formTypeShine($son_data)[0]; + } + } + $formbuider = array_merge($formbuider, $this->createRadioForm($data, $builder, $builder_two)); + break; + case 'textarea'://多行文本框 + $formbuider = array_merge($formbuider, $this->createTextareaForm($data)); + break; + case 'upload'://文件上传 + $formbuider = array_merge($formbuider, $this->createUploadForm((int)$data['upload_type'], $data)); + break; + case 'checkbox'://多选框 + $formbuider = array_merge($formbuider, $this->createCheckboxForm($data)); + break; + case 'select'://多选框 + $formbuider = array_merge($formbuider, $this->createSelectForm($data)); + break; + } + } + return $formbuider; + } + + /**无组件绑定规则 + * @param array $list + * @return array|bool + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function createNoCrontrolForm(array $list) + { + if (!$list) return false; + $formbuider = []; + foreach ($list as $key => $data) { + + switch ($data['type']) { + case 'text'://文本框 + $formbuider = array_merge($formbuider, $this->createTextForm($data['input_type'], $data)); + break; + case 'radio'://单选框 + $formbuider = array_merge($formbuider, $this->createRadioForm($data)); + break; + case 'textarea'://多行文本框 + $formbuider = array_merge($formbuider, $this->createTextareaForm($data)); + break; + case 'upload'://文件上传 + $formbuider = array_merge($formbuider, $this->createUploadForm((int)$data['upload_type'], $data)); + break; + case 'checkbox'://多选框 + $formbuider = array_merge($formbuider, $this->createCheckboxForm($data)); + break; + case 'select'://多选框 + $formbuider = array_merge($formbuider, $this->createSelectForm($data)); + break; + } + } + return $formbuider; + } + + /** + * 有组件绑定规则 + * @param array $list + * @param array $relatedRule + * @return array|bool + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function createBindCrontrolForm(array $list, array $relatedRule) + { + if (!$list || !$relatedRule) return false; + $formbuider = []; + $new_data = array(); + foreach ($list as $dk => $dv) { + $new_data[$dv['menu_name']] = $dv; + } + foreach ($relatedRule as $rk => $rv) { + if (isset($rv['son_type'])) { + $data = $new_data[$rk]; + switch ($data['type']) { + case 'text'://文本框 + $formbuider = array_merge($formbuider, $this->createTextForm($data['input_type'], $data)); + break; + case 'radio'://单选框 + $son_builder = array(); + foreach ($rv['son_type'] as $sk => $sv) { + if (isset($sv['son_type'])) { + foreach ($sv['son_type'] as $ssk => $ssv) { + $son_data = $new_data[$sk]; + $son_data['show_value'] = $sv['show_value']; + $son_builder[] = $this->formTypeShine($son_data, $this->formTypeShine($new_data[$ssk])[0])[0]; + } + } else { + $son_data = $new_data[$sk]; + $son_data['show_value'] = $rv['show_value']; + $son_builder[] = $this->formTypeShine($son_data)[0]; + } + + } + $formbuider = array_merge($formbuider, $this->createRadioForm($data, $son_builder)); + break; + case 'textarea'://多行文本框 + $formbuider = array_merge($formbuider, $this->createTextareaForm($data)); + break; + case 'upload'://文件上传 + $formbuider = array_merge($formbuider, $this->createUploadForm((int)$data['upload_type'], $data)); + break; + case 'checkbox'://多选框 + $formbuider = array_merge($formbuider, $this->createCheckboxForm($data)); + break; + case 'select'://多选框 + $formbuider = array_merge($formbuider, $this->createSelectForm($data)); + break; + } + } + } + return $formbuider; + } + + /** + * 系统配置form表单创建 + * @param $url + * @param int $tabId + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ +// public function getConfigForm($url, int $tabId) +// { +// /** @var SystemConfigTabServices $service */ +// $service = app()->make(SystemConfigTabServices::class); +// $title = $service->value(['id' => $tabId], 'title'); +// $list = $this->dao->getConfigTabAllList($tabId); +// $formbuider = $this->createForm($list); +// $name = 'setting'; +// if ($url) { +// $name = explode('/', $url)[2] ?? $name; +// } +// $postUrl = $this->postUrl[$name]['url'] ?? '/setting/config/save_basics'; +// return create_form($title, $formbuider, $this->url($postUrl), 'POST'); +// } + + /** + * 新增路由增加设置项验证 + * @param $url + * @param $post + * @return bool + */ + public function checkParam($url, $post) + { + $name = ''; + if ($url) { + $name = explode('/', $url)[2] ?? $name; + } + $auth = $this->postUrl[$name]['auth'] ?? false; + if ($auth === false) { + throw new AdminException(400601); + } + if ($auth) { + /** @var SystemConfigTabServices $systemConfigTabServices */ + $systemConfigTabServices = app()->make(SystemConfigTabServices::class); + foreach ($post as $key => $value) { + $tab_ids = $systemConfigTabServices->getColumn([['eng_title', 'IN', $auth]], 'id'); + if (!$tab_ids || !in_array($key, $this->dao->getColumn([['config_tab_id', 'IN', $tab_ids]], 'menu_name'))) { + throw new AdminException(400602); + } + } + } + return true; + } + + /** + * 修改配置获取form表单 + * @param int $id + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function editConfigForm(int $id) + { + $menu = $this->dao->get($id)->getData(); + if (!$menu) { + throw new AdminException(100026); + } + /** @var SystemConfigTabServices $service */ + $service = app()->make(SystemConfigTabServices::class); + $formbuider = []; + $formbuider[] = $this->builder->input('menu_name', '字段变量', $menu['menu_name'])->disabled(1); + $formbuider[] = $this->builder->hidden('type', $menu['type']); + $formbuider[] = $this->builder->select('config_tab_id', '分类', (int)$menu['config_tab_id'])->setOptions($service->getSelectForm()); + $formbuider[] = $this->builder->input('info', '配置名称', $menu['info'])->autofocus(1); + $formbuider[] = $this->builder->input('desc', '配置简介', $menu['desc']); + switch ($menu['type']) { + case 'text': + $menu['value'] = json_decode($menu['value'], true); + $formbuider[] = $this->builder->select('input_type', '类型', $menu['input_type'])->setOptions([ + ['value' => 'input', 'label' => '文本框'] + , ['value' => 'dateTime', 'label' => '时间'] + , ['value' => 'color', 'label' => '颜色'] + , ['value' => 'number', 'label' => '数字'] + ]); + //输入框验证规则 + $formbuider[] = $this->builder->input('value', '默认值', $menu['value']); + if (!empty($menu['required'])) { + $formbuider[] = $this->builder->number('width', '文本框宽(%)', (int)$menu['width']); + $formbuider[] = $this->builder->input('required', '验证规则', $menu['required'])->placeholder('多个请用,隔开例如:required:true,url:true'); + } + break; + case 'textarea': + $menu['value'] = json_decode($menu['value'], true); + //多行文本 + if (!empty($menu['high'])) { + $formbuider[] = $this->builder->textarea('value', '默认值', $menu['value'])->rows(5); + $formbuider[] = $this->builder->number('width', '文本框宽(%)', (int)$menu['width']); + $formbuider[] = $this->builder->number('high', '多行文本框高(%)', (int)$menu['high']); + } else { + $formbuider[] = $this->builder->input('value', '默认值', $menu['value']); + } + break; + case 'radio': + $formbuider = array_merge($formbuider, $this->createRadioForm($menu)); + //单选和多选参数配置 + if (!empty($menu['parameter'])) { + $formbuider[] = $this->builder->textarea('parameter', '配置参数', $menu['parameter'])->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色"); + } + break; + case 'checkbox': + $formbuider = array_merge($formbuider, $this->createCheckboxForm($menu)); + //单选和多选参数配置 + if (!empty($menu['parameter'])) { + $formbuider[] = $this->builder->textarea('parameter', '配置参数', $menu['parameter'])->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色"); + } + break; + case 'upload': + $formbuider = array_merge($formbuider, $this->createUploadForm(($menu['upload_type']), $menu)); + //上传类型选择 + if (!empty($menu['upload_type'])) { + $formbuider[] = $this->builder->radio('upload_type', '上传类型', $menu['upload_type'])->options([['value' => 1, 'label' => '单图'], ['value' => 2, 'label' => '多图'], ['value' => 3, 'label' => '文件']]); + } + break; + } + $formbuider[] = $this->builder->number('sort', '排序', (int)$menu['sort']); + $formbuider[] = $this->builder->radio('status', '状态', $menu['status'])->options([['value' => 1, 'label' => '显示'], ['value' => 0, 'label' => '隐藏']]); + return create_form('编辑字段', $formbuider, $this->url('/setting/config/' . $id), 'PUT'); + } + + /** + * 字段状态 + * @return array + */ + public function formStatus(): array + { + return [['value' => 1, 'label' => '显示'], ['value' => 0, 'label' => '隐藏']]; + } + + /** + * 选择文文件类型 + * @return array + */ + public function uploadType(): array + { + return [ + ['value' => 1, 'label' => '单图'] + , ['value' => 2, 'label' => '多图'] + , ['value' => 3, 'label' => '文件'] + ]; + } + + /** + * 选择文本框类型 + * @return array + */ + public function textType(): array + { + return [ + ['value' => 'input', 'label' => '文本框'] + , ['value' => 'dateTime', 'label' => '时间'] + , ['value' => 'color', 'label' => '颜色'] + , ['value' => 'number', 'label' => '数字'] + ]; + } + + /** + * 获取创建配置规格表单 + * @param int $type + * @param int $tab_id + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function createFormRule(int $type, int $tab_id): array + { + /** @var SystemConfigTabServices $service */ + $service = app()->make(SystemConfigTabServices::class); + $formbuider = []; + $form_type = ''; + $info_type = []; + $parameter = []; + switch ($type) { + case 0://文本框 + $form_type = 'text'; + $info_type = $this->builder->select('input_type', '类型')->setOptions($this->textType()); + $parameter[] = $this->builder->input('value', '默认值'); + $parameter[] = $this->builder->number('width', '文本框宽(%)', 100); + $parameter[] = $this->builder->input('required', '验证规则')->placeholder('多个请用,隔开例如:required:true,url:true'); + break; + case 1://多行文本框 + $form_type = 'textarea'; + $parameter[] = $this->builder->textarea('value', '默认值'); + $parameter[] = $this->builder->number('width', '文本框宽(%)', 100); + $parameter[] = $this->builder->number('high', '多行文本框高(%)', 5); + break; + case 2://单选框 + $form_type = 'radio'; + $parameter[] = $this->builder->textarea('parameter', '配置参数')->placeholder("参数方式例如:\n1=>男\n2=>女\n3=>保密"); + $parameter[] = $this->builder->input('value', '默认值'); + break; + case 3://文件上传 + $form_type = 'upload'; + $parameter[] = $this->builder->radio('upload_type', '上传类型', 1)->options($this->uploadType()); + break; + case 4://多选框 + $form_type = 'checkbox'; + $parameter[] = $this->builder->textarea('parameter', '配置参数')->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色"); + break; + case 5://下拉框 + $form_type = 'select'; + $parameter[] = $this->builder->textarea('parameter', '配置参数')->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色"); + break; + } + if ($form_type) { + $formbuider[] = $this->builder->hidden('type', $form_type); + $formbuider[] = $this->builder->select('config_tab_id', '分类', $tab_id)->setOptions($service->getSelectForm()); + if ($info_type) { + $formbuider[] = $info_type; + } + $formbuider[] = $this->builder->input('info', '配置名称')->autofocus(1); + $formbuider[] = $this->builder->input('menu_name', '字段变量')->placeholder('例如:site_url'); + $formbuider[] = $this->builder->input('desc', '配置简介'); + $formbuider = array_merge($formbuider, $parameter); + $formbuider[] = $this->builder->number('sort', '排序', 0); + $formbuider[] = $this->builder->radio('status', '状态', 1)->options($this->formStatus()); + } + return create_form('添加字段', $formbuider, $this->url('/setting/config'), 'POST'); + } + + /** + * radio 和 checkbox规则的判断 + * @param $data + * @return bool + */ + public function valiDateRadioAndCheckbox($data) + { + $option = []; + $option_new = []; + $data['parameter'] = str_replace("\r\n", "\n", $data['parameter']);//防止不兼容 + $parameter = explode("\n", $data['parameter']); + if (count($parameter) < 2) { + throw new AdminException(400603); + } + foreach ($parameter as $k => $v) { + if (isset($v) && !empty($v)) { + $option[$k] = explode('=>', $v); + } + } + if (count($option) < 2) { + throw new AdminException(400603); + } + $bool = 1; + foreach ($option as $k => $v) { + $option_new[$k] = $option[$k][0]; + foreach ($v as $kk => $vv) { + $vv_num = strlen($vv); + if (!$vv_num) { + $bool = 0; + } + } + } + if (!$bool) { + throw new AdminException(400603); + } + $num1 = count($option_new);//提取该数组的数目 + $arr2 = array_unique($option_new);//合并相同的元素 + $num2 = count($arr2);//提取合并后数组个数 + if ($num1 > $num2) { + throw new AdminException(400603); + } + return true; + } + + /** + * 验证参数 + * @param $data + * @return bool + */ + public function valiDateValue($data) + { + if (!$data || !isset($data['required']) || !$data['required']) { + return true; + } + $valids = explode(',', $data['required']); + foreach ($valids as $valid) { + $valid = explode(':', $valid); + if (isset($valid[0]) && isset($valid[1])) { + $k = strtolower(trim($valid[0])); + $v = strtolower(trim($valid[1])); + switch ($k) { + case 'required': + if ($v == 'true' && $data['value'] === '') { + throw new AdminException(400604, ['name' => $data['info'] ?? '']); + } + break; + case 'url': + if ($v == 'true' && !check_link($data['value'])) { + throw new AdminException(400605, ['name' => $data['info'] ?? '']); + } + break; + } + } + } + } + + /** + * 保存平台电子面单打印信息 + * @param array $data + * @return bool + */ + public function saveExpressInfo(array $data) + { + if (!is_array($data) || !$data) return false; + // config_export_id 快递公司id + // config_export_temp_id 快递公司模板id + // config_export_com 快递公司编码 + // config_export_to_name 发货人姓名 + // config_export_to_tel 发货人电话 + // config_export_to_address 发货人详细地址 + // config_export_siid 电子面单打印机编号 + foreach ($data as $key => $value) { + $this->dao->update(['menu_name' => 'config_export_' . $key], ['value' => json_encode($value)]); + } + $this->cacheDriver()->clear(); + return true; + } + + /** + * 获取分享海报 兼容方法 + */ + public function getSpreadBanner() + { + //配置 + $banner = sys_config('spread_banner', []); + if (!$banner) { + //组合数据 + $banner = sys_data('routine_spread_banner'); + if ($banner) { + $banner = array_column($banner, 'pic'); + $this->dao->update(['menu_name' => 'spread_banner'], ['value' => json_encode($banner)]); + $this->cacheDriver()->clear(); + } + } + return $banner; + } + + /** + * 保存wss配置 + * @param int $wssOpen + * @param string $wssLocalpk + * @param string $wssLocalCert + */ + public function saveSslFilePath(int $wssOpen, string $wssLocalpk, string $wssLocalCert) + { + $wssFile = root_path() . '.wss'; + $content = <<make(SystemConfigTabServices::class); + //上传配置->基础配置 + $tab_id = $systemConfigTabServices->getColumn(['eng_title' => 'base_config'], 'id'); + if ($tab_id) { + $all = $this->dao->getColumn(['config_tab_id' => $tab_id], 'value', 'menu_name'); + if (array_intersect(array_keys($all), array_keys($post))) { + foreach ($post as $key => $item) { + //配置更改删除原来生成的缩略图 + if (isset($all[$key]) && $item != json_decode($all[$key], true)) { + try { + FileService::delDir(public_path('uploads/thumb_water')); + break; + } catch (\Throwable $e) { + + } + } + } + } + } + return true; + } + + /** + * 变更分销绑定关系模式 + * @param array $post + * @return bool + */ + public function checkBrokerageBinding(array $post) + { + try { + $config_data = $post['store_brokerage_binding_status']; + $config_one = $this->dao->getOne(['menu_name' => 'store_brokerage_binding_status']); + $config_old = json_decode($config_one['value'], true); + if ($config_old != 2 && $config_data == 2) { + //自动解绑上级绑定 + + /** @var AgentManageServices $agentManage */ + $agentManage = app()->make(AgentManageServices::class); + $agentManage->resetSpreadTime(); + } + } catch (\Throwable $e) { + Log::error('变更分销绑定模式重置绑定时间失败,失败原因:' . $e->getMessage()); + return false; + } + return true; + } +} diff --git a/demo/thinkphp/backend/app/services/system/config/SystemConfigTabServices.php b/demo/thinkphp/backend/app/services/system/config/SystemConfigTabServices.php new file mode 100644 index 0000000000000000000000000000000000000000..ed7f800563dadf3d432139e0013db0c4864aec64 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/config/SystemConfigTabServices.php @@ -0,0 +1,139 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\config; + + +use app\dao\system\config\SystemConfigTabDao; +use app\services\BaseServices; +use crmeb\exceptions\AdminException; +use crmeb\services\FormBuilder as Form; + +/** + * 系统配置分类 + * Class SystemConfigTabServices + * @package app\services\system\config + * @method save(array $data) 写入数据 + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method delete($id, ?string $key = null) 删除数据 + */ +class SystemConfigTabServices extends BaseServices +{ + /** + * SystemConfigTabServices constructor. + * @param SystemConfigTabDao $dao + */ + public function __construct(SystemConfigTabDao $dao) + { + $this->dao = $dao; + } + + /** + * 系统设置头部分类读取 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfigTab(int $pid) + { + $list = $this->dao->getConfigTabAll(['status' => 1, 'pid' => $pid], ['id', 'id as value', 'title as label', 'pid', 'icon', 'type'], $pid ? [] : [['type', '=', '0']]); + return get_tree_children($list); + } + + /** + * 获取配置分类列表 + * @param array $where + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfgTabList(array $where) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getConfgTabList($where, $page, $limit); + $count = $this->dao->count($where); + $menusValue = []; + foreach ($list as $item) { + $menusValue[] = $item->getData(); + } + $list = get_tree_children($menusValue); + return compact('list', 'count'); + } + + /** + * 获取配置分类选择下拉树 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getSelectForm() + { + $menuList = $this->dao->getConfigTabAll([], ['id', 'pid', 'title']); + $list = sort_list_tier($menuList, 0, 'pid', 'id'); + $menus = [['value' => 0, 'label' => '顶级按钮']]; + foreach ($list as $menu) { + $menus[] = ['value' => $menu['id'], 'label' => $menu['html'] . $menu['title']]; + } + return $menus; + } + + /** + * 创建form表单 + * @param array $formData + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function createConfigTabForm(array $formData = []) + { + $form[] = Form::select('pid', '父级分类', isset($formData['pid']) ? (string)$formData['pid'] : '')->setOptions($this->getSelectForm())->filterable(true); + $form[] = Form::input('title', '分类名称', $formData['title'] ?? ''); + $form[] = Form::input('eng_title', '分类字段英文', $formData['eng_title'] ?? ''); + $form[] = Form::frameInput('icon', '图标', $this->url(config('app.admin_prefix', 'admin') . '/widget.widgets/icon', ['fodder' => 'icon'], true), $formData['icon'] ?? '')->icon('ios-ionic')->height('560px')->modal(['footer-hide' => true]); + $form[] = Form::radio('type', '类型', $formData['type'] ?? 0)->options([ + ['value' => 0, 'label' => '系统'], + ['value' => 3, 'label' => '其它'] + ]); + $form[] = Form::radio('status', '状态', $formData['status'] ?? 1)->options([['value' => 1, 'label' => '显示'], ['value' => 2, 'label' => '隐藏']]); + $form[] = Form::number('sort', '排序', (int)($formData['sort'] ?? 0))->precision(0); + return $form; + } + + /** + * 添加配置分类表单 + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createForm() + { + return create_form('添加配置分类', $this->createConfigTabForm(), $this->url('/setting/config_class')); + } + + /** + * 修改配置分类表单 + * @param int $id + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function updateForm(int $id) + { + $configTabInfo = $this->dao->get($id); + if (!$configTabInfo) { + throw new AdminException(100026); + } + return create_form('编辑配置分类', $this->createConfigTabForm($configTabInfo->toArray()), $this->url('/setting/config_class/' . $id), 'PUT'); + } +} diff --git a/demo/thinkphp/backend/app/services/system/config/SystemGroupDataServices.php b/demo/thinkphp/backend/app/services/system/config/SystemGroupDataServices.php new file mode 100644 index 0000000000000000000000000000000000000000..6dc690644c5bd0525e16c1555faf798b9afecb95 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/config/SystemGroupDataServices.php @@ -0,0 +1,392 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\config; + +use app\dao\system\config\SystemGroupDataDao; +use app\services\BaseServices; +use crmeb\exceptions\AdminException; +use crmeb\services\FormBuilder as Form; + +/** + * 组合数据数据集 + * Class SystemGroupDataServices + * @package app\services\system\config + * @method delete($id, ?string $key = null) 删除数据 + * @method get(int $id, ?array $field = []) 获取一条数据 + * @method save(array $data) 保存数据 + * @method update($id, array $data, ?string $key = null) 修改数据 + */ +class SystemGroupDataServices extends BaseServices +{ + /** + * SystemGroupDataServices constructor. + * @param SystemGroupDataDao $dao + */ + public function __construct(SystemGroupDataDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取某个配置下的数据从新组合成新得数据返回 + * @param string $configName + * @param int $limit + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfigNameValue(string $configName, int $limit = 0) + { + /** @var SystemGroupServices $systemGroupServices */ + $systemGroupServices = app()->make(SystemGroupServices::class); + $value = $this->dao->getGroupDate((int)$systemGroupServices->getConfigNameId($configName), $limit); + $data = []; + foreach ($value as $key => $item) { + $data[$key]["id"] = $item["id"]; + if (isset($item['status'])) $data[$key]["status"] = $item["status"]; + $fields = json_decode($item["value"], true) ?: []; + foreach ($fields as $index => $field) { + if ($field['type'] == 'upload') { + $data[$key][$index] = set_file_url($field['value']); + } else { + $data[$key][$index] = $field["value"]; + } + } + } + return $data; + } + + /** + * 获取组合数据列表 + * @param array $where + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGroupDataList(array $where) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getGroupDataList($where, $page, $limit); + $count = $this->dao->count($where); + $type = ''; + $gid = (int)$where['gid']; + /** @var SystemGroupServices $services */ + $services = app()->make(SystemGroupServices::class); + $group = $services->getOne(['id' => $gid], 'id,config_name,fields'); + + $header = json_decode($group['fields'], true) ?? []; + $title = []; + $param = []; + foreach ($header as $item) { + if ($group['config_name'] == 'order_details_images' && $item['title'] == 'order_status') { + $status = str_replace("\r\n", "\n", $item["param"]);//防止不兼容 + $status = explode("\n", $status); + if (is_array($status) && !empty($status)) { + foreach ($status as $index => $v) { + $vl = explode('=>', $v); + if (isset($vl[0]) && isset($vl[1])) { + $param[$vl[0]] = $vl[1]; + } + } + } + } + if ($item['type'] == 'upload' || $item['type'] == 'uploads') { + $title[$item['title']] = []; + $type = $item['title']; + } else { + $title[$item['title']] = ''; + } + } + foreach ($list as $key => $value) { + $list[$key] = array_merge($value, $title); + $infos = json_decode($value['value'], true) ?: []; + foreach ($infos as $index => $info) { + if ($group['config_name'] == 'order_details_images' && $index == 'order_status') { + $list[$key][$index] = ($param[$info['value']] ?? '') . '/' . $info['value']; + } else { + if ($info['type'] == 'upload') { + $list[$key][$index] = [set_file_url($info['value'])]; + } elseif ($info['type'] == 'checkbox') { + $list[$key][$index] = implode(",", $info["value"]); + } else { + $list[$key][$index] = $info['value']; + } + } + } + unset($list[$key]['value']); + } + return compact('list', 'count', 'type'); + } + + /** + * 根据gid判断出是否能再次添加组合数据 + * @param int $gid + * @param int $count + * @param string $key + * @return bool + */ + public function isGroupGidSave(int $gid, int $count, string $key): bool + { + /** @var SystemGroupServices $services */ + $services = app()->make(SystemGroupServices::class); + $configName = $services->value(['id' => $gid], 'config_name'); + if ($configName == $key) { + return $this->dao->count(['gid' => $gid]) >= $count; + } else { + return false; + } + } + + /** + * 创建表单 + * @param int $gid + * @param array $groupData + * @return mixed + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createGroupForm(int $gid, array $groupData = []) + { + $groupDataValue = isset($groupData["value"]) ? json_decode($groupData["value"], true) : []; + /** @var SystemGroupServices $services */ + $services = app()->make(SystemGroupServices::class); + $fields = $services->getValueFields($gid); + $f[] = Form::hidden('gid', $gid); + foreach ($fields as $key => $value) { + $info = []; + if (isset($value["param"])) { + $value["param"] = str_replace("\r\n", "\n", $value["param"]);//防止不兼容 + $params = explode("\n", $value["param"]); + if (is_array($params) && !empty($params)) { + foreach ($params as $index => $v) { + $vl = explode('=>', $v); + if (isset($vl[0]) && isset($vl[1])) { + $info[$index]["value"] = $vl[0]; + $info[$index]["label"] = $vl[1]; + } + } + } + } + $fvalue = $groupDataValue[$value['title']]['value'] ?? ''; + switch ($value["type"]) { + case 'input': + if ($gid == 55 && $value['title'] == 'sign_num') { + $f[] = Form::number($value["title"], $value["name"], (int)$fvalue)->precision(0); + } else { + $f[] = Form::input($value["title"], $value["name"], $fvalue); + } + break; + case 'textarea': + $f[] = Form::input($value["title"], $value["name"], $fvalue)->type('textarea')->placeholder($value['param']); + break; + case 'radio': + $f[] = Form::radio($value["title"], $value["name"], $fvalue ?: (int)$info[0]["value"] ?? '')->options($info); + break; + case 'checkbox': + $f[] = Form::checkbox($value["title"], $value["name"], $fvalue ?: $info[0] ?? '')->options($info); + break; + case 'select': + $f[] = Form::select($value["title"], $value["name"], $fvalue !== '' ? $fvalue : $info[0] ?? '')->options($info)->multiple(false); + break; + case 'upload': + if (!empty($fvalue)) { + $image = is_string($fvalue) ? $fvalue : $fvalue[0]; + } else { + $image = ''; + } + $f[] = Form::frameImage($value["title"], $value["name"], $this->url(config('app.admin_prefix', 'admin') . '/widget.images/index', ['fodder' => $value["title"], 'big' => 1], true), $image)->icon('ios-image')->width('950px')->height('560px')->modal(['footer-hide' => true]); + break; + case 'uploads': + if ($fvalue) { + if (is_string($fvalue)) $fvalue = [$fvalue]; + $images = !empty($fvalue) ? $fvalue : []; + } else { + $images = []; + } + $f[] = Form::frameImages($value["title"], $value["name"], $this->url(config('app.admin_prefix', 'admin') . '/widget.images/index', ['fodder' => $value["title"], 'big' => 1, 'type' => 'many', 'maxLength' => 5], true), $images)->maxLength(5)->icon('ios-images')->width('950px')->height('560px')->modal(['footer-hide' => true])->spin(0); + break; + default: + $f[] = Form::input($value["title"], $value["name"], $fvalue); + break; + + } + } + $f[] = Form::number('sort', '排序', (int)($groupData["sort"] ?? 1))->precision(0); + $f[] = Form::radio('status', '状态', (int)($groupData["status"] ?? 1))->options([['value' => 1, 'label' => '显示'], ['value' => 0, 'label' => '隐藏']]); + return $f; + } + + /** + * 获取添加组合数据表单 + * @param int $gid + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createForm(int $gid) + { + return create_form('添加数据', $this->createGroupForm($gid), $this->url('/setting/group_data')); + } + + /** + * 获取修改组合数据表单 + * @param int $gid + * @param int $id + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function updateForm(int $gid, int $id) + { + $groupData = $this->dao->get($id); + if (!$groupData) { + throw new AdminException(100026); + } + return create_form('编辑数据', $this->createGroupForm($gid, $groupData->toArray()), $this->url('/setting/group_data/' . $id), 'PUT'); + } + + /** + * 根据id获取当前记录中的数据 + * @param $id + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function getDateValue($id) + { + $value = $this->dao->get($id); + $data["id"] = $value["id"]; + $data["status"] = $value["status"]; + $fields = json_decode($value["value"], true); + foreach ($fields as $index => $field) { + $data[$index] = $field["value"]; + } + return $data; + } + + /** + * 根据id获取数据 + * @param array $ids + * @param string $field + */ + public function getGroupDataColumn(array $ids) + { + $systemGroup = []; + if (!empty($ids)) { + $systemGroupData = $this->dao->idByGroupList($ids); + if (!empty($systemGroupData)) + $systemGroup = array_combine(array_column($systemGroupData, 'id'), $systemGroupData); + } + return $systemGroup; + } + + /** + * 根据gid删除数据 + * @param int $gid + * @return mixed + */ + public function delGroupDate(int $gid) + { + return $this->dao->delGroupDate($gid); + } + + /** + * 批量保存 + * @param array $params + * @param string $config_name + * @return bool + * @throws \Exception + */ + public function saveAllData(array $params, string $config_name) + { + /** @var SystemGroupServices $systemGroupServices */ + $systemGroupServices = app()->make(SystemGroupServices::class); + $gid = $systemGroupServices->value(['config_name' => $config_name], 'id'); + if (!$gid) throw new AdminException(100026); + $group = $systemGroupServices->getOne(['id' => $gid], 'id,config_name,fields'); + $fields = json_decode($group['fields'], true) ?? []; + $this->transaction(function () use ($gid, $params, $fields) { + $this->delGroupDate($gid); + $data = []; + $sort = count($params); + foreach ($params as $k => $v) { + $value = []; + foreach ($v as $key => $param) { + foreach ($fields as $index => $field) { + if ($key == $field["title"]) { + if ($param == "") { + throw new AdminException(400607, ['name' => $field["name"]]); + } else { + $value[$key]["type"] = $field["type"]; + $value[$key]["value"] = $param; + } + } + } + } + $data[$k] = [ + "gid" => $gid, + "add_time" => time(), + "value" => json_encode($value), + "sort" => $sort, + "status" => $v["status"] ?? 1 + ]; + $sort--; + } + $this->dao->saveAll($data); + }); + \crmeb\services\CacheService::clear(); + return true; + } + + /** + * 检查秒杀时间段 + * @param SystemGroupServices $services + * @param $gid + * @param $params + * @param int $id + * @return mixed + */ + public function checkSeckillTime(SystemGroupServices $services, $gid, $params, $id = 0) + { + $name = $services->value(['id' => $gid], 'config_name'); + if ($name == 'routine_seckill_time') { + if ($params['time'] == '') { + throw new AdminException(400190); + } + if (!$params['continued']) { + throw new AdminException(400191); + } + if (!preg_match('/^(\d|1\d|2[0-3])$/', $params['time'])) { + throw new AdminException(400192); + } + if (!preg_match('/^([1-9]|1\d|2[0-4])$/', $params['continued'])) { + throw new AdminException(400193); + } + if (($params['time'] + $params['continued']) > 24) throw new AdminException(400194); + $list = $this->dao->getColumn(['gid' => $gid], 'value', 'id'); + if ($id) unset($list[$id]); + $times = $time = []; + foreach ($list as $item) { + $info = json_decode($item, true); + for ($i = 0; $i < $info['continued']['value']; $i++) { + $times[] = $info['time']['value'] + $i; + } + } + for ($i = 0; $i < $params['continued']; $i++) { + $time[] = $params['time'] + $i; + } + foreach ($time as $v) { + if (in_array($v, $times)) throw new AdminException(400195); + } + } + } +} diff --git a/demo/thinkphp/backend/app/services/system/config/SystemGroupServices.php b/demo/thinkphp/backend/app/services/system/config/SystemGroupServices.php new file mode 100644 index 0000000000000000000000000000000000000000..293a7dfff271d25e5374143625aab45becee4861 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/config/SystemGroupServices.php @@ -0,0 +1,101 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\config; + +use app\dao\system\config\SystemGroupDao; +use app\services\BaseServices; + +/** + * 组合数据 + * Class SystemGroupServices + * @package app\services\system\config + * @method getConfigNameId(string $configName) 获取配置id + * @method save(array $data) 新增数据 + * @method get(int $id, ?array $field = []) 获取一条数据 + * @method count(array $where = []): int 根据条件获取条数 + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method delete($id, ?string $key = null) 删除数据 + * @method value(array $where, ?string $field = '') 获取某个值 + */ +class SystemGroupServices extends BaseServices +{ + + /** + * SystemGroupServices constructor. + * @param SystemGroupDao $dao + */ + public function __construct(SystemGroupDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取组合数据列表 + * @param array $where + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGroupList(array $where, array $field = ['*']) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getGroupList($where, $field, $page, $limit); + $count = $this->dao->count($where); + foreach ($list as $key => $value) { + if (isset($value['fields'])) { + $list[$key]['typelist'] = $value['fields']; + unset($list[$key]['fields']); + } + } + return compact('list', 'count'); + } + + /** + * 获取组合数据tab下的header头部 + * @param int $id + * @return array + */ + public function getGroupDataTabHeader(int $id) + { + $data = $this->getValueFields($id); + $header = []; + foreach ($data as $key => $item) { + if ($item['type'] == 'upload' || $item['type'] == 'uploads') { + $header[$key]['key'] = $item['title']; + $header[$key]['minWidth'] = 60; + $header[$key]['type'] = 'img'; + } elseif ($item['title'] == 'url' || $item['title'] == 'wap_url' || $item['title'] == 'link' || $item['title'] == 'wap_link') { + $header[$key]['key'] = $item['title']; + $header[$key]['minWidth'] = 200; + } else { + $header[$key]['key'] = $item['title']; + $header[$key]['minWidth'] = 100; + } + $header[$key]['title'] = $item['name']; + } + array_unshift($header, ['key' => 'id', 'title' => '编号', 'minWidth' => 35]); + array_push($header, ['slot' => 'status', 'title' => '是否可用', 'minWidth' => 80], ['key' => 'sort', 'title' => '排序', 'minWidth' => 80], ['slot' => 'action', 'fixed' => 'right', 'title' => '操作', 'minWidth' => 120]); + return compact('header'); + } + + /** + * 获取组合数据fields字段 + * @param int $id + * @return array|mixed + */ + public function getValueFields(int $id) + { + return json_decode($this->dao->value(['id' => $id], 'fields'), true) ?: []; + } + +} diff --git a/demo/thinkphp/backend/app/services/system/config/SystemStorageServices.php b/demo/thinkphp/backend/app/services/system/config/SystemStorageServices.php new file mode 100644 index 0000000000000000000000000000000000000000..d84f2a5fd7e5fb7659c115c96ebaa7a412e28adb --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/config/SystemStorageServices.php @@ -0,0 +1,573 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\config; + + +use app\dao\system\config\SystemStorageDao; +use app\services\BaseServices; +use phoenix\exceptions\AdminException; +use phoenix\services\FormBuilder; +use app\services\other\UploadService; + + +/** + * Class SystemStorageServices + * + * @author Mr.April + * @since 1.0 + */ +class SystemStorageServices extends BaseServices +{ + + /** + * SystemStorageServices constructor. + * @param SystemStorageDao $dao + */ + public function __construct(SystemStorageDao $dao) + { + $this->dao = $dao; + } + + /** + * @param array $where + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where) + { + [$page, $limit] = $this->getPageValue(); + $config = $this->getStorageConfig((int)$where['type']); + $where['access_key'] = $config['accessKey']; + $list = $this->dao->getList($where, ['*'], $page, $limit, 'add_time'); + foreach ($list as &$item) { + $item['cname'] = str_replace('https://', '', $item['domain']); + $item['_add_time'] = date('Y-m-d H:i:s', $item['add_time']); + $item['_update_time'] = date('Y-m-d H:i:s', $item['update_time']); + $service = UploadService::init($item['type']); + $region = $service->getRegion(); + foreach ($region as $value) { + if (strstr($item['region'], $value['value'])) { + $item['_region'] = $value['label']; + } + } + } + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * @param int $type + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function getFormStorage(int $type) + { + $upload = UploadService::init($type); + + $config = $this->getStorageConfig($type); + $ruleConfig = []; + if (!$config['accessKey']) { + $ruleConfig = [ + FormBuilder::input('accessKey', 'AccessKeyId:', $config['accessKey'] ?? '')->required(), + FormBuilder::input('secretKey', 'AccessKeySecret::', $config['secretKey'] ?? '')->required(), + ]; + } + + if ($type === 4 && isset($config['appid']) && !$config['appid']) { + $ruleConfig[] = FormBuilder::input('appid', 'APPID', $config['appid'] ?? '')->required(); + } + + $rule = [ + FormBuilder::input('name', '空间名称')->required(), + FormBuilder::select('region', '空间区域')->options($upload->getRegion())->required(), + FormBuilder::radio('acl', '读写权限', 'public-read')->options([ + ['label' => '公共读(推荐)', 'value' => 'public-read'], + ['label' => '公共读写', 'value' => 'public-read-write'], + ])->required(), + ]; + + $rule = array_merge($ruleConfig, $rule); + return create_form('添加云空间', $rule, '/system/config/storage/' . $type); + } + + /** + * @param int $type + * @return array + */ + public function getStorageConfig(int $type) + { + $config = [ + 'accessKey' => '', + 'secretKey' => '' + ]; + switch ($type) { + case 2://七牛 + $config = [ + 'accessKey' => sys_config('qiniu_accessKey', ''), + 'secretKey' => sys_config('qiniu_secretKey', ''), + ]; + break; + case 3:// oss 阿里云 + $config = [ + 'accessKey' => sys_config('accessKey', ''), + 'secretKey' => sys_config('secretKey', ''), + ]; + break; + case 4:// cos 腾讯云 + $config = [ + 'accessKey' => sys_config('tengxun_accessKey', ''), + 'secretKey' => sys_config('tengxun_secretKey', ''), + 'appid' => sys_config('tengxun_appid', ''), + ]; + break; + case 5:// cos 京东云 + $config = [ + 'accessKey' => sys_config('jd_accessKey', ''), + 'secretKey' => sys_config('jd_secretKey', ''), + ]; + break; + case 6:// cos 华为云 + $config = [ + 'accessKey' => sys_config('hw_accessKey', ''), + 'secretKey' => sys_config('hw_secretKey', ''), + ]; + break; + case 7:// cos 天翼云 + $config = [ + 'accessKey' => sys_config('ty_accessKey', ''), + 'secretKey' => sys_config('ty_secretKey', ''), + ]; + break; + } + return $config; + } + + /** + * @param int $type + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function getFormStorageConfig(int $type) + { + $config = $this->getStorageConfig($type); + $rule = [ + FormBuilder::hidden('type', $type), + FormBuilder::input('accessKey', 'AccessKeyId:', $config['accessKey'] ?? '')->required(), + FormBuilder::input('secretKey', 'AccessKeySecret:', $config['secretKey'] ?? '')->required(), + ]; + + if ($type === 4) { + $rule[] = FormBuilder::input('appid', 'APPID', $config['appid'] ?? '')->required(); + } + + + return create_form('配置信息', $rule, '/system/config/storage/config'); + } + + /** + * 删除空间 + * @param int $id + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function deleteStorage(int $id) + { + $storageInfo = $this->dao->get(['is_delete' => 0, 'id' => $id]); + if (!$storageInfo) { + throw new AdminException(400608); + } + if ($storageInfo->status) { + throw new AdminException(400609); + } + + try { + $upload = UploadService::init($storageInfo->type); + $res = $upload->deleteBucket($storageInfo->name, $storageInfo->region); + if (false === $res) { + throw new AdminException($upload->getError()); + } + } catch (\Throwable $e) { + throw new AdminException($e->getMessage()); + } + $storageInfo->is_delete = 1; + $storageInfo->save(); + + $this->cacheDriver()->clear(); + + return true; + } + + public function saveConfig(int $type, array $data) + { + //保存配置信息 + if (1 !== $type) { + $accessKey = $secretKey = $appid = ''; + if (isset($data['accessKey']) && isset($data['secretKey']) && $data['accessKey'] && $data['secretKey']) { + $accessKey = $data['accessKey']; + $secretKey = $data['secretKey']; + unset($data['accessKey'], $data['secretKey']); + } + if (isset($data['appid']) && $data['appid']) { + $appid = $data['appid']; + unset($data['appid']); + } + if (!$accessKey || !$secretKey) { + return true; + } + /** @var SystemConfigServices $make */ + $make = app()->make(SystemConfigServices::class); + switch ($type) { + case 2://七牛 + $make->update('qiniu_accessKey', ['value' => json_encode($accessKey)], 'menu_name'); + $make->update('qiniu_secretKey', ['value' => json_encode($secretKey)], 'menu_name'); + break; + case 3:// oss 阿里云 + $make->update('accessKey', ['value' => json_encode($accessKey)], 'menu_name'); + $make->update('secretKey', ['value' => json_encode($secretKey)], 'menu_name'); + break; + case 4:// cos 腾讯云 + $make->update('tengxun_accessKey', ['value' => json_encode($accessKey)], 'menu_name'); + $make->update('tengxun_secretKey', ['value' => json_encode($secretKey)], 'menu_name'); + $make->update('tengxun_appid', ['value' => json_encode($appid)], 'menu_name'); + break; + case 5:// oss 京东云 + $make->update('jd_accessKey', ['value' => json_encode($accessKey)], 'menu_name'); + $make->update('jd_secretKey', ['value' => json_encode($secretKey)], 'menu_name'); + break; + case 6:// oss 华为云 + $make->update('hw_accessKey', ['value' => json_encode($accessKey)], 'menu_name'); + $make->update('hw_secretKey', ['value' => json_encode($secretKey)], 'menu_name'); + break; + case 7:// oss 天翼云 + $make->update('ty_accessKey', ['value' => json_encode($accessKey)], 'menu_name'); + $make->update('ty_secretKey', ['value' => json_encode($secretKey)], 'menu_name'); + break; + } + $make->cacheDriver()->clear(); + } + } + + /** + * 保存云存储 + * @param int $type + * @param array $data + * @return mixed + */ + public function saveStorage(int $type, array $data) + { + //保存配置信息 + $this->saveConfig($type, $data); + if ($this->dao->count(['name' => $data['name']])) { + throw new AdminException(400610); + } + //保存云存储 + $data['type'] = $type; + $upload = UploadService::init($type); + $res = $upload->createBucket($data['name'], $data['region'], $data['acl']); + if (false === $res) { + throw new AdminException($upload->getError()); + } + if (3 === $type) { + $data['region'] = $this->getReagionHost($type, $data['region']); + } + $data['domain'] = $this->getDomain($type, $data['name'], $data['region'], sys_config('tengxun_appid')); + if (2 === $type) { + $domianList = $upload->getDomian($data['name']); + $data['domain'] = $domianList[count($domianList) - 1]; + } else { + $data['cname'] = $data['domain']; + } + $data['add_time'] = time(); + $data['update_time'] = time(); + $config = $this->getStorageConfig($type); + $data['access_key'] = $config['accessKey']; + + $this->cacheDriver()->clear(); + + return $this->dao->save($data); + } + + /** + * 同步云储存桶 + * @param int $type + * @return bool + */ + public function synchronization(int $type) + { + $data = []; + switch ($type) { + case 2://七牛 + $config = $this->getStorageConfig($type); + $upload = UploadService::init($type); + $list = $upload->listbuckets(); + foreach ($list as $item) { + if (!$this->dao->count(['name' => $item['id'], 'access_key' => $config['accessKey']])) { + $data[] = [ + 'type' => $type, + 'access_key' => $config['accessKey'], + 'name' => $item['id'], + 'region' => $item['region'], + 'acl' => $item['private'] == 0 ? 'public-read' : 'private', + 'status' => 0, + 'is_delete' => 0, + 'add_time' => time(), + 'update_time' => time() + ]; + } + } + break; + case 3:// oss 阿里云 + $upload = UploadService::init($type); + $list = $upload->listbuckets(); + $config = $this->getStorageConfig($type); + foreach ($list as $item) { + if (!$this->dao->count(['name' => $item['name'], 'access_key' => $config['accessKey']])) { + $region = $this->getReagionHost($type, $item['location']); + $data[] = [ + 'type' => $type, + 'access_key' => $config['accessKey'], + 'name' => $item['name'], + 'region' => $region, + 'acl' => 'public-read', + 'domain' => $this->getDomain($type, $item['name'], $region), + 'status' => 0, + 'is_delete' => 0, + 'add_time' => strtotime($item['createTime']), + 'update_time' => time() + ]; + } + } + break; + case 4:// cos 腾讯云 + $upload = UploadService::init($type); + $list = $upload->listbuckets(); + if (!empty($list['Name'])) { + $newList = $list; + $list = []; + $list[] = $newList; + } + $config = $this->getStorageConfig($type); + foreach ($list as $item) { + if (!$this->dao->count(['name' => $item['Name'], 'access_key' => $config['accessKey']])) { + $data[] = [ + 'type' => $type, + 'access_key' => $config['accessKey'], + 'name' => $item['Name'], + 'region' => $item['Location'], + 'acl' => 'public-read', + 'status' => 0, + 'domain' => sys_config('tengxun_appid') ? $this->getDomain($type, $item['Name'], $item['Location']) : '', + 'is_delete' => 0, + 'add_time' => strtotime($item['CreationDate']), + 'update_time' => time() + ]; + } + } + break; + case 5:// cos 京东云 + $upload = UploadService::init($type); + $res = $upload->listbuckets(); + $list = $res['Buckets']; + $location = explode('.', $res['@metadata']['effectiveUri'])[1] ?? 'cn-north-1'; + $config = $this->getStorageConfig($type); + foreach ($list as $item) { + if (!$this->dao->count(['name' => $item['Name'], 'access_key' => $config['accessKey']])) { + $data[] = [ + 'type' => $type, + 'access_key' => $config['accessKey'], + 'name' => $item['Name'], + 'region' => $location, + 'acl' => 'public-read', + 'status' => 0, + 'domain' => $this->getDomain($type, $item['Name'], $location), + 'is_delete' => 0, + 'add_time' => time(), + 'update_time' => time() + ]; + } + } + break; + case 6:// cos 华为云 + case 7:// cos 天翼云 + $upload = UploadService::init($type); + $list = $upload->listbuckets(); + if (!empty($list['Name'])) { + $newList = $list; + $list = []; + $list[] = $newList; + } + $config = $this->getStorageConfig($type); + foreach ($list as $item) { + if (!$this->dao->count(['name' => $item['Name'], 'access_key' => $config['accessKey']])) { + $data[] = [ + 'type' => $type, + 'access_key' => $config['accessKey'], + 'name' => $item['Name'], + 'region' => $item['Location'], + 'acl' => 'public-read', + 'status' => 0, + 'domain' => $this->getDomain($type, $item['Name'], $item['Location']), + 'is_delete' => 0, + 'add_time' => strtotime($item['CreationDate']), + 'update_time' => time() + ]; + } + } + break; + } + if ($data) { + $this->dao->saveAll($data); + } + + $this->cacheDriver()->clear(); + + return true; + } + + /** + * @param int $type + * @param string $reagion + * @return mixed|string + */ + public function getReagionHost(int $type, string $reagion) + { + $upload = UploadService::init($type); + $reagionList = $upload->getRegion(); + foreach ($reagionList as $item) { + if (strstr($item['value'], $reagion) !== false) { + return $item['value']; + } + } + return ''; + } + + /** + * 获取域名 + * @param int $type + * @param string $name + * @param string $reagion + * @param string $appid + * @return string + */ + public function getDomain(int $type, string $name, string $reagion, string $appid = '') + { + $domainName = ''; + switch ($type) { + case 3:// oss 阿里云 + $domainName = 'https://' . $name . '.' . $reagion; + break; + case 4:// cos 腾讯云 + $domainName = 'https://' . $name . ($appid ? '-' . $appid : '') . '.cos.' . $reagion . '.myqcloud.com'; + break; + case 5:// cos 京东云 + $domainName = 'https://' . $name . '.s3.' . $reagion . '.jdcloud-oss.com'; + break; + case 6:// cos 华为云 + $domainName = 'https://' . $name . '.obs.' . $reagion . '.myhuaweicloud.com'; + break; + case 7:// cos 天翼云 + $domainName = 'https://' . $name . '.obs.' . $reagion . '.ctyun.cn'; + break; + } + return $domainName; + } + + + /** + * 获取云存储配置 + * @param int $type + * @return array|string[] + */ + public function getConfig(int $type) + { + $res = ['name' => '', 'region' => '', 'domain' => '', 'cdn' => '']; + try { + $config = $this->dao->get(['type' => $type, 'status' => 1, 'is_delete' => 0]); + if ($config) { + return ['name' => $config->name, 'region' => $config->region, 'domain' => $config->domain, 'cdn' => $config->cdn]; + } + } catch (\Throwable $e) { + } + return $res; + + } + + /** + * 获取修改域名表单 + * @param int $id + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function getUpdateDomainForm(int $id) + { + $storage = $this->dao->get(['id' => $id], ['domain', 'cdn']); + $rule = [ + FormBuilder::input('domain', '空间域名', $storage['domain']), + FormBuilder::input('cdn', 'cdn域名', $storage['cdn']), + ]; + return create_form('修改空间域名', $rule, '/system/config/storage/domain/' . $id); + } + + /** + * 修改域名并绑定 + * @param int $id + * @param string $domain + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function updateDomain(int $id, string $domain, array $data = []) + { + $info = $this->dao->get($id); + if (!$info) { + throw new AdminException(100026); + } + if ($info->domain != $domain) { + $info->domain = $domain; + $upload = UploadService::init($info->type); + //是否添加过域名不存在需要绑定域名 + $domainList = $upload->getDomian($info->name, $info->region); + $domainParse = parse_url($domain); + if (false === $domainParse) { + throw new AdminException('域名输入有误'); + } + if (!in_array($domainParse['host'], $domainList)) { + //绑定域名到云储存桶 + $res = $upload->bindDomian($info->name, $domain, $info->region); + if (false === $res) { + throw new AdminException($upload->getError()); + } + } + //七牛云需要通过接口获取cname + if (2 === ((int)$info->type)) { + $resDomain = $upload->getDomianInfo($domain); + $info->cname = $resDomain['cname'] ?? ''; + } + $info->save(); + } + if ($info->cdn != $data['cdn']) { + $info->cdn = $data['cdn']; + $info->save(); + } + + $this->cacheDriver()->clear(); + + return true; + } +} diff --git a/demo/thinkphp/backend/app/services/system/crontab/CrontabRunServices.php b/demo/thinkphp/backend/app/services/system/crontab/CrontabRunServices.php new file mode 100644 index 0000000000000000000000000000000000000000..56d972ae689f3c9d65957c5587d234a14d3a0ef0 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/crontab/CrontabRunServices.php @@ -0,0 +1,232 @@ + '未支付自动取消订单', + 'pinkExpiration' => '拼团到期订单处理', + 'agentUnbind' => '到期自动解绑上级', + 'liveProductStatus' => '自动更新直播商品状态', + 'liveRoomStatus' => '自动更新直播间状态', + 'takeDelivery' => '订单自动收货', + 'advanceOff' => '预售商品到期自动下架', + 'productReplay' => '订单商品自动好评', + 'clearPoster' => '清除昨日海报', + ]; + + /** + * 调用不存在的方法 + * + * @param $name + * @param $arguments + * + * @return mixed|void + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function __call($name, $arguments) + { + $this->crontabLog($name . '方法不存在'); + } + + /** + * 定时任务日志 + * + * @param $msg + */ + protected function crontabLog($msg) + { + $timer_log_open = config("log.timer_log", false); + if ($timer_log_open) { + $date = date('Y-m-d H:i:s', time()); + Log::write($date . $msg, 'crontab'); + } + } + + /** + * 未支付自动取消订单 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function orderCancel() + { + echo '测试定时任务\n'; +// try { +// app()->make(StoreOrderServices::class)->orderUnpaidCancel(); +// $this->crontabLog(' 执行未支付自动取消订单'); +// } catch (\Throwable $e) { +// $this->crontabLog('自动取消订单失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 拼团到期订单处理 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function pinkExpiration() + { + echo '拼团\n'; +// try { +// app()->make(StorePinkServices::class)->statusPink(); +// $this->crontabLog(' 执行拼团到期订单处理'); +// } catch (\Throwable $e) { +// $this->crontabLog('拼团到期订单处理失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 自动解除上级绑定 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function agentUnbind() + { + echo '自动解除上级绑定\n'; +// try { +// app()->make(AgentManageServices::class)->removeSpread(); +// $this->crontabLog(' 执行自动解绑上级绑定'); +// } catch (\Throwable $e) { +// $this->crontabLog('自动解除上级绑定失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 更新直播商品状态 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function liveProductStatus() + { + echo '更新直播\n'; +// try { +// app()->make(LiveGoodsServices::class)->syncGoodStatus(); +// $this->crontabLog(' 执行更新直播商品状态'); +// } catch (\Throwable $e) { +// $this->crontabLog('更新直播商品状态失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 更新直播间状态 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function liveRoomStatus() + { + echo '更新直播状态\n'; +// try { +// app()->make(LiveRoomServices::class)->syncRoomStatus(); +// $this->crontabLog(' 执行更新直播间状态'); +// } catch (\Throwable $e) { +// $this->crontabLog('更新直播间状态失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 自动收货 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function takeDelivery() + { + echo '自动收货\n'; +// try { +// app()->make(StoreOrderTakeServices::class)->autoTakeOrder(); +// $this->crontabLog(' 执行自动收货'); +// } catch (\Throwable $e) { +// $this->crontabLog('自动收货失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 预售到期商品自动下架 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function advanceOff() + { + echo '自动下架\n'; +// try { +// app()->make(StoreProductServices::class)->downAdvance(); +// $this->crontabLog(' 执行预售到期商品自动下架'); +// } catch (\Throwable $e) { +// $this->crontabLog('预售到期商品自动下架失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 自动好评 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function productReplay() + { + echo '自动好评\n'; +// try { +// app()->make(StoreOrderServices::class)->autoComment(); +// $this->crontabLog(' 执行自动好评'); +// } catch (\Throwable $e) { +// $this->crontabLog('自动好评失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 清除昨日海报 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function clearPoster() + { + echo '自动清楚\n'; +// try { +// app()->make(SystemAttachmentServices::class)->emptyYesterdayAttachment(); +// $this->crontabLog(' 执行清除昨日海报'); +// } catch (\Throwable $e) { +// $this->crontabLog('清除昨日海报失败,失败原因:' . $e->getMessage()); +// } + } +} diff --git a/demo/thinkphp/backend/app/services/system/crontab/SystemCrontabServices.php b/demo/thinkphp/backend/app/services/system/crontab/SystemCrontabServices.php new file mode 100644 index 0000000000000000000000000000000000000000..3034a7abcbb09751f48e326806b1cc11789bf498 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/crontab/SystemCrontabServices.php @@ -0,0 +1,214 @@ +dao = $dao; + } + + /** + * 定时任务列表 + * + * @param array $where + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function getTimerList(array $where = []): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->selectList($where, '*', $page, $limit, 'create_time desc'); + foreach ($list as &$item) { + $item['next_execution_time'] = date('Y-m-d H:i:s', $item['next_execution_time']); + $item['last_execution_time'] = $item['last_execution_time'] != 0 ? date('Y-m-d H:i:s', $item['last_execution_time']) : '暂未执行'; + } + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * 定时任务详情 + * + * @param $id + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getTimerInfo($id) + { + $info = $this->dao->get($id); + if (!$info) throw new AdminException(100026); + return $info->toArray(); + } + + /** + * 定时任务类型 + * + * @return string[] + */ + public function getMarkList(): array + { + return app()->make(CrontabRunServices::class)->markList; + } + + /** + * 保存定时任务 + * + * @param array $data + * + * @return bool + */ + public function saveTimer(array $data = []): bool + { + if (!$data['id'] && $this->dao->getCount(['mark' => $data['mark'], 'delete_time' => null])) { + throw new AdminException('该定时任务已存在,请勿重复添加'); + } + $data['name'] = $this->getMarkList()[$data['mark']]; + $data['create_time'] = time(); + if (!$data['id']) { + unset($data['id']); + $res = $this->dao->save($data); + } else { + $res = $this->dao->update(['id' => $data['id']], $data); + if (!$res) throw new AdminException(100006); + } + return true; + } + + /** + * 删除定时任务 + * + * @param $id + * + * @return bool + */ + public function delTimer($id): bool + { + $res = $this->dao->destroy($id); + if (!$res) throw new AdminException(100008); + return true; + } + + /** + * 设置定时任务状态 + * + * @param $id + * @param $is_open + * + * @return bool + */ + public function setTimerStatus($id, $is_open) + { + $res = $this->dao->update(['id' => $id], ['is_open' => $is_open]); + if (!$res) throw new AdminException(100014); + return true; + } + + /** + * 计算定时任务下次执行时间 + * + * @param $data + * @param int $time + * + * @return false|float|int|mixed + */ + public function getTimerCycleTime($data, $time = 0) + { + if (!$time) $time = time(); + switch ($data['type']) { + case 1: // 每隔几秒 + $cycle_time = $time + $data['second']; + break; + case 2: // 每隔几分 + $cycle_time = $time + ($data['minute'] * 60); + break; + case 3: // 每隔几时 + $cycle_time = $time + ($data['hour'] * 3600) + ($data['minute'] * 60); + break; + case 4: // 每隔几日 + $cycle_time = $time + ($data['day'] * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60); + break; + case 5: // 每日几时几分几秒 + $cycle_time = strtotime(date('Y-m-d ' . $data['hour'] . ':' . $data['minute'] . ':' . $data['second'], time())); + if ($time >= $cycle_time) { + $cycle_time = $cycle_time + 86400; + } + break; + case 6: // 每周周几几时几分几秒 + $todayStart = strtotime(date('Y-m-d 00:00:00', time())); + $w = date("w"); + if ($w > $data['week']) { + $cycle_time = $todayStart + ((7 - $w + $data['week']) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } else if ($w == $data['week']) { + $cycle_time = $todayStart + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + if ($time >= $cycle_time) { + $cycle_time = $cycle_time + (7 * 86400); + } + } else { + $cycle_time = $todayStart + (($data['week'] - $w) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } + break; + case 7: // 每月几日几时几分几秒 + $d = date("d"); + $firstDate = date('Y-m-01', time()); + $maxDay = date('d', strtotime("$firstDate + 1 month -1 day")); + $todayStart = strtotime(date('Y-m-d 00:00:00', time())); + if ($d > $data['day']) { + $cycle_time = $todayStart + (($maxDay - $d + $data['day']) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } elseif ($d == $data['day']) { + $cycle_time = $todayStart + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + if ($time >= $cycle_time) { + $cycle_time = $cycle_time + (($maxDay - $d + $data['day']) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } + } else { + $cycle_time = $todayStart + (($data['day'] - $d) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } + break; + default: + $cycle_time = 0; + break; + } + return $cycle_time; + } + + /** + * 执行任务 + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/02/17 + */ + public function crontabRun() + { + $crontabRunServices = app()->make(CrontabRunServices::class); + $time = time(); + file_put_contents(root_path() . 'runtime/.timer', $time); //检测定时任务是否正常 + $list = $this->dao->selectList(['is_open' => 1, 'delete_time' => null])->toArray(); + foreach ($list as $item) { + if ($item['next_execution_time'] < $time) { + //转化小驼峰方法名 + $functionName = Str::camel($item['mark']); + //执行定时任务 + $crontabRunServices->$functionName(); + //写入本次执行时间和下次执行时间 + $this->dao->update(['mark' => $item['mark']], ['last_execution_time' => $time, 'next_execution_time' => $this->getTimerCycleTime($item)]); + } + } + } +} diff --git a/demo/thinkphp/backend/app/services/system/databackup/SystemDatabackupServices.php b/demo/thinkphp/backend/app/services/system/databackup/SystemDatabackupServices.php new file mode 100644 index 0000000000000000000000000000000000000000..71711e409f05fd83897641bbbd6b9b546f6a8d17 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/databackup/SystemDatabackupServices.php @@ -0,0 +1,125 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\databackup; + + +use app\services\BaseServices; +use phoenix\services\MysqlBackupService; +use think\facade\Db; +use think\facade\Env; + +/** + * 数据库备份 + * Class SystemDatabackupServices + * @package app\services\system + */ +class SystemDatabackupServices extends BaseServices +{ + + /** + * + * @var MysqlBackupService + */ + protected $dbBackup; + + /** + * 构造方法 + * SystemDatabackupServices constructor. + */ + public function __construct() + { + $this->dbBackup = app()->make(MysqlBackupService::class, [[ + //数据库备份卷大小 + 'compress' => 1, + //数据库备份文件是否启用压缩 0不压缩 1 压缩 + 'level' => 5, + ]]); + } + + /** + * 获取数据库列表 + * @return array + */ + public function getDataList(): array + { + $list = $this->dbBackup->dataList(); + $count = count($list); + return compact('list', 'count'); + } + + /** + * 获取表详情 + * + * @param string|null $tablename + * + * @return array + */ + public function getRead(?string $tablename): array + { + $database = Env::get("database.database"); + $list = Db::query("select * from information_schema.columns where table_name = '" . $tablename . "' and table_schema = '" . $database . "'"); + $count = count($list); + foreach ($list as $key => $f) { + $list[$key]['EXTRA'] = ($f['EXTRA'] == 'auto_increment' ? '是' : ' '); + } + return compact('list', 'count'); + } + + /** + * @return MysqlBackupService + */ + public function getDbBackup(): MysqlBackupService + { + return $this->dbBackup; + } + + /** + * 备份表 + * @param string $tables + * @return string + * @throws \think\db\exception\BindParamException + */ + public function backup(string $tables): string + { + $tables = explode(',', $tables); + $data = ''; + ini_set ("memory_limit","-1"); + foreach ($tables as $t) { + $res = $this->dbBackup->backup($t, 0); + if ($res == false && $res != 0) { + $data .= $t . '|'; + } + } + return $data; + } + + /** + * 获取备份列表 + * @return array + */ + public function getBackup(): array + { + $files = $this->dbBackup->fileList(); + $data = []; + foreach ($files as $key => $t) { + $data[$key]['filename'] = $t['filename']; + $data[$key]['part'] = $t['part']; + $data[$key]['size'] = $t['size'] . 'B'; + $data[$key]['compress'] = $t['compress']; + $data[$key]['backtime'] = $key; + $data[$key]['time'] = $t['time']; + } + krsort($data);//根据时间降序 + return ['count' => count($data), 'list' => array_values($data)]; + } + +} diff --git a/demo/thinkphp/backend/app/services/system/dict/SystemDictServices.php b/demo/thinkphp/backend/app/services/system/dict/SystemDictServices.php new file mode 100644 index 0000000000000000000000000000000000000000..a05e160633aabf0307b8328fbb55e23b1210f226 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/dict/SystemDictServices.php @@ -0,0 +1,162 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\dict; + +use app\dao\system\dict\SystemDictDao; +use app\services\BaseServices; +use phoenix\exceptions\AdminException; + +class SystemDictServices extends BaseServices +{ + + /** + * 构造方法 + * SystemLogServices constructor. + * + * @param \app\dao\system\dict\SystemDictDao $dao + */ + public function __construct(SystemDictDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取字典选项列表 + * + * @param array $where + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getDictList(array $where): array + { + [$page, $limit] = $this->getPageValue(); + $where['name'] = $this->dictNameToOptionName($where['name']); + $list = $this->dao->selectList($where, '*', $page, $limit, 'create_time asc', [], true); + //去除字典前缀 + foreach ($list as $key => $value) { + $position = strpos($value['name'], "dict_") + 5; + $list[$key]['name'] = substr($value['name'], $position); + } + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * 字典保存 + * + * @param string $name + * @param $values + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function saveDict(string $name, $values): mixed + { + if (!preg_match('/[a-zA-Z]/', $name)) { + throw new AdminException('字典名只能包含字母'); + } + $option_name = $this->dictNameToOptionName($name); + if ($this->dao->getName($option_name)) { + return app('json')->fail(400188); + } + $format_values = $this->filterValue($values); + $data = [ + 'name' => $option_name, + 'value' => json_encode($format_values), + ]; + return $this->save($data); + } + + /** + * 字典名到option名转换 + * + * @param string $name + * + * @return string + */ + public function dictNameToOptionName(string $name): string + { + return "dict_$name"; + } + + /** + * 过滤值 + * + * @param array $values + * + * @return array + * @throws BusinessException + */ + public function filterValue(array $values): array + { + $format_values = []; + foreach ($values as $item) { + if (!isset($item['value']) || !isset($item['name'])) { + throw new AdminException('字典格式错误'); + } + $format_values[] = ['value' => $item['value'], 'name' => $item['name']]; + } + return $format_values; + } + + /** + * 字典详情 + * + * @param $id + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function read($id): array + { + $data = $this->dao->get($id); + $position = strpos($data->name, "dict_") + 5; + $data->name = substr($data->name, $position); + $data->value = json_decode($data->value, 1); + return $data->getData(); + } + + /** + * 更新字典 + * + * @param $id + * @param $data + * + * @return mixed + */ + public function updateDict($id, $data): mixed + { + if (!preg_match('/[a-zA-Z]/', $data['name'])) { + throw new AdminException('字典名只能包含字母'); + } + $option_name = $this->dictNameToOptionName($data['name']); + $where = [['name', '=', $option_name], ['id', '<>', $id]]; + if ($this->dao->getCount($where)) { + throw new AdminException(400188); + } + + $format_values = $this->filterValue($data['value']); + $upd = [ + 'name' => $option_name, + 'value' => json_encode($format_values), + ]; + return $this->update($id, $upd); + } +} diff --git a/demo/thinkphp/backend/app/services/system/lang/LangCodeServices.php b/demo/thinkphp/backend/app/services/system/lang/LangCodeServices.php new file mode 100644 index 0000000000000000000000000000000000000000..0b5029c4fd50f03bdf0c72c636008c6379537cdb --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/lang/LangCodeServices.php @@ -0,0 +1,223 @@ +dao = $dao; + } + + /** + * 语言列表 + * + * @param array $where + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function langCodeList(array $where = []): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->selectList($where, '*', $page, $limit, 'id desc', [], true)->toArray(); + /** @var LangTypeServices $langTypeServices */ + $langTypeServices = app()->make(LangTypeServices::class); + $typeList = $langTypeServices->getColumn([['status', '=', 1], ['delete_time', '=', null]], 'language_name,file_name,id', 'id'); + $langType = [ + 'isAdmin' => [ + ['title' => '用户端页面', 'value' => 0], + ['title' => '后端接口', 'value' => 1], + ], + ]; + foreach ($typeList as $value) { + $langType['langType'][] = ['title' => $value['language_name'] . '(' . $value['file_name'] . ')', 'value' => $value['id']]; + } + foreach ($list as &$item) { + $item['language_name'] = isset($typeList[$item['type_id']]['language_name']) && $typeList[$item['type_id']]['file_name'] ? $typeList[$item['type_id']]['language_name'] . '(' . $typeList[$item['type_id']]['file_name'] . ')' : ''; + } + $count = $this->dao->count($where); + return compact('list', 'count', 'langType'); + } + + /** + * 语言详情 + * + * @param $code + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function langCodeInfo($code): array + { + if (!$code) throw new AdminException(100026); + /** @var LangTypeServices $langTypeServices */ + $langTypeServices = app()->make(LangTypeServices::class); + $typeList = $langTypeServices->getColumn([['status', '=', 1], ['delete_time', '=', null]], 'language_name,file_name,id', 'id'); + $list = $this->dao->selectList([['code', '=', $code], ['type_id', 'in', array_column($typeList, 'id')]])->toArray(); + foreach ($list as &$item) { + $item['language_name'] = $typeList[$item['type_id']]['language_name'] . '(' . $typeList[$item['type_id']]['file_name'] . ')'; + } + $remarks = $list[0]['remarks']??''; + return compact('list', 'code', 'remarks'); + } + + /** + * 保存修改语言 + * + * @param $data + * + * @return bool + * @throws \Exception + */ + public function langCodeSave($data): bool + { + if ($data['edit'] == 0) { + if ($data['is_admin'] == 1) { + $code = $this->dao->getMax(['is_admin' => 1], 'code'); + if ($code < 500000) { + $code = 500000; + } else { + $code = $code + 1; + } + } else { + $code = $data['remarks']; + } + } else { + $code = $data['code']; + } + $saveData = []; + foreach ($data['list'] as $key => $item) { + $saveData[$key] = [ + 'code' => $code, + 'remarks' => $data['remarks'], + 'lang_explain' => $item['lang_explain'], + 'type_id' => $item['type_id'], + 'is_admin' => $data['is_admin'], + ]; + if (isset($item['id']) && $item['id'] != 0) { + $saveData[$key]['id'] = $item['id']; + } + } + $this->dao->saveAll($saveData); + $this->clearLangCache(); + return true; + } + + /** + * 删除语言 + * + * @param $id + * + * @return bool + */ + public function langCodeDel($id): bool + { + $code = $this->dao->value(['id' => $id], 'code'); + $res = $this->dao->delete(['code' => $code]); + $this->clearLangCache(); + if ($res) return true; + throw new AdminException(100008); + } + + /** + * 清除语言缓存 + * + * @return bool + */ + public function clearLangCache(): bool + { + /** @var LangTypeServices $langTypeServices */ + $langTypeServices = app()->make(LangTypeServices::class); + $typeList = $langTypeServices->getColumn(['status' => 1, 'delete_time' => null], 'file_name'); + foreach ($typeList as $value) { + $langStr = 'api_lang_' . str_replace('-', '_', $value); + CacheService::delete($langStr); + } + $this->cacheDriver()->clear(); + return true; + } + + /** + * 机器翻译 + * + * @param string $text + * + * @return array + * @throws \Throwable + */ + public function langCodeTranslate(string $text = ''): array + { +// if (sys_config('hs_accesskey') == '' || sys_config('hs_secretkey') == '') { +// throw new AdminException('请先配置火山翻译key'); +// } + $translator = Translate::getInstance(); + $translator->setAccessKey('AKLTMzkzZTEzNjg3OTg2NDViM2IwNmFlYzhmNzE4MmI4YmI'); + $translator->setSecretKey("TVRneU16STFOVFV4WVRkbE5ERTJaV0pqWm1aaU1UaGlNVFppWldZeE1HUQ=="); +// $translator->setAccessKey(sys_config('hs_accesskey')); +// $translator->setSecretKey(sys_config('hs_secretkey')); + /** @var LangTypeServices $langTypeServices */ + $langTypeServices = app()->make(LangTypeServices::class); + $typeList = $langTypeServices->getColumn([['status', '=', 1], ['delete_time', '=', null]], 'language_name,file_name,id', 'id'); + $data = []; + foreach ($typeList as $item) { + if ($item['file_name'] == 'zh-Hant') { + $lang = 'zh-Hant'; + } else { + $lang = substr($item['file_name'], 0, 2); + } + $data[$item['id']] = $translator->translateText("", $lang, array($text))[0]['Translation']; + } + return $data; + } + + /** + * 获取多语言缓存 + * + * @return mixed + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/06 + */ + public function getLangVersion() + { + return $this->cacheDriver()->remember('lang_version', function () { + return [ + 'version' => uniqid(), + ]; + }); + } + + /** + * @return array + */ + public function langCodeType(): array + { + $langTypeServices = app()->make(LangTypeServices::class); + $typeList = $langTypeServices->getColumn([['status', '=', 1], ['delete_time', '=', null]], 'language_name,file_name,id', 'id'); + $list = [ + 'is_admin' => [ + ['title' => '用户端页面', 'value' => 0], + ['title' => '后端接口', 'value' => 1], + ], + ]; + foreach ($typeList as $value) { + $list['lang_type'][] = ['title' => $value['language_name'] . '(' . $value['file_name'] . ')', 'value' => $value['id']]; + } + + return compact('list'); + } +} diff --git a/demo/thinkphp/backend/app/services/system/lang/LangCountryServices.php b/demo/thinkphp/backend/app/services/system/lang/LangCountryServices.php new file mode 100644 index 0000000000000000000000000000000000000000..547aac40fb67e65975d3300b86ed8900001027ce --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/lang/LangCountryServices.php @@ -0,0 +1,83 @@ +dao = $dao; + } + + /** + * 地区语言列表 + * + * @param array $where + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function LangCountryList(array $where = []): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->selectList($where, '*', $page, $limit, 'id desc', [], true)->toArray(); + /** @var LangTypeServices $langTypeServices */ + $langTypeServices = app()->make(LangTypeServices::class); + $langTypeList = $langTypeServices->getColumn([], 'language_name,file_name,id', 'id'); + foreach ($list as &$item) { + if (isset($langTypeList[$item['type_id']])) { + $item['link_lang'] = $langTypeList[$item['type_id']]['language_name'] . '(' . $langTypeList[$item['type_id']]['file_name'] . ')'; + } else { + $item['link_lang'] = ''; + } + } + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * 保存语言地区 + * + * @param $id + * @param $data + * + * @return bool + */ + public function LangCountrySave($id, $data): bool + { + if ($id) { + $res = $this->dao->update(['id' => $id], $data); + } else { + $res = $this->dao->save($data); + } + if (!$res) throw new AdminException(100007); + $this->cacheDriver()->clear(); + return true; + } + + /** + * 删除语言地区 + * + * @param $id + * + * @return bool + */ + public function langCountryDel($id): bool + { + $res = $this->dao->delete($id); + if (!$res) throw new AdminException(100008); + $this->cacheDriver()->clear(); + return true; + } +} diff --git a/demo/thinkphp/backend/app/services/system/lang/LangTypeServices.php b/demo/thinkphp/backend/app/services/system/lang/LangTypeServices.php new file mode 100644 index 0000000000000000000000000000000000000000..2c61cd6edf7570b5c159c7b97b6dd7d566e37666 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/lang/LangTypeServices.php @@ -0,0 +1,123 @@ +dao = $dao; + } + + /** + * 获取语言类型列表 + * + * @param array $where + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function langTypeList(array $where = []): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->selectList($where, '*', $page, $limit, '', [], true); + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * 保存语言类型 + * + * @param array $data + * + * @return bool + */ + public function langTypeSave(array $data): bool + { + if ($data['id']) { + $this->dao->update($data['id'], $data); + $id = $data['id']; + } else { + unset($data['id']); + $res = $this->dao->save($data); + if ($res) { + //同步语言 + /** @var LangCodeServices $codeServices */ + $codeServices = app()->make(LangCodeServices::class); + $list = $codeServices->selectList(['type_id' => 1])->toArray(); + foreach ($list as $key => $item) { + unset($list[$key]['id']); + $list[$key]['type_id'] = $res->id; + } + $codeServices->saveAll($list); + } else { + throw new AdminException(100006); + } + $id = $res->id; + } + //设置默认 + if ($data['is_default'] == 1) $this->dao->update([['id', '<>', $id]], ['is_default' => 0]); + $this->setDefaultLangName(); + return true; + } + + /** + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/10 + */ + public function setDefaultLangName() + { + $fileName = $this->dao->value(['is_default' => 1], 'file_name'); + $this->cacheDriver()->set('range_name', $fileName); + app()->make(LangCodeServices::class)->cacheDriver()->clear(); + } + + /** + * 修改语言类型状态 + * + * @param $id + * @param $status + * + * @return bool + */ + public function langTypeStatus($id, $status): bool + { + $res = $this->dao->update(['id' => $id], ['status' => $status]); + if (!$res) throw new AdminException(100015); + $this->setDefaultLangName(); + return true; + } + + /** + * 删除语言类型 + * + * @param string $id + * + * @return bool + */ + public function langTypeDel(string $id='0'): bool + { + $this->dao->update(['id' => $id], ['delete_time' => time()]); + /** @var LangCountryServices $countryServices */ + $countryServices = app()->make(LangCountryServices::class); + $countryServices->update(['type_id' => $id], ['type_id' => 0]); + /** @var LangCodeServices $codeServices */ + $codeServices = app()->make(LangCodeServices::class); + $codeServices->delete(['type_id' => $id]); + $this->setDefaultLangName(); + return true; + } +} diff --git a/demo/thinkphp/backend/app/services/system/log/ClearServices.php b/demo/thinkphp/backend/app/services/system/log/ClearServices.php new file mode 100644 index 0000000000000000000000000000000000000000..b524cefd022b9861ffbab4d004a4b58b143310a6 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/log/ClearServices.php @@ -0,0 +1,83 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\log; + +use app\services\BaseServices; +use think\facade\Cache; + +/** + * Class ClearServices + * + * @package app\services\system\log + */ +class ClearServices extends BaseServices +{ + /** 递归删除文件 + * + * @param $dirName + */ + protected function delDirAndFile($dirName) + { + $list = glob($dirName . '*'); + foreach ($list as $file) { + if (is_dir($file)) + $this->delDirAndFile($file . DS); + else + @unlink($file); + } + @rmdir($dirName); + } + + /** + * 删除日志 + */ + public function deleteLog() + { + $root = app()->getRootPath() . 'runtime' . DS; + $this->delDirAndFile($root . 'admin' . DS . 'log' . DS); + $this->delDirAndFile($root . 'api' . DS . 'log' . DS); + $this->delDirAndFile($root . 'log' . DS); + } + + /** + * 刷新数据缓存 + */ + public function refresCache() + { + $root = app()->getRootPath() . 'runtime' . DS; + $adminRoute = $root . 'admin'; + $apiRoute = $root . 'api'; + $cacheRoute = $root . 'cache'; + $cache = []; + + if (is_dir($adminRoute)) + $cache[$adminRoute] = scandir($adminRoute); + if (is_dir($apiRoute)) + $cache[$apiRoute] = scandir($apiRoute); + if (is_dir($cacheRoute)) + $cache[$cacheRoute] = scandir($cacheRoute); + + foreach ($cache as $p => $list) { + foreach ($list as $file) { + if (!in_array($file, ['.', '..', 'log', 'schema', 'route.php'])) { + $path = $p . DS . $file; + if (is_file($path)) { + @unlink($path); + } else { + $this->delDirAndFile($path . DS); + } + } + } + } + Cache::clear(); + } +} diff --git a/demo/thinkphp/backend/app/services/system/log/SystemLogServices.php b/demo/thinkphp/backend/app/services/system/log/SystemLogServices.php new file mode 100644 index 0000000000000000000000000000000000000000..73875fbfa5c08a39c542ab4c33e11b3294720eef --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/log/SystemLogServices.php @@ -0,0 +1,93 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\log; + +use app\dao\system\log\SystemLogDao; +use app\services\BaseServices; +use app\services\system\admin\SystemMenusServices; + +/** + * 系统日志 + * Class SystemLogServices + * + * @package app\services\system\log + * @method deleteLog() 定期删除日志 + */ +class SystemLogServices extends BaseServices +{ + + /** + * 构造方法 + * SystemLogServices constructor. + * + * @param SystemLogDao $dao + */ + public function __construct(SystemLogDao $dao) + { + $this->dao = $dao; + } + + /** + * 记录访问日志 + * + * @param int $adminId + * @param string $adminName + * @param string $type + * + * @return bool + */ + public function recordAdminLog(string|int $adminId, string $adminName, string $type) + { + $request = app()->request; + $module = app('http')->getName(); + $rule = trim(strtolower($request->rule()->getRule())); + + /** @var SystemMenusServices $service */ + $service = app()->make(SystemMenusServices::class); + $data = [ + 'method' => $module, + 'admin_id' => $adminId, + 'add_time' => time(), + 'admin_name' => $adminName, + 'path' => $rule, + 'page' => $service->getVisitName($rule) ?: '未知', + 'ip' => $request->ip(), + 'type' => $type, + ]; + + if ($this->dao->save($data)) { + return true; + } else { + return false; + } + } + + /** + * 获取系统日志列表 + * + * @param array $where + * @param int $level + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getLogList(array $where, int $level): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getLogList($where, $page, $limit); + $count = $this->dao->count($where); + return compact('list', 'count'); + } +} diff --git a/demo/thinkphp/backend/app/services/system/route/SystemRouteCateServices.php b/demo/thinkphp/backend/app/services/system/route/SystemRouteCateServices.php new file mode 100644 index 0000000000000000000000000000000000000000..5f2ffbcc24f229339bdf5e4cd0d5ef408fff7cb8 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/route/SystemRouteCateServices.php @@ -0,0 +1,120 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\services\system\route; + + +use app\dao\system\route\SystemRouteCateDao; +use app\services\BaseServices; +use phoenix\services\FormBuilder; + +/** + * Class SystemRouteCateServices + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + * @package app\services\system + */ +class SystemRouteCateServices extends BaseServices +{ + + /** + * SystemRouteCateServices constructor. + * @param SystemRouteCateDao $dao + */ + public function __construct(SystemRouteCateDao $dao) + { + $this->dao = $dao; + } + + public function getPathValue(array $path) + { + $pathAttr = explode('/', $path); + $pathData = []; + foreach ($pathAttr as $item) { + if (!$item) { + $pathData[] = $item; + } + } + return $pathAttr; + } + + /** + * @param array $path + * @param int $id + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function setPathValue(array $path, int $id) + { + return ($path ? '/' . implode('/', $path) : '') . '/' . $id . '/'; + } + + /** + * @param string $appName + * @param string $field + * @param string $order + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function getAllList(string $appName = 'outapi', string $field = '*', string $order = ''): array + { + $list = $this->dao->selectList(['app_name' => $appName], $field, 0, 0, $order)->toArray(); + return get_tree_children($list); + } + + /** + * @param int $id + * @param string $appName + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function getFrom(int $id = 0, string $appName = 'outapi') + { + $url = '/system/route_cate'; + $cateInfo = []; + $path = []; + if ($id) { + $cateInfo = $this->dao->get($id); + $cateInfo = $cateInfo ? $cateInfo->toArray() : []; + $url .= '/' . $id; + $path = explode('/', $cateInfo['path']); + $newPath = []; + foreach ($path as $item) { + if ($item) { + $newPath[] = $item; + } + } + $path = $newPath; + } + $options = $this->dao->selectList(['app_name' => $appName], 'name as label,id as value,id,pid')->toArray(); + $rule = [ +// FormBuilder::cascader('path', '上级分类', $path)->data(get_tree_children($options)), + FormBuilder::input('name', '分类名称', $cateInfo['name'] ?? '')->required(), + FormBuilder::number('sort', '排序', (int)($cateInfo['sort'] ?? 0)), + FormBuilder::hidden('app_name', $appName) + ]; + + return create_form($id ? '修改分类' : '添加分类', $rule, $url, $id ? 'PUT' : 'POST'); + } +} diff --git a/demo/thinkphp/backend/app/services/system/route/SystemRouteServices.php b/demo/thinkphp/backend/app/services/system/route/SystemRouteServices.php new file mode 100644 index 0000000000000000000000000000000000000000..1390941cff211e956727db6bd491df39dcc9d458 --- /dev/null +++ b/demo/thinkphp/backend/app/services/system/route/SystemRouteServices.php @@ -0,0 +1,388 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\services\system\route; + + +use app\dao\system\route\SystemRouteDao; +use app\services\BaseServices; +use phoenix\services\FormBuilder; +use think\exception\ValidateException; +use think\helper\Str; + +/** + * Class SystemRouteServices + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + * @package app\services\system + */ +class SystemRouteServices extends BaseServices +{ + + /** + * SystemRouteServices constructor. + * @param SystemRouteDao $dao + */ + public function __construct(SystemRouteDao $dao) + { + $this->dao = $dao; + } + + /** + * @param array $where + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function getList(array $where) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->selectList($where, 'name,path,method', $page, $limit)->toArray(); + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * @param int $id + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/10 + */ + public function getInfo(int $id) + { + $routeInfo = $this->dao->get($id); + if (!$routeInfo) { + throw new ValidateException(500036); + } + + $routeInfo = $routeInfo->toArray(); + $routeInfo['cate_tree'] = app()->make(SystemRouteCateServices::class)->getAllList($routeInfo['app_name'], '*', 'id asc,sort desc'); + return $routeInfo; + } + + /** + * 获取tree数据 + * @param string $appName + * @param string $name + * @return mixed + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/05/06 + */ + public function getTreeList(string $appName = 'adminapi', string $name = '') + { +// return $this->cacheDriver()->remember('ROUTE_LIST' . strtoupper($appName), function () use ($name, $appName) { + + $list = app()->make(SystemRouteCateServices::class) + ->selectList(['app_name' => $appName], '*', 0, 0, 'id asc,sort desc', [ + 'children' => function ($query) use ($name, $appName) { + $query->where('app_name', $appName) + ->when('' !== $name, function ($q) use ($name) { + $q->where('name|path', 'LIKE', '%' . $name . '%'); + }); + } + ]) + ->toArray(); + + foreach ($list as $key => $item) { + if (!empty($item['children'])) { + foreach ($item['children'] as $k => $v) { + if (isset($v['cate_id']) && isset($v['method'])) { + if ($v['method'] === 'DELETE') { + $v['method'] = 'DEL'; + } + $v['pid'] = $v['cate_id']; + $list[$key]['children'][$k] = $v; + } + } + } + } + + return get_tree_children($list,'children','id','pid'); +// }, 600); + } + + /** + * @param array $importData + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/26 + */ + public function importData(array $importData) + { + foreach ($importData as $item) { + $id = $this->dao->value(['method' => $item['method'], 'path' => $item['path']], 'id'); + if ($id) { + $this->dao->update($id, [ + 'request' => $item['request'], + 'response' => $item['response'], + 'request_type' => $item['request_type'], + ]); + } + } + return true; + } + + /** + * 获取某个应用下的所有路由权限 + * @param string $app + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function getRouteListAll(string $app = 'adminapi') + { + //获取所有的路由 + $this->app = app(); + $this->app->route->setTestMode(true); + $this->app->route->clear(); + $path = $this->app->getRootPath() . 'app' . DS . $app . DS . 'route' . DS; + $files = is_dir($path) ? scandir($path) : []; + foreach ($files as $file) { + if (strpos($file, '.php')) { + include $path . $file; + } + } + + $route = $this->app->route->getRuleList(); + $action_arr = ['index', 'read', 'create', 'save', 'edit', 'update', 'delete']; + + + foreach ($route as $key => $item) { + $real_name = $item['option']['real_name'] ?? ''; + if (is_array($real_name)) { + foreach ($action_arr as $a) { + if (Str::contains($item['route'], $a)) { + $real_name = $real_name[$a] ?? ''; + } + } + } + $item['option']['real_name'] = $real_name; + $route[$key] = $item; + $except = $item['option']['except'] ?? []; + + $router = is_string($item['route']) ? explode('/', $item['route']) : []; + $action = $router[count($router) - 1] ?? null; + //去除不需要的路由 + if ($except && $action && in_array($action, $except)) { + unset($route[$key]); + } + $only = $item['option']['only'] ?? []; + if ($only && $action && !in_array($action, $only)) { + unset($route[$key]); + } + } + + return $route; + } + + /** + * 获取顶级id + * + * @param string $app + * @param string $cateName + * @param int $pid + * + * @return mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/11 + */ + public function topCateId(string $app, string $cateName, int $pid = 0) + { + $oneId = app()->make(SystemRouteCateServices::class)->value(['app_name' => $app, 'name' => $cateName, 'pid' => 0], 'id'); + if (!$oneId) { + $res = app()->make(SystemRouteCateServices::class)->save([ + 'app_name' => $app, + 'name' => $cateName, + 'pid' => $pid, + 'create_time' => time(), + ]); + return $res->id; + } + return $oneId; + } + + /** + * 同步路由 + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function syncRoute(string $app = 'adminapi') + { + //路由列表 + $listAll = $this->getRouteListAll($app); + $list = []; + foreach ($listAll as $item) { + if (!isset($item['option']['mark_name']) || strstr($item['rule'], '') !== false) { + continue; + } else { + $list[$item['option']['mark_name']][] = $item; + } + } + + + $newsList = [];; + foreach ($list as $key => $item) { + $newItem = []; + foreach ($item as $value) { + if (isset($value['option']['cate_name'])) { + $newItem[$value['option']['cate_name']][] = $value; + } else { + $newItem[$key][] = $value; + } + } + $newsList[$key] = $newItem; + } + + $list = []; + foreach ($newsList as $key => $item) { + $keys = array_keys($item); + $pid = $this->topCateId($app, $key, 0); + if ($keys == 1 && $key == $keys[0]) { + foreach ($item[$key] as $value) { + $list[$pid][] = $value; + } + } else { + foreach ($item as $i => $k) { + $cateId = $this->topCateId($app, $i, $pid); + foreach ($k as $value) { + $list[$cateId][] = $value; + } + } + } + } + + //保持新增的权限路由 + $data = $this->dao->selectList(['app_name' => $app], 'path,method')->toArray(); + $save = []; + foreach ($list as $key => $value) { + foreach ($value as $item) { + if (!$this->diffRoute($data, $item['rule'], $item['method']) && strstr($item['rule'], '') === false) { + $pathAndAction = explode('/', $item['route']); + $save[] = [ + 'name' => $item['option']['real_name'] ?? $item['name'], + 'path' => $item['rule'], + 'cate_id' => $key, + 'app_name' => $app, + 'file_path' => 'app/' . $app . '/controller/' . str_replace('.', '/', $pathAndAction[0]) . '.php', + 'action' => $pathAndAction[1], + 'type' => isset($item['option']['is_common']) && $item['option']['is_common'] ? 1 : 0, + 'method' => $item['method'], + 'create_time' => date('Y-m-d H:i:s'), + ]; + } + } + } + + if ($save) { + $this->dao->saveAll($save); + } + //删除不存在的权限路由 + $data = $this->dao->selectList(['app_name' => $app], 'path,method,id')->toArray(); + $delete = []; + $deleteData = []; + foreach ($data as $item) { + if (!$this->diffRoute($listAll, $item['path'], $item['method'], 'rule') && $item['path'] !== '') { + $delete[] = $item['id']; + $deleteData[] = [ + 'path' => $item['path'], + 'method' => $item['method'] + ]; + } + } + //删除不存在的路由 + if ($delete) { + $this->dao->delete([['id', 'in', $delete]]); + } + //删除不存在的权限 +// if ($deleteData) { +// foreach ($deleteData as $item) { +// app()->make(SystemMenusServices::class)->deleteMenu($item['path'], $item['method']); +// } +// } + $this->cacheDriver()->clear(); + } + + /** + * 对比路由 + * @param array $data + * @param string $path + * @param string $method + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + protected function diffRoute(array $data, string $path, string $method, string $key = 'path') + { + $res = false; + foreach ($data as $item) { + if (strtolower($item['method']) == strtolower($method) && strtolower($item[$key]) == strtolower($path)) { + $res = true; + break; + } else if ($method === '*' && strtolower($item[$key]) == strtolower($path)) { + $res = true; + break; + } + } + return $res; + } + + /** + * 添加和修改路由 + * @param int $id + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function getFrom(int $id = 0, string $appName = 'adminapi') + { + $cateList = app()->make(SystemRouteCateServices::class)->getAllList($appName, 'name as label,path as value'); + + $url = '/system/route'; + $routeInfo = []; + if ($id) { + $routeInfo = $this->dao->get($id); + $routeInfo = $routeInfo ? $routeInfo->toArray() : []; + $url .= '/' . $id; + } + + $rule = [ + FormBuilder::cascader('cate_id', '分类', $routeInfo['cate_id'] ?? 0)->data($cateList), + FormBuilder::input('name', '路由名称', $routeInfo['name'] ?? '')->required(), + FormBuilder::input('path', '路由路径', $routeInfo['path'] ?? '')->required(), + FormBuilder::select('method', '请求方式', $routeInfo['method'] ?? '')->options([ + ['value' => 'POST', 'label' => 'POST'], + ['value' => 'GET', 'label' => 'GET'], + ['value' => 'DELETE', 'label' => 'DELETE'], + ['value' => 'PUT', 'label' => 'PUT'], + ['value' => '*', 'label' => '*'], + ])->required(), + FormBuilder::radio('type', '类型', $routeInfo['type'] ?? 0)->options([ + ['value' => 0, 'lable' => '普通路由'], + ['value' => 1, 'lable' => '公共路由'], + ]), + FormBuilder::hidden('app_name', $appName), + ]; + + return create_form($id ? '修改路由' : '添加路由', $rule, $url, $id ? 'PUT' : 'POST'); + } +} diff --git a/demo/thinkphp/backend/backup/20240311-152214-1.sql.gz b/demo/thinkphp/backend/backup/20240311-152214-1.sql.gz new file mode 100644 index 0000000000000000000000000000000000000000..9564e877d187eb99f1466364819fc3f55008a930 Binary files /dev/null and b/demo/thinkphp/backend/backup/20240311-152214-1.sql.gz differ diff --git a/demo/thinkphp/backend/composer.json b/demo/thinkphp/backend/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..be51db058b5e29aabe6dcbb0c9d96e6e897c03e5 --- /dev/null +++ b/demo/thinkphp/backend/composer.json @@ -0,0 +1,68 @@ +{ + "name": "topthink/think", + "description": "the new thinkphp framework", + "type": "project", + "keywords": [ + "framework", + "thinkphp", + "ORM" + ], + "homepage": "https://www.thinkphp.cn/", + "license": "Apache-2.0", + "authors": [ + { + "name": "liu21st", + "email": "liu21st@gmail.com" + }, + { + "name": "yunwuxin", + "email": "448901948@qq.com" + } + ], + "require": { + "php": ">=8.0.0", + "topthink/framework": "^8.0", + "topthink/think-orm": "^3.0", + "topthink/think-filesystem": "^2.0", + "topthink/think-multi-app": "^1.0", + "firebase/php-jwt": "^6.8", + "xaboy/form-builder": "~2.0", + "topthink/think-captcha": "^3.0", + "spatie/macroable": "^2.0", + "ramsey/uuid": "^4.7", + "volcengine/volc-sdk-php": "^1.0", + "topthink/think-queue": "^3.0", + "topthink/think-view": "^2.0", + "workerman/workerman": "^4.1", + "workerman/crontab": "^1.0", + "workerman/channel": "^1.2", + "topthink/think-image": "^1.0", + "phpenum/phpenum": "^1.4", + "kphoen/rulerz": "^0.21.1", + "karka/ingenious": "@dev", + "monolog/monolog": "^2.9", + "ingen/ingenious": "^1.0" + }, + "require-dev": { + "symfony/var-dumper": ">=4.2", + "topthink/think-trace": "^1.0" + }, + "autoload": { + "psr-4": { + "app\\": "app", + "phoenix\\": "phoenix" + }, + "psr-0": { + "": "extend/" + } + }, + "config": { + "preferred-install": "dist" + }, + "scripts": { + "post-autoload-dump": [ + "@php think service:discover", + "@php think vendor:publish" + ] + } +} diff --git a/demo/thinkphp/backend/config/app.php b/demo/thinkphp/backend/config/app.php new file mode 100644 index 0000000000000000000000000000000000000000..add341ad5f06fd0c0b1da03fccc1cde936264ef3 --- /dev/null +++ b/demo/thinkphp/backend/config/app.php @@ -0,0 +1,43 @@ + env('APP_HOST', ''), + // 应用的命名空间 + 'app_namespace' => '', + // 是否启用路由 + 'with_route' => true, + // 是否启用事件 + 'with_event' => true, + // 默认应用 + 'default_app' => 'index', + // 默认时区 + 'default_timezone' => 'Asia/Shanghai', + + //自动多应用模式 + 'auto_multi_app' => true, + //开启应用快速访问 + "app_express" => true, + + // 应用映射(自动多应用模式有效) + 'app_map' => [], + // 域名绑定(自动多应用模式有效) + 'domain_bind' => [], + // 禁止URL访问的应用列表(自动多应用模式有效) + 'deny_app_list' => [], + + // 异常页面的模板文件 + 'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl', + + // 错误显示信息,非调试模式有效 + 'error_message' => '页面错误!请稍后再试~', + // 显示错误信息 + 'show_error_msg' => true, + // 没有开启消息队列命令或者定时任务命令的提醒开关 + 'console_remind' => true, + //应用前缀 + 'admin_prefix' => 'ingenious', +]; diff --git a/demo/thinkphp/backend/config/cache.php b/demo/thinkphp/backend/config/cache.php new file mode 100644 index 0000000000000000000000000000000000000000..f9c7f7b431eab1a2b94e3573002e73d884ea0b5e --- /dev/null +++ b/demo/thinkphp/backend/config/cache.php @@ -0,0 +1,54 @@ + 'redis', + + // 缓存连接方式配置 + 'stores' => [ + 'file' => [ + // 驱动方式 + 'type' => 'File', + // 缓存保存目录 + 'path' => app()->getRuntimePath() . 'cache' . DIRECTORY_SEPARATOR, + // 缓存前缀 + 'prefix' => '', + // 缓存有效期 0表示永久缓存 + 'expire' => 0, + // 缓存标签前缀 + 'tag_prefix' => 'tag:', + // 序列化机制 例如 ['serialize', 'unserialize'] + 'serialize' => [], + ], + // 更多的缓存连接 + // redis缓存 + 'redis' => [ + // 驱动方式 + 'type' => 'redis', + // 服务器地址 + 'host' => Env::get('redis.redis_hostname', '127.0.0.1'), + // 端口 + 'port' => Env::get('redis.port', '6379'), + // 密码 + 'password' => Env::get('redis.redis_password', ''), + // 缓存有效期 0表示永久缓存 + 'expire' => 0, + // 缓存前缀 + 'prefix' => Env::get('cache.cache_prefix', 'phoenix:'), + // 缓存标签前缀 + 'tag_prefix' => Env::get('cache.cache_tag_prefix', 'PHOENIX:'), + // 数据库 0号数据库 + 'select' => intval(Env::get('redis.select', 0)), + // 序列化机制 例如 ['serialize', 'unserialize'] + 'serialize' => [], + // 服务端主动关闭 + 'timeout' => 0, + ], + ], +]; diff --git a/demo/thinkphp/backend/config/captcha.php b/demo/thinkphp/backend/config/captcha.php new file mode 100644 index 0000000000000000000000000000000000000000..9bbf529188ce4349b6deeff387bb8c84b274535a --- /dev/null +++ b/demo/thinkphp/backend/config/captcha.php @@ -0,0 +1,39 @@ + 5, + // 验证码字符集合 + 'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY', + // 验证码过期时间 + 'expire' => 1800, + // 是否使用中文验证码 + 'useZh' => false, + // 是否使用算术验证码 + 'math' => false, + // 是否使用背景图 + 'useImgBg' => false, + //验证码字符大小 + 'fontSize' => 25, + // 是否使用混淆曲线 + 'useCurve' => true, + //是否添加杂点 + 'useNoise' => true, + // 验证码字体 不设置则随机 + 'fontttf' => '', + //背景颜色 + 'bg' => [243, 251, 254], + // 验证码图片高度 + 'imageH' => 0, + // 验证码图片宽度 + 'imageW' => 0, + + // 添加额外的验证码设置 + // verify => [ + // 'length'=>4, + // ... + //], +]; diff --git a/demo/thinkphp/backend/config/console.php b/demo/thinkphp/backend/config/console.php new file mode 100644 index 0000000000000000000000000000000000000000..f91b537a343710614345f86decfa83c5b3e552d2 --- /dev/null +++ b/demo/thinkphp/backend/config/console.php @@ -0,0 +1,13 @@ + [ + 'workerman' => \phoenix\command\Workerman::class, + 'timer' => \phoenix\command\Timer::class, + 'util' => \phoenix\command\Util::class, + 'npm' => \phoenix\command\Npm::class + ], +]; diff --git a/demo/thinkphp/backend/config/cookie.php b/demo/thinkphp/backend/config/cookie.php new file mode 100644 index 0000000000000000000000000000000000000000..20602e73529f2953115f1fe06cb2383b44e85119 --- /dev/null +++ b/demo/thinkphp/backend/config/cookie.php @@ -0,0 +1,31 @@ + 0, + // cookie 保存路径 + 'path' => '/', + // cookie 有效域名 + 'domain' => 'http://127.0.0.5', + // cookie 启用安全传输 + 'secure' => false, + // httponly设置 + 'httponly' => false, + // 是否使用 setcookie + 'setcookie' => true, + // samesite 设置,支持 'strict' 'lax' + 'samesite' => '', + + // 跨域header + 'header' => [ + 'Access-Control-Allow-Origin' => '*', + 'Access-Control-Allow-Headers' => 'Authori-zation,Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With, Form-type, Cb-lang, Invalid-zation', + 'Access-Control-Allow-Methods' => 'GET,POST,PATCH,PUT,DELETE,OPTIONS,DELETE', + 'Access-Control-Max-Age' => '1728000', + 'Access-Control-Allow-Credentials' => 'true', + ], + // token名称 + 'token_name' => 'Authori-zation', +]; diff --git a/demo/thinkphp/backend/config/database.php b/demo/thinkphp/backend/config/database.php new file mode 100644 index 0000000000000000000000000000000000000000..a76e9427308ced9af99599abb94cf852fb5723a3 --- /dev/null +++ b/demo/thinkphp/backend/config/database.php @@ -0,0 +1,86 @@ + env('DB_DRIVER', 'mysql'), + + // 自定义时间查询规则 + 'time_query_rule' => [], + + // 自动写入时间戳字段 + // true为自动识别类型 false关闭 + // 字符串则明确指定时间字段类型 支持 int timestamp datetime date + 'auto_timestamp' => true, + + // 时间字段取出后的默认时间格式 + 'datetime_format' => 'Y-m-d H:i:s', + + // 时间字段配置 配置格式:create_time,update_time + 'datetime_field' => '', + + // 数据库连接配置信息 + 'connections' => [ + 'mysql' => [ + // 数据库类型 + 'type' => Env::get('database.type', 'mysql'), + // 服务器地址 + 'hostname' => Env::get('database.hostname', '127.0.0.1'), + // 数据库名 + 'database' => Env::get('database.database', 'thinkphp_flow'), + // 用户名 + 'username' => Env::get('database.username', 'root'), + // 密码 + 'password' => Env::get('database.password', 'root'), + // 端口 + 'hostport' => Env::get('database.hostport', '3306'), + // 连接dsn + 'dsn' => '', + // 数据库连接参数 + 'params' => [], + // 数据库编码默认采用utf8 + 'charset' => Env::get('database.charset', 'utf8'), + // 数据库表前缀 + 'prefix' => Env::get('database.prefix', 'lms_clx_'), + // 数据库调试模式 + 'debug' => Env::get('database.debug', true), + // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) + 'deploy' => 0, + // 数据库读写是否分离 主从式有效 + 'rw_separate' => false, + // 读写分离后 主服务器数量 + 'master_num' => 1, + //是否严格模式 + 'strict' => true, + // 指定从服务器序号 + 'slave_no' => '', + // 是否严格检查字段是否存在 + 'fields_strict' => true, + // 是否需要进行SQL性能分析 + 'sql_explain' => false, + // Builder类 + 'builder' => '', + // Query类 + 'query' => '', + // 是否需要断线重连 + 'break_reconnect' => true, + // 监听SQL + 'trigger_sql' => env('APP_DEBUG', true), + // 开启字段缓存 + 'fields_cache' => false, + ], + // 更多的数据库配置信息 + ], + //数据分页配置 + 'page' => [ + //页码key + 'pageKey' => 'page', + //每页截取key + 'limitKey' => 'limit', + //每页截取最大值 + 'limitMax' => 1000, + //默认条数 + 'defaultLimit' => 10, + ], +]; diff --git a/demo/thinkphp/backend/config/filesystem.php b/demo/thinkphp/backend/config/filesystem.php new file mode 100644 index 0000000000000000000000000000000000000000..508443e5784d62b88bf095015e8e420e918ff94d --- /dev/null +++ b/demo/thinkphp/backend/config/filesystem.php @@ -0,0 +1,27 @@ + Env::get('filesystem.driver', 'public'), + // 磁盘列表 + 'disks' => [ + 'local' => [ + 'type' => 'local', + 'root' => app()->getRuntimePath() . 'storage', + ], + 'public' => [ + // 磁盘类型 + 'type' => 'local', + // 磁盘路径 + 'root' => app()->getRootPath() . 'public/uploads', + // 磁盘路径对应的外部URL路径 + 'url' => '/uploads', + // 可见性 + 'visibility' => 'public', + ], + // 更多的磁盘配置信息 + ], + 'password' => '', +]; diff --git a/demo/thinkphp/backend/config/ingenious.php b/demo/thinkphp/backend/config/ingenious.php new file mode 100644 index 0000000000000000000000000000000000000000..3552039768e5e0e173c2cb4e5947d53acbf7480f --- /dev/null +++ b/demo/thinkphp/backend/config/ingenious.php @@ -0,0 +1,16 @@ + app()->getRootPath() . 'runtime/ingenious/log/',//日志路径 + 'is_debug' => true,//是否调试模式 + 'redis' => [ + 'host' => '127.0.0.1', + 'port' => '6379', + 'password' => '', + 'expire' => 0, + 'prefix' => 'l:', + 'tag_prefix' => 'ingenious:', + 'select' => 0, + 'timeout' => 0, + ], +]; diff --git a/demo/thinkphp/backend/config/lang.php b/demo/thinkphp/backend/config/lang.php new file mode 100644 index 0000000000000000000000000000000000000000..a00e551384400ec5d0e0e283e90cb97537036223 --- /dev/null +++ b/demo/thinkphp/backend/config/lang.php @@ -0,0 +1,34 @@ + Env::get('DEFAULT_LANG', 'zh-cn'), + // 允许的语言列表 + 'allow_lang_list' => ['zh-cn', 'en-us'], + // 多语言自动侦测变量名 + 'detect_var' => 'lang', + // 是否使用Cookie记录 + 'use_cookie' => true, + // 多语言cookie变量 + 'cookie_var' => 'think_lang', + // 多语言header变量 + 'header_var' => 'think-lang', + + // 扩展语言包 + 'extend_list' => [ + 'zh_cn' => app()->getBasePath() . 'lang/zh_cn.php', + 'en_us' => app()->getBasePath() . 'lang/en_us.php', + ], + // Accept-Language转义为对应语言包名称 + 'accept_language' => [ + 'zh-hans-cn' => 'zh_cn', + 'en-hans-us' => 'en_us', + ], + // 是否支持语言分组 + 'allow_group' => false, +]; diff --git a/demo/thinkphp/backend/config/lflow.php b/demo/thinkphp/backend/config/lflow.php new file mode 100644 index 0000000000000000000000000000000000000000..bb9cc0932dfffa4efe67738e7de176c33bad617a --- /dev/null +++ b/demo/thinkphp/backend/config/lflow.php @@ -0,0 +1,9 @@ + 'leaveForm',//子流程表单 + 'is_future_running' => false,//启动子流程方式 +]; diff --git a/demo/thinkphp/backend/config/log.php b/demo/thinkphp/backend/config/log.php new file mode 100644 index 0000000000000000000000000000000000000000..98ede8556ffb35e889af2dfb1cecb79fb1dd3893 --- /dev/null +++ b/demo/thinkphp/backend/config/log.php @@ -0,0 +1,48 @@ + Env::get('log.channel', 'file'), + // 日志记录级别 + 'level' => ['error', 'warning', 'fail', 'success', 'info', 'notice', 'crontab', 'phoenix'], + // 日志类型记录的通道 ['error'=>'email',...] + 'type_channel' => [], + + //是否开启业务成功日志 + 'success_log' => false, + //是否开启业务失败日志 + 'fail_log' => false, + //是否开启定时任务日志 + 'timer_log' => false, + // 关闭全局日志写入 + 'close' => false, + // 全局日志处理 支持闭包 + 'processor' => null, + + // 日志通道列表 + 'channels' => [ + 'file' => [ + // 日志记录方式 + 'type' => 'File', + // 日志保存目录 + 'path' => app()->getRuntimePath() . 'log' . DIRECTORY_SEPARATOR, + // 单文件日志写入 + 'single' => false, + // 独立日志级别 + 'apart_level' => ['error', 'fail', 'success', 'crontab', 'phoenix'], + // 最大日志文件数量 + 'max_files' => 60, + 'time_format' => 'Y-m-d H:i:s', + 'format' => '%s|%s|%s', + // 是否实时写入 + 'realtime_write' => false, + ], + // 其它日志通道配置 + ], + +]; diff --git a/demo/thinkphp/backend/config/middleware.php b/demo/thinkphp/backend/config/middleware.php new file mode 100644 index 0000000000000000000000000000000000000000..b31e7ecd474d73ca66ad254d0a04f3117a30cee7 --- /dev/null +++ b/demo/thinkphp/backend/config/middleware.php @@ -0,0 +1,9 @@ + [], + // 优先级设置,此数组中的中间件会按照数组中的顺序优先执行 + 'priority' => [], + +]; diff --git a/demo/thinkphp/backend/config/queue.php b/demo/thinkphp/backend/config/queue.php new file mode 100644 index 0000000000000000000000000000000000000000..c9a144277c5b46581f54c4652fc1e3409c139981 --- /dev/null +++ b/demo/thinkphp/backend/config/queue.php @@ -0,0 +1,42 @@ + +// +---------------------------------------------------------------------- + +use think\facade\Env; + +return [ + 'default' => 'redis', + 'prefix' => 'phoenix_', + 'connections' => [ + 'sync' => [ + 'type' => 'sync', + ], + 'database' => [ + 'type' => 'database', + 'queue' => 'default', + 'table' => 'jobs', + 'connection' => null, + ], + 'redis' => [ + 'type' => 'redis', + 'queue' => 'PHOENIX' . Env::get('queue.queue_name', ''), + 'host' => Env::get('redis.redis_hostname', '127.0.0.1'), + 'port' => Env::get('redis.port', 6379), + 'password' => Env::get('redis.redis_password', ''), + 'select' => Env::get('redis.select', 0), + 'timeout' => 0, + 'persistent' => false, + ], + ], + 'failed' => [ + 'type' => 'none', + 'table' => 'failed_jobs', + ], +]; diff --git a/demo/thinkphp/backend/config/route.php b/demo/thinkphp/backend/config/route.php new file mode 100644 index 0000000000000000000000000000000000000000..e256675140547e1968d9a46e91caad502ee95880 --- /dev/null +++ b/demo/thinkphp/backend/config/route.php @@ -0,0 +1,46 @@ + '/', + // URL伪静态后缀 + 'url_html_suffix' => 'html', + // URL普通方式参数 用于自动生成 + 'url_common_param' => true, + // 是否开启路由延迟解析 + 'url_lazy_route' => false, + // 是否强制使用路由 + 'url_route_must' => true,//默认false + // 合并路由规则 + 'route_rule_merge' => false, + // 路由是否完全匹配 + 'route_complete_match' => true,//默认false + // 访问控制器层名称 + 'controller_layer' => 'controller', + // 空控制器名 + 'empty_controller' => 'Error', + // 是否使用控制器后缀 + 'controller_suffix' => false, + // 默认的路由变量规则 +// 'default_route_pattern' => '[\w\.]+', + 'default_route_pattern' => '[\w\-]+',//匹配适应中划线id传参 + // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则 + 'request_cache_key' => false, + // 请求缓存有效期 + 'request_cache_expire' => null, + // 全局请求缓存排除规则 + 'request_cache_except' => [], + // 默认控制器名 + 'default_controller' => 'Index', + // 默认操作名 + 'default_action' => 'index', + // 操作方法后缀 + 'action_suffix' => '', + // 默认JSONP格式返回的处理方法 + 'default_jsonp_handler' => 'jsonpReturn', + // 默认JSONP处理方法 + 'var_jsonp_handler' => 'callback', +]; diff --git a/demo/thinkphp/backend/config/session.php b/demo/thinkphp/backend/config/session.php new file mode 100644 index 0000000000000000000000000000000000000000..a1635127df1d952f4198821a389a21b36e8e0a39 --- /dev/null +++ b/demo/thinkphp/backend/config/session.php @@ -0,0 +1,19 @@ + 'PHPSESSID', + // SESSION_ID的提交变量,解决flash上传跨域 + 'var_session_id' => '', + // 驱动方式 支持file cache + 'type' => 'file', + // 存储连接标识 当type使用cache的时候有效 + 'store' => null, + // 过期时间 + 'expire' => 10080, + // 前缀 + 'prefix' => '', +]; diff --git a/demo/thinkphp/backend/config/trace.php b/demo/thinkphp/backend/config/trace.php new file mode 100644 index 0000000000000000000000000000000000000000..fad2392d9bba5b6e9aaedf64824bc30560212aee --- /dev/null +++ b/demo/thinkphp/backend/config/trace.php @@ -0,0 +1,10 @@ + 'Html', + // 读取的日志通道名 + 'channel' => '', +]; diff --git a/demo/thinkphp/backend/config/upload.php b/demo/thinkphp/backend/config/upload.php new file mode 100644 index 0000000000000000000000000000000000000000..a15d62a348d8b69bce464e8697268a56ae794476 --- /dev/null +++ b/demo/thinkphp/backend/config/upload.php @@ -0,0 +1,76 @@ + +// +---------------------------------------------------------------------- + +return [ + //默认上传模式,后台配置优先,添加类型一定索引要和驱动名一致 用小些字母 + 'default' => 'local', + //上传文件大小 + 'filesize' => 20971520, + //上传文件后缀类型 + 'fileExt' => ['jpg', 'jpeg', 'png', 'gif', 'pem', 'mp3', 'wma', 'wav', 'amr', 'mp4', 'key', 'xlsx', 'xls', 'txt', 'ico'], + //上传文件类型 + 'fileMime' => [ + 'image/jpg', + 'image/jpeg', + 'image/gif', + 'image/png', + 'text/plain', + 'audio/mpeg', + 'video/mp4', + 'application/octet-stream', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/vnd.ms-works', + 'application/vnd.ms-excel', + 'application/zip', + 'application/vnd.ms-excel', + 'application/vnd.ms-excel', + 'text/xml', + 'image/x-icon', + 'image/vnd.microsoft.icon', + 'application/x-x509-ca-cert', + ], + //驱动模式,此配置优先与后台配置,后台添加配置请加前缀,例如添加七牛云配置:accessKey 后台添加变量名 qiniu_accessKey + 'stores' => [ + //本地上传配置 + 'local' => [], + //七牛云上传配置 + 'qiniu' => [ + 'AccessKeyId' => '', // sys_config('qiniu_accessKey') + 'AccessKeySecret' => '', // sys_config('qiniu_secretKey') + ], + //oss 阿里云上传配置 + 'oss' => [ + 'AccessKeyId' => '', // sys_config('accessKey') + 'AccessKeySecret' => '', // sys_config('secretKey') + ], + //cos 腾讯云上传配置 + 'cos' => [ + 'AccessKeyId' => '', //sys_config('tengxun_accessKey') + 'AccessKeySecret' => '', //sys_config('tengxun_secretKey') + 'APPID' => '', //sys_config('tengxun_appid') + ], + //oss 京东云 + 'jdoss' => [ + 'AccessKeyId' => '', // sys_config('accessKey') + 'AccessKeySecret' => '', // sys_config('secretKey') + ], + //oss 华为云 + 'obs' => [ + 'AccessKeyId' => '', // sys_config('accessKey') + 'AccessKeySecret' => '', // sys_config('secretKey') + ], + //oss 天翼云 + 'tyoss' => [ + 'AccessKeyId' => '', // sys_config('accessKey') + 'AccessKeySecret' => '', // sys_config('secretKey') + ], + ] +]; diff --git a/demo/thinkphp/backend/config/view.php b/demo/thinkphp/backend/config/view.php new file mode 100644 index 0000000000000000000000000000000000000000..01259a0ef527b6a92d8eb31f4d89cd3bdb369579 --- /dev/null +++ b/demo/thinkphp/backend/config/view.php @@ -0,0 +1,25 @@ + 'Think', + // 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法 + 'auto_rule' => 1, + // 模板目录名 + 'view_dir_name' => 'view', + // 模板后缀 + 'view_suffix' => 'html', + // 模板文件名分隔符 + 'view_depr' => DIRECTORY_SEPARATOR, + // 模板引擎普通标签开始标记 + 'tpl_begin' => '{', + // 模板引擎普通标签结束标记 + 'tpl_end' => '}', + // 标签库标签开始标记 + 'taglib_begin' => '{', + // 标签库标签结束标记 + 'taglib_end' => '}', +]; diff --git a/demo/thinkphp/backend/config/workerman.php b/demo/thinkphp/backend/config/workerman.php new file mode 100644 index 0000000000000000000000000000000000000000..5e003c3695b2e5addfd62c919020b3a176972bc9 --- /dev/null +++ b/demo/thinkphp/backend/config/workerman.php @@ -0,0 +1,55 @@ + +// +---------------------------------------------------------------------- +return [ + + // 系统程序接收到发送过来的消息,通过此端口推送给对应的客户或者客服,以及后台新订单弹窗提醒 + 'channel' => [ + //内部通讯监听端口 + 'port' => 50003, + //内部通讯地址 + 'ip' => '127.0.0.1', + ], + + // notice 新订单和新退款单发送消息给程序,后台的消息通知 + 'admin' => [ + //协议 + 'protocol' => 'websocket', + //监听地址 + 'ip' => '0.0.0.0', + //监听端口 + 'port' => 50001, + //设置当前Worker实例启动多少个进程 + 'serverCount' => 1, + ], + + // msg 客户或者客服发送消息给程序,客服消息通知 + 'chat' => [ + //协议 + 'protocol' => 'websocket', + //监听地址 + 'ip' => '0.0.0.0', + //监听端口 + 'port' => 50002, + //设置当前Worker实例启动多少个进程 + 'serverCount' => 1, + ], + + 'kefu' => [ + //协议 + 'protocol' => 'websocket', + //监听地址 + 'ip' => '0.0.0.0', + //监听端口,端口一定不能和配置文件内的有重复 + 'port' => 20004, + //设置当前Worker实例启动多少个进程 + 'serverCount' => 1, + ], +]; diff --git a/demo/thinkphp/backend/data.sql b/demo/thinkphp/backend/data.sql new file mode 100644 index 0000000000000000000000000000000000000000..38bc79a39d258e2ed6a5b7058931909a2e74e60c --- /dev/null +++ b/demo/thinkphp/backend/data.sql @@ -0,0 +1,7235 @@ +/* + Navicat Premium Data Transfer + + Source Server : 127.0.0.1 + Source Server Type : MySQL + Source Server Version : 80012 + Source Host : localhost:3306 + Source Schema : thinkphp_flow + + Target Server Type : MySQL + Target Server Version : 80012 + File Encoding : 65001 + + Date: 28/05/2024 10:29:19 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for lms_clx_lang_code +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_lang_code`; +CREATE TABLE `lms_clx_lang_code` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID', + `type_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '语言类型', + `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '状态码', + `remarks` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '备注说明', + `lang_explain` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '说明', + `is_admin` tinyint(1) NOT NULL DEFAULT 0 COMMENT '服务端1,用户端2', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '语言code表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_lang_code +-- ---------------------------- +INSERT INTO `lms_clx_lang_code` VALUES ('1', '1', '100000', '保存成功', '保存成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('10', '1', '100009', '图片上传成功', '图片上传成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('100', '1', '400033', '请填写管理员账号', '请填写管理员账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1000', '1', '410169', '缺少字体文件Normal', '缺少字体文件Normal', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1001', '1', '410170', '生成图片失败', '生成图片失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1002', '1', '410171', '生成图片时,系统错误', '生成图片时,系统错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1003', '1', '410172', '生成海报失败', '生成海报失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1004', '1', '410173', '订单不存在', '订单不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1005', '1', '410174', '订单已支付', '订单已支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1006', '1', '410175', '请填写实际支付金额', '请填写实际支付金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1007', '1', '410176', '实际支付金额不能小于0元', '实际支付金额不能小于0元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1008', '1', '410177', '请填写备注内容', '请填写备注内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1009', '1', '410178', '请先处理售后申请', '请先处理售后申请', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('101', '1', '400034', '管理员账号为英文字母', '管理员账号为英文字母', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1010', '1', '410179', '用户已取消申请', '用户已取消申请', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1011', '1', '410180', '售后订单状态不支持该操作', '售后订单状态不支持该操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1012', '1', '410181', '退款修改状态错误', '退款修改状态错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1013', '1', '410182', '修改退款状态成功', '修改退款状态成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1014', '1', '410183', '已退完支付金额,不能再退款了', '已退完支付金额,不能再退款了', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1015', '1', '410184', '请输入退款金额', '请输入退款金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1016', '1', '410185', '退款金额大于支付金额,请修改退款金额', '退款金额大于支付金额,请修改退款金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1017', '1', '410186', '退款成功', '退款成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1018', '1', '410187', '退款失败', '退款失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1019', '1', '410188', '请输入核销码或者扫描核销二维码', '请输入核销码或者扫描核销二维码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('102', '1', '400035', '请输管理员姓名', '请输管理员姓名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1020', '1', '410189', '核销成功', '核销成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1021', '1', '410190', '请输入付款金额', '请输入付款金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1022', '1', '410191', '支付金额不能为0元', '支付金额不能为0元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1023', '1', '410192', '付费会员功能暂未开启', '付费会员功能暂未开启', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1024', '1', '410193', '支付数据生成失败', '支付数据生成失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1025', '1', '410194', '支付订单不存在', '支付订单不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1026', '1', '410195', '微信支付成功', '微信支付成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1027', '1', '410196', '前往支付', '前往支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1028', '1', '410197', '余额支付成功', '余额支付成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1029', '1', '410198', '请传入支付宝支付回调URL', '请传入支付宝支付回调URL', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('103', '1', '400036', '请选择管理员身份', '请选择管理员身份', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1030', '1', '410199', '支付宝支付成功', '支付宝支付成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1031', '1', '410200', '订单生成失败', '订单生成失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1032', '1', '410201', '请提交购买的商品', '请提交购买的商品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1033', '1', '410202', '商品不存在,请重新选择商品下单', '商品不存在,请重新选择商品下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1034', '1', '410203', '订单创建成功', '订单创建成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1035', '1', '410204', '收货成功', '收货成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1036', '1', '410205', '收货失败', '收货失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1037', '1', '410206', '快递单号不存在', '快递单号不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1038', '1', '410207', '默认运费模板未配置,无法下单', '默认运费模板未配置,无法下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1039', '1', '410208', '订单已过期,请刷新当前页面', '订单已过期,请刷新当前页面', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('104', '1', '400037', '身份必须为数组', '身份必须为数组', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1040', '1', '410209', '订单已创建,请点击查看完成支付', '订单已创建,请点击查看完成支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1041', '1', '410210', '订单生成失败,你已经在该团内不能再参加了', '订单生成失败,你已经在该团内不能再参加了', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1042', '1', '410211', '订单生成失败,你已经参加该团了,请先支付订单', '订单生成失败,你已经参加该团了,请先支付订单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1043', '1', '410212', '该团人员已满', '该团人员已满', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1044', '1', '410213', '暂不支持该支付方式,请刷新页面或者联系管理员', '暂不支持该支付方式,请刷新页面或者联系管理员', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1045', '1', '410214', '您购买的商品库存已不足{:cart_num}{:unit_name}', '您购买的商品库存已不足{:cart_num}{:unit_name}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1046', '1', '410215', '该订单已失效', '该订单已失效', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1047', '1', '410216', '支付失败', '支付失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1048', '1', '410217', '支付成功', '支付成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1049', '1', '410218', '支付方式错误', '支付方式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('105', '1', '400038', '请填写城市名称', '请填写城市名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1050', '1', '410219', '订单商品已评价', '订单商品已评价', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1051', '1', '410220', '请为商品评分', '请为商品评分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1052', '1', '410221', '请为商家服务评分', '请为商家服务评分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1053', '1', '410222', '评价失败', '评价失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1054', '1', '410223', '请重新选择退款商品或件数', '请重新选择退款商品或件数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1055', '1', '410224', '当前状态不能取消申请', '当前状态不能取消申请', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1056', '1', '410225', '重选成功', '重选成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1057', '1', '410226', '订单已退款', '订单已退款', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1058', '1', '410227', '使用积分抵扣失败', '使用积分抵扣失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1059', '1', '410228', '会员类型不存在', '会员类型不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('106', '1', '400039', 'level数据格式错误,应为整数', 'level数据格式错误,应为整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1060', '1', '410229', '您已是永久会员无需再购买', '您已是永久会员无需再购买', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1061', '1', '410230', '该会员卡暂时无法购买', '该会员卡暂时无法购买', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1062', '1', '410231', '您已经领取过免费会员', '您已经领取过免费会员', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1063', '1', '410232', '此类型会员卡暂未开售', '此类型会员卡暂未开售', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1064', '1', '410233', '获取购物车信息失败', '获取购物车信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1065', '1', '410234', '您要购买的优惠券已失效,无法购买', '您要购买的优惠券已失效,无法购买', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1066', '1', '410235', '您已获取过该优惠券,无法再次购买', '您已获取过该优惠券,无法再次购买', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1067', '1', '410236', '请刷新后重试', '请刷新后重试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1068', '1', '410237', '暂无库存', '暂无库存', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1069', '1', '410238', '选择的规格库存不足', '选择的规格库存不足', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('107', '1', '400040', 'parent_id数据格式错误,应为整数', 'parent_id数据格式错误,应为整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1070', '1', '410239', '单次购买数量不能大于 {:limit} 件', '单次购买数量不能大于 {:limit} 件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1071', '1', '410240', '该商品限购 {:limit} 件,您已经购买 {:pay_num} 件', '该商品限购 {:limit} 件,您已经购买 {:pay_num} 件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1072', '1', '410241', '选择支付方式有误', '选择支付方式有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1073', '1', '410242', '选择的优惠劵无效', '选择的优惠劵无效', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1074', '1', '410243', '不满足优惠劵的使用条件', '不满足优惠劵的使用条件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1075', '1', '410244', '使用优惠劵失败', '使用优惠劵失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1076', '1', '410245', '请填写姓名和电话', '请填写姓名和电话', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1077', '1', '410246', '营销商品不能使用线下支付', '营销商品不能使用线下支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1078', '1', '410247', '暂无门店无法选择门店自提', '暂无门店无法选择门店自提', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1079', '1', '410248', '订单商品结算失败', '订单商品结算失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('108', '1', '400041', '请输入有效的网址', '请输入有效的网址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1080', '1', '410249', '发票已申请', '发票已申请', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1081', '1', '410250', '正在申请退款中', '正在申请退款中', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1082', '1', '410251', '申请失败', '申请失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1083', '1', '410252', '退款件数大于订单件数', '退款件数大于订单件数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1084', '1', '410253', '该订单已全部拆分', '该订单已全部拆分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1085', '1', '410254', '申请退款失败', '申请退款失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1086', '1', '410255', '存在待处理退款单', '存在待处理退款单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1087', '1', '410256', '该订单无法删除', '该订单无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1088', '1', '410257', '订单已经支付无法取消', '订单已经支付无法取消', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1089', '1', '410258', '拼团商品不能再来一单,请在拼团商品内自行下单', '拼团商品不能再来一单,请在拼团商品内自行下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('109', '1', '400042', '一级返佣比例必须为数字', '一级返佣比例必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1090', '1', '410259', '砍价商品不能再来一单,请在砍价商品内自行下单', '砍价商品不能再来一单,请在砍价商品内自行下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1091', '1', '410260', '秒杀商品不能再来一单,请在秒杀商品内自行下单', '秒杀商品不能再来一单,请在秒杀商品内自行下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1092', '1', '410261', '预售商品不能再来一单,请在预售商品内自行下单', '预售商品不能再来一单,请在预售商品内自行下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1093', '1', '410262', '再来一单失败,请重新下单', '再来一单失败,请重新下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1094', '1', '410263', '该订单无法支付', '该订单无法支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1095', '1', '410264', '订单支付状态有误,无法进行支付', '订单支付状态有误,无法进行支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1096', '1', '410265', '该订单已支付', '该订单已支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1097', '1', '410266', '订单状态错误', '订单状态错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1098', '1', '410267', '此订单不能被核销', '此订单不能被核销', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1099', '1', '410268', '订单有售后申请请先处理', '订单有售后申请请先处理', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('11', '1', '100010', '操作成功', '操作成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('110', '1', '400043', '一级返佣比例最多两位小数', '一级返佣比例最多两位小数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1100', '1', '410269', '您无权限核销此订单,请联系管理员', '您无权限核销此订单,请联系管理员', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1101', '1', '410270', '订单已核销', '订单已核销', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1102', '1', '410271', '拼团订单暂未成功无法核销', '拼团订单暂未成功无法核销', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1103', '1', '410272', '核销失败', '核销失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1104', '1', '410273', '发货成功', '发货成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1105', '1', '410274', '无需支付', '无需支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1106', '1', '410275', '获取用户openid失败,无法支付', '获取用户openid失败,无法支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1107', '1', '410276', '网站名称配置未填写,无法支付', '网站名称配置未填写,无法支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1108', '1', '410277', '支付方式不存在', '支付方式不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1109', '1', '410278', '不支持该类型方式', '不支持该类型方式', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('111', '1', '400044', '一级返佣比例填写范围在0-100之间', '一级返佣比例填写范围在0-100之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1110', '1', '410279', '余额支付失败', '余额支付失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1111', '1', '410280', '暂未开启发票', '暂未开启发票', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1112', '1', '410281', '暂未开启专用发票', '暂未开启专用发票', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1113', '1', '410282', '该发票已经存在', '该发票已经存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1114', '1', '410283', '设置默认发票失败', '设置默认发票失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1115', '1', '410284', '没有此用户,无法检测升级用户等级', '没有此用户,无法检测升级用户等级', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1116', '1', '410285', '检测升级失败', '检测升级失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1117', '1', '410286', '修改订单失败', '修改订单失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1118', '1', '410287', '修改用户信息失败', '修改用户信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1119', '1', '410288', '绑定推广关系失败', '绑定推广关系失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('112', '1', '400045', '二级返佣比例必须为数字', '二级返佣比例必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1120', '1', '410289', '天数不能为0', '天数不能为0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1121', '1', '410290', '添加签到数据失败', '添加签到数据失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1122', '1', '410291', '赠送经验失败', '赠送经验失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1123', '1', '410292', '请先配置签到天数', '请先配置签到天数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1124', '1', '410293', '已经签到', '已经签到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1125', '1', '410294', '商品不存在', '商品不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1126', '1', '410295', '该商品已下架或删除', '该商品已下架或删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1127', '1', '410296', '该商品库存不足', '该商品库存不足', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1128', '1', '410297', '该商品库存不足{:num}', '该商品库存不足{:num}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1129', '1', '410298', '每人总共限购{:num}件', '每人总共限购{:num}件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('113', '1', '400046', '二级返佣比例最多两位小数', '二级返佣比例最多两位小数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1130', '1', '410299', '砍价已结束', '砍价已结束', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1131', '1', '410300', '您不能再发起此件商品砍价', '您不能再发起此件商品砍价', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1132', '1', '410301', '该分享未开启砍价', '该分享未开启砍价', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1133', '1', '410302', '您已经帮砍过此砍价', '您已经帮砍过此砍价', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1134', '1', '410303', '砍价信息没有查到', '砍价信息没有查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1135', '1', '410304', '用户砍价信息未查到', '用户砍价信息未查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1136', '1', '410305', '请选择有效的商品属性', '请选择有效的商品属性', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1137', '1', '410306', '砍价商品不存在', '砍价商品不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1138', '1', '410307', '砍价失败', '砍价失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1139', '1', '410308', '砍价未成功', '砍价未成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('114', '1', '400047', '二级返佣比例填写范围在0-100之间', '二级返佣比例填写范围在0-100之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1140', '1', '410309', '砍价已支付', '砍价已支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1141', '1', '410310', '您不能再帮砍此件商品', '您不能再帮砍此件商品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1142', '1', '410311', '商品已被删除', '商品已被删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1143', '1', '410312', '拼团不存在或已下架,请手动申请退款', '拼团不存在或已下架,请手动申请退款', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1144', '1', '410313', '每个订单限购{:num}件', '每个订单限购{:num}件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1145', '1', '410314', '未查到拼团信息,无法取消', '未查到拼团信息,无法取消', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1146', '1', '410315', '拼团已到期', '拼团已到期', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1147', '1', '410316', '拼团已完成,无法取消', '拼团已完成,无法取消', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1148', '1', '410317', '每人限购{:num}件', '每人限购{:num}件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1149', '1', '410318', '抽奖不存在', '抽奖不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('115', '1', '400048', '待补货数量必须为数字', '待补货数量必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1150', '1', '410319', '领取成功', '领取成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1151', '1', '410320', '领取失败', '领取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1152', '1', '410321', '活动未开始', '活动未开始', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1153', '1', '410322', '活动已结束', '活动已结束', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1154', '1', '410323', '您已有这张优惠券,请勿重复购买', '您已有这张优惠券,请勿重复购买', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1155', '1', '410324', '请核对快递公司编码', '请核对快递公司编码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1156', '1', '410325', '请选择发票', '请选择发票', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1157', '1', '-1', '系统繁忙,请稍候再试', '系统繁忙,请稍候再试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1158', '1', '43104', 'appid与openid不匹配', 'appid与openid不匹配', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1159', '1', '45009', '达到微信api每日限额上限', '达到微信api每日限额上限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('116', '1', '400049', '警戒库存必须为数字', '警戒库存必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1160', '1', '45008', '图文消息超过限制', '图文消息超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1161', '1', '45007', '语音播放时间超过限制', '语音播放时间超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1162', '1', '45006', '图片链接字段超过限制', '图片链接字段超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1163', '1', '45005', '链接字段超过限制', '链接字段超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1164', '1', '45004', '描述字段超过限制', '描述字段超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1165', '1', '45003', '标题字段超过限制', '标题字段超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1166', '1', '45002', '消息内容超过限制', '消息内容超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1167', '1', '45001', '多媒体文件大小超过限制', '多媒体文件大小超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1168', '1', '44004', '文本消息内容为空', '文本消息内容为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1169', '1', '44003', '图文消息内容为空', '图文消息内容为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('117', '1', '400050', '提现最小金额只能为数字', '提现最小金额只能为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1170', '1', '44002', 'POST 的数据包为空', 'POST 的数据包为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1171', '1', '44001', '多媒体文件为空', '多媒体文件为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1172', '1', '43019', '需要将接收者从黑名单中移除', '需要将接收者从黑名单中移除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1173', '1', '43005', '需要好友关系', '需要好友关系', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1174', '1', '43004', '需要接收者关注', '需要接收者关注', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1175', '1', '43003', '需要 HTTPS 请求', '需要 HTTPS 请求', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1176', '1', '43002', '需要 POST 请求', '需要 POST 请求', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1177', '1', '43001', '需要 GET 请求', '需要 GET 请求', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1178', '1', '42007', '用户修改微信密码, accesstoken 和 refreshtoken 失效,需要重新授权', '用户修改微信密码, accesstoken 和 refreshtoken 失效,需要重新授权', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1179', '1', '42003', 'oauth_code 超时', 'oauth_code 超时', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('118', '1', '400051', '提现最小金额必须大于0', '提现最小金额必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1180', '1', '42002', 'refresh_token 超时', 'refresh_token 超时', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1181', '1', '42001', 'access_token 超时,请检查 access_token 的有效期,请参考基础支持 - 获取 access_token 中,对 access_token 的详细机制说明', 'access_token 超时,请检查 access_token 的有效期,请参考基础支持 - 获取 access_token 中,对 access_token 的详细机制说明', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1182', '1', '41009', '缺少 openid', '缺少 openid', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1183', '1', '41008', '缺少 oauth code', '缺少 oauth code', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1184', '1', '41007', '缺少子菜单数据', '缺少子菜单数据', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1185', '1', '41006', '缺少 media_id 参数', '缺少 media_id 参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1186', '1', '41005', '缺少多媒体文件数据', '缺少多媒体文件数据', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1187', '1', '41004', '缺少 secret 参数', '缺少 secret 参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1188', '1', '41003', '缺少 refresh_token 参数', '缺少 refresh_token 参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1189', '1', '41002', '缺少 appid 参数', '缺少 appid 参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('119', '1', '400052', '佣金冻结时间范围在0-180之间', '佣金冻结时间范围在0-180之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1190', '1', '41001', '缺少 access_token 参数', '缺少 access_token 参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1191', '1', '40163', 'oauth_code已使用', 'oauth_code已使用', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1192', '1', '40155', '请勿添加其他公众号的主页链接', '请勿添加其他公众号的主页链接', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1193', '1', '40137', '不支持的图片格式', '不支持的图片格式', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1194', '1', '40132', '微信号不合法', '微信号不合法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1195', '1', '40125', '无效的appsecret', '无效的appsecret', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1196', '1', '40121', '不合法的 media_id 类型', '不合法的 media_id 类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1197', '1', '40120', '子 button 类型错误', '子 button 类型错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1198', '1', '40119', 'button 类型错误', 'button 类型错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1199', '1', '40118', 'media_id 大小不合法', 'media_id 大小不合法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('12', '1', '100011', '暂无数据', '暂无数据', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('120', '1', '400053', '满额分销金额金额必须为数字', '满额分销金额金额必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1200', '1', '40117', '分组名字不合法', '分组名字不合法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1201', '1', '40060', '删除单篇图文时,指定的 article_idx 不合法', '删除单篇图文时,指定的 article_idx 不合法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1202', '1', '40051', '分组名字不合法', '分组名字不合法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1203', '1', '40050', '不合法的分组 id', '不合法的分组 id', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1204', '1', '40048', '无效的url', '无效的url', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1205', '1', '40039', '不合法的 URL 长度', '不合法的 URL 长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1206', '1', '40035', '不合法的参数', '不合法的参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1207', '1', '40038', '不合法的请求格式', '不合法的请求格式', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1208', '1', '40033', '不合法的请求字符,不能包含 \\uxxxx 格式的字符', '不合法的请求字符,不能包含 \\uxxxx 格式的字符', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1209', '1', '40032', '不合法的 openid 列表长度', '不合法的 openid 列表长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('121', '1', '400054', '积分抵用比例必须为数字', '积分抵用比例必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1210', '1', '40031', '不合法的 openid 列表', '不合法的 openid 列表', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1211', '1', '40030', '不合法的 refresh_token', '不合法的 refresh_token', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1212', '1', '40029', '无效的 oauth_code', '无效的 oauth_code', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1213', '1', '40028', '不合法的自定义菜单使用用户', '不合法的自定义菜单使用用户', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1214', '1', '40027', '不合法的子菜单按钮 URL 长度', '不合法的子菜单按钮 URL 长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1215', '1', '40026', '不合法的子菜单按钮 KEY 长度', '不合法的子菜单按钮 KEY 长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1216', '1', '40025', '不合法的子菜单按钮名字长度', '不合法的子菜单按钮名字长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1217', '1', '40024', '不合法的子菜单按钮类型', '不合法的子菜单按钮类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1218', '1', '40023', '不合法的子菜单按钮个数', '不合法的子菜单按钮个数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1219', '1', '40022', '不合法的子菜单级数', '不合法的子菜单级数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('122', '1', '400055', '积分抵用比例最多两位小数', '积分抵用比例最多两位小数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1220', '1', '40021', '不合法的菜单版本号', '不合法的菜单版本号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1221', '1', '40020', '不合法的按钮 URL 长度', '不合法的按钮 URL 长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1222', '1', '40019', '不合法的按钮 KEY 长度', '不合法的按钮 KEY 长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1223', '1', '40018', '不合法的按钮名字长度', '不合法的按钮名字长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1224', '1', '40017', '不合法的按钮类型', '不合法的按钮类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1225', '1', '40016', '不合法的按钮个数', '不合法的按钮个数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1226', '1', '40015', '不合法的菜单类型', '不合法的菜单类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1227', '1', '40014', '不合法的 access_token ,请开发者认真比对 access_token 的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口', '不合法的 access_token ,请开发者认真比对 access_token 的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1228', '1', '40013', '不合法的 AppID ,请开发者检查 AppID 的正确性,避免异常字符,注意大小写', '不合法的 AppID ,请开发者检查 AppID 的正确性,避免异常字符,注意大小写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1229', '1', '40012', '不合法的缩略图文件大小', '不合法的缩略图文件大小', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('123', '1', '400056', '积分抵用比例必须在0-1000之间', '积分抵用比例必须在0-1000之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1230', '1', '40011', '不合法的视频文件大小', '不合法的视频文件大小', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1231', '1', '40010', '不合法的语音文件大小', '不合法的语音文件大小', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1232', '1', '40009', '不合法的图片文件大小', '不合法的图片文件大小', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1233', '1', '40008', '不合法的消息类型', '不合法的消息类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1234', '1', '40007', '不合法的媒体文件 id', '不合法的媒体文件 id', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1235', '1', '40006', '不合法的文件大小', '不合法的文件大小', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1236', '1', '40005', '不合法的文件类型', '不合法的文件类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1237', '1', '40004', '不合法的媒体文件类型', '不合法的媒体文件类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1238', '1', '40003', '不合法的 OpenID ,请开发者确认 OpenID (该用户)是否已关注公众号,或是否是其他公众号的 OpenID', '不合法的 OpenID ,请开发者确认 OpenID (该用户)是否已关注公众号,或是否是其他公众号的 OpenID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1239', '1', '40002', '不合法的凭证类型', '不合法的凭证类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('124', '1', '400057', '积分抵用上限必须为数字', '积分抵用上限必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1240', '1', '40001', '获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口', '获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1241', '1', '200011', '此账号已被封禁,无法操作', '此账号已被封禁,无法操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1242', '1', '200012', '个人模版数已达上限,上限25个', '个人模版数已达上限,上限25个', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('1243', '1', '200014', '请检查小程序所属类目', '请检查小程序所属类目', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('12431', '1', '选择地址', '选择地址', '选择地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12432', '1', '选择其它地址', '选择其它地址', '选择其它地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12433', '1', '已选商品', '已选商品', '已选商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12434', '1', '清空', '清空', '清空', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12435', '1', '¥', '¥', '¥', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12436', '1', '已售罄', '已售罄', '已售罄', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12437', '1', '已下架', '已下架', '已下架', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12438', '1', '删除', '删除', '删除', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12439', '1', '商品券', '商品券', '商品券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12440', '1', '品类券', '品类券', '品类券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12441', '1', '通用券', '通用券', '通用券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12442', '1', '优惠券', '优惠券', '优惠券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12443', '1', '满', '满', '满', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12444', '1', '元可用', '元可用', '元可用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12445', '1', '无门槛券', '无门槛券', '无门槛券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12446', '1', '领取后', '领取后', '领取后', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12447', '1', '天内可用', '天内可用', '天内可用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12448', '1', '已领取', '已领取', '已领取', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12449', '1', '立即领取', '立即领取', '立即领取', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12450', '1', '购物满', '购物满', '购物满', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12451', '1', '减', '减', '减', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12452', '1', '不限时', '不限时', '不限时', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12453', '1', '秒杀', '秒杀', '秒杀', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12454', '1', '砍价', '砍价', '砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12455', '1', '拼团', '拼团', '拼团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12456', '1', '已售', '已售', '已售', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12457', '1', '立即购买', '立即购买', '立即购买', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12458', '1', '加入购物车', '加入购物车', '加入购物车', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12459', '1', '选规格', '选规格', '选规格', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12460', '1', '跳过', '跳过', '跳过', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12461', '1', '立即体验', '立即体验', '立即体验', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12462', '1', '首页', '首页', '首页', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12463', '1', '搜索', '搜索', '搜索', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12464', '1', '购物车', '购物车', '购物车', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12465', '1', '我的收藏', '我的收藏', '我的收藏', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12466', '1', '个人中心', '个人中心', '个人中心', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12467', '1', '券', '券', '券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12468', '1', '正在加载中', '正在加载中', '正在加载中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12469', '1', '上拉加载更多', '上拉加载更多', '上拉加载更多', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12470', '1', '代付金额', '代付金额', '代付金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12471', '1', '共', '共', '共', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12472', '1', '件商品', '件商品', '件商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12473', '1', '订单包裹', '订单包裹', '订单包裹', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12474', '1', '申请退款中', '申请退款中', '申请退款中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12475', '1', '已退款', '已退款', '已退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12476', '1', '已完成', '已完成', '已完成', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12477', '1', '件退款中', '件退款中', '件退款中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12478', '1', '不支持配送', '不支持配送', '不支持配送', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12479', '1', '不支持自提', '不支持自提', '不支持自提', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12480', '1', '已评价', '已评价', '已评价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12481', '1', '评价', '评价', '评价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12482', '1', '申请退款', '申请退款', '申请退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12483', '1', '查看物流', '查看物流', '查看物流', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12484', '1', '确认收货', '确认收货', '确认收货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12485', '1', '选择付款方式', '选择付款方式', '选择付款方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12486', '1', '支付', '支付', '支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12487', '1', '去付款', '去付款', '去付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12488', '1', '请选择要支付的订单', '请选择要支付的订单', '请选择要支付的订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12489', '1', '余额不足', '余额不足', '余额不足', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12490', '1', '支付中', '支付中', '支付中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12491', '1', '缺少支付参数', '缺少支付参数', '缺少支付参数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12492', '1', '取消支付', '取消支付', '取消支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12493', '1', '支付成功', '支付成功', '支付成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12494', '1', '支付失败', '支付失败', '支付失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12495', '1', '库存', '库存', '库存', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12496', '1', '限量', '限量', '限量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12497', '1', '数量', '数量', '数量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12498', '1', '我要参团', '我要参团', '我要参团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12499', '1', '确定', '确定', '确定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('125', '1', '400058', '积分抵用上限必须大于等于0', '积分抵用上限必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('12500', '1', '热门推荐', '热门推荐', '热门推荐', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12501', '1', '最高返佣', '最高返佣', '最高返佣', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12502', '1', '推广享佣金', '推广享佣金', '推广享佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12503', '1', '立即分享', '立即分享', '立即分享', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12504', '1', '发现新版本', '发现新版本', '发现新版本', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12505', '1', '立即升级', '立即升级', '立即升级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12506', '1', '下载进度', '下载进度', '下载进度', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12507', '1', '店小二', '店小二', '店小二', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12508', '1', '暂无记录', '暂无记录', '暂无记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12509', '1', '正在下载海报,请稍后再试', '正在下载海报,请稍后再试', '正在下载海报,请稍后再试', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12510', '1', '海报二维码生成失败', '海报二维码生成失败', '海报二维码生成失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12511', '1', '倒计时', '倒计时', '倒计时', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12512', '1', '天', '天', '天', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12513', '1', '时', '时', '时', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12514', '1', '分', '分', '分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12515', '1', '秒', '秒', '秒', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12516', '1', '砍价成功', '砍价成功', '砍价成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12517', '1', '活动已结束', '活动已结束', '活动已结束', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12518', '1', '已砍至', '已砍至', '已砍至', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12519', '1', '活动进行中', '活动进行中', '活动进行中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12520', '1', '取消活动', '取消活动', '取消活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12521', '1', '继续砍价', '继续砍价', '继续砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12522', '1', '暂无砍价记录', '暂无砍价记录', '暂无砍价记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12523', '1', '人正在参与', '人正在参与', '人正在参与', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12524', '1', '最低', '最低', '最低', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12525', '1', '参与砍价', '参与砍价', '参与砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12526', '1', '砍价列表', '砍价列表', '砍价列表', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12527', '1', '人查看', '人查看', '人查看', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12528', '1', '人分享', '人分享', '人分享', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12529', '1', '人参与', '人参与', '人参与', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12530', '1', '邀请您帮忙砍价', '邀请您帮忙砍价', '邀请您帮忙砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12531', '1', '查看商品', '查看商品', '查看商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12532', '1', '当前', '当前', '当前', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12533', '1', '已砍', '已砍', '已砍', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12534', '1', '还剩', '还剩', '还剩', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12535', '1', '立即参与砍价', '立即参与砍价', '立即参与砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12536', '1', '商品暂无库存', '商品暂无库存', '商品暂无库存', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12537', '1', '邀请好友帮砍价', '邀请好友帮砍价', '邀请好友帮砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12538', '1', '已有', '已有', '已有', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12539', '1', '位好友成功砍价', '位好友成功砍价', '位好友成功砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12540', '1', '帮好友砍一刀', '帮好友砍一刀', '帮好友砍一刀', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12541', '1', '好友已砍价成功', '好友已砍价成功', '好友已砍价成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12542', '1', '我也要参与', '我也要参与', '我也要参与', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12543', '1', '已成功帮助好友砍价', '已成功帮助好友砍价', '已成功帮助好友砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12544', '1', '恭喜您砍价成功,快去支付', '恭喜您砍价成功,快去支付', '恭喜您砍价成功,快去支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12545', '1', '立即支付', '立即支付', '立即支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12546', '1', '抢更多商品', '抢更多商品', '抢更多商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12547', '1', '砍价帮', '砍价帮', '砍价帮', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12548', '1', '砍掉', '砍掉', '砍掉', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12549', '1', '更多', '更多', '更多', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12550', '1', '关闭', '关闭', '关闭', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12551', '1', '点击加载更多', '点击加载更多', '点击加载更多', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12552', '1', '商品详情', '商品详情', '商品详情', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12553', '1', '砍价规则', '砍价规则', '砍价规则', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12554', '1', '您已砍掉', '您已砍掉', '您已砍掉', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12555', '1', '元,听说分享次数越多砍价成功的机会越大哦', '元,听说分享次数越多砍价成功的机会越大哦', '元,听说分享次数越多砍价成功的机会越大哦', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12556', '1', '成功帮砍', '成功帮砍', '成功帮砍', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12557', '1', '您也可以砍价低价拿哦,快去挑选心仪的商品吧', '您也可以砍价低价拿哦,快去挑选心仪的商品吧', '您也可以砍价低价拿哦,快去挑选心仪的商品吧', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12558', '1', '发送给朋友', '发送给朋友', '发送给朋友', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12559', '1', '微信好友', '微信好友', '微信好友', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12560', '1', '微信朋友圈', '微信朋友圈', '微信朋友圈', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12561', '1', '生成海报', '生成海报', '生成海报', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12562', '1', '砍价详情', '砍价详情', '砍价详情', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12563', '1', '分享成功', '分享成功', '分享成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12564', '1', '分享失败', '分享失败', '分享失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12565', '1', '该商品每人限购', '该商品每人限购', '该商品每人限购', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12566', '1', '您的好友', '您的好友', '您的好友', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12567', '1', '邀请您砍价', '邀请您砍价', '邀请您砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12568', '1', '人团', '人团', '人团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12569', '1', '去拼团', '去拼团', '去拼团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12570', '1', '拼团列表', '拼团列表', '拼团列表', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12571', '1', '类型', '类型', '类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12572', '1', '累计销量', '累计销量', '累计销量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12573', '1', '限购', '限购', '限购', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12574', '1', '种规格可选', '种规格可选', '种规格可选', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12575', '1', '已拼', '已拼', '已拼', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12576', '1', '件', '件', '件', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12577', '1', '还差', '还差', '还差', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12578', '1', '人成团', '人成团', '人成团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12579', '1', '去拼单', '去拼单', '去拼单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12580', '1', '查看更多', '查看更多', '查看更多', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12581', '1', '收起', '收起', '收起', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12582', '1', '拼团玩法', '拼团玩法', '拼团玩法', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12583', '1', '开团/参团', '开团/参团', '开团/参团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12584', '1', '邀请好友', '邀请好友', '邀请好友', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12585', '1', '满员发货', '满员发货', '满员发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12586', '1', '用户评价', '用户评价', '用户评价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12587', '1', '好评率', '好评率', '好评率', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12588', '1', '产品介绍', '产品介绍', '产品介绍', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12589', '1', '单独购买', '单独购买', '单独购买', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12590', '1', '立即开团', '立即开团', '立即开团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12591', '1', '请选择', '请选择', '请选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12592', '1', '商品', '商品', '商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12593', '1', '详情', '详情', '详情', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12594', '1', '缺少参数无法查看商品', '缺少参数无法查看商品', '缺少参数无法查看商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12595', '1', '参数错误', '参数错误', '参数错误', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12596', '1', '已选择', '已选择', '已选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12597', '1', '保存成功', '保存成功', '保存成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12598', '1', '保存失败', '保存失败', '保存失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12599', '1', '人拼', '人拼', '人拼', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('126', '1', '400059', '下单赠送积分必须为数字', '下单赠送积分必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('12600', '1', '剩余', '剩余', '剩余', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12601', '1', '结束', '结束', '结束', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12602', '1', '恭喜您拼团成功', '恭喜您拼团成功', '恭喜您拼团成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12603', '1', '人,拼团失败', '人,拼团失败', '人,拼团失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12604', '1', '拼团中,还差', '拼团中,还差', '拼团中,还差', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12605', '1', '人拼团成功', '人拼团成功', '人拼团成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12606', '1', '邀请好友参团', '邀请好友参团', '邀请好友参团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12607', '1', '再次开团', '再次开团', '再次开团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12608', '1', '取消开团', '取消开团', '取消开团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12609', '1', '查看订单信息', '查看订单信息', '查看订单信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12610', '1', '大家都在拼', '大家都在拼', '大家都在拼', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12611', '1', '更多拼团', '更多拼团', '更多拼团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12612', '1', '邀请您参团', '邀请您参团', '邀请您参团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12613', '1', '你不是该团的成员', '你不是该团的成员', '你不是该团的成员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12614', '1', '已抢', '已抢', '已抢', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12615', '1', '抢购中', '抢购中', '抢购中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12616', '1', '未开始', '未开始', '未开始', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12617', '1', '已结束', '已结束', '已结束', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12618', '1', '暂无商品,去看点别的吧', '暂无商品,去看点别的吧', '暂无商品,去看点别的吧', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12619', '1', '即将开始', '即将开始', '即将开始', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12620', '1', '距秒杀结束仅剩', '距秒杀结束仅剩', '距秒杀结束仅剩', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12621', '1', '累计销售', '累计销售', '累计销售', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12622', '1', '收藏', '收藏', '收藏', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12623', '1', '保存到手机', '保存到手机', '保存到手机', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12624', '1', '长按图片可以保存到手机', '长按图片可以保存到手机', '长按图片可以保存到手机', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12625', '1', '抢购详情页', '抢购详情页', '抢购详情页', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12626', '1', '二维码获取失败', '二维码获取失败', '二维码获取失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12627', '1', '请选择属性', '请选择属性', '请选择属性', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12628', '1', '提示:点击图片即可保存至手机相册', '提示:点击图片即可保存至手机相册', '提示:点击图片即可保存至手机相册', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12629', '1', '拼团海报', '拼团海报', '拼团海报', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12630', '1', '砍价海报', '砍价海报', '砍价海报', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12631', '1', '海报生成中', '海报生成中', '海报生成中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12632', '1', '海报图片获取失败', '海报图片获取失败', '海报图片获取失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12633', '1', '海报', '海报', '海报', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12634', '1', '已预定', '已预定', '已预定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12635', '1', '预售价', '预售价', '预售价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12636', '1', '立即预定', '立即预定', '立即预定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12637', '1', '开售时间', '开售时间', '开售时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12638', '1', '预售活动', '预售活动', '预售活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12639', '1', '起', '起', '起', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12640', '1', '划线价', '划线价', '划线价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12641', '1', '开通“超级会员”立省', '开通“超级会员”立省', '开通“超级会员”立省', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12642', '1', '元', '元', '元', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12643', '1', '立即开通', '立即开通', '立即开通', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12644', '1', '预售活动时间', '预售活动时间', '预售活动时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12645', '1', '预售结束后', '预售结束后', '预售结束后', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12646', '1', '天内发货', '天内发货', '天内发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12647', '1', '活动', '活动', '活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12648', '1', '参与秒杀', '参与秒杀', '参与秒杀', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12649', '1', '参与拼团', '参与拼团', '参与拼团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12650', '1', '复制口令', '复制口令', '复制口令', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12651', '1', '复制成功', '复制成功', '复制成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12652', '1', '推荐', '推荐', '推荐', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12653', '1', '缺少经纬度信息无法查看地图', '缺少经纬度信息无法查看地图', '缺少经纬度信息无法查看地图', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12654', '1', '产品库存不足,请选择其它属性', '产品库存不足,请选择其它属性', '产品库存不足,请选择其它属性', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12655', '1', '立即退款', '立即退款', '立即退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12656', '1', '一键改价', '一键改价', '一键改价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12657', '1', '订单备注', '订单备注', '订单备注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12658', '1', '商品总价', '商品总价', '商品总价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12659', '1', '原始邮费', '原始邮费', '原始邮费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12660', '1', '实际支付', '实际支付', '实际支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12661', '1', '退款金额', '退款金额', '退款金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12662', '1', '请填写备注信息', '请填写备注信息', '请填写备注信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12663', '1', '立即修改', '立即修改', '立即修改', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12664', '1', '确认退款', '确认退款', '确认退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12665', '1', '拒绝退款', '拒绝退款', '拒绝退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12666', '1', '取消', '取消', '取消', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12667', '1', '订单号', '订单号', '订单号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12668', '1', '发货方式', '发货方式', '发货方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12669', '1', '发货类型', '发货类型', '发货类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12670', '1', '快递公司', '快递公司', '快递公司', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12671', '1', '快递单号', '快递单号', '快递单号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12672', '1', '顺丰请输入单号 :收件人或寄件人手机号后四位', '顺丰请输入单号 :收件人或寄件人手机号后四位', '顺丰请输入单号 :收件人或寄件人手机号后四位', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12673', '1', '例如:SF000000000000:3941', '例如:SF000000000000:3941', '例如:SF000000000000:3941', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12674', '1', '电子面单', '电子面单', '电子面单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12675', '1', '预览', '预览', '预览', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12676', '1', '寄件人姓名', '寄件人姓名', '寄件人姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12677', '1', '填写寄件人姓名', '填写寄件人姓名', '填写寄件人姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12678', '1', '寄件人电话', '寄件人电话', '寄件人电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12679', '1', '填写寄件人电话', '填写寄件人电话', '填写寄件人电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12680', '1', '寄件人地址', '寄件人地址', '寄件人地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12681', '1', '填写寄件人地址', '填写寄件人地址', '填写寄件人地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12682', '1', '送货人', '送货人', '送货人', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12683', '1', '确认提交', '确认提交', '确认提交', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12684', '1', '发货', '发货', '发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12685', '1', '送货', '送货', '送货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12686', '1', '无需物流', '无需物流', '无需物流', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12687', '1', '手动填写', '手动填写', '手动填写', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12688', '1', '电子面单打印', '电子面单打印', '电子面单打印', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12689', '1', '填写快递单号', '填写快递单号', '填写快递单号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12690', '1', '请选择电子面单', '请选择电子面单', '请选择电子面单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12691', '1', '待付款', '待付款', '待付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12692', '1', '待发货', '待发货', '待发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12693', '1', '待收货', '待收货', '待收货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12694', '1', '待评价', '待评价', '待评价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12695', '1', '售后/退款', '售后/退款', '退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12696', '1', '数据统计', '数据统计', '数据统计', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12697', '1', '今日成交额', '今日成交额', '今日成交额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12698', '1', '昨日成交额', '昨日成交额', '昨日成交额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12699', '1', '本月成交额', '本月成交额', '本月成交额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('127', '1', '400060', '下单赠送积分必须在0-1000之间', '下单赠送积分必须在0-1000之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('12700', '1', '今日订单数', '今日订单数', '今日订单数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12701', '1', '昨日订单数', '昨日订单数', '昨日订单数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12702', '1', '本月订单数', '本月订单数', '本月订单数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12703', '1', '详细数据', '详细数据', '详细数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12704', '1', '日期', '日期', '日期', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12705', '1', '订单数', '订单数', '订单数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12706', '1', '成交额', '成交额', '成交额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12707', '1', '立即核销', '立即核销', '立即核销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12708', '1', '查看', '查看', '查看', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12709', '1', '确定要核销此订单吗', '确定要核销此订单吗', '确定要核销此订单吗', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12710', '1', '确定核销', '确定核销', '确定核销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12711', '1', '请输入核销码', '请输入核销码', '请输入核销码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12712', '1', '请输入正确的核销码', '请输入正确的核销码', '请输入正确的核销码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12713', '1', '查询中', '查询中', '查询中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12714', '1', '订单', '订单', '订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12715', '1', '订单未备注,点击添加备注信息', '订单未备注,点击添加备注信息', '订单未备注,点击添加备注信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12716', '1', '复制', '复制', '复制', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12717', '1', '件商品,应支付', '件商品,应支付', '件商品,应支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12718', '1', '邮费', '邮费', '邮费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12719', '1', '订单编号', '订单编号', '订单编号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12720', '1', '下单时间', '下单时间', '下单时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12721', '1', '支付状态', '支付状态', '支付状态', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12722', '1', '已支付', '已支付', '已支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12723', '1', '未支付', '未支付', '未支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12724', '1', '支付方式', '支付方式', '支付方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12725', '1', '买家留言', '买家留言', '买家留言', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12726', '1', '支付金额', '支付金额', '支付金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12727', '1', '优惠券抵扣', '优惠券抵扣', '优惠券抵扣', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12728', '1', '运费', '运费', '运费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12729', '1', '实付款', '实付款', '实付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12730', '1', '配送方式', '配送方式', '配送方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12731', '1', '快递', '快递', '快递', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12732', '1', '送货人电话', '送货人电话', '送货人电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12733', '1', '确认付款', '确认付款', '确认付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12734', '1', '去发货', '去发货', '去发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12735', '1', '改价成功', '改价成功', '改价成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12736', '1', '改价失败', '改价失败', '改价失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12737', '1', '请输入备注', '请输入备注', '请输入备注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12738', '1', '退款中', '退款中', '退款中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12739', '1', '部分退款中', '部分退款中', '部分退款中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12740', '1', '件商品,实付款', '件商品,实付款', '件商品,实付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12741', '1', '同意退货', '同意退货', '同意退货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12742', '1', '待用户发货', '待用户发货', '待用户发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12743', '1', '请输入正确的金额', '请输入正确的金额', '请输入正确的金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12744', '1', '今天', '今天', '今天', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12745', '1', '昨天', '昨天', '昨天', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12746', '1', '最近7天', '最近7天', '最近7天', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12747', '1', '本月', '本月', '本月', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12748', '1', '自定义', '自定义', '自定义', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12749', '1', '营业额(元)', '营业额(元)', '营业额(元)', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12750', '1', '订单量(份)', '订单量(份)', '订单量(份)', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12751', '1', '增长率', '增长率', '增长率', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12752', '1', '增长', '增长', '增长', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12753', '1', '单位', '单位', '单位', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12754', '1', '元.', '元.', '元', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12755', '1', '分.', '分.', '分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12756', '1', '固定', '固定', '固定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12757', '1', '指定范围', '指定范围', '指定范围', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12758', '1', '提交时间', '提交时间', '提交时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12759', '1', '原因', '原因', '原因', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12760', '1', '暂无申请记录,快去申请吧!', '暂无申请记录,快去申请吧!', '暂无申请记录,快去申请吧!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12761', '1', '没有更多啦', '没有更多啦', '没有更多啦', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12762', '1', '待审核', '待审核', '待审核', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12763', '1', '审核通过', '审核通过', '审核通过', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12764', '1', '审核未通过', '审核未通过', '审核未通过', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12765', '1', '编辑', '编辑', '编辑', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12766', '1', '重新提交', '重新提交', '重新提交', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12767', '1', '会员优惠价', '会员优惠价', '会员优惠价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12768', '1', '余额支付', '余额支付', '余额支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12769', '1', '可用余额', '可用余额', '可用余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12770', '1', '微信支付', '微信支付', '微信支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12771', '1', '确认', '确认', '确认', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12772', '1', '支付提醒', '支付提醒', '支付提醒', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12773', '1', '线下支付已关闭,请点击确认按钮返回主页', '线下支付已关闭,请点击确认按钮返回主页', '线下支付已关闭,请点击确认按钮返回主页', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12774', '1', '请输入支付金额', '请输入支付金额', '请输入支付金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12775', '1', '正在确认', '正在确认', '正在确认', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12776', '1', '进入商城', '进入商城', '进入商城', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12777', '1', '代理商名称', '代理商名称', '代理商名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12778', '1', '请输入代理商名称', '请输入代理商名称', '请输入代理商名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12779', '1', '用户姓名', '用户姓名', '用户姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12780', '1', '请输入姓名', '请输入姓名', '请输入姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12781', '1', '联系电话', '联系电话', '联系电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12782', '1', '请输入手机号', '请输入手机号', '请输入手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12783', '1', '验证码', '验证码', '验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12784', '1', '填写验证码', '填写验证码', '填写验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12785', '1', '邀请码', '邀请码', '邀请码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12786', '1', '请输入代理商邀请码', '请输入代理商邀请码', '请输入代理商邀请码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12787', '1', '请上传营业执照及行业相关资质证明图片', '请上传营业执照及行业相关资质证明图片', '请上传营业执照及行业相关资质证明图片', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12788', '1', '图片最多可上传10张,图片格式支持JPG、PNG、JPEG', '图片最多可上传10张,图片格式支持JPG、PNG、JPEG', '图片最多可上传10张,图片格式支持JPG、PNG、JPEG', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12789', '1', '上传图片', '上传图片', '上传图片', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12790', '1', '已阅读并同意', '已阅读并同意', '已阅读并同意', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12791', '1', '代理商协议', '代理商协议', '代理商协议', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12792', '1', '提交申请', '提交申请', '提交申请', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12793', '1', '代理商入驻协议', '代理商入驻协议', '代理商入驻协议', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12794', '1', '恭喜,您的资料提交成功!', '恭喜,您的资料提交成功!', '恭喜,您的资料提交成功!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12795', '1', '返回首页', '返回首页', '返回首页', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12796', '1', '恭喜,您的资料通过审核!', '恭喜,您的资料通过审核!', '恭喜,您的资料通过审核!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12797', '1', '您的申请未通过!', '您的申请未通过!', '您的申请未通过!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12798', '1', '重新申请', '重新申请', '重新申请', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12799', '1', '获取验证码', '获取验证码', '获取验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('128', '1', '400061', '普通商品未支付取消订单时间必须为数字', '普通商品未支付取消订单时间必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('12800', '1', '请输入正确的手机号码', '请输入正确的手机号码', '请输入正确的手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12801', '1', '重新获取', '重新获取', '重新获取', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12802', '1', '请上传营业执照', '请上传营业执照', '请上传营业执照', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12803', '1', '请勾选并同意入驻协议', '请勾选并同意入驻协议', '请勾选并同意入驻协议', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12804', '1', '专题栏', '专题栏', '专题栏', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12805', '1', '暂无数据', '暂无数据', '暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12806', '1', '请输入卡号', '请输入卡号', '请输入卡号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12807', '1', '请输入卡密', '请输入卡密', '请输入卡密', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12808', '1', '确认激活', '确认激活', '确认激活', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12809', '1', 'SVIP会员尊享权', 'SVIP会员尊享权', 'SVIP会员尊享权', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12810', '1', '正在激活', '正在激活', '正在激活', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12811', '1', '已使用', '已使用', '已使用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12812', '1', '永久SVIP会员', '永久SVIP会员', '永久SVIP会员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12813', '1', 'SVIP会员', 'SVIP会员', 'SVIP会员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12814', '1', '到期', '到期', '到期', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12815', '1', '您与', '您与', '您与', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12816', '1', '商城的第', '商城的第', '商城的第', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12817', '1', '天.', '天.', '天.', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12818', '1', '已累积为您节省', '已累积为您节省', '已累积为您节省', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12819', '1', '开通即享会员权益', '开通即享会员权益', '开通即享会员权益', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12820', '1', '续费会员', '续费会员', '续费会员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12821', '1', '开通会员', '开通会员', '开通会员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12822', '1', '有效期至', '有效期至', '有效期至', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12823', '1', '试用', '试用', '试用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12824', '1', '购买即视为同意', '购买即视为同意', '购买即视为同意', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12825', '1', '会员用户协议', '会员用户协议', '会员用户协议', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12826', '1', '点击兑换卡密', '点击兑换卡密', '点击兑换卡密', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12827', '1', '会员优惠券', '会员优惠券', '会员优惠券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12828', '1', 'SVIP商品推荐', 'SVIP商品推荐', 'SVIP商品推荐', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12829', '1', '商城价', '商城价', '商城价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12830', '1', '激活会员卡', '激活会员卡', '激活会员卡', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12831', '1', '支付宝支付', '支付宝支付', '支付宝支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12832', '1', '成功开启0元试用', '成功开启0元试用', '成功开启0元试用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12833', '1', '确认绑定', '确认绑定', '确认绑定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12834', '1', '绑定成功', '绑定成功', '绑定成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12835', '1', '商城客服已离线', '商城客服已离线', '商城客服已离线', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12836', '1', '我要反馈', '我要反馈', '我要反馈', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12837', '1', '请填写内容', '请填写内容', '请填写内容', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12838', '1', '提交', '提交', '提交', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12839', '1', '精品推荐', '精品推荐', '精品推荐', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12840', '1', '热门榜单', '热门榜单', '热门榜单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12841', '1', '首发新品', '首发新品', '首发新品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12842', '1', '促销单品', '促销单品', '促销单品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12843', '1', '预告', '预告', '预告', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12844', '1', '回放', '回放', '回放', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12845', '1', '进行中', '进行中', '进行中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12846', '1', '发送客服', '发送客服', '发送客服', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12847', '1', '客服连接中', '客服连接中', '客服连接中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12848', '1', '连接失败', '连接失败', '连接失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12849', '1', '提示', '提示', '提示', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12850', '1', '客服已下线,是否需要反馈?', '客服已下线,是否需要反馈?', '客服已下线,是否需要反馈?', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12851', '1', '和好友一起分享', '和好友一起分享', '和好友一起分享', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12852', '1', '积分抵扣', '积分抵扣', '积分抵扣', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12853', '1', '已开票', '已开票', '已开票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12854', '1', '未开票', '未开票', '未开票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12855', '1', '发票信息', '发票信息', '发票信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12856', '1', '发票抬头', '发票抬头', '发票抬头', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12857', '1', '发票抬头类型', '发票抬头类型', '发票抬头类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12858', '1', '个人', '个人', '个人', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12859', '1', '企业', '企业', '企业', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12860', '1', '发票类型', '发票类型', '发票类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12861', '1', '电子普通发票', '电子普通发票', '电子普通发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12862', '1', '电子专用发票', '电子专用发票', '电子专用发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12863', '1', '企业税号', '企业税号', '企业税号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12864', '1', '联系信息', '联系信息', '联系信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12865', '1', '真实姓名', '真实姓名', '真实姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12866', '1', '联系邮箱', '联系邮箱', '联系邮箱', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12867', '1', '抬头选择', '抬头选择', '抬头选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12868', '1', '默认', '默认', '默认', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12869', '1', '普通', '普通', '普通', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12870', '1', '专用', '专用', '专用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12871', '1', '您还没有添加发票信息哟', '您还没有添加发票信息哟', '您还没有添加发票信息哟', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12872', '1', '添加新的抬头', '添加新的抬头', '添加新的抬头', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12873', '1', '不开发票', '不开发票', '不开发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12874', '1', '抽奖', '抽奖', '抽奖', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12875', '1', '全选', '全选', '全选', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12876', '1', '属性', '属性', '属性', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12877', '1', '请填写具体地址', '请填写具体地址', '请填写具体地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12878', '1', '省', '省', '省', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12879', '1', '市', '市', '市', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12880', '1', '区', '区', '区', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12881', '1', '添加成功', '添加成功', '添加成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12882', '1', '您已拒绝导入微信地址权限', '您已拒绝导入微信地址权限', '您已拒绝导入微信地址权限', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12883', '1', '是否进入权限管理,调整授权?', '是否进入权限管理,调整授权?', '是否进入权限管理,调整授权?', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12884', '1', '已取消', '已取消', '已取消', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12885', '1', '添加失败', '添加失败', '添加失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12886', '1', '请填写收货人姓名', '请填写收货人姓名', '请填写收货人姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12887', '1', '请选择所在地区', '请选择所在地区', '请选择所在地区', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12888', '1', '请填写详细地址', '请填写详细地址', '请填写详细地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12889', '1', '星', '星', '星', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12890', '1', '商品满足你的期待么?说说你的想法,分享给想买的他们吧', '商品满足你的期待么?说说你的想法,分享给想买的他们吧', '商品满足你的期待么?说说你的想法,分享给想买的他们吧', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12891', '1', '立即评价', '立即评价', '立即评价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12892', '1', '商品质量', '商品质量', '商品质量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12893', '1', '服务态度', '服务态度', '服务态度', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12894', '1', '缺少参数', '缺少参数', '缺少参数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12895', '1', '请填写你对宝贝的心得', '请填写你对宝贝的心得', '请填写你对宝贝的心得', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12896', '1', '正在发布评论', '正在发布评论', '正在发布评论', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12897', '1', '感谢您的评价', '感谢您的评价', '感谢您的评价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12898', '1', '评价完成', '评价完成', '评价完成', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12899', '1', '恭喜您', '恭喜您', '恭喜您', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('129', '1', '400062', '活动商品未支付取消订单时间必须为数字', '活动商品未支付取消订单时间必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('12900', '1', '获得', '获得', '获得', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12901', '1', '机会', '机会', '机会', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12902', '1', '领取成功', '领取成功', '领取成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12903', '1', '评分', '评分', '评分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12904', '1', '全部', '全部', '全部', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12905', '1', '好评', '好评', '好评', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12906', '1', '中评', '中评', '中评', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12907', '1', '差评', '差评', '差评', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12908', '1', '加载更多', '加载更多', '加载更多', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12909', '1', '千米距离', '千米距离', '千米距离', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12910', '1', '搜索商品名称', '搜索商品名称', '搜索商品名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12911', '1', '价格', '价格', '价格', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12912', '1', '销量', '销量', '销量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12913', '1', '新品', '新品', '新品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12914', '1', '已全部加载', '已全部加载', '已全部加载', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12915', '1', '缺少订单号', '缺少订单号', '缺少订单号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12916', '1', '退货件数', '退货件数', '退货件数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12917', '1', '退款类型', '退款类型', '退款类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12918', '1', '退款原因', '退款原因', '退款原因', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12919', '1', '备注说明', '备注说明', '备注说明', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12920', '1', '填写备注信息,100字以内', '填写备注信息,100字以内', '填写备注信息,100字以内', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12921', '1', '仅退款', '仅退款', '仅退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12922', '1', '退货并退款', '退货并退款', '退货并退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12923', '1', '申请成功', '申请成功', '申请成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12924', '1', '请先选择退货商品', '请先选择退货商品', '请先选择退货商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12925', '1', '搜索历史', '搜索历史', '搜索历史', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12926', '1', '热门搜索', '热门搜索', '热门搜索', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12927', '1', '请输入要搜索的商品', '请输入要搜索的商品', '请输入要搜索的商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12928', '1', '正在搜索中', '正在搜索中', '正在搜索中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12929', '1', '中奖记录', '中奖记录', '中奖记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12930', '1', '我的奖品', '我的奖品', '我的奖品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12931', '1', '活动规则', '活动规则', '活动规则', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12932', '1', '昵称', '昵称', '昵称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12933', '1', '序号', '序号', '序号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12934', '1', '奖品名称', '奖品名称', '奖品名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12935', '1', '获奖时间', '获奖时间', '获奖时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12936', '1', '商家暂未上架活动哦', '商家暂未上架活动哦', '商家暂未上架活动哦', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12937', '1', '获取抽奖信息', '获取抽奖信息', '获取抽奖信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12938', '1', '奖品类型', '奖品类型', '奖品类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12939', '1', '立即兑换', '立即兑换', '立即兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12940', '1', '兑换时间', '兑换时间', '兑换时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12941', '1', '暂无中奖记录', '暂无中奖记录', '暂无中奖记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12942', '1', '积分', '积分', '积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12943', '1', '余额', '余额', '余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12944', '1', '红包', '红包', '红包', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12945', '1', '设置收货地址', '设置收货地址', '设置收货地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12946', '1', '暂无门店信息', '暂无门店信息', '暂无门店信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12947', '1', '剩余积分', '剩余积分', '剩余积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12948', '1', '当前积分', '当前积分', '当前积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12949', '1', '开具发票', '开具发票', '开具发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12950', '1', '请填写', '请填写', '请填写', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12951', '1', '配送运费', '配送运费', '配送运费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12952', '1', '会员商品优惠', '会员商品优惠', '会员商品优惠', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12953', '1', '会员运费优惠', '会员运费优惠', '会员运费优惠', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12954', '1', '合计', '合计', '合计', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12955', '1', '使用微信快捷支付', '使用微信快捷支付', '使用微信快捷支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12956', '1', '使用支付宝支付', '使用支付宝支付', '使用支付宝支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12957', '1', '线下支付', '线下支付', '线下支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12958', '1', '使用线下付款', '使用线下付款', '使用线下付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12959', '1', '好友代付', '好友代付', '好友代付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12960', '1', '找微信好友支付', '找微信好友支付', '找微信好友支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12961', '1', '立即使用', '立即使用', '立即使用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12962', '1', '请选择要购买的商品', '请选择要购买的商品', '请选择要购买的商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12963', '1', '发票', '发票', '发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12964', '1', '不使用', '不使用', '不使用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12965', '1', '订单创建成功', '订单创建成功', '订单创建成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12966', '1', '请选择支付方式', '请选择支付方式', '请选择支付方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12967', '1', '请选择收货地址', '请选择收货地址', '请选择收货地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12968', '1', '请填写联系人或联系人电话', '请填写联系人或联系人电话', '请填写联系人或联系人电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12969', '1', '暂无门店,请选择其他方式', '暂无门店,请选择其他方式', '暂无门店,请选择其他方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12970', '1', '请输入', '请输入', '请输入', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12971', '1', '请输入正确的', '请输入正确的', '请输入正确的', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12972', '1', '请上传', '请上传', '请上传', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12973', '1', '订单支付中', '订单支付中', '订单支付中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12974', '1', '请按以上退货信息将商品退回', '请按以上退货信息将商品退回', '请按以上退货信息将商品退回', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12975', '1', '请联系管理员获取退货地址', '请联系管理员获取退货地址', '请联系管理员获取退货地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12976', '1', '待核销', '待核销', '待核销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12977', '1', '核销信息', '核销信息', '核销信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12978', '1', '营业时间', '营业时间', '营业时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12979', '1', '每日', '每日', '每日', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12980', '1', '使用说明', '使用说明', '使用说明', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12981', '1', '可将二维码出示给店员扫描或提供数字核销码', '可将二维码出示给店员扫描或提供数字核销码', '可将二维码出示给店员扫描或提供数字核销码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12982', '1', '可将二维码出示给配送员进行核销', '可将二维码出示给配送员进行核销', '可将二维码出示给配送员进行核销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12983', '1', '查看位置', '查看位置', '查看位置', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12984', '1', '拒绝原因', '拒绝原因', '拒绝原因', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12985', '1', '联系客服', '联系客服', '联系客服', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12986', '1', '商家备注', '商家备注', '商家备注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12987', '1', '收货人', '收货人', '收货人', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12988', '1', '收货地址', '收货地址', '收货地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12989', '1', '配送人姓名', '配送人姓名', '配送人姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12990', '1', '拨打', '拨打', '拨打', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12991', '1', '虚拟发货', '虚拟发货', '虚拟发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12992', '1', '已发货,请注意查收', '已发货,请注意查收', '已发货,请注意查收', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12993', '1', '虚拟备注', '虚拟备注', '虚拟备注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12994', '1', '总代付', '总代付', '总代付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12995', '1', '申请开票', '申请开票', '申请开票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12996', '1', '查看发票', '查看发票', '查看发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12997', '1', '取消订单', '取消订单', '取消订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12998', '1', '立即付款', '立即付款', '立即付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('12999', '1', '批量退款', '批量退款', '批量退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13', '1', '100012', '更新成功', '更新成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('130', '1', '400063', '砍价商品未支付取消订单时间必须为数字', '砍价商品未支付取消订单时间必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('13000', '1', '查看拼团', '查看拼团', '查看拼团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13001', '1', '再次购买', '再次购买', '再次购买', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13002', '1', '取消申请', '取消申请', '取消申请', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13003', '1', '填写退货信息', '填写退货信息', '填写退货信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13004', '1', '查看退货物流', '查看退货物流', '查看退货物流', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13005', '1', '您确认放弃此次申请吗', '您确认放弃此次申请吗', '您确认放弃此次申请吗', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13006', '1', '操作成功', '操作成功', '操作成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13007', '1', '订单信息不存在', '订单信息不存在', '订单信息不存在', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13008', '1', '为保障权益,请收到货确认无误后,再确认收货', '为保障权益,请收到货确认无误后,再确认收货', '为保障权益,请收到货确认无误后,再确认收货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13009', '1', '删除订单', '删除订单', '删除订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13010', '1', '确定删除该订单', '确定删除该订单', '确定删除该订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13011', '1', '删除成功', '删除成功', '删除成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13012', '1', '确认取消该订单', '确认取消该订单', '确认取消该订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13013', '1', '订单信息', '订单信息', '订单信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13014', '1', '消费订单', '消费订单', '消费订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13015', '1', '总消费', '总消费', '总消费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13016', '1', '预售', '预售', '预售', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13017', '1', '线下付款,未支付', '线下付款,未支付', '线下付款,未支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13018', '1', '未核销', '未核销', '未核销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13019', '1', '件商品,总金额', '件商品,总金额', '件商品,总金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13020', '1', '查看详情', '查看详情', '查看详情', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13021', '1', '暂无订单', '暂无订单', '暂无订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13022', '1', '缺少订单号无法取消订单', '缺少订单号无法取消订单', '缺少订单号无法取消订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13023', '1', '订单支付成功', '订单支付成功', '订单支付成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13024', '1', '订单支付失败', '订单支付失败', '订单支付失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13025', '1', '暂未支付', '暂未支付', '暂未支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13026', '1', '失败原因', '失败原因', '失败原因', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13027', '1', '重新购买', '重新购买', '重新购买', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13028', '1', '重新支付', '重新支付', '重新支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13029', '1', '赠送优惠券', '赠送优惠券', '赠送优惠券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13030', '1', '有效期', '有效期', '有效期', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13031', '1', '缺少参数无法查看订单支付状态', '缺少参数无法查看订单支付状态', '缺少参数无法查看订单支付状态', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13032', '1', '最多可上传3张', '最多可上传3张', '最多可上传3张', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13033', '1', '请选择产品', '请选择产品', '请选择产品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13034', '1', '该产品没有更多库存了', '该产品没有更多库存了', '该产品没有更多库存了', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13035', '1', '优品推荐', '优品推荐', '优品推荐', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13036', '1', '暂无产品', '暂无产品', '暂无产品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13037', '1', '重新选择', '重新选择', '重新选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13038', '1', '请选择数量', '请选择数量', '请选择数量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13039', '1', '砍价专区·BARGAINING', '砍价专区·BARGAINING', '砍价专区·BARGAINING', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13040', '1', '立即砍价', '立即砍价', '立即砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13041', '1', '拼团活动', '拼团活动', '拼团活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13042', '1', '人拼团成功.', '人拼团成功.', '人拼团成功.', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13043', '1', '人参团', '人参团', '人参团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13044', '1', '拼团价', '拼团价', '拼团价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13045', '1', '已过期', '已过期', '已过期', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13046', '1', '关注', '关注', '关注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13047', '1', '推荐好货', '推荐好货', '推荐好货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13048', '1', '暂无商品', '暂无商品', '暂无商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13049', '1', '限时秒杀', '限时秒杀', '限时秒杀', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13050', '1', '抢', '抢', '抢', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13051', '1', '广告位', '广告位', '广告位', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13052', '1', '精彩内容', '精彩内容', '精彩内容', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13053', '1', '砍价模块,暂无数据', '砍价模块,暂无数据', '砍价模块,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13054', '1', '砍价活动', '砍价活动', '砍价活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13055', '1', '呼朋唤友来砍价', '呼朋唤友来砍价', '呼朋唤友来砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13056', '1', '拼团模块,暂无数据', '拼团模块,暂无数据', '拼团模块,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13057', '1', '享超值开团价', '享超值开团价', '享超值开团价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13058', '1', '优惠券,暂无数据', '优惠券,暂无数据', '优惠券,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13059', '1', '领取今日好券', '领取今日好券', '领取今日好券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13060', '1', '可用', '可用', '可用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13061', '1', '领取', '领取', '领取', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13062', '1', '客服', '客服', '客服', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13063', '1', '商品列表,暂无数据', '商品列表,暂无数据', '商品列表,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13064', '1', '搜索商品', '搜索商品', '搜索商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13065', '1', '暂无图片,请上传图片', '暂无图片,请上传图片', '暂无图片,请上传图片', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13066', '1', '首发新品,暂无数据', '首发新品,暂无数据', '首发新品,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13067', '1', '多个优质商品最新上架', '多个优质商品最新上架', '多个优质商品最新上架', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13068', '1', '暂无新闻,请上传新闻', '暂无新闻,请上传新闻', '暂无新闻,请上传新闻', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13069', '1', '热度 TOP', '热度 TOP', '热度 TOP', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13070', '1', '排行榜、暂无数据', '排行榜、暂无数据', '排行榜、暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13071', '1', '促销单品,暂无数据', '促销单品,暂无数据', '促销单品,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13072', '1', '库存商品优惠促销活动', '库存商品优惠促销活动', '库存商品优惠促销活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13073', '1', '精品推荐,暂无数据', '精品推荐,暂无数据', '精品推荐,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13074', '1', '上百种商品分类任您选择', '上百种商品分类任您选择', '上百种商品分类任您选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13075', '1', '秒杀模块,暂无数据', '秒杀模块,暂无数据', '秒杀模块,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13076', '1', '场', '场', '场', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13077', '1', '暂无数据,请设置', '暂无数据,请设置', '暂无数据,请设置', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13078', '1', '暂无数据,请先添加分类', '暂无数据,请先添加分类', '暂无数据,请先添加分类', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13079', '1', '暂无标题', '暂无标题', '暂无标题', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13080', '1', '诚意推荐品质商品', '诚意推荐品质商品', '诚意推荐品质商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13081', '1', '点击“立即关注”即可关注公众号', '点击“立即关注”即可关注公众号', '点击“立即关注”即可关注公众号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13082', '1', '立即关注', '立即关注', '立即关注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13083', '1', '添加到我的小程序, 微信首页下拉即可访问商城。', '添加到我的小程序, 微信首页下拉即可访问商城。', '添加到我的小程序, 微信首页下拉即可访问商城。', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13084', '1', '点击', '点击', '点击', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13085', '1', '服务协议与隐私政策', '服务协议与隐私政策', '服务协议与隐私政策', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13086', '1', '请务必审慎阅读、充分理解“服务协议与 隐私政策”各条款,包括但不限于:为了 向你提供即时通讯、内容分享等服务,我 们需要收集你的设备信息、操作日志等个 人信息。你可以在“设置”中查看、变更、删除个人信息并管理你的授权。', '请务必审慎阅读、充分理解“服务协议与 隐私政策”各条款,包括但不限于:为了 向你提供即时通讯、内容分享等服务,我 们需要收集你的设备信息、操作日志等个 人信息。你可以在“设置”中查看、变更、删除个人信息并管理你的授权。', '请务必审慎阅读、充分理解“服务协议与 隐私政策”各条款,包括但不限于:为了 向你提供即时通讯、内容分享等服务,我 们需要收集你的设备信息、操作日志等个 人信息。你可以在“设置”中查看、变更、删除个人信息并管理你的授权。', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13087', '1', '你可以阅读', '你可以阅读', '你可以阅读', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13088', '1', '《服务协议与隐私政策》', '《服务协议与隐私政策》', '《服务协议与隐私政策》', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13089', '1', '了解详细信息。如你同意,请点击“我同意”开始接受我们的服务。', '了解详细信息。如你同意,请点击“我同意”开始接受我们的服务。', '了解详细信息。如你同意,请点击“我同意”开始接受我们的服务。', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13090', '1', '我同意', '我同意', '我同意', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13091', '1', '残忍拒绝', '残忍拒绝', '残忍拒绝', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13092', '1', '下拉加载更多', '下拉加载更多', '下拉加载更多', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13093', '1', '网络连接断开', '网络连接断开', '网络连接断开', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13094', '1', '请检查情况:', '请检查情况:', '请检查情况:', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13095', '1', '在设置中是否已开启网络权限', '在设置中是否已开启网络权限', '在设置中是否已开启网络权限', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13096', '1', '当前是否处于弱网环境', '当前是否处于弱网环境', '当前是否处于弱网环境', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13097', '1', '版本是否过低,升级试试吧', '版本是否过低,升级试试吧', '版本是否过低,升级试试吧', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13098', '1', '重新连接', '重新连接', '重新连接', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13099', '1', '加载中', '加载中', '加载中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('131', '1', '400064', '拼团商品未支付取消订单时间必须为数字', '拼团商品未支付取消订单时间必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('13100', '1', '没有更多内容啦~', '没有更多内容啦~', '没有更多内容啦~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13101', '1', '100%正品保证', '100%正品保证', '100%正品保证', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13102', '1', '所有商品精挑细选', '所有商品精挑细选', '所有商品精挑细选', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13103', '1', '售后无忧', '售后无忧', '售后无忧', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13104', '1', '管理', '管理', '管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13105', '1', '购物数量', '购物数量', '购物数量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13106', '1', '请重新选择商品规格', '请重新选择商品规格', '请重新选择商品规格', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13107', '1', '重选', '重选', '重选', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13108', '1', '失效商品', '失效商品', '失效商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13109', '1', '失效', '失效', '失效', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13110', '1', '该商品已失效', '该商品已失效', '该商品已失效', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13111', '1', '立即下单', '立即下单', '立即下单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13112', '1', '产品库存不足,请选择其它', '产品库存不足,请选择其它', '产品库存不足,请选择其它', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13113', '1', '添加购物车成功', '添加购物车成功', '添加购物车成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13114', '1', '清除成功', '清除成功', '清除成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13115', '1', '暂无兑换记录~', '暂无兑换记录~', '暂无兑换记录~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13116', '1', '大家都在换', '大家都在换', '大家都在换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13117', '1', '人兑换', '人兑换', '人兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13118', '1', '轻松赚积分', '轻松赚积分', '轻松赚积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13119', '1', '购买商品', '购买商品', '购买商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13120', '1', '购买商品可获得积分奖励', '购买商品可获得积分奖励', '购买商品可获得积分奖励', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13121', '1', '去完成', '去完成', '去完成', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13122', '1', '每日签到活动', '每日签到活动', '每日签到活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13123', '1', '每日签到可获得积分奖励', '每日签到可获得积分奖励', '每日签到可获得积分奖励', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13124', '1', '九宫格抽奖活动', '九宫格抽奖活动', '九宫格抽奖活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13125', '1', '幸运抽奖可获得积分奖励', '幸运抽奖可获得积分奖励', '幸运抽奖可获得积分奖励', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13126', '1', '我的积分', '我的积分', '我的积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13127', '1', '每日签到', '每日签到', '每日签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13128', '1', '积分抽奖', '积分抽奖', '积分抽奖', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13129', '1', '兑换记录', '兑换记录', '兑换记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13130', '1', '已兑换', '已兑换', '已兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13131', '1', '无法兑换', '无法兑换', '无法兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13132', '1', '[默认]', '[默认]', '[默认]', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13133', '1', '可用积分', '可用积分', '可用积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13134', '1', '快递费用', '快递费用', '快递费用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13135', '1', '免运费', '免运费', '免运费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13136', '1', '备注信息', '备注信息', '备注信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13137', '1', '请添加备注(150字以内)', '请添加备注(150字以内)', '请添加备注(150字以内)', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13138', '1', '使用线上支付宝支付', '使用线上支付宝支付', '使用线上支付宝支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13139', '1', '可用余额:', '可用余额:', '可用余额:', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13140', '1', '选择线下付款方式', '选择线下付款方式', '选择线下付款方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13141', '1', '正在加载…', '正在加载…', '正在加载…', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13142', '1', '可用积分不足!', '可用积分不足!', '可用积分不足!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13143', '1', '订单状态', '订单状态', '订单状态', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13144', '1', '支付积分', '支付积分', '支付积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13145', '1', '备注', '备注', '备注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13146', '1', '配送核销码', '配送核销码', '配送核销码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13147', '1', '当前可用余额:', '当前可用余额:', '当前可用余额:', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13148', '1', '正在加载', '正在加载', '正在加载', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13149', '1', '缺少经纬度信息无法查看地图!', '缺少经纬度信息无法查看地图!', '缺少经纬度信息无法查看地图!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13150', '1', '商品兑换成功', '商品兑换成功', '商品兑换成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13151', '1', '兑换方式', '兑换方式', '兑换方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13152', '1', '积分兑换', '积分兑换', '积分兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13153', '1', '兑换积分', '兑换积分', '兑换积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13154', '1', '取消兑换', '取消兑换', '取消兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13155', '1', '缺少参数无法查看订单兑换状态', '缺少参数无法查看订单兑换状态', '缺少参数无法查看订单兑换状态', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13156', '1', '用户离开了', '用户离开了', '用户离开了', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13157', '1', '兑换成功', '兑换成功', '兑换成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13158', '1', '物流公司', '物流公司', '物流公司', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13159', '1', '复制单号', '复制单号', '复制单号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13160', '1', '设为默认', '设为默认', '设为默认', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13161', '1', '添加新地址', '添加新地址', '添加新地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13162', '1', '导入微信地址', '导入微信地址', '导入微信地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13163', '1', '取消选择', '取消选择', '取消选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13164', '1', '您设置的默认地址不存在!', '您设置的默认地址不存在!', '您设置的默认地址不存在!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13165', '1', '设置成功', '设置成功', '设置成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13166', '1', '您删除的地址不存在!', '您删除的地址不存在!', '您删除的地址不存在!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13167', '1', '获取头像', '获取头像', '获取头像', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13168', '1', '请点击授权', '请点击授权', '请点击授权', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13169', '1', '绑定手机号', '绑定手机号', '绑定手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13170', '1', '永久', '永久', '永久', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13171', '1', '会员到期', '会员到期', '会员到期', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13172', '1', '未开通会员', '未开通会员', '未开通会员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13173', '1', '查看会员权益', '查看会员权益', '查看会员权益', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13174', '1', '立即续费', '立即续费', '立即续费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13175', '1', '立即激活', '立即激活', '立即激活', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13176', '1', '会员可享多项权益', '会员可享多项权益', '会员可享多项权益', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13177', '1', '订单中心', '订单中心', '订单中心', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13178', '1', '我的服务', '我的服务', '我的服务', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13179', '1', '隐私协议', '隐私协议', '隐私协议', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13180', '1', '商家管理', '商家管理', '商家管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13181', '1', '更新用户信息成功', '更新用户信息成功', '更新用户信息成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13182', '1', '客服接待', '客服接待', '客服接待', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13183', '1', '点击复制网址去浏览器中打开', '点击复制网址去浏览器中打开', '点击复制网址去浏览器中打开', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13184', '1', '点击复制', '点击复制', '点击复制', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13185', '1', '完成支付', '完成支付', '完成支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13186', '1', '点击右上角', '点击右上角', '点击右上角', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13187', '1', '选择 在浏览器 打开,去支付宝支付', '选择 在浏览器 打开,去支付宝支付', '选择 在浏览器 打开,去支付宝支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13188', '1', '支付订单不存在,页面将在2秒后自动关闭!', '支付订单不存在,页面将在2秒后自动关闭!', '支付订单不存在,页面将在2秒后自动关闭!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13189', '1', '正在支付中', '正在支付中', '正在支付中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13190', '1', '支付订单不存在,页面将在2秒后自动关闭', '支付订单不存在,页面将在2秒后自动关闭', '支付订单不存在,页面将在2秒后自动关闭', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13191', '1', '复制失败', '复制失败', '复制失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13192', '1', '您目前的排名', '您目前的排名', '您目前的排名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13193', '1', '您目前暂无排名', '您目前暂无排名', '您目前暂无排名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13194', '1', '暂无排名~', '暂无排名~', '暂无排名~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13195', '1', '我也是有底线的', '我也是有底线的', '我也是有底线的', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13196', '1', '输入手机号', '输入手机号', '输入手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13197', '1', '输入验证码', '输入验证码', '输入验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13198', '1', '立即登录', '立即登录', '立即登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13199', '1', '请填写手机号码', '请填写手机号码', '请填写手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('132', '1', '400065', '订单发货后自动收货时间必须为数字', '订单发货后自动收货时间必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('13200', '1', '请填写验证码', '请填写验证码', '请填写验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13201', '1', '请输入正确的验证码', '请输入正确的验证码', '请输入正确的验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13202', '1', '正在登录中', '正在登录中', '正在登录中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13203', '1', '登录成功', '登录成功', '登录成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13204', '1', '获取授权', '获取授权', '获取授权', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13205', '1', '获取微信的手机号授权', '获取微信的手机号授权', '获取微信的手机号授权', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13206', '1', '获取微信手机号', '获取微信手机号', '获取微信手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13207', '1', '输入手机号码', '输入手机号码', '输入手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13208', '1', '填写登录密码', '填写登录密码', '填写登录密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13209', '1', '登录', '登录', '登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13210', '1', '快速登录', '快速登录', '快速登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13211', '1', '账号登录', '账号登录', '账号登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13212', '1', '其他方式登录', '其他方式登录', '其他方式登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13213', '1', '登录中', '登录中', '登录中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13214', '1', '获取用户信息失败', '获取用户信息失败', '获取用户信息失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13215', '1', '请绑定手机号后,继续操作', '请绑定手机号后,继续操作', '请绑定手机号后,继续操作', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13216', '1', '错误信息', '错误信息', '错误信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13217', '1', '用户点击确定', '用户点击确定', '用户点击确定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13218', '1', '用户点击取消', '用户点击取消', '用户点击取消', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13219', '1', '登录失败', '登录失败', '登录失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13220', '1', '请勿重复点击', '请勿重复点击', '请勿重复点击', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13221', '1', '请填写密码', '请填写密码', '请填写密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13222', '1', '您输入的密码过于简单', '您输入的密码过于简单', '您输入的密码过于简单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13223', '1', '请填写账号', '请填写账号', '请填写账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13224', '1', '请输入正确的账号', '请输入正确的账号', '请输入正确的账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13225', '1', '[图片]', '[图片]', '[图片]', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13226', '1', '[语音]', '[语音]', '[语音]', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13227', '1', '[商品]', '[商品]', '[商品]', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13228', '1', '[订单]', '[订单]', '[订单]', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13229', '1', '亲、暂无消息记录哟!', '亲、暂无消息记录哟!', '亲、暂无消息记录哟!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13230', '1', '站内消息', '站内消息', '站内消息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13231', '1', '客服消息', '客服消息', '客服消息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13232', '1', '通知于', '通知于', '通知于', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13233', '1', '获取详情中', '获取详情中', '获取详情中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13234', '1', '代付订单创建成功,发给好友帮你付款吧~', '代付订单创建成功,发给好友帮你付款吧~', '代付订单创建成功,发给好友帮你付款吧~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13235', '1', '帮我付一下这件商品了,谢谢~', '帮我付一下这件商品了,谢谢~', '帮我付一下这件商品了,谢谢~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13236', '1', '已经有人替我代付,谢谢啦~', '已经有人替我代付,谢谢啦~', '已经有人替我代付,谢谢啦~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13237', '1', '谢谢你帮我支付,么么哒~', '谢谢你帮我支付,么么哒~', '谢谢你帮我支付,么么哒~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13238', '1', '我已为你代付成功,商家正在努力发货中~', '我已为你代付成功,商家正在努力发货中~', '我已为你代付成功,商家正在努力发货中~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13239', '1', '好友代付成功,商家正在努力发货中~', '好友代付成功,商家正在努力发货中~', '好友代付成功,商家正在努力发货中~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13240', '1', '发送给微信好友', '发送给微信好友', '发送给微信好友', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13241', '1', '查看订单详情', '查看订单详情', '查看订单详情', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13242', '1', '订单已支付', '订单已支付', '订单已支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13243', '1', '如果订单申请退款,已支付金额将原路退还给您', '如果订单申请退款,已支付金额将原路退还给您', '如果订单申请退款,已支付金额将原路退还给您', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13244', '1', '代付成功', '代付成功', '代付成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13245', '1', '谢谢你为我付款,还可以再去看看其他商品哟~', '谢谢你为我付款,还可以再去看看其他商品哟~', '谢谢你为我付款,还可以再去看看其他商品哟~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13246', '1', '该订单暂未支付', '该订单暂未支付', '该订单暂未支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13247', '1', '人', '人', '人', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13248', '1', '推广人数', '推广人数', '推广人数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13249', '1', '一级', '一级', '一级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13250', '1', '二级', '二级', '二级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13251', '1', '点击搜索会员名称', '点击搜索会员名称', '点击搜索会员名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13252', '1', '团队排序', '团队排序', '团队排序', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13253', '1', '金额排序', '金额排序', '金额排序', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13254', '1', '订单排序', '订单排序', '订单排序', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13255', '1', '单', '单', '单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13256', '1', '加入时间', '加入时间', '加入时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13257', '1', '累积推广订单', '累积推广订单', '累积推广订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13258', '1', '本月累计推广订单', '本月累计推广订单', '本月累计推广订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13259', '1', '返佣', '返佣', '返佣', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13260', '1', '暂未返佣', '暂未返佣', '暂未返佣', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13261', '1', '返佣时间', '返佣时间', '返佣时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13262', '1', '单号', '单号', '单号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13263', '1', '暂无推广订单~', '暂无推广订单~', '暂无推广订单~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13264', '1', '推广订单列表', '推广订单列表', '推广订单列表', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13265', '1', '找回密码', '找回密码', '找回密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13266', '1', '填写您的新密码', '填写您的新密码', '填写您的新密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13267', '1', '加载失败', '加载失败', '加载失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13268', '1', '点击授权登录您的客服工作台', '点击授权登录您的客服工作台', '点击授权登录您的客服工作台', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13269', '1', '授权登录', '授权登录', '授权登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13270', '1', '没有登录的code,请重新扫码', '没有登录的code,请重新扫码', '没有登录的code,请重新扫码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13271', '1', '员工人数', '员工人数', '员工人数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13272', '1', '邀请', '邀请', '邀请', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13273', '1', '分佣比例', '分佣比例', '分佣比例', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13274', '1', '修改分佣比例', '修改分佣比例', '修改分佣比例', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13275', '1', '请输入百分比', '请输入百分比', '请输入百分比', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13276', '1', '删除员工', '删除员工', '删除员工', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13277', '1', '确定删除该员工?', '确定删除该员工?', '确定删除该员工?', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13278', '1', '请输入比例', '请输入比例', '请输入比例', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13279', '1', '分类', '分类', '分类', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13280', '1', '我的', '我的', '我的', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13281', '1', '姓名', '姓名', '姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13282', '1', '请输入联系电话', '请输入联系电话', '请输入联系电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13283', '1', '所在地区', '所在地区', '所在地区', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13284', '1', '详细地址', '详细地址', '详细地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13285', '1', '设置为默认地址', '设置为默认地址', '设置为默认地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13286', '1', '立即保存', '立即保存', '立即保存', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13287', '1', '浙江省', '浙江省', '浙江省', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13288', '1', '杭州市', '杭州市', '杭州市', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13289', '1', '滨江区', '滨江区', '滨江区', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13290', '1', '广东省', '广东省', '广东省', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13291', '1', '广州市', '广州市', '广州市', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13292', '1', '番禺区', '番禺区', '番禺区', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13293', '1', '修改地址', '修改地址', '修改地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13294', '1', '添加地址', '添加地址', '添加地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13295', '1', '已取消!', '已取消!', '已取消!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13296', '1', '请填写联系电话', '请填写联系电话', '请填写联系电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13297', '1', '保存中', '保存中', '保存中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13298', '1', '修改成功', '修改成功', '修改成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13299', '1', '消费', '消费', '消费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('133', '1', '400066', '满额包邮金额必须为数字', '满额包邮金额必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('13300', '1', '充值', '充值', '充值', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13301', '1', '暂无账单的记录哦~', '暂无账单的记录哦~', '暂无账单的记录哦~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13302', '1', '点击【立即注销】即代表您已经同意《用户注销协议》', '点击【立即注销】即代表您已经同意《用户注销协议》', '点击【立即注销】即代表您已经同意《用户注销协议》', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13303', '1', '立即注销', '立即注销', '立即注销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13304', '1', '是否确认注销', '是否确认注销', '是否确认注销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13305', '1', '注销后无法恢复,请谨慎操作', '注销后无法恢复,请谨慎操作', '注销后无法恢复,请谨慎操作', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13306', '1', '注销', '注销', '注销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13307', '1', '持卡人', '持卡人', '持卡人', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13308', '1', '请输入持卡人姓名', '请输入持卡人姓名', '请输入持卡人姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13309', '1', '卡号', '卡号', '卡号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13310', '1', '请填写卡号', '请填写卡号', '请填写卡号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13311', '1', '银行', '银行', '银行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13312', '1', '提现', '提现', '提现', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13313', '1', '最低提现金额', '最低提现金额', '最低提现金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13314', '1', '当前可提现金额', '当前可提现金额', '当前可提现金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13315', '1', '冻结佣金', '冻结佣金', '冻结佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13316', '1', '说明: 每笔佣金的冻结期为', '说明: 每笔佣金的冻结期为', '说明: 每笔佣金的冻结期为', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13317', '1', '天,到期后可提现', '天,到期后可提现', '天,到期后可提现', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13318', '1', '账号', '账号', '账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13319', '1', '请填写您的微信账号', '请填写您的微信账号', '请填写您的微信账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13320', '1', '收款码', '收款码', '收款码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13321', '1', '请填写您的支付宝账号', '请填写您的支付宝账号', '请填写您的支付宝账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13322', '1', '请选择银行', '请选择银行', '请选择银行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13323', '1', '银行卡', '银行卡', '银行卡', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13324', '1', '微信', '微信', '微信', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13325', '1', '支付宝', '支付宝', '支付宝', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13326', '1', '请填写持卡人姓名', '请填写持卡人姓名', '请填写持卡人姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13327', '1', '请填写微信号', '请填写微信号', '请填写微信号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13328', '1', '请填写提现金额', '请填写提现金额', '请填写提现金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13329', '1', '提现金额不能低于', '提现金额不能低于', '提现金额不能低于', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13330', '1', '未使用', '未使用', '未使用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13331', '1', '已使用/过期', '已使用/过期', '已使用/过期', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13332', '1', '通用劵', '通用劵', '通用劵', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13333', '1', '一级分佣上浮', '一级分佣上浮', '一级分佣上浮', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13334', '1', '二级分佣上浮', '二级分佣上浮', '二级分佣上浮', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13335', '1', '快速升级技巧', '快速升级技巧', '快速升级技巧', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13336', '1', '未完成', '未完成', '未完成', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13337', '1', '已领完', '已领完', '已领完', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13338', '1', '当前共', '当前共', '当前共', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13339', '1', '取关', '取关', '取关', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13340', '1', '请选择商品', '请选择商品', '请选择商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13341', '1', '头像', '头像', '头像', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13342', '1', '手机号码', '手机号码', '手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13343', '1', '点击绑定手机号', '点击绑定手机号', '点击绑定手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13344', '1', 'ID号', 'ID号', 'ID号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13345', '1', '权限设置', '权限设置', '权限设置', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13346', '1', '点击管理', '点击管理', '点击管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13347', '1', '密码', '密码', '密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13348', '1', '点击修改密码', '点击修改密码', '点击修改密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13349', '1', '更换手机号码', '更换手机号码', '更换手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13350', '1', '点击更换手机号码', '点击更换手机号码', '点击更换手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13351', '1', '缓存大小', '缓存大小', '缓存大小', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13352', '1', '当前版本', '当前版本', '当前版本', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13353', '1', '地址管理', '地址管理', '地址管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13354', '1', '发票管理', '发票管理', '发票管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13355', '1', '账号注销', '账号注销', '账号注销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13356', '1', '注销后无法恢复', '注销后无法恢复', '注销后无法恢复', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13357', '1', '累计积分', '累计积分', '累计积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13358', '1', '累计消费', '累计消费', '累计消费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13359', '1', '冻结积分', '冻结积分', '冻结积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13360', '1', '积分规则', '积分规则', '积分规则', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13361', '1', '提示:积分数值的高低会直接影响您的会员等级', '提示:积分数值的高低会直接影响您的会员等级', '提示:积分数值的高低会直接影响您的会员等级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13362', '1', '提示:你有', '提示:你有', '提示:你有', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13363', '1', '积分在', '积分在', '积分在', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13364', '1', '过期,请尽快使用', '过期,请尽快使用', '过期,请尽快使用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13365', '1', '暂无积分记录哦~', '暂无积分记录哦~', '暂无积分记录哦~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13366', '1', '赚积分', '赚积分', '赚积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13367', '1', '分值明细', '分值明细', '分值明细', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13368', '1', '分值提升', '分值提升', '分值提升', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13369', '1', '抬头类型', '抬头类型', '抬头类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13370', '1', '增值税电子专用发票', '增值税电子专用发票', '增值税电子专用发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13371', '1', '增值税电子普通发票', '增值税电子普通发票', '增值税电子普通发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13372', '1', '需要开具发票的姓名', '需要开具发票的姓名', '需要开具发票的姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13373', '1', '需要开具发票的企业名称', '需要开具发票的企业名称', '需要开具发票的企业名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13374', '1', '税号', '税号', '税号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13375', '1', '纳税人识别号', '纳税人识别号', '纳税人识别号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13376', '1', '手机号', '手机号', '手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13377', '1', '您的手机号', '您的手机号', '您的手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13378', '1', '邮箱', '邮箱', '邮箱', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13379', '1', '您的联系邮箱', '您的联系邮箱', '您的联系邮箱', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13380', '1', '开户银行', '开户银行', '开户银行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13381', '1', '您的开户银行', '您的开户银行', '您的开户银行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13382', '1', '银行账号', '银行账号', '银行账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13383', '1', '您的银行账号', '您的银行账号', '您的银行账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13384', '1', '企业地址', '企业地址', '企业地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13385', '1', '您所在的企业地址', '您所在的企业地址', '您所在的企业地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13386', '1', '企业电话', '企业电话', '企业电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13387', '1', '您的企业电话', '您的企业电话', '您的企业电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13388', '1', '设置为默认抬头', '设置为默认抬头', '设置为默认抬头', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13389', '1', '保存', '保存', '保存', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13390', '1', '发票类型选择', '发票类型选择', '发票类型选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13391', '1', '纸质发票开出后将以邮寄形式交付', '纸质发票开出后将以邮寄形式交付', '纸质发票开出后将以邮寄形式交付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13392', '1', '请输入需要开具发票的姓名', '请输入需要开具发票的姓名', '请输入需要开具发票的姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13393', '1', '请输入您的手机号', '请输入您的手机号', '请输入您的手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13394', '1', '请正确输入您的手机号', '请正确输入您的手机号', '请正确输入您的手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13395', '1', '请输入您的联系邮箱', '请输入您的联系邮箱', '请输入您的联系邮箱', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13396', '1', '请正确输入您的联系邮箱', '请正确输入您的联系邮箱', '请正确输入您的联系邮箱', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13397', '1', '请输入需要开具发票的企业名称', '请输入需要开具发票的企业名称', '请输入需要开具发票的企业名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13398', '1', '请输入纳税人识别号', '请输入纳税人识别号', '请输入纳税人识别号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13399', '1', '请正确输入纳税人识别号', '请正确输入纳税人识别号', '请正确输入纳税人识别号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('134', '1', '400067', '积分倍数必须大于0', '积分倍数必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('13400', '1', '请输入您的开户银行', '请输入您的开户银行', '请输入您的开户银行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13401', '1', '请输入您的银行账号', '请输入您的银行账号', '请输入您的银行账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13402', '1', '请正确输入您的银行账号', '请正确输入您的银行账号', '请正确输入您的银行账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13403', '1', '请输入您所在的企业地址', '请输入您所在的企业地址', '请输入您所在的企业地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13404', '1', '请输入您的企业电话', '请输入您的企业电话', '请输入您的企业电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13405', '1', '发票记录', '发票记录', '发票记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13406', '1', '抬头管理', '抬头管理', '抬头管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13407', '1', '申请时间', '申请时间', '申请时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13408', '1', '没有发票信息哟~', '没有发票信息哟~', '没有发票信息哟~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13409', '1', '个人普通发票', '个人普通发票', '个人普通发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13410', '1', '企业普通发票', '企业普通发票', '企业普通发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13411', '1', '企业专用发票', '企业专用发票', '企业专用发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13412', '1', '添加新发票', '添加新发票', '添加新发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13413', '1', '删除该发票?', '删除该发票?', '删除该发票?', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13414', '1', '发票编号', '发票编号', '发票编号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13415', '1', '发票备注', '发票备注', '发票备注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13416', '1', '快递号', '快递号', '快递号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13417', '1', '总资产(元)', '总资产(元)', '总资产(元)', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13418', '1', '累计充值(元)', '累计充值(元)', '累计充值(元)', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13419', '1', '累计消费(元)', '累计消费(元)', '累计消费(元)', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13420', '1', '账单记录', '账单记录', '账单记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13421', '1', '消费记录', '消费记录', '消费记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13422', '1', '充值记录', '充值记录', '充值记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13423', '1', '积分中心', '积分中心', '积分中心', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13424', '1', '签到领积分', '签到领积分', '签到领积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13425', '1', '赚积分抵现金', '赚积分抵现金', '赚积分抵现金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13426', '1', '领取优惠券', '领取优惠券', '领取优惠券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13427', '1', '满减享优惠', '满减享优惠', '满减享优惠', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13428', '1', '最新拼团活动', '最新拼团活动', '最新拼团活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13429', '1', '最新的优惠商品上架拼团', '最新的优惠商品上架拼团', '最新的优惠商品上架拼团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13430', '1', '立即参与', '立即参与', '立即参与', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13431', '1', '当前限时秒杀', '当前限时秒杀', '当前限时秒杀', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13432', '1', '最新商品秒杀进行中', '最新商品秒杀进行中', '最新商品秒杀进行中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13433', '1', '我的余额', '我的余额', '我的余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13434', '1', '赠送', '赠送', '赠送', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13435', '1', '其他', '其他', '其他', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13436', '1', '注意事项', '注意事项', '注意事项', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13437', '1', '冻结佣金为', '冻结佣金为', '冻结佣金为', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13438', '1', '立即转入', '立即转入', '立即转入', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13439', '1', '立即充值', '立即充值', '立即充值', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13440', '1', '请输入金额', '请输入金额', '请输入金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13441', '1', '转入余额', '转入余额', '转入余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13442', '1', '转入余额后无法再次转出,确认是否转入余额', '转入余额后无法再次转出,确认是否转入余额', '转入余额后无法再次转出,确认是否转入余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13443', '1', '转入成功', '转入成功', '转入成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13444', '1', '正在支付', '正在支付', '正在支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13445', '1', '充值金额必须为数字', '充值金额必须为数字', '充值金额必须为数字', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13446', '1', '充值金额不能为0', '充值金额不能为0', '充值金额不能为0', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13447', '1', '填写手机号码', '填写手机号码', '填写手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13448', '1', '是否绑定账号', '是否绑定账号', '是否绑定账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13449', '1', '绑定', '绑定', '绑定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13450', '1', '您已取消绑定!', '您已取消绑定!', '您已取消绑定!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13451', '1', '当前手机号', '当前手机号', '当前手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13452', '1', '设置新密码', '设置新密码', '设置新密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13453', '1', '确认新密码', '确认新密码', '确认新密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13454', '1', '手机号码不存在,无法发送验证码!', '手机号码不存在,无法发送验证码!', '手机号码不存在,无法发送验证码!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13455', '1', '请输入新密码', '请输入新密码', '请输入新密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13456', '1', '两次输入的密码不一致!', '两次输入的密码不一致!', '两次输入的密码不一致!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13457', '1', '请输入验证码', '请输入验证码', '请输入验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13458', '1', '暂无退款订单~', '暂无退款订单~', '暂无退款订单~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13459', '1', '缺少订单号无法查看订单详情', '缺少订单号无法查看订单详情', '缺少订单号无法查看订单详情', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13460', '1', '明细', '明细', '明细', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13461', '1', '第七天', '第七天', '第七天', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13462', '1', '第7天', '第7天', '第7天', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13463', '1', '奖励', '奖励', '奖励', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13464', '1', '已签到', '已签到', '已签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13465', '1', '立即签到', '立即签到', '立即签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13466', '1', '已累计签到', '已累计签到', '已累计签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13467', '1', '据说连续签到第', '据说连续签到第', '据说连续签到第', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13468', '1', '天可获得超额积分,一定要坚持签到哦~~~', '天可获得超额积分,一定要坚持签到哦~~~', '天可获得超额积分,一定要坚持签到哦~~~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13469', '1', '签到成功', '签到成功', '签到成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13470', '1', '好的', '好的', 'OK', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13471', '1', '您今日已签到!', '您今日已签到!', '您今日已签到!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13472', '1', '暂无签到记录~', '暂无签到记录~', '暂无签到记录~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13473', '1', '保存海报', '保存海报', '保存海报', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13474', '1', '长按保存图片', '长按保存图片', '长按保存图片', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13475', '1', '分销海报', '分销海报', '分销海报', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13476', '1', '小程序二维码需要发布正式版后才能获取到', '小程序二维码需要发布正式版后才能获取到', '小程序二维码需要发布正式版后才能获取到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13477', '1', '获取中', '获取中', '获取中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13478', '1', '暂无数据~', '暂无数据~', '暂无数据~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13479', '1', '提现记录', '提现记录', '提现记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13480', '1', '提现总额', '提现总额', '提现总额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13481', '1', '佣金记录', '佣金记录', '佣金记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13482', '1', '佣金明细', '佣金明细', '佣金明细', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13483', '1', '分销等级', '分销等级', '分销等级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13484', '1', '昨日收益', '昨日收益', '昨日收益', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13485', '1', '累积已提', '累积已提', '累积已提', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13486', '1', '代理商申请', '代理商申请', '代理商申请', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13487', '1', '立即提现', '立即提现', '立即提现', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13488', '1', '推广名片', '推广名片', '推广名片', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13489', '1', '推广人统计', '推广人统计', '推广人统计', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13490', '1', '推广人订单', '推广人订单', '推广人订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13491', '1', '推广订单', '推广订单', '推广订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13492', '1', '事业部', '事业部', '事业部', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13493', '1', '代理商', '代理商', '代理商', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13494', '1', '推广人排行', '推广人排行', '推广人排行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13495', '1', '佣金排行', '佣金排行', '佣金排行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13496', '1', '员工列表', '员工列表', '员工列表', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13497', '1', '您目前暂无推广权限', '您目前暂无推广权限', '您目前暂无推广权限', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13498', '1', '商城购物可享', '商城购物可享', '商城购物可享', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13499', '1', '折', '折', '折', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('135', '1', '400068', '折扣数必须大于0', '折扣数必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('13500', '1', '当前等级', '当前等级', '当前等级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13501', '1', '未达成', '未达成', '未达成', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13502', '1', '今日成长值', '今日成长值', '今日成长值', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13503', '1', '点', '点', '点', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13504', '1', '我的成长值记录', '我的成长值记录', '我的成长值记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13505', '1', '暂未解锁该等级', '暂未解锁该等级', '暂未解锁该等级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13506', '1', '点,需达到', '点,需达到', '点,需达到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13507', '1', '已解锁更高等级', '已解锁更高等级', '已解锁更高等级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13508', '1', '我的成长特权', '我的成长特权', '我的成长特权', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13509', '1', '购物折扣', '购物折扣', '购物折扣', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13510', '1', '专属徽章', '专属徽章', '专属徽章', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13511', '1', '经验累积', '经验累积', '经验累积', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13512', '1', '尊享客服', '尊享客服', '尊享客服', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13513', '1', '签到', '签到', '签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13514', '1', '可获得', '可获得', '可获得', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13515', '1', '点经验', '点经验', '点经验', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13516', '1', '每日签到可获得经验值,已签到', '每日签到可获得经验值,已签到', '每日签到可获得经验值,已签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13517', '1', '去签到', '去签到', '去签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13518', '1', '点经验/元', '点经验/元', '点经验/元', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13519', '1', '购买商品可获得对应的经验值', '购买商品可获得对应的经验值', '购买商品可获得对应的经验值', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13520', '1', '去购买', '去购买', '去购买', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13521', '1', '点经验/人', '点经验/人', '点经验/人', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13522', '1', '邀请好友注册商城可获得经验值', '邀请好友注册商城可获得经验值', '邀请好友注册商城可获得经验值', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13523', '1', '去邀请', '去邀请', '去邀请', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13524', '1', '积分数', '积分数', '积分数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13525', '1', '消费金额', '消费金额', '消费金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13526', '1', '暂无经验记录', '暂无经验记录', '暂无经验记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13527', '1', '账户登录', '账户登录', '账户登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13528', '1', '微信登录', '微信登录', '微信登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13529', '1', '手机号登录', '手机号登录', '手机号登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13530', '1', '账户充值', '账户充值', '账户充值', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13531', '1', '佣金转入', '佣金转入', '佣金转入', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13532', '1', '周榜', '周榜', '周榜', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13533', '1', '月榜', '月榜', '月榜', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13534', '1', '周排行', '周排行', '周排行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13535', '1', '月排行', '月排行', '月排行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13536', '1', '语言切换', '语言切换', '语言切换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13537', '1', '点击前往', '点击前往', '点击前往', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13538', '1', '查看全部', '查看全部', '查看全部', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13539', '1', '查看订单', '查看订单', '查看订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13540', '1', '无法获取图片信息', '无法获取图片信息', '无法获取图片信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13541', '1', '长按或扫描查看', '长按或扫描查看', '长按或扫描查看', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13542', '1', '点解锁', '点解锁', '点解锁', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13543', '1', '确认修改', '确认修改', '确认修改', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13544', '1', '保存修改', '保存修改', '保存修改', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13545', '1', '退出登录', '退出登录', '退出登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13546', '1', '付费会员', '付费会员', '付费会员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13547', '1', '地址信息', '地址信息', '地址信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13548', '1', '我的推广', '我的推广', '我的推广', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13549', '1', '砍价记录', '砍价记录', '砍价记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13550', '1', '我的等级', '我的等级', '我的等级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13551', '1', '兑换', '兑换', '兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13552', '1', '申请中', '申请中', '申请中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13553', '1', '统计管理', '统计管理', '统计管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13554', '1', '退款', '退款', '退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13555', '1', '未发货', '未发货', '未发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13556', '1', '当前为最新版本', '当前为最新版本', '当前为最新版本', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13557', '1', '清除缓存', '清除缓存', '清除缓存', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13558', '1', '确定清楚本地缓存数据吗', '确定清楚本地缓存数据吗', '确定清楚本地缓存数据吗', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13559', '1', '缓存清理完成', '缓存清理完成', '缓存清理完成', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13560', '1', '切换的账号不存在', '切换的账号不存在', '切换的账号不存在', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13561', '1', '正在切换中', '正在切换中', '正在切换中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13562', '1', '确认退出登录', '确认退出登录', '确认退出登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13563', '1', '我知道了', '我知道了', '我知道了', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13564', '1', '系统错误', '系统错误', '系统错误', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13565', '1', '请求失败', '请求失败', '请求失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13566', '1', '邀请您加入', '邀请您加入', '邀请您加入', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13567', '1', '图片上传中', '图片上传中', '图片上传中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13568', '1', '上传图片失败', '上传图片失败', '上传图片失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13569', '1', '访问位置被拒绝', '访问位置被拒绝', '访问位置被拒绝', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13570', '1', '系统定位已关闭', '系统定位已关闭', '系统定位已关闭', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13571', '1', '需要定位权限', '需要定位权限', '需要定位权限', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13572', '1', '订单核销', '订单核销', '订单核销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13573', '1', '当前可转入佣金为', '当前可转入佣金为', '当前可转入佣金为', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13574', '1', '浏览记录', '浏览记录', '浏览记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13575', '1', '签到奖励', '签到奖励', '签到奖励', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13576', '1', '请输入内容', '请输入内容', '请输入内容', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13577', '1', '单次限购', '单次限购', '单次限购', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13578', '1', '永久限购', '永久限购', '永久限购', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13579', '1', '《用户协议》', '《用户协议》', '《用户协议》', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13580', '1', '《隐私协议》', '《隐私协议》', '《隐私协议》', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13581', '1', '与', '与', '与', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13582', '1', '请先阅读并同意协议', '请先阅读并同意协议', '请先阅读并同意协议', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13583', '1', '绑定下级通知', '绑定下级通知', '绑定下级通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13584', '1', '购买成功通知', '购买成功通知', '购买成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13585', '1', '确认收货通知', '确认收货通知', '确认收货通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13586', '1', '改价通知', '改价通知', '改价通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13587', '1', '退款成功通知', '退款成功通知', '退款成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13588', '1', '充值成功通知', '充值成功通知', '充值成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13589', '1', '积分到账通知', '积分到账通知', '积分到账通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13590', '1', '佣金到账通知', '佣金到账通知', '佣金到账通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13591', '1', '砍价成功通知', '砍价成功通知', '砍价成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13592', '1', '拼团成功通知', '拼团成功通知', '拼团成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13593', '1', '拼团失败通知', '拼团失败通知', '拼团失败通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13594', '1', '开团成功通知', '开团成功通知', '开团成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13595', '1', '提现成功通知', '提现成功通知', '提现成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13596', '1', '提现失败通知', '提现失败通知', '提现失败通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13597', '1', '充值退款通知', '充值退款通知', '充值退款通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13598', '1', '退款申请拒绝通知', '退款申请拒绝通知', '退款申请拒绝通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13599', '1', '您有新的退款待处理', '您有新的退款待处理', '您有新的退款待处理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('136', '1', '400069', '积分倍数必须大于0', '积分倍数必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('13600', '1', '您有新的订单待处理', '您有新的订单待处理', '您有新的订单待处理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13601', '1', '发货通知', '发货通知', '发货通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13602', '1', '取消拼团通知', '取消拼团通知', '取消拼团通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13603', '1', '参团成功通知', '参团成功通知', '参团成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13604', '1', '你有个新的提现申请待处理', '你有个新的提现申请待处理', '你有个新的提现申请待处理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13605', '1', '你有个新的用户收货待处理', '你有个新的用户收货待处理', '你有个新的用户收货待处理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13606', '1', '提醒付款通知', '提醒付款通知', '提醒付款通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13607', '1', '短信验证码', '短信验证码', '短信验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13608', '1', '到店自提', '到店自提', '到店自提', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('13609', '1', '快递配送', '快递配送', '快递配送', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('137', '1', '400070', '折扣数必须大于0', '折扣数必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('138', '1', '400071', '下单赠送经验比率必须为数字', '下单赠送经验比率必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('139', '1', '400072', '下单赠送经验比率必须大于0', '下单赠送经验比率必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('14', '1', '100013', '更新失败', '更新失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('140', '1', '400073', '签到赠送经验必须为数字', '签到赠送经验必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('141', '1', '400074', '签到赠送经验必须大于0', '签到赠送经验必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('142', '1', '400075', '邀请新用户赠送经验必须为数字', '邀请新用户赠送经验必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('143', '1', '400076', '邀请新用户赠送经验必须大于0', '邀请新用户赠送经验必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('144', '1', '400077', '发货人姓名必须为汉字', '发货人姓名必须为汉字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('145', '1', '400078', '发货人姓名长度在2-10位', '发货人姓名长度在2-10位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('146', '1', '400079', '发货人电话必须为数字', '发货人电话必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('147', '1', '400080', '发货人电话请填写有效的手机号', '发货人电话请填写有效的手机号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('148', '1', '400081', '发货人地址只能是汉字、字母、数字', '发货人地址只能是汉字、字母、数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('149', '1', '400082', '发货人地址长度为10-100位', '发货人地址长度为10-100位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('15', '1', '100014', '设置成功', '设置成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('150', '1', '400083', '电子面单打印机编号必须为数字、字母', '电子面单打印机编号必须为数字、字母', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('151', '1', '400084', '电子面单打印机编号长度为10-50位', '电子面单打印机编号长度为10-50位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('152', '1', '400085', '客服反馈长度位10-90位', '客服反馈长度位10-90位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('153', '1', '400086', '请填写标签分类名称', '请填写标签分类名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('154', '1', '400087', '请填写标签分类排序', '请填写标签分类排序', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('155', '1', '400088', '标签分类必须为数字', '标签分类必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('156', '1', '400089', '账号只能为数字和字母', '账号只能为数字和字母', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('157', '1', '400090', '限量不能超过商品库存', '限量不能超过商品库存', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('158', '1', '400091', '商品已下架或移入回收站', '商品已下架或移入回收站', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('159', '1', '400092', '占用库存失败', '占用库存失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('16', '1', '100015', '设置失败', '设置失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('160', '1', '400093', '商品已下架或已删除', '商品已下架或已删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('161', '1', '400094', '请选择有效的商品属性', '请选择有效的商品属性', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('162', '1', '400095', '金额不能小于0', '金额不能小于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('163', '1', '400096', '结束时间不能小于今天', '结束时间不能小于今天', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('164', '1', '400097', '您不是付费会员', '您不是付费会员', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('165', '1', '400098', '暂时无法领取', '暂时无法领取', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('166', '1', '400099', '请先配置小票打印开发者', '请先配置小票打印开发者', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('167', '1', '400100', '请填写分类名称', '请填写分类名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('168', '1', '400101', '该分类已存在', '该分类已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('169', '1', '400102', '请先删除子分类', '请先删除子分类', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('17', '1', '100016', '获取失败', '获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('170', '1', '400103', '分类不存在', '分类不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('171', '1', '400104', '文件名称不能为空', '文件名称不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('172', '1', '400105', '该分类有下级分类,无法修改上级', '该分类有下级分类,无法修改上级', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('173', '1', '400106', '备注不能为空', '备注不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('174', '1', '400107', '请输入姓名', '请输入姓名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('175', '1', '400108', '请输入提现金额', '请输入提现金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('176', '1', '400109', '请输入支付宝账号', '请输入支付宝账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('177', '1', '400110', '请输入微信账号', '请输入微信账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('178', '1', '400111', '请输入银行卡号', '请输入银行卡号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('179', '1', '400112', '请输入开户行', '请输入开户行', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('18', '1', '100017', '提交成功', '提交成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('180', '1', '400113', '拒绝理由不能为空', '拒绝理由不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('181', '1', '400114', '不能重复收货', '不能重复收货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('182', '1', '400115', '请先发货或者送货', '请先发货或者送货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('183', '1', '400116', '收货失败,请稍候再试', '收货失败,请稍候再试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('184', '1', '400117', '收货成功', '收货成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('185', '1', '400118', '订单不存在', '订单不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('186', '1', '400119', '用户信息不存在', '用户信息不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('187', '1', '400120', '快递单号不存在', '快递单号不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('188', '1', '400121', '打印成功', '打印成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('189', '1', '400122', '打印失败', '打印失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('19', '1', '100018', '提交失败', '提交失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('190', '1', '400123', '快递公司编号缺失', '快递公司编号缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('191', '1', '400124', '请配置腾讯地图KEY', '请配置腾讯地图KEY', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('192', '1', '400125', '请选择门店位置', '请选择门店位置', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('193', '1', '400126', '添加的核销员用户已存在', '添加的核销员用户已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('194', '1', '400127', '请选择所属提货点', '请选择所属提货点', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('195', '1', '400128', '请填写核销员名称', '请填写核销员名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('196', '1', '400129', '请填写核销员电话', '请填写核销员电话', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('197', '1', '400130', '核销员添加成功', '核销员添加成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('198', '1', '400131', '核销员添加失败', '核销员添加失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('199', '1', '400132', '请填写手机号', '请填写手机号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('2', '1', '100001', '修改成功', '修改成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('20', '1', '100019', '取消成功', '取消成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('200', '1', '400133', '请填写账号', '请填写账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('201', '1', '400134', '请填写密码', '请填写密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('202', '1', '400135', '请填写短信签名', '请填写短信签名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('203', '1', '400136', '短信签名最长为8位', '短信签名最长为8位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('204', '1', '400137', '请填写验证码', '请填写验证码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('205', '1', '400138', '请填写域名', '请填写域名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('206', '1', '400139', '登录成功', '登录成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('207', '1', '400140', '账号或密码错误', '账号或密码错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('208', '1', '400141', '请先填写短信配置', '请先填写短信配置', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('209', '1', '400142', '请输入模板名称', '请输入模板名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('21', '1', '100020', '取消失败', '取消失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('210', '1', '400143', '请输入模板内容', '请输入模板内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('211', '1', '400144', '售后订单状态不支持该操作', '售后订单状态不支持该操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('212', '1', '400145', '修改退款状态成功', '修改退款状态成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('213', '1', '400146', '请输入退款金额', '请输入退款金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('214', '1', '400147', '已退完支付金额,不能再退款了', '已退完支付金额,不能再退款了', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('215', '1', '400148', '退款金额大于支付金额,请修改退款金额', '退款金额大于支付金额,请修改退款金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('216', '1', '400149', '退款成功', '退款成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('217', '1', '400150', '退款失败', '退款失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('218', '1', '400151', '验证成功', '验证成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('219', '1', '400152', '核销成功', '核销成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('22', '1', '100021', '添加成功', '添加成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('220', '1', '400153', '核销订单未查到', '核销订单未查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('221', '1', '400154', '核销失败', '核销失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('222', '1', '400155', '订单金额必须填写', '订单金额必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('223', '1', '400156', '请选择需要删除的订单', '请选择需要删除的订单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('224', '1', '400157', '您选择的的订单存在用户未删除的订单', '您选择的的订单存在用户未删除的订单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('225', '1', '400158', '请选择发货商品', '请选择发货商品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('226', '1', '400159', '请重新选择发货商品或发货件数', '请重新选择发货商品或发货件数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('227', '1', '400160', '订单已删除无法退积分', '订单已删除无法退积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('228', '1', '400161', '请输入积分', '请输入积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('229', '1', '400162', '已退完积分', '已退完积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('23', '1', '100022', '添加失败', '添加失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('230', '1', '400163', '退积分大于支付积分,请修改退积分', '退积分大于支付积分,请修改退积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('231', '1', '400164', '退积分成功', '退积分成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('232', '1', '400165', '退积分失败', '退积分失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('233', '1', '400166', '请填写开票号', '请填写开票号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('234', '1', '400167', '请填写正确的开票号', '请填写正确的开票号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('235', '1', '400168', '请上传文件', '请上传文件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('236', '1', '400169', '回复成功', '回复成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('237', '1', '400170', '注册成功', '注册成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('238', '1', '400171', '注册失败', '注册失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('239', '1', '400172', '登录失败', '登录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24', '1', '100023', '保存token失败', '保存token失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('240', '1', '400173', '获取套餐列表失败', '获取套餐列表失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('241', '1', '400174', '获取支付码失败', '获取支付码失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('242', '1', '400175', '请先开通短信服务', '请先开通短信服务', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24221', '1', '退款发起查询失败', '退款发起失败', '微信支付:发起退款查询失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24231', '1', '500000', '发起退款查询失败', '微信支付:发起退款查询失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24241', '1', '500001', '请输入承载快递员名', '请输入承载快递员名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24261', '1', '500002', '请输入客户账户名称', '请输入客户账户名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24271', '1', '500003', '请输入电子面单承载编号', '请输入电子面单承载编号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24281', '1', '优质精选好物', '优质精选好物', '优质精选好物', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24291', '1', '商品分类', '商品分类', '商品分类', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('243', '1', '400176', '请先开通物流查询服务', '请先开通物流查询服务', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24301', '1', '领优惠券', '领优惠券', '领优惠券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24311', '1', '行业资讯', '行业资讯', '行业资讯', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24321', '1', '秒杀活动', '秒杀活动', '秒杀活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24331', '1', '预售管理', '预售管理', '预售管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24341', '1', '积分商城', '积分商城', '积分商城', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24351', '1', '快速选择', '快速选择', '快速选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24361', '1', '上百种商品分类', '上百种商品分类', '上百种商品分类', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24371', '1', '促销精品', '促销精品', '促销精品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24381', '1', '排行榜', '排行榜', '排行榜', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24391', '1', '新品推荐', '新品推荐', '新品推荐', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('244', '1', '400177', '请先开通电子面单打印服务', '请先开通电子面单打印服务', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24401', '1', '精选单品', '精选单品', '精选单品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24411', '1', '余额支付购买商品', '余额支付购买商品', '余额支付购买商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24421', '1', '商品退款', '商品退款', '商品退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24431', '1', '系统增加余额', '系统增加余额', '系统增加余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24441', '1', '系统减少余额', '系统减少余额', '系统减少余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24451', '1', '用户充值余额', '用户充值余额', '用户充值余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24461', '1', '用户充值退款', '用户充值退款', '用户充值退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24471', '1', '佣金提现到余额', '佣金提现到余额', '佣金提现到余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24481', '1', '参与抽奖使用余额', '参与抽奖使用余额', '参与抽奖使用余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24491', '1', '抽奖中奖赠送余额', '抽奖中奖赠送余额', '抽奖中奖赠送余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('245', '1', '400178', '请先开通商品采集服务', '请先开通商品采集服务', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24501', '1', '新用户注册赠送余额', '新用户注册赠送余额', '新用户注册赠送余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24511', '1', '购买商品赠送积分', '购买商品赠送积分', '购买商品赠送积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24521', '1', '下单赠送积分', '下单赠送积分', '下单赠送积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24531', '1', '扣除订单下单赠送积分', '扣除订单下单赠送积分', '扣除订单下单赠送积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24541', '1', '返还下单使用积分', '返还下单使用积分', '返还下单使用积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24551', '1', '商品退积分', '商品退积分', '商品退积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24561', '1', '参与抽奖使用积分', '参与抽奖使用积分', '参与抽奖使用积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24571', '1', '抽奖中奖赠送积分', '抽奖中奖赠送积分', '抽奖中奖赠送积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24581', '1', '积分兑换商品', '积分兑换商品', '积分兑换商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24591', '1', '下单赠送经验', '下单赠送经验', '下单赠送经验', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('246', '1', '400179', '请设置短信签名', '请设置短信签名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24601', '1', '获得自购订单佣金', '获得自购订单佣金', '获得自购订单佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24611', '1', '获得下级推广订单佣金', '获得下级推广订单佣金', '获得下级推广订单佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24621', '1', '获得二级推广订单佣金', '获得二级推广订单佣金', '获得二级推广订单佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24631', '1', '获得推广用户佣金', '获得推广用户佣金', '获得推广用户佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24641', '1', '佣金提现', '佣金提现', '佣金提现', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24651', '1', '提现失败', '提现失败', '提现失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24661', '1', '退款退佣金', '退款退佣金', '退款退佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24671', '1', '获得员工推广订单佣金', '获得员工推广订单佣金', '获得员工推广订单佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24681', '1', '获得代理推广订单佣金', '获得代理推广订单佣金', '获得代理推广订单佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('247', '1', '400180', '修改短信签名成功', '修改短信签名成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24701', '1', '获得拼团团长佣金', '获得拼团团长佣金', '获得拼团团长佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24711', '1', '全部已读', '全部已读', '全部已读', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('24721', '1', '500004', '您有一笔支付成功的订单待处理,订单号{:order_id}!', '您有一笔支付成功的订单待处理,订单号{:order_id}!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24731', '1', '500005', '恭喜,又一员猛将将永久绑定到您的团队,用户{:nickname}加入您的队伍!', '恭喜,又一员猛将将永久绑定到您的团队,用户{:nickname}加入您的队伍!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24741', '1', '500006', '您购买的商品已支付成功,支付金额{:pay_price}元,订单号{:order_id},感谢您的光临!', '您购买的商品已支付成功,支付金额{:pay_price}元,订单号{:order_id},感谢您的光临!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24751', '1', '500007', '亲,您的订单{:order_id},商品{:store_name}已确认收货,感谢您的光临!', '亲,您的订单{:order_id},商品{:store_name}已确认收货,感谢您的光临!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24761', '1', '500008', '您的订单{:order_id},实际支付金额已被修改为{:pay_price}', '您的订单{:order_id},实际支付金额已被修改为{:pay_price}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24781', '1', '500009', '您的订单{:order_id}已同意退款,退款金额{:refund_price}元。', '您的订单{:order_id}已同意退款,退款金额{:refund_price}元。', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24791', '1', '500010', '您成功充值¥{:price},现剩余余额¥{:now_money}元', '您成功充值¥{:price},现剩余余额¥{:now_money}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('248', '1', '400181', '默认模板不能删除', '默认模板不能删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24801', '1', '500011', '亲,您成功获得积分{:gain_integral},现有积分{:integral}', '亲,您成功获得积分{:gain_integral},现有积分{:integral}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24811', '1', '500012', '亲,恭喜您成功获得佣金{:brokerage_price}元', '亲,恭喜您成功获得佣金{:brokerage_price}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24821', '1', '500013', '亲,好腻害!你的朋友们已经帮你砍到底价了,商品名称{:title},底价{:min_price}', '亲,好腻害!你的朋友们已经帮你砍到底价了,商品名称{:title},底价{:min_price}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24831', '1', '500014', '亲,您的拼团已经完成了,拼团名称{:title},团长{:nickname}', '亲,您的拼团已经完成了,拼团名称{:title},团长{:nickname}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24841', '1', '500015', '亲,您的拼团失败,活动名称{:title}', '亲,您的拼团失败,活动名称{:title}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24851', '1', '500016', '亲,您已成功参与拼团,活动名称{:title}', '亲,您已成功参与拼团,活动名称{:title}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24861', '1', '500017', '亲,您成功提现佣金{:extract_number}元', '亲,您成功提现佣金{:extract_number}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24871', '1', '500018', '亲,您发起的提现被驳回,返回佣金{:extract_number}元', '亲,您发起的提现被驳回,返回佣金{:extract_number}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24881', '1', '500019', '亲,您充值的金额已退款,本次退款{:refund_price}元', '亲,您充值的金额已退款,本次退款{:refund_price}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24891', '1', '500020', '您好!您的订单{:order_id}已拒绝退款。', '您好!您的订单{:order_id}已拒绝退款。', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('249', '1', '400182', '管理员信息读取失败', '管理员信息读取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24901', '1', '500021', '您有一笔退款订单待处理,订单号{:order_id}!', '您有一笔退款订单待处理,订单号{:order_id}!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24911', '1', '500022', '亲爱的用户{:nickname}您的商品{:store_name},订单号{:order_id}已发货,请注意查收', '亲爱的用户{:nickname}您的商品{:store_name},订单号{:order_id}已发货,请注意查收', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24921', '1', '500023', '亲,您的拼团取消,活动名称{:title}', '亲,您的拼团取消,活动名称{:title}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24931', '1', '500024', '亲,您已成功参与拼团,活动名称{:title}', '亲,您已成功参与拼团,活动名称{:title}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24941', '1', '500025', '您有一笔提现申请待处理,提现金额{:money}!', '您有一笔提现申请待处理,提现金额{:money}!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24951', '1', '500026', '您有一笔订单已经确认收货,订单号{:order_id}!', '您有一笔订单已经确认收货,订单号{:order_id}!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24961', '1', '500027', '您有未付款订单,订单号为:{:order_id},商品数量有限,请及时付款。', '您有未付款订单,订单号为:{:order_id},商品数量有限,请及时付款。', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24971', '1', '500028', '请填写邀请码', '请填写邀请码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24981', '1', '500029', '金额最多两位小数', '金额最多两位小数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('24991', '1', '500030', '名称长度需在6-17个字符之间', '名称长度需在6-17个字符之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25', '1', '100024', '备注成功', '备注成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('250', '1', '400183', '密码太过简单,请输入较为复杂的密码', '密码太过简单,请输入较为复杂的密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25001', '1', '500031', '接口名不能为空', '接口名不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25011', '1', '500032', '接口地址不能为空', '接口地址不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25021', '1', '500033', '请求方式不能为空', '请求方式不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25031', '1', '500034', '模块分类不能为空', '模块分类不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25041', '1', '500035', '接口不存在', '接口不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25051', '1', '500036', '接口信息不存在', '接口信息不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25061', '1', '500037', '接口分类名称不能为空', '接口分类名称不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25071', '1', '500038', '该分类下有接口,无法删除', '该分类下有接口,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25081', '1', '500039', 'zip扩展未安装', 'zip扩展未安装', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25091', '1', '500040', '删除文件失败,失败原因{:message}', '删除文件失败,失败原因{:message}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('251', '1', '400184', '协议类型不存在', '协议类型不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25101', '1', '500041', '系统数据表,无法生成', '系统数据表,无法生成', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25111', '1', '500042', '表名不能为空', '表名不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25121', '1', '500043', '功能创建成功', '功能创建成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25131', '1', '500044', '字段类型不存在', '字段类型不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25141', '1', '500045', '不存在的资源路由类型', '不存在的资源路由类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25151', '1', '500046', '表单类型至少选择一项', '表单类型至少选择一项', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('25181', '1', '支付剩余时间', '支付剩余时间', '支付剩余时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('25191', '1', '确认支付', '确认支付', '确认支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('252', '1', '400185', '清除成功', '清除成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('253', '1', '400186', '清除失败', '清除失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('254', '1', '400187', '请输入名称', '请输入名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('255', '1', '400188', '请不要重复添加', '请不要重复添加', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('256', '1', '400189', '添加数据成功', '添加数据成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('257', '1', '400190', '请输入开始时间', '请输入开始时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('258', '1', '400191', '请输入持续时间', '请输入持续时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('259', '1', '400192', '请输入0-23点之前的整点数', '请输入0-23点之前的整点数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('26', '1', '100025', '备注失败', '备注失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('260', '1', '400193', '请输入1-24点之前的整点数', '请输入1-24点之前的整点数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('261', '1', '400194', '开始时间+持续时间不能大于24小时', '开始时间+持续时间不能大于24小时', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('262', '1', '400195', '时段已占用', '时段已占用', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('263', '1', '400196', '请输入签到赠送积分', '请输入签到赠送积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('264', '1', '400197', '请输入大于等于0的整数', '请输入大于等于0的整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('265', '1', '400198', '请填写按钮名称', '请填写按钮名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('266', '1', '400199', '没有查到此身份', '没有查到此身份', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('267', '1', '400200', '请输入等级名称', '请输入等级名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('268', '1', '400201', '请输入等级', '请输入等级', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('269', '1', '400202', '请选择等级图标', '请选择等级图标', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('27', '1', '100026', '数据不存在', '数据不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('270', '1', '400203', '二级返佣比例不能大于一级', '二级返佣比例不能大于一级', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('271', '1', '400204', '当前等级已存在', '当前等级已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('272', '1', '400205', '添加等级成功', '添加等级成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('273', '1', '400206', '编辑的等级不存在', '编辑的等级不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('274', '1', '400207', '请输入任务名称', '请输入任务名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('275', '1', '400208', '请选择任务类型', '请选择任务类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('276', '1', '400209', '请输入限定数量', '请输入限定数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('277', '1', '400210', '添加任务成功', '添加任务成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('278', '1', '400211', '编辑的任务不存在', '编辑的任务不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('279', '1', '400212', '获取推广二维码失败,请检查您的微信配置', '获取推广二维码失败,请检查您的微信配置', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('28', '1', '100027', '申请成功', '申请成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('280', '1', '400213', '上级推广人不能为自己', '上级推广人不能为自己', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('281', '1', '400214', '用户不存在', '用户不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('282', '1', '400215', '上级用户不存在', '上级用户不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('283', '1', '400216', '当前推广人已经是所选人', '当前推广人已经是所选人', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('284', '1', '400217', '上级推广人不能为自己下级', '上级推广人不能为自己下级', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('285', '1', '400218', '赠送成功', '赠送成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('286', '1', '400219', '赠送失败', '赠送失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('287', '1', '400220', '请输入身份名称', '请输入身份名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('288', '1', '400221', '请选择最少一个权限', '请选择最少一个权限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('289', '1', '400222', '添加身份成功', '添加身份成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('29', '1', '100028', '申请失败', '申请失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('290', '1', '400223', '添加身份失败', '添加身份失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('291', '1', '400224', '缺少APPID', '缺少APPID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('292', '1', '400225', '请先设置空间域名', '请先设置空间域名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('293', '1', '400226', '格式错误,请输入格式为:http://域名', '格式错误,请输入格式为:http://域名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('294', '1', '400227', '未有正在使用的存储空间', '未有正在使用的存储空间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('295', '1', '400228', '切换云存储成功,请检查是否开启使用了存储空间', '切换云存储成功,请检查是否开启使用了存储空间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('296', '1', '400229', '切换本地存储成功', '切换本地存储成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('297', '1', '400230', '请输入模板编号', '请输入模板编号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('298', '1', '400231', '请输入模板编号已存在,请重新输入', '请输入模板编号已存在,请重新输入', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('299', '1', '400232', '请输入模板ID', '请输入模板ID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('3', '1', '100002', '删除成功', '删除成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('30', '1', '100029', '暂无此方法', '暂无此方法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('300', '1', '400233', '请输入模板名', '请输入模板名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('301', '1', '400234', '请输入回复内容', '请输入回复内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('302', '1', '400235', '添加模板消息成功', '添加模板消息成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('303', '1', '400236', '请先配置小程序appid、appSecret等参数', '请先配置小程序appid、appSecret等参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('304', '1', '400237', '二维码生成失败', '二维码生成失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('305', '1', '400238', '请添加至少一个按钮', '请添加至少一个按钮', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('306', '1', '400239', '请输入关键字', '请输入关键字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('307', '1', '400240', '请选择回复类型', '请选择回复类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('308', '1', '400241', '回复类型有误', '回复类型有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('309', '1', '400242', '回复消息参数有误', '回复消息参数有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('31', '1', '100030', '发送成功', '发送成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('310', '1', '400243', '请添加图文', '请添加图文', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('311', '1', '400244', '标题不能为空', '标题不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('312', '1', '400245', '作者不能为空', '作者不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('313', '1', '400246', '正文不能为空', '正文不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('314', '1', '400247', '摘要不能为空', '摘要不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('315', '1', '400248', '请先配置微信公众号appid、appSecret等参数', '请先配置微信公众号appid、appSecret等参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('316', '1', '400249', '模版消息一键设置成功', '模版消息一键设置成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('317', '1', '400250', '请选择用户', '请选择用户', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('318', '1', '400251', '该用户没有绑定手机号,请手动填写', '该用户没有绑定手机号,请手动填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('319', '1', '400252', '手机号格式错误', '手机号格式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('32', '1', '100031', '发送失败', '发送失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('320', '1', '400253', '客服已存在', '客服已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('321', '1', '400254', '请输入账号', '请输入账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('322', '1', '400255', '账号必须为数字或者字母的组合4-30位', '账号必须为数字或者字母的组合4-30位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('323', '1', '400256', '请输入密码', '请输入密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('324', '1', '400257', '密码必须为数字或者字母的组合6-20位', '密码必须为数字或者字母的组合6-20位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('325', '1', '400258', '该手机号的客服已存在', '该手机号的客服已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('326', '1', '400259', '该客服账号已存在', '该客服账号已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('327', '1', '400260', '客服添加成功', '客服添加成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('328', '1', '400261', '客服添加失败', '客服添加失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('329', '1', '400262', '客服名称不能为空', '客服名称不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('33', '1', '100032', '上传成功', '上传成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('330', '1', '400263', '请输入确认密码', '请输入确认密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('331', '1', '400264', '两次输入的密码不一致', '两次输入的密码不一致', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('332', '1', '400265', '用户不存在,客服将强制禁止登录', '用户不存在,客服将强制禁止登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('333', '1', '400266', '登录的客服不存在', '登录的客服不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('334', '1', '400267', '请先填写客服账号和密码再尝试进入客服平台', '请先填写客服账号和密码再尝试进入客服平台', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('335', '1', '400268', '反馈内容不存在', '反馈内容不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('336', '1', '400269', '话术不能重复添加', '话术不能重复添加', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('337', '1', '400270', '创建话术成功', '创建话术成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('338', '1', '400271', '创建话术失败', '创建话术失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('339', '1', '400272', '删除的话术不存在', '删除的话术不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('34', '1', '100033', '上传失败', '上传失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('340', '1', '400273', '系统分类不能删除', '系统分类不能删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('341', '1', '400274', '请输入配置名称', '请输入配置名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('342', '1', '400275', '请输入字段名称', '请输入字段名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('343', '1', '400276', '请输入配置简介', '请输入配置简介', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('344', '1', '400277', '请输入文本框的宽度', '请输入文本框的宽度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('345', '1', '400278', '请输入正确的文本框的宽度', '请输入正确的文本框的宽度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('346', '1', '400279', '请输入多行文本框的宽度', '请输入多行文本框的宽度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('347', '1', '400280', '请输入多行文本框的高度', '请输入多行文本框的高度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('348', '1', '400281', '请输入正确的多行文本框的宽度', '请输入正确的多行文本框的宽度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('349', '1', '400282', '请输入正确的多行文本框的宽度', '请输入正确的多行文本框的宽度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('35', '1', '100034', '移动成功', '移动成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('350', '1', '400283', '请输入配置参数', '请输入配置参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('351', '1', '400284', '添加配置成功', '添加配置成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('352', '1', '400285', '一二级返佣比例不能大于100%', '一二级返佣比例不能大于100%', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('353', '1', '400286', '分销海报不能多于5张', '分销海报不能多于5张', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('354', '1', '400287', '提现最低金额只能为数字', '提现最低金额只能为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('355', '1', '400288', '满额分销最低金额不能为空', '满额分销最低金额不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('356', '1', '400289', '满额分销最低金额不能小于0', '满额分销最低金额不能小于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('357', '1', '400290', '绑定有效期请填写正整数', '绑定有效期请填写正整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('358', '1', '400291', '请输入标题', '请输入标题', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('359', '1', '400292', '添加配置分类成功', '添加配置分类成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('36', '1', '100035', '移动失败', '移动失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('360', '1', '400293', '存在下级配置,无法删除', '存在下级配置,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('361', '1', '400294', '字段至少存在一个', '字段至少存在一个', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('362', '1', '400295', '添加数据组成功', '添加数据组成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('363', '1', '400296', '数据关键字已存在', '数据关键字已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('364', '1', '400297', '字段不能为空', '字段不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('365', '1', '400298', '不能大于四个', '不能大于四个', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('366', '1', '400299', '签到天数配置不能大于7天', '签到天数配置不能大于7天', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('367', '1', '400300', '关联成功', '关联成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('368', '1', '400301', '关联失败', '关联失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('369', '1', '400302', '数据缓存刷新成功', '数据缓存刷新成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('37', '1', '100036', '退款成功', '退款成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('370', '1', '400303', '数据缓存刷新失败', '数据缓存刷新失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('371', '1', '400304', '请输入需要更换的域名', '请输入需要更换的域名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('372', '1', '400305', '域名不合法', '域名不合法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('373', '1', '400306', '替换成功', '替换成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('374', '1', '400307', '初始化完成', '初始化完成', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('375', '1', '400308', '备份文件可能已经损坏,请检查', '备份文件可能已经损坏,请检查', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('376', '1', '400309', '还原数据出错', '还原数据出错', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('377', '1', '400310', '正在还原...', '正在还原...', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('378', '1', '400311', '还原完成', '还原完成', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('379', '1', '400312', '权益编辑成功', '权益编辑成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('38', '1', '100037', '退款失败', '退款失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('380', '1', '400313', '卡片生成成功', '卡片生成成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('381', '1', '400314', '手机号已经存在', '手机号已经存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('382', '1', '400315', '请输入正确的身份证', '请输入正确的身份证', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('383', '1', '400316', '请选择分组', '请选择分组', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('384', '1', '400317', '请选择标签', '请选择标签', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('385', '1', '400318', '加入消息队列成功', '加入消息队列成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('386', '1', '400319', '注销成功', '注销成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('387', '1', '400320', '拒绝注销', '拒绝注销', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('388', '1', '400321', '请输入分组名称', '请输入分组名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('389', '1', '400322', '会员标签不能为空', '会员标签不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('39', '1', '100038', '同步成功', '同步成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('390', '1', '400323', '该分类下有标签,请先删除标签', '该分类下有标签,请先删除标签', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('391', '1', '400324', '请输入等级名称', '请输入等级名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('392', '1', '400325', '请输入等级', '请输入等级', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('393', '1', '400326', '请输入等级说明', '请输入等级说明', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('394', '1', '400327', '请上传等级图标', '请上传等级图标', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('395', '1', '400328', '请上传等级背景图标', '请上传等级背景图标', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('396', '1', '400329', '请输入升级经验值', '请输入升级经验值', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('397', '1', '400330', '授权成功,写入数据库失败,请检查数据库链接配置', '授权成功,写入数据库失败,请检查数据库链接配置', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('398', '1', '400331', '请填写公司名称', '请填写公司名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('399', '1', '400332', '请填写授权域名', '请填写授权域名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('4', '1', '100003', '显示成功', '显示成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('40', '1', '100039', '同步失败', '同步失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('400', '1', '400333', '请填写手机号码', '请填写手机号码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('401', '1', '400334', '请填写订单id', '请填写订单id', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('402', '1', '400335', '申请授权成功', '申请授权成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('403', '1', '400336', '验证码错误', '验证码错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('404', '1', '400337', '请选择商品', '请选择商品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('405', '1', '400338', '请输入商品名称', '请输入商品名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('406', '1', '400339', '请选择背景图', '请选择背景图', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('407', '1', '400340', '请输入直播价格', '请输入直播价格', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('408', '1', '400341', '直播价格必须大于0', '直播价格必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('409', '1', '400342', '请输入直播间名称', '请输入直播间名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('41', '1', '100040', '恢复成功', '恢复成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('410', '1', '400343', '请选择背景图', '请选择背景图', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('411', '1', '400344', '请选择分享图', '请选择分享图', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('412', '1', '400345', '请选择主播', '请选择主播', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('413', '1', '400346', '请选择直播开始、结束时间', '请选择直播开始、结束时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('414', '1', '400347', '请填写活动简介', '请填写活动简介', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('415', '1', '400348', '请填写单位', '请填写单位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('416', '1', '400349', '请选择商品轮播图', '请选择商品轮播图', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('417', '1', '400350', '您设置得商品个数超出系统限制', '您设置得商品个数超出系统限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('418', '1', '400351', '模板不存在', '模板不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('419', '1', '400352', '请输入页面名称', '请输入页面名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42', '1', '100041', '恢复失败', '恢复失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('420', '1', '400353', '请选择活动时间段', '请选择活动时间段', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('421', '1', '400354', '请填写购买数量限制', '请填写购买数量限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('422', '1', '400355', '购买数量限制必须大于0', '购买数量限制必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('423', '1', '400356', '请填写帮砍次数', '请填写帮砍次数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('424', '1', '400357', '帮砍次数必须大于0', '帮砍次数必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('425', '1', '400358', '请填写砍价人数', '请填写砍价人数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('426', '1', '400359', '砍价人数必须大于1', '砍价人数必须大于1', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('427', '1', '400360', '请选择运费模板', '请选择运费模板', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('428', '1', '400361', '请填写商品详情', '请填写商品详情', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42878', '18', '100000', '保存成功', '保存成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42879', '18', '100001', '修改成功', '修改成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42880', '18', '100002', '删除成功', '删除成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42881', '18', '100003', '显示成功', '显示成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42882', '18', '100004', '隐藏成功', '隐藏成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42883', '18', '100005', '操作失败', '操作失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42884', '18', '100006', '保存失败', '保存失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42885', '18', '100007', '修改失败', '修改失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42886', '18', '100008', '删除失败', '删除失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42887', '18', '100009', '图片上传成功', '图片上传成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42888', '18', '100010', '操作成功', '操作成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42889', '18', '100011', '暂无数据', '暂无数据', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42890', '18', '100012', '更新成功', '更新成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42891', '18', '100013', '更新失败', '更新失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42892', '18', '100014', '设置成功', '设置成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42893', '18', '100015', '设置失败', '设置失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42894', '18', '100016', '获取失败', '获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42895', '18', '100017', '提交成功', '提交成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42896', '18', '100018', '提交失败', '提交失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42897', '18', '100019', '取消成功', '取消成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42898', '18', '100020', '取消失败', '取消失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42899', '18', '100021', '添加成功', '添加成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('429', '1', '400362', '请选择规格', '请选择规格', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42900', '18', '100022', '添加失败', '添加失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42901', '18', '100023', '保存token失败', '保存token失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42902', '18', '100024', '备注成功', '备注成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42903', '18', '100025', '备注失败', '备注失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42904', '18', '100026', '数据不存在', '数据不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42905', '18', '100027', '申请成功', '申请成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42906', '18', '100028', '申请失败', '申请失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42907', '18', '100029', '暂无此方法', '暂无此方法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42908', '18', '100030', '发送成功', '发送成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42909', '18', '100031', '发送失败', '发送失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42910', '18', '100032', '上传成功', '上传成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42911', '18', '100033', '上传失败', '上传失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42912', '18', '100034', '移动成功', '移动成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42913', '18', '100035', '移动失败', '移动失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42914', '18', '100036', '退款成功', '退款成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42915', '18', '100037', '退款失败', '退款失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42916', '18', '100038', '同步成功', '同步成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42917', '18', '100039', '同步失败', '同步失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42918', '18', '100040', '恢复成功', '恢复成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42919', '18', '100041', '恢复失败', '恢复失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42920', '18', '100042', '退出成功', '退出成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42921', '18', '100043', '退出失败', '退出失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42922', '18', '100044', '开通成功', '开通成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42923', '18', '100045', '开通失败', '开通失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42924', '18', '100046', '清除数据成功', '清除数据成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42925', '18', '100047', '优化成功', '优化成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42926', '18', '100048', '优化失败', '优化失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42927', '18', '100049', '修复成功', '修复成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42928', '18', '100050', '修复失败', '修复失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42929', '18', '100051', '备份成功', '备份成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42930', '18', '100052', '备份失败', '备份失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42931', '18', '100100', '参数错误', '参数错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42932', '18', '100101', '非法操作', '非法操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42933', '18', '100102', '数据获取失败', '数据获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42934', '18', '100103', '站点升级中,请稍候访问', '站点升级中,请稍候访问', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42935', '18', '100104', '缺少code', '缺少code', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42936', '18', '110000', '您暂时没有访问权限', '您暂时没有访问权限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42937', '18', '110001', '接口未授权,您无法访问', '接口未授权,您无法访问', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42938', '18', '110002', '请登录', '请登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42939', '18', '110003', '登录已过期,请重新登录', '登录已过期,请重新登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42940', '18', '110004', '登录状态有误,请重新登录', '登录状态有误,请重新登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42941', '18', '110005', '请登录', '请登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42942', '18', '110006', '登录已过期,请重新登录', '登录已过期,请重新登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42943', '18', '110007', '登录状态有误,请重新登录', '登录状态有误,请重新登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42944', '18', '400000', '请选择用户头像', '请选择用户头像', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42945', '18', '400001', '请填写用户昵称', '请填写用户昵称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42946', '18', '400002', '请填写评论内容', '请填写评论内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42947', '18', '400003', '请选择商品分数', '请选择商品分数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42948', '18', '400004', '请选择服务分数', '请选择服务分数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42949', '18', '400005', '商品分数必须是1-5之间的整数', '商品分数必须是1-5之间的整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42950', '18', '400006', '服务分数必须是1-5之间的整数', '服务分数必须是1-5之间的整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42951', '18', '400007', '请选择快递公司', '请选择快递公司', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42952', '18', '400008', '请填写寄件人姓名', '请填写寄件人姓名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42953', '18', '400009', '请输入寄件人手机号码', '请输入寄件人手机号码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42954', '18', '400010', '寄件人手机号码不正确', '寄件人手机号码不正确', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42955', '18', '400011', '请填写寄件人详细地址', '请填写寄件人详细地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42956', '18', '400012', '请填写云打印机编号', '请填写云打印机编号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42957', '18', '400013', '请传入套餐id', '请传入套餐id', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42958', '18', '400014', '套餐id必须为数字', '套餐id必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42959', '18', '400015', '请填写套餐金额', '请填写套餐金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42960', '18', '400016', '请填写购买数量', '请填写购买数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42961', '18', '400017', '购买数量必须为数字', '购买数量必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42962', '18', '400018', '请填写购买套餐类型', '请填写购买套餐类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42963', '18', '400019', '您输入的手机号码必须为数字', '您输入的手机号码必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42964', '18', '400020', '密码必须填写', '密码必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42965', '18', '400021', '短信验证码必须为数字', '短信验证码必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42966', '18', '400022', '请填写话术内容', '请填写话术内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42967', '18', '400023', '请填写排序数字', '请填写排序数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42968', '18', '400024', '请填写排序数字', '请填写排序数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42969', '18', '400025', '请填写运费模板名称', '请填写运费模板名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42970', '18', '400026', '运费信息必须为数组', '运费信息必须为数组', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42971', '18', '400027', '包邮信息必须为数组', '包邮信息必须为数组', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42972', '18', '400028', '不送达信息必须为数组', '不送达信息必须为数组', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42973', '18', '400029', 'type数据格式错误,应为1或2或3', 'type数据格式错误,应为1或2或3', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42974', '18', '400030', 'appoint数据格式错误,应为0或1', 'appoint数据格式错误,应为0或1', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42975', '18', '400031', 'no_delivery数据格式错误,应为0或1', 'no_delivery数据格式错误,应为0或1', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42976', '18', '400032', 'sort数据格式错误,应为整数', 'sort数据格式错误,应为整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42977', '18', '400033', '请填写管理员账号', '请填写管理员账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42978', '18', '400034', '管理员账号为英文字母', '管理员账号为英文字母', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42979', '18', '400035', '请输管理员姓名', '请输管理员姓名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42980', '18', '400036', '请选择管理员身份', '请选择管理员身份', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42981', '18', '400037', '身份必须为数组', '身份必须为数组', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42982', '18', '400038', '请填写城市名称', '请填写城市名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42983', '18', '400039', 'level数据格式错误,应为整数', 'level数据格式错误,应为整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42984', '18', '400040', 'parent_id数据格式错误,应为整数', 'parent_id数据格式错误,应为整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42985', '18', '400041', '请输入有效的网址', '请输入有效的网址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42986', '18', '400042', '一级返佣比例必须为数字', '一级返佣比例必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42987', '18', '400043', '一级返佣比例最多两位小数', '一级返佣比例最多两位小数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42988', '18', '400044', '一级返佣比例填写范围在0-100之间', '一级返佣比例填写范围在0-100之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42989', '18', '400045', '二级返佣比例必须为数字', '二级返佣比例必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42990', '18', '400046', '二级返佣比例最多两位小数', '二级返佣比例最多两位小数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42991', '18', '400047', '二级返佣比例填写范围在0-100之间', '二级返佣比例填写范围在0-100之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42992', '18', '400048', '待补货数量必须为数字', '待补货数量必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42993', '18', '400049', '警戒库存必须为数字', '警戒库存必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42994', '18', '400050', '提现最小金额只能为数字', '提现最小金额只能为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42995', '18', '400051', '提现最小金额必须大于0', '提现最小金额必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42996', '18', '400052', '佣金冻结时间范围在0-180之间', '佣金冻结时间范围在0-180之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42997', '18', '400053', '满额分销金额金额必须为数字', '满额分销金额金额必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42998', '18', '400054', '积分抵用比例必须为数字', '积分抵用比例必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('42999', '18', '400055', '积分抵用比例最多两位小数', '积分抵用比例最多两位小数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43', '1', '100042', '退出成功', '退出成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('430', '1', '400363', '请填写虚拟拼团比例', '请填写虚拟拼团比例', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43000', '18', '400056', '积分抵用比例必须在0-1000之间', '积分抵用比例必须在0-1000之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43001', '18', '400057', '积分抵用上限必须为数字', '积分抵用上限必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43002', '18', '400058', '积分抵用上限必须大于等于0', '积分抵用上限必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43003', '18', '400059', '下单赠送积分必须为数字', '下单赠送积分必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43004', '18', '400060', '下单赠送积分必须在0-1000之间', '下单赠送积分必须在0-1000之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43005', '18', '400061', '普通商品未支付取消订单时间必须为数字', '普通商品未支付取消订单时间必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43006', '18', '400062', '活动商品未支付取消订单时间必须为数字', '活动商品未支付取消订单时间必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43007', '18', '400063', '砍价商品未支付取消订单时间必须为数字', '砍价商品未支付取消订单时间必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43008', '18', '400064', '拼团商品未支付取消订单时间必须为数字', '拼团商品未支付取消订单时间必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43009', '18', '400065', '订单发货后自动收货时间必须为数字', '订单发货后自动收货时间必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43010', '18', '400066', '满额包邮金额必须为数字', '满额包邮金额必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43011', '18', '400067', '积分倍数必须大于0', '积分倍数必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43012', '18', '400068', '折扣数必须大于0', '折扣数必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43013', '18', '400069', '积分倍数必须大于0', '积分倍数必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43014', '18', '400070', '折扣数必须大于0', '折扣数必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43015', '18', '400071', '下单赠送经验比率必须为数字', '下单赠送经验比率必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43016', '18', '400072', '下单赠送经验比率必须大于0', '下单赠送经验比率必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43017', '18', '400073', '签到赠送经验必须为数字', '签到赠送经验必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43018', '18', '400074', '签到赠送经验必须大于0', '签到赠送经验必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43019', '18', '400075', '邀请新用户赠送经验必须为数字', '邀请新用户赠送经验必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43020', '18', '400076', '邀请新用户赠送经验必须大于0', '邀请新用户赠送经验必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43021', '18', '400077', '发货人姓名必须为汉字', '发货人姓名必须为汉字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43022', '18', '400078', '发货人姓名长度在2-10位', '发货人姓名长度在2-10位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43023', '18', '400079', '发货人电话必须为数字', '发货人电话必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43024', '18', '400080', '发货人电话请填写有效的手机号', '发货人电话请填写有效的手机号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43025', '18', '400081', '发货人地址只能是汉字、字母、数字', '发货人地址只能是汉字、字母、数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43026', '18', '400082', '发货人地址长度为10-100位', '发货人地址长度为10-100位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43027', '18', '400083', '电子面单打印机编号必须为数字、字母', '电子面单打印机编号必须为数字、字母', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43028', '18', '400084', '电子面单打印机编号长度为10-50位', '电子面单打印机编号长度为10-50位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43029', '18', '400085', '客服反馈长度位10-90位', '客服反馈长度位10-90位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43030', '18', '400086', '请填写标签分类名称', '请填写标签分类名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43031', '18', '400087', '请填写标签分类排序', '请填写标签分类排序', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43032', '18', '400088', '标签分类必须为数字', '标签分类必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43033', '18', '400089', '账号只能为数字和字母', '账号只能为数字和字母', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43034', '18', '400090', '限量不能超过商品库存', '限量不能超过商品库存', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43035', '18', '400091', '商品已下架或移入回收站', '商品已下架或移入回收站', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43036', '18', '400092', '占用库存失败', '占用库存失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43037', '18', '400093', '商品已下架或已删除', '商品已下架或已删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43038', '18', '400094', '请选择有效的商品属性', '请选择有效的商品属性', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43039', '18', '400095', '金额不能小于0', '金额不能小于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43040', '18', '400096', '结束时间不能小于今天', '结束时间不能小于今天', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43041', '18', '400097', '您不是付费会员', '您不是付费会员', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43042', '18', '400098', '暂时无法领取', '暂时无法领取', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43043', '18', '400099', '请先配置小票打印开发者', '请先配置小票打印开发者', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43044', '18', '400100', '请填写分类名称', '请填写分类名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43045', '18', '400101', '该分类已存在', '该分类已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43046', '18', '400102', '请先删除子分类', '请先删除子分类', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43047', '18', '400103', '分类不存在', '分类不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43048', '18', '400104', '文件名称不能为空', '文件名称不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43049', '18', '400105', '该分类有下级分类,无法修改上级', '该分类有下级分类,无法修改上级', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43050', '18', '400106', '备注不能为空', '备注不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43051', '18', '400107', '请输入姓名', '请输入姓名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43052', '18', '400108', '请输入提现金额', '请输入提现金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43053', '18', '400109', '请输入支付宝账号', '请输入支付宝账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43054', '18', '400110', '请输入微信账号', '请输入微信账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43055', '18', '400111', '请输入银行卡号', '请输入银行卡号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43056', '18', '400112', '请输入开户行', '请输入开户行', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43057', '18', '400113', '拒绝理由不能为空', '拒绝理由不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43058', '18', '400114', '不能重复收货', '不能重复收货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43059', '18', '400115', '请先发货或者送货', '请先发货或者送货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43060', '18', '400116', '收货失败,请稍候再试', '收货失败,请稍候再试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43061', '18', '400117', '收货成功', '收货成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43062', '18', '400118', '订单不存在', '订单不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43063', '18', '400119', '用户信息不存在', '用户信息不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43064', '18', '400120', '快递单号不存在', '快递单号不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43065', '18', '400121', '打印成功', '打印成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43066', '18', '400122', '打印失败', '打印失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43067', '18', '400123', '快递公司编号缺失', '快递公司编号缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43068', '18', '400124', '请配置腾讯地图KEY', '请配置腾讯地图KEY', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43069', '18', '400125', '请选择门店位置', '请选择门店位置', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43070', '18', '400126', '添加的核销员用户已存在', '添加的核销员用户已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43071', '18', '400127', '请选择所属提货点', '请选择所属提货点', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43072', '18', '400128', '请填写核销员名称', '请填写核销员名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43073', '18', '400129', '请填写核销员电话', '请填写核销员电话', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43074', '18', '400130', '核销员添加成功', '核销员添加成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43075', '18', '400131', '核销员添加失败', '核销员添加失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43076', '18', '400132', '请填写手机号', '请填写手机号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43077', '18', '400133', '请填写账号', '请填写账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43078', '18', '400134', '请填写密码', '请填写密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43079', '18', '400135', '请填写短信签名', '请填写短信签名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43080', '18', '400136', '短信签名最长为8位', '短信签名最长为8位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43081', '18', '400137', '请填写验证码', '请填写验证码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43082', '18', '400138', '请填写域名', '请填写域名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43083', '18', '400139', '登录成功', '登录成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43084', '18', '400140', '账号或密码错误', '账号或密码错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43085', '18', '400141', '请先填写短信配置', '请先填写短信配置', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43086', '18', '400142', '请输入模板名称', '请输入模板名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43087', '18', '400143', '请输入模板内容', '请输入模板内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43088', '18', '400144', '售后订单状态不支持该操作', '售后订单状态不支持该操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43089', '18', '400145', '修改退款状态成功', '修改退款状态成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43090', '18', '400146', '请输入退款金额', '请输入退款金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43091', '18', '400147', '已退完支付金额,不能再退款了', '已退完支付金额,不能再退款了', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43092', '18', '400148', '退款金额大于支付金额,请修改退款金额', '退款金额大于支付金额,请修改退款金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43093', '18', '400149', '退款成功', '退款成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43094', '18', '400150', '退款失败', '退款失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43095', '18', '400151', '验证成功', '验证成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43096', '18', '400152', '核销成功', '核销成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43097', '18', '400153', '核销订单未查到', '核销订单未查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43098', '18', '400154', '核销失败', '核销失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43099', '18', '400155', '订单金额必须填写', '订单金额必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('431', '1', '400364', '虚拟参团人数不能大于成团人数', '虚拟参团人数不能大于成团人数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43100', '18', '400156', '请选择需要删除的订单', '请选择需要删除的订单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43101', '18', '400157', '您选择的的订单存在用户未删除的订单', '您选择的的订单存在用户未删除的订单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43102', '18', '400158', '请选择发货商品', '请选择发货商品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43103', '18', '400159', '请重新选择发货商品或发货件数', '请重新选择发货商品或发货件数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43104', '18', '400160', '订单已删除无法退积分', '订单已删除无法退积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43105', '18', '400161', '请输入积分', '请输入积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43106', '18', '400162', '已退完积分', '已退完积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43107', '18', '400163', '退积分大于支付积分,请修改退积分', '退积分大于支付积分,请修改退积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43108', '18', '400164', '退积分成功', '退积分成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43109', '18', '400165', '退积分失败', '退积分失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43110', '18', '400166', '请填写开票号', '请填写开票号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43111', '18', '400167', '请填写正确的开票号', '请填写正确的开票号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43112', '18', '400168', '请上传文件', '请上传文件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43113', '18', '400169', '回复成功', '回复成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43114', '18', '400170', '注册成功', '注册成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43115', '18', '400171', '注册失败', '注册失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43116', '18', '400172', '登录失败', '登录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43117', '18', '400173', '获取套餐列表失败', '获取套餐列表失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43118', '18', '400174', '获取支付码失败', '获取支付码失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43119', '18', '400175', '请先开通短信服务', '请先开通短信服务', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43120', '18', '400176', '请先开通物流查询服务', '请先开通物流查询服务', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43121', '18', '400177', '请先开通电子面单打印服务', '请先开通电子面单打印服务', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43122', '18', '400178', '请先开通商品采集服务', '请先开通商品采集服务', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43123', '18', '400179', '请设置短信签名', '请设置短信签名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43124', '18', '400180', '修改短信签名成功', '修改短信签名成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43125', '18', '400181', '默认模板不能删除', '默认模板不能删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43126', '18', '400182', '管理员信息读取失败', '管理员信息读取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43127', '18', '400183', '密码太过简单,请输入较为复杂的密码', '密码太过简单,请输入较为复杂的密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43128', '18', '400184', '协议类型不存在', '协议类型不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43129', '18', '400185', '清除成功', '清除成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43130', '18', '400186', '清除失败', '清除失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43131', '18', '400187', '请输入名称', '请输入名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43132', '18', '400188', '请不要重复添加', '请不要重复添加', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43133', '18', '400189', '添加数据成功', '添加数据成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43134', '18', '400190', '请输入开始时间', '请输入开始时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43135', '18', '400191', '请输入持续时间', '请输入持续时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43136', '18', '400192', '请输入0-23点之前的整点数', '请输入0-23点之前的整点数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43137', '18', '400193', '请输入1-24点之前的整点数', '请输入1-24点之前的整点数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43138', '18', '400194', '开始时间+持续时间不能大于24小时', '开始时间+持续时间不能大于24小时', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43139', '18', '400195', '时段已占用', '时段已占用', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43140', '18', '400196', '请输入签到赠送积分', '请输入签到赠送积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43141', '18', '400197', '请输入大于等于0的整数', '请输入大于等于0的整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43142', '18', '400198', '请填写按钮名称', '请填写按钮名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43143', '18', '400199', '没有查到此身份', '没有查到此身份', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43144', '18', '400200', '请输入等级名称', '请输入等级名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43145', '18', '400201', '请输入等级', '请输入等级', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43146', '18', '400202', '请选择等级图标', '请选择等级图标', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43147', '18', '400203', '二级返佣比例不能大于一级', '二级返佣比例不能大于一级', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43148', '18', '400204', '当前等级已存在', '当前等级已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43149', '18', '400205', '添加等级成功', '添加等级成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43150', '18', '400206', '编辑的等级不存在', '编辑的等级不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43151', '18', '400207', '请输入任务名称', '请输入任务名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43152', '18', '400208', '请选择任务类型', '请选择任务类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43153', '18', '400209', '请输入限定数量', '请输入限定数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43154', '18', '400210', '添加任务成功', '添加任务成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43155', '18', '400211', '编辑的任务不存在', '编辑的任务不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43156', '18', '400212', '获取推广二维码失败,请检查您的微信配置', '获取推广二维码失败,请检查您的微信配置', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43157', '18', '400213', '上级推广人不能为自己', '上级推广人不能为自己', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43158', '18', '400214', '用户不存在', '用户不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43159', '18', '400215', '上级用户不存在', '上级用户不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43160', '18', '400216', '当前推广人已经是所选人', '当前推广人已经是所选人', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43161', '18', '400217', '上级推广人不能为自己下级', '上级推广人不能为自己下级', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43162', '18', '400218', '赠送成功', '赠送成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43163', '18', '400219', '赠送失败', '赠送失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43164', '18', '400220', '请输入身份名称', '请输入身份名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43165', '18', '400221', '请选择最少一个权限', '请选择最少一个权限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43166', '18', '400222', '添加身份成功', '添加身份成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43167', '18', '400223', '添加身份失败', '添加身份失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43168', '18', '400224', '缺少APPID', '缺少APPID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43169', '18', '400225', '请先设置空间域名', '请先设置空间域名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43170', '18', '400226', '格式错误,请输入格式为:http://域名', '格式错误,请输入格式为:http://域名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43171', '18', '400227', '未有正在使用的存储空间', '未有正在使用的存储空间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43172', '18', '400228', '切换云存储成功,请检查是否开启使用了存储空间', '切换云存储成功,请检查是否开启使用了存储空间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43173', '18', '400229', '切换本地存储成功', '切换本地存储成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43174', '18', '400230', '请输入模板编号', '请输入模板编号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43175', '18', '400231', '请输入模板编号已存在,请重新输入', '请输入模板编号已存在,请重新输入', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43176', '18', '400232', '请输入模板ID', '请输入模板ID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43177', '18', '400233', '请输入模板名', '请输入模板名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43178', '18', '400234', '请输入回复内容', '请输入回复内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43179', '18', '400235', '添加模板消息成功', '添加模板消息成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43180', '18', '400236', '请先配置小程序appid、appSecret等参数', '请先配置小程序appid、appSecret等参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43181', '18', '400237', '二维码生成失败', '二维码生成失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43182', '18', '400238', '请添加至少一个按钮', '请添加至少一个按钮', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43183', '18', '400239', '请输入关键字', '请输入关键字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43184', '18', '400240', '请选择回复类型', '请选择回复类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43185', '18', '400241', '回复类型有误', '回复类型有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43186', '18', '400242', '回复消息参数有误', '回复消息参数有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43187', '18', '400243', '请添加图文', '请添加图文', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43188', '18', '400244', '标题不能为空', '标题不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43189', '18', '400245', '作者不能为空', '作者不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43190', '18', '400246', '正文不能为空', '正文不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43191', '18', '400247', '摘要不能为空', '摘要不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43192', '18', '400248', '请先配置微信公众号appid、appSecret等参数', '请先配置微信公众号appid、appSecret等参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43193', '18', '400249', '模版消息一键设置成功', '模版消息一键设置成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43194', '18', '400250', '请选择用户', '请选择用户', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43195', '18', '400251', '该用户没有绑定手机号,请手动填写', '该用户没有绑定手机号,请手动填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43196', '18', '400252', '手机号格式错误', '手机号格式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43197', '18', '400253', '客服已存在', '客服已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43198', '18', '400254', '请输入账号', '请输入账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43199', '18', '400255', '账号必须为数字或者字母的组合4-30位', '账号必须为数字或者字母的组合4-30位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('432', '1', '400365', '虚拟参团人数不能大于成团人数', '虚拟参团人数不能大于成团人数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43200', '18', '400256', '请输入密码', '请输入密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43201', '18', '400257', '密码必须为数字或者字母的组合6-20位', '密码必须为数字或者字母的组合6-20位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43202', '18', '400258', '该手机号的客服已存在', '该手机号的客服已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43203', '18', '400259', '该客服账号已存在', '该客服账号已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43204', '18', '400260', '客服添加成功', '客服添加成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43205', '18', '400261', '客服添加失败', '客服添加失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43206', '18', '400262', '客服名称不能为空', '客服名称不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43207', '18', '400263', '请输入确认密码', '请输入确认密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43208', '18', '400264', '两次输入的密码不一致', '两次输入的密码不一致', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43209', '18', '400265', '用户不存在,客服将强制禁止登录', '用户不存在,客服将强制禁止登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43210', '18', '400266', '登录的客服不存在', '登录的客服不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43211', '18', '400267', '请先填写客服账号和密码再尝试进入客服平台', '请先填写客服账号和密码再尝试进入客服平台', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43212', '18', '400268', '反馈内容不存在', '反馈内容不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43213', '18', '400269', '话术不能重复添加', '话术不能重复添加', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43214', '18', '400270', '创建话术成功', '创建话术成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43215', '18', '400271', '创建话术失败', '创建话术失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43216', '18', '400272', '删除的话术不存在', '删除的话术不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43217', '18', '400273', '系统分类不能删除', '系统分类不能删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43218', '18', '400274', '请输入配置名称', '请输入配置名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43219', '18', '400275', '请输入字段名称', '请输入字段名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43220', '18', '400276', '请输入配置简介', '请输入配置简介', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43221', '18', '400277', '请输入文本框的宽度', '请输入文本框的宽度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43222', '18', '400278', '请输入正确的文本框的宽度', '请输入正确的文本框的宽度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43223', '18', '400279', '请输入多行文本框的宽度', '请输入多行文本框的宽度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43224', '18', '400280', '请输入多行文本框的高度', '请输入多行文本框的高度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43225', '18', '400281', '请输入正确的多行文本框的宽度', '请输入正确的多行文本框的宽度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43226', '18', '400282', '请输入正确的多行文本框的宽度', '请输入正确的多行文本框的宽度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43227', '18', '400283', '请输入配置参数', '请输入配置参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43228', '18', '400284', '添加配置成功', '添加配置成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43229', '18', '400285', '一二级返佣比例不能大于100%', '一二级返佣比例不能大于100%', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43230', '18', '400286', '分销海报不能多于5张', '分销海报不能多于5张', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43231', '18', '400287', '提现最低金额只能为数字', '提现最低金额只能为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43232', '18', '400288', '满额分销最低金额不能为空', '满额分销最低金额不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43233', '18', '400289', '满额分销最低金额不能小于0', '满额分销最低金额不能小于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43234', '18', '400290', '绑定有效期请填写正整数', '绑定有效期请填写正整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43235', '18', '400291', '请输入标题', '请输入标题', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43236', '18', '400292', '添加配置分类成功', '添加配置分类成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43237', '18', '400293', '存在下级配置,无法删除', '存在下级配置,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43238', '18', '400294', '字段至少存在一个', '字段至少存在一个', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43239', '18', '400295', '添加数据组成功', '添加数据组成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43240', '18', '400296', '数据关键字已存在', '数据关键字已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43241', '18', '400297', '字段不能为空', '字段不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43242', '18', '400298', '不能大于四个', '不能大于四个', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43243', '18', '400299', '签到天数配置不能大于7天', '签到天数配置不能大于7天', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43244', '18', '400300', '关联成功', '关联成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43245', '18', '400301', '关联失败', '关联失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43246', '18', '400302', '数据缓存刷新成功', '数据缓存刷新成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43247', '18', '400303', '数据缓存刷新失败', '数据缓存刷新失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43248', '18', '400304', '请输入需要更换的域名', '请输入需要更换的域名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43249', '18', '400305', '域名不合法', '域名不合法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43250', '18', '400306', '替换成功', '替换成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43251', '18', '400307', '初始化完成', '初始化完成', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43252', '18', '400308', '备份文件可能已经损坏,请检查', '备份文件可能已经损坏,请检查', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43253', '18', '400309', '还原数据出错', '还原数据出错', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43254', '18', '400310', '正在还原...', '正在还原...', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43255', '18', '400311', '还原完成', '还原完成', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43256', '18', '400312', '权益编辑成功', '权益编辑成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43257', '18', '400313', '卡片生成成功', '卡片生成成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43258', '18', '400314', '手机号已经存在', '手机号已经存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43259', '18', '400315', '请输入正确的身份证', '请输入正确的身份证', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43260', '18', '400316', '请选择分组', '请选择分组', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43261', '18', '400317', '请选择标签', '请选择标签', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43262', '18', '400318', '加入消息队列成功', '加入消息队列成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43263', '18', '400319', '注销成功', '注销成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43264', '18', '400320', '拒绝注销', '拒绝注销', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43265', '18', '400321', '请输入分组名称', '请输入分组名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43266', '18', '400322', '会员标签不能为空', '会员标签不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43267', '18', '400323', '该分类下有标签,请先删除标签', '该分类下有标签,请先删除标签', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43268', '18', '400324', '请输入等级名称', '请输入等级名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43269', '18', '400325', '请输入等级', '请输入等级', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43270', '18', '400326', '请输入等级说明', '请输入等级说明', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43271', '18', '400327', '请上传等级图标', '请上传等级图标', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43272', '18', '400328', '请上传等级背景图标', '请上传等级背景图标', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43273', '18', '400329', '请输入升级经验值', '请输入升级经验值', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43274', '18', '400330', '授权成功,写入数据库失败,请检查数据库链接配置', '授权成功,写入数据库失败,请检查数据库链接配置', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43275', '18', '400331', '请填写公司名称', '请填写公司名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43276', '18', '400332', '请填写授权域名', '请填写授权域名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43277', '18', '400333', '请填写手机号码', '请填写手机号码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43278', '18', '400334', '请填写订单id', '请填写订单id', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43279', '18', '400335', '申请授权成功', '申请授权成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43280', '18', '400336', '验证码错误', '验证码错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43281', '18', '400337', '请选择商品', '请选择商品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43282', '18', '400338', '请输入商品名称', '请输入商品名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43283', '18', '400339', '请选择背景图', '请选择背景图', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43284', '18', '400340', '请输入直播价格', '请输入直播价格', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43285', '18', '400341', '直播价格必须大于0', '直播价格必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43286', '18', '400342', '请输入直播间名称', '请输入直播间名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43287', '18', '400343', '请选择背景图', '请选择背景图', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43288', '18', '400344', '请选择分享图', '请选择分享图', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43289', '18', '400345', '请选择主播', '请选择主播', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43290', '18', '400346', '请选择直播开始、结束时间', '请选择直播开始、结束时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43291', '18', '400347', '请填写活动简介', '请填写活动简介', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43292', '18', '400348', '请填写单位', '请填写单位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43293', '18', '400349', '请选择商品轮播图', '请选择商品轮播图', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43294', '18', '400350', '您设置得商品个数超出系统限制', '您设置得商品个数超出系统限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43295', '18', '400351', '模板不存在', '模板不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43296', '18', '400352', '请输入页面名称', '请输入页面名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43297', '18', '400353', '请选择活动时间段', '请选择活动时间段', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43298', '18', '400354', '请填写购买数量限制', '请填写购买数量限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43299', '18', '400355', '购买数量限制必须大于0', '购买数量限制必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('433', '1', '400366', '请填写单次购买数量', '请填写单次购买数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43300', '18', '400356', '请填写帮砍次数', '请填写帮砍次数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43301', '18', '400357', '帮砍次数必须大于0', '帮砍次数必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43302', '18', '400358', '请填写砍价人数', '请填写砍价人数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43303', '18', '400359', '砍价人数必须大于1', '砍价人数必须大于1', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43304', '18', '400360', '请选择运费模板', '请选择运费模板', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43305', '18', '400361', '请填写商品详情', '请填写商品详情', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43306', '18', '400362', '请选择规格', '请选择规格', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43307', '18', '400363', '请填写虚拟拼团比例', '请填写虚拟拼团比例', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43308', '18', '400364', '虚拟参团人数不能大于成团人数', '虚拟参团人数不能大于成团人数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43309', '18', '400365', '虚拟参团人数不能大于成团人数', '虚拟参团人数不能大于成团人数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43310', '18', '400366', '请填写单次购买数量', '请填写单次购买数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43311', '18', '400367', '单次购买数量必须大于0', '单次购买数量必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43312', '18', '400368', '请填写成团人数', '请填写成团人数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43313', '18', '400369', '拼团人数不能小于2人', '拼团人数不能小于2人', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43314', '18', '400370', '请填写成团有效期', '请填写成团有效期', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43315', '18', '400371', '成团有效期必须大于0', '成团有效期必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43316', '18', '400372', '请填写优惠券名称', '请填写优惠券名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43317', '18', '400373', '请选择商品分类', '请选择商品分类', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43318', '18', '400374', '请填写优惠券金额', '请填写优惠券金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43319', '18', '400375', '请填写优惠券最小使用金额', '请填写优惠券最小使用金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43320', '18', '400376', '请填写优惠券有效期', '请填写优惠券有效期', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43321', '18', '400377', '请选择秒杀时间段', '请选择秒杀时间段', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43322', '18', '400378', '请填写门店名称', '请填写门店名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43323', '18', '400379', '请填写门店简介', '请填写门店简介', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43324', '18', '400380', '请填写门店电话', '请填写门店电话', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43325', '18', '400381', '请选择提货点logo', '请选择提货点logo', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43326', '18', '400382', '请选择提货点大图', '请选择提货点大图', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43327', '18', '400383', '请选择地址', '请选择地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43328', '18', '400384', '请填写详细地址', '请填写详细地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43329', '18', '400385', '请选择经纬度', '请选择经纬度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43330', '18', '400386', '请选择营业时间', '请选择营业时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43331', '18', '400387', '短信账号必须填写', '短信账号必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43332', '18', '400388', '短信密码必须填写', '短信密码必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43333', '18', '400389', '订单号必须存在', '订单号必须存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43334', '18', '400390', '订单号有误', '订单号有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43335', '18', '400391', '订单号必须为字母和数字', '订单号必须为字母和数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43336', '18', '400392', '订单金额必须填写', '订单金额必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43337', '18', '400393', '订单金额必须为数字', '订单金额必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43338', '18', '400394', '订单金额必须填写', '订单金额必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43339', '18', '400395', '订单金额必须为数字', '订单金额必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43340', '18', '400396', '订单邮费必须填写', '订单邮费必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43341', '18', '400397', '订单邮费必须为数字', '订单邮费必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43342', '18', '400398', '赠送积分必须为数字', '赠送积分必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43343', '18', '400399', '请选择用户头像', '请选择用户头像', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43344', '18', '400400', '请输入公司名称', '请输入公司名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43345', '18', '400401', '添加公司成功', '添加公司成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43346', '18', '400402', '请输入月结账号', '请输入月结账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43347', '18', '400403', '请输入月结密码', '请输入月结密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43348', '18', '400404', '请输入取件网点', '请输入取件网点', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43349', '18', '400405', '缩略图大图尺寸(高)必须为数字', '缩略图大图尺寸(高)必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43350', '18', '400406', '缩略图大图尺寸(高)必须大于等于0', '缩略图大图尺寸(高)必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43351', '18', '400407', '缩略图大图尺寸(宽)必须为数字', '缩略图大图尺寸(宽)必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43352', '18', '400408', '缩略图大图尺寸(宽)必须大于等于0', '缩略图大图尺寸(宽)必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43353', '18', '400409', '缩略图中图尺寸(高)必须为数字', '缩略图中图尺寸(高)必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43354', '18', '400410', '缩略图中图尺寸(高)必须大于等于0', '缩略图中图尺寸(高)必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43355', '18', '400411', '缩略图中图尺寸(宽)必须为数字', '缩略图中图尺寸(宽)必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43356', '18', '400412', '缩略图中图尺寸(宽)必须大于等于0', '缩略图中图尺寸(宽)必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43357', '18', '400413', '缩略图小图尺寸(高)必须为数字', '缩略图小图尺寸(高)必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43358', '18', '400414', '缩略图小图尺寸(高)必须大于等于0', '缩略图小图尺寸(高)必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43359', '18', '400415', '缩略图小图尺寸(宽)必须为数字', '缩略图小图尺寸(宽)必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43360', '18', '400416', '缩略图小图尺寸(宽)必须大于等于0', '缩略图小图尺寸(宽)必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43361', '18', '400417', '水印文字只能是汉字、字母、数字', '水印文字只能是汉字、字母、数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43362', '18', '400418', '水印文字长度为1-10位', '水印文字长度为1-10位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43363', '18', '400419', '水印文字大小必须为数字', '水印文字大小必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43364', '18', '400420', '水印文字大小必须大于等于0', '水印文字大小必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43365', '18', '400421', '水印横坐标偏移量必须为数字', '水印横坐标偏移量必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43366', '18', '400422', '水印横坐标偏移量必须大于等于0', '水印横坐标偏移量必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43367', '18', '400423', '水印纵坐标偏移量必须为数字', '水印纵坐标偏移量必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43368', '18', '400424', '水印纵坐标偏移量必须大于等于0', '水印纵坐标偏移量必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43369', '18', '400425', '该主播已经存在', '该主播已经存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43370', '18', '400426', '请先去小程序认证主播', '请先去小程序认证主播', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43371', '18', '400427', '商品已创建', '商品已创建', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43372', '18', '400428', '审核中或审核失败不允许此操作', '审核中或审核失败不允许此操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43373', '18', '400429', '在审核中或已经审核通过', '在审核中或已经审核通过', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43374', '18', '400430', '审核通过或失败', '审核通过或失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43375', '18', '400431', '商品审核中,无法删除', '商品审核中,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43376', '18', '400432', '该主播不存在', '该主播不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43377', '18', '400433', '开播时间需要在当前时间的10分钟后,并且开始时间不能在6个月后', '开播时间需要在当前时间的10分钟后,并且开始时间不能在6个月后', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43378', '18', '400434', '开播时间和结束时间间隔不得短于30分钟,不得超过24小时', '开播时间和结束时间间隔不得短于30分钟,不得超过24小时', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43379', '18', '400435', '请输入理由', '请输入理由', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43380', '18', '400436', '请选择正确的直播商品', '请选择正确的直播商品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43381', '18', '400437', '直播间状态有误', '直播间状态有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43382', '18', '400438', '奖品不存在', '奖品不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43383', '18', '400439', '写入中奖记录失败', '写入中奖记录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43384', '18', '400440', '请继续参与活动抽奖', '请继续参与活动抽奖', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43385', '18', '400441', '已经领取成功', '已经领取成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43386', '18', '400442', '分销等级不存在', '分销等级不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43387', '18', '400443', '选择的等级不存在', '选择的等级不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43388', '18', '400444', '该等级已存在此类型任务', '该等级已存在此类型任务', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43389', '18', '400445', '不能小于低等级同类型任务限定数量', '不能小于低等级同类型任务限定数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43390', '18', '400446', '不能大于高等级同类型任务限定数量', '不能大于高等级同类型任务限定数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43391', '18', '400447', '解除失败', '解除失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43392', '18', '400448', '代理商佣金比例不能大于事业部佣金比例', '代理商佣金比例不能大于事业部佣金比例', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43393', '18', '400449', '代理商到期时间不能大于事业部到期时间', '代理商到期时间不能大于事业部到期时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43394', '18', '400450', '请填写用户UID', '请填写用户UID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43395', '18', '400451', '管理员信息未查到', '管理员信息未查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43396', '18', '400452', '管理员已经删除', '管理员已经删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43397', '18', '400453', '管理员姓名不能为空', '管理员姓名不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43398', '18', '400454', '该分类有下级分类,无法删除', '该分类有下级分类,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43399', '18', '400455', '该分类下有文章,无法删除', '该分类下有文章,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('434', '1', '400367', '单次购买数量必须大于0', '单次购买数量必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43400', '18', '400456', '请稍后查看', '请稍后查看', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43401', '18', '400457', '默认模板不能删除', '默认模板不能删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43402', '18', '400458', '该模板使用中,无法删除', '该模板使用中,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43403', '18', '400459', '个人中心模板不存在', '个人中心模板不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43404', '18', '400460', '反馈内容没有查到', '反馈内容没有查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43405', '18', '400461', '您修改的话术内容不存在', '您修改的话术内容不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43406', '18', '400462', '短信平台:{:msg}', '短信平台:{:msg}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43407', '18', '400463', '订单商品获取失败,无法打印', '订单商品获取失败,无法打印', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43408', '18', '400464', '小票打印未开启', '小票打印未开启', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43409', '18', '400465', '请先配置小票打印开发者', '请先配置小票打印开发者', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43410', '18', '400466', '请选择图片', '请选择图片', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43411', '18', '400467', '配送员已存在', '配送员已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43412', '18', '400468', '同一个手机号的配送员只能添加一个', '同一个手机号的配送员只能添加一个', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43413', '18', '400469', '配送员名称不能为空', '配送员名称不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43414', '18', '400470', '订单未能查到,不能发货', '订单未能查到,不能发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43415', '18', '400471', '订单已删除,不能发货', '订单已删除,不能发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43416', '18', '400472', '订单已发货请勿重复操作', '订单已发货请勿重复操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43417', '18', '400473', '核销订单不能发货', '核销订单不能发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43418', '18', '400474', '拼团未完成暂不能发货', '拼团未完成暂不能发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43419', '18', '400475', '订单有售后申请请先处理', '订单有售后申请请先处理', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43420', '18', '400476', '快递公司编缺失', '快递公司编缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43421', '18', '400477', '请填写寄件人电话', '请填写寄件人电话', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43422', '18', '400478', '请填写寄件人地址', '请填写寄件人地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43423', '18', '400479', '虚拟发货,无需修改发货信息', '虚拟发货,无需修改发货信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43424', '18', '400480', '未发货,请先发货再修改配送信息', '未发货,请先发货再修改配送信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43425', '18', '400481', '自提订单无法打印', '自提订单无法打印', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43426', '18', '400482', '请先发货', '请先发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43427', '18', '400483', '请先在系统设置中打开单子面单打印开关', '请先在系统设置中打开单子面单打印开关', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43428', '18', '400484', '发票已申请,正在审核打印中', '发票已申请,正在审核打印中', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43429', '18', '400485', '订单已退款', '订单已退款', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43430', '18', '400486', '正在申请退款中', '正在申请退款中', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43431', '18', '400487', '申请失败', '申请失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43432', '18', '400488', '未支付无法退款', '未支付无法退款', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43433', '18', '400489', '回退积分和优惠券失败', '回退积分和优惠券失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43434', '18', '400490', '拼团修改失败', '拼团修改失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43435', '18', '400491', '回退佣金失败', '回退佣金失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43436', '18', '400492', '余额退款失败', '余额退款失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43437', '18', '400493', '购买的优惠券已使用或者已过期', '购买的优惠券已使用或者已过期', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43438', '18', '400494', '回退积分增加失败', '回退积分增加失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43439', '18', '400495', '售后订单不存在', '售后订单不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43440', '18', '400496', '积分已退或者积分为零无法再退', '积分已退或者积分为零无法再退', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43441', '18', '400497', '未支付无法退积分', '未支付无法退积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43442', '18', '400498', '订单退积分失败', '订单退积分失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43443', '18', '400499', '请输入拒绝退款理由', '请输入拒绝退款理由', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43444', '18', '400500', '限制单次购买数量不能大于总购买数量', '限制单次购买数量不能大于总购买数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43445', '18', '400501', '请添加抽奖活动名称', '请添加抽奖活动名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43446', '18', '400502', '请添加抽奖描述等文案', '请添加抽奖描述等文案', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43447', '18', '400503', '活动结束时间必须大于开始时间', '活动结束时间必须大于开始时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43448', '18', '400504', '请添加奖品', '请添加奖品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43449', '18', '400505', '请填写消耗数量', '请填写消耗数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43450', '18', '400506', '商品参与其他活动开启,无法开启预售', '商品参与其他活动开启,无法开启预售', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43451', '18', '400507', '活动结束时间不能小于当前时间', '活动结束时间不能小于当前时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43452', '18', '400508', '活动已结束,请重新添加或复制', '活动已结束,请重新添加或复制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43453', '18', '400509', '添加优惠券成功', '添加优惠券成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43454', '18', '400510', '发布优惠劵成功', '发布优惠劵成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43455', '18', '400511', '砍价最低价不能大于或等于起始金额', '砍价最低价不能大于或等于起始金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43456', '18', '400512', '砍价人数不能大于{:num}人', '砍价人数不能大于{:num}人', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43457', '18', '400513', '使用开始时间不能小于领取开始时间', '使用开始时间不能小于领取开始时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43458', '18', '400514', '使用结束时间不能小于领取结束时间', '使用结束时间不能小于领取结束时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43459', '18', '400515', '优惠券不存在', '优惠券不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43460', '18', '400516', '领取的优惠劵已领完或已过期', '领取的优惠劵已领完或已过期', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43461', '18', '400517', '已领取过该优惠劵', '已领取过该优惠劵', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43462', '18', '400518', '抱歉,优惠券已经领取完了', '抱歉,优惠券已经领取完了', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43463', '18', '400519', '选择用户已拥有该优惠券,请勿重复发放', '选择用户已拥有该优惠券,请勿重复发放', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43464', '18', '400520', '订单已删除', '订单已删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43465', '18', '400521', '订单已发货', '订单已发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43466', '18', '400522', '暂时不支持其他发货类型', '暂时不支持其他发货类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43467', '18', '400523', '请输入送货人姓名', '请输入送货人姓名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43468', '18', '400524', '请输入送货人电话号码', '请输入送货人电话号码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43469', '18', '400525', '请输入送货人信息', '请输入送货人信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43470', '18', '400526', '请输入正确的送货人电话号码', '请输入正确的送货人电话号码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43471', '18', '400527', '请选择电子面单模板', '请选择电子面单模板', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43472', '18', '400528', '电子面单已关闭,请选择其他发货方式', '电子面单已关闭,请选择其他发货方式', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43473', '18', '400529', '发货失败', '发货失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43474', '18', '400530', '订单状态错误', '订单状态错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43475', '18', '400531', '请输入快递单号', '请输入快递单号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43476', '18', '400532', '请先发货再修改配送信息', '请先发货再修改配送信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43477', '18', '400533', '商品不存在', '商品不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43478', '18', '400534', '您查看的积分商品已被删除', '您查看的积分商品已被删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43479', '18', '400535', '请添加商品', '请添加商品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43480', '18', '400536', '添加抽奖活动失败', '添加抽奖活动失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43481', '18', '400537', '抽奖活动不存在', '抽奖活动不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43482', '18', '400538', '请填写奖品名称', '请填写奖品名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43483', '18', '400539', '请选择奖品图片', '请选择奖品图片', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43484', '18', '400540', '请填写奖品中奖权重', '请填写奖品中奖权重', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43485', '18', '400541', '请选择奖品类型', '请选择奖品类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43486', '18', '400542', '请填写奖品赠送{:type}数', '请填写奖品赠送{:type}数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43487', '18', '400543', '请选择优惠券', '请选择优惠券', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43488', '18', '400544', '生成新订单失败', '生成新订单失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43489', '18', '400545', '修改原来订单商品拆分状态失败', '修改原来订单商品拆分状态失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43490', '18', '400546', '新增拆分订单商品信息失败', '新增拆分订单商品信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43491', '18', '400547', '保存新订单商品信息失败', '保存新订单商品信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43492', '18', '400548', '协议类型缺失', '协议类型缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43493', '18', '400549', '请填写协议名称', '请填写协议名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43494', '18', '400550', '请填写协议内容', '请填写协议内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43495', '18', '400551', '该类型协议已经存在', '该类型协议已经存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43496', '18', '400552', '临时二维码获取错误', '临时二维码获取错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43497', '18', '400553', '永久二维码获取错误', '永久二维码获取错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43498', '18', '400554', '请先配置接口密钥', '请先配置接口密钥', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43499', '18', '400555', '无法创建文件夹,请检查您的上传目录权限', '无法创建文件夹,请检查您的上传目录权限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('435', '1', '400368', '请填写成团人数', '请填写成团人数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43500', '18', '400556', '商品参数错误', '商品参数错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43501', '18', '400557', '上传方式错误', '上传方式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43502', '18', '400558', '格式错误', '格式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43503', '18', '400559', '图片流获取失败', '图片流获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43504', '18', '400560', '商品详情保存失败', '商品详情保存失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43505', '18', '400561', '关联优惠券失败', '关联优惠券失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43506', '18', '400562', '缺少商品ID', '缺少商品ID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43507', '18', '400563', '缺少用户UID', '缺少用户UID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43508', '18', '400564', '缺少订单ID', '缺少订单ID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43509', '18', '400565', '暂不支持该类型记录', '暂不支持该类型记录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43510', '18', '400566', '添加商品记录失败', '添加商品记录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43511', '18', '400567', '评论时间应小于当前时间', '评论时间应小于当前时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43512', '18', '400568', '添加虚拟评论失败', '添加虚拟评论失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43513', '18', '400569', '回复失败', '回复失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43514', '18', '400570', '请选择限购类型', '请选择限购类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43515', '18', '400571', '限购数量不能小于1', '限购数量不能小于1', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43516', '18', '400572', '一二级返佣相加不能大于商品售价', '一二级返佣相加不能大于商品售价', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43517', '18', '400573', '商品类型不能切换', '商品类型不能切换', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43518', '18', '400574', '请输入规则名称', '请输入规则名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43519', '18', '400575', '请输入属性名称', '请输入属性名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43520', '18', '400576', '请输入正确的属性', '请输入正确的属性', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43521', '18', '400577', '请填写正确的商品信息', '请填写正确的商品信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43522', '18', '400578', '请填写正确的商品价格', '请填写正确的商品价格', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43523', '18', '400579', '请填写正确的商品库存', '请填写正确的商品库存', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43524', '18', '400580', '请填写正确的商品成本价格', '请填写正确的商品成本价格', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43525', '18', '400581', '请上传商品图片', '请上传商品图片', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43526', '18', '400582', '{:name}规格不存在', '{:name}规格不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43527', '18', '400583', '{:name}属性不存在', '{:name}属性不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43528', '18', '400584', '请设置至少一个属性', '请设置至少一个属性', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43529', '18', '400585', '商品参与秒杀活动开启,无法进行此操作', '商品参与秒杀活动开启,无法进行此操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43530', '18', '400586', '商品参与砍价活动开启,无法进行此操作', '商品参与砍价活动开启,无法进行此操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43531', '18', '400587', '商品参与拼团活动开启,无法进行此操作', '商品参与拼团活动开启,无法进行此操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43532', '18', '400588', '会员价格不能为0', '会员价格不能为0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43533', '18', '400589', '虚拟优惠券商品请选择优惠券', '虚拟优惠券商品请选择优惠券', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43534', '18', '400590', '卡号:{:key}密码:{:value},已经添加过,请重新添加卡密', '卡号:{:key}密码:{:value},已经添加过,请重新添加卡密', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43535', '18', '400591', '缺少城市id无法保存', '缺少城市id无法保存', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43536', '18', '400592', '修改的模板不存在', '修改的模板不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43537', '18', '400593', '指定区域邮费添加失败', '指定区域邮费添加失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43538', '18', '400594', '管理员不存在', '管理员不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43539', '18', '400595', '您已被禁止登录', '您已被禁止登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43540', '18', '400596', '管理员账号已存在', '管理员账号已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43541', '18', '400597', '原始密码错误', '原始密码错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43542', '18', '400598', '请输入新密码', '请输入新密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43543', '18', '400599', '请选择要删除的图片', '请选择要删除的图片', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43544', '18', '400600', '移动失败或不能重复移动到同一分类下', '移动失败或不能重复移动到同一分类下', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43545', '18', '400601', '请求不被允许', '请求不被允许', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43546', '18', '400602', '设置类目不被允许', '设置类目不被允许', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43547', '18', '400603', '请输入正确格式的配置参数', '请输入正确格式的配置参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43548', '18', '400604', '{:name}请输入默认值', '{:name}请输入默认值', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43549', '18', '400605', '{:name}请输入正确url', '{:name}请输入正确url', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43550', '18', '400606', '保存wss证书失败', '保存wss证书失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43551', '18', '400607', '{:name}不能为空', '{:name}不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43552', '18', '400608', '删除的云存储不存在', '删除的云存储不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43553', '18', '400609', '云存储正在使用中,需要启动其他空间才能删除', '云存储正在使用中,需要启动其他空间才能删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43554', '18', '400610', '云空间名称不能重复', '云空间名称不能重复', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43555', '18', '400611', '没有权限', '没有权限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43556', '18', '400612', '替换失败,失败原因:{:msg}', '替换失败,失败原因:{:msg}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43557', '18', '400613', '请先删除改菜单下的子菜单', '请先删除改菜单下的子菜单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43558', '18', '400614', '请填写批次名称', '请填写批次名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43559', '18', '400615', '请填写要生成卡的数量', '请填写要生成卡的数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43560', '18', '400616', '卡片数量只能为正整数', '卡片数量只能为正整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43561', '18', '400617', '单次制卡数量最高不得超过6000张', '单次制卡数量最高不得超过6000张', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43562', '18', '400618', '请填写免费使用天数', '请填写免费使用天数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43563', '18', '400619', '免费使用天数只能为正整数', '免费使用天数只能为正整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43564', '18', '400620', '生成卡失败', '生成卡失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43565', '18', '400621', '会员功能暂未开启', '会员功能暂未开启', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43566', '18', '400622', '请输入会员卡号', '请输入会员卡号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43567', '18', '400623', '请输入领取卡密', '请输入领取卡密', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43568', '18', '400624', '会员卡不存在', '会员卡不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43569', '18', '400625', '会员卡未激活,暂无法使用', '会员卡未激活,暂无法使用', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43570', '18', '400626', '会员卡密码有误', '会员卡密码有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43571', '18', '400627', '会员卡已使用', '会员卡已使用', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43572', '18', '400628', '您已是永久会员,无需再领取,可以将此卡转送亲朋好友,一起享受优惠', '您已是永久会员,无需再领取,可以将此卡转送亲朋好友,一起享受优惠', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43573', '18', '400629', '暂无此类型会员卡', '暂无此类型会员卡', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43574', '18', '400630', '会员权益类型缺失', '会员权益类型缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43575', '18', '400631', '请设置权益名称', '请设置权益名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43576', '18', '400632', '请上传会员权益图标', '请上传会员权益图标', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43577', '18', '400633', '请设置返还积分倍数', '请设置返还积分倍数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43578', '18', '400634', '返还积分倍数不能为负数', '返还积分倍数不能为负数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43579', '18', '400635', '请设置运费折扣', '请设置运费折扣', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43580', '18', '400636', '运费折扣不能为负数', '运费折扣不能为负数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43581', '18', '400637', '请设置签到积分倍数', '请设置签到积分倍数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43582', '18', '400638', '签到积分倍数不能为负数', '签到积分倍数不能为负数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43583', '18', '400639', '请设置线下付款折扣', '请设置线下付款折扣', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43584', '18', '400640', '线下付款不能为负数', '线下付款不能为负数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43585', '18', '400641', '请填写会员卡名称', '请填写会员卡名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43586', '18', '400642', '会员卡类型缺失', '会员卡类型缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43587', '18', '400643', '请填写有效期(天)', '请填写有效期(天)', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43588', '18', '400644', '有效期(天)不能为负数', '有效期(天)不能为负数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43589', '18', '400645', '请填写价格', '请填写价格', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43590', '18', '400646', '价格不能为负数', '价格不能为负数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43591', '18', '400647', '优惠价不能大于原价', '优惠价不能大于原价', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43592', '18', '400648', '地址不存在', '地址不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43593', '18', '400649', '取消原来默认地址失败', '取消原来默认地址失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43594', '18', '400650', '设置默认地址失败', '设置默认地址失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43595', '18', '400651', '地址已存在', '地址已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43596', '18', '400652', '收货地址格式错误', '收货地址格式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43597', '18', '400653', '请登录', '请登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43598', '18', '400654', '登录已过期,请重新登录', '登录已过期,请重新登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43599', '18', '400655', '增加记录失败', '增加记录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('436', '1', '400369', '拼团人数不能小于2人', '拼团人数不能小于2人', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43600', '18', '400656', '记录分享记录失败', '记录分享记录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43601', '18', '400657', '增加用户佣金失败', '增加用户佣金失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43602', '18', '400658', '企业付款到零钱失败,请稍后再试', '企业付款到零钱失败,请稍后再试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43603', '18', '400659', '已经提现', '已经提现', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43604', '18', '400660', '您的提现申请已被拒绝', '您的提现申请已被拒绝', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43605', '18', '400661', '可提现佣金不足', '可提现佣金不足', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43606', '18', '400662', '提现金额不能小于{:money}元', '提现金额不能小于{:money}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43607', '18', '400663', '提现佣金不足{:money}元', '提现佣金不足{:money}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43608', '18', '400664', '提现佣金大于0', '提现佣金大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43609', '18', '400665', '企业微信付款到零钱最低金额为1元', '企业微信付款到零钱最低金额为1元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43610', '18', '400666', '该分组已经存在', '该分组已经存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43611', '18', '400667', '清空用户标签失败', '清空用户标签失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43612', '18', '400668', '设置标签失败', '设置标签失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43613', '18', '400669', '请选择标签分类', '请选择标签分类', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43614', '18', '400670', '该标签已经存在', '该标签已经存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43615', '18', '400671', '修改用户等级信息失败', '修改用户等级信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43616', '18', '400672', '用户等级不存在', '用户等级不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43617', '18', '400673', '用户等级经验必须大于上一等级设置的经验', '用户等级经验必须大于上一等级设置的经验', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43618', '18', '400674', '用户等级经验必须小于下一等级设置的经验', '用户等级经验必须小于下一等级设置的经验', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43619', '18', '400675', '已检测到您设置过的用户等级,此等级不可重复', '已检测到您设置过的用户等级,此等级不可重复', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43620', '18', '400676', '已检测到您设置过该用户等级经验值,经验值不可重复', '已检测到您设置过该用户等级经验值,经验值不可重复', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43621', '18', '400677', '订单未支付', '订单未支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43622', '18', '400678', '佣金转入余额,不能退款', '佣金转入余额,不能退款', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43623', '18', '400679', '已支付的订单记录无法删除', '已支付的订单记录无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43624', '18', '400680', '转入金额不能大于可提现佣金', '转入金额不能大于可提现佣金', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43625', '18', '400681', '写入余额充值失败', '写入余额充值失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43626', '18', '400682', '您选择的充值方式已下架', '您选择的充值方式已下架', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43627', '18', '400683', '充值订单生成失败', '充值订单生成失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43628', '18', '400684', '保存用户信息失败', '保存用户信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43629', '18', '400685', '密码重置失败', '密码重置失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43630', '18', '400686', '增加推广人数失败', '增加推广人数失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43631', '18', '400687', '设置登录类型失败', '设置登录类型失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43632', '18', '400688', '设置推广员失败', '设置推广员失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43633', '18', '400689', '增加用户余额失败', '增加用户余额失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43634', '18', '400690', '减少用户余额失败', '减少用户余额失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43635', '18', '400691', '减少用户佣金失败', '减少用户佣金失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43636', '18', '400692', '增加用户积分失败', '增加用户积分失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43637', '18', '400693', '减少用户积分失败', '减少用户积分失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43638', '18', '400694', '增加用户经验失败', '增加用户经验失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43639', '18', '400695', '减少用户经验失败', '减少用户经验失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43640', '18', '400696', '该分组不存在', '该分组不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43641', '18', '400697', '设置分组失败或无改动', '设置分组失败或无改动', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43642', '18', '400698', '有标签不存在或被删除', '有标签不存在或被删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43643', '18', '400699', '等级不存在或被删除', '等级不存在或被删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43644', '18', '400700', '此用户已有该用户等级,无法再次赠送', '此用户已有该用户等级,无法再次赠送', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43645', '18', '400701', '赠送天数不能为0', '赠送天数不能为0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43646', '18', '400702', '天数输入错误', '天数输入错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43647', '18', '400703', '用户信息储存失败', '用户信息储存失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43648', '18', '400704', '您得ip不再白名单中,请前往腾讯微信公众平台添加ip白名单', '您得ip不再白名单中,请前往腾讯微信公众平台添加ip白名单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43649', '18', '400705', '您填写得appid无效,请检查', '您填写得appid无效,请检查', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43650', '18', '400706', '请输入回复信息内容', '请输入回复信息内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43651', '18', '400707', '请上传回复的图片', '请上传回复的图片', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43652', '18', '400708', '请上传回复的声音', '请上传回复的声音', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43653', '18', '400709', '请选择图文消息', '请选择图文消息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43654', '18', '400710', '对应的uid不存在', '对应的uid不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43655', '18', '400711', '取消关注失败', '取消关注失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43656', '18', '400712', '电子面单模板ID缺失', '电子面单模板ID缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43657', '18', '400713', '快递公司编码缺失', '快递公司编码缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43658', '18', '400714', '寄件人信息缺失', '寄件人信息缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43659', '18', '400715', '收件人信息缺失', '收件人信息缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43660', '18', '400716', '云打印机编号缺失', '云打印机编号缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43661', '18', '400717', '商品数量缺失', '商品数量缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43662', '18', '400718', '获取access_token获取失败', '获取access_token获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43663', '18', '400719', '手机号不能为空', '手机号不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43664', '18', '400720', '模版ID不存在', '模版ID不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43665', '18', '400721', '请先配置accessKey和secretKey', '请先配置accessKey和secretKey', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43666', '18', '400722', '请先配置水印图片', '请先配置水印图片', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43667', '18', '400723', '请先配置水印文字', '请先配置水印文字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43668', '18', '400724', '远程水印图片下载失败', '远程水印图片下载失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43669', '18', '400725', '上传图片不存在', '上传图片不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43670', '18', '400726', '图片流获取失败', '图片流获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43671', '18', '400727', '图片下载失败', '图片下载失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43672', '18', '400728', '必须上传xlsx格式文件', '必须上传xlsx格式文件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43673', '18', '400729', '数据不能为空', '数据不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43674', '18', '400730', '缺少pay_price', '缺少pay_price', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43675', '18', '400731', '退款失败:{:msg}', '退款失败:{:msg}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43676', '18', '400732', '获取微信粉丝信息失败', '获取微信粉丝信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43677', '18', '400733', '您已关闭上传功能', '您已关闭上传功能', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43678', '18', '400734', '文件不可写', '文件不可写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43679', '18', '400735', '时间格式不正确', '时间格式不正确', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43680', '18', '400736', '文件可能损坏,请检查', '文件可能损坏,请检查', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43681', '18', '400737', '修复错误,请重试', '修复错误,请重试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43682', '18', '400738', '请指定要修复的表', '请指定要修复的表', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43683', '18', '400739', '请配置支付证书', '请配置支付证书', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43684', '18', '400740', '只支持两级分类', '只支持两级分类', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43685', '18', '400741', '运费格式错误', '运费格式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43686', '18', '400742', '请检查属性编码或库存数量', '请检查属性编码或库存数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43687', '18', '400743', '同步条数不能超过100', '同步条数不能超过100', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43688', '18', '400744', 'appid或appsecret错误', 'appid或appsecret错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43689', '18', '400745', '父级ID参数类型错误', '父级ID参数类型错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43690', '18', '400746', '分类名称长度不能超过25个字符', '分类名称长度不能超过25个字符', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43691', '18', '400747', '分类图标长度不能超过128个字符', '分类图标长度不能超过128个字符', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43692', '18', '400748', '分类大图长度不能超过200个字符', '分类大图长度不能超过200个字符', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43693', '18', '400749', '排序参数类型错误', '排序参数类型错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43694', '18', '400750', '排序不能小于0', '排序不能小于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43695', '18', '400751', '状态必须是0-1之间的整数', '状态必须是0-1之间的整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43696', '18', '400752', '权益简介不能大于8个字', '权益简介不能大于8个字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43697', '18', '400753', '提现方式最少选一种', '提现方式最少选一种', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43698', '18', '400754', '身份使用中,无法删除', '身份使用中,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43699', '18', '400755', '展示名称不能大于6个字', '展示名称不能大于6个字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('437', '1', '400370', '请填写成团有效期', '请填写成团有效期', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43700', '18', '400756', '推广佣金单价不能小于0', '推广佣金单价不能小于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43701', '18', '400757', '每日推广佣金上限不能小于-1', '每日推广佣金上限不能小于-1', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43702', '18', '400758', '请核对领取方式', '请核对领取方式', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43703', '18', '400759', '请输入优惠券名称', '请输入优惠券名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43704', '18', '400760', '请输入真实姓名', '请输入真实姓名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43705', '18', '400761', '描述内容不能超过120字', '描述内容不能超过120字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43706', '18', '400762', '账号密码必须是在6到32位之间', '账号密码必须是在6到32位之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43707', '18', '400763', '商户号不能为空', '商户号不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43708', '18', '410000', '请输入账号和密码', '请输入账号和密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43709', '18', '410001', '登录成功', '登录成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43710', '18', '410002', '退出成功', '退出成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43711', '18', '410003', '发送验证码失败,请刷新页面重新获取', '发送验证码失败,请刷新页面重新获取', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43712', '18', '410004', '请输入验证码', '请输入验证码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43713', '18', '410005', '验证码输入有误', '验证码输入有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43714', '18', '410006', '验证码已发送', '验证码已发送', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43715', '18', '410007', '验证码发送成功', '验证码发送成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43716', '18', '410008', '验证码发送失败', '验证码发送失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43717', '18', '410009', '请先获取验证码', '请先获取验证码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43718', '18', '410010', '验证码错误', '验证码错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43719', '18', '410011', '密码必须是在6到16位之间', '密码必须是在6到16位之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43720', '18', '410012', '密码太过简单,请输入较为复杂的密码', '密码太过简单,请输入较为复杂的密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43721', '18', '410013', '注册成功', '注册成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43722', '18', '410014', '注册失败', '注册失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43723', '18', '410015', '请输入手机号', '请输入手机号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43724', '18', '410016', '绑定成功', '绑定成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43725', '18', '410017', '绑定失败', '绑定失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43726', '18', '410018', '手机号格式不正确', '手机号格式不正确', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43727', '18', '410019', '登录失败', '登录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43728', '18', '410020', '扫码失败请重新扫描', '扫码失败请重新扫描', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43729', '18', '410021', '二维码已过期请重新扫描', '二维码已过期请重新扫描', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43730', '18', '410022', '授权成功,请绑定手机号', '授权成功,请绑定手机号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43731', '18', '410023', '授权成功', '授权成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43732', '18', '410024', '请先关注公众号', '请先关注公众号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43733', '18', '410025', '账号或密码错误', '账号或密码错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43734', '18', '410026', '请修改您的初始密码,再尝试登录', '请修改您的初始密码,再尝试登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43735', '18', '410027', '您已被禁止登录,请联系管理员', '您已被禁止登录,请联系管理员', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43736', '18', '410028', '手机号已注册', '手机号已注册', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43737', '18', '410029', '您今日发送得短信次数已经达到上限', '您今日发送得短信次数已经达到上限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43738', '18', '410030', '此IP今日发送次数已经达到上限', '此IP今日发送次数已经达到上限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43739', '18', '410031', '短信平台验证码发送失败', '短信平台验证码发送失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43740', '18', '410032', '用户不存在', '用户不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43741', '18', '410033', '修改密码失败', '修改密码失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43742', '18', '410034', '用户登录失败,无法生成新用户,请稍后再试', '用户登录失败,无法生成新用户,请稍后再试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43743', '18', '410035', '用户不存在,无法切换', '用户不存在,无法切换', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43744', '18', '410036', '修改新用户登录类型出错', '修改新用户登录类型出错', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43745', '18', '410037', '请刷新页面或者重新授权', '请刷新页面或者重新授权', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43746', '18', '410038', '获取用户访问token失败', '获取用户访问token失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43747', '18', '410039', '此手机已经绑定,无法多次绑定', '此手机已经绑定,无法多次绑定', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43748', '18', '410040', '您的账号已经绑定过手机号码', '您的账号已经绑定过手机号码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43749', '18', '410041', 'H5已有账号是否绑定此账号上', 'H5已有账号是否绑定此账号上', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43750', '18', '410042', '新手机号和原手机号相同,无需修改', '新手机号和原手机号相同,无需修改', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43751', '18', '410043', '此手机已经注册', '此手机已经注册', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43752', '18', '410044', '用户信息获取失败', '用户信息获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43753', '18', '410045', '请选择收货地址', '请选择收货地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43754', '18', '410046', '地址选择有误', '地址选择有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43755', '18', '410047', '可用积分不足', '可用积分不足', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43756', '18', '410048', '奖品不存在', '奖品不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43757', '18', '410049', '写入中奖记录失败', '写入中奖记录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43758', '18', '410050', '请继续参与活动抽奖', '请继续参与活动抽奖', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43759', '18', '410051', '已经领取成功', '已经领取成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43760', '18', '410052', '请输入收货人信息', '请输入收货人信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43761', '18', '410053', '请输入正确的收货人电话', '请输入正确的收货人电话', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43762', '18', '410054', '抽奖记录不存在', '抽奖记录不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43763', '18', '410055', '该奖品不需要发货', '该奖品不需要发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43764', '18', '410056', '请选择快递公司或输入快递单号', '请选择快递公司或输入快递单号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43765', '18', '410057', '活动不存在或已删除', '活动不存在或已删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43766', '18', '410058', '暂未有该类型活动', '暂未有该类型活动', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43767', '18', '410059', '您暂时无法参与该活动', '您暂时无法参与该活动', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43768', '18', '410060', '活动状态有误,请联系管理员', '活动状态有误,请联系管理员', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43769', '18', '410061', '可用积分不足,没有更多抽奖次数', '可用积分不足,没有更多抽奖次数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43770', '18', '410062', '余额不足,没有更多抽奖次数', '余额不足,没有更多抽奖次数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43771', '18', '410063', '购买商品之后获得更多抽奖次数', '购买商品之后获得更多抽奖次数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43772', '18', '410064', '订单完成评价之后获得更多抽奖次数', '订单完成评价之后获得更多抽奖次数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43773', '18', '410065', '邀请更多好友获取抽奖次数', '邀请更多好友获取抽奖次数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43774', '18', '410066', '抽奖扣除用户积分失败', '抽奖扣除用户积分失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43775', '18', '410067', '抽奖失败,余额不足', '抽奖失败,余额不足', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43776', '18', '410068', '抽奖扣除用户余额失败', '抽奖扣除用户余额失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43777', '18', '410069', '抽奖扣除用户推广获取抽奖次数失败', '抽奖扣除用户推广获取抽奖次数失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43778', '18', '410070', '抽奖减少奖品总数失败', '抽奖减少奖品总数失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43779', '18', '410071', '分销等级不存在', '分销等级不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43780', '18', '410072', '永久二维码获取错误', '永久二维码获取错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43781', '18', '410073', '邀请码无效', '邀请码无效', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43782', '18', '410074', '授权失败,参数有误', '授权失败,参数有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43783', '18', '410075', 'openid获取失败', 'openid获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43784', '18', '410076', '获取session_key失败,请检查您的配置', '获取session_key失败,请检查您的配置', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43785', '18', '410077', '获取会话密匙失败', '获取会话密匙失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43786', '18', '410078', '静默授权失败', '静默授权失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43787', '18', '410079', '获取用户信息失败', '获取用户信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43788', '18', '410080', '更新信息失败', '更新信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43789', '18', '410081', '请上传二维码', '请上传二维码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43790', '18', '410082', '请关注公众号', '请关注公众号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43791', '18', '410083', '新增用户失败', '新增用户失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43792', '18', '410084', '用户关注失败', '用户关注失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43793', '18', '410085', '获取token失败{:msg}', '获取token失败{:msg}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43794', '18', '410086', '配置已更改或token已失效', '配置已更改或token已失效', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43795', '18', '410087', '平台错误:发生异常,请稍后重试', '平台错误:发生异常,请稍后重试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43796', '18', '410088', '企业微信支付到零钱需要支付证书,检测到您没有上传', '企业微信支付到零钱需要支付证书,检测到您没有上传', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43797', '18', '410089', '发起企业支付到零钱失败', '发起企业支付到零钱失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43798', '18', '410090', '无效的token不能查找到用户聊天记录', '无效的token不能查找到用户聊天记录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43799', '18', '410091', '图片上传成功', '图片上传成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('438', '1', '400371', '成团有效期必须大于0', '成团有效期必须大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43800', '18', '410092', '用户uid不再当前聊天用户范围内', '用户uid不再当前聊天用户范围内', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43801', '18', '410093', '请输入订单价格', '请输入订单价格', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43802', '18', '410094', '请去后台售后订单列表处理', '请去后台售后订单列表处理', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43803', '18', '410095', '分类名称不能为空', '分类名称不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43804', '18', '410096', '分类不存在', '分类不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43805', '18', '410097', '添加的内容重复', '添加的内容重复', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43806', '18', '410098', '缺少转接人id', '缺少转接人id', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43807', '18', '410099', '转接成功', '转接成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43808', '18', '410100', '话术没有被查到', '话术没有被查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43809', '18', '410101', '公共话术不能修改', '公共话术不能修改', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43810', '18', '410102', '话术标题内容不能为空', '话术标题内容不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43811', '18', '410103', '已拥有此分组', '已拥有此分组', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43812', '18', '410104', '缺少标签id', '缺少标签id', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43813', '18', '410105', '请填汉字字母或者数字', '请填汉字字母或者数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43814', '18', '410106', '标题长度不能超过50个字', '标题长度不能超过50个字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43815', '18', '410107', '请选择分类', '请选择分类', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43816', '18', '410108', '分类必须为数字', '分类必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43817', '18', '410109', '请填写话术内容', '请填写话术内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43818', '18', '410110', '话术长度不能超过500个字', '话术长度不能超过500个字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43819', '18', '410111', '排序必须为数字', '排序必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43820', '18', '410112', '微信最低提现金额不能小于1元', '微信最低提现金额不能小于1元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43821', '18', '410113', '用户不存在', '用户不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43822', '18', '410114', '提现方式不存在', '提现方式不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43823', '18', '410115', '提现金额输入有误', '提现金额输入有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43824', '18', '410116', '银行卡号输入有误', '银行卡号输入有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43825', '18', '410117', '请输入支付宝账号', '请输入支付宝账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43826', '18', '410118', '请输入银行卡账号', '请输入银行卡账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43827', '18', '410119', '请输入开户行信息', '请输入开户行信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43828', '18', '410120', '申请提现成功', '申请提现成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43829', '18', '410121', '申请提现失败', '申请提现失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43830', '18', '410122', '充值金额不能为0元', '充值金额不能为0元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43831', '18', '410123', '充值方式不支持', '充值方式不支持', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43832', '18', '410124', '充值金额不能低于{:money}', '充值金额不能低于{:money}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43833', '18', '410125', '充值成功', '充值成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43834', '18', '410126', '充值失败', '充值失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43835', '18', '410127', '签到获得{:integral}积分', '签到获得{:integral}积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43836', '18', '410128', '签到失败', '签到失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43837', '18', '410129', '收藏成功', '收藏成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43838', '18', '410130', '收藏失败', '收藏失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43839', '18', '410131', '授权失败', '授权失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43840', '18', '410132', 'unionid不存在', 'unionid不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43841', '18', '410133', '获取用户UID失败', '获取用户UID失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43842', '18', '410134', '请输入昵称或者选择头像', '请输入昵称或者选择头像', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43843', '18', '410135', '注销成功', '注销成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43844', '18', '410136', '暂无客服人员在线,请稍后联系', '暂无客服人员在线,请稍后联系', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43845', '18', '410137', '不能和自己聊天', '不能和自己聊天', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43846', '18', '410138', '您不是客服无法登录', '您不是客服无法登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43847', '18', '410139', '自己不能转接给自己', '自己不能转接给自己', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43848', '18', '410140', '转接客服失败', '转接客服失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43849', '18', '410141', '没有此用户', '没有此用户', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43850', '18', '410142', '客服不存在', '客服不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43851', '18', '410143', '商品未查到', '商品未查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43852', '18', '410144', '请填写开票手机号', '请填写开票手机号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43853', '18', '410145', '请填写发票抬头(开具发票企业名称)', '请填写发票抬头(开具发票企业名称)', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43854', '18', '410146', '请填写正确的发票抬头(开具发票企业名称)', '请填写正确的发票抬头(开具发票企业名称)', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43855', '18', '410147', '请填写发票税号', '请填写发票税号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43856', '18', '410148', '请填写正确的发票税号', '请填写正确的发票税号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43857', '18', '410149', '请填写正确的银行卡号', '请填写正确的银行卡号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43858', '18', '410150', '地址不存在', '地址不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43859', '18', '410151', '收货地址格式错误', '收货地址格式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43860', '18', '410152', '收货地址格式错误或系统未完善当前地址', '收货地址格式错误或系统未完善当前地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43861', '18', '410153', '收货地址格式错误,请重新选择', '收货地址格式错误,请重新选择', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43862', '18', '410154', '请填写详细地址', '请填写详细地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43863', '18', '410155', '名称必须填写', '名称必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43864', '18', '410156', '名称最多不能超过25个字符', '名称最多不能超过25个字符', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43865', '18', '410157', '手机号必须填写', '手机号必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43866', '18', '410158', '手机号格式错误', '手机号格式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43867', '18', '410159', '省必须填写', '省必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43868', '18', '410160', '市必须填写', '市必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43869', '18', '410161', '区/县必须填写', '区/县必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43870', '18', '410162', '详细地址必须填写', '详细地址必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43871', '18', '410163', '请填写反馈内容', '请填写反馈内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43872', '18', '410164', '比例不能大于您的比例', '比例不能大于您的比例', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43873', '18', '410165', '激活成功', '激活成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43874', '18', '410166', '暂无海报', '暂无海报', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43875', '18', '410167', '二维码生成失败', '二维码生成失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43876', '18', '410168', '缺少字体文件Bold', '缺少字体文件Bold', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43877', '18', '410169', '缺少字体文件Normal', '缺少字体文件Normal', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43878', '18', '410170', '生成图片失败', '生成图片失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43879', '18', '410171', '生成图片时,系统错误', '生成图片时,系统错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43880', '18', '410172', '生成海报失败', '生成海报失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43881', '18', '410173', '订单不存在', '订单不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43882', '18', '410174', '订单已支付', '订单已支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43883', '18', '410175', '请填写实际支付金额', '请填写实际支付金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43884', '18', '410176', '实际支付金额不能小于0元', '实际支付金额不能小于0元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43885', '18', '410177', '请填写备注内容', '请填写备注内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43886', '18', '410178', '请先处理售后申请', '请先处理售后申请', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43887', '18', '410179', '用户已取消申请', '用户已取消申请', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43888', '18', '410180', '售后订单状态不支持该操作', '售后订单状态不支持该操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43889', '18', '410181', '退款修改状态错误', '退款修改状态错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43890', '18', '410182', '修改退款状态成功', '修改退款状态成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43891', '18', '410183', '已退完支付金额,不能再退款了', '已退完支付金额,不能再退款了', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43892', '18', '410184', '请输入退款金额', '请输入退款金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43893', '18', '410185', '退款金额大于支付金额,请修改退款金额', '退款金额大于支付金额,请修改退款金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43894', '18', '410186', '退款成功', '退款成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43895', '18', '410187', '退款失败', '退款失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43896', '18', '410188', '请输入核销码或者扫描核销二维码', '请输入核销码或者扫描核销二维码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43897', '18', '410189', '核销成功', '核销成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43898', '18', '410190', '请输入付款金额', '请输入付款金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43899', '18', '410191', '支付金额不能为0元', '支付金额不能为0元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('439', '1', '400372', '请填写优惠券名称', '请填写优惠券名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43900', '18', '410192', '付费会员功能暂未开启', '付费会员功能暂未开启', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43901', '18', '410193', '支付数据生成失败', '支付数据生成失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43902', '18', '410194', '支付订单不存在', '支付订单不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43903', '18', '410195', '微信支付成功', '微信支付成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43904', '18', '410196', '前往支付', '前往支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43905', '18', '410197', '余额支付成功', '余额支付成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43906', '18', '410198', '请传入支付宝支付回调URL', '请传入支付宝支付回调URL', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43907', '18', '410199', '支付宝支付成功', '支付宝支付成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43908', '18', '410200', '订单生成失败', '订单生成失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43909', '18', '410201', '请提交购买的商品', '请提交购买的商品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43910', '18', '410202', '商品不存在,请重新选择商品下单', '商品不存在,请重新选择商品下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43911', '18', '410203', '订单创建成功', '订单创建成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43912', '18', '410204', '收货成功', '收货成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43913', '18', '410205', '收货失败', '收货失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43914', '18', '410206', '快递单号不存在', '快递单号不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43915', '18', '410207', '默认运费模板未配置,无法下单', '默认运费模板未配置,无法下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43916', '18', '410208', '订单已过期,请刷新当前页面', '订单已过期,请刷新当前页面', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43917', '18', '410209', '订单已创建,请点击查看完成支付', '订单已创建,请点击查看完成支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43918', '18', '410210', '订单生成失败,你已经在该团内不能再参加了', '订单生成失败,你已经在该团内不能再参加了', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43919', '18', '410211', '订单生成失败,你已经参加该团了,请先支付订单', '订单生成失败,你已经参加该团了,请先支付订单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43920', '18', '410212', '该团人员已满', '该团人员已满', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43921', '18', '410213', '暂不支持该支付方式,请刷新页面或者联系管理员', '暂不支持该支付方式,请刷新页面或者联系管理员', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43922', '18', '410214', '您购买的商品库存已不足{:cart_num}{:unit_name}', '您购买的商品库存已不足{:cart_num}{:unit_name}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43923', '18', '410215', '该订单已失效', '该订单已失效', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43924', '18', '410216', '支付失败', '支付失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43925', '18', '410217', '支付成功', '支付成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43926', '18', '410218', '支付方式错误', '支付方式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43927', '18', '410219', '订单商品已评价', '订单商品已评价', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43928', '18', '410220', '请为商品评分', '请为商品评分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43929', '18', '410221', '请为商家服务评分', '请为商家服务评分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43930', '18', '410222', '评价失败', '评价失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43931', '18', '410223', '请重新选择退款商品或件数', '请重新选择退款商品或件数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43932', '18', '410224', '当前状态不能取消申请', '当前状态不能取消申请', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43933', '18', '410225', '重选成功', '重选成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43934', '18', '410226', '订单已退款', '订单已退款', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43935', '18', '410227', '使用积分抵扣失败', '使用积分抵扣失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43936', '18', '410228', '会员类型不存在', '会员类型不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43937', '18', '410229', '您已是永久会员无需再购买', '您已是永久会员无需再购买', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43938', '18', '410230', '该会员卡暂时无法购买', '该会员卡暂时无法购买', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43939', '18', '410231', '您已经领取过免费会员', '您已经领取过免费会员', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43940', '18', '410232', '此类型会员卡暂未开售', '此类型会员卡暂未开售', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43941', '18', '410233', '获取购物车信息失败', '获取购物车信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43942', '18', '410234', '您要购买的优惠券已失效,无法购买', '您要购买的优惠券已失效,无法购买', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43943', '18', '410235', '您已获取过该优惠券,无法再次购买', '您已获取过该优惠券,无法再次购买', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43944', '18', '410236', '请刷新后重试', '请刷新后重试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43945', '18', '410237', '暂无库存', '暂无库存', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43946', '18', '410238', '选择的规格库存不足', '选择的规格库存不足', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43947', '18', '410239', '单次购买数量不能大于 {:limit} 件', '单次购买数量不能大于 {:limit} 件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43948', '18', '410240', '该商品限购 {:limit} 件,您已经购买 {:pay_num} 件', '该商品限购 {:limit} 件,您已经购买 {:pay_num} 件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43949', '18', '410241', '选择支付方式有误', '选择支付方式有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43950', '18', '410242', '选择的优惠劵无效', '选择的优惠劵无效', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43951', '18', '410243', '不满足优惠劵的使用条件', '不满足优惠劵的使用条件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43952', '18', '410244', '使用优惠劵失败', '使用优惠劵失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43953', '18', '410245', '请填写姓名和电话', '请填写姓名和电话', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43954', '18', '410246', '营销商品不能使用线下支付', '营销商品不能使用线下支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43955', '18', '410247', '暂无门店无法选择门店自提', '暂无门店无法选择门店自提', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43956', '18', '410248', '订单商品结算失败', '订单商品结算失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43957', '18', '410249', '发票已申请', '发票已申请', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43958', '18', '410250', '正在申请退款中', '正在申请退款中', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43959', '18', '410251', '申请失败', '申请失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43960', '18', '410252', '退款件数大于订单件数', '退款件数大于订单件数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43961', '18', '410253', '该订单已全部拆分', '该订单已全部拆分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43962', '18', '410254', '申请退款失败', '申请退款失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43963', '18', '410255', '存在待处理退款单', '存在待处理退款单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43964', '18', '410256', '该订单无法删除', '该订单无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43965', '18', '410257', '订单已经支付无法取消', '订单已经支付无法取消', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43966', '18', '410258', '拼团商品不能再来一单,请在拼团商品内自行下单', '拼团商品不能再来一单,请在拼团商品内自行下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43967', '18', '410259', '砍价商品不能再来一单,请在砍价商品内自行下单', '砍价商品不能再来一单,请在砍价商品内自行下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43968', '18', '410260', '秒杀商品不能再来一单,请在秒杀商品内自行下单', '秒杀商品不能再来一单,请在秒杀商品内自行下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43969', '18', '410261', '预售商品不能再来一单,请在预售商品内自行下单', '预售商品不能再来一单,请在预售商品内自行下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43970', '18', '410262', '再来一单失败,请重新下单', '再来一单失败,请重新下单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43971', '18', '410263', '该订单无法支付', '该订单无法支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43972', '18', '410264', '订单支付状态有误,无法进行支付', '订单支付状态有误,无法进行支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43973', '18', '410265', '该订单已支付', '该订单已支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43974', '18', '410266', '订单状态错误', '订单状态错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43975', '18', '410267', '此订单不能被核销', '此订单不能被核销', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43976', '18', '410268', '订单有售后申请请先处理', '订单有售后申请请先处理', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43977', '18', '410269', '您无权限核销此订单,请联系管理员', '您无权限核销此订单,请联系管理员', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43978', '18', '410270', '订单已核销', '订单已核销', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43979', '18', '410271', '拼团订单暂未成功无法核销', '拼团订单暂未成功无法核销', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43980', '18', '410272', '核销失败', '核销失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43981', '18', '410273', '发货成功', '发货成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43982', '18', '410274', '无需支付', '无需支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43983', '18', '410275', '获取用户openid失败,无法支付', '获取用户openid失败,无法支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43984', '18', '410276', '网站名称配置未填写,无法支付', '网站名称配置未填写,无法支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43985', '18', '410277', '支付方式不存在', '支付方式不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43986', '18', '410278', '不支持该类型方式', '不支持该类型方式', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43987', '18', '410279', '余额支付失败', '余额支付失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43988', '18', '410280', '暂未开启发票', '暂未开启发票', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43989', '18', '410281', '暂未开启专用发票', '暂未开启专用发票', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43990', '18', '410282', '该发票已经存在', '该发票已经存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43991', '18', '410283', '设置默认发票失败', '设置默认发票失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43992', '18', '410284', '没有此用户,无法检测升级用户等级', '没有此用户,无法检测升级用户等级', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43993', '18', '410285', '检测升级失败', '检测升级失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43994', '18', '410286', '修改订单失败', '修改订单失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43995', '18', '410287', '修改用户信息失败', '修改用户信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43996', '18', '410288', '绑定推广关系失败', '绑定推广关系失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43997', '18', '410289', '天数不能为0', '天数不能为0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43998', '18', '410290', '添加签到数据失败', '添加签到数据失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('43999', '18', '410291', '赠送经验失败', '赠送经验失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44', '1', '100043', '退出失败', '退出失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('440', '1', '400373', '请选择商品分类', '请选择商品分类', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44000', '18', '410292', '请先配置签到天数', '请先配置签到天数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44001', '18', '410293', '已经签到', '已经签到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44002', '18', '410294', '商品不存在', '商品不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44003', '18', '410295', '该商品已下架或删除', '该商品已下架或删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44004', '18', '410296', '该商品库存不足', '该商品库存不足', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44005', '18', '410297', '该商品库存不足{:num}', '该商品库存不足{:num}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44006', '18', '410298', '每人总共限购{:num}件', '每人总共限购{:num}件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44007', '18', '410299', '砍价已结束', '砍价已结束', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44008', '18', '410300', '您不能再发起此件商品砍价', '您不能再发起此件商品砍价', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44009', '18', '410301', '该分享未开启砍价', '该分享未开启砍价', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44010', '18', '410302', '您已经帮砍过此砍价', '您已经帮砍过此砍价', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44011', '18', '410303', '砍价信息没有查到', '砍价信息没有查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44012', '18', '410304', '用户砍价信息未查到', '用户砍价信息未查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44013', '18', '410305', '请选择有效的商品属性', '请选择有效的商品属性', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44014', '18', '410306', '砍价商品不存在', '砍价商品不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44015', '18', '410307', '砍价失败', '砍价失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44016', '18', '410308', '砍价未成功', '砍价未成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44017', '18', '410309', '砍价已支付', '砍价已支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44018', '18', '410310', '您不能再帮砍此件商品', '您不能再帮砍此件商品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44019', '18', '410311', '商品已被删除', '商品已被删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44020', '18', '410312', '拼团不存在或已下架,请手动申请退款', '拼团不存在或已下架,请手动申请退款', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44021', '18', '410313', '每个订单限购{:num}件', '每个订单限购{:num}件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44022', '18', '410314', '未查到拼团信息,无法取消', '未查到拼团信息,无法取消', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44023', '18', '410315', '拼团已到期', '拼团已到期', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44024', '18', '410316', '拼团已完成,无法取消', '拼团已完成,无法取消', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44025', '18', '410317', '每人限购{:num}件', '每人限购{:num}件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44026', '18', '410318', '抽奖不存在', '抽奖不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44027', '18', '410319', '领取成功', '领取成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44028', '18', '410320', '领取失败', '领取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44029', '18', '410321', '活动未开始', '活动未开始', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44030', '18', '410322', '活动已结束', '活动已结束', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44031', '18', '410323', '您已有这张优惠券,请勿重复购买', '您已有这张优惠券,请勿重复购买', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44032', '18', '410324', '请核对快递公司编码', '请核对快递公司编码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44033', '18', '410325', '请选择发票', '请选择发票', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44034', '18', '-1', '系统繁忙,请稍候再试', '系统繁忙,请稍候再试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44035', '18', '43104', 'appid与openid不匹配', 'appid与openid不匹配', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44036', '18', '45009', '达到微信api每日限额上限', '达到微信api每日限额上限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44037', '18', '45008', '图文消息超过限制', '图文消息超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44038', '18', '45007', '语音播放时间超过限制', '语音播放时间超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44039', '18', '45006', '图片链接字段超过限制', '图片链接字段超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44040', '18', '45005', '链接字段超过限制', '链接字段超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44041', '18', '45004', '描述字段超过限制', '描述字段超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44042', '18', '45003', '标题字段超过限制', '标题字段超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44043', '18', '45002', '消息内容超过限制', '消息内容超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44044', '18', '45001', '多媒体文件大小超过限制', '多媒体文件大小超过限制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44045', '18', '44004', '文本消息内容为空', '文本消息内容为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44046', '18', '44003', '图文消息内容为空', '图文消息内容为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44047', '18', '44002', 'POST 的数据包为空', 'POST 的数据包为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44048', '18', '44001', '多媒体文件为空', '多媒体文件为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44049', '18', '43019', '需要将接收者从黑名单中移除', '需要将接收者从黑名单中移除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44050', '18', '43005', '需要好友关系', '需要好友关系', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44051', '18', '43004', '需要接收者关注', '需要接收者关注', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44052', '18', '43003', '需要 HTTPS 请求', '需要 HTTPS 请求', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44053', '18', '43002', '需要 POST 请求', '需要 POST 请求', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44054', '18', '43001', '需要 GET 请求', '需要 GET 请求', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44055', '18', '42007', '用户修改微信密码, accesstoken 和 refreshtoken 失效,需要重新授权', '用户修改微信密码, accesstoken 和 refreshtoken 失效,需要重新授权', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44056', '18', '42003', 'oauth_code 超时', 'oauth_code 超时', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44057', '18', '42002', 'refresh_token 超时', 'refresh_token 超时', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44058', '18', '42001', 'access_token 超时,请检查 access_token 的有效期,请参考基础支持 - 获取 access_token 中,对 access_token 的详细机制说明', 'access_token 超时,请检查 access_token 的有效期,请参考基础支持 - 获取 access_token 中,对 access_token 的详细机制说明', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44059', '18', '41009', '缺少 openid', '缺少 openid', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44060', '18', '41008', '缺少 oauth code', '缺少 oauth code', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44061', '18', '41007', '缺少子菜单数据', '缺少子菜单数据', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44062', '18', '41006', '缺少 media_id 参数', '缺少 media_id 参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44063', '18', '41005', '缺少多媒体文件数据', '缺少多媒体文件数据', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44064', '18', '41004', '缺少 secret 参数', '缺少 secret 参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44065', '18', '41003', '缺少 refresh_token 参数', '缺少 refresh_token 参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44066', '18', '41002', '缺少 appid 参数', '缺少 appid 参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44067', '18', '41001', '缺少 access_token 参数', '缺少 access_token 参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44068', '18', '40163', 'oauth_code已使用', 'oauth_code已使用', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44069', '18', '40155', '请勿添加其他公众号的主页链接', '请勿添加其他公众号的主页链接', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44070', '18', '40137', '不支持的图片格式', '不支持的图片格式', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44071', '18', '40132', '微信号不合法', '微信号不合法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44072', '18', '40125', '无效的appsecret', '无效的appsecret', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44073', '18', '40121', '不合法的 media_id 类型', '不合法的 media_id 类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44074', '18', '40120', '子 button 类型错误', '子 button 类型错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44075', '18', '40119', 'button 类型错误', 'button 类型错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44076', '18', '40118', 'media_id 大小不合法', 'media_id 大小不合法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44077', '18', '40117', '分组名字不合法', '分组名字不合法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44078', '18', '40060', '删除单篇图文时,指定的 article_idx 不合法', '删除单篇图文时,指定的 article_idx 不合法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44079', '18', '40051', '分组名字不合法', '分组名字不合法', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44080', '18', '40050', '不合法的分组 id', '不合法的分组 id', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44081', '18', '40048', '无效的url', '无效的url', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44082', '18', '40039', '不合法的 URL 长度', '不合法的 URL 长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44083', '18', '40035', '不合法的参数', '不合法的参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44084', '18', '40038', '不合法的请求格式', '不合法的请求格式', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44085', '18', '40033', '不合法的请求字符,不能包含 \\uxxxx 格式的字符', '不合法的请求字符,不能包含 \\uxxxx 格式的字符', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44086', '18', '40032', '不合法的 openid 列表长度', '不合法的 openid 列表长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44087', '18', '40031', '不合法的 openid 列表', '不合法的 openid 列表', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44088', '18', '40030', '不合法的 refresh_token', '不合法的 refresh_token', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44089', '18', '40029', '无效的 oauth_code', '无效的 oauth_code', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44090', '18', '40028', '不合法的自定义菜单使用用户', '不合法的自定义菜单使用用户', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44091', '18', '40027', '不合法的子菜单按钮 URL 长度', '不合法的子菜单按钮 URL 长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44092', '18', '40026', '不合法的子菜单按钮 KEY 长度', '不合法的子菜单按钮 KEY 长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44093', '18', '40025', '不合法的子菜单按钮名字长度', '不合法的子菜单按钮名字长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44094', '18', '40024', '不合法的子菜单按钮类型', '不合法的子菜单按钮类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44095', '18', '40023', '不合法的子菜单按钮个数', '不合法的子菜单按钮个数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44096', '18', '40022', '不合法的子菜单级数', '不合法的子菜单级数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44097', '18', '40021', '不合法的菜单版本号', '不合法的菜单版本号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44098', '18', '40020', '不合法的按钮 URL 长度', '不合法的按钮 URL 长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44099', '18', '40019', '不合法的按钮 KEY 长度', '不合法的按钮 KEY 长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('441', '1', '400374', '请填写优惠券金额', '请填写优惠券金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44100', '18', '40018', '不合法的按钮名字长度', '不合法的按钮名字长度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44101', '18', '40017', '不合法的按钮类型', '不合法的按钮类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44102', '18', '40016', '不合法的按钮个数', '不合法的按钮个数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44103', '18', '40015', '不合法的菜单类型', '不合法的菜单类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44104', '18', '40014', '不合法的 access_token ,请开发者认真比对 access_token 的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口', '不合法的 access_token ,请开发者认真比对 access_token 的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44105', '18', '40013', '不合法的 AppID ,请开发者检查 AppID 的正确性,避免异常字符,注意大小写', '不合法的 AppID ,请开发者检查 AppID 的正确性,避免异常字符,注意大小写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44106', '18', '40012', '不合法的缩略图文件大小', '不合法的缩略图文件大小', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44107', '18', '40011', '不合法的视频文件大小', '不合法的视频文件大小', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44108', '18', '40010', '不合法的语音文件大小', '不合法的语音文件大小', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44109', '18', '40009', '不合法的图片文件大小', '不合法的图片文件大小', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44110', '18', '40008', '不合法的消息类型', '不合法的消息类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44111', '18', '40007', '不合法的媒体文件 id', '不合法的媒体文件 id', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44112', '18', '40006', '不合法的文件大小', '不合法的文件大小', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44113', '18', '40005', '不合法的文件类型', '不合法的文件类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44114', '18', '40004', '不合法的媒体文件类型', '不合法的媒体文件类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44115', '18', '40003', '不合法的 OpenID ,请开发者确认 OpenID (该用户)是否已关注公众号,或是否是其他公众号的 OpenID', '不合法的 OpenID ,请开发者确认 OpenID (该用户)是否已关注公众号,或是否是其他公众号的 OpenID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44116', '18', '40002', '不合法的凭证类型', '不合法的凭证类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44117', '18', '40001', '获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口', '获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44118', '18', '200011', '此账号已被封禁,无法操作', '此账号已被封禁,无法操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44119', '18', '200012', '个人模版数已达上限,上限25个', '个人模版数已达上限,上限25个', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44120', '18', '200014', '请检查小程序所属类目', '请检查小程序所属类目', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44121', '18', '选择地址', '选择地址', '选择地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44122', '18', '选择其它地址', '选择其它地址', '选择其它地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44123', '18', '已选商品', '已选商品', '已选商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44124', '18', '清空', '清空', '清空', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44125', '18', '¥', '¥', '¥', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44126', '18', '已售罄', '已售罄', '已售罄', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44127', '18', '已下架', '已下架', '已下架', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44128', '18', '删除', '删除', '删除', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44129', '18', '商品券', '商品券', '商品券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44130', '18', '品类券', '品类券', '品类券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44131', '18', '通用券', '通用券', '通用券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44132', '18', '优惠券', '优惠券', '优惠券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44133', '18', '满', '满', '满', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44134', '18', '元可用', '元可用', '元可用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44135', '18', '无门槛券', '无门槛券', '无门槛券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44136', '18', '领取后', '领取后', '领取后', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44137', '18', '天内可用', '天内可用', '天内可用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44138', '18', '已领取', '已领取', '已领取', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44139', '18', '立即领取', '立即领取', '立即领取', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44140', '18', '购物满', '购物满', '购物满', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44141', '18', '减', '减', '减', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44142', '18', '不限时', '不限时', '不限时', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44143', '18', '秒杀', '秒杀', '秒杀', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44144', '18', '砍价', '砍价', '砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44145', '18', '拼团', '拼团', '拼团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44146', '18', '已售', '已售', '已售', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44147', '18', '立即购买', '立即购买', '立即购买', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44148', '18', '加入购物车', '加入购物车', '加入购物车', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44149', '18', '选规格', '选规格', '选规格', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44150', '18', '跳过', '跳过', '跳过', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44151', '18', '立即体验', '立即体验', '立即体验', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44152', '18', '首页', '首页', '首页', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44153', '18', '搜索', '搜索', '搜索', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44154', '18', '购物车', '购物车', '购物车', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44155', '18', '我的收藏', '我的收藏', '我的收藏', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44156', '18', '个人中心', '个人中心', '个人中心', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44157', '18', '券', '券', '券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44158', '18', '正在加载中', '正在加载中', '正在加载中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44159', '18', '上拉加载更多', '上拉加载更多', '上拉加载更多', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44160', '18', '代付金额', '代付金额', '代付金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44161', '18', '共', '共', '共', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44162', '18', '件商品', '件商品', '件商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44163', '18', '订单包裹', '订单包裹', '订单包裹', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44164', '18', '申请退款中', '申请退款中', '申请退款中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44165', '18', '已退款', '已退款', '已退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44166', '18', '已完成', '已完成', '已完成', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44167', '18', '件退款中', '件退款中', '件退款中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44168', '18', '不支持配送', '不支持配送', '不支持配送', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44169', '18', '不支持自提', '不支持自提', '不支持自提', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44170', '18', '已评价', '已评价', '已评价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44171', '18', '评价', '评价', '评价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44172', '18', '申请退款', '申请退款', '申请退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44173', '18', '查看物流', '查看物流', '查看物流', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44174', '18', '确认收货', '确认收货', '确认收货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44175', '18', '选择付款方式', '选择付款方式', '选择付款方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44176', '18', '支付', '支付', '支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44177', '18', '去付款', '去付款', '去付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44178', '18', '请选择要支付的订单', '请选择要支付的订单', '请选择要支付的订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44179', '18', '余额不足', '余额不足', '余额不足', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44180', '18', '支付中', '支付中', '支付中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44181', '18', '缺少支付参数', '缺少支付参数', '缺少支付参数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44182', '18', '取消支付', '取消支付', '取消支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44183', '18', '支付成功', '支付成功', '支付成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44184', '18', '支付失败', '支付失败', '支付失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44185', '18', '库存', '库存', '库存', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44186', '18', '限量', '限量', '限量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44187', '18', '数量', '数量', '数量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44188', '18', '我要参团', '我要参团', '我要参团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44189', '18', '确定', '确定', '确定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44190', '18', '热门推荐', '热门推荐', '热门推荐', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44191', '18', '最高返佣', '最高返佣', '最高返佣', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44192', '18', '推广享佣金', '推广享佣金', '推广享佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44193', '18', '立即分享', '立即分享', '立即分享', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44194', '18', '发现新版本', '发现新版本', '发现新版本', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44195', '18', '立即升级', '立即升级', '立即升级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44196', '18', '下载进度', '下载进度', '下载进度', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44197', '18', '店小二', '店小二', '店小二', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44198', '18', '暂无记录', '暂无记录', '暂无记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44199', '18', '正在下载海报,请稍后再试', '正在下载海报,请稍后再试', '正在下载海报,请稍后再试', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('442', '1', '400375', '请填写优惠券最小使用金额', '请填写优惠券最小使用金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44200', '18', '海报二维码生成失败', '海报二维码生成失败', '海报二维码生成失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44201', '18', '倒计时', '倒计时', '倒计时', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44202', '18', '天', '天', '天', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44203', '18', '时', '时', '时', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44204', '18', '分', '分', '分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44205', '18', '秒', '秒', '秒', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44206', '18', '砍价成功', '砍价成功', '砍价成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44207', '18', '活动已结束', '活动已结束', '活动已结束', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44208', '18', '已砍至', '已砍至', '已砍至', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44209', '18', '活动进行中', '活动进行中', '活动进行中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44210', '18', '取消活动', '取消活动', '取消活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44211', '18', '继续砍价', '继续砍价', '继续砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44212', '18', '暂无砍价记录', '暂无砍价记录', '暂无砍价记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44213', '18', '人正在参与', '人正在参与', '人正在参与', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44214', '18', '最低', '最低', '最低', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44215', '18', '参与砍价', '参与砍价', '参与砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44216', '18', '砍价列表', '砍价列表', '砍价列表', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44217', '18', '人查看', '人查看', '人查看', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44218', '18', '人分享', '人分享', '人分享', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44219', '18', '人参与', '人参与', '人参与', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44220', '18', '邀请您帮忙砍价', '邀请您帮忙砍价', '邀请您帮忙砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44221', '18', '查看商品', '查看商品', '查看商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44222', '18', '当前', '当前', '当前', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44223', '18', '已砍', '已砍', '已砍', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44224', '18', '还剩', '还剩', '还剩', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44225', '18', '立即参与砍价', '立即参与砍价', '立即参与砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44226', '18', '商品暂无库存', '商品暂无库存', '商品暂无库存', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44227', '18', '邀请好友帮砍价', '邀请好友帮砍价', '邀请好友帮砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44228', '18', '已有', '已有', '已有', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44229', '18', '位好友成功砍价', '位好友成功砍价', '位好友成功砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44230', '18', '帮好友砍一刀', '帮好友砍一刀', '帮好友砍一刀', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44231', '18', '好友已砍价成功', '好友已砍价成功', '好友已砍价成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44232', '18', '我也要参与', '我也要参与', '我也要参与', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44233', '18', '已成功帮助好友砍价', '已成功帮助好友砍价', '已成功帮助好友砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44234', '18', '恭喜您砍价成功,快去支付', '恭喜您砍价成功,快去支付', '恭喜您砍价成功,快去支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44235', '18', '立即支付', '立即支付', '立即支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44236', '18', '抢更多商品', '抢更多商品', '抢更多商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44237', '18', '砍价帮', '砍价帮', '砍价帮', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44238', '18', '砍掉', '砍掉', '砍掉', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44239', '18', '更多', '更多', '更多', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44240', '18', '关闭', '关闭', '关闭', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44241', '18', '点击加载更多', '点击加载更多', '点击加载更多', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44242', '18', '商品详情', '商品详情', '商品详情', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44243', '18', '砍价规则', '砍价规则', '砍价规则', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44244', '18', '您已砍掉', '您已砍掉', '您已砍掉', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44245', '18', '元,听说分享次数越多砍价成功的机会越大哦', '元,听说分享次数越多砍价成功的机会越大哦', '元,听说分享次数越多砍价成功的机会越大哦', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44246', '18', '成功帮砍', '成功帮砍', '成功帮砍', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44247', '18', '您也可以砍价低价拿哦,快去挑选心仪的商品吧', '您也可以砍价低价拿哦,快去挑选心仪的商品吧', '您也可以砍价低价拿哦,快去挑选心仪的商品吧', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44248', '18', '发送给朋友', '发送给朋友', '发送给朋友', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44249', '18', '微信好友', '微信好友', '微信好友', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44250', '18', '微信朋友圈', '微信朋友圈', '微信朋友圈', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44251', '18', '生成海报', '生成海报', '生成海报', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44252', '18', '砍价详情', '砍价详情', '砍价详情', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44253', '18', '分享成功', '分享成功', '分享成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44254', '18', '分享失败', '分享失败', '分享失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44255', '18', '该商品每人限购', '该商品每人限购', '该商品每人限购', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44256', '18', '您的好友', '您的好友', '您的好友', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44257', '18', '邀请您砍价', '邀请您砍价', '邀请您砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44258', '18', '人团', '人团', '人团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44259', '18', '去拼团', '去拼团', '去拼团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44260', '18', '拼团列表', '拼团列表', '拼团列表', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44261', '18', '类型', '类型', '类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44262', '18', '累计销量', '累计销量', '累计销量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44263', '18', '限购', '限购', '限购', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44264', '18', '种规格可选', '种规格可选', '种规格可选', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44265', '18', '已拼', '已拼', '已拼', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44266', '18', '件', '件', '件', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44267', '18', '还差', '还差', '还差', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44268', '18', '人成团', '人成团', '人成团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44269', '18', '去拼单', '去拼单', '去拼单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44270', '18', '查看更多', '查看更多', '查看更多', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44271', '18', '收起', '收起', '收起', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44272', '18', '拼团玩法', '拼团玩法', '拼团玩法', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44273', '18', '开团/参团', '开团/参团', '开团/参团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44274', '18', '邀请好友', '邀请好友', '邀请好友', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44275', '18', '满员发货', '满员发货', '满员发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44276', '18', '用户评价', '用户评价', '用户评价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44277', '18', '好评率', '好评率', '好评率', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44278', '18', '产品介绍', '产品介绍', '产品介绍', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44279', '18', '单独购买', '单独购买', '单独购买', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44280', '18', '立即开团', '立即开团', '立即开团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44281', '18', '请选择', '请选择', '请选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44282', '18', '商品', '商品', '商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44283', '18', '详情', '详情', '详情', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44284', '18', '缺少参数无法查看商品', '缺少参数无法查看商品', '缺少参数无法查看商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44285', '18', '参数错误', '参数错误', '参数错误', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44286', '18', '已选择', '已选择', '已选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44287', '18', '保存成功', '保存成功', '保存成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44288', '18', '保存失败', '保存失败', '保存失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44289', '18', '人拼', '人拼', '人拼', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44290', '18', '剩余', '剩余', '剩余', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44291', '18', '结束', '结束', '结束', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44292', '18', '恭喜您拼团成功', '恭喜您拼团成功', '恭喜您拼团成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44293', '18', '人,拼团失败', '人,拼团失败', '人,拼团失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44294', '18', '拼团中,还差', '拼团中,还差', '拼团中,还差', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44295', '18', '人拼团成功', '人拼团成功', '人拼团成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44296', '18', '邀请好友参团', '邀请好友参团', '邀请好友参团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44297', '18', '再次开团', '再次开团', '再次开团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44298', '18', '取消开团', '取消开团', '取消开团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44299', '18', '查看订单信息', '查看订单信息', '查看订单信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('443', '1', '400376', '请填写优惠券有效期', '请填写优惠券有效期', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44300', '18', '大家都在拼', '大家都在拼', '大家都在拼', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44301', '18', '更多拼团', '更多拼团', '更多拼团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44302', '18', '邀请您参团', '邀请您参团', '邀请您参团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44303', '18', '你不是该团的成员', '你不是该团的成员', '你不是该团的成员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44304', '18', '已抢', '已抢', '已抢', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44305', '18', '抢购中', '抢购中', '抢购中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44306', '18', '未开始', '未开始', '未开始', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44307', '18', '已结束', '已结束', '已结束', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44308', '18', '暂无商品,去看点别的吧', '暂无商品,去看点别的吧', '暂无商品,去看点别的吧', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44309', '18', '即将开始', '即将开始', '即将开始', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44310', '18', '距秒杀结束仅剩', '距秒杀结束仅剩', '距秒杀结束仅剩', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44311', '18', '累计销售', '累计销售', '累计销售', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44312', '18', '收藏', '收藏', '收藏', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44313', '18', '保存到手机', '保存到手机', '保存到手机', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44314', '18', '长按图片可以保存到手机', '长按图片可以保存到手机', '长按图片可以保存到手机', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44315', '18', '抢购详情页', '抢购详情页', '抢购详情页', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44316', '18', '二维码获取失败', '二维码获取失败', '二维码获取失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44317', '18', '请选择属性', '请选择属性', '请选择属性', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44318', '18', '提示:点击图片即可保存至手机相册', '提示:点击图片即可保存至手机相册', '提示:点击图片即可保存至手机相册', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44319', '18', '拼团海报', '拼团海报', '拼团海报', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44320', '18', '砍价海报', '砍价海报', '砍价海报', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44321', '18', '海报生成中', '海报生成中', '海报生成中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44322', '18', '海报图片获取失败', '海报图片获取失败', '海报图片获取失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44323', '18', '海报', '海报', '海报', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44324', '18', '已预定', '已预定', '已预定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44325', '18', '预售价', '预售价', '预售价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44326', '18', '立即预定', '立即预定', '立即预定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44327', '18', '开售时间', '开售时间', '开售时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44328', '18', '预售活动', '预售活动', '预售活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44329', '18', '起', '起', '起', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44330', '18', '划线价', '划线价', '划线价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44331', '18', '开通“超级会员”立省', '开通“超级会员”立省', '开通“超级会员”立省', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44332', '18', '元', '元', '元', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44333', '18', '立即开通', '立即开通', '立即开通', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44334', '18', '预售活动时间', '预售活动时间', '预售活动时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44335', '18', '预售结束后', '预售结束后', '预售结束后', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44336', '18', '天内发货', '天内发货', '天内发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44337', '18', '活动', '活动', '活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44338', '18', '参与秒杀', '参与秒杀', '参与秒杀', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44339', '18', '参与拼团', '参与拼团', '参与拼团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44340', '18', '复制口令', '复制口令', '复制口令', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44341', '18', '复制成功', '复制成功', '复制成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44342', '18', '推荐', '推荐', '推荐', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44343', '18', '缺少经纬度信息无法查看地图', '缺少经纬度信息无法查看地图', '缺少经纬度信息无法查看地图', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44344', '18', '产品库存不足,请选择其它属性', '产品库存不足,请选择其它属性', '产品库存不足,请选择其它属性', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44345', '18', '立即退款', '立即退款', '立即退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44346', '18', '一键改价', '一键改价', '一键改价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44347', '18', '订单备注', '订单备注', '订单备注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44348', '18', '商品总价', '商品总价', '商品总价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44349', '18', '原始邮费', '原始邮费', '原始邮费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44350', '18', '实际支付', '实际支付', '实际支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44351', '18', '退款金额', '退款金额', '退款金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44352', '18', '请填写备注信息', '请填写备注信息', '请填写备注信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44353', '18', '立即修改', '立即修改', '立即修改', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44354', '18', '确认退款', '确认退款', '确认退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44355', '18', '拒绝退款', '拒绝退款', '拒绝退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44356', '18', '取消', '取消', '取消', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44357', '18', '订单号', '订单号', '订单号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44358', '18', '发货方式', '发货方式', '发货方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44359', '18', '发货类型', '发货类型', '发货类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44360', '18', '快递公司', '快递公司', '快递公司', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44361', '18', '快递单号', '快递单号', '快递单号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44362', '18', '顺丰请输入单号 :收件人或寄件人手机号后四位', '顺丰请输入单号 :收件人或寄件人手机号后四位', '顺丰请输入单号 :收件人或寄件人手机号后四位', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44363', '18', '例如:SF000000000000:3941', '例如:SF000000000000:3941', '例如:SF000000000000:3941', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44364', '18', '电子面单', '电子面单', '电子面单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44365', '18', '预览', '预览', '预览', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44366', '18', '寄件人姓名', '寄件人姓名', '寄件人姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44367', '18', '填写寄件人姓名', '填写寄件人姓名', '填写寄件人姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44368', '18', '寄件人电话', '寄件人电话', '寄件人电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44369', '18', '填写寄件人电话', '填写寄件人电话', '填写寄件人电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44370', '18', '寄件人地址', '寄件人地址', '寄件人地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44371', '18', '填写寄件人地址', '填写寄件人地址', '填写寄件人地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44372', '18', '送货人', '送货人', '送货人', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44373', '18', '确认提交', '确认提交', '确认提交', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44374', '18', '发货', '发货', '发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44375', '18', '送货', '送货', '送货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44376', '18', '无需物流', '无需物流', '无需物流', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44377', '18', '手动填写', '手动填写', '手动填写', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44378', '18', '电子面单打印', '电子面单打印', '电子面单打印', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44379', '18', '填写快递单号', '填写快递单号', '填写快递单号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44380', '18', '请选择电子面单', '请选择电子面单', '请选择电子面单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44381', '18', '待付款', '待付款', '待付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44382', '18', '待发货', '待发货', '待发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44383', '18', '待收货', '待收货', '待收货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44384', '18', '待评价', '待评价', '待评价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44385', '18', '售后/退款', '售后/退款', '退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44386', '18', '数据统计', '数据统计', '数据统计', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44387', '18', '今日成交额', '今日成交额', '今日成交额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44388', '18', '昨日成交额', '昨日成交额', '昨日成交额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44389', '18', '本月成交额', '本月成交额', '本月成交额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44390', '18', '今日订单数', '今日订单数', '今日订单数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44391', '18', '昨日订单数', '昨日订单数', '昨日订单数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44392', '18', '本月订单数', '本月订单数', '本月订单数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44393', '18', '详细数据', '详细数据', '详细数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44394', '18', '日期', '日期', '日期', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44395', '18', '订单数', '订单数', '订单数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44396', '18', '成交额', '成交额', '成交额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44397', '18', '立即核销', '立即核销', '立即核销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44398', '18', '查看', '查看', '查看', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44399', '18', '确定要核销此订单吗', '确定要核销此订单吗', '确定要核销此订单吗', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('444', '1', '400377', '请选择秒杀时间段', '请选择秒杀时间段', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44400', '18', '确定核销', '确定核销', '确定核销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44401', '18', '请输入核销码', '请输入核销码', '请输入核销码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44402', '18', '请输入正确的核销码', '请输入正确的核销码', '请输入正确的核销码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44403', '18', '查询中', '查询中', '查询中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44404', '18', '订单', '订单', '订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44405', '18', '订单未备注,点击添加备注信息', '订单未备注,点击添加备注信息', '订单未备注,点击添加备注信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44406', '18', '复制', '复制', '复制', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44407', '18', '件商品,应支付', '件商品,应支付', '件商品,应支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44408', '18', '邮费', '邮费', '邮费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44409', '18', '订单编号', '订单编号', '订单编号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44410', '18', '下单时间', '下单时间', '下单时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44411', '18', '支付状态', '支付状态', '支付状态', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44412', '18', '已支付', '已支付', '已支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44413', '18', '未支付', '未支付', '未支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44414', '18', '支付方式', '支付方式', '支付方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44415', '18', '买家留言', '买家留言', '买家留言', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44416', '18', '支付金额', '支付金额', '支付金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44417', '18', '优惠券抵扣', '优惠券抵扣', '优惠券抵扣', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44418', '18', '运费', '运费', '运费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44419', '18', '实付款', '实付款', '实付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44420', '18', '配送方式', '配送方式', '配送方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44421', '18', '快递', '快递', '快递', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44422', '18', '送货人电话', '送货人电话', '送货人电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44423', '18', '确认付款', '确认付款', '确认付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44424', '18', '去发货', '去发货', '去发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44425', '18', '改价成功', '改价成功', '改价成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44426', '18', '改价失败', '改价失败', '改价失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44427', '18', '请输入备注', '请输入备注', '请输入备注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44428', '18', '退款中', '退款中', '退款中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44429', '18', '部分退款中', '部分退款中', '部分退款中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44430', '18', '件商品,实付款', '件商品,实付款', '件商品,实付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44431', '18', '同意退货', '同意退货', '同意退货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44432', '18', '待用户发货', '待用户发货', '待用户发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44433', '18', '请输入正确的金额', '请输入正确的金额', '请输入正确的金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44434', '18', '今天', '今天', '今天', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44435', '18', '昨天', '昨天', '昨天', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44436', '18', '最近7天', '最近7天', '最近7天', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44437', '18', '本月', '本月', '本月', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44438', '18', '自定义', '自定义', '自定义', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44439', '18', '营业额(元)', '营业额(元)', '营业额(元)', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44440', '18', '订单量(份)', '订单量(份)', '订单量(份)', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44441', '18', '增长率', '增长率', '增长率', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44442', '18', '增长', '增长', '增长', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44443', '18', '单位', '单位', '单位', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44444', '18', '元.', '元.', '元', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44445', '18', '分.', '分.', '分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44446', '18', '固定', '固定', '固定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44447', '18', '指定范围', '指定范围', '指定范围', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44448', '18', '提交时间', '提交时间', '提交时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44449', '18', '原因', '原因', '原因', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44450', '18', '暂无申请记录,快去申请吧!', '暂无申请记录,快去申请吧!', '暂无申请记录,快去申请吧!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44451', '18', '没有更多啦', '没有更多啦', '没有更多啦', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44452', '18', '待审核', '待审核', '待审核', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44453', '18', '审核通过', '审核通过', '审核通过', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44454', '18', '审核未通过', '审核未通过', '审核未通过', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44455', '18', '编辑', '编辑', '编辑', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44456', '18', '重新提交', '重新提交', '重新提交', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44457', '18', '会员优惠价', '会员优惠价', '会员优惠价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44458', '18', '余额支付', '余额支付', '余额支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44459', '18', '可用余额', '可用余额', '可用余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44460', '18', '微信支付', '微信支付', '微信支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44461', '18', '确认', '确认', '确认', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44462', '18', '支付提醒', '支付提醒', '支付提醒', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44463', '18', '线下支付已关闭,请点击确认按钮返回主页', '线下支付已关闭,请点击确认按钮返回主页', '线下支付已关闭,请点击确认按钮返回主页', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44464', '18', '请输入支付金额', '请输入支付金额', '请输入支付金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44465', '18', '正在确认', '正在确认', '正在确认', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44466', '18', '进入商城', '进入商城', '进入商城', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44467', '18', '代理商名称', '代理商名称', '代理商名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44468', '18', '请输入代理商名称', '请输入代理商名称', '请输入代理商名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44469', '18', '用户姓名', '用户姓名', '用户姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44470', '18', '请输入姓名', '请输入姓名', '请输入姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44471', '18', '联系电话', '联系电话', '联系电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44472', '18', '请输入手机号', '请输入手机号', '请输入手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44473', '18', '验证码', '验证码', '验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44474', '18', '填写验证码', '填写验证码', '填写验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44475', '18', '邀请码', '邀请码', '邀请码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44476', '18', '请输入代理商邀请码', '请输入代理商邀请码', '请输入代理商邀请码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44477', '18', '请上传营业执照及行业相关资质证明图片', '请上传营业执照及行业相关资质证明图片', '请上传营业执照及行业相关资质证明图片', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44478', '18', '图片最多可上传10张,图片格式支持JPG、PNG、JPEG', '图片最多可上传10张,图片格式支持JPG、PNG、JPEG', '图片最多可上传10张,图片格式支持JPG、PNG、JPEG', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44479', '18', '上传图片', '上传图片', '上传图片', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44480', '18', '已阅读并同意', '已阅读并同意', '已阅读并同意', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44481', '18', '代理商协议', '代理商协议', '代理商协议', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44482', '18', '提交申请', '提交申请', '提交申请', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44483', '18', '代理商入驻协议', '代理商入驻协议', '代理商入驻协议', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44484', '18', '恭喜,您的资料提交成功!', '恭喜,您的资料提交成功!', '恭喜,您的资料提交成功!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44485', '18', '返回首页', '返回首页', '返回首页', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44486', '18', '恭喜,您的资料通过审核!', '恭喜,您的资料通过审核!', '恭喜,您的资料通过审核!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44487', '18', '您的申请未通过!', '您的申请未通过!', '您的申请未通过!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44488', '18', '重新申请', '重新申请', '重新申请', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44489', '18', '获取验证码', '获取验证码', '获取验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44490', '18', '请输入正确的手机号码', '请输入正确的手机号码', '请输入正确的手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44491', '18', '重新获取', '重新获取', '重新获取', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44492', '18', '请上传营业执照', '请上传营业执照', '请上传营业执照', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44493', '18', '请勾选并同意入驻协议', '请勾选并同意入驻协议', '请勾选并同意入驻协议', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44494', '18', '专题栏', '专题栏', '专题栏', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44495', '18', '暂无数据', '暂无数据', '暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44496', '18', '请输入卡号', '请输入卡号', '请输入卡号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44497', '18', '请输入卡密', '请输入卡密', '请输入卡密', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44498', '18', '确认激活', '确认激活', '确认激活', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44499', '18', 'SVIP会员尊享权', 'SVIP会员尊享权', 'SVIP会员尊享权', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('445', '1', '400378', '请填写门店名称', '请填写门店名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44500', '18', '正在激活', '正在激活', '正在激活', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44501', '18', '已使用', '已使用', '已使用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44502', '18', '永久SVIP会员', '永久SVIP会员', '永久SVIP会员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44503', '18', 'SVIP会员', 'SVIP会员', 'SVIP会员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44504', '18', '到期', '到期', '到期', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44505', '18', '您与', '您与', '您与', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44506', '18', '商城的第', '商城的第', '商城的第', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44507', '18', '天.', '天.', '天.', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44508', '18', '已累积为您节省', '已累积为您节省', '已累积为您节省', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44509', '18', '开通即享会员权益', '开通即享会员权益', '开通即享会员权益', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44510', '18', '续费会员', '续费会员', '续费会员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44511', '18', '开通会员', '开通会员', '开通会员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44512', '18', '有效期至', '有效期至', '有效期至', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44513', '18', '试用', '试用', '试用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44514', '18', '购买即视为同意', '购买即视为同意', '购买即视为同意', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44515', '18', '会员用户协议', '会员用户协议', '会员用户协议', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44516', '18', '点击兑换卡密', '点击兑换卡密', '点击兑换卡密', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44517', '18', '会员优惠券', '会员优惠券', '会员优惠券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44518', '18', 'SVIP商品推荐', 'SVIP商品推荐', 'SVIP商品推荐', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44519', '18', '商城价', '商城价', '商城价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44520', '18', '激活会员卡', '激活会员卡', '激活会员卡', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44521', '18', '支付宝支付', '支付宝支付', '支付宝支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44522', '18', '成功开启0元试用', '成功开启0元试用', '成功开启0元试用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44523', '18', '确认绑定', '确认绑定', '确认绑定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44524', '18', '绑定成功', '绑定成功', '绑定成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44525', '18', '商城客服已离线', '商城客服已离线', '商城客服已离线', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44526', '18', '我要反馈', '我要反馈', '我要反馈', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44527', '18', '请填写内容', '请填写内容', '请填写内容', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44528', '18', '提交', '提交', '提交', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44529', '18', '精品推荐', '精品推荐', '精品推荐', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44530', '18', '热门榜单', '热门榜单', '热门榜单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44531', '18', '首发新品', '首发新品', '首发新品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44532', '18', '促销单品', '促销单品', '促销单品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44533', '18', '预告', '预告', '预告', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44534', '18', '回放', '回放', '回放', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44535', '18', '进行中', '进行中', '进行中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44536', '18', '发送客服', '发送客服', '发送客服', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44537', '18', '客服连接中', '客服连接中', '客服连接中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44538', '18', '连接失败', '连接失败', '连接失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44539', '18', '提示', '提示', '提示', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44540', '18', '客服已下线,是否需要反馈?', '客服已下线,是否需要反馈?', '客服已下线,是否需要反馈?', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44541', '18', '和好友一起分享', '和好友一起分享', '和好友一起分享', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44542', '18', '积分抵扣', '积分抵扣', '积分抵扣', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44543', '18', '已开票', '已开票', '已开票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44544', '18', '未开票', '未开票', '未开票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44545', '18', '发票信息', '发票信息', '发票信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44546', '18', '发票抬头', '发票抬头', '发票抬头', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44547', '18', '发票抬头类型', '发票抬头类型', '发票抬头类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44548', '18', '个人', '个人', '个人', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44549', '18', '企业', '企业', '企业', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44550', '18', '发票类型', '发票类型', '发票类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44551', '18', '电子普通发票', '电子普通发票', '电子普通发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44552', '18', '电子专用发票', '电子专用发票', '电子专用发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44553', '18', '企业税号', '企业税号', '企业税号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44554', '18', '联系信息', '联系信息', '联系信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44555', '18', '真实姓名', '真实姓名', '真实姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44556', '18', '联系邮箱', '联系邮箱', '联系邮箱', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44557', '18', '抬头选择', '抬头选择', '抬头选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44558', '18', '默认', '默认', '默认', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44559', '18', '普通', '普通', '普通', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44560', '18', '专用', '专用', '专用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44561', '18', '您还没有添加发票信息哟', '您还没有添加发票信息哟', '您还没有添加发票信息哟', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44562', '18', '添加新的抬头', '添加新的抬头', '添加新的抬头', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44563', '18', '不开发票', '不开发票', '不开发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44564', '18', '抽奖', '抽奖', '抽奖', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44565', '18', '全选', '全选', '全选', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44566', '18', '属性', '属性', '属性', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44567', '18', '请填写具体地址', '请填写具体地址', '请填写具体地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44568', '18', '省', '省', '省', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44569', '18', '市', '市', '市', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44570', '18', '区', '区', '区', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44571', '18', '添加成功', '添加成功', '添加成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44572', '18', '您已拒绝导入微信地址权限', '您已拒绝导入微信地址权限', '您已拒绝导入微信地址权限', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44573', '18', '是否进入权限管理,调整授权?', '是否进入权限管理,调整授权?', '是否进入权限管理,调整授权?', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44574', '18', '已取消', '已取消', '已取消', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44575', '18', '添加失败', '添加失败', '添加失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44576', '18', '请填写收货人姓名', '请填写收货人姓名', '请填写收货人姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44577', '18', '请选择所在地区', '请选择所在地区', '请选择所在地区', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44578', '18', '请填写详细地址', '请填写详细地址', '请填写详细地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44579', '18', '星', '星', '星', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44580', '18', '商品满足你的期待么?说说你的想法,分享给想买的他们吧', '商品满足你的期待么?说说你的想法,分享给想买的他们吧', '商品满足你的期待么?说说你的想法,分享给想买的他们吧', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44581', '18', '立即评价', '立即评价', '立即评价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44582', '18', '商品质量', '商品质量', '商品质量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44583', '18', '服务态度', '服务态度', '服务态度', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44584', '18', '缺少参数', '缺少参数', '缺少参数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44585', '18', '请填写你对宝贝的心得', '请填写你对宝贝的心得', '请填写你对宝贝的心得', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44586', '18', '正在发布评论', '正在发布评论', '正在发布评论', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44587', '18', '感谢您的评价', '感谢您的评价', '感谢您的评价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44588', '18', '评价完成', '评价完成', '评价完成', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44589', '18', '恭喜您', '恭喜您', '恭喜您', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44590', '18', '获得', '获得', '获得', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44591', '18', '机会', '机会', '机会', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44592', '18', '领取成功', '领取成功', '领取成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44593', '18', '评分', '评分', '评分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44594', '18', '全部', '全部', '全部', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44595', '18', '好评', '好评', '好评', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44596', '18', '中评', '中评', '中评', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44597', '18', '差评', '差评', '差评', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44598', '18', '加载更多', '加载更多', '加载更多', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44599', '18', '千米距离', '千米距离', '千米距离', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('446', '1', '400379', '请填写门店简介', '请填写门店简介', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44600', '18', '搜索商品名称', '搜索商品名称', '搜索商品名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44601', '18', '价格', '价格', '价格', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44602', '18', '销量', '销量', '销量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44603', '18', '新品', '新品', '新品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44604', '18', '已全部加载', '已全部加载', '已全部加载', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44605', '18', '缺少订单号', '缺少订单号', '缺少订单号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44606', '18', '退货件数', '退货件数', '退货件数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44607', '18', '退款类型', '退款类型', '退款类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44608', '18', '退款原因', '退款原因', '退款原因', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44609', '18', '备注说明', '备注说明', '备注说明', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44610', '18', '填写备注信息,100字以内', '填写备注信息,100字以内', '填写备注信息,100字以内', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44611', '18', '仅退款', '仅退款', '仅退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44612', '18', '退货并退款', '退货并退款', '退货并退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44613', '18', '申请成功', '申请成功', '申请成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44614', '18', '请先选择退货商品', '请先选择退货商品', '请先选择退货商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44615', '18', '搜索历史', '搜索历史', '搜索历史', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44616', '18', '热门搜索', '热门搜索', '热门搜索', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44617', '18', '请输入要搜索的商品', '请输入要搜索的商品', '请输入要搜索的商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44618', '18', '正在搜索中', '正在搜索中', '正在搜索中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44619', '18', '中奖记录', '中奖记录', '中奖记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44620', '18', '我的奖品', '我的奖品', '我的奖品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44621', '18', '活动规则', '活动规则', '活动规则', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44622', '18', '昵称', '昵称', '昵称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44623', '18', '序号', '序号', '序号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44624', '18', '奖品名称', '奖品名称', '奖品名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44625', '18', '获奖时间', '获奖时间', '获奖时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44626', '18', '商家暂未上架活动哦', '商家暂未上架活动哦', '商家暂未上架活动哦', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44627', '18', '获取抽奖信息', '获取抽奖信息', '获取抽奖信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44628', '18', '奖品类型', '奖品类型', '奖品类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44629', '18', '立即兑换', '立即兑换', '立即兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44630', '18', '兑换时间', '兑换时间', '兑换时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44631', '18', '暂无中奖记录', '暂无中奖记录', '暂无中奖记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44632', '18', '积分', '积分', '积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44633', '18', '余额', '余额', '余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44634', '18', '红包', '红包', '红包', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44635', '18', '设置收货地址', '设置收货地址', '设置收货地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44636', '18', '暂无门店信息', '暂无门店信息', '暂无门店信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44637', '18', '剩余积分', '剩余积分', '剩余积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44638', '18', '当前积分', '当前积分', '当前积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44639', '18', '开具发票', '开具发票', '开具发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44640', '18', '请填写', '请填写', '请填写', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44641', '18', '配送运费', '配送运费', '配送运费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44642', '18', '会员商品优惠', '会员商品优惠', '会员商品优惠', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44643', '18', '会员运费优惠', '会员运费优惠', '会员运费优惠', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44644', '18', '合计', '合计', '合计', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44645', '18', '使用微信快捷支付', '使用微信快捷支付', '使用微信快捷支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44646', '18', '使用支付宝支付', '使用支付宝支付', '使用支付宝支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44647', '18', '线下支付', '线下支付', '线下支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44648', '18', '使用线下付款', '使用线下付款', '使用线下付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44649', '18', '好友代付', '好友代付', '好友代付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44650', '18', '找微信好友支付', '找微信好友支付', '找微信好友支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44651', '18', '立即使用', '立即使用', '立即使用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44652', '18', '请选择要购买的商品', '请选择要购买的商品', '请选择要购买的商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44653', '18', '发票', '发票', '发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44654', '18', '不使用', '不使用', '不使用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44655', '18', '订单创建成功', '订单创建成功', '订单创建成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44656', '18', '请选择支付方式', '请选择支付方式', '请选择支付方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44657', '18', '请选择收货地址', '请选择收货地址', '请选择收货地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44658', '18', '请填写联系人或联系人电话', '请填写联系人或联系人电话', '请填写联系人或联系人电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44659', '18', '暂无门店,请选择其他方式', '暂无门店,请选择其他方式', '暂无门店,请选择其他方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44660', '18', '请输入', '请输入', '请输入', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44661', '18', '请输入正确的', '请输入正确的', '请输入正确的', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44662', '18', '请上传', '请上传', '请上传', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44663', '18', '订单支付中', '订单支付中', '订单支付中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44664', '18', '请按以上退货信息将商品退回', '请按以上退货信息将商品退回', '请按以上退货信息将商品退回', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44665', '18', '请联系管理员获取退货地址', '请联系管理员获取退货地址', '请联系管理员获取退货地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44666', '18', '待核销', '待核销', '待核销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44667', '18', '核销信息', '核销信息', '核销信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44668', '18', '营业时间', '营业时间', '营业时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44669', '18', '每日', '每日', '每日', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44670', '18', '使用说明', '使用说明', '使用说明', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44671', '18', '可将二维码出示给店员扫描或提供数字核销码', '可将二维码出示给店员扫描或提供数字核销码', '可将二维码出示给店员扫描或提供数字核销码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44672', '18', '可将二维码出示给配送员进行核销', '可将二维码出示给配送员进行核销', '可将二维码出示给配送员进行核销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44673', '18', '查看位置', '查看位置', '查看位置', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44674', '18', '拒绝原因', '拒绝原因', '拒绝原因', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44675', '18', '联系客服', '联系客服', '联系客服', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44676', '18', '商家备注', '商家备注', '商家备注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44677', '18', '收货人', '收货人', '收货人', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44678', '18', '收货地址', '收货地址', '收货地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44679', '18', '配送人姓名', '配送人姓名', '配送人姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44680', '18', '拨打', '拨打', '拨打', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44681', '18', '虚拟发货', '虚拟发货', '虚拟发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44682', '18', '已发货,请注意查收', '已发货,请注意查收', '已发货,请注意查收', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44683', '18', '虚拟备注', '虚拟备注', '虚拟备注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44684', '18', '总代付', '总代付', '总代付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44685', '18', '申请开票', '申请开票', '申请开票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44686', '18', '查看发票', '查看发票', '查看发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44687', '18', '取消订单', '取消订单', '取消订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44688', '18', '立即付款', '立即付款', '立即付款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44689', '18', '批量退款', '批量退款', '批量退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44690', '18', '查看拼团', '查看拼团', '查看拼团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44691', '18', '再次购买', '再次购买', '再次购买', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44692', '18', '取消申请', '取消申请', '取消申请', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44693', '18', '填写退货信息', '填写退货信息', '填写退货信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44694', '18', '查看退货物流', '查看退货物流', '查看退货物流', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44695', '18', '您确认放弃此次申请吗', '您确认放弃此次申请吗', '您确认放弃此次申请吗', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44696', '18', '操作成功', '操作成功', '操作成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44697', '18', '订单信息不存在', '订单信息不存在', '订单信息不存在', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44698', '18', '为保障权益,请收到货确认无误后,再确认收货', '为保障权益,请收到货确认无误后,再确认收货', '为保障权益,请收到货确认无误后,再确认收货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44699', '18', '删除订单', '删除订单', '删除订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('447', '1', '400380', '请填写门店电话', '请填写门店电话', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44700', '18', '确定删除该订单', '确定删除该订单', '确定删除该订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44701', '18', '删除成功', '删除成功', '删除成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44702', '18', '确认取消该订单', '确认取消该订单', '确认取消该订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44703', '18', '订单信息', '订单信息', '订单信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44704', '18', '消费订单', '消费订单', '消费订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44705', '18', '总消费', '总消费', '总消费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44706', '18', '预售', '预售', '预售', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44707', '18', '线下付款,未支付', '线下付款,未支付', '线下付款,未支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44708', '18', '未核销', '未核销', '未核销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44709', '18', '件商品,总金额', '件商品,总金额', '件商品,总金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44710', '18', '查看详情', '查看详情', '查看详情', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44711', '18', '暂无订单', '暂无订单', '暂无订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44712', '18', '缺少订单号无法取消订单', '缺少订单号无法取消订单', '缺少订单号无法取消订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44713', '18', '订单支付成功', '订单支付成功', '订单支付成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44714', '18', '订单支付失败', '订单支付失败', '订单支付失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44715', '18', '暂未支付', '暂未支付', '暂未支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44716', '18', '失败原因', '失败原因', '失败原因', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44717', '18', '重新购买', '重新购买', '重新购买', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44718', '18', '重新支付', '重新支付', '重新支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44719', '18', '赠送优惠券', '赠送优惠券', '赠送优惠券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44720', '18', '有效期', '有效期', '有效期', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44721', '18', '缺少参数无法查看订单支付状态', '缺少参数无法查看订单支付状态', '缺少参数无法查看订单支付状态', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44722', '18', '最多可上传3张', '最多可上传3张', '最多可上传3张', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44723', '18', '请选择产品', '请选择产品', '请选择产品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44724', '18', '该产品没有更多库存了', '该产品没有更多库存了', '该产品没有更多库存了', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44725', '18', '优品推荐', '优品推荐', '优品推荐', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44726', '18', '暂无产品', '暂无产品', '暂无产品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44727', '18', '重新选择', '重新选择', '重新选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44728', '18', '请选择数量', '请选择数量', '请选择数量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44729', '18', '砍价专区·BARGAINING', '砍价专区·BARGAINING', '砍价专区·BARGAINING', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44730', '18', '立即砍价', '立即砍价', '立即砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44731', '18', '拼团活动', '拼团活动', '拼团活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44732', '18', '人拼团成功.', '人拼团成功.', '人拼团成功.', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44733', '18', '人参团', '人参团', '人参团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44734', '18', '拼团价', '拼团价', '拼团价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44735', '18', '已过期', '已过期', '已过期', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44736', '18', '关注', '关注', '关注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44737', '18', '推荐好货', '推荐好货', '推荐好货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44738', '18', '暂无商品', '暂无商品', '暂无商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44739', '18', '限时秒杀', '限时秒杀', '限时秒杀', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44740', '18', '抢', '抢', '抢', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44741', '18', '广告位', '广告位', '广告位', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44742', '18', '精彩内容', '精彩内容', '精彩内容', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44743', '18', '砍价模块,暂无数据', '砍价模块,暂无数据', '砍价模块,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44744', '18', '砍价活动', '砍价活动', '砍价活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44745', '18', '呼朋唤友来砍价', '呼朋唤友来砍价', '呼朋唤友来砍价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44746', '18', '拼团模块,暂无数据', '拼团模块,暂无数据', '拼团模块,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44747', '18', '享超值开团价', '享超值开团价', '享超值开团价', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44748', '18', '优惠券,暂无数据', '优惠券,暂无数据', '优惠券,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44749', '18', '领取今日好券', '领取今日好券', '领取今日好券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44750', '18', '可用', '可用', '可用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44751', '18', '领取', '领取', '领取', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44752', '18', '客服', '客服', '客服', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44753', '18', '商品列表,暂无数据', '商品列表,暂无数据', '商品列表,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44754', '18', '搜索商品', '搜索商品', '搜索商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44755', '18', '暂无图片,请上传图片', '暂无图片,请上传图片', '暂无图片,请上传图片', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44756', '18', '首发新品,暂无数据', '首发新品,暂无数据', '首发新品,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44757', '18', '多个优质商品最新上架', '多个优质商品最新上架', '多个优质商品最新上架', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44758', '18', '暂无新闻,请上传新闻', '暂无新闻,请上传新闻', '暂无新闻,请上传新闻', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44759', '18', '热度 TOP', '热度 TOP', '热度 TOP', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44760', '18', '排行榜、暂无数据', '排行榜、暂无数据', '排行榜、暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44761', '18', '促销单品,暂无数据', '促销单品,暂无数据', '促销单品,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44762', '18', '库存商品优惠促销活动', '库存商品优惠促销活动', '库存商品优惠促销活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44763', '18', '精品推荐,暂无数据', '精品推荐,暂无数据', '精品推荐,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44764', '18', '上百种商品分类任您选择', '上百种商品分类任您选择', '上百种商品分类任您选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44765', '18', '秒杀模块,暂无数据', '秒杀模块,暂无数据', '秒杀模块,暂无数据', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44766', '18', '场', '场', '场', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44767', '18', '暂无数据,请设置', '暂无数据,请设置', '暂无数据,请设置', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44768', '18', '暂无数据,请先添加分类', '暂无数据,请先添加分类', '暂无数据,请先添加分类', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44769', '18', '暂无标题', '暂无标题', '暂无标题', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44770', '18', '诚意推荐品质商品', '诚意推荐品质商品', '诚意推荐品质商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44771', '18', '点击“立即关注”即可关注公众号', '点击“立即关注”即可关注公众号', '点击“立即关注”即可关注公众号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44772', '18', '立即关注', '立即关注', '立即关注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44773', '18', '添加到我的小程序, 微信首页下拉即可访问商城。', '添加到我的小程序, 微信首页下拉即可访问商城。', '添加到我的小程序, 微信首页下拉即可访问商城。', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44774', '18', '点击', '点击', '点击', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44775', '18', '服务协议与隐私政策', '服务协议与隐私政策', '服务协议与隐私政策', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44776', '18', '请务必审慎阅读、充分理解“服务协议与 隐私政策”各条款,包括但不限于:为了 向你提供即时通讯、内容分享等服务,我 们需要收集你的设备信息、操作日志等个 人信息。你可以在“设置”中查看、变更、删除个人信息并管理你的授权。', '请务必审慎阅读、充分理解“服务协议与 隐私政策”各条款,包括但不限于:为了 向你提供即时通讯、内容分享等服务,我 们需要收集你的设备信息、操作日志等个 人信息。你可以在“设置”中查看、变更、删除个人信息并管理你的授权。', '请务必审慎阅读、充分理解“服务协议与 隐私政策”各条款,包括但不限于:为了 向你提供即时通讯、内容分享等服务,我 们需要收集你的设备信息、操作日志等个 人信息。你可以在“设置”中查看、变更、删除个人信息并管理你的授权。', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44777', '18', '你可以阅读', '你可以阅读', '你可以阅读', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44778', '18', '《服务协议与隐私政策》', '《服务协议与隐私政策》', '《服务协议与隐私政策》', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44779', '18', '了解详细信息。如你同意,请点击“我同意”开始接受我们的服务。', '了解详细信息。如你同意,请点击“我同意”开始接受我们的服务。', '了解详细信息。如你同意,请点击“我同意”开始接受我们的服务。', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44780', '18', '我同意', '我同意', '我同意', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44781', '18', '残忍拒绝', '残忍拒绝', '残忍拒绝', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44782', '18', '下拉加载更多', '下拉加载更多', '下拉加载更多', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44783', '18', '网络连接断开', '网络连接断开', '网络连接断开', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44784', '18', '请检查情况:', '请检查情况:', '请检查情况:', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44785', '18', '在设置中是否已开启网络权限', '在设置中是否已开启网络权限', '在设置中是否已开启网络权限', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44786', '18', '当前是否处于弱网环境', '当前是否处于弱网环境', '当前是否处于弱网环境', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44787', '18', '版本是否过低,升级试试吧', '版本是否过低,升级试试吧', '版本是否过低,升级试试吧', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44788', '18', '重新连接', '重新连接', '重新连接', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44789', '18', '加载中', '加载中', '加载中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44790', '18', '没有更多内容啦~', '没有更多内容啦~', '没有更多内容啦~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44791', '18', '100%正品保证', '100%正品保证', '100%正品保证', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44792', '18', '所有商品精挑细选', '所有商品精挑细选', '所有商品精挑细选', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44793', '18', '售后无忧', '售后无忧', '售后无忧', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44794', '18', '管理', '管理', '管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44795', '18', '购物数量', '购物数量', '购物数量', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44796', '18', '请重新选择商品规格', '请重新选择商品规格', '请重新选择商品规格', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44797', '18', '重选', '重选', '重选', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44798', '18', '失效商品', '失效商品', '失效商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44799', '18', '失效', '失效', '失效', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('448', '1', '400381', '请选择提货点logo', '请选择提货点logo', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44800', '18', '该商品已失效', '该商品已失效', '该商品已失效', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44801', '18', '立即下单', '立即下单', '立即下单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44802', '18', '产品库存不足,请选择其它', '产品库存不足,请选择其它', '产品库存不足,请选择其它', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44803', '18', '添加购物车成功', '添加购物车成功', '添加购物车成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44804', '18', '清除成功', '清除成功', '清除成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44805', '18', '暂无兑换记录~', '暂无兑换记录~', '暂无兑换记录~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44806', '18', '大家都在换', '大家都在换', '大家都在换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44807', '18', '人兑换', '人兑换', '人兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44808', '18', '轻松赚积分', '轻松赚积分', '轻松赚积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44809', '18', '购买商品', '购买商品', '购买商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44810', '18', '购买商品可获得积分奖励', '购买商品可获得积分奖励', '购买商品可获得积分奖励', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44811', '18', '去完成', '去完成', '去完成', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44812', '18', '每日签到活动', '每日签到活动', '每日签到活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44813', '18', '每日签到可获得积分奖励', '每日签到可获得积分奖励', '每日签到可获得积分奖励', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44814', '18', '九宫格抽奖活动', '九宫格抽奖活动', '九宫格抽奖活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44815', '18', '幸运抽奖可获得积分奖励', '幸运抽奖可获得积分奖励', '幸运抽奖可获得积分奖励', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44816', '18', '我的积分', '我的积分', '我的积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44817', '18', '每日签到', '每日签到', '每日签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44818', '18', '积分抽奖', '积分抽奖', '积分抽奖', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44819', '18', '兑换记录', '兑换记录', '兑换记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44820', '18', '已兑换', '已兑换', '已兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44821', '18', '无法兑换', '无法兑换', '无法兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44822', '18', '[默认]', '[默认]', '[默认]', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44823', '18', '可用积分', '可用积分', '可用积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44824', '18', '快递费用', '快递费用', '快递费用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44825', '18', '免运费', '免运费', '免运费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44826', '18', '备注信息', '备注信息', '备注信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44827', '18', '请添加备注(150字以内)', '请添加备注(150字以内)', '请添加备注(150字以内)', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44828', '18', '使用线上支付宝支付', '使用线上支付宝支付', '使用线上支付宝支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44829', '18', '可用余额:', '可用余额:', '可用余额:', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44830', '18', '选择线下付款方式', '选择线下付款方式', '选择线下付款方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44831', '18', '正在加载…', '正在加载…', '正在加载…', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44832', '18', '可用积分不足!', '可用积分不足!', '可用积分不足!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44833', '18', '订单状态', '订单状态', '订单状态', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44834', '18', '支付积分', '支付积分', '支付积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44835', '18', '备注', '备注', '备注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44836', '18', '配送核销码', '配送核销码', '配送核销码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44837', '18', '当前可用余额:', '当前可用余额:', '当前可用余额:', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44838', '18', '正在加载', '正在加载', '正在加载', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44839', '18', '缺少经纬度信息无法查看地图!', '缺少经纬度信息无法查看地图!', '缺少经纬度信息无法查看地图!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44840', '18', '商品兑换成功', '商品兑换成功', '商品兑换成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44841', '18', '兑换方式', '兑换方式', '兑换方式', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44842', '18', '积分兑换', '积分兑换', '积分兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44843', '18', '兑换积分', '兑换积分', '兑换积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44844', '18', '取消兑换', '取消兑换', '取消兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44845', '18', '缺少参数无法查看订单兑换状态', '缺少参数无法查看订单兑换状态', '缺少参数无法查看订单兑换状态', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44846', '18', '用户离开了', '用户离开了', '用户离开了', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44847', '18', '兑换成功', '兑换成功', '兑换成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44848', '18', '物流公司', '物流公司', '物流公司', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44849', '18', '复制单号', '复制单号', '复制单号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44850', '18', '设为默认', '设为默认', '设为默认', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44851', '18', '添加新地址', '添加新地址', '添加新地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44852', '18', '导入微信地址', '导入微信地址', '导入微信地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44853', '18', '取消选择', '取消选择', '取消选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44854', '18', '您设置的默认地址不存在!', '您设置的默认地址不存在!', '您设置的默认地址不存在!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44855', '18', '设置成功', '设置成功', '设置成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44856', '18', '您删除的地址不存在!', '您删除的地址不存在!', '您删除的地址不存在!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44857', '18', '获取头像', '获取头像', '获取头像', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44858', '18', '请点击授权', '请点击授权', '请点击授权', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44859', '18', '绑定手机号', '绑定手机号', '绑定手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44860', '18', '永久', '永久', '永久', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44861', '18', '会员到期', '会员到期', '会员到期', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44862', '18', '未开通会员', '未开通会员', '未开通会员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44863', '18', '查看会员权益', '查看会员权益', '查看会员权益', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44864', '18', '立即续费', '立即续费', '立即续费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44865', '18', '立即激活', '立即激活', '立即激活', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44866', '18', '会员可享多项权益', '会员可享多项权益', '会员可享多项权益', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44867', '18', '订单中心', '订单中心', '订单中心', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44868', '18', '我的服务', '我的服务', '我的服务', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44869', '18', '隐私协议', '隐私协议', '隐私协议', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44870', '18', '商家管理', '商家管理', '商家管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44871', '18', '更新用户信息成功', '更新用户信息成功', '更新用户信息成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44872', '18', '客服接待', '客服接待', '客服接待', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44873', '18', '点击复制网址去浏览器中打开', '点击复制网址去浏览器中打开', '点击复制网址去浏览器中打开', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44874', '18', '点击复制', '点击复制', '点击复制', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44875', '18', '完成支付', '完成支付', '完成支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44876', '18', '点击右上角', '点击右上角', '点击右上角', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44877', '18', '选择 在浏览器 打开,去支付宝支付', '选择 在浏览器 打开,去支付宝支付', '选择 在浏览器 打开,去支付宝支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44878', '18', '支付订单不存在,页面将在2秒后自动关闭!', '支付订单不存在,页面将在2秒后自动关闭!', '支付订单不存在,页面将在2秒后自动关闭!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44879', '18', '正在支付中', '正在支付中', '正在支付中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44880', '18', '支付订单不存在,页面将在2秒后自动关闭', '支付订单不存在,页面将在2秒后自动关闭', '支付订单不存在,页面将在2秒后自动关闭', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44881', '18', '复制失败', '复制失败', '复制失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44882', '18', '您目前的排名', '您目前的排名', '您目前的排名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44883', '18', '您目前暂无排名', '您目前暂无排名', '您目前暂无排名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44884', '18', '暂无排名~', '暂无排名~', '暂无排名~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44885', '18', '我也是有底线的', '我也是有底线的', '我也是有底线的', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44886', '18', '输入手机号', '输入手机号', '输入手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44887', '18', '输入验证码', '输入验证码', '输入验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44888', '18', '立即登录', '立即登录', '立即登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44889', '18', '请填写手机号码', '请填写手机号码', '请填写手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44890', '18', '请填写验证码', '请填写验证码', '请填写验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44891', '18', '请输入正确的验证码', '请输入正确的验证码', '请输入正确的验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44892', '18', '正在登录中', '正在登录中', '正在登录中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44893', '18', '登录成功', '登录成功', '登录成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44894', '18', '获取授权', '获取授权', '获取授权', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44895', '18', '获取微信的手机号授权', '获取微信的手机号授权', '获取微信的手机号授权', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44896', '18', '获取微信手机号', '获取微信手机号', '获取微信手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44897', '18', '输入手机号码', '输入手机号码', '输入手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44898', '18', '填写登录密码', '填写登录密码', '填写登录密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44899', '18', '登录', '登录', '登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('449', '1', '400382', '请选择提货点大图', '请选择提货点大图', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('44900', '18', '快速登录', '快速登录', '快速登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44901', '18', '账号登录', '账号登录', '账号登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44902', '18', '其他方式登录', '其他方式登录', '其他方式登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44903', '18', '登录中', '登录中', '登录中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44904', '18', '获取用户信息失败', '获取用户信息失败', '获取用户信息失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44905', '18', '请绑定手机号后,继续操作', '请绑定手机号后,继续操作', '请绑定手机号后,继续操作', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44906', '18', '错误信息', '错误信息', '错误信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44907', '18', '用户点击确定', '用户点击确定', '用户点击确定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44908', '18', '用户点击取消', '用户点击取消', '用户点击取消', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44909', '18', '登录失败', '登录失败', '登录失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44910', '18', '请勿重复点击', '请勿重复点击', '请勿重复点击', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44911', '18', '请填写密码', '请填写密码', '请填写密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44912', '18', '您输入的密码过于简单', '您输入的密码过于简单', '您输入的密码过于简单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44913', '18', '请填写账号', '请填写账号', '请填写账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44914', '18', '请输入正确的账号', '请输入正确的账号', '请输入正确的账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44915', '18', '[图片]', '[图片]', '[图片]', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44916', '18', '[语音]', '[语音]', '[语音]', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44917', '18', '[商品]', '[商品]', '[商品]', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44918', '18', '[订单]', '[订单]', '[订单]', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44919', '18', '亲、暂无消息记录哟!', '亲、暂无消息记录哟!', '亲、暂无消息记录哟!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44920', '18', '站内消息', '站内消息', '站内消息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44921', '18', '客服消息', '客服消息', '客服消息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44922', '18', '通知于', '通知于', '通知于', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44923', '18', '获取详情中', '获取详情中', '获取详情中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44924', '18', '代付订单创建成功,发给好友帮你付款吧~', '代付订单创建成功,发给好友帮你付款吧~', '代付订单创建成功,发给好友帮你付款吧~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44925', '18', '帮我付一下这件商品了,谢谢~', '帮我付一下这件商品了,谢谢~', '帮我付一下这件商品了,谢谢~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44926', '18', '已经有人替我代付,谢谢啦~', '已经有人替我代付,谢谢啦~', '已经有人替我代付,谢谢啦~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44927', '18', '谢谢你帮我支付,么么哒~', '谢谢你帮我支付,么么哒~', '谢谢你帮我支付,么么哒~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44928', '18', '我已为你代付成功,商家正在努力发货中~', '我已为你代付成功,商家正在努力发货中~', '我已为你代付成功,商家正在努力发货中~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44929', '18', '好友代付成功,商家正在努力发货中~', '好友代付成功,商家正在努力发货中~', '好友代付成功,商家正在努力发货中~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44930', '18', '发送给微信好友', '发送给微信好友', '发送给微信好友', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44931', '18', '查看订单详情', '查看订单详情', '查看订单详情', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44932', '18', '订单已支付', '订单已支付', '订单已支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44933', '18', '如果订单申请退款,已支付金额将原路退还给您', '如果订单申请退款,已支付金额将原路退还给您', '如果订单申请退款,已支付金额将原路退还给您', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44934', '18', '代付成功', '代付成功', '代付成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44935', '18', '谢谢你为我付款,还可以再去看看其他商品哟~', '谢谢你为我付款,还可以再去看看其他商品哟~', '谢谢你为我付款,还可以再去看看其他商品哟~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44936', '18', '该订单暂未支付', '该订单暂未支付', '该订单暂未支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44937', '18', '人', '人', '人', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44938', '18', '推广人数', '推广人数', '推广人数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44939', '18', '一级', '一级', '一级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44940', '18', '二级', '二级', '二级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44941', '18', '点击搜索会员名称', '点击搜索会员名称', '点击搜索会员名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44942', '18', '团队排序', '团队排序', '团队排序', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44943', '18', '金额排序', '金额排序', '金额排序', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44944', '18', '订单排序', '订单排序', '订单排序', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44945', '18', '单', '单', '单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44946', '18', '加入时间', '加入时间', '加入时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44947', '18', '累积推广订单', '累积推广订单', '累积推广订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44948', '18', '本月累计推广订单', '本月累计推广订单', '本月累计推广订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44949', '18', '返佣', '返佣', '返佣', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44950', '18', '暂未返佣', '暂未返佣', '暂未返佣', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44951', '18', '返佣时间', '返佣时间', '返佣时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44952', '18', '单号', '单号', '单号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44953', '18', '暂无推广订单~', '暂无推广订单~', '暂无推广订单~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44954', '18', '推广订单列表', '推广订单列表', '推广订单列表', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44955', '18', '找回密码', '找回密码', '找回密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44956', '18', '填写您的新密码', '填写您的新密码', '填写您的新密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44957', '18', '加载失败', '加载失败', '加载失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44958', '18', '点击授权登录您的客服工作台', '点击授权登录您的客服工作台', '点击授权登录您的客服工作台', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44959', '18', '授权登录', '授权登录', '授权登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44960', '18', '没有登录的code,请重新扫码', '没有登录的code,请重新扫码', '没有登录的code,请重新扫码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44961', '18', '员工人数', '员工人数', '员工人数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44962', '18', '邀请', '邀请', '邀请', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44963', '18', '分佣比例', '分佣比例', '分佣比例', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44964', '18', '修改分佣比例', '修改分佣比例', '修改分佣比例', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44965', '18', '请输入百分比', '请输入百分比', '请输入百分比', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44966', '18', '删除员工', '删除员工', '删除员工', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44967', '18', '确定删除该员工?', '确定删除该员工?', '确定删除该员工?', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44968', '18', '请输入比例', '请输入比例', '请输入比例', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44969', '18', '分类', '分类', '分类', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44970', '18', '我的', '我的', '我的', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44971', '18', '姓名', '姓名', '姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44972', '18', '请输入联系电话', '请输入联系电话', '请输入联系电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44973', '18', '所在地区', '所在地区', '所在地区', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44974', '18', '详细地址', '详细地址', '详细地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44975', '18', '设置为默认地址', '设置为默认地址', '设置为默认地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44976', '18', '立即保存', '立即保存', '立即保存', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44977', '18', '浙江省', '浙江省', '浙江省', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44978', '18', '杭州市', '杭州市', '杭州市', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44979', '18', '滨江区', '滨江区', '滨江区', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44980', '18', '广东省', '广东省', '广东省', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44981', '18', '广州市', '广州市', '广州市', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44982', '18', '番禺区', '番禺区', '番禺区', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44983', '18', '修改地址', '修改地址', '修改地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44984', '18', '添加地址', '添加地址', '添加地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44985', '18', '已取消!', '已取消!', '已取消!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44986', '18', '请填写联系电话', '请填写联系电话', '请填写联系电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44987', '18', '保存中', '保存中', '保存中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44988', '18', '修改成功', '修改成功', '修改成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44989', '18', '消费', '消费', '消费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44990', '18', '充值', '充值', '充值', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44991', '18', '暂无账单的记录哦~', '暂无账单的记录哦~', '暂无账单的记录哦~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44992', '18', '点击【立即注销】即代表您已经同意《用户注销协议》', '点击【立即注销】即代表您已经同意《用户注销协议》', '点击【立即注销】即代表您已经同意《用户注销协议》', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44993', '18', '立即注销', '立即注销', '立即注销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44994', '18', '是否确认注销', '是否确认注销', '是否确认注销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44995', '18', '注销后无法恢复,请谨慎操作', '注销后无法恢复,请谨慎操作', '注销后无法恢复,请谨慎操作', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44996', '18', '注销', '注销', '注销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44997', '18', '持卡人', '持卡人', '持卡人', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44998', '18', '请输入持卡人姓名', '请输入持卡人姓名', '请输入持卡人姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('44999', '18', '卡号', '卡号', '卡号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45', '1', '100044', '开通成功', '开通成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('450', '1', '400383', '请选择地址', '请选择地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45000', '18', '请填写卡号', '请填写卡号', '请填写卡号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45001', '18', '银行', '银行', '银行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45002', '18', '提现', '提现', '提现', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45003', '18', '最低提现金额', '最低提现金额', '最低提现金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45004', '18', '当前可提现金额', '当前可提现金额', '当前可提现金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45005', '18', '冻结佣金', '冻结佣金', '冻结佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45006', '18', '说明: 每笔佣金的冻结期为', '说明: 每笔佣金的冻结期为', '说明: 每笔佣金的冻结期为', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45007', '18', '天,到期后可提现', '天,到期后可提现', '天,到期后可提现', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45008', '18', '账号', '账号', '账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45009', '18', '请填写您的微信账号', '请填写您的微信账号', '请填写您的微信账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45010', '18', '收款码', '收款码', '收款码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45011', '18', '请填写您的支付宝账号', '请填写您的支付宝账号', '请填写您的支付宝账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45012', '18', '请选择银行', '请选择银行', '请选择银行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45013', '18', '银行卡', '银行卡', '银行卡', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45014', '18', '微信', '微信', '微信', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45015', '18', '支付宝', '支付宝', '支付宝', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45016', '18', '请填写持卡人姓名', '请填写持卡人姓名', '请填写持卡人姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45017', '18', '请填写微信号', '请填写微信号', '请填写微信号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45018', '18', '请填写提现金额', '请填写提现金额', '请填写提现金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45019', '18', '提现金额不能低于', '提现金额不能低于', '提现金额不能低于', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45020', '18', '未使用', '未使用', '未使用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45021', '18', '已使用/过期', '已使用/过期', '已使用/过期', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45022', '18', '通用劵', '通用劵', '通用劵', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45023', '18', '一级分佣上浮', '一级分佣上浮', '一级分佣上浮', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45024', '18', '二级分佣上浮', '二级分佣上浮', '二级分佣上浮', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45025', '18', '快速升级技巧', '快速升级技巧', '快速升级技巧', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45026', '18', '未完成', '未完成', '未完成', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45027', '18', '已领完', '已领完', '已领完', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45028', '18', '当前共', '当前共', '当前共', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45029', '18', '取关', '取关', '取关', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45030', '18', '请选择商品', '请选择商品', '请选择商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45031', '18', '头像', '头像', '头像', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45032', '18', '手机号码', '手机号码', '手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45033', '18', '点击绑定手机号', '点击绑定手机号', '点击绑定手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45034', '18', 'ID号', 'ID号', 'ID号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45035', '18', '权限设置', '权限设置', '权限设置', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45036', '18', '点击管理', '点击管理', '点击管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45037', '18', '密码', '密码', '密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45038', '18', '点击修改密码', '点击修改密码', '点击修改密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45039', '18', '更换手机号码', '更换手机号码', '更换手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45040', '18', '点击更换手机号码', '点击更换手机号码', '点击更换手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45041', '18', '缓存大小', '缓存大小', '缓存大小', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45042', '18', '当前版本', '当前版本', '当前版本', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45043', '18', '地址管理', '地址管理', '地址管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45044', '18', '发票管理', '发票管理', '发票管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45045', '18', '账号注销', '账号注销', '账号注销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45046', '18', '注销后无法恢复', '注销后无法恢复', '注销后无法恢复', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45047', '18', '累计积分', '累计积分', '累计积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45048', '18', '累计消费', '累计消费', '累计消费', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45049', '18', '冻结积分', '冻结积分', '冻结积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45050', '18', '积分规则', '积分规则', '积分规则', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45051', '18', '提示:积分数值的高低会直接影响您的会员等级', '提示:积分数值的高低会直接影响您的会员等级', '提示:积分数值的高低会直接影响您的会员等级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45052', '18', '提示:你有', '提示:你有', '提示:你有', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45053', '18', '积分在', '积分在', '积分在', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45054', '18', '过期,请尽快使用', '过期,请尽快使用', '过期,请尽快使用', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45055', '18', '暂无积分记录哦~', '暂无积分记录哦~', '暂无积分记录哦~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45056', '18', '赚积分', '赚积分', '赚积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45057', '18', '分值明细', '分值明细', '分值明细', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45058', '18', '分值提升', '分值提升', '分值提升', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45059', '18', '抬头类型', '抬头类型', '抬头类型', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45060', '18', '增值税电子专用发票', '增值税电子专用发票', '增值税电子专用发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45061', '18', '增值税电子普通发票', '增值税电子普通发票', '增值税电子普通发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45062', '18', '需要开具发票的姓名', '需要开具发票的姓名', '需要开具发票的姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45063', '18', '需要开具发票的企业名称', '需要开具发票的企业名称', '需要开具发票的企业名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45064', '18', '税号', '税号', '税号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45065', '18', '纳税人识别号', '纳税人识别号', '纳税人识别号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45066', '18', '手机号', '手机号', '手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45067', '18', '您的手机号', '您的手机号', '您的手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45068', '18', '邮箱', '邮箱', '邮箱', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45069', '18', '您的联系邮箱', '您的联系邮箱', '您的联系邮箱', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45070', '18', '开户银行', '开户银行', '开户银行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45071', '18', '您的开户银行', '您的开户银行', '您的开户银行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45072', '18', '银行账号', '银行账号', '银行账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45073', '18', '您的银行账号', '您的银行账号', '您的银行账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45074', '18', '企业地址', '企业地址', '企业地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45075', '18', '您所在的企业地址', '您所在的企业地址', '您所在的企业地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45076', '18', '企业电话', '企业电话', '企业电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45077', '18', '您的企业电话', '您的企业电话', '您的企业电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45078', '18', '设置为默认抬头', '设置为默认抬头', '设置为默认抬头', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45079', '18', '保存', '保存', '保存', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45080', '18', '发票类型选择', '发票类型选择', '发票类型选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45081', '18', '纸质发票开出后将以邮寄形式交付', '纸质发票开出后将以邮寄形式交付', '纸质发票开出后将以邮寄形式交付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45082', '18', '请输入需要开具发票的姓名', '请输入需要开具发票的姓名', '请输入需要开具发票的姓名', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45083', '18', '请输入您的手机号', '请输入您的手机号', '请输入您的手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45084', '18', '请正确输入您的手机号', '请正确输入您的手机号', '请正确输入您的手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45085', '18', '请输入您的联系邮箱', '请输入您的联系邮箱', '请输入您的联系邮箱', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45086', '18', '请正确输入您的联系邮箱', '请正确输入您的联系邮箱', '请正确输入您的联系邮箱', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45087', '18', '请输入需要开具发票的企业名称', '请输入需要开具发票的企业名称', '请输入需要开具发票的企业名称', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45088', '18', '请输入纳税人识别号', '请输入纳税人识别号', '请输入纳税人识别号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45089', '18', '请正确输入纳税人识别号', '请正确输入纳税人识别号', '请正确输入纳税人识别号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45090', '18', '请输入您的开户银行', '请输入您的开户银行', '请输入您的开户银行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45091', '18', '请输入您的银行账号', '请输入您的银行账号', '请输入您的银行账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45092', '18', '请正确输入您的银行账号', '请正确输入您的银行账号', '请正确输入您的银行账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45093', '18', '请输入您所在的企业地址', '请输入您所在的企业地址', '请输入您所在的企业地址', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45094', '18', '请输入您的企业电话', '请输入您的企业电话', '请输入您的企业电话', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45095', '18', '发票记录', '发票记录', '发票记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45096', '18', '抬头管理', '抬头管理', '抬头管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45097', '18', '申请时间', '申请时间', '申请时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45098', '18', '没有发票信息哟~', '没有发票信息哟~', '没有发票信息哟~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45099', '18', '个人普通发票', '个人普通发票', '个人普通发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('451', '1', '400384', '请填写详细地址', '请填写详细地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45100', '18', '企业普通发票', '企业普通发票', '企业普通发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45101', '18', '企业专用发票', '企业专用发票', '企业专用发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45102', '18', '添加新发票', '添加新发票', '添加新发票', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45103', '18', '删除该发票?', '删除该发票?', '删除该发票?', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45104', '18', '发票编号', '发票编号', '发票编号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45105', '18', '发票备注', '发票备注', '发票备注', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45106', '18', '快递号', '快递号', '快递号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45107', '18', '总资产(元)', '总资产(元)', '总资产(元)', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45108', '18', '累计充值(元)', '累计充值(元)', '累计充值(元)', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45109', '18', '累计消费(元)', '累计消费(元)', '累计消费(元)', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45110', '18', '账单记录', '账单记录', '账单记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45111', '18', '消费记录', '消费记录', '消费记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45112', '18', '充值记录', '充值记录', '充值记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45113', '18', '积分中心', '积分中心', '积分中心', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45114', '18', '签到领积分', '签到领积分', '签到领积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45115', '18', '赚积分抵现金', '赚积分抵现金', '赚积分抵现金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45116', '18', '领取优惠券', '领取优惠券', '领取优惠券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45117', '18', '满减享优惠', '满减享优惠', '满减享优惠', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45118', '18', '最新拼团活动', '最新拼团活动', '最新拼团活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45119', '18', '最新的优惠商品上架拼团', '最新的优惠商品上架拼团', '最新的优惠商品上架拼团', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45120', '18', '立即参与', '立即参与', '立即参与', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45121', '18', '当前限时秒杀', '当前限时秒杀', '当前限时秒杀', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45122', '18', '最新商品秒杀进行中', '最新商品秒杀进行中', '最新商品秒杀进行中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45123', '18', '我的余额', '我的余额', '我的余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45124', '18', '赠送', '赠送', '赠送', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45125', '18', '其他', '其他', '其他', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45126', '18', '注意事项', '注意事项', '注意事项', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45127', '18', '冻结佣金为', '冻结佣金为', '冻结佣金为', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45128', '18', '立即转入', '立即转入', '立即转入', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45129', '18', '立即充值', '立即充值', '立即充值', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45130', '18', '请输入金额', '请输入金额', '请输入金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45131', '18', '转入余额', '转入余额', '转入余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45132', '18', '转入余额后无法再次转出,确认是否转入余额', '转入余额后无法再次转出,确认是否转入余额', '转入余额后无法再次转出,确认是否转入余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45133', '18', '转入成功', '转入成功', '转入成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45134', '18', '正在支付', '正在支付', '正在支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45135', '18', '充值金额必须为数字', '充值金额必须为数字', '充值金额必须为数字', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45136', '18', '充值金额不能为0', '充值金额不能为0', '充值金额不能为0', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45137', '18', '填写手机号码', '填写手机号码', '填写手机号码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45138', '18', '是否绑定账号', '是否绑定账号', '是否绑定账号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45139', '18', '绑定', '绑定', '绑定', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45140', '18', '您已取消绑定!', '您已取消绑定!', '您已取消绑定!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45141', '18', '当前手机号', '当前手机号', '当前手机号', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45142', '18', '设置新密码', '设置新密码', '设置新密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45143', '18', '确认新密码', '确认新密码', '确认新密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45144', '18', '手机号码不存在,无法发送验证码!', '手机号码不存在,无法发送验证码!', '手机号码不存在,无法发送验证码!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45145', '18', '请输入新密码', '请输入新密码', '请输入新密码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45146', '18', '两次输入的密码不一致!', '两次输入的密码不一致!', '两次输入的密码不一致!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45147', '18', '请输入验证码', '请输入验证码', '请输入验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45148', '18', '暂无退款订单~', '暂无退款订单~', '暂无退款订单~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45149', '18', '缺少订单号无法查看订单详情', '缺少订单号无法查看订单详情', '缺少订单号无法查看订单详情', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45150', '18', '明细', '明细', '明细', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45151', '18', '第七天', '第七天', '第七天', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45152', '18', '第7天', '第7天', '第7天', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45153', '18', '奖励', '奖励', '奖励', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45154', '18', '已签到', '已签到', '已签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45155', '18', '立即签到', '立即签到', '立即签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45156', '18', '已累计签到', '已累计签到', '已累计签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45157', '18', '据说连续签到第', '据说连续签到第', '据说连续签到第', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45158', '18', '天可获得超额积分,一定要坚持签到哦~~~', '天可获得超额积分,一定要坚持签到哦~~~', '天可获得超额积分,一定要坚持签到哦~~~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45159', '18', '签到成功', '签到成功', '签到成功', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45160', '18', '好的', '好的', 'OK', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45161', '18', '您今日已签到!', '您今日已签到!', '您今日已签到!', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45162', '18', '暂无签到记录~', '暂无签到记录~', '暂无签到记录~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45163', '18', '保存海报', '保存海报', '保存海报', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45164', '18', '长按保存图片', '长按保存图片', '长按保存图片', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45165', '18', '分销海报', '分销海报', '分销海报', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45166', '18', '小程序二维码需要发布正式版后才能获取到', '小程序二维码需要发布正式版后才能获取到', '小程序二维码需要发布正式版后才能获取到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45167', '18', '获取中', '获取中', '获取中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45168', '18', '暂无数据~', '暂无数据~', '暂无数据~', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45169', '18', '提现记录', '提现记录', '提现记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45170', '18', '提现总额', '提现总额', '提现总额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45171', '18', '佣金记录', '佣金记录', '佣金记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45172', '18', '佣金明细', '佣金明细', '佣金明细', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45173', '18', '分销等级', '分销等级', '分销等级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45174', '18', '昨日收益', '昨日收益', '昨日收益', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45175', '18', '累积已提', '累积已提', '累积已提', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45176', '18', '代理商申请', '代理商申请', '代理商申请', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45177', '18', '立即提现', '立即提现', '立即提现', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45178', '18', '推广名片', '推广名片', '推广名片', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45179', '18', '推广人统计', '推广人统计', '推广人统计', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45180', '18', '推广人订单', '推广人订单', '推广人订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45181', '18', '推广订单', '推广订单', '推广订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45182', '18', '事业部', '事业部', '事业部', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45183', '18', '代理商', '代理商', '代理商', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45184', '18', '推广人排行', '推广人排行', '推广人排行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45185', '18', '佣金排行', '佣金排行', '佣金排行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45186', '18', '员工列表', '员工列表', '员工列表', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45187', '18', '您目前暂无推广权限', '您目前暂无推广权限', '您目前暂无推广权限', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45188', '18', '商城购物可享', '商城购物可享', '商城购物可享', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45189', '18', '折', '折', '折', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45190', '18', '当前等级', '当前等级', '当前等级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45191', '18', '未达成', '未达成', '未达成', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45192', '18', '今日成长值', '今日成长值', '今日成长值', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45193', '18', '点', '点', '点', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45194', '18', '我的成长值记录', '我的成长值记录', '我的成长值记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45195', '18', '暂未解锁该等级', '暂未解锁该等级', '暂未解锁该等级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45196', '18', '点,需达到', '点,需达到', '点,需达到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45197', '18', '已解锁更高等级', '已解锁更高等级', '已解锁更高等级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45198', '18', '我的成长特权', '我的成长特权', '我的成长特权', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45199', '18', '购物折扣', '购物折扣', '购物折扣', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('452', '1', '400385', '请选择经纬度', '请选择经纬度', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45200', '18', '专属徽章', '专属徽章', '专属徽章', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45201', '18', '经验累积', '经验累积', '经验累积', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45202', '18', '尊享客服', '尊享客服', '尊享客服', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45203', '18', '签到', '签到', '签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45204', '18', '可获得', '可获得', '可获得', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45205', '18', '点经验', '点经验', '点经验', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45206', '18', '每日签到可获得经验值,已签到', '每日签到可获得经验值,已签到', '每日签到可获得经验值,已签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45207', '18', '去签到', '去签到', '去签到', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45208', '18', '点经验/元', '点经验/元', '点经验/元', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45209', '18', '购买商品可获得对应的经验值', '购买商品可获得对应的经验值', '购买商品可获得对应的经验值', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45210', '18', '去购买', '去购买', '去购买', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45211', '18', '点经验/人', '点经验/人', '点经验/人', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45212', '18', '邀请好友注册商城可获得经验值', '邀请好友注册商城可获得经验值', '邀请好友注册商城可获得经验值', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45213', '18', '去邀请', '去邀请', '去邀请', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45214', '18', '积分数', '积分数', '积分数', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45215', '18', '消费金额', '消费金额', '消费金额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45216', '18', '暂无经验记录', '暂无经验记录', '暂无经验记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45217', '18', '账户登录', '账户登录', '账户登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45218', '18', '微信登录', '微信登录', '微信登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45219', '18', '手机号登录', '手机号登录', '手机号登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45220', '18', '账户充值', '账户充值', '账户充值', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45221', '18', '佣金转入', '佣金转入', '佣金转入', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45222', '18', '周榜', '周榜', '周榜', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45223', '18', '月榜', '月榜', '月榜', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45224', '18', '周排行', '周排行', '周排行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45225', '18', '月排行', '月排行', '月排行', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45226', '18', '语言切换', '语言切换', '语言切换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45227', '18', '点击前往', '点击前往', '点击前往', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45228', '18', '查看全部', '查看全部', '查看全部', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45229', '18', '查看订单', '查看订单', '查看订单', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45230', '18', '无法获取图片信息', '无法获取图片信息', '无法获取图片信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45231', '18', '长按或扫描查看', '长按或扫描查看', '长按或扫描查看', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45232', '18', '点解锁', '点解锁', '点解锁', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45233', '18', '确认修改', '确认修改', '确认修改', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45234', '18', '保存修改', '保存修改', '保存修改', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45235', '18', '退出登录', '退出登录', '退出登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45236', '18', '付费会员', '付费会员', '付费会员', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45237', '18', '地址信息', '地址信息', '地址信息', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45238', '18', '我的推广', '我的推广', '我的推广', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45239', '18', '砍价记录', '砍价记录', '砍价记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45240', '18', '我的等级', '我的等级', '我的等级', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45241', '18', '兑换', '兑换', '兑换', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45242', '18', '申请中', '申请中', '申请中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45243', '18', '统计管理', '统计管理', '统计管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45244', '18', '退款', '退款', '退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45245', '18', '未发货', '未发货', '未发货', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45246', '18', '当前为最新版本', '当前为最新版本', '当前为最新版本', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45247', '18', '清除缓存', '清除缓存', '清除缓存', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45248', '18', '确定清楚本地缓存数据吗', '确定清楚本地缓存数据吗', '确定清楚本地缓存数据吗', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45249', '18', '缓存清理完成', '缓存清理完成', '缓存清理完成', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45250', '18', '切换的账号不存在', '切换的账号不存在', '切换的账号不存在', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45251', '18', '正在切换中', '正在切换中', '正在切换中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45252', '18', '确认退出登录', '确认退出登录', '确认退出登录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45253', '18', '我知道了', '我知道了', '我知道了', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45254', '18', '系统错误', '系统错误', '系统错误', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45255', '18', '请求失败', '请求失败', '请求失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45256', '18', '邀请您加入', '邀请您加入', '邀请您加入', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45257', '18', '图片上传中', '图片上传中', '图片上传中', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45258', '18', '上传图片失败', '上传图片失败', '上传图片失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45259', '18', '访问位置被拒绝', '访问位置被拒绝', '访问位置被拒绝', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45260', '18', '系统定位已关闭', '系统定位已关闭', '系统定位已关闭', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45261', '18', '需要定位权限', '需要定位权限', '需要定位权限', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45262', '18', '订单核销', '订单核销', '订单核销', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45263', '18', '当前可转入佣金为', '当前可转入佣金为', '当前可转入佣金为', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45264', '18', '浏览记录', '浏览记录', '浏览记录', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45265', '18', '签到奖励', '签到奖励', '签到奖励', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45266', '18', '请输入内容', '请输入内容', '请输入内容', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45267', '18', '单次限购', '单次限购', '单次限购', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45268', '18', '永久限购', '永久限购', '永久限购', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45269', '18', '《用户协议》', '《用户协议》', '《用户协议》', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45270', '18', '《隐私协议》', '《隐私协议》', '《隐私协议》', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45271', '18', '与', '与', '与', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45272', '18', '请先阅读并同意协议', '请先阅读并同意协议', '请先阅读并同意协议', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45273', '18', '绑定下级通知', '绑定下级通知', '绑定下级通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45274', '18', '购买成功通知', '购买成功通知', '购买成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45275', '18', '确认收货通知', '确认收货通知', '确认收货通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45276', '18', '改价通知', '改价通知', '改价通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45277', '18', '退款成功通知', '退款成功通知', '退款成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45278', '18', '充值成功通知', '充值成功通知', '充值成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45279', '18', '积分到账通知', '积分到账通知', '积分到账通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45280', '18', '佣金到账通知', '佣金到账通知', '佣金到账通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45281', '18', '砍价成功通知', '砍价成功通知', '砍价成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45282', '18', '拼团成功通知', '拼团成功通知', '拼团成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45283', '18', '拼团失败通知', '拼团失败通知', '拼团失败通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45284', '18', '开团成功通知', '开团成功通知', '开团成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45285', '18', '提现成功通知', '提现成功通知', '提现成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45286', '18', '提现失败通知', '提现失败通知', '提现失败通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45287', '18', '充值退款通知', '充值退款通知', '充值退款通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45288', '18', '退款申请拒绝通知', '退款申请拒绝通知', '退款申请拒绝通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45289', '18', '您有新的退款待处理', '您有新的退款待处理', '您有新的退款待处理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45290', '18', '您有新的订单待处理', '您有新的订单待处理', '您有新的订单待处理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45291', '18', '发货通知', '发货通知', '发货通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45292', '18', '取消拼团通知', '取消拼团通知', '取消拼团通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45293', '18', '参团成功通知', '参团成功通知', '参团成功通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45294', '18', '你有个新的提现申请待处理', '你有个新的提现申请待处理', '你有个新的提现申请待处理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45295', '18', '你有个新的用户收货待处理', '你有个新的用户收货待处理', '你有个新的用户收货待处理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45296', '18', '提醒付款通知', '提醒付款通知', '提醒付款通知', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45297', '18', '短信验证码', '短信验证码', '短信验证码', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45298', '18', '到店自提', '到店自提', '到店自提', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45299', '18', '快递配送', '快递配送', '快递配送', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('453', '1', '400386', '请选择营业时间', '请选择营业时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45300', '18', '退款发起查询失败', '退款发起失败', '微信支付:发起退款查询失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45301', '18', '500000', '发起退款查询失败', '微信支付:发起退款查询失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45302', '18', '500001', '请输入承载快递员名', '请输入承载快递员名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45303', '18', '500002', '请输入客户账户名称', '请输入客户账户名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45304', '18', '500003', '请输入电子面单承载编号', '请输入电子面单承载编号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45305', '18', '优质精选好物', '优质精选好物', '优质精选好物', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45306', '18', '商品分类', '商品分类', '商品分类', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45307', '18', '领优惠券', '领优惠券', '领优惠券', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45308', '18', '行业资讯', '行业资讯', '行业资讯', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45309', '18', '秒杀活动', '秒杀活动', '秒杀活动', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45310', '18', '预售管理', '预售管理', '预售管理', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45311', '18', '积分商城', '积分商城', '积分商城', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45312', '18', '快速选择', '快速选择', '快速选择', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45313', '18', '上百种商品分类', '上百种商品分类', '上百种商品分类', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45314', '18', '促销精品', '促销精品', '促销精品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45315', '18', '排行榜', '排行榜', '排行榜', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45316', '18', '新品推荐', '新品推荐', '新品推荐', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45317', '18', '精选单品', '精选单品', '精选单品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45318', '18', '余额支付购买商品', '余额支付购买商品', '余额支付购买商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45319', '18', '商品退款', '商品退款', '商品退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45320', '18', '系统增加余额', '系统增加余额', '系统增加余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45321', '18', '系统减少余额', '系统减少余额', '系统减少余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45322', '18', '用户充值余额', '用户充值余额', '用户充值余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45323', '18', '用户充值退款', '用户充值退款', '用户充值退款', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45324', '18', '佣金提现到余额', '佣金提现到余额', '佣金提现到余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45325', '18', '参与抽奖使用余额', '参与抽奖使用余额', '参与抽奖使用余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45326', '18', '抽奖中奖赠送余额', '抽奖中奖赠送余额', '抽奖中奖赠送余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45327', '18', '新用户注册赠送余额', '新用户注册赠送余额', '新用户注册赠送余额', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45328', '18', '购买商品赠送积分', '购买商品赠送积分', '购买商品赠送积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45329', '18', '下单赠送积分', '下单赠送积分', '下单赠送积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45330', '18', '扣除订单下单赠送积分', '扣除订单下单赠送积分', '扣除订单下单赠送积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45331', '18', '返还下单使用积分', '返还下单使用积分', '返还下单使用积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45332', '18', '商品退积分', '商品退积分', '商品退积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45333', '18', '参与抽奖使用积分', '参与抽奖使用积分', '参与抽奖使用积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45334', '18', '抽奖中奖赠送积分', '抽奖中奖赠送积分', '抽奖中奖赠送积分', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45335', '18', '积分兑换商品', '积分兑换商品', '积分兑换商品', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45336', '18', '下单赠送经验', '下单赠送经验', '下单赠送经验', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45337', '18', '获得自购订单佣金', '获得自购订单佣金', '获得自购订单佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45338', '18', '获得下级推广订单佣金', '获得下级推广订单佣金', '获得下级推广订单佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45339', '18', '获得二级推广订单佣金', '获得二级推广订单佣金', '获得二级推广订单佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45340', '18', '获得推广用户佣金', '获得推广用户佣金', '获得推广用户佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45341', '18', '佣金提现', '佣金提现', '佣金提现', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45342', '18', '提现失败', '提现失败', '提现失败', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45343', '18', '退款退佣金', '退款退佣金', '退款退佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45344', '18', '获得员工推广订单佣金', '获得员工推广订单佣金', '获得员工推广订单佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45345', '18', '获得代理推广订单佣金', '获得代理推广订单佣金', '获得代理推广订单佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45347', '18', '获得拼团团长佣金', '获得拼团团长佣金', '获得拼团团长佣金', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45348', '18', '全部已读', '全部已读', '全部已读', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45349', '18', '500004', '您有一笔支付成功的订单待处理,订单号{:order_id}!', '您有一笔支付成功的订单待处理,订单号{:order_id}!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45350', '18', '500005', '恭喜,又一员猛将将永久绑定到您的团队,用户{:nickname}加入您的队伍!', '恭喜,又一员猛将将永久绑定到您的团队,用户{:nickname}加入您的队伍!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45351', '18', '500006', '您购买的商品已支付成功,支付金额{:pay_price}元,订单号{:order_id},感谢您的光临!', '您购买的商品已支付成功,支付金额{:pay_price}元,订单号{:order_id},感谢您的光临!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45352', '18', '500007', '亲,您的订单{:order_id},商品{:store_name}已确认收货,感谢您的光临!', '亲,您的订单{:order_id},商品{:store_name}已确认收货,感谢您的光临!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45353', '18', '500008', '您的订单{:order_id},实际支付金额已被修改为{:pay_price}', '您的订单{:order_id},实际支付金额已被修改为{:pay_price}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45354', '18', '500009', '您的订单{:order_id}已同意退款,退款金额{:refund_price}元。', '您的订单{:order_id}已同意退款,退款金额{:refund_price}元。', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45355', '18', '500010', '您成功充值¥{:price},现剩余余额¥{:now_money}元', '您成功充值¥{:price},现剩余余额¥{:now_money}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45356', '18', '500011', '亲,您成功获得积分{:gain_integral},现有积分{:integral}', '亲,您成功获得积分{:gain_integral},现有积分{:integral}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45357', '18', '500012', '亲,恭喜您成功获得佣金{:brokerage_price}元', '亲,恭喜您成功获得佣金{:brokerage_price}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45358', '18', '500013', '亲,好腻害!你的朋友们已经帮你砍到底价了,商品名称{:title},底价{:min_price}', '亲,好腻害!你的朋友们已经帮你砍到底价了,商品名称{:title},底价{:min_price}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45359', '18', '500014', '亲,您的拼团已经完成了,拼团名称{:title},团长{:nickname}', '亲,您的拼团已经完成了,拼团名称{:title},团长{:nickname}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45360', '18', '500015', '亲,您的拼团失败,活动名称{:title}', '亲,您的拼团失败,活动名称{:title}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45361', '18', '500016', '亲,您已成功参与拼团,活动名称{:title}', '亲,您已成功参与拼团,活动名称{:title}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45362', '18', '500017', '亲,您成功提现佣金{:extract_number}元', '亲,您成功提现佣金{:extract_number}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45363', '18', '500018', '亲,您发起的提现被驳回,返回佣金{:extract_number}元', '亲,您发起的提现被驳回,返回佣金{:extract_number}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45364', '18', '500019', '亲,您充值的金额已退款,本次退款{:refund_price}元', '亲,您充值的金额已退款,本次退款{:refund_price}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45365', '18', '500020', '您好!您的订单{:order_id}已拒绝退款。', '您好!您的订单{:order_id}已拒绝退款。', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45366', '18', '500021', '您有一笔退款订单待处理,订单号{:order_id}!', '您有一笔退款订单待处理,订单号{:order_id}!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45367', '18', '500022', '亲爱的用户{:nickname}您的商品{:store_name},订单号{:order_id}已发货,请注意查收', '亲爱的用户{:nickname}您的商品{:store_name},订单号{:order_id}已发货,请注意查收', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45368', '18', '500023', '亲,您的拼团取消,活动名称{:title}', '亲,您的拼团取消,活动名称{:title}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45369', '18', '500024', '亲,您已成功参与拼团,活动名称{:title}', '亲,您已成功参与拼团,活动名称{:title}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45370', '18', '500025', '您有一笔提现申请待处理,提现金额{:money}!', '您有一笔提现申请待处理,提现金额{:money}!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45371', '18', '500026', '您有一笔订单已经确认收货,订单号{:order_id}!', '您有一笔订单已经确认收货,订单号{:order_id}!', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45372', '18', '500027', '您有未付款订单,订单号为:{:order_id},商品数量有限,请及时付款。', '您有未付款订单,订单号为:{:order_id},商品数量有限,请及时付款。', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45373', '18', '500028', '请填写邀请码', '请填写邀请码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45374', '18', '500029', '金额最多两位小数', '金额最多两位小数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45375', '18', '500030', '名称长度需在6-17个字符之间', '名称长度需在6-17个字符之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45376', '18', '500031', '接口名不能为空', '接口名不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45377', '18', '500032', '接口地址不能为空', '接口地址不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45378', '18', '500033', '请求方式不能为空', '请求方式不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45379', '18', '500034', '模块分类不能为空', '模块分类不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45380', '18', '500035', '接口不存在', '接口不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45381', '18', '500036', '接口信息不存在', '接口信息不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45382', '18', '500037', '接口分类名称不能为空', '接口分类名称不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45383', '18', '500038', '该分类下有接口,无法删除', '该分类下有接口,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45384', '18', '500039', 'zip扩展未安装', 'zip扩展未安装', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45385', '18', '500040', '删除文件失败,失败原因{:message}', '删除文件失败,失败原因{:message}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45386', '18', '500041', '系统数据表,无法生成', '系统数据表,无法生成', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45387', '18', '500042', '表名不能为空', '表名不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45388', '18', '500043', '功能创建成功', '功能创建成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45389', '18', '500044', '字段类型不存在', '字段类型不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45390', '18', '500045', '不存在的资源路由类型', '不存在的资源路由类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45391', '18', '500046', '表单类型至少选择一项', '表单类型至少选择一项', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('45394', '18', '支付剩余时间', '支付剩余时间', '支付剩余时间', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('45395', '18', '确认支付', '确认支付', '确认支付', 0); +INSERT INTO `lms_clx_lang_code` VALUES ('454', '1', '400387', '短信账号必须填写', '短信账号必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('455', '1', '400388', '短信密码必须填写', '短信密码必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('456', '1', '400389', '订单号必须存在', '订单号必须存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('457', '1', '400390', '订单号有误', '订单号有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('458', '1', '400391', '订单号必须为字母和数字', '订单号必须为字母和数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('459', '1', '400392', '订单金额必须填写', '订单金额必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('46', '1', '100045', '开通失败', '开通失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('460', '1', '400393', '订单金额必须为数字', '订单金额必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('461', '1', '400394', '订单金额必须填写', '订单金额必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('462', '1', '400395', '订单金额必须为数字', '订单金额必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('463', '1', '400396', '订单邮费必须填写', '订单邮费必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('464', '1', '400397', '订单邮费必须为数字', '订单邮费必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('465', '1', '400398', '赠送积分必须为数字', '赠送积分必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('466', '1', '400399', '请选择用户头像', '请选择用户头像', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('467', '1', '400400', '请输入公司名称', '请输入公司名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('468', '1', '400401', '添加公司成功', '添加公司成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('469', '1', '400402', '请输入月结账号', '请输入月结账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('47', '1', '100046', '清除数据成功', '清除数据成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('470', '1', '400403', '请输入月结密码', '请输入月结密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('471', '1', '400404', '请输入取件网点', '请输入取件网点', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('472', '1', '400405', '缩略图大图尺寸(高)必须为数字', '缩略图大图尺寸(高)必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('473', '1', '400406', '缩略图大图尺寸(高)必须大于等于0', '缩略图大图尺寸(高)必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('474', '1', '400407', '缩略图大图尺寸(宽)必须为数字', '缩略图大图尺寸(宽)必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('475', '1', '400408', '缩略图大图尺寸(宽)必须大于等于0', '缩略图大图尺寸(宽)必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('476', '1', '400409', '缩略图中图尺寸(高)必须为数字', '缩略图中图尺寸(高)必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('477', '1', '400410', '缩略图中图尺寸(高)必须大于等于0', '缩略图中图尺寸(高)必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('478', '1', '400411', '缩略图中图尺寸(宽)必须为数字', '缩略图中图尺寸(宽)必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('479', '1', '400412', '缩略图中图尺寸(宽)必须大于等于0', '缩略图中图尺寸(宽)必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('48', '1', '100047', '优化成功', '优化成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('480', '1', '400413', '缩略图小图尺寸(高)必须为数字', '缩略图小图尺寸(高)必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('481', '1', '400414', '缩略图小图尺寸(高)必须大于等于0', '缩略图小图尺寸(高)必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('482', '1', '400415', '缩略图小图尺寸(宽)必须为数字', '缩略图小图尺寸(宽)必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('483', '1', '400416', '缩略图小图尺寸(宽)必须大于等于0', '缩略图小图尺寸(宽)必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('484', '1', '400417', '水印文字只能是汉字、字母、数字', '水印文字只能是汉字、字母、数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('485', '1', '400418', '水印文字长度为1-10位', '水印文字长度为1-10位', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('486', '1', '400419', '水印文字大小必须为数字', '水印文字大小必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('487', '1', '400420', '水印文字大小必须大于等于0', '水印文字大小必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('488', '1', '400421', '水印横坐标偏移量必须为数字', '水印横坐标偏移量必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('489', '1', '400422', '水印横坐标偏移量必须大于等于0', '水印横坐标偏移量必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('49', '1', '100048', '优化失败', '优化失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('490', '1', '400423', '水印纵坐标偏移量必须为数字', '水印纵坐标偏移量必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('491', '1', '400424', '水印纵坐标偏移量必须大于等于0', '水印纵坐标偏移量必须大于等于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('492', '1', '400425', '该主播已经存在', '该主播已经存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('493', '1', '400426', '请先去小程序认证主播', '请先去小程序认证主播', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('494', '1', '400427', '商品已创建', '商品已创建', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('495', '1', '400428', '审核中或审核失败不允许此操作', '审核中或审核失败不允许此操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('496', '1', '400429', '在审核中或已经审核通过', '在审核中或已经审核通过', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('497', '1', '400430', '审核通过或失败', '审核通过或失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('498', '1', '400431', '商品审核中,无法删除', '商品审核中,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('499', '1', '400432', '该主播不存在', '该主播不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('5', '1', '100004', '隐藏成功', '隐藏成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('50', '1', '100049', '修复成功', '修复成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('500', '1', '400433', '开播时间需要在当前时间的10分钟后,并且开始时间不能在6个月后', '开播时间需要在当前时间的10分钟后,并且开始时间不能在6个月后', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('501', '1', '400434', '开播时间和结束时间间隔不得短于30分钟,不得超过24小时', '开播时间和结束时间间隔不得短于30分钟,不得超过24小时', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('502', '1', '400435', '请输入理由', '请输入理由', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('503', '1', '400436', '请选择正确的直播商品', '请选择正确的直播商品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('504', '1', '400437', '直播间状态有误', '直播间状态有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('505', '1', '400438', '奖品不存在', '奖品不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('506', '1', '400439', '写入中奖记录失败', '写入中奖记录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('507', '1', '400440', '请继续参与活动抽奖', '请继续参与活动抽奖', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('508', '1', '400441', '已经领取成功', '已经领取成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('509', '1', '400442', '分销等级不存在', '分销等级不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('51', '1', '100050', '修复失败', '修复失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('510', '1', '400443', '选择的等级不存在', '选择的等级不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('511', '1', '400444', '该等级已存在此类型任务', '该等级已存在此类型任务', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('512', '1', '400445', '不能小于低等级同类型任务限定数量', '不能小于低等级同类型任务限定数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('513', '1', '400446', '不能大于高等级同类型任务限定数量', '不能大于高等级同类型任务限定数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('514', '1', '400447', '解除失败', '解除失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('515', '1', '400448', '代理商佣金比例不能大于事业部佣金比例', '代理商佣金比例不能大于事业部佣金比例', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('516', '1', '400449', '代理商到期时间不能大于事业部到期时间', '代理商到期时间不能大于事业部到期时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('517', '1', '400450', '请填写用户UID', '请填写用户UID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('518', '1', '400451', '管理员信息未查到', '管理员信息未查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('519', '1', '400452', '管理员已经删除', '管理员已经删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('52', '1', '100051', '备份成功', '备份成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('520', '1', '400453', '管理员姓名不能为空', '管理员姓名不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('521', '1', '400454', '该分类有下级分类,无法删除', '该分类有下级分类,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('522', '1', '400455', '该分类下有文章,无法删除', '该分类下有文章,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('523', '1', '400456', '请稍后查看', '请稍后查看', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('524', '1', '400457', '默认模板不能删除', '默认模板不能删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('525', '1', '400458', '该模板使用中,无法删除', '该模板使用中,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('526', '1', '400459', '个人中心模板不存在', '个人中心模板不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('527', '1', '400460', '反馈内容没有查到', '反馈内容没有查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('528', '1', '400461', '您修改的话术内容不存在', '您修改的话术内容不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('529', '1', '400462', '短信平台:{:msg}', '短信平台:{:msg}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('53', '1', '100052', '备份失败', '备份失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('530', '1', '400463', '订单商品获取失败,无法打印', '订单商品获取失败,无法打印', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('531', '1', '400464', '小票打印未开启', '小票打印未开启', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('532', '1', '400465', '请先配置小票打印开发者', '请先配置小票打印开发者', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('533', '1', '400466', '请选择图片', '请选择图片', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('534', '1', '400467', '配送员已存在', '配送员已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('535', '1', '400468', '同一个手机号的配送员只能添加一个', '同一个手机号的配送员只能添加一个', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('536', '1', '400469', '配送员名称不能为空', '配送员名称不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('537', '1', '400470', '订单未能查到,不能发货', '订单未能查到,不能发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('538', '1', '400471', '订单已删除,不能发货', '订单已删除,不能发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('539', '1', '400472', '订单已发货请勿重复操作', '订单已发货请勿重复操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('54', '1', '100100', '参数错误', '参数错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('540', '1', '400473', '核销订单不能发货', '核销订单不能发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('541', '1', '400474', '拼团未完成暂不能发货', '拼团未完成暂不能发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('542', '1', '400475', '订单有售后申请请先处理', '订单有售后申请请先处理', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('543', '1', '400476', '快递公司编缺失', '快递公司编缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('544', '1', '400477', '请填写寄件人电话', '请填写寄件人电话', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('545', '1', '400478', '请填写寄件人地址', '请填写寄件人地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('546', '1', '400479', '虚拟发货,无需修改发货信息', '虚拟发货,无需修改发货信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('547', '1', '400480', '未发货,请先发货再修改配送信息', '未发货,请先发货再修改配送信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('548', '1', '400481', '自提订单无法打印', '自提订单无法打印', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('549', '1', '400482', '请先发货', '请先发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('55', '1', '100101', '非法操作', '非法操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('550', '1', '400483', '请先在系统设置中打开单子面单打印开关', '请先在系统设置中打开单子面单打印开关', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('551', '1', '400484', '发票已申请,正在审核打印中', '发票已申请,正在审核打印中', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('552', '1', '400485', '订单已退款', '订单已退款', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('553', '1', '400486', '正在申请退款中', '正在申请退款中', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('554', '1', '400487', '申请失败', '申请失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('555', '1', '400488', '未支付无法退款', '未支付无法退款', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('556', '1', '400489', '回退积分和优惠券失败', '回退积分和优惠券失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('557', '1', '400490', '拼团修改失败', '拼团修改失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('558', '1', '400491', '回退佣金失败', '回退佣金失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('559', '1', '400492', '余额退款失败', '余额退款失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('56', '1', '100102', '数据获取失败', '数据获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('560', '1', '400493', '购买的优惠券已使用或者已过期', '购买的优惠券已使用或者已过期', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('561', '1', '400494', '回退积分增加失败', '回退积分增加失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('562', '1', '400495', '售后订单不存在', '售后订单不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('563', '1', '400496', '积分已退或者积分为零无法再退', '积分已退或者积分为零无法再退', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('564', '1', '400497', '未支付无法退积分', '未支付无法退积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('565', '1', '400498', '订单退积分失败', '订单退积分失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('566', '1', '400499', '请输入拒绝退款理由', '请输入拒绝退款理由', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('567', '1', '400500', '限制单次购买数量不能大于总购买数量', '限制单次购买数量不能大于总购买数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('568', '1', '400501', '请添加抽奖活动名称', '请添加抽奖活动名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('569', '1', '400502', '请添加抽奖描述等文案', '请添加抽奖描述等文案', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('57', '1', '100103', '站点升级中,请稍候访问', '站点升级中,请稍候访问', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('570', '1', '400503', '活动结束时间必须大于开始时间', '活动结束时间必须大于开始时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('571', '1', '400504', '请添加奖品', '请添加奖品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('572', '1', '400505', '请填写消耗数量', '请填写消耗数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('573', '1', '400506', '商品参与其他活动开启,无法开启预售', '商品参与其他活动开启,无法开启预售', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('574', '1', '400507', '活动结束时间不能小于当前时间', '活动结束时间不能小于当前时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('575', '1', '400508', '活动已结束,请重新添加或复制', '活动已结束,请重新添加或复制', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('576', '1', '400509', '添加优惠券成功', '添加优惠券成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('577', '1', '400510', '发布优惠劵成功', '发布优惠劵成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('578', '1', '400511', '砍价最低价不能大于或等于起始金额', '砍价最低价不能大于或等于起始金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('579', '1', '400512', '砍价人数不能大于{:num}人', '砍价人数不能大于{:num}人', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('58', '1', '100104', '缺少code', '缺少code', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('580', '1', '400513', '使用开始时间不能小于领取开始时间', '使用开始时间不能小于领取开始时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('581', '1', '400514', '使用结束时间不能小于领取结束时间', '使用结束时间不能小于领取结束时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('582', '1', '400515', '优惠券不存在', '优惠券不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('583', '1', '400516', '领取的优惠劵已领完或已过期', '领取的优惠劵已领完或已过期', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('584', '1', '400517', '已领取过该优惠劵', '已领取过该优惠劵', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('585', '1', '400518', '抱歉,优惠券已经领取完了', '抱歉,优惠券已经领取完了', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('586', '1', '400519', '选择用户已拥有该优惠券,请勿重复发放', '选择用户已拥有该优惠券,请勿重复发放', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('587', '1', '400520', '订单已删除', '订单已删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('588', '1', '400521', '订单已发货', '订单已发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('589', '1', '400522', '暂时不支持其他发货类型', '暂时不支持其他发货类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('59', '1', '110000', '您暂时没有访问权限', '您暂时没有访问权限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('590', '1', '400523', '请输入送货人姓名', '请输入送货人姓名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('591', '1', '400524', '请输入送货人电话号码', '请输入送货人电话号码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('592', '1', '400525', '请输入送货人信息', '请输入送货人信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('593', '1', '400526', '请输入正确的送货人电话号码', '请输入正确的送货人电话号码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('594', '1', '400527', '请选择电子面单模板', '请选择电子面单模板', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('595', '1', '400528', '电子面单已关闭,请选择其他发货方式', '电子面单已关闭,请选择其他发货方式', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('596', '1', '400529', '发货失败', '发货失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('597', '1', '400530', '订单状态错误', '订单状态错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('598', '1', '400531', '请输入快递单号', '请输入快递单号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('599', '1', '400532', '请先发货再修改配送信息', '请先发货再修改配送信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('6', '1', '100005', '操作失败', '操作失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('60', '1', '110001', '接口未授权,您无法访问', '接口未授权,您无法访问', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('600', '1', '400533', '商品不存在', '商品不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('601', '1', '400534', '您查看的积分商品已被删除', '您查看的积分商品已被删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('602', '1', '400535', '请添加商品', '请添加商品', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('603', '1', '400536', '添加抽奖活动失败', '添加抽奖活动失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('604', '1', '400537', '抽奖活动不存在', '抽奖活动不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('605', '1', '400538', '请填写奖品名称', '请填写奖品名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('606', '1', '400539', '请选择奖品图片', '请选择奖品图片', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('607', '1', '400540', '请填写奖品中奖权重', '请填写奖品中奖权重', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('608', '1', '400541', '请选择奖品类型', '请选择奖品类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('609', '1', '400542', '请填写奖品赠送{:type}数', '请填写奖品赠送{:type}数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('61', '1', '110002', '请登录', '请登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('610', '1', '400543', '请选择优惠券', '请选择优惠券', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('611', '1', '400544', '生成新订单失败', '生成新订单失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('612', '1', '400545', '修改原来订单商品拆分状态失败', '修改原来订单商品拆分状态失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('613', '1', '400546', '新增拆分订单商品信息失败', '新增拆分订单商品信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('614', '1', '400547', '保存新订单商品信息失败', '保存新订单商品信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('615', '1', '400548', '协议类型缺失', '协议类型缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('616', '1', '400549', '请填写协议名称', '请填写协议名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('617', '1', '400550', '请填写协议内容', '请填写协议内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('618', '1', '400551', '该类型协议已经存在', '该类型协议已经存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('619', '1', '400552', '临时二维码获取错误', '临时二维码获取错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('62', '1', '110003', '登录已过期,请重新登录', '登录已过期,请重新登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('620', '1', '400553', '永久二维码获取错误', '永久二维码获取错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('621', '1', '400554', '请先配置接口密钥', '请先配置接口密钥', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('622', '1', '400555', '无法创建文件夹,请检查您的上传目录权限', '无法创建文件夹,请检查您的上传目录权限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('623', '1', '400556', '商品参数错误', '商品参数错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('624', '1', '400557', '上传方式错误', '上传方式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('625', '1', '400558', '格式错误', '格式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('626', '1', '400559', '图片流获取失败', '图片流获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('627', '1', '400560', '商品详情保存失败', '商品详情保存失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('628', '1', '400561', '关联优惠券失败', '关联优惠券失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('629', '1', '400562', '缺少商品ID', '缺少商品ID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('63', '1', '110004', '登录状态有误,请重新登录', '登录状态有误,请重新登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('630', '1', '400563', '缺少用户UID', '缺少用户UID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('631', '1', '400564', '缺少订单ID', '缺少订单ID', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('632', '1', '400565', '暂不支持该类型记录', '暂不支持该类型记录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('633', '1', '400566', '添加商品记录失败', '添加商品记录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('634', '1', '400567', '评论时间应小于当前时间', '评论时间应小于当前时间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('635', '1', '400568', '添加虚拟评论失败', '添加虚拟评论失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('636', '1', '400569', '回复失败', '回复失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('637', '1', '400570', '请选择限购类型', '请选择限购类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('638', '1', '400571', '限购数量不能小于1', '限购数量不能小于1', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('639', '1', '400572', '一二级返佣相加不能大于商品售价', '一二级返佣相加不能大于商品售价', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('64', '1', '110005', '请登录', '请登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('640', '1', '400573', '商品类型不能切换', '商品类型不能切换', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('641', '1', '400574', '请输入规则名称', '请输入规则名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('642', '1', '400575', '请输入属性名称', '请输入属性名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('643', '1', '400576', '请输入正确的属性', '请输入正确的属性', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('644', '1', '400577', '请填写正确的商品信息', '请填写正确的商品信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('645', '1', '400578', '请填写正确的商品价格', '请填写正确的商品价格', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('646', '1', '400579', '请填写正确的商品库存', '请填写正确的商品库存', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('647', '1', '400580', '请填写正确的商品成本价格', '请填写正确的商品成本价格', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('648', '1', '400581', '请上传商品图片', '请上传商品图片', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('649', '1', '400582', '{:name}规格不存在', '{:name}规格不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('65', '1', '110006', '登录已过期,请重新登录', '登录已过期,请重新登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('650', '1', '400583', '{:name}属性不存在', '{:name}属性不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('651', '1', '400584', '请设置至少一个属性', '请设置至少一个属性', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('652', '1', '400585', '商品参与秒杀活动开启,无法进行此操作', '商品参与秒杀活动开启,无法进行此操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('653', '1', '400586', '商品参与砍价活动开启,无法进行此操作', '商品参与砍价活动开启,无法进行此操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('654', '1', '400587', '商品参与拼团活动开启,无法进行此操作', '商品参与拼团活动开启,无法进行此操作', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('655', '1', '400588', '会员价格不能为0', '会员价格不能为0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('656', '1', '400589', '虚拟优惠券商品请选择优惠券', '虚拟优惠券商品请选择优惠券', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('657', '1', '400590', '卡号:{:key}密码:{:value},已经添加过,请重新添加卡密', '卡号:{:key}密码:{:value},已经添加过,请重新添加卡密', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('658', '1', '400591', '缺少城市id无法保存', '缺少城市id无法保存', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('659', '1', '400592', '修改的模板不存在', '修改的模板不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('66', '1', '110007', '登录状态有误,请重新登录', '登录状态有误,请重新登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('660', '1', '400593', '指定区域邮费添加失败', '指定区域邮费添加失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('661', '1', '400594', '管理员不存在', '管理员不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('662', '1', '400595', '您已被禁止登录', '您已被禁止登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('663', '1', '400596', '管理员账号已存在', '管理员账号已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('664', '1', '400597', '原始密码错误', '原始密码错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('665', '1', '400598', '请输入新密码', '请输入新密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('666', '1', '400599', '请选择要删除的图片', '请选择要删除的图片', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('667', '1', '400600', '移动失败或不能重复移动到同一分类下', '移动失败或不能重复移动到同一分类下', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('668', '1', '400601', '请求不被允许', '请求不被允许', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('669', '1', '400602', '设置类目不被允许', '设置类目不被允许', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('67', '1', '400000', '请选择用户头像', '请选择用户头像', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('670', '1', '400603', '请输入正确格式的配置参数', '请输入正确格式的配置参数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('671', '1', '400604', '{:name}请输入默认值', '{:name}请输入默认值', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('672', '1', '400605', '{:name}请输入正确url', '{:name}请输入正确url', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('673', '1', '400606', '保存wss证书失败', '保存wss证书失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('674', '1', '400607', '{:name}不能为空', '{:name}不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('675', '1', '400608', '删除的云存储不存在', '删除的云存储不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('676', '1', '400609', '云存储正在使用中,需要启动其他空间才能删除', '云存储正在使用中,需要启动其他空间才能删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('677', '1', '400610', '云空间名称不能重复', '云空间名称不能重复', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('678', '1', '400611', '没有权限', '没有权限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('679', '1', '400612', '替换失败,失败原因:{:msg}', '替换失败,失败原因:{:msg}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('68', '1', '400001', '请填写用户昵称', '请填写用户昵称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('680', '1', '400613', '请先删除改菜单下的子菜单', '请先删除改菜单下的子菜单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('681', '1', '400614', '请填写批次名称', '请填写批次名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('682', '1', '400615', '请填写要生成卡的数量', '请填写要生成卡的数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('683', '1', '400616', '卡片数量只能为正整数', '卡片数量只能为正整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('684', '1', '400617', '单次制卡数量最高不得超过6000张', '单次制卡数量最高不得超过6000张', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('685', '1', '400618', '请填写免费使用天数', '请填写免费使用天数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('686', '1', '400619', '免费使用天数只能为正整数', '免费使用天数只能为正整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('687', '1', '400620', '生成卡失败', '生成卡失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('688', '1', '400621', '会员功能暂未开启', '会员功能暂未开启', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('689', '1', '400622', '请输入会员卡号', '请输入会员卡号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('69', '1', '400002', '请填写评论内容', '请填写评论内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('690', '1', '400623', '请输入领取卡密', '请输入领取卡密', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('691', '1', '400624', '会员卡不存在', '会员卡不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('692', '1', '400625', '会员卡未激活,暂无法使用', '会员卡未激活,暂无法使用', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('693', '1', '400626', '会员卡密码有误', '会员卡密码有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('694', '1', '400627', '会员卡已使用', '会员卡已使用', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('695', '1', '400628', '您已是永久会员,无需再领取,可以将此卡转送亲朋好友,一起享受优惠', '您已是永久会员,无需再领取,可以将此卡转送亲朋好友,一起享受优惠', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('696', '1', '400629', '暂无此类型会员卡', '暂无此类型会员卡', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('697', '1', '400630', '会员权益类型缺失', '会员权益类型缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('698', '1', '400631', '请设置权益名称', '请设置权益名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('699', '1', '400632', '请上传会员权益图标', '请上传会员权益图标', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('7', '1', '100006', '保存失败', '保存失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('70', '1', '400003', '请选择商品分数', '请选择商品分数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('700', '1', '400633', '请设置返还积分倍数', '请设置返还积分倍数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('701', '1', '400634', '返还积分倍数不能为负数', '返还积分倍数不能为负数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('702', '1', '400635', '请设置运费折扣', '请设置运费折扣', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('703', '1', '400636', '运费折扣不能为负数', '运费折扣不能为负数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('704', '1', '400637', '请设置签到积分倍数', '请设置签到积分倍数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('705', '1', '400638', '签到积分倍数不能为负数', '签到积分倍数不能为负数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('706', '1', '400639', '请设置线下付款折扣', '请设置线下付款折扣', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('707', '1', '400640', '线下付款不能为负数', '线下付款不能为负数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('708', '1', '400641', '请填写会员卡名称', '请填写会员卡名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('709', '1', '400642', '会员卡类型缺失', '会员卡类型缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('71', '1', '400004', '请选择服务分数', '请选择服务分数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('710', '1', '400643', '请填写有效期(天)', '请填写有效期(天)', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('711', '1', '400644', '有效期(天)不能为负数', '有效期(天)不能为负数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('712', '1', '400645', '请填写价格', '请填写价格', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('713', '1', '400646', '价格不能为负数', '价格不能为负数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('714', '1', '400647', '优惠价不能大于原价', '优惠价不能大于原价', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('715', '1', '400648', '地址不存在', '地址不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('716', '1', '400649', '取消原来默认地址失败', '取消原来默认地址失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('717', '1', '400650', '设置默认地址失败', '设置默认地址失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('718', '1', '400651', '地址已存在', '地址已存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('719', '1', '400652', '收货地址格式错误', '收货地址格式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('72', '1', '400005', '商品分数必须是1-5之间的整数', '商品分数必须是1-5之间的整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('720', '1', '400653', '请登录', '请登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('721', '1', '400654', '登录已过期,请重新登录', '登录已过期,请重新登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('722', '1', '400655', '增加记录失败', '增加记录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('723', '1', '400656', '记录分享记录失败', '记录分享记录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('724', '1', '400657', '增加用户佣金失败', '增加用户佣金失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('725', '1', '400658', '企业付款到零钱失败,请稍后再试', '企业付款到零钱失败,请稍后再试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('726', '1', '400659', '已经提现', '已经提现', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('727', '1', '400660', '您的提现申请已被拒绝', '您的提现申请已被拒绝', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('728', '1', '400661', '可提现佣金不足', '可提现佣金不足', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('729', '1', '400662', '提现金额不能小于{:money}元', '提现金额不能小于{:money}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('73', '1', '400006', '服务分数必须是1-5之间的整数', '服务分数必须是1-5之间的整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('730', '1', '400663', '提现佣金不足{:money}元', '提现佣金不足{:money}元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('731', '1', '400664', '提现佣金大于0', '提现佣金大于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('732', '1', '400665', '企业微信付款到零钱最低金额为1元', '企业微信付款到零钱最低金额为1元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('733', '1', '400666', '该分组已经存在', '该分组已经存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('734', '1', '400667', '清空用户标签失败', '清空用户标签失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('735', '1', '400668', '设置标签失败', '设置标签失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('736', '1', '400669', '请选择标签分类', '请选择标签分类', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('737', '1', '400670', '该标签已经存在', '该标签已经存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('738', '1', '400671', '修改用户等级信息失败', '修改用户等级信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('739', '1', '400672', '用户等级不存在', '用户等级不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('74', '1', '400007', '请选择快递公司', '请选择快递公司', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('740', '1', '400673', '用户等级经验必须大于上一等级设置的经验', '用户等级经验必须大于上一等级设置的经验', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('741', '1', '400674', '用户等级经验必须小于下一等级设置的经验', '用户等级经验必须小于下一等级设置的经验', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('742', '1', '400675', '已检测到您设置过的用户等级,此等级不可重复', '已检测到您设置过的用户等级,此等级不可重复', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('743', '1', '400676', '已检测到您设置过该用户等级经验值,经验值不可重复', '已检测到您设置过该用户等级经验值,经验值不可重复', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('744', '1', '400677', '订单未支付', '订单未支付', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('745', '1', '400678', '佣金转入余额,不能退款', '佣金转入余额,不能退款', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('746', '1', '400679', '已支付的订单记录无法删除', '已支付的订单记录无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('747', '1', '400680', '转入金额不能大于可提现佣金', '转入金额不能大于可提现佣金', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('748', '1', '400681', '写入余额充值失败', '写入余额充值失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('749', '1', '400682', '您选择的充值方式已下架', '您选择的充值方式已下架', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('75', '1', '400008', '请填写寄件人姓名', '请填写寄件人姓名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('750', '1', '400683', '充值订单生成失败', '充值订单生成失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('751', '1', '400684', '保存用户信息失败', '保存用户信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('752', '1', '400685', '密码重置失败', '密码重置失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('753', '1', '400686', '增加推广人数失败', '增加推广人数失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('754', '1', '400687', '设置登录类型失败', '设置登录类型失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('755', '1', '400688', '设置推广员失败', '设置推广员失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('756', '1', '400689', '增加用户余额失败', '增加用户余额失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('757', '1', '400690', '减少用户余额失败', '减少用户余额失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('758', '1', '400691', '减少用户佣金失败', '减少用户佣金失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('759', '1', '400692', '增加用户积分失败', '增加用户积分失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('76', '1', '400009', '请输入寄件人手机号码', '请输入寄件人手机号码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('760', '1', '400693', '减少用户积分失败', '减少用户积分失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('761', '1', '400694', '增加用户经验失败', '增加用户经验失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('762', '1', '400695', '减少用户经验失败', '减少用户经验失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('763', '1', '400696', '该分组不存在', '该分组不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('764', '1', '400697', '设置分组失败或无改动', '设置分组失败或无改动', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('765', '1', '400698', '有标签不存在或被删除', '有标签不存在或被删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('766', '1', '400699', '等级不存在或被删除', '等级不存在或被删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('767', '1', '400700', '此用户已有该用户等级,无法再次赠送', '此用户已有该用户等级,无法再次赠送', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('768', '1', '400701', '赠送天数不能为0', '赠送天数不能为0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('769', '1', '400702', '天数输入错误', '天数输入错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('77', '1', '400010', '寄件人手机号码不正确', '寄件人手机号码不正确', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('770', '1', '400703', '用户信息储存失败', '用户信息储存失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('771', '1', '400704', '您得ip不再白名单中,请前往腾讯微信公众平台添加ip白名单', '您得ip不再白名单中,请前往腾讯微信公众平台添加ip白名单', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('772', '1', '400705', '您填写得appid无效,请检查', '您填写得appid无效,请检查', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('773', '1', '400706', '请输入回复信息内容', '请输入回复信息内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('774', '1', '400707', '请上传回复的图片', '请上传回复的图片', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('775', '1', '400708', '请上传回复的声音', '请上传回复的声音', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('776', '1', '400709', '请选择图文消息', '请选择图文消息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('777', '1', '400710', '对应的uid不存在', '对应的uid不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('778', '1', '400711', '取消关注失败', '取消关注失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('779', '1', '400712', '电子面单模板ID缺失', '电子面单模板ID缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('78', '1', '400011', '请填写寄件人详细地址', '请填写寄件人详细地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('780', '1', '400713', '快递公司编码缺失', '快递公司编码缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('781', '1', '400714', '寄件人信息缺失', '寄件人信息缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('782', '1', '400715', '收件人信息缺失', '收件人信息缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('783', '1', '400716', '云打印机编号缺失', '云打印机编号缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('784', '1', '400717', '商品数量缺失', '商品数量缺失', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('785', '1', '400718', '获取access_token获取失败', '获取access_token获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('786', '1', '400719', '手机号不能为空', '手机号不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('787', '1', '400720', '模版ID不存在', '模版ID不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('788', '1', '400721', '请先配置accessKey和secretKey', '请先配置accessKey和secretKey', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('789', '1', '400722', '请先配置水印图片', '请先配置水印图片', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('79', '1', '400012', '请填写云打印机编号', '请填写云打印机编号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('790', '1', '400723', '请先配置水印文字', '请先配置水印文字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('791', '1', '400724', '远程水印图片下载失败', '远程水印图片下载失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('792', '1', '400725', '上传图片不存在', '上传图片不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('793', '1', '400726', '图片流获取失败', '图片流获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('794', '1', '400727', '图片下载失败', '图片下载失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('795', '1', '400728', '必须上传xlsx格式文件', '必须上传xlsx格式文件', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('796', '1', '400729', '数据不能为空', '数据不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('797', '1', '400730', '缺少pay_price', '缺少pay_price', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('798', '1', '400731', '退款失败:{:msg}', '退款失败:{:msg}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('799', '1', '400732', '获取微信粉丝信息失败', '获取微信粉丝信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('8', '1', '100007', '修改失败', '修改失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('80', '1', '400013', '请传入套餐id', '请传入套餐id', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('800', '1', '400733', '您已关闭上传功能', '您已关闭上传功能', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('801', '1', '400734', '文件不可写', '文件不可写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('802', '1', '400735', '时间格式不正确', '时间格式不正确', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('803', '1', '400736', '文件可能损坏,请检查', '文件可能损坏,请检查', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('804', '1', '400737', '修复错误,请重试', '修复错误,请重试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('805', '1', '400738', '请指定要修复的表', '请指定要修复的表', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('806', '1', '400739', '请配置支付证书', '请配置支付证书', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('807', '1', '400740', '只支持两级分类', '只支持两级分类', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('808', '1', '400741', '运费格式错误', '运费格式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('809', '1', '400742', '请检查属性编码或库存数量', '请检查属性编码或库存数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('81', '1', '400014', '套餐id必须为数字', '套餐id必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('810', '1', '400743', '同步条数不能超过100', '同步条数不能超过100', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('811', '1', '400744', 'appid或appsecret错误', 'appid或appsecret错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('812', '1', '400745', '父级ID参数类型错误', '父级ID参数类型错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('813', '1', '400746', '分类名称长度不能超过25个字符', '分类名称长度不能超过25个字符', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('814', '1', '400747', '分类图标长度不能超过128个字符', '分类图标长度不能超过128个字符', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('815', '1', '400748', '分类大图长度不能超过200个字符', '分类大图长度不能超过200个字符', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('816', '1', '400749', '排序参数类型错误', '排序参数类型错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('817', '1', '400750', '排序不能小于0', '排序不能小于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('818', '1', '400751', '状态必须是0-1之间的整数', '状态必须是0-1之间的整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('819', '1', '400752', '权益简介不能大于8个字', '权益简介不能大于8个字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('82', '1', '400015', '请填写套餐金额', '请填写套餐金额', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('820', '1', '400753', '提现方式最少选一种', '提现方式最少选一种', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('821', '1', '400754', '身份使用中,无法删除', '身份使用中,无法删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('822', '1', '400755', '展示名称不能大于6个字', '展示名称不能大于6个字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('823', '1', '400756', '推广佣金单价不能小于0', '推广佣金单价不能小于0', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('824', '1', '400757', '每日推广佣金上限不能小于-1', '每日推广佣金上限不能小于-1', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('825', '1', '400758', '请核对领取方式', '请核对领取方式', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('826', '1', '400759', '请输入优惠券名称', '请输入优惠券名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('827', '1', '400760', '请输入真实姓名', '请输入真实姓名', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('828', '1', '400761', '描述内容不能超过120字', '描述内容不能超过120字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('829', '1', '400762', '账号密码必须是在6到32位之间', '账号密码必须是在6到32位之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('83', '1', '400016', '请填写购买数量', '请填写购买数量', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('830', '1', '400763', '商户号不能为空', '商户号不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('831', '1', '410000', '请输入账号和密码', '请输入账号和密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('832', '1', '410001', '登录成功', '登录成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('833', '1', '410002', '退出成功', '退出成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('834', '1', '410003', '发送验证码失败,请刷新页面重新获取', '发送验证码失败,请刷新页面重新获取', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('835', '1', '410004', '请输入验证码', '请输入验证码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('836', '1', '410005', '验证码输入有误', '验证码输入有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('837', '1', '410006', '验证码已发送', '验证码已发送', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('838', '1', '410007', '验证码发送成功', '验证码发送成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('839', '1', '410008', '验证码发送失败', '验证码发送失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('84', '1', '400017', '购买数量必须为数字', '购买数量必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('840', '1', '410009', '请先获取验证码', '请先获取验证码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('841', '1', '410010', '验证码错误', '验证码错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('842', '1', '410011', '密码必须是在6到16位之间', '密码必须是在6到16位之间', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('843', '1', '410012', '密码太过简单,请输入较为复杂的密码', '密码太过简单,请输入较为复杂的密码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('844', '1', '410013', '注册成功', '注册成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('845', '1', '410014', '注册失败', '注册失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('846', '1', '410015', '请输入手机号', '请输入手机号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('847', '1', '410016', '绑定成功', '绑定成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('848', '1', '410017', '绑定失败', '绑定失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('849', '1', '410018', '手机号格式不正确', '手机号格式不正确', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('85', '1', '400018', '请填写购买套餐类型', '请填写购买套餐类型', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('850', '1', '410019', '登录失败', '登录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('851', '1', '410020', '扫码失败请重新扫描', '扫码失败请重新扫描', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('852', '1', '410021', '二维码已过期请重新扫描', '二维码已过期请重新扫描', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('853', '1', '410022', '授权成功,请绑定手机号', '授权成功,请绑定手机号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('854', '1', '410023', '授权成功', '授权成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('855', '1', '410024', '请先关注公众号', '请先关注公众号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('856', '1', '410025', '账号或密码错误', '账号或密码错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('857', '1', '410026', '请修改您的初始密码,再尝试登录', '请修改您的初始密码,再尝试登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('858', '1', '410027', '您已被禁止登录,请联系管理员', '您已被禁止登录,请联系管理员', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('859', '1', '410028', '手机号已注册', '手机号已注册', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('86', '1', '400019', '您输入的手机号码必须为数字', '您输入的手机号码必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('860', '1', '410029', '您今日发送得短信次数已经达到上限', '您今日发送得短信次数已经达到上限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('861', '1', '410030', '此IP今日发送次数已经达到上限', '此IP今日发送次数已经达到上限', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('862', '1', '410031', '短信平台验证码发送失败', '短信平台验证码发送失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('863', '1', '410032', '用户不存在', '用户不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('864', '1', '410033', '修改密码失败', '修改密码失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('865', '1', '410034', '用户登录失败,无法生成新用户,请稍后再试', '用户登录失败,无法生成新用户,请稍后再试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('866', '1', '410035', '用户不存在,无法切换', '用户不存在,无法切换', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('867', '1', '410036', '修改新用户登录类型出错', '修改新用户登录类型出错', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('868', '1', '410037', '请刷新页面或者重新授权', '请刷新页面或者重新授权', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('869', '1', '410038', '获取用户访问token失败', '获取用户访问token失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('87', '1', '400020', '密码必须填写', '密码必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('870', '1', '410039', '此手机已经绑定,无法多次绑定', '此手机已经绑定,无法多次绑定', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('871', '1', '410040', '您的账号已经绑定过手机号码', '您的账号已经绑定过手机号码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('872', '1', '410041', 'H5已有账号是否绑定此账号上', 'H5已有账号是否绑定此账号上', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('873', '1', '410042', '新手机号和原手机号相同,无需修改', '新手机号和原手机号相同,无需修改', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('874', '1', '410043', '此手机已经注册', '此手机已经注册', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('875', '1', '410044', '用户信息获取失败', '用户信息获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('876', '1', '410045', '请选择收货地址', '请选择收货地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('877', '1', '410046', '地址选择有误', '地址选择有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('878', '1', '410047', '可用积分不足', '可用积分不足', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('879', '1', '410048', '奖品不存在', '奖品不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('88', '1', '400021', '短信验证码必须为数字', '短信验证码必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('880', '1', '410049', '写入中奖记录失败', '写入中奖记录失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('881', '1', '410050', '请继续参与活动抽奖', '请继续参与活动抽奖', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('882', '1', '410051', '已经领取成功', '已经领取成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('883', '1', '410052', '请输入收货人信息', '请输入收货人信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('884', '1', '410053', '请输入正确的收货人电话', '请输入正确的收货人电话', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('885', '1', '410054', '抽奖记录不存在', '抽奖记录不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('886', '1', '410055', '该奖品不需要发货', '该奖品不需要发货', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('887', '1', '410056', '请选择快递公司或输入快递单号', '请选择快递公司或输入快递单号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('888', '1', '410057', '活动不存在或已删除', '活动不存在或已删除', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('889', '1', '410058', '暂未有该类型活动', '暂未有该类型活动', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('89', '1', '400022', '请填写话术内容', '请填写话术内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('890', '1', '410059', '您暂时无法参与该活动', '您暂时无法参与该活动', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('891', '1', '410060', '活动状态有误,请联系管理员', '活动状态有误,请联系管理员', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('892', '1', '410061', '可用积分不足,没有更多抽奖次数', '可用积分不足,没有更多抽奖次数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('893', '1', '410062', '余额不足,没有更多抽奖次数', '余额不足,没有更多抽奖次数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('894', '1', '410063', '购买商品之后获得更多抽奖次数', '购买商品之后获得更多抽奖次数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('895', '1', '410064', '订单完成评价之后获得更多抽奖次数', '订单完成评价之后获得更多抽奖次数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('896', '1', '410065', '邀请更多好友获取抽奖次数', '邀请更多好友获取抽奖次数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('897', '1', '410066', '抽奖扣除用户积分失败', '抽奖扣除用户积分失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('898', '1', '410067', '抽奖失败,余额不足', '抽奖失败,余额不足', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('899', '1', '410068', '抽奖扣除用户余额失败', '抽奖扣除用户余额失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('9', '1', '100008', '删除失败', '删除失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('90', '1', '400023', '请填写排序数字', '请填写排序数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('900', '1', '410069', '抽奖扣除用户推广获取抽奖次数失败', '抽奖扣除用户推广获取抽奖次数失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('901', '1', '410070', '抽奖减少奖品总数失败', '抽奖减少奖品总数失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('902', '1', '410071', '分销等级不存在', '分销等级不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('903', '1', '410072', '永久二维码获取错误', '永久二维码获取错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('904', '1', '410073', '邀请码无效', '邀请码无效', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('905', '1', '410074', '授权失败,参数有误', '授权失败,参数有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('906', '1', '410075', 'openid获取失败', 'openid获取失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('907', '1', '410076', '获取session_key失败,请检查您的配置', '获取session_key失败,请检查您的配置', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('908', '1', '410077', '获取会话密匙失败', '获取会话密匙失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('909', '1', '410078', '静默授权失败', '静默授权失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('91', '1', '400024', '请填写排序数字', '请填写排序数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('910', '1', '410079', '获取用户信息失败', '获取用户信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('911', '1', '410080', '更新信息失败', '更新信息失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('912', '1', '410081', '请上传二维码', '请上传二维码', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('913', '1', '410082', '请关注公众号', '请关注公众号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('914', '1', '410083', '新增用户失败', '新增用户失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('915', '1', '410084', '用户关注失败', '用户关注失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('916', '1', '410085', '获取token失败{:msg}', '获取token失败{:msg}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('917', '1', '410086', '配置已更改或token已失效', '配置已更改或token已失效', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('918', '1', '410087', '平台错误:发生异常,请稍后重试', '平台错误:发生异常,请稍后重试', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('919', '1', '410088', '企业微信支付到零钱需要支付证书,检测到您没有上传', '企业微信支付到零钱需要支付证书,检测到您没有上传', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('92', '1', '400025', '请填写运费模板名称', '请填写运费模板名称', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('920', '1', '410089', '发起企业支付到零钱失败', '发起企业支付到零钱失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('921', '1', '410090', '无效的token不能查找到用户聊天记录', '无效的token不能查找到用户聊天记录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('922', '1', '410091', '图片上传成功', '图片上传成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('923', '1', '410092', '用户uid不再当前聊天用户范围内', '用户uid不再当前聊天用户范围内', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('924', '1', '410093', '请输入订单价格', '请输入订单价格', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('925', '1', '410094', '请去后台售后订单列表处理', '请去后台售后订单列表处理', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('926', '1', '410095', '分类名称不能为空', '分类名称不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('927', '1', '410096', '分类不存在', '分类不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('928', '1', '410097', '添加的内容重复', '添加的内容重复', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('929', '1', '410098', '缺少转接人id', '缺少转接人id', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('93', '1', '400026', '运费信息必须为数组', '运费信息必须为数组', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('930', '1', '410099', '转接成功', '转接成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('931', '1', '410100', '话术没有被查到', '话术没有被查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('932', '1', '410101', '公共话术不能修改', '公共话术不能修改', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('933', '1', '410102', '话术标题内容不能为空', '话术标题内容不能为空', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('934', '1', '410103', '已拥有此分组', '已拥有此分组', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('935', '1', '410104', '缺少标签id', '缺少标签id', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('936', '1', '410105', '请填汉字字母或者数字', '请填汉字字母或者数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('937', '1', '410106', '标题长度不能超过50个字', '标题长度不能超过50个字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('938', '1', '410107', '请选择分类', '请选择分类', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('939', '1', '410108', '分类必须为数字', '分类必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('94', '1', '400027', '包邮信息必须为数组', '包邮信息必须为数组', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('940', '1', '410109', '请填写话术内容', '请填写话术内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('941', '1', '410110', '话术长度不能超过500个字', '话术长度不能超过500个字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('942', '1', '410111', '排序必须为数字', '排序必须为数字', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('943', '1', '410112', '微信最低提现金额不能小于1元', '微信最低提现金额不能小于1元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('944', '1', '410113', '用户不存在', '用户不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('945', '1', '410114', '提现方式不存在', '提现方式不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('946', '1', '410115', '提现金额输入有误', '提现金额输入有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('947', '1', '410116', '银行卡号输入有误', '银行卡号输入有误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('948', '1', '410117', '请输入支付宝账号', '请输入支付宝账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('949', '1', '410118', '请输入银行卡账号', '请输入银行卡账号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('95', '1', '400028', '不送达信息必须为数组', '不送达信息必须为数组', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('950', '1', '410119', '请输入开户行信息', '请输入开户行信息', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('951', '1', '410120', '申请提现成功', '申请提现成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('952', '1', '410121', '申请提现失败', '申请提现失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('953', '1', '410122', '充值金额不能为0元', '充值金额不能为0元', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('954', '1', '410123', '充值方式不支持', '充值方式不支持', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('955', '1', '410124', '充值金额不能低于{:money}', '充值金额不能低于{:money}', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('956', '1', '410125', '充值成功', '充值成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('957', '1', '410126', '充值失败', '充值失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('958', '1', '410127', '签到获得{:integral}积分', '签到获得{:integral}积分', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('959', '1', '410128', '签到失败', '签到失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('96', '1', '400029', 'type数据格式错误,应为1或2或3', 'type数据格式错误,应为1或2或3', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('960', '1', '410129', '收藏成功', '收藏成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('961', '1', '410130', '收藏失败', '收藏失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('962', '1', '410131', '授权失败', '授权失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('963', '1', '410132', 'unionid不存在', 'unionid不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('964', '1', '410133', '获取用户UID失败', '获取用户UID失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('965', '1', '410134', '请输入昵称或者选择头像', '请输入昵称或者选择头像', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('966', '1', '410135', '注销成功', '注销成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('967', '1', '410136', '暂无客服人员在线,请稍后联系', '暂无客服人员在线,请稍后联系', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('968', '1', '410137', '不能和自己聊天', '不能和自己聊天', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('969', '1', '410138', '您不是客服无法登录', '您不是客服无法登录', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('97', '1', '400030', 'appoint数据格式错误,应为0或1', 'appoint数据格式错误,应为0或1', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('970', '1', '410139', '自己不能转接给自己', '自己不能转接给自己', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('971', '1', '410140', '转接客服失败', '转接客服失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('972', '1', '410141', '没有此用户', '没有此用户', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('973', '1', '410142', '客服不存在', '客服不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('974', '1', '410143', '商品未查到', '商品未查到', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('975', '1', '410144', '请填写开票手机号', '请填写开票手机号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('976', '1', '410145', '请填写发票抬头(开具发票企业名称)', '请填写发票抬头(开具发票企业名称)', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('977', '1', '410146', '请填写正确的发票抬头(开具发票企业名称)', '请填写正确的发票抬头(开具发票企业名称)', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('978', '1', '410147', '请填写发票税号', '请填写发票税号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('979', '1', '410148', '请填写正确的发票税号', '请填写正确的发票税号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('98', '1', '400031', 'no_delivery数据格式错误,应为0或1', 'no_delivery数据格式错误,应为0或1', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('980', '1', '410149', '请填写正确的银行卡号', '请填写正确的银行卡号', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('981', '1', '410150', '地址不存在', '地址不存在', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('982', '1', '410151', '收货地址格式错误', '收货地址格式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('983', '1', '410152', '收货地址格式错误或系统未完善当前地址', '收货地址格式错误或系统未完善当前地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('984', '1', '410153', '收货地址格式错误,请重新选择', '收货地址格式错误,请重新选择', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('985', '1', '410154', '请填写详细地址', '请填写详细地址', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('986', '1', '410155', '名称必须填写', '名称必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('987', '1', '410156', '名称最多不能超过25个字符', '名称最多不能超过25个字符', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('988', '1', '410157', '手机号必须填写', '手机号必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('989', '1', '410158', '手机号格式错误', '手机号格式错误', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('99', '1', '400032', 'sort数据格式错误,应为整数', 'sort数据格式错误,应为整数', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('990', '1', '410159', '省必须填写', '省必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('991', '1', '410160', '市必须填写', '市必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('992', '1', '410161', '区/县必须填写', '区/县必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('993', '1', '410162', '详细地址必须填写', '详细地址必须填写', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('994', '1', '410163', '请填写反馈内容', '请填写反馈内容', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('995', '1', '410164', '比例不能大于您的比例', '比例不能大于您的比例', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('996', '1', '410165', '激活成功', '激活成功', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('997', '1', '410166', '暂无海报', '暂无海报', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('998', '1', '410167', '二维码生成失败', '二维码生成失败', 1); +INSERT INTO `lms_clx_lang_code` VALUES ('999', '1', '410168', '缺少字体文件Bold', '缺少字体文件Bold', 1); + +-- ---------------------------- +-- Table structure for lms_clx_lang_country +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_lang_country`; +CREATE TABLE `lms_clx_lang_country` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID', + `type_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '管理语言类型', + `code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '国家标识', + `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '国家名称', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '浏览器语言类型表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_lang_country +-- ---------------------------- +INSERT INTO `lms_clx_lang_country` VALUES ('10', '0', 'ar-BH', '阿拉伯语(巴林) '); +INSERT INTO `lms_clx_lang_country` VALUES ('100', '0', 'sa-IN', '梵语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('101', '0', 'fil', '菲律宾语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('102', '0', 'fil-PH', '菲律宾语(菲律宾) '); +INSERT INTO `lms_clx_lang_country` VALUES ('103', '0', 'fi', '芬兰语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('104', '0', 'fi-FI', '芬兰语(芬兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('105', '0', 'fy', '弗里西亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('106', '0', 'fy-NL', '弗里西亚语(荷兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('107', '0', 'km', '高棉语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('108', '0', 'km-KH', '高棉语(柬埔寨) '); +INSERT INTO `lms_clx_lang_country` VALUES ('109', '0', 'kl', '格陵兰语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('11', '0', 'ar-QA', '阿拉伯语(卡塔尔) '); +INSERT INTO `lms_clx_lang_country` VALUES ('110', '0', 'kl-GL', '格陵兰语(格陵兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('111', '0', 'ka', '格鲁吉亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('112', '0', 'ka-GE', '格鲁吉亚语(格鲁吉亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('113', '0', 'gu', '古吉拉特语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('114', '0', 'gu-IN', '古吉拉特语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('115', '0', 'kk', '哈萨克语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('116', '0', 'kk-KZ', '哈萨克语(哈萨克斯坦) '); +INSERT INTO `lms_clx_lang_country` VALUES ('117', '0', 'ha', '豪撒语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('118', '0', 'ha-Latn', '豪撒语(拉丁语) '); +INSERT INTO `lms_clx_lang_country` VALUES ('119', '0', 'ha-Latn-NG', '豪撒语(拉丁语,尼日利亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('12', '0', 'ar-KW', '阿拉伯语(科威特) '); +INSERT INTO `lms_clx_lang_country` VALUES ('120', '0', 'nl', '荷兰语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('121', '0', 'nl-BE', '荷兰语(比利时) '); +INSERT INTO `lms_clx_lang_country` VALUES ('122', '0', 'nl-NL', '荷兰语(荷兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('123', '0', 'qut', '基切语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('124', '0', 'qut-GT', '基切语(危地马拉) '); +INSERT INTO `lms_clx_lang_country` VALUES ('125', '0', 'ky', '吉尔吉斯语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('126', '0', 'ky-KG', '吉尔吉斯语(吉尔吉斯斯坦) '); +INSERT INTO `lms_clx_lang_country` VALUES ('127', '0', 'gl', '加利西亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('128', '0', 'gl-ES', '加利西亚语(加利西亚语) '); +INSERT INTO `lms_clx_lang_country` VALUES ('129', '0', 'ca', '加泰罗尼亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('13', '0', 'ar-LB', '阿拉伯语(黎巴嫩) '); +INSERT INTO `lms_clx_lang_country` VALUES ('130', '0', 'ca-ES', '加泰罗尼亚语(加泰罗尼亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('131', '0', 'cs', '捷克语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('132', '0', 'cs-CZ', '捷克语(捷克共和国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('133', '0', 'co', '科西嘉语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('134', '0', 'co-FR', '科西嘉语(法国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('135', '0', 'hr', '克罗地亚语'); +INSERT INTO `lms_clx_lang_country` VALUES ('136', '0', 'hr-HR', '克罗地亚语(克罗地亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('137', '0', 'hr-B', '克罗地亚语(拉丁语,波斯尼亚和黑塞哥维那) '); +INSERT INTO `lms_clx_lang_country` VALUES ('138', '0', 'quz', '克丘亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('139', '0', 'quz-BO', '克丘亚语(玻利维亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('14', '0', 'ar-LY', '阿拉伯语(利比亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('140', '0', 'quz-EC', '克丘亚语(厄瓜多尔) '); +INSERT INTO `lms_clx_lang_country` VALUES ('141', '0', 'quz-PE', '克丘亚语(秘鲁) '); +INSERT INTO `lms_clx_lang_country` VALUES ('142', '0', 'kok', '孔卡尼语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('143', '0', 'kok-IN', '孔卡尼语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('144', '0', 'lv', '拉脱维亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('145', '0', 'lv-LV', '拉脱维亚语(拉脱维亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('146', '0', 'lo', '老挝语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('147', '0', 'lo-LA', '老挝语(老挝人民民主共和国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('148', '0', 'lt', '立陶宛语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('149', '0', 'lt-LT', '立陶宛语(立陶宛) '); +INSERT INTO `lms_clx_lang_country` VALUES ('15', '0', 'ar-MA', '阿拉伯语(摩洛哥) '); +INSERT INTO `lms_clx_lang_country` VALUES ('150', '0', 'lb', '卢森堡语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('151', '0', 'lb-LU', '卢森堡语(卢森堡) '); +INSERT INTO `lms_clx_lang_country` VALUES ('152', '0', 'rw', '卢旺达语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('153', '0', 'rw-RW', '卢旺达语(卢旺达) '); +INSERT INTO `lms_clx_lang_country` VALUES ('154', '0', 'ro', '罗马尼亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('155', '0', 'ro-RO', '罗马尼亚语(罗马尼亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('156', '0', 'rm', '罗曼什语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('157', '0', 'rm-CH', '罗曼什语(瑞士) '); +INSERT INTO `lms_clx_lang_country` VALUES ('158', '0', 'smj', '律勒萨米语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('159', '0', 'smj-NO', '律勒萨米语(挪威) '); +INSERT INTO `lms_clx_lang_country` VALUES ('16', '0', 'ar-SA', '阿拉伯语(沙特阿拉伯) '); +INSERT INTO `lms_clx_lang_country` VALUES ('160', '0', 'smj-SE', '律勒萨米语(瑞典) '); +INSERT INTO `lms_clx_lang_country` VALUES ('161', '0', 'mt', '马耳他语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('162', '0', 'mt-MT', '马耳他语(马耳他) '); +INSERT INTO `lms_clx_lang_country` VALUES ('163', '0', 'mr', '马拉地语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('164', '0', 'mr-IN', '马拉地语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('165', '0', 'ml', '马拉雅拉姆语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('166', '0', 'ml-IN', '马拉雅拉姆语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('167', '0', 'ms', '马来语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('168', '0', 'ms-MY', '马来语(马来西亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('169', '0', 'ms-BN', '马来语(文莱达鲁萨兰国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('17', '0', 'ar-TN', '阿拉伯语(突尼斯) '); +INSERT INTO `lms_clx_lang_country` VALUES ('170', '0', 'arn', '马普丹冈语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('171', '0', 'arn-CL', '马普丹冈语(智利) '); +INSERT INTO `lms_clx_lang_country` VALUES ('172', '0', 'mk', '马其顿语(前南斯拉夫马其顿共和国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('173', '0', 'mk-MK', '马其顿语(前南斯拉夫马其顿共和国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('174', '0', 'mi', '毛利语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('175', '0', 'mi-NZ', '毛利语(新西兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('176', '0', 'mn', '蒙古语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('177', '0', 'mn-Mong', '蒙古语(传统蒙古语) '); +INSERT INTO `lms_clx_lang_country` VALUES ('178', '0', 'mn-Mong-CN', '蒙古语(传统蒙古语,中国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('179', '0', 'mn-Cyrl', '蒙古语(西里尔文) '); +INSERT INTO `lms_clx_lang_country` VALUES ('18', '0', 'ar-SY', '阿拉伯语(叙利亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('180', '0', 'mn-MN', '蒙古语(西里尔文,蒙古) '); +INSERT INTO `lms_clx_lang_country` VALUES ('181', '0', 'bn', '孟加拉语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('182', '0', 'bn-BD', '孟加拉语(孟加拉国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('183', '0', 'bn-IN', '孟加拉语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('184', '0', 'moh', '莫霍克语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('185', '0', 'moh-CA', '莫霍克语(莫霍克) '); +INSERT INTO `lms_clx_lang_country` VALUES ('186', '0', 'af', '南非荷兰语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('187', '0', 'af-ZA', '南非荷兰语(南非) '); +INSERT INTO `lms_clx_lang_country` VALUES ('188', '0', 'sma', '南萨米语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('189', '0', 'sma-NO', '南萨米语(挪威) '); +INSERT INTO `lms_clx_lang_country` VALUES ('19', '0', 'ar-YE', '阿拉伯语(也门) '); +INSERT INTO `lms_clx_lang_country` VALUES ('190', '0', 'sma-SE', '南萨米语(瑞典) '); +INSERT INTO `lms_clx_lang_country` VALUES ('191', '0', 'ne', '尼泊尔语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('192', '0', 'ne-NP', '尼泊尔语(尼泊尔) '); +INSERT INTO `lms_clx_lang_country` VALUES ('193', '0', 'nn-NO', '尼诺斯克挪威语(挪威) '); +INSERT INTO `lms_clx_lang_country` VALUES ('194', '0', 'no', '挪威语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('195', '0', 'nn', '挪威语(尼诺斯克语) '); +INSERT INTO `lms_clx_lang_country` VALUES ('196', '0', 'pa', '旁遮普语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('197', '0', 'pa-IN', '旁遮普语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('198', '0', 'pt', '葡萄牙语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('199', '0', 'pt-BR', '葡萄牙语(巴西) '); +INSERT INTO `lms_clx_lang_country` VALUES ('20', '0', 'ar-IQ', '阿拉伯语(伊拉克) '); +INSERT INTO `lms_clx_lang_country` VALUES ('200', '0', 'pt-PT', '葡萄牙语(葡萄牙) '); +INSERT INTO `lms_clx_lang_country` VALUES ('201', '0', 'ps', '普什图语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('202', '0', 'ps-AF', '普什图语(阿富汗) '); +INSERT INTO `lms_clx_lang_country` VALUES ('203', '0', 'ja', '日语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('204', '0', 'ja-JP', '日语(日本) '); +INSERT INTO `lms_clx_lang_country` VALUES ('205', '0', 'sv', '瑞典语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('206', '0', 'sv-FI', '瑞典语(芬兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('207', '0', 'sv-SE', '瑞典语(瑞典) '); +INSERT INTO `lms_clx_lang_country` VALUES ('208', '0', 'sr', '塞尔维亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('209', '0', 'sr-Latn', '塞尔维亚语(拉丁语) '); +INSERT INTO `lms_clx_lang_country` VALUES ('21', '0', 'ar-JO', '阿拉伯语(约旦) '); +INSERT INTO `lms_clx_lang_country` VALUES ('210', '0', 'sr-L', '塞尔维亚语(拉丁语,波斯尼亚和黑塞哥维那) '); +INSERT INTO `lms_clx_lang_country` VALUES ('211', '0', 'sr-Latn-ME', '塞尔维亚语(拉丁语,黑山共和国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('212', '0', 'sr-Latn-RS', '塞尔维亚语(拉丁语,塞尔维亚共和国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('213', '0', 'sr-Lat', '塞尔维亚语(拉丁语,塞尔维亚和黑山(前)) '); +INSERT INTO `lms_clx_lang_country` VALUES ('214', '0', 'sr-Cyrl', '塞尔维亚语(西里尔文) '); +INSERT INTO `lms_clx_lang_country` VALUES ('215', '0', 'sr', '塞尔维亚语(西里尔文,波斯尼亚和黑塞哥维那) '); +INSERT INTO `lms_clx_lang_country` VALUES ('216', '0', 'sr-Cyrl-ME', '塞尔维亚语(西里尔文,黑山共和国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('217', '0', 'sr-Cyrl-', '塞尔维亚语(西里尔文,塞尔维亚共和国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('218', '0', 'sr-C', '塞尔维亚语(西里尔文,塞尔维亚和黑山(前)) '); +INSERT INTO `lms_clx_lang_country` VALUES ('219', '0', 'si', '僧伽罗语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('22', '0', 'am', '阿姆哈拉语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('220', '0', 'si-LK', '僧伽罗语(斯里兰卡) '); +INSERT INTO `lms_clx_lang_country` VALUES ('221', '0', 'hsb', '上索布语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('222', '0', 'hsb-DE', '上索布语(德国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('223', '0', 'nb', '书面挪威语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('224', '0', 'nb-NO', '书面挪威语(挪威) '); +INSERT INTO `lms_clx_lang_country` VALUES ('225', '0', 'sms', '斯科特萨米语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('226', '0', 'sms-FI', '斯科特萨米语(芬兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('227', '0', 'sk', '斯洛伐克语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('228', '0', 'sk-SK', '斯洛伐克语(斯洛伐克) '); +INSERT INTO `lms_clx_lang_country` VALUES ('229', '0', 'sl', '斯洛文尼亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('23', '0', 'am-ET', '阿姆哈拉语(埃塞俄比亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('230', '0', 'sl-SI', '斯洛文尼亚语(斯洛文尼亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('231', '0', 'sw', '斯瓦希里语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('232', '0', 'sw-KE', '斯瓦希里语(肯尼亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('233', '0', 'gd', '苏格兰盖立语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('234', '0', 'gd-GB', '苏格兰盖立语(英国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('235', '0', 'xh', '索萨语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('236', '0', 'xh-ZA', '索萨语(南非) '); +INSERT INTO `lms_clx_lang_country` VALUES ('237', '0', 'tg', '塔吉克语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('238', '0', 'tg-Cyrl', '塔吉克语(西里尔文) '); +INSERT INTO `lms_clx_lang_country` VALUES ('239', '0', 'tg-Cyrl-TJ', '塔吉克语(西里尔文,塔吉克斯坦) '); +INSERT INTO `lms_clx_lang_country` VALUES ('24', '0', 'as', '阿萨姆语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('240', '0', 'tzm', '塔马塞特语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('241', '0', 'tzm-Latn', '塔马塞特语(拉丁语) '); +INSERT INTO `lms_clx_lang_country` VALUES ('242', '0', 'tzm-Latn-DZ', '塔马塞特语(拉丁语,阿尔及利亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('243', '0', 'th', '泰国语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('244', '0', 'te', '泰卢固语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('245', '0', 'te-IN', '泰卢固语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('246', '0', 'ta', '泰米尔语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('247', '0', 'ta-IN', '泰米尔语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('248', '0', 'th-TH', '泰语(泰国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('249', '0', 'tr', '土耳其语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('25', '0', 'as-IN', '阿萨姆语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('250', '0', 'tr-TR', '土耳其语(土耳其) '); +INSERT INTO `lms_clx_lang_country` VALUES ('251', '0', 'tk', '土库曼语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('252', '0', 'tk-TM', '土库曼语(土库曼斯坦) '); +INSERT INTO `lms_clx_lang_country` VALUES ('253', '0', 'cy', '威尔士语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('254', '0', 'cy-GB', '威尔士语(英国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('255', '0', 'ug', '维吾尔语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('256', '0', 'ug-CN', '维吾尔语(中国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('257', '0', 'wo', '沃洛夫语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('258', '0', 'wo-SN', '沃洛夫语(塞内加尔) '); +INSERT INTO `lms_clx_lang_country` VALUES ('259', '0', 'ur', '乌尔都语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('26', '0', 'az', '阿塞拜疆语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('260', '0', 'ur-PK', '乌尔都语(巴基斯坦伊斯兰共和国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('261', '0', 'uk', '乌克兰语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('262', '0', 'uk-UA', '乌克兰语(乌克兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('263', '0', 'uz', '乌兹别克语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('264', '0', 'uz-Latn', '乌兹别克语(拉丁语) '); +INSERT INTO `lms_clx_lang_country` VALUES ('265', '0', 'uz-Latn-UZ', '乌兹别克语(拉丁语,乌兹别克斯坦) '); +INSERT INTO `lms_clx_lang_country` VALUES ('266', '0', 'uz-Cyrl', '乌兹别克语(西里尔文) '); +INSERT INTO `lms_clx_lang_country` VALUES ('267', '0', 'uz-Cyrl-UZ', '乌兹别克语(西里尔文,乌兹别克斯坦) '); +INSERT INTO `lms_clx_lang_country` VALUES ('268', '0', 'es', '西班牙语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('269', '0', 'es-AR', '西班牙语(阿根廷) '); +INSERT INTO `lms_clx_lang_country` VALUES ('27', '0', 'az-Latn', '阿塞拜疆语(拉丁语) '); +INSERT INTO `lms_clx_lang_country` VALUES ('270', '0', 'es-PY', '西班牙语(巴拉圭) '); +INSERT INTO `lms_clx_lang_country` VALUES ('271', '0', 'es-PA', '西班牙语(巴拿马) '); +INSERT INTO `lms_clx_lang_country` VALUES ('272', '0', 'es-PR', '西班牙语(波多黎各) '); +INSERT INTO `lms_clx_lang_country` VALUES ('273', '0', 'es-BO', '西班牙语(玻利维亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('274', '0', 'es-DO', '西班牙语(多米尼加共和国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('275', '0', 'es-EC', '西班牙语(厄瓜多尔) '); +INSERT INTO `lms_clx_lang_country` VALUES ('276', '0', 'es-CO', '西班牙语(哥伦比亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('277', '0', 'es-CR', '西班牙语(哥斯达黎加) '); +INSERT INTO `lms_clx_lang_country` VALUES ('278', '0', 'es-HN', '西班牙语(洪都拉斯) '); +INSERT INTO `lms_clx_lang_country` VALUES ('279', '0', 'es-US', '西班牙语(美国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('28', '0', 'az-Latn-AZ', '阿塞拜疆语(拉丁语,阿塞拜疆) '); +INSERT INTO `lms_clx_lang_country` VALUES ('280', '0', 'es-PE', '西班牙语(秘鲁) '); +INSERT INTO `lms_clx_lang_country` VALUES ('281', '0', 'es-MX', '西班牙语(墨西哥) '); +INSERT INTO `lms_clx_lang_country` VALUES ('282', '0', 'es-NI', '西班牙语(尼加拉瓜) '); +INSERT INTO `lms_clx_lang_country` VALUES ('283', '0', 'es-SV', '西班牙语(萨尔瓦多) '); +INSERT INTO `lms_clx_lang_country` VALUES ('284', '0', 'es-GT', '西班牙语(危地马拉) '); +INSERT INTO `lms_clx_lang_country` VALUES ('285', '0', 'es-VE', '西班牙语(委内瑞拉玻利瓦尔共和国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('286', '0', 'es-UY', '西班牙语(乌拉圭) '); +INSERT INTO `lms_clx_lang_country` VALUES ('287', '0', 'es-ES', '西班牙语(西班牙,国际排序) '); +INSERT INTO `lms_clx_lang_country` VALUES ('288', '0', 'es-CL', '西班牙语(智利) '); +INSERT INTO `lms_clx_lang_country` VALUES ('289', '0', 'he', '希伯来语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('29', '0', 'az-Cyrl', '阿塞拜疆语(西里尔文) '); +INSERT INTO `lms_clx_lang_country` VALUES ('290', '0', 'he-IL', '希伯来语(以色列) '); +INSERT INTO `lms_clx_lang_country` VALUES ('291', '0', 'el', '希腊语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('292', '0', 'el-GR', '希腊语(希腊) '); +INSERT INTO `lms_clx_lang_country` VALUES ('293', '0', 'dsb', '下索布语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('294', '0', 'dsb-DE', '下索布语(德国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('295', '0', 'hu', '匈牙利语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('296', '0', 'hu-HU', '匈牙利语(匈牙利) '); +INSERT INTO `lms_clx_lang_country` VALUES ('297', '0', 'syr', '叙利亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('298', '0', 'syr-SY', '叙利亚语(叙利亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('299', '0', 'sah', '雅库特语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('30', '0', 'az-Cyrl-AZ', '阿塞拜疆语(西里尔文,阿塞拜疆) '); +INSERT INTO `lms_clx_lang_country` VALUES ('300', '0', 'sah-RU', '雅库特语(俄罗斯) '); +INSERT INTO `lms_clx_lang_country` VALUES ('301', '0', 'hy', '亚美尼亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('302', '0', 'hy-AM', '亚美尼亚语(亚美尼亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('303', '0', 'ig', '伊博语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('304', '0', 'ig-NG', '伊博语(尼日利亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('305', '0', 'smn', '伊纳里萨米语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('306', '0', 'smn-FI', '伊纳里萨米语(芬兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('307', '0', 'ii', '彝语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('308', '0', 'ii-CN', '彝语(中国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('309', '0', 'it', '意大利语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('31', '0', 'kn', '埃纳德语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('310', '0', 'it-CH', '意大利语(瑞士) '); +INSERT INTO `lms_clx_lang_country` VALUES ('311', '0', 'it-IT', '意大利语(意大利) '); +INSERT INTO `lms_clx_lang_country` VALUES ('312', '0', 'iu', '因纽特语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('313', '0', 'iu-Latn', '因纽特语(拉丁语) '); +INSERT INTO `lms_clx_lang_country` VALUES ('314', '0', 'iu-Latn-CA', '因纽特语(拉丁语,加拿大) '); +INSERT INTO `lms_clx_lang_country` VALUES ('315', '0', 'iu-Cans', '因纽特语(音节) '); +INSERT INTO `lms_clx_lang_country` VALUES ('316', '0', 'iu-Cans-CA', '因纽特语(音节,加拿大) '); +INSERT INTO `lms_clx_lang_country` VALUES ('317', '0', 'hi', '印地语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('318', '0', 'hi-IN', '印地语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('319', '0', 'id', '印度尼西亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('32', '0', 'kn-IN', '埃纳德语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('320', '0', 'id-ID', '印度尼西亚语(印度尼西亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('321', '0', 'en', '英语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('322', '0', 'en-IE', '英语(爱尔兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('323', '0', 'en-AU', '英语(澳大利亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('324', '0', 'en-BZ', '英语(伯利兹) '); +INSERT INTO `lms_clx_lang_country` VALUES ('325', '0', 'en-PH', '英语(菲律宾共和国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('326', '0', 'en-029', '英语(加勒比海) '); +INSERT INTO `lms_clx_lang_country` VALUES ('329', '0', 'en-MY', '英语(马来西亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('33', '0', 'ga', '爱尔兰语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('330', '0', 'en-US', '英语(美国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('331', '0', 'en-ZA', '英语(南非) '); +INSERT INTO `lms_clx_lang_country` VALUES ('332', '0', 'en-TT', '英语(特立尼达和多巴哥) '); +INSERT INTO `lms_clx_lang_country` VALUES ('333', '0', 'en-SG', '英语(新加坡) '); +INSERT INTO `lms_clx_lang_country` VALUES ('334', '0', 'en-NZ', '英语(新西兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('335', '0', 'en-JM', '英语(牙买加) '); +INSERT INTO `lms_clx_lang_country` VALUES ('336', '0', 'en-IN', '英语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('337', '0', 'en-GB', '英语(英国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('338', '0', 'yo', '约鲁巴语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('34', '0', 'ga-IE', '爱尔兰语(爱尔兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('343', '0', 'zh-Hant', '中文(繁体) '); +INSERT INTO `lms_clx_lang_country` VALUES ('344', '0', 'zh-MO', '中文(繁体,澳门特别行政区) '); +INSERT INTO `lms_clx_lang_country` VALUES ('345', '0', 'zh-TW', '中文(繁体,台湾) '); +INSERT INTO `lms_clx_lang_country` VALUES ('346', '0', 'zh-HK', '中文(繁体,香港特别行政区) '); +INSERT INTO `lms_clx_lang_country` VALUES ('347', '1', 'zh-CN', '中文(简体) '); +INSERT INTO `lms_clx_lang_country` VALUES ('348', '0', 'zh-SG', '中文(简体,新加坡) '); +INSERT INTO `lms_clx_lang_country` VALUES ('349', '0', 'zu', '祖鲁语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('35', '0', 'et', '爱沙尼亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('350', '0', 'zu-ZA', '祖鲁语(南非) '); +INSERT INTO `lms_clx_lang_country` VALUES ('36', '0', 'et-EE', '爱沙尼亚语(爱沙尼亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('37', '0', 'oc', '奥克西唐语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('38', '0', 'oc-FR', '奥克西唐语(法国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('39', '0', 'or', '奥里雅语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('40', '0', 'or-IN', '奥里雅语(印度) '); +INSERT INTO `lms_clx_lang_country` VALUES ('41', '0', 'ba', '巴什基尔语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('42', '0', 'ba-RU', '巴什基尔语(俄罗斯) '); +INSERT INTO `lms_clx_lang_country` VALUES ('43', '0', 'eu', '巴斯克语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('44', '0', 'eu-ES', '巴斯克语(巴斯克) '); +INSERT INTO `lms_clx_lang_country` VALUES ('45', '0', 'nso', '巴索托语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('46', '0', 'nso-ZA', '巴索托语(南非) '); +INSERT INTO `lms_clx_lang_country` VALUES ('47', '0', 'be', '白俄罗斯语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('48', '0', 'be-BY', '白俄罗斯语(白俄罗斯) '); +INSERT INTO `lms_clx_lang_country` VALUES ('49', '0', 'bg', '保加利亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('50', '0', 'bg-BG', '保加利亚语(保加利亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('51', '0', 'se', '北萨米语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('52', '0', 'se-FI', '北萨米语(芬兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('53', '0', 'se-NO', '北萨米语(挪威) '); +INSERT INTO `lms_clx_lang_country` VALUES ('54', '0', 'se-SE', '北萨米语(瑞典) '); +INSERT INTO `lms_clx_lang_country` VALUES ('55', '0', 'is', '冰岛语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('56', '0', 'is-IS', '冰岛语(冰岛) '); +INSERT INTO `lms_clx_lang_country` VALUES ('57', '0', 'pl', '波兰语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('58', '0', 'pl-PL', '波兰语(波兰) '); +INSERT INTO `lms_clx_lang_country` VALUES ('59', '0', 'bs', '波斯尼亚语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('6', '0', 'ar-DZ', '阿拉伯语(阿尔及利亚) '); +INSERT INTO `lms_clx_lang_country` VALUES ('60', '0', 'bs-Latn', '波斯尼亚语(拉丁语) '); +INSERT INTO `lms_clx_lang_country` VALUES ('61', '0', 'bs-L', '波斯尼亚语(拉丁语,波斯尼亚和黑塞哥维那) '); +INSERT INTO `lms_clx_lang_country` VALUES ('62', '0', 'bs-Cyrl', '波斯尼亚语(西里尔文) '); +INSERT INTO `lms_clx_lang_country` VALUES ('63', '0', 'bs', '波斯尼亚语(西里尔文,波斯尼亚和黑塞哥维那) '); +INSERT INTO `lms_clx_lang_country` VALUES ('64', '0', 'fa', '波斯语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('65', '0', 'fa-IR', '波斯语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('66', '0', 'br', '布里多尼语'); +INSERT INTO `lms_clx_lang_country` VALUES ('67', '0', 'br-FR', '布里多尼语(法国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('68', '0', 'bo', '藏语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('69', '0', 'bo-CN', '藏语(中国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('6a75e9e1-c08a-4831-be66-997acc690698', '1', '阿萨德', '阿阿撒旦法v'); +INSERT INTO `lms_clx_lang_country` VALUES ('6d640bda-ca35-4f5e-aaf0-bec2f8920862', '1', 'tanwan', '台湾1'); +INSERT INTO `lms_clx_lang_country` VALUES ('7', '0', 'ar-AE', '阿拉伯语(阿联酋) '); +INSERT INTO `lms_clx_lang_country` VALUES ('70', '0', 'ko', '朝鲜语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('71', '0', 'ko-KR', '朝鲜语(韩国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('72', '0', 'tn', '茨瓦纳语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('73', '0', 'tn-ZA', '茨瓦纳语(南非) '); +INSERT INTO `lms_clx_lang_country` VALUES ('74', '0', 'prs', '达里语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('75', '0', 'prs-AF', '达里语(阿富汗) '); +INSERT INTO `lms_clx_lang_country` VALUES ('76', '0', 'tt', '鞑靼语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('77', '0', 'tt-RU', '鞑靼语(俄罗斯) '); +INSERT INTO `lms_clx_lang_country` VALUES ('78', '0', 'da', '丹麦语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('79', '0', 'da-DK', '丹麦语(丹麦) '); +INSERT INTO `lms_clx_lang_country` VALUES ('8', '0', 'ar-OM', '阿拉伯语(阿曼) '); +INSERT INTO `lms_clx_lang_country` VALUES ('80', '0', 'de', '德语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('81', '0', 'de-AT', '德语(奥地利) '); +INSERT INTO `lms_clx_lang_country` VALUES ('82', '0', 'de-DE', '德语(德国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('83', '0', 'de-LI', '德语(列支敦士登) '); +INSERT INTO `lms_clx_lang_country` VALUES ('84', '0', 'de-LU', '德语(卢森堡) '); +INSERT INTO `lms_clx_lang_country` VALUES ('85', '0', 'de-CH', '德语(瑞士) '); +INSERT INTO `lms_clx_lang_country` VALUES ('86', '0', 'dv', '迪维希语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('87', '0', 'dv-MV', '迪维希语(马尔代夫) '); +INSERT INTO `lms_clx_lang_country` VALUES ('88', '0', 'ru', '俄语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('89', '0', 'ru-RU', '俄语(俄罗斯) '); +INSERT INTO `lms_clx_lang_country` VALUES ('90', '0', 'fo', '法罗语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('91', '0', 'fo-FO', '法罗语(法罗群岛) '); +INSERT INTO `lms_clx_lang_country` VALUES ('92', '0', 'fr', '法语 '); +INSERT INTO `lms_clx_lang_country` VALUES ('93', '0', 'fr-BE', '法语(比利时) '); +INSERT INTO `lms_clx_lang_country` VALUES ('94', '0', 'fr-FR', '法语(法国) '); +INSERT INTO `lms_clx_lang_country` VALUES ('95', '0', 'fr-CA', '法语(加拿大) '); +INSERT INTO `lms_clx_lang_country` VALUES ('96', '0', 'fr-LU', '法语(卢森堡) '); +INSERT INTO `lms_clx_lang_country` VALUES ('97', '0', 'fr-MC', '法语(摩纳哥) '); +INSERT INTO `lms_clx_lang_country` VALUES ('98', '0', 'fr-CH', '法语(瑞士) '); + +-- ---------------------------- +-- Table structure for lms_clx_lang_type +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_lang_type`; +CREATE TABLE `lms_clx_lang_type` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID', + `language_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '语言名称', + `file_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '配置文件名称', + `status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '1启用0禁用', + `is_default` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否默认语言', + `delete_time` int(11) NULL DEFAULT NULL COMMENT '是否删除 默认null', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `id`(`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '语言类型' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_lang_type +-- ---------------------------- +INSERT INTO `lms_clx_lang_type` VALUES ('1', '中文', 'zh-CN', 1, 1, NULL); +INSERT INTO `lms_clx_lang_type` VALUES ('11', 'asdefv', 'zh-CN', 1, 0, 1692595275); +INSERT INTO `lms_clx_lang_type` VALUES ('12', 'asdfa', 'zh-CN', 1, 0, 1692595236); +INSERT INTO `lms_clx_lang_type` VALUES ('13', '46+54d', 'zh-CN', 1, 0, 1692595955); +INSERT INTO `lms_clx_lang_type` VALUES ('2', 'English', 'en-US', 1, 0, NULL); +INSERT INTO `lms_clx_lang_type` VALUES ('3', '繁體中文', 'zh-Hant', 1, 0, NULL); +INSERT INTO `lms_clx_lang_type` VALUES ('4', 'Français', 'fr-FR', 1, 0, NULL); +INSERT INTO `lms_clx_lang_type` VALUES ('5', 'Italiano', 'it-IT', 1, 0, NULL); +INSERT INTO `lms_clx_lang_type` VALUES ('6', '日本語', 'ja-JP', 1, 0, NULL); +INSERT INTO `lms_clx_lang_type` VALUES ('7', '한국어', 'ko-KR', 1, 0, NULL); +INSERT INTO `lms_clx_lang_type` VALUES ('8', 'Монгол', 'mn-MN', 1, 0, NULL); +INSERT INTO `lms_clx_lang_type` VALUES ('9', 'ภาษาไทย', 'th-TH', 1, 0, 1694743510); + +-- ---------------------------- +-- Table structure for lms_clx_system +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system`; +CREATE TABLE `lms_clx_system` ( + `sys_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '系统ID', + `sys_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '系统名称', + `sys_code` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '系统编码', + PRIMARY KEY (`sys_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统基本信息' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system +-- ---------------------------- + +-- ---------------------------- +-- Table structure for lms_clx_system_admin +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_admin`; +CREATE TABLE `lms_clx_system_admin` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '后台管理员表ID', + `account` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '后台管理员账号', + `head_pic` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '管理员头像', + `pwd` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '后台管理员密码', + `real_name` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '后台管理员姓名', + `last_ip` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '后台管理员最后一次登录ip', + `login_count` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '登录次数', + `status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '后台管理员状态 1有效0无效', + `division_id` int(11) NOT NULL DEFAULT 0 COMMENT '事业部id', + `level` int(11) NULL DEFAULT 1 COMMENT '是否超级管理员0 ', + `last_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '后台管理员最后一次登录时间', + `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '后台管理员添加时间', + `sex` int(1) NOT NULL DEFAULT 1 COMMENT '性别(0:女 1:男)', + `cell_phone_number` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号', + `address` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '住址', + `email` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '电子邮件', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `delete_time` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '是否删除', + `remarks` varchar(255) CHARACTER SET tis620 COLLATE tis620_thai_ci NULL DEFAULT '' COMMENT '备注信息', + PRIMARY KEY (`id`) USING BTREE, + INDEX `account`(`account`) USING BTREE, + INDEX `status`(`status`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '后台管理员表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_admin +-- ---------------------------- +INSERT INTO `lms_clx_system_admin` VALUES ('1', 'admin', '/statics/system_images/admin_head_pic.png', '$2y$10$gpJURmyXF7cHYRKlpnAF6.v/4EkGQ6dTB2k7UE1nSl5f57ZzhiXKe', '超级管理员', '0.0.0.0', 170, 1, 0, 0, 1712105785, 1693289376, 2, '11111111111', '在是的v', '特洒脱', 1712105785, NULL, '??'); +INSERT INTO `lms_clx_system_admin` VALUES ('12b440e6-0e71-48f2-9926-509bc4135ab8', 'LiMing2023', '', '$2y$10$gpJURmyXF7cHYRKlpnAF6.v/4EkGQ6dTB2k7UE1nSl5f57ZzhiXKe', '李明', '0.0.0.0', 113, 1, 0, 1, 1712111791, 1694053170, 1, '18999999999', '北京博物馆', '11111111@163.com', 1712111791, NULL, '????????'); +INSERT INTO `lms_clx_system_admin` VALUES ('136ee2de-bace-4659-b7ae-7e07c0fbbffe', 'ZhangXiaoHong1', '/statics/system_images/admin_head_pic.png', '$2y$10$gpJURmyXF7cHYRKlpnAF6.v/4EkGQ6dTB2k7UE1nSl5f57ZzhiXKe', '张晓红', '127.0.0.1', 17, 1, 0, 1, 1710394884, 1694052917, 1, NULL, NULL, NULL, 1710394884, NULL, '13'); +INSERT INTO `lms_clx_system_admin` VALUES ('1b408381-f510-4571-b473-006479eee7b1', 'WangQiang888', '/statics/system_images/admin_head_pic.png', '$2y$10$gpJURmyXF7cHYRKlpnAF6.v/4EkGQ6dTB2k7UE1nSl5f57ZzhiXKe', '王强', '127.0.0.1', 2, 1, 0, 1, 1710400921, 1694054098, 1, NULL, NULL, NULL, 1710400921, NULL, '456456'); +INSERT INTO `lms_clx_system_admin` VALUES ('277011bd-36c1-41f7-8109-85b7285c8f29', 'LiuTing999', '/statics/system_images/admin_head_pic.png', '$2y$10$gpJURmyXF7cHYRKlpnAF6.v/4EkGQ6dTB2k7UE1nSl5f57ZzhiXKe', '刘婷', '127.0.0.1', 5, 1, 0, 1, 1710400861, 1694053926, 1, NULL, NULL, NULL, 1710400861, NULL, '12464'); +INSERT INTO `lms_clx_system_admin` VALUES ('4ff74a5b-18f8-49a7-a7f1-161e35a24dda', 'ChenLei123', '/statics/system_images/admin_head_pic.png', '$2y$10$gpJURmyXF7cHYRKlpnAF6.v/4EkGQ6dTB2k7UE1nSl5f57ZzhiXKe', '陈磊', '127.0.0.1', 5, 1, 0, 1, 1710401294, 1694053059, 1, NULL, NULL, NULL, 1710401294, NULL, '13'); +INSERT INTO `lms_clx_system_admin` VALUES ('5c06a922-309f-4224-8f43-76023485443f', 'ZhaoMin2000', '/statics/system_images/admin_head_pic.png', '$2y$10$gpJURmyXF7cHYRKlpnAF6.v/4EkGQ6dTB2k7UE1nSl5f57ZzhiXKe', '赵敏', '', 0, 1, 0, 1, 0, 1694054139, 2, '2', '4', '3', 1710125550, NULL, '456456'); +INSERT INTO `lms_clx_system_admin` VALUES ('9ded8e78-b5f4-416f-beab-88a57bb84d38', 'HuangYong777', '/statics/system_images/admin_head_pic.png', '$2y$10$wGDLTsgEVNEkb/0sg/7ZAeb1tJKOtycseP4czKkRke92EGylFb9LS', '黄勇', '', 0, 1, 0, 1, 0, 1710125117, 2, '11111111111', 'c', '405784684@qq.com', 1710125546, NULL, ''); +INSERT INTO `lms_clx_system_admin` VALUES ('9ded8e78-b5f4-416f-beab-88a57bb84d39', 'ZhouJing666', '/statics/system_images/admin_head_pic.png', '$2y$10$wGDLTsgEVNEkb/0sg/7ZAeb1tJKOtycseP4czKkRke92EGylFb9LS', '周静', '127.0.0.1', 2, 1, 0, 1, 1710481857, 1710125117, 2, '11111111111', 'c', '405784684@qq.com', 1710481857, NULL, ''); +INSERT INTO `lms_clx_system_admin` VALUES ('9ded8e78-b5f4-416f-beab-88a57bb84d40', 'WuWei1001', '/statics/system_images/admin_head_pic.png', '$2y$10$wGDLTsgEVNEkb/0sg/7ZAeb1tJKOtycseP4czKkRke92EGylFb9LS', '吴伟', '127.0.0.1', 1, 1, 0, 1, 1710471463, 1710125117, 2, '11111111111', 'c', '405784684@qq.com', 1710471463, NULL, ''); +INSERT INTO `lms_clx_system_admin` VALUES ('9ded8e78-b5f4-416f-beab-88a57bb84d41', 'HanNa2021', '/statics/system_images/admin_head_pic.png', '$2y$10$wGDLTsgEVNEkb/0sg/7ZAeb1tJKOtycseP4czKkRke92EGylFb9LS', '韩娜', '0.0.0.0', 1, 1, 0, 1, 1712113062, 1710125117, 2, '11111111111', 'c', '405784684@qq.com', 1712113062, NULL, ''); + +-- ---------------------------- +-- Table structure for lms_clx_system_admin_dept +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_admin_dept`; +CREATE TABLE `lms_clx_system_admin_dept` ( + `admin_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户ID', + `dept_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '组织ID' +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '管理员部门关联表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_admin_dept +-- ---------------------------- +INSERT INTO `lms_clx_system_admin_dept` VALUES ('1', 'b9191372-1051-45aa-aa32-63b6eca5f1c1'); +INSERT INTO `lms_clx_system_admin_dept` VALUES ('12b440e6-0e71-48f2-9926-509bc4135ab8', '06c9f2dc-c1a7-4a8e-b317-fa78af8e3346'); +INSERT INTO `lms_clx_system_admin_dept` VALUES ('136ee2de-bace-4659-b7ae-7e07c0fbbffe', '44d21f0e-e34f-4a2b-92f5-ad1f1b0a049a'); +INSERT INTO `lms_clx_system_admin_dept` VALUES ('277011bd-36c1-41f7-8109-85b7285c8f29', '460b9e0a-2dce-44c9-b29d-4a0dc8565a1e'); +INSERT INTO `lms_clx_system_admin_dept` VALUES ('9ded8e78-b5f4-416f-beab-88a57bb84d40', '4908ba01-0562-455d-8b22-3b6b266b6d29'); +INSERT INTO `lms_clx_system_admin_dept` VALUES ('9ded8e78-b5f4-416f-beab-88a57bb84d39', '460b9e0a-2dce-44c9-b29d-4a0dc8565a1e'); +INSERT INTO `lms_clx_system_admin_dept` VALUES ('5c06a922-309f-4224-8f43-76023485443f', '44d21f0e-e34f-4a2b-92f5-ad1f1b0a049a'); +INSERT INTO `lms_clx_system_admin_dept` VALUES ('4ff74a5b-18f8-49a7-a7f1-161e35a24dda', '06c9f2dc-c1a7-4a8e-b317-fa78af8e3346'); +INSERT INTO `lms_clx_system_admin_dept` VALUES ('1b408381-f510-4571-b473-006479eee7b1', '8a161db3-59d4-49e5-89cf-0b44ddc891ff'); + +-- ---------------------------- +-- Table structure for lms_clx_system_admin_post +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_admin_post`; +CREATE TABLE `lms_clx_system_admin_post` ( + `admin_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户ID', + `post_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '职位ID' +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '管理员-职位关联表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_admin_post +-- ---------------------------- +INSERT INTO `lms_clx_system_admin_post` VALUES ('1', '7de1c1af-af39-4687-bda6-9ba6d20cdbe4'); +INSERT INTO `lms_clx_system_admin_post` VALUES ('12b440e6-0e71-48f2-9926-509bc4135ab8', '0e22c1c8-6c54-4f22-b8c7-35c45e0d93cd'); +INSERT INTO `lms_clx_system_admin_post` VALUES ('136ee2de-bace-4659-b7ae-7e07c0fbbffe', '745e3ac7-7b85-4356-b507-4ce3ff5517fa'); +INSERT INTO `lms_clx_system_admin_post` VALUES ('277011bd-36c1-41f7-8109-85b7285c8f29', '967eb4d9-d99d-40a0-84ae-82abf640c983'); +INSERT INTO `lms_clx_system_admin_post` VALUES ('9ded8e78-b5f4-416f-beab-88a57bb84d40', '1e9c9f97-0cc1-42fe-99ff-072bfa987cf2'); +INSERT INTO `lms_clx_system_admin_post` VALUES ('9ded8e78-b5f4-416f-beab-88a57bb84d39', '03ad4b7c-c0ce-45f8-a20d-49fcafcb4f59'); +INSERT INTO `lms_clx_system_admin_post` VALUES ('5c06a922-309f-4224-8f43-76023485443f', 'cf94fe6d-c948-4e70-9af8-cc2ad35adcb2'); +INSERT INTO `lms_clx_system_admin_post` VALUES ('4ff74a5b-18f8-49a7-a7f1-161e35a24dda', '8ba40db4-a435-4c1e-b8b7-5dc80c14f3ee'); +INSERT INTO `lms_clx_system_admin_post` VALUES ('1b408381-f510-4571-b473-006479eee7b1', '31dc9ec6-dd9f-4ea8-8b4c-b571bc18ee6d'); + +-- ---------------------------- +-- Table structure for lms_clx_system_attachment +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_attachment`; +CREATE TABLE `lms_clx_system_attachment` ( + `att_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '自增ID', + `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '附件名称', + `att_dir` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '附件路径', + `satt_dir` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '压缩图片路径', + `att_size` char(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '附件大小', + `att_type` char(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '附件类型', + `pid` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '关联类型ID', + `ext` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '文件后缀', + `time` int(11) NOT NULL DEFAULT 0 COMMENT '上传时间', + `image_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '图片上传类型 1本地 2七牛云 3OSS 4COS ', + `module_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '图片上传模块类型 1 后台上传 2 用户生成', + `real_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '原始文件名', + `scan_token` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '扫码上传的token', + PRIMARY KEY (`att_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '附件管理表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_attachment +-- ---------------------------- +INSERT INTO `lms_clx_system_attachment` VALUES ('f2025abc-471d-41d6-b077-5575b6fc5196', '1c526cd8d18bf6cab9de97bef8c505d2.png', '/uploads/attach/2024/03/20240311/1c526cd8d18bf6cab9de97bef8c505d2.png', '/uploads/attach/2024/03/20240311/1c526cd8d18bf6cab9de97bef8c505d2.png', '171421', 'image/jpeg', '', 'png', 1710129281, 1, 1, '屏幕截图(2).png', ''); + +-- ---------------------------- +-- Table structure for lms_clx_system_attachment_category +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_attachment_category`; +CREATE TABLE `lms_clx_system_attachment_category` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID', + `pid` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '父级ID', + `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '分类名称', + `enname` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '分类目录', + `sort` int(10) NULL DEFAULT NULL COMMENT '排序', + `remarks` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '备注', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `id`(`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '附件分类表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_attachment_category +-- ---------------------------- +INSERT INTO `lms_clx_system_attachment_category` VALUES ('432177b0-e72f-44aa-8b17-6a4a2eb44019', '-1', '素材', '', NULL, ''); +INSERT INTO `lms_clx_system_attachment_category` VALUES ('e4511adc-9c7b-4557-928f-17696cc8c662', '-1', '系统', '', NULL, ''); + +-- ---------------------------- +-- Table structure for lms_clx_system_config +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_config`; +CREATE TABLE `lms_clx_system_config` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '配置id', + `config_tab_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '配置分类id', + `menu_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '字段名称', + `type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '类型(文本框,单选按钮...)', + `input_type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'input' COMMENT '表单类型', + `parameter` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '规则 单选框和多选框', + `upload_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '上传文件格式1单图2多图3文件', + `required` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '规则', + `width` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '多行文本框的宽度', + `high` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '多行文框的高度', + `value` varchar(5000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '默认值', + `info` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '配置名称', + `desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '配置简介', + `sort` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序', + `status` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否隐藏', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '配置表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_config +-- ---------------------------- +INSERT INTO `lms_clx_system_config` VALUES ('1', '1', 'site_name', 'text', 'input', '', 1, 'required:true', 100, 0, '\"CRMEB\"', '网站名称', '网站名称很多地方会显示的,建议认真填写', 97, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('108', '31', 'upload_type', 'radio', '', '1=>本地存储\n2=>七牛云存储\n3=>阿里云OSS\n4=>腾讯COS', 1, '', 0, 0, '1', '上传类型', '文件储存配置,注意:一旦配置就不要轻易修改,会导致文件不能使用', 100, 1, NULL, 1695360305); +INSERT INTO `lms_clx_system_config` VALUES ('110', '32', 'accessKey', 'text', 'input', '', 0, '', 100, 0, '\"\"', '阿里云云存储accessKey', 'accessKey', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('111', '32', 'secretKey', 'text', 'input', '', 0, '', 100, 0, '\"\"', '阿里云云存储secretKey', 'secretKey', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('113', '115', 'order_cancel_time', 'text', 'number', '', 1, '', 0, 0, '\"2\"', '普通未支付订单取消', '普通商品未支付订单的自动取消时间,单位(小时)', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('114', '115', 'order_activity_time', 'text', 'number', '', 1, '', 0, 0, '\"1\"', '活动未支付订单取消', '活动商品未支付的订单自动取消时间,单位(小时)', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('115', '115', 'order_bargain_time', 'text', 'number', '', 1, '', 0, 0, '\"1\"', '砍价未支付订单取消', '砍价未支付订单自动取消时间,单位(小时),如果为0将使用默认活动取消时间,优先使用单独活动配置', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('116', '115', 'order_seckill_time', 'text', 'number', '', 1, '', 0, 0, '\"1\"', '秒杀未支付订单取消', '秒杀未支付订单自动取消时间,单位(小时),如果为0将使用默认活动取消时间,优先使用单独活动配置', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('117', '115', 'order_pink_time', 'text', 'number', '', 1, '', 0, 0, '\"1\"', '拼团未支付订单取消', '拼团未支付订单自动取消时间,单位(小时),如果为0将使用默认活动取消时间,优先使用单独活动配置', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('122', '116', 'system_delivery_time', 'text', 'number', '', 1, 'required:true,digits:true,min:0', 100, 0, '\"7\"', '自动收货时间', '商城订单发货之后,用户如果不手动点击收货,则在N天后自动收货,设置0为不自动收货', 80, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('123', '18', 'sms_account', 'text', 'input', '', 1, '', 0, 0, '\"\"', 'AppId', '一号通账号内创建应用的AppId', 10, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('13', '2', 'wechat_appid', 'text', 'input', '', 1, '', 0, 0, '\"\"', 'AppID', '微信公众号的AppID', 99, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('137', '18', 'sms_token', 'text', 'input', '', 1, '', 0, 0, '\"\"', 'AppSecret', '一号通账号内创建应用的AppSecret', 9, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('138', '105', 'h5_avatar', 'upload', 'input', '', 1, '', 0, 0, '\"\\/statics\\/system_images\\/default_avatar.jpeg\"', '用户默认头像', '用户默认头像,后台添加用户以及用户登录的默认头像显示,尺寸(80*80)', 100, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('139', '109', 'offline_pay_status', 'radio', 'input', '1=>开启\n2=>关闭', 1, '', 0, 0, '\"1\"', '线下支付', '线下支付请选择开启或关闭', 89, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('14', '2', 'wechat_appsecret', 'text', 'input', '', 1, '', 0, 0, '\"\"', 'AppSecret', '微信公众号的AppSecret', 95, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('141', '28', 'recharge_switch', 'radio', 'input', '1=>开启\n0=>关闭', 1, '', 0, 0, '0', '小程序充值开关', '仅小程序端的充值开关,小程序提交审核前,需要关闭此功能', 4, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('142', '124', 'tengxun_map_key', 'text', 'input', '', 1, '', 0, 0, '\"SMJBZ-WCHK4-ZPZUA-DSIXI-XDDVQ-XWFX7\"', '腾讯地图KEY', '腾讯地图KEY,申请地址:https://lbs.qq.com', 77, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('143', '119', 'store_self_mention', 'radio', 'input', '1=>开启\n0=>关闭', 1, '', 0, 0, '\"1\"', '开启到店自提', '开启后下单页面支持到店自提,需要在设置->发货设置->提货点设置中添加提货点,关闭则隐藏此功能', 95, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('145', '86', 'pay_success_printing_switch', 'radio', 'input', '1=>开启\n0=>关闭', 1, '', 0, 0, '0', '小票打印开关', '支付成功自动小票打印功能,需要购买易联云K4或者K6无线打印机,或者购买飞鹅云V58系列', 10, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('146', '87', 'develop_id', 'text', 'input', '', 1, '', 0, 0, '\"\"', '开发者ID', '易联云申请应用后页面开发者信息中的用户ID', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('147', '87', 'printing_api_key', 'text', 'input', '', 1, '', 0, 0, '\"\"', '应用密钥', '易联云申请应用后页面开发者信息中的应用密钥', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('148', '87', 'printing_client_id', 'text', 'input', '', 1, '', 0, 0, '\"\"', '应用ID', '易联云申请应用后页面开发者信息中的应用ID', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('149', '87', 'terminal_number', 'text', 'input', '', 1, '', 0, 0, '\"\"', '终端号', '易联云打印机标签上的终端号', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('15', '2', 'wechat_token', 'text', 'input', '', 1, '', 0, 0, '\"\"', '微信验证TOKEN', '微信验证TOKEN', 88, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('150', '20', 'lower_order_switch', 'radio', '', '0=>关闭\n1=>开启', 0, '', 0, 0, '0', '支付成功提醒开关', '支付成功提醒开关', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('151', '20', 'deliver_goods_switch', 'radio', '', '0=>关闭\n1=>开启', 0, '', 0, 0, '0', '发货提醒开关', '发货提醒开关', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('152', '20', 'confirm_take_over_switch', 'radio', '', '0=>关闭\n1=>开启', 0, '', 0, 0, '0', '确认收货提醒开关', '确认收货提醒开关', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('153', '20', 'admin_lower_order_switch', 'radio', '', '0=>关闭\n1=>开启', 0, '', 0, 0, '0', '用户下单管理员提醒开关', '用户下单管理员提醒开关', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('154', '20', 'admin_pay_success_switch', 'radio', '', '0=>关闭\n1=>开启', 0, '', 0, 0, '0', '用户支付成功管理员提醒开关', '用户支付成功管理员提醒开关', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('155', '20', 'admin_refund_switch', 'radio', '', '0=>关闭\n1=>开启', 0, '', 0, 0, '0', '用户退款管理员提醒开关', '用户退款管理员提醒开关', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('156', '20', 'admin_confirm_take_over_switch', 'radio', '', '0=>关闭\n1=>开启', 0, '', 0, 0, '0', '用户确认收货管理员短信提醒', '用户确认收货管理员短信提醒', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('158', '28', 'recharge_attention', 'textarea', '', '', 0, '', 100, 5, '\"\\u5145\\u503c\\u540e\\u5e10\\u6237\\u7684\\u91d1\\u989d\\u4e0d\\u80fd\\u63d0\\u73b0\\uff0c\\u53ef\\u7528\\u4e8e\\u5546\\u57ce\\u6d88\\u8d39\\u4f7f\\u7528\\n\\u4f63\\u91d1\\u5bfc\\u5165\\u8d26\\u6237\\u4e4b\\u540e\\u4e0d\\u80fd\\u518d\\u6b21\\u5bfc\\u51fa\\u3001\\u4e0d\\u53ef\\u63d0\\u73b0\\n\\u8d26\\u6237\\u5145\\u503c\\u51fa\\u73b0\\u95ee\\u9898\\u53ef\\u8054\\u7cfb\\u5546\\u57ce\\u5ba2\\u670d\\uff0c\\u4e5f\\u53ef\\u62e8\\u6253\\u5546\\u57ce\\u5ba2\\u670d\\u70ed\\u7ebf\\uff1a4008888888\\n\\n\\n\"', '充值注意事项', '充值注意事项', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('159', '73', 'extract_time', 'text', 'input', '', 0, '', 100, 0, '\"0\"', '冻结时间', '防止用户退款,佣金被提现了,所以需要设置佣金冻结时间(天)', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('16', '2', 'wechat_encode', 'radio', 'input', '0=>明文模式\n1=>兼容模式\n2=>安全模式', 1, '', 0, 0, '0', '消息加解密方式', '如需使用安全模式请在管理中心修改,仅限服务号和认证订阅号', 84, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('160', '72', 'store_brokerage_price', 'text', 'input', '', 0, '', 100, 0, '\"100\"', '满额分销最低金额', '满额分销满足金额开通分销权限', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('162', '20', 'price_revision_switch', 'radio', 'input', '0=>关闭\n1=>开启', 0, '', 0, 0, '0', '改价短信提醒开关', '改价短信提醒开关', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('168', '122', 'site_logo_square', 'upload', 'input', '', 1, '', 0, 0, '\"\\/statics\\/system_images\\/admin_logo_small.png\"', '后台小LOGO', '后台菜单缩进小LOGO,尺寸180*180', 90, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('17', '2', 'wechat_encodingaeskey', 'text', 'input', '', 1, '', 0, 0, '\"\"', 'EncodingAESKey', '公众号消息加解密Key,在使用安全模式情况下要填写该值,请先在管理中心修改,然后填写该值,仅支持认证服务号', 80, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('170', '109', 'yue_pay_status', 'radio', 'input', '1=>开启\n2=>关闭', 1, '', 0, 0, '\"1\"', '余额支付', '余额支付请选择开启或关闭', 95, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('171', '122', 'login_logo', 'upload', 'input', '', 1, '', 0, 0, '\"\\/statics\\/system_images\\/admin_login_logo.png\"', '后台登录页LOGO', '后台登录页LOGO,建议尺寸270x75', 93, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('173', '80', 'qiniu_accessKey', 'text', 'input', '', 0, '', 100, 0, '\"\"', 'accessKey', '七牛云accessKey', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('174', '80', 'qiniu_secretKey', 'text', 'input', '', 0, '', 100, 0, '\"\"', 'secretKey', '七牛云secretKey', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('178', '82', 'tengxun_accessKey', 'text', 'input', '', 0, '', 100, 0, '\"\"', 'accessKey', '腾讯云accessKey', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('179', '82', 'tengxun_secretKey', 'text', '', '', 0, '', 100, 0, '\"\"', 'secretKey', '腾讯云secretKey', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('18', '70', 'wechat_share_img', 'upload', 'input', '', 1, '', 0, 0, '\"\\/statics\\/system_images\\/share_image.jpeg\"', '微信分享图片', '若填写此图片地址,则分享网页出去时会分享此图片。可有效防止分享图片变形,图片比例5:4,建议小于50KB', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('187', '90', 'copy_product_apikey', 'text', 'input', '', 1, '', 0, 0, '\"\"', '99Api apiKey', '注册99api采集接口在个人中心复制key', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('189', '28', 'balance_func_status', 'radio', 'input', '1=>开启\n0=>关闭\n', 1, '', 0, 0, '1', '余额功能启用', '商城余额功能启用或者关闭', 5, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('19', '2', 'wechat_qrcode', 'upload', 'input', '', 1, '', 0, 0, '\"\"', '关注二维码', '引导关注公众号显示的公众号关注二维码', 76, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('190', '72', 'brokerage_func_status', 'radio', '', '1=>开启\n0=>关闭', 0, '', 0, 0, '1', '分销启用', '商城分销功能开启|关闭', 100, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('191', '11', 'order_give_integral', 'text', 'input', '', 0, '', 100, 0, '\"1\"', '下单赠送积分', '下单支付金额按比例赠送积分(实际支付1元赠送多少积分)', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('193', '45', 'member_func_status', 'radio', '', '1=>开启\n0=>关闭', 1, '', 0, 0, '\"0\"', '用户等级启用', '商城用户等级功能开启|关闭', 0, 1, NULL, 1695360168); +INSERT INTO `lms_clx_system_config` VALUES ('194', '67', 'member_price_status', 'radio', 'input', '1=>开启\n0=>关闭', 1, '', 0, 0, '\"1\"', '商品付费会员价', '商品付费会员价是否展示', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('195', '105', 'store_user_mobile', 'radio', 'input', '1=>强制\n0=>不强制', 1, '', 0, 0, '0', '强制手机号登录', '用户在授权之后强制绑定手机号,可以实现用户多端统一', 95, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('196', '45', 'order_give_exp', 'text', 'input', '', 1, '', 0, 0, '\"1\"', '订单赠送经验', '下单赠送用户经验比例(实际支付1元赠送多少经验)', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('198', '126', 'sign_give_exp', 'text', 'number', '', 1, '', 0, 0, '1', '签到赠送经验', '签到赠送用户经验值', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('199', '45', 'invite_user_exp', 'text', 'input', '', 1, '', 0, 0, '\"\\\"50\\\"\"', '邀新赠送经验', '邀请一个新用户赠送用户经验值', 0, 1, NULL, 1695360152); +INSERT INTO `lms_clx_system_config` VALUES ('2', '1', 'site_url', 'text', 'input', '', 1, 'required:true,url:true', 100, 0, '\"http://127.0.0.4\"', '网站地址', '安装自动配置,不要轻易修改,更换会影响网站访问、接口请求、本地文件储存、支付回调、微信授权、支付、小程序图片访问、部分二维码、官方授权等', 95, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('200', '72', 'brokerage_bindind', 'radio', '', '1=>所有用户\n2=>新用户', 0, '', 0, 0, '2', '分销关系绑定', '所有用户”指所有没有上级推广人的用户点击或扫推广人码绑定分销关系,“新用户”指新注册的用户或首次进入系统的用户才会绑定推广关系', 98, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('21', '70', 'wechat_share_title', 'text', 'input', '', 0, 'required:true', 100, 0, '\"CRMEB v4\\u6807\\u51c6\\u7248\"', '微信分享标题', '微信分享标题', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('22', '70', 'wechat_share_synopsis', 'textarea', '', '', 0, '', 100, 5, '\"\\u5b8c\\u5584\\u7684\\u6587\\u6863 \\u5168\\u201c\\u5fc3\\u201d\\u800c\\u6765\\uff01\"', '微信分享简介', '微信分享简介', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('235', '20', 'unpaid_order_switch', 'radio', '', '1=>开启\n0=>关闭', 0, '', 0, 0, '0', '未支付短信提醒开关', '未支付短信提醒开关', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('236', '20', 'verify_expire_time', 'text', 'input', '', 0, '', 100, 0, '\"5\"', '验证码有效期', '短信验证码过期时间(分钟)', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('246', '50', 'invoice_func_status', 'radio', '', '1=>开启\n0=>关闭', 0, '', 0, 0, '1', '发票功能启用', '发票功能开启|关闭', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('247', '50', 'special_invoice_status', 'radio', '', '1=>开启\n0=>关闭', 0, '', 0, 0, '1', '专用发票启用', '专用发票功能开启|关闭', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('25', '4', 'pay_weixin_mchid', 'text', 'input', '', 0, '', 100, 0, '\"\"', 'Mchid', '微信商户商户号,微信商户商户号', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('26', '4', 'pay_weixin_client_cert', 'upload', 'input', '', 3, '', 0, 0, '\"\"', '微信支付证书', '微信支付证书,在微信商家平台中可以下载!文件名一般为apiclient_cert.pem', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('27', '4', 'pay_weixin_client_key', 'upload', 'input', '', 3, '', 0, 0, '\"\"', '微信支付证书密钥', '微信支付证书密钥,在微信商家平台中可以下载!文件名一般为apiclient_key.pem', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('28', '4', 'pay_weixin_key', 'text', 'input', '', 0, '', 100, 0, '\"\"', 'Key', '商户支付密钥Key。审核通过后,在微信发送的邮件中查看。', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('287', '109', 'ali_pay_status', 'radio', 'input', '0=>关闭\nalipay=>支付宝\nallinpay=>通联', 1, '', 0, 0, '\"alipay\"', '支付宝支付', '请选择支付宝通道,关闭用户端不显示', 98, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('288', '63', 'alipay_public_key', 'textarea', '', '', 1, '', 100, 5, '\"\"', '支付应用公钥', '支付宝加签完成后申城的支付宝公钥', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('289', '63', 'alipay_merchant_private_key', 'textarea', '', '', 0, '', 100, 5, '\"\"', '支付应用私钥', '支付应用私钥', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('290', '63', 'ali_pay_appid', 'text', 'input', '', 0, '', 100, 0, '\"\"', '支付应用Appid', '支付应用Appid', 91, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('291', '91', 'logistics_type', 'radio', 'input', '1=>一号通\n2=>阿里云物流查询', 1, '', 0, 0, '1', '接口选择', '建议使用一号通更方便不用配置密钥,阿里云云市场购买链接:https://0x9.me/w9vnq', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('299', '94', 'config_export_id', 'text', 'input', '', 1, '', 0, 0, '\"\"', '快递公司', '快递公司', 0, 0, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('3', '122', 'site_logo', 'upload', 'input', '', 1, '', 0, 0, '\"\\/statics\\/system_images\\/admin_logo_big.png\"', '后台大LOGO', '菜单展开左上角logo,建议尺寸[170*50]', 89, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('300', '94', 'config_export_temp_id', 'text', 'input', '', 1, '', 0, 0, '\"\"', '快递模板', '快递模板', 0, 0, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('301', '94', 'config_export_to_name', 'text', 'input', '', 1, '', 0, 0, '\"\"', '发货人姓名', '快递面单发货人姓名', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('302', '94', 'config_export_to_tel', 'text', 'input', '', 1, '', 0, 0, '\"\"', '发货人电话', '快递面单发货人电话', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('303', '94', 'config_export_to_address', 'text', 'input', '', 1, '', 0, 0, '\"\"', '发货人详细地址', '快递面单发货人详细地址', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('304', '94', 'config_export_siid', 'text', 'input', '', 1, '', 0, 0, '\"\"', '打印机编号', '请购买快递100二代云打印机(KX100L3)', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('305', '69', 'service_feedback', 'textarea', 'input', '', 1, '', 100, 7, '\"\\u5c0a\\u656c\\u7684\\u7528\\u6237\\uff0c\\u5ba2\\u670d\\u5f53\\u524d\\u4e0d\\u5728\\u7ebf\\uff0c\\u6709\\u95ee\\u9898\\u8bf7\\u7559\\u8a00\\uff0c\\u6211\\u4eec\\u4f1a\\u7b2c\\u4e00\\u65f6\\u95f4\\u8fdb\\u884c\\u5904\\u7406\\uff01\\uff01\\uff01\"', '客服反馈', '暂无客服在线是,联系客服跳转的客服反馈页面的显示文字', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('307', '11', 'integral_max_num', 'text', 'input', '', 0, '', 100, 0, '\"100\"', '积分抵扣上限', '单次下单积分使用上限,0不限制', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('308', '74', 'brokerage_type', 'radio', 'input', '0=>线下手动转账\n1=>自动到微信零钱', 1, '', 0, 0, '0', '到账方式', '佣金到账方式支持线下转账和微信零钱自动转账,手动转账更安全,自动转账更方便', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('310', '67', 'member_card_status', 'radio', 'input', '1=>开启\n0=>关闭', 1, '', 0, 0, '1', '开启付费会员', '付费会员开关', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('324', '72', 'spread_banner', 'upload', '', '', 2, '', 0, 0, '[\"\\/statics\\/system_images\\/spread_1.jpeg\",\"\\/statics\\/system_images\\/spread_2.jpeg\"]', '分销海报图', '个人中心分销海报图片,建议尺寸600x1000', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('326', '122', 'wap_login_logo', 'upload', 'input', '', 1, '', 0, 0, '\"\\/statics\\/system_images\\/login_logo.jpeg\"', '移动端登录LOGO', '移动端登录logo,建议尺寸86x86,建议png格式', 88, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('327', '75', 'pc_logo', 'upload', '', '', 1, '', 0, 0, '\"\\/statics\\/system_images\\/pc_logo.png\"', 'PC端LOGO', 'PC端LOGO', 0, 0, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('328', '125', 'record_No', 'text', 'input', '', 1, '', 0, 0, '\"\"', '备案号', '网站的备案号,显示在H5和PC端底部', 70, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('329', '7', 'routine_contact_type', 'radio', 'input', '0=>跟随系统\n1=>小程序客服', 1, '', 0, 0, '0', '客服类型', '跟随系统:跟随系统使用默认客服、电话或者跳转链接;小程序客服:需要在小程序后台配置客服用户;', 97, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('33', '114', 'offline_postage', 'radio', 'input', '1=>包邮\n0=>不包邮', 1, '', 0, 0, '0', '线下支付是否包邮', '用户选择线下支付时是否包邮', 97, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('330', '1', 'station_open', 'radio', 'input', '1=>开启\n0=>关闭', 1, '', 0, 0, '\"1\"', '站点开启', '站点开始|关闭(用于升级等临时关闭),关闭后前端会弹窗显示站点升级中,请稍后访问', 100, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('331', '73', 'uni_brokerage_price', 'text', 'input', '', 0, '', 100, 0, '\"2\"', '推广佣金单价', '分销推广佣金单价(每推广一个用户)', 93, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('332', '73', 'day_brokerage_price_upper', 'text', 'input', '', 0, '', 100, 0, '\"-1\"', '每日推广佣金上限', '每日推广佣金上限(0:不发佣金-1:不限制;注最好是推广佣金单价的整数倍)', 92, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('333', '73', 'is_self_brokerage', 'radio', '', '1=>开启\n0=>关闭', 0, '', 0, 0, '0', '自购返佣', '是否开启自购返佣(开启:分销员自己购买商品,享受一级返佣,上级享受二级返佣; 关闭:分销员自己购买商品没有返佣)', 99, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('334', '72', 'store_brokerage_binding_status', 'radio', '', '1=>永久\n2=>有效期\n3=>临时', 0, '', 0, 0, '1', '绑定模式', '永久”一次绑定永久有效,“有效期”绑定后一段时间内有效,“临时” 临时有效', 91, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('335', '72', 'store_brokerage_binding_time', 'text', 'input', '', 0, '', 100, 0, '\"1\"', '绑定有效期', '绑定有效期(绑定后N天内有效)', 90, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('336', '71', 'refund_name', 'text', 'input', '', 1, '', 0, 0, '\"\"', '退货收货人姓名', '用户退货退款后台同意之后,显示在退货订单详情显示的接受退货的人员姓名', 90, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('337', '71', 'refund_phone', 'text', 'input', '', 1, '', 0, 0, '\"\"', '退货收货人电话', '用户退货退款后台同意之后,显示在退货订单详情显示的接受退货的人员电话', 90, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('338', '71', 'refund_address', 'text', 'input', '', 1, '', 0, 0, '\"\"', '退货收货人地址', '用户退货退款后台同意之后,显示在退货订单详情显示的接受退货的地址信息', 90, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('339', '73', 'brokerage_user_status', 'radio', '', '1=>开启\n0=>关闭', 0, '', 100, 0, '1', '推广用户返佣', '分销推广用户获取佣金', 94, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('34', '11', 'integral_ratio', 'text', 'input', '', 0, 'number:true', 100, 0, '\"0.1\"', '积分抵用', '积分抵用比例(1积分抵多少金额)单位:元', 10, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('340', '75', 'wechat_open_app_id', 'text', 'input', '', 1, '', 0, 0, '\"\"', 'AppID', '微信开放平台申请网页应用后给予的AppID', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('341', '75', 'wechat_open_app_secret', 'text', 'input', '', 1, '', 0, 0, '\"\"', 'AppSecret', '微信开放平台申请网页应用后给予的AppSecret', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('342', '75', 'contact_number', 'text', 'input', '', 1, '', 0, 0, '\"\"', '联系电话', 'PC底部显示的联系电话', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('343', '75', 'company_address', 'text', 'input', '', 1, '', 0, 0, '\"\"', '公司地址', 'PC底部显示的公司地址', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('345', '75', 'site_keywords', 'text', 'input', '', 0, '', 100, 0, '\"\"', '关键词', '网站关键词', 0, 0, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('346', '75', 'site_description', 'textarea', '', '', 0, '', 100, 5, '\"\"', '网站描述', '网站描述', 0, 0, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('347', '75', 'product_phone_buy_url', 'radio', 'input', '1=>公众号\n2=>小程序', 1, '', 0, 0, '\"1\"', '二维码类型', '商品详情手机购买显示公众号码或者小程序码', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('348', '75', 'bast_number', 'text', 'number', '', 0, 'required:true,digits:true,min:1', 100, 0, '0', '精品推荐个数', '首页配置精品推荐个数', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('349', '75', 'first_number', 'text', 'number', '', 0, 'required:true,digits:true,min:1', 100, 0, '0', '首发新品个数', '首页配置首发新品个数', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('350', '69', 'customer_type', 'radio', 'input', '0=>系统客服\n1=>拨打电话\n2=>跳转链接', 0, '', 0, 0, '0', '客服类型', '系统客服:点击联系客服使用系统的自带客服;拨打电话:点击联系客服拨打客服电话;跳转链接:跳转外部链接联系客服', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('351', '69', 'customer_url', 'text', 'input', '', 1, '', 0, 0, '\"\"', '客服链接', '客服类型选择跳转链接时,跳转的链接地址', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('352', '69', 'customer_phone', 'text', 'input', '', 1, '', 0, 0, '\"\"', '客服电话', '客服类型选择不打电话是,用户点击联系客服的联系电话', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('353', '77', 'wechat_app_appid', 'text', 'input', '', 1, '', 0, 0, '\"\"', 'APPID', '微信开放平台申请移动应用后给予的APPID', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('354', '77', 'wechat_app_appsecret', 'text', 'input', '', 1, '', 0, 0, '\"\"', 'AppSecret', '微信开放平台申请移动应用后给予的AppSecret', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('355', '123', 'statistic_script', 'textarea', 'input', '', 1, '', 100, 10, '\"\"', '统计代码', '程序访问统计代码,填写script标签内的内容', 80, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('359', '2', 'weixin_ckeck_file', 'upload', 'input', '', 3, '', 0, 0, '\"\"', '微信校验文件', '配置微信网页授权域名时候下载的微信校验文件,在此处上传', 72, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('360', '31', 'thumb_big_width', 'text', 'input', '', 0, '', 100, 0, '\"800\"', '缩略大图(单位:px):宽', '缩略大图(单位:px):宽', 99, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('361', '31', 'thumb_big_height', 'text', 'input', '', 0, '', 100, 0, '\"800\"', '缩略大图(单位:px):高', '缩略大图(单位:px):高', 98, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('362', '31', 'thumb_mid_width', 'text', 'input', '', 0, '', 50, 0, '\"300\"', '缩略中图(单位:px):宽', '缩略中图(单位:px):宽', 97, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('363', '31', 'thumb_mid_height', 'text', 'input', '', 0, '', 50, 0, '\"300\"', '缩略中图(单位:px):高', '缩略中图(单位:px):高', 96, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('364', '31', 'thumb_small_width', 'text', 'input', '', 0, '', 50, 0, '\"150\"', '缩略小图(单位:px): 宽', '缩略小图(单位:px): 宽', 95, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('365', '31', 'thumb_small_height', 'text', 'input', '', 0, '', 50, 0, '\"150\"', '缩略小图(单位:px): 高', '缩略小图(单位:px): 高', 94, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('366', '31', 'image_watermark_status', 'radio', '', '1=>开启\n0=>关闭', 0, '', 0, 0, '0', '是否开启水印', '图片水印是否开服', 80, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('367', '31', 'watermark_type', 'radio', '', '1=>图片\n2=>文字', 0, '', 0, 0, '1', '水印类型', '水印类型:图片、文字', 29, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('368', '31', 'watermark_image', 'upload', 'input', '', 1, '', 0, 0, '\"\"', '水印图片', '水印图片链接', 28, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('369', '31', 'watermark_position', 'radio', '', '1=>左上\n2=>上中\n3=>右上\n4=>左中\n5=>中\n6=>右中\n7=>左下\n8=>下中\n9=>右下', 0, '', 0, 0, '5', '水印位置', 'watermark_position', 27, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('370', '31', 'watermark_opacity', 'text', 'input', '', 0, '', 100, 0, '\"\"', '水印图片透明度', '水印图片透明度', 25, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('371', '31', 'watermark_rotate', 'text', 'input', '', 0, '', 100, 0, '\"\"', '水印图片倾斜度', '水印图片倾斜度', 24, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('372', '31', 'watermark_text', 'text', 'input', '', 1, '', 0, 0, '\"\"', '水印文字', '水印文字', 28, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('373', '31', 'watermark_text_size', 'text', 'input', '', 0, '', 100, 0, '\"\"', '水印文字大小(单位:px)', '水印文字大小(px)', 27, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('374', '31', 'watermark_text_color', 'text', 'input', '', 0, '', 100, 0, '\"#666666\"', '水印字体颜色', '水印字体颜色', 25, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('375', '31', 'watermark_text_angle', 'text', 'input', '', 0, '', 100, 0, '\"\"', '水印字体旋转角度', '水印字体旋转角度', 24, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('376', '31', 'watermark_x', 'text', 'input', '', 0, '', 100, 0, '\"\"', '水印横坐标偏移量(单位:px)', '水印横坐标偏移量(单位:px)', 23, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('377', '31', 'watermark_y', 'text', 'input', '', 0, '', 100, 0, '\"\"', '水印纵坐标偏移量(单位:px)', '水印纵坐标偏移量(单位:px)', 22, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('379', '122', 'ico_path', 'upload', 'input', '', 3, '', 0, 0, '\"\"', '系统ICO图标', '程序ICO图标,更换后需要清除浏览器缓存', 85, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('383', '82', 'tengxun_appid', 'text', 'input', '', 0, '', 0, 0, '\"\"', '腾讯云APPID', '腾讯云APPID', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('384', '74', 'extract_type', 'checkbox', 'input', '0=>银行卡\n1=>微信\n2=>支付宝', 1, '', 0, 0, '[\"0\",\"1\",\"2\"]', '提现方式', '提现方式', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('385', '11', 'integral_frozen', 'text', 'input', '', 1, '', 100, 0, '\"0\"', '积分冻结(天)', '积分冻结(天),0为不冻结', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('386', '86', 'print_type', 'radio', 'input', '1=>易联云\n2=>飞鹅云', 1, '', 0, 0, '\"1\"', '平台选择', '打印平台选择', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('387', '93', 'config_export_type', 'radio', 'input', '1=>一号通', 1, '', 0, 0, '1', '电子面单类型', '电子面单类型', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('388', '69', 'customer_corpId', 'text', 'input', '', 1, '', 0, 0, '\"\"', '企业ID', '如果客服链接填写企业微信客服,小程序需要跳转企业微信客服的话需要配置此项,并且在小程序客服中绑定企业ID', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('389', '2', 'create_wechat_user', 'radio', 'input', '1=>开启\r\n0=>关闭', 1, '', 0, 0, '0', '关注是否生成用户', '用户关注公众号之后是否生成商城用户', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('390', '109', 'friend_pay_status', 'radio', 'input', '1=>开启\r\n0=>关闭', 1, '', 0, 0, '1', '好友代付', '好友代付开关,关闭后付款类型不显示好友代付', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('392', '72', 'brokerage_level', 'radio', 'input', '1=>一级分销\r\n2=>二级分销', 1, '', 0, 0, '2', '分销层级', '分销层级,一级是只返上级一层的佣金,二级是返上级和上上级的佣金', 98, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('393', '97', 'sms_type', 'radio', 'input', '0=>一号通\r\n1=>阿里云\r\n2=>腾讯云', 1, '', 0, 0, '0', '短信类型', '短信类型,选择发送的短信类型', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('395', '98', 'aliyun_AccessKeySecret', 'text', 'input', '', 1, '', 0, 0, '\"\"', 'AccessKeySecret', '阿里云AccessKeySecret', 99, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('396', '98', 'aliyun_RegionId', 'text', 'input', '', 1, '', 0, 0, '\"\"', 'RegionId', '阿里云RegionId', 98, 0, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('397', '98', 'aliyun_SignName', 'text', 'input', '', 1, '', 100, 0, '\"\"', '短信签名', '短信签名', 97, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('398', '99', 'tencent_sms_app_id', 'text', 'input', '', 1, '', 100, 0, '\"\"', 'SKD AppID', '腾讯云短信应用SKD APPID', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('399', '99', 'tencent_sms_secret_id', 'text', 'input', '', 1, '', 100, 0, '\"\"', 'AccessKeyId', '腾讯云AccessKeyId', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('3e773cd2-9df1-4d67-b520-3c182f0f31c6', 'f7c6a5dc-2354-491d-9e07-1ede3b80480b', 'trest_url', 'text', '', '', 1, '', 100, 5, '\"\"', '测试添加', 'asdfasdgf', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('4', '1', 'site_phone', 'text', 'input', '', 0, '', 100, 0, '\"\"', '联系电话', '联系电话', 0, 0, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('400', '99', 'tencent_sms_secret_key', 'text', 'input', '', 1, '', 100, 0, '\"\"', 'AccessKeySecret', '腾讯云AccessKeySecret', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('401', '99', 'tencent_sms_sign_name', 'text', '', '', 1, '', 100, 0, '\"\"', '腾讯云短信签名', '腾讯云短信签名', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('402', '99', 'tencent_sms_region', 'text', 'input', '', 1, '', 100, 0, '\"\"', '短信区域', '短信区域ap-beijing、ap-guangzhou、ap-nanjing任选其一填写', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('409', '4', 'pay_new_weixin_open', 'radio', 'input', '0=>商户号绑定\n1=>非商户号绑定', 1, '', 0, 0, '0', '小程序商户号选择', '小程序开发后台有支付管理的请选择非商户号绑定', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('410', '4', 'pay_new_weixin_mchid', 'text', 'input', '', 1, '', 0, 0, '\"\"', '小程序支付商户号', '小程序开通支付管理生成的商户号', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('411', '117', 'system_comment_time', 'text', 'number', '', 1, '', 0, 0, '\"0\"', '自动评价时间', '商城订单在收货之后,用户如果不主动评价订单商品,则在N天后自动评价,设置0为永远不自动评价', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('412', '117', 'comment_content', 'text', 'input', '', 1, '', 0, 0, '\"\\u6b64\\u7528\\u6237\\u672a\\u505a\\u8bc4\\u4ef7\"', '自动评价文字', '自动评价显示的评价文字', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('413', '4', 'pay_wechat_type', 'radio', 'input', '0=>v2 (支持企业付款到零钱)\n1=>v3 (支持商户转账到零钱)', 1, '', 0, 0, '0', '支付接口类型', '支付接口类型v2对应微信支付旧版v2支付。v3对应微信支付v3支付接口。支付证书可以通用一个。支付秘钥和v2旧版支付有区别', 10, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('414', '4', 'pay_weixin_serial_no', 'text', 'input', '', 1, '', 100, 0, '\"\"', '证书序列号', '「商户API证书」的「证书序列号」,可以在证书管理里面查看', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('415', '4', 'pay_weixin_key_v3', 'text', 'input', '', 1, '', 100, 0, '\"\"', 'V3支付Key', 'V3支付秘钥', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('416', '105', 'reward_money', 'text', 'number', '', 1, '', 0, 0, '\"0\"', '赠送余额(元)', '新用户奖励金额,必须大于等于0,0为不赠送', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('417', '105', 'reward_integral', 'text', 'number', '', 1, '', 0, 0, '\"0\"', '赠送积分', '新用户奖励积分,必须大于等于0,0为不赠送', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('418', '106', 'hs_accesskey', 'text', 'input', '', 1, '', 0, 0, '\"AKLTMzkzZTEzNjg3OTg2NDViM2IwNmFlYzhmNzE4MmI4YmI\"', 'AccessKey', '机器翻译仅支持火山翻译,注册地址https://console.volcengine.com,在访问控制里面新建api密钥', 1, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('419', '106', 'hs_secretkey', 'text', 'input', '', 1, '', 0, 0, '\"TVRneU16STFOVFV4WVRkbE5ERTJaV0pqWm1aaU1UaGlNVFppWldZeE1HUQ==\"', 'SecretKey', '机器翻译仅支持火山翻译,注册地址https://console.volcengine.com,在访问控制里面新建api密钥', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('420', '107', 'fey_user', 'text', 'input', '', 1, '', 0, 0, '\"\"', '飞鹅云USER', '飞鹅云后台注册账号', 10, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('421', '107', 'fey_ukey', 'text', 'input', '', 1, '', 0, 0, '\"\"', '飞鹅云UYEK', '飞鹅云后台注册账号后生成的UKEY 【备注:这不是填打印机的KEY】', 7, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('422', '107', 'fey_sn', 'text', 'input', '', 1, '', 100, 0, '\"\"', '飞鹅云SN', '打印机标签上的编号,必须要在管理后台里添加打印机或调用API接口添加之后,才能调用API', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('423', '108', 'allin_private_key', 'text', 'input', '', 1, '', 100, 5, '\"\"', '通联MD5私钥', '通联支付的MD5私钥,可以在商户后台设置中进行配置', 96, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('425', '108', 'allin_cusid', 'text', '', '', 1, '', 0, 0, '\"\"', '通联商户号', '通联支付商户号,由贵公司申请获得', 99, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('426', '108', 'allin_appid', 'text', '', '', 1, '', 100, 0, '\"\"', '通联支付Appid', '通联商户后台的设置-》对接设置中查看', 98, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('428', '1', 'queue_open', 'radio', 'input', '1=>开启\n0=>关闭', 1, '', 0, 0, '\"1\"', '消息队列', '是否启用消息队列,启用后提升程序运行速度,启用前必须配置Redis缓存,文档地址:https://doc.crmeb.com/single/crmeb_v4/7217', 73, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('429', '7', 'get_avatar', 'radio', 'input', '1=>开启\n0=>关闭', 1, '', 0, 0, '\"1\"', '强制获取昵称头像', '是否在小程序用户授权之后,弹窗获取用户的昵称和头像', 89, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('430', '2', 'share_qrcode', 'radio', 'input', '0=>商城\n1=>公众号', 1, '', 0, 0, '0', '公众号推广码类型', '公众号生成的推广码类型:商城:扫码直接进入商城,公众号:扫码进入公众号后推送商城的链接', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('431', '73', 'member_brokerage', 'radio', 'input', '1=>开启\n0=>关闭', 1, '', 0, 0, '\"0\"', '购买付费会员返佣', '购买付费会员是否按照设置的佣金比例进行返佣', 98, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('432', '73', 'user_brokerage_type', 'radio', 'input', '0=>按照商品价格返佣\n1=>按照实际支付价格返佣', 1, '', 0, 0, '\"0\"', '返佣类型', '选择返佣类型,按照商品价格返佣(按照商品售价计算返佣金额)以及按照实际支付价格返佣(按照商品的实际支付价格计算返佣 )', 97, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('433', '125', 'network_security', 'text', 'input', '', 1, '', 0, 0, '\"\"', '网安备案', '公安部门登记的备案信息,显示在pc底部', 8, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('435', '125', 'icp_url', 'text', 'input', '', 1, '', 0, 0, '\"\"', 'ICP备案链接', 'H5和PC底部显示的ICP备案号点击跳转的链接', 9, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('436', '125', 'network_security_url', 'text', 'input', '', 1, '', 0, 0, '\"\"', '网安备案链接', 'H5和PC底部显示的网安备案号点击跳转的链接', 7, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('438', '7', 'order_shipping_open', 'radio', 'input', '1=>开启\n0=>关闭', 1, '', 0, 0, '0', '发货信息管理', '小程序有订单发货管理时,请打开此开关,否则会导致订单资金冻结', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('44', '28', 'store_user_min_recharge', 'text', 'number', '', 1, 'required:true,number:true,min:0', 100, 0, '0.01', '最低充值金额', '用户单次最低充值金额', 3, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('440', '110', 'jd_accessKey', 'text', 'input', '', 1, '', 100, 0, '\"\"', '京东云accessKey', '京东云accessKey', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('441', '110', 'jd_secretKey', 'text', 'input', '', 1, '', 100, 0, '\"\"', '京东云secretKey', '京东云secretKey', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('442', '111', 'hw_accessKey', 'text', 'input', '', 1, '', 100, 0, '\"\"', '华为云accessKey', '华为云accessKey', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('443', '111', 'hw_secretKey', 'text', 'input', '', 1, '', 100, 0, '\"\"', '华为云secretKey', '华为云secretKey', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('444', '112', 'ty_secretKey', 'text', 'input', '', 1, '', 100, 0, '\"\"', '天翼云secretKey', '天翼云secretKey', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('445', '112', 'ty_accessKey', 'text', 'input', '', 1, '', 100, 0, '\"\"', '天翼云accessKey', '天翼云accessKey', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('446', '71', 'coupon_return_open', 'radio', 'input', '1=>退还\n0=>不退还', 1, '', 0, 0, '\"0\"', '优惠券退还状态', '优惠券是否退回开关,商品成功退款后,退回/不退回使用的优惠券', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('447', '110', 'jd_storageRegion', 'text', 'input', '', 1, '', 100, 0, '\"\"', '京东云storageRegion', '京东云storageRegion', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('449', '126', 'sign_status', 'radio', 'input', '1=>开启\n0=>关闭', 1, '', 0, 0, '1', '签到开关', '签到开关,商城是否开启签到功能,关闭后隐藏签到入口', 100, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('450', '126', 'sign_mode', 'radio', 'input', '-1=>无限制\n1=>周循环\n0=>月循环', 1, '', 0, 0, '\"-1\"', '签到模式', '无限制,累积和连续签到不会清零,周循环,每周一会清理累积和连续的记录为0,重新开启计算,月循环,每月一号会清理累积和连续的记录为0,重新开启计算', 95, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('451', '126', 'sign_remind', 'radio', 'input', '1=>开启\n0=>关闭', 1, '', 0, 0, '0', '签到提醒', '是否开启签到提醒,提醒方式为短信以及站内信', 90, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('452', '126', 'sign_remind_time', 'text', 'time', '', 1, '', 100, 0, '\"09:00:00\"', '提醒时间', '选择每日未签到提醒的通知时间', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('453', '126', 'sign_remind_type', 'checkbox', 'input', '1=>短信\n2=>站内信', 1, '', 0, 0, '[\"1\",\"2\"]', '提醒方式', '签到每日提醒的提醒方式,支持短信和站内信', 80, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('454', '126', 'sign_give_point', 'text', 'number', '', 1, '', 0, 0, '10', '签到赠送积分', '签到赠送积分,每日签到赠送的积分值', 75, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('455', '4', 'mer_type', 'radio', 'input', '0=>微信支付商户模式\n1=>微信支付服务商模式', 1, '', 0, 0, '0', '商户类型', '商户类型,目前支持普通微信商户模式和普通微信服务商模式;', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('456', '4', 'pay_sub_merchant_id', 'text', 'input', '', 1, '', 0, 0, '\"\"', '子商户商户号', '微信支付服务商子商户商户号', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('457', '74', 'withdrawal_fee', 'text', 'number', '', 1, '', 100, 0, '\"0\"', '提现手续费', '提现手续费百分比,范围0-100,0为无提现手续费,例:设置10,即收取10%手续费,提现100元,到账90元,10元手续费', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('458', '7', 'routine_auth_type', 'checkbox', 'input', '1=>微信授权\n2=>手动填写', 1, '', 0, 0, '[\"1\",\"2\"]', '手机号获取方式', '小程序获取手机号的方式,微信授权和手机号验证码', 90, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('459', '2', 'wechat_template_to_miniprogram', 'radio', 'input', '1=>小程序页面\n0=>公众号页面', 1, '', 0, 0, '\"0\"', '模版消息跳转地址', '用户收到的模版消息,点击是跳转小程序还是公众号,如果跳转小程序,需要在小程序中关联公众号', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('46', '92', 'system_express_app_code', 'text', 'input', '', 1, '', 0, 0, '\"\"', '快递查询密钥', '阿里云云市场快递查询接口密钥购买地址:https://market.aliyun.com/products/57126001/cmapi021863.html?spm=5176.2020520132.101.4.42a672183nvgfH#sku=yuncode1586300000', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('460', '1', 'cert_crmeb', 'text', 'input', '', 1, '', 0, 0, '\",\\u5f00\\u6e90\\u7248\"', '授权密钥', '', 0, 2, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('461', '1', 'test', '', 'input', '1=>白色\n2=>红色\n4=>绿色', 1, '', 0, 0, '\"\"', '下来框test', '测试下拉框', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('462', '1', 'trr', '', 'input', '1=>test\n2=>asdfa', 1, '', 0, 0, '\"\"', '123', 'adsfsdg', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('49', '73', 'store_brokerage_ratio', 'text', 'input', '', 0, 'required:true,min:0,max:100,number:true', 100, 0, '\"10\"', '一级返佣比例', '订单交易成功后给上级返佣的比例0 - 100,例:5 = 反订单商品金额的5%', 5, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('53', '74', 'user_extract_min_price', 'text', 'input', '', 0, 'required:true,number:true,min:0', 100, 0, '\"1\"', '提现最低金额', '用户提现最低金额限制', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('59', '7', 'routine_appId', 'text', 'input', '', 1, '', 100, 0, '\"1\"', 'appId2', '小程序appID', 100, 1, NULL, 1695360388); +INSERT INTO `lms_clx_system_config` VALUES ('60', '7', 'routine_appsecret', 'text', 'input', '', 0, '', 100, 0, '\"\"', 'AppSecret', '小程序AppSecret', 99, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('61', '2', 'api', 'text', 'input', '', 1, '', 0, 0, '\"\\/api\\/wechat\\/serve\"', '接口地址', '配置服务器域名使用的接口地址,直接复制输入框内容(此项系统生成,无法修改)', 92, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('74', '7', 'routine_name', 'text', 'input', '', 0, '', 100, 0, '\"\"', '小程序名称', '小程序名称', 98, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('77', '120', 'store_stock', 'text', 'number', '', 1, '', 0, 0, '\"10\"', '警戒库存', '商品库存数量低于多少时,提示库存不足', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('85', '71', 'stor_reason', 'textarea', 'input', '', 1, '', 100, 8, '\"\\u6536\\u8d27\\u5730\\u5740\\u586b\\u9519\\u4e86\\n\\u4e0e\\u63cf\\u8ff0\\u4e0d\\u7b26\\n\\u4fe1\\u606f\\u586b\\u9519\\u4e86\\uff0c\\u91cd\\u65b0\\u62cd\\n\\u6536\\u5230\\u5546\\u54c1\\u635f\\u574f\\u4e86\\n\\u672a\\u6309\\u9884\\u5b9a\\u65f6\\u95f4\\u53d1\\u8d27\\n\\u5176\\u5b83\\u539f\\u56e0\"', '退货理由', '配置退货理由,一行一个理由', 0, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('87', '73', 'store_brokerage_two', 'text', 'input', '', 0, 'required:true,min:0,max:100,number:true', 100, 0, '\"5\"', '二级返佣比例', '订单交易成功后给上级返佣的比例0 - 100,例:5 = 反订单商品金额的5%', 4, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('88', '72', 'store_brokerage_statu', 'radio', '', '1=>指定分销\n2=>人人分销\n3=>满额分销', 0, '', 0, 0, '1', '分销模式', '人人分销”默认每个人都可以分销,“指定分销”仅可后台手动设置推广员,“满额分销”指用户购买商品满足消费金额后自动开启分销', 95, 1, NULL, NULL); +INSERT INTO `lms_clx_system_config` VALUES ('99', '74', 'user_extract_bank', 'textarea', '', '', 0, '', 100, 5, '\"\\u4e2d\\u56fd\\u94f6\\u884c\"', '提现银行卡', '配置提现银行卡类型,每个银行换行', 0, 1, NULL, NULL); + +-- ---------------------------- +-- Table structure for lms_clx_system_config_tab +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_config_tab`; +CREATE TABLE `lms_clx_system_config_tab` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '配置分类id', + `pid` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '上级分类id', + `title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '配置分类名称', + `eng_title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '配置分类英文名称', + `status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '配置分类状态', + `info` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '配置分类是否显示', + `icon` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '图标', + `type` int(2) NOT NULL DEFAULT 0 COMMENT '配置类型', + `sort` int(11) NOT NULL DEFAULT 0 COMMENT '排序', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '配置分类表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_config_tab +-- ---------------------------- +INSERT INTO `lms_clx_system_config_tab` VALUES ('1', '129', '基础配置', 'basics', 1, 0, 'ios-settings', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('100', '-1', '用户配置', 'system_user_config', 1, 0, 'layui-icon-rate-half', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('102', '65', '对外接口配置', 'out_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('103', '102', '基础配置', 'out_basic', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('104', '102', '推送配置', 'out_push', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('105', '100', '新用户设置', 'new_user_setting', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('106', '129', '翻译配置', 'online_translation', 0, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('107', '21', '飞鹅云配置', 'fey_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('108', '23', '通联支付', 'allinpay', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('109', '23', '基础配置', 'pay_basic', 1, 0, '', 3, 100); +INSERT INTO `lms_clx_system_config_tab` VALUES ('11', '100', '用户积分配置', 'point', 0, 0, 'logo-euro', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('110', '79', '京东云配置', 'jd_oss_config', 0, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('111', '79', '华为云配置', 'obs_config', 0, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('112', '79', '天翼云配置', 'ty_oss_config', 0, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('113', '0', '订单配置', 'order_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('114', '113', '包邮设置', 'free_shipping_config', 1, 0, '', 3, 10); +INSERT INTO `lms_clx_system_config_tab` VALUES ('115', '113', '订单取消配置', 'order_cancel_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('116', '113', '自动收货配置', 'auto_take_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('117', '113', '自动评价配置', 'auto_reviews_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('119', '113', '到店自提配置', 'self_mention_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('120', '113', '警戒库存配置', 'store_stock_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('122', '129', 'LOGO配置', 'site_logo_config', 1, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('123', '129', '统计配置', 'statistics_config', 1, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('124', '129', '地图配置', 'map_config', 1, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('125', '129', '备案配置', 'beian_config', 1, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('126', '100', '用户签到配置', 'user_sign_config', 0, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('129', '0', '系统配置', 'system_config', 1, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('18', '65', '一号通', 'system_sms', 1, 0, 'ios-chatboxes', 3, 99); +INSERT INTO `lms_clx_system_config_tab` VALUES ('2', '78', '公众号配置(H5)', 'wechat', 1, 0, 'ios-chatbubbles', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('21', '65', '小票打印配置', 'printing_deploy', 1, 0, 'logo-buffer', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('23', '65', '商城支付配置', 'pay_config', 1, 0, 'logo-usd', 3, 70); +INSERT INTO `lms_clx_system_config_tab` VALUES ('28', '100', '用户充值配置', 'recharge_site', 0, 0, '', 3, 2); +INSERT INTO `lms_clx_system_config_tab` VALUES ('31', '79', '基础配置', 'base_config', 0, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('4', '23', '微信支付配置', 'pay', 1, 0, 'ios-chatbubbles', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('41', '65', '采集商品配置', 'copy_product', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('45', '100', '用户等级配置', 'store_member', 1, 0, '', 3, 3); +INSERT INTO `lms_clx_system_config_tab` VALUES ('497fdf2d-cc01-4c2a-96cb-7576727030d6', '-1', '阿萨的官方', '私人代表', 1, 0, 'layui-icon-face-smile', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('50', '113', '发票功能配置', 'store_invoice', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('63', '23', '支付宝支付配置', 'ali_pay', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('64', '65', '物流查询配置', 'logistics_select', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('65', '0', '接口设置', 'system_serve', 1, 0, 'md-briefcase', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('66', '65', '电子面单配置', 'electronic_sheet', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('67', '100', '付费会员配置', 'member_card', 0, 0, '', 3, 2); +INSERT INTO `lms_clx_system_config_tab` VALUES ('69', '0', '客服配置', 'kefu_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('7', '78', '小程序配置', 'routine', 1, 0, 'logo-android', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('70', '129', '分享配置', 'share_index_config', 1, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('71', '113', '售后退款配置', 'refund_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('72', '9', '分销模式', 'brokerage_type', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('73', '9', '返佣设置', 'brokerage_set', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('74', '9', '提现设置', 'extract_set', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('75', '78', 'PC站点配置', 'system_pc', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('77', '78', 'APP配置', 'app', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('78', '0', '应用配置', 'sys_app', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('79', '65', '系统存储配置', 'storage_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('80', '79', '七牛云配置', 'qiniu_config', 0, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('81', '79', '阿里云配置', 'oss_config', 0, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('82', '79', '腾讯云配置', 'cos_config', 0, 0, '', 0, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('86', '21', '基础配置', 'print_basic', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('87', '21', '易联云配置', 'yly_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('89', '41', '基础配置', 'copy_basic', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('9', '0', '分销配置', 'fenxiao', 1, 0, 'md-contacts', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('90', '41', '99api配置', '99api_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('91', '64', '基础配置', 'logistics_basic', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('92', '64', '阿里云配置', 'logistics_aliyun', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('93', '66', '基础配置', 'electronic_basic', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('94', '66', '一号通配置', 'system_electronic_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('96', '65', '短信接口配置', 'sms_config', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('97', '96', '基础配置', 'sms_config_basic', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('98', '96', '阿里云配置', 'sms_aliyun', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('99', '96', '腾讯云配置', 'tencent_sms', 1, 0, '', 3, 0); +INSERT INTO `lms_clx_system_config_tab` VALUES ('f7c6a5dc-2354-491d-9e07-1ede3b80480b', '-1', '测试分类', 'test', 1, 0, 'layui-icon-face-smile', 0, 0); + +-- ---------------------------- +-- Table structure for lms_clx_system_cross_menu +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_cross_menu`; +CREATE TABLE `lms_clx_system_cross_menu` ( + `cross_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '跨权限者的ID(用户ID、用户组ID、职位ID、组织ID)', + `permission_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '被跨越的权限ID', + `cross_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '跨越者名称', + `permission_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '被跨越权限名称', + `sys_code` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '系统编码C', + PRIMARY KEY (`cross_id`, `permission_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '跨权限映射表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_cross_menu +-- ---------------------------- + +-- ---------------------------- +-- Table structure for lms_clx_system_cross_role +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_cross_role`; +CREATE TABLE `lms_clx_system_cross_role` ( + `cross_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '跨角色者的ID(用户ID、用户组ID、职位ID、组织ID)', + `role_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '被跨越的角色ID', + `cross_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '跨角色者的名称', + `role_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '被跨越角色名称', + `sys_code` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '系统编码', + PRIMARY KEY (`cross_id`, `role_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '跨角色映射表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_cross_role +-- ---------------------------- + +-- ---------------------------- +-- Table structure for lms_clx_system_dept +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_dept`; +CREATE TABLE `lms_clx_system_dept` ( + `dept_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '组织ID', + `dept_type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '组织类型(1:总公司 2:分公司 3:部门)', + `dept_code` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组织编码', + `dept_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '组织名称', + `pid` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '上级组织ID', + `sort` int(3) NULL DEFAULT NULL COMMENT '节点位置,越小越靠前', + `icon` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字体图标', + `level` int(10) NULL DEFAULT 1 COMMENT '部门等级', + `status` tinyint(4) NULL DEFAULT 1 COMMENT '正常1 禁用0', + `delete_time` int(10) NULL DEFAULT NULL COMMENT '删除时间', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `remark` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '备注', + PRIMARY KEY (`dept_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '部门表(有上下级关系)' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_dept +-- ---------------------------- +INSERT INTO `lms_clx_system_dept` VALUES ('06c9f2dc-c1a7-4a8e-b317-fa78af8e3346', '1', 'IT', '信息技术', 'b9191372-1051-45aa-aa32-63b6eca5f1c1', 10, 'layui-icon-group', 1, 1, NULL, 1710229114, 1710229390, NULL); +INSERT INTO `lms_clx_system_dept` VALUES ('44d21f0e-e34f-4a2b-92f5-ad1f1b0a049a', '1', 'SLS', '销售', 'b9191372-1051-45aa-aa32-63b6eca5f1c1', 10, 'layui-icon-group', 1, 1, NULL, 1710229046, 1710229397, NULL); +INSERT INTO `lms_clx_system_dept` VALUES ('460b9e0a-2dce-44c9-b29d-4a0dc8565a1e', '1', 'ADM', '行政', 'b9191372-1051-45aa-aa32-63b6eca5f1c1', 10, 'layui-icon-group', 1, 1, NULL, 1710229181, 1710229405, NULL); +INSERT INTO `lms_clx_system_dept` VALUES ('4908ba01-0562-455d-8b22-3b6b266b6d29', '1', 'CS', '客户服务', 'b9191372-1051-45aa-aa32-63b6eca5f1c1', 10, 'layui-icon-group', 1, 1, NULL, 1710229134, 1710229414, NULL); +INSERT INTO `lms_clx_system_dept` VALUES ('61041c06-86a8-4543-a123-50c409c69eac', '1', 'OPS', '运营', 'b9191372-1051-45aa-aa32-63b6eca5f1c1', 10, 'layui-icon-group', 1, 1, NULL, 1710229097, 1710229422, NULL); +INSERT INTO `lms_clx_system_dept` VALUES ('6dd10bef-c440-4c90-9205-0178fdf75d02', '1', 'MKT', '市场营销', 'b9191372-1051-45aa-aa32-63b6eca5f1c1', 10, 'layui-icon-group', 1, 1, NULL, 1710229032, 1710229436, NULL); +INSERT INTO `lms_clx_system_dept` VALUES ('79bd5ff7-df1e-4960-88ef-b28522722b48', '1', '0002', '深圳分公司', '-1', 100, 'layui-icon-group', 1, 1, NULL, 1710229499, 1710229518, NULL); +INSERT INTO `lms_clx_system_dept` VALUES ('8a161db3-59d4-49e5-89cf-0b44ddc891ff', '1', 'HR', '人力资源', 'b9191372-1051-45aa-aa32-63b6eca5f1c1', 10, 'layui-icon-group', 1, 1, NULL, 1710229077, 1710229450, NULL); +INSERT INTO `lms_clx_system_dept` VALUES ('94fa363c-66b0-4bb4-a59f-f4774c9c37ca', '1', 'FIN', '财务', 'b9191372-1051-45aa-aa32-63b6eca5f1c1', 10, 'layui-icon-group', 1, 1, NULL, 1710229058, 1710229442, NULL); +INSERT INTO `lms_clx_system_dept` VALUES ('b9191372-1051-45aa-aa32-63b6eca5f1c1', '1', 'DB', '上海集团总部', '-1', 10, 'layui-icon-group', 1, 1, NULL, 1710229311, 1710229384, NULL); +INSERT INTO `lms_clx_system_dept` VALUES ('e218caed-4c77-4a0b-a481-895f1986e9e0', '1', 'PND', '研发', 'b9191372-1051-45aa-aa32-63b6eca5f1c1', 10, 'layui-icon-group', 1, 1, NULL, 1710229148, 1710229458, NULL); +INSERT INTO `lms_clx_system_dept` VALUES ('f76ac4cd-2072-4ee4-9109-d34e54e4f5be', '1', 'LGL', '法务', 'b9191372-1051-45aa-aa32-63b6eca5f1c1', 10, 'layui-icon-group', 1, 1, NULL, 1710229167, 1710229464, NULL); + +-- ---------------------------- +-- Table structure for lms_clx_system_group +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_group`; +CREATE TABLE `lms_clx_system_group` ( + `group_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户组ID', + `group_name` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户组名称', + `group_code` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组编码', + PRIMARY KEY (`group_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户组(无上下级关系)' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_group +-- ---------------------------- + +-- ---------------------------- +-- Table structure for lms_clx_system_log +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_log`; +CREATE TABLE `lms_clx_system_log` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '管理员操作记录ID', + `admin_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '管理员id', + `admin_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '管理员姓名', + `path` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '链接', + `page` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '行为', + `method` varchar(12) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '访问类型', + `ip` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '登录IP', + `type` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '类型', + `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '操作时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `admin_id`(`admin_id`) USING BTREE, + INDEX `add_time`(`create_time`) USING BTREE, + INDEX `type`(`type`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '管理员操作记录表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_log +-- ---------------------------- +INSERT INTO `lms_clx_system_log` VALUES ('001920e7-dc9d-470a-ade9-1a37981b1bce', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127411); +INSERT INTO `lms_clx_system_log` VALUES ('0079d282-5c8f-44ab-8804-bf10f9f5d099', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712123792); +INSERT INTO `lms_clx_system_log` VALUES ('00cfbcc7-6e78-4242-843e-e6e1c4189fc2', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712121836); +INSERT INTO `lms_clx_system_log` VALUES ('0215eba6-00c8-42d3-ad74-d0ad8a5c1737', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114955); +INSERT INTO `lms_clx_system_log` VALUES ('02e3d01e-026b-4f40-837b-645457cb83dd', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129574); +INSERT INTO `lms_clx_system_log` VALUES ('03acb2a5-edbf-46f6-b7c7-4cee3f77a465', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127924); +INSERT INTO `lms_clx_system_log` VALUES ('04612172-3c06-4a82-b398-3e668fcc604d', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122833); +INSERT INTO `lms_clx_system_log` VALUES ('047dcc89-f515-4cfc-9c1e-db6fbc7d92b7', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/update_define', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113342); +INSERT INTO `lms_clx_system_log` VALUES ('0514af89-bcbf-4990-9b1d-7cfb2078610e', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712123561); +INSERT INTO `lms_clx_system_log` VALUES ('0607091a-b560-4f87-aa29-26886621e14a', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113071); +INSERT INTO `lms_clx_system_log` VALUES ('06402a78-3849-444c-8aeb-7bba1b22b393', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125926); +INSERT INTO `lms_clx_system_log` VALUES ('06f6c02f-87d7-4aac-a72f-100bd02e10ac', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/user/info', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113290); +INSERT INTO `lms_clx_system_log` VALUES ('07bdbf77-892f-466f-aac2-4530bba7b563', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114822); +INSERT INTO `lms_clx_system_log` VALUES ('0856febd-f418-48d7-b4b7-aae5963fd487', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125445); +INSERT INTO `lms_clx_system_log` VALUES ('085faae7-3e0c-4611-9245-cb566742a953', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114955); +INSERT INTO `lms_clx_system_log` VALUES ('09773956-ee93-4574-9b34-a453894c0323', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125575); +INSERT INTO `lms_clx_system_log` VALUES ('0a947206-835a-4654-944c-6f4f01efa76a', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114955); +INSERT INTO `lms_clx_system_log` VALUES ('0b25f173-0f77-4f12-92ab-cc6b160017b5', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113241); +INSERT INTO `lms_clx_system_log` VALUES ('0c0d20c1-02d2-4834-a6e1-baad4fa732b6', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124423); +INSERT INTO `lms_clx_system_log` VALUES ('0c8453a5-53a8-49d7-93fd-f676a3792566', '1', '超级管理员', 'wf/designer/deploy', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863287); +INSERT INTO `lms_clx_system_log` VALUES ('0cbde28b-3bce-40ab-8556-f7e02e572c12', '1', '超级管理员', 'wf/other/user/info', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863046); +INSERT INTO `lms_clx_system_log` VALUES ('0ce13336-7254-4d3f-a1e7-cc5c91d03cce', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122839); +INSERT INTO `lms_clx_system_log` VALUES ('0d23bf55-f22a-40be-b91b-711c86bcab39', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127924); +INSERT INTO `lms_clx_system_log` VALUES ('0d6a0eba-f4ca-4275-89d1-1e4d470fade4', '1', '超级管理员', 'wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716862924); +INSERT INTO `lms_clx_system_log` VALUES ('0e2881f3-a059-4125-9c58-ec887b99e69a', '12b440e6-0e71-48f2-9926-509bc4135ab8', '李明', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113054); +INSERT INTO `lms_clx_system_log` VALUES ('0ec2c825-27ec-46bf-b449-c70c68d3f6cd', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114837); +INSERT INTO `lms_clx_system_log` VALUES ('12e98691-d735-4196-954f-7941cd8d51e0', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127924); +INSERT INTO `lms_clx_system_log` VALUES ('13313ec9-cbbd-4431-8116-e32f82797b7e', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/approval_record', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127228); +INSERT INTO `lms_clx_system_log` VALUES ('135c54f0-59fd-4e8d-bd20-36f18cf63304', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/done/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129574); +INSERT INTO `lms_clx_system_log` VALUES ('1371a7af-84f9-4fa3-a9ad-fb4f5c7e453a', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125467); +INSERT INTO `lms_clx_system_log` VALUES ('13c251b4-f550-49a5-ae5d-1fbbe9b957cb', '1', '超级管理员', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1711956019); +INSERT INTO `lms_clx_system_log` VALUES ('16c11dd1-1093-46db-82fe-e6129cd2e636', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/approval_record', '未知', 'adminapi', '127.0.0.1', 'admin', 1712126021); +INSERT INTO `lms_clx_system_log` VALUES ('1959d880-0287-4579-994d-4df51c3a4f78', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712123561); +INSERT INTO `lms_clx_system_log` VALUES ('1a48cad6-12b6-43c9-a998-5fe4a82f96c8', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712123897); +INSERT INTO `lms_clx_system_log` VALUES ('1b13fb10-2dae-4160-8e28-0ec6f3d47f6d', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712121836); +INSERT INTO `lms_clx_system_log` VALUES ('1bd89759-4b28-4892-9a14-45b5930ff5c3', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113122); +INSERT INTO `lms_clx_system_log` VALUES ('1c7f4fbd-0fe4-481b-9d95-4f6c2c299a69', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114955); +INSERT INTO `lms_clx_system_log` VALUES ('1cd60ddd-6831-4415-b84b-498ff3c5ca64', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127828); +INSERT INTO `lms_clx_system_log` VALUES ('1d68f5b9-3f8a-4c3c-a6ae-eac6a1aea528', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129574); +INSERT INTO `lms_clx_system_log` VALUES ('1db65237-06e0-4830-8237-a01e2608b105', '1', '超级管理员', 'wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863014); +INSERT INTO `lms_clx_system_log` VALUES ('1dfaa0e2-d8a7-47fb-9bcc-e4116edd9e6a', '1', '超级管理员', 'wf/other/user/list', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863069); +INSERT INTO `lms_clx_system_log` VALUES ('1e0e97df-e595-456a-b64e-f7a340156fb4', '1', '超级管理员', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712111677); +INSERT INTO `lms_clx_system_log` VALUES ('20abfcc1-a362-48b9-8bd5-9996304d52e5', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113064); +INSERT INTO `lms_clx_system_log` VALUES ('218f4820-a6f3-4718-a9c0-735eef9940ca', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115767); +INSERT INTO `lms_clx_system_log` VALUES ('21a88f65-fb1e-4c8b-abfb-f2abef92678d', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127228); +INSERT INTO `lms_clx_system_log` VALUES ('21ac1480-29e4-4f27-b5a5-adf40abf6d9d', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/delete', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113136); +INSERT INTO `lms_clx_system_log` VALUES ('2214a355-c0ee-4e10-94ae-83ec0507220a', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114822); +INSERT INTO `lms_clx_system_log` VALUES ('2290c824-cc2c-4b15-b8f2-091c922eb98a', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124879); +INSERT INTO `lms_clx_system_log` VALUES ('238837e1-48a0-4e2c-ab57-75d05cd0d521', '1', '超级管理员', 'wf/other/assignment_handler', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863248); +INSERT INTO `lms_clx_system_log` VALUES ('24558167-299a-4b42-8ac5-2493eab1511a', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127420); +INSERT INTO `lms_clx_system_log` VALUES ('24954f23-75df-48e1-8420-066ea231c899', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125575); +INSERT INTO `lms_clx_system_log` VALUES ('252556b3-bd72-4142-9072-70d80bc04037', '1', '超级管理员', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110820); +INSERT INTO `lms_clx_system_log` VALUES ('25b34dd9-56a3-41d2-b21e-2c0203cf58ae', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129574); +INSERT INTO `lms_clx_system_log` VALUES ('26cea281-c197-4f3e-9634-055919d3b34c', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/assignment_handler', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113304); +INSERT INTO `lms_clx_system_log` VALUES ('27682e5f-3c6e-4af0-9222-be5adfa6f720', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113083); +INSERT INTO `lms_clx_system_log` VALUES ('27acaeec-4990-4181-85f4-168a26742b6f', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127423); +INSERT INTO `lms_clx_system_log` VALUES ('27d05a0b-5242-4a16-95b8-4f50d81359ab', '1', '超级管理员', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712106177); +INSERT INTO `lms_clx_system_log` VALUES ('2898f099-8ae0-455e-b034-a9c4ae551583', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124982); +INSERT INTO `lms_clx_system_log` VALUES ('2927274c-6e47-42bb-bef6-a1a6babf480a', '1', '超级管理员', '/adminapi/wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712111694); +INSERT INTO `lms_clx_system_log` VALUES ('2ab81676-2d7f-43b3-a123-4af9a88cd97d', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/done/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127828); +INSERT INTO `lms_clx_system_log` VALUES ('2c4a28eb-dcdd-4609-85d0-27337e2b4de0', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/user/info', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113289); +INSERT INTO `lms_clx_system_log` VALUES ('2cc82675-3a67-43ed-ae1d-b5e8ae897652', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122851); +INSERT INTO `lms_clx_system_log` VALUES ('2fc7b342-0c53-426f-bad7-97c4223fbc9e', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/form/option', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113318); +INSERT INTO `lms_clx_system_log` VALUES ('30d87dd6-4a91-4bde-8369-bd1fd77e9722', '1', '超级管理员', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712111677); +INSERT INTO `lms_clx_system_log` VALUES ('3133fd3e-b037-4fcf-ac3b-bfc5ad498bd2', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127258); +INSERT INTO `lms_clx_system_log` VALUES ('3317955f-4a51-40a6-95a3-6c346be4faab', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127407); +INSERT INTO `lms_clx_system_log` VALUES ('33cf1cd6-1a97-4d0e-9dc7-36b6788e85dc', '1', '超级管理员', 'wf/other/user/list', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863039); +INSERT INTO `lms_clx_system_log` VALUES ('35c93089-8bd5-4a2b-a3c3-d12b63ac9a26', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/user/list', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115744); +INSERT INTO `lms_clx_system_log` VALUES ('36ab4b35-5498-4fb2-bf07-232b328c4659', '1', '超级管理员', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712111681); +INSERT INTO `lms_clx_system_log` VALUES ('37528835-f85b-4fba-8c25-101c21943801', '1', '超级管理员', 'wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863267); +INSERT INTO `lms_clx_system_log` VALUES ('37fa0cf6-6d2b-4ccd-a984-6d5f21f3b747', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115617); +INSERT INTO `lms_clx_system_log` VALUES ('385deb6f-6aff-4cfe-bde6-3b13b4300d59', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/done/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113114); +INSERT INTO `lms_clx_system_log` VALUES ('387d8d83-b618-4bb4-80f6-2febbb326e6a', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/user/info', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115744); +INSERT INTO `lms_clx_system_log` VALUES ('39137074-2f5f-4166-8d7d-2ea7168a0999', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712121836); +INSERT INTO `lms_clx_system_log` VALUES ('397cd70d-7b62-4e48-839d-49591bc55f56', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712121836); +INSERT INTO `lms_clx_system_log` VALUES ('39a0c535-1706-46f5-a1c2-70e694c13aaa', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113069); +INSERT INTO `lms_clx_system_log` VALUES ('3c0bda8c-3392-4598-9114-24079a8aa739', '1', '超级管理员', 'wf/other/assignment_handler', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863239); +INSERT INTO `lms_clx_system_log` VALUES ('3c81a122-0a4b-4f52-be66-9970b33999ea', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125265); +INSERT INTO `lms_clx_system_log` VALUES ('3de66848-8588-4254-a563-c0f6357ace38', '1', '超级管理员', 'wf/designer/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863023); +INSERT INTO `lms_clx_system_log` VALUES ('3f5a34e7-44b1-4cf2-9e1f-b63bbebf23f9', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127413); +INSERT INTO `lms_clx_system_log` VALUES ('3f82eff3-20fa-4a3e-8c9d-b0c089f72ba6', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125530); +INSERT INTO `lms_clx_system_log` VALUES ('3f8b742c-2489-484f-b6ed-9176c38159b0', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127924); +INSERT INTO `lms_clx_system_log` VALUES ('405c6f18-019b-4dc7-b5fa-214dbcdd0732', '1', '超级管理员', 'wf/process_define/start_and_execute', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863311); +INSERT INTO `lms_clx_system_log` VALUES ('413e4c8b-3b7b-4157-948c-90bd73e38fe4', '1', '超级管理员', 'wf/other/form/option', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863281); +INSERT INTO `lms_clx_system_log` VALUES ('4205b3ec-098e-4c2f-a613-3ed5c57c7dc9', '1', '超级管理员', 'wf/other/form/option', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863271); +INSERT INTO `lms_clx_system_log` VALUES ('43b03247-aae3-48ea-b0ce-6d4702132fd4', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/user/list', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113304); +INSERT INTO `lms_clx_system_log` VALUES ('43e456f9-4718-4fbb-92ce-cac34c6cc966', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712123897); +INSERT INTO `lms_clx_system_log` VALUES ('4410ea18-09fd-4878-a4dd-9aeabba4f542', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127437); +INSERT INTO `lms_clx_system_log` VALUES ('44c47d2c-bd6a-4658-8131-4870d9afff74', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122839); +INSERT INTO `lms_clx_system_log` VALUES ('44cd21ad-97e2-48c2-817b-7852c0c74fe1', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127924); +INSERT INTO `lms_clx_system_log` VALUES ('45059132-89e3-4ab5-a80b-b8c6508dc83a', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/delete', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127267); +INSERT INTO `lms_clx_system_log` VALUES ('4538c141-d968-4cc6-95b2-cbccc05f0c05', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113106); +INSERT INTO `lms_clx_system_log` VALUES ('453d3074-5eb3-4397-9598-1759d1036f6f', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127828); +INSERT INTO `lms_clx_system_log` VALUES ('463bc85d-cd0d-45fb-ab90-face62082973', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114822); +INSERT INTO `lms_clx_system_log` VALUES ('4670c049-f4b2-485c-a2e5-99180e8d29e5', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127228); +INSERT INTO `lms_clx_system_log` VALUES ('4792984f-9f07-4e8a-b8e8-311e0c6401c5', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/approval_record', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125926); +INSERT INTO `lms_clx_system_log` VALUES ('4929b6e5-6274-42fc-8b13-4cdc816d4284', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122837); +INSERT INTO `lms_clx_system_log` VALUES ('49698cd4-beb2-43f6-aa23-4f4c97f54387', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125475); +INSERT INTO `lms_clx_system_log` VALUES ('49cb647a-890c-4348-8319-c785b5d7ae3c', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125926); +INSERT INTO `lms_clx_system_log` VALUES ('4ac9b0f1-476c-41cb-b9c0-da609688f94d', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113086); +INSERT INTO `lms_clx_system_log` VALUES ('4bdf2180-84c6-4824-848d-f2522f741987', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125013); +INSERT INTO `lms_clx_system_log` VALUES ('4bea03d3-d865-480c-9203-a2c20c56a0aa', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114822); +INSERT INTO `lms_clx_system_log` VALUES ('4c53638e-2508-431c-9e22-42e694b4e6f7', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/form/option', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113313); +INSERT INTO `lms_clx_system_log` VALUES ('4c7fdc2a-0c9e-4d98-9f42-37559c22d4ed', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127417); +INSERT INTO `lms_clx_system_log` VALUES ('4c983c24-1f85-4ae4-b195-f5c5c101ef92', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127706); +INSERT INTO `lms_clx_system_log` VALUES ('4d24bda3-ecc2-4dde-81db-f5d62c192b0d', '1', '超级管理员', 'wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863212); +INSERT INTO `lms_clx_system_log` VALUES ('4e12005d-5245-48ec-8c97-182f2d120a3c', '1', '超级管理员', 'wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863316); +INSERT INTO `lms_clx_system_log` VALUES ('4e211b99-c07f-4f6a-bc45-6eb4aa303a58', '1', '超级管理员', 'wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863289); +INSERT INTO `lms_clx_system_log` VALUES ('4f1fade9-3d05-474f-9f60-465fc05a5a0e', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127421); +INSERT INTO `lms_clx_system_log` VALUES ('52d63ba3-9bf3-4273-b341-5f4eec9ac398', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/deploy', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115763); +INSERT INTO `lms_clx_system_log` VALUES ('533dade0-3fc4-4308-a11c-40e673f7eb86', '1', '超级管理员', 'wf/other/user/list', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863239); +INSERT INTO `lms_clx_system_log` VALUES ('53b77121-ffaf-4803-aa14-249ceb6989d3', '1', '超级管理员', 'wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863312); +INSERT INTO `lms_clx_system_log` VALUES ('541fdf19-3c0a-4f12-a515-ca678b75e07f', '1', '超级管理员', 'wf/other/user/list', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863045); +INSERT INTO `lms_clx_system_log` VALUES ('543eab6a-835f-4f32-a4e1-280a20366c06', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127237); +INSERT INTO `lms_clx_system_log` VALUES ('5469482c-a048-43ac-bd52-1cc6d3377791', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/delete', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113131); +INSERT INTO `lms_clx_system_log` VALUES ('54bbf32a-9161-4088-8971-29106c637124', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127235); +INSERT INTO `lms_clx_system_log` VALUES ('550bafa7-2516-4cfd-bf2a-5ae07713c4d5', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122852); +INSERT INTO `lms_clx_system_log` VALUES ('554a4137-71f4-4a61-9822-fcc08d1e21eb', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114958); +INSERT INTO `lms_clx_system_log` VALUES ('5607ceb6-2cb8-4610-9189-e86bf130de36', '1', '超级管理员', 'wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863211); +INSERT INTO `lms_clx_system_log` VALUES ('57760602-cfe0-42ae-ba04-9c6b5339d236', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114825); +INSERT INTO `lms_clx_system_log` VALUES ('58017729-3141-47f7-8b91-0bb2a383713c', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127706); +INSERT INTO `lms_clx_system_log` VALUES ('585174a7-78be-4bf7-8247-331eb5e51f3f', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124040); +INSERT INTO `lms_clx_system_log` VALUES ('58a84063-8603-4113-a26e-763ffa923768', '1', '超级管理员', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110334); +INSERT INTO `lms_clx_system_log` VALUES ('590072c6-d555-4740-8bc0-f6ba618565f6', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/done/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127924); +INSERT INTO `lms_clx_system_log` VALUES ('5978c4ac-3366-4c00-9e2d-53dd37c92916', '1', '超级管理员', 'wf/designer/update_define', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863246); +INSERT INTO `lms_clx_system_log` VALUES ('5b504a45-2d26-4d4c-8312-98eb29116b42', '1', '超级管理员', '/adminapi/wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716388677); +INSERT INTO `lms_clx_system_log` VALUES ('5b756940-3436-4f98-a603-13dc12cc69a1', '1', '超级管理员', 'wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863212); +INSERT INTO `lms_clx_system_log` VALUES ('5b793764-084c-411e-bf64-e71561005ced', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/deploy', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127971); +INSERT INTO `lms_clx_system_log` VALUES ('5b94ede4-ced3-4215-b67d-cb2c4b2a9dc8', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/cc_list', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127924); +INSERT INTO `lms_clx_system_log` VALUES ('5be76141-a049-4ec3-a886-d749d8d50ff0', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125246); +INSERT INTO `lms_clx_system_log` VALUES ('5d71b2da-2734-43aa-9ca7-2e8a687aee89', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/done/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712121836); +INSERT INTO `lms_clx_system_log` VALUES ('5f7f0121-ec16-4674-83e5-d5763378bf6a', '1', '超级管理员', 'wf/other/form/option', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863269); +INSERT INTO `lms_clx_system_log` VALUES ('5fedc27f-5e8e-4d8b-955a-5839f30785f9', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712123414); +INSERT INTO `lms_clx_system_log` VALUES ('6056c203-2279-4c46-9f7d-2964de5a5bde', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/start_and_execute', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122829); +INSERT INTO `lms_clx_system_log` VALUES ('606d6024-ef8d-4016-8d10-da7265729155', '1', '超级管理员', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712111688); +INSERT INTO `lms_clx_system_log` VALUES ('62397418-98a8-4613-9fce-8aa8fe17ff24', '1', '超级管理员', 'wf/other/user/info', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863239); +INSERT INTO `lms_clx_system_log` VALUES ('628ae552-2839-45f8-9f30-a00ea2bb4603', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712126021); +INSERT INTO `lms_clx_system_log` VALUES ('62e8caeb-41a9-47ea-8ae2-b9ee7d527775', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712121836); +INSERT INTO `lms_clx_system_log` VALUES ('63515447-2ff7-4c71-90de-ffb64d557e52', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/form/option', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113319); +INSERT INTO `lms_clx_system_log` VALUES ('640108f0-63d2-4e80-9d48-e9763ee3d274', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125265); +INSERT INTO `lms_clx_system_log` VALUES ('657d104c-4817-4639-933d-4a2a87809b8c', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115712); +INSERT INTO `lms_clx_system_log` VALUES ('66acfddb-e7ad-4cda-b4c3-ae104e754fa2', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/set_status', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129577); +INSERT INTO `lms_clx_system_log` VALUES ('66f5c003-5b7e-41ff-8bc0-ff8f8609925b', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114822); +INSERT INTO `lms_clx_system_log` VALUES ('67126591-24f6-4745-a898-76ce2a2f5512', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/user/info', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113282); +INSERT INTO `lms_clx_system_log` VALUES ('68332943-0400-4e56-934b-1d71f4154e91', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127706); +INSERT INTO `lms_clx_system_log` VALUES ('683d684f-a6aa-4130-a3cc-228d2c02ed8b', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124982); +INSERT INTO `lms_clx_system_log` VALUES ('68f2488f-61af-43db-90c5-f5a74763f1d9', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125475); +INSERT INTO `lms_clx_system_log` VALUES ('69fd9a22-a8a3-4516-a73e-fb087209c545', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/set_status', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113128); +INSERT INTO `lms_clx_system_log` VALUES ('6b9e98f3-9c91-4039-8abd-933b43b5bf8d', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125530); +INSERT INTO `lms_clx_system_log` VALUES ('6cda9506-79af-4a71-a822-af374c37c2f9', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124713); +INSERT INTO `lms_clx_system_log` VALUES ('6cec8a3d-85c0-4331-bb19-a33ff964f5f3', '1', '超级管理员', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1711952853); +INSERT INTO `lms_clx_system_log` VALUES ('6e2f92b9-ead0-409b-b431-0b8a6955c3f5', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127290); +INSERT INTO `lms_clx_system_log` VALUES ('6ee2012a-51cb-4696-868e-0463d9a24e90', '1', '超级管理员', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712111689); +INSERT INTO `lms_clx_system_log` VALUES ('6f544f30-5dfd-419f-a130-f7a9fcaec11d', '1', '超级管理员', 'wf/other/user/info', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863277); +INSERT INTO `lms_clx_system_log` VALUES ('6fce496b-cc94-4881-ab88-f27948687986', '1', '超级管理员', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110372); +INSERT INTO `lms_clx_system_log` VALUES ('6ffb8eb6-1bd7-4929-b629-f840d7f39d4a', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124145); +INSERT INTO `lms_clx_system_log` VALUES ('70710dec-f685-4fb7-ba92-dcd40e30e4e5', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127419); +INSERT INTO `lms_clx_system_log` VALUES ('71368ef1-961e-4bf1-b208-2ee299fdddec', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127446); +INSERT INTO `lms_clx_system_log` VALUES ('7160d828-540c-4b4f-93e3-7b7b8fb5cf79', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122843); +INSERT INTO `lms_clx_system_log` VALUES ('71b9adf6-be58-4607-9d57-aa9f71f1ad51', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127706); +INSERT INTO `lms_clx_system_log` VALUES ('72bf13ba-739a-4939-9284-3ac29b9153f2', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114955); +INSERT INTO `lms_clx_system_log` VALUES ('72ce2798-5bd4-4fc0-9335-ad8abeff306a', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113082); +INSERT INTO `lms_clx_system_log` VALUES ('732860ac-20a5-4428-86f0-105825097a49', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/update_define', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115552); +INSERT INTO `lms_clx_system_log` VALUES ('733de59c-3d2c-43b2-8fdc-96e2c9dd66df', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127410); +INSERT INTO `lms_clx_system_log` VALUES ('736f1bb5-e7a1-4ca9-be34-c90b6c921857', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127828); +INSERT INTO `lms_clx_system_log` VALUES ('74a4de5e-106a-4e38-9a53-c5631ef78aae', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127232); +INSERT INTO `lms_clx_system_log` VALUES ('75597806-2e4c-4d31-8082-3244d25e6873', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124879); +INSERT INTO `lms_clx_system_log` VALUES ('75d0fe47-a2d6-41af-a7ae-6e98f2cc1287', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/done/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127706); +INSERT INTO `lms_clx_system_log` VALUES ('75e9d313-aeec-44ab-9c0d-9b6792ec9cea', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124847); +INSERT INTO `lms_clx_system_log` VALUES ('7600e3ad-0cdd-4458-a28a-798244f41f61', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/cc_list', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127424); +INSERT INTO `lms_clx_system_log` VALUES ('76af0270-2f51-489e-b6d4-128625499dca', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/cc_list', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127706); +INSERT INTO `lms_clx_system_log` VALUES ('76f3a69c-570b-44b1-91f2-850d5636204c', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122843); +INSERT INTO `lms_clx_system_log` VALUES ('772e2295-2c9e-446c-9aa3-64a225672a8f', '1', '超级管理员', 'wf/process_task/done/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863017); +INSERT INTO `lms_clx_system_log` VALUES ('7739fd97-8904-45a7-bec9-4059a67d3fec', '1', '超级管理员', 'wf/other/assignment_handler', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863277); +INSERT INTO `lms_clx_system_log` VALUES ('78e663d2-7f34-481b-82b7-5393129d246e', '1', '超级管理员', 'wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863020); +INSERT INTO `lms_clx_system_log` VALUES ('795a5c2a-78ed-48a7-8394-b5b6bd0d0af1', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/set_status', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113128); +INSERT INTO `lms_clx_system_log` VALUES ('79bedca0-6204-4deb-98ee-b15a1a13be54', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/done/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122830); +INSERT INTO `lms_clx_system_log` VALUES ('7abc3c2c-8652-466b-8413-0fd26971af3c', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/form/option', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113339); +INSERT INTO `lms_clx_system_log` VALUES ('7b489953-d42c-48eb-bdf2-91e68c973ec5', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129574); +INSERT INTO `lms_clx_system_log` VALUES ('7b89973d-603e-4a6e-ae5c-471098f001d8', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/assignment_handler', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113282); +INSERT INTO `lms_clx_system_log` VALUES ('7ba84243-60b4-4ef7-b64e-aecfea7b9b34', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/update_define', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115759); +INSERT INTO `lms_clx_system_log` VALUES ('7bc357c3-406b-43e6-95a3-9f74aae6dc72', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712121836); +INSERT INTO `lms_clx_system_log` VALUES ('7d4371f0-097d-42c5-8985-8b74632d303e', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/form/option', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113310); +INSERT INTO `lms_clx_system_log` VALUES ('7ef3a86a-d1b5-4a0c-9652-1f2cc7dac8e5', '1', '超级管理员', 'wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863018); +INSERT INTO `lms_clx_system_log` VALUES ('7fae3d3d-bf92-48c8-91d4-53e75dc87829', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114955); +INSERT INTO `lms_clx_system_log` VALUES ('8059c6e0-2f1d-46e4-b032-b388fcd03696', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712126021); +INSERT INTO `lms_clx_system_log` VALUES ('8164eb09-d096-4633-bf3d-92cb7aa7ba42', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712121843); +INSERT INTO `lms_clx_system_log` VALUES ('82fdd5a9-16a5-43a6-bb43-6edbd37e2ebc', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127828); +INSERT INTO `lms_clx_system_log` VALUES ('83020176-c3f1-4a2e-81c1-7441cb0bcbaa', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127706); +INSERT INTO `lms_clx_system_log` VALUES ('834935d7-4da2-4da2-836f-e7444ba1ca3e', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127284); +INSERT INTO `lms_clx_system_log` VALUES ('83600a7c-a309-4702-b31d-d43d470c792f', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124032); +INSERT INTO `lms_clx_system_log` VALUES ('842a0d0b-c534-4403-99b7-196a2145ec3a', '1', '超级管理员', 'wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863209); +INSERT INTO `lms_clx_system_log` VALUES ('845ee117-1e5f-4d2d-bfbd-0034df667f76', '1', '超级管理员', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1711952960); +INSERT INTO `lms_clx_system_log` VALUES ('86483875-728d-40c0-ba33-1b544f403c16', '1', '超级管理员', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110343); +INSERT INTO `lms_clx_system_log` VALUES ('87f207c0-6db8-4e41-bbb1-ae902ccde2f7', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127415); +INSERT INTO `lms_clx_system_log` VALUES ('887136c7-2f88-4207-b844-a1c9683e9afa', '1', '超级管理员', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712111686); +INSERT INTO `lms_clx_system_log` VALUES ('88c527f6-7280-4121-9171-3f1501fd1023', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127418); +INSERT INTO `lms_clx_system_log` VALUES ('8a925738-8847-4826-a51b-940c976fe8c8', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712123792); +INSERT INTO `lms_clx_system_log` VALUES ('8bf72124-d527-425d-9e62-eb4b5d2d0dab', '1', '超级管理员', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110233); +INSERT INTO `lms_clx_system_log` VALUES ('8c29a93b-d116-4de5-9b5e-a68b3ec6351a', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127706); +INSERT INTO `lms_clx_system_log` VALUES ('8c4b1130-ff20-46aa-bc45-de3df387c7b5', '1', '超级管理员', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110624); +INSERT INTO `lms_clx_system_log` VALUES ('8c657d60-9f3d-484a-b51b-32e2965f4dc8', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/delete', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113228); +INSERT INTO `lms_clx_system_log` VALUES ('8cd38ca9-5112-4f36-8015-6e5a0af204a5', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113119); +INSERT INTO `lms_clx_system_log` VALUES ('8d207a62-0e17-4093-bbb8-84b531ab6ec5', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124318); +INSERT INTO `lms_clx_system_log` VALUES ('8e3e8bfc-e75e-4258-8946-21a8708c76fb', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122841); +INSERT INTO `lms_clx_system_log` VALUES ('8e7b31df-f95d-400c-95df-42ed07e69e03', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122837); +INSERT INTO `lms_clx_system_log` VALUES ('8ed84a95-97ae-414a-956a-84f2cdec1f46', '1', '超级管理员', '/adminapi/wf/process_instance/cc_list', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110291); +INSERT INTO `lms_clx_system_log` VALUES ('927d1642-58f0-4414-8c56-0c5845fdb6b9', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127828); +INSERT INTO `lms_clx_system_log` VALUES ('92837791-83e1-459b-a02d-c7b89e34ce27', '1', '超级管理员', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712111685); +INSERT INTO `lms_clx_system_log` VALUES ('931fd4fa-e774-425b-9822-8cb5b79d01eb', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712123780); +INSERT INTO `lms_clx_system_log` VALUES ('93493dfd-7ffe-4008-a9a4-39a2c1882149', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/user/list', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113290); +INSERT INTO `lms_clx_system_log` VALUES ('958fb51f-f9d1-4d81-afc5-c6df40497c39', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114822); +INSERT INTO `lms_clx_system_log` VALUES ('95a65049-3fbb-41e3-ad5f-89a9d3ee8cb8', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/done/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114822); +INSERT INTO `lms_clx_system_log` VALUES ('96381d56-41ec-47a5-8d88-49c6e1dd800b', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113087); +INSERT INTO `lms_clx_system_log` VALUES ('96d6b3da-5c75-4485-9c1c-a87a1363a38b', '1', '超级管理员', 'wf/other/user/info', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863248); +INSERT INTO `lms_clx_system_log` VALUES ('97c66d10-cda6-42bb-b6ed-63ff0838a084', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127706); +INSERT INTO `lms_clx_system_log` VALUES ('9841d1fa-a259-4ba7-8c7a-e2198fa79f5a', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124847); +INSERT INTO `lms_clx_system_log` VALUES ('9842c1ff-ce5c-48d5-bd46-0a7b2b5e61f4', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127232); +INSERT INTO `lms_clx_system_log` VALUES ('9990c4ee-3a95-4fc8-b906-bf5a5ad8df31', '1', '超级管理员', 'wf/other/user/list', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863248); +INSERT INTO `lms_clx_system_log` VALUES ('9a81d02e-68c1-40e6-bf7a-2ddb1ffa8d87', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127407); +INSERT INTO `lms_clx_system_log` VALUES ('9abd7a60-30c2-4d87-8458-1f260b40b5c4', '1', '超级管理员', '/adminapi/wf/process_task/done/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110317); +INSERT INTO `lms_clx_system_log` VALUES ('9b7dd78e-6528-4ea7-9e5f-49c025cdbb90', '1', '超级管理员', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110824); +INSERT INTO `lms_clx_system_log` VALUES ('9bc39aa0-89e9-4b6e-a635-8f169b56057d', '1', '超级管理员', 'wf/other/assignment_handler', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863039); +INSERT INTO `lms_clx_system_log` VALUES ('9bfd5900-5d06-4fcc-88e9-ec3af3f0e394', '1', '超级管理员', 'wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863021); +INSERT INTO `lms_clx_system_log` VALUES ('9c33536f-7e28-464c-8db3-7e9da480c73e', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/assignment_handler', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113289); +INSERT INTO `lms_clx_system_log` VALUES ('9c4ff57a-4214-4963-9893-197bd3e2046f', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/done/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114955); +INSERT INTO `lms_clx_system_log` VALUES ('9ed39f44-ee88-46cd-bb83-f8a70cd63c1d', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125467); +INSERT INTO `lms_clx_system_log` VALUES ('a14154cf-10f3-46f7-8aa1-02a8e0d6a9d1', '1', '超级管理员', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110322); +INSERT INTO `lms_clx_system_log` VALUES ('a349de8f-c87d-407d-b1bd-0f998dc9c577', '1', '超级管理员', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712111690); +INSERT INTO `lms_clx_system_log` VALUES ('a3c9be07-6ede-4dd9-b1cc-10a65666a165', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/set_status', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129578); +INSERT INTO `lms_clx_system_log` VALUES ('a45ae04c-9c56-4f8d-ab28-64c099a85262', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114955); +INSERT INTO `lms_clx_system_log` VALUES ('a620febc-8c06-487c-ab26-e3ff59f99887', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127272); +INSERT INTO `lms_clx_system_log` VALUES ('a6312bd0-ad15-4b63-aec6-f89b456d4089', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127924); +INSERT INTO `lms_clx_system_log` VALUES ('a780a293-f8d2-4684-aded-d64044ff173e', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129574); +INSERT INTO `lms_clx_system_log` VALUES ('a79ce09f-25b6-4ebb-a473-29dc594e7d53', '1', '超级管理员', 'wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863320); +INSERT INTO `lms_clx_system_log` VALUES ('a8ea8dc0-d366-4839-9546-2a84733b8c20', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129574); +INSERT INTO `lms_clx_system_log` VALUES ('a9786961-8dee-45d0-bdda-09c92880d573', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124211); +INSERT INTO `lms_clx_system_log` VALUES ('abbf2c3f-35e2-4925-bd0d-804f90cc7f14', '1', '超级管理员', 'wf/other/user/info', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863070); +INSERT INTO `lms_clx_system_log` VALUES ('abdd188f-bbc8-494b-bfcd-49b635d0c064', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712123414); +INSERT INTO `lms_clx_system_log` VALUES ('ac2e9f6b-282d-47f6-8be9-1ad78a5090df', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129574); +INSERT INTO `lms_clx_system_log` VALUES ('ac89adc3-121b-4f3d-ba61-0b2d8c6b91ab', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/user/list', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113282); +INSERT INTO `lms_clx_system_log` VALUES ('ace37cd1-4cb9-4631-8a88-bf72b395276a', '1', '超级管理员', '/adminapi/wf/process_define/favorite/setting', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110326); +INSERT INTO `lms_clx_system_log` VALUES ('acfe9316-d266-4836-9967-de1faf2f301a', '1', '超级管理员', 'wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863025); +INSERT INTO `lms_clx_system_log` VALUES ('ad310b29-e655-4c85-9ce8-bf92c607c091', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/user/list', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113289); +INSERT INTO `lms_clx_system_log` VALUES ('aee05447-1999-4f0e-9990-220f1488fefb', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113257); +INSERT INTO `lms_clx_system_log` VALUES ('aef098c0-7b6c-4ac9-9846-025a7e6ae49d', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/assignment_handler', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115744); +INSERT INTO `lms_clx_system_log` VALUES ('af74effe-7f7f-4b81-b572-28e38cdc87f5', '1', '超级管理员', 'wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863319); +INSERT INTO `lms_clx_system_log` VALUES ('b070d5f1-6a95-4c8e-8768-953a1395ac7d', '1', '超级管理员', 'wf/designer/update_define', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863279); +INSERT INTO `lms_clx_system_log` VALUES ('b1531ab4-f7de-4b4a-915c-53b9f002e297', '1', '超级管理员', '/adminapi/wf/designer/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110424); +INSERT INTO `lms_clx_system_log` VALUES ('b2063f8b-d4fd-4a08-8f50-cf1507317308', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127924); +INSERT INTO `lms_clx_system_log` VALUES ('b2220d77-0d4d-4a4a-9426-6aca464bd9dd', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124713); +INSERT INTO `lms_clx_system_log` VALUES ('b2727123-8a15-4ba5-bb80-77ac35eab7e9', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129574); +INSERT INTO `lms_clx_system_log` VALUES ('b28a51cd-5e7f-4870-91ad-58b08ee6cbc6', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125246); +INSERT INTO `lms_clx_system_log` VALUES ('b2e739c7-f1db-44fb-8af6-2a250ba722fa', '1', '超级管理员', 'wf/designer/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863211); +INSERT INTO `lms_clx_system_log` VALUES ('b31621a9-c29e-4caa-b790-f56a18568209', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712121836); +INSERT INTO `lms_clx_system_log` VALUES ('b4415cd2-c9f2-4b07-8cd4-e092e1d2f82b', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127976); +INSERT INTO `lms_clx_system_log` VALUES ('b4883bb7-5dbe-45a3-aac3-faafc40d4571', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127706); +INSERT INTO `lms_clx_system_log` VALUES ('b65be77e-b98a-4e3f-b35e-e98272c8e49c', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115769); +INSERT INTO `lms_clx_system_log` VALUES ('b6be994c-eb35-49c3-9a15-ec936f783d7c', '1', '超级管理员', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712111677); +INSERT INTO `lms_clx_system_log` VALUES ('b8a52f97-9dbc-4450-a7c6-373920b64363', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127235); +INSERT INTO `lms_clx_system_log` VALUES ('b8ef6558-4e98-44c9-b3d0-9052feb97993', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127416); +INSERT INTO `lms_clx_system_log` VALUES ('bab5365f-6d70-4cdb-85fe-78bd01321fe0', '1', '超级管理员', 'wf/other/user/info', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863251); +INSERT INTO `lms_clx_system_log` VALUES ('bd2f0a0b-a6aa-47d0-82ed-4acb3e55ee05', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127413); +INSERT INTO `lms_clx_system_log` VALUES ('be4011c8-ad6e-4084-a4f5-2f5ecb0f3d98', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124465); +INSERT INTO `lms_clx_system_log` VALUES ('bef6a1f6-3263-4c56-afac-9229d0449fa4', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127828); +INSERT INTO `lms_clx_system_log` VALUES ('c01b5a05-2ab4-46c4-a365-a40c95902785', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/cc_list', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127828); +INSERT INTO `lms_clx_system_log` VALUES ('c1a10762-e6c2-49f5-b268-8136407bb804', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127418); +INSERT INTO `lms_clx_system_log` VALUES ('c22ea9a9-bd59-4df5-96c9-fe148517fdd3', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113075); +INSERT INTO `lms_clx_system_log` VALUES ('c3ebd82d-396b-49b2-9acf-5aa856db90bb', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124032); +INSERT INTO `lms_clx_system_log` VALUES ('c70a16c9-618b-457a-a0e3-d7610c2a7f3d', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/form/option', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115752); +INSERT INTO `lms_clx_system_log` VALUES ('c96285ca-b36a-475b-8752-ee501e858e90', '1', '超级管理员', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110417); +INSERT INTO `lms_clx_system_log` VALUES ('cd258f0c-75a9-4546-95f5-f7fa07c53654', '1', '超级管理员', 'wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863296); +INSERT INTO `lms_clx_system_log` VALUES ('cdf9e3dd-087d-4648-a7a7-5e432a4797a9', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127706); +INSERT INTO `lms_clx_system_log` VALUES ('ce82e243-3c66-46c1-9b7b-fc98a00891c0', '1', '超级管理员', 'wf/other/user/info', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863040); +INSERT INTO `lms_clx_system_log` VALUES ('cf480a42-d29f-4f30-a6cf-b35939717fe5', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124145); +INSERT INTO `lms_clx_system_log` VALUES ('cfd32802-700b-4588-a175-0dce446bd50f', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/favorite/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114955); +INSERT INTO `lms_clx_system_log` VALUES ('d06c4508-4090-44f6-92ed-c433ba2b2114', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124211); +INSERT INTO `lms_clx_system_log` VALUES ('d0c62805-0fe1-49c8-9d3b-aec0185e0944', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113265); +INSERT INTO `lms_clx_system_log` VALUES ('d1d450bc-7172-460a-9ac5-6e964b5b6e55', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127828); +INSERT INTO `lms_clx_system_log` VALUES ('d2591b63-496d-4328-851f-31fd11a7550b', '1', '超级管理员', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110822); +INSERT INTO `lms_clx_system_log` VALUES ('d44e6985-2f77-43f5-8b21-58eaff08a6c2', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115710); +INSERT INTO `lms_clx_system_log` VALUES ('d461c164-ea56-42a7-9203-fc688231f9af', '12b440e6-0e71-48f2-9926-509bc4135ab8', '李明', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113016); +INSERT INTO `lms_clx_system_log` VALUES ('d5411048-a2ca-439f-8739-65ed4130e5ce', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129574); +INSERT INTO `lms_clx_system_log` VALUES ('d577b3d9-587e-43c7-9249-c349d73f2c2c', '1', '超级管理员', 'wf/other/assignment_handler', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863069); +INSERT INTO `lms_clx_system_log` VALUES ('d624e30d-f52c-4f92-8c8a-89bdc5c02c6c', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/delete', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113231); +INSERT INTO `lms_clx_system_log` VALUES ('d6937766-3d08-464d-b733-6539700b1685', '1', '超级管理员', 'wf/other/user/list', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863251); +INSERT INTO `lms_clx_system_log` VALUES ('d7d6271c-ac22-47ff-b95e-2fd94dc3f41c', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/cc_list', '未知', 'adminapi', '127.0.0.1', 'admin', 1712129574); +INSERT INTO `lms_clx_system_log` VALUES ('d86e7b1b-4e90-49ed-a615-6f93d4d10df5', '1', '超级管理员', 'wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863212); +INSERT INTO `lms_clx_system_log` VALUES ('d8a88ebd-abd6-4285-9a3d-1bc81fbb21d9', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125013); +INSERT INTO `lms_clx_system_log` VALUES ('da15f18d-c844-4b15-ad2b-481cdaa7666a', '1', '超级管理员', 'wf/other/assignment_handler', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863045); +INSERT INTO `lms_clx_system_log` VALUES ('da495b7c-5c1d-4824-a4b9-ed439cebbb40', '1', '超级管理员', '/adminapi/wf/process_task/todo/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110309); +INSERT INTO `lms_clx_system_log` VALUES ('da82abed-3bed-4cd2-88c8-2e62c08c53c7', '1', '超级管理员', 'wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863292); +INSERT INTO `lms_clx_system_log` VALUES ('dac3053f-c963-4b4b-83bd-11c6dc607e0b', '1', '超级管理员', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1716388677); +INSERT INTO `lms_clx_system_log` VALUES ('dad0f877-db7b-4c98-b86d-266baf51b73d', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127828); +INSERT INTO `lms_clx_system_log` VALUES ('dbb14ef0-69a0-41a1-9132-5622030b4af6', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127263); +INSERT INTO `lms_clx_system_log` VALUES ('dc4072a1-fede-42f8-8d5f-419af36442ef', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/deploy', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127572); +INSERT INTO `lms_clx_system_log` VALUES ('dce872cb-3012-4643-9590-91f0658554e0', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712122841); +INSERT INTO `lms_clx_system_log` VALUES ('e054c227-282b-4906-9a39-dab277155714', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127828); +INSERT INTO `lms_clx_system_log` VALUES ('e101fcb7-8e8c-43b8-ac0f-a33e8cbed16c', '1', '超级管理员', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110821); +INSERT INTO `lms_clx_system_log` VALUES ('e45dcf88-696b-4b7f-b787-92af658fffd3', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127924); +INSERT INTO `lms_clx_system_log` VALUES ('e5651148-df69-439f-a0e5-e83c01fc3255', '1', '超级管理员', '/adminapi/wf/designer/deploy', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110421); +INSERT INTO `lms_clx_system_log` VALUES ('e5822bae-a21f-4eb2-8c48-75b88fc55e35', '1', '超级管理员', '/adminapi/wf/designer/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110333); +INSERT INTO `lms_clx_system_log` VALUES ('e67ee897-7153-4b53-892b-2d5e15cb7650', '1', '超级管理员', 'wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863214); +INSERT INTO `lms_clx_system_log` VALUES ('e8963162-93ae-4e15-a1af-49a4d39e81ca', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115719); +INSERT INTO `lms_clx_system_log` VALUES ('e93669b1-41e0-437a-95b8-141c6a109a9c', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/category/save', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127262); +INSERT INTO `lms_clx_system_log` VALUES ('e9375314-866f-4459-88c9-4e53779a5246', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113084); +INSERT INTO `lms_clx_system_log` VALUES ('ea99689c-a739-4f65-a2d6-325c257d69f6', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/user/info', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113304); +INSERT INTO `lms_clx_system_log` VALUES ('eaa94e86-12cc-435a-8738-69ec216b6a99', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127555); +INSERT INTO `lms_clx_system_log` VALUES ('eb1d9ef5-7e43-4f36-b129-882cc8aff464', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113087); +INSERT INTO `lms_clx_system_log` VALUES ('ec887a99-ddde-4f80-8193-48ab4057b81b', '1', '超级管理员', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110322); +INSERT INTO `lms_clx_system_log` VALUES ('ed4662a1-5219-40b7-8cc5-a9936607c8d7', '1', '超级管理员', 'wf/other/user/list', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863277); +INSERT INTO `lms_clx_system_log` VALUES ('edd974e2-c529-42b5-bd5a-af3326671af4', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113070); +INSERT INTO `lms_clx_system_log` VALUES ('f044a017-bb7d-4905-9010-8a6050ffe032', '1', '超级管理员', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712111688); +INSERT INTO `lms_clx_system_log` VALUES ('f0d49349-d000-48f7-b4e1-09ad1007e1b2', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/setting/permission', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114822); +INSERT INTO `lms_clx_system_log` VALUES ('f10b643d-16c0-496d-b952-666a3dade9bb', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127420); +INSERT INTO `lms_clx_system_log` VALUES ('f1c4b2dd-1145-411a-8ccc-9feab96556ae', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712121836); +INSERT INTO `lms_clx_system_log` VALUES ('f2a1fc26-f894-47b9-94fc-7b524ae8714a', '1', '超级管理员', 'wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863018); +INSERT INTO `lms_clx_system_log` VALUES ('f3a4c921-c555-4e36-af39-3338e69e149a', '1', '超级管理员', 'wf/process_instance/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863022); +INSERT INTO `lms_clx_system_log` VALUES ('f52f99c9-5954-4dc0-a855-f4591c19b356', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125881); +INSERT INTO `lms_clx_system_log` VALUES ('f5bc5596-7c26-4874-9bbe-9fe8d6238e6b', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712124465); +INSERT INTO `lms_clx_system_log` VALUES ('f6881b6a-e99b-4a69-8cdb-912f44dd433f', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712114822); +INSERT INTO `lms_clx_system_log` VALUES ('f7005e13-1f83-42fe-8c19-307a3eb94030', '1', '超级管理员', 'wf/process_task/done/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863212); +INSERT INTO `lms_clx_system_log` VALUES ('f81bb960-cb50-4eaf-8acc-284639f8185c', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/highlight', '未知', 'adminapi', '127.0.0.1', 'admin', 1712125445); +INSERT INTO `lms_clx_system_log` VALUES ('f84e7e57-3455-43da-a5ff-ce4af67d7812', '1', '超级管理员', '/adminapi/wf/process_define/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712111687); +INSERT INTO `lms_clx_system_log` VALUES ('f8815cef-375b-4ca9-82c2-6c4189a9138f', '1', '超级管理员', 'wf/designer/update_define', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863074); +INSERT INTO `lms_clx_system_log` VALUES ('f8d2f8f8-795c-4126-ab4d-cf5e49a83afa', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712127924); +INSERT INTO `lms_clx_system_log` VALUES ('f9271a9e-9964-48bf-874f-3007371b6fa2', '1', '超级管理员', 'wf/other/assignment_handler', '未知', 'adminapi', '127.0.0.1', 'admin', 1716863251); +INSERT INTO `lms_clx_system_log` VALUES ('fa328cf6-a4c7-4f5d-83bb-ffbab5d8add8', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/other/assignment_handler', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113290); +INSERT INTO `lms_clx_system_log` VALUES ('fa5a6c85-fcfd-4b31-a923-ff6a15e69d10', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113250); +INSERT INTO `lms_clx_system_log` VALUES ('faa5a4cc-64a3-4cff-bd61-f94bf0aea7fc', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/designer/update_define', '未知', 'adminapi', '127.0.0.1', 'admin', 1712115706); +INSERT INTO `lms_clx_system_log` VALUES ('fd22b88e-9a3d-4d19-b8da-cb1e3796e976', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_instance/detail', '未知', 'adminapi', '127.0.0.1', 'admin', 1712123780); +INSERT INTO `lms_clx_system_log` VALUES ('fea13319-2910-438b-adeb-5c2f8ea8b4a0', '1', '超级管理员', '/adminapi/wf/category/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1711952661); +INSERT INTO `lms_clx_system_log` VALUES ('fed4d3c0-9023-469e-8ff4-c1a58e9a72fa', '1', '超级管理员', '/adminapi/wf/category/select_tree', '未知', 'adminapi', '127.0.0.1', 'admin', 1712110820); +INSERT INTO `lms_clx_system_log` VALUES ('ff698550-ad60-4d09-8f70-f76b195895a9', '9ded8e78-b5f4-416f-beab-88a57bb84d41', '韩娜', '/adminapi/wf/process_define/page', '未知', 'adminapi', '127.0.0.1', 'admin', 1712113083); + +-- ---------------------------- +-- Table structure for lms_clx_system_menus +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_menus`; +CREATE TABLE `lms_clx_system_menus` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单ID', + `pid` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '-1' COMMENT '父级id', + `icon` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '图标', + `menu_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '按钮名', + `module` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '模块名', + `controller` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '控制器', + `action` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '方法名', + `api_url` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'api接口地址', + `methods` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '提交方式POST GET PUT DELETE', + `params` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '[]' COMMENT '参数', + `sort` tinyint(3) NOT NULL DEFAULT 1 COMMENT '排序', + `is_show` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '是否为隐藏菜单0=隐藏菜单,1=显示菜单', + `is_show_path` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否为隐藏菜单供前台使用', + `access` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '子管理员是否可用', + `menu_path` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '路由名称 前端使用', + `path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '路径', + `auth_type` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否为菜单 1菜单 2功能', + `header` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '顶部菜单标示', + `is_header` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否顶部菜单1是0否', + `unique_auth` varchar(150) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '前台唯一标识', + `mark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `delete_time` int(10) NULL DEFAULT NULL COMMENT '是否删除默认null', + PRIMARY KEY (`id`) USING BTREE, + INDEX `pid`(`pid`) USING BTREE, + INDEX `is_show`(`is_show`) USING BTREE, + INDEX `access`(`access`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '菜单表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_menus +-- ---------------------------- +INSERT INTO `lms_clx_system_menus` VALUES ('00f2cf25-61c2-4265-bab9-fc60569b40c6', '88cab609-0d7f-4394-a00e-ad24bd2c5ae5', 'layui-icon-face-smile', '修改', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-category-edit', '', 1696835200, 1696835200, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('03c5a106-ed45-42d2-9467-e3448ed369b3', '382c1114-59db-4594-b870-da3ce1a29c56', 'layui-icon-face-smile', '权限设置', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/setting/system_menus/index.html', '', 1, '', 0, 'setting-system-menus', '', 1693984082, 1694305159, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('08580779-066d-4b3b-9985-124df63625a4', '8b55c722-256a-40b3-ae27-1fdf99164094', '', '角色列表', '', '', '', 'setting/role/select', 'GET', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-role-select', '', 1694564002, 1694564002, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('0a4aff69-ad1d-42b2-8634-00dc3e52360b', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', 'layui-icon-face-smile', '组织管理', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'setting/org', '', 1, '', 0, 'setting-org', '', 1694310705, 1694310705, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('0db53e02-4829-4413-ad96-00ff34fbfd2d', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', '', '批量删除管理员', '', '', '', 'setting/admin/batch_remove', 'PUT', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-admin-batch_remove', '', 1710144809, 1710144809, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('0efa9244-f4b0-45a6-8781-cac2fff19abe', '6ee2d444-cd5f-45ca-a880-11976d16c210', 'layui-icon-face-smile', '我的抄送', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/wf/carbon/index.html', '', 1, '', 0, '', '', 1709533561, 1709533561, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('0f690e32-1e73-4190-9f87-e349f129451b', 'd65fe5a4-b207-4afa-8a88-7ca21dd7df7a', 'layui-icon-face-smile', '删除角色', 'admin', '', '', '', '', '[]', 102, 1, 1, 1, '', '', 3, '', 0, 'system-role-delete', '', 1694074649, 1694074958, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('120640c4-6c67-4166-9a7b-8e08e4018cc1', '39c763a5-b3d7-4292-99d2-c07f3a04d62f', 'layui-icon-face-smile', '添加字典', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'system-dict-add', '', 1695365718, 1695365718, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('16a335ef-abea-4581-8de0-1f03d669792e', 'ac72da18-cd39-4a6c-baf7-d2f75ca7b4b7', 'layui-icon-face-smile', '附件删除', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'system-file-delete', '', 1696668625, 1696668625, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('170320e1-d592-4809-9447-f40b27fc7aa9', '2b84ae82-4c4a-49ac-8471-a3233b0703db', 'layui-icon-face-smile', '我的待办', 'admin', '', '', '', '', '[]', 10, 1, 0, 1, 'view/wf/task/todo/index.html', '', 1, '', 0, '', '', 1696728340, 1697427557, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('18e6af3d-e99b-4b1c-be28-2a9547cf6eef', 'd9579432-b71c-4b71-9f9d-606a7317446a', 'layui-icon-face-smile', '添加配置分类', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'config-tab-add', '', 1695278678, 1695278678, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('1d244ec5-cf4e-445a-9374-aaddcb4d84f9', 'd6744062-bdbb-4f75-a83e-51cdb9d96f5a', 'layui-icon-face-smile', '语言列表', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/setting/lang/list/index.html', '', 1, '', 0, 'setting-lang-list', '', 1693980120, 1693980120, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('1e52ad08-670a-4425-9e72-3925ba871dcf', 'baa9d8a3-0ea0-4689-9489-0a5ca387409c', 'layui-icon-face-smile', '管理员状态', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'system-admin-status', '', 1694070554, 1694070554, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('21abf252-b962-4379-bc19-381749e2cb80', 'd6c3dc71-a5a4-4468-bd6c-4c92c24d098b', 'layui-icon-face-smile', '作废', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-order-undo', '', 1700550017, 1700550017, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('22900032-1fa4-4a53-bb04-f8b535ea9793', '857bd274-30f4-429a-8004-a2e6d0ccb6de', 'layui-icon-face-smile', '数据库管理', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/system/maintain/system_databackup/index.html', '', 1, '', 0, '', '', 1693978197, 1694073476, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('22d89696-2c65-4925-bf5e-d1b253f9ec17', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', '', '修改当前管理员信息', '', '', '', 'setting/update_admin', 'PUT', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-update_admin', '', 1710144809, 1710144809, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('25f880bd-856f-49fa-b59c-3f76b7d389c7', 'cb38b36a-c7ad-4899-bcbc-eee2d4291f69', 'layui-icon-face-smile', '删除定时任务', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'crontab-delete', '', 1694757362, 1694757362, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('2ac1fd8d-2ca4-4eea-bd1c-f3989096eea2', '8b55c722-256a-40b3-ae27-1fdf99164094', '', '角色详情', '', '', '', 'setting/role/get', 'GET', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-role-get', '', 1694564002, 1694564002, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('2ace6826-3984-4718-9497-ab0dd463bbcb', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', '', '退出登陆', '', '', '', 'setting/admin/logout', 'GET', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-admin-logout', '', 1710144809, 1710144809, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('2b3e6ae9-7509-4be9-a669-26047ee2e769', '4dd18197-2477-421a-8e42-238c6298c7c9', 'layui-icon-face-smile', '配置列表', 'admin', '', '', '', '', '[]', 21, 0, 0, 1, 'view/system/maintain/system_config/list/index.html', '', 1, '', 0, '', '', 1695279116, 1695279192, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('2b433461-3e8c-498d-85a0-33aafade3365', 'bc9ac16f-c3bb-43a1-bd05-bbda718513ef', 'layui-icon-face-smile', '新增', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'file-category-add', '', 1695824383, 1695824383, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('2b84ae82-4c4a-49ac-8471-a3233b0703db', '6ee2d444-cd5f-45ca-a880-11976d16c210', 'layui-icon-face-smile', '流程任务', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 1, '', 0, '', '', 1697427507, 1697427507, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('2d1f9c58-f0bf-43ff-a729-fabadabd3b8c', 'bc9ac16f-c3bb-43a1-bd05-bbda718513ef', 'layui-icon-face-smile', '修改', 'admin', '', '', '', '', '[]', 10, 1, 0, 1, '', '', 3, '', 0, 'file-category-edit', '', 1695824402, 1695824460, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('2e79d53d-3a7d-4e17-8944-bdd0b0f63df0', 'ee6010ce-a330-4217-9674-07435ce22833', 'layui-icon-face-smile', '删除', 'admin', '', '', '', '', '[]', 10, 1, 0, 1, '', '', 3, '', 0, 'wf-definition-delete', '', 1696926709, 1696926877, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('30dd2e7c-3233-45d3-b538-c2985f9a6ce7', '1d244ec5-cf4e-445a-9374-aaddcb4d84f9', 'layui-icon-face-smile', '修改语言列表', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'lang-list-edit', '', 1694698925, 1694698925, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('31d43b76-ae60-4ce5-a04e-2d1d1ec2604b', 'd4538387-432c-4422-9618-3ffbedf83473', '', '删除组织', '', '', '', 'setting/dept/', 'DELETE', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-dept', '', 1694671563, 1694671563, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('366472c2-cb67-4dd9-a8bb-2ae9f045b5c4', 'd6744062-bdbb-4f75-a83e-51cdb9d96f5a', 'layui-icon-face-smile', '语言详情', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/setting/lang/info/index.html', '', 1, '', 0, 'setting-lang-info', '', 1693980174, 1693980174, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('382c1114-59db-4594-b870-da3ce1a29c56', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', 'layui-icon-face-smile', '管理权限', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 1, '', 0, 'setting/auth', '', 1693981007, 1693981007, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('388b4b2f-5ca8-4cd5-804d-1716b8e02cd0', 'd9579432-b71c-4b71-9f9d-606a7317446a', 'layui-icon-face-smile', '配置分类状态切换', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'config-tab-status', '', 1695278861, 1695278861, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('3907df96-3152-4aba-9e23-a44575cc7251', '03c5a106-ed45-42d2-9467-e3448ed369b3', 'layui-icon-face-smile', '编辑菜单', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'system-menu-edit', '', 1694305219, 1694305219, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('39c763a5-b3d7-4292-99d2-c07f3a04d62f', '857bd274-30f4-429a-8004-a2e6d0ccb6de', 'layui-icon-face-smile', '数据字典', 'admin', '', '', '', '', '[]', 10, 1, 0, 1, 'view/system/maintain/system_dict/index.html', '', 1, '', 0, '', '', 1695363137, 1695363161, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('3a07101c-46ac-4ad7-824d-b2bf0de65b90', '4dd18197-2477-421a-8e42-238c6298c7c9', 'layui-icon-face-smile', '权限维护', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/system/maintain/system_menus/index.html', '', 1, '', 0, 'system_menus-index', '', 1693978496, 1693979401, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('3b7afea6-ddd5-4532-8a3f-9c2e126e731a', '39c763a5-b3d7-4292-99d2-c07f3a04d62f', 'layui-icon-face-smile', '修改字典', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'system-dict-edit', '', 1695365751, 1695365751, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('3d5e3491-7546-4046-acb3-d7b34fda210c', '4c0175ac-5b37-4ef5-a2dc-c14caa7b6e42', 'layui-icon-vercode', '安全维护', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'system/maintain', '', 1, '', 0, 'system-maintain-index', '', 1693978041, 1693979866, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('3e2df7be-9e8c-4ce2-9ddb-61f13d3142bf', '857bd274-30f4-429a-8004-a2e6d0ccb6de', 'layui-icon-face-smile', '表单构建', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/system/maintain/form_build/index.html', '', 1, '', 0, '', '', 1695016931, 1695017591, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('3e74a70e-fb39-41d6-b3f1-abd93ca56014', 'd9579432-b71c-4b71-9f9d-606a7317446a', 'layui-icon-face-smile', '配置列表', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'config-tab-list', '', 1695374799, 1695374799, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('3eb2a028-3398-4e62-abe3-0c295a795065', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', '', '获取当前管理员信息', '', '', '', 'setting/info', 'GET', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-info', '', 1710144809, 1710144809, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('3f9e4f79-1b00-4ce7-9187-62bd91ace077', 'd65fe5a4-b207-4afa-8a88-7ca21dd7df7a', 'layui-icon-face-smile', '分配组织', 'admin', '', '', '', '', '[]', 106, 1, 1, 1, '', '', 3, '', 0, 'system-role-dept', '', 1694074901, 1694074901, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('428ee06e-c350-4c9e-8c29-1e59a9e97570', 'd9579432-b71c-4b71-9f9d-606a7317446a', 'layui-icon-face-smile', '修改配置分类', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'config-tab-edit', '', 1695278712, 1695278712, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('4474d199-7089-4efb-bc68-b638a7aef300', '6ee2d444-cd5f-45ca-a880-11976d16c210', 'layui-icon-face-smile', '流程设计', 'admin', '', '', '', '', '[]', 127, 1, 1, 1, 'view/wf/designer/index.html', '', 1, '', 0, '', '', 1696835300, 1696926811, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('4811a205-a4ec-499a-ba85-30ca5ab95feb', '63a64d73-40df-4275-af16-c7c0fd382bf2', 'layui-icon-face-smile', '删除部门', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'setting-dept-delete', '', 1694353633, 1694353633, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('4a26ba61-676b-4842-a087-743eb0354203', 'd65fe5a4-b207-4afa-8a88-7ca21dd7df7a', 'layui-icon-face-smile', '分配权限', 'admin', '', '', '', '', '[]', 104, 1, 1, 1, '', '', 3, '', 0, 'system-role-auth', '', 1694074815, 1694075004, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('4c0175ac-5b37-4ef5-a2dc-c14caa7b6e42', '-1', 'layui-icon-util', '维护', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'system', '', 1, '', 0, '', '', 1693978041, 1710126090, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('4dd18197-2477-421a-8e42-238c6298c7c9', '4c0175ac-5b37-4ef5-a2dc-c14caa7b6e42', 'layui-icon-username', '开发配置', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'system/config', '', 1, '', 0, 'system-config-index', '', 1693978041, NULL, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('54480923-4b9e-4c85-90c8-19712b709bb2', 'd6744062-bdbb-4f75-a83e-51cdb9d96f5a', 'layui-icon-face-smile', '地区列表', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/setting/lang/country/index.html', '', 1, '', 0, 'setting-lang-country', '', 1693980228, 1693980228, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('57f79696-1bd2-43f5-a411-75080735b700', '4474d199-7089-4efb-bc68-b638a7aef300', 'layui-icon-face-smile', '添加', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-designer-add', '', 1696900498, 1696900498, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('588383d3-d8fe-4023-b9e7-220baac09a0d', '63a64d73-40df-4275-af16-c7c0fd382bf2', 'layui-icon-face-smile', '新增部门', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'setting-dept-add', '', 1694353599, 1694353599, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('59ca4011-f611-4514-a7ac-a404228e2e73', '6ee2d444-cd5f-45ca-a880-11976d16c210', 'layui-icon-face-smile', '发起申请', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/wf/instance/startProcess.html', '', 1, '', 0, '', '', 1709541635, 1709541635, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('5a22017d-6f19-41e8-936b-f70d405639dd', 'd6c3dc71-a5a4-4468-bd6c-4c92c24d098b', 'layui-icon-face-smile', '新增', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-order-add', '', 1700549878, 1700549878, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('5f4d2ab0-0cde-4bd3-829f-5a11d96b6440', '3907df96-3152-4aba-9e23-a44575cc7251', '', '菜单列表', '', '', '', 'setting/permission/select', 'GET', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-permission-select', '', 1694307886, 1694307886, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('60fea859-c085-4b37-8d7a-d03e81afe73a', 'baa9d8a3-0ea0-4689-9489-0a5ca387409c', 'layui-icon-face-smile', '分配职位', 'admin', '', '', '', '', '[]', 105, 1, 1, 1, '', '', 3, '', 0, 'system-admin-jobs', '', 1694070831, 1694070831, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('63a64d73-40df-4275-af16-c7c0fd382bf2', '0a4aff69-ad1d-42b2-8634-00dc3e52360b', 'layui-icon-face-smile', '部门设置', 'admin', '', '', '', '', '[]', 1, 1, 1, 1, 'view/setting/org/dept/index.html', '', 1, '', 0, 'setting-dept-list', '', 1694310916, 1694311025, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('64308d28-674e-4e61-8700-b8b508162c5d', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', '', '保存管理员', '', '', '', 'setting/admin', 'POST', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-admin', '', 1710144809, 1710144809, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('67cfcfe5-7441-44fd-bc61-3e9dc3059362', '1d244ec5-cf4e-445a-9374-aaddcb4d84f9', 'layui-icon-face-smile', '语言列表状态', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'lang-list-status', '', 1694698983, 1694698983, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('6b674c34-7d23-4a27-9a05-688ed3e9c38e', 'd6c3dc71-a5a4-4468-bd6c-4c92c24d098b', 'layui-icon-face-smile', '删除', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-order-delete', '', 1700549954, 1700549954, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('6ee2d444-cd5f-45ca-a880-11976d16c210', '-1', 'layui-icon-face-smile', '工作流程', 'admin', '', '', '', '', '[]', 0, 1, 1, 1, '', '', 1, '', 0, '', '', 1696728191, 1710126098, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('73aebdf5-fae6-4aa9-a319-8fcc48b6351b', 'ee6010ce-a330-4217-9674-07435ce22833', 'layui-icon-face-smile', '添加', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-definition-add', '', 1696926692, 1696926692, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('75300596-9c65-4e63-87c3-19c974e7bf1e', 'd65fe5a4-b207-4afa-8a88-7ca21dd7df7a', 'layui-icon-face-smile', '角色状态', 'admin', '', '', '', '', '[]', 103, 1, 1, 1, '', '', 3, '', 0, 'system-role-status', '', 1694074678, 1694074678, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('7a5eaccc-0019-4064-8f83-7c564c431a7c', '4474d199-7089-4efb-bc68-b638a7aef300', 'layui-icon-face-smile', '修改', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-designer-edit', '', 1696900547, 1696900547, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('7c259013-7919-4235-ab8c-bfcda9b51184', '857bd274-30f4-429a-8004-a2e6d0ccb6de', 'layui-icon-face-smile', '文件管理', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/system/maintain/system_file/index.html', '', 1, '', 0, 'system-maintain-system-file', '', 1693978336, 1693978336, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('7e72c463-d80a-4b83-937d-eb20d63a9636', 'd6c3dc71-a5a4-4468-bd6c-4c92c24d098b', 'layui-icon-face-smile', '查看', 'admin', '', '', '', '', '[]', 10, 1, 0, 1, '', '', 3, '', 0, 'wf-order-detail', '', 1700549972, 1700550026, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('7ee73260-eaaf-463a-84ff-ac285055e0c1', '54480923-4b9e-4c85-90c8-19712b709bb2', 'layui-icon-face-smile', '添加语言地区', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'lang-country-add', '', 1694700335, 1694700335, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('817c3d6e-2f2a-4af9-9b84-97e76029302d', '2b3e6ae9-7509-4be9-a669-26047ee2e769', 'layui-icon-face-smile', '修改系统配置', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'setting-config-edit', '', 1695362530, 1695362530, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('857bd274-30f4-429a-8004-a2e6d0ccb6de', '4c0175ac-5b37-4ef5-a2dc-c14caa7b6e42', 'layui-icon-tips', '开发工具', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'tool', '', 1, '', 0, 'system-tool', '', 1693978041, NULL, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('88cab609-0d7f-4394-a00e-ad24bd2c5ae5', '6ee2d444-cd5f-45ca-a880-11976d16c210', 'layui-icon-face-smile', '流程类型', 'admin', '', '', '', '', '[]', 127, 1, 1, 1, 'view/wf/category/index.html', '', 1, '', 0, '', '', 1696827780, 1696926800, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('8b55c722-256a-40b3-ae27-1fdf99164094', 'd65fe5a4-b207-4afa-8a88-7ca21dd7df7a', 'layui-icon-face-smile', '分配职位', 'admin', '', '', '', '', '[]', 107, 1, 1, 1, '', '', 3, '', 0, 'system-role-post', '', 1694074927, 1694099345, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('8c3e3149-4438-4b1c-b32c-10978b1a54ef', '88cab609-0d7f-4394-a00e-ad24bd2c5ae5', 'layui-icon-face-smile', '删除', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-category-delete', '', 1696835221, 1696835221, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('91c5a906-911d-4222-b534-df2e5041e0dd', 'ee6010ce-a330-4217-9674-07435ce22833', 'layui-icon-face-smile', '查看', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-definition-check', '', 1696926781, 1696926781, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('92158f89-3eb8-462a-85c9-f9586075e274', 'd65fe5a4-b207-4afa-8a88-7ca21dd7df7a', 'layui-icon-face-smile', '编辑角色', 'admin', '', '', '', '', '[]', 103, 1, 1, 1, '', '', 3, '', 0, 'system-role-edit', '', 1694074625, 1694074979, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('92bfab0f-88e6-47ee-b2f2-5d0916f11ef1', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', 'layui-icon-face-smile', '附件管理', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 1, '', 0, '', '', 1695782767, 1695782767, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('94d4cd83-3d89-493d-97ba-27ded6503a8f', '2b84ae82-4c4a-49ac-8471-a3233b0703db', 'layui-icon-face-smile', '我的已办', 'admin', '', '', '', '', '[]', 10, 1, 0, 1, 'view/wf/task/done/index.html', '', 1, '', 0, '', '', 1696728323, 1697601330, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('982ac136-2353-47b2-9c81-c6b9dd5684c0', 'ac72da18-cd39-4a6c-baf7-d2f75ca7b4b7', 'layui-icon-face-smile', '附件修改', 'admin', '', '', '', '', '[]', 10, 0, 1, 1, '', '', 2, '', 0, 'system-file-edit', '', 1696668655, 1696668655, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('99f5f7b2-d584-44f0-b93d-aee0b8030649', '3907df96-3152-4aba-9e23-a44575cc7251', '', '菜单详情', '', '', '', 'setting/permission/get/', 'GET', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-permission-get', '', 1694307886, 1694307886, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('9f1161f9-a3bb-42c8-9b8f-19b12aecf708', 'baa9d8a3-0ea0-4689-9489-0a5ca387409c', 'layui-icon-face-smile', '修改管理员', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'system-admin-edit', '', 1694070481, 1694070481, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('9fb603da-e232-4beb-ad9b-2351e0274029', 'd6c3dc71-a5a4-4468-bd6c-4c92c24d098b', 'layui-icon-face-smile', '取回', 'admin', '', '', '', '', '[]', 10, 1, 0, 1, '', '', 3, '', 0, 'wf-order-back', '', 1700549994, 1700550041, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('a16b6f89-bd60-4ffd-b833-337ccd8fed36', 'bc9ac16f-c3bb-43a1-bd05-bbda718513ef', 'layui-icon-face-smile', '删除', 'admin', '', '', '', '', '[]', 10, 1, 0, 1, '', '', 3, '', 0, 'file-category-delete', '', 1695824421, 1695824471, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('a51a3e37-c890-40b2-adf4-ca7f3856fd84', '4474d199-7089-4efb-bc68-b638a7aef300', 'layui-icon-face-smile', '设计', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-designer-design', '', 1696900605, 1696900605, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('aaf1c674-956f-4349-8f61-b1d8d3285e20', 'ac72da18-cd39-4a6c-baf7-d2f75ca7b4b7', 'layui-icon-face-smile', '附件上传', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'system-file-add', '', 1696668604, 1696668604, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('ac632dc7-9f6e-4d07-9d50-0561a456417d', '-1', 'layui-icon-set-fill', '设置', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'setting', '', 1, '', 0, '', '', 1693978041, 1694614725, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('ac72da18-cd39-4a6c-baf7-d2f75ca7b4b7', '92bfab0f-88e6-47ee-b2f2-5d0916f11ef1', 'layui-icon-face-smile', '附件列表', 'admin', '', '', '', '', '[]', 10, 1, 0, 1, 'view/file/list/index.html', '', 1, '', 0, '', '', 1695783806, 1695783806, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('b21c5ea2-3eb9-4d4e-8244-bdb3caf7ee80', '366472c2-cb67-4dd9-a8bb-2ae9f045b5c4', 'layui-icon-face-smile', '编辑语言详情', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'lang-info-edit', '', 1694700127, 1694700127, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('b30dce1f-89e8-4563-b52c-5e85a836ebb1', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', '', '获取详情', '', '', '', 'setting/admin/', 'GET', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-admin', '', 1710144809, 1710144809, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('b4c85694-38b6-4332-a62c-260cd597f257', '54480923-4b9e-4c85-90c8-19712b709bb2', 'layui-icon-face-smile', '编辑语言地区', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'lang-country-edit', '', 1694700369, 1694700369, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('b7ae5925-9e84-403e-b8a2-eb4528b11d89', '1d244ec5-cf4e-445a-9374-aaddcb4d84f9', 'layui-icon-face-smile', '添加语言列表', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'lang-list-add', '', 1694698886, 1694698886, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('ba789614-2967-4b16-99d0-b14f9ec98818', 'cb38b36a-c7ad-4899-bcbc-eee2d4291f69', 'layui-icon-face-smile', '添加定时任务', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'crontab-add', '', 1694757302, 1694757302, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('baa9d8a3-0ea0-4689-9489-0a5ca387409c', '382c1114-59db-4594-b870-da3ce1a29c56', 'layui-icon-face-smile', '管理员列表', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/setting/system_admin/index.html', '', 1, '', 0, 'setting-system-list', '', 1693984108, 1693990119, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('bad80eed-ef69-4e42-8d36-ceea6df674d1', 'd65fe5a4-b207-4afa-8a88-7ca21dd7df7a', '', '添加角色', 'admin', '', '', '', '', '[]', 101, 1, 1, 1, '', '', 3, '', 0, 'system-role-add', '', 1694074602, 1694075262, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('bc9ac16f-c3bb-43a1-bd05-bbda718513ef', '92bfab0f-88e6-47ee-b2f2-5d0916f11ef1', 'layui-icon-face-smile', '附件分类', 'admin', '', '', '', '', '[]', 10, 1, 0, 1, 'view/file/category/index.html', '', 1, '', 0, '', '', 1695782844, 1695783828, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('bd3fbcde-13b8-4c76-9293-755d349b3873', 'ee6010ce-a330-4217-9674-07435ce22833', 'layui-icon-face-smile', '修改', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-definition-edit', '', 1696926759, 1696926759, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('bdd9f5be-2460-41b9-8212-044bfae1a568', '3d5e3491-7546-4046-acb3-d7b34fda210c', 'layui-icon-refresh-3', '刷新缓存', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/system/maintain/clear/index.html', '', 1, '', 0, 'system-clear', '', 1693979776, 1693979776, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('beb61b71-362f-4a59-ba8c-aba8135602a0', '366472c2-cb67-4dd9-a8bb-2ae9f045b5c4', 'layui-icon-face-smile', '删除语言详情', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'lang-info-delete', '', 1694700227, 1694700227, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('bec0e802-1606-4d96-a2a1-7a3bc68852d8', '39c763a5-b3d7-4292-99d2-c07f3a04d62f', 'layui-icon-face-smile', '删除字典', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'system-dict-delete', '', 1695365775, 1695365775, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('cb38b36a-c7ad-4899-bcbc-eee2d4291f69', '4dd18197-2477-421a-8e42-238c6298c7c9', 'layui-icon-face-smile', '定时任务', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/system/maintain/crontab/index.html', '', 1, '', 0, 'system-crontab-index', '', 1693979471, 1693979471, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('d4538387-432c-4422-9618-3ffbedf83473', '63a64d73-40df-4275-af16-c7c0fd382bf2', 'layui-icon-face-smile', '状态切换', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'setting-dept-status', '', 1694353709, 1694353709, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('d65fe5a4-b207-4afa-8a88-7ca21dd7df7a', '382c1114-59db-4594-b870-da3ce1a29c56', 'layui-icon-face-smile', '角色管理', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/setting/system_role/index.html', '', 1, '', 0, 'setting-system-role', '', 1693984062, 1694074445, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('d6744062-bdbb-4f75-a83e-51cdb9d96f5a', '4c0175ac-5b37-4ef5-a2dc-c14caa7b6e42', 'layui-icon-face-smile', '语言设置', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'setting/lang', '', 1, '', 0, 'setting-lang', '', 1693980014, 1693980014, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('d6872382-8bba-40be-953c-b999b1b5387c', 'cb38b36a-c7ad-4899-bcbc-eee2d4291f69', 'layui-icon-face-smile', '编辑定时任务', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'crontab-edit', '', 1694757328, 1694757328, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('d6c3dc71-a5a4-4468-bd6c-4c92c24d098b', '6ee2d444-cd5f-45ca-a880-11976d16c210', 'layui-icon-face-smile', '我发起的', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/wf/instance/index.html', '', 1, '', 0, '', '', 1696728282, 1696926622, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('d8884521-f21e-4468-a50b-b3978022cef2', '857bd274-30f4-429a-8004-a2e6d0ccb6de', 'layui-icon-face-smile', '接口管理', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/system/maintain/backend_routing/index.html', '', 1, '', 0, 'system-config-backend-routing', '', 1693978399, 1693978399, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('d9579432-b71c-4b71-9f9d-606a7317446a', '4dd18197-2477-421a-8e42-238c6298c7c9', 'layui-icon-face-smile', '配置分类', 'admin', '', '', '', '', '[]', 20, 1, 0, 1, 'view/system/maintain/system_config/category/index.html', '', 1, '', 0, '', '', 1695265996, 1695279151, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('d97843a4-c154-4943-b8fa-0bbac76706cb', '2b3e6ae9-7509-4be9-a669-26047ee2e769', 'layui-icon-face-smile', '添加系统配置', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'setting-config-add', '', 1695362505, 1695362505, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('da6b2620-828d-49e1-82d2-dda9217b0f6f', '366472c2-cb67-4dd9-a8bb-2ae9f045b5c4', 'layui-icon-face-smile', '添加语言详情', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'lang-info-add', '', 1694699213, 1694699213, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('db010262-fa5b-494b-a961-3e6a40ceaf71', '0a4aff69-ad1d-42b2-8634-00dc3e52360b', 'layui-icon-face-smile', '职位设置', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/setting/org/post/index.html', '', 1, '', 0, 'setting-post-list', '', 1694310994, 1694310994, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('dc147005-906d-4373-90a0-c331cbc07b79', '3907df96-3152-4aba-9e23-a44575cc7251', '', '菜单更新', '', '', '', 'setting/permission/update', 'POST', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-permission-update', '', 1694307886, 1694307886, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('dd097886-0cee-4731-bc9a-da48eacece91', 'baa9d8a3-0ea0-4689-9489-0a5ca387409c', 'layui-icon-face-smile', '删除管理员', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'system-admin-delete', '', 1694070525, 1694070525, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('e0db89ff-5832-4057-83a1-afb3af069b5e', '6ee2d444-cd5f-45ca-a880-11976d16c210', 'layui-icon-rate-solid', '我的收藏', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/wf/favorite/index.html', '', 1, '', 0, '', '', 1709620419, 1709620419, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('e16554a1-0325-407f-9ec4-5a5b60138730', '2b3e6ae9-7509-4be9-a669-26047ee2e769', 'layui-icon-face-smile', '设置系统配置状态', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'setting-config-status', '', 1695362627, 1695362627, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('e19558fc-2a31-440b-b356-05a3c9af9804', '1d244ec5-cf4e-445a-9374-aaddcb4d84f9', 'layui-icon-face-smile', '删除语言列表', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'lang-list-delete', '', 1694698953, 1694698953, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('e6c8ca0f-a219-41fe-9289-b07957104e7a', 'baa9d8a3-0ea0-4689-9489-0a5ca387409c', 'layui-icon-file', '添加管理员', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'system-admin-add', '', 1694070456, 1694070456, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('ec8940c7-5a43-460a-8778-6d85f0172c2b', '2b3e6ae9-7509-4be9-a669-26047ee2e769', 'layui-icon-face-smile', '删除系统配置', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'setting-config-delete', '', 1695362580, 1695362580, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('ecdfd3a9-17b4-4f5d-bb8c-ebc1f189aa49', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', '', '获取管理员列表', '', '', '', 'setting/admin', 'GET', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-admin', '', 1710144809, 1710144809, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('ee6010ce-a330-4217-9674-07435ce22833', '6ee2d444-cd5f-45ca-a880-11976d16c210', 'layui-icon-face-smile', '流程定义', 'admin', '', '', '', '', '[]', 127, 1, 1, 1, 'view/wf/definition/index.html', '', 1, '', 0, '', '', 1696728303, 1696926821, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('f28e981b-07b1-40cd-9071-aea501269627', '54480923-4b9e-4c85-90c8-19712b709bb2', 'layui-icon-face-smile', '删除语言地区', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'lang-country-delete', '', 1694700400, 1694700400, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('f478742b-8060-41ae-9162-4a08c18e28ea', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', '', '修改管理员状态', '', '', '', 'setting/set_status//', 'PUT', '[]', 1, 1, 1, 1, '', '', 2, '', 0, 'setting-set_status', '', 1710144809, 1710144809, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('f77a8ac8-6395-481d-a31e-c46b9f9b35c5', '4474d199-7089-4efb-bc68-b638a7aef300', 'layui-icon-face-smile', '删除', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-designer-delete', '', 1696900523, 1696900523, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('f858a70c-65e8-4edb-9e24-0d94c337b0d0', '88cab609-0d7f-4394-a00e-ad24bd2c5ae5', 'layui-icon-face-smile', '添加', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'wf-category-add', '', 1696835183, 1696835183, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('fc6c26c2-2abf-48d1-81d5-16e20c341b92', '3d5e3491-7546-4046-acb3-d7b34fda210c', 'layui-icon-list', '系统日志', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, 'view/system/maintain/system_log/index.html', '', 1, '', 0, 'system-maintain-log', '', 1693979842, 1693979842, NULL); +INSERT INTO `lms_clx_system_menus` VALUES ('fcabee71-1473-4020-84d8-6f7eaa9ebfe5', 'd9579432-b71c-4b71-9f9d-606a7317446a', 'layui-icon-face-smile', '删除配置分类', 'admin', '', '', '', '', '[]', 10, 1, 1, 1, '', '', 3, '', 0, 'config-tab-delete', '', 1695278754, 1695278754, NULL); + +-- ---------------------------- +-- Table structure for lms_clx_system_mutex_roles +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_mutex_roles`; +CREATE TABLE `lms_clx_system_mutex_roles` ( + `role_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色Id', + `mutex_role_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '互斥角色Id', + `sys_code` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '系统编码', + PRIMARY KEY (`role_id`, `mutex_role_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '互斥角色表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_mutex_roles +-- ---------------------------- +INSERT INTO `lms_clx_system_mutex_roles` VALUES ('53c735852284434ca6e95fe8ea3a47e5', 'ee209a85eb494a5fa90bd5448d309736', NULL); + +-- ---------------------------- +-- Table structure for lms_clx_system_options +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_options`; +CREATE TABLE `lms_clx_system_options` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '键', + `value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '值', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '选项表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_options +-- ---------------------------- +INSERT INTO `lms_clx_system_options` VALUES ('0fdb52c5-019b-4a8e-bafd-32a84e12df81', 'fgsdf', NULL, 1695048895, 1695048895); +INSERT INTO `lms_clx_system_options` VALUES ('1', 'system_config1', '{\"logo\":{\"title\":\"WorkingFlowe\",\"image\":\"data:image\\/png;base64,\\/9j\\/4AAQSkZJRgABAQAAAQABAAD\\/\\/gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2OTApLCBxdWFsaXR5ID0gODUK\\/9sAQwAFAwQEBAMFBAQEBQUFBgcMCAcHBwcPCwsJDBEPEhIRDxERExYcFxMUGhURERghGBodHR8fHxMXIiQiHiQcHh8e\\/9sAQwEFBQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e\\/8AAEQgCowSwAwEiAAIRAQMRAf\\/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC\\/\\/EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29\\/j5+v\\/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC\\/\\/EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29\\/j5+v\\/aAAwDAQACEQMRAD8A+U\\/NedRHJctgAk5brz1z2H+NQXG2RhJGqIMYZIycZHHf1p4Li1NstvGdz7h8oDfTJ7VAYyeDkL2AGMY9qzSNGxhLHKEMMHA9RUksgeIRjPHXOaZFCZCfL3FQOnc++KHiEcg3cN0OTk5piJooZEj8zCFQBkHpnnGfr9amEhmAkkLFx1Y5O7tj\\/PpTImJUxhWIGNg4Ibnpz0HWlaSQy7lTavORt\\/rSGBVA7HO4hBn92ePX8vWhAu4lCCB2PUn\\/APVU6sUC5jZ9+cgFcVA42t5a4AJ5JI\\/EfnQBMzB41y0rD76gtz0HP5Ciyjnu5PslujPMRuG3sB17\\/wCcV0ej6fC2l\\/bJrpHFxFLHtZAzKFK\\/dX1784HFO8Bwra+I284DJhcgnPOV9PWuedZRjJrobQp80kn1M7StHzqNrbTggNIPNIYDB3Yxn3Ndt4m06ae1mlhMjuY1lmVVOchgGHGepY8CsDVLWBrmeeBpI3im5OeuWbPH5fSujnn1jT9Lt7y+kIjuGeOWNOCAwG3+Y71x15Sk4STXp+JtTSjzKxyGqWF7LBPeLb+ZHHlRjJZQOAOe4yK6jwZrFzpmiLY3iSQCZWMUjtkDJU9Md8Ae1X9Be6sdfSDyUcyQuSZJSyMwTPQD68nuKy9JjnuLy9uLhGEgKxW6sThVkDfNgg5B49KzrSVWDhNaKzKpXpyUludD4gvri5RLiEQwrqCrEfNVW3IzsvB6jnce3Ss3VbS9Gjafd3MdsbeSEOGA\\/jEYAJ+hUj\\/9dZiyeTavZ3UkxvrdwqRyuNu5ACoXj\\/e68cjHest9XubyCO3nHlpbPJux8mQRleOgOSB+NRHCuNuS1l+VtDT26u7nSeHNNhxbX80sqSG42xDqNm9k69jjP5g1teLtNutRtry7gtxHcQxJIpjU4yjsvB9Sqp255psdjJbxaVfpGJLB4Q8fAYgnDHkd\\/vVt6pNfW0BeyjZURd7NJnbJE2SQc+hC\\/nXnupKVRTi\\/6T2OlpKLTX9W3PGLzRpE0t9WMwOZnQrjlfQ5zWWqqHYSZGF+Y7fT\\/Hj869PsNItdStJNNZA7292u914wCh2sR6HKk\\/SuG8S6c1hqM+MLBnIJTIXjOOn1r3MPilUk4Pf9Dz61HlSktjHto8lRJuLPyMDgc4HHfjnilWORCoLbPl64zkUSIu1SCACQW5J6d6QlTIUDuUyGV8eg\\/wAf5V2nOK29H89IRwwBBHUn060ib2ZvmXcyndz1GenX3p8glK\\/vWA4BK7MEgA85A9h19KkmfcyeWN8rIQ4X37dscelICZYVJWbZujDYHOd3AOAPYU1ypQkSOjKB8pye\\/Qc\\/54pYy5W3XzJFJztY8jj0\\/Sq5XbwuZSSTwOpPt+X51JRYdJ7ZQ0oaNZFyhIyBz25+o5pI4laDEingZ3ZGAB3IH4VLCzSGGO5YkEFU2KD2\\/wAeaSKOWGJt0pCFmBXy8nngtnoQCO56ilcdiJ1LXSAYZiu3Izg\\/hQpIXG5F5xnGCRjPfn8vSnRSAozormXqzN\\/F0+X881BOwkwV2oq53KRjn0Gc\\/r6UxFmcqbVoM7mC5RyDx+J+lVPMDuARufPXHB4x\\/gTmmF8LGpGVUEsAcAkdgcVAsr7NgVtuSTtPDf5xTURNmhJMjRFkCltwAPJPsM\\/mMZ7d6hvVCTHHMcoDZLAdev8A9bNOd3kZIHePJQDA7djT79p\\/MREeRwo\\/dnJPH0JPrSWjB6mXJhmbdkhcMzZ\\/DgflUkYGz59z5zwe5xx\\/jSXEReVVL5fPyhgB19f0psoV5AOE46c+p4rQkkkhJHy5kwo3HoF55wKV0jxmQc4GB03A\\/wD66miSRs4jfKg52pknpk1CFJLB22Db98g5H\\/6+lTcBbqOMlir7m64znnH59TVYlvLYEkHtxwT6fyqQckMjqzBSW9D9TTOQrhlGwE7TnvxzTQMeI1RRwuFHJwBjj\\/69OjhiSIvPFJyflfdhR25GMnt3pIP3kyq8jLFjAJGccf41Kk3lOYppBIiblVR930yP\\/wBVGoKxGmfszRyMQAd428D1xipL8yqkU6bjC4IVscEjqKgmEatlC+wnOOpGR0pIp3dY4ZDI0YcnYOgyaLdQuKlxIPvMSMjPNTyqWtw43K3BJ7AVZe6023RfJszI+MkSnOD2PuPas8OzLtdm5x0GM0tyr2L1vKLsl2cK0YGT2x\\/n1qS5bFrKpBXDbVyKqyOgbMITaUwwPGferll5lxbBJdpiVsk4ww\\/Ejp0qGupSfQrWEKyQN5h2+WAyn+lWz5dwhcjJGCAMgAY6g59expMKytCg3oy5zjkH0\\/OrdqwEagHbK3yk7cBvUDHHf9aUn1GkV1\\/dxFIsyxnKHc3Q45A9fSqdu7xuWOEGACDw2eB36Va1CFGiiMTAI3L5G0qc4\\/HqaglJWEB9wVW3ImehoWwmXIzA2ySVg6M3LMdxHc8A\\/wCeasG3SQExIrIqgLkZyemM8c4z+XesmKQogUKrICTjH4j61taPdOt2g3cZ3li23H0\\/H\\/OOKyqJxV0a02pOzOq+HlxJoWtR3MpkML\\/u5MA5wSOc9OD2Ndd\\/wromET+H5Fube5R3hMjEYJJwucfezkH6elcjYyQSRGCXdmVSwEfQ5z0HGemB+FdX8P8Axw3h2KWx1tybO4+aGROTE3QHOfxr4\\/NI4q8q2G+LS6\\/mS\\/Vfke9g\\/Yq0am3fsa6+HLDQtP8A7Se5kTVIAC8ATCgBsHCj19+PTFcFr32uDxHLfESQWRiEKADCzMFJBAUAEYIGDznPFeg63dyaw76hZ33nB1KDIDdAfb26H0rldUhu1soYVtpA1uPM2n5lXJOVHGcHp17V5+XVailzVXeT0d+nl8n+Z24mjF25OnYfZPcXhKx3yJJt8oI4\\/eMdrApuIzySe38QzWkY55fMnuot9lCBsaJv9YpPVj6YwOBn8MVxscjEoX2xNbljHGwwQRgdQCeh6n375rp9B1CKXT5bPN0qzqG3CAMRkBgHXI\\/iJxj056V0Yqg4Lmj\\/AF8\\/QzpVL6Mi1eTTruRmgIiQQ7grfcdwM4H455\\/LrVPTrG4dJNyzKjzqiyodwyMBQRxgDrnr1qfVrJxaMryYQR7mljk3kMAAwyDxyqgg91xxVnS9\\/wBpkSSSCKRBsDMCI3y2OehHbBA6mkpclL3WO15ambq1lqQgMgleSItgEKcEgeh\\/DPGaw1IhJjCZcMC5ycYxzx6+9ejyySiBLQ3Elw45ijD7luH+Y8NwSQSvTPTvnA5a\\/S2n1Kae2CwmMDzFYDhiCMEfiD061eFxTacZL7hVaS3Rzl9uW5YqgQFcooOMDkY9yKit2QIEGXj3jkHg4x268\\/pj6V0Gu2QOrT+XJE4abcMMFY5J+YdgBwD9KzW0qVLtRCJCScKAMjjrg+3H\\/wBavSp14SgrvockqclLQoeYyqfkDGMEgEcHOOp\\/z3q5b+VcMWbzJGznJkx36e55FB82W7j3qQNuCQu7I7HHbj+VWNY0qS1CXVuWIYhlKKRhCMYPpjjp605TjdRejYKL1a1RWuLPF1LCf3CGQLiU\\/wCTjrVbY\\/nIjlcKcD5skbc\\/pyDn2NbzR2zWanMjX0bYkSRdxx2znkYyfX8MViX8Lq6uBJGxbYyZzjBAxz07dfSlRqc2jCcLao17axljiDwqqvkDBkBTA7kjt\\/8AXpLmLfK8aSOig7CARt7Zx79f++hT\\/DVxbXdokd1PHCCpijZ1OCpGOf157cVq3ixLdmRYXeKZFO\\/h9pwVIIPPrg9QAOtcVSpKFRxludMEpRTRQ05Usp1eSaaIo2GIAKsBzkN3OcD8aswJbxEXBVyU3ZMZ6sRn7p4yc8emAKW1haZJoJ12BDxGVO5ckdG4yOvHHfrVuxsFdxdJcj5EwzBiSpGcEKOvYce\\/44VKiu22aRi+g7Trry3ja7ktz85+VAM8sfmPcYwo9B6U3UZEls3tCjuzyMB5BB5K88HAwfYdzUM0QMpWQQiWBWYSRkkHJyRx7t0PPenjyrqRbY2589t672OASAGIxngkbefasuWKlzFXdrGDHbPDdxvA7QOmU+VvmJPO4Hjsefy9afd+WljCof5pGDFotv3lyoDAnj16H+Va4hX7So84xCErHuZSQT\\/eyRnHv6Yqlf6a9vcr5s8amVmZSpJDAHv+v511xrKUldmLhZaFS2hS3lj82UmJwS6+nXGfQg45xzxV7VvD9ossMkN0hhmw26MFmUBuu3uR35A5q5a3cN1Oks6JG5KrvRt+5wvy8fUD6HtUMupWlq7WzzxxuZD5YO1xG2S3UcY4z0z09Kh1arn7t7\\/1+Q2qcY+9sZTxKkX7uY+WjHD+XgA5Geex\\/wAmhrRCzR\\/Z1TDsFwuUPORnPt71pW11p2oyRgyIZFj8qZYhwQRhW9CeDnA9+2abfWcU8\\/LRhEbyyyKD02hjxyDgE8\\/0rRVWnaV0xKKavHUWJ\\/JjeEwzLPLwzRsQTgggHIwcE56Z6VG9nIHVJchGVSE8zIORgg5+mMZ4wDV60We3VVkuW2uRgMh2kH5QRgf73H04zxVhbiKWwaa6t\\/NWRQNrEbnUnGV7gcDA\\/Xmud1Gnoa8qa1MbU5XktwN3AK5Upj5jyRgdwMfnXKTrcPcyiNCUhVkLOG+X39OQc1va\\/AyRum91hkI2ADbuYKBjj8PyPpUNrZTX4ZbVHKBiZSR34HI\\/CvQw8o0oc3Q8uvQlVlbqZWn3B0uO5jdYmt2O4Rkq5jb7r5PqSPw498dfp8Vq9lG8enxwts3cn5mYkAn0GAR6Dg9c1xx0ma4ne4ujlWf5owwPTrgd+5\\/Guq05r+XUbhUhBjMaxxFRjBXrwBznpnGBx68PG8sldPXr+BeEUoaT+Rfms0uYpvMlhtY0YyOGXjjIxx14AA5HFYMM6WNjNEF8yUujgKxAII4JAPHA5rWfR\\/EdxetHa27tF5mzkDByck\\/iDium8OeCHtZGvNUUSyOSzR7RwVwAMenJ+teZLF0cPB880+yR2exniNFG3mzzlNP1q9JFjYyORI6xzOSVQkdR6nKj8629B8A+IbvUraa7DxwwSF3lkk2A5HT3z\\/LNevRtcvaQweTbWKIwXC4LYHXAHc8VU8TafqV7Bmw1JkS3UZyu4Fh0HHOcmuCWf1ZvkioxvfXV+RpDKYRXM220JGsOj6A7jyYlCkmJSW3c\\/eB75OM965nXJtfGj6Qq3a3VyYUlMY3K0bBMggdSOe\\/ofWsa1uNbbT7qSW58+9SIxROMjBJ6tjrgAkAf\\/q3dIa\\/1C\\/FxBcg6tHZ+TC5ACLk4AH6Yz6e9ZLD\\/AFducmpWbf4ffbXVm7nUqNRasjLtb3VoNNW4utTezu7WVYzbTJhWdkwoIHGORn29cVoeHX0zSdNM2u3cdxqSCSOWOGU7YgwZyy45ydy89RnHXNPuvButT60k+rX1nJNJCVSNQfmbPzPwfvKG\\/wDrUj+D9Hu7ryLhb1rlQiMDJksAeMntnP61pOvhpxs5aPV8q\\/C+jtuZxoVG+b82c5ceINMsLU2miwSxRzoC247sKc4yM\\/Mfr\\/hXReFm0e00mC91Ivd3dwWuFe6i\\/wBSMbiygn0HB7066+HmkTbIIYJ4FMymSd5SASeMduKpeLbfW4zbafZ263cVvEIUKxBw0Zx0yPQAcelaSq4bEpU6Umr6tt2f3\\/8ABQSpVI\\/Fr2saenWdgPENxqt39igis1eaSBcgzEniQ4zwQG4yOg6542LfxBZS6\\/NPPaYtrGAm2kMiBm3BSV2\\/3QpGD3571xXh+Cfw6Yb3VJ40u2BXyPJZ5ZfZmPH5e9aEdm+q+JJtU1Wzktk+ztFcTO5Y7mkJAA6YVRjPpjNc9fDQlKTnK8UrJ\\/dt3v313t6FNT0idXc+LNKMLXxSC2klUtbISQWwcZfA4GefUgVxtl48mvtSXTZtGN3fR3LxxpITkNlV5ySN3X6daibwxoP9uQRX731\\/d7TPbWowisB9wHGfoc4H0rqfDUGmWNpLcX2jwaS3nPIqquCVBOSeeMEdaj2WDw1NuMHNvbp321u13Bc8pWbsvvItPi0bRZVju7RX1LYS8rSkBGKEsF5woyoXOe1O8B2V\\/LBY6jfPPc35laQRNIWhiDkuMA98e+B0p1j4q8G+IHsktYXeZjvgDgcNz949+c8Gul8M+X+9SGaYQwzcsdqtK3A7chQR\\/OuLFVatKnJVItSe9\\/mrLstdjopqEpJwd0Lc6feF2dpI7Bm+VpI+W2+uOnoMDrk5qhNrOkaFatb2whDfZyfPZgJGZdu0OepJz61oa7FfRyfZreWB47lHZpJHwF5G0ADk+mc+9eTX3h97TSv7fn1Ez6nEVma0kGVHzhggHOSVz19h2yJy\\/D08Sv3s7LSyXX1+7roTiKn8iLGk+JPFPiDVjp0MUBuWUq0yQHfB1+cN1xz175GBzXf6Vp073sFs+uxzfYFK7IAzvHkbcsxYc43dv5Vx3gjQPEdz\\/a13cz\\/2cLxxMsyHzZJOCAvJ+7yQOAR+Axs6FJZ6G95LqkUdvdXUgRZ4Jy+5MZ3gHpzgnI5IFd2YKnJyhQtolpFX1a1+7Xb57nPTUrJy3Ov1jXbTSI0KRPO0gCwKIzxwfm6YHbmsP\\/hNdH1RZImlSSWDfsCuzRttHVuBx7Vmwmz8Ryaot1PqFppO+LH7wqXJVXABH8I3AY9BWbNN4Z0vzbbTfKYwLtUBhuLZye3T\\/CuKhgaKXLKMnNdunq\\/0\\/E1nKy5m9C2LXU7i2WGxH2aCWQszKSCwPA\\/Q960pb2w8NWCQgLJKMZCgAc9zXKax4xu0VY7ZvLVR17gcd64XV9dmnmb99I77j1Ge4r16GVV8U0qmkd7Lr6swq5nCCtSWvdnXa94sv7pSlvOVLnhFPC1grd6iiMx+Vs8sMHJrBmvFhlAUGPAG7rn8aaNSYwExs\\/J7DHA46fl+VfQUcsVOCUYqx5\\/t1zNzd2dJJehGG+QtOy8nBJPbOOuK0LO6uJJHkkQGMctx97jnP+e9cYNTjt2MpO5iMcv09PapYPEc2WeORJi3G0HABx0H5dcVNTAya91DWPjF6s9EWaSaMbmjVCCyow5Y\\/UYOMH6Vz17qN1HqM8lrFGo8goisQRuJ+6cE55\\/HnmpPBV7ZahqX2XUTNiQFpBuI7cDP41P4jvLTREFtaMzKGBCqoI25+8T3rzoU\\/Z1nS5bv8D0VP2lH2iehzN34ZsSUv9VukilZPNlt0Gec9scfhVmxEaNKy7YbUKG8s4BBx\\/np\\/PiqF3qLSal5n2hp2kbCH0xzhQfr3+tOjvLi5f5AoSE7Q87\\/AHcY2j8Suen4167p1pQXO\\/8AgehwxqUqb\\/dq36m5ALe1ZZL6GKYsw6LnAzkjHH91euPf3lFzb3NnE5wsbsRDGMFlAb0UZHeuJn1udcXLzASMMHI9fz\\/+vSP4hZWwtw6vKpQk8fLjkUv7OqS16k\\/X43sdtqsL3MytK4lXCIqRArgdeMZwcY5Pt68bC6g0E73F3O8byxny45MGPPfJHpweetec\\/wBqTXV\\/C5QRrEMpGWz8wIxk\\/kOOeD0zW9da7cyzKBC8EUa\\/vflLAc7ickHjriuatgZ2jFnRSxUXdo61pfNUNFdQ3O7J8xSE\\/AA9s5wPfnismO0eIlHikaKL1wCX9cd+P\\/r4pfD09rLLCm2KNFAdFjc8gdWYDjd+QB+uK30M9rc2witLK4XaEVJ4sOTjdliCcjpjOPwBNebNug3Ff5HbG1RanMyTXao92tvcSRRqQx25CEjqccD9KbHNBHGqQlGeNAyytHuCk85FdfPqstuj21\\/9hSBhtlt4lC9s4Gc5JPtWNJ4fN\\/dDUbZY7axYARxznDIB3I6\\/55xxmqeIi1+8Vl0d9H5ev4HNiMFzyTpu\\/wDW5zy6nPcSPvmkCoMCVEbf17HAHPvUb3TK8zNzGy\\/JJKTnrjoO9aGq+GksRLLpmJ4gR5+W2j347\\/8A165TU9U8iNrYkI7Nnpwo79T\\/AJzXp4eNOv8AwtjysTSnh9Jmb4hu1CN5cmSWwmSPlFYUN4MquGL4xgn9ar6teyz3W2M71zwFHFPtEkjTfOCjgcc5x+HSvqKNBU6aTPFnUvIuTCJlKGN3LLgYyAPX61p+HtVtrBhG4aNcYAUZP1\\/zmsG8u83K27NIkRxtIk79OlUtTuyZFRGbBUck5NV7D2keV9RwrSpy5onpmoy2mraYjkhTb4Zw4ByCePX0rBeO4j0d3lkRFhYLGQpDDIII9v8A9dUNG1xbGzZyQ0+woP3Y24xxkVmX13d6hdxPOdpIG3CEKOvp61jRw0qbceh11cUqiUnuad1ex6hbQgDYsK4A3jJwDkYHbnikih+aMrFCs80hCbB8yx5+8PcVXtoLhNUWVLVZ4g3yv\\/Cnt\\/8ArrVNoG1MeY6raM+7y0kxtz2\\/+tWzajotjJaq7EkvY1iWyso55JUC7ZVYDpnO49\\/vGodJ85ZZvtBZn3YdS\\/GMhcD2ANb8mlR2dja3lmVNtEx3qjkFyDnnJ6e3rWFeNJHqTM95FK7gPsgbIUHqCR35rOnUjO6iayi1Zskl06ZpZZIrZkYB4piW2rjqCM9fXP1qaM2xs3s31C28x495k2nMvIAx3z1474JqHU9RiiuZcvKIhGVyuQZAOPl4HB96rW7zzwweRKiCJlHzOducrycAZxjjvyavlk1qTzJPQn+w3bwalcwRyQtbgbwf4UKk+nXOPzpykposTiNA0hJYkDcB3P1I4pfEt9eKssr3KtHPIQwjPLgcAnHHpxUcqK+kNldqxqNpOfvEdffqacU3G7E2r2RhEoEc\\/vANxAx0we\\/50mjxSwapbzna20MY93QsOf8A69TPF5Spg5XnGSc4z0NTwTxLYgrGJGEeyNcZYdj09v510t6GFtSjJfyiVyYo2fzM5ZCSp6E81b3k3i3k+Zs7QDINqr3IGO+OKqXUCO63EIdpBhmVTnkt3JroJJRJorEll4AiMjfn1rObStZFwTd7i6XZBg0qPHJtkBVceu3\\/ABqpqlrGttdzySMzblAUDIxkjmtrwioNkVLqX3qoIPIJPT8sVU1xGUhGRl3liAMZYjOP1\\/lWKm\\/aNGziuS5zFonmuPtMghLcjCA5+nQf5FOxCYjKy5JYhQ+QeRwc1XMUnkCVmA5yqlsN9celTKBtDuyOZBhmIDHpnIPXNd7OJE2mQv5bMvzSfwD371JfJFuiZ4irsPmyTyaTR5xFdLhWdmHB\\/H\\/9dO1gMbnezAjnGecfhS6j6FUSKMsFZQRyFGduT+vanW75yHL4Ykl85IOPf8KpSofOG5Nm1ck4zuPvU8biWMks2RnIC88e9OwrlvamzzFVgnC8DvzjP15prgFSsZDH7ysq9e3P\\/wBemlizLlhKW4Unr0wBitTS9PWOVWv8RPtEkaZLZwQefbFTKSitSkr7Ghb3dxYJZ29vA6XlrM2C6BlZWHcH69x6Vq6hol0LNr50wn2lkLxqASpJ546EEGsie5WK0McsIxCCybRnll4\\/DJH416N4KkWPw7qmnaqr+RZyhg+cl1JJLD1+8SPbFeZi60qMVOK66+jf\\/BOqhBTk4s80tdQmF3NaTzlt4Pz45LDgZP8A3ya6HSI5dW+0aZdTF\\/NiLqGyeVVTkA57HA9xWV4iggfUJLmytppEDKwwnPIOc9u36V3fgWJJ722ukhAKWxyyDjYcZ4AyDgHj2p4mqo0edL\\/hwpRvOzK2hXFjZy2Oum7ZIbVvI++OkgccnjgE8mubu3mk8Sm2tpZS5MaosbHa4UZVgQfRveumWxso9em0C\\/gUgS7wUOFYMQwOD06EenIrXtoorXxBb2+nxRPYzKIftilTJCSPxyuDiuCeIVKTkldtfK26\\/X1OmFHnSXmcPqOi3P8AZLahczytLKuXJI5kbI5zwORt\\/D2rI1yxuYrZ2miMRF0M7\\/vghPlJ4AAIIx9BXoM\\/hSOOW4W+1ErDJtePcMbjgEn8Mk8D1PFXbTTi1nqK6mF1CUhZEGzLLGDge4+UfkfetYY9RXNv+G4pYa7shvwpvLW4017W63eVHPGFjCl9mRhm9gx5yOla3jfT9SsrllspmETR7GVxuQKxzuA7HJH5Vj\\/Du4sBNFCkQheRJIHldhtYZbDMOoxl\\/TtXp7afL5drL5VvKskaxqsnzINjZIIIPv75FeJjqzw2K5ls+h20IKpSs90eLWai01CSK5MXlOghuZN\\/LqF+XI+m0g+31qr4utbmfRJdy7lSbzoHVM5QLhgfxYfrXceKdA0qDV7fWFuXdYnLvCAANir\\/APEnP0rK8W2l6dRutL08ym2tiTEhH3d3VB6jGCM57V6eGxUZzhJduvl\\/X3HPVpPlaPGlcbiHGH9T2Pv0HrTnLgTywx\\/IG2BwvHX\\/AA5\\/GpdYgktruaJTuXkh+55I6\\/Sqmdq+XtRyCDlufTj0+lfRrXVHkvR2J0ZjcglXVm7Lg9PekkVFOwgtITtII5GePzpQwQ4aP72W37vXH9M8UFcMHDBg3XqMD1\\/DrQA6MbTsIwFAJVjyec8fpU0DMXYspAAyp3EZ4wOO+arXSFlUiTsN3r9OTz9fah1fLTK20LgZVz8rD8u3fpS3HcsIIYiDHcBzvOFJwAPXJ9T\\/AJ5qZbtJlcSuAGU\\/KXPyE54+p3Z7\\/wA6rRRI8bqFLMTwhUkj8vrVZCFcIs3JGCcEDnqOfxHvStcL2J2uQ0aRpEypIT855JGRjI7Yps8u8LCJCAQN5OeOOO\\/pSK4jlLoA3I6nHAFNhJ3s7qrSrxg8j3zxzTsANJGw3B\\/MJPy8YPPWmlDG6yJJEzcYxkkH\\/OD+FSW6IYWBXDZIBPJx1HaoZ4nTsFkUYbK5Puef500Jj2Zi24hkIyAQRgHAHWprUSq4ZyxHKnj8OhxxUEUMjqoKdFOTjuTg8GlgWR5ChG3OeemKGAt1EskSN0YZY5XpnHBPrzVN0aTJz8u0A85571o3DNISwMRAGFIxjA6jjpye\\/WqkoaBhDlXbhmkABOeOhyeKEwaJYZJYjtjb5lO7B6MDxz\\/LFTXECRRnzInXfGGjx0Yc5+n+cdaqSBUVd+QMB1bOevbvVkYeF4hcMTJgKqg4OPw+tDBEFxaZMjQ7lTAwOuPb3xUMUciRHcp4GcHuMcirGJVmDSEkjOBj0Hv26c1PbH7WhEmPM3AoCPu4Gef5fSi9gtdlS1jXCeYNqsSNyjHGOKmuIFkijkcliyEqf4jx3J6Y+naohG1sTK8aSQr8uTzyR\\/8ArrThPnAneN23Pl7QeB1IP4D3pN9RpdDECsqr83JPKk+g55qVImMQKOoKHCljzgnjHr9fetC4s443EchEny7yCOV7dPoP\\/r1nspG1YZSQ6\\/MyjHrkU07iasLdW7xSAI6Sqw3KwOMCmeVI6jH7wDqepB\\/wq40USGONo1iIG5mxknJPGaqSnyjsjLLydvI5FCYNCxbImLJnKrh2IzjnjH6VcgNvK6yhzECo4bJOe\\/NZ2JxgITuGAMA5Ga0NOSRJAZYpRGSQ2clWIx0HelIEy9NbmN2aORI48BFIfnOMj696IAys6TJIFkG0uehPqfxq60cZiMo8otkhFVT1J6jjt1qIrC9uPPmk8sqCARnBA9fzrG5tYq3TSC1lh3HyyVIJH32GRwfWs+R\\/MZ1cOc8\\/L65q+0gMbIRHJtx5bHv36VTZ1N3I0g4P8UGBxx7dauJDIFC5ILYbPUn\\/AAp0U43Da2zHRh68d6bnecMGJYYXHXrn86lt0ikn2TzG3IUc7d2eOcY7VUmkrsSNfTNXkV1CFgwQJg8A+pz2Na0koljk4SeOJdo+XGCB6fj1\\/wAK4x5CkjYlEm0jBHcY9K2NH1BFl8mR9ikYZuint3781yVcOn70UdNOu9mdJoXiC40acpbsJLUcsjnIzyCM9hkn8+9d5o\\/iywv7kXNzvDLEqTBgfljyThR6DJP415LcFWjU\\/vFjADbsZz1GM+v+FQ2l8+UikwsgPyuO3J6n868vF5TSxKcrWfc7qGPnSaXQ9l1VrXVdBF3EIo4oPtCwxRZMkxkO2NsY7ZJI5561zV1DcaCVgl8ydUYRiQKdxIUMenUDIGT3PPSs3wzrjwT2dmbxI7cPgM7Z2FiNzcDtjJ9a7zxfLpslncJayrO0m+R5mULInmDkgc5BwOn3eDXhOjUwlVUGrxk3\\/V\\/6v9x6PtYVY86dmjCW604I0McMk8Cq0hQTFXjO5fl2kcgr9Bls47DQsGFxdiQxx3lttCFzlCy56d853dyemc1wgY28zp5xVHzy2QScgHn68Y962dK1cRRTxqo2JbBlGcGHrnnoeuMfXit8RgZKN4a\\/1+f9bip4lN6nc22lrBdQ3MkJLgExbGX93yrLjJIP3h1Azzg07VLNoovtEYd5plQyKvynDZOMHpyD1yfmp0F1ZRfZp7i7cFYwMysGWROuCM5\\/L0NZOseLtJivJopIZBJIGaQCP5DjAyR16ZPNeDCNepUXKm7f5nVLEUYLWSKWoRv5TBWa4t2jILMM8c8jgYOSaox3E6ske7zVcgK8Zw3y5HB+oHHUYHereneJ7LUb8ukiiVfmdiqpG5GPlAOQRwO3OK6OysNDfS4jcWguZ0DlQMx8s5PygEAdvp7V21KssN7tWDFBKtrTZw19Ztb3MUk6uTIjIuwArgFjjj64\\/wAir0NpIIormzjkLJEZGlbJJA4XGDxznqMYrU1S\\/wBNu7c2cFvLCVny5VAW2cbxkZzjArOjL2E4mtA4IjYossf3kIXPAPHBJ4HRuldEas5wV1Z+ZEqcYy01K0V5DJfSzzxySuJAzlvlYH5dxwvA69OlVtT+y4EkduscEmeBIRkAYGBjjg\\/pW3qtvAzGWO38pXYHzMqFUtg7Wx1GT17YNZd\\/pZuId7BLNm+dd+fKd8E8HGOQO3c81pSqQbT2IqJxWpTtWghRoYGKddikA9e\\/Pv6c8itXStatYbdWdioMaoXblW29+c49T9fesy4h0y1MInmCySy7UiTJ2jJ+Y56cfj1pGlMWqfZwfO8tPvRoGwc9x78Z9On11nTjVWt+5EayjazR2lnBb6lpwnUgXSp5rBZMMu35uBn7uWH04rFl8RWdpbh5Gl2Ahy4wpAxuIbHJH1Hf24f4hvbbT9EinN6gmmILSIfmKjA6jPOMEj2Ned3s8lzPczRkyPsAkMq\\/KGBLAMOAd2V57bawwOCVe8p\\/DfQwxeOlSkow3PVrCfTNX08zWUgFu8hUyIpLBgck7SfyNRX1jJLKziRfLS3PCIThhgH0xuBBJ9h078x8PVi0pi11ftL5rZygJjBPIK8dh6ev0ro4\\/EFo0F2LYSTLwhkKhVlyMEA9+nUDsa5q1CdGs40rtL9f6\\/4B1UsVCdNOpoyS5gKmLztjb4sh3QHcucZJzz16f4U2TTvLulZFWUA+ZGRIDgbeOnIAIH049arW\\/iCynuv7N3xfbwqxiPHQ\\/NwCOOpzx2PvWN4g1i7Vvs6yTKkTjyljGT6n6\\/dPFVToVpSUdv8ALuVUxNOMeZamvOVeGKHybeJ1DbEDAOH5A29iMjpk8fSuPez1O7Mxgt1dS52ySLgb8bvTJwcDk9q6zwH4L1rxLrUN3Lb3CWuFW6eZtq7SOSncnrz7169beENA024ggVvMQkRqHbdl9mc89+9Y4jN6GXT9mnzS301t+JEMLLF2c\\/dXTzPnXTLHU4b95goBG4RHaSFJOGyO\\/wDFXc28qNEBDBJG46kDcB26fXBNezaj4H0a506G2dNkikkTAc8nOcDvmpbfQdPgt3t7eBHm2svmBQCAzE4z615OJ4oo4hKXJqjtw+A9jdJ6HjLWZ1CRGtrZ0mjYMVjY7GCk7mHucA47Z961dM0rUtRhuxBbRPbwxkMJhlUUZO0ZGc4B6Z6169baHYROrhInlChXLAfMcDGR+FUPEugX+ot5FnqMWn2zAcLHuJbOT6Y6c+tcP9vRqSUErLu7u36+htPDtK8Xdnjmu+G7qdopw6R2znKO7fKI2XjjnA\\/kR2qvZaNaW13cXOmb7oxAIyKhWOPhee3vjFd34g+HWuS6SsFtrCXFyqrE25dqrHuxkAcDjtj+lXfBvg7VPD0Xl39\\/FNbhWSaBUG1xzgj3r0XnFJYf3aqb2tqr\\/h\\/kZfVW5qy+Zy9npOkzxxrcRMPMKyMFG1QQCcn169\\/Wuos7XSrW+isrK3S4ud6tMeihT\\/XjP4129tpemraq0MNsWxwxXINVbyfTreWPeYUMrBU3Y59OPw4PtXg1M0dd8qT66XOuNKKa6Gf9jt7aaRUiWIOCpwdwwTUtzb2zRhQ7APglwMA9elTa1dxWWkvO+wOgHyg579M1h6b4k\\/tK+t9PQ+YVjLu5AAXpx+Fc1OFarH2i2W\\/yOlyS0JLiws7G5gVPMklf5QT1XJ449eCfwpNVjtrTTbq3tIpZr6KFpBDuGXyPcHn396PEGuWtlbuVuk83YcOozjBG4E+o4H41w1xba1r2oWup2EBDLbtAAHwX3MpbcxAyAFJGfXA9\\/SwuHnVSnVlZLq+r3+44sROW1M6nRLfRbbSJb25jWQxxZuUdd7K4UlhgdWGcce1ZSavv8UJaafZWttY3doXtJIzl\\/MXGcj0ww\\/WsuLTPEU2py2Nrc2MEdsA0qI5clmwAWxjHr1yc1f8ACvgq9sJLpUlVWdmML\\/eMMJb7ik4I68\\/1wK7ZU6FJTnUqXbWi16\\/5b9dNCU6rkna0V\\/X4mhHpesXEtuJrtGkifcsrP93KkEBQPf17Vuvpx062YzXjSojiTOwj515BHqR\\/SuL0yw1y48STQwPMYbeYxzTMQACD\\/CM16VBafaVaOWR3ijOUyctx649a4MfN0nFOSa30R0U1GSatoczFpusXd9LqTQSKrKFKynAbaDgjJ4znmrOLYM2k6Zd20F9IjGQqvMfHGPTrW1dMloIkurpFgZ1iRAcMXPIGf89qo21lZTXbS2gZZPnbcw+9gFRk+xrmWIc1eWiW1lp5XvuSnCCsmZc+hvZW6Lqt2ssaICJdgLg8ZGTzyf51S\\/tyNdPSeys5LxWf5lQh\\/M3NwxAOe2ax\\/Emh614h1NzpesRNGzgujSH5cdVI7c4\\/SpNN8DXukS2lm+r7SZGBaBPmReozk4xXqxp0PZp1qqct7Wa\\/L+uxlKVZytFaGpda5ZWLyIgWCZOPKMYGNwGN3tjB\\/EVV1FrjX7Wa0fTZWeaN4zKLc4i7ZGRzkknHf8K2bPSPC9jcT3epxwGSaRQsszgNI+Bzg+wH5VNqnjHTdPv0gsTHNsZVnHJZCegHr1rnjU95fV6bcl1en9a9wmoyb52rmD4I8GWNnp1qfJETQ4QgHAwDySPU8\\/mc1sWaqs93Z2kAt9NSIEMg+ZpWYlj9B1\\/GugE0VzqFuGjUQzKWG3+Ecfe9yCPyNVfE9n\\/xL3FndxWqRjzHlJARSOx71yzxtSvV\\/evWX3LX8zaNOEI6dDl7zTtL1iO2aS9vYLW3gDS7W+eQ4BBLHpx1A7msLxdo9lJd28Omw3s4NtJNv8xcYi2r0445H58Z5rd13VrfTvDjzalepMHeOGNrdCElDHA2k8HrzjPSs7Qbdjp8M+r+UJZF8uOH5Q0m4qdoJA7YA9t3pXrYeVWnH2rbsm0l3\\/BN+f6HHKUb8sX6lGx1TxPe6FtsEeKBGVNyplkAHXgZOMhvft1qlqE322X7fqVs8QMSIsQPUru+dhjgkscj0Ar0mw1cWWmyW76LHaNDgHYyiPbkjOc+gz+H0rntUudK1QSJDHJtHIZFwp9we\\/Wiji37R2pcqvuvM0lSjOPuS1OE1bVtRVPI09oobbaBtYkDBOOg71zgNvYWoRnUSMcsxGWJrZ8SI9lFNdK0flRnBDfexXnWs30moTNKHWOMAtlzg469O1fYZZhVWj7ui6+vmeBinKD9\\/cdrN\\/NNe+RDcArn5mHbn+mKqpLIvJZgCOSOvX\\/69Ns4S+XEJXHOW4J+g4pb6aOyxH5hDJy+MYJPQZ9q+kjCEFyI8xz6j3eKKRjI8Q47dQPWqrXbiJmBMant\\/EMf1rGe4MskjOdozk554xT\\/ADFC+UqKcDJYHpWvsX1MHUbLkmoExgtmZ+cbl5\\/Wnw3skxAeaOCPG3AwF6+nes+3tZ3kDMHEZ\\/iI6f5\\/pViKO2ifMkhfbkjPQenFEoQWiJTd9TtIL3SbLTwlmWmuZE3OwcgZI4GOvfpntWQ9+ZkKyGRmK\\/O\\/3sH2z2xnj39qw3u0hLvC5Oc84HygdqqPqVxKELHanJPGMVhSwKi29\\/U6qmObSilZLsa9zqBLIqqy7CAI+reueO5Pb3qE6reTSLGHZgz5+diwI54x04B\\/Ss2GRLqZIURmZj1+6M\\/5zWutoLS2PlRLJ1AYc4rpdOEVZrUzjOc9Uxs0KbJGmu0bjgL8oB+grOWODYZUkJYE4Lc47dulQXLSMrbiuR0A+ta1na7rGOdzEWkXaG4+U57nntkdqpLkWrJvzO1h1jdzqhhmk3puztZucgdvQ9OcV1PhaRBMwmhaUNErpExy8mPl4z6Dn8Kz9J0+GC4AEavNKmUk3EIpHJOT7A447VpaRG8E4ltppXG\\/AbJUuOmO3HbH+R5uMlCcZJHdh1KLTZ2dlexpb4iiCsx2fKo4B4IzjqeK111ZI53TiOdeAqxg8kYABOOQO\\/bNcxZ32yzeCZoxIOckknPOffnGPas2bUREzpI4KMuMrydx7Ljp+NfNPA+1k1Y9hYnlS1NnVdUFw8ccStICjM7DGCcnHI5xwD61RfV7qESO7BsgbA6llTHcZJxms241GBFDbs5UbYxwR\\/P3\\/EVgXOqzSzfIX54DZx+X\\/wCuvTw+XcytbQ5auNcep2dp4omctkjb0JI4Prx27+lct4r0uG4gbUDqSmQ8pCo7H1x+NZianEJfnjaXBPyKeCB3rq9KutITR2urqNYD0Jdtwz7DrXT9V+pyVSmvuMpVli48lR7fgeWXkc1q+JYShYZXJ7fSoHmkclpG+Yj0BrrtevtAurwSASuFX5WUcn\\/AVkmKymCx21oVkPdup\\/DoPpXvUqrlFOUbM8Orh1GTUZJoxHUucqSSeRx3pwicDJVstyGx0FekWHhLT47aNpSs8kgyQWyuMcdPftWbrQaaYQx2ot44yzKicZ9CT3\\/Cso46M5csUVLCTpx5pnFxRSO22MMxznJ4x+dTXEjKVhgnDucBiM5J9c1alu5GdoSIizHGVHQflUMDxAEQs2QMBmQbjn6f4103b1aOZgktxbW4gMz7SxJVfmAPoeaniuGjuVbzmcKxJJHB+gqrOwCofOPThUX35zSwnzmKxk7FOSXbJP4f\\/WpON1cm7Na+1bz4UtsbVB5CnH0FU5buDT4lit5HMh+ZwvQH0z+VQsxVU8p2ViMFsYGPX2qrHHA0pcykxqc\\/MPvHvUwpxS8i\\/aS3Fle5uZUlkEznkLznB6\\/lV61dYTGGQsGQERsxIdySNx9AB\\/Sqyyy+eiFPKQj5Rx0PcipZLpp7jesYeRR99gAVx0\\/\\/AFCtH2sNS7nQ3hLaQlqnlzSeYJMgcKMZKjjpwPxqjqN7Gtu8TOVUH5RjqcdM\\/gKfDNHBZIVikjLgKrfdz6856f41hXlwCzo5RvXHf\\/69Y0ldlSqtkM8spcySuRnkjPU\\/StLRZ5p7C4t12huAGxjA6Y49fr2rFkVvvdAeQD1rV06JobSOVnwHBZVJ4OO5\\/wA9q3mlyip7m9cfZtO0UQ+YGu1cB1c\\/KB1LA8Z7dKdJMmoaTZsUO5vlGDgdcHH6VlR2d1dSNLNuVZUJVmJYkf5zVjTPtEVh5KriKOY\\/vc+uMDHX1rmcUtb6nUpPbodF4enMccaCNjI7lvl4CnGcn9KTV1nutYSXcAUjkKrj7p6\\/0zUGjXC212sLDaF3PjBOA2MGpZJJbi\\/laJuDE52E9AcD8KwtabZre8UjjJQy7JFlhmJj4Mbcr9e4pGkVnBVFVXyQM55\\/z3qBgDz5jDgcE9PQU+OIpJtkEiSfwnbgN\\/8AWx\\/KvTPPLlrmJDIcCPO0sB3A6Z+hq7ZW0t9rcFtcROyNtLADGI+Pm\\/Ksy7tpovmKNjA+8uf\\/ANVbfgRJpPEUEMZQllYEMOGGMkfpWdWXLBy7I0pq80jd8YeEZrSzk1GBQ1nEgaJ9pCtyAVH+fWuKEmyPYWPLDCYHbg\\/rXs+tWt5caJqWm3lw8sSRF40VfkXoc\\/WvLotOt00+CW5BLTjfu3AOh7YHTHGef0rjwGIdSm+Z3aN8VS5J6DPDFvbXWosJUKpEhkG1cjI6Z9RXSXtjH\\/alsskZNu8Jw5XiNDgY49s4rA8KbLTWIXkmQq4YRBT8znkDvxg8812VxYicOzySuQvmMrOSADwe\\/PIP4EUYmfLPfoOirx2MGW0xqt1aLd2yTKXIkMjFWAIKjgEYwK9Q0VdQ1TwxMtlJC7GIHy9uHZCgzkEdyOucjB9a5jwhZ2x1LbEY1CMjssoz1Qqc\\/icit3w34li0uU2jRvHGjNDMUXBVCeGQ9dw44I715WPnUqxtTV3GzOvDxjB3k9GVtJgvWsdOZbR9NngRllusBgwL\\/KMewAqCyu7rwh4sW+uHC2t3M\\/IGfLydoOD06Ka9KM+m\\/wDCMSpplzHfmVN0EkgGWUg4zx2xXLr4c1ZGgk1iKG4cXS\\/Z4slgkZBLKcgAjgHPvXDRxinKUaqsndW6vd9ezN6lGyTh0NnXrbS4tXmvbuO2ZLpN3mfeydoBX+R\\/Gqn\\/AAj9vZJbTCaNLKZCzxR8SK5Q4wP945Nd7faZpVxpllcWdjbxKqupEaABc8EY9c\\/jxVDxBZ299JZ3M0TvKIQFaN8DJK9R3xuryliWuRK\\/VP5HXGHxHJPosXifSbd3LJcWMZilhZDuTnsR\\/Osrw3F\\/wjF\\/O915tzG9uqBYkz8pHJOfcr09K7XTBPBqV1ZQzvI1ycfdIJOSP5AVR0qNpPGs1u7Q7IoTBt6nICsPp1NdlDEyUJ05axtf5GFWn70ZI87kuJLDxJDfKpgtrVw3kEgDy3OcqPr1+tegW2vJdyw2dnLbvYXCtcQsQxdGUgSAADGOQevOeAKxPi5oVvc+HDqu6QPBbsVMJAPRiB6Y+Yce3asTwQ5g0vTkcCQFJML3YcAjjoTxXfPkxFCNV7rQwV4VHBddTo9Sjur9bddqtFHv3uYypPylQCM9OT+Vals22+u9Y82JYnOGjZvmViCFGMYxx\\/L8LVlDol5oltflJJ4LzDKN5U\\/0I6Y\\/CsOGzf8AtOew0uAyxr87b2LABN2M99xGPzrn5oT92OlrlJTWr8jxrx\\/EYPFM4RgAvMeRknJ9KwvPwBtRVb+8T1OfSuz+LNlc2\\/iZIrmGAwSxuYnUnLYA4z9CK4iFQXjwpkIIL7hwPb9DX1WElz0IS8jy665akkTh9sLKXkP8eeABlT\\/9b9OaazAENuOWX5doA79CB7GlukWV2dLeJVyG2oSRz0UHv61EqtAOREdpIx2BGBkg9utbmRPtOI3Jw7MQRn7o7nn6+9RuEUb5Fl2jgHsSBz7d6eoZ0DoFGSQG56nH6UkhOFxtxGcYOM9f\\/wBVAEB8xtxTlxgcHjhR6dORToIZXTcifvE5Kg4wPX6Zq3HLcn95bMcYCfcHrk9vWknaaed2kdw8nykZz15HHXr2pXCxVZ1UqUU5z1ByPTv+FPgWHzw5MgXOCAOvI49u9Wb2zktnaGQlGCj5gG7\\/AIZ9vc5qnHKwZYgHCrkNIew6nHtT32DYmeGUzs8b741IA2jGSen8xUWE53o4w3O45IH9KtDzPNxFLsZjtBYHB\\/IH04\\/+tVho90\\/leVEXGMuXAOcdz\\/ntSvYdrlB4mhYDY8UciYJ7dKsRCDYu2dllbKrk45OPy\\/Hjmq0NvGEV0KGMSBCzE88Z6fn39KuKpS4V7dopFUEn5M8ntj+lJgiNZfssckSKFR15BGRyc59+g96pTxq4eQYZiwYk8Y+gAq9cRiKVVeXcGwjgL83169ef\\/wBdU43QKXj34JJDNgZJPHFNCZZtmij2i6Eu9iFbBBDKAB+fH60S2yMzx4\\/eZwAY9pKgdvyFW2h+1IJLkBCEJyvDfxZGB168fh71CsUxCSurs0a7Yzu4Uccd8kcUrjKtpHeSwyMMSBTiWPGTtzk8H+lTAzWzSbZGCMvzhuTjHHHB7+3StJbBokkd5DbllyTHkB+CemPXt0qtFa7yweWOQE+Yqk4ZugOSfpxmp50x2sU2H2hiPM27QuVY4Lnr+XBrRt7dJre4ujAogjRdjK2Mc9fXt2GM10M+laGdMuLcSTHUGt0n2JykTBeQD+JyPUCsfU7i90o\\/YZrVIFXjLchgSeC3IJODwKxdbm0ihppPUybtWGyIwuhdV2Z7Ajp9M5\\/yartaG2uFkJAjyGLEd89Pr\\/Src10sqtch0+ZNuwHlAfT9amDQvcIj7wkigZYZLAYxg\\/Wt4vQWjIVMU8SyAOhjGIht+Ut15\\/CoIbImRzKMIHYEgknPQAetbVkLW3tTvjSQFgGwVGQPwP6VbvfDs12sd1YxNO8q\\/Ikhw6DJPb7xwvWs51FFb2HySktDn794oTHJGMMB80mSdx6EZ7etZMt7PvxA0nIJyTlV6c\\/oau6rZX1qpknhchV2\\/MhIBJyQM96rRwSRsQYSVdFZUIIBPvx7dKIWtd6mElK+pd0uabLSzREAKAGxgtz1Ge3FXZQFkQBccbRluoPXjt+J7Vi297JLdHKg8FT5ijjBHHHP\\/wBerkV4LtWUfJGH+UkYJ\\/Lr+PSrs29UaQlpYtTxTSMZTI8j7MFgmATnJPHJ\\/lTI1iMKvJAWZQTnIIIJzzQZLq2iUxqrIo2uuDgj0OOKRbpTG0eFCICoJyoAwBj9KVmaaFJtiFmKb0cgggn5f8+9Nt4I57xY9+7ccAE42\\/Wlmffzjjge5qBY5Mlgh3DlTjmtHe2hBp65p1rYSRG3meTcAuSh2Z9QRwazYpT537wNtYnIHPPFSulyzLHKZFCnPl7jgE9\\/rimPA6zBVBGM9\\/5elZ0k4xtJ3fcqWrukaVtcuEeMlnjC5ALEY\\/A8cVWmaSJ2Eo5J5wc+1SWBVH2T\\/KjHDLnqO2ce+PyFOv450d4JEKMRuOR+fNCtcrWwxbgoMqSUUjgcVs2Hia8SHyJ5ZJEjOFB575xXO2sbJKTtwTyDUm2Q7mYbscc8VFSjTnpJXKhVnHVM3rq\\/jumjmjXy5sfMinABz1wasWWoedMkk6oxyB07AdMfXn8K5tvNiZsJIDnKsRjAx\\/8AXqSK+kU72Vsg5ye54JrGeGUo2RtGu07s9C1LUpLm3W1a4giiZmVZGHPJOc\\/3sc1zOpXjWwk8mR5BKRLNckD733SBxzgtn\\/DvVtIm1d\\/IjhSZ+TDH6n0\\/mf8A9daGoeHtYjiUh0t4bhwkm9wMNgfKR9ARj2rzKeHp4eSg2vT+v+GuOrCdT34oo6O1jo\\/imH7XGbiFUV40BwC\\/Trn1H5V3PirxQY1t0CeSrcrnkjA6e3BrzqfTLizc30byyRowTIG7a\\/UY9vepdYn1OQQT3NuqxmMhSxBXJXggduBnnvWmIwVPEVYTk72Vt\\/0NaWKq4em4RVrnc6dMZtOinJjlhWXrvIKnr+vt3HvWjpdzLPfQOFCfdYliHHHbnpkZGPbNefWms3FtpzIkYO4oAAQzscevHOOKlhvNdkt5LdomjDnKnaS5xt469enfvXFVy6TctkdEcc9krnotn4h0CGW9hvC9xFsC+Y+GUNkFG9+Rt4xx265wNR1MajZrp1rdHbazoTHID8qHpkjgjjnA4\\/Wp9H8KQzWTSalem3SbbIxKDdtI4xjoc11Jfwo+vzzyRQLbtbKPKChVTa24k\\/XIFeTKdChN8ilJr7rqy\\/G727HQ4Vq0F7RpI5DRvDmpa7aJrVq9tFPbyOUickSOxUBiuRgryMZ5GMZplzpmvPpl3H9hvbQ20im4klt9gAHJALcE\\/J79fz2fE\\/jd7y9a2imiM1seDAxAwcYHHuW596W78V2tzpSw3mrXD3oty7DiODucYxyzA4J75roU8b7spU1ZvRatpfqvUxVOgtFIk8MeB9J8QaJBLq+ryWU8oZrRAylzH8ytuyOPmIxjHUU7Tvh9YXeq38Vpez3UMCNLKbcDqVZgr5J5JyMfSuK8M65bPJNfyGaORmZIolIcEHOFA9Bls\\/UD1r074f317HCWjndbi4Qhok++542lh6465yfU1jmKxuEU5Ko9dl0XV+enfudGEhh67uoq5j6L4Um1dluby9Sy0u3D+XJKdyyMqjIUZ5Ixn6L3rnfEdhruj+KLPSYrKW4aZMW0mMQyhsBSuRwwbIOemfxrY1vW4pL6LTLlX+z25BVR025J3Ef3jlvzNdlpwgv72w88w3ttbyKtqyZaRWZQc98YYE1g8VXwz9pUV4tPTt2d+rfW9vLY0+o0qt1F2aZwXgvwlf6PcTSXokkv7hnVlEPAVSVbB9AQee5Ar1vwnomgWV6kmrRQXd7Lbq5EkONnJyenbOPxrM8aatpcJTU5tVkvrqC1aCGOKDO7ewB698qOOO3rWXO9lqFtHKbu9hZhGuTtUJkjJbnIOCOOeT7V5mLr4jMIc9RuPNo7J\\/ctnY7MPGnQXLBJ2PWLvUNOstLllSRLaAxiMShSMDoP0rBtZUAutXhvReSbB5EGwnbhSCy56k\\/5NcpdXd5pX\\/EsudVF1BKmVWJA5QcZ+g6eppPCOtQIIJLFbh4Iyba7aU5LEZwfqCP5j0rxoZa6dKUou9\\/xXz1V7WO11abqK+5a1Txt4llDN\\/Zc6pDgO8aHCndtH15NVdB8WeKZwJQ22F5d7CZCPk9Ae\\/AzWzdavcRavHvle3gVMsgIHyscZYEds04zWGoXcnnXcF0M+WIwpHzZz0456d8Y\\/GuhexjTt7BW+b\\/r7yuVt6Sf4Fu48UmXTRdWE8c5gy8zxpkEY6YPPbt6Uzw74httfla+E5tktwT5UzFRvJ7+x\\/qK5e91Wy0CK5ieVYpeCzRAEbjzjkc4B7nPFUbO+tYvCknlLCgffJChRScqoxuOTnJwAByOKpZbB03yxau0k\\/J7mVStJStc2PFPxOsU8Qro32u6t5Fc5lt1yAw3AxufwU5xUaa7r+t3NhBPFLZvIGz5ZUkAKcnr1xnr+HNcFrNtNY+Oln1pYDezaeZY4Nx2p8hUMWwASW5HXOecYrt\\/EXnxWelEyWzXUltHaGCByHEzknAHYFeuOn4V6NTAYXDxpRoxV2t3rrZ7abfhocOHrzlzOb0T\\/q5Ld+ObzS9GFpbTJLqEfEqIu\\/ndjCnjJrdvtZ8RR+H31qXSYGVLbepT\\/WJgDPykZIGXOOuB7muXvNE0vThDqGYUucI0ttIcMqsQvmYJzneTVjVtZvZNZltNPT+1bZrUI87koRLlgcgd8E9v7vpmuSWGoTcXSgt223p2uui9N\\/K5vU5pfa12K3hfXTrGsT6zreoJ9g8lXijYjb5mDyF75Xk\\/lUT6tLF4ov7PT3hW2iKSR7QFESsvzb2HX7pIB7bfWsyXwVrscSxxLb23V4Yo5CBAnZRyTkCuo8IeFbOx0OZLxYy\\/m7JDhlYDcGwhI7bjjHvXVXlg6SdSMrp2Sitl5+v5mWHjiOZKorW6jp9UsZtQjhuLcyIZVA8wqn3gMsRju2f1\\/HSNxcQyrZGBxDICzKoBQDgZGOSTTbubwU5jawktri58seXuJZc7sAlRg4z\\/AI1Z0jWr7UNC+2TaXFHeRu0YRj5ayMpxhCcnHI\\/zmvLqawUowaW3vaa9Gkd1OrBtpszdEkiSC8ZPKtWuJwAUbkEHue+cHr0zxWy9+DayOJZhMMoojO4FcZJJHXtV23t0SMTNZojMg\\/dkBgp7\\/jz1ri9Uvde0aS\\/mhsjdFmMhPmARgktuAxzjlQAO5qIRWKqO2\\/m16bjqc1OPka9vqK2lnFDA7wG6l580YZyeS5z+n4Vprq7Wlgwtl8nyDw7HceuATz6+teYDxLqWo6loqxWP7q0YjyXQgk4xlmOc8884612UUOp3MzC8hjt45QpxHJyGGW2tj+8P0FdOKwCp29rbXV6+f46E0aznF2RLPbz6rLHcvPLMbe6ScmI5U5QooGepyN2eBz3xVvxBpWs2fh+aCy1dbe4dxI2UORnkKozyOO5qlrGqTaFMl3awNMrSgNsBLMT1CiqWvX2saxdW0EBnt0juFlkUAMJFCgHJ9ucfUccVEKdWcoSVlBa626eQpJK8WrlzwDY6zZQzvc6hGZbsl95X5\\/MPGc98D9a7XSdPvlu\\/tN5Pb7tpOyNcDknJz78Vz8Hl28ULQQzsy\\/KrH5lXucc\\/XnFbN9qZ0+23bBsccuRuVB6+tedjZ1K1RuKV5eSOqFKEIrTYoa74MtdTtmOpXcCMJxK9wFG7gnAye2D09hWe3hvw\\/p+twajo9\\/C8yMu4FxLu9R9TWrpV9HqcbxLdecCS4Vl+UqMDj15NcoJ5rK+SazsEW1mnNrB5h8sM4Yq3PUYKnn0zjNb4b6zLmpym1bpolr6+n4GdT2UdbI7ya6soGLoFWaRiXGOEHOWx+X5iuA1jxpNqOialp1tYXF7cXUTR2dusWFYFcAk8HAOSTngfq+3vPEd5HbWqOtpMrO0hkXBcqxCjI65wQB9DWnd366Opt4NQS7jRcWxKrvD9Coz0B29cn+taUMNChJcy55brV9H3S\\/Xa+phWlKatsmctovh\\/V7OCO+1OWOV4blbiGwjlDrCu45K85yAwHGO9bl5pd5PeWWo2es6arwRAG2WIsgOMLh+3GR046iprbUNJt7mfWMLFNJGC8MijDJyPkU9MsRn6GvPviNrMVpfWNt4fiaOR7xIVMTFbcoFyTkHOeRzx0NenRjiMbX5dnrrZW21X\\/B3ZyTcaUG3\\/AMEtah4nuIr27sNYupIGgdo1CkOzMcgnjtyCD71ydv471KANE0izBuBvO0DHHH6Vc8cyTDU7i9NjJDBKixqyxKM7ThnI9zkdeQAe9cBJe2z3MaywyqhJZs9D6fQfhX1GX5fQq0+ZwvdLto7Hk4vE1aU7RdjX1vUdT1C0ZrhysDLkbj9\\/0I74\\/pWEJI4I2cuHkfGNy5BAzz04onv7k3JlljQIPlyeW\\/D8qyr++ZjKdxOTxxwK+gw9BxjyJJLyPIrV5Td2yxPqEzqXmysWfk7bjVciG5ZWd2JUcgngmoCtxdhQykYOCc9P\\/rVZgtWEhU5wnQ45J\\/pXYoxitNyIqT1Zt6ZodndwAz3iW20bW3FeOuMc\\/Tr+GaTU7XSNLtnW1kiu5SwDPjjj0rOe6lYZUDEQAO7JyeOO3+RVTUZ3MaxyHexOeDjk1zqjUc9ZO3Y3nUhGOkde4+e7klGVcvkcqAPzNZjyyPIQ3r2\\/QVYkuQg8oqGJ78fl\\/Koks7qeNWWFdhyRziuyCUFrocTbbA280sWBGwQcsepqxHaWojBkczMCRhXx+FbEMUUAIMkatjJXOQePXFZ14bdlCxwkBiOYyODnjtWarObshNWJ4rowLlU2IvK7Rgd63rLWYE0mWMwK8hO8HHOR0rlpLi4VfJK+WsY2jIGAR0FU7e4mbPlswJ\\/1hPWolhlUWprSrSpu6N2KOSW9Em8OZFzIVU8Lnn3FbloIftVnZMm5UIaRA+SPlznvx7Vz1pbSujNFIVYnBJ46+\\/bpiuo0UquIV8tpQm07gADnaP5VlidI6HXR1ZLfXGYVSO3ZLqSYqiAMSnQkDsSR79\\/TitW5jk8hdiRqUjXITO4vxk46AdeOetJZpHHtErGR\\/L+R1Y4iyAOg5Y9sn0qO\\/lEJRizGLAVRgA5B5OeT\\/wDqryX70lFLY79k2zJ8+SK2+zsWPzBmL4IfnpjsKqvM4V8ycDJOO3oPSpr26WWPayqAGztQZx0H+c1Rv54J5FSPYFT5fUH\\/ADx+VelSp+Rx1J+ZXMyuz53Mpychc\\/Wq880TBxGGXAG7Hp\\/SmysEBQKVYr83J9+B6CokVT1JVB\\/fPf6V2Rikcrk2RySiTaV6AYVc+lSSGV5U+0OzjqqE4GBmnojIskqsqsp9M\\/l+dQyHczIseDtGAw9j+NXZMm7QXVukVqszMhZidsIOTj1OOn\\/1qrWsrJcNN5oAPZeMfhS+WSxO9m5OB0AHeoXR5JAUw3GABwMfh1q0tLMm9nc6zTfE\\/wBitxA8ZlXBAQYOPxqex1a3uP8AS5oFVR8vlg5OD79a49kAYRsV4HQcVasHaO4R2UqByvzYxjFc0sLT1aWrOiOJnonsb2saTp0dpNd2vmZPzF36A+gri5p2DlIHcICc812eoXS3+mfZ0uVWRyFDMOAM88jtWbpWhWchd2n8zaNyjbyff6UUJ+zi+cjEUuea5Ec9M4KoiKRjgZ61ZgWUJlopCJG+YjjIFdpbaBbwlpDGJZCgO6R+APpUes2lnJAxS6SSbYAoj+6n0xVfWYydkiXgpKN2cddXsZPlKg8sAALjgUkDhdsspEcQbdgJ94jtXR6V4WUWxlufMDsDg549jj\\/GubFr\\/prpIzyIj7Rj5t361tGcJXS6GE6UoJOXUsTtDe3DBweVyGTg\\/lWlZ2qW6hgWeV1OxNw+U9i2Rz0qvGkikjZIgUgBSoG0D3\\/Kr9pFBJC9\\/cLJIqyZEYIzk9znPp\\/WspuystjNajdet7m5ljYvt2D7z4UH\\/d55+tc\\/PZyRMTcDYuMqwXOf610JBO2ffKVdiqiRgxznt7fh+NRanPHEfLURLjqQvLMOmPQClSnKNooZz99bhUSZAyxkAYPXNW5rkPbW9udkYiAUk9R3P405t0sS+ZNuydzHrg+wqlfRSKzSMyHG3kY5yD\\/hXQve0Y9Vsamm68ttehpAzRhNgPHy+hFadktxcAs+Ht7gO+AMANnP\\/wBauMOTz+tdT4Qv4kuo0YszBduM8k9QB+X61NWmormibUp3dmdLpZMck8tyiB5V8uJBlsbcdeMDgVmi5MBleZC0hO1dhxheevp1J\\/KraSQMsJ2K2yQ5YNnnn9eaj+xiCH50V2mPmcjuCePpxXIrXdzpfkcUVXABWTBPJPb19e1TPMI\\/mR5ic\\/xHBx0Xk9RUbx+UQJYZBIV3gtHw+T744xWvp\\/hvWb+3+2wRILYDO+SdFAGcH7x4\\/KvSOAqXuoGcLEgYKpyGzyRxjI6ZFTeGb2XTdVtb5GIMb\\/Ng9jkH9M1Bc2stncPDIYz5Z+fYQw46\\/MOPyqG3YFh82Sv8X+FTKKlFxZSk00z6G1y0WPQLjUpZAH8k7kzt38EcY61wGpaHLqHhu1uFENtbzBsDycbGVemc5I+9XbLdSXOnwWd2UlmNiGJOfmdgM\\/qp496RbWW88HwwyIEeKV9kIGdrZY8+nH86+VwuInh5cr7\\/AIWZ7VelGrG\\/keQ\\/2fBBMt\\/HMizQgs0fABZRjg\\/nxXbaRFqMsrwTQrLLLasQIQSQCQR0z\\/Sr82gRXuiXvzqLq0uRtCEDYT8y5PuK6r4QNYNptpHeMkmo2ErxKxHzAZI2njkda68fjF7F1Iq9tP8AL5HPhqLU+V9SbVbbS\\/DbJNawwRRvCAyxtuGcDGc1x2sveJq0q2PkF79laN9nGX24B5PTAHHGO1dpqzxXkF1b3SL5UbzW7uozyrjaMnpxgZ6VWFvBqelRX9tbsPKeJQACCACeOAOOePoK8nD13SfNJX6N\\/ijtnTU1ZM53wFLcaVqSWU+5bmHKzwMcHdxjB6Ecnj\\/ar2G91lYtJs7\\/AFBYLcKiCdhn92p4J5A74\\/MV4n8Q4xoetXc0Wo3M0u2Py8x5B6Z7c9QMn1rfsL5db8Aadpd5MXl3mKbcQWC7SSD68CunE0IYl06\\/d\\/oY05OmpQ\\/rc9FuhHq3huaa3vT5DXbqWj6HadvH4iobi+B061fTIZpHEIT5UyUAwrDHqGHT\\/Csmx1KKxtJLGRnSwmUSJKv3g3qR2B9f0rqvDWqaXJZHTfOQzRHzUIOS27BOO\\/1rxcRSnThz2uk216PudlOacreRg6qk2lazp1\\/FDdRLdLGCvOAQxDc9iRs4+vvW7pdvatf7mhSKeadmQHgsdjbs8c8Anml8X+RIunrKBsW4HJPbemf0zS+IZ7HSNW0m62R7DcSRu5PAVom79jkCojJ1ElbVpjl7tmZMOnWupW2raPMoEUluwToVP3lJH4gH8a848Hy3qs1jcWKCJJdi3RjLhA2dvfA6enau2lvptMvBNbB5rSKWSESdtj4YEH2yPyrkfDuu6doupXlne6kbdl2vEW5E6ZJX5umcH1r1ME5qjPl120\\/BmFaK9pG+h2viSdJdBju7aOTg4ldIjsBGQx44Azmsj4Uut3bzsE8qctNzkb5NsrZOepyK3vB15p+q2l\\/ZpLuhBJZUbOY2YvuHp98\\/lXO6PCkN3ZxWTXCvHcFo2jiJYK\\/L+23cTjPPPTisaMHDnpLvf5alTfMlJnOfEGK01GDTLq4UxwQSeSrMOPl3IQfY7V+hFeU6jZpZXMtumWjd\\/lc9GHQEfTmvc\\/idZXl54UYROgFs7yBRHyxDdvxOa8X8TQ3sEdlHPKJ45YFmUnnaGz09O1fSZXVTpcr3u\\/8AM83Fw97mMaCWRZxl1HpgA8ZxgYrpfAGiLrniez0yZpJo5VZnP3SQFLfKTn0\\/nXM2kfzux6oM\\/NnJ9unXj867n4W309l4tt2cKgCsqsVOAWVsA+5\\/rXoV5ctOTXY5aSvJJkGueGbTT\\/FVnpHmXKmSbZOWYDCkgccehP50fErwtbeGZrKOxu5Lq3uVIdiQDvBHBxweCPyrc+IkKXHiixcMd8KCaRc5Ytv5B+vbFanje0GteFVkZYpZhcKkTICT7nH4VwfW5c9N30Z1exTjLTY8mjYSW5CkCTqcjGwLgZHb1qxGwjST7QzRKFDRvgE9tvT2z9P57fh3wtNqWp\\/Z\\/PW2YRuZGVB8uOB8uRnOOv0rI1PTrix1GZI3EixTmIOEyHCkjp0JyD9OPau5VacpOKepy8rS5iOeP5d5Ja3YmNGZTnkZBb0+6T09agnJkjKbUCg7iyPy34euO1aELWsaTLKXBCjB4ChgDxj9P8nNYQKHBlSAqOCB+GCM9Ov51d7biYit5Eayqy43HLMvCjGB7H6+n41IJ4rmIKFWQ4HmPjcThsL6dh\\/OpJCplCvb+bF0EsgAyd3f0HT8BVNpJVnkktoC7yfeVOQv0P0GajmTFexanslebZFIjRRlueFCnjjHfsc1GqoWGGSJgcBgvPB5OAOT\\/iKrTbnwc44wGYYwOcdKfZKYS+yFt0Yz5jEEbsj\\/AOvQnZasOYgvDMLkwlScjKMFHU88kVci0+d4Nwh2kuq7sY2nPJJ74z06\\/lU1ofskv+m3CszPuUhc4z6ZPt+tV57yOBS00s5LnKhQCM5449KHU6IV11J5VFg6iBjcHpgDjp145qK\\/1K\\/VFkV0tyMhFKhT16j2qLQ9Tgg160vriSchJAXkX5guBwcegPPWu18Ua7o+tmaLWdPjEK7Ut7l49rMSCcZ4K85\\/A5rKUpKaTjcTba0KHgHUrezNzqGpQyvKV2xK4LK6MOeAOc\\/XtWNry3EetT6po9oyQxZZxkLsOG5Cn2weM89K6aNbu51SWddTNt4ftnbbLGQ2wmMAKAc4xkY68iq13No0dvJBpT3L3NsmHlkkB89CpwMduD2H6ioi0pt23+4m1zO8PTavbxpdx2oeSeFnuMtkyQ4xnHQcsOPx6VD4g1NdX0KdyrCaOTGwEn5znoB153c\\/Wug8MSahBphtZdFSVZQBJIJAGYHG78wO1avhXwnbxX9xfXFmsQlnKxQnb91uR16d656uJp0m5y3W1up2UsNOo0rWPKIbDWpUMhs7jGPveXx\\/Kui\\/sS4iv009iZGMYKOvKtkZ\\/A+1ev6hKIY5oLeK3WIMqxMr9cDoR61kSvZwSTzOwiZinVQSrrxwc98iuaObVJr4LHU8BCD+I53UfCdvpNvbXlxdiZFBaSMKS2QQR9f5cV0fhPWdMe4W0WORWwACU28Ae\\/40mmXWoXwlk+zrEpbyx5j4U\\/5wahttGsxdO8paWdfn3p0DLnPOa8\\/EVPaRaxMnddtvuOqnGMJKVLZnVTro9y5huLRZwoLlym5QMDn9Krah4f8ADerQMklpHFlArMw+Y+hHPTg1z+oXRS1kW9mlhilXyyzHII65B\\/H8KijtHEEMlvc5QYWMNIOGPQk+nPTrXJSwr+KNRr77HRLERejjdHK+PPDOm2NxBFpUDQwyKyyOoLM3pWJb2UEFt5bDYFU4yBknPTn8K9W\\/s8SKGnvUKxkneyg7OwPJ9f1rJ1nw1ZTHzRdK80wUlgm0DDcnAGO\\/T6V7eFzBQgqdRtvvqedXwl5OUEeZ3U7FTGsmwKBkY6Y4PAzVdmVpW8wEqARnp\\/nrXS6roWo2rPshjmhXkTDgEcViyxyqu3ykbPIA5x2OPyr2IVYyV4s4JxcXZlcNEI1RVyvVgTT4pGkYKigt0+6TUbNGwy0e3DAZK9Se3BoWSCKB3ltC7dY28w\\/L69O9OTsrk86FmupQwbO7nHC8UjNLgjdgn17VTt7lDC0iRspQ4RSQcE\\/\\/AKqSWe6luCCoYDq3p\\/8AXp21sL2mti2ZXEBIALH\\/AGBmrDSjyAsjNHKBjJbgfjWdcSiNskNjGBkdKryLe3UXniKR4U+UMR1POOabiEpO+hekf5sNMZMruXa4P0NQxu5AQHO7+6KS1sbiR2Xa2VJ5Cn6\\/pj9K10srq3gMVw6LhGkhy4O7AyQPz\\/E020uoK7ICfIsl3yfeB6nnI\\/XpTNP33MywuREj8Esoyw7Yz9Kfe2txM8KQs0kjrkDacLyP8aml066+0QxgSvOB918A8AVjzLqy0pX20O80UWunbHhRBH5e15nxleBnpyKmvdWh1CS2snDzxliynt1+8M\\/jXLXMctun2YoryN97D8EHkVo6dPb6TbY1K4jaU\\/KoWLcwbBx06DBrxZ4SLftE7y6f5npqu0uXZG1JpE9ncz3UEOy2kkDxQo2egz\\/PPBqlibUF3SQxjDBlMjDGzkBj79apweJ7VrLdLHJlgAHAzs9cdvzqhc3ayNhLm4VWGShHDgc\\/41McLWvee\\/f+mEq0LWjsW5NJW2ndmmhWNwR1O1ewP1zj9Kuajfy6fpVtceYjbpSjkHODjhs457jFYJv5bzy7WKWRm3qAq+vp9P8A9VXdZheK2TRPNt5Y5FBSRAcbg5yTn6GtpUHOUfau\\/wDkZ+1UU\\/Z6GhZancarCxMrpAg2qiANtAGMn\\/8AXWfqcMjbrj7WzxsvKykDjHQHofpVSye4gkbTk8mFlwzBgVBXI+bpz2qreXtxORahkUL0c8DA75PY8VVLB8k7xsl+gSrpx13GQQsdQWZFzAjruySoIPBHGR2B9s1d+0aZqVvqtpcGSCSWAeTI\\/QbAAAD1Occ8VDHOsEAuCsV0rMA+M\\/Nj+v8A9aojdHULnz\\/sqeVGgG1cYHXqccZAPSumUXJ37dTHS1rlv4e2mnxOL2UNMoQNEWAGwgkHI\\/A\\/pXaz+LoNNvYmU+SjKyuyrnGQO3b\\/AOvXAQ63ACkaQi2izh1CjBcdOnJ7VBrd+0t2VaNmI4Ee7I2kZ6D8PTGK46+XLFV+art2udNPF+xo8kDtpdcsr64OtWk0ImVmkuBcPiSYFVDD2+7x2GPerul6lpz2YmsY2QydMNyMe+e2f1rzPWLOcWtvJDGgVwsaBcDeWOccdue9dF4aRHsHWeNjtDRtEvGGABGR74x\\/PrWWJy2kqScW\\/wDgdvP+kVh8ZOMmnsdbbTS3MV5HJdqtsc7Q64YK+MkYPHz4P4VFrWtGNEhtI47sRqFCJHnBP8WOg5GK55dXjl0zy7ZpIxINpfZkKQc45\\/Cren3n2e1lSJ3O1wA5ABYg89M89K4JYJxlzSWz2\\/A6vrKa5U9+pSfxDdW8yteRykbAihxg4zz9OldT8MNXa102VRHLD5krOr7SxOMnk\\/XPXnArDur5Lu5EFyiSumMvLGCF69TW1pWqKiMYHSNIxjdgKuByKWMpKdBw9nvbrp5dBYNKnV5+c39b12VZEa4ncNLG2\\/IAOcgj5uwGP1PFJo2o29vps115sXmONrKwwDjgD2z3P5V5\\/wCKfEA1G7VY7V3YKQAAcD3AHfn0PpWro+pjTdGSLULG4fLGQBG2Y4OB\\/LgjnFccstcaEVbV9NDanjXKtKzvFHoulywfapmMcFzZvAA8bEboio+VVz3+Zvm9Dj0rE1eKC3j+0XIWDErtsXBZwy7dpHIHGScY6Vxsk+oXOrxM1wbSzibzitw25mz0AC+\\/c4rbsvGEV7q8enfYVlaFmL+YvC8cEfjz71z\\/ANn1aT54a6XduiX4X\\/rc6qeNp1Fyy0108yLXdQh1x7PSLXTbyWOG6SQvNIGMcaAk7TtBHUjGcYPQYrorFNZupnvpYvIsZ3VvJiYZyDkc9Sfl\\/H8aZeX0DXUUVlKLTCNbLEMuJST7D3\\/IVsT6eiCC3e8gtCiKyrKcqWHcgA8gnuc1hXrpQjFRtvvdvu\\/02RpCnGLbky7DpUmrXzahqkW2f7OsZ3HlQG3ADHXkt+J44rS0PRLWwuTL5c8NmRmI+aAGlPG47uNvbFVtE1y0m1IGJjcxMoikneHyyJBnI9Dntj071z3xF1CGWBJrO4kQFCYoEOFUjqcDvkHmvIjTxFar7BvlT+5f15nTVnClS9pFG94x8QxTzpZ6DaxRalLKEinUBjFtClzJz93DbcjqeO1N1jQdR1rRYbeS\\/SFoh+8UryxAAJUcDbXE+ALOWR21OBjNcPEU3KxxuJHyEDvntnHeu1bTdRutSia\\/JhkSECY+axUD04wAM84\\/xravRhg5Rp05JcvV6u\\/z6GeHc6sLy6\\/ccvp\\/gmCeOK+s\\/EMnlM+Csan7wyOnHOCRz6mus07SpbcxxRST7i7S\\/wCk7iuSW4UdEHzEfT1qxFHZRWwW7aFbaF\\/3USoeD64xyM9qtw2qXniH7Xs3sVDQvuOyLHpWGIx1Wrfnlor9F8ui+Z0woRjqlqX7+1vZn+zxY8oIFI54bHJBzz2qnpmkQQTxQ3U8s2xS0jM2QT16VIdR33LGK4LtFuQovOOR19x0qvqBuViN7LcJEuOdoLcdenU9K86CqJcl7X\\/M2lKK943pprMMY4bWMl+FAUfMTnj8cVieIdYn0ywtbh7RS8lwkUkILM4znnYoz0578U6xmgusPkb9o8nnOevz4rFtdO11JpdQe8C3dxcqfmQjMW0hh3xzg59AfWqw+HpqX7x7d767\\/wBXIq1J2XIbst9pcs0BWxnczS7mdojhT1yc+mP8mrOpJbWkavvjt5bhQvmso+UAjPHv9KTw\\/GbXRpIrZ1yrsx4Hy5ySSenr+NZgGlarqc0seordahZyuk9uWxgAnO3jlsrgHIFRGKc3a\\/LH1fpfol+Bc58sddyfQtVtWZbI6jbXd0S4lktxlAu47e2Pu4z2BrV1SzgurNobjcsLDk5xn3x+dc3q95oGk31nNay2UccZYXmxt8khwMAHpnPUjjiuY1bXNS8V6vNpNjNbC3k+SS5RipEQYHucDG05+tdUMDKvNVIXjHdt9Nf6svQ5HjoQShe7Om1bxBoFmosbGdYBEyw5UZUgFckjuQM\\/rVLwhcaV4lsrmTVIjfoLhWhkMYVYiA2GTOOSBnJ55qhDpfgu0lSTU7zzMTnyv3oAkODknn2z7das23jDSra9a0sNLt4YdxZvuxpleNygfe6r+fFdboL2TjQjJy35np+O\\/wDVjFyjJ6yTXqR+F\\/EdzFrWq6beWazW2nK0i3ZUlyxOBlT06k8ehrn9Y07UPEPiESSzSzxhEQocxZ2M3O3jBPH0ArtLA2+oava3ltB59hfj7LdynOZHRdyjH0XBPsPWujsYtLtbiSaGOAyySnKkjIwMUpY6OFqOdOFpNfc9n6O6v06G1PDqqvfd9f8Ahjhp\\/DGq6s\\/2i9hWF4IPLiEOH+8B\\/EeANwyai+zaL4TH2WSS2mv\\/ACt07n52JOcbV7fX61veMdXkltjHptxHJBDlZYlfZ6YBOR2zXl3jCeC409XuJhcMhZGMQAbo205ySR69PyrrwEa2LtGo7RfRfqZYu1NNxKt38QE1Jvsl3bMFLAYI3Kg6dj35P41HqGpWPiSF9OuoU+z2yB1x8gztIwo9eenasHRb6W51hbVbNILZkWN5Y49rBQegyOT69z68V0uiaL9nMzuzFTISoKg71PIJJ6Gvp6tDD4RXjHla1Wp4kHUrPlbujg9U8J6zDAGhkWSEkBQeMe\\/NUG8L6jZFZryIMgPITDDivVrppHu1t7cyMP7qqCqnPX8BSXdtqc9r54hRmH3UPB\\/H8K3hnFaKSlbX5Gc8DSu3G5xOlaVqWq7trxRoTyEj2kemTWlH4GkkhaeW4MZJX7o3F\\/qPqK2tFlvys8UsMdsjAttA6HNWI9UlhPmTbtwUID2OKyq47EqbVKyNoUqLSc7nOxeBp4tjNeRrjoV4IrOv\\/C9usK7UM5AwjBscfSu\\/a9eSCS5lBZSRsyoPUVSR454gjnCrwcDGPzqaWZYm95sc8NQtZI8+vPDWmQwtcKtxhEzgkcnjk1zN1K6ztIpZWYkLyeK9jeP7RHJAsUccYGCeDnivMPE1kkF41wUaNdxAOcgn6V7eAxjrNxnueXjcOopSiZ1qU3vdTl2IODuPGfTPFSpeWaOsm1Tg7sqpwpx61Qe7MpSNmZEj4AHHJPekhM01yqInmbuNoGBXpunfWR5ty9LqP2hfLRE8stk468Dk1TVJCOi5x\\/Cf8+1a8GlRHKsTuyMgKAOwwKrSadJayPtjdhj5cNwB1wTjmpp1Kd7RNEn1LGnJJ5BUyEccgLtJGM\\/l9a2ra5EUEyMu3PJ3LuUn064JrI01zFO5VEjUjDsxHvx\\/L8quyzoGeNVH3smXd1wcn8D0qakeZnRCVjcS9FxLExzu+6XJwHPtjrzimyzhZjDbhZMggnOSvvn9SayluViCIoX5hlckHjof5Dj3p93cxpGwDY2EDYWAwTnPPc8j9a5vYK+ht7V2DVHO9hHIJVJyVznnHOM8VQmOEKhgu35QAOR6+woLl2AdgS3JOOgxnHHWgRiaDLKcgnPPJ9cGumMeVGMpcxAI5HJbKtgdWOP69OtMjCqFfLFic4GB83X9MVPbqHBPnLGc7sbeg5+7\\/iafJGIk3xRurA7SW5yc9sDgEdq0v0IsU5BEjGSXO7pGoOck9OKgWJpHbAy\\/f27VNIoQiV1Usx5UDJ\\/zxTpIGVN5ZgzYPC59ME+1USRmEAlUV8AZYoSAPb8zj8agLKG+ZTjaAF9AO9SYZXJ3kADO7tUah1HmdmYlcHn6Dv8A\\/rqkIjVsDLH39M03JAfcu8jqc9u\\/FEXmP8yjGDjnrmkyx3R8A45wOTz\\/APWqibk8FxhgzjBC+nH6Vahv7hH2oAwY55Azms\\/aZMKMJnBA\\/Sp47eV0wCoVflYg44\\/DrUyiupUZS6GnLLeTWzp5rhn+V\\/nPPtmtfS7SSy0z7QsMQkVSqjeBk+v4VV0hVs\\/KAkZhIPl+Tjqf8Ogrf06dbVzNPG0s8nCR7htA\\/vHsB+VcVWdlZI7qUU9ZMjkW8i0SSZpm8x1yzufkTjtnvXDW0RtlaX7UPNkPUjP1NdF4x1xpENqdsgwQoz8o\\/LiuaRVkiJdvkReiDox+lXh4y5W5dTixdWM5JR6CzRhSIy7sZDkkk\\/0rSs4JE09g8sLZYYjkGdwHY45ArLtohGokQSYPBLHoKr3moO7gxnCL8q47n1rocXLRHKal5NGGjjSN9xyQV6ZPfnpWTMjjmS4+UtjGck+\\/WmRlnEkzlXkXsCT\\/APWxUMbPuSYqWUHLfLwB6VcYcuwyYJF5S+Uhk9WJxt\\/xqPBlLRj\\/AICB\\/M1ZMoYlBEuDjaAenGelSRP5MpkKxnnuufy9aLtDtoUTYz4JABx0Gck\\/hVvTLdodTjkkGzyzkgDPb\\/GpxNEyK4yWYYAyAAfX3+lRRzedJIqkBFB7EZz\\/ACocpNAtDcgvobd7eCEvI5IGCDgknmt+7kZ0iVyzSKykZGODnNcB58ZRkMzKd275RyT9f89a3l1uOOxUyOZHI2sSefqPxrnqUno0dUKy6msNOtbmHTEtHjuc4t5I2DHbIoOeRyOPQ9s1pWNpaaXo9rcFCphvngmiMmTg9QR+P61k+EbW\\/gH9oW++RLa6jmZArEsMHcR68Zz9a3\\/E5YpqWoOsT2kkiuiquDuGMNnvmsKkpKap30\\/rT8TWCTjzW1PP\\/EaqusShIfKUgMiu2cAgHPP1rT0Dwvd6pBFch9qSFtnBb7vU9RR4xtFvNQt7q0Jk3RLlEG4gAYrqPBlzcW\\/hC6uktXV7GT5I5BgsrcEfnXTVqyhSUo+SMIQi5tM6rS9TtI5dPivI0h8hVjJCswcnOAcZwep9K11SGODUoZJlRmlFxCFkAbDHZ74znH4iuI0q8vrua9uIYFa7VI5Y4tgYcEqeD9as6CL2XXFvbqCOKO5jKs+doyJI2VduSOorxq1CCTd7Nf8AD\\/5nfCpNu1hdf1WXQ9OlvIbGC2NxIGS3SbexIyCS34dKw9F1y5j1W1dV8mXUVaTEWPkYd+elega54bsNQ0fzLu0hbUJ+ElCgmPrgc+wrkLfw7DHr8txJK86W8Me1jwTuPG0+m1cV208RGtBwkrvXoc8qTg1NOx2OhXq3titt5E1vLFPJmZ5FJlk+YFiR05\\/pW54Zs5RBcWwvpZXVfnPONxBB4\\/GuT0rUZNJ0q7tLXy2nFycNKquu3PXrxVi38S\\/ZL6aO+vFtBJGC0yr84Y9wACCD\\/SvOqYaVpKC0etmdMat2m3sT+J9IXWdNM5TdFBKkruBklQQceo6dPXFZPhyx03T\\/ABJFql8wmtzOkkUkcZBUbNoDY5xgd6s2F3D9m1DTdHvvtMU7bpHeVmIJHLAt6nPHv0qaysAvhS6s70RLd3EzCyUTDcVZ12kEHHy9cexrSEXCm4622fkn1JnLmmmzX8V+HYrq3mazZvJjkKBvug544IPbI\\/Kua8A30NhrEEd5epK4cwx+YjEgsCWPoMA966Hwrr8dzDJoM10Hmh+4C4J4Jzn6kZ\\/Kue0OzsdC80XVos8s0xlSQx7twY8RlSDz1+uK5aMZezq0Kj9PR9Tack5QqRO5v766+3FdTfEtum+BV43MCATjHqFyPSuy8RadaahHa3Uk+WhZJUjyNpYEckV5Zp+ovrGqRQ3e4Mszzu0inOzYNo9jz09K7XVNb\\/s3R5r8M8vlbDGNm+RvmG7nHTGa82vQlCrGC3\\/zOmNRShzGjrpM7GGG2aO2uY8tn5TuA2kY+mPyrhbm0a0+JMAupLd55bBlDvgAbSvX3xXTnWb\\/AFu9c3FiLeOEKFeN92VcYAPbdnP5imarZzT+KdIuTbSfZ4V2sWxznIYHqSeBj61nQ5qMpQfVP8iptTUZeZiaR4obTtTlEv7tnkVZI9oIaMA5JPsf6Uv2fVGaSz0u4Aj81pUnXC\\/uSNwOcemPzPNZfxM8PjTdXF\\/a2ck5DEPGjbScEEZ4PHsOuK0fhH4tjk8a29nqWjvaW8sToqyLuRG27lyD0B9O2R617eEpU8RCnWp2XR\\/5\\/wBdDhxE5UnKMteqOgOlreeG5Wkuo5FlZnYxcKcIBgcnjivE\\/iLYzahqcdjp8SN5BdI4k4KxhgwBB6cOOtek6itxpGkyPa6jBObSecKofETRliUjznBwjL7jpXnF1qU0t7Nd2sTrPtMBYN8wkIxjJPTgfTitcBSlRrSvrZsjEVFUhG2l0XfhZbvpBv7fWLcIJWjCBmyX25yF9eo\\/Sl1Wwg0u8VroWsQv5laIR3SsVHPyMAcr1HPfBpIrZInt7q5vZro2tyknmbMhS5CMCc8jgnFJ8abTTtN0sRabJbkC8MbTRRBTJIh3Buxxgj867FWVWq4q65v0MvZOnBSetiDxDLHb30E8V6kfy7CFj3DyiVwT0JIDEfUVIbu6\\/tG3sbC4a4aVlmKsu0MHPPbAPG7vnFZ2l393D4cTVLKZ2md1gkUICjZIx2yOSKuLFqk889\\/qd1FHMibfLNwCdwYBcgfdA5+tQ1GK\\/eWb2+f\\/AADXmk3aG25U8KXsXh3VJpJ3aWWGJYZS7nDFjkgDg4GVxTvFWk6vqWqSTadplwsM8YdGIC4Y8uASRk9c4+tF5oFrd+LL1NTuDa3NxFFcW0cRHlqxXcYyOvHA\\/wD1102ma3m9k0+W4RzaEvvH3UOzJY\\/XcBj\\/AGaVWtyTU6Su2lf9CYUlOHLN2t\\/TPJI452eSKdMyA9WY4GP1z\\/8AXpZjFEyzyW7kDbwrHA9\\/Q9K7u00pZdOuFt7KK9KXCvcXMwBIO75gASOODyPWrniTwzo8SSS6dJcedvG1SyvGVPLBSozkZ6HHeu94mDlys43Sla55tPd4nC3DOCoDLHjCjuMVDFeEFQol3FujDII7fliuyh8NrPau05Tzg6tEs77EkAznlvbH+RXVW\\/hTRPsNuYYF8xFZfLBOQGGT+HPWsquJp0ulxww0p+R5RbS3l6GazV5Ft0LyFVyVXgbjn61pW9jqzxqy6ZIS8oWI7QQxIBHJx6ivTNM03StGtrq4KC3URbf3K5DA9j1JGR6GpIr+1stMEEQlkiOWiYKP4vmBOT2\\/CueeMlL+HE2jhEvikecw+D\\/EF7OZZrZomADCMuvIyM89jg+lbA+H1vdSIo1EsVJWTDY+b154ABGK7nTdbRpY5nuSzOOrBQOCRzjkdARVlLrTrkia3mMLSq2SFGC3Jzz0\\/CuWeJxV+3obxoUFG5yMvg2zs7MWmiXX\\/HwQbhWmDAYBBGevOaS8+HVlJHuvdSmmuJTk+XtRd3TJzyf\\/AKxrburya11KS0itrZkkGBLLljtJyDtGOeKL4RTWyzvrMYldshACVAycnA47VXPXVvftf7wjGlZ6XMpfCyeWkK3KNbwxNEIpWwDnoTg4J+96dansfDllp7LGqzBlB8yVjw+RgED9Pyqpda21w\\/lxWsF9iQL5sqncjAADbyODz+tW7W7vwGSSSySWbJ2+YpK49fUZx6VU41lHWQRdK+kTqYljsohJI9vCPlHZSD3GOT70251e2Wd555IZCJSFJyAQeOMKf1rlZri7jsvMmMUmwgiQQhiBjkAAjr3z6VF9puhcvFJqNpFC4AOSwftjjn16eormWFT1bNXWd9DpLiQSJLIyyPGw5MKrzk9SM8CqUqRQtJNb+TOFYBY3TlRjnJ4weMGsF9b+yyG2a7uZm2r5pI2p0JOM49DU+neIhcTkfZIXUj5l+YZB4HBOM81aoOKujN1oye5rZvry4NtHCywMCWwNmSfQnrgHqKR2H2Qx\\/bJI2SE5CxsFbp3\\/AExVA695hdvscCRRYMCysdofjGTkk49qy59XuL1286KO8jchY4Y3ChH7AAAEgYPftR9WdTSUbIpVlDbU6uO2ha1t4ru5txFLyib8tz04PT\\/61UvLcMZLWMNAHOEUK+1QCR14A4B49aoi3iFklzMEW7UFBD\\/EhGSD784GfTvgVWvo7spC1nekzsxFwkbYCSHPXtyvfI6GopYVQbUX\\/X9dS5VrrYsahb6rNeSyi62WikElG4YZ5xkVHNrebo+Q8qOkgGHDD5Avzc\\/dye2KqLLPa2csdxLJNMeN27PyngjuBwMZ9+vSqc8kV60aGzxE+T5ksvzIe2TxngAenPeuyNFP4ldIxdRrYk1XWda1af7HbzPDGEztDAcA9Tzx\\/wDXrhrq7vfmgkV1k5VtwPJzwOK66RjZOftVtZ7XlCly7GQrnpycEZOfwqro5T\\/S7Jk3SArIAiBty7h0yOuPfsK6acYU1pHQ5asPaPV6nNafO0SCRYx5oOSS2Qe3Q11TaBDc2ZljvFeRwrqCmMA5z19CKyXuVgknsvsUSOPmzKmxgTj72RwKpz3bWzFC43\\/Mp8t8qTk8\\/T\\/GtpqUvh0ISUN9TSOitZwRyNayZaP7jjk8dQfrnjrWRHZzsk8RR1JHAVc8+hrX0fXFk04pO+GGEUmMdB8xwc8c9sc5rUtZr6W+ghtoYYQ4O8RqAjgjOC3r+NZuU4XcjT2UJ2sQz+H5pLO3SUqYreLJAj3EFsnGepPatJZJ7fTYbWxgiEKj\\/lqgYk5IGcdG\\/oat2Yu7d5EIuZOB5hP+qXcDgE4yOaZJpkc0Bjur+CPMgUAsCCoHdgOMlTwfWuNVfaL95quh0uHI\\/dMC7gKX0k8rrG+QwiZlB27VyR+J6e1WLDSJb+6nMMiYjiKoWGQqkHH0\\/nya6NLXSN6SW+y5dEIlwuMPwADnntj0pZ4lsEdokZ3aTiEMAuCOOn0H6USxUnHlgrPzEqKTu9SCKEacYd\\/lXDmL51HJUg9KdNb3l5pgmRkt2Z23uIzhgMZGcDnk\\/WmT\\/bZlZ44EYgoHKDB5XGP\\/AK9Zt\\/pWvXKO0kc0durLsUBsnAGQBWFOEbpykr+f+RpJu1ktBl59mjuPkZZXXhAnJJPY+lczqOq3GoP5EkGFikBbaD8yjg59e\\/NdJpvh\\/USYvNhaN5InMb7GweCAOnXGee2KjtfD96t8Ib1vK8w\\/ut7YBPcdfUj9a7o4ihTbvJaHPOE2r2K1rpsv9kzO7RC3B328fJcjqSMDoeRzVvTIbi+E9wyMq7AfnPBDe+PbH411dn4YR7crd3CYRBHGqsxVR6jJz+daL6JZw+TtA2Mm1kxks3XOAOBXn1c2pfCnqdFPCyWr2OTurZ9NsgXjSJt3LxxAEttwM\\/TNc\\/fpPLet5Mks626EjjaBk5OT369vWu71KG5tmuUtop5ROR8uw9MYxj8v0rHvYNevLqZZLZogOcouFGBkcY\\/zmtcNiVbmbWvd\\/oKrSvojnW09jJG0LNG8mVd\\/MG0hsZHpwAPWqJt7ixigmtrgmRy8TMOGUg9j7g\\/zrqE0G5uLTy5bORlEigFs5bPH4DvSW+i6vcRP\\/orxIijYQPvDP6etdP1ykvtr8DL2Muxz+n6deSQShsPEhKxuznbnjkexrPkvLm0vDDdwttUEKE+7nPBz3rpb\\/R9YS3VRGNuNqgtxnv8A59qyL22uoWRZrZ13KJEkDAkDnHHetqdSE3umZThKPdHSeFbS2WxlvtWsXlku5lECphVQgY59DkVzWtCO21yS3h3bfOLhinzEdVx+GKtNBO2nxq1yzRygkqhyVzwCRx1I6+gqCXTow8a3M8swWJdiu3zYPQDrRCMYzcm9xy5mkrFm6tLua9ilg2GZQMyttUDA6ZP+eatxaHqPlrfLcQRxrGgdiwIznBzg5\\/H6Vnz2TXDFhbXRXkqrEsVA457dz2rYXX9RtoksrEfYIV+Q4jIYgHgAkH1J\\/E1E+eyULFadTmNdW+0fUU06RwIckoVXqvcleufat979dT0PYt1HbywjEMLcHbgAk8Z7frUV1LAbp5Jrhh5hJ3MhLkn3Bx169Ky9Rgt7q6hykuPu5icAt9R\\/9fvVqCna61XUys43sy9p105hVLlCwY7WMjc4HUVclZvLZIpSse4R7mIAHTH9K5i6lhgtoktS\\/wAvGS2ecnpx6VteH3u77yLG2tAwZQ0sm4DGSBkk\\/XpWdSlb3tkXCs\\/hY+3uYrA\\/aotQxcLIdoi4IznIB+hqWfVUu2ZLqS5bzXVZNp6gDqO\\/1PfNZVxo91pF3K1wFYkE5Dg8Hgd\\/51a8LabLcXpaJblo4mGSgB79\\/TjNTOnSt7Ru\\/mOFSbaiie81TytW8mASSZRcKo2kke5we1XdI1+TT757p7VXWVcKZEIYrgjJOeuTxxWvbxB5Zp5kt0TKgSzEc44P4c1MNT0K0uEmS3W7udwOxuY0YY7f56V5tScLcipuWltP60O2FG0ufmsbHhq\\/jaYajexSW4ZytrmHOAeeo56d8fnWp4b0rWfFd\\/HdTefbwCIFAoyeM8H16c+nFY1pqusXMyoqkwIQIVSEhVwDuP5gfXNej+DfP0XTr3UL7zbUXQVLdc\\/u0TOQCB90nPc9P1+YzGpKhGUopKb0Wt7eS\\/NnsUqanFJttfcZ+l6B\\/YllLbTMsMqyly5YqXBkYjCkeh9Kf4o0q1llSbULsLFAQGCLuyOuFH8\\/rWV8TNMnkvo5dREl3DFbxRCQTFQQCxDt6tkj2wPxrES7lLHT737SbiJFJWJ9oIP3SoIxjC+3IPFc1GjOso4hVLt72X5f1pc3c7L2bhp01O20ZHbUY7S1gksbGFDmRAMljyCVH161rXFnZtE6SXRk4PmMeuCDn2zz+VeQ6l4l1oRWlvbJKJMPtcEAvjuxz0x3PpVWx8TatY3s0mo3e6PJZEiGfmHVQx4raWR4io+dSS8t2\\/6\\/rYzWZQhLk5Xbuen3jI18krSSylCdj7QBtIxgen\\/6qfc6lcLFK2bdFjCqqM5Jfr1PX9a8l1XxZd6jMTcXBhAQlYwxwmAP1OR0p+l6zJY2Blm8l1Xa0ZLEg9zyc57V0f2DVUE5Wv2JeZQv7ux6H9u1EqIrKCNYVILMX4PqTxmuX8R+Jbe1ujHPdeYYkKbEJ2ZPX6\\/SoL3xYl21o0KhmVgJBuK4JO0ZHoOKwPEOhNqd+0TGW8QSDMkOWCNgccd\\/8K3weXwhNOuuXf1\\/r7jPE4mpOH7l6nRv8QX0qyim3qnlgYjTkY\\/uFq3vDvxAv\\/EGiXsk0Lh5srGVGDnHRRk56D9a4VfAyMkdpPb3ollwoidl3KVOMhevPHX3xmr2n3k2h3ltZS6I91FHkMQGwnODkD0wO9XXwOBqQaox5p730Wi1017nHGvjKWsnp952elX+oSKsMtxerZgOs0YUIWO0cAgf1Oc1tu0K2rCysZg14TLONuMOxydzZ65ycf41B4evdJ1TSxPdTxXSxTAiPdjDErgNjrxkUuo3toPsrW9x\\/Z0Hmh57eNeGbbkr7H5T+ftXz1W8qnLyWa+7v2uzthUqRjdyuvxOY8S2VsshkhS5kMSgNJM2A5J6Ad\\/QfWsfTtRex1EKIora3uYkilZYwWMYYhsdt2O568V6N4avR4jkR9QLW67S6RgZ5znJ9MAY7Uy\\/h+wfaJrbS1ulRgHlii37gecBcZx0JwOCa6qeO5L0Kkbv1\\/XY55YaL\\/eRna\\/kcz4btree\\/uo9Ftft9\\/bxyMst1hg3ygbNv3c43AH39K6e+ubKxtoxLZxM14qwTrFGPnbGCM\\/3gc4+npipbGSws9PdUhS1u5pFZpY1Afk5x16DivMPHevalYeIbyzuJna02jMaMB5rAfeB6jgLxx0qsPQnmOIcY6Jd3q7emm+qKUo4SPNc7CXxbH4c1STR4na1sgoMSrllUkYO18knkEkduKfpk2nW+pzajeTX5llRp1252pGxBDDOcBiSPTpivPfD9tc+JLmKGeORLa3GY5WHJyQT0zzgdP8AarvdR8TaBbWETm7iCIDHljjIxtC4A5AA4z0ya6MVgo0ZKlTTc2rSt+HR79Rxru3O3p0NK9GhXuL+WOVVRPLRwxHmHOMenXIwK841\\/WLfRNel0gWcZt8Bt7YJ29cH3zn8a2tc17TdK0mKOyt4ECr\\/AKNGX+YBuTnPcEg5PvXI+IL+LVhaXRVTM+VZQhJ29\\/mPXtXdleXyTvUTcHdK7+4wxGNm3dPU07nxbawWCXFu0UaCTEZSMfL\\/AFzjH51A3i6OL\\/RXxDDKRI2F55xxz+dU4LbTJrOLT3s1XaMgucYHc5quNO0D+0ngMM80qPho852gdeR+A\\/OvWpYTDWacH\\/WxyVq1S\\/NzI6G01u1lSKezDKSxdSo+56k\\/pW1Lqt5cEAgjAw+1QO3161z1pBDbQi3gKyOecFsnA9vaorl762SQAqEHOVBLBj756VxVMFTqS91elzeniHGOrubF7eRyCazVSZyOX24HT171m29hIluXnmM8mN0fzcD3pdPu2uITBcyou0ltpbBI9T3qF74SSFUTzRGCpXafX+VONCUE4x+ZLlGXvMpD7elwjm5kaMgkgMTzU6LK8nlJPvLtjBJwDjNSedbxqYmj2M3OR0I9ifeq1zdp9haKGbaWJbIODyefpXUrydrGei6mklxFCEtnGJWBHB4J\\/wA4rNudEttWZ4pXBKnJGPesvzZGjVZcNtbAZjyABgf596tm4a0t2mjmjuA4yoBzg+2K0VCVJ3g9SXVjLSS0Mq78GW63hjt\\/NkdgSOelZ1\\/pmn6TdSfNJ5gH3MnP0\\/E12+lPulV57kwbhx0BY\\/5xWR42j019kjzOZ0BHyDGRn0rro4mrKooTbaMa2HhyOUVY5QySXLNJG8ibSQuW4P0\\/\\/VTmiYRp5kobb8zHdhufT\\/Cs2NJZH3jKxjoikn9KVZJpX\\/dStvHJVcLgZ7mvT5LbM81M1vPspECRFsscgkEDPH5Z9fept0LzCBX2gMW3v0I559jWTHuR3PmB9w2fMeevNTSThip+YnAyV5Pp0\\/Sml0NIzuaUe9wWSPaEUcsPXnI\\/znJokYXG7MCoMABx1Ge3P5c0y6Mk3lNboYoyNpY4wOec85449P60k0PlQy26SmRiRhccE\\/Xg\\/wAqnQ0bJJIW8lV8wKwGMKcvnt9BROsixK1wCHJwqZGF55Jxk4z+fNTBAyIWmVQhJGGB2\\/iD04Xt+lUmAi812KhHGBh8scn09c0lJPqJyQu4xIF4K5BkXBzge3GO9J5k23MZwmeN+CCR9e3OahZzGGiWLLE4yWzwf60ou1J2eUzpt2qzjA3epA7DnjjtWthXFeaJiJN0bA9AOCT1Jx269hU0kiLEjlHSVwMYBG7gAY\\/Kq5kDXO+aOJGXLbUThfwHXt+fHenTXG\\/7oKlQQxGPmHYBcCiwXIp+6xxrwu0E9AOueKrySBAfMQEse56fT\\/Cppg6+UjKQM\\/KhyAT3Oe\\/PpUqRJhnnI3spMZYnBOM9u\\/Tj\\/wDVVbEsqzwoXJXecglVbufp270TRkFd67QIxtJ649cenv8ASnF5MjDhB1YKABj9PSnCKJ0yAWDLnOfmOf61QikZHCkAYVuOnLAURnE2+QybScFEOOPSrUAWMkOMNjDO3IH+H1\\/KobhW2dNqk5IxyfT3xVEmrotwluVlfiMDJUnA\\/wDr8f5FWbjU7mbz49Oik2eVkbFP6fnWA5ZoV39hkAc4+tdBpWpW9jp5YBWd1OF3dR7isKkEtbXZvTnzLlbsjETS7h1LTsEJAOwDp9aivS9u6QsyIg6oD3xWlNqE10irPMEJPCocfrWXfxC7vmWFvMVTywGdx\\/rVxu37xhUjFaRK1zdSsyfOSgGFU9\\/r2qs7SysAfn9ABWvbaHd3UpGAi49MED6dqnFtDZv5ECHz8YDtjOfpVc8VohRpSerMjzHjhCzBlXHCA4zUIeRlxCm1F69\\/zqzeDhllT94pwrHPzCl2W1ukbkOXYBuoKj8Mc1d0Q0kyXT0uHl3SRHc3O9uw+lLc\\/ZUZQ6thRkEdM+lVZHWQlvNChzlhiqrEEEKARnOaSjd3JLSXUqxNGhGCcnP86bJcO25mZSSOCFHHtVXk49+M1bs4ZJGKhQVGcZHeqcUtRjIkjR\\/37sMjgAZqyfs6I7+fzjCKvU\\/WobkNAdrAeYOpDciqxZnYZJJNK3NqB7NZy6doFuLKO9j+0qhP+rJZ8E46jpz79Kpa1q+ra5YtYXVpa2tv8mHcnKhicHIyMcDt3rf0f\\/ibeItO1EqiiQPF8gBz8m4Yz9cVQ1zSLlIboSxlkOFkY8HCSMQPTqK8lYhOVpLX9T0HRtqtjm9St73SCJE8kXEUA5U5znP3cjtxV3SrprLwreBrktdXUkLTFpBuRu+c+gAFGtSifLCJsmHZGoHOARn69MVU1qztbbTZCWVY55FbDEZwcYxx6jrVc3tIqMtw5eVuSNK61fUtK16K40yK3eCEF5mUHLxk9G\\/nW5o2pJFc27EG3Rp9zLkjgsDiuS0kwXtlbSGRg7EpcyEZVVXG0gHjOSetadxPYQ3UcN5LNIbcB1DNgjHOTwc9Af51nVoqorNa9zSE3HVPQ7rxNKdL0p9k6LJMzSBB1j4Jx7jmuZit57\\/TUlSe4treW2VmLy7csFHp154q7a3sF5P595ZGJJUDo08oQsnr7n2PqK5jW9X\\/ALR8WG0so2+yxIuMbHKnnONuRjnP4VGHw1RK17NdQrVo7paMarLH4fLPEJUjeRQVGFJ\\/un8s\\/nVLS411OR53iLwqUz84A2\\/3fqfrVa9idNQtbeVoVh3fdUqzOM4J46cetdHqMNlf3rrbQ2lvFsYKttDsBdRuBwo6kZH4V1uUYaPr+Bkk56om1AxafFBaaVJG93dtGjQxPvVeQAc4DZIz19azvEdnr2nazDCqGdp4FYIhIEZJHUkcc4\\/Kk0xvI1F9Ua2WYWzhFilOVYcYz9PT2rRsdesNTu7uO9tEkml3TISMru3D5E5wRhRWN5U5Xjqlv8\\/0RWktGJpFxdWuqR3sNvCs8zDzZwgkTliBzj2arzR3+qlrO81byZWYsLgR5cLuLBQAeBu9egJ4qi+swancXLiKK0I2+WsahIxtGcBR05\\/9CrMtp7ibUILg3JEc1rhzt3EbmOASeOnv3rJxlJ6qzRrzRitNjo7zXXtntdT09TO1s+5peQX7FG+gBA98Vv614wtbrwXqV1awTeYZV2sy4yh+YHtnoR+XrXETa1ZwWUVocEou1JA4POTjoetaNtqkNm6R25N2yKJFjjIG4Ajq3Y9fWsZ4dVOWUo6xf3pPqUqlk1F6P8zsPDXjDQ9XtzDA9zHeswd4xG7FWA6kjA4A4rrPEOoadcaJcDT7wT4InhZWO7sCT3B3BhXnug+OEtop\\/sOjx26bS0bsgMu8dQ2RjGT3681Fq2teK9Xtd8lrYQllYHyWWJhk464yePQ4NclXK4uqpqVrd3\\/wC4YuShytXO10fWLY6FBqeoXS+fMkagvJlcgDJ3E9QAQc5PNc58QLrSp9SiGlyLJbSwGN2hfcEBAGCRnsAB9O1c68JGn2cEaLO9qTJ5CShsOcZ9jyOme1Q29j4hF4LqW3jkBGFRpgnyZzjgcenHbiro4WNOTlzdy5VXJbFbXZL2xvnihLPHcYZt4DCJhtAzg454PQcn3qJklOmNJOymNpN7B2wDtOdq85Bz9etWibnUNSJMRWeZPL8lIg3HAHPb7g\\/LNOuNCurkxxXskcMkf7rbuCkjJwQRjmvRU0rRk9TlcW7tItWmoQIiIyq0Mke8IWJAKnJBA7dSP\\/ANdaD6ZB4vW7jl02O6uPJLpF5uxY5NvVOc8hQec9PwrFurOO0HkQPJPdNiMhWB8tjnGeMAcdO9RyLd2ICQJdswKhZo3KhAvAGf4uD9KzUFvDRjlJ9dRdCht7LSrzT9ahiR7eYp5UTdCOBu7npUenXMd28srTSqHV32kAFs5Ick\\/41c0\\/T25v7hNksoYvJNKSJmJ+vBLe\\/f6CrFzpYuHkmlVZGVdqMrBVUdwSeO3vilKULtN\\/15Aue6djm7XS5LkS3M80RvUJkld8bV6bef4eMfjjFLpltCqmMagAuoSATYcl9jHI\\/NTjNdLp2mrHFKZJ7OdbhyWV54\\/lGOAATntVzTdOsLJHkk\\/1j4AEyAKVxwB3PI6+lFTErX8Bwp2tcxrW\\/WJdQYSeXC7rb20AjwJSWI4Qc\\/xAf\\/qrD01JvtsGoW2oyyzwlldCduWBJIzk5YZ46dK6aaxs75Z5IlWCdVEkU0Lkng5XbkYB79aoadpNjNNPDaQXl7dn5o5xG2yKTnJyDg8nPORV0q8Y3fcipByskamkX2lXFs8iiOPCjazcAvxnkexrTvNOEtol5p98wf5cxi42r1yOMEk8H261hado7rHHHaeTDbq2Xjd1JYY5yccdOuK1dNmXTFke3lszcFiqrlmR85wAMe4FZVal5XgyoxstTF1eyktNO+0v9tQyTmPzTbht4x\\/CV5Kg8ZPpUUukJceHrW5Q3g1MHc6SqAm3JHAJ4x9fXiu21O1S5WC6mVhqVqhaOEt5kSkk5OzIGec\\/\\/qrBv9O1W7s7WzndnjLsrbodmxWYl\\/u5BPTt0q6VdSitdU9f67ETi7s5jTE1i3iuXtrSY7U3P8uRGoxtyTxyD1puq3MVnDama+WSXG7aGOMAfLjGMHJr0vRPDmqWM4S11W4tzOFR44rddhQKcAsDzyeMjv8AXHIeOPBtrBrFtC2oypdyo25GtmRRkE8MTjqOwOK1WIpyqW6E8suXUwDNutDdNfQqH+8FuedpyckHpzjip3vrmaze3s9lyfuEKoPznsD17dOMkday73w5DZWTPeyJErELu8zkZIx7YPX8DTLe\\/ht2MWlwxNswS4XGfpn1rq5FPWJHNy6M6Cw0mSxidLwKwcMpFwSijgNnjGCF7E9+lEB0ldSXyJZJGReJJ+FJAwQAPvDI9OlYDXOt6rE1qRLJJv7OojQc5yO2B6Vd0W1WOdNPvbpvtJO6J7eQDIxz83THXoexrKVN2fNLUfPy620GT6pqFxcmSeBryeRgI1bJG0DIwD2FOt5YkLSStJ97AG3ceR0\\/QflVbUktlulJ+07YMN5zTEY4zt9\\/r7UQXkjWcqRJsViScux4A9QenStPZ3iJTKMj6gXupUFyIwhIZV2gFTzz9M0mhG3F3cNJIzMsQMKlc7ju9P8APrQNfnnhexESB1UpISTh+eDjscE\\/mar2epzLeQBGMki\\/dCrgZz06e\\/ar9m1FqxCa0NzzZFffKiFoHVsDIU5z8pPsefrVbyVOoF7a2d4I\\/lLBuVJJzz04qa\\/Z5NO1IRRzXbhid6xs+Dg9SARjAFYVnqNxFp0wY7Sp3LnhjgYI\\/LmpjFtXRo2k9Tqp4y6PqaF2jZyVj3bnj+bIOT3wPWsuW\\/njiaKMv5qxMjBpPmIJyW9c1nw3UM9vc3cj\\/MVIjJyxVgPTr171jxyMtxGTJI0pJU5yGI7VVOi9binUWljrLW5m1BXluA5kQlDuUDKAdiO\\/FX7uzSLTrS\\/kcpZz79oHzbXBG4Y7jHriuJFw0OpGWJiI4lwy5OSM9TjvzXRXutS3WjrZWyIUhkaTl1QbSFAwCc9QSfrUVKU1Jcu3UqFSNnzGfq7y3ulvKv2i4YXDrHleABjaxPIz+NVtCuLyLW7d1xG8aBTlcBvmGcnuKLee4W2lia5hSGY7lU8nPTOQfaksdNtRAtzd30qIwLKVAUsew5z6Vvy2i0zJu7TRpalq0DX92QjzKVdZnJ4OM4A+g6kYPJrMtLGOSBRPOEDKGHGeoBx+dXWOnyyKLCBfkG7Ej8PgAHI+vXGBVC+cieK1iDeY7AADp7YqI2XurQU5a66mpDpZbFlYSJLGsoLuF7Ec8Hgiux07RGspYb3zooYVUxjjPzdBkdutY2ixpplpOYsyxxqqk5JwzdzwcDitOPVbi407cY1dCwHykbgdwJJA5A43E+3evPrupN2i9PzuddLlWr3K2q6hI9ztaRo4yu7K\\/MpyBxj6\\/wAqpWcBvJrpZlk3QtvCqTyAORj24z\\/+utCSLUnuZXWSNIGdU84SbQfvHjIzgEHHue9FrYMb2b7XMFVCQfLlyxAz83A9cfgKqMowjZDd5O46wsbpCssNnP5bkpK5faMr9cZHf61HdxX0Mv2aLU0khjjHlwhu\\/Bx685\\/wrUkWC1vIkeWWdX+UEyfK2Ac4\\/AdDWXq6m6WOIecreZskiVR6tj73brxjjjms6bcpXe39dxy0Rt6LfS6bulvJb25VwMpjdh+DxkgdD0+ladrrV9JeLKsd0ImhBXcAMcdfbPf2rlHtrqGCMXF1O8Jfcqk5XGNoPHXt6VunUJ4vLigBfa+1phGGxkbevY8jiuWvhot8yim38jWnUtpexr2slnbOtxdMEld2ZYScnuCAScf5NV9YGn3L27W9okio7R7znCkkdx1wM9Peueey1fy0F5IyYdkOQMZPIPQ4646+lSRXdtp+fPeVpWkJUI+AoHQFupPU9f8A6+P1KLl7RSu\\/LYt1tOVqxrv5UcvlRlA44JDbUHA\\/xFSyXBtXdjfQjy87+dxCDpgD8K57WPFNncQTT\\/YJHKhizCUnO4Dv14NZyeJbiEFPKikaRTyyElsnGOuMfpTjl85JXX5CeIijuGvRJCzAmF0i3M0smFKk8D\\/eI96z5ddt41wJ0mjQlpDu+buVH4d+tcILy9u5DJNcsyykhSw\\/hGAe2MVHZwB7uSK58sRQD5ZNxZnPfJH+eldEMqpr4iJYuXRHYQeJIhPJPeWVxC8kSrAhOUO7+IAj72O4I+9Wjp9\\/YXnnsrIiKuxfMm2szdQQPauMn07Trg3SwX01yEXIRXGV2nkj1HT9KghhLXdvHBb3K27AMFaUZBHqQBjOB2\\/OnLLaEruLs\\/67ijiZp6q52VzdaUgkWa8IMBwuOSw659+eKzLeC+1Oxmuolgljb93GrgZK9z9B\\/SkksbMf6OWdWckhW+faCeBnPPHtVUmGLY8bKEhwucFDjP3sD\\/PFTToxivcevmv63KlNvfYh1p0sVgd5pFuFT5jn5FOeFA7cHr\\/jWTFqZFyjJbvK8WSVHyBsjHX0yKua1Hb3Dh3uWYAFllK7g44OBz9e\\/YVyv2WVbt0aa3QgktE5bORnA6d\\/yr0qFNOGu5y1JtPQ6m31xmtpvtSSm3GNiAk7eRxn8vQVmXmyQb1R5cZZWZjjrjnHbH9ahfzri2dWYRfMPN2njjAA\\/QZqe2vzHOYSscm0cfTbnOfwq1Dlu4k3voyldTIypFMXVjksMjH1H6D8KdpRihm3MhDZ2kNtZSvspHXitDSdO0\\/VdUhW8l8lNxy+ep4IU\\/Xn8q6y08BINT860jhniDAhZJGxj3xjHU1FbF0qK5ZjhRnN3RzSz2FpdfamsYJpFIeIRMy8n25HTjp1rpPCOiXs0bNb2cllbyfMZHO4sCMDGcHj\\/wDVXX6Lo9lbO1rqOhadFE3AljclhgdgQc\\/nWyypbq0UMKOc\\/IXX5cdga8DFZrdctOOve9\\/+AelRwSbvNnkXiDw7c3mozR6fDdRiMAM8wOOw2gD+ddD8PbTVNGeWDUrC3NqwKtKikMeg5P0zXe3E32dR5qBF2kj5cc81wHi\\/V1fURM2pSLa2wzMiSAbie39PpUUsZWxsfYuOnfdlVMNDDv2qeptyad4SiEh+1wxlmZnUkksCT8pJp9q2lNanyIrGyRT8rpDulPpyQD78V5vqGoWBitpbSIwRu52hpC7OwI4\\/QVt6bq8N+BA1v5aLgGTI3SHBGCcdTzTxGXVYw5nOT\\/T5dfxFRxFOctkjqU1a1tGNvbLczOcb7qQ7yEB6dsHIqex8UXOoxhpvOktXjETRrMVIGeSQQeTjgcYyKztAsC+o3V\\/LJIscjJKIVIITj+L39q6hbPRrS5Oy3OwHzCjsNpXj09814uI9hTfLytvv+f8AS0PToxaWmiM5ru7+zMZVkBgiVRBIAxZCCBk\\/wjAxz+dY39nalf6RJJHGsIYsYWk5aNApIU5xnlv6dq7DUvEtg5mv7dLbG0hsEDIB\\/l1ridd8YSOhNvJGqRkKAF7EZGc4HP8AjV4KGJqv3KdtVv08h1qtKK96RXsNNmt9PE13qQtpllAX5gSwPU+vbp9a5\\/WNPt5LpTLqLyy3DbmYsS2COB144q5dNLqEu2S7DH\\/lmUGFY9W46dMc1RttKurm2jaGIth2LKw5KgAfkP6V9HQpum3Oc7P0R5NWfP7qiUrjTlgE7SykxpkBudu\\/sD6+1QXF5bybJ5N6xFlUDHbHJ746Vo3ljcvPssoJ2YHEg3ZB446\\/rVC5tbh79bNolSQp8qLzjHY+mRXoU5xluzlmmtkaWn3enWzGeZ5ZS\\/MRHzYI5x25GRzjtXTaL4mupLCS0t7SIRKC0bE\\/M46HIzz\\/APq9a5Pw74SvtT1qJXbfCNskjdAg5OK9f0\\/SfDtltjMMMEyRY4Y7vUDr7dPevAzevhaTUWueW\\/oengo1ZK\\/wr8zn\\/C1lpkc+qazejyXuUjjhhJwAcZLBu+eOBzxXSWtjoy28JxEwdWJYvyRnkknvn+dc9eW2lTavu1C9H2JVVljK8s3+GQtO12+02W2ZoZITtwAFxkHHJ4+leRWpzrzTTlrb0WlkjupuNNPY6i41Lw3bQtJHHCvl4G2NBkkDqAOuP6VwvibxJp8cwtoraaCOS6yryrvJbBGV5OPvGsGG8kj1Li5hE0ylY4JEY4HUjgegH5VNbw2+tWljeXMz7bdzK\\/y\\/M2M4UDjg57+ld9DK4YWXPUba9X5\\/qc1TFOqrQsmdnpo1JLbUJNHZLOK8cmEXNwMnBIKAKeOd3JA4xS61rmp6J4eSa9gnluHIW4ZWB8nB46euV49BXPahq81vcieyHlhwT5seGaMbSCx7ZPA5pt5ea3qmnrauJHkaMM73SKseMjHbnOOPbNTDL3UlGVRLlur99rb\\/ANanLUxChdRZDovjWZrRJdXOya3lcD3+XBUr789elZ3nQ3HjRYbhwPOhzCZ3PIOcjvznjHtTL7wt5s7XWpi6e8vpAUe1wUUnA\\/Pg+mKjElpoF0IZLe4a5UBI2kA3H5sEA4wBz+Oa9mlhaMXKVFatPRbL08kzhniJNJPod7aNLZNDYi3jS23blPmgeYeo9+tc7r2habLCpuYZraHzJSrZwcvuxjtkHn9aoXt5Nbyvf+bbyFY2WEn5ijHjj8APzrN0jxVNNKLe6Tz2jZpHR0OQwPB\\/+tWVDATpv2lN+oVMVKatIzPEehXNux1GOf7REsrL5Q\\/1gXPGT9Oe2K17HxSumaS8MUDOC25YSQWVeAcnsKS18S2N1qjRT29siSAbpFQZBHc+v41ZsLPRLm6nNuXupJgTIJMKuCeeR39q9Gbbhy1o3sYxkk7xZlXnihL+WKOLf8zAOrbefQevUU\\/WNQeFft7Wpe8lHlOoblVyWwe3T+dWWtvD41IpaRNZXUbBMgb1Bxgfj1NTxaTBHHM0lxJO0p5buBzS5qULJRaJqSbXNJmG2rB7JreMSWpABYkkgnr7GtvwzqKJZSQ3MSndlmySSf8A61M+yQLOBGgyTzuGSepqQfM+EK7VO1j05HaifLONkjnVW2w+3ezhv5tyzNbiQNEucAEj+Qqe5ceY6x71DA4Mh4P4\\/wCFVZ7gwhiPm2j5RjgnFJFcW16PLuo3ZhyAnasZUr+8zeliG9CH91HsUP8AaXGA2Fz\\/APWrTGnG4tj\\/AKPsbHDMAW\\/KoY9PiUExh03n5cnGDWfrt7qGm2TOtwyyBtkalu\\/9aj2bnJKm9TrT5IuUloGo21nZROdQ+RyPky+dwx0xUWl6\\/YQPEjQgRL9wqATnHeuKub6eeUzXUjygcYA4\\/WoJL2QsqqQi9cZr0o4C8bTdzheKaleKsehX3iSzgVhAu9iuS\\/Hp0Gf8K5SW8+2F\\/OUYOSSc5x7fnWP9qkLAjbkf3hk\\/rUs1\\/K0ISSYYPIPf\\/wDVWtPCKn8JFTETqbk0V40LlIEEWTypyNw9z2qOdYBK80Ma7SuPLJ6n1FVdksu8wo3yn5jjrTYkuLuRYolBOOOma6VBLW5hcle6mkj8vedqcgFun0Hfv+dSW85knGF81VHRl49a2G0extLSIXrKk8mcENxj3HrS29strYytFNG8ajJX+9145\\/DpWarQa900UbMrSXc2wP5O0BeOgI7ZA9OBQl1PIMW\\/mOrfMCxqoRFPOYnPydivyg+3pUvnQiR1TgZwSP1Ax0pOK7ENtkxmhtU2ytiTqvPQ+4+pqlcai6OpiRB1JI5BqpeHEnloc7TnJHOaFl3xqjL8p4JJyT9PStI0ktXqTcuSzmaFG8wE7c528j396ljVRjeEAC5GRgZxnv8A0qnJIZpMjIJH8I6D0FaFnCkiAzkqVJJDMFY4HQAjj0qtkbR1JopJUcRo2NxIDAbSD1Hzdu1TrExgaWXaF3HKcYyBxxx0yOaZAAUDrsEkYyWYM2\\/A6r0B9cVYLNuW4km3MdwJJwcYBHv6VDZpYoybw48r7zAcqpBAPp9aayEQE4OVG0bmzu+ntUipKxLSh2ByQcd\\/THerE9t9kKI8wJ287GBLH35OMdxVXJKscVxISWjdl2gdhjjk\\/wCFRXUwJWOVTwMYdcDirVzJLckorncAoDL0IAxn27VVnjjATfGH42gbs49f8\\/4VS8xMhZiCBInykfeHYde9I5DoNqmTnbtPAHvnuasNGvlAuACQWA3dcdzUW0NLv\\/1jA5KZwDz+VO5Ix4GWASyxkDOAegI96Aisq5kIBGVUfT3IqyIChxdNswd33jjnvj6eh9KhVXRxIjZ25JJwAMcfn+vNO4WLWmKjxMrxq6EHDMcHkdev9atic2LQrbRRspPBWMDdx64zWXamR32tKmxRkHado9efWr0Uk0sg8s71P3Qv3QO306\\/jWM43eptCVthZryZ9ysVjkLFnIJPbpj1p3nx2hHlqryZLEsozzxiqwaIR4dgZRkhCuBntjjrVrS4EuGcCNSQM7ieAcetJpJFptvzMDUy02oPNJv8AL6tgdPaoGEcjokafMw\\/vdK3dSsS0hiVCEKnOByT2rPGg6qJFMUDMc\\/eUHA\\/GtYzjbV2OedOV9EZ0kMir8wCD0JqCt2LRry5ykj4EXLkDOBWlpvhOIrDd3k+LeT5lXIDOB9cYoliIQWrIVOTOXtIZpH3xKSE5LYyBVkSSRRusO1QUG8r1zn1rrPE5063tYbPTlAaXqyZGccYAFc55ZtruGOSUM7sCwbjHsSamNX2ivYKkOR2vcF0iUhHmkVi52jqMeuTimXFulnKzwtESThVPJHscgUyZLrz3VZCyqcnkioCGlLb1LADIz1HvTXM92TY9ftorjSYkmjQuLSQOoVuuQcn6Yxz7Vl+IfEeqQD5UWTzCQxZeOQSev1zXO3qa1PskuLmYbf3aqfvD1GT1qvONSVxJN57BJCymbJXpgAjpXLHD01K8tWdcqsmrI6W3nea6iW5095ZWHMrOQAD0VQK2WGiTqkV8YYzCARAAwUDH8RbnPNc5pVjrTBgZdiSMrmMRjhh2HUgD+tT3drpVhMJNXcTSBdmyLjYuBhjg9ayqUoTlZP7i41ZQjdo1dU0nQpbJRbStBKMFERMxjk8nOM4zWEmj3dnYva3duzybtxEa\\/vWyTgc8AdDVQXFi8ssWnyyfOQQZH68nKgn6itX7BqcsW+xWU\\/IBJuk+UsTjIHbjH4irjF01yuX3kufO7pFXXbbxBfW8a7naB490aiZHZOmQcAMB+GOKdpngS\\/uGM8t1HZLMVCpMxwVxgscc4rVn0fWJoDAsDzyeWPNeRstxjryDj8TTNQsNYnJk1SeaIiEr5Ue0EDI564o9q2rQkkLl1u1czb\\/wvo2m6y8H9rm7jiVWEkUZUNn0HJ6\\/nVvTnJ1KKTzmVIvkR0iClhgj5j3JGf8ACtKx0S30u2USQGRwBJl5lcuO2AoP6+nWprzTLa4kW6aAxsclV2BQzHgnOexOOlZTqpuzu1bcuCtsc5MGvdbkZvMitlcoQWI3dewFS2rW9vdIgdDaRKV8uJ2LPnIAOen510MOmlo5RFEkQQZdmk3KD14OP0zTtKs9lzmHT1lWbcgySwZvUegpOsuWyQcjbvcyIYYZ5ntLIhY32yZK\\/Mr9CAc5q\\/Np17p1isVrL5cQwXjSPIJPXAPqAOh7VIFu7UZigFmC4UjjIPOeRyTkVNavfQXoe9kupBgkrsKqyk9jnnGD+dTOcm+ll+JUUkjP0jw5dCYFcxNI\\/mDzUxnBHfPof0rdXSZ7cvBaLFGAAZpmVAW\\/2V5JA96z7Kzn17WpI7C5RVdmaJmJwq85B69uOK19PtL7T5HhlEblTt8wMSCccAAdams5PW+o6faw+2sUgeUvdyYCeZKVXcQoye+3g+1PuNV0q4txbTWk7wHhgwwxwCPqM8c1HE8lmLpklH26OQqCMkleQ2CT3JAx24qK2ubWwvWnvbVmHlMFTbzux1YMevNY+zV7vVmjncr3Or2kGntb6Vo8cGOEk3ZY\\/iOKlsJ9RktC95FACFwTKA233yMCs9L+E3CLBKZpJSWx1CjPIJ79Rya19RTUo7e3uk1C2aCZx5kUW0Mo\\/hyO+Dxx\\/hR7JdOve4KexDqVzcNDjT1MYjwWMIVScA9G\\/H\\/OaqWd9rt0jrNY+YobghcMoB749+vNb1pAIz9i\\/tC5hAx80CgxliR13cD8M+tS3WgRzXLWlvqjwMiAuyZ2McjjIAPU9qxjyK7kl6lSbvZGNo9rBcTo8DPb3BGXDxKwx7dPzFbKxWcpaIyyXlwMkbZlQfljIH1rROi3FnA1pAzTqFB37tvJ9B1x+dRPaLppeLc8dznYxwd\\/f16D1+orH2ntG7P0NlG1iFfs5heO1tbfMIw6SSM+Dk4A6Z6ZqncSW4nja8sLPcHAUSBhtz7Z4\\/8Ar1fuAzEPczEbup2AZPtxWfOszwKwdVjUAjGN4HPP404RTY3dIm1GS3t715IdIs55IlzHKm9SD75J56dqotcJdXDNqFpbkxIAV81lxnpn8Ktafxeg3ARMAuQrY47AgE9cAfjSXLmS4e4nkg2rwhYKAR2ByOD7dK0sk9jO42G9gjuVW00my8khfNLgycjpgk8YFad1rV35L2Yjt4owpI3IqMAf7oUD261jm9h33G+2leTcRFJGB8pB7kcYPPX\\/ABpNMu1hnmllmkOFEhJO9iF5CY7Hnp\\/hRKmt7A3oU7a3ubZ7iGC4a0jZsOZI+eewPf8A\\/XUUFru3zwXYVIX3b5WwTgj0479v6Vqy3NjfRM8kwErkEwupO7jvg5bnv9ax4La71FtrRtJDACRnCKPU45PY9a3S0benczv0KIjcO0sUrks27eGIOemT3rT0fUZrO5iEs04VGDHZLtwe3JP8qjntFmjH2dWVUGAykBSPx49vxNRssX2RLbyCbh5PkKj5QOxNErSQ1FHoll4olnslOoqJlUYBlPzD6N3qaW5NwFlt51Zf4FlVWBU+hNec6fJNMXiMcLLjJQFniPGM+oPHUV0E15b2\\/lwGGGXy0BYMuVUAY4Ga5nTaZbVx\\/ie2TV7afTpT9lRyAwQblJH3flzgD2GK8w13wzrOlXANmkFxuyw8scIoPHynucdB0r1uy1jTzEq3D7Qy7Aq9h9SM1Subxbe8EtnGkoXaW3EAgc9CRn0\\/L1rqoYidHToc86XMeU6ZqepWVrIbmCFXnOBNMm3aN3XHHGTjJpp1K6ubM3d1FGkYk3rKCdwUjBGFwMc8Z9BXomvWzax+6uLWOWNwGUsocqW4bnt2xXLyeBo5VkVBNBGF+RZCCvGOxPpXdDFUm\\/f0Zm6M7e7qcdFqsYMkRhmeJn\\/dRqxAYYPJP4DpTLHUZ5rNolURLHJvGScn8ccntVzUfCmr2GxoWhu4QzIRBJ8w7YIODmq8TR\\/ZWDPBYxKpyM5lx9O1dq5ZrQ59YvUyVBtNScyiQbj8ysfmGcdasxyRG\\/mkhneQKv7tmOC3GO3T8qyhcJJM7zPJIzfxOck+\\/NOtbt4rpWZ\\/lYbW5z8pGMVo4makat\\/NdRN9mx5YKAbd\\/rn0+tP0mxmt4pjclIxg7PM4LZHaq2vyJcXkb27RuBHtOM4HrnJ\\/lWdLczySgszysmfvHIFLlvErmsy+6TQO0aE4+9lCDnv2qlLcyyXKttYFRgc80t7cS\\/JCrHcB8wByPwqsheNiqqCzDHIzVJaESZOpmaUOyuhk+6fX\\/OKmnlxMYjKHGeo4BrW0fw7czwpc3TMMg+VGOccj0+tSzeEdRe+dITEYlPMhbj\\/Gs3UhfcpQla6RW\\/sXUL66UNEBlC37uRSDgdARnmtTT\\/DF6EUXcEgiZtqiMCTaT\\/X2rq9GtF0yDyFiWQkZ3D5WOD2yD6DtWpb61DNdPb3NqbYEl1xECASvJyvf0GK4quJqXtFHVCjG2pHo2iadHASNN+zwyxHdJJnf2yMde47Cs7UtMQXzumnxiQ8pJjcWX29M4P6Vq6jdSNBCvmvPIV2gKBkE9DgAbeo6VVukvWnBH+j+SRnc+\\/GRyceuR0\\/xzXHCMk3JvVm7UbJWKOyCO2ml1ENEoTbFGmCMfMST6\\/X\\/AArPaI6hqCrbTusKBQwU7NseecDpnjg85xW1NBBLbibUFe4SNt23y+QMgn3Uj06devNWr66sLfT0KQpHKsTEKqnIyBjOCM9auMrP3d\\/wQOPfYqSWunpZiC4lddu0qVPyuOTgnJ6cn\\/CsqDVw\\/k24nt4AWZUUuAfTcfXp16\\/nVzTr5JrCI\\/ZpXkgkMkgdQo56Ac4Ofzplymgrp6yRWO0I5zLdyFthBzjaB6nNOCs3GQS2uhIr6GWZoI5VlEcS+U4ZSUbJPB75GRSXd\\/DDMbSWRJ45rfl0IxE33eT9D+GKw31a1uJk062n\\/clTHlF2B+vHI+neqWgRqk08l24NuSYow\\/8Ay0kPQeuPUitlQSu2ZOpfRHaLezyW0TRW58lI1VSvJfIJyCQQPx9qausXLySxwrKBEd3BH97gnIwD34rNvdXuNJ0yKDYhJ3EMqgY2nbwOwwO9YuiXNwfNe4EkcbYaZ9xHOeATxx6ioVBOLbWhTqWdjpiNXk2GFmWEMZJGkY7hxtyfbof85rGNy8Vvsu1QyyOMFl\\/hOTwSQMnB9atXLRW0UHm3SxmbnCMQDyDs49cDn2qxJbQyW0EEkUYktypcM3DjIIyeO2D165pL3d9vuG9djBTzvKTK+XG0bZEvfJGffPHp6VegvAjpbgpJNBkE\\/wAK57gkdckdj1rRCxtfXW24V1eIvvK\\/JGdw+X0OOefrWTFCtvcSX1woiCuVRIIyckDrj06DOAMflWqamiNYkkNld3bxlZNq4LgjkFAoOfUDqP8A9VWY9Axb3PnXRVvKMgIcBj8mepGMdB+FJI9+m\\/UGkEEcarsUHJKseRnsPy\\/pVe81B5CVVYlJU7sZPHUYORk9D+FK05P3XoP3Vui9b2Vx9pLXXlQRC34dZOANuAvPLdBn8aWJ4RIsU0p+QqxV2BQjG3jHuentUEfiFViLXIWRFjEUWM7DtUevf\\/OaxrvUibpSkbQLPEWj3ZXHYEde\\/p1pqnKW+gnNR2Oov1DXRgjufJAXcD9wBQMdRzzyeneuauL1Tdxw207FUYM7HI5BIx3I6+nepJri4uPJEayqfL4wpUHBHc9cd\\/QGqb3rSymQRKEZN7N\\/Gv6\\/Srp0uVWJnO7J766kWAMqCMLlyNn3yfXtwfzqGaKHVJnuZb1LW7kT5R5RO5h0XOcg+9Lpd7GkPlr0dNhyvUZyP8+9OtpLVL1kR2jjfhTzlG2nH6+n05q1eN9BO0upiQ3k0LotynO7gMMYOe+eo5q7GyCIP5R+TG3b\\/Ecn+gH6VYS1gkJhnh4HKlmPBxzk9fWuj8KaDbSQETXszrIylo0T5gV6YPpzmitWhTjzMVKnKTsjBhQyxJP5O1CCJShO7HZvT8zXe+BPEUKwsmpylSrbYzH\\/ABpjqQO+c96ns\\/COnAok0V+w3EkN91u4B9AP61d0\\/R9JSQsQAEkwiIpHTnrXj4rFUa0HFpno0aFSnJSua8uqac8RlimlMagkt2HoelZWoazZQ2ZuIybo7gFy2VznPOORitow6aq7ERUYnbxzuFY+oadBP51tZxq5UD5QoCqD19Ae1eNRVPm969juqc1tNyXRvEEFzZyi+sbdGRgFInyrZ68nHNYHi3StH1Z9ytOjgZIt1DBehGSevStnTNO060jltrxbe8dMz7No+YlgQPf6UtvqKPcTvZ2kcazM6sSwAUnGMDnitYVPZ1ZToRennZfjqZyXNBRqM4u28IRWpH2l5TMX3RKw4C8fMAOO\\/tV23sJrW2ntI13yKyMihSeCeOc+p\\/Kum1bULeAm6vpYZWaRUAUjCKATwOtZ+t6xp1iftEE0ccswDlsHByOM11xxWJrWTje\\/3XX6GLp06exnaZZ6wNWuo2QWzPGruImADbh0wRjPJq41h4huyBBd3JbeYwWOMJ6k9xz+VcVqfi8zzybp8jcfnCsDx0XntkU6w8U3URSDzXhiG3IDEF+RkfSuyWBxDXN7t9Ohz\\/Wae2v3naWuiLdsqzzOYo4CjAuV8wgnkj0\\/wp934Yt\\/nXbH5RYMq85GQeTzzjisE63A0zxxsqJIm1myR0ODx34FWH8SXqsYrWRP3KbCsq8lvf04FYPDYtSvCRr7ak1qjag08PBFFLAsSxrtU46e59uvH0qsbmC1uAIbpDsjZNzttVRkZHTk8VFbm6MQu7zUliuDtQwmTcCNo\\/u\\/Wrbae17pMMkzD5C+VZQCWzwBnpxisZKMH+8ej0\\/ruaJtr3UXPttvcWjG2RYllRmUFc498d+BVa5GkW1muom3XzUcE7lwxxxjP61npcQaU0Dz3WY4eCyRjcTgjHNZHiHVrTUv9ZbzSFpAy+X8uB6cf49adLBuUvcvy\\/1oE8Qkve3LdzrWpPIf7PnGnxsQfKXBBXAxjC++avJrMi3MN4IvMlSXjecM\\/Hr\\/AJ\\/WuJvNRuV1Bo9oh8ohFjJGcFQFXIGfWluJrqS0QLIWVVAbykO4Z78\\/Q8969H6hCSV0v68+v3nL9Zab1Om1HxpLDeAS2C5yQCV+8PxHqKo3+tz6hAbiOUja2dgXaFyOFyRjt+tVNO0XWr87xZTAIVPmkdD35zyK2tL8HwRSTHW92Tt8jyXK\\/Nwec1Dhg8NqrXXbX8B89ee+xzCzOxM0c00UyqGD45H0Oa0dFXV5Jh5Ntdzxj74YHHOcYxx0967bS9A0KylMojt5JiBuEjDgf5\\/pWpbPpcMXl2626xFjtA6A965a+aRaapwv6lwoWs5SOSjtbq11Ga8lzdypGwWGQggk88Dtjn86LrVFn03UE1V2t4lKiLynIbIXoMjp26d\\/atvVtTj0ySQxWtq5Kbvki49Blup69BXPWjxasQb2I\\/aGXgMAi7u4xk\\/yp0ZzqR55x0016iqUoJ2T1IrbxmbmSOz01fISNQgaY\\/N7nj7wABqWe8vVhMzwpLLErBflDBifukDqQa0ToWioizXVpDjPLRsCcemOvpU6NoVtMoWwbzlAVd7E8CrlWp39yD\\/rzIjRtvJHETQX94UMy27Xb\\/vli3hTGy5425wc8Z+lZbX6PE5v7Uy3Lb13R5BU5B3ZHDc59f1r1TUtKstQhQSK0DPnlF2sFx0z2zz+AqpHomj2KxrJA8mFIyPpWsMyppax17A8FJvSWh5NoErWtzN9ozH5kRTBBHUfpWtpEslhF9pklXa7fINxDc+3B6\\/y967eb7NbiR20vy4VOP3nJ2461g3dj4enuhuS7Mm0SEYB457YyMnmuuOLVW94u33mDw3KrKRq6JBAJGlS2DMRlHJyC2O\\/vSyiW3GJmKlmyxA4yf5VpeF207cLdILhLlcgeYuVI9QVOOp9q6C5tykscTJE5I+VN4G4fSvJrYlwqtWOr6pGpT1ZxL6nDEVU9R\\/FjJ5q3b31m6eVBGFLn5mPQn\\/HrWxPY6Xe3zQs9qLhR8kYkGeO2M8\\/\\/Xrz\\/wAcXsml6+LeOJVjiGY1Tocj\\/wDXW1G2IfJFNPc5amGVBc17o6yTSLy6k220CTRkZBVgOoq7ZaHeRW7l1jgkU4AGGz+VcF4f8XXFvctLLEro3BVSQQfau9Fxa6v5MtlqohlUAlGPU9wc8\\/8A6qzxNPEUnaW3fc6MO6M17q17FnTIbxoH3W0Ejx8CSXIUH2FYerwardMlm4tXuJHysIUbMD1OOPxNdgjak4islurUhvvMXxj6VgDS5VuXWd2i8s\\/69QBu9snk1yYetaTk7HXOLcUlcw7vwPHqEym5ihsNwOY4HJA561Un+G8EL7o7vfkn5X4ruJbVLn7k2JVGN27d+dVLqKaxgBmukcscF1ByPpmumGOxC0UvkRLDUtXKPzOCk8DSLGyrdRlcZBwQc46fyqpL4LlitS73CIqjMjZznjpXqFo0c8DL5cc7LjC8AkUl1GWtUIsdhZwpQrwB681cc0rJ2b\\/IweCpyV4o8idmtGG1S3lgBWC\\/e44z2\\/CpYrq+iuFS2tYmmJ\\/eOI\\/myeo9f89a9JbTtKVPNudPVQzcOT1NX7DRtNtpBOittbGG2\\/dB7DitpZjTtrE545dNvc8vl0uW6HzWs4kkYBQoyMj69K3rPwvBawt9vZ2dgRsPTP8ASuy\\/0eCYtCZs9AOPzrbisNMVcXsxuC43HgbfpnvXLWzOUYq2x00sDG\\/meC6ho97b3EpgcyqOTtB49P51mIksaSy71Eh4XC8V7N4naygjP9nwiJM4dkXLcdQB+NcJqNlYTbFmUsV5MgG3j1Ir1cNmHtIq6POxNFUp8qZwx3DLFCScjPv3oC5OBnjvjvXZLp1tdI0NjZjcoLYz97+oqF7AWZWO6jRGAzhAH2H0Poeld8cVGTt17GEYXMTTLOaRxvTAZdwJYdMdfXpmry27JaMdhJdiA3496vsBJbJkKr5JCleWGMdh0z360gLtGsgQNgHcGwQh7YGcY6VXM2bKKQiwCOyZzdHzDwgUkkj2Huf\\/ANVBaWNNrQOmArKx6ADnr0FEs4lledH4xtySPbceeefaiWUSWikswPAUEdcdhg8Ae\\/vUjCeZwFXzHYrkDzDzuJHPH5VEzM4w28NtzkqOepPP0yad5Sywtck5ZQSqjBC9B+Jye1Mff5MX70BEUb9r89T04\\/z61SJGz7oQZSnOAVzkkZ6HuO3Wo7cySybyrs4+b5iM8dTzkYqciI+UzhQ+zBy3U9sn69PpSiESXLqAkjcneGB47\\/5NO4rEQCmRlnDNkbg2SQO4A5xg+p9TxT1MP2syIhUHkD7x7ccCmy26xylJXwAAd6kkcevv+VTxxoIXMXmOq42\\/7R7k9OPwoY0QOFY+W5jDEE5A4QnoPrjtn+VEEEZtyAiySu+V2jceO2e\\/UdKtpviWPe+UIxuUfdOe3p6Z\\/wDr0NbLNc7IwxfBZ5GbKgevTpn\\/AA5pXCxUlVhcGMxmPn5to4wPoMfjSStPCjESyBT\\/AKsDIJJ6npyBjFXbiRLY7YX+YMofgEkj+6fr64qq8LXMKOQWcFgEBHA7d8k5znPSmtQ2JLSKAxs1xK7kcPlFK7geBU9hO63BtVWXDDKNjkc4\\/wA\\/Si0t3mXcXiwCoYY5yOOPp7VpQ6btWRvK5354O3I\\/xIAPoKylbqbRb6EMQntpm8qGJ3LZDcMCT6\\/rV+4uH5dpHEsS5Eb8ruH+zn1qje\\/ZLaXfHIqSdCrHcR\\/n1461g3NzdXmqSOHaVG+8hPygduh5rP2fPqxSruCaJrm6kM7yzSpGzH5kT7mPQnpUMc1w++2jRpHPTC42jP8ALmmSRYmGGPnFMrtHA9hjNXbXfawsgdoS2HkLBiSfpVuyWhxuTbHJp7o2bksgKfKWb8+hrOWzuLqQeVCGCD52LDp+eM0lxqV1I7QW8W4dSNufbvV+DU7hbUW7oLfagBZAOfTPt\\/jStUirgh13pNyjK5Vsjbli4IX26f07VFe6daJA2ybL\\/wBxOD79aqXOqu3lrKzOA+7OcYPQ1p2v9nXNoXyBK7KhUr9333D8fSj34pOX4GsbPQ7JrLT7Vmjk1GSZ0U4IVRg\\/UnnH0ptk1xNEy30MMEEK7o5d\\/ll+epPcdulVdN0+OW+muog86KuSJQMZwMkYznnNadyVns2k1pFaF1OFCnKg9OT+HSsJ6aXubxdyTTLSXUb8wx39vZQT7nVzIZmZR16A\\/wBKtaxonh0Mk159qniBx5vlALIOmMDJx+ArNhksIbKBtMkk8lAdnlsQ2M4bvgn60ul6mbi8Z5J7lliIeK3kVc5IxjAHTH\\/6qzanuna33lJrZ9ToPB2k6VdXT3IsbS2s\\/LZfnQIAD0Yg9x149jWHe29\\/Frt3FGsFnYod8cW4FirED8TznrTZb24fUFSWLzJ5G3usEh+TPAAX+L3GaW31K+uY5rtzDIEIBUgtImOM46DP5c0owak5PUblokTarJfiSaazvFSJiB5mw88Y4yea5+HU7aC72w41G6Vly5Xjg85z75rVlW6msFkkhcxhwg3BvmJAA2jPOBjsfrVrw\\/agOsUkTICSCr8HPbbn+VaqKimRe7J7e7QOkr2TxOMoBu24Uk8HHHfvnjFM1nULy5vIrZ7QLBbn90I4wrEMBxu7\\/wCfena1BfXMKadZXEAVDucCI7x12lieRkA1mQ3c26KKZJU2EHeCW+bJ7Hj9ai3vXGkraGpHZTahHH5MsiomEeNQFC9Tnr856iqUurXFtpMVjAsu1J1kYMcGL159QAKsx4lt5I1aaLDEFWYjd3zwapX+iWsRaRb+KZFPBL\\/M2fQdcirSje0ha7l7UtW1C4vbS1aKBoMrjzOrHkluOn3f0pzajcJDPLHFFNNLEQsb8ckkHjPQDtWPNHDZ6W80swin2iOINy0gHoeMHr0FV7WUnVAJIQIvLBO0dfT3HesfYLlslovx6l81n6m3ot4dOuYgVaMqQ0hRMsDyOOcDiti1khTV\\/NSeSQsDucttz8uRyeRkj\\/CqOiM9tDDc2\\/kZL4MMzbmKnOScr94c9fUUyGaQ3F6jQW05njZY1CkiJsDLAAY4A4471UoKbYlJxK8099FOqIixOsucmTdnDdz3BxjPet65Frq4+1TSSNdRRhjEu0bl3Hp6n86xLGGC8uZIr+\\/MaquMeU2QQMKvXof69qr3JuhFE9pDFvZyqSsGULnGed2QB7c+tKUddNyky0YrMT20llYSW8zF4Z3YgBw3GOeR1POPwqcPLaxXMdtCZZAitG0TsxXOM4yMnvnnt7VnroctzqljBcagkqupcxxs2A\\/Byckkjr+YqW6stRtrpozGI\\/mEZ8rHzJjP1HGODmolyu0blxT3NfU9Rt7i20uaJZYbpTiSYKykkdcqB1rT8L6WLi8N5c30dz5S7vs8Ib72O+T6dqxpNHs7Kwa8tdRljCuCVmbzyR0xngDpn+VJpuvW0GvRPFeNb26EBnZcbsfz\\/Ae9cs1zU3Gn+RpFWepteIfFUZuRbwxtESuXeeJgEPYZzx+FUm11tQulW8u1X5N6OyFAw45wTk8jiruvw2PiJxPZzSwtuXduU\\/Nz6dOSO\\/8AWuPv7632XEF6kUAtQ4LL8rsVPHRRjnqOetVh6MeRKMRTm09TfF1CZGEDrIWxuzIVA468n+tV3sI5HuZbW7WeCOM8SSqX25+8oHpz0ODxUZitNT05Ht4ZVik2s6rOTkEdOSSe3t9KhtbSzsWCwWiIqKElIfc0jAjI69PYmqitdBSk9EWbF7JbRZIxP5+z97jblVBABB5wOn\\/16kmNlPF5ws\\/N4A27s5boeh5P4VYvbyz1S4jeOGW3jJ2OnmAcckBdo9Ac5NVLPy0SQJFEUTlSzAs6kngbeoBHWhvXzKjtclt7qK0iMZg8mXHy7XOeT6dcdKZaT6ld\\/afs0Tpb+aFaUIgOc5O4gEheAMjufrUAu7QSiK7iIBQq2G5A7YyOB16H8TU2kW1vPepELtrSFpkiVVYHaowQFPrwOM96Tjb3rFuV1Yz7mWSymthPibzX\\/cthixUkH1BGAc8+var0ttC8TAh9xfayebjd65xTvHgjga0Fjaq32fcGZQNzNnjgZxkDOSen6ZbzPFG8ciSfKFkidQQZG\\/u4Izgk9eOorSN6kFJGTfK2mXvIJj8qGRopF5XoSP6Zz\\/SsuSNIc77hpGhwECsF38885z17Y9a1PMWbbLJbA8fvESPapY4zwTjpXNT6HJearLq5uIYo7dh5EaMOnP3u1TTs27scnKy5UdXp9zbJCEt547dlj3S7xncfwHvVLWBskjgJKzJwXKncwbvjjjj1rb0Tw6t3b27P5kW5csqyFMKR7HoOuM0niOOL7bazQyp5yqyska7\\/ADAMEbV65HNZRqQ5+Vamkk7XZhhjGW+0MhUjCrIw\\/qR1\\/GoNJ1Jrq5vLW3WWR4irMHTCsMZ9vw57VY1iwa908tb2bxqVRo1kiVSwAPUNnnhv84qposkGl3d20cRaSZWlmdgU+Ynjbt44\\/Hr71s1F03ZXfYhN8y6IZ4gnC3VpqAXKCQB3LlcKWAwc9uW\\/KteO1s1ure4N6ZEyrJbpyrt90nJ479\\/biqHi6K7vvC7zCzkDFA+NwJ2huv0xipbSSWPwsTbzyNchNuQg+8BwvAHIwOMZqJR5qcbO3QqMuWT+8f4psRp9rFdWqRyXHn73U9CDk7RjqeBUWo3wubNPMsLW4UoCEkCtx6Y9R6V0WoW\\/9oeFGExMc6WrSbWXad4Uce3NcJ43jhi07Qxps++FW8xnJJKBgDz35Oa0wVXm5YPu\\/wDMzxMN5ehz2vQ2F0AtxYpaumMvA+1cemCPauSurZYH+VgyhuHzwR6YI617np2mafr9tFDJbRLE7KHmACyozZyBnOBgdBjnmsLX\\/hvgq8N2J4ZSzoGGxhjg59PqOK9KljKd+VuzOKpQla9jzWS1R1G54yBjDImGPrntVIiNJ3jySh\\/i24P5V2934IvGWVLO6gVIwuUeT58n09qzV8OHQ5ILjVL5IRKSAgjLbsYz7d661Ug9EzFwktWjM0q3tZoxM8c0km7IWPOAB9Oc\\/lXTzzWsbQsbO3EuxWUCAsxyPfv7VFugMET3UlrBASNkUIwWHQEnPYemfxq7aNZWD2s5Au1nU+XC7YGM9DgfQ\\/U1lN3NIJIlaXUJkaJZVtlZ8bgPk2nOc4PsP5Vdij1RfKiEz3AGRISgRs8chfTAPXHQVavbu2laAxIPNYZVFUkIMY4IPA59DWXdXd5aqRpUwjVjgwq7O5k2\\/NnnB6Dt0Fcr5no1Y30WqLm1UlIaRbWNskkqGdk3EgDnnoc9KfdahDE8TadDulceXCEY5cEDt0GOnWs211NtPtQsy200pU7mI6cnOM9Mdx9Md6Q6rDPK4EMLLEnmYZQRuHYHsv0x+FOMGtwckafh+3uoLg3F4RLLOxYuuMIo6AtgDJwOn8qLzUby6vF8lOmWR94Vkx\\/Exwc9P85qjBfx6lDbTy3H7wpgnJ6bjhevP\\/1z7U+w1D7NKixWdswnkdmMUJ34C925znOe\\/eocHdtjUlZJGnoV2Wt8yKDvfEkhydx4HBPvk\\/hWbq8OoXN5ut4HZgrGJkkCn5fXirstzEkT+QsUUasVTbIQ2e\\/fjPHas\\/VNSMDRrG8ShcxsY8bnGByWx2yPypU4+9oVKXu6kcV5ftprW0lrGZznr\\/CMZ49+vJzjFQ3kGp3VrcSRlWhfEY3Kc8c59SRyPxNY+nR3N\\/rax\\/aSDEzEuz4wOxGf8K63SbdLmKTzYFkEL\\/fkG0HgYC845OefetKkVTd4oiEnJanNQeG1tHhlmnd22b9iJnbkZ9R9Oua27fRFmtElit0CqQQShXeezDJOMg88dqiUssky26fZxHJt3qwBIzyM5z360skmpXiwxpbrNFEkkj\\/ZnJLgDLbv4TwOgJxxRUVRq7CPJsjXis9ES0YXUQu5EwqvnzAreoHAOT7YHNZGo3kv2ow2xtgyOuFjTqBwMA8cE\\/pV9PNvGRRNKbdcfu9u1unGevPbHvj0qK+0oyC5ntdsbNsKmQKJTjHIJ6AdenQcVzQtGV5f8MbS1WhShsZbcm6uoN5jRizysGG488DHJx2HfuKsalLdSfZLS2aW982PEqLCCcnOegxwSB14qwkNpI5F\\/NvnT5QFYbFOSfx4xS6nOHjiuYreSKFdoYx4VmOThc\\/wjPXFXfmkritZOxixT6pZ3tzcvBIsHMJSTgEgjK59eh9a1tavpBAcWoikjwAIwWXHU8d\\/xqS8k1A6escwVrWLJdCQ5ILHqSck4xzWbcXT\\/ZIjaRtEz4LlmLNjoM+ufc+lNe80xN2TRaWeO4sIrqdwzJKDgoyqVOcgY4zj1zWVeeWzxXsMsrysChbf\\/tEDrxycfhmrUMFxJbu6OYmeX5CwOWO085z\\/AJxUUej7r\\/7Rc3yN5SEyqrMOdvAGQFzn3qo2i27ild2VjPkif7N9nltkYZUoxfKqWxxjPQY7U9YolkikSEp5fBKPzMT6k5wuTjNWZikHlwhGYseGVzh2VcEnv1B4zWPd3P2G6fy4Comb52+Y7BnnGee\\/et4py0MnZal2S5MTLtjhZgrKgj4aMjPJ\\/HApbw2l0jSXcSpKYhtCsRtbJ4\\/DP6Cs+W7nsblQXWQowGEwQ3Iz+f8AWrb6hI0yxTw5MrAKdvBUH09R0\\/PmnyapoXN0ZGkVtbQvAXka4K74z94N6DH0PtVUW6wtFJcLIyKCzCMDJAOc89P8K17X7PHZSMoXduZQhA4P1HIGOO45qgbmZBnCFQSqMjFgTj1xggEY6URd27A1tc2LXWNKg+WXTHUAfe8xdx+v4VuWHii28qKVLS+htwcK6bWJPYcjH4fzrmGnmvpgJ8yS\\/dO4FR2wN2Mnnt711EVw1naLHJaB4YVUOqRAgle+4r0zn\\/GuKvShomrv1OmlUl0enoW7TxHHfambVba9t\\/KXMksjlWP1CDB9celPn1i2RAkXmSFW2p5pVgTzgn39jWLLq7+b9nG9YzKRJEeCec9h7jnjiqtm0yW8oWPfCzF1R15c98Huf\\/r1h9Uhva3zNfbvbcde+KNaLea7xSxF8IyjHA79cCr0GuXi2suyWDzmJDLG7H2zk59PSsx\\/mhmM8flCLakcbP2\\/iIA61XuLjSxdsil8KvK4xh155HTJOfzrodClNW5PwMVVnHXmJ7a+khuEe5vR5m\\/DBgc89MEDPTAxViPWnuIvs+5GjI+dQTggKeM8knj+dYl1fXAJeQw+WjbvMUgYIH9f51ctrhJIBdTWjDklEOSu3JA4z069fStJ0I7tExqvZMjur8sZJnBjjXkIEyxPQAH6Z61Is0l7pV3NJaxmSOPALLwmT8rY6Z5HT1qpq1zcG13QJzj958vzKfQD07VT0LVW0gl3G+HzOEf5SR6Y\\/wD1VTpXjdLUSqe9Zk914WuY7FLyXYEdggVH3O7Z54Bz+nGKyligFyEuLvzChIYImNvXufcVva7rWnXNopga7FyGZyjsTGpOePvEH5eOmf51jzMsRW4nQMlxGyoVQDnkjAzyOn\\/160pSqNe+RUUE\\/dJ4pXupnlUl4IhvBKY27cdfXr29qtgwm3eaS1KTyxgl2+7j1459PzqrpwkeMShXjjiXdKxXauMkdhk1f1AXdqJLu5X90BtXbngnBGOgbipnvYcXpcibUhHdFGbkE5KEYYZ4brjofSrWoapfW\\/lvJNI0RwE2thWb1A+mPqRWLcKfIibzgSULKvO8k9iPQf5zVUao1xGInG10VhyBjJ\\/z+dV7JSs0hOdtGbY1kMzxzxZ2jEe5i25uRnPp6fWrM9xHI+EZUQH+D+LpjHGeuRz3Fcxe3Fy0yuZcoi4GEwB\\/njmugtIrSeztW\\/1bscluPwxjoeB19T60pwUEmOMnJ2G3cqXCsPs6CaLpJK+GIPTjv\\/gaq20LyrEJp1V+NoTAxjjrirttBaLPlZY3zhmY5xgYz16\\/hnpUlx\\/okDNahTMFUY3BPl5Gee2R\\/nNQpKOiLcW9WblnY6xDp6rps+Wc79rnY238R1yaEuNestSB1WSNFjOVlZ8lAc8AZ5zx1\\/CodJmuJLKKea7CB+SEBBXnjn0PFMkSxgk86a4ll3NhjgiMnsOTziuJxfM1Kz+Wv3nQpKya\\/M2RrdrHZSSm4jZ5ZGBZ48blB7ZwSf8AGoH1eB5IoYYYvlH7zY3ze2fT\\/wCvWJLJDfs89wjGRMECI7cc8DDHnoPWrUtmljZfbIozG6p8+5QW5HqOn4VH1enHfdlc8pa9DX0rU765kZVtxZqFIjaUFi2Bk9+nvVhbd5XDSSW087RsVZE+Y\\/oMCuXg8Qz3AkidlV2tyU8uPoB7euarQ6le+YzSThQ3VmQDPH8j74qvqk7u1kT7aNktzpdB0bXDeKXmEkLLzu6qM9Mdcdf0rYkNnaMs8\\/ltGh5CkkNkdAKxdA8R22m3bKkdwZzgM0bAIecZ68D3rak161uLOR44mjk5UuybtrD36c\\/WuLEqtKfvR08tDamoKPuvXzIjq9rFKDbb4PMPC4JFWJtShupI4Edp2LAlgn3D65qlZ67p0UESz2BvJ5Ru81YwAOe5\\/wAKfN4thhiA\\/s9rViB90LuGfwqHQk3ZQf3r\\/hxJtauS+4yfFllPfsbaG\\/unZT88UCFhuOfvMeBx2qpYaClvbrDcvJZyOhPnSIGJbPQ46e1dZomtR3arxcylycPKcxqR6n\\/PpWVr+iLfbri914GJyFVIyVj3Z4GOfpW9OvKH7mWiX9dF+ZUqUZe+tWRaHa6Jp8iySarDNcMdzF5sb+uTXSxyPeTC8sUim2jCszAjGOikfXufWuNj8Jab57QpqEVzNGhQlJsBR0xjOT+lXbKC60No0kWREK7sRvjnuSD\\/AIioxFKnVd4zbfn\\/AEhU5ThvGy8h8miQR3Oy8uLe2kkf5pPMIYMepHp0IqhrHg2GU+bFNKVwNrSHcevrXdWOteH7q3Rvt8NxMDny5hhsg46Hmp9Uih1KGXNiiqPl3bh+dcn1+vTmotNf15lyo0pp9Twy70W6hvXhiXMYk27yOPr+tXdAhu7W\\/kd5MIO5J3bc4JB6V6DPpNhbOrX88aQE7hmcKrEdBisy31Pw9DK0khSBVB2+UA+\\/mvYjjXUjZRb07HB9VUHe9ie5nsY8MJpY5MEjDs2enJ2jIGKqeJ9UurmbybW7RYBjJX5TzjB+Yetbun2sWoW8V3pkZlilG0GTCOB\\/9ar17YlDJZ2rIGSPG5h1\\/MV5v1iFKa5ldrv0O5qbi7dTG0eCW3tGur2eNvMO6NxIQCPcAf4U2C+S8do2ZN6tu2nJBHsadf2kwszbtOpmHXuTj3rnRp+pOrC1fkAjcOK3pxp1bylLU5qtWpC0YrQ3pNUsbW4PksFLckrmtq08U2jW\\/k3F0ShOCrJ1rzubw14hWZVigaUuOCOM4pW0PxDBMU+xsSVJLZBU5961ngcLNK8vxOZYrEQb5TvI7nRjOtwvmSLu\\/wBWTlVP0PephqVrFG2bhxjosgxkn29q86m\\/tLS4\\/PvlMYABCZ5NUL3VJ7obxOdrqAMZ4Pt60pZfGduWV13COOqR+Janc3+vJZpJMV2GIEBwuQT1x71zdxr17e3PnJcFTtxtJ459P8+tcqLq+V5AwLIp7nIA\\/WrOm2c0w8uN\\/LDZYErkcep\\/KuqGBp0leVjKVedXdmil5PNBMLy5dFZsmMNyT6\\/zpsQsZZXQSBFON7YOB6ck\\/wAqgvLG+eFNtuHjU7g+OW4Pb8KgtQZU3SxiNUPU9CT3OfwrdU42bi\\/uM+W250JEBglt7WZ4mfhWVcFyMnkjBJx+VVGmggjQbYXH3neYEscj8h\\/k1VjkzcmaSVWIO0ANySc8DGfamXc5upj5YCSdAmM7h3z78VnCk09wvbYtSos8kZkSQbmHlFcneMf\\/AFx2qK8s5YJo3RcgnAJBHIHULzjrjn0pbC+mlla3hi8sleBvx8v1zxnng1owyymLe\\/2hG2\\/JDt+UA9cn8qftJ0nZjUjElVyhZGLxkgbiuGJ9P0oikkYFTncPlG7BKrgg9qt6ja6nJa7pYWjTO7ywcfQgCqlszNbknmXOAFBPArthNSVxkyxq9syKpTZEXfjO\\/wB+MY5\\/yaqxpCFiVZgWxsbKgjuOPXjHNWLWBJGBcBiAVjVwcEjng\\/Q+taFssManyvIlmyA4OPLUZztHJ\\/P+dTKqoA2jH2rJKN8hwzAEY3Hrjtj\\/ACKcybNhZpCd5HlBdrDGOw9eauNHKbxY1g8lJZDudM4wff0yDUNyPs7OBDHHIrDcrDIGOhAJz6VopJgCCaRcrGGDfLhk3YxxknrkYq0qRM6QiCNAV++z\\/ewMjJwD17570u+KMCadWdAQzgnBbOQdvr17ntU1zK1xAZ4QsQICFlyWTt17fReMCpbKSKgMyZVuSSqJtwQjdjkD\\/OPWnRf2jcFITMPnyhkJDDBPdm6dDzn+da13BFLZqyyiZQNg\\/d8ghuhP0Pf\\/AAzJFaqC8ccu6MZAk3CMBm5xub8vlPSp50VymU1oReGKWVJn27V2uHww4yGPbjr7HHXNXm025uoAxURxxndFIowG5wAAex9f1NSjyTdBFZt0YwJAB1I3Yyp3fjnPvV+a6lCRLIsE77y37vOVGec\\/TofpSbloCSM+9uraw0+SMRhCmNpJ5duuSPTtgg+uR0rmJdaupjMWZiyqWGD0HoK2NQkuGj3eVEUXrxtxyOpPXgnrxXJXIkigMgCmN33DPBb8B2q4U4vUyq8wNHGreZ5+ZSoba2cfSnStLGu+NvMWbqo456d+1VIZZpJSUVjJjjHUCtjTLFmtpzKUQhD8zHp3zjr+laTfKrswKGlQXDXXmlSNv8WeBkevSrupi2YonnEXGMsfM3Z\\/LAz7Cq8R+0XkqqzvGqEKAOuPam22i3V1tMKjzGY5j7gf5zSdr3k7AkyFLmMXGPmOcBW3dPXP51pxSCOxljjQTOmRllySvtx\\/WpU8MnJkhusygZCIMsOPwpJrqCOzENuhLxnY5JyXJ69O3uaiU4y0jqW4OO5nXOoxTBFIK47gZwfXBqGx8uW7dvn2DJJ6f\\/q70MhMqiNdikkNhScf402O0nZna3hlkjzgkDj6fnWySSsSem6fbST2JP2h5nBxsSUBsj1zxjk\\/zqzqrfbRHbS28zRAAKD3wPXrirqaMdMLtPdQXIK9Y14VeMnIIyf8ahhvHiu41tlYOjAHDFSyZ67cZ\\/XArz+bmd0dtrIoJpk1rKIvtbxQEeZ9nSAEDnuQOPx61PFqMrNMtnIr3SgLHEMDp1Y57duKTVp7nWZBp6kqgbfvhYDBI\\/ixgnv1rF0Dzjq2dM2SGEcmVQAWJ9T0GR9cCqcXJXe5KdjbigQzwl7hGaaN2lDhtqMAMc7eRn2qxLp80FvFmOK1dmXeRMNjDPXbgccjqe9YsDtbeK7RxM8kcsksTxb\\/AJFYqTgdiOvPr1rvL1LU29pJPbJ5iIGaUxoflHVQR0HXqfasqknTkl3NI+8jldbuJ5J4IYw8cdvFvdm4ySCPkYD1546Y71sTWrTaRFLbHydRUsyFiS21uenpj1\\/rXQPoWl\\/2HNc2JAfySIFZRMof3BJ4y2cCszzGvLIabJcyz3sETNPJJHtyRkDb0479hwKzjiE7JbIqVN636nOSw6xY3jNLqUUsz7f3qggEjGQD3I44qtcQaqdQilW1mEcUf7pXGC3Unpz2NbH9lTx28TLOzTZAAc8HI4GeoJFWdG0TUbfXY7y5mkt7WPDMzH5HHUsufr6A1q6qV3dEqHREUNheAWjys6JIQF25B3dRyTx37EfnTVSOTTWnihuAnmNFndkgjO7se\\/p2rstUFncWL2VvLbZ2KQoKltxwASc8ZwKzbbSk0vXI54YROtzHEGhYfxEHJ446DdjjpWMa3MinCzOJv7qCWwjh8t3MD8KIsZPcEcHqB3qOO\\/mW3Eklo8RbKR7rcrnt8vXjvg++B2rfu7OGDV72FLKPcUADpgky4yeGIAzx361rQRxvbG5vrizlcZiIiX7g6EHHfn1\\/StXUUVsK1+pzK2Wo\\/Zo9SaaYJGuZWQ8jPTOeox7dj+OpBqt3HLHcxpD9paJlMUxGWyOTjI5HHr346GrM+y51Oz0xHdYI40EjqwAlIZjhv9nHOAevNY2uz6fqD2FlpmpWt3d+eNwiYsBGVwdxAI4wvJx29KUJ87SaFJWRp6RJavYTzTTLNLDH5g+Xdv68e351UttWikighJnhKAHHy9cnGTztx29KbaRRRxSn7W0sgBDjyziQnhlz049f\\/wBdRm3F5ZGVUl8nJGwFeGB9OOnP5ijki3qCbRtrrptZ2Bik+0gqHkMaOQPTIXv780urO9xC8r3conl5M20RsOwUED8Pzrm9FlitpZrWViIp1BXHzPk8YAPTkHPNX9QuUexS1e9uI5Q33cEZ44A47ZFYVKSU01uaQl7ruc5ql22ntAlsZprcbkJkXYOvUcDP4cVfstPvru3s7KPTUtJZ2yLwyhi3IOcdhg8fyq7p9nJdW\\/kS3LSTR4zGuxwAcEHDAnjnOPbFdNo2hXv\\/AAkuJpY2RYl8p2XKKduQyqRxkcdT39OLqzUVfqhxV3Y0I9HS10KRxK++2hYuobGWVjxgHFeSeKIb2WS1vn2oJSwKxrswox+fGf0r6JM9pKs9mbXzpyp8zYcgjHXtXkfjq3MuhC2yluYCjxgdZM8E+vrWGXVJRqNT3ZWLSlBOJyGh3U5tzD87GJgQqFVOOcDJ\\/L+tdHpT+fM8E7mDCbow+QRyBj5SQOvU1naFp13eO0FvunuHRThXMZK5\\/vHp2rX0rw\\/qC6e63DSxXCOG8qX+AMcjnv8Age1dtScOZ62MYKXKUdSdJGu1O95sk28atjAHVmPp15yP6VXfUJNOsyIoxHK0aeX5iAljkcfT8Ks3rw4MVzaSx7juEiENz3IOcYPvn1qWPRZ2U6lezNcH5RGG+Y7unHOMdDj6c01FW97YLu+hoWlreakq3cux1PyfLwxbHc\\/\\/AK6u+I2tjoUNsYEF1Go+zN2LIeeOuePrxWHqEsNyq3em28ySIMSSJkZzkYOD9f5d6pSXBl0vzIbwoypnGe\\/HAJ79ah027MObc1LHXIbi+ImtWa8ixvmRNgUjjOOQfyq9rrTT2wYoVMKqyCMlvPORmTgdOBnHTisSymcxta2kcj8ebIvXcM9TjOBkYz79a6XQ4IpYXsL24kW7mx5aSSAqO2QnO0cnpgd656kVSfMkbRfOrEDw2jSPDptwGkkTc7StyijkhecAe59KoX2mWEely3EztNcR42+Uu4PnhWHOG+vYYrpoNBtpoZ2N01te20Q3eWQgXgZI\\/wBk5Oc1RurWCGzTUNPczbW2FGXOT0LnbgD1HIxnpUU6i5rJ\\/wBeo5x0K\\/hzxVLfaeLC4C2VyI2SN52ZdwOMZI+XJxjmoTF9kuRfSz2Mk6u6GWNjg4GSoH8I6Dpk\\/wA5NZisIraJbyfBmBaJYzk4A5B7r16+4rL0i8ntrGN3t0miDM8bKF2IO3P+TS9mtZQVr9ClLZSNqfW\\/31lFLAfKePMyouSoCjgeuRjHbvmsnxBLax3GjqbOQznKSRK3zIrLwTjp29e1X7Ow1KUS3efNwGlAROBH6ZOSFxWHNJPJf+RALVljjZjOx9CMbT\\/jVUoxcrx6EzclHUvXup2sEE9opTfL+5EDkkgdRgfifyrS0u4sYNLS5nj4iYysY24Em3AJGOR27dB+HLaHFfXfiZ9kq6gFbJZlyqKyjGMcA+3tWhJDKbeexnju7Qx7NhkA+dRnO0D2xj61VSnBNQv2uEJSa5jpmuZtQ0J5gWhRxtCzsC25hgqDnPtmsHxg0E2iS3zCErFJEEVRjA3jKn1wOM1fs44Ly1a1W5LzD90DMAQhySW28\\/dG78RS+INHsyW06K4jla8UAvGjBVO084IGTz9OtYUUqVVf1oXO84GZ4dvCtknmzxwNKyhSDggE8H6DOfwrW1W7u4rb7Hp7yXhh3Ay\\/dV0LZUZBJI9q4DSLW4PiE6LNcCSSCT53Yc4X7oAJ9e1egeIZJ7WwQzQTQ3B42BC2FyeQBkYwV\\/yK2r0eWtFrVMmlO9N3OY0W8udJmvLa5cpvtZRlFz5abm3gcZHOPoQMdK4dt+tXUFvdM6RqhKuQPlJ6D0H0r0PxTbW8dxHP9oIjSMMIgcZV12vjpkcD866PwV4T8Iaz4eW9vLNxNC3luJGJTcAORzjpg89816WEqxcXN9TixEGnbsePy+E9Ymj8u2gd44wNrAFsZ78DiqN7omrWzrayDzvLJBTqU\\/vDivotNE0xHeKCwjWHZtzIjYx1\\/hpsvhaJRHJEkUdsqDdHFD5i5I5z6Y\\/CuiWIS2TMY0+7PnnT9aayDW8NtJHGOWGDycd+amstUe\\/1WGOzsN0pbcBsLYPTOM479a931L4faNePK9vDE+\\/kNGdwGeucHge1ZCfDI6Yz32mgrdeXIqMVPVlOCcfX2rGdf3W1HUtQadrnj\\/ia7D3Z81UWTowj4XOfSs\\/T9Qa3imVYlfqOehFeswfCK8vCHu2g8xsn5CTg\\/wAvekPwmvbB28gQysCTveUAHjpgjilCuuSyV7EypzTu2eeeFm+0FVaPbFCpfJO0e4BJrqzeWzokO8KIkABkVQ7AEkbTgnHOP61la74M1S3vFSHT5Li3AwoUZXd0OCKyX8PatEfs72sdsSOJGYsOh6cVolCrZ3tcfNKKs0WtVu7eO7SeOeJ0LeWgDnIbsD26YzTmlGoGWWW4tTIFDOIhhFA4zxwCfyrIHhx5FTfcySyMxyEiPy9eufoamuNNMdtdWe6K1k3ABCW5I68kc\\/0rTljsnqTzMvrrFppl\\/HFZRbCD+8lcDcTzx06dK6S01pWtWlIEz9XLfocV5wLWd7om4jdivLlenpkH9fwqQ2eowKwZpY1IBG4EH2qJ0Iy0bKhVlHU7GW9mvZbiOKEmBju34AUYJ4BrTtJLeK78xYi1y0bIsZc4UHqPYdyMd64CXUNXEe1buRQMchjzjtV7+1FhSG4GpTSXO8q0Rjxnpz7d6mdHSyLjV11O9k\\/tRDGkFnFaIxJLD7xGOuTyeap6kt3aXMcqBJVRMFVyOpz6fh3qrb6o6iV0n80FBtUS4HP44BqxFfrfyPGJZA7D5uA24jrj369qwcIvVmqm1ojKWSX7fJdvaFRkMOdvzZ45\\/u8HPT8q0Y7pp78JG58pkLmOOLcuMjBJ9\\/8AGtrUYVsLaNXgwJ32g7wdnXqMAc57VjhNQmjiFgF2MFLiJVXb9SOelZwmp9NCpRcRt1NcKptLLT7l0Vsh9gRCvYHJ5x6Dvms+1N\\/Errcw+ZOWBCrgEDnOOvAwOMc1q6ZLeWkM9nfNuIlBCsckrjt61laZcXdzfzSyecsJXG4BgM\\/49K1jyuL8iXzJou2Mjx2wtrhJY4ipY+YmTz1bJ56Vk65ql7bTyWtnJcRxGT94xjwCCPYZAqzeXt7LLdOpmdFUIkZUbivqc84zk5rPt0u4pAskcqmQCTB2jPJHIHP+fpVQhZ8xMp3XKaOnxQ2GitdXssUksY82NcAlieeuRjNPjXT5lCXVoCsyELg\\/MDgkFRxuye9UZdJaeUSJKwfgrBLx9eD6\\/h1qzao0sIuJAiupZQn91uBmlO1rtjje9rEEFjpkl6lrCAREMvJKGZsg+2B0qY2OkQeZefLcvHzHE+cLnGBg9ee49RWkmkyy6WRHJHb\\/AChfkThj15HfP9KjtbKOKZgkQuUMO18EhlbPUD8B3rN1+bRM0VJLdEukLpq2n723hBeEh02HqSCMEn27epqtaG0mv5o0jhSCHBHz53AjGeQdvNNgZYJFW6gkkACrJG8ZO4c4A\\/MduPesm5udSiuXkttKkTJZY42T\\/wBlA6jmiEZNtLqKTSSZ1F7aXInWYeTBuOd+PlAHc84wOf098SuunQaXcSrqccsW8BgWHJGeM+hOOhrD0Qu4RdVuGSUlgGkJ6hW6H2PaqVxClrcmSWcBTuPmHLLnsQP4qyUOd8re3luaO0YqS6m3cxpHMJbC3jDsjYJTAUDBJ9zisie4m1BxIbgtIrq6CU4UBcAem0c54649qYL0yKibhcAoPM5wSMc57AdfWrEsMTWcdydQjeRVy8fXbgL2649q2ilHfcxd3sZF\\/wDaprlY5SN7qX2pk54HQgZydw\\/Oo5IikgmnSVI5Q3nKrjfjJAODyMYrTutQii09LjT0EhEmxmFvtPzKfX39+1VZQLmzWXyS0k7H5gGYgH1PIHPat1J3s9jJrUZbmQ2YhSUtEh37CPkJPQk898flUmnLJKZftNyC+35pMgqR1P5+lTpbTS6VA9vIgZ\\/lYbCWB7lff\\/Go5YXt7e1tVTcz\\/M0YVlYkZ4I\\/LJ+tNtMEmiLVRPF5RtyEUHj5Tg4HBz6\\/WoLmCYRhJIUulcDciKcZ7kEd8mtkSy3N\\/DazThIgdpWRuOgAB5\\/r+AplxYWLhZElUso+6pO0DP1x0Hr+FRz20ZXL1OeNlDDYSNNazQyhwoG84APUmr93cwSQWUX7iBeiCNm+QDknnpnritC4vNJYCML5TBdu8DLEdvpnpirEOk2OpactyIogoI2FFY88Z\\/l29KzVa9nJMcUnpEzLeNba1jvrYlic7FyCQ3065P0pyS3WoQP9okm2MSsaY3HOOxYcdQf5Vpw6LYWVuDJLtZifLHH3ehXkn37dqtXumaezxsZJWaN9y\\/3e3y+hOMflUurG5oqcjjn0if7TJL5NxJErDP8AeP8Asn\\/PNTR6UgubT7TZC0hmAMcrv8vc5J5zwDxXV3LK8v2eOIIjKYj0GT3OT6f5FZV1prspit0M8oISN3YY54B\\/+t7Varye+gnSS1Wojwxm6kmkWIzc\\/vT05BHy8c8AVVkhSQKkSv8AaBjLjqOSRwR9OffH1ux6XrEIaS4lFuucMTJ94dAPbqeBWpplhLdRyxxm7ZkG0TMduQR6nJx9MVHOoq9x8rb2MG3s7WKF7i9nhIQkMhGSG9sd8Y9qmtLTSPNjjiiml844ILAnk5GB37dfStnTrGCYymC0QbYSJVYBsvuBGFA6\\/L\\/k1p6PpifZLqMWcEF4kZkj8xgzBs8Y\\/DgDsPepqVlFO9xxhcxb7TEjQoNqxxncFMoCgjAORyfwqeOKxmu44bwWweUCSONQxYkcEgetUNJc\\/Y2a4EsilipjLern5T+eeKkW3iXxGk0+Le3gAkjlkVunIwM8Yzk\\/iKlxeqbKUuqRsrDp1sWhnLwFRjKlSGPOBg\\/ToPaobwuI1tEM0sLJlVBHB55JHfPbNF5PBdTG7iGY1UIzAYUqex9TTNes7K0sY5jJGfO6SO3I69B+NYxSur7mjk7aGQtnbJqMdyEu7dU3CMrHvDnlcAZ4568dqjfTLu+Vmluh5bMshVo9nYEZwenNWI9ThS0FqJoHUxMFBwTg9RnOT\\/jTLKKSbWPJlizBKPLXa2AB1LYB5HA\\/KupcyV3oY+62aNqNM0+IRNdRCcYyNqkZzkAk\\/wCfakstRv47gyPb7jISQ2zAAJ47YHSoP7Mkgv8A99\\/pEbushRepI5HbPY8YxU2tW97I8l5ZwpHbwEgCNwA49SAc5znqOgFYOlB3vrfuaKo9Oljb0\\/P2gmNYw5UYPUAg9vSrk1grRlZhDdOwA4XGW4OTjoKy9Fj8QNoUdzbxwRiQkoJpMNgHk4PA+pz2rJi1\\/VYbq4SYSTC3k3M8AGAM4zkcEcV58sLUlNuLWnmdPtKdle+p2EdhqkUQWK2ZIQTuSBcluOMf\\/XrQudLuZ7eFf7KdGQ7leRkJT8MmsCy8aQqyCW4Z8cg5woHX860rbxXazbf34kB+8xPX8K86rDFxd+T8zopxov7Q218OeKYfMaJ7NwHL8Km4qfU4zWNr0uvNFKH02Pg7CoX749a66HxJCtsCjLhyAQB1FPt7yC9nfzDCVA+UEYPT8xUwxlaMuarTTt5WLlRg1yxkzydYdWDrbC38sJjkx9MHI+Yc13XhDV1umbTvtEgbb8smwOGYdjnnNXfFGrWlpawWdtGxmc\\/PtXf8vT+I1U0+aKxi22lghlGHaV2BZj2zjFd9XFPE0byha+3+epzQoeznZM39S8P6RdWIe4lVrgYO1l4H+FZEfgfQt6TCInYc43flwal\\/4SdoQ\\/2u1t5XJJAWbHpgYH860U8QaXJEWjMsYcZJ8tiOO2AK8\\/mxlFWV7eR02pSetrkWnWdroSx28VndSQyc\\/e6euB1p8t1II2+zW8zS5ACyDGRn\\/Jqr\\/bOn3N55CzX8UqgFZJF2JyO2f61oAXbyLC9o0oHSUYJx+FRO971Fr5kKLvZPTyKM0TsN1xbhWBySZBgVVub+0s2LfaBK3mBREPkPJx+n64rQutKiLPLiZg4wzKcbOvavL7+xvZrx7a2nMgeUCPJYoRkj8uPfpXVhKUa7aTtY48S5U37qvc9C1LU51s45LLRZfMl5ZpV4AxwRisu01i9e8ktLmzkt5eq\\/uzsf8+V\\/\\/XWBqOra7oiKl6ZckBY+coF9wTnOe5FF9PJHYz6k0zLdWbB4d0rnBI6Ant7Y55r06eDShZ212erMebW5leLLHXNU1QAg+UGyFCnB59Peok0Bt5a4mIKjABkBPTpgdOprpb\\/xPNe6XFA8XkzlFMzFQpJPUA5GOMGubmsWjiY216JXeQDLgDbxnrnJ7VtSq1FFQlaNtDirKClo7lW60sC3lFvOpZWGWbgL+n6VXgjljtY1e7STDZZAo4X146+4NUby4MfyPGzTIcAkcn8ce9Mub5poER49oVQNxz27fTNegqc3FJmKNhb6KMmfzN8UeNnG0Ajvjv1pn2+0uIleQxJzlsg5b2x26dawRLJcRh\\/KG5cBDuGfwB60y4DHllkHy5Owfr1qlh4p+Yc7NyHULdFkjR22s2PlYDA9AfeorRmW+ie3yqyA7fkBwcdzWVp1nNPNsUD7o35wu0euTwK2\\/JhsYyCd7DO48bhx26jH4UpxhB2WrYJ33JNTvWhWNtyM5OJNqKCTzz7U+1vEUK7TB5hk4xtIGencelYsi27xxu0pXg4UdW9zxV+OztHWNy8khCZyGwDxyMdj9al04qNguPOqTTSQ5LuTlxuI\\/r7jvTiEikkuY59jsu7DEsCcegGOv4ce1WUW2vZltp7eKDYDgx84z3Hb0HtWZrDW1rAsUUT7MkFM9Tx70Qs3ypWC5BfatfXLIqsxVTjeowOntwO\\/FBv5Z5F8lJUQfKwU8fXPrVN7kyMkiQZLZAzk8\\/4\\/\\/WpjNNFiUfIxIyR27\\/5+tdKpRSslYi5oR6zeQ3fmRuy84bcc+30\\/SrpvbScM0iu0yfNy4UMRgDrz2\\/Wuc86VsGTn5shsZP4VoadFcSPA7CQKr4RgoP1xzzQ6UVqXFs2bSa1eWJ2jlyRkKrYIOcccEY9\\/f610Vl5Lqsz7WKkCT95leW7cE5Jxzge\\/HFMtLIJHDcz20iDKqflC7QR95mAx2zjH61OY4rjYsDOxAbzjkxhMYxnnnGOox0H44ylfY6UrEsdtNDdqkkXysGknUrjbg8ZXGBwCcd8GrGFlBknuWdRgRRhRhBz\\/AA8k8YyT+nFNXMchtLy9KyBOE3DYTjORg\\/U+uM8imCGKRC1vDJJDIWVUCfcHJBJOcdR0Pes9N2Wr7IRLRTBJlQ5ThIR8gPzDJzkkjgcYyM+tV7+4tYIzJdBEnCkAJlU5JwBznAI\\/zzVl3eG0aFpJdiKUH74BcYztHHU4P9euaz72we8svs9jE\\/lb8qokzgDhmYHg7j054x+Tvr7zshOy0W5zsniL5pIpGDI55QrxnPpVgTaVdQbboESOuNsY759atzfDy8RBOtzG0W\\/a2DjHT29xXSeHPDcdujQQtG823mTZlSuRnrnB96yqYrDRjzRlsKnQqxfvIytO8MwW2mLfX1wiRyNsaJU5jx0AzznOMmqQgsxK01nv2bPLMUuDnB759yOtdR4mtHubcxafJJPcR\\/Lt35ByeeDiuam8Ka1PGxjg3CLhQpAJOfQ9eDXNRxCqJynO1wqU2\\/gRj2lmN3lRlIpgSrDYBnJ4PXnmrfh52t9YiDyDcTwwx8+R29PxqxqMM9lbpZHySJWByAN3HJ59iags47Wxupbm4uGYNkCIDnOc8kHjjjiuzn5oPrc5nenJC+K7u1tb2RlXbNIMHywRhP6Gud06FZnJCSuhbIy3TjgVuX40y+eQSswmIzs3cA5FWtOhjEMYgZRAExhxgcDk5689M1cZqnT8xSlzu4afZ2yF31WAFFG9ck\\/dOOfToacr28CtcaVbAxYZVHTHvg1Jf7G050hkbazYaSMg89gQSeKoQ6fc3XlRRTRFwcfJ8pHcHNZpp+9J\\/wCRtF2skd5p11brpNxHfb7i3jmSOJjldp5OVwD8vTIrRsbFLi2uL97ZEhSJYoySVLgHnHGSMkDkDpUHheGyXT41vJpERLhlEKyDYSrH72Bk9u9XfGd3HeWksdoZT5M4ZURBGqpgA9OTyTWM379l1N0vduzBnvBZaRef2dZILiLJebaCFwcHjGSeOorD+HCXN613HEFTeSzP0bOMDA\\/Out0vS4f+EbmihijWN2PmHaARnkkgHJ\\/Gs3wTbW13rNys13LDOflt2izhQFUYKjHXGM4puquSdt0EYPmjcq61o8+m6xpcM22dZbl8twCG2FcY7\\/Wuzaa2sbCZNSXzYowFjQwfM2OMg5569B6Cqfi7T7i1mhkuGxErBwB8xUrgjkeu3rRcabNrGl2OuXLxPYhQ01tFcbCXHQFiO341z+051Fyen6mvJa6SMf7Xe2y3F3pbNFmSP\\/Rym05bI69RwwPXnFaUVt4lkinkl1O3gZ1WWZliAbcx4VuSM\\/KM9vb1t6iYtOsXZbCWOARkCOSfcSD8o2lSeenX8u9Q+GNLK2aarqF3MYt4nKPKGDqowuAeSB1FaTkuXnS\\/C5EU78pW02cnWRpesXc04Djy\\/lABbB6be3GK63WES705buyNzei1YBkjQ5VSuec57jrjpmuBvrFNU1yW806MlnjM0AwwJeNt3y8kYPPcV33gC9bUrN5xbi3E6FWQDjcBkY6j+I9OlFWC0kgjJrRmNpTXt5PPPaQsLp5EhSJ5BtjAxnA7duB6V0PimO8t\\/Kfy3N1HGCscYBxwSxY4GQAfzxWnpWmWF3cSah9neS\\/UrsZG2nKk8n1OCOtY+spKb555ZtzkGMuWyR3PGF446c1jBqVW3Yud1AwfDUZv9Vl1K9QfZ22I4MgbyWTB5HQHo34VueIhZ6frzQ3diZo59vlTxAZRsYYk9GHfHGKytCs4dRl1BvsxFyblYjFHysS7FywHQZxkk9hXoGm6RHHZxpNcrdyWe\\/Y5fPykHg8HJwT+lVXlabbJp\\/CcPf6FBqGqX95bW8kMkgVThzkAg\\/N16HkfhVEabY6D4I1m9iWxkmtt0ZliVkcOuACOOMcd+a7\\/AMMQaXPM1pazFHWJcZQq+VO4Enow5J9Oa4Xx3biK707wnb2nmRXlx9svWBw0o3FmznuSCfTtissPVk6ns3srP5IurBcl0YN9bLBpthcOgSWS3RmSPOd2BxjgnPPeoNOkmsLo2t\\/ayPuy4RwC6kMBlScjqf5Vu6bq4fVDALWGdbaQnzdwXy0yODnr04H1rq9TtbfN3M9uEkubdUUyOSBySQO4zx+VdqnKC5ZIwaTd0cH4h+xXEktzp5jdpzkBmMbQOep4789OlXLJwJ7KKN7VpEDYaaLczNt+YKScjoOlczqlslnrzWdxJ5HmAsjgEhWAyDjIyOf0rofD2ovpySxGFHimxzGeEx0bOOF7kkcZ\\/GnWglFcuo6cu5Z8QtJpM0d2LYWtzvy6Rgtuz2z+X+RWu0hu1s7pZAskgZ3Du2CuRhiPqOo9auaBpi69C41iYl42MiGE5TBB2hZOrLyTx6846VDpvhSeK4uLS11B47u0Imt052sh+YfKx6Fic15lWataW6OuEddNmaNsklsRLcBPOQCVSJGKv6jJ9e1ct4yt7TS7KXVLktcTMfJtYkjBGSBjdnpzuPHt6V0utW11cj\\/XxJ5Z2yxYHDjuD6D2Hoa5XxVcGSzsIXDeYsvO3kEkHGfrzXRhpKpZ9epjUThdGb4FtmSa4hcmW5DDzSmf3WeQOOvPUe3eum1TRJX0+zV1IGWeaPdyQQex5HHPNTfDMpBJfsbeICaVSGXhiMAnPfr29jVu+vUj8RyQXEku0yDygAT3xk468fhUVJN1m10Li0oJHH6jZS3umxadFAkk0JY+WU\\/5Zgld38ulc9o1nq81x9kmj8uRV2BTGW7YDgd+Mc17Lc6ck1zALbbC5EeWC8EZPX1AzWXe6VE2qXFy90wkDmIPDwB8vzcfjnrWkMauVxsQ6Otzk9OhnhvpILho2byTiOJNg5AGcfgOMisTVNMijtrye5nldYFDSRHYWRSMBs5ye\\/Br1C1j03VPD91cW8SrKqp5jS5C\\/KMnBxyM+lcL40tNM\\/4RPW5n1FJLy52yCDcB5YUnZhe4+Xn9a0o1+aVn3SJnCyZX0mE3Nt5dheQwRW8YSXGVDk5ITIJzjJzjv+dbVjAbGFZYJXNwnytGtvvAPHJcgY6AknOOlVPh42mTaDDHeSMH35KhMbSAoGNgGOB39OtX\\/Eb3kOoNCbWSTS4YXmQpH0YnOWY\\/e7nHXkcms5y56kqb0t+JolyxUkOSTVbe\\/W5cGdsGRCNrq8ZBz93rg4\\/A9KdqkuoRopstGurqS7byxwAmQODu+g5GO3bmtCyvUmXTWuITp6pIoQTRsAxIwcBsd2OOOorkvFP\\/AAlF\\/rMunaVeExW8h8uSKDLHccMTzjjpnHQVlTlzPWysVJWXe5Z8MeGb1blry7xfXjytGbYyqxjOcbQuT+OK2ZvtlvqLudGt2hSXYxlbcCRhSvy8YGD0PasjS7eT7Glvp8rLMj+XK0jYYoWwWY\\/j+tdZqGoPZ6dFbnWIgBJ5SJsBXC4PA7+nelWbm77\\/ANeRULR0I7fWL4RXEVpZSW89xt2wRINgGcZ3HoMqc5P5Vx\\/xNTTLvTI4bO9so7pWJlSzlO44H8WOCM+hrorTxBOLjUNPtvOuFV2iiaNSvmOcEgcdMse56VheO4J7XSfOuI4YZpXP7lRk4AAyTn39qWFjy1U2Os7wZ1vhTTdH0bw3FHFb\\/Njez\\/d3HHXJP0\\/Korayhur641ZrkghVUfvMBMDk89egx+NQaJ5uu+GLVAsqPGixziT5ShGM5H+etWtRtxPNdWhnQW6xCJUTO8DkZP5\\/SvNjCSrScnq27\\/edUpJ00ktDn57aEa7CLdVea6mCoCGVFDbstkcE4JH557Vc1Gxghv7m6h1JZ7mCQRRw+WDjAGckkDgGsm30b7RqbywyTboQVTapOw9Qx\\/IDp3q5d6NewXjJatwxMsrB2xtPByMd\\/avVmk2tehxxbSenU4jw+4Xxxq9xvjdvtW4FucgHgdenaus8SSy3+mx6hbo6XUERjGQFbf8AQnGOB\\/KuQ0KwvJfFeoS6WoEkZ2szAFlBJJPIHt19CK7afRby6lY21iNTgTc5Djcpww\\/LOD0roxCiqql1SX5GVK7hYxNaSwOjol\\/cWU0iQlI4FulDb2+8zA5JYZOMfTjNPTXNT8K2FpYadGBDMoLvPuchxjqR2+92\\/lw+TTbEzK9xp8UKSOV3LHhkJyNucDkVyHxYuDZarp7\\/AGaGdBEwCyLlSRjn3\\/Gt8I05xi\\/MyxCtFs7v\\/hPZ5oUN5fWruX5CmRDs9AWUhc8c47VpR+P5Hud8umS3myPAEE6yAj+8eFyOpzjtXz3JfxzupntLdQp\\/5ZpsOPwrctTYuiiwvroEAZUHZnJ5HJx09a9R0qc5K6OJTklue8aT8SdIWydJkW2uo0PmIFxls9Bz6e\\/9aktfiXptwGtxLcwfMDGyQSNuA4yMcDP09OteWeEo7NUltL19Ogh8vdNeT2\\/myqCcZGPyH51uWuqadY6rFf2N9aXieVtT7Ru3byD1RWAx09ORQ8HG\\/UXttD1rSJf7Rt57nTZ7m2tlO7zbmIx7x1OA2MVZuLGG5hke91C28mQB41Ehd8FeSOme+P5VxnhDxbaJeAamLuSZFGxbaBmU+pKnge3J4rvj4s8HXCLNqllcQSKPl3wFcjnjAPP1Irnq4GV7xNIYlWsylpMmlaxJM2iaW11FA3kyNK2fnA5Vd3fGf5VaufCNrqaO8ItxvT5k5JXk\\/KOg9uMjg1u6L4y8I2VtMNFlhtEOWaKCyCgN3JwoyfxNYnin4g+HjDLa3OsTNfY+U20BWVWxwVzlfwOR7Vl7CS0Wr80X7VbkMPw+NpK9zJqdis2flPkDKrnpnPP+eK57Wvh5pyyvqVyRcgE5eEZOfpkfn0963\\/hj4vF74WC6\\/fQjWjvMwkxjYOV+XjBx2Geh5Nb3iea41jTmMV5FPYxICIYZMNLz0zgjbgfdA59fXJc8Zcs2o\\/IttNXirnl6eHPAN7JILZboSgjLeSxB9QDt6e9Zt94N8Jy3vmLNdDA8tEmlWMKxHXDYH516DrXhuO+itm0lZf7UIWcW099KGCY9iOhxxtH0rL0L4cXUkLXevxmxnEm+H7PKBEU6gsSD+HJzmu3lpSV+d\\/18jHmqL7KPNdf+Fs8MvmaG4tYiuWZpYpi\\/0wcgnnvXGap4A1OOQiS8sY2YDGSCTzjGFLEV9SP4Utrqwe81HUbF4IlDuVRBxj73LEZ45rD1XTNOu5Wi0x7S+ktVRHtbPaXLsGKvu4Cg7TkdfrkVCmoac1\\/67jV5a2Pl678NeINLhnlwGUffKk8DPBH681V0jXZdLCs0LyOoIOGxnPfPPtX0LN4Uu9S1U2ks1ufLbddW0YLGFcfJuAJZiTjHrg4Arhbrwjpf20LeRMQdxaS3RSRg8jAPBB7U6c\\/a3i1cckoWadji7zxML+KJ5ZljCkHaX5H4cVL4U12KPUxas8bxyx5555A+ntXR6p4R8ORxxG1lupSTuPnwiPZwMZO8+3auS1XR7BWMy3sTqhG5AffoNo\\/lV+xXLa1hOo+a9zqxOYxNIIZEi8pWcDkhtvU\\/jWRqPnwRLKjOrYBbAP3tvPXr6Zp2k6\\/LNLDara2scDbYiq7jx7tuJIx646nmt\\/xQpvbeOW4YofL2xJEUWPdnqw+8P1xXF71KSTR0JqaujmLWSyhuYrq8vUdsAyLjoSOmMf5xWrJqMdxcR\\/Z8PaiXaZGGCcnH5ZqsfDqMub6S4RWByYwm3GSQMnv9KYYdGigNqNWYIsob5LZi3GSBkHB\\/D2rRpS16iUnHToW9dt0sLQXisRGjkFYznf8AIfXgcqD61k\\/2mt\\/DFJbxbSQWlkXgk4\\/L3qa+8rW5\\/s1lespU7thgxvAwM5zjOKr6bGbBvs5iYMwZgA23t\\/n\\/AOtUxVo2lqxt3ldbHQeH7t9QhSyZwjOw3qBk8ZBx+JrrLazEVsoVMnzSuWrzzwrfrY3zXOohljjLMJEXnknAP6\\/lXS6h4ohhtI3gsL5k3s28hVQn65968\\/FUp+0tBaM6qNSPJeTJ9Zjzq9sssSmNhjIPJxj\\/AOvWdJbkancLFI0UaExkqchmBBP86ypfEEmqzNLaRBTFjILbtvUZzx61Z1SDUWUXVnEzkhppipG0Dqw56mtIU5wSUnZkucZXa1GajojTXMg+2StIH24kOBgjsfbnio9W0mUXwgnkM80MYYiJADzgZGffPTFJNqkVtfx29zcszySxSjIz94cggcdQPzrsPEEdnb6+sMKoq+WiLjGfvA\\/lRKtUpySfZ\\/oNQhNOxxC6UA32iG4lWRQylJFOcc9fXP8AWq08Uir9ouIlcufMLvAUJPIx2zz1Aro\\/EN1Fb6jMkSBnKhVV1ygwMk\\/+PDp6VWtNUzaC1kht2njDeZKy8dc8D3HHauilWnJKTRlUpRjojPs4jBHYrI8SW902R5sagbj\\/ABHAzgEZHatXVrJ4rBLZkilAYeWfNCNzjjAP49e\\/NR6heWt7bwzRwQJGhBXau9c+hBHAxx1PsKi0549RO6KxMc0ULSkBugAycA8ZwMdKUpNLmlpYcYXfKg07RtQglNr5n2JJAXAlmDN04PoMe3NA07UjAZ5JPNXGUEZy5XgA7jzgD3PoKtWl1bxxi4JmluSCXSWTJQHIxt4yev6U3Tb9HtPs8R2TIWCJ5YICkYwDkY+pJ7VMp1Grqw404p2ZPdWUlqBdPp9teNsKiWRugU4CkMeT3zUek2ur3tw7tZC3sict5agcj0yeBweBUp0\\/VLrVJLYvGY7dV3FlyeRkDHpgfninW3mW5nspZJN0V4FLoCV2MAcgdOM1jKq1Gzkm\\/wBC401e6QybSbcsjjS4pWb5ndokJznndnkenQd8VetraQW7Wt1eQC3VdzJEi\\/MCRg9MD\\/65q9eacbCS3EkzNKUO6TJBOCuOn41z\\/kRp4omCGZz5bh2GRgE8gHPp71EKiqR91\\/1+hUocktUa01pJ9jjEQDW0X8SoJMHnjGSS30BHNUBLFB8t4kzjIMcO1cDj6Zz+PrVyO2LXkkg3gEnBDgNmpbvTf+JFeSsryshXYXHP\\/wCs0ueC0Y2pbozJdTsYLP7TBai5dx+6ZsKufyz3PrWx4W0+TU1EsmYiGGVBKlSW6HHcAmsltH8jSILoW4kmSFY2QsOm08gdM8fjWl8P9Q8p7i2eQRy7v3avnk5yev1pVLKnKVIE25JTM6\\/sR\\/bVvZOJDDuLEbzliFyv8sY4611giQW14IogPlBHHsCDmsHV5PN1+G4ZhtiKEsjAgcn+la+ozTQGS0DqqzMBGwzkqFGRmuevKUuVeRpSitTk\\/D0Elyz+a86mOYiQoxUghs5\\/z603xBpupDxE0sF3KII4sZkOCoAIwPzre0i0lt9RvdgHlOisvzdH2DII\\/I1Zuw8d1bapeQxGCRJVJYDAKsD\\/ACzW31hqpddjP2S5bM85jDT6NJIL6FCk+87CWkZ95wF9B0rs9OiSxums766Z5blQC0gC9xjaB1wBTPAOnQMkl7cx27\\/aZTmKWPJTnj6Dkfga2NVdbXVGnktpCTE0Y2phVweOD04H6mjEYjnqOmun\\/AClS5YqbOM8Ta9qNtJPBp9urwBljLMMEkHsvPU1Qu7+51OS3S5sFjMPzurjblQOcevbpV2+aW0keeSPM\\/mblR9rMSeB7ZxVy4\\/tSRrI3CQLGsofzMkEHBblcY7YrrTjCySXr8jJpyu2xNWis5NFl3WEUc6jcSBhhxxgj610fhPTrS30q3mnsYpJmhUvJGB5hBXJGMck1zurax9p0CXzrdUyWXzFOd\\/ON3PuDXQCUaVoNrIw83IUhR94gBcD6fXvWMlP2fL3ZScea\\/kUxDG2oXdzBamGEBUWMkglcYwc5OM5496r6rYLFbXF6JE+xmUKUIz5m0sCMHgDH58VYstZl1KW7jWIwrGV3rIMMpwcfXmrGrWdzd29tpllCjnOSWYkEjgs3oMHNU7xauJWd7HQQW1vY6HotjdMnmQoiyZ+6uQpxjoOo61keKNQtPt1wX0+3Qqu2JfLAU5z97t64JzjPtT9Wl8SaOo1PVZ4LuJpQsiRx9E6tyO3HTB478Va0e50q\\/DTT6Upu7gqrrOSTgnA2kH5QSeg4+9muaMdfab+ho3Zcpzem+FdEuUe5nwZSrN5UCnBJUEBQMk43YHqfpVhvBmgi\\/glhMyovyvBMWO8kcE9MHn6fSurtdIlfXiolMSzWjmLcv7qM8ZbPbj+dJbabZWTXFlatLLEhLRNIuN5JJ3fiSaHiJt6SY\\/ZxS1R5tZeGtXktr02E8SpbOWEDk7pPmwPYdM\\/iKgTTPE9qfNjKI+xpHWKQYQAkZI7nP1\\/w9c8N3OnLDDb3dltu7icsNgGRyVHJBz0B\\/LOao+LdJnFzcTaeFtEeU7WU8srknGSeeR+HNX9bfPyyS17i9npdNnlF2niUXKkkShEDhjnHOAQPcH37fWrFpoetTJIxvopXALJHC5A6n0AHbH4VaW6uILy9MqNFKuRO\\/DIwwMSBTx26D1Nbfhy8tP7RdpVY25XzIRsEYbBAPGM9SeuB+ldcpOMdEjFe89WzkpNO1SOJy9lcKYuTvOAe55ycj9Kn0S7niuTJHd4kRuU3Z3D0INdtfajDqNowv2Jnml2GFQwcqQDncOgA6+31rmPFGiW9jpi3NsGtpmV5I0RycdxnJ9O3FRGqqq5ZKzZTjyO6Z0kNxql7EhaCEqyfeQ8gnjO1q24tUvdKeKC5eS5aMYRYVzuHrj+grzrSY\\/Epms1WaaSN4sybTtVc4Od49iOvc9DUt7deJLUtdxyXvlxzeUFDEu3vg8EcdeK8yrlvtHytxt2OuOLS11N\\/wAZ+J782rrYQSw3EuA6mPLbe+ew4z681jeFtNlvizag1ztjXkZK4PbAHTrn8Kqf8JJq1tetbahEIZFycyqNqHj6+orNi17VHumZp2l82Q7WiQ7X6BcDGeuOK6qOCqU6Lp00ovvuZTrwlNSk7+R6JqEWpy5Q2sE8aqNryID\\/AEPNcx4ilM+nMkupvvjbIQITu56Ee1LZeJ7y2MeVkSRyQPlOCR26c4waS48V2dzdE31nJcAYG7ZgjPcED+dZUaFenJXje3b\\/AIJtUq0px33MC9S4uolt5Zy9xGdqLOojJUnggjg\\/zNI3hjxLgqumSMm7EZDDg98Z5xXZ2dj4I16W3u5LmRSij9z5m1gQeua9Cg1XRUtd0lwihRguzZb26VNfNXRajGDv1TT\\/AAOdZcqjcm\\/uZ5vp\\/gsz6esWrw7bgfdKgYU\\/XvWXqHgGZoFjDgAMS21cggdK9Vl8Q+HoIF80STLk8hC361nap4g8NQcm7kRCMbfLyAeuO3071z0sfi+bSL18jZ4Sko2Z41feEL+G5Hk22Y1b+Hg\\/jiqet6DqSt81o58tMZjUnjFe4WepeGrhGkhvBcKASWRs9fbGRRe6rpQj\\/dBlBUMrcc\\/T9K6lnFWMkpQd0YzwNG1+Y8Es9Gv08wSQzQKyglnjOMep9\\/QVFYm6E00MChh0GVyOeOPTrXsGsX9qtqFWweUTEqdzAkEdSMH3PNc7d2egraK1uI47iT5pATjZ7AfrxXbSzJ1b80P1POrUIQ+GVzmNLtVt7RGnso5JwSsZcfKCPUHj1FW3uWeRWhg86RF2Z6KMrzjoPStAok257i9hKNx5Z4yo4+6OMnnntWdKLa2YfYhI8i5yTJwoxj069P8ACrU\\/aSu1r87HMQ6nDewWJ3qFiZFzHj5ieOu0frn9awZL1Lr93OEQgYXYuMe\\/NXby\\/uBdRsZpJEj5CspAJyavQ6It1HFdylIo3XA4OcnpkdSO1dkWqUbzH6HJ42ldykq+eQvbPb0\\/CpoIw0w2qsRyMCU8fl3FdveaXCloII7iPcWXbsYBiMckDsDz0NS21vopv447iN1kB3NIW3c4wBnGTz701i4yWxSgurOb0vQrhkM93DLHGc7WETZbjjbgd+2a7G0sbUwqbXZKpAXysArkdW3E\\/KCevI6elTNZg3UcEE0DPk9S3EZ4HC9yDjPbP1zN5NvZbob24Zwr7VXaoVsY6cnH16+\\/aplU5tbm6SgixcaUJkFoIydoDurzAhPl4I7Hr3PYdahkSzjQTzyKXZCsYMgd9wGBwDwQM469u9VU1KzuZ1VrqOKUZUsDuYqfXAx7+v5Ve0q3t7q5kSyv4ppRLwzxHKD2bOe3Tp060rpIakpOyK0Fu93eJPGrbgQqvJ95B7YHA9uvFWJWtbZ3tp7e4mySHMUiqM9snOcdeAOtdRaxW9jaiOOA784MxBP8ziqNxYRyFpJVkmV+QeWAPbjH1FcLxiu3JadDt+r2jo9TzzWddeNjbKwGdwKyKCWJ65zn0FVNE1PUrS6MyM6osbgbhgEYGcCutk8OwJDNcXKwiHdhyU3nBzk+oIxnGO4qdvCccmW0eWYW8b\\/vlUliEI+9hvb045oWYYZ+6+vV7HBGjU57paknhw3GuiOZpJFgGfMVl3IW4+UjP15rd1pjAU\\/s2Pa0kQQv0U5IHHqfr+dYttO2mLPBBbNFartHnRDBZjxz0A\\/QfyrJsNRjlv5Z7meRfIYxocZ6++O3rxXnVYSrTbivdjt53N5VfZx5ZbjdQ\\/tmHUprR2gjaJQQwfIx04HcmixvdVPiuJZ55yVUBudypgdc\\/d9yKsXF5GJ94iiN7HHmNgTyuT0\\/D2HNY+o6peQ2jfdhhcNtcR845zxnrnnrXZRUprl5VtY5fapO0dr3NrxQLZi\\/n3VrcMCTH5hHzehwOnpXJ6tam9s2uZTGZI+FMQxvPfJBIHpzimWeqtdbkWOS8VOXMkYbJxgfh7D0qnqFwz2wgFm+1cKBtYEHJ7c+td1ChOnaN9iK1V1Jcxd023NrZoFt5xLIxJBwQDg45xj8CakkkhWyea8lleUZAEcfp\\/X8ehqNYYRF9nDi28tDvdpeffAAyT1z1qfdJFbEWM0TD7hQ8KAOflBJLds\\/U1UtXcxW5VtbhBaCKNsFwT8zEnrxkY5\\/\\/VVq51iSDRBbWwhdllO6WPnI916g8dfpVeXRbOGUyM919okUOIUQbSSeOcnj\\/Parl5ZWLrG8JMFuu3fFNwMkHOABzyepI4P40S9nJp763NoRlbQ9CW\\/0maCS7FkSpmIiAbPy4HX3yev1rlNbuNQu\\/EDWmk3M1tFPNGpiRV5B4J5HXrzV\\/S9Mm1G5S3huXjUjcDEeGOejDpV5tOOmeLEmjCzyoi3Epc\\/KnalaMJO2rsdSvJK5e0lr+y06Szs7y4jZLnyS8ibpNg6sSq\\/TmotJOo6Z4hu2TR7zVBMpEUkaLuTp1BI46cDmt\\/Rri6huZr3UZ5p7d0CxrbgsM5PPuTkdeB7VoeJJb2aOFLOW4Ryh3rMoyBgnBA469815dSq+ZxstTshDrc4Dxhd6lLcXFhftfxTPGz26yKRyPT2zxiut8A3llHaRMkEjIUDEOCwBONx79CDzXLQpPqd5HaTJKWiLPnPPYHBNd18P\\/DdrLYXdxcFTNCUFvIzFSjclhgHnI28H\\/Guiu4xpKL\\/AzhdybNp4tMubkmUQxQxoS+wqu0kcHkf\\/AF\\/SuBuluD4OYRyJE23ZvmGVaNQdxxjJyen4V1usC11CNNPiEUrRyZZyuFJ\\/AjOP51D4z0+x0\\/SSYtLDLJAI4pVkz8zY4IPQ59K5ac+W0Xu3+RrKN7s5nShc6bp1t9hCXVwYseUrIRnGMY6rn1yOtb8MV1o95Bc29pLHHcSKl0jjaqsy\\/KRnqeMHFXPBt3Fqeny3Mllb2lxDLhmkjIcEjnDZOAMg4z3qDVdVH2BPtd0peC6WRkzguAeuT1x\\/SuqHM5ar1MJ2SsiXU\\/EN3odwixxbw5LKoG0HoMk+lY81xLqmqPJdSyQzPGzBYslQcg4Oe34CrXiW8OpalJHbQq+y22h1bIy4Ygj1Hyn8qveDrQR2dzqs\\/lhnbYrFccY5x+VaQjGMea2pE5Nu3Q53wvYa1Z+P101biIQ6ha\\/abgD\\/AFm3O3ALDqQK7HxzZ6xbD+z9Kt71lkCCKfAOxmwOSuM8dqzLLW7S68fRXVnvkktraMuWGwtmQoBz2B5\\/\\/XXpNlqUtwZ7eSFzGD8rOQee4B68ZrGrUlGrzPsioxvCx5HHPeQa5HNBDdwSbmUknggHAPXHRcY\\/wpmq3lxc+LHIKlmsJIxIDkqQVyMjvyfzroPEnhjVD4hkayuF2QMGcyPjGeuOMAYPWud8T25tri3ulkgaURSrJmRSxJK854zg9CPetoShJ3XYl3SMPTrS6sgrx6ZM4mQFCgJxgkbz1POOvA6GtCTV7zYI2liJIIALnCnueP1+lanhy9MVjJbXrGTzSTGiIT5SEDIZvrnjsD1rm\\/EENxqF8+lWTw2ryM2yVlJJGOUUe9dkfedpGD02GeI4bhymrTSRTyhQI2iJZAuBzyO+T\\/8AXqzpKv4gvp7fT7WezsY4N8vy7c8cjn1OfrzV3UdJVdQtdOgljihZdpEZcjhTnr64IwPWvQEh0\\/T\\/AA+8ttbTxedGhLRpkAjPUkf7Vc9WryWtuawjdHA6Trt7FZWtrHqdixgfy5Y0jZZYznb97oSAOnHBrtrm6uhqFrfWsiuYoCHiYcyKxHf1BH6151dx2CXVzHb3hkuV3zSDy5G8ognAJOQOD2x7V1PgzVY5Jx9pt3ciFQzyKTtbknA7DI\\/SufEUVOHNFGtOfLKzOiv01m8gRdI+x211M2Wmnh3hVAyTgD5j9TXm+uDXGBn1G9trto7mN2kjg8vPJxkZP5CvWItRjurd7i3uRHubAB6kDr\\/KvOPGtxEujI8O4eYBhhxg8nNZYKMoSs1+BdeSkibwPdyXUNxMiEkzurHPHBycfnXa2VoZdQWTarsoB2NzuBPIz2PNcP8ADK2mu7S7SCQrcmRjG5OVK9O\\/+7XaQC6TdBdXarPFJtZwWEYATpu7de1Z4n+JKJVNe6mXPEeoLptoIbQbCMkKCPT09ap28v8Aauix3clq8LkYZSQAGIOc461Q1vTdQmtlvv7QsYoU+9GsTOuB1CsTye3Q1hyeJL20v4tFeJWt3kUGUZDLxu5B9uKdGnGpTtDcU24yuztrCGMaDb2sMKsgh+6QPmAIHfjP+FeN\\/FCYpb3Fhbx7p7loxujPHl4+YY+o4r1+O5gTQVnfd5CK6OxOCuCQfpzXmetTWMniczGR5ESEbU24+Y9h6jHf3q8BBxm5PoLESTSSM34YEvbyW0qhpHUxDzCRtbeDx+Fena5p908r2jRxvbfZm3GQgAEAnn05AryzQnSO6lmiaaMLMSFEvIwRwen5V6Y0sVzaLPqFxL5bRiPaJWRW4J+bHtx7ipxcW6\\/MuppSaVOzKmgX1m1rbR28ks8bWyxs9veM6s27BwCcAKM9uM1iRWuqaZq93dW1t9v8yRooo1XfujDnk84JweePwrXs7HR9CtbDUIY4rYTnaS8ZiWLJyN5x06ntnjtU32uyuo7yXTtStH8h1kRrcbssFwFAyxBJB547cVldxukrp9\\/UpK9mzl7FJxYX\\/msbaSR8eS0exwc4G3OCVGevPQ\\/Wr02lRWohE+HJhYEJyQW5\\/kMfjVPxtr9tq2rRx4NmsAw8hAEucZPTnrxU+hNEdP3advkhWNm81iR5rHGQCe\\/PfmtpqSpcz0v\\/AFuRG0p2QxBpzXHOouqTEiVGtuEbsvQ49iPXrVPXZIWu7u8ksCY0j2xIF3EZyATk8dOvvWz4qnh1a2sk+wvZ2XnLFcTJDwDtPUKDz05IrmdYvLSK0ktI1xCJFxLIMsUUHvjnGf508Ndq\\/UK29jq9AvZ7Ozt45FiywXKsg\\/w5q9cz4vbpIm8vKo6MBwQc5\\/WuEsNbtr7Xr250mze5aO3iiRtu0M245AOOmCOcDOK6\\/wAMwXmoapJ\\/a1gLURoAipKWLdeCMDGPx61z1KXs3zS\\/r5GympKyLU00Fho0nkMqTSyBepI54PrjjJrnNbvbiSKPTF+0ExpmVmxjJx+B612utaZbnS5kjhLkgMFDcnHYema5dNWt01tlVoobC0QNhPmLHoAAf4jz26c1rQd1dK5nMj8E2Yi1HVYry3xK8UUm102kKQ2PpwT+dXHENrHPNE0O9o5FjWGZg24jIHP16ZrjZ9dMnjqXVbx7mOCZCmbYtvCKeD6HryDx7Guz03VdLldkhlkcmITCWaNd8gIyCSBtBAx6fStqtOcZc\\/dIyhJNWOb1FmgVxJ+9ZZVZW3B8sBgt37gnNcl8ZLc\\/ZtOmjXCRM0bH3IB\\/9lNdrbThJbu7WVQJrgOJChbYoJzhV7dM1keN7Ke40K2ke0u5YoyHWEOiyO2ACRgMe\\/Q114d2qxMq38NnjaFvNU7A2D0I6\\/WrtpfNbzBjHFGV6MIskH1612dlYxyTid9B1GGNVJlMisoC\\/ULt\\/T8K6hPhnFrumrc+FtY0\\/U4tuTHgxyIwweRtPPUH8xX0dPDTlrFni1MRCHxHP\\/Di0sdd07WHmgurm8TbOyhNyGJAd59QeVxjH48iub1EXaTGFYCINwYQhAA4\\/hYkY4IroLi213wne3T6etqzSRGCeAYckd8AqOeB0qnN4ljv2W21e1+yXi\\/KHZNnU98\\/jjNZ1Iyg7M0pyjPVMSHxHLAke2xSCTHPlnHQdcYqz9pj11g+oa5eWscS7t0MTOOOhY5HOeBgVv6To0WhrD4gtJrLVoyMMJMFI26EEdDz\\/OucbTdRY3draW\\/ltOS8iQ\\/6sjdwMHnAz+FTzyaLsi3puvvoyn7Dr09wxJCo9tvZ\\/Tg8frWXqWpa5NIz3804M2XYeecrz3yTjp0NWZNEtYIYpjPluRcqUBZSMgkNz7Y+ua7jwB8OW8T6e9\\/dXItbMBpGVoHMjgdeSAp75IJ96ylVSV5aFqL6HFWWpaiLdbaxubqWUgjao3MOO3f8q6nwRr\\/jSK+is57rUUsjJtdGMkeCDg4YYKHnrmu98AaM+jvqn\\/CMw2U2lwagILu\\/SUC5QKAdinPK5xgheeeuM16J4x0Hw5eWUdjrWmwi6ncR25mDEhm438dSMZ4J9RWTxLk7Ifs4pXZah1rX59PXT2s2isRDzduz+bcoUxsOzmPqf3h2n5c7VJFeOeKPF9\\/Z6zcNeaHJDpou1iksJn3RqFAJ2o2VCbQcBRg57cV3vhO21XwzafZtV8UE6ciTXFvPBbufPhj25X7uEQrwcgD5sgkkVheKvB0\\/jT4f2lvpFxBaLozOkrG2dTJA3zIULLlvrkd+ORWcajk\\/eQ3BR2NPQfG8l5qFtpumwadaaSZFc+XapGFQ\\/eJB4UdRnHQn0zTfEHxFksPFVzplpYW4IRolRYhuYq8oBBHXhVPpXK+FvCuv6Xq9vY2i6dqMdzHtjuZNxeJeTjsAfTr+WavXHwu0mbxDKmt+IrzTpFk8uGFoiJSF25cHkKuWPPYgkZrlqTUJctT+vU2jFSV4ncfCy71HxRoiXEkVo11NIPOU20eAQzfe45ynAOePzqh4r+Gnhq48dq1lp1pHf2lvEbhIy\\/76SeQor7C21lQJIxBwDgE5wQcXUvHB8NW8NpYauftd9LHAkOnoI40bgK7seckZ6AZz6YrS8Jau\\/iT4oQaveaT\\/AKPcWsC29y9wUkjZRKCJFDZw3mSAE4+6uB3rONSpFuetinCLVjhfiRYyeHJZ\\/wDinbCJIX486FWWReMEBVAwc5BOCeOODXl10ItWa0jtrKJrqcsGFuxQoV6gqcjkYIx2r3L40wG\\/8LWEF9DFHe2Mm5fLcbbmPYWJOO+V6\\/pg15Q+gK+nzatFOIYZABFGPmZmOf4uvOK76Nf2sU3ozCVLkdkc9pOiy3N4PsWowwTbC5e4RkPQcK68HqOuKSTyJ7hotUvftZK5j2SPt6453D8c11mieHZhfyadJb3sl1McLtmADPkD5g2epIxyBXq\\/jj4deF5NE03U7VbSfS5EdJNl1+9AU8MgOGfAPIH1I605VIqXcai7Hz\\/DNHaXM9pZPdRQBgSSwZWO3qAR6989u9RQeJNTtUxmJgG2oJFViB6dAB7YFTXVpe6Zc3FvFpN5PArlo59hZSgz+HQ\\/zrH1GITXDyxyQxCfLcnBUdwPU803GM90Ck4rRnqPgjU9BubQPqFmmcZWVFAKscDHHasC7K\\/2wsrybIGO1x3Ck4rmPD+pX+k3QgadooJgAJDCME\\/j\\/MfnW1p8kdw43vKyBt0zElc89fpj+Zrilh1SlKa6nTGq6iUWaGgWEUJ1KOdomTe6l1+7hScEexrf1HSoNT0zy3ixBCisuwbQp44469zWFYta2+nzSHDJMpwqMSOvXr9TXSajqsEGmw2ZYIwVd4I7gAn9a460ZymmmdFOUVGzOYWOzs7t4NkKwOuCoHJxn0\\/D9a17HxTd21r9hs4rYTvtQyPGCxJ+UEkcHoOfoK5nUPLlDX0MykRPvZTnBHIIH51P4XiWaK4vb55IRMPlKR5HXOBzx0B6HrWlSlHl5pa\\/5ihN81o6EmoXq3V\\/Dcy2VleXbD5i8ZHlcHtnB7Vk3N5FDrultarMZJGw07yFwm4gbVBOFxWibdLWKfbKjO4X5N25lwT3HY\\/L1rLsdO8lVlkjfzXmGB12cjnjvn+Yq6fJYVRS0sbviGWeW2a8uI45thAaP7oxnqD1DcDp+VUrKG2u9Ome0hlhmYbiZZAcBe2Cuf17V2M9lZ29m8EsQbELnDHPzKg5\\/OuOv02XVvavdRwpLFvIkUnP+znPAPHTFZYerzLljoXVgl7zNK0gtVaXbIU8lhgCFiQ2ORjnpnqBVWa4lN9CLe6eNgpPmE7cfL0x16Z\\/L8KzJp1jjgRTNJMQWLFeoPPXv90jn0\\/GprOwvJ9Wt41UGSSMuy4xtBUj9ADV8qV3JhfVcqNXRYRf3GozO8dwYSp82UljkkD9M9\\/SrHhtUW\\/Z7kwATs0auAM5XJz0wOKpWlxqVrqt1aoDCZXwGGzLttwD1OPugnnvVaf+0LW3SyuI9rgsse1dpyThssOufQE1DhKV430dvyG5pWdtT0jxHqmk2GtMVkcxyMcuoyu7GOoPTip\\/D2o6ZMdSWWVSGmAjj2YLfKvr3yK8t1OGVILeyjiaSbaSoQM21BjsOmeO+Pm962\\/DsUtlBFKDJIWdXy0u\\/co6naOCcHPU81xTy2Lp6S1\\/yNY4tqWq0Ou177U1tdahBZzRGFsJbMFxLkg5z249P1rm7W5iudbZNojk2uWiIG5CG5Bx+H51p+JfEy3KLbaZdjJ+9G0OQQvXBx8uPU554rg3vby41YXCs0c6qHSRIipDk\\/NkKDkEbhk9cg9qvC4WfI+fQmtVjze6ehafbie6dFA3Y\\/UCrV8qJppsnVi88m5umAi45\\/QD8ayfD2tag9pNdw20N04X+LKkuTx0zxjNX7u\\/J01biXTmF0EZV2uPXgYPJ\\/8Ar1jOm1KzLjK6NO1s4Li1Qrjy2t1ORjoQe\\/41wviFoklUWsh+0wlSHUHcHUcZx6gHPtmul0qbU9SK28SLbRm2Qg9GY5wT7denauCt9G1SG6ltMSsWnkj84sQWYA+3XBPXHb1qsHHlqS5pbdPvJrO8VZG\\/E5vLeOSVGEk2DJlgCg65J+ldDBaRX0ARvMDws22QclQfbv0\\/lXOanpVxp5into\\/OEalWMh5HGASc+\\/6VreGL+WWKNZIJQsY2NMykCQjoQDz0Oce9XXi6kFKmFKXJJqRLcWstjC8r3C7i+SoXBG0bT39MfpUl\\/cxLoKOCJ2jlPlxk4PTvnp2NaVg0LSXV2bgMhcLHn5tzHqPxwOOelZ\\/jK6S00K4MipBIxDlQQSGz2H4D2rmjdzUXvc1duVtHK6ZfX\\/mskFtEZGk3lPPKgnYOcgc4H61U8Rauq6lNG11LFC75iRYGLMcDcdzfjz7VoeGvDqTaTFfWbSx3pcESklsZHIweMHJzVubwdqGqXQn1C+jiUNtXyBnYDkY6dye9dynRjVcn\\/X5nO1UcEjj9NeC81KFmjukCcu08m47uvHc1saprdq6Lpz2zXBZ85yMAdOSc459u9ad58OLVp7SCB5Q80bmScyEnKjr7dRWRbeEIG8NXErRxefFcPGjnJZ8gAdemK6eajUtK5japDQgvtOt30VrlNUePzZUhWDaCCx6LgDg1t6kLm8u7axsbuIwwKXIdWPqcHtxXFeGbUXWuRCeIyNb5ZnLluOnQnHBOa9W06wge0gbTtyjaVO4dSeD65+vvWk7Ut3ciL59kZHhlxcSXz3ES5TYn7voSA3Nauiag+k3hb7It0XgIEZfDAn0PP49OO9RQWSm61D\\/SN3zKO2cAHPQe5rD1FL8Mj2yeZIo3Jkt8vHHA61zyiqjfY0i3FHT2niO+eBob2wt1u2QshYsIypBz1HuB6fN+FP8ACOk68CJrNLeeWFi80krErjnBA79PasLWm1TSEsL97pJb6QCOWAQpxxnjd6Zr034fadcHQJLiG4mjuLlfmIwBjv2x61zTcaVJySWpprKaTObu9curXW7KGSKSNVJR5Hj\\/AHUhYqRtPJx064zitmKK1u4ZJHRRtzGADhgRx+XFYXxdP9maRC7XDmSGdMMeS4U7v0Nania5jsPDjTWsxBKGRmHPbj361h7PmUXHroa81rpieHLS1uobCfHmSLOY3Z2z0Iz2p\\/jKPZYTTwMySxABAXO0DLc456Y6+9XfAttJJHOcqEF4xA+qA9KPEenx3NjdyBWKSyeVuySpIwD+uaxm\\/wB9uVH4Tyi4sgmp6CLgXKi4byJiEYedjac8jnOXrrdTtWSa1s3cKhUqWkUKcfXtVLx3bTfaNLVZ5GW2JmZscgjaRj25q\\/r7Tu2lzyv1mxnqcEHj+Vd0pOfJ8zFLlv8AI1ZtNs7C8VreX7TujTa20AM2OQDnJGTn8q4bx\\/FJc6tY2EcszK4KMsYHPKgbs9skZrv7WCyGmQyJA25RyuQFUg84AHTNeX\\/FKRI9Zso7eVlZAHkdWw3HGBnp25rPBXlVXzKr6QZ6H4V8PWkPiVnEguMwM06\\/ejcD7vBP+1+Nc945023mAtNPndCJPOk2kEoo5z\\/XAxXGaTqmoWmvJq+l3dwk7pteOQF1kJ6g\\/XA\\/pV\\/V9av7sWk+q6dsjgnWRmaNlEh529egwOPXFdKoTVVSv\\/XoZ86cWrDdTu9Km0+0vtSlmlttrNBGqKHkYMUJbjjPXOT0A4qbw9pt7ZXu6WJ\\/JvIi4kLEqiYyM8feyRj3JrrNP0nQo9JuFtBZu82TEkgBYBi21Ao57ZB5PJrq9TtZoLC0iix5JUImcqAo6DHpjtVV8SoqyREKd9zy7Ufs1+I30i2Q3pYC2QSAKPU7QOOjEjnk5zXP6ppt7YXQGpQyQEgpvBODznGBx1\\/nXTx+Hbu81y8t7Vbe3nFwvlZZgTkYBHTHORkVZ1HRNS1fXPs91HqWbCJpjbSpklyflCnbgjAY5\\/kc1pGrFaJicX2OKt9Hmvci1vLZoRt8wFyrEY44AxXfQaTYRafHbteQQs4CqAQOc9OPWvM\\/EIu9OuruSWG7tGuXyik4x0P3vXGM961\\/hxFe6jqcImnnMUZ3YbOAMn8658wo1HS9r7S0Y67G2HqJT5FHVm\\/e6Pqlvp8stjYOWEigJIwcj3H+e1c\\/d2Pi2UtJc6e8hCgJwGLZ47Hjj+Vew\\/2bCYQZPN443JIVb9Ov5VzXiu6\\/sOb7bbRiYqowjSbW6EZGBXlYHNnUlyKKb9P1udeLwypx5m2kc1aWN54bBnuLeSNniVWXcAuVXJX17jJ74PSuZutakuhdzqjwqPljdsgrzkDpzjn3rtfAmrTa\\/qly+q7tqDEectgnPGfp\\/KugvPBGk3tqxjMvmZydqcu2eOT0H\\/666nio0Kj+sr3tNVscEcNPEQ5qex5MmpzW9o1wpSUMAQHUlQcdOT179BTJtWjuQrM0Ssx5bb8wP1\\/z+Ndtr3hB\\/tEdtHaoiOoJIlAYHvxxkZqmvwruJPLeXUoIpWbmLcAeOgJ\\/wruhjsE1zydv68jnlga97WPOZbporsqz+cwzyzHA+lN+2TLKGXIXcN2O\\/fmvQovhfqa3TGeSJFzuV8qwI7DHXGKuTeCdOiuZ7WVMyLjkDGR6D25ro\\/tPCbRlf0M1g63VWOM0F4HtZJGVi43EYOAw469scHr19alu5ryUNJFtiAJG0TBQAOjYzWhqPh6zhiMxUQwxTbRbpndKfXJIwKxvE0FtF5cVuvKNuDAEn1xu7960g4VJ3iYSpyiVWe4s5mMkwdc7SwUdOO5pP7RWLzBPJI7O2Ru5wvOMAVUdybdrl7gq7A5UqMk8Y56+tQLD9rljSKQPMW+fewC\\/zrrVNPczPQPD+q2x01v+WkhXgbywOAOSOx4Irmtf1WeUABoxGWxhowPc5x\\/+uunt49JttKNvPHaoy4DBSOD7Hk1h6vptncrJPDcCNNwVVCdO3Q8+tcFCrD2sm07Ftt6HPwJO0gcKhwobJORj6\\/56Vt6Pfz27JIZGjULtLlTg579P88VlQBLceUCeevtVzT7yCV1SUqH3DYQCwA6nd6849q756oErM9F8PtPqF+sNu4bcFEZdcFTzk54z7cV3HhyMWNs1nqu7fGOpzk9uvauC8LyHTi2pTSBbccxAPkl+uCSePXFa0viuZnP9qOhZkO2NFyWHvxz\\/AJ5r5\\/MY1K94wV4r77ns4WUKcebqzdvZ9Pt7xYVu4oYH5yX+8SwJOCvJOCOadql7Z6ZZvJHK4V8fKF+UewJ6dvXvXmurPcTJDdwg7g2MLJuJAAK+vP1\\/xpnif7XY2MjrqEsoDtH5RlGcDnPy8d+lcVPKoOcU57iWMcHJ8q8iDxb4ua5lMFoqqjY3tGDlwBjJ+mKg0m6hbSowqyzpyJVC\\/MG9QcHGK5C3gku7oQCYQx7vmctkAetdXbxwiwt7aykhLtx8zqp453Hp\\/M19DPD0qNNU4L+vM8arUlUfNIsQXa3RdpJLpIsKI5YMMS27vnPT3I61D4ps5bjS1Wa6DOzYi+U7m5P3j0\\/yKS9vx9saCW5W3ZcDEY+aTAznKng1ZgntU1SF0uJU8pCqrIoaR8ckFjnjA5yPTArCzhJTS21\\/r1\\/qxmrle18L6hptsvkfvTIoMqqwXIweMk4NLbTykTiaGZpVGNu8nbx0Azir2n63cSvDaRTAW7uAkzPl+ufm\\/wDre1XLm0efW5rk25Il\\/iCA7+eOPz\\/yKmVSpqq1jenSdR2OGe0N5cxiCKQowOcJgnt1x35rbsNIECia3jubgr9wo+FDYzlhjp0zxW7qEdwltJp6wRwrEcDorYwThiD6e3esqVfJtwrxSQEgEsJR+8PqMjP4Vs68qkbLQqvQ9loWNL069u79ZppYAioA0m8HBHbGB83vnitDxPp8VppkrtOWhkwCsY5\\/M9e9UtB2vOtxsV0wWPlMdxAGST71q+KJvN0iO3+Uxsu7z25ZRzxnHauJ1J+2SvodeGa9hK61Ql7perWUmn3+nSq3lzBWQE9CQR0Ptj8a19YmMmuiDymM11GsbZ6ImQT\\/AC961vDwZkVWRWAccMenvUfxBkay8QWF\\/DAitLbIXOAQvJHA9a75ybqJW6MiK9y5oysn2LTwrTSSFlHl7giqOgPTI5x7GpoEltnXfK80ZnChpXxtzkELzzyenT0rItI5bjT4II9Qe3MkhlAdvkUbiQSD3BwPyqtca5EbmK2d5WNtciRnRwOh5+o6cd64Z4dyTSOmNWz1Ipg9r4iS3Mjogm3Iw\\/hJIz\\/n610fhu7lkh1pL15CBeKVBwx+4PTHXrUep20VzOS1t5csJUrKOA49T\\/n1pb6KWy1m6kSTbaXEML42HhgCM8DByB654qoyU4We4mmpXRahSwKt5llcC4j5Bjkwee5B7Va1JHbTYrd5DcCKaOcgH7oB5B49KzI7W9uS09uJZlYctGhIx\\/kVtQWbxaZdSPdeTP5Y3biCVGRk49MetYVLJ3NU76GB44t7rS737Ra2n7kkbAqk5O3B6Dqcd\\/Sueg8\\/UrQm+cxlZGjRm+6xHBww4J45xXpmoaPcatBm5lX94xCRnd90ZyQV6HB7nFczqxs5m08wWj2otmMLmQAxoF5PzAAE89PrXZhaq5IxZy1ovmbKvw90+ztrC6bUcS7rnDEjJAy4GOCO\\/Q11D6k7XQ0+ztru\\/jmURt5bA+Wpz6kAfd6Vw1pPeJ9tuNGAuo3mSVVKZAZWLEqx4HANdD4Sd7iSC+jtp3gubsCVEiKqAwOHyuSSBxzx16daqvFpykyabvZGr4e0fT7bx5e3uowKqiySFIpiDwNwO4dz0rfs9d0DStKVLdwZcbcJgtx2\\/CsLVtQsbK6uv7QgluljgWCMzx7zI5YnBLZCnGevt61zXiLSJoRZz2lrJhlLkwoGVM4IyUHofyrlpQVWXvv+ka1G4r3TYuPEU815JFG7FZ33fMxyBn\\/A9KTVLLTJdc0qea0Sb5pFEYjyDuQ8EAdOtcbYak0d88JglFxjAV4HGfocYrXvZYW1vRpNQvra1MlxuY3any1IRsLgEHDHA69T+Fds6ajt2MFK+5cj0VLS5Bla2EkrOYkitzCECnoMsc9aLa2stLmZ\\/wCzBPezKf8AiYTtuKnAyo\\/DoAB3q7qsl\\/aG3HlaO1tcSsgubVsoD2BU8r0I69eK5HT9Shd76TUNXcNDccRNPgSAA8DBySeOg\\/nTptzhdikrSsixpT2ek+K4p9QB8hZPMYzABirKQAF6+oAGcc16RA9pf2a3VrNLcxohRYY977Tnj5O\\/vjPY15lPpen3qrrVtZ\\/aTMiW0UbI0Id2ckgFyDwB1zXUeGLC\\/wBL8s2LmWNJMhVflc8lSOMnGfWs8RGM1dPUuneOjIte0HVtQ1EfYw9lHEELqjbYZOORJ+Oc06+RbCVLYsg80Bxj5eCAPbIyDg1IPHugaNPcWd1dXUUJJIjntHdMHqMqCMduelcB4g8ZW2va3Jc6MqpGkQZ0KNgDHOABwckD8DjJxWdKlUvqvdNJTi15naWMxkvBEjGUeYVUDjGR1qhrcIXQr6KYgNAsoy3Yg4xXL+HvHFvpM7tfabNNLG5CxxNlsjsQQCB+FZ3izxnd69DeRW2nPZR3M4ZyZQ\\/Xtx789a6Y0puptoZOcVHzOu+BuvpY6u1nd3K4nDbA3GFLEg\\/nkV0XiO5tIPE8st20qByhV0QMvGeuSBjr+VeSaNp08+uWzJdvbb0ES7AGXI6ZHpyfxr0\\/RrIarIun63LE3kZZpQxjdlHuCSMf1PWuTE04QxHtb7rU6KUpSpcvY6iy8QLLpbwBVvEjbaHRQXQ+uA3Dcg5\\/lXJXVlc32rCbklN0hJByCQMDOBnv69K29XuJdHvINN0bRo0SKAsDHG21uSPvAHnjvjrnNcZdeJb1ZzfWtykGnmUxmMqJDIwPzMG3nCDP3zx0AFLDqzvFaE1HdanT6xPef2WbPgWtxIC4PLjnJGMcA+59eKwpNKlTxJeDUohbrKo8tycFSMYAz35\\/TFbOh6rrU8Z1DTdQjjtjeLDEViDCYEYyCwIHOTnB61Y+IesXMMFvpqQtcPOMTNC21xjvnAYd+VopNxqci63HNe5zM4XSLa8vtZdYonC3WJVyAN20+WSPxX9a74aXf2mlXMc7RLJG6+REfvSenI6HI4rzKfVJP+Em0dLOH7K1urDbFI5+XPIJYsSD159e1el2Go2auZbmSWFXwwAndcdjjBHU8Y5x7VWMpTUk0FConGzOT17V743Bt7ma7w0vyw44QccnGByc84yB9a5mJ9RtrxrezmW2DvvmlZmyvIwQD9T6d61\\/G9nqGrajLeaEXMA+4iNu9juLZ9KwoYrjVLVGmlTeVMfkxKY14bB3Y6n369K6adNcutjOU9dDSivI2Erx3E1y6fO21ynmMM5Z\\/myx7jsc\\/Srnw71SHzWu7O+g03UJGkEE86hkK8DbJ044zz35pmh2mnWxkt2gMCzQMu1ifv8Afb7+9df4V0DR\\/wDhFrJbq0t3dFBYkEE7ie4IOMGuKvUik42fQ6IRekiH+wPFd9uu9UvtHnt0VmWOERopY8BiC232yema0raDQRdvb3my44EZsoFWQgKOjNkhRz0ANaqab4aij8ozWNhPHyBNOzAg\\/MAqs2MZ96k8LadZTavLqEKCK1RsQnbsVyF+ZgB2yP0rldV212+40UUcTqGhJFev\\/ZkUUM6oP3EsquEVvuFhkjqR19iRmth4W8JeHt73JkEZVpmnOcEkBiWGcDtznpVTxtceIb26\\/tPT4WnRXQKRKwaRt69gMY+XpkVi+NPFDais+imFYUcGN5nPmM5yBtRQD8xPQEit+SVVx106kc3In3J9S+I+iMrQR6jmTG7dChcN14BA9fpWQGljsUtZFEi3twkpZl+ZkAI5AOfoOP1rR8PeC7a00+GJIVlLQGZ8lQQ6YOPbrz16Ve1bTJEks9V1ZUsIAQ4iVRvY5J4GeAFGS3T25qo1aSfLTE4SteZzL6UftlzekyxxQMwEcZIJQ9ic9M474rs4rXwbZaINVeKzW7ljVyhYMxYqB65znHHrWT4Wgm1zWZri0VksJwd00wyNquGyuepzgZxU9r4dtJtKu7S10+0W4tnUPdfMWJPcADGcH69auq02lJvS39MUdFoZfhQ+QZoltVkubpMKQeRnAP6Z\\/wAmtXV28q4OlyjzGgJ+Zv41PXvx1qTwPoItdSaUm5uDFgb5Vz5ZGenAx2qh4oiC6g18ZSTIxB3Mc56Yx6cZ6960pyVSs7dPzIqLlgrnnWt6T4o8O6m10LTU4Ld8SQTIDtKt0OR2qLTPE9\\/PqtoqzTw3azgq8PyFjnkEDjPvX1l4Cu9O8YeC47cWqGayBtnBXJUrxkexGDXzx8b\\/AADdeHdVOt6fC62rSfvNo\\/1bdjX2EY1PZpp3TVz5j20HVcJKz2PoPRfDWm6nYJJqiR3kV4ilbgrsljbHRiOv1qvdfBrSNVWS3uLZpxE4CPO5kZB6c9vpWv8Asz6uPEnw5hgvrbLwDy3cjiT3z616xaWTW7jBEiDgE\\/exXP8AvE7zkHIouyPlXx\\/8GrTwlHPqXhzUJ4buOIySacSfImQckE5yp9D2rzvwP4j8P6r4h+yanaajZSynEcqXSsASOQSV5+tfb\\/i\\/w3ba9ZTWlwAY54zG4x1BHr1FfEXxl+Hd18OPEcEdvPJPYSZ+zzEDegzna2OD7GtlTg4px6bmlOpK7jL5HqWieG\\/BBiZYUe9uUY\\/PcsTvbHAAB2mtPTNS0aXw5LY6sJ9MlvJ9tyltAUYMr43PkZKlQR3xnjBryXw38SL3TdMWC4kt3sImUCGUkBsfxYVgc5+tdVpHxF8G+JtdhsJPO064mbcGdVEMjf3NwIPPbdgf15K9BTfu6M66dRx+LVHomkeG\\/DXh62uTpOtWMiX9vtZVYloph91iwzk4JHUc\\/Wruv694ah1S0n1e5s5hHEu61ZTHLEBwCvH3jk+gOB0xmvNLjSruz8YPcwW8s9uQGLg5C7uhx7f0zWnr2g2PiS2e2vtRthqVs6\\/Z52lXzJAMZXA5Knnjkg+1efPCck76t9TpjV54+R291fP4604WGlaGW0ktsN1DCF8vG1mB+brxtJHGfWqmkaPrxjltNY1xtO01Y3RZpphC+5QRsQk4KlgucDtz6Vxk2uzaZd6RpPgvVLtNNg3C5BUlkbcxYFFYEg7tvQnv616Jofh4tcCC91D7NYrGk6wIDHbmYF97sNvJIMfvwR0rKpGN+e9vQuLaXLuebJaavp0yT2s5CNlbaTcybkU8OzgEkcn25967S5utduI477xDBBqqtbB7cy22x94bGMDkjoQcZ49+N7x7dwyxCxmDzTxN8sRiPlyfKeDxyPlJ\\/AE9qsWdjeXt1p+hpZ3KOkfntE8exJEXZkqdwIJ3gLjptOTmuSo09DWN9zzt4PCniC4jtoGisLqNkM0Uy7F3CMjKkttbawBPfucV0OsJp922mWFjZw6mILG4Nylm0LlQ0inc5bcQCAeRg56HBqTVfD+gpLfWV\\/bTyzW0SKovIiyxymTcCm4MDkrg4GMLyCM1zesaDYaHrGh3VvYw5WwW11CyjlVpLngM7kNx\\/CMZ79sdJvB7PX+vmVqHxBafUvscr6OYorORLbFwwb7RGN3zBQBtGO1eb31pjXdR0Nh+9hcy2oQ8YKhouD7EcHpXuFnFb3Xha61Gz0UaTpq2rPAs0YE0+cgu2CdvIwM8nnoK8r+INr5uoaf4l0vaZYICtyMEM2zhf0z06Y6YFa0qvLOz0\\/zE43jodJ4U8JLc6be6nqkk0V1p6pDHFKmS0y4ZsELtzhkCqc5JrqPD66bYa7Lol0jBlaS5sohB5YjRyQyl1ID7gBlRwMAdGxWX8PG1bUPBurC4tUbSrhGSCNv9b5xYDIOD0IX73QrxgdK\\/xM1eLSdQ0WGbyY7qXbC\\/DM2QYu3fkk5Hv+M1JuUnFeYkuVXZS+O0Imhiv7R\\/JkeQJMRwGUI5GfbIH518zJqE9rdosiDCsTlTgkEete2\\/tB6vbRTDTNKuZmKEFlBcrIFG0sdx65DH8ee9eFamqkJKD8zfeHP0\\/pXZgb8mphWknKyNZbm3vx5M8skGcHccEfyzVhbZT5b2mqQxeTlwXjZfr2NZNmvmSCIx72UAk+nTvW3qsFvG5CdC0ybVPbPH8\\/0rpk9bEpF7R55ykzyvBMjqDnb8p9QAPXJHv+NbKXFnNIFMEuwoAYzzz1G309OccVwKs6yREZBAPHGOKWG5umnjeKWczOrbju\\/KspUIt3LjUa0Olu7KRDcRxwoFkBCxl+SB14\\/z0rotAhD+E91wRvR9wYjkHkcHtXO6LELm5UyyL5ka5+c8KCMEDjIyWFdZYIF8MNjjkA\\/XOK48R8FvNHTS+K5na7BJYXbXN5tmheOOaVhwUAYcAdDkfzqzJBBb6A\\/IGbtNp4\\/2Twf+A1F8QGiu7JmjOdtssS47kEcfzrD0zU5ZI7bTL+bKRSIAqnGSBjr7AYrkjCVSnGXbf5G0qqhNx6PY6bW5S94xG\\/7j7tv0A\\/mag8VaEbvQtN1GFVNyqKRGTguuOfxyBWhBbfbPOkaRZHVRyuOjEYz\\/AN8\\/oa2rK3WTwdpeoSc+VGF3HthwPy4rF1XSUWuj\\/Q25VJtM5\\/8A0G8s7G4gt2jaODyZY2X51cFgf\\/QvyqXwdBBLrDSupkaO2YZ\\/u4\\/yf1pEs2j8RzxB2MFwgdkBwPMx1GOnT9KveEo7ddW2pKYpmjOVDj5hk\\/8A6qipZQkl2NIyelyDVYxDrLyW9s1yVZyi55JIPTt1JrI8bwXF9PZtHaCzZRJM6dSCOeuQM5\\/ya3d7jxOLfbIsvmxvGuR+9DZGenbB71T8SXV63imKDTYxJdxQs4id\\/kbOc559OnrV0ZyU427GVRJxd+5lIqTXyW9uscKwSRgufmllAx1HGAc+o6e1aOrLcaVak6d9nuJX+WOMEKYTn75HP4j1XPrU1ldXeLhrm235CmFY1BMR6YYZz2\\/XHNU9WvRHB5UdniXIaa6mUoiZY47cNyPy+ldUWm0rmDv2NGLw6bLQGvtSlEd26SGVpJyQ0gPbBxj6DPSuZtoIL+4LS28cFtcRhVkdWRDjqA3TsOPY12Hhie6vNMLmWK8aEYiRZVLyljjOSQMnjqe1U9ZjEcwcx6rHDHI3+j7YpIycZ+8u7uTx1wDxXPSxE4ScZO7\\/AK2NJUlJXWhN8NIIVvp1RpFhhB8qLzcj72C+AcZ4I9ua6jxHoOm6jqlvcTL\\/AMe21o9pPUjvj1Ncx4OuCJ7hm094I5GkkUrEsbNhjktznnevYdK0tJvp77VrqFoQjbEbjBwvPB\\/P9a5sRzKpKouiNaeqUWaegQwx6\\/8AaYw5f7LJ5RXOCAp49znn8qecyWAV4gGeRnJA5JOASfeodCh8m9nlDNtgs1hTDEBSVZm6d8FPypt\\/eyR\\/Zo0TPmI3B5wCev6frXFZynp5fqdGy1KcUranZ3UE7cxBliwOwPSo\\/CUFomlr54CmWeU9cBhuI59TXRNFaxQRR2EPllAS5ZOWJHUn8KwrW8n0fw++Z3huZLhvJjVC2SzEqOARnkV1czcLR7oycVzXYuoJb2t5IDuiW6QbCox8wYdvfPX6Vy3xAvgYrHSreIuIhvlfYANzdz7\\/AJ1p+JNN1i0maa7vFuLaRlDjy8bDnjpzjp3rkIrGSW5hkuL+SYMPM2DOOOOT1PT6V04eEHarzXsZzctYWO98OzJa6KFlDBinQd+2aY2rTwRy4MbAbcBvXrk09ylvFAWyY1R2znggYrAt5JLjzXGWLtnA6dayw1qic2XWXK7HUy6hdJdWkqpHxbTMBjAGcd685v8AxLqP\\/CNTwNDHCyXYwe5yP8mu4lv3W7iZivywt8pOA3+cVwHiuBn0u4mWIIHk3bF6LgkfjXoYaKvaS7HJVdloT\\/DHTbhLZtakjMhmyqnk7VDdT9SP5V3mrWsv9nxmG4MLmPcHi6LnPIHTJFUPAJkj8Oad5TiHbbx7h68ZNSeMLKSa2U295JB5i7pIgqmM5HoffninWletdipL3NCvpWny2GhvdSTGV3jLyM55OakFqs9v\\/aMhlZbbAcRnGDjr9OcfnUsLwXdqNJhLFJUJZyR8q9h\\/n0rY0nQpP7GhmjLwys0g+1OxxgdsfQdPWpxM1FeZVGN2czf2MeoXMMmnvNKbdyYgxAAbGeuOSeO44FeueBZ7L+yDaJepK0Y2GRQUGc9s57+9eV2d\\/o2manCkS25cECRow21mxt3kc9j25rutK1eGGeO+mtQtuYwpRBuWTdhehPXPWuLEc04W6I2iuWRzPxisJ9R1kW4dVhjgyZJDgEknOPzror3Qp5PCzxtC4ka0xtPJUhex5zWD4uFt4g10pBDMhMQEMMEeCWydoIPHbJrtNJ15rjSxb3iwrceUyOqkj5wAOOMD86hSlyxS6FSSTbMLwNeS2euz2ErsizgSA56EDBz+lauualaWyR6XCz3dwWLgKMk5JzwPQiuY8QaraaVdB1lt45Zk2yCWRVBJBwMn3wRz2FKbyH+3Bb28iT3iQr5cczBS+BuG0A5JH+e9OVHmlzsSnZWK\\/jaS8ubbdZWMqoYSHk28JnaM4JHofbiuYj8ZQ6hZQ2ywsbu3+fyRGxJdT04HtXS+PNQ1i90cWltbNNdPjzIwTg8jOfbua0PCuk2VppMrtFH5z7gRszlv72ep5HT610wUIxStf5mTcm7m14FvrbUtKuIZoCnltu2SL8y56g46HINeN6lqOkn4k6mn2Pz44P8AV5+ZSwYlsr3HJFe36Ra6fC0s1oESW5Ta2xUVQBnkgDr7\\/wCFeHXtjJJ49vhpwhuJ03tIYwTnLAYyeM9f15owUIqtU9BVpN04nVeMJvsiWV7plmsyTFQzm3COXxkKVHJxgnn2rA8V+I47u0mt3KyOhhlUKmAjAcg9Bxzjr0rqEVlto7CXLLdI0TL5qlQRwTgZ52k+nOOtNtrI6Y1w7WNrKFuQIIlj7BQvTJAPQAkA8ds10QUV8XQmTdtDmNPXXbOZNRWzkiiTEjOk2E2g5AIBx74r2HxTcR+TY3Ulx5Vvhnldj0AXt35OO1cPcX811bLbabDGsc\\/JdXyqqcDAwDnBzXX+MbOzm0bTbaWzWeNChldmYbRjHXOR71y4qOsbmlJ3uecaF4ottT+IqNBJJHE5zGgYdVOUyfXqa7VBPbXl7fwztHe3MbMqyO7hCOMjcM8k5I7enSuRv\\/hwuneI7LVLGe1jCzq5hiDBQoX5sZySSRnnHStzxPFem08\\/TpoYpEYw+c2cc8DjnOSPwq6qg3FQeliYOSvzHj\\/iKPUZtZ+yXtxPcRs7SMAwB2gFmIz3+ZuPbFb2h6jcQ6YkNsqW6P8AuVm8xhtYnPOQcnv36HpVC5OpQeLHglfzbpIjHNPDn5AzBQT6cdfrXeXOgw3WmaV9jjto7y2vtqBjsEzFgWUkjpgAY\\/2cV31lB04qaujCnKSm3HcoxSeJZobYXOtWkdv5hdzHJjMQJ5JGeMDgA5xXNa441WG9u47mJSkirGBM3zLgD5QQMZ6n610Fh4aFt4n\\/ALEaSaKFIlllhmZGZNp+ZlXnGCR+B71h+NbmS3mhhazlsZEiUwLnduXGQTjkEgjjqO9YUaVOM7U0l6JI0qSlOPvv8TH0fW9Q0ezkaJk8pjuZBjLHgHH0BFd5o1l4o1uxgvl1aW2jCYW324PJz14z9K4PSZrG4vFS4EZeR8CJRsH47h2r03TfFFhpNnbi5gvVXyxIrmBgNpIGfpyOR\\/WuTNY1Uk6FNOTfZP8AM3wXJtOdl6m01xPaSq13JLnZty8mBkfoKrXF1pT3qz7pPMjGwYbP5KP6Vhan470qe4Xyot6M20mRAFH\\/AH17VLa+JbS5vU+xNbwzJjdvBBKkHp2714kcFXsnKDWh6Tr09oyTOourxYrESkSEM2SRk49B7Vymta+qTmV1VZgcA7eceldHDrK6nH5Mt0u4qOAOW7Zz+FUL\\/TdJSeOa5EMgyd+4ZHHSsaEKdGrapF3M6yq1FeGhhRWt7qrrd29q0oxkBPm5z\\/OuN8S6fqz35uGtJofNUqIyOo9T7c16ra3tpHeSWliRBFJF8kiOFAzg5H4EH8a5XXNZFvKbaeR5FKYaXcCWwCMc\\/wCea9vB4mpz2jHT9DjxVKHJeTPLrjS3D7JnJlxhQP4QPXirfh7S3+3Rv5qgI+QueCe3+TW5qUuWdZJgwbkAZBK88Cr3hDSf7YuJY4His4YtvmM7bnUHI4HGTx19Afavf9s\\/ZtyZ5UYRnK0Tm7i0uGuWilkE04Zm2Kfxz6cYqa3vLeBPMkaVo8EBY1wq57nj9eK1NR8N6jaXjyWihYU3L5jkqJBk8j2OOtYsaXaEpJauxaXDblJGOwJP1rO8ZrciVKUHsSw+RMoaXLrIdowNvfjJro9C8PabFbrcPG2C2efyzz6VFElqIQl3JClxkBYAR7Ybt\\/8AXqxexa3Gqebc28sTceWrZYg9jzwf5YrGpNzXLF2O2MEt1cfql\\/dpFcW0SgW+Fk25zyB0z34PasCS9u7+KeGQqHDg+bITyMH5R24x+oq4NKkvp2Y3yTBMMnlyEhT3X3OB2OKnWGOVI7KC3kdCxTeQRlj1CjHXjmnF06URVJTkjMsXTTtNkjcpNK7BZHOcdcqAe\\/SqNxrlw4W3WBcqcKGBPXjvnNaR0K4js5DdszNwViaHBK56dMjjtxVLUdNjjQ3Jt\\/s8btlSu47eMYPJJ5Xr9aqDpSld6nHOE46sozlbSBElVGMiAFiuSDnp+FXRFo8drGsN0JrgxFiShDE9gD\\/StTS9FOpXkJnztY4jUSEk8YPuOc9f\\/r1vap4Og0aEzR2\\/2mWQgMjnKxr1P4Z\\/HioqYunFqDepccLOcXJbI5DRbC6uruK6+yzJFggGELnIxyQfT1Jxn8q1P7NaeR3ug8sWAAJAQ4OPxqyfIitHkgVMYZTHHgpnGMjDDk59O3NU3jFm2+eV5fvDiTBQ7htBBxxx\\/nipc5TlfbsKVHk1Nnw34d06GI3NwiwPuBjkJDD05z05x34rUktN6\\/ZLG9C3Ua7iHYB+fr0HbiuSiuzcx7rgOCHKxIYuCpAwQDnB59as2P2mS7Eds0obyvladvlI\\/Uj\\/AOtWFSjNtylL\\/I39rGEUrG3fadrMdg7maFZFO0ruDEAk5Y8fn9a5d9Nupbl47totsuMySyAEADJwzU6w1hrDULpb\\/egdTGpJMjHthSe2R1zWdqd+XiCXMonU\\/KwiO0gHp068fyropUZx7a+RlUnCSvbU1NBuvM8q0SB4EcFVuDyoX1zwPWu7sJtMk042000EqsuETYWYPtHHU5H+NcHompNcQRaXpsCb5pBHHD5a7v8AvrHPIyc4Hftx2Gj6I2n3L2d3sea6LPGqsCkRGOuCV3Z7jI7ZrlxlGNm3p1\\/4JvhL3917j9M8RSQlnmiiggf5YWmk2h26HHBIH4da1dQ1HV575XmhgmkjX9wnlttX3Vioyfeudvb+yt9Xj0yVYbkyEq5YkmL8eMnP8q2NMurrVYP7JuXWKBfkjaaHcxUHDL2xn1r0a9P7SRlSn0ZJplvey6bKkkUflhyWZGJyc5PzDqe+Tn6Vy2pLdQalJMIZ5vLcb7l0BPB52hQN3I64\\/Guss7K1GvakqzrZiAh4o0l2ADgnIPBByMA54FZPiaPUr+AgXdpPZ4\\/cxrbswkYk55BwDnPtzXPCdptPqayjdJm9o\\/im1urNUuYZVnSTywQpZgM5wUHP6VQ1HUdcvNYinNrcwWgXYSdp8wKflYRsQy8EkgnuOtZfh7w5caXqF5dXN7K22EqDArs6MMehz0z2\\/Gu88KTXUFvHqF7Mbme\\/UFdzsr7VHy5J5U+oHesmqcW3T1NE5WXMbfhzUtO\\/sz7NNIvmTbiB9mKrkk8AFetcL4o8Sh5LrRtPSK3iYbHATe0wz0z2H0qxrfiiLUtTj0yWzH2ppA+xZ\\/NfYDu4zyDt+nWotbOl20Vvr0VvLHYxNshaFgGk5wC2eR+Pv+MQw6jK8luOVW60NHQPE1xeNa6W8T+YMlXCuoQdju2np+FaP2Xw9PeHTbkS6i9qjOyrBK0jO3B5QBRkYGcD6muML6bLc\\/2pdzXNrK5zAbeb5HHclRtxnv1\\/odm01qCzaSazjighkUHZE5wSoOMlst3OT8oOMYrplQ5bKOhgql7swdZ1e7hvS1rbT2ttC\\/7i2ZmVBsOcZ3ZPJJz\\/AJGj4Ev7ixktvtsTpp1w5ZIpJMiMkHoTwATwPTn8IdVgktdMiu30+e4thlphCxYpxkjnqOMkZ61H4b1qPxJo97byRlZreI+UHwrHJYowA9BgEY\\/nXROlB07W0MlUlzXPStThh1HyNOll+zQmFt7n51OeoYZ77ievBWrljrCeG4E023ma8jX5kdLd3BzwQNnbJwB15rG0cQv4T064vHE93LEjM\\/8ArXdxgDq4I706fVl0LQby4GmXNysQaQQO+DuxkA4zgHHGR\\/8AX8mpR6b\\/ANbnbCp3MnXvFelWV1azCGS3EryxSiaFgwJPykk+uCK5jW0tfGuu2GmWllchYoyZZXiBjBGCCOc9cg13Hh7xTpt\\/4TT+2oVSS9jy9uGEvlruIAzgAZGOcDrWpHZxSacYtAvRZ7AHaRsuFG7IG0EDPHXk8mupSlCO1nsY2TfkctfeA9KQjT4j9l82LDukrbEIGCNgGM9R69znmtGLwno\\/hjTFTw\\/pOj6vcom3\\/S8eZ16gng8diM+9dnbXsGp6eTJeMkYVkbZwfvEY3dgeK8l8e2mqaZDdx6dFPL9kkKsyAlkAIw2e2QRkevNZ4dOb5JsdWVleKL+p6xZyeK7FzpepbY2Ilt7yJfLRABl1RBjGSRnPequt+IluPFAeOS5tIJnYJ5blVyCFyMjioPDXjO8urUWFzMFnCjhySJQOqnBBP5iuhOnJc2NlewxIbeVDJFGybWjUhiwYDvgj8q3UPZVeWS0sRKXNC6epnXF\\/pYsWN48S+QsiSnJaR1UcBc8ZJI57Va+HfgDQNW8K217fWi+bKrSYcbuNxCj68fqazdGNlF4huFuXtpIV8v8Ad7AVBwf7xz+XpXoHmJe28em2Mgs1lLKrwrj5Rk9egHWubFQlD3YNq5rRmpK7PJtW0nSoNUurLTI7KK0iO0STQqN5GCSS6n1x2rC1iGKGS1sBc29yXQuTAsapy3+wox365r6D0\\/wfpNtpz20kxuYSASJm3EHH3txzk5ArhfEHhjRbbUL0Ja\\/vJFUI7HO3J7H2608PiLy66DqRVji\\/D2nTp4l0wrCmze7tlsnIUYH4jNdvrQsX121k+yz23zgSjb94d\\/8AP1rI05ha+P7Swjtm2SR\\/u5SQVQ7Tnv14NejeINOtrixad9xKKWUrjJwK5MVVftIt9UdFKK5WkYmqT6Lc2MkUs6SReVmSFjtaXaCemRu\\/Lmi5j0ganZaVbwCCyihE0kMIVS3IGPUd+4qDw7aadaQTSNo1vPcBt4YhSxBAxgMuR6\\/eAzmrDXaW0zySulnMYAqohV3OWbB3HPQgjB9TWnsLvR6GXtbKzK81mv2y3lhRkitpI9g3DC\\/N1x0H9azviBbH7bA4GTKFfduBPQ+nbmujsmd7eaeW5Eq\\/um3s+5mPGc4+ormNfaS91LlWxCAm0HjO3JP5mnQUlVu+g6jTh6nmktlNF4u8xeiWxbI9z\\/8AWr1zwmTa6eHmsw0knHmBclV9R6d64SO2X+1b55VMYaBII2bnLHcT+mK7Dw5f3MNh5EE1rl5DuEqDDKFHfr2Nd2K\\/eI56Xumbqtpc6bqS3YbENyxVETjB9x64qxo+n2lrBeNb2mZLqfz9zMOPoO3Uce1UPF93OdQ0i1knjcjeWWIEDLbcdhk9O1bGktbqjRSbllRSqAgA4PTPB5rGcZKCbLjJXZV1ewsp9PVLpYI50mQpJkDyw2ASM45xngHmrlvo0mlWn2L7TJKiwlkI6Njkjk\\/X8KwEudUGuraSy\\/aICwDK8C7SAc5LEcdO1bdiEu9QvrgXtxHbSA5hZwyZOc8dv65rGpScXvpuaQqXRYs\\/DcXiDVPtMkolEMaIodijBhnOPoa6l0lstMa03wLN5WIpd2V3HPYH9K5vw6qwaxJG0gRfKZtgAz1HpgZqXV5FiiCx3LrgbgrEngEHNZTp81n2GptaHP6la6veRtbr4jha4jHymHzGEbZHLDnBGeBxVbXdItlv7eOKNFW3jD\\/KoLSOSBkhQMAEjv3qzf69FH5kdre6hcRxqoYwzJGCzdMk5OPYdahbUNY1W+R0tBb2ETrPNL5nzkLggHBKknrjjGBVtSWuxV0b2vPLZW0SWq+bKF8tfMO1SSeSWPfg9TXG\\/FWx1ue80ixv7sL5xKswbJAZlGAFwMAE9ucV0uq6vb6jeraWt4AyqGViQ3PXkHr06VlahFpkXiiwCSSX+ozzCWSSVSgcKQo+cnHGDgAdKjCxlSak1rqFRqehuaLp9npdiywx39wkNsVM91GyxDkbgmRgcYyee3BrL0TWIoxrGp3MRHnKsixhgdxYtsI6c4x2rbuJ5rnTbpdYVIWz5Yt1uQy4znklcDt0rnJAbrxJNd30sFpFcxpJGtwx8tVUDGWwSflJ7Z6dK2px5otyIk7SSR0XhGd4NLuGWRi8i58pvvJ6Z+ua5ma6hfV1g1OBI7aE7Q8jD77evYdO+K19P1e3sHu72+miSyuXMds8JDKUUnLHGWx9abr03h7V7aNtK1GxuJvMUsFmXPucHn0rfDpxm3Yzq2aSIfg\\/rc3hf4g3WkJcNcW97IJ4QT0LdRX0lqugad4n0afT9TtEIlTqV5Ga+VfhPbWTfFryNTjujNG+YpWnyCc8YAAAFfYNkrJbRv3HGfavsIznTowdz5mrGE6stDmvgz4Nbwbpl3pLPujE5aM9ip6V6FEVWXYfwqvakHB9qjvHKTIwrOMue5bVjSuIAyb16jqK5Xxv4U0Hxdpj2Gs6dDdJ1AcfMp9VbqDXW2sgkhFZ+oR+XL5gzjPOKdJ3dmKcdLnh8v7O3w+FnI32W+ZiTz9o4T8MfzrkpP2a\\/CLTOia9qtrdSuPszFVZUPYHHX9K+lnghkYSKxRmGCR0P1FVm0e0tpftMu+ZVIZUU8A10ShBxskSqlSL3PkXxSt\\/8ONQXwz4qc3RMnnQXiDEcsZ749Qeo\\/8A11X1HUluvs0elrCWEgbzDInzBsHcuCc4H0I+tfSPxZ8B6B8RtGRLlp4ZYGJikjxuQ+nPavljxX8J9c0a48q21eNbWGQmOSQMhQ+pIBH61hUoz5PdNqdanf3nZndeCPC87+HtWjsbzfdtKZLOUsf3nB3IwPAPXvg+1dFodv4p0Twa8ltHFdz+V9qazlw3mKDtP3gQp5yOTnHPqPELDxH8QPCkkr2uqWM2FIxGySF\\/9oYzz79a6jw38UYfEkYt\\/EVzeLOrYdN5VBnqMDHy8dDXjVcI07nqU60ZLc6\\/W9Vk1qxubeBkjuWtxIoiIysoPLD5uTjP\\/fRziuk8Fa3ead4n0z7U1zcRTaetisSQ5G9PmZ3lJADnHfngDNW9FFk9pavpC2zxAljtj3FQvLDofpis7xNr0Njp8Uen3zy6\\/JeMyRpsjkEbfcICgblBXGevJJPavPnR5dEzp54vY6zV7SC38Vpqd54ijtDdBJTZzyKzOiiTIxzjlz39euBXm3ijV\\/Cdr4vudU1HxJdTCGIwSWaB\\/tDzEkMShQYVQeBkZ6nqc8zq6XGoy21zqNnf3OoX04Ihij2+WdxO4DgklgM8jGaih0XUfFsNrDE+maeILZxbhZEidCrbT5m3ncShPzEn9aI0VHd7jumt9TuJvEMlp4aTw5baLd+RcKAt9eE26sp6Al1BG0DtnGBxXhniPV9e024fTp7ie88qUossO4eXhj91gcc5OeOc17J8PbvSNQ8H20\\/iW4aSSD5WhjgJAYAjG7pkgDg9M8GuRkivR4yv22QvYSZNrauvKHgKdxzhvxx0q4pRbbWxm43ejNH4R\\/EVBYXunTvJYRzAMs0itJt+Y7\\/nyPXpXE\\/F\\/wAZLf6xZrbSpLJbkSrPsIw5Cj+IDoEUYx1HvXoHhrW9M+2S21n4Tiu5EjMflBwgiBwXYbTzkjpnt9a4nxP4a0\\/U9SM+028k7+Z5YU5UHOFBPb3waKcUp8zjZCnBuNkzzXWdevNYvDfardtNJ0Clc49OOB\\/+v8KzJczKu35gxGeMBT6elegap4LjuRA9jdwRJAfKMU75ILNlenYk9azLjwVeaTclL+ReSoEUbZdgecgdSPf3rthUglZHO6UrkWh6PPBdx7riKWKZQHMJ3Mo7cce1X9V0myG501C588zN+7aMfdIGfoc5\\/KrMN09vJHDZIkEiDG8oGYkn161p6NqE9jctPKYXmXpvQ4xuBB\\/MVjOc9zpUYHGLpQW\\/QQ3F06hyMmJcgY9sipX0m\\/t9TRoIWW2JGxmGMgccZ\\/Gtu6ubuRZ1SyhkEzNvkkjyUOc\\/QE9OlVLuaQ26W7IjEZJCL647D8apymwUIFOazgkWK5Mk1tPvKvubhQTxjv3qydS1QafJZ213GVU4dfLIYY6EH\\/JqO5Me2B+VKEPh13EH0\\/rWppt3FprMI4be4lulLosvzBQT\\/ngVlVk1Ha44wu7JmB9v1A4ilczRKudw6kgdK1J9UtYtYhuUspxHExZ44zksxBzz+PT61cFvp03lJbxq8zNuIDAKh4yePp0rX0u20+e1igntniJIO9CDluM+3tXLVrwiruLNqeGneyka2kvC+j3l9AybLmRdpU8YVQufrnNGhanDc+CI7OCbzPJ3LKcEbX3Zxz9R+VZOuaBZ7ZEtHljUoDwSise\\/OMYzjj1FYGjPc6ddfYo50awmkJliUhtuR2bHXH8jXNCNOvC8X1TNKjlRnaS3OwN\\/5mpOUAIa2BB754\\/+vV3w5LC1kgWJCVhkIIwcHf8A4isO6jgg1\\/To7ZZms72J0ikYqW\\/iO35c8dBnHpUmm7LDVbWOBLmRpJmhniLKSD1LBV5A9sUp0lKOnb\\/MtTaep16xwrr0Eu1WlUsYyeuMfTPasiOBrjxreXDY\\/cRqinrz6ValvLCyv7SW8unG2Mg9Du6jOfXk1H4UvLG7vL9\\/MaGSR2cBzj5f\\/rGuSlGUbyt0t+JrNpq3mV7iTUbWO8vbWB443BZhwFIYEAgHn64xjg9aq6LBqSTiVbZWaRTJGplO3GF\\/hI55brkDg102uaZb3WkzT\\/uvMMa4TOZGCg88nHTHGOwrJbVNM0\\/wUly67vIyroMvvGSvXnGTg4H41upc6XItdjLa\\/MzlfDOlxvZ3V0t1Cwe4JaIZCsucZBBB5zx1rsbu2stON1c2WnxPcJGPLM4AESL6EDcFCg8A+1ef2Nj5GmRalcxu24qI49w3Dq24ICenH5dK6J7zUIbSWe5jZrG8t3hVz1DgE+vcZ61tXpylPe6\\/4Ymm0o7HVeFZne4upLhIgRG6EJnaMkdMk46fiaxtH1SE\\/EOdIx+6kRlG08bgQAfwAP51saDLaKLy2lKiWYGRFyQQBg57eoNY+n+Gzcag17baiLNkUkDyyyEMBgkjOMkceuMVwwjGTqc+l1Y3k2lHlOngXFrckLgtI+TtwT+7HX+X4e1ZmosftVjPnI8tUPGOB3\\/X9K0tGurRoL7ex\\/ctmQhehBwSe\\/6VjX1zCbhYVgJYnamDhcAn5iT6+nXisaMXGbTX9WNZNOJ1aNCUd1UrjOeaxdJlaMzyosM+GJBPLRnaM4PaqklwX0+dWvEihjPzkg7QuejH34471X\\/4SSx07SW3JIIHAigEagFiepUMwyO+a0dOTi4xV7kKSTuyXUrg3El1HIZEA+8Rhjux2BzXM6Tbr\\/aEIdBjyiCCckDJ61ZvNcu3juJYbFzDguB5q7ieF5APHPfmsSDUbwhZm0iGbftDRPPkFTgkEgcZFddGhPkaWhnOrHmTO51OMp4bWSDEhVWHPIXkEjHUcVytlczKHLQsCe\\/PNTvrt1BpVoh0e1tIWYSyeUxVcYI4XqT0yT6UqzRvZpcW8U0yseAhXqfTJHT8aKFB0U09bsVSqp2ZUvLjhpCAoRWwCensKyNbvHt9FePhmIG7cM9f5VX1a+1C1v0tf7Okk3MSylgTt\\/Dgc+\\/5VDrep20ll5f9nX645JaNQCQPXca9WnC1jhnLc3vBXivTn+x6dLFJE6xCPzXxs3YxjOfbvXWakoms7glvkVdoBGOMdq8q8HrHdSXsEw2qI0YDuGycg+9X7LxTqFqs1ldQPcxr9xwQrAHsex\\/nWdfD80\\/c6F0qvLH3judIhFuZZhtZ1RQRkZI5\\/wAK35L2W68MXRguNoZGRX3bNrNwFH+0cnHX8qyJ0e10uWZJSWkznaT8oFQaTsvHsI5Id7QyGNwwwpBBIbjr6c+tYTipe8y1Ll0Rn6DoNmdfazaK7ukUMr3JO1QwXO0MO4PpXSeFFutBkvlW7up5BIQcNksMcnk47jnNdFf2NvZwNby6WJLLoSuAq5xk\\/U9P61zPi64tRphttNtokaIqzxWxXcmemcexb86wjKVSWq0NHZR0epq2mp28\\/iCOSOZo7h41DFiAWXdgrnPfIzj061pGG30+MSTNGFTJDO+Tj88dcV5qn9rQeZqB02aUDEfmuPu49Mc9RjOa0LzW9e1y3eyXTnjmRQz+cfLLpnhsHGefrTqUk5pLYIt2bZr+Jo7oIurR2UNx5zriKWIF4sN8pzuGAQD06ZrO1zxNdOlldtZRq8xIDiRXZccHkDPfrWp4Z03VLi7RtTuhJC8fyKhxtYhSDjkd+tc\\/rPhqKS6eG9hjlkVypkQeWygEAHI5JxyaFKnzcrHyytfqVrLxfLpk00sVmJsyMjSPnbuycr6dc855xXX+EfEqa7EsbwKGhXLMncljn09R3NcxpGh6FL4ZuIYHluHjwg3lo18zklj3\\/GoNCg1HRybi3wyNwyxHYjKMjOCM\\/wAq6PZwu2lqZObasemzWzyPyqRwlGDFWzkZOOleOaJqNxp\\/jzULezuzbS3CuI5CAcOCcdfr3r1rSL24khkeUOm1X3rjg4zgivHfsyan4vElvEyPEGmkY8YHXr7nis8ErufN2CvtGxtXFk89wlxbahJazBvKaY27He+MljjAXqeg71fuG1iwvjNbyG8VY0aO9dcM7bh8gAznqPXg9KtWLRx6TeW5LSP9oO5ScKAwXAJJHv8AmaZHrF1LdWUBs5YbKxIbO3y93zY2hyeRgjn+lbN3lYlbXMi9uL64kSLUdPuignUuCAAxznHA7\\/lXp2oXFtqkK2x+2RIigxyK5jUHHIGDycEcEEVz9jCmo+ILq8KN5MZPz4yAAAOPfOT+preMC\\/YUgjmZjnIBCsVye5xg9xxWMqfPJeRfPZFCXVrRNVW0+1xvJIhQBsbk+Xrx7\\/SsbxhfW1rDFAl+u9p0LgAkA7s8kdOp6+lSxeHrVdRn1Ka3t1lWTETRsdu3AHKdMnn+dZWoPDZamtvHcyP9o8xFjBG1MrjOPbOaFStNWDmVmYPhpbi78QahPGY1FxeiOXC5YoMY59DmtPXjeaM85tGlnuJbo+VFIeLcKrHcGB7kE854wTycDJ8B2sh8VXFgbi5WFHWYyomzcQeBz1HY\\/Q16no2mRavqAExVhGm2RSOCSQAMfRj+ddmIkoR1MKavI8\\/sPt9z4m8Pa6YpJHuEaKRGb5ziMv8AP25GCDWB4qtpor+7v7eCd7GEBXWZRlZSo+TkdMnt2A6V6ZfaVLa+O9PW0jaC0gLhVZMH\\/VP8o9gGH0OK4L4vX11p15Po6+WbSeBHl3AK3yk4wR1PIHfpWNCTlKNv6VzSorXucp4Y0ebVrmztREqyXcjOkpcDKgfxE9sn17V63f6fZyWcEmoz2qhWNtZHY\\/mJtPTuuMjdnHrXCeALWKbwxE76jPb77gRxlTkoRJyPoQQPxNeseHvtt7ZvHpQSz1GyBMrXFuDEIiOcZBz0AOCDyfYVtiW29OhnSslc8s+MWjT2E9nJLAr24BEk0ceC7kE5YgAevT8q5fRrVQ7X0n2qRZk\\/dJHE5+YMuNxPByM8g16b47tUS0lvdRs2luGYvEFj2Rc\\/KMNyW+9361zfh\\/U9Oi0SO2X7IwEDtmaIeZbvuOdrEAqTgHrgY6U6c2qdrXCSvK5m+FrbXdTnmtdPsJ2eJWkLmQLtXuDx69u\\/NS39tdtbPLc6jaCdi52vINwxng7enTHftXW6NdzaFoFtqt1G09hcWaITDuBZicq0jZGBwOme9ctr5TVNRN5bizgKBdsMIAXAJ5zgZ7djms2lzt2SNYuXKlcktvE32rSmtLVlllij2Ruo2iT0yp5zgVjG8nnEk8SRyPLHjlQec8gZ6d\\/yqK0trm5Rp9OgEYWT\\/SWVRtGeDg9Sfp71Y02JLIpcz3MsbOT+7Dbu+OeODxTVGnTu4oUpuqlGRgGyu5Zi0ivGzH5gME+30ruvh3BNFeT24g8+GWNm3SxZTgAEM2OMhuOeuPWse9ncMyxBAjp8o9fU5xXo3g21ktPCkl\\/AJWiTy1mK4ImBAMmwcYxyPcrxVVKjcNSIUowloW9UtY7bw7pl1fA28iQLHFFv3IcnJbcctjk8Njv2rkryS0iLgrEEY\\/KV\\/iPua6rxJ9k1jwlDNJFHCiFpykQxLInO0sex2449hXB6vYXsGtNp9hYTIywrLIz\\/AHVUruAAOeg785Irmhh+Z8zZ0Otyqwk8On\\/aPtKRpMXIMjYzj29DXS+IPFFnc6CttNGvmRkOkh2qW2j5h1B7DjPcVwN6039ofZRMtyY22uF+UIAfvcc9z19PpV3RbW21PULbSvtDQwTyrlnIwuOSw+uMD3I9a3lRVlzdDmklN8y0Oh1TRrm90e2vZLWFLK7jE0YtsYPpkLnH0rGj36TamzcMokYvGI1JMZHXAOea9Q8Ca3aalYXdjYxQXF1p0RRIbhigYxjgsG5HPbnHSvLPGdtqth4glbzfMiuGkG0MD5bquWjyCV6Hn61EYOb5HtuaSlG12V5r25GplmIKzAlhtOMD+InOc1X\\/ALSiNs0IuQsiEsw3Eg89P6j605dHjxAbhZIrmaVUWMKWznoBxg\\/SrQ0m3MMs0NpcPGjkECPGW46gDAHpWjjTVjGVNzdyHRdZaHZKHZ3j2xoyx5fHfnt2Gev1qbUdWmvHFsbm6hilxkgFmkPPArZ8JwGDXbW1awkUyyKhjMTZG3OCrKQc884rsNbs\\/wCztOub+ysftEyCR1muCAY1DkFuB1ycDOcgfhWFSUIzvy6m9ODStc8wghjsFH2a1uruViuEkwEU5HbjJ47Vt6la\\/bYrJYY1je5XBRmLKuOo6euOlV7s3eqX2brTJI5XQSLJkgkZIz2zzn16Ves7m\\/hVNOkDPGoPWLLKPck+\\/pyTSrOTs47+oezjJ67GLZae0DxxNHHB5ZZnljXOSQeBnnoffqKzYWkfVI54LmYqkrGSPOAQT249q7lNFn1USSx3y26rtVkcZ28HkjIx61nXnhu0iikdLgsF+RPmwzHrkAfpzjtUwxUHeMnqKeElo4rQwfE2mraC5kht3Rgm4BwDjJ6gjPPX8a5rRLR9Q1D7M6mJSpVjzzx\\/jXfSxbLGeGCJ5Sm0BWyTycgjPTv+VUpb621GzTTo0jtdSBBeQKEZ8qAMNnpxXXh6suRx\\/Ewq04yd1oWdMi03TI5me2imlEJWQoQxx12nv6fWtXQ9cvdRmdXRI7ROVjiYll55UZHHHQ4x6d646y0LU7i+lhJ\\/dpJtJUgMSMZBGcngf5xXb6ZpMdrpcKNcCO3jkJCL8rsTnBJGQevOTXLiZQjG0nd\\/kaYalV7aHJ6PZXOpump3to0QF2AxckP8xz3HQAV6nqKPapGlhZBgAWDMfMPc8c4H5VzVw2t6kbG207SrmK0iSMtJcQFC2OrAdR19\\/wBa2NX1Fp9Kgg0+\\/wBt08oRsEBuSc7mIIHAx2r0Kk+dq5zxhbY51Z7aVGmvoY1D5ZlAGBg8Edyf513ttqWlXNnbLFOy2oIjlLQ7CjMD2Ix9OK5zULEQfZ4tPit7tYUWJklnaVVB74yec4HHrx0rN1+51K2ZLTUbS6gK\\/NHG0B4U9Duz\\/QVxzpKq0dEZ8qZ3FnPHLcyyQzxyQF0cp5QLgY25HqD3Pak0yyl1jSG8lYpPs8kgUM5bbj5gAwz6DvWfBd2OmxRz30Tzr5QVZwuQCwBOAPf0HStn4aX1kbW5trbzPs6TnO6LB5Ge\\/wBa5VF025JGspcysUdQ8Mwad4gg1gDyTdotu0rHJiBPO3J4yOOQfwrzHWtUjhuLyx1aIqElKxFFIEg9eeO\\/HFfRmr2Gm6nZQWiTn7RFGPm2kAMOQfqK8n+MHhyACG4mnmklyDJLjqcD07Z\\/nXXha958sjCpC0bowLm2e38Pfb4IkmS3teFcYP3gN2Mc4yM\\/WsbTUn1O\\/Sya3jgkjikYupCliWjwWIxkDd3r0nTtNS48FuJpisM8eAcHknOB+i1kQ2ejjxgkK3ENvLqFqIwfvBS0e0gLnrkD8a7KVTR+RhNa6FWafWbdUtLLU5bfT5kFtMCnmFjj5u+AMkgcVr\\/DDw1YvqkmoPciDy7eMABcDgDJYZ+8SKqaBpunQRrai4uXntJDgO6FSxYdQVPbPfitzw\\/rUaXzCWOFGYsjCOMKH9Mgd+\\/41VZXi0iYOzuWfsl5fSwWWm3MgTc6qXlkUqm5yWVQwDY4wCcUzwsYodeu7e8kxHMGSWFyG8zB5Lc8cEHHvVy8u1Tw19sspSupLM5xcOwVkLsAoHpisazGmvpscgto\\/wC0Hk3yuhICqdvzHA4GckfQDvXLa8Wn6Gy0Zk+MdTl0C7FroAs1idniw7BvLxhgOmT9\\/OD0wetXdH8RabpXh9bWTVLpLiQ\\/vZUuEiDEgAn51PuaX4h6o1hplrfrJslgy3mHHzPnlT7EZ\\/KvN4NWuruEyC0YmQkR+XM3DZ6hRyAMj8a0w9NVKK5hVZcs3Y9Q8Ma5pEiyTtZXWoS2p+V2uQNi4wAckZ4GScY59am8QX1rqHhvULu882BXbeWhuSVlXAAU46nI\\/h9epql4H0yygubuxP2i9lkso3nDL8qO4bo2AR6HHvV7VbXYRbtYS6bbCOMhQAVcggkA7sAdeufSo5Ie00ByfKeXWNjdjTNa1iCSSGK1k\\/d27xsWYHHznPzDGRj+ua9T0fxILj4eaNdSpO92Y5EKRQbwwVyoyfw6d60vElpYrHr0+nWULfaLVbyNVdQwbDAsD6EMpwOhBqDQtM0uTQLKyubmSYxxCTamWVty7ic9OcmnWlzxTa2f6BCybRxWkzXWo3Md4tvcQySysqeZapvkZTg7SQdp5GeO3avR9JmaFUfKT36KUYzkO3IG4cHGeBzXnGuGa\\/1MDwtYz2QtnMPmRquCFY7m5IwO2B1xz1r0bwZYR6barDJO9zc7mMks8Y3qzDJ4AHY1liHzRTe5dNcrdjs9Klb7AGuW2M4BYIwA6VyHxP3W0NlcRF0RgQ4OAeDkZPetczrckrM21oyADu5OOvFYPxEt3vNFVxc71jYFVCcjgjGe3\\/1q4qMbVUazfulfRILS8\\/sXUFjXz4bqRQ\\/VjlD1Pp2rtLxtunNuiLKVKEAZ\\/PivM\\/AWrIpbT5GdJY7hXRcE8FWByPbFeg6hKrW7KH+dOWUckiuPGUpKtb+u51UZpwOcsbnSrywk0+80+\\/nAiAmFvvCOD0+6wHIx14NVb3RtNsdIEpgS2nudgWGCNVEQB+6ck89sjOOaTSrrWobc2lpb2s6RBmZ5Y9644yMnp1pviXWr23guIXjW+NtLtUoxRE5wMjOPyHQds16dODla35nJJ2ua2iW88mkyJb\\/bfL8rMclzGEQkY2nfnOO4zXOabHcXF9taVHCyspZZAy5zjqOv1rP02\\/8AEscsV3qF3B\\/Z7ErNFb2K+YFweF2gseQB361h6brmrpr1zb2lukdssu8i4jdW+ZjgDAyTweMZPtWiotSkiefRM62+ksdPvNQsroo6gxsQVzvLLj\\/2WuXvNRttsNnG7WkeMDy4wZME8nABPc09ru\\/jujqGtS2zSXoRUjVcKqoTg9Sc5Peua8SeIbWx1eYyiJhhkKjBODwRj863hSvIlzsjY1m1kbxIl1FM1xAsgX5T3AH+P51qWbssskwmeOQryCOc5\\/8A1flXFTeJLZtNtorKLU7q8nYmQHiMEYIVBt4H\\/wBbrUgXxhel7kRW8PlgARNk9efr2NaTh7qUnYmL1ukdilvbG+WZrh5CAQQBt9c9eR1q7ZS3Cveiy2kb22qWzuB7DnHX1OK5yzsr\\/S\\/KfUbprs43lgwUBj97tn16nHetmzkLxgW6xjzW3EFmAIHTk479hn6151eolLuu510qV15mZpuoa\\/Z6u+t3Gj3E9luaMmFf3i4HXaevPofWt3RLnSL+xuT\\/AG5dzT7D573JKlcjBGw4wOeO3FXtZvLi7hWR5ore2j2uEjhLvwuMknjOSSOBziucXw1f3mlx3yPcpN1fcSyYx3wcHBJOMYqo1adRXehEqc4sj8RvLdWj3aSWun2kbo0TPNgcHAG1SAScE4P4Vqy3KyaEP7K1qfUbpiS6Igji4ABUgAdcAZJ6HvmqL6HpKzwrOZJpfLAjST5EwvQqvT8R+tbMFppVtaPbjENuDunaFVOCemMDPXv7Vz1cTSTUUn939M3hRna7Zy0mgiwnMV1CIw5DXMdmZAIRyFJO5uMepHUe9bUlm1\\/Dc3xmd5bWELYyIMEOigInOMkn5jgHgD1pkUUbSXMr29vKjMxjedNkki9mxjOSMVqy6tbwWypamNAgVW8pDhT0\\/PnrnvRUxT2td\\/1\\/ww44fr0My51C7uLq4iPhq4dnJdJJpI3wxUDOOeBj1zV\\/Rbi+SaZbjT9YRHyGkMyruPPqTgZx0x9KWHVIBMjTSYRHAdWyMn\\/vmugi1I5WNFhEYIxsbgjHOR1J\\/GuZ4upFWUNPmafV4t3uefX48X3F1czXFowil3RRRs4JEf8AdAYfmcisq7v9Z0bRmgjs41Ug5byfn68ndmu7vrtw8kLP5ZHzhbX5mx7\\/AC1W16d7qyUSxzOsqlEBUFmOOT7Ee9ezgpOq486SR5+IXInysk+HGlnWdMsvENogF5CcTOBgll+n1r6p8DXB1Lw3BO4+cphgfUda+Xf2e9Ui0vxRceHbptsWoJujw3AcDkf59q+pfh9aNZaa1u\\/Z2\\/nX1k5qVBW6aHzMKbhWafU1YYyjYxiqesNsXd6VryjDg1j+IuLdselc1H4rG9XYuaNciSMYNXblA4wRxXIeGr0iXyyTwa7AHfGDRNckxwfNEpzxpFHkHAxVTTb2MuYWkBxxg1Z1MFrSRRwcZFeYyapPBq20bid2CK7qUPaRZz1KnJJHfvJDZTuwx5cvJB9e9Y\\/izStK1qxeGaGMZzuIUZ+uac8w1DTuTgn9DVAOIEiaSTcrHYwpWadxSs1bofO\\/\\/CJ2UPjSeF5ImNvKVkgmTlo2OAynvjoe\\/SvKfiVoCaH4lu4UPkXMM2UTZ1X+vGK9++KSz6V4vt9Usc78beOpVsZ+teUfHYJc+L4bpWk\\/0q0Rw+QpR8EHr9DXHjoKMbo2ws3zIi+Gfio6XYzS2jR5mX97FvO4EjaWHPGQcHjnjpivUfBHhLStR0xdfvLkyXscrsmcNsbKMinncT1HuHP1r5b0u6+y6mvmswAbBK445\\/I17d8O9Sm0rVrJLi7drS6f5RI24E5GVGOh46+4ry61K6vE9aM7M9BudFuYdEkkmaPNqwlTyvmdn3ELggk8jbgHoWIz6c34WsLjTPFet2F2QYmRZj5aFVkLDO7PGTz0BHQ9siu3vdPFzp11YSW6kl0l3C42HywclQcnnAxntnNchrd3bp4oVNODwXrTK7ywO+6Y7GRVZuFTCjBBOCWzxiua100aXNHwnGizapb25Rgs7zSh4iGkbGFD5PZTxj1HtXO\\/EPT5IYZ7y0tpDI7sFJGCAB8xHoO3HrntXU6Povmrf3upfbHuChkciZWWBV6uGOOhVO\\/IP0rifEur2\\/mILa7kiQoYwkh3lCOTt79SOpB4qHG01Y0hK61MvwfefZLqFdgeNmbzlQfPtwQSPfk16FqdldXVus9raBHliaWOeUZd0C\\/MVGcjODzj+tcB4Y0lYNSguPNMgd+AwyrsCCQMdvmHBr2SKJLnTUjWRpESHyYDIV+QO+08kcgZ9ex5FS2uYqV+U4Y+Gru5iS4jso5X+WDduOQzMp3bWwOd2PTHPetb4yWEY0TT9UuXge6EXlxLEzB3PZ+vyquMAHoc+tdp4LgilEtzJN9tedvszrnbGfLOxTn7vOMY574z2T4u+GrV\\/DEOoR3qYjHklBhY8ZLLnHBwc\\/5HKi9dSW9T5r0yDDbfLRX2nJ3Z\\/L\\/69UL+5hS43IEYIMlc85\\/Diu51Cytrdn2xvebFBd1jMYXILHqMtycc9h1rzO8jlvdUmcbUklkBEKLgDpx1rphKMm2TJNIv2VwWVnDLJI7DDN\\/D1zweCc+tWLxooBFGw3PISAWXH9PpWPARBctvYBlO49tvpkVcgujdXSvGrNngKMfLkcnnr61Uo9RKT2M7WzNE4WORfPHK7W3YOenPr\\/TFUraQJdb8JOSSCz56YwDjkdz+Vad9bBpkBhP2m4IJDcDHTH15HI9T7VnT2JiYxKy+aXKYc4bbxg57f\\/XojZqzG7p3Q+yErSpG+3yGfcFXOB+XX6E10VnqUllE+2NPJVSMNJl93OO\\/Of6VzVg8CmQuhzghQCR25OMEdh3q48BuY0kiYxDZjaG4fGf14H\\/1qzq01PSWxdObitNx\\/iPVrzUttu07rGcsFLkbSRjnOB3\\/AFqhG17bzRqrSyblG1EyQe4HufUVtaTpb3Mb28iyGIKxLngHjpjr0A\\/yKvyWttFfxI1zH5nl7lVXA3ABvUjryD359KlSp01yRWw+SUvebH6RDqWswRwtbXEcLARpIkRZVxzyx7delTWltpuna\\/bxz+TGVQmYhiuW5A+UHjn8e3tV+68SafaW4stCZRedXlLARrtGMLxyffFc1ZQxx3CXmqoIY\\/PEjF5AwmOcsGKksPyrmhzyvdWXRdTeTirW1Zoa\\/d38rNYyQxzNDuVyYipVck5IJ61UjE1sYRL5ivCv3Udm5OMA54\\/L3rR027l1i4vZrqxcrIjFFRQgXqV+YgZBwf8APTrZ9IRwtvaXh0+WQiZxsGGORjI68YzkYqXV9naElYUYJtyRzU2vW0tvFPqBnuroKVkVpcKhGAoC44xzk5rBMkN1pk0UAkaS5lz5ZPyogwd2MD889zxXc6cLuS7v5AtpLIQwlUW42yL90k5yenYDBrA1XT7v7aRPY2lrGvTycllPtjtkinSnFNpfmOcbpGA2jPCv2nM8m0gozAKVJ7DB46\\/pWoi6hctaDMjLCMrDMWVG6EjI74H\\/ANetDiG5FvO0gjUDEm3AOQO\\/tnvTRfP9ris4fOZsfKgKnOM+pBB9qTrVZdLl+yprrY09T8RXVzLugSK0271X5Ccggj8Bzj6Y9KnfxTez2SW1qVhcRiOQxQJlwANoywPQrnjHYdq5S\\/ui0jxLBOshj3EbcEDpz6Z\\/rTbR1ijRTKTn5imeQDz0AyT16gDrWboe6tClOPNudHb69qcM0jqIo2kJaZvJXMmeoJOc9ScewqK+mhvJUvZLqGBozudI7UhmbGMk7vQdiBz06Vii+t1kWPY25v4mKj8+anaynku4I4ljleWPIRZQpA75BBPpxSjTad7WByixRqLLAIGVJFH8Sg9c55BJzyAat3viW6mmTckJ2KQFZRsHHHHqPXH1qOPwjqTyTPGJEdIg4B5ErHkKMn5euKy73SNSs3YXlsYRxuwytjnBII6f\\/XrTkpye9yeZroWbnUXd5njSGN3TDlQcduQPwA6dhUOm6pqK+THHKk0UX\\/LJgFXpz6fzqslvC0TNJI7OOQAcg\\/WoWiCIYyHQsuQyuAeuB9OnT+VWoxtYlt3ubUesPKqtdOIvKkwAi\\/KQQeMDqAfQikTVoV82JbZ1jLgq2T8nXt6cnism1WTzHW2iDiNMtjliAPfqaetvcvNJDM8UBB3YcbuPbH4+vSjkDmLz6sWlSX7Xbeb5hbabcqFGDgk559MYxzWH4nuIbqzkZpJGcPkIU+UZz79QPwq9p+jSahcKkbOTJuKuy8cfy6H9Kr+LLaLTpYLaKEkybZGXnC9R+JJramoqatuYzbcfI5nQ7oWbyySmWPemEZUDEN68n0z+dbsF5Y6hfmKBpWQ5OXGC3Htx2qj\\/AGdcagwgjQRqp5Y8BfritvTfCiQQSl7jrjL4ycjsB68n8q1q1aad5OzMqcKmy2R6dKyvovmSx8liWX0Bxn6nk1SvNPKwM0bv5kDpv8qQgbioOOPT\\/OKo+GPEUFzfJp18VUQOmVzncVHIz35xx7+1dythCliZLyQkXEjyKNu3y+vBweeuK8+relHU6oNSkaHhy6nuozZXk87YJBWQ\\/eA756Efh2qHxfoWi39nLaIrW12IWkFxFhXAzjr34A\\/CnWNpMbKCS1heFfI3earhtxIBPBwetQLFNLql\\/c30ZjtrSFQXyQzEDOODyOvtXBd8+jNuXQraIps7C2trvBiijZ\\/MJ3b1UuPm9z1\\/GrayRTxia0tPtFyNm8BcYwCQCfpg49xntXPf2pbSFoLmeIYjVEQsw4I57HnJIGeOO9dCs7waTBcyCOIxlyEj3DGc4Jzzk12OPfcxT+4fpT3E0UtzdworRjPzEcdzggdB0\\/D2rzyw8ZW+qeNbu1lso0jjnZYSMknCMpzx3ArvLa4a60+4EsEkbSlYpQrMSW7t1wOvTiuD0bQX0zxbbXVwsohklwZHH3lYHnI\\/D86mlyOpLm36Dnzci5T0vWPD8Z0SOfHluFB2qgwzH\\/8AWayrnSpI7NY02kSBgHB6ZPT9TW54y1iHwxY2UU1q1wl5cIhmGNqZONxPQ96z\\/EGqzHQ55tOj814sp5Sfe3Y6Ade46VlF1Jba3ZXup2ZB4X\\/5Bk63EymU7g2OgOP6V53pdgf+EpkYy5SVnUx+oGOeB7Hn3rai+3W+m27Xss8DzGRmVjskd2YZ42jAAHB6iqfg4SNdah5iqgjuNkTuAzn5SxyfTLCuulB0+aV9zKclKyNDxD4buL3yr2Kd7eBgBIsbnDDIIyO\\/FdP4W0Ga400i7zNC4VUlQjzGGOnPA7+tPEkf\\/COWrI24yZdj6KOuK6PQD9k8OwxNho3iaQJu56f\\/AF6dVuyFHcwdYht7RrWwt7Py4zKPkznIA5JI65NZmraoLcSFFKOMd8AZPb8K0JdSgk1qSRnEcSRKOu4A8HGfxrlNclWS+kninMgeNipB4XHA+v8A9eqproEmbNlHNdXD3k27yihyHb5cYHOfXg1yWoSQ3fi8QWki3D26sZZU5RScADPT16ehrotJvhFoNy9wGKOcRgLljnoPyHSuWtif7KkuoG8mWe9BePaUby+FC8dOAD+NbwWt2Q9rDtP059M1a51ETM8UrLbhi33mGcn3AJI\\/CvTvh8WlWbeylRhjjhjwvfrXnviTUI77Qoks7XcY5UMhH\\/LDb83IyCRhfw\\/GrPg3WZtNt1vbnbGs52SxhyDGf6+nPpWWLi5033HT0kem+IjZza1Yu8amRYpBuyeMlc9+vArxz48WcS21vdJE7vhk3nlQDjv68ius1jXku7\\/Shp0pkd5SGO0hSpHTP1APvVf4jz2cnw+vzIm+SM79rfwvng9Pf\\/PWuag3FwZtNbo5HSrIWfgjRpYUQXCgzIsjAZBAYkNgkdeDXqej3t9J4ctWCyJNKql41UMqhhyp9ccc9eK8yGo6afh9o17c20l3cJB5UCKSEiKgAu4wcgHHBGPrXtMWrW2naLZwXLokpgVWd492cAZz\\/nvXXXvt5mEErXOM8bae76fpu9w0ct7FHIUkzgbgQBwABgfoK88+KejxafqsMdjp8IW8KA7m75PGPfPX\\/ZrvdduJdSt9PkRglqdQVbZF4ycgk47DNZvxbihc2CzqTIsqbdpwCRx+I5rmpTcKsVfubyjzQZv6Pplvf+EzpN7JCwuHWERIV8wYAHAOM469+lcH4q8DxRapALC5aO2e5WAWsaFmUEYHJ5JzjI7Zr1azs4V0ceVH5b213GwkY\\/Lscru6dOM1J4ps4bfw+mtNA3mWzidVIwxwwPGPXFQq0ozuurDlTVjl\\/C+jWll4duGtCjXEa+YyhSBtGVBOQMnbtOfr6Vk6Vo+mz6NqUerafLHbicJthXeYmPzB8DnHJzjnmu11mO6\\/4R9pNOlCmzgit5TIoLtyCysD396yfDUVhceFhBeTRnUE2TSf6ScuzKAwYZ6dB\\/hirpzbu+7JkkrHk95o\\/wBgtw0804gmeSKPCFSNp+UsWHRh0HXkH1r1u0tzPoJlj3qZgEEagFFdRtbHoGC5HbiptdsdNsdFsxKtu7zo4xG25ZMY3EEnHYkZ9ao6vqd1pegC2tHiuZzGqxtDyHcgKoA4PU1rNuWnmJNJ3K\\/hKA6vrWqKbaTTYLCAN9nmuNu8FWB3bRwDjOPx+ud4Tjku9Rm2amLm+ZC0GWH7qFRhcj0yCOTkjbTLqHXY9cSOCS1EAQQartQSRyEqzMvGG3Yz06dzWdrt2g1LUtSso7Ux2Dh49sxyJHB5KsMbQF9sY4HNaqLat3IvrczdM8LaZrGtX01pcEtKV48ksEkwS0Z2kFTkAfTPTNamieCNXtL28m8N6jCsyoJ3leMtnnlFUE8blPJ5p\\/w1lWbT7u4nlSXVbi\\/3wqzBUlk2tuJDY4+YZwex78VpeAfFKaNJqUV1pkcC2MLxyFZlKyMGHygnAOScY6Cio56pMIpb2PODc6zZRawYLxInuYRdy3BLKWkWU8x4+6QTjvkc8cVR119V8PT29vqUR+0JIZxNu3LMr8sGU5B6Ac16Jqps\\/E8c2rXVjFpllGY7bfG+1E3sF2tjGD8uCBkDgnNcwdMtPFfi\\/VUln+zJbqTbTMueC+ApBxnljz14Fa0590ROPYiS8XX9ds5IprhrKOWOSNAAm1VYKTnBOeBz9elex6fo2g2iR2g0i3+xgjYyv5hbJByWbnccrnv6cV5n4H8GPqdrqPlW6TSQ2kkVqwdgjSK67nXODnacYPGT2HNepaU2i6LBpNrr97bw3EMS24unmAKsOCEBwBk53H3xmuLHJtWi9jfDtJ3ZSGoaqZrXT9K8MSbbaRiLgkBFAO1sseecH5SM96zPE1q9hpqQm1i+xuji8igux5gkyGG0dSRzwT83vxXpFxdabe20OrW0irFOvlS+VKAHYn5SOvOM8+9cprunHxFqFtBNLLb3ttO6zFsruRVJ3DaNpGcHrnt3NctGV2lbQ2ntc5Gx0X+3Z4oLRpV0y3tVCYYRzFWyVXcAcHbz6HpkiuT1jw9fabel1jmiVZfL2QMNuR\\/Ey5JUkdj9a7C98NQ6S+rajp2uXdrdwp9oggGGR42PBKgAAbuw6VxXiLxJrus2cdtqdx9n1KNP3ruFijkizxntu9x1yK64Rqc\\/uW5evf8A4Jk5x5fe3OitNXS7h8mK4gDK2FM43Z68Dd1x7fnSLbWzOJFd4iSWfZhEB+nTH07fSsWLSdPfSrbVNL1S+gkWRYTFcqFLMwy4jPOVU9+frW7\\/AMIzZ6tofm2U9w+o23\\/H5E8wdsY5woP0x\\/nGE8LGDunY3jiOZaowvEEdxDdRmxFveQhCWJ4WPnqR36981LY6xpKMvmWEd5ejrIFyDg8lcD2qnqlne6Tq7QQ2V5LCygxQsQWJ7YwDz69qo+JdTeOZEj01oWWIeYr\\/ADeWeg\\/H2Pv0rpjQUoqL189jJ1eVto7EajFDeKtraSqCRJKpG07j2OFO7HfNMhnuprS4864Bjc7QVwAq+nHp6e3pXIWs18LpRZPcTyRttMbgDacE5IBPoc5xXS2cxNp9luIY96DO5XwxJ7LxjJ9qwqYVQ2\\/4JrGs5blnxZ4g8SxaXbxXeo2wWYfu7SAuqlcYPRAOMjqTUGjW1xq9kFe8vEUMu2LbleMDq3A4PWt2Lw9CXL22l\\/b7xyVuFIwsnPBDLyO394DFZsieJ4tLIWH7C1rCJQUYEgFuMnnI6ivQTXLpoeb1GWASxvHH2eJEWVVM80g\\/eEHIxgDn2967+4YahHBdaqx8j7SwiH3Qc\\/MrHOMAYZeT+FcNbrqF5LCoZWAVZkgk\\/eq2OvHUHJ7kVFfeJnstOltZxOT5p8+JgrFO3BJOPYc\\/WspUnNp9S1NK6Ol17S7rU75be20oyW2xUtw4jCh8nLZ3A4A9Mnr6Ve+Huni1uNUt4wHImUtl95+6eep7j1rjfD13dNdWstpcymFHUOkoztyDtOQeMnivRPB17cXXju7luIIbf7REjCNHJY4BG7PQj8fWsa8XCDV9P+CXB3kmdLOq3WnWX2dsSeYN46cH3\\/E1hfE\\/TY20qZmi3oiBgVGCo5H9K6JIVRndlCPbswGBjvkfpWJ4nnkudUuLEyx\\/ZDaiSQE89QFH4kn8q5KcmppmklozndIltl8IaS1xcRhZbpUWATBHZMhegIJB5J+ho+IWmWJ13R9RjQJHBgERLtDglCoPtwagtdZ0QWltpYubczxoLaS3lYKyPuwPL3HkknsD9OhpviW50TSNNvZ9Rv5hNHJ5lvBskdWIBwgyAOy9D+Xb0U2paLv+JzNJoqS6aLDxTqUaW4mRolmijjbaq5I4P5fr0rmr5pNG1SSd9ilZfM2D5upwR+XNQajr6\\/2yutaBDPdW7qEuYpA++IfeG3LEAfnz9ai8Sa\\/p2tNmCSRZZY2DJKArBsdPQ9fWu+nd6M55KwvivXT9r8lI5BHP8yusJKgnnHHUj+tLbavc6LNHciaFxMgItTGVZcEAZX6c9f61D4c8RWUWjzabcRiS5il3rK6+YBg9FUEdsfpnpV6fS9OmskmctdNNM0lsxmAEEeFbbwME8t+dTZL3WitXqbNtcvqcN7b3unLcTOokSCZ4yp4xwASBgEnJ5+pqKx0e5NlZzPotlZQrE6lYFLl\\/lyWyi5BGR19fzj060F7e28MKxLmUxiWEKGk5IPXkjr1xxWxb6Etlp5niMJu\\/mttykIFTIznGRyAD17HrWFN8t+mppNbdTorJrWx8y\\/fUJXjleNBlOB8vA57c\\/wCeazr6Y3ltKkpDJGQct6g98CuA1TVb37UbS0lFwsPz7jJhcRn5SR0wTjjPvitqO\\/a5hu5kuWeV1HyhjtjI5JCqM846c0nT5ZX7gneJ0C3sLy21vuEqNpsluVQ4IPb69PU1R8No2nLcanqTuirAIYYgSM7E257dduePxrzj\\/hLJra7dQks\\/kMVfZESAD2yQCDk45rqLvV4L7SrOzgeB7iZ\\/M+V0YxAg8HBJzxyB681rKFtHsR6GtZajpun6fFMtk97LHmRZHwGDsQSRwcDJPNaf\\/CY2Wk6Tf3LweZLbuD5UMG0NIy5A4J5OBk9s+xrB\\/s8NNHJFZKJgm0ySExk4bP8ADkDPpUlnpeqJb3NzLrlkI5JPNe2lhd3kdcgnIYZPQcn9RXHKpRa3\\/E6PZ1Oxc8M6\\/eRaPbX+rOxl1OZ3jds7Q2PuADthR1\\/nXTJPp+qaTJtuGLMpQq0+7afpnpxXI+LYNY8TWFr9puLS1s+FlS2hdWAOeiF8dO\\/vz0FV9I8FafcaebNdV1FIVb542lf5xjngHb1HeslKm1eTs79C3GWyWhTtkabxPHLZO6SW4YsqD72CMA8YyeeP5V6BpOs6cvn27PcQ3tw\\/zJOBgHHTcMcfgK4U6VZeGbtI7drnbuwv2hssx747Y4\\/Cr7z6driq0m1l3El2HBxjj0Pb2rmxNRyqXs+U6aVNKFuprTa1psaz\\/bJzavISdhVmV9vTOASenqelcd4k8QfaEuLrGq3SySjiO2EcbqMHHY49yOw49e30DWNJiWbTZhbShHWRmMQ2HnAX0J\\/PpV3SprGSdoJ3s47ds\\/MYiu7bzhQMcZP8q0hUdOPNyv8Ar5GcoRlK1zhvDHibxJdXj\\/YNHW1gZgTJN85QA5wAB1xVbXrHWL+\\/uL6\\/tmuZrobUJkaCOJV+6Ci9epOPeu+1Ge2tbloLCIQcYQICEDHJx054781ymoNqQeW4gbcF+Yo7AnGMkgnAI4ro9rOb5opIzVOnHRsxIvAk9zp6Rm9i85lKuhiZmIyD3zjHtg+9S23gu300LmxsjMg+eSUO+444IHH1705NVulvDJco8jFAxKyqynPPBH\\/6+amm8W28m0TyzQIDtUhOIhzk5549hz9Kxm8a5cvQ2isOlfqSG0s4mjkSPzJon3qiqNqk8cA\\/hyaht7yO+ujCbyWIHJY7CVGOpz3+mfWqdw++VJDJFdvKpYmIFRCo5B\\/2mOTxyR61RMlncwPeENArYLuzNKXwepHOATkDnt9K6PqspR956\\/kY+3jF6LQ121zS7XzbOW5kdwnzMMkAfTnr\\/Wq8PiKK3BmuJBub5Qpcl1B6HgZGR2rEktPtcUzQGJIlzkqnVgM84GR1\\/lUUlldzTx+V5LCIFWmCBQW6dCBntz160fUaK0b33H9ZnukdLN4hQbYZGup\\/NOR5bHdj3BwMDjvVy18UNYpAPtDq8hBjORjOCSB6n\\/PeuSMb2tiBPOPtagGMS5wwJ\\/EnvwKyLyZnt4zBHG7zOFDCIkgZ\\/hz6kD86ccDT6CeKl1Ow1jWZLpjdfMynCFpeAn1x0A565FWPD99HepLdXMl00cHzYjkGwtxyQQTnkYx0rmnhlncJBvmUoNy5xwDxkZ9c9\\/X3qvNqcFrAqW6kSRscxMcYY\\/xD0A9Dnpn2pywcZQ5YrXuCxDUrvY7jWdbe6c\\/2fAzufljlmjIKjGeWPpWV4ZumuY3jSO5mkZ23CFAVHXPXuBzx+NctYXV5eW0hkm2qz5YK2cDvgZ571t6fLBbXEsematJHHMgGSmVxwSMgkjJ7YqfqcKVPkSGsRKc+Yv2l1MmtPbSQP5qsT0UgE56gYFdCP7TSJHa6SNY1+dNoBB\\/AHH6muc02DTrp0KXE6zeUwf8AdcA5\\/vHvz6+lNGj6fZSqDqUlvOo3eYrE8nt0\\/wDrmn7OnKVmtvITnOKvf8TrdJu7C3hZ1dTPINrhkwo9ee5+tS+Kdfs2e205o4HbbvdipAT0FYsC2sFnGlxdyrI7YG3Azzx1GMVc17TzbC3CqyxEh1yMuW\\/2utOnCEcRG7fWxFRylTdtupwF9f3th4y+1QF7W5tplK7SMkDuMcYx3r7r+E3ieLxN4U0\\/VY9oaaHEgHZ1OGr4p8X6bFpl7FqESs0M0m2be2cMeR9PpX0b+ylerJoV3o6bQ9vIJ0wcblbOePbHXvX0FOfvuL6r8jwqrtJJnvTtkA1meIE3Wpx6VeGdn41Bqa7rU\\/StI6SJnrE5rw9YE3jSMxA7Cu0iQrHg1zenSiKRuB0610sEomtVcYPFViE73CjZKxSuzjNeY+I7TyNcd9vytz1xXpd\\/3rgfH6lYluF9MGuvBy6HLi1pc2PDMlpJbxxRncxXawPcipfGGlQ22nmePIYjdgdK4Twhrf2O\\/Uu\\/yhwcexr0TxdMLrS5ApzgBh9DV1ItVF2CElKmzxnx7avqdpbyocMON3oR3ri\\/2g9B00eE9K1Cz3\\/aBH5dx5fUrgZPJ55\\/nXsUFjHLp7WzrvLfMpA5B+teR\\/GnS7uHSore4Z1jeNtmU4PTj68Vliop02TSbjJep8y6lDFHODCzsDzgrgiut8G3921mhWUytHLlvMIJxkdMnrz+FYVysDRz7Y0DE7QvA2470vgkSvrSQxtECwO3zJdig9OvrXjwd1ZntxZ9d2EF3rHhux1OFZJllUxzEIAoC4BzwMD5PT155rBk0bQ7ttSlutXuLPyWDSRRIyK0hYFWAJAbG5ST9Qa4jwFrr6NI1rd3km15kCqhJCkkh8\\/kvp+NdnHHDqHiuysbK3W7e5CvC0sgWI\\/KoY4J5UBedoznHpXFOLi2jdO+p3Qln0TRDPplh9rXy0ill37pJCRj5gDtUcA+n4181+IJLyz1\\/ULeazdIJZWuERfuqGP8IwM43dOOMV9ParpF\\/pPhp2vb+1s2CK8rxAsisMFQAQPQDHvxivAviP5k+o2F1CTJfzwSi6MSECJggJHzHOAdwwSTxnGamk1qir9RfBM87Nb\\/AGqSMxQb9kZkBIB2enfgDHFenXF7b3enx2hS4trGcvDKHk2B0UZUoQDtJJB79D1FeO\\/D7zWkNoxPlhXLFiFIzg\\/lx+tdldXUOqWMAHmblRVVGXKKUYhhjrkj\\/PpjKK9ozZt8h6V4Ptb+PSJ7Kwhe3Ec6rCJ1DhJd2c7R26nH0+tdR8R7C5u\\/BVwsrIZIolnWNAyKSvYA9QeeCO\\/tWT4SvtmpKuoQLJutowojddo8sqDk8EtxySAPpXS+I5o7nStRyzeWUMaq6EYPHOSMEdTnpUt2buZ9rHztqmnW8mlXmoEFXgRmW2XacMy98dcEgYPTn1rxIyMWd+FZiS7sQT14AAr3TX7nU5oLiGK3sBb2uUMgQoXGQMdSpJIHI64Bryi9s40hcxAjG4qCvPU9T\\/nrW2H0umOoznbW5mjlJbJ3\\/IxPQgCtCGPiNlR8s204PQHIrOgdlZlkUnbkbSPwrpNARAN7xCQRgP5bKCGOenWuqdkrmUdXYr3khnuU3ljscqzMmeTjJ4OemD+HWqvmXttevdCAeZHIU+foeBkZGOgx\\/kV0ujQpLcSXgtzBHvkyNvGCVI+XnOefbn61h6zqMVzHIVBUNJuUx5CMMnJ6EjOccelcsXd8tjeWiuYuEm8pGmV5iPlKkng9BzXTWVtp9rp0FzI7JMJFxGBnu27PTP09x9azdNW3inwzuWDBdm3hQOucY9AMDrXW6c8FzJFHHbrdkBpURQYySSCvbI7\\/AForTtoh049xZ9YitdBnFnZu9zJw7yKAM4OQo+hH5iuIjsbX7SzTb4CY2kVW4IzjkEfjxW7rsm6+lgl85LUuRmEbiJAoXqTwTt9eM496pQxXcOoeeLa4aCJMtsBRgP73J79cfrUUYqCbXUqo+Z69Df0bwgJITf3UtuLZy2Nh2716gggg\\/THGBVm20eCe7\\/s+C3SG13by6yFt5254BGN2AM4zx9eLOlWl7Jolu6q5dNpVpSHiPA4ADcjGQfc1t+GZJgXtr3SWSRTiQxtuXnPOMAjn0z3xXHVqzV3e5tGMdFY5W+iSInTZ3nhWNhh1YsSRyQeefr+Iq82tvea1DaJGfsCo0SuDgyYAJ5HPXjPerdxZm71G5dIJJWaRd54bgEcgjHYVJdaMYZLOcrDJDEWUmPClSQcdqzlODspblqL6G\\/Z6ZYWlo9ybqASyAhQp\\/wBZxjODn6VheJlW4njEtjmQAFlEXbOTgg856\\/41YtLO4nkleyvyFC7XEignB\\/hHY1Y13TLlbGK5uoDFJD86JDIVjkPqcgk5z2681jTfLP3nqXLVaIzb7QwLr7TdWjWOnrCsYihkwxZgNhyCMFuvrxk4pt74Yt\\/7Nsr+Zo0miu0O7y1zKDggv1bgDoDXY6dpy2ltNeGTerS4RCPugRqoGT\\/ngVl3t3fnWbfT57X7VGs\\/mgpuBUjIGOMEgY7\\/AKVcK83K0XoiJQVgtvD1pqViby7E0MkwASaN2AwcBcKTjqO4PXvXO+PvDNto0EE+lw3BVY1SYtIMMcFizAnjg\\/p0rrbLV2tvC0xls5WaG7UMnKkYVMgMR3+YVkePbtb+xd7a7QR5AaIgrv4APzcjHOB256mnSlUVRa6EyUeXzPOIwsmtIIFaOybrkbg2c4ZSDjPHt713lr4Timvov3khOEPzScvxg4646Zz7cY4rlo5Y7Wwjisms5AJEMsy\\/fPHG3J+YY7iuz00T219axW9pO6xnMs7fedtpBJBwSOc5H8q68RJpe7oZ0l3NqxWGzvDEsUoi2smJDv54wQeuCV6k9+1UrzS459Wk+0Z+zyLgxA84J6Vdnlh05o7u8vFLzEhsuVBBzz8wGBgdB61yniLURa3ZW1u3ZphlJHGAGOeAQPw6\\/wAq86ClKXunS2ktRniHwyQyTwSspkmKu03AUHnjGMfT0rlrqO2sL7ZLJbTYJUshDA447Gujvku7N3srjU5TK1v567IsoGIORuwQRhfbr1rI1BLK40uObbA7zkeTMjHceDkFcdj3rupRfVmMpJbGcHdpomgLll+dFjUptA+hzWvNpGtfa5bpAbuCGMOsqsNpIXgdT0BxWXfwsJvI8tDK\\/wB1VbcqenOef1rtvAouba1n0+SRvJaHeG28EkNlR+VOcmo8yH1sZuiXETPPOkzBnQO4fH3uhOa43xxq9td3axxeWJGC5bA\\/DBB\\/zzWtqZTRb25DRs9uIpGhRv4c4J7evFcJp+3UdRtvNQGRXG9QNoKjHHvwDXXRpq7qHNUm\\/hO88M2psYlQSQt5igHCjt7+vNad7GGlRVieQnnHQ\\/jntSGa2jEciwRmfoqDACE\\/T8ataa0I06VtQeOOcuuP3pBGSewryKs23ztHoQppR5UYkMcqa\\/ayvCfs0T7p\\/JQdgcfXHX8K9Y+3aTqVnEqXQRXBwp+TOR6HGPWvM3u7B4Vh3\\/NlslTwDn3qw+sajcBLdb1oEjAVSuAFxWkpOcUmrWM1S5W2nuex2F6q6XBGAFxFtjJA5OOe\\/tWL4nvrRLO6tnvBK1ztLovIA6YH\\/wBfivLrvVLhr0RzXFwjt92QDJc\\/57DiqKX1xHqQspZ3LlvlVVy7ZOQATx+lZ0qHvXE5q1pehv32magmqje8aRs6ENvV3bHPDA7f\\/r13eumSa0t9rhCyhm2gAHA4579K81826jDTbYorqGYyqG4kY5wR7YOCAfTp1rp5odQ1XQTbR601pchQ0pjAdmxgdTghuOwP1rrvZ3kzNx7Grp2s2tjFKjh5J52+ZY\\/mKqAfmx78Cs21unuTbzaotraqIF+zxmTcWwfvD0B68+9cosB8JWuoX8LS6nfXUISF5AW\\/2iTz+nt7V0GhWmn+JtPsI9Xk8i9Fqo\\/dsAYRjIJH59ahUlzOotv66Bz2Sgz0aHULHWtKMF3GrrFEShkGdpHQj1+tYSrEI7hnOIny8E6HKlxgA9OmcDg9gT1qpp99FZPYWUM4nPlhecklVGC3p17kgZNUPDn2m+1C5MbLCscrkqzghiD0Hp1HHqaunBQbaJldpHP+JI74medpTaOzsCDN5nygnpnoT6DpVXwRPEmo6kAwHzRqrE8HIX8+RW545jinSJi1q8iF\\/wB1FIWYY5bOQOOvNeeyzTxzyXVikexTksvRsc8+tXCfMnFhKNrM9qEpj8K2A8rcVDKoOfzx6e1dJpwa5s18hoZGhj8sg9UJx\\/nNchZ30mo+FdFlBj3tApdckckc49e3HSut8D20YvbmQIvmkguynHmA8jd24FZ1rpIUTl20dZLuf7bIJVIZmUPu53YyQevasfT4LC3uZXmtyFOY4kGcEA8nkn6fhXa61p0Vvfz3yyuFlUq0DnOPdfXp0rlNUtrfTZoEWB5A6FpMPh2zyTnnHJIrWnK7JlsZWu6tK48iGCGNRKMbVxhdw4z\\/AFqdIp08P2kzWUDy\\/u3Mi53cc\\/N68461y\\/iK8eRzLHGyLETGCvAL4yRu74xziuyCuUs1USXMzbDgKQANyg+nqa6E0yWmiZ4bXS7LVbidIzG8YdQCMEkEfj1rBsvCUE\\/h37ff3bvM7NP5IIMIBBbnj6Djua6fXtHj1LS7u3kgWaRRvSMsRh8EjOOvUnj2q9pWkyJpUGn3ORaJEEKk4PCkFs5JJ+YcHOKyqOy3Kjuc\\/LqdrrVnpnlvFDaWJWWB42IQMAAAw7AHPHFVvHWo6feWDWce9oLpTH5sI8xNwA49ATyP\\/r1vS6PpkV+8ctlGkIVXjhGAoAx1ABBOcdc\\/nXOfEKDUXaGXTpbe3tII9ywJGCFKnGT0PQk5B7VFNRlZlSbV0ZXg2JLbw3e2DxI0rIiqw5yAc456cjp713P2q21PUVWZTJG0AbZjvj7pP1FP+Fuk2114Og1a9Zp551cEsMBgGIyM\\/StC802G3itZLGaSGVW8plIyjHGe\\/pg+mfXmtKurZnDYzdT05FNijo58g7o4yM4bGc+1Z2p6c3iOJ1nuNkmnjznGwlmIYYAP4HJ\\/SnTa1Kly32xFhKKhVyww4YfeXj7vbrnJ6Y5rKi1JEvLs7yYpQv3f4vmUcfr+dczg42tudCd0dFeaxpttbX+nvqUgmvGjYNtP7sDG5T6njtkc1p+PtRtpPC082lXcNwggDgudqZ3Lgkjp3\\/KsOOz0VLlrrXJbVooYl2GXGC67sY3EjOyuL8VeLtP1GCKySK9udJglVHeL\\/VKmQMKD1OD2FCo8zViHNRPU7rUdP03wvBPrF4t1LcAOzMcgvyCQMdOP0968p1vWotY8fCCSzivdMMaKiYXDMDkHJ9zj8q9N17Q9J1rw7bQ27RwpHDut2DHaq9SxAIyfrXA6poU3h2ZtSsvKn8kZjUj93NgH5Qckgjr35+vF0oxT5hSbasb174YsdesrWTT0ktrK2JOyOVgBISGwqdMbiDx3+lYV\\/e6noOrzahvSRoT5sduw+4p9PUjJ6967LwXrOlnw+dQvDCo3EqikM8bNgL0PU+vAGas2+kafqUIuL0pdXCo21Y3JVB1IGSdxBGN3f6URk4t32BpNI88svEEVzaX0vmiOS82gWzqfmZvk2k44I4PB9DWV4wsrbT7+dYri6jItbV\\/JhU4uMkrzjIGDt5OM9M816Bqfg2\\/vPEsmr2oQReYv7plAd2CkH5icAew\\/TmrfjaXStP0mRZoLS2hn+zhJPlMm5ZFbB7nPPp06Vt7TVJInlWrOf+E95baf4Xvo7Q5nieRDaTjZJEzFf4sEYIXp7VnanpX9o6rqlxDZWNokv3miJJZMnbgZAyWGSx9MVo6W0eopdS6QZNTDNvleLll4GEIHQjk9uv5r4OaK81G9tL90jiWGMeRMPJkXhsr8wx1\\/pT5tG+ordEcjYaTcC2+xSXSXEU6tJc26KSNsYLZJByCPXB68EmqGgaWs1tBqEFzf2TAvGY4zu2nG5eepGSck9zXdxWPhfT\\/F+nWGlXEs87QztIVZoxIGUbEJBGAeeP8AGvL\\/ABpFf6NdrDFPNaFcARxSMO3JJznr65opTdR2i7XCS5VeSuekeCtF1Oy0ibX7i6uC81kJXMOXKOxAJZMZyQDyM8Dqe2jpn2jW9AtZb2Rbhj5igD5z5gY7i2Rn+EcmtbwZp+rap8KwNTvrlpIlt3WINtwqEMFJGCcjg5Ned+CNRN5JrOnzXLW7XcziGLeVGwt1A69Aw6nrzUSTnzq+w4tJRZJ4b8cX\\/hLxG1tPMz6PPKdsMqlkZ1wN\\/PKj3Bx0r3PUfEVnqmnNd6N5WoAAGQxuMJ0yDz6cnNfON5oFxrTPNevK629qWi+6C3JPQdgOc45xXd\\/Czwxq1poV1dW+tT6Zay4FzsUFm2A5K5BK8EdMHke1FalSl797NBCU4u1tGWfF0c6anb6puAETb0tpYUcMQVXHIyoIb6DjB5rC8aaxFaXi6vBbodZkRFmeFTtidwQ25T2OQB9BzV2O0vbGRo9VbWb+wFwxguFdeY3wMMW5XkdcH6irGr+EbjUL65sBfWy6fLGrzESbpI9uGyDnJwABjpnkY5p01HTW4Tb10LOmG28b6LPaWsrWQtL7yjJEo2FQcq20nqcZP8qn0qTUdOie6\\/4R+C7in4uBYsYmt3UhQ21mII+bqevoRWfc3Wm+Dhe2ksEkTfZ0mtjGuXd8bcfgAevHNaHw6TULO8my3mSyOska3EbrLGJIwrMoxg9TkDI5znsYqwTT00HBtW7mT8SPExZ4ra3C2d9HcncWQ7kXHBUY6EHr2rgL27upLwSTy21yyZLK6lUz3yDwe39K9L1G1t726S21HzoLmASma9VfMA\\/ujIxzjaMEY681wOpXeo2V8bW\\/s\\/7ZtZX8wJMNjqW4GHXGBwOOlOg42slqOo2vQxIjPaxpdW95LFuJYMc4YE8sTnuTjp2rS02+Z7qNZrq48oEAvGwUq2DnhuST\\/Wum+w6Vr8WnaWt15VskixxMMBbfC7nWQt1YE7Rgj7o696eu+F76zlkYTwrbhss5GTGu4c4IJyByea3dSLdno2RGLtdHoGnS6XceIPt5bTbcGLKyZwUx6hTjv3Nc1f6oRDqLO1uts5ktreWDEjzhXwOnzBRjqQePTNYGqx2UqK0xZipI8s3BiUntgLjOOaWG43iNYi0KEY80N0HsTk0uePREKm76sXw9ClsrtEoglkZZGSI4dACCyggjIOB36mr9ktpFbyg200t7LM7GMsCTFnKjj+LAAzz3qC3RWBVZleUL87kHIBPHIPNXVtooisRRIoiuUTo31POazlXs9TRUV0HLr9ndWwtoofsV9k8bD8oVvlznjtjoK7TwlrFkPFkJjuIvL8sqJCSMsCOOc8jnOPX61w9t9jgsrl42EiOCN7klc9hn0yeBzWdFdrbX6yPPBtJYPHswCegC8c9\\/zqJWqpxSsVGHJZtn0ddJp2oKC86LJtLgLvBP1I61yWopdafPHG0NuumzMimWZvmXHJA7nOOhPFeb\\/wBr3fMsWtSxO8ajEx24x2Xp6Dn2rUbXEbTopLm7muZ4lDEtJhBxgjjOcj61k8Ny21uOM7ncwWfh3WtPS6mi08XlmgaMlCDuBPOAOeMdvWuf8RappMFqWv2EkMS7g8ABA3DAyoPHB9O\\/aoB\\/Y8mjG9k02G4keJcNEkW48d9xznnrjv1rA+wX93pFveW+nx29ugIjtyA0kiqMA45xx65z7AVvRSi7sznFvS5Rkk\\/4R\\/T49SjimubmaYiASOfLKspBK4U4IBOfp0HFc9eaMPEcrXDW\\/wBhnkYE4fj\\/AHiW\\/H07V6FFBq8p8r+z0cRgMsTDYVHTuvFammaZajTPtctvaFfMI80IGwwyMMTwADxnvWqnKPqTKEPU858PabbaQklql\\/LMHZWdQBhiDnHIPOccfpWvaWdhcr9nurNbiVMjyrh2LqT19AOvQY71Y164uLeaa2jubSSAS5jliTYMleBhfvHg\\/nWXA2q7LWWaQojkhBvUM5HBXBBx\\/wB81lUjUqL3ZfiaRcI7oWbSPDtiG8zTCkwXepiDNgD0K8g\\/jWxb+JRJCRcXYIZshDIAc\\/Rs8iuaudZubwqtyZ4IjIy7BhTgY68jr9KvaZbWst5vvppookyTOWAVsrwAR2BH+c1Lw8pK1SWvqNVIp3gtB2rzT3motO8cnmyrucpKdrc9TubHbsO1N0a\\/SxklVogzY\\/1s\\/O88jggfpmprmx1qS7tbK2nnNvesux3UsMnjgt25qhrqatp99\\/ZaSi3UShXQOAGUZ6g4PX26muinRlblkzKdWN7pFq2vIIsLJYx2oQHaq25JLE9cDoali1dbEm4+zM0ssQRmkTaDj0wSazNStbi0gaW1niW4yN0KspH1BXrjPX86rafdywReTfvDKXKo3TKZxyMd\\/wAqcsHCcXGWzEsRKLujYg8U3l3PEnkKI1Y+WUABI+h\\/EVsvcxX1vuuItjgHCx5Eg9M888+n51xrWwhhMyzwhLsMY4sgsqjkDj8Dn+dXdP12CwkCPHFPHDCSyq53Ljp9DXLWwEIq9FWaN6eJlL+IzvrfVGsrFLDzTslAYxj5h29T7Dms2TXrrPkgq8A6IyDj3z1zVLSda07VpFZI2RPuBWHOexz+PtVbxEr2cEjaYj+ZgnDDO05HoMHr+nSuCEZ+05JaNnS3Dk5lsW5tQcxO93c2wAB4ZCykAjjp1PqMH3rIuNNXULlxBA9mo37YsKTj+Fsj+HI55rIXS78pJfaur+SEPAm4LHjpkY+lRJeKt41vDdrZQOoJIBZs8jaFHOcHkHj+vr4WmknZ3OGvNvpY2YHms7S62SQTyKEYx26KyqnOc+hOcc\\/pW5omruNatoJY3tfKtkLYZQGkClWzjtyPauY1W+1GSBorK2Mcdw6KsEjjJxxkHAOPl6e9VvD9tqq3UkM0qrK7FnczE8nIAGPTqSeRW1aEZRbkY0200keoXF\\/aXupQoLS3kbZh24CqR0GcnBJ\\/zxWHq1zZWmm6k15+9lGAkZIAGc4GRxnA\\/SsIJqUOohn1NpI4mLGIs+3cVxwSD0+tadrcwyTGAXJL3LZ4IxkgZBPXoMcfTjNcsYKL913Rs2+pyy3EM14t\\/Pbyxx+WEjy4wBjsOc1eENs9iGuIYzvbenmAKAM\\/ewCST9amTQtKe\\/u5ZipWJQI1ikYRqWJyACfvYOO\\/JIx6U9Lk046kYb2VvKThQDgcEg56Z\\/KuxWexje2hk68TLcwmQ4cFiERSBIAMgjA6Zx270QQXMEAtYS6zGMhgsyqFAGSP14zzmtnVtTNy1ubO1a2gjDr5oQNnkdx36VzV0y3t7I089z5IO6IKpZZDjv78VdrIm92aba3d2cwjWONtybY0dldgD7r+PuM02z1q3srjz7jQ0mnZvlLSEBfYBsnvWQk9vA8qwwTLIVyGZyFxjkngn9efamjzIVWSVw7Dn5udxJ6YIrN0ISvfr6\\/5lqrJbHQarrEF9bxy22nOtyMifd8wcZyAAvT8v0pkccVw+nyahA2YpBIUVyDJgZCcjHGOw74qjIl6ZI7a2KKzsGYZAGB\\/vdfpnmpbmSaPW7UlFxISz\\/LsU45+6p29ycDjml7JKPKvzH7Rt3Zta5DYIENpC9obmNpJYjNuVVHUnHQnPSsbdbT6fJAkxjnmIUs2SoA4O8sOCc8AZ6du1HybnUdXubp3dmUfKYgoyPYDGfWnWsNmbaa\\/F7HIYVBCscHqMAADhjTp0nBKLbYpzUnexoiOxtLf7Kt0zyN+7VIsDPUH\\/OaR7GVUMemxzyGPG0Aqc46kg9vpnpTIYlSYTSb0iwAzrHkAbTwMZ9T9e9TXGnXdyxe1je4MJ8z911j9iOvbryKmbs9yoLTYn00TRLLeSokcSuUZlCsOcAknkDrU9slydn2Jprm4ddo2NlMdAc5AI98\\/4Umh3BTTGt2QpI0m75lG1snuPoa09FsodPuXnvhPtZvM3QFVPc7c4J79RzTb5dRWvoFvp11b3NuLt\\/K2ybpdiq2xR74FXvEkdt9od4rmed3KNG7tkYHYVam1XSoLCXyXBExO5ZiTImfUnrXOw3Kgxp5hEWSA33gM+tTQjKrU53pbT1KqyUI8u9zovH1k2q\\/D2LUm2lonVWccbiSAGIJBA9wO5qx8AfETeF\\/H1o0kuy1dhDP8xxsbgHnoAcH8Ku+NhZ2fwdjjVnb7SUJbaeGXPUjt164rzGGaa2EE\\/mSBSmS4j3DPb3PeuipOdNwkvM8jFRcpe6forKoOGXowyKr3SZgYe1cD+z144Txr8O7aaV831gfs1wCeWwPlb8R+oNeizrlD716slqmjNrozkpyYmJzjBNbHhm5Mlm0ZPK1h6s6RXjrL0HIFT+HbuP7cYk4VlzXTVjeBz05Wkbl\\/zGTXHeMITPpEwA5XkV2F1yhFc9qEYkjljIzlanCysx11dWPD455IL1lGeDivXNMvjfaHaSMcl4djfUf\\/AKq5fT9L0+W9uILlAXySDgZ\\/Ouo0XTTb6YBBIHiRtyg9QPSu+tbQ5aN7WJ9Fs5pJYZEg3BOGrlvjtBp9x4SlnZVSaPA2rwPT+temaQRFbApxtHzV5x8boVvdLmjXKhgwYgZz3zXM25Nm00owPi2S0gS4ueAxEpHLYJHsK5xCLW+JIEioxGM4zXYa9ara6nKfOzIG3rv68HqDnj8a467Ba6kJJBL87uoPvXgwvzO561J3imdpo2sFtLjjLLDNuO0FSQV6gZB9e2K9h8AT3tz4VtV0q+i+0SRxRjYWUq4mBwDggH5+QOw69q8V0qO7tLi0MRWRNzDMT5DDBJBOPyBzXrfgG6bTLS3u5JPJWK7kmiSQ4COE79+Qf06VGJXu3OinuejeIF12W0jS8vpr8rCXjhVWOT5fDFd3HUYBwMcg8GvPviLZXEFrZ2SeGtSs7mIZMsqkiWIMBuUdSowSewB5xnFdh4O8UXUmoz3EIXynt0Ej2shwu12UHHG3IbgZGNwPWofiD9iuibi1muopJS0ZguSyttMY4Dg84JPG7pn8OSN4vXoXZnhUKX2j63c2eovsmhYMoVxkgkemQevTOK9Z8MeVJ4bM9vHk2Z3BGywZnJxkE4OOT2757CuX8daFYrdw3KRmWT7OuxtuS2eSc9uOnJ\\/WtDwHdMLbzIQRFICmxl5ztzxx14Pr79Kc\\/eSkjSOmh6ppsdzdpEIbreEXb+5fIGXwvfue\\/cda6SVpZJLn92BCwwW39GHyH5jgA+36mvN\\/C008DxhEQpcZRo1PzJtxhwO3QdR36mu9aGEqspuWhZoGkuHlXLFgFO3H8QB4J2\\/\\/AF+ecXJ2Q9FueHeK7hF1K4WGOZUaUuXMrbsKxIGMDJG3qc49a4jWbWQwSqrLG4IYKjnAzz6\\/5zXVajLNBdXE+nSojNkMZcGRxk9iDnjBOOOea47X5GIcOzSKQcBx1OcY6ck812UqbRnKSsciVKzuxkyvp+P+Fdp4ajOHPnKoCZZtxBxjtwfUVykMZuJfLMaRgNkDk\\/hXZ+FrS3WNmnQyA8hSx4I6nGeeD3rTEK8GTSdpDJ7kQ6Q7IhRzkuAAAdxIznrnkduQK5gW0t3cqyMHdmyMgkdScc8nnOSa6PVbNp9OmkgMiO21HBj25YjIC+pzxx2x6VHDprx36wy28riUCILE3QHv0I64+tc8HyRbOiS5mkWoECNAbpIZbco0j+VDiQSNkDOfTr1xx3rW02wby0F0SwnbK5\\/5ZgPhTznJ689cZ\\/GOytoW02BPLiinVsSRDHzEKOp645yRn\\/69XWLldkNm8MkzOykeSACUAPA9+DzjvXI25OyNtIq5geJpUkupo2d1llmPzL91mOMjk8fhXS+CtFmv7e7u9Vyrkxr97HygngHtmsF9PuDaxTzxsLvPmIXzkDnnHpz17YHrXofgVZJbCYXt2TgpICu4Bjk8EBhxz\\/LinXnyUrRIpxvK7LutWl1p0SmytzNbxsGaJ2PPGeBjBH4ip7dYrhTcQXCwySBw+Q27GQBhTgDnH9Kt61LI8a28KRTeccFo7gAsuBk+vp\\/nmnRNFmOyiURmKMeUCAzAg9RwecY5JryZVG4rudkY6nNaSt3G6RW8ECSLJmWRogC2c5wQASORgH1rqTbJdsIdiR7h99TtzySBnsOmT6d6S0trNZRG1qkpALFlzuB7c7h2znjnk1swwyTK0CypGWyAqOANuOB6jgd\\/xrnrVXJ3NoRSRjvockMkZtD9tlnmEcxt4\\/uAtgsfVR6g1vS2lmLqSwXaLaNlKBjuPfOSPx\\/WmwQ3VkJlsri3jnkU7nIPIHXGcAk5PHP86zbOZ\\/t+WjkaFn5k2DC988fT\\/PNTdyd77A9mSwJNFctZgOqLOWGG2EqRjGeoPas\\/Vr1heMkUgWPzmaQRsp2deOTwACc+1b+qRFmmlHkQygq6Ek9T1IHT3\\/D34xrjToo7yZYGj8+4lZyCCgBJ4+prohJPVmDVtDlYtt0l7b2c8xVhHhwu9yANm5MnbgYX5uQMdDVnWLCZ\\/D0EF1fh3jjBJULGSeccgYBwcZxRfWOowSfarNLY3EW5GiDf65O4DHp8xz\\/WsHUblp7UW12vlTGMbV3lx3XBAJwSvcep9cV3QXM009DKWisUNY0z7E9w4Cu22MGYORJkdxwOBg59R+vXeCUsYNG8ieQSPalpojLuDIrFj94jvjtzz2rkLm\\/Ny94kd1FwEjMbgmMnjgcZPX9K6HT47WXTLe7vRuSFdpjik+VR2DdCDnOB\\/siujEXcEmZ01Z3Em0q8a+a4mgZoI23JHbt5rsGAHVh7fljFVobieVoNPg0maZoGGzzLfadnGcgcDHHzcjn3rpvDBsI43lad0tcB4i0wbtzkliOoU9c\\/mapeI7MJdSPaNI9yYmY3gcZUL34xnjsMA8d+a5VK7szbYy\\/F8Yvp7eD7RFDLLFtVNvzliw+UeowO2Ooz6i1qejxxQpFFZLGkfLqY9o5BXKhRyeM8\\/nTNDslS4S8sZYpLjehkt5SfN2A4OGY52knce2MD62fEcya8Es4ZXiVJUZZYiuGYc7Sevr1Ap8zTUVshPqzF\\/s7T7Ha3nQyDe8SBrYh3J4DAdSAe\\/IFafh9SgW3LFjbyvvLjAxk++R9Pet2CytpojOxTzUy6g4+UbiRkY46+9ct4jlXRtaumjgmuEuI1mCIN2N3U8kAelXGTqLlIfu6nIeMkN3qsincIIoNwWMgdcdfyrE8I6XG2uXKyOY0UssexdxPPb04q94v1IzyieeH7GhiCeWMbieQCdv8AKn\\/C+GGa3vZQDJKjqcBfmI5HX6kdOmO1ekm40Wc29RHQXOhollFdWf2tvMRWYcEpkkAY65OPwqbUNA+zWSTu0sjfIQqqcgtnC5zjJ9\\/T8+x0eOSTVpI8\\/uVgLNGyHqoJwufQHGPaiHauvLdzKTA48tXiXcSScjplfXtnmvP9pd2OrVHKjwifsZvZIVW34VgJSXibI4x0OcdM9\\/ao\\/EHhttMiiMN+8j7SZgV29uB83Q544Nel2llC1nKtwqytHKrknG3AUckDHJxj15rP8dWKahHFIQghmU+ZtZR8uBhgAPp+tRGs3KzLseWW7TyI4KhGXdyW+53A469Ovr6Uk8MtrJ5scFuLoKGUuN0gB6HjpXfz6bY\\/2PKXsV8+CPCPtAQbR2Hr94Y968o1618Qq8clxDKI5lDJsTnHQZx9OAa2p2qN20M605QWiuP0fULSXV8+Zco8iFH2kYY9SRkHHTpj8q6iLVRYwF9HLKS6+a0y7pGODzz2yOnT61S8KWNnBpAkCxx6gsZBEpBdic5AU8dOOvrwa0NFsbe31KRdStELQqfPjk2nzDj+HuDgjtjp+NzcHfyJpRmkr9RtxfX93ZRI1sgbn94gYK3GPmH0\\/Cr+DHd202nssCQQrEUl4DDGWxjpyOB0rLkNotu1vYIwjl3ZuJCqt8u0FeMcZGQPofrgHUJkK2Txo05YeQrkkMGHPB989x9PXONOUvh0NnKMfiO01vxFLbaXIkt3FEznfG6namCfu9gTg54z9OOcnQfEN3byRPOuYpQGdY3JKN95T2B6KSB\\/WsmS8eDzLO7hMhnVXVQQ4APHpww46AnirJ08XMCXzWhiUELlWfcWA7HJz+NWoKLvJfMhu6tEsX2paxqEUz2UBR5Imj3gDI3D5gAxH0z6HpVfRLaW5\\/0XUGkhWGJlmc8B5CxIOOD0I9KhxqqM0sDh1XJdXbc0Yz6joOfbpRqdmLyCKZFMsx27zC20leeaL293S35Ba+utzu\\/Cj2\\/9gLbeeXOnzqsILYfaHB5Hcc44NekeB7eVInuJMBZUVgBnjjFeAWup3Ph+4mSDdcE2ox5o+ZecnAHHXBr2Hwv4ssE0eG7a5FtDKMRRyfLtBPT3PP6VVaF4pmN9Wjb8Q7XjMLqSMkjcR9M\\/WuM1qLzL+ZI3AQIYm3fd5xxxWnrGrJcWLXH2tY4cuS+chuMYyDkHJH5Vj3lkZbiK8S7VrVZQ7x5xuXOOCevXNFNWYnew638K2WoWsUcqYWKJpdsblR5jfLnGf9knPTpTrS5ltrSa2WJQtm8ayDcC2Q69Bjjgg9e9Gl6gIbjUb57lFgWKNcSyALyDtA\\/MVBd3ljDp+o3Cw25mlmZN8cg3krjkde+OvtW9iLs6i4RY7U3rtJ50TIMDBZsnB\\/IE964vXfEGrXF02nuBFaAuC+z95xt4J7d8jvWl4o8R2y6WdOtbuOSVbq2huT5nzKTKufqKrWFit7q128s67UlwhJwJWC4xnPuSeeeR61LjcfNYx49Z1bW9ZgkVZIIk3RxyOvyOARyAeGOePpTvGJ8RvpctslnE5crwjBgyqcsQrDjjsCTV6+uWg1HTrVbOxaKAKolhB3hVK5Hpz3x6Vy+u+K7y4mieynCvc37W6ggEogO0gg5HJ7irhRWnKhSn3Pf7GK2t9CWxtVWKO2gWILtAHTge3XNcvdavcWsuxmVYCSZQAFQjPTHb0\\/XNW7PxBprWqpFcl5XPKJE+QcdCMds1558QLi\\/1m2m+xpJbaYpIaRxsac44ABGcFsemee2KblFvUSTSsY3iDxHY6vq40WxfzV37mdQMAKMkAjjt2rbFglvYr5jKVCKCehzleT361ynw58NLZzGW5JaZxhgOdqnj+tdMl\\/Bq+sPpNkXlaFvMlkRcKNoJxk9TuC9K5sQveUY9DWk3a7NPxYbWDXtG03UdDjmsLi7ZlncZ+VWODjPUjHUHiulfw1o8toLO2tkKq3mMQQBgc447dOab450x7r+xXKLN+9ljAzySytirOh2VtY3IVzKWEY3WbzjZnucHjB5HXnmuaacrLsaq0dShqF7Bomh2vlstxbeQE3q+cY6nk4xgDiuV1mI6jo9lNGwktriZgFUqAScjPy8jHrz1ru5dJTU3lureeOKAt+8gf5tjA87dp4J\\/unIrM1uy0nSJ9OtbecMxLusCx5MfXc\\/fjPbHHP0rWLfYl27nETzJpXnWhWeCA3GyOK12BiFYAH5uvfj68V0Hgy6t7eGSSG9uZkErxrHMI8odqnB29ecjt9Kq+IY7STQZNfhdLy6DP5O+NdqyFnRRjHzY3H72eRWI+i+MNN061jluNPDGTcwRSrFs5DA8Y5IGAAOtbxp3RnKWp23idNTgsIfENjLcyWpt2e4iQx+Ww4JflgQevY9eneobWzk8URS3s6KYbZEmsGkTJXhsMQRzu+Uj0HpXKLFL\\/ZVjoesahPG0VySY4Zhtljkyc84HykHqOAQe9ei6JYReHdElmurwpCtqm9pW+UBAVHT2x3Nc+Kmqast+hpRi5O\\/QyvgTod8mq640qtHGL3zGjjjKxkhSAQM9D1\\/rXQeD4dll4pMnm26JGQJCnyrgE5+bjIx0rmvBfxD1Szka70jS1ewupCJbi5cIFLOwXB5AAwODj\\/Hc+Ieua5rHhq+0fzrGKSQmOQ2mWzkc547DP86mo2373W36Dgl07l\\/QNDi1PVm1Ka3Zo4x5aKUBHylgWU4yvX8ya8B+LFnqcnjW\\/tHaNolYuvlymTylDMRuPY8ng16p8M\\/FUlvpmn6DBcRwrEkfm+Y3zIFTaTjPHIz+fesn4gzare2UzX1oLW4lvTEwKMscoB4dW53AjuavD05UKl3sE5KrG3U7v4eKsPgS6dLgyqsSeXvXByI15OOvOef5V8+a3ocmn+MbW5guQr3DtLGzOPlfBOcnjGcf\\/Xr6c8NxLbeDpoJYFijj3+Y3K4IBJHPYV88\\/EMefqSQ2sBmVLZWaRY2AEZJLsD0I\\/hBrehL95LzMZr3FckbUbjxJYWOmf2U2nwEwvJLESS0ZYrzgcZYN17V6xphuNOSazsxFM0eJYN\\/Q5ZCe\\/avNtH1+Syu3lsrI\\/wDHhEJY4rb5Cw+btyACxGetdLa+IrWK20+7+S2mktzvhYDccjJJBGTyQMnr1pSi5StbQqMtPM9Emvw91p0enxLmQlbmR4hySCSFzkdR6VnWUGmJr9zHNZeUoDQM5bCb2wSNvfK96yJPEVqNP0W6iWK5VL6CBIlfB3NnJ9eAP51z\\/wAVtPuNduLu9065miNrc74pFdx91QMYzjO4H9KzhFRnZ6Ip3cbrc1fjJZeTpr63bXYikgCiFVQMoAfvnk5C1H8OfEFzceAbq\\/it\\/tF3DPLMVllz5MaR8qD1PQkDpXmGq\\/EHWL3SZ9I1yxjutwA863+Rlxn7y9CefavWPAFtp9j8HkiktFa71KOeSMzJuADZC59OCO459a6JxcIe93\\/AyUuaSSMnxX9pPh+4NzLBZagkaNIqxq23IG5dx6uCw5A7\\/icm1sPDDafNLqeqwrPciMwxq2yXfg4A\\/hzlfw49q3dJnjX4cxW8F+l5fzQSPeSSCQ4Ytl\\/mHBbK9T6VysWp+G7CyMU7rbXKowmPkl3fLAqVJ6Hg5BPbrXNGN21G+jNm9E2RG71PRtXisoLqaN5yIli42MyhMLIGGNpyPm6kZ5rY8Z6tFqGlLfxC5jn2GOWC2XfDkN8zB8YbgHvjnGTiuV8OwXWq6pd60bg3zzTGIBmRAingLgHaDjGB04GDWj4rvU0PwxYC3ivzKIXgSIv\\/AKPCpbJIkVRuY4Axz1OTXVOmm1pqZRm1dnLQyee8bzLLJIMHOCBg5yeRwenNLEXgkMM8scVsxzvB3DHqQcfh64qO9s7u0lzCJFBxsQ5YYPpg0QB\\/MncXEP2oIcoUPsQAw78V3OC5Tk53c2wLaKyklgmM5cIG+Xkeox6+nNVJLqCC2HnD5W5BUkSE5xtxxUGk2t3cSQi4P2bzly5ZuB\\/9eneJIYrWeHe6PGSu1t3PfqAf0rj5I8\\/K2dPM+W6Gx3U0sUloIMLAnmPuY7mG7PGe\\/wBOwrotL0iK3to76SLzbdmzufgN8pOQT71gaXCZdVa72tCIz+7OzOeB1APTn\\/OMV06SQppyo+nqyPLvjBXMf0UZ4HfHFOraPuxQqd37zO18M2elXtjbFpVkgljImRm3lTnPGeQRk5\\/pmo9a8Kh9Le10yQFBJwWP8Ppjr07iuc0UbbiU+XMkAUmVEc5XuxHIx9APyrsNE1SC\\/dbm1inuCqlecn6c\\/wCetcdTnhrE1Vm7M43S50s4ru01C2ngjtwUilRd53gnDBfvHGMcfpS+A9WuBaMtzK+9ZGY54CqT0A65P4Vt+LILmZ4rkhV8wkMkIHmAEcHOM4yfb615\\/oVsm25ivruQNvMjNIWCIePflug6elddN+0jfuYv3XY9Xl1P7JrN1OLdZftESwxSCX5YgBy7EHGPQdenSodbuLtvCVpZ2k0It9uyZTwWYsQWzg45ycHI5rhtt7aW32SPa1vv81d6sC3QZwex6DjP4Zru\\/Ds76n4enhlWW5MishcOpClhwTkfKM+nTr0pVKdkmxRnukefahZWdjcR28Oqag1zHLtkjRTkEkdQoGOuear6npNzbwyTTFo\\/LfIPnbnYHkMecD2r1GytkmjvY9LuLK606NIysaSsTIQcFy3IySMcg8AYxXH63ockdlcskc0zX1wYxGbgFUj+8SQDjOGA5B61qkr7WI55W1OXt7WeO33XESu0qiSNiBiTPTkfe+g4yDWz4b0yF7Sa7ja1aSIFvLuVYlmUZ4AIP44H41b8RaRFp4juIswSxuycpgKMfdGBwPxrYM882iSjTLeT+0Ps25fJuvLQhum5M9euAc5P4iqlsmhJmfpQvbq60hru+t3kt0MsNo+QQME85I2849\\/fjNV\\/G2nXWs+I7qDT7ZI44UfzboIwXHU7csSx7dhVz4f262epmaWVxO8yKu9jwFALZwQWA9uMmtLx5dx6fqLX0DCS5mjEcUQi2fKScnHY\\/UfWiT5ZiV2jmZdNstPhNveQSRq6KryK4KsdvUnPJ7445rHubBbKCeK2ldIJQQhxl2U5\\/WrEur393cCK5tRJLEhiRUhRio9B7d+\\/fjmsa6kaSQJJgFBhGVssuDjt6URk27FONlcju54Dcyp5TK0ICo0hOzjqOmSeap3sQu4wnlSOAd8s0cpZh6KBtGD371NZwwahdSxyTxpsVi5eXhifQZwP\\/rd6mmAsodpCl3UKoDgk\\/gRx+OKtWvbsJ3tcydJ1G5t7uF7ecuInDuXlxgcjaSetdJHq+ox+dqFwbac3LCNIFkKsoI6Ljjv+lc\\/qAigtZo0Y+eoAfKjg5Hfufp0qhaz3H2hpmkaMxk\\/dkJXJzwABjPPTipqUI1NWioVZQ0Oh1HXdQuWmW3TZBbcMmDsyPUkc468\\/hVvQFt0u5NWcBgoRUJQKcnoSOi8g9yah0VbjVY4tIk1JJYicpsXYxIboD17Hr\\/hRqerXGjxMRGJNMk\\/d7J4ziUj7yrg569TnjHesGkl7KK\\/4b\\/M1vd87f9f5GzJqlw90kZWGdQxZi0RJJ6fK38ycc9qff+IrKDTDFEs2lTAbUaFBIz84wW9Tz09a423kLTPfRGKxi2F1hRQAy9emapX+29uUSKOR143kHn6bunWm8HTmlfp\\/XoSsRKN7F+Z7O5yLaa7sr2Q7i0shww+vatSzeaO6WCS2jmdQFLJhXBIIG3JwT+fbmq8aRW9mlvIvkhgRGgjSQnoWzkZBzjn\\/APXThYIY9sVzLESpZYnU7i+PbA6Y\\/Tr0rX3UifeZvSLJPaieW2uJZ0JZGkbOxucEgAYP09K53UbHzI5IpY0eWSQF5AGYgk53EnkDGBg8fWrzSSpbSO10sb4CEPGSEXgHrnnrTbP7FJBdQG4XBAzlxGG9M5HI47fhTc1FXEoNuxj3BLaVD5KRKi5UbCC5IOfmz+Jxjp3qS0+1XTN9tumuScBITI2wKO+0dfw6U7UpEMZUlVfeMRwR5cgdG6DaO3vx161sacb7bJeXV9a6QGYRu+0SyAdwSMnd1561NSryxKhTuznPshnmlKxFfM\\/doQxwPUnOT0+lTWOnPJegvG86JnZIMhWI4zjHPP8AKtbUbPTS6pa3Ul3C6GRnEYiJGOuMhR+JzVC31LT4ESCG6aFnC7VEQYhsdC3PGMAc\\/linGpzRuhOFnZiSQXX28SSBi6kKhVsbBjJPI69KLaBBK88oWQrCQNrZwxGTknq3SrE1mkVrNqVxqls7cMY4G3OB0y2DyAeP15FQi6torJjs8xWwcq5Uvx2B7e\\/\\/AOqqU1JaCcWnqVbK8n0\\/T2juJCIHOFIOSW4BAbpjH1rS0fRYZkguPswW3T5pCrrg8cDDYGT6VSgy8Ty\\/Z7IfZ4sscDeo4+bn68H3p41GWTTxut5zawDaVjTcHJJJZ+nUADP145qavO1aI6fLfU3U1SwhcxXNmZbaJ2cRW8mxmYgY3N8wz1HXselRS3Ns1vO0Q8mO4J\\/cLc\\/vYiD3IGAO3QdetYOnTaW0Dw7Vg8071kOdqAZ49z+uccVfuI7K8dYmt4o4wiMfJUFwu0Yyx6nkk5xycdhXP7FKXU29q2uhZ0+do1Rmmg2o21VibdM\\/oducn6571ZbWZbkC1lC\\/ZoXO4K4imA+uCcfQVUkiGnTSnS7sOvljIyDjOCfukg4weCTk1lQRZjFwBE0hJMbyP864I5Cjjv1PHp0raMebXoZt8uh0a3LWN0XhsrJ5gu5t5BOPxAwf1NLo4k1K7F7PbxeWudoAHJ78DgVmRQfbQ195gRjgO28jKjtjHH\\/160bi7tktFWxBCJgAjJOfTJP8q3jT1TSMnN2s2e0al4cOt\\/CdlLYKY8oMx+QHPXsf88189RQ+Zb31gZ5EltnfA7Mq5GMH+f5V9R+A\\/M1D4XpBeSi0jmhJ8yPcsg25+YMD8pBxz2r5q168uTd39vcvczqGYwXC9CC\\/JY4z1z15rKrzumkujOXEK70PSP2SPFT6J46Oi3LbLfUYAgB4y6jg\\/XrX2VHIGQKTz2r84PDuqnS\\/Fen39sGRoJ1J3EcYbrkf4dq\\/QLw3qaapoFpqERyJYlb9K9fDPnpWZzVdLMzvG0W11kzjPyk1i6BKYdUhy4PJGa6HxxiXSGmHYV5vo2pn+0kJPRxXpQjzUjgk7VT2KU5XNYV98sx9DWrDKJbZHB6rWTqfDZrkoq0jpqPQ8712ZrHxEkmcK7YOPeup8I6rvjubJ2HytuX6GuU+JEbKEuF7HOap+HNSMOuwNn5ZkANepOPPA4ab5ZHqEN4YYJFzxtzXP+OIYJfDU80jsXbgYPTg1ZuZ8w\\/7yEVz3iK7MvhqRSc4IrmUeprOV1Y+SPFqzyajLDBJu25DB22j25rip2O4NlHJGDnHBruvGUZl126ia4S3yxIBJBb2Arir1QgZDkFD8u5cZH0xXz21SSPYpfAjQ0u9RoI1cldqMhGQC3PA\\/Wu6hvhNaC2lbz4WRSMSkCPjnj1+vYHivPNDAkd9ziKIMrMR7ZOMfhXqXw0tLKezuLq5zI1lcQzIsgGWgBOcAjnlGzz\\/ABU6slGN2bwTbsepfCiS8i+zy2k6JCCYo3CgysC6klRjk4TofQY712njgTXnhK7n1CO2hNtKs06lVGSrlePRiOuep9q474dPaafZkWAuXjS+VomiceaUfkEDouVyePpnrXTXd3cX1xcwXttNFLc2UyyJdRn95IW2yMiqBkfKV+7\\/AHuwry5PmbaOiyW55n4h08\\/2TGDHdwkxGSIRhChUMxBRlHzKQep7856ZxPC8oie6tZkMjbPMXnaVAIPC9ST0wD6969C8XxSeLNSsYNOtRDsaWOVwu0P8uCCBng7fU5PfOced6RENKuNTuXZSszLaksmw7G3ZZR2bCjBHYH1Fac19BpdTrIJol0t1tdwSIyNKVZt2QFzluo\\/i4HoSOwrrrW9a2t7fVJfK2RWxnSOeYnauAAGYAbslVB\\/Dg1xGgC3d4YlVoAtyUdpjksTlWPPUHH6Guu0e10u6nIuLiNbVPKkjgk8tfKRyARkfLnLAg9uM0rpaWJlFtHnfiiSaaVTNFaQMyM6lVUKoPcHIOT16YyTj0HlV\\/NFLdMkbIAWLLwcZzwPy\\/nXq3xA1PR724u5oHkNxmQOnmMY1IHyqpHXnJOfw7ivIRy7uSF8wluOea7KVrXSsZSLllEkbF2BdhyzZyMkHt9f5V2fhXZcpvMeQifMRwXyS2Bxxkkfh0ribW3lkcIztIuMlWHOfbHXn9K3NPvVsLMb5JmuBMojaEkBWyCM+w4\\/EClWTcRw0Z1Woadbw20quHmBkZFbaGkXBUMRgdOv0xUM2h6nf3ii3s7V4D8xYt5YAxkYAGQQSR0zTHvLy922Mc6NdQTsscpXOVOAX9M8Zz+NdF4T0xofKu7+edpRGqh3dShA+bjHJBBHJry6k3CN76nZFXdilZ6ffaLbfZlWK5ZizsjjenzHB5Hfkc\\/Tinapp9lLPIYpjNJAuRiPb5Y3EhNzdSd2c+ldVqMsiQ26RrIzMhbBxle+TnGee36Vxt1KzvPdyT3Cx3B8vEZODkdM+px0FccJOT5rm7SWgsmnLdT7kiu457WKONQwXau44zkHDYAzx\\/Wt\\/w9p8ZiWHyPMkRRLJNI2\\/fjgEE9O3QetZ13eQQRWlpOwCsfIliYq5klIOQcg4IYE57\\/StVZJIpkMa3EMjhfN5xs3EhTxz2PfGKynzyVrlxcVsFnpc4u7uS7aCROdrrH5ZUZ\\/2jjPPBAqSW1gBWKO7ilYL8rwAFh7d8n5TjHp0pdT1e2hMVmZ4YHOVHmso85x3GedoI\\/X8ax7zUdOFreT3eoWs6Mm3ywScvnrlcevXIHpWcYOT1LbstDX+xRutspneV4sq+ZGB3Z3EsAQCR\\/UjvUmg655etzrNZXEiQYkEzLhJQOpB56Ajjg\\/rXL2HiVbsbbGwurl1RizLH9zdj5sMeRyMcc8VoQaQ0dlJfNqUMmUMQuZFb92qnhRsfAHBzxnkjNVOjupijO2xqavaXF1IL1\\/tCzSOTbxxguAm7jIXoeKII7ppwzSyGVo\\/3iKTu4OM88Z9v51f0XWFuNOtUkhuCpDs8gBYKB2APOM\\/XH1Nci4vtOv9TnGsPKLpw8fnZXbhsYGckfN0GPSs4Qb0fQqUjsongkCXX2YPEoG3BBZhkg\\/yFRZgS7IkjYCNf3eflI4PfpzxVCzmLFMgTTxxmN\\/ODckjkgnjOOOfTinX87q5mnd7QADyxtV2CjHGTwB0GMDg80JNuyFolcrahD9rhMEVuHWXHmGFsMNxX9PXFY2r2cv9mm1vLWErKFVQrAGViWGTn0AAB9617e9lWe1jvhHbJIpVXiG1Zu4BznsvODxx6ikVXmldWnlSVcJCnlhx8xJyMf7uex5H0rupJxsc9R3ORurC186C1Nk4yViOyDbj5NoywPJ6Y4A49zXUQ6bLpccJsrUzu8e11llAJOQeASeR19ufeoL+4uJ51trQQPaREFnYcF2+YAKB3we3cfhde4uUJu0tPtjhxGZPMXY5GSAM8qRk9Mnjnrx01E2kmzKElfQZod3PY3Ez6jpi29okRjkkIUqpB6e+CT+tPsLmCNob9IbuWMRtEQGUKSSCC24gngcHB4Jqr4euElmD3ckVvvGWgJUJuPRvfOD6Z569asra3cMUEELoUd2MkhlIC88EE9M+\\/Nc0opM1u7GlLGo8yRomR88ELk5PUn2A\\/pWKdBsJ5\\/LWRhJKzSSER4C84AyMHJwcA8CrVpqmn6jfSWMs+8M2dkbny1VcZz33H34571csNVgka5ktbaCKGMgKplIdjnGQD\\/8ArrG0oml0yhMsmlwxwbph5kZSMsPMXJB7DnjAyT3Ncn4ustSMyyyyrBNAhWRcgqcLuPOc47V1kxvb2QXXkoqQIwkbeDnJ6AE+xwapa18+nm6ZBu8sbdr7sbuDnHH+Tn26aTUZIyldo8h8akSGOMjZdIADg9QRwee2OfxrrvhLpUb+Hnu0m8l1uCxbn98AB8n06\\/nXGa\\/K15q0skTM6wKFZjknJHPB9K9e+Hdqlj4AXbucyhpVVUDsPfn8\\/wAq7sU3Gikc9FXqXNJo5bWCOPyhIH4iMYYqmSeozuI6Dg0uk3FxtSHUofKNpJtV4iPLyvGTjOO2QeRxWtayWn2OyvBMUk2k26yoVyOucemefxHvVXxLeQ6bYSsxhMl2fky2d5xgH8TzXkpu9jt03NqS7\\/d+cpj8uW4jSQsxyqcAngdeo\\/WszVCL64mhkYC43ZgKAEYAyGJ7DpwaZ9ogvPB0J1FntwIUdmRQCpC\\/e29cf\\/qrKNva6pp3mRa68tpcRmNRHH+8jx17Ag+v0q1FLUi7NDToJtT0KWaaANKsjRurOOmcZ7cHOenGa5TxW+kTqttZCV7WKba9y67syEZwM9eO2P6V33g35rGe0lYXBnXJkl2qQdv3iB9AMdaS80O0NmUmUgW0gkKhVfBU8+ueufXioUlGTL6HlkunSMI4bMx3KQxvcJdfNHuzgbCgO09c9jUVlFqIhiCC2nmkT94u3YUGQRg8nHX0HWu9aJ5fE0Edo6\\/vLZkkjdDjY+eRg+w\\/PnFVfGcEf7i3sfMdlfMeCQQgAXHXJxnPfketdkJqaMneLOW1e30azMtslrGLiNV4kOWJZW7bAMnbjIB6j3rmIhZy3qw6gftDwOgI3BFiUjJIb1BzxweBW\\/4vsoLDUEtGnmurq3JaYqTIg3BSBg4+UDaOe+MVjIl3dabI0FmsEEqGV5Qu0GNTjAPPBPX8frW9JaXRE3pqaS2elPFKtmBJIxyj\\/Lgn0IHAB9sVkLeGCwLifYVy3lK+7JyV2kEjj6Dt6Uiy3ljqiESJdMkgiLRvlTgYyAO+SO1XovsUV+14XtWlHzZBYFSQTwcYznv+tZ3dO6l7yZppO3LoVdGjvUuI725kiRXPJYKAy8ZBxnjHHbFasitYWC3qSRhJByUOFCgj1JPcU\\/T76LUL8xwDdEUO+MrlUwAT69eeD71TvJgkqJsjXeishDIEVTzhsc+uR0GfzSUp6yjYG1HSLuPOrWU872E8UVxKSVVn4fb\\/AHcnjv8ApTE0gWQY2N4kYZN3lbsMODjGcn8qqi10uaEyySB3Zy8kaFlUuD8xAJy3tjjA5ptxbzWt1aG3kYtOu50eMKx9VAHQAhq0UEl7jt6kuX8yH21kwtZIEm87\\/nm8uQI8\\/wB3B46dfYVr2Gry2jvDdNeiKOEDDupUMByyE5YdB047daqSSI7C3hlDOgO5Qc4PXrzU6SMtm73qFTK2cg8EDjn\\/APVWTqyT1HyKxkWupXMVhAipHc287MWDsUYfNhdxJwenGauXtpNNJYzLeonnTKWiBLDkgn5voBnA7VnwrCkktlG\\/lQysrGIqNpABOQx+vpU6aQqWKM+oCZIpNqW6LvYZJBA6+v6V0ucYtO+5z8kppKPQ2fEc9nJqNhJcWcIeKdTcXDL94ZBwOeR78Vp63dW9vGLU30UtpcSkqVLAE9CAw4X3yeOtcdHPZx2kObVvOilPkI2SgweFJ4Jzn\\/A4FXF1+6srWOT7GPMZiQrW5VASeT3HII7U7trRFcivqzY0mGG311ZIZZzAwbCSZIQ8g9fpXJXCMnjKytxKAZrxZgc9dzZA\\/l+dbmna6k9rcXjWbWfnKsSiNmWJQOflwM45PHvXIre291r815fTziKJmlA3bOmAgHcdvyrsgtDlmeuTW91e3Spp8RSd8724wqcc4Pf0FaEFzfG0hXUbcyRhHhVNm52kCjYDjk5wSPQV5\\/4Zv9Rl8RmzsdUurANaCWN2LPGwwDgL2HJI+ldr4N0\\/XNV1m5tdfuIr60jC3HmtHlhJtAABJOOCP8iuCqraHTF31G21jMsSpPJJEZiBngeXHgkDgdSAKb8PrW7TxHcRXSQhijPiJcL5eQqr2561f1NYdM8iRgsALIsaAFtjZPPoeO\\/uKd4LhlXxnqF1PPmBoCiyZ5yGU44579TWMtTRKx1mqxl5tIkYSIFuhuCnjG1uvPoDUOs6rb6fdzTLtU7QqSP03MRgE9cZqvqutA3GnW6yBJfOPlgr9\\/5DkZ\\/OqcRh+03uq6hqy2VtbgK\\/my7Q5Oc4HUnp+daQhfUmUjpJNSsdA04T313FFaDA8x85Y9+3JOe3rXk\\/iPxlol1qd1qokWSdwYo8k4hhAwMgZzk847e9ZXjnVNOvWkOpapeXDBC0FmhbAXI24yAo4HJIJ+auISNJjIYoZYi\\/zqrfM+3PQ9yMevpWsaaa1MalRRdkzr\\/DPjOyTT4dJ1Ocb59RhlUeWSsS+YCcngY78H19a9V8SQPOkSoEBUF1wPvDGAce2a8Ra6hRFWW1hDsuBn5mXBx6V65oGu2WteG7HUEwb2NTBK2wLtZfvD2BwD+NXdvW1iYSUtL3NLwothL4g0aG8shO7NLIAUyOBt549xxnpTvHfht7rT9Qt4b+5axBEdvaGc7Y5TnHGM7QvOM4GDxU\\/hudIzp95I4DRq8iBk5I6cZ6DrUOn3y6vJqFlIkkt1DFvVFGA3Jyx6APkj14WuHFxbkmun+Z10WkmeW6xJ4n+H9\\/awwO0+mxyo4iYnypSpDFcdcZHrXonhPxt4f1vT7gS6Ta6RdTxkDybf5XbGSCfXr19q2fGNja3lrFbNbqFtxHcSmVgFIyQQeDxwaqXOk6fpnhd1a1icQusfyIAT8q5OevY9+9OfLWhaS1ErwldMqfDfw1oGrQwW15aJLcT3jyyxvH86RiNtoPB43E\\/Q96ueLtBXw1eaZFpt\\/qDWc1\\/DC1pNIXhVdwwMNnaBgfdx24rS8N+DlilGo2F9c6ZOxRIzH0x05HcYxTfirearaaRYxaldgXL3AjiMIwLk5z8wAO35QT1\\/Kiz51qK6aJPFX9qobtP7QWGwv8otjMgIkbyYhuQgE5LN05HBPqa8l+IGkT3Gp3OqrcfY4Hgjt0iGGyqgY3YPXOT14rvdU1yw1PxEsFtJMyrwJNmWAwAUXPIHHT2964v4k3dr\\/aaFbpZLdIgWiA6PkgZ4OBwSTj09a1hBx16jtGSszB0W0WwgkuQ89w6oUVc7QTj8cjnPvxXTReDL\\/W47nU9MXzHjtmed1UbS2OEDHBLdCQRkdOTWDbrr\\/iKxjtNPsYlit0+TbPtKr1JwMAkkd\\/T0r0Tw3bXkhjtobmRI9iSu0DbXZuBwR3DjOapN8y11CVuXyMWx06\\/hXS7qHSpx\\/Z7rLNHLGwkk4ZcHI5YbiOn9MdRaaFrV\\/otw6WUsKuxJNx8ihSSSecMSAcdK73bbR3ltYw77qaKMCa4lkBlJPXdnJP0zTvEs8ykxxtB5LR5YyyYJPoFxg9u\\/4VEoaMUZbHhNv4JtrnW57ktusUGN6kfO4OCv6frXceMYIbbwB5CHy2jEIjCnBC7FOQR9Kt+JLq107S5HtURAQFAAHy57ke+SawfE2p27eFLCLzUkV1gF0xyQg24OdvIPFVFSainqJ2u2iNbK4NpplzYWok0u4lO9S52iQnHQH1HPHua42z0G41DxW893ErLGzLLEyYU\\/OeAx4Pce1eneE7NrZvsyX0z2kI+V2+VcFRu6cfz70zxGLS20mZ0uHeK1tmRXJzhyRtYewyPyqXUalbuNR0MTwXb6HfaZqlnJY2ttMl8IjDGBlotmVc9iW3HnjnFcR468Qazqq32mWTJ9jUeWtoipIiZ9Djrk\\/hU0ttNpN5c3Nu8kkhs180F9ryg8biRz3GPp2xxg3ckuhpFq8cWwzyKXw29jyCSff866IRjZWM23rcm0vUZ2vE060t0N0q8uzruX6k\\/wCFU9SOpWKXu4LIUOGnJwuTyeT1+tbWk20VpBFeXMUUbmQ4BkbzDkZAxg\\/41c1nSbG608mK3O98ExsshdyBweM8Y+ld8oxkrM4VJxehgeB4Y9T10JqErxQRxxxRiNRnLZzweo70\\/wAS6JHZO0cMkm+PcM55JwCOMnnBq34dsJGvNQW4YwsyosUpQN2OPXuuKNVsp4b+VZFR4xbpJuwrdsFeAD1PfmsotX0NGmUrZIHsWhnlmjd8EMu0bs4AyfbHt1rr9L1BF0eGwOBfxygPEybQyqc7gD2PHQYrzy7jZUtwGLlmywJwoOT6Hn8q7jT768lnhzbPOIwzeUuWbqMNj14pVFa1xx7o7\\/QLSznuJB5cVvPuV3VlDZB65HPPIq9Fo\\/lWMlrGsUsoZmUAABWzwwHT9K4rw8l2usf25ueNDOYyGUAsOcnPbkV6Kkmmx2zXaBmcxsw3gAcjnkds151WLjsbxd9yrqmjRX2jxWhkRbpgQMIrHIIOQcjHOO+a4G2sZNCsbiO3FspnKxFVJzn+9tO5s8EYr0RNXayt2s9RjSeOVPNtZ0YRrtxnBZjndx6CuN1HxNoq6jqAjs2uC6pIkrosqtj7wUkDjGOcdqrAvdCxCe5xmtrJY+ZFEjfbZ49qosuVVPTg8HPOT6V1vw6K6fp4kaOPdHlZYl5JbGCcDk4GM4471z\\/jK509r62lgUW6NDllSJQq5\\/hUYPX0GOpqDQ9eu7IQr5e+N5wsrurCRBk5UZ6DH8q9CpG8Tngzd0\\/XLeG7KyW83myTuzypujRc\\/wAJBfccY6kd+vNbAktZLO4nghQOOXlCM7cnqWyceorm\\/EGkTRahBeaLDKnmpmclgyEA9Nox27n8aLK+slmFi10wdXQSwrDubYWx97dhSc4qVFbjb6G14qazubG1gkV7hyfMMyRktGAB6HqeBms83WrwteS6ZpbTxxqsBZj5beUAxUhGOSTkHOfwroYJoLO+t7lVdViQ7\\/MIRemOBjk9O5\\/lXI6nqt0+rXN9d3UDfbTvHlFtwwmFDMenTHAPBp3W4lHWxS0m41K11NLy++zw\\/vS4iSUswOPTbg9qta1qDX2qLeIsQYI6xorAseuDz1qhZsrs3nO6yJ85kEgZY8gdDgdz0rHeeB5ICFlk8pj+8A759xQ3eRSjpcllieeO4eYSJPjed0oUYI77TVLTYHnh84sHaMklTnaR6bgQcflV+8WCbSXns43fylIZpIwEyc9+OeMcc8YrnrW5u4DKsM5clwojC43Dt7e3BqkroTZs6wxvrWK1soLe1OSZFj4ySfcnJwcZrO1VHZreCaMs42xgueFHTIGfp+VW5obiy057mYSQSsykBsYcEHGOSByPwqi2nXktxCvnxyKzr88QPycZPUDpx7URioocpXBrFjmL7ZbQTZ3qxBJYkDA4FU73S7wXP2a0uXuWK5Zi2MDAJIBPT3xWnqViNHkiZ184S52KihwR0zjg55rJt3u11OVoBMJdmQjn7p56geg7VaJJI\\/s+nYgEjx3gbPmh2QJnt2JqW6hlvMRxzR3AC5UCQ7VPvk8Hg8cdqqSm4XMl4kkjOSEyRhW65A\\/\\/AFVObR5Pnu5btdqmUSyFjHIwAwAegP50muvUL9Dd1HTtNitrd726tUtc7Y0EgkZ9vUbk5HX0\\/GqF\\/q1rC102meVFbRhRgIz7m56lmJA\\/x9qrw3TXczJqS+WZWAaY7WYjHY8Yz\\/nNQ75o7Ta4hvYWkAVSpyD2x36gZArCNN7yd\\/yNnNfZ0K9teXsl+urJAp8snOyQkkkDJ5\\/pxVy5vpbq1VpRK\\/nHAMcxx34KADJ\\/z0q\\/YQ21xbfZ7iRmuUXaxgkAjHYEkjJPXgc8c1SS28m6MM13FDbRkjzZGLEEZyBjI5x0zmmnCT22E1JL1KpVWgW3WUgEh9rNhTnufwq5FF9rk+ywW6XBBJhVIwGbAxyQMn1\\/CnsLYgXMcck8gXCELswuOu08gDjmqYtpoYw9xK3mSNl49u4KOo59efwPFbW0M7j9UWC3LQ2sMsW3AumhfZHwQQAfmBPv9OM1BZGM6hI2oz3EMMa72QKGeQHBC8kAnv8Ah0p81zKlpDE0MB2kbAUYBecjdkDdnB65\\/pVCWWYygweWqMcl9oAJPXjA9+gqVB2sNzV7l2a8uZpzvnd0J3eWidifbgdKvW97C6Sw6fBZQNsJlnlk+dxkfKo4xnIGBknGfpkI5jj3yqhVjwdoYN2PPQD\\/ABpHu4IygdyxVw24Mc4A4AAP0\\/8ArU5U01YUZtO5q3NveIpvLxY1R+UKvuU+wGcEZ69Tk1Va8AWQTQoRJ9xVQISv94nBOOP85qqL6E3LzFwkXBDFc7lHbnpmpXurj7GZLqzy0jZWRDtznIAIxgj8qcY2VmDld6D7e+2NDFJbu43GRY0cJtPqe+e\\/WtWz12\\/vbyGysJp7WRlwQwTDtzyTgEDBHUnHJrOmh1NLVJZJLSESMQuASycdM++T+VMtpLnSZmmlgSR7mPKGSFeFDYBXOSOnUYrKpBSWquzSnJx20NnxH\\/aGmz770NFdFFKvauAcevGCMjP51m2V+4aRWdIjtzvmwC2OcepHAx61Iur3U9tcy3P7xZU2IsqLtUZ4PPJ53dB\\/Ssd4YFjSQzTiNxksQVU9SAP8PpTpRcVaS1JqSu7pnWQQveQPLNPJdorbYSkeFLZ4XaDk5PH9ahltjBMbe6uUWWZwskka4jhwwxkg88Doelc7bapd6XdZtWlEYJ5Uke2Vrr9Am0z+zJ7q\\/ZpZGDkwvjKZwMnJ9u2a2aM7j9Lur2a5dPOtUjXITcm1yuevJ\\/nT9YuI2t4DaxTRbcggZO5gevPaotKvrZI5TcXyqJDvZtmXfkgAFuAO\\/b8ak8RanFdQ289vHAAp2hlAO4gdc4rSCIbPcvDt1aWnwzjvJ4TL9ltHKR71+diDkZ+h46\\/ia8K1uWe9Ezx\\/YzZ3DtIYl+QgYHIJ6kY7Y6d69c0LSY9e+HrMqM1xb2Jm8sg+WxGeSB3B5BrxPVr+7thFpphhjTafN2\\/LubIGeD0I9RXBiVVlTXJ31+RjiottKJla19m8+GLTQSiruYgZZmGMk9\\/Wvsn9mbXhqvgOG3Z8tD8mD2xXx3aXEs0U1usgyjOQobJYkev4V7p+yRrwS5ksSNgPbJ5967Msm43pv+uphNPks+h9H64vm6bc25\\/unFeGWt41vrckJOCp\\/ka941UfLuHRhXzz4wB0\\/wAZOOiuxxX0lHWDPMqfxEe\\/aBcibSoWB\\/hpup8oaxPh9eCfRI\\/mycVt33KGuPl5ZnW3eJxfjmATaW57gV5tBdtDJZy55jfH616zrsXnafKmM8GvF7\\/MbTRd0k4r0YawOLaZ7Alx5tmkme4Nc9qsh\\/sq7TupOPzq74ckNxoMb5z8grK1Q4W7jPcE\\/pWUUVI+bvH0LL4gnYBTznk+npXGXK3F7M8SxNMwVjgKAVAGTXoPxJXytSmxtxJ1ZhnaK89guV06QSqySTEMACu4ICCDlSMHOfevnqsbVpHtYd3poseG0j8ue2nLK7HhSccY616ZpVza6NopuBcRswsHiYdkYuwXcTxyG6+9eVW0kqXsVzblY5EZFQRtyxPvnrW14o\\/tCaKCyZ5WWOIGQBVUBmc5Bx1xyPwrGrDm0udcZW6HtngvxDoUk1hounSRQXStvvPNy6Sq0fzqD\\/e54AHG7Fei6RqCPqEz2bO8dvZyW1soI8xd5XcT23bpG68cd64P4X+C00uxt7kgi5MLPI4djuLiIsvvweDxyvfmvTrm20zT\\/FN1LcIWHlxbpPL2pGXIIb0zx9eenAx5lRx6HSk3ucroEmr6Pp0t5It5MsCGQBpQVIJcF1wcrwV5zz6V5V4jSc3bSyQAI7rMYU3ZbhsBuOuMj2zmva7g6Za291LeTeZafY8G3yHHzbGAx35IyO\\/PcmvPPE1ndXV9aWUVjIhlgUXUa7VRImbJ5xk5wMZ6cUU6tpByXRHpcsk725haNHSETRLGRtk2AsQwJ5ydyjGAfl7k1Z1C+1aXTJTcHzrdpJPMiKsZUU48svhhkDduVTnIAPoQeFJCbQ3k+o30SI0h8tod6+XhQCCBnqjdcDnHNXtT12105IZ\\/sks52B2jkn2CJmyQfTPQjjgr35Fbc7T0VzNxVrNnnXjFrK3spJ9PkkJaMq\\/nRDuuMcAEjIGAema88tiwJyoAGRtPAJPsa7jxvdTahazzSqqGQgMquA23I7YBxnvgZGO1cfaxvJCuwnrjaxGG9O\\/9K7Kd1HUyluWY3jEsTb18w8H5s4PrW\\/p8SBpW86KCDaxPmOMuw2nHJ6Z25Nc69rMJWQqFHAY9gO2fStQWck62yM67BL5eT3OCTj1IGP0qKrVioJ3OjvreGz06HUI2M4ZwmXGzY2GGc+m7GCB2rtfh9NGfCFrDeWLO8X+si25ILq2PfPrXn2vSQJ4ft1F0HWI7R8wBDAnjjnjP8q67wjq6aPJbedYfu5ULzzK+5lOM5x3HPP8AKvHrwbpW8zug\\/eO501y0cO2HCqHMhYYYZA2\\/oRXEapZTRW98gtFdEeGdI5FwHkJK53YOSBtP4+ldRpurajdRS3TxxFtjOkQPsCDnHPB\\/TpXO6NqLalZG8nFukxy0tu55lKsoBHUgfd7HBHbNefSUozbOiVmhyaas+pwW97KA0Z8wy7FXzXAyMc8cHGOldTq6w2egxXRmRB5YLTSkDaB056cH+dU2Qz2bz3yCGRsSNGSCQm7pweckfrT7nc8FlbxrvjOOZAAF+bIGCe+cDnpUSblJWZS0WxyWsaZbX9hJb2Qa7mSMCPUd4JyG5GdoBGO49SBS+GvDMtjbO11bI1yCoDois+wnJJJI\\/Rj2xXZz2\\/2aNXMkEA3ZaErgkAAZBzyTzx+VVoFu4Ar2atcx5G8rGQvJPTPfGK2VZ2sRya3ObfwpBZyyXVtZoLhkZreSMoMHIAA5yOmemOfwrobWGRLyDTLm4llYhGHyMcAjJJPQZP8AMYFMu5fJ1O3u442eORwmYhuYDBzuAzxnbk\\/nW\\/pd3ZnVXaSQrcSxK8cW4bsD72AOvOKitOTWuo4JbnGa7IYNXYpczzW6PhrUKqoV+YEE5Gc578dAc1An2aWOSecOrOigxAbs85znnOTjjNaeuxsb66kVXMXmSZ2p8o64LDH+c1jyTQRiVLbYJCcse49f93Oc\\/WrhdpFNJD31FS09rDdSG5kBhUhRuQnJDc+mc4qwIlFvCLuQXc8KhRcn74UYzjOeu2o7W2gkvLhru6CYGSwcLvHJA9Mj5uOuCK0Y4VhgZiXYbyA0YL7uM49zk1c4qJClcxJYlk057uzsnjurdGjhN2p+YH2B6E8+vFJfW7JptnAfkEA8uTaSVzkBgFU8AA4PHqPWtWQGJ0laH5ZMxvv4yccFufYDj1rLlM0VqInkWNpwTGqqRtAzk8jIBKjGOOK3pSvYxqKxee9isNMkglEXneWAxEeQrocYzzkA457e1buriKZrSW2KACTzT3GQBzk15uYJ5XLy3NyySbkG9GI+9k8jr\\/8AXrp9N1OXUrW3gNtIbeC0IkwCdzHACkY\\/2Oee9b1Y2SdzGD1A6VbXOpC6kT5CV8pWbAbjjOD9OP8AJyNVGsWUMx06d7lWu1fCqWVHVssvsCxA4rY03Up11SK4vIUi27njjXqc4wB69AM89eT3qdftMtvmby4vOkEnzDLAlicDpjnPPTio1TuzS91Yr\\/2FAU0ya8iRZ5wwuYUHyMQCOc89MY9MVnaxodlpdodQ07z1d7gwrhyHIx\\/s8kDGa7PxZIbfTLMRMwPO7A744\\/H\\/AOtXI+JtqxaXDNJJl0LS4OeD74+tTB3Y2acVxdvaWenwvu2xF7lpGwMkEKv5eozk1zmtXzNYSosT4huMSMxODuJXgjAIGOOf\\/rd1psdstqkQjn2PwVVdvOM+w7V554+uJbTTbywjGI0kTBfDEZGfm4A64\\/wooWlK1gndI89g3y6j9mtIv9dI4U8\\/vCzY+vavfdP0dY7G3tkjH2cIIwquUZiQAX5PTB9z9MV4z4VtbxvFFlFb2gneGMZQYJJ6A+mec\\/hXu19fTSb4Y42gnTGHVchxjIJOQefYcVtjZPSKIoLcW7SGVS0MaSLGvyBHAxgYPy46d8enPNcj4waO4061iiti5mJQGNf9WvBJXgjgZ54xmpPD8t0uvzTT2kcK7Ar7W4boeQuc5H5A8mty\\/wBIlmlezjuWgGwY+Uk7Dl2XpjDcDjPBrjjHkkje90QfD8LNpmyeNmMZZACeUAH3h6jt3PB96tpc2ltONOl0+VIGnKhmhXY+TyeD7fzp\\/gW3gl0l9PurOPdb5A8t9m9gMHDdzkMauEwm8dVs5CilUV1ckBsYJJ6D6ds1FT4mOBX8MXtlcXM1rbu8Eih18tkMcgwcZw3sR046VQ8WalqCaWyWFrcyGaQh5XYqyqpOOo77SfopNZ0eltZ6hdalbKjkSbF+1swbzGKgjeMYB46en5aepQ3esarbQmwUQsrzN++BKMSUwo7dwSRxk1ShFa9Acnc47Rhr0GsR6gY\\/KMXPkvJuddwIRTj72crWzq94+p6dNeXlsLO5jG2JiNsjyDDZyRhh6dun0rV8UaM9lLYzw219vlXyRJb2waOFRznjkHkjd\\/8AqrL1O8u7bU2sVu4inmKjmaJiyhmBbB4yOegOOvYVrCV0rIme92ea31xf2Hia4uXvpJZQHWRpR83zdchs\\/KCPbOePWu90Czli06zF7IJVWAhDbDbL1BI9yc8nPOPzzNeso212GS7sRNA00sk8mcrJx8m4nHHzKcflXbaPpstvoNltu\\/KM8KMXRAc9+cg\\/ga7HO8UYNWZynih7CTX7S20+KUzuOZfLycYY8nrnhR+J5yK4q+aJoTCi25lxkRH5X9cKw78Hr3r0\\/wAfXcMEyakkBlWIEExKrEZ6nHp9a86hfS5Lj7Xdx+c15FmPPyhUZV4z6g9f51LXu83YuD15e5Q+H2o21veSCWZXilBcG4QhiSCCBtzk898Vt+IbC4v553haFYbZfLQ7MFMDb1GMcE8Y9+1Rx2dpNBb2cenwwRJnyivysRjkEg\\/NnHJqe11CF7wrPblrcARSxl8fKOcZHI6dcHpmqjXU5XSsKVJwWpREF5BZWjXMVpIHjAMoUMdoPAxkkkjIzxirvik6Fqmrwy28MVlMyAuVkZk3ZJHQEnPPORwv4Vp6ha\\/ar22trHykaOIFZBuYORnC4GM44yePxrLvLM6Xqmy4II2BpRG21cg5CqehGQprRLUlyM5LaPTJYppv9JDA4lAxIASMZyOuD0HJ5qtrt8jA2UbvMmS+QCGz0HP4\\/wAq2b2XzLm4mJiMsXB+YYARecge+eeOvXrXJauiX8zyQw7kcYGfl249WA9e9S4KU02Z1XJ0+VdR1vcjzPIZyiDnjJZz1P4eprrtKuPDtroK3qlUupAylugAHUn8Oc9ya4m1tbS3vj58zhWXO5DlgfTPXH861IbxIlL3Mkk8mAoDxchgccA9TyPbis8RR9porjwidFmxcONQ09GkkMsikMGduEyD8uMA4\\/P61m2Vrdi7WZVlm4OxvNO0fKQAcEA9vpitGy07yzKYoAsQAHC8s3A3H8P880ttdrOkaRSpHCknlShlO4++PTqeaxU3FNR2NpxlKSZmajZzX9m6ahciVssyrErD09+fpWRa6aWud11az3ce0ru3hAgz39K19YS2Ekj2l2428tgHaFycnp0H9akt5Xayng+zm9smi3lw4UP04Bz9TjrXRCpKMdNvuMLTlOzR1HhKC3fQ7XVbaKC3mslkjuJFR2LJvIxgEtjGPSvV7TUNHXwnaNY+U0bgsZQM+ZwBnHU8HGOeB614b4bk1HT7oWAthHaX6qh3RhWXjkEBsEHAPNS6rrt9aapFbNHe2MCQoypbk\\/vGwM7VOADzyc9s1UoqTdmWrpXZ6Brd1GLaG\\/8AJIktJFMRPUA479SOh69qpaNqNtLaLehPsijLSo0WHOW5JBOfQ\\/QU2x+yXvhe41WW1kFowUQRzzHcXx8zMuOT93H59+MDU9bt5bG5kVZYnEqZkUsMR7cNhc4yG68ZxWdraFrUk8d6pLF4ps10+Rp4LSVZJGjORkjDAHseelcnr+uTajOrXA\\/dwMXRGkAjBOBuPHLdOM8Zpl7NNdNO0U\\/mGU5bcAhbPfH8R56+v1rHs4Lh0WKKJEViRum+6vqTxj0H1NdENInJX572iRmXzZPMuLsM45USpswmSQFzyfy7VBYymO2eRrjfHKxBwMvGORnnHB+vatOXSY3aTz5o4gjAIJGwpPY\\/y9qij0uCzMs07Ruzy\\/LxuLDr0HTvxirU42MXRfN7zM68n+1ELI+yP7gDxYfAzn2zXp3wj\\/s+bwtKr3bIVuW3b2+78owcdOw4rjvEmky6XezyyTLJGuVhkh6MDyCB6c\\/rTPDN8NMuJ2aa6TzE+XzDwec5IxyDzTupR0NIU3CZ6t4k0CHWfD+kTGOWJLKJzvhbaQOehHuPWsT4UXk\\/h7Xr1dXNxJaQZR5\\/LkklCt9wFVBJGfTvnNdDonjvQJfC0emnzJPKgCTQkmPdux9wr0xzzxiuV03xnp1prE1zNAtvY3rvDKFnUSRKOVI45HUE+4xzXNU523G10dceW1z1bVtT06+i1xHzNbvp0BiYNs3h1YgZPQ5x\\/hT4mtpp7K2eXfFcMEfy2zjALjPvkY6V4xe+LdKh1WGLRtb1Geym2RXURTdhV6AMeucKAM4HNdz4V1dLjRLS7+3JZbJUVp2IYEYCkEBuuWH5ippwtHmenqE3rZHsdnLDDaOdhU4GD0PpxmuH8QXEGueLUjLo0dhAeTzslk+UD2OAfzok8ZQ\\/8Iwkunb7q+md0QbAEVxuAL5I+X5T0z0xXLaTerotzcx26Xuq3dzseae2tmKGRsFtgPzEAMOeg6cHinytPQFaxhalZ3EviW8g+z7HV2YBSQdp6Nn8jVSwtI9T8Qy2E0jSxso2uCQwbHPTnnpW5Pqem6vr87ma7spyqoI8YJGeQePl6HvjmsjwNrNrd+Nbi4liKT7g0YQBRtxtz\\/KuuLv9xlJ2TNLS\\/BA0C6\\/tG31gloyRDGLYoHyCCjZPPJPQD9a3fD8t1c38USw+U8UbEODtRyCWIHvwOKTV49Tlu4ZYfKCTl\\/NVhulcLwhXCjnBwenBrT8Oapbx6lFYTxC2lkDeQlzHj5vlwR2Pfoc9c1wRcnO7Ol2ULGhYzW2pXUGo\\/bXLgO5YOGI4Cj8uePcVqa8LCdLZGlkYliqHBO4gZIPp1\\/lXDaFoGpW93qQtNUgh8qYxqpYgNgngZGK1XXUbP7HPrE\\/mwscKYtvOWA4I684GcZ+tbzj5kRZzfjO2nvbS7upUmCZyygY+Xtnn2qPxD4T0Q+HG1ASXQuTpimWOOQhDhRgNwcAcn8OKb4paTU0urRVlVzIVijiQEvyMYHX2\\/Gi9uxeiWzuPIF7EohaKON\\/LO5WGCRwcErwTV7LQlrUtWfiiW2065js1MIeEMhdT85OMdvQ1leJNWvJtOuYYlDJcIY2WOTHJeMAD\\/PrVi\\/1a3vY4beKeARRlURGAGACexOea5\\/VNVFxq+mafHHiA3OZSi5LZIAAHfBH41jCHvao0lL3Tq7\\/T7RdGuL26ZYJJk8uJSgLmMHk9sZx\\/OuQ8T25e0ghEm5EIxI\\/CAZyOTxXd+MrORYrS0AEpu7eQbNgG3GMZx0x\\/WvnPxDHeWlwba7gjypxuA4P5VtRSnLRmVRuMTu7XUjNO21XHl4GUJwTjmrGl6vLbTyII32MzbTMS7BsdeeenvXMzzeWwMRYTZyGK4VR7nNT+Hb2RNdjnWLzzFli27KgnjPoOa7OWT3Zy3itkdNpmrqLwXMstvKsmQys24YHsDnv7VavoRqMzEuWeQMFYEHcDk+g4yT059qp2UP8ApzTTW4ikLmVSNgITGc+p5A\\/wrQsb\\/TxOyz3J3A\\/IItm0k56kDjHp+dRCHIrIc58zuc5ZzPGJbW+GY+RGAjEvz69h+X86mtLmIusQZSqnBwQc5zxtPPHr2pbi3VL25hR1WMAFPMXiRck5B4+lZ7TyzNNK0aBUfCRBCoYjoO\\/8qKlO+txwnbQ9b8BzAxyQ27bW2KzEuSQf4ggxnnP\\/ANau1Om210w\\/eSs3DkLHGiuAOM4Uk8duleSfD+61Br23hU7BIPM3SKRuIOPX2PBOD7V6Do2vXEHiKRr2doFPElrLuQxrkAMuMhh83XtzXBXoNtq+ptCpbU3rIwRSmN4NkCPtC5Gwd\\/unGCPYDvVa+03SNUkilkS1klWBgYguzaDg5yMk9Pp\\/Ormq3rxILq206WW3uEBa6jfeIwOThMjdgdwO\\/tWAFkmbUtSt551S6nSNoki2s6qg2kMRlc5GQN3JJGCcDlwcWtzTENPY888W6dd29tHMlm32eDZskjkI+YA5BznPHc+\\/WuXsriYmSSMrPCSWcEL64yewHpXpPia71O+0p45bi3hZEaBlKu\\/yOQA+1gOeOfTr348yw7Q3UsaCOKHAlVdqmTGOAOpJPbNe1B8y1OJ6M7nw8qFZpCAs8sQfezb\\/ACx6ZORzn6\\/SmXkVvJLEbuSBRHsae4ikVRiPJwc9TkKMVhWDSqYprq9EMZ+WJG2jacHOT6npx0q+4tNStxBFIwJByiTZCtg9Wycjpz\\/Ps0tbhI1tT1C01PTxeI7BY1JQzxgqw\\/h9sjFcvqdncXKWSsVU3TYCOwymGxgDA6njGcV0WhTWdxatY3UZi8hfLhkgJZST13DPXP8AkduZ1U\\/YX33Mbuwy9tFKMrgkAMcY574z3ORVpWJuLeWs7r9l1CymEtttiJTB3YXJJ243Y4x1I7kU4WIv75by2FwYIyyEMAgifHy9ufp7VRE7eZDayQ7WJ83znYc888gcDgitg3W53GoOkNlCu6GFAFRnPTKjkjHfn6mjl6hexBZ2i\\/ZhbapcR+WF3FWwuTngbRz3OSR6VW1iy0q3mCQ\\/O3LMgbzEUY6qe4ySeM1ravfXM9tp0Vu93Gl1xOFYhtoPOQSccd8VjXUdjHLMtovmx43B7lA\\/Vu35AUmhplzSLeyuLFWMLGeFAAzo2M89ck4UgjGP61z8l5GLwWwWMRknKjg8HPBPTv8AkK6G0NwZolvNUj8h8+YluTKAV2lVbtgDuOnTmoVNhNrarYWqo6XDIJSh28DJOAB06cfrTSFcy9bsbaON\\/PDeZ5ZEJZwDgYJ4x3P4iuf0S+l03UZJLaJZ5CvJmAcA9u\\/AHrXQrFBcakbVb14pnYxyMYySW3c7M52ioprbTNH1RTJBJOEXBDsD25x03En8v5Ow7lWBtS81zDbwvcSZZnuHyFBx0XO0enOelacOky3gknvLmJGVVZ8oAoJOASBn0znAzWfvkNxDdW9zcebI4RdylmTjpjjjj\\/OKdJ9uu\\/M0+2RPNg3rL5jHfLyT83pjtn1oAv8A\\/CJPceHmvLe9lvBF8zL5fyN1HXP3uBgVh6ssMEMaXFw9u9tIwW2K5KMM9foR0rqLPxPdadZJpSulvDHH8o3ZLvkck5wBkk968\\/10XEt7iSVpTKdzlh8zE81Ebt6lPRF7TZDqF1m5k86SeTbGX3Km4t1wPYk1p6sI0txaWtr51uY49k85VCTzkjgEjOcemPauZsBNPOrRuU8vGFXjB9h68VeuZ2vkjmmaKOGBdkjKFDMQPTPJPFJwvJdkNS91lq1Rp2LI75DMzIVLs3fr97GAe\\/5UyCGeW7aNGWGQj5uTlNuMnk9Sf8iqdhNF5qykFEIyMEnFQXN0kju2xi5Y846j\\/PvWpBoW4jDzM1wbzyYyI1AJUnHBPbjnjBqtdLaSkHEZbYBujDKq98c9eB2Heqsl1cldnmh0zlgrYA\\/D9Oac2pSRsEbDrs24HAx68df\\/AK1MRebTyyvO0sRiXB+QAD8BVW4ns1hWKGPzC0hy75OB0xwRnPFMS6jEbxQhsSn5nZePyqW1WyjQiZVmAc7HDEMw5xge+O9AhL2exkVYEtmiYDcxRj8xHTr0pm8PdbZgGUAsu0kgcfhycDmlnCi63LbsodC2JG55BHUfTvTktwLhWhMYj+VSpfdkkAHkjHr9KTGifzUkij8y2iBJOFV2JUn2zx75z7UwrepciV4zJiMF+PuL27cH\\/CpLq5too5kRgzlycbeAB069O\\/A9qhN3LIzzySht6Dczfxf\\/AF+c1HmWEV1M9vMB5C20bqWCqFY49cDLDOOtSwRrc2xmgdpHjAaSWQAKAD3yOSSRjB\\/+tjqfMilClyMjKg5yM9T0qR5H2gNEkUZwRsHT0qiTYtz\\/AKWPLtpsIGSV\\/wCHPTrjGMg8e9RW0kkIWXeGZclRtztGMZ\\/Oo\\/8AhIL5LXyBs8kgIcIABznt3P8Ah6UzTRd3xEKNAIwRlpXA5Hbrk5pSkoq7Yr2N7S7CKW3We5Z3OQiRoF+duvatG6itkLrFD5BaQDao3ZH1\\/wAK5xZ3FxFau7KoY7Qv3d3A5J9q2YCPtCwi4BeNdxTgqD65rSMovYVj6F8IxvH8O54kkdHSDCqkmCyntkdB6189+JUgtPE1xGII5lcAoSm1juA544PSvoH4bavpEfh+K3vHtxdeWVwjAswxkdOuemDivHPjTDY2njeR\\/KlE0sSARcqAxXJbPoDnjGK5lFtSuhVkm7nH6QVS4ePY24Y4HH1zXoXwLuDo\\/jOGNJQUaXBA6qCeM157p0klvIw+UyNxuJyB68etbHhK8Gn+IbC4Eql3n+cg8kbgRn86zoOUcSn0djkmnzM+8nk+0aajj+7XhPxltjBq0F2oxk817L4VuhdaLEc5ygP6V558aLLzdKMoGTGc19fh3ujy8QrNSL3wjvfM0zZnOOMV3lw25K8c+DN7gvET36GvXd+UrCrG0rmkJaGZeLujkX2rxjxLB5es3ER4DHNe1TjLEeoryX4gQ+RrIkwfmFddN+6znm7SR1XgVs6GYmPzJkH86zdZOLpxnhlxTfAt2C80W7O45x9aXxESsyt9RUR3ZbPBfij5iX37typbjKjJPPauS8QaFbWFvZiMySvcTEOWIz3wOnHTnmu5+JVrJNfxDy2C+aNzkHaoyOSew6VzHie2LzWsUVxJKEkbzHX5iMqT+HJP514eKSVVnsYRr2aKPhqwWZCIFRnt83hZsBXWMZ24JBY7hjAxn1r0PW7ZL+3luJNNFyhkhlupo0DuI3feUUdG5zxz0rzjwTM1rcw3UXlMQZFePzCrEbcdiDjH4cV65oFlqK+Ho9RigaWBpUfaX2CQqrEgH1Ga46kep2xdjY8N6rqA8O3MkLQWptriSKM3K7WZFjztYLxu\\/dn+dZ8vibWofFcttf3Imgv7hltBwcRYAUlcc4XHcHr1qHSo4m0W\\/j1adBZzzrczzyEgglJBj6jP41N480eHSdW8P6pFI909yuDM2Nhbc4ABHqCp\\/CvPcY3s1udKk9zD16aUa21\\/pni2W1s5FZ\\/NaGSRZZQq\\/uyn93ezgccADHQYz7TxPAPEN3FfzFb1pRBljgr95Wzgct\\/I\\/hV3U7e3\\/wCEmGm29zBZWhm3y\\/aWUKgXljknH8LYB65ArnLC2tJdbmTV4G814pZpPNJdsk7wxHJDFdxx7VTtGN\\/IS1Z6g+q241DTtLsNRnmuBizT7ZiFURsHbhT0H7xf7xLsOans9Ltte8RPFq8zi3gmLwRbWRXU5C\\/MMZwMDA4+nSvF57CIwXU1lPLbrFdoyPyMZxtbJGRk469wfSn2FzfQ6rGJfFd2bwjcxkumKgsf7zcdcE+tSk7aSC3dGv8AEp47YLZwLC0EZRTOkhJbg8ENyen\\/AI6PWuRtrlbdiSwOASoA59qt6vqFok1\\/b\\/aReK0okVsg7SSc8jj0qssEU2JpJXEOzKhQGOefTtXZD4bMxluWbJLu9uWS0tWnlbnbHl22g4z39q6S5XUJ9EsrKTSppFjuRI6sm1wckEbm6ZOB37Vg+GdXvtE1qK9sFCNLC6Rll6ZHGffpXc+HrvxJqlhZ3t5JbC1SMiGPygSSTktxjn+X8+PF1JQV9LHRQipOxhagEttCvJBp52OymNZMExAkjdx9O\\/citDw7KYrddRF48lznfJGCzBh2AJz+fsRWlryXEcQgg0wXInBVQZgmGPI69eg9OK5VdJ8S3qvqDLFakfvQFOAoGOAB2+cHr61zxkqkPedjVrllZanfW+u6aIjJFdryhG1yVYM3UE4ByOOv4HrVm0S0uLcmWWGIMVK4wqjlRw3Vj6DtxxUfgG2W30cSXkUckrsN7+WBvHXOAMdfStqDTdHutju0OI5X2qWGwZJyMY44+nX6V5VacYzaV9DsjFtJkVzfWyrFA7pFhgiHgY4H3TjA57Z9K2wbOW0xdi2bYQAjsOD3OB6jn\\/OK5bXNH0y2Dz6elpG8CFt4UsSCCCCQQenTnsK5Sy8Ra6FjmvrQ26CVo\\/MgjXnkgfJjk9SeR0NKEfbK8XsD9x6nfahJG5jEUSRbMEwuwOzDDaM\\/jV1pZLeSRoGlMTKhDvIwDYGOBwBnPJGMjHFchp+s2JuPOsruO4uyTGyiUBj8p5KnGP8AOK6HRtXZLIfa4XnUBg67DuD7+T1IIIrRU5R0IlJMSeR4YpoUEpMT7s4KghskcjGMD34HY09tYSy0tfNd5fLA2vIoGCuMkEKP73fNWLy2hlUMryBncliG64HGcYz0rK8WwwWOlW6QSRvc3MqqrFiwVvXH4UJqT5WHLZXKMmtzGNUnggkaViwMILsPmPzEgD8+lOvoWbZJ5aBYxkksTvbaSSxz1PH5HPFSnTdLs0jWGzmlZk2zTFz97PPU8DP86bqlj5GnzJaaeY4iOS8pHXnJXow6nGfzqoVItqwSi0tTF027SF0lEPmxyPuRWIwE559Ac9uT\\/Otnw9dI7SKY\\/KTbuMIwUHX+fp9elcPb6kby7aCeOK2ET\\/MQvy4HKspxjB9O1dDpbShppVESqY0RZYlznG5mAwQenfj6GuyvT0fcwpy1OgsYV33EnlRmaNCd75JUlj0B6YArM1WWRhOoMQJ\\/iB54xnvx1PFaWkWl4bWczyLtlQ7toO45OcEk9uOlY2sCO1LPbJhkjZQGGVHue555Nc9FpzZpUVolWy066vdRWa1mmi+yIVnnDH7qjOcHsBnHHetFrWCKyiiicAbRvByN+AMcAY5I5z6+tMbTtct9L8zUraIWzOH\\/ALzO3PfGOv6VWtZyQ8t3KbBsBo4FfdJKDnnG3IzwBnt9a6Kkua1mZQVm7mvqFqLK0ifEMCqoBSPjIxycYyo9PpVCOQPPAyzBpCTsG4jZycE89eCPXk06cSTaRPIzQqwIYecdzOg55bse2AMc1T0sTz3LSLGAjrvlTdt2jaQoBVscnOT9aVF2jqOotdDTKXM1tGJdSnkKDzMNKNmATzhh1I6fSmwL9v1qOe5uzFEsOyEhVLSdRuCnjGRU1joU4ObqCCCCRC7fNuaNQmSuCOp9eo9KzdS0G9nke40+e3TgEK69V7DcpyP89elTzQelw5WjsLK6E128BuHa2iUlpTjPI4xgDrz36fr5z42mjurp7aI5Mkq79\\/O3YDuYnPOMY7Dn2rV05rzT0lbUh5MImVBHbvvJCjPJwBg4HPH503UTa3GjXOrXAjH+kBIsbcqnIBxnOehyeOaulHkldaik7rUy\\/hMyXXjm8kG7y0tzEo3kAfMF\\/D6j0ruvEeozxaZLDaB0WJysRaLLbgSCPmHTqPz+tcR8Lby2nl1A2rbbyOXYrk4BRfmIA9cnA9cV28uovezRmSCRk2YJYFVXbuyQMYJz681WIV6upNN+4ZmgC\\/vdLtry\\/isheyXLIIogw+XIXpnqSDz046GupaQ3Bbb9o+6qmR\\/3RKnGefxwPas6wEtmLaSW23W4UGXa4BAbBycHOcnGB6mrOo2uo6fEE09CIt2VdiVdGKDbnHb8KyfxF9DptJ0e2nto0iu0BjJZZEX5lJJYnOOAQTj69qzBHarJcNGkiqcoVQhS7HbgY9OSPY1H4T1iyn1FGvJPLMUZ8zLgIZAAuef95v8A61bLML+wurgs8VusLBogoGXGSQMgc9s\\/l61Dhd3Y1LoczpVpeTaxOl3CtvZEqoZjkAlQSo56Ek8AknH0q1DbPbW5ubSOWFIyys4HAOfmAH1APGRz9KtX1te2GhyyWLyak52+bGDgZ3ESEEZ2425wMfzq1Bq9vd6a9vZwPdWcwxGipgP85BJz06dc44701FSVhczuc9Lc6tNFc2a3zWs5RGSPGJPvLyCSMhunt+IFcr4gtr23hvPtqyyNFiWOTO2RsKqghc8Lkjnnk+9dnq4jl0+a5eBfO8x4kQy4LSZOACcgAY6jPXjmudmux\\/wltg5hH+kSP8igrt3LhAQzE4AA446fdHSt6UFHYUptkenyw6nbWZuWmaSQCaYFB5YVo8feC4HzEkZ5\\/Ck1CwsW1KWxU3Ebxw+Wv2dyCoQdyD8vG3A4PU13cmg2draXIGnov2sASLEu1sKeG+UjOAo46\\/nzzmsWN1a6ouqpqaC0uY7eGRCnMrCQjgA7c\\/N2GeKtRvoRz2PNvFUuoX+inTBcxO9tLviZ0PmHquM4+br19uc9a5nVbphp2nW0myNoo15xkK3t6Z6V3fibRdaSadvtZBC8wwgg4wfmIyOwHIzzmuG1pgkFrDeW7q4kG+RlxkFTjH48c+ld9KFkkc8p3Op0R9Pi0QSanctHFJC2xcEENjtwQemKxhayW32eZ4EgF0flVoSpdgCCB8ueen+edEvpq6XcJavDetESrqzsTgbju5bqAvQVQvJl1XVIbG4uruZ2VRGXkUxx+YQdx9OvpXLH4npY3lLlS6nQ+FphJJp0RP2S3hBUozEhWP8AF6Djj059qh8TwxNqGqvGluyCILHIzhVUFjnHzexGTz2FXLKSHRNbhIvreSIxmEuSwRW2nGXPJJz29RzUuvys63F0Bb3B3cRRqXB2jgFug5Pr04znFUpq1w5XexyOlaZNPbSzyT+VMjbghfjHO4k+nGactozQTt5UNtJEp2DdwxDd+vp1961NLu\\/tP2S9M9rHfSKVmiiQR7wQcjqOgAyPU1LqFrINOie8gIeaDJVMEcL7fz4q3HnRKlys4G7K3F+st2yDzAGZbcgcnoAK04pEhlYNLsnVlZpJ12sF\\/wCBdT\\/gKp30FukljN\\/Z6S7iNy5KhxjHOOcg1p6Tb28tvdi5WMyMDkEjoBxjP1HT0q5WJje5QttZa3sg8sks8aKzbACqhjkjp+FTIbX+zYdUiW5lYOxeAjC\\/MDj5u+D\\/ADxU9ja295qMNndJGweLeyx9lVc4yTjPXpV66vWtt9rpkNvLaQIrIg5OTx8wxnrzz6VlUcYu0VqylzS1vojO1G2EIeONTaqzhykijLsPug8D5e+P\\/rVc8PkDSXOoJFIkDbog6bvMYHAwq5PBC844\\/GtWPTZ7i1V9SUvKP3pMMfzN14x68fzqC9W6bU1ijjgktVViiQgh1X5ScBhg8e3WsIT9r7hSUovnexNb6rBeiIpD9quZJMkRx4TAHZmwF9Pc46ZzUV9cXK3\\/AMzvKU+cGNSJNv8AEvmYPHJ\\/DNafh3Rop0m+2W\\/2iYyIqYUxALnbkp+PbjirHjrRo47iH7BLa2LNMsbGFcMvTpycDgHoOtL2UYvQ19o2jCEepHw9ex2k0LeZMXyC4I5AYdcAng4I7+tNnOqWoi3LLPbSYe4a2csSB0GDgkcDvTb6xvdJkXZdEo0pyyS58x+NpK9M4X0rTW80+LTZpL27uGuRJukQSbc5xn5euAf7vHtVSc1qtUKnKE9jEtJE+1pc3MUdvKT92QMNpAJBI4VcDH41JO0GmzjUtK8trkTHDuqSE8DcQuSV56HHGevWnaxqMLRRRN5kyMnytAM8YIxkgc8dPbmudvJN33rSV0JYkGLawOOAfXPUmtqd2r2sYYiTimo6lJ7qQzyrLbNJFsJA2AfMR15HPXrW3YT6gj\\/a42EUUi43gK+0FegByQRkHI5rn4zDHE1xI7yFeHR3+56AZHtXR\\/8AEuW2F5pxZXPzSRtI8e4MOQB2z1Hb61c4nn0pxjP3l8ykou3iW6h854BKIVikB3KpP3lx2FdZrumXF3o8MzOkAji+cHG7PGBgfj2zz1rlFuoxbgizvYpUl2+b9oUZ9z0rpNLla5sgDO7uUJSOQknknPI78568\\/jWVVNWZ6dGV21c5iXTbqS0+y2i+XDO+0LKoYg98HGV6j6574rPu\\/CN9FPFCeJZ\\/uRlhuwMDJHb9K7i4t7UbvOPkIsm5UYYA4APrjp+lUbWaU6vA9spmnLlY1A3OztnGD2+pxThXk\\/hFKnHqSPZolg9uscVlIQm6NEA+T+HJ\\/LocnPtV3wVpml3+l6rZyh5zHPHNE7JgOCuGXPKhuO5FQafKlzaXMF+s91eEMV8tGPOeGY4wcdOOOevrraDFP4etJvEbQyXEsc\\/kLAH+UnZyTgcg5XjtWTcndX1NrJWZY1jTL2TTBJpEENpYIAwiinWRn6gEh+h9xxweoFFhq2n3Jvr42sUN3dq9qGCgTwkL8x6hShyR16DgVe1251a3t45Zbe3ms7yGIW6ySMq7ABnKjnp2B68j0rmbi0vLTxFdSWNxDeLhmR4pTGyYXDN8x4GGJwM9evFZUpSd036Dko2TRHdQvqELLpl5aWioMPJcOUkiUPwdwOG6g7j9Pry9lqWqaF4mh1BJ4ZRatwjKqKydB0HQn0rolgubufULm7uGuHVm+WSMliu3HmfKcKMlR3qG302Ixyi+cSzG08yFSjMCvJ2gbSQRg+neuxVHF6mDpqSNFPH2oajrthGLfUlmldgxDhQu7BG0luVHHU4PpW1qGr3s5gaae1aHT5jtkS4VppFY7SSBjHXrz9O9YGnraTTu2rRWjGC2+VAv3hjAbGMAjvjjmpNR1a3s9DsbGxgSyMqN50sBIZyMlcnPbJH+RWMneS5YgpxT5WzsfCfi3T4tGnS8vJGcrhGeMCRvmIBXn5+nt3roPtcWq2MV3pty6\\/ZvleKaMRSRsMcYwOCM9P6V48t1aT2CpfursjuWhlzibjKncAcU3RvPkgnuITdadZyNtDRTkKTgjgYGew6dutaqXWeiFzJOyO08R+IpRvisnlS5iYO7KqkKOwycj\\/PSsfwlIJ9YnsmRltbs71yuFyu5uM4749jVHT7nSrC2NpG8TTOwaVcszkHp+PXj3q\\/c3tnHap9ptbhjuOxCu1iBxnHXGD+X1rCWIalZR0NVDmV2znvEg+ypJFa3DXK7iMQqWwMcZIqX4f2jT+LLH7Su0Ebg7EAxnrnBwMj3p+uapg4g3LjhYzEO3UDsOhrKzFJKLqGcRFBgMk+wg\\/U9+vFbwqTlHVWM5xjHVs9Gute1TUdQc2dq6QrCVdmRn2gnHbjJxXAeKft2qCWO7itUaApE8nlMMyPnAx\\/eA5p95rtxLK2y\\/lQzKAyecXDBOFGehxgfjU+pavBbaBbay9w8+prcBoIZGBVWHG8rgZ4XOff15p0ocr2M5VlO6uOhVLNleC0tJbmZyGDgMFOOnJ4wO\\/NRb1dJleeGRohvby93ynAwMdCB61RsJLpreG7lWQuS4izGSMHOSSc5P4DFXtH3Tz3rSziOMKEzFGFYjPPzAcEgYzz9K9U4djSmjtbkpLJeRNGIMSOhwQOCo5OevqMVP5bWmkLJZR2d\\/CRvaVExtxjcSCd249z9cVSvdLhurCO\\/tg0Ubt9nkVVY8DJ4wCSeF57+lWfC8MqR31vHMYACFUlsZDKrDB6ZrFPUu2hQ1F4mi3pCShGVAIPl5J+Vf4mPPfoPwpunLHdSRRhljkjBP2aZMjJxhsEkZwe\\/6VFeWc97FZNFbxvarn\\/U7UYbTgqXHU\\/UdTR59+1gbuCaaJ0PJt8\\/6sHDcBhwP5027gl0NdBeC5jbYRHnexXYNpU+nOMn2H9a7LVNVkvtC0vWbWVZL+3JUoqs3nqOqkAguCAeP5VwGsPNLoe95Zkkjjwk+DHuDEHBwcE4zxzXS\\/D+ZTZGBHEtxDbGPagUEED5dzcZznABz0rGdK6uac9tDtLTx1axaQ1rrcZsbxZCLfz7doo1UAbXycgZ9Mn0rW03XNO1S1t5Yo\\/tax\\/M32STcNw4VsdNuW\\/mccVHBc2OvwG1uN8d2kPEcqoQvUDjPXrx1GM4xRHbtBAsljcS74IiILeCCMFMgq83X58bznB7cCuJRs9jSTXcy\\/FN8L3RJVEISEOSJWTypeGxnkggYH5fp5JrWmxf2vOySm22SbkiK8EkZ3KQTkDGRzzj1r1bStaWYax4f1K4sp0iUGNbdTEkSg8Ll8fMQDwOw71xvxLihV45vJvIoSEG5yhAAHQEdcZ6V20tNDJu+pyut6cLO9igvr6O9yUZYVkIIDfdYMc4HGcH61subaJBZ6bauk7Hy43BOQADng5znGK55Lq3sPtVzaW4mPmgq8xO0DaMAjkE+n0raIFpeW11hFkjl2Psmy5LZ5IxjHWuggsi9gtNHnWKSRrh5GDYUBTIvAXHA75Pr3zUHiXT9Yg0W1ecqIWG+5kfBYMDjIJIzw3TPpxTbjVbqW7Q3cMU0NvhXUoMMQDjjjsf51maLqvnXcn2om6F1O8SK5LLGSCThc8HoAfr0xU2Y7kltczwS+enmyechMJTBYDORnH3SOTjj1rHhRp3njSaEG3j38hkfIP3emCcD6dK6+9tbKO3iLPIkuFVickDDc8E8nP0qkq2t1tmjnNw8gKiEKq4HcnJGeaLBcwdM1Ge21SMXSywxor4CqCSxA\\/lx9K3rdLW002db3UizyxkQoBnj5hg477u\\/wBKoj7FCJJpWDSoQ6ED7wGM9scex\\/KobKWe2ng1drUyKZJUiRnGCzA4Y45AH9KN0HUry3MMVgkdpM8t35mfLAypXHU+n9a1nlexWwsljd7mRt58kBMM46ZIOfvHv27VSSykiElukcHmIgdWQgCTd0OSOc9B+PrVCfVriPUo1nDLNE4BLsPkwCAM545pxsJ3N2zishawNM8guoGaR5VK7uQeME5B5HQfkawbhJIru4uIpjJAWIVJQTxjqM4zgfjUK6pKkSSTrJdyvHjcjY5wAOccnH8zRayS29mkTRo87sCXBD8MxGA3bpQkMuaaLaPUY2uFVHYArJs8sqcei8fjTdZeM3F5cW0rfaQ4UsuQJFZcnjGODz\\/jSa\\/eSyQW0UkkfmMcLEEw0a56EkDP156VjPcLC1xA87M7kAdfzGDj86ewjWvrtoIYBexo7QISgaPO4YG0E\\/09\\/esrXbm51XVopwhxI3BLYBIxnvx2\\/wD1VSc3ayeaFwFABMgHp6HrTJ5Z\\/kYEZ4wqj5jx7c0DNaNLS2kJLlHZeTyct6DBrFuYWSRg0hVDIRgjH5\\/nV9jcNHmWPDKemBn6HuKjbTw0MjebFuGSFD\\/qPXnNFgFkus25jhhjAC4IUcfUHr+GahtDHD+8ckzEEgbcgZPQ5796qopiypIOeThu1StJJGWcI43D5W3dB60rBcstPcXCKp8raB90cZHvVR7acudgZFJxktkGpYy8YQ5wZEOTkAfr3qa1uI4rYgMWkkPzZ+6q45+p5oAr26ur4YsydCoPU5q\\/bTzWv70K65+6wyV7+vpmgTWFoyvFli0fOMAcnnr7GnCaIpLFHtLMcrtJwM4J47dKSYylcsQJLjz5C3AAccnp+Q+tV7i+kaVgC3DcAE444zT9QPnbpQojQZAXPcHnj8apwqwKvtyM8DHU0xEkTAykTxkhicdjntz9a0dlpDZRySQSEh3iYqw3ZAGeO3U461JY6db3FnJJPclZhlliU4Kt6AdTV7TtHtDb\\/wBoXkoMERIMSo3zNxwT3qW0VYx2Cm2Y20UmzGfnxkdB1A5BOfyp9sls2ltLJbTy3TzfJIf9VtA+YdPvZIrXa0trh5Xso3jXYSwZySR16fhWZbSO8FtZhg\\/kmRlDEDluvXvxQmJkFu02peRZIsaASAKB1JrqfBtgslzeIYheYglVEIHyEgfMAeGwT+ma57SGitLxTcwyxnaHT5TksBjH516FoOn6Nc+GI5Jt5le8Z5Y4ozvuIwoOwd8Zb6ZWsKmi0HCKbOXQx3s9lbQQmTYu5w6\\/KSMduh966TSPDkcXiK2gltjDFLBvQDIMg25H86jmsodNuZFtAsVzJYmRI3fADDO5R+XY10PjC6FpaaRdW+2e4i05CyoTklgBz1xiudvkso7MEuVHR\\/DO\\/wDDWkeI4ZtQuPslx9oe2xkyFV28MVXmuS+Ld1pviHxxeva3jT9PIcgr90AEY4I78YrH03RoHiGpX1ofMeXcwVcIQDyPasDV5U\\/4SIpZOFRT+4UPgLkdM8c811TqOUWouzsc9VOS0dmRahCY2QSyNLgYwBztP8uT39ajs2CahE+CCpAQgY3EHOaS5EsURjlSSOeQZznJ2Ecf59qo27tBcZQtlehYdKMOvdWt2RGL5T7q+Et8bnw3ZsTyYwD9an+Itn9p0qdMZyhrj\\/2f783HhS3JfJWvSdfjE1k3GcrX02HlqmeViY6NHhXwzmNpr7wMcfNXt8Eu6MHNeHQR\\/wBn+NmXoC9exafNvt0OeorWtHUzpyui3Ny+a83+J9vykw7GvRZGyK4z4kQ+ZpzMOo5qqW1iKjON8C3gXUtueorpvEoUqG96868NXRi1pFz\\/ABYr0PXG32av7ZqYplN6Hl\\/j2KedTCjjYzZYHpj6VwuqS6dpccLAR3KvKqyI8YIIB6gj+ddr8Q5ZEsneIZYHivGL+OYyF3VizMT3zXi42mp1LSPTwTTjY9B1CXwP5wufMhS4bkrEWjaPPUHFXrGQ6XDHcaLqr29u77nAlY5X33Z6DjkV5EY1KmQMSa7fwjqVubW3tJrmLzCGXkZYAnuT\\/SuOVBJHoqRu+J9evBYrZtrC3FmW8wwmIc46fNgE4\\/LrSJdahqlmt7NJ9ny29RE67E\\/3QQcdiefwrL8Q2KRuAZwI2QkyKm7AGCMHOcVlaWt1EgjXzVjMilfMiYoFzjkd88ce1cbhbS5Sq2nqX5ZobfUTC97dG2lYyPGku3BOTuOO\\/PbHpmqYXTFxsDrGrsx89j8wzjOPx9a2NLsI\\/KuWLRjbuJlA5bB7ZBI4q8+iXDzRRyLaw2zGNpWdAxwx+UE5G7GKp8q6lScrXSMO5nsJbRI3sI3kUDJWMBHAHCgA8nnJNJof2K6yWtreFncq5A4Ucd+\\/X9K0dZ0P+yLuOIXP20SOrLIgwNp6jjgcD16YqK4tSt29uNyT534YA56YUenf9KlxVrFxct2Zut+HLOWEzw3kMUiAgxrJ6d+vc1lJps8KlobqRNvQEADP0xWott9uudlyVAWUqZEOMqOcAD8TzWu1rZ3LJFJGSpAb5ZACRnABGeelUnKCtcHZ9DG0m41\\/T7KONBbvHFI0iPNGHKblx2OR7V12jeObiLSbSxPh+V\\/s8ON0Mq5kbjLEccewzVeyvRBzcWmI8r90nLMWBOecADg9q6O3s9N1SYahawj7a0XlFchtpGOmG4\\/KuSu1LScTWk0n7r1OX1XXrnxNcx21tb3GnGPHn+aNyqvY8dPerF54rmtHk021sIfsMcQWIAsAAoAySex21PqF3JZ3b2lrYO5MWJJXjwoO4cex+tcNrTTQ3VyS77FJVpnXOf8AZxRTpRkrOOgVajjqndnocPiy0n06SwtL+3jugoeJTgY46Zbg4NcNY+N9V0mSS3EkEpMhyyL2BJ49jnHTsK5q7likgTYAGc85znGcDr9KZZWsc15FCXKMzhNxXgHPfmtoYOlFPmV0zGWJqStZ2Z62PiLLqtqYYrKWIsmZfLJDEAjIU9Bnpye9T6l4rhuBFF4d0poJWjYSveREjGAfvBuTnPfmsnT9Dto7bzgJYothWRt+FP68jrWk1zbFpF8mNti\\/d28Lg9CAeleVKFGMrU4Hop1eX3pHG6vdT6hqUT38FpCYZQBNACpIJ4PJ\\/H2xWlB4x1LRL19PW4jvoyzBZm4fcQTjcMgjJB5FWvFfh3zGN0tnLFv2qu5GCAEA5z6Y96wz4VnaKGNViKbfMYBhz07de+K7ac6Uorm+442qyk7anQaL8QfETa7YWWpJaeRPnzPKVsgbcDBJOOQP1rb8beIo4pooo0SS4CbowSWbd67Rz0A5yK8513T5bcRzLDGIlPIjYKPr9OlZUFw1reCGG4kjVW3DY2DkjB+YYPTjrVLDU5tTirCeJnTTjI7GLx5I9w\\/223t\\/MLBbcAkBQzc7iTg46fjXoUeoQzaIZI5xL5pKp+83hscEjBPvXz7EvIk81mbaW56jjPH+f51s+Hri+EZsIr1YoJgygspJBPJIPUHr\\/hVVcDT0cdLBSxU22pam94l8XzXl69jbSbbWDzCJUbYZGC\\/LgjsGXt1Na3g\\/xlo+k6BZpdpJdXEjFGAfJQhuGKkjOd3fPQ1zmj6C14GtVdUWCXAeWMnrkHp6mrNp4PuI7OaQzhpV3CJVTknPXOeP6Yqqjw9uSTsVCNa\\/Mkevafrcd5aTOsUcIR0IAALEE8Fsd+MH6VE2m2F\\/fgXu3aytvLkDaOeea8s0C+8URzXCWt40pjAiY3Manaw6Ywc++avJqPiGeKCKJrVZbhdj3abjJKPqckDjnn8q4nhOST5ZWubqvzpXRp6p4\\/1iNl0zTrRIbGF1hhYSuzEkHDAADOcEflWpo9rrmuy4uUls7VmyrTqZJicZByW2jHPAHHNZemeELPU7hY9Qn3ywqCCrlFGOp\\/8A1n0rotW03Uo4gbDXrqBrdGa3UlJEJ7jBGWOP61Up0l7sN+4lGpuzP8V6np1hb2Ogm7Tz4QxmIjO5mJ2jgLx34FdF4ZtrWHSWuo3VyR5swA5JKqdv1AwK5u10rWpdVXVr6+i1SREZZo5EEW0f3QFAwcjP0pbjQNeTKWOpbIZy0ht0cAEkYwTzkDHv04qJOFlBMa5n7zR0DXV5rEMs8SR2SpuaMFtxwR0BPGfUkH6VteDIGmto55YMskQDBuNxHHFc3oNlrlrpTW96sM9wApWaaEqsQUj7xPX3z+VVdT13xbb29rDHqmnQJBCsatAu4svPzEEYzz1z1waz5U24pqxTb7HUalZ6U9zP9rluYSzMU8psZPQk8fgPxrzX4n661lPHY2txGITGCxbLPkMOfQE4H5VftNV1m4M0U+tK5ZQHZ4VZwBkgKe3Xn19q4jxXoGpR6i731wsyygt5jDnvjHJwO3WuvDypKpyyepz1lUUL20L\\/AML1a8lvRGWWcypsGOmQw59R0JHtXoialqtq0+kai0Ua5YxSBMF5SeFB+vb0B9q8z0iO40m0N5atIjs6hDGNvTIySOR69a7ZvFVxPqtjc3dvO1y7CNVgw6tgD5iV44A6Ac\\/jit6kY1G2jODcEkz0O0ikmsojLdtI4TC\\/NlZMAgnGTxnNP8aTfaokeKWZI0BbMK\\/Ntx0YdwMYqPSZ7jULq2RSsQnt8Fc5KkYHyk8\\/dz+IFYerv4k0jVWslislgnBRLhnLMwOM5GCOT\\/nnFclSk00bQqJmlbz6X\\/x7XZMrYMjkAj5SOMYJ6YJIzXQ+J\\/Nk0DdZ3UqJBEQwU45YcZOOPrkVgSWUIspTPZs8oQmMqqq6kAnaMAZHI69jWtHJ\\/aHh6O12wySuRtEr7RLhuMH2wePasb6mljb8IWySaMqJHFDudmZUw6yOSc5HcEEHr3qj4ghksn0+0tYCEQRoSgB2c9SDz1J+mc1peHhLaxW9mFghW2LI5eT5WCjjaBjnLHk\\/3eam1VomgluJJFQwOWjUtnOM+tOK1E3YxZ7SwsYUJaRjckSSB3yQ+AOc8iuD1rVopvFGnW0ZUFY1SWPOGOIuBnv+Pr716DqtlY6lp9sDE10VTfKgJX+EkDrzyQc+3vXKy2VtBrFpai02ruddigg4aJWPPYgr+tdMO5m2mdBbapHNpC3KiYHzWC+XztI45xXMeLLie6tYZLTM7LKGV1G7YVyTgduRnp2weldKYjaC5EMCC0iiDlvmI3EhseoI6njuK4rxJG1vrQu7NZdkxMbCBWBc4OT7gc\\/iRXRTSvcymyY3E2qafH9oC+aqOzFvvLnacbhxgg+n9K828SbJNZ+xPHC0fyPtJLZTHA68HnjHtW7q0ep2tkLsyJGZgo8pkb5VUBmJXqc5544xXK6ZPbat4iSQqIbfzC1wYUJVBggAZPtkV2w1ic8lZnqOl+FtMh0eeG9PlyGJmhjZ9pAK9Ouf4gcd6w5NFtdJ19klWN7q3WPzn8kJhcfdPr8oHTnqTVqzxcz2Wrb2mRCUViygxqJQoLEnlhsA5z2z0rpPiN9ojtvt5jha7E8bxGNCzscKQT6jG4d8DPrXJOPKdEKl9DlbLTZUmknlEglUJ80nKuTtB2564+nfHtWPqkU11qN3GskwmAaSSO3wgB\\/iYkY9M556H1rtNS0hJ5NP80uJZZtxcOV5PALkHKgkqeQB25ptzYebfXFtEqTxmNvtEsLK+HVgdo57gKe3J7CsmubQ0jJrVnA2GoW6yuWg8wBURpYwVDhVGMk9Qf8A6\\/etrUPEVnqOiR+XBLbXjts8tRhcscbucAr071DrqQRFINReOBFCLDD5mGOVH7xwvy9CB9PzrOS9sEJsTEuMuVlRxhQOgxk88f55rRNrRENxerZi20N61xbAZLrIT5fQjrgg9f8AIqeyiZbmdGtCr7BGWUhtzhixbPoQP5VBaTQDUpGM8j7Yn3D157AfWtfSdUeadXKGJYtwMLEnJA5OM989aLyc7NaFWXLdMoJB5UsjIUE7N8zIpChRnjIOeSPWs7QLea61Z54o0WBFaRk3H5sc459PSt6MwzX07YeNJWkLBWwV2oXG3J\\/vFaxYZ3Fi+PMjlaQQKyAAk4yc4OR1q7WYr6HQ3+qWF1o7XCpLHL91EUsW3dz6554p2nT20F+kbPdxxshYPuBKtjpuI56AdDVXwxp8M9tLPfNbQ2Vs6hS+0MxGeATx159eRzWxrEmkzR2724WJoY2d06s2OhAGP7pBPP1rOnSjSTsXKTlZFfU9fNvp0sUF1NAzSKsSTxKWfgZZduAo9OCfpzVBNTbUZ\\/JvCkkwfaJF5bHQ7gMgHj1HTtxTtWu7m7Fuj2SWgjAJM4UZYrkYzxt+7z1GelQrbtFpbAabFGGXdO0rqASw+XeQQGye4CkdKmorrUcXYtoNIt5keC4W5kALpN5ZbGMjg4wSKr3X9nz3kJuVM8kfzMvkFVOee+Rzx7cfjUlmyWMCiO5gursuvklWUxxkDggZJ7dD68jvSXOnzyalFBM4jwVYyuu3zATkjAGD06CsqKtJu5c7WtYhW+tb2ZFeFVgiZViGPL8gk8gE5A6HJI96l8RWiWdgHnRGvnJMcYfh0IGB0GTknGP1pttYXcto01vZxKPtHlmRwQuO3U5HX+XOK6LVbK8SGBDIuoOqCRWXG4NnACgknPsOePSt27Ge5wdvZQTuY54pBMrZMbx5LHGT9ed3T8qmzaahfQR2cLQuqDO0NGyjGD+oB6\\/rWneWTRyksJZZFOHWTkowxvIGQRz+HB\\/ChpVtP511cQfLBsIRuigs2Txx6YPpRa+tyOSK0sa01pa6Yu2Sye7bOFWVN7ADHJ9OKvHTLa7CLcwxxEqH+QENzwBkcd+lcn9o1e+uSkszROhPmOGPGTjAzzg9eKvLrFzbaYLAWk\\/2i3lB8xeR3OSfoTxzXNLD1Uk09TVOlfbQ2Eh1G2cPG0d1bFgN20s6KGG4jAGTjNc3e3M0d7tt45dqzKA5kUt16A9QfbjHetWx128t7VTdrcyQSBUWRMM4bPPGff8AnV\\/93dpcG7mWSFZGCF3ClCDjoPfiiMpU\\/jRUkpbMtSXsP9kvBZ6bcadJaSq5lSIF5N4wwGe24A4PXrx0rPTV9X\\/4R2TSlEYEgMkkc5272Zju5A7bR1Ppiqzi6uZza3kUWqC2hUALNtaIbicnacEc9+eOD64ltPZW2opZXdvPvjmKr825SDgY5PBB5\\/GujlveSMpK8VFmjp2o65qd1YaPcGSRfOIig887FGBuJz2wOvWqt1Zz6VrSy3EDo8G1s4Zl6524GPp16Uur301tq9vPp4UXFvJsWWBCVYdMbeh644HTv3q1e3F4ugveXFt5LSuixSwgKhHRt6nnuMHPUfkop2TStcUUoLlfQrRTQ6hcR\\/ad3lniIrnK4GcIewwO5x6VbtLeeNgBK1sIWBadwVfZuxgFf978gar6i2nJdQ3Dy7ZmT\\/SIywIJ5LY5AHBxgDt1PWqcEGqanNBdQSCVWJ\\/dbwC3PG7HYkZxWiVyPaqTtE1dR1O81i123IhSSAeWpEe3K4C8jHGdoyD0PpWXp2lXjyxPfMkcSbpIw2CHHTCjr3rT0+8nYm0u1XzYBuchifMySQAT6sSeO1bS+VLa200sRmlf5II2ixtJ+8xHpyTn0rnqVZU20kaKmpasp+HNOurlnu76LZCx2xwD5cYP6DHNavifyzobRRyKxYhYYo9v3utXyjzwW8hg+WEYSMgAvwRuOPU54z61lXUao099eSIxZgEAXlTzwB29Olee6ntKik+nQ05VFO+5xlhqV\\/BB5aSK12jFZJWRf3KhsdR654Pv71u6dHqF3cszX5FqA3l+ap3SMqg4yfmIz\\/n0yL3T45NaBKyxpcNtE4mCpn0I784\\/Krdhr08On\\/YRALwxjG5SyKV3EcdyDxnNetyxkua2pj7Tl0uZfia+lvL6aG51K0dpCWuFtkUIi54Vf9rnrWe\\/mQWsnmQIduSrSE5x6gY54rZ1HSre2jOoXSRQTytukMS7VXjPH6fjWXPJaSxRtE4lAYlHdtuPUEEc\\/nWkJqSXLscuJdtH1Mxwsro8cZVBkfLHkrn1x\\/npSOsolgLjzIoyNwyqqPUZOOeKLfF1qaJbZjdeU2AHkHkkmtC8eKC3WFXkncHsAAD6HAzXRc5m7Oxq3+qTC2TzxGTBL+5YxKoXB5Cr19van6W39tXOX2i2QhTtj4BOcnGMcetaGo2csVlDcahp8S25HlwFpG3SLyc7Q20YyMnFLHeR28Cq+9i2f3EexVUkeg5xnHFdRZs69axppa2tpH5NmkyzozJs3Pg7uCAcED0xyPrWGbJbtm1V7aCNG25VCBGR0yR1z+PXtxVnxbr1wdHstlrIiYyfObzMk5GcHnpmues9RfTb9mVZnjJ34EhAYkfTpnntWdtSl8JraLYOun39tBMp8ony1d1C5PXGSGLccY+p4p+lgyaF9uWVp7m0YR+VnaixkscZ7nPPXHNOS9+3JEjwOwktnVJYwfMDf7RDDI9\\/etK2nfS7VopNKZZJApjElsWVQcBmPBJHGcE4+uamN92ipdkzCCefYrPard+UARMjQqB3YLuyevP4VqaJqt1b39xqEsMUztKrLEzgKpCjjb\\/F2BohguoIB5Q8\\/wA5kl8xLdAu7DY+XHyr+HaqenXr\\/bvOvVi85plijnaMARgDnC8Lgew4P63LaxMT1W11eZNL065a4MkkHyujIyNI+MEBjwce2MY\\/CrzR6RqBN5e\\/Z7aWC58uSRRtdMKGMjFVyTnuenHFed2+r2UrxRtHKbkSfMcBi6c7sqRycDr9K3tCvLWPfaQ38lwLxGDiSRi5YKwXIPHBUYyDwa5+XWxclpdHQ6PoWmw6jca7IJ52kYG3MwCKoGSMAnLcdeMeuMVxXxTkmntf30LhgAsqyREbCM5K4+9nb27dT0p02veJrK+t7fT0aaS7Yu26LdsK8kr7bR+GMjFb1j4p\\/tCwWx1GOa7mu9pnVo+M\\/ISqg8Z2nGfriqUGpcyFfQ8usYB\\/YV42nkuJBiaSVAhQDOTnPPGP0HNdjLpUt94XtH0m5hCxRq1wZ0K5O4ll39Ouee2BzWu8Ol28WmQX8JtrU5d0jQKk+OTkDliOOCMDn1rQ1rTbfRnk1zTIIBpkqbJbe5YssecDKqeh5Hy5AGPeiUnpoCsee\\/2ddiHUopbQhlQNC9uzPs2H7zgj7pH6HNc3ogt4J0jluJCsDtJ+4QB2c4xknqOvAr2CW0tLjTbuRWVbo4SSSwhwJYpOccZyOe\\/p15xXk2paVNaXdwXgYWq5kH2hNo2cldv1zxzmrUtLiSu7E15Je30QN45eJwyB3UHYTzx6Vl6XZy20h862meMDGFAJODk4B7EZ6Vr28lhEHeQGBpYiHbySVAwCCF556c8dvamwXc2lyztp8D7pQUKyZ3Mj\\/dJzyuf89KYzMmYMXnuoJAZTvTI2kHtj17elWPDd5LFDIU08T7XHyypuUN2JzwSfTipRb3k6zJqFysKoMrEGAkVT\\/F05UcUzTrq1063ljN02\\/GThsE\\/QnjI9O9OKBjZ9XuLZfJNp5as28EDoA38Pp1PtWLdXcT6gj28R8rflkJJJVT61uaoz3TQwtBGskxJkfIJQDnpkbfxxWTrfmafehHZPNYcyIQTjJHqSOc\\/WqETb4Y0KG0lBzmIrINgH+0COc46CmXGmPFAt2Jog7ReYYW4JGcAn8MHtVGTUZ1DR+c7BmG4sck\\/jVW7vrlWeNZW2SKN2TncOw+lS1rdDvpqWROlzcos8nCkAmLuBz19O34UyAN\\/aj7PM4YBWJwBxxyP8KgFy7We\\/cwYjbhDjIyeMfXFGnP5ckqIMM2CCx54zTAuQ27yZnnliLBiArHAzjOTx9emar3lzbxyBoYId2Ml+oJPp6DtzTmD5V0jcggg4zjOOf8arzMEUQsSsTH5sLgceuOtNCZYDJJFucu8rv8mDhQP8OlQyROBNuAfCnHcA+tJZYnuF3h9gHytg9uvStVnsIAwlZ0YoRyhznHvRuBj2ED3c5AKqzdTngfXPWi1tbi7VpWYssed2ATgAZPTr6AVf0qxe7jE7M0NujFTJHEWy3YZ6d66PwlZeF7rQrmXUHmsws20yBmZ2GAeMZ5\\/Csq0\\/Zxva\\/oXCPM7HEyRzPFHJIX+YkKOwH+c1HfRFDGgYkHuQRz6V1+q+FrnTWkubPVtLuotgZG835+cYG0jgkEdeKXw34N1TUdSmk1iC4htrXPnSSI2FJ6AeuSQfpzUutDl5rj9nK9jD0yK3WB1l34Kfd6gn1qtbWUVxqaQxTvHE3zF2wMAHkj\\/69dbq\\/guUSoNDmkvAYy+GLRgDnGD0J4ORXNQrb2M7pdearrGUkTP3W7g\\/iOlOFSNRXiwlBxdmVJFia3SCGdnZmJcADGPX1rp9DsbGx0ptUufJLk\\/uw7DcQO3U4PH1rG0WS1iMrbTNIwVURULMTjnj61uWWja9q2n21hd24sLCKVpmMp2bmcKP0AHX3qKzVrN2RVJO90rle88RG\\/e4XykWOSHy49+Dgkg5\\/IY\\/E1KNE1a\\/0NIrK1tQts4zEH\\/eNnJ3EngA8cevpXXSeD9PtNDVo3U\\/vRsufujH8QPBHsPfFRR2xvL5rNL1\\/LUsgdZGLqR1POM9Dyfp0HOFOvTcf3eyNJ0539\\/qctBp9xpiF9Rglti0edyrvVT8uMsDx1PWsj+zZB9ovoyqojFkdvuEcng988Ae9d7rOkWdsMW\\/k3UJbKSyKPmGBnA4ycg+tRarpukv4Th1BGYKuNjxqBuy3C4H1PPv7VpGs38yJQRwUNtcSTedLDcGSVv3hVR8oyDwOPT1rvo31iDSbbTtG0q4ZPKIaa+TcWODnYqn5eWOOc1r3XhSP79tc+eYxGqH1G0E5\\/z6Vq6TCNKZ7mMTlZI94gckjccZx2B6n8KxrV24c0dbdC400nZnnuqaVfv5zXhm+1gMRiQ4UE5KqAcAdeK3dDg\\/0WynYoyeWc+YgySo4BJPI6flVu2le\\/N1NHbeY0TDkuMgEEk89eO3aswXMp86zWKP90di7jyue4\\/Ssop1bRfQylTS1LF3dzx2csgUyB8sEjb5R7gdq53TLePzS11ocZWRgFnDMCp57Z5z+FbV9b3ulSebcyxeUw+ZtuQB+HNZUkph1SKC2Xz4j85Ksdi5\\/i5rKpSnDmS\\/VHlVubnlYl1zV3dNlunkwxlcSc54XBArmZBEHEimRyeu\\/qTWnLZL5zSSZEBODhmAB6nrxj29\\/wAs4226AuF3bMjHck114KNOnFKCLoRhGNon0p+zReb9GeHPCnivc5wJLIj2r5n\\/AGZL0JdSW4J5HQ19LQNmArX1NB+6mctdLmaPFvG1sbXxLHOoxlq73w\\/P5lmhz\\/DWB8S7P9+soHQ5zVnwrPm1QE9q9CouaNzgho7HWbsiuf8AGcQl0mQexraR8jrWfr6eZp8o9jUUtGXU1R4HBJ9n14Dph\\/616hO3naOrf7NeW66Ps+vsf9qvSNKk8\\/QRzn5aLWk0N6xTPOvHo\\/4l8pweBnivLhHFcws0hLBVYYGOPf8AOvWfGa5s5enAPWvGGSVpp0gBJJ6YwR6c9q8bM4e+mjtwavczLoAJsRiRnv6VDH5gIWIsHY4AXqc1NBBJLcRwBlZpGCAA9\\/et\\/wAO6Ow11cT7JbWUMUaEvkg8Zwen41xymk7dT1E1ex0N\\/DdCKw01ERJPIwyhCdpI5PH4cniry6fp2iaNcXF3qUiXDIyhZWBVjkcgYwcD29a47xTq91Br0htLjyXT5RLEMbhjGR3HesrVdW1K\\/tmW7vJ5wqjaHACgcZwMdc45HNc3s23c0i1q7HUwa9HZRSG7DtFNGQpUZM3PJ7e1b0vjNZ2igR10+yePOJEVZCFxxhcs3zE47cH0NeZWNvOsUweI\\/NGCpL4CbsEN0PYGvUPhx4XV7FdXuIWafa+TOQcEYG0hmUdyOvXj2olGEdWVFytZFHWNatTqcc9nbXFxZPFsbdER5jDjI44wB1681Dc3Mt9DDNFCYJ7ZSs2GySv9TjNdZdaf5dq8MkckUyxqXkjb5lBweqk4zkd+5FGjaX\\/aeoXC3BUiS086BwV3M4ZhtJ7k85zzxWc3Tiua5ceZuxwc\\/wBl0m9ku7VgkMqb4WkznnGRg985rPzfSTgzlx5hUl8HdgHPHoK6rU20yPy4ntUMkU7xtJuDFlC\\/IenBzkn6Vz1lqrreE3QabZyuTz\\/+vp61cHzK4pKw+8naW4ZTukGUQKzbQSTySP8A6xrd8MJ9hZWguXiWZPMwpLliCRyAenQdP61z9ujaleRJBG7iVw+3H3R6Y9utaa3JbVYYHEUcVtu3jzPnbcMEAenAP4UqkU42FF2dzo7+7imsZEdI2mbayylN2GHI9CCSDU+laXY39w1nd28SGZN+Q42p0yOSSe\\/bPrisS7jgskMiRSbHXaAw9QRz+VanhS8sWaUeRKCURjtw+TjBHsOPSuSUPc0OhS11I7rwDY+fcx2MPGcsyqW6AjapAIwetQ+GvClhaasiBI55YxnBYNlh1GMds9a9F0qFEsb+aWM26El1z1AKg\\/41zXh61hdZb5bjDJ8wBDAhuS3XBPb8z71yKrUaacjbkhdOxvaFFFLZzPHbQo6OTKxcnBBP3BjgZ\\/keKqw2NlHLMkGFE7bjs\\/dhjgcEr1\\/r7ZrKtbiWzt9VYLOPNhklQPG0YzuIHUeh\\/Cp\\/7JmsdLj1K9vZpfMtMJ5BZuqqeNqHcflPQkjH1rD2TTepo57HVLa\\/arNLaWMxwDyxJHu3OOc\\/eGccV59r8cWj6kn2SB7qMSsLeEgucMSxQEficnpXbWF1KdCtXtLYOXWN5Q42rgkBunU4qeewht9PlmaBTIZxJFl+T93tnr1xSpJwevUVSSa0OE1G0jgngumAeOePEiGMOPu8KcEYz0z7HrUeqeE9IlsS0kbW7xKoVFQqQThjzjoe1aXii8uLq4TSbK2iVIGMssgHOTnDcA8qvr0qOO4uzcot7YMPtLBVnIbY\\/wChJ78cVpP2sUuTcdPkk3zLQ5SHwfpyxPfQyO0IyqFwMFsdvfpVqLToLdEhmtni3MWBACkY+nrkV2+p6bcjwwC+neYkBeQyK\\/J5IHHft68Y5rlRaXFzr0bXTtKXQ7kb\\/Vfc5IUZAwT1HccCto+0l8UhNwS91C6nZf2ha2P2OUEiTEgHDJjkFjxjPPFaVraKkkYS6TIAMjzASSkYwBx3xiqenlt+zbFbW8Y8xnkyN+DhQSOR0PoMfXnr\\/Dehada7ZLmJp7gqZYsoSD3O7I4\\/PpWVSnK1lsjSNVL3nuzF1qxsbTVSunNARKu53bIZcZ646nqPy71myCUXUIjTDOCUdwVUjIHU9M56njitl7+B3+yz6X5ty07YQSBEEfBLDPXqoHqT7k1Km1rtGntCl2jhFZkysT4O0D++Pu+tVGg3ZszddK6Q6207XTC95a2fkx8qYyACy465zhuvWq+l211rmoXA3w6fcqFKxklUIxz7k9+a9HjkSewkWMM75CxkkAZI7EcH\\/PWotZs2tdJ8q2jt7S5MRKSJEOGIGG9\\/\\/wBdZclr6DVU46fTtU069azQXdykh3mZEZtpA67MYxzzyTxXVWmnXstoz3rpHKgZAHVWAU9OvftyCR71dstP1KPRI4GvZnk2iRpJRtIODuKjjg5PXnmmahdW2mWMkV\\/L5chiXbLGufMbkYB5wTjJ57VLgrDU7nK+Fo2fV59J1BV+zus+0\\/Z1QHBQADAx0J54zVrUvDFpa2EklgfJe3AiSNHGHRWHJ3HnHPbtWBpn2mTVzrFzaXfnzhY0lX7jgtyf1\\/HFb\\/g3xGL\\/AEpZdVl2XSOYnRGHzFWPQHg9eR657VXLK1yE7SscPrWj3NjaWtz9jBndvMjmJ3b1K579Peqdq11f6hHY3GnRTRqduQh5Ix09cc813Xj69gtdWDXrwSbrfZG0isdjH+EAcdMk5I6dea4vw2ZF8\\/U0ldEDEorDkg8DB9Dnd+FFbSm5PfoOM\\/esdDaeHbeS2mtJrc+Su1V29dx5b+n6elZVz4Zj0y6gvkjkTyJA4RXwW9ufoa6rw7rVpboI2vhuU4CMMkknJPHPPNdFrEFrMsX2WNW3gBiB06H29a8JYyvQqXu7HoqFOpGzRgeC31CHXRq9vKk0csA+WVuIoxnI6nnsa3PGdro+vxR6jpsxi\\/dMX8iMjcwwc4HHbrXCeKNI8RaXa3H9gTIqXIzMoPXg\\/KD268kEZrn9F+IM+lacbXWLd47sAhpki3RynPXjpx1\\/MV9NRrxxUFOm\\/kePUoyoyaew7xh4q1m91GFLJZYJIjHEkZi4ZiMYVeAwIB5I\\/HitLQfHd\\/p9pdNrWk3sKRTGJZY13KDuJHyjoQvXB5x9atWmpaX4j0e2lm8g3KqscLK2HAQYyAeevetqw0+LULddJnuFXfL5m4kAFtigbu2PvVrKEUknElTbbszoPBHi4eItQiTSLO5lsc5mmuGMQ3Ajop6sQD0wBkcknje1BFCG3muWjt5Ad+MMRn7wznPfIxnPNec6TeN4V1tH+128FizCOQujNiQfwgKOhyec9cCvTJbqGaBbh4VnSRBHGfvKuTnJA6596xlHlehSdzLguBdadPbWivAiEqNnBcHAVm+6OxOPQY71xdzeQWniNZZS6rZzsxJOCfk2dBnjOOcDv9a6uPVbdrq5inmdp4OFHyrjoDyMHv0\\/XAxXHSWpv9YvLu1EzLHEqyNJGPnc5J+7gdBgHHHvVJSS0QJxvZs6zUdUSJvlfEjx7iY5MAqRjkdSOR25yawrfU5\\/OeW9QeawOwRp8u7B5HJI+mfSm6bEtjZLb3ClXaQh9q7gWDdiOOMn86zGET6hLBqVncvEBsjaMHDcrnPP04Nd1GLSuzmqO+iKGoXJ1C7t\\/OaVUkt5SdoAL7c5Gc9cL0649K5DQ9Bj+1yJaea0xw5WNhgn5uDknsCa6zxCg03RUhnESQQwsyEtufP+zgDb1wRz1+lU\\/h3qemuLmRo1hv1UfeUHeqrjI9T1\\/OupWsZO6N7SLaeWwWMW0Xl3ljIY4hhjGwYEjgYJGTn3B9K6izuYZdFXz4122cStCrExiPJwQzFV5IJ7d65K0kFvcWMtvdvFdxRyNGXQFFaTPbkAbmxj610kuiXdy9pqOo6q40uW\\/LC3WBFCxK+ASwG4ZIB69\\/xrgk7u19jpVluXtMB1Wztd8a2SRW5eNFQMyqQg2swGSQT+a1y2maQLKefUo5pZ0WNMusrHLElUZgT0OB+XQV2ficrYarOlpFG1jIA823ksDgeWMA8EnI\\/X3ZfwQ6n4fsJsOkdwCHSODa6Kof7w6f45qIuw2zzTxzPZXN7HPLLbtsyskvG5WBAO3gcnHqPT6YsejRWt+Ti22NEPJHO5gd2eB05xwe3rVPxDDcza3LLK8TokpBVCVY4PAAxnAzjn3rqrx7V9QtNVkHklY1d8RE4jIJIxxlsAnPuK1Sb2ZKb+0jzYRPDqswtbCKQMRG0hGSu4dhnGeO9dXp2kSsbJU1GSF3w7EY2qpUsRk9wM9fX2rEtiraiRGpIEock4G5mJxnJyPrXfa3ZRjwtG11GDIMEOkeAMAqB0+91yPpya0au0EbK9jk7uxNtIyZNxGCyGZxgkNnIJ6gH2556iqNrZ\\/YoAiqmxZslA5ZA3AzjryMDoeldZaxTy+FZEuolMKoqbg2SeGI4znnj16GsrU7a109LaSVHKJJCzNIjDAZE6Egg9+cHis7NM00aLdq1tBpYsFtm23P3UaEkq6nkgruI7c9\\/anafpV6wW4vHlmmKhfJQkGcEZbOMHb0BPpms6O4v49Y+z7wy+cGIY8xHGMAZ4BB7jP0zV+2vZ4r23vWa9kmBI3KzSYHAIZGG3Bx0+nSolKyuUk27Ikeb7X9sSYRGRD5cBkl+QOD8wYq3oBjnnisnUrIXUKzS3paZ0Imi3DMioRsVcdc54HJ9zzWldXl3HqRZ5ICz8TWxiWJivZmyTux+H4cVZ1GfTbm7jeeGCaRYNqt5BWJtoOB87AZ5U4zyBxSpyvs9An2aOUZ59Oe4lUTRFm3FGABXp16n9R2p5uJZikMiTAxp5oZgFVSRxnJ4zz36mtiGytdQmTMbFIIme6DAKdqjhQvOCTzj6+lad3pmdMktXuLi2a7fcGmVV80cAbjnIIGDz0qmo7sE3siHwkZ9VtUtvLkSKUMjSSL5anjBAbJCnIHPGemelOnjvLKCV5ru3uEtwV8tJOUzkAkcjjAwM5qx4TX7No8kD3FvHCjGWGZ4zIVdTkgDtn1yOlPmefVLQNGrOSGmV432hvmK5OfrnOe9Q+thrsznptUuL5biGFAzxoI4klYMSrnhdx5HP8vznQwRaFlI598b+VI2CcENj+HPy5zXOQzC61tpLdPIcKsojB4B3YB5\\/PA967ee6FlprRTQllmkBbBwVBbk\\/Tr09a1cE1axCk0ytqFrHDpUcYigeW4h8zlANqFe5PJPU\\/h71BoheHR7t0RJWFuDhgMtwMZ\\/ADB9jUN5tu7qS7giK7CQBEcErjHBJ4HXj0qGTULIaYLQQ+fJJaxRsnKsJBnkYPI7Zz1rOMnazLa7FeXVGld7w6dMscUAjSSFshQMMAQQMDrzimW9xHax+XcxtbpkvtZTiVyfmbvjA45\\/OnRaokP8AxKkhV7dgomVBiQfLwMgcgcZ65wcVcZYrvVZI4g8tn5xk8wn5huOSoz93lhnNOUVL5gm18jN0Se1ttXNtFHKvm5aGRSNobjBwR9eRyfSr+r6Yt+s11IjSXG0LseRQjkHoAQSMevFT62kM0rRQWzSMFjaMo\\/7tyCeGI4zg\\/pWHZ399b2v2aV5LpwpmmWYbREAAQqk8k\\/4gVE6U7qUHqNSWzM640i80+5SW1t7izYL8zwMxznqMg9+mK0rbUnAih1O3WRQcqrRhWK56dcnGO\\/T8q6Ky1N2to7lo7po2VHZmUjZnpyO2Ofwrm9ZMc8hDOqTDhWc5yp7nNOFaU5cs0S4cqumUp4NLu72WacCFSS7DGGYA5PGa0NH1VEjvXiA8uGMfZERwf3hYHIHGcAN06cVlTWQnt8svmNu27VOS5+q\\/w\\/41Db+HLpU8yFo0KNkMJcnPdSAcj8fet0oX1ZlJXeiOwtGV7Wa7+yRiGBFKzSjIZivAJ\\/ix0GM+prmri81e8u5L6KKaWK3Qb5Ixk\\/TnrziornULtrQWL3rFYgFgiAClj0\\/E8Z\\/Guh0XSXsNCQXiXKXM2GKxjgLnPTtkcmsaiVO8pbvb0NFLm0XQv+HtV1PUNLSbaBJuCyebwEUKOnrkkn64qh4huLlYiqws205P7vhvTHGD0\\/8A1VoWniHRLKForKHdtxvJ5LEYBZu\\/U\\/rUsUcd9dC7gQIvDbVB6kdPXP4157fJNzcbIusm46s5IvdSxKtzC0Skg4JGSO446cf571dglgBYxn5FKouX+vv2yPrW5qSwXNwbeGLL\\/ew+SMFRx7\\/hVI6VFaJ56OVXbkiQFeeB07fStlXjJaqxyOD57lfVI5721kjuIeSoKgPyc9gP89a46e1itboP5rM0YwiZ+73+968GuxuJ0j37PmKptyRnBHXHt9ax7vRbe6mjUwTSPxhTnOO5P610YefKrPYupHn6XMmzjitrSe9fzWlmbgKclBnv\\/wDX\\/Gof+PuSU+QXVPkVox1YdeTjuauaphXWKOFxsYIEXgI2ePfOOxx0qrJBAV8vdIgJJPy9Djnpwe3AzXbF3Vzztb6nYapqMFzq6PcKVtGQA+YQJJEzlcKBwCMcDt1rFnv2udUmuYYktf3yiJVU4CKMfXt3\\/Ou31XwnpRjhmSU7j+8kLRhWCsOhAHB\\/HI5qbTfAum6xarNYvIHjG0SRgBBg4JYkHJP449u\\/b5l3SucLfh5rYbjLBavjICglsAZYjvyQetNGmsyRxW8j3m91DhQA2Sx6DOSMV1fiPTLaymsbL7aNSkVvLWEyZJPoDx7e3bvTvEFnAulT6qLm4t5WYRyr5hPlk9MgknPpgAYxzgip6lJ6aFOMzafZwLBGIracKA\\/GeeSPbof0qzbyzW6vBfXlwgfbsIgLFkIOcDcM8ED+VYdnr81tp6o8jSLE6j5i2xuD8rHpnHOPbvV0+M7CKSN5oVeYNlWjf5xkZzuUDjplT60LUGiW0W8t3+xrMHtXZcwPkFlB9xxj3rXstIfynutVzcW\\/73EsG2Xy2KhRgFQByDk9Rjjkc41t4qhMQjhhtZvMyitcIpaIexPuavXOvXkOlRRXERV4n2qC29GYZJIOSOevBHrjmhvRgld66FHake6drWSG4mfBBPmBjnAbIydp\\/wAMVcsoL22nhMtw0QaccINsq4XO0HnAOT9O+R1x59ZtIbqN2mLLLHiX58jdjjnHy4yOmcenFQ6Fq1vNqEYkhOFLCN5JC20nPQcVCg1HXctyTemx6Hqet6jc2+m2VtZzR3yXG5GiYAptGDnI6YPJ\\/TtVTxlM+i6Tpgt5IInjl3tLGRKWkYDIZhjBGe4\\/Ptyml6vOuuRLqExtUW3JZ4I9pOWXJPPPA\\/nVzxwbe78OwT6fLO9ul0gcPKoC5JOcZz\\/Dj8apRJ9Dr9Tjkjs7QzXttqc5QZtokESxZA6Ag56Hqc88VF4fmuvMaVLjzLeQNHIkzsURSxzhCASSABXEy6rq15prtHodzI4kDCeN+EVc\\/KSeOpNP0HUdTmW4a8t57EwtnlijAsOGIJGeBg4GMZpJpqwNWO91qygSJlupNUsdNuCsdvcQSb0HbLAHAPA447c888vfXGmQ6i8Euoae8m3y48KFKFf4mB559D+tWdK1qDX0TTWvry3hVCJbezk2xnrlge+cnn0rpvCS+GPC8N1djRba8jK7m4YtG6joCc4BB9\\/qKwlJa02Wk7c9jzHXD4ka7SdUjvHmUIscESrlMcDA56D8MGucsv7WkvhKLORmkZldfunA6ru5Iyfz96+h\\/BL\\/ANqWVxduqbmuZLho4eGAJztAPGACB2\\/GvNfE\\/mza1KYLg6a0uoSRO0iK3lqWYrnb3GOvuamjUbVnsipLU5U2es2ky3OofLbyxgozYJQHjGeOn+c1i6qI7ed0ilEigZViME\\/\\/AF+K9G8eTTHQpNPmhaW4hUhXCl0YZyV7dOueeteaXkMcQjP2qKZ1X50ByF455PH4VvF3JIU1eWR4Tcl3SMbSM4GPTjt061G1zbbG8qJmY5+dj+g9q0\\/COmre3gtZpFQu4Uxtj5iemPyrZ8QWKeHb+1g\\/syHdgFZZ0JBIPIGaXP73KNR0vc5aSEME3SIWb+Fcgr165GOvvVS6gZJGAIJGQxB461r3F0klzLgRBIo924DgnvjH4VmyTSTqjw7YkRPp3\\/M1tYgTT\\/Oh2s6Ax8gbxkHsaZJNLLfStIweSQ\\/eB9\\/bitaxtLC4s2R7y8m1DZujiERZDz93jn8ffpWbC4iu1YJtKE8CoTuNoHuXVEjEkibFO7kfeyemOnGKdDZajqwDWtrLKqnBxyM+1RyuGkLlhsMhZkHQD0rpPBNvqtpqP2+HT5hbqh8x3GE24564HpU1JcsbocVd6mdLotxpIZjfRQ3aMFkgGS6ZGevT+ddH4b8CaxqMi3FwgmZwSkKANJIPfn5Rx1I710\\/hfwXd6oJJbiAw2gmLLAr\\/AHCTjIXnd0A6\\/WvTdC8Nf2bdCWO5VnC5JfG\\/rkKenoK8vF5lCjpzanXRwznrY8m1CzvNOeexuLOWzhmZvKa3jUcsCcDOMAA49ePpUEVjaXeg2tt4diuLdkG2YSHIeQ8fNkBc49Cete3XOgWmoApPJBKQw+UtsAP+yT34qaDSdC0yNnS3jWQtl1Qhsnt932+vSvOnncIqyV5eR0QwGr6Jnilh4G12yvre\\/k8orbR7tzKWBkyMD5TnOMGuqTw54qFhIba+gto0YE5BAIzkg7iSfQ9eneu+OuWUxltLN4wICGliHDrwc9R14PSsrUvEqW3nLujmkAYkM4O5M9enA9s56UvreMrNPlXzLVKjDS543Np2q2d7cl7qWCGScASw5kBY7jyc8dqfbaP4TmtrGK6juX1C5xvXdtV5MkZJxkAn3FbXxG8ZCWO1ht7NAzKZiF2v8vzZ4HPJx1APB9azprx9Q0ZHwzRhWKdN4bLYwPrnOM9Pwr14+1lFOorN9mcb5U3y6lnSNPbSpS0FjHEi3CxbI5NwHTLnqTxnvU+oX6JcujyGSykJEyA5CrxzjPJ6e3PFc6kt9Nqn2q1ka2hjOMqpO0FegwfrWpFq+m39lDFJbTNCE2tlwCWJyzDg+mMU5UXJ3eolVUVZE0097f2EiCL7NGsTFIpPmICYYEjoPT8amjuvs9jD+5C7gZJjhd0m3OR07kUthr6XV19k0iFFKK8fmEB3YnIwNwPUYHH9Kl8O6fMupCwvyHCSeZIsZyQSSpPphQM4561XsoxVrC9o2yrry3r6rHJ5OY47fMIYcbSGIOMcdT+lVYRKPC1jbiJH8tt6qQPmIY9\\/fBP41rt9gbS\\/s9nMLq+mtvK4BGwIxGT6cbeOtR2sQ0i1t7HUf3sTybSRyYWPQg5xyT07VcY3XoQ5a+p3nh1F1bRJJrQfLLEm1RgEs+AMfjtFYWuade6dc4O0RpHg5Ug7gOVx1zwR6VY8Ealplto1xoss6hknHlEElmG4MuAOh5A9OKh8U300cUeVaQNFsMoiYjd257nGTxjrXIvdk0kbPVJs5YzNb6JAsStKt1H8ysnCkg8\\/y+lY1nZ3lvPD59uZWZslWON2emT2r1DTra5vrX7WJFV7eD92i53KAvJJIHXGMD39axNV0wvC0kk9tZRwjdK00oDSN\\/EMNwD7cdcZrrpNKTSSOed7anH6vew3FsbW3tHWTlZQ82EU9Mgdx16k1Gl3Bp2lm0jMty0gBDOcgcc\\/hVK\\/0651T7VNbOixo48vemM4+nQVnm7vbbUkglS3nBITy1UkHjg+gFcuMpxqz5U\\/No8zEU1OVk\\/NoT7RPNe20Kzu7StwMbgOfSqGoxyW181vK7OQ\\/UYBPt\\/KtW1sr4X7SQ248xTkcldpPXHcVRvori1vWEjyeYz8FT9\\/ntW2HnHn5YtbbF05x5rRa2PSv2erpofE4iJYZ9Rg19X2j\\/KPcV8cfB2WS08YIsvyuHwfmz3r6\\/0+TdbxuO6ivpcLK9NHLiPiuYHj+2821Lelc34bfyxsJ6Gu38TxedYsO+K4OxzFckdOa9aGsDzZaTZ2VvJuTr2pl+N9u6+1VrOTKde1TyndER7VnFWZTeh4P49j8nWie+6uy8ISebohX0Wub+KUOy9L4x82a1\\/h5N5lgU\\/2auStMqLvTMXxav8Aos6Ac814fqCl7uR2kZNuTyeCK948VpxOAMnmvD\\/ENvm8lCIqs5O3ax6Z\\/wDrV4+Z6SR3YF6sxCTDKhjbcykEDPer02r3gmLQSyQSZLMd2Du+vpVIFrSWeCSBHkOYzvGdvPb0PvTNplkkflmC5PQYPtXncvM9Uep1uV7t5JJjJLK0jscszNkk1JIZ5rMOQPKjfBI6jjqaZIVdz85wB1IrXaXTdPuI38k3EU9spdQSFVyM+vODgkHqPQ8iWWjrvh5Y200L6hqcskKKsSxypCXyAWTbhhg52Ecfnwa9I+H0pfw5PJDYv57SXCW032qZR5ZY\\/KfKGCxJIBLDkjdxXE\\/DwWl94Rn06eMh5JW8q5wSsZIOE6nkjfgYPXjPNddodxK\\/\\/ErUF1t2XyogmMADLOoA4J3Mfm9MeorlnrfyNldHc+HXTT9HurLU1jstRvLQtFIzncQQp2ED0wM5PfBPWuN8faLHNc2dt5wS0illitrOMFcAHPzcdjjnLevrVzRpJbS61YyzfbrrzSLSZjIWlIJ2hQMDB4HzemMVjG+83VLy\\/MW0LKoVXO5kcoMbfbGCB0xjArmUWpXiaXvGzOC1azjt7t0kMrQxIzBo1XcT6AnA\\/wDrVg2CiS4QzrlGJBCHGB9a6bxndM2piFYVlheMEs8ePmJI6\\/gB+NUdD0K4vrVjAC7twsJKgvz0zn05rsTsrsxtroMtEht5vMIl8ts7VgI3Adsn05pt1Y+dLNLblTOkWdki5GCDkkd8YXH1qwlvJFI1rPEbcoD8smd2NwHYHnnPpx1ptsbi31by\\/LMtvNIELh1zKAein3+tKT0bQkknqbHlz\\/2fDYXjDzkKhGOACcD2z+v9as+HfPTURYwxhmLbFIcBiR9eDwaz9cacWkK\\/ZyGTIljZ+Ux2x+Hc1oafeRQXkKSoYJFh8xGJIAO7kjP4DJrBxfIbXVz0W332uj6g8+ZmRmDuRgKdgH5cda86uru41SEwwSpYuke0JuIwvUZIGc9feruv6ndalYS6VbiRV2M7qflLLknkds5Hf2rLs30ezjWM3O+5nwxQ49fu9awpUeVXe5c53djV0eO8vLOKSXWBMgikWbef9WNvJBz9e1dte3UOgeGr5ob17qCYCW3ck4KvlQowQOMljgDj1rg4FjNnayG7fy+WZFbaBnruxxmtnTLWWSF7a5s7IT\\/YyD5IwNu5SC7OOWxjGOOOvPCqQTauO+h0ekXsV1pax27oY12oxBxnnB6f54qa61OxtRJauySiPKxLGCcnPp7cCqXgqCxtNKguWEpuRMdwPUqG2gEDOeMHPb861vE6adbaeLiA28RZisjx8Pkgt94DLEEH8ayjTTlYcpHIaA8E8+u3Lsgu7gJDCk6\\/3wxOTxzkDr6V3lnY3s11b6sdFmlsLdlkhjDqWQL\\/ABIAfnz7nNeUWBurqe5ghRSBcbTnO4YAU5PTnAr1O3kvby1Crqa2rQRLh4gyh0UDC7gQTyDjHPpWjp2mmJy9043x\\/qkl5dRaZaaa0MkzC4kaReBCuCPlP3SWPJA9ea5W8S4uLiG5hmhRASSpbyxnJJ9yOD+Vb+kt\\/Z3iTUprhzJMwc+WGzkk8M2\\/sFHUjpxxnBx9bg1CfT7e\\/sbSKOdYkadl2n5WXeeM\\/KMnoOo7DpWii5yuhOXs42NLQLa7vb2DyQrhnBcAAhgOze3fn2rtLi3sNIsWtJ1klmuRIbWNYs4IO1UA5A4YAdM9+9U\\/g601r4cW1kUeXcFSxI27s5Bz7cD86vPc217qWp6fHA05jlAiKtjY3B4OeMFePwrOVN6psXtbtWRX0HS72KHZqAtFMMm1yt0ucE4+6AewwefQ49G6HfK1\\/dahZ2MbxNftbRiPLklY\\/vMxYcngcYHHTtWfLePeQyWsbvbSeaftcKTlVd0DE7lGcnIyMtyDjPep9Kn1q28SG2htBHaDUlYYhbYVbCt1Hy84IPaq6EM6K51GPS\\/KuIVjjnaWMPGkZ8r5pApHIHr2x0PrXZIj6he2xNoNwXcWVSAvHb8v1rhvFNhDO17bxRy2srSrK1yzZikxg5Tnk5GOfTOK7HTb2WbS4Zbe7kkljjMbGPAAI4PQccYP1Nc846mkZXRs3VqluvJCYUBcKAOMmsi+08XN4FnijeNVLKpPJODyM9f\\/AK9Qarqbpa21qGm82GWPBMnDDjOT1PBPfqOtZWqNrkt5dSxa2sRjUtsWIEKB0xnnnipStqX8znvEeorZ6fGId5YcR4G1V6g7QP4uCPwrk9Hhex0HbbKEuyzysZF5y3WPdn0P5itKdftVpHZXpl84NvVyN3PzEgsCBndyPrXPxytbaa7iIvHCzsSzEbmXP580pXlZRXqaQSjdth8TZmvGtUtb154xEPPWNQyqxG0HPf6elaD6aNHKrcSRPbRQDAPAQ4GeO54\\/DNcn4asbzU4LmTZsgiTfuz1br\\/TFWbzVLjUL1LS6LiPYzPxgMeSefwFTUpTrSVOL0W5EHDWcvkXNJ6x3HzmNpTIr9MLgZ+vQ8V2Wt6xGIvNgvMFYgwhUEgtk8N71iR6TKi2jO8ahYI2Ty+Bzjr+o59a1bLRIxCZnlRWkcbGlztOCQMYGB75OelZV8DGvUTeljpp4j2cO9zU03xFayxQwXqZkxk\\/JwoHU4\\/Lr7Uo0bR9U8+fy4HiUBgSnLHH3R+tYd+i2OoSKWSWQAGTY5YKp9TtBGfX071HZ3rx2sxkAHztKiAnqfu5A56D8MGvMrZfKjNukdVPFKcfeGeJvBljcyBIbV7eSP50micD5s4wvOc81hW0niPwzrFvcXkl1eaeuFLzITIgAOQPUc98+3pXQXXiGC1u2mknmjl8rbtRtyDgAADv0\\/WsDWdR1PxBfo08jWloSEAC8ntn8T+Nd2DrYmnZT+Hz\\/AEOPGOj0XveX6mf4p8S2+q3JmD3FlarIXjh8lnkYjPJIxtHtk9z7V33gvxoBqdrYf2hCbUxx+UvlAMQqnIfJIySVPAHSvMdd0m5t5ciBLi2kYKGViWBOANwPH8utZl9p8VpdxRWSNHLKVZkXO07cHkeh7\\/WvahOFWJ47rThPlkj2nXdduxr4tf7Es2uZlzbvO5KuP73p+tYXg6\\/1m9u79tXjEFs8+RDFIVB2rgBWAORx2PfrWb4X1C807TJG\\/sS\\/8qZEVpXn85UCn+H5twGCeOnt3pNd1y8TTGXTfDn2NWZVVI4wF2gZLY5wD7881HPFO119\\/wDwTr0aOu1Ga2W9lvtPMX2OPcfLjYqzSAhSM9+RzXO3Est4Gksi5uZn2u6bvlBPI3ccA49e+a5dvEetW2m3KahazIrp+7l2YTBUA5yeD0\\/wro\\/CN3Nf6Tpdmbm3s4ZY3YukSlmZQuWyW5yQc8Dp1NdVNqS0M5aFrxVZ293pDSXcJVgDiN0IaSNOGyUyUGMdF7iuX8Kpcw6nJM9iDBBF9nlKfKYjkgEkc7yP5fl2WozyXMM0szQXOmvMWSSG6KoxHpkKVy3oPxNcNf8AiDyr4abd2txEzMHEawlSVJ3B\\/lwffPXr61om3HUztZ6Hcav4hnudN002ixajHM8iTyMn3VVSQORkMPTnp+Nd\\/pYWLwxpaQDzfs8ccc7Jja2VyTzxk56nua8i0zXLS00eK0SGKzP3UQ7g0rn5cAHlTtbduyM7e\\/SvR\\/C3iW01HSWiiubYNAcFEG5g\\/PUdCCp4x02jk544nHk6HQ3zGvfRXE7qhsgHKYkVWZiwbdtwD0OATitjULWyl8I2MsBaVAFEiKxDcjaenI702K5V9Hk1SNZQI3VZixKqQAOcA4xjI+vpWc9xYHTPPLtHBLEGaPeQUkblc+nUnj0FK6bSEk9zgPEWjy3Ok3huI0by7qSdY0I3FRyB\\/P8AHisfWLae5KTRvFb5Y7I0AH8IHIIPPr+leh3c6SySR2qSkCFWaV0DOHYe3sBkHGeMnrXN+LIBp9tBJIi3QZWO\\/K71wOuRkc8+v6cbwSSsDbbuzy62s3XV49qBJzISUYFsg9yOnFen+ILjzdCsXa1EcscOMbgPM46EEehHvxXDaYq3GpHUWVdgBHkOAWbnnkEDJIP5Gtuea9utPWO1lmhS4j\\/5aA\\/KNxAUHovCnoR3q6jaCFi14FKXFk1vfJFGER5AOQxXbwDjAJ5B6Z4xxTNV0qG4u5dIjXfseMuJYwqsTnPGOCAAcc9T1NVrTVgIrc2955L7Y4rryyFZCWXOAQOCAT3wDXR+Jp4p4dNukgaJ7mXdIxkYgyKh3DJOccDse9KwXIrHQbO3tZ7iKU\\/K3+tEe1g2eevck+nbjiq8Wjvpy5ukEhFscxgg4IGARnj5jt9K1ZLtwg043KJO4eR0iHmOWCnauOxzt\\/WreswQX73NpcoIE8mJ385gWLgMCoByCRkMdpxx61Eti4HEyw37+I5bCwMb2qYEE5ULn5ckZ+9xnBx+lSa1pDsGeFYHlRAs7BT8mWKg9OcbR0ycH8at6H4baC7udRjR5pAAyyIykbQepIxgnAAAPY+lW7y0tZobu1hecRzNvnf1kzkoTzyQe3pUKmoL1LdTmZz1lPfAx3FoYfszKQ0ZYyIDjkPuAYbsg++e5q1ea3pl\\/ZtZXapC68DKElWBzk9MZ57nGazbmIiVje\\/uU2FYGa42uuwbclfTkZHTjPOKpJ9nu43trllRS7PBKBtdkC\\/dK5zzwcnHX8KaUrWbE7PYuaJqRtdMlijGPORotrckEkcA5HHLHv8AlXXXd1BB4bOjrbGVVtiFnBxIo+6QD36dq4bTrdUjbeHUR\\/OkezG1RjBPJ4oN5ff2tMbO5H2fy2UIwIXDcbhkYzyelOmtGyZNXRk+FDHc6\\/qIhR1hD7QzDO0KSFHvwfbrXV+IJFa0ZVkjl+QJGeR8wwDg9ecDisfQLeO3W4CKUuHuGH95ZB6fp+tac8VwNDt4ZJlg\\/e5lZl6fN+mPSnKd56BGKUTm47qynjvPMNyhyu4ImBjBIBPqD3\\/xraisbG40q3soYkilcDE6E7mB2hcjsOfw696iGn2gW7VpYYiUMjKACAenB7k9fbk9qsWmgW9vdWMKeVD9qkLjDhvlBwSM4zwCfypXT2KtbclutHktNRt7eUIyrGWwcEuhU9OOR157Vrw3VppwuJmjh2SIVtTNDksQAOTx2H5GruuSpbOi3zeaIoxGLhpSMEHbwGPTPPHr6GsXxRpx1NTfQXUkFrGm2N0BAyMK3JBIXkn86Uo3SBSsypq+LieKK3MEEkscbwCBdvOBu5XAH3e59axyUVp57nUDPduHiaOUZfgjBBHB574rR8PoY9RtbK38+6WOXBlKALtPUqeTg+3TrV3xPp8b61dSoixeaylUaMDaMjGGx8pIBo5XfTRi5lbyObhubViWkiZIIE3Nul5mwABknoMgE+wwM1VW6tNbvpXaJY8ghgWwDgE5GOeg9K2ddsTbNIkUGUkPmlGXIQKemB14B\\/OsiWJINQR47RYXuI5nKsTtwcAAZ\\/PiqnTT1W4k3s9jf02TfbxLZRgxyRfIynaMdj1qtYaTZSyIs19tKh5HhhIOV6Ek9\\/THt7VVjvdPtLYgzkDygjxDhi2SSgOeAM9vb0qjokR1KSaQJFiRW2EsAqqnOB09D71ywpSbk07FppNF5Do9p4ihvbmxkkto4j5SlcgOcgH1Oec1qurXGtGWWXzY4QNzKxJxjGMDgdR3Nc3eW1zPZpcSXENs0fzIrAnd2wM5ySc\\/rVLwxqZ0i7ub2\\/muGYjAQcbSSMk9uMen5VUqPMuZPVKwKVnZrRnXxeGYVvnktQI4XjZZGOQJAeuDkZ\\/\\/AFVekitYrRLWwhdTEu07SMbeB1PXoenpXM+JfEt5f3Mc2j7\\/ALMkWWbIAAweME9uvr3FJJ8QktrGC1igRiF\\/eMIQMemOOfrXM6FepGLav5dvUv8Adaps357jS7KRZ5rlU3bVaTbneAemOw6dazNSi84Ga1kiY8xpGcrt6c5\\/Ac\\/yrFmvr3U5VvIrZooppDGqRDvjGD+NX7WaSALFbAXUQYPJJySxOflA68dK1VB09b6kNRa2HjSLzyI7acL5gJlJbPGD1x05OMf0rR1C3WysXukfyi4\\/eOwycZwEB688n8q6Kxt7PT9MW61AqJCuVjQjPrtGOn4niuD8R3cSXscthbNbQq5xvO9XZup3dPY896ihKVedui+4pr2avIwPEs6FcFyiODk+fuaQ89BjgfXmrvgOyiu9QtrdV8t1R53nmQsqgAn8BkAdD171BqNo+rW737Qi3llJWJBwnBwcH1JzW14V2i\\/s7Bd+26tPJdFcAhx\\/eOPY8cdRXq8q5HE4Yx97m7kfiPxkNSktwL7IVVR4kDLHwBzhvp0x+NW7PxPNJA0NtA8dukezCj5cnjIA6f1qx4g0HSLe\\/hubWzmltpUbbOyrjkZyAOB0PHaodKtNKtmEcyiUPGSsUakncMEFvau2F+XU520ael2trcWUs0G5LmPEiOwBVCBzweCCOuaL3VoYLSHSjEZJEneUSKigYAPyMNoyDx1PHA+jn859NeIxJbxyL5XmS4G4HIOFDZIxnqRRoXgvTrjTLC8uLlmdJUk3LI33QwyuAcr9cdutRUnFNXCCk0zl0tG1ee7srHT3LgmRAiHLKeoCr2H8qqxaBLHqcq3EbwFJfkRR8w\\/A8jqK9J0fwVDD\\/aOtx34T7Aw8uJhzLG5IYgFuevQc9OlZt1ZWH2q2SGfz7hmUxi7jEcKSFh6MTgdsDPNEakGnK+xTTTSON0q8h0G\\/WUWiS3OD5T43EHGDlfzq\\/rmt6hqPhwyS6dA0M0wCXkcZAD7m+Qk9+D0PTtWnqlrcxauwvdKiPlsXkm34VuPm25PGfTH+FYWpvYQbEgCzR4I3x\\/dUkghtxAyeP85ojUurxd0Nw11Lfh+zh1DRJ49Vglt44nNwBGGZ5V4GzIOFBJH\\/ANfmtDQbPS4fsjJBK0V1nh+sb9Bzg5xg5x2rP1TV9dgF1aXl7HFcmFZGm3mRrk5AySSTx1GfToKyLua5j0xIrRp2kRdsc0HzA5OTg9QeD2q7rQizdzcurS5h8fRx28FxuMBkSMHJcZz27H0pNbWa40DVQUtLUQ3Kyshchx8rDoeMkhjWVBfaxp+uW2oySvfXCxlI4SpaVFHCqcDA9cjNTf2B4g1wzahJZu9zMzSOXI5J6DDdgP8AOaTnBatjUZM2PCMcl7pLCS4vI4pGAPlnIyAc\\/Kau6z4Ng1EtImoyC5ijyHyu3HpgdT6k9Kt+E\\/DGoabZW6Ti5SdEx5Zmwq5bJwA2CeO+a0tQ0\\/8Asm8hSeaW5tpshomRTuG49hnI7kdeB0ryqtd814SZ3QpaWkjh9M8OWLakWu\\/EM8l7gEKLdmyoPHTryPUCuov9J82Rb6fWIrm0hxK1tKgjLN6k\\/wAXfpXW2+k2tvpaS3Om\\/ZWlkI2JuVHAOA2B0HA+9g8Vm3NnFcXk2\\/THkgJDmeRSIQAVUgls4OdvHFZrFOpO6f5FuioRs1+ZqaJPNZ6cbd7GTT0MjTHy4\\/N8tCxPUnB6qB2\\/KvGtfXUb\\/V7q4V7ppXnMywLCQfmY4H1x6+nevcjZTXlk8tk9zIxVATDGCRjGR16dPyPes0y22mbIJUumlRdjCCBt7KckZOBgk59etVTzBKNkk32M3hXzXex51qGna3eWUN7dadOmwhbkbjlwMc7V+YHGcnIrM1dpP7Glt4LN7eNZR5ZS3IIXuemO+PrXpd74ygFupt7GRJo5CojmXO5upGOcEHHP4+1YfiPxHqmo2yS2bWcuxm86AxLIvALBlOOvyn86ulia0pLngkvUcqMEtGeV41EXz3YgupmypSQwsSSOnauzXV7zUNKurXW9A1C8l8pPJk2FgjjAAAOAq8E9Celah8V6ZewN9qjvLd4YsxzpuyXOOqghevPTtwal8B6lZTfbV1C8Miq6sbifrs7kd+vHWt6lecYOTjsZxpRlJJPc4KLwVr14y\\/6FJD5z4EbBRgcY7+9dSnwnuRY+bcyz2zRHDQhQ5bkAYweOeozXd6jq9jp0SNpCecCQDMVBOM4yCTnHvVuHxrH\\/AGOZ3t4nh2kSM8BaPcOduFHT61yLF16kVKEf6+Zs6FOLtJnH+GPhtHbXsc93e3DxjGQB5ZU55BPPfj+Gp9T8OeE7HU3vfsb3UYY5VW2p3OTvJ3HoOuDV\\/S\\/E1reX0cscGyObbiKJeFXpkjpz6emKzdSjVLhdNjkRniTeZCyylsHjuR1PeqTrKV6jYmoWtFHU6LommyQLPF4dtIYM+WJPKjAHUkgDv0HWsXWTp4ke2tpGdpZQUh3eWQQeGAI6ZHQcVk6n4pntrhI4ft11GYDGRGcAEn+5yM8feP8A+rmrK9v7ueW8vvtIiWM+SqqCRk8jtlj0z+lKnRm5OU9ugTlG1oo9qh8S2+mWbQrCiswDgKVznAySPr6c884rI1DxnE10GSSR5\\/KG5Fk3Rqe+cc8cememPXyOO\\/WfXNuqT3FrAo3mNiW3DcpCk5GBjk4rprfWrUeKoDpFwrKMBXLc\\/wARyOeBz9aHl9JScrXYLEzta5ta\\/rL\\/ANt20Hn3D3ErhpW2YK5BCgAHpnoBgnHNZB+I0wS7kvVklaNxHGIXKlid2ex9u\\/SsjxhcXuoXgmtpCfKiM0ilvlQHg9eSeBz6daqeEdMi1Gzl1CVbeGGCZTIZVZt4BGEyOnBJPB6VusLRaTnFGftp391mpp2qaqugXSQyiGS82OwUZk4BLdDwM7sd8VX0SHVNT1G6je4GyX5WkkkA6qXCBW5zgHjr26nFbHgLQEvdR1P7XPOltFgBxxtDK3Iz7ZA4zk8V1i6Sn2G9so4LN45YvMjlG4uhC4J+bpgnP44AFaXjBtInV2bPIrK0uJtXura4dkSBAqhOjDHB5xkHP5VfeQm5udPWZzBEsZMcR2KWOMhsgf1+tdPod3FH4s1EX1xFczXdlA7NECvkup5UD2UD8q0PDmmx6jYrbLocsks9wWlvJrvZuG4F8gcgnbt79qtzd9iUtDB03zZNUu9MmhjRvs+1AEDBcZC88+uc++atTaNFo+lQzspkYlZTvk2hQT0wBk+pNdF4U0lL+9W4ku4becQSQyKse5cRkAemScbs\\/wCFb\\/iS20q2soLi5ZmmWV43KxrMXf8AhGOR0OcelZe0SnyluLaucV4K0M23iqVLq7slDsXaRnVYkXeFBHGCCWHHerNvp6weK9Uknu5UhjthLHJGDtkIU56jG3IPJGKzNNtrgX9rftfiBrv\\/AEXzCAXj3fdKqp4bggehIz3rqBG82nX1lbTR6rL5ZiuL+VtqrGw2sOchXzkDjnJJ6Vo31MyP4f6PaSsuoz2sqhnMjxiSNIyGOVwW5A24\\/wAe9ZfxL1CwN5CqzwSqkjG4mUrjcgBAypIPQd6s+IdMa9Ftp+o\\/6NIiJC4ikC+cFUc47HA7devesvUvDOnX+o6ToyXnkwozLOu5MRgDj5VJ25Ynk\\/41MGua73G9tGQ6P4n0bTobq21BZZJ2mE6zRKdm0joQTnPA9Ouaqt44t720ktUuGuIjMZIoShRVcnjgc46etcb4zs7Oy8RSadaXbXcKbUyhHJxwM5wcf56VR8OadcNqaST20qWquPNJQnK98AdaJU4ptti9q9Ez3O\\/bxVq\\/hVo7EQwtKC0z27sGZCAOowAoxxkE8nmszWvDceh2H2291SORzGAwlX5gw7IT0GKln8RavcWEI0BFsNNClvMuY03ttDEnZk54xgc8EetZ3jTT2u4NMNzc\\/aLjLFhMQ26MgHJAHboM9M4FYQl7+xUtU2cvcXx1K1ktNKsJ40SMqoMg+b3I9\\/WqemadPDiS8iLMmAoCDcpHYGruuomhxw3Uclw06HGXTaGUjps6Dn3qppV9eakszx7TuO4DH3cdMDNY411bNqyj+J5eL9or2tYsrIsl47zZZDj5HHH44rN1ywub6X7VZAZKFXUuCAfYjt064pbm0vctH5ofcMvyOB3qpbXiCJoWQIVGBjjp6isaFOUXz0ndo5qNPl96Duzf8AxXdvrdtM4VlRlG7oRX1\\/4fm83S4HznKivirw3eyrqsAJCxiTAU84r7B8CXPn+H7ds5+QV9bl3P7O0h11L7Rvakoe1Ye1efXKeVdn616FN80JHtXD61Ftum7c17dHax59XRluwlyAfatBWyuM1i6e+MVqRt1FO2okzzP4s2\\/wDGAelUvhxNhNme1dD8Tod9mXx2rj\\/h7PtuWQ9jRP4kyoP3WjT8Vpl5xjqK8L8RM8Ors0agvnjP1r33xUg3ufVTXg3iZvL1WVigOCeOPzry80hdJnZgZWbRk3FtJG6Xd06NLNIWO77hHc5FUFke3uD5TDJGM9jW8HH9mFdquXyAW5KrjnAH6nmucClmcoOFBJOe1eTF6XPXi7rUlVHaXZlVfduAZR196vsk2qXUvmooNpaE4ijwMInU4H5k0\\/wwmmzzi11C4uLfc+RKihgi4PY+p2\\/hmukjvdCtrHV1gupEnuJfLEkUfyqrjJ+XcF68EDI4PUdZkzRI1PD0mjtodlcalc3jTxQeVa29vGFhLBV2szLjLbnJ5GRg89DXqGgR6ZFbW+oW1jNaxQHOXTdI0X3WcI2QB8wBwW+8D1BrzHwe93oiRWtuZL62SV9kY5j3sAvmL6bgOfbHrXZa1q2tmzYSQfZ1unUyoYhH8qsSFUDjaOOCOCT6nOE46bmkZanb6ZrPg5W1u7n0a5ukUKYGt+TAZEJLnDYA3KOeuTjPavJfEc81h4haUyOLdZm2iYFm2xjcB5h67VYDqeCPaujbUrOe1hht41gt0JmLS24Lyk5+UuvzAgKAoHA5JwTVbxto\\/laNDqKJNBaTi48hYpFkIDhD8zZ9cD8AccHOXJyND5uY5q+1axuQFtbiGZC2+QKwymDwcjkEAVnxarFa6pDJbqsEMbFg3Rg3p9P8awt1xDBcMG2xk4BC53HjpVuxMQnVLhftCoNxY57\\/AI8fT2raMES5XOkvddtbi9NywE0hRtrbeC3B\\/p0rPvrNNTv7SRw8KMx5VSgILE\\/h26envTZZ7GB41Ns0inIRmGNvTkYGcirm27lheW0tS8CqFDSNmTB9xjH4e1Vyom5sDSheQkDVIJNqsokeXJkPGFPJ4HPPv3qC2068tNZk0q5uLS5gIMqedLw\\/THAILEdcA8YzVC3g81bhJd1q845EYViXwCFJ469cgdQa0NK0+y02NrbVb21mEpJVnUPIg53Bc8DJ9jnj1rLlsrFcyWyKj6TZarqU1xaTT+H4wDkNJuadsYyADgAkHOSaz7O1uIIWu4NSW6TcOUB+Y5OevfJ7Hv8AWu0ub7w1p+iGCWxltAHY2nnQtJJKuAS2Djg7iMMcZ9MV5vBFq85kvbO6VGec7LUDbFgnkKOwye1Ry93oaKXkaGnavFa6jJI8TGOdNojDkRjjpzknmu00VrjULgJbl1fymVv3qqApBGGXHIAxg\\/8A6z51OuoX1obmDy7S4hct5AkJwRjsfrnPv37XdG1bVYby1tJ59QcWQeVYkRVZGxncvTcM8EEkc8elEqSeqBTa0O3Gm65aX8kWnXd9st4t7IHVWAHJJA59+exFGpaheQ6fDLLPayTSTHMaj5\\/TJCDjGe59Kn8MeJ7qbVXvbvUJngZlE0uxzLJwckxquFGVwM4wAOo5pdb1myvYls4dOTzmbyTIwKPIM8EhVO7PTBxzz7VjyO+pXMmNdbGTTJmtLma3MjCWTJJQZGTkj7xA5wQDgMa2rTXLTTfDqte3Ml+WtyB5YCpkAFs4G7q2O3biuTutCuYtV8y7s5LaSzBSNAGVJRsBJO4KGPzDPJPOcesMF7f6gTbeS9zHGhjJTCMo3Ake4wB0PYVpye9uRz3iaN1bW95FLq8OnRyNctiMKyuYl2gcbmyW9eOpH0rnpdTuJ7e5EtxeyXcswKodka7EHHQ4H0+mD0roNL0if7VFbXaG3wUKukewryfU7eMdSV+lVtSW\\/aWRbu3eRJLooN\\/HJOMYCn0I4zz35rRJ3E2h\\/hHxBe6VqEmm6xb2\\/wBllRAwU7WixjacnAI6ZPt+FegeD7jSbVNXmuIHjlaTClYdyDIYcPj6\\/lXlipdXMV21zbRrcWe4JLbAbwVUlcgDnBZewzk816d4T02a98I3et3l88TxwCO0QjI8zBJ3D+IknGP1rCqilYwfDptptV+1R2yXcrCV45JP9XbsQ3zBueQSufQHoeKitvE9zHE0UzI11av+\\/wDPkbY4EnZslhgkn068ViWPh691ln1OS7NpBHcIY0jPz4UAMwySdzEEA+nb5gK7ay0uxXT5ZrjcLiOUtlkCsyhssCrYBPXAI44HNE0oIafM2zrLOa9jthdXkM7NJbxJACm3IKucLgk9dpJbGMZ71Ta6uvDepzWsMYcXAKyqwbYr+oz2xx1q74aSGbU5NVmme8yojtXldSVHJYgDpngbSAeM8dKyfEUNzPdSS3VpMlxJKY4RzlQQNp4553DnHGKw3dhqyVzKv\\/EEzT7mt4mbeB93c2B34NbNpc30lwCxaIsm9SWG2VcfN09B71yMl29vcC3W1AiklAU+YXPAOecDrznk4xz0rutAZnks0gi\\/dp5jBiOWDZ4J7DofU+1TJcppe6ON8eo1lrhIaCUqolGwY4OVGcHPQfr14rmtYjtE0yW2kuV\\/fQgnYwyG25VR3Ndr460+9ExEcyxxhUWUs3qSTj1ry\\/Vc2088gVFkwJI2lG35znnoTnGPy60o0+Z6PUcpNRt0NTw5FLZ+H4EcSYI8vydgOCQDlunGT+g9Kp3cUVzdvGjuqqjDjgDOB69eTWnpsccmkqfP83zxI8m4\\/d2\\/KO\\/J46e9Zo02O2QamJR5k7NGEyeR1JPPsO\\/alRtCo4z3bHJe4uXY6qG4uv7YtRcRfufLEUaA54AwAce9djcrb6haSaU0BgaFllIJKlRgEgZOMnBGfSuKvLtbW60qeKQNtliyQN2OcZ\\/z6V0HiHUlg1LUXhiWR5Y08n5TknBBx6Yxnn0rr5GtTGTvojmdQt444rpbW5ilR7jyQX5kUAKV6Y5yTz7j61t6taQQ2aWxEk68FyCM4xyen1x161y\\/h5p0E6X6GV5bligLYZjwNwAHbA49jU2vavLLqD2qBoY2jbAxjIzgfy5rlrVeWTUVqaWfLdvQxL5JbvyrlG83cCFVhlhjv9f61reGbJDcq93+8RmIwWO0MACSfp6VU8IWzHTbkm4ee4X51hVS3yg5O49AM\\/0rodMgt5NWn07fGJooWkPynPzFSuMdejemcHpWVaDqRkosdKyak+pLZz6QBJbW3lSm4cqd3AB9B\\/jWLqfh+GzkkltvLWS5HlwgkHj2Ppmt7U9LtNNgimkhzIsZMZGR3HP168ZrNmea\\/ihnub232RDeirgErkHp0GR61wOlUw8rxlo9zacIVI2S1MW5XWNLgh0yOZvJZflIyS2T2J7Z4qvfTX8caxyTylFJaU7yzY44Oe+PwrajiTKXFyXnVH5g\\/ugfh06fl7VleIxcXKx4je2iLhSXbZvYcjPGME10RvKSTXqznlQaTdypfTLfObcRv5SnAAJJXJPB9SSetc7c2R07VI2nieS0jYhMSOqA5yTxzzyO2a6tIbiygFyQ0RVf3mCAHJ6AE8c56+lS6cU1G6iimtiEdyjMMkH3966KVZ0tY7HPHWXLIl+x2\\/iS1mW2vrnTESPzraKdwUkIHUA57gLxg5PPWm+EPC8kXjaI6ldx3SPEQrAYAYZwB68fTrWldeF47W1iNrPLFNyCVbAIIweM4Of1qhZWGraFOuqyTpezKxKwyYXKngY4z2GK6qePo1FZPc1eHmtj0bxNolhaeF7lP3WI1ZsGIy5+UnGP\\/r4rktG0TSdZ0C31bSh\\/Z11btuSS3JzvVsg8cH+Htiquoa3P4hE9tcWd1EtunEZC7XJH3n2ggkcY9Oua2fhgxs9TubFxm08j7vy5DgKMdMD6+3tQ5Xuk9dykrJNh4NvvEp8cpZXrW724spPOAiKpMwxhm7KcenoTg9K3tVtpk2T2yxhGGwRSy7Y22qCGyRjJ2\\/Q8ZrlPEuvyeH\\/E8Z02W3lvGJR4XyQQQDtOOntj8jVLxH4r8XT6MltrOl2CAyGMyTSkBwx4Xbtx0OOvap5W7MLpXO51XUxDplmgkSOeSQs7AKQwfdls9+PTPfHpXO3izS2k1vKGddqFQ0f3c54yeoPHT6\\/TE03SL8afaXJmaPcCt1bRYdAP4igbpwePriqVjLqkQv7u7luNRRHWKCQRBXiVSQA54+XD\\/mBx1rVb7iWxsR6bM3lMsMiwecgJBBUHdyVXBA71sq0fki1uYZ3ZGaRnjbsFZlx\\/D0BPTnmsO3a+060S8lgE6hGEjICpjIYABlIx16cjnNdGVjvvDe62MRcKZoyrHCkptIwM9O4yOa0uHkchDZ2KW9wI8Rm6IAVgGYtnO76YzyBnjHrXQCdI7vQLEx7VtlZj5wAw2MDkk54NZetWbWVpaXgZtgdGm3bmIVSMkADkbQTk8VZ8UavHbXtu8cQuMIY4RAuWC7CehIH6VUbsUki4GvrfxM8092ixAiBI0+UF2bqy5x0wM+mB7Vt6de2vkpp8U0MdxuB2TFXcZypbGAQCQBkev41yFnerfT6fKG8tLYiWVJ12qGGzkHJA6dvWukiu7ax8Q2RTTv8ASmMkkxkbAG1S3IGBySSB\\/jxDaZVrIZ4VLw3FxpEn2RBbhcIjHaVchiThsj+DnnHr2qzet9rt57a3Vbh0JluEbaI4iSAGDevXnvk+tQ63dG01OLUXykerOsnlTZ8rKooGB+HcdPyqC+166EWpM2ly27ubdPNQqictwOOduCOg68HFK\\/Qa7k09haXFtNayPFczXPmrH5RWRgvyjnIHOT0GTimW3hB2lv7iewSKG2jjMEUah2zgYBI6KPw6AnvS6hby+XbqsRs\\/IdXEnmDCY24Y5A78kd+eetdDoVjFaRCOBI5or+DzJ2kYZmyc7iMFQOeM4PAHpVb7ibtszyZ9ZtrGXEunqWMm4kuSSCfQAdyOCcdKqS2F3fRJJapGJi5I2rxtJ+UHGfQcHFXPGekxjXWWOVXRGVI5i3ysSQACCMDHTPvV+60+awCJYXsmBEZHGMj5TjGAO5z26HOa5o0lfmjv1Kk+6K1jF5NgbeZCxZTsk3kbWPQYAxg9KxbK8iMcq24aR5iQflySSMkEYOenX61JbXNvc3UEX21BE\\/z7A4LBlUlie\\/DfrUOmC4tdZgaKBygy6gjqwXJJPfvV+z9936g6loq3QfqUyad58FzaFYZ4QskgPzSH7wGTjHH6Yrp7TUlsLOwW50qQQhZWluIxuDAqTkAcj7y9R+lc7q7f2rpkn2q1kdoJVQOCDuUEYbGeQAMcev1ruLjRlOgTXFv9o2sqxqGU4CnG1ge46g\\/WtOXlRKlzMLWSaSzklkW2ayktyVjkAOCo+VVPY8+tZVzbyP4dtHgml+wsifaHlQLgCRzgMTnbhOcfUelWbiOyvfDcktkwkFu2AcFcpuOAVzkcY4NJb+JILnSNOsLqIxWlq43oLYsG2Hlsk5ySzcDHPelKaS1G01qc94Ug1WDxbBdvNIUibDwsh3bQFHQ\\/dHRh3GfxrQ+IF9HIko23MEq3AVDOQu9CeCCuR6561raVrltbLd3CuJDcpuhYBTJF0Uq5wSM7euPX603xlPbahJB5TAOI1fbtwwZuB8uefxHfpVqd3YmxBFafZra1t76Brk3GyMO2GyxUtgnjGST61xnj1fL1hLfy9gjXb8sn3WbHT06gY9q763vry68Q2ktyga200ZOwcE4G04zjq3bpt6V5prSzz3Nzc3kgy0pxI4+Y88DgevQilCLUht+6c9eebDb2ySo7gAyo0mQRkkAjPX\\/9Vb3hBppfDc9rKRtkudqSv1UsvKjPQc54681U1AmR3mhZyYWUMik4KnGfxP8ASkstOntMztd7Iotr+WTjc\\/XoeOOv5etaS1hqSviOnuBBYWNtYJbxTuGJEmwOA2M8sc5z71XPhe61u3heeSGAOW8zzUCFAB1\\/ugdOi55\\/GtOLUdIltLO1ifDSENI8XDM54O44Hb19fxrWt9MFyzKFAikUgyyHAQAHofx\\/OvJnWlDyfc6uVSdjM0Lw0y6PFaTmGfSckrIeCxyPmHXg++OOaddWum3G9xa20Cfc3IoLHA5z0z\\/gK0fEtq8GnW9jblxaJEgUB+ZMdR9OO\\/rXNT2slkGmWZEWNdo3cgHvkD9Kzg5VHzOX9f5hVgk7CpoNtbRyxWeoN8w2LESNocjOQOp\\/n71FLp2qPp32S\\/T7JHH\\/ABIM+bgcHjt7etWrHVjJL5TWiW8A+\\/KsmWP0Gcde+a1tX1y+trJM6bGbZzkTZyVX06YJI9BWkqlVSUbXJUYtbnG2Gp32o+ZZuUjtIlEbTSHawHQYzxk+9bOnDRRpaxQkOioEfzG3gMc9PfH5VRubi71RZ49PthHuLCeGGP8AdAD+ItjngDnPY9Kr6LaG3sls7+1hFrJLs83GSzcN16Ang44znHNeg8OpJfZM\\/a2fcydWmntra6jgdViaQ7QIxhQccc+ueoq14WkNukMwhQujiZS0fyHYrE7vz6024ikit7yykjfyWlDMY49xyCSF4Pp+lbXhzyYvs1pOjIbjfFAC207dvzHj0IHX3966E7Kxi1d3O01+5sygi+zWg3cTF4wTtBDdSB\\/WuQsYVmnlfTkhtIQcsERQGHv3z9a1Ybv+1YPsr21n9q2quWuB8hGOcA5PsBU9rDLZQzXclvEsUKBJD0DZxjAPT9a5I1nCPJ1K9lFu\\/Qjl0lLVDvEe3H\\/LRwzZ9hngVa8NPcJY7NpliBwo3HGCfQemTWJqXivTXv4LLTomk8z7xB+4xxnpj064q\\/aava6dZlbm8uTFv2r5cGJEAOeG9MfyNTWpTcbNal05K9zUEv2O6SKWbzYZlJ2Iy7Y8ds9e\\/wBajtrjRpL1LKS1bepOWfIC89Sec5OO3NYWsa9oweOKyslndgfnBG4HPUkglqw7LWI9M12SS1ZjFIo81nG4ZHPA9Kr6rKUb9Re2SZ6DP4g003flRwb5YiVkDqN\\/fJyOMcd8dc1l3Igu7bzY7V7WLBcyh8oRzgKMkBuAeMVyx1yKa7Q2VncXKZKyh5AobOQTz6j8OK7TSdEvI9OSa1hKwy58+CVVG1SNuM9AAMGs5Uvq6Tv97KUlVewzwpp2hvMot1tGl42MtuCxABJL+n1HGa17jTktImWzgW5QE+cIkX5BjhexHXPXp9aj0bVoNGMVtrCPbMJvI86JFUPx146gg8H0q5491p2QWvhiB52hjBklDnYB03E5wTxyOtc1StOVZJXs\\/u+81jTioX7GHq10lm3lQwKZeGZ2RVK8ZKkdcZ9PSti01zUYNIF1bxo8ibSiNklyM5x1IGcHknpjpWFaWN\\/qEb3i2kU624CMhfBkc5Jbg9Pb39als9Vjt5Y9PZT9ofhYkYqF4GQOpLHnjtnrWrhezjq0K9lZmlqV9caheQS3lyVutzZiQfJ0x94nnHsfT0rpdC0zT3tm1CPdLLblmJnf7jEHPU5Gee\\/HrXnmp6iPPVUHzrIOJMKTjr1PPTNc7rOo6jevDb\\/bHhXO4r93IIGBnjPeoqYWtXslKyKjVp009Ls9B8WeKYrMC0aT7ZuYYgLHavToV7D8fxrLsteNzqtxbS7IEYhj5JIQHPI6ge\\/T8K4eGFm1MSiUo3HX734da6W8mt7CzjmUgtC\\/yl8kSNyfbnjnBFbfUqdFJW1I9vKV2dky6tY28s+mSSQrNncob5R39Oe1ZS3HilrpYzesobggsDu\\/UH\\/PtVaT4hRzWMdlbsLydgVJiiKKp7YGSfT\\/AAFQ67B4gt\\/D4uokkFzEvmSsj5cAjOe\\/ct71zLDq\\/vpJt6XNPa3Xuu6HXt1aQfaLvULgbI3wu45AfGCeRyeT05xUGjXunXy3Gm2MhjgMwM8kEYMrk8FlP4YPXivP5Y5ntobu+u3ZZJGbYTnPu2fXBqvHeyA7NNt2jmlOMhscE8cA4r0vqMXF66nL9ZalsXfFC2wvriOwtJksYPlJmyGJBxkn8Kl0i5fTtMnnupPIuiUMSbd6svBye2MHgGpNG8L3epXkcmuzSOlwfNIikDMUwTk498fnS6slidVKtLcy2FuAGCcM2AOGODwMema6IyUlyb2MNU+bY0bG7utZnjnja4aWNRwHAXrg8VL4iu2Gh22mm4aXYxXHfBz16flToNRVQLi1tIliKhAkKhBkcgsMdex9aZCl3eXH2m5jCu8nJKkKuRkgVMY2adrFSldNXLPgzT7i\\/ksJLiNYrdDlFUAMx\\/vE\\/gOOlMj1SGxu7lY45HmklaIDIYFVP3geTjPt+ddh8PNPnMUlvJp7v5W4o8ku1eRngE\\/r9a43S9Eu727vJo0eaKOV49iZADMxXAI54yOxHWm5Rd77CSa2MnVbmGPU521HKNCpDfZ87SSBxz7A+lN0CNZtDmvLaK5E0bZbZg8EHAx06Z4\\/KtXxLoEFhoyQQwxyzXD8Nv4jfc2QfX5dtZ+lJeaVZ3FgIoOZSWZw3ykccYI7Ann0prla0DW+plaRpt1q+oSXUiTPMrjdFgln56KvXp6VevNGubTUob9rgR3kzB4YY03MRnjoPlP1rXOu\\/wBjmL7LNFcTyIhleRSgGfX\\/AGfcfj0p8Or2N9qBupbNo4UQRiP70UpBGSpzg5OTyKqLbvfYlq1hw0VLnVLVI5VYPbfMQABkEAgj09Rx0rU8P6K2nW95YtKk5bDOVGQgIYZOAemOlJoVukiy7INirC0lqhdAd2fmLDI456cVDY3ssPnDUbu6MpHyMsOxNq4LEZHvyM\\/zpb6Ma7nZeFdT0jTPFOqJczwWWn3FrFJA1xIqrKyFgTySFI7DOeKs3899rt\\/bz+G9KSWzWB\\/9OYeUsjsVJIUnJA2Hk8dx615d4\\/1q98Qy6fp1vaIlhZBfkhRlG4gdRz8x6nr\\/AFrttK1HZ4Uh0aw0uezSKDfd3DqAJVGd0Y9QcjJ\\/CspQS95jTbVihoPhSHU9Suo7DVLC5vVOWRW+Z+Wbhh94YYdK9K8E6Z5d\\/wD2fdWMCQshkjLSFyCV2q20KPl4H8WcmvNPBl5fw+ME1TT7KNZ5JCkcJGzam04+U4JHAbn8OtdZbeJfEenare3c8zfaUjChUiDFdzk7hkgcgd+mOKxqxqp3i9C4cvUq31q2ifEK60wBmjl2vC0qABnY4J25Ochse\\/FXNas2Ie9ht4TdSuqh+MhypHGcjGBgnrXK3mrS614yEspd44MvlwM5G3AXBPYH6dq9B1K9lm0yNfKmCCVSVZRvDA8gAYOOvH9Kmq5OUWVDRNHnup2FxL4GtrYweY7yLunK5aEKSQFGPlJ+mCM9OM3dEf8Asywi2xRwvPDIrTuryn5kIy34fwgZyeMmtfxBNPpcakkX9q0YeRFUABfuj7xHQ9O\\/PX043TtSu5b57DyhtljKYTbjCEc4Y4Iw2Mg889Aa1u7XZDtcv+Nhc6hbghRa2nkRruaZN3mbBkAA\\/KMg8AHt0NXfDx8HXPhInVJ\\/LlCo8ccj7YgcBTgZzkdwR2yM0usafdwaCsl3IpgiDQokUshBYHO0gnC9T69OlZ9rpjXbxaFcWrCFIt0scWcMx9cDGVA6Dru7VvGb5TJxVzyw20drc3NzIwuWVykeRjCgnBHpxitHSNQW6ltlkimMfzALv5JAznuMA9z+laPiyxs7LVruziLqBAuFJBw+ORkgex\\/GsbRrmNxp4V3G5njWMRhsZbg47nP4VzyXtJptf1Y5v+XmvQ9s8Py6HBoVrG9zEb2WNXS3K7HJHDdPuDiqsEA1O0eKztrGCWEOiO2Y\\/mJXaFz6cDgc+vFclO8VvNcWelRG41eWYRwyynHkpj5mJ\\/Tjjmu2ksdSGkR6fM97MpUiTBAO4HIbKAHg8e9aUqKhqdU6kmtrHn3jbS5YZ7aw1gGNlI3opHfnG7+n86y7SbTrW4uBBPGgZcgL9Kn8Y4t72OzuEcyzyALvcnJJwc+p6cmuX1m3j00eQCJZiTuYdQOwrHF0o1pqF2tNjzsRT9pLlbepJd35uLxDb+Y8fPygkM\\/v9Kr29vdPLiNJFXOG3DlT3\\/CrFpFJY2ZuLbpgEsyc\\/wA+n1q3b+dKPtErCGNzxnqR6\\/Sp9oqStT22M3JU1aOxFpVoYdSActKVIbdnAA6j69a+r\\/hRceb4cgXOcCvlLypTeSzRTxbI8BFUjJHXJFfS3wVnL6Gik9q9zKqrndNmNaTklqelk5Q1y3iGP95urpwawdejyCcdK+io7nBVMK0fbJitaJ8kfSsVSVkFacD\\/AHc1q0Zq5i+PIRLpTnrivMvCDGHV3Q8fNXrfiVBLpco68V5Hpn+j662OpbmiSuky6fVHXeJhnn1SvAvGULHWWj+6WOfqPX6V7\\/r\\/AM0Mbeq14J46Vl1qQ7jgHH4V52Zr92dmBX7wx1neMyYkTDJhkPRh6detZlvIytPGsav5q7cEZxyDx78Vq3KNFaAxh2R0IkcLkDnA57Cs62iwZCW2sOVJYLn8zXgxtJHsxd0QRSzWsu9C6Erg4JGQexx2rRsrLzPD93euDuLhYzn+LIP5\\/wCNZzSK0JVlUNn73U4x0rp31gHwbZWougsiO7bVUABkxtyO7c8HA78nnA\\/I0R6X4ItbKx07S5ZpfKk+y28m9IWYKSGwZCx6dMbRjDN\\/d56S6t77V7W3uftCy+SzvFZpGXdwCu84UAqOD+AOOhrD8CQ6tfQOl9dK6GwjEXnQlUIOeUAA+YZKj1DMR0Gek0+3hsNJuoCn2a6W5tglyJcfZwpYHGOc84OM9c9hXLKSWkjW3VDlsWbS57K30u5tnklChCQ7y7mXAPIZVII9BxncaztQuBN8NLO1Km2uYLmS3ZCpZnJBXOO3O3jmumnuLPS7\\/V7VNZv5ZNO3zrJPdpJumVMhQCPmwAeBwAPU85fxt87SLaLTdxWSaMv9pWJYzIccZwOuR69OtS\\/eSEnZtHjWrafDDo8yyzGWRETfzhoiDhgFzz\\/9as+y\\/doskb3CFwecY3YJ79vpUn28\\/bLi7vIhMxRg6Pglyc4PJHQ\\/jVIQ31y620JYAxsV7KcAk88+nSto3EzpI5mMe+OR7mQthfMO49OgIx39PXrWha3EkaPDbRTyFl5XoR69fxOOew71zdhZarcFJwqRESneyNtcFeDjjA\\/\\/AFd62tQjuURI9jvbh1SR5lABHruXHfjp7\\/R2ZOg\\/XLuaSIra7EVkJ8zHzgAZyMZB6fhzXL3Op6nHKtuJo5Shx5oKEnkcnr749qr6nco8jLHdOI8hGKsZMDnlfbgd\\/wDCo4Ly9tIv9JjZUlBIJhDE8D1OB25waLOw00bK6vJcRGTUJDcyt8kUeV\\/d7f0IOc5xWtol9FDYldkykMpiLKCTzk4GQeSCc89e1c7pa6ZZ31ss4tLi3mYebGCGfHqTgkc46H6iu1kvIFg22KxiNhuwuB8mBwAfTIPb8KynG+xcXbUxY5Xi1Py0u2gglwC6nIwTyeoyOpxgj866K9t7TVbqSe7hhKmEJDJC4IEi5w3oN2OmPpmsC5a1tLxU1YFlOQpBLKnboDgEZ\\/8Ar1Loxsbe52Q3cq20jjarSFkJ7Ec\\/KevOT17UlHmHzp6ofHNd2l5He2Vo4dF8l0dIwzYGD82OOcn1xxx1qGDW7CSZ4ZvtP2p3DrNcli8JB3Eqy4xyexA4zXQXMFytxMtmHe1ji+dhGW25BBYgc4469hWVfOkUtnB\\/r3aYqXhQDcpBBB69AR69Pxq1DQlyVzp7bXbiVLrS7lkJiCyQSxfMm0jOenUnnPX3PU5kNnqNw\\/mM8JiiDf6IQy7xjcRkA\\/NwRz3NVpUtBPAkUDQSLFsZgy\\/MzMMcHqc+nY9+h6e2a0uEaNTsuCGSWckfMwBONoKqevH1rKzTKsmtjNttW1eO\\/k8y6aWZZGi+zsylQmPlyBwzZyDxk+opIWgtrKd4YLl5baQ+fbGEncC4G04kKv7MOxPUVz+pztb3Uzw3EmQdsiy8hh0OOTitNNdsTp5SxucuEAVCql41IPDYIJPzHnHGT1qnKQnFWNmfX7C2mjudMsLqyjFp5MtzbAJInIyXzu9SCQAefTg9T4f1aPV\\/CN7Kt9eJtbKbW3fux1aQlTuPPr9AK4q2laCL7NJLcXkZw5DQsyNlsAEZxyeP0yK2H1LSLPwqNFi024jnxIV8tS8YBz8mF7lgp61ElYNyLQ7NP7RRb1dxsLhJPJt4RJHdo2GDMgYdMc4zyvSu60u4gk0G4hutNjMMSsWZlx8xPVgQCnBH5\\/SuE0e6tre3\\/dXX7vaUDKhG58n5Ny56854xjoQa6jTLy8u\\/BV3KsUFxCZwkkTFgwO0ZUZHOCRyRyBnnNTVi2lcItXNjTvtF1H51he+XDbNiOPblcgbRg9Scdau6os+o2bfvWimbaoeMZKbSSC+BwOnBPvxisPw\\/c6rZ6It0LMXFg4dgNpLQtgHBxnj1PGD2p95rCPpYkgjQvvImAiBi3bd2zcAMkgEZGCD64pODeqBSWxg6lHczarLdXv2N4rYkgxKsbEZAxkdWI9c1u2V6lrbfMEhTBcOzfN7DGc+35VgRX\\/nWt4s1olnKEWSNYV+VRwMgtn39K4rVdVea\\/RS8kq7SkZd+M4H9TUzhpo9TRS6HVa14hgvLxkvJBHas4BAPzEBAMZOeM9cetcd4ie3l1K4hglmkGQq4BwDjI5yf6cVY0jz5YjHJCrQxbpnMrMFYYGGAz7EVz935st3IkvnRysxe22gcqAcA5Oe+OnarhTs7hKWlkbejJBNHcRCRoXhWNduAN6sepOM5yPXvzVTWi4OIi6xBiGA5BBGTjpnOc5q\\/pRcakbh7UCFbZSrRAE5A+8ccY5J55qxr1navNdXFnbtFbwqWaQ4XDnPbjHT1x1+lKcbtO2wKW5l3l5djTYEhhmZUZTuVwSOhwAfT61t6BqM+p+IftUg8yG3g3yYHOfuk457E9PWqTwp5UkJujm1clQATuyAenrz+QHWrPh2zvYHlubuxdY3j3o7LjPOBgY\\/T6UlU5m422KSs0x97bXZ8YaelnM6whxNhhtL7v4f885qzoegyeIL2+mkhus22FjLkHqW3Aj8B3HWsO1ge4R51LhUuCplaQjjcGVRn\\/OK734cTsl5d+XdNJ5yfvNxwSwLc5x6EHHbIrGrG6bfQpass\\/D7S307T75Lu2kVyCwTH8J\\/z\\/Oqvha00+bxJrGquG82OXyEJJwUUBjkfUnmuzsCbyK689QXgiw7r\\/E\\/PPHXr04rz7wHb3B8Z6o1leRvb3UT7oXyGWUM6kjII+6FznrmlCL5WUx\\/iuK6udEvLw3kiqryNG+PkaNR0B6jkHnv1rOnht7q2t7e1JgNxAsvzqARHsU8evPH1zWp8SNVk+3Lo9xCIYHljgDqmMKSRkr3HfHXrUllp+l\\/b7aC21KO9AjMZjVtjBRlefTkjjHYVLhzQGnbQz\\/D9ne3Gnfa4bd5ZIk3ymU43EMdvHXbjAPfrSzwwQXk0lyiJK8DSW8Uk\\/loWzjYuSNxBJz+PXFeg+ELKA6Abx5GWNmKnAUtHtY43EcEjHbFedfE22S1mN4GE+wCNNyBew7ZrOK5p2fUtu0SlqiNf2lnaQwhrqUI6TF+ChAI+XpwM\\/pWjNdm0uLSO5jBmcBnckkDkA5wPvYPb15q5a6Q8Wpwi2I2rbDnc2QEGAFyeR+H5Uy5srq21EmaJ181hG0pIYgY5wOc9u4rkq0buy2X6lxavzPcXUNTt5Z3kUSHynUkuu3IGOMZ9Bjt1BqlaX0d3J9nvUyzSN5MiqSpAB3c9Rk8dKr3X2yO0ugt2gBIV0AK7fm5xk56EH86zkntp5oFuJWicKHEb5Acr\\/dK9j1xThg1FP+mJ1EpXNGeRrW+laJmiDxnDFgN647ep9CR61U1KG6eaVrQyDy2BMoQKXyT\\/AHcHB\\/x461tR2cN9cyS+cfLhQmAQ4UMckYPHXGfwrB1NIbm6jgjNxBAjBsIQMkEHnnpyfzrbD1IN26odVNanPa\\/NI4aRoGi5ywSPYqtjpg4LdM85qPxJrGr6hpNva3M5kWIqApUF2x3yOccAZOT71o6\\/9nsxJtnSVZY9pkYNyemSVOCcHHTv0rm5JobS9823BkXjaocr3A5I\\/lngCu+HkjhrSdtdjvvD3jSN4Xguk+zRHDRhsfMOB36H6dear+KdRI0+7exuraHzBtkJI5wcjnPHTrXnt9KkkflxRgKx5VTnJJ75J9BXSeHfD9heac1yYon3RjC7c7WH3hk5\\/pWylGKu0Y05qpKyLHhWw1rVdON4upF4IHZH05pTslQjcwJABAbnHHFeieEdT054LPRJY4rLUUYqC7\\/IyqxGFbHXgZ45HSvNde07UbOB10aZ4kOCyhivl8nGCuD2PrXOvq2tQRxLeMCA+9JHBLbgSdytnOef5U42nqbO8dD3jxFCH0R4ri1JkmQpGkspJOVPzoGIyuME+nIrP1bR4bm2tf8ASGLpDy5O3BYkHtjp35rjIPiJqbRQQ6zLJcWTspYKFBZByfoT0zj2rq9Iu7HVoRLpk7y2\\/GYipLRdSc4OeA3P0od4oas2W5LWO0jtLWK3LXDBI4i2SDyvOOO2Dz0rQ02ORtQYNNBJdxtIYm2ncQwA5GeccDj8hVq3guortEkkijhkk8wfMHGMLtwR7KTn6ehqrC8dvq6yWUqs7XB81o2KjLKRsDEjnng5HOKmLvqOZ0Pj+1a5TRoYjtFsyPJKI8lNqhiOe\\/ynjriuc15bS9I+0pJPCfLWPGR05y6nnOeeo6jsBXZeKre5GhQLBDG0zmLcvlFmDNuOGOM42gjrz+dee3smqW19HaxfZrtZXfcpZgqRuCF6DdnBznp9RVNrqTG9huuW8Mt1Np1pI5fYhDOWAbcVJPXkY6c8V01m9xZjy1v7eW0MQVnuG8pIFAwd2QcjgDjJ4FZFrYzXutTaldW8redbsIrdZS2DtVck9cDiunn0ZZdLi069SS2tlj3OocjceVByOcA+\\/ahr3boL+9ZnnHibVIF1d7m6eCaO9kYqzNvRQFC\\/e4wDxznIwePWzraxraW1xZRSR3ckUgli2Nhs7cDnn+InPOM1zXiu\\/wDsF1bQWNqk+J5G2yQOoUiRjgMuA2cdfw9a3tKnATVodRjigkjVJUESHau+GNwiAnIHHr2HWs6aluXNpOxyHh7TmsNJuLoRrDMlwEMzhsRq52nlfvcMMgDtVi6sbu5uJUiunlN0SdojMQt0JHADZY8AdT3FdDb3cep6Lp1nFYqYkuBiVz\\/rSp25yRx3OP510NxYxRXNxqFwItr5IO3PygcZ9OgPWtZTVyVC5yF9blLWxtLVoIIWYSzhsYIzjIyPfP0FbehX8mhWs0AinvLSdkWVC4cDONuzaefvAE49OhBFU76J8aZHC0fmTR7mkA3FRgn15x0696NJsL26hQaeomMNwFEqt8s+xly2SMgEDjH90\\/jMlzJND+FnRXGn2I1rWNEsruOw5EsfnKqKEUkv0HI+YDnnK471k67piQ6S6LfxSs0piiiMRDLhycHp1Az6c1vXgilMF42+a7l8y3BRhhCW+6wP547ik8UR2llcNZWbNPc2SyTkB1QzKAoIwRnBMucDj5aTh0HGdnoea3r2sFotvd2uyZxsdgCMDgY9evvgVLaambaA21zFcPJKoEVzkZKLgJ78EHnp\\/XV\\/4Ru21ASTXcEgdNoUpkEbmORtPsMcmsnxGNJsg9u+Y3PKTMxYhQfujHHXPX1rJQ9l70bu5b9\\/yF0XUmZZEN3It0JmWNyoBdcDBIP58jGO9ZGr3EdxdPa8wvApwWUfNx83454yfekkMlw0ZXy2uVXeJOgA7KemOTn8qw4\\/NIvL2+J3FwmcgHODn19vzraMlV16oz1hoylMzrO4kmaOHBEewkj2yDyc8mu3sZXksbZLj7HclFUBGRMFj2YDnHPufpWVbafbW9hC91ukjkJRXyCAwAbPT0zj61fs4RdymTEsiYz5QAMcYOVIPQAjA\\/yKdZXVgp6Mv6XfvuvHuVtrYxz+Wvmx+wGQpHGM8elaOq395BpUNj5bEyk72UBgB03Dsfyx\\/OuXnl0i7lu5VnmmRCxDzqMcdSCPvAZ4FDaza3sfltPemKMffVckqenBO1f58e9ef7BSlzNHQp8psw29xJC5uJUJbi3UrwFAGWI65\\/wNRXCSXN8RNcqsB6wjq30HUCkbUIRamW2EzOVVDu\\/eE8ZBIxgZznHtVzTrSVrwXLW3lz3BCyNIhJjXHG3Pvzn2qJ3hq9BSlfQrQxWto9xNPidR2PLAY43DoewH0qhqmprfs1heWgjs3VESeGTGPcgjjmujuNNFtcs928UhYfLGyjIPXJYnv+PWs17GxWfIhEu3KqrSHYpJIJ57\\/T0pU6sJO71K20MW5sdTtXnitJl8qdRE7bizunpkf5NTeErpLNI9Nn0+S72su10lC8gDqCMHjnaf7vNbJit02OV3orkoJUEarznr1P8A9eodXsILi381reR7iPkNBkbRz1GfTtn610wxT2ZPsk7tFO0v9NXUXiublZpGuWby0U\\/LgHavvz\\/KqXh+0k1LxrYJOHtxBkgFdpQA4x6dST+NYaW0mm+IDfzwt9ndXKBc4Bx0PJODyPXmrdtr9xd6jPcwOYpSDsA\\/gXPzHk+x4A713RWnus55PWzNzUHhm1KaWwtLZ4I2VDPKAoUAn5j69e1VvF2rQf2bcW1jdI8JkHmqr\\/NIcdRwDgH6V12reCGupyoIWSUYI+b5hjIB5xiuSHgmWHU0TUp5VwcCNIiMqMZ5AI4z1Nc1GvQnZt7EyjUV9NzK8K26ybJjbqoIZYipCktjjJP061Bq\\/wDbNzqM1u90JGCcoudi4A9BgnPGfWusvoiMRaZYhktmVUusEovJHyjpnjuc13GhW4ttOH9vXtobdlARXLMEPQ5bsckenWtK2L9jaclv06ihSc7pM8SlspYL02bRyy3AAXBGwqTwePrUmrxWFnbqv2l5pslWEWdo46ZHB5r1jVNQ+H0dpNYxzor3MbF7iGLJGDgDJye\\/6V53LoV9qNreXWk2d1NYWylhKtvhWI6\\/NnnjPNa0cVGom5Jx9SZ0nGyWozQrMx2K6lDFbX7ou1oJDyhJ7gdce4pw8T+JZr61jgmmhk3AAI2ELZxxjqOh5z+RrnLdpYm8uyuJvOcfNF9wqQpOfQjFen\\/CXw7Zy2GpXTyzyX8Vsf3ckZCRyEEHB6nIAA+h\\/CcVKFOHPUV+2hVJSk+WOhvvp66xpsP9pSRQwxptKIvyiRc45IzjGOceh4rzy3tLy015tHXVnjhYkkxRkPJ8pJwBxyenNOv9c16zgj0+y1fZADuxlUUeo5565\\/Sul0rwjaazH\\/b2v+K7a3uJIx5c1vyu5Bt3EkA5I5xx3Oa5OVYWL9o\\/de2jev3G6ftn7q16m\\/qOgW8l9Dp2kXsiecuJUaQokSgDDHGM8tjj3qbVPB0mk2i6vYQzXt\\/EuzLMGYnOMoOo+vOKjubP+xbKNb3U7G8jeNwLpBksoAwGJPHX9Kyh4q0pdiRa9cxaeWSJ4SmWZQSThic5ycZGeMVwQnWsvZu666bnQ4w+1ozC1rTkEsl+qXk97G5WYt8vkEAluCQMcgZ\\/xrR1SbwxommQ\\/bdNe5muFCuZ5SxBBPAC42gZPbHStKDw\\/P4sf+0YrmSOwiDvHK0m9pWB25II54H1rj5xPFdSxQ28E1+FMDicMVRCQoI5wM9ePUV3xkq1o31W6TsYW5E3bcn0fStM1HVC2nGKG2dz80iPleOW+nH6gVo3+ny3Og36RCQwWx+R2wqucDnPXjnj\\/GsSK01a6tbu2tNOha4AVmNuGyNp6fL247daavhfxZqOqxaLEbi2ivWDz4D+WNvB3ccngfXit5WTd5JJGWr0tuWPhda2ltqL3uoxRLApASNjnrnGc4GO3FXfHXi2\\/kubiCwhMaOPLj2v0XJz+mB9KzfiFaXOlSRWlo5EqsIyUYFJEAGGGBgVzsFrqOq3LROPOMQyViO7cenQ1VKjCpP28nfTQmU3CKppWLt4LzVbqOS105ZFjt\\/KliVM4wDl\\/wD9VX9F0SbV9Rt7htNfT7WxQC4x8pfHOfmPJGOcetS+H9OuVlFqDc2nmuFjbJRWY8YbGPzrqNVtY5rCLT9LxBNFAVb98zO8nJYH\\/Zz3x1pV6rj7sf8Ahh04J6s4R7Erduum3MtnBKwMf2xto2ZxkEcEE9O9V47OaaeS1uNShlQS\\/MgcgEZ4wen4e3NWxoV7ZQC61W3ubmAzHBSUFGyM5HU56dR+NE+n2mGeOGWF9xCkOEPAHHB5OcdvWt4zvszNrujpdH0PQPtqx6hf6lbwtho9lsvXB55I\\/l+VXPEdtDpc06aVLceSEO0XRCybiCM4x8vGODXFteXMNmGd7tCRgCYeZGRx9054I984OOa2NXuZLyFrue6BlkG1E3YKEcHcMZPA6DjnNJQaleTbE5K1kjq\\/AVy1nqcsuoahdTzaimFLxlgVwMbenQ8ceh70TW+jaZL9nga4kvLdWupxtKsGB+QEEYyc9OSPbvQkjMqJHPJFNqyRgIkTsxjLYwGIUge4+vPFY2vyTJf3s7zmS4kKyLERlwT1PTsAPXipdP3tx810a01r5muC1uo2xbEr5BHMbHuwGOcc49T7U3WtP0\\/+y72OZCMH93mT5hIRgfT3ri9S12V4iLe68y4nObhUyshJOMZx39a2rfULzVbI6bZiNYIUUHeA21j1Ylu47cd61cNEiE2tTI0My6jeNbo8gRFCBt2ACAcYA5OD0BPXmtzWtMtNL273gUsAG3w5y47heoPrj9au+Fon0yB7e287YfLYywlgzMPZSAecdc9Caj15NUF4BHcLbDzt3lS4y3pjgtj\\/ADmq0uLUm8LWEUTJeBfOjeVkI8xotvBIOX5AwpJqzqEFtr2p6bpOmgWvnGUyTO+4nIHzDBAPA2jgZ9wc1c0bS7VoowdZ86dnJjjlfapbaRlV2\\/L1PP8AMmoXX7PcYg3W+pW90JPMhkULg5XAIbLE\\/TtWUnfYtabnQ6dpGm6Zpn2dHTzipZEQBpW4YlmdsKACB1\\/Ctrwp4im0a0g0+5spb+1ZWRGOC8RKKSAGPcnqMflXKWl4YNLu4bazmuZ4pC73UzOAiBgoGTknJLA4PuadbIbpZbZ9QdTIuHUZJG75c5BDAAY4HUZznvmoO7aHdI6PDXmpQtZ3S2t1aSrulTAMfHAPXr0Ofxqh4+snhu9TvNOihW2Y7ljXHO3nPPIBzz0GOlY\\/hfT10Hxno863SNHK3kTPIxG5952uOc5+YDOTnIzx12fjdq6W2tXthY3AuZ7iMou3BKE53HI6cY7flURTVWz7Dfw3RyViIxptq6eVHEkQ8xogSWdgQF56Y59evtXVEXGp6TBMr\\/Ypl3szSBsbchVOVAJI4\\/MVyel3n9naJLpUiuZvtESocA\\/Ln5gMjH\\/667dHgjsImgtkjlXBhWRfm6HkjOMDrmtJwCMrlLxJbSW2mwzXWoyS3E8w8xmK5O4Bcr36DHU4\\/WuX0UQSeJdKjEhZrG3MUjDLBEI53N\\/FyR04HNdNqOkEzRXN27ozblM0o8wgYB+Ucn16enSqui28dzd+bbOYIp8pGrLh\\/LU\\/Jux13BSeferhSvEh1LM1pWtzpL3m1\\/K8390CuzILbOhwFGC3UE9TjmuZ1W4nZJZJy\\/zlba1jV8K4Vt5bdnnHT1\\/WtuHLeHow9tcLBG0jPKmZGJfOBjI6hyOrY3VWvYmN3CkkosYLSAiFX3q53cO2AD2JGR64zThTtdClM8\\/8ZWskc6XN9b3VvbvJjzGLGTdtBwSeTnJI5PFc3ocQgTzH8tJdwNvJI+AikklienbOOewr0L4jqWsrWZlZyZGkZJh86LtUDknnOSeOPevP7WWZpZ54miUND5K+bHnOeOOu3AHX\\/GpqL3rLQ5ZN89r2Or8L2mpa1p9u8N01xcNMZFkQtG5TJzhiNoAIzx6CvSrjxR4yXQZHXTdNOl2US+aZnYkkjg7z1YjnGCea838AxT6Va3Fi0uT9oXa3mhVZSAQMZDEDG7A9eR3HcSaxaxad5OsRSJBeTfMVl3Av5b4GASFxxwM9O2ObjC7umdE5aWPNNU8QQavqR1HUWi8uL\\/j3EIfajd22t3x0z3Oahig0wl\\/NmikEnMrS\\/eIPqc8fSoPEWjw2fgmyv0ki3LdvmMXAfKn+EjhgQRjoOtYGoam0tk0H2S2hRhkCIMO\\/fk5\\/GubEYaVSV1J6nJVoOb0Z199cx\\/2eFinNvCV2xLFGdzY9Dkj86rxSW9vIqyvcyScYd5g2DzxgdPxrM0u+DaepZTI8EeQN20L9ehNXbeGzvWWV2dTIo3GOMMEI+vr6VjDARjCzuYxwkbWbHX8HkO5cqMndggKx59Qa9x+BtyfsvkllBXjapyB+NeH6hqdml+6QuN2Am0\\/xdec8\\/h7V6r8DrlRcOqjA3HP1r1cohOnV5Z9jnq0pU1ZnvINZurLmNquq2VBqrfjchz6V9VT3OKexyc42yVagf5RUGoLtkPFJbN8uK6GjFbFrUxvspB6rXjtyTD4gIP8Aer2KXD2zA+leR+I4\\/K1\\/P+3Sl8JVPSR1WonfYRN\\/s14Z8REaPWW+TO72zXuDnfpcX0rx74iRk67EEbDkADPTOa87NP4NzswTtV+8wtRYxaGsccRDAhZSVZTubOB09AfyrnE2+WWIYsDz6CtnxBqNzLH9mMwEAJLR9Buz+Z6Dmsq1kiAKynknumT0\\/Mdq+eoRtDXqezSVolJsZ25IAJ6iumsNOupdJ0a4n06SWze4aIKoP747ieMdT1HfoKzYNEv7glvIkiDZO+RSExjI+b\\/CvXfhnrWlabow04eTC80qy\\/apCfJjIXgnOSG3dQMEgHkVnOvCLtc0U43tc7vwZFdadDpKyeHrRdKvbiGGWN59jbPKDh12nJHJPODnIPXjauzbaT4juNCtrC3Ftfwt5kd0AztLhmVR\\/GxYxuOhxxySQK5Dwb4qtNeOi6PqMRLf2jFG0cal\\/wB2zbVPAO0cL97nJOMADHX+OtK0O+utNvbE363FhYfblnR1ZTHvUhcgHDZfjI5wcgms5crNNboyZNB1lLXUdWtEjDXU8jSWKyFI87n2+gkx\\/ugccZFct8XdUvdS8K2Fzexxw3xkVz5SttVGQMeWA5ywGOvB9qp6z4vvrPStX015ryZXudsBfZ8sWSxO7kqMn7oIHP1riNf17WdbsIHv5S0StlHEeF2hVTPpzs9OuelVGPVg9zE8+IvmePfGQQ20ZIyP8nHtXSWLwC1trm0VvvlQdvJ798cY9\\/WsKDTZtshW4R97hM5xgH+IevH86uSW0mm38LPObhFf5EKrg9euRg\\/\\/AF62SsS3cl1fXpbEXEOGmkMhYKACRuPBOPrXMf2hdttubqacuZD84cqOAMYI7j+tbd8trJNKJZJ2iJA2r2YEqeB8p4z74xisgrYnS3zJMLkMzBGYBFPY8d+nXv2pvewkS2EgtjvhiSVTnf8AvCYnwOAQpyOvfv16VPrOmXE+p4mDSzPl5FjmMx2rwc45znJPHArMX7bZbjbXTKUUoTE2PMGRkZHUfWrduVUi7t74uwHzq7lWViw6Hj15wegNJ7aDuZd5IJHj8hSjRoBlPlPfrwPY02K8u1c+ZdTBjwHEnzZ6AZ9McY6Vr2enx35EkMjqyjuoGST6\\/THWqusQRC5V4YvLEZAfccb2BGSO1CtsN33L5vNQSCRJnMrFNzyBcv0yO4yMDBPaotP1jcpS5ZYwGLMApwBnsO3apEklkuvtFjaSlY4whDRAEHGOV6Hjr1zVG6B85ZHhBCHaTycLkYIB9OeKWi0JvZ2Ou0vxXFY6oY7mZJrJodpD\\/vRHkcenOeP8aV9chmnkljP2iORtwZDtYMDgkAj2rB1OwsvIgjhiV5GlG91GAwxxxgY7fnUc\\/hm8t4FmjLR5APEmDjnoPwpXS0Ktd3Owu7mCfUw8ypmOJSq56NjO4D1q1qd7uVXnCEug2qigkrtznOOOTyM++K8x1C2v4ZAXnnMnAO5yTjAx3q\\/Z6jqcbwR3dxcbIvkwz4UL154465yc8fTFLluiuazOnSZbu6+7NGZF2vIzbiTjrjFRAXui6wjQzuYJFCHa3H3uuPr296s2umXcBimcXH2eQLKs4jZlwc45HYkEA810d7b6RdxRXMztZgOfLBg5wASx9SO5PbH4VDsh3J9K1RodM1Oa6iidWKqGjGC7Aq3IHHIU80L4htL+wuxoqvZWyxjzkm+YIMjcepyM85P5VS0W7sdTgu7VHht3iUyyrGmdyoQSQMDkjHGex61Baw29nHNaWzzqt0o8iTByMng9cnt2rOUItaocZPodT4UaLTCkWjPaSJDmV7i6uBFEG\\/hKeoPTBPUds16Dos0Wq2tldLYLZMFIYohHnj+8WJ528AdfvMcjOK8u0eWTUp7GyurxnnKMPsip++V+7vn04Hbn6V6b4ALXXhy3tbi8ZXtZ5olRAqsUBJGepwARz6VFZK2hMdGM1zX9I0aC+sQIDqqSFIomUKzRvk5DE5Od2MD0\\/Pjbe\\/1SLT9RVNPga2uLjdNItyrIjZXOAMEn5l6DOT0wKqfEq+iTXIpLZbcSOm3znbLKCPvc+nr6iqjXMU9hNcCSYyts+0SIEMb+hBTAznjofrWsF7ugPR3OulW5TRruOSyj2mENuliDbcZOMH6\\/hj3ri9T0mEaekdvbJLIWTdNHLhhu4+bjAzn36V3lhewvoFm\\/mNma2kU7+Tn8fXBNcFpGo3J1pIXZwLR0zuWMLgEAsAQFXjHLdSRWcHo7jlcw\\/OSzZ0minBiAjZ92XB7cnI25x06\\/Q4qLUJoXvVS6VlvYmC\\/IoG5iuBkAYxnH161d8RQxTanORJvU3OM5AUqGGAQPXmsXxBBHFqOZWEM0rNKNp3EEt0z68iqbvqhu6jct6Jqc9hPdQJBIj3cBSID5hwew59+PetWHV4GlkW8WVE+ZZHjfCspB5AA59eOlclAXkuAzssbBA0eCDj09xyc1l3N\\/cIxiaTLGQbh69\\/w9605eZAn1PY\\/AS6ddabqMyW0Zk85iNqkZbbnOMnByR0NaWpWw06J1sM\\/Y5YTIwhIwjp97jPBOSCRnj9OF+G15NBax3Z3+RJIDKi534U9gB3Hp6e1bWu3Vz\\/wlFnJpNzJGdQhb+AKjqVY528jO0DJPJGK5+VqbNk7ow9FupmvpdKEEimaVrqJ8DacIFPIIwQVYge\\/5dr4M1v7NeXkTW1zGrzAC4Rf3QYxj5eCSPxFcs9hrEXhE+JrOazkktJWYKqsVXazAnPOcnPU5wa2vDKyanqGqRSKYLm6KySJE7I67lUAgrgkAq6nOeCPWoqL3WwW56B4ZZYU1ErG8srRmVl42hiAOAMEgADvWB4Xls9M1zzmhmBCksWiIAJODlsYC\\/Wtbw3dvo8t0tzDO32SdoFuwRunClcABRkttOeeu0nrxUttqFrPeXDx2dwIY4wW80KG2++O5+XpXPTjJaNmrkunU53W4rDWNRuLpZI5pI2UMsb5MRBOOe1SeJrO3upYIAPI+0zblkfG4sSzFQ2Sw559K82v\\/ABL5XxCkR7eaOKWZbZkztUocYz6nP4YJr0xlk1PSWsmTdLZyIQ8jKCvRkOO\\/BHp0rZwcIpkqSbaOm0m2aw8KwWVtcgxidsKQrPJ0P3vX5v0ryjx3Iby9VIp0DSXKrudyVDZChc89DXpmg6dqCWqqDEGtcvIu4YdsgnH4Ac+1eT\\/Gm\\/09o4oIj9mnhLSBPM3BW3Z9PTHHrxWVGLlNDnK0We4WV7pkSw3zJcSyW0ixSbY95AYhNucDd16Vn+MTA+oHzWSDy5dmzYe\\/8RI9\\/T0rz3wXr9\\/qnh+wuNQliVnuoZW8tsGRUcbpNnYDHXpn64rq9e1CC+1B0iu5H2lldmO0K+NwHI6DIrGcnTvzLYuK5rWM06Sbu4vL9Z1ECxYCkbFO0g5APrgfkK5u7lTUniBsUTyMsG2EluqjceufTJrp9JPlafPEWaSzIZ1kYfMnPKso6rzngfhVK51TSrPQ7aQrEt2sTRsWJUMeCcg4OM\\/wnr+ta06kXZoip7u+hmacws9KMc9vNBmQu+T8swGCpBzyM9cenTmpvCSW2pOxvLmNI0WRlQ5Q7Rk4I78kDn0FQPq2nanAsKW8u5wqL5bbVGO2AOlUXgtoCRbyo7xbvMR2A3Ek8E9+p9zWM4wjJ33ZSq6LsGpxtFbSuIkfzI8RDCnGRuyT06Y4xnpXG3emLFeWyvK7rK6gSOpXAJBOR2Bz+Rrqm1FV0+e2lVm3lVQHoDgY78jrzxxVRYbZ5Zry7IGzrgB\\/Tdx6\\/jwBW1Gbi9TOraa5Uc34utjY3yLaMkCSMAXRcEH1A\\/r71Y8LaxNYeZD5kjxuCR8+cMOenTHHet7+zLK8v7q6a3mnhSENH5Um4Ac8nBz26Zx3rF1CwgiKzQwLKs8jRrEGbcCMc47fjmuiNVSfKcjw84z51oauja6dQBmmEUUchMbxt1xk5IJ7fSqWsw2d0sUEdwpt2j+RFfockfz4qHR7SSKMFwAQzMq8YHt37DrVq3sLcNdRnHkN85yCDv4OB\\/n8ablCMtDoi76HJR6Peu0n2e4VDsyyb+Rxxitzw5rGv2t4Eju0mnuQRMjp1Kg7SuMEEgnnuamaKI31uZFkXc+FYqBgBST09hnpxTtKdY9Ztr2KI3BtXzIgHLKeBgE1vGaktSXG2x6J8PfFkGtyraahut7l\\/ny7Y2gcfJnjPXpgniujt9Ikupp4tNmZIxdefJOZ8O7AkgDA7HHp174rwmHVVea4huLIskDMI4Nu1njLZznnBAz61Y8PeKfEPg9p7exieW23oXhbDggkEhXHKnrwM9abh2J5j6L8TeIdT0+2tzKI5z5aggbkZ2ZSAFIBGBycg54NYA8y+13SnsrSG5jit1+0bfncjZgk56NyWAJOBggd68qt\\/iXdvq9rNbQT2tn5zSPB57PhAMqSBgZyx42456Z5re8C+I4tatJbHTNdvtIlSRxcSRlmXawOwowGQTt9Og7VjUhK2pcJJHo8c9zFrF7HCf3BtBGMAFtx5xwewKepx2rUlSxfw+lxLdT2TWxcsRLhnK5B+VsbRluue\\/bivMLDxF4aspINOg1jUYWswBFfxo0iyTOWDu+enXPI6Y9KrfEbUPF0OmTWs17FewbB5VzZxsCpVl3BgvABOSTwcgA+hVrrlC+tw8Q2aXOrWcNgJJVVZI2RosF2HDEg9MhhjPuR7XLPSZ7d9UkugptnZUSUsGOFG1RweD8p4+lW\\/DOnTRS\\/abu+l1GeeEGTLnbGhGWcbjjcefrk9+a6LXdHjk8OWWnwmRpzHlyCQQFBw5KnAySMZ7Yqo2grId+Z3Y3w9pVjHBoVqiASOpnk2qwblGK5HqD6e1VfE39rX9y8WlJIiSMVnYKoUjIGclT\\/AI81rafo93YabHMBJI0UyhygDhFIVSWY46c\\/KAfWpTbrF4bs79w6SGZlJ3svy4YbiP8AgP61m3eRa2PPNK069tbxVRN4ghmYsQSA3AwOPYfXNdt4asRJ4Hn1OKyjtb3zw4dx8uEGN3PCjrx7561z19qtvDLdl28olCmDJkoSwwOBgcD1NdV4+kj0vwDFa6bEdlyuXaMZ8xNvzE9jyfccVtJapIlHmUup6nD4e0HSMTNvuWYSJgPHlwW+vr9DXUz6\\/ERewWyRrqiOY2lWElWyqg4644B7n61z8f2mXSbG5klYTIXkaN3yUDRDC4HOCMDOOMH3qpFO8uom5uHXYybSFJ+bc2eegzyTnpgVTSWrM4xvsai6teSatd\\/aIHiSHy184nbuyz7j0zngjp\\/PNYurQQX6xpEoEQjJSNhhkyc8k84OM56VvWyTrG9v9oEsasV2ELuA3dBkYJGenvWOlnKb6dpZ1S1MgZGjGCFUYIbHTmqkropaGVqM9pp8Pm3GS020MhjznB4bpz9a53VbmO6RtzGNcgBMcEA5yffn8q09YkhhRZ1IkaVQI43BAiJyMnj0GaxpYJkhukuAIyqbk3ADJJGQPXr1rGEFdS6lSf2SSKYXWnC3glbBm3Mm44xtxu9\\/8McVsacLe3LzXF35ReE7reMlUbLlVxggHBOT6ZrH8IRW\\/wDaQtnU+bIvyqEzyWHPTrt4x71p63p82nPPeWu0PExVAOVKFup9B9K1k7uxEVpch0aKbUGWC1kWzVI94jz8rxDAIznjIA4PXBqxPDPDCsdnD5dtLtiDHBITfyxJ+6T0HrzUfgq0lvUTDsz5Mk4JKIRuPy59wOnU9K7IS6ZFI0NypJkAJeRBhvXB7KOhJI6Vw1ans52tc3UeaNyOyGn3mhRyW0kUHlA+fPgNuXPHzHnoM4q3ZapaXZE0qCe1Qb0If5iAODyOOgrLvZUvLWO1FxBaRo5WCELuJUDG5xyeTnGeTjqRUH2C8tHmSeC4trOEsSbZ9nnE\\/ljqe\\/8A9fjnCM73Zst9jYv2t5dPWW0hwxbcZZSWJbsMY6fSs9rWBrjzUSdpdm1UwcAevHToD1FS29yjm1MUyRFowIoXcOeB97pk9Bz\\/AD73JNSt7Yi1ka2tmJIUZYMCc46gcfyrFc0NEEqfMye105p2iedZYIxjA3Fhk4Hpj246VneJLjUNHbZZvH5EbHem4nzD\\/nFZd74hvdGjNqjBrzyyY5Y23MPmwMkDnOewHSmS+KJTfRDXIE1FScMqDyihOOME5GM8ZFdlKlLl1QnaL0ZjXeoTap\\/pkSmzCMVJz8oHQn8cnjpWbJYu8JDzGYl+FQY4GCSRj3rU18LNKlksaWrZ+ePKsB0wBjr+nWoYbeQ6SjaNLFMhPzSyqVZiMeh\\/DBrtg+SKtp\\/XcxkuZnofjHxDNpliL6eFDcD5ljZtjIp5yV\\/rXPav4u1eeOO9uphbWT4RcH97IOjcA\\/KMEdx0rL0Pw\\/qvjnW7m+dk8kYDNhuVBx8pZcHoK19R8HazHiHWJ2jiiYxRiFd\\/mE8qeowBxz16ilSoYWiuSbXOjCdSrJ8y2JL3xBbQ+G5ba2vHSGbzFtoYZQyhc53MOST6ZIPWseDX\\/Cs1glpqp1O6lhRpFxPtUucHYAAcZPT6flb0DTLC8vbSGW2QJbK7zHG0Nu4RSF7ZXJ9c+9O8a+BtSl0iLVoFti9szLNDaIdoXJIZRgdiPbPelalGXJJtNvfz\\/r8yuaVrpXRNq+reFFsU0rRNBRvP4ZCzNKSG7HsTtFV9S8cahequjaTZRWcKjaLZY\\/uL3BBGBjkZzWF4a1nTtFSK+SGR7y1bKyo4XezKc7u5Ax+Z+tW9FvLca3qeoabdWkdzNbmZzN0TccuF2jB6+ntjvVxw0I3503bu+onVk\\/h0v2OaRmstY\\/0myRJLeQSeVOpwRnoMdj2zx710Nt4rlivZJNMi8qW92iWLewQYHGP6DI7Vd0vTJtd0sWy2Fu08l0ypdhgY4xgbVBLZHTjH0I5rO1PwhPbRz3FjcpdT2uPNWNz0HXIIG3H1NdPtKTlaW+xk4ytpsc9PeyzXObxCx3MpYsfmPoOaiE00SK0c+I94YoOV\\/EHvV\\/S44oLhQLc\\/cYTed8u3AO7pg9Ow9frVC4so5L0f2cJ7hGOIg0fzvzj7oz\\/Wut2a1MVe+h2ngvxlPBPFp4sbZ7eRDDKsiHZIexPbOM\\/yrub\\/AEbRNSktIxpv2G1t3DmV4mUMM8AN6EnGB1BPpmuD8AXEPh+e6uNWhghvozvtxcI4cYznGBwe3Su9v9dTR\\/DsN74hul1GTUphJCkQ+SKItnOByTgYPPFeDi4OFVeyVr9uv6aI9GjPmh75vQXFtpll\\/ZQuroJbqsk08MACCQndjI4zzjnHQVhTeGfDun29xq9\\/PJeMyYZI0w5DHO45I4zwMdq6LwLdafrmm6il1a3DQXERBtgpATK\\/eUAZAyM59MeprkdTv7bRruRPKle3dMKksZ3BOig5zt4yOea54YapHWLd3v5lOvFuzWxseCtQ03TbGC2060sLi\\/vJGfemGWGPcQu4kYAGecn2HaqviPxlrPhu9lttGWfU8hvtFyFJEbnrs7BRxz1rBe7vvDumm803TT9kuk8uRyFPmAH7xcfd5OP4c4yenPM6dc6re311HYhtrk7oFcnIIJxwT\\/OtoYONSUqktV5\\/1pbt95Mq7ilFaFvUQ+sgahfOscyurPMwL7ixIICgY4znj8+9WdA8Mpd6lGY5VljkILsF8oKD3z+P51t6Lpq3IWTUYwbi0ZViic4iGMHGMdefqa2NU1vR7OaOK0tEk3ErKkH3Zj3A39Dk9OK2liJR\\/dU1qZez055M5LxtaroC2y2dlJaWud8uHJknAJ+cM3HPXtWNoWsW0mpLJb2i2zquTJuMjvyD0LY3cH0rqLjWbw6r9kurSJ7eE757O8ITcp5UEYxjjHynpVHQ5YtYvJk06ytrW5MzMG8gBQAei8e4\\/DrXTSjNQ5Zr53M5Ti5XR2bz2lxpqw\\/YTIqxlo1mkImiY43EhsgNx0Hv0FYGtf2TJarIFjluGbYkbxKVZeCTuGB6c96z9V1LW7K8ntbme5KxZ3BIQSueOD9MVZbVLcpEwLb5XG+NlIUHAOSARuOM8kde1RRwsVqmE6snuZFvfWi30yT3UAHzF\\/MBVFwvIUgkfgMfjVfR1uZLqS8itmubbd86MBG6KMldwJ4XgHv0p1nqFhL4yugVNxAzghlTyxuHBxz0OO5rf8Vzbb7SJYiLS4WTKeWoO1T0zjIPQdevp1ru5Pd0exz83varcXVY7mBv9EnkiuZo5JGkUgRhM4GABnBOSCePSorGwi0\\/SZrq5vA95KieWrKzOScg4D9yDnoTxWIia9q95Pqmv395NI03lMjHYNuOgUcAc\\/ma7LTZbiTSnhi1GCKNIv3u9RmNR6YHU4rJwd0jRNJHn8ejxJfz3RVgIbllBCjJIOCSRxnOcVuWEaNLG3mx20apj5Rn0OCOOe1GmmEwH7FeyKJJmkQbMgDdxnjuPp16Grl3Lc2U8dxHsXqGkjXame3GBzz1H9K3cXEzTUma9oLJD5GyTzHTCsS2McEADJ29+p9DxWNqELxx7TFmSRiA6Fg3Xlsjoe2T1\\/DjZ8KPa3OoQfaro3F1MdyjH3c\\/z4Peq3i\\/XrvzI4JZ7PL\\/AHjHiMxADABTBH5+nrisIN8zRo0rXJYrFbeYfu5L5TtLSyqSoYgjnOVz+GetY9jPpoa7sWguppbi7UGGDcqhQwOT\\/CQO3WtLUvEOmzWCQRJFjyxulLYcdhtGRtGcfXmsGzv4lt3T91E7RkRjBcAdjk57jqM9e1LkbWg1LU1pYrCLW7qzmhnmgjtlkaKWRtpbrgjoeRn8RWul5Y2+gaddzwgStmJY4nVCSpOWx0IAA9\\/zrzrTzLd6uILi+lAlX96WfO8DnA\\/Xjpiug1BPCtvaRI0ETgORJcrIUYc8jGefpj8qajZrXYG9AbUtEvr+XUJTdSPAUSKNmGVI6gDnpk9PSqpsVnNxcWrmJdoALMSQCM9yeck1V0fVrA3r+TAkaAgll+Ubefc54FSLqUksKtC0hRxyudhwCc4HpV2uydiaS68rayyNLIo+Unna3PT3rT8Oag1tNL5jNLLMmZJJGJYkcD+frXMyX0Qh5Ty0IxGmP4vXJ+vpVa21JpJ0jtpJ1PCqEYjA9sGn7PoHMeieJtSkXw+t0XeKRd0SrHgHcwAJyM4PP6fWmWl1DbwafFbJHkxqMMm5tx+XOT1xzXLazcN9hjeeWRJTJ828ZBAGAe9VodTuWmi23IjG5VUhQWXnJ6Z9\\/wAquMOVEt3PUhdJp+lSWcd6om3ZkJYFl54wp4z744rK1iJo9RaRoCim2VVklc4YA7sEYz2yePTpxVCXRrx9PmkOZbgPuEzMdwOMk5xjOPcfpVF7aOG3c3rJcXdxHmOKT5yWIGQXyfxA\\/HoK0VJt6mXtEtil4\\/vf7Ss5Lye6SSQSMI06KRjAwc9hjjn8K83ljaK0W8Pzbl2Ft5A646DnHeut8XSeZCunwXRVthVLeJNie7YGM+nP69sDWoJpNPsYre1UKQFbfhmHpz19TxXPX5YSjFEuSurmTZX7x3AklLiFHORv6MenJ57Cuts9SvL61bUTOLWzWYlBkKquylSMAYwctzxjPtXOarZCHayCMK42P2ZCOcn8M03Tbye0h+zMqyxySHbH\\/ECRgH9c042kuZGsZqUbo6XUL+NtPWHyobZUeN1jU5idgAAQAOeAOpzksSTXPrqRub+M30MKxRsfMhiiWPJHrj+tLrN3Fb2psrd0lLEMTs9s9TzwePpWdaPJLL5rbRklnY55Oc\\/hzU1IxnqxTpx3NqGVtQIkWeBZpN4A3FRHGOcZxzVyOA22mSSOY3WMHPHzZZR6Z6D1rH0CITTRsYmMUeWkAbH9a0Lu8F0bsW9xKxcctMoXtgYAzztyKqMoxjyLoCcUrLoZdo88aCULubOSSM9a9a+Cd2w1Ty2IUE5AHSvLxaRpbrFLehio4EYJGfX6ivQPhX5FtrUSxSsST\\/EMVvgq0XXRx4ipGUbH05bvuhU+1NuuYzUOnuGtkI9KmnOVNfSx3PKkc5qq\\/NmqELYOK1NUQlSayFOGrptoYGjGcxYry3xvGY9YDf7VemW7fKea89+IMe29V\\/WlJe6xx0kmaNk+\\/Sl78V5L8TwF1VGJwAOucV6poj79Mx7V5l8WLeFr+FnlZMg8gZx9a8\\/Mf93bOrCu1ZHn8xt0jdnZmlJBQe3qTVEMPM3BeTz1rfm0RbmASw3KIwXky\\/KG98\\/4UmmeHZ5CZ7rcYUGAYhuBPb\\/OK+Y+tUlHV7HtRrQtuM8NG51GdbV5FcRlBGJF3BMsFyAfqKtXen3tlNc6Yl8sDWk8gkbO0yBc8479OK2YNP0\\/TIPMMYglKIUl8zjcGB5HfoK0TbQXbSSi6t5pZY2Jd2woDtuYjg5PHGSMe9cf1qk3dLT0HGpCXQzfC019Fot5qttqNwty9z5IdGIK7SHU5656kfjXWJ4pu7uykgAuLG7isUtEktvMImVW3biozjjGeccA9a4aaH+yLtpIQbiCRvniL7cMBwePY5p4XWNQuJHtby3t12sBGjbgo5+XnoOAOOOldq5bXRstdCzd30isVePmcooDNjbgEYJIzn\\/Cp7r7PDp62sO1VCxhh5hwcj5jj6\\/lWalrrv2cEvZlEYrkEgjqOcH3P51BHHcPaCF7WWW4Rt0Txxs5xzgA+mMflVKcW9BhpU1vbfN9mSKMg5cEE5Gcdc46fj+daqNcXNyZ53Lop+VVXljjrzwBmsOa3u7SzJvIBEJE+VtxJJA59j1\\/Wt3S7v7RLOiyLEVVAu\\/AAwO\\/HrVRd9hNGbMkTX4yk0Mr4jjIAb5ieW3N0xx09evFRXdluvfs0VtJKyAB3jAVVGONzHj3roZZ7ee6iSR4kO1S0gOFDEEcZ6dDVm8lU2qR28u5QobZu756j3oavK4LY5n+zIE0\\/wC02pklZ1yCzAiMfxDg8\\/X2rMWSUo1rDFuikYMUI6kHOMdT0FdZb3EBjuPPEEQknYRqDjqeePx\\/Wo1MNtDJ9nR3dpt0jIcN5eOB+Yz+VKTtsNeZz0QuLOci0dgJxyzHGwk4wc8+lWXtofsKJPeyrFBliGG05J6jIzzWmqJq2op5bZW3HRlw4PuO\\/JzUvijToY4nIZRIlqWUsPmbIzn8qlX6jOfsi6tLaQDzXIONhJ7YUZ+v8q0LKy1aS8kF7Zyoqxq77osgqi46etUt0ME0UttCYysKg7NwKnHLZGP8npWzHcNY2a3zTSO92hWVZX3Fl44y2eOP\\/r1TEjLvUmuZktJIwXVmKOCACBxjA4J6ZOTwK6rSbiLWbcrb6e4kt1XzeCxYHhWPUDpzx\\/FWBcSLaT+fDEEKFXWTaS0ZPoM88\\/zHFdvol\\/LGUvzbxK17A0LqwKtL0AIU4OeAfTp1rGsmldFQ3OM8TxfZdVZ4402MDHtK4D8YI4xUOoyWt2kge0e2uJLRHKFjhwqbcj9Dz6da12uNRlup4Z7CKVvMCoGUN5fJGRjin3vhMl9+GLm3DRbxkDgkge2M\\/kKIvuVJD\\/AetWYFtZ6law30XlFQImRXRFXkHd3xnjH516FpsvhyeK6uL603WijbC3lbF+6cEhRjrg8j25wM+P33hTXNNWeeRs+SCd6H5ueCOfxH4VteB49RvPDlzHNfLaQKuFkuW2xHtjOevB6DtWkktzOxqrex2KxyWtks7Yz5fLJ5bHnGNpH8XHI6ioNU0nXJI4Bb2iLbPJhWU7zEhJxuxkgAnGT0GKt6MTp0dtK97ZI1w2webMSYx8wKZGSOeuenTNJrOqXHmeSDLBKDsMyXG9ZeSd2Cfu4PYcYqHoWtWaXga5099bheZY7qOCZnmdohKzPzvBIxvX0J6ADqOK1L\\/wAS22k3l\\/pNjessE8zhZ44PLVlc7gqrnI5zgemPUioPhf4csrxrjUkM1pAzlZFQsyo235svtC9D0B71N8XtNtDp8djY+bJJajMZ43BtxYnge3PHOaykr3XRlLc5HUGn1Nttz51zKEPltcoOhHO3BzxnPP5Vct\\/s2l6D9jkvree5Ej7bcIGkVTkYJ6Ahgfz4rB1rUJxAmy38i52qpdNwI4ALD6nOR7mrOn2cJuHF0jpGON0fUtjgZ69SBye9KM1BA0mad7rsi6KNKtVG5o12KwGArHk5654zx71BcySWeoNKlykjmMctH8uQeAAfbGTyf51k2aXdvqMc6CSRowNrsd+xhnAGQcDaDge1W5QLmOONcCQt95zjCgZBJ7L8vPbpWNuV2Wz3HzORn38ckcgulZ1SblFUYHyjI78k+\\/uKoS38mozqzuivnaGCkED5Sc9e4HSr007G6jExjKxrwOMM3Q4A45659hWdetFamVGt5d8ak7xggnORgemK3jdKz3JvqVLe4ktRdzFZhOYsgjGB82Oc9RwaxNQumuLkMdxc\\/ezznOMnjv2rUe1uZoHaXfFvbahbuucnPpVLVoBHcpOtviIYzsPGcde\\/et1JXsZua2PQ9Om+y+FPJtpCubVH3sc4Y55wfbI496p6JrOp3ep6NrU0ZiigjjtUdjtToRwCcHjH149ayF1SOFruOUlSLMKCvGG+c4A7ckdqig1hbnwhawPbmCa0lj8qZX4dQSOQeKjl0N3I7JtYdrfWtFcB4InlWN4QNy7xlQVx90sDz7jHetOby5fF+ksoeLcoxPgqysHAOB1xk8dTjNeZaz4gunvZ7+CBIVuLdYXZQVPBBGCPoPbFelarJdm80rU7HZDcRQm5TevEi7Dxk88kdzjkVnKNreYXuej6to1tqdtZ3erfaBcgs6TxSBlYFlKnOR6nBBJ5rC+HOtxx+Mr\\/AE67upXUW5Iabc7OqtgE5+vYdTXQafqI1TwSunSxrNBLHbbHll\\/eKSF3A5PYg9PU85ArgfEKHwzq8GsWKxzM7CG5k3sAfmC8EZPpwc5B\\/GuWCcW1I0lZ6o5y40qbxJ40vL6aS4tLF777OjQr8wKE4fngkYX35r1XQLhlthZ3qtErBWtrhcP5iYUhvTI9Pb61g6IYtl5bXbQ2Us06tFI0n\\/PUEfKMYPzD8S3bmuulsY7KwkS3itpXU7IjEPmT2CjoRtHA45NOpU5lYqC6nH+IPFlw8w0KFHjwWE8inmXPJAPPrXCa\\/ozxaNq+p3haSIp5cZxknnPB7DPOa2dMeO28Uail5x9nAnlZ1\\/1YC8gE+gA\\/ya3hfaXrUEk0iiSzvCoELgbkYnAHB6mpUeSd15f5kuKlqzG+FVhAvw\\/1W6tMvc78o6gjaQxIHI4Pyggip7uS\\/wBRjkj0qZYWd9tw84x5RCgdOobHUnjAXGc1Y+HM6adrmueFJJmFvPsuLcxqNnzYBUg8dcY4xkmtyOytl8V6jE4mme0mG790AmxuFBZQeOAeSORmis7OTte+pUNkij4pa50bwYlpJEUSDLCWXGWGCc\\/1rhrO11fWNBE1+xt\\/3bvGvl\\/MRyMk+n14rpvjLqMM\\/h2102ONBubYAuPUHoOnWrAn0y205E09CsfkKXk8sckJ6ZPftjtWNO3s+a13cKkFOdn0OP021urW4iEsrnzUbcE4VSDnnsc89Pb0q5FffazcxrGqpEVdcjOGNVRqUExu5FupoYjJ5QCpjdgdz7g\\/lWeb8R3MaQPGFwiOp4PAOefU8DNOUHN3tqcbqRvyIerXF8zRXoknltpAGyvBGeOnPQ1pw3YghVFtzugUN\\/rMkkn369fy\\/HNWaWXzLaSJijsQ7oXxnB5Jx\\/nisu7ngtJ7lp5HAYlCQxJHTHf0x3pxkp2svkONZI6uHV4YZTJZPKls7ETdCWGMkN6gbm6egrHsnnnkm8xt0m8yRMGCqF45Hcnj9KoQRoLRDAZZYHGVG4Hk+tZerRXziOCPzmIwduTg4HXA9qulCKk7dRfW3KfKzfjdp3URNIbeZjJv3DHQk\\/Tn+VW9Pjikd7eWV4pHKukif3e4Hb0Oa5u31qbTbNI2gjnjiO3I5yehB5qT+2Els7e7KxxyyM0cY6hQOmcexxVToVE9C4vld0dFqdsYJEVZRNk43uRjac9yeSar\\/Z4LS1eUvMhcqFRSVcDscjk4z0FUob9pII2SMjauWw33nGCOPoR+VSWct221rtlWLflcDJU8\\/Mcf4VnGUoaSZKrqMrMk1jSpSrtOpLxyKrPyp4xz68mqdv4UtW2XTESW8pLYySfXOPw61otLBLdSbYpJIeN2ep4Az\\/nFaFs8ltmM+V9nURuWfPKg4IHpxj8veto1nax0WjLUx7PTJLi2W2sDaQzI7B1bKrKhHDA4PI5HOOtVtE0e7SfWjHZJuEKxRFXKFPm+8CB\\/dB5PvXfXttY2tja3Kqo3vxsYB2yA2Mfw9Dz0yKZ4f0UR3V8WSW3WUMWlabcQACFUZOOu7jGOvaq9tZO4vZ9jyW5vr3SdUF1BbJbFTugDZZVII5U8Y6fqa9S+DNpZ+ItZvbo22JJo2LwoTmNiSRk8HHyg987vrXF+L4jPqs0AihiSMcMMkFQOvTjgGuk\\/Z8nh0fxzF5rtGblvLMnIXGM7ST3ORW\\/MpRv1OWM3zuJ6b4r0Jo7iHSItJg+wIzOJYQUnVnVjkEMvAJOQc5HFdN4htLGLweNTvbowQwaeoYDfznKqML1yQPpXV+IYrd2inD7xcI5jwMkYjPP0rzbxPqVmfhpZ2P2qOQqI\\/NghwXXaWIUqP4clR+tY0le9zrl0Zq6BqD3HhI6fNBDDH9nhwhkIOWONpOOTkDndzzT9RuoIYxYXVz+681IngZTiMPwqq5PzcsMgj9Kp\\/wDCQWeg6QVlsxfF544pYhtHllY9y8HAx079xXbWDaf4k0GE3kcE8N8oZF+X5DtGB9R0+opyhrcIyPA9Rjkiu7hJNrTreFQAvyvh8DtjqT610PjHVVuPD\\/lXjCH7KsUPlb9oQBTkbe2dy\\/lVKOx01bm+juvMuZbe5ijtk81QiFn3OCvPIBAzj8Kt6lbwaxZ6lNp0eY4po1XGJF8wlCQDgYIz0zxg1d9hoqapDBdPJbiUuFj2Nj7rBBxgDPRSMd+tcoIpJtDOJAokfYRnDspIx29j+Yrd07VZtH1tri4jMoCOhUqdu5hg9vb9KhtIEmt4oGgaJmbcCeA\\/PYn8at6CRFocc8WjSta3GxhHtzMfmbLHnnOen6d+1a1gn1QvM1ysMtuBHBEkj\\/vGPc7s4z3x+GKjtrZotCs\\/tgkEE77iSNvyx5B4B9yT65p9t9kgdWVFlhMi5YFVfOAcg8AAgjOSB71W5JmazZmG9fa5KecDv8zdyOMY9ee9c7qtq13aTCSBXZcvvA5GDj5uOOnXNdNewGXULWCZXtoVBuWiJwMdQMjPtVGW5SbwTd+T528yv+6Vwfk3AAn178n\\/ABpxSuTLQxvBssUfiWGWB0eONdzMATt4wBk9iSK29auYLjT08uNi7v5y+mDwBwOuSKz\\/AAxa2lwWgGEjjgUMQBucn1PVT79K6mLR3k1BpDEyG0RUuI5ZTsj2gEY6EgjHTOTjr1rnrVFTd2aUocysjM05L6G1itbdIWkaRi5RvuLwSD0wecenPNR3+vOmpwvpcF1GAh2TMxwFBweOO24c\\/wCFWNUh1acXLWkQmtpyzzAtuB5AOBxjHp2IrNvId1sluJ3jaEiO2UBSJEBI5zjoMHuPpxWUqacryNedpaFSTVYdSY6xd2SvcKNvmwMR84PClTnB5696muby\\/u9RFzbi7CQYMTGMKRg9DgHjPrT7G6Se+lW4trO0cx+WXiUKj4yQcDjPXr6VLElvbWAuorkvF5aiWMOcxse7HGACQec9x61XJFdBKTZmLqVzJevcGZUlZtxGzaenKhj7c\\/X1rdv7aLW7GO5jgvPOCfx52k9OASRjvn+lY+oatHqOkxpLpkcE0XytcxxMzyDHBbnGTxzx1ziqv9qXdvFiC7fyIExEGfGeepVuRzml7K9mlZoPad9UX7mzmgnWORZZ7iNA3mGRFVFA\\/iGcdMjoKh0yyu7pmnu4rm50qSRPtTrFs2nOBtbr8ufpWdDK9xci6ZAs8m4M2DJyQRnbkDj1FdQjeILNA72X2hHjXau8jYg7nkfMeevBq3eEbN6\\/1sTfmdzO8m0t9WjFmLgWqTbJpZQAJWDDAGG5zgdvTNdRplnMfPmvopLaAKCBHIIUcZ4IH3iPXB9q5vU1DSpLdyeR5siqkLgeYhyMHA6fzrXikuTbR\\/2xdIZj8kAlbLJ3+XbyMnB9sVhUu4o2gveaNn4T6zBJb3el2ACT+cDJJgkMADkqOMA\\/Xqa6HxZaapPDaanHMq+dP5RLZAVM\\/Kx98D09OnNbFvpulaVosVxbWK2wkJVmhl\\/1mDnqOc+3v9a5u4vLr7c0ybnjHHLYBUZA49s9a82df2mIdWC+8ibVOmoP8Cp4l8MX9roa6jpLTXt2G2ERjzN6hduCnIJxg\\/rU3wv8PeKdDaT+2ra3liu0373cl14xsI6Dj2IrpfB11qagJJZlrVX+9yCh7dep\\/Ct\\/U7q10q3e9uNSM6xoC1sSGBIOQMdTzx1qZ42q6bouzv8AeXSpwk1URyl14L8Mf2jd39lbWVpqyEEDy8ohz8x2dO+M8dqoD4f+F7GwlS6tmW4m\\/eLcRsFIZsjaFHAUdh7HrWjb32gXtw10LlYgIw6sxKEjgbSfYEde1Xg+h3MX2u1mX7Tny3VnDYAyMDceB071Htq0dHJhyxd9Ec\\/a6E1rpEdvp1ybYrlopQV27gCNz8d+c45p\\/hzRriO3KzC58RSsWknjWQRwRKeBwxHPvjP5VYup9KUpBDKFmTKfKSGc+5zjAP8AnvXS+Eitjpqosvly5YearfK5H8Jx1J\\/z1oniZqD8\\/wCt9xUuWUvQ8yk+FOtalq0v2W4hsdJuHxhzudB12Y7kZx15xmtseEdI8KRyTaZetdXkVuViX+7Mc\\/P1wM9Bxxius8aRaxKpvrW3u4DE4cIjH95wOQP4WOeM+lecX9xf6VNJdS\\/aQ8ju1xckHGTk7OR2GPxJrpp4jE4pW5vl39S5UqNHdHFa1PceIL4rqdqmnXELkSKhKFi3JLDOB\\/8AXqKWynF2I4Z5LmNV2x5zIOcZK\\/5FN1S9TXNbuJ5naORsEo6oC2AACWb+HvjmoJILrf8AYjL9oKpuVYssoznAOD1r6WjT9xXXQ8mpP3nqej6BrX9khbe3j3XNtaIZXMp2zKe2OxGPb8a5fxHrWpamJC4gaNm+Vllxjtt+n+FbPgvd9hnNxawqs8YgWN1HmlcAEhjkDA9PTFRa14TnxMUuHubVARabSC3GNv3emckdB2\\/Hig4U6jjPRlOV1dMh0XxJqFhp89oXjktXjMG1pBv54JAPHHPvz71oWEavZJHa2VrHPbuJLa52AyKOuBg9DWTpvhOcxrLqjlIBkCLbhs9sn\\/8AXVqaXXbDSZYbO1SWOMMiuCNyg8ZOO4Bz+VdnsKcb3jvqZ+2lK1pbFzT7gg3V9q+pCO4lz\\/rDvIwOMDPXjtVbTCJnS5troXiMxlkzGQoGSShzg7hjjrXNC0urfzYC8XzSE+cZN5O7IOB+PSuu8MPC0F3b6hex6bEIBIhKsXZgME9xn5gRnmsnBJ3SsVd21d7l\\/XTb3d7a3redayeVhGVtpdSDgZ6k9PzrM0HyrO8tdRt4b62gmwLgAlc5JyQ33SOMd+lSi8t0azF011cW8YM0jYByR0OOeeenAo1TUIbO2\\/dWbzyXCbIVVyQynlSwHdfxzx6Vr8S0Ely7l3XHNl4iW2vPMnN2xZstvSNT6EDHYniuW8YQ+RfiW1neMhCVkXpjGDweKZczSTfYpo7dVYq2Ek3qoODzkYyOT\\/8Aqquuk3Vw8T3eq3E0SkKFZCcA89c\\/hz3pQp63SG5WVmzH8PXbpq6fu5JHLgligwT159Ofp1rpmS4vppb8KHtxKC0yycrjnBH8I47frwKr32gxWKoYXYJKyF0Eu2TLEkEjjjHr\\/jVtoI5tSsrTVrsWNiqb9jzZVzwFJCEjdyMnjp2ppPmsDaaub+iSRtqWpaYEWeI4dAH3sqqFAzliRkc9aytS1WO0tLyK2EguZI2j\\/fYXqQAfc8njHY1f8N2lrE99fqzrIxyZXk2DbtDYAIPb\\/PIqncQXl0fMjQt++Vm3SDczHnOOegH48njpVqPKRzXH3aPZ6faQQahEGWMKYkOHYgDBJHb\\/AA\\/Cl0W723ccniC6uNicheB1IA+8BnPHHXgVo3CWMth\\/aFs2y6gG5ZPs3lbe5Abnceo54qHWY47myjvNUv575z+6jQxFywIyDhRjjGeB\\/SqlC63JjKzLWm3Sya9DrFvaeVbRzFVZ+wA4BJI5rFhsrR724vTD5hSUuzzgbV5PG0Zyc+\\/b3qxZWF\\/q8FmIrSe3gVhBFHOVC\\/MxBbaD3JA5HbkVPJo17Dff2e95I0TStGd0gLb1OMk8cAc4HeuWOktzd7HPaxBb3N6kphaBQm4qJwDkk4x7jp37961vD+jWcdlJc3N5IY32sdnllW5xgtjI5qvcW1tp17PNcMbi1AYgSyN8+OMYI45JFYaTSjTQY0Yx7vnijGACDjPp+dbaIjVo0pdINz4qaNLyIARmXKuQSAFxjPU4+v41Wn8IXbw\\/bpFJL4bhQWweQGOcDgHgfjVlnmj1aLUVj8oKB0YEr+Y6jj\\/69aWqapBfT2b3UkroIx5jBif4QRwBjgDtg89aJK+w02jno9Ln23bKWa38tC0nTaFHXB68nt61Z0bStQvNO8xZ7aC1tY2eQTH5ny2OOmSBnr68c12Omzi6T7OjC3iIaJC6bWOemcjjtXPaxHHFphtHkmLLIRK20AIQe3fr\\/Wso817Mp2tc5LX5Emtg65RN5RVAGOg9PwrR8EwSGS3uPLjwrlskcnGOP51c8JaJo+vTNb6nqU9lCoLIQoO9vQ8fLwPfNafiDR00DS\\/t+k3Liz3GLEsm\\/JI4woHfnmuuMLq5jKaXumb4tvhqM13MLfCW5UBV+UZLew9q1tB09YrSXUYYrrfCg2+YgA6jPfpWBbXsEPhKSO6klLzXitlI0xkEZJ53HjoMYrd1PxYkVi8bBink4ZiNpZ+MgA\\/X61rGy1ZnJPZG7e3ebeaKB44NoVtpPzITkY4yMYJry\\/xXq81jeRC3uHibqyoxChhycYwOeOxqHU\\/Ed9IF8q5mjfeWZCTs7YUAdSTyfXj0rltVm86dnaQyMxLFivUk+9Zym2i400ncuWd+02oSzyzEE5JZgPmP5+3auk0+WWRwzFQSqMowTnJ7AdK4SHzBMnl8SbgVPvW7DPqdvAb22Yyqg8kPjIQ9cDPOc47dq4K9Pm16k1aSkbl\\/HcxuxeEMnLMFXG49ev8AjWDqzwtDHc20RjZXyTu46np\\/ntUMWqaksn7yQuwYj94M43deKiGHsRGhIYfKwLcMM56e1KnTlHcVOlybkUlw8ituLNtwAWOeK0tMjlV5JIxvd+MMMA5HB\\/PNZZX5mY4Ct15rWtFuJLZYwdwAO054HvmtpLQ1lqhLAvEku5sMc9D3psaSyS7mPB4wDUkkEYjTyz82cHNPiLo+4Lwp60ktWzNjpsR3yhDjkZ5\\/Suu8BTeXr8Zz\\/wAtOM\\/qa4u5Qh9zMFz83Pc+1bngedo9WiIY\\/eFdGGjapFmNWF43PrbQ5d9kh9hV6Q\\/LWH4Wl36dEf8AZFbTH5K+nSPHkzM1AZVhXPzfK5x27V0d6Mg1zt4MSGumOqOdvUlt3ycVxvxFTOx66y3bDda53x9HutQ3tTa0BPVGb4YkzZFfavP\\/AIt7hPGA21SvzenWu38KP+7K1xXxgUHySw45Brhx0b0GdeFdqyOP1mV9PSzaKRZ1kg4LnO0\\/j6Vkf2jcxrGwnkLg8g\\/d46cUaixNrAXwx2bV9gCarXUPlxwuG3CRN3TGOSMfpXytOCUbPU9+EdNTU0y\\/mvLxo50SUSRsvz5Izgnj0JxVGyvtQE6RxSs+U2BGbjaARj6Ypse3fEigs2MAA9WPT9aIJPscsm3azFuuewzn6VXs4rZFpJF+W8nlmjEkbL5hL+g569fTH6GrkerTWyNHhGUNnBQnOOP19apX8z3WoxR78RRhliQMSFU9AO\\/epIrZElXl28wgEkHPXkc\\/\\/XpJaajLx1S4kiid5iGQ5wF465+opIry4ZZY1lARcdDg85zzRf2yW87r5pSJ+i7sZqC7aVZiJx5jIiqrEfMF5+maaStoD3I57iW6k8iaQjaDsBOQBmnIyJFGvlEEE7nzyVwOOeB3596gQDzTK3TB6\\/T\\/ABqzalmKnjcjBxk9MdvyosO5bsrh2lUF1Kn5huGQDn9fWrEBV9oKgEPt3HjJzjNUIjmJ9wGWyfcHrQJlJRd\\/zBvm+bGemO\\/9KVgNOIwSWU8KQRRzearK3lgs2eNu7kjPHH19aTWFsbe4VUaVbiJlEpDELu\\/i6\\/gPwNTyNJBLJaNCksqsils7sBGIIB9Dx+VUtRJvJLiWZVQlPuBAozz245rJJ83kU3oHmMl5I63c8akHOADjAGCe+KsTxy3L+VfanE0UqBSzAg4A\\/hwMY9yan8I2z31mYGSMvlkVnGTyMj+VGqRXWm6oun6lp7wgn5WWXcmD1Odv+FU3ra4W0KL2+oQWwUpst2XhkcjaGHcYORx\\/9epFspIreKWWW3nlUlAzTHKr02+wI9q07+SGzubmOeOYQFFEKsrBW+XsWA\\/LFZ9tHMb61IQPt4MJzgr3GPTr+VJN9R6FvTI5IG882Fsu0ndu53EEEcHg9Rxj1rR13WLyVYjLbF52Gd4AG84AGABwABjFULW9WF3smgQhmLoGJBTnIxg9gMcVatGa8Wa1aNsIzBJyvCHggH8j09aTkxWXQZoeuLa6qJXl8sEjfHKAp65Yc\\/zFdrq2pWeoeHncOgY2xREUBm3Dnp179PTtXGTW80t2I2jt2njJLbhuTIPPpg8Y\\/GrdysFpYLdBAsko\\/wBVGcmNsY+g7\\/lUyeuxVrmxrQhtvDkcmmTSzQSjbdI6ElQvJZB646g57dKpW3ii6s\\/Cj+BJbGGUPM2yZCAsqP8AMrYPQ5IIPvioIMM6Wt1PPEseAYmIQNnPII69uO9O1c+HJ7NXt1CSowVwhILBTgFfQ9PzNY+095RabNEtLod4u0\\/T4Z9GvrY3JiliE9wjN5vkzhhvROmeNpxn19OdG1vLea0WwuNOcySOViO0EMCdx69xtVSM9z1xWPa3V3b6Xa7PmSOaQBigDAEYPzHPOCDgce1bImjltLq5t3NrdRZmjLRAiYAcHPKZ5zgDnvW97W5jO19Uab6ydL0VtFjWSFJo5N6Mm5wWH45PJHXsMGuefxKsMkrQxl7qb5Y2ZABxwMD0\\/wA81oy\\/Y5YruRY18ya3aaIwsmIN3KgDJO7I5I6Z9sjE8OafBceJp7SYNFtQCFSgXcSTubsOoH50ptNWHBNMgNzJGrtP8pc5QfxNyA344zxTrbTrl5PmVgkqb0mbhSM4GPXv+IrS+IQsNNtmkW4j1GWFxGiMoIRmYFiSCOoz7jjmsXV9bW7ijiYhpVTy3wdqgAjaw5ODjPSsoU1a5UmloEMV3p0N1az2Lu4T7Qki5Vkw\\/HTHy8jjn8KuzS28gsZ50FvejDTvG5XcpYfLjPGPy61j6ZqEtubiSNBcCSPy5SZCz4yMnOMVWdCJPOV8AgKqc9ACRj25q5WTMuexb1GWxacM6L5UhwJEONowetYGywV7qVbksc7ZPmyAOMY9eK1ZIjcWVzbkrvRAB8uAOnP5Vzl1BKtoXMBiTaRhlGSxP6daIq7epk5JvcvJey2k8LyyKyqobBHX\\/wCvin3Etpf20kpml8t+ETaOCevPU9elZkkE86TxswLRBSSf4ugAwPTmi2aSxVnQSNa\\/LywwN4IyB6\\/4U+RbrclxTdyOOK7sp2kXesRj+fcBlkHXHWqMVy0JePh42zuBHDdD\\/QVrapMJWMiSO67VUgjb8p9MfjUFta20skrohEUXyqGbLAEdSK2Uu5t1NC7isH8I\\/arZnZkk8toWH+rzzuyOvXHJq\\/Y+JZZRotkJ7kfZpPmkLBiUPIUnjgentTdKjiTwVcW7IzXEs5CYXnaB\\/jmuTtluEkHlhxITxtB3KV5PuOKEk\\/kNux9N+DZ9nhPw9a20Cz3j6lGl4FXOFDlnJHYcZ\\/EVd+Kp0WxvLZL23g2zhxknbt+ZSuTuCjgNy39a8j8IeJ9Qg0X+0tHkCahZsitCqfLMhKj7nALDOM5BI74r0\\/Q7qHxYw1PUJ\\/MNtb\\/aZYpcNtAJyOmBygH41x1YNTTN4SvGxjTpBPpV54hg1ORk03AVIp1bYd5O3KABjhVP4mu41CHULtLZ4LiSWzntt8jgFdjgjYxOMYIZs\\/7oPWvJNMIOk+IvDDRW0RcPeRzliHLIiblA2kH65456ZrX8FeMNXWzuFtkikKiOJFj4MoYsuVyCB0YkYOSBjjgKcEt9RKpqZ3xAs9T1Gbbp0chF\\/KquGJLShNoHzdOeW688elaGieHHXRzHbtepIvyi1ix5krYJDAEDHO7rkdM1s6lYRXsVl\\/Z+Lad4FkeUOxVEbksg9OBj6GtjQ01byI45WS3EMIMF5sBIJ5D7T\\/ukenWoU3K1ger3OX0GzvND8dztqxiiuJoYoUgkQM5JbK42jBJ2Hp3FUPFmqbfiFpUULz2r3z\\/6Ud23zNzfKCPYjr+ea6DXNR0u4ksWudUXULqVPJZ\\/lEiOBlR93HU56fXPbyTxKt9c+LJnuLiMXVrAkkTcDaytwo28ZP8AUVtCKm9ewSbij23x94agh0Bb2K08oRoMxMTIz55yWP1469a8\\/ltLaGwZ7qe5VZgrrbt93sSOlejeGfE8jXsGga\\/czSl4TLb\\/ACjbIvO5SFHUZrn\\/ABHpzz3kLhDH53mLAoVlYqNoGF28feHXsD25rznGcZWTNJx5lzRPPtCs5hbXdnBbXFy0tyJkkjcbFTGCvzdx+HA681Z\\/smGG1mjViZ1iEmZOrc84Pc9+1b99pt9a3dzt09bdDGJXGQ48w90YcEZz+FYElwE1KH7Zu8ycFHBYjkDIOT06Dj\\/9VaVZykt9fzOSqrRtLcpW1rcWNoPMuxKsUbCMsRvA5wOv06+tZV5AINLlWeOOSd2bfh0YoRjjIPc+\\/aujktluZEMRZokI3hVBDjoQTiqWq6VeXMMkZMMbJgIEPG05OQB7n9PSlRrxT992v8jnhO61Zn+FbuYxeSqBkGBtHyqAQCCM++am1VZFZkt2Lyjjfx8oP6Vj6bF9l1SKx3gecoDscjBXrj8K6PS4JLGGN5pT9nkkwS7cDIJAOe30HeuitHll7SP3dwlS97nRzeoQXNxOtmiR2\\/n4427Q23ozDJGfpUcmnn+zWwX3+YCVB+7gkdOmOc5Bro9bnt5dXtJvKEiyFo98gBKjhsj0Ixj8elZtqlvDrlvBJcs0DfdLAnBz7dTxWkK8pQTtbS9jVSbRqabYPbWhVtyo4zz9MUMlwCqJxGR87k4\\/z1rYNpcS2sc86IVZQIwrZ4Hv+BokszdIoZVVgMlRnj6+9eZGvzNtnnzlJSdzHst1vNtPGcBT2z2yM4rXurcizR45pZFVk+8pHmDPJI9fTtVd7GOKUiVXcYwAKrancG202UIspZgANuSF6DOfz\\/Orb55LlOqjVlbRmokD3N7FG0mY23S5xkKmRkD9Pyr0Pw\\/Dolz4ea\\/M7wXEW+N4mfAJ3H5gD2JJ578CvLbGWVFSewMUsqwqv75cqvPQHHoO9bcN7N5NtYxXSyvLEZHhUlwjDgjrjgkkfjjitNb2PTpO0fMn1vRzqttLPbrblUwysRh8ZAA6j1Pp0FZng23ltdQntrwqFRVeSF024PQsG45BPr6EV1Hh9dRW5SS5vBIsaqjKBnywSQAMH6n05q39msV1S4aGXocoy8sw3Als44wO56Y+lW5uOg\\/YqU1Muz654jgvbK6vL2yt7OBNsUabi0iEbWGCQM4J59fxrI1XWZfMuNI0O3utRlddsaOqquWzykm7nBxwfTrxWpcWP27XXiu59sUsYMWx8uxA4GeoOfT61zN7plhaeILJnu0tD5TO7s4C7lwfQYYHpyevY5rWlN3uwnC2x2tv4d1oR2cuq69pNvvsjLcrcWy74nARNg24ZtoB6f7XXNdzDquheDPBb6fdXtvZi3Vo7WQsuZz98sq\\/Vv59K8P07Wr0arbf8JFp2p3NwsqyyXUCEfuud5K7uTnrxk4Peo\\/iBZL4h8S2tr4dmt5La4QuzM5kc7cqFIYDaRyMA9fpWvLrqZc2h6R4QsbbxboNvrfnRXLtNLJJFGEDEvJg54wOFBwe31rP1i2fTIr+0tZrgRP89tEi7kBGAynvjpgexqr4Nmt\\/AnhryrswR21iTuUzfvZd5JJVR1IIH51DpWtQeK9bN7bxG50+BmKQwq0bMoXIweOepxwelPl1uti09NTl4lu5piMSvsZdzKSWIIyODwDirL3clhYRb5maLcoZG+6pweMnr36DtjNNv7WKyS9gurlBJI+Ar5XOCCOpycYAx9awIdfkRriyuhIYSF8gdAZMnccgHnB68YrWwmzpTdW1tdWVtbmW6uZI5A6Kh8uJeFAyTjoen+1+NR60DbapDBZFGikiVVRW3KME555A5I9OlaBtLafw9Ld3NyEaKIKDt3ZQ4cDjnIIPHA\\/rhXksVtcotve\\/Zo0h8xlKZz8u7vjvgcnpTUdbi5uhQ8SyvaaaLozM0s+4KCSPQA8cHmsi140Gys1iR43aV33nIdgTwRjtg4P1rV1y9bULQzQyuLeFdgdlBV2AzwOp6dRVGO8ENlbW68TFWUhkByXzzg+5WrSJZq6IPKttrGOOOWHDpgk5wFwP4uDt\\/L3pbeW4Ezv5mZrmcEMnKbVAGcHHJ3Dr0q5odnFaa7ZXErEIRINxY5J4OAPwrGu71pbuc2MCCK2IilIACoX6DnBBOCOB261zVYOb8jWEuU0Zri0hVTc3L\\/bpDvfLqIEU5ABVSQc9eMduDWF4hvxYXEUyW0MsGx18wK2Msfm2MTzxwOO5rSnS0hZYr9mvJpNilBJliNgORjsAy9TjrxVa8uNBhu3ishGsEMqsiywly5AywOSQFyen15waxXNF6psttNaFe1tLe6jtb5GlUrGCzLGMLweMYA4wR6nB9aqCKRLm6vorhngEi\\/6piEc8nbjHAzjv6+ldjqOleHtQtJY9HkVLuNPNcxSFkO75gGDYA\\/Dgd6w5LB7SJLa7tTumCiV8Hy2APJGPlIzirp1oVFy7PzJnTlDUdbahbx6d5FpDFbGPck7ylgGGRhBknr7beDWLqVtFcmOa2ujslT5o5UwEPOAo\\/i6Zznv3q\\/HBHbGSObbJHgPxH1yudpHfkdfQUmrXVzpyGMi3jaOMB4pZCQvOQAR\\/jVxiou6E5XVmUdPOn2LtKYle4iJaN4U3LnHQbuOD2x61r6d4wurbTAjzma\\/K4cSqSZAQwQr9AOfwrN0g2l1o9zPO00FygYqoI8ls8Dk++adqM4OlRFoxIBGjIfMIweM4K\\/w8HjpzSnGNR2avYcW4q6Kd2g1Ng93JM80chJcuAGb24Hc+v4VX1W\\/nkuriO3RUdlCMxiwBtH8LcY75479as6cVtNPiMbiEyHeGkX7rdwSefwpbK4t9T\\/4l88QjZ2BZE4SSQ8DP5f8A1qvRa20ROr66ntQ8SR6hOtney2sMsZOVB+RWyCMeuazNd1O5029e4js2aILghM+WQzFd2R9MVnWWt+Hbq+mvjpi3zwL5Nv8AIMzcA8+rcEDPrWBe+JtQvXubG8iSxIjKwxSKZFOMZAIOOg\\/OvIo4RuduXTrf9DWpUja7epf0\\/wAe6lLfXsUD3AdSZUijGQw2gqgUnpkHP1qPUrrxlf6Vb6pLGlrEY1MUaH94SedwUHofmOSD16Vz+gaHqOi3D6nZQtcReWZTuRldR6sMcj6E++K9Y8CtLFpYurPzJYfID3CXKE7WJbmPA+4CoA74x06V04mFGhacIpmVOcpqzZxnhPw2fEN3c6\\/r0LR2kRKCJRty4A3MR+OcnqR2rR8RazbxQwWMFrAluwD280RwScfMp9Dnp9R610b3F5e3NxMJI4TKSXUqckbGXI\\/HA5rlLjRN1zDG0D3E8I8yNSpPJIP3Qe+Md6wjOFWXNU2Wy7BKSULLqJBcRSRzSXCKNrZBkbk5GcHjrnt71fstXisDbmJbi5C5do4wSFxgk8cdK0Y9E00I2pPfK1u6fLaJtLBsc\\/L1ySD2461Wgj0mS0MNutncoqhYYo4S+HYZALjBJwD2wOc0P2E\\/suxhGDi9Ds5\\/E+n3sUdu9xyY0BNvNvJPH4cDufT8a8\\/1fR9KuZZbLTtZne9ed2eORM7mxlQSGACngZPetXSLvTPCtiEljikvmXzroE7yrAbTuOMAAk\\/L9a5bRxqN1fSeICLg2t1M0Uiqu9z3wpHI4wOmaWHpOjzSg7JbebNq1bmSUjO1nwPBazwS3FwxV4\\/MuJkPEWSQFPvxUB0u40UibTIFvY9pJhP8WcDdtBJJz\\/OtLVNNv72dpjq1vbRNn5TF+9YjPDLkc4zxzTI9O0S4tnij1VlmTPmMYdrEnkYIHT+Xtivfw2Ifs7PWXc86ory30J9EB1S\\/hty0i3DxlPKiTCRL3wfcdev4Va1rUSt4I0dUYM0JCOZMbemFznnIJOSOKy2+2aYUgtzNGsZMZmXhmB64PUkj3rc8LWVhLaS3OrRxwrGrKkbFWVARk7lyDzyePTnrVypwqu8ldkP3PQq6vPeWugQrG8rXLsscYjjOFZjjPHGR+PNZaXV\\/DC9neSGK5gj8sxxqWLtx1Pbr1\\/8ArVfN1bSXQtUuZFgX7stzLscqOQAq7jntwMdCeKy9XtQl4r6C7RKhEbyuhAlJz94HPJyc56VrUTST7BTs7o1ktDcJLBepNNPMq\\/LF+8KKMfMDkZHXI4NZ8EE8VnLqMCzXLRFgizHlUxjJA46YOffvWzY6Tss5L621WW4mkO2SKRmdI+vyh+F6Z6+3FaOlrc3qLbXltc3V7FtAhMmwMQu4IXGSxxgnjjgcc0oRUvdY3Jx2OSl1GG9gY3Flb3RZt2InAKjjOFYDOeuaqaZq01pN9nS0YTBxHDh8ySK2BhnyeMemMfjXV6zY2dn9nS\\/v\\/MuApjiWFgQp28KAAcjn73JIA+lYOpWlrJfxrJPBFbJKC0gbbKcYySp5xyOen40ONndGsZX0Zrx3dxJqyy3VhZrbRQmJreP5WPJCvtU8jg89sjpmotOt9QhjSa6URGdT9mt9pXr0fpg4AHQ8+9P02Ez3BtrKN1UyDZNFF5jk7egYkAYPJ46Z+la+ovqKmOW4W+tHx5TSSSKHYHIILZJCj22jnoBitKblNGU1GDMXUtLgublIY9SV7uJPJJkTY6rgAbjghuc46H1NWbjSrK2WRdWuRJLPiKIROdkh4xgjIIGAevaqh1KO01q3srEWUL\\/eaaK48wMc9wE5xz0z37VZ1PxHNfxxy\\/2hO7XDlp5C4CxheoRcdO3OM8nmjli733DmatbYbFHcT2rRSW1h5t0zxo5d1k5YhvlzggAfXir3mkGGC6ijRXYuYo1z8yggKDx1Le2Tj3rnNMu9ZtmlECpLEkjLuUYQnd7dua3b6\\/j0maN9TS1IKbtq7mL\\/AHSOOvUnoD15pcq0G2w+1BtFm\\/dRMN6gxFBI2QwGM9vwqDxS81jHZ3Hz27yM7bTMx2gIc\\/KR1+Yc+nFUPDsst9JFcJLcWcPmFpnEmXYEnIwRx+VaCWNzrPiGG2MxFrbxM7SmIPnJxtOSoUH1J4xmo5dLFJ6q5ujTLq9t9JK3UcKs0cmXJACLtLEnGF6457isjxxOLXxg8On3SzxtahgjqcI5O04OeeRmuoW50Pw+LTUGQKLkhbeOBV82QH5hufjAHfr0HNcN8W\\/EEV94u0y4tSEjSIxKAMEfNnnHXk\\/zqY0YxQ3UbemxT0XSYmgv7p4muXgZVLqcBmOW6cZIx\\/h6mnZgR+H5C93DDJcvJJIgOdgDAkAdjwaktr2dRfwyzn98ElXavRgD0z3GRUOjWF1qWi3jMs3lxFh5oUOdxIGMZ3ck9u9N03ew1PS7KVxOlzdiZJmVcKpXcWGO54HTFXBNYxI6WkBWYEhZInBD9wcEZB7ZzXappWmtbf2ZcX15KHVViVYvkHBG5iOQRgnnPHrVPRV8O6PYQSWsEl1cRzFPtUKkkk5BySQAPYdOD352hRaeplKqmtC1oWmC\\/gbVPFV02nW6xqsEEhO+ZwOWVeSw6evU+lU1s9Ot9M1WzW2v7kbS5ZoWUqApLSEjKhRnHQmtLUdZsRexafFcTlp0zJmTcoX+EH1J9+P0rIvdbs7vS7lIpWgTc8ex\\/nLKq53ENyRjtxn2rWVOHzMlOTZQ8O6Dqml29nf34EQnkU+Vt+ZVJHJ7Dr0qb4last9HFaWUjXBW73eUI2RRgFTlc8kHaM4FZ+pePZY7S0to7yK6Ro8zCRNpb5s9F4A449OPpXMa\\/wCKxLc3Edrbxx25YGMpxsKrjcB6njPris1aCaT3NbSm02ti1qBMJs7a8gt9qzK0rxSDoBkg4PHB9jWLr2qWl1fzSyxjy5mLdSxXB\\/h9M8dc9DWVd30xKRz4IOWOcEZJ\\/Sof3swLlF2Hso5UA4wcc8k1k5NmiiMuiouS0T5QAHceOcDp+NV1RpHLkbRtZue+KlSTCMQWVyCMkdBjp\\/nHSoWO+UK7\\/Kg9eP8AJqGaDcn7wAJbPFWI7mfy0hZz5HUouPTGfrTAqGEFowM8g55600jjlVXb2JOTUvUHqSyFpJU81yAo25ds9KmS2dl3FScZJGRjAHrUMKgQu42nC5JZffpUlvkow35QgcHjJz09PehCH+UQjEKPnJx9Pp+NdHo0sP8AZ0Y8nawBUjNY+neW0byMqhsZBPOQO1X7eSVLRsFec9ufzqJR5tDOWpJe7TFvRAijkc1WGHhLM33SMAUzZM7L9oYnj5QOmKefkbG3A9q0ULIlsb8plG7njHNaPh1hDqkOMAb\\/AOtQRhHG7p7e9Otisd0jqeQQc1dJ2miJO6aPqXwNN5mlQkHPFdP\\/AA1wnwzuN+jRc84ruVOVr6hHiTVmVbocGsDUVw+a35\\/ukZrE1IZFdENjnluUImw1ZXjFN9iTjtWgpAeqviNd9g30rRCOP8MNiYrnvXMfF9M28bdME9K6LQztvSv+1WL8XEzYKxHRq4sWr0ZHXQ0rJnlZRbmyKoPmjyy9efas4klQrMdoPT0zWjp9vJc3KxRDO5goycDJOBWumhnbLFclEfzyDtkAQYPJ29T7V8ot7H0EWc0JMMXjCh1O4MO30pyxxybmklAVdvQfNz1OOhx9RVjUNNminm8mCYorfKSO3rWnBo1+9hHdiCN90\\/zyHBwducEds9efWqfmWtSKW1mbTbS7e+LgELjktGOflHbtnHvVjSXdr5J54FIgkIZXbgkf7OakgtbhzbRLuiFxKMeZ+6jIHX5jxgY7U+PMd\\/dr5flSRSOQkeGCtuOfqAOM1mlbQaVh+uQQz2qzCKO3LsQGx+n05rEjFyC8SK7gn5tvHP41p3829S+M7RlMsGwc8Gmx5AKQzRREdSy7iSew9e3Yc5ppWHuV2SWGNy0ceSnHfn0qBZpYGE5t8RnjrnPsKdfJduw82QSLjqmU5z7jmoZXjVQuzcFHRnPX3Bz+mKALFtcRkAyABcgncQSOv4ipZJIgxMMrBASMFgSM9D9Kym8puVilDkfwnj6HOasPp0xiSRZiAQd2QAR+XWgVzoNLvhBcEXJdT92RscZ3A579cfpV5xHdQ+cMkEnftUswHcnH1NcxPEEVdmoEIFwwYg49v1plreXNqQ1tqjq4A2oF+U+2Kmy3Gdf4cup9LukuIxFcW7up8soVcYPUE98Hp3zXT\\/EfWINY+x6pbRDZG5ygb5vcEAfKRgjvXmdnqGuRx7IY0G4AgkZI64+nX9BRZXGpX9wyS3TxK3LeWcHPTJ71m6d5KXYpS0sdBdajbX1rFBLM9uYMKomQlWXnvwM8daFtXljTUtPCgRyhVZV+VjtGevYkdsfhWJqWnXynM947ja2BNIeFXgYJx74pbK51TRbUyRO0tm8n3M5VmGeehzxn0p3XQXN3NvWTfm4iW4sAPu+W6uDgj1yOnNdj4bi8+wmkSM21yp3Zkt\\/lOOrMQ2DziuVk8T6ZrUG24j8m7GAiMMK3GDgn+R9K6Dwbrun2sYW8eWO5dBHHth2oM9d3HK\\/jUSV1qti1voT26JDYX87lbiQvtWQKBk5JJCjtye\\/ah1t10GbS7i2BuBJvD7f3kbcgfTjtWxPp97fWUg05lXdIzRhVIUHH3d27BGM9v51n6Rps01jDcJFIpjLM6xqFIGB3PBx7+hoTVtQs7lJ7eYKS0gPlIHUYyrADhhn86jtLC9vFw4ieIEMjKm085xyR7nr6VuarEbaONzb+Xg4OThlVj8wx9dw\\/KtPwfNp93p8sUwjFr5QUknlWHAPXPP8AM471ErNXsUuxyh06RLRhlsAkEuNwc9+gyenGfQV0HiCa5his7e1ZRZ28arOy4AJPAPHbpz7n0pbu3+yyPE9ybiNX8uIKpwQByeBk8Hr\\/ALXXvVxCokkt2O2RHGZM53JuPJ9SpA6ZyKzasUncy54jH5Nt5UrTFCBJHIF2Acc4Hv8ApWPNo7Qyh58byPNEuSMHkdeoGK3oNRjh12281m+zTWcdpvQApvUnBOemScZGev0qx4q0+fzPtNvcJ9lVeUEYXYcHGaiKUepXxHk+s3FyZ5Le7kSWNJi0rpgkg4Hp2\\/xqQXcSMimCBkYhAduCQP8APWsu0WSa+nmk3ujlw4x0GT8x9OP6VYjkt7dLeAyIyKeWBBYkn8vSt5xOSV3dl+4L7o7coka7yx2R5\\/vDue2RU77t6k3CMTuAVVO7DD1HTp096bC7Xr+bJG+C3OP1raSC1GmhooXTGWBduZCTjjuBn+RrjqVnGx5868ou1zHGlXEVsRLK6lmbBU4ySf8A9X5VShjurSMJcN9oD\\/KGkQEDP3cdeffrzXaa1ZiCGGW5meW4mACqnKqOmOawbxIliaJlDMWzvBHB5HBrOliHUWpjTxLlvqcrEkTl5XkYEtl0HBU\\/T8M1YtYZGtYYf9cqyN5h2bgqspAP\\/jx+nFWLtoGl+Ygu7bXc96ls4YIYriXLBThdrN99sjnH4V3SneJ1utdHPauUtoTAhdZoW2klhzg8EDqKZ4btZdS1R5HuxCcM8kr\\/ADdiSSO9bGoWlzqDSodkabHlaUg\\/MQFAU5\\/P8axdMH2W+aCYSOpyrCDDHqOR2I\\/pWylzRaT1N4z5lpudvaR6VcaZCbWVJLgqFmYAgBjnKqfocZrldd06O0dxJOhnOw9CAoIOWxznnFb3hJIU05gZkCqdz8\\/Nn34wPp7H61k69Gl9ezyySrF5Cl4eB+8+bvjp1rCnJ+1avoQm\\/aMoeFb17W5EcpxBLiMttyMFhnpz05+oFfQHwp1O0eLxNZ2l40g+zxR2\\/wAiozoC4xkgZGOTx+deIaFLbTzQxyRxedb8BGXcrgA8EHsfarOuXDwa9Z6lpKJYshjR4lGFyNpyV9CcHHet5+87bM6Yysdvq72utXV9pizQ2M9q0txayI2x2V927KjPUBRwTndUvgnRobaBLZ0VkeFnaZWBXZtwwZm4B+bpjIOevbivF9++r6pNqkGGmiVUDxAqSAoA4I6BQc84O4Vs+Crq01Ke8stXvLiNZoR9lQt5bvvPTPcHKjPXvXNUU3G6fqgctTU8N6zNbaXqCYS4t4ZpYQzrj5QAsbDPXJYnHqT6VsaD4wkvLu7026gljWKNYFOzztoBZjkqORz9auWGkWtq8LR2ML2VpAGaFpd4GJAcHrv7nkflWlNq+gaf4l1QKbcwXxC2+5QsUW3IAAPK8OpA7cjjFc06lJwc+n+XobJ6q5wOpXlnrPj3TIra3kgtk+e6WRyQMJtzwMqCMnH4102heErDV9Q1SOIjz1laKOOSQc7VByh9j3PGT2rgNa021uLi+1q1uZZUivYYt6McMrByyjjsqDv3rp\\/h3qk9r49s73UbS48uWzK2bIjFZizHBHHTAP5CuuKvBSj2CLXU2L2K+TV4bzU7eSK4sHhWOOaMxndt+b5u\\/I+90P4ZrY8fQ6L4n8Mi4s9RltLmyD4idtu24\\/hjYf7WcDB5JGOtdLqjW+paLf6hqigNJIwh2rtMZQcA5GecN19a8p8Bw6JqcOqQayAi3SOzSMpjRgCdgyOP4fx+tRyX97sa81tDT1CW8\\/4Qm0utQuzAHjcSW8YDsrA49OATjAz+PauKubj+0dTX7OzsSjSxDbzubAAx6DOa7WfR7iy2pvN74fF2kItnkLNEMHJQnkAMD7HP0Nc54s0s+FNaj1DSmtbpHuR9nLjDqSpypI4IxzyOjA1EaUebT5GVSLlZvoVkvZrSRluYtqlsNGPvRydwR6HtUWqXcsNnNNEwDyYwM579verFxcR3NtFqyqJEuAGMTQKoK843MAD1D857elN1XS7c2vlW1ztiUFmJx8ncY9TWUqFNNSZxuhCLc0czHfW66zZ3E1rveRWVXk6ByeDgY5B\\/Cutkt457NQGXqNwLjBPHrz0HSuO1qws444r21nJ8sgKjD74JLZ6d+cfhVyOW6imtY8FDPMJf3g6AkY57\\/wD1q6akHUiuV2FJyktHYn8WrNEsV1EijyPnCOOPQ\\/iPasPTRDezkyzuixRhY2fg47\\/juIxXfSxST7ZrqBCSCEVhw2OmBn+lcPNJcjV70eSz4AA2DiMA5\\/p\\/OpwsuaLj2M8PUv7rO5h1G0l0S1toJ2LQxBQu0liAcZ469abp8F1MouZZG8kMRhQVBIJHNc5bXU9zaSNa2rQKrlhLwMHAJB9Nwx9efpTNK1u5gs57SectHCoMaZ5UHrgd+o61xvBygpKlvfW\\/mVOkmnbc7CQ\\/aImCszccsQc5xWTp9q09nILu4RWilMajZyfRufXOfrV6xuJ715crJBCu04I5br\\/jWhd6XFJbWrOG8sOGPPUg9Tiub23sXZ7\\/AJHNQvSbTMR7yCCV0iIcq2xyVG4t16fnUcXki3juBLHaB92WzzkqeR0xUaQR3Wv3JhO37Mu5kYc85O4e+cCltJob8bSxL20gACKOSR7+vSuhe7Zryv8AM6oycXdGq2uRw6FcxRpKLliYwzYJJ5yc+49q3be5NtBZ34uJJVmjCOisCVOQGz6jLfgD2xXKahDGIRcIFDRMZCAOeuCf09e1QWV2Y9OshcxTXRkyEXncGIYZ69\\/6CqUlUjddzso4rm3PQLPW7jIuUtkRbZWKiU8lBkYIzgYHH+FVdd1Wa9hhlj0+MKwDbdynY5bIOe2do\\/Oua0VPszGK6l2mdiDHK3Leo7k9QeoqfxJrU39rJpdqAkIVQx\\/55gFcfkc\\/1rWCblaJ0c143Zvr4gF9bvZO7teWbqshLBy43NwOME89Of8AHmdeCS+XPEYYnhl3HqQpyfQ8nIPryTR4Uj\\/4n2qLZq4ijMZXJDFCQ2DnpnI5PrV+4ks7u61BklO2OEbVcElOmTk55J68dqKlXknYwqq8Dl76+uJLcy6jJAY4yxjTzN+WOMnBPGf0\\/Cp\\/hzqup2Gpw2stzNYWjFpHa1hDuqnjpg8ZI7cc1V1B7e7u7b7NNCAIjkYUIMDkgE+uQCR603QtSk07VvtshVmlIZkVt28A\\/wAP5iuqnLSzPNpzVKq03odXqtzoNxqDWV9qaX2oXVqZ38\\/YPLmJB8sYHDYHcknOKb\\/wjcds2nLIjgvKu4nrtY4HH0Ofyrgtcu47zVWe4MUnmyHrksFyT948\\/wBMV0fh3UdYupYZW1O5vrKI5ZZxkkDp83UnJHUmqd01Y76deM1sd4Ve00d7W\\/zJGCTBCpHPy9M9dvKgA8DFca0sEkqxalBIUIZY8jOMdQcfh1rf1W9+xW8N1eLJM4L7AiAgsfurycdTjPPHr0rmbNI77SILe5lY3rTMJFK7thLEnpyB09c810WsW2P1RzJYWcUbpsiBZmjyVY5z3zyce3biqAkkuL1rLetuwO4nA2hRgDOfy\\/GrN\\/pstlCqIhAJAKFW3hskgH0+n0NV2aBXkmkA80AQiRWyCAzZ4x6jH5U7q5Joarqskt7p1jabSqgs42bNvdiS2c4A\\/HPaq+ttCs2pW+mKqWjyJcwxbVAlUEKzKck4JGQMdDnFWvCdlBPrGlrLI8seGjnVVAJdhz1xnuKhtY7m48TXKT2+77Gz2kXPDLuAAGRjIBP5CotbYbd9yPRdTku7iXUpI3nmWWCIL5oAjXIG1iegJ4GRjgVP4ksdH8+Z7ZpoJ03s6sw5Az8rHjJyeozweMjmqcupLYrqttJFauXdZUlt1A2Mu44LYPG7B47ir5W71f7N9hW7+yvdSKAZVkGzzGJQdC2c+3U0ntcE9bGJPBqFsVvPKVWjwSWIHViDx3Gc\\/lXW2OsXEkG68tJNUV\\/3WGxGqMR8rYA3A1d8WWJSxMDxi1uZkBIkQDerAj5VzjjZnPBOTxxXO+Eo7W5UPAqGfzGYxnLeYEViDgdMFe\\/t05rGrRVRXNqdRwLGpDSru3Z7J2imSPyybicsSDnGB6c+v59ql1o8lzp4hnS0hQHhTcAsSPvZY\\/xHggZ79Kbr97KbyBx5gdxungLHOFJAzjufes3wxCIdRnGuQ3P2ZslVDHluw5644\\/Ss7ThDR\\/q\\/0L92Utv0JxG8GmGz+SNYg28RYYyEZIJIOR16HHSqWvXEMdhbMqFIZVVTlQTtByTjtknr\\/hWlfzM017bRWzL5xA86MhSSGHynHYZx71BfW+nXNmYZZrkXMA2hPJCg5PfIOMeuTWkZ2SlLqRKPSJEkcX9nJqQYl5DgZXbtzjLLznHB\\/I1QtbOGa7S8TfKijbIrMDuAGAAfU\\/5zV6aPf9hsmcFCpEYEoVVJUKTz2\\/AnrU5NoiW9pJa3onD8McMoHd93GOQTzjAqlLl3E432PRp9E1M+GILO70m1t5Lt5HkhEa+YQemOcF+hz7CuL8Sadq16sX2fSNUlgtpilv8AaMsxcnls8jPyg9xW5rvinULu4kkW5lMgyxIHOO+OvHHatnwn4rlv7ZJtQvr1baJ2LQomd8hOeDxwMjiuS1bDQ9pJJ39ephOpCXWxB4R0zV4Ht7+6u3hS5gINpLKCeMAMMY4JB9K6FpxBvuIHhtYJz5T7ItwkI9efl6DrXO6jrS3txJahMGQEq7HG0dhnPFZTT3lvJbWw0+4d5htt5S\\/ytj72OTng9a4pQnWlzS0\\/yMHXf2TrbiRZJds8cIc5JlV1DMSeOV4496q7ra1kllkl2yxncZF4bg8Hj+Vc9f3M2mWW6BNzgZZQxBY+gzz1PvU2mSSamFnv761jhKfcG5ihHPO7oB+uapYaXK5X0IU5PU1dQv4LqytzHHHCQQwlYDc5IwSCeQxHbOOaqQ+Ibm50y7dVgiGCrSRqA6jG0EtnAz\\/KuW8YXJt53sLO+V4Ww\\/mKMMVHGP8APr2pJ7WF9ISJNgWMKuwMu9mK9+OeMnnnoBXXTwidON+oOcm7tj9T8TXl1Y3OnRNI3mbYpVV1cexUg\\/r9a6LTpTbaQlhYXvkW0UeZZHTBQk4JGTyeccdsVzmkWNpE9pdlbRVt8ny1YCRuc5\\/litCYw3F0d6KWjUhI0YgDHJzgHGc\\/Q5rarTg2qaWi1ZlOo09NjD1q\\/FxhV1GQeYdsuJggc5x046jP9ak0nSbhIla1kmkaVuUToh\\/u7ivHHOfen2mmiPVxdXCmKRJBJGrHggMM9O\\/btW1a3N3cyfYorryZPO3xTBT5ahmyzYCknHPr7DivXjFRVhyldaFyO4gsz5Qt9RlEEXmmO4lEiDk4AJ+bA6kd+3rWxeXVta6arW6Sw\\/aVYlY8DLYHJEin5evHJ6Y61kgQaXDII1m1K6mdo\\/NuXJmKkYAAJwAcE4JIx6dKsaVo3iaUXMl1Y20cbEKI4513IPugbAwHQ9QOfXrSUoudyGmkclO9re3zXbSTtqEHEeI8bMY2lgFA5A\\/Xn33ftk2m2lvNfQFru6kZYVbAmi\\/hHysCoB9Sp6\\/jW5pmkajpllLHYxQRuV8yS5lBXcxOM8YI\\/PpjpkVT1OFYX+zRx291fwASeepdUgIboMsc8kds5PTmqc\\/aTshKSWhnXNxfGDTJ1tWHl+Z5EiOBvwTnK8BOhbgirL+JIoNPtIIrCGLy2O3ehRQyt8zA4yWweTk96nfStctNRWFREI1kwDDKzFD8xyDweOTjuccioNS02HS5La6mkWGSeTbbW4O+SRjwS7E5AJ4wDxnPvWji1HQalFyszG8YXV4be21a8tjE7AeSgl3MwIzknryOB9c1Qv4BJFDONJOJYmeMrC7ZXrz2GAOo9Kf44meLwwt5HN5ktjeLE\\/f3IHJyBnGe+Pwqz4JudSl1O2lBRobW3kIhchyyEgEBee3NRFqTszV3jG6LttqV3c26RNIIkXbs2IBj6DpnNZeuz35MNvI8r85bcT16ZPp0q1Lc3em3FxaRQAIjErJIoBwOh6kd+3p1rn9W1ST+yJmuopLi7mmGZGc4ALDOV6HHT8aaaQmm9Sz5ahFlE8TywShm6kgk4x9QCa6fVGjuLGynt7RLWTzdzusYyWKnjfxjJyOueDWd8PNKb+0bR5WCSyMXCsvCqVJD88DjIHU5PTtUGr3Fv\\/wk80FpfySNaTqVzHsBK43EA55yTnp1+7TSV7sUnf3Ub+nWFpbaddG4nlhljxuhWbYH654zycrjHapZJob3UIEQIvkQPITPcqD\\/AAgYJz9a4fxFq1xcauunrIsVs+ZRt+UNIT8xAHAzgVpwTwWsMlzdXk9vCkHl7oSoLk5O3B+8Pl\\/DNOVRaWQlTet2bOlWN3PJKYoo13lym2TKv83AWQ4DE57ce9b3hN2061ummeW3u55QHtZYcl4wBtyGGQQS+CB+dYWiXNvNbRXa\\/uYUL7S+7q2WLIMfh0610PhsWgtNQv7lGZicsXd5H4Gc7mzkfTjg4rJRbVy5SS0MrUp45NQgsHS3CWrCNdicnb0Y+\\/vXA+I\\/s954ktYFiuQyREosSgliTgADPqDWp4z12IeOJtPs1YIsakMQCxOzPTHB9h3rln1s22p2zxQv9ohWQSbiysc9B609LBFO9zpbqQaLHZR3VyJWwyurbdy7sE8D5sggDn19sVc8M6\\/DCgtHkt4LR3zOUIQ4JJLO55zggYGK4PUtSmv7jzzDDFvPmBYhtUHk\\/wCfTFZzyy3LvK77yWJY5znuSapTs7ofJeNmeojxkIoZEgmSLygdkZY7XyCAGI79CM8jnNYNrrl7D5kqtaCJV8o87ixXjdg889B6YHpXGXUrzkF2YcBc8ENjtntSWweJXYqQjMFIyQV9jTdWTYlSjEvzTo0gcuUbJZQRu46Y5JP51SebYoJ3sxPY8Z\\/lVO6uc3JbDFQMAZ6+5qxau0iGTZsVQSzggZGOff0rK92apWLsMSyDzWbJI3Fj+mKo30qRyLHu3BTyB6VV82aBxslYZ52845prb5pipwpPrxik5DsJ88shfBY9yeamcRqqmPaee4Gckc\\/X\\/wCvS2wEDbpGJUDdhT1PTHFNC75WCKTgEDjGCfxpAMmGEQ4Vd\\/XByeOOfxzTY4ZJhti+dzwEUckYJz+lTRQpIdr7lbtgdTzx79qeLdhF5xZwAdmT3Pt9KljuRp5yqAisHBzyOe3+FCPuumaZAxYEcjvjrVoIkTMoZ2dgQCOMEe1VvKlWQSMjOQeQQc0hXLMcalwCrOiDB+vOMipooZvszyiDbFkhScDnn\\/Go5iY5yQpLEBirAEZH9asWayXUnlBSVYZx6H15\\/wAfxoVyWXtPgBhTDAEIMbSCDnnn8TTnVkzGyhiOAQfve9S6d58iFBHukBAzjngY\\/SpiPLlIZSTkckdKcUQ7ldYOuQcrxj0qLy2ycAn19q0lkx5gDryAW4qm0jKGCr97rx2rRIzvchfCrgcHNIpIkBxxmkJbJbbSfMZBkHr1q4x1Bo+hvhJPu0mMZ7V6TGcrXkXwen3WgTuK9ahPyg19JDWKPFq\\/ExkuMkGsfUFypFa8vWs2\\/HBrogc0jn34emasN9i30qS4GJCPeo7vm0bPpW1tSThLE+XqpHPJrN+LQzpAYZyG7VpMvl6sD2zVX4oRh9ByeneuTEr91JeR00pWnE8h0+SOKQtGPmXknPT3rudJ8S\\/Z7cLLFbSozMXZgNxyOR69a89ijTf0bDHg9qusD5IZoQShAY4O3H4d6+Lqxu7p2PenHVWZ0Ka\\/DIZPtFwh3liQGUEk8enA46Vnx6jLNrRGmNLIrsHkUybVfaQRnoM8da52+i2SvllzjJJznOfT9K6fwxcw6Hdb4lla5L7JB8pCrszuB6+\\/UYxW9+bU3jtdFr4gXarrIto7a6W3IV\\/s8zltr4yQpzwMkHFYMV\\/bxB8XOzzOTgdD17Dpz+naptW1WSbVJGMj7kAjZpG3Hg8k55zgnjtW\\/P4NjuNGstSs3jlUwZmVG+ZHBGcjHoR\\/30Km6SL1ZykdwtxII7i9AjHOV4AxyO1W5b5QpSDZJjozHAXHv+dRpoCtcyW6h5GjIDEKeuM4x2qheWtrGkixOD5bY3E\\/e\\/8ArDH60ySS6vW2KYpbdTjaQidvrURuLdo40eWTZ95gueD3wOnP9KgVbeP7x35zg8gf\\/Xpk8kbAbFIPvgAUhmomp2UMRjtrfGe71DLqHmAZmbPOPnIA69gBn\\/69UGdZESNIVUgYJBJ3H19qIId5IPGDg+1G4XASmGYGOQgjoyE8etWoruCN22qjK396Lp+RpktumzMBLbVBbjPt19OR+dVpYipOQwI657GiwGxZajHEzOI4pOegdlIHsD1+maiS+khvGmRWiB6ofXr36Cs62DiUGNlDL843d8c9O9T2txEkMyTLL5m393swFznvntjPT2pAdPd+IFu9sskQeUReUxQfwgfeOP1x9avWt5o174cuLZypuEYSwxhiW43ccfh+tcnby28zw\\/aIVt1LBd+07R2J68dKuTaYhVZLV4JCWZQ8U5YjABzjH+1+eahwVrId2TxaTbXNjF5MqLJg7mMo7DjI\\/P8AStHS\\/EF7pTf2ZqFuJYgnlZHzE8HoD7EDHtWLpJlFwUCRlh8pR3w307HFX7q3RrqC5smlhnZ8Mkse5fmHUfyqXHo9UCbWx1ul+MfsemiCG+SSHG+JJCWK5JHQk84PQj6V1PhzUbfU9EAtHzNGX83bEzOR1HQYIxnnNeXS3Ag0kW97pP3o8LPEQe+BkEfqD\\/OpdM1H+zrNTo099buwKMxQOrtnoA2aUlpoVfU9Q8VX1tdi0ltNSjnYq0bxR7PNxkndtJyeh646+9UdH1jRrSa4jj1MGVwirA7BN4zyAWxhgAeM+lYHhJ4Z76BdUY3ckpQK5yMcdB0Pr0+lbHjfwxpsjsIrOMbMbswlfLUjqWODwfaseZJ8rK1aujYvJdP1C6ju9F1OF3hDK8M8ZjKYUZ7dSf8A0HNYNzeaXo+qQQatqKSF1aOURvuKA84HOQT3Jx1rjdC8MreavLphO2fabi3IcgOB\\/Af8a7iEaLb+ExFBYNIPKkW7Ux5kik2\\/Nkn36GnNxjoON2YWuauXs7iL7RfpJBH\\/AKPMyqkEnBIH3fvFQvHHIJ712Gta1Dc+Cn1OQAedGI\\/s7HkSDrken5GvK1mNysunx5jt7ryX8pX2on7sEt9eK6J7O9OhpaxtkRQpJluFc7Bkc9eP6VNWKilfQn2lrmJ4Ht1XVJdxR1cdAMsW64HqDnp34qnr9obO7khlJ2FldmXIIBXjrUmk215C1zJBYW8r2oRp\\/OXIHIcAZ7HYBjr1HfFal7YzNd2kr+TbW1yXjkEiBVUKoOwjPoo5AHJxWnPyybuT0I9NvWhidVPWNinH3j0A\\/wA\\/1qxDfTPc+XcP\\/DxGe2On61nwWU0FzZ28rKYXdyz+Z\\/q1AJwT06YP4VkXUl2LpneUZQNlhkgfNjGfxrJ4eM7s55Yam7yO7i1p5ONwkMZEKAjjrjOfwNVtY1MXNysKxKSzZ3HtjoB+v5CuM+13NussULlVkfIJ69T\\/ADq5cvcJNaO0mS4DHn26YrKOBUXzIwWChzcxv3thbtpy3PHmLy6ggbep\\/OhI7N4o1QsPUEZwf8muffUZpi9tJ+7\\/AHhkJXk47Vfe422Ek0Lb2X5UAHVjx+NKVGcVZsc8PZaMv29tM0hgK7lVcLuPAPfv2rOW1htdXLtmCLKKkkOBjGSSTnPTcPwrV066ea2jLIVlIwykYG7pxk8Zqy1tM8A+yW3nMCRIQMkE8A4zzyR6VHtHFtMxTlTm1LY5KK7C63JarGsVtJG0e0ADjJI579KzZL+SS2aV4o3ffkNj7vXP4dOK7PWdJhgu4biaxUFgN+1iCG3Zzj0B6Zqjqfh03FvIbQxKzZYL\\/ExyOP5\\/lXTRxFJpN6XOqNWBj6dfmSeO\\/mjgj3T4kcqo+Zl5bHpjt0yc0uvXMt1qMl5FIQsiRoyp0YjAHGc4+XPT0qU+G54LIy3ryneyrGY8FT2zkkYAGfT9KoXVost35Ewme4hjKkIQQSCcHPpz71tTlTnK8XsbKS6HUaBa2cGgxTTC4a4ZnR8HajhiPbJydo596TwVZQHxZbx3sn2iOMGOExvtZdpJCngZzj0PFYlvrt3a2sOJomMDmSNPJAHOeTxyDmneF7xf7Vh+1bgrzgnJ+VDkkH+fXpgUShLWXcep9KafpFhp95Gg+0SSzW7Sxx+UJFbg5jYjOOOn4ivIrzQ9Q8Ta+1mHYQxSefHOgACgKAVI65OOPc4rv7fU7extUnkFzMQwWFo22SB0bAIyDk89P4hnr3qeBtI1WfTF1OzupIZppWZW8xlyGzu\\/3T8h+ma89RdKN+v9am8o82iMGSNhpsnhmPSZoYg\\/2qXcoXfJsAwOhI6dz2465wb7xRr\\/AIa1FLiy1G6NtFEBaBoVljiwSNnzD5etdL4r8SXGg+IrzT9S0xprVGB320+4iQgDJyBkZxgbh1I5rhtZvYrqwnN1cI0skrgWk0hLROGOFGOmeeuK2opwST1X3ku0Y2Pavid4rtdO0Gz1e3VWtJ28uXZalGO7LfMWGRyMEjGDXmXh\\/XNH02DU7mKVnSS6aOK3kjgkR4yRgszDdwcgEEe3Sm+LNc\\/tDw7a2NsskkExeaUFSApCqm0ZHZlOAOmcds1n+B9Ft7rQC+p+WkEVwzRovBkONpz16YB6dxW\\/KuT3h819Een6Xps2h+Hracap5kSSbsli4JdsnCjhhgMMdgK4HxRBc6nqc1\\/bLb2lvO5jRIWJLDBVjgkjJB69wRWhp\\/iC81HwfLBq1zdXN7YTLBbRlnDMFb7xYHB4P8WcZPY1h\\/2jf\\/8ACPTafc2jyzadbyQtIDkrlhgscbeQCo5JJHpWLp1b3i7Mc3dWTK+k+HZ4h5FxMyody+WjcIfmORg8HA9e5q5eQD7U6oUUvFh5VYKjZJIwMklv6CuruNAvdY06C6\\/suaANp5aFmCfvgpXIVgcE8kYI6GuI1u2vtJ1x7G1J8qNxLsKnZvIzuzjjgZrODqz0la\\/4GLjJKzORVvs4n098SOWxHJ5hGCOhx\\/LpWhpWqKI5I7pQt0kTeU5AwCBkcevWsjVit1qZEcCxzMxB2sTvPr6U5bOW40+W4YPIRF8ny8ggjI9xg16MoKcbSFa61O0jkubjSzeyS+eoiUgj5VRsfr\\/+qsHRLot4iLXYwNp3uOTjGCeTxgc\\/hWNpmtXVjC1szFoTw0Zrehjl1u9tri12PJDGW2SkYYDJC\\/8A6\\/TrXM6Xs1Lm2fXsZxjynSrDps1ittp67HmY+ZO\\/zM\\/Y9DwfeucstPlk1S+sreZy0nByhAGTx37j6jBpdEvrlbqPz42MRcgFuFXrkfzqPUJ7qXWrhLNUQzfINoOAV4B+mKwp0ZUpSinvrrqNX57dDstL1CaS5vYZEEaiUMgA+UISeOwXtjHp61vRzLdJhLhTGq4yGyR+P51wPh65vXvYJCUkAfyZSRtGGXIOOmcq2K3dVvBYTTWgDxxjYeMDG7Byfz7V5eJwdqlor+tjGtS5tUZXjJGOqwSRstqzwMm\\/JG7BH59enpVBrltFV7WCRZJW2h3UZDc9sd+2PatnUr2BLSKa\\/iklDOUix8p6fX+Vc9q1nNayrK4MNu8g2yK+4Mh+ZSB1HQdfT8K9HC\\/BGEv+H\\/4Y1pK0EmW9W+3Wml3U5V2DMpjLpyAT\\/n86q2OuiyhV2neV422si9NgwGB9PvHGKv67qU8+hZLR3KtN5eY+CR1AP+RXMxabLcSQRqWBnjkBVlOcKevHvkfhW+HhzQftUty4X15kd1qckGpzWmpyK4QBAqRtuYrjooHfk+9Nlg+32C6xa3UyCcsn2dogTtAOCOOuRnGemPww\\/Bt48V1aRX0u0wNuTBz8oB654yB\\/QVr+IRNa7LnT7iP7LbSSKsT8KQ3J4\\/u8Y6k9KUI8klBPb8jpjPmTbHeE7grBc6lANlxNII+eQeMkHjnkn6Vf0aRIY7gbd+JVXKuQHyCce\\/U03w\\/pdzF4ehaKEMZsucjaIxxhsHHdux7UzT7vyLe4sTGTMMvA5Xj5RliT+I5rir3nKTWpnNStcg1GGRTBbQSCOWYnz\\/QdTj26+vNU9Z0l9J2C6YSyJFuBwAfmI6DPBGCcj1p+nGO7vJJbjzikD72JOMnoAPrzWrq3k3VvNLcLgsvRjk7m9M9SCRwKanKMlH7zihRU7rqcTqNzCYElgaaEBgVUQ\\/eYDHPofXgdvrVzwzJfnyLJJY1eS5V4ioO7rzgD8T07VNbaNM9yYrolmKb13HHzDHHPr\\/jVSG9kstTF1FgzQXEZGBwoycgds16cGmtDoo0lTidx4svRpsUctx5TxLg3UUnG8kdR6N0\\/SuV066g1HVRcQzz2mmkFmVAzMpHQcepH6Vp6hDD4ljNwmnk+U3kssrEsCcFSCfUdvauYv737LE9tp3mQZURzbCVckHkY9OK1UuhtOSjqaWs61EL6zgjvpru1iO2SbZiYD7ud2ck4wM8dK07jw5cWUH9oSXkzQQMDHHJGoIPocjI57e9UodN0BtJW58+Xb5QPnsejlgMNj7oGDj1rd8QasD4ZWwjme4EhM0bOOinsT+GRmoqc3MrF07NO5H4TluntXnspUE5Jw\\/AKkYLEdxwB0FbdstgNYjv9zW0MkkruBgAsTgA\\/ofWuY8ItcQ6NfStkI0oBkGFES5UZznuSorRXVbuaWyt7hTAjXgmRy5DiMTkEsMdBtHGe1a9boh9jB1WyM+rzWFrdhlvZclI8hdpPHUZPynviuu0PSbz\\/AIRQLYxTPI11DCXiG0RL8vcEAHJHOOe5zWLrDronjS8nht4maF3RV25AbYQVGPcjv6V2fwv1y\\/1CCaxhBIOoh7iCOE5RAy4Ye4Ix65IxmiNuX3hS3ujP+IcAjtNBguQ0NutzLbS3I6l1kY4Az0+meCDVPR9Mji8O69qlnM8UEUrpaYjOGA+XJYAgZzjnHJ7Vt\\/FLR3fWNP0ua5S5i\\/tCZwWk2l88jDD\\/AHce2D0xVLT9PtrrwTb2umXf+mCVspLKQVQ7SdqnqvbJzkr9KTikmioy1TOO0uJZblbaaZkuZiMMmSFYDGOOpwQ2cijWbJYNUNtDdG7keL5S0hBQAck8nOQeK39J01Zr66uJraG5nhVQgiyuT1OOo9fQHPtVXXtNNxJcXttCbSRYlCxIQNwJ5\\/QcD68VnGMXqzRtrREthptnPojtfXMjTSLvglQbAT0BYAeoHcVyd9dx2qm0+0ozo3LSNv3A\\/mcfjXU6hAl1blUtZ4\\/KEKF0lAZck4AB65K5\\/wA5rg57aUatMZU+VDhWLAbiDw2G7cVXIuWzJ53fQ6JGitNVti0ltPNbIQ3mRbQXC9Mjtxxmp1ez\\/tE3t5IgWWM\\/KHyfM3LjJB9O57H2xXK6xdu5urudI2l8zy5G6Bs9MAHjoecVKLralqsayS20UpMTs5JIzjBx0Xjp1\\/pPJbUrm6Hqdtoun2+JNV1U44EttaxZGPXcSc9OuKg17xLY25gs7WyT7DEQIxGABGMffYAcnOSTzzS31xGIjaw\\/PcPjMMb8gDvjnr61C2sRSQ+XBZ6erxsFfMY3soPVj+OOevpXnuFapP8AeK\\/4Hmym72aKcGkarqM63luzQ2spVo0lfCSnnOeh9P8A6\\/WtqO5WKweJ7iGQMgWMxjADjnjJ4Gcj8BVbUpFnYzCSS5mk3MyxTMu0j+FQOmPxFcrfR3EqpaiKeIGMEMrlUKdOvGB179qulRdd2lokKM1JtLoa13q2nwXRurmzjdYiRskfLM56YHXIxn8as21ydd1GOSV\\/sttDyvlx4UZ5xz15zWBHYTaf5M22BoIXAEindkHnA4q7P4g+3LHawLDL5bBOAUjx\\/ewcY+pyf5V6iwy0iu2\\/+Q76aGhrWnW0y3GqrGohXhCACXIxxjHFZtpp1\\/qhLXN7DDBCxaSBZP8AVYwMsOm4+vX0qwL2xmtpbKaZ2WA5kAY8467T6dKs3l5f6hdSrb2EkWjZUSyADCKORjI6nP15HPat\\/ZRgorokQpNJpDIrVUQxJHcpuiYwMeA\\/P3dpYFVwOvt9aisdJvWgURWVu0ojxIXn3uzHJJbHQ8j8xzVbUbe6uHjsdKnls4Xlykcch3ZJxg8ZLHr1x178V1mg6FPaWb\\/v7mSENmaN5shnXqXAHTjv+uKxnywd1uTz23M+1ivrKFImbMs2ULRScYyfuAjnqfUcdavwRxJoyTmS9mlQkndKBGFDc4weT17+tRajaTNfLcas8kgZdtuuz5cY4Bwdy8duep4zSWFxaW1lDJqV0RBExji2KFMrZyAcDIx7eh59CjGVSWpnrua1lLZyPbz2l61pbwRE2siGMuG25Ybwemc8bs44AbBqrYanMZjO2qyRlFZJbndGSpk3Bs\\/xcccnJOe3BptnrssCSyRmC6Rg0ai8RXRGfjKccnHG8k98Yqg2l6K8ct1qO4yzSMvlxMwSNgevZccdK2k4wkn1LST0DUL86hd+VYxfarRAytdNLk4A+9wSM5zjPHH0qxpM9pcebpumRwSLcBfMlZWO71ZsnLdCCMY+hwKo6TJLcwWy6akNrbr8jzK+9iSTx0IBYY7Y6fWsrxFqVp4R1a0l0rdHNJ8k8JJdZEy3zk\\/3hx1GefrWlOMlJyeiB2fuo0rXxpcedHDEiEKxWWQIFdyep45AHGFzxjnJ5pnmXjaat1FLeSTwXcdyA9sPLciThQEUDow43HqelcX4bSeXRL2\\/dUlZWYkc\\/KM7ic9AAO\\/b8q6ODV7V4XuPtUqrZyFXREIZvVic4yMY4HOKfPzL0LcOV6GL41AvtdfTLKSVryUST3plOFLgBtoVSRn5D3PPem+C73y7OXUrmWIJZ\\/PKUwhkDsF2HGDg4PbjisTWb+\\/vdZubi1shHHMo5xwB5ZUtkdsZOfWotGSW4tJYEAFuMTSHgn92pyfZec\\/lWUW3qze1o2OjHiUXl5I12myKVNkCqBiJAQo3Aeuc\\/UmnXCpcXfnO6+VGw8toyD84GQSPTOK4i3fexcFxwTlj0Xt\\/L1rStReG2ZVZmAkG9Qx5x7VSetwcbKx6hbTDSra4nvdQkdvKO9ll+4dozgcDjpkV53pd5KlhcapDOsQsh8kZQ4cM2DhuoPzKfwrrdFvNMvfCUlvMwG6N1ZJGD7cKTu54A4\\/SvNry+uk0ttN87\\/RmmMigZ+bBx+WR+lVOTWpnCKuzoPEk+\\/UtKWFT5ckYcMD1bJHBPbpVzSyL22ltri4SJUBZTKOAQRhVw3BwRzg55rm4\\/tDwJNNKVS1QLGWxnkdAK3\\/D013f2U0lsscBgUPO6nDHJxxz3AOfp15qLPqa9NDYsQ1ra6w4uIlFsmzELuuWXOGDDnaQT35OBU2g6zBfS3AlWcKgQRwt90DC4zzyOvX61yeuqbHVZonn3qZ2DMZBlxuK\\/MO2MH8aZcagU1EXsMqMWHlnYADtX5fu9jxmqv0Jt1K95rD\\/APCY3mrOMssjhNvTgFV\\/pWOBO0pkkG7d3Zs8mrcJRvnl+eLdgZ4UZB5OM5NWZFW2tVMCwvs+ZpAQSecYz+f5VCiXewy1jk2BjI0Q5Vtoxjpxn8RUV2kb7XiKnA2hQvbP0604OskRaeQLKzj5TjC9B9egp8aRWTOgcykg5VX2844P4H+dVYRNb2hNmDc7UWQZTHLZz1A6Uj3MaXcTlJFTaUJKnDeuc89\\/1pVhkubSRppkjw2UXPO4Z4x3z\\/IVFb2cZi8yS6y3IAUZ28H19+PxpvyEU7lYIZRK8bgM2VjbrgHBzRHLE0YiKeXhwxbPYdsfWpMW8YKz+ZvVs7WRWOMZGajMzpIYlVTGSCAwzg4x2\\/GoKHpHHfXbbImXjoBxnoM80tzHJbM6z7WaVMqx5OP8eKgvJC8nnxtgMAAoXHAA\\/rmo086XL+YzCIDndyB2pXGPvL6a4RY5EAK4H4AcUsbyEh87ic5BHsB2\\/CrFhZSXEoYQsUG0EL3z29zW1PZ28SC3WEvcb8nDDIAHTFRKWupLaWhRniNtMbhUxnJPYAccY9KXT7aK8Y7zLHAAWBJ+6M8Yp+syvMxZNxLSEbWwOBjjAo01TfsrmQRsGwUBPT0\\/nU9LivpcpJLmykaKdEXft2ADe\\/OcnjpzTbS1knaRmlRFz8zNzk81LJZxxzgI424y23OO\\/wDShAXUssQKI+Nynk89RVIfoOW1McyqUO4kBnfAx37\\/AOetaCRKk28khFyPTjmq8abpVMNsZHKk8tuIPHJ7djXRaXbRvbGSWBJmwcq5+UH6A80m7MErjbBILaParyIeu4KcNuPIB7YHpQ6JLKVH3S2Ao4NEjAPh\\/mJc8LjA9quWjRedvVT5hHy47CqiupDRmpGil1bk54qSWBIgdrZO3gj1qS4QLcHjnNSuN659RXTGNzGTszGaH5DnnHNMtwxk2\\/wk56VpTQsRxUUUG11raNJ3E5qx6h8IZNjiPPavZrc\\/uxXh3wzby7+Md69uszmIV7dNe4jya246XrVG8Hy9Kuy9ap3PKmuiByyOevRiQ1BJzAR7Vb1BcHNVOsbCtyDiNRXbqYP+1UHxEXf4aJ\\/2ava0u2\\/Bx3qHxmu\\/wu\\/H8Nctf4JI6KfxRPBxJJHkgcK+MdqupqLh1McG0x\\/MWcnAPqcdqqOg8+RSOr856YpLhJIPNRXLBwMkN16Hn24zXx0km7M+lsmP1F0nsUnLkyb2B4+mP61DJcvI6zW8BVkjAds7jkYG727Ux2AtmicjrkAc8jjP862PD8Eq6RfX0UoCxRsFDLxlgN3P0GPxrKUlSjd\\/1crSKMyS5SW9eaVTJJOcuWbbyev610PhvxBqGmExWl15U00OxSBnI46g8dR9ayI9Lma5eYrtSOMSDI4J\\/u59eD+lUohE9wJHm75IBKn8Dg+9aRkpaIafY0UubmS6klmaQvKFL5J\\/eZPU+tUjErMxkLKeDj2OaiFzImRuyNm1SeeM\\/wD1zUSSYyx5BGCPSrAl+YFt0Ubhfl+cn0PT\\/PagRwMQ8j7AzHcFXO30wM1CZWLE45xUZYmkMs7gifISpIww6UWzFJG2HGRhuOlV2bJyV69KVWwecccHmgDUlighVGVnYZBDpkAg89\\/6elCqjWabt37wttK87ecYI7VSFwxhRSxBRsjAHX3pBc7AdgAyScY6fSndCsMl8tZGCKcZ4bNSSJ5zKkZdtgK8nOTyeB2FQPI8hJY57mnCRk5jOMcA96Qy1a3kC2r208HyOQTIoBYEf0qTSb9bC582N5Ym81SlzGMOignOPqD0+lZqjPGQMetPjdVZQ4ZkByy560rAa15L9rnbUGvheTTTZm81MHPYt9c9asT6o0MxxbOg2rvViCgIxyoA4rn5WBclenr61fD7bCGSS4VkdtrRhssAD6Z\\/nRYDu31XS9WhDWjILzI8uDbjdg55zwOmO+aoNLcaVfjUbC4tXuGJbyTtZTuBRlYYIDAMevqCOgrloYYjFLPZy5KK0jKxCkLnHHPXkdPet03nlaari6W5inA8yIqCT3OcdKjltsO4\\/VNZvTHBKGtZN4Mm232B0PoRg9DW3pvjfWIoZkk1oCSKDmG9hA3HumcDtjFc1KI9MZZhDDc24bKBiygqec8nB9K17nUtA1VrcLZizie6i3q7KFQZAbJH8OB+lTKK6oaYuq+J4pFt76KE2mo2zhozu3pIP4hkdscc\\/wBK7XVL+28U+Ccx3ltp8zDdJ5cZG48jGR1H0zz1qtrMOi6rfi1so4HiRWAkjAPTG0flmuH1fQb+wv0WzkMQklLIuegyMnrjHA\\/Ss+WMrPZlXcbk\\/iCdtJvreXRpFliltgHEoD4ITbuU+mD9M0aD4l1CyW5huoEvrSSE5jb5WUgfKyjjgEflWBcWt1BcmeWSNw7nzShBxyMkjt1zkUmq2MCOTbXHmxmMOuOmCcd6pKLjZ6kanoOh6b9o1D7ILj\\/R76SOUSBCySKMvjPJ\\/h\\/T60\\/XdIu11J5XiItvmdIwQQpOcsOvTHX6H2rz3QNW1DS7qO7066lR4RwqtyOucZz6npXruna\\/DJ4LW9CRTRyOMLJukJ+Yg7lJ44wOOxyPQ8tWE4tdRq0lYzdStpWM1uxfy5If7QsZRgsGxhkOM5GQOeK8\\/wBL8+R5Pte8tLwwL7RgEnp656fhXpvirVUtNL+wm3t51cDyJOQ0KFgQvOc4zweuOpNeaSTTzXG6ZTH5S5O3gEZJH860p6xaCeuiHPZXkenRaoYYJrUMdySjPIJBPTpz61lvPILnzAflEYCqxz7YrSj1K7GmmxaYtEASijkEkcnP1NU1V4pvs7gxtLgZkXvnH9a6Y3SJLt0HsminjaMOyFgDg4OMEe\\/BqPSrt4pUaJsoSNxc\\/d4IJ4HHPPSk1xZIphh9k65BCjBGOOf5VnWl3MhgfdxG3UKGxkg4I\\/OpcOZaiaOytbmCaVTG6sF+Zx68Z7Vaa4aBvNnaQlzjCtjPcVylnBbxRpc21xvcA+bET0+Yir0N4zyN9rXbsdZFG07ecDkn9P8A69cU8Prpsc9WhGaNfWtSEKlLhzI4XDFjkg5AH5cVd0SSOeWJ9wYTIFGM9RXIrMza19p8p5Fi+Y74yVbByfoO2a0NL1eWeQgsAomVom2jChmIP8xRLDr2dgjRjGNjpLuyki0s2tzII4yjLIAueGJPGPauPguo7OGNkAefzFMj4KsV3DK+4GOv4V29hdLLGjygFCQSznIA7n3HWue1SP7R4pne3VgiJmPy1BbBAKhecDofwrmwzSck15kUtbqRThgjmt71LiGM2wmbbEE3PH2yOmBkdc8e\\/NUDoGo27Ktuv2iMlGDRt2xklTnsGwcZ61uxTxTaOtqNOuxPFHJ84cZZiu1vlzwM\\/UnB4GKgl1WHQ9XnubO4cwxqqm3dS43bMDngAZ6YrpjUrfZXffZ\\/NdzpV7C6br2qf2JJaTQbLi1lDxSvuVwc5DEE4B6V634Du5tP8MQIssfzX0qsGbhpAh3\\/AE+YP6dfevLRqVpqOm3V6gDqIXZomyfLI7A+nTjt+VdX8M9LS\\/0WK4nkaG0JaRnyWLSZOcknjoMkYrLEYnkpOU4216a69jSFZp6op\\/EHxIt1rVzpd1FAzkgCViCCGydwOO2AOffrxXkOoSb7mU4IJck5JwTmvRvFFumneJY7mRZFtMlGdEJJQc5J5GckY7HNcs+krqdtq17D+68iViqMu0AcHr0HHaunByg1zx6pC5uZ3NjSZ4k0iGdrSdpp1lWKGOHKKHJxtLZxzgYGDx1JrR8IpcfbtQgvrk6fJb27LHDLGWz8zMTx8oPY9M8ECtjw\\/Cz\\/AA5TTo5Ps93FH5gDhdzMeUAPTaTzmuPn1eVtetxBG1vJ5jRtCrks7MDuJbndkkc8549KuD51JIpaK6EuLqK81GXSrmQQBPMMLseMuQcAnGMYOK09I0+\\/TUL+WS5kt2MbSbycrIFkGCRjBHc56fjWddRppWrSvaXBluoZEhMLxh8god\\/XsOeOa2L+\\/vXtmjW7W3Z7ZGG1ssIfM6ED3Udf61liJ1HFKGifV\\/IhttG4mrxN4UTSLiC7iu7UiSFow4RTkASIQcA8scD3rPvry4fSNQv1bZIyKhCx5DAFgGB7jjHPOeveoRJBJLczahqE1xpt2YlS5iiIVAABj5cdV3AjHGO54qpfbZVu\\/JaOGzubf5hbks5jDnHy455wayotydmv8vx\\/IpN21OJ1hb7+2ZDqEZSVMCUqgXaD7AelbXhO4MulTWxikkw6qWT+FSwySewyFqsJALh\\/tEhnTiMSuQckEgbh1xgYI5PfuBWfpGo3Gn6gRY3Vxb724ZGKEjqOh9QOK9Jq8bISNrX9KCXEzx2ogjV1VmwcB8475I+n\\/wCqq2nJcaPdoWiOJQrFdvKNzge2atza49+l6NVvGmnuZwzy+SAq\\/IcYVCBgtxjB6dqszaT4g1KQJeXttFcmEyOszBMRoeTgDngkg+x5qLpQtUG0tkU3knvdSS5triO3czKdjsAAeinb3PXj3HrW\\/wCCpjfW+tG8kPyqJBGkYDNsAOR2Iz27D1rA0RYrS9gaQwqznMUk6fJ5gYHEmeeD+fr2robfQb6KJtTm05YrSeRYhKLotjcCQqgHJGA2ex7cYFYzhFvkf9ai0TNLwbHo1teTQauzyQuYg8ZkDLmPaQwwB8vTPqetXPEdnb3OuahfJhrTeUDKNq5AB2qDzx0rWg0jSraJob+K48tN13cTWgGUYoWCqNvyAlTuB4CnH1hvbCC5icaZdFITOxMS54IABA46Ecjj1rhqydRXg\\/66lyi3GyOX1SxfU7HTrUzrHcqjMhVvl3c4BOfYfka5\\/wAUwS2VtZWU9y0sqbsIQBsU9v0P5107xrqV3BLayKY4Oqv8uOf\\/AKwqj4o0oNq0d3bXaTOqgNg8qPvdO2RkZ\\/Cow9T2c4wk+7t2ev3HJGXLJRMOC2e0sLWO4CySXU4YLz90ev4Z\\/OptEtDcatKtkXmjFvtIXOVznHbpggE+9GovdQWyXtyGMZ+VEYfMByM5x1wSPyo0HUYLbT3\\/ANIkj+9N8rbQDkBRxjODjP1HFegpPlctzeMrasfFbPb6PNJNGiO8u1GdiV+XHcHHUgYrUuYb2R1gQxmKSRSyIS2\\/HzHIGTnAz+lNstPnutNka9DKSTJGJG2nJ5PIB4PUj\\/Cs3S9SXS542vrmO4aJg69CGwW+XjHbI\\/Kp5m5aFN2a7HpC2F7LNFLOg8hMOZMFQ\\/Xb8v0rlL+JJIZvIuZo720k2z7VyBuUkDkdM5X8B7V08WqXF41okBJgYDPmSFwnr7Z7Vb1Lw4+k6Tf3Um25nu3ExMcWCQFHy8ZBxz9efWuWNFQTS0OicE1oclorX0Gm3EMMKK8W1nIA4dlOAcnIwMHpjmoGe61HWYLf7QLlbcuZcJgH0HXnrXS6PBqriCaSG3FzPEfOwu1tinGwD0wc5xRpkVpYuSLm3kj835mYYCjaWx65BUe3WqjCMb3WoU4JRVzm7+O1hRrwXMzkHahYADOcADHpnFY9hYPq3iEfYZ3EKZllnKjIC8nA6ZyDitTxlq9veKkdt5bQ25AG1QOeCT0557+\\/vS+D7OZUM6AeexDKylsCMcHp7kA\\/WtE3GDtuYyqqdTkiWNLjDXUd\\/Z3Ulgssan5jlmJAK7sDqSD7YPvXM+IdPkTWCJYokLMWLBuMck8\\/ge2OK7zT4FjvYNPglCKkrs48rOCFypOOn3lHQ9KpXi28VxaRXW6Z8uciMkHqMnt3\\/SnCckaypRlHU5HR7PdciwvpJIbNsSCBVzGzAcZ75PX\\/ABqPxB+7vZbYLKmEDYd+OgHH5V02tSJDeJZRTYSYBUlY7FPHQnHAwMfjWDOYLwSTPNFFNAjA7WGwYYgL37Z784rooylP3mZpcqsjt4vC6S\\/CiycSKXuf37RTAjcrYIIP0A\\/w70eGdMvrnxPp9q7Ga1srxYIlVFBYmQO249CBlhzxxUui6vf3Pg22t7m4eVbeXyQgAyiBRtOB06HFSeD9bsNPWGK7luTJG090bSPMbyk4AbnjjGeOeTzg1rfcbWg3xLa2KeOdVuIWlWe5ZdxcnIMiB8gn6ryO9ej\\/AAl8DwLFa6h5kYNxPJNLiNXz+8faVBPpt9RxXkt9bPeeIViuL2CGyt0IiVcGYZ2YKucFjgZ78A8c12Pw88Z6v4e8VXFpdzxrp+m28zfZWkX\\/AFjSjagY4LELzz3JNPmjF2ZDTauiP4tixi8f6aJZZpVtJvszIwG1ixAZwo7cnHfp71yGj399plhFfyR3V0sCzwReWCzbiQNxwCR1IyOnOK1PFccep+MVuzNcTw7pLl592PLUHO5uD3OPp9Ko2bWqeD0Sw1UrIysZ5ECv+8aUgYGcg7AeQOmOOc0Tso3Zcb3sjb8JxOmjyX0qywpcqzOFcPtHIUZ75A9D1qLT52u0ludTeWMyXBfdx90A9Scd1A\\/4FVOyu0svBsYWKG4k3iOMpnaVXn5hhf8APcd57ZJfEGlKu+O082R90oBdQFHpwcE49f1NRKSirtWSRSV9OrMrVNYutQSaDTtK3W8twzl5H3O20YDc8nHJxnHpWNrWl23kf2tLMPKkAGJFYM4GMnGRnBzXUmOTTIFt3lsmSQrtKRkEr3jBxnHT8+c1layP7cvjHBZiMRxLDCNw3F2ZVBPY5ycY4oU+ePusbjyvU53xZBYzpD9iMSGdA3mOpjLbmJUgZOOMcfzq5o+k+R4Tmtb9ruGG3vCvmg7YmfZkqCW5YZAxjBz1qrrlpPbXejXyrF5VnKICtxPvAwxwPZflYDB7E1v6JcXJhuNFmV5GS8bUJlhYrjcRyODjaDk8dMU5RfKTF6laG4uktvKnsIzZO2GdxsUgHsQu\\/d06DnvUFnZ\\/aXibTYkkSWQfup87MDvIM4ABzz7itnVgEYyT2k9td7S3mB2y4GevIB7dvaqGmXX2fMpS+ihmI3PMu0zccZwOBwQB9aSqtapHmuTsXrvS7vS9JE0eoSxkEvIinI3Hrz2Hp+VMsYEvTiZmlhm4+VgpZ+4wevOeR7fStF7i8LWrCzUWqneWG51fpuDc88Hnv+dX7jyLCWSBZ7LJyrQxTqZSvc5JyOD1znjmrdWU1bZmfPyq7KcOh2N5Y\\/2bHcr5CY3q10rkc9yAAnQ8kd+\\/bDGhWbv9mt45bdw4XaeAxDZB4yTxkccGuxtdckhsJBaqtl9nhzFJFHvcAnGScEnAXpgD3GaoXbgtHcSRJOrReYjO4RZScgsQPuZ9Djnn2racrJcruSpyadjMHhOazt\\/3BGC5WWSNvvMMDbkggH6+tNurzU1dUtIrCaOL928ksGyQjIPTjBH9PSt2CLVvFF4q6leS2dtvVWhto12KOQrE7hxn168nnrT3vtNW22jUfOhttpaB4UUcbgSTHn5erHI4zUL2l\\/d1+Q7tL3jl4bS3sZRJqF9eBZBvILhFfk8ZPA6cEZ6dK0mNtdw3EFtMk8XylgJGDKTxyMgMRt4CjuCcd7Ta7p0t5qAS5t7y33bPNbb5EQ5GI4y2SM+gJ29+xwr9vLtraAiW0lOWgRW2sFLDv0GDu6dPTvWtOlJPmkx7rU6HWdZsbzTIliYGG3ZMDjexyCcE9\\/lIA4A5GeorJ1Oa3W18gRXkMcKGdY1Vdu7AywYgdQcZx361R1NbmTWG0yN2vZIky0qREGInkAY9Aepx1NVb693wxaU7QidEZZBK+EUKc5zjJzhRyep9snT3be6UqbZs6RfxzXVtZTKlu0QIiMil1jfAJZwR1Od2QT1NY9vfXE2qXakCYzPu3Ku0Op4IK5GB8vHelaB4dQe9sJ4JpPKV5XkcmMYX1xjAwf0rO0m\\/X+1I9RWJHhWNvNdkALZAVnJHIAPT8e1HIr3LUbbFjw7rO6\\/udPSYR2MsYktyNxEe0AMuCetO8VaXJf6fDPZRO8rJgZxhUDY3E9uq5+vpXKaVcwR6nPHCXR2kba3UqAflH+NaF1rU9xoY08gby+SV\\/hQcEE9cZ2n8BQnoW07kmgXN1ZaPK1isUwicxTb1DZ3Eg46jHA656DisK8nJtv7K8xzMLjdIzcZfLLkkn0Ptjmt7w9ra2Nq1q8SLHcM6SKgwQpH3iRzjPPsAK5W0kW3vVufLa4WGTdjGVb6nHep1WhaWp0N4lxYW01tM6RTfZnUF3AygO0bevJwRx2PpzWagNtomoXYyJCy2pU\\/7QJY49eAKgvdSu9RmZ7wgiXGCRnaq8hffgD3596rPcTSwzW6sBFMwkkLDnjgc+9Dd9hpW3DT3kJDFN+T8o25GBXZeBpohroMkSxItq6M0fV9qkgkE85x7fhXMQSvBHbRqrKhIXleG55GeK6vT3gs5\\/tUCBZpAHUyOF2o3JOT26j2z3rWCIm7qxi6Vd26G4F\\/JMsagAbFGdgD8Yz1JY\\/l71zl2zSzG4dcKzHYnQAZzj9at3UltLJJKsmDJvZlUEgHdgAfh3rPnLAbWDEZyM1lJlxRqrCwgluJXYvG2dgPGSDjOfQD361p6XdLDfyxRTGNzauZMLuO9GB\\/L5f8AOawra9lkeeFB8syttXPCk4\\/wxipNNje2l86aJnxuWRd2BgjGCfzo5r7By9yexuYUuzfTDdIXbJIyoPYc0+\\/vW1CE38hjilVRHsCBVOFADADudvPqailiedZIo3CQ7gdrZCoMgZA79fypxEdvCiSTRyYDBXEYcEZ5x+FFmPQjsdNkNo15IxjtwVDluO3Bx1Iz396iuhIYzsZQjNngEBsCrF1OZiBFLC287BHnhSTgHHT1596dPYNYq0c8zE43AeWBn25NVyq2hN+5mrGfLe4ZSx9ewP8Akd6u2qSm2aV5fm3bgpPQ+vX6fnUMYjLKszMECkrxwD27dKWQATo4jOwckYzx689setJKxT1I5mkjXymmZ0PowI3Y6\\/lQ8bxSMEI3DneCBj1GM1ILeaeCYxkbFbJHy\\/WlnS4a4VHLRSDPyo+QB3Oc896VguR27SQlwyrKJRjtnINOm\\/dWjIHfaSCR2zz+XeoYbh4bmNVlx5cgKORkj39DT3ilVwswwZmDjPXB5\\/ChPQCSWcbVlUIsrDYAhJJ5zub1J\\/pTLZGEqqrqCNpZiOnI\\/lWnZQETpNdDcUjOyLGccDGRmrlzo5i09J0J3kF3wRxjueeOfUVEpakuSWhYtYryKZhDJFJFDjcdhXc2MkH1+tRFZDdySLJGjxlxnGFJyOMenHFEImaPzI2dUkQFiGOCcflnIFXtOsIp7KVWVt6kszBuWAHH86xb6sjZ3K0kayWaTyIpbDd+nHWqejvGyPvbDBgB8ucAen5Vb1zybbTktlTYxk4Utk455rL028S1Ch0D8n5Qcd\\/yqoq6KWqNG8Fv9uEkg3o67mzgYwKzbZZDKTG22IsWALY3DPbjil1C7a9YFkESZxjOf8\\/Sr2jW++4J2Haq9SCp9gDWkY2G3ZGrptiUIjgCbSn71nIJPQ4H+e9Xb6SOyttnJlYZKJjaBirem2qQgeZIqlUwqhuPfmsHXpYjqBVHLO33udxA9Km12JMr2KOZiMsMDIGenr\\/Wte3V1lAl3A7M7QecHpVCwXJZxIQyrjBUHOff\\/GtWxBYvKylSqBQGbOTj\\/PFaolsqtgv8vHtUwHyjPFNfgZ4Jz1pYWDcZ6V10zCY4qMfWiOEHnGaeduKVGwetd8Emc0mdR4HbytRjx0zXt2nNmBSPSvDPCkmL1D717bo77rRD7V3w+E4apcmqpNjB61Zm+7VaTkVtFHOzF1Jc1nr90itXUF4NZQ6muhGdzl\\/ECf6SD15qLxEgk8LyA\\/3ava+nzZqDUV3+G5l\\/2a56qumbQezPAnhjfUpg7FQDkD1p+pxNLbRor5wenOOnWn6p5kF\\/LsGVc4Py5P8A9aq0TCX5HdUDHq2QF4\\/LJr4yrBqdz6ZO6TIoLaOWIuMAgD5fU1NbJJLB9lhmcgEs0K9CR\\/PoKtWYCmKMbi2R0OT+HFSvJAs+1ZbiO5RiYmPAzn3xjvWMrspsoS6leiy\\/s+RUEUWQflweapSlGldthGOQAwXjt1rTjdPNeKSAyyOAN7nGOvUVTVIFumVEeQDIG0ccdzVQSjshrQoyA9dpxRvIBZflJPb0rVuLaMoZAoWKI7XGScZx\\/wDXrNfauQVUHd07irTKTuRHceTnJ7mkIx1qWNBNMEGQCfqcVJc2rJP5aKT0A9SaBkMSbs8tnGBgZyfSpPKwoIXkcEHmn2aq1wqhwq45YjpipWMkh2sysBk5wAPU8+tAmyrIg2AqvU8k1EfSraq727vJIFDEEDH3jnv7dag2BpSq\\/dGeSe1AXEXjn2496eAhPJ59ulXHSGSaKFX+VEyT6HPP9aju4QgMoKoM\\/InTP0FArlSUIJCEPAHWmcn3p8iEucEOepIp9tCXb5iEU8bmHFAyMow2gjlhkUrRSrFvZWCE8H1qyEC7VITKr+J+tRXEZVFkdslycY9AcUwuQrjkEZJGBz0pUkkUhlYgr09qQgbyE3EZ49aVIy\\/PQdzjIH1pDLsV8YrAwNbq+4YVmbIXnkgdj71UMzbs+4LA9G+oqPBzilCMTgCgDXjujbSxGG68pHIbfEclePY5Hbj2re1LUptR0iB5bcsEO77UkgOPVSDz2rjnO2UPHhRgMB1Apokk8soHIQnlQcA\\/hSauB6Jby+H9RMcU8qQytbuqtJHsDNgYBI+UnGOnrVW18NW9zLPBBKrgMB5aSAAZHXJzjG0\\/5GK4hnlSExBmCE7ivv0rW8Ma4dEupJI7cSxyptlhcAhiOhHp3\\/PvUuFlZD9S3b2K6bcShjE7o3APOQVzx+Y\\/Ku5+E+pW\\/wBtg8MXyxG1m+eHcjFyzYIQHOOT7VwC6jNqGsMzR5e4kP3gPvMePpzjkVPpNzCfEFmb0vAkcqBm6\\/Ju+bBHtmsalNyTCOjujtvinDGkkbWM13II90JkmAHUhgAVO0nJPof515+\\/m24VXlLlWCsuehHJBHWvTvF4\\/sPV9MuIZGubK8jSSWG4UNmJuQyZAZMKwA6fw157q1iIte1SBg8ybpXxE3AxyCfYHFFF2ikVJdRbxjcTTLbRi3IbKKCDlOSM9+hPOazkl2X6C4jYqPlILZ59R3HarujzwzNbvftEQytnd8pYZPVgDyOeuauabZaXqF\\/eFXk8lEeX5OSgPQc9cfieKpvlTTIaurGNfzrc3krwPO6eYWVpCWdwfU\\/1qbS7ZmYo8cYf7xVl2uMEDbx0yDmtnwSuhC+jj1bL5YgKzFCR\\/wDqFHi2ys7bUJL\\/AEvItfMw0LnLIfqc5qn\\/AChZ2Kv9nxRu8EkIDO+13BG0HJI+YHqeQeMcVR1f5ZJPJMduzJtdI8gYz37c4rYiSG5htIoFaOYo8kskhADgEAH06K2fc4rFltXuJ2Lt8q4BJ6ex9+\\/5UU\\/MmPmPikvvsrTNGz2ke0MEztUN14B6EBs9Oa3rQaRcxRGxcxHLKCznHUkEg+9VJGvUmVEjR0eJTIWGd2FO3n05NY63M1kIfsSmKXyiJVDEhwWODjsenTvWFSnKptp\\/XUznBy2Z29tC0FikKzzSlgy5cZJ3AdPYgf8A16ztV1W5064RLrTvKCxeVHIGI2kJjIOPcn8faq2i3txb2xvLuP7SiAOoeQkY6FdvsM8+1bPiFrPVbTz4LVhsIkknZCSBkqQPl559K89xdOryzjeL6mCThKz1TKOgXUSeH50uJXmeO422yfxM2Rkj3PXjpz61hyOl3GZBG3+t\\/e71z7jjnPU8VuWvhSaSKO+hvLeFZN3lBOTjHUds\\/kahu9Eul0cCWWBhGpPm7uCCpxgYzz8o9u9dtGtRUpWnu\\/u6f15nRCUXezNDwCttc2ZDeWkQXy5I8ghlLHOfrxzXf+FNCn0\\/UL62060aewu0MkbiQMqOD82M9CcH2IrwzRb+ayulS3kMBY7CeNrZ65zx6V634JuruXVLqb7fs0popYnSYhljfbwVT7pB3Dg+1cuIwlT2\\/NGXu9V\\/XXsXBJS0MfVdSxqkun6zawgSAIJIpcxSg5AIGMjldpxnBrlsS2avZyedcQTupWRGGMhiI8n04b\\/IrofiDptusJ1jSnjF2ieXexNEqxuM8so784H+eeIRPPlmP20RsSAATgyEnPSt8LTpuLlTur9Nf6\\/zQNLVo9shF3p\\/hqxvJBD5LxxGHAAUbcevThfwrmdc0NLvUI7uF5IpDKJ1lCjIIx37dR+laNtfy2ItrPVFlaxmVoGKplWkjLAlTnocrz\\/hWP4h1KfTtQtGnSI2txIwDq2VyvyjvivLjTxNOpyp97ea\\/wAzOqqm0WZ+o6NMLYapcM9tJFK0hkKqXkJYBscnpkdT0HTk0+9kS5v4tWsbeWCCRBDORx5Y65Azx8+SR06VpRia5ujcW9pJNIVAMZGEyM5HoT3wcdD7UxbXT5JCttBJameV0kZoyMjBIxnp07frW6xbu1PX9PVb\\/P8AAUZt6SK+vahcadYadbIsctvKN8crxjDjjsOhycYx2x3qnrEiNY2N6iSrFFaeWRE\\/BkY4Cn\\/Z+XoPY03VvCsc1x9njvJBHGdsKzNlUBx3x8oyemO4q3az2tjoy6Rf2zuLQ+c1zatGwYowKkMSOxAx7evTojOLjGVPV316aP8AXb5mu+zMnRdBsNZtb9ohJbXNvGCbeNjsLqvBVueTg\\/n9K52HTPOuooUIDmM8yttAwSN3PQZGMYrs7zUZYtSnvLFUkSZP3sdtj5JBIcb9uRjDD5s4OKq6RBYarq6Xl3eXC\\/upS7fJvVw3y7fTJJxkDpWtGdW8pS+F2st7abArtnP3VtL9riuILc3UlvGkshQkg\\/xZJ9eRkfWujsdT1W606HxBp0EE81rEIbyKXJJCqQSf7yEMOpPPGMYpYvNWWf7EULwJG7O23lYzvyD34AAzng4Nb3gGKKbUrvVNPngid7l2iibIUp6MM453Y57Zrac1NNSWn+fcalqcvqOjwpLf3UFpBJBGV+V5CwwSGZe5VgARxg4H53LKeW10qB5I72eB+loJD5cS\\/d8zIA+YFc7vcdM89H4vsbLUNckOlw\\/Zb8kC6nUZid9hLH05IHIA4LZ5qt4UhjXwnC726xrGWWJnIHWQ8NnrnHT60KTceZFvfQlh8XX0NvbpPHb3tusiSXFxC371ofl+Vgcc5PBBHQVc1270ySGKbRruO5vhdLcJGQVdYhkhVGOAQOfTJ65rB8jS3j3pF9nu5IztETHbIFdlcYwc87eO2D1xUJuYH1IQzIxniKszKpw4xncD1BGccAVM7J6IpOxa0+wvpftM0EgMZtZLiOKFhgy\\/Myoq+ylfu\\/dPUc1Yj0W+\\/sMazdAQW8ZJmWVSAeCAASME8+owaTTJo00iezvBdlZbkmKaO7ChVwq4znC\\/KMFup4681u69rei3ng\\/\\/AIR25eWEfaldpfJz9o8uNiATjClmC5+uenNZ8sZScSHGMjz3UbmWawcNE8sSLuy+AAoJGcdcHviq9m0TWcs0scRjQpszHtHII4IPIGD1\\/OtrwysVzNPb7l8tVeLnAJQKpcZyevzHmm6WdOmkXRrjS4U3Es21\\/wDVjJYKSDyfr6U21BNW2M5WhG5US8trpnvofNsNnB2sxjXd1xx7jjFc7uimuoLid4hE0y7gvJGcMSR17kZ\\/wru9bGnW2nSxqrRWdsVIT+8R249TWD4aOm6hqryW1qRJAhkLHG0AEcY69QB+PTmjD1ea8ktDLD1\\/bttI62e9Q6xa6VZos6vDjyWGSQBk9TyMAACujgmubFrGyUx3D2+4OjE4VPLwuDzg5yMHrgGuS1HQL691Ce53PFNZSMVZIiW2lNwIx7nqOn41ueFNY02Xxi9tNbBLiW3CrMvPmMuc85yDgn8qSjfWPzO\\/Yf4kvJLa+s\\/JaRRt+8eGUNkkcevHT0rn\\/ExudVUSNbvEkUkasFXYSN2CcemMZPqa1fF0Ny3iVoftLO3mqNu7aABywX607xXMsN0Xgk3SuANjNlSuwEjH4Z6VDf76K8mRUTb12R5vfvLNOwjyYtxWMMccA459+K6y1XUNJ8PiO4DOJCPLcEho05LBcdz0Ge5Fc1q7y2t1FO0GzADGNiT1Pv7frXRWeuySaTHb3TyrOI28lEGCQcYxn2zW0k+S6VyKMVG8iew1p7axuJ0tF+0I5kXksXyuO\\/PYj2FUYvF9ppk6zCzEiTxkHcS2zntnjnB\\/A0+xt\\/tOn\\/6VvjDOfljBwD3UZ+lYepafGdVldvKFqNzPgjJ7dvQ4+lc9JU5NxkY08S2+W+xB4hv7i4CmMFV8oOCX4YnknjGBjtzRo1vdT2weEyjchOxWwGI77QRnngfStm5Fnc2s8W8FY7VUhXqdnBY++DTdFQmVLGOWWVRA53bRiMtkBuxz3\\/KuiNZcuiNIVLvUteCr21+2R6W07Rxzph\\/mOxyh3ZOe\\/GPzrd8eTeHtHsrjUo5XvNRuJPJsYkkBCABRu+mR04zkVzGpWGm6fcrHpk0gMELF2zwxZc5JJ7jPHuBWUto8uq6eXkMsfm795dWAXggZBx1rWMlUSmtje9lZnV6FAl1d6dBrs4SUakog8yPcJU5RtzE4+UFMewPpWprVks9wRp1zFaGC13XJmZU3oZGwu0kZYHAznn6jnA1N4LpbG3OlGV7YpumDZU\\/Mchh9TjHtWx8YrTS7bUEsNPEMVrb2sI8yOHOCAdzAdjknPcVpNJxuzCclG\\/UzrM6nrBuJ5DD5S20sTu1uVWQKMk4BwGHBJ6HNVfCENrL9l0q4RbSYOvmM0uGuA7sePwwOh6e4rY1C7Xw54FuNAmJS5YruO8hSHIYMVIwQRk5zkduM5gk8OadF9kmluZnnMUEkAgZVeNWjONzNgDLcE9sHvQpKSNFuNS3N7ozvAkcEL6i1vFI5DFwq78Hpyu\\/GenIFdjq4TSvDD3O44MCtGepTLAcDPAO09fYiue1eSwk8L6da6Vbq00ayzlobguzOWO7IxtzgADb1HoeKteOLuYeGIYmhlWKeRI4y6cjb\\/D7HjoKduZNMrZpnKaPLc6rcva3TPImcyEFchRkjAOB26j8q1JLrAFzY745YG2QTEAMSOQ\\/oeeaz7K1hu9WuozC7WsajBQBZAw28ZOOP8itXVNLWw8DxXYQl5bhVkiKc7gOB7HHX6VkoamnNdGFol5beILuLTLu7NxcSXCvLO4wFb5vm5OScnkdORXV+LNJSPRLjxFpbS+SXgRiGAIkYAP0PJzwa8\\/8ACWjXEHiW3W7QrM8xjRFJ3I2N27IIHAz1yK9E8UX922jSaLbTCYPfq67FKjCqCBgnjB4\\/KtdEQrsteKbybf8AaZZJLi2k+WGRgDvxwcHH04Pp75rlmnvLuReWljEm0RlAzA9cbuo+gIqWSCeRZJb2djbW5BiQgb2YnlvYHB69MirGmO8ckWUgSJ5STvXDJGcckr8p9cf\\/AFqt0HD3zxlbe5JGsscKm5kkn2ttQHdsj9lGePfnn8KvXflQRJNf75ZbliXCztuUY75Bz1HPNU7G\\/wB93dTBYDZmcsry8NnGSwx24PGfwrIjvJtR0QSyMbsyR5lOGbBJIAJI7A9simoc12waludD4e1CT+y5jDPmzjfy8uwkD5BIQJ1JJbtnvyKzft5uFuAlpaxrL8ktsXUKq5yoCk7jjOfxrnbS8fS7eLzQLdZWaYZGSdrcFB1BCjucdhzTBcXFvdEwlZmlG1gWYE5AOfqMYrojTpmnI1qje\\/tG4FtiBAyralG8jKMnIIzkH0xnPA5qlJZSwRxRm4lnPlb2HJVWwoGfUKXGR09qv7oo1SyvLWRbwqJFHmBWdPXdjaCBwPp3yKrzS6bdJ9oiuJLa3iwypc5Lrtz8iHtkkfXA4qqadmh37lnQFIafUI5ZbSaTc0ieVhRGoG8Aj5gC2c7T6ZrJu9SD6jDHBetx\\/ozTujFUC5YnB5z\\/AJ7Crmg3d7ezzSSNLAlxI8cYU4Ljggn8MnsMisF7VvD98UmhMtiCz74m3\\/vNpC4PTPI71N9TRQ6ljLx6h5umSzTNJJktggvwATtPI6d\\/fjio9Y1KHU1tWa3EEkExQKAq44yQcYJPy9eKNGeCCLR5zKN0Z23CEAYLOOuPmyOeT+eK6bxjoumhV1GFYYZopVIVuA49Tk\\/TjpRcrRPUxrvVQdAuYEuke8ljRHKjaoyyj9BgHrWRpJEmlXdkk4jj2HJYY3qChAB44BXvnua0Z9HjkS8vJGtfswDiKVVbYoIOcDHZuCfyrFudy6bGYpIzOIxGxBIZdxwAOfRvelew7roVEZY7gSRqGiLYYggbiO4PYc\\/yqratJNPJN5qonP3nwWAOeccnnFad7ElmJ0gYGMLhAWGD2H16E\\/jVJo5J1eaFJMorEuiY6DJ4HTGD+VUNMuq0TXixKsixTqcBn4DBSATjtnn14qncQiWdooG89CwUkAqueAevoT+ma0rLTV1GzaeF5FREUzyKgI+8d2On8Knr34zzWZqUT2+lafcRw+VDM0iqwflwDhgR+IoltdhF9BiTMz3EMlylt5CExgKdoYY4HuSOp9KoGN1hRnbhiWxgHj1PNE0wLIViUoowARwWwATU9sIBDhpCMqWypww9QO3P9KjcvYhDS+ZG28OQMLzkKMdvpUl9NL5MUfzMsXyKzDgcdB2\\/xpLOQLOWSCRiR8oznGeufwpWQ+W0sksagvgqPmxzk9fp60dA6leO3uOMRuA\\/A4+9TyitI7TuUwM7WPLfQ+tTDicTTYxsBjGQT6A4B\\/Go0njeP98rEqMfKAM+g\\/zmlZIeo5ExDvjKfcwRwDn29frT4iHmjijmkdSAWCgkFuenPviqbMzsUAfB+6ue1TujQqtuARKrbyduCuPX+dFwNOA3iGPzbnyxnAEgwe36YHfpVKaa3nAjZNjNhTISdo5PIx161Fb+dcXGySdEHUs74A9805Ake5YCGZztCMCSPfPT+dU3dE2sWrWBLW6Yqhng27JH2\\/KhPGc8+vb1qHUWgaeJEk3rnBkDEnGfetG3ngFoYZI4lhXDeWTkk5\\/U+9VriBBBPcSlFcH5BtwV57Af1qnHTQSeuoXCwN9omeNyqRhF\\/eDOex56\\/Sq1ss3lGeyUgAASl8EA4\\/8A19qqAkjzGIA6dOT\\/AJ\\/pUlvKZGeMyFEbLe2f6VF7sq1kaD2xnZEnYxCRDjbjG4c89PyqOF7Y30Uc+GQA7vmABOPXHrVNg00Rw7loRwM8AetRFCyg8AKtDl5Akal0wecoykqvyIUX5jzzUVnAk98Q5wgDbd3X1\\/Omaacyxq6jqMkjPX1GRmttIoU2TeTGh2yBdoPJwcdzjGfXHSlJ6Et2LNjCCqwRAEFgZBngZIxnPf8AHvVq+uTEDYWsfyNlHC8gc+voKqR3McVu8Ru1WZuckHJGfUGkhgkQs3zEyLuIk5UDIyc+h\\/WsWtTJq7uy3bzoPNgUr8mdinAwDnHPSmRajbWs8qzyfKyL0J64qnfXMX2mcgruWMqAFCjr2A\\/+vVZ3jkgCTD5xnc\\/f2\\/lTULlJdyneTi6u3uZCzc9CABimRNukLhRgk4yc9ewpzRpyWJZe3PGa0bGCIwByuXJ+XnORnnHpWqRbditb2jSOrO+fm69NvP8AOt+CJoFUwsq4yoYlSTgHsPwqtOswiMK7VUHDYXvWlai1giiCYcqQSWbp6\\/8A6qUmStSvqN\\/cWsAWNhHK3BQ8nr1\\/zxVTTVNx5ks7ruJAJbv\\/AJzT9QmF9fM5AZFGxCckn8\\/rU93c2scRtoUZmIAYngg9z9e1NIGyzawlYAYyI42JyoblsdakaT5niUKVOOQOPoOKzoC3kxkblByABzmr1u0MQ4U7gOWJ6n1q4om4OFUcsS5OMelNViOlDOHDthi5P3s9vTFMU84PeuumrGMiff8ALzSK\\/wA3ao2OPakVua7YM55I6Pw3LtvEHuK9x8OybrJPpXgWgvi6X617l4UfdYpzniu+lrE4qyszem5WqpxirMh+Q1VJ610RORlK9XKmsZhhzW7dDKmsScbZD9a2Wxn1MTXUyucdKrFfM0KZf9mtDWF3RE4qpbDOlzr7Gs5ouL0PCtfjIu5o9vVutZn2d3CqWd+eh4rqNbhQak+4DAb+tV2jRmAReD7V8piKfvs+ipVPdRltE4UxM\\/Gc5xyPrSC1USjdIQTg7x2HOK0orQ\\/vDLIEVV5J5yao3VrNGPtLxuFzxxjIrm9nY2UrlO8t2t4vlyCygD3FSW2orawSIxG6VcMFUU14pp423ZPXANCWBS2ebaS4HGfSp5S9LamfKAkJJbLMNzLg8e\\/+fWm29u90JXBC4GeR1+n5VsQWQnmQTPGiEgsChAJ\\/u5\\/wq7ENOgupw4D+SpUe\\/bk8elElYHKxyduxSVXXG5emehrWs4Zp7lJZ0VFTDM4IG0c\\/1qoIIfswdkcSE5XHdeeavea0dmYFRGjdcFmBDce3fGaVim7lHYovlUShkHJkKfr64qWRooFVt2TjbjqTkck80NDKhaR42Ea7Q59Mjpj8RUZE1szNgxeYSDkDkD0FFguNjEgijKrjGVABBJPqR260+3tY1ErTzxgovAyDkkdKLkKQyMHVzkr0AAqO2tVuLnykZVAXnJxuPHTNFguV4iVk8zcQB0JWllfzHLEHC8AGtLUbaO3hiIiKSO2QzH5duOBjH6mqVtCn2tI5z+5zgupx+RosO99QhgXyGZ2KPuxtJxwOenWr1+8MdnbrAQcw4JVTyw6\\/XvzUbwLNmNOHZhgMcsBk4BPr09Biq86yhQEB+T5TnHH+c0WFuRwP824LgIOcVPKy3Afe2THyBjgDOD0P09alNpOmjpeeWvlElCx7Nk4\\/Hg9e1RQptZmiIlLgH5hheRzwfQ\\/yp2AFijuJnY4VgB8oOc8etRtZgIcMCy\\/eGRgZ6c1MsTbfOEZXAy5HSrnySReWsi7kXAGMcf8A1\\/eiwm2ZjQIGZlbgEAA9c4qRIliuBHI2Nw6jnn0q9KsG8BEAJHzA84PT09c1BPAFjBEjPg4AYc8980WC5UMSmJRs+cDoOp5pUhj8rcykEHn2+tXhD5UAE0ZXcuVBPJyOCKit4YpVYybhhTjLYyfx\\/lSsO5XhEbLK28gDgAd+39TUDiUsJDvOAOeuB6flUipth3lgATkL61bg2GymLttJOMg8HP8A+qgdw1DZC8d9a3RkDkOP7yP1OfoRUdrcrd6hF\\/aU7JDJIDNMibnUE8tjue9RLgWDM0PcqJMd+OOlRxriJmxngY9uf\\/rVNirnf+F9VvZ10y2uZ4LgQ3WLTcuWQsyDD99hAGPQqMccU\\/x7p+ox+K759PaNC8eHVDhWXClgPQcH8q4rQ7hrS4iu4zE0kcikxODh\\/mBxnsOK9DuLyz1\\/Qhq83mR3rwyrLBEx2LtbA4wTwpH1GawnFxldFqV1Y4+PRNVm0W2nitDHH8zxyFxmQccBfqSfz9KbcavdS6tczTwra3DpslRRwSAAcenIJrq7e6tALy6je5ezLRiFIHZFA2bcZ2nBz1IGSa4XVpWnv5\\/LBbLnkndn1OTg89eRmqV5Np7E31LBIhspZBJIboTDch5G0Dvz2Oam1G7tZreJYIf3z\\/M7qThsD07Hk1BpN3BFq0d3dWrNEJgZooiPmXPKjORzSTxRIY5YXXDJlsDke1U9x7otae0VrqiRzSTwrNCMOoAUkjPI\\/ug9TntnitSymTTb4RiCK8MTMswaTKTfMRxjnpgAj\\/GuanEsiW2zj+Hk9DzThbmK1FwCHbztrxFsEDHBAHPr+lEVrcmyuehPqun386RwWFnG+M+RJKytn2YAfh61yFxpV7MLjUTtTBYsfM3Fe4xjnrTBZa5pyWlxKJ83UCzwZ+fMZOB74zil8z7JLFOsixNIRIUCOCozyD14GP5U7q9wSRY8MSeddi1LtBeICImLcKdwOzBPQ\\/MPxrubCzSSW\\/tFAt7ny1xEB5QBV8hhkD\\/exg4+nNcPrHkyXn2qyCPLH8zGFcZXvuHXP5V03h\\/xHptxb6W2oykX8UuFkkkIABYnqRj0OCcV5GZUajXPT1X5dfu0\\/wAjmr029UW9L0e9s9PmmY7LZJZXjQt8rtGT8rE5AHPTGckEGue1qBoLCK4ltzHlRu+bJYtwMk9SM4xnt3rqrmDR78z+Rrc0kkMO6OFFVd2ZA0jnB5wj4BI5wetZ+tT2Zt0iuke2tXJkikiIBPzEA9ME4FLDymkqj3b2tZ\\/d3KUmkmcH4gWBIIra3eJiNvygfNnHJz3Bz39K6KSHU7DQ9LaFmlSaRpEiRtyyIpVCGAA7jAPTrUU0ekXUMs9ygUo2BIcAkDvx9Pr1p\\/hK+SxJvJIYrmOMrGA43BIxknA9ea9Vpqmmax2LOua49\\/LCr6a4jbIO0N+6CMN4wR1\\/Dow71hx2FuNctzdzots8iCRlGWQEZJ2+2Dn6Gr72X9ra5fSWbs0slwY4SWAzz3BOenPfpyc1eHhXUWtZZZY99w8bMZ5HKZUjbg8HJwQRyuM965pYinQ0k0iXOz1Ow1JZLi+0aytJEmtdMLwrJG5wwIJJyDhgNpBx\\/dFcz47sZrbVNMthMZQ8hMi\\/wl9+NuAT1Az681sfCy11f7WLa5mijiUvMipGHVlXqcrx1Poe5xV3xM2nzeJdENwwicXzm4RQwLDKEEcDk5J98cVyqpyYmKtdW3+8ta6nGxTataaqbdLNRMIY8jA3bRtPJ6jcD6d8Vr5e4s0MsM4DkzIsZUbMc7c8nnknntVfUIraL4i3Lq0iQH90AynDqEw3zdCVxjAz09q6HU9PNlopuJZyjNsEgzzGxQjGRwOHPHtz6DLEuPNGy1du\\/mZTjeWhPf2OlGVZINe09ZZYC1158wwAw5UrjII29s9sjvVT+ydLtPOsrrU49QguCVVLAblckZL9SR0wTwR0rMXwpDqlykczySyqpj3ZByQVGDz0AJ49j0o8NaD9nu57G\\/1C1+wxo6xurbg+JB1bnC8flWNPBSSt7Vv5JP5PfQ25OhU1ewh0fVmWyUtZYLPcAllLBSu35ju+8F6k4OPasHTZbfSruS1uC0guihXnHlSHkMw7gbiMfWuq8XyaRZSRCzP+lI0ZltmOY5lBYseuACQMjFReGzYXejW1qY4buCdjJLA0SlkcDGMleB8o9+c967o154emnJN20v19f60ZjVqeyV5bHL31yggnsbaVBOJ3iuBnKyKCMMB2HH\\/6q2bO9ubHQ7C6ZvJCTlCiASeYpwM8egzyDkcexqZvDVpYs\\/2e1aRvLKs55KsRhSM9h368VVvtH+y+Ghci7k86ORYmh8psR8g7vcEKTkdxW\\/1uhNK73YqeJpz1TNWHVrVtQfTkkllhF2kkTeZ5YVAuCeB3BPr71saBN5FlKyC3eASGZkaYINpILAEcAEgkdOtcjrc+p\\/aLe2vLWF23ubdiPl2537Mn6sMZ7Ur+ILe20aWSK0WNpsxrEi4RVChc49cgn8ac1zpcmtzZSvqixqtzfaXrogtbTdp0kvnJGxZGU7eQCDnowJA646VbtJW\\/tG7NxYoDdR5dR84AywYpn7pyPc8jg1x1rrSxJaMblndZt0gePKqgTaB757\\/StzXJVW1W3tG4+zvMVjO5RjPf+7nj8BWjpu6uVcmlMMy+fIJpLVZBvitlw0MjblRR029eQfy7VeCWxlt79bhJ5Y9koDN9852+meqnqBgH0rnNJ1GSO0uonk8y2vwkUsauPlkx8rcehLe\\/Oa0tP1B7nWZZ44EW2gACpCxUE9B5ncfMAc\\/lnNKdNJX7AnqUdXsG0O7TUbRnUTqS8O8NuBU8d8n19jXWWWhX9nawi7VDPFGocomVQEfKCRjnHfnvVOyvodY11bBixKq7iNg20lSxVecZI49Oea62z1IWfht7SRLmSaaAQz3MsW5GYKoU4zkHHOT146k1x15TlGMWtWLkVRWZw2t2kt19mcSbbb7QvmqiYO08FgD15qp4JWC\\/8YTIlusMcdiyOAcbgGHzcDuMVRutTaz02ErcBZ1lZlwMkbRgHOeOc9PSmeC9RZvFyXFhbi3Mls6SorFtx25J59SBxXTQpyjCz8zDC0\\/ZJJ92euaDby6na\\/aLlPtARyHS3TYSB90t6\\/KAPT86p3EaTTKbS2SO6M26MgqSFU9+eDkDgc8\\/Sug0HUZLC8ZLeOOGCFWMpLYDkYQAg98Lnr3rH1IWdza+fGtnGrHMsySYchjwcdQfp6LWFSNpM9BSXLqU4Lm4g1eO4m0kBBIc7XDF88ZB6\\/KGHUdqd4mtYDqfniZFeIMQQudy4B6d\\/Tn1NVdYglkutMgtriS5aYIE25I+9hs57gDPYdcgVbaG1hvZ5HmdpooSSrtkyeo6c5GTwO9c1acl76MpyaRwHiK1n1HUJkhcsHVVVwPlLf3Qfcdz3FU9IgB1y1tL8PIfLb5C+csVICgk8np6YIrZ1URoWvoGYRgxhfmOVc4yB69f85rAinmv9ZtVhtnjdJsQxIcKCfY9OmT9a7qDlypbKxhDmT8jofE8syQ293aK1tEzKwTHCjcdu4f7pH1qrHaQR3EwvJ4ZXL+W5VvvjGckdBjA59\\/arGvJd3twszQ7LOOMCbnO5lTg49MYrK1PTZNOP72zMKNOAJWY7nyuccnBBJP0xisaMY8vJez19SYwVmiLWfNnka3ttodpdkSrHtKIAQRu9Dj\\/ADmtPTEumjsW80wMECjy05YhMgn1HHeq9ssMdxJFNE801zxAEydrY56c81qxBRdNM9qq+Y2S7yDAA4C9MgdvWr2tG2hVKLViWysrdryZZhmI5GWHIQrjHueD+dXI9H01YbO9hENvtkOxFYlXJ+79DnP5GoUke4mure1VXeIFm424AGcjJP8AnPFXNLuPtllNA7xwr5sUsJwuFYPk5yeBwScdqmtzOLs7WOq0ZKzGtqSTkaI9rHEJHOZRGxLHG4cBsHtjgc+vbnNe1yw1LT5rK8kZZ7cP5RWP5ZCxJ6lgR16V0Gr3c8UKy2EtwkqbozubLR8HPOMEZ7c+3rXA+HtNutX8SWmnXFwFZ5S6Z4ztwT9OB39K68NJSjbqZ1PdZ6B4ytbZ9RsbXy7cEW9vaN+7UKT5WG+bPHPf2qgJtLj0jUtPMUq3rDy47ov8rw+YpCrjpjJGeMg1zuv+HvEWgszyXE8UtxOyxIJchsggnGcdD+tYNs1zJcXc948klx5fy7mIOSQN3PWtXG2guZXR75AHgstK0W50WW0W1EcF5JEQnlPnkgbju6DDd8546ViePNIj0zxHvsSZDD+92SsWj3EYPHbHbpjNei+H77SrzwrDFO08urvGt3me3WGS5hQcAMg+bkfdznjnua8217WdQ1fU3DoV3j5QTkYJ4zk8VaSQJ6DPA1tdSRx6papI7m7dZkidd2G4ON3UHb27GpfFF9ZRx2tnHIkbxXUs65lG4yleN2OAB97PtUVzu0sW9rG7qVZycMMchSOn41zGoCD7NqF5qCMgkYLDJ03ccjd179P8KxUE5c3U25ny2G+EriS\\/8arI9yzxxyNcOwBOSFHHPXrXdfFiwj06ztrdnMlxcqhO1TuEm3I+6M5zgf4Vxvw6eG68qAWckjmbznkWQ5aMsAVx34z+ddt8T5HuvF0X2VnujFcLkIfmPIJHt0AzVzbi0KCUk2cHqFwkl\\/YWsMsjq6BboYLYKgbT7qMkAVLqTBlCtMDsGEAQ7mYHAzk89hxSaIYIpmklk81oZifNC\\/NjHTBAwR1\\/AVn6Wy6nqE4ZEnumQmLJI8khjjgDkgY4rsnFvY8u2vob39n6hNow0W53xrlnwC3GeSQvOc4x\\/nNPS2+y6btsJJHtfLMSwysTvLZGF\\/h6\\/MMdOQSamu9YEFsxgL3FyI2c3AG7aoXGFPfJz0Peq+i6qsCIuRcXEce6BN5QRgrty3bjkEYJqlFJWepK5mct4lu4F1bTrWzkeae2DxHzFwBnp1HPU4P0qjaIywXSB4uIWdPkJPUYHtnsaZ4sdrjWHmlIZhIMBc\\/3R7\\/SrGjTyXGqtFLy8tuqpk8EhuM\\/gCOKW1zoS0RueIb4XFhFdyW3ktBGFbkEO3AGO+PlP44Fc54liu7HXLe1mZnYASEDgYPP+P51dvJXguLrTJ22xKrJCQNwXfhh6fXn+lZtx9u1TWbRy7zXBjjjIZsliOMD8aUr2sgirO5aS4k3xzTyFW3Fs+YVVRjgfXOOah1BXtkkaadzcN5juH6tnAHUc9\\/y+tR6vceZeIJ0QSBVzGoGS5x1A746+9afii1tjFJqVnOUZ1XYh4Ck\\/eAz24\\/Oj0Drqc3YyM8MiM2PM3DcRkA4ByTmul0XV5Gikt9Rnkkt5EDFVmG5TjhjuOPwrmrPCwBj5YKhiCpBJ9c8\\/Wn+cbqcMocp5aptDHPGOATSWxbO3uI45dB+ySXUNpO8\\/wAvkxFtwCtg57ZPv39jWGI4pL64s761YyuN0bg7njABYZPORyCe\\/FQaU8Es0sTedszGTEXyJRuJYY7cA0urLaz6jqbWJl2w3BZBL95ueRx+J7fd96pGdrMZEourIz+U6wW7p55jTqg4JbjGeR71Qu5DaQG2hDKZWIO3rjLdR6kP2NXLO6lHh+4slRfIZ1JfoTjrjjp7e1Yl2jJefN93fgN64OKU3ZJlQWrR0OjajdppdzbAb\\/PVEWOTJVguTzk8DBPPFYE80jpDbOymKJiF5O3k5\\/LmtHVIIodQtrnzSIpoRIvGemQePTK1ZWOO78FXkzRK1xb3ylpifm2uAAvuOKGr6DTS17mNeXZ8v7LFsMQP3tvJ6f8AxI\\/+vRFsEGZomPBG8Yx0wBUcgSGQKo3hOWDEYJpo8xlkAUN9O30qL66l2Gyyh92V2twMAYHFJD8x8ticHoAM5NR1NaKzy7UALEEYI61Kd2PZEtoS9zsnZhjOc9QO\\/frxUckimYMkaqM9McfTpT2gPnlASMLljt6ZHSpbcwKANjY44JGD9apJiFRCYVJV1kORHkkcdT7Ac015JLgLgu7AHgDOc8YGKlkfDlJwoZG5JBYZ+g4\\/Kmbd8zSJIFDZydo4HIzjpk1T7CIpEkt28li5V1BcbSMnGQKlSYeWQzOCVwBnoM5\\/wpfNYQyiVt6sQQAAc8+vbioZhvnzFG8SHB25LcdzmlsG5NZyxQu5MKTkg\\/fHQ\\/TNEi3Fxa+bMwEIbAKgY3E9PypJosMyBV2BuHJA9QM5pVYIxZWQ7GxsA5Pv06ZFDfQBGt3UCMbX3AEbATx60S2j28scijacZZTyVNWNMLbo2jjYnJyxUEZz1H0HOakni83Ji+Zkx5gz3OMd\\/rRZC5tSK3ceS3mvkkcrzyeeenpU9jZQ7gC8jo4wfLHOcjjnHtVI3FxlVCnB+5njAxjitm1kQoqxkoxALonJHHb8vWi4pNopmGS2ZZAjIFABUrk5x1\\/StK0cS2LQNuZwNpD9Bk9fT\\/8AXTLqVlWFWVCV2j7xwMD61WhkeRpYizJlsHaMcjnn1qdyd0XGt7fZCxZd6j5yWXqOuPUdDxQ1wGuZEgRpFZBsP8JxjGM844NVYyrJ9maNiQclwST97oe3T0p2oTWiPE8exn8nDhRjaaVhWGzJhwJ22kg5AHOfciobpohcv5a5jPT8e\\/NW5rpro+ZccMQQijO0HGP6ZqrFGH4cggHL89apIpeYtvG7DcNronXHf\\/Oa39IhY237wbEClfMYdBgnsepAqrptndO7eUjbVHPGRU85nt4PJXZtkGDyWIGO3QVT0Ik76Cp5ao8w2sqnIVuoBz19+lU3M1wGdtyNncTkDPvilVvKideNxYfMAfwFPkIFqI4Q298eY5PJ4PH\\/ANb2pJBsQw7jF80nIJ6dWx\\/TiraW5ezaR8A5GxM8sT3NMhiEUZGGdjwSO1aH2R3hRUcsO\\/t+NWkRKRWtIsQl5QcdcmlZmZiMY5AAHNXntpLfT1cK2ZWCjjqOvf6delVXZmLBDsVfvEgcn6flWsUTzXEXA+Udf5VHvzx1FS3pEcUYVlLMpLbR61SyVU8fjW2xO5aDHH1pc1CjBiM8fjUxK4wOfeumDM5I09HfFwhz0Ne2+DZN1mg6ivCtLbFwnbBr2nwNJm0XPtXpUNYnn17p3O0Y5Wqx61ODlart98iuiJxsjmHy1i3q4kzW3J0NZN8vJNbIh7mPqYzEfpVGy\\/49J19jWjqAzEazLI4SUeq0pIcdjyfxJ8upS\\/Lnnj2rOQ8qVOGxk1q+LExqcuR3rHjgUYffnPb0r5vExftGe9QacEWfkUqZWzkgkY+8c9PyqfWrlZovLGBEPmwB949v5mqTQsy4znAyuPapAhaAEqDzjPrXNytm2m5XtwEYhVIOzPHamXTMu8DOGHSpUhkWZX25we4q9Bbb38wqZO5UHnFS6bZXMkcxO0\\/kp5hdpI0+VRjaox19z\\/Kq8Vvc3bpCvzyMQqg+9dBcxCWaUgN5e3GCc4OD7U\\/w3aut+knlktGc8joaylF3NOdJXMy0s7i3jYMHjKttfJHOOoHHBpBF5jFHjyylyzMwwcDit2dAdRnEpUM3KqecMcVVNtaRTkzsZcNnjoTjtzyMip5WJTvqZMkFxJIsMnmrDJtKlh1GeD\\/9eo7i0LTfvJj8nJI6bh2\\/lVprmU3MDO5IhzgqoyD2+vSpZps2pTbGWcMTnkglv6UrFXZUu4CdOjeMD5xgFj07H+VVktJBLGDKsbMSQ6kknrz+NW7ciQpDdlhFuJVyDgGq8yh71Vj3KinrjB4\\/zmixS7DtQunv5bSB3SURRbAQOeCev4AUpRUt5fOCgsScAcK31q1oFhEs5eZQSUZhk8DH51Hqbq9tJJ5EuwPtjfGVJB\\/\\/AF0CvrZFC2McYd2iztUjJGRnGM8\\/jV2zDRWcNxmCRHZoQmOQRhsnP16+1V7WxuriB2itp3CqNwQHGPU+1O+ySblcptJHC4o2KZX8kzFtqBeTnLcE+gp2FjmaR4UbeCPLUEbPT8Kvme3TTEi8ndIXPznjHH\\/6\\/wBKbFBHckxgYkV8nJxn29qLBcQ3Ut65WeGOB4gqBQuMAdMj1qC7hjhmVkXcSpGAvRuP6Gm+UHvjHsAByoIPAwev866LT49Pt9MZrhCGU4D7cjrjp3\\/OkJuxzqSBZgpwCMrz6f0rRgMcWn3AntY2XgI8knC544x1PNZSvmSaUgDcWPA6d6ltpzIfljJA9Tx+VMbRMItqxsYWTcCck5BPqOPpUYiLK\\/Q8cA+vf6datXMbNcorkBiPlC8AVNfRPFZb229CcggE9eR7cUgMmBR5hjQckbUzg8\\/y7frU0bRy+aAgB+XgAHrnP06ilS0d4fNikDLnG0ryDnj\\/ACKbal47hyjKR5gX0Bwc9KljIpLU75Y\\/M24+dU28H\\/Iqu4Cw7Qdhzzz3\\/wD1VqzuykyKBtVhvIGCVPX+lZ97byCJptrABsYwOBz\\/AIGkncdx+lxIVuIpI87l+Vs4K4NTvYsqiWDzFGOqsc9B\\/iapxpclVHlsEAxkDoP8itnR9QiW2ktLnzN5T9228ke36VMrrVA2Mj+1R6OGiuLgW8TgyRhsruzjcBjjoOueapmGd7pp1VNzDJ2ABTu9R2rqrKy8\\/TZ4spGswChh+ny9z71ny2Uls\\/2cuUVnBwoPPYZHfnP0rJVE3YlyMWWN1JAG1SAWH0Pb8qs7Q6xSIfKeOMYGz5TgDBweDnrVnVYNphFswbdCCHXsfSoEs7xIHlMeUKEAirctLlRdzPne7jhWB5PMizuG5clDnsa6Rbf7VpsVzpzqIre2V7syr1kBdtmB97IP5CsG32XK3Ec2UdULDP15rc+Hup3thJfR2csHmNbllWZQVO0H19M\\/Ssq85QpuUd0E5WVzop9PvPEWm2cdv4buY\\/7KCw+csuJpdwL52k4HAY4B4JFcrYAXOtWsWq3jTRHMYE6MCnO49ASe4+pr1mymvk8Ea7NGOZEgkjngbBBWCJvlK8ZAzn8fevIbwXOmXlytwLd3liE8RlXcMnlWGBgHHYjHJqqL5lqazJ9Rt7QW0TxuIL1TLHJIrk+cFQMp244z06kk81WSPTri0liY+XOqB4MDKPnb8uTjBHzcnPTHvXReLLiy1rwvpWo2doLK8hjW1ugG6PGg2uO\\/KgH\\/APVVWx0cWFnbahIpv7MyvBMIIwy4B5YMDk4ODn271aelrkMhXStRM109qkQe1hZrhPNVwAxx8v5n8ORTp7mLUNGIkuGBtUAKhWIUcAHI4A3HHPPNdb8L10M+JtVVALj92hjdlwIjzxhgDgEDgdqpX+mgQIl3YRRIVlV5YxtQBirRgkAZPyhc9ORSV76k21OEuTHNCd+4nv8ANuJ61J4VuWguZrVZpfKuD5WzK7TuBHKt+WQeKvS6fDd3bpZXMcbkM5hYNuBwMgYBGMZ56YrFe0AL+SjvcDLrIsmAoGOcHr+dVK0lYJHXSppdpORcRmw1FZhCyu+SpPOQB\\/D15JPOOMV0Wl37Wi3mj6jIIQFiMBZxhl\\/iAz97O3j07+\\/LQu+saLLeXHkTXdjH+9iIAkYZ+8ABhsYU9f4W6ithmuNVtbSZ\\/sV9awKsiQ7CFix1QbeTwc4JJJArx8TS9s+Wb9fJ7q3\\/AAe+9zCUVO6Yy88Qx\\/8ACSWw0m6ktLQNtuHH75QkgAL7QDyBweOM45q\\/qo1EeNNMu7rVIpI\\/kZ\\/uhGUZyVJwGUFByMY49awp0sBqpuLEw5dtssEZBXyzyew3A9RxwcUl\\/bJb6+HW+nXCqYrkJhZI3iBBYA5yc4OPQnB6VpCnGKjGK6PdXfmaU9Fyo6DxLeQrNcNc2cLMsn2loj8jFsFPMGQPlHpnJyPStxZm1fwnZCUwESq\\/7\\/BIbyyFDfNyc5H45rF+JX2fVLe11FLA2LT20szSzfvXeTZ80Yzg8s33vY+gqPw3JcxaHbWLwb7JYsq3TBZmznoQf\\/rVMsPaMZLdM15bPQ66zn0ttOM81sfkGDHGcOXIJyOfXvmuV1zSrHUIVmScpMsjZWOcqQD975eQCBkdwa6Tw7bRRLdGK2aeVdsaFiSFHufesTxxbWOk2AuZoJfKumCLIr7XX+8owfrmqUJRm5xbdxtuKbtc8v1u\\/kvtQlSSQz+SBErtw5Cg9SODyTXV\\/Dtf+Je7bt4d2XJP3SMYB9K4\\/UbeC3vp1jSWPDZCSdeeec11nw9knKyLDCbi1SVZLyIDnbzjB7HAbnP+NdeLXNh3Y560faUztWeeQLFLKu5Dlgw4x2596rwuIy0s8qBVfhQ2Cw5HSoPEutWOiai+mtb3TyKuBcEniROgyexyc4z1HvSNJp2p6WksETLC2GRmbD4Jxs9Rjacexr5xQlyqTi+WXU8p4Wajd6B4s0xNU0kTW04EkL+aoVcnPbB7flXE3ulS2ztb3LSCW4kUKAwZCuQAOn3q9B8sWliRCSVOcgtkcckfr\\/nFUbVI9QnWGZJGUsDuDdQD0we1dmDxcqUWvsoqjip0rJ6xOG8TaNZQSWa2c6lTIULK4JIOMNgc9dwxz07VF4uvZotRV7KdhA1qse4JtLr3Jz64z+NesatpOkaoLbTniWF1O5Z4htZDnjn6k9a53V\\/AtpBb7f7SZzGBHC20LuTg8++S35DitsNndGo0ql1Ltbfz0O9Yyny80tDiPCtsslo9w5iRY5cBmxkMR\\/Lj8M1r+G77R9M8RyyX73K2TZhaNFwCM5BbrkZHT2pl\\/wCFbm0szb210ywsdz8Hk4746DpWNcztAqRyoDOhG6QjJLcjoeDyc568V60akaq913NaVenV1g7nUaranStMGu2D2os0n\\/cTQuCxAOQrLjn5sHOQQMivUfDj6dLpC3\\/kKZZsPIq5EMhQbS3zcj6Zx09M152dKmn+GrI5M7jdIkLH7u0ld4we2D9a3fDCarbadJJbXFtNBAyb7MIAHjycYbGQScdRjpzXNiLSjv1OqnKzPMPFbtY6k9ssZIBkI8yP518zI2k45Ixwckdx1q58LHjbxAzPy\\/lELxzk96634j+G4Dqd7suDcSNbRzKQhCqwkRSi7uc\\/vDntz1rmfDGjy6VrTy3UMgTyDJC2CAeeQRxnA64rphJciT3JtZno+kau8t9qS36xjT1laNIiVBZUH3ic5wTtx71j6XD\\/AGlr+oRrbSAw\\/KZR0GCRgH68\\/StxI7PybPX5CnkCzCKCfvp5TEk46EMO46tge2P4SvXutKN2DGL2e7mlmWOPa4TcBjjoTgjv0FceIpq0qi3tYU4rdj\\/EEtgLS2WASyTpKAdkvEW3Dls4wD1rS1zzfsrxOIY5LmPJJU7sYyACOvAx1pNc0+Xw5FYz3LSFrmRwBFCCzuUYIg+Y4OPl461XfSLuPQZdSjd2uo9jyCXgAvncOcZH4cZP1rNUOSC1+8pK17nFeIZPs8sIZJHsiVkZUPOdo5JHH+TWfoER1Px0iQwSeXhsRrwQMHHf1I\\/Kp5ZI9OYWT3HmkSfviDlSAAduTx27e1RaBc6jH4k861cxJdv5bMrbcoeme3cda7KTajby3M0zrr7EGs2wkfMUccQUzBgXA465OT69PujNYvjy4kvZrVbyQSFCSTAcMRgFTjp0\\/ka6uBF0\\/XFlu3El1KrRIGHyt0OB2weAe\\/p61zXjBJ2T7WojiYqU3xqTg8DGcnIOO+K5I017VSe5o6au5F\\/wfYyQyHM0cgVfLLysSyr12\\/7Pf1p+t28FjYpdctJeTeUkchO1GAU9fThv0pbW5i0fRYLq7t3Qpb5kB+UF\\/U885OOvrUums3ja1s3luEgtbXdJIjjh+QO3PGRWsL3u9irpRt1KxSTTdMt3adma+mJ2qRjaARuHPOckc+nvRGHhRkMcRQEErKoCgHkEHpjpxWF4phhstcVGuZhFazAxRD5lUtliR6LyMVc0+3SW3udbnv1mhjX7jnqQo+XJ9OO4rLkcJOUnv5fcjBScZs29cLw2E8pddyKQWHWV2wOvOeqntXn5ile4YrHFBLBJtZ84IXGM\\/wBPqa660nEttPGwkYs7eWV29sAEHqCTxk1uaFoFpp1lBPeK95fXhEm2UkrEOfUnJz+RHtWNXFwwkXzasxxNVJpnK61fazPZ2qXEiTQ2sHlRZGJGwBycnnnAJ61nW2m3MyJdpFDApiKmMhiSCc4PJKgV3fiS2NpMi28u5ypU7snb34x\\/niudhSSaK4V0vYIVdFXZGBvI6ZHXPHJP19a0oYx1Ye0M8VdRVal\\/XyOi8AeLxoPiDStLkSNbOeYwzSXUQL2m9SoKTDGQT\\/eHQ0ePmg0PxK13pt7HdWEpIAV1JXHIz\\/nmuT1mKBlb7coWNlZ0ChGO7J2gnuACep459qglsbi+0uxtJNR3OThXZdygEA43evHrjH512xr81isJiXUXvI7HXJZrvSbbUuWiuXBQgevGOf8AdArB+IkjLpcFq7yjDbPKRkADHnn5cn86NP1Ge1WTTpbhvs8cy+U5IKlsDBbrtAwW98j0rn\\/EMiz6rERfQTxRyAl0ZtrHjp7cit4tM7HVjbc6DwTex+Hdbsp7qzBtILckv5gBaQqSBk8DIIAB7j3roor+C21a+aWaSW7nd5RI6glVALBRn04rzfUtYiu1mtVMrq0wWPgbcZAHoa9J0XSln1OKWMDDxyRPv5IzGBxj61o7J3COuiOE8PXYj0q\\/nnkKSbSQ4UtlgCcfyrR0m21BtAiurCV2uZ7kJLtxyCuO3Oc4Htz0rmImMELWLmALdFVZQ33OnPHAOcf5zXReHdbWz8yyuIflS4ZY2HK9Bnnv0JrpjLU45LsY\\/jG5isPI0uznnUxL5dwrEgIwwdqj0zk59a37mODVfDEGsWQEN1HEwZlIX8z9Qa5fxXF\\/aOrTaow8uGR8ELySQcGp\\/DeryWNqsEgkNg0hCknjHTkds880nfm1Kt7ituO19DNpkGonaXljLEFgSQpAA49Bx2rJ0OV49ZjVmQkjA3Llc89fXk1JrF5CbuUYby4jsQBcZ4IJ6+v\\/ANas9XiSeD7OvLY3EHLZz29KUnqVFaWOg11g9tJeSoqO7KGBYks7A57dsDg9McVa0XSr4sl1Z2qSGO6Rdy4PIIGcN37\\/AIZqj4oS3xIYNxRVjDeYd235OmfXiprbVJtKs7WS0u5YXJbIcjgEDkcdfxoe5P2dDL8R2+oQa9NbTgtcShSX3biykZz\\/AC\\/KpZrhrjTbLDb1WTy2jEmflAzyPxq34svob6SK8S1SCV0QSoWLbyo5YFiSMk96yDcYhjjTd5KbXkAOADjHTv1\\/Wi1it0h8zgSLbFI0DfuwQFwVyCST9fpUVgrEXBdj5hOwYwSTg+n9KgiDbmkSIFChGewJ6nnpV60KpbCaR2MwBEaA4BYnHOevGelLdlbLQWxu4rKQyRwgzoo2yBdybx3IP+evBrf8Ore6gk0Pl\\/a7i+QRLmDzHQBs7k9+CMHmsD5orUqsaZYcIj5bjjJ9B3x3Ar0C51m+j1CC8s9NigisVgmaOJxkhMSEZxnkoSfr0oTs7ETdjgIyiSXFjcLIjKrZQcEt3JHbtx9ay7yZGEEcSkJGg4Y5+Y9fwz2q1qt8bzWZNTEa755TIY+SASenPaqkyuckEMCMYx0AP8qUncuK6stXEwewt13\\/AL0KynHZc5\\/z9Ki+0uLQ2isBEXEjkdW9M\\/nT1RYrfabaNnP8e7OPyOP\\/ANVQQLCeZG2t2GOKGNWHXDxmMQoxCKSw3r1P60i25b54wWQDJJGPqKtwwqtzHIfmTzRyBxtzyCenp7UglcSrJApdV+V1J6g8exxj+VJ+Yr9h0UTxRxmLy9wYFvm+6fx\\/+v8ArVN12XLkSqrJ9056nPbFaNo1o9uYSXguAQ6sijkjPB96piIyMTIGacud5PpjrjFK93YE+5HcTOZJJWxJu+UkqBj8uKZC5CAAr83BBHXmnqjLtjEn7stg\\/Njdg9Rn8KDGkalklDL347Zp67laE+QZIbZ7ZiwOdikfMxx6fhVzUobRLtfsWxmJ+dUPyKRgkjPGMkgfSrIeya1eXy0DALtIOPTnvk\\/4dao2TWnlSB1kVtwZWMe4E5798Y7Z604u5ne+os0Ryqsy+Yu4\\/J8zDOflJzg\\/\\/Xqm8YSTzHY\\/K2MMuRx0z9a2WnK3EdwkMWSB9Tzw2AMZHp17\\/Sq8TSFL2Pe+xsNtQAjt05HX2psFKxUjRWQR\\/Zt25gM7uh\\/lVpLSaEutwvlxHBckZIGcZ296mWE3Uvlx3TMB85M\\/OABjA\\/LH5VbtpLRI2ikgLsBjG4\\/MSc5GPwqRORXtEjCSymEeWjtu2sysVZc8HpUd2lk2phbRpoEO0K+eD6Ej3GKn0+RI4w87RqWYoxbjp0PtRcRRS3EBV\\/OYyHCqTgKOQAKBbMgvreIWoltyBtIX6jrkDrU0LbIA0m5pdwdcj7p3enuKfLIYoGSaLfgERuQQyY70iO5IctuO7qTnjr+HGKAvcluYluJJLd2y27zMsePbmqstmYpWiglX73bIIyMcj0qWYgziNCAxwqk9sdDn0pGEsVy5lLMRhSyMMA84\\/SiwLQq85QnfgqQfmwCBShImJl8o4wNuec81I9vJImfMcnJ2AjggH0\\/KpbdkB\\/fQyCTI2DGRTQ2ysirt+fBG7OOhP4VoadayuC4wE5yD1NMiiH3\\/AOJnzjOa1Yg6xAzJ9nAXcWboR3xVWJbH2lwLSMBw4KgouOmcg\\/1qlfXQ847mJ28jnJJpzlJEaQNhWf5BnmmvarK7qpVhkAYByfYVO4JJasQOZ5sFtz5zwM9B\\/LAqaeEqI2chVf5goPIqukYxhQd3AJ9OcVZkUSOEIEZB+Y+vt7VcUTId8yMZhxGD1q7Y3SIzRsjEHgkHqPSqEwzIIVQMo49Px+tT20aRf6wgNkgZ54rRIyeu5cuJbiSDC4ZI3+UBsYz\\/AEqK7fd9\\/jdHtIQcCl4e13cqQvG0fzqpC+E5GWJATPO45\\/8ArVa0EkQMpIG1SGzzk8YpMhGKg809hiUKwAPT61E4Aw3Q960SKuCtteplYkZPTtVdmHlZHJzUkb7l9K3pkS2NHTj+9U17B4ClzbqK8e005cZr1fwA\\/wAiivUw+x52IZ6RCcqDUMn36ktz8gpkw+bNdMdzibI26VnXy8GtIiqV6uVNaxM2zBvR+7NYsTFZJB6it67HymsGRNszHpVtBc878VxA37scck4rHtrZXkG8HANdfrtkZbk5HeoLbTcDlRjtXl1sNzTbPSpV+WFjDFplsqDjtVqOyIQKAa3YrADggdc1cS1TbtwKzWFSKeIZy0lmQucdabJb\\/uVRUO4d+grqJ7NNuPaqctqSNpPA7VM8MVHEM5aS1KyKWBGF\\/OrkKR2keY93Pvya07i03fM3PGPoKjazBALdvaud4axr7ZPcwZLVmnaZ1O1+9Ry27OAq7iQMV0EtuMYbjNRrAiqTsBJHX0rF4c1jXOeisUEigrxkZoubJXuHaKLCDpj+dbhtwWLKKmmtE2gxY3E8kVm8OX7axzckLlFi2jhSBkZxmq0tozXJfHzEgcGurltI\\/swAwHjxjjlj9apva4xtIyfQdKh0GVGsZFouSTFEFCxMDz0+7zWcLaSSNB82xOQvXk9\\/5V0BtHQN5ZALDB9aWCz7GbyznsOOnpWbpO5op21KGjG4gvC5Pkx4BKoOCAc8+tT6+0N1cJLCfLK5LZPUk9quTaZ8pMV8pLfez1NUpbSfnMu\\/HI9OKTptKwuZN3M+JfIleJYfMYn5fl3ZH+RVnTPssMXnD7Ok+5SFkDHoeg7c+9S28h85Y5V2EnGT05x\\/hTm0+3ntp3B+fzcDHTFRylc\\/RmVehkdF2x7nbO7IJHXj6Ubo7iRIriZhb5yyr0GPX3OKvwWqzMgcLL8+35uOBgdfTmoNWtIre7KW52DcFcKeD\\/nmpcS1NPQqalZQ+aZIDmL7oCjHA702JfIkjmh4K5GRj+v9aJ7W7kUeYhCADbj07Guhh0COewdlu8sVBYMuAM9s01BsHJIzdQvI7pYDtylpgIGTLOCcnLDt6Dtmrca6DN4fmmubyf7cUIjgUZQH69gOtZFwrQhVUHyzIQCp9h+lMtnAkKcIMMQ7Hj8ahruO2mg3a0UQ2SbsL1UH071BbWbSSFY2CBSC7MPStlbWGW0WSN0jTGHkL8AkdsjHr3pkttC1iJIrhvOORtVdqkY559eKTiPmJRZRW+jW8hEctxNJIRuGTtQgZPbnJ\\/Kst\\/KaRUjA8s4dgT\\/n3rVtGtuT\\/aFxgwYUc5z\\/AHGIHXjp3z1qjNaMLJgWcTKQm1xgKMkkH0OSaVriTsV7l38thzt64HAqkEDTeZuZztGfftjp6VfsoWn1ERB9rMuznJU\\/41ZkRYpBC4jDKNxYcA8ZqS7lfw7reo6fdrbtMfs5YKxK7tgPGR3yBXRa20QvILyAxPEHTO6Memfy5PTH6VzUpit5Iy0ecSbnHQEYq+sYW0eGO4RUcCTZIMnHtjp1H5GsJ01zcyJkk2QapcySyStGBhJTGRjjOOfz5qfQ9Vkt0a3k2yRSA5Vh3xj+lYySzWyzeZCzwyNktnGCPSgSrKzNb7sr8zDaflHfNOVO65WWlY2t1i18BtRFYFD7AjH86paYsdteLKkmzHBwQRjvnPaqbsCwZcnI59KijkaOdmDYZT35zQodCnZ6Hovhfx4NA8Oa3oLweZ\\/aBAjIYgIOSSV6HI4yDngVzHiXULK6S1nsmjQJH5TqxBZtpyCV7jBA\\/wCA+9c69xMJ1LnOOBRuiKbpBnnH4VoopO4X0sWzfQx3zZjWaDBTIXbk4xuxnrzXsvg62t5PBdwbSFTbtJOiAknbuRSuM+7AV4qkMLArlQ2cg5619F\\/CbT1i8N2EczYge3S9ZT\\/EzBlwD2+4PzrGs7JMIp3R5N8Qbmzt9cg1rToLi0a6BkmjbCswbnqCeuar2+utqOlq7ZnFr5jvE6DJGBjle2WJ5H8A6Vv\\/ABm8P3MWpJqMdvEtlJGFQIOhUdPX\\/wDXXndg0sReG2YyGUlJI9pzjgkA44+o960pNSgrFTXKzttP04QLBereWNsbwmMyyyptCEspwD1B29R2\\/XH1rQZ7LUIIzJE9vE6KxhfIYsTnaSSM4U+1AuL15LC2a3WVJGE0CXKnLHJ2qSMAjB\\/DJ57VBrgis4W0zzknlkaKSJoC3loQvQbj7nnkc8YxSUoqdu5ipRctOoaJdi71NdN+3fY7ec+W0khyY8cDGMc44PUYPNXdB+1aPf21pJvEFw4zGcASqdwDg4JHAx78+9cytxJZ3XnAbZlO4fIMg5zyOh\\/Cr9\\/d3ur775XZDK7LtBOyIH+AZ6D5uB2zVygpXT2Zdkd5b+EtM1q\\/mSCWaOWSXa0QZSY2DHGcnPblgOg6c1lww3fhvU7jTt0c8UcYcuRny4ixBCkHI5JOPf0PPP6P4jl0rUFuVmnRtnlzxknMnzdc+3v1xivTEW3u7iC4NxcPdOgiG2PdlWB4B4yOOnHNeZ7GvSqPmlzQtoutzGEZxdrkdpq0B06aE3dtdGO1YHeMOwfaHXJAGQc5yGPTj71c5Zb7HGieULrNwnlTuMYGfu8MMkZHHsceg6DVNAtbuVrlDMI5XIh+zxsGY7hgEjGPlHdcZAHOM1l+KPC1zHLGLJpJJL6QRzkqpZudxbOPvcH3z3p0505y5P60NlVbsmeq+EolttMito0dormAE7sZ7nnp0J\\/HFcv4+0hxYIjQebbxhmVM8MQ2Tj+Vee6DrWvWXlJe3108W3HlrIUkQZ\\/Ucjvxmu6nurZNFur221m7la1gaRrKSUSZYr6sMge3bpXQqbgzXmUlyo8e8TXKz6zdXCKQGkPy45HbFaXgi\\/e01iJPN2xXJ8uRQxX5c9c9uhGRzz374EuZMyuxLbvn3H9a6jw3YPFZx38cY8+2Idw0ZwqscKTj7wO4Dtx9DWldQjR5Xtsc8rRjY628trW6tZbq5s1nWKPAmWQo7YxnnPzDOOP9pjUng6yil8KiOLAlhDCVNv3Rww6855z+dauk65bzaRbaVdaeIlZmW63Q8wEqSH5GCvXGAccZNc7FcPpWq3UVvcpCrxI8eMBJNwG0NnpwuO3XjHQ\\/N03UmpUWmrO66rT\\/AIc5kr+4zTVsaaLcYCBSrgADnnPP51VikezuVMESbETBkaRAF9fp35P+NLf6T4mstBn1JYc73xEIlZmHIzkdCMN972qhE8KaDc38k06XcqmNYXtULEc5A3Zxn2HrSpxTTcWpJu2muvn6HLHDPm97Y1dSkkkgkmsXIP8AC5kJDkHjke5FVvC+tLqls9veszrCoSRs5ycnGc\\/Q1kT6nANPj0428kcawh3lwqghlGeRnPzA+1ZXgicW3iBoio8icbQHbG7J3Lz3J6fjXXTwbVGbktVt6DeF\\/dyj21R3P2cTK8pUpbYKop7\\/AImsnW\\/BtnqSq1kkUU7YzIMkMf8AHOOfrXRTu8sTLLGyKuABjAI\\/D\\/PNZtteXdmYLyK0e7smjff5XLIQ3LEdhwT+Neaq9dPmpSs19z8jlw1KcZNw0KngK7ubPxNdaFqbh0jti9sUXOTnGPcEk+tdX8N4JodRu793HlyRqsUUuXykj4DIB2GzJzj+H3riNVm086zp+qwP5yqTsnIboQSFx65b04wa7+NL6JrS6TT\\/ACLYbQt1DJuj2lj8uB1AOPX9TXufWoOjF1NJP5a+Xme5Rm5RTZe+I50u08Oag0k6tHbyNHHg\\/vJE4OMnpyARn06Zrzmz1lV0qWLVfP8ALZG2O\\/QR8lQGzyeR+dbfixrG50rVru1826ZIi7hlwreXICHQ9BwxyOp46Vm+HYln0aC4uIY2iki2QCRNw64JA91x+VdNKOnO1\\/wDoqO7uRaJqMk3gqK0NvvnWFj+8yg8pZQckA8k7xwMDrwa6D4S6RZvpNvM7IkZDs7tnG0sxBz2GQPz75rlvErxW0tioieEXFx5kpER3bSQfLXHXHyjH1r1LQ7fTtJuVVXhawWUpDuYr94HJJ4wOSaK0lUivX8iKdpNHOa5p0mtePVSaaaZNGh81EeMJ5zqwyc9Dj6DNbniz7Fql7ZQ3MTRCUMJoJPlDoF2kjsSC2QOe9J4XnlbXNSlaJot2eUUeXtD5PHVuoGRXP6\\/Dd6n43MkM222hQK5aRlVRlewPOSACOx60fF5GrsjhdR0crLdRNcwyh5xFEhw292XK8nBH3euKisYbePW4Ps13FDd4JwwBjYjkg8nj73XnpXQ3+oW1pd\\/aIXL2ltqGxyTjYixBRgfU5\\/OotAtbS60hZGihN0Z\\/wByZuAAzAjPOSB1PFaNWV2ZOKvoak9mt3dSW+qwPDLahvLaGUZJ5yM\\/QcZ6A1T1OOERC0gyxQfN5jA7OpP15zyfWtO9SR7ZbiRJPPl2uJCGH7s5B65wScdMis0JNPquniUMJp2dyxyoOGPXHXGVPvmuJw5btvRFaRi7jfEOkyXmgj7YVkadNkY4ym3PzH8c+nfNYvhJIdL1Wyktn2KkT+YXB\\/eAg+nvt56deuK6TxLqETybOBt52M\\/cEk9PX\\/PWuc8Nag8moortFLbhZHlGzdtIxgcEdAcjmssFiKlRSb26HJRruc2+g\\/U7Sx1JjqMs\\/mOgaRguOi4AU475Y9KzPDtk2oWkZmcQ27CQLGSCoBHHGeoPPNJ4rvFhk+0acRNb3B3P5aFQSe5B6dhgHtUeiG4srpNScieAjZHKHwoIGACMdAB7V3exnJP3t\\/6sOVOTk9dzTgi+y+IIbbT5\\/LQwDqu4kHJGN3GOSTivQ47uxureze5325aIqm0fNhQAPbtn3rifhw0V9fXl5IyiaNNsPy5A6dsdBn1rpJZZdMDXW+OYyIyIioAidc4XoCR6fSvOx+FjWqRg9H+ejHUoxlbm7lfV3hmv7WaQFEKne2QQMdADjGc5\\/TNZSwCaBrlLaG7tyzEkvtBG7n5uh+YVqSz28WkrMxlQxncpYckNjJ5HOKs+CbIXktwXmM9rGGaOESbVRAQSzcEYJBHSiMY0aUu0XY7aHIly2MC3EZji8yDy1eQ5+V8xsSApHHKnB9ue1TXcV0YF3SuJYd8s+7jqMNgZ9Dx9PrXQardqJ\\/MhtYkYrsfcXZQNp2kBQWA6H1qlNZjU2FiGj86RAJkXAzgcNux0xxTp1U48zVi\\/q9Nxlyre\\/wCJw8ciw2QcDzrqUeY0jxlju\\/DPTB44H1qhDYxSXEnmxGRlO6MTDy96456jBwSOMdq7F\\/DMds3nTT7ZEUlIXPyDAzg5+v51zl5E8si4leVY5SEQfxHk5x2x0zXVSxEJt8jPn5y5G4p6mFdW1pYvbOd3mq6AxuNvfJPr6\\/pXpWiazFa63becUaIh3bLYORggfp+tcZqdtcyCcS+Qdp3RTPtTrgBcduAfy7VmX0N4RHfXd5AAzEBYySeAQcYGPUV2xnzRs2deFxS5feeo3xfayW7xbZI+JCmI2yccYPXpnOKraVJczWszLG8i85ZUJK54zxUEbzTubVH4D5GRgdeuK3\\/DAuBqN9YRsIrQIUO5eC31\\/M123UdTSTUY2ZH5EkcVvHqB8qG4ZlRn5GNrLvJ5OcnOO2Kg8OI5sJ4m8p4QyZVu59vXrW\\/41eGXw\\/p9vC4a4tWYtx1zk9u3tWFou9NBuo7aRgCgeRgOeJOw65OByO1WnzGafNC6MTxECurTQ7VVUbChegHX+tR2apHewyFnaMHhgMZI7CrHiVmk1N5JVUMflwoKjgD1p1gieUszOilV2geXnv1JPeoUfesbp+6iz9sicXcU0W7zZRwzEnCjjgHryevqauz2s0a2ryLDMXQOsYkIxxyWA6fQe9YMUi3U+ZF2gZZ3PT9BxWwANkeobx5nmqHRznem3PU+oz+Yq4siSsVNWKRar5Y4kIywUHgEZGM\\/z96yxJLITAjEBmzirt2yTXKuymJo1RclvTg9P6elU7UlLvzVGApJGRx+NRK5pHYnm\\/flbaBdhA+Ys+S5z2A\\/lipJ41gto\\/tErNMoHlRjpjJzn05prqDdiNhEpZgSxHy4PPOf5fnTGYo0kQJkCcoQDjH0P1\\/WgBFnaO\\/BjZhnA+YdB1rvvEusafqWm2sQsjDe29n5LTGTaJQP9njnB65PTpXAQxqbqN3kJ+cDB4Pb8KuXU3nTylFfy5JAPMkY+2c9B\\/n8nHQUldlGCKSSYYLBQ2QRyB9KJljikdPnCq21ux68\\/wAquWaReUw+cy4whjPcc9Pfnn8eaocIQWIA3DKkHik1ZDJHuJI4zCm4qwyM8HlfQexP5062j2+U0e3e46SDIzS2ima4OCT8u53cgEjv1NLE8cIVMK7A9l689KT1E30HkobpGtlDHP3W5U8\\/Xp1rShsElg8\\/yhIVwWKEgx\\/Ng9eOOPWs2eeV2VgUL7sRhVA24A6D\\/Pen290\\/lSoCWkcHIK5yPqeaGS0ybyRFI4EqMM\\/MMenO0E8\\/571Bco7380sMRaMgE8dsVI0lxLA7NHGdrhiVXk54x\\/8AWqRAqXBWfzYjFD8iHnJA7kUluF2tTOEErlljQsVOdoOSKsW6yvp0mBuETYHcLu9se1XLGH7TJOY1dnx5h8o847k9\\/wABS2VtGkNxBO7BwN2BhlcjOBnt196YOaK1k0sLXNukieWYsj5sjORgj35qtau8eoROwaRNwzgZ6+mfxqzdRfZyWiDYaIEkrxgkdM0y2tcxR3Kh\\/lcAgKSpIPOTniiw7q1y7aETPMkyv8kzbcthucd\\/wq0Y0t4hJAjoGJLjafl5\\/pToVWO6+0Ei3SQbkA4O44Bxk9Oo61G1zfSyywRyA+Y2SDhSB6Z7cYoMndkaQM+o5eMKGbYGduM9M59P8KcYGiaVghE6uyxleuc+p7dqfbG6nYw3MskyIGMSctk\\/h0Oef8adcafcRWcDLkSbDI4D4ZAT1P14p2E5JOzZDb4lRPNX91uO47clc4yPzqWaK2jktvKnbyhIQM4Bx0ycVYsopjHblVRUcZABBOScHPpznrVLyJEkeJl3qG4UDkkdaBqSZPEgkLho5GeRD8gz0yMdO3FPS1mS4RfLmghI3KZjjK\\/1zUZ1OS1uYX8oKoUBlPfBzWjqmqG\\/EchAywChf7oAx+vH5UaEvmv5EMVus00q3NzHG5Xb0PQE9D3OcUjyWv2o7GQBcbmIJHHOAB9P1qCGC4nuRtBDbTwBkjpTJrSWJ2Doyhjj6mmmO3mLIWlyyKoB43sMY5zxTYTwVlUsN2QOnNWCAsAVZAAcjb+PWoAjYz1JbAwMcVTQJqxasIWur\\/dIyswYHG7GfpV3VpfOfyd+9EIG7PU+voe9Z0e7zuV2jGRj+dTqwKHJqugut2Nt9kE5DLuB5APrUM7SNcs0YCADkZ6inXDn5enAqWzRWDSOCF6ZqYxKcrIQ3Ef2cI4xtGD6nmpp5Y0aN0bcw5xjGM1Qkcm4JEYPzEgZ7UrXCsxQrgE5\\/GtFdMhrQteY3nEcnJywI5p77nmJLcAZ5PSobWUKS8ZG+oTKXkOQAMdBVk21NB7lxb4jAUAHO0Y9s\\/WqiPlI5A6jYeB3J9aTznVNu0cgjp61AAODnmqtcasWmkDOpZsnrUd0wE77TuXJwaiyFYnnOKijkbGSM57GtI7WE0TLjcAcgVPwHI6DNVEzkY5zVpSWkGeuK2poiTNLT8iQV6j4DfoK8zsE+ZTjvXpHgcFZFHSvVoLQ86vqj0+zOYhT5lOelR6eMxirTxkjpxW\\/U4WVdtV7mPKnir\\/lkVDJGcHitYmbObuo+WrJuIPmzXS3kHzHisyeHJwBzWxCfQ5q6sQ77iKjWxwOgroWt8HkVG8WO2KXKi1IxPsYHOKY1uFHStaZDVSVTnpUuCK5mjPePgjiq0kYNX5FPTFVpFrNwRoplGWMYPT8qrvGMYJ4q\\/IvFQMvoKylTNVMpPGhPIzTGRMZxmrMin0qB1NYSpmimREqoIC4B61GZMZwAKkdSaidD6Vzyps3jMYzg8EZqMkYxgU8r6ijbxXPKmzVTRA2OygVGw\\/2RVkpTCgzjNYypGimQHA6LUbnttqwUFRun1\\/Ks3BlqSKzrE\\/DxgjtQqRBuPlyAOlSEYPIpjAY7VDVi7ixIscyzQ+XuUEYIBHIxyDVC8tbmWWSXC75DyQBx9PQVZY4P196jd8cAn86iRUbjGWcWUsDQtukxhs\\/dHf86zzaXYXAkkBHA5q+ZZAPvn86QXLr0b8Kh2LTaKN4LoW0cbof3cm75hyTx1P4Cqs0kbjDqyElucdu1bX2xyCG2sPTFRu1rJ\\/rIAD3xUSSZSl5GSsG23jeSf8AclTtA78\\/45\\/Krt+VisFWGBiX+8zZKgkD8Kc9vaE\\/LjAHQiobizaVVQzh0XomeBUciK5rlPTbu4s7ppOdrHPyn5d2f8ams9au1tblPMfcyqdq5+Yq+efwJ\\/HFT\\/Ybpbd0i2bDggHNVtKW3gvyt63lHBUkjI54z\\/8AWpcrTK5kybS5XbV4GmXBwRjpxg4\\/HvU06Q3Nze3LHKedlcf3d5HT04quksNrN9qtrliYgVDjKnkEZ\\/WnqYLfT7mIyb2R9sZIwSOufbNZyVhoZbSW4ErzO26WJvKJTPPI\\/wA\\/\\/WrR0+BGtolugFidgjgvnnadp5HAzVGGCaTQo7ncMW7EAjrzyR61L9kSKG2kDP5kmCM\\/Ug\\/qKhx5loTN6CapZxrFNHgx5f5EAOAB1P8A+usS402WBTMqSRoygq2Tgjnv+B\\/I1tasxe9NtHKqlVO\\/5uSec9aqQNHEs9tdy3cjRI0KFJB5a8nHUHIOT0x196uKstRxbaKKpcJALm5jIhd9qSHHDADg\\/hiq1zMuRMhAJIwuRn6+1a2vTpJizSCIKzKxfJyDgjj2\\/wAKox2iyx7PkHfJNSlfUtN9SiW3KpJ\\/Wm84x1z0FTTWbJHJJGysivs45\\/z\\/APWojBEoz06885BpjCJvnTI7Yr6F+Hd403hKzhSY4+yqnA5G1jn\\/ANDA\\/CvBQv72L59yE5UZBOATnPcV7F8Lb62tLGxNzeWkNsfNtZvNbBUlnkUnsMiPArKqtCkcXr2o+IdS1qXQRfTTZuGijRzwCTj14HH6Vj28V5pd5d2Uv+hylTHulUNu6Yyew6c9P1qTV7uRPE76rp42zfa2miBAODvyMjvS6zqmo6pJCLuE+c0hx1IDFm4U5yB7f4CtEtLIUlfQink1Ka323pkuA7KoULzuzlfk9WUAAjgg9zTtSU6pr97LBaXMMMReYRPBh48kbt2O278v0pILu2htyyxNHcwT8SM3OCM9cHBBUYPufrT7K\\/eCO+libY9ygicK2TsJB3E46fLz\\/wDXqYxs9EZRVtijJC0iDcATuPJFV7TVL7T7e60+1lIt7hf3qLgbgcZB9elbF9tisGkThUUHB79KxrG1nnQzhMspzwOT24\\/Wmmash1BYwHdPMZUcqhcY4\\/8A116rcanpsPh2E2w3yiNJEKk7jtQAqpHTHJ\\/+tXn\\/AIlYJpViAf8AWqX2g8cADp9QTXefDvw+2oeDrO4Rh5jzSKFLdV4H49CO3anJK2pLL1prtlHoEtrJcR4C7hHcSbmUn76jPJO4HHsc9qv6LIXsIp0VbqBJgVMTDAZsgkngZznnp6156\\/iEWuvSDVLN7WDDJGUTcV+Y8kHr36GrXgzxLbafdz+bqc9vp0jbWgy5Djn94px8pzyM9KzVKKu0gSszobOCKTxDcWi21xl0ZZII2Ubhux7hj7D2x1q5e6lpi+C\\/EzvbkXDwiI4QdhtUg4H8Wc4rk4\\/HMukM0llBFcvHIZEudhwzN83zDPTk8dverviC7iu\\/BiDeIWvYfMWJlLHhiRhgOnGOfX8alU3dNhonc85lWU2okI3LJgHkE56\\/Xv1rc0bV2sYoYwgvYJFdPlwJUyMYJ5wOpweD1x3qv4e09rwSwZMU1vKjNMhLYUnk8dSMbhjng1pabZx\\/aJpry1UweY6pMg8tJlxsyB0PJ5wCRk8cVdSMZ+7IUrM6ieQLFHc\\/Z7sfbEMJUkyGOTOTgNjdxkA\\/XnvWn4XtLXW9Enl1C0EcMbBneSTIbDsxGw4JA4Hf6VgWuo3cGoWenX8wjisboJ5HL5IyVk+9yoPHBGQcD27DSb2yOqXcF\\/dxNa3FmZfPkjwoVjtYqFX5idoIzgkAnqa8LFUqlGle2qd9LvS9tPOxCg7DrW8+zwi8+z+bGoJS7tBxJGfmBYHADAFe56DvXM67daXKpeSS5fzdsqCZXZhjDDkHoST2xjjirOvy65cQWQs47S3jiR7VvJSMrKQhIdV24AKAfN\\/ePasvQ20q6s7wRJiWEpFukYI2eP4eOM9cdD7ZNLC4aLl7Tr5O\\/Xr\\/AMAhS5nZGBazRz+H9RtjBLJdwqriYtjau\\/hQOcjDH04qLwcI5vE9vFdlVO0GPYQAXVeM\\/lXYaXa2d35upm1xcNHLbHGAGYgbSRntu69gBVXStM061jtrm8DFmYvaMVJzsDDYcEDllzjr9ea9GvV5Kco63f6r\\/gFNuzTNfUtTjjiMMqNDcwsYztXBAwAeO\\/APTPr0rPv77VYfD11p+lusttczNHLOQRtyflU8AZIB4PJzXYavBp+t6Nba7YgGWOESTbAr7wAA68fmeB15xWX4Ve3Twne2aja803nxxMglCgnAAPAxhh+dfP06sXTi+TVSSafR33+W6M4U1DU4+5v7hdeEMUnnXMaCVPLQbTKGXJwB9fSu3Qza\\/dm6t2eW0jZUlxP8zH5VBAPOCfT0PSvP9L8p2Z5LhYXji\\/0u4dhvj+bhF555I4XJxXpfw9MX2KxNjaxXLxs63CI2z5A\\/3we+ODjvXvypQ2tsdVOKTsYHj15tK0GfTrAytbZKLuQkAEglfxzj6io9IlhtvDtiLS9klk8zEaLIoCZORu7Dg9+ldL8ZrPPh93tQxDEpEeCwPm8E46Y2ke+a810q2v4dJ+wp91j5jlRwBuwST3\\/\\/AF1pSS5N+ppJWZt6qts\\/iTTZrOYskzwycDLLvGCN2cDPAPNejNZPa+H5DaQAb5B5HnHJJ3DH0yefxri9ISGwecwTwpNaeXGsko4l3buOvHKgfSu0vtUlm8CRTX9q6zIilzCNqqwP8JJznp705R0QqcbNlzwbbz2C+eq7Ee1LSMjF038PgZ4HU9OuK5vWLk6bp9\\/fkSL8xZ1AJ4LEZIz079j0rvfBk0N14RbyIJoHS4MUqy43b8hSeD0wOMnpXJ\\/FC5SLSbuF0ieRyQEc7RtAOcnvxxjPUik43mkaWurnnWqB7rSNOS4iQSzs8kweMBkyTtbnrwBUPhWK9VNRhu5SILTCqN\\/zfxEFTn7uCOOlWLSO4XQ7VjepdSYDxyDLKh+bdjjPAGAPw5rI0vUbqHUbYvZmCM7Y1kRWCugYAsSc8bSBkYrVXvboZS3O6ubu7u3sJbdpWhjUmcSuOJMcgheg\\/X3rn\\/Es15LfWrKQ1xEsm1LRiUC4yPlB46DqcH3rQudThFlE0TRmGYltrEDcMYbvjv79veufttV+wa9Jc2cgSQW4CQlSytgENkjuATgj3rFQfM+wSlfQoreC6H2u5cuXlXzA74IGSOFA56N3FXvA9ncRavfXC20bWqrKpjUgZyAAcZ9DnGa0LywtE0yYyvGu2cSopJBdlAb7pGMcEcnPI461R8MX5XUhAGjjadJTmL5sglh06dVUfnQkkmoozSSlYxvGDRHyFaNbZDBnYDzIT0J57DHH0616R4w8KaLpXw30RbKeRr28Qu28oSVPzdAMjkn865r4lWzf8IzbCWNPLjdUjkdFDj5RkZH1xn2\\/K5pV\\/Fq3g94ZI4wbMSiWSLLy4UDac47bgOP6Yq4v3PdLSs2UvBLDRNMvphA0c092BE45EcXzZz+KYqW\\/u\\/ssyabbSxzlFEuWyctIASM9c8YqDSYbZNJJiljJQkZLEyKcZGfTg\\/nn8IfDds2o3TTzM4dJ0CtHgF16AEd+OeafutqTHF3iT+IdSnuLq0gWIJ58bBFVgBkDBJz3\\/wA+1dn4b0+bQbRtKubuV5\\/LLeXGSVQM4OMDHfP4V59aTG38V6ZNdRFrSGQq+ZSjMm75jkHOTk9K9V1\\/TZLDVIJotRtZFdA0MJb53GenocgE5x2NefmdObp8tPbdk1YucW10MbWdOvv7OncPGJghaWOXBJPHKntwP1rM8FW9zrGqXt7c74TCweWNQuTjjZ06Eluh7VLrOpzRSzRqjBuAflx2I5NaPg9LmHSZr29lkQ3RHkbUAIjGR1HY9BXlwrVIYaSfXY4YYypGm4voS+Io7do5VCSeYqkF1I4bqAB7Y\\/Nh1ritRtrab920hgYyFhERgkLzztx611utTxR4VZXhdvnYgdWHOOnXr+dY0FuL24864t5VhTa6MAwDNz68k9BU4KUoRuzzpTbdznLSwhv7wW6wBY7U\\/OVj3eZwPXHpWxZ+CLdzOy2ziOUL8rou0H\\/Zb69RiussNNM1uJGbAyTngEE9P8avXtzHBbpaWqkBRl27MeM9iO5rrqY2ptDQIzl0eh4zGph8y7fYLeR8xb5AoY8ckDnAwM+uTVO2\\/tBnGo26+b5mZGOThNpxn+dVddugtlbRPG3msNxUucKPQD061r2c6QeGobZ0BbYGKgdCT6kdTmvqNtEehaUYrS93+BT8U+b9kW4y4Bbyx8oUAADp+dZOifaCdsEZOSN7t91Rz+VXtXuJp9BhE775DJyoOTg85PvgCqV3bNpwt9zSAyJlyAV4yeP0zVqSudFPSPKyxqv+kayGkhyy5EgONpYDB7\\/pmqepSGWHzFRFUtwq9B14+nH86I7kvJBBEyxgRsru3AOc5yadpdtLd38MEbCTzDuySASozwM+2aqUlZsrSKu+gum2c0ySOtqskca\\/OQcYz3J6cf0rU1G5tJrBdKtWDjzdwdsDLD19B6Y9KvS3Pk+EY4kjYvds+D5IxgE5BbqcDB\\/\\/AFVyqqzSRj7hZgEPr9Px6msoy5tfMzhJ1G2+jLRWW2gWSZiS27avJ68Yx+JqrcXLSkK+0Atn7uAufYfWpJJJPs6xzOu4SHGDyMgHsaQWzeUkxXIZ2UnkdAD+PH9K0fkbLzHwSRQMS8CzxbyAcHJPt0wcZppMMz5ZZcsSzch2bPuf89aZdSSMUlQBNwPQBAc56AdqZAY1gOJmWU8BVXquPXP4YpXGl1JFDqI32qVV9vTCg47+\\/rWhcXUkxkjQsYQhVSzEqvAzz6np+NVtNhEyTR+YI0iO\\/LNgHjGB\\/tH+lAkURyNJtYA5VRwSx7fTgUyXqyDMfmNIzbWVQUJPJOevtxVeEK5G8AAdSB\\/Tv2qSS2mkiknUM0UKruYkfLk8frmogSuydhkbsAY4OOualvUpE9uC5kjL7QBxk43e1OFrttjM+1EEgXf3bOckD2\\/wp1rJvlMG4RuVJEjN3x0z\\/Kr0OlPOjT3EruJBksoLHqPm98k0ESly7lW0t1kWEhgp5bphsDNFlaEYDjZ8wGXBUc9CW7VLZW4gnaOaQbo+2efcVdlNot1DDC+9VyTkc4I4GfzosQ562RUtJITL5LLLsCAKvAO8nj6jmtHWdPmguIxdrsYwhmXGTjgZ69z+tUZLQrfpJGGcKd5VuDgH1\\/Sr2obrqGFbYsqhC5B5xjAA9aCZP3k1sQiSePUUUFTNtG3amwkdTk\\/TuearXQngk83aYQ2N25c5HQ89xxXQ+RE1jHJ5UIICbJGBDKMHI9zkc1Hp0c01u4eFpE7q7AcHpkfUk9PSmZ+1S1SKA8q70gSXM3JyuFbJ6jt26daTTbKKOAp9rCwyfMR1CjPGSe\\/T\\/wCtWjJYtukjigdTI6OVYbODn5AB2BxS2mjXaiATRRqdhIXoTjGM5\\/E4oSD2qtuQ20DGNh5kaGP7+5d3JGVCjv3\\/ADohSKSOblEZU3HcnDdMADH+ea1BaGGFEiVXlBHmMckLwcZPTPPQHtWZd6ZPbRMkRkPmKGI24wO\\/1HvSvYhVFLS5ElqsbCaKOSfzIiW3LwAB3HYg1dt5VZZTJMZCEwoKDjGR2HJ5\\/Wjw20JmmW7cHaOATy2Tj+ZNXNTt2UKYS+QudxQLtySD6elWrE1H71mUrKWY25lTywHfGWX6dhxxn9KLMYdm2gsZOu0YPPXnqPyrS06ZF0UGSIAbgUXqDx0x179f51HDsjiluNphuRJgbfvKMgdD9T+lN3J51qiprFiNQnSBJY\\/NJDM23G44\\/MDqKp2VhcLcxWwjBYPgk8jk46+nIq1dWs8WoyyK5dlGd2RnpnnHTjtmtWC1DtD9qv41lC\\/6uFSQowCdxPHapaL9pyx30K1lNFZ6tLI8a+bEGVVHIz6570xZd98ZrohyAWT0B45NLPayLdSb49odt8ZIO4rnr6etVLoCLOw4UDGCT7ZqtIvUElLUr3AMszuSBGh3bQOeasWl1biF1EGJW4VifuispmmDgoTt7gdKI2z8qkknr7CtDTlTWpNKybwY8+hOafkmM7j0qvMwA4OcelOVyUxVKI29B0oyoJqWOUfZipbk1VlzTEY54qlET1RKjt56lPvHPWnPGpGTwRUTKQ3P4U4hiSSc5q+VsVx0GC+exFJjbKfeltwdxBNWPs5dsgdOauNFsiVSz1IW5wKRgwGBnpVlLZiRmrKWxxgjNdMcOzN10tjOdGYg4pzWxyMjtxitSOzZuiGtGDS3fGUGfet4YVszliV3Oet7RmOO\\/atG006VmHyHHrXR2mkwxsGYgkdhWtDAmcJGBXRHCpHO8S5bGNYaY4AJFdv4VgMci1TtLTJBxXRaRbeXICBxXTGHKc85ts7PS1JRa0vLyOlUtIX5AK24o8r0qZOzMdWZ5g9aY0Bx0rW8nNIYKamDic3eWpOeKy5rcgniuwuLYEHisu5tAMnFdEZ3Rg4uJzMsRHaqsie1dBNb9sVQmg7YrTQDGliGOlVZIeta80JFUZkOTxTDUy5YgM1UlRRWlMpx61SlTrSaNIlF1UjFQsqjjrU0qe1VnBrNotXI3Ve9QSBcc1M\\/A64qtKSelZtGq2I5NuKhJUd6WUmq0pOKwkkXG5IxQ81GzIOlV3Y+veoZGaueSN4lppVx1qKSVfXNUmc+pxULuc9a5pnRBFx5wO9RNcAA81ReQiq8khz1rmmzeMTQecE8mo3mFZ5l96Y0uO9YORool55evNRNKKptKaY0tZNmiiW3lGc+lRmVfXmqrSe9MMnrUMqxbaXjtTWmDDmqbSZphk96hspIueYPWhnA5B\\/CqRkpPNqR2NOC7kjPyuR+NPluo5jieGNz64rKWYfWjzsdKd2LlL7W9tLJ5inY2QR+FQS6TOIiySFlHvmoopyMjrVqG8aMcH\\/Ci66jtJGfHO3ktbElXzjGTyB\\/Sr9rcnaUeUYUbQPYcj68morhYrtt7gB+xXgioTp1wAXhk3gD+LrS5ew7rqSpNFPOVmhWRpSVVm6g5HOe2P8APWrkunFbdmZVWKSRWi5+bHJ7dhk5OMcdqzNNk8q5RZVLEEliV+7\\/AJ4o1G+abUUUTMIozkDOM4NRtoOz6D9aUJrDrICVOOPf\\/Oait7gshiJfBO1UB6f5yaXU9RS4v1ee1DIDg7TgsMk9fxqDTWhW7WQs6qrcZNKK0KZe2GK2cKCGcFimMjvzTrHSLe4gRxclZGiJ+RgfmAJAI464\\/n9DbvBEZI5GGB5bM2OBj0\\/X9KrXMYjtLWSNHWJo924rjkdcHvQ9CU7lXUtF1C0EcjRhw\\/zIycj6H0PtWlocNzqVtdxRrIIrf\\/SZ1jOSNgIyBnnAY5+tT6jdxJG0lu5nkMSNAxGRjBDDnnIIqla\\/adNvIpbVnJkwSgBAZTztcdCDwPTpQrdQTdireQFXe5trwSopzuBwQe3v1rRk1iafQrG0jhQ\\/Y5w7gR8s2cqd4w2DluM8c1Z1iPTpb13itxHJOpJjUBEVx04Hbr044qW6tdRurRfs0wia3hxNJ90yIvKqcfex2PX8hU8ySGpdWZk97D9su5YrT7NG7K5hY7s5GCoYjIHJ\\/wAahsRp1xrUUFxcC1huJAkm0YEYJ5I7Ac4qYiFYRJcrK8fKljJuVmKnBHpg8+vWs\\/R5rZGllkgjfEWwlwScnIyOcZxRJNxdtxSTs7bmtrGmOFuJrWaP7BDKV3NJnzGBwFUDJ6YPPHWqLXk1rpMdvJGUeRA8LrwSP8aS91Mvo628I\\/cFztjKjcjEDnd1OfSoRJez6fHNKonWIhVJPKc9KSg9m7lQ5ktWaPiaaOVtMtMAvDZr06lmG7H6it\\/4eard6NAt\\/eW802lBWXegG6IsxBIz1PGa5F7mSDUYbgxg5i2HzBx93aSB+damma8y+FI9LmndUS480gDO9R0GD+XXpVSV0NGr4\\/jsbiz07UrK4S4hnEiBlGOQ2Tkdjz0NY02iInhxNRWUqzkKFIwPu5P9P1rFnaZUZIZCYi2\\/Z7+v1q\\/cXlxdaRBCApVFAwrc+nTPXoKFcZf8YQw2ulaYsEbJvtIi\\/Iw3y559\\/mrrbixuv+Eb0y6tlWUmzjQxnjACq2cjoMj9TXC+I5L86fYW0\\/kbEhBUAkOMZGDn6dK9I0vS54vha+oG7CkWozvfcd2VIQqeRx6YpTdkJJtnmFtc\\/Zrq5gy8ZltyjhXxlw2QcfUDjityTTo7Pw7JNlbiEXBjkdG3fKuNv+7neSAe46da5O7LG9yxViON3UH\\/AOtXT2WqDVLKXSQpgEkckxPmvyyAttwS3UAcnHQ1E4y3j8zOpzXvE60Wuh3mgefqbrLM48uN2GXmIBA6ZxgEDPtVvwqJL7Rb+0uLr7SliiRQqEAKhSGVmJUjA3Ng+gPHIrm\\/D11E0e8+TLE7NGAx3tFIFALggAhNuPf64NafgTVYtH1aa6u55nhv43ljZgdu4M6ANwCAcnkflxXLDDtOV2311\\/QijHlbTdzpEkitrGG+j02LUHJxGiNta1Lt\\/GyDCsSWwNuQMg9ax72wxdXd3FFcw31yCklk8JjOzduzwRuYY7ZBz1pttrB8o6iLwr9ruWc2wk2iLc53AqTlsrgdAcY9aW91W0sWuLi0Be2kCyQMbqVDE428qegBznaD69q4VhXGu5w0v6\\/d2t+ZnyJVedED2FvqVrDbabq1xY7ElmZXj4VlAH3sZAI4J6GqvhW1t5rTyBqXnOHDIs4bG0HaAG3bR0bqeh6c1c0G\\/nnv7eXw\\/EmZ8oyL85wAeCp67mDcZ6Yx2FU9TtZdJ0vzdLDtcnMNz5oGCCGZsxnvgE5AJwPpXVVT5HBSs+n\\/AATok7rQ39M+0+F72J9Ft4ZYZLbzJRMg8sttBZQc4zgjBIGQR365Hh6S5g1eDUoWe3tLt3Z4VJAAXquDyAFI6\\/hkDNJ4X1aG\\/af+1b22gEEvmwK7AAKccbemVOBgj09sdDdaRLaz3M1tLcRyO5AachkKgcgHgj69+OoFccoxpS5qqXNLRvv28tDOVaNJKU1v5HLavYyr4uvbGNIpLU3ZmeAcSN8oYgHH93Pt69q6PT7G0s5dRvrC6+zRsi+RGrHEgP30B\\/DH5d6xh4iv9N8Rm5vMlJQ0DvIuM7l2ggEei5+jD3robIxT+bDcxrIqwtt3NsBO4P16dAfSu2o3ou52U0muYr6mG1LRPtM+pTxmMBDuJwVJBXnoew\\/\\/AF1n6Xptq+lT21uXmkVI3EiHO5hvJUDPBznrnj8K1teVbrw2bSxud6wxquHkDCZRxuCnkY69x0rP8NWq6Xb3MD2zz3ZKsjA5XgMcjuCNwP6VSdo2RdupW1aK7m8N6zci6Scx4Z5lPzFldcZ\\/X07V3c2pDVfhhb3iROiG8jilLYI4IUk4zjnJrlnEA0fUrWR8wSNFG3ljeyEYznjoT6\\/zrr9Ons7n4VvZ2yg+VJO8oUHdtWQ7GI68jB564NbKzSTMU7Nmnplutrdm2me4XdIH3xSYwdq9Qcgjknp3qDX7CG5uJmYyXKRS+Y8ozgAYIGM8ZOO+ParT3Elumo30tqH+y7GGDhiuzqPp1xWbp9wdZ0OXxBYSy2kckssGxgMyEcE8HI6Dg461nVTUro1g7xscvfLZRXbwklYrdBtRWwFA+UfUc9Kw9b1eKd5I9MkjWGOAJHE6\\/wCsQtksD\\/Cd2eMdM5rT1mO1j1O5j8pXlaH5NzYOV9CehOcD3IrjtSRrbTriWbMTJGF2nA2fKQoPcntx65oktFZ6mVVtaIt3Vuq6Ppk7rHmVcAoCX8rf0GQBzk8AVQubxINSltVnhVG3fZ3SHkhhwDjrzx+NXbCJn8M26LIzpFFwZTjnqQvPAya5h9RF5APsdusVwJkX5U3nYMkN7n\\/Ae1Th4N8yk+\\/\\/AADmhF3d2dXql\\/BLpX2K2MjytIzn5QCMAgAdCemPx7nNUPC7oddggERvLiWEwoFkwmWBPzd\\/vAntjn2q5LYPZxeYiN9qnUeZIZCTkHl1XIA55wemD0xU\\/g7ToD4u06W+vIIkiEhyo+bcFAViefmYtVUErO2zNI73E8U2t3JZQ2EgWVFuAEVZMq53FT+Pytxnt60vw3MeiSaveago+z3ge2igBDEsx4Oecjgiu0+JlolmrzT7Ahkhjt1hwSp+d2IweCSV\\/KszwhYPFoMM1zeKS9tJMquTuG07eOCM4HBP5UXlFNJmq3tcwLW2ktZoL8aYSsNs6tEFwx3E8t04HBGMnHXuaTSF1GGK5igmSDzVUG3j6qAQQRx15I7dvSti2Yi1ttQkkmazMbKpUg7ATtBwO3TqT0qxrklvpWn2t1c2s1xG0oCXKyHdhud2DwcHtxWcLzfvIpU9rnLXMMU+rWktwBJEsbZPcjI6jH1\\/OvQtNmuL3SYmWDP2SIFZwxJXBww5OBkE8Vx0lidRgjk0+4ikw7NgjG1TkHv364BrY0h3fwNf6XZTSfaTcMjuQQFVUDEkdhxj8fxp1kqkXA0jZtpnJeJ7sa1ffY4rpZpFkKhAu3eCcYHJyfxrt7Z7iO4bT5px9k0uJLeYyAAMDwAD65X1796888HMsnjOxspkBCTb224zuRScA9McV6UklrLZ6nIIG89pFcEnaqYBxk9M9fzry8z5aKVKMdLfdra55+Imo+4kjIt5ptT1yWJDtt4GILjGRntjHf8Awrq0sre3t0W4VFtoolMbEEljjp19h+VYGgWD\\/wBjyajbXUUUkkp81pwSAQeNvqMdDWna3V5ql4UhDOS+1QVzsTBwOBxwa4HCUmrbI89vTUeusSvcPDaQxyQhdqLGuCxPOeRya6HS7SDTrFriUbriYfM2Bgn0A\\/CtnTPDU+lQiaS1ilLDKgHaCOCT0BPSud8X6tcXCSQzFERTt+9kD3yB7\\/8A16zlJS92Io0m9WtDwbTdJt457u9vYhdQoAItzfKeOp\\/AfrUENxHMVRSjNKRlEjJI29Ofbgf0qNr6a602CwDHY8hV9vA7E\\/zpuo2KWc\\/2W3nd9vMzkHHIGADjrzn06V91D4nc64p8z53r09EUXikmu2LyN8zFTz7fn2FR3V4bm6S4mVJWwBtBACgcDpwB9avXFo9m3mMEdIgGjyDlwT2\\/I8\\/WskCE2zkNli3C4A7dTWmnQ6FZ6kaRhp5AzIijIJ6gfl3p8UrS3IdF8sDIU43AE8d+lVo9wDgDORjGfx6fhUiO8MoaN9xRg29M8H15rO5rY6y6ihg8IuFRmuIcNuYZ2K\\/HOemQfTtXHhyJI2U9CMZ7Guhhb7bZvug3FkOflJ29OenJz\\/I1hpAv2hImG0seGY4AGepFTGHLfzMKEeTmTfW4P8sbK21vmzkH69vy\\/SpyksiiOJGdFOQQB6Dn+VNvI1iJBdpmABDgZBGMdaW18+FwGcwKwJBYHHTp+PStFo7G3QkstsksdrMyLFneWZc7Rj88cdM1BeBUl8mJQ2w5LjPb\\/P60pguRcCURDP3yEH3R7+lW7HT2llS5nzFC0nzO2cYzg8+nNDJcktWJYrDsm2o8r+USy52hTkgH9am1SSdYkt53GPJ37RjaDn278fpW1GtjBfzNLDKsDNsdkGIwoxxjn\\/JqzcLpVy8H2KAzMxy0b5UOFzkEDOR19KSb7HO69pbM4oM1wSillUnhc8Z+lXdNt9u7zUbbkFCRuGCCOh49Oa0tat1kvQUtYopH+URRr0b+7x6fhTUtiWtjHL5ckiBXGMg4z6DvinHuaOomvUzlspLa4Rx5cuOhXkA9BntW9GiGOeCJxvVd6bQc5zk9fTOMfWomtpfPVYYkGcOd6kgAEck9x19aswwxtLGQZXkkw0rBTj+voPfntSZnOfMUWg82JkVmbMa4OwAnGSfrj61a0rToWULErSzYy3GR0HStPRCI7u4jaN0Z42jCqxkL9fY4P9c1LJDcW98ii3U\\/LtkxwAcDKkZ5H1x0qW+hhOs1dFBrQR6iQ11GrLHzk5Bz0A9eahs4Gecq4eMYxu2ZXZuwc+3J6VqQaU0P2i+uXDQ3D4G07WQ9uOmMflmo9NFsrB5oGktA3lqQDuJP81zwaEL2ujs7kOkwNKxModYY2O2QIAW544H1H51ZC3Ca2AJIWDqGwrlVYA445BPQd+grfWxaOyheWGWCADI2tkkHsVxgDvxk8Vi6iywXcF9p0ok8iUKJY1OAOmOTgk+3ald30IjNVG7Fq1it5f3oYh03PjBIwucdx69frUE9qLBJbo207iLA8wA5z0wOwP49Kfl5tQt70+TIJ0Jlijfyy3HPJzjgdKi1i4v7mzmNtb3P2QDCZB479e54oUnccVbroS2U66ppf2cA3AEhDFdwYKOpOOnFEjxtZhmRY5PLCMxjzknPGSMkjnp+uOec8N6pfaYs6mISecv3Xzn\\/AHl9D7\\/Wt69e2bS7a8tHc7owShbcUY8N+ZBHNVawTo8s7dL6GdolpvnguTJhXkGcD0Jwf51t6lPsSdw0nkIBsDDHPBYge5OayNEu4LeBPtSs4YBVAfG3uT\\/n1rZ8TtutrZFdf36gkhc5wO2OnSlJ6pBXf7yKfUztHuyNMFu4DDoqqeeT39hjt61DFPKLpREM7n3BcEnIxg4PPpxWlptuscEUTm0t22ZRySxLEEjOOh+U\\/l2qqt3dNqizxoVnhPzNuxx6Z7HjtzzWyvsT7vM7I1ptLaOwudRvYQkrFcF87z2JPGPSsq81KG2RLa1TLDjcAcY6E5\\/OtbxB4lku9PNhDaywvjbJuydo9znk4\\/nXJvA8+593Kjt061ok+XzFShd3matvKjLuzukzk+w5rMvpQY5Tnkk4x2pA\\/lQsVb73AwagaUG3I9az9nrc64qzK1vdGKBkAzkd6Yo6t93HQU0kZ6ZxUhn3A4AA6AVukU9Nh8gBUKgyepNOhwF5PaooiwbIINTKozwDzW0I3MpOyEI3DrUaoQDk1Y8kMcA5qRbZvT610RokOpYrhSVBzUsUYNW4rQ9+KsRWqg5xW0aBjKqVYbY8EDFaEFr8uWYDIqSNFHp9KnTaO9dUKcUc86jZHHbxIeOfaraIu3Cxj8qIvLwORVyAw8AsK6FbZHO2yKCJuwrRtrd2xxUlqYNwGc\\/hWvZmEkfJxW8YpmUpsr21kzDpWpZ6cwwcVftvJGCFH5VpwbewrTlRm5FW2sGGPlxWrZWxUjip7VM+1a9laK3OaiSsCm7lrSkxgVuwDgVRtLYIBgg1fi471yT3NIMmCil2D0pFzkVIp9ai5qQToMdKzLmME1rzDI4qlNCSCTWkZWM5q5h3EWKozRj0rdnhFUZ4Aa3jMwcTDuIvas+eHqcVvTQ9qpzwAjrWqkLY524j4NZ06Y5xXRXFqDWfcWfXBq7jTOflUY6VUlX0rYubVxnFZ81u4PAqJGiZmyLjiq0g5rQliY5yKqSxEHpWTNU7FCUVWkHFXpEPoarSoeeDWTNEyhLmq8hPSrsiGoJErnkjaJRcmoGJ71cdBzVaVcVzTR0xK7\\/Sq8g9KssO1QsK5po3iyo+aiYmrTr6VC6HNc0om0WQk4ppJp7qR2phBrFosYetMNSHNMapaKGE4phPNPIpjCpaLuNJpCacaaeKmwxKQnPenGkxxSANxzUik461HxmnEjHFAMkRyverlpdlCAfu+lZymnKcc5oTsJq5rXoju0\\/djYwHVTzWWtoYsgKCW4ZjyT1\\/xp8chHO6rUN1z84DD9ad7iSaWhVmskaMYUDAxn1qJbeO2DMWOTjBI4x3Fav7mXlWwT26VXu7R9nTK+tAc3cW7mRkZp5fOHlhI0Q4ODkkjHYdecdakGp2Fxp1tp09q2U3Kk8TEPznAIPBHT3rIlgYuOX444bHbFOFjIYPtDS7XjPAA6jr1H40rXGrJGndCO0tohGzDEmAO4ww\\/EVu299YReG5YQq3N+04ZWVvmB7Ljrjr+Zrk7TUGV0jZPtC8gL0OSMA\\/hVnSdQeHUkkkupYpIgPIfYrEEnoc9R\\/jWaj3HJXLYdLyWCS5Do2SGCgqVG7qPf8AGpGhMCC7NxJIYwSVYE4wT19eO+KIpoby1YI7STuhZxuOV5+YjjvjNOaeT7AbS4gjmd2GwyKMlRjuD3\\/ChpCV7ld3glLxs+2JwDhTknjAPFQ2trDdXrJdR3CII\\/uogypGTjtnikmhQI3m71lWRtoVAAi55+vOD7c1Z0eW2FvLDNIpmZMqd2Aec\\/5zTVkPXodDovh+2Twhd645a4jsRIUtDhSwO0fOOoyGzkegrjLpUlt1ggITPMijhWfJ6A9hk\\/rW8\\/iJrbwleaZCz+fcXHn8Z2iMrhuCPYD34rAvob2ILNdwPC80YeMuCN+eNwPfrVTtZWHC+tyx4gRrQ6emUfyYypdG3KWDNnn86p2NjcXEFzJCgaOBVMjkfdJOAKmspr6OaOBx51ujDfET8pwx7dzyava1etb62\\/2Nrd7SJgkc0afLIMDPI6mpQa3sVb3TbzTbwWt7H5MhUMASOR147dKovI0FvJDJCyOclH5GAe3071t3Fx\\/bE6Qy3QG0586U52L+GePasTUokimaJbsXCJyG24P5Zptdh36DrOSTU9Qsra8uzChOxp352KTye3Fdg2p6xH4VntZb0TWcYjMcbxBldR02sDxypGPr7VxOj+S+ook+wI4ZdzsVCnBwcj3rq7zXrJvDIggM1ve+cGm2rtDARnj0I3c8880mk0DvfQ5\\/TLWTWdaENtIYWlIVPMbcRkgAZ4qTyhY6qiz3WU2FWkjXqCMFenoSO9XvDN3HJeQAyi0dZlCypF1XO47sc8ED8K2dTtoNG1uW\\/wBGf7TEg84+e6lkweGHGMg9uc5p2droTfQytZ8jTgDamZAUAj5B3cYOSvBGODkDqa6WS+sY7ax1ueEyvJFLiCO3dIwx3LhSBt43c4PcdDWR4un8yytryRnkZhuQTc7weeGAwRkH8Qaf4IluZ7yTT7SWO2kuQIJXcDEZLABs4JTluo\\/pWUk5K8bff+plUu4XjubHjdLfUrK0MDRv5wViY0IdsLyHyc+hHJ4Fc7r0stt4P0+GNiyl5I9i56k5yceucY9q9Wv7S0fQZV1llgvYQGtngBKyEY2sGC8HkZz2HSud8ZaDc6Leadb+IhZSWQJuS0RISQ7VwjAcqQO+BXHgsSpxcOWzTfo\\/RmWEk\\/ZtONrHO6deXkN6kOmXENl9nMESZY7PPYYIJzgYJOT04PfFdN4isJxDYCzuB5kbrHK7MMA8uWJx12lTn3PrXEXFxBq2sw6bo9z5VplJpGd9p8xFI4Oc4wBjvzXWeNZpbW0sdKeIFon8uC4gJBdmQBQ3AI+U56kcD0NbRhqm+prDRajbWeCx1GGxaCM3NwqOJJcZVhkEkYwSV289\\/XJrp\\/D1\\/dW8\\/lszzQI\\/zhSQD0DYJ3HPK5J4HPNeeahdTM+m38CmXNw4g8xmyI1JwR3AwOg9fpXaR6zbCAXQihWOclkJKksu1flAHP3iDjPuayq4ePK4WumbQstGZ3xGgjv9Y0+XZMbSZwzEfLg4BXv\\/AHeRnHBrr7XTXZ59OaW2LqWPkSYSYYAOVwBuXG7HTIOe1c9ruoRJo8d65d7vzt0kirjHGVCj2BOc+vtUsGq3t\\/LpyzTMZcmSCLYflOeVwOegHuTWSpu0Ymt0ncuCKDStaigvLAxgBYFYZ8sZOCeBzjqT\\/Oqt7L9l1jV5WVh5BKpJGwxxjPBPXPPOcjFT6usl\\/fLH9rhkjjBBuF28PjpnqDwMEY7VXs9FmmguJ7VZfJklHnJ5bfKWwW3cdMZ6nvRyOLNub3Rb5lmkvrEJFaExMYsyfPKwCtng453YHGOKm8NaxJpNlc22oxCaKeIKVYfvFZdykdeVPXk9qoQWME2qmSe9jgEBe3LMQEXcileQenQZHWtmbSdSnm\\/4mAjuCqAhkcfJ79PUdatpON+qI5bs1vEHiSay0Bbz7A0wug+UWXayKoUdMHPB9RVX4fXs934TmjvLVrYJfO6xsS3LBcfyJ\\/GopWl\\/ssbYd10GWH5pvuxfMikE8YzgYz\\/SptBiexuvsUpLGQeYFDAqGYgqSAe\\/z9eRWnxx13JXusoa9ptpeXN0ZAibZY4nYuFKjO49e2Qv5Vy3xL0eO00xo4hlpGj3FmY4OACB6nJOMetel3OnrOI18xN8zqzM3G0ISxz+IrivirBia0tPtRPmyptOznC5YknjHQdPSmtGhS8zkvEUF3YaL9mt1ZbKSHEYVtzIwYA5\\/wB45rOuLS2g1nSdNt0FvFM8BnBwWzwGJI993T1Fd5omkahrc4+1QSrbPNJK0cyYZViK7BtJGeT364965HxHpiaV4thuMna8puIjImGMaHjr1zxgDjH6EY+9dvuZOOvMaPiKP+yLXU2spbxlDNEpJDJIGIXHblScYxzzVb4c6PJJqU11K7SzWMKzLsbBjI3kEY9CR9DjNUfFM909nb6XOp+cJGj+p39T+f1rtvhqLWHW723mR2Eix+YN207PnBTPbkZ\\/Krgmo3RaSIvGOvxXOixwfb0v9QZzKjAbFUbemOmfvZzwMD8cXwybl\\/B9zqMtubgtujAMmdsfBIA\\/HsD6+9Wfipp1tb3vnWqlSCESJUAxyd3X2x156571c8MFofD9xp1rcRRNC0ZlLE7suSp4+gHHv0rmpw5E3e7b6\\/1sZJWndk\\/h+wt08LXNyba5SJ3Rbfa7fLkrnpwOWzk+nSszX7yCGw1G0u42W7DbGuCzNhdygLg98A84FT6\\/4ljj182s0C+S0Z81lnO3zFBOfTvjt29Kz\\/GdqIL2xZZ5p5LiNTMsoBwxPAwOozxinCM3ZzVuprKV3Y5\\/S1ntruN5kliimQtGTIRuLDCkgda6LwT4mTw7d6hBqsMrw3C4McYUjI6Z9+2R+RrB1q5R7Z7aVJkFuyIgdiSoAwfwzuPfmu18Lm2vL+0vp7eM20LM08vJIUqQGJ7joO\\/HpW0k5q8kFKTvqQaRq2mXniCXWp7HyY4keRWViTIxwvHGO4\\/Kqdw93qGsWlqlw5ivJxMI8kDZu2hSBnHrzVPxpewNNJBYoiQxDY4SPglx\\/D37dK2fCVoi+J9Ba5Dl3tzFtCkKVAYofqAK4KlONnX8no+yVzKqoyk5vc3NZhEafZbCF1ijRYlBfGfUn+fpXXeB9AlslhkuIYm+RZJiR8ygkAZ+ueOO1c9cS\\/ZruUXYmBDl1BJYoOAWIJ5wOccVpeF\\/FBgutQaXTbq\\/hvGV4i251jIVvvY74PHBGfzryKVOpiIqMNEcdChGpNOex0HjXxOLFreytoIRFko7KdwCYB7ce348CuB1YXMkcskkyBpkDQhDjuBgjuOCPUdKp+MfFFlrGoXGn2Nr9nZHHlsCVwoAyOM4OcnOT6eldDoukG70a3jmEcyhQBu+UyE+pYDOMnB61E8P9WtzbnZiHF1PZU0eACZYfJkhXa7pvRSQRu5B46D6VNfTtcytOk5ICoqh1HLkAHtyASagspUmniiuhvhjdg2ByMcKMj8akF9\\/ZsLpHbYkUAx7iDjPQ+\\/tX3D7mTWui1L2sWWz90bkPMigSAMVXAA69+wFcywEQByN+Oh7A9\\/1rQN20hD3H76aTdnnnPY4+uTWXE+JCeOmASBxS2SKpqSVmPjgcb2ZW2hdxPTg9DTWMb7irBMAfL6\\/0q5eXEcxuMh\\/MYg54PH4VWdEG4qOM4U5\\/LgZ96XoaJ9y9pN9cWtzFPbMA6ZA4\\/z2q5aaLPeRrNaOi7MYZh95+eucD07HqOtQ2du9okU0hVw+cID0UHkH0\\/8A1Vr2SmQ7BFIIzgqqtty2RnGc89Py96GrK63OStNxvKBk39qbBisc0nmMoEq4wNvQ49eRSX0tvcwxjdci4kA3KchV5PqSW7HqO\\/tW7ffZ3YqwH2k55JAwB\\/D6f\\/rqnDbrJYu0ztGZF2p8wG\\/+8C3Iz7DHH1ojOyCnWuk5bkem7vLZLQK0nlkySyDG3BJ9SB+VMumkYMcSeaCsjbThAAOT\\/L2wK3o9JI0eNbSZUmYA3G9wAQcgNn+LOf5g+lS6cltFOtzIr7t\\/lyZ5DLgAE+uPQClKotzGddK8krlKxRTZ+YqGVpmTO0ZK9dxBz+dWpbOKKe2EQORICZFDfL8o+U85HOOe4FWooPs1272YjET9BtJ2jIO8AAk9Ks3E0UyI1yQY9ysyja\\/IcBwT3yOcEd6y9ppcwdXS6Od\\/s121FmkeNvNYlFYlDnu3zduKsQiUQr5CwYSXBZVClDjjBIGTyT\\/+oVo6ykT67JJH51vbRAqpZQoCFgPlx2H+e9ZN8GkjjMFyisW8pCCBuUHgupOQOeM9eKtT5krGkKjqRTY5B9mKzTWcryxKImj2bcrg5bPP8XGP1HFRtZ3sl3EunyQo2Mud4+Ujp+OKxZbiVJW88AlPvIZMqQOv5nBq3ZXBEDMha4kmUltvCgHAJ5\\/D8qqWx0cjWppWsLy6iY\\/tdrIsa5Lh9obn5gT7gHHHcVda6tLWIoNzMm7y1foGOQRg446YznHH0rN0c3EUf263jidQhQmQZ8rpzgDPAz0qd4Lu4tIZvtFw7BwgYkMGfr6nH41KabsY1VFvV6DtFkuL6\\/MUdyVMjfKjMcLxn8iB9eK35rsJqJjmJeJpcb1GXyvQqT9MdKw1Mdi8m25Pmx4BAK\\/IykjoKNXjm8qKS6lUzrHvEYjYNg85+mcnn8KtxMGlKfkdL4hmjki+zacs6yZO+R5djndnKkHqOg5x6etc+I7C38uxWbzTLyD1MR47A\\/St\\/Smt7ote3UcyiNxsRkLknGCoP1Arn9Qu7dLpBZWsbOMYk5CjOD1xjjI59u9CSSsjOjzRbgrnXXJSPQvKgtIYrmGYbQ3Er5bIIHrn9OKz3vb600hrR7aGZkXCSPPtwmOBgjtkjr3FVrO\\/utVvY7m7e0X7NhDskyzPg4289c1n3TxXUpS9PLoxjUnAbHGT\\/ePFOMUzFRk5ctRXtqzV8Gw3mr6zaDyrUBGWSMzjeOC3GB6nB\\/AVV8YR3FoLi1NtbrbRynYiDB57Y7dcgVjWxu7K5tXVTH5Q3Kqn5jznH0z2roNRvre6t7ZTNL5rnzJJGAVPun5Bjucj8hV8r26HTJyhVTWq\\/I58JA9ko2jJA6etWNVvGMGnMVJKRHoM5wcVWvLKaG6bYyyN5e9lySAB2J9cY6U6JRcbI41ZQo3AhunXj8SaSp+8n2OqTjK0i\\/PHPJaRzxboJPM3CSNtpXJx2Hp\\/k0QXMVvGJI\\/9IlJJfzDhd3BOR+HT3rQtr5hbRWl2mdpLLnjsRgjvzz74qHXYVtWtop5of3mJAY+GUerDGMkc9c1pFtM5768rRT0\\/EszzTtEBIclVG1WIz0FUtVnZrgrbqI4ygX5cjipbzUYiSkG7B53HAJP0\\/CqkglnA83kD7oAxitYQbdzRR97mZXcMPukNj361VdyVxyT3q9JHxhm\\/CoSIl9K15EjZSKQDHtUiRsQPlJ9an8yEdBS\\/alXoBVJQW7Byk+gsEDFh+74HerghjABYjNUWvmP3WwKiN05\\/irSNanAiVOUjUDRpnFL9oUVkGcnuab5p\\/vUPFvoJYddTaF4O1H2xjWOJakWWl9Ykx+xRqG7b1xR9pc\\/xGs9ZCf6VKmTzmrVWTIlSiuhoxzt\\/eP51bt5Sx5Yn6VnQR5xWrZxYI5rspXZzVbJGnZSPkYU\\/jW\\/ZM2MGsmzh6Eniti12LjvXp0kedOWptWZ5Xmtu0I6YrBt5UBGBk1p290o6tz6VsYPc6O0IGMVqW8pTFcvBfqMDOKvwX+D61lNNjV9zp47zGADVhL0etc0t6uMipkugV4NY8lylKx08d8DVmO7UiuViuhnGasrdYGM0eyK9o0dG10mOoqtNdrgisJ74Dq1RS3qkcHml7JidQ1JrpSOTms+4uo8dayLrUADw\\/NZd3qYwSTz71qopEu7Nm4vF5wTWbcX4UnHP41iXOpBifmx9KzbnUeflf9avRFKLN6fUB64P1qlNqHX5s\\/jXPTalx94Gqkuo5GDn+lS5otUzoJtQ6gsKqS30ZFc9Pe+h\\/Kqk122M7iKxlWNPZHRy3MZ\\/ixVd51x1BrnDenHL003bdnrN1zVUWbkjKTnbmqsrxjsayTfSL\\/F+Bpj32R71lKui1RZfmePFVJGjOcVUku89elRG5XrWLrI1VJoncpmoJAh5BNRvOD0FRmVaylUuaqLQroPWoXQdM1IXWo2I6A1jJm0UyJkqF0GetTsR61E3XrWTNUQtGD3qJo6nbp0pjY9axaLTKzLTGWp2HvTCKzaLRCy+9RlT3qc4ppx6VJRAVpDUjbe2aTC4qWiyPFNIqQikPtUgRGjHFPIOelIRUjG5z1zRk0howSKAFBIOaUOelMPTFJnFAydJCDwSKt297JH8vBXuDWdmlDEd6Lieps77W5UBxsb1FRT2TAfu23KazQ5HerEN5JFjB\\/CnfuTZrYgntDGwePKODkEVUdbjzS5yWJzk\\/XtW2t7E4xLH171KsNpOP3cgVvQ+tK1xqTW5h2Ny9lc+coPAO0mti0vYby3czzgT42pltpB67hn6c0TaWduQoYHuDWXc6bIrdxt9e1JxGpJmlaruuJIfNEjFAc+ueTyf\\/r1nYmivTCqvvXgLjBzj\\/wDVUbvPGUDqSg25x6DipI7lnukUbgBllZj8xwDjmp5dSrlrWpk2RPCp+aIBgwHBK7SPU4wpqO11a4SJre63SW77VYEAsqjkBSfujODx7VR1WaOW\\/JjLGMYCkjnFQM+cAdM8UDNlvslzqMjwyTRQOhLeZyVHU9Pyqq8mbVvkQ7GxHgnAU5yMY5z1yfSobRhtl3tjKjk+lAjSQKFkUtuwCTx+NK2oGslvZPbRNtmhimKjarAknBBHPuOKh1rRmtoXuYX2WisFRZGBkYntx0PGcHtS6nCIREWYp5SjaV654P8AWq00s00UKw3rBN2RCWPyH19KqLutRNWZVt90EbgojNIu3B7A\\/wAq7O5060Hg5tTkVPNAa3zIAGYqU6D1+Y9s4HrzXPS6essv+jjIVVZyzBS3Tp+f\\/wCuuh1oG38JWMMqRkN50gxIMoeB8w9TgY9e3ehqwbnLQrFDetBvW5UqPKkiYgK5wc8gHgZFehW9pJc\\/DnUL+0jaaIzNAXI3SLkQ7g2BgKM5Brz1IZIWiZvLYuucJknnufp\\/Su2+FeryhtR0Br+6tmvm3p9mKq0p2MGXLcAnIrKrU9lBz7ailZe8znr+3uLy+nt0DvHAjyYAJXAUcgDpkDr3zWp4BgumuYry++1R6aJGhaWOHKlmVeGI7HAHsceuauXlxfWGgzRulut7CY7OULC7SKoztVuduR5Y4AOc57Uzw0Irixl0wyyJFNcIkiDA2sS2Cy4HAKqcemfalCXOm+nT\\/MhSu32O915hFNHfWO2W0WPaFYF1bjgHAwDyxzk49O9ZPii405tK+2XVrcRxrGqCWJgSy4H97r93H4g89K6G1juLNPs63bWqyS7GJQ8gDgkdefp2I9a4vxxOvkLDIBKizlpomORnnBAJ5yT0HSvNw9Bxe\\/zW\\/wA+hM53Vkcv4S0mTUvEyy\\/aE8qM+ZcGQbVH+z1GePoevpXda9YLd+Hk06wubG7W2AK+TL8ykcdFJYdfzH4VzfhCwhN9EhWa5\\/epLNs+Xb8rKQu7jPzKc99p5FaV7ol7b3l7Y+ZbgSTO0LMCuNwyCwwQcAg\\/\\/rFdddS9orSs7Xta63MKnM52jKzt28yKC1sNVsItP82aKbT7ZyqSRYDo4AEgAPGAO2c5zntUNrpsSaQt1Be2Qj25dZm2sDj5cbiABkevr7Vj+GUurnXZ7XUZpXW3EkaRiMYDlgW6jAOAxz6gUaxNHMf7Mt4lkhtmdVnbO9492EDduAMdPXrWsI2bje\\/U3hFx0vc39L1IaxFLYrbrb4QMzx7SrucA4IOO3pWrp+hTteNZEyRzIB9ilLFHJ+8duTk8DPWvPYrK5FxBb7SshQlgjgZLEEdwB6Vsap411QXti8UgZoOLe5lG1sZGNwHUYHPqKtU0pXNm9LHXS22pabsMNuTZtMko37fMSRcZYMRgnJJwT29q6nwZcrrOoyaTGkcHm24ugbiLMSHcoJ4OG5z1Ix3IxXmOn+NvEkOp2rXji7gchmt8lUGCGJx\\/ePr6Guj0m7sZdBfVHu5r68kfyI7cZRUdwzdAMZVsfXd70OEbk8zSN\\/VvBT2\\/iV9LWO0824iCO1sxCzHAYcbj37Z7YrRm06+iktLK4eFmvJGE+0phPXhAcjBzxx071jxan4kgurbUNUkiVlTbCr53MSu7cdxwvPPGO9dP4ek0w2g1i586S9knZY2iUkoGXheTyNvr64rnk1P4RqUtLMq3qxJZ2UBVJY7dmTzi53fKTtKgHqANwzkdeDUGuTadY2dvP9sBUP5okYFnyCd2Rz2UDPHc8dqGpxQWNxJFmOMyKJW2yCNhK7HGAo5+XHoeaoa6kN\\/4euIyJlFnZtlklLK33mA65xgk8\\/j6VMItWS6lVJ6nTw302oQ212lviNoy+zOS6lScgY6kHOKxvFlrLLdWMaRCb+zdJ+Z9oUI8jnk9xhV4\\/CrmsTw2Gk2UJ3yQQKlvE+cEHaFBzg\\/nSeG44w\\/iHS5GIkntl8t2cFgATnC+nzde340STldFTXNoWrSxnsvC7TTEsbjYMoP3gVgCw56DJ\\/lXnVhJear4stzf4J0+zO1C3zF5GYhcjsORj0GK9S1WO5l0iC3WIMA+6RjztG3AwCeDXmeyWw8Ua1dTIqyJDH8m7d8xL962itweiscv4uS6v\\/FkMazR3CpLFGXh\\/jb5Tk984YD8K67wRr8a3F\\/a6jZLObi8ELbcgLHtO3PrzkDkcmuWhQR+OL7cfJWDa7HbkBmEeT+YNdLp+kTadYf2lazn7TcyhoueDjgA\\/mePpVpAze+JOiDxBo2la\\/FL9na6Nu06B2ZY1Y7MgcA4JznHOK53SL+w8K6hJpGoKtzbvGALhJCSsuQcj+9g447Vq6ddaxZQJpN1Gio8cMluu\\/dhkcFsZ4+Y5OPbHNc7NoEGpYmMrq8lwxRZd2JFBAHH14\\/PiuSvHmTg27Pt+GpMveeh0I08Xyw3j2MVxFI+8uy5IA7DPO089O\\/WoNP0S8v\\/ABDe3k8LpFGshUScbRn5SBzzz+FdzoEtuvhWwsJoXg1O0Vy8dqnWMEkMF9f\\/AK1cBdWxuvE2pQukpdXSPd5jHGcFgze569unWio7UvfemlxKyjeRkappl5d3xcpcLGeXiSLOSvBAAHUnqfWtLwimoJdJFFarHbMflYyF2kO0FVBUgDAJ\\/Xvmuo1HT9+kIltdx28skLxqMdQVG5j3JPI49jXHNo\\/2REZ7uWGFJP3Ac8h8AYIX64zzg1hhcfTqppvYhYim3uQ+S9p4oNvqqxebLLiJAcqoYkbiW7KB+PAzXWa9p1xDrVlc6HA1xdANAswkwkfABLf+PcfWqXhi+t9fN7qWpxx2tlpIDJ0MtxKD+7jJ9OGJxzxW54FmF1dWDmT90JHuZUVyAv3iifMM5JH05HNLHuaiqi6XuujuOrTlNKSLF+dUi8UO1xbJeH7NhVib5iWIyMHg8gcevrTPC7akuo3aw2MtsszErGcrMrHgBhnaAMcY7E\\/hZ1zVI9M8XaXqKbhFOyq\\/y4\\/D6DI4qvq2o38nihYLJpZZrhkaPbIAGzwFP6nNTgIJ4eLha9n95VGCjFX7k2heENPuL24vZZ\\/NEDKDIpO922BmIOeRkkfl0rN8Q+IpNPuQunF5FjZZVLjBTBAIxxnivTby1i0uzGkeVBaX8yNNJN0DuCBnGOvTHP09K5PWbyb+zpZtWNv9sgLK8WQ8mCMAFRnOecdK83Dfvqr9or\\/1v6HfDCxoJzW76\\/ofO9xOllpn2OJE85mDSYOeSOnpx9ar2Ol3F3cpArIkrgsxdsYwcbfXPampdeb8ksajYcqQQMsT3J7Y7cVLa3skWopcx7QQ7sm7ufwxnmvr2tNDybSjF23IL6CUb3l8uONZCiDG05P4dBxUFxpk0dvaz8Mlyp2Y45FWdduJLq5NzcPksAGww5IHJx+lUYtrSROj98YfHy88c9\\/rU9NdzSHNypslZJI4CJNvIxnIPIPr\\/SptDgie6RZGG9pFAD4C47nkHPp+NRy27tMsMDPM3LE4xxXT6P5UahbxEBJCLuxwD0wR14FBnUnyx06mdfaXMlw0crICGYxlGGCozzgeuK1LGSKGK2mw\\/lY2uhXJOO2OMDP5Vcijjvrry432z267nd8ru4I3LgnsKghEnzW90FG5gwYMMkkdvpxn60KXRnJKpzK0ie9XdOWht4hcSTZMZA+6QPlHrximWMNvHZGG\\/IXDhlcIcg8Z64xxmrdlao9tDctcGaSaEsd0ZKoqcHJHU4xjFWEs5La2nM2GR5AVdWwBgcg\\/gOwNZymrWRh7SKdmQ6lObazFsm5ozKyGW3G5cnGPmI4H+HakFraxRh7qSR1eU+WEXCkdySOnuf1rqLaOx0+3NybeW6s7gZyXDCMg7QDnqCMe4x71h6TFa3s8spijVfMbaA5YHA9Tjqcg8\\/yrGM1YzVRON0XNYFp5kEdtdmQqAGmVzjcVAzkHpkCsG2l87Uobe7tzt3xqw\\/v8jPJ\\/z9K17aW3iupb5ECWqRBoN48yOXaOhGc4JOcds47VS1u\\/sZxFHFCI5I\\/kDKW+V8cYIP8A9YZ6cUK7VrDhTcVyJfMv+IFgujLboYkgiDFZAQXjwFyBnPr+OT17edwC+uL+GKWI4YhkCL8vuefrXT2kt9NdXljp8YmjkhX7Q7dxjaQDg8mq1pc3eladNaSWSxtlhvKjehfHRvwP51tShKEO6OqhD2MOTd\\/1qZclhBdeIJ4kTdGed5lCBRj5gARz7VNpGlJOyQwsqOeQHOGI7fnimpenz5xHAGuXIEYUEYOMYBPXAx1q5d3TWjM1vNDGdmxAwBZRzkgfXvVz1WhpOU9okFndSaRfPC7Q3UYOGGRyCPzBHoa0\\/DeoXU7JHdxvFYxyNIGVc7cjjd6D+vFUkaGQSXEapdkuEkXbsBGPXHU1cuIp4bOOGBYZvnwY\\/MyFJ4wfcds1N0jCryyVpLV9SzqLrcNBCmw+TEPMBJIQZwQB6nA6dhUd3NMkfkxyBovLKDYOWUg8ck9zniqO7T4UuBLJPJcEqph8wkZz15HPc8nvUb25mvoxHJEjkMcStnaewyBkGtNCI01p5dx1zvhTekojiVsiNpQD94ehyKfHHLJZT2M9woRgJY0X7rA4AOe5BFQCyWa6eGZSAFUM5P3emcHv9fSn3Een2qRyR3HmMrDCDuvUg1duxq5c3u319DKlsL1Dvh35jPbqKli1RzIP7QiM5UYV93KVpXWsGaNDDC8LfxkMPmI6VnGabymj8z5X6jaOev6c1pGF9WaxcpL30bVhcRz3aPDcR7JX3nLfcf8ALOc88V0V7byNZQBvIjCyhmcsFZwDjAHbP9K4K3h\\/eCU\\/eHQqABx9K0pZXlA8+csAOjN2rSKOerQvJNG3d6pZpdMUMaELsComQDjoT35xz9azbe9EF26RWxeMncSwDKT+H4\\/nVUT2sXBTPHFB1RUBCog\\/CnzQjuxwoWVki\\/O9zcSNshSNWILNtwWwc5PJ79qhuIQ8hlu7oyuR65rNm1OVifmNVZb12GcmodWK2RtGjI1JZ7eIHYoJ9TVSa+J6HH0rNknJ6n9ageTPepdaTNY0Ui7Jdk\\/xVA1wT3NVS2TSE1PO2aKKJzMTSeaTUGaUGjmHykwkNKHPrUQIpwNMCQMc1IpzUANPDUxNEwJFSK1V1bNSJ1q0yGiwrelWImaqyGpo2AreDMpI0bdjkc1q2cqqc9awo5AOlWYpWPHNd1KsonHVpNnUwXIAG5vwzV2C9A6En0rk47gqeTn6VYjvG3dcfSu6GIOOdDsdampYA+bb9KswX7tyGxXJxXP9489hVyK8C9GH09K2jWuYumddFe7VHOfWrcGoEHhiPxrjUvWJHz\\/\\/AF6mjvzngg1p7S4vZtHdwajkjLfrV2LUf9rH41wcF8x7kCrcepEY5PXmnzonlO4XUF3feqcaiOm79a4RNSbzep5qw2okH7wx7Gnzol0zrpr\\/AAp5z+NUJdVA4D8\\/Wubk1IlMbif8Kzbq\\/JBZG9+vSh1EhxpHS32ohl4cHPvWBf6q6ZEn5g1ky6k3Uvx\\/KqF3e+YMk5P1rnnWVjWNLUvT6oedrmqcmqM3BP41iXU3zEgjFVGuSDiuKeKaZ2ww6kdBJqPB5\\/rVVtQGeuPpWK87YypqB52J5rCWLZrHCm21+OSGFVpr881jvKT0NRl29655Yps3jhoo1GvcnqTSfb+MEmsouSDTS9YvESNVRibH2zP8R\\/GmG6z3rIL46Gl8w+tL27K9kjUa49CKYbk+tZvmn1pDLjvUusxqmaX2mlE49ay\\/Oo84ip9sx+yRp+ec8UGb1rNExNOE3qaftmHsy\\/5ozRvHrVES8Uvm0e0FyFxj6VGWOar+bR5nvRzj5SU9aYTTfMFIXzUN3KSBqYR7U7dTC1IYhUUwrTy1NLGpKG4PamnNKSaaWOKkYZNNJ74pd9NJFSNASMUmaOKQge9AxKKMUcYoAQ0CjIozQAU4GmZo3GgB4anBzng1EDSg+9IC\\/bX08P3XPuDzWlFqNtPgXEZjY9WXp9cGuf3EClDYpqTRDimb81lDMuYSsin+6efyrGvtNnQN5XI7j\\/61Njnkj5RiCPer8GrPws6LKvTnrVXTC0lsYMkMu5Q4PAxSfZ3P3cGuoX7BdjEbhX7LJ\\/jUc2mxqcH90w7g5Wp5Bqoc+krRwyQN8u4\\/NgdvSolYBxtOPrW5daJJsMoTzF7MnIrHuLYIe4I7Gk4tFRknsasxXUoDHEW81PmdiflZcAYxjOc1Uto5LeUPzHLG2EK84b3+lNguGtbWSBov3kn3T\\/8AXpbSQxCNSUDMxYswzs5qUrFXubelt9qmuJJNplYrtRPlUcD16dKsajpLXL\\/b7uWG3hPyBd+5lHqVPXHeq+l3FoJmtdRSSRFGR5REZZQPl6D\\/ADzTtXWEaYRbAzh8sjO37xFXkr7jBz\\/hV6dSLPoZmqWrWrhEEjpgMku7j8MdutXYbCafXbEWE6xy3EqLFLE+1jwATx0ODk1nW81+wM0Vp5gWLarspwuP4uoHY9eOTW54dj\\/s2PT9Y8mRriK5WSQrIcmI5wQNuAARjIJ+8OOlTo9ByuafjDSZPDj3+mzS\\/aN8EZe4ErOfMySoz9DnGO3YkVF4Uu7BteunZY3t5n3LMZG8xXKEjGevzZyD16d6rXWp\\/bbua61Mh7Se7UylWOFTIU4HJPA7+lJ4dsIRffboYcQSSnyWkBCYOQqnjPPQHpng96SXKhNKx3XiKe4R1jiuYoHlC4MhCsTzjIPYHaPxFeea+5+1x2okhnmj3Mzrk4YkkjoN3bpn+db+v36zXy3kkW1hpyNKJNoYSALnaW6EMeo54IriNWnmupY5mYC4Ay+OGOSxz78Y5+lJK22xMYtPyOn0vUZ5vEFvfT6Yq2NzcELFCWUo6L2KgnI4JwO9bN3qt1b6k1xduxnmgwiHIKpjhugPRep5rm9HvpnQWrWzreb4Ps0sf3cxlhuz9DjPIx6cVt+ILlDmUu1xcEL5jFM71wScjOBkd\\/rWb96fvIS1drEWhy33iDxBaXKRRxBwVPkEqEXvuPrjv3qb+xWiubiO7SXzLqUSqH4LKST09s\\/rVDwJqZGp3FtbmRFmkdvkjypwAAMdhg\\/oOnNdn9in1Jpt9xHBPFjyJWQk5yPlPGBnGO9cznKhV1SUNutznbnSnslBetzktShhsbWV\\/tEkd2gO1lY5HIHH0AP6elSeHPDdtrVj9tuJ4o4Ik8tEJy8h3dRngcfypviS2lvNUuLKC3mnuJFKx+QN2x+cKfQEA\\/jn0rX8MXq2\\/hz7PcQJDLpshUKUPmEHOM+2Wrtk90nqdKku5S1HTLWzjhCTQrcByMlslVHcZ74\\/OsqG2D3NwlrJIsYkJ+V1VyFPBzj8a6nX4rabVfMlihCKcxqj43N6Hnn8K5zS5Ft78XqyxDKuyIR85I5HFJ3WhUdVoei+HNZj1nSjNeoJrq1KQCaVMsBuOxyenI689R2q3r0l1d3kkcYW3eICa4kR\\/LiOACgXJ64HXjIIrivh5OF11bORnZZlP32xuK\\/MPp0x+tehX8MstrcjazIEHkkc8I2DuY+4H+GK55e7MDH1GI3Oj3uo26K3yKHkf5yv3cFeevGPxNJoFl9r0orO5gc32AqrkMCvKsM5wQMc+tP0oLPoWp6OLcLc\\/avKZiM7SQOA3A6+noa1\\/Ay29ldarYssbCzkFwfn3GQsvb06YAB9KtXTsWorcl1GfTW0a4Npb3HySeWmPnU4GG4wOQM\\/pzWfaNOniRBbCPdIkhdkBBHPCsv4j8qdc2a6ddwqsjxxXUpkeP7pZ2wSSc8cDt2JrO0bVpl8aXNnJgbV3mTs4DZIz3wXx1pTiug1fqdtpiy6XDL\\/AGlhUmcsWkIKsxfjB\\/z0rzLxbEr+LZokXcbu7ii25yNoZu\\/\\/AAKvRvEU\\/wBv8PWIEU8Ll5H\\/AHbDbgZOc89sGvNNOSNvHdjcSbhEtwxPPHCkgYFOG9hyehn3unXUnjPXiqEFr2RTjn5Ixx\\/KtbSEvESwgnn3+VO0nltyEBIIGD2xz+NJ9sTTryGSVB59y8ktxknBeQEkD2z2qTRtRumW1h8jAkkUbnyG2hhuPuDg\\/hitUI2Lja2vaLZ3DbHMSvMXHQY5UZx36H1p97pM7aE09rtS6gYSqM7soGUsR+tUvGVysfia61J02wxRpGJCflUZLtjHtgVftPEjpdgWXkLA8Yys\\/wAhYMx4Bbp1HI5rOpC9mJbsL7UvJs4gkEbRxRl7y62EyncMDbjnPIx9MVyHhq8uRp4W5jlFzJMiZcbXJYtg7Tjpx1rpryy1K7iubiKyiTTbqAor+coKsQ2MDqSMjsRwPw4zTLC5nnm+3yCNbKWNEIXLzKFydvuOK4MUlUpK6t1f9dTCs243todM8pW4YNK32O0AjT\\/powABYj3Oax769Gpao8aGPYiMUQcsDjaMds9+9TX0aiyISRljKFUBOOuD3HXj86oaeIbW3+2CNSqfu1ZTu3P+PJGMmvHpU0rze+y\\/rueHTerle7KFo32XTdStyuzy7pQCD\\/EU54H0Pbua9D8DSaRBocV7ql0\\/2y72BZjH5ipCoPyr2zkcjg4HHevIjFef2tezCKRYDkqqqW3txg\\/qea9K0uHSY\\/hILu4vJbe6YSylGYqJX3lFKZXkA4yBzg5r6Rx5qdu59HSalFF7xbqFjcWS6nDPbG3tFVHj3AyFsHLBeo\\/H\\/wCvWXo2qWS6hZSuu+VnBiZuijk4461W8M6XcajqVxpP+hTma0S4M6uxVFcE8qByw5yCRzWXfeE5bG\\/k+y380UVrGZ0kVSSy4yGCk4xnj6CppQVK8UaOzPUrrxBY6lLKZLgwXHQlmypXr368iuQ8UR+KNPnma1vo9QQhWKxKvTHGRkk4BPNdfq3hvSToVlqul6ffXXkwxvfXCtJtnbKlkwCQGx\\/BxjNcky2r6t9t+2SvCjk5lPG3B7+ntmm6cad3ZXKjNy9DyaHRomR3u51tEEYdnc+YSxPGADk\\/\\/rqBI7O0vljMbXQWMMeBhiOT36c\\/pQYLu7KyxRTSRKQC5GAwUdMCpI3UaELhABP5\\/AUDOAAMfr0rsuedd9Xe+hSvzbpeKLaM7ANzJIfkB64Ht0qiqtJNiNQT1wBW2EguNK8lLeM3XmEhxndjtnt61Jo2nqNRMVwYmCuEdT\\/F83r9ePei2hoqijF36C2kJi1KN5mJfaQQBnHbk9jx749q3ftMUO8T24UKuwJ6H1zz1zUklvZqdrx4PITH3lyeg9xWffXS2reXMIZmcY3OvYZ6nv3qea+hxSl7V6G5plwom+SRzPn5pAuGyexxyB2\\/pVO4uLuCaFY3E0qOQoZAFQY9Vx6Ede341naa32SB0ilnkUlW5lO0KR04x7frVhLiKaWYQOkjGMKsZbIJweAenXHHueajZmbpPmdtTodEtjLDcW011DEynEXmMdrrycgccZI46f1ma4aO1BAiBY5JjbcNwPByfp24rlZJZbeCDdYyGdkAG0cuDyCQP\\/11asLi7uGOnwmXzZAVzOTvQcg445H5n61nKLuc88Pdczf9fedDfajAHkmt7kQnO5bbBZHboWx2P+7jvVRru0h07zGaaV8lC53AbSOTk9MZP4VngTAPAkqxzLlBJgZz1HOBkYPp0p8u8IsefkTlkLsd+chgDnkj8BWPIkOFKKVmy3qN+jaHZItqx2MsgbzMbwMY+XpgAd\\/XisuG9ljmVmGVXmJmAAB65xnuTz069ahu4gbB7p5XjVAI1AySwJwDn24Ofaqkkc0FxbjduWL\\/AFe4DAHUHI6nrXRCx006dla5vXU9no6RPbKs8kkZ3mAgkMoA3bQeAf5g+tcjNqFzK11c3sU8vmqQpkO3DdmxnHHpjua6AGwu7N8Ro8zgly5B2YI5yew96x7uRbpY7UxiWdSoiccKBxjv+GMVtSfKi6KSvda9ylnUpFRYUl2lRIVJOdwzyB+lXobqU3YkuUjmwOFl+Uq3TByD65NWTPZ+Vc3EUKNICGIZstwBwPxzUckiXN6GHmxMEJMbgJ3z06H\\/AOtTduhq5uW8TR1O5\\/s20ihBjaQsrb\\/LKrkE5PrWVc3ljdXRmEksN95gHyDKnPQ5P0\\/Woda1F7iKNZj5iRPhMNj5cdPasaaaNgSsSbs9fb0o5L6jpUVa73OhNzLJgs6m434YAg8Dgg+3cGkk1D7LBAHdZZI0IVgecHt+ArBWd1JZAFLDnjNNBy24nJJyTVKPcfsYmjNqE87hicDPoOlRCTJzVXdxzxR5mPer5jRQS0RdDnuaXz1U+v41nmbNMMh9c1PMyuU0vtZGMEimNdN\\/eqhv96N\\/0pNthypFxp2zgHNNEpI6nNVd9O3fjUjsT+Zxn\\/IppbNRA80ufWgB5PqaQmm54pCaYhSeKTNNz3ozQUOzSimAkUoNMCQUuaYDSg00wJAaUGo804GqESq2KkV81BnilB5qriaLKufWpUeqgJqVXA+tUpMhxL0b461KLnAxWeJM96A5NaqrYzdO5ppNuPWp459owKyUkx3qRZTjrWkazREqSZrpdY53YNPW8bPBrH8w1IklaxxDMnQRtJdsBjdVm3usnqawVkqxFNjGM1vDEGM6COkiu8LkE575qSK6JHXOa59bogdak+18AZBNbrEGDom4Lza5PpVhb7cFwfzrm\\/tBIOSetPF4RgbulV7dE+xZvvefKxLY9KzZrw7shsVUNyDGeuaoXE2HNZVK9kXCjd6ly4uSHJHINVJbg888VBJNkVWaTINcc6zex2QopEskx5NV3fI4NMd8momPcVzTnc6IwsP80g8HimF80xiO9MJweKycjRIlLAdaQsMYqMsO9ITilcdh+QaYT70gde45prlc8GlcaQrGmEmkOfU03cR71LZSQ\\/dSZzTCwpM+lK4yTOaO9MBPelz9aQC7qUMabn1FN79aLgTB6dvqvzS7sUXCxNupdx4qDdxShqdwsS7jQHNR7hRuo5gsS7zSFxURagmlcLEu4etBaoc0mTmi47EvFNP1phY0m6lcLDitNP0pC3vSbqBi0maMjPWj3oEITRzQaSlcYUhNKRTcUAO3D0oyPSmijNADwVo4poNFMBSeaM038aKAHZoDfjTc+tJQBIr45BNaVlqEiEAvuHo1ZFKCc+lGxLjc7Cxu1374WEMh+8p+639Kk1PSItQgM0MYjuAOV7N9K5W0vHgI\\/iFdBpmpglcEsByRnkVrCSejMZRcdUc3dxTRloZBtI6hhzVVGczAuSMkDr712mq20Oo5kVgJMde\\/0NclqFnLbv8AOCPQ+tROFjWnNSHTGOJkeKRjIVO\\/j5fbBzzx1rQTVrgab9jEw8pG8xFKAkMQMkH\\/AICPzrIS5dpVMgVsccjnFaltYRX06W8dxFCrgkSPkqvBODgEjoPpmotd6Gm25oeIbE6f9h2arPeR3OnJdYcFRGXXJTGTnGev6VVN4L77Ja20EjCG3IZVb7x5Y5PtgH\\/gNa3i\\/SriAWSPcW0wSyEKzRyFllxwCBjcOMfeArlUVbdY7qOTdJFIuU246YIOfrn8qSv1Atq8kti1u0M4iEu4kRdCR8oP1Nd98LNIsIoJNW1VbgWsE6Pg4G10y6KCecEg5\\/CuW0zT7XVLgW1xqCWzyqpWZyCkZ\\/u4B+7\\/ACGBiu38KS\\/bPCd54YtIftOpw+a04RxjJIQMpGBsAOcg9aJpWsLc53xAs97AmutCPs0qyyxwu2QqBwqoSenH16Vz1\\/b2r2TsqJFIkSmNACxfJAHPuM\\/5Fdb47ju7fStG0IFI1SzIkhYkMSPmO7HToCO2a5XWrqHU7kG10kxhokXdBzwpZQcY77l4z2HrmiL0AseB72eCZrd7Fbg3DqqsfvJuB5UA9TtIz71d1i7srD7Aiwo8kqu1yrr975ztHA64Pp1NYGjX09tNNMkvlSQ2wCNtGQcgD8eaj1KRS6xk73hjBYnggjn9SaFFL3ieVczfc7r4c6XNd2epX1tCY44f3cg34WMnPOT9V\\/I10lk+oy3SKNssFpbs3LcKQvJ9OvevPPC+q3tv4fvbFEcWxnjlk3S9e2MY6DINdpYX6W2iXFg8rpc3A8sDbg7SwwoPTABOaFBOV2JtpHO35drmfVrKVRIzZMeThlzg\\/wA\\/1qXQYdRvbuW8YFra9cuxkjJ5V+Qp6ZJznHpVfdC1\\/M09ux25hjWNvLI5zzjjsf0pbHV5bPTIEnuHUQSG2i2tgKWyCxAxj+I\\/jU1VJ\\/CiJJ9EdHqMFtPqAgnBaEMJI8rjy269ceuea5W2BhvFQtldxZlwAOO59ecfnW5DqYjkuLuaa5uE3Hy5QP4yMZPPrz17dK5fVdSSB\\/N8ol1UIe24kZyf0H4Uk3Lc0g3saljqSW2u6c0nlH\\/TFKgA8JnkHr24\\/wAa9ZguGW1vAky7JDtCRyfd3jPTsOcHpwa+f98097ZzIHV2XzeDyTk8j8RXsHhm\\/trjSlsLqUR3EqAu5y+N27BHJz9zH0A9ayqw1TRcdx9lZxQXFxKtycmcNPIo+TeWcnDEdFPGcfw465xLrl1cW\\/iG4ubWTy5ZYERVYMFJRlBz68En6kdKju9L+2TXlqJ5XhijdotrFSjjhhwfmGGbp1FYC3F1YXtylzegxxgCDeMDAZDgZGc4T9KL9CInStdzXt7pJurlWmUtJOZFwBx049AyjjvxVfxTfwtc207IoRGKMqjO9dynr3Py0apdx3mpJeCNwFttkbxPsGVAZskkKRllzkY49uK\\/gG0t9S1GMXUvnttaWTcF2nsuAfmP3h+XrmsW3zLQpybdjd8T6tJbPBZyRlSA\\/lxhchI8Y5x7H8cVieEILbUdeN3vJtIUldnBxk7PX8R+daXjp5TrBNlLBc\\/Z7aQToFCbMjgk88AcheehFWPCUqQ+Gmgzbo8lnJKssqrtUnBAPX+70966IxaepSd0ed6v9ovXjWVM+YAylRn5exwOe2a2tNtpLiCDniFVAIPIGBn+tY2qXf2XRotrefduojRc\\/dDfLn867Lw0ttBo9\\/c3JACRMSw6gBf8\\/lW8UTJs5P4n6tdNZw6PCD5m0TXD46LgEZPvXU276TdaDZNeI32kBHV4mEbJt+6ynuCQc9a4FmufEd1drZiaNJ5N7qzABI\\/MxGDnrwMdRXpfhrSLi20qyto4TMzQs4cEHeCpwQRg9+Rnsa48RPlWncfM9kZ1\\/PDHp0t\\/cSXEd2GKXESTMIwSM7guMA8dB61ppaQa14Ahu4ZGkmbfLnG1pAgx098gfjXL63PZWNoba5W3hu5uUSRdxzypIXp6Y59a6bwZb3P2qLT7S+DSfZZMYACE5ztx2PQ1zU4qN9\\/m\\/wAvIIwt1OHaR4rxIcypNIMLC3zAHocn8KsvIGaK08tFSOV064APbgf7p61bkSO31G9a7lWQrcMtx5WCSuCQMnHOAvTHT60RadLbeNYo2XytPjjEy4JAlVsHHX5uuOvQ9sVyVqSjFzfTU5KuFjG8zC060u5NP1EsqSS52wtuwVxgnA688frjvXReF9P1jVPCl1otzdi3kQLLBa7wsbBVLNkEcOQCflxkZzXX6fp9nua5mAO7BwwwgVTlcD8Tz6VPremzqsN1pl3EwkljkZogFkC8BscY6dveufDZzB1OWSsv1MMPi3zcrMDQZLfS9bvoIZkIZ3giMLEGTaB8wBGMcZ5H0qPR7S4XxTZXc97cD5\\/K+dNwUgYAIP8Avd63Y7RGu5buGMYd2ysRIK44APOc5PUevYVrrZy3lvDpltD9pMsm93aUKUGQWYH8cfhQ8ylKqnfQ63Kbdk9Dc03xpe2NpNYxrLbGyBZIpIFKXIDEb0b0JxnOcenevOfiJ\\/YmrW82oaZP9huFIeeDywBNIzHeRnOG47cHjjqa6W8gkilubG\\/2yG3g2QP5QGwMcncVw2DgGuTnsrCPS5be1jMlzvy88uSQe5A9Bx69K9apj6c4qUbu\\/wDVzrpU5NXWhwOj+UuiKqRspVSrZT8gT05rnV3Wt0WjjZCh3ELyrc\\/ocdP1ro9RvIrd2iTkGQLt25ZP0I7frWRMkyXawXiy+XMMRuMY579M\\/hxXZB2u+542G3lJ9STSzGJIWto\\/LkdgfMf72Rxx14q\\/FLbwwMhu0IA+dGT5twHJ65A71ihXMkwDf6kHzMKcYHuMY78Vdthb3FvJKpHmqCRCCqgDHBbJ5GB6ntVtms11YmpaugRFhUlk+Zm3bgucdP8AIqi4W5gwPMMzfMcjI554GOB07\\/hTUuhZpKHhVgz5OCrMVHAyecD\\/AD9EtyqWonbbE8h\\/d+ZnpkEYyPbGc1aRrGCitERxzm0nILhx0YgEMcew6YJ71o2M9uiIp2tITgMQABk8A1FdXTSBpVEIZyquiuTtPcjIP9aktIo4yZBDLtUKUJlA57847D69KnQmVmtSFI2jfEksjZP7l95KrznHP\\/1q1LMXXn\\/a1l8mchlWVWDfLx05\\/DBrLuLqykAEQ8wZBfIxsPcmpbO6EPytL5sZIUkAZk+bjB6\\/h6UndaoU4OUdS1JPO3ytP5rl97gjlMHGMjvx0pxjMl5IYF3q0bSAIuAGA9B+H4npVBp7iVHmIxCpyA6nIJyPx\\/XpUaXIWR+UwjKVZGLbe2OvT86XKSqdtjXnllkkitZA0kc3zCJWIXjrgdjwRk9axZZrjzXB3ww7jiNuVJx056irURSeSWX7UCFyeG+bJ4JH\\/wBaqkt1LAPLM4ZSPm3L8xP1ppJdDSCtojRsbU2FvFNcKkoVt5O7Iz6YNV9auHu79J7RwuECgYzgc\\/5\\/OqdzqCrbYaUvvJPltghfpis5ry4lXy1IVc54GM1au9BxpScuZslmPkfMku5j833uOvp3pkmoXExXJGVzggev\\/wCqoVh28tx9adujQcHJqlDub6eo0B8YcnHpmkAUemKa8hY+lMz70ORVibeByKQyVHmkzU3CxIXNJupmaKAsO3UmabS0xjgaM98803NFADwfenA1GKcDzQIkGMc4zS5FR5456UueKQrDiT0pCabmkJpgOzRmm0fWgocDS54ptKKBMkWnCoxmnCmhD6cDxUa808cCncB1KKbmjmncCTdilBP0qMetOzTuKxJu4pVaoc96UNTFYsK3PNSK2KrBuKlRqaZLRMGqRWqvmnqcVopEOJYDHFPWTFVlal3e9WpWJcblvzTgDNAmOc1U30u6jnYuRF5Jie9I0vPFVFbFKzZFV7Rk8hcScg9ajmck9arbyKduyKHNtD5LAzketRs+aVzxURrGTNEgY00ntQTTGP0qGy7A3FNJpdxHBpp56UikBwe9MORS\\/Wl4HvSGMzmg4pTg9OKafTOakYhIpM0jLxTcmkA402lBzS4B5pDEFKRjpzSY9KTJFACg0pwehpAwPakOO1AASQe9JmnAdjQy9xQAgxRkik5ooAUNS5FMoyKAsPLCgNimd6AfWgZICD7UjDFMJoyfWgQpJppozSZoGLn8aKTNITSAUg0nNGeKM0ALk0maTn8KDSAXNANNJozQA4\\/WkNJmgHPrQAtBNIaSmAuaTNFBouAoPvRTcUZ4ouAuTmjNNpaAFzUkUjI2VJB9jUQpePWgDcstUDYWZirYwHHWtaGe3kURX8aSQk8sP8e1cdnFW7O8eI7S2VPGDyK0jNpmM6fY2fFnhqG1RbzTZTNauOp6r7Guf024ayugWUMPQnjPrXU6Zq6rEYid0bD5om5B+lRar4biu4ftmlyBweWjzyD6Vc4qT5oCpzcVyzM+W9aTVWjYo0YYB+25s8t9efbpVa9js5bdpIXdZQRuVx29RVQRTWUrB4j5o6EkgqfX\\/wDXSy77ktMyjIUKVUcjA64\\/Csnc203JpjJANpYtJnaXU+gHIrp\\/hrr02ia\\/c3zyeUJ7d7ZT5e\\/Bfpj24\\/Wue0mKEtJBcwu2UyrqcY55P0xVifTkhth5cuY5Fzk\\/8s2BGR+Wf89Ztcq5U1zU7m71a4uJ5pZPMk3HJwT6dPatS+1m31DT0jGnwW0SxLGAigFmHLEnH14GO1Y81rOrlXjbsDznAPempEIonZlV1KnbuYgbuOOOpGc4oV0DsyGZHgtk3cNKu\\/Ptk\\/mOKjj2vG4zmQj+IE856Djr0rdhs9OFqp1VrtGWMBGVVZcEHGACPbn3ptlZi5glj06Dz1GHIjYeYoHU4Iz9MUJXYXOh8GQrL4SmKvGjmTbIjKcsPXJ49Koy3cj21teT+WDbuDMqnG5S33eO+3nFZtxd3NpZvp1vHcQrK+94WwWCjpk4z06\\/\\/WqwtmIdMjkkkjTBSRiegGQce\\/BqrdCLdSWe28mCW4jmZBH86jOQ5zj8+TSWdtbX1uzXM8yvIRu+UAHBGCM\\/jnmpp9e066WRwrgRDGHPD4Bwa57TtUNtq32xrfzIwxfy88Drz+tJtIaTZ3uus+l6XZWzS29wgbfC0fzbSScB+2c4JHPT3rE1DV5tWvJRcXEUcbOvkyFMKpGT0I4Oe\\/esvWL+XUIIYjHsiJZm2kHBznqOuMinXEapophe7tNyEyJGFO7PYlumSM9+1Yqklq9+\\/qZezV03uQarIttf280SIjiMNIY2GMnjtwARzgev4V0OifaN0d3bzyRrvZFaMk5TGMcdx8p\\/GuT08R3sqpJHLJOeAUcA4C8AD8q6jw5dl7SKGSQBGYkeYMIjBQGz37D8qdnsi3orHscUcM+mzy3O2Jkjkxtb\\/VuxCclv9lgfzrjrnam1zMbqQJIUWdcK\\/UA5zk9f160+PU59Ot757e2F5LqGxf3g+VmIALZyewNKdSaTw+ishkliA2\\/IzMjYUFecfKNoP49Oa55K3oaL3i3qemhNKla9vrW1uLLSw\\/lmQESbyoAHq2AOB6fXEnwvtE0nRlngxJd30whiXf8AKEYjOAfxPAqsX87SIoY442SW2MeZThFKgEkE9CB0xg81DPqcFje6Q9ygt7fTp5WLBDkkDGePoBVQdrkWdyxq8TS6RcuhMb6jqIiZh18pRz\\/Ot7R4g+nXabIhBZ2mS4UEuWO0DJH1\\/KoJdKOqz6Za3Lx2ZMEslvsm+UzMMpkddxweMGqtpLdW+l3FteobeTaGZghJLZI25A4GSD+netYT7ltI4eT7Jqnid08qSIRSear8FXXcAo46cJ9KPF3iAW+kXGkQRqvnyne+efLGOAPripLW0uPtT31u6hY4o45tzH942ABjvk4zj61U1exlt7y4kaGOQJD+\\/bAkVN2QOOmcN7Y\\/Cr1HoXPh8l63hu51GwvIopLcwk27RBnlUO+MEnjv1FemaNrUz6BFfRs6MZXRIjlAhCkcbeAx9xivNfCUeqpJqOlaPDBLcSvHGHdCDGNr4x9AD+Wa9F8FaTfWngmWw1Rd1wlxI7NyeSc5BzXPXV16BFLmucF40BNpDqVzZo80qskgcth2bOGHX8M1reEtOtNNs7W8eUrK8geJQvzBVA\\/LIwc471b+22C+IdHa6tZ7iCKfc1rnKtgHbznghue\\/brUF\\/JttFE6pulBeBYG3fIVAAGeRjHp25zXl4yrVjRtDd7+hhi5ShB8m5BaTJc3d75rxs0MvnyqVAZ4+uMDvwOfwrK03W\\/7R1qSVIo0VYwrOAMLgkAc8flWPLfTQ+Jp7q3DhEiWOVASMlhjBHXritXUtIlfw3pkNrKsU024uFTh3yc447Y\\/OtYwjKlyyerRNL95SUZPU9QZPsEU8MUCzMiFV2FuB\\/d6YBBGPrVDwzemJFtrixESk7UhXkoB\\/B6Zzzz26VFpVtc6XpUUl3G0iywqTMefNckZJ5xyex7k1S8L3V7PrKaPBbxmMOd0sZ2SADHboR154\\/wAfAp4CUYzT1t17kwwjgnc6y0awF48MzLAqYwFAD98FQMcntVpG1SG0MulxRwwsxiYO5UbmYDcMen079ak0y0Es2+7UeZOMNtAbam04y\\/8ACRkAnrV3w5BEusL5Mkj6bAM3Lb2YYByD+JNYUXFSszqwcFHfc5+6tb69vEmSXZcxBVuZSu2PyznvgZOc\\/nWjd6PBaWk8kksBhlAG4HaznIyMDPOPb8a0Z57WTWpLWzk+SHbK8KBSCp5UjIB6ZBHrnipNRhivHURROsgi3jYNwHXIK54PTt2rrdeSSpvSKPYhQjrJHzZpW6NrecWX2m3nVlYybmZHPdSvYep4qhLIt\\/df6bPJHGnzMiJgA54UE+3eup06+bS7jy7uxVoRkCdUBTacZwRnFZl9e299JPa2VqJ7ZCSCzhMnAOB79a+ojVc5PT5nxtOpLmvy79f66nLG4FxrSrYRGJN2FXg57Ek47+lbtlZ2szjz5zbzRgKp37SenryR049M1hR3SxXc72VoFmbg7juCc8\\/jW1o08kqSXdxOn2mYbYyvzHOMehA7AdveuiV0tDrxF1HTT8yOaKzlS5t0dDcFi0cqqVTPA2nPHU9euc1SuoBe3cS6jMttEBgKGyAAD0Pqf6iui1CwS2tGhV4GnkXO5lO0+ox9fSse5tbSKAQxQLLN0+aXBQ8k+3+etKFVuPKtmZ0a8ZbXM+6umsrWa2tJoJIJcqpdAJMdD04\\/E0zT9ReCb7MdzQJncBlufX+nrVi3tza3Ls8Lsqploj8wXPTkH+tSm3tWYkQOZyuWBBY7jjv\\/AJNVZI6rxsZN5GVgEsE6BZVwVD7mY+\\/vUNirBNzs6Y6FVxitExPBsDpGrsCshwCVAHb3H9aZL5rWnlghg\\/JRY+hx600UpaWJbO5ZLfMLYl3gYZR+YP07U2aVoiJsxMjE7\\/n+8TjgjrVGS6LQ4ZMsBjc7E\\/lUMkq+UqMjHJ5J7\\/1q0g5NbltZdwEqCJSrBthUY44qtdXAKMgG7J4z\\/D64qGSXLbduwCr+j6Pc3x3IoCdee9aU6Uqj5Yq45ONNc0nYzVjP8RxmritBCnAy2K0brRLuFS2xGBOM5zWRLbzhiCnStKlKVLRqwo1Y1NmRzStI2SeKjzTnjdPvcVHXO7mySFzRRwBkmlGCM9KQwopM80UhC0UUUwDvRRRQAUtJRSAWlFIBzS1QC5ooGKM80gCj60E0hpgLmlpopaAHZFFJSg0CHjnvTsqB71Hk0ueKYDwaUHNMBpwNFxD80uaZnvS59aAH5opmaXPNO4C5p2femZpw96LgSKKkBxUIbjing1SJJQfeng8VCPrUgNUhND80ZpgNL3p3FYkWgUCii4hVNOzTaTPWhMLD91AamA0hNVcVh+4nikbFNJ70m7jrUtjSGmkPTmgnmmvUlDSecUZzyDzTTz1\\/OkAwetIY9hxmmbsU5jkZqJiKTKQ4kE0EcdKj708GpuAZ29DQQDyKawzzSLwaAFxxTelPyaaQR1FIBAR9adwTTCpHNKoPrQMVk9KQcUuD60u0nqKBDc0biOgoYYpuaBjiQe2KSk+opc0AJnikJpcZPSkIxQMM+ooNJnvSjmgBB70Up6dBSY70gDPNIaXjFIfpSASlzSEijrQAtIOelIfSkGaAHc4owcetJnPrSZNACkUhBoLHpxRuIoAKKCfpmkzQAvejmgnNJk0AGaSikoAUUZNFIaAAmlzSUUAGacTTe1ApgOzR70gooAmilKngmtOw1aa3bIY\\/nWNShj68U02iXFM7hbnS9dhWG9CwXGMJKP61z2taRe6TIWCnynGFkXkMKzIpnRsqa7HQ9TZ7EWuoRmWzcbdy4O01tFqpo9zJp09Y7djkJJWZVbeWKgqAx5UZzx+Zq1HNd3olBAby0yQFznHOKva5ogg3T2jedAeQw7exFY+n31zpt4Lm1ba4BUgjIIPtWclZ6msXzLQ0TITF5rJIC4B3McYAAyBjr\\/n3qxpbwW98k9xYreWyyBzHKcBl7rx6jv8ASq1ndh1mmYxmQuAyMdvy85wenpReXKPMJcSMgIMWOpUZ49uSam5diDVJEimltXV2XdkfNgD0+pwaXS0kivI5c3EkEX3ljk2OFbsDzwfp3qO+t7n7WYpUKc5AI5H5VqJo+p2Nha6gIFUXTYhlU9SpIwMHrx3GfwpWaC6LEekNPcf2hZTo9ud8TNPKC0b7dwU45yRwD0zn0OMXULye6ZbaY+WFbndnJ+taeixJBqQN2fk3EuE+Ykd\\/0J6VBr0ulXHkTRMw4aMnYNzgdHPPvine6FsyhbeVMhhYbvKG4YOAxzyTnrxVWV0RSi7TnrlenetARzXLRLaQeZKyAAImflGeSD3wM09bOCW3Ny37tlIK7SMLjGQ2MMD+HUilyuwXSKzrFZ3iB3cxmAMCBnDMmeOegJ9e1WNFiu767ljSCWWNEYfKMhTg4y3THv8AWs4x3FyiskcjIowMAnbjt9KuwQC4VIVvvLYEKinIC+pI\\/Ht71GttBPbfUqTRmARlZEfcN5EZ5HJ4Pp\\/9etCwvJUt1jUBkDqyktznGMfoaTUtKuLOaOO4uoWklBwXOFC4POTUGnQhNTjtm8mXLAM247dp46j654qmmtRtpo9T8JJNrMFqGkaLylyz7gzs4XjP4A1e1ljbXokSKB7OSTJBIdSRjrjouV+mP188la8jhVLdWR4SHWPcQz5HOcdevGe3rWtoGu+c9jb3rgxvPtkikbEeCe2MHjnvWTjpoQpPcpavLPfZSKGdbfzWASJiYyoY4P5M3YfrXVR6NcX\\/AIaiiO4RvZHyiT828Lzj64qOPTo3eO3ktZYLSJ5C0obk4YEcdQOTwPUCuh8OXmntpt1GiYeRibZ5CQR8x47ZAULkZzzUJ9UEZcxestUX+0ILlWDpYIqSM2HJkKlCO\\/OS1ZdxqFncJq9pctIUt3DiU5xtUDpkYBLDHvk8VBHY3dq9zYNbgzTXIeWbzRlyVBxjqOCcE+uDVg6bp0vm6TaedIlyGlkkVi7LnIUH\\/gW71Iqoz8invdmXFpgfRbBoiIY75\\/Nck8oq\\/Nn2woNaSO8MVyi2ghknjEkYmkGX9WHT5jlfXrnmq9zDcW15psU0DpZo8kYO4nzAi7RuGc9SPwxx1FZfibUIl8+6VhLcmT5lYEfuwd3uPy9K3km46ENvodl4Z1lY4b6+tdJeCMTSfaLmS3xJK+VUBGJyBk9+xPSof7dOueIZoIWmsohAwXMuFkfO3DDB3c+mOoweldu17pMOnWdpazQwotsiR4b5FIQYyPTjFeenW7k6uk3k2wmSXcXH3FQg4B5IC5IrKadrGsbbiQ3VtbBbgQiILL5LOyuDjHUYB7Zz2wKzbyOKHzpmuWuPszsVl3jGcKAAeuMseO\\/NO1MxfbNOkMheWa5j+VQWUDJJYkdQQpyR2puq6XqLaU9kjJ5dxeGRTBwoLDdgZAwBheledWSqLlvq\\/wCmTNKV4nA6ldiPWYZbechLw\\/MxXJXJxuxj\\/OK9GnvNCsNFW2aW83iARpKPl8lzycjG4AtnBXI6c15PdymHXFiuUKC1nxIyc9OoH5f1r1W7ea50G1s3sfNtooy0c1xt8xOu3juQeTjsBWs4RpxjcVGMaSszpNWMS6LaW1vMt1FiMtLAuEPzD5sg4PIbPfrXOQbk1xY7OITPK+wsTnowCgZP4n1\\/KtqAxnT9Oke4jIuwZBHDEyrhS3IGCSeCTnjnrniub1QW8+pyC1YjfNEcplS3zruH+fWop0Y3sdUpXR6bHKLXUJreAPEs1usgmd964UHf3Pr0qfw7GdYv2fT7gyafC5S5UMRHlDnYwyAck5Dc\\/wCHH+LpL+1v5dPiaYLaW7lHJx5ncpwSB271c+Fk0y6Nb3N3dC0VJmEru3ysQW3MeRn7369sVwVcCot1I6M3puN0ak19M3iy9jjvbiKSKMLGGbcIwF4jBYg7ec8e\\/rWxFcC5miRnkaV4gz+UQoXPfPXPXOc\\/jmuN12axh1lF0a7i8t2Y7z8pIUZY56EnkHtzWnoE7aZoSalftDAtwzFpcvtWMZAxyT09+4rnxFF8vObqo7WieWaiTGJI0OEkglLr2OMY4rlr1Fgs4vJUJ5gDsR1JI5oor6Ghsj5PBv3EWvDdrbzLcCWJX2jcM9ia2dQVbPRWntVWGRBGVKADG4gGiilVfvpeZhiG3XSe10Y\\/2u4jt7xlkOfMTkgHGcA9elZzTyNFG7FSzR5OUHJ9enuaKK3glqehQirPT+rI0nAmjkeTLMCOc\\/7Nc\\/c3dwLpysrKVJxjiiitDeCWpsWWJ7eF5VRm2E5KjrtP+FZQA2Sj0U4\\/76AooojszKPxMqyO3mlckheQDVeYYmUdqKKt7HUtxJP+PhfwrfhZkjVUYqAp4Boorop6ORlV6FEXVwZcec+B0GfWpr+V1t0CtgEHNFFCk+V6isrox5HZj8xJqM0UVys6EKoBBzQOtFFDGB60UUVIDqX0oopiGmiiihgxR0FL2oooEHfFL60UUAGaDRRQAGhetFFAC0h7UUUwFFKOlFFADh0oHSiigBaeOlFFBImacKKKaAKO1FFIAHWnf4UUUIBy05SaKK0WwmPBOKeP60UUxC96enWiimIeKXtRRQSHakoooGKO1NNFFNiDuaa3eiikNDGpp6GiikykRntSiiioKDJxj3qJqKKTBCCnLRRSQCU7AzRRTAUjml\\/hNFFUgGfxUp46UUVIDDUsRJU89qKKFuDGk561GwFFFDBAOlFFFIbA801Dkc0UUANbtTh94UUUhjj0pnaiimAnfFFFFSAhptFFAAelIetFFACkcUlFFACUd6KKAFoPX8aKKEADvSUUUAIaFPNFFACmkoooAQ9qWiigBBSnvRRTAX1+lJ2oooYCnpRRRQAd66LwU7NfvCzExtGSVPQ0UVrQ\\/iIyrfw2XIHZNRe3ViIixGzqKwvEMMcOoypEgVfQUUVVTZ+pFP4l6BpPFldjAOYx1Gf71RR3E0kMYd9218DIHA44+lFFRLZG8epsawqyRQXjqDcT2qySPjktvZc+3AA4qvZTTNoMqmV9sW5oxnhTwcj8qKKmpuFPYyLi4nnkWGWVmiD5CZ4BOMnFTXcSf2Xb3BBMpmkjLFiflUJgfhk0UVmi2a\\/hCSRdVTbI67GTbhiMbnAb8xVPW2KtdxqFCiTIwo7nmiitL+4Q17yKNjNLHZ3ao+B5Ybp33AfyNO1ZViuI\\/LAXdBC5x3JjUk\\/maKKlbD+0VjLLc3UazyNIAwUbj2q7GPL11lT5R5xGB6bulFFL7IS2Nnwsok1eWF8mMRbcZ6g46+taC20A8MfaFjCyhZGDg4IIc4NFFYXfP936mKf7z7ixo2pX1xBrEU1y8iRgOoPYkkmrtjmDV9OtoiyQytudAeCcr+X4UUVMviZf2jZ8PTzahrls95I0rFQhJ4O35zjj3rf0yNIYru4iGyZY3YODyCU5IooqqXxI0e33GPpssg02wj3Er9kjbB55km+c\\/U5NZniSztn1hy8QbMDqck9Nr\\/4Ciiuqp8LMir4ru7mK5sY45mVEQKoHQDb\\/APWrqfD8cbeF5JmjQySSxxO5UZKHJxn0zRRWa1kW\\/hI\\/EbNbWGli3ZosxIfkODnDj+RP51P4gJW2aVT8\\/wBqYZ6\\/wrRRXHJafeTT3Z57omnWUuuxxy2yOm37rcjqB\\/Wu9sJZLfQb4xOQUjG3PzY+6e\\/+8aKKzr6wXy\\/Mii2\\/xK2qs1rY6fewMUnFucNnIGWOcDpzk1V+Iai10ZVt8xg5Jwf9o0UVdLU7Fub+tMyaHoyA8S2EMkmed7FMknPWsvwrc3G42Jnla1kcs0TsWUnnsaKKzl8L\\/ruWtH9xu+LLS2t4NHmhhRJJCyMQP4QpwB6dO1UtJLXGvx2U7vLbfZwBG7kqB7A9OvaiivKu3Qd\\/P8yqujdvI\\/\\/Z\",\"file\":\"\"},\"menu\":{\"data\":\"api\\/setting\\/permission\\/select\",\"controlWidth\":500,\"select\":0,\"accordion\":false,\"collapse\":false,\"control\":false,\"async\":true},\"tab\":{\"keepState\":true,\"session\":true,\"preload\":true,\"max\":\"30\",\"title\":\"\\u4eea\\u8868\\u76d8\",\"href\":\"view\\/console\\/console1.html\",\"id\":\"0\",\"index\":{\"id\":\"0\",\"href\":\"view\\/console\\/console1.html\",\"title\":\"\\u4eea\\u8868\\u76d8\"},\"enable\":true},\"theme\":{\"defaultColor\":\"2\",\"defaultMenu\":\"light-theme\",\"defaultHeader\":\"light-theme\",\"allowCustom\":true,\"banner\":false},\"colors\":[{\"id\":\"1\",\"color\":\"#36b368\",\"second\":\"#f0f9eb\"},{\"id\":\"2\",\"color\":\"#2d8cf0\",\"second\":\"#ecf5ff\"},{\"id\":\"3\",\"color\":\"#f6ad55\",\"second\":\"#fdf6ec\"},{\"id\":\"4\",\"color\":\"#f56c6c\",\"second\":\"#fef0f0\"},{\"id\":\"5\",\"color\":\"#3963bc\",\"second\":\"#ecf5ff\"}],\"other\":{\"keepLoad\":\"500\",\"autoHead\":false,\"footer\":false},\"header\":{\"message\":false}}', 1694677268, 1694677268); +INSERT INTO `lms_clx_system_options` VALUES ('17', 'table_form_schema_wa_admin_roles', '{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"主键\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"enable_sort\":true,\"searchable\":true,\"search_type\":\"normal\",\"form_show\":false},\"role_id\":{\"field\":\"role_id\",\"_field_id\":\"1\",\"comment\":\"角色id\",\"control\":\"inputNumber\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"admin_id\":{\"field\":\"admin_id\",\"_field_id\":\"2\",\"comment\":\"管理员id\",\"control\":\"inputNumber\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}', 1694677268, 1694677268); +INSERT INTO `lms_clx_system_options` VALUES ('173b5b0f-a658-4064-a143-93fb7a64d0ce', 'rtea', '[{\"value\":\"asd\",\"name\":\"sd\"},{\"value\":\"ddd\",\"name\":\"dd\"}]', 1695087422, 1695087422); +INSERT INTO `lms_clx_system_options` VALUES ('2', 'table_form_schema_wa_users', '{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"主键\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"enable_sort\":true,\"searchable\":true,\"search_type\":\"normal\",\"form_show\":false},\"username\":{\"field\":\"username\",\"_field_id\":\"1\",\"comment\":\"用户名\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"nickname\":{\"field\":\"nickname\",\"_field_id\":\"2\",\"comment\":\"昵称\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"password\":{\"field\":\"password\",\"_field_id\":\"3\",\"comment\":\"密码\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"sex\":{\"field\":\"sex\",\"_field_id\":\"4\",\"comment\":\"性别\",\"control\":\"select\",\"control_args\":\"url:\\/app\\/admin\\/dict\\/get\\/sex\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"avatar\":{\"field\":\"avatar\",\"_field_id\":\"5\",\"comment\":\"头像\",\"control\":\"uploadImage\",\"control_args\":\"url:\\/app\\/admin\\/upload\\/avatar\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"email\":{\"field\":\"email\",\"_field_id\":\"6\",\"comment\":\"邮箱\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"mobile\":{\"field\":\"mobile\",\"_field_id\":\"7\",\"comment\":\"手机\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"level\":{\"field\":\"level\",\"_field_id\":\"8\",\"comment\":\"等级\",\"control\":\"inputNumber\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false},\"birthday\":{\"field\":\"birthday\",\"_field_id\":\"9\",\"comment\":\"生日\",\"control\":\"datePicker\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"between\",\"list_show\":false,\"enable_sort\":false},\"money\":{\"field\":\"money\",\"_field_id\":\"10\",\"comment\":\"余额(元)\",\"control\":\"inputNumber\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false},\"score\":{\"field\":\"score\",\"_field_id\":\"11\",\"comment\":\"积分\",\"control\":\"inputNumber\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false},\"last_time\":{\"field\":\"last_time\",\"_field_id\":\"12\",\"comment\":\"登录时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"between\",\"list_show\":false,\"enable_sort\":false},\"last_ip\":{\"field\":\"last_ip\",\"_field_id\":\"13\",\"comment\":\"登录ip\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false},\"join_time\":{\"field\":\"join_time\",\"_field_id\":\"14\",\"comment\":\"注册时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"between\",\"list_show\":false,\"enable_sort\":false},\"join_ip\":{\"field\":\"join_ip\",\"_field_id\":\"15\",\"comment\":\"注册ip\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false},\"token\":{\"field\":\"token\",\"_field_id\":\"16\",\"comment\":\"token\",\"control\":\"input\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"17\",\"comment\":\"创建时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"search_type\":\"between\",\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"18\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"between\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"role\":{\"field\":\"role\",\"_field_id\":\"19\",\"comment\":\"角色\",\"control\":\"inputNumber\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"status\":{\"field\":\"status\",\"_field_id\":\"20\",\"comment\":\"禁用\",\"control\":\"switch\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}', 1694677268, 1694677268); +INSERT INTO `lms_clx_system_options` VALUES ('22fc7cf5-7d48-4364-83d7-a5a8ed5b9c28', 'uypd', '[{\"value\":\"\\u963f\\u8428\\u5fb7\",\"name\":\"\\u5355\\u72ec\"},{\"value\":\"\\u963f\\u8428\\u5fb7\",\"name\":\"\\u5355\\u72ec\"}]', 1695099996, 1695099996); +INSERT INTO `lms_clx_system_options` VALUES ('25', '阿瑟东发', '{\"config\":{\"logo\":{\"title\":\"Pear Admin\",\"image\":\"admin\\/images\\/logo.png\"},\"menu\":{\"data\":\"admin\\/data\\/menu.json\",\"method\":\"GET\",\"accordion\":true,\"collapse\":false,\"control\":false,\"controlWidth\":500,\"select\":\"10\",\"async\":true},\"tab\":{\"enable\":true,\"keepState\":true,\"session\":true,\"preload\":false,\"max\":\"30\",\"index\":{\"id\":\"10\",\"href\":\"view\\/console\\/console1.html\",\"title\":\"\\u9996\\u9875\"}},\"theme\":{\"defaultColor\":\"2\",\"defaultMenu\":\"dark-theme\",\"defaultHeader\":\"light-theme\",\"allowCustom\":true,\"banner\":false},\"colors\":[{\"id\":\"1\",\"color\":\"#2d8cf0\",\"second\":\"#ecf5ff\"},{\"id\":\"2\",\"color\":\"#36b368\",\"second\":\"#f0f9eb\"},{\"id\":\"3\",\"color\":\"#f6ad55\",\"second\":\"#fdf6ec\"},{\"id\":\"4\",\"color\":\"#f56c6c\",\"second\":\"#fef0f0\"},{\"id\":\"5\",\"color\":\"#3963bc\",\"second\":\"#ecf5ff\"}],\"other\":{\"keepLoad\":\"1200\",\"autoHead\":false,\"footer\":false},\"header\":{\"message\":\"admin\\/data\\/message.json\"}},\"logo\":{\"title\":\"asdf \",\"image\":\"http:\\/\\/127.0.0.7\\/storage\\/upload\\/avatar\\/202307\\/e4a16f2b2b901bbd4ba66569ccf8c0b9.jpg\",\"file\":\"\"}}', 1694677268, 1694677268); +INSERT INTO `lms_clx_system_options` VALUES ('29', 'asdfs', '', 1694677268, 1694677268); +INSERT INTO `lms_clx_system_options` VALUES ('3', 'table_form_schema_wa_roles', '{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"主键\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"name\":{\"field\":\"name\",\"_field_id\":\"1\",\"comment\":\"角色组\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"rules\":{\"field\":\"rules\",\"_field_id\":\"2\",\"comment\":\"权限\",\"control\":\"treeSelectMulti\",\"control_args\":\"url:\\/app\\/admin\\/rule\\/get?type=0,1,2\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"3\",\"comment\":\"创建时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"4\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"pid\":{\"field\":\"pid\",\"_field_id\":\"5\",\"comment\":\"父级\",\"control\":\"select\",\"control_args\":\"url:\\/app\\/admin\\/role\\/select?format=tree\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}', 1694677268, 1694677268); +INSERT INTO `lms_clx_system_options` VALUES ('30', 'asdfasd', '[{\"value\":\"sad\",\"_field_id\":\"0\",\"name\":\"sdf\"}]', 1694677268, 1694677268); +INSERT INTO `lms_clx_system_options` VALUES ('378a205e-f3fd-4daf-ad37-070ed17aca91', 'restaaa', '[{\"value\":\"as\",\"name\":\"1\"},{\"value\":\"aa\",\"name\":\"2\"}]', 1695087585, 1695087585); +INSERT INTO `lms_clx_system_options` VALUES ('39', 'system_config', '{\"logo\":{\"title\":\"Admin\",\"image\":\"data:image\\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKoAAACmCAYAAABKtBT5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+1pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw\\/eHBhY2tldCBiZWdpbj0i77u\\/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDY3IDc5LjE1Nzc0NywgMjAxNS8wMy8zMC0yMzo0MDo0MiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMTYtMDUtMjNUMTQ6MjI6NTErMDg6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDE2LTA1LTIzVDA2OjIzOjI5KzA4OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDE2LTA1LTIzVDA2OjIzOjI5KzA4OjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCRUY5MkVDRDExOUQxMUU2QTcxRkQxRUQzNTEyMDk1RiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCRUY5MkVDRTExOUQxMUU2QTcxRkQxRUQzNTEyMDk1RiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkJFRjkyRUNCMTE5RDExRTZBNzFGRDFFRDM1MTIwOTVGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkJFRjkyRUNDMTE5RDExRTZBNzFGRDFFRDM1MTIwOTVGIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+6OVf9gAAM3FJREFUeNrsfQl8HFeZ5\\/uquyVZki9JviTbcZzYsZOQCxhyM0mABMhMgAlHmFwk4YYEGGAH2B\\/MDuwPSICwDAwL\\/NiBZUKA2WEYFnY3F1eSiQM5iBMcJ47t2I4t2Y5lWbYsqburvv1eXf3q1auqV0e3ZFtll6q6rq6u96\\/\\/+3\\/Hew\\/YMTpVbxxYSIsrGMOXMGDtNDsTMIu2TbqfkZbj9mZAvm\\/C3mZvwCp9rrvnmDRX3V2WfZx\\/PRx3r2N\\/rX0s\\/wpgNT6D\\/51sUriHwwzQW5+kv6azD2v2dzrH0TacdI\\/h07iztK89Xv7MKB5N5QXHJEivX7aUgfUx+vUdjaeATACKepsHWPHJiceptvnXU51n+edBaJ+4xGBJQcS1A\\/duecfUAAz3hbLq7svCX5wDtP4Enfur0icP1maAOh2Bet2y\\/0y\\/fJlbeFIBq4AnAyUHYJXXswLHgPRdgfMSv1NxjPAbgRnB38zYTlreXvrU6MHpXGbGMQfSa5Z1Udkus2tpPlv0CNBw172KnUoQofHZXne3uechfUb6jFZjm3+cd57lbvPOC13P+2w07oMLDz77+4TzpHvwryXeq3yMxYLXpotj4DvZAM03m5+b0z4D1Gk0USHNCoJGAqxlBAGFMcDzQBsFWO\\/cwHmQADwRVA5omQxa\\/9oR3xm4tviSNH6fA1gXtJaxnI55j\\/nZOeUZoE4bpELdZywZBCGGiwCZFc+y8YynYFkl8Bos6wE2kmUt6TstRY2AMQzuAPZk+nyN+ffzpqUcLB9zQLXYKInAMVrrQpdiwdN4KKl2XpCeYeLvA5+aG+dAQy8yh2G9fb6WZSBcAxvnMfGzCyrZQPLugwMKIowL4TtZ6DsxeG33Pp19LlfZ17bOpjVuZP10xpiaBtPkVcvPpcV1KqMEQgaMvLTUxhE7qoyvn5Q\\/M3rfDFCnA1jfdtzVtLgg5OpxCy\\/kLgqBQcdbEOPiinU3CayXCDwNF1ccYNUuLv4AvlP+u5FHZzTqlGtV9iOatwY0nqDpHANJ0IXHlvHFQxA31j8zb\\/UMo06DaeItK+ZRqXyKqs45kVVtWlmgw7KSgx60GC+GZWPYPhPLNq7NI3G3lf9+5IUZoE41WN+84kR6Ch+hQipBnPYUgAeQQhYkAS9RFkRoYC3gFSILRuiYWwms+2aAOtVgvXLFn9OTuCrEcBqFOe2MrzjAeo6GOONL\\/ZIM0fqt5c\\/uH5sB6lSD9a+Ov54K5RyZ8SDOAtcxvo4eWbCZll8tf25\\/dcaYmsqqBdkdZEhsC0ZyXKNKduDHGF8syfiSQ6my8ZUmVCvdayhUqwwGSMaXKuChNr5OoM831T8135gB6hRO7T\\/dWiOy+SYB9lADQNAArBx1stQx\\/IC3wErwFsjRKxl4Esjse9COQkEC8MRwakzkK3je6fT57TNV\\/3Twr75x5UlUIh9y0oyYHwkKG1YFyIIj1yf7i\\/Lnh\\/\\/3DFA1p+q7l7ycyuBU+hlzaTnhzPbbz\\/MuD7nMgbQ84JU9zQeJOUwXgeP0edJljhotHWNhsnQB\\/b1c1GsYYwhBnJUuAQ8ija4o42sK82Tjja8flL+w74EZoMZMtfct5qlpd1I1e4EAwEZ1x1g4CYNJVTDzqjoIbPM+W3WiVB+drOYdQZvqVLYuBfJsfSfLn9f4gFjzHil9ZZWhG8R3WgJYfmY+QxMc2rLsTH\\/0AVAVmLHmnwNout\\/F1y3i+iqUrFFWwcNTaHzxC3yz\\/MV9T8wAVQXSDyxqp0f0KMHiFA98GAlQ9ycGojgsBFoMHeeu1whJtG6A+Liw8ALA2KIRk1OkzWXcArNrD9ByYop8srxpzO0E1s0zxlT4jt9B8ylEdz4DAK2DgY2HzNcN99eBe5z92XJmj0XcY3gCEQSOc6\\/R1vhai7MsYoTQzM4DyKKQigIyQch8EjbXjZXsQOVy4vj2KTK+KrTv\\/fWP9y6eAWrYj\\/Q6v4ryQOW96TJgQQasB9BowAavTTVvm2mD1P4IAmARNQCLeoAFoTZQolhI0xPT+bi2QOhhB9ouJWFQnqLWCF30KG6pf6x33gxQg4U62wESCuDDABBBBCVIxxniPgGs\\/rnMBbvL1iWay438TcPHEAQBiyrQStW3EoiSxS7KF4gBrM+0NlgWs9G2i2k7FJsQw3QTYnroMXyw9rHeWccsUHHjQBmfWXoiPrv0JNy0tExAezoINkU1H2JX1pADoJADILGrB1j3OGizbOeBhxznsugSG2crFLAkFKjIqAhBwHqgVRhyIcCKl0JJP7o3TubZChytnJ\\/KJ5vUGiGdLFhK572v9tHe8jEFVHyaAPr0wH+h1d00b6J5Iz2UQeM1laptLRuCFpWr+Tg5kFG\\/QrvpAshFMRUWoGf8Qghz9ja\\/MD02lAArSgfvOBCZF4N0L7IrYpi968ZaHCufFRn5ar4sWE2AvaH2Nwvg2GFUxB\\/S30\\/T3OOod3trn3GCcYux1vhDkFExxKg+kAU5kEu\\/kgRgHSbDgFvHAyzas2wG+eaxV1WLgA1pWEF7+r8XJPgLjliUXg3vkGrpZTheXjOFebIvpfnNx4R7Cjf0v55HPxptkRiT182fTKzHYeu0oI9U7ROV3VQoV6kp\\/K9Yo8IcL4fbWXnGje8lVzxo\\/1hs\\/B5k4bZaYhUfuF6oUZdkr\\/naFumlugvare1+EEEn8lWsT\\/anldv33nV0Myqyt0QaHO5UelP7yaydbQtozIAcaI5+hTZXBnjMFLhHcP6hADTBV9uo9b0qFIPO1IAeFat7kWEFgKIvpgWJ4YYJxkuvwqqxaAoTYt5U+9DCs4\\/2qv+SEKugwB58pQzl0hs6uklDHmqAiikAW7x+hVmEhLKljHYFIBsyhGQCh1DNHn4xFYAVvQcoAxs9Ziyzw6VLWQ3mTWFCzLW1WxaefFQCFZ9achItBmLdOB4R9Ri9xkVtgx6p2OwnAlb0iRatX7vN8NNTAta9txBjKpwDiW5XiK9mQvUvdhCzvo6Z0KnM4rISWDa\\/8VXiHVvUbl543NHIqBfHlgUG12FVeZVxUvkxhyEFwIpyIM6vCii4pBKOk\\/yvMLuuBlUEYEMMjNLh3jmWBmBREV5VHEeA6sbDpdeixdqmqJEij5p9sHbzogVHG1AvCVX5qnXREfTKtrNgnvFko0pnYY2ZV7+q5ECJWLXTDANTziewPDEgYQ+DxljA4JdBpXxZIfm7wa6ie9l4+TU8nWWKeoiZTctbah9cNPuosPrxySUcAnvprnp8SxcEqxfC1r+\\/XmM1846xIVaHZeEMKaZISIGIxJWgR0An4QUPlxnjM8Ow1gx5osD3l4qSW5SY4kViVQAmRG8N6ZgSbmazzPv82FrrGyluo79frnx99+SUAhX\\/1N9FhXAB3fcqWvLOyF6k5SNwxu71mkA9kxaPKcGpXGcN\\/yMv+GHcY\\/30cDcBqlNmFp+MUTIkGIv4DFJKIMQeZx1oY1AzguxvSMADDAFRCdgITRpiYx\\/cUkRLxb7gg\\/VJ1mE+JAOv8EaK0Xmyf6Lv\\/EblG7vNKQEqbujvp9\\/8ESqg2YE6zFk+QPXDP8NZe2Nz5HD94o\\/SL7styneqs249U9uID0yuUftVJYbV8b8KoIz0v9pVJdkNI8SqpiHF6VUhz7DVhCE2BoGpNAArSgFARa6AcEgZ10GbuT62NUJz+y54iJbfr3xjSDtnshCNik8P8K9\\/F81RGuR8mi\\/LZEghY0k+1cAPWlNZAysd4yqsSzPoV0NTv3K9OsfNlQ448hsh10b4U3Ke2l\\/h+GBD9IquVLDQ1322ERPSo4JrCuWQq2SA1uBsrJVOjG2kaLFmNlI8h+Y3TIUxtYrmJQnHXIGPLjg1EuxPLK7Q4sLI6EycT1VaNy7qOAvmwlPqMKuXISUCthj\\/qx0MmFsL+0UD+lThxIcGC9qADcT6hfwCUcOgkxbTIHkUkl1kwIazuqAKf06AXTqFjRQvq7138UWtBupaTZlxIz6yoC9i\\/yvoR3SFky0So1hKPWb8Zecq0mO7RPdT0MXUIDtt\\/ysk+1+hg5i1qx7r\\/42MOglVZgOwoACsJFN8wMpphxjKshJONohVX4116ItpIh1sMh7Hstl8sm+tvmfJWa0E6hrN4zppfh\\/+oa9dAbhLEgGoWf3bx7RDO4G1RL9wPM7Zn8r\\/amjkv3K2nV1lrGJpmAUJUScPtzJgUcIvioCFIGBDPtkAYCtkAL4W68YclCNOrek4jt\\/sjdV3L1nVdKDixgE+ssiKFKfwqNO1+Ps+OYv4Yq0qX6f694qkt7QIzm3f2tCSGFHNF6xfOfD7Jp39mGSGSwBW1CggAtYC9WUkY9AGrJgnG\\/LJ+k1cZpEEeB1dt8PXkarcUwl4BfbaXablBwisA81m1NUZrvMyml\\/jF93jizjTnpMmIqXLvsaatpPhOG5cRTFqk\\/Qrn\\/sm\\/YaoQYDISBNACwmAjQjH+pewpDMUMYFwfgLMgWrptfS5rN9DDBRpfHXQtW+uvqt\\/fjOBelLG896ID\\/edLHgFKrEAZCkBLKwbF3WexbqNDXHh01j9Ctn0q9FmMuipSQCRMqFQasQnA1YlHkACLMYAFsNBLFSHfBcAaVYCkDFFPcTM49Gr6jv7u5oF1DUZz+OP9J24rq\\/XCZsyKfitWf0nodTFQOmKrpWkG4fSJFv7+tXIrl+NLgJqd13xgqFTmCC4oBgLNlNhLJzMjxFYVrFsKIwbm47Aj1kGdbgQFAwaKwuKM76W0Of3V2\\/qbysUqPjMUu43XZrjErZxRfOr8jCmlsHVDh3GZbOJ5qzJoN5svn415pNebVPkBNhxeGwkUgdeVvDzTUEErFT1gwqwUSFWhZZEWUZbsJrVjZd775vK3eSAtmnG1wk031i9sd8oklFPKoCRT2B188xU1b3MTDE+1YCje0FpifFnnc\\/57ChX+zr6FTLoV1oaCyedc1R05gOWSe2lhCiVC9hQKxUxMBQYtSWdi08MJBJoziSwnmI3s7EkwPoMCqxpxheyM+icq4oE6prcMAW2xGl7bLFM1X9K9oW1bacYA22PgWFI+jMurQ+DWf5Z9GvZYrBoUoj3QzCtz4\\/Vq91U3jYvgoWoNpJAty8BlbtMfPQWO5fV4XgPeB5gIcKwijW+ssmCC6vvGLh8+gDVS5Kuc81m5av+NQ0vuKTrLNYJTwOvz0MZ\\/LIcKE6\\/8mAA9Ewq\\/Kaus99iwVarMusEkvjdkKtM0OilE8b06oKqZIEQsHl7xYvtPgMkh30LZcFfVK9fdl4uoOKzS3tosaAARm34z+qWIr8yp09VBWYCjvEX3SuI5XY77CgCtrn6FeaSYTWnLtw+NsKfMrshhg1DSYP6ESwf9w2N6wBK4VUIqAtQvAn+VCKQXUbgm+\\/3tSHE8VskC64msK40pphNuTE1L+BjrJos1AQ4b0hVtd5hzDJeTYjhPejxrns8wEbpVyhOvxoLJmx2RS9LHmPAEpJAav8psIarxwMsupq1AVimACyGI19if1fMbhnAAwJd4aq7AFmQ7JM1aP7LqQUqsAEl0GpmKqd+ZsAuKg\\/AWZ3Pik1MfHaV9atRkH71wqxLxhmUGnmHPmBR7l1FDLFimFmtYLgVWLBKlgHLZMAiCNpY7CADxX4Juhywus1ZBPChLAtULJvfJ7tqqhl1QIkuk5Z1M1\\/1r4Nk3nHEqR2nwuLKo41qXmDXRDmQQb96erXigDXQ1BlRYB8MGFENj72i0wmpSUsAsJYnC9DPZvUBa7HgSxECLBPHgJ1P2y6zQ55SxxMBWYBBwBbkky1lAipuWsa7GZxbAFD7I\\/dwVrWw8JCq0hNwyZyXsg54NtSTnw9YqyD9GjwOukxmLBxnwW57BMCK7yIKgEKJYSN8qI2WIhBwe\\/mABSkY4Bt2LlqskM3Fy\\/0ipzO28OjYKllQkPG1PSujri0ApHy0vO5Yt8lEXa3PUmtUjN7uGVeXzxsg0+HFsNVepH4NpxNCT5WeRE2O6AfuOVRjy90EYYR+lR1Qkp9WTJNVZWJFhGOPp\\/k8pgSeAzSUWTa\\/8XVfVqCeVGy1L1ZlUnXOwWrlDKnGsap3ziyjy7hkzrjdJbkCbLn1qyp\\/wL12aWC80fsKxvg3UQJsoKkMqoMJyEItRQLNaCAy9i9V\\/YHtJ9NGRWdsYf1ZgPH16\\/Y7tz9cSl3tP7eM3\\/Zf20kkmc1xezqDNs1XOp4Dp7m951YMzQZ\\/Om2rmLTd\\/dBdmkvbN7C9tUWBuKR\\/XXRPNQRQqo4TNkA4zgmBPptcJHBWHWkLpvEBU\\/dLJSWoBLv7YaHuqeRdkHCM0sWKKtkGfKijfSH+Rjk6FvRkgFAjNNoD2p9rtH2UVvbQ+gZa\\/9eOn2z7Dd+bpS\\/L5a5bqVh9Gqc5uXHF3Vbt5egwaiA9DoKul9C6WDjBUoLTOl\\/Cdtcfxz3VMwMtPJlwXTJJHXelQbstqTm22Ds0NgoNgv35+DW4GwYC\\/iIuG2O4rVvdEUUEmPy2gxBR9Uf0rwZShFZ5nlj1q4AMeCH9nnGuIYMdwNk7vZFpDtFxNNvjd43xJYmOg3wf8FFoAPhINKOAONb+b1sjRwXMAtQirH0eLOhIYNzgE54koHLbr2yEwcniT01cF7uC5KsXzz4Dfza8iU3iqmCXj3JnZd5AJ9zV57XONILAZhF9nkotRTjgYbbFjMXjzBqcFbw\\/KymIJHX+xxKSVIRrAyjkhFI5oWMYBr8EoIQXocney0zj98wB3iHafrDj\\/2yaZAVOWYCaX58iG0ivGujJjNNL2lVxOtNPAqDudVVVYInU6GvnL7Z+\\/uI+Zhm9ymyQANtathxw2NUSotMiSOMAL6z1TdDvJEV2oE3q0lJiN2+7EQYkxgAWXTr1xyvghqS7bgW6iW90UAERI8e4rNwOZbiVoXle+8+2PM+aNKVq14+bl5fpjr\\/K7NEwpD5oEpdCeNTCy2wJEWeVY+jpOiscpF1tjQJK0qRSJxXBdUm0yTp2qLrN+s3IgJ35rt0PgMuuohxI6C8g1NmFZTBrVwfDfW1KoyrQGJC70cpueLZs2SFy2\\/Ul+oBdA9B3lWUdzohJY3MJoVr6vJXWzyWwDk0HoPIeUD6aDqAhoFIp4HVMzOhX+QNRBrBQR7XRA+6sqMGZ16iS9uETh5\\/ADYdOb9yXoQE8XcDGdGjBF3W6RtW1ikWmY4LuZYo+n\\/x4RpPG32LqnmPodv5In19JWnO0aKCmdU+tKaDa72OqZidpfKVVy3FbFRFGRVXdKGi40ztPh77KH9UjqUjRqST\\/K2j4X8UBL4ghjVkmg646g1k0t1t2RIunDNpzqIUCSz+cUcL4BaFre5E1r6m4EKUjvJ5BmP\\/XyTcd3zbVQC3C0b80W6qedOCE6aQG5mmmwiJ8qnLk6uL5p0E7PMeUWVIsPJRQlP\\/V0PC\\/hgAf7X+V8wcShzNS5clCuuGMQqmL8kBygK8iwH6PwApTAlTcspy3xV+Rn1GxX9\\/VmoDbQ5ON7sXzhlTjji8ZBlzau4DwNiIyjhKwyjBrjvwBVTg2In8gsTtNUIR7MwxnJL8ogX3O9qvQwC9PFaOeyIss5\\/fx8xcVdvc2WKvJ3S+GDLaEkGpoooLrKs+F8+ftt9toSqyjZEpDUZ3L6YQZ8geyN+fO0P9rmuE4RfZ17vXDE1eu+PBUAHVtAcBarAd21GdCHgwYq2qEVzUZNu6c\\/o7j2Uld6z3XDQiME6tfFVWsU+A59Gtcd0TKFrasycNxKvXrVybevOItrQZqAYYUDrBmTDxqNWHma6aiaYjB6bPPgPmVJ\\/yO0QIJ01FyoIn61dDLf82kX41C9Ot3J96yYklLgIpbl3exfM2ivQLvz938OQqAhyedpiwqVs1T\\/aNQ\\/XvrF\\/e8hLXB1kBPfhLjTJl+NYrSr6wo\\/dpN+65pFaOelNbnqpi4y2KBFt1hBkrkvrxRwbjK465K6lGwTMbVqxfMJxEzGujJTwRslH6FI0W\\/YpH6tb+VQM03Wbgk0CV9US1L5enAZGReZirwKvcJ7fK7SvPg7Pl77HFZJV0aq181XERa+hWaqF+hcP1abRVQizCkCtSnMb5QblzZnoB0Pf+FLqRjiA3MOpGd2Lm+UYjBqrOp+tVoon7VGc4onX79ZdOBis8vn1+IS8kGapHUGTNxw2rczK59U0S64Mx5Z8BcblwJgJR7oj7S9Wu+4eR\\/3n7H9t+2glGLyJaaRX\\/mF2l9J048GFCzig2pMqH6F3de1HcKq1jbgto0Qg40Q78qqu\\/i9CvLql+50PsBbbuqCO7RSfPL75ayrP5iCFQx1EeIMYWkzRECa28HT9uT8lcjcgMT8lQjUwvLUIaLFnXjvUMHCcez7THT5fvy+uj3ejcByaNgUy+LSA4V818N92uFdEJQdUiVkP\\/KXLCioThOkZLoJZ44F7HqWBqpQvvBMewaGzHmTeyD+fU9Ri\\/uNhYamyorSvfOORefalvG3VKfNL7A\\/tH6255deUo+0ZKnqv8LdpMRZCxb1hTyFqUXkjG1Rs1goAAdRoxIp0jQjAKqd8mKwWB+h\\/vm52imEthuqM\\/dcfhZfGTf6sa9l9R9mIr92DMW7iwssA000gmZZlaXejgjE8sjVWwfHWezxkbY3Mlh7KnuYX24GxbALmNhZUdpoGOwtLBzyOibM1TqmTdYngcGCMUnoclv1NB4psP09\\/XWf+pZ1xSg4rbjFtIv+WzwQWYA6qRJ9I+ztYGKUZGpDEDlK7PKDOa2B4Glm6fqpbWH9gnbhRab+Pj+x9m2Q2c2nldJAl4YsKhIscua\\/2qhcYCD7jDOGjtozZl40eqp7cEF1hAuhEG2sPwCDHTsZIs56GbvNnrmDRnzSha9xRAFPJCKijkpwYFjowEqXot3n3Si+bGeQ82o+otI6+MAnR1t2KACiBks\\/rhUf94yoEKA6SwnH56l+hfL48z5Z+Lw5JPsYO0lbozX3VMKAkD47WJnZ41jLAJd6RCBbmTc6iLQzZ4YNufVdluLzEFzIdtlLq4MskXtO7C\\/czf2zR5ifXP3wPxKFUq8v4W5\\/r0ZEmgUIAJQM6MMwCSA+iBVXIu2c4Oc5yF\\/oxlAze+WMq3mhE3Tvi+jk04DurZS1hcuBthSA8ELF63B\\/7dzByFtWaOKx8NVbBuZsLoPjZpzJobr86p76wvMnbUlsKu+sDRoLm7baS7p2mku6t7NeuftYT1tk1jppst2RxR8AySxI+1FMyREAC8zQBXXkL7jZYUbU7h9BW9cvTo\\/Qty0voxdROZzEUhdjO+fYNA3y2kkmKaVKjIFq1pO9awCbwUqm04\\/Z\\/f1P\\/67tt3mgrlD2NsxgW285W4ni2AvJRNBYsEr2YtBzHYNgHr7UupQ5XcEXibGJpph9fPYfnfrHf2YrrZn8VVxkN2J1\\/YRWBd0hpsg66ynmP7r798z9+HaaYuiCpglFHRiwWuckwjQ4nVo9H06679uhh+1ALcU9jg+1OKDUJn786\\/WGR6YSO9fVe6zwlrbVjvGyI+fu3iVWEgIwWpa6VfVYFGMOyfmWgBSF1TSfm+f4c7yd4nnguo+IeE+GRui\\/T+bpkC19LL5m5aeh2pHPQ+xjtXThaRS5Lbev\\/Xlm2tYDhWwEqBR1TxI4\\/1qAlIFUIgCKMQAlKkBChnu093\\/NfPDPZlj\\/sqqH3es4D6PVfmBGpE1k6dhX1729TZxvdo2y\\/EGpKn+NdY\\/\\/+A7+rV1aBoN2QQd6lXzBepQlcE2Rvu\\/madooxh1Jc3tOWEDVPX3p6pOW+oGoP97xxVtrjI0UxEOnqi3Dd47eNYSFeOwCFYLHRcFsCQGVbGbZjWvkilR7A9R1TxTMznN37E+1DPSDKDmj++byJtFt2lrx0IpNOpwKwgw3ihg72H9al3juH\\/f8KohdAMAx5wOVcsAk+av5i3pchP16UA0ljRNaWwem\\/pfP1l3ZEDPrGznS+tfWHfdCZBUZaep5pvpDxV0aEp\\/qL5HgbGfWLf0bMtbZCFGxRdWtLlVf16Lf6BpZFkUM3sMe3CSNca5ylj9066RiTlb14+snJNYZccZILrVPNMwthQ6VFXNhwylODkSweRKd5STaXVbEdyiYtQTWLbO08SpRGW3KFkkJjkrFdvFUKu8DjnAy3sLnGUkG0xRIVWa\\/ucTVxyaUn+oDovm9Ydqs6z9sO6zbu59vFlAzR82reOixrUzVPNFVvlx70CUTaRznRCYLbz98bevYTHVfqIlrhEGbVFcPls1L3Rp7R7zpaKKsdwcfWr2pwZTYSC11DZikpQwgMWGVJkkCyRW3THa\\/8z2wwvWHKM61H9mwjFP0eKuQDX7uWGeaNFG+7hHqULncJlZoc+8x7sanbvX+tuesUSg4s6VnaTblue3+GHA0X+QrPkQItAKKSgR84O8YuQKqX7rsbfWtf2MR64\\/VB6h3feGGFIxwyT8HmvsFvjscDfdF8+e63IBGXtfxheHH6DlndbHe+pxjLqa5W0Wbfedai3UYsxW+VCTvpNnVBmgZdUHulP3F0b1v29449ojVoei1NjA24Zujrjl9HxpyMOvs8Yf6bvHrLrdHGFt6nsDdj5zklf+Jc7qz1\\/tm9YSlr8PgJzuKjEGbyUeDWKeaoae\\/zbuPWHD\\/lp3qUh\\/aLQVneAPZcLoKWQfgun0pk\\/sxuxGy5PODOP0mSpZi2Y8TNvG3dnbT+cYPJWWn+dex3OSAFN4FsTPFnuK7suK89UmeBkuKt023B7HqEUAtT8dsjSzThCiT8k14jSd0NmWgk3D3337I9d2NkWHssZAfSC0AhAlNLrt7Lyu\\/r12foF4PRNazGiwLRhyErf62Ijaokqgfjoli8q\\/n7\\/0fJyHwRBQcdfKOXR3S\\/IDFVubKJ03b6Cj4jT+k6t2zdFULCyN3rnl1avz6lC7Q+6aU8361W4UOBReAL9JI0jDA6TRoYb06MSwaTJAvd+xkQ+EjCk8DRH3ZkRV\\/fndUhZ20K\\/szQw4LKTeV\\/ibLPV1OBhmtQnUlUJTu9X\\/up1nbDqMbeHCTxGXZ7xqHnerWUtw1aqymFTOfpYvLo\\/QYFFkinuU7yH6RbBIbjwZxaKgG5J19h+KqvqLiu\\/nN5iwRezLH0pnKXNyNJ9ufeSGRVn9ob6enJRGIopjURE4Od1NgSx+hRzRYVH7GsxtBGuxzc7YUZlZ1FsOWh\\/pORAF1CLGj4JCe+hrmlxwKaujHN6eYjC1CbNtzy+HXrE0UYfGgacabZWrqvkiAOqzKGSv5gP3432vyZ6Qw7IZ\\/bX3yEXmuL8GV\\/Je9npzA6AEL0pQTV+dFjpZsdeGzkp6l5awfvfWV+6wvI4j0qbfeceZaj2LRrgKL4pFwZDOl+6TaWRhgXyPjL1A7\\/lwXPZVUt6Au3+U9j2sBCorZhBeXo+ME1g3tswPmqeZisGCLVIz9Pz3xcfecVzm\\/NAIkCIInZeAhhbVTHIR3UKouk+mlyYIIkiZ8FJxNs2mReUX7FfWh4LOfhGoawsDVXt5HX35SMtBiqnvU6jK0\\/f8N1qdvW3dyNq+XP5QM4JFoTgWtbWjBBbl+RrNVUDB9O45++i37MzBot53cC+uskM1A4dOgMIY1bm5GoHgXoEv0lFWZuPLSiUllNV+Ck39o02X74uLKiWl39nH1QUwqViUpbPoVSwqW+5aLBzBosoXwNWmOVnU2\\/4AselhJVCZM8rz7EKr6hIMs4rxIGv1pOtT5X7TipFNPrjrtz91zeo8zUDsSI8E0EDhxrFoAggCLMrSs3DgPuX7N4IWvcFHkDbZltgXiDGd1gg85HpfpKosyNoPT5XSRtKsz7XWqrf0gNxRUVf5qnUFSgcPL9z47Fh\\/d552SlY9wmEu+DLTsqhczWdhUWWIk0kvFWv0OUeP6knGGr1uJzSZjmsV+6h1c8++1gPV0YH3098Rtf5jGln0zUE4zKqwPINe\\/NPTV07mictb3jsF4areL8wULOqDqAAWVVnsKGWECECrsrodiUp+FonGGt4da6czZ6Cz5kxcr7YZCr1aIB7TnlsB3p+pnq9VbVTV\\/uGZt63V1XfK9vJ1TRbVsOhlgGqxKNPTojKLylqZHtEG5uSRRj8LltC3gJ3Dihutm3u3JwG1s6m1cckYJmA8mAmAyt7+WMZcF7fnvPaKZpWvvtaz+1c+vbc2p023mlceV5NYNCqbiCVU84YURdJlUYjQorIHgoUjaUzUlHX2VE4W9fbfnej5pPnFpktHUa9moc+iggU8BamjnOtaX99wTSVXe3mr0e1VwODR8RywsBsrikUxC4saYWMpssm3xTbRoYdzsKi3n\\/dEvUEHqK2xzivG\\/XSToy35rijQVcpCcFuDVaXq37JKY99\\/\\/vVrUuWHyu3lTYFFWRgEGFONisYSY+G8UBEkRhYWhUQWbWw32fo8LCqw8F3WB3pRB6icdrc3HTxcr1aMe5R6NRFwUciz9C\\/Cw\\/vtRnZNTOc8uvfUjYewHbR0aFT2UF2tRVHSkkqfKFOwKNMDeREs6m0Hi\\/CCbH8OFvXuj4\\/W\\/YjO4zdg8Wb+6L7NcvRdqT0ZsI+V4KGmtjiN2s6fUJuRK1Hmyxtu6NHVoUo3jxlhVYsMGOMTZRBfzRu6flHfv5SSRZkvX57QisKxSBb19t9nvb+3rgUd+5wlW\\/bS4vstqZbLxgb61s0tjwTwuL6dGaxZ5UvVfx3LL\\/7b0IXH5+q3yYwGjyqfNcSiEfF7g6Xwi7pD7qCiIaCW35axvQTUQb0onJJFvXmC5vu1Oc6\\/z\\/4tj9HiNy0C6+\\/o72jyQLks3WC6MawK7aVcCS337Tz\\/+Ro9Lu1+mxSs5FX7Se2GVH2pqkBsMIVUUFxDZFGMYFFtv23dZdPsLOot77fe1zueGqju9C8t06tluMfuQKuZPlMxU6pc0nPqR0y3Pn3TMm0dqtJ2psKpHuN0D7BoBGNH9d8fkgoCi0rlkNZvy8fRej4Hi3rXMSEmXJoIVBjY0lq9apBe1bXcY7VkglHFrX1V79CoV\\/2P1zq2\\/3b\\/aYu0q3lFv012z4FZWBTC1XxU\\/D\\/AoqxR1UdV88AYS6U1ydIHcB5kRhb1fv8j5nt792cGqn2hpc+3Tq+WYAP9gM3FW1XBy4HOSCgxL8L\\/2v66PVpNfmMc7Ty2r8WiEN3aU6eaZ4IWla35SIOMMZ1eoycJos9EsajgvI91\\/ruf707Na8qaednzLdarMFpYdR9m7kbINK23wWXVL226YZWWDo2qNusRTnOmAFgKxg4BlDVyRpXVfBq\\/rWCwgdMeaoOrspUsCgkAFXT2BvM9vS8UAtSW6lUeUCzBvX7dXDCxQqUUlgi61T8P2032PPvU2PK5ebpnVGVKqVqVRrFoEgszFmRRGaAsJjwLMd1eCu43k4dLgyBMzaLecXdn4pvIAl7+vKdXJ1tgXL1Iv+ihply73dA3zhSM+\\/0tV45l6ibcKxx3AOk4FgXIwaIQwaIQwaJMMsaiAgeG4N2w2CYu1eXoUgoW9Y7bYb279+lCgWp\\/2XHbuF79QUskgAF\\/or9b82jJ0HrJrfojq\\/xEQ6r+ta1vPznjcDUNa7+JLCpnOEWxWaTfNiIULGV7rc\\/Jot58T2Z4JJLdiu1\\/oMXvWgTW39r+1USQWnrXK5cVWVf6TVaeH1u+4YVab3vG4WqcfbXmsmiommcprs9YZK6CX2Mg20bzSA4W9Zb76dp\\/aBpQ3eknNL\\/QAqhW6Zeq9Wrq0CePRkE6JpY+\\/+NzVxtZugn3GcTtmqfpLMoyXh\\/iu05HpwHiEzlZ1HsB7jXf2Ws1Fahw\\/HbOC99qnV5l2fSqCDru4AeI2Kno4kcyqmj18Hd3vuFkHR0aMkw8NqplYFHGYgdSizOWsrB0XCgYEHeDhUM5WNRLVhvHFOHSPIzKYOX2PS3Tq4wF9aoyXGrFo7VsaAYL1JdYP3LKxhGr00gD0ND+Wj6WC2nhAlgUdVgUnDcV3FS+WBZVXFd8AdzPv7Nu6p1sCVDt+zmhhXoVWLxeTaLWspHNEHOn\\/7b5htm6OlTZnr6OsYWZlkVVBlMWFvUAGsWiNkBJlBq8xxKTPZ\\/IohJA5VGp0Rln6le5zZcM57RQr7J7ldSJCfV+udRIo1cdk+BTNdEY\\/vHeS1ZlHK7GKWhTzZIQk2TSchYFBYt6FZFFlr4tTqO\\/N4FFveuvs27sHWk5UOHEHa3Tq04zGUmvWsmgLRvxuQIJ0\\/0vnrN5gpVTdizRSMawv7IG6VgUCmJRFs2iYMRU8+CC1Nk\\/QTz4LEvwVMSwqPgb7y3EIZSpVl61o9V69XltQ4o\\/zVKG3qmF9Vu3vKs\\/XY8iwWQMVGRKRbKoyqOQh0VVaYdG9EBo9r0b0nUteubI6jlY1Dv+KeuG3l1TBlT7Hla\\/wPXqAy0CK9erB5NZUtSmGAHm+Op\\/0uzYeffoSwd0dGhE8wrSp\\/osKgNUyaIx0SUdFpUBitK9yyl49O9POVnU+213FeZiz3n+j2je1QKgTtJzvY\\/p5AOUjNQWvrj+86FLd3FhpqNDI0FcA20W9cGrYFFIiC6pDJ0Qi6q6kRRqgJDfFtkz9NMmcrCo94JuM9\\/R++y0ACqc9EIr9SqXGw\\/H35CqC+WE6l\\/yqX5p+00nxOnQROd3LYZFjbDeS5OKl8Sift+nRoQnIYpFxePqds5pHhb1rn93kYWfl1EZrNk5RIs7WiIAeD9HGKNXy0YYoUq5gEowH6jP2fTI+Ak9cToUYrpnFFuZBljUYMpcU61UvJQsqtahCSzqLksW22ogG1WxqOC8TxzZjz7zPqQem1ZAte9r7U7OdA+2CKyOXlVV4So21Yliuev\\/vPPKUV0dqnJZ2dxsgrLfJojosjHgM83LohHVvA9SSHBbSV2bJ\\/VXEOMRuMe8Pnu4tGlAdac7W6dXMahX+VySO6VP0qihkKr11V3XrdXSoRHObz9kKhhGUQaJqFaiAJqaRZmaReP8tr7eRDZEj2FPDhb1juODTfxH0YVeGFDh5F2t06tIehXx4QDYSkZ0T9Ea7a92TvRv2FJb2JkmlS0EwHpDi0KMW0dkUZaRRX2QggqkKVhUSD5ByMWi3nG\\/ta7tnZy2QLWfwym7WqdXLVGvYnAsU53qXvr8rReutnR1qDJTyPY\\/gjJ82QwWFZzzSoteh0WF+xphJtueg0W97+AK\\/dfNKG6j6AvCqYOt06smkl7FQw2QRvX8F+9TRTQmv733ypN1dKiK2exlNdw2HiGiq5w4lkxgwSJZVGiFwJNPUJtFVVE1517WEZuOHhFAbbleNUmvGoaZJvIk43bj2Oo\\/7bW6y1lS2XyXTR0iWVQXoHEsWDiLNq4zzmpsUyoWVV+HP9W7m1XQTQEqvGSQ69XvODzTdL26lZ7iJ3Ws+qjq\\/2s7b+jU1aFKHSe0i1KxqEpCoGIMqfRalGVnUc\\/YIwlluB2BYEKbMBaT0ELXWI\\/X9O4+ooBq\\/6bThna5zNrs6VEygG6j8vpFuJpPCE0hl7rGgTv2v3aNlg6FiMhMLYZFE7ragYRqPp5FMRuLuqVukFEKVfZknPM+gUVFTXt3MwvZaObF4fQh7qZ4qMlAfRguHOEovI7mHWmr\\/4cOvPzZMVbR06FMHZmBGoSr8Jhqnmmk+kX7RT3XWTwLGzE9VRt8qHKuSyfZL9180aws6r0IW8yre59rZiGXW8B4nFVX0LykCdfmERD7AcGF+4fx\\/vlvJQD+jh5m2QdjaPjy4PpXdr5rYaQlq+NPNN1xIyLGPw25pGIiQyymlxQfoCw+uiTdJ6\\/SRwiU++keh\\/kSeL+mFjvoDwWqY9Enf889zQYRtACoDB9f1E9C7hP0aNr8tkko+DT9z1FLb7bk\\/f8XLj30s8B33T\\/\\/o\\/SrbvOfOAgIkdarVvtQ9+NPLLaEoUSiABpgJ+HpWeN0TA1iwZMIAgXLhsOrGAdy\\/q6MUFW+Hx0wDvOOdhHtFhIoxuijfgeoBgxOBijfz3MwPm29vRePdEZlcObuXfjYgjvd6rnQal+x7cs0v5IK6vKk1\\/DukYu3WwCLtQCqYh\\/mVPvaANVg0QSAcjAc4CAkdhy20GFIWj\\/A3LGegOWK0adh0UZnvE0GacuAav+ms\\/b+Bz66YDWtnlPQJXcQmw6GvucCIpL7519HD\\/GP9HFZuMp3N9Di84PvW44KQGoXbC25kHX3S2l+\\/CYPAuKwC8r9jI\\/cbNpdifu96amiX+JvycuiGtfhvci0xGfeMqA2Qa+ui3wpLiC9+gDXq+DqVWyUrAuDMav739dVV1+hBdCogq3FaNEEEAj7D9E8bJgERIuAyAFp4YjhdkiGqtGg82jqYljU+\\/wrvKq3dtQBFV66dxIfWcD7s\\/oEzW25vKcsfpACOH\\/\\/Q\\/hAz1\\/T6ndp7g6cCewXN2y5\\/eP0sK\\/Q0aGqgnVMFVB2Ya6SAkTkHJA8VMn7BeWGzTCiDcwaE8HIMBXI0rJoJEhTXMfdzwH6G7NV2GFTMOEf+s6j8rg2hzH1NLz64Fe1vuvBHm7Vv5F+6VoqoWGuqeCcfQ\\/Ct\\/eV6GFzB3VvFuaBKonCCQg69p0spHHfmCFAUkU9Qj9jmLZVc3YlHvyeqWNRb\\/9vzbf1\\/pAdzUC1f\\/Tv+26gsnlFRqB+j4Ca2z9b+s4+zqpfjC3UKP12iI2xmt2vq23Y8CVpSL6cjLtenp6ao1g0M0jTs6j\\/kT5\\/2npr755W4aXMpm66w9Wri1Kex6ucxwt5WWw3FltFqzdFaUtuZdNxfARl3uCNd2b7FI6xF+AgfMRuWqVoRpIGoN4xGHWd6cWi3ufHWwnSKWVU+0c\\/3DdAZfUJej8rKRj1EXjV6HeKvA\\/jf+x7DS2upEJdyngyDdhNtJ+iQtlgXde7M3T8rcOX0uJNuixYBIsWBtLsLCp+zxett\\/RuaSVWppJRGbzixZ24ro+3ZL2mCGs\\/62Td0Mvj1NqxagLAK5SFK7GgmiWPWBb19m9uNUjte2FTPMHZL\\/K+AR7WPJxbzhum8n5Ltw3302JAmcjBdIZZzNXHaJ6k5gBLZgGp+5vvmornXmbTY9LVq7zaN6f4Xs8OgWw6sWiE8ZeTRb3Pu+nz+ql46MZ0QCmcs49byt9ifkeN6hqatWqklqiH9aVhoAL7s\\/SD1baQRQsGqZT1dQ9e2fxw6bQFqv0Mzt3HjZbvMXXHp\\/zh\\/BAuGR2c4ts8kQprftohv3P21KyswjOm46XeL9zzNmhRuHQ6V\\/3O8zhv+BF8oIcnXJ9H83J3Mx9C6CG4eOSFqb9Bl02nq0VfIIuKMgIcL8g\\/WX9VbFv9I8Y9dSRNxleG+Ut9G82d8VoT9bSoAhRNTsfT3T\\/iuug4Yeyi79tKAN011c+\\/PANB7ekUKrTOo4hFR+nzoAdKWufSaxDf3HtY1lzTYZoBqm7VQ9V+EovqgqzFLMqBt5MD0fCASbP5tt5DR9LznwGqxlS6fbhEBX36NGfRcQ5AgSU5Q+6y3t5oZ28ewWUwA1SNiQp\\/Ni0qRSaS5GBR7sobdEHps6R5dbphxWeAelTW++5zai2L8jzVIbfa3iUYOMPWtQ1fpnmMFMEMUPWmahNZ1LQZ0gHhIDjLnXxgOPP6Xpx59DNATcGoeBCcKnZJjqRm7oPc7WrIna6G5ADdY90wdf7JI6dSm5n0DKp\\/2LeMQPY3tDorgUU5C+5xNaTNkoYDyt3mO3vNmSc5A9SmT8bX9\\/XRE+PNWk62AcvYPruq9nyQDjCHrHe3psHbsTT9fwEGABlNj373go\\/vAAAAAElFTkSuQmCC\",\"file\":\"\"},\"menu\":{\"data\":\"\\/adminapi\\/setting\\/permission\\/rule\",\"controlWidth\":500,\"select\":1,\"accordion\":false,\"collapse\":false,\"control\":false,\"async\":true},\"tab\":{\"enable\":true,\"keepState\":true,\"session\":true,\"preload\":false,\"max\":\"30\",\"index\":{\"id\":\"10\",\"href\":\"view\\/console\\/console1.html\",\"title\":\"\\u9996\\u9875\"}},\"theme\":{\"defaultColor\":\"2\",\"defaultMenu\":\"dark-theme\",\"defaultHeader\":\"light-theme\",\"allowCustom\":true,\"banner\":false},\"colors\":[{\"id\":\"1\",\"color\":\"#2d8cf0\",\"second\":\"#ecf5ff\"},{\"id\":\"2\",\"color\":\"#36b368\",\"second\":\"#f0f9eb\"},{\"id\":\"3\",\"color\":\"#f6ad55\",\"second\":\"#fdf6ec\"},{\"id\":\"4\",\"color\":\"#f56c6c\",\"second\":\"#fef0f0\"},{\"id\":\"5\",\"color\":\"#3963bc\",\"second\":\"#ecf5ff\"}],\"other\":{\"keepLoad\":\"1200\",\"autoHead\":false,\"footer\":false},\"header\":{\"message\":\"\\/adminapi\\/setting\\/message\"}}', NULL, NULL); +INSERT INTO `lms_clx_system_options` VALUES ('4', 'table_form_schema_wa_rules', '{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"主键\",\"control\":\"inputNumber\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"title\":{\"field\":\"title\",\"_field_id\":\"1\",\"comment\":\"标题\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"icon\":{\"field\":\"icon\",\"_field_id\":\"2\",\"comment\":\"图标\",\"control\":\"iconPicker\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"key\":{\"field\":\"key\",\"_field_id\":\"3\",\"comment\":\"标识\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"pid\":{\"field\":\"pid\",\"_field_id\":\"4\",\"comment\":\"上级菜单\",\"control\":\"treeSelect\",\"control_args\":\"\\/app\\/admin\\/rule\\/select?format=tree&type=0,1\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"5\",\"comment\":\"创建时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"6\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"href\":{\"field\":\"href\",\"_field_id\":\"7\",\"comment\":\"url\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"type\":{\"field\":\"type\",\"_field_id\":\"8\",\"comment\":\"类型\",\"control\":\"select\",\"control_args\":\"data:0:目录,1:菜单,2:权限\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"weight\":{\"field\":\"weight\",\"_field_id\":\"9\",\"comment\":\"排序\",\"control\":\"inputNumber\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}', NULL, NULL); +INSERT INTO `lms_clx_system_options` VALUES ('5', 'table_form_schema_wa_admins', '{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"ID\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"enable_sort\":true,\"search_type\":\"between\",\"form_show\":false,\"searchable\":false},\"username\":{\"field\":\"username\",\"_field_id\":\"1\",\"comment\":\"用户名\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"nickname\":{\"field\":\"nickname\",\"_field_id\":\"2\",\"comment\":\"昵称\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"password\":{\"field\":\"password\",\"_field_id\":\"3\",\"comment\":\"密码\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"avatar\":{\"field\":\"avatar\",\"_field_id\":\"4\",\"comment\":\"头像\",\"control\":\"uploadImage\",\"control_args\":\"url:\\/app\\/admin\\/upload\\/avatar\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"email\":{\"field\":\"email\",\"_field_id\":\"5\",\"comment\":\"邮箱\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"mobile\":{\"field\":\"mobile\",\"_field_id\":\"6\",\"comment\":\"手机\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"7\",\"comment\":\"创建时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"between\",\"list_show\":false,\"enable_sort\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"8\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"login_at\":{\"field\":\"login_at\",\"_field_id\":\"9\",\"comment\":\"登录时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"between\",\"enable_sort\":false,\"searchable\":false},\"status\":{\"field\":\"status\",\"_field_id\":\"10\",\"comment\":\"禁用\",\"control\":\"switch\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}', NULL, NULL); +INSERT INTO `lms_clx_system_options` VALUES ('6', 'table_form_schema_wa_options', '{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"name\":{\"field\":\"name\",\"_field_id\":\"1\",\"comment\":\"键\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"value\":{\"field\":\"value\",\"_field_id\":\"2\",\"comment\":\"值\",\"control\":\"textArea\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"3\",\"comment\":\"创建时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"4\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false}}', NULL, NULL); +INSERT INTO `lms_clx_system_options` VALUES ('603d7ef9-811b-4500-8cad-7063c8282dfb', 'dict_set', '[{\"value\":\"1\",\"name\":\"\\u7537\"},{\"value\":\"2\",\"name\":\"\\u5973\"}]', 1710142338, 1710142338); +INSERT INTO `lms_clx_system_options` VALUES ('7', 'table_form_schema_wa_uploads', '{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"主键\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"enable_sort\":true,\"search_type\":\"normal\",\"form_show\":false,\"searchable\":false},\"name\":{\"field\":\"name\",\"_field_id\":\"1\",\"comment\":\"名称\",\"control\":\"input\",\"control_args\":\"\",\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false},\"url\":{\"field\":\"url\",\"_field_id\":\"2\",\"comment\":\"文件\",\"control\":\"upload\",\"control_args\":\"url:\\/app\\/admin\\/upload\\/file\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"admin_id\":{\"field\":\"admin_id\",\"_field_id\":\"3\",\"comment\":\"管理员\",\"control\":\"select\",\"control_args\":\"url:\\/app\\/admin\\/admin\\/select?format=select\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"file_size\":{\"field\":\"file_size\",\"_field_id\":\"4\",\"comment\":\"文件大小\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"between\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"mime_type\":{\"field\":\"mime_type\",\"_field_id\":\"5\",\"comment\":\"mime类型\",\"control\":\"input\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"image_width\":{\"field\":\"image_width\",\"_field_id\":\"6\",\"comment\":\"图片宽度\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"image_height\":{\"field\":\"image_height\",\"_field_id\":\"7\",\"comment\":\"图片高度\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"ext\":{\"field\":\"ext\",\"_field_id\":\"8\",\"comment\":\"扩展名\",\"control\":\"input\",\"control_args\":\"\",\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false},\"storage\":{\"field\":\"storage\",\"_field_id\":\"9\",\"comment\":\"存储位置\",\"control\":\"input\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"10\",\"comment\":\"上传时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"searchable\":true,\"search_type\":\"between\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false},\"category\":{\"field\":\"category\",\"_field_id\":\"11\",\"comment\":\"类别\",\"control\":\"select\",\"control_args\":\"url:\\/app\\/admin\\/dict\\/get\\/upload\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"12\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}', NULL, NULL); +INSERT INTO `lms_clx_system_options` VALUES ('8', 'table_form_schema_wa_uploads', '{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"主键\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"enable_sort\":true,\"search_type\":\"normal\",\"form_show\":false,\"searchable\":false},\"name\":{\"field\":\"name\",\"_field_id\":\"1\",\"comment\":\"名称\",\"control\":\"input\",\"control_args\":\"\",\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false},\"url\":{\"field\":\"url\",\"_field_id\":\"2\",\"comment\":\"文件\",\"control\":\"upload\",\"control_args\":\"url:\\/app\\/admin\\/upload\\/file\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"admin_id\":{\"field\":\"admin_id\",\"_field_id\":\"3\",\"comment\":\"管理员\",\"control\":\"select\",\"control_args\":\"url:\\/app\\/admin\\/admin\\/select?format=select\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"file_size\":{\"field\":\"file_size\",\"_field_id\":\"4\",\"comment\":\"文件大小\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"between\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"mime_type\":{\"field\":\"mime_type\",\"_field_id\":\"5\",\"comment\":\"mime类型\",\"control\":\"input\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"image_width\":{\"field\":\"image_width\",\"_field_id\":\"6\",\"comment\":\"图片宽度\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"image_height\":{\"field\":\"image_height\",\"_field_id\":\"7\",\"comment\":\"图片高度\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"ext\":{\"field\":\"ext\",\"_field_id\":\"8\",\"comment\":\"扩展名\",\"control\":\"input\",\"control_args\":\"\",\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false},\"storage\":{\"field\":\"storage\",\"_field_id\":\"9\",\"comment\":\"存储位置\",\"control\":\"input\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"10\",\"comment\":\"上传时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"searchable\":true,\"search_type\":\"between\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false},\"category\":{\"field\":\"category\",\"_field_id\":\"11\",\"comment\":\"类别\",\"control\":\"select\",\"control_args\":\"url:\\/app\\/admin\\/dict\\/get\\/upload\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"12\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}', NULL, NULL); +INSERT INTO `lms_clx_system_options` VALUES ('da49ebe5-2f0d-4190-ba27-0772222482a8', 'adsfa', NULL, 1695099862, 1695099862); + +-- ---------------------------- +-- Table structure for lms_clx_system_post +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_post`; +CREATE TABLE `lms_clx_system_post` ( + `post_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '职位ID', + `post_name` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '职位名称', + `post_code` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '职位编码', + `pid` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '上级职位ID', + `dept_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '所属组织ID', + `icon` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字体图标', + `sort` int(3) NULL DEFAULT NULL COMMENT '节点位置,越小越靠前', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `delete_time` int(10) NULL DEFAULT NULL COMMENT '删除时间', + `level` int(10) NULL DEFAULT 1 COMMENT '部门等级', + `remarks` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '备注', + PRIMARY KEY (`post_id`) USING BTREE, + UNIQUE INDEX `代码`(`post_code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '职位表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_post +-- ---------------------------- +INSERT INTO `lms_clx_system_post` VALUES ('03ad4b7c-c0ce-45f8-a20d-49fcafcb4f59', '行政助理', '0101', '', '460b9e0a-2dce-44c9-b29d-4a0dc8565a1e', 'layui-icon-group', 10, 1710229919, 1710229919, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('0e22c1c8-6c54-4f22-b8c7-35c45e0d93cd', '网络工工程师', '1001', '', '06c9f2dc-c1a7-4a8e-b317-fa78af8e3346', 'layui-icon-group', 10, 1710229717, 1710230243, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('135ef3d8-1e0b-4fed-afdb-1e8945199414', '客户服务代表', '0201', '', '4908ba01-0562-455d-8b22-3b6b266b6d29', 'layui-icon-group', 10, 1710229954, 1710229954, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('191507d0-0b76-435e-b2a6-2c7f4bc83d4f', '产品经理', '0702', '', 'e218caed-4c77-4a0b-a481-895f1986e9e0', 'layui-icon-group', 10, 1710230157, 1710230157, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('1e9c9f97-0cc1-42fe-99ff-072bfa987cf2', '技术支持工程师', '0202', '', '4908ba01-0562-455d-8b22-3b6b266b6d29', 'layui-icon-group', 10, 1710229968, 1710229968, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('2d4760b6-bcb6-4fbe-8ab6-6157e0a41753', '品牌经理', '0401', '', '6dd10bef-c440-4c90-9205-0178fdf75d02', 'layui-icon-group', 10, 1710230041, 1710230041, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('31dc9ec6-dd9f-4ea8-8b4c-b571bc18ee6d', '员工关系专员', '0502', '', '8a161db3-59d4-49e5-89cf-0b44ddc891ff', 'layui-icon-group', 10, 1710230078, 1710230078, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('745e3ac7-7b85-4356-b507-4ce3ff5517fa', '销售代表', '0001', '', '44d21f0e-e34f-4a2b-92f5-ad1f1b0a049a', 'layui-icon-group', 10, 1710229766, 1710229766, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('7b80a503-2be7-48a2-83ce-b3b4281c655e', '研发工程师', '0701', '', 'e218caed-4c77-4a0b-a481-895f1986e9e0', 'layui-icon-group', 10, 1710230143, 1710230143, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('7de1c1af-af39-4687-bda6-9ba6d20cdbe4', '超级管理员', '0000', '', 'b9191372-1051-45aa-aa32-63b6eca5f1c1', 'layui-icon-group', 10, 1710230209, 1710230209, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('8ba40db4-a435-4c1e-b8b7-5dc80c14f3ee', '软件开发工程师', '1002', '', '06c9f2dc-c1a7-4a8e-b317-fa78af8e3346', 'layui-icon-group', 10, 1710229736, 1710230252, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('8d2d7ba8-ab90-4892-8dc9-0f0d2fc3fd92', '会计师', '0601', '', '94fa363c-66b0-4bb4-a59f-f4774c9c37ca', 'layui-icon-group', 10, 1710230100, 1710230100, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('967eb4d9-d99d-40a0-84ae-82abf640c983', '设施主管', '0102', '', '460b9e0a-2dce-44c9-b29d-4a0dc8565a1e', 'layui-icon-group', 10, 1710229934, 1710229934, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('a258f586-37c4-42b5-ad81-e49458c1ec37', '财务分析师', '0602', '', '94fa363c-66b0-4bb4-a59f-f4774c9c37ca', 'layui-icon-group', 10, 1710230114, 1710230114, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('ac90bac6-80b9-4fad-b238-4d4f48b86f68', '市场专员', '0301', '', '61041c06-86a8-4543-a123-50c409c69eac', 'layui-icon-group', 10, 1710229990, 1710229990, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('b559c91e-fd88-4517-b741-560b366d8645', '合规主管', '0802', '', 'f76ac4cd-2072-4ee4-9109-d34e54e4f5be', 'layui-icon-group', 10, 1710230183, 1710230183, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('ba3bd8ed-1136-4911-94f4-dbc580b740ba', '法务专员', '0801', '', 'f76ac4cd-2072-4ee4-9109-d34e54e4f5be', 'layui-icon-group', 10, 1710230171, 1710230171, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('cf94fe6d-c948-4e70-9af8-cc2ad35adcb2', '销售经理', '0002', '', '44d21f0e-e34f-4a2b-92f5-ad1f1b0a049a', 'layui-icon-group', 10, 1710229783, 1710229783, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('e64e0a18-0849-49c8-92a3-92300e3f410d', '市场专员', '0302', '', '61041c06-86a8-4543-a123-50c409c69eac', 'layui-icon-group', 10, 1710230009, 1710230009, NULL, 1, ''); +INSERT INTO `lms_clx_system_post` VALUES ('e9e48049-c25e-42c8-b702-a3dc4ed5c781', '人力资源助理', '0501', '', '8a161db3-59d4-49e5-89cf-0b44ddc891ff', 'layui-icon-group', 10, 1710230066, 1710230066, NULL, 1, ''); + +-- ---------------------------- +-- Table structure for lms_clx_system_role +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_role`; +CREATE TABLE `lms_clx_system_role` ( + `role_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id', + `role_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色名称', + `role_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色编码', + `pid` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '父角色id(如果没有父ID,则为-1)', + `status` tinyint(4) NULL DEFAULT NULL COMMENT '正常1 禁用0', + `sort` int(3) NOT NULL DEFAULT 1 COMMENT '节点位置(超级管理员:0,其他角色最小为1)', + `icon` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字体图标', + `is_super` int(2) NULL DEFAULT 0 COMMENT '是否是超级角色(1 是 0 不是 2 基础角色)', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建日期', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `delete_time` int(10) NULL DEFAULT NULL COMMENT '删除时间', + `level` int(10) NULL DEFAULT 1 COMMENT '等级', + `remarks` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注信息', + PRIMARY KEY (`role_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_role +-- ---------------------------- +INSERT INTO `lms_clx_system_role` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '新增测试', NULL, '-1', 1, 10, 'layui-icon-group', 0, 1694354520, 1694596672, NULL, 1, '大师傅'); +INSERT INTO `lms_clx_system_role` VALUES ('9b549461-3999-477a-96a0-60d8f99e998b', 'dfgbdfxhtf', NULL, '-1', 1, 10, 'layui-icon-face-surprised', 0, 1710127107, 1710127107, NULL, 1, 'dvb'); +INSERT INTO `lms_clx_system_role` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '超级管理员', 'is_super', '-1', 1, 0, 'layui-icon-group', 1, 1694139885, 1694139885, NULL, 0, '这是超级管理员,默认分配所有角色和权限,禁止删除!'); + +-- ---------------------------- +-- Table structure for lms_clx_system_role_dept +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_role_dept`; +CREATE TABLE `lms_clx_system_role_dept` ( + `role_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id', + `dept_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '组织id', + `sys_code` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '系统编码', + PRIMARY KEY (`role_id`, `dept_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色管理组织关系表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_role_dept +-- ---------------------------- + +-- ---------------------------- +-- Table structure for lms_clx_system_role_menu +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_role_menu`; +CREATE TABLE `lms_clx_system_role_menu` ( + `role_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id', + `menu_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '权限id', + `sys_code` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '系统编码', + PRIMARY KEY (`role_id`, `menu_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色管理权限规则' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_role_menu +-- ---------------------------- +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '03c5a106-ed45-42d2-9467-e3448ed369b3', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '08580779-066d-4b3b-9985-124df63625a4', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '0a4aff69-ad1d-42b2-8634-00dc3e52360b', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '0f690e32-1e73-4190-9f87-e349f129451b', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '1e52ad08-670a-4425-9e72-3925ba871dcf', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '2ac1fd8d-2ca4-4eea-bd1c-f3989096eea2', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '382c1114-59db-4594-b870-da3ce1a29c56', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '3907df96-3152-4aba-9e23-a44575cc7251', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '3f9e4f79-1b00-4ce7-9187-62bd91ace077', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '4811a205-a4ec-499a-ba85-30ca5ab95feb', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '4a26ba61-676b-4842-a087-743eb0354203', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '588383d3-d8fe-4023-b9e7-220baac09a0d', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '5f4d2ab0-0cde-4bd3-829f-5a11d96b6440', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '60fea859-c085-4b37-8d7a-d03e81afe73a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '63a64d73-40df-4275-af16-c7c0fd382bf2', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '75300596-9c65-4e63-87c3-19c974e7bf1e', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '8b55c722-256a-40b3-ae27-1fdf99164094', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('7ebf3afd23014766bba0007cb5a7250d', '92158f89-3eb8-462a-85c9-f9586075e274', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '00f2cf25-61c2-4265-bab9-fc60569b40c6', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '03c5a106-ed45-42d2-9467-e3448ed369b3', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '08580779-066d-4b3b-9985-124df63625a4', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '0a4aff69-ad1d-42b2-8634-00dc3e52360b', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '0f690e32-1e73-4190-9f87-e349f129451b', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '16a335ef-abea-4581-8de0-1f03d669792e', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '170320e1-d592-4809-9447-f40b27fc7aa9', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '18e6af3d-e99b-4b1c-be28-2a9547cf6eef', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '1d244ec5-cf4e-445a-9374-aaddcb4d84f9', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '1e52ad08-670a-4425-9e72-3925ba871dcf', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '21abf252-b962-4379-bc19-381749e2cb80', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '22900032-1fa4-4a53-bb04-f8b535ea9793', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '25f880bd-856f-49fa-b59c-3f76b7d389c7', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '2ac1fd8d-2ca4-4eea-bd1c-f3989096eea2', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '2b433461-3e8c-498d-85a0-33aafade3365', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '2b84ae82-4c4a-49ac-8471-a3233b0703db', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '2d1f9c58-f0bf-43ff-a729-fabadabd3b8c', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '2e79d53d-3a7d-4e17-8944-bdd0b0f63df0', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '30dd2e7c-3233-45d3-b538-c2985f9a6ce7', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '31d43b76-ae60-4ce5-a04e-2d1d1ec2604b', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '366472c2-cb67-4dd9-a8bb-2ae9f045b5c4', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '382c1114-59db-4594-b870-da3ce1a29c56', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '388b4b2f-5ca8-4cd5-804d-1716b8e02cd0', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '3907df96-3152-4aba-9e23-a44575cc7251', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '3d5e3491-7546-4046-acb3-d7b34fda210c', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '3e2df7be-9e8c-4ce2-9ddb-61f13d3142bf', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '3e74a70e-fb39-41d6-b3f1-abd93ca56014', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '3f9e4f79-1b00-4ce7-9187-62bd91ace077', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '428ee06e-c350-4c9e-8c29-1e59a9e97570', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '4474d199-7089-4efb-bc68-b638a7aef300', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '4811a205-a4ec-499a-ba85-30ca5ab95feb', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '4a26ba61-676b-4842-a087-743eb0354203', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '4c0175ac-5b37-4ef5-a2dc-c14caa7b6e42', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '4dd18197-2477-421a-8e42-238c6298c7c9', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '54480923-4b9e-4c85-90c8-19712b709bb2', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '57f79696-1bd2-43f5-a411-75080735b700', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '588383d3-d8fe-4023-b9e7-220baac09a0d', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '5a22017d-6f19-41e8-936b-f70d405639dd', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '5f4d2ab0-0cde-4bd3-829f-5a11d96b6440', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '60fea859-c085-4b37-8d7a-d03e81afe73a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '63a64d73-40df-4275-af16-c7c0fd382bf2', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '67cfcfe5-7441-44fd-bc61-3e9dc3059362', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '6b674c34-7d23-4a27-9a05-688ed3e9c38e', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '6ee2d444-cd5f-45ca-a880-11976d16c210', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '73aebdf5-fae6-4aa9-a319-8fcc48b6351b', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '75300596-9c65-4e63-87c3-19c974e7bf1e', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '7a5eaccc-0019-4064-8f83-7c564c431a7c', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '7c259013-7919-4235-ab8c-bfcda9b51184', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '7e72c463-d80a-4b83-937d-eb20d63a9636', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '7ee73260-eaaf-463a-84ff-ac285055e0c1', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '857bd274-30f4-429a-8004-a2e6d0ccb6de', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '88cab609-0d7f-4394-a00e-ad24bd2c5ae5', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '8b55c722-256a-40b3-ae27-1fdf99164094', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '8c3e3149-4438-4b1c-b32c-10978b1a54ef', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '91c5a906-911d-4222-b534-df2e5041e0dd', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '92158f89-3eb8-462a-85c9-f9586075e274', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '92bfab0f-88e6-47ee-b2f2-5d0916f11ef1', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '94d4cd83-3d89-493d-97ba-27ded6503a8f', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '99f5f7b2-d584-44f0-b93d-aee0b8030649', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '9f1161f9-a3bb-42c8-9b8f-19b12aecf708', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', '9fb603da-e232-4beb-ad9b-2351e0274029', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'a16b6f89-bd60-4ffd-b833-337ccd8fed36', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'a51a3e37-c890-40b2-adf4-ca7f3856fd84', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'aaf1c674-956f-4349-8f61-b1d8d3285e20', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'ac72da18-cd39-4a6c-baf7-d2f75ca7b4b7', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'b21c5ea2-3eb9-4d4e-8244-bdb3caf7ee80', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'b4c85694-38b6-4332-a62c-260cd597f257', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'b7ae5925-9e84-403e-b8a2-eb4528b11d89', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'ba789614-2967-4b16-99d0-b14f9ec98818', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'baa9d8a3-0ea0-4689-9489-0a5ca387409c', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'bad80eed-ef69-4e42-8d36-ceea6df674d1', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'bc9ac16f-c3bb-43a1-bd05-bbda718513ef', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'bd3fbcde-13b8-4c76-9293-755d349b3873', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'bdd9f5be-2460-41b9-8212-044bfae1a568', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'beb61b71-362f-4a59-ba8c-aba8135602a0', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'cb38b36a-c7ad-4899-bcbc-eee2d4291f69', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'd4538387-432c-4422-9618-3ffbedf83473', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'd65fe5a4-b207-4afa-8a88-7ca21dd7df7a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'd6744062-bdbb-4f75-a83e-51cdb9d96f5a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'd6872382-8bba-40be-953c-b999b1b5387c', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'd6c3dc71-a5a4-4468-bd6c-4c92c24d098b', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'd9579432-b71c-4b71-9f9d-606a7317446a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'da6b2620-828d-49e1-82d2-dda9217b0f6f', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'db010262-fa5b-494b-a961-3e6a40ceaf71', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'dc147005-906d-4373-90a0-c331cbc07b79', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'dd097886-0cee-4731-bc9a-da48eacece91', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'e19558fc-2a31-440b-b356-05a3c9af9804', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'e6c8ca0f-a219-41fe-9289-b07957104e7a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'ee6010ce-a330-4217-9674-07435ce22833', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'f28e981b-07b1-40cd-9071-aea501269627', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'f77a8ac8-6395-481d-a31e-c46b9f9b35c5', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'f858a70c-65e8-4edb-9e24-0d94c337b0d0', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'fc6c26c2-2abf-48d1-81d5-16e20c341b92', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('8ab91579-7891-4723-8da3-d13bef84cc72', 'fcabee71-1473-4020-84d8-6f7eaa9ebfe5', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '03c5a106-ed45-42d2-9467-e3448ed369b3', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '08580779-066d-4b3b-9985-124df63625a4', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '0a4aff69-ad1d-42b2-8634-00dc3e52360b', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '0f690e32-1e73-4190-9f87-e349f129451b', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '1e52ad08-670a-4425-9e72-3925ba871dcf', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '2ac1fd8d-2ca4-4eea-bd1c-f3989096eea2', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '31d43b76-ae60-4ce5-a04e-2d1d1ec2604b', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '382c1114-59db-4594-b870-da3ce1a29c56', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '3907df96-3152-4aba-9e23-a44575cc7251', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '3f9e4f79-1b00-4ce7-9187-62bd91ace077', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '4811a205-a4ec-499a-ba85-30ca5ab95feb', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '4a26ba61-676b-4842-a087-743eb0354203', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '588383d3-d8fe-4023-b9e7-220baac09a0d', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '5f4d2ab0-0cde-4bd3-829f-5a11d96b6440', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '60fea859-c085-4b37-8d7a-d03e81afe73a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '63a64d73-40df-4275-af16-c7c0fd382bf2', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '75300596-9c65-4e63-87c3-19c974e7bf1e', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '8b55c722-256a-40b3-ae27-1fdf99164094', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '92158f89-3eb8-462a-85c9-f9586075e274', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '92bfab0f-88e6-47ee-b2f2-5d0916f11ef1', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '99f5f7b2-d584-44f0-b93d-aee0b8030649', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', '9f1161f9-a3bb-42c8-9b8f-19b12aecf708', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', 'ac72da18-cd39-4a6c-baf7-d2f75ca7b4b7', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', 'baa9d8a3-0ea0-4689-9489-0a5ca387409c', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', 'bad80eed-ef69-4e42-8d36-ceea6df674d1', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', 'd4538387-432c-4422-9618-3ffbedf83473', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', 'd65fe5a4-b207-4afa-8a88-7ca21dd7df7a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', 'db010262-fa5b-494b-a961-3e6a40ceaf71', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', 'dc147005-906d-4373-90a0-c331cbc07b79', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', 'dd097886-0cee-4731-bc9a-da48eacece91', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2024ca4-e6fc-412f-964c-b8a3f6bc48fa', 'e6c8ca0f-a219-41fe-9289-b07957104e7a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '03c5a106-ed45-42d2-9467-e3448ed369b3', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '0875b602-8750-4d34-947b-0aa0491e9af8', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '0f690e32-1e73-4190-9f87-e349f129451b', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '1d244ec5-cf4e-445a-9374-aaddcb4d84f9', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '1e52ad08-670a-4425-9e72-3925ba871dcf', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '22900032-1fa4-4a53-bb04-f8b535ea9793', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '366472c2-cb67-4dd9-a8bb-2ae9f045b5c4', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '382c1114-59db-4594-b870-da3ce1a29c56', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '3a07101c-46ac-4ad7-824d-b2bf0de65b90', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '3d5e3491-7546-4046-acb3-d7b34fda210c', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '3f9e4f79-1b00-4ce7-9187-62bd91ace077', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '4a26ba61-676b-4842-a087-743eb0354203', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '4c0175ac-5b37-4ef5-a2dc-c14caa7b6e42', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '4dd18197-2477-421a-8e42-238c6298c7c9', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '54480923-4b9e-4c85-90c8-19712b709bb2', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '60fea859-c085-4b37-8d7a-d03e81afe73a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '75300596-9c65-4e63-87c3-19c974e7bf1e', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '7c259013-7919-4235-ab8c-bfcda9b51184', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '857bd274-30f4-429a-8004-a2e6d0ccb6de', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '8b55c722-256a-40b3-ae27-1fdf99164094', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '92158f89-3eb8-462a-85c9-f9586075e274', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', '9f1161f9-a3bb-42c8-9b8f-19b12aecf708', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', 'ac632dc7-9f6e-4d07-9d50-0561a456417d', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', 'baa9d8a3-0ea0-4689-9489-0a5ca387409c', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', 'bad80eed-ef69-4e42-8d36-ceea6df674d1', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', 'bdd9f5be-2460-41b9-8212-044bfae1a568', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', 'cb38b36a-c7ad-4899-bcbc-eee2d4291f69', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', 'd65fe5a4-b207-4afa-8a88-7ca21dd7df7a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', 'd6744062-bdbb-4f75-a83e-51cdb9d96f5a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', 'd8884521-f21e-4468-a50b-b3978022cef2', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', 'dd097886-0cee-4731-bc9a-da48eacece91', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', 'e6c8ca0f-a219-41fe-9289-b07957104e7a', NULL); +INSERT INTO `lms_clx_system_role_menu` VALUES ('f2b17336-e930-42f2-8c13-c2866f97c61b', 'fc6c26c2-2abf-48d1-81d5-16e20c341b92', NULL); + +-- ---------------------------- +-- Table structure for lms_clx_system_role_post +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_system_role_post`; +CREATE TABLE `lms_clx_system_role_post` ( + `post_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '职位ID', + `role_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色ID', + `sys_code` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '系统编码', + PRIMARY KEY (`post_id`, `role_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_system_role_post +-- ---------------------------- +INSERT INTO `lms_clx_system_role_post` VALUES ('0554940219d2404c8899b56f5ae897ec', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('188a85efef74471290669d449e5789e1', '53c735852284434ca6e95fe8ea3a47e5', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('188a85efef74471290669d449e5789e1', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('1f8d9dd4c9a0401e83e0dd79982890b7', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('1f8d9dd4c9a0401e83e0dd79982890b7', 'f2b17336-e930-42f2-8c13-c2866f97c61b', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('2a021458e76f4bf896a2456c57291091', '53c735852284434ca6e95fe8ea3a47e5', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('2a021458e76f4bf896a2456c57291091', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('2df734ef705447138f799a54134e2251', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('350ba82b46cb4c29b72929ce8476aa66', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('587cf60a2ef6421c985d11e6a8a3235b', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('5b98b7fbfc9247fb871bc7a15170e61a', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('5e29deab516047659a5fc49e2f9934b7', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('62e4443d0e0d453eb3566b2cc641420b', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('65c1018b37e54629bc05ee21a5678a7a', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('68d0f1b23fbf4caab80a59a6fa9eac59', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('6bd2c1239cea4b05a3506b014bbf2ecb', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('6cd4bb2c89f743e4b81c8ba68c7a9b9a', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('7a9975de7b5d4e90b77d3f0648aebb4e', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('80ecce66132d4c4ab819ad80cd4eb8b1', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('84842e4c959b4618aee97643a477d67b', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('85b046c440804270adedb160d3c5c370', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('88c0d1bf7f2349d4962214adc45e06ae', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('8cce953ef0be44beb95789cb7d1c340c', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('9259feda543b4bd7947554d484110c47', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('9259feda543b4bd7947554d484110c47', 'ee209a85eb494a5fa90bd5448d309736', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('94c8165538b341eeb8e7cb946cbcb85f', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('9622ec55cf024ae5a58438ea208763c2', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('a01b43446138406380035e9b44ce11f9', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('a472d8e7-1174-4bd7-ac57-b409183cda17', '8ab91579-7891-4723-8da3-d13bef84cc72', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('a863285750a44289ae4f796e42a7de9e', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('b318934bae6e4725a8410f0b547a73cb', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('b463667e989e4dc89e3c398420fdc7a1', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('b75429fad1e64e7687889bb21ce08bb2', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('b8ca9478e98c4909925d3c97291e640b', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('beb0fe2c46e14d258e19c4792662c4c5', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('d5091dab641142318f4fe4bb694f4a1b', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('d75623269c744f159c9d7dce78b43776', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('d7bd04120dac4027b5d5cc0ea99862f9', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('de8c56f7fe75469cadd4960ade356856', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('e4d9a482049f410e90393885be37db1a', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('ee2cecfef1de4c8fa3b26ed65400669f', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('ee4ac9b12a054088bb86687d50f8ddb7', '7ebf3afd23014766bba0007cb5a7250d', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('f11db8365bff4a3bacee844073199d63', '5f68648f4ee24982a629b0923cf3c1a1', NULL); +INSERT INTO `lms_clx_system_role_post` VALUES ('f11db8365bff4a3bacee844073199d63', '7ebf3afd23014766bba0007cb5a7250d', NULL); + +-- ---------------------------- +-- Table structure for lms_clx_wf_process_cc_instance +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_wf_process_cc_instance`; +CREATE TABLE `lms_clx_wf_process_cc_instance` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `process_instance_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程实例ID', + `actor_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '被抄送人ID', + `state` int(11) NULL DEFAULT 0 COMMENT '抄送状态(1:已读;0:未读)', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_pccins_pinsid`(`process_instance_id`) USING BTREE, + INDEX `idx_pccins_actor_id`(`actor_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程实例抄送' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_wf_process_cc_instance +-- ---------------------------- + +-- ---------------------------- +-- Table structure for lms_clx_wf_process_define +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_wf_process_define`; +CREATE TABLE `lms_clx_wf_process_define` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `type_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程分类', + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '唯一编码', + `display_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '显示名称', + `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '流程描述', + `state` int(11) NULL DEFAULT 0 COMMENT '流程是否可用(1可用;0不可用)', + `content` json NULL COMMENT '流程模型定义', + `version` int(11) NULL DEFAULT 0 COMMENT '版本', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', + `is_del` int(1) NULL DEFAULT 0 COMMENT '是否删除0 否1是', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_process_define_name`(`name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程定义' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_wf_process_define +-- ---------------------------- +INSERT INTO `lms_clx_wf_process_define` VALUES ('2324ca02-7392-4ce0-8ed3-7f0ad901e3aa', '58167035-5c04-42c0-bb08-33cc4eb994c3', 'leave', '员工请假', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"b8e00ac9-35fa-4a7d-afc8-7bc96f14a53b\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 440, \"y\": 280}, \"pointsList\": {\"0\": {\"x\": 318, \"y\": 280}, \"1\": {\"x\": 440, \"y\": 280}}, \"properties\": {}, \"startPoint\": {\"x\": 318, \"y\": 280}, \"sourceNodeId\": \"0263a08b-fdd8-4ba4-a72e-54d1a97981c1\", \"targetNodeId\": \"30f3d411-1d8f-494a-a1f4-20dc20f44eb4\"}, \"1\": {\"id\": \"d9439eac-036d-4169-ab43-8431203b64e2\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 680, \"y\": 280}, \"pointsList\": {\"0\": {\"x\": 560, \"y\": 280}, \"1\": {\"x\": 680, \"y\": 280}}, \"properties\": {}, \"startPoint\": {\"x\": 560, \"y\": 280}, \"sourceNodeId\": \"30f3d411-1d8f-494a-a1f4-20dc20f44eb4\", \"targetNodeId\": \"ca52b704-d477-47f0-9487-47cec10c9836\"}, \"2\": {\"id\": \"b06f3adf-a25b-414c-aeab-bc4edcf0f775\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 942, \"y\": 280}, \"pointsList\": {\"0\": {\"x\": 800, \"y\": 280}, \"1\": {\"x\": 942, \"y\": 280}}, \"properties\": {}, \"startPoint\": {\"x\": 800, \"y\": 280}, \"sourceNodeId\": \"ca52b704-d477-47f0-9487-47cec10c9836\", \"targetNodeId\": \"23509c29-1998-43ce-8524-b701d1810cbd\"}}, \"nodes\": {\"0\": {\"x\": 300, \"y\": 280, \"id\": \"0263a08b-fdd8-4ba4-a72e-54d1a97981c1\", \"text\": {\"x\": 300, \"y\": 320, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {}}, \"1\": {\"x\": 500, \"y\": 280, \"id\": \"30f3d411-1d8f-494a-a1f4-20dc20f44eb4\", \"text\": {\"x\": 500, \"y\": 280, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"scope\": 1, \"assignee\": \"\", \"task_type\": \"Major\", \"perform_type\": \"ANY\", \"back_permission\": 1, \"pre_interceptors\": \"\", \"post_interceptors\": \"\", \"assignment_handler\": \"\"}}, \"2\": {\"x\": 740, \"y\": 280, \"id\": \"ca52b704-d477-47f0-9487-47cec10c9836\", \"text\": {\"x\": 740, \"y\": 280, \"value\": \"主管审批:王强\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"scope\": 1, \"assignee\": \"1b408381-f510-4571-b473-006479eee7b1\", \"task_type\": \"Major\", \"perform_type\": \"ANY\", \"back_permission\": 1, \"pre_interceptors\": \"\", \"post_interceptors\": \"\", \"assignment_handler\": \"\"}}, \"3\": {\"x\": 960, \"y\": 280, \"id\": \"23509c29-1998-43ce-8524-b701d1810cbd\", \"text\": {\"x\": 960, \"y\": 320, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {}}}, \"type_id\": \"58167035-5c04-42c0-bb08-33cc4eb994c3\", \"expire_time\": \"\", \"display_name\": \"员工请假\", \"instance_url\": \"leaveForm.html\", \"instance_no_class\": \"\"}', 1, 1716863287, '1', 1716863287, NULL, 0); + +-- ---------------------------- +-- Table structure for lms_clx_wf_process_define_favorite +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_wf_process_define_favorite`; +CREATE TABLE `lms_clx_wf_process_define_favorite` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT 'ID', + `user_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '用户ID', + `process_define_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '流程定义ID', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `favorite` tinyint(3) NULL DEFAULT 1 COMMENT '收藏1', + `remark` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '备注', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '流程收藏表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_wf_process_define_favorite +-- ---------------------------- + +-- ---------------------------- +-- Table structure for lms_clx_wf_process_design +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_wf_process_design`; +CREATE TABLE `lms_clx_wf_process_design` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '唯一编码', + `display_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '显示名称', + `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '描述', + `type_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程分类', + `icon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标', + `is_deployed` tinyint(1) NULL DEFAULT 0 COMMENT '是否已部署', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', + `is_del` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除', + `remark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '备注', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_process_designer_name`(`name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程设计' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_wf_process_design +-- ---------------------------- +INSERT INTO `lms_clx_wf_process_design` VALUES ('373c17e7-54bf-4e2e-8205-87a8818d2bd1', 'test', '测试添加', '启动此流程,抛出信号,触发<请假继承集成>流程,并将数据带入表单。', '58167035-5c04-42c0-bb08-33cc4eb994c3', NULL, 1, 1705891323, '1', 1708217888, '1', 1, 'ads'); +INSERT INTO `lms_clx_wf_process_design` VALUES ('443b9e44-06d1-4660-b974-93e1f53da01d', 'leave', '员工请假', '启动此流程,抛出信号,触发<请假继承集成>流程,并将数据带入表单。', '58167035-5c04-42c0-bb08-33cc4eb994c3', '', 1, 1705327712, '1', 1716863287, '1', 0, ''); +INSERT INTO `lms_clx_wf_process_design` VALUES ('5d97e8e2-1bfa-4448-b415-65e9fd400d49', 'dsaf', 'asdf', '启动此流程,抛出信号,触发<请假继承集成>流程,并将数据带入表单。', '58167035-5c04-42c0-bb08-33cc4eb994c3', NULL, 0, 1706168559, '1', 1706170828, '1', 1, ''); + +-- ---------------------------- +-- Table structure for lms_clx_wf_process_design_history +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_wf_process_design_history`; +CREATE TABLE `lms_clx_wf_process_design_history` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `process_design_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程设计ID', + `content` json NULL COMMENT '流程模型定义', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `versions` float(3, 1) NULL DEFAULT 1.0 COMMENT '版本', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_process_design_his_pdid`(`process_design_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程设计历史' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_wf_process_design_history +-- ---------------------------- +INSERT INTO `lms_clx_wf_process_design_history` VALUES ('143e6d8d-465b-4037-a854-a612116211cb', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"b8e00ac9-35fa-4a7d-afc8-7bc96f14a53b\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 440, \"y\": 280}, \"pointsList\": [{\"x\": 318, \"y\": 280}, {\"x\": 440, \"y\": 280}], \"properties\": [], \"startPoint\": {\"x\": 318, \"y\": 280}, \"sourceNodeId\": \"0263a08b-fdd8-4ba4-a72e-54d1a97981c1\", \"targetNodeId\": \"30f3d411-1d8f-494a-a1f4-20dc20f44eb4\"}, {\"id\": \"d9439eac-036d-4169-ab43-8431203b64e2\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 680, \"y\": 280}, \"pointsList\": [{\"x\": 560, \"y\": 280}, {\"x\": 680, \"y\": 280}], \"properties\": [], \"startPoint\": {\"x\": 560, \"y\": 280}, \"sourceNodeId\": \"30f3d411-1d8f-494a-a1f4-20dc20f44eb4\", \"targetNodeId\": \"ca52b704-d477-47f0-9487-47cec10c9836\"}, {\"id\": \"b06f3adf-a25b-414c-aeab-bc4edcf0f775\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 942, \"y\": 280}, \"pointsList\": [{\"x\": 800, \"y\": 280}, {\"x\": 942, \"y\": 280}], \"properties\": [], \"startPoint\": {\"x\": 800, \"y\": 280}, \"sourceNodeId\": \"ca52b704-d477-47f0-9487-47cec10c9836\", \"targetNodeId\": \"23509c29-1998-43ce-8524-b701d1810cbd\"}], \"nodes\": [{\"x\": 300, \"y\": 280, \"id\": \"0263a08b-fdd8-4ba4-a72e-54d1a97981c1\", \"text\": {\"x\": 300, \"y\": 320, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": []}, {\"x\": 500, \"y\": 280, \"id\": \"30f3d411-1d8f-494a-a1f4-20dc20f44eb4\", \"text\": {\"x\": 500, \"y\": 280, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"scope\": \"1\", \"assignee\": \"\", \"task_type\": \"Major\", \"perform_type\": \"ANY\", \"back_permission\": \"1\", \"pre_interceptors\": \"\", \"post_interceptors\": \"\", \"assignment_handler\": \"\"}}, {\"x\": 740, \"y\": 280, \"id\": \"ca52b704-d477-47f0-9487-47cec10c9836\", \"text\": {\"x\": 740, \"y\": 280, \"value\": \"主管审批:王强\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"scope\": \"1\", \"assignee\": \"1b408381-f510-4571-b473-006479eee7b1\", \"task_type\": \"Major\", \"perform_type\": \"ANY\", \"back_permission\": \"1\", \"pre_interceptors\": \"\", \"post_interceptors\": \"\", \"assignment_handler\": \"\"}}, {\"x\": 960, \"y\": 280, \"id\": \"23509c29-1998-43ce-8524-b701d1810cbd\", \"text\": {\"x\": 960, \"y\": 320, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": []}], \"type_id\": \"58167035-5c04-42c0-bb08-33cc4eb994c3\", \"expire_time\": \"\", \"display_name\": \"员工请假\", \"instance_url\": \"leaveForm.html\", \"instance_no_class\": \"\"}', 1716863279, '1', 1.2); +INSERT INTO `lms_clx_wf_process_design_history` VALUES ('393ec58f-56c7-430d-8394-4087357194d2', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"b8e00ac9-35fa-4a7d-afc8-7bc96f14a53b\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 440, \"y\": 280}, \"pointsList\": [{\"x\": 318, \"y\": 280}, {\"x\": 440, \"y\": 280}], \"properties\": [], \"startPoint\": {\"x\": 318, \"y\": 280}, \"sourceNodeId\": \"0263a08b-fdd8-4ba4-a72e-54d1a97981c1\", \"targetNodeId\": \"30f3d411-1d8f-494a-a1f4-20dc20f44eb4\"}, {\"id\": \"d9439eac-036d-4169-ab43-8431203b64e2\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 680, \"y\": 280}, \"pointsList\": [{\"x\": 560, \"y\": 280}, {\"x\": 680, \"y\": 280}], \"properties\": [], \"startPoint\": {\"x\": 560, \"y\": 280}, \"sourceNodeId\": \"30f3d411-1d8f-494a-a1f4-20dc20f44eb4\", \"targetNodeId\": \"ca52b704-d477-47f0-9487-47cec10c9836\"}, {\"id\": \"b06f3adf-a25b-414c-aeab-bc4edcf0f775\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 942, \"y\": 280}, \"pointsList\": [{\"x\": 800, \"y\": 280}, {\"x\": 942, \"y\": 280}], \"properties\": [], \"startPoint\": {\"x\": 800, \"y\": 280}, \"sourceNodeId\": \"ca52b704-d477-47f0-9487-47cec10c9836\", \"targetNodeId\": \"23509c29-1998-43ce-8524-b701d1810cbd\"}], \"nodes\": [{\"x\": 300, \"y\": 280, \"id\": \"0263a08b-fdd8-4ba4-a72e-54d1a97981c1\", \"text\": {\"x\": 300, \"y\": 320, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": []}, {\"x\": 500, \"y\": 280, \"id\": \"30f3d411-1d8f-494a-a1f4-20dc20f44eb4\", \"text\": {\"x\": 500, \"y\": 280, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"scope\": \"1\", \"assignee\": \"\", \"task_type\": \"Major\", \"perform_type\": \"ANY\", \"back_permission\": \"1\", \"pre_interceptors\": \"\", \"post_interceptors\": \"\", \"assignment_handler\": \"\"}}, {\"x\": 740, \"y\": 280, \"id\": \"ca52b704-d477-47f0-9487-47cec10c9836\", \"text\": {\"x\": 740, \"y\": 280, \"value\": \"主管审批:王强\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"scope\": \"1\", \"assignee\": \"\", \"task_type\": \"Major\", \"perform_type\": \"ANY\", \"back_permission\": \"1\", \"pre_interceptors\": \"\", \"post_interceptors\": \"\", \"assignment_handler\": \"\"}}, {\"x\": 960, \"y\": 280, \"id\": \"23509c29-1998-43ce-8524-b701d1810cbd\", \"text\": {\"x\": 960, \"y\": 320, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": []}], \"type_id\": \"58167035-5c04-42c0-bb08-33cc4eb994c3\", \"expire_time\": \"\", \"display_name\": \"员工请假\", \"instance_url\": \"\", \"instance_no_class\": \"\"}', 1716863074, '1', 1.0); +INSERT INTO `lms_clx_wf_process_design_history` VALUES ('735649d7-dcb7-4e4f-bfa9-0d4c016d8b35', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"b8e00ac9-35fa-4a7d-afc8-7bc96f14a53b\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 440, \"y\": 280}, \"pointsList\": [{\"x\": 318, \"y\": 280}, {\"x\": 440, \"y\": 280}], \"properties\": [], \"startPoint\": {\"x\": 318, \"y\": 280}, \"sourceNodeId\": \"0263a08b-fdd8-4ba4-a72e-54d1a97981c1\", \"targetNodeId\": \"30f3d411-1d8f-494a-a1f4-20dc20f44eb4\"}, {\"id\": \"d9439eac-036d-4169-ab43-8431203b64e2\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 680, \"y\": 280}, \"pointsList\": [{\"x\": 560, \"y\": 280}, {\"x\": 680, \"y\": 280}], \"properties\": [], \"startPoint\": {\"x\": 560, \"y\": 280}, \"sourceNodeId\": \"30f3d411-1d8f-494a-a1f4-20dc20f44eb4\", \"targetNodeId\": \"ca52b704-d477-47f0-9487-47cec10c9836\"}, {\"id\": \"b06f3adf-a25b-414c-aeab-bc4edcf0f775\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 942, \"y\": 280}, \"pointsList\": [{\"x\": 800, \"y\": 280}, {\"x\": 942, \"y\": 280}], \"properties\": [], \"startPoint\": {\"x\": 800, \"y\": 280}, \"sourceNodeId\": \"ca52b704-d477-47f0-9487-47cec10c9836\", \"targetNodeId\": \"23509c29-1998-43ce-8524-b701d1810cbd\"}], \"nodes\": [{\"x\": 300, \"y\": 280, \"id\": \"0263a08b-fdd8-4ba4-a72e-54d1a97981c1\", \"text\": {\"x\": 300, \"y\": 320, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": []}, {\"x\": 500, \"y\": 280, \"id\": \"30f3d411-1d8f-494a-a1f4-20dc20f44eb4\", \"text\": {\"x\": 500, \"y\": 280, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"scope\": \"1\", \"assignee\": \"\", \"task_type\": \"Major\", \"perform_type\": \"ANY\", \"back_permission\": \"1\", \"pre_interceptors\": \"\", \"post_interceptors\": \"\", \"assignment_handler\": \"\"}}, {\"x\": 740, \"y\": 280, \"id\": \"ca52b704-d477-47f0-9487-47cec10c9836\", \"text\": {\"x\": 740, \"y\": 280, \"value\": \"主管审批:王强\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"scope\": \"1\", \"assignee\": \"1b408381-f510-4571-b473-006479eee7b1\", \"task_type\": \"Major\", \"perform_type\": \"ANY\", \"back_permission\": \"1\", \"pre_interceptors\": \"\", \"post_interceptors\": \"\", \"assignment_handler\": \"\"}}, {\"x\": 960, \"y\": 280, \"id\": \"23509c29-1998-43ce-8524-b701d1810cbd\", \"text\": {\"x\": 960, \"y\": 320, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": []}], \"type_id\": \"58167035-5c04-42c0-bb08-33cc4eb994c3\", \"expire_time\": \"\", \"display_name\": \"员工请假\", \"instance_url\": \"\", \"instance_no_class\": \"\"}', 1716863246, '1', 1.1); + +-- ---------------------------- +-- Table structure for lms_clx_wf_process_form +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_wf_process_form`; +CREATE TABLE `lms_clx_wf_process_form` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '唯一编码', + `display_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '显示名称', + `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '描述', + `type_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程分类', + `icon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标', + `is_deployed` tinyint(1) NULL DEFAULT 0 COMMENT '是否已部署', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', + `is_del` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除', + `remark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '备注', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_process_form_name`(`name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '表单设计' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_wf_process_form +-- ---------------------------- + +-- ---------------------------- +-- Table structure for lms_clx_wf_process_form_history +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_wf_process_form_history`; +CREATE TABLE `lms_clx_wf_process_form_history` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `process_form_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `content` json NULL COMMENT '模型定义', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `versions` float(3, 1) NULL DEFAULT 1.0 COMMENT '版本', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_process_design_his_pdid`(`process_form_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '表单设计历史' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_wf_process_form_history +-- ---------------------------- + +-- ---------------------------- +-- Table structure for lms_clx_wf_process_instance +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_wf_process_instance`; +CREATE TABLE `lms_clx_wf_process_instance` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `parent_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父流程ID,子流程实例才有值', + `process_define_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程定义ID', + `state` int(11) NULL DEFAULT NULL COMMENT '流程实例状态(10:进行中;20:已完成;30:已撤回;40:强行中止;50:挂起;99:已废弃)', + `parent_node_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父流程依赖的节点名称', + `business_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '业务编号', + `operator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程发起人', + `variable` json NULL COMMENT '附属变量json存储', + `expire_time` int(10) NULL DEFAULT NULL COMMENT '期望完成时间', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `update_time` int(3) NULL DEFAULT NULL COMMENT '更新时间', + `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_process_instance_pfid`(`process_define_id`) USING BTREE, + INDEX `idx_process_instance_operator`(`operator`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程实例' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_wf_process_instance +-- ---------------------------- +INSERT INTO `lms_clx_wf_process_instance` VALUES ('f938c5b1-2d09-43a6-8643-81d6f3ca6784', NULL, '2324ca02-7392-4ce0-8ed3-7f0ad901e3aa', 10, NULL, '202405281028316949', '1', '{\"f_day\": \"1\", \"f_reason\": \"测试\", \"u_dept_id\": \"b9191372-1051-45aa-aa32-63b6eca5f1c1\", \"u_post_id\": \"7de1c1af-af39-4687-bda6-9ba6d20cdbe4\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-28 10:28:26\", \"u_dept_name\": \"上海集团总部\", \"u_post_name\": \"超级管理员\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-28 10:28:24\", \"auto_gen_title\": \"超级管理员的员工请假-2024-05-28 10:28\", \"process_define_id\": \"2324ca02-7392-4ce0-8ed3-7f0ad901e3aa\"}', NULL, 1716863311, NULL, 1716863311, NULL); + +-- ---------------------------- +-- Table structure for lms_clx_wf_process_surrogate +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_wf_process_surrogate`; +CREATE TABLE `lms_clx_wf_process_surrogate` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `process_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程名称', + `operator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '授权人', + `surrogate` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '代理人', + `start_time` int(11) NULL DEFAULT NULL COMMENT '授权开始时间', + `end_time` int(11) NULL DEFAULT NULL COMMENT '授权结束时间', + `enabled` tinyint(1) NULL DEFAULT 1 COMMENT '是否启用', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程委托代理' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_wf_process_surrogate +-- ---------------------------- + +-- ---------------------------- +-- Table structure for lms_clx_wf_process_task +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_wf_process_task`; +CREATE TABLE `lms_clx_wf_process_task` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `process_instance_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程实例ID', + `task_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务名称编码', + `display_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务显示名称', + `task_type` int(11) NULL DEFAULT NULL COMMENT '任务类型(0:主办任务;1:协办任务)', + `perform_type` int(11) NULL DEFAULT NULL COMMENT '参与类型(0:普通参与;1:会签参与)', + `task_state` int(11) NULL DEFAULT NULL COMMENT '任务状态(10:进行中;20:已完成;30:已撤回;40:强行中止;50:挂起;99:已废弃)', + `operator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '任务处理人', + `finish_time` int(10) NULL DEFAULT NULL COMMENT '任务完成时间', + `expire_time` int(10) NULL DEFAULT NULL COMMENT '任务期待完成时间', + `form_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '任务处理表单KEY', + `task_parent_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父任务ID', + `variable` json NULL COMMENT '附属变量json存储', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_process_task_piid`(`process_instance_id`) USING BTREE, + INDEX `idx_process_task_name`(`task_name`) USING BTREE, + INDEX `idx_process_task_operator`(`operator`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程任务' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_wf_process_task +-- ---------------------------- +INSERT INTO `lms_clx_wf_process_task` VALUES ('3ab5f33e-3825-435e-92ef-609039003a17', 'f938c5b1-2d09-43a6-8643-81d6f3ca6784', '30f3d411-1d8f-494a-a1f4-20dc20f44eb4', '申请人', NULL, 0, 20, 'flow_auto', 1716863311, NULL, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"测试\", \"u_dept_id\": \"b9191372-1051-45aa-aa32-63b6eca5f1c1\", \"u_post_id\": \"7de1c1af-af39-4687-bda6-9ba6d20cdbe4\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-28 10:28:26\", \"submit_type\": 0, \"u_dept_name\": \"上海集团总部\", \"u_post_name\": \"超级管理员\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-28 10:28:24\", \"reminder_time\": \"\", \"auto_gen_title\": \"超级管理员的员工请假-2024-05-28 10:28\", \"reminder_repeat\": \"\", \"process_define_id\": \"2324ca02-7392-4ce0-8ed3-7f0ad901e3aa\", \"is_first_task_node\": true}', 1716863311, NULL, 1716863311, 'flow_auto'); +INSERT INTO `lms_clx_wf_process_task` VALUES ('79c2e6e0-3927-4eda-9271-074abafa0aee', 'f938c5b1-2d09-43a6-8643-81d6f3ca6784', 'ca52b704-d477-47f0-9487-47cec10c9836', '主管审批:王强', NULL, 0, 10, NULL, NULL, NULL, NULL, '3ab5f33e-3825-435e-92ef-609039003a17', '{\"f_day\": \"1\", \"f_reason\": \"测试\", \"u_dept_id\": \"b9191372-1051-45aa-aa32-63b6eca5f1c1\", \"u_post_id\": \"7de1c1af-af39-4687-bda6-9ba6d20cdbe4\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-28 10:28:26\", \"submit_type\": 0, \"u_dept_name\": \"上海集团总部\", \"u_post_name\": \"超级管理员\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-28 10:28:24\", \"reminder_time\": \"\", \"auto_gen_title\": \"超级管理员的员工请假-2024-05-28 10:28\", \"reminder_repeat\": \"\", \"process_define_id\": \"2324ca02-7392-4ce0-8ed3-7f0ad901e3aa\", \"is_first_task_node\": false}', 1716863311, NULL, 1716863311, NULL); + +-- ---------------------------- +-- Table structure for lms_clx_wf_process_task_actor +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_wf_process_task_actor`; +CREATE TABLE `lms_clx_wf_process_task_actor` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `process_task_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程任务ID', + `actor_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '参与者ID', + `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', + `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_process_task_actor_ptid`(`process_task_id`) USING BTREE, + INDEX `idx_process_task_actor_aid`(`actor_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程任务和参与人关系' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_wf_process_task_actor +-- ---------------------------- +INSERT INTO `lms_clx_wf_process_task_actor` VALUES ('f6b5c94a-ab6a-4bd8-9a6e-85ceafc5b83c', '79c2e6e0-3927-4eda-9271-074abafa0aee', '1b408381-f510-4571-b473-006479eee7b1', 1716863311, NULL); + +-- ---------------------------- +-- Table structure for lms_clx_wf_process_type +-- ---------------------------- +DROP TABLE IF EXISTS `lms_clx_wf_process_type`; +CREATE TABLE `lms_clx_wf_process_type` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `pid` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0' COMMENT '父id', + `icon` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'icon', + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '分组名称', + `sort` int(11) NULL DEFAULT 0 COMMENT '排序', + `status` tinyint(3) NULL DEFAULT 1 COMMENT '1启用 2禁用', + `create_time` int(10) NOT NULL COMMENT '创建时间', + `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', + `update_user` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', + `create_user` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `is_del` tinyint(3) NOT NULL DEFAULT 0 COMMENT '1删除 默认0', + `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '模型分组' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of lms_clx_wf_process_type +-- ---------------------------- +INSERT INTO `lms_clx_wf_process_type` VALUES ('0a67e17d-7878-47f2-93d2-a960367178cc', '0', 'ele-Folder', '行政', 0, 1, 1706087406, 1706171994, '1', '1', 0, ''); +INSERT INTO `lms_clx_wf_process_type` VALUES ('3606568e-2a81-4cd1-b5f5-0aba6c414746', 'c1bf068a-aec7-4801-9160-d61af713330c', 'ele-Folder', '业务流程', 0, 1, 1706172538, 1706172538, NULL, '1', 0, ''); +INSERT INTO `lms_clx_wf_process_type` VALUES ('4295de01-f687-4c1e-b7ad-20bed8d1eaf5', '0', 'ele-House', 'OA', 10, 1, 1706087453, 1706172391, '1', '1', 0, ''); +INSERT INTO `lms_clx_wf_process_type` VALUES ('58167035-5c04-42c0-bb08-33cc4eb994c3', '0', 'ele-UserFilled', '人事', 0, 1, 1706087412, 1706171963, '1', '1', 0, ''); +INSERT INTO `lms_clx_wf_process_type` VALUES ('c1bf068a-aec7-4801-9160-d61af713330c', '0', 'ele-HomeFilled', '集团流程库', -1, 1, 1706172341, 1706172450, '1', '1', 0, ''); +INSERT INTO `lms_clx_wf_process_type` VALUES ('d7dc0900-1609-44e9-a60c-586d086fb130', '0a67e17d-7878-47f2-93d2-a960367178cc', NULL, '总务', 0, 1, 1706088738, 1706088738, NULL, '1', 0, ''); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/demo/thinkphp/backend/extend/.gitignore b/demo/thinkphp/backend/extend/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c96a04f008ee21e260b28f7701595ed59e2839e3 --- /dev/null +++ b/demo/thinkphp/backend/extend/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/demo/thinkphp/backend/phoenix/basic/BaseController.php b/demo/thinkphp/backend/phoenix/basic/BaseController.php new file mode 100644 index 0000000000000000000000000000000000000000..dcc51e280990c34dd3923cf55aacc90ce9412318 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/basic/BaseController.php @@ -0,0 +1,68 @@ + +// +---------------------------------------------------------------------- +declare (strict_types=1); + +namespace phoenix\basic; + +use think\App; + +/** + * 控制器基础类 + */ +abstract class BaseController +{ + /** + * Request实例 + * @var \app\Request + */ + protected $request; + + /** + * 应用实例 + * @var \think\App + */ + protected $app; + + /** + * 控制器中间件 + * @var array + */ + protected $middleware = []; + + /** + * @var + */ + protected $services; + + /** + * 需要授权的接口地址 + * @var string[] + */ + private $authRule = []; + /** + * 构造方法 + * @access public + * @param App $app 应用对象 + */ + public function __construct(App $app) + { + $this->app = $app; + $this->request = app('request'); + $this->initialize(); + } + + /** + * @return mixed + */ + abstract protected function initialize(); + + +} diff --git a/demo/thinkphp/backend/phoenix/basic/BaseJobs.php b/demo/thinkphp/backend/phoenix/basic/BaseJobs.php new file mode 100644 index 0000000000000000000000000000000000000000..200eeb06ab1065ee191c86ad343550a199477f8b --- /dev/null +++ b/demo/thinkphp/backend/phoenix/basic/BaseJobs.php @@ -0,0 +1,82 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\basic; + +use phoenix\interfaces\JobInterface; +use think\queue\Job; + +/** + * 消息队列基类 + * + * @author Mr.April + * @since 1.0 + */ +abstract class BaseJobs implements JobInterface +{ + + /** + * @param $name + * @param $arguments + */ + public function __call($name, $arguments) + { + $this->fire(...$arguments); + } + + /** + * 运行消息队列 + * + * @param $job + * @param $data + */ + public function fire($job, $data): void + { + try { + $action = $data['do'] ?? 'doJob';//任务名 + $infoData = $data['data'] ?? [];//执行数据 + $errorCount = $data['errorCount'] ?? 0;//最大错误次数 + $this->runJob($action, $job, $infoData, $errorCount); + } catch (\Throwable $e) { + $job->delete(); + } + } + + /** + * 执行队列 + * + * @param string $action + * @param Job $job + * @param array $infoData + * @param int $errorCount + */ + protected function runJob(string $action, Job $job, array $infoData, int $errorCount = 3) + { + $action = method_exists($this, $action) ? $action : 'handle'; + if (!method_exists($this, $action)) { + $job->delete(); + } + + if ($this->{$action}(...$infoData)) { + //删除任务 + $job->delete(); + } else { + if ($job->attempts() >= $errorCount && $errorCount) { + //删除任务 + $job->delete(); + } else { + //从新放入队列 + $job->release(); + } + } + + } +} diff --git a/demo/thinkphp/backend/phoenix/basic/BaseManager.php b/demo/thinkphp/backend/phoenix/basic/BaseManager.php new file mode 100644 index 0000000000000000000000000000000000000000..cface59ea3ec3c135d16c8ea0979b14f25f5e1bf --- /dev/null +++ b/demo/thinkphp/backend/phoenix/basic/BaseManager.php @@ -0,0 +1,219 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\basic; + +use think\facade\Config; +use think\helper\Str; +use think\Container; + +/** + * Class BaseManager + * @package crmeb\basic + */ +abstract class BaseManager +{ + /** + * 驱动的命名空间 + * @var null + */ + protected $namespace = null; + + /** + * 配置 + * @var null + */ + protected $configFile = null; + + /** + * 配置 + * @var array + */ + protected $config = []; + + /** + * 驱动 + * @var array + */ + protected $drivers = []; + + /** + * 驱动类型 + * @var null + */ + protected $name = null; + + /** + * BaseManager constructor. + * @param string|array|int $name驱动名称 + * @param array $config 配置 + */ + public function __construct($name = null, array $config = []) + { + $type = null; + if (is_array($name)) { + $config = $name; + $name = null; + } + + if (is_int($name)) { + $type = $name; + $name = null; + } + + if ($name) + $this->name = $name; + if ($type && is_null($this->name)) { + $this->setHandleType((int)$type - 1); + } + $this->config = $config; + } + + /** + * 提取配置文件名 + * @return $this + */ + protected function getConfigFile() + { + if (is_null($this->configFile)) { + $this->configFile = strtolower((new \ReflectionClass($this))->getShortName()); + } + return $this; + } + + /** + * 设置文件句柄 + * @param int $type + */ + protected function setHandleType(int $type) + { + $this->getConfigFile(); + $stores = array_keys(Config::get($this->configFile . '.stores', [])); + $name = $stores[$type] ?? null; + if (!$name) { + throw new \RuntimeException($this->configFile . ' type is not used'); + } + $this->name = $name; + } + + /** + * 设置默认句柄 + * @return mixed + */ + abstract protected function getDefaultDriver(); + + /** + * 动态调用 + * @param $method + * @param $arguments + * @return mixed + */ + public function __call($method, $arguments) + { + return $this->driver()->{$method}(...$arguments); + } + + /** + * 获取驱动实例 + * @param null|string $name + * @return mixed + */ + protected function driver(string $name = null) + { + $name = $name ?: $this->name; + $name = $name ?: $this->getDefaultDriver(); + + if (is_null($name)) { + throw new \InvalidArgumentException(sprintf( + 'Unable to resolve NULL driver for [%s].', static::class + )); + } + + return $this->drivers[$name] = $this->getDriver($name); + } + + /** + * 获取驱动实例 + * @param string $name + * @return mixed + */ + protected function getDriver(string $name) + { + return $this->drivers[$name] ?? $this->createDriver($name); + } + + /** + * 获取驱动类型 + * @param string $name + * @return mixed + */ + protected function resolveType(string $name) + { + return $name; + } + + /** + * 创建驱动 + * + * @param string $name + * @return mixed + * + */ + protected function createDriver(string $name) + { + $type = $this->resolveType($name); + + $method = 'create' . Str::studly($type) . 'Driver'; + + if (method_exists($this, $method)) { + return $this->$method($name); + } + + $class = $this->resolveClass($type); + $this->name = $type; + return $this->invokeClass($class); + } + + + /** + * 获取驱动类 + * @param string $type + * @return string + */ + protected function resolveClass(string $type): string + { + if ($this->namespace || false !== strpos($type, '\\')) { + $class = false !== strpos($type, '\\') ? $type : $this->namespace . Str::studly($type); + if (class_exists($class)) { + return $class; + } + } + + throw new \InvalidArgumentException("Driver [$type] not supported."); + } + + /** + * 实例化类 + * @param $class + * @return mixed + */ + protected function invokeClass($class) + { + if (!class_exists($class)) { + throw new \RuntimeException('class not exists: ' . $class); + } + $this->getConfigFile(); + $handle = Container::getInstance()->invokeClass($class, [$this->name, $this->config, $this->configFile]); + $this->config = []; + return $handle; + } + +} diff --git a/demo/thinkphp/backend/phoenix/basic/BaseModel.php b/demo/thinkphp/backend/phoenix/basic/BaseModel.php new file mode 100644 index 0000000000000000000000000000000000000000..7f1871b16cef59c969ce50e18b0066af5388547f --- /dev/null +++ b/demo/thinkphp/backend/phoenix/basic/BaseModel.php @@ -0,0 +1,52 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\basic; + +use phoenix\traits\ModelTrait; +use Ramsey\Uuid\Uuid; +use think\Model; + +/** + * Class BaseModel + * + * @package crmeb\basic + * @mixin ModelTrait + */ +class BaseModel extends Model +{ + + /** + * 获取模型定义的字段列表 + * + * @return mixed + */ + public function getFields(): mixed + { + return $this->getTableFields(); + } + + /** + * 获取模型定义的数据库表名【全称】 + */ + public static function getTableName(): string + { + $self = (new static()); + return $self->getConfig('prefix') . $self->name; + } + + public static function getTableNameNoPrefix(): string + { + $self = (new static()); + return $self->name; + } + +} diff --git a/demo/thinkphp/backend/phoenix/basic/BaseStorage.php b/demo/thinkphp/backend/phoenix/basic/BaseStorage.php new file mode 100644 index 0000000000000000000000000000000000000000..e2c24767ab3cfe8c54ccfc937bbbd7393e486942 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/basic/BaseStorage.php @@ -0,0 +1,89 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\basic; + +/** + * Class BaseStorage + * + * @package crmeb\basic + */ +abstract class BaseStorage +{ + + /** + * 驱动名称 + * + * @var string + */ + protected $name; + + /** + * 驱动配置文件名 + * + * @var string + */ + protected string $configFile; + + /** + * 错误信息 + * + * @var string|null + */ + protected string|null $error; + + /** + * BaseStorage constructor. + * + * @param string $name 驱动名 + * @param array $config 其他配置 + * @param string|null $configFile 驱动配置名 + */ + public function __construct(string $name, array $config = [], string $configFile = null) + { + $this->name = $name; + $this->configFile = $configFile; + $this->initialize($config); + } + + /** + * 设置错误信息 + * + * @param string|null $error + * + * @return bool + */ + protected function setError(?string $error = null): bool + { + $this->error = $error ?: '未知错误'; + return false; + } + + /** + * 获取错误信息 + * + * @return string + */ + public function getError(): string + { + $error = $this->error; + $this->error = null; + return $error; + } + + /** + * 初始化 + * + * @param array $config + */ + abstract protected function initialize(array $config); + +} diff --git a/demo/thinkphp/backend/phoenix/command/Npm.php b/demo/thinkphp/backend/phoenix/command/Npm.php new file mode 100644 index 0000000000000000000000000000000000000000..8a559c3b7e9702af68941d4902c0d2f2f72b47a2 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/command/Npm.php @@ -0,0 +1,89 @@ + + * +---------------------------------------------------------------------- + */ + +namespace phoenix\command; + +use phoenix\services\FileService; +use phoenix\utils\Terminal; +use think\console\Command; +use think\console\input\Argument; +use think\console\input\Option; + +/** + * Class Npm + * + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + * @package crmeb\command + */ +class Npm extends Command +{ + /** + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + protected function configure() + { + $this->setName('npm') + ->addOption('path', 'dp', Option::VALUE_OPTIONAL, '默认路径') + ->addOption('build', 'bu', Option::VALUE_OPTIONAL, '打包存放路径') + ->setDescription('NPM打包工具'); + } + + /** + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + public function handle() + { + $path = $this->input->getOption('path'); + $build = $this->input->getOption('build'); + if (!$build) { + $build = public_path() . 'admin'; + } + + $terminal = new Terminal(); + $terminal->setOutput($this->output); + + $adminPath = $path ?: $terminal->adminTemplatePath(); + + $adminPath = dirname($adminPath); + + if (is_dir($adminPath . DS . 'dist')) { + $question = $this->output->confirm($this->input, '检测到已经生成打包文件是否重新打包?', false); + if (!$question) { + $this->output->info('已退出打包程序'); + return; + } + } + + $dir = $adminPath . DS . 'node_modules'; + if (!is_dir($dir)) { + $terminal->run('npm-install'); + } + + $terminal->run('npm-build'); + + if (!is_dir($adminPath . DS . 'dist')) { + $this->output->error('打包失败'); + return; + } + + $this->app->make(FileService::class)->copyDir($adminPath . DS . 'dist', $build); + + $this->output->info('执行成功'); + } +} diff --git a/demo/thinkphp/backend/phoenix/command/Timer.php b/demo/thinkphp/backend/phoenix/command/Timer.php new file mode 100644 index 0000000000000000000000000000000000000000..33e2179a3ffc871997e9a017ae73ae92e7a6fe5a --- /dev/null +++ b/demo/thinkphp/backend/phoenix/command/Timer.php @@ -0,0 +1,70 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\command; + +use think\console\Command; +use think\console\Input; +use think\console\input\Argument; +use think\console\input\Option; +use think\console\Output; +use Workerman\Worker; + +class Timer extends Command +{ + /** + * @var int + */ + protected int $timer; + + /** + * @var int|float + */ + protected int|float $interval = 1; + + protected function configure() + { + // 指令配置 + $this->setName('timer') + ->addArgument('status', Argument::REQUIRED, 'start/stop/reload/status/connections') + ->addOption('d', null, Option::VALUE_NONE, 'daemon(守护进程)方式启动') + ->addOption('i', null, Option::VALUE_OPTIONAL, '多长时间执行一次,可以精确到0.001') + ->setDescription('start/stop/restart 定时任务'); + } + + protected function init(Input $input, Output $output) + { + global $argv; + if ($input->hasOption('i')) { + $this->interval = floatval($input->getOption('i')); + } + $argv[1] = $input->getArgument('status') ?: 'start'; + if ($input->hasOption('d')) { + $argv[2] = '-d'; + } else { + unset($argv[2]); + } + } + + protected function execute(Input $input, Output $output) + { + $this->init($input, $output); + Worker::$pidFile = app()->getRootPath() . 'runtime/timer.pid'; + $task = new Worker(); + + date_default_timezone_set('PRC');//设置成中国时区 + $task->count = 1; + $task->onWorkerStart = function () { + event('CrontabListener'); + + }; + $task->runAll(); + } +} diff --git a/demo/thinkphp/backend/phoenix/command/Util.php b/demo/thinkphp/backend/phoenix/command/Util.php new file mode 100644 index 0000000000000000000000000000000000000000..91c9a8482aae82e08f09f81d3654718d60e585e9 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/command/Util.php @@ -0,0 +1,233 @@ +setName('util') + ->addArgument('type', Argument::REQUIRED, '类型replace/route/file/apifox') + ->addOption('h', null, Option::VALUE_REQUIRED, '替换成当前域名') + ->addOption('u', null, Option::VALUE_REQUIRED, '替换的域名') + ->addOption('a', null, Option::VALUE_REQUIRED, '应用名') + ->addOption('f', null, Option::VALUE_REQUIRED, '导入文件路径,文件只能在项目根目录下或者根目录下的其他文件夹内') + ->setDescription('工具类'); + } + + protected function execute(Input $input, Output $output) + { + $type = $input->getArgument('type'); + + switch ($type) { + case 'replace': + $host = $input->getOption('h'); + $url = $input->getOption('u'); + if (!$host) { + return $output->error('缺少替换域名'); + } + if (!$url) { + return $output->error('缺少替换的域名'); + } + $this->replaceSiteUrl($url, $host); + break; + case 'route': + $appName = $input->getOption('a'); + if (!$appName) { + return $output->error('缺少应用名称'); + } + app()->make(SystemRouteServices::class)->syncRoute($appName); + break; + case 'file': + app()->make(SystemFileInfoServices::class)->syncfile(); + break; + case 'apifox': + $filePath = $input->getOption('f'); + if (!$filePath) { + return $output->error('缺少导入文件地址'); + } + $this->import($filePath); + break; + } + + $output->info('执行成功'); + } + + protected function replaceSiteUrl(string $url, string $siteUrl) + { + $siteUrlJosn = str_replace('http://', 'http:\\\/\\\/', $siteUrl); + $siteUrlJosn = str_replace('https://', 'https:\\\/\\\/', $siteUrlJosn); + $valueJosn = str_replace('http://', 'http:\\\/\\\/', $url); + $valueJosn = str_replace('https://', 'https:\\\/\\\/', $valueJosn); + $prefix = Config::get('database.connections.' . Config::get('database.default') . '.prefix'); + $sql = [ + "UPDATE `{$prefix}article` SET `image_input` = replace(`image_input` ,'{$siteUrl}','{$url}')", + "UPDATE `{$prefix}article_category` SET `image` = replace(`image` ,'{$siteUrl}','{$url}')", + "UPDATE `{$prefix}article_content` SET `content` = replace(`content` ,'{$siteUrl}','{$url}')", + "UPDATE `{$prefix}diy` SET `value` = replace(value ,'{$siteUrlJosn}','{$valueJosn}'),`default_value` = replace(default_value ,'{$siteUrlJosn}','{$valueJosn}')", + "UPDATE `{$prefix}luck_lottery` SET `image` = replace(image ,'{$siteUrlJosn}','{$valueJosn}')", + "UPDATE `{$prefix}luck_prize` SET `image` = replace(image ,'{$siteUrlJosn}','{$valueJosn}')", + "UPDATE `{$prefix}store_bargain` SET `image` = replace(image ,'{$siteUrl}','{$url}'),`images` = replace(images,'{$siteUrlJosn}','{$valueJosn}')", + "UPDATE `{$prefix}store_category` SET `pic` = replace(`pic` ,'{$siteUrl}','{$url}'),`big_pic` = replace(`big_pic` ,'{$siteUrl}','{$url}')", + "UPDATE `{$prefix}store_combination` SET `image` = replace(image ,'{$siteUrl}','{$url}'),`images` = replace(images,'{$siteUrlJosn}','{$valueJosn}')", + "UPDATE `{$prefix}store_integral` SET `image` = replace(image ,'{$siteUrl}','{$url}'),`images` = replace(images,'{$siteUrlJosn}','{$valueJosn}')", + "UPDATE `{$prefix}store_product` SET `image` = replace(image ,'{$siteUrl}','{$url}'),`slider_image` = replace(slider_image ,'{$siteUrlJosn}','{$valueJosn}'),`recommend_image` = replace(recommend_image ,'{$siteUrlJosn}','{$valueJosn}')", + "UPDATE `{$prefix}store_product_attr_result` SET `result` = replace(result ,'{$siteUrl}','{$url}')", + "UPDATE `{$prefix}store_product_attr_value` SET `image` = replace(image ,'{$siteUrl}','{$url}')", + "UPDATE `{$prefix}store_product_description` SET `description`= replace(description,'{$siteUrl}','{$url}')", + "UPDATE `{$prefix}store_seckill` SET `image` = replace(image ,'{$siteUrl}','{$url}'),`images` = replace(images,'{$siteUrlJosn}','{$valueJosn}')", + "UPDATE `{$prefix}system_attachment` SET `att_dir` = replace(att_dir ,'{$siteUrl}','{$url}'),`satt_dir` = replace(satt_dir ,'{$siteUrl}','{$url}')", + "UPDATE `{$prefix}system_config` SET `value` = replace(value ,'{$siteUrlJosn}','{$valueJosn}')", + "UPDATE `{$prefix}system_group_data` SET `value` = replace(value ,'{$siteUrlJosn}','{$valueJosn}')", + "UPDATE `{$prefix}user` SET `avatar` = replace(avatar ,'{$siteUrlJosn}','{$valueJosn}')", + ]; + + return Db::transaction(function () use ($sql) { + try { + foreach ($sql as $item) { + Db::execute($item); + } + } catch (\Throwable $e) { + throw new AdminException(400612, ['msg' => $e->getMessage()]); + } + }); + } + + /** + * 导入数据 + * @param string $filePath + * @return mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/26 + */ + protected function import(string $filePath) + { + $preg = '/\{+[a-zA-Z0-9]+\}/'; + + $res = file_get_contents(app()->getRootPath() . $filePath); + + $data = json_decode($res, true)['apiCollection'][0]['items']; + + $route = []; + foreach ($data as $item) { + foreach ($item['items'] as $value) { + if (isset($value['api'])) { + $path = str_replace('//', '/', str_replace('{}', '', $value['api']['path'])); + $paramePath = $this->getPathValue($value['api']['parameters']['path'] ?? []); + if (strstr($path, ':') !== false) { + $path = str_replace(':', '', $path); + } + if (preg_match_all($preg, $path, $matches)) { + $paramePathMatche = []; + if (isset($matches[0]) && $matches[0]) { + foreach ($matches[0] as $v) { + $paramePathMatche[] = str_replace(['{', '}'], ['<', '>'], $v); + } + } + if ($paramePathMatche) { + $paramePath = implode('/', $paramePathMatche); + } + } + if ($path[0] === '/') { + $path = substr($path, 1); + } + $route[] = [ + 'method' => strtoupper($value['api']['method']), + 'path' => $path . $paramePath, + 'request_type' => $value['api']['requestBody']['type'], + 'request' => $this->getRequest($value['api']['requestBody']['parameters'] ?? []), + 'response' => $this->getResponse($value['api']['responses'][0]['jsonSchema']['properties'] ?? []), + ]; + } + } + } + + return app()->make(SystemRouteServices::class)->importData($route); + } + + /** + * 获取请求返回数据 + * @param array $options + * @param string $parentId + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/26 + */ + protected function getResponse(array $options, $parentId = '') + { + $response = []; + foreach ($options as $key => $option) { + $id = uniqid(); + $response[] = [ + 'attribute' => $key, + 'type' => $option['type'], + 'trip' => '', + 'id' => $id, + 'parentId' => $parentId, + ]; + if (isset($option['properties'])) { + $response = array_merge($response, $this->getResponse($option['properties'], $id)); + } + } + + return $response; + } + + /** + * 获取请求数据 + * @param array $options + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/26 + */ + protected function getRequest(array $options) + { + $request = []; + foreach ($options as $option) { + $request[] = [ + 'attribute' => $option['name'], + 'type' => $option['type'] === 'text' ? 'string' : $option['type'], + 'must' => 0, + 'trip' => $option['description'], + 'id' => $option['id'], + ]; + } + return $request; + } + + /** + * 处理path路径 + * @param array $options + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/26 + */ + protected function getPathValue(array $options) + { + $path = []; + foreach ($options as $option) { + if (strstr($option['name'], '?') !== false) { + $option['name'] = str_replace('?', '', $option['name']) . '?'; + } + $path[] = '<' . $option['name'] . '>'; + } + + return implode('/', $path); + } +} diff --git a/demo/thinkphp/backend/phoenix/command/Workerman.php b/demo/thinkphp/backend/phoenix/command/Workerman.php new file mode 100644 index 0000000000000000000000000000000000000000..35d96c29a4b1c05c61ca3cded66a8eafb893b78e --- /dev/null +++ b/demo/thinkphp/backend/phoenix/command/Workerman.php @@ -0,0 +1,166 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\command; + +use app\services\system\config\SystemConfigServices; +use Channel\Server; +use phoenix\services\workerman\chat\ChatService; +use phoenix\services\workerman\kefu\KefuService; +use phoenix\services\workerman\WorkermanService; +use think\console\Command; +use think\console\Input; +use think\console\input\Argument; +use think\console\input\Option; +use think\console\Output; +use Workerman\Worker; + +class Workerman extends Command +{ + /** + * @var array + */ + protected array $config = []; + + /** + * @var Worker + */ + protected $workerServer; + + /** + * @var Worker + */ + protected $chatWorkerServer; + + /** + * @var Server + */ + protected $channelServer; + + /** + * @var Input + */ + public $input; + + /** + * @var Output + */ + public $output; + /** + * @var \Workerman\Worker + */ + protected $kefuWorkerServer; + + protected function configure() + { + // 指令配置 + $this->setName('workerman') + ->addArgument('status', Argument::REQUIRED, 'start/stop/reload/status/connections') + ->addArgument('server', Argument::OPTIONAL, 'admin/chat/channel') + ->addOption('d', null, Option::VALUE_NONE, 'daemon(守护进程)方式启动') + ->setDescription('start/stop/restart workerman'); + } + + protected function init(Input $input, Output $output) + { + global $argv; + $argv[1] = $input->getArgument('status') ?: 'start'; + $server = $input->getArgument('server'); + if ($input->hasOption('d')) { + $argv[2] = '-d'; + } else { + unset($argv[2]); + } + + $this->config = config('workerman'); + + return $server; + } + + protected function execute(Input $input, Output $output) + { + $server = $this->init($input, $output); + /** @var SystemConfigServices $services */ + $services = app()->make(SystemConfigServices::class); + $sslConfig = $services->getSslFilePath(); +// $confing['wss_open'] = $sslConfig['wssOpen'] ?? 0; + $confing['wss_open'] = 0; + $confing['wss_local_cert'] = $sslConfig['wssLocalCert'] ?? ''; + $confing['wss_local_pk'] = $sslConfig['wssLocalpk'] ?? ''; + // 证书最好是申请的证书 + if ($confing['wss_open']) { + $context = [ + 'ssl' => [ + // 请使用绝对路径 + 'local_cert' => realpath('public' . $confing['wss_local_cert']), // 也可以是crt文件 + 'local_pk' => realpath('public' . $confing['wss_local_pk']), + 'verify_peer' => false, + ], + ]; + } else { + $context = []; + } + Worker::$pidFile = app()->getRootPath() . 'runtime/workerman.pid'; + + if (!$server || $server == 'admin') { + var_dump('admin'); + //创建 admin 长连接服务 + $this->workerServer = new Worker($this->config['admin']['protocol'] . '://' . $this->config['admin']['ip'] . ':' . $this->config['admin']['port'], $context); + $this->workerServer->count = $this->config['admin']['serverCount']; + if ($confing['wss_open']) { + $this->workerServer->transport = 'ssl'; + } + } + +// if (!$server || $server == 'chat') { +// var_dump('chat'); +// //创建 h5 chat 长连接服务 +// $this->chatWorkerServer = new Worker($this->config['chat']['protocol'] . '://' . $this->config['chat']['ip'] . ':' . $this->config['chat']['port'], $context); +// $this->chatWorkerServer->count = $this->config['chat']['serverCount']; +// if ($confing['wss_open']) { +// $this->chatWorkerServer->transport = 'ssl'; +// } +// } + + if (!$server || $server == 'channel') { + var_dump('channel'); + //创建内部通讯服务 + $this->channelServer = new Server($this->config['channel']['ip'], $this->config['channel']['port']); + } + $this->bindHandle(); + try { + Worker::runAll(); + } catch (\Exception $e) { + $output->warning($e->getMessage()); + } + } + + protected function bindHandle() + { + if (!is_null($this->workerServer)) { + $server = new WorkermanService($this->workerServer, $this->channelServer); + // 连接时回调 + $this->workerServer->onConnect = [$server, 'onConnect']; + // 收到客户端信息时回调 + $this->workerServer->onMessage = [$server, 'onMessage']; + // 进程启动后的回调 + $this->workerServer->onWorkerStart = [$server, 'onWorkerStart']; + // 断开时触发的回调 + $this->workerServer->onClose = [$server, 'onClose']; + } +// if (!is_null($this->chatWorkerServer)) { +// $chatServer = new ChatService($this->chatWorkerServer, $this->channelServer); +// $this->chatWorkerServer->onConnect = [$chatServer, 'onConnect']; +// $this->chatWorkerServer->onMessage = [$chatServer, 'onMessage']; +// $this->chatWorkerServer->onWorkerStart = [$chatServer, 'onWorkerStart']; +// $this->chatWorkerServer->onClose = [$chatServer, 'onClose']; +// } + } +} diff --git a/demo/thinkphp/backend/phoenix/exceptions/AdminException.php b/demo/thinkphp/backend/phoenix/exceptions/AdminException.php new file mode 100644 index 0000000000000000000000000000000000000000..9be4a6e4a9947dded8ac9f8a634a6ecc4835624b --- /dev/null +++ b/demo/thinkphp/backend/phoenix/exceptions/AdminException.php @@ -0,0 +1,37 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\exceptions; + +/** + * Class AuthException + * @package crmeb\exceptions + */ +class AdminException extends \RuntimeException +{ + public function __construct($message, $replace = [], $code = 0, \Throwable $previous = null) + { + if (is_array($message)) { + $errInfo = $message; + $message = $errInfo[1] ?? '未知错误'; + if ($code === 0) { + $code = $errInfo[0] ?? 400; + } + } + + if (is_numeric($message)) { + $code = $message; + $message = getLang($message, $replace); + } + + parent::__construct($message, $code, $previous); + } +} diff --git a/demo/thinkphp/backend/phoenix/exceptions/ApiException.php b/demo/thinkphp/backend/phoenix/exceptions/ApiException.php new file mode 100644 index 0000000000000000000000000000000000000000..c3aca76c56d0a352ca64aa014a32f90170cc6f47 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/exceptions/ApiException.php @@ -0,0 +1,38 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\exceptions; + +/** + * API应用错误信息 + * Class ApiException + * @package crmeb\exceptions + */ +class ApiException extends \RuntimeException +{ + public function __construct($message, $replace = [], $code = 0, \Throwable $previous = null) + { + if (is_array($message)) { + $errInfo = $message; + $message = $errInfo[1] ?? '未知错误'; + if ($code === 0) { + $code = $errInfo[0] ?? 400; + } + } + + if (is_numeric($message)) { + $code = $message; + $message = getLang($message, $replace); + } + + parent::__construct($message, $code, $previous); + } +} diff --git a/demo/thinkphp/backend/phoenix/exceptions/ApiStatusException.php b/demo/thinkphp/backend/phoenix/exceptions/ApiStatusException.php new file mode 100644 index 0000000000000000000000000000000000000000..6ad8cbc734a34bfea21bd6041edaa038768e2c56 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/exceptions/ApiStatusException.php @@ -0,0 +1,60 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\exceptions; + +/** + * API应用错误信息 + * Class ApiException + * @package crmeb\exceptions + */ +class ApiStatusException extends \RuntimeException +{ + protected $apiStatus; + protected $apiData; + + public function __construct($status, $message, $data = [], $replace = [], $code = 0, \Throwable $previous = null) + { + if (is_array($message)) { + $errInfo = $message; + $message = $errInfo[1] ?? '未知错误'; + if ($code === 0) { + $code = $errInfo[0] ?? 400; + } + } + + if (is_numeric($message)) { + $code = $message; + $message = getLang($message, $replace); + } + + $this->apiData = $data; + $this->apiStatus = $status; + + parent::__construct($message, $code, $previous); + } + + /** + * @return mixed + */ + public function getApiStatus() + { + return $this->apiStatus; + } + + /** + * @return array|mixed + */ + public function getApiData() + { + return $this->apiData; + } +} diff --git a/demo/thinkphp/backend/phoenix/exceptions/AuthException.php b/demo/thinkphp/backend/phoenix/exceptions/AuthException.php new file mode 100644 index 0000000000000000000000000000000000000000..1dd48b2b0a7d13b0a8d90f5dfd810ab06d307351 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/exceptions/AuthException.php @@ -0,0 +1,37 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\exceptions; + +/** + * Class AuthException + * @package crmeb\exceptions + */ +class AuthException extends \RuntimeException +{ + public function __construct($message = "", $replace = [], $code = 0, \Throwable $previous = null) + { + if (is_array($message)) { + $errInfo = $message; + $message = $errInfo[1] ?? '未知错误'; + if ($code === 0) { + $code = $errInfo[0] ?? 400; + } + } + + if (is_numeric($message)) { + $code = $message; + $message = getLang($message, $replace); + } + + parent::__construct($message, $code, $previous); + } +} diff --git a/demo/thinkphp/backend/phoenix/exceptions/CrudException.php b/demo/thinkphp/backend/phoenix/exceptions/CrudException.php new file mode 100644 index 0000000000000000000000000000000000000000..26f161f4e5e6ff29c7be15136fe2c32fda059c53 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/exceptions/CrudException.php @@ -0,0 +1,36 @@ + + * +---------------------------------------------------------------------- + */ + +namespace phoenix\exceptions; + + +class CrudException extends \RuntimeException +{ + public function __construct($message = "", $replace = [], $code = 0, \Throwable $previous = null) + { + if (is_array($message)) { + $errInfo = $message; + $message = $errInfo[1] ?? '未知错误'; + if ($code === 0) { + $code = $errInfo[0] ?? 400; + } + } + + if (is_numeric($message)) { + $code = $message; + $message = getLang($message, $replace); + } + + parent::__construct($message, $code, $previous); + } +} diff --git a/demo/thinkphp/backend/phoenix/exceptions/PayException.php b/demo/thinkphp/backend/phoenix/exceptions/PayException.php new file mode 100644 index 0000000000000000000000000000000000000000..7afb8d1e284c3b0e5e78e0742650371451dcb03b --- /dev/null +++ b/demo/thinkphp/backend/phoenix/exceptions/PayException.php @@ -0,0 +1,37 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\exceptions; + +/** + * Class PayException + * @package crmeb\exceptions + */ +class PayException extends \RuntimeException +{ + public function __construct($message, $replace = [], $code = 0, \Throwable $previous = null) + { + if (is_array($message)) { + $errInfo = $message; + $message = $errInfo[1] ?? '未知错误'; + if ($code === 0) { + $code = $errInfo[0] ?? 400; + } + } + + if (is_numeric($message)) { + $code = $message; + $message = getLang($message, $replace); + } + + parent::__construct($message, $code, $previous); + } +} diff --git a/demo/thinkphp/backend/phoenix/exceptions/UploadException.php b/demo/thinkphp/backend/phoenix/exceptions/UploadException.php new file mode 100644 index 0000000000000000000000000000000000000000..e8e2c7ea0637df88c2d89c00d5ed833a6157564a --- /dev/null +++ b/demo/thinkphp/backend/phoenix/exceptions/UploadException.php @@ -0,0 +1,37 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\exceptions; + +/** + * Class AuthException + * @package crmeb\exceptions + */ +class UploadException extends \RuntimeException +{ + public function __construct($message, $replace = [], $code = 0, \Throwable $previous = null) + { + if (is_array($message)) { + $errInfo = $message; + $message = $errInfo[1] ?? '未知错误'; + if ($code === 0) { + $code = $errInfo[0] ?? 400; + } + } + + if (is_numeric($message)) { + $code = $message; + $message = getLang($message, $replace); + } + + parent::__construct($message, $code, $previous); + } +} diff --git a/demo/thinkphp/backend/phoenix/filetree.txt b/demo/thinkphp/backend/phoenix/filetree.txt new file mode 100644 index 0000000000000000000000000000000000000000..9f946cadfed3ba3f61a9affcb8a868d840649df1 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/filetree.txt @@ -0,0 +1,73 @@ +. +├── basic +│   ├── BaseController.php //控制器基类 +│   ├── BaseJobs.php //队列基类 +│   ├── BaseManager.php //驱动管理基类 +│   ├── BaseModel.php //model基类 +│   └── BaseStorage.php //驱动基类 +├── command +│   ├── stubs //命令模版 +│   ├── Dao.php //创建Dao类命令 +│   ├── Service.php //创建Service类命令 +│   ├── Timer.php //定时任务命令类 +│   └── Workerman.php //workman命令类 +├── exceptions +│   ├── AdminException.php //后台管理端异常处理 +│   ├── ApiException.php //移动端接口异常处理 +│   ├── AuthException.php //用户授权异常处理 +│   ├── PayException.php //支付异常处理 +│   ├── SmsException.php //短信异常处理 +│   ├── TemplateException.php //微信模版消息异常处理 +│   ├── UploadException.php //上传异常处理 +│   └── WechatReplyException.php //微信自动回复异常处理 +├── interfaces +│   ├── JobInterface.php //队列任务 +│   ├── ListenerInterface.php //事件 +│   ├── MiddlewareInterface.php //中间件 +│   └── ProviderInterface.php //容器 +├── services +│   ├── app //应用端 +│   ├── easywechat //easywechat +│   ├── express //物流查询 +│   ├── pay //支付 +│   ├── printer //打印机 +│   ├── copyproduct //采集商品 +│   ├── serve //服务平台 +│   ├── sms //短信 +│   ├── template //模版消息 +│   ├── upload //上传 +│   ├── workerman //workerman +│   ├── AccessTokenServeService.php //获取token +│   ├── AliPayService.php +│   ├── CacheService.php //缓存类 +│   ├── FileService.php //文件处理类 +│   ├── FormBuilder.php //自动生成表单类 +│   ├── GroupDataService.php //组合数据类 +│   ├── HttpService.php //curl 请求处理类 +│   ├── MysqlBackupService.php //数据库备份管理类 +│   ├── SpreadsheetExcelService.php //excel处理类 +│   ├── SystemConfigService.php //系统配置获取类 +│   ├── UpgradeService.php //系统更新类 +│   └── UploadService.php //文件上传类 +├── traits +│   ├── ErrorTrait.php //错误处理扩展类 +│   ├── JwtAuthModelTrait.php //Jwt鉴权扩展类 +│   ├── ModelTrait.php //model扩展类 +│   ├── QueueTrait.php //队列扩展累 +│   ├── SearchDaoTrait.php //dao扩展类 +│   └── ServicesTrait.php //Services扩展类 +├── utils +│   ├── Arr.php //操作数组帮助类 +│   ├── Canvas.php //图片处理类 +│   ├── Captcha.php //验证码类 +│   ├── DownloadImage.php //远程图片下载类 +│   ├── ErrorCode.php //错误码处理类 +│   ├── Hook.php //钩子类 +│   ├── Json.php //Json处理类 +│   ├── JwtAuth.php //Jwt鉴权类 +│   ├── QRcode.php //二维码获取类 TODO +│   ├── Queue.php //队列类 +│   └── Str.php //字符处理类 +└── filetree.txt + +17 directories, 70 files diff --git a/demo/thinkphp/backend/phoenix/interfaces/JobInterface.php b/demo/thinkphp/backend/phoenix/interfaces/JobInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..193e7279a3624ca015381a99bc5d734638d4e2ed --- /dev/null +++ b/demo/thinkphp/backend/phoenix/interfaces/JobInterface.php @@ -0,0 +1,20 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\interfaces; + +use think\queue\Job; + +interface JobInterface +{ + + public function fire(Job $job, $data): void; +} diff --git a/demo/thinkphp/backend/phoenix/interfaces/ListenerInterface.php b/demo/thinkphp/backend/phoenix/interfaces/ListenerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..ef4635a4a74d971ae2fc25c8a36181a954c7777d --- /dev/null +++ b/demo/thinkphp/backend/phoenix/interfaces/ListenerInterface.php @@ -0,0 +1,18 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\interfaces; + + +interface ListenerInterface +{ + public function handle($event): void; +} diff --git a/demo/thinkphp/backend/phoenix/interfaces/MiddlewareInterface.php b/demo/thinkphp/backend/phoenix/interfaces/MiddlewareInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..fe7be83b254917cbb830ac8f427d99c479cf198d --- /dev/null +++ b/demo/thinkphp/backend/phoenix/interfaces/MiddlewareInterface.php @@ -0,0 +1,20 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\interfaces; + + +use app\Request; + +interface MiddlewareInterface +{ + public function handle(Request $request, \Closure $next); +} diff --git a/demo/thinkphp/backend/phoenix/interfaces/ProviderInterface.php b/demo/thinkphp/backend/phoenix/interfaces/ProviderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..bf6a6b1b523785f181c49190a40a43913605619e --- /dev/null +++ b/demo/thinkphp/backend/phoenix/interfaces/ProviderInterface.php @@ -0,0 +1,19 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\interfaces; + + +interface ProviderInterface +{ + public function register($config); +} + diff --git a/demo/thinkphp/backend/phoenix/middleware/AllowCrossOriginMiddleware.php b/demo/thinkphp/backend/phoenix/middleware/AllowCrossOriginMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..68641078055b08e7760eb81bb53f20da39fe03b3 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/middleware/AllowCrossOriginMiddleware.php @@ -0,0 +1,45 @@ +cookieDomain = Config::get('cookie.domain', ''); + $header = Config::get('cookie.header'); + $origin = $request->header('origin'); + if ($origin && ('' == $this->cookieDomain || strpos($origin, $this->cookieDomain))) + $header['Access-Control-Allow-Origin'] = $origin; + if ($request->method(true) == 'OPTIONS') { + $response = Response::create('ok')->code(200)->header($header); + exit; + } else { + $response = $next($request)->header($header); + } + return $response; + + } +} diff --git a/demo/thinkphp/backend/phoenix/middleware/BaseMiddleware.php b/demo/thinkphp/backend/phoenix/middleware/BaseMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..361a55a80b2c69fa0de6b48946693e5fd3991bac --- /dev/null +++ b/demo/thinkphp/backend/phoenix/middleware/BaseMiddleware.php @@ -0,0 +1,53 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\middleware; + +use app\Request; +use phoenix\interfaces\MiddlewareInterface; + +/** + * Class BaseMiddleware + * + * @package app\api\middleware + */ +class BaseMiddleware implements MiddlewareInterface +{ + /** + * @param Request $request + * @param \Closure $next + * @param bool $force + * + * @return mixed + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/04/07 + */ + public function handle(Request $request, \Closure $next, bool $force = true): mixed + { + if (!$request->hasMacro('uid')) { + $request->macro('uid', function () { + return 0; + }); + } + if (!$request->hasMacro('adminId')) { + $request->macro('adminId', function () { + return 0; + }); + } + if (!$request->hasMacro('adminInfo')) { + $request->macro('adminInfo', function () { + return []; + }); + } + return $next($request); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/AccessTokenServeService.php b/demo/thinkphp/backend/phoenix/services/AccessTokenServeService.php new file mode 100644 index 0000000000000000000000000000000000000000..7eb874a41edb7888d4c259c541daae66d629ba04 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/AccessTokenServeService.php @@ -0,0 +1,185 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services; + + +use crmeb\exceptions\ApiException; + +/** + * Class AccessTokenServeService + * @package crmeb\services + */ +class AccessTokenServeService extends HttpService +{ + /** + * 配置 + * @var string + */ + protected $account; + + /** + * @var string + */ + protected $secret; + + /** + * @var Cache|null + */ + protected $cache; + + /** + * @var string + */ + protected $accessToken; + + /** + * @var string + */ + protected $cacheTokenPrefix = "_crmeb_plat"; + + /** + * @var string + */ + protected $apiHost = 'http://sms.crmeb.net/api/'; + + /** + * 沙盒地址 + * @var string + */ + protected $sandBoxApi = 'https://api_v2.crmeb.net/api/'; + + /** + * 沙盒模式 + * @var bool + */ + protected $sandBox = false; + + /** + * 登录接口 + */ + const USER_LOGIN = "user/login"; + + + /** + * AccessTokenServeService constructor. + * @param string $account + * @param string $secret + * @param Cache|null $cache + */ + public function __construct(string $account, string $secret, $cache = null) + { + if (!$cache) { + /** @var CacheService $cache */ + $cache = app()->make(CacheService::class); + } + $this->account = $account; + $this->secret = $secret; + $this->cache = $cache; + } + + /** + * 获取配置 + * @return array + */ + public function getConfig() + { + return [ + 'account' => $this->account, + 'secret' => $this->secret + ]; + } + + /** + * 获取缓存token + * @return mixed + * @throws \Psr\SimpleCache\InvalidArgumentException + */ + public function getToken() + { + $accessTokenKey = md5($this->account . '_' . $this->secret . $this->cacheTokenPrefix); + $cacheToken = $this->cache->get($accessTokenKey); + if (!$cacheToken) { + $getToken = $this->getTokenFromServer(); + $this->cache->set($accessTokenKey, $getToken['access_token'], 300); + $cacheToken = $getToken['access_token']; + } + $this->accessToken = $cacheToken; + + return $cacheToken; + + } + + /** + * 从服务器获取token + * @return mixed + */ + public function getTokenFromServer() + { + $params = [ + 'account' => $this->account, + 'secret' => $this->secret, + ]; + $response = $this->postRequest($this->get(self::USER_LOGIN), $params); + $response = json_decode($response, true); + if (!$response) { + throw new ApiException(410085, ['msg' => '']); + } + if ($response['status'] === 200) { + return $response['data']; + } else { + throw new ApiException(410085, ['msg' => ':' . $response['msg']]); + } + } + + /** + * 请求 + * @param string $url + * @param array $data + * @param string $method + * @param bool $isHeader + * @return array|mixed + */ + public function httpRequest(string $url, array $data = [], string $method = 'POST', bool $isHeader = true, array $header = []) + { + if ($isHeader) { + $this->getToken(); + if (!$this->accessToken) { + throw new ApiException(410086); + } + $header = array_merge($header, ['Authorization:Bearer-' . $this->accessToken]); + } + + $res = $this->request($this->get($url), $method, $data, $header); + if (!$res) { + throw new ApiException(410087); + + } + $result = json_decode($res, true) ?: false; + if (!isset($result['status']) || $result['status'] != 200) { + throw new ApiException($result['msg']); + } + return $result['data'] ?? []; + + } + + /** + * @param string $apiUrl + * @return string + */ + public function get(string $apiUrl = '') + { + if ($this->sandBox) { + return $this->sandBoxApi . $apiUrl; + } + return $this->apiHost . $apiUrl; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/AliPayService.php b/demo/thinkphp/backend/phoenix/services/AliPayService.php new file mode 100644 index 0000000000000000000000000000000000000000..f3531118101115f0f3f7a786db174dd53b1e4343 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/AliPayService.php @@ -0,0 +1,288 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services; + +use Alipay\EasySDK\Payment\Wap\Models\AlipayTradeWapPayResponse; +use app\services\pay\PayServices; +use think\facade\Event; +use think\facade\Log; +use think\facade\Route as Url; +use Alipay\EasySDK\Kernel\Config; +use Alipay\EasySDK\Kernel\Factory; +use crmeb\exceptions\PayException; +use Alipay\EasySDK\Kernel\Util\ResponseChecker; + +/** + * Class AliPayService + * @package crmeb\services + */ +class AliPayService +{ + + /** + * 配置 + * @var array + */ + protected $config = [ + 'appId' => '', + 'merchantPrivateKey' => '',//应用私钥 + 'alipayPublicKey' => '',//支付宝公钥 + 'notifyUrl' => '',//可设置异步通知接收服务地址 + 'encryptKey' => '',//可设置AES密钥,调用AES加解密相关接口时需要(可选) + ]; + + /** + * @var ResponseChecker + */ + protected $response; + + /** + * @var static + */ + protected static $instance; + + /** + * AliPayService constructor. + * @param array $config + */ + protected function __construct(array $config = []) + { + if (!$config) { + $config = [ + 'appId' => sys_config('ali_pay_appid'), + 'merchantPrivateKey' => sys_config('alipay_merchant_private_key'), + 'alipayPublicKey' => sys_config('alipay_public_key'), + 'notifyUrl' => sys_config('site_url') . Url::buildUrl('/api/pay/notify/alipay'), + ]; + } + $this->config = array_merge($this->config, $config); + $this->initialize(); + $this->response = new ResponseChecker(); + } + + /** + * 实例化 + * @param array $config + * @return static + */ + public static function instance(array $config = []) + { + if (is_null(self::$instance)) { + self::$instance = new static($config); + } + return self::$instance; + } + + /** + * 初始化 + */ + protected function initialize() + { + Factory::setOptions($this->getOptions()); + } + + /** + * 设置配置 + * @return Config + */ + protected function getOptions() + { + $options = new Config(); + $options->protocol = 'https'; + $options->gatewayHost = 'openapi.alipay.com'; + $options->signType = 'RSA2'; + + $options->appId = $this->config['appId']; + // 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中 + $options->merchantPrivateKey = $this->config['merchantPrivateKey']; + //注:如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可 + $options->alipayPublicKey = $this->config['alipayPublicKey']; + //可设置异步通知接收服务地址(可选) + $options->notifyUrl = $this->config['notifyUrl']; + //可设置AES密钥,调用AES加解密相关接口时需要(可选) + if ($this->config['encryptKey']) { + $options->encryptKey = $this->config['encryptKey']; + } + + return $options; + } + + /** + * 创建订单 + * @param string $title 商品名称 + * @param string $orderId 订单号 + * @param string $totalAmount 支付金额 + * @param string $passbackParams 备注 + * @param string $quitUrl 同步跳转地址 + * @param string $siteUrl + * @param bool $isCode + * @return AlipayTradeWapPayResponse + */ + public function create(string $title, string $orderId, string $totalAmount, string $passbackParams, string $quitUrl = '', string $siteUrl = '', bool $isCode = false) + { + $title = trim($title); + try { + if ($isCode) { + //二维码支付 + $result = Factory::payment()->faceToFace()->optional('passback_params', $passbackParams)->precreate($title, $orderId, $totalAmount); + } else if (request()->isApp()) { + //app支付 + $result = Factory::payment()->app()->optional('passback_params', $passbackParams)->pay($title, $orderId, $totalAmount); + } else { + //h5支付 + $result = Factory::payment()->wap()->optional('passback_params', $passbackParams)->pay($title, $orderId, $totalAmount, $quitUrl, $siteUrl); + } + if ($this->response->success($result)) { + return $result->body ?? $result; + } else { + throw new PayException('失败原因:' . $result->msg . ',' . $result->subMsg); + } + } catch (\Exception $e) { + throw new PayException($e->getMessage()); + } + } + + /** + * 订单退款 + * @param string $outTradeNo 订单号 + * @param string $totalAmount 退款金额 + * @param string $refund_id 退款单号 + * @return \Alipay\EasySDK\Payment\Common\Models\AlipayTradeRefundResponse + */ + public function refund(string $outTradeNo, string $totalAmount, string $refund_id) + { + try { + $result = Factory::payment()->common()->refund($outTradeNo, $totalAmount, $refund_id); + if ($this->response->success($result)) { + return $result; + } else { + throw new PayException('失败原因:' . $result->msg . ',' . $result->subMsg); + } + } catch (\Exception $e) { + throw new PayException($e->getMessage()); + } + } + + /** + * 查询交易退款单号信息 + * @param string $outTradeNo + * @param string $outRequestNo + * @return \Alipay\EasySDK\Payment\Common\Models\AlipayTradeFastpayRefundQueryResponse + */ + public function queryRefund(string $outTradeNo, string $outRequestNo) + { + try { + $result = Factory::payment()->common()->queryRefund($outTradeNo, $outRequestNo); + if ($this->response->success($result)) { + return $result; + } else { + throw new PayException('失败原因:' . $result->msg . ',' . $result->subMsg); + } + } catch (\Exception $e) { + throw new PayException($e->getMessage()); + } + } + + /** + * 支付异步回调 + * @return string + */ + public static function handleNotify() + { + return self::instance()->notify(function ($notify) { + if (isset($notify->out_trade_no)) { + + $data = [ + 'attach' => $notify->attach, + 'out_trade_no' => $notify->out_trade_no, + 'transaction_id' => $notify->trade_no + ]; + + return Event::until('NotifyListener', [$data, PayServices::ALIAPY_PAY]); + } + return false; + }); + } + + /** + * 异步回调 + * @param callable $notifyFn + * @return string + */ + public function notify(callable $notifyFn) + { + app()->request->filter(['trim']); + $paramInfo = app()->request->postMore([ + ['gmt_create', ''], + ['charset', ''], + ['seller_email', ''], + ['subject', ''], + ['sign', ''], + ['buyer_id', ''], + ['invoice_amount', ''], + ['notify_id', ''], + ['fund_bill_list', ''], + ['notify_type', ''], + ['trade_status', ''], + ['receipt_amount', ''], + ['buyer_pay_amount', ''], + ['app_id', ''], + ['seller_id', ''], + ['sign_type', ''], + ['gmt_payment', ''], + ['notify_time', ''], + ['passback_params', ''], + ['version', ''], + ['out_trade_no', ''], + ['total_amount', ''], + ['trade_no', ''], + ['auth_app_id', ''], + ['buyer_logon_id', ''], + ['point_amount', ''], + ], false, false); + + //商户订单号 + $postOrder['out_trade_no'] = $paramInfo['out_trade_no'] ?? ''; + //支付宝交易号 + $postOrder['trade_no'] = $paramInfo['trade_no'] ?? ''; + //交易状态 + $postOrder['trade_status'] = $paramInfo['trade_status'] ?? ''; + //备注 + $postOrder['attach'] = isset($paramInfo['passback_params']) ? urldecode($paramInfo['passback_params']) : ''; + if (in_array($paramInfo['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED']) && $this->verifyNotify($paramInfo)) { + try { + if ($notifyFn((object)$postOrder)) { + return 'success'; + } + } catch (\Exception $e) { + Log::error($e->getMessage()); + Log::error('支付宝异步会回调成功,执行函数错误。错误单号:' . $postOrder['out_trade_no']); + } + } + return 'fail'; + + } + + /** + * 验签 + * @return bool + */ + protected function verifyNotify(array $param) + { + try { + return Factory::payment()->common()->verifyNotify($param); + } catch (\Exception $e) { + Log::error('支付宝回调成功,验签发生错误,错误原因:' . $e->getMessage()); + } + return false; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/CacheService.php b/demo/thinkphp/backend/phoenix/services/CacheService.php new file mode 100644 index 0000000000000000000000000000000000000000..3063a2ea3a6dac0435446d2c86f60f0c174895e2 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/CacheService.php @@ -0,0 +1,228 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\services; + +use think\cache\Driver; +use think\cache\TagSet; +use think\facade\Cache; +use think\facade\Config; + +/** + * phoenix 缓存类 + * Class CacheService + * @package crmeb\services + */ +class CacheService +{ + /** + * 缓存队列key + * @var string[] + */ + protected static array $redisQueueKey = [ + 0 => 'product', + 1 => 'seckill', + 2 => 'bargain', + 3 => 'combination', + 6 => 'advance' + ]; + + /** + * 过期时间 + * @var int + */ + protected static int $expire; + + /** + * 获取缓存过期时间 + * @param int|null $expire + * @return int + */ + protected static function getExpire(int $expire = null): int + { + if ($expire == null) { + if (self::$expire) { + return (int)self::$expire; + } + $default = Config::get('cache.default'); + $expire = Config::get('cache.stores.' . $default . '.expire'); + if (!is_int($expire)) { + $expire = (int)$expire; + } + } + return self::$expire = $expire; + } + + /** + * 写入缓存 + * @param string $name 缓存名称 + * @param mixed $value 缓存值 + * @param int|null $expire 缓存时间,为0读取系统缓存时间 + */ + public static function set(string $name, $value, int $expire = null, string $tag = 'phoenix') + { + try { + return Cache::tag($tag)->set($name, $value, $expire ?? self::getExpire($expire)); + } catch (\Throwable $e) { + return false; + } + } + + /** + * 如果不存在则写入缓存 + * @param string $name + * @param mixed $default + * @param int|null $expire + * @param string $tag + * @return mixed|string|null + */ + public static function remember(string $name, $default = '', int $expire = null, string $tag = 'phoenix') + { + try { + return Cache::tag($tag)->remember($name, $default, $expire ?? self::getExpire($expire)); + } catch (\Throwable $e) { + try { + if (is_callable($default)) { + return $default(); + } else { + return $default; + } + } catch (\Throwable $e) { + return null; + } + } + } + + /** + * 读取缓存 + * + * @param string $name + * @param mixed|string $default + * + * @return mixed|string + */ + public static function get(string $name, mixed $default = ''): mixed + { + return Cache::get($name) ?? $default; + } + + /** + * 删除缓存 + * @param string $name + * @return bool + */ + public static function delete(string $name): bool + { + return Cache::delete($name); + } + + /** + * 清空缓存池 + * + * @param string $tag + * + * @return bool + */ + public static function clear(string $tag = 'phoenix'): bool + { + return Cache::tag($tag)->clear(); + } + + /** + * 检查缓存是否存在 + * @param string $key + * @return bool + */ + public static function has(string $key): bool + { + try { + return Cache::has($key); + } catch (\Throwable $e) { + return false; + } + } + + /** + * 检查锁 + * @param string $key + * @param int $timeout + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/11/22 + */ + public static function setMutex(string $key, int $timeout = 10): bool + { + $curTime = time(); + $readMutexKey = "redis:mutex:{$key}"; + $mutexRes = Cache::store('redis')->handler()->setnx($readMutexKey, $curTime + $timeout); + if ($mutexRes) { + return true; + } + //就算意外退出,下次进来也会检查key,防止死锁 + $time = Cache::store('redis')->handler()->get($readMutexKey); + if ($curTime > $time) { + Cache::store('redis')->handler()->del($readMutexKey); + return Cache::store('redis')->handler()->setnx($readMutexKey, $curTime + $timeout); + } + return false; + } + + /** + * 删除锁 + * @param string $key + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/11/22 + */ + public static function delMutex(string $key): void + { + $readMutexKey = "redis:mutex:{$key}"; + Cache::store('redis')->handler()->del($readMutexKey); + } + + /** + * Redis缓存句柄 + * + * @param null $type + * + * @return \TagSet|\Driver + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/02/10 + */ + public static function redisHandler($type = null): \TagSet|\Driver + { + if ($type) { + return Cache::store('redis')->tag($type); + } else { + return Cache::store('redis'); + } + } + + /** + * 数据库锁 + * @param $key + * @param $fn + * @param int $ex + * @return mixed + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public static function lock($key, $fn, int $ex = 6): mixed + { + if (Config::get('cache.default') == 'file') { + return $fn(); + } + return app()->make(LockService::class)->exec($key, $fn, $ex); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/FileService.php b/demo/thinkphp/backend/phoenix/services/FileService.php new file mode 100644 index 0000000000000000000000000000000000000000..c2aa6052978b1fbcc73300272a3efbc71c4ba0e6 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/FileService.php @@ -0,0 +1,1094 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\services; + +use phoenix\exceptions\AdminException; +use phoenix\exceptions\CrudException; +use phoenix\services\crud\Make; + +/** + * 文件操作类 + * Class FileService + * @package crmeb\services + */ +class FileService +{ + + /** + * 创建目录 + * @param string $dir + * @return bool + */ + public static function mkDir(string $dir) + { + $dir = rtrim($dir, '/') . '/'; + if (!is_dir($dir)) { + if (mkdir($dir, 0700) == false) { + return false; + } + return true; + } + return true; + } + + /** + * @param $filename 写入文件名 + * @param $writetext 保存内容 + * @param string $openmod 打开方式 + * @return bool + */ + public static function writeFile(string $filename, string $writetext, string $openmod = 'w') + { + if (@$fp = fopen($filename, $openmod)) { + flock($fp, 2); + fwrite($fp, $writetext); + fclose($fp); + return true; + } else { + return false; + } + } + + /** + * 删除目录下所有满足条件文件 + * @param $path 文件目录 + * @param $start 开始时间 + * @param $end 结束时间 + * return bool + */ + public static function del_where_dir($path, $start = '', $end = '') + { + if (!file_exists($path)) { + return false; + } + $dh = @opendir($path); + if ($dh) { + while (($d = readdir($dh)) !== false) { + if ($d == '.' || $d == '..') {//如果为.或.. + continue; + } + $tmp = $path . '/' . $d; + if (!is_dir($tmp)) {//如果为文件 + $file_time = filemtime($tmp); + if ($file_time) { + if ($start != '' && $end != '') { + if ($file_time >= $start && $file_time <= $end) { + @unlink($tmp); + } + } elseif ($start != '' && $end == '') { + if ($file_time >= $start) { + @unlink($tmp); + } + } elseif ($start == '' && $end != '') { + if ($file_time <= $end) { + @unlink($tmp); + } + } else { + @unlink($tmp); + } + } + } else {//如果为目录 + self::delDir($tmp, $start, $end); + } + } + //判断文件夹下是否 还有文件 + $count = count(scandir($path)); + closedir($dh); + if ($count <= 2) @rmdir($path); + } + return true; + } + + /** + * 删除目录 + * @param $dirName + * @return bool + */ + public static function delDir($dirName) + { + if (!file_exists($dirName)) { + return false; + } + + $dir = opendir($dirName); + while ($fileName = readdir($dir)) { + $file = $dirName . '/' . $fileName; + if ($fileName != '.' && $fileName != '..') { + if (is_dir($file)) { + self::delDir($file); + } else { + unlink($file); + } + } + } + closedir($dir); + return rmdir($dirName); + } + + + /** + * 拷贝目录 + * @param string $surDir + * @param string $toDir + * @return bool + */ + public function copyDir(string $surDir, string $toDir) + { + $surDir = rtrim($surDir, '/') . '/'; + $toDir = rtrim($toDir, '/') . '/'; + if (!file_exists($surDir)) { + return false; + } + + if (!file_exists($toDir)) { + $this->createDir($toDir); + } + $file = opendir($surDir); + while ($fileName = readdir($file)) { + $file1 = $surDir . '/' . $fileName; + $file2 = $toDir . '/' . $fileName; + if ($fileName != '.' && $fileName != '..') { + if (is_dir($file1)) { + $this->copyDir($file1, $file2); + } else { + copy($file1, $file2); + } + } + } + closedir($file); + return true; + } + + + /** + * 列出目录 + * @param $dir 目录名 + * @return array 列出文件夹下内容,返回数组 $dirArray['dir']:存文件夹;$dirArray['file']:存文件 + */ + static function getDirs($dir) + { + $dir = rtrim($dir, '/') . '/'; + $dirArray [][] = NULL; + if (false != ($handle = opendir($dir))) { + $i = 0; + $j = 0; + while (false !== ($file = readdir($handle))) { + if (is_dir($dir . $file)) { //判断是否文件夹 + $dirArray ['dir'] [$i] = $file; + $i++; + } else { + $dirArray ['file'] [$j] = $file; + $j++; + } + } + closedir($handle); + } + return $dirArray; + } + + /** + * 统计文件夹大小 + * @param $dir + * @return int 文件夹大小(单位 B) + */ + public static function getSize($dir) + { + $dirlist = opendir($dir); + $dirsize = 0; + while (false !== ($folderorfile = readdir($dirlist))) { + if ($folderorfile != "." && $folderorfile != "..") { + if (is_dir("$dir/$folderorfile")) { + $dirsize += self::getSize("$dir/$folderorfile"); + } else { + $dirsize += filesize("$dir/$folderorfile"); + } + } + } + closedir($dirlist); + return $dirsize; + } + + /** + * 检测是否为空文件夹 + * @param $dir + * @return bool + */ + static function emptyDir($dir) + { + return (($files = @scandir($dir)) && count($files) <= 2); + } + + /** + * 创建多级目录 + * @param string $dir + * @param int $mode + * @return boolean + */ + public function createDir(string $dir, int $mode = 0777) + { + return is_dir($dir) or ($this->createDir(dirname($dir)) and mkdir($dir, $mode)); + } + + /** + * 创建指定路径下的指定文件 + * @param string $path (需要包含文件名和后缀) + * @param boolean $over_write 是否覆盖文件 + * @param int $time 设置时间。默认是当前系统时间 + * @param int $atime 设置访问时间。默认是当前系统时间 + * @return boolean + */ + public function createFile(string $path, bool $over_write = FALSE, int $time = NULL, int $atime = NULL) + { + $path = $this->dirReplace($path); + $time = empty($time) ? time() : $time; + $atime = empty($atime) ? time() : $atime; + if (file_exists($path) && $over_write) { + $this->unlinkFile($path); + } + $aimDir = dirname($path); + $this->createDir($aimDir); + return touch($path, $time, $atime); + } + + /** + * 关闭文件操作 + * @param string $path + * @return boolean + */ + public function close(string $path) + { + return fclose($path); + } + + /** + * 读取文件操作 + * @param string $file + * @return boolean + */ + public static function readFile(string $file) + { + return @file_get_contents($file); + } + + /** + * 确定服务器的最大上传限制(字节数) + * @return int 服务器允许的最大上传字节数 + */ + public function allowUploadSize() + { + $val = trim(ini_get('upload_max_filesize')); + return $val; + } + + /** + * 字节格式化 把字节数格式为 B K M G T P E Z Y 描述的大小 + * @param int $size 大小 + * @param int $dec 显示类型 + * @return int + */ + public static function byteFormat($size, $dec = 2) + { + $a = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; + $pos = 0; + while ($size >= 1024) { + $size /= 1024; + $pos++; + } + return round($size, $dec) . " " . $a[$pos]; + } + + /** + * 删除非空目录 + * 说明:只能删除非系统和特定权限的文件,否则会出现错误 + * @param string $dirName 目录路径 + * @param boolean $is_all 是否删除所有 + * @param boolean $delDir 是否删除目录 + * @return boolean + */ + public function removeDir(str $dir_path, bool $is_all = FALSE) + { + $dirName = $this->dirReplace($dir_path); + $handle = @opendir($dirName); + while (($file = @readdir($handle)) !== FALSE) { + if ($file != '.' && $file != '..') { + $dir = $dirName . '/' . $file; + if ($is_all) { + is_dir($dir) ? $this->removeDir($dir) : $this->unlinkFile($dir); + } else { + if (is_file($dir)) { + $this->unlinkFile($dir); + } + } + } + } + closedir($handle); + return @rmdir($dirName); + } + + /** + * 获取完整文件名 + * @param string $fn 路径 + * @return string + */ + public function getBasename(string $file_path) + { + $file_path = $this->dirReplace($file_path); + return basename(str_replace('\\', '/', $file_path)); + //return pathinfo($file_path,PATHINFO_BASENAME); + } + + /** + * 获取文件后缀名 + * @param string $file_name 文件路径 + * @return string + */ + public static function getExt(string $file) + { + $file = self::dirReplace($file); + return pathinfo($file, PATHINFO_EXTENSION); + } + + /** + * 取得指定目录名称 + * @param string $path 文件路径 + * @param int $num 需要返回以上级目录的数 + * @return string + */ + public function fatherDir(string $path, $num = 1) + { + $path = $this->dirReplace($path); + $arr = explode('/', $path); + if ($num == 0 || count($arr) < $num) return pathinfo($path, PATHINFO_BASENAME); + return substr(strrev($path), 0, 1) == '/' ? $arr[(count($arr) - (1 + $num))] : $arr[(count($arr) - $num)]; + } + + /** + * 删除文件 + * @param string $path + * @return boolean + */ + public function unlinkFile(string $path) + { + $path = $this->dirReplace($path); + if (file_exists($path)) { + return unlink($path); + } + } + + /** + * 文件操作(复制/移动) + * @param string $old_path 指定要操作文件路径(需要含有文件名和后缀名) + * @param string $new_path 指定新文件路径(需要新的文件名和后缀名) + * @param string $type 文件操作类型 + * @param boolean $overWrite 是否覆盖已存在文件 + * @param array $ignore 按后缀名过滤 + * @return boolean + */ + public function handleFile(string $old_path, string $new_path, string $type = 'copy', bool $overWrite = FALSE, array $ignore = []) + { + $old_path = $this->dirReplace($old_path); + $new_path = $this->dirReplace($new_path); + if (file_exists($new_path) && $overWrite = FALSE) { + return FALSE; + } else if (file_exists($new_path) && $overWrite = TRUE) { + $this->unlinkFile($new_path); + } + + $extension = pathinfo($old_path, PATHINFO_EXTENSION); + if ($ignore && $extension && in_array($extension, $ignore)) { + return true; + } + + $aimDir = dirname($new_path); + $this->createDir($aimDir); + switch ($type) { + case 'copy': + return copy($old_path, $new_path); + case 'move': + return @rename($old_path, $new_path); + } + } + + /** + * 文件夹操作(复制/移动) + * @param string $old_path 指定要操作文件夹路径 + * @param string $aimDir 指定新文件夹路径 + * @param string $type 操作类型 + * @param boolean $overWrite 是否覆盖文件和文件夹 + * @param array $ignore 按目录名过滤 + * @return boolean + */ + public function handleDir(string $old_path, string $new_path, string $type = 'copy', bool $overWrite = FALSE, array $ignore = []) + { + $new_path = $this->checkPath($new_path); + $old_path = $this->checkPath($old_path); + if (!is_dir($old_path)) return FALSE; + + if (!file_exists($new_path)) $this->createDir($new_path); + + $dirHandle = opendir($old_path); + + if (!$dirHandle) return FALSE; + + $boolean = TRUE; + + while (FALSE !== ($file = readdir($dirHandle))) { + if ($file == '.' || $file == '..') continue; + + if (!is_dir($old_path . $file)) { + $boolean = $this->handleFile($old_path . $file, $new_path . $file, $type, $overWrite); + } else { + if ($ignore && in_array($file, $ignore)) { + break; + } + $this->handleDir($old_path . $file, $new_path . $file, $type, $overWrite); + } + } + switch ($type) { + case 'copy': + closedir($dirHandle); + return $boolean; + case 'move': + closedir($dirHandle); + return @rmdir($old_path); + } + } + + /** + * 替换相应的字符 + * @param string $path 路径 + * @return string + */ + public static function dirReplace(string $path) + { + return str_replace('//', '/', str_replace('\\', '/', $path)); + } + + /** + * 读取指定路径下模板文件 + * @param string $path 指定路径下的文件 + * @return string $rstr + */ + public static function getTempltes(string $path) + { + $path = self::dirReplace($path); + if (file_exists($path)) { + $fp = fopen($path, 'r'); + $rstr = fread($fp, filesize($path)); + fclose($fp); + return $rstr; + } else { + return ''; + } + } + + /** + * @param string $oldname 原始名称 + * @param string $newname 新名称 + * @return bool + */ + public function rename(string $oldname, string $newname) + { + if (($newname != $oldname) && is_writable($oldname)) { + return rename($oldname, $newname); + } + } + + /** + * 获取指定路径下的信息 + * @param string $dir 路径 + * @return ArrayObject + */ + public function getDirInfo(string $dir) + { + $handle = @opendir($dir);//打开指定目录 + $directory_count = 0; + $total_size = 5; + $file_cout = 0; + $file_cout = 0; + while (FALSE !== ($file_path = readdir($handle))) { + if ($file_path != "." && $file_path != "..") { + //is_dir("$dir/$file_path") ? $sizeResult += $this->get_dir_size("$dir/$file_path") : $sizeResult += filesize("$dir/$file_path"); + $next_path = $dir . '/' . $file_path; + if (is_dir($next_path)) { + $directory_count++; + $result_value = self::getDirInfo($next_path); + $total_size += $result_value['size']; + $file_cout += $result_value['filecount']; + $directory_count += $result_value['dircount']; + } elseif (is_file($next_path)) { + $total_size += filesize($next_path); + $file_cout++; + } + } + } + closedir($handle);//关闭指定目录 + $result_value['size'] = $total_size; + $result_value['filecount'] = $file_cout; + $result_value['dircount'] = $directory_count; + return $result_value; + } + + /** + * 指定文件编码转换 + * @param string $path 文件路径 + * @param string $input_code 原始编码 + * @param string $out_code 输出编码 + * @return boolean + */ + public function changeFileCode(string $path, string $input_code, string $out_code) + { + if (is_file($path))//检查文件是否存在,如果存在就执行转码,返回真 + { + $content = file_get_contents($path); + $content = string::chang_code($content, $input_code, $out_code); + $fp = fopen($path, 'w'); + fclose($fp); + return (bool)fputs($fp, $content); + } + } + + /** + * 指定目录下指定条件文件编码转换 + * @param string $dirname 目录路径 + * @param string $input_code 原始编码 + * @param string $out_code 输出编码 + * @param boolean $is_all 是否转换所有子目录下文件编码 + * @param string $exts 文件类型 + * @return boolean + */ + public function changeDirFilesCode(string $dirname, string $input_code, string $out_code, bool $is_all = TRUE, string $exts = '') + { + if (is_dir($dirname)) { + $fh = opendir($dirname); + while (($file = readdir($fh)) !== FALSE) { + if (strcmp($file, '.') == 0 || strcmp($file, '..') == 0) { + continue; + } + $filepath = $dirname . '/' . $file; + + if (is_dir($filepath) && $is_all == TRUE) { + $files = $this->changeDirFilesCode($filepath, $input_code, $out_code, $is_all, $exts); + } else { + if ($this->getExt($filepath) == $exts && is_file($filepath)) { + $boole = $this->changeFileCode($filepath, $input_code, $out_code, $is_all, $exts); + if (!$boole) continue; + } + } + } + closedir($fh); + return TRUE; + } else { + return FALSE; + } + } + + /** + * 列出指定目录下符合条件的文件和文件夹 + * @param string $dirname 路径 + * @param boolean $is_all 是否列出子目录中的文件 + * @param string $exts 需要列出的后缀名文件 + * @param string $sort 数组排序 + * @return ArrayObject + */ + public function listDirInfo(string $dirname, bool $is_all = FALSE, string $exts = '', string $sort = 'ASC') + { + //处理多于的/号 + $new = strrev($dirname); + if (strpos($new, '/') == 0) { + $new = substr($new, 1); + } + $dirname = strrev($new); + + $sort = strtolower($sort);//将字符转换成小写 + + $files = []; + $subfiles = []; + + if (is_dir($dirname)) { + $fh = opendir($dirname); + while (($file = readdir($fh)) !== FALSE) { + if (strcmp($file, '.') == 0 || strcmp($file, '..') == 0) continue; + + $filepath = $dirname . '/' . $file; + + switch ($exts) { + case '*': + if (is_dir($filepath) && $is_all == TRUE) { + $files = array_merge($files, self::listDirInfo($filepath, $is_all, $exts, $sort)); + } + array_push($files, $filepath); + break; + case 'folder': + if (is_dir($filepath) && $is_all == TRUE) { + $files = array_merge($files, self::listDirInfo($filepath, $is_all, $exts, $sort)); + array_push($files, $filepath); + } elseif (is_dir($filepath)) { + array_push($files, $filepath); + } + break; + case 'file': + if (is_dir($filepath) && $is_all == TRUE) { + $files = array_merge($files, self::listDirInfo($filepath, $is_all, $exts, $sort)); + } elseif (is_file($filepath)) { + array_push($files, $filepath); + } + break; + default: + if (is_dir($filepath) && $is_all == TRUE) { + $files = array_merge($files, self::listDirInfo($filepath, $is_all, $exts, $sort)); + } elseif (preg_match("/\.($exts)/i", $filepath) && is_file($filepath)) { + array_push($files, $filepath); + } + break; + } + + switch ($sort) { + case 'asc': + sort($files); + break; + case 'desc': + rsort($files); + break; + case 'nat': + natcasesort($files); + break; + } + } + closedir($fh); + return $files; + } else { + return FALSE; + } + } + + /** + * 返回指定路径的文件夹信息,其中包含指定路径中的文件和目录 + * @param string $dir + * @return ArrayObject + */ + public function dirInfo(string $dir) + { + return scandir($dir); + } + + /** + * 判断目录是否为空 + * @param string $dir + * @return boolean + */ + public function isEmpty(string $dir) + { + $handle = opendir($dir); + while (($file = readdir($handle)) !== false) { + if ($file != '.' && $file != '..') { + closedir($handle); + return true; + } + } + closedir($handle); + return false; + } + + /** + * 返回指定文件和目录的信息 + * @param string $file + * @return ArrayObject + */ + public static function listInfo(string $file) + { + $dir = []; + $dir['filename'] = basename($file);//返回路径中的文件名部分。 + $dir['pathname'] = strstr(php_uname('s'), 'Windows') ? str_replace('\\', '\\\\', realpath($file)) : realpath($file);//返回绝对路径名。 + $dir['owner'] = fileowner($file);//文件的 user ID (所有者)。 + $dir['perms'] = fileperms($file);//返回文件的 inode 编号。 + $dir['inode'] = fileinode($file);//返回文件的 inode 编号。 + $dir['group'] = filegroup($file);//返回文件的组 ID。 + $dir['path'] = dirname($file);//返回路径中的目录名称部分。 + $dir['atime'] = fileatime($file);//返回文件的上次访问时间。 + $dir['ctime'] = filectime($file);//返回文件的上次改变时间。 + $dir['perms'] = fileperms($file);//返回文件的权限。 + $dir['size'] = self::byteFormat(filesize($file), 2);//返回文件大小。 + $dir['type'] = filetype($file);//返回文件类型。 + $dir['ext'] = is_file($file) ? pathinfo($file, PATHINFO_EXTENSION) : '';//返回文件后缀名 + $dir['mtime'] = filemtime($file);//返回文件的上次修改时间。 + $dir['isDir'] = is_dir($file);//判断指定的文件名是否是一个目录。 + $dir['isFile'] = is_file($file);//判断指定文件是否为常规的文件。 + $dir['isLink'] = is_link($file);//判断指定的文件是否是连接。 + $dir['isReadable'] = is_readable($file);//判断文件是否可读。 + $dir['isWritable'] = is_writable($file);//判断文件是否可写。 + $dir['isUpload'] = is_uploaded_file($file);//判断文件是否是通过 HTTP POST 上传的。 + return $dir; + } + + /** + * 返回关于打开文件的信息 + * @param $file + * @return ArrayObject + * 数字下标 关联键名(自 PHP 4.0.6) 说明 + * 0 dev 设备名 + * 1 ino 号码 + * 2 mode inode 保护模式 + * 3 nlink 被连接数目 + * 4 uid 所有者的用户 id + * 5 gid 所有者的组 id + * 6 rdev 设备类型,如果是 inode 设备的话 + * 7 size 文件大小的字节数 + * 8 atime 上次访问时间(Unix 时间戳) + * 9 mtime 上次修改时间(Unix 时间戳) + * 10 ctime 上次改变时间(Unix 时间戳) + * 11 blksize 文件系统 IO 的块大小 + * 12 blocks 所占据块的数目 + */ + public function openInfo(string $file) + { + $file = fopen($file, "r"); + $result = fstat($file); + fclose($file); + return $result; + } + + /** + * 改变文件和目录的相关属性 + * @param string $file 文件路径 + * @param string $type 操作类型 + * @param string $ch_info 操作信息 + * @return boolean + */ + public function change_file($file, $type, $ch_info) + { + switch ($type) { + case 'group' : + $is_ok = chgrp($file, $ch_info);//改变文件组。 + break; + case 'mode' : + $is_ok = chmod($file, $ch_info);//改变文件模式。 + break; + case 'ower' : + $is_ok = chown($file, $ch_info);//改变文件所有者。 + break; + } + } + + /** + * 取得文件路径信息 + * @param $full_path 完整路径 + * @return ArrayObject + */ + public function getFileType(string $path) + { + //pathinfo() 函数以数组的形式返回文件路径的信息。 + //---------$file_info = pathinfo($path); echo file_info['extension'];----------// + //extension取得文件后缀名【pathinfo($path,PATHINFO_EXTENSION)】-----dirname取得文件路径【pathinfo($path,PATHINFO_DIRNAME)】-----basename取得文件完整文件名【pathinfo($path,PATHINFO_BASENAME)】-----filename取得文件名【pathinfo($path,PATHINFO_FILENAME)】 + return pathinfo($path); + } + + /** + * 取得上传文件信息 + * @param $file file属性信息 + * @return array + */ + public function getUploadFileInfo($file) + { + $file_info = request()->file($file);//取得上传文件基本信息 + $info = []; + $info['type'] = strtolower(trim(stripslashes(preg_replace("/^(.+?);.*$/", "\\1", $file_info['type'])), '"'));//取得文件类型 + $info['temp'] = $file_info['tmp_name'];//取得上传文件在服务器中临时保存目录 + $info['size'] = $file_info['size'];//取得上传文件大小 + $info['error'] = $file_info['error'];//取得文件上传错误 + $info['name'] = $file_info['name'];//取得上传文件名 + $info['ext'] = $this->getExt($file_info['name']);//取得上传文件后缀 + return $info; + } + + /** + * 设置文件命名规则 + * @param string $type 命名规则 + * @param string $filename 文件名 + * @return string + */ + public function setFileName(string $type) + { + switch ($type) { + case 'hash' : + $new_file = md5(uniqid(mt_rand()));//mt_srand()以随机数md5加密来命名 + break; + case 'time' : + $new_file = time(); + break; + default : + $new_file = date($type, time());//以时间格式来命名 + break; + } + return $new_file; + } + + /** + * 文件保存路径处理 + * @return string + */ + public function checkPath($path) + { + return (preg_match('/\/$/', $path)) ? $path : $path . '/'; + } + + /** + * 文件下载 + * $save_dir 保存路径 + * $filename 文件名 + * @return array + */ + public static function downRemoteFile(string $url, string $save_dir = '', string $filename = '', int $type = 0) + { + + if (trim($url) == '') { + return ['file_name' => '', 'save_path' => '', 'error' => 1]; + } + if (trim($save_dir) == '') { + $save_dir = './'; + } + if (trim($filename) == '') {//保存文件名 + $ext = strrchr($url, '.'); + // if($ext!='.gif'&&$ext!='.jpg'){ + // return ['file_name'=>'','save_path'=>'','error'=>3]; + // } + $filename = time() . $ext; + } + if (0 !== strrpos($save_dir, '/')) { + $save_dir .= '/'; + } + //创建保存目录 + if (!file_exists($save_dir) && !mkdir($save_dir, 0777, true)) { + return ['file_name' => '', 'save_path' => '', 'error' => 5]; + } + //获取远程文件所采用的方法 + if ($type) { + $ch = curl_init(); + $timeout = 5; + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); + $img = curl_exec($ch); + curl_close($ch); + } else { + ob_start(); + readfile($url); + $img = ob_get_contents(); + ob_end_clean(); + } + //$size=strlen($img); + //文件大小 + $fp2 = fopen($save_dir . $filename, 'a'); + + fwrite($fp2, $img); + fclose($fp2); + unset($img, $url); + return ['file_name' => $filename, 'save_path' => $save_dir . $filename, 'error' => 0]; + } + + /** + * 解压zip文件 + * @param string $filename + * @param string $savename + * @return bool + */ + public static function zipOpen(string $filename, string $savename) + { + $zip = new \ZipArchive; + $zipfile = $filename; + $res = $zip->open($zipfile); + $toDir = $savename; + if (!file_exists($toDir)) mkdir($toDir, 0777); + $docnum = $zip->numFiles; + for ($i = 0; $i < $docnum; $i++) { + $statInfo = $zip->statIndex($i); + if ($statInfo['crc'] == 0 && $statInfo['comp_size'] != 2) { + //新建目录 + mkdir($toDir . '/' . substr($statInfo['name'], 0, -1), 0777); + } else { + //拷贝文件 + copy('zip://' . $zipfile . '#' . $statInfo['name'], $toDir . '/' . $statInfo['name']); + } + } + $zip->close(); + return true; + } + + /** + *设置字体格式 + * @param $title string 必选 + * return string + */ + public static function setUtf8($title) + { + return iconv('utf-8', 'gb2312', $title); + } + + /** + *检查指定文件是否能写入 + * @param $file string 必选 + * return boole + */ + public static function isWritable($file) + { + $file = str_replace('\\', '/', $file); + if (!file_exists($file)) return false; + return is_writable($file); + } + + /**读取excel文件内容 + * @param $filePath + * @param string $suffix + * @return bool + * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception + */ + public function readExcel($filePath, $row_num = 1, $suffix = 'Xlsx') + { + if (!$filePath) return false; + $pathInfo = pathinfo($filePath, PATHINFO_EXTENSION); + if (!$pathInfo || $pathInfo != "xlsx") throw new AdminException(400728); + //加载读取模型 + $readModel = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($suffix); + // 创建读操作 + // 打开文件 载入excel表格 + try { + $spreadsheet = $readModel->load($filePath); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->getHighestColumn(); + $highestRow = $sheet->getHighestRow(); + $lines = $highestRow - 1; + if ($lines <= 0) { + throw new AdminException(400729); + } + // 用于存储表格数据 + $data = []; + for ($i = $row_num; $i <= $highestRow; $i++) { + $t1 = $this->objToStr($sheet->getCellByColumnAndRow(1, $i)->getValue()) ?? ''; + $t2 = $this->objToStr($sheet->getCellByColumnAndRow(2, $i)->getValue()); + if ($t2) { + $data[] = [ + 'key' => $t1, + 'value' => $t2 + ]; + } + } + return $data; + } catch (\Exception $e) { + throw new AdminException($e->getMessage()); + } + } + + /**对象转字符 + * @param $value + * @return mixed + */ + public function objToStr($value) + { + return is_object($value) ? $value->__toString() : $value; + } + + /** + * 压缩文件夹及文件 + * @param string $source 需要压缩的文件夹/文件路径 + * @param string $destination 压缩后的保存地址 + * @param string $folder 文件夹前缀,保存时需要去掉的父级文件夹 + * @return boolean + */ + function addZip($source, $destination, $folder = '') + { + if (!extension_loaded('zip') || !file_exists($source)) { + return false; + } + + $zip = new \ZipArchive; + if (!$zip->open($destination, $zip::CREATE)) { + return false; + } + $source = str_replace('\\', '/', $source); + $folder = str_replace('\\', '/', $folder); + if (is_dir($source) === true) { + $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source), \RecursiveIteratorIterator::SELF_FIRST); + foreach ($files as $file) { + $file = str_replace('\\', '/', $file); + if (in_array(substr($file, strrpos($file, '/') + 1), array('.', '..'))) continue; + if (is_dir($file) === true) { + $fileName = $folder ? str_replace($folder . '/', '', $file . '/') : $file . '/'; + $zip->addEmptyDir($fileName); + } else if (is_file($file) === true) { + $fileName = $folder ? str_replace($folder . '/', '', $file) : $file; + $zip->addFromString($fileName, file_get_contents($file)); + } + } + } else if (is_file($source) === true) { + $zip->addFromString(basename($source), file_get_contents($source)); + } + return $zip->close(); + } + + /** + * 解压缩文件夹及文件 + * @param string $source 需要解压缩的文件路径 + * @param string $folder 文件夹前缀,保存时需要去掉的父级文件夹 + * @return boolean + */ + public function extractFile(string $source, string $folder): bool + { + if (!extension_loaded('zip') || !file_exists($source)) { + return false; + } + + $zip = new \ZipArchive; + $zip->open($source); + return $zip->extractTo($folder); + } + + /** + * 批量写入文件 + * @param array $make + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/18 + */ + public static function batchMakeFiles(array $make) + { + + $files = []; + $dirnames = []; + foreach ($make as $item) { + if ($item instanceof Make) { + $files[] = $item = $item->toArray(); + } + try { + $dirnames[] = $dirname = dirname($item['path']); + if (!is_dir($dirname)) { + mkdir($dirname, 0755, true); + } + } catch (\Throwable $e) { + if ($dirnames) { + foreach ($dirnames as $dirname) { + if (strstr($dirname, app()->getRootPath() . 'backup') !== false) { + rmdir($dirname); + } + } + } + throw new \RuntimeException($e->getMessage()); + } + } + $res = true; + foreach ($files as $item) { + $res = $res && file_put_contents($item['path'], $item['content'], LOCK_EX); + } + + return $res; + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/FormBuilder.php b/demo/thinkphp/backend/phoenix/services/FormBuilder.php new file mode 100644 index 0000000000000000000000000000000000000000..cf255e7528a9f8c85d69e5be2f7b48286b99745c --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/FormBuilder.php @@ -0,0 +1,34 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\services; + +use FormBuilder\Factory\Iview as Form; + +/** + * Form Builder + * Class FormBuilder + * @package crmeb\services + */ +class FormBuilder extends Form +{ + + public static function setOptions($call){ + if (is_array($call)) { + return $call; + }else{ + return $call(); + } + + } + + +} diff --git a/demo/thinkphp/backend/phoenix/services/GroupDataService.php b/demo/thinkphp/backend/phoenix/services/GroupDataService.php new file mode 100644 index 0000000000000000000000000000000000000000..d33e4b2c61205ac2805dec038ade028894b00193 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/GroupDataService.php @@ -0,0 +1,87 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\services; + +use app\services\system\config\SystemGroupDataServices; + +/** + * 获取组合数据配置 + * Class GroupDataService + * @package crmeb\services + */ +class GroupDataService +{ + /** + * 获取单个值 + * @param string $config_name 配置名称 + * @param int $limit 截取多少条 + * @param bool $isCaChe 是否读取缓存 + * @return array + */ + public static function getData(string $config_name, int $limit = 0, bool $isCaChe = false): array + { + $callable = function () use ($config_name, $limit) { + try { + /** @var SystemGroupDataServices $service */ + $service = app()->make(SystemGroupDataServices::class); + return $service->getConfigNameValue($config_name, $limit); + } catch (\Exception $e) { + return []; + } + }; + try { + $cacheName = $limit ? "data_{$config_name}_{$limit}" : "data_{$config_name}"; + + if ($isCaChe) + return $callable(); + + return CacheService::remember($cacheName, $callable); + + } catch (\Throwable $e) { + return $callable(); + } + } + + /** + * 根据id 获取单个值 + * @param int $id + * @param bool $isCaChe 是否读取缓存 + * @return array + */ + public static function getDataNumber(int $id, bool $isCaChe = false): array + { + $callable = function () use ($id) { + try { + + /** @var SystemGroupDataServices $service */ + $service = app()->make(SystemGroupDataServices::class); + $data = $service->getDateValue($id); + if (is_object($data)) + $data = $data->toArray(); + return $data; + } catch (\Exception $e) { + return []; + } + }; + try { + $cacheName = "data_number_{$id}"; + + if ($isCaChe) + return $callable(); + + return CacheService::remember($cacheName, $callable); + + } catch (\Throwable $e) { + return $callable(); + } + } +} diff --git a/demo/thinkphp/backend/phoenix/services/HttpService.php b/demo/thinkphp/backend/phoenix/services/HttpService.php new file mode 100644 index 0000000000000000000000000000000000000000..e9f09ed4dfaac495dd7e6d4a6dda173fb54bd8a3 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/HttpService.php @@ -0,0 +1,151 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services; + +/** + * Class HttpService + * @package crmeb\services + */ +class HttpService +{ + /** + * 错误信息 + * @var string + */ + private static $curlError; + + /** + * header头信息 + * @var string + */ + private static $headerStr; + + /** + * 请求状态 + * @var int + */ + private static $status; + + /** + * @return string + */ + public static function getCurlError() + { + return self::$curlError; + } + + /** + * @return mixed + */ + public static function getStatus() + { + return self::$status; + } + + /** + * 模拟GET发起请求 + * @param $url + * @param array $data + * @param bool $header + * @param int $timeout + * @return bool|string + */ + public static function getRequest($url, $data = array(), $header = false, $timeout = 10) + { + if (!empty($data)) { + $url .= (stripos($url, '?') === false ? '?' : '&'); + $url .= (is_array($data) ? http_build_query($data) : $data); + } + + return self::request($url, 'get', array(), $header, $timeout); + } + + /** + * curl 请求 + * @param $url + * @param string $method + * @param array $data + * @param bool $header + * @param int $timeout + * @return bool|string + */ + public static function request($url, $method = 'get', $data = array(), $header = false, $timeout = 15) + { + self::$status = null; + self::$curlError = null; + self::$headerStr = null; + + $curl = curl_init($url); + $method = strtoupper($method); + //请求方式 + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); + //post请求 + if ($method == 'POST') curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + //超时时间 + curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); + //设置header头 + if ($header !== false) curl_setopt($curl, CURLOPT_HTTPHEADER, $header); + + curl_setopt($curl, CURLOPT_FAILONERROR, false); + //返回抓取数据 + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + //输出header头信息 + curl_setopt($curl, CURLOPT_HEADER, true); + //TRUE 时追踪句柄的请求字符串,从 PHP 5.1.3 开始可用。这个很关键,就是允许你查看请求header + curl_setopt($curl, CURLINFO_HEADER_OUT, true); + //https请求 + if (1 == strpos("$" . $url, "https://")) { + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); + } + self::$curlError = curl_error($curl); + + list($content, $status) = [curl_exec($curl), curl_getinfo($curl), curl_close($curl)]; + self::$status = $status; + self::$headerStr = trim(substr($content, 0, $status['header_size'])); + $content = trim(substr($content, $status['header_size'])); + return (intval($status["http_code"]) === 200) ? $content : false; + } + + /** + * 模拟POST发起请求 + * @param $url + * @param $data + * @param bool $header + * @param int $timeout + * @return bool|string + */ + public static function postRequest($url, $data = array(), $header = false, $timeout = 10) + { + return self::request($url, 'post', $data, $header, $timeout); + } + + /** + * 获取header头字符串类型 + * @return mixed + */ + public static function getHeaderStr() + { + return self::$headerStr; + } + + /** + * 获取header头数组类型 + * @return array + */ + public static function getHeader() + { + $headArr = explode("\r\n", self::$headerStr); + return $headArr; + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/LockService.php b/demo/thinkphp/backend/phoenix/services/LockService.php new file mode 100644 index 0000000000000000000000000000000000000000..64a32d5ed7fab67a7f1210c0025db0363ea6c31c --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/LockService.php @@ -0,0 +1,54 @@ +lock($key, $key, $ex); + return $fn(); + } finally { + $this->unlock($key, $key); + } + } + + public function tryLock($key, $value = '1', $ex = 6) + { + return Cache::store('redis')->handler()->set('lock_' . $key, $value, ["NX", "EX" => $ex]); + } + + public function lock($key, $value = '1', $ex = 6) + { + if ($this->tryLock($key, $value, $ex)) { + return true; + } + usleep(200); + $this->lock($key, $value, $ex); + } + + public function unlock($key, $value = '1') + { + $script = <<< EOF +if (redis.call("get", "lock_" .. KEYS[1]) == ARGV[1]) then + return redis.call("del", "lock_" .. KEYS[1]) +else + return 0 +end +EOF; + return Cache::store('redis')->handler()->eval($script, [$key, $value], 1) > 0; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/MysqlBackupService.php b/demo/thinkphp/backend/phoenix/services/MysqlBackupService.php new file mode 100644 index 0000000000000000000000000000000000000000..693a678ebddfea27d4818185e89f49785439a091 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/MysqlBackupService.php @@ -0,0 +1,516 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\services; + +use phoenix\exceptions\AdminException; +use think\facade\Db; + +class MysqlBackupService +{ + /** + * 文件指针 + * @var resource + */ + private $fp; + + /** + * 备份文件信息 part - 卷号,name - 文件名 + * @var array + */ + private array $file; + /** + * 当前打开文件大小 + * @var integer + */ + private int $size = 0; + + /** + * 数据库配置 + */ + private $dbconfig = array(); + /** + * 备份配置 + * @var integer + */ + private $config = array( + 'path' => './Data/', + //数据库备份路径 + 'part' => 20971520, + //数据库备份卷大小 + 'compress' => 0, + //数据库备份文件是否启用压缩 0不压缩 1 压缩 + 'level' => 9, + ); + + /** + * 数据库备份构造方法 + * + * @param array $config 备份配置信息 + */ + public function __construct(array $config = []) + { + $this->config['path'] = app()->getRootPath() . 'backup/'; + $this->config = array_merge($this->config, $config); + //初始化文件名 + $this->setFile(); + //初始化数据库连接参数 + $this->setDbConn(); + //检查文件是否可写 + if (!$this->checkPath($this->config['path'])) { + throw new AdminException(400734); + } + } + + /** + * 设置脚本运行超时时间 + * 0表示不限制,支持连贯操作 + */ + public function setTimeout($time = null): static + { + if (!is_null($time)) { + set_time_limit($time) || ini_set("max_execution_time", $time); + } + return $this; + } + + /** + * 设置数据库连接必备参数 + * + * @param array $dbconfig 数据库连接配置信息 + * + * @return $this + */ + public function setDbConn(array $dbconfig = []): static + { + if (empty($dbconfig)) { + $this->dbconfig = config('database.connections.' . config('database.default')); + //$this->dbconfig = Config::get('database'); + } else { + $this->dbconfig = $dbconfig; + } + return $this; + } + + /** + * 设置备份文件名 + * + * @param null $file + * @return $this + */ + public function setFile($file = null): static + { + if (is_null($file)) { + $this->file = ['name' => date('Ymd-His'), 'part' => 1]; + } else { + if (!array_key_exists("name", $file) && !array_key_exists("part", $file)) { + $this->file = $file['1']; + } else { + $this->file = $file; + } + } + return $this; + } + + //数据类连接 + public static function connect(): \think\db\ConnectionInterface + { + return Db::connect(); + } + + /** + * 数据库表列表 + * + * @param string|null $table + * @param int $type + * + * @return array + */ + public function dataList(?string $table = null, int $type = 1): array + { + $db = self::connect(); + if (is_null($table)) { + $list = $db->query("SHOW TABLE STATUS"); + } else { + if ($type) { + $list = $db->query("SHOW FULL COLUMNS FROM {$table}"); + } else { + $list = $db->query("show columns from {$table}"); + } + } + return array_map('array_change_key_case', $list); + } + + /** + * 数据库备份文件列表 + * + * @return array + */ + public function fileList(): array + { + if (!is_dir($this->config['path'])) { + mkdir($this->config['path'], 0755, true); + } + $path = realpath($this->config['path']); + $flag = \FilesystemIterator::KEY_AS_FILENAME; + $glob = new \FilesystemIterator($path, $flag); + $list = array(); + foreach ($glob as $name => $file) { + if (preg_match('/^\\d{8,8}-\\d{6,6}-\\d+\\.sql(?:\\.gz)?$/', $name)) { + $info['filename'] = $name; + $name = sscanf($name, '%4s%2s%2s-%2s%2s%2s-%d'); + $date = "{$name[0]}-{$name[1]}-{$name[2]}"; + $time = "{$name[3]}:{$name[4]}:{$name[5]}"; + $part = $name[6]; + if (isset($list["{$date} {$time}"])) { + $info = $list["{$date} {$time}"]; + $info['part'] = max($info['part'], $part); + $info['size'] = $info['size'] + $file->getSize(); + } else { + $info['part'] = $part; + $info['size'] = $file->getSize(); + } + $extension = strtoupper(pathinfo($file->getFilename(), PATHINFO_EXTENSION)); + $info['compress'] = $extension === 'SQL' ? '-' : $extension; + $info['time'] = strtotime("{$date} {$time}"); + $list["{$date} {$time}"] = $info; + } + } + return $list; + } + + /** + * @param string $type + * @param int $time + * @return array|false|string + * @throws \Exception + */ + public function getFile($type = '', $time = 0) + { + // + if (!is_numeric($time)) { + throw new AdminException(400735); + } + switch ($type) { + case 'time': + $name = date('Ymd-His', $time) . '-*.sql*'; + $path = realpath($this->config['path']) . DIRECTORY_SEPARATOR . $name; + return glob($path); + case 'timeverif': + $name = date('Ymd-His', $time) . '-*.sql*'; + $path = realpath($this->config['path']) . DIRECTORY_SEPARATOR . $name; + $files = glob($path); + $list = array(); + foreach ($files as $name) { + $basename = basename($name); + $match = sscanf($basename, '%4s%2s%2s-%2s%2s%2s-%d'); + $gz = preg_match('/^\\d{8,8}-\\d{6,6}-\\d+\\.sql.gz$/', $basename); + $list[$match[6]] = array($match[6], $name, $gz); + } + $last = end($list); + if (count($list) === $last[0]) { + return $list; + } else { + throw new AdminException(400736); + } + case 'pathname': + return "{$this->config['path']}{$this->file['name']}-{$this->file['part']}.sql"; + case 'filename': + return "{$this->file['name']}-{$this->file['part']}.sql"; + case 'filepath': + return $this->config['path']; + default: + return array('pathname' => "{$this->config['path']}{$this->file['name']}-{$this->file['part']}.sql", 'filename' => "{$this->file['name']}-{$this->file['part']}.sql", 'filepath' => $this->config['path'], 'file' => $this->file); + } + } + + /** + * 删除备份文件 + * @param $time + * @return mixed + * @throws \Exception + */ + public function delFile($time): mixed + { + if ($time) { + $file = $this->getFile('time', $time); + array_map("unlink", $this->getFile('time', $time)); + if (count($this->getFile('time', $time))) { + throw new AdminException(100008); + } else { + return $time; + } + } else { + throw new AdminException(400735); + } + } + + /** + * 下载备份 + * + * @param $time + * @param int $part + * @param bool $isFile + * + * @return bool|int|string + * @throws \Exception + */ + public function downloadFile($time, int $part = 0, bool $isFile = false): bool|int|string + { + $file = $this->getFile('time', $time); + $fileName = $file[$part]; + if (file_exists($fileName)) { + if ($isFile) { + $key = password_hash(time() . $fileName, PASSWORD_DEFAULT); + CacheService::set($key, ['path' => $fileName, 'fileName' => substr(strstr($fileName, 'backup'), 7)], 300); + return $key; + } + ob_end_clean(); + header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); + header('Content-Description: File Transfer'); + header('Access-Control-Allow-Origin: ' . request()->domain()); + header('Content-Type: application/octet-stream'); + header('Content-Length: ' . filesize($fileName)); + header('Content-Disposition: attachment; filename=' . basename($fileName)); + return readfile($fileName); + } else { + throw new AdminException(400736); + } + } + + public function import($start): bool|array|int + { + //还原数据 + $db = self::connect(); + if ($this->config['compress']) { + $gz = gzopen($this->file[1], 'r'); + $size = 0; + } else { + $size = filesize($this->file[1]); + $gz = fopen($this->file[1], 'r'); + } + $sql = ''; + if ($start) { + $this->config['compress'] ? gzseek($gz, $start) : fseek($gz, $start); + } + for ($i = 0; $i < 1000; $i++) { + $sql .= $this->config['compress'] ? gzgets($gz) : fgets($gz); + if (preg_match('/.*;$/', trim($sql))) { + if (false !== $db->execute($sql)) { + $start += strlen($sql); + } else { + return false; + } + $sql = ''; + } elseif ($this->config['compress'] ? gzeof($gz) : feof($gz)) { + return 0; + } + } + return array($start, $size); + } + + /** + * 写入初始数据 + * + * @return boolean true - 写入成功,false - 写入失败 + */ + public function Backup_Init(): bool + { + $sql = "-- -----------------------------\n"; + $sql .= "-- Think MySQL Data Transfer \n"; + $sql .= "-- \n"; + $sql .= "-- Host : " . $this->dbconfig['hostname'] . "\n"; + $sql .= "-- Port : " . $this->dbconfig['hostport'] . "\n"; + $sql .= "-- Database : " . $this->dbconfig['database'] . "\n"; + $sql .= "-- \n"; + $sql .= "-- Part : #{$this->file['part']}\n"; + $sql .= "-- Date : " . date("Y-m-d H:i:s") . "\n"; + $sql .= "-- -----------------------------\n\n"; + $sql .= "SET FOREIGN_KEY_CHECKS = 0;\n\n"; + return $this->write($sql); + } + + /** + * 备份表结构 + * + * @param string $table + * @param int $start + * @param string $sql + * + * @return bool|int + * @throws \think\db\exception\BindParamException + */ + public function backup(string $table, int $start, string $sql = ''): bool|int + { + $db = self::connect(); + // 备份表结构 + if (0 == $start) { + $result = $db->query("SHOW CREATE TABLE `{$table}`"); + $sql .= "\n"; + $sql .= "-- -----------------------------\n"; + $sql .= "-- Table structure for `{$table}`\n"; + $sql .= "-- -----------------------------\n"; + $sql .= "DROP TABLE IF EXISTS `{$table}`;\n"; + $sql .= trim($result[0]['Create Table']) . ";\n\n"; + } + //数据总数 + $result = $db->query("SELECT COUNT(*) AS count FROM `{$table}`"); + $count = $result['0']['count']; + //备份表数据 + if ($count) { + //写入数据注释 + if (0 == $start) { + $sql .= "-- -----------------------------\n"; + $sql .= "-- Records of `{$table}`\n"; + $sql .= "-- -----------------------------\n"; + } + //备份数据记录 + $result = $db->query("SELECT * FROM `{$table}` LIMIT :MIN, 1000", ['MIN' => intval($start)]); + foreach ($result as $row) { + $row = array_map('addslashes', $row); + $sql .= "INSERT INTO `{$table}` VALUES ('" . str_replace(array("\r", "\n"), array('\\r', '\\n'), implode("', '", $row)) . "');\n"; + } + if (false === $this->write($sql)) { + return false; + } + //还有更多数据 + if ($count > $start + 1000) { + //return array($start + 1000, $count); + return $this->backup($table, $start + 1000); + } + } + //备份下一表 + return 0; + } + + /** + * 优化表 + * + * @param array|string $tables + * + * @return mixed + */ + public function optimize(array|string $tables): mixed + { + if ($tables) { + $db = self::connect(); + if (is_array($tables)) { + $tables = implode('`,`', $tables); + $list = $db->query("OPTIMIZE TABLE `{$tables}`"); + } else { + $list = $db->query("OPTIMIZE TABLE {$tables}"); + } + if (!$list) { + throw new AdminException(400737); + } + return $list; + } else { + throw new AdminException(400738); + } + } + + /** + * 修复表 + * + * @param string|array|null $tables + * + * @return array + */ + public function repair(string|array|null $tables = null): array + { + if ($tables) { + $db = self::connect(); + if (is_array($tables)) { + $tables = implode('`,`', $tables); + $list = $db->query("REPAIR TABLE `{$tables}`"); + } else { + $list = $db->query("REPAIR TABLE {$tables}"); + } + if ($list) { + return $list; + } else { + throw new AdminException(400737); + } + } else { + throw new AdminException(400738); + } + } + + /** + * 写入SQL语句 + * + * @param string $sql 要写入的SQL语句 + * @return boolean true - 写入成功,false - 写入失败! + */ + private function write(string $sql): bool + { + $size = strlen($sql); + //由于压缩原因,无法计算出压缩后的长度,这里假设压缩率为50%, + //一般情况压缩率都会高于50%; + $size = $this->config['compress'] ? $size / 2 : $size; + $this->open($size); + return $this->config['compress'] ? @gzwrite($this->fp, $sql) : @fwrite($this->fp, $sql); + } + + /** + * 打开一个卷,用于写入数据 + * + * @param integer $size 写入数据的大小 + */ + private function open(int $size): void + { + if ($this->fp) { + $this->size += $size; + if ($this->size > $this->config['part']) { + $this->config['compress'] ? @gzclose($this->fp) : @fclose($this->fp); + $this->fp = null; + $this->file['part']++; + session('backup_file', $this->file); + $this->Backup_Init(); + } + } else { + $backuppath = $this->config['path']; + $filename = "{$backuppath}{$this->file['name']}-{$this->file['part']}.sql"; + if ($this->config['compress']) { + $filename = "{$filename}.gz"; + $this->fp = @gzopen($filename, "a{$this->config['level']}"); + } else { + $this->fp = @fopen($filename, 'a'); + } + $this->size = filesize($filename) + $size; + } + } + + /** + * 检查目录是否可写 + * + * @param string $path + * @return bool + */ + protected function checkPath(string $path): bool + { + if (is_dir($path)) { + return true; + } + if (mkdir($path, 0755, true)) { + return true; + } else { + return false; + } + } + + /** + * 析构方法,用于关闭文件资源 + */ + public function __destruct() + { +// $this->config['compress'] ? @gzclose($this->fp) : @fclose($this->fp); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/SpreadsheetExcelService.php b/demo/thinkphp/backend/phoenix/services/SpreadsheetExcelService.php new file mode 100644 index 0000000000000000000000000000000000000000..c33630848f0d950aef052f59b39688fd3c893932 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/SpreadsheetExcelService.php @@ -0,0 +1,307 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services; + + +class SpreadsheetExcelService +{ + // + private static $instance = null; + //PHPSpreadsheet实例化对象 + private static $spreadsheet = null; + //sheet实例化对象 + private static $sheet = null; + //表头计数 + protected static $count; + //表头占行数 + protected static $topNumber = 3; + //表能占据表行的字母对应self::$cellkey + protected static $cells; + //表头数据 + protected static $data = []; + //文件名 + protected static $title = '订单导出'; + //行宽 + protected static $width = 20; + //行高 + protected static $height = 50; + //保存文件目录 + protected static $path = './phpExcel/'; + //设置style + private static $styleArray = [ +// 'borders' => [ +// 'allBorders' => [ +// // PHPExcel_Style_Border里面有很多属性,想要其他的自己去看 +// // 'style' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK,//边框是粗的 +// // 'style' => \PHPExcel_Style_Border::BORDER_DOUBLE,//双重的 +// // 'style' => \PHPExcel_Style_Border::BORDER_HAIR,//虚线 +// // 'style' => \PHPExcel_Style_Border::BORDER_MEDIUM,//实粗线 +// // 'style' => \PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT,//虚粗线 +// // 'style' => \PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT,//点虚粗线 +// 'style' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,//细边框 +// // 'color' => ['argb' => 'FFFF0000'], +// ], +// ], + 'font' => [ + 'bold' => true + ], + 'alignment' => [ + 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, + 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER + ] + ]; + + private function __construct() + { + } + + private function __clone() + { + } + + public static function instance() + { + if (self::$instance === null) { + self::$instance = new self(); + self::$spreadsheet = $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); + self::$sheet = $spreadsheet->getActiveSheet(); + } + return self::$instance; + } + + /** + *设置字体格式 + * @param $title string 必选 + * return string + */ + public static function setUtf8($title) + { + return iconv('utf-8', 'gb2312', $title); + } + + /** + * 创建保存excel目录 + * return string + */ + public static function savePath() + { + if (!is_dir(self::$path)) { + if (mkdir(self::$path, 0700) == false) { + return false; + } + } + //年月一级目录 + $mont_path = self::$path . date('Ym'); + if (!is_dir($mont_path)) { + if (mkdir($mont_path, 0700) == false) { + return false; + } + } + //日二级目录 + $day_path = $mont_path . '/' . date('d'); + if (!is_dir($day_path)) { + if (mkdir($day_path, 0700) == false) { + return false; + } + } + return $day_path; + } + + /** + * 设置标题 + * @param $title string || array ['title'=>'','name'=>'','info'=>[]] + * @param $Name string + * @param $info string || array; + * @param $funName function($style,$A,$A2) 自定义设置头部样式 + * @return $this + */ + public function setExcelTile($title = '', $Name = '', $info = [], $funName = null) + { + //设置参数 + if (is_array($title)) { + if (isset($title['title'])) $title = $title['title']; + if (isset($title['name'])) $Name = $title['name']; + if (isset($title['info'])) $info = $title['info']; + } + if (empty($title)) + $title = self::$title; + else + self::$title = $title; + + if (empty($Name)) $Name = time(); + //设置Excel属性 + self::$spreadsheet->getProperties() + ->setCreator("Neo") + ->setLastModifiedBy("Neo") + ->setTitle(self::setUtf8($title)) + ->setSubject($Name) + ->setDescription("") + ->setKeywords($Name) + ->setCategory(""); + self::$sheet->setTitle($Name); + self::$sheet->setCellValue('A1', $title); + self::$sheet->setCellValue('A2', self::setCellInfo($info)); + //文字居中 + self::$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER); + self::$sheet->getStyle('A2')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER); + + //合并表头单元格 + self::$sheet->mergeCells('A1:' . self::$cells . '1'); + self::$sheet->mergeCells('A2:' . self::$cells . '2'); + + self::$sheet->getRowDimension(1)->setRowHeight(40); + self::$sheet->getRowDimension(2)->setRowHeight(20); + + //设置表头字体 + self::$sheet->getStyle('A1')->getFont()->setName('黑体'); + self::$sheet->getStyle('A1')->getFont()->setSize(20); + self::$sheet->getStyle('A1')->getFont()->setBold(true); + self::$sheet->getStyle('A2')->getFont()->setName('宋体'); + self::$sheet->getStyle('A2')->getFont()->setSize(14); + self::$sheet->getStyle('A2')->getFont()->setBold(true); + + self::$sheet->getStyle('A3:' . self::$cells . '3')->getFont()->setBold(true); + return $this; + } + + /** + * 设置第二行标题内容 + * @param $info array (['name'=>'','site'=>'','phone'=>123] || ['我是表名','我是地址','我是手机号码'] ) || string 自定义 + * @return string + */ + private static function setCellInfo($info) + { + $content = ['操作者:', '导出日期:' . date('Y-m-d', time()), '地址:', '电话:']; + if (is_array($info) && !empty($info)) { + if (isset($info['name'])) { + $content[0] .= $info['name']; + } else { + $content[0] .= $info[0] ?? ''; + } + if (isset($info['site'])) { + $content[2] .= $info['site']; + } else { + $content[2] .= $info[1] ?? ''; + } + if (isset($info['phone'])) { + $content[3] .= $info['phone']; + } else { + $content[3] .= $info[2] ?? ''; + } + return implode(' ', $content); + } else if (is_string($info)) { + return empty($info) ? implode(' ', $content) : $info; + } + } + + /** + * 设置头部信息 + * @param $data array + * @return $this + */ + public static function setExcelHeader($data) + { + $span = 'A'; + foreach ($data as $key => $value) { + self::$sheet->getColumnDimension($span)->setWidth(self::$width); + self::$sheet->setCellValue($span . self::$topNumber, $value); + $span++; + } + self::$sheet->getRowDimension(3)->setRowHeight(self::$height); + self::$cells = $span; + return new self; + } + + /** + * + * execl数据导出 + * @param $data 需要导出的数据 格式和以前的可是一样 + * + * 特殊处理:合并单元格需要先对数据进行处理 + */ + public function setExcelContent($data = []) + { + if (!empty($data) && is_array($data)) { + $span = ''; + $column = self::$topNumber + 1; + // 行写入 + foreach ($data as $key => $rows) { + $span = 'A'; + // 列写入 + foreach ($rows as $keyName => $value) { + self::$sheet->setCellValue($span . $column, $value); + $span++; + } + $column++; + } + self::$sheet->getDefaultRowDimension()->setRowHeight(self::$height); + //设置内容字体样式 + self::$sheet->getStyle('A1:' . $span . $column)->applyFromArray(self::$styleArray); + //设置边框 + self::$sheet->getStyle('A1:' . $span . $column)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); + //设置自动换行 + self::$sheet->getStyle('A4:' . $span . $column)->getAlignment()->setWrapText(true); + } + return new self; + } + + /** + * 保存表格数据,直接下载 + * @param $filename 文件名称 + * @param $suffix 文件后缀名 + * @param $is_save 是否保存文件 + * @return 保存文件:return string + */ + public function excelSave($fileName = '', $suffix = 'xlsx', $is_save = false) + { + if (empty($fileName)) { + $fileName = date('YmdHis') . time(); + } + if (empty($suffix)) { + $suffix = 'xlsx'; + } + // 重命名表(UTF8编码不需要这一步) + if (mb_detect_encoding($fileName) != "UTF-8") { + $fileName = iconv("utf-8", "gbk//IGNORE", $fileName); + } + if ($suffix == 'xlsx') { + header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); + $class = "\PhpOffice\PhpSpreadsheet\Writer\Xlsx"; + } elseif ($suffix == 'xls') { + header('Content-Type:application/vnd.ms-excel'); + $class = "\PhpOffice\PhpSpreadsheet\Writer\Xls"; + } + // 清理缓存 +// ob_end_clean(); + $spreadsheet = self::$spreadsheet; + $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet); + if (!$is_save) {//直接下载 + + header('Content-Disposition: attachment;filename="' . $fileName . '.' . $suffix . '"'); + header('Cache-Control: max-age=0'); + $writer->save('php://output'); + // 删除清空 释放内存 + $spreadsheet->disconnectWorksheets(); + unset($spreadsheet); + exit; + } else {//保存文件 + $path = self::savePath() . '/' . $fileName . '.' . $suffix; + //$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx'); + //$writer->save($path); + $writer->save(public_path() . $path); + // 删除清空 释放内存 + $spreadsheet->disconnectWorksheets(); + unset($spreadsheet); + return $path; + } + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/SystemConfigService.php b/demo/thinkphp/backend/phoenix/services/SystemConfigService.php new file mode 100644 index 0000000000000000000000000000000000000000..d3b776860cf9f8f574d074659254ff6298dd4fb8 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/SystemConfigService.php @@ -0,0 +1,75 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\services; + +use app\services\system\config\SystemConfigServices; +use phoenix\utils\Arr; + +/** 获取系统配置服务类 + * Class SystemConfigService + * @package service + */ +class SystemConfigService +{ + const CACHE_SYSTEM = 'system_config'; + + /** + * 获取单个配置效率更高 + * @param string $key + * @param $default + * @param bool $isCaChe 是否获取缓存配置 + * @return bool|mixed|string + */ + public static function get(string $key, $default = '', bool $isCaChe = false) + { + /** @var SystemConfigServices $service */ + $service = app()->make(SystemConfigServices::class); + + $callable = function () use ($service, $key) { + return $service->getConfigValue($key); + }; + + try { + if ($isCaChe) { + return $callable(); + } + return $service->cacheDriver()->remember(self::CACHE_SYSTEM . ':' . $key, $callable); + } catch (\Throwable $e) { + return $default; + } + } + + /** + * 获取多个配置 + * @param array $keys 示例 [['appid','1'],'appkey'] + * @param bool $isCaChe 是否获取缓存配置 + * @return array + */ + public static function more(array $keys, bool $isCaChe = false) + { + /** @var SystemConfigServices $service */ + $service = app()->make(SystemConfigServices::class); + + $callable = function () use ($service, $keys) { + return Arr::getDefaultValue($keys, $service->getConfigAll($keys)); + }; + try { + if ($isCaChe) + return $callable(); + + return $service->cacheDriver()->remember(self::CACHE_SYSTEM . ':' . md5(implode(',', $keys)), $callable); + } catch (\Throwable $e) { + return Arr::getDefaultValue($keys); + } + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/UpgradeService.php b/demo/thinkphp/backend/phoenix/services/UpgradeService.php new file mode 100644 index 0000000000000000000000000000000000000000..4cb0a15f5fa38c0cde5fab6ca16afd7e6160aaac --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/UpgradeService.php @@ -0,0 +1,205 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services; + +class UpgradeService extends FileService +{ + //请求域名 + public static $domain = 'http://shop.crmeb.net/'; + //及时更新网址信息 + public static $updatewebinfourl = 'index.php/admin/server.upgrade_api/updatewebinfo.html'; + //公共接口地址 获取版本号 + public static $isNowVersionUrl = 'index.php/admin/server.upgrade_api/now_version.html'; + //公共接口地址 获取版本详情 + public static $isVersionInfo = 'index.php/admin/server.upgrade_api/version_info.html'; + //公共接口地址 获取历史版本列表 + public static $isList = 'index.php/admin/server.upgrade_api/get_version_list.html'; + //公共接口地址 写入更新版本信息 + public static $isInsertLog = 'index.php/admin/server.upgrade_api/set_upgrade_info.html'; + //公共接口地址 获取大于当前版本的所有版本 + public static $isNowVersion = 'index.php/admin/server.upgrade_api/get_now_version.html'; + //公共接口地址 更新网址信息 + protected static $UpdateWeBinfo = 'index.php/admin/server.upgrade_api/updatewebinfo.html'; + //公共接口地址 获取多少版本未更新 + public static $NewVersionCount = 'index.php/admin/server.upgrade_api/new_version_count.html'; + //公共接口地址 判断是否有权限 返回1有权限,0无权限 + protected static $Isauth = 'index.php/admin/server.upgrade_api/isauth.html'; + //相隔付 + private static $seperater = "{&&}"; + + //更新网址信息 + public function snyweninfo($serverweb) + { + return self::request_post(self::$UpdateWeBinfo, $serverweb); + } + + //判断是否有权限 返回1有权限,0无权限 + public function isauth() + { + return self::request_post(self::$Isauth); + } + + /* + *获取ip token 生成当前时间和过期时间 + * @param string ip + * @param int $valid_peroid 过期周期 15天 + */ + public static function get_token($ip = '', $valid_peroid = 1296000) + { + $request = app('request'); + if (empty($ip)) $ip = $request->ip(); + $to_ken = $request->domain() . self::$seperater . $ip . self::$seperater . time() . self::$seperater . (time() + $valid_peroid) . self::$seperater; + $token = self::enCode($to_ken); + return $token; + } + + private static function getRet($msg, $code = 400) + { + return ['msg' => $msg, 'code' => $code]; + } + + /** + * + * @param string $url + * @param array $post_data + */ + public static function start() + { + $pach = app()->getRootPath() . 'version'; + $request = app('request'); + if (!file_exists($pach)) return self::getRet($pach . '升级文件丢失,请联系管理员'); + $version = @file($pach); + if (!isset($version[0])) return self::getRet('获取失败'); + $lv = self::request_post(self::$isNowVersionUrl, ['token' => self::get_token($request->ip())]); + if (isset($lv['code']) && $lv['code'] == 200) + $version_lv = isset($lv['data']['version']) && $lv['data']['version'] ? $lv['data']['version'] : false; + else + return isset($lv['msg']) ? self::getRet($lv['msg']) : self::getRet('获取失败'); + if ($version_lv === false) return self::getRet('获取失败'); + if (strstr($version[0], '=') !== false) { + $version = explode('=', $version[0]); + if ($version[1] != $version_lv) { + return self::getRet($version_lv, 200); + } + } + return self::getRet('获取失败'); + } + + public static function getVersion() + { + $pach = app()->getRootPath() . '.version'; + if (!file_exists($pach)) return self::getRet($pach . '升级文件丢失,请联系管理员'); + $version = @file($pach); + if (!isset($version[0]) && !isset($version[1])) return self::getRet('获取失败'); + $arr = []; + foreach ($version as $val) { + list($k, $v) = explode('=', $val); + $arr[$k] = $v; + } + return self::getRet($arr, 200); + } + + /** + * 模拟post进行url请求 + * @param string $url + * @param array $post_data + */ + public static function request_post($url = '', $post_data = array()) + { + if (strstr($url, 'http') === false) $url = self::$domain . $url; + if (empty($url)) { + return false; + } + if (!isset($post_data['token'])) $post_data['token'] = self::get_token(); + $o = ""; + foreach ($post_data as $k => $v) { + $o .= "$k=" . urlencode($v) . "&"; + } + $post_data = substr($o, 0, -1); + $postUrl = $url; + $curlPost = $post_data; + $ch = curl_init();//初始化curl + curl_setopt($ch, CURLOPT_URL, $postUrl);//抓取指定网页 + curl_setopt($ch, CURLOPT_HEADER, 0);//设置header + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上 + curl_setopt($ch, CURLOPT_POST, 1);//post提交方式 + curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost); + curl_setopt($ch, CURLOPT_TIMEOUT, 20); + $data = curl_exec($ch);//运行curl + curl_close($ch); + if ($data) { + $data = json_decode($data, true); + } + return $data; + } + + /** + * 验证远程文件是否存在 以及下载 + * @param string $url 文件路径 + * @param string $savefile 保存地址 + */ + public static function check_remote_file_exists($url, $savefile) + { + $url = self::$domain . 'public' . DS . 'uploads' . DS . 'upgrade' . DS . $url; + $url = str_replace('\\', '/', $url); + $curl = curl_init($url); + curl_setopt($curl, CURLOPT_NOBODY, true); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET'); + // 发送请求 + $result = curl_exec($curl); + $found = false; + // 如果请求没有发送失败 + if ($result !== false) { + // 再检查http响应码是否为200 + $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + if ($statusCode == 200) { + curl_close($curl); + + $fileservice = new self; + //下载文件 + $zip = $fileservice->downRemoteFile($url, $savefile); + if ($zip['error'] > 0) return false; + if (!isset($zip['save_path']) && empty($zip['save_path'])) return false; + if (!file_exists($zip['save_path'])) return false; + return $zip['save_path']; + } + } + curl_close($curl); + return $found; + } + + /** + * 通用加密 + * @param String $string 需要加密的字串 + * @param String $skey 加密EKY + * @return String + */ + private static function enCode($string = '', $skey = 'fb') + { + $skey = array_reverse(str_split($skey)); + $strArr = str_split(base64_encode($string)); + $strCount = count($strArr); + foreach ($skey as $key => $value) { + $key < $strCount && $strArr[$key] .= $value; + } + return str_replace('=', 'O0O0O', join('', $strArr)); + } + + /** + * 去除回车,去取空格,去除换行,去除tab + * @param String $str 需要去除的字串 + * @return String + */ + public static function replace($str) + { + return trim(str_replace(array("\r", "\n", "\t"), '', $str)); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/app/MiniProgramService.php b/demo/thinkphp/backend/phoenix/services/app/MiniProgramService.php new file mode 100644 index 0000000000000000000000000000000000000000..0698d830073e9f803b52b004d8b34be146ec46d2 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/app/MiniProgramService.php @@ -0,0 +1,898 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\app; + +use app\services\order\StoreOrderTakeServices; +use crmeb\exceptions\AdminException; +use crmeb\services\easywechat\orderShipping\MiniOrderService; +use crmeb\services\SystemConfigService; +use app\services\pay\PayNotifyServices; +use crmeb\services\easywechat\Application; +use EasyWeChat\Payment\Order; +use think\facade\Log; +use crmeb\utils\Hook; +use think\facade\Cache; +use think\Response; + +/** + * 微信小程序接口 + * Class WechatMinService + * @package service + */ +class MiniProgramService +{ + const MSG_CODE = [ + '1' => '未创建直播间', + '1003' => '商品id不存在', + '47001' => '入参格式不符合规范', + '200002' => '入参错误', + '300001' => '禁止创建/更新商品 或 禁止编辑&更新房间', + '300002' => '名称长度不符合规则', + '300006' => '图片上传失败', + '300022' => '此房间号不存在', + '300023' => '房间状态 拦截', + '300024' => '商品不存在', + '300025' => '商品审核未通过', + '300026' => '房间商品数量已经满额', + '300027' => '导入商品失败', + '300028' => '房间名称违规', + '300029' => '主播昵称违规', + '300030' => '主播微信号不合法', + '300031' => '直播间封面图不合规', + '300032' => '直播间分享图违规', + '300033' => '添加商品超过直播间上限', + '300034' => '主播微信昵称长度不符合要求', + '300035' => '主播微信号不存在', + '300036' => '主播微信号未实名认证', + '300037' => '购物直播频道封面图不合规', + '300038' => '未在小程序管理后台配置客服', + '9410000' => '直播间列表为空', + '9410001' => '获取房间失败', + '9410002' => '获取商品失败', + '9410003' => '获取回放失败', + '300003' => '价格输入不合规', + '300004' => '商品名称存在违规违法内容', + '300005' => '商品图片存在违规违法内容', + '300007' => '线上小程序版本不存在该链接', + '300008' => '添加商品失败', + '300009' => '商品审核撤回失败', + '300010' => '商品审核状态不对', + '300011' => '操作非法', + '300012' => '没有提审额度', + '300013' => '提审失败', + '300014' => '审核中,无法删除', + '300017' => '商品未提审', + '300018' => '图片尺寸不符合要求', + '300021' => '商品添加成功,审核失败', + '40001' => 'AppSecret错误或者AppSecret不属于这个小程序,请确认AppSecret 的正确性', + '40002' => '请确保grant_type字段值为client_credential', + '40013' => '不合法的AppID,请检查AppID的正确性,避免异常字符,注意大小写', + '40125' => '小程序配置无效,请检查配置', + '41002' => '缺少appid参数', + '41004' => '缺少secret参数', + '43104' => 'appid与openid不匹配', + '48001' => '微信接口暂无权限,请先去获取', + '-1' => '系统错误', + ]; + /** + * @var Application + */ + protected static $instance; + + /** + * @return array + */ + public static function options() + { + $wechat = SystemConfigService::more(['wechat_app_appsecret', 'wechat_app_appid', 'site_url', 'routine_appId', 'routine_appsecret', 'wechat_token', 'wechat_encodingaeskey']); + $payment = SystemConfigService::more(['pay_weixin_mchid', 'pay_weixin_key', 'pay_weixin_client_cert', 'pay_weixin_client_key', 'pay_weixin_open', 'pay_new_weixin_open', 'pay_new_weixin_mchid']); + $config = []; + if (request()->isApp()) { + $appId = isset($wechat['wechat_app_appid']) ? trim($wechat['wechat_app_appid']) : ''; + $appsecret = isset($wechat['wechat_app_appsecret']) ? trim($wechat['wechat_app_appsecret']) : ''; + } else { + $appId = isset($wechat['routine_appId']) ? trim($wechat['routine_appId']) : ''; + $appsecret = isset($wechat['routine_appsecret']) ? trim($wechat['routine_appsecret']) : ''; + } + $config = [ + 'token' => isset($wechat['wechat_token']) ? trim($wechat['wechat_token']) : '', + 'aes_key' => isset($wechat['wechat_encodingaeskey']) ? trim($wechat['wechat_encodingaeskey']) : '', + ]; + $config['mini_program'] = [ + 'app_id' => $appId, + 'secret' => $appsecret, + 'token' => isset($wechat['wechat_token']) ? trim($wechat['wechat_token']) : '', + 'aes_key' => isset($wechat['wechat_encodingaeskey']) ? trim($wechat['wechat_encodingaeskey']) : '' + ]; + $config['payment'] = [ + 'app_id' => $appId, + 'merchant_id' => empty($payment['pay_new_weixin_open']) ? trim($payment['pay_weixin_mchid']) : trim($payment['pay_new_weixin_mchid']), + 'key' => trim($payment['pay_weixin_key']), + 'cert_path' => substr(public_path(parse_url($payment['pay_weixin_client_cert'])['path']), 0, strlen(public_path(parse_url($payment['pay_weixin_client_cert'])['path'])) - 1), + 'key_path' => substr(public_path(parse_url($payment['pay_weixin_client_key'])['path']), 0, strlen(public_path(parse_url($payment['pay_weixin_client_key'])['path'])) - 1), + 'notify_url' => trim($wechat['site_url']) . '/api/pay/notify/routine' + ]; + return $config; + } + + /** + * 初始化 + * @param bool $cache + * @return Application + */ + public static function application($cache = false) + { + (self::$instance === null || $cache === true) && (self::$instance = new Application(self::options())); + return self::$instance; + } + + /** + * 小程序接口 + * @return \EasyWeChat\MiniProgram\MiniProgram + */ + public static function miniprogram() + { + return self::application()->mini_program; + } + + /** + * 获得用户信息 根据code 获取session_key + * @param array|string $openid + * @return $userInfo + */ + public static function getUserInfo($code) + { + try { + return self::miniprogram()->sns->getSessionKey($code); + } catch (\Throwable $e) { + throw new AdminException($e->getMessage()); + } + } + + /** + * 加密数据解密 + * @param $sessionKey + * @param $iv + * @param $encryptData + * @return $userInfo + */ + public static function encryptor($sessionKey, $iv, $encryptData) + { + return self::miniprogram()->encryptor->decryptData($sessionKey, $iv, $encryptData); + } + + /** + * 上传临时素材接口 + * @return \EasyWeChat\Material\Temporary + */ + public static function materialTemporaryService() + { + return self::miniprogram()->material_temporary; + } + + /** + * 客服消息接口 + * @param null $to + * @param null $message + */ + public static function staffService() + { + return self::miniprogram()->staff; + } + + /** + * 微信小程序二维码生成接口 + * @return \EasyWeChat\QRCode\QRCode + */ + public static function qrcodeService() + { + return self::miniprogram()->qrcode; + } + + /**微信小程序二维码生成接口不限量永久 + * @param $scene + * @param null $page + * @param null $width + * @param null $autoColor + * @param array $lineColor + * @return \Psr\Http\Message\StreamInterface + */ + public static function appCodeUnlimitService($scene, $page = null, $width = 430, $autoColor = false, $lineColor = ['r' => 0, 'g' => 0, 'b' => 0]) + { + return self::qrcodeService()->appCodeUnlimit($scene, $page, $width, $autoColor, $lineColor); + } + + + /** + * 模板消息接口 + * @return \EasyWeChat\Notice\Notice + */ + public static function noticeService() + { + return self::miniprogram()->notice; + } + + /** + * 订阅模板消息接口 + * @return \crmeb\services\subscribe\ProgramSubscribe + */ + public static function SubscribenoticeService() + { + return self::miniprogram()->now_notice; + } + + /** + * 发送订阅消息 + * @param string $touser 接收者(用户)的 openid + * @param string $templateId 所需下发的订阅模板id + * @param array $data 模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } } + * @param string $link 击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + * @throws \EasyWeChat\Core\Exceptions\InvalidArgumentException + */ + public static function sendSubscribeTemlate(string $touser, string $templateId, array $data, string $link = '') + { + return self::SubscribenoticeService()->to($touser)->template($templateId)->andData($data)->withUrl($link)->send(); + } + + /** + * 添加订阅消息模版 + * @param string $tid + * @param array $kidList + * @param string $sceneDesc + * @return mixed + */ + public static function addSubscribeTemplate(string $tid, array $kidList, string $sceneDesc = '') + { + try { + $res = self::SubscribenoticeService()->addTemplate($tid, $kidList, $sceneDesc); + if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['priTmplId'])) { + return $res['priTmplId']; + } else { + Log::error('添加订阅消息模版失败:' . $res['errmsg']); + } + } catch (\Throwable $e) { + Log::error('添加订阅消息模版失败:' . $e->getMessage()); + } + return true; + } + + /** + * 删除订阅消息模版 + * @param string $tid + * @param array $kidList + * @param string $sceneDesc + * @return mixed + */ + public static function delSubscribeTemplate(string $priTmplId) + { + try { + $res = self::SubscribenoticeService()->delTemplate($priTmplId); + if (isset($res['errcode']) && $res['errcode'] == 0) { + return true; + } else { + Log::error('删除订阅消息模版失败:' . $res['errmsg']); + } + } catch (\Throwable $e) { + Log::error('删除订阅消息模版失败:' . $e->getMessage()); + } + return true; + } + + + /** + * 获取模版标题的关键词列表 + * @param string $tid + * @return mixed + */ + public static function getSubscribeTemplateKeyWords(string $tid) + { + try { + $res = self::SubscribenoticeService()->getPublicTemplateKeywords($tid); + if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['data'])) { + return $res['data']; + } else { + throw new AdminException($res['errmsg']); + } + } catch (\Throwable $e) { + throw new AdminException($e); + } + } + + /** + * 获取订阅消息列表 + * @return mixed + */ + public static function getSubscribeTemplateList() + { + try { + return self::SubscribenoticeService()->getTemplateList(); + } catch (\Exception $e) { + throw new AdminException($e->getMessage()); + } + } + + /** + * 支付 + * @return \EasyWeChat\Payment\Payment + */ + public static function paymentService() + { + return self::application()->payment; + } + + /** + * 生成支付订单对象 + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return Order + */ + protected static function paymentOrder($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = 'JSAPI', $options = []) + { + $total_fee = bcmul($total_fee, 100, 0); + $order = array_merge(compact('openid', 'out_trade_no', 'total_fee', 'attach', 'body', 'detail', 'trade_type'), $options); + if ($order['detail'] == '') unset($order['detail']); + return new Order($order); + } + + /** + * 获得下单ID + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return mixed + */ + public static function paymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = 'JSAPI', $options = []) + { + $key = 'pay_' . $out_trade_no; + $result = Cache::get($key); + if ($result) { + return $result; + } else { + $order = self::paymentOrder($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $trade_type, $options); + $result = self::paymentService()->prepare($order); + if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS') { + Cache::set($key, $result->prepay_id, 7000); + return $result->prepay_id; + } else { + if ($result->return_code == 'FAIL') { + exception('微信支付错误返回:' . $result->return_msg); + } else if (isset($result->err_code)) { + exception('微信支付错误返回:' . $result->err_code_des); + } else { + exception('没有获取微信支付的预支付ID,请重新发起支付!'); + } + exit; + } + } + } + + /** + * 获得下单ID + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return mixed + */ + public static function newPaymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $options = []) + { + $key = 'pay_' . $out_trade_no; + $result = Cache::get($key); + if ($result) { + return $result; + } else { + $order = self::paymentOrder($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $options); + $result = self::application()->minipay->createorder($order); + if ($result->errcode === 0) { + Cache::set($key, $result->payment_params, 7000); + return $result->payment_params; + } else { + exception('微信支付错误返回:' . '[' . $result->errcode . ']' . $result->errmsg); + exit; + } + } + } + + + /** + * 获得jsSdk支付参数 + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return array|string + */ + public static function jsPay($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = 'JSAPI', $options = []) + { + return self::paymentService()->configForJSSDKPayment(self::paymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $trade_type, $options)); + } + + /** + * 获得jsSdk支付参数 + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return array|string + */ + public static function newJsPay($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $options = []) + { + $config = self::newPaymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $options); + $config['timestamp'] = $config['timeStamp']; + unset($config['timeStamp']); + return $config; + + } + + /** + * 获得App支付参数 + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return array|string + */ + public static function appPay($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = Order::APP, $options = []) + { + return self::paymentService()->configForAppPayment(self::paymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $trade_type, $options)); + } + + /** + * 使用商户订单号退款 + * @param $orderNo + * @param $refundNo + * @param $totalFee + * @param null $refundFee + * @param null $opUserId + * @param string $refundReason + * @param string $type + * @param string $refundAccount + */ + public static function refund($orderNo, $refundNo, $totalFee, $refundFee = null, $opUserId = null, $refundReason = '', $type = 'out_trade_no', $refundAccount = 'REFUND_SOURCE_UNSETTLED_FUNDS') + { + $totalFee = floatval($totalFee); + $refundFee = floatval($refundFee); + if ($type == 'out_trade_no') { + return self::paymentService()->refund($orderNo, $refundNo, $totalFee, $refundFee, $opUserId, $type, $refundAccount, $refundReason); + } else { + return self::paymentService()->refundByTransactionId($orderNo, $refundNo, $totalFee, $refundFee, $opUserId, $refundAccount, $refundReason); + } + } + + /** + * 使用商户订单号退款 + * @param $orderNo + * @param $refundNo + * @param $totalFee + * @param null $refundFee + * @param null $opUserId + * @param string $refundReason + * @param string $type + * @param string $refundAccount + */ + public static function miniRefund($orderNo, $totalFee, $refundFee = null, $opt) + { + $totalFee = floatval($totalFee); + $refundFee = floatval($refundFee); + + $order = [ + 'openid' => $opt['open_id'], + 'trade_no' => $opt['order_id'], + 'transaction_id' => $opt['trade_no'], + 'refund_no' => $opt['refund_no'], + 'total_amount' => $totalFee, + 'refund_amount' => $refundFee, + ]; + return self::application()->minipay->refundorder($order); + } + + /** 根据订单号退款 + * @param $orderNo + * @param array $opt + * @return bool + */ + public static function payOrderRefund($orderNo, array $opt) + { + if (!isset($opt['pay_price'])) throw new AdminException(400730); + if (sys_config('pay_weixin_client_key') == '' || sys_config('pay_weixin_client_cert') == '') throw new AdminException(400739); + $totalFee = floatval(bcmul($opt['pay_price'], 100, 0)); + $refundFee = isset($opt['refund_price']) ? floatval(bcmul($opt['refund_price'], 100, 0)) : null; + $refundReason = $opt['desc'] ?? ''; + $refundNo = $opt['refund_id'] ?? $orderNo; + $opUserId = $opt['op_user_id'] ?? null; + $type = $opt['type'] ?? 'out_trade_no'; + /*仅针对老资金流商户使用 + REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款(默认使用未结算资金退款) + REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款*/ + $refundAccount = $opt['refund_account'] ?? 'REFUND_SOURCE_UNSETTLED_FUNDS'; + try { + $res = (self::refund($orderNo, $refundNo, $totalFee, $refundFee, $opUserId, $refundReason, $type, $refundAccount)); + if ($res->return_code == 'FAIL') throw new AdminException(400731, ['msg' => $res->return_msg]); + if (isset($res->err_code)) throw new AdminException(400731, ['msg' => $res->err_code_des]); + } catch (\Exception $e) { + throw new AdminException($e->getMessage()); + } + return true; + } + + /** + * 微信支付成功回调接口 + * @return \Symfony\Component\HttpFoundation\Response + * @throws \EasyWeChat\Core\Exceptions\FaultException + */ + public static function handleNotify() + { + return self::paymentService()->handleNotify(function ($notify, $successful) { + if ($successful && isset($notify->out_trade_no)) { + if (isset($notify->attach) && $notify->attach) { + if (($count = strpos($notify->out_trade_no, '_')) !== false) { + $notify->out_trade_no = substr($notify->out_trade_no, $count + 1); + } + (new Hook(PayNotifyServices::class, 'wechat'))->listen($notify->attach, $notify->out_trade_no, $notify->transaction_id); + } + return false; + } + }); + } + + /** + * 作为客服消息发送 + * @param $to + * @param $message + * @return bool + */ + public static function staffTo($to, $message) + { + $staff = self::staffService(); + $staff = is_callable($message) ? $staff->message($message()) : $staff->message($message); + $res = $staff->to($to)->send(); + return $res; + } + + + /** + * 获取直播列表 + * @param int $page + * @param int $limit + * @return array + */ + public static function getLiveInfo(int $page = 1, int $limit = 10) + { + try { + $res = self::miniprogram()->wechat_live->getLiveInfo($page, $limit); + if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['room_info']) && $res['room_info']) { + return $res['room_info']; + } else { + return []; + } + } catch (\Throwable $e) { + return []; + } + } + + /** + * 获取直播回放 + * @param int $room_id + * @param int $page + * @param int $limit + * @return mixed + */ + public static function getLivePlayback(int $room_id, int $page = 1, int $limit = 10) + { + try { + $res = self::miniprogram()->wechat_live->getLivePlayback($room_id, $page, $limit); + if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['live_replay'])) { + return $res['live_replay']; + } else { + throw new AdminException($res['errmsg']); + } + } catch (\Throwable $e) { + throw new AdminException(self::getValidMessgae($e)); + } + } + + /** + * 创建直播间 + * @param array $data + * @return mixed + */ + public static function createLiveRoom(array $data) + { + try { + $res = self::miniprogram()->wechat_live->createRoom($data); + if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['roomId'])) { + unset($res['errcode']); + return $res; + } else { + throw new AdminException($res['errmsg']); + } + } catch (\Throwable $e) { + throw new AdminException(self::getValidMessgae($e)); + } + } + + /** + * 直播间添加商品 + * @param int $roomId + * @param $ids + * @return bool + */ + public static function roomAddGoods(int $roomId, $ids) + { + try { + $res = self::miniprogram()->wechat_live->roomAddGoods($roomId, $ids); + if (isset($res['errcode']) && $res['errcode'] == 0) { + return true; + } else { + throw new AdminException($res['errmsg']); + } + } catch (\Throwable $e) { + throw new AdminException(self::getValidMessgae($e)); + } + } + + /** + * 获取商品列表 + * @param int $status + * @param int $page + * @param int $limit + * @return mixed + */ + public static function getGoodsList(int $status = 2, int $page = 1, int $limit = 10) + { + try { + $res = self::miniprogram()->wechat_live->getGoodsList($status, $page, $limit); + if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['goods'])) { + return $res['goods']; + } else { + throw new AdminException($res['errmsg']); + } + } catch (\Throwable $e) { + throw new AdminException(self::getValidMessgae($e)); + } + } + + /** + * 获取商品详情 + * @param $goods_ids + * @return mixed + */ + public static function getGooodsInfo($goods_ids) + { + try { + $res = self::miniprogram()->wechat_live->getGooodsInfo($goods_ids); + if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['goods'])) { + return $res['goods']; + } else { + throw new AdminException($res['errmsg']); + } + } catch (\Throwable $e) { + throw new AdminException(self::getValidMessgae($e)); + } + } + + /** + * 添加商品 + * @param string $coverImgUrl + * @param string $name + * @param int $priceType + * @param string $url + * @param $price + * @param string $price2 + * @return mixed + */ + public static function addGoods(string $coverImgUrl, string $name, int $priceType, string $url, $price, $price2 = '') + { + try { + $res = self::miniprogram()->wechat_live->addGoods($coverImgUrl, $name, $priceType, $url, $price, $price2); + if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['goodsId'])) { + unset($res['errcode']); + return $res; + } else { + throw new AdminException($res['errmsg']); + } + } catch (\Throwable $e) { + throw new AdminException(self::getValidMessgae($e)); + } + } + + /** + * 商品撤回审核 + * @param int $goodsId + * @param $auditId + * @return bool + */ + public static function resetauditGoods(int $goodsId, $auditId) + { + try { + $res = self::miniprogram()->wechat_live->resetauditGoods($goodsId, $auditId); + if (isset($res['errcode']) && $res['errcode'] == 0) { + return true; + } else { + throw new AdminException($res['errmsg']); + } + } catch (\Throwable $e) { + throw new AdminException(self::getValidMessgae($e)); + } + } + + /** + * 商品重新提交审核 + * @param int $goodsId + * @return mixed + */ + public static function auditGoods(int $goodsId) + { + try { + $res = self::miniprogram()->wechat_live->auditGoods($goodsId); + if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['auditId'])) { + return $res['auditId']; + } else { + throw new AdminException($res['errmsg']); + } + } catch (\Throwable $e) { + throw new AdminException(self::getValidMessgae($e)); + } + } + + /** + * 删除商品 + * @param int $goodsId + * @return bool + */ + public static function deleteGoods(int $goodsId) + { + try { + $res = self::miniprogram()->wechat_live->deleteGoods($goodsId); + if (isset($res['errcode']) && $res['errcode'] == 0) { + return true; + } else { + throw new AdminException($res['errmsg']); + } + } catch (\Throwable $e) { + throw new AdminException(self::getValidMessgae($e)); + } + } + + /** + * 更新商品 + * @param int $goodsId + * @param string $coverImgUrl + * @param string $name + * @param int $priceType + * @param string $url + * @param $price + * @param string $price2 + * @return bool + */ + public static function updateGoods(int $goodsId, string $coverImgUrl, string $name, int $priceType, string $url, $price, $price2 = '') + { + try { + $res = self::miniprogram()->wechat_live->updateGoods($goodsId, $coverImgUrl, $name, $priceType, $url, $price, $price2); + if (isset($res['errcode']) && $res['errcode'] == 0) { + return true; + } else { + throw new AdminException($res['errmsg']); + } + } catch (\Throwable $e) { + throw new AdminException(self::getValidMessgae($e)); + } + } + + /** + * 更新商品 + * @param int $goodsId + * @param string $coverImgUrl + * @param string $name + * @param int $priceType + * @param string $url + * @param $price + * @param string $price2 + * @return bool + */ + public static function getRoleList($role = 2, int $page = 0, int $limit = 30, $keyword = '') + { + try { + $res = self::miniprogram()->wechat_live->getRoleList($role, $page, $limit, $keyword); + if (isset($res['errcode']) && $res['errcode'] == 0 && isset($res['list'])) { + return $res['list']; + } else { + throw new AdminException($res['errmsg']); + } + } catch (\Throwable $e) { + throw new AdminException(self::getValidMessgae($e)); + } + } + + public static function getValidMessgae(\Throwable $e) + { + $message = ''; + if (!isset(self::MSG_CODE[$e->getCode()]) && strstr($e->getMessage(), 'Request AccessToken fail') !== false) { + $message = str_replace('Request AccessToken fail. response:', '', $e->getMessage()); + $message = json_decode($message, true) ?: []; + $errcode = $message['errcode'] ?? false; + if ($errcode) { + $message = self::MSG_CODE[$errcode] ?? $message; + } + } + return $message ?: self::MSG_CODE[$e->getCode()] ?? $e->getMessage(); + } + + + /** + * @return Response + * @throws \EasyWeChat\Server\BadRequestException + */ + public static function serve(): Response + { + $wechat = self::application(true); + $server = $wechat->server; + self::hook($server); + $response = $server->serve(); + return response($response->getContent()); + } + + private static function hook($server) + { + $server->setMessageHandler(function ($message) { + switch ($message->MsgType) { + case 'event': + switch (strtolower($message->Event)) { + case 'trade_manage_remind_access_api': // 小程序完成账期授权时 小程序产生第一笔交易时 已产生交易但从未发货的小程序,每天一次 + break; + case 'trade_manage_remind_shipping': // 曾经发过货的小程序,订单超过48小时未发货时 + break; + case 'trade_manage_order_settlement': // 订单完成发货时 订单结算时 + if (isset($message['estimated_settlement_time'])) { //订单完成发货时 + MiniOrderService::notifyConfirmByTradeNo($message['merchant_trade_no'], time()); + } + if (isset($message['confirm_receive_method'])) { // 订单结算时 + /** @var StoreOrderTakeServices $StoreOrderTakeServices */ + $storeOrderTakeServices = app()->make(StoreOrderTakeServices::class); + $storeOrderTakeServices->miniOrderTakeOrder($message['merchant_trade_no']); + } + break; + }; + break; + }; + }); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/app/WechatOpenService.php b/demo/thinkphp/backend/phoenix/services/app/WechatOpenService.php new file mode 100644 index 0000000000000000000000000000000000000000..97a3a451beac09f6809cd566509eb3e85132a2bb --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/app/WechatOpenService.php @@ -0,0 +1,65 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\app; + +use crmeb\services\easywechat\Application; + +class WechatOpenService +{ + + protected function options() + { + $options = [ + 'app_id' => sys_config('wechat_open_app_id'), + 'secret' => sys_config('wechat_open_app_secret') + ]; + return $options; + } + + /** + * @return Application + */ + protected function application() + { + return new Application($this->options()); + } + + /** + * @return mixed + */ + public function serve() + { + return $this->application()->open_platform->server->serve(); + } + + /** + * 使用授权码换取公众号的接口调用凭据和授权信息 + * @param string $code + * @return \EasyWeChat\Support\Collection + */ + public function getAuthorizationInfo() + { + return $this->application()->oauth->user(); + } + + /** + * 获取授权方的公众号帐号基本信息 + * @param string $appid + * @return \EasyWeChat\Support\Collection + */ + public function getAuthorizerInfo() + { + return $this->application()->oauth->user(); + } + + +} diff --git a/demo/thinkphp/backend/phoenix/services/app/WechatService.php b/demo/thinkphp/backend/phoenix/services/app/WechatService.php new file mode 100644 index 0000000000000000000000000000000000000000..76a24c935387e8b20bab3f049c197e312de04be9 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/app/WechatService.php @@ -0,0 +1,887 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\app; + +use app\services\message\wechat\MessageServices; +use app\services\pay\PayServices; +use app\services\wechat\WechatMessageServices; +use app\services\wechat\WechatReplyServices; +use crmeb\exceptions\AdminException; +use crmeb\exceptions\ApiException; +use crmeb\services\easywechat\Application; +use EasyWeChat\Message\Article; +use EasyWeChat\Message\Image; +use EasyWeChat\Message\Material; +use EasyWeChat\Message\News; +use EasyWeChat\Message\Text; +use EasyWeChat\Message\Video; +use EasyWeChat\Message\Voice; +use EasyWeChat\Payment\Order; +use EasyWeChat\Server\Guard; +use Symfony\Component\HttpFoundation\Request; +use think\facade\Event; +use think\facade\Log; +use think\Response; +use think\facade\Cache; +use crmeb\services\SystemConfigService; + +/** + * 微信公众号 + * Class WechatService + * @package crmeb\services\app + */ +class WechatService +{ + /** + * @var Application + */ + protected static $instance; + + /** + * @return array + */ + public static function options() + { + $wechat = SystemConfigService::more(['wechat_appid', 'wechat_app_appid', 'wechat_app_appsecret', 'wechat_appsecret', 'wechat_token', 'wechat_encodingaeskey', 'wechat_encode']); + $payment = SystemConfigService::more(['pay_weixin_mchid', 'pay_weixin_client_cert', 'pay_weixin_client_key', 'pay_weixin_key', 'pay_weixin_open']); + if (request()->isApp()) { + $appId = isset($wechat['wechat_app_appid']) ? trim($wechat['wechat_app_appid']) : ''; + $appsecret = isset($wechat['wechat_app_appsecret']) ? trim($wechat['wechat_app_appsecret']) : ''; + } else { + $appId = isset($wechat['wechat_appid']) ? trim($wechat['wechat_appid']) : ''; + $appsecret = isset($wechat['wechat_appsecret']) ? trim($wechat['wechat_appsecret']) : ''; + } + $config = [ + 'app_id' => $appId, + 'secret' => $appsecret, + 'token' => isset($wechat['wechat_token']) ? trim($wechat['wechat_token']) : '', + 'guzzle' => [ + 'timeout' => 10.0, // 超时时间(秒) + 'verify' => false + ], + ]; + if (isset($wechat['wechat_encode']) && (int)$wechat['wechat_encode'] > 0 && isset($wechat['wechat_encodingaeskey']) && !empty($wechat['wechat_encodingaeskey'])) + $config['aes_key'] = $wechat['wechat_encodingaeskey']; + if (isset($payment['pay_weixin_open'])) { + $config['payment'] = [ + 'app_id' => $appId, + 'merchant_id' => trim($payment['pay_weixin_mchid']), + 'key' => trim($payment['pay_weixin_key']), + 'cert_path' => substr(public_path(parse_url($payment['pay_weixin_client_cert'])['path']), 0, strlen(public_path(parse_url($payment['pay_weixin_client_cert'])['path'])) - 1), + 'key_path' => substr(public_path(parse_url($payment['pay_weixin_client_key'])['path']), 0, strlen(public_path(parse_url($payment['pay_weixin_client_key'])['path'])) - 1), + 'notify_url' => trim(sys_config('site_url')) . '/api/pay/notify/wechat' + ]; + } + return $config; + } + + /** + * @param bool $cache + * @return Application + */ + public static function application($cache = false) + { + (self::$instance === null || $cache === true) && (self::$instance = new Application(self::options())); + return self::$instance; + } + + /** + * @return Response + * @throws \EasyWeChat\Server\BadRequestException + */ + public static function serve(): Response + { + $wechat = self::application(true); + $server = $wechat->server; + self::hook($server); + $response = $server->serve(); + return response($response->getContent()); + } + + /** + * 监听行为(微信) + * @param Guard $server + * @throws \EasyWeChat\Core\Exceptions\InvalidArgumentException + */ + private static function hook($server) + { + /** @var MessageServices $messageService */ + $messageService = app()->make(MessageServices::class); + /** @var WechatReplyServices $wechatReplyService */ + $wechatReplyService = app()->make(WechatReplyServices::class); + $server->setMessageHandler(function ($message) use ($messageService, $wechatReplyService) { + /** @var WechatMessageServices $wechatMessage */ + $wechatMessage = app()->make(WechatMessageServices::class); + $wechatMessage->wechatMessageBefore($message); + switch ($message->MsgType) { + case 'event': + switch (strtolower($message->Event)) { + case 'subscribe': + $response = $messageService->wechatEventSubscribe($message); + break; + case 'unsubscribe': + $messageService->wechatEventUnsubscribe($message); + break; + case 'scan': + $response = $messageService->wechatEventScan($message); + break; + case 'location': + $response = $messageService->wechatEventLocation($message); + break; + case 'click': + $response = $wechatReplyService->reply($message->EventKey); + break; + case 'view': + $response = $messageService->wechatEventView($message); + break; + case 'funds_order_pay': + if (($count = strpos($message['order_info']['trade_no'], '_')) !== false) { + $trade_no = substr($message['order_info']['trade_no'], $count + 1); + } else { + $trade_no = $message['order_info']['trade_no']; + } + $prefix = substr($trade_no, 0, 2); + //处理一下参数 + switch ($prefix) { + case 'cp': + $data['attach'] = 'Product'; + break; + case 'hy': + $data['attach'] = 'Member'; + break; + case 'cz': + $data['attach'] = 'UserRecharge'; + break; + } + $data['out_trade_no'] = $message['order_info']['trade_no']; + $data['transaction_id'] = $message['order_info']['transaction_id']; + $data['opneid'] = $message['FromUserName']; + if (Event::until('NotifyListener', [$data, PayServices::WEIXIN_PAY])) { + $response = 'success'; + } else { + $response = 'faild'; + } + Log::error(['data' => $data, 'res' => $response, 'message' => $message]); + break; + } + break; + case 'text': + $response = $wechatReplyService->reply($message->Content, $message->FromUserName); + break; + case 'image': + $response = $messageService->wechatMessageImage($message); + break; + case 'voice': + $response = $messageService->wechatMessageVoice($message); + break; + case 'video': + $response = $messageService->wechatMessageVideo($message); + break; + case 'location': + $response = $messageService->wechatMessageLocation($message); + break; + case 'link': + $response = $messageService->wechatMessageLink($message); + break; + // ... 其它消息 + default: + $response = $messageService->wechatMessageOther($message); + break; + } + + return $response ?? false; + }); + } + + + /** + * 多客服消息转发 + * @param string $account + * @return \EasyWeChat\Message\Transfer + */ + public static function transfer($account = '') + { + $transfer = new \EasyWeChat\Message\Transfer(); + return empty($account) ? $transfer : $transfer->to($account); + } + + + /** + * 上传永久素材接口 + * @return \EasyWeChat\Material\Material + */ + public static function materialService() + { + return self::application()->material; + } + + /** + * 上传临时素材接口 + * @return \EasyWeChat\Material\Temporary + */ + public static function materialTemporaryService() + { + return self::application()->material_temporary; + } + + /** + * 用户接口 + * @return \EasyWeChat\User\User + */ + public static function userService() + { + return self::application()->user; + } + + + /** + * 客服消息接口 + * @param null $to + * @param null $message + */ + public static function staffService() + { + return self::application()->staff; + } + + /** + * 微信公众号菜单接口 + * @return \EasyWeChat\Menu\Menu + */ + public static function menuService() + { + return self::application()->menu; + } + + /** + * 微信二维码生成接口 + * @return \EasyWeChat\QRCode\QRCode + */ + public static function qrcodeService() + { + return self::application()->qrcode; + } + + /** + * 短链接生成接口 + * @return \EasyWeChat\Url\Url + */ + public static function urlService() + { + return self::application()->url; + } + + /** + * 用户授权 + * @return \Overtrue\Socialite\Providers\WeChatProvider + */ + public static function oauthService() + { + return self::application()->oauth; + } + + /** + * 网页授权 + * @return easywechat\oauth2\wechat\WechatOauth2Provider + */ + public static function oauth2Service() + { + $request = app()->request; + self::application()->oauth2->setRequest(new Request($request->get(), $request->post(), [], [], [], $request->server(), $request->getContent())); + return self::application()->oauth2; + } + + /** + * 模板消息接口 + * @return \EasyWeChat\Notice\Notice + */ + public static function noticeService() + { + return self::application()->notice; + } + + public static function sendTemplate($openid, $templateId, array $data, $url = null, $defaultColor = null) + { + $notice = self::noticeService()->to($openid)->template($templateId)->andData($data); + if ($url !== null) $notice->url($url); + if ($defaultColor !== null) $notice->defaultColor($defaultColor); + return $notice->send(); + } + + + /** + * 支付 + * @return \EasyWeChat\Payment\Payment + */ + public static function paymentService() + { + return self::application()->payment; + } + + public static function downloadBill($day, $type = 'ALL') + { +// $payment = self::paymentService(); +// $merchant = $payment->getMerchant(); +// $params = [ +// 'appid' => $merchant->app_id, +// 'bill_date'=>$day, +// 'bill_type'=>strtoupper($type), +// 'mch_id'=> $merchant->merchant_id, +// 'nonce_str' => uniqid() +// ]; +// $params['sign'] = \EasyWeChat\Payment\generate_sign($params, $merchant->key, 'md5'); +// $xml = XML::build($params); +// dump(self::paymentService()->downloadBill($day)->getContents()); +// dump($payment->getHttp()->request('https://api.mch.weixin.qq.com/pay/downloadbill','POST',[ +// 'body' => $xml, +// 'stream'=>true +// ])->getBody()->getContents()); + } + + public static function userTagService() + { + return self::application()->user_tag; + } + + public static function userGroupService() + { + return self::application()->user_group; + } + + + /** + * 企业付款到零钱 + * @param string $openid openid + * @param string $orderId 订单号 + * @param string $amount 金额 + * @param string $desc 说明 + */ + public static function merchantPay(string $openid, string $orderId, string $amount, string $desc) + { + $options = self::options(); + if (!isset($options['payment']['cert_path'])) { + throw new ApiException(410088); + } + if (!$options['payment']['cert_path']) { + throw new ApiException(410088); + } + $merchantPayData = [ + 'partner_trade_no' => $orderId, //随机字符串作为订单号,跟红包和支付一个概念。 + 'openid' => $openid, //收款人的openid + 'check_name' => 'NO_CHECK', //文档中有三种校验实名的方法 NO_CHECK OPTION_CHECK FORCE_CHECK + 'amount' => (int)bcmul($amount, '100', 0), //单位为分 + 'desc' => $desc, + 'spbill_create_ip' => request()->ip(), //发起交易的IP地址 + ]; + $result = self::application()->merchant_pay->send($merchantPayData); + if ($result->return_code == 'SUCCESS' && $result->result_code != 'FAIL') { + return true; + } else { + throw new ApiException($result->err_code_des ?? 400658); + } + } + + /** + * 生成支付订单对象 + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return Order + */ + protected static function paymentOrder($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = 'JSAPI', $options = []) + { + $total_fee = bcmul($total_fee, 100, 0); + $order = array_merge(compact('out_trade_no', 'total_fee', 'attach', 'body', 'detail', 'trade_type'), $options); + if (!is_null($openid)) $order['openid'] = $openid; + if ($order['detail'] == '') unset($order['detail']); + return new Order($order); + } + + /** + * 获得下单ID + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return mixed + */ + public static function paymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = 'JSAPI', $options = []) + { + $key = 'pay_' . $out_trade_no; + $result = Cache::get($key); + if ($result) { + return $result; + } else { + $order = self::paymentOrder($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $trade_type, $options); + $result = self::paymentService()->prepare($order); + if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS') { + Cache::set($key, $result, 7000); + return $result; + } else { + if ($result->return_code == 'FAIL') { + exception('微信支付错误返回:' . $result->return_msg); + } else if (isset($result->err_code)) { + exception('微信支付错误返回:' . $result->err_code_des); + } else { + exception('没有获取微信支付的预支付ID,请重新发起支付!'); + } + exit; + } + } + } + + /** + * 获得下单ID 新小程序支付 + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return mixed + */ + public static function newPaymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $options = []) + { + $key = 'pay_' . $out_trade_no; + $result = Cache::get($key); + if ($result) { + return $result; + } else { + $order = self::paymentOrder($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $options); + $result = self::application()->minipay->createorder($order); + if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS') { + Cache::set($key, $result, 7000); + return $result; + } else { + if ($result->return_code == 'FAIL') { + exception('微信支付错误返回:' . $result->return_msg); + } else if (isset($result->err_code)) { + exception('微信支付错误返回:' . $result->err_code_des); + } else { + exception('没有获取微信支付的预支付ID,请重新发起支付!'); + } + exit; + } + } + } + + /** + * 获得jsSdk支付参数 + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return array|string + */ + public static function jsPay($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = 'JSAPI', $options = []) + { + $paymentPrepare = self::paymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $trade_type, $options); + return self::paymentService()->configForJSSDKPayment($paymentPrepare->prepay_id); + } + + /** + * 获得jsSdk支付参数 新小程序支付 + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return array|string + */ + public static function newJsPay($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $options = []) + { + $paymentPrepare = self::newPaymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $options); + return self::paymentService()->configForJSSDKPayment($paymentPrepare->prepay_id); + } + + /** + * 获得APP付参数 + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return array|string + */ + public static function appPay($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = Order::APP, $options = []) + { + $paymentPrepare = self::paymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $trade_type, $options); + return self::paymentService()->configForAppPayment($paymentPrepare->prepay_id); + } + + /** + * 获得native支付参数 + * @param $openid + * @param $out_trade_no + * @param $total_fee + * @param $attach + * @param $body + * @param string $detail + * @param string $trade_type + * @param array $options + * @return array|string + */ + public static function nativePay($openid, $out_trade_no, $total_fee, $attach, $body, $detail = '', $trade_type = 'NATIVE', $options = []) + { + $data = self::paymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $trade_type, $options); + if ($data) { + $res['code_url'] = $data['code_url']; + $res['invalid'] = time() + 60; + $res['logo'] = sys_config('wap_login_logo'); + } else $res = []; + return $res; + } + + + /** + * 使用商户订单号退款 + * @param $orderNo + * @param $refundNo + * @param $totalFee + * @param null $refundFee + * @param null $opUserId + * @param string $refundReason + * @param string $type + * @param string $refundAccount + */ + public static function refund($orderNo, $refundNo, $totalFee, $refundFee = null, $opUserId = null, $refundReason = '', $type = 'out_trade_no', $refundAccount = 'REFUND_SOURCE_UNSETTLED_FUNDS') + { + $totalFee = floatval($totalFee); + $refundFee = floatval($refundFee); + if ($type == 'out_trade_no') { + return self::paymentService()->refund($orderNo, $refundNo, $totalFee, $refundFee, $opUserId, $type, $refundAccount, $refundReason); + } else { + return self::paymentService()->refundByTransactionId($orderNo, $refundNo, $totalFee, $refundFee, $opUserId, $refundAccount, $refundReason); + } + } + + + public static function payOrderRefund($orderNo, array $opt) + { + if (!isset($opt['pay_price'])) throw new AdminException(400730); + $totalFee = floatval(bcmul($opt['pay_price'], 100, 0)); + $refundFee = isset($opt['refund_price']) ? floatval(bcmul($opt['refund_price'], 100, 0)) : null; + $refundReason = $opt['desc'] ?? ''; + $refundNo = $opt['refund_id'] ?? $orderNo; + $opUserId = $opt['op_user_id'] ?? null; + $type = $opt['type'] ?? 'out_trade_no'; + /*仅针对老资金流商户使用 + REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款(默认使用未结算资金退款) + REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款*/ + $refundAccount = $opt['refund_account'] ?? 'REFUND_SOURCE_UNSETTLED_FUNDS'; + try { + $res = (self::refund($orderNo, $refundNo, $totalFee, $refundFee, $opUserId, $refundReason, $type, $refundAccount)); + if ($res->return_code == 'FAIL') throw new AdminException(400731, ['msg' => $res->return_msg]); + if (isset($res->err_code)) throw new AdminException(400731, ['msg' => $res->err_code_des]); + } catch (\Exception $e) { + throw new AdminException($e->getMessage()); + } + return true; + } + + /** + * 微信支付成功回调接口 + * @return \Symfony\Component\HttpFoundation\Response + * @throws \EasyWeChat\Core\Exceptions\FaultException + */ + public static function handleNotify() + { + return self::paymentService()->handleNotify(function ($notify, $successful) { + + if ($successful) { + + $data = [ + 'attach' => $notify->attach, + 'out_trade_no' => $notify->out_trade_no, + 'transaction_id' => $notify->transaction_id + ]; + + return Event::until('NotifyListener', [$data, PayServices::WEIXIN_PAY]); + } + + return false; + }); + } + + /** + * jsSdk + * @return \EasyWeChat\Js\Js + */ + public static function jsService() + { + return self::application()->js; + } + + /** + * 获取js的SDK + * @param string $url + * @return array|string + */ + public static function jsSdk($url = '') + { + $apiList = ['openAddress', 'updateTimelineShareData', 'updateAppMessageShareData', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'onVoicePlayEnd', 'uploadVoice', 'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'translateVoice', 'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'closeWindow', 'scanQRCode', 'chooseWXPay', 'openProductSpecificView', 'addCard', 'chooseCard', 'openCard']; + $jsService = self::jsService(); + if ($url) $jsService->setUrl($url); + try { + return $jsService->config($apiList); + } catch (\Exception $e) { + return '{}'; + } + + } + + + /** + * 回复文本消息 + * @param string $content 文本内容 + * @return Text + */ + public static function textMessage($content) + { + return new Text(compact('content')); + } + + /** + * 回复图片消息 + * @param string $media_id 媒体资源 ID + * @return Image + */ + public static function imageMessage($media_id) + { + return new Image(compact('media_id')); + } + + /** + * 回复视频消息 + * @param string $media_id 媒体资源 ID + * @param string $title 标题 + * @param string $description 描述 + * @param null $thumb_media_id 封面资源 ID + * @return Video + */ + public static function videoMessage($media_id, $title = '', $description = '...', $thumb_media_id = null) + { + return new Video(compact('media_id', 'title', 'description', 'thumb_media_id')); + } + + /** + * 回复声音消息 + * @param string $media_id 媒体资源 ID + * @return Voice + */ + public static function voiceMessage($media_id) + { + return new Voice(compact('media_id')); + } + + /** + * 回复图文消息 + * @param string|array $title 标题 + * @param string $description 描述 + * @param string $url URL + * @param string $image 图片链接 + */ + public static function newsMessage($title, $description = '...', $url = '', $image = '') + { + if (is_array($title)) { + if (isset($title[0]) && is_array($title[0])) { + $newsList = []; + foreach ($title as $news) { + $newsList[] = self::newsMessage($news); + } + return $newsList; + } else { + $data = $title; + } + } else { + $data = compact('title', 'description', 'url', 'image'); + } + return new News($data); + } + + /** + * 回复文章消息 + * @param string|array $title 标题 + * @param string $thumb_media_id 图文消息的封面图片素材id(必须是永久 media_ID) + * @param string $source_url 图文消息的原文地址,即点击“阅读原文”后的URL + * @param string $content 图文消息的具体内容,支持HTML标签,必须少于2万字符,小于1M,且此处会去除JS + * @param string $author 作者 + * @param string $digest 图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空 + * @param int $show_cover_pic 是否显示封面,0为false,即不显示,1为true,即显示 + * @param int $need_open_comment 是否打开评论,0不打开,1打开 + * @param int $only_fans_can_comment 是否粉丝才可评论,0所有人可评论,1粉丝才可评论 + * @return Article + */ + public static function articleMessage($title, $thumb_media_id, $source_url, $content = '', $author = '', $digest = '', $show_cover_pic = 0, $need_open_comment = 0, $only_fans_can_comment = 1) + { + $data = is_array($title) ? $title : compact('title', 'thumb_media_id', 'source_url', 'content', 'author', 'digest', 'show_cover_pic', 'need_open_comment', 'only_fans_can_comment'); + return new Article($data); + } + + /** + * 回复素材消息 + * @param string $type [mpnews、 mpvideo、voice、image] + * @param string $media_id 素材 ID + * @return Material + */ + public static function materialMessage($type, $media_id) + { + return new Material($type, $media_id); + } + + /** + * 作为客服消息发送 + * @param $to + * @param $message + * @return bool + */ + public static function staffTo($to, $message) + { + $staff = self::staffService(); + $staff = is_callable($message) ? $staff->message($message()) : $staff->message($message); + $res = $staff->to($to)->send(); + return $res; + } + + /** + * 获得用户信息 + * @param array|string $openid + * @return \EasyWeChat\Support\Collection + */ + public static function getUserInfo($openid) + { + $userService = self::userService(); + $userInfo = []; + try { + if (is_array($openid)) { + $res = $userService->batchGet($openid); + if (isset($res['user_info_list'])) { + $userInfo = $res['user_info_list']; + } else { + throw new AdminException(400732); + } + } else { + $userInfo = $userService->get($openid); + } + } catch (\Throwable $e) { + throw new AdminException(self::getMessage($e->getMessage())); + } + return $userInfo; + } + + + /** + * 获取用户列表 + * @param null $next_openid + * @return array + */ + public static function getUsersList($next_openid = null) + { + $userService = self::userService(); + $list = []; + try { + $res = $userService->lists($next_openid); + $list['data'] = $res['data']['openid'] ?? []; + $list['next_openid'] = $res['next_openid'] ?? null; + return $list; + } catch (\Exception $e) { + throw new AdminException(self::getMessage($e->getMessage())); + } + return $list; + } + + /** + * 处理返回错误信息友好提示 + * @param string $message + * @return array|mixed|string + */ + public static function getMessage(string $message) + { + if (strstr($message, 'Request AccessToken fail') !== false) { + $message = str_replace('Request AccessToken fail. response:', '', $message); + $message = json_decode($message, true) ?: []; + $errcode = $message['errcode'] ?? false; + if ($errcode) { + $message = $errcode; + } + } + return $message; + } + + /** + * 设置模版消息行业 + */ + public static function setIndustry($industryOne, $industryTwo) + { + return self::application()->notice->setIndustry($industryOne, $industryTwo); + } + + /** + * 获得添加模版ID + * @param $template_id_short + */ + public static function addTemplateId($template_id_short) + { + try { + return self::application()->notice->addTemplate($template_id_short); + } catch (\Exception $e) { + throw new AdminException(self::getMessage($e->getMessage())); + } + } + + /** + * 获取模板列表 + * @return \EasyWeChat\Support\Collection + */ + public static function getPrivateTemplates() + { + try { + return self::application()->notice->getPrivateTemplates(); + } catch (\Exception $e) { + throw new AdminException(self::getMessage($e->getMessage())); + } + } + + /* + * 根据模版ID删除模版 + */ + public static function deleleTemplate($template_id) + { + try { + return self::application()->notice->deletePrivateTemplate($template_id); + } catch (\Exception $e) { + throw new AdminException(self::getMessage($e->getMessage())); + } + + } +} diff --git a/demo/thinkphp/backend/phoenix/services/copyproduct/BaseCopyProduct.php b/demo/thinkphp/backend/phoenix/services/copyproduct/BaseCopyProduct.php new file mode 100644 index 0000000000000000000000000000000000000000..8ec031cecb5814cc796b44213bbb9f65f588be48 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/copyproduct/BaseCopyProduct.php @@ -0,0 +1,64 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\copyproduct; + +use crmeb\services\AccessTokenServeService; +use crmeb\basic\BaseStorage; + +/** + * Class BaseProduct + * @package crmeb\services\copyproduct + */ +abstract class BaseCopyProduct extends BaseStorage +{ + + /** + * access_token + * @var null + */ + protected $accessToken = NULL; + + /** + * BaseProduct constructor. + * @param string $name + * @param AccessTokenServeService $accessTokenServeService + * @param string $configFile + */ + public function __construct(string $name, AccessTokenServeService $accessTokenServeService, string $configFile) + { + parent::__construct($name, [], $configFile); + $this->accessToken = $accessTokenServeService; + } + + /** + * 初始化 + * @param array $config + * @return mixed|void + */ + protected function initialize(array $config = []) + { +// parent::initialize($config); + } + + /** + * 开通服务 + * @return mixed + */ + abstract public function open(); + + /**复制商品 + * @param string $url + * @param array $options + * @return mixed + */ + abstract public function goods(string $url, array $options = []); +} diff --git a/demo/thinkphp/backend/phoenix/services/copyproduct/CopyProduct.php b/demo/thinkphp/backend/phoenix/services/copyproduct/CopyProduct.php new file mode 100644 index 0000000000000000000000000000000000000000..0b39f148e8683c5d8fc00a44680143311277e21d --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/copyproduct/CopyProduct.php @@ -0,0 +1,63 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\copyproduct; + +use crmeb\basic\BaseManager; +use crmeb\services\AccessTokenServeService; +use think\facade\Config; +use think\Container; + + +/** + * Class Product + * @package crmeb\services\copyproduct + * @mixin \crmeb\services\copyproduct\CopyProduct + */ +class CopyProduct extends BaseManager +{ + /** + * 空间名 + * @var string + */ + protected $namespace = '\\crmeb\\services\\copyproduct\\storage\\'; + + /** + * 默认驱动 + * @return mixed + */ + protected function getDefaultDriver() + { + return Config::get('product.default', 'copy'); + } + + /** + * 获取类的实例 + * @param $class + * @return mixed|void + */ + protected function invokeClass($class) + { + if (!class_exists($class)) { + throw new \RuntimeException('class not exists: ' . $class); + } + $this->getConfigFile(); + + if (!$this->config) { + $this->config = Config::get($this->configFile . '.stores.' . $this->name, []); + } + $handleAccessToken = new AccessTokenServeService($this->config['account'] ?? '', $this->config['secret'] ?? ''); + $handle = Container::getInstance()->invokeClass($class, [$this->name, $handleAccessToken, $this->configFile]); + $this->config = []; + return $handle; + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/copyproduct/storage/Copy.php b/demo/thinkphp/backend/phoenix/services/copyproduct/storage/Copy.php new file mode 100644 index 0000000000000000000000000000000000000000..795d5b71dbab5fd57031178d8b347382b2a612d3 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/copyproduct/storage/Copy.php @@ -0,0 +1,61 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\copyproduct\storage; + +use crmeb\services\copyproduct\BaseCopyProduct; + + +/** + * Class Copy + * @package crmeb\services\product\storage + */ +class Copy extends BaseCopyProduct +{ + + /** + * 是否开通 + */ + const PRODUCT_OPEN = 'copy/open'; + /** + * 获取详情 + */ + const PRODUCT_GOODS = 'copy/goods'; + + /** 初始化 + * @param array $config + */ + protected function initialize(array $config = []) + { + parent::initialize($config); + } + + /** 是否开通复制 + * @return mixed + */ + public function open() + { + return $this->accessToken->httpRequest(self::PRODUCT_OPEN, []); + } + + /** 复制商品 + * @param string $url + * @param array $options + * @return mixed + */ + public function goods(string $url, array $options = []) + { + $param['url'] = $url; + return $this->accessToken->httpRequest(self::PRODUCT_GOODS, $param); + } + + +} diff --git a/demo/thinkphp/backend/phoenix/services/copyproduct/storage/Copy99api.php b/demo/thinkphp/backend/phoenix/services/copyproduct/storage/Copy99api.php new file mode 100644 index 0000000000000000000000000000000000000000..88f702d58d84e5993ba38aa22cecf87995890f2b --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/copyproduct/storage/Copy99api.php @@ -0,0 +1,739 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\copyproduct\storage; + + +use crmeb\services\copyproduct\BaseCopyProduct; +use crmeb\services\CacheService; +use crmeb\services\HttpService; + +/** + * Class Copy99api + * @package crmeb\services\copyproduct\storage + */ +class Copy99api extends BaseCopyProduct +{ + + /** + * @var string[] + */ + protected $host = ['taobao', 'tmall', 'jd', 'pinduoduo', 'suning', 'yangkeduo', '1688']; + + //接口地址 + protected static $api = [ + 'taobao' => 'https://api03.6bqb.com/taobao/detail', //https://api03.6bqb.com/app/taobao/detail + 'tmall' => 'https://api03.6bqb.com/tmall/detail', + 'jd' => 'https://api03.6bqb.com/jd/detail', + 'pdd' => 'https://api03.6bqb.com/pdd/detail', + 'suning' => 'https://api03.6bqb.com/suning/detail', + '1688' => 'https://api03.6bqb.com/alibaba/detail' + ]; + protected static $apiKey = '';//996EF05B079F8706345938A0CD7339BB + //商品默认字段 + protected static $productInfo = [ + 'cate_id' => '', + 'store_name' => '', + 'store_info' => '', + 'unit_name' => '件', + 'price' => 0, + 'keyword' => '', + 'ficti' => 0, + 'ot_price' => 0, + 'give_integral' => 0, + 'postage' => 0, + 'cost' => 0, + 'image' => '', + 'slider_image' => '', + 'video_link' => '', + 'add_time' => 0, + 'stock' => 0, + 'description' => '', + 'description_images' => [], + 'soure_link' => '', + 'temp_id' => '', + 'items' => [], + 'attrs' => [], + 'info' => [], + 'sku' => [] + ]; + + /** + * 整合 + * @param $url + * @param $method + * @param $data + * @return string + */ + public static function makeUrl(string $url, string $method, array $data) + { + $param = ''; + if (strtolower($method) == 'get' && $data) { + foreach ($data as $key => $value) { + $param .= '&' . $key . '=' . $value; + } + } + return $url . '?apikey=' . self::$apiKey . $param; + } + + /** + * @param bool $status + * @param string $msg + * @param array $data + */ + public static function setReturn(bool $status = true, string $msg = 'SUCCESS', array $data = []) + { + return ['status' => $status, 'msg' => $msg, 'data' => $data]; + } + + public function open() + { + return true; + } + + + public function getType(string $link) + { + $shopid = 0; + $url_arr = parse_url($link); + if (isset($url_arr['host'])) { + foreach ($this->host as $name) { + if (strpos($url_arr['host'], $name) !== false) { + $type = $name; + } + } + } + $type = ($type == 'pinduoduo' || $type == 'yangkeduo') ? 'pdd' : $type; + switch ($type) { + case 'taobao': + case 'tmall': + $params = []; + if (isset($url_arr['query']) && $url_arr['query']) { + $queryParts = explode('&', $url_arr['query']); + foreach ($queryParts as $param) { + $item = explode('=', $param); + if (isset($item[0]) && $item[1]) $params[$item[0]] = $item[1]; + } + } + $id = $params['id'] ?? ''; + break; + case 'jd': + $params = []; + if (isset($url_arr['path']) && $url_arr['path']) { + $path = str_replace('.html', '', $url_arr['path']); + $params = explode('/', $path); + } + $id = $params[1] ?? ''; + break; + case 'pdd': + $params = []; + if (isset($url_arr['query']) && $url_arr['query']) { + $queryParts = explode('&', $url_arr['query']); + foreach ($queryParts as $param) { + $item = explode('=', $param); + if (isset($item[0]) && $item[1]) $params[$item[0]] = $item[1]; + } + } + $id = $params['goods_id'] ?? $params['goodsId'] ?? ''; + break; + case 'suning': + $params = []; + if (isset($url_arr['path']) && $url_arr['path']) { + $path = str_replace('.html', '', $url_arr['path']); + $params = explode('/', $path); + } + $id = $params[2] ?? ''; + $shopid = $params[1] ?? ''; + break; + case '1688': + $params = []; + if (isset($url_arr['query']) && $url_arr['query']) { + $path = str_replace('.html', '', $url_arr['path']); + $params = explode('/', $path); + } + $id = $params[2] ?? ''; + $shopid = $params[1] ?? ''; + break; + } + return [$type, $id, $shopid]; + } + + /** + * + * @param string $link + * @param array $options + * @return array + */ + public function goods(string $link, array $options = []) + { + [$type, $id, $shopid] = $this->getType($link); + $apikey = $options['apikey'] ?? null; + $data = [ + 'itemid' => $id, + 'shopid' => $shopid, + ]; + if (!$apikey) { + return self::setReturn(false, '请先去设置复制商品apiKey'); + } + $url = self::$api[$type] ?? ''; + $type = $type == '1688' ? 'alibaba' : $type; + $action = $type . 'Info'; + $deal_action = $type . 'Deal'; + $method = 'get'; + self::$apiKey = $apikey; + if (!$data || !$url || !is_callable(self::class, $action) || !is_callable(self::class, $deal_action)) { + return self::setReturn(false, '暂不支持该平台商品复制'); + } + switch ($type) { + case 'taobao': + case 'tmall': + case 'jd': + case 'pdd': + case 'alibaba': + $method = 'get'; + if (!isset($data['itemid']) || !$data['itemid']) + return self::setReturn(false, '缺少商品ID'); + break; + case 'suning': + $method = 'get'; + if (!isset($data['itemid']) || !$data['itemid']) + return self::setReturn(false, '缺少商品ID'); + if (!isset($data['shopid']) || !$data['shopid']) + return self::setReturn(false, '缺少商户ID'); + break; + } + $url = self::makeUrl($url, $method, $data); + if ($cache_info = CacheService::get(md5($url))) { + return self::setReturn(true, 'SUCCESS', $cache_info); + } + $info = self::$action($url, $data); + if (!$info) return self::setReturn(false, '获取商品失败'); + $info = json_decode($info, true); + if (!$info || (!in_array($info['retcode'], ['0000']))) { + return self::setReturn(false, $info['message'] ?? '获取商品失败', $info); + } + $result = $info['data']; + //可能存在下一页 但是api中没有分页参数 暂留 +// if (isset($info['hasNext']) && $info['hasNext']) { +// $data['page'] = $info['page'] + 1; +// } + $result = self::$deal_action($result); + //过滤采集到的规格 删除其中的空值 + if ($result['items']) { + foreach ($result['items'] as $k => $item) { + if (isset($item['value'])) { + if ($item['value'] == '') unset($result['items'][$k]); + if (!$item['detail'] || !isset($item['detail'][0]) || $item['detail'][0] == '') unset($result['items'][$k]); + } else { + unset($result['items'][$k]); + } + } + } + if (!$result['items']) { + $result['items'] = [ + [ + 'value' => '默认', + 'detail' => [ + '默认' + ] + ] + ]; + } + $result['info'] = self::formatAttr($result['items'], $result['sku']); + if (!$result['image'] && $result['slider_image']) + $result['image'] = $result['slider_image'][0] ?? ''; + if ($result['description']) { + $result['description'] = str_replace('data-lazyload', 'src', $result['description']); + } + CacheService::set(md5($url), $result, 3600 * 24); + return self::setReturn(true, 'SUCCESS', $result); + } + + /** + * 获取淘宝商品 + * @param $url + * @param $data + * @param string $method + * @return bool|string + */ + public static function taobaoInfo(string $url, array $data, string $method = 'get') + { + $info = HttpService::request($url, $method, $data); + $result = false; + if ($info) { + $result = $info; + } + return $result; + } + + /** + * 处理获取淘宝的商品 + * @param $data + * @return mixed + */ + public static function taobaoDeal(array $data) + { + $info = $data['item'] ?? []; + $result = self::$productInfo; + if ($info) { + $result['store_name'] = $info['title'] ?? ''; + $result['store_info'] = $info['subTitle'] ?? ''; + $result['slider_image'] = $info['images'] ?? ''; + $result['description'] = $info['desc'] ?? ''; + $result['description_images'] = $info['descImgs'] ?? []; + $items = []; + if (isset($info['props']) && $info['props']) { + foreach ($info['props'] as $key => $prop) { + $item['value'] = $prop['name']; + $item['detail'] = []; + foreach ($prop['values'] as $name) { + $item['detail'][] = $name['name']; + } + $items[] = $item; + } + } + $sku = []; + if (isset($info['sku']) && $info['sku']) { + foreach ($info['sku'] as $item) { + if ($item['skuId']) { + $skuName = explode(';', $item['skuName']); + $skuNameData = []; + foreach ($skuName as $v) { + [$kp, $vv] = explode('--', $v); + $skuNameData[] = $vv; + } + $sku[implode(',', $skuNameData)] = [ + 'price' => $item['price'] + ]; + } + } + } + $result['sku'] = $sku; + $result['items'] = array_merge($items); + } + return $result; + } + + + /** + * 获取天猫商品 + * @param $url + * @param $data + * @param string $method + * @return bool|string + */ + public static function tmallInfo(string $url, array $data, string $method = 'get') + { + $info = HttpService::request($url, $method, $data); + $result = false; + if ($info) { + $result = $info; + } + return $result; + } + + /** + * 处理天猫商品 + * @param $data + * @return mixed + */ + public static function tmallDeal(array $data) + { + $info = $data['item'] ?? []; + $result = self::$productInfo; + if ($info) { + $result['store_name'] = $info['title'] ?? ''; + $result['store_info'] = $info['subTitle'] ?? ''; + $result['slider_image'] = self::lingByHttp($info['images'] ?? ''); + $result['description_images'] = self::lingByHttp($info['descImgs'] ?? []); + $description = ''; + foreach ($result['description_images'] as $item) { + $description .= ''; + } + unset($item); + $result['description'] = $description; + $items = []; + if (isset($info['props']) && $info['props']) { + foreach ($info['props'] as $key => $prop) { + $item['value'] = $prop['name']; + $item['detail'] = []; + foreach ($prop['values'] as $name) { + $item['detail'][] = $name['name']; + } + $items[] = $item; + } + } + $sku = []; + if (isset($info['sku']) && $info['sku']) { + foreach ($info['sku'] as $item) { + if ($item['skuId']) { + $skuName = explode(';', $item['skuName']); + $skuNameData = []; + foreach ($skuName as $v) { + [$kp, $vv] = explode('--', $v); + $skuNameData[] = $vv; + } + $sku[implode(',', $skuNameData)] = [ + 'price' => $item['price'] + ]; + } + } + } + $result['sku'] = $sku; + $result['items'] = array_merge($items); + } + return $result; + } + + /** + * 获取京东商品 + * @param $url + * @param $data + * @param string $method + * @return bool|string + */ + public static function jdInfo(string $url, array $data, string $method = 'get') + { + $info = HttpService::request($url, $method, $data); + $result = false; + if ($info) { + $result = $info; + } + return $result; + } + + /** + * 处理京东商品 + * @param $data + * @return mixed + */ + public static function jdDeal(array $data) + { + $info = $data['item'] ?? []; + $result = self::$productInfo; + if ($info) { + $result['store_name'] = $info['name'] ?? ''; + $result['store_info'] = $result['store_name']; + $result['price'] = $info['price'] ?? 0; + $result['ot_price'] = $info['originalPrice'] ?? 0; + $result['slider_image'] = $info['images'] ?? []; + $result['description'] = $info['desc'] ?? ''; + $result['description_images'] = $info['descImgs'] ?? []; + $result['description_images'] = array_map(function ($item) { + if (strstr($item, 'http') === false) { + $item = 'http:' . $item; + } + return $item; + }, $result['description_images']); + if (strstr($result['description'], ' diff --git a/demo/thinkphp/backend/phoenix/services/crud/stubs/view/router/modules/crud.stub b/demo/thinkphp/backend/phoenix/services/crud/stubs/view/router/modules/crud.stub new file mode 100644 index 0000000000000000000000000000000000000000..3df7b57f6f06faed09a75a7db577c3c682970ea4 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/crud/stubs/view/router/modules/crud.stub @@ -0,0 +1,39 @@ +// +--------------------------------------------------------------------- +// | CRMEB [ CRMEB赋能开发者,助力企业发展 ] +// +--------------------------------------------------------------------- +// | Copyright (c) 2016~{%year%} https://www.crmeb.com All rights reserved. +// +--------------------------------------------------------------------- +// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权 +// +--------------------------------------------------------------------- +// | Author: CRMEB Team +// +--------------------------------------------------------------------- + +import LayoutMain from '@/layout'; +import setting from '@/setting' + +let routePre = setting.routePre + +const meta = { + auth: true, +} + +const pre = '{%name%}_' + +export default { + path: `${routePre}`, + name: 'crud_{%name%}', + header: '{%nameHeader%}', + meta, + component: LayoutMain, + children: [ + { + path: '{%route%}', + name: `${pre}list`, + meta: { + auth: ['{%name%}-crud-list-index'], + title: '{%menus%}', + }, + component: () => import('@/pages/crud/{%pagePath%}/index'), + }, + ], +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/Application.php b/demo/thinkphp/backend/phoenix/services/easywechat/Application.php new file mode 100644 index 0000000000000000000000000000000000000000..b96ba8dae6940c6166792ec2cc5519019334b040 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/Application.php @@ -0,0 +1,59 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\easywechat; + + +use crmeb\services\easywechat\miniPayment\ServiceProvider; +use crmeb\services\easywechat\oauth2\wechat\WechatOauth2Provider; +use crmeb\services\easywechat\orderShipping\OrderClient; +use crmeb\services\easywechat\subscribe\ProgramProvider; +use crmeb\services\easywechat\v3pay\PayClient; +use crmeb\services\easywechat\wechatlive\ProgramProvider as LiveProgramProvider; +use crmeb\services\easywechat\v3pay\ServiceProvider as V3PayServiceProvider; +use crmeb\services\easywechat\orderShipping\ServiceProvider as OrderServiceProvider; + + +/** + * Class Application + * @package crmeb\services\easywechat + * @property LiveProgramProvider $wechat_live + * @property WechatOauth2Provider $oauth2 + * @property PayClient $v3pay + * @property OrderClient $order_ship + */ +class Application extends \EasyWeChat\Foundation\Application +{ + + /** + * @var string[] + */ + protected $providersNew = [ + LiveProgramProvider::class, + WechatOauth2Provider::class, + ServiceProvider::class, + ProgramProvider::class, + V3PayServiceProvider::class, + \crmeb\services\easywechat\Open3rd\ProgramProvider::class, + OrderServiceProvider::class + ]; + + /** + * Application constructor. + * @param $config + */ + public function __construct($config) + { + $this->providers = array_merge($this->providers, $this->providersNew); + parent::__construct($config); + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/Open3rd/AccessToken.php b/demo/thinkphp/backend/phoenix/services/easywechat/Open3rd/AccessToken.php new file mode 100644 index 0000000000000000000000000000000000000000..38ade663c6bac86b33222ce27567c15aceeaa92a --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/Open3rd/AccessToken.php @@ -0,0 +1,346 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\easywechat\open3rd; + + +use crmeb\exceptions\ApiException; +use crmeb\services\HttpService; + +/** + * Class AccessTokenServeService + * @package crmeb\services + */ +class AccessToken extends HttpService +{ + /** + * 第三方平台 appid + * @var string + */ + protected $component_appid; + + /** + * 第三方平台 appsecret + * @var string + */ + protected $component_appsecret; + + /** + * 微信后台推送的 ticket + * @var string + */ + protected $component_verify_ticket; + + /** + * @var Cache|null + */ + protected $cache; + + /** + * 第三方平台token + * @var string + */ + protected $component_access_token; + + /** + * 授权方appid + * @var string + */ + protected $authorizer_appid; + + /** + * 接口调用令牌(在授权的公众号/小程序具备 API 权限时,才有此返回值) + * @var string + */ + protected $authorizer_access_token; + + /** + * 刷新令牌(在授权的公众号具备API权限时,才有此返回值),刷新令牌主要用于第三方平台获取和刷新已授权用户的 authorizer_access_token。一旦丢失,只能让用户重新授权,才能再次拿到新的刷新令牌。用户重新授权后,之前的刷新令牌会失效 + * @var string + */ + protected $authorizer_refresh_token; + + /** + * @var string + */ + protected $cacheTokenPrefix = "component_access_token_crmeb"; + + /** + * 获取第三方平台token + * @var string + */ + const TOKEN_URL = 'https://api.weixin.qq.com/cgi-bin/component/api_component_token'; + + /** + * 使用授权码获取授权信息 + */ + const AUTH_INFO = 'https://api.weixin.qq.com/cgi-bin/component/api_query_auth'; + /** + * 获取、刷新接口调用token + */ + const AUTHORIZER_TOKEN = 'https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token'; + + /** + * AccessTokenServeService constructor. + * @param string $component_appid + * @param string $component_appsecret + * @param string $component_verify_ticket + * @param string $authorizer_appid + * @param Cache|null $cache + */ + public function __construct(string $component_appid, string $component_appsecret, string $component_verify_ticket, string $authorizer_appid = '', $cache = null) + { + if (!$cache) { + $cache = app()->make(\crmeb\services\CacheService::class); + } + $this->component_appid = $component_appid; + $this->component_appsecret = $component_appsecret; + $this->component_verify_ticket = $component_verify_ticket; + $this->authorizer_appid = $authorizer_appid; + $this->cache = $cache; + } + + /** + * 获取配置 + * @return array + */ + public function getConfig() + { + return [ + 'component_appid' => $this->component_appid, + 'component_appsecret' => $this->component_appsecret, + 'component_verify_ticket' => $this->component_verify_ticket, + ]; + } + + /** + * @return string + */ + public function getComponentAppid() + { + return $this->component_appid; + } + + /** + * @return string + */ + public function getComponentAppsecret() + { + return $this->component_appsecret; + } + + /** + * @return string + */ + public function getAuthorizerAppid() + { + return $this->authorizer_appid; + } + + /** + * 获取第三方缓存token + * @return mixed + * @throws \Psr\SimpleCache\InvalidArgumentException + */ + public function getComponentToken() + { + $accessTokenKey = md5($this->component_appid . '_' . $this->component_appid . '_' . $this->component_verify_ticket . '_' . $this->cacheTokenPrefix); + $component_access_token = $this->cache->get($accessTokenKey); + if (!$component_access_token) { + $getToken = $this->getTokenFromServer(); + $this->cache->set($accessTokenKey, $getToken['component_access_token'], $getToken['expires_in'] ? $getToken['expires_in'] - 200 : 7000); + $component_access_token = $getToken['component_access_token']; + } + $this->component_access_token = $component_access_token; + + return $component_access_token; + + } + + /** + * 从服务器获取token + * @return mixed + */ + public function getTokenFromServer() + { + $config = $this->getConfig(); + if (!$config['component_appid'] || !$config['component_appsecret']) { + throw new ApiException('请先配置第三方component_appid、component_appsecret'); + } + if (!$config['component_verify_ticket']) { + throw new ApiException('未配置微信开放平台或者未收到推送ticket,请等待10分钟后再试'); + } + $res = $this->postRequest(self::TOKEN_URL, $config); + $res = json_decode($res, true); + if (!$res || $res['errcode'] != 0 || !isset($res['component_access_token']) || !$res['component_access_token']) { + throw new ApiException('获取component_access_token失败,原因:' . $res['errmsg']); + } + return $res; + } + + /** + * 获取授权方token + * @param $authorizer_appid + * @return mixed + */ + public function getAccessToken($authorizer_appid) + { + $accessTokenKey = md5('authorizer_access_token' . $authorizer_appid . '_' . $this->cacheTokenPrefix); + $authorizer_access_token = $this->cache->get($accessTokenKey); + if (!$authorizer_access_token) { + $refreshTokenKey = md5('authorizer_refresh_token' . $authorizer_appid . '_' . $this->cacheTokenPrefix); + $authorizer_refresh_token = $this->cache->get($refreshTokenKey); + if (!$authorizer_refresh_token) { + throw new ApiException('请重新授权'); + } + $res = $this->freshAuthorizationToken($authorizer_appid, $authorizer_refresh_token); + $this->cache->set(md5('authorizer_access_token' . $res['authorizer_appid'] . '_' . $this->cacheTokenPrefix), $res['authorizer_access_token'], $res['expires_in'] ? $res['expires_in'] - 200 : 7000); + $this->cache->set(md5('authorizer_refrssh_token' . $res['authorizer_appid'] . '_' . $this->cacheTokenPrefix), $res['authorizer_refresh_token'], 30 * 24 * 3600); + $authorizer_access_token = $res['authorizer_access_token']; + } + return $authorizer_access_token; + } + + /** + * 获取授权信息 + * @param $authorization_code 授权码 + * @return authorizer_appid string 授权方 appid + * @return authorizer_access_token string 接口调用令牌(在授权的公众号/小程序具备 API 权限时,才有此返回值) + * @return authorizer_refresh_token string 刷新令牌(在授权的公众号具备API权限时,才有此返回值),刷新令牌主要用于第三方平台获取和刷新已授权用户的 authorizer_access_token。一旦丢失,只能让用户重新授权,才能再次拿到新的刷新令牌。用户重新授权后,之前的刷新令牌会失效 + * @return array|bool|mixed + */ + public function getAuthorizationInfo($authorization_code) + { + $res = $this->httpRequest(self::AUTH_INFO, ['authorization_code' => $authorization_code], false); + if (!$res || $res['errcode'] != 0 || !isset($res['authorization_info']) || !$res['authorization_info']) { + throw new ApiException('获取authorizer_access_token失败'); + } + $res = $res['authorization_info']; + $this->cache->set(md5('authorizer_access_token' . $res['authorizer_appid'] . '_' . $this->cacheTokenPrefix), $res['authorizer_access_token'], $res['expires_in'] ? $res['expires_in'] - 200 : 7000); + //在授权的公众号具备API权限时,才有此返回值 + if (isset($res['authorizer_refrsh_token'])) { + $this->cache->set(md5('authorizer_refresh_token' . $res['authorizer_appid'] . '_' . $this->cacheTokenPrefix), $res['authorizer_refrsh_token'], 30 * 24 * 3600); + } + return $res; + } + + /** + * 获取/刷新接口调用令牌 + * @param $authorizer_appid 授权方appid + * @param $authorizer_refresh_token 刷新令牌,获取授权信息时得到 + * @return authorizer_access_token string 授权方令牌 + * @return authorizer_refresh_token string 刷新令牌 + * @return array|bool|mixed + */ + public function freshAuthorizationToken($authorizer_appid, $authorizer_refresh_token) + { + $res = $this->postRequest(self::AUTHORIZER_TOKEN, ['component_access_token' => $this->component_access_token, 'authorizer_appid' => $authorizer_appid, 'authorizer_refresh_token' => $authorizer_refresh_token]); + if (!$res || $res['errcode'] != 0 || !isset($res['authorizer_access_token']) || !$res['authorizer_access_token']) { + throw new ApiException('刷新authorizer_access_token失败,请重新获取授权'); + } + return $res; + } + + + /** + * 请求 + * @param string $url + * @param array $data + * @param string $method + * @param bool $isHeader + * @return array|mixed + */ + public function httpRequest(string $url, array $data = [], bool $is_atuh = true, string $method = 'POST') + { + if (!$is_atuh) { + $this->getComponentToken(); + if (!$this->component_access_token) { + throw new ApiException('配置已更改或component_access_token已失效'); + } + $url .= '?component_access_token=' . $this->component_access_token; + $data = array_merge($data, ['component_appid' => $this->component_appid]); + } else { + if (!$this->authorizer_appid) { + throw new ApiException('缺少授权方authorizer_appid'); + } + $access_token = $this->getAccessToken($this->authorizer_appid); + if (!$access_token) { + throw new ApiException('配置已更改或授权已失效请重新授权'); + } + $url .= '?access_token=' . $access_token; + } + $res = $this->request($url, $method, $data); + if (!$res) { + throw new ApiException('请求微信服务器发生异常,请稍后重试'); + } + return json_decode($res, true) ?: false; + } + + /** + * XML数据转换成array数组 + * @param string $xml + * @return array + */ + public function xmlToArray($xml) + { + // 禁止引用外部xml实体 + libxml_disable_entity_loader(true); + $res = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); + return (array)$res; + } + + /** + * 对解密后的明文进行补位删除 + * @param decrypted 解密后的明文 + * @return 删除填充补位后的明文 + */ + public function decode($text) + { + + $pad = ord(substr($text, -1)); + if ($pad < 1 || $pad > 32) { + $pad = 0; + } + return substr($text, 0, (strlen($text) - $pad)); + } + + /** + * 对密文进行解密 + * @param string $encodingAesKey 解密 + * @param string $encrypted 需要解密的密文 + * @return string 解密得到的明文 + */ + public function decrypt($encodingAesKey, $encrypted) + { + try { + //使用BASE64对需要解密的字符串进行解码 + $ciphertext_dec = base64_decode($encrypted); + $iv = substr(base64_decode($encodingAesKey . "="), 0, 16); + $decrypted = openssl_decrypt($ciphertext_dec, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); + } catch (\Throwable $e) { + throw new ApiException($e->getMessage()); + } + try { + //去除补位字符 + $result = $this->decode($decrypted); + //去除16位随机字符串,网络字节序和AppId + if (strlen($result) < 16) + return ""; + $content = substr($result, 16, strlen($result)); + $len_list = unpack("N", substr($content, 0, 4)); + $xml_len = $len_list[1]; + $xml_content = substr($content, 4, $xml_len); + } catch (\Throwable $e) { + throw new ApiException($e->getMessage()); + } + return $xml_content; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/Open3rd/ProgramOpen3rd.php b/demo/thinkphp/backend/phoenix/services/easywechat/Open3rd/ProgramOpen3rd.php new file mode 100644 index 0000000000000000000000000000000000000000..a818dca73f345ba6cd6aa1fce457f85e477be1d7 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/Open3rd/ProgramOpen3rd.php @@ -0,0 +1,326 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\easywechat\open3rd; + + +/** + * Class ProgramWechatLive + * @package crmeb\services\wechatlive + */ +class ProgramOpen3rd +{ + /** + * @var AccessToken + */ + protected $accessToken; + + /** + * 预授权码 + */ + const PRE_AUTH_CODE = 'https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode'; + + /** + * 获取授权方的帐号基本信息 + */ + const GET_AUTHORIZER_INFO = 'https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info'; + /** + * 获取体验真列表 + */ + const MEMBER_AUTH_LIST = 'https://api.weixin.qq.com/wxa/memberauth'; + /** + * 绑定体验者 + */ + const BIND_MEMBER_AUTH = 'https://api.weixin.qq.com/wxa/bind_tester'; + /** + * 解除绑定体验者 + */ + const UNBIND_MEMBER_AUTH = 'https://api.weixin.qq.com/wxa/unbind_tester'; + /** + * 获取代码草稿列表 + */ + const DRAFT_LIST = 'https://api.weixin.qq.com/wxa/gettemplatedraftlist'; + /** + * 将草稿添加到代码模板库 + */ + const ADD_TO_TEMPLATE = 'https://api.weixin.qq.com/wxa/addtotemplate'; + /** + * 获取代码模版列表 + */ + const TEMPLATE_LIST = 'https://api.weixin.qq.com/wxa/gettemplatelist'; + /** + * 删除指定代码模版 + */ + const DEL_TEMPLATE = 'https://api.weixin.qq.com/wxa/deletetemplate'; + /** + * 上传代码 + */ + const COMMIT = 'https://api.weixin.qq.com/wxa/commit'; + /** + * 获取已上传的代码页面列表 + */ + const GET_PAGE = 'https://api.weixin.qq.com/wxa/get_page'; + /** + * 获取体验二维码 + */ + const GET_QRCODE = 'https://api.weixin.qq.com/wxa/get_qrcode'; + /** + * 代码提交审核 + */ + const SUBMIT_AUDIT = 'https://api.weixin.qq.com/wxa/submit_audit'; + /** + * 查询指定版本审核状态 + */ + const GET_AUDIT_STATUS = 'https://api.weixin.qq.com/wxa/get_auditstatus'; + /** + * 查询最近一次提交审核状态 + */ + const GET_LATEST_AUDIT_STATUS = 'https://api.weixin.qq.com/wxa/get_latest_auditstatus'; + /** + * 撤回审核 + */ + const UNDO_CODE_AUDIT = 'https://api.weixin.qq.com/wxa/undocodeaudit'; + /** + * 发布已经通过审核的小程序 + */ + const RELEASE = 'https://api.weixin.qq.com/wxa/release'; + /** + * 分阶段发布 + */ + const GRAY_RELEASE = 'https://api.weixin.qq.com/wxa/grayrelease'; + /** + * 版本回退 + */ + const REVERT_CODE_RELEASE = 'https://api.weixin.qq.com/wxa/revertcoderelease'; + + /** + * ProgramOpen3rd constructor. + * @param AccessToken $accessToken + */ + public function __construct(AccessToken $accessToken) + { + $this->accessToken = $accessToken; + $this->config = $accessToken->getConfig(); + } + + + /** + * 获取预授权码 + * @return array|bool|mixed + */ + public function getPreAuthCode() + { + return $this->accessToken->httpRequest(self::PRE_AUTH_CODE, [], false); + } + + /** + * 获取授权 + * @param $authorization_code + * @return authorizer_appid + */ + public function getAuth($authorization_code) + { + return $this->accessToken->getAuthorizationInfo($authorization_code); + } + + /** + * 获取授权方帐号基本信息 + * @param $authorizer_appid + * @return array|bool|mixed + */ + public function getAuthorizerinfo(string $authorizer_appid) + { + return $this->accessToken->httpRequest(self::GET_AUTHORIZER_INFO, ['authorizer_appid' => $authorizer_appid], false); + } + + /** + * 获取授权体验者列表 + * @return array|bool|mixed + */ + public function getMemberAuthList() + { + return $this->accessToken->httpRequest(self::MEMBER_AUTH_LIST, ['action' => 'get_experiencer']); + } + + /** + * 绑定体验者 + * @param string $wechatid + * @return array|bool|mixed + */ + public function bindMemberAuth(string $wechatid) + { + return $this->accessToken->httpRequest(self::BIND_MEMBER_AUTH, ['wechatid' => $wechatid]); + } + + /** + * 解除绑定体验者 + * @param string $wechatid + * @param string $userstr + * @return array|bool|mixed + */ + public function unBindMemberAuth(string $wechatid, string $userstr = '') + { + $data = ['wechatid' => $wechatid]; + if ($userstr) $data['userstr'] = $userstr; + return $this->accessToken->httpRequest(self::UNBIND_MEMBER_AUTH, $data); + } + + /** + * 获取草稿列表 + * @return array|bool|mixed + */ + public function getDraftList() + { + return $this->accessToken->httpRequest(self::DRAFT_LIST); + } + + /** + * 将草稿添加到代码模版 + * @param $draft_id + * @return array|bool|mixed + */ + public function addToTemplate($draft_id) + { + return $this->accessToken->httpRequest(self::ADD_TO_TEMPLATE, ['draft_id' => $draft_id]); + } + + /** + * 获取代码模版列表 + * @return array|bool|mixed + */ + public function getTemplateList() + { + return $this->accessToken->httpRequest(self::TEMPLATE_LIST); + } + + /** + * 删除指定模版 + * @param $template_id + * @return array|bool|mixed + */ + public function delTemplate($template_id) + { + return $this->accessToken->httpRequest(self::DEL_TEMPLATE, ['template_id' => $template_id]); + } + + /** + * 代码上传 + * @param $template_id + * @param string $ext_json + * @param string $user_version + * @param string $user_desc + * @return array|bool|mixed + */ + public function commit($template_id, string $ext_json, string $user_version, string $user_desc = '') + { + return $this->accessToken->httpRequest(self::COMMIT, ['template_id' => $template_id, 'ext_json' => $ext_json, 'user_version' => $user_version, 'user_desc' => $user_desc]); + } + + /** + * 获取已上传代码列表 + * @return array|bool|mixed + */ + public function getPage() + { + return $this->accessToken->httpRequest(self::GET_PAGE, []); + } + + /** + * 获取体验二维码 + * @return array|bool|mixed + */ + public function getQrcode($path = '') + { + return $this->accessToken->httpRequest(self::GET_QRCODE, ['path' => $path], true, 'GET'); + } + + /** + * 提交审核 + * @param array $data + * @param data = [ + * 'item_list' => [],//审核项列表(选填,至多填写 5 项) + * 'preview_info' => (object)[],//预览信息(小程序页面截图和操作录屏) + * 'version_desc' => '',//小程序版本说明和功能解释 + * 'feedback_info' => '',//反馈内容,至多 200 字 + * 'feedback_stuff' => '',//用 | 分割的 media_id 列表,至多 5 张图片, 可以通过新增临时素材接口上传而得到 + * 'ugc_declare' => (object)[],//用户生成内容场景(UGC)信息安全声明 + * ]; + * @return array|bool|mixed + */ + public function submitAudit($data = []) + { + $base = [ + 'item_list' => [], + 'preview_info' => (object)[], + 'version_desc' => '', + 'feedback_info' => '', + 'feedback_stuff' => '', + 'ugc_declare' => (object)[], + ]; + $data = array_merge($base, $data); + return $this->accessToken->httpRequest(self::SUBMIT_AUDIT, $data); + } + + /** + * 查询指定版本的审核状态 + * @param string $auditid + * @return array|bool|mixed + */ + public function getAuditStatus(string $auditid) + { + return $this->accessToken->httpRequest(self::GET_AUDIT_STATUS, ['auditid' => $auditid]); + } + + /** + * 获取最后一次提交审核状态 + * @return array|bool|mixed + */ + public function getLatestAuditStatus() + { + return $this->accessToken->httpRequest(self::GET_LATEST_AUDIT_STATUS, [], true, 'GET'); + } + + /** + * 审核撤回 + * @return array|bool|mixed + */ + public function undoAudit() + { + return $this->accessToken->httpRequest(self::UNDO_CODE_AUDIT, [], true, 'GET'); + } + + /** + * 发布已通过审核小程序 + * @return array|bool|mixed + */ + public function release() + { + return $this->accessToken->httpRequest(self::RELEASE); + } + + /** + * 分阶段发布 + * @param int $gray_percentage 1-100整数 + * @return mixed + */ + public function grayRelease(int $gray_percentage) + { + return $this->accessToken->httpRequest(self::GRAY_RELEASE, ['gray_percentage' => $gray_percentage]); + } + + /** + * 版本回退 + * @return array|bool|mixed + */ + public function revertCodeRelease() + { + return $this->accessToken->httpRequest(self::REVERT_CODE_RELEASE, [], true, 'GET'); + } +} \ No newline at end of file diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/Open3rd/ProgramProvider.php b/demo/thinkphp/backend/phoenix/services/easywechat/Open3rd/ProgramProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..f336ed15b866cec45eb8a79b749d5d156a74f67c --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/Open3rd/ProgramProvider.php @@ -0,0 +1,38 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\easywechat\Open3rd; + +use Pimple\Container; +use Pimple\ServiceProviderInterface; + +/** + * 注册第三方平台 + * Class ProgramProvider + * @package crmeb\utils + */ +class ProgramProvider implements ServiceProviderInterface +{ + public function register(Container $pimple) + { + $pimple['mini_program.component_access_token'] = function ($pimple) { + return new AccessToken( + $pimple['config']['open3rd']['component_appid'], + $pimple['config']['open3rd']['component_appsecret'], + $pimple['config']['open3rd']['component_verify_ticket'], + $pimple['config']['open3rd']['authorizer_appid'] + ); + }; + + $pimple['mini_program.open3rd'] = function ($pimple) { + return new ProgramOpen3rd($pimple['mini_program.component_access_token']); + }; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/miniPayment/ServiceProvider.php b/demo/thinkphp/backend/phoenix/services/easywechat/miniPayment/ServiceProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..f66e6b72958fa20e732ea4e9e466896e9e5eca18 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/miniPayment/ServiceProvider.php @@ -0,0 +1,52 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace crmeb\services\easywechat\miniPayment; + +use EasyWeChat\Payment\Merchant; +use Pimple\Container; +use Pimple\ServiceProviderInterface; +use EasyWeChat\MiniProgram\AccessToken; + +/** + * Class ServiceProvider. + * + * @author mingyoung + */ +class ServiceProvider implements ServiceProviderInterface +{ + /** + * {@inheritdoc}. + */ + public function register(Container $pimple) + { + $pimple['merchant'] = function ($pimple) { + $config = array_merge( + ['app_id' => $pimple['config']['app_id']], + $pimple['config']->get('payment', []) + ); + + return new Merchant($config); + }; + + $pimple['mini_program.access_token'] = function ($pimple) { + return new AccessToken( + $pimple['config']['mini_program']['app_id'], + $pimple['config']['mini_program']['secret'], + $pimple['cache'] + ); + }; + + $pimple['minipay'] = function ($pimple) { + return new WeChatClient($pimple['mini_program.access_token'],$pimple['merchant']); + }; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/miniPayment/WeChatClient.php b/demo/thinkphp/backend/phoenix/services/easywechat/miniPayment/WeChatClient.php new file mode 100644 index 0000000000000000000000000000000000000000..1605b7567cb65bc68f49c864f95da8d304343e12 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/miniPayment/WeChatClient.php @@ -0,0 +1,110 @@ +merchant = $merchant; + } + + /** + * 支付 + * @param array $params [ + * 'openid'=>'支付者的openid', + * 'out_trade_no'=>'商家合单支付总交易单号', + * 'total_fee'=>'支付金额', + * 'wx_out_trade_no'=>'商家交易单号', + * 'body'=>'商品描述', + * 'attach'=>'支付类型', //product 产品 member 会员 + * ] + * @param $isContract + * @return mixed + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function createorder($order) + { + $params = [ + 'openid' => $order['openid'], // 支付者的openid + 'combine_trade_no' => $order['out_trade_no'], // 商家合单支付总交易单号 + 'expire_time' => time() + $this->expire_time, + 'sub_orders' => [ + [ + 'mchid' => $this->merchant->merchant_id, + 'amount' => (int)$order['total_fee'], + 'trade_no' => $order['out_trade_no'], + 'description' => $order['body'] + ] + ] + ]; + return $this->parseJSON('post', [self::API_SET_CREATE_ORDER, json_encode($params)]); + } + + /** + * 退款 + * @param array $params [ + * 'openid'=>'退款者的openid', + * 'trade_no'=>'商家交易单号', + * 'transaction_id'=>'支付单号', + * 'refund_no'=>'商家退款单号', + * 'total_amount'=>'订单总金额', + * 'refund_amount'=>'退款金额', //product 产品 member 会员 + * ] + * @return mixed + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function refundorder(array $order) + { + $params = [ + 'openid' => $order['openid'], + 'mchid' => $this->merchant->merchant_id, + 'trade_no' => $order['trade_no'], + 'transaction_id' => $order['transaction_id'], + 'refund_no' => $order['refund_no'], + 'total_amount' => $order['total_amount'], + 'refund_amount' => $order['refund_amount'], + ]; + return $this->parseJSON('post', [self::API_SET_REFUND_ORDER, json_encode($params)]); + } + + +} \ No newline at end of file diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/oauth2/wechat/WechatOauth.php b/demo/thinkphp/backend/phoenix/services/easywechat/oauth2/wechat/WechatOauth.php new file mode 100644 index 0000000000000000000000000000000000000000..aebb42c7ac7aa0f4f725efb9eecb3cf4a30d4ca5 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/oauth2/wechat/WechatOauth.php @@ -0,0 +1,282 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\easywechat\oauth2\wechat; + +use Doctrine\Common\Cache\Cache; +use Doctrine\Common\Cache\FilesystemCache; +use EasyWeChat\Core\AbstractAPI; +use EasyWeChat\Core\AccessToken; +use EasyWeChat\Core\Exceptions\HttpException; +use EasyWeChat\Core\Http; +use EasyWeChat\Support\Collection; +use GuzzleHttp\Psr7\Uri; +use Psr\Http\Message\RequestInterface; +use Symfony\Component\HttpFoundation\Request; + +/** + * Class WechatOauth + * @package crmeb\services\easywechat\oauth\wechat + */ +class WechatOauth extends AbstractAPI +{ + /** + * 通过code获取网页授权access_token + */ + const API_OAUTH_ACCESS_TOKEN = 'https://api.weixin.qq.com/sns/oauth2/access_token'; + + /** + * 检验授权凭证(access_token)是否有效 + */ + const API_OAUTH_CHECK_TOKEN = 'https://api.weixin.qq.com/sns/auth'; + + /** + * 刷新access_token + */ + const API_OAUTH_REFRESH_TOKEN = 'https://api.weixin.qq.com/sns/oauth2/refresh_token'; + + /** + * 获取用户信息 + */ + const API_OAUTH_GET_USER_INFO = 'https://api.weixin.qq.com/sns/userinfo'; + + + /** + * App ID. + * + * @var string + */ + protected $appId; + + /** + * App secret. + * + * @var string + */ + protected $secret; + + /** + * Cache. + * + * @var Cache + */ + protected $cache; + + protected $openid; + + /** + * @var Request + */ + protected $request; + + /** + * Query name. + * + * @var string + */ + protected $queryName = 'access_token'; + + /** + * Response Json key name. + * + * @var string + */ + protected $tokenJsonKey = 'access_token'; + + + /** + * Response Json key name. + * + * @var string + */ + protected $refreshTokenJsonKey = 'refresh_token'; + + /** + * Cache key prefix. + * + * @var string + */ + protected $prefix = 'easywechat.common.oauth.access_token.'; + + /** + * WechatOauth constructor. + * @param AccessToken $accessToken + * @param $appId + * @param $appSecret + */ + public function __construct(AccessToken $accessToken, $appId, $appSecret) + { + parent::__construct($accessToken); + $this->appId = $appId; + $this->secret = $appSecret; + } + + /** + * @param Request $request + * @return $this + */ + public function setRequest(Request $request) + { + $this->request = $request; + + return $this; + } + + /** + * 获取code + * @return mixed + */ + public function getCode() + { + return $this->request->get('code'); + } + + /** + * 授权获取token + * @param string $code + * @return false|mixed + * @throws HttpException + */ + public function oauth(string $code = '') + { + $params = [ + 'appid' => $this->appId, + 'secret' => $this->secret, + 'code' => $code ?: $this->getCode(), + 'grant_type' => 'authorization_code', + ]; + + $http = new Http(); + + $token = $http->parseJSON($http->get(self::API_OAUTH_ACCESS_TOKEN, $params)); + + if (empty($token[$this->tokenJsonKey])) { + throw new HttpException('Request AccessToken fail. response: ' . json_encode($token, JSON_UNESCAPED_UNICODE)); + } + $this->setCache($token); + + return $token; + } + + /** + * 刷新token + * @param string $refresh_token + * @return false|mixed + * @throws HttpException + */ + public function refreshToken(string $refresh_token) + { + $params = [ + 'appid' => $this->appId, + 'refresh_token' => $refresh_token, + 'grant_type' => 'refresh_token', + ]; + + $http = new Http(); + + $token = $http->parseJSON($http->get(self::API_OAUTH_REFRESH_TOKEN, $params)); + + if (empty($token[$this->tokenJsonKey])) { + throw new HttpException('Request AccessToken fail. response: ' . json_encode($token, JSON_UNESCAPED_UNICODE)); + } + $this->setCache($token); + + return $token; + } + + /** + * 获取用户信息 + * @param $openId + * @param string $lang + * @return Collection|null + * @throws HttpException + */ + public function getUserInfo($openId, $lang = 'zh_CN') + { + $params = [ + 'openid' => $openId, + 'lang' => $lang, + ]; + $this->openid = $openId; + return $this->parseJSON('get', [self::API_OAUTH_GET_USER_INFO, $params]); + } + + /** + * 获取token + * @param false $forceRefresh + * @return bool|mixed|string + * @throws HttpException + */ + public function getToken($forceRefresh = false) + { + $cacheKey = $this->prefix; + $cached = $this->getCache()->fetch($cacheKey . $this->tokenJsonKey . $this->openid); + + if ($forceRefresh || !$cached) { + $refreshCached = $this->getCache()->fetch($cacheKey . $this->refreshTokenJsonKey . $this->openid); + if ($refreshCached) { + $token = $this->refreshToken($refreshCached); + + return $token[$this->tokenJsonKey]; + } + return ''; + } + + return $cached; + } + + /** + * 保存token信息 + * @param $token + * @return bool + */ + public function setCache($token) + { + $cacheKey = $this->prefix; + // XXX: T_T... 7200 - 1500 + $this->getCache()->save($cacheKey . $this->tokenJsonKey . $token['openid'], $token[$this->tokenJsonKey], $token['expires_in'] - 1500); + $this->getCache()->save($cacheKey . $this->refreshTokenJsonKey . $token['openid'], $token[$this->refreshTokenJsonKey], 30 * 24 * 3600); + return true; + } + + /** + * Return the cache manager. + * + * @return \Doctrine\Common\Cache\Cache + */ + public function getCache() + { + return $this->cache ?: $this->cache = new FilesystemCache(sys_get_temp_dir()); + } + + /** + * Attache access token to request query. + * + * @return \Closure + */ + protected function accessTokenMiddleware() + { + return function (callable $handler) { + return function (RequestInterface $request, array $options) use ($handler) { + $token = $this->getToken(); + if (!$token) { + return $handler($request, $options); + } + + $request = $request->withUri(Uri::withQueryValue($request->getUri(), $this->queryName, $token)); + + return $handler($request, $options); + }; + }; + } + + +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/oauth2/wechat/WechatOauth2Provider.php b/demo/thinkphp/backend/phoenix/services/easywechat/oauth2/wechat/WechatOauth2Provider.php new file mode 100644 index 0000000000000000000000000000000000000000..27c00f6e8a163d85181b87fa6f3d405d4ffd601a --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/oauth2/wechat/WechatOauth2Provider.php @@ -0,0 +1,51 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\easywechat\oauth2\wechat; + + +use crmeb\services\SystemConfigService; +use Pimple\Container; +use Pimple\ServiceProviderInterface; +use think\facade\Request; + +/** + * 微信网页授权 + * Class WechatOauthProvider + * @package crmeb\services\easywechat\oauth\wechat + * @method oauth(string $code = '') code授权获取acces_token openid + * @method getUserInfo($openId, $lang = 'zh_CN') openid 获取用户信息 + * @method setRequest(Request $request) 设置request对象 + */ +class WechatOauth2Provider implements ServiceProviderInterface +{ + + /** + * + * @param Container $pimple + */ + public function register(Container $pimple) + { + $request = app('request'); + $wechat = SystemConfigService::more(['wechat_appid', 'wechat_app_appid', 'wechat_app_appsecret', 'wechat_appsecret']); + if ($request->isApp()) { + $appId = isset($wechat['wechat_app_appid']) ? trim($wechat['wechat_app_appid']) : ''; + $appsecret = isset($wechat['wechat_app_appsecret']) ? trim($wechat['wechat_app_appsecret']) : ''; + } else { + $appId = isset($wechat['wechat_appid']) ? trim($wechat['wechat_appid']) : ''; + $appsecret = isset($wechat['wechat_appsecret']) ? trim($wechat['wechat_appsecret']) : ''; + } + + $pimple['oauth2'] = function ($pimple) use ($appId, $appsecret) { + return new WechatOauth($pimple['access_token'], $appId, $appsecret); + }; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/BaseOrder.php b/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/BaseOrder.php new file mode 100644 index 0000000000000000000000000000000000000000..def23811c74b00fa400a1685ffc70f525ea2d97a --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/BaseOrder.php @@ -0,0 +1,201 @@ +config = $config; + $this->accessToken = $accessToken; + } + + private function resultHandle(Collection $result) + { + if (empty($result)) { + throw new AdminException('微信接口返回异常'); + } + $res = $result->toArray(); + if ($res['errcode'] == 0) { + return $res; + } else { + throw new AdminException("微信接口异常:code = {$res['errcode']} msg = {$res['errmsg']}"); + } + } + + + /** + * request. + * + * @param string $endpoint + * @param string $method + * @param array $options + * @param bool $returnResponse + */ + public function request(string $method, string $endpoint, array $options = []) + { + + if (isset($options['json'])) { + $body = json_encode($options['json']); + $options['body'] = $body; + unset($options['json']); + } + + $headers = [ + 'Content-Type' => 'text/plain', + 'User-Agent' => 'curl', + 'Accept' => 'text/plain', + ]; + + $options['headers'] = array_merge($headers, ($options['headers'] ?? [])); + + + return $this->_doRequestCurl($method, self::BASE_API . $endpoint, $options); + } + + /** + * @param $method + * @param $location + * @param array $options + * @return mixed + */ + private function _doRequestCurl($method, $location, $options = []) + { + //拼接$accessToken + $location .= $this->accessToken->getToken(); + var_dump($location); + $curl = curl_init(); + // POST数据设置 + if (strtolower($method) === 'post') { + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $options['data'] ?? $options['body'] ?? ''); + } + // CURL头信息设置 + if (!empty($options['headers'])) { + $headers = []; + foreach ($options['headers'] as $k => $v) { + $headers[] = "$k: $v"; + } + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + } + curl_setopt($curl, CURLOPT_URL, $location); + curl_setopt($curl, CURLOPT_HEADER, true); + curl_setopt($curl, CURLOPT_TIMEOUT, 60); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); + $content = curl_exec($curl); + $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE); + curl_close($curl); + return json_decode(substr($content, $headerSize), true); + } + + /** + * 发货 + * @param $params + * @return array + * @throws \EasyWeChat\Core\Exceptions\HttpException + * + * @date 2023/05/09 + * @author yyw + */ + public function shipping($params) + { + return $this->resultHandle($this->parseJSON('POST', [self::BASE_API . self::ORDER . 'upload_shipping_info', json_encode($params, JSON_UNESCAPED_UNICODE)])); + } + + /** + * 合单 + * @param $params + * @return array + * @throws \EasyWeChat\Core\Exceptions\HttpException + * + * @date 2023/05/09 + * @author yyw + */ + public function combinedShipping($params) + { + return $this->resultHandle($this->parseJSON('POST', [self::BASE_API . self::ORDER . 'upload_combined_shipping_info', json_encode($params)])); + } + + + /** + * 签收消息提醒 + * @param $params + * @return array + * @throws \EasyWeChat\Core\Exceptions\HttpException + * + * @date 2023/05/09 + * @author yyw + */ + public function notifyConfirm($params) + { + return $this->resultHandle($this->parseJSON('POST', [self::BASE_API . self::ORDER . 'notify_confirm_receive', json_encode($params)])); + } + + + /** + * 查询小程序是否已开通发货信息管理服务 + * @return array + * @throws \EasyWeChat\Core\Exceptions\HttpException + * + * @date 2023/05/09 + * @author yyw + */ + public function isManaged() + { + $params = [ + 'appid' => $this->config['config']['mini_program']['app_id'] + ]; + return $this->resultHandle($this->parseJSON('POST', [self::BASE_API . self::ORDER . 'is_trade_managed', json_encode($params)])); + } + + /** + * 设置跳转连接 + * @param $path + * @return array + * @throws \EasyWeChat\Core\Exceptions\HttpException + * + * @date 2023/05/10 + * @author yyw + */ + public function setMesJumpPath($path) + { + $params = [ + 'path' => $path + ]; + return $this->resultHandle($this->parseJSON('POST', [self::BASE_API . self::ORDER . 'set_msg_jump_path', json_encode($params)])); + } + + /** + * 获取运力id列表get_delivery_list + * @return array + * @throws \EasyWeChat\Core\Exceptions\HttpException + * + * @date 2023/05/09 + * @author yyw + */ + public function getDeliveryList() + { + return $this->resultHandle($this->parseJSON('POST', [self::BASE_API . self::EXPRESS . 'get_delivery_list', "{}"])); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/MiniOrderService.php b/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/MiniOrderService.php new file mode 100644 index 0000000000000000000000000000000000000000..c7ddf146179db5e687aa6e79008695b7b6cb0812 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/MiniOrderService.php @@ -0,0 +1,135 @@ + isset($payment['wechat_token']) ? trim($payment['wechat_token']) : '', + 'aes_key' => isset($payment['wechat_encodingaeskey']) ? trim($payment['wechat_encodingaeskey']) : '', + 'mini_program' => [ + 'app_id' => $payment['routine_appId'] ?? '', + 'secret' => $payment['routine_appsecret'] ?? '', + 'merchant_id' => empty($payment['pay_new_weixin_open']) ? trim($payment['pay_weixin_mchid']) : trim($payment['pay_new_weixin_mchid']), + ] + ]; + } + + /** + * 初始化 + * @param bool $cache + * @return Application + */ + protected static function application($cache = false) + { + (self::$instance === null || $cache === true) && (self::$instance = new Application(self::options())); + return self::$instance; + } + + protected static function order() + { + return self::application()->order_ship; + } + + + /** + * 上传订单 + * @param string $out_trade_no 订单号(商城订单好) + * @param int $logistics_type 物流模式,发货方式枚举值:1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品,虚拟商品,例如话费充值,点卡等,无实体配送形式 4、用户自提 + * @param array $shipping_list 物流信息列表,发货物流单列表,支持统一发货(单个物流单)和分拆发货(多个物流单)两种模式,多重性: [1, 10] + * @param string $payer_openid 支付者,支付者信息 + * @param int $delivery_mode 发货模式,发货模式枚举值:1、UNIFIED_DELIVERY(统一发货)2、SPLIT_DELIVERY(分拆发货) 示例值: UNIFIED_DELIVERY + * @param bool $is_all_delivered 分拆发货模式时必填,用于标识分拆发货模式下是否已全部发货完成,只有全部发货完成的情况下才会向用户推送发货完成通知。示例值: true/false + * @return array + * + * @throws HttpException + * @date 2023/05/09 + * @author yyw + */ + public static function shippingByTradeNo(string $out_trade_no, int $logistics_type, array $shipping_list, string $payer_openid, string $path, int $delivery_mode = 1, bool $is_all_delivered = true) + { + return self::order()->shippingByTradeNo($out_trade_no, $logistics_type, $shipping_list, $payer_openid, $path, $delivery_mode, $is_all_delivered); + } + + /** + * 合单 + * @param string $out_trade_no + * @param int $logistics_type + * @param array $sub_orders + * @param string $payer_openid + * @param int $delivery_mode + * @param bool $is_all_delivered + * @return array + * @throws HttpException + * + * @date 2023/05/10 + * @author yyw + */ + public static function combinedShippingByTradeNo(string $out_trade_no, int $logistics_type, array $sub_orders, string $payer_openid, int $delivery_mode = 2, bool $is_all_delivered = false) + { + return self::order()->combinedShippingByTradeNo($out_trade_no, $logistics_type, $sub_orders, $payer_openid, $delivery_mode, $is_all_delivered); + } + + /** + * 签收通知 + * @param string $merchant_trade_no + * @param string $received_time + * @return array + * + * @date 2023/05/09 + * @author yyw + */ + public static function notifyConfirmByTradeNo(string $merchant_trade_no, string $received_time) + { + return self::order()->notifyConfirmByTradeNo($merchant_trade_no, $received_time); + } + + /** + * 判断是否开通 + * @return bool + * @throws HttpException + * + * @date 2023/05/17 + * @author yyw + */ + public static function isManaged() + { + return self::order()->checkManaged(); + } + + + /** + * 设置小修跳转路径 + * @param $path + * @return array + * @throws HttpException + * + * @date 2023/05/10 + * @author yyw + */ + public static function setMesJumpPathAndCheck($path) + { + return self::order()->setMesJumpPathAndCheck($path); + } + + +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/OrderClient.php b/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/OrderClient.php new file mode 100644 index 0000000000000000000000000000000000000000..ef226a65154f89c373f6d3cec929f9002431c2a3 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/OrderClient.php @@ -0,0 +1,294 @@ +redis)) { + $this->redis = Cache::store('redis')->handler(); + } + return $this->redis; + } + + /** + * 处理联系人 + * @param array $contact + * @return array + * + * @date 2023/05/10 + * @author yyw + */ + protected function handleContact(array $contact = []): array + { + if (isset($contact)) { + if (isset($contact['consignor_contact']) && $contact['consignor_contact']) { + $contact['consignor_contact'] = Utility::encryptTel($contact['consignor_contact']); + } + if (isset($contact['receiver_contact']) && $contact['receiver_contact']) { + $contact['receiver_contact'] = Utility::encryptTel($contact['receiver_contact']); + } + } + return $contact; + } + + /** + * 发货 + * @param string $out_trade_no + * @param int $logistics_type + * @param array $shipping_list + * @param string $payer_openid + * @param int $delivery_mode + * @param bool $is_all_delivered + * @return array + * @throws HttpException + * + * @date 2023/05/10 + * @author yyw + */ + public function shippingByTradeNo(string $out_trade_no, int $logistics_type, array $shipping_list, string $payer_openid, $path, int $delivery_mode = 1, bool $is_all_delivered = true) + { + if (!$this->checkManaged()) { + throw new AdminException('开通小程序订单管理服务后重试'); + } + $params = [ + 'order_key' => [ + 'order_number_type' => 1, + 'mchid' => $this->config['config']['mini_program']['merchant_id'], + 'out_trade_no' => $out_trade_no, + ], + 'logistics_type' => $logistics_type, + 'delivery_mode' => $delivery_mode, + 'upload_time' => date(DATE_RFC3339), + 'payer' => [ + 'openid' => $payer_openid + ] + ]; + if ($delivery_mode == 2) { + $params['is_all_delivered'] = $is_all_delivered; + } + + foreach ($shipping_list as $shipping) { + $contact = $this->handleContact($shipping['contact'] ?? []); + $params['shipping_list'][] = [ + 'tracking_no' => $shipping['tracking_no'] ?? '', + 'express_company' => isset($shipping['express_company']) ? $this->getDelivery($shipping['express_company']) : '', + 'item_desc' => $shipping['item_desc'], + 'contact' => $contact + ]; + } + // 跳转路径 +// $this->setMesJumpPath($path); + return $this->shipping($params); + } + + + /** + * 合单 + * @param string $out_trade_no + * @param int $logistics_type + * @param array $sub_orders + * @param string $payer_openid + * @param int $delivery_mode + * @param bool $is_all_delivered + * @return array + * @throws HttpException + * + * @date 2023/05/10 + * @author yyw + */ + public function combinedShippingByTradeNo(string $out_trade_no, int $logistics_type, array $sub_orders, string $payer_openid, int $delivery_mode = 2, bool $is_all_delivered = false) + { + if (!$this->checkManaged()) { + throw new AdminException('开通小程序订单管理服务后重试'); + } + $params = [ + 'order_key' => [ + 'order_number_type' => 1, + 'mchid' => $this->config['config']['mini_program']['merchant_id'], + 'out_trade_no' => $out_trade_no, + ], + 'upload_time' => date(DATE_RFC3339), + 'payer' => [ + 'openid' => $payer_openid + ] + ]; + + foreach ($sub_orders as $order) { + $sub_order = [ + 'order_key' => [ + 'order_number_type' => 1, + 'mchid' => $this->config['config']['mini_program']['merchant_id'], + 'out_trade_no' => $order['out_trade_no'], + 'logistics_type' => $logistics_type, + ], + 'delivery_mode' => $delivery_mode, + 'is_all_delivered' => $is_all_delivered + ]; + foreach ($sub_orders['shipping_list'] as $shipping) { + $contact = $this->handleContact($shipping['contact'] ?? []); + $sub_order['shipping_list'][] = [ + 'tracking_no' => $shipping['tracking_no'] ?? '', + 'express_company' => isset($shipping['express_company']) ? $this->getDelivery($shipping['express_company']) : '', + 'item_desc' => $shipping['item_desc'], + 'contact' => $contact + ]; + } + $params['sub_orders'][] = $sub_order; + } + + return $this->combinedShipping($params); + } + + + /** + * 签收通知 + * @param string $merchant_trade_no + * @param string $received_time + * @return array + * @throws HttpException + * + * @date 2023/05/10 + * @author yyw + */ + public function notifyConfirmByTradeNo(string $merchant_trade_no, string $received_time) + { + $params = [ + 'merchant_id' => $this->config['config']['mini_program']['merchant_id'], + 'merchant_trade_no' => $merchant_trade_no, + 'received_time' => $received_time + ]; + return $this->notifyConfirm($params); + } + + /** + * 设置跳转连接 + * @param $path + * @return array + * @throws \EasyWeChat\Core\Exceptions\HttpException + * + * @date 2023/05/10 + * @author yyw + */ + public function setMesJumpPathAndCheck($path) + { + if (!$this->checkManaged()) { + throw new AdminException('开通小程序订单管理服务后重试'); + } + return $this->setMesJumpPath($path); + } + + /** + * 设置小程序管理服务开通状态 + * @return bool + * @throws HttpException + * + * @date 2023/05/09 + * @author yyw + */ + public function setManaged() + { + $res = $this->isManaged(); + if ($res['is_trade_managed']) { + $key = self::redis_prefix . '_is_trade_managed'; + $this->getRedis()->set($key, $res['is_trade_managed']); + return true; + } else { + return false; + } + + } + + /** + * @return bool + * @throws HttpException + * + * @date 2023/05/10 + * @author yyw + */ + public function checkManaged() + { + $key = self::redis_prefix . '_is_trade_managed'; + if ($this->getRedis()->exists($key)) { + return true; + } else { + return $this->setManaged(); + } + } + + /** + * 同步去微信物流列表 + * @return array + * @throws HttpException + * + * @date 2023/05/10 + * @author yyw + */ + public function setDeliveryList() + { + $list = $this->getDeliveryList(); + if ($list) { + $key = self::redis_prefix . '_delivery_list'; + $date = array_column($list['delivery_list'], 'delivery_id', 'delivery_name'); + // 创建缓存 + $this->getRedis()->hMSet($key, $date); + + return $date; + } else { + throw new AdminException('物流公司列表异常'); + } + } + + /** + * 获取物流公司编码 + * @param $company_name + * @return array|mixed + * @throws HttpException + * + * @date 2023/05/10 + * @author yyw + */ + public function getDelivery($company_name) + { + $key = self::redis_prefix . '_delivery_list'; + if (!$this->getRedis()->exists($key)) { + $date = $this->setDeliveryList(); + if (!isset($date[$company_name])) { +// throw new AdminException('物流公司异常1'); + } + $express_company = $date[$company_name]; + } else { + $express_company = $this->getRedis()->hMGet($key, [$company_name])[$company_name] ?? ''; + } + if (empty($express_company)) { +// throw new AdminException('物流公司异常2'); + $express_company = self::express_company; + } + + return $express_company; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/ServiceProvider.php b/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/ServiceProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..8307dbc7189a356f5c0e1785361a72b49bb5cb72 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/ServiceProvider.php @@ -0,0 +1,43 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace crmeb\services\easywechat\orderShipping; + +use EasyWeChat\Payment\Merchant; +use Pimple\Container; +use Pimple\ServiceProviderInterface; +use EasyWeChat\MiniProgram\AccessToken; + +/** + * Class ServiceProvider. + * + * @package crmeb\services\easywechat\order_ship + * @package crmeb\services\easywechat\mini_express + */ +class ServiceProvider implements ServiceProviderInterface +{ + /** + * {@inheritdoc}. + */ + public function register(Container $pimple) + { + $pimple['mini_program.access_token'] = function ($pimple) { + return new AccessToken( + $pimple['config']['mini_program']['app_id'], + $pimple['config']['mini_program']['secret'], + $pimple['cache'] + ); + }; + $pimple['order_ship'] = function ($pimple) { + return new OrderClient($pimple['mini_program.access_token'], $pimple); + }; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/Utility.php b/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/Utility.php new file mode 100644 index 0000000000000000000000000000000000000000..5cb8d33c0111a0fb89fb48e1546955b417f7b078 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/orderShipping/Utility.php @@ -0,0 +1,42 @@ +getPublicKey(), $padding)) { + throw new AdminException('Encrypting the input $plaintext failed, please checking your $publicKey whether or nor correct.'); + } + + return base64_encode($encrypted); + } + + public static function encryptTel($tel) + { + $new_tel = substr_replace($tel, '****', 3, 4); + return $new_tel; + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/subscribe/ProgramProvider.php b/demo/thinkphp/backend/phoenix/services/easywechat/subscribe/ProgramProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..129bdb50f70dad5c183fdf7c1b57c70805571d69 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/subscribe/ProgramProvider.php @@ -0,0 +1,38 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\easywechat\subscribe; + +use EasyWeChat\MiniProgram\AccessToken; +use Pimple\Container; +use Pimple\ServiceProviderInterface; + +/** + * 注册订阅消息 + * Class ProgramProvider + * @package crmeb\utils + */ +class ProgramProvider implements ServiceProviderInterface +{ + public function register(Container $pimple) + { + $pimple['mini_program.access_token'] = function ($pimple) { + return new AccessToken( + $pimple['config']['mini_program']['app_id'], + $pimple['config']['mini_program']['secret'], + $pimple['cache'] + ); + }; + + $pimple['mini_program.now_notice'] = function ($pimple) { + return new ProgramSubscribe($pimple['mini_program.access_token']); + }; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/subscribe/ProgramSubscribe.php b/demo/thinkphp/backend/phoenix/services/easywechat/subscribe/ProgramSubscribe.php new file mode 100644 index 0000000000000000000000000000000000000000..4665a3ef60eaed8bd9791fcc176b3244ec357213 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/subscribe/ProgramSubscribe.php @@ -0,0 +1,283 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\easywechat\subscribe; + +use EasyWeChat\Core\AbstractAPI; +use EasyWeChat\Core\AccessToken; +use EasyWeChat\Core\Exceptions\InvalidArgumentException; + +/** + * 小程序订阅消息 + * Class ProgramSubscribe + * @package crmeb\utils + * @method $this + * @method $this template(string $template_id) 设置模板id + * @method $this withTemplateId(string $template_id) 设置模板id + * @method $this andTemplateId(string $template_id) 设置模板id + * @method $this andTemplate(string $template_id) 设置模板id + * @method $this andUses(string $template_id) 设置模板id + * @method $this to(string $touser) 设置opendid + * @method $this andReceiver(string $touser) 设置opendid + * @method $this withReceiver(string $touser) 设置opendid + * @method $this with(array $data) 设置发送内容 + * @method $this andData(array $data) 设置发送内容 + * @method $this withData(array $data) 设置发送内容 + * @method $this data(array $data) 设置发送内容 + * @method $this withUrl(string $page) 设置跳转路径 + */ +class ProgramSubscribe extends AbstractAPI +{ + + /** + * 添加模板接口 + */ + const API_SET_TEMPLATE_ADD = 'https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate'; + + /** + * 删除模板消息接口 + */ + const API_SET_TEMPLATE_DEL = 'https://api.weixin.qq.com/wxaapi/newtmpl/deltemplate'; + + /** + * 获取模板消息列表 + */ + const API_GET_TEMPLATE_LIST = 'https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate'; + + /** + * 获取模板消息分类 + */ + const API_GET_TEMPLATE_CATE = 'https://api.weixin.qq.com/wxaapi/newtmpl/getcategory'; + + /** + * 获取模板消息关键字 + */ + const API_GET_TEMPLATE_KEYWORKS = 'https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatekeywords'; + + /** + * 获取公共模板 + */ + const API_GET_PUBLIC_TEMPLATE = 'https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatetitles'; + + /** + * 发送模板消息 + */ + const API_SUBSCRIBE_SEND = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send'; + + /** + * Attributes + * @var array + */ + protected $message = [ + 'touser' => '', + 'template_id' => '', + 'page' => '', + 'data' => [], + ]; + + /** + * Message backup. + * + * @var array + */ + protected $messageBackup; + + protected $required = ['template_id', 'touser']; + + /** + * ProgramSubscribeService constructor. + * @param AccessToken $accessToken + */ + public function __construct(AccessToken $accessToken) + { + parent::__construct($accessToken); + + $this->messageBackup = $this->message; + + } + + /** + * 获取当前拥有的模板列表 + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function getTemplateList() + { + return $this->parseJSON('get', [self::API_GET_TEMPLATE_LIST]); + } + + /** + * 获取公众模板列表 + * @param string $ids + * @param int $start + * @param int $limit + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function getPublicTemplateList(string $ids, int $start = 0, int $limit = 10) + { + $params = [ + 'ids' => $ids, + 'start' => $start, + 'limit' => $limit + ]; + return $this->parseJSON('get', [self::API_GET_PUBLIC_TEMPLATE, $params]); + } + + /** + * 获取模板分类 + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function getTemplateCate() + { + return $this->parseJSON('get', [self::API_GET_TEMPLATE_CATE]); + } + + /** + * 获取模板标题下的关键词列表 + * @param string $tid 模板标题 id,可通过接口获取 + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function getPublicTemplateKeywords(string $tid) + { + $params = [ + 'tid' => $tid + ]; + return $this->parseJSON('get', [self::API_GET_TEMPLATE_KEYWORKS, $params]); + } + + /** + * 添加订阅模板消息 + * @param string $tid 模板标题 id,可通过接口获取,也可登录小程序后台查看获取 + * @param array $kidList 模板序列号 关键词顺序可以自由搭配(例如 [3,5,4] 或 [4,5,3]),最多支持5个,最少2个关键词组合 + * @param string $sceneDesc 服务场景描述,15个字以内 + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function addTemplate(string $tid, array $kidList, string $sceneDesc = '') + { + $params = [ + 'tid' => $tid, + 'kidList' => $kidList, + 'sceneDesc' => $sceneDesc, + ]; + return $this->parseJSON('json', [self::API_SET_TEMPLATE_ADD, $params]); + } + + /** + * 删除模板消息 + * @param string $priTmplId + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function delTemplate(string $priTmplId) + { + $params = [ + 'priTmplId' => $priTmplId + ]; + return $this->parseJSON('json', [self::API_SET_TEMPLATE_DEL, $params]); + } + + /** + * 发送订阅消息 + * @param array $data + * @return \EasyWeChat\Support\Collection|null + * @throws InvalidArgumentException + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function send(array $data = []) + { + $params = array_merge($this->message, $data); + + foreach ($params as $key => $value) { + if (in_array($key, $this->required, true) && empty($value) && empty($this->message[$key])) { + throw new InvalidArgumentException("Attribute '$key' can not be empty!"); + } + + $params[$key] = empty($value) ? $this->message[$key] : $value; + } + + $params['data'] = $this->formatData($params['data']); + + $this->message = $this->messageBackup; + + return $this->parseJSON('json', [self::API_SUBSCRIBE_SEND, $params]); + } + + /** + * 设置订阅消息发送data + * @param array $data + * @return array + */ + protected function formatData(array $data) + { + $return = []; + + foreach ($data as $key => $item) { + if (is_scalar($item)) { + $value = $item; + } elseif (is_array($item) && !empty($item)) { + if (isset($item['value'])) { + $value = strval($item['value']); + } elseif (count($item) < 2) { + $value = array_shift($item); + } else { + [$value] = $item; + } + } else { + $value = 'error data item.'; + } + + $return[$key] = ['value' => $value]; + } + + return $return; + } + + + /** + * Magic access.. + * + * @param $method + * @param $args + * @return $this + */ + public function __call($method, $args) + { + $map = [ + 'template' => 'template_id', + 'templateId' => 'template_id', + 'uses' => 'template_id', + 'to' => 'touser', + 'receiver' => 'touser', + 'url' => 'page', + 'link' => 'page', + 'data' => 'data', + 'with' => 'data', + ]; + + if (0 === stripos($method, 'with') && strlen($method) > 4) { + $method = lcfirst(substr($method, 4)); + } + + if (0 === stripos($method, 'and')) { + $method = lcfirst(substr($method, 3)); + } + + if (isset($map[$method])) { + $this->message[$map[$method]] = array_shift($args); + } + + return $this; + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/v3pay/BaseClient.php b/demo/thinkphp/backend/phoenix/services/easywechat/v3pay/BaseClient.php new file mode 100644 index 0000000000000000000000000000000000000000..4846541797abaf01f7fa05bf3e97b5dd9ebdca27 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/v3pay/BaseClient.php @@ -0,0 +1,280 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\services\easywechat\v3pay; + + +use crmeb\exceptions\PayException; +use crmeb\services\easywechat\Application; +use EasyWeChat\Core\AbstractAPI; +use EasyWeChat\Core\AccessToken; +use EasyWeChat\Core\Exceptions\HttpException; +use EasyWeChat\Core\Exceptions\InvalidConfigException; +use EasyWeChat\Core\Http; +use EasyWeChat\Encryption\EncryptionException; +use think\exception\InvalidArgumentException; + + +class BaseClient extends AbstractAPI +{ + + use Certficates; + + /** + * @var Application + */ + protected $app; + + const BASE_URL = 'https://api.mch.weixin.qq.com/'; + + const KEY_LENGTH_BYTE = 32; + + const AUTH_TAG_LENGTH_BYTE = 16; + + /** + * BaseClient constructor. + * @param AccessToken $accessToken + * @param $app + */ + public function __construct(AccessToken $accessToken, $app) + { + parent::__construct($accessToken); + $this->app = $app; + } + + /** + * request. + * + * @param string $endpoint + * @param string $method + * @param array $options + * @param bool $returnResponse + */ + public function request(string $endpoint, string $method = 'POST', array $options = [], $serial = true) + { + $body = $options['body'] ?? ''; + + if (isset($options['json'])) { + $body = json_encode($options['json']); + $options['body'] = $body; + unset($options['json']); + } + + $headers = [ + 'Content-Type' => 'application/json', + 'User-Agent' => 'curl', + 'Accept' => 'application/json', + 'Authorization' => $this->getAuthorization($endpoint, $method, $body), + ]; + + $options['headers'] = array_merge($headers, ($options['headers'] ?? [])); + + if ($serial) { + $options['headers']['Wechatpay-Serial'] = $this->getCertficatescAttr('serial_no'); + } + + return $this->_doRequestCurl($method, self::BASE_URL . $endpoint, $options); + } + + /** + * @param $method + * @param $location + * @param array $options + * @return mixed + */ + private function _doRequestCurl($method, $location, $options = []) + { + $curl = curl_init(); + // POST数据设置 + if (strtolower($method) === 'post') { + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $options['data'] ?? $options['body'] ?? ''); + } + // CURL头信息设置 + if (!empty($options['headers'])) { + $headers = []; + foreach ($options['headers'] as $k => $v) { + $headers[] = "$k: $v"; + } + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + } + curl_setopt($curl, CURLOPT_URL, $location); + curl_setopt($curl, CURLOPT_HEADER, true); + curl_setopt($curl, CURLOPT_TIMEOUT, 60); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); + $content = curl_exec($curl); + $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE); + curl_close($curl); + return json_decode(substr($content, $headerSize), true); + } + + /** + * To id card, mobile phone number and other fields sensitive information encryption. + * + * @param string $string + * + * @return string + */ + protected function encryptSensitiveInformation(string $string) + { + $certificates = $this->app->certficates->get()['certificates']; + if (null === $certificates) { + throw new InvalidConfigException('config certificate connot be empty.'); + } + $encrypted = ''; + if (openssl_public_encrypt($string, $encrypted, $certificates, OPENSSL_PKCS1_OAEP_PADDING)) { + //base64编码 + $sign = base64_encode($encrypted); + } else { + throw new EncryptionException('Encryption of sensitive information failed'); + } + return $sign; + } + + + /** + * @param string $url + * @param string $method + * @param string $body + * @return string + */ + protected function getAuthorization(string $url, string $method, string $body) + { + $nonceStr = uniqid(); + $timestamp = time(); + $message = $method . "\n" . + '/' . $url . "\n" . + $timestamp . "\n" . + $nonceStr . "\n" . + $body . "\n"; + openssl_sign($message, $raw_sign, $this->getPrivateKey(), 'sha256WithRSAEncryption'); + $sign = base64_encode($raw_sign); + $schema = 'WECHATPAY2-SHA256-RSA2048 '; + $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', + $this->app['config']['v3_payment']['mchid'], $nonceStr, $timestamp, $this->app['config']['v3_payment']['serial_no'], $sign); + return $schema . $token; + } + + /** + * 获取商户私钥 + * @return bool|resource + */ + protected function getPrivateKey() + { + $key_path = $this->app['config']['v3_payment']['key_path']; + if (!file_exists($key_path)) { + throw new \InvalidArgumentException( + "SSL certificate not found: {$key_path}" + ); + } + return openssl_pkey_get_private(file_get_contents($key_path)); + } + + /** + * 获取商户公钥 + * @return bool|resource + */ + protected function getPublicKey() + { + $key_path = $this->app['config']['v3_payment']['cert_path']; + if (!file_exists($key_path)) { + throw new \InvalidArgumentException( + "SSL certificate not found: {$key_path}" + ); + } + return openssl_pkey_get_public(file_get_contents($key_path)); + } + + /** + * 替换url + * @param string $url + * @param $search + * @param $replace + * @return array|string|string[] + */ + public function getApiUrl(string $url, $search, $replace) + { + $newSearch = []; + foreach ($search as $key) { + $newSearch[] = '{' . $key . '}'; + } + return str_replace($newSearch, $replace, $url); + } + + /** + * @param int $padding + */ + private static function paddingModeLimitedCheck(int $padding): void + { + if (!($padding === OPENSSL_PKCS1_OAEP_PADDING || $padding === OPENSSL_PKCS1_PADDING)) { + throw new PayException(sprintf("Doesn't supported padding mode(%d), here only support OPENSSL_PKCS1_OAEP_PADDING or OPENSSL_PKCS1_PADDING.", $padding)); + } + } + + /** + * 加密数据 + * @param string $plaintext + * @param int $padding + * @return string + */ + public function encryptor(string $plaintext, int $padding = OPENSSL_PKCS1_OAEP_PADDING) + { + self::paddingModeLimitedCheck($padding); + + if (!openssl_public_encrypt($plaintext, $encrypted, $this->getPublicKey(), $padding)) { + throw new PayException('Encrypting the input $plaintext failed, please checking your $publicKey whether or nor correct.'); + } + + return base64_encode($encrypted); + } + + /** + * decrypt ciphertext. + * + * @param array $encryptCertificate + * + * @return string + */ + public function decrypt(array $encryptCertificate) + { + $ciphertext = base64_decode($encryptCertificate['ciphertext'], true); + $associatedData = $encryptCertificate['associated_data']; + $nonceStr = $encryptCertificate['nonce']; + $aesKey = $this->app['config']['v3_payment']['key']; + + try { + // ext-sodium (default installed on >= PHP 7.2) + if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') && \sodium_crypto_aead_aes256gcm_is_available()) { + return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey); + } + // ext-libsodium (need install libsodium-php 1.x via pecl) + if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') && \Sodium\crypto_aead_aes256gcm_is_available()) { + return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey); + } + // openssl (PHP >= 7.1 support AEAD) + if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) { + $ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE); + $authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE); + return \openssl_decrypt($ctext, 'aes-256-gcm', $aesKey, \OPENSSL_RAW_DATA, $nonceStr, $authTag, $associatedData); + } + } catch (\Exception $exception) { + throw new InvalidArgumentException($exception->getMessage(), $exception->getCode()); + } catch (\SodiumException $exception) { + throw new InvalidArgumentException($exception->getMessage(), $exception->getCode()); + } + throw new InvalidArgumentException('AEAD_AES_256_GCM 需要 PHP 7.1 以上或者安装 libsodium-php'); + } +} + diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/v3pay/Certficates.php b/demo/thinkphp/backend/phoenix/services/easywechat/v3pay/Certficates.php new file mode 100644 index 0000000000000000000000000000000000000000..3776d956372d166351abd0197ba54b4d1a827bac --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/v3pay/Certficates.php @@ -0,0 +1,68 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\services\easywechat\v3pay; + + +use crmeb\exceptions\PayException; +use think\facade\Cache; + +/** + * Class Certficates + * @package crmeb\services\easywechat\v3pay + */ +trait Certficates +{ + + /** + * @param string|null $key + * @return array|mixed|null + * @throws \Psr\SimpleCache\InvalidArgumentException + */ + public function getCertficatescAttr(string $key = null) + { + $driver = Cache::store('file'); + $cacheKey = '_wx_v3' . $this->app['config']['v3_payment']['serial_no']; + if ($driver->has($cacheKey)) { + $res = $driver->get($cacheKey); + if ($key && $res) { + return $res[$key] ?? null; + } else { + return $res; + } + } + $certficates = $this->getCertficates(); + $driver->set($cacheKey, $certficates, 3600 * 24 * 30); + if ($key && $certficates) { + return $certficates[$key] ?? null; + } + return $certficates; + } + + /** + * get certficates. + * + * @return array + */ + public function getCertficates() + { + $response = $this->request('v3/certificates', 'GET', [], false); + if (isset($response['code'])) { + throw new PayException($response['message']); + } + $certificates = $response['data'][0]; + $certificates['certificates'] = $this->decrypt($certificates['encrypt_certificate']); + unset($certificates['encrypt_certificate']); + return $certificates; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/v3pay/PayClient.php b/demo/thinkphp/backend/phoenix/services/easywechat/v3pay/PayClient.php new file mode 100644 index 0000000000000000000000000000000000000000..a9dd78bdd1a0d1d22a737668d5c455c88acd6cb1 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/v3pay/PayClient.php @@ -0,0 +1,433 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\services\easywechat\v3pay; + + +use crmeb\exceptions\PayException; +use crmeb\services\wechat\Payment; +use EasyWeChat\Payment\Order; + +/** + * v3支付 + * Class PayClient + * @package crmeb\services\easywechat\v3pay + */ +class PayClient extends BaseClient +{ + //app支付 + const API_APP_APY_URL = 'v3/pay/transactions/app'; + //二维码支付截图 + const API_NATIVE_URL = 'v3/pay/transactions/native'; + //h5支付接口 + const API_H5_URL = 'v3/pay/transactions/h5'; + //jsapi支付接口 + const API_JSAPI_URL = 'v3/pay/transactions/jsapi'; + //发起商家转账API + const API_BATCHES_URL = 'v3/transfer/batches'; + //退款 + const API_REFUND_URL = 'v3/refund/domestic/refunds'; + //退款查询接口 + const API_REFUND_QUERY_URL = 'v3/refund/domestic/refunds/{out_refund_no}'; + + /** + * @var string + */ + protected $type = Order::JSAPI; + + /** + * @param string $type + * @return $this + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/10 + */ + public function setType(string $type) + { + $this->type = $type; + return $this; + } + + /** + * 公众号jsapi支付下单 + * @param string $outTradeNo + * @param string $total + * @param string $description + * @param string $attach + * @return mixed + */ + public function jsapiPay(string $openid, string $outTradeNo, string $total, string $description, string $attach) + { + $appId = $this->app['config']['wechat']['appid']; + $res = $this->pay('jsapi', $appId, $outTradeNo, $total, $description, $attach, ['openid' => $openid]); + return $this->configForJSSDKPayment($appId, $res['prepay_id']); + } + + /** + * 小程序支付 + * @param string $outTradeNo + * @param string $total + * @param string $description + * @param string $attach + * @return array|false|string + */ + public function miniprogPay(string $openid, string $outTradeNo, string $total, string $description, string $attach) + { + $appId = $this->app['config']['miniprog']['appid']; + $res = $this->pay('jsapi', $appId, $outTradeNo, $total, $description, $attach, ['openid' => $openid]); + return $this->configForJSSDKPayment($appId, $res['prepay_id']); + } + + /** + * APP支付下单 + * @param string $outTradeNo + * @param string $total + * @param string $description + * @param string $attach + * @return mixed + */ + public function appPay(string $outTradeNo, string $total, string $description, string $attach) + { + $res = $this->pay('app', $this->app['config']['app']['appid'], $outTradeNo, $total, $description, $attach); + return $this->configForAppPayment($res['prepay_id']); + } + + /** + * native支付下单 + * @param string $outTradeNo + * @param string $total + * @param string $description + * @param string $attach + * @return mixed + */ + public function nativePay(string $outTradeNo, string $total, string $description, string $attach) + { + return $this->pay('native', $this->app['config']['web']['appid'], $outTradeNo, $total, $description, $attach); + } + + /** + * h5支付下单 + * @param string $outTradeNo + * @param string $total + * @param string $description + * @param string $attach + * @return mixed + */ + public function h5Pay(string $outTradeNo, string $total, string $description, string $attach) + { + return $this->pay('h5', $this->app['config']['wechat']['appid'], $outTradeNo, $total, $description, $attach); + } + + /** + * 下单 + * @param string $type + * @param string $appid + * @param string $outTradeNo + * @param string $total + * @param string $description + * @param string $attach + * @param array $payer + * @return mixed + */ + public function pay(string $type, string $appid, string $outTradeNo, string $total, string $description, string $attach, array $payer = []) + { + $totalFee = (int)bcmul($total, '100'); + + $data = [ + 'appid' => $appid, + 'mchid' => $this->app['config']['v3_payment']['mchid'], + 'out_trade_no' => $outTradeNo, + 'attach' => $attach, + 'description' => $description, + 'notify_url' => $this->app['config']['v3_payment']['notify_url'], + 'amount' => [ + 'total' => $totalFee, + 'currency' => 'CNY' + ], + ]; + + if ($payer) { + $data['payer'] = $payer; + } + + $url = ''; + switch ($type) { + case 'h5': + $url = self::API_H5_URL; + $data['scene_info'] = [ + 'payer_client_ip' => request()->ip(), + 'h5_info' => [ + 'type' => 'Wap' + ] + ]; + break; + case 'native': + $url = self::API_NATIVE_URL; + break; + case 'app': + $url = self::API_APP_APY_URL; + break; + case 'jsapi': + $url = self::API_JSAPI_URL; + break; + } + + if (!$url) { + throw new PayException('缺少请求地址'); + } + + $res = $this->request($url, 'POST', ['json' => $data]); + + if (!$res) { + throw new PayException('微信支付:下单失败'); + } + if (isset($res['code']) && isset($res['message'])) { + throw new PayException($res['message']); + } + + return $res; + } + + /** + * 发起商家转账API + * @param string $outBatchNo + * @param string $amount + * @param string $batchName + * @param string $remark + * @param array $transferDetailList + * @return mixed + */ + public function batches(string $outBatchNo, string $amount, string $batchName, string $remark, array $transferDetailList) + { + $totalFee = '0'; + $amount = bcadd($amount, '0', 2); + foreach ($transferDetailList as &$item) { + if ($item['transfer_amount'] >= 2000 && empty($item['user_name'])) { + throw new PayException('明细金额大于等于2000时,收款人姓名必须填写'); + } + $totalFee = bcadd($totalFee, $item['transfer_amount'], 2); + $item['transfer_amount'] = (int)bcmul($item['transfer_amount'], 100, 0); + if (isset($item['user_name'])) { + $item['user_name'] = $this->encryptor($item['user_name']); + } + } + + if ($totalFee !== $amount) { + throw new PayException('转账明细金额总和和转账总金额不一致'); + } + + $amount = (int)bcmul($amount, 100, 0); + + $appid = null; + if ($this->type === Order::JSAPI) { + $appid = $this->app['config']['wechat']['appid']; + } else if ($this->type === 'mini') { + $appid = $this->app['config']['miniprog']['appid']; + } else if ($this->type === Order::APP) { + $appid = $this->app['config']['app']['appid']; + } + + if (!$appid) { + throw new PayException('暂时只支持微信用户、小程序用户、APP微信登录用户提现'); + } + + $data = [ + 'appid' => $appid, + 'out_batch_no' => $outBatchNo, + 'batch_name' => $batchName, + 'batch_remark' => $remark, + 'total_amount' => $amount, + 'total_num' => count($transferDetailList), + 'transfer_detail_list' => $transferDetailList + ]; + + $res = $this->request(self::API_BATCHES_URL, 'POST', ['json' => $data]); + + if (!$res) { + throw new PayException('微信支付:发起商家转账失败'); + } + + if (isset($res['code']) && isset($res['message'])) { + throw new PayException($res['message']); + } + + return $res; + + } + + /** + * 退款 + * @param string $outTradeNo + * @param array $options + * @return mixed + */ + public function refund(string $outTradeNo, array $options = []) + { + if (!isset($options['pay_price'])) { + throw new PayException(400730); + } + $totalFee = floatval(bcmul($options['pay_price'], 100, 0)); + $refundFee = isset($options['refund_price']) ? floatval(bcmul($options['refund_price'], 100, 0)) : null; + $refundReason = $options['desc'] ?? ''; + $refundNo = $options['refund_id'] ?? $outTradeNo; + /*仅针对老资金流商户使用 + REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款(默认使用未结算资金退款) + REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款 + */ + $refundAccount = $opt['refund_account'] ?? 'AVAILABLE'; + + $data = [ + 'transaction_id' => $outTradeNo, + 'out_refund_no' => $refundNo, + 'amount' => [ + 'refund' => (int)$refundFee, + 'currency' => 'CNY', + 'total' => (int)$totalFee + ], + 'funds_account' => $refundAccount + ]; + + if ($refundReason) { + $data['reason'] = $refundReason; + } + + $res = $this->request(self::API_REFUND_URL, 'POST', ['json' => $data]); + + if (!$res) { + throw new PayException('微信支付:发起退款失败'); + } + + if (isset($res['code']) && isset($res['message'])) { + throw new PayException($res['message']); + } + + return $res; + } + + /** + * 查询退款 + * @param string $outRefundNo + * @return mixed + */ + public function queryRefund(string $outRefundNo) + { + $res = $this->request($this->getApiUrl(self::API_REFUND_QUERY_URL, ['out_refund_no'], [$outRefundNo]), 'GET'); + + if (!$res) { + throw new PayException(500000); + } + + if (isset($res['code']) && isset($res['message'])) { + throw new PayException($res['message']); + } + + return $res; + } + + /** + * jsapi支付 + * @param string $appid + * @param string $prepayId + * @param bool $json + * @return array|false|string + */ + public function configForPayment(string $appid, string $prepayId, bool $json = true) + { + $params = [ + 'appId' => $appid, + 'timeStamp' => strval(time()), + 'nonceStr' => uniqid(), + 'package' => "prepay_id=$prepayId", + 'signType' => 'RSA', + ]; + $message = $params['appId'] . "\n" . + $params['timeStamp'] . "\n" . + $params['nonceStr'] . "\n" . + $params['package'] . "\n"; + openssl_sign($message, $raw_sign, $this->getPrivateKey(), 'sha256WithRSAEncryption'); + $sign = base64_encode($raw_sign); + + $params['paySign'] = $sign; + + return $json ? json_encode($params) : $params; + } + + /** + * Generate app payment parameters. + * @param string $prepayId + * @return array + */ + public function configForAppPayment(string $prepayId): array + { + $params = [ + 'appid' => $this->app['config']['app']['appid'], + 'partnerid' => $this->app['config']['v3_payment']['mchid'], + 'prepayid' => $prepayId, + 'noncestr' => uniqid(), + 'timestamp' => time(), + 'package' => 'Sign=WXPay', + ]; + $message = $params['appid'] . "\n" . + $params['timestamp'] . "\n" . + $params['noncestr'] . "\n" . + $params['prepayid'] . "\n"; + openssl_sign($message, $raw_sign, $this->getPrivateKey(), 'sha256WithRSAEncryption'); + $sign = base64_encode($raw_sign); + + $params['sign'] = $sign; + + return $params; + } + + /** + * 小程序支付 + * @param string $appid + * @param string $prepayId + * @return array|false|string + */ + public function configForJSSDKPayment(string $appid, string $prepayId) + { + $config = $this->configForPayment($appid, $prepayId, false); + + $config['timestamp'] = $config['timeStamp']; + unset($config['timeStamp']); + + return $config; + } + + /** + * @param $callback + * @return \think\Response + */ + public function handleNotify($callback) + { + $request = request(); + $success = $request->post('event_type') === 'TRANSACTION.SUCCESS'; + $data = $this->decrypt($request->post('resource', [])); + + $handleResult = call_user_func_array($callback, [json_decode($data), $success]); + if (is_bool($handleResult) && $handleResult) { + $response = [ + 'code' => 'SUCCESS', + 'message' => 'OK', + ]; + } else { + $response = [ + 'code' => 'FAIL', + 'message' => $handleResult, + ]; + } + + return response($response, 200, [], 'json'); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/v3pay/ServiceProvider.php b/demo/thinkphp/backend/phoenix/services/easywechat/v3pay/ServiceProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..ca2c9d14be5861dd8013d6c2449eaac959dab740 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/v3pay/ServiceProvider.php @@ -0,0 +1,36 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\services\easywechat\v3pay; + + +use Pimple\Container; +use Pimple\ServiceProviderInterface; + +/** + * Class ServiceProvider + * @package crmeb\services\easywechat\v3pay + */ +class ServiceProvider implements ServiceProviderInterface +{ + + /** + * @param Container $pimple + */ + public function register(Container $pimple) + { + $pimple['v3pay'] = function ($pimple) { + return new PayClient($pimple['access_token'], $pimple); + }; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/wechatlive/ProgramProvider.php b/demo/thinkphp/backend/phoenix/services/easywechat/wechatlive/ProgramProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..023197e7ee1be7a066e0c8a576f9765fa0140853 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/wechatlive/ProgramProvider.php @@ -0,0 +1,38 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\easywechat\wechatlive; + +use EasyWeChat\MiniProgram\AccessToken; +use Pimple\Container; +use Pimple\ServiceProviderInterface; + +/** + * 注册直播 + * Class ProgramProvider + * @package crmeb\utils + */ +class ProgramProvider implements ServiceProviderInterface +{ + public function register(Container $pimple) + { + $pimple['mini_program.access_token'] = function ($pimple) { + return new AccessToken( + $pimple['config']['mini_program']['app_id'], + $pimple['config']['mini_program']['secret'], + $pimple['cache'] + ); + }; + + $pimple['mini_program.wechat_live'] = function ($pimple) { + return new ProgramWechatLive($pimple['mini_program.access_token']); + }; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/easywechat/wechatlive/ProgramWechatLive.php b/demo/thinkphp/backend/phoenix/services/easywechat/wechatlive/ProgramWechatLive.php new file mode 100644 index 0000000000000000000000000000000000000000..01a9caddaa9306c482ddfbe4c5dc32968bc31a9d --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/easywechat/wechatlive/ProgramWechatLive.php @@ -0,0 +1,308 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\easywechat\wechatlive; + +use EasyWeChat\Core\AbstractAPI; +use EasyWeChat\Core\AccessToken; + +/** + * Class ProgramWechatLive + * @package crmeb\services\wechatlive + */ +class ProgramWechatLive extends AbstractAPI +{ + + /** + * 获取直播列表信息 + */ + const API_WECHAT_LIVE = 'https://api.weixin.qq.com/wxa/business/getliveinfo'; + /** + * 创建直播间 + */ + const CREATE_LIVE_ROOM = 'https://api.weixin.qq.com/wxaapi/broadcast/room/create'; + /** + * 直播间导入商品 + */ + const LIVE_ROOM_ADD_GOODS = 'https://api.weixin.qq.com/wxaapi/broadcast/room/addgoods'; + + /** + * 获取商品列表信息 + */ + const GOODS_LIST = 'https://api.weixin.qq.com/wxaapi/broadcast/goods/getapproved'; + /** + * 商品添加并审核 + */ + const GOODS_ADD = 'https://api.weixin.qq.com/wxaapi/broadcast/goods/add'; + /** + * 撤回审核 + */ + const GOODS_RESET_AUDIT = 'https://api.weixin.qq.com/wxaapi/broadcast/goods/resetaudit'; + /** + * 重新提交审核 + */ + const GOODS_AUDIT = 'https://api.weixin.qq.com/wxaapi/broadcast/goods/autdit'; + /** + * 删除商品 + */ + const GOODS_DELETE = 'https://api.weixin.qq.com/wxaapi/broadcast/goods/delete'; + /** + * 更新商品 + */ + const GOODS_UPDATE = 'https://api.weixin.qq.com/wxaapi/broadcast/goods/update'; + /** + * 获取商品状态 + */ + const GOODS_INFO = 'https://api.weixin.qq.com/wxa/business/getgoodswarehouse'; + /** + * 获取成员列表 + */ + const ROLE_LIST = 'https://api.weixin.qq.com/wxaapi/broadcast/role/getrolelist'; + /** + * 添加直播间参数 + * @var array + */ + protected $create_data = [ + 'name' => '', // 房间名字 + 'coverImg' => '', // 通过 uploadfile 上传,填写 mediaID + 'startTime' => 0, // 开始时间 + 'endTime' => 0, // 结束时间 + 'anchorName' => '', // 主播昵称 + 'anchorWechat' => '', // 主播微信号 + 'shareImg' => '', //通过 uploadfile 上传,填写 mediaID + 'feedsImg' => '', //通过 uploadfile 上传,填写 mediaID + 'isFeedsPublic' => 1, // 是否开启官方收录,1 开启,0 关闭 + 'type' => 1, // 直播类型,1 推流 0 手机直播 + 'screenType' => 0, // 1:横屏 0:竖屏 + 'closeLike' => 0, // 是否 关闭点赞 1 关闭 + 'closeGoods' => 0, // 是否 关闭商品货架,1:关闭 + 'closeComment' => 0, // 是否开启评论,1:关闭 + 'closeReplay' => 1, // 是否关闭回放 1 关闭 + 'closeShare' => 0, // 是否关闭分享 1 关闭 + 'closeKf' => 0 // 是否关闭客服,1 关闭 + ]; + + /** + * ProgramWechatLive constructor. + * @param AccessToken $accessToken + */ + public function __construct(AccessToken $accessToken) + { + parent::__construct($accessToken); + } + + /** + * 获取直播间列表 + * @param int $page + * @param int $limit + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function getLiveInfo(int $page = 1, int $limit = 10) + { + $page = ($page - 1) * $limit; + $params = [ + 'start' => $page, + 'limit' => $limit + ]; + return $this->parseJSON('json', [self::API_WECHAT_LIVE, $params]); + } + + /** + * 获取直播间回放 + * @param int $room_id + * @param int $page + * @param int $limit + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function getLivePlayback(int $room_id, int $page = 1, int $limit = 10) + { + $page = ($page - 1) * $limit; + $params = [ + 'action' => 'get_replay', + 'room_id' => $room_id, + 'start' => $page, + 'limit' => $limit + ]; + return $this->parseJSON('json', [self::API_WECHAT_LIVE, $params]); + } + + /** + * 创建直播间 + * @param $data + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function createRoom(array $data) + { + $params = array_merge($this->create_data, $data); + return $this->parseJSON('json', [self::CREATE_LIVE_ROOM, $params]); + } + + /** + * 直播间导入商品 + * @param int $room_id + * @param $ids + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function roomAddGoods(int $room_id, $ids) + { + $params = [ + 'ids' => $ids, + 'roomId' => $room_id + ]; + return $this->parseJSON('json', [self::LIVE_ROOM_ADD_GOODS, $params]); + } + + /** + * 获取商品列表 + * @param $status + * @param int $page + * @param int $limit + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function getGoodsList($status, int $page = 0, $limit = 30) + { + $params = [ + 'offset' => $page * $limit, + 'limit' => $limit, + 'status' => $status + ]; + return $this->parseJSON('json', [self::GOODS_LIST, $params]); + } + + /** + * 获取商品详情 + * @param $ids + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function getGooodsInfo($ids) + { + $params = [ + 'goods_ids' => $ids + ]; + return $this->parseJSON('json', [self::GOODS_INFO, $params]); + } + + /** + * 添加商品 + * @param string $coverImgUrl + * @param string $name + * @param int $priceType + * @param string $url + * @param $price + * @param string $price2 + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function addGoods(string $coverImgUrl, string $name, int $priceType, string $url, $price, $price2 = '') + { + $params = ['goodsInfo' => [ + 'coverImgUrl' => $coverImgUrl, + 'name' => $name, + 'priceType' => $priceType, + 'price' => $price, + 'url' => $url + ]]; + if ($priceType != 1) $params['goodsInfo']['price2'] = $price2; + return $this->parseJSON('json', [self::GOODS_ADD, $params]); + } + + /** + * 商品撤回审核 + * @param int $goodsId + * @param int $auditId + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function resetauditGoods(int $goodsId, int $auditId) + { + $params = [ + 'goodsId' => $goodsId, + 'auditId' => $auditId + ]; + return $this->parseJSON('json', [self::GOODS_RESET_AUDIT, $params]); + } + + /** + * 商品重新提交审核 + * @param int $goodsId + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function auditGoods(int $goodsId) + { + $params = [ + 'goodsId' => $goodsId + ]; + return $this->parseJSON('json', [self::GOODS_AUDIT, $params]); + } + + /** + * 删除商品 + * @param int $goodsId + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function deleteGoods(int $goodsId) + { + $params = [ + 'goodsId' => $goodsId + ]; + return $this->parseJSON('json', [self::GOODS_DELETE, $params]); + } + + /** + * 更新商品 + * @param int $goodsId + * @param string $coverImgUrl + * @param string $name + * @param int $priceType + * @param string $url + * @param $price + * @param string $price2 + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function updateGoods(int $goodsId, string $coverImgUrl, string $name, int $priceType, string $url, $price, $price2 = '') + { + $params = ['goodsInfo' => [ + 'goodsId' => $goodsId, + 'coverImgUrl' => $coverImgUrl, + 'name' => $name, + 'priceType' => $priceType, + 'price' => $price, + 'url' => $url + ]]; + if ($priceType != 1) $params['goodsInfo']['price2'] = $price2; + return $this->parseJSON('json', [self::GOODS_UPDATE, $params]); + } + + /** + * 获取成员列表 + * @param int $goodsId + * @return \EasyWeChat\Support\Collection|null + * @throws \EasyWeChat\Core\Exceptions\HttpException + */ + public function getRoleList($role = 2, int $page = 0, $limit = 30, $keyword = '') + { + $params = [ + 'role' => $role, + 'offset' => $page * $limit, + 'limit' => $limit, + 'keyword' => $keyword + ]; + return $this->parseJSON('get', [self::ROLE_LIST, $params]); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/express/BaseExpress.php b/demo/thinkphp/backend/phoenix/services/express/BaseExpress.php new file mode 100644 index 0000000000000000000000000000000000000000..d67431c82aca84994fe120252f6bff0a0a498efb --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/express/BaseExpress.php @@ -0,0 +1,74 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\express; + +use crmeb\basic\BaseStorage; +use crmeb\services\AccessTokenServeService; + +/** + * 物流查询 + * Class BaseExpress + * @package crmeb\basic + */ +abstract class BaseExpress extends BaseStorage +{ + + /** + * access_token + * @var null + */ + protected $accessToken = NULL; + + + public function __construct(string $name, AccessTokenServeService $accessTokenServeService, string $configFile) + { + parent::__construct($name, [], $configFile); + $this->accessToken = $accessTokenServeService; + } + + /** + * 初始化 + * @param array $config + * @return mixed|void + */ + protected function initialize(array $config = []) + { +// parent::initialize($config); + } + + + /** + * 开通服务 + * @return mixed + */ + abstract public function open(); + + /**物流追踪 + * @return mixed + */ + abstract public function query(string $num, string $com = ''); + + /**电子面单 + * @return mixed + */ + abstract public function dump($data); + + /**快递公司 + * @return mixed + */ + //abstract public function express($type, $page, $limit); + + /**面单模板 + * @return mixed + */ + abstract public function temp(string $com); +} diff --git a/demo/thinkphp/backend/phoenix/services/express/Express.php b/demo/thinkphp/backend/phoenix/services/express/Express.php new file mode 100644 index 0000000000000000000000000000000000000000..682fa527255f1580657e5a2717b23fc2a209f96e --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/express/Express.php @@ -0,0 +1,62 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\express; + + +use crmeb\basic\BaseManager; +use crmeb\services\AccessTokenServeService; +use think\Container; +use think\facade\Config; + +/** + * Class Express + * @package crmeb\services\express + * @mixin \crmeb\services\express\storage\Express + */ +class Express extends BaseManager +{ + /** + * 空间名 + * @var string + */ + protected $namespace = '\\crmeb\\services\\express\\storage\\'; + + /** + * 默认驱动 + * @return mixed + */ + protected function getDefaultDriver() + { + return Config::get('express.default', 'express'); + } + + /** + * 获取类的实例 + * @param $class + * @return mixed|void + */ + protected function invokeClass($class) + { + if (!class_exists($class)) { + throw new \RuntimeException('class not exists: ' . $class); + } + $this->getConfigFile(); + + if (!$this->config) { + $this->config = Config::get($this->configFile . '.stores.' . $this->name, []); + } + $handleAccessToken = new AccessTokenServeService($this->config['account'] ?? '', $this->config['secret'] ?? '', app()->cache); + $handle = Container::getInstance()->invokeClass($class, [$this->name, $handleAccessToken, $this->configFile]); + $this->config = []; + return $handle; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/express/storage/AliyunExpress.php b/demo/thinkphp/backend/phoenix/services/express/storage/AliyunExpress.php new file mode 100644 index 0000000000000000000000000000000000000000..53375e805e416d2a5e9da30ca42d031468e0e8b8 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/express/storage/AliyunExpress.php @@ -0,0 +1,56 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\express\storage; + +use crmeb\services\express\BaseExpress; +use crmeb\services\HttpService; + +/** + * Class AliyunExpress + * @package crmeb\services\express\storage + */ +class AliyunExpress extends BaseExpress +{ + /** + * @var string[] + */ + protected static $api = [ + 'query' => 'https://wuliu.market.alicloudapi.com/kdi' + ]; + + /** + * @param string $no + * @param string $type + * @return bool|mixed + */ + public function query(string $no = '', string $type = '', string $appCode = '') + { + if (!$appCode) return false; + $res = HttpService::getRequest(self::$api['query'], compact('no', 'type'), ['Authorization:APPCODE ' . $appCode]); + return json_decode($res, true) ?: false; + } + + public function open() + { + // TODO: Implement open() method. + } + + public function dump($data) + { + // TODO: Implement dump() method. + } + + public function temp(string $com) + { + // TODO: Implement temp() method. + } +} diff --git a/demo/thinkphp/backend/phoenix/services/express/storage/Express.php b/demo/thinkphp/backend/phoenix/services/express/storage/Express.php new file mode 100644 index 0000000000000000000000000000000000000000..e94a30647b862541e690f0cd17b8542f211d13f5 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/express/storage/Express.php @@ -0,0 +1,262 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\express\storage; + +use app\services\shipping\ExpressServices; +use crmeb\services\express\BaseExpress; +use crmeb\exceptions\AdminException; + +/** + * Class Express + * @package crmeb\services\express\storage + */ +class Express extends BaseExpress +{ + /** + * 注册服务 + */ + const EXPRESS_OPEN = 'expr/open'; + + /** + * 电子面单模版 + */ + const EXPRESS_TEMP = 'expr/temp'; + + /** + * 快递公司 + */ + const EXPRESS_LIST = 'expr/express'; + + /** + * 快递查询 + */ + const EXPRESS_QUERY = 'expr/query'; + + /** + * 面单打印 + */ + const EXPRESS_DUMP = 'expr/dump'; + + //获取物流公司信息 + const SHIPMENT_KUAIDI_NUMS = 'shipment/get_kuaidi_coms'; + //创建商家寄件订单 + const SHIPMENT_CREATE_ORDER = 'shipment/create_order'; + //取消商家寄件 + const SHIPMENT_CANCEL_ORDER = 'shipment/cancel_order'; + //获取商家寄件订单列表 + const SHIPMENT_INDEX = 'shipment/index'; + + /** 初始化 + * @param array $config + * @return mixed|void + */ + + protected function initialize(array $config = []) + { + parent::initialize($config); // TODO: Change the autogenerated stub + } + + /** + * 商家寄件获取快递公司 + * @return array|mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/15 + */ + public function getKuaidiComs() + { + return $this->accessToken->httpRequest(self::SHIPMENT_KUAIDI_NUMS, [], 'GET'); + } + + /** + * 商家寄件创建订单 + * @param array $data + * @return array|mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/15 + */ + public function shippmentCreateOrder(array $data) + { + $siid = sys_config('config_export_siid'); + $param = [ + 'kuaidicom' => $data['kuaidicom'], + 'man_name' => $data['man_name'], + 'phone' => $data['phone'], + 'address' => $data['address'], + 'send_real_name' => $data['send_real_name'], + 'send_phone' => $data['send_phone'], + 'send_address' => $data['send_address'], + 'call_back_url' => sys_config(''), + 'return_type' => $siid ? '10' : '20', + 'siid' => $siid, + 'tempid' => $data['tempid'], + 'cargo' => $data['cargo'], + 'weight' => $data['weight'], + ]; + return $this->accessToken->httpRequest(self::SHIPMENT_CREATE_ORDER, $param); + } + + /** + * 取消商家寄件订单 + * @param array $data + * @return array|mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/15 + */ + public function shipmentCancelOrder(array $data) + { + $param = [ + 'task_id' => $data['task_id'],//快递100商家寄件任务id + 'order_id' => $data['order_id'],//快递100商家寄件发起的订单号。并不是系统中的订单号 + 'cancel_msg' => $data['cancel_msg'],//取消原因 + ]; + return $this->accessToken->httpRequest(self::SHIPMENT_CANCEL_ORDER, $param); + } + + /** + * 获取商家寄件订单列表 + * @param array $data + * @return array|mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/15 + */ + public function getShipmentOrderList(array $data) + { + $param = [ + 'kuaidi_num' => $data['kuaidi_num'] ?? '', + 'courier_name' => $data['courier_name'] ?? '', + 'page' => $data['page'] ?? 1, + 'limit' => $data['limit'] ?? 10, + ]; + + return $this->accessToken->httpRequest(self::SHIPMENT_INDEX, $param, 'GET'); + } + + /** + * 开通物流服务 + * @return bool|mixed + */ + public function open() + { + return $this->accessToken->httpRequest(self::EXPRESS_OPEN, []); + } + + /** + * 获取电子面单模版 + * @param $com 快递公司编号 + * @param int $page + * @param int $limit + * @return bool|mixed + */ + public function temp(string $com) + { + $param = [ + 'com' => $com + ]; + + return $this->accessToken->httpRequest(self::EXPRESS_TEMP, $param); + } + + /** + * 获取物流公司列表 + * @param int $type 快递类型:1,国内运输商;2,国际运输商;3,国际邮政 + * @return bool|mixed + */ + public function express(int $type = 0, int $page = 0, int $limit = 20) + { + if ($type) { + $param = [ + 'type' => $type, + 'page' => $page, + 'limit' => $limit + ]; + } else { + $param = []; + } + + return $this->accessToken->httpRequest(self::EXPRESS_LIST, $param); + } + + /** + * 查询物流信息 + * @param $com + * @param $num + * @return bool|mixed + * @return 是否签收 ischeck + * @return 物流状态:status 0在途,1揽收,2疑难,3签收,4退签,5派件,6退回,7转单,10待清关,11清关中,12已清关,13清关异常,14收件人拒签 + * @return 物流详情 content + */ + public function query(string $num, string $com = '', $phone = '') + { + $param = [ + 'com' => $com, + 'num' => $num, + 'phone' => $phone + ]; + if ($com === null) { + unset($param['com']); + } + return $this->accessToken->httpRequest(self::EXPRESS_QUERY, $param); + } + + /** + * 电子面单打印 + * @param array $data 必需参数: com(快递公司编码)、to_name(寄件人)、to_tel(寄件人电话)、to_addr(寄件人详细地址)、from_name(收件人)、from_tel(收件人电话)、from_addr(收件人地址)、temp_id(电子面单模板ID)、siid(云打印机编号)、count(商品数量) + * @return bool|mixed + */ + public function dump($data) + { + $param = $data; + $param['com'] = $data['com'] ?? ''; + if (!$param['com']) throw new AdminException(400713); + $param['to_name'] = $data['to_name'] ?? ''; + $param['to_tel'] = $data['to_tel'] ?? ''; + $param['order_id'] = $data['order_id'] ?? ''; + $param['to_addr'] = $data['to_addr'] ?? ''; + if (!$param['to_addr'] || !$param['to_tel'] || !$param['to_name']) throw new AdminException(400714); + $param['from_name'] = $data['from_name'] ?? ''; + $param['from_tel'] = $data['from_tel'] ?? ''; + $param['from_addr'] = $data['from_addr'] ?? ''; + if (!$param['from_name'] || !$param['from_tel'] || !$param['from_addr']) throw new AdminException(400715); + $param['temp_id'] = $data['temp_id'] ?? ''; + if (!$param['temp_id']) { + throw new AdminException(400712); + } + $param['siid'] = sys_config('config_export_siid'); +// if (!$param['siid']) { +// throw new AdminException(400716); +// } + $param['count'] = $data['count'] ?? ''; + $param['cargo'] = $data['cargo'] ?? ''; + if (!$param['count']) { + throw new AdminException(400717); + } + /** @var ExpressServices $expressServices */ + $expressServices = app()->make(ExpressServices::class); + $expressData = $expressServices->getOneByWhere(['code' => $param['com']])->toArray(); + if (isset($data['cargo'])) $param['cargo'] = $data['cargo']; + if ($expressData['partner_id'] == 1) $param['partner_id'] = $expressData['account']; + if ($expressData['partner_key'] == 1) $param['partner_key'] = $expressData['key']; + if ($expressData['net'] == 1) $param['net'] = $expressData['net_name']; + if ($expressData['check_man'] == 1) $param['checkMan'] = $expressData['courier_name']; + if ($expressData['partner_name'] == 1) $param['partnerName'] = $expressData['customer_name']; + if ($expressData['is_code'] == 1) $param['code'] = $expressData['code_name']; + if (!$data['siid']) { + $param['print_type'] = 'IMAGE'; + } + return $this->accessToken->httpRequest(self::EXPRESS_DUMP, $param, 'POST', true, ['version:v1.1']); + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/oauth/OAuth.php b/demo/thinkphp/backend/phoenix/services/oauth/OAuth.php new file mode 100644 index 0000000000000000000000000000000000000000..17606bb97d3b6c42521f7e289ca48d0c594b2c60 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/oauth/OAuth.php @@ -0,0 +1,45 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\oauth; + + +use crmeb\basic\BaseManager; +use crmeb\services\oauth\storage\MiniProgram; +use crmeb\services\oauth\storage\TouTiao; +use crmeb\services\oauth\storage\Wechat; +use think\facade\Config; + +/** + * 第三方登录 + * Class OAuth + * @package crmeb\services\oauth + * @mixin Wechat + * @mixin TouTiao + * @mixin MiniProgram + */ +class OAuth extends BaseManager +{ + + /** + * 空间名 + * @var string + */ + protected $namespace = '\\crmeb\\services\\oauth\\storage\\'; + + /** + * @return mixed + */ + protected function getDefaultDriver() + { + return Config::get('oauth.default', 'wechat'); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/oauth/OAuthException.php b/demo/thinkphp/backend/phoenix/services/oauth/OAuthException.php new file mode 100644 index 0000000000000000000000000000000000000000..6461ebc0c17d3edd702592ee801560b87c9caed6 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/oauth/OAuthException.php @@ -0,0 +1,44 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\oauth; + +/** + * Class OAuthException + * @package crmeb\services\oauth + */ +class OAuthException extends \RuntimeException +{ + /** + * OAuthException constructor. + * @param $message + * @param array $replace + * @param int $code + * @param \Throwable|null $previous + */ + public function __construct($message, $replace = [], $code = 0, \Throwable $previous = null) + { + if (is_array($message)) { + $errInfo = $message; + $message = $errInfo[1] ?? '未知错误'; + if ($code === 0) { + $code = $errInfo[0] ?? 400; + } + } + + if (is_numeric($message)) { + $code = $message; + $message = getLang($message, $replace); + } + + parent::__construct($message, $code, $previous); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/oauth/OAuthInterface.php b/demo/thinkphp/backend/phoenix/services/oauth/OAuthInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..8c1a0adceb92058e849e92abb210205f58322fc6 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/oauth/OAuthInterface.php @@ -0,0 +1,37 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\oauth; + +/** + * 第三方登录 + * Interface OAuthInterface + * @package crmeb\services\oauth + */ +interface OAuthInterface +{ + + /** + * 获取用户信息 + * @param string $openid + * @return mixed + */ + public function getUserInfo(string $openid); + + /** + * 授权 + * @param string|null $code + * @param array $options + * @return mixed + */ + public function oauth(string $code = null, array $options = []); + +} diff --git a/demo/thinkphp/backend/phoenix/services/oauth/storage/MiniProgram.php b/demo/thinkphp/backend/phoenix/services/oauth/storage/MiniProgram.php new file mode 100644 index 0000000000000000000000000000000000000000..64c905c82bd59547c93794ab7056191bf411fa28 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/oauth/storage/MiniProgram.php @@ -0,0 +1,85 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\oauth\storage; + + +use crmeb\basic\BaseStorage; +use crmeb\services\app\MiniProgramService; +use crmeb\services\oauth\OAuthException; +use crmeb\services\oauth\OAuthInterface; + +/** + * 小程序登录 + * Class MiniProgram + * @package crmeb\services\oauth\storage + */ +class MiniProgram extends BaseStorage implements OAuthInterface +{ + + protected function initialize(array $config) + { + // TODO: Implement initialize() method. + } + + /** + * @param string $openid + * @return array|mixed + */ + public function getUserInfo(string $openid) + { + return []; + } + + /** + * 授权登录 + * @param string|null $code + * @param array $options + * @return mixed + */ + public function oauth(string $code = null, array $options = []) + { + if (!$code) { + throw new OAuthException(100104); + } + + try { + $userInfoCong = MiniProgramService::getUserInfo($code); + $session_key = $userInfoCong['session_key']; + } catch (\Exception $e) { + throw new OAuthException($e->getMessage()); + } + + if (!isset($userInfoCong['openid'])) { + throw new OAuthException(410075); + } + + //是否静默授权 + if (isset($options['silence']) && $options['silence'] === true) { + return $userInfoCong; + } + + if (empty($options['iv']) || empty($options['encryptedData'])) { + throw new OAuthException(100100); + } + + try { + //解密获取用户信息 + $userInfo = MiniProgramService::encryptor($session_key, $options['iv'], $options['encryptedData']); + } catch (\Exception $e) { + if ($e->getCode() == '-41003') { + throw new OAuthException(410077); + } + } + + return [$userInfoCong, $userInfo]; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/oauth/storage/TouTiao.php b/demo/thinkphp/backend/phoenix/services/oauth/storage/TouTiao.php new file mode 100644 index 0000000000000000000000000000000000000000..c7d3d4396cd45c28a524ae36f6b7cb902859d9c4 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/oauth/storage/TouTiao.php @@ -0,0 +1,40 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\oauth\storage; + + +use crmeb\basic\BaseStorage; +use crmeb\services\oauth\OAuthInterface; + +/** + * 头条小程序登录 + * Class TouTiao + * @package crmeb\services\oauth\storage + */ +class TouTiao extends BaseStorage implements OAuthInterface +{ + + protected function initialize(array $config) + { + // TODO: Implement initialize() method. + } + + public function getUserInfo(string $openid) + { + // TODO: Implement getUserInfo() method. + } + + public function oauth(string $code = null, array $options = []) + { + // TODO: Implement oauth() method. + } +} diff --git a/demo/thinkphp/backend/phoenix/services/oauth/storage/Wechat.php b/demo/thinkphp/backend/phoenix/services/oauth/storage/Wechat.php new file mode 100644 index 0000000000000000000000000000000000000000..d2791ef58683438c99885c2a76ea9ac178e0f7cf --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/oauth/storage/Wechat.php @@ -0,0 +1,75 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\oauth\storage; + + +use crmeb\basic\BaseStorage; +use crmeb\services\app\WechatOpenService; +use crmeb\services\app\WechatService; +use crmeb\services\oauth\OAuthException; +use crmeb\services\oauth\OAuthInterface; + +/** + * 微信公众号登录 + * Class Wechat + * @package crmeb\services\oauth\storage + */ +class Wechat extends BaseStorage implements OAuthInterface +{ + + protected function initialize(array $config) + { + // TODO: Implement initialize() method. + } + + + /** + * 获取用户信息 + * @param string $openid + * @return mixed + */ + public function getUserInfo(string $openid) + { + return WechatService::oauth2Service()->getUserInfo($openid)->toArray(); + } + + /** + * 授权 + * @param string|null $code + * @param array $options + * @return \EasyWeChat\Support\Collection|mixed + */ + public function oauth(string $code = null, array $options = []) + { + $open = false; + if (!empty($options['open'])) { + $open = true; + } + + if (!$open) { + try { + $wechatInfo = WechatService::oauth2Service()->oauth(); + } catch (\Throwable $e) { + throw new OAuthException($e->getMessage()); + } + } else { + /** @var WechatOpenService $service */ + $service = app()->make(WechatOpenService::class); + $wechatInfo = $service->getAuthorizationInfo(); + if (!$wechatInfo) { + throw new OAuthException(410131); + } + } + + return $wechatInfo; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/pay/BasePay.php b/demo/thinkphp/backend/phoenix/services/pay/BasePay.php new file mode 100644 index 0000000000000000000000000000000000000000..7c175ce68b328d3dde2474e697b16a630c13cc63 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/pay/BasePay.php @@ -0,0 +1,62 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\pay; + +use EasyWeChat\Payment\Order; +use crmeb\basic\BaseStorage; + +/** + * Class BasePay + * @package crmeb\services\pay + */ +abstract class BasePay extends BaseStorage +{ + /** + * @var string + */ + protected $payType; + + /** + * 设置支付类型 + * @param string $type + * @return $this + */ + public function setPayType(string $type) + { + $this->payType = $type; + return $this; + } + + /** + * 设置支付类型 + * @param string $type + * @return $this + */ + public function authSetPayType() + { + if (!$this->payType) { + if (request()->isPc()) { + $this->payType = Order::NATIVE; + } + if (request()->isApp()) { + $this->payType = Order::APP; + } + if (request()->isRoutine() || request()->isWechat()) { + $this->payType = Order::JSAPI; + } + if (request()->isH5()) { + $this->payType = 'h5'; + } + } + } + + +} diff --git a/demo/thinkphp/backend/phoenix/services/pay/Pay.php b/demo/thinkphp/backend/phoenix/services/pay/Pay.php new file mode 100644 index 0000000000000000000000000000000000000000..1bc92d4ab13558c4614fe45be48ffc7ce8eb48dd --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/pay/Pay.php @@ -0,0 +1,44 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\pay; + + +use crmeb\basic\BaseManager; +use crmeb\services\pay\storage\AliPay; +use crmeb\services\pay\storage\V3WechatPay; +use crmeb\services\pay\storage\WechatPay; +use think\facade\Config; + +/** + * 第三方支付 + * Class AllinPay + * @package crmeb\services\pay + * @mixin WechatPay + */ +class Pay extends BaseManager +{ + /** + * 空间名 + * @var string + */ + protected $namespace = '\\crmeb\\services\\pay\\storage\\'; + + /** + * 默认驱动 + * @return mixed + */ + protected function getDefaultDriver() + { + return Config::get('pay.default', 'wechat_pay'); + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/pay/PayInterface.php b/demo/thinkphp/backend/phoenix/services/pay/PayInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..adc62aa4ca100d607b327d4070ec3c37d907946e --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/pay/PayInterface.php @@ -0,0 +1,77 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\pay; + +/** + * 支付接口类 + * Interface PayInterface + * @package crmeb\services\pay + */ +interface PayInterface +{ + + /** + * 设置支付类型 + * @param string $type 支付类型 + * @return $this + */ + public function setPayType(string $type); + + /** + * 创建支付 + * @param string $orderId 订单号 + * @param string $totalFee 支付金额 + * @param string $attach 回调内容 + * @param string $body 支付body + * @param string $detail 详情 + * @param string $tradeType 支付类型 + * @param array $options 其他参数 + * @return mixed + */ + public function create(string $orderId, string $totalFee, string $attach, string $body, string $detail, array $options = []); + + /** + * 企业支付到零钱 + * @param string $openid openid + * @param string $orderId 订单id + * @param string $amount 支付金额 + * @param array $options 其他参数 + * @return mixed + */ + public function merchantPay(string $openid, string $orderId, string $amount, array $options = []); + + /** + * 退款 + * @param string $outTradeNo 退款单号 + * @param string $totalAmount 退款金额 + * @param string $refund_id 退款 + * @param array $options 其他参数 + * @return mixed + */ + public function refund(string $outTradeNo, array $options = []); + + /** + * 查询订单 + * @param string $outTradeNo 退款单号 + * @param string $outRequestNo 支付商户单号 + * @param array $other 其他参数 + * @return mixed + */ + public function queryRefund(string $outTradeNo, string $outRequestNo, array $other = []); + + /** + * 支付回调 + * @return mixed + */ + public function handleNotify(); + +} diff --git a/demo/thinkphp/backend/phoenix/services/pay/extend/allinpay/AllinPay.php b/demo/thinkphp/backend/phoenix/services/pay/extend/allinpay/AllinPay.php new file mode 100644 index 0000000000000000000000000000000000000000..2a4af0840fd449295263055d48a139e834c3c2e9 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/pay/extend/allinpay/AllinPay.php @@ -0,0 +1,344 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\pay\extend\allinpay; + + +/** + * + * Class AllinPay + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/12/27 + * @package crmeb\services\pay\extend\allinpay + */ +class AllinPay extends Client +{ + + //统一支付接口 + const UNITODER_PAY_API = 'unitorder/pay'; + + //统一扫码接口 + const UNITORDER_SCANQRPAY = 'unitorder/scanqrpay'; + + //退款 + const UNITODER_TRANX_REFUND = 'tranx/refund'; + + //订单查询 + const UNITODER_TRANX_QUERY = 'tranx/query'; + + const UNITODER_QPAY_AGREEAPPLY = 'qpay/agreeapply'; + + //微信公众号内支付请求地址 + const UNITODER_H5UNIONPAY = 'https://vsp.allinpay.com/apiweb/h5unionpay/unionorder'; + + /** + * @var string + */ + protected $api = ''; + + /** + * 支付类型 + * @var string + */ + protected $payType = ''; + + /** + * @var string + */ + protected $version = ''; + + /** + * @var string + */ + protected $orderKey = 'reqsn'; + + /** + * @var int + */ + protected $validtime = 720; + + /** + * 创建支付订单 + * @param string $trxamt + * @param string $orderId + * @param string $body + * @param string|null $openId + * @param string|null $appid + * @param string $frontUrl + * @param string $remark + * @return mixed + */ + public function create(string $trxamt, string $orderId, string $body, string $returl = null, string $openId = null, string $appid = null, string $frontUrl = '', string $remark = '') + { + $totalFee = (int)bcmul($trxamt, '100'); + + $data = [ + 'trxamt' => $totalFee, + $this->orderKey => $orderId, + 'validtime' => $this->validtime, + 'notify_url' => $this->notifyUrl + ]; + + if ($body) { + $data['body'] = $body; + } + + if ($remark) { + $data['remark'] = $remark; + } + + if ($this->payType) { + $data['paytype'] = $this->payType; + } + + if ($returl) { + $data['returl'] = $returl; + } + + if ($openId) { + $data['acct'] = $openId; + } + + if ($appid) { + $data['sub_appid'] = $appid; + } + + if ($frontUrl) { + $data['front_url'] = $frontUrl; + } + + if ($this->version) { + $data['version'] = $this->version; + } + + $form = !$this->api; + $api = $this->api; + + $this->version = ''; + $this->payType = ''; + $this->api = ''; + $this->orderKey = 'reqsn'; + $this->validtime = 720; + + return $this->send($api, ['data' => $data, 'form' => $form]); + } + + /** + * 微信H5支付 + * @param string $trxamt + * @param string $orderId + * @param string $body + * @param string $returl + * @param string $remark + * @return mixed + */ + public function h5Pay(string $trxamt, string $orderId, string $body, string $returl, string $remark = '') + { + $this->version = self::VERSION_NUM_12; + return $this->create($trxamt, $orderId, $body, $returl, null, null, '', $remark); + } + + /** + * 微信js支付 + * @param string $trxamt + * @param string $orderId + * @param string $body + * @param string $openId + * @param string $appId + * @param string $frontUrl + * @param string $remark + * @return mixed + */ + public function wechatPay(string $trxamt, string $orderId, string $body, string $openId, string $appId, string $frontUrl, string $remark = '') + { + $this->api = self::UNITODER_PAY_API; + return $this->create($trxamt, $orderId, $body, null, $openId, $appId, $frontUrl, $remark); + } + + /** + * app支付 微信和支付宝 + * @param string $trxamt + * @param string $orderId + * @param string $body + * @param bool $isWechat + * @param string $remark + * @return mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/1/14 + */ + public function appPay(string $trxamt, string $orderId, string $body, string $appid, string $openid = null, bool $isWechat = true, string $remark = '') + { + $this->api = self::UNITODER_PAY_API; + $this->payType = $isWechat ? 'A02' : 'A01'; + $this->version = self::VERSION_NUM_11; + return $this->create($trxamt, $orderId, $body, null, $openid, $appid, '', $remark); + } + + /** + * PC 收银台支付 + * @param string $trxamt + * @param string $orderId + * @param string $body + * @return mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/1/15 + */ + public function pcPay(string $trxamt, string $orderId, string $body, string $remark, bool $isWechat = true) + { + $this->api = self::UNITODER_PAY_API; + $this->payType = $isWechat ? 'W01' : 'A01'; + $this->version = self::VERSION_NUM_11; + $res = $this->create($trxamt, $orderId, $body, null, null, null, '', $remark); + $invalid = time() + 60; + if ($isWechat) { + $key = 'code_url'; + } else { + $key = 'qrCode'; + } + return ['invalid' => $invalid, 'logo' => sys_config('wap_login_logo'), $key => $res['payinfo']]; + } + + /** + * @param string $trxamt + * @param string $orderId + * @param string $body + * @param string $returl + * @param string $remark + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/1/15 + */ + public function miniproPay(string $trxamt, string $orderId, string $body, string $remark = '') + { + $totalFee = bcmul($trxamt, '100'); + + $data = [ + 'paytype' => 'W06', + 'trxamt' => $totalFee, + 'reqsn' => $orderId, + 'notify_url' => $this->notifyUrl, + 'body' => $body, + 'validtime' => (string)$this->validtime, + 'cusid' => $this->cusid, + 'appid' => $this->appid, + 'signtype' => $this->signType, + 'randomstr' => uniqid(), + 'remark' => $remark, + 'version' => self::VERSION_NUM_12 + ]; + + $data['sign'] = $this->sign($data); + + return $data; + } + + public function agreeapply() + { + $data = [ + 'meruserid' => 'eesssxxx', + 'accttype' => '00', + 'acctno' => '', + 'idtype' => 0, + 'idno' => '', + 'acctname' => '', + 'mobile' => '', + 'cvv2' => '', + 'reqip' => request()->ip(), + 'reqtime' => date('Y-m-d H:i:s'), + 'version' => self::VERSION_NUM_11, + ]; + + $data['cusid'] = $this->cusid; + $data['appid'] = $this->appid; + $data['signtype'] = $this->signType; + $data['randomstr'] = uniqid(); + $data['sign'] = $this->sign($data); + + return $this->request(self::UNITODER_QPAY_AGREEAPPLY, $data); + } + + + /** + * 查询订单 + * @param string $reqsn + * @return array|mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/1/15 + */ + public function query(string $reqsn) + { + $data = [ + 'reqsn' => $reqsn + ]; + + return $this->send(self::UNITODER_TRANX_QUERY, ['data' => $data]); + } + + /** + * 发起退款 + * @param string $trxamt + * @param string $reqsn + * @return array|mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/1/15 + */ + public function refund(string $trxamt, string $orderId, string $reqsn) + { + $totalFee = (int)bcmul($trxamt, '100'); + + $data = [ + 'trxamt' => $totalFee, + 'reqsn' => $orderId, + 'oldtrxid' => $reqsn, + ]; + + return $this->send(self::UNITODER_TRANX_REFUND, ['data' => $data]); + } + + /** + * 异步回调 + * @param callable $callback + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/1/15 + */ + public function handleNotify(callable $callback) + { + $params = []; + foreach (request()->post() as $key => $val) { + $params[$key] = $val; + } + + $this->debugLog('通联支付回调数据' . json_encode($params)); + + if (count($params) < 1) { + //如果参数为空,则不进行处理 + return "error"; + } + + $res = $this->validSign($params); + + $this->debugLog('通联支付回调验证:' . json_encode(['res' => $res])); + + if ($res && isset($params['trxstatus']) && $params['trxstatus'] === '0000') { + //验签成功 + return $callback($params) ? 'success' : 'error'; + } else { + return "error"; + } + } +} diff --git a/demo/thinkphp/backend/phoenix/services/pay/extend/allinpay/Client.php b/demo/thinkphp/backend/phoenix/services/pay/extend/allinpay/Client.php new file mode 100644 index 0000000000000000000000000000000000000000..3087989676d6b24246e55d5458eed60411c9bcb0 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/pay/extend/allinpay/Client.php @@ -0,0 +1,283 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\pay\extend\allinpay; + +use crmeb\exceptions\ApiException; +use crmeb\services\HttpService; +use think\facade\Cache; +use think\facade\Log; + +/** + * Class Client + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/12/27 + * @package crmeb\services\pay\extend\allinpay + */ +class Client +{ + + //生产地址 + const API_URL = 'https://vsp.allinpay.com/apiweb/'; + + //测试接口地址 + const BETA_API_URL = 'https://syb-test.allinpay.com/apiweb/'; + + //版本号 + const VERSION_NUM_11 = '11'; + + //版本号 + const VERSION_NUM_12 = '12'; + + + protected $signType = 'MD5'; + + /** + * @var string + */ + protected $cusid = ''; + + /** + * @var string + */ + protected $appid = ''; + + /** + * @var string + */ + protected $privateKey = ''; + + /** + * @var + */ + protected $publicKey = ''; + + /** + * 回调地址 + * @var string + */ + protected $notifyUrl = ''; + + /** + * 是否测试 + * @var bool + */ + protected $isBeta = true; + + /** + * debug模式 + * @var bool + */ + protected $isDebug = true; + + /** + * Client constructor. + * @param array $config + */ + public function __construct(array $config = []) + { + $this->appid = $config['appid'] ?? ''; + $this->cusid = $config['cusid'] ?? ''; + $this->privateKey = $config['privateKey'] ?? ''; + $this->publicKey = $config['publicKey'] ?? ''; + $this->notifyUrl = $config['notifyUrl'] ?? ''; + $this->isBeta = $config['isBeta'] ?? true; + } + + /** + * 发送请求 + * @param string $url + * @param array $options + * @return mixed + */ + public function send(string $url, array $options = []) + { + $data = $options['data'] ?? []; + $header = $options['header'] ?? []; + + $data['cusid'] = $this->cusid; + $data['appid'] = $this->appid; + if (!isset($data['version'])) { + $data['version'] = self::VERSION_NUM_11; + } + + $data['signtype'] = $this->signType; + $data['randomstr'] = uniqid(); + + if (!empty($options['form'])) { + $data['charset'] = 'UTF-8'; + $data['version'] = self::VERSION_NUM_12; + $data['sign'] = $this->sign($data); + return $data; + } + + $data['sign'] = $this->sign($data); + + $response = $this->request($url, $data, 'post', $header); + + if ('SUCCESS' !== $response['retcode']) { + throw new ApiException($response['retmsg']); + } + + if (!empty($response['trxstatus']) && !in_array($response['trxstatus'], ['0000', '2008', '2000'])) { + throw new ApiException($response['errmsg']); + } + + if ($this->validSign($response)) { + return $response; + } + + throw new ApiException('创建订单成功验签失败'); + } + + /** + * @param string $url + * @param array $data + * @param string $method + * @param array $header + * @param int $timeout + * @return mixed + */ + public function request(string $url, array $data = [], string $method = 'post', array $header = [], int $timeout = 10) + { + $headerData = []; + if ($header) { + foreach ($header as $key => $item) { + $headerData[] = $key . ':' . $item; + } + } + + $content = HttpService::request($this->baseUrl($url), $method, $data, $headerData, $timeout); + + $respones = json_decode($content, true, 512, JSON_BIGINT_AS_STRING); + + $this->debugLog('API response decoded:', ['content' => $respones, 'header' => $header]); + + if (JSON_ERROR_NONE !== json_last_error()) { + throw new ApiException('Failed to parse JSON: ' . json_last_error_msg()); + } + + return $respones; + } + + /** + * @param string $message + * @param array $contents + */ + protected function debugLog(string $message, array $contents = []) + { + $this->isDebug && Log::debug($message, $contents); + } + + /** + * @param string|null $url + * @return string + */ + protected function baseUrl(string $url = null) + { + $baseUrl = $this->isBeta ? self::BETA_API_URL : self::API_URL; + if ($url) { + $baseUrl .= $url; + } + + return $baseUrl; + } + + /** + * @param array $data + * @return string + */ + public function sign(array $data) + { + + $private_key = $this->privateKey; + + if ($this->signType === 'MD5') { + $data['key'] = $private_key; + ksort($data); + + $bufSignSrc = $this->toUrlParams($data); + + return md5($bufSignSrc); + } else { + ksort($data); + + $bufSignSrc = $this->toUrlParams($data); + + $private_key = chunk_split($private_key, 64, "\n"); + + $key = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($private_key) . "-----END RSA PRIVATE KEY-----"; + + openssl_sign($bufSignSrc, $signature, $key); + + $sign = base64_encode($signature);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的 + + return $sign; + } + } + + /** + * @param array $data + * @return string + */ + public function toUrlParams(array $data) + { + $buff = ""; + foreach ($data as $k => $v) { + if ($v != "" && !is_array($v)) { + $buff .= $k . "=" . $v . "&"; + } + } + + $buff = trim($buff, "&"); + return $buff; + } + + /** + * @param array $data + * @return false|int + */ + public function validSign(array $data) + { + $sign = $data['sign']; + unset($data['sign']); + + if ($this->signType === 'MD5') { + $data['key'] = $this->privateKey; + ksort($data); + $bufSignSrc = $this->toUrlParams($data); + return strtolower($sign) == strtolower(md5($bufSignSrc)); + } else { + ksort($data); + $bufSignSrc = $this->toUrlParams($data); + $public_key = $this->publicKey; + + $public_key = chunk_split($public_key, 64, "\n"); + + $key = "-----BEGIN PUBLIC KEY-----\n$public_key-----END PUBLIC KEY-----\n"; + + return openssl_verify($bufSignSrc, base64_decode($sign), $key); + } + } + + /** + * @param string $notifyUrl + * @return $this + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/7 + */ + public function setNotifyUrl(string $notifyUrl) + { + $this->notifyUrl = $notifyUrl; + return $this; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/pay/storage/AliPay.php b/demo/thinkphp/backend/phoenix/services/pay/storage/AliPay.php new file mode 100644 index 0000000000000000000000000000000000000000..492513b238d0e5ffcffefb1c2bc4be77df0d0e20 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/pay/storage/AliPay.php @@ -0,0 +1,102 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\pay\storage; + + +use Alipay\EasySDK\Payment\Common\Models\AlipayTradeFastpayRefundQueryResponse; +use Alipay\EasySDK\Payment\Common\Models\AlipayTradeRefundResponse; +use Alipay\EasySDK\Payment\Wap\Models\AlipayTradeWapPayResponse; +use crmeb\services\pay\BasePay; +use crmeb\services\pay\PayInterface; +use crmeb\services\AliPayService; + +/** + * 支付宝支付 + * Class AliPay + * @package crmeb\services\pay\storage + */ +class AliPay extends BasePay implements PayInterface +{ + + protected function initialize(array $config) + { + // TODO: Implement initialize() method. + } + + /** + * 创建订单发起支付 + * @param string $orderId + * @param string $totalFee + * @param string $attach + * @param string $body + * @param string $detail + * @param string|null $tradeType + * @param array $options + * @return AlipayTradeWapPayResponse|mixed + */ + public function create(string $orderId, string $totalFee, string $attach, string $body, string $detail, array $options = []) + { + $code = false; + if (request()->isPC() || request()->isRoutine()) { + $code = true; + } + + return AliPayService::instance()->create($body, $orderId, $totalFee, $attach, $options['uitUrl'] ?? '', $options['siteUrl'] ?? '', $code); + } + + /** + * 企业支付到零钱 + * @param string $openid + * @param string $orderId + * @param string $amount + * @param array $options + * @return bool|mixed + */ + public function merchantPay(string $openid, string $orderId, string $amount, array $options = []) + { + return false; + } + + /** + * 退款 + * @param string $outTradeNo + * @param string $totalAmount + * @param string $refund_id + * @param array $options + * @return AlipayTradeRefundResponse|mixed + */ + public function refund(string $outTradeNo, array $options = []) + { + return AliPayService::instance()->refund($outTradeNo, $options['totalAmount'], $options['refund_id']); + } + + /** + * 查询退款 + * @param string $outTradeNo + * @param string $outRequestNo + * @param array $other + * @return AlipayTradeFastpayRefundQueryResponse|mixed + */ + public function queryRefund(string $outTradeNo, string $outRequestNo, array $other = []) + { + return AliPayService::instance()->queryRefund($outTradeNo, $outRequestNo); + } + + /** + * 支付异步回调 + * @return mixed|string + */ + public function handleNotify() + { + return AliPayService::handleNotify(); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/pay/storage/AllinPay.php b/demo/thinkphp/backend/phoenix/services/pay/storage/AllinPay.php new file mode 100644 index 0000000000000000000000000000000000000000..b676b518eeb2e0200c65ad126a6498211e39dcac --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/pay/storage/AllinPay.php @@ -0,0 +1,154 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\services\pay\storage; + +use app\services\pay\PayServices; +use crmeb\exceptions\AdminException; +use crmeb\exceptions\PayException; +use crmeb\services\pay\BasePay; +use crmeb\services\pay\PayInterface; +use crmeb\services\pay\extend\allinpay\AllinPay as AllinPayService; +use EasyWeChat\Payment\Order; +use think\facade\Event; + +/** + * 通联支付 + * Class AllinPay + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/1 + * @package crmeb\services\pay\storage + */ +class AllinPay extends BasePay implements PayInterface +{ + + /** + * @var AllinPayService + */ + protected $pay; + + /** + * @param array $config + * @return mixed|void + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/1/15 + */ + protected function initialize(array $config) + { + $this->pay = new AllinPayService([ + 'appid' => sys_config('allin_appid'), + 'cusid' => sys_config('allin_cusid'), + 'privateKey' => sys_config('allin_private_key'), + 'publicKey' => sys_config('allin_public_key'), + 'notifyUrl' => trim(sys_config('site_url')) . '/api/pay/notify/allin', + 'isBeta' => false, + ]); + } + + /** + * 创建支付 + * @param string $orderId + * @param string $totalFee + * @param string $attach + * @param string $body + * @param string $detail + * @param array $options + * @return array|mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/1/15 + */ + public function create(string $orderId, string $totalFee, string $attach, string $body, string $detail, array $options = []) + { + $this->authSetPayType(); + + $options['returl'] = sys_config('site_url') . '/pages/index/index'; + if ($options['returl']) { + $options['returl'] = str_replace('http://', 'https://', $options['returl']); + } + $options['appid'] = sys_config('routine_appId'); + + + $notifyUrl = trim(sys_config('site_url')) . '/api/pay/notify/allin' . $attach; + $this->pay->setNotifyUrl($notifyUrl); + + switch ($this->payType) { + case Order::APP: + return $this->pay->appPay($totalFee, $orderId, $body, '', '', false, $attach); + case Order::JSAPI: + if (request()->isRoutine()) { + return $this->pay->miniproPay($totalFee, $orderId, $body, $attach); + } else { + return $this->pay->h5Pay($totalFee, $orderId, $body, $options['returl'] ?? '', $attach); + } + case Order::NATIVE: + return $this->pay->pcPay($totalFee, $orderId, $body, $attach, !empty($options['wechat'])); + default: + throw new PayException('通联支付:支付类型错误或者暂不支持此环境下支付'); + } + } + + public function merchantPay(string $openid, string $orderId, string $amount, array $options = []) + { + throw new PayException('通联支付:暂不支持商家转账'); + } + + /** + * 发起退款 + * @param string $outTradeNo + * @param array $options + * @return array|mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/1/15 + */ + public function refund(string $outTradeNo, array $options = []) + { + $result = $this->pay->refund($options['refund_price'], $options['order_id'], $outTradeNo); + if ($result['retcode'] != 'SUCCESS') throw new AdminException($result['retmsg']); + } + + public function queryRefund(string $outTradeNo, string $outRequestNo, array $other = []) + { + // TODO: Implement queryRefund() method. + } + + /** + * 异步回调 + * @return mixed|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/1/15 + */ + public function handleNotify(string $attach = '') + { + $attach = str_replace('allin', '', $attach); + + return $this->pay->handleNotify(function ($notify) use ($attach) { + + if (isset($notify['cusorderid'])) { + + $data = [ + 'attach' => $attach, + 'out_trade_no' => $notify['cusorderid'], + 'transaction_id' => $notify['trxid'] + ]; + + return Event::until('NotifyListener', [$data, PayServices::ALLIN_PAY]); + } + return false; + }); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/pay/storage/V3WechatPay.php b/demo/thinkphp/backend/phoenix/services/pay/storage/V3WechatPay.php new file mode 100644 index 0000000000000000000000000000000000000000..208b98229c4a56dc9f6cb7cec70a6388e2a06577 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/pay/storage/V3WechatPay.php @@ -0,0 +1,211 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\services\pay\storage; + +use app\services\pay\PayServices; +use crmeb\exceptions\PayException; +use crmeb\services\app\MiniProgramService; +use crmeb\services\easywechat\Application; +use crmeb\services\pay\BasePay; +use crmeb\services\pay\PayInterface; +use EasyWeChat\Payment\Order; +use think\facade\Event; + +/** + * Class 微信支付v3 + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + * @package crmeb\services\pay\storage + */ +class V3WechatPay extends BasePay implements PayInterface +{ + + /** + * @var Application + */ + protected $instance; + + /** + * @param array $config + * @return mixed|void + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + */ + protected function initialize(array $config = []) + { + $wechatAppid = sys_config('wechat_appid'); + $config = [ + 'app' => [ + 'appid' => sys_config('wechat_app_appid'), + ], + 'wechat' => [ + 'appid' => $wechatAppid, + ], + 'miniprog' => [ + 'appid' => sys_config('routine_appId'), + ], + 'web' => [ + 'appid' => $wechatAppid, + ], + 'v3_payment' => [ + 'mchid' => sys_config('pay_weixin_mchid'), + 'key' => sys_config('pay_weixin_key_v3'), + 'serial_no' => sys_config('pay_weixin_serial_no'), + 'cert_path' => public_path() . $this->getPemPath(sys_config('pay_weixin_client_cert')), + 'key_path' => public_path() . $this->getPemPath(sys_config('pay_weixin_client_key')), + 'notify_url' => trim(sys_config('site_url')) . '/api/pay/notify/v3wechat', + ] + ]; + $this->instance = new Application($config); + } + + /** + * 获取证书不带域名的路径 + * @param string $path + * @return mixed|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + */ + public function getPemPath(string $path) + { + if (strstr($path, 'http://') === false && strstr($path, 'https://') === false) { + return $path; + } else { + $res = parse_url($path); + return $res['path'] ?? ''; + } + } + + /** + * 创建订单返回支付参数 + * @param string $orderId + * @param string $totalFee + * @param string $attach + * @param string $body + * @param string $detail + * @param array $options + * @return array|false|mixed|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + */ + public function create(string $orderId, string $totalFee, string $attach, string $body, string $detail, array $options = []) + { + $this->authSetPayType(); + + switch ($this->payType) { + case Order::NATIVE: + $res = $this->instance->v3pay->nativePay($orderId, $totalFee, $body, $attach); + $res['invalid'] = time() + 60; + $res['logo'] = sys_config('wap_login_logo'); + return $res; + case Order::APP: + return $this->instance->v3pay->appPay($orderId, $totalFee, $body, $attach); + case Order::JSAPI: + if (empty($options['openid'])) { + throw new PayException('缺少openid'); + } + if (request()->isRoutine()) { + // 获取配置 判断是否为新支付 + if ($options['pay_new_weixin_open']) { + return MiniProgramService::newJsPay($options['openid'], $orderId, $totalFee, $attach, $body, $detail, $options); + } + return $this->instance->v3pay->miniprogPay($options['openid'], $orderId, $totalFee, $body, $attach); + } + return $this->instance->v3pay->jsapiPay($options['openid'], $orderId, $totalFee, $body, $attach); + case 'h5': + return $this->instance->v3pay->h5Pay($orderId, $totalFee, $body, $attach); + default: + throw new PayException('微信支付:支付类型错误'); + } + } + + /** + * @param string $openid + * @param string $orderId + * @param string $amount + * @param array $options + * @return mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + */ + public function merchantPay(string $openid, string $orderId, string $amount, array $options = []) + { + return $this->instance->v3pay->setType($options['type'])->batches( + $orderId, + $amount, + $options['batch_name'], + $options['batch_remark'], + [ + [ + 'out_detail_no' => $orderId, + 'transfer_amount' => $amount, + 'transfer_remark' => $options['batch_remark'], + 'openid' => $openid + ] + ] + ); + } + + /** + * 发起退款 + * @param string $outTradeNo + * @param array $options + * @return mixed + */ + public function refund(string $outTradeNo, array $options = []) + { + return $this->instance->v3pay->refund($outTradeNo, $options); + } + + /** + * 查询退款 + * @param string $outTradeNo + * @param string|null $outRequestNo + * @param array $other + * @return mixed + */ + public function queryRefund(string $outTradeNo, string $outRequestNo = null, array $other = []) + { + return $this->instance->v3pay->queryRefund($outTradeNo); + } + + /** + * @return mixed|\think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + */ + public function handleNotify() + { + return $this->instance->v3pay->handleNotify(function ($notify, $successful) { + + if ($successful) { + $data = [ + 'attach' => $notify->attach, + 'out_trade_no' => $notify->out_trade_no, + 'transaction_id' => $notify->transaction_id + ]; + + return Event::until('NotifyListener', [$data, PayServices::WEIXIN_PAY]); + } + + return false; + }); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/pay/storage/WechatPay.php b/demo/thinkphp/backend/phoenix/services/pay/storage/WechatPay.php new file mode 100644 index 0000000000000000000000000000000000000000..ef230cddcb83c7eacb6c13e7a86540946ef3729c --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/pay/storage/WechatPay.php @@ -0,0 +1,149 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\pay\storage; + + +use crmeb\exceptions\AdminException; +use crmeb\services\pay\BasePay; +use crmeb\exceptions\PayException; +use crmeb\services\pay\PayInterface; +use crmeb\services\app\MiniProgramService; +use crmeb\services\app\WechatService; +use crmeb\services\SystemConfigService; +use EasyWeChat\Payment\API; +use EasyWeChat\Payment\Order; +use EasyWeChat\Support\Collection; +use Psr\Http\Message\ResponseInterface; + +/** + * 微信支付 + * Class WechatPay + * @package crmeb\services\pay\storage + */ +class WechatPay extends BasePay implements PayInterface +{ + + protected function initialize(array $config) + { + // TODO: Implement initialize() method. + } + + /** + * 创建订单进行支付 + * @param string $orderId + * @param string $totalFee + * @param string $attach + * @param string $body + * @param string $detail + * @param array $options + * @return array|mixed|string + */ + public function create(string $orderId, string $totalFee, string $attach, string $body, string $detail, array $options = []) + { + $this->authSetPayType(); + + switch ($this->payType) { + case Order::NATIVE: + return WechatService::nativePay(null, $orderId, $totalFee, $attach, $body, $detail); + case Order::APP: + return WechatService::appPay($options['openid'], $orderId, $totalFee, $attach, $body, $detail); + case Order::JSAPI: + if (empty($options['openid'])) { + throw new PayException('缺少openid'); + } + if (request()->isRoutine()) { + // 获取配置 判断是否为新支付 + if ($options['pay_new_weixin_open']) { + return MiniProgramService::newJsPay($options['openid'], $orderId, $totalFee, $attach, $body, $detail, $options); + } + return MiniProgramService::jsPay($options['openid'], $orderId, $totalFee, $attach, $body, $detail); + } + return WechatService::jsPay($options['openid'], $orderId, $totalFee, $attach, $body, $detail); + case 'h5': + return WechatService::paymentPrepare(null, $orderId, $totalFee, $attach, $body, $detail, 'MWEB'); + default: + throw new PayException('微信支付:支付类型错误'); + } + } + + /** + * 支付到零钱 + * @param string $openid + * @param string $orderId + * @param string $amount + * @param array $options + * @return bool|mixed + */ + public function merchantPay(string $openid, string $orderId, string $amount, array $options = []) + { + return WechatService::merchantPay($openid, $orderId, $amount, $options['desc'] ?? ''); + } + + /** + * 退款 + * @param string $outTradeNo + * @param array $opt + * @return Collection|mixed|ResponseInterface + */ + public function refund(string $outTradeNo, array $opt = []) + { + if (!isset($opt['pay_price'])) throw new PayException(400730); + $totalFee = floatval(bcmul($opt['pay_price'], 100, 0)); + $refundFee = isset($opt['refund_price']) ? floatval(bcmul($opt['refund_price'], 100, 0)) : null; + $refundReason = $opt['desc'] ?? ''; + $refundNo = $opt['refund_id'] ?? $outTradeNo; + $opUserId = $opt['op_user_id'] ?? null; + $type = $opt['type'] ?? 'out_trade_no'; + /** + * 仅针对老资金流商户使用 + * REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款(默认使用未结算资金退款) + * REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款 + */ + $refundAccount = $opt['refund_account'] ?? 'REFUND_SOURCE_UNSETTLED_FUNDS'; + if (isset($opt['wechat'])) { + $result = WechatService::refund($outTradeNo, $refundNo, $totalFee, $refundFee, $opUserId, $refundReason, $type, $refundAccount); + if(isset($result['return_code']) && $result['return_code'] != 'SUCCESS') throw new AdminException($result['return_msg']); + if(isset($result['status']) && $result['status'] != 'SUCCESS') throw new AdminException($result['status']); + } else { + if ($opt['pay_new_weixin_open']) { + $result = MiniProgramService::miniRefund($outTradeNo, $totalFee, $refundFee, $opt); + if ($result['errcode'] != 0) throw new AdminException($result['errmsg']); + } else { + $result = MiniProgramService::refund($outTradeNo, $refundNo, $totalFee, $refundFee, $opUserId, $refundReason, $type, $refundAccount); + if(isset($result['return_code']) && $result['return_code'] != 'SUCCESS') throw new AdminException($result['return_msg']); + if(isset($result['status']) && $result['status'] != 'SUCCESS') throw new AdminException($result['status']); + } + } + } + + /** + * 查询退款订单 + * @param string $outTradeNo + * @param string $outRequestNo + * @param array $other + * @return Collection|mixed|ResponseInterface + */ + public function queryRefund(string $outTradeNo, string $outRequestNo, array $other = []) + { + return WechatService::queryRefund($outTradeNo, $other['type'] ?? API::OUT_TRADE_NO); + } + + /** + * 异步回调 + * @return mixed|\Symfony\Component\HttpFoundation\Response + * @throws \EasyWeChat\Core\Exceptions\FaultException + */ + public function handleNotify() + { + return WechatService::handleNotify(); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/printer/AccessToken.php b/demo/thinkphp/backend/phoenix/services/printer/AccessToken.php new file mode 100644 index 0000000000000000000000000000000000000000..89fefe350f3c69e954bc2e2e93f6d2b10fb108c6 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/printer/AccessToken.php @@ -0,0 +1,177 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\printer; + + +use app\services\other\CacheServices; +use crmeb\exceptions\AdminException; +use crmeb\services\HttpService; +use think\helper\Str; + +/** + * + * Class AccessToken + * @package crmeb\services\printer + */ +class AccessToken extends HttpService +{ + + /** + * token + * @var array + */ + protected $accessToken; + + /** + * 请求接口 + * @var string + */ + protected $apiUrl; + + /** + * @var string + */ + protected $clientId; + + /** + * 终端号码 + * @var string + */ + protected $machineCode; + + /** + * 开发者id + * @var string + */ + protected $partner; + + /** + * 驱动类型 + * @var string + */ + protected $name; + + /** + * 配置文件名 + * @var string + */ + protected $configFile; + + /** + * api key + * @var string + */ + protected $apiKey; + + /** + * 飞鹅云SN + * @var string + */ + protected $feySn; + + /** + * 飞鹅云UYEK + * @var string + */ + protected $feyUkey; + + /** + * 飞鹅云USER + * @var string + */ + protected $feyUser; + + public function __construct(array $config = [], string $name, string $configFile) + { + $this->clientId = $config['clientId'] ?? null; + $this->apiKey = $config['apiKey'] ?? null; + $this->partner = $config['partner'] ?? null; + $this->machineCode = $config['terminal'] ?? null; + $this->feyUser = $config['feyUser'] ?? null; + $this->feyUkey = $config['feyUkey'] ?? null; + $this->feySn = $config['feySn'] ?? null; + $this->name = $name; + $this->configFile = $configFile; + } + + /** + * 获取token + * @return mixed|null|string + * @throws \Exception + */ + public function getAccessToken() + { + if (isset($this->accessToken[$this->name])) { + return $this->accessToken[$this->name]; + } + + $action = 'get' . Str::studly($this->name) . 'AccessToken'; + if (method_exists($this, $action)) { + return $this->{$action}(); + } else { + throw new \RuntimeException(__CLASS__ . '->' . $action . '(),Method not worn in'); + } + } + + /** + * 获取易联云token + * @return mixed|null|string + * @throws \Exception + */ + protected function getYiLianYunAccessToken() + { + /** @var CacheServices $cacheServices */ + $cacheServices = app()->make(CacheServices::class); + $this->accessToken[$this->name] = $cacheServices->getDbCache('YLY_access_token', function () { + $request = self::postRequest('https://open-api.10ss.net/oauth/oauth', [ + 'client_id' => $this->clientId, + 'grant_type' => 'client_credentials', + 'sign' => strtolower(md5($this->clientId . time() . $this->apiKey)), + 'scope' => 'all', + 'timestamp' => time(), + 'id' => $this->createUuid(), + ]); + $request = json_decode($request, true); + $request['error'] = $request['error'] ?? 0; + $request['error_description'] = $request['error_description'] ?? ''; + if ($request['error'] == 0 && $request['error_description'] == 'success') { + return $request['body']['access_token'] ?? ''; + } + return ''; + }, 86400); + if (!$this->accessToken[$this->name]) + throw new AdminException(400718); + + return $this->accessToken[$this->name]; + } + + /** + * 生成UUID4 + * @return string + */ + public function createUuid() + { + return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), + mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)); + } + + /** + * 获取属性 + * @param $name + * @return mixed + */ + public function __get($name) + { + if (in_array($name, ['clientId', 'apiKey', 'accessToken', 'partner', 'terminal', 'machineCode', 'feyUser', 'feyUkey', 'feySn'])) { + return $this->{$name}; + } + } +} diff --git a/demo/thinkphp/backend/phoenix/services/printer/BasePrinter.php b/demo/thinkphp/backend/phoenix/services/printer/BasePrinter.php new file mode 100644 index 0000000000000000000000000000000000000000..c15ae12d454aa0bf5f46158f71f7e2bd50726005 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/printer/BasePrinter.php @@ -0,0 +1,61 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\printer; + +use crmeb\basic\BaseStorage; + +/** + * Class BasePrinter + * @package crmeb\basic + */ +abstract class BasePrinter extends BaseStorage +{ + + /** + * token句柄 + * @var AccessToken + */ + protected $accessToken; + + /** + * 打印内容 + * @var string + */ + protected $printerContent; + + /** + * BasePrinter constructor. + * @param string $name + * @param AccessToken $accessToken + * @param string $configFile + */ + public function __construct(string $name, AccessToken $accessToken, string $configFile) + { + parent::__construct($name, [], $configFile); + $this->accessToken = $accessToken; + } + + /** + * 开始打印 + * @param array|null $systemConfig + * @return mixed + */ + abstract public function startPrinter(); + + /** + * 设置打印内容 + * @param array $config + * @return mixed + */ + abstract public function setPrinterContent(array $config); + +} diff --git a/demo/thinkphp/backend/phoenix/services/printer/Printer.php b/demo/thinkphp/backend/phoenix/services/printer/Printer.php new file mode 100644 index 0000000000000000000000000000000000000000..9a9ed2e0aeed047c6245366ac9241efd86bae6d1 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/printer/Printer.php @@ -0,0 +1,71 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\printer; + +use crmeb\basic\BaseManager; +use think\facade\Config; +use think\Container; + +/** + * Class Printer + * @package crmeb\services\auth + * @mixin \crmeb\services\printer\storage\YiLianYun + */ +class Printer extends BaseManager +{ + + /** + * 空间名 + * @var string + */ + protected $namespace = '\\crmeb\\services\\printer\\storage\\'; + + /** + * @var object + */ + protected $handleAccessToken; + + /** + * 默认驱动 + * @return mixed + */ + protected function getDefaultDriver() + { + return Config::get('printer.default', 'yi_lian_yun'); + } + + /** + * 获取类的实例 + * @param $class + * @return mixed|void + */ + protected function invokeClass($class) + { + if (!class_exists($class)) { + throw new \RuntimeException('class not exists: ' . $class); + } + $this->getConfigFile(); + + if (!$this->config) { + $this->config = Config::get($this->configFile . '.stores.' . $this->name, []); + } + + if (!$this->handleAccessToken) { + $this->handleAccessToken = new AccessToken($this->config, $this->name, $this->configFile); + } + + $handle = Container::getInstance()->invokeClass($class, [$this->name, $this->handleAccessToken, $this->configFile]); + $this->config = []; + return $handle; + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/printer/storage/FeiEYun.php b/demo/thinkphp/backend/phoenix/services/printer/storage/FeiEYun.php new file mode 100644 index 0000000000000000000000000000000000000000..a1858498e3ff2ec5fbe6fb77760d6aa9bf521dff --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/printer/storage/FeiEYun.php @@ -0,0 +1,162 @@ +printerContent) { + return $this->setError('Missing print'); + } + $time = time(); + $request = $this->accessToken->postRequest('http://api.feieyun.cn/Api/Open/', [ + 'user' => $this->accessToken->feyUser, + 'stime' => $time, + 'sig' => sha1($this->accessToken->feyUser . $this->accessToken->feyUkey . $time), + 'apiname' => 'Open_printMsg', + 'sn' => $this->accessToken->feySn, + 'content' => $this->printerContent, + 'times' => 1 + ]); + $res = json_decode($request, true); + if ($res['msg'] == 'ok') { + return $res; + } else { + return $this->setError($res['msg']); + } + } + + /** + * 设置打印内容 + * @param array $config + * @return YiLianYun + */ + public function setPrinterContent(array $config): self + { + $printTime = date('Y-m-d H:i:s', time()); + $product = $config['product']; + $orderInfo = $config['orderInfo']; + $orderTime = date('Y-m-d H:i:s', $orderInfo['pay_time']); + $this->printerContent = '**' . $config['name'] . '**
'; + $this->printerContent .= '--------------------------------
'; + $this->printerContent .= '订单编号:' . $orderInfo['order_id'] . '
'; + $this->printerContent .= '打印时间: ' . $printTime . '
'; + $this->printerContent .= '付款时间: ' . $orderTime . '
'; + $this->printerContent .= '姓 名: ' . $orderInfo['real_name'] . '
'; + $this->printerContent .= '电 话: ' . $orderInfo['user_phone'] . '
'; + $this->printerContent .= '地 址: ' . $orderInfo['user_address'] . '
'; + $this->printerContent .= '赠送积分: ' . $orderInfo['gain_integral'] . '
'; + $this->printerContent .= '订单备注:' . $orderInfo['mark'] . '
'; + $this->printerContent .= '**************商品**************
'; + $this->printerContent .= '名称 单价 数量 金额
'; + $this->printerContent .= '--------------------------------
'; + foreach ($product as $item) { + $name = $item['productInfo']['store_name']; + $price = $item['truePrice']; + $num = $item['cart_num']; + $prices = bcmul((string)$item['cart_num'], (string)$item['truePrice'], 2); + $kw3 = ''; + $kw1 = ''; + $kw2 = ''; + $kw4 = ''; + $str = $name; + $blankNum = 14;//名称控制为14个字节 + $lan = mb_strlen($str, 'utf-8'); + $m = 0; + $j = 1; + $blankNum++; + $result = array(); + if (strlen($price) < 6) { + $k1 = 6 - strlen($price); + for ($q = 0; $q < $k1; $q++) { + $kw1 .= ' '; + } + $price = $price . $kw1; + } + if (strlen($num) < 3) { + $k2 = 3 - strlen($num); + for ($q = 0; $q < $k2; $q++) { + $kw2 .= ' '; + } + $num = $num . $kw2; + } + if (strlen($prices) < 6) { + $k3 = 6 - strlen($prices); + for ($q = 0; $q < $k3; $q++) { + $kw4 .= ' '; + } + $prices = $prices . $kw4; + } + for ($i = 0; $i < $lan; $i++) { + $new = mb_substr($str, $m, $j, 'utf-8'); + $j++; + if (mb_strwidth($new, 'utf-8') < $blankNum) { + if ($m + $j > $lan) { + $m = $m + $j; + $tail = $new; + $lenght = iconv("UTF-8", "GBK//IGNORE", $new); + $k = 14 - strlen($lenght); + for ($q = 0; $q < $k; $q++) { + $kw3 .= ' '; + } + if ($m == $j) { + $tail .= $kw3 . ' ' . $price . ' ' . $num . ' ' . $prices; + } else { + $tail .= $kw3 . '
'; + } + break; + } else { + $next_new = mb_substr($str, $m, $j, 'utf-8'); + if (mb_strwidth($next_new, 'utf-8') < $blankNum) { + continue; + } else { + $m = $i + 1; + $result[] = $new; + $j = 1; + } + } + } + } + $head = ''; + foreach ($result as $key => $value) { + if ($key < 1) { + $v_lenght = iconv("UTF-8", "GBK//IGNORE", $value); + $v_lenght = strlen($v_lenght); + if ($v_lenght == 13) $value = $value . " "; + $head .= $value . ' ' . $price . ' ' . $num . ' ' . $prices; + } else { + $head .= $value . '
'; + } + } + $this->printerContent .= $head . $tail; + unset($price); + } + $this->printerContent .= '--------------------------------
'; + $this->printerContent .= '合计:' . number_format($orderInfo['total_price'], 1) . '元
'; + $this->printerContent .= '邮费:' . number_format($orderInfo['pay_postage'], 1) . '元
'; + $this->printerContent .= '优惠:' . number_format($orderInfo['coupon_price'], 1) . '元
'; + $this->printerContent .= '抵扣:' . number_format($orderInfo['deduction_price'], 1) . '元
'; + $this->printerContent .= '实际支付:' . number_format($orderInfo['pay_price'], 1) . '元
'; + $this->printerContent .= '' . $config['url'] . '';//把解析后的二维码生成的字符串用标签套上即可自动生成二维码 + return $this; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/printer/storage/YiLianYun.php b/demo/thinkphp/backend/phoenix/services/printer/storage/YiLianYun.php new file mode 100644 index 0000000000000000000000000000000000000000..df20b7596e38ed67f1ecacbfaf3fb4855c42a4a8 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/printer/storage/YiLianYun.php @@ -0,0 +1,106 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\printer\storage; + +use crmeb\services\printer\BasePrinter; + +/** + * Class YiLianYun + * @package crmeb\services\printer\storage + */ +class YiLianYun extends BasePrinter +{ + + /** + * 初始化 + * @param array $config + * @return mixed|void + */ + protected function initialize(array $config) + { + + } + + /** + * 开始打印 + * @return bool|mixed|string + * @throws \Exception + */ + public function startPrinter() + { + if (!$this->printerContent) { + return $this->setError('Missing print'); + } + $request = $this->accessToken->postRequest('https://open-api.10ss.net/print/index', [ + 'client_id' => $this->accessToken->clientId, + 'access_token' => $this->accessToken->getAccessToken(), + 'machine_code' => $this->accessToken->machineCode, + 'content' => $this->printerContent, + 'origin_id' => 'crmeb' . time(), + 'sign' => strtolower(md5($this->accessToken->clientId . time() . $this->accessToken->apiKey)), + 'id' => $this->accessToken->createUuid(), + 'timestamp' => time() + ]); + if ($request === false) { + return $this->setError('request was aborted'); + } + $request = is_string($request) ? json_decode($request, true) : $request; + if (isset($request['error']) && in_array($request['error'], [18, 14])) { + return $this->setError('Accesstoken has expired'); + } + return $request; + } + + /** + * 设置打印内容 + * @param array $config + * @return YiLianYun + */ + public function setPrinterContent(array $config): self + { + $printTime = date('Y-m-d H:i:s', time()); + $goodsStr = ''; + $product = $config['product']; + foreach ($product as $item) { + $goodsStr .= ''; + $price = bcmul((string)$item['cart_num'], (string)$item['truePrice'], 2); + $goodsStr .= ""; + $goodsStr .= ''; + unset($price); + } + $goodsStr .= '
商品名称数量单价金额
{$item['productInfo']['store_name']}{$item['cart_num']}{$item['truePrice']}{$price}
'; + $orderInfo = $config['orderInfo']; + $orderTime = date('Y-m-d H:i:s',$orderInfo['pay_time']); + $name = $config['name']; + $this->printerContent = <<
** {$name} **
+---------------- +订单编号:{$orderInfo['order_id']}\r +打印时间: {$printTime} \r +付款时间: {$orderTime}\r +姓 名: {$orderInfo['real_name']}\r +电 话: {$orderInfo['user_phone']}\r +地 址: {$orderInfo['user_address']}\r +赠送积分: {$orderInfo['gain_integral']}\r +订单备注:{$orderInfo['mark']}\r +*************商品***************\r +{$goodsStr} +********************************\r + +合计:¥{$orderInfo['total_price']},优惠: ¥{$orderInfo['coupon_price']} +邮费:¥{$orderInfo['pay_postage']},抵扣:¥{$orderInfo['deduction_price']} +实际支付:¥{$orderInfo['pay_price']} + +
** 完 **
+CONTENT; + return $this; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/serve/Serve.php b/demo/thinkphp/backend/phoenix/services/serve/Serve.php new file mode 100644 index 0000000000000000000000000000000000000000..b8fac6a0eaaf4119c77936fef971d2adae88af1e --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/serve/Serve.php @@ -0,0 +1,64 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\serve; + + +use crmeb\basic\BaseManager; +use crmeb\services\AccessTokenServeService; +use crmeb\services\serve\storage\Crmeb; +use think\facade\Config; +use think\Container; + +/** + * Class Serve + * @package crmeb\services\serve + * @mixin Crmeb + */ +class Serve extends BaseManager +{ + /** + * 空间名 + * @var string + */ + protected $namespace = '\\crmeb\\services\\serve\\storage\\'; + + /** + * 默认驱动 + * @return mixed + */ + protected function getDefaultDriver() + { + return Config::get('serve.default', 'crmeb'); + } + + /** + * 获取类的实例 + * @param $class + * @return mixed|void + */ + protected function invokeClass($class) + { + if (!class_exists($class)) { + throw new \RuntimeException('class not exists: ' . $class); + } + $this->getConfigFile(); + + if (!$this->config) { + $this->config = Config::get($this->configFile . '.stores.' . $this->name, []); + } + + $handleAccessToken = new AccessTokenServeService($this->config['account'] ?? '', $this->config['secret'] ?? ''); + $handle = Container::getInstance()->invokeClass($class, [$this->name, $handleAccessToken, $this->configFile]); + $this->config = []; + return $handle; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/serve/storage/Crmeb.php b/demo/thinkphp/backend/phoenix/services/serve/storage/Crmeb.php new file mode 100644 index 0000000000000000000000000000000000000000..634dccb4cd5884328fc4f1890f72fb3049f9cc3b --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/serve/storage/Crmeb.php @@ -0,0 +1,176 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\serve\storage; + + +use crmeb\basic\BaseStorage; +use crmeb\exceptions\AdminException; +use crmeb\services\AccessTokenServeService; + +/** + * Class Crmeb + * @package crmeb\services\serve\storage + */ +class Crmeb extends BaseStorage +{ + + protected $accessToken; + + /** + * Crmeb constructor. + * @param string $name + * @param AccessTokenServeService $service + * @param string|null $configFile + */ + public function __construct(string $name, AccessTokenServeService $service, string $configFile = null) + { + $this->accessToken = $service; + } + + protected function initialize(array $config) + { + // TODO: Implement initialize() method. + } + + /** + * 获取用户信息 + * @param string $account + * @param string $secret + * @return array|mixed + */ + public function getUser() + { + return $this->accessToken->httpRequest('user/info'); + } + + /** + * 用户登录 + * @param string $account + * @param string $secret + * @return array|mixed + */ + public function login(string $account, string $secret) + { + return $this->accessToken->httpRequest('user/login', ['account' => $account, 'secret' => $secret], 'POST', false); + } + + /** + * 注册平台 + * @param array $data + * @return array|mixed + */ + public function register(array $data) + { + return $this->accessToken->httpRequest('user/register', $data, 'POST', false); + } + + /** + * 平台用户消息记录 + * @param int $page + * @param int $limit + * @return array|mixed + */ + public function userBill(int $page, int $limit) + { + return $this->accessToken->httpRequest('user/bill', ['page' => $page, 'limit' => $limit]); + } + + /** + * 找回账号 + * @param array $data + * @return array|mixed + */ + public function forget(array $data) + { + return $this->accessToken->httpRequest('user/forget', $data, 'POST', false); + } + + /** + * 修改密码 + * @param array $data + * @return array|mixed + */ + public function modify(array $data) + { + return $this->accessToken->httpRequest('user/modify', $data, 'POST', false); + } + + /** + * 获取验证码 + * @param string $phone + * @return array|mixed + */ + public function code(string $phone, $type = 0) + { + return $this->accessToken->httpRequest('user/code', ['phone' => $phone, 'types' => $type], 'POST', false); + } + + /** + * 验证验证码 + * @param string $phone + * @return array|mixed + */ + public function checkCode(string $phone, string $verify_code) + { + return $this->accessToken->httpRequest('user/code/verify', ['phone' => $phone, 'verify_code' => $verify_code], 'POST', false); + } + + /** + * 套餐列表 + * @param string $type 套餐类型:sms,短信;query,物流查询;dump,电子面单;copy,产品复制 + * @return array|mixed + */ + public function mealList(string $type) + { + return $this->accessToken->httpRequest('meal/list', ['type' => $type]); + } + + /** + * 套餐支付 + * @param array $data + * @return array|mixed + */ + public function payMeal(array $data) + { + return $this->accessToken->httpRequest('meal/code', $data); + } + + /** + * 用量记录 + * @param int $page + * @param int $limit + * @param int $type + * @return array|mixed + */ + public function record(int $page, int $limit, int $type, $status = '') + { + $typeContent = [1 => 'sms', 2 => 'expr_dump', 3 => 'expr_query', 4 => 'copy']; + if (!isset($typeContent[$type])) { + throw new AdminException(100100); + } + $data = ['page' => $page, 'limit' => $limit, 'type' => $typeContent[$type]]; + if ($type == 1 && $status != '') { + $data['status'] = $status; + } + return $this->accessToken->httpRequest('user/record', $data); + } + + /** + * 修改手机号 + * @param array $data + * @return array|mixed + */ + public function modifyPhone(array $data) + { + return $this->accessToken->httpRequest('user/modify/phone', $data); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/sms/BaseSms.php b/demo/thinkphp/backend/phoenix/services/sms/BaseSms.php new file mode 100644 index 0000000000000000000000000000000000000000..835201056c80fecf817404ba3e181ab9f4888bb7 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/sms/BaseSms.php @@ -0,0 +1,108 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\sms; + +use crmeb\basic\BaseStorage; +use crmeb\services\AccessTokenServeService; + +/** + * Class BaseSmss + * @package crmeb\basic + */ +abstract class BaseSms extends BaseStorage +{ + + /** + * access_token + * @var null + */ + protected $accessToken = NULL; + + /** + * BaseSmss constructor. + * @param string $name + * @param AccessTokenServeService $accessTokenServeService + * @param string $configFile + */ + public function __construct(string $name, AccessTokenServeService $accessTokenServeService, string $configFile, array $config = []) + { + $this->accessToken = $accessTokenServeService; + $this->name = $name; + $this->configFile = $configFile; + $this->initialize($config); + } + + /** + * 初始化 + * @param array $config + * @return mixed|void + */ + protected function initialize(array $config = []) + { + + } + + + /** + * 开通服务 + * @return mixed + */ + abstract public function open(); + + /**修改签名 + * @return mixed + */ + abstract public function modify(string $sign = null, string $phone, string $code); + + /**用户信息 + * @return mixed + */ + abstract public function info(); + + /**发送短信 + * @return mixed + */ + abstract public function send(string $phone, string $templateId, array $data); + + /** + * 短信模板 + * @param int $page + * @param int $limit + * @param int $type + * @return mixed + */ + abstract public function temps(int $page, int $limit, int $type); + + + /** + * 申请模板 + * @param string $title + * @param string $content + * @param int $type + * @return mixed + */ + abstract public function apply(string $title, string $content, int $type); + + /** + * 模板记录 + * @param int $tempType + * @param int $page + * @param int $limit + * @return mixed + */ + abstract public function applys(int $tempType, int $page, int $limit); + + /**发送记录 + * @return mixed + */ + abstract public function record($record_id); +} diff --git a/demo/thinkphp/backend/phoenix/services/sms/Sms.php b/demo/thinkphp/backend/phoenix/services/sms/Sms.php new file mode 100644 index 0000000000000000000000000000000000000000..a255b564a292922a79f06263a1c77727b670c2e1 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/sms/Sms.php @@ -0,0 +1,65 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\sms; + +use crmeb\basic\BaseManager; +use crmeb\services\AccessTokenServeService; +use crmeb\services\sms\storage\yihaotong; +use think\Container; +use think\facade\Config; + + +/** + * Class Sms1 + * @package crmeb\services\sms + * @mixin yihaotong + */ +class Sms extends BaseManager +{ + + /** + * 空间名 + * @var string + */ + protected $namespace = '\\crmeb\\services\\sms\\storage\\'; + + /** + * 默认驱动 + * @return mixed + */ + protected function getDefaultDriver() + { + return Config::get('sms.default'); + } + + /** + * 获取类的实例 + * @param $class + * @return mixed|void + */ + protected function invokeClass($class) + { + if (!class_exists($class)) { + throw new \RuntimeException('class not exists: ' . $class); + } + $this->getConfigFile(); + + if (!$this->config) { + $this->config = Config::get($this->configFile . '.stores.' . $this->name, []); + } + + $handleAccessToken = new AccessTokenServeService($this->config['sms_account'] ?? '', $this->config['sms_token'] ?? ''); + $handle = Container::getInstance()->invokeClass($class, [$this->name, $handleAccessToken, $this->configFile, $this->config]); + $this->config = []; + return $handle; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/sms/storage/Aliyun.php b/demo/thinkphp/backend/phoenix/services/sms/storage/Aliyun.php new file mode 100644 index 0000000000000000000000000000000000000000..9fd0f2ecb6e71d449b6e5bb229c8b046df6011b4 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/sms/storage/Aliyun.php @@ -0,0 +1,120 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\sms\storage; + +use AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi; +use AlibabaCloud\SDK\Dysmsapi\V20170525\Models\SendSmsRequest; +use AlibabaCloud\Tea\Exception\TeaError; +use AlibabaCloud\Tea\Utils\Utils\RuntimeOptions; +use crmeb\exceptions\ApiException; +use crmeb\services\sms\BaseSms; +use Darabonba\OpenApi\Models\Config as AliConfig; +use think\exception\ValidateException; +use think\facade\Config; + + +/** + * Class Aliyun + * @package crmeb\services\sms\storage + */ +class Aliyun extends BaseSms +{ + protected $AccessKeyId = ''; + protected $AccessKeySecret = ''; + protected $SignName = ''; + + /** + * @param array $config + * @return mixed|void + */ + protected function initialize(array $config = []) + { + parent::initialize($config); + $this->SignName = $config['aliyun_SignName'] ?? ''; + $this->AccessKeyId = $config['aliyun_AccessKeyId'] ?? ''; + $this->AccessKeySecret = $config['aliyun_AccessKeySecret'] ?? ''; + } + + /** + * 发送短信 + * @param string $phone + * @param string $templateId + * @param array $data + * @return array|bool|mixed + */ + public function send(string $phone, string $templateId, array $data = []) + { + if (empty($phone)) { + return $this->setError('电话号码不能为空'); + } + + $config = new AliConfig([ + "accessKeyId" => $this->AccessKeyId, + "accessKeySecret" => $this->AccessKeySecret + ]); + // 访问的域名 + $config->endpoint = "dysmsapi.aliyuncs.com"; + $client = new Dysmsapi($config); + + if (!$templateId) throw new ApiException('模板不存在:' . $templateId); + + $sendSmsRequest = new SendSmsRequest([ + "phoneNumbers" => $phone, + "signName" => $this->SignName, + "templateCode" => $templateId, + "templateParam" => json_encode($data), + ]); + $runtime = new RuntimeOptions([]); + try { + // 复制代码运行请自行打印 API 的返回值 + $resp = $client->sendSmsWithOptions($sendSmsRequest, $runtime); + if (isset($resp) && $resp->body->code !== 'OK') { + throw new ApiException('【阿里云平台错误提示】:' . $resp->body->message); + } + return [ + 'id' => $resp->body->requestId, + 'content' => json_encode($data), + 'template' => $templateId, + ]; + } catch (\Exception $e) { + throw new ApiException('【阿里云平台错误提示】:' . $e->getMessage()); + } + } + + public function open() + { + } + + public function modify(string $sign = null, string $phone, string $code) + { + } + + public function info() + { + } + + public function temps(int $page = 0, int $limit = 10, int $type = 1) + { + } + + public function apply(string $title, string $content, int $type) + { + } + + public function applys(int $tempType, int $page, int $limit) + { + } + + public function record($record_id) + { + } +} diff --git a/demo/thinkphp/backend/phoenix/services/sms/storage/Chuanglan.php b/demo/thinkphp/backend/phoenix/services/sms/storage/Chuanglan.php new file mode 100644 index 0000000000000000000000000000000000000000..3a5e7592df4c8d90bfbb125ef17f2147b5e09296 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/sms/storage/Chuanglan.php @@ -0,0 +1,261 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\sms\storage; + +use crmeb\services\sms\BaseSms; +use crmeb\exceptions\AdminException; +use think\facade\Config; + + +/** + * Class Chuanglan + * @package crmeb\services\sms\storage + */ +class Chuanglan extends BaseSms +{ + + /** + * 开通 + */ + const SMS_OPEN = 'sms_v2/open'; + + /** + * 修改签名 + */ + const SMS_MODIFY = 'sms_v2/modify'; + + /** + * 用户信息 + */ + const SMS_INFO = 'sms_v2/info'; + + /** + * 发送短信 + */ + const SMS_SEND = 'sms_v2/send'; + + /** + * 短信模板 + */ + const SMS_TEMPS = 'sms_v2/temps'; + + /** + * 申请模板 + */ + const SMS_APPLY = 'sms_v2/apply'; + + /** + * 模板记录 + */ + const SMS_APPLYS = 'sms_v2/applys'; + + /** + * 发送记录 + */ + const SMS_RECORD = 'sms_v2/record'; + + /** + * 获取短信发送状态 + */ + const SMS_STSTUS = 'sms/status'; + + /** + * 短信签名 + * @var string + */ + protected $sign = ''; + + /** + * 模板id + * @var array + */ + protected $templateIds = []; + + /** 初始化 + * @param array $config + */ + protected function initialize(array $config = []) + { + parent::initialize($config); + $this->templateIds = Config::get($this->configFile . '.stores.' . $this->name . '.template_id', []); + + } + + /** + * 提取模板code + * @param string $templateId + * @return null + */ + protected function getTemplateCode(string $templateId) + { + return $this->templateIds[$templateId] ?? null; + } + + /** + * 设置签名 + * @param $sign + * @return $this + */ + public function setSign($sign) + { + $this->sign = $sign; + return $this; + } + + /** + * 获取验证码 + * @param string $phone + * @return array|mixed + */ + public function captcha(string $phone) + { + $params = [ + 'phone' => $phone + ]; + return $this->accessToken->httpRequest('sms/captcha', $params, 'GET', false); + } + + /** + * 开通服务 + * @return array|bool|mixed + */ + public function open() + { + $param = [ + 'sign' => $this->sign + ]; + return $this->accessToken->httpRequest(self::SMS_OPEN, $param); + } + + /** + * 修改签名 + * @param string $sign + * @return array|bool|mixed + */ + public function modify(string $sign = null, string $phone, string $code) + { + $param = [ + 'sign' => $sign ?: $this->sign, + 'verify_code' => $code, + 'phone' => $phone + ]; + return $this->accessToken->httpRequest(self::SMS_MODIFY, $param); + } + + /** + * 获取用户信息 + * @return array|bool|mixed + */ + public function info() + { + return $this->accessToken->httpRequest(self::SMS_INFO, []); + } + + /** + * 获取短信模板 + * @param int $page + * @param int $limit + * @param int $type + * @return array|mixed + */ + public function temps(int $page = 0, int $limit = 10, int $type = 1) + { + $param = [ + 'page' => $page, + 'limit' => $limit, + 'temp_type' => $type + ]; + return $this->accessToken->httpRequest(self::SMS_TEMPS, $param); + } + + /** + * 申请模版 + * @param $title + * @param $content + * @param $type + * @return array|bool|mixed + */ + public function apply(string $title, string $content, int $type) + { + $param = [ + 'title' => $title, + 'content' => $content, + 'type' => $type + ]; + return $this->accessToken->httpRequest(self::SMS_APPLY, $param); + } + + /** + * 申请记录 + * @param $temp_type + * @param int $page + * @param int $limit + * @return array|bool|mixed + */ + public function applys(int $tempType, int $page, int $limit) + { + $param = [ + 'temp_type' => $tempType, + 'page' => $page, + 'limit' => $limit + ]; + return $this->accessToken->httpRequest(self::SMS_APPLYS, $param); + } + + /** + * 发送短信 + * @param $phone + * @param $template + * @param $param + * @return bool|string + */ + public function send(string $phone, string $templateId, array $data = []) + { + if (!$phone) { + throw new AdminException(400719); + } + $param = [ + 'phone' => $phone, + 'host' => request()->host() + ]; + $param['temp_id'] = $this->getTemplateCode($templateId); + if (is_null($param['temp_id'])) { + throw new AdminException(400720); + } + $param['param'] = json_encode($data); + return $this->accessToken->httpRequest(self::SMS_SEND, $param); + } + + /** + * 发送记录 + * @param $record_id + * @return array|bool|mixed + */ + public function record($record_id) + { + $param = [ + 'record_id' => $record_id + ]; + return $this->accessToken->httpRequest(self::SMS_RECORD, $param); + } + + /** + * 获取发送状态 + * @param array $recordIds + * @return array|mixed + */ + public function getStatus(array $recordIds) + { + $data['record_id'] = json_encode($recordIds); + return $this->accessToken->httpRequest(self::SMS_STSTUS, $data, 'POST', false); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/sms/storage/Tencent.php b/demo/thinkphp/backend/phoenix/services/sms/storage/Tencent.php new file mode 100644 index 0000000000000000000000000000000000000000..80b736525faa48f4e8ba6e063efec7eef01eaf5d --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/sms/storage/Tencent.php @@ -0,0 +1,211 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\sms\storage; + + +use crmeb\services\sms\BaseSms; +use crmeb\services\HttpService; + +/** + * 腾讯云短信 + * Class Tencent + * @package crmeb\services\sms\storage + */ +class Tencent extends BaseSms +{ + + //接口请求地址 + const API_URL = 'https://sms.tencentcloudapi.com'; + + /** + * 发送模板id + * @var array + */ + protected $templates = []; + + /** + * @var string[] + */ + protected $header = ['Content-Type:application/json']; + + /** + * @var string + */ + protected $secretId = ''; + + /** + * @var string + */ + protected $secretKey = ''; + + /** + * 短信SDKid + * @var string + */ + protected $smsSdkAppId = ''; + + /** + * 短信签名 + * @var string + */ + protected $signName = ''; + + /** + * @var string + */ + protected $region = "ap-guangzhou"; + + /** + * 版本号 + * @var string + */ + protected $version = "2021-01-11"; + + /** + * 加密方式 + * @var string + */ + protected $algorithm = 'TC3-HMAC-SHA256'; + + /** + * 产品名称 + * @var string + */ + protected $service = 'sms'; + + /** + * @param array $config + * @return mixed|void + */ + protected function initialize(array $config = []) + { + parent::initialize($config); + $this->smsSdkAppId = $config['tencent_sms_app_id'] ?? ''; + $this->secretId = $config['tencent_sms_secret_id'] ?? ''; + $this->secretKey = $config['tencent_sms_secret_key'] ?? ''; + $this->signName = $config['tencent_sms_sign_name'] ?? ''; + $this->region = $config['tencent_sms_region'] ?? ''; + } + + /** + * @param string $phone + * @param string $templateId + * @param array $data + * @return mixed|void + */ + public function send(string $phone, string $templateId, array $data) + { + $body = json_encode([ + 'PhoneNumberSet' => [$phone], + 'SmsSdkAppId' => $this->smsSdkAppId, + 'SignName' => $this->signName, + 'TemplateId' => $templateId, + 'TemplateParamSet' => $data, + ]); + $res = HttpService::request(self::API_URL, 'post', $body, $this->getHeader($body)); + $res = json_decode($res, true); + if (!empty($res['Response']['Error'])) { + return $this->setError($res['Response']['Message']); + } + if ($res['Response']['SendStatusSet'][0]['Code'] != 'Ok') { + return $this->setError($res['Response']['SendStatusSet'][0]['Message']); + } + + return $res; + } + + /** + * 获取请求header + * @param string $boby + * @return string[] + */ + protected function getHeader(string $boby) + { + $host = str_replace(['https://', 'http://'], '', self::API_URL); + $header = [ + 'Content-Type:application/json; charset=utf-8', + 'Host:' . $host, + 'X-TC-Action:SendSms' + ]; + $httpRequestMethod = 'POST'; + $canonicalUri = '/'; + $canonicalQueryString = ''; + $canonicalHeaders = "content-type:application/json; charset=utf-8\n" . "host:" . $host . "\n"; + $signedHeaders = 'content-type;host'; + $hashedRequestPayload = hash("SHA256", $boby); + $canonicalRequest = $httpRequestMethod . "\n" + . $canonicalUri . "\n" + . $canonicalQueryString . "\n" + . $canonicalHeaders . "\n" + . $signedHeaders . "\n" + . $hashedRequestPayload; + + $service = $this->service; + $timestamp = time(); + $date = gmdate("Y-m-d", $timestamp); + $credentialScope = $date . "/" . $service . "/tc3_request"; + + $hashedCanonicalRequest = hash("SHA256", $canonicalRequest); + $stringToSign = $this->algorithm . "\n" + . $timestamp . "\n" + . $credentialScope . "\n" + . $hashedCanonicalRequest; + + $secretDate = hash_hmac("SHA256", $date, "TC3" . $this->secretKey, true); + $secretService = hash_hmac("SHA256", $service, $secretDate, true); + $secretSigning = hash_hmac("SHA256", "tc3_request", $secretService, true); + $signature = hash_hmac("SHA256", $stringToSign, $secretSigning); + $authorization = $this->algorithm + . " Credential=" . $this->secretId . "/" . $credentialScope + . ", SignedHeaders=content-type;host, Signature=" . $signature; + + array_push($header, 'Authorization:' . $authorization, 'X-TC-Timestamp:' . $timestamp, 'X-TC-Version:' . $this->version, + 'X-TC-Region:' . $this->region); + + return $header; + } + + public function open() + { + // TODO: Implement open() method. + } + + public function modify(string $sign = null, string $phone = '', string $code = '') + { + // TODO: Implement modify() method. + } + + public function info() + { + // TODO: Implement info() method. + } + + public function temps(int $page, int $limit, int $type) + { + // TODO: Implement temps() method. + } + + public function apply(string $title, string $content, int $type) + { + // TODO: Implement apply() method. + } + + public function applys(int $tempType, int $page, int $limit) + { + // TODO: Implement applys() method. + } + + public function record($record_id) + { + // TODO: Implement record() method. + } +} diff --git a/demo/thinkphp/backend/phoenix/services/sms/storage/Yihaotong.php b/demo/thinkphp/backend/phoenix/services/sms/storage/Yihaotong.php new file mode 100644 index 0000000000000000000000000000000000000000..502070e03eb0741dc6424a6c795353c3fbb36dfd --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/sms/storage/Yihaotong.php @@ -0,0 +1,244 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\sms\storage; + +use crmeb\services\sms\BaseSms; +use crmeb\exceptions\AdminException; +use think\facade\Config; + + +/** + * Class yihaotong + * @package crmeb\services\sms\storage + */ +class Yihaotong extends BaseSms +{ + + /** + * 开通 + */ + const SMS_OPEN = 'sms_v2/open'; + + /** + * 修改签名 + */ + const SMS_MODIFY = 'sms_v2/modify'; + + /** + * 用户信息 + */ + const SMS_INFO = 'sms_v2/info'; + + /** + * 发送短信 + */ + const SMS_SEND = 'sms_v2/send'; + + /** + * 短信模板 + */ + const SMS_TEMPS = 'sms_v2/temps'; + + /** + * 申请模板 + */ + const SMS_APPLY = 'sms_v2/apply'; + + /** + * 模板记录 + */ + const SMS_APPLYS = 'sms_v2/applys'; + + /** + * 发送记录 + */ + const SMS_RECORD = 'sms_v2/record'; + + /** + * 获取短信发送状态 + */ + const SMS_STSTUS = 'sms/status'; + + /** + * 短信签名 + * @var string + */ + protected $sign = ''; + + /** 初始化 + * @param array $config + */ + protected function initialize(array $config = []) + { + parent::initialize($config); + } + + + /** + * 设置签名 + * @param $sign + * @return $this + */ + public function setSign($sign) + { + $this->sign = $sign; + return $this; + } + + /** + * 获取验证码 + * @param string $phone + * @return array|mixed + */ + public function captcha(string $phone) + { + $params = [ + 'phone' => $phone + ]; + return $this->accessToken->httpRequest('sms/captcha', $params, 'GET', false); + } + + /** + * 开通服务 + * @return array|bool|mixed + */ + public function open() + { + $param = [ + 'sign' => $this->sign + ]; + return $this->accessToken->httpRequest(self::SMS_OPEN, $param); + } + + /** + * 修改签名 + * @param string $sign + * @return array|bool|mixed + */ + public function modify(string $sign = null, string $phone, string $code) + { + $param = [ + 'sign' => $sign ?: $this->sign, + 'verify_code' => $code, + 'phone' => $phone + ]; + return $this->accessToken->httpRequest(self::SMS_MODIFY, $param); + } + + /** + * 获取用户信息 + * @return array|bool|mixed + */ + public function info() + { + return $this->accessToken->httpRequest(self::SMS_INFO, []); + } + + /** + * 获取短信模板 + * @param int $page + * @param int $limit + * @param int $type + * @return array|mixed + */ + public function temps(int $page = 0, int $limit = 10, int $type = 1) + { + $param = [ + 'page' => $page, + 'limit' => $limit, + 'temp_type' => $type + ]; + return $this->accessToken->httpRequest(self::SMS_TEMPS, $param); + } + + /** + * 申请模版 + * @param $title + * @param $content + * @param $type + * @return array|bool|mixed + */ + public function apply(string $title, string $content, int $type) + { + $param = [ + 'title' => $title, + 'content' => $content, + 'type' => $type + ]; + return $this->accessToken->httpRequest(self::SMS_APPLY, $param); + } + + /** + * 申请记录 + * @param $temp_type + * @param int $page + * @param int $limit + * @return array|bool|mixed + */ + public function applys(int $tempType, int $page, int $limit) + { + $param = [ + 'temp_type' => $tempType, + 'page' => $page, + 'limit' => $limit + ]; + return $this->accessToken->httpRequest(self::SMS_APPLYS, $param); + } + + /** + * 发送短信 + * @param $phone + * @param $template + * @param $param + * @return bool|string + */ + public function send(string $phone, string $templateId, array $data = []) + { + if (!$phone) { + throw new AdminException(400719); + } + $param = [ + 'phone' => $phone, + 'host' => request()->host() + ]; + $param['temp_id'] = $templateId; + if (is_null($param['temp_id'])) { + throw new AdminException(400720); + } + $param['param'] = json_encode($data); + return $this->accessToken->httpRequest(self::SMS_SEND, $param); + } + + /** + * 发送记录 + * @param $record_id + * @return array|bool|mixed + */ + public function record($record_id) + { + $param = [ + 'record_id' => $record_id + ]; + return $this->accessToken->httpRequest(self::SMS_RECORD, $param); + } + + /** + * 获取发送状态 + * @param array $recordIds + * @return array|mixed + */ + public function getStatus(array $recordIds) + { + $data['record_id'] = json_encode($recordIds); + return $this->accessToken->httpRequest(self::SMS_STSTUS, $data, 'POST', false); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/template/BaseMessage.php b/demo/thinkphp/backend/phoenix/services/template/BaseMessage.php new file mode 100644 index 0000000000000000000000000000000000000000..dc9ba025ec154fd5ef60a1fa7219d8903af8193c --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/template/BaseMessage.php @@ -0,0 +1,153 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\template; + +use crmeb\basic\BaseStorage; +use think\facade\Config; + +abstract class BaseMessage extends BaseStorage +{ + /** + * 模板id + * @var array + */ + protected $templateIds = []; + + /** + * openId + * @var string + */ + protected $openId; + + /** + * 跳转链接 + * @var string + */ + protected $toUrl; + + /** + * 颜色 + * @var string + */ + protected $color; + + /** + * 初始化 + * @param array $config + * @return mixed|void + */ + protected function initialize(array $config) + { + $this->templateIds = Config::get($this->configFile . '.stores.' . $this->name . '.template_id', []); + } + + /** + * 是否记录日志 + * @return mixed + */ + public function isLog() + { + $isLog = Config::get($this->configFile . 'isLog', false); + return Config::get($this->configFile . '.stores.' . $this->name . '.isLog', $isLog); + } + + /** + * 获取模板id + * @return array + */ + public function getTemplateId() + { + return $this->templateIds; + } + + /** + * openid + * @param string $openId + * @return $this + */ + public function to(string $openId) + { + $this->openId = $openId; + return $this; + } + + /** + * 跳转路径 + * @param string $url + * @return $this + */ + public function url(string $url) + { + $this->toUrl = $url; + return $this; + } + + /** + * 设置背景颜色 + * @param string $color + * @return $this + */ + public function color(?string $color) + { + $this->color = $color; + return $this; + } + + /** + * 提取模板code + * @param string $templateId + * @return null + */ + protected function getTemplateCode(string $templateId) + { + return $this->templateIds[$templateId] ?? null; + } + + /** + * 恢复默认值 + */ + protected function clear() + { + $this->openId = null; + $this->toUrl = null; + $this->color = null; + } + + /** + * 发送消息 + * @param string $templateId + * @param array $data + * @return mixed + */ + abstract public function send(string $templateId, array $data = []); + + /** + * 添加模板 + * @param string $shortId + * @return mixed + */ + abstract public function add(string $shortId); + + /** + * 删除模板 + * @param string $templateId + * @return mixed + */ + abstract public function delete(string $templateId); + + /** + * 获取所有模板 + * @return mixed + */ + abstract public function list(); + +} diff --git a/demo/thinkphp/backend/phoenix/services/template/Template.php b/demo/thinkphp/backend/phoenix/services/template/Template.php new file mode 100644 index 0000000000000000000000000000000000000000..c36e6ac6096e86bf04e71c0ff32da282bfa236e3 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/template/Template.php @@ -0,0 +1,40 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\template; + +use crmeb\basic\BaseManager; +use think\facade\Config; + +/** + * Class Template + * @package crmeb\services\template + * @mixin \crmeb\services\template\storage\Wechat + * @mixin \crmeb\services\template\storage\Subscribe + */ +class Template extends BaseManager +{ + + /** + * 空间名 + * @var string + */ + protected $namespace = '\\crmeb\\services\\template\\storage\\'; + + /** + * 设置默认扩展 + * @return mixed|string + */ + protected function getDefaultDriver() + { + return 'wechat'; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/template/storage/Baidu.php b/demo/thinkphp/backend/phoenix/services/template/storage/Baidu.php new file mode 100644 index 0000000000000000000000000000000000000000..b885a435ab83c8af21aea22607a0d13ed2b8e6d8 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/template/storage/Baidu.php @@ -0,0 +1,68 @@ + +// +---------------------------------------------------------------------- + +namespace crmeb\services\template\storage; + + +use crmeb\services\template\BaseMessage; + +class Baidu extends BaseMessage +{ + /** + * 初始化 + * @param array $config + * @return mixed|void + */ + protected function initialize(array $config) + { + parent::initialize($config); // TODO: Change the autogenerated stub + } + + /** + * 发送模板消息 + * @param string $templateId + * @param array $data + * @return mixed|void + */ + public function send(string $templateId, array $data = []) + { + // TODO: Implement send() method. + } + + /** + * 添加模板消息 + * @param string $shortId + * @return mixed|void + */ + public function add(string $shortId) + { + // TODO: Implement add() method. + } + + /** + * 删除模板消息 + * @param string $templateId + * @return mixed|void + */ + public function delete(string $templateId) + { + // TODO: Implement delete() method. + } + + /** + * 模板消息列表 + * @return mixed|void + */ + public function list() + { + // TODO: Implement list() method. + } +} diff --git a/demo/thinkphp/backend/phoenix/services/template/storage/Subscribe.php b/demo/thinkphp/backend/phoenix/services/template/storage/Subscribe.php new file mode 100644 index 0000000000000000000000000000000000000000..839b67a740196764c4deecaea3f0dc5d7e57ca1f --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/template/storage/Subscribe.php @@ -0,0 +1,103 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\template\storage; + +use app\services\message\TemplateMessageServices; +use crmeb\services\template\BaseMessage; +use crmeb\services\app\MiniProgramService; +use think\facade\Log; + +/** + * 订阅消息 + * Class Subscribe + * @package crmeb\services\template\storage + */ +class Subscribe extends BaseMessage +{ + protected $error; + + protected function initialize(array $config) + { + parent::initialize($config); // TODO: Change the autogenerated stub + } + + /** + * @param string $templateId + * @return mixed + */ + public function getTempId(string $templateId) + { + /** @var TemplateMessageServices $services */ + $services = app()->make(TemplateMessageServices::class); + return $services->getTempId($templateId); + } + + /** + * 发送订阅消息 + * @param string $tempid + * @param array $data + * @return bool|\EasyWeChat\Support\Collection|mixed|null + */ + public function send(string $tempid, array $data = []) + { + if (!$tempid) { + return $this->setError('Template ID does not exist'); + } + if (!$this->openId) { + return $this->setError('Openid does not exist'); + } + try { + $res = MiniProgramService::sendSubscribeTemlate($this->openId, $tempid, $data, $this->toUrl); + $this->clear(); + return $res; + } catch (\Throwable $e) { + $this->isLog() && Log::error('发送给openid为:' . $this->openId . '小程序订阅消息失败,模板id为:' . $tempid . ';错误原因为:' . $e->getMessage()); + return $this->setError($e->getMessage()); + } + } + + public function delete(string $templateId) + { + // TODO: Implement delete() method. + } + + public function add(string $shortId) + { + // TODO: Implement add() method. + } + + public function list() + { + // TODO: Implement list() method. + } + + /** + * 设置错误信息 + * @param string|null $error + * @return bool + */ + protected function setError(?string $error = null) + { + $this->error = $error ?: '未知错误'; + return false; + } + + /** + * 获取错误信息 + * @return string + */ + public function getError() + { + $error = $this->error; + $this->error = null; + return $error; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/template/storage/Wechat.php b/demo/thinkphp/backend/phoenix/services/template/storage/Wechat.php new file mode 100644 index 0000000000000000000000000000000000000000..87945b55355de08faeaa0d96c26601ffd1eb5102 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/template/storage/Wechat.php @@ -0,0 +1,135 @@ + +// +---------------------------------------------------------------------- +namespace crmeb\services\template\storage; + +use app\services\message\TemplateMessageServices; +use crmeb\services\template\BaseMessage; +use crmeb\services\app\WechatService; +use think\facade\Log; + +class Wechat extends BaseMessage +{ + protected $error; + + /** + * 初始化 + * @param array $config + * @return mixed|void + */ + protected function initialize(array $config) + { + parent::initialize($config); // TODO: Change the autogenerated stub + } + + /** + * @param string $templateId + * @return mixed + */ + public function getTempId(string $templateId) + { + /** @var TemplateMessageServices $services */ + $services = app()->make(TemplateMessageServices::class); + return $services->getTempId($templateId, 1); + } + + /** + * 发送消息 + * @param string $tempid + * @param array $data + * @return bool|mixed + */ + public function send(string $tempid, array $data = []) + { + if (!$tempid) { + return $this->setError('Template ID does not exist'); + } + if (!$this->openId) { + return $this->setError('Openid does not exist'); + } + try { + $res = WechatService::sendTemplate($this->openId, $tempid, $data, $this->toUrl, $this->color); + $this->clear(); + return $res; + } catch (\Exception $e) { + $this->isLog() && Log::error('发送给openid为:' . $this->openId . '微信模板消息失败,模板id为:' . $tempid . ';错误原因为:' . $e->getMessage()); + return $this->setError($e->getMessage()); + } + } + + /** + * 获取所有模板 + * @return \EasyWeChat\Support\Collection|mixed + */ + public function list() + { + return WechatService::noticeService()->getPrivateTemplates(); + } + + /** + * 添加模板消息 + * @param string $shortId + * @return \EasyWeChat\Support\Collection|mixed + */ + public function add(string $shortId) + { + return WechatService::noticeService()->addTemplate($shortId); + } + + /** + * 删除模板消息 + * @param string $templateId + * @return \EasyWeChat\Support\Collection|mixed + */ + public function delete(string $templateId) + { + return WechatService::noticeService()->deletePrivateTemplate($templateId); + } + + /** + * 返回所有支持的行业列表 + * @return \EasyWeChat\Support\Collection + */ + public function getIndustry() + { + return WechatService::noticeService()->getIndustry(); + } + + /** + * 设置模版消息行业 + * @return \EasyWeChat\Support\Collection + */ + public function setIndustry($one, $two) + { + return WechatService::noticeService()->setIndustry($one, $two); + } + + /** + * 设置错误信息 + * @param string|null $error + * @return bool + */ + protected function setError(?string $error = null) + { + $this->error = $error ?: '未知错误'; + return false; + } + + /** + * 获取错误信息 + * @return string + */ + public function getError() + { + $error = $this->error; + $this->error = null; + return $error; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/upload/BaseUpload.php b/demo/thinkphp/backend/phoenix/services/upload/BaseUpload.php new file mode 100644 index 0000000000000000000000000000000000000000..840c8b179411820589a8a5f6d9156582bf5d8eaf --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/upload/BaseUpload.php @@ -0,0 +1,506 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\services\upload; + +use phoenix\basic\BaseStorage; +use think\facade\Config; + +/** + * Class BaseUpload + * + * @package crmeb\basic + */ +abstract class BaseUpload extends BaseStorage +{ + /** + * 缩略图 + * + * @var string[] + */ + protected array $thumb = ['big', 'mid', 'small']; + + /** + * 缩略图配置 + * + * @var array + */ + protected array $thumbConfig = [ + 'thumb_big_height' => 800, + 'thumb_big_width' => 800, + 'thumb_mid_height' => 300, + 'thumb_mid_width' => 300, + 'thumb_small_height' => 100, + 'thumb_small_width' => 100, + ]; + /** + * 水印配置 + * + * @var array + */ + protected array $waterConfig = [ + 'image_watermark_status' => 0, + 'watermark_type' => 1, + 'watermark_image' => '', + 'watermark_opacity' => 0, + 'watermark_position' => 1, + 'watermark_rotate' => 0, + 'watermark_text' => '', + 'watermark_text_angle' => "", + 'watermark_text_color' => '#000000', + 'watermark_text_size' => '5', + 'watermark_text_font' => '', + 'watermark_x' => 0, + 'watermark_y' => 0, + ]; + /** + * 图片信息 + * + * @var array|object + */ + protected array|object $fileInfo; + + /** + * 下载图片信息 + */ + protected $downFileInfo; + + /** + * 要生成缩略图、水印的图片地址 + * + * @var string + */ + protected string $filePath; + + /** + * 验证配置 + * + * @var string|array + */ + protected array|string $validate; + + /** + * 保存路径 + * + * @var string + */ + protected string $path = ''; + + /** + * 是否自动裁剪 + * + * @var bool + */ + protected bool $authThumb = true; + + protected function initialize(array $config) + { + $this->fileInfo = $this->downFileInfo = new \StdClass(); + $thumbConfig = $this->thumbConfig; + $config['thumb'] = $config['thumb'] ?? []; + $this->thumbConfig = $config['thumb'] ?? []; + foreach ($config['thumb'] as $item) { + if ($item == '' || $item == 0) { + $this->thumbConfig = $thumbConfig; + } + } + $this->waterConfig = array_merge($this->waterConfig, $config['water'] ?? []); + } + + /** + * 设置处理缩略图、水印图片路径 + * + * @param string $filePath + * + * @return $this + */ + public function setFilepath(string $filePath): static + { + $this->filePath = str_starts_with($filePath, '.') ? substr($filePath, 1) : $filePath; + return $this; + } + + /** + * 是否自动裁剪 + * + * @param bool $auth + * + * @return $this + */ + public function setAuthThumb(bool $auth): static + { + $this->authThumb = $auth; + return $this; + } + + /** + * 上传文件路径 + * + * @param string $path + * + * @return $this + */ + public function to(string $path): static + { + $this->path = $path; + return $this; + } + + /** + * 获取文件信息 + * + * @return array + */ + public function getFileInfo(): array + { + return $this->fileInfo; + } + + /** + * 检测是否是图片 + * + * @param $filePath + * + * @return bool + */ + protected function checkImage($filePath): bool + { + //获取图像信息 + $info = @getimagesize($filePath); + //检测图像合法性 + if (false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))) { + return false; + } + return true; + } + + /** + * 验证合法上传域名 + * + * @param string $url + * + * @return string + */ + protected function checkUploadUrl(string $url): string + { + if ($url && !str_contains($url, 'http')) { + $url = 'http://' . $url; + } + return $url; + } + + /** + * 获取系统配置 + * + * @return mixed + */ + protected function getConfig(): mixed + { + $config['filesize'] = Config::get($this->configFile . '.filesize', []); + $config['fileExt'] = Config::get($this->configFile . '.fileExt', []); + $config['fileMime'] = Config::get($this->configFile . '.fileMime', []); + return $config; + } + + /** + * 设置验证规则 + * + * @param array|null $validate + * + * @return $this + */ + public function validate(?array $validate = null): static + { + if (is_null($validate)) { + $validate = $this->getConfig(); + } + $this->validate = $validate; + return $this; + } + + /** + * 验证目录是否正确 + * + * @param string $key + * + * @return false|string + */ + protected function getUploadPath(string $key): bool|string + { + $path = ($this->path ? $this->path . '/' : '') . $key; + if ($path && $path[0] === '/') { + $path = substr($path, 1); + } + return $path; + } + + /** + * 提取文件名 + * + * @param string|null $path + * @param string $ext + * + * @return string + */ + protected function saveFileName(string $path = null, string $ext = 'jpg'): string + { + return ($path ? substr(md5($path), 0, 5) : '') . date('YmdHis') . rand(0, 9999) . '.' . $ext; + } + + /** + * 提取文件后缀以及之前部分 + * + * @param string $path + * + * @return false|string[] + */ + protected function getFileName(string $path): array|bool + { + $_empty = ['', '']; + if (!$path) return $_empty; + if (strpos($path, '?')) { + $_tarr = explode('?', $path); + $path = trim($_tarr[0]); + } + $arr = explode('.', $path); + if (!is_array($arr) || count($arr) <= 1) return $_empty; + $ext_name = trim($arr[count($arr) - 1]); + $ext_name = !$ext_name ? 'jpg' : $ext_name; + return [explode('.' . $ext_name, $path)[0], $ext_name]; + } + + /** + * 获取图片地址 + * + * @param string $filePath + * @param bool $is_parse_url + * + * @return string + */ + protected function getFilePath(string $filePath = '', bool $is_parse_url = false): string + { + $path = $filePath ?: $this->filePath; + if ($is_parse_url) { + $data = parse_url($path); + //远程地址处理 + if (isset($data['host']) && isset($data['path'])) { + if (file_exists(app()->getRootPath() . 'public' . $data['path'])) { + $path = $data['path']; + } + } + } + return $path; + } + + /** + * 获取文件类型和大小 + * + * @param string $url + * @param bool $isData + * + * @return array + */ + protected function getFileHeaders(string $url, bool $isData = true): array + { + stream_context_set_default(['ssl' => ['verify_peer' => false, 'verify_peer_name' => false]]); + $header['size'] = 0; + $header['type'] = 'image/jpeg'; + if (!$isData) { + return $header; + } + try { + $headerArray = get_headers(str_replace('\\', '/', $url), true); + if (!isset($headerArray['Content-Length'])) { + $header['size'] = 0; + } + if (!isset($headerArray['Content-Type'])) { + $header['type'] = 'image/jpeg'; + } + if (is_array($headerArray['Content-Length']) && count($headerArray['Content-Length']) == 2) { + $header['size'] = $headerArray['Content-Length'][1]; + } + if (is_array($headerArray['Content-Type']) && count($headerArray['Content-Type']) == 2) { + $header['type'] = $headerArray['Content-Type'][1]; + } + } catch (\Exception $e) { + } + return $header; + } + + /** + * 获取上传信息 + * + * @return array + */ + public function getUploadInfo(): array + { + if (isset($this->fileInfo->filePath)) { + if (!str_contains($this->fileInfo->filePath, 'http')) { + $url = request()->domain() . $this->fileInfo->filePath; + } else { + $url = $this->fileInfo->filePath; + } + $headers = $this->getFileHeaders($url); + return [ + 'name' => $this->fileInfo->fileName, + 'real_name' => $this->fileInfo->realName ?? '', + 'size' => !empty($headers['size']) ? $headers['size'] : $this->fileInfo->uploadInfo->getSize(), + 'type' => !empty($headers['type']) ? $headers['type'] : $this->fileInfo->uploadInfo->getType(), + 'dir' => $this->fileInfo->filePath, + 'ext' => $this->fileInfo->uploadInfo->getExtension(), + 'thumb_path' => $this->fileInfo->filePath, + 'thumb_path_big' => $this->fileInfo->filePathBig ?? '', + 'thumb_path_mid' => $this->fileInfo->filePathMid ?? '', + 'thumb_path_small' => $this->fileInfo->filePathSmall ?? '', + 'thumb_path_water' => $this->fileInfo->filePathWater ?? '', + 'time' => time(), + ]; + } else { + return []; + } + } + + /** + * 获取下载信息 + * + * @return array + */ + public function getDownloadInfo(): array + { + if (isset($this->downFileInfo->downloadFilePath)) { + if (!str_contains($this->downFileInfo->downloadFilePath, 'http')) { + $url = request()->domain() . $this->downFileInfo->downloadFilePath; + } else { + $url = $this->downFileInfo->downloadFilePath; + } + $headers = $this->getFileHeaders($url); + return [ + 'name' => $this->downFileInfo->downloadFileName, + 'real_name' => $this->downFileInfo->downloadRealName ?? '', + 'size' => $headers['size'] ?? 0, + 'type' => $headers['type'] ?? 'image/jpeg', + 'dir' => $this->downFileInfo->downloadFilePath ?? '', + 'thumb_path' => $this->downFileInfo->downloadFilePath ?? '', + 'time' => time(), + ]; + } else { + return []; + } + } + + /** + * 文件上传 + * + * @param string $file + * + * @return mixed + */ + abstract public function move(string $file = 'file'): mixed; + + /** + * 文件流上传 + * + * @param $fileContent + * @param string|null $key + * + * @return mixed + */ + abstract public function stream($fileContent, string $key = null): mixed; + + /** + * 删除文件 + * + * @param string $filePath + * + * @return mixed + */ + abstract public function delete(string $filePath): mixed; + + /** + * 实例化上传 + * + * @return mixed + */ + abstract protected function app(); + + /** + * 创建空间 + * + * @param string $name + * @param string $region ; + * + * @return mixed + */ + abstract public function createBucket(string $name, string $region); + + /** + * 获得区域 + * + * @return mixed + */ + abstract public function getRegion(); + + /** + * 删除空间 + * + * @param string $name + * + * @return mixed + */ + abstract public function deleteBucket(string $name); + + /** + * 绑定自定义域名 + * + * @param string $name + * @param string $domain + * @param string|null $region + * + * @return mixed + */ + abstract public function bindDomian(string $name, string $domain, string $region = null); + + /** + * 设置跨域 + * + * @param string $name + * @param string $region + * + * @return mixed + */ + abstract public function setBucketCors(string $name, string $region); + + /** + * 获取上传密钥 + * + * @return mixed + */ + abstract public function getTempKeys(); + + /** + * 获取缩略图 + * + * @param string $filePath + * + * @return mixed + */ + abstract public function thumb(string $filePath = ''); + + /** + * 添加水印 + * + * @param string $filePath + * + * @return mixed + */ + abstract public function water(string $filePath = ''); + +} diff --git a/demo/thinkphp/backend/phoenix/services/upload/Upload.php b/demo/thinkphp/backend/phoenix/services/upload/Upload.php new file mode 100644 index 0000000000000000000000000000000000000000..5375d53a35a8bba9d27da33650f4a3c47e32d084 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/upload/Upload.php @@ -0,0 +1,46 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\services\upload; + +use phoenix\basic\BaseManager; +use think\facade\Config; + + +/** + * Upload + * + * @author Mr.April + * @since 1.0 + * @mixin \phoenix\services\upload\storage\Local + * @mixin \phoenix\services\upload\storage\OSS + * @mixin \phoenix\services\upload\storage\COS + * @mixin \phoenix\services\upload\storage\Qiniu + */ +class Upload extends BaseManager +{ + /** + * 空间名 + * + * @var string + */ + protected $namespace = '\\phoenix\\services\\upload\\storage\\'; + + /** + * 设置默认上传类型 + * + * @return mixed + */ + protected function getDefaultDriver(): mixed + { + return Config::get('upload.default', 'local'); + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/upload/extend/cos/Client.php b/demo/thinkphp/backend/phoenix/services/upload/extend/cos/Client.php new file mode 100644 index 0000000000000000000000000000000000000000..febf2e602d04b5ae8fa3be670a0b0539a18f00c8 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/upload/extend/cos/Client.php @@ -0,0 +1,574 @@ + + * +---------------------------------------------------------------------- + */ + +namespace phoenix\services\upload\extend\cos; + +use phoenix\exceptions\UploadException; + +/** + * Class Client + * + * @author Mr.April + * @since 1.0 + */ +class Client +{ + + /** + * @var string + */ + protected $accessKey; + + /** + * @var string + */ + protected $secretKey; + + /** + * @var string + */ + protected $appid; + + /** + * @var mixed|string + */ + protected $bucket; + + /** + * @var mixed|string + */ + protected $region; + + /** + * @var mixed|string + */ + protected $uploadUrl; + + /** + * @var string + */ + protected $action = ''; + + /** + * @var array + */ + protected $response = ['content' => null, 'code' => 200, 'header' => []]; + + /** + * @var array + */ + protected $request = ['header' => [], 'body' => [], 'host' => '']; + + /** + * @var string + */ + protected $cosacl = 'public-read'; + + /** + * Client constructor. + * @param array $config + */ + public function __construct(array $config) + { + $this->accessKey = $config['accessKey'] ?? ''; + $this->secretKey = $config['secretKey'] ?? ''; + $this->appid = $config['appid'] ?? ''; + $this->bucket = $config['bucket'] ?? ''; + $this->region = $config['region'] ?? 'ap-chengdu'; + $this->uploadUrl = $config['uploadUrl'] ?? ''; + } + + /** + * 获取实际请求 + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/17 + */ + public function getResponse() + { + $response = $this->response; + + $this->response = ['content' => null, 'http_code' => 200, 'header' => []]; + + return $response; + } + + /** + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/17 + */ + public function getRequest() + { + $request = $this->request; + + $this->request = ['header' => [], 'body' => [], 'host' => '']; + + return $request; + } + + /** + * 拼接请求地址 + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/29 + */ + protected function makeUpUrl() + { + return $this->bucket . '.cos.' . $this->region . '.myqcloud.com'; + } + + /** + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/29 + */ + protected function ssl() + { + return strstr($this->uploadUrl, 'https://') !== false; + } + + /** + * 检查参数 + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/29 + */ + protected function checkOptions() + { + if (!$this->bucket) { + throw new UploadException('请传入桶名'); + } + if (!$this->region) { + throw new UploadException('请传入所属地域'); + } + if (!$this->accessKey) { + throw new UploadException('请传入SecretId'); + } + if (!$this->secretKey) { + throw new UploadException('请传入SecretKey'); + } + } + + /** + * 上传文件 + * @param string $key + * @param $body + * @return string[] + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/29 + */ + public function putObject(string $key, $body) + { + + $this->checkOptions(); + + $url = $this->makeUpUrl(); + + $header = [ + 'Content-Type' => 'image/jpeg', + 'x-cos-acl' => $this->cosacl, + 'Content-MD5' => base64_encode(md5($body, true)), + 'Host' => $url + ]; + + $imageUrl = ($this->ssl() ? 'https://' : 'http://') . $url . '/' . $key; + + $res = $this->request($imageUrl, 'PUT', ['body' => $body], $header); + + if ($res && !empty($res['Message'])) { + throw new UploadException($res['Message']); + } + + return [ + 'name' => $key, + 'path' => $imageUrl + ]; + } + + /** + * 删除文件 + * @param string $bucket + * @param string $key + * @return array|false + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/19 + */ + public function deleteObject(string $bucket, string $key) + { + $url = $this->getRequestHost($bucket); + + $header = [ + 'Host' => $url + ]; + + $res = $this->request('https://' . $url . '/' . $key, 'delete', [], $header); + + if ($res && !empty($res['Message'])) { + throw new UploadException($res['Message']); + } + + return $res; + } + + /** + * 获取桶列表 + * @return array|false|\SimpleXMLElement|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/19 + */ + public function listBuckets() + { + $url = 'service.cos.myqcloud.com'; + + $header = [ + 'Host' => $url + ]; + + $res = $this->request('https://' . $url . '/', 'get', [], $header); + + if ($res && !empty($res['Message'])) { + throw new UploadException($res['Message']); + } + + return $res; + } + + /** + * 检测桶,不存在返回true + * @param string $bucket + * @param string $region + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/17 + */ + public function headBucket(string $bucket, string $region = '') + { + $url = $this->getRequestHost($bucket, $region); + + $header = [ + 'Host' => $url + ]; + + $this->request('https://' . $url, 'head', [], $header); + + $response = $this->getResponse(); + + return $response['code'] == 404; + } + + /** + * 创建桶 + * @param string $bucket + * @param string $region + * @param string $acl + * @return array|false|\SimpleXMLElement|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/17 + */ + public function createBucket(string $bucket, string $region = '', string $acl = 'public-read') + { + return $this->noBodyRequest('put', $bucket, $region, $acl); + } + + /** + * 组合成xml + * @param array $data + * @param string $root + * @param string $itemKey + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/17 + */ + protected function xmlBuild(array $xmlAttr, string $root = 'xml', string $itemKey = 'item') + { + $xml = '<' . $root . '>'; + $xml .= '<' . $itemKey . '>'; + + foreach ($xmlAttr as $kk => $vv) { + if (is_array($vv)) { + foreach ($vv as $v) { + $xml .= '<' . $kk . '>' . $v . ''; + } + } else { + $xml .= '<' . $kk . '>' . $vv . ''; + } + } + $xml .= ''; + $xml .= ''; + + return $xml; + } + + /** + * 设置跨域 + * @param string $bucket + * @param string $region + * @param array $data + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/17 + */ + public function putBucketCors(string $bucket, array $data, string $region = '') + { + $url = $this->getRequestHost($bucket, $region); + + $xml = $this->xmlBuild($data, 'CORSConfiguration', 'CORSRule'); + + $header = [ + 'Host' => $url, + 'Content-Type' => 'application/xml', + 'Content-Length' => strlen($xml), + 'Content-MD5' => base64_encode(md5($xml, true)) + ]; + + $res = $this->request('https://' . $url . '/?cors', 'put', ['xml' => $xml], $header); + + if ($res && !empty($res['Message'])) { + throw new UploadException($res['Message']); + } + + return $res; + } + + /** + * 删除 + * @param string $name + * @param string $region + * @return array|false|\SimpleXMLElement|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/17 + */ + public function deleteBucket(string $name, string $region = '') + { + return $this->noBodyRequest('delete', $name, $region); + } + + /** + * 获取桶下的 + * @param string $name + * @param string $region + * @return array|false|\SimpleXMLElement|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/17 + */ + public function getBucketDomain(string $name, string $region = '') + { + $this->action = 'domain'; + return $this->noBodyRequest('get', $name, $region); + } + + /** + * 绑定域名 + * @param string $bucket + * @param string $region + * @param array $data + * @return array|false|\SimpleXMLElement|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/19 + */ + public function putBucketDomain(string $bucket, string $region, array $data) + { + $url = $this->getRequestHost($bucket, $region); + + $xml = $this->xmlBuild($data, 'DomainConfiguration', 'DomainRule'); + + $header = [ + 'Host' => $url, + 'Content-Type' => 'application/xml', + 'Content-Length' => strlen($xml), + 'Content-MD5' => base64_encode(md5($xml, true)) + ]; + + $res = $this->request('https://' . $url . '/?domain', 'put', ['xml' => $xml], $header); + + if ($res && !empty($res['Message'])) { + throw new UploadException($res['Message']); + } + + return $res; + } + + /** + * @param string $bucket + * @param string $region + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/17 + */ + protected function getRequestHost(string $bucket, string $region = '') + { + if (!$this->accessKey) { + throw new UploadException('请传入SecretId'); + } + if (!$this->secretKey) { + throw new UploadException('请传入SecretKey'); + } + + if (strstr($bucket, '-') === false) { + $bucket = $bucket . '-' . $this->appid; + } + + return $bucket . '.cos.' . ($region ?: $this->region) . '.myqcloud.com'; + } + + /** + * @param string $method + * @param string $bucket + * @param string $region + * @param string|null $acl + * @return array|false|\SimpleXMLElement|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/10/17 + */ + public function noBodyRequest(string $method, string $bucket, string $region = '', string $acl = null, bool $isExc = true) + { + + $url = $this->getRequestHost($bucket, $region); + + $header = [ + 'Host' => $url + ]; + + if ($acl) { + $header['x-cos-acl'] = $acl; + } + + if (in_array($method, ['put', 'post'])) { + $header['Content-Length'] = 0; + } + + $res = $this->request('https://' . $url . '/' . ($this->action ? '?' . $this->action : ''), $method, [], $header); + $this->action = ''; + + if ($isExc) { + if ($res && !empty($res['Message'])) { + throw new UploadException($res['Message']); + } + } + + return $res; + } + + /** + * 发起请求 + * @param string $url + * @param string $method + * @param array $data + * @param array $header + * @param int $timeout + * @return array|false|\SimpleXMLElement|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/29 + */ + public function request(string $url, string $method, array $data, array $header = [], int $timeout = 5) + { + + $this->request['body'] = $data; + $this->request['host'] = $url; + + + $urlAttr = parse_url($url); + $curl = curl_init($url); + $method = strtoupper($method); + //请求方式 + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); + + //超时时间 + curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); + //设置header头 + + $header = array_merge($header, $this->getSign($url, $method, $urlAttr['path'] ?? '', [], $header)); + + $this->request['header'] = $header; + + $clientHeader = []; + foreach ($header as $key => $item) { + $clientHeader[] = $key . ':' . $item; + } + + curl_setopt($curl, CURLOPT_HTTPHEADER, $clientHeader); + + + curl_setopt($curl, CURLOPT_FAILONERROR, false); + //返回抓取数据 + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + //输出header头信息 + curl_setopt($curl, CURLOPT_HEADER, true); + //TRUE 时追踪句柄的请求字符串,从 PHP 5.1.3 开始可用。这个很关键,就是允许你查看请求header + curl_setopt($curl, CURLINFO_HEADER_OUT, true); + //https请求 + if (1 == strpos("$" . $url, "https://")) { + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); + } + + //post请求 + if ($method == 'PUT' && !empty($data['body'])) { + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + // 注意这里的'file'是上传地址指定的key名 + curl_setopt($curl, CURLOPT_POSTFIELDS, $data['body']); + } + + if (!empty($data['xml'])) { + curl_setopt($curl, CURLOPT_POSTFIELDS, $data['xml']); + } + + list($content, $status) = [curl_exec($curl), curl_getinfo($curl), curl_close($curl)]; + + $content = trim(substr($content, $status['header_size'])); + + $this->response['content'] = $content; + $this->response['code'] = $status['http_code']; + $this->response['header'] = $status; + + $res = XML::parse($content); + if ($res) { + return $res; + } + return (intval($status["http_code"]) === 200) ? $content : false; + } + + /** + * 获取签名 + * @param string $method + * @param string $urlPath + * @param array $query + * @param array $headers + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/27 + */ + public function getSign(string $url, string $method, string $urlPath, array $query = [], array $headers = []) + { + return (new Signature($this->accessKey, $this->secretKey, ['signHost' => $url]))->signRequest($method, $urlPath, $query, $headers); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/upload/extend/cos/Scope.php b/demo/thinkphp/backend/phoenix/services/upload/extend/cos/Scope.php new file mode 100644 index 0000000000000000000000000000000000000000..d82f9fa2d7adf8a87988603e17a85b4e5b27b6d2 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/upload/extend/cos/Scope.php @@ -0,0 +1,82 @@ + + * +---------------------------------------------------------------------- + */ + +namespace phoenix\services\upload\extend\cos; + +/** + * + * Class Scope + * @author Mr.April + * @since 1.0 + */ +class Scope +{ + protected $action; + protected $bucket; + protected $region; + protected $resourcePrefix; + protected $effect = 'allow'; + + public function __construct($action, $bucket, $region, $resourcePrefix) + { + $this->action = $action; + $this->bucket = $bucket; + $this->region = $region; + $this->resourcePrefix = $resourcePrefix; + } + + public function set_effect($isAllow) + { + if ($isAllow) { + $this->effect = 'allow'; + } else { + $this->effect = 'deny'; + } + } + + public function get_action() + { + if ($this->action == null) { + throw new \Exception("action == null"); + } + return $this->action; + } + + public function get_resource() + { + if ($this->bucket == null) { + throw new \Exception("bucket == null"); + } + if ($this->region == null) { + throw new \Exception("region == null"); + } + if ($this->resourcePrefix == null) { + throw new \Exception("resourcePrefix == null"); + } + $index = strripos($this->bucket, '-'); + if ($index < 0) { + throw new Exception("bucket is invalid: " . $this->bucket); + } + $appid = substr($this->bucket, $index + 1); + if (!(strpos($this->resourcePrefix, '/') === 0)) { + $this->resourcePrefix = '/' . $this->resourcePrefix; + } + return 'qcs::cos:' . $this->region . ':uid/' . $appid . ':' . $this->bucket . $this->resourcePrefix; + } + + public function get_effect() + { + return $this->effect; + } + +} diff --git a/demo/thinkphp/backend/phoenix/services/upload/extend/cos/Signature.php b/demo/thinkphp/backend/phoenix/services/upload/extend/cos/Signature.php new file mode 100644 index 0000000000000000000000000000000000000000..332561862f7a36cbb3be595b1de64f942b763442 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/upload/extend/cos/Signature.php @@ -0,0 +1,213 @@ + + * +---------------------------------------------------------------------- + */ + +namespace phoenix\services\upload\extend\cos; + + +/** + * Class 生成签名 + * + * @author Mr.April + * @since 1.0 + */ +class Signature +{ + /** + * @var string + */ + private string $accessKey; + + /** + * @var string + */ + private string $secretKey; + + /** + * @var array + */ + private array $options; + + /** + * Signature constructor. + * @param string $accessKey + * @param string $secretKey + * @param array $options + * @param string $token + */ + public function __construct(string $accessKey, string $secretKey, array $options = [], string $token = '') + { + $this->accessKey = $accessKey; + $this->secretKey = $secretKey; + $this->options = $options; + $this->token = $token; + $this->signHeader = [ + 'cache-control', + 'content-disposition', + 'content-encoding', + 'content-length', + 'content-md5', + 'content-type', + 'expect', + 'expires', + 'host', + 'if-match', + 'if-modified-since', + 'if-none-match', + 'if-unmodified-since', + 'origin', + 'range', + 'response-cache-control', + 'response-content-disposition', + 'response-content-encoding', + 'response-content-language', + 'response-content-type', + 'response-expires', + 'transfer-encoding', + 'versionid', + ]; + date_default_timezone_set('PRC'); + } + + public function needCheckHeader($header): bool + { + if ($this->startWith($header, 'x-cos-')) { + return true; + } + if (in_array($header, $this->signHeader)) { + return true; + } + return false; + } + + /** + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/29 + * @param $haystack + * @param $needle + * @return bool + */ + protected function startWith($haystack, $needle): bool + { + $length = strlen($needle); + if ($length == 0) { + return true; + } + return (substr($haystack, 0, $length) === $needle); + } + + /** + * @param string $method + * @param string $urlPath + * @param array $querys + * @param array $headers + * @return string[] + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/26 + */ + public function signRequest(string $method, string $urlPath, array $querys = [], array $headers = []): array + { + $authorization = $this->createAuthorization($method, $urlPath, $querys, $headers); + return ['Authorization' => $authorization]; + } + + /** + * @param string $method + * @param string $urlPath + * @param array $querys + * @param array $headers + * @param string $expires + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/26 + */ + public function createAuthorization(string $method, string $urlPath, array $querys = [], array $headers = [], $expires = '+30 minutes'): string + { + if (is_null($expires) || !strtotime($expires)) { + $expires = '+30 minutes'; + } + $signTime = ( string )(time() - 60) . ';' . ( string )(strtotime($expires)); + $urlParamListArray = []; + foreach ($querys as $query) { + if (!empty($query)) { + $tmpquery = explode('=', $query); + //为了保证CI的key中有=号的情况也能正常通过,ci在这层之前已经encode了,这里需要拆开重新encode,防止上方explode拆错 + $key = strtolower(rawurlencode(urldecode($tmpquery[0]))); + if (count($tmpquery) >= 2) { + $value = $tmpquery[1]; + } else { + $value = ""; + } + //host开关 + if (!$this->options['signHost'] && $key == 'host') { + continue; + } + $urlParamListArray[$key] = $key . '=' . $value; + } + } + ksort($urlParamListArray); + $urlParamList = join(';', array_keys($urlParamListArray)); + $httpParameters = join('&', array_values($urlParamListArray)); + + $headerListArray = []; + foreach ($headers as $key => $value) { + $key = strtolower(urlencode($key)); + $value = rawurlencode($value); + if (!$this->options['signHost'] && $key == 'host') { + continue; + } + if ($this->needCheckHeader($key)) { + $headerListArray[$key] = $key . '=' . $value; + } + } + ksort($headerListArray); + $headerList = join(';', array_keys($headerListArray)); + $httpHeaders = join('&', array_values($headerListArray)); + $httpString = strtolower($method) . "\n" . urldecode($urlPath) . "\n" . $httpParameters . + "\n" . $httpHeaders . "\n"; + + $sha1edHttpString = sha1($httpString); + $stringToSign = "sha1\n$signTime\n$sha1edHttpString\n"; + $signKey = hash_hmac('sha1', $signTime, trim($this->secretKey)); + $signature = hash_hmac('sha1', $stringToSign, $signKey); + $authorization = 'q-sign-algorithm=sha1&q-ak=' . trim($this->accessKey) . + "&q-sign-time=$signTime&q-key-time=$signTime&q-header-list=$headerList&q-url-param-list=$urlParamList&" . + "q-signature=$signature"; + return $authorization; + } + + /** + * @param string $url + * @param string $method + * @param string $urlPath + * @param array $querys + * @param array $headers + * @param string $expires + * @return string[] + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/26 + */ + public function createPresignedUrl(string $url, string $method, string $urlPath, array $querys = [], array $headers = [], string $expires = '+30 minutes'): array + { + $authorization = $this->createAuthorization($method, $urlPath, $querys, $headers, $expires); + $uri = $url; + $query = 'sign=' . urlencode($authorization) . '&' . implode('&', $querys); + if ($this->token != null) { + $query = $query . '&x-cos-security-token=' . $this->token; + } + return [$uri, $query]; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/upload/extend/cos/Sts.php b/demo/thinkphp/backend/phoenix/services/upload/extend/cos/Sts.php new file mode 100644 index 0000000000000000000000000000000000000000..adbb8bb0a8170c1fef21e64b37fbc43ae3564862 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/upload/extend/cos/Sts.php @@ -0,0 +1,326 @@ + + * +---------------------------------------------------------------------- + */ + +namespace phoenix\services\upload\extend\cos; + +/** + * + * + * @author Mr.April + * @since 1.0 + */ +class Sts +{ +// 临时密钥计算样例 + function _hex2bin($data): string + { + $len = strlen($data); + return pack("H" . $len, $data); + } + + // obj 转 query string + function json2str($obj, $notEncode = false): string + { + ksort($obj); + $arr = array(); + if (!is_array($obj)) { + throw new \Exception('$obj must be an array, the actual value is:' . json_encode($obj)); + } + foreach ($obj as $key => $val) { + array_push($arr, $key . '=' . ($notEncode ? $val : rawurlencode($val))); + } + return join('&', $arr); + } + + // 计算临时密钥用的签名 + function getSignature($opt, $key, $method, $config): string + { + $host = "sts.tencentcloudapi.com"; + + if (array_key_exists('domain', $config)) { + $host = $config['domain']; + } + + if (array_key_exists('endpoint', $config)) { + $host = "sts." . $config['endpoint']; + } + + $formatString = $method . $host . '/?' . $this->json2str($opt, 1); + $sign = hash_hmac('sha1', $formatString, $key); + $sign = base64_encode($this->_hex2bin($sign)); + return $sign; + } + + // v2接口的key首字母小写,v3改成大写,此处做了向下兼容 + function backwardCompat($result): array + { + if (!is_array($result)) { + throw new \Exception('$result must be an array, the actual value is:' . json_encode($result)); + } + $compat = array(); + foreach ($result as $key => $value) { + if (is_array($value)) { + $compat[lcfirst($key)] = $this->backwardCompat($value); + } elseif ($key == 'Token') { + $compat['sessionToken'] = $value; + } else { + $compat[lcfirst($key)] = $value; + } + } + return $compat; + } + + // 获取临时密钥 + function getTempKeys($config): array + { + $result = null; + try { + if (array_key_exists('policy', $config)) { + $policy = $config['policy']; + } else { + if (array_key_exists('bucket', $config)) { + $ShortBucketName = substr($config['bucket'], 0, strripos($config['bucket'], '-')); + $AppId = substr($config['bucket'], 1 + strripos($config['bucket'], '-')); + } else { + throw new \Exception("bucket== null"); + } + if (array_key_exists('allowPrefix', $config)) { + if (!(strpos($config['allowPrefix'], '/') === 0)) { + $config['allowPrefix'] = '/' . $config['allowPrefix']; + } + } else { + throw new \Exception("allowPrefix == null"); + } + if (!array_key_exists('region', $config)) { + throw new \Exception("region == null"); + } + $policy = array( + 'version' => '2.0', + 'statement' => array( + array( + 'action' => $config['allowActions'], + 'effect' => 'allow', + 'resource' => array( + 'qcs::cos:' . $config['region'] . ':uid/' . $AppId . ':' . $config['bucket'] . $config['allowPrefix'] + ) + ) + ) + ); + } + $policyStr = str_replace('\\/', '/', json_encode($policy)); + $Action = 'GetFederationToken'; + $Nonce = rand(10000, 20000); + $Timestamp = time(); + $Method = 'POST'; + if (array_key_exists('durationSeconds', $config)) { + if (!(is_integer($config['durationSeconds']))) { + throw new \Exception("durationSeconds must be a int type"); + } + } + $params = array( + 'SecretId' => $config['secretId'], + 'Timestamp' => $Timestamp, + 'Nonce' => $Nonce, + 'Action' => $Action, + 'DurationSeconds' => $config['durationSeconds'], + 'Version' => '2018-08-13', + 'Name' => 'cos', + 'Region' => $config['region'], + 'Policy' => urlencode($policyStr) + ); + $params['Signature'] = $this->getSignature($params, $config['secretKey'], $Method, $config); + $url = 'https://sts.tencentcloudapi.com/'; + + if (array_key_exists('url', $config)) { + $url = $config['url']; + } + + if (!array_key_exists('url', $config) && array_key_exists('domain', $config)) { + $url = 'https://sts.' . $config['domain']; + } + + if (array_key_exists('endpoint', $config)) { + $url = 'https://sts.' . $config['endpoint']; + } + + $ch = curl_init($url); + if (array_key_exists('proxy', $config)) { + $config['proxy'] && curl_setopt($ch, CURLOPT_PROXY, $config['proxy']); + } + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $this->json2str($params)); + $result = curl_exec($ch); + if (curl_errno($ch)) $result = curl_error($ch); + curl_close($ch); + $result = json_decode($result, 1); + if (isset($result['Response'])) { + $result = $result['Response']; + if (isset($result['Error'])) { + throw new \Exception("get cam failed"); + } + $result['startTime'] = $result['ExpiredTime'] - $config['durationSeconds']; + } + $result = $this->backwardCompat($result); + return $result; + } catch (\Exception $e) { + if ($result == null) { + $result = "error: " . $e->getMessage(); + } else { + $result = json_encode($result); + } + throw new \Exception($result); + } + } + + //申请角色授权 + function getRoleCredential($config): array + { + $result = null; + try { + if (array_key_exists('policy', $config)) { + $policy = $config['policy']; + } else { + if (array_key_exists('bucket', $config)) { + $ShortBucketName = substr($config['bucket'], 0, strripos($config['bucket'], '-')); + $AppId = substr($config['bucket'], 1 + strripos($config['bucket'], '-')); + } else { + throw new \Exception("bucket== null"); + } + if (array_key_exists('allowPrefix', $config)) { + if (!(strpos($config['allowPrefix'], '/') === 0)) { + $config['allowPrefix'] = '/' . $config['allowPrefix']; + } + } else { + throw new \Exception("allowPrefix == null"); + } + if (!array_key_exists('region', $config)) { + throw new \Exception("region == null"); + } + $policy = array( + 'version' => '2.0', + 'statement' => array( + array( + 'action' => $config['allowActions'], + 'effect' => 'allow', + 'resource' => array( + 'qcs::cos:' . $config['region'] . ':uid/' . $AppId . ':' . $config['bucket'] . $config['allowPrefix'] + ) + ) + ) + ); + } + if (array_key_exists('roleArn', $config)) { + $RoleArn = $config['roleArn']; + } else { + throw new \Exception("roleArn == null"); + } + $policyStr = str_replace('\\/', '/', json_encode($policy)); + $Action = 'AssumeRole'; + $Nonce = rand(10000, 20000); + $Timestamp = time(); + $Method = 'POST'; + $ExternalId = ""; + if (array_key_exists('externalId', $config)) { + $ExternalId = $config['externalId']; + } + if (array_key_exists('durationSeconds', $config)) { + if (!(is_integer($config['durationSeconds']))) { + throw new \Exception("durationSeconds must be a int type"); + } + } + $params = array( + 'SecretId' => $config['secretId'], + 'Timestamp' => $Timestamp, + 'RoleArn' => $RoleArn, + 'Action' => $Action, + 'Nonce' => $Nonce, + 'DurationSeconds' => $config['durationSeconds'], + 'Version' => '2018-08-13', + 'RoleSessionName' => 'cos', + 'Region' => $config['region'], + 'ExternalId' => $ExternalId, + 'Policy' => urlencode($policyStr) + ); + $params['Signature'] = $this->getSignature($params, $config['secretKey'], $Method, $config); + $url = 'https://sts.internal.tencentcloudapi.com/'; + + if (array_key_exists('endpoint', $config)) { + $url = 'https://sts.' . $config['endpoint']; + } + $ch = curl_init($url); + if (array_key_exists('proxy', $config)) { + $config['proxy'] && curl_setopt($ch, CURLOPT_PROXY, $config['proxy']); + } + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $this->json2str($params)); + $result = curl_exec($ch); + if (curl_errno($ch)) $result = curl_error($ch); + curl_close($ch); + $result = json_decode($result, 1); + if (isset($result['Response'])) { + $result = $result['Response']; + if (isset($result['Error'])) { + throw new \Exception("get cam failed"); + } + $result['startTime'] = $result['ExpiredTime'] - $config['durationSeconds']; + } + $result = $this->backwardCompat($result); + return $result; + } catch (\Exception $e) { + if ($result == null) { + $result = "error: " . $e->getMessage(); + } else { + $result = json_encode($result); + } + throw new \Exception($result); + } + } + + + // get policy + function getPolicy($scopes) + { + if (!is_array($scopes)) { + return null; + } + $statements = array(); + + for ($i = 0, $counts = count($scopes); $i < $counts; $i++) { + $actions = array(); + $resources = array(); + array_push($actions, $scopes[$i]->get_action()); + array_push($resources, $scopes[$i]->get_resource()); + + $statement = array( + 'action' => $actions, + 'effect' => $scopes[$i]->get_effect(), + 'resource' => $resources + ); + array_push($statements, $statement); + } + + $policy = array( + 'version' => '2.0', + 'statement' => $statements + ); + return $policy; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/upload/extend/cos/XML.php b/demo/thinkphp/backend/phoenix/services/upload/extend/cos/XML.php new file mode 100644 index 0000000000000000000000000000000000000000..35089397375797573c16c6f9b1fd55dcb8062a41 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/upload/extend/cos/XML.php @@ -0,0 +1,153 @@ + $value) { + $_attr[] = "{$key}=\"{$value}\""; + } + + $attr = implode(' ', $_attr); + } + + $attr = trim($attr); + $attr = empty($attr) ? '' : " {$attr}"; + $xml = "<{$root}{$attr}>"; + $xml .= self::data2Xml($data, $item, $id); + $xml .= ""; + + return $xml; + } + + /** + * Build CDATA. + * + * @param string $string + * + * @return string + */ + public static function cdata($string): string + { + return sprintf('', $string); + } + + /** + * Object to array. + * + * @param SimpleXMLElement $obj + * + * @return array + */ + protected static function normalize($obj): array|SimpleXMLElement + { + $result = null; + + if (is_object($obj)) { + $obj = (array)$obj; + } + + if (is_array($obj)) { + foreach ($obj as $key => $value) { + $res = self::normalize($value); + if (('@attributes' === $key) && ($key)) { + $result = $res; // @codeCoverageIgnore + } else { + $result[$key] = $res; + } + } + } else { + $result = $obj; + } + + return $result; + } + + /** + * Array to XML. + * + * @param array $data + * @param string $item + * @param string $id + * + * @return string + */ + protected static function data2Xml(array $data, string $item = 'item', string $id = 'id'): string + { + $xml = $attr = ''; + + foreach ($data as $key => $val) { + if (is_numeric($key)) { + $id && $attr = " {$id}=\"{$key}\""; + $key = $item; + } + + $xml .= "<{$key}{$attr}>"; + + if ((is_array($val) || is_object($val))) { + $xml .= self::data2Xml((array)$val, $item, $id); + } else { + $xml .= is_numeric($val) ? $val : self::cdata($val); + } + + $xml .= ""; + } + + return $xml; + } + + /** + * Delete invalid characters in XML. + * + * @see https://www.w3.org/TR/2008/REC-xml-20081126/#charsets - XML charset range + * @see http://php.net/manual/en/regexp.reference.escape.php - escape in UTF-8 mode + * + * @param string $xml + * + * @return string + */ + public static function sanitize($xml): string + { + return preg_replace('/[^\x{9}\x{A}\x{D}\x{20}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]+/u', '', $xml); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/upload/storage/Cos.php b/demo/thinkphp/backend/phoenix/services/upload/storage/Cos.php new file mode 100644 index 0000000000000000000000000000000000000000..1e896342dbd4152facd092b23847d7b40b551388 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/upload/storage/Cos.php @@ -0,0 +1,650 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\services\upload\storage; + +use phoenix\services\upload\BaseUpload; +use phoenix\exceptions\AdminException; +use phoenix\exceptions\UploadException; +use GuzzleHttp\Psr7\Utils; +use Qcloud\Cos\Client; +use QCloud\COSSTS\Sts; +use phoenix\services\upload\extend\cos\Client as CrmebClient; + +/** + * 腾讯云COS文件上传 + * Class COS + * @package crmeb\services\upload\storage + */ +class Cos extends BaseUpload +{ + + /** + * 应用id + * @var string + */ + protected string $appid; + + /** + * accessKey + * @var mixed + */ + protected mixed $accessKey; + + /** + * secretKey + * @var mixed + */ + protected mixed $secretKey; + + /** + * 句柄 + * @var CrmebClient + */ + protected $handle; + + /** + * 空间域名 Domain + * @var mixed + */ + protected mixed $uploadUrl; + + /** + * 存储空间名称 公开空间 + * @var mixed + */ + protected mixed $storageName; + + /** + * COS使用 所属地域 + * @var mixed|null + */ + protected mixed $storageRegion; + + /** + * 水印位置 + * @var string[] + */ + protected array $position = [ + '1' => 'northwest',//:左上 + '2' => 'north',//:中上 + '3' => 'northeast',//:右上 + '4' => 'west',//:左中 + '5' => 'center',//:中部 + '6' => 'east',//:右中 + '7' => 'southwest',//:左下 + '8' => 'south',//:中下 + '9' => 'southeast',//:右下 + ]; + + /** + * 初始化 + * + * @param array $config + * + * @return void + */ + public function initialize(array $config):void + { + parent::initialize($config); + $this->accessKey = $config['accessKey'] ?? null; + $this->appid = $config['appid'] ?? null; + $this->secretKey = $config['secretKey'] ?? null; + $this->uploadUrl = $this->checkUploadUrl($config['uploadUrl'] ?? ''); + $this->storageName = $config['storageName'] ?? null; + $this->storageRegion = $config['storageRegion'] ?? null; + $this->waterConfig['watermark_text_font'] = 'simfang仿宋.ttf'; + } + + /** + * 实例化cos + * @return CrmebClient + */ + protected function app() + { + $this->handle = new CrmebClient([ + 'accessKey' => $this->accessKey, + 'secretKey' => $this->secretKey, + 'region' => $this->storageRegion ?: 'ap-chengdu', + 'bucket' => $this->storageName, + 'appid' => $this->appid, + 'uploadUrl' => $this->uploadUrl + ]); + return $this->handle; + } + + /** + * 上传文件 + * @param string|null $file + * @param bool $isStream 是否为流上传 + * @param string|null $fileContent 流内容 + * @return array|bool|\StdClass + */ + protected function upload(string $file = null, bool $isStream = false, string $fileContent = null): bool|array|\StdClass + { + if (!$isStream) { + $fileHandle = app()->request->file($file); + if (!$fileHandle) { + return $this->setError('上传的文件不存在'); + } + if ($this->validate) { + if (!in_array(pathinfo($fileHandle->getOriginalName(), PATHINFO_EXTENSION), $this->validate['fileExt'])) { + return $this->setError('不合法的文件后缀'); + } + if (filesize($fileHandle) > $this->validate['filesize']) { + return $this->setError('文件过大'); + } + if (!in_array($fileHandle->getOriginalMime(), $this->validate['fileMime'])) { + return $this->setError('不合法的文件类型'); + } + } + $key = $this->saveFileName($fileHandle->getRealPath(), $fileHandle->getOriginalExtension()); + $body = fopen($fileHandle->getRealPath(), 'rb'); + $body = (string)Utils::streamFor($body); + } else { + $key = $file; + $body = $fileContent; + } + try { + $key = $this->getUploadPath($key); + $this->fileInfo->uploadInfo = $this->app()->putObject($key, $body); + $this->fileInfo->filePath = $this->uploadUrl . '/' . $key; + $this->fileInfo->realName = isset($fileHandle) ? $fileHandle->getOriginalName() : $key; + $this->fileInfo->fileName = $key; + $this->fileInfo->filePathWater = $this->water($this->fileInfo->filePath); + $this->authThumb && $this->thumb($this->fileInfo->filePath); + return $this->fileInfo; + } catch (UploadException $e) { + return $this->setError($e->getMessage()); + } + } + + /** + * 文件流上传 + * + * @param $fileContent + * @param string|null $key + * + * @return mixed + */ + public function stream($fileContent, string $key = null):mixed + { + if (!$key) { + $key = $this->saveFileName(); + } + return $this->upload($key, true, $fileContent); + } + + /** + * 文件上传 + * + * @param string $file + * @param bool $realName + * + * @return mixed + */ + public function move(string $file = 'file', bool $realName = false):mixed + { + return $this->upload($file); + } + + /** + * 缩略图 + * + * @param string $filePath + * @param string $fileName + * @param string $type + * + * @return array + */ + public function thumb(string $filePath = '', string $fileName = '', string $type = 'all'):array + { + $filePath = $this->getFilePath($filePath); + $data = ['big' => $filePath, 'mid' => $filePath, 'small' => $filePath]; + $this->fileInfo->filePathBig = $this->fileInfo->filePathMid = $this->fileInfo->filePathSmall = $this->fileInfo->filePathWater = $filePath; + if ($filePath) { + $config = $this->thumbConfig; + foreach ($this->thumb as $v) { + if ($type == 'all' || $type == $v) { + $height = 'thumb_' . $v . '_height'; + $width = 'thumb_' . $v . '_width'; + $key = 'filePath' . ucfirst($v); + if (sys_config('image_thumbnail_status', 1) && isset($config[$height]) && isset($config[$width]) && $config[$height] && $config[$width]) { + $this->fileInfo->$key = $filePath . '?imageMogr2/thumbnail/' . $config[$width] . 'x' . $config[$height]; + $this->fileInfo->$key = $this->water($this->fileInfo->$key); + $data[$v] = $this->fileInfo->$key; + } else { + $this->fileInfo->$key = $this->water($this->fileInfo->$key); + $data[$v] = $this->fileInfo->$key; + } + } + } + } + return $data; + } + + /** + * 水印 + * @param string $filePath + * @return mixed|string + */ + public function water(string $filePath = '') + { + $filePath = $this->getFilePath($filePath); + $waterConfig = $this->waterConfig; + $waterPath = $filePath; + if ($waterConfig['image_watermark_status'] && $filePath) { + if (strpos($filePath, '?') === false) { + $filePath .= '?watermark'; + } else { + $filePath .= '&watermark'; + } + switch ($waterConfig['watermark_type']) { + case 1://图片 + if (!$waterConfig['watermark_image']) { + throw new AdminException(400722); + } + $waterPath = $filePath .= '/1/image/' . base64_encode($waterConfig['watermark_image']) . '/gravity/' . ($this->position[$waterConfig['watermark_position']] ?? 'northwest') . '/blogo/1/dx/' . $waterConfig['watermark_x'] . '/dy/' . $waterConfig['watermark_y']; + break; + case 2://文字 + if (!$waterConfig['watermark_text']) { + throw new AdminException(400723); + } + $waterPath = $filePath .= '/2/text/' . base64_encode($waterConfig['watermark_text']) . '/font/' . base64_encode($waterConfig['watermark_text_font']) . '/fill/' . base64_encode($waterConfig['watermark_text_color']) . '/fontsize/' . $waterConfig['watermark_text_size'] . '/gravity/' . ($this->position[$waterConfig['watermark_position']] ?? 'northwest') . '/dx/' . $waterConfig['watermark_x'] . '/dy/' . $waterConfig['watermark_y']; + break; + } + } + return $waterPath; + } + + /** + * TODO 删除资源 + * @param $key + * @return mixed + */ + public function delete(string $filePath) + { + try { + return $this->app()->deleteObject($this->storageName, $filePath); + } catch (\Exception $e) { + return $this->setError($e->getMessage()); + } + } + + /** + * 生成签名 + * @return array|mixed + * @throws \Exception + */ + public function getTempKeys() + { + $sts = new Sts(); + $config = [ + 'url' => 'https://sts.tencentcloudapi.com/', + 'domain' => 'sts.tencentcloudapi.com', + 'proxy' => '', + 'secretId' => $this->accessKey, // 固定密钥 + 'secretKey' => $this->secretKey, // 固定密钥 + 'bucket' => $this->storageName, // 换成你的 bucket + 'region' => $this->storageRegion, // 换成 bucket 所在园区 + 'durationSeconds' => 1800, // 密钥有效期 + 'allowPrefix' => '*', // 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的具体路径,例子: a.jpg 或者 a/* 或者 * (使用通配符*存在重大安全风险, 请谨慎评估使用) + // 密钥的权限列表。简单上传和分片需要以下的权限,其他权限列表请看 https://cloud.tencent.com/document/product/436/31923 + 'allowActions' => [ + // 简单上传 + 'name/cos:PutObject', + 'name/cos:PostObject', + // 分片上传 + 'name/cos:InitiateMultipartUpload', + 'name/cos:ListMultipartUploads', + 'name/cos:ListParts', + 'name/cos:UploadPart', + 'name/cos:CompleteMultipartUpload' + ] + ]; + // 获取临时密钥,计算签名 + $result = $sts->getTempKeys($config); + $result['url'] = $this->uploadUrl . '/'; + $result['type'] = 'COS'; + $result['bucket'] = $this->storageName; + $result['region'] = $this->storageRegion; + return $result; + } + + /** + * 计算临时密钥用的签名 + * @param $opt + * @param $key + * @param $method + * @param $config + * @return string + */ + public function getSignature($opt, $key, $method, $config) + { + $formatString = $method . $config['domain'] . '/?' . $this->json2str($opt, 1); + $sign = hash_hmac('sha1', $formatString, $key); + $sign = base64_encode($this->_hex2bin($sign)); + return $sign; + } + + public function _hex2bin($data) + { + $len = strlen($data); + return pack("H" . $len, $data); + } + + // obj 转 query string + public function json2str($obj, $notEncode = false) + { + ksort($obj); + $arr = array(); + if (!is_array($obj)) { + return $this->setError($obj . " must be a array"); + } + foreach ($obj as $key => $val) { + array_push($arr, $key . '=' . ($notEncode ? $val : rawurlencode($val))); + } + return join('&', $arr); + } + + // v2接口的key首字母小写,v3改成大写,此处做了向下兼容 + public function backwardCompat($result) + { + if (!is_array($result)) { + return $this->setError($result . " must be a array"); + } + $compat = array(); + foreach ($result as $key => $value) { + if (is_array($value)) { + $compat[lcfirst($key)] = $this->backwardCompat($value); + } elseif ($key == 'Token') { + $compat['sessionToken'] = $value; + } else { + $compat[lcfirst($key)] = $value; + } + } + return $compat; + } + + /** + * 桶列表 + * @param string|null $region + * @param bool $line + * @param bool $shared + * @return array|mixed + * "Name" => "record-1254950941" + * "Location" => "ap-chengdu" + * "CreationDate" => "2019-05-16T08:33:29Z" + * "BucketType" => "cos" + */ + public function listbuckets(string $region = null, bool $line = false, bool $shared = false) + { + try { + $res = $this->app()->listBuckets(); + return $res['Buckets']['Bucket'] ?? []; + } catch (\Throwable $e) { + return []; + } + } + + /** + * 创建桶 + * @param string $name + * @param string $region + * @param string $acl public-read=公共独写 + * @return bool|mixed + */ + public function createBucket(string $name, string $region = '', string $acl = 'public-read') + { + $regionData = $this->getRegion(); + $regionData = array_column($regionData, 'value'); + if (!in_array($region, $regionData)) { + return $this->setError('COS:无效的区域!'); + } + $this->storageRegion = $region; + $app = $this->app(); + //检测桶 + try { + $app->headBucket($name); + } catch (\Throwable $e) { + //桶不存在返回404 + if (strstr('404', $e->getMessage())) { + return $this->setError('COS:' . $e->getMessage()); + } + } + //创建桶 + try { + $res = $app->createBucket($name . '-' . $this->appid, '', $acl); + } catch (\Throwable $e) { + if (strstr('[curl] 6', $e->getMessage())) { + return $this->setError('COS:无效的区域!!'); + } else if (strstr('Access Denied.', $e->getMessage())) { + return $this->setError('COS:无权访问'); + } + return $this->setError('COS:' . $e->getMessage()); + } + return $res; + } + + /** + * 删除桶 + * @param string $name + * @return bool|mixed + */ + public function deleteBucket(string $name) + { + try { + $res = $this->app()->deleteBucket($name); + if ($res->get('RequestId')) { + return true; + } + } catch (\Throwable $e) { + return $this->setError($e->getMessage()); + } + return false; + } + + /** + * @param string $name + * @param string|null $region + * @return array|object + */ + public function getDomian(string $name, string $region = null) + { + $this->storageRegion = $region; + try { + $res = $this->app()->GetBucketDomain($name); + $domainRules = $res->toArray()['DomainRules']; + return array_column($domainRules, 'Name'); + } catch (\Throwable $e) { + } + return []; + } + + /** + * 绑定域名 + * @param string $name + * @param string $domain + * @param string|null $region + * @return bool|mixed + */ + public function bindDomian(string $name, string $domain, string $region = null) + { + $this->storageRegion = $region; + $parseDomin = parse_url($domain); + try { + $res = $this->app()->putBucketDomain($name, '', [ + 'Name' => $parseDomin['host'], + 'Status' => 'ENABLED', + 'Type' => 'REST', + 'ForcedReplacement' => 'CNAME' + ]); + if (method_exists($res, 'toArray')) { + $res = $res->toArray(); + } + if ($res['RequestId'] ?? null) { + return true; + } + } catch (\Throwable $e) { + if ($message = $this->setMessage($e->getMessage())) { + return $this->setError($message); + } + return $this->setError($e->getMessage()); + } + return false; + } + + /** + * 处理 + * @param string $message + * @return string + */ + protected function setMessage(string $message) + { + $data = [ + 'The specified bucket does not exist.' => '指定的存储桶不存在。', + 'Please add CNAME/TXT record to DNS then try again later. Please allow up to 10 mins before your DNS takes effect.' => '请将CNAME记录添加到DNS,然后稍后重试。在DNS生效前,请等待最多10分钟。' + ]; + $msg = $data[$message] ?? ''; + if ($msg) { + return $msg; + } + foreach ($data as $item) { + if (strstr($message, $item)) { + return $item; + } + } + return ''; + } + + /** + * 设置跨域 + * @param string $name + * @param string $region + * @return bool + */ + public function setBucketCors(string $name, string $region) + { + $this->storageRegion = $region; + try { + $res = $this->app()->PutBucketCors($name, [ + 'AllowedHeaders' => ['*'], + 'AllowedMethods' => ['PUT', 'GET', 'POST', 'DELETE', 'HEAD'], + 'AllowedOrigins' => ['*'], + 'ExposeHeaders' => ['ETag', 'Content-Length', 'x-cos-request-id'], + 'MaxAgeSeconds' => 12 + ]); + if (isset($res['RequestId'])) { + return true; + } + } catch (\Throwable $e) { + return $this->setError($e->getMessage()); + } + return false; + } + + /** + * 地域 + * @return mixed|\string[][] + */ + public function getRegion() + { + return [ + [ + 'value' => 'ap-chengdu', + 'label' => '成都' + ], + [ + 'value' => 'ap-shanghai', + 'label' => '上海' + ], + [ + 'value' => 'ap-guangzhou', + 'label' => '广州' + ], + [ + 'value' => 'ap-nanjing', + 'label' => '南京' + ], + [ + 'value' => 'ap-beijing', + 'label' => '北京' + ], + [ + 'value' => 'ap-chongqing', + 'label' => '重庆' + ], + [ + 'value' => 'ap-shenzhen-fsi', + 'label' => '深圳金融' + ], + [ + 'value' => 'ap-shanghai-fsi', + 'label' => '上海金融' + ], + [ + 'value' => 'ap-beijing-fsi', + 'label' => '北京金融' + ], + [ + 'value' => 'ap-hongkong', + 'label' => '中国香港' + ], + [ + 'value' => 'ap-singapore', + 'label' => '新加坡' + ], + [ + 'value' => 'ap-mumbai', + 'label' => '孟买' + ], + [ + 'value' => 'ap-jakarta', + 'label' => '雅加达' + ], + [ + 'value' => 'ap-seoul', + 'label' => '首尔' + ], + [ + 'value' => 'ap-bangkok', + 'label' => '曼谷' + ], + [ + 'value' => 'ap-tokyo', + 'label' => '东京' + ], + [ + 'value' => 'na-siliconvalley', + 'label' => '硅谷(美西)' + ], + [ + 'value' => 'na-ashburn', + 'label' => '弗吉尼亚(美东)' + ], + [ + 'value' => 'na-toronto', + 'label' => '多伦多' + ], + [ + 'value' => 'sa-saopaulo', + 'label' => '圣保罗' + ], + [ + 'value' => 'eu-frankfurt', + 'label' => '法兰克福' + ], + [ + 'value' => 'eu-moscow', + 'label' => '莫斯科' + ] + ]; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/upload/storage/Local.php b/demo/thinkphp/backend/phoenix/services/upload/storage/Local.php new file mode 100644 index 0000000000000000000000000000000000000000..e1dc2e60b9df9b4caa4b1c577941f20a2d3a26ea --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/upload/storage/Local.php @@ -0,0 +1,420 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\services\upload\storage; + +use phoenix\services\upload\BaseUpload; +use phoenix\exceptions\AdminException; +use phoenix\utils\DownloadImage; +use think\exception\ValidateException; +use think\facade\Config; +use think\facade\Filesystem; +use think\File; +use think\Image; + +/** + * 本地上传 + * Class Local + * @package crmeb\services\upload\storage + */ +class Local extends BaseUpload +{ + + /** + * 默认存放路径 + * @var string + */ + protected $defaultPath; + + /** + * 缩略图、水印图存放位置 + * @var string + */ + public $thumbWaterPath = 'thumb_water'; + + /** + * + * @param array $config + * + * @return mixed|void + */ + public function initialize(array $config) + { + parent::initialize($config); + $this->defaultPath = Config::get('filesystem.disks.' . Config::get('filesystem.default') . '.url'); + $this->waterConfig['watermark_text_font'] = app()->getRootPath() . 'public' . '/statics/font/simsunb.ttf'; + } + + protected function app() + { + // TODO: Implement app() method. + } + + public function getTempKeys() + { + // TODO: Implement getTempKeys() method. + return $this->setError('请检查您的上传配置,视频默认oss上传'); + } + + /** + * 生成上传文件目录 + * @param $path + * @param null $root + * @return string + */ + public function uploadDir($path, $root = null) + { + if ($root === null) $root = app()->getRootPath() . 'public/'; + return str_replace('\\', '/', $root . 'uploads/' . $path); + } + + /** + * 检查上传目录不存在则生成 + * @param $dir + * @return bool + */ + protected function validDir($dir) + { + return is_dir($dir) == true || mkdir($dir, 0777, true) == true; + } + + /** + * 检测filepath是否是远程地址 + * @param string $filePath + * @return bool + */ + public function checkFilePathIsRemote(string $filePath) + { + return strpos($filePath, 'https:') !== false || strpos($filePath, 'http:') !== false || substr($filePath, 0, 2) === '//'; + } + + /** + * 生成与配置相关的文件名称以及路径 + * @param string $filePath 原地址 + * @param string $toPath 保存目录 + * @param array $config 配置相关参数 + * @param string $root + * @return string + */ + public function createSaveFilePath(string $filePath, string $toPath, array $config = [], $root = '/') + { + [$path, $ext] = $this->getFileName($filePath); + $fileName = md5(json_encode($config) . $filePath); + return $this->uploadDir($toPath, $root) . '/' . $fileName . '.' . $ext; + } + + /** + * 文件上传 + * + * @param string $file + * @param bool $realName + * + * @return mixed + */ + public function move(string $file = 'file', bool $realName = false):mixed + { + $fileHandle = app()->request->file($file); + if (!$fileHandle) { + return $this->setError('上传的文件不存在'); + } + if ($this->validate) { + if (!in_array(pathinfo($fileHandle->getOriginalName(), PATHINFO_EXTENSION), $this->validate['fileExt'])) { + return $this->setError('不合法的文件后缀'); + } + if (filesize($fileHandle) > $this->validate['filesize']) { + return $this->setError('文件过大'); + } + if (!in_array($fileHandle->getOriginalMime(), $this->validate['fileMime'])) { + return $this->setError('不合法的文件类型'); + } + } + if ($realName) { + $fileName = Filesystem::putFileAs($this->path, $fileHandle, $fileHandle->getOriginalName()); + } else { + $fileName = Filesystem::putFile($this->path, $fileHandle); + } + if (!$fileName) + return $this->setError('Upload failure'); + $filePath = Filesystem::path($fileName); + $this->fileInfo->uploadInfo = new File($filePath); + $this->fileInfo->realName = $fileHandle->getOriginalName(); + $this->fileInfo->fileName = $this->fileInfo->uploadInfo->getFilename(); + $this->fileInfo->filePath = $this->defaultPath . '/' . str_replace('\\', '/', $fileName); + if ($this->checkImage(public_path() . $this->fileInfo->filePath) && $this->authThumb && pathinfo($fileName, PATHINFO_EXTENSION) != 'ico' && pathinfo($fileName, PATHINFO_EXTENSION) != 'gif') { + try { + $this->thumb($this->fileInfo->filePath, $this->fileInfo->fileName); + } catch (\Throwable $e) { + return $this->setError($e->getMessage()); + } + } + return $this->fileInfo; + } + + /** + * 文件流上传 + * @param $fileContent + * @param string|null $key + * @return array|bool|mixed|\StdClass + */ + public function stream($fileContent, string $key = null):mixed + { + if (!$key) { + $key = $this->saveFileName(); + } + $dir = $this->uploadDir($this->path); + if (!$this->validDir($dir)) { + return $this->setError('Failed to generate upload directory, please check the permission!'); + } + $fileName = $dir . '/' . $key; + file_put_contents($fileName, $fileContent); + $this->fileInfo->uploadInfo = new File($fileName); + $this->fileInfo->realName = $key; + $this->fileInfo->fileName = $key; + $this->fileInfo->filePath = $this->defaultPath . '/' . $this->path . '/' . $key; + if ($this->checkImage(public_path() . $this->fileInfo->filePath) && $this->authThumb) { + try { + $this->thumb($this->fileInfo->filePath, $this->fileInfo->fileName); + } catch (\Throwable $e) { + return $this->setError($e->getMessage()); + } + } + return $this->fileInfo; + } + + /** + * 文件流下载保存图片 + * @param string $fileContent + * @param string|null $key + * @return array|bool|mixed|\StdClass + */ + public function down(string $fileContent, string $key = null) + { + if (!$key) { + $key = $this->saveFileName(); + } + $dir = $this->uploadDir($this->path); + if (!$this->validDir($dir)) { + return $this->setError('Failed to generate upload directory, please check the permission!'); + } + $fileName = $dir . '/' . $key; + file_put_contents($fileName, $fileContent); + $this->downFileInfo->downloadInfo = new File($fileName); + $this->downFileInfo->downloadRealName = $key; + $this->downFileInfo->downloadFileName = $key; + $this->downFileInfo->downloadFilePath = $this->defaultPath . '/' . $this->path . '/' . $key; + return $this->downFileInfo; + } + + /** + * 生成缩略图 + * @param string $filePath + * @param string $fileName + * @param string $type + * @return array|mixed|string[] + */ + public function thumb(string $filePath = '', string $fileName = '', string $type = 'all') + { + $config = $this->thumbConfig; + $data = ['big' => $filePath, 'mid' => $filePath, 'small' => $filePath]; + $this->fileInfo->filePathBig = $this->fileInfo->filePathMid = $this->fileInfo->filePathSmall = $this->fileInfo->filePathWater = $filePath; + //地址存在且不是远程地址 + $filePath = str_replace(sys_config('site_url'), '', $filePath); + if ($filePath && !$this->checkFilePathIsRemote($filePath)) { + $findPath = str_replace($fileName, $type . '_' . $fileName, $filePath); + if (file_exists('.' . $findPath)) { + return [ + 'big' => str_replace($fileName, 'big_' . $fileName, $filePath), + 'mid' => str_replace($fileName, 'mid_' . $fileName, $filePath), + 'small' => str_replace($fileName, 'small_' . $fileName, $filePath) + ]; + } + try { + $this->water($filePath); + foreach ($this->thumb as $v) { + if ($type == 'all' || $type == $v) { + $height = 'thumb_' . $v . '_height'; + $width = 'thumb_' . $v . '_width'; + $savePath = str_replace($fileName, $v . '_' . $fileName, $filePath); + //防止重复生成 + if (!file_exists('.' . $savePath)) { + $Image = Image::open(app()->getRootPath() . 'public' . $filePath); + $Image->thumb($config[$width], $config[$height])->save(root_path() . 'public' . $savePath); + } + $key = 'filePath' . ucfirst($v); + $data[$v] = $this->fileInfo->$key = $savePath; + } + } + } catch (\Throwable $e) { + throw new AdminException($e->getMessage()); + } + } + return $data; + } + + /** + * 添加水印 + * @param string $filePath + * @return mixed|string + */ + public function water(string $filePath = '') + { + $waterConfig = $this->waterConfig; + if ($waterConfig['image_watermark_status'] && $filePath) { + + switch ($waterConfig['watermark_type']) { + case 1: + if ($waterConfig['watermark_image']) $filePath = $this->image($filePath, $waterConfig); + break; + case 2: + $filePath = $this->text($filePath, $waterConfig); + break; + } + } + return $filePath; + } + + /** + * 图片水印 + * @param string $filePath + * @param array $waterConfig + * @param string $waterPath + * @return string + */ + public function image(string $filePath, array $waterConfig = []) + { + if (!$waterConfig) { + $waterConfig = $this->waterConfig; + } + $watermark_image = $waterConfig['watermark_image']; + //远程图片 + $filePath = str_replace(sys_config('site_url'), '', $filePath); + if ($watermark_image && $this->checkFilePathIsRemote($watermark_image)) { + //看是否在本地 + $pathName = $this->getFilePath($watermark_image, true); + if ($pathName == $watermark_image) {//不再本地 继续下载 + [$p, $e] = $this->getFileName($watermark_image); + $name = 'water_image_' . md5($watermark_image) . '.' . $e; + $watermark_image = '.' . $this->defaultPath . '/' . $this->thumbWaterPath . '/' . $name; + if (!file_exists($watermark_image)) { + try { + /** @var DownloadImage $down */ + $down = app()->make(DownloadImage::class); + $data = $down->path($this->thumbWaterPath)->downloadImage($waterConfig['watermark_image'], $name); + $watermark_image = $data['path'] ?? ''; + } catch (\Throwable $e) { + throw new AdminException(400724); + } + } + } else { + $watermark_image = '.' . $pathName; + } + } + if (!$watermark_image) { + throw new AdminException(400722); + } + $savePath = public_path() . $filePath; + try { + $Image = Image::open(app()->getRootPath() . 'public' . $filePath); + $Image->water($watermark_image, $waterConfig['watermark_position'] ?: 1, (int)$waterConfig['watermark_opacity'])->save($savePath); + } catch (\Throwable $e) { + throw new AdminException($e->getMessage()); + } + return $savePath; + } + + /** + * 文字水印 + * @param string $filePath + * @param array $waterConfig + * @return string + */ + public function text(string $filePath, array $waterConfig = []) + { + if (!$waterConfig) { + $waterConfig = $this->waterConfig; + } + if (!$waterConfig['watermark_text']) { + throw new AdminException(400723); + } + $savePath = public_path() . $filePath; + try { + $Image = Image::open(app()->getRootPath() . 'public' . $filePath); + if (strlen($waterConfig['watermark_text_color']) < 7) { + $waterConfig['watermark_text_color'] = substr($waterConfig['watermark_text_color'], 1); + $waterConfig['watermark_text_color'] = '#' . $waterConfig['watermark_text_color'] . $waterConfig['watermark_text_color']; + } + if (strlen($waterConfig['watermark_text_color']) > 7) { + $waterConfig['watermark_text_color'] = substr($waterConfig['watermark_text_color'], 0, 7); + } + $Image->text($waterConfig['watermark_text'], $waterConfig['watermark_text_font'], (float)$waterConfig['watermark_text_size'], $waterConfig['watermark_text_color'], $waterConfig['watermark_position'], [$waterConfig['watermark_x'], $waterConfig['watermark_y'], $waterConfig['watermark_text_angle']])->save($savePath); + } catch (\Throwable $e) { + throw new AdminException($e->getMessage() . $e->getLine()); + } + return $savePath; + } + + /** + * 删除文件 + * @param string $filePath + * @return bool|mixed + */ + public function delete(string $filePath):mixed + { + if (file_exists($filePath)) { + try { + $fileArr = explode('/', $filePath); + $fileName = end($fileArr); + unlink($filePath); + unlink(str_replace($fileName, 'big_' . $fileName, $filePath)); + unlink(str_replace($fileName, 'mid_' . $fileName, $filePath)); + unlink(str_replace($fileName, 'small_' . $fileName, $filePath)); + return true; + } catch (\Exception $e) { + return $this->setError($e->getMessage()); + } + } + return false; + } + + public function listbuckets(string $region, bool $line = false, bool $shared = false) + { + return []; + } + + public function createBucket(string $name, string $region) + { + return null; + } + + public function deleteBucket(string $name) + { + return null; + } + + public function setBucketCors(string $name, string $region) + { + return true; + } + + public function getRegion() + { + return []; + } + + public function bindDomian(string $name, string $domain, string $region = null) + { + return true; + } + + public function getDomian(string $name, string $region = null) + { + return []; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/upload/storage/Oss.php b/demo/thinkphp/backend/phoenix/services/upload/storage/Oss.php new file mode 100644 index 0000000000000000000000000000000000000000..c642444e0d4e5073bb731e24de5417040dd3c755 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/upload/storage/Oss.php @@ -0,0 +1,562 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\services\upload\storage; + +use phoenix\services\upload\BaseUpload; +use phoenix\exceptions\AdminException; +use phoenix\exceptions\UploadException; +use Guzzle\Http\EntityBody; +use OSS\Core\OssException; +use OSS\Model\CorsConfig; +use OSS\Model\CorsRule; +use OSS\OssClient; + + +/** + * 阿里云OSS上传 + * Class OSS + */ +class Oss extends BaseUpload +{ + /** + * accessKey + * @var mixed + */ + protected $accessKey; + + /** + * secretKey + * @var mixed + */ + protected $secretKey; + + /** + * 句柄 + * @var OssClient + */ + protected $handle; + + /** + * 空间域名 Domain + * @var mixed + */ + protected $uploadUrl; + + /** + * 存储空间名称 公开空间 + * @var mixed + */ + protected $storageName; + + /** + * COS使用 所属地域 + * @var mixed|null + */ + protected $storageRegion; + + /** + * 水印位置 + * @var string[] + */ + protected $position = [ + '1' => 'nw',//:左上 + '2' => 'north',//:中上 + '3' => 'ne',//:右上 + '4' => 'west',//:左中 + '5' => 'center',//:中部 + '6' => 'east',//:右中 + '7' => 'sw',//:左下 + '8' => 'south',//:中下 + '9' => 'se',//:右下 + ]; + + /** + * 初始化 + * @param array $config + * @return mixed|void + */ + protected function initialize(array $config) + { + parent::initialize($config); + $this->accessKey = $config['accessKey'] ?? null; + $this->secretKey = $config['secretKey'] ?? null; + $this->uploadUrl = $this->checkUploadUrl($config['uploadUrl'] ?? ''); + $this->storageName = $config['storageName'] ?? null; + $this->storageRegion = $config['storageRegion'] ?? null; + } + + /** + * 初始化oss + * @return OssClient + * @throws OssException + */ + protected function app() + { + if (!$this->accessKey || !$this->secretKey) { + throw new UploadException(400721); + } + $this->handle = new OssClient($this->accessKey, $this->secretKey, $this->storageRegion); + //不再自动创建 +// if (!$this->handle->doesBucketExist($this->storageName)) { +// $this->handle->createBucket($this->storageName, OssClient::OSS_ACL_TYPE_PUBLIC_READ_WRITE); +// } + return $this->handle; + } + + /** + * 上传文件 + * @param string $file + * @param bool $realName + * @return array|bool|mixed|\StdClass + */ + public function move(string $file = 'file', $realName = false) + { + $fileHandle = app()->request->file($file); + if (!$fileHandle) { + return $this->setError('上传的文件不存在'); + } + if ($this->validate) { + if (!in_array(pathinfo($fileHandle->getOriginalName(), PATHINFO_EXTENSION), $this->validate['fileExt'])) { + return $this->setError('不合法的文件后缀'); + } + if (filesize($fileHandle) > $this->validate['filesize']) { + return $this->setError('文件过大'); + } + if (!in_array($fileHandle->getOriginalMime(), $this->validate['fileMime'])) { + return $this->setError('不合法的文件类型'); + } + } + $key = $this->saveFileName($fileHandle->getRealPath(), $fileHandle->getOriginalExtension()); + $key = $this->getUploadPath($key); + try { + $uploadInfo = $this->app()->uploadFile($this->storageName, $key, $fileHandle->getRealPath()); + if (!isset($uploadInfo['info']['url'])) { + return $this->setError('Upload failure'); + } + $this->fileInfo->uploadInfo = $uploadInfo; + $this->fileInfo->realName = $fileHandle->getOriginalName(); + $this->fileInfo->filePath = $this->uploadUrl . '/' . $key; + $this->fileInfo->fileName = $key; + $this->fileInfo->filePathWater = $this->water($this->fileInfo->filePath); + $this->authThumb && $this->thumb($this->fileInfo->filePath); + return $this->fileInfo; + } catch (UploadException $e) { + return $this->setError($e->getMessage()); + } + } + + /** + * 文件流上传 + * @param $fileContent + * @param string|null $key + * @return array|bool|mixed + * @throws OssException + */ + public function stream($fileContent, string $key = null) + { + try { + if (!$key) { + $key = $this->saveFileName(); + } + $key = $this->getUploadPath($key); + $fileContent = (string)EntityBody::factory($fileContent); + $uploadInfo = $this->app()->putObject($this->storageName, $key, $fileContent); + if (!isset($uploadInfo['info']['url'])) { + return $this->setError('Upload failure'); + } + $this->fileInfo->uploadInfo = $uploadInfo; + $this->fileInfo->realName = $key; + $this->fileInfo->filePath = $this->uploadUrl . '/' . $key; + $this->fileInfo->fileName = $key; + $this->fileInfo->filePathWater = $this->water($this->fileInfo->filePath); + $this->thumb($this->fileInfo->filePath); + return $this->fileInfo; + } catch (UploadException $e) { + return $this->setError($e->getMessage()); + } + } + + /** + * 缩略图 + * @param string $filePath + * @param string $fileName + * @param string $type + * @return array|mixed + */ + public function thumb(string $filePath = '', string $fileName = '', string $type = 'all') + { + $filePath = $this->getFilePath($filePath); + $data = ['big' => $filePath, 'mid' => $filePath, 'small' => $filePath]; + $this->fileInfo->filePathBig = $this->fileInfo->filePathMid = $this->fileInfo->filePathSmall = $this->fileInfo->filePathWater = $filePath; + if ($filePath) { + $config = $this->thumbConfig; + foreach ($this->thumb as $v) { + if ($type == 'all' || $type == $v) { + $height = 'thumb_' . $v . '_height'; + $width = 'thumb_' . $v . '_width'; + $key = 'filePath' . ucfirst($v); + if (sys_config('image_thumbnail_status', 1) && isset($config[$height]) && isset($config[$width]) && $config[$height] && $config[$width]) { + $this->fileInfo->$key = $filePath . '?x-oss-process=image/resize,h_' . $config[$height] . ',w_' . $config[$width]; + $this->fileInfo->$key = $this->water($this->fileInfo->$key); + $data[$v] = $this->fileInfo->$key; + } else { + $this->fileInfo->$key = $this->water($this->fileInfo->$key); + $data[$v] = $this->fileInfo->$key; + } + } + } + } + return $data; + } + + /** + * 水印 + * @param string $filePath + * @return mixed|string + */ + public function water(string $filePath = '') + { + $filePath = $this->getFilePath($filePath); + $waterConfig = $this->waterConfig; + $waterPath = $filePath; + if ($waterConfig['image_watermark_status'] && $filePath) { + if (strpos($filePath, '?x-oss-process') === false) { + $filePath .= '?x-oss-process=image'; + } + switch ($waterConfig['watermark_type']) { + case 1://图片 + if (!$waterConfig['watermark_image']) { + throw new AdminException(400722); + } + $waterPath = $filePath .= '/watermark,image_' . base64_encode($waterConfig['watermark_image']) . ',t_' . $waterConfig['watermark_opacity'] . ',g_' . ($this->position[$waterConfig['watermark_position']] ?? 'nw') . ',x_' . $waterConfig['watermark_x'] . ',y_' . $waterConfig['watermark_y']; + break; + case 2://文字 + if (!$waterConfig['watermark_text']) { + throw new AdminException(400723); + } + $waterConfig['watermark_text_color'] = str_replace('#', '', $waterConfig['watermark_text_color']); + $waterPath = $filePath .= '/watermark,text_' . base64_encode($waterConfig['watermark_text']) . ',color_' . $waterConfig['watermark_text_color'] . ',size_' . $waterConfig['watermark_text_size'] . ',g_' . ($this->position[$waterConfig['watermark_position']] ?? 'nw') . ',x_' . $waterConfig['watermark_x'] . ',y_' . $waterConfig['watermark_y']; + break; + } + } + return $waterPath; + } + + /** + * 删除资源 + * @param $key + * @return mixed + */ + public function delete(string $key) + { + try { + return $this->app()->deleteObject($this->storageName, $key); + } catch (OssException $e) { + return $this->setError($e->getMessage()); + } + } + + /** + * 获取OSS上传密钥 + * @return mixed|void + */ + public function getTempKeys($callbackUrl = '', $dir = '') + { + // TODO: Implement getTempKeys() method. + $base64CallbackBody = base64_encode(json_encode([ + 'callbackUrl' => $callbackUrl, + 'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}', + 'callbackBodyType' => "application/x-www-form-urlencoded" + ])); + + $policy = json_encode([ + 'expiration' => $this->gmtIso8601(time() + 30), + 'conditions' => + [ + [0 => 'content-length-range', 1 => 0, 2 => 1048576000], + [0 => 'starts-with', 1 => '$key', 2 => $dir] + ] + ]); + $base64Policy = base64_encode($policy); + $signature = base64_encode(hash_hmac('sha1', $base64Policy, $this->secretKey, true)); + return [ + 'accessid' => $this->accessKey, + 'host' => $this->uploadUrl, + 'policy' => $base64Policy, + 'signature' => $signature, + 'expire' => time() + 30, + 'callback' => $base64CallbackBody, + 'type' => 'OSS' + ]; + } + + /** + * 获取ISO时间格式 + * @param $time + * @return string + */ + protected function gmtIso8601($time) + { + $dtStr = date("c", $time); + $mydatetime = new \DateTime($dtStr); + $expiration = $mydatetime->format(\DateTime::ISO8601); + $pos = strpos($expiration, '+'); + $expiration = substr($expiration, 0, $pos); + return $expiration . "Z"; + } + + /** + * 获取当前管理下的所有桶 + * @param string|null $region + * @param bool $line + * @param bool $shared + * @return mixed|\OSS\Model\BucketListInfo + * @throws OssException + */ + public function listbuckets(string $region = 'oss-cn-hangzhou.aliyuncs.com', bool $line = false, bool $shared = false) + { + $handle = new OssClient($this->accessKey, $this->secretKey, $region); + $response = $handle->listBuckets(); + $data = $response->getBucketList(); + $list = []; + foreach ($data as $item) { + $list[] = [ + 'location' => $item->getLocation(), + 'name' => $item->getName(), + 'createTime' => $item->getCreateDate() + ]; + } + return $list; + } + + /** + * @param string $name + * @param string $region + * @param string $acl + * @return mixed|void + */ + public function createBucket(string $name, string $region = '', string $acl = OssClient::OSS_ACL_TYPE_PUBLIC_READ) + { + $regionData = $this->getRegion(); + if (!in_array($region, array_column($regionData, 'value'))) { + return $this->setError('OSS:无效的区域'); + } + try { + $handle = new OssClient($this->accessKey, $this->secretKey, $region); + if ($handle->doesBucketExist($name)) { + return $this->setError('OSS:空间已经存在,请更换空间名'); + } + return $handle->createBucket($name, $acl); + } catch (\Throwable $e) { + if (strstr('The bucket you access does not belong to you', $e->getMessage())) { + return $this->setError('OSS:空间已被使用,请更换空间名'); + } + return $this->setError('OSS:' . $e->getMessage()); + } + } + + /** + * @param string $name + * @param string $region + * @return bool|mixed|null + */ + public function deleteBucket(string $name, string $region = '') + { + try { + $handle = new OssClient($this->accessKey, $this->secretKey, $region); + return $handle->deleteBucket($name); + } catch (\Throwable $e) { + return $this->setError($e->getMessage()); + } + } + + /** + * @param string $name + * @param string|null $region + * @return array|bool + */ + public function getDomian(string $name, string $region = null) + { + try { + $handle = new OssClient($this->accessKey, $this->secretKey, $region); + $res = $handle->getBucketCname($name); + $data = $res->getCnames(); + return array_column($data, 'Domain'); + } catch (\Throwable $e) { + } + return []; + } + + /** + * 绑定域名 + * @param string $name + * @param string $domain + * @param string|null $region + * @return bool|mixed + */ + public function bindDomian(string $name, string $domain, string $region = null) + { + $parseDomin = parse_url($domain); + try { + $handle = new OssClient($this->accessKey, $this->secretKey, $region); + $res = $handle->getBucketCname($name); + $data = $res->getCnames(); + if (in_array($parseDomin['host'], array_column($data, 'Domain'))) { + return true; + } + return $handle->addBucketCname($name, $parseDomin['host']); + } catch (\Throwable $e) { + return $this->setError($e->getMessage()); + } + } + + /** + * 设置跨域 + * @param string $name + * @param string $region + * @return bool|null + */ + public function setBucketCors(string $name, string $region) + { + try { + $handle = new OssClient($this->accessKey, $this->secretKey, $region); + $corsConfig = new CorsConfig(); + $rule = new CorsRule(); + // 设置允许跨域请求的响应头。AllowedHeader可以设置多个,每个AllowedHeader中最多只能使用一个通配符星号(*)。 + // 建议无特殊需求时设置AllowedHeader为星号(*)。 + $rule->addAllowedHeader("*"); + // 设置允许用户从应用程序中访问的响应头。ExposeHeader可以设置多个,ExposeHeader中不支持使用通配符星号(*)。 + $rule->addExposeHeader("ETag"); + // 设置允许的跨域请求的来源。AllowedOrigin可以设置多个,每个AllowedOrigin中最多只能使用一个通配符星号(*)。 + // 设置AllowedOrigin为星号(*)时,表示允许所有域的来源。 + $rule->addAllowedOrigin("*"); + // 设置允许的跨域请求方法。 + $rule->addAllowedMethod("POST"); + $rule->addAllowedMethod("GET"); + $rule->addAllowedMethod("DELETE"); + $rule->addAllowedMethod("PUT"); + $rule->addAllowedMethod("HEAD"); + // 设置浏览器对特定资源的预取(OPTIONS)请求返回结果的缓存时间,单位为秒。 + $rule->setMaxAgeSeconds(600); + // 每个Bucket最多支持添加10条规则。 + $corsConfig->addRule($rule); + return $handle->putBucketCors($name, $corsConfig); + } catch (\Throwable $e) { + return $this->setError($e->getMessage()); + } + } + + /** + * 数据中心 + * @return mixed|\string[][] + */ + public function getRegion() + { + return [ + [ + 'value' => 'oss-cn-hangzhou.aliyuncs.com', + 'label' => '华东1(杭州)' + ], + [ + 'value' => 'oss-cn-shanghai.aliyuncs.com', + 'label' => '华东2(上海)' + ], + [ + 'value' => 'oss-cn-qingdao.aliyuncs.com', + 'label' => '华北1(青岛)' + ], + [ + 'value' => 'oss-cn-beijing.aliyuncs.com', + 'label' => '华北2(北京)' + ], + [ + 'value' => 'oss-cn-zhangjiakou.aliyuncs.com', + 'label' => '华北 3(张家口)' + ], + [ + 'value' => 'oss-cn-huhehaote.aliyuncs.com', + 'label' => '华北5(呼和浩特)' + ], + [ + 'value' => 'oss-cn-wulanchabu.aliyuncs.com', + 'label' => '华北6(乌兰察布)' + ], + [ + 'value' => 'oss-cn-shenzhen.aliyuncs.com', + 'label' => '华南1(深圳)' + ], + [ + 'value' => 'oss-cn-heyuan.aliyuncs.com', + 'label' => '华南2(河源)' + ], + [ + 'value' => 'oss-cn-guangzhou.aliyuncs.com', + 'label' => '华南3(广州)' + ], + [ + 'value' => 'oss-cn-chengdu.aliyuncs.com', + 'label' => '西南1(成都)' + ], + [ + 'value' => 'oss-cn-hongkong.aliyuncs.com', + 'label' => '中国(香港)' + ], + [ + 'value' => 'oss-us-west-1.aliyuncs.com', + 'label' => '美国(硅谷)*' + ], + [ + 'value' => 'oss-us-east-1.aliyuncs.com', + 'label' => '美国(弗吉尼亚)*' + ], + [ + 'value' => 'oss-ap-southeast-1.aliyuncs.com', + 'label' => '新加坡*' + ], + [ + 'value' => 'oss-ap-southeast-2.aliyuncs.com', + 'label' => '澳大利亚(悉尼)*' + ], + [ + 'value' => 'oss-ap-southeast-3.aliyuncs.com', + 'label' => '马来西亚(吉隆坡)*' + ], + [ + 'value' => 'oss-ap-southeast-5.aliyuncs.com', + 'label' => '印度尼西亚(雅加达)*' + ], + [ + 'value' => 'oss-ap-northeast-1.aliyuncs.com', + 'label' => '日本(东京)*' + ], + [ + 'value' => 'oss-ap-south-1.aliyuncs.com', + 'label' => '印度(孟买)*' + ], + [ + 'value' => 'oss-eu-central-1.aliyuncs.com', + 'label' => '德国(法兰克福)*' + ], + [ + 'value' => 'oss-eu-west-1.aliyuncs.com', + 'label' => '英国(伦敦)' + ], + [ + 'value' => 'oss-me-east-1.aliyuncs.com', + 'label' => '阿联酋(迪拜)*' + ], + [ + 'value' => 'oss-ap-southeast-6.aliyuncs.com', + 'label' => '菲律宾(马尼拉)' + ] + ]; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/upload/storage/Qiniu.php b/demo/thinkphp/backend/phoenix/services/upload/storage/Qiniu.php new file mode 100644 index 0000000000000000000000000000000000000000..9d43828c1033db9943410319cd0089b3f4a9c7c6 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/upload/storage/Qiniu.php @@ -0,0 +1,467 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\services\upload\storage; + +use phoenix\services\upload\BaseUpload; +use phoenix\exceptions\AdminException; +use phoenix\exceptions\UploadException; +use Qiniu\Auth; +use Qiniu\Http\Client; +use Qiniu\Http\Error; +use Qiniu\Storage\BucketManager; +use Qiniu\Storage\UploadManager; +use Qiniu\Config; + + +/** + * TODO 七牛云上传 + * Class Qiniu + */ +class Qiniu extends BaseUpload +{ + /** + * accessKey + * @var mixed + */ + protected $accessKey; + + /** + * secretKey + * @var mixed + */ + protected $secretKey; + + /** + * 句柄 + * @var object + */ + protected $handle; + + /** + * 空间域名 Domain + * @var mixed + */ + protected $uploadUrl; + + /** + * 存储空间名称 公开空间 + * @var mixed + */ + protected $storageName; + + /** + * COS使用 所属地域 + * @var mixed|null + */ + protected $storageRegion; + + /** + * 水印位置 + * @var string[] + */ + protected $position = [ + '1' => 'NorthWest',//:左上 + '2' => 'North',//:中上 + '3' => 'NorthEast',//:右上 + '4' => 'West',//:左中 + '5' => 'Center',//:中部 + '6' => 'East',//:右中 + '7' => 'SouthWest',//:左下 + '8' => 'South',//:中下 + '9' => 'SouthEast',//:右下 + ]; + + /** + * 初始化 + * @param array $config + * @return mixed|void + */ + public function initialize(array $config) + { + parent::initialize($config); + $this->accessKey = $config['accessKey'] ?? null; + $this->secretKey = $config['secretKey'] ?? null; + $this->uploadUrl = $this->checkUploadUrl($config['uploadUrl'] ?? ''); + $this->storageName = $config['storageName'] ?? null; + $this->storageRegion = $config['storageRegion'] ?? null; + } + + /** + * 实例化七牛云 + * @return object|Auth + */ + protected function app() + { + if (!$this->accessKey || !$this->secretKey) { + throw new UploadException(400721); + } + $this->handle = new Auth($this->accessKey, $this->secretKey); + return $this->handle; + } + + /** + * 上传文件 + * @param string $file + * @param bool $realName + * @return array|bool|mixed|\StdClass|string + */ + public function move(string $file = 'file', $realName = false) + { + $fileHandle = app()->request->file($file); + if (!$fileHandle) { + return $this->setError('上传的文件不存在'); + } + if ($this->validate) { + if (!in_array(pathinfo($fileHandle->getOriginalName(), PATHINFO_EXTENSION), $this->validate['fileExt'])) { + return $this->setError('不合法的文件后缀'); + } + if (filesize($fileHandle) > $this->validate['filesize']) { + return $this->setError('文件过大'); + } + if (!in_array($fileHandle->getOriginalMime(), $this->validate['fileMime'])) { + return $this->setError('不合法的文件类型'); + } + } + $key = $this->saveFileName($fileHandle->getRealPath(), $fileHandle->getOriginalExtension()); + $key = $this->getUploadPath($key); + $token = $this->app()->uploadToken($this->storageName); + try { + $uploadMgr = new UploadManager(); + [$result, $error] = $uploadMgr->putFile($token, $key, $fileHandle->getRealPath()); + if ($error !== null) { + return $this->setError($error->message()); + } + $this->fileInfo->uploadInfo = $result; + $this->fileInfo->realName = $fileHandle->getOriginalName(); + $this->fileInfo->filePath = $this->uploadUrl . '/' . $key; + $this->fileInfo->fileName = $key; + $this->fileInfo->filePathWater = $this->water($this->fileInfo->filePath); + $this->authThumb && $this->thumb($this->fileInfo->filePath); + return $this->fileInfo; + } catch (UploadException $e) { + return $this->setError($e->getMessage()); + } + } + + /** + * 文件流上传 + * @param $fileContent + * @param string|null $key + * @return array|bool|mixed|\StdClass + */ + public function stream($fileContent, string $key = null) + { + if (!$key) { + $key = $this->saveFileName(); + } + $key = $this->getUploadPath($key); + $token = $this->app()->uploadToken($this->storageName, $key); + try { + $uploadMgr = new UploadManager(); + [$result, $error] = $uploadMgr->put($token, $key, $fileContent); + if ($error !== null) { + return $this->setError($error->message()); + } + $this->fileInfo->uploadInfo = $result; + $this->fileInfo->realName = $key; + $this->fileInfo->filePath = $this->uploadUrl . '/' . $key; + $this->fileInfo->fileName = $key; + $this->fileInfo->filePathWater = $this->water($this->fileInfo->filePath); + $this->thumb($this->fileInfo->filePath); + return $this->fileInfo; + } catch (UploadException $e) { + return $this->setError($e->getMessage()); + } + } + + /** + * 缩略图 + * @param string $filePath + * @param string $fileName + * @param string $type + * @return array|mixed + */ + public function thumb(string $filePath = '', string $fileName = '', string $type = 'all') + { + $filePath = $this->getFilePath($filePath); + $data = ['big' => $filePath, 'mid' => $filePath, 'small' => $filePath]; + $this->fileInfo->filePathBig = $this->fileInfo->filePathMid = $this->fileInfo->filePathSmall = $this->fileInfo->filePathWater = $filePath; + if ($filePath) { + $config = $this->thumbConfig; + foreach ($this->thumb as $v) { + if ($type == 'all' || $type == $v) { + $height = 'thumb_' . $v . '_height'; + $width = 'thumb_' . $v . '_width'; + $key = 'filePath' . ucfirst($v); + if (sys_config('image_thumbnail_status', 1) && isset($config[$height]) && isset($config[$width]) && $config[$height] && $config[$width]) { + $this->fileInfo->$key = $filePath . '?imageView2/2/w/' . $config[$width] . '/h/' . $config[$height]; + $this->fileInfo->$key = $this->water($this->fileInfo->$key); + $data[$v] = $this->fileInfo->$key; + } else { + $this->fileInfo->$key = $this->water($this->fileInfo->$key); + $data[$v] = $this->fileInfo->$key; + } + } + } + } + return $data; + } + + /** + * 水印 + * @param string $filePath + * @return mixed|string + */ + public function water(string $filePath = '') + { + $filePath = $this->getFilePath($filePath); + $waterConfig = $this->waterConfig; + $waterPath = $filePath; + if ($waterConfig['image_watermark_status'] && $filePath) { + if (strpos($filePath, '?') === false) { + $filePath .= '?watermark'; + } else { + $filePath .= '&watermark'; + } + switch ($waterConfig['watermark_type']) { + case 1://图片 + if (!$waterConfig['watermark_image']) { + throw new AdminException(400722); + } + $waterPath = $filePath .= '/1/image/' . base64_encode($waterConfig['watermark_image']) . '/gravity/' . ($this->position[$waterConfig['watermark_position']] ?? 'SouthEest') . '/dissolve/' . $waterConfig['watermark_opacity'] . '/dx/' . $waterConfig['watermark_x'] . '/dy/' . $waterConfig['watermark_y']; + break; + case 2://文字 + if (!$waterConfig['watermark_text']) { + throw new AdminException(400723); + } + $waterPath = $filePath .= '/2/text/' . base64_encode($waterConfig['watermark_text']) . '/fill/' . base64_encode($waterConfig['watermark_text_color']) . '/fontsize/' . $waterConfig['watermark_text_size'] . '/gravity/' . ($this->position[$waterConfig['watermark_position']] ?? 'SouthEest') . '/dx/' . $waterConfig['watermark_x'] . '/dy/' . $waterConfig['watermark_y']; + break; + } + } + return $waterPath; + } + + /** + * 获取上传配置信息 + * @return array + */ + public function getSystem() + { + $token = $this->app()->uploadToken($this->storageName); + $domain = $this->uploadUrl; + $key = $this->saveFileName(); + return compact('token', 'domain', 'key'); + } + + /** + * TODO 删除资源 + * @param $key + * @param $bucket + * @return mixed + */ + public function delete(string $key) + { + $bucketManager = new BucketManager($this->app(), new Config()); + return $bucketManager->delete($this->storageName, $key); + } + + /** + * 获取七牛云上传密钥 + * @return mixed|string + */ + public function getTempKeys() + { + $token = $this->app()->uploadToken($this->storageName); + $domain = $this->uploadUrl; + $key = $this->saveFileName(NULL, 'mp4'); + $type = 'QINIU'; + return compact('token', 'domain', 'key', 'type'); + } + + /** + * 获取当前所有桶列表 + * @param string|null $region + * @param bool $line + * @param bool $shared + * @return bool|mixed + */ + public function listbuckets(string $region = null, bool $line = false, bool $shared = false) + { + $bucket = new BucketManager($this->app()); + [$response, $error] = $bucket->listbuckets($region, $line ? 'true' : 'false', $shared ? 'true' : 'false'); + if ($error !== null) { + return $this->setError($error->message()); + } + return $response; + } + + /** + * @param string $name + * @param string $region + * @return bool|mixed + */ + public function createBucket(string $name, string $region = 'z0') + { + $regionData = $this->getRegion(); + if (!in_array($region, array_column($regionData, 'value'))) { + return $this->setError('七牛云:无效的区域'); + } + $url = 'https://' . Config::UC_HOST . '/mkbucketv3/' . $name . '/region/' . $region; + $body = null; + $headers = $this->app()->authorizationV2($url, 'POST', $body, 'application/json'); + $headers["Content-Type"] = 'application/json'; + $ret = Client::post($url, $body, $headers); + if (!$ret->ok()) { + $error = new Error($url, $ret); + if ('bucket exists' === $error->message()) { + return $this->setError('七牛云:云空间已存在'); + } + return $this->setError('七牛云:' . $error->message()); + } + return ($ret->body === null) ? array() : $ret->json(); + } + + /** + * 获取区域 + * @return mixed|\string[][] + */ + public function getRegion() + { + return [ + [ + 'value' => 'z0', + 'label' => '华东' + ], + [ + 'value' => 'z1', + 'label' => '华北' + ], + [ + 'value' => 'z2', + 'label' => '华南' + ], + [ + 'value' => 'na0', + 'label' => '北美' + ], + [ + 'value' => 'as0', + 'label' => '东南亚' + ], + [ + 'value' => 'cn-east-2', + 'label' => '华东-浙江2' + ], + ]; + } + + /** + * 删除空间 + * @param string $name + * @return bool|mixed + */ + public function deleteBucket(string $name) + { + $bucket = new BucketManager($this->app()); + [$response, $error] = $bucket->deleteBucket($name); + if ($error !== null) { + return $this->setError($error->message()); + } + return $response; + } + + /** + * 获取七牛域名 + * @param string $name + * @return array|bool|mixed|null + */ + public function getDomian(string $name) + { + $url = 'https://' . Config::UC_HOST . '/v2/domains?tbl=' . $name; + $body = null; + $headers = $this->app()->authorizationV2($url, 'POST', $body, 'application/x-www-form-urlencoded'); + $headers["Content-Type"] = 'application/x-www-form-urlencoded'; + $ret = Client::post($url, $body, $headers); + if (!$ret->ok()) { + $error = new Error($url, $ret); + return $this->setError('七牛云:' . $error->message()); + } + return ($ret->body === null) ? array() : $ret->json(); + } + + public function getDomianInfo(string $host) + { + $url = 'https://' . Config::API_HOST . '/domain/' . $host; + $headers = $this->app()->authorization($url, null, 'application/x-www-form-urlencoded'); + $headers["Content-Type"] = 'application/x-www-form-urlencoded'; + $ret = Client::get($url, $headers); + if (!$ret->ok()) { + $error = new Error($url, $ret); + return $this->setError('七牛云:' . $error->message()); + } + return ($ret->body === null) ? array() : $ret->json(); + } + + /** + * + * @param string $name + * @param string $domain + * @param string|null $region + * @return array|bool|mixed|null + */ + public function bindDomian(string $name, string $domain, string $region = null) + { + $parseDomin = parse_url($domain); + $url = 'https://' . Config::API_HOST . '/domain/' . $parseDomin['host']; + $body = [ + 'type' => 'normal', + 'platform' => 'web', + 'geocover' => 'china', + 'source' => [ + 'sourceType' => 'qiniuBucket', + 'sourceQiniuBucket' => $name, + 'TestURLPath' => 'qiniu_do_not_delete.gif', + ], + 'protocol' => $parseDomin['scheme'], + 'cache' => [ + 'cacheControls' => [ + [ + 'time' => 1, + 'timeunit' => 4, + 'type' => 'all', + 'rule' => '*' + ] + ], + 'ignoreParam' => false + ] + ]; + $bodyJson = json_encode($body); + $headers = $this->app()->authorization($url, $bodyJson, 'application/json'); + $headers["Content-Type"] = 'application/json'; + $ret = Client::post($url, $bodyJson, $headers); + if (!$ret->ok()) { + $error = new Error($url, $ret); + return $this->setError('七牛云:' . $error->message()); + } + return ($ret->body === null) ? array() : $ret->json(); + } + + /** + * 跨域 + * @param string $name + * @param string $region + * @return bool + */ + public function setBucketCors(string $name, string $region) + { + return true; + } +} diff --git a/demo/thinkphp/backend/phoenix/services/workerman/ChannelService.php b/demo/thinkphp/backend/phoenix/services/workerman/ChannelService.php new file mode 100644 index 0000000000000000000000000000000000000000..f76ccb0eef599221d0f27206ca80aaf6ae068fa3 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/workerman/ChannelService.php @@ -0,0 +1,94 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\services\workerman; + + +use Channel\Client; + +/** + * + * + * @author GQL + * @since 1.0 + */ +class ChannelService +{ + /** + * @var Client + */ + protected $channel; + + /** + * @var + */ + protected string $trigger = 'phoenix'; + + /** + * @var ChannelService + */ + protected static $instance; + + public function __construct() + { + self::connet(); + } + + public static function instance() + { + if (is_null(self::$instance)) + self::$instance = new self(); + + return self::$instance; + } + + public static function connet(): void + { + $config = config('workerman.channel'); + Client::connect($config['ip'], $config['port']); + } + + /** + * @param string $name + * + * @return \phoenix\services\workerman\ChannelService + */ + public function setTrigger(string $name): static + { + $this->trigger = $name; + return $this; + } + + /** + * 发送消息 + * @param string $type 类型 + * @param array|null $data 数据 + * @param array|null $ids 用户 id,不传为全部用户 + */ + public function send(string $type, ?array $data = null, ?array $ids = null): void + { + $res = compact('type'); + + if (!is_null($data)) + $res['data'] = $data; + + if (!is_null($ids) && count($ids)) + $res['ids'] = $ids; + + $this->trigger($this->trigger, $res); + $this->trigger = 'phoenix'; + } + + public function trigger(string $type, ?array $data = null): void + { + Client::publish($type, $data); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/workerman/Response.php b/demo/thinkphp/backend/phoenix/services/workerman/Response.php new file mode 100644 index 0000000000000000000000000000000000000000..142c4f3fdba6097f402b5852b076ad0c1b8419d0 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/workerman/Response.php @@ -0,0 +1,116 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\services\workerman; + + +use Workerman\Connection\TcpConnection; + +/** + * + * + * @author GQL + * @since 1.0 + */ +class Response +{ + /** + * @var TcpConnection + */ + protected $connection; + + /** + * 设置用户 + * + * @param TcpConnection $connection + * @return $this + */ + public function connection(TcpConnection $connection) + { + $this->connection = $connection; + return $this; + } + + /** + * 发送请求 + * + * @param string $type + * @param array|null $data + * @param bool $close + * @param array $other + * @return bool|null + */ + public function send(string $type, ?array $data = null, bool $close = false, array $other = []) + { + $this->connection->lastMessageTime = time(); + $res = compact('type'); + + if (!is_null($data)) $res['data'] = $data; + $data = array_merge($res, $other); + + if ($close) + $data['close'] = true; + + $json = json_encode($data); + + return $close + ? ($this->connection->close($json)) + : $this->connection->send($json); + } + + /** + * 成功 + * + * @param string $message + * @param array|null $data + * @return bool|null + */ + public function success($type = 'success', ?array $data = null) + { + if (is_array($type)) { + $data = $type; + $type = 'success'; + } + return $this->send($type, $data); + } + + /** + * 失败 + * + * @param string $message + * @param array|null $data + * @return bool|null + */ + public function fail($type = 'error', ?array $data = null) + { + if (is_array($type)) { + $data = $type; + $type = 'error'; + } + return $this->send($type, $data); + } + + /** + * 关闭连接 + * + * @param string $type + * @param array|null $data + * @return bool|null + */ + public function close($type = 'error', ?array $data = null) + { + if (is_array($type)) { + $data = $type; + $type = 'error'; + } + return $this->send($type, $data, true); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/workerman/WorkermanHandle.php b/demo/thinkphp/backend/phoenix/services/workerman/WorkermanHandle.php new file mode 100644 index 0000000000000000000000000000000000000000..01816b4db4e81a87b6384f0b2044a872969ff9be --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/workerman/WorkermanHandle.php @@ -0,0 +1,65 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\services\workerman; + +use app\services\system\admin\SystemAuthServices; +use phoenix\exceptions\AuthException; +use Workerman\Connection\TcpConnection; + +class WorkermanHandle +{ + protected $service; + + public function __construct(WorkermanService &$service) + { + $this->service = &$service; + } + + /** + * @param \Workerman\Connection\TcpConnection $connection + * @param array $res + * @param \phoenix\services\workerman\Response $response + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function login(TcpConnection &$connection, array $res, Response $response): mixed + { + if (!isset($res['data']) || !$token = $res['data']) { + return $response->close([ + 'msg' => '授权失败!', + ]); + } + try { + /** @var SystemAuthServices $adminAuthService */ + $adminAuthService = app()->make(SystemAuthServices::class); + $authInfo = $adminAuthService->parseToken($token); + } catch (AuthException $e) { + return $response->close([ + 'msg' => $e->getMessage(), + 'code' => $e->getCode(), + ]); + } + + if (!$authInfo || !isset($authInfo['id'])) { + return $response->close([ + 'msg' => '授权失败!', + ]); + } + $connection->adminInfo = $authInfo; + $connection->adminId = $authInfo['id']; + $this->service->setUser($connection); + return $response->success(); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/workerman/WorkermanService.php b/demo/thinkphp/backend/phoenix/services/workerman/WorkermanService.php new file mode 100644 index 0000000000000000000000000000000000000000..73b1368b56f60d72b7b6875bb1ff88fa47c15a06 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/workerman/WorkermanService.php @@ -0,0 +1,117 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\services\workerman; + +use Channel\Client; +use Workerman\Connection\TcpConnection; +use Workerman\Lib\Timer; +use Workerman\Worker; + +class WorkermanService +{ + /** + * @var Worker + */ + protected $worker; + + /** + * @var TcpConnection[] + */ + protected array $connections = []; + + /** + * @var TcpConnection[] + */ + protected $user = []; + + /** + * @var WorkermanHandle + */ + protected $handle; + + /** + * @var Response + */ + protected $response; + + /** + * @var int + */ + protected $timer; + + public function __construct(Worker $worker) + { + $this->worker = $worker; + $this->handle = new WorkermanHandle($this); + $this->response = new Response(); + } + + /** + * setUser + * + * @param \Workerman\Connection\TcpConnection $connection + */ + public function setUser(TcpConnection $connection): void + { + $this->user[$connection->adminInfo['id']] = $connection; + } + + /** + * @param \Workerman\Connection\TcpConnection $connection + */ + public function onConnect(TcpConnection $connection): void + { + $this->connections[$connection->id] = $connection; + $connection->lastMessageTime = time(); + } + + public function onMessage(TcpConnection $connection, $res) + { + $connection->lastMessageTime = time(); + $res = json_decode($res, true); + if (!$res || !isset($res['type']) || !$res['type'] || $res['type'] == 'ping') { + return $this->response->connection($connection)->success('ping', ['now' => time()]); + } + if (!method_exists($this->handle, $res['type'])) return; + + $this->handle->{$res['type']}($connection, $res + ['data' => []], $this->response->connection($connection)); + } + + public function onWorkerStart(Worker $worker) + { + + ChannelService::connet(); + Client::on('phoenix', function ($eventData) use ($worker) { + if (!isset($eventData['type']) || !$eventData['type']) return; + $ids = isset($eventData['ids']) && count($eventData['ids']) ? $eventData['ids'] : array_keys($this->user); + foreach ($ids as $id) { + if (isset($this->user[$id])) + $this->response->connection($this->user[$id])->success($eventData['type'], $eventData['data'] ?? null); + } + }); + + //定时检测超时连接 +// $this->timer = Timer::add(15, function () use (&$worker) { +// $time_now = time(); +// foreach ($worker->connections as $connection) { +// if ($time_now - $connection->lastMessageTime > 15) { +// $this->response->connection($connection)->close('timeout'); +// } +// } +// }); + } + + public function onClose(TcpConnection $connection): void + { + unset($this->connections[$connection->id]); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/workerman/chat/ChatHandle.php b/demo/thinkphp/backend/phoenix/services/workerman/chat/ChatHandle.php new file mode 100644 index 0000000000000000000000000000000000000000..a9a4a7d5924aebd438f7c400416ca449fc02f097 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/workerman/chat/ChatHandle.php @@ -0,0 +1,356 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\services\workerman\chat; + +use app\services\kefu\LoginServices; +use app\services\kefu\service\StoreServiceLogServices; +use app\services\kefu\service\StoreServiceRecordServices; +use app\services\kefu\service\StoreServiceServices; +use app\services\order\StoreOrderServices; +use app\services\product\product\StoreProductServices; +use app\services\user\UserServices; +use app\services\wechat\WechatUserServices; +use app\services\user\UserAuthServices; +use phoenix\exceptions\AuthException; +use phoenix\services\app\WechatService; +use phoenix\services\workerman\Response; +use phoenix\utils\Arr; +use think\facade\Log; +use Workerman\Connection\TcpConnection; + +/** + * + * + * @author GQL + * @since 1.0 + */ +class ChatHandle +{ + /** + * @var ChatService + */ + protected $service; + + /** + * ChatHandle constructor. + * @param ChatService $service + */ + public function __construct(ChatService &$service) + { + $this->service = &$service; + } + + /** + * 客服登录 + * @param TcpConnection $connection + * @param array $res + * @param Response $response + * @return bool|null + * @throws \Psr\SimpleCache\InvalidArgumentException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function kefu_login(TcpConnection &$connection, array $res, Response $response) + { + if (!isset($res['data']) || !$token = $res['data']) { + return $response->close([ + 'msg' => '授权失败!' + ]); + } + try { + /** @var LoginServices $services */ + $services = app()->make(LoginServices::class); + $kefuInfo = $services->parseToken($token); + } catch (AuthException $e) { + return $response->close([ + 'msg' => $e->getMessage() + ]); + } + + $connection->kefuUser = $kefuInfo; + /** @var UserServices $userService */ + $userService = app()->make(UserServices::class); + $connection->user = $userService->get($kefuInfo['uid'], ['uid', 'nickname']); + if (!isset($connection->user->uid)) { + return $response->close([ + 'msg' => '您登录的客服用户不存在' + ]); + } + /** @var StoreServiceRecordServices $service */ + $service = app()->make(StoreServiceRecordServices::class); + $service->updateRecord(['to_uid' => $connection->user->uid], ['online' => 1]); + /** @var StoreServiceServices $service */ + $service = app()->make(StoreServiceServices::class); + $service->update(['uid' => $connection->user->uid], ['online' => 1]); + $this->service->setKefuUser($connection); + + return $response->success(); + } + + /** + * 用户登录 + * @param TcpConnection $connection + * @param array $res + * @param Response $response + * @return bool|null + */ + public function login(TcpConnection &$connection, array $res, Response $response) + { + if (!isset($res['data']) || !$token = $res['data']) { + return $response->close([ + 'msg' => '授权失败!' + ]); + } + + try { + /** @var UserAuthServices $services */ + $services = app()->make(UserAuthServices::class); + $authInfo = $services->parseToken($token); + } catch (AuthException $e) { + return $response->close([ + 'msg' => $e->getMessage() + ]); + } + + $connection->user = $authInfo['user']; + $connection->tokenData = $authInfo['tokenData']; + $this->service->setUser($connection); + + /** @var StoreServiceRecordServices $service */ + $service = app()->make(StoreServiceRecordServices::class); + $service->updateRecord(['to_uid' => $connection->user->uid], ['online' => 1, 'type' => $res['form_type'] ?? 1]); + $connections = $this->service->kefuUser(); + foreach ($connections as &$conn) { + if (!isset($conn->onlineUids) || !in_array($connection->user->uid, $conn->onlineUids ?? [])) { + $response->connection($conn)->send('user_online', ['to_uid' => $connection->user->uid, 'online' => 1]); + } + if (!isset($conn->onlineUids)) { + $conn->onlineUids = []; + } + array_push($conn->onlineUids, $connection->user->uid); + $this->service->setKefuUser($conn, false); + } + + return $response->connection($connection)->success(); + } + + /** + * + * @param TcpConnection $connection + * @param array $res + * @param Response $response + */ + public function to_chat(TcpConnection &$connection, array $res, Response $response) + { + $tourist_uid = $res['data']['tourist_uid'] ?? 0; + if ($tourist_uid) { + $connection->isTourist = true; + $connection->user = (object)['uid' => $tourist_uid]; + $connections = $this->service->user(); + if (!isset($connections[$tourist_uid])) { + $this->service->setUser($connection); + } + } + $connection->chatToUid = $res['data']['id'] ?? 0; + if (isset($connection->user)) { + $uid = $connection->user->uid; + if ($connection->chatToUid && !isset($connection->isTourist)) { + /** @var StoreServiceRecordServices $service */ + $service = app()->make(StoreServiceRecordServices::class); + $service->update(['user_id' => $uid, 'to_uid' => $connection->chatToUid], ['mssage_num' => 0]); + /** @var StoreServiceLogServices $logServices */ + $logServices = app()->make(StoreServiceLogServices::class); + $logServices->update(['uid' => $connection->chatToUid, 'to_uid' => $uid], ['type' => 1]); + } + $response->send('mssage_num', ['uid' => $connection->chatToUid, 'num' => 0, 'recored' => (object)[]]); + } + } + + /** + * 用户向客服发送消息 + * @param TcpConnection $connection + * @param array $res + * @param Response $response + * @return bool|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function chat(TcpConnection &$connection, array $res, Response $response) + { + $to_uid = $res['data']['to_uid'] ?? 0; + $msn_type = $res['data']['type'] ?? 0; + $msn = $res['data']['msn'] ?? ''; + $formType = $res['form_type'] ?? 0; + //是否为游客 + $isTourist = $res['data']['is_tourist'] ?? 0; + $tourist_uid = $res['data']['tourist_uid'] ?? 0; + $isTourist = $isTourist && $tourist_uid; + $tourist_avatar = $res['data']['tourist_avatar'] ?? ''; + $uid = $isTourist ? $tourist_uid : $connection->user->uid; + if (!$to_uid) { + return $response->send('err_tip', ['msg' => '用户不存在']); + } + if ($to_uid == $uid) { + return $response->send('err_tip', ['msg' => '不能和自己聊天']); + } + /** @var StoreServiceLogServices $logServices */ + $logServices = app()->make(StoreServiceLogServices::class); + if (!in_array($msn_type, $logServices::MSN_TYPE)) { + return $response->send('err_tip', ['msg' => '格式错误']); + } + $msn = trim(strip_tags(str_replace(["\n", "\t", "\r", " "], '', htmlspecialchars_decode($msn)))); + $data = compact('to_uid', 'msn_type', 'msn', 'uid'); + $data['add_time'] = time(); + $data['is_tourist'] = $res['data']['is_tourist'] ?? 0; + $connections = $this->service->user(); + $online = isset($connections[$to_uid]) && isset($connections[$to_uid]->chatToUid) && $connections[$to_uid]->chatToUid == $uid; + $data['type'] = $online ? 1 : 0; + $data = $logServices->save($data); + $data = $data->toArray(); + $data['_add_time'] = $data['add_time']; + $data['add_time'] = strtotime($data['add_time']); + if (!$isTourist) { + if (isset($this->service->kefuUser()[$data['uid']])) { + /** @var StoreServiceServices $userService */ + $userService = app()->make(StoreServiceServices::class); + $_userInfo = $userService->get(['uid' => $data['uid']], ['nickname', 'avatar']); + } else { + /** @var UserServices $userService */ + $userService = app()->make(UserServices::class); + $_userInfo = $userService->getUserInfo($data['uid'], 'nickname,avatar'); + } + $data['nickname'] = $_userInfo['nickname']; + $data['avatar'] = $_userInfo['avatar']; + } else { + $avatar = sys_config('tourist_avatar'); + $_userInfo['avatar'] = $tourist_avatar ?: Arr::getArrayRandKey(is_array($avatar) ? $avatar : []); + $_userInfo['nickname'] = '游客' . $uid; + $data['nickname'] = $_userInfo['nickname']; + $data['avatar'] = $_userInfo['avatar']; + } + + //商品消息类型 + $data['productInfo'] = []; + if ($msn_type == StoreServiceLogServices::MSN_TYPE_GOODS && $msn) { + /** @var StoreProductServices $productServices */ + $productServices = app()->make(StoreProductServices::class); + $productInfo = $productServices->getProductInfo((int)$msn, 'store_name,IFNULL(sales,0) + IFNULL(ficti,0) as sales,image,slider_image,price,vip_price,ot_price,stock,id'); + $data['productInfo'] = $productInfo ? $productInfo->toArray() : []; + } + //订单消息类型 + $data['orderInfo'] = []; + if ($msn_type == StoreServiceLogServices::MSN_TYPE_ORDER && $msn) { + /** @var StoreOrderServices $orderServices */ + $orderServices = app()->make(StoreOrderServices::class); + $order = $orderServices->getUserOrderDetail($msn, $uid); + if ($order) { + $order = $orderServices->tidyOrder($order->toArray(), true, true); + $order['add_time_y'] = date('Y-m-d', $order['add_time']); + $order['add_time_h'] = date('H:i:s', $order['add_time']); + $data['orderInfo'] = $order; + } + } + //给自己回复消息 + $response->send('chat', $data); + + //用户向客服发送消息,判断当前客服是否在登录中 + /** @var StoreServiceRecordServices $serviceRecored */ + $serviceRecored = app()->make(StoreServiceRecordServices::class); + $unMessagesCount = $logServices->getMessageNum(['uid' => $uid, 'to_uid' => $to_uid, 'type' => 0, 'is_tourist' => $isTourist ? 1 : 0]); + //记录当前用户和他人聊天记录 + $data['recored'] = $serviceRecored->saveRecord($uid, $to_uid, $msn, $formType ?? 0, $msn_type, $unMessagesCount, $isTourist, $data['nickname'], $data['avatar']); + //是否在线 + if ($online) { + $response->connection($this->service->user()[$to_uid])->send('reply', $data); + } else { + //用户在线,可是没有和当前用户进行聊天,给当前用户发送未读条数 + if (isset($connections[$to_uid])) { + $data['recored']['nickname'] = $_userInfo['nickname']; + $data['recored']['avatar'] = $_userInfo['avatar']; + $response->connection($this->service->user()[$to_uid])->send('mssage_num', [ + 'uid' => $uid, + 'num' => $unMessagesCount, + 'recored' => $data['recored'] + ]); + } + if ($isTourist) { + return true; + } + //用户不在线 + /** @var WechatUserServices $wechatUserServices */ + $wechatUserServices = app()->make(WechatUserServices::class); + $userInfo = $wechatUserServices->getOne(['uid' => $to_uid, 'user_type' => 'wechat'], 'nickname,subscribe,openid,headimgurl'); + if ($userInfo && $userInfo['subscribe'] && $userInfo['openid']) { + $description = '您有新的消息,请注意查收!'; + if ($formType) { + $head = '客服接待消息提醒'; + $url = sys_config('site_url') . '/kefu/mobile_chat?toUid=' . $uid . '&nickname=' . $_userInfo['nickname']; + } else { + $head = '客服回复消息提醒'; + $url = sys_config('site_url') . '/pages/extension/customer_list/chat?uid=' . $uid; + } + $message = WechatService::newsMessage($head, $description, $url, $_userInfo['avatar']); + $userInfo = $userInfo->toArray(); + try { + WechatService::staffService()->message($message)->to($userInfo['openid'])->send(); + } catch (\Exception $e) { + + Log::error($userInfo['nickname'] . '发送失败' . $e->getMessage()); + } + } + } + } + + /** + * 上下线 + * @param TcpConnection $connection + * @param array $res + * @param Response $response + */ + public function online(TcpConnection &$connection, array $res, Response $response) + { + $online = $res['data']['online'] ?? 0; + $connections = $this->service->user(); + if (isset($connection->user->uid)) { + $uids = $connection->user->uid; + /** @var StoreServiceServices $service */ + $service = app()->make(StoreServiceServices::class); + $service->update(['uid' => $uids], ['online' => $online]); + //广播给正在和自己聊天的用户 + foreach ($connections as $uid => $conn) { + if ($uid !== $uids && $uids == ($conn->chatToUid ?? 0)) { + $response->connection($conn)->send('online', ['online' => $online, 'uid' => $uids]); + } + } + } + } + + /** + * 客服转接 + * @param TcpConnection $connection + * @param array $res + * @param Response $response + */ + public function transfer(TcpConnection &$connection, array $res, Response $response) + { + $data = $res['data'] ?? []; + $uid = $data['recored']['uid'] ?? 0; + if ($uid && $this->service->user($uid)) { + $data['recored']['online'] = 1; + } else { + $data['recored']['online'] = 0; + } + $response->send('transfer', $data); + } +} diff --git a/demo/thinkphp/backend/phoenix/services/workerman/chat/ChatService.php b/demo/thinkphp/backend/phoenix/services/workerman/chat/ChatService.php new file mode 100644 index 0000000000000000000000000000000000000000..4df194535fe9f2e1e1107f0695f7774883f0906c --- /dev/null +++ b/demo/thinkphp/backend/phoenix/services/workerman/chat/ChatService.php @@ -0,0 +1,204 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\services\workerman\chat; + + +use app\services\kefu\service\StoreServiceRecordServices; +use app\services\kefu\service\StoreServiceServices; +use Channel\Client; +use phoenix\services\workerman\ChannelService; +use phoenix\services\workerman\Response; +use Workerman\Connection\TcpConnection; +use Workerman\Lib\Timer; +use Workerman\Worker; + +/** + * + * + * @author GQL + * @since 1.0 + */ +class ChatService +{ + /** + * @var Worker + */ + protected $worker; + + /** + * @var TcpConnection[] + */ + protected $connections = []; + + /** + * @var TcpConnection[] + */ + protected $user = []; + + /** + * 在线客服 + * @var TcpConnection[] + */ + protected $kefuUser = []; + + /** + * @var ChatHandle + */ + protected $handle; + + /** + * @var Response + */ + protected $response; + + /** + * @var int + */ + protected $timer; + + public function __construct(Worker $worker) + { + $this->worker = $worker; + $this->handle = new ChatHandle($this); + $this->response = new Response(); + } + + public function setUser(TcpConnection $connection) + { + $this->user[$connection->user->uid] = $connection; + } + + /** + * 获得当前在线客服 + * @return TcpConnection[] + */ + public function kefuUser() + { + return $this->kefuUser; + } + + /** + * 设置当前在线客服 + * @param TcpConnection $connection + */ + public function setKefuUser(TcpConnection $connection, bool $isUser = true) + { + $this->kefuUser[$connection->kefuUser->uid] = $connection; + if ($isUser) { + $this->user[$connection->user->uid] = $connection; + } + } + + public function user($key = null) + { + return $key ? ($this->user[$key] ?? false) : $this->user; + } + + public function onConnect(TcpConnection $connection) + { + $this->connections[$connection->id] = $connection; + $connection->lastMessageTime = time(); + } + + public function onMessage(TcpConnection $connection, $res) + { + $connection->lastMessageTime = time(); + $res = json_decode($res, true); + if (!$res || !isset($res['type']) || !$res['type'] || $res['type'] == 'ping') { + return $this->response->connection($connection)->success('ping', ['now' => time()]); + } + if (!method_exists($this->handle, $res['type'])) return; + try { + $this->handle->{$res['type']}($connection, $res + ['data' => []], $this->response->connection($connection)); + } catch (\Throwable $e) { + } + } + + + public function onWorkerStart(Worker $worker) + { + ChannelService::connet(); + + Client::on('crmeb_chat', function ($eventData) use ($worker) { + if (!isset($eventData['type']) || !$eventData['type']) return; + $ids = isset($eventData['ids']) && count($eventData['ids']) ? $eventData['ids'] : array_keys($this->user); + $fun = $eventData['fun'] ?? false; + foreach ($ids as $id) { + if (isset($this->user[$id])) { + if ($fun) { + $this->handle->{$eventData['type']}($this->user[$id], $eventData + ['data' => []], $this->response->connection($this->user[$id])); + } else { + $this->response->connection($this->user[$id])->success($eventData['type'], $eventData['data'] ?? null); + } + } + } + }); + + $this->timer = Timer::add(15, function () use (&$worker) { + $time_now = time(); + foreach ($worker->connections as $connection) { + if ($time_now - $connection->lastMessageTime > 12) { + //定时器判断当前用户是否下线 + if (isset($connection->user->uid) && !isset($connection->user->isTourist)) { + /** @var StoreServiceRecordServices $service */ + $service = app()->make(StoreServiceRecordServices::class); + $service->updateRecord(['to_uid' => $connection->user->uid], ['online' => 0]); + } + $this->response->connection($connection)->close('timeout'); + //广播给客服谁下线了 + foreach ($this->kefuUser as $uid => &$conn) { + if (isset($connection->user->uid) && $connection->user->uid != $uid) { + if (isset($conn->onlineUids) && ($key = array_search($connection->user->uid, $conn->onlineUids)) !== false) { + unset($conn->onlineUids[$key]); + } + $this->response->connection($conn)->send('user_online', ['to_uid' => $connection->user->uid, 'online' => 0]); + } + } + } + } + }); + + Timer::add(2, function () use (&$worker) { + $uids = []; + foreach ($this->user() as $uid => $connection) { + if (!isset($connection->isTourist)) { + $uids[] = $uid; + } + } + if ($uids) { + //除了当前在线的其他全部都下线 + /** @var StoreServiceRecordServices $service */ + $service = app()->make(StoreServiceRecordServices::class); + $service->updateOnline(['notUid' => $uids], ['online' => 0]); + } + $kefuUid = array_keys($this->kefuUser()); + if ($kefuUid) { + /** @var StoreServiceServices $kefuService */ + $kefuService = app()->make(StoreServiceServices::class); + $kefuService->updateOnline(['notUid' => $kefuUid], ['online' => 0]); + } + }); + } + + + public function onClose(TcpConnection $connection) + { + var_dump('close'); + unset($this->connections[$connection->id]); + if (isset($connection->user->uid)) { + unset($this->user[$connection->user->uid]); + } + if (isset($connection->kefuUser->uid)) { + unset($this->kefuUser[$connection->kefuUser->uid]); + } + } +} diff --git a/demo/thinkphp/backend/phoenix/traits/JwtAuthModelTrait.php b/demo/thinkphp/backend/phoenix/traits/JwtAuthModelTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..5f6eff8b1a9b09c2fad799107a40831d4a904afa --- /dev/null +++ b/demo/thinkphp/backend/phoenix/traits/JwtAuthModelTrait.php @@ -0,0 +1,68 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\traits; + + +use Firebase\JWT\BeforeValidException; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\JWT; +use Firebase\JWT\SignatureInvalidException; +use think\facade\Env; +use UnexpectedValueException; + +trait JwtAuthModelTrait +{ + /** + * @param string $type + * @param array $params + * @return array + */ + public function getToken(string $type, array $params = []): array + { + $id = $this->{$this->getPk()}; + $host = app()->request->host(); + $time = time(); + + $params += [ + 'iss' => $host, + 'aud' => $host, + 'iat' => $time, + 'nbf' => $time, + 'exp' => strtotime('+30 days'), + ]; + $params['jti'] = compact('id', 'type'); + $token = JWT::encode($params, Env::get('app.app_key', 'default')); + + return compact('token', 'params'); + } + + /** + * @param string $jwt + * @return array + * + * @throws UnexpectedValueException Provided JWT was invalid + * @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed + * @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf' + * @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat' + * @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim + * + */ + public static function parseToken(string $jwt): array + { + JWT::$leeway = 60; + + $data = JWT::decode($jwt, Env::get('app.app_key', 'default'), array('HS256')); + + $model = new self(); + return [$model->where($model->getPk(), $data->jti->id)->find(), $data->jti->type]; + } +} diff --git a/demo/thinkphp/backend/phoenix/traits/ModelTrait.php b/demo/thinkphp/backend/phoenix/traits/ModelTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..9cbaa0f5392211768907321b630b69236f6ef4b5 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/traits/ModelTrait.php @@ -0,0 +1,121 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\traits; + +use think\Model; + +/** + * Trait ModelTrait + * @package crmeb\traits + */ +trait ModelTrait +{ + /** + * 时间段搜索器 + * + * @param Model $query + * @param $value + * @param $data + */ + public function searchTimeAttr($query, $value, $data): void + { + if ($value) { + $timeKey = $data['timeKey'] ?? 'create_time'; + if (is_array($value)) { + $startTime = $value[0] ?? 0; + $endTime = $value[1] ?? 0; + if ($startTime || $endTime) { + if ($startTime == $endTime || $endTime == strtotime(date('Y-m-d', $endTime))) { + $endTime = $endTime + 86400; + } + $query->whereBetween($timeKey, [$startTime, $endTime]); + } + } elseif (is_string($value)) { + switch ($value) { + case 'today': + case 'week': + case 'month': + case 'year': + case 'yesterday': + case 'last year': + case 'last week': + case 'last month': + $query->whereTime($timeKey, $value); + break; + case 'quarter': + [$startTime, $endTime] = $this->getMonth(); + $query->whereBetween($timeKey, [strtotime($startTime), strtotime($endTime)]); + break; + case 'lately7': + $query->whereBetween($timeKey, [strtotime("-7 day"), time()]); + break; + case 'lately30': + $query->whereBetween($timeKey, [strtotime("-30 day"), time()]); + break; + default: + if (strstr($value, '-') !== false) { + [$startTime, $endTime] = explode('-', $value); + $startTime = trim($startTime) ? strtotime($startTime) : 0; + $endTime = trim($endTime) ? strtotime($endTime) : 0; + if ($startTime && $endTime) { + if ($startTime == $endTime || $endTime == strtotime(date('Y-m-d', $endTime))) { + $endTime = $endTime + 86400; + } + $query->whereBetween($timeKey, [$startTime, $endTime]); + } else if (!$startTime && $endTime) { + $query->whereTime($timeKey, '<', $endTime + 86400); + } else if ($startTime && !$endTime) { + $query->whereTime($timeKey, '>=', $startTime); + } + } + break; + } + } + } + } + + /** + * 获取本季度 time + * @param int $ceil + * @return array + */ + public function getMonth(int $ceil = 0) + { + if ($ceil != 0) { + $season = ceil(date('n') / 3) - $ceil; + } else { + $season = ceil(date('n') / 3); + } + $firstday = date('Y-m-01', mktime(0, 0, 0, ($season - 1) * 3 + 1, 1, date('Y'))); + $lastday = date('Y-m-t', mktime(0, 0, 0, $season * 3, 1, date('Y'))); + return [$firstday, $lastday]; + } + + /** + * 获取某个字段内的值 + * @param $value + * @param string $filed + * @param string $valueKey + * @param array|string[] $where + * @return mixed + */ + public function getFieldValue($value, string $filed, ?string $valueKey = '', ?array $where = []) + { + $model = $this->where($filed, $value); + if ($where) { + $model->where(...$where); + } + return $model->value($valueKey ?: $filed); + } + + +} diff --git a/demo/thinkphp/backend/phoenix/traits/QueueTrait.php b/demo/thinkphp/backend/phoenix/traits/QueueTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..7062404f1b3c18529f1b44856a640e6c939f1abc --- /dev/null +++ b/demo/thinkphp/backend/phoenix/traits/QueueTrait.php @@ -0,0 +1,91 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\traits; + +use phoenix\utils\Queue; + + +/** + * 快捷加入消息队列 + * @author Mr.April + * @since 1.0 + */ +trait QueueTrait +{ + /** + * 列名 + * @return null + */ + protected static function queueName() + { + return null; + } + + /** + * 加入队列 + * @param $action + * @param array $data + * @param string|null $queueName + * @return mixed + */ + public static function dispatch($action, array $data = [], string $queueName = null) + { + if (sys_config('queue_open', 1) == 1) { + $queue = Queue::instance()->job(__CLASS__); + if (is_array($action)) { + $queue->data(...$action); + } else if (is_string($action)) { + $queue->do($action)->data(...$data); + } + if ($queueName) { + $queue->setQueueName($queueName); + } else if (static::queueName()) { + $queue->setQueueName(static::queueName()); + } + return $queue->push(); + } else { + $className = '\\' . __CLASS__; + $res = new $className(); + if (is_array($action)) { + $res->doJob(...$action); + } else { + $res->$action(...$data); + } + } + } + + /** + * 延迟加入消息队列 + * @param int $secs + * @param $action + * @param array $data + * @param string|null $queueName + * @return mixed + */ + public static function dispatchSecs(int $secs, $action, array $data = [], string $queueName = null): mixed + { + if (sys_config('queue_open', 1) == 1) { + $queue = Queue::instance()->job(__CLASS__)->secs($secs); + if (is_array($action)) { + $queue->data(...$action); + } else if (is_string($action)) { + $queue->do($action)->data(...$data); + } + if ($queueName) { + $queue->setQueueName($queueName); + } else if (static::queueName()) { + $queue->setQueueName(static::queueName()); + } + return $queue->push(); + } + } +} diff --git a/demo/thinkphp/backend/phoenix/traits/ServicesTrait.php b/demo/thinkphp/backend/phoenix/traits/ServicesTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..e250f59f3b7504aa98f19ef0849d57eca2d5fda4 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/traits/ServicesTrait.php @@ -0,0 +1,32 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\utils; + +/** + * 操作数组帮助类 + * Class Arr + * + * @package crmeb\utils + */ +class Arr +{ + /** + * 对数组增加默认值 + * + * @param array $keys + * @param array $configList + * + * @return array + */ + public static function getDefaultValue(array $keys, array $configList = []) + { + $value = []; + foreach ($keys as $val) { + if (is_array($val)) { + $k = $val[0] ?? ''; + $v = $val[1] ?? ''; + } else { + $k = $val; + $v = ''; + } + $value[$k] = $configList[$k] ?? $v; + } + return $value; + } + + /** + * 获取layui菜单列表 + * + * @param array|object $data + * + * @return array + */ + public static function getMenuLayuiViewList(array|object $data): array + { + return Arr::toLayuiUi($data); + } + + /** + * 转化layuiUi需要的key值 + * + * @param array|object $rules + * @param int $type + * @param null $setKeysById + * + * @return array + */ + public static function toLayuiUi(array|object $rules, int $type = 1, $setKeysById = null): array + { + $retMenu = []; //返回值(也是顶层menu) + static $tmpMenu = []; // 按id为key的menu 解决作用域问题静态处理 + foreach ($rules as $r) { + if ($type === 1 && $r['auth_type'] !== 1) { + //api + continue; + } + if ($r['is_show'] !== 1) { //是否显示 + continue; + } + + //制作菜单: + if (!isset($tmpMenu[$r['id']])) { //如果还不存在,则创建 + $tmpMenu[$r['id']] = ['type' => 1]; + } + $tmpMenu[$r['id']]['id'] = $r['id']; + $tmpMenu[$r['id']]['title'] = $r['menu_name']; + $tmpMenu[$r['id']]['icon'] = 'layui-icon ' . $r['icon']; +// $tmpMenu[$r['id']]['openType'] = "_iframe"; + $tmpMenu[$r['id']]['openType'] = "_component";//1._component 2._iframe 3._blank 4._layer + $tmpMenu[$r['id']]['href'] = $r['menu_path']; + + //加入额外的keys + if ($setKeysById) { + //如果这个id在给定的Id列表内 + if (in_array($r['id'], $setKeysById[0])) { + $tmpMenu[$r['id']][$setKeysById[1]] = $setKeysById[2]; //给特定key赋值 + } + } + + if ($r['pid'] === '-1') { //顶层 + $retMenu[] = &$tmpMenu[$r['id']]; + continue; + } + if (!isset($tmpMenu[$r['pid']])) { //子菜单 + $tmpMenu[$r['pid']] = ['children' => []]; //创建父菜单 + } elseif (!isset($tmpMenu[$r['pid']]['children'])) { + $tmpMenu[$r['pid']]['children'] = []; + } + $tmpMenu[$r['pid']]['type'] = 0; //菜单 + $tmpMenu[$r['pid']]['children'][] = &$tmpMenu[$r['id']]; //加入父菜单 children + } + + return $retMenu; + } + + /** + * 获取树型菜单 + * + * @param $data + * @param int $pid + * @param int $level + * + * @return array + */ + public static function getTree($data, $pid = 0, $level = 1) + { + $childs = self::getChild($data, $pid, $level); + $dataSort = array_column($childs, 'sort'); + array_multisort($dataSort, SORT_DESC, $childs); + foreach ($childs as $key => $navItem) { + $resChild = self::getTree($data, $navItem['id']); + if (null != $resChild) { + $childs[$key]['children'] = $resChild; + } + } + return $childs; + } + + /** + * 递归数据 + * + * @param array $data + * @param int|string $pid + * @param string $field1 + * @param string $field2 + * @param string $field3 + * + * @return array + */ + public static function tree(array $data, int|string $pid = 0, string $field1 = 'id', string $field2 = 'pid', string $field3 = 'children'): array + { + $arr = []; + foreach ($data as $k => $v) { + if ($v[$field2] == $pid) { + $v[$field3] = self::tree($data, $v[$field1], $field1, $field2, $field3); + $arr[] = $v; + } + } + return $arr; + } + + /** + * 获取子菜单 + * + * @param $arr + * @param $id + * @param $lev + * + * @return array + */ + private static function getChild(&$arr, $id, $lev) + { + $child = []; + foreach ($arr as $value) { + if ($value['pid'] == $id) { + $value['level'] = $lev; + $child[] = $value; + } + } + return $child; + } + + /** + * 格式化数据 + * + * @param array $array + * @param $value + * @param int $default + * + * @return mixed + */ + public static function setValeTime(array $array, $value, $default = 0) + { + foreach ($array as $item) { + if (!isset($value[$item])) + $value[$item] = $default; + else if (is_string($value[$item])) + $value[$item] = (float)$value[$item]; + } + return $value; + } + + /** + * 获取二维数组中某个值的集合重新组成数组,并判断数组中的每一项是否为真 + * + * @param array $data + * @param string $filed + * + * @return array + */ + public static function getArrayFilterValeu(array $data, string $filed) + { + return array_filter(array_unique(array_column($data, $filed)), function ($item) { + if ($item) { + return $item; + } + }); + } + + /** + * 数组转字符串去重复 + * + * @param array $data + * + * @return false|string[] + */ + public static function unique(array $data) + { + return array_unique(explode(',', implode(',', $data))); + } + + /** + * 获取数组中去重复过后的指定key值 + * + * @param array $list + * @param string $key + * + * @return array + */ + public static function getUniqueKey(array $list, string $key) + { + return array_unique(array_column($list, $key)); + } + + /** + * 获取数组中随机值 + * + * @param array $data + * + * @return bool|mixed + */ + public static function getArrayRandKey(array $data) + { + if (!$data) { + return false; + } + $mun = rand(0, count($data)); + if (!isset($data[$mun])) { + return self::getArrayRandKey($data); + } + return $data[$mun]; + } + + /** + * 选出列字符串 + * + * @param array $array + * @param string $key + * @param string $index + * + * @return string + */ + public static function extractStr(array $array, string $key, string $index): string + { + $names = []; + foreach ($array as $item) { + if (isset($item[$key][$index])) { + $names[] = $item[$key][$index]; + } + } + return implode(',', $names); + } + + /** + * 多个一维索引型数组合并并去重 + * + * @param ...$arrays + * + * @return array + */ + public static function mergeAndUniqueArrays(...$arrays): array + { + $mergedArray = array_merge(...$arrays); + return array_values(array_unique($mergedArray)); + } + + /** + * 多维数组去重并重置KEY + * + * @param $array + * + * @return array + */ + public static function uniqueArrayValues(&$array): array + { + $result = array(); + foreach ($array as $key => $value) { + if (is_array($value)) { + $value = self::uniqueArrayValues($value); + } + if (is_array($value) && count($value) > 0) { + $value = array_values($value); + } + if (!in_array($value, $result)) { + $result[$key] = $value; + } + } + return $result; + } +} diff --git a/demo/thinkphp/backend/phoenix/utils/Cache.php b/demo/thinkphp/backend/phoenix/utils/Cache.php new file mode 100644 index 0000000000000000000000000000000000000000..f5ec6ed6771ace560a802d78e9d5c2559ce58459 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/Cache.php @@ -0,0 +1,155 @@ + + * +---------------------------------------------------------------------- + */ + +namespace phoenix\utils; + + +use think\cache\TagSet; +use think\facade\Cache as ThinkCache; + +/** + * Class Cache + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/8 + * @package crmeb\utils + */ +class Cache +{ + + protected $key; + + /** + * @var string + */ + protected string $origin = 'phoenix'; + + /** + * Cache constructor. + * @param string $key + */ + public function __construct(string $key) + { + $this->key = $key; + } + + /** + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/8 + */ + public function getTagName() + { + return $this->origin . ':t:' . $this->key; + } + + /** + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/8 + */ + public function getValueName() + { + return $this->origin . ':v:' . $this->key; + } + + /** + * @return TagSet + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/8 + */ + protected function tag() + { + return ThinkCache::tag($this->getTagName()); + } + + /** + * @param string $name + * @param $value + * @param null $expire + * @return mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/8 + */ + public function remember(string $name, $value, $expire = null) + { + return $this->tag()->remember($this->getValueName() . ':' . $name, $value, $expire); + } + + /** + * @param $name + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/8 + */ + public function delete($name): bool + { + return ThinkCache::delete($this->getValueName() . ':' . $name); + } + + /** + * @param $name + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/8 + */ + public function has($name): bool + { + return ThinkCache::has($this->getValueName() . ':' . $name); + } + + /** + * @param $name + * @param null $default + * @return mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/8 + */ + public function get($name, $default = null) + { + return ThinkCache::get($this->getValueName() . ':' . $name, $default); + } + + /** + * @param $name + * @param $value + * @param null $expire + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/8 + */ + public function set($name, $value, $expire = null) + { + return $this->tag()->set($this->getValueName() . ':' . $name, $value, $expire); + } + + /** + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/8 + */ + public function clear() + { + return $this->tag()->clear(); + } + +} diff --git a/demo/thinkphp/backend/phoenix/utils/Canvas.php b/demo/thinkphp/backend/phoenix/utils/Canvas.php new file mode 100644 index 0000000000000000000000000000000000000000..09a3bd49d0d76ce33df876fb451d477b26df79f6 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/Canvas.php @@ -0,0 +1,324 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\utils; + + +/** + * Class Canvas + * @package crmeb\utils + * @method $this setFileName(string $fileName) 设置文件名 + * @method $this setPath(string $path) 设置存放路径 + * @method $this setImageType(string $imageType) 设置图片类型 + * @method $this setBackgroundHeight(int $backgroundHeight) 设置背景高 + * @method $this setBackgroundWidth(int $backgroundWidth) 设置背景宽 + * @method $this setFontSize(int $fontSize) 设置字体大小 + * @method $this setFontColor($fontColor) 设置字体颜色 + * @method $this setFontLeft(int $fontLeft) 设置字体距离左侧位置 + * @method $this setFontTop(int $fontTop) 设置字体距离顶部位置 + * @method $this setFontText(string $fontText) 设置文字 + * @method $this setFontPath(string $fontPath) 设置字体文件路径 + * @method $this setFontAngle(int $fontAngle) 设置字体角度 + * @method $this setImageUrl(string $imageUrl) 设置图片路径 + * @method $this setImageLeft(int $imageLeft) 设置图片距离左侧位置 + * @method $this setImageTop(int $imageTop) 设置图片距离顶部位置 + * @method $this setImageRight(int $imageRight) 设置图片距离左侧位置 + * @method $this setImageStream(bool $imageStream) 设置图片是否未流文件 + * @method $this setImageBottom(int $imageBottom) 设置图片距离底部位置 + * @method $this setImageWidth(int $imageWidth) 设置图片宽 + * @method $this setImageHeight(int $imageHeight) 设置图片高 + * @method $this setImageOpacity(int $imageOpacity) 设置图片透明度 + */ +class Canvas +{ + + const FONT = 'statics/font/Alibaba-PuHuiTi-Regular.otf'; + + /** + * 背景宽 + * @var int + */ + protected $backgroundWidth = 600; + + /** + * 背景高 + * @var int + */ + protected $backgroundHeight = 1000; + + /** + * 图片类型 + * @var string + */ + protected $imageType = 'jpeg'; + + /** + * 保存地址 + * @var string + */ + protected $path = 'uploads/routine/'; + + /** + * 文件名 + * @var string + */ + protected $fileName; + + /** + * 规则 + * @var array + */ + protected $propsRule = ['fileName', 'path', 'imageType', 'backgroundHeight', 'backgroundWidth']; + + /** + * 字体数据集 + * @var array + */ + protected $fontValue = []; + + /** + * 字体默认可设置vlaue + * @var array + */ + protected $defaultFontValue = [ + 'fontSize' => 0, + 'fontColor' => '231,180,52', + 'fontLeft' => 0, + 'fontTop' => 0, + 'fontText' => '', + 'fontPath' => self::FONT, + 'fontAngle' => 0, + ]; + + protected $defaultFont; + /** + * 图片数据集 + * @var array + */ + protected $imageValue = []; + + /** + * 图片可设置属性 + * @var array + */ + protected $defaultImageValue = [ + 'imageUrl' => '', + 'imageLeft' => 0, + 'imageTop' => 0, + 'imageRight' => 0, + 'imageBottom' => 0, + 'imageWidth' => 0, + 'imageHeight' => 0, + 'imageOpacity' => 0, + 'imageStream' => false, + ]; + + /** + * 实例化本身 + * @var self + */ + protected static $instance; + + protected $defaultImage; + + protected function __construct() + { + $this->defaultImage = $this->defaultImageValue; + $this->defaultFont = $this->defaultFontValue; + } + + /** + * 实例化本类 + * @return Canvas + */ + public static function instance() + { + if (is_null(self::$instance)) { + self::$instance = new self(); + } + return self::$instance; + } + + /** + * 创建一个新图象 + * @param string $file + * @return array + */ + public function createFrom(string $file): array + { + $file = str_replace('https', 'http', $file); + $imagesize = getimagesize($file); + $type = image_type_to_extension($imagesize[2], true); + $canvas = NULL; + switch ($type) { + case '.png': + $canvas = imagecreatefrompng($file); + break; + case '.jpg': + case '.jpeg': + $canvas = imagecreatefromjpeg($file); + break; + case '.gif': + $canvas = imagecreatefromgif($file); + break; + } + return [$canvas, $imagesize]; + + } + + /** + * 放入字体 + * @return $this + */ + public function pushFontValue() + { + array_push($this->fontValue, $this->defaultFontValue); + $this->defaultFontValue = $this->defaultFont; + return $this; + } + + /** + * 放入图片 + * @return $this + */ + public function pushImageValue() + { + array_push($this->imageValue, $this->defaultImageValue); + $this->defaultImageValue = $this->defaultImage; + return $this; + } + + /** + * 创建背景 + * @param int $w + * @param int $h + * @return false|resource + */ + public function createTrueColor(int $w = 0, int $h = 0) + { + return imagecreatetruecolor($w ?: $this->backgroundWidth, $h ?: $this->backgroundHeight); + } + + + /** + * 开始画图 + * @param bool $force 生成错误时是否抛出异常 + * @return string + * @throws \Exception + */ + public function starDrawChart(bool $force = false): string + { + try { + $image = $this->createTrueColor(); + + foreach ($this->imageValue as $item) { + if ($item['imageUrl']) { + if ($item['imageStream']) { + $res = getimagesizefromstring($item['imageUrl']); + $mer = imagecreatefromstring($item['imageUrl']); + } else { + [$mer, $res] = $this->createFrom($item['imageUrl']); + } + if ($mer && $res) { + $scrW = $res[0] ?? 0; + $scrH = $res[1] ?? 0; + $imageWidth = $item['imageWidth'] ?: $scrW; + $imageHeight = $item['imageHeight'] ?: $scrH; + imagecopyresampled($image, $mer, $item['imageLeft'], $item['imageTop'], $item['imageRight'], $item['imageBottom'], $imageWidth, $imageHeight, $scrW, $scrH); + unset($scrW, $scrH, $imageWidth, $imageHeight, $res, $mer); + } + + } + } + + foreach ($this->fontValue as $val) { + if (!is_array($val['fontColor'])) + $fontColor = explode(',', $val['fontColor']); + else + $fontColor = $val['fontColor']; + if (count($fontColor) < 3) + throw new \RuntimeException('fontColor Separation of thousand bits'); + [$r, $g, $b] = $fontColor; + $fontColor = imagecolorallocate($image, $r, $g, $b); + $val['fontLeft'] = $val['fontLeft'] < 0 ? $this->backgroundWidth - abs($val['fontLeft']) : $val['fontLeft']; + $val['fontTop'] = $val['fontTop'] < 0 ? $this->backgroundHeight - abs($val['fontTop']) : $val['fontTop']; + imagettftext($image, $val['fontSize'], $val['fontAngle'], $val['fontLeft'], $val['fontTop'], $fontColor, $val['fontPath'], $val['fontText']); + unset($r, $g, $b, $fontColor); + } + if (is_null($this->fileName)) { + $this->fileName = md5(time()); + } + + $strlen = stripos($this->path, 'uploads'); + $path = $this->path; + if ($strlen !== false) { + $path = substr($this->path, 8); + } + make_path($path, 4, true); + + $save_file = $this->path . $this->fileName . '.' . $this->imageType; + switch ($this->imageType) { + case 'jpeg': + case 'jpg': + imagejpeg($image, public_path().$save_file, 70); + break; + case 'png': + imagepng($image, public_path().$save_file, 70); + break; + case 'gif': + imagegif($image, public_path().$save_file, 70); + break; + default: + throw new \RuntimeException('Incorrect type set:' . $this->imageType); + } + imagedestroy($image); + + return $save_file; + } catch (\Throwable $e) { + if ($force || $e instanceof \RuntimeException) + throw new \Exception($e->getMessage()); + return ''; + } + } + + /** + * Magic access.. + * + * @param $method + * @param $args + * @return $this + */ + public function __call($method, $args): self + { + + if (0 === stripos($method, 'set') && strlen($method) > 3) { + $method = lcfirst(substr($method, 3)); + } + + $imageValueKes = array_keys($this->defaultImageValue); + $fontValueKes = array_keys($this->defaultFontValue); + + if (in_array($method, $imageValueKes)) { + $this->defaultImageValue[$method] = array_shift($args); + } + + if (in_array($method, $fontValueKes)) { + $this->defaultFontValue[$method] = array_shift($args); + } + + if (in_array($method, $this->propsRule)) { + $this->{$method} = array_shift($args); + } + + return $this; + } + + +} diff --git a/demo/thinkphp/backend/phoenix/utils/Captcha.php b/demo/thinkphp/backend/phoenix/utils/Captcha.php new file mode 100644 index 0000000000000000000000000000000000000000..3b39695778b3ab8e0b4fc584137a03038083ab55 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/Captcha.php @@ -0,0 +1,322 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\utils; + +use think\facade\Cache; +use think\facade\Config; +use think\Response; + +/** + * Class Captcha + * + * @package crmeb\utils + */ +class Captcha +{ + // 验证码图片实例 + private ?object $im = null; + // 验证码字体颜色 + private null|string $color = null; + // 验证码字符集合 + protected string $codeSet = '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY'; + // 验证码过期时间(s) + protected int $expire = 1800; + // 使用中文验证码 + protected bool $useZh = false; + // 中文验证码字符串 + protected string $zhSet = '们以我到他会作时要动国产的一是工就年阶义发成部民可出能方进在了不和有大这主中人上为来分生对于学下级地个用同行面说种过命度革而多子后自社加小机也经力线本电高量长党得实家定深法表着水理化争现所二起政三好十战无农使性前等反体合斗路图把结第里正新开论之物从当两些还天资事队批点育重其思与间内去因件日利相由压员气业代全组数果期导平各基或月毛然如应形想制心样干都向变关问比展那它最及外没看治提五解系林者米群头意只明四道马认次文通但条较克又公孔领军流入接席位情运器并飞原油放立题质指建区验活众很教决特此常石强极土少已根共直团统式转别造切九你取西持总料连任志观调七么山程百报更见必真保热委手改管处己将修支识病象几先老光专什六型具示复安带每东增则完风回南广劳轮科北打积车计给节做务被整联步类集号列温装即毫知轴研单色坚据速防史拉世设达尔场织历花受求传口断况采精金界品判参层止边清至万确究书术状厂须离再目海交权且儿青才证低越际八试规斯近注办布门铁需走议县兵固除般引齿千胜细影济白格效置推空配刀叶率述今选养德话查差半敌始片施响收华觉备名红续均药标记难存测士身紧液派准斤角降维板许破述技消底床田势端感往神便贺村构照容非搞亚磨族火段算适讲按值美态黄易彪服早班麦削信排台声该击素张密害侯草何树肥继右属市严径螺检左页抗苏显苦英快称坏移约巴材省黑武培著河帝仅针怎植京助升王眼她抓含苗副杂普谈围食射源例致酸旧却充足短划剂宣环落首尺波承粉践府鱼随考刻靠够满夫失包住促枝局菌杆周护岩师举曲春元超负砂封换太模贫减阳扬江析亩木言球朝医校古呢稻宋听唯输滑站另卫字鼓刚写刘微略范供阿块某功套友限项余倒卷创律雨让骨远帮初皮播优占死毒圈伟季训控激找叫云互跟裂粮粒母练塞钢顶策双留误础吸阻故寸盾晚丝女散焊功株亲院冷彻弹错散商视艺灭版烈零室轻血倍缺厘泵察绝富城冲喷壤简否柱李望盘磁雄似困巩益洲脱投送奴侧润盖挥距触星松送获兴独官混纪依未突架宽冬章湿偏纹吃执阀矿寨责熟稳夺硬价努翻奇甲预职评读背协损棉侵灰虽矛厚罗泥辟告卵箱掌氧恩爱停曾溶营终纲孟钱待尽俄缩沙退陈讨奋械载胞幼哪剥迫旋征槽倒握担仍呀鲜吧卡粗介钻逐弱脚怕盐末阴丰雾冠丙街莱贝辐肠付吉渗瑞惊顿挤秒悬姆烂森糖圣凹陶词迟蚕亿矩康遵牧遭幅园腔订香肉弟屋敏恢忘编印蜂急拿扩伤飞露核缘游振操央伍域甚迅辉异序免纸夜乡久隶缸夹念兰映沟乙吗儒杀汽磷艰晶插埃燃欢铁补咱芽永瓦倾阵碳演威附牙芽永瓦斜灌欧献顺猪洋腐请透司危括脉宜笑若尾束壮暴企菜穗楚汉愈绿拖牛份染既秋遍锻玉夏疗尖殖井费州访吹荣铜沿替滚客召旱悟刺脑措贯藏敢令隙炉壳硫煤迎铸粘探临薄旬善福纵择礼愿伏残雷延烟句纯渐耕跑泽慢栽鲁赤繁境潮横掉锥希池败船假亮谓托伙哲怀割摆贡呈劲财仪沉炼麻罪祖息车穿货销齐鼠抽画饲龙库守筑房歌寒喜哥洗蚀废纳腹乎录镜妇恶脂庄擦险赞钟摇典柄辩竹谷卖乱虚桥奥伯赶垂途额壁网截野遗静谋弄挂课镇妄盛耐援扎虑键归符庆聚绕摩忙舞遇索顾胶羊湖钉仁音迹碎伸灯避泛亡答勇频皇柳哈揭甘诺概宪浓岛袭谁洪谢炮浇斑讯懂灵蛋闭孩释乳巨徒私银伊景坦累匀霉杜乐勒隔弯绩招绍胡呼痛峰零柴簧午跳居尚丁秦稍追梁折耗碱殊岗挖氏刃剧堆赫荷胸衡勤膜篇登驻案刊秧缓凸役剪川雪链渔啦脸户洛孢勃盟买杨宗焦赛旗滤硅炭股坐蒸凝竟陷枪黎救冒暗洞犯筒您宋弧爆谬涂味津臂障褐陆啊健尊豆拔莫抵桑坡缝警挑污冰柬嘴啥饭塑寄赵喊垫丹渡耳刨虎笔稀昆浪萨茶滴浅拥穴覆伦娘吨浸袖珠雌妈紫戏塔锤震岁貌洁剖牢锋疑霸闪埔猛诉刷狠忽灾闹乔唐漏闻沈熔氯荒茎男凡抢像浆旁玻亦忠唱蒙予纷捕锁尤乘乌智淡允叛畜俘摸锈扫毕璃宝芯爷鉴秘净蒋钙肩腾枯抛轨堂拌爸循诱祝励肯酒绳穷塘燥泡袋朗喂铝软渠颗惯贸粪综墙趋彼届墨碍启逆卸航衣孙龄岭骗休借'; + // 使用背景图片 + protected bool $useImgBg = false; + // 验证码字体大小(px) + protected int $fontSize = 25; + // 是否画混淆曲线 + protected bool $useCurve = false; + // 是否添加杂点 + protected bool $useNoise = true; + // 验证码图片高度 + protected int $imageH = 0; + // 验证码图片宽度 + protected int $imageW = 0; + // 验证码位数 + protected int $length = 4; + // 验证码字体,不设置随机获取 + protected string $fontttf = ''; + // 背景颜色 + protected array $bg = [243, 251, 254]; + //算术验证码 + protected bool $math = false; + + //验证码 + protected $generator; + + /** + * 架构方法 设置参数 + * Captcha constructor. + * + * @param array $config + */ + public function __construct(array $config = []) + { + $this->length = $config['length'] ?? Config::get('captcha.length', $this->length); + $this->imageW = $config['imageW'] ?? $this->imageW; + $this->imageH = $config['imageH'] ?? $this->imageH; + $this->useCurve = $config['useCurve'] ?? $this->useCurve; + $this->fontSize = $config['fontSize'] ?? $this->fontSize; + $this->useImgBg = $config['useImgBg'] ?? $this->useImgBg; + $this->useZh = $config['useZh'] ?? $this->useZh; + $this->expire = $config['expire'] ?? $this->expire; + $this->math = $config['math'] ?? $this->math; + $this->zhSet = $config['zhSet'] ?? $this->zhSet; + $this->codeSet = $config['codeSet'] ?? $this->codeSet; + } + + /** + * 创建验证码 + * + * @return array + * @throws Exception|\Exception + */ + public function generate(): array + { + $bag = ''; + + if ($this->math) { + $this->useZh = false; + + $x = random_int(10, 30); + $y = random_int(1, 9); + $bag = "{$x} + {$y} = "; + $key = $x + $y; + $key .= ''; + } else { + if ($this->useZh) { + $characters = preg_split('/(?zhSet); + } else { + $characters = str_split($this->codeSet); + } + + for ($i = 0; $i < $this->length; $i++) { + $bag .= $characters[rand(0, count($characters) - 1)]; + } + + $key = mb_strtolower($bag, 'UTF-8'); + } + + $hash = password_hash($key, PASSWORD_BCRYPT, ['cost' => 10]); + + $generator = [ + 'value' => $bag, + 'key' => $hash, + ]; + Cache::set('captcha_' . $key, $generator, $this->expire); + return $generator; + } + + /** + * 验证验证码是否正确 + * + * @access public + * + * @param string $code 用户验证码 + * + * @return bool 用户验证码是否正确 + */ + public function check(string $code): bool + { + $code = mb_strtolower(trim($code), 'UTF-8'); + $name = 'captcha_' . $code; + if (!Cache::has($name) || !($generator = Cache::get($name))) { + return false; + } + $key = $generator['key'] ?? ''; + $res = password_verify($code, $key); + + if ($res) { + Cache::delete($name); + } + + return $res; + } + + /** + * 输出验证码 + * + * @param array|null $generator + * + * @return \think\Response + * @throws \Exception + */ + public function create(array $generator = null): Response + { + if (!$generator) { + $generator = $this->generate(); + } + // 图片宽(px) + $this->imageW || $this->imageW = $this->length * $this->fontSize * 1.5 + $this->length * $this->fontSize / 2; + // 图片高(px) + $this->imageH || $this->imageH = $this->fontSize * 2.5; + // 建立一幅 $this->imageW x $this->imageH 的图像 + $this->im = imagecreate($this->imageW, $this->imageH); + // 设置背景 + imagecolorallocate($this->im, $this->bg[0], $this->bg[1], $this->bg[2]); + + // 验证码字体随机颜色 + $this->color = imagecolorallocate($this->im, mt_rand(1, 150), mt_rand(1, 150), mt_rand(1, 150)); + + //TODO 待测试 + // 验证码使用随机字体 + $ttfPath = dirname(app()->getThinkPath(), 2) . DS . 'think-captcha' . DS . 'assets/' . ($this->useZh ? 'zhttfs' : 'ttfs') . '/'; + if (empty($this->fontttf)) { + $dir = dir($ttfPath); + $ttfs = []; + while (false !== ($file = $dir->read())) { + if ('.' != $file[0] && substr($file, -4) == '.ttf') { + $ttfs[] = $file; + } + } + $dir->close(); + $this->fontttf = $ttfs[array_rand($ttfs)]; + } + + $fontttf = $ttfPath . $this->fontttf; + + if ($this->useImgBg) { + $this->background(); + } + + if ($this->useNoise) { + // 绘杂点 + $this->writeNoise(); + } + if ($this->useCurve) { + // 绘干扰线 + $this->writeCurve(); + } + // 绘验证码 + $text = $this->useZh ? preg_split('/(? $char) { + + $x = $this->fontSize * ($index + 1) * mt_rand(1.2, 1.6) * ($this->math ? 1 : 1.5); + $y = $this->fontSize + mt_rand(10, 20); + $angle = $this->math ? 0 : mt_rand(-40, 40); + + imagettftext($this->im, $this->fontSize, $angle, $x, $y, $this->color, $fontttf, $char); + } + ob_start(); + // 输出图像 + imagepng($this->im); + $content = ob_get_clean(); + imagedestroy($this->im); + $img = "data:image/png;base64," . base64_encode($content); + return json(['img' => $img, 'key' => $generator['key'],'value'=>$generator['value']]); +// return response($content, 200, ['Content-Length' => strlen($content)])->contentType('image/png'); + } + + /** + * 画一条由两条连在一起构成的随机正弦函数曲线作干扰线(你可以改成更帅的曲线函数) + * 高中的数学公式咋都忘了涅,写出来 + * 正弦型函数解析式:y=Asin(ωx+φ)+b + * 各常数值对函数图像的影响: + * A:决定峰值(即纵向拉伸压缩的倍数) + * b:表示波形在Y轴的位置关系或纵向移动距离(上加下减) + * φ:决定波形与X轴位置关系或横向移动距离(左加右减) + * ω:决定周期(最小正周期T=2π/∣ω∣) + */ + protected function writeCurve(): void + { + $px = $py = 0; + + // 曲线前部分 + $A = mt_rand(1, $this->imageH / 2); // 振幅 + $b = mt_rand(-$this->imageH / 4, $this->imageH / 4); // Y轴方向偏移量 + $f = mt_rand(-$this->imageH / 4, $this->imageH / 4); // X轴方向偏移量 + $T = mt_rand($this->imageH, $this->imageW * 2); // 周期 + $w = (2 * M_PI) / $T; + + $px1 = 0; // 曲线横坐标起始位置 + $px2 = mt_rand($this->imageW / 2, $this->imageW * 0.8); // 曲线横坐标结束位置 + + for ($px = $px1; $px <= $px2; $px = $px + 1) { + if (0 != $w) { + $py = $A * sin($w * $px + $f) + $b + $this->imageH / 2; // y = Asin(ωx+φ) + b + $i = (int)($this->fontSize / 5); + while ($i > 0) { + imagesetpixel($this->im, $px + $i, $py + $i, $this->color); // 这里(while)循环画像素点比imagettftext和imagestring用字体大小一次画出(不用这while循环)性能要好很多 + $i--; + } + } + } + + // 曲线后部分 + $A = mt_rand(1, $this->imageH / 2); // 振幅 + $f = mt_rand(-$this->imageH / 4, $this->imageH / 4); // X轴方向偏移量 + $T = mt_rand($this->imageH, $this->imageW * 2); // 周期 + $w = (2 * M_PI) / $T; + $b = $py - $A * sin($w * $px + $f) - $this->imageH / 2; + $px1 = $px2; + $px2 = $this->imageW; + + for ($px = $px1; $px <= $px2; $px = $px + 1) { + if (0 != $w) { + $py = $A * sin($w * $px + $f) + $b + $this->imageH / 2; // y = Asin(ωx+φ) + b + $i = (int)($this->fontSize / 5); + while ($i > 0) { + imagesetpixel($this->im, $px + $i, $py + $i, $this->color); + $i--; + } + } + } + } + + /** + * 画杂点 + * 往图片上写不同颜色的字母或数字 + */ + protected function writeNoise(): void + { + $codeSet = '2345678abcdefhijkmnpqrstuvwxyz'; + for ($i = 0; $i < 10; $i++) { + //杂点颜色 + $noiseColor = imagecolorallocate($this->im, mt_rand(150, 225), mt_rand(150, 225), mt_rand(150, 225)); + for ($j = 0; $j < 5; $j++) { + // 绘杂点 + imagestring($this->im, 5, mt_rand(-10, $this->imageW), mt_rand(-10, $this->imageH), $codeSet[mt_rand(0, 29)], $noiseColor); + } + } + } + + /** + * 绘制背景图片 + * 注:如果验证码输出图片比较大,将占用比较多的系统资源 + */ + protected function background(): void + { + $path = dirname(app()->getThinkPath(), 2) . DS . 'think-captcha' . DS . '/assets/bgs/'; + $dir = dir($path); + + $bgs = []; + while (false !== ($file = $dir->read())) { + if ('.' != $file[0] && substr($file, -4) == '.jpg') { + $bgs[] = $path . $file; + } + } + $dir->close(); + + $gb = $bgs[array_rand($bgs)]; + + list($width, $height) = @getimagesize($gb); + // Resample + $bgImage = @imagecreatefromjpeg($gb); + @imagecopyresampled($this->im, $bgImage, 0, 0, 0, 0, $this->imageW, $this->imageH, $width, $height); + @imagedestroy($bgImage); + } +} diff --git a/demo/thinkphp/backend/phoenix/utils/DownloadImage.php b/demo/thinkphp/backend/phoenix/utils/DownloadImage.php new file mode 100644 index 0000000000000000000000000000000000000000..54671309063ce05521a60356850953a3e992a8cf --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/DownloadImage.php @@ -0,0 +1,145 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\utils; + + +use app\services\other\UploadService; +use crmeb\exceptions\AdminException; +use think\Image; + +/** + * 下载图片到本地 + * Class DownloadImage + * @package crmeb\utils + * @method $this thumb(bool $thumb) 是否生成缩略图 + * @method $this thumbWidth(int $thumbWidth) 缩略图宽度 + * @method $this thumHeight(int $thumHeight) 缩略图宽度 + * @method $this path(int $path) 存储位置 + */ +class DownloadImage +{ + //是否生成缩略图 + protected $thumb = false; + //缩略图宽度 + protected $thumbWidth = 300; + //缩略图高度 + protected $thumHeight = 300; + //存储位置 + protected $path = 'attach'; + + /** + * @var string[] + */ + protected $rules = ['thumb', 'thumbWidth', 'thumHeight', 'path']; + + /** + * 获取即将要下载的图片扩展名 + * @param string $url + * @param string $ex + * @return array|string[] + */ + public function getImageExtname($url = '', $ex = 'jpg') + { + $_empty = ['file_name' => '', 'ext_name' => $ex]; + if (!$url) return $_empty; + if (strpos($url, '?')) { + $_tarr = explode('?', $url); + $url = trim($_tarr[0]); + } + $arr = explode('.', $url); + if (!is_array($arr) || count($arr) <= 1) return $_empty; + $ext_name = trim($arr[count($arr) - 1]); + $ext_name = !$ext_name ? $ex : $ext_name; + return ['file_name' => md5($url) . '.' . $ext_name, 'ext_name' => $ext_name]; + } + + /** + * 下载图片 + * @param string $url + * @param string $name + * @param int $upload_type + * @return mixed + */ + public function downloadImage(string $url, $name = '') + { + if (!$name) { + //TODO 获取要下载的文件名称 + $downloadImageInfo = $this->getImageExtname($url); + $ext = $downloadImageInfo['ext_name']; + $name = $downloadImageInfo['file_name']; + if (!$name) throw new AdminException(400725); + } else { + $ext = $this->getImageExtname($name)['ext_name']; + } + if (in_array($ext, ['php', 'js', 'html'])) { + throw new AdminException(400558); + } + if (strstr($url, 'http://') === false && strstr($url, 'https://') === false) { + $url = 'http:' . $url; + } + $url = str_replace('https://', 'http://', $url); + if ($this->path == 'attach') { + $date_dir = date('Y') . DIRECTORY_SEPARATOR . date('m') . DIRECTORY_SEPARATOR . date('d'); + $to_path = $this->path . '/' . $date_dir; + } else { + $to_path = $this->path; + } + $upload = UploadService::init(1); + if (!file_exists($upload->uploadDir($to_path) . '/' . $name)) { + ob_start(); + readfile($url); + $content = ob_get_contents(); + ob_end_clean(); + $size = strlen(trim($content)); + if (!$content || $size <= 2) throw new AdminException(400726); + if ($upload->to($to_path)->down($content, $name) === false) { + throw new AdminException(400727); + } + $imageInfo = $upload->getDownloadInfo(); + $path = $imageInfo['dir']; + if ($this->thumb) { + Image::open(root_path() . 'public' . $path)->thumb($this->thumbWidth, $this->thumHeight)->save(root_path() . 'public' . $path); + $this->thumb = false; + } + } else { + $path = '/uploads/' . $to_path . '/' . $name; + $imageInfo['name'] = $name; + } + $date['path'] = $path; + $date['name'] = $imageInfo['name']; + $date['size'] = $imageInfo['size'] ?? ''; + $date['mime'] = $imageInfo['type'] ?? ''; + $date['image_type'] = 1; + $date['is_exists'] = false; + return $date; + } + + /** + * @param $name + * @param $arguments + * @return $this + */ + public function __call($name, $arguments) + { + if (in_array($name, $this->rules)) { + if ($name === 'path') { + $this->{$name} = $arguments[0] ?? 'attach'; + } else { + $this->{$name} = $arguments[0] ?? null; + } + return $this; + } else { + throw new \RuntimeException('Method does not exist' . __CLASS__ . '->' . $name . '()'); + } + } + +} diff --git a/demo/thinkphp/backend/phoenix/utils/Hook.php b/demo/thinkphp/backend/phoenix/utils/Hook.php new file mode 100644 index 0000000000000000000000000000000000000000..006706edf9fa90e9895cf31a28adf7f6be4fc639 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/Hook.php @@ -0,0 +1,68 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\utils; + +use think\helper\Str; + +/** + * + * Class Hook + * @package crmeb\utils + */ +class Hook +{ + /** + * 类名 + * @var string + */ + protected $namespace; + + /** + * 方法前缀 + * @var string + */ + protected $prefix; + + /** + * 构造方法 + * Hook constructor. + * @param string $namespace + * @param string|null $prefix + */ + public function __construct(string $namespace, string $prefix = null) + { + $this->namespace = $namespace; + if ($prefix) { + $this->prefix = $prefix; + } + } + + /** + * 执行挂载方法 + * @param string $hookName + * @param mixed ...$arguments + * @return bool + */ + public function listen(string $hookName, ...$arguments) + { + if (class_exists($this->namespace)) { + $handle = app()->make($this->namespace); + $hookName = Str::studly(($this->prefix ?: '') . ucfirst($hookName)); + if (method_exists($handle, $hookName)) { + try { + return call_user_func_array([$handle, $hookName], $arguments); + } catch (\Throwable $e) { + } + } + } + return false; + } +} diff --git a/demo/thinkphp/backend/phoenix/utils/Json.php b/demo/thinkphp/backend/phoenix/utils/Json.php new file mode 100644 index 0000000000000000000000000000000000000000..56abec504e47e62162aa26016e7da7744dd0538d --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/Json.php @@ -0,0 +1,76 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\utils; + +use think\Response; + +/** + * + * JSON输出类 + * @author Mr.April + * @since 1.0 + */ +class Json +{ + private int $code = 200; + + public function code(int $code): self + { + $this->code = $code; + return $this; + } + + public function make(int $status, string $msg, ?array $data = null, ?array $replace = []): Response + { + $res = compact('status', 'msg'); + + if (!is_null($data)) + $res['data'] = $data; + + if (is_numeric($res['msg'])) { + $res['code'] = $res['msg']; + $res['msg'] = getLang($res['msg'], $replace); + } + + return Response::create($res, 'json', $this->code); + } + + public function success($msg = 'success', ?array $data = null, ?array $replace = []): Response + { + if (is_array($msg)) { + $data = $msg; + $msg = 'success'; + } + + return $this->make(200, $msg, $data, $replace); + } + + public function fail($msg = 'fail', ?array $data = null, ?array $replace = []): Response + { + if (is_array($msg)) { + $data = $msg; + $msg = 'fail'; + } + + return $this->make(400, $msg, $data, $replace); + } + + public function status($status, $msg, $result = []) + { + $status = strtoupper($status); + if (is_array($msg)) { + $result = $msg; + $msg = 'success'; + } + return $this->success($msg, compact('status', 'result')); + } +} diff --git a/demo/thinkphp/backend/phoenix/utils/JwtAuth.php b/demo/thinkphp/backend/phoenix/utils/JwtAuth.php new file mode 100644 index 0000000000000000000000000000000000000000..3061f90f9ac3147405840c994742709e93887da6 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/JwtAuth.php @@ -0,0 +1,119 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\utils; + +use Firebase\JWT\Key; +use phoenix\services\CacheService; +use Firebase\JWT\JWT; +use phoenix\exceptions\AdminException; +use think\facade\Env; + + +/** + * + * JWT类 + * @author Mr.April + * @since 1.0 + */ +class JwtAuth +{ + + /** + * token + * + * @var string + */ + protected string $token; + + /** + * alg + * + * @var string + */ + protected string $algorithm = 'HS256'; + + /** + * 获取token + * + * @param int|string $id + * @param string $type + * @param array $params + * + * @return array + */ + public function getToken($id, string $type, array $params = []): array + { + $keyId = "keyId"; //这个东西必须要加上,不加上,报错,报错内容:'"kid" empty, unable to lookup correct key' + $host = app()->request->host(); + $time = time(); + $exp_time = strtotime('+ 30day'); + $params += [ + 'iss' => $host, + 'aud' => $host, + 'iat' => $time, + 'nbf' => $time, + 'exp' => $exp_time, + ]; + $params['jti'] = compact('id', 'type'); + $token = JWT::encode($params, Env::get('app.app_key', 'default'), $this->algorithm, $keyId); + return compact('token', 'params'); + } + + /** + * 解析token + * + * @param string $jwt + * + * @return array + */ + public function parseToken(string $jwt): array + { + $this->token = $jwt; + list($headb64, $bodyb64, $cryptob64) = explode('.', $this->token); + $payload = JWT::jsonDecode(JWT::urlsafeB64Decode($bodyb64)); + return [$payload->jti->id, $payload->jti->type, $payload->pwd ?? '',$payload->exp]; + } + + /** + * 验证token + */ + public function verifyToken(): void + { + JWT::$leeway = 60; + JWT::decode($this->token, new Key(Env::get('app.app_key', 'default'), $this->algorithm)); + } + + /** + * 获取token并放入令牌桶 + * + * @param $id + * @param string $type + * @param array $params + * + * @return array + */ + public function createToken($id, string $type, array $params = []): array + { + $tokenInfo = $this->getToken($id, $type, $params); + $exp = $tokenInfo['params']['exp'] - $tokenInfo['params']['iat'] + 60; + $info = [ + 'uid' => $id, + 'token' => $tokenInfo['token'], + 'exp' => $exp, + ]; + $res = CacheService::set(md5($tokenInfo['token']), $info, (int)$exp, $type); + if (!$res) { + throw new AdminException(10023); + } + return $tokenInfo; + } +} diff --git a/demo/thinkphp/backend/phoenix/utils/Queue.php b/demo/thinkphp/backend/phoenix/utils/Queue.php new file mode 100644 index 0000000000000000000000000000000000000000..7c78a93444de0e36457ad5f7bedaafce3746a465 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/Queue.php @@ -0,0 +1,252 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\utils; + +use think\facade\Config; +use think\facade\Queue as QueueThink; +use think\facade\Log; + +/** + * Class Queue + * + * @package crmeb\utils + * @method $this do(string $do) 设置任务执行方法 + * @method $this job(string $job) 设置任务执行类名 + * @method $this errorCount(int $errorCount) 执行失败次数 + * @method $this data(...$data) 执行数据 + * @method $this secs(int $secs) 延迟执行秒数 + * @method $this log($log) 记录日志 + */ +class Queue +{ + + /** + * 错误信息 + * + * @var string + */ + protected string $error; + + /** + * 设置错误信息 + * + * @param string|null $error + * + * @return bool + */ + protected function setError(?string $error = null): bool + { + $this->error = $error ?: '未知错误'; + return false; + } + + /** + * 获取错误信息 + * + * @return string + */ + public function getError(): string + { + $error = $this->error; + $this->error = null; + return $error; + } + + /** + * 任务执行 + * + * @var string + */ + protected string $do = 'doJob'; + + /** + * 默认任务执行方法名 + * + * @var string + */ + protected string $defaultDo; + + /** + * 任务类名 + * + * @var string + */ + protected string $job; + + /** + * 错误次数 + * + * @var int + */ + protected int $errorCount = 3; + + /** + * 数据 + * + * @var array|string + */ + protected string|array $data; + + /** + * 队列名 + * + * @var null + */ + protected $queueName = null; + + /** + * 延迟执行秒数 + * + * @var int + */ + protected int $secs = 0; + + /** + * 记录日志 + * + * @var string|callable|array + */ + protected $log; + + /** + * @var array + */ + protected array $rules = ['do', 'data', 'errorCount', 'job', 'secs', 'log']; + + /** + * @var static + */ + protected static ?Queue $instance; + + /** + * Queue constructor. + */ + protected function __construct() + { + $this->defaultDo = $this->do; + } + + /** + * @return static + */ + public static function instance() + { + + if (!isset(self::$instance)) { + self::$instance = new static(); + } + return self::$instance; + } + + /** + * 设置列名 + * + * @param string $queueName + * + * @return $this + */ + public function setQueueName(string $queueName): static + { + $this->queueName = $queueName; + return $this; + } + + /** + * 放入消息队列 + * + * @param array|null $data + * + * @return mixed + */ + public function push(?array $data = null): mixed + { + if (!$this->job) { + return $this->setError('需要执行的队列类必须存在'); + } + $jodValue = $this->getValues($data); + $res = QueueThink::{$this->action()}(...$jodValue); + if (!$res) { + $res = QueueThink::{$this->action()}(...$jodValue); + if (!$res) { + Log::error('加入队列失败,参数:' . json_encode($this->getValues($data))); + } + } + $this->clean(); + return $res; + } + + /** + * 清除数据 + */ + public function clean(): void + { + $this->secs = 0; + $this->data = []; + $this->log = null; + $this->queueName = null; + $this->errorCount = 3; + $this->do = $this->defaultDo; + } + + /** + * 获取任务方式 + * + * @return string + */ + protected function action(): string + { + return $this->secs ? 'later' : 'push'; + } + + /** + * 获取参数 + * + * @param $data + * + * @return array + */ + protected function getValues($data): array + { + $jobData['data'] = $data ?: $this->data; + $jobData['do'] = $this->do; + $jobData['errorCount'] = $this->errorCount; + $jobData['log'] = $this->log; + if ($this->do != $this->defaultDo) { + $this->job .= '@' . Config::get('queue.prefix', 'phoenix_') . $this->do; + } + if ($this->secs) { + return [$this->secs, $this->job, $jobData, $this->queueName]; + } else { + return [$this->job, $jobData, $this->queueName]; + } + } + + /** + * @param $name + * @param $arguments + * + * @return $this + */ + public function __call($name, $arguments) + { + if (in_array($name, $this->rules)) { + if ($name === 'data') { + $this->{$name} = $arguments; + } else { + $this->{$name} = $arguments[0] ?? null; + } + return $this; + } else { + throw new \RuntimeException('Method does not exist' . __CLASS__ . '->' . $name . '()'); + } + } +} diff --git a/demo/thinkphp/backend/phoenix/utils/Rsa.php b/demo/thinkphp/backend/phoenix/utils/Rsa.php new file mode 100644 index 0000000000000000000000000000000000000000..8a164328849cd49cf33da4173c64ab95e9905330 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/Rsa.php @@ -0,0 +1,200 @@ + + * +---------------------------------------------------------------------- + */ + +namespace phoenix\utils; + +use think\exception\ValidateException; + +/** + * Class Rsa + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/16 + * @package crmeb\utils + */ +class Rsa +{ + /** + * @var string + */ + protected $publicKey; + + /** + * @var string + */ + protected $privateKey; + + /** + * @var string + */ + protected $basePath; + + /** + * 获取证书文件 + * @param $publicKey + * @param $privateKey + */ + public function __construct(string $publicKey = 'cert_public_password.key', string $privateKey = 'cert_private_password.key') + { + $this->basePath = app()->getRootPath(); + if ($publicKey) { + $this->publicKey = $this->basePath . $publicKey; + } + if ($privateKey) { + $this->privateKey = $this->basePath . $publicKey; + } + if (!is_file($this->publicKey) || !is_file($this->privateKey)) { + $this->exportOpenSSLFile(); + } + } + + /** + * @return false|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/16 + */ + public function getPublicKey() + { + if (!is_file($this->publicKey)) { + $this->exportOpenSSLFile(); + } + + return file_get_contents($this->publicKey); + } + + /** + * 生成证书 + * @return bool + */ + public function exportOpenSSLFile($passwork = null) + { + + $publicKey = $privateKey = ''; + $dir = app()->getRootPath() . 'runtime/conf'; + $conf = 'openssl.cnf'; + if (!is_dir($dir)) { + mkdir($dir, 0700); + } + if (!file_exists($conf)) { + touch($dir . '/' . $conf); + } + + //参数设置 + $config = [ + "digest_alg" => "sha256", + //字节数 512 1024 2048 4096 等 + "private_key_bits" => 1024, + "config" => $dir . '/' . $conf, + //加密类型 + "private_key_type" => OPENSSL_KEYTYPE_RSA, + ]; + + //创建私钥和公钥 + $res = openssl_pkey_new($config); + if ($res == false) { + //创建失败,请检查openssl.cnf文件是否存在 + return false; + } + + //将密钥导出为PEM编码的字符串,并输出(通过引用传递)。 + openssl_pkey_export($res, $privateKey, $passwork, $config); + $publicKey = openssl_pkey_get_details($res); + $publicKey = $publicKey["key"]; + + //生成证书 + $createPublicFileRet = file_put_contents($this->publicKey, $publicKey); + $createPrivateFileRet = file_put_contents($this->privateKey, $privateKey); + if (!($createPublicFileRet || $createPrivateFileRet)) { + return false; + } + + openssl_free_key($res); + return true; + } + + /** + * 数据加密 + * @param string $data + * @param string|null $passwork + * @return false|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/16 + */ + function privateEncrypt(string $data, string $passwork = null) + { + $encrypted = ''; + $pi_key = openssl_pkey_get_private(file_get_contents($this->privateKey), $passwork);//这个函数可用来判断私钥是否是可用的,可用返回资源id Resource id + //最大允许加密长度为117,得分段加密 + $plainData = str_split($data, 100);//生成密钥位数 1024 bit key + foreach ($plainData as $chunk) { + $partialEncrypted = ''; + $encryptionOk = openssl_private_encrypt($chunk, $partialEncrypted, $pi_key);//私钥加密 + if ($encryptionOk === false) { + return false; + } + $encrypted .= $partialEncrypted; + } + + $encrypted = base64_encode($encrypted);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的 + return $encrypted; + } + + /** + * RSA公钥解密(私钥加密的内容通过公钥可以解密出来) + * @param string $public_key 公钥 + * @param string $data 私钥加密后的字符串 + * @return string $decrypted 返回解密后的字符串 + * @author mosishu + */ + function publicDecrypt(string $data) + { + $decrypted = ''; + $pu_key = openssl_pkey_get_public(file_get_contents($this->publicKey));//这个函数可用来判断公钥是否是可用的 + $plainData = str_split(base64_decode($data), 128);//生成密钥位数 1024 bit key + foreach ($plainData as $chunk) { + $str = ''; + $decryptionOk = openssl_public_decrypt($chunk, $str, $pu_key);//公钥解密 + if ($decryptionOk === false) { + return false; + } + $decrypted .= $str; + } + return $decrypted; + } + + /** + * 私钥解密 + * @param string $data + * @return mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/16 + */ + public function privateDecrypt(string $data) + { + if (!is_file($this->privateKey)) { + $this->exportOpenSSLFile(); + } + + $res = openssl_private_decrypt(base64_decode($data), $decryptedData, file_get_contents($this->privateKey)); + + if (false === $res) { + throw new ValidateException('RSA:解密失败'); + } + + return $decryptedData; + } + +} diff --git a/demo/thinkphp/backend/phoenix/utils/Str.php b/demo/thinkphp/backend/phoenix/utils/Str.php new file mode 100644 index 0000000000000000000000000000000000000000..0e899b00c53271f8c1a2d7784dc52e5cbdf04754 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/Str.php @@ -0,0 +1,80 @@ + +// +---------------------------------------------------------------------- + +namespace phoenix\utils; + +use Ramsey\Uuid\Uuid; + +/** + * + * 字符串操作帮助类 + * @author Mr.April + * @since 1.0 + */ +class Str +{ + /** + * @param string $action + * @param string $controller + * @param string $module + * @param $route + * + * @return string + */ + public static function getAuthName(string $action, string $controller, string $module, $route): string + { + return strtolower($module . '/' . $controller . '/' . $action . '/' . self::paramStr($route)); + } + + /** + * @param $params + * + * @return string + */ + public static function paramStr($params): string + { + if (!is_array($params)) $params = json_decode($params, true) ?: []; + $p = []; + foreach ($params as $key => $param) { + $p[] = $key; + $p[] = $param; + } + return implode('/', $p); + } + + /** + * 截取中文指定字节 + * + * @param string $str + * @param int $utf8len + * @param string $chaet + * @param string $file + * + * @return string + */ + public static function substrUTf8(string $str, int $utf8len = 100, string $chaet = 'UTF-8', string $file = '....'): string + { + if (mb_strlen($str, $chaet) > $utf8len) { + $str = mb_substr($str, 0, $utf8len, $chaet) . $file; + } + return $str; + } + + /** + * 生成字符串id + * + * @return string + */ + public static function uuid(): string + { + return Uuid::uuid4()->toString(); + } +} diff --git a/demo/thinkphp/backend/phoenix/utils/Terminal.php b/demo/thinkphp/backend/phoenix/utils/Terminal.php new file mode 100644 index 0000000000000000000000000000000000000000..e5853d0c888aa31c94d7060e04feeb8e51039ca4 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/Terminal.php @@ -0,0 +1,208 @@ + + * +---------------------------------------------------------------------- + */ + +namespace phoenix\utils; + +use think\Response; +use think\console\Output; + +/** + * 执行命令 + * Class Terminal + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + * @package crmeb\utils + */ +class Terminal +{ + /** + * 命令 + * @var \string[][] + */ + protected $command = [ + 'npm-build' => [ + 'run_root' => '', + 'command' => 'npm run build', + ], + 'npm-install' => [ + 'run_root' => '', + 'command' => 'npm run install', + ], + ]; + + /** + * 执行内容保存地址 + * @var string + */ + protected $outputFile; + + /** + * 执行状态 + * @var integer + */ + protected $procStatus; + + /** + * 响应内容 + * @var string + */ + protected $outputContent; + + /** + * @var + */ + protected $output; + + /** + * Terminal constructor. + */ + public function __construct() + { + $this->command['npm-build']['run_root'] = str_replace('DS', DS, config('app.admin_template_path')); + $this->command['npm-install']['run_root'] = str_replace('DS', DS, config('app.admin_template_path')); + + $outputDir = root_path() . 'runtime' . DIRECTORY_SEPARATOR . 'terminal'; + $this->outputFile = $outputDir . DIRECTORY_SEPARATOR . 'exec.log'; + if (!is_dir($outputDir)) { + mkdir($outputDir, 0755, true); + } + file_put_contents($this->outputFile, ''); + } + + /** + * @param Output $output + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + public function setOutput(Output $output) + { + $this->output = $output; + } + + /** + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + public function adminTemplatePath() + { + return $this->command['npm-install']['run_root']; + } + + /** + * 执行 + * @param string $name + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + public function run(string $name) + { + if (!function_exists('proc_open')) { + throw new \RuntimeException('缺少proc_open函数无法运行'); + } + + if (!isset($this->command[$name])) { + throw new \RuntimeException('运行的命令不存在'); + } + + $command = $this->command[$name]; + + $descriptorspec = [0 => ['pipe', 'r'], 1 => ['file', $this->outputFile, 'w'], 2 => ['file', $this->outputFile, 'w']]; + $process = proc_open($command['command'], $descriptorspec, $pipes, $command['run_root'], null, ['suppress_errors' => true]); + if (is_resource($process)) { + while ($this->getProcStatus($process)) { + $contents = file_get_contents($this->outputFile); + if (strlen($contents) && $this->outputContent != $contents) { + $newOutput = str_replace($this->outputContent, '', $contents); + if (preg_match('/\r\n|\r|\n/', $newOutput)) { + $this->echoOutputFlag($newOutput); + $this->outputContent = $contents; + } + } + usleep(500000); + } + foreach ($pipes as $pipe) { + fclose($pipe); + } + proc_close($process); + } + + return $this->output('run success'); + } + + /** + * 判断状态 + * @param $process + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + public function getProcStatus($process): bool + { + $status = proc_get_status($process); + if ($status['running']) { + $this->procStatus = 1; + return true; + } elseif ($this->procStatus === 1) { + $this->procStatus = 0; + $this->output('exit: ' . $status['exitcode']); + if ($status['exitcode'] === 0) { + $this->echoOutputFlag('success'); + } else { + $this->echoOutputFlag('error'); + } + return true; + } else { + return false; + } + } + + /** + * 直接输入响应 + * @param string $message + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + public function echoOutputFlag(string $message) + { + if ($this->output && $this->output instanceof Output) { + $this->output->info($message); + } else { + echo $this->output($message); + @ob_flush(); + } + } + + /** + * 返回响应内容 + * @param string $data + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + private function output($data) + { + $data = [ + 'message' => $data, + ]; + return Response::create($data, 'json')->getContent(); + } +} diff --git a/demo/thinkphp/backend/phoenix/utils/Translate.php b/demo/thinkphp/backend/phoenix/utils/Translate.php new file mode 100644 index 0000000000000000000000000000000000000000..c22afed478b5bea07e600bf29a53317f60d08be4 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/Translate.php @@ -0,0 +1,85 @@ + [ + "url" => "/", + "method" => "post", + "config" => [ + "query" => [ + "Action" => "LangDetect", + "Version" => "2020-06-01", + ], + ], + ], + "TranslateText" => [ + "url" => "/", + "method" => "post", + "config" => [ + "query" => [ + "Action" => "TranslateText", + "Version" => "2020-06-01", + ], + ], + ], + ]; + + protected function getConfig(string $region) + { + return [ +// "host" => "https://translate.volcengineapi.com", + "host" => "https://open.volcengineapi.com", + "config" => [ + "timeout" => 5.0, + "headers" => [ + "Accept" => "application/json", + ], + "v4_credentials" => [ + "region" => "cn-north-1", + "service" => "translate", + ], + ], + ]; + } + + public function langDetect(array $textList): array + { + $req = array('TextList' => $textList); + try { + $resp = $this->request('LangDetect', ['json' => $req]); + } catch (\Throwable $e) { + throw $e; + } + if ($resp->getStatusCode() != 200) { + throw new ApiException("failed to detect language: status_code=%d, resp=%s", $resp->getStatusCode(), $resp->getBody()); + } + return json_decode($resp->getBody()->getContents(), true)["DetectedLanguageList"]; + } + + public function translateText(string $sourceLanguage, string $targetLanguage, array $textList): array + { + $req = array('SourceLanguage' => $sourceLanguage, 'TargetLanguage' => $targetLanguage, 'TextList' => $textList); + try { + $resp = $this->request('TranslateText', ['json' => $req]); + } catch (\Throwable $e) { + throw $e; + } + if ($resp->getStatusCode() != 200) { + throw new ApiException("failed to translate: status_code=%d, resp=%s", $resp->getStatusCode(), $resp->getBody()); + } + return json_decode($resp->getBody()->getContents(), true)["TranslationList"]; + } +} diff --git a/demo/thinkphp/backend/phoenix/utils/fileVerification.php b/demo/thinkphp/backend/phoenix/utils/fileVerification.php new file mode 100644 index 0000000000000000000000000000000000000000..7abb8870514bea53b996ed9efbf883d732ea8634 --- /dev/null +++ b/demo/thinkphp/backend/phoenix/utils/fileVerification.php @@ -0,0 +1,76 @@ + +// +---------------------------------------------------------------------- +namespace phoenix\utils; + +use Exception; + +/** + * 签名计算 + * Class fileVerification + * @package crmeb\utils + */ +class fileVerification +{ + public $path = ""; + public $fileValue = ""; + + /** + * 项目路径 + * @param string $path + * @return string + * @throws Exception + */ + public function getSignature(string $path): string + { + if (!is_dir($path) && !is_file($path)) { + throw new Exception($path . " 不是有效的文件或目录!"); + } + + $appPath = $path . DS . 'app'; + if (!is_dir($appPath)) { + throw new Exception($appPath . " 不是有效的目录!"); + } + + $crmebPath = $path . DS . 'crmeb'; + if (!is_dir($crmebPath)) { + throw new Exception($crmebPath . " 不是有效的目录!"); + } + + $this->path = $appPath; + $this->getFileSignature($appPath); + $this->path = $crmebPath; + $this->getFileSignature($crmebPath); + return md5($this->fileValue); + } + + /** + * 计算签名 + * @param string $path + * @return void + * @throws Exception + */ + public function getFileSignature(string $path) + { + if (!is_dir($path)) { + $this->fileValue .= @md5_file($path); + } else { + if (!$dh = opendir($path)) throw new Exception($path . " File open failed!"); + while (($file = readdir($dh)) != false) { + if ($file == "." || $file == "..") { + continue; + } else { + $this->getFileSignature($path . DS . $file); + } + } + closedir($dh); + } + } +} diff --git a/demo/thinkphp/backend/public/.htaccess b/demo/thinkphp/backend/public/.htaccess new file mode 100644 index 0000000000000000000000000000000000000000..ee41fd6dc1636d6cd89c62540a86cf5bcc3c4c7c --- /dev/null +++ b/demo/thinkphp/backend/public/.htaccess @@ -0,0 +1,8 @@ + + Options +FollowSymlinks -Multiviews + RewriteEngine On + + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L] + \ No newline at end of file diff --git a/demo/thinkphp/backend/public/favicon.ico b/demo/thinkphp/backend/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3f2817f0665b40973f7004ea31b223e3a685c668 Binary files /dev/null and b/demo/thinkphp/backend/public/favicon.ico differ diff --git a/demo/thinkphp/backend/public/index.php b/demo/thinkphp/backend/public/index.php new file mode 100644 index 0000000000000000000000000000000000000000..96c252e49391638d8f503bd22f7cc9f35722e0b5 --- /dev/null +++ b/demo/thinkphp/backend/public/index.php @@ -0,0 +1,39 @@ + +// +---------------------------------------------------------------------- + +// [ 应用入口文件 ] +namespace think; + + +/* + * 不在tp加载后判断,为了安全的使用exit() + * 使用绝对路径,确保花里胡哨的url均能正确判定和跳转 + */ + +if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { + header("Access-Control-Allow-Credentials: true"); + header("Access-Control-Max-Age: 86400"); + header("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS"); + header("Access-Control-Allow-Headers: " . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']); + header("Access-Control-Allow-Origin: *"); +} + + +require __DIR__ . '/../vendor/autoload.php'; + +// 执行HTTP应用并响应 +$http = (new App())->http; + +$response = $http->run(); +// +$response->send(); + +$http->end($response); diff --git a/demo/thinkphp/backend/public/nginx.htaccess b/demo/thinkphp/backend/public/nginx.htaccess new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/demo/thinkphp/backend/public/router.php b/demo/thinkphp/backend/public/router.php new file mode 100644 index 0000000000000000000000000000000000000000..9b39a62c9771c00bd676713be4bb48f3a5cdc443 --- /dev/null +++ b/demo/thinkphp/backend/public/router.php @@ -0,0 +1,19 @@ + +// +---------------------------------------------------------------------- +// $Id$ + +if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) { + return false; +} else { + $_SERVER["SCRIPT_FILENAME"] = __DIR__ . '/index.php'; + + require __DIR__ . "/index.php"; +} diff --git a/demo/thinkphp/backend/public/static/.gitignore b/demo/thinkphp/backend/public/static/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c96a04f008ee21e260b28f7701595ed59e2839e3 --- /dev/null +++ b/demo/thinkphp/backend/public/static/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/demo/thinkphp/backend/public/uploads/attach/2024/03/20240311/1c526cd8d18bf6cab9de97bef8c505d2.png b/demo/thinkphp/backend/public/uploads/attach/2024/03/20240311/1c526cd8d18bf6cab9de97bef8c505d2.png new file mode 100644 index 0000000000000000000000000000000000000000..e5b3976ffda591775a4c643d605d826eaa9e14c5 Binary files /dev/null and b/demo/thinkphp/backend/public/uploads/attach/2024/03/20240311/1c526cd8d18bf6cab9de97bef8c505d2.png differ diff --git a/demo/thinkphp/backend/public/uploads/attach/2024/03/20240311/big_1c526cd8d18bf6cab9de97bef8c505d2.png b/demo/thinkphp/backend/public/uploads/attach/2024/03/20240311/big_1c526cd8d18bf6cab9de97bef8c505d2.png new file mode 100644 index 0000000000000000000000000000000000000000..50a87486616a3140cb7828086f45c777c57ae503 Binary files /dev/null and b/demo/thinkphp/backend/public/uploads/attach/2024/03/20240311/big_1c526cd8d18bf6cab9de97bef8c505d2.png differ diff --git a/demo/thinkphp/backend/public/uploads/attach/2024/03/20240311/mid_1c526cd8d18bf6cab9de97bef8c505d2.png b/demo/thinkphp/backend/public/uploads/attach/2024/03/20240311/mid_1c526cd8d18bf6cab9de97bef8c505d2.png new file mode 100644 index 0000000000000000000000000000000000000000..fc72a8eec636a6010bcac7ef4b599f9cf52285ff Binary files /dev/null and b/demo/thinkphp/backend/public/uploads/attach/2024/03/20240311/mid_1c526cd8d18bf6cab9de97bef8c505d2.png differ diff --git a/demo/thinkphp/backend/public/uploads/attach/2024/03/20240311/small_1c526cd8d18bf6cab9de97bef8c505d2.png b/demo/thinkphp/backend/public/uploads/attach/2024/03/20240311/small_1c526cd8d18bf6cab9de97bef8c505d2.png new file mode 100644 index 0000000000000000000000000000000000000000..fbf9620b8cac67f2f292f04cdccec7bdaccbbd48 Binary files /dev/null and b/demo/thinkphp/backend/public/uploads/attach/2024/03/20240311/small_1c526cd8d18bf6cab9de97bef8c505d2.png differ diff --git a/demo/thinkphp/backend/route/route.php b/demo/thinkphp/backend/route/route.php new file mode 100644 index 0000000000000000000000000000000000000000..c56c5bfe1920866d7ea880171d156c6329d28f0b --- /dev/null +++ b/demo/thinkphp/backend/route/route.php @@ -0,0 +1,24 @@ +pathinfo(); + + if ($appRequest === null) { + $appName = ''; + } else { + $appRequest = str_replace('//', '/', $appRequest); + $appName = explode('/', $appRequest)[0] ?? ''; + } + + switch (strtolower($appName)) { + case config('app.admin_prefix', 'admin'): + return view(app()->getRootPath() . 'public' . DS . config('app.admin_prefix', 'admin') . DS . 'index.html'); + break; + } + +}); diff --git a/demo/thinkphp/backend/think b/demo/thinkphp/backend/think new file mode 100644 index 0000000000000000000000000000000000000000..2429d223a2e44b29a52a721ae88d4085c0d274f3 --- /dev/null +++ b/demo/thinkphp/backend/think @@ -0,0 +1,10 @@ +#!/usr/bin/env php +console->run(); \ No newline at end of file diff --git a/demo/thinkphp/backend/workerman.bat b/demo/thinkphp/backend/workerman.bat new file mode 100644 index 0000000000000000000000000000000000000000..1ec56a48928982f3dd206df5d3c7833fd82e5f42 --- /dev/null +++ b/demo/thinkphp/backend/workerman.bat @@ -0,0 +1,10 @@ +chcp 65001 +start "Admin Serve" /b php think workerman start admin +start "Time Task" /b php think timer start +php think workerman start channel + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/.htaccess b/demo/thinkphp/frontend/layui_admin_flow/.htaccess new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/demo/thinkphp/frontend/layui_admin_flow/LICENSE b/demo/thinkphp/frontend/layui_admin_flow/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..2f283ae16ebc0ec888890433bf06b3fea362d626 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 就眠儀式 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/README.md b/demo/thinkphp/frontend/layui_admin_flow/README.md new file mode 100644 index 0000000000000000000000000000000000000000..728aa3fe2ae3c84554fc87bec7658384b937ccfe --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/README.md @@ -0,0 +1,139 @@ +
+ +
+
+ +

+ Pear Admin Layui +

+

+ 开 箱 即 用 的 前 后 端 解 决 方 案 +

+ + [预 览](http://layui.pearadmin.com) | [官 网](http://www.pearadmin.com/) | [文档](http://www.pearadmin.com/doc) + +
+ +

+ + Pear Admin Layui Version + + + Jquery Version + + + Layui Version + +

+
+
+ +
+
+ +### 项目介绍 + +

+ +Pear Admin 是一款开箱即用的前端开发模板,提供便捷快速的开发方式,延续 Admin 的设计规范。 + +若你需要更多版本 (Java Go Think 等),请前往 [Pear Admin 社区](https://gitee.com/pear-admin) + +项目不定时更新,建议 Star watch 一份 + +

+ +### 新特性 + +- [重构] frame.js 组件,重命名为 page.js, 移除 iframe 嵌套。 +- [重构] tab.js 组件,重命名为 tabPage.js, 移除 iframe 嵌套。 +- [新增] admin.js 模块 setConfigurationProvider 方法,用于自定义 configuration 来源。 +- [优化] admin.js 模块 logout 方法,返回值由 boolean 调整为 Promise 类型。 +- [新增] 夜间模式适配,目前已完成整体框架兼容,layui 待完成。 +- [新增] menuSearch.js 模块,原有的菜单搜索功能。 + +### Branch 说明 + +

+ +main: 最新的功能,主要维护的版本。 + +package: 通过 gulp.js 提供打包构建,适合对资源加载和编译速度有要求的项目。 + +i18n: 集成 translate.js 提供 i18n 国际化功能的版本。 + +

+ +### 项目结构 + +``` +Pear Admin Layui +│ +├─admin 资源 +│ │ +│ ├─css 样式 +│ │ +│ ├─data 数据 +│ │ +│ └─images 图片 +│ +├─component 组件 +│ │ +│ ├─layui 核心框架 +│ │ +│ └─pear 扩展组件 +│ +├─config 配置 +│ │ +│ ├─pear.config.yml 配置文件 +│ │ +│ └─pear.config.json 配置文件 +│ +├─view 视图 +│ │ +│ ├─analysis 分析页 +│ │ +│ ├─component 组件案例 +│ │ +│ ├─console 控制台 +│ │ +│ ├─exception 错误页 +│ │ +│ ├─listing 列表页 +│ │ +│ └─result 结果页 +│ +├─index.html 入口 +│ +└─login.html 登录 + +``` + +### 项目截图 + +| | | +|---------------------|---------------------| +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/221841_9d135fe6_4835367.png "屏幕截图.png") | ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/221901_b5282417_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/221920_84f71864_4835367.png "屏幕截图.png")| ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/221953_eacb1578_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222007_334b5411_4835367.png "屏幕截图.png")| ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222020_ed5e67ac_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222105_9a1036c6_4835367.png "屏幕截图.png")| ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222116_50936543_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222150_6251bb30_4835367.png "屏幕截图.png")| ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222206_777ccf74_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222315_712d2942_4835367.png "屏幕截图.png")|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222345_2629d03c_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222410_e83792fa_4835367.png "屏幕截图.png")| ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222431_5b884442_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222453_b02034b2_4835367.png "屏幕截图.png")| ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222508_fec3ad5e_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222533_abda701e_4835367.png "屏幕截图.png")|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222547_db49f0b8_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222611_7ffd378b_4835367.png "屏幕截图.png")|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222625_55e092f3_4835367.png "屏幕截图.png") | + +### 开源共建 + +

+ +1. 欢迎提交 [pull request](https://gitee.com/pear-admin/Pear-Admin-Layui/pulls),注意对应提交对应 `main` 分支 + +2. 欢迎提交 [issue](https://gitee.com/pear-admin/Pear-Admin-Layui/issues),请写清楚遇到问题的原因、开发环境、复显步骤。 + +

+ +感谢每一位贡献代码的朋友。 + +如果对您有帮助,您可以点右上角 💘Star💘 支持 diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/css/admin.css b/demo/thinkphp/frontend/layui_admin_flow/admin/css/admin.css new file mode 100644 index 0000000000000000000000000000000000000000..a96ce163111abc867c276e2588a715d233427efe --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/css/admin.css @@ -0,0 +1,647 @@ +html, +body, +.layui-layout { + height: 100%; +} + +.pear-admin .layui-body, +.pear-admin .layui-logo, +.pear-admin .layui-side, +.pear-admin .layui-header, +.pear-admin .layui-header .layui-layout-left { + transition: all .3s; +} + +.pear-admin.banner-layout .layui-side { + top: 60px !important; +} + +.pear-admin.banner-layout .layui-side .layui-logo { + display: none; +} + +.pear-admin.banner-layout .layui-header .layui-logo { + display: inline-block; +} + +.pear-admin.banner-layout .layui-side .layui-side-scroll { + height: 100% !important; +} + +.pear-admin.banner-layout .layui-side .layui-side-scroll { + height: 100% !important; +} + +.pear-admin .layui-header.dark-theme .layui-layout-control .layui-this * { + background-color: rgba(0, 0, 0, .1) !important; +} + +.pear-admin .layui-header .layui-logo { + display: none; +} + +.pear-admin .layui-logo .title { + font-size: 20px; +} + +.pear-admin .layui-layout-right .layui-nav-child { + border: 1px solid whitesmoke; + border-radius: 4px; + width: auto; + left: auto; + right: -23px; +} + +.pear-admin .layui-header { + left: 230px; + width: calc(100% - 230px); + background-color: white; +} + +.pear-admin .layui-layout-control { + left: 140px; + position: absolute; +} + +.pear-admin .layui-layout-control .layui-nav { + padding: 0px; +} + +.pear-admin .layui-logo { + height: 60px; + line-height: 60px; + border-bottom: 1px solid rgba(0, 0, 0, .12); + box-sizing: border-box; + position: relative; + background-color: #28333E; + width: 230px; +} + +.pear-admin .layui-logo img { + width: 34px; + height: 34px; +} + +.pear-admin .layui-logo .title { + font-size: 21px; + font-weight: 550; + color: var(--global-primary-color); + position: relative; + top: 5px; + margin-left: 5px; +} + +.pear-admin .layui-logo .logo { + display: none; +} + +.pear-admin .layui-side { + top: 0px; + width: 230px; + box-shadow: 2px 0 6px rgba(0, 21, 41, .20); + z-index: 9999; +} + +.pear-admin .layui-side-scroll::-webkit-scrollbar { + width: 0px; + height: 0px; +} + +.pear-admin .layui-side-scroll { + height: calc(100% - 60px) !important; + background-color: #28333E; + width: 247px; + +} + +.pear-admin .layui-header .layui-nav .layui-nav-item>a { + color: black; + font-size: 15px; +} + +.pear-admin .layui-body { + bottom: 0px; + padding-bottom: 0px; + background-color: whitesmoke; + height: calc(100% - 60px); + overflow-y: auto; + left: 230px; +} + +.pear-admin .layui-body>div { + height: 100%; +} + +.pear-admin .layui-layout-left { + left: 0px; +} + +.pear-admin .layui-footer { + position: absolute; + display: flex; + justify-content: space-between; + left: 230px; + background: #fff; + border-top: 1px solid #F2F2F2; + box-shadow: none; + -webkit-transition: left .3s; + transition: left .3s; + overflow: hidden; + color: #3c3c3cb3; + font-weight: 300; + font-size: 13.6px; +} + +.pear-admin .layui-footer.close { + display: none; +} + +/** 通栏布局 */ + +.pear-admin.banner-layout .layui-header { + left: 0px; + z-index: 99999; + width: 100%; +} + +.pear-admin.banner-layout .layui-header.light-theme { + border-bottom: 1px solid whitesmoke; +} + +.pear-admin.banner-layout .layui-header.auto-theme, +.pear-admin.banner-layout .layui-header.dark-theme { + box-shadow: 0 1px 4px rgba(0, 0, 0, .1); +} + +.pear-admin.banner-layout .layui-header .layui-layout-left { + left: 230px; +} + +.pear-admin.banner-layout .layui-header .layui-logo .title { + top: 2px; +} + +.pear-admin.banner-layout .layui-header .layui-layout-control { + display: inline-block; + left: 370px; +} + +/** 头部主题 */ +.pear-admin .auto-theme { + background-color: var(--global-primary-color); + color: white; +} + +.pear-admin .auto-theme .layui-logo { + background-color: var(--global-primary-color); + border: none; +} + +.pear-admin .auto-theme .layui-logo .title { + color: white; +} + +.pear-admin .auto-theme .layui-nav * { + color: white !important; +} + +.pear-admin .auto-theme .layui-nav.pear-nav-control .layui-this * { + color: black !important; +} + +.pear-admin .auto-theme .layui-nav .layui-nav-child a { + color: #5f5f5f !important; + color: rgba(0, 0, 0, .8) !important; +} + +/** 收缩布局 */ +.pear-mini .layui-side .layui-logo .title { + display: none; +} + +.pear-mini .layui-side .layui-logo .logo { + display: inline-block; +} + +.pear-mini .layui-side { + width: 60px; +} + +.pear-mini .layui-header { + left: 60px; + width: calc(100% - 60px); +} + +.pear-mini .layui-body { + left: 60px; +} + +.pear-mini .layui-side .layui-logo { + width: 60px; +} + +.pear-mini .layui-footer { + left: 60px; +} + +.pear-mini .layui-nav-tree .layui-nav-item span { + display: none; +} + +.pear-mini .layui-side-scroll { + height: calc(100% - 60px); +} + +.pear-admin .layui-header .layui-nav .layui-nav-bar { + top: 0px !important; + background-color: var(--global-primary-color); + height: 2px !important; +} + +.pear-admin .layui-header .layui-nav .layui-this:after { + display: none; +} + +.pear-admin .layui-header .layui-nav-more { + display: none; +} + +.pear-collapsed-pe { + right: 30px; + bottom: 30px; + z-index: 400000; + position: absolute; + background-color: var(--global-primary-color) !important; + box-shadow: 2px 0 6px rgba(0, 21, 41, .20); + text-align: center; + border-radius: 4px; + line-height: 50px; + display: none; + height: 50px; + width: 50px; +} + +.pear-collapsed-pe a { + color: white !important; +} + +@media screen and (min-width: 768px) { + .layui-hide-sm { + display: inline-block !important; + } +} + +@media screen and (min-width: 769px) { + .layui-hide-sm { + display: none !important; + } +} + +/** 新增兼容 */ +@media screen and (max-width:768px) { + .collapse { + display: none !important; + } + + .pear-collapsed-pe { + display: inline-block !important; + } + + .layui-layout-control { + left: 45px !important; + } + + .layui-layout-left { + padding-left: 10px; + padding-right: 10px; + } + + .pear-mini .layui-side-scroll { + height: calc(100% - 62px); + } + + .pear-mini .layui-side { + width: 0px; + } + + .pear-mini .layui-header { + left: 0px; + width: 100%; + } + + .pear-mini .layui-body { + left: 0px; + } + + .pear-mini .layui-footer { + left: 0px; + } + + .pear-mini .layui-logo { + width: 0px; + } + + .pear-admin .layui-body { + left: 0px; + } + + .pear-admin .layui-header { + left: 0px; + width: 100%; + } + + .pear-admin .pear-cover { + width: 100%; + height: 100%; + background-color: #1E1E1E; + display: block; + position: absolute; + z-index: 1000; + opacity: 0; + margin-top: -60px; + } + + .pear-mini .pear-cover { + display: none; + } +} + +@-webkit-keyframes am-horizontal-roll_show { + 0% { + opacity: 1; + -webkit-transform: translateX(2000px); + transform: translateX(2000px) + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0) + } +} + +@keyframes am-horizontal-roll_show { + 0% { + opacity: 1; + -webkit-transform: translateX(800px); + -ms-transform: translateX(800px); + transform: translateX(800px) + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0) + } +} + +.layer-anim-right { + -webkit-animation: am-horizontal-roll_show .5s ease-out; + animation: am-horizontal-roll_show .5s ease-out; + +} + +/** 侧边主题 (亮) */ +.light-theme.layui-side { + box-shadow: 2px 0 8px 0 rgba(29, 35, 41, .05) !important; +} + +.light-theme.layui-side .layui-logo { + background-color: white !important; + color: black !important; + border-bottom: 1px whitesmoke solid; +} + +.light-theme.layui-side .layui-side-scroll { + background-color: white !important; + color: black !important; +} + +.dark-theme.layui-header { + border-bottom: none; + background-color: #28333E; + color: whitesmoke; +} + +.dark-theme.layui-header li>a { + color: whitesmoke !important; +} + +.dark-theme.layui-header .layui-logo { + box-shadow: none; + border: none; +} + +/** 顶部主题 (白) */ +.light-theme.layui-header .layui-logo { + background-color: white; + border: none; + box-shadow: none; +} + +/** 主题面板 */ +.pearone-color .set-text { + height: 42px; + line-height: 42px; +} + +.pearone-color .color-title { + padding: 15px 0 0px 20px; + margin-bottom: 4px; +} + +.pearone-color .color-content { + padding: 15px 10px 0 20px; +} + +.pearone-color .color-content ul { + list-style: none; + padding: 0px; +} + +.pearone-color .color-content ul li { + position: relative; + display: inline-block; + vertical-align: top; + width: 70px; + height: 50px; + margin: 0 20px 20px 0; + padding: 2px 2px 2px 2px; + background-color: #f2f2f2; + cursor: pointer; + font-size: 12px; + color: #666; +} + +.pearone-color .color-content li.layui-this:after, +.pearone-color .color-content li:hover:after { + width: 100%; + height: 100%; + padding: 4px; + top: -6px; + left: -6px; + border: var(--global-primary-color) 2px solid; + opacity: 1; + border-radius: 4px; +} + +.pearone-color .color-content li:after { + content: ''; + position: absolute; + z-index: 20; + top: 50%; + left: 50%; + width: 1px; + height: 0; + border: 2px solid #F2F2F2; + transition: all .3s; + -webkit-transition: all .3s; + opacity: 0; +} + +.select-color { + margin-bottom: 30px; +} + +.select-color .select-color-title { + padding: 15px 0 0px 20px; + margin-bottom: 4px; +} + +.select-color .select-color-content { + padding: 20px 0 0px 0px; + margin-bottom: 4px; +} + +.select-color .select-color-content .select-color-item { + width: 24px; + height: 24px; + color: white; + margin-left: 24px; + border-radius: 6px; + background-color: gray; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .15); + text-align: center; + line-height: 24px; + font-size: 12px; + float: left; +} + +.message .layui-tab-title li:not(:last-child) { + border-right: 1px solid #eee; +} + +/** 首屏加载 */ +.loader-wrapper { + position: fixed; + width: 100%; + height: 100%; + background-color: whitesmoke; + z-index: 9999999; +} + +.loader { + width: 50px; + height: 50px; + margin: 30px auto 40px; + margin-top: 20%; + position: relative; + z-index: 999999; + background-color: whitesmoke; +} + +.loader:before { + content: ""; + width: 50px; + height: 7px; + border-radius: 50%; + background: #000; + opacity: 0.1; + position: absolute; + top: 59px; + left: 0; + animation: shadow .5s linear infinite; +} + +.loader:after { + content: ""; + width: 50px; + height: 50px; + border-radius: 10px; + background-color: var(--global-primary-color); + position: absolute; + top: 0; + left: 0; + animation: loading .5s linear infinite; +} + +@-webkit-keyframes loading { + 17% { + border-bottom-right-radius: 3px; + } + + 25% { + transform: translateY(9px) rotate(22.5deg); + } + + 50% { + transform: translateY(18px) scale(1, 0.9) rotate(45deg); + border-bottom-right-radius: 40px; + } + + 75% { + transform: translateY(9px) rotate(67.5deg); + } + + 100% { + transform: translateY(0) rotate(90deg); + } +} + +@keyframes loading { + 17% { + border-bottom-right-radius: 3px; + } + + 25% { + transform: translateY(9px) rotate(22.5deg); + } + + 50% { + transform: translateY(18px) scale(1, 0.9) rotate(45deg); + border-bottom-right-radius: 40px; + } + + 75% { + transform: translateY(9px) rotate(67.5deg); + } + + 100% { + transform: translateY(0) rotate(90deg); + } +} + +@-webkit-keyframes shadow { + + 0%, + 100% { + transform: scale(1, 1); + } + + 50% { + transform: scale(1.2, 1); + } +} + +@keyframes shadow { + + 0%, + 100% { + transform: scale(1, 1); + } + + 50% { + transform: scale(1.2, 1); + } +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/css/admin.dark.css b/demo/thinkphp/frontend/layui_admin_flow/admin/css/admin.dark.css new file mode 100644 index 0000000000000000000000000000000000000000..3898bf216d360735d8fe62cff49278855c72333e --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/css/admin.dark.css @@ -0,0 +1,337 @@ +/** loader */ +.pear-admin-dark .loader-wrapper, +.pear-admin-dark .loader-wrapper .loader { + background-color: #141414; +} + +/** layout */ +.pear-admin-dark .layui-layout { + background-color: #141414; +} + +/** header */ +.pear-admin-dark .layui-header, +.pear-admin-dark .layui-header .layui-logo { + background-color: #141414 !important; + box-shadow: none !important; + border: none !important; +} +.pear-admin-dark .layui-header.auto-theme, +.pear-admin-dark .layui-header.auto-theme .layui-logo { + background-color: var(--global-primary-color) !important; +} + +.pear-admin-dark .layui-header.auto-theme .layui-logo .title { + color: #ffffff !important; +} + +.pear-admin-dark .layui-header { + border: 1px solid rgba(0, 0, 0, .40) !important; +} + +.pear-admin-dark .layui-header .layui-nav * { + color: #ffffff !important; +} + +.pear-admin-dark .layui-header .layui-nav .layui-nav-child { + box-shadow: 0 3px 4px rgba(0, 0, 0, .6) !important; + background-color: #141414; + border-color: #141414; +} + +.pear-admin-dark .layui-header .layui-nav .layui-nav-child dd > a:hover { + background-color: #141414 !important; +} + +.pear-admin-dark .layui-header .pear-nav-control .layui-this a{ + background-color: #0c0c0c !important; +} + +.pear-admin-dark .auto-theme .layui-logo .title{ + color: var(--global-primary-color) !important; +} + +/** side */ +.pear-admin-dark .layui-side { + box-shadow: 0 3px 4px rgba(0, 0, 0, .6) !important; +} + +.pear-admin-dark .layui-logo { + border-color: rgba(0, 0, 0, .30) !important; +} + +.pear-admin-dark .layui-side .layui-logo, +.pear-admin-dark .layui-side .layui-side-scroll, +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav-tree{ + background-color: #141414 !important; +} + +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav-tree .layui-nav-child { + background-color: rgba(0,0,0,.3)!important; +} + +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-item a, +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-item a > .layui-nav-more { + color: rgba(255,255,255,.7) !important; +} + +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-child dd.layui-this a, +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-itemed > a, +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-itemed > a > .layui-nav-more, +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-item > a:hover { + color: #ffffff !important; +} + +/** body */ +.pear-admin-dark .layui-body, +.pear-admin-dark .layui-body .pear-tab-page-loading, +.pear-admin-dark .layui-body .pear-page-loading { + background-color: #0a0a0a !important; +} + +.pear-admin-dark .layui-body .layui-tab .layui-tab-title, +.pear-admin-dark .layui-body .layui-tab .layui-tab-title li, +.pear-admin-dark .layui-body .layui-tab .layui-tab-control li { + background-color: #141414 !important; + border-color:rgba(0, 0, 0, .30) !important; + color: #ffffff; +} + +.pear-admin-dark .layui-body .layui-tab .layui-tab-title li > span:first-child { + background-color: #434343; +} + +.pear-admin-dark .layui-body .layui-tab .layui-nav-child.layui-anim { + border-color: #141414; + background-color: #141414 !important; +} + +.pear-admin-dark .layui-body .layui-tab .layui-nav-child.layui-anim a { + color: #ffffff; +} + +.pear-admin-dark .layui-body .layui-tab .layui-nav-child.layui-anim a:hover { + background-color: #0a0a0a; +} + +.pear-admin-dark .layui-body .layui-tab .layui-tab-close:hover { + border-radius: 50%; + background-color: #0a0a0a !important; +} + +.pear-admin-dark .pear-tab-page-menu ul li { + color: #ffffff !important; +} + +.pear-admin-dark .layui-footer { + background-color: #141414; + border-top: 1px solid #141414; +} + +/** theme */ +.pear-admin-dark .set-text, +.pear-admin-dark .select-color-title, +.pear-admin-dark .color-title { + color: #ffffff; +} + +/** search */ +.pear-admin-dark .menu-search-no-data { + color: #ffffff; +} + +.pear-admin-dark .menu-search-tips * { + color: #ffffff; +} + +.pear-admin-dark .menu-search-tips kbd { + border-color: rgba(0, 0, 0, .30) !important; +} + + +/** message center */ +.pear-admin-dark .pear-message-center .layui-tab-title, +.pear-admin-dark .pear-message-center .message-item { + border-color: rgba(0, 0, 0, .30) !important; + color: #ffffff; +} + +/** button */ +.pear-admin-dark .layui-btn { + color: #ffffff; + border-color: #4C4D4F; +} + +/** layer */ +.pear-admin-dark .layui-layer { + background-color: #141414; +} + +.pear-admin-dark .layui-layer-msg { + border-color: #141414; +} + +.pear-admin-dark .layui-layer-msg .layui-layer-content { + color: #E5EAF3; +} + +.pear-admin-dark .layui-layer .layui-layer-setwin > span, +.pear-admin-dark .layui-layer .layui-layer-title { + color: #ffffff; +} + +/** card */ +.pear-admin-dark .layui-card { + background-color: #1d1e1f !important; +} + +.pear-admin-dark .layui-card .layui-card-header { + border-bottom-color: #414243; + color: #ffffff; +} + +.pear-admin-dark .layui-card .layui-card-body { + color: #ffffff; +} + +/** input */ +.pear-admin-dark .layui-input { + background-color: transparent; + color: #ffffff; + border-color: rgba(0, 0, 0, .30) !important; +} + +/** switch */ +.pear-admin-dark .layui-form-switch { + border-color: #484849; + background-color: rgba(255,255,255,.08); +} + +/** table */ +.pear-admin-dark .layui-table { + background-color: transparent; +} + +.pear-admin-dark .layui-table tr:hover { + background-color: #141414 !important; +} + +.pear-admin-dark .layui-table td, +.pear-admin-dark .layui-table th, +.pear-admin-dark .layui-table-view, +.pear-admin-dark .layui-table-page, +.pear-admin-dark .layui-table-tool, +.pear-admin-dark .layui-table-header { + border-color: rgba(0, 0, 0, .40) !important; +} + +.pear-admin-dark .layui-laypage select, +.pear-admin-dark .layui-laypage button { + border-color: rgba(0, 0, 0, .40) !important; + color: #ffffff !important; + background-color: transparent; +} + +.pear-admin-dark .layui-table-tool-self > div { + border-color: rgba(0, 0, 0, .40) !important; + color: #ffffff !important; + background-color: transparent; +} + +/** panel */ +.pear-admin-dark .layui-panel { + background-color: #1d1e1f !important; + border-color: #1d1e1f !important; +} + +/** menu */ +.pear-admin-dark .layui-menu { + background-color: #1d1e1f !important; +} + +.pear-admin-dark .layui-menu .layui-menu-body-title, +.pear-admin-dark .layui-menu .layui-menu-body-title:hover { + color: #ffffff; + background-color: #1d1e1f !important; +} + +/** timeline */ +.pear-admin-dark .layui-timeline-axis { + background-color: rgb(29, 30, 31) !important; +} + +.pear-admin-dark .layui-timeline-item:before { + background-color: #414243 !important; +} + + +/** toast */ +.pear-admin-dark .iziToast { + background-color: #1f1f1f !important; +} + +/** console */ + +.pear-admin-dark .deputy, +.pear-admin-dark .shortcut-menu { + background-color: #141414 !important; +} + +.pear-admin-dark .deputy:hover, +.pear-admin-dark .shortcut-menu:hover { + box-shadow: 0 3px 4px rgba(0, 0, 0, .6) !important; +} + +.pear-admin-dark .message-board li { + border-bottom: 1px solid rgba(0, 0, 0, .40) !important; +} + +/** analysis */ +.pear-admin-dark .top-panel-number { + color: #ffffff !important; + border-color: #414243; +} + + +.pear-admin-dark .dynamic-status dd { + border-color: #414243; +} + +/** success failure */ +.pear-admin-dark .pear-result .content { + background-color: rgba(153, 153, 153, 0.12); + color: #E5EAF3; +} + +.pear-admin-dark .pear-result .title{ + color: #ffffff; +} + +.pear-admin-dark .pear-result .description{ + color: #8D9095; +} + +/** 403 404 500*/ +.pear-admin-dark .pear-exception .title p{ + color: #E5EAF3 !important; +} + +/** scroll */ +.pear-admin-dark *::-webkit-scrollbar-thumb { + background: #141414; + border-radius: 4px; +} + +.pear-admin-dark *::-webkit-scrollbar-thumb:hover { + background: #0a0a0a; +} + +/** profile */ +.pear-admin-dark .user-name, +.pear-admin-dark .user-desc { + color: whitesmoke; +} + +.pear-admin-dark .user-desc { + border-top: 1px solid #141414; +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/analysis.css b/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/analysis.css new file mode 100644 index 0000000000000000000000000000000000000000..3525a21a63b6904d2ea66a9a591306edf1af5d7f --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/analysis.css @@ -0,0 +1,65 @@ +.top-panel { + border-radius: 4px; + text-align: center; +} + +.top-panel>.layui-card-body { + height: 60px; +} + +.top-panel-number { + line-height: 60px; + font-size: 29px; + border-right: 1px solid #eceff9; +} + +.top-panel-tips { + padding-left: 8px; + padding-top: 16px; + line-height: 30px; + font-size: 12px; +} + +.top-panel-tips i { + font-size: 33px; +} + +.top-panel-tips svg { + margin-top: -12px; + width: 50px; + height: 50px; +} + +.dynamic-status { + padding: 0 10px 10px; +} + +.dynamic-status dd { + padding: 15px 0; + border-bottom: 1px solid #EEE; + display: -webkit-flex; + display: flex; +} + +.dynamic-status dd div.dynamic-status-img { + width: 32px; + height: 32px; + border-radius: 50%; + margin-right: 15px; +} + +.dynamic-status dd div.dynamic-status-img a { + width: 100%; + height: 100%; + display: inline-block; + text-align: center; + line-height: 32px; +} + +.dynamic-status dd div span { + color: #BBB; +} + +.dynamic-status dd div a { + color: #01AAED; +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/console.css b/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/console.css new file mode 100644 index 0000000000000000000000000000000000000000..af9930ba4d959a0cf2143f0a89d385faac0721c3 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/console.css @@ -0,0 +1,81 @@ + +.shortcut-menu { + width: 100%; + height: 66px; + background-color: #F8F8F8; + display: inline-block; + border-radius: 5px; + text-align: center; + margin-bottom: 3px; +} + +.shortcut-menu i { + font-size: 30px; + height: 66px; + line-height: 66px; +} + +.shortcut-menu:hover { + box-shadow: 2px 0 8px 0 lightgray !important; +} + +.shortcut-menu-label { + width: 100%; + display: inline-block; + text-align: center; +} + +.deputy { + width: 100%; + height: 90px; + background-color: #F8F8F8; + display: inline-block; + border-radius: 5px; + text-align: center; + margin-bottom: 3px; +} + +.deputy:hover { + box-shadow: 2px 0 8px 0 lightgray !important; +} + +.deputy .deputy-label { + color: gray; + margin-top: 14px; + font-size: 14px; +} + +.deputy .deputy-count { + margin-top: 12px; + color: var(--global-primary-color); + font-size: 30px; +} + +.message-board { + padding: 0 10px 10px; +} + +.message-board li { + position: relative; + padding: 10px 0; + border-bottom: 1px solid #EEE; +} + +.message-board li p { + padding-bottom: 10px; + padding-top: 3px; +} + +.message-board li>span { + color: #999; + height: 24px; + line-height: 24px; +} + +.message-board .message-board-reply { + position: absolute; + right: 20px; + bottom: 12px; + height: 24px; + line-height: 24px; +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/exception.css b/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/exception.css new file mode 100644 index 0000000000000000000000000000000000000000..e7f2027cfeeb42dd728f1397552c2c1e4cb480b6 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/exception.css @@ -0,0 +1,28 @@ +.pear-exception { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + text-align: center; + box-sizing: border-box; + padding: 70px 40px +} + +.pear-exception .title { + margin-top: 20px; +} + +.pear-exception .title p { + color: rgb(0, 0, 0); + font-size: 20px; +} + +.pear-exception .description { + margin-top: 10px; + color: #8D9095; + font-size: 14px; +} + +.pear-exception .extra { + margin: 30px; +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/login.css b/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/login.css new file mode 100644 index 0000000000000000000000000000000000000000..853e09221e47f8f024345c8ee495fb5e77af3490 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/login.css @@ -0,0 +1,218 @@ +html, +body{ + height: 100%; +} + +.login-page { + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + display: flex; + justify-content: center; + align-items: center; +} + +.layui-row { + width: 1000px; + height: 600px; + box-shadow: 2px 0 6px rgba(0, 21, 41, .20); + border: 3px solid whitesmoke; + border-radius: 15px; +} + +.login-bg { + height: 100%; + box-sizing: border-box; + background-color: rgb(250, 250, 250); + display: flex; + align-items: center; + justify-content: center; + border-bottom-left-radius: 15px; + border-top-left-radius: 15px; +} + +.login-bg-img { + width: 90%; + display: inline-block; + margin: 0 auto; +} + +.login-form { + height: 100%; + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: center; + background-color: #fff; + border-bottom-right-radius: 15px; + border-top-right-radius: 15px; +} + +.form-center { + background: #fff; + box-sizing: border-box; + flex-flow: row wrap; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + text-align: center; +} + +.form-center-box { + width: 360px; +} + +.top-log-title { + align-items: center; + justify-content: center; + display: flex; + margin-bottom: 30px; +} + +.top-log { + width: 50px; + border-radius: 12px; + margin-right: 20px; + height: 50px; +} + +.top-log-title span { + font-size: 32px; + font-weight: 700; + color: var(--global-primary-color); +} + +.top-desc { + font-size: 14px; + color: #808695; + +} + +.tab-log-method { + width: 100%; + display: flex; + padding: 20px 0px; +} + +.tab-log-method-item { + flex: 1; + box-sizing: border-box; + padding: 5px 50px; + text-align: right; + color: #1f2225; + font-size: 16px; +} + +.tab-log-method-item:nth-child(2) { + text-align: left; +} + +.tab-log-method-item>span { + display: inline-block; + width: 40px; + text-align: center; + height: 30px; + border-bottom: 2px solid transparent; +} + +.tab-log-method-item>span:hover { + cursor: pointer; + color: #16baaa; + border-bottom: 2px solid #16baaa; +} + +.tab-log-verification { + width: 100%; + display: flex; +} + +.verification-text { + flex: 2; + box-sizing: border-box; + margin-right: 20px; +} + +.verification-img { + flex: 1; + box-sizing: border-box; + border: 1px solid #eeeeee; + border-radius: 4px; + height: 40px; + overflow: hidden; + text-align: center; +} + +.remember-passsword { + margin: 20px 0; + width: 100%; + display: flex; + box-sizing: border-box; +} + +.remember-cehcked { + flex: 1; + text-align: left; +} + +.greenText { + color: #16baaa; + cursor: pointer; +} + + +.login-btn { + width: 100%; + box-sizing: border-box; +} + +.login-btn>.layui-btn { + width: 100%; +} + +.other-login { + width: 100%; + box-sizing: border-box; + margin: 20px 0 0; + text-align: left; + display: flex; +} + +.other-login-methods { + display: inline-block; + flex: 1; +} + +.layui-input { + border-radius: 4px; + line-height: 40px; + height: 40px; +} + +.layui-btn { + border-radius: 4px; + background-color: var(--global-primary-color); +} + +@media(min-width: 992px) and (max-width:1200px){ + .layui-row{ + width: 900px; + } +} +@media(min-width: 768px) and (max-width:992px){ + .layui-row{ + width: 90%; + } + .form-center{width: 90%;} +} +@media (max-width:768px){ + .layui-row{ + width: 90%; + } + .login-form { + border-bottom-left-radius: 15px; + border-top-left-radius: 15px; + } + .form-center-box{width: 95%;} +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/profile.css b/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/profile.css new file mode 100644 index 0000000000000000000000000000000000000000..4c779ee44d8963357b2fc438ea65a5207b277ad0 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/profile.css @@ -0,0 +1,77 @@ +.text-center { + text-align: center; +} + +.user-info { + width: 110px; + height: 110px; + line-height: 110px; + position: relative; + display: inline-block; + border-radius: 50%; + overflow: hidden; + cursor: pointer; + margin: 0 auto; +} + +.user-name { + padding-top: 20px; + font-size: 20px !important; +} + +.user-home { + padding-top: 8px; + margin-top: 10px; + font-size: 13.5px; +} + +.user-desc { + height: 45px; + border-top: 1px whitesmoke solid; + text-align: center; + line-height: 45px; + font-size: 13.5px; +} + +.blog-title { + padding-left: 13.5px; +} + +.blog-content { + padding-left: 13px; + font-size: 13px; + color: dimgray; +} + +.layui-tab-title { + border-bottom: none; +} + +.message-board { + padding: 0 10px 10px; +} + +.message-board li { + position: relative; + padding: 10px 0; + border-bottom: 1px solid #EEE; +} + +.message-board li p { + padding-bottom: 10px; + padding-top: 3px; +} + +.message-board li>span { + color: #999; + height: 24px; + line-height: 24px; +} + +.message-board .message-board-reply { + position: absolute; + right: 20px; + bottom: 12px; + height: 24px; + line-height: 24px; +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/result.css b/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/result.css new file mode 100644 index 0000000000000000000000000000000000000000..393c464e564a8e38ab6ac592ea4fffde7093a0aa --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/css/other/result.css @@ -0,0 +1,40 @@ +.pear-result { + text-align: center; + +} +.pear-result .success svg { + color: #32C682; + text-align: center; + margin-top: 40px; + +} +.pear-result .error svg { + color: #f56c6c; + text-align: center; + margin-top: 40px; + +} +.pear-result .title { + margin-top: 25px; + +} +.pear-result .description { + margin-top: 25px; + width: 60%; + margin-left: 20%; + color: rgba(0, 0, 0, .45); +} +.pear-result .content { + margin-top: 20px; + width: 80%; + border-radius: 4px; + background-color: whitesmoke; + padding: 20px 32px; + margin-left: 10%; + margin-bottom: 30px; + text-align: left; +} +.pear-result .extra { + padding-top: 10px; + margin-top: 25px; +} diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/css/reset.css b/demo/thinkphp/frontend/layui_admin_flow/admin/css/reset.css new file mode 100644 index 0000000000000000000000000000000000000000..dbd9d61bbe7a72820f887ff70435471e8a37f396 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/css/reset.css @@ -0,0 +1,387 @@ +.layui-dropdown { + border-radius: var(--global-border-radius); +} + +.layui-input { + border-radius: var(--global-border-radius); +} + +.layui-form-onswitch { + background-color: var(--global-primary-color) !important; +} + +.layui-form-onswitch { + border-color: var(--global-primary-color); +} + +.layui-form-radio:hover>*, +.layui-form-radioed>i, +.layui-form-radioed { + color: var(--global-primary-color) !important; +} + +.layui-form-checked[lay-skin=primary]>i { + border-color: var(--global-primary-color) !important; + background-color: var(--global-primary-color); + color: #fff; +} + +.layui-form-checkbox[lay-skin=primary]>.layui-icon-indeterminate, +.layui-form-checkbox[lay-skin=primary]>.layui-icon-indeterminate:hover { + border-color: var(--global-primary-color); +} + +.layui-form-checkbox[lay-skin=primary]>.layui-icon-indeterminate:before { + background-color: var(--global-primary-color); +} + +.layui-btn { + background-color: var(--global-primary-color); +} + +.layui-btn.layui-btn-primary:hover { + border: 1px solid var(--global-primary-color); +} + +.layui-btn.layui-btn-normal { + background-color: #1e9fff !important; +} + +.layui-btn.layui-btn-danger { + background-color: #ff5722 !important; +} + +.layui-btn.layui-btn-warm { + background-color: #ffb800 !important; +} + +.layui-btn.layui-btn-primary { + background-color: transparent !important; + color: #5f5f5f !important; +} + +.layui-card { + border-radius: var(--global-border-radius); +} + +.layui-timeline-axis { + color: var(--global-primary-color); +} + +.layui-table-checked { + background-color: #f8f8f8; +} + +/* input框选中颜色 */ +.layui-input:focus, .layui-textarea:focus { + border-color: var(--global-primary-color) !important; + /* 这种写法暂时不支持火狐,找不到更好的写法了 */ + box-shadow: 0 0 0 3px rgb(from var(--global-primary-color) r g b / 8%); +} + +/* select框选项颜色 */ +.layui-form-select dl dd.layui-this { + color: var(--global-primary-color); +} + +/* 数字输入框后面的上下角标 */ +.layui-input-wrap .layui-input:focus+.layui-input-split { + border-color: var(--global-primary-color) +} + +/* 标签框文字 */ +.layui-form-checked:hover>div, .layui-form-checked>div { + background-color: var(--global-primary-color); +} + +/* 标签框选中 */ +.layui-form-checked:hover>i, .layui-form-checked>i { + color: var(--global-primary-color); +} + +/* laypage按钮选中颜色 */ +.layui-laypage .layui-laypage-curr .layui-laypage-em { + background-color: var(--global-primary-color); +} + +/* laypage第几页input选中颜色 */ +.layui-laypage input:active { + border-color: var(--global-primary-color); +} + +/* laypage按钮hover颜色 */ +.layui-laypage a:hover { + color: var(--global-primary-color); +} + +/* laypage每页条数select框选中颜色 */ +.layui-laypage input:focus, .layui-laypage select:focus { + border-color: var(--global-primary-color) !important; +} + +/* laydate被选中的元素颜色 */ +.layui-laydate .layui-this, .layui-laydate .layui-this>div { + background-color: var(--global-primary-color) !important; +} + +/* laydate范围按钮hover时的颜色 */ +.layui-laydate-header i:hover, .layui-laydate-header span:hover { + color: var(--global-primary-color); +} + +/* laydate按钮hover时的颜色 */ +.layui-laydate-footer span:hover { + color: var(--global-primary-color); +} + +/* 标签页选中颜色 */ +.layui-tab-brief>.layui-tab-title .layui-this { + color: var(--global-primary-color); +} + +/* 标签页选中下划线颜色 */ +.layui-tab-brief>.layui-tab-more li.layui-this:after, .layui-tab-brief>.layui-tab-title .layui-this:after { + border-bottom: 2px solid var(--global-primary-color); +} + +/* 进度条颜色 */ +.layui-progress-bar { + background-color: var(--global-primary-color); +} + +/* tree选择框hover颜色 */ +.layui-form-checkbox[lay-skin=primary]:hover>i { + border-color: var(--global-primary-color); +} + + + + +/** 表详情顶部搜索框 Start **/ + +.top-search-from .layui-form-item { + position: relative; + display: inline-block; + *display: inline; + *zoom: 1; + vertical-align: middle; +} + +.top-search-from .layui-form-item .layui-input-block { + float: left; + width: 270px; + margin-right: 10px; + margin-left: 0; + display: inline-block; + vertical-align: middle; + position: relative; +} + +.top-search-from .layui-input, .top-search-from .layui-select, .top-search-from .layui-textarea { + width: 270px; +} + +.top-search-from .item-inline .layui-form-item .layui-input-block { + width: 270px; +} + +.top-search-from .layui-form-mid { + margin-left: 7px; + margin-right: 7px; +} + +.top-search-from .layui-form-label { + width: 60px; + white-space: nowrap; +} + +.top-search-from .inline-block { + width: 128px; + display: inline-block +} + +.top-search-from .layui-form-item { + width: 370px; +} + +.top-search-from .toggle-btn { + text-align: center; +} + +.top-search-from .toggle-btn a { + cursor: pointer; + color: #999; +} + +.top-search-from .toggle-btn a:hover { + color: #333; +} + +@media screen and (max-width: 768px) { + .top-search-from .layui-input { + max-width: 234px; + } + + .top-search-from .layui-input.inline-block { + max-width: 110px; + } + + .layui-table-tool-self .layui-inline:nth-child(3) { + display: none; + } +} + + + +/*额外*/ +button { + line-height: 100% !important; +} + +.pear-btn-md, .pear-btn-sm, .pear-btn-xs, .pear-btn { + line-height: 100%; + letter-spacing: 2px; + padding: 0 15px; + font-weight: 400; + font-size: 14px; +} + +.layui-layer-btn { + padding: 0 15px 19px; + letter-spacing: 2px; +} + +.pear-btn i { + font-size: 14px; +} + +.layui-table-cell .pear-btn i { + font-size: 15px; +} + +.layui-table-tips-main { + overflow: hidden; +} + +.layui-table th { + font-weight: 500; +} + +.layui-laypage a, .layui-laypage span { + font-size: 14px; +} + +.layui-table-tool .layui-inline[lay-event], .layui-table-tool .layui-inline[lay-event]:hover { + border: none; +} + +.layui-table-tool-self .layui-icon { + font-size: 18px; +} + +.layui-table, .pear-tab .layui-tab-title li { + color: #333; +} + +.tool-btn.pear-btn-xs { + background: transparent; + font-weight: normal; + font-size: 14px; + color: #333; + border: none; + padding: 0 2px; + height: auto !important; +} + +.layui-iconpicker { + max-width: 290px !important; +} + +.layui-iconpicker .layui-anim { + max-height: 220px !important; +} + +.layui-input:disabled { + color: rgba(0, 0, 0, .25); + background: #f5f5f5; + cursor: not-allowed; +} + +.layui-form-label.required:after { + content: "*"; + color: red; + display: inline-block; + padding: 7px 5px; + line-height: 20px; + text-align: right; + position: absolute; + right: 0; + top: 5px; +} + +.layui-bg-green { + background-color: #36b368 !important; +} + +a { + cursor: pointer; +} + +*[permission] { + display: none; +} + +@media screen and (max-width: 768px) { + /** **/ + .layui-table-tool-self .layui-inline:nth-child(3) { + display: none; + } +} + +/** 右间隔 **/ +.mr-1 { + margin-right: 4px; +} + +.mr-2 { + margin-right: 8px; +} + +.mr-3 { + margin-right: 16px; +} + +.mr-4 { + margin-right: 24px; +} + +.mr-5 { + margin-right: 48px; +} + +/** 图片尺寸 **/ +.img-1 { + max-width: 16px; + max-height: 16px; + border-radius: 6px; +} + +.img-2 { + max-width: 32px; + max-height: 32px; + border-radius: 6px; +} + +.img-3 { + max-width: 64px; + max-height: 64px; + border-radius: 6px; +} + +.img-4 { + max-width: 128px; + max-height: 128px; + border-radius: 6px; +} + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/css/variables.css b/demo/thinkphp/frontend/layui_admin_flow/admin/css/variables.css new file mode 100644 index 0000000000000000000000000000000000000000..a0f467e43a018e41a9b15c320c238a1ec930c3b6 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/css/variables.css @@ -0,0 +1,9 @@ +:root { + + /* 主题颜色 */ + --global-primary-color: #16baaa; + + /** 圆角度数 */ + --global-border-radius: 4px; + +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/data/menu.json b/demo/thinkphp/frontend/layui_admin_flow/admin/data/menu.json new file mode 100644 index 0000000000000000000000000000000000000000..b4dda48e228f18ff446247db0121eb5ab34cf9dc --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/data/menu.json @@ -0,0 +1,314 @@ +{"data":[ + { + "id": 1, + "title": "工作空间", + "icon": "layui-icon layui-icon-console", + "type": 0, + "children": [ + { + "id": "10", + "title": "分析页", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_component", + "href": "view/analysis/index.html" + }, + { + "id": "11", + "title": "工作台", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_component", + "href": "view/console/index.html" + } + ] + }, + { + "id": 9, + "title": "列表页面", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "children": [ + { + "id": 91, + "title": "查询表格", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/listing/table.html" + } + ] + }, + { + "id": 2, + "title": "扩展组件", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "children": [ + { + "id": 21, + "title": "核心方法", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/component/admin.html" + }, + { + "id": 23, + "title": "高级栅格", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/component/grid.html" + }, + { + "id": 24, + "title": "消息提示", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/component/toast.html" + }, + { + "id": 25, + "title": "路由过渡", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/component/nprogress.html" + } + ] + }, + { + "id": "result", + "title": "结果页面", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "href": "", + "children": [ + { + "id": "success", + "title": "成功页面", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/result/success.html" + }, + { + "id": "failure", + "title": "失败页面", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_component", + "href": "view/result/error.html" + } + ] + }, + { + "id": "exception", + "title": "异常页面", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "href": "", + "children": [ + { + "id": "403", + "title": "403", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/exception/403.html" + }, + { + "id": "404", + "title": "404", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_component", + "href": "view/exception/404.html" + }, + { + "id": "500", + "title": "500", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_component", + "href": "view/exception/500.html" + } + ] + }, + { + "id": "open", + "title": "菜单模式", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "children": [ + { + "id": "a", + "title": "普通路由", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/result/success.html" + }, + { + "id": "b", + "title": "嵌套网页", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "http://www.layui-vue.com" + }, + { + "id": "c", + "title": "新建标签", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_blank", + "href": "http://www.layui-vue.com" + }, + { + "id": "d", + "title": "弹窗网页", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_layer", + "href": "http://www.layui-vue.com" + } + ] + }, + { + "id": "deep", + "title": "深度测试", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "href": "", + "children": [ + { + "id": "deep1-1", + "title": "二级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 0, + "openType": "_component", + "href": "view/result/success.html", + "children": [ + { + "id": "deep1-1-1", + "title": "三级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 0, + "openType": "_component", + "href": "view/result/success.html", + "children": [ + { + "id": "deep1-1-1-1", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/result/success.html" + }, + { + "id": "deep1-1-1-2", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_blank", + "href": "http://www.layui-vue.com" + } + ] + }, + { + "id": "deep1-1-2", + "title": "三级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 0, + "openType": "_blank", + "href": "http://www.layui-vue.com", + "children": [ + { + "id": "deep1-1-2-1", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/result/success.html" + }, + { + "id": "deep1-1-2-2", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_blank", + "href": "http://www.layui-vue.com" + } + ] + } + ] + }, + { + "id": "deep1-2", + "title": "二级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 0, + "openType": "_blank", + "href": "http://www.layui-vue.com", + "children": [ + { + "id": "deep1-2-1", + "title": "三级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 0, + "openType": "_component", + "href": "view/result/success.html", + "children": [ + { + "id": "deep1-2-1-1", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/result/success.html" + }, + { + "id": "deep1-2-1-2", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_blank", + "href": "http://www.layui-vue.com" + } + ] + }, + { + "id": "deep1-2-2", + "title": "三级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 0, + "openType": "_blank", + "href": "http://www.layui-vue.com", + "children": [ + { + "id": "deep1-2-2-1", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/result/success.html" + }, + { + "id": "deep1-2-2-2", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_blank", + "href": "http://www.layui-vue.com" + } + ] + } + ] + } + ] + } +] +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/data/message.json b/demo/thinkphp/frontend/layui_admin_flow/admin/data/message.json new file mode 100644 index 0000000000000000000000000000000000000000..b95a924f37b6136c7c9482607c9845bb9a31b1c7 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/data/message.json @@ -0,0 +1,102 @@ +{ + "code": 200, + "data": [ + { + "id": 1, + "title": "通知", + "children": [ + { + "id": 11, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + "title": "你收到了 14 份新周报", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 12, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png", + "title": "曲妮妮 已通过第三轮面试", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 11, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png", + "title": "可以区分多种通知类型", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 12, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png", + "title": "左侧图标用于区分不同的类型", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 11, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + "title": "内容不要超过两行字", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + } + ] + }, + { + "id": 2, + "title": "消息", + "children": [ + { + "id": 11, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + "title": "你收到了 14 份新周报", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 12, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png", + "title": "曲妮妮 已通过第三轮面试", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 11, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png", + "title": "可以区分多种通知类型", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 12, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png", + "title": "左侧图标用于区分不同的类型", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 11, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + "title": "内容不要超过两行字", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + } + ] + }, + { + "id": 3, + "title": "代办", + "children": [] + } + ] +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/data/table.json b/demo/thinkphp/frontend/layui_admin_flow/admin/data/table.json new file mode 100644 index 0000000000000000000000000000000000000000..c0249f0cdd8cf4d78eab02d84eb5f8a0fb073440 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/data/table.json @@ -0,0 +1,303 @@ +{ + "code": 0, + "msg": "", + "count": 1000, + "totalRow": { + "era": { + "tang": "2", + "song": "2", + "xian": "20" + } + }, + "data": [ + { + "id": "10001", + "username": "就眠儀式", + "email": "test1@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10002", + "username": "杜甫", + "email": "test2@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "108", + "joinTime": "2016-10-14", + "LAY_CHECKED": true + }, + { + "id": "10003", + "username": "就眠儀式", + "email": "test3@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10004", + "username": "就眠儀式", + "email": "test4@email.com", + "sex": "女", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10005", + "username": "就眠儀式", + "email": "test5@email.com", + "sex": "女", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10006", + "username": "就眠儀式", + "email": "test6@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10007", + "username": "就眠儀式", + "email": "test7@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10008", + "username": "就眠儀式", + "email": "test8@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10009", + "username": "就眠儀式", + "email": "test9@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10010", + "username": "就眠儀式", + "email": "test10@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10011", + "username": "就眠儀式", + "email": "test11@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10012", + "username": "就眠儀式", + "email": "test12@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10013", + "username": "就眠儀式", + "email": "test13@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10014", + "username": "就眠儀式", + "email": "test14@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10015", + "username": "就眠儀式", + "email": "test15@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10016", + "username": "就眠儀式", + "email": "test16@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10017", + "username": "就眠儀式", + "email": "test17@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10018", + "username": "就眠儀式", + "email": "test18@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10019", + "username": "就眠儀式", + "email": "test19@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10020", + "username": "就眠儀式", + "email": "test20@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10021", + "username": "就眠儀式", + "email": "test21@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10022", + "username": "就眠儀式", + "email": "test22@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10023", + "username": "就眠儀式", + "email": "test23@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10024", + "username": "就眠儀式", + "email": "test24@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + } + ] +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/images/avatar.jpg b/demo/thinkphp/frontend/layui_admin_flow/admin/images/avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..206a8b6c2def8679090c377e433a185dc92c501b Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/admin/images/avatar.jpg differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/images/background.svg b/demo/thinkphp/frontend/layui_admin_flow/admin/images/background.svg new file mode 100644 index 0000000000000000000000000000000000000000..1b153e0df5adb683065b92f39a78f1ccc9de7f94 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/admin/images/background.svg @@ -0,0 +1,68 @@ + + + Group 21 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/images/banner.png b/demo/thinkphp/frontend/layui_admin_flow/admin/images/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..a509ca6a55ac9b541d5f43d2a95117487fa5442e Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/admin/images/banner.png differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/images/blog.jpg b/demo/thinkphp/frontend/layui_admin_flow/admin/images/blog.jpg new file mode 100644 index 0000000000000000000000000000000000000000..46eb3da8faccbd3a2d0f025d2e20e5e281ec20d2 Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/admin/images/blog.jpg differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/images/captcha.gif b/demo/thinkphp/frontend/layui_admin_flow/admin/images/captcha.gif new file mode 100644 index 0000000000000000000000000000000000000000..2273bd45ecf14d496c781e8bc8b2442b6b0ecf69 Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/admin/images/captcha.gif differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/admin/images/logo.png b/demo/thinkphp/frontend/layui_admin_flow/admin/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a3dbbf3375012028cee418c22f15249eed58cede Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/admin/images/logo.png differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/layui/css/layui.css b/demo/thinkphp/frontend/layui_admin_flow/component/layui/css/layui.css new file mode 100644 index 0000000000000000000000000000000000000000..c075f1073445cd00f946c981b912d9be8ad6800e --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/layui/css/layui.css @@ -0,0 +1 @@ +blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:active,a:hover{outline:0}img{display:inline-block;border:none;vertical-align:middle}li{list-style:none}table{border-collapse:collapse;border-spacing:0}h1,h2,h3,h4{font-weight:700}h5,h6{font-weight:500;font-size:100%}button,input,select,textarea{font-size:100%}button,input,optgroup,option,select,textarea{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;outline:0}pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}body{line-height:1.6;color:#333;color:rgba(0,0,0,.85);font:14px Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif}hr{height:0;line-height:0;margin:10px 0;padding:0;border:none;border-bottom:1px solid #eee;clear:both;overflow:hidden;background:0 0}a{color:#333;text-decoration:none}a:hover{color:#777}a cite{font-style:normal;*cursor:pointer}.layui-border-box,.layui-border-box *{box-sizing:border-box}.layui-box,.layui-box *{box-sizing:content-box}.layui-clear{clear:both;*zoom:1}.layui-clear:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-clear-space{word-spacing:-5px}.layui-inline{position:relative;display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.layui-edge{position:relative;display:inline-block;vertical-align:middle;width:0;height:0;border-width:6px;border-style:dashed;border-color:transparent;overflow:hidden}.layui-edge-top{top:-4px;border-bottom-color:#999;border-bottom-style:solid}.layui-edge-right{border-left-color:#999;border-left-style:solid}.layui-edge-bottom{top:2px;border-top-color:#999;border-top-style:solid}.layui-edge-left{border-right-color:#999;border-right-style:solid}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-disabled,.layui-icon,.layui-unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-disabled,.layui-disabled:hover{color:#d2d2d2!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-show-v{visibility:visible!important}.layui-hide-v{visibility:hidden!important}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=282);src:url(../font/iconfont.eot?v=282#iefix) format('embedded-opentype'),url(../font/iconfont.woff2?v=282) format('woff2'),url(../font/iconfont.woff?v=282) format('woff'),url(../font/iconfont.ttf?v=282) format('truetype'),url(../font/iconfont.svg?v=282#layui-icon) format('svg')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-icon-leaf:before{content:"\e701"}.layui-icon-folder:before{content:"\eabe"}.layui-icon-folder-open:before{content:"\eac1"}.layui-icon-gitee:before{content:"\e69b"}.layui-icon-github:before{content:"\e6a7"}.layui-icon-disabled:before{content:"\e6cc"}.layui-icon-moon:before{content:"\e6c2"}.layui-icon-error:before{content:"\e693"}.layui-icon-success:before{content:"\e697"}.layui-icon-question:before{content:"\e699"}.layui-icon-lock:before{content:"\e69a"}.layui-icon-eye:before{content:"\e695"}.layui-icon-eye-invisible:before{content:"\e696"}.layui-icon-backspace:before{content:"\e694"}.layui-icon-tips-fill:before{content:"\eb2e"}.layui-icon-test:before{content:"\e692"}.layui-icon-clear:before{content:"\e788"}.layui-icon-heart-fill:before{content:"\e68f"}.layui-icon-light:before{content:"\e748"}.layui-icon-music:before{content:"\e690"}.layui-icon-time:before{content:"\e68d"}.layui-icon-ie:before{content:"\e7bb"}.layui-icon-firefox:before{content:"\e686"}.layui-icon-at:before{content:"\e687"}.layui-icon-bluetooth:before{content:"\e689"}.layui-icon-chrome:before{content:"\e68a"}.layui-icon-edge:before{content:"\e68b"}.layui-icon-heart:before{content:"\e68c"}.layui-icon-key:before{content:"\e683"}.layui-icon-android:before{content:"\e684"}.layui-icon-mike:before{content:"\e6dc"}.layui-icon-mute:before{content:"\e685"}.layui-icon-gift:before{content:"\e627"}.layui-icon-windows:before{content:"\e67f"}.layui-icon-ios:before{content:"\e680"}.layui-icon-logout:before{content:"\e682"}.layui-icon-wifi:before{content:"\e7e0"}.layui-icon-rss:before{content:"\e808"}.layui-icon-email:before{content:"\e618"}.layui-icon-reduce-circle:before{content:"\e616"}.layui-icon-transfer:before{content:"\e691"}.layui-icon-service:before{content:"\e626"}.layui-icon-addition:before{content:"\e624"}.layui-icon-subtraction:before{content:"\e67e"}.layui-icon-slider:before{content:"\e714"}.layui-icon-print:before{content:"\e66d"}.layui-icon-export:before{content:"\e67d"}.layui-icon-cols:before{content:"\e610"}.layui-icon-screen-full:before{content:"\e622"}.layui-icon-screen-restore:before{content:"\e758"}.layui-icon-rate-half:before{content:"\e6c9"}.layui-icon-rate-solid:before{content:"\e67a"}.layui-icon-rate:before{content:"\e67b"}.layui-icon-cellphone:before{content:"\e678"}.layui-icon-vercode:before{content:"\e679"}.layui-icon-login-weibo:before{content:"\e675"}.layui-icon-login-qq:before{content:"\e676"}.layui-icon-login-wechat:before{content:"\e677"}.layui-icon-username:before{content:"\e66f"}.layui-icon-password:before{content:"\e673"}.layui-icon-refresh-3:before{content:"\e9aa"}.layui-icon-auz:before{content:"\e672"}.layui-icon-shrink-right:before{content:"\e668"}.layui-icon-spread-left:before{content:"\e66b"}.layui-icon-snowflake:before{content:"\e6b1"}.layui-icon-tips:before{content:"\e702"}.layui-icon-note:before{content:"\e66e"}.layui-icon-senior:before{content:"\e674"}.layui-icon-refresh-1:before{content:"\e666"}.layui-icon-refresh:before{content:"\e669"}.layui-icon-flag:before{content:"\e66c"}.layui-icon-theme:before{content:"\e66a"}.layui-icon-notice:before{content:"\e667"}.layui-icon-console:before{content:"\e665"}.layui-icon-website:before{content:"\e7ae"}.layui-icon-face-surprised:before{content:"\e664"}.layui-icon-set:before{content:"\e716"}.layui-icon-template:before{content:"\e663"}.layui-icon-app:before{content:"\e653"}.layui-icon-template-1:before{content:"\e656"}.layui-icon-home:before{content:"\e68e"}.layui-icon-female:before{content:"\e661"}.layui-icon-male:before{content:"\e662"}.layui-icon-tread:before{content:"\e6c5"}.layui-icon-praise:before{content:"\e6c6"}.layui-icon-rmb:before{content:"\e65e"}.layui-icon-more:before{content:"\e65f"}.layui-icon-camera:before{content:"\e660"}.layui-icon-cart-simple:before{content:"\e698"}.layui-icon-face-cry:before{content:"\e69c"}.layui-icon-face-smile:before{content:"\e6af"}.layui-icon-survey:before{content:"\e6b2"}.layui-icon-read:before{content:"\e705"}.layui-icon-location:before{content:"\e715"}.layui-icon-dollar:before{content:"\e659"}.layui-icon-diamond:before{content:"\e735"}.layui-icon-return:before{content:"\e65c"}.layui-icon-camera-fill:before{content:"\e65d"}.layui-icon-fire:before{content:"\e756"}.layui-icon-more-vertical:before{content:"\e671"}.layui-icon-cart:before{content:"\e657"}.layui-icon-star-fill:before{content:"\e658"}.layui-icon-prev:before{content:"\e65a"}.layui-icon-next:before{content:"\e65b"}.layui-icon-upload:before{content:"\e67c"}.layui-icon-upload-drag:before{content:"\e681"}.layui-icon-user:before{content:"\e770"}.layui-icon-file-b:before{content:"\e655"}.layui-icon-component:before{content:"\e857"}.layui-icon-find-fill:before{content:"\e670"}.layui-icon-loading:before{content:"\e63d"}.layui-icon-loading-1:before{content:"\e63e"}.layui-icon-add-1:before{content:"\e654"}.layui-icon-pause:before{content:"\e651"}.layui-icon-play:before{content:"\e652"}.layui-icon-video:before{content:"\e6ed"}.layui-icon-headset:before{content:"\e6fc"}.layui-icon-voice:before{content:"\e688"}.layui-icon-speaker:before{content:"\e645"}.layui-icon-fonts-del:before{content:"\e64f"}.layui-icon-fonts-html:before{content:"\e64b"}.layui-icon-fonts-code:before{content:"\e64e"}.layui-icon-fonts-strong:before{content:"\e62b"}.layui-icon-unlink:before{content:"\e64d"}.layui-icon-picture:before{content:"\e64a"}.layui-icon-link:before{content:"\e64c"}.layui-icon-face-smile-b:before{content:"\e650"}.layui-icon-align-center:before{content:"\e647"}.layui-icon-align-right:before{content:"\e648"}.layui-icon-align-left:before{content:"\e649"}.layui-icon-fonts-u:before{content:"\e646"}.layui-icon-fonts-i:before{content:"\e644"}.layui-icon-tabs:before{content:"\e62a"}.layui-icon-circle:before{content:"\e63f"}.layui-icon-radio:before{content:"\e643"}.layui-icon-share:before{content:"\e641"}.layui-icon-edit:before{content:"\e642"}.layui-icon-delete:before{content:"\e640"}.layui-icon-engine:before{content:"\e628"}.layui-icon-chart-screen:before{content:"\e629"}.layui-icon-chart:before{content:"\e62c"}.layui-icon-table:before{content:"\e62d"}.layui-icon-tree:before{content:"\e62e"}.layui-icon-upload-circle:before{content:"\e62f"}.layui-icon-templeate-1:before{content:"\e630"}.layui-icon-util:before{content:"\e631"}.layui-icon-layouts:before{content:"\e632"}.layui-icon-prev-circle:before{content:"\e633"}.layui-icon-carousel:before{content:"\e634"}.layui-icon-code-circle:before{content:"\e635"}.layui-icon-water:before{content:"\e636"}.layui-icon-date:before{content:"\e637"}.layui-icon-layer:before{content:"\e638"}.layui-icon-fonts-clear:before{content:"\e639"}.layui-icon-dialogue:before{content:"\e63a"}.layui-icon-cellphone-fine:before{content:"\e63b"}.layui-icon-form:before{content:"\e63c"}.layui-icon-file:before{content:"\e621"}.layui-icon-triangle-r:before{content:"\e623"}.layui-icon-triangle-d:before{content:"\e625"}.layui-icon-set-sm:before{content:"\e620"}.layui-icon-add-circle:before{content:"\e61f"}.layui-icon-layim-download:before{content:"\e61e"}.layui-icon-layim-uploadfile:before{content:"\e61d"}.layui-icon-404:before{content:"\e61c"}.layui-icon-about:before{content:"\e60b"}.layui-icon-layim-theme:before{content:"\e61b"}.layui-icon-down:before{content:"\e61a"}.layui-icon-up:before{content:"\e619"}.layui-icon-circle-dot:before{content:"\e617"}.layui-icon-set-fill:before{content:"\e614"}.layui-icon-search:before{content:"\e615"}.layui-icon-friends:before{content:"\e612"}.layui-icon-group:before{content:"\e613"}.layui-icon-reply-fill:before{content:"\e611"}.layui-icon-menu-fill:before{content:"\e60f"}.layui-icon-face-smile-fine:before{content:"\e60c"}.layui-icon-picture-fine:before{content:"\e60d"}.layui-icon-log:before{content:"\e60e"}.layui-icon-list:before{content:"\e60a"}.layui-icon-release:before{content:"\e609"}.layui-icon-add-circle-fine:before{content:"\e608"}.layui-icon-ok:before{content:"\e605"}.layui-icon-help:before{content:"\e607"}.layui-icon-chat:before{content:"\e606"}.layui-icon-top:before{content:"\e604"}.layui-icon-right:before{content:"\e602"}.layui-icon-left:before{content:"\e603"}.layui-icon-star:before{content:"\e600"}.layui-icon-download-circle:before{content:"\e601"}.layui-icon-close:before{content:"\1006"}.layui-icon-close-fill:before{content:"\1007"}.layui-icon-ok-circle:before{content:"\1005"}.layui-main{position:relative;width:1160px;margin:0 auto}.layui-header{position:relative;z-index:1000;height:60px}.layui-header a:hover{transition:all .5s;-webkit-transition:all .5s}.layui-side{position:fixed;left:0;top:0;bottom:0;z-index:999;width:200px;overflow-x:hidden}.layui-side-scroll{position:relative;width:220px;height:100%;overflow-x:hidden}.layui-body{position:relative;left:200px;right:0;top:0;bottom:0;z-index:900;width:auto;box-sizing:border-box}.layui-layout-body{overflow-x:hidden}.layui-layout-admin .layui-header{position:fixed;top:0;left:0;right:0;background-color:#23292e}.layui-layout-admin .layui-side{top:60px;width:200px;overflow-x:hidden}.layui-layout-admin .layui-body{position:absolute;top:60px;padding-bottom:44px}.layui-layout-admin .layui-main{width:auto;margin:0 15px}.layui-layout-admin .layui-footer{position:fixed;left:200px;right:0;bottom:0;z-index:990;height:44px;line-height:44px;padding:0 15px;box-shadow:-1px 0 4px rgb(0 0 0 / 12%);background-color:#fafafa}.layui-layout-admin .layui-logo{position:absolute;left:0;top:0;width:200px;height:100%;line-height:60px;text-align:center;color:#16baaa;font-size:16px;box-shadow:0 1px 2px 0 rgb(0 0 0 / 15%)}.layui-layout-admin .layui-header .layui-nav{background:0 0}.layui-layout-left{position:absolute!important;left:200px;top:0}.layui-layout-right{position:absolute!important;right:0;top:0}.layui-container{position:relative;margin:0 auto;box-sizing:border-box}.layui-fluid{position:relative;margin:0 auto;padding:0 15px}.layui-row:after,.layui-row:before{content:"";display:block;clear:both}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9,.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9,.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9,.layui-col-xl1,.layui-col-xl10,.layui-col-xl11,.layui-col-xl12,.layui-col-xl2,.layui-col-xl3,.layui-col-xl4,.layui-col-xl5,.layui-col-xl6,.layui-col-xl7,.layui-col-xl8,.layui-col-xl9,.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{position:relative;display:block;box-sizing:border-box}.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{float:left}.layui-col-xs1{width:8.33333333%}.layui-col-xs2{width:16.66666667%}.layui-col-xs3{width:25%}.layui-col-xs4{width:33.33333333%}.layui-col-xs5{width:41.66666667%}.layui-col-xs6{width:50%}.layui-col-xs7{width:58.33333333%}.layui-col-xs8{width:66.66666667%}.layui-col-xs9{width:75%}.layui-col-xs10{width:83.33333333%}.layui-col-xs11{width:91.66666667%}.layui-col-xs12{width:100%}.layui-col-xs-offset1{margin-left:8.33333333%}.layui-col-xs-offset2{margin-left:16.66666667%}.layui-col-xs-offset3{margin-left:25%}.layui-col-xs-offset4{margin-left:33.33333333%}.layui-col-xs-offset5{margin-left:41.66666667%}.layui-col-xs-offset6{margin-left:50%}.layui-col-xs-offset7{margin-left:58.33333333%}.layui-col-xs-offset8{margin-left:66.66666667%}.layui-col-xs-offset9{margin-left:75%}.layui-col-xs-offset10{margin-left:83.33333333%}.layui-col-xs-offset11{margin-left:91.66666667%}.layui-col-xs-offset12{margin-left:100%}@media screen and (max-width:767.98px){.layui-container{padding:0 15px}.layui-hide-xs{display:none!important}.layui-show-xs-block{display:block!important}.layui-show-xs-inline{display:inline!important}.layui-show-xs-inline-block{display:inline-block!important}}@media screen and (min-width:768px){.layui-container{width:720px}.layui-hide-sm{display:none!important}.layui-show-sm-block{display:block!important}.layui-show-sm-inline{display:inline!important}.layui-show-sm-inline-block{display:inline-block!important}.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9{float:left}.layui-col-sm1{width:8.33333333%}.layui-col-sm2{width:16.66666667%}.layui-col-sm3{width:25%}.layui-col-sm4{width:33.33333333%}.layui-col-sm5{width:41.66666667%}.layui-col-sm6{width:50%}.layui-col-sm7{width:58.33333333%}.layui-col-sm8{width:66.66666667%}.layui-col-sm9{width:75%}.layui-col-sm10{width:83.33333333%}.layui-col-sm11{width:91.66666667%}.layui-col-sm12{width:100%}.layui-col-sm-offset1{margin-left:8.33333333%}.layui-col-sm-offset2{margin-left:16.66666667%}.layui-col-sm-offset3{margin-left:25%}.layui-col-sm-offset4{margin-left:33.33333333%}.layui-col-sm-offset5{margin-left:41.66666667%}.layui-col-sm-offset6{margin-left:50%}.layui-col-sm-offset7{margin-left:58.33333333%}.layui-col-sm-offset8{margin-left:66.66666667%}.layui-col-sm-offset9{margin-left:75%}.layui-col-sm-offset10{margin-left:83.33333333%}.layui-col-sm-offset11{margin-left:91.66666667%}.layui-col-sm-offset12{margin-left:100%}}@media screen and (min-width:992px){.layui-container{width:960px}.layui-hide-md{display:none!important}.layui-show-md-block{display:block!important}.layui-show-md-inline{display:inline!important}.layui-show-md-inline-block{display:inline-block!important}.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9{float:left}.layui-col-md1{width:8.33333333%}.layui-col-md2{width:16.66666667%}.layui-col-md3{width:25%}.layui-col-md4{width:33.33333333%}.layui-col-md5{width:41.66666667%}.layui-col-md6{width:50%}.layui-col-md7{width:58.33333333%}.layui-col-md8{width:66.66666667%}.layui-col-md9{width:75%}.layui-col-md10{width:83.33333333%}.layui-col-md11{width:91.66666667%}.layui-col-md12{width:100%}.layui-col-md-offset1{margin-left:8.33333333%}.layui-col-md-offset2{margin-left:16.66666667%}.layui-col-md-offset3{margin-left:25%}.layui-col-md-offset4{margin-left:33.33333333%}.layui-col-md-offset5{margin-left:41.66666667%}.layui-col-md-offset6{margin-left:50%}.layui-col-md-offset7{margin-left:58.33333333%}.layui-col-md-offset8{margin-left:66.66666667%}.layui-col-md-offset9{margin-left:75%}.layui-col-md-offset10{margin-left:83.33333333%}.layui-col-md-offset11{margin-left:91.66666667%}.layui-col-md-offset12{margin-left:100%}}@media screen and (min-width:1200px){.layui-container{width:1150px}.layui-hide-lg{display:none!important}.layui-show-lg-block{display:block!important}.layui-show-lg-inline{display:inline!important}.layui-show-lg-inline-block{display:inline-block!important}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9{float:left}.layui-col-lg1{width:8.33333333%}.layui-col-lg2{width:16.66666667%}.layui-col-lg3{width:25%}.layui-col-lg4{width:33.33333333%}.layui-col-lg5{width:41.66666667%}.layui-col-lg6{width:50%}.layui-col-lg7{width:58.33333333%}.layui-col-lg8{width:66.66666667%}.layui-col-lg9{width:75%}.layui-col-lg10{width:83.33333333%}.layui-col-lg11{width:91.66666667%}.layui-col-lg12{width:100%}.layui-col-lg-offset1{margin-left:8.33333333%}.layui-col-lg-offset2{margin-left:16.66666667%}.layui-col-lg-offset3{margin-left:25%}.layui-col-lg-offset4{margin-left:33.33333333%}.layui-col-lg-offset5{margin-left:41.66666667%}.layui-col-lg-offset6{margin-left:50%}.layui-col-lg-offset7{margin-left:58.33333333%}.layui-col-lg-offset8{margin-left:66.66666667%}.layui-col-lg-offset9{margin-left:75%}.layui-col-lg-offset10{margin-left:83.33333333%}.layui-col-lg-offset11{margin-left:91.66666667%}.layui-col-lg-offset12{margin-left:100%}}@media screen and (min-width:1400px){.layui-container{width:1330px}.layui-hide-xl{display:none!important}.layui-show-xl-block{display:block!important}.layui-show-xl-inline{display:inline!important}.layui-show-xl-inline-block{display:inline-block!important}.layui-col-xl1,.layui-col-xl10,.layui-col-xl11,.layui-col-xl12,.layui-col-xl2,.layui-col-xl3,.layui-col-xl4,.layui-col-xl5,.layui-col-xl6,.layui-col-xl7,.layui-col-xl8,.layui-col-xl9{float:left}.layui-col-xl1{width:8.33333333%}.layui-col-xl2{width:16.66666667%}.layui-col-xl3{width:25%}.layui-col-xl4{width:33.33333333%}.layui-col-xl5{width:41.66666667%}.layui-col-xl6{width:50%}.layui-col-xl7{width:58.33333333%}.layui-col-xl8{width:66.66666667%}.layui-col-xl9{width:75%}.layui-col-xl10{width:83.33333333%}.layui-col-xl11{width:91.66666667%}.layui-col-xl12{width:100%}.layui-col-xl-offset1{margin-left:8.33333333%}.layui-col-xl-offset2{margin-left:16.66666667%}.layui-col-xl-offset3{margin-left:25%}.layui-col-xl-offset4{margin-left:33.33333333%}.layui-col-xl-offset5{margin-left:41.66666667%}.layui-col-xl-offset6{margin-left:50%}.layui-col-xl-offset7{margin-left:58.33333333%}.layui-col-xl-offset8{margin-left:66.66666667%}.layui-col-xl-offset9{margin-left:75%}.layui-col-xl-offset10{margin-left:83.33333333%}.layui-col-xl-offset11{margin-left:91.66666667%}.layui-col-xl-offset12{margin-left:100%}}.layui-col-space1{margin:-.5px}.layui-col-space1>*{padding:.5px}.layui-col-space2{margin:-1px}.layui-col-space2>*{padding:1px}.layui-col-space4{margin:-2px}.layui-col-space4>*{padding:2px}.layui-col-space5{margin:-2.5px}.layui-col-space5>*{padding:2.5px}.layui-col-space6{margin:-3px}.layui-col-space6>*{padding:3px}.layui-col-space8{margin:-4px}.layui-col-space8>*{padding:4px}.layui-col-space10{margin:-5px}.layui-col-space10>*{padding:5px}.layui-col-space12{margin:-6px}.layui-col-space12>*{padding:6px}.layui-col-space14{margin:-7px}.layui-col-space14>*{padding:7px}.layui-col-space15{margin:-7.5px}.layui-col-space15>*{padding:7.5px}.layui-col-space16{margin:-8px}.layui-col-space16>*{padding:8px}.layui-col-space18{margin:-9px}.layui-col-space18>*{padding:9px}.layui-col-space20{margin:-10px}.layui-col-space20>*{padding:10px}.layui-col-space22{margin:-11px}.layui-col-space22>*{padding:11px}.layui-col-space24{margin:-12px}.layui-col-space24>*{padding:12px}.layui-col-space25{margin:-12.5px}.layui-col-space25>*{padding:12.5px}.layui-col-space26{margin:-13px}.layui-col-space26>*{padding:13px}.layui-col-space28{margin:-14px}.layui-col-space28>*{padding:14px}.layui-col-space30{margin:-15px}.layui-col-space30>*{padding:15px}.layui-col-space32{margin:-16px}.layui-col-space32>*{padding:16px}.layui-padding-1{padding:4px!important}.layui-padding-2{padding:8px!important}.layui-padding-3{padding:16px!important}.layui-padding-4{padding:32px!important}.layui-padding-5{padding:48px!important}.layui-margin-1{margin:4px!important}.layui-margin-2{margin:8px!important}.layui-margin-3{margin:16px!important}.layui-margin-4{margin:32px!important}.layui-margin-5{margin:48px!important}.layui-btn,.layui-input,.layui-select,.layui-textarea,.layui-upload-button{outline:0;-webkit-appearance:none;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-elem-quote{margin-bottom:10px;padding:15px;line-height:1.8;border-left:5px solid #16b777;border-radius:0 2px 2px 0;background-color:#fafafa}.layui-quote-nm{border-style:solid;border-width:1px;border-left-width:5px;background:0 0}.layui-elem-field{margin-bottom:10px;padding:0;border-width:1px;border-style:solid}.layui-elem-field legend{margin-left:20px;padding:0 10px;font-size:20px}.layui-field-title{margin:16px 0;border-width:0;border-top-width:1px}.layui-field-box{padding:15px}.layui-field-title .layui-field-box{padding:10px 0}.layui-progress{position:relative;height:6px;border-radius:20px;background-color:#eee}.layui-progress-bar{position:absolute;left:0;top:0;width:0;max-width:100%;height:6px;border-radius:20px;text-align:right;background-color:#16b777;transition:all .3s;-webkit-transition:all .3s}.layui-progress-big,.layui-progress-big .layui-progress-bar{height:18px;line-height:18px}.layui-progress-text{position:relative;top:-20px;line-height:18px;font-size:12px;color:#5f5f5f}.layui-progress-big .layui-progress-text{position:static;padding:0 10px;color:#fff}.layui-collapse{border-width:1px;border-style:solid;border-radius:2px}.layui-colla-content,.layui-colla-item{border-top-width:1px;border-top-style:solid}.layui-colla-item:first-child{border-top:none}.layui-colla-title{position:relative;height:42px;line-height:42px;padding:0 15px 0 35px;color:#333;background-color:#fafafa;cursor:pointer;font-size:14px;overflow:hidden}.layui-colla-content{display:none;padding:10px 15px;line-height:1.6;color:#5f5f5f}.layui-colla-icon{position:absolute;left:15px;top:0;font-size:14px}.layui-card{margin-bottom:15px;border-radius:2px;background-color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.layui-card:last-child{margin-bottom:0}.layui-card-header{position:relative;height:42px;line-height:42px;padding:0 15px;border-bottom:1px solid #f8f8f8;color:#333;border-radius:2px 2px 0 0;font-size:14px}.layui-card-body{position:relative;padding:10px 15px;line-height:24px}.layui-card-body[pad15]{padding:15px}.layui-card-body[pad20]{padding:20px}.layui-card-body .layui-table{margin:5px 0}.layui-card .layui-tab{margin:0}.layui-panel{position:relative;border-width:1px;border-style:solid;border-radius:2px;box-shadow:1px 1px 4px rgb(0 0 0 / 8%);background-color:#fff;color:#5f5f5f}.layui-panel-window{position:relative;padding:15px;border-radius:0;border-top:5px solid #eee;background-color:#fff}.layui-auxiliar-moving{position:fixed;left:0;right:0;top:0;bottom:0;width:100%;height:100%;background:0 0;z-index:9999999999}.layui-scrollbar-hide{overflow:hidden!important}.layui-bg-red{background-color:#ff5722!important;color:#fff!important}.layui-bg-orange{background-color:#ffb800!important;color:#fff!important}.layui-bg-green{background-color:#16baaa!important;color:#fff!important}.layui-bg-cyan{background-color:#2f4056!important;color:#fff!important}.layui-bg-blue{background-color:#1e9fff!important;color:#fff!important}.layui-bg-purple{background-color:#a233c6!important;color:#fff!important}.layui-bg-black{background-color:#2f363c!important;color:#fff!important}.layui-bg-gray{background-color:#fafafa!important;color:#5f5f5f!important}.layui-badge-rim,.layui-border,.layui-colla-content,.layui-colla-item,.layui-collapse,.layui-elem-field,.layui-form-pane .layui-form-item[pane],.layui-form-pane .layui-form-label,.layui-input,.layui-input-split,.layui-panel,.layui-quote-nm,.layui-select,.layui-tab-bar,.layui-tab-card,.layui-tab-title,.layui-tab-title .layui-this:after,.layui-textarea{border-color:#eee}.layui-border{border-width:1px;border-style:solid;color:#5f5f5f!important}.layui-border-red{border-width:1px;border-style:solid;border-color:#ff5722!important;color:#ff5722!important}.layui-border-orange{border-width:1px;border-style:solid;border-color:#ffb800!important;color:#ffb800!important}.layui-border-green{border-width:1px;border-style:solid;border-color:#16baaa!important;color:#16baaa!important}.layui-border-cyan{border-width:1px;border-style:solid;border-color:#2f4056!important;color:#2f4056!important}.layui-border-blue{border-width:1px;border-style:solid;border-color:#1e9fff!important;color:#1e9fff!important}.layui-border-purple{border-width:1px;border-style:solid;border-color:#a233c6!important;color:#a233c6!important}.layui-border-black{border-width:1px;border-style:solid;border-color:#2f363c!important;color:#2f363c!important}hr.layui-border-black,hr.layui-border-blue,hr.layui-border-cyan,hr.layui-border-green,hr.layui-border-orange,hr.layui-border-purple,hr.layui-border-red{border-width:0 0 1px}.layui-timeline-item:before{background-color:#eee}.layui-text{line-height:1.8;font-size:14px}.layui-text h1,.layui-text h2,.layui-text h3,.layui-text h4,.layui-text h5,.layui-text h6{color:#3a3a3a}.layui-text h1{font-size:32px}.layui-text h2{font-size:24px}.layui-text h3{font-size:18px}.layui-text h4{font-size:16px}.layui-text h5{font-size:14px}.layui-text h6{font-size:13px}.layui-text ol,.layui-text ul{padding-left:15px}.layui-text ul li{margin-top:5px;list-style-type:disc}.layui-text ol li{margin-top:5px;list-style-type:decimal}.layui-text-em,.layui-word-aux{color:#999!important;padding-left:5px!important;padding-right:5px!important}.layui-text p{margin:15px 0}.layui-text p:first-child{margin-top:0}.layui-text p:last-child{margin-bottom:0}.layui-text a:not(.layui-btn){color:#01aaed}.layui-text a:not(.layui-btn):hover{text-decoration:underline}.layui-text blockquote:not(.layui-elem-quote){padding:5px 15px;border-left:5px solid #eee}.layui-text pre>code:not(.layui-code){padding:15px;font-family:"Courier New",Consolas,"Lucida Console"}.layui-font-12{font-size:12px!important}.layui-font-13{font-size:13px!important}.layui-font-14{font-size:14px!important}.layui-font-16{font-size:16px!important}.layui-font-18{font-size:18px!important}.layui-font-20{font-size:20px!important}.layui-font-22{font-size:22px!important}.layui-font-24{font-size:24px!important}.layui-font-26{font-size:26px!important}.layui-font-28{font-size:28px!important}.layui-font-30{font-size:30px!important}.layui-font-32{font-size:32px!important}.layui-font-red{color:#ff5722!important}.layui-font-orange{color:#ffb800!important}.layui-font-green{color:#16baaa!important}.layui-font-cyan{color:#2f4056!important}.layui-font-blue{color:#01aaed!important}.layui-font-purple{color:#a233c6!important}.layui-font-black{color:#000!important}.layui-font-gray{color:#c2c2c2!important}.layui-btn{display:inline-block;vertical-align:middle;height:38px;line-height:38px;border:1px solid transparent;padding:0 18px;background-color:#16baaa;color:#fff;white-space:nowrap;text-align:center;font-size:14px;border-radius:2px;cursor:pointer;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-btn:hover{opacity:.8;filter:alpha(opacity=80);color:#fff}.layui-btn:active{opacity:1;filter:alpha(opacity=100)}.layui-btn+.layui-btn{margin-left:10px}.layui-btn-container{word-spacing:-5px}.layui-btn-container .layui-btn{margin-right:10px;margin-bottom:10px;word-spacing:normal}.layui-btn-container .layui-btn+.layui-btn{margin-left:0}.layui-table .layui-btn-container .layui-btn{margin-bottom:9px}.layui-btn-radius{border-radius:100px}.layui-btn .layui-icon{padding:0 2px;vertical-align:middle\0;vertical-align:bottom}.layui-btn-primary{border-color:#d2d2d2;background:0 0;color:#5f5f5f}.layui-btn-primary:hover{border-color:#16baaa;color:#333}.layui-btn-normal{background-color:#1e9fff}.layui-btn-warm{background-color:#ffb800}.layui-btn-danger{background-color:#ff5722}.layui-btn-checked{background-color:#16b777}.layui-btn-disabled,.layui-btn-disabled:active,.layui-btn-disabled:hover{border-color:#eee!important;background-color:#fbfbfb!important;color:#d2d2d2!important;cursor:not-allowed!important;opacity:1}.layui-btn-lg{height:44px;line-height:44px;padding:0 25px;font-size:16px}.layui-btn-sm{height:30px;line-height:30px;padding:0 10px;font-size:12px}.layui-btn-xs{height:22px;line-height:22px;padding:0 5px;font-size:12px}.layui-btn-xs i{font-size:12px!important}.layui-btn-group{display:inline-block;vertical-align:middle;font-size:0}.layui-btn-group .layui-btn{margin-left:0!important;margin-right:0!important;border-left:1px solid rgba(255,255,255,.5);border-radius:0}.layui-btn-group .layui-btn-primary{border-left:none}.layui-btn-group .layui-btn-primary:hover{border-color:#d2d2d2;color:#16baaa}.layui-btn-group .layui-btn:first-child{border-left:none;border-radius:2px 0 0 2px}.layui-btn-group .layui-btn-primary:first-child{border-left:1px solid #d2d2d2}.layui-btn-group .layui-btn:last-child{border-radius:0 2px 2px 0}.layui-btn-group .layui-btn+.layui-btn{margin-left:0}.layui-btn-group+.layui-btn-group{margin-left:10px}.layui-btn-fluid{width:100%}.layui-input,.layui-select,.layui-textarea{height:38px;line-height:1.3;line-height:38px\9;border-width:1px;border-style:solid;background-color:#fff;color:rgba(0,0,0,.85);border-radius:2px}.layui-input::-webkit-input-placeholder,.layui-select::-webkit-input-placeholder,.layui-textarea::-webkit-input-placeholder{line-height:1.3}.layui-input,.layui-textarea{display:block;width:100%;padding-left:10px}.layui-input:hover,.layui-textarea:hover{border-color:#d2d2d2!important}.layui-input:focus,.layui-textarea:focus{border-color:#16b777!important;box-shadow:0 0 0 3px rgba(22,183,119,.08)}.layui-textarea{position:relative;min-height:100px;height:auto;line-height:20px;padding:6px 10px;resize:vertical}.layui-input[disabled],.layui-textarea[disabled]{background-color:#fafafa}.layui-select{padding:0 10px}.layui-form input[type=checkbox],.layui-form input[type=radio],.layui-form select{display:none}.layui-form [lay-ignore]{display:initial}.layui-form-item{position:relative;margin-bottom:15px;clear:both;*zoom:1}.layui-form-item:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-form-label{position:relative;float:left;display:block;padding:9px 15px;width:80px;font-weight:400;line-height:20px;text-align:right}.layui-form-label-col{display:block;float:none;padding:9px 0;line-height:20px;text-align:left}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block,.layui-input-inline{position:relative}.layui-input-block{margin-left:110px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{position:relative;float:left;display:block;padding:9px 0!important;line-height:20px;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border-color:#ff5722!important;box-shadow:0 0 0 3px rgba(255,87,34,.08)}.layui-input-prefix,.layui-input-split,.layui-input-suffix,.layui-input-suffix .layui-input-affix{position:absolute;right:0;top:0;padding:0 10px;width:35px;height:100%;text-align:center;transition:all .3s;box-sizing:border-box}.layui-input-prefix{left:0;border-radius:2px 0 0 2px}.layui-input-suffix{right:0;border-radius:0 2px 2px 0}.layui-input-split{border-width:1px;border-style:solid}.layui-input-prefix .layui-icon,.layui-input-split .layui-icon,.layui-input-suffix .layui-icon{position:relative;font-size:16px;color:#5f5f5f;transition:all .3s}.layui-input-group{position:relative;display:table;box-sizing:border-box}.layui-input-group>*{display:table-cell;vertical-align:middle;position:relative}.layui-input-group .layui-input{padding-right:15px}.layui-input-group>.layui-input-prefix{width:auto;border-right:0}.layui-input-group>.layui-input-suffix{width:auto;border-left:0}.layui-input-group .layui-input-split{white-space:nowrap}.layui-input-wrap{position:relative;line-height:38px}.layui-input-wrap .layui-input{padding-right:35px}.layui-input-wrap .layui-input::-ms-clear,.layui-input-wrap .layui-input::-ms-reveal{display:none}.layui-input-wrap .layui-input-prefix+.layui-input,.layui-input-wrap .layui-input-prefix~* .layui-input{padding-left:35px}.layui-input-wrap .layui-input-split+.layui-input,.layui-input-wrap .layui-input-split~* .layui-input{padding-left:45px}.layui-input-wrap .layui-input-prefix~.layui-form-select{position:static}.layui-input-wrap .layui-input-prefix,.layui-input-wrap .layui-input-split,.layui-input-wrap .layui-input-suffix{pointer-events:none}.layui-input-wrap .layui-input:hover+.layui-input-split{border-color:#d2d2d2}.layui-input-wrap .layui-input:focus+.layui-input-split{border-color:#16b777}.layui-input-wrap .layui-input.layui-form-danger:focus+.layui-input-split{border-color:#ff5722}.layui-input-wrap .layui-input-prefix.layui-input-split{border-width:0;border-right-width:1px}.layui-input-affix{line-height:38px}.layui-input-suffix .layui-input-affix{right:auto;left:-35px}.layui-input-affix .layui-icon{color:rgba(0,0,0,.8);pointer-events:auto!important;cursor:pointer}.layui-input-affix .layui-icon-clear{color:rgba(0,0,0,.3)}.layui-input-affix .layui-icon:hover{color:rgba(0,0,0,.6)}.layui-input-wrap .layui-input-number{width:24px;padding:0}.layui-input-wrap .layui-input-number .layui-icon{position:absolute;right:0;width:100%;height:50%;line-height:normal;font-size:12px}.layui-input-wrap .layui-input-number .layui-icon:before{position:absolute;left:50%;top:50%;margin-top:-6px;margin-left:-6px}.layui-input-wrap .layui-input-number .layui-icon-up{top:0;border-bottom:1px solid #eee}.layui-input-wrap .layui-input-number .layui-icon-down{bottom:0}.layui-input-wrap .layui-input-number .layui-icon:hover{font-weight:700}.layui-input-wrap .layui-input[type=number]::-webkit-inner-spin-button,.layui-input-wrap .layui-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none!important}.layui-input-wrap .layui-input[type=number]{-moz-appearance:textfield}.layui-input-wrap .layui-input[type=number].layui-input-number-out-of-range{color:#ff5722}.layui-form-select{position:relative;color:#5f5f5f}.layui-form-select .layui-input{padding-right:30px;cursor:pointer}.layui-form-select .layui-edge{position:absolute;right:10px;top:50%;margin-top:-3px;cursor:pointer;border-width:6px;border-top-color:#c2c2c2;border-top-style:solid;transition:all .3s;-webkit-transition:all .3s}.layui-form-select dl{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #eee;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:1px 1px 4px rgb(0 0 0 / 8%);box-sizing:border-box}.layui-form-select dl dd,.layui-form-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-form-select dl dt{font-size:12px;color:#999}.layui-form-select dl dd{cursor:pointer}.layui-form-select dl dd:hover{background-color:#f8f8f8;-webkit-transition:.5s all;transition:.5s all}.layui-form-select .layui-select-group dd{padding-left:20px}.layui-form-select dl dd.layui-select-tips{padding-left:10px!important;color:#999}.layui-form-select dl dd.layui-this{background-color:#f8f8f8;color:#16b777;font-weight:700}.layui-form-select dl dd.layui-disabled{background-color:#fff}.layui-form-selected dl{display:block}.layui-form-selected .layui-edge{margin-top:-9px;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.layui-form-selected .layui-edge{margin-top:-3px\0}:root .layui-form-selected .layui-edge{margin-top:-9px\0/IE9}.layui-form-selectup dl{top:auto;bottom:42px}.layui-select-none{margin:5px 0;text-align:center;color:#999}.layui-select-disabled .layui-disabled{border-color:#eee!important}.layui-select-disabled .layui-edge{border-top-color:#d2d2d2}.layui-form-checkbox{position:relative;display:inline-block;vertical-align:middle;height:30px;line-height:30px;margin-right:10px;padding-right:30px;background-color:#fff;cursor:pointer;font-size:0;-webkit-transition:.1s linear;transition:.1s linear;box-sizing:border-box}.layui-form-checkbox>*{display:inline-block;vertical-align:middle}.layui-form-checkbox>div{padding:0 11px;font-size:14px;border-radius:2px 0 0 2px;background-color:#d2d2d2;color:#fff;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.layui-form-checkbox>div>.layui-icon{line-height:normal}.layui-form-checkbox:hover>div{background-color:#c2c2c2}.layui-form-checkbox>i{position:absolute;right:0;top:0;width:30px;height:100%;border:1px solid #d2d2d2;border-left:none;border-radius:0 2px 2px 0;color:#fff;color:rgba(255,255,255,0);font-size:20px;text-align:center;box-sizing:border-box}.layui-form-checkbox:hover>i{border-color:#c2c2c2;color:#c2c2c2}.layui-form-checked,.layui-form-checked:hover{border-color:#16b777}.layui-form-checked:hover>div,.layui-form-checked>div{background-color:#16b777}.layui-form-checked:hover>i,.layui-form-checked>i{color:#16b777}.layui-form-item .layui-form-checkbox{margin-top:4px}.layui-form-checkbox.layui-checkbox-disabled>div{background-color:#eee!important}.layui-form [lay-checkbox]{display:none}.layui-form-checkbox[lay-skin=primary]{height:auto!important;line-height:normal!important;min-width:18px;min-height:18px;border:none!important;margin-right:0;padding-left:24px;padding-right:0;background:0 0}.layui-form-checkbox[lay-skin=primary]>div{margin-top:-1px;padding-left:0;padding-right:15px;line-height:18px;background:0 0;color:#5f5f5f}.layui-form-checkbox[lay-skin=primary]>i{right:auto;left:0;width:16px;height:16px;line-height:14px;border:1px solid #d2d2d2;font-size:12px;border-radius:2px;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-checkbox[lay-skin=primary]:hover>i{border-color:#16b777;color:#fff}.layui-form-checked[lay-skin=primary]>i{border-color:#16b777!important;background-color:#16b777;color:#fff}.layui-checkbox-disabled[lay-skin=primary]>div{background:0 0!important}.layui-form-checked.layui-checkbox-disabled[lay-skin=primary]>i{background:#eee!important;border-color:#eee!important}.layui-checkbox-disabled[lay-skin=primary]:hover>i{border-color:#d2d2d2}.layui-form-item .layui-form-checkbox[lay-skin=primary]{margin-top:10px}.layui-form-checkbox[lay-skin=primary]>.layui-icon-indeterminate{border-color:#16b777}.layui-form-checkbox[lay-skin=primary]>.layui-icon-indeterminate:before{content:'';display:inline-block;vertical-align:middle;position:relative;width:50%;height:1px;margin:-1px auto 0;background-color:#16b777}.layui-form-switch{position:relative;display:inline-block;vertical-align:middle;height:24px;line-height:22px;min-width:44px;padding:0 5px;margin-top:8px;border:1px solid #d2d2d2;border-radius:20px;cursor:pointer;box-sizing:border-box;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch>i{position:absolute;left:5px;top:3px;width:16px;height:16px;border-radius:20px;background-color:#d2d2d2;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch>div{position:relative;top:0;margin-left:21px;padding:0!important;text-align:center!important;color:#999!important;font-style:normal!important;font-size:12px}.layui-form-onswitch{border-color:#16b777;background-color:#16b777}.layui-form-onswitch>i{left:100%;margin-left:-21px;background-color:#fff}.layui-form-onswitch>div{margin-left:0;margin-right:21px;color:#fff!important}.layui-checkbox-disabled{border-color:#eee!important}.layui-checkbox-disabled>div{color:#c2c2c2!important}.layui-checkbox-disabled>i{border-color:#eee!important}.layui-checkbox-disabled:hover>i{color:#fff!important}.layui-form-radio{display:inline-block;vertical-align:middle;line-height:28px;margin:6px 10px 0 0;padding-right:10px;cursor:pointer;font-size:0}.layui-form-radio>*{display:inline-block;vertical-align:middle;font-size:14px}.layui-form-radio>i{margin-right:8px;font-size:22px;color:#c2c2c2}.layui-form-radio:hover>*,.layui-form-radioed,.layui-form-radioed>i{color:#16b777}.layui-radio-disabled>i{color:#eee!important}.layui-radio-disabled>*{color:#c2c2c2!important}.layui-form [lay-radio]{display:none}.layui-form-pane .layui-form-label{width:110px;padding:8px 15px;height:38px;line-height:20px;border-width:1px;border-style:solid;border-radius:2px 0 0 2px;text-align:center;background-color:#fafafa;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;box-sizing:border-box}.layui-form-pane .layui-input-inline{margin-left:-1px}.layui-form-pane .layui-input-block{margin-left:110px;left:-1px}.layui-form-pane .layui-input{border-radius:0 2px 2px 0}.layui-form-pane .layui-form-text .layui-form-label{float:none;width:100%;border-radius:2px;box-sizing:border-box;text-align:left}.layui-form-pane .layui-form-text .layui-input-inline{display:block;margin:0;top:-1px;clear:both}.layui-form-pane .layui-form-text .layui-input-block{margin:0;left:0;top:-1px}.layui-form-pane .layui-form-text .layui-textarea{min-height:100px;border-radius:0 0 2px 2px}.layui-form-pane .layui-form-checkbox{margin:4px 0 4px 10px}.layui-form-pane .layui-form-radio,.layui-form-pane .layui-form-switch{margin-top:6px;margin-left:10px}.layui-form-pane .layui-form-item[pane]{position:relative;border-width:1px;border-style:solid}.layui-form-pane .layui-form-item[pane] .layui-form-label{position:absolute;left:0;top:0;height:100%;border-width:0;border-right-width:1px}.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left:110px}@media screen and (max-width:450px){.layui-form-item .layui-form-label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-form-item .layui-inline{display:block;margin-right:0;margin-bottom:20px;clear:both}.layui-form-item .layui-inline:after{content:'\20';clear:both;display:block;height:0}.layui-form-item .layui-input-inline{display:block;float:none;left:-3px;width:auto!important;margin:0 0 10px 112px}.layui-form-item .layui-input-inline+.layui-form-mid{margin-left:110px;top:-5px;padding:0}.layui-form-item .layui-form-checkbox{margin-right:5px;margin-bottom:5px}}.layui-laypage{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;margin:10px 0;font-size:0}.layui-laypage>a:first-child,.layui-laypage>a:first-child em{border-radius:2px 0 0 2px}.layui-laypage>a:last-child,.layui-laypage>a:last-child em{border-radius:0 2px 2px 0}.layui-laypage>:first-child{margin-left:0!important}.layui-laypage>:last-child{margin-right:0!important}.layui-laypage a,.layui-laypage button,.layui-laypage input,.layui-laypage select,.layui-laypage span{border:1px solid #eee}.layui-laypage a,.layui-laypage span{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding:0 15px;height:28px;line-height:28px;margin:0 -1px 5px 0;background-color:#fff;color:#333;font-size:12px}.layui-laypage a[data-page]{color:#333}.layui-laypage a{text-decoration:none!important;cursor:pointer}.layui-laypage a:hover{color:#16baaa}.layui-laypage em{font-style:normal}.layui-laypage .layui-laypage-spr{color:#999;font-weight:700}.layui-laypage .layui-laypage-curr{position:relative}.layui-laypage .layui-laypage-curr em{position:relative;color:#fff}.layui-laypage .layui-laypage-curr .layui-laypage-em{position:absolute;left:-1px;top:-1px;padding:1px;width:100%;height:100%;background-color:#16baaa}.layui-laypage-em{border-radius:2px}.layui-laypage-next em,.layui-laypage-prev em{font-family:Sim sun;font-size:16px}.layui-laypage .layui-laypage-count,.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh,.layui-laypage .layui-laypage-skip{margin-left:10px;margin-right:10px;padding:0;border:none}.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh{vertical-align:top}.layui-laypage .layui-laypage-refresh i{font-size:18px;cursor:pointer}.layui-laypage select{height:22px;padding:3px;border-radius:2px;cursor:pointer}.layui-laypage .layui-laypage-skip{height:30px;line-height:30px;color:#999}.layui-laypage button,.layui-laypage input{height:30px;line-height:30px;border-radius:2px;vertical-align:top;background-color:#fff;box-sizing:border-box}.layui-laypage input{display:inline-block;width:40px;margin:0 10px;padding:0 3px;text-align:center}.layui-laypage input:focus,.layui-laypage select:focus{border-color:#16baaa!important}.layui-laypage button{margin-left:10px;padding:0 10px;cursor:pointer}.layui-flow-more{margin:10px 0;text-align:center;color:#999;font-size:14px;clear:both}.layui-flow-more a{height:32px;line-height:32px}.layui-flow-more a *{display:inline-block;vertical-align:top}.layui-flow-more a cite{padding:0 20px;border-radius:3px;background-color:#eee;color:#333;font-style:normal}.layui-flow-more a cite:hover{opacity:.8}.layui-flow-more a i{font-size:30px;color:#737383}.layui-table{width:100%;margin:10px 0;background-color:#fff;color:#5f5f5f}.layui-table tr{transition:all .3s;-webkit-transition:all .3s}.layui-table th{text-align:left;font-weight:600}.layui-table-mend{background-color:#fff}.layui-table-click,.layui-table-hover,.layui-table[lay-even] tbody tr:nth-child(even){background-color:#f8f8f8}.layui-table-checked{background-color:#dbfbf0}.layui-table-checked.layui-table-click,.layui-table-checked.layui-table-hover{background-color:#abf8dd}.layui-table td,.layui-table th,.layui-table-col-set,.layui-table-fixed-r,.layui-table-grid-down,.layui-table-header,.layui-table-mend,.layui-table-page,.layui-table-tips-main,.layui-table-tool,.layui-table-total,.layui-table-view,.layui-table[lay-skin=line],.layui-table[lay-skin=row]{border-width:1px;border-style:solid;border-color:#eee}.layui-table td,.layui-table th{position:relative;padding:9px 15px;min-height:20px;line-height:20px;font-size:14px}.layui-table[lay-skin=line] td,.layui-table[lay-skin=line] th{border-width:0;border-bottom-width:1px}.layui-table[lay-skin=row] td,.layui-table[lay-skin=row] th{border-width:0;border-right-width:1px}.layui-table[lay-skin=nob] td,.layui-table[lay-skin=nob] th{border:none}.layui-table img{max-width:100px}.layui-table[lay-size=lg] td,.layui-table[lay-size=lg] th{padding-top:15px;padding-right:30px;padding-bottom:15px;padding-left:30px}.layui-table-view .layui-table[lay-size=lg] .layui-table-cell{height:50px;line-height:40px}.layui-table[lay-size=sm] td,.layui-table[lay-size=sm] th{padding-top:5px;padding-right:10px;padding-bottom:5px;padding-left:10px;font-size:12px}.layui-table-view .layui-table[lay-size=sm] .layui-table-cell{height:30px;line-height:20px;padding-top:5px;padding-left:11px;padding-right:11px}.layui-table[lay-data],.layui-table[lay-options]{display:none}.layui-table-box{position:relative;overflow:hidden}.layui-table-view{clear:both}.layui-table-view .layui-table{position:relative;width:auto;margin:0;border:0;border-collapse:separate}.layui-table-view .layui-table[lay-skin=line]{border-width:0;border-right-width:1px}.layui-table-view .layui-table[lay-skin=row]{border-width:0;border-bottom-width:1px}.layui-table-view .layui-table td,.layui-table-view .layui-table th{padding:0;border-top:none;border-left:none}.layui-table-view .layui-table th [lay-event],.layui-table-view .layui-table th.layui-unselect .layui-table-cell span{cursor:pointer}.layui-table-view .layui-table td,.layui-table-view .layui-table th span{cursor:default}.layui-table-view .layui-table td[data-edit]{cursor:text}.layui-table-view .layui-table td[data-edit]:hover:after{position:absolute;left:0;top:0;width:100%;height:100%;box-sizing:border-box;border:1px solid #16b777;pointer-events:none;content:""}.layui-table-view .layui-form-checkbox[lay-skin=primary] i{width:18px;height:18px;line-height:16px}.layui-table-view .layui-form-radio{line-height:0;padding:0}.layui-table-view .layui-form-radio>i{margin:0;font-size:20px}.layui-table-init{position:absolute;left:0;top:0;width:100%;height:100%;text-align:center;z-index:199}.layui-table-init .layui-icon{position:absolute;left:50%;top:50%;margin:-15px 0 0 -15px;font-size:30px;color:#c2c2c2}.layui-table-header{border-width:0;border-bottom-width:1px;overflow:hidden}.layui-table-header .layui-table{margin-bottom:-1px}.layui-table-column{position:relative;width:100%;min-height:41px;padding:8px 16px;border-width:0;border-bottom-width:1px}.layui-table-column .layui-btn-container{margin-bottom:-8px}.layui-table-column .layui-btn-container .layui-btn{margin-right:8px;margin-bottom:8px}.layui-table-tool .layui-inline[lay-event]{position:relative;width:26px;height:26px;padding:5px;line-height:16px;margin-right:10px;text-align:center;color:#333;border:1px solid #ccc;cursor:pointer;-webkit-transition:.5s all;transition:.5s all}.layui-table-tool .layui-inline[lay-event]:hover{border:1px solid #999}.layui-table-tool-temp{padding-right:120px}.layui-table-tool-self{position:absolute;right:17px;top:10px}.layui-table-tool .layui-table-tool-self .layui-inline[lay-event]{margin:0 0 0 10px}.layui-table-tool-panel{position:absolute;top:29px;left:-1px;z-index:399;padding:5px 0!important;min-width:150px;min-height:40px;border:1px solid #d2d2d2;text-align:left;overflow-y:auto;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-table-tool-panel li{padding:0 10px;margin:0!important;line-height:30px;list-style-type:none!important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-transition:.5s all;transition:.5s all}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary]{width:100%}.layui-table-tool-panel li:hover{background-color:#f8f8f8}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary]{padding-left:28px}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] i{position:absolute;left:0;top:0}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] span{padding:0}.layui-table-tool .layui-table-tool-self .layui-table-tool-panel{left:auto;right:-1px}.layui-table-col-set{position:absolute;right:0;top:0;width:20px;height:100%;border-width:0;border-left-width:1px;background-color:#fff}.layui-table-sort{width:10px;height:20px;margin-left:5px;cursor:pointer!important}.layui-table-sort .layui-edge{position:absolute;left:5px;border-width:5px}.layui-table-sort .layui-table-sort-asc{top:3px;border-top:none;border-bottom-style:solid;border-bottom-color:#b2b2b2}.layui-table-sort .layui-table-sort-asc:hover{border-bottom-color:#5f5f5f}.layui-table-sort .layui-table-sort-desc{bottom:5px;border-bottom:none;border-top-style:solid;border-top-color:#b2b2b2}.layui-table-sort .layui-table-sort-desc:hover{border-top-color:#5f5f5f}.layui-table-sort[lay-sort=asc] .layui-table-sort-asc{border-bottom-color:#000}.layui-table-sort[lay-sort=desc] .layui-table-sort-desc{border-top-color:#000}.layui-table-cell{height:38px;line-height:28px;padding:6px 15px;position:relative;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;box-sizing:border-box}.layui-table-cell .layui-form-checkbox[lay-skin=primary]{top:-1px;padding:0}.layui-table-cell .layui-form-checkbox[lay-skin=primary]>div{padding-left:24px}.layui-table-cell .layui-table-link{color:#01aaed}.layui-table-cell .layui-btn{vertical-align:inherit}.layui-table-cell[align=center]{-webkit-box-pack:center}.layui-table-cell[align=right]{-webkit-box-pack:end}.laytable-cell-checkbox,.laytable-cell-numbers,.laytable-cell-radio,.laytable-cell-space{text-align:center;-webkit-box-pack:center}.layui-table-body{position:relative;overflow:auto;margin-right:-1px;margin-bottom:-1px}.layui-table-body .layui-none{line-height:26px;padding:30px 15px;text-align:center;color:#999}.layui-table-fixed{position:absolute;left:0;top:0;z-index:101}.layui-table-fixed .layui-table-body{overflow:hidden}.layui-table-fixed-l{box-shadow:1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r{left:auto;right:-1px;border-width:0;border-left-width:1px;box-shadow:-1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r .layui-table-header{position:relative;overflow:visible}.layui-table-mend{position:absolute;right:-49px;top:0;height:100%;width:50px;border-width:0;border-left-width:1px}.layui-table-tool{position:relative;width:100%;min-height:50px;line-height:30px;padding:10px 15px;border-width:0;border-bottom-width:1px}.layui-table-tool .layui-btn-container{margin-bottom:-10px}.layui-table-total{margin-bottom:-1px;border-width:0;border-top-width:1px;overflow:hidden}.layui-table-page{border-width:0;border-top-width:1px;margin-bottom:-1px;white-space:nowrap;overflow:hidden}.layui-table-page>div{height:26px}.layui-table-page .layui-laypage{margin:0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span{height:26px;line-height:26px;margin-bottom:10px;border:none;background:0 0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span.layui-laypage-curr{padding:0 12px}.layui-table-page .layui-laypage span{margin-left:0;padding:0}.layui-table-page .layui-laypage .layui-laypage-prev{margin-left:-11px!important}.layui-table-page .layui-laypage .layui-laypage-curr .layui-laypage-em{left:0;top:0;padding:0}.layui-table-page .layui-laypage button,.layui-table-page .layui-laypage input{height:26px;line-height:26px}.layui-table-page .layui-laypage input{width:40px}.layui-table-page .layui-laypage button{padding:0 10px}.layui-table-page select{height:18px}.layui-table-pagebar{float:right;line-height:23px}.layui-table-pagebar .layui-btn-sm{margin-top:-1px}.layui-table-pagebar .layui-btn-xs{margin-top:2px}.layui-table-view select[lay-ignore]{display:inline-block}.layui-table-patch .layui-table-cell{padding:0;width:30px}.layui-table-edit{position:absolute;left:0;top:0;z-index:189;min-width:100%;min-height:100%;padding:5px 14px;border-radius:0;box-shadow:1px 1px 20px rgba(0,0,0,.15);background-color:#fff}.layui-table-edit:focus{border-color:#16b777!important}input.layui-input.layui-table-edit{height:100%}select.layui-table-edit{padding:0 0 0 10px;border-color:#d2d2d2}.layui-table-view .layui-form-checkbox,.layui-table-view .layui-form-radio,.layui-table-view .layui-form-switch{top:0;margin:0}.layui-table-view .layui-form-checkbox{top:-1px;height:26px;line-height:26px}.layui-table-view .layui-form-checkbox i{height:26px}.layui-table-grid .layui-table-cell{overflow:visible}.layui-table-grid-down{position:absolute;top:0;right:0;width:24px;height:100%;padding:5px 0;border-width:0;border-left-width:1px;text-align:center;background-color:#fff;color:#999;cursor:pointer}.layui-table-grid-down .layui-icon{position:absolute;top:50%;left:50%;margin:-8px 0 0 -8px;font-size:14px}.layui-table-grid-down:hover{background-color:#fbfbfb}.layui-table-expanded{height:95px}.layui-table-expanded .layui-table-cell,.layui-table-view .layui-table[lay-size=lg] .layui-table-expanded .layui-table-cell,.layui-table-view .layui-table[lay-size=sm] .layui-table-expanded .layui-table-cell{height:auto;max-height:94px;white-space:normal;text-overflow:clip}.layui-table-cell-c{position:absolute;bottom:-10px;right:50%;margin-right:-9px;width:20px;height:20px;line-height:18px;cursor:pointer;text-align:center;background-color:#fff;border:1px solid #eee;border-radius:50%;z-index:1000;transition:.3s all;font-size:14px}.layui-table-cell-c:hover{border-color:#16b777}.layui-table-expanded td:hover .layui-table-cell{overflow:auto}.layui-table-main>.layui-table>tbody>tr:last-child>td>.layui-table-cell-c{bottom:0}body .layui-table-tips .layui-layer-content{background:0 0;padding:0;box-shadow:0 1px 6px rgba(0,0,0,.12)}.layui-table-tips-main{margin:-49px 0 0 -1px;max-height:150px;padding:8px 15px;font-size:14px;overflow-y:scroll;background-color:#fff;color:#5f5f5f}.layui-table-tips-c{position:absolute;right:-3px;top:-13px;width:20px;height:20px;padding:3px;cursor:pointer;background-color:#5f5f5f;border-radius:50%;color:#fff}.layui-table-tips-c:hover{background-color:#777}.layui-table-tips-c:before{position:relative;right:-2px}.layui-table-tree-nodeIcon{max-width:20px}.layui-table-tree-nodeIcon>*{width:100%}.layui-table-tree-flexIcon,.layui-table-tree-nodeIcon{margin-right:2px}.layui-table-tree-flexIcon{cursor:pointer}.layui-upload-file{display:none!important;opacity:.01;filter:Alpha(opacity=1)}.layui-upload-list{margin:11px 0}.layui-upload-choose{max-width:200px;padding:0 10px;color:#999;font-size:14px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-upload-drag{position:relative;display:inline-block;padding:30px;border:1px dashed #e2e2e2;background-color:#fff;text-align:center;cursor:pointer;color:#999}.layui-upload-drag .layui-icon{font-size:50px;color:#16baaa}.layui-upload-drag[lay-over]{border-color:#16baaa}.layui-upload-form{display:inline-block}.layui-upload-iframe{position:absolute;width:0;height:0;border:0;visibility:hidden}.layui-upload-wrap{position:relative;display:inline-block;vertical-align:middle}.layui-upload-wrap .layui-upload-file{display:block!important;position:absolute;left:0;top:0;z-index:10;font-size:100px;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-btn-container .layui-upload-choose{padding-left:0}.layui-menu{position:relative;margin:5px 0;background-color:#fff;box-sizing:border-box}.layui-menu *{box-sizing:border-box}.layui-menu li,.layui-menu-body-title,.layui-menu-body-title a{padding:5px 15px;color:initial}.layui-menu li{position:relative;margin:0 0 1px;line-height:26px;color:rgba(0,0,0,.8);font-size:14px;white-space:nowrap;cursor:pointer;transition:all .3s}.layui-menu li:hover{background-color:#f8f8f8}.layui-menu li.layui-disabled,.layui-menu li.layui-disabled *{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important}.layui-menu-item-parent:hover>.layui-menu-body-panel{display:block;animation-name:layui-fadein;animation-duration:.3s;animation-fill-mode:both;animation-delay:.2s}.layui-menu-item-group>.layui-menu-body-title,.layui-menu-item-parent>.layui-menu-body-title{padding-right:38px}.layui-menu .layui-menu-item-divider:hover,.layui-menu .layui-menu-item-group:hover,.layui-menu .layui-menu-item-none:hover{background:0 0;cursor:default}.layui-menu .layui-menu-item-group>ul{margin:5px 0 -5px}.layui-menu .layui-menu-item-group>.layui-menu-body-title{color:rgba(0,0,0,.35);user-select:none}.layui-menu .layui-menu-item-none{color:rgba(0,0,0,.35);cursor:default}.layui-menu .layui-menu-item-none{text-align:center}.layui-menu .layui-menu-item-divider{margin:5px 0;padding:0;height:0;line-height:0;border-bottom:1px solid #eee;overflow:hidden}.layui-menu .layui-menu-item-down:hover,.layui-menu .layui-menu-item-up:hover{cursor:pointer}.layui-menu .layui-menu-item-up>.layui-menu-body-title{color:rgba(0,0,0,.8)}.layui-menu .layui-menu-item-up>ul{visibility:hidden;height:0;overflow:hidden}.layui-menu .layui-menu-item-down>.layui-menu-body-title>.layui-icon-down{transform:rotate(180deg)}.layui-menu .layui-menu-item-up>.layui-menu-body-title>.layui-icon-up{transform:rotate(-180deg)}.layui-menu .layui-menu-item-down:hover>.layui-menu-body-title>.layui-icon,.layui-menu .layui-menu-item-up>.layui-menu-body-title:hover>.layui-icon{color:#000}.layui-menu .layui-menu-item-down>ul{visibility:visible;height:auto}.layui-menu .layui-menu-item-checked,.layui-menu .layui-menu-item-checked2{background-color:#f8f8f8!important;color:#16b777}.layui-menu .layui-menu-item-checked a,.layui-menu .layui-menu-item-checked2 a{color:#16b777}.layui-menu .layui-menu-item-checked:after{position:absolute;right:-1px;top:0;bottom:0;border-right:3px solid #16b777;content:""}.layui-menu-body-title{position:relative;margin:-5px -15px;overflow:hidden;text-overflow:ellipsis}.layui-menu-body-title a{display:block;margin:-5px -15px;color:rgba(0,0,0,.8)}.layui-menu-body-title a:hover{transition:all .3s}.layui-menu-body-title>.layui-icon{position:absolute;right:15px;top:50%;margin-top:-6px;line-height:normal;font-size:14px;transition:all .2s;-webkit-transition:all .2s}.layui-menu-body-title>.layui-icon:hover{transition:all .3s}.layui-menu-body-title>.layui-icon-right{right:14px}.layui-menu-body-panel{display:none;position:absolute;top:-7px;left:100%;z-index:1000;margin-left:13px;padding:5px 0}.layui-menu-body-panel:before{content:"";position:absolute;width:20px;left:-16px;top:0;bottom:0}.layui-menu-body-panel-left{left:auto;right:100%;margin:0 13px 0}.layui-menu-body-panel-left:before{left:auto;right:-16px}.layui-menu-lg li{line-height:32px}.layui-menu-lg .layui-menu-body-title a:hover,.layui-menu-lg li:hover{background:0 0;color:#16b777}.layui-menu-lg li .layui-menu-body-panel{margin-left:14px}.layui-menu-lg li .layui-menu-body-panel-left{margin:0 15px 0}.layui-dropdown{position:absolute;left:-999999px;top:-999999px;z-index:77777777;margin:5px 0;min-width:100px}.layui-dropdown:before{content:"";position:absolute;width:100%;height:6px;left:0;top:-6px}.layui-dropdown-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px");position:fixed;_position:absolute;pointer-events:auto}.layui-nav{position:relative;padding:0 15px;background-color:#2f363c;color:#fff;border-radius:2px;font-size:0;box-sizing:border-box}.layui-nav *{font-size:14px}.layui-nav .layui-nav-item{position:relative;display:inline-block;*display:inline;*zoom:1;margin-top:0;list-style:none;vertical-align:middle;line-height:60px}.layui-nav .layui-nav-item a{display:block;padding:0 20px;color:#fff;color:rgba(255,255,255,.7);transition:all .3s;-webkit-transition:all .3s}.layui-nav .layui-this:after,.layui-nav-bar{content:"";position:absolute;left:0;top:0;width:0;height:3px;background-color:#16b777;transition:all .2s;-webkit-transition:all .2s;pointer-events:none}.layui-nav-bar{z-index:1000}.layui-nav[lay-bar=disabled] .layui-nav-bar{display:none}.layui-nav .layui-nav-item a:hover,.layui-nav .layui-this a{color:#fff;text-decoration:none}.layui-nav .layui-this:after{top:auto;bottom:0;width:100%}.layui-nav-img{width:30px;height:30px;margin-right:10px;border-radius:50%}.layui-nav .layui-nav-more{position:absolute;top:0;right:3px;left:auto!important;margin-top:0;font-size:12px;cursor:pointer;transition:all .2s;-webkit-transition:all .2s}.layui-nav .layui-nav-mored,.layui-nav-itemed>a .layui-nav-more{transform:rotate(180deg)}.layui-nav-child{display:none;position:absolute;left:0;top:65px;min-width:100%;line-height:36px;padding:5px 0;box-shadow:0 2px 4px rgba(0,0,0,.12);border:1px solid #eee;background-color:#fff;z-index:100;border-radius:2px;white-space:nowrap;box-sizing:border-box}.layui-nav .layui-nav-child a{color:#5f5f5f;color:rgba(0,0,0,.8)}.layui-nav .layui-nav-child a:hover{background-color:#f8f8f8;color:rgba(0,0,0,.8)}.layui-nav-child dd{margin:1px 0;position:relative}.layui-nav-child dd.layui-this{background-color:#f8f8f8;color:#000}.layui-nav-child dd.layui-this:after{display:none}.layui-nav-child-r{left:auto;right:0}.layui-nav-child-c{text-align:center}.layui-nav.layui-nav-tree{width:200px;padding:0}.layui-nav-tree .layui-nav-item{display:block;width:100%;line-height:40px}.layui-nav-tree .layui-nav-item a{position:relative;height:40px;line-height:40px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-nav-tree .layui-nav-item>a{padding-top:5px;padding-bottom:5px}.layui-nav-tree .layui-nav-more{right:15px}.layui-nav-tree .layui-nav-item>a .layui-nav-more{padding:5px 0}.layui-nav-tree .layui-nav-bar{width:5px;height:0}.layui-side .layui-nav-tree .layui-nav-bar{width:2px}.layui-nav-tree .layui-nav-child dd.layui-this,.layui-nav-tree .layui-nav-child dd.layui-this a,.layui-nav-tree .layui-this,.layui-nav-tree .layui-this>a,.layui-nav-tree .layui-this>a:hover{background-color:#16baaa;color:#fff}.layui-nav-tree .layui-this:after{display:none}.layui-nav-itemed>a,.layui-nav-tree .layui-nav-title a,.layui-nav-tree .layui-nav-title a:hover{color:#fff!important}.layui-nav-tree .layui-nav-bar{background-color:#16baaa}.layui-nav-tree .layui-nav-child{position:relative;z-index:0;top:0;border:none;background:0 0;background-color:rgba(0,0,0,.3);box-shadow:none}.layui-nav-tree .layui-nav-child dd{margin:0}.layui-nav-tree .layui-nav-child a{color:#fff;color:rgba(255,255,255,.7)}.layui-nav-tree .layui-nav-child a:hover{background:0 0;color:#fff}.layui-nav-itemed>.layui-nav-child,.layui-nav-itemed>.layui-nav-child>.layui-this>.layui-nav-child{display:block}.layui-nav-side{position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;z-index:999}.layui-nav-tree.layui-bg-gray a,.layui-nav.layui-bg-gray .layui-nav-item a{color:#373737;color:rgba(0,0,0,.8)}.layui-nav-tree.layui-bg-gray .layui-nav-itemed>a{color:#000!important}.layui-nav.layui-bg-gray .layui-this a{color:#16b777}.layui-nav-tree.layui-bg-gray .layui-nav-child{padding-left:11px;background:0 0}.layui-nav-tree.layui-bg-gray .layui-nav-child dd.layui-this,.layui-nav-tree.layui-bg-gray .layui-nav-child dd.layui-this a,.layui-nav-tree.layui-bg-gray .layui-this,.layui-nav-tree.layui-bg-gray .layui-this>a{background:0 0!important;color:#16b777!important;font-weight:700}.layui-nav-tree.layui-bg-gray .layui-nav-bar{background-color:#16b777}.layui-breadcrumb{visibility:hidden;font-size:0}.layui-breadcrumb>*{font-size:14px}.layui-breadcrumb a{color:#999!important}.layui-breadcrumb a:hover{color:#16b777!important}.layui-breadcrumb a cite{color:#5f5f5f;font-style:normal}.layui-breadcrumb span[lay-separator]{margin:0 10px;color:#999}.layui-tab{margin:10px 0;text-align:left!important}.layui-tab[overflow]>.layui-tab-title{overflow:hidden}.layui-tab .layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom-width:1px;border-bottom-style:solid;transition:all .2s;-webkit-transition:all .2s}.layui-tab .layui-tab-title li{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;font-size:14px;transition:all .2s;-webkit-transition:all .2s}.layui-tab .layui-tab-title li{position:relative;line-height:40px;min-width:65px;margin:0;padding:0 15px;text-align:center;cursor:pointer}.layui-tab .layui-tab-title li a{display:block;padding:0 15px;margin:0 -15px}.layui-tab-title .layui-this{color:#000}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:"";width:100%;height:41px;border-width:1px;border-style:solid;border-bottom-color:#fff;border-radius:2px 2px 0 0;box-sizing:border-box;pointer-events:none}.layui-tab-bar{position:absolute;right:0;top:0;z-index:10;width:30px;height:39px;line-height:39px;border-width:1px;border-style:solid;border-radius:2px;text-align:center;background-color:#fff;cursor:pointer}.layui-tab-bar .layui-icon{position:relative;display:inline-block;top:3px;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item{display:none}.layui-tab-more{padding-right:30px;height:auto!important;white-space:normal!important}.layui-tab-more li.layui-this:after{border-bottom-color:#eee;border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;top:3px\0;-webkit-transform:rotate(180deg);transform:rotate(180deg)}:root .layui-tab-more .layui-tab-bar .layui-icon{top:-2px\0/IE9}.layui-tab-content{padding:15px 0}.layui-tab-title li .layui-tab-close{position:relative;display:inline-block;width:18px;height:18px;line-height:20px;margin-left:8px;top:1px;text-align:center;font-size:14px;color:#c2c2c2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li .layui-tab-close:hover{border-radius:2px;background-color:#ff5722;color:#fff}.layui-tab-brief>.layui-tab-title .layui-this{color:#16baaa}.layui-tab-brief>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-title .layui-this:after{border:none;border-radius:0;border-bottom:2px solid #16b777}.layui-tab-brief[overflow]>.layui-tab-title .layui-this:after{top:-1px}.layui-tab-card{border-width:1px;border-style:solid;border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1)}.layui-tab-card>.layui-tab-title{background-color:#fafafa}.layui-tab-card>.layui-tab-title li{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-title .layui-this{background-color:#fff}.layui-tab-card>.layui-tab-title .layui-this:after{border-top:none;border-width:1px;border-bottom-color:#fff}.layui-tab-card>.layui-tab-title .layui-tab-bar{height:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:#16b777}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-timeline{padding-left:5px}.layui-timeline-item{position:relative;padding-bottom:20px}.layui-timeline-axis{position:absolute;left:-5px;top:0;z-index:10;width:20px;height:20px;line-height:20px;background-color:#fff;color:#16b777;border-radius:50%;text-align:center;cursor:pointer}.layui-timeline-axis:hover{color:#ff5722}.layui-timeline-item:before{content:"";position:absolute;left:5px;top:0;z-index:0;width:1px;height:100%}.layui-timeline-item:first-child:before{display:block}.layui-timeline-item:last-child:before{display:none}.layui-timeline-content{padding-left:25px}.layui-timeline-title{position:relative;margin-bottom:10px;line-height:22px}.layui-badge,.layui-badge-dot,.layui-badge-rim{position:relative;display:inline-block;padding:0 6px;font-size:12px;text-align:center;background-color:#ff5722;color:#fff;border-radius:2px}.layui-badge{height:18px;line-height:18px}.layui-badge-dot{width:8px;height:8px;padding:0;border-radius:50%}.layui-badge-rim{height:18px;line-height:18px;border-width:1px;border-style:solid;background-color:#fff;color:#5f5f5f}.layui-btn .layui-badge,.layui-btn .layui-badge-dot{margin-left:5px}.layui-nav .layui-badge,.layui-nav .layui-badge-dot{position:absolute;top:50%;margin:-5px 6px 0}.layui-nav .layui-badge{margin-top:-10px}.layui-tab-title .layui-badge,.layui-tab-title .layui-badge-dot{left:5px;top:-2px}.layui-carousel{position:relative;left:0;top:0;background-color:#f8f8f8}.layui-carousel>[carousel-item]{position:relative;width:100%;height:100%;overflow:hidden}.layui-carousel>[carousel-item]:before{position:absolute;content:'\e63d';left:50%;top:50%;width:100px;line-height:20px;margin:-10px 0 0 -50px;text-align:center;color:#c2c2c2;font-family:layui-icon!important;font-size:30px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-carousel>[carousel-item]>*{display:none;position:absolute;left:0;top:0;width:100%;height:100%;background-color:#f8f8f8;transition-duration:.3s;-webkit-transition-duration:.3s}.layui-carousel-updown>*{-webkit-transition:.3s ease-in-out up;transition:.3s ease-in-out up}.layui-carousel-arrow{display:none\0;opacity:0;position:absolute;left:10px;top:50%;margin-top:-18px;width:36px;height:36px;line-height:36px;text-align:center;font-size:20px;border:none 0;border-radius:50%;background-color:rgba(0,0,0,.2);color:#fff;-webkit-transition-duration:.3s;transition-duration:.3s;cursor:pointer}.layui-carousel-arrow[lay-type=add]{left:auto!important;right:10px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow{opacity:1;left:20px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel[lay-arrow=none] .layui-carousel-arrow{display:none}.layui-carousel-arrow:hover,.layui-carousel-ind ul:hover{background-color:rgba(0,0,0,.35)}.layui-carousel:hover .layui-carousel-arrow{display:block\0;opacity:1;left:20px}.layui-carousel:hover .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel-ind{position:relative;top:-35px;width:100%;line-height:0!important;text-align:center;font-size:0}.layui-carousel[lay-indicator=outside]{margin-bottom:30px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind{top:10px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind ul{background-color:rgba(0,0,0,.5)}.layui-carousel[lay-indicator=none] .layui-carousel-ind{display:none}.layui-carousel-ind ul{display:inline-block;padding:5px;background-color:rgba(0,0,0,.2);border-radius:10px;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind ul li{display:inline-block;width:10px;height:10px;margin:0 3px;font-size:14px;background-color:#eee;background-color:rgba(255,255,255,.5);border-radius:50%;cursor:pointer;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind ul li:hover{background-color:rgba(255,255,255,.7)}.layui-carousel-ind ul li.layui-this{background-color:#fff}.layui-carousel>[carousel-item]>.layui-carousel-next,.layui-carousel>[carousel-item]>.layui-carousel-prev,.layui-carousel>[carousel-item]>.layui-this{display:block}.layui-carousel>[carousel-item]>.layui-this{left:0}.layui-carousel>[carousel-item]>.layui-carousel-prev{left:-100%}.layui-carousel>[carousel-item]>.layui-carousel-next{left:100%}.layui-carousel>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel>[carousel-item]>.layui-carousel-prev.layui-carousel-right{left:0}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-left{left:-100%}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-right{left:100%}.layui-carousel[lay-anim=updown] .layui-carousel-arrow{left:50%!important;top:20px;margin:0 0 0 -18px}.layui-carousel[lay-anim=updown] .layui-carousel-arrow[lay-type=add]{top:auto!important;bottom:20px}.layui-carousel[lay-anim=updown] .layui-carousel-ind{position:absolute;top:50%;right:20px;width:auto;height:auto}.layui-carousel[lay-anim=updown] .layui-carousel-ind ul{padding:3px 5px}.layui-carousel[lay-anim=updown] .layui-carousel-ind li{display:block;margin:6px 0}.layui-carousel[lay-anim=updown]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next{top:100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-left{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-right{top:100%}.layui-carousel[lay-anim=fade]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev{opacity:0}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{opacity:1}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-right{opacity:0}.layui-fixbar{position:fixed;right:16px;bottom:16px;z-index:999999}.layui-fixbar li{width:50px;height:50px;line-height:50px;margin-bottom:1px;text-align:center;cursor:pointer;font-size:30px;background-color:#9f9f9f;color:#fff;border-radius:2px;opacity:.95}.layui-fixbar li:hover{opacity:.85}.layui-fixbar li:active{opacity:1}.layui-fixbar .layui-fixbar-top{display:none;font-size:40px}body .layui-util-face{border:none;background:0 0}body .layui-util-face .layui-layer-content{padding:0;background-color:#fff;color:#5f5f5f;box-shadow:none}.layui-util-face .layui-layer-TipsG{display:none}.layui-util-face ul{position:relative;width:372px;padding:10px;border:1px solid #d9d9d9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-util-face ul li{cursor:pointer;float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px;text-align:center}.layui-util-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layui-code{display:block;position:relative;padding:15px;line-height:20px;border:1px solid #eee;border-left-width:6px;background-color:#fff;color:#333;font-family:"Courier New",Consolas,"Lucida Console";font-size:12px}.layui-transfer-box,.layui-transfer-header,.layui-transfer-search{border-width:0;border-style:solid;border-color:#eee}.layui-transfer-box{position:relative;display:inline-block;vertical-align:middle;border-width:1px;width:200px;height:360px;border-radius:2px;background-color:#fff}.layui-transfer-box .layui-form-checkbox{width:100%;margin:0!important}.layui-transfer-header{height:38px;line-height:38px;padding:0 11px;border-bottom-width:1px}.layui-transfer-search{position:relative;padding:11px;border-bottom-width:1px}.layui-transfer-search .layui-input{height:32px;padding-left:30px;font-size:12px}.layui-transfer-search .layui-icon-search{position:absolute;left:20px;top:50%;line-height:normal;margin-top:-8px;color:#5f5f5f}.layui-transfer-active{margin:0 15px;display:inline-block;vertical-align:middle}.layui-transfer-active .layui-btn{display:block;margin:0;padding:0 15px;background-color:#16b777;border-color:#16b777;color:#fff}.layui-transfer-active .layui-btn-disabled{background-color:#fbfbfb;border-color:#eee;color:#d2d2d2}.layui-transfer-active .layui-btn:first-child{margin-bottom:15px}.layui-transfer-active .layui-btn .layui-icon{margin:0;font-size:14px!important}.layui-transfer-data{padding:5px 0;overflow:auto}.layui-transfer-data li{height:32px;line-height:32px;margin-top:0!important;padding:0 11px;list-style-type:none!important}.layui-transfer-data li:hover{background-color:#f8f8f8;transition:.5s all}.layui-transfer-data .layui-none{padding:15px 11px;text-align:center;color:#999}.layui-rate,.layui-rate *{display:inline-block;vertical-align:middle}.layui-rate{padding:11px 6px 11px 0;font-size:0}.layui-rate li{margin-top:0!important}.layui-rate li i.layui-icon{font-size:20px;color:#ffb800}.layui-rate li i.layui-icon{margin-right:5px;transition:all .3s;-webkit-transition:all .3s}.layui-rate li i:hover,.layui-rate-hover{cursor:pointer;transform:scale(1.12);-webkit-transform:scale(1.12)}.layui-rate[readonly] li i:hover{cursor:default;transform:scale(1)}.layui-colorpicker{width:38px;height:38px;border:1px solid #eee;padding:5px;border-radius:2px;line-height:24px;display:inline-block;cursor:pointer;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-colorpicker:hover{border-color:#d2d2d2}.layui-colorpicker.layui-colorpicker-lg{width:44px;height:44px;line-height:30px}.layui-colorpicker.layui-colorpicker-sm{width:30px;height:30px;line-height:20px;padding:3px}.layui-colorpicker.layui-colorpicker-xs{width:22px;height:22px;line-height:16px;padding:1px}.layui-colorpicker-trigger-bgcolor{display:block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);border-radius:2px}.layui-colorpicker-trigger-span{display:block;height:100%;box-sizing:border-box;border:1px solid rgba(0,0,0,.15);border-radius:2px;text-align:center}.layui-colorpicker-trigger-i{display:inline-block;color:#fff;font-size:12px}.layui-colorpicker-trigger-i.layui-icon-close{color:#999}.layui-colorpicker-main{position:absolute;left:-999999px;top:-999999px;z-index:77777777;width:280px;margin:5px 0;padding:7px;background:#fff;border:1px solid #d2d2d2;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-colorpicker-main-wrapper{height:180px;position:relative}.layui-colorpicker-basis{width:260px;height:100%;position:relative}.layui-colorpicker-basis-white{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(90deg,#fff,hsla(0,0%,100%,0))}.layui-colorpicker-basis-black{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(0deg,#000,transparent)}.layui-colorpicker-basis-cursor{width:10px;height:10px;border:1px solid #fff;border-radius:50%;position:absolute;top:-3px;right:-3px;cursor:pointer}.layui-colorpicker-side{position:absolute;top:0;right:0;width:12px;height:100%;background:linear-gradient(red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.layui-colorpicker-side-slider{width:100%;height:5px;box-shadow:0 0 1px #888;box-sizing:border-box;background:#fff;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;left:0}.layui-colorpicker-main-alpha{display:none;height:12px;margin-top:7px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-alpha-bgcolor{height:100%;position:relative}.layui-colorpicker-alpha-slider{width:5px;height:100%;box-shadow:0 0 1px #888;box-sizing:border-box;background:#fff;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;top:0}.layui-colorpicker-main-pre{padding-top:7px;font-size:0}.layui-colorpicker-pre{width:20px;height:20px;border-radius:2px;display:inline-block;margin-left:6px;margin-bottom:7px;cursor:pointer}.layui-colorpicker-pre:nth-child(11n+1){margin-left:0}.layui-colorpicker-pre-isalpha{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-pre.layui-this{box-shadow:0 0 3px 2px rgba(0,0,0,.15)}.layui-colorpicker-pre>div{height:100%;border-radius:2px}.layui-colorpicker-main-input{text-align:right;padding-top:7px}.layui-colorpicker-main-input .layui-btn-container .layui-btn{margin:0 0 0 10px}.layui-colorpicker-main-input div.layui-inline{float:left;margin-right:10px;font-size:14px}.layui-colorpicker-main-input input.layui-input{width:150px;height:30px;color:#5f5f5f}.layui-slider{height:4px;background:#eee;border-radius:3px;position:relative;cursor:pointer}.layui-slider-bar{border-radius:3px;position:absolute;height:100%}.layui-slider-step{position:absolute;top:0;width:4px;height:4px;border-radius:50%;background:#fff;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.layui-slider-wrap{width:36px;height:36px;position:absolute;top:-16px;-webkit-transform:translateX(-50%);transform:translateX(-50%);z-index:10;text-align:center}.layui-slider-wrap-btn{width:12px;height:12px;border-radius:50%;background:#fff;display:inline-block;vertical-align:middle;cursor:pointer;transition:.3s}.layui-slider-wrap:after{content:"";height:100%;display:inline-block;vertical-align:middle}.layui-slider-wrap-btn.layui-slider-hover,.layui-slider-wrap-btn:hover{transform:scale(1.2)}.layui-slider-wrap-btn.layui-disabled:hover{transform:scale(1)!important}.layui-slider-tips{position:absolute;top:-42px;z-index:77777777;white-space:nowrap;display:none;-webkit-transform:translateX(-50%);transform:translateX(-50%);color:#fff;background:#000;border-radius:3px;height:25px;line-height:25px;padding:0 10px}.layui-slider-tips:after{content:"";position:absolute;bottom:-12px;left:50%;margin-left:-6px;width:0;height:0;border-width:6px;border-style:solid;border-color:#000 transparent transparent transparent}.layui-slider-input{width:70px;height:32px;border:1px solid #eee;border-radius:3px;font-size:16px;line-height:32px;position:absolute;right:0;top:-14px;box-sizing:border-box}.layui-slider-input-btn{position:absolute;top:0;right:0;width:20px;height:100%;border-left:1px solid #eee}.layui-slider-input-btn i{cursor:pointer;position:absolute;right:0;bottom:0;width:20px;height:50%;font-size:12px;line-height:16px;text-align:center;color:#999}.layui-slider-input-btn i:first-child{top:0;border-bottom:1px solid #eee}.layui-slider-input-txt{height:100%;font-size:14px}.layui-slider-input-txt input{height:100%;border:none;padding-right:21px}.layui-slider-input-btn i:hover{color:#16baaa}.layui-slider-vertical{width:4px;margin-left:33px}.layui-slider-vertical .layui-slider-bar{width:4px}.layui-slider-vertical .layui-slider-step{top:auto;left:0;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-wrap{top:auto;left:-16px;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-tips{top:auto;left:2px}@media \0screen{.layui-slider-wrap-btn{margin-left:-20px}.layui-slider-vertical .layui-slider-wrap-btn{margin-left:0;margin-bottom:-20px}.layui-slider-vertical .layui-slider-tips{margin-left:-8px}.layui-slider>span{margin-left:8px}}.layui-tree{line-height:22px}.layui-tree .layui-form-checkbox{margin:0!important}.layui-tree-set{width:100%;position:relative}.layui-tree-pack{display:none;padding-left:20px;position:relative}.layui-tree-line .layui-tree-pack{padding-left:27px}.layui-tree-line .layui-tree-set .layui-tree-set:after{content:"";position:absolute;top:14px;left:-9px;width:17px;height:0;border-top:1px dotted #c0c4cc}.layui-tree-entry{position:relative;padding:3px 0;height:26px;white-space:nowrap}.layui-tree-entry:hover{background-color:#eee}.layui-tree-line .layui-tree-entry:hover{background-color:rgba(0,0,0,0)}.layui-tree-line .layui-tree-entry:hover .layui-tree-txt{color:#999;text-decoration:underline;transition:.3s}.layui-tree-main{display:inline-block;vertical-align:middle;cursor:pointer;padding-right:10px}.layui-tree-line .layui-tree-set:before{content:"";position:absolute;top:0;left:-9px;width:0;height:100%;border-left:1px dotted #c0c4cc}.layui-tree-line .layui-tree-set.layui-tree-setLineShort:before{height:13px}.layui-tree-line .layui-tree-set.layui-tree-setHide:before{height:0}.layui-tree-iconClick{display:inline-block;vertical-align:middle;position:relative;height:20px;line-height:20px;margin:0 10px;color:#c0c4cc}.layui-tree-icon{height:14px;line-height:12px;width:14px;text-align:center;border:1px solid #c0c4cc}.layui-tree-iconClick .layui-icon{font-size:18px}.layui-tree-icon .layui-icon{font-size:12px;color:#5f5f5f}.layui-tree-iconArrow{padding:0 5px}.layui-tree-iconArrow:after{content:"";position:absolute;left:4px;top:3px;z-index:100;width:0;height:0;border-width:5px;border-style:solid;border-color:transparent transparent transparent #c0c4cc;transition:.5s}.layui-tree-spread>.layui-tree-entry .layui-tree-iconClick>.layui-tree-iconArrow:after{transform:rotate(90deg) translate(3px,4px)}.layui-tree-txt{display:inline-block;vertical-align:middle;color:#555}.layui-tree-search{margin-bottom:15px;color:#5f5f5f}.layui-tree-btnGroup{visibility:hidden;display:inline-block;vertical-align:middle;position:relative}.layui-tree-btnGroup .layui-icon{display:inline-block;vertical-align:middle;padding:0 2px;cursor:pointer}.layui-tree-btnGroup .layui-icon:hover{color:#999;transition:.3s}.layui-tree-entry:hover .layui-tree-btnGroup{visibility:visible}.layui-tree-editInput{position:relative;display:inline-block;vertical-align:middle;height:20px;line-height:20px;padding:0;border:none;background-color:rgba(0,0,0,.05)}.layui-tree-emptyText{text-align:center;color:#999}.layui-anim{-webkit-animation-duration:.3s;-webkit-animation-fill-mode:both;animation-duration:.3s;animation-fill-mode:both}.layui-anim.layui-icon{display:inline-block}.layui-anim-loop{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.layui-trans,.layui-trans a{transition:all .2s;-webkit-transition:all .2s}@-webkit-keyframes layui-rotate{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes layui-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}.layui-anim-rotate{-webkit-animation-name:layui-rotate;animation-name:layui-rotate;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes layui-up{from{-webkit-transform:translate3d(0,100%,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-up{from{transform:translate3d(0,100%,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-up{-webkit-animation-name:layui-up;animation-name:layui-up}@-webkit-keyframes layui-upbit{from{-webkit-transform:translate3d(0,15px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-upbit{from{transform:translate3d(0,15px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-upbit{-webkit-animation-name:layui-upbit;animation-name:layui-upbit}@keyframes layui-down{0%{opacity:.3;transform:translate3d(0,-100%,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-anim-down{animation-name:layui-down}@keyframes layui-downbit{0%{opacity:.3;transform:translate3d(0,-5px,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-anim-downbit{animation-name:layui-downbit}@-webkit-keyframes layui-scale{0%{opacity:.3;-webkit-transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale{0%{opacity:.3;-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scale{-webkit-animation-name:layui-scale;animation-name:layui-scale}@-webkit-keyframes layui-scale-spring{0%{opacity:.5;-webkit-transform:scale(.5)}80%{opacity:.8;-webkit-transform:scale(1.1)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale-spring{0%{opacity:.5;transform:scale(.5)}80%{opacity:.8;transform:scale(1.1)}100%{opacity:1;transform:scale(1)}}.layui-anim-scaleSpring{-webkit-animation-name:layui-scale-spring;animation-name:layui-scale-spring}@keyframes layui-scalesmall{0%{opacity:.3;transform:scale(1.5)}100%{opacity:1;transform:scale(1)}}.layui-anim-scalesmall{animation-name:layui-scalesmall}@keyframes layui-scalesmall-spring{0%{opacity:.3;transform:scale(1.5)}80%{opacity:.8;transform:scale(.9)}100%{opacity:1;transform:scale(1)}}.layui-anim-scalesmall-spring{animation-name:layui-scalesmall-spring}@-webkit-keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}@keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}.layui-anim-fadein{-webkit-animation-name:layui-fadein;animation-name:layui-fadein}@-webkit-keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}@keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}.layui-anim-fadeout{-webkit-animation-name:layui-fadeout;animation-name:layui-fadeout}html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-wrap{font-size:13px;font-family:"Courier New",Consolas,"Lucida Console"}.layui-code-view{display:block;position:relative;padding:0!important;border:1px solid #eee;border-left-width:6px;background-color:#fff;color:#333}.layui-code-view pre{margin:0!important}.layui-code-header{position:relative;z-index:3;padding:0 11px;height:40px;line-height:40px;border-bottom:1px solid #eee;background-color:#fafafa;font-size:12px}.layui-code-header>.layui-code-header-about{position:absolute;right:11px;top:0;color:#b7b7b7}.layui-code-header-about>a{padding-left:10px}.layui-code-wrap{position:relative;display:block;z-index:1;margin:0!important;padding:11px 0!important;overflow-x:hidden;overflow-y:auto}.layui-code-line{position:relative;line-height:19px;margin:0!important}.layui-code-line-number{position:absolute;left:0;top:0;padding:0 8px;min-width:45px;height:100%;text-align:right;user-select:none;white-space:nowrap;overflow:hidden}.layui-code-line-content{padding:0 11px;word-wrap:break-word;white-space:pre-wrap}.layui-code-ln-mode>.layui-code-wrap>.layui-code-line{padding-left:45px}.layui-code-ln-side{position:absolute;left:0;top:0;bottom:0;z-index:0;width:45px;border-right:1px solid #eee;border-color:rgb(126 122 122 / 15%);background-color:#fafafa;pointer-events:none}.layui-code-nowrap>.layui-code-wrap{overflow:auto}.layui-code-nowrap>.layui-code-wrap>.layui-code-line>.layui-code-line-content{white-space:pre;word-wrap:normal}.layui-code-nowrap>.layui-code-ln-side{border-right-width:0!important;background:0 0!important}.layui-code-fixbar{position:absolute;top:8px;right:11px;padding-right:45px;z-index:5}.layui-code-fixbar>span{position:absolute;right:0;top:0;padding:0 8px;color:#777;transition:all .3s}.layui-code-fixbar>span:hover{color:#16b777}.layui-code-copy{display:none;cursor:pointer}.layui-code-preview>.layui-code-view>.layui-code-fixbar .layui-code-copy{display:none!important}.layui-code-view:hover>.layui-code-fixbar .layui-code-copy{display:block}.layui-code-view:hover>.layui-code-fixbar .layui-code-lang-marker{display:none}.layui-code-theme-dark,.layui-code-theme-dark>.layui-code-header{border-color:rgb(126 122 122 / 15%);background-color:#1f1f1f}.layui-code-theme-dark{border-width:1px;color:#ccc}.layui-code-theme-dark>.layui-code-ln-side{border-right-color:#2a2a2a;background:0 0;color:#6e7681}.layui-code textarea{display:none}.layui-code-preview>.layui-code,.layui-code-preview>.layui-code-view{margin:0}.layui-code-preview>.layui-tab{position:relative;z-index:1;margin-bottom:0}.layui-code-preview>.layui-tab>.layui-tab-title{border-width:0}.layui-code-preview .layui-code-item{display:none}.layui-code-item-preview{position:relative;padding:16px}.layui-code-item-preview>iframe{position:absolute;top:0;left:0;width:100%;height:100%;border:none}.layui-code-tools{position:absolute;right:11px;top:8px;line-height:normal}.layui-code-tools>i{display:inline-block;margin-left:6px;padding:3px;cursor:pointer}.layui-code-tools>i.layui-icon-file-b{color:#999}.layui-code-tools>i:hover{color:#16b777}.layui-code-full{position:fixed;left:0;top:0;z-index:1111111;width:100%;height:100%;background-color:#fff}.layui-code-full .layui-code-item{width:100%!important;border-width:0!important;border-top-width:1px!important}.layui-code-full .layui-code-item,.layui-code-full .layui-code-view,.layui-code-full .layui-code-wrap{height:calc(100vh - 51px)!important;box-sizing:border-box}.layui-code-full .layui-code-item-preview{overflow:auto}.layui-code-view.layui-code-hl{line-height:20px!important;border-left-width:1px}.layui-code-view.layui-code-hl>.layui-code-ln-side{background-color:transparent}.layui-code-theme-dark.layui-code-hl,.layui-code-theme-dark.layui-code-hl>.layui-code-ln-side{border-color:rgb(126 122 122 / 15%)}html #layuicss-laydate{display:none;position:absolute;width:1989px}.layui-laydate *{margin:0;padding:0}.layui-laydate,.layui-laydate *{box-sizing:border-box}.layui-laydate{position:absolute;z-index:99999999;margin:5px 0;border-radius:2px;font-size:14px;line-height:normal;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-laydate-main{width:272px}.layui-laydate-content td,.layui-laydate-header *,.layui-laydate-list li{transition-duration:.3s;-webkit-transition-duration:.3s}.layui-laydate-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px");position:fixed;_position:absolute;pointer-events:auto}@keyframes laydate-downbit{0%{opacity:.3;transform:translate3d(0,-5px,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-laydate{animation-name:laydate-downbit}.layui-laydate-static{position:relative;z-index:0;display:inline-block;margin:0;-webkit-animation:none;animation:none}.laydate-ym-show .laydate-next-m,.laydate-ym-show .laydate-prev-m{display:none!important}.laydate-ym-show .laydate-next-y,.laydate-ym-show .laydate-prev-y{display:inline-block!important}.laydate-ym-show .laydate-set-ym span[lay-type=month]{display:none!important}.laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-time-show .layui-laydate-header .layui-icon{display:none!important}.layui-laydate-header{position:relative;line-height:30px;padding:10px 70px 5px}.layui-laydate-header *{display:inline-block;vertical-align:bottom}.layui-laydate-header i{position:absolute;top:10px;padding:0 5px;color:#999;font-size:18px;cursor:pointer}.layui-laydate-header i.laydate-prev-y{left:15px}.layui-laydate-header i.laydate-prev-m{left:45px}.layui-laydate-header i.laydate-next-y{right:15px}.layui-laydate-header i.laydate-next-m{right:45px}.laydate-set-ym{width:100%;text-align:center;box-sizing:border-box;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate-set-ym span{padding:0 10px;cursor:pointer}.laydate-time-text{cursor:default!important}.layui-laydate-content{position:relative;padding:10px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content table{border-collapse:collapse;border-spacing:0}.layui-laydate-content td,.layui-laydate-content th{width:36px;height:30px;padding:0;text-align:center}.layui-laydate-content th{font-weight:400}.layui-laydate-content td{position:relative;cursor:pointer}.laydate-day-mark{position:absolute;left:0;top:0;width:100%;line-height:30px;font-size:12px;overflow:hidden}.laydate-day-mark::after{position:absolute;content:'';right:2px;top:2px;width:5px;height:5px;border-radius:50%}.laydate-day-holidays:before{position:absolute;left:0;top:0;font-size:12px;transform:scale(.7)}.laydate-day-holidays:before{content:'\4F11';color:#ff5722}.laydate-day-holidays[type=work]:before{content:'\73ED';color:inherit}.layui-laydate .layui-this .laydate-day-holidays:before{color:#fff}.layui-laydate-footer{position:relative;height:46px;line-height:26px;padding:10px}.layui-laydate-footer span{display:inline-block;vertical-align:top;height:26px;line-height:24px;padding:0 10px;border:1px solid #c9c9c9;border-radius:2px;background-color:#fff;font-size:12px;cursor:pointer;white-space:nowrap;transition:all .3s}.layui-laydate-footer span:hover{color:#16b777}.layui-laydate-footer span.layui-laydate-preview{cursor:default;border-color:transparent!important}.layui-laydate-footer span.layui-laydate-preview:hover{color:#777}.layui-laydate-footer span:first-child.layui-laydate-preview{padding-left:0}.laydate-footer-btns{position:absolute;right:10px;top:10px}.laydate-footer-btns span{margin:0 0 0 -1px;border-radius:0}.laydate-footer-btns span:first-child{border-radius:2px 0 0 2px}.laydate-footer-btns span:last-child{border-radius:0 2px 2px 0}.layui-laydate-shortcut{width:80px;padding:6px 0;display:inline-block;vertical-align:top;overflow:auto;max-height:276px;text-align:center}.layui-laydate-shortcut+.layui-laydate-main{display:inline-block;border-left:1px solid #e2e2e2}.layui-laydate-shortcut>li{padding:5px 8px;cursor:pointer;line-height:18px}.layui-laydate .layui-laydate-list{position:absolute;left:0;top:0;width:100%;height:100%;padding:10px;box-sizing:border-box;background-color:#fff}.layui-laydate .layui-laydate-list>li{position:relative;display:inline-block;width:33.3%;height:36px;line-height:36px;margin:3px 0;vertical-align:middle;text-align:center;cursor:pointer;list-style:none}.layui-laydate .laydate-month-list>li{width:25%;margin:17px 0}.layui-laydate .laydate-time-list>li{height:100%;margin:0;line-height:normal;cursor:default}.layui-laydate .laydate-time-list p{position:relative;top:-4px;margin:0;line-height:29px}.layui-laydate .laydate-time-list ol{height:181px;overflow:hidden}.layui-laydate .laydate-time-list>li:hover ol{overflow-y:auto}.layui-laydate .laydate-time-list ol li{width:130%;padding-left:33px;height:30px;line-height:30px;text-align:left;cursor:pointer}.layui-laydate-hint{position:absolute;top:115px;left:50%;width:250px;margin-left:-125px;line-height:20px;padding:15px;text-align:center;font-size:12px;color:#ff5722}.layui-laydate-range{width:546px}.layui-laydate-range .layui-laydate-main{display:inline-block;vertical-align:middle;max-width:50%}.layui-laydate-range .laydate-main-list-1 .layui-laydate-content,.layui-laydate-range .laydate-main-list-1 .layui-laydate-header{border-left:1px solid #e2e2e2}.layui-laydate-range.layui-laydate-linkage .laydate-main-list-0 .laydate-next-m,.layui-laydate-range.layui-laydate-linkage .laydate-main-list-0 .laydate-next-y,.layui-laydate-range.layui-laydate-linkage .laydate-main-list-1 .laydate-prev-m,.layui-laydate-range.layui-laydate-linkage .laydate-main-list-1 .laydate-prev-y{display:none}.layui-laydate,.layui-laydate-hint{border:1px solid #d2d2d2;box-shadow:0 2px 4px rgba(0,0,0,.12);background-color:#fff;color:#777}.layui-laydate-header{border-bottom:1px solid #e2e2e2}.layui-laydate-header i:hover,.layui-laydate-header span:hover{color:#16b777}.layui-laydate-content{border-top:none 0;border-bottom:none 0}.layui-laydate-content th{color:#333}.layui-laydate-content td{color:#777}.layui-laydate-content td.laydate-day-now{color:#16b777}.layui-laydate-content td.laydate-day-now:after{content:'';position:absolute;width:100%;height:30px;left:0;top:0;border:1px solid #16b777;box-sizing:border-box}.layui-laydate-linkage .layui-laydate-content td.laydate-selected>div{background-color:#00f7de}.layui-laydate-linkage .laydate-selected:hover>div{background-color:#00f7de!important}.layui-laydate-content td.laydate-selected:after,.layui-laydate-content td:hover:after{content:none}.layui-laydate-content td>div:hover,.layui-laydate-list li:hover,.layui-laydate-shortcut>li:hover{background-color:#eee;color:#333}.laydate-time-list li ol{margin:0;padding:0;border:1px solid #e2e2e2;border-left-width:0}.laydate-time-list li:first-child ol{border-left-width:1px}.laydate-time-list>li:hover{background:0 0}.layui-laydate-content .laydate-day-next,.layui-laydate-content .laydate-day-prev{color:#d2d2d2}.layui-laydate-linkage .laydate-selected.laydate-day-next>div,.layui-laydate-linkage .laydate-selected.laydate-day-prev>div{background-color:#f8f8f8!important}.layui-laydate-footer{border-top:1px solid #e2e2e2}.layui-laydate-hint{color:#ff5722}.laydate-day-mark::after{background-color:#16b777}.layui-laydate-content td.layui-this .laydate-day-mark::after{display:none}.layui-laydate-footer span[lay-type=date]{color:#16b777}.layui-laydate .layui-this,.layui-laydate .layui-this>div{background-color:#16baaa!important;color:#fff!important}.layui-laydate .laydate-disabled,.layui-laydate .laydate-disabled:hover{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content td>div{padding:7px 0;height:100%}.laydate-theme-molv{border:none}.laydate-theme-molv.layui-laydate-range{width:548px}.laydate-theme-molv .layui-laydate-main{width:274px}.laydate-theme-molv .layui-laydate-header{border:none;background-color:#16baaa}.laydate-theme-molv .layui-laydate-header i,.laydate-theme-molv .layui-laydate-header span{color:#f6f6f6}.laydate-theme-molv .layui-laydate-header i:hover,.laydate-theme-molv .layui-laydate-header span:hover{color:#fff}.laydate-theme-molv .layui-laydate-content{border:1px solid #e2e2e2;border-top:none;border-bottom:none}.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content{border-left:none}.laydate-theme-molv .layui-laydate-footer{border:1px solid #e2e2e2}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li,.laydate-theme-grid .layui-laydate-content td,.laydate-theme-grid .layui-laydate-content thead{border:1px solid #e2e2e2}.layui-laydate-linkage.laydate-theme-grid .laydate-selected,.layui-laydate-linkage.laydate-theme-grid .laydate-selected:hover{background-color:#f2f2f2!important;color:#16baaa!important}.layui-laydate-linkage.laydate-theme-grid .laydate-selected.laydate-day-next,.layui-laydate-linkage.laydate-theme-grid .laydate-selected.laydate-day-prev{color:#d2d2d2!important}.laydate-theme-grid .laydate-month-list,.laydate-theme-grid .laydate-year-list{margin:1px 0 0 1px}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li{margin:0 -1px -1px 0}.laydate-theme-grid .laydate-year-list>li{height:43px;line-height:43px}.laydate-theme-grid .laydate-month-list>li{height:71px;line-height:71px}.laydate-theme-grid .layui-laydate-content td>div{height:29px;margin-top:-1px}.laydate-theme-circle .layui-laydate-content td.layui-this>div,.laydate-theme-circle .layui-laydate-content td>div{width:28px;height:28px;line-height:28px;border-radius:14px;margin:0 4px;padding:0}.layui-laydate.laydate-theme-circle .layui-laydate-content table td.layui-this{background-color:transparent!important}.laydate-theme-grid.laydate-theme-circle .layui-laydate-content td>div{margin:0 3.5px}.laydate-theme-fullpanel .layui-laydate-main{width:526px}.laydate-theme-fullpanel .layui-laydate-list{width:252px;left:272px}.laydate-theme-fullpanel .laydate-set-ym span{display:none}.laydate-theme-fullpanel .laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-theme-fullpanel .laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-theme-fullpanel .laydate-time-show .layui-laydate-header .layui-icon{display:inline-block!important}.laydate-theme-fullpanel .laydate-btns-time{display:none}html #layuicss-layer{display:none;position:absolute;width:1989px}.layui-layer,.layui-layer-shade{position:fixed;_position:absolute;pointer-events:auto}.layui-layer-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px")}.layui-layer{-webkit-overflow-scrolling:touch}.layui-layer{top:150px;left:0;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;border-radius:2px;box-shadow:1px 1px 50px rgba(0,0,0,.3)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #b2b2b2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-btn a,.layui-layer-setwin span{display:inline-block;vertical-align:middle;*display:inline;*zoom:1}.layui-layer-move{display:none;position:fixed;*position:absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layer-anim{-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-00{-webkit-animation-name:layer-bounceIn;animation-name:layer-bounceIn}@-webkit-keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:layer-zoomInDown;animation-name:layer-zoomInDown}@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}@-webkit-keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:layer-zoomInLeft;animation-name:layer-zoomInLeft}@-webkit-keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}@keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);-ms-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}.layer-anim-04{-webkit-animation-name:layer-rollIn;animation-name:layer-rollIn}@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}@-webkit-keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layer-anim-06{-webkit-animation-name:layer-shake;animation-name:layer-shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes layer-slide-down{from{transform:translate3d(0,-100%,0)}to{transform:translate3d(0,0,0)}}@keyframes layer-slide-down-out{from{transform:translate3d(0,0,0)}to{transform:translate3d(0,-100%,0)}}.layer-anim-slide-down{animation-name:layer-slide-down}.layer-anim-slide-down-out{animation-name:layer-slide-down-out}@keyframes layer-slide-left{from{transform:translate3d(100%,0,0)}to{transform:translate3d(0,0,0)}}@keyframes layer-slide-left-out{from{transform:translate3d(0,0,0)}to{transform:translate3d(100%,0,0)}}.layer-anim-slide-left{animation-name:layer-slide-left}.layer-anim-slide-left-out{animation-name:layer-slide-left-out}@keyframes layer-slide-up{from{transform:translate3d(0,100%,0)}to{transform:translate3d(0,0,0)}}@keyframes layer-slide-up-out{from{transform:translate3d(0,0,0)}to{transform:translate3d(0,100%,0)}}.layer-anim-slide-up{animation-name:layer-slide-up}.layer-anim-slide-up-out{animation-name:layer-slide-up-out}@keyframes layer-slide-right{from{transform:translate3d(-100%,0,0)}to{transform:translate3d(0,0,0)}}@keyframes layer-slide-right-out{from{transform:translate3d(0,0,0)}to{transform:translate3d(-100%,0,0)}}.layer-anim-slide-right{animation-name:layer-slide-right}.layer-anim-slide-right-out{animation-name:layer-slide-right-out}.layui-layer-title{padding:0 81px 0 16px;height:50px;line-height:50px;border-bottom:1px solid #f0f0f0;font-size:14px;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:2px 2px 0 0}.layui-layer-setwin{position:absolute;right:15px;*right:0;top:16px;font-size:0;line-height:initial}.layui-layer-setwin span{position:relative;width:16px;height:16px;line-height:18px;margin-left:10px;text-align:center;font-size:16px;cursor:pointer;color:#000;_overflow:hidden;box-sizing:border-box}.layui-layer-setwin .layui-layer-min:before{content:'';position:absolute;width:12px;border-bottom:1px solid #2e2d3c;left:50%;top:50%;margin:-.5px 0 0 -6px;cursor:pointer;_overflow:hidden}.layui-layer-setwin .layui-layer-min:hover:before{background-color:#2d93ca}.layui-layer-setwin .layui-layer-max:after,.layui-layer-setwin .layui-layer-max:before{content:'';position:absolute;left:50%;top:50%;z-index:1;width:9px;height:9px;margin:-5px 0 0 -5px;border:1px solid #2e2d3c}.layui-layer-setwin .layui-layer-max:hover:after,.layui-layer-setwin .layui-layer-max:hover:before{border-color:#2d93ca}.layui-layer-setwin .layui-layer-min:hover:before{background-color:#2d93ca}.layui-layer-setwin .layui-layer-maxmin:after,.layui-layer-setwin .layui-layer-maxmin:before{width:7px;height:7px;margin:-3px 0 0 -3px;background-color:#fff}.layui-layer-setwin .layui-layer-maxmin:after{z-index:0;margin:-5px 0 0 -1px}.layui-layer-setwin .layui-layer-close{cursor:pointer}.layui-layer-setwin .layui-layer-close:hover{opacity:.7}.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;color:#fff;background-color:#787878;padding:3px;border:3px solid;width:28px;height:28px;font-size:16px;font-weight:bolder;border-radius:50%;margin-left:0;*right:-18px;_display:none}.layui-layer-setwin .layui-layer-close2:hover{opacity:unset;background-color:#3888f6}.layui-layer-btn{text-align:right;padding:0 15px 12px;pointer-events:auto;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:30px;line-height:30px;margin:5px 5px 0;padding:0 16px;border:1px solid #dedede;background-color:#fff;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none;box-sizing:border-box}.layui-layer-btn a:hover{opacity:.9;text-decoration:none}.layui-layer-btn a:active{opacity:.8}.layui-layer-btn .layui-layer-btn0{border-color:transparent;background-color:#1e9fff;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.layui-layer-dialog{min-width:240px}.layui-layer-dialog .layui-layer-content{position:relative;padding:16px;line-height:24px;word-break:break-all;overflow:hidden;font-size:14px;overflow-x:hidden;overflow-y:auto}.layui-layer-dialog .layui-layer-content .layui-layer-face{position:absolute;top:18px;left:16px;color:#959595;font-size:32px;_left:-40px}.layui-layer-dialog .layui-layer-content .layui-icon-tips{color:#f39b12}.layui-layer-dialog .layui-layer-content .layui-icon-success{color:#16b777}.layui-layer-dialog .layui-layer-content .layui-icon-error{top:19px;color:#ff5722}.layui-layer-dialog .layui-layer-content .layui-icon-question{color:#ffb800}.layui-layer-dialog .layui-layer-content .layui-icon-lock{color:#787878}.layui-layer-dialog .layui-layer-content .layui-icon-face-cry{color:#ff5722}.layui-layer-dialog .layui-layer-content .layui-icon-face-smile{color:#16b777}.layui-layer-rim{border:6px solid #8d8d8d;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #d3d4d3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:rgba(0,0,0,.6);color:#fff;border:none}.layui-layer-hui .layui-layer-close{color:#fff}.layui-layer-hui .layui-layer-content{padding:11px 24px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:18px 24px 18px 58px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-iframe .layui-layer-btn,.layui-layer-page .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:0 0}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:0 0;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:76px;height:38px;line-height:38px;text-align:center}.layui-layer-loading-icon{font-size:38px;color:#959595}.layui-layer-loading2{text-align:center}.layui-layer-loading-2{position:relative;height:38px}.layui-layer-loading-2:after,.layui-layer-loading-2:before{content:'';position:absolute;left:50%;top:50%;width:38px;height:38px;margin:-19px 0 0 -19px;border-radius:50%;border:3px solid #d2d2d2;box-sizing:border-box}.layui-layer-loading-2:after{border-color:transparent;border-left-color:#1e9fff}.layui-layer-tips{background:0 0;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:8px 15px;font-size:12px;_float:left;border-radius:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow:hidden}.layui-layer-tips i.layui-layer-TipsB,.layui-layer-tips i.layui-layer-TipsT{left:5px;border-right-style:solid;border-right-color:#000}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layui-layer-TipsB{top:-8px}.layui-layer-tips i.layui-layer-TipsL,.layui-layer-tips i.layui-layer-TipsR{top:5px;border-bottom-style:solid;border-bottom-color:#000}.layui-layer-tips i.layui-layer-TipsR{left:-8px}.layui-layer-tips i.layui-layer-TipsL{right:-8px}.layui-layer-lan .layui-layer-title{background:#4476a7;color:#fff;border:none}.layui-layer-lan .layui-layer-btn{padding:5px 10px 10px;border-top:1px solid #e9e7e7}.layui-layer-lan .layui-layer-btn a{background:#fff;border-color:#e9e7e7;color:#333}.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#c9c5c5}.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}.layui-layer-molv .layui-layer-btn a{background:#009f95;border-color:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92b8b1}.layui-layer-lan .layui-layer-setwin .layui-icon,.layui-layer-molv .layui-layer-setwin .layui-icon{color:#fff}.layui-layer-win10{border:1px solid #aaa;box-shadow:1px 1px 6px rgba(0,0,0,.3);border-radius:none}.layui-layer-win10 .layui-layer-title{height:32px;line-height:32px;padding-left:8px;border-bottom:none;font-size:12px}.layui-layer-win10 .layui-layer-setwin{right:0;top:0}.layui-layer-win10 .layui-layer-setwin span{margin-left:0;width:32px;height:32px;padding:8px}.layui-layer-win10.layui-layer-page .layui-layer-setwin span{width:38px}.layui-layer-win10 .layui-layer-setwin span:hover{background-color:#e5e5e5}.layui-layer-win10 .layui-layer-setwin span.layui-icon-close:hover{background-color:#e81123;color:#fff}.layui-layer-win10.layui-layer-dialog .layui-layer-content{padding:8px 16px 32px;color:#0033bc}.layui-layer-win10.layui-layer-dialog .layui-layer-padding{padding-top:18px;padding-left:58px}.layui-layer-win10 .layui-layer-btn{padding:5px 5px 10px;border-top:1px solid #dfdfdf;background-color:#f0f0f0}.layui-layer-win10 .layui-layer-btn a{height:20px;line-height:18px;background-color:#e1e1e1;border-color:#adadad;color:#000;font-size:12px;transition:all .3s}.layui-layer-win10 .layui-layer-btn a:hover{border-color:#2a8edd;background-color:#e5f1fb}.layui-layer-win10 .layui-layer-btn .layui-layer-btn0{border-color:#0078d7}.layui-layer-prompt .layui-layer-input{display:block;width:260px;height:36px;margin:0 auto;line-height:30px;padding-left:10px;border:1px solid #e6e6e6;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px;padding:6px 10px}.layui-layer-prompt .layui-layer-content{padding:16px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;display:inline-block;vertical-align:top;border-left:1px solid transparent;border-right:1px solid transparent;min-width:80px;max-width:300px;padding:0 16px;text-align:center;cursor:default;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;cursor:pointer}.layui-layer-tab .layui-layer-title span.layui-this{height:51px;border-left-color:#eee;border-right-color:#eee;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left-color:transparent}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.layui-this{display:block}.layui-layer-photos{background:0 0;box-shadow:none}.layui-layer-photos .layui-layer-content{overflow:visible;text-align:center}.layui-layer-photos .layer-layer-photos-main img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-photos-next,.layui-layer-photos-prev{position:fixed;top:50%;width:52px;height:52px;line-height:52px;margin-top:-26px;cursor:pointer;font-size:52px;color:#717171}.layui-layer-photos-prev{left:32px}.layui-layer-photos-next{right:32px}.layui-layer-photos-next:hover,.layui-layer-photos-prev:hover{color:#959595}.layui-layer-photos-toolbar{position:fixed;left:0;right:0;bottom:0;width:100%;height:52px;line-height:52px;background-color:#000\9;filter:Alpha(opacity=60);background-color:rgba(0,0,0,.32);color:#fff;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;font-size:0}.layui-layer-photos-toolbar>*{display:inline-block;vertical-align:top;padding:0 16px;font-size:12px;color:#fff;*display:inline;*zoom:1}.layui-layer-photos-toolbar *{font-size:12px}.layui-layer-photos-header{top:0;bottom:auto}.layui-layer-photos-header>span{cursor:pointer}.layui-layer-photos-header>span:hover{background-color:rgba(51,51,51,.32)}.layui-layer-photos-header .layui-icon{font-size:18px}.layui-layer-photos-footer>h3{max-width:65%;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-layer-photos-footer a:hover{text-decoration:underline}.layui-layer-photos-footer em{font-style:normal}@-webkit-keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:layer-bounceOut;animation-name:layer-bounceOut;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.eot b/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..3f5e98bb584b80ae0ce0d39b598fb37423ea8220 Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.eot differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.svg b/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.svg new file mode 100644 index 0000000000000000000000000000000000000000..4f1920deddba24bdb57bdc74a8abcc160f4d960f --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.svg @@ -0,0 +1,405 @@ + + + + Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.ttf b/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6e84a89e031247509801ae5d65cc8d20323cb766 Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.ttf differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.woff b/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..acd7ed6082729ae968e44aa9f676cd50a37e8eb6 Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.woff differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.woff2 b/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..5badd6e38ec077cd5b50da3d41f029f7534be086 Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/component/layui/font/iconfont.woff2 differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/layui/layui.js b/demo/thinkphp/frontend/layui_admin_flow/component/layui/layui.js new file mode 100644 index 0000000000000000000000000000000000000000..f0ac221c5ad63c5339320416ed2976cb85131506 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/layui/layui.js @@ -0,0 +1 @@ +/** v2.9.2 | MIT Licensed */;!function(d){"use strict";var t,h=d.document,m={modules:{},status:{},timeout:10,event:{}},n=function(){this.v="2.9.2"},e=d.LAYUI_GLOBAL||{},v=(t=h.currentScript?h.currentScript.src:function(){for(var t,e=h.scripts,o=e.length-1,n=o;01e3*m.timeout/4?g(s+" is not a valid module","error"):void(m.status[s]?y():setTimeout(n,4))}())}function y(){e.push(layui[s]),11e3*m.timeout/4?g(s+" is not a valid module","error"):void("string"==typeof m.modules[s]&&m.status[s]?y():setTimeout(f,4))}():((r=h.createElement("script"))["async"]=!0,r.charset="utf-8",r.src=i+((u=!0===m.version?m.v||(new Date).getTime():m.version||"")?"?v="+u:""),l.appendChild(r),!r.attachEvent||r.attachEvent.toString&&r.attachEvent.toString().indexOf("[native code")<0||b?r.addEventListener("load",function(t){p(t,i)},!1):r.attachEvent("onreadystatechange",function(t){p(t,i)}),m.modules[s]=i)),a},n.prototype.disuse=function(t){var o=this;return t=o.isArray(t)?t:[t],o.each(t,function(t,e){m.status[e],delete o[e],delete N[e],delete o.modules[e],delete m.status[e],delete m.modules[e]}),o},n.prototype.getStyle=function(t,e){t=t.currentStyle||d.getComputedStyle(t,null);return t[t.getPropertyValue?"getPropertyValue":"getAttribute"](e)},n.prototype.link=function(o,n,t){var r=this,e=h.getElementsByTagName("head")[0],i=h.createElement("link"),a="layuicss-"+((t="string"==typeof n?n:t)||o).replace(/\.|\//g,""),u="creating",l=0;return i.href=o+(m.debug?"?v="+(new Date).getTime():""),i.rel="stylesheet",i.id=a,i.media="all",h.getElementById(a)||e.appendChild(i),"function"==typeof n&&function s(t){var e=h.getElementById(a);return++l>1e3*m.timeout/100?g(o+" timeout"):void(1989===parseInt(r.getStyle(e,"width"))?(t===u&&e.removeAttribute("lay-status"),e.getAttribute("lay-status")===u?setTimeout(s,100):n()):(e.setAttribute("lay-status",u),setTimeout(function(){s(u)},100)))}(),r},n.prototype.addcss=function(t,e,o){return layui.link(m.dir+"css/"+t,e,o)},m.callback={},n.prototype.factory=function(t){if(layui[t])return"function"==typeof m.callback[t]?m.callback[t]:null},n.prototype.img=function(t,e,o){var n=new Image;if(n.src=t,n.complete)return e(n);n.onload=function(){n.onload=null,"function"==typeof e&&e(n)},n.onerror=function(t){n.onerror=null,"function"==typeof o&&o(t)}},n.prototype.config=function(t){for(var e in t=t||{})m[e]=t[e];return this},n.prototype.modules=function(){var t,e={};for(t in N)e[t]=N[t];return e}(),n.prototype.extend=function(t){for(var e in t=t||{})this[e]||this.modules[e]?g(e+" Module already exists","error"):this.modules[e]=t[e];return this},n.prototype.router=n.prototype.hash=function(t){var o={path:[],search:{},hash:((t=t||location.hash).match(/[^#](#.*$)/)||[])[1]||""};return/^#\//.test(t)&&(t=t.replace(/^#\//,""),o.href="/"+t,t=t.replace(/([^#])(#.*$)/,"$1").split("/")||[],this.each(t,function(t,e){/^\w+=/.test(e)?(e=e.split("="),o.search[e[0]]=e[1]):o.path.push(e)})),o},n.prototype.url=function(t){var r,e,o=this;return{pathname:(t?((t.match(/\.[^.]+?\/.+/)||[])[0]||"").replace(/^[^\/]+/,"").replace(/\?.+/,""):location.pathname).replace(/^\//,"").split("/"),search:(r={},e=(t?((t.match(/\?.+/)||[])[0]||"").replace(/\#.+/,""):location.search).replace(/^\?+/,"").split("&"),o.each(e,function(t,e){var o=e.indexOf("="),n=o<0?e.substr(0,e.length):0!==o&&e.substr(0,o);n&&(r[n]=0(l.innerHeight||h.documentElement.clientHeight)},d.getStyleRules=function(t,n){if(t)return t=(t=t.sheet||t.styleSheet||{}).cssRules||t.rules,"function"==typeof n&&layui.each(t,function(t,e){if(n(e,t))return!0}),t},d.style=function(t){t=t||{};var e=d.elem("style"),n=t.text||"",i=t.target;if(n)return"styleSheet"in e?(e.setAttribute("type","text/css"),e.styleSheet.cssText=n):e.innerHTML=n,e.id="LAY-STYLE-"+(t.id||(n=d.style.index||0,d.style.index++,"DF-"+n)),i&&((t=d(i).find("#"+e.id))[0]&&t.remove(),d(i).append(e)),e},d.position=function(t,e,n){var i,o,r,c,u,a,s,f;e&&(n=n||{},t!==h&&t!==d("body")[0]||(n.clickType="right"),i="right"===n.clickType?{left:(i=n.e||l.event||{}).clientX,top:i.clientY,right:i.clientX,bottom:i.clientY}:t.getBoundingClientRect(),s=e.offsetWidth,f=e.offsetHeight,o=function(t){return h.body[t=t?"scrollLeft":"scrollTop"]|h.documentElement[t]},r=function(t){return h.documentElement[t?"clientWidth":"clientHeight"]},c="margin"in n?n.margin:5,u=i.left,a=i.bottom,"center"===n.align?u-=(s-t.offsetWidth)/2:"right"===n.align&&(u=u-s+t.offsetWidth),(u=u+s+c>r("width")?r("width")-s-c:u)r()&&(i.top>f+c&&i.top<=r()?a=i.top-f-2*c:n.allowBottomOut||(a=r()-f-2*c)<0&&(a=0)),(s=n.position)&&(e.style.position=s),e.style.left=u+("fixed"===s?0:o(1))+"px",e.style.top=a+("fixed"===s?0:o())+"px",d.hasScrollbar()||(f=e.getBoundingClientRect(),!n.SYSTEM_RELOAD&&f.bottom+c>r()&&(n.SYSTEM_RELOAD=!0,setTimeout(function(){d.position(t,e,n)},50))))},d.options=function(t,e){if(e="object"==typeof e?e:{attr:e},t===h)return{};var t=d(t),n=e.attr||"lay-options",t=t.attr(n);try{return new Function("return "+(t||"{}"))()}catch(i){return layui.hint().error(e.errorText||[n+'="'+t+'"',"\n parseerror: "+i].join("\n"),"error"),{}}},d.isTopElem=function(n){var t=[h,d("body")[0]],i=!1;return d.each(t,function(t,e){if(e===n)return i=!0}),i},d.clipboard={writeText:function(n){var i=String(n.text);function t(){var t=h.createElement("textarea");t.value=i,t.style.position="fixed",t.style.opacity="0",t.style.top="0px",t.style.left="0px",h.body.appendChild(t),t.select();try{h.execCommand("copy"),"function"==typeof n.done&&n.done()}catch(e){"function"==typeof n.error&&n.error(e)}finally{t.remove?t.remove():h.body.removeChild(t)}}navigator&&"clipboard"in navigator?navigator.clipboard.writeText(i).then(n.done,function(){t()}):t()}},d.passiveSupported=function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});l.addEventListener("test",null,e),l.removeEventListener("test",null,e)}catch(n){}return t}(),d.touchEventsSupported=function(){return"ontouchstart"in l},d.touchSwipe=function(t,e){var n,i,o,r=e,c=d(t)[0];c&&d.touchEventsSupported()&&(n={pointerStart:{x:0,y:0},pointerEnd:{x:0,y:0},distanceX:0,distanceY:0,direction:"none",timeStart:null},e=function(t){1===t.touches.length&&(c.addEventListener("touchmove",i,!!d.passiveSupported&&{passive:!1}),c.addEventListener("touchend",o),c.addEventListener("touchcancel",o),n.timeStart=Date.now(),n.pointerStart.x=n.pointerEnd.x=t.touches[0].clientX,n.pointerStart.y=n.pointerEnd.y=t.touches[0].clientY,r.onTouchStart)&&r.onTouchStart(t,n)},i=function(t){t.preventDefault(),n.pointerEnd.x=t.touches[0].clientX,n.pointerEnd.y=t.touches[0].clientY,n.distanceX=n.pointerStart.x-n.pointerEnd.x,n.distanceY=n.pointerStart.y-n.pointerEnd.y,Math.abs(n.distanceX)>Math.abs(n.distanceY)?n.direction=0]|&(?=#[a-zA-Z0-9]+)/g.test(e+="")?e.replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,"""):e}},i=function(e){return new RegExp(e,"g")},u=function(e,r){var n="Laytpl Error: ";return"object"==typeof console&&console.error(n+e+"\n"+(r||"")),n+e},n=function(e,r){var n=this,e=(n.config=n.config||{},n.template=e,function(e){for(var r in e)n.config[r]=e[r]});e(c),e(r)},r=(n.prototype.tagExp=function(e,r,n){var c=this.config;return i((r||"")+c.open+["#([\\s\\S])+?","([^{#}])*?"][e||0]+c.close+(n||""))},n.prototype.parse=function(e,r){var n=this,c=n.config,t=e,o=i("^"+c.open+"#",""),p=i(c.close+"$","");if("string"!=typeof e)return e;e='"use strict";var view = "'+(e=e.replace(/\s+|\r|\t|\n/g," ").replace(i(c.open+"#"),c.open+"# ").replace(i(c.close+"}"),"} "+c.close).replace(/\\/g,"\\\\").replace(i(c.open+"!(.+?)!"+c.close),function(e){return e=e.replace(i("^"+c.open+"!"),"").replace(i("!"+c.close),"").replace(i(c.open+"|"+c.close),function(e){return e.replace(/(.)/g,"\\$1")})}).replace(/(?="|')/g,"\\").replace(n.tagExp(),function(e){return'";'+(e=e.replace(o,"").replace(p,"")).replace(/\\(.)/g,"$1")+';view+="'}).replace(n.tagExp(1),function(e){var r='"+laytpl.escape(';return e.replace(/\s/g,"")===c.open+c.close?"":(e=e.replace(i(c.open+"|"+c.close),""),/^=/.test(e)?e=e.replace(/^=/,""):/^-/.test(e)&&(e=e.replace(/^-/,""),r='"+('),r+e.replace(/\\(.)/g,"$1")+')+"')}))+'";return view;';try{return n.cache=e=new Function("d, laytpl",e),e(r,l)}catch(a){return delete n.cache,u(a,t)}},n.prototype.render=function(e,r){e=e||{};var n=this,e=n.cache?n.cache(e,l):n.parse(n.template,e);return"function"==typeof r&&r(e),e},function(e,r){return new n(e,r)});r.config=function(e){for(var r in e=e||{})c[r]=e[r]},r.v="2.0.0",e("laytpl",r)});layui.define(function(e){"use strict";var r=document,u="getElementById",c="getElementsByTagName",a="layui-disabled",t=function(e){var a=this;a.config=e||{},a.config.index=++o.index,a.render(!0)},o=(t.prototype.type=function(){var e=this.config;if("object"==typeof e.elem)return e.elem.length===undefined?2:3},t.prototype.view=function(){var i,e,t,n=this.config,r=n.groups="groups"in n?Number(n.groups)||0:5,u=(n.layout="object"==typeof n.layout?n.layout:["prev","page","next"],n.count=Number(n.count)||0,n.curr=Number(n.curr)||1,n.limits="object"==typeof n.limits?n.limits:[10,20,30,40,50],n.limit=Number(n.limit)||10,n.pages=Math.ceil(n.count/n.limit)||1,n.curr>n.pages?n.curr=n.pages:n.curr<1&&(n.curr=1),r<0?r=1:r>n.pages&&(r=n.pages),n.prev="prev"in n?n.prev:"上一页",n.next="next"in n?n.next:"下一页",n.pages>r?Math.ceil((n.curr+(1'+n.prev+"":"",page:function(){var e=[];if(n.count<1)return"";1'+(n.first||1)+"");var a=Math.floor((r-1)/2),t=1n.pages?n.pages:a:r;for(i-t…');t<=i;t++)t===n.curr?e.push('"+t+""):e.push(''+t+"");return n.pages>r&&n.pages>i&&!1!==n.last&&(i+1…'),0!==r)&&e.push(''+(n.last||n.pages)+""),e.join("")}(),next:n.next?''+n.next+"":"",count:''+(e="object"==typeof n.countText?n.countText:["\u5171 "," \u6761"])[0]+n.count+e[1]+"",limit:(i=['"),refresh:['','',""].join(""),skip:[''+(e="object"==typeof n.skipText?n.skipText:["到第","页","确定"])[0],'',e[1]+'",""].join("")};return['
',(t=[],layui.each(n.layout,function(e,a){l[a]&&t.push(l[a])}),t.join("")),"
"].join("")},t.prototype.jump=function(e,a){if(e){var t=this,i=t.config,n=e.children,r=e[c]("button")[0],u=e[c]("input")[0],e=e[c]("select")[0],l=function(){var e=Number(u.value.replace(/\s|\D/g,""));e&&(i.curr=e,t.render())};if(a)return l();for(var s=0,p=n.length;si.pages||(i.curr=e,t.render())});e&&o.on(e,"change",function(){var e=this.value;i.curr*e>i.count&&(i.curr=Math.ceil(i.count/e)),i.limit=e,t.render()}),r&&o.on(r,"click",function(){l()})}},t.prototype.skip=function(t){var i,e;t&&(i=this,e=t[c]("input")[0])&&o.on(e,"keyup",function(e){var a=this.value,e=e.keyCode;/^(37|38|39|40)$/.test(e)||(/\D/.test(a)&&(this.value=a.replace(/\D/,"")),13===e&&i.jump(t,!0))})},t.prototype.render=function(e){var a=this,t=a.config,i=a.type(),n=a.view(),i=(2===i?t.elem&&(t.elem.innerHTML=n):3===i?t.elem.html(n):r[u](t.elem)&&(r[u](t.elem).innerHTML=n),t.jump&&t.jump(t,e),r[u]("layui-laypage-"+t.index));a.jump(i),t.hash&&!e&&(location.hash="!"+t.hash+"="+t.curr),a.skip(i)},{render:function(e){return new t(e).index},index:layui.laypage?layui.laypage.index+1e4:0,on:function(a,e,t){return a.attachEvent?a.attachEvent("on"+e,function(e){e.target=e.srcElement,t.call(a,e)}):a.addEventListener(e,t,!1),this}});e("laypage",o)});!function(i,v){"use strict";var n=i.layui&&layui.define,l={getPath:i.lay&&lay.getPath?lay.getPath:"",link:function(e,t,a){D.path&&i.lay&&lay.layui&&lay.layui.link(D.path+e,t,a)}},e=i.LAYUI_GLOBAL||{},a="laydate",d="layui-"+a+"-id",D={v:"5.5.0",config:{weekStart:0},index:i.laydate&&i.laydate.v?1e5:0,path:e.laydate_dir||l.getPath,set:function(e){var t=this;return t.config=lay.extend({},t.config,e),t},ready:function(e){var t="laydate",a=(n?"modules/":"")+"laydate.css?v="+D.v;return n?layui["layui.all"]?"function"==typeof e&&e():layui.addcss(a,e,t):l.link(a,e,t),this}},s=function(){var t=this,e=t.config.id;return(s.that[e]=t).inst={hint:function(e){t.hint.call(t,e)},reload:function(e){t.reload.call(t,e)},config:t.config}},x="layui-this",k="laydate-disabled",h=[100,2e5],T="layui-laydate-static",w="layui-laydate-list",o="laydate-selected",r="layui-laydate-hint",y="laydate-day-prev",m="laydate-day-next",C=".laydate-btns-confirm",M="laydate-time-text",L="laydate-btns-time",E="layui-laydate-preview",S="layui-laydate-shade",I=function(e){var t,a=this,n=(a.index=++D.index,a.config=lay.extend({},a.config,D.config,e),lay(e.elem||a.config.elem));return 1\u8bf7\u91cd\u65b0\u9009\u62e9",invalidDate:"\u4e0d\u5728\u6709\u6548\u65e5\u671f\u6216\u65f6\u95f4\u8303\u56f4\u5185",formatError:["\u65e5\u671f\u683c\u5f0f\u4e0d\u5408\u6cd5
\u5fc5\u987b\u9075\u5faa\u4e0b\u8ff0\u683c\u5f0f\uff1a
","
\u5df2\u4e3a\u4f60\u91cd\u7f6e"],preview:"\u5f53\u524d\u9009\u4e2d\u7684\u7ed3\u679c"},en:{weeks:["Su","Mo","Tu","We","Th","Fr","Sa"],time:["Hours","Minutes","Seconds"],timeTips:"Select Time",startTime:"Start Time",endTime:"End Time",dateTips:"Select Date",month:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],tools:{confirm:"Confirm",clear:"Clear",now:"Now"},timeout:"End time cannot be less than start Time
Please re-select",invalidDate:"Invalid date",formatError:["The date format error
Must be followed\uff1a
","
It has been reset"],preview:"The selected result"}};return e[this.config.lang]||e.cn},I.prototype.reload=function(e){this.config=lay.extend({},this.config,e),this.init()},I.prototype.init=function(){var r=this,o=r.config,e="static"===o.position,t={year:"yyyy",month:"yyyy-MM",date:"yyyy-MM-dd",time:"HH:mm:ss",datetime:"yyyy-MM-dd HH:mm:ss"};o.elem=lay(o.elem),o.eventElem=lay(o.eventElem),o.elem[0]&&("array"!==layui.type(o.theme)&&(o.theme=[o.theme]),o.fullPanel&&("datetime"!==o.type||o.range)&&delete o.fullPanel,r.rangeStr=o.range?"string"==typeof o.range?o.range:"-":"",r.rangeLinked=!(!o.range||!o.rangeLinked||"date"!==o.type&&"datetime"!==o.type),r.autoCalendarModel=function(){var e=r.rangeLinked;return r.rangeLinked=o.range&&("date"===o.type||"datetime"===o.type)&&(!r.startDate||!r.endDate||r.startDate&&r.endDate&&r.startDate.year===r.endDate.year&&r.startDate.month===r.endDate.month),lay(r.elem)[r.rangeLinked?"addClass":"removeClass"]("layui-laydate-linkage"),r.rangeLinked!=e},r.autoCalendarModel.auto=r.rangeLinked&&"auto"===o.rangeLinked,"array"===layui.type(o.range)&&(r.rangeElem=[lay(o.range[0]),lay(o.range[1])]),t[o.type]||(i.console&&console.error&&console.error("laydate type error:'"+o.type+"' is not supported"),o.type="date"),o.format===t.date&&(o.format=t[o.type]||t.date),r.format=s.formatArr(o.format),o.weekStart&&!/^[0-6]$/.test(o.weekStart)&&(t=r.lang(),o.weekStart=t.weeks.indexOf(o.weekStart),-1===o.weekStart)&&(o.weekStart=0),r.EXP_IF="",r.EXP_SPLIT="",lay.each(r.format,function(e,t){e=new RegExp(c).test(t)?"\\d{"+(new RegExp(c).test(r.format[0===e?e+1:e-1]||"")?/^yyyy|y$/.test(t)?4:t.length:/^yyyy$/.test(t)?"1,4":/^y$/.test(t)?"1,308":"1,2")+"}":"\\"+t;r.EXP_IF=r.EXP_IF+e,r.EXP_SPLIT=r.EXP_SPLIT+"("+e+")"}),r.EXP_IF_ONE=new RegExp("^"+r.EXP_IF+"$"),r.EXP_IF=new RegExp("^"+(o.range?r.EXP_IF+"\\s\\"+r.rangeStr+"\\s"+r.EXP_IF:r.EXP_IF)+"$"),r.EXP_SPLIT=new RegExp("^"+r.EXP_SPLIT+"$",""),r.isInput(o.elem[0])||"focus"===o.trigger&&(o.trigger="click"),o.elem.attr("lay-key",r.index),o.eventElem.attr("lay-key",r.index),o.elem.attr(d,o.id),o.mark=lay.extend({},o.calendar&&"cn"===o.lang?{"0-1-1":"\u5143\u65e6","0-2-14":"\u60c5\u4eba","0-3-8":"\u5987\u5973","0-3-12":"\u690d\u6811","0-4-1":"\u611a\u4eba","0-5-1":"\u52b3\u52a8","0-5-4":"\u9752\u5e74","0-6-1":"\u513f\u7ae5","0-9-10":"\u6559\u5e08","0-10-1":"\u56fd\u5e86","0-12-25":"\u5723\u8bde"}:{},o.mark),lay.each(["min","max"],function(e,t){var a=[],n=[];if("number"==typeof o[t])var i=o[t],l=new Date,l=r.newDate({year:l.getFullYear(),month:l.getMonth(),date:l.getDate(),hours:e?23:0,minutes:e?59:0,seconds:e?59:0}).getTime(),e=new Date(i?i<864e5?l+864e5*i:i:l),a=[e.getFullYear(),e.getMonth()+1,e.getDate()],n=[e.getHours(),e.getMinutes(),e.getSeconds()];else if("string"==typeof o[t])a=(o[t].match(/\d+-\d+-\d+/)||[""])[0].split("-"),n=(o[t].match(/\d+:\d+:\d+/)||[""])[0].split(":");else if("object"==typeof o[t])return o[t];o[t]={year:0|a[0]||(new Date).getFullYear(),month:a[1]?(0|a[1])-1:(new Date).getMonth(),date:0|a[2]||(new Date).getDate(),hours:0|n[0],minutes:0|n[1],seconds:0|n[2]}}),r.elemID="layui-laydate"+o.elem.attr("lay-key"),(o.show||e)&&r.render(),e||r.events(),o.value)&&o.isInitValue&&("date"===layui.type(o.value)?r.setValue(r.parse(0,r.systemDate(o.value))):r.setValue(o.value))},I.prototype.render=function(){var a,n,i,l,r=this,o=r.config,d=r.lang(),s="static"===o.position,y=r.elem=lay.elem("div",{id:r.elemID,"class":["layui-laydate",o.range?" layui-laydate-range":"",r.rangeLinked?" layui-laydate-linkage":"",s?" "+T:"",o.fullPanel?" laydate-theme-fullpanel":"",(a="",lay.each(o.theme,function(e,t){"default"===t||/^#/.test(t)||(a+=" laydate-theme-"+t)}),a)].join("")}),m=r.elemMain=[],c=r.elemHeader=[],u=r.elemCont=[],h=r.table=[],e=r.footer=lay.elem("div",{"class":"layui-laydate-footer"}),t=r.shortcut=lay.elem("ul",{"class":"layui-laydate-shortcut"}),f=(o.zIndex&&(y.style.zIndex=o.zIndex),lay.each(new Array(2),function(e){if(!o.range&&0'+d.timeTips+""),(o.range||"datetime"!==o.type||o.fullPanel)&&f.push(''),lay.each(o.btns,function(e,t){var a=d.tools[t]||"btn";o.range&&"now"===t||(s&&"clear"===t&&(a="cn"===o.lang?"\u91cd\u7f6e":"Reset"),n.push(''+a+""))}),f.push('"),f.join(""))),o.shortcuts&&(y.appendChild(t),lay(t).html((i=[],lay.each(o.shortcuts,function(e,t){i.push('
  • '+t.text+"
  • ")}),i.join(""))).find("li").on("click",function(e){var t=o.shortcuts[this.dataset.index]||{},t=("function"==typeof t.value?t.value():t.value)||[],n=(layui.isArray(t)||(t=[t]),o.type),t=(lay.each(t,function(e,t){var a=[o.dateTime,r.endDate][e];"time"===n&&"date"!==layui.type(t)?r.EXP_IF.test(t)&&(t=(t.match(r.EXP_SPLIT)||[]).slice(1),lay.extend(a,{hours:0|t[0],minutes:0|t[2],seconds:0|t[4]})):lay.extend(a,r.systemDate("date"===layui.type(t)?t:new Date(t))),"time"!==n&&"datetime"!==n||(r[["startTime","endTime"][e]]={hours:a.hours,minutes:a.minutes,seconds:a.seconds}),0===e?r.startDate=lay.extend({},a):r.endState=!0,"year"===n||"month"===n||"time"===n?r.listYM[e]=[a.year,a.month+1]:e&&r.autoCalendarModel.auto&&r.autoCalendarModel()}),r.checkDate("limit").calendar(null,null,"init"),lay(r.footer).find("."+L).removeClass(k));t&&"date"===t.attr("lay-type")&&t[0].click(),r.done(null,"change"),lay(this).addClass(x),"static"!==o.position&&r.setValue(r.parse()).done().remove()})),lay.each(m,function(e,t){y.appendChild(t)}),o.showBottom&&y.appendChild(e),lay.elem("style")),p=[],g=!0,t=(lay.each(o.theme,function(e,t){g&&/^#/.test(t)?(g=!(l=!0),p.push(["#{{id}} .layui-laydate-header{background-color:{{theme}};}","#{{id}} li.layui-this,#{{id}} td.layui-this>div{background-color:{{theme}} !important;}",-1!==o.theme.indexOf("circle")?"":"#{{id}} .layui-this{background-color:{{theme}} !important;}","#{{id}} .laydate-day-now{color:{{theme}} !important;}","#{{id}} .laydate-day-now:after{border-color:{{theme}} !important;}"].join("").replace(/{{id}}/g,r.elemID).replace(/{{theme}}/g,t))):!g&&/^#/.test(t)&&p.push(["#{{id}} .laydate-selected>div{background-color:{{theme}} !important;}","#{{id}} .laydate-selected:hover>div{background-color:{{theme}} !important;}"].join("").replace(/{{id}}/g,r.elemID).replace(/{{theme}}/g,t))}),o.shortcuts&&o.range&&p.push("#{{id}}.layui-laydate-range{width: 628px;}".replace(/{{id}}/g,r.elemID)),p.length&&(p=p.join(""),"styleSheet"in f?(f.setAttribute("type","text/css"),f.styleSheet.cssText=p):f.innerHTML=p,l&&lay(y).addClass("laydate-theme-molv"),y.appendChild(f)),r.remove(I.thisElemDate),D.thisId=o.id,s?o.elem.append(y):(v.body.appendChild(y),r.position()),o.shade?'
    ':"");y.insertAdjacentHTML("beforebegin",t),r.checkDate().calendar(null,0,"init"),r.changeEvent(),I.thisElemDate=r.elemID,r.renderAdditional(),"function"==typeof o.ready&&o.ready(lay.extend({},o.dateTime,{month:o.dateTime.month+1})),r.preview()},I.prototype.remove=function(e){var t=this,a=t.config,n=lay("#"+(e||t.elemID));return n[0]&&(n.hasClass(T)||t.checkDate(function(){n.remove(),delete t.startDate,delete t.endDate,delete t.endState,delete t.startTime,delete t.endTime,delete D.thisId,"function"==typeof a.close&&a.close(t)}),lay("."+S).remove()),t},I.prototype.position=function(){var e=this.config;return lay.position(e.elem[0],this.elem,{position:e.position}),this},I.prototype.hint=function(e){var t=this,a=(t.config,lay.elem("div",{"class":r}));t.elem&&(a.innerHTML=(e="object"==typeof e?e||{}:{content:e}).content||"",lay(t.elem).find("."+r).remove(),t.elem.appendChild(a),clearTimeout(t.hinTimer),t.hinTimer=setTimeout(function(){lay(t.elem).find("."+r).remove()},"ms"in e?e.ms:3e3))},I.prototype.getAsYM=function(e,t,a){return a?t--:t++,t<0&&(t=11,e--),11h[1]&&(e.year=h[1],o=!0),11t)&&(e.date=t,o=!0)},u=function(n,i,l){var r=["startTime","endTime"];i=(i.match(d.EXP_SPLIT)||[]).slice(1),l=l||0,s.range&&(d[r[l]]=d[r[l]]||{}),lay.each(d.format,function(e,t){var a=parseFloat(i[e]);i[e].lengthd.getDateTime(s.max)?(r=s.dateTime=lay.extend({},s.max),i=!0):d.getDateTime(r)d.getDateTime(s.max))&&(d.endDate=lay.extend({},s.max),i=!0),d.startTime={hours:s.dateTime.hours,minutes:s.dateTime.minutes,seconds:s.dateTime.seconds},d.endTime={hours:d.endDate.hours,minutes:d.endDate.minutes,seconds:d.endDate.seconds},"month"===s.type)&&(s.dateTime.date=1,d.endDate.date=1),i&&m&&(d.setValue(d.parse()),d.hint("value "+l.invalidDate+l.formatError[1])),d.startDate=d.startDate||m&&lay.extend({},s.dateTime),d.autoCalendarModel.auto&&d.autoCalendarModel(),d.endState=!s.range||!d.rangeLinked||!(!d.startDate||!d.endDate),e&&e()),d},I.prototype.mark=function(e,a){var n,t=this.config;return lay.each(t.mark,function(e,t){e=e.split("-");e[0]!=a[0]&&0!=e[0]||e[1]!=a[1]&&0!=e[1]||e[2]!=a[2]||(n=t||a[2])}),n&&e.find("div").html(''+n+""),this},I.prototype.holidays=function(n,i){var e=this.config,l=["","work"];return"array"===layui.type(e.holidays)&&lay.each(e.holidays,function(a,e){lay.each(e,function(e,t){t===n.attr("lay-ymd")&&n.find("div").html('"+i[2]+"")})}),this},I.prototype.limit=function(t){t=t||{};var i=this,e=i.config,l={},a=t.index>(t.time?0:41)?i.endDate:e.dateTime;return lay.each({now:lay.extend({},a,t.date||{}),min:e.min,max:e.max},function(e,a){var n;l[e]=i.newDate(lay.extend({year:a.year,month:"year"===t.type?0:a.month,date:"year"===t.type||"month"===t.type?1:a.date},(n={},lay.each(t.time,function(e,t){n[t]=a[t]}),n))).getTime()}),a=l.nowh[1]&&(d.year=h[1],o.hint(y.invalidDate)),o.firstDate||(o.firstDate=lay.extend({},d)),s.setFullYear(d.year,d.month,1),i=(s.getDay()+(7-n.weekStart))%7,l=D.getEndDate(d.month||12,d.year),r=D.getEndDate(d.month+1,d.year),lay.each(c,function(e,t){var a,n=[d.year,d.month];(t=lay(t)).removeAttr("class"),e"+n[2]+""),o.mark(t,n).holidays(t,n).limit({elem:t,date:{year:n[0],month:n[1]-1,date:n[2]},index:e})}),lay(u[0]).attr("lay-ym",d.year+"-"+(d.month+1)),lay(u[1]).attr("lay-ym",d.year+"-"+(d.month+1)),"cn"===n.lang?(lay(u[0]).attr("lay-type","year").html(d.year+" \u5e74"),lay(u[1]).attr("lay-type","month").html(d.month+1+" \u6708")):(lay(u[0]).attr("lay-type","month").html(y.month[d.month]),lay(u[1]).attr("lay-type","year").html(d.year)),m&&(n.range?!e&&"init"===a||(o.listYM=[[(o.startDate||n.dateTime).year,(o.startDate||n.dateTime).month+1],[o.endDate.year,o.endDate.month+1]],o.list(n.type,0).list(n.type,1),"time"===n.type?o.setBtnStatus("\u65f6\u95f4",lay.extend({},o.systemDate(),o.startTime),lay.extend({},o.systemDate(),o.endTime)):o.setBtnStatus(!0)):(o.listYM=[[d.year,d.month+1]],o.list(n.type,0))),n.range&&"init"===a&&(o.rangeLinked?(s=o.getAsYM(d.year,d.month,t?"sub":null),o.calendar(lay.extend({},d,{year:s[0],month:s[1]}),1-t)):o.calendar(null,1-t)),n.range||(c=["hours","minutes","seconds"],o.limit({elem:lay(o.footer).find(".laydate-btns-now"),date:o.systemDate(/^(datetime|time)$/.test(n.type)?new Date:null),index:0,time:c}),o.limit({elem:lay(o.footer).find(C),index:0,time:c})),o.setBtnStatus(),lay(o.shortcut).find("li."+x).removeClass(x),n.range&&!m&&"init"!==a&&o.stampRange(),o},I.prototype.list=function(n,i){var l,r,e,o,d=this,s=d.config,y=d.rangeLinked?s.dateTime:[s.dateTime,d.endDate][i],m=d.lang(),t=s.range&&"date"!==s.type&&"datetime"!==s.type,c=lay.elem("ul",{"class":w+" "+{year:"laydate-year-list",month:"laydate-month-list",time:"laydate-time-list"}[n]}),a=d.elemHeader[i],u=lay(a[2]).find("span"),h=d.elemCont[i||0],f=lay(h).find("."+w)[0],p="cn"===s.lang,g=p?"\u5e74":"",v=d.listYM[i]||{},D=["hours","minutes","seconds"],T=["startTime","endTime"][i];return v[0]<1&&(v[0]=1),"year"===n?(e=l=v[0]-7,l<1&&(e=l=1),lay.each(new Array(15),function(e){var t=lay.elem("li",{"lay-ym":l}),a={year:l,month:0,date:1};l==v[0]&&lay(t).addClass(x),t.innerHTML=l+g,c.appendChild(t),d.limit({elem:lay(t),date:a,index:i,type:n}),l++}),lay(u[p?0:1]).attr("lay-ym",l-8+"-"+v[1]).html(e+g+" - "+(l-1)+g)):"month"===n?(lay.each(new Array(12),function(e){var t=lay.elem("li",{"lay-ym":e}),a={year:v[0],month:e,date:1};e+1==v[1]&&lay(t).addClass(x),t.innerHTML=m.month[e]+(p?"\u6708":""),c.appendChild(t),d.limit({elem:lay(t),date:a,index:i,type:n})}),lay(u[p?0:1]).attr("lay-ym",v[0]+"-"+v[1]).html(v[0]+g)):"time"===n&&(r=function(){lay(c).find("ol").each(function(a,e){lay(e).find("li").each(function(e,t){d.limit({elem:lay(t),date:[{hours:e},{hours:d[T].hours,minutes:e},{hours:d[T].hours,minutes:d[T].minutes,seconds:e}][a],index:i,time:[["hours"],["hours","minutes"],["hours","minutes","seconds"]][a]})})}),s.range||d.limit({elem:lay(d.footer).find(C),date:d[T],index:0,time:["hours","minutes","seconds"]})},s.range?d[T]||(d[T]="startTime"===T?y:d.endDate):d[T]=y,lay.each([24,60,60],function(t,e){var a=lay.elem("li"),n=["

    "+m.time[t]+"

      "];lay.each(new Array(e),function(e){n.push(""+lay.digit(e,2)+"")}),a.innerHTML=n.join("")+"
    ",c.appendChild(a)}),r()),f&&h.removeChild(f),h.appendChild(c),"year"===n||"month"===n?(lay(d.elemMain[i]).addClass("laydate-ym-show"),lay(c).find("li").on("click",function(){var e=0|lay(this).attr("lay-ym");lay(this).hasClass(k)||(d.rangeLinked?lay.extend(y,{year:"year"===n?e:v[0],month:"year"===n?v[1]-1:e}):y[n]=e,"year"===s.type||"month"===s.type?(lay(c).find("."+x).removeClass(x),lay(this).addClass(x),"month"===s.type&&"year"===n&&(d.listYM[i][0]=e,t&&((i?d.endDate:y).year=e),d.list("month",i))):(d.checkDate("limit").calendar(y,i,"init"),d.closeList()),d.setBtnStatus(),!s.range&&s.autoConfirm&&("month"===s.type&&"month"===n||"year"===s.type&&"year"===n)&&d.setValue(d.parse()).done().remove(),d.autoCalendarModel.auto&&!d.rangeLinked?d.choose(lay(h).find("td.layui-this"),i):d.endState&&d.done(null,"change"),lay(d.footer).find("."+L).removeClass(k))})):(e=lay.elem("span",{"class":M}),o=function(){lay(c).find("ol").each(function(e){var a=this,t=lay(a).find("li");a.scrollTop=30*(d[T][D[e]]-2),a.scrollTop<=0&&t.each(function(e,t){if(!lay(this).hasClass(k))return a.scrollTop=30*(e-2),!0})})},u=lay(a[2]).find("."+M),o(),e.innerHTML=s.range?[m.startTime,m.endTime][i]:m.timeTips,lay(d.elemMain[i]).addClass("laydate-time-show"),u[0]&&u.remove(),a[2].appendChild(e),(f=lay(c).find("ol")).each(function(t){var a=this;lay(a).find("li").on("click",function(){var e=0|this.innerHTML;lay(this).hasClass(k)||(s.range?d[T][D[t]]=e:y[D[t]]=e,lay(a).find("."+x).removeClass(x),lay(this).addClass(x),r(),o(),(d.endDate||"time"===s.type||"datetime"===s.type&&s.fullPanel)&&d.done(null,"change"),d.setBtnStatus())})}),lay.touchEventsSupported()&&f.on("touchstart",function(){this.style["overflow-y"]="auto"})),d},I.prototype.listYM=[],I.prototype.closeList=function(){var a=this;a.config;lay.each(a.elemCont,function(e,t){lay(this).find("."+w).remove(),lay(a.elemMain[e]).removeClass("laydate-ym-show laydate-time-show")}),lay(a.elem).find("."+M).remove()},I.prototype.setBtnStatus=function(e,t,a){var n=this,i=n.config,l=n.lang(),r=lay(n.footer).find(C);i.range&&"time"!==i.type&&(t=t||(n.rangeLinked?n.startDate:i.dateTime),a=a||n.endDate,i=!n.endState||n.newDate(t).getTime()>n.newDate(a).getTime(),n.limit({date:t})||n.limit({date:a})?r.addClass(k):r[i?"addClass":"removeClass"](k),e)&&i&&n.hint("string"==typeof e?l.timeout.replace(/\u65e5\u671f/g,e):l.timeout)},I.prototype.parse=function(e,t){var a=this,n=a.config,i=a.rangeLinked?a.startDate:n.dateTime,t=t||("end"==e?lay.extend({},a.endDate,a.endTime):n.range?lay.extend({},i||n.dateTime,a.startTime):n.dateTime),i=D.parse(t,a.format,1);return n.range&&e===undefined?i+" "+a.rangeStr+" "+a.parse("end"):i},I.prototype.newDate=function(e){return e=e||{},new Date(e.year||1,e.month||0,e.date||1,e.hours||0,e.minutes||0,e.seconds||0)},I.prototype.getDateTime=function(e){return this.newDate(e).getTime()},I.prototype.setValue=function(e){var t=this,a=t.config,n=a.elem[0];return"static"!==a.position&&(e=e||"",t.isInput(n)?lay(n).val(e):(a=t.rangeElem)?("array"!==layui.type(e)&&(e=e.split(" "+t.rangeStr+" ")),a[0].val(e[0]||""),a[1].val(e[1]||"")):(0===lay(n).find("*").length&&lay(n).html(e),lay(n).attr("lay-date",e))),t},I.prototype.preview=function(){var e,t=this,a=t.config;a.isPreview&&(e=lay(t.elem).find("."+E),a=!a.range||(t.rangeLinked?t.endState:t.endDate)?t.parse():"",e.html(a),e.html())&&(e.css({color:"#16b777"}),setTimeout(function(){e.css({color:"#777"})},300))},I.prototype.renderAdditional=function(){this.config.fullPanel&&this.list("time",0)},I.prototype.stampRange=function(){var n,i=this,l=i.config,r=i.rangeLinked?i.startDate:l.dateTime,e=lay(i.elem).find("td");l.range&&!i.endState&&lay(i.footer).find(C).addClass(k),r=r&&i.newDate({year:r.year,month:r.month,date:r.date}).getTime(),n=i.endState&&i.endDate&&i.newDate({year:i.endDate.year,month:i.endDate.month,date:i.endDate.date}).getTime(),lay.each(e,function(e,t){var a=lay(t).attr("lay-ymd").split("-"),a=i.newDate({year:a[0],month:a[1]-1,date:a[2]}).getTime();l.rangeLinked&&!i.startDate&&a===i.newDate(i.systemDate()).getTime()&&lay(t).addClass(lay(t).hasClass(y)||lay(t).hasClass(m)?"":"laydate-day-now"),lay(t).removeClass(o+" "+x),a!==r&&a!==n||(i.rangeLinked||!i.rangeLinked&&(e<42?a===r:a===n))&&lay(t).addClass(lay(t).hasClass(y)||lay(t).hasClass(m)?o:x),rn.getDateTime(i.max)&&(n[t]={hours:i.max.hours,minutes:i.max.minutes,seconds:i.max.seconds},lay.extend(l,n[t])))}),a||(n.startDate=lay.extend({},l)),n.endState&&!n.limit({date:n.thisDateTime(1-a)})&&(((r=n.endState&&n.autoCalendarModel.auto?n.autoCalendarModel():r)||n.rangeLinked&&n.endState)&&n.newDate(n.startDate)>n.newDate(n.endDate)&&(e=n.startDate.year===n.endDate.year&&n.startDate.month===n.endDate.month&&n.startDate.date===n.endDate.date,o=n.startDate,n.startDate=lay.extend({},n.endDate,e?{}:n.startTime),i.dateTime=lay.extend({},n.startDate),n.endDate=lay.extend({},o,e?{}:n.endTime),e)&&(o=n.startTime,n.startTime=n.endTime,n.endTime=o),r)&&(i.dateTime=lay.extend({},n.startDate)),n.rangeLinked?(e=lay.extend({},l),!t||a||r||(o=n.getAsYM(l.year,l.month,"sub"),lay.extend(i.dateTime,{year:o[0],month:o[1]})),n.calendar(e,t,r?"init":null)):n.calendar(null,a,r?"init":null),n.endState&&n.done(null,"change")):"static"===i.position?n.calendar().done().done(null,"change"):"date"===i.type?i.autoConfirm?n.setValue(n.parse()).done().remove():n.calendar().done(null,"change"):"datetime"===i.type&&n.calendar().done(null,"change"))},I.prototype.tool=function(t,e){var a=this,n=a.config,i=a.lang(),l=n.dateTime,r="static"===n.position,o={datetime:function(){lay(t).hasClass(k)||(a.list("time",0),n.range&&a.list("time",1),lay(t).attr("lay-type","date").html(a.lang().dateTips))},date:function(){a.closeList(),lay(t).attr("lay-type","datetime").html(a.lang().timeTips)},clear:function(){r&&(lay.extend(l,a.firstDate),a.calendar()),n.range&&(delete n.dateTime,delete a.endDate,delete a.startTime,delete a.endTime),a.setValue(""),a.done(null,"onClear").done(["",{},{}]).remove()},now:function(){var e=new Date;if(lay(t).hasClass(k))return a.hint(i.tools.now+", "+i.invalidDate);lay.extend(l,a.systemDate(),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()}),a.setValue(a.parse()),r&&a.calendar(),a.done(null,"onNow").done().remove()},confirm:function(){if(n.range){if(lay(t).hasClass(k))return a.hint("time"===n.type?i.timeout.replace(/\u65e5\u671f/g,"\u65f6\u95f4"):i.timeout)}else if(lay(t).hasClass(k))return a.hint(i.invalidDate);a.setValue(a.parse()),a.done(null,"onConfirm").done().remove()}};o[e]&&o[e]()},I.prototype.change=function(n){var i=this,l=i.config,r=i.thisDateTime(n),o=l.range&&("year"===l.type||"month"===l.type),d=i.elemCont[n||0],s=i.listYM[n],e=function(e){var t=lay(d).find(".laydate-year-list")[0],a=lay(d).find(".laydate-month-list")[0];return t&&(s[0]=e?s[0]-15:s[0]+15,i.list("year",n)),a&&(e?s[0]--:s[0]++,i.list("month",n)),(t||a)&&(lay.extend(r,{year:s[0]}),o&&(r.year=s[0]),l.range||i.done(null,"change"),l.range||i.limit({elem:lay(i.footer).find(C),date:{year:s[0]}})),i.setBtnStatus(),t||a};return{prevYear:function(){e("sub")||(i.rangeLinked?(l.dateTime.year--,i.checkDate("limit").calendar(null,null,"init")):(r.year--,i.checkDate("limit").calendar(null,n),i.autoCalendarModel.auto?i.choose(lay(d).find("td.layui-this"),n):i.done(null,"change")))},prevMonth:function(){i.rangeLinked&&(r=l.dateTime);var e=i.getAsYM(r.year,r.month,"sub");lay.extend(r,{year:e[0],month:e[1]}),i.checkDate("limit").calendar(null,null,"init"),i.rangeLinked||(i.autoCalendarModel.auto?i.choose(lay(d).find("td.layui-this"),n):i.done(null,"change"))},nextMonth:function(){i.rangeLinked&&(r=l.dateTime);var e=i.getAsYM(r.year,r.month);lay.extend(r,{year:e[0],month:e[1]}),i.checkDate("limit").calendar(null,null,"init"),i.rangeLinked||(i.autoCalendarModel.auto?i.choose(lay(d).find("td.layui-this"),n):i.done(null,"change"))},nextYear:function(){e()||(i.rangeLinked?(l.dateTime.year++,i.checkDate("limit").calendar(null,0,"init")):(r.year++,i.checkDate("limit").calendar(null,n),i.autoCalendarModel.auto?i.choose(lay(d).find("td.layui-this"),n):i.done(null,"change")))}}},I.prototype.changeEvent=function(){var i=this;i.config;lay(i.elem).on("click",function(e){lay.stope(e)}).on("mousedown",function(e){lay.stope(e)}),lay.each(i.elemHeader,function(n,e){lay(e[0]).on("click",function(e){i.change(n).prevYear()}),lay(e[1]).on("click",function(e){i.change(n).prevMonth()}),lay(e[2]).find("span").on("click",function(e){var t=lay(this),a=t.attr("lay-ym"),t=t.attr("lay-type");a&&(a=a.split("-"),i.listYM[n]=[0|a[0],0|a[1]],i.list(t,n),lay(i.footer).find("."+L).addClass(k))}),lay(e[3]).on("click",function(e){i.change(n).nextMonth()}),lay(e[4]).on("click",function(e){i.change(n).nextYear()})}),lay.each(i.table,function(e,t){lay(t).find("td").on("click",function(){i.choose(lay(this),e)})}),lay(i.footer).find("span").on("click",function(){var e=lay(this).attr("lay-type");i.tool(this,e)})},I.prototype.isInput=function(e){return/input|textarea/.test(e.tagName.toLocaleLowerCase())||/INPUT|TEXTAREA/.test(e.tagName)},I.prototype.events=function(){var e,t=this,a=t.config;a.elem[0]&&!a.elem[0].eventHandler&&(a.elem.on(a.trigger,e=function(){D.thisId!==a.id&&t.render()}),a.elem[0].eventHandler=!0,a.eventElem.on(a.trigger,e),t.unbind=function(){t.remove(),a.elem.off(a.trigger,e),a.elem.removeAttr("lay-key"),a.elem.removeAttr(d),a.elem[0].eventHandler=!1,a.eventElem.off(a.trigger,e),a.eventElem.removeAttr("lay-key"),delete s.that[a.id]})},s.that={},s.getThis=function(e){var t=s.that[e];return!t&&n&&layui.hint().error(e?a+" instance with ID '"+e+"' not found":"ID argument required"),t},l.run=function(n){n(v).on("mousedown",function(e){var t,a;D.thisId&&(t=s.getThis(D.thisId))&&(a=t.config,e.target===a.elem[0]||e.target===a.eventElem[0]||e.target===n(a.closeStop)[0]||a.elem[0]&&a.elem[0].contains(e.target)||t.remove())}).on("keydown",function(e){var t;D.thisId&&(t=s.getThis(D.thisId))&&"static"!==t.config.position&&13===e.keyCode&&n("#"+t.elemID)[0]&&t.elemID===I.thisElemDate&&(e.preventDefault(),n(t.footer).find(C)[0].click())}),n(i).on("resize",function(){if(D.thisId){var e=s.getThis(D.thisId);if(e)return!(!e.elem||!n(".layui-laydate")[0])&&void e.position()}})},D.render=function(e){e=new I(e);return s.call(e)},D.reload=function(e,t){e=s.getThis(e);if(e)return e.reload(t)},D.getInst=function(e){e=s.getThis(e);if(e)return e.inst},D.hint=function(e,t){e=s.getThis(e);if(e)return e.hint(t)},D.unbind=function(e){e=s.getThis(e);if(e)return e.unbind()},D.close=function(e){e=s.getThis(e||D.thisId);if(e)return e.remove()},D.parse=function(a,n,i){return a=a||{},n=((n="string"==typeof n?s.formatArr(n):n)||[]).concat(),lay.each(n,function(e,t){/yyyy|y/.test(t)?n[e]=lay.digit(a.year,t.length):/MM|M/.test(t)?n[e]=lay.digit(a.month+(i||0),t.length):/dd|d/.test(t)?n[e]=lay.digit(a.date,t.length):/HH|H/.test(t)?n[e]=lay.digit(a.hours,t.length):/mm|m/.test(t)?n[e]=lay.digit(a.minutes,t.length):/ss|s/.test(t)&&(n[e]=lay.digit(a.seconds,t.length))}),n.join("")},D.getEndDate=function(e,t){var a=new Date;return a.setFullYear(t||a.getFullYear(),e||a.getMonth()+1,1),new Date(a.getTime()-864e5).getDate()},n?(D.ready(),layui.define("lay",function(e){D.path=layui.cache.dir,l.run(lay),e(a,D)})):"function"==typeof define&&define.amd?define(function(){return l.run(lay),D}):(D.ready(),l.run(i.lay),i.laydate=D)}(window,window.document);!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e):function(e){if(e.document)return t(e);throw new Error("jQuery requires a window with a document")}:t(e)}("undefined"!=typeof window?window:this,function(T,M){var f=[],g=T.document,c=f.slice,O=f.concat,R=f.push,P=f.indexOf,B={},W=B.toString,m=B.hasOwnProperty,y={},e="1.12.4",C=function(e,t){return new C.fn.init(e,t)},I=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,$=/^-ms-/,z=/-([\da-z])/gi,X=function(e,t){return t.toUpperCase()};function U(e){var t=!!e&&"length"in e&&e.length,n=C.type(e);return"function"!==n&&!C.isWindow(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+a+")"+a+"*"),ee=new RegExp("="+a+"*([^\\]'\"]*?)"+a+"*\\]","g"),te=new RegExp(G),ne=new RegExp("^"+s+"$"),f={ID:new RegExp("^#("+s+")"),CLASS:new RegExp("^\\.("+s+")"),TAG:new RegExp("^("+s+"|[*])"),ATTR:new RegExp("^"+J),PSEUDO:new RegExp("^"+G),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+a+"*(even|odd|(([+-]|)(\\d*)n|)"+a+"*(?:([+-]|)"+a+"*(\\d+)|))"+a+"*\\)|)","i"),bool:new RegExp("^(?:"+Y+")$","i"),needsContext:new RegExp("^"+a+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+a+"*((?:-\\d)?\\d*)"+a+"*\\)|)(?=[^-]|$)","i")},re=/^(?:input|select|textarea|button)$/i,ie=/^h\d$/i,c=/^[^{]+\{\s*\[native \w/,oe=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ae=/[+~]/,se=/'|\\/g,d=new RegExp("\\\\([\\da-f]{1,6}"+a+"?|("+a+")|.)","ig"),p=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(65536+r):String.fromCharCode(r>>10|55296,1023&r|56320)},ue=function(){C()};try{D.apply(n=V.call(v.childNodes),v.childNodes),n[v.childNodes.length].nodeType}catch(F){D={apply:n.length?function(e,t){U.apply(e,V.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function H(e,t,n,r){var i,o,a,s,u,l,c,f,d=t&&t.ownerDocument,p=t?t.nodeType:9;if(n=n||[],"string"!=typeof e||!e||1!==p&&9!==p&&11!==p)return n;if(!r&&((t?t.ownerDocument||t:v)!==E&&C(t),t=t||E,N)){if(11!==p&&(l=oe.exec(e)))if(i=l[1]){if(9===p){if(!(a=t.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(d&&(a=d.getElementById(i))&&y(t,a)&&a.id===i)return n.push(a),n}else{if(l[2])return D.apply(n,t.getElementsByTagName(e)),n;if((i=l[3])&&g.getElementsByClassName&&t.getElementsByClassName)return D.apply(n,t.getElementsByClassName(i)),n}if(g.qsa&&!A[e+" "]&&(!m||!m.test(e))){if(1!==p)d=t,f=e;else if("object"!==t.nodeName.toLowerCase()){for((s=t.getAttribute("id"))?s=s.replace(se,"\\$&"):t.setAttribute("id",s=k),o=(c=w(e)).length,u=ne.test(s)?"#"+s:"[id='"+s+"']";o--;)c[o]=u+" "+_(c[o]);f=c.join(","),d=ae.test(e)&&de(t.parentNode)||t}if(f)try{return D.apply(n,d.querySelectorAll(f)),n}catch(h){}finally{s===k&&t.removeAttribute("id")}}}return P(e.replace(L,"$1"),t,n,r)}function le(){var n=[];function r(e,t){return n.push(e+" ")>b.cacheLength&&delete r[n.shift()],r[e+" "]=t}return r}function q(e){return e[k]=!0,e}function h(e){var t=E.createElement("div");try{return!!e(t)}catch(F){return!1}finally{t.parentNode&&t.parentNode.removeChild(t)}}function ce(e,t){for(var n=e.split("|"),r=n.length;r--;)b.attrHandle[n[r]]=t}function fe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||1<<31)-(~e.sourceIndex||1<<31);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function x(a){return q(function(o){return o=+o,q(function(e,t){for(var n,r=a([],e.length,o),i=r.length;i--;)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function de(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in g=H.support={},O=H.isXML=function(e){e=e&&(e.ownerDocument||e).documentElement;return!!e&&"HTML"!==e.nodeName},C=H.setDocument=function(e){var e=e?e.ownerDocument||e:v;return e!==E&&9===e.nodeType&&e.documentElement&&(t=(E=e).documentElement,N=!O(E),(e=E.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",ue,!1):e.attachEvent&&e.attachEvent("onunload",ue)),g.attributes=h(function(e){return e.className="i",!e.getAttribute("className")}),g.getElementsByTagName=h(function(e){return e.appendChild(E.createComment("")),!e.getElementsByTagName("*").length}),g.getElementsByClassName=c.test(E.getElementsByClassName),g.getById=h(function(e){return t.appendChild(e).id=k,!E.getElementsByName||!E.getElementsByName(k).length}),g.getById?(b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&N)return(e=t.getElementById(e))?[e]:[]},b.filter.ID=function(e){var t=e.replace(d,p);return function(e){return e.getAttribute("id")===t}}):(delete b.find.ID,b.filter.ID=function(e){var t=e.replace(d,p);return function(e){e="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return e&&e.value===t}}),b.find.TAG=g.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):g.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"!==e)return o;for(;n=o[i++];)1===n.nodeType&&r.push(n);return r},b.find.CLASS=g.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&N)return t.getElementsByClassName(e)},r=[],m=[],(g.qsa=c.test(E.querySelectorAll))&&(h(function(e){t.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&m.push("[*^$]="+a+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||m.push("\\["+a+"*(?:value|"+Y+")"),e.querySelectorAll("[id~="+k+"-]").length||m.push("~="),e.querySelectorAll(":checked").length||m.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||m.push(".#.+[+~]")}),h(function(e){var t=E.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&m.push("name"+a+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||m.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),m.push(",.*:")})),(g.matchesSelector=c.test(i=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.msMatchesSelector))&&h(function(e){g.disconnectedMatch=i.call(e,"div"),i.call(e,"[s!='']:x"),r.push("!=",G)}),m=m.length&&new RegExp(m.join("|")),r=r.length&&new RegExp(r.join("|")),e=c.test(t.compareDocumentPosition),y=e||c.test(t.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},$=e?function(e,t){var n;return e===t?(l=!0,0):(n=!e.compareDocumentPosition-!t.compareDocumentPosition)||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!g.sortDetached&&t.compareDocumentPosition(e)===n?e===E||e.ownerDocument===v&&y(v,e)?-1:t===E||t.ownerDocument===v&&y(v,t)?1:u?j(u,e)-j(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===E?-1:t===E?1:i?-1:o?1:u?j(u,e)-j(u,t):0;if(i===o)return fe(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?fe(a[r],s[r]):a[r]===v?-1:s[r]===v?1:0}),E},H.matches=function(e,t){return H(e,null,null,t)},H.matchesSelector=function(e,t){if((e.ownerDocument||e)!==E&&C(e),t=t.replace(ee,"='$1']"),g.matchesSelector&&N&&!A[t+" "]&&(!r||!r.test(t))&&(!m||!m.test(t)))try{var n=i.call(e,t);if(n||g.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(F){}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(d,p),e[3]=(e[3]||e[4]||e[5]||"").replace(d,p),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||H.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&H.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return f.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&te.test(n)&&(t=(t=w(n,!0))&&n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(d,p).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=W[e+" "];return t||(t=new RegExp("(^|"+a+")"+e+"("+a+"|$)"))&&W(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(t,n,r){return function(e){e=H.attr(e,t);return null==e?"!="===n:!n||(e+="","="===n?e===r:"!="===n?e!==r:"^="===n?r&&0===e.indexOf(r):"*="===n?r&&-1(?:<\/\1>|)$/,G=/^.[^:#\[\.,]*$/;function K(e,n,r){if(C.isFunction(n))return C.grep(e,function(e,t){return!!n.call(e,t,e)!==r});if(n.nodeType)return C.grep(e,function(e){return e===n!==r});if("string"==typeof n){if(G.test(n))return C.filter(n,e,r);n=C.filter(n,e)}return C.grep(e,function(e){return-1)[^>]*|#([\w-]*))$/,ee=((C.fn.init=function(e,t,n){if(e){if(n=n||Q,"string"!=typeof e)return e.nodeType?(this.context=this[0]=e,this.length=1,this):C.isFunction(e)?"undefined"!=typeof n.ready?n.ready(e):e(C):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),C.makeArray(e,this));if(!(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&3<=e.length?[null,e,null]:Z.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof C?t[0]:t,C.merge(this,C.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:g,!0)),J.test(r[1])&&C.isPlainObject(t))for(var r in t)C.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r])}else{if((n=g.getElementById(r[2]))&&n.parentNode){if(n.id!==r[2])return Q.find(e);this.length=1,this[0]=n}this.context=g,this.selector=e}}return this}).prototype=C.fn,Q=C(g),/^(?:parents|prev(?:Until|All))/),te={children:!0,contents:!0,next:!0,prev:!0};function ne(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}C.fn.extend({has:function(e){var t,n=C(e,this),r=n.length;return this.filter(function(){for(t=0;t
    a",y.leadingWhitespace=3===S.firstChild.nodeType,y.tbody=!S.getElementsByTagName("tbody").length,y.htmlSerialize=!!S.getElementsByTagName("link").length,y.html5Clone="<:nav>"!==g.createElement("nav").cloneNode(!0).outerHTML,q.type="checkbox",q.checked=!0,k.appendChild(q),y.appendChecked=q.checked,S.innerHTML="",y.noCloneChecked=!!S.cloneNode(!0).lastChild.defaultValue,k.appendChild(S),(q=g.createElement("input")).setAttribute("type","radio"),q.setAttribute("checked","checked"),q.setAttribute("name","t"),S.appendChild(q),y.checkClone=S.cloneNode(!0).cloneNode(!0).lastChild.checked,y.noCloneEvent=!!S.addEventListener,S[C.expando]=1,y.attributes=!S.getAttribute(C.expando);var x={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:y.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]};function b(e,t){var n,r,i=0,o="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):undefined;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||C.nodeName(r,t)?o.push(r):C.merge(o,b(r,t));return t===undefined||t&&C.nodeName(e,t)?C.merge([e],o):o}function we(e,t){for(var n,r=0;null!=(n=e[r]);r++)C._data(n,"globalEval",!t||C._data(t[r],"globalEval"))}x.optgroup=x.option,x.tbody=x.tfoot=x.colgroup=x.caption=x.thead,x.th=x.td;var Te=/<|&#?\w+;/,Ce=/"!==f[1]||Ce.test(a)?0:u:u.firstChild)&&a.childNodes.length;o--;)C.nodeName(c=a.childNodes[o],"tbody")&&!c.childNodes.length&&a.removeChild(c);for(C.merge(h,u.childNodes),u.textContent="";u.firstChild;)u.removeChild(u.firstChild);u=p.lastChild}else h.push(t.createTextNode(a));for(u&&p.removeChild(u),y.appendChecked||C.grep(b(h,"input"),Ee),g=0;a=h[g++];)if(r&&-1]","i"),Pe=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,Be=/\s*$/g,ze=be(g).appendChild(g.createElement("div"));function Xe(e,t){return C.nodeName(e,"table")&&C.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ue(e){return e.type=(null!==C.find.attr(e,"type"))+"/"+e.type,e}function Ve(e){var t=Ie.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Ye(e,t){if(1===t.nodeType&&C.hasData(e)){var n,r,i,e=C._data(e),o=C._data(t,e),a=e.events;if(a)for(n in delete o.handle,o.events={},a)for(r=0,i=a[n].length;r")},clone:function(e,t,n){var r,i,o,a,s,u=C.contains(e.ownerDocument,e);if(y.html5Clone||C.isXMLDoc(e)||!Re.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(ze.innerHTML=e.outerHTML,ze.removeChild(o=ze.firstChild)),!(y.noCloneEvent&&y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||C.isXMLDoc(e)))for(r=b(o),s=b(e),a=0;null!=(i=s[a]);++a)if(r[a]){f=c=l=p=d=void 0;var l,c,f,d=i,p=r[a];if(1===p.nodeType){if(l=p.nodeName.toLowerCase(),!y.noCloneEvent&&p[C.expando]){for(c in(f=C._data(p)).events)C.removeEvent(p,c,f.handle);p.removeAttribute(C.expando)}"script"===l&&p.text!==d.text?(Ue(p).text=d.text,Ve(p)):"object"===l?(p.parentNode&&(p.outerHTML=d.outerHTML),y.html5Clone&&d.innerHTML&&!C.trim(p.innerHTML)&&(p.innerHTML=d.innerHTML)):"input"===l&&ge.test(d.type)?(p.defaultChecked=p.checked=d.checked,p.value!==d.value&&(p.value=d.value)):"option"===l?p.defaultSelected=p.selected=d.defaultSelected:"input"!==l&&"textarea"!==l||(p.defaultValue=d.defaultValue)}}if(t)if(n)for(s=s||b(e),r=r||b(o),a=0;null!=(i=s[a]);a++)Ye(i,r[a]);else Ye(e,o);return 0<(r=b(o,"script")).length&&we(r,!u&&b(e,"script")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=C.expando,u=C.cache,l=y.attributes,c=C.event.special;null!=(n=e[a]);a++)if((t||v(n))&&(o=(i=n[s])&&u[i])){if(o.events)for(r in o.events)c[r]?C.event.remove(n,r):C.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||"undefined"==typeof n.removeAttribute?n[s]=undefined:n.removeAttribute(s),f.push(i))}}}),C.fn.extend({domManip:w,detach:function(e){return Je(this,e,!0)},remove:function(e){return Je(this,e)},text:function(e){return d(this,function(e){return e===undefined?C.text(this):this.empty().append((this[0]&&this[0].ownerDocument||g).createTextNode(e))},null,e,arguments.length)},append:function(){return w(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Xe(this,e).appendChild(e)})},prepend:function(){return w(this,arguments,function(e){var t;1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(t=Xe(this,e)).insertBefore(e,t.firstChild)})},before:function(){return w(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return w(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&C.cleanData(b(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&C.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return C.clone(this,e,t)})},html:function(e){return d(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined)return 1===t.nodeType?t.innerHTML.replace(Oe,""):undefined;if("string"==typeof e&&!Be.test(e)&&(y.htmlSerialize||!Re.test(e))&&(y.leadingWhitespace||!ve.test(e))&&!x[(me.exec(e)||["",""])[1].toLowerCase()]){e=C.htmlPrefilter(e);try{for(;n")).appendTo(t.documentElement))[0].contentWindow||Ge[0].contentDocument).document).write(),t.close(),n=Qe(e,t),Ge.detach()),Ke[e]=n),n}var n,et,tt,nt,rt,it,ot,a,at=/^margin/,st=new RegExp("^("+e+")(?!px)[a-z%]+$","i"),ut=function(e,t,n,r){var i,o={};for(i in t)o[i]=e.style[i],e.style[i]=t[i];for(i in r=n.apply(e,r||[]),t)e.style[i]=o[i];return r},lt=g.documentElement;function t(){var e,t=g.documentElement;t.appendChild(ot),a.style.cssText="-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",n=tt=it=!1,et=rt=!0,T.getComputedStyle&&(e=T.getComputedStyle(a),n="1%"!==(e||{}).top,it="2px"===(e||{}).marginLeft,tt="4px"===(e||{width:"4px"}).width,a.style.marginRight="50%",et="4px"===(e||{marginRight:"4px"}).marginRight,(e=a.appendChild(g.createElement("div"))).style.cssText=a.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",e.style.marginRight=e.style.width="0",a.style.width="1px",rt=!parseFloat((T.getComputedStyle(e)||{}).marginRight),a.removeChild(e)),a.style.display="none",(nt=0===a.getClientRects().length)&&(a.style.display="",a.innerHTML="
    t
    ",a.childNodes[0].style.borderCollapse="separate",(e=a.getElementsByTagName("td"))[0].style.cssText="margin:0;border:0;padding:0;display:none",nt=0===e[0].offsetHeight)&&(e[0].style.display="",e[1].style.display="none",nt=0===e[0].offsetHeight),t.removeChild(ot)}ot=g.createElement("div"),(a=g.createElement("div")).style&&(a.style.cssText="float:left;opacity:.5",y.opacity="0.5"===a.style.opacity,y.cssFloat=!!a.style.cssFloat,a.style.backgroundClip="content-box",a.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===a.style.backgroundClip,(ot=g.createElement("div")).style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",a.innerHTML="",ot.appendChild(a),y.boxSizing=""===a.style.boxSizing||""===a.style.MozBoxSizing||""===a.style.WebkitBoxSizing,C.extend(y,{reliableHiddenOffsets:function(){return null==n&&t(),nt},boxSizingReliable:function(){return null==n&&t(),tt},pixelMarginRight:function(){return null==n&&t(),et},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),rt},reliableMarginLeft:function(){return null==n&&t(),it}}));var l,p,ct=/^(top|right|bottom|left)$/;function ft(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}T.getComputedStyle?(l=function(e){var t=e.ownerDocument.defaultView;return(t=t&&t.opener?t:T).getComputedStyle(e)},p=function(e,t,n){var r,i,o=e.style;return""!==(i=(n=n||l(e))?n.getPropertyValue(t)||n[t]:undefined)&&i!==undefined||C.contains(e.ownerDocument,e)||(i=C.style(e,t)),n&&!y.pixelMarginRight()&&st.test(i)&&at.test(t)&&(e=o.width,t=o.minWidth,r=o.maxWidth,o.minWidth=o.maxWidth=o.width=i,i=n.width,o.width=e,o.minWidth=t,o.maxWidth=r),i===undefined?i:i+""}):lt.currentStyle&&(l=function(e){return e.currentStyle},p=function(e,t,n){var r,i,o,a=e.style;return null==(n=(n=n||l(e))?n[t]:undefined)&&a&&a[t]&&(n=a[t]),st.test(n)&&!ct.test(t)&&(r=a.left,(o=(i=e.runtimeStyle)&&i.left)&&(i.left=e.currentStyle.left),a.left="fontSize"===t?"1em":n,n=a.pixelLeft+"px",a.left=r,o)&&(i.left=o),n===undefined?n:n+""||"auto"});var dt=/alpha\([^)]*\)/i,pt=/opacity\s*=\s*([^)]*)/i,ht=/^(none|table(?!-c[ea]).+)/,gt=new RegExp("^("+e+")(.*)$","i"),mt={position:"absolute",visibility:"hidden",display:"block"},yt={letterSpacing:"0",fontWeight:"400"},vt=["Webkit","O","Moz","ms"],xt=g.createElement("div").style;function bt(e){if(e in xt)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=vt.length;n--;)if((e=vt[n]+t)in xt)return e}function wt(e,t){for(var n,r,i,o=[],a=0,s=e.length;a
    a",F=q.getElementsByTagName("a")[0],k.setAttribute("type","checkbox"),q.appendChild(k),(F=q.getElementsByTagName("a")[0]).style.cssText="top:1px",y.getSetAttribute="t"!==q.className,y.style=/top/.test(F.getAttribute("style")),y.hrefNormalized="/a"===F.getAttribute("href"),y.checkOn=!!k.value,y.optSelected=e.selected,y.enctype=!!g.createElement("form").enctype,S.disabled=!0,y.optDisabled=!e.disabled,(k=g.createElement("input")).setAttribute("value",""),y.input=""===k.getAttribute("value"),k.value="t",k.setAttribute("type","radio"),y.radioValue="t"===k.value;var Lt=/\r/g,Ht=/[\x20\t\r\n\f]+/g;C.fn.extend({val:function(t){var n,e,r,i=this[0];return arguments.length?(r=C.isFunction(t),this.each(function(e){1!==this.nodeType||(null==(e=r?t.call(this,e,C(this).val()):t)?e="":"number"==typeof e?e+="":C.isArray(e)&&(e=C.map(e,function(e){return null==e?"":e+""})),(n=C.valHooks[this.type]||C.valHooks[this.nodeName.toLowerCase()])&&"set"in n&&n.set(this,e,"value")!==undefined)||(this.value=e)})):i?(n=C.valHooks[i.type]||C.valHooks[i.nodeName.toLowerCase()])&&"get"in n&&(e=n.get(i,"value"))!==undefined?e:"string"==typeof(e=i.value)?e.replace(Lt,""):null==e?"":e:void 0}}),C.extend({valHooks:{option:{get:function(e){var t=C.find.attr(e,"value");return null!=t?t:C.trim(C.text(e)).replace(Ht," ")}},select:{get:function(e){for(var t,n=e.options,r=e.selectedIndex,i="select-one"===e.type||r<0,o=i?null:[],a=i?r+1:n.length,s=r<0?a:i?r:0;s").append(C.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this)},C.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){C.fn[t]=function(e){return this.on(t,e)}}),C.expr.filters.animated=function(t){return C.grep(C.timers,function(e){return t===e.elem}).length},C.offset={setOffset:function(e,t,n){var r,i,o,a,s=C.css(e,"position"),u=C(e),l={};"static"===s&&(e.style.position="relative"),o=u.offset(),r=C.css(e,"top"),a=C.css(e,"left"),s=("absolute"===s||"fixed"===s)&&-1'+(s?a.title[0]:a.title)+"":"";return a.zIndex=o,t([a.shade?'
    ':"",'
    '+(e&&2!=a.type?"":s)+"'+(n=["layui-icon-tips","layui-icon-success","layui-icon-error","layui-icon-question","layui-icon-lock","layui-icon-face-cry","layui-icon-face-smile"],o="layui-anim layui-anim-rotate layui-anim-loop",0==a.type&&-1!==a.icon?'':3==a.type?(i=["layui-icon-loading","layui-icon-loading-1"],2==a.icon?'
    ':''):"")+((1!=a.type||!e)&&a.content||"")+'
    '+(n=[],l&&(n.push(''),n.push('')),a.closeBtn&&n.push(''),n.join(""))+"
    "+(a.btn?function(){var e="";"string"==typeof a.btn&&(a.btn=[a.btn]);for(var t,i=0,n=a.btn.length;i'+a.btn[i]+"";return'
    '+e+"
    "}():"")+(a.resize?'':"")+""],s,m('
    ')),this},t.pt.creat=function(){var e,t,i,n,a,o=this,s=o.config,l=o.index,r="object"==typeof(f=s.content),c=m("body");if(s.id&&m("."+u[0]).find("#"+s.id)[0])e=m("#"+s.id).closest("."+u[0]),t=e.attr("times"),i=e.data("config"),n=m("#"+u.SHADE+t),"min"===(e.data("maxminStatus")||{})?g.restore(t):i.hideOnClose&&(n.show(),e.show());else{switch(s.removeFocus&&document.activeElement.blur(),"string"==typeof s.area&&(s.area="auto"===s.area?["",""]:[s.area,""]),s.shift&&(s.anim=s.shift),6==g.ie&&(s.fixed=!1),s.type){case 0:s.btn="btn"in s?s.btn:d.btn[0],g.closeAll("dialog");break;case 2:var f=s.content=r?s.content:[s.content||"","auto"];s.content='';break;case 3:delete s.title,delete s.closeBtn,-1===s.icon&&s.icon,g.closeAll("loading");break;case 4:r||(s.content=[s.content,"body"]),s.follow=s.content[1],s.content=s.content[0]+'',delete s.title,s.tips="object"==typeof s.tips?s.tips:[s.tips,!0],s.tipsMore||g.closeAll("tips")}o.vessel(r,function(e,t,i){c.append(e[0]),r?2==s.type||4==s.type?m("body").append(e[1]):f.parents("."+u[0])[0]||(f.data("display",f.css("display")).show().addClass("layui-layer-wrap").wrap(e[1]),m("#"+u[0]+l).find("."+u[5]).before(t)):c.append(e[1]),m("#"+u.MOVE)[0]||c.append(d.moveElem=i),o.layero=m("#"+u[0]+l),o.shadeo=m("#"+u.SHADE+l),s.scrollbar||d.setScrollbar(l)}).auto(l),o.shadeo.css({"background-color":s.shade[1]||"#000",opacity:s.shade[0]||s.shade}),2==s.type&&6==g.ie&&o.layero.find("iframe").attr("src",f[0]),4==s.type?o.tips():(o.offset(),parseInt(d.getStyle(document.getElementById(u.MOVE),"z-index"))||(o.layero.css("visibility","hidden"),g.ready(function(){o.offset(),o.layero.css("visibility","visible")}))),!s.fixed||d.events.resize[o.index]||(d.events.resize[o.index]=function(){o.resize()},h.on("resize",d.events.resize[o.index])),s.time<=0||setTimeout(function(){g.close(o.index)},s.time),o.move().callback(),u.anim[s.anim]&&(a="layer-anim "+u.anim[s.anim],o.layero.addClass(a).one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){m(this).removeClass(a)})),o.layero.data("config",s)}},t.pt.resize=function(){var e=this,t=e.config;e.offset(),(/^\d+%$/.test(t.area[0])||/^\d+%$/.test(t.area[1]))&&e.auto(e.index),4==t.type&&e.tips()},t.pt.auto=function(e){var t=this.config,i=m("#"+u[0]+e),n=(""===t.area[0]&&0t.maxWidth)&&i.width(t.maxWidth),[i.innerWidth(),i.innerHeight()]),a=i.find(u[1]).outerHeight()||0,o=i.find("."+u[6]).outerHeight()||0,e=function(e){(e=i.find(e)).height(n[1]-a-o-2*(0|parseFloat(e.css("padding-top"))))};return 2===t.type?e("iframe"):""===t.area[1]?0t.maxHeight?(n[1]=t.maxHeight,e("."+u[5])):t.fixed&&n[1]>=h.height()&&(n[1]=h.height(),e("."+u[5])):e("."+u[5]),this},t.pt.offset=function(){var e=this,t=e.config,i=e.layero,n=[i.outerWidth(),i.outerHeight()],a="object"==typeof t.offset;e.offsetTop=(h.height()-n[1])/2,e.offsetLeft=(h.width()-n[0])/2,a?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):"auto"!==t.offset&&("t"===t.offset?e.offsetTop=0:"r"===t.offset?e.offsetLeft=h.width()-n[0]:"b"===t.offset?e.offsetTop=h.height()-n[1]:"l"===t.offset?e.offsetLeft=0:"lt"===t.offset?(e.offsetTop=0,e.offsetLeft=0):"lb"===t.offset?(e.offsetTop=h.height()-n[1],e.offsetLeft=0):"rt"===t.offset?(e.offsetTop=0,e.offsetLeft=h.width()-n[0]):"rb"===t.offset?(e.offsetTop=h.height()-n[1],e.offsetLeft=h.width()-n[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?h.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?h.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=h.scrollTop(),e.offsetLeft+=h.scrollLeft()),"min"===i.data("maxminStatus")&&(e.offsetTop=h.height()-(i.find(u[1]).outerHeight()||0),e.offsetLeft=i.css("left")),i.css({top:e.offsetTop,left:e.offsetLeft})},t.pt.tips=function(){var e=this.config,t=this.layero,i=[t.outerWidth(),t.outerHeight()],n=m(e.follow),a={width:(n=n[0]?n:m("body")).outerWidth(),height:n.outerHeight(),top:n.offset().top,left:n.offset().left},o=t.find(".layui-layer-TipsG"),n=e.tips[0];e.tips[1]||o.remove(),a.autoLeft=function(){0h.width()&&(o=h.width()-180-(d.minStackArr.edgeIndex=d.minStackArr.edgeIndex||0,d.minStackArr.edgeIndex+=3))<0&&(o=0),t.minStack&&(l.left=o,l.top=h.height()-n,a||d.minStackIndex++,r.attr("minLeft",o)),r.attr("position",s),g.style(e,l,!0),i.hide(),"page"===r.attr("type")&&r.find(u[4]).hide(),d.restScrollbar(e),c.hide())},g.restore=function(e){var t=m("#"+u[0]+e),i=m("#"+u.SHADE+e),n=t.attr("area").split(","),a=t.attr("type"),o=t.data("config")||{};t.removeData("maxminStatus"),g.style(e,{width:n[0],height:n[1],top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr("position"),overflow:"visible"},!0),t.find(".layui-layer-max").removeClass("layui-layer-maxmin"),t.find(".layui-layer-min").show(),"page"===a&&t.find(u[4]).show(),o.scrollbar?d.restScrollbar(e):d.setScrollbar(e),i.show()},g.full=function(t){var i=m("#"+u[0]+t),e=i.data("maxminStatus");"max"!==e&&("min"===e&&g.restore(t),i.data("maxminStatus","max"),d.record(i),u.html.attr("layer-full")||d.setScrollbar(t),setTimeout(function(){var e="fixed"===i.css("position");g.style(t,{top:e?0:h.scrollTop(),left:e?0:h.scrollLeft(),width:"100%",height:"100%"},!0),i.find(".layui-layer-min").hide()},100))},g.title=function(e,t){m("#"+u[0]+(t||g.index)).find(u[1]).html(e)},g.close=function(o,s){var l,e,r=(t=m("."+u[0]).children("#"+o).closest("."+u[0]))[0]?(o=t.attr("times"),t):m("#"+u[0]+o),c=r.attr("type"),t=r.data("config")||{},f=t.id&&t.hideOnClose;r[0]&&(l={slideDown:"layer-anim-slide-down-out",slideLeft:"layer-anim-slide-left-out",slideUp:"layer-anim-slide-up-out",slideRight:"layer-anim-slide-right-out"}[t.anim]||"layer-anim-close",e=function(){var e="layui-layer-wrap";if(f)return r.removeClass("layer-anim "+l),r.hide();if(c===d.type[1]&&"object"===r.attr("conType")){r.children(":not(."+u[5]+")").remove();for(var t=r.find("."+e),i=0;i<2;i++)t.unwrap();t.css("display",t.data("display")).removeClass(e)}else{if(c===d.type[2])try{var n=m("#"+u[4]+o)[0];n.contentWindow.document.write(""),n.contentWindow.close(),r.find("."+u[5])[0].removeChild(n)}catch(a){}r[0].innerHTML="",r.remove()}"function"==typeof d.end[o]&&d.end[o](),delete d.end[o],"function"==typeof s&&s(),d.events.resize[o]&&(h.off("resize",d.events.resize[o]),delete d.events.resize[o])},m("#"+u.SHADE+o)[f?"hide":"remove"](),t.isOutAnim&&r.addClass("layer-anim "+l),6==g.ie&&d.reselect(),d.restScrollbar(o),"string"==typeof r.attr("minLeft")&&(d.minStackIndex--,d.minStackArr.push(r.attr("minLeft"))),g.ie&&g.ie<10||!t.isOutAnim?e():setTimeout(function(){e()},200))},g.closeAll=function(n,a){"function"==typeof n&&(a=n,n=null);var o=m("."+u[0]);m.each(o,function(e){var t=m(this),i=n?t.attr("type")===n:1;i&&g.close(t.attr("times"),e===o.length-1?a:null)}),0===o.length&&"function"==typeof a&&a()},g.closeLast=function(e,t){g.close(m(".layui-layer-"+(e=e||"page")+":last").attr("times"),t)},g.cache||{}),v=function(e){return i.skin?" "+i.skin+" "+i.skin+"-"+e:""};g.prompt=function(i,n){var e="",t="";"function"==typeof(i=i||{})&&(n=i),i.area&&(e='style="width: '+(o=i.area)[0]+"; height: "+o[1]+';"',delete i.area),i.placeholder&&(t=' placeholder="'+i.placeholder+'"');var a,o=2==i.formType?'":'",s=i.success;return delete i.success,g.open(m.extend({type:1,btn:["确定","取消"],content:o,skin:"layui-layer-prompt"+v("prompt"),maxWidth:h.width(),success:function(e){(a=e.find(".layui-layer-input")).val(i.value||"").focus(),"function"==typeof s&&s(e)},resize:!1,yes:function(e){var t=a.val();t.length>(i.maxlength||500)?g.tips("最多输入"+(i.maxlength||500)+"个字数",a,{tips:1}):n&&n(t,e,a)}},i))},g.tab=function(n){var a=(n=n||{}).tab||{},o="layui-this",s=n.success;return delete n.success,g.open(m.extend({type:1,skin:"layui-layer-tab"+v("tab"),resize:!1,title:function(){var e=a.length,t=1,i="";if(0'+a[0].title+"";t"+a[t].title+"";return i}(),content:'
      '+function(){var e=a.length,t=1,i="";if(0'+(a[0].content||"no content")+"";t'+(a[t].content||"no content")+"";return i}()+"
    ",success:function(e){var t=e.find(".layui-layer-title").children(),i=e.find(".layui-layer-tabmain").children();t.on("mousedown",function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0;var e=m(this),t=e.index();e.addClass(o).siblings().removeClass(o),i.eq(t).show().siblings().hide(),"function"==typeof n.change&&n.change(t)}),"function"==typeof s&&s(e)}},n))},g.photos=function(n,e,a){var s={};if((n=m.extend(!0,{toolbar:!0,footer:!0},n)).photos){var t=!("string"==typeof n.photos||n.photos instanceof m),i=t?n.photos:{},o=i.data||[],l=i.start||0,r=n.success;if(s.imgIndex=1+(0|l),n.img=n.img||"img",delete n.success,t){if(0===o.length)return g.msg("没有图片")}else{var c=m(n.photos),f=function(){o=[],c.find(n.img).each(function(e){var t=m(this);t.attr("layer-index",e),o.push({alt:t.attr("alt"),pid:t.attr("layer-pid"),src:t.attr("lay-src")||t.attr("layer-src")||t.attr("src"),thumb:t.attr("src")})})};if(f(),0===o.length)return;if(e||c.on("click",n.img,function(){f();var e=m(this).attr("layer-index");g.photos(m.extend(n,{photos:{start:e,data:o,tab:n.tab},full:n.full}),!0)}),!e)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=o.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>o.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){var t;s.end||(t=e.keyCode,e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&g.close(s.index))},s.tabimg=function(e){if(!(o.length<=1))return i.start=s.imgIndex-1,g.close(s.index),g.photos(n,!0,e)},s.isNumber=function(e){return"number"==typeof e&&!isNaN(e)},s.image={},s.getTransform=function(e){var t=[],i=e.rotate,n=e.scaleX,e=e.scale;return s.isNumber(i)&&0!==i&&t.push("rotate("+i+"deg)"),s.isNumber(n)&&1!==n&&t.push("scaleX("+n+")"),s.isNumber(e)&&t.push("scale("+e+")"),t.length?t.join(" "):"none"},s.event=function(e,i,n){var a,o;s.main.find(".layui-layer-photos-prev").on("click",function(e){e.preventDefault(),s.imgprev(!0)}),s.main.find(".layui-layer-photos-next").on("click",function(e){e.preventDefault(),s.imgnext(!0)}),m(document).on("keyup",s.keyup),e.off("click").on("click","*[toolbar-event]",function(){var e=m(this);switch(e.attr("toolbar-event")){case"rotate":s.image.rotate=((s.image.rotate||0)+Number(e.attr("data-option")))%360,s.imgElem.css({transform:s.getTransform(s.image)});break;case"scalex":s.image.scaleX=-1===s.image.scaleX?1:-1,s.imgElem.css({transform:s.getTransform(s.image)});break;case"zoom":var t=Number(e.attr("data-option"));s.image.scale=(s.image.scale||1)+t,t<0&&s.image.scale<0-t&&(s.image.scale=0-t),s.imgElem.css({transform:s.getTransform(s.image)});break;case"reset":s.image.scaleX=1,s.image.scale=1,s.image.rotate=0,s.imgElem.css({transform:"none"});break;case"close":g.close(i)}n.offset(),n.auto(i)}),s.main.on("mousewheel DOMMouseScroll",function(e){var t=e.originalEvent.wheelDelta||-e.originalEvent.detail,i=s.main.find('[toolbar-event="zoom"]');(0n)&&("left"===t.direction?s.imgnext(!0):"right"===t.direction&&s.imgprev(!0))},m.each([n.shadeo,s.main],function(e,t){a.touchSwipe(t,{onTouchEnd:o})}))},s.loadi=g.load(1,{shade:!("shade"in n)&&.9,scrollbar:!1});var t=o[l].src,d=function(e){g.close(s.loadi);var t,i=o[l].alt||"";a&&(n.anim=-1),s.index=g.open(m.extend({type:1,id:"layui-layer-photos",area:(e=[e.width,e.height],t=[m(p).width()-100,m(p).height()-100],!n.full&&(t[0]'+i+''+(t=['
    '],1','','',"
    "].join("")),n.toolbar&&t.push(['
    ','','','','','','',"
    "].join("")),n.footer&&t.push(['"].join("")),t.push(""),t.join(""))+"",success:function(e,t,i){s.main=e.find(".layer-layer-photos-main"),s.footer=e.find(".layui-layer-photos-footer"),s.imgElem=s.main.children("img"),s.event(e,t,i),n.tab&&n.tab(o[l],e),"function"==typeof r&&r(e)},end:function(){s.end=!0,m(document).off("keyup",s.keyup)}},n))},u=function(){g.close(s.loadi),g.msg("当前图片地址异常
    是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){1").addClass(r));layui.each(i.bars,function(t,e){var n=s('
  • ');n.addClass(e.icon).attr({"lay-type":e.type,style:e.style||(i.bgcolor?"background-color: "+i.bgcolor:"")}).html(e.content),n.on("click",function(){var t=s(this).attr("lay-type");"top"===t&&("body"===i.target?s("html,body"):u).animate({scrollTop:0},i.duration),"function"==typeof i.click&&i.click.call(this,t)}),"object"===layui.type(i.on)&&layui.each(i.on,function(t,e){n.on(t,function(){var t=s(this).attr("lay-type");"function"==typeof e&&e.call(this,t)})}),"top"===e.type&&(n.addClass("layui-fixbar-top"),o=n),l.append(n)}),c.find("."+r).remove(),"object"==typeof i.css&&l.css(i.css),c.append(l),o&&(e=function e(){return u.scrollTop()>=i.margin?t||(o.show(),t=1):t&&(o.hide(),t=0),e}()),u.on("scroll",function(){e&&(clearTimeout(n),n=setTimeout(function(){e()},100))})},countdown:function(i){i=s.extend(!0,{date:new Date,now:new Date},i);var o=arguments,r=(1]|&(?=#[a-zA-Z0-9]+)/g.test(t+="")?t.replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,"""):t},unescape:function(t){return t!==undefined&&null!==t||(t=""),(t+="").replace(/\&/g,"&").replace(/\</g,"<").replace(/\>/g,">").replace(/\'/g,"'").replace(/\"/g,'"')},openWin:function(t){var e=(t=t||{}).window||window.open(t.url||"",t.target,t.specs);t.url||(e.document.open("text/html","replace"),e.document.write(t.content||""),e.document.close())},toVisibleArea:function(t){var e,n,i,o,r,a,c,u;(t=s.extend({margin:160,duration:200,type:"y"},t)).scrollElem[0]&&t.thisElem[0]&&(e=t.scrollElem,c=t.thisElem,i=(r="y"===t.type)?"top":"left",o=e[n=r?"scrollTop":"scrollLeft"](),r=e[r?"height":"width"](),a=e.offset()[i],u={},(c=c.offset()[i]-a)>r-t.margin||c."+v,E=function(e){var i=this;i.index=++h.index,i.config=c.extend({},i.config,h.config,e),i.init()};E.prototype.config={trigger:"click",content:"",className:"",style:"",show:!1,isAllowSpread:!0,isSpreadItem:!0,data:[],delay:[200,300],shade:0,accordion:!1},E.prototype.reload=function(e,i){var t=this;t.config=c.extend({},t.config,e),t.init(!0,i)},E.prototype.init=function(e,i){var t,n=this,a=n.config,l=c(a.elem);return 1');return 0No data
  • '),e},u=function(r,e){return layui.each(e,function(e,i){var t,n=i[s.children]&&0",(t="href"in i?''+l+"":l,n?'
    '+t+("parent"===o?'':"group"===o&&d.isAllowSpread?'':"")+"
    ":'
    '+t+"
    "),""].join(""))).data("item",i),n&&(a=c('
    '),t=c("
      "),"parent"===o?(a.append(u(t,i[s.children])),l.append(a)):l.append(u(t,i[s.children]))),r.append(l))}),r},a=['
      ',"
      "].join("");!(e="contextmenu"!==d.trigger&&!lay.isTopElem(d.elem[0])?e:!0)&&d.elem.data(y+"_opened")||(l.elemView=c("."+g+'[lay-id="'+d.id+'"]'),"reloadData"===i&&l.elemView.length?l.elemView.html(d.content||n()):(l.elemView=c(a),l.elemView.append(d.content||n()),d.className&&l.elemView.addClass(d.className),d.style&&l.elemView.attr("style",d.style),h.thisId=d.id,l.remove(),t.append(l.elemView),d.elem.data(y+"_opened",!0),e=d.shade?'
      ':"",l.elemView.before(e),"mouseenter"===d.trigger&&l.elemView.on("mouseenter",function(){clearTimeout(f.timer)}).on("mouseleave",function(){l.delayRemove()})),l.position(),(f.prevElem=l.elemView).data("prevElem",d.elem),l.elemView.find(".layui-menu").on(o,function(e){layui.stope(e)}),l.elemView.find(".layui-menu li").on("click",function(e){var i=c(this),t=i.data("item")||{},n=t[s.children]&&0n.width()&&(t.addClass(x),(i=t[0].getBoundingClientRect()).left<0)&&t.removeClass(x),i.bottom>n.height())&&t.eq(0).css("margin-top",-(i.bottom-n.height()+5))}).on("mouseleave",t,function(e){var i=c(this).children("."+C);i.removeClass(x),i.css("margin-top",0)}),h.close=function(e){e=f.getThis(e);return e?(e.remove(),f.call(e)):this},h.reload=function(e,i,t){e=f.getThis(e);return e?(e.reload(i,t),f.call(e)):this},h.reloadData=function(){var t=c.extend([],arguments),n=(t[2]="reloadData",new RegExp("^("+["data","templet","content"].join("|")+")$"));return layui.each(t[1],function(e,i){n.test(e)||delete t[1][e]}),h.reload.apply(null,t)},h.render=function(e){e=new E(e);return f.call(e)},e(r,h)});layui.define(["jquery","lay"],function(e){"use strict";var g=layui.$,x=layui.lay,c={config:{},index:layui.slider?layui.slider.index+1e4:0,set:function(e){var t=this;return t.config=g.extend({},t.config,e),t},on:function(e,t){return layui.onevent.call(this,i,e,t)}},i="slider",v="layui-disabled",b="layui-slider-bar",T="layui-slider-wrap",w="layui-slider-wrap-btn",M="layui-slider-tips",L="layui-slider-input-txt",E="layui-slider-hover",t=function(e){var t=this;t.index=++c.index,t.config=g.extend({},t.config,c.config,e),t.render()};t.prototype.config={type:"default",min:0,max:100,value:0,step:1,showstep:!1,tips:!0,input:!1,range:!1,height:200,disabled:!1,theme:"#16baaa"},t.prototype.render=function(){var n=this,a=n.config,e=g(a.elem);if(1a.max&&(a.value=a.max),i=Math.floor((a.value-a.min)/(a.max-a.min)*100)+"%");var l,e=a.disabled?"#c2c2c2":a.theme,t='
      '+(a.tips?'
      ':"")+'
      '+(a.range?'
      ':"")+"
      ",i=g(a.elem),s=i.next(".layui-slider");if(s[0]&&s.remove(),n.elemTemp=g(t),a.range?(n.elemTemp.find("."+T).eq(0).data("value",a.value[0]),n.elemTemp.find("."+T).eq(1).data("value",a.value[1])):n.elemTemp.find("."+T).data("value",a.value),i.html(n.elemTemp),"vertical"===a.type&&n.elemTemp.height(a.height+"px"),a.showstep){for(var o=(a.max-a.min)/a.step,r="",u=1;u<1+o;u++){var d=100*u/o;d<100&&(r+='
      ')}n.elemTemp.append(r)}a.input&&!a.range&&(e=g('
      '),i.css("position","relative"),i.append(e),i.find("."+L).children("input").val(a.value),"vertical"===a.type?e.css({left:0,top:-48}):n.elemTemp.css("margin-right",e.outerWidth()+15)),a.disabled?(n.elemTemp.addClass(v),n.elemTemp.find("."+w).addClass(v)):n.slide(),n.elemTemp.find("."+w).on("mouseover",function(){var e="vertical"===a.type?a.height:n.elemTemp[0].offsetWidth,t=n.elemTemp.find("."+T),i=("vertical"===a.type?e-g(this).parent()[0].offsetTop-t.height():g(this).parent()[0].offsetLeft)/e*100,t=g(this).parent().data("value"),e=a.setTips?a.setTips(t):t;n.elemTemp.find("."+M).html(e),clearTimeout(l),l=setTimeout(function(){"vertical"===a.type?n.elemTemp.find("."+M).css({bottom:i+"%","margin-bottom":"20px",display:"inline-block"}):n.elemTemp.find("."+M).css({left:i+"%",display:"inline-block"})},300)}).on("mouseout",function(){clearTimeout(l),n.elemTemp.find("."+M).css("display","none")})},t.prototype.slide=function(e,t,i){var u=this,d=u.config,c=u.elemTemp,v=function(){return"vertical"===d.type?d.height:c[0].offsetWidth},m=c.find("."+T),o=c.next(".layui-slider-input"),r=o.children("."+L).children("input").val(),p=100/((d.max-d.min)/Math.ceil(d.step)),f=function(e,t,i){e=(e=100<(e=100n[1]&&n.reverse(),u.value=d.range?n:l,d.change&&d.change(u.value),"done"===i&&d.done&&d.done(u.value)},h=function(e){var t=e/v()*100/p,i=Math.round(t)*p;return i=e==v()?Math.ceil(t)*p:i},y=g(['
      v()?v():t)/v()*100/p;f(t,o),r.addClass(E),c.find("."+M).show(),e.preventDefault()},n=function(e){r.removeClass(E),setTimeout(function(){c.find("."+M).hide()},e)},a=function(){n&&n(x.touchEventsSupported()?1e3:0),y.remove(),d.done&&d.done(u.value),x.touchEventsSupported()&&(t[0].removeEventListener("touchmove",i,!!x.passiveSupported&&{passive:!1}),t[0].removeEventListener("touchend",a),t[0].removeEventListener("touchcancel",a))},g("#LAY-slider-moving")[0]||g("body").append(y),y.on("mousemove",i),y.on("mouseup",a).on("mouseleave",a),x.touchEventsSupported()&&(t[0].addEventListener("touchmove",i,!!x.passiveSupported&&{passive:!1}),t[0].addEventListener("touchend",a),t[0].addEventListener("touchcancel",a))})}),c.on("click",function(e){var t=g("."+w),i=g(this);!t.is(event.target)&&0===t.has(event.target).length&&t.length&&(i=(t=(t=(t="vertical"===d.type?v()-e.clientY+i.offset().top-g(window).scrollTop():e.clientX-i.offset().left-g(window).scrollLeft())<0?0:t)>v()?v():t)/v()*100/p,t=d.range?"vertical"===d.type?Math.abs(t-parseInt(g(m[0]).css("bottom")))>Math.abs(t-parseInt(g(m[1]).css("bottom")))?1:0:Math.abs(t-m[0].offsetLeft)>Math.abs(t-m[1].offsetLeft)?1:0:0,f(i,t,"done"),e.preventDefault())}),o.children(".layui-slider-input-btn").children("i").each(function(t){g(this).on("click",function(){r=o.children("."+L).children("input").val();var e=((r=1==t?r-d.stepd.max?d.max:Number(r)+d.step)-d.min)/(d.max-d.min)*100/p;f(e,0,"done")})});var n=function(){var e=this.value,e=(e=(e=(e=isNaN(e)?0:e)d.max?d.max:e,((this.value=e)-d.min)/(d.max-d.min)*100/p);f(e,0,"done")};o.children("."+L).children("input").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),n.call(this))}).on("change",n)},t.prototype.events=function(){this.config},c.render=function(e){e=new t(e);return function(){var i=this,n=i.config;return{setValue:function(e,t){return e=(e=e>n.max?n.max:e)',"",'','',"","","
      "].join("")),t=i.elem=k(i.elem);i.size&&o.addClass("layui-colorpicker-"+i.size),t.addClass("layui-inline").html(e.elemColorBox=o),i.id="id"in i?i.id:t.attr("id")||e.index,e.color=e.elemColorBox.find("."+C)[0].style.background,e.events()},d.prototype.renderPicker=function(){var o,e=this,i=e.config,t=e.elemColorBox[0],r=e.elemPicker=k(['
      ','
      ','
      ','
      ','
      ','
      ',"
      ",'
      ','
      ',"
      ","
      ",'
      ','
      ','
      ',"
      ","
      ",i.predefine?(o=['
      '],layui.each(i.colors,function(e,i){o.push(['
      ','
      ',"
      "].join(""))}),o.push("
      "),o.join("")):"",'
      ','
      ','',"
      ",'
      ','','',"","
      "].join(""));e.elemColorBox.find("."+C)[0];k(a)[0]&&k(a).data("index")==e.index?e.removePicker(d.thisElemInd):(e.removePicker(d.thisElemInd),k("body").append(r)),n.thisId=i.id,d.thisElemInd=e.index,d.thisColor=t.style.background,e.position(),e.pickerEvents()},d.prototype.removePicker=function(e){var i=this.config,e=k("#layui-colorpicker"+(e||this.index));return e[0]&&(e.remove(),delete n.thisId,"function"==typeof i.close)&&i.close(this.color),this},d.prototype.position=function(){var e=this,i=e.config;return r.position(e.bindElem||e.elemColorBox[0],e.elemPicker[0],{position:i.position,align:"center"}),e},d.prototype.val=function(){var e,i=this,o=(i.config,i.elemColorBox.find("."+C)),t=i.elemPicker.find("."+M),r=o[0].style.backgroundColor;r?(e=Y(F(r)),o=o.attr("lay-type"),i.select(e.h,e.s,e.b),"torgb"===o?t.find("input").val(r):"rgba"===o?(o=F(r),3===(r.match(/[0-9]{1,3}/g)||[]).length?(t.find("input").val("rgba("+o.r+", "+o.g+", "+o.b+", 1)"),i.elemPicker.find("."+D).css("left",280)):(t.find("input").val(r),r=280*r.slice(r.lastIndexOf(",")+1,r.length-1),i.elemPicker.find("."+D).css("left",r)),i.elemPicker.find("."+T)[0].style.background="linear-gradient(to right, rgba("+o.r+", "+o.g+", "+o.b+", 0), rgb("+o.r+", "+o.g+", "+o.b+"))"):t.find("input").val("#"+j(e))):(i.select(0,100,100),t.find("input").val(""),i.elemPicker.find("."+T)[0].style.background="",i.elemPicker.find("."+D).css("left",280))},d.prototype.side=function(){var n=this,l=n.config,c=n.elemColorBox.find("."+C),a=c.attr("lay-type"),s=n.elemPicker.find(".layui-colorpicker-side"),e=n.elemPicker.find("."+B),d=n.elemPicker.find("."+I),t=n.elemPicker.find("."+E),u=n.elemPicker.find("."+T),f=n.elemPicker.find("."+D),p=e[0].offsetTop/180*360,h=100-(t[0].offsetTop+3)/180*100,g=(t[0].offsetLeft+3)/260*100,v=Math.round(f[0].offsetLeft/280*100)/100,y=n.elemColorBox.find("."+w),i=n.elemPicker.find(".layui-colorpicker-pre").children("div"),m=function(e,i,o,t){n.select(e,i,o);var r=X({h:e,s:i,b:o}),e=j({h:e,s:i,b:o}),i=n.elemPicker.find("."+M).find("input");y.addClass(x).removeClass(P),c[0].style.background="rgb("+r.r+", "+r.g+", "+r.b+")","torgb"===a?i.val("rgb("+r.r+", "+r.g+", "+r.b+")"):"rgba"===a?(f.css("left",280*t),i.val("rgba("+r.r+", "+r.g+", "+r.b+", "+t+")"),c[0].style.background="rgba("+r.r+", "+r.g+", "+r.b+", "+t+")",u[0].style.background="linear-gradient(to right, rgba("+r.r+", "+r.g+", "+r.b+", 0), rgb("+r.r+", "+r.g+", "+r.b+"))"):i.val("#"+e),l.change&&l.change(k.trim(n.elemPicker.find("."+M).find("input").val()))},o=k(['
      '].join("")),b=function(e){k("#LAY-colorpicker-moving")[0]||k("body").append(o),o.on("mousemove",e),o.on("mouseup",function(){o.remove()}).on("mouseleave",function(){o.remove()})};e.on("mousedown",function(e){var t=this.offsetTop,r=e.clientY;b(function(e){var i=t+(e.clientY-r),o=s[0].offsetHeight,o=(i=o<(i=i<0?0:i)?o:i)/180*360;m(p=o,g,h,v),e.preventDefault()}),e.preventDefault()}),s.on("click",function(e){var i=e.clientY-k(this).offset().top+L.scrollTop(),i=(i=(i=i<0?0:i)>this.offsetHeight?this.offsetHeight:i)/180*360;m(p=i,g,h,v),e.preventDefault()}),t.on("mousedown",function(e){var n=this.offsetTop,l=this.offsetLeft,c=e.clientY,a=e.clientX;layui.stope(e),b(function(e){var i=n+(e.clientY-c),o=l+(e.clientX-a),t=d[0].offsetHeight-3,r=d[0].offsetWidth-3,r=((o=r<(o=o<-3?-3:o)?r:o)+3)/260*100,o=100-((i=t<(i=i<-3?-3:i)?t:i)+3)/180*100;m(p,g=r,h=o,v),e.preventDefault()}),e.preventDefault()}),d.on("mousedown",function(e){var i=e.clientY-k(this).offset().top-3+L.scrollTop(),o=e.clientX-k(this).offset().left-3+L.scrollLeft(),o=((i=i<-3?-3:i)>this.offsetHeight-3&&(i=this.offsetHeight-3),((o=(o=o<-3?-3:o)>this.offsetWidth-3?this.offsetWidth-3:o)+3)/260*100),i=100-(i+3)/180*100;m(p,g=o,h=i,v),layui.stope(e),e.preventDefault(),t.trigger(e,"mousedown")}),f.on("mousedown",function(e){var t=this.offsetLeft,r=e.clientX;b(function(e){var i=t+(e.clientX-r),o=u[0].offsetWidth,o=(o<(i=i<0?0:i)&&(i=o),Math.round(i/280*100)/100);m(p,g,h,v=o),e.preventDefault()}),e.preventDefault()}),u.on("click",function(e){var i=e.clientX-k(this).offset().left,i=((i=i<0?0:i)>this.offsetWidth&&(i=this.offsetWidth),Math.round(i/280*100)/100);m(p,g,h,v=i),e.preventDefault()}),i.each(function(){k(this).on("click",function(){k(this).parent(".layui-colorpicker-pre").addClass("selected").siblings().removeClass("selected");var e=this.style.backgroundColor,i=Y(F(e)),o=e.slice(e.lastIndexOf(",")+1,e.length-1);p=i.h,g=i.s,h=i.b,3===(e.match(/[0-9]{1,3}/g)||[]).length&&(o=1),v=o,m(i.h,i.s,i.b,o)})}),r.touchEventsSupported()&&layui.each([{elem:s,eventType:"click"},{elem:u,eventType:"click"},{elem:d,eventType:"mousedown"}],function(e,t){r.touchSwipe(t.elem,{onTouchMove:function(e){var i,o;e=e,i=t.eventType,e=e.touches[0],(o=document.createEvent("MouseEvent")).initMouseEvent(i,!0,!0,window,1,e.screenX,e.screenY,e.clientX,e.clientY,!1,!1,!1,!1,0,null),e.target.dispatchEvent(o)}})})},d.prototype.select=function(e,i,o,t){this.config;var r=j({h:e,s:100,b:100}),e=(j({h:e,s:i,b:o}),e/360*180),o=180-o/100*180-3,i=i/100*260-3;this.elemPicker.find("."+B).css("top",e),this.elemPicker.find("."+I)[0].style.background="#"+r,this.elemPicker.find("."+E).css({top:o,left:i})},d.prototype.pickerEvents=function(){var c=this,a=c.config,s=c.elemColorBox.find("."+C),d=c.elemPicker.find("."+M+" input"),o={clear:function(e){s[0].style.background="",c.elemColorBox.find("."+w).removeClass(x).addClass(P),c.color="",a.done&&a.done(""),c.removePicker()},confirm:function(e,i){var o,t,r,n,l=k.trim(d.val());-1>16,g:(65280&r)>>8,b:255&r},t=Y(n),s[0].style.background=o="#"+j(t),c.elemColorBox.find("."+w).removeClass(P).addClass(x)),"change"===i?(c.select(t.h,t.s,t.b,i),a.change&&a.change(o)):(c.color=l,a.done&&a.done(l),c.removePicker())}};c.elemPicker.on("click","*[colorpicker-events]",function(){var e=k(this),i=e.attr("colorpicker-events");o[i]&&o[i].call(this,e)}),d.on("keyup",function(e){var i=k(this);o.confirm.call(this,i,13===e.keyCode?null:"change")})},d.prototype.events=function(){var e=this;e.config;e.elemColorBox.on("click",function(){e.renderPicker(),k(a)[0]&&(e.val(),e.side())})},s.on(i,function(e){var i,o,t;n.thisId&&(i=l.getThis(n.thisId))&&(o=i.config,t=i.elemColorBox.find("."+C),k(e.target).hasClass(c)||k(e.target).parents("."+c)[0]||k(e.target).hasClass(a.replace(/\./g,""))||k(e.target).parents(a)[0]||i.elemPicker&&(i.color?(e=Y(F(i.color)),i.select(e.h,e.s,e.b)):i.elemColorBox.find("."+w).removeClass(x).addClass(P),t[0].style.background=i.color||"","function"==typeof o.cancel&&o.cancel(i.color),i.removePicker()))}),L.on("resize",function(){if(n.thisId){var e=l.getThis(n.thisId);if(e)return!(!e.elemPicker||!k(a)[0])&&void e.position()}}),l.that={},l.getThis=function(e){var i=l.that[e];return i||o.error(e?t+" instance with ID '"+e+"' not found":"ID argument required"),i},n.render=function(e){e=new d(e);return l.call(e)},e(t,n)});layui.define("jquery",function(t){"use strict";var u=layui.$,d=(layui.hint(),layui.device()),c="element",r="layui-this",h="layui-show",o=".layui-tab-title",i=function(){this.config={}},y=(i.prototype.set=function(t){return u.extend(!0,this.config,t),this},i.prototype.on=function(t,i){return layui.onevent.call(this,c,t,i)},i.prototype.tabAdd=function(t,i){var a,e=u(".layui-tab[lay-filter="+t+"]"),l=e.children(o),n=l.children(".layui-tab-bar"),e=e.children(".layui-tab-content"),s=""+(i.title||"unnaming")+"";return n[0]?n.before(s):l.append(s),e.append('
      '+(i.content||"")+"
      "),i.change&&this.tabChange(t,i.id),l.data("LAY_TAB_CHANGE",i.change),C.tabAuto(i.change?"change":null),this},i.prototype.tabDelete=function(t,i){t=u(".layui-tab[lay-filter="+t+"]").children(o).find('>li[lay-id="'+i+'"]');return C.tabDelete(null,t),this},i.prototype.tabChange=function(t,i){t=u(".layui-tab[lay-filter="+t+"]").children(o).find('>li[lay-id="'+i+'"]');return C.tabClick.call(t[0],{liElem:t}),this},i.prototype.tab=function(a){a=a||{},e.on("click",a.headerElem,function(t){var i=u(this).index();C.tabClick.call(this,{index:i,options:a})})},i.prototype.progress=function(t,i){var a="layui-progress",t=u("."+a+"[lay-filter="+t+"]").find("."+a+"-bar"),a=t.find("."+a+"-text");return t.css("width",function(){return/^.+\/.+$/.test(i)?100*new Function("return "+i)()+"%":i}).attr("lay-percent",i),a.text(i),this},".layui-nav"),f="layui-nav-item",p="layui-nav-bar",b="layui-nav-tree",v="layui-nav-child",m="layui-nav-more",g="layui-anim layui-anim-upbit",C={tabClick:function(t){var i=(t=t||{}).options||{},a=t.liElem||u(this),e=i.headerElem?a.parent():a.parents(".layui-tab").eq(0),i=i.bodyElem?u(i.bodyElem):e.children(".layui-tab-content").children(".layui-tab-item"),l=a.find("a"),l="javascript:;"!==l.attr("href")&&"_blank"===l.attr("target"),n="string"==typeof a.attr("lay-unselect"),s=e.attr("lay-filter"),t="index"in t?t.index:a.parent().children("li").index(a);l||n||(a.addClass(r).siblings().removeClass(r),i.eq(t).addClass(h).siblings().removeClass(h)),layui.event.call(this,c,"tab("+s+")",{elem:e,index:t})},tabDelete:function(t,i){var i=i||u(this).parent(),a=i.parent().children("li").index(i),e=i.closest(".layui-tab"),l=e.children(".layui-tab-content").children(".layui-tab-item"),n=e.attr("lay-filter");i.hasClass(r)&&(i.next()[0]&&i.next().is("li")?C.tabClick.call(i.next()[0],{index:a+1}):i.prev()[0]&&i.prev().is("li")&&C.tabClick.call(i.prev()[0],null,a-1)),i.remove(),l.eq(a).remove(),setTimeout(function(){C.tabAuto()},50),layui.event.call(this,c,"tabDelete("+n+")",{elem:e,index:a})},tabAuto:function(l){var n="layui-tab-more",s="layui-tab-bar",o="layui-tab-close",c=this;u(".layui-tab").each(function(){var t,i=u(this),a=i.children(".layui-tab-title"),e=(i.children(".layui-tab-content").children(".layui-tab-item"),'lay-stope="tabmore"'),e=u('');c===window&&d.ie,i.attr("lay-allowclose")&&a.find("li").each(function(){var t,i=u(this);i.find("."+o)[0]||((t=u('')).on("click",C.tabDelete),i.append(t))}),"string"!=typeof i.attr("lay-unauto")&&(a.prop("scrollWidth")>a.outerWidth()+1||a.find("li").length&&a.height()>(t=a.find("li").eq(0).height())+t/2?("change"===l&&a.data("LAY_TAB_CHANGE")&&a.addClass(n),a.find("."+s)[0]||(a.append(e),i.attr("overflow",""),e.on("click",function(t){var i=a.hasClass(n);a[i?"removeClass":"addClass"](n)}))):(a.find("."+s).remove(),i.removeAttr("overflow")))})},hideTabMore:function(t){var i=u(".layui-tab-title");!0!==t&&"tabmore"===u(t.target).attr("lay-stope")||(i.removeClass("layui-tab-more"),i.find(".layui-tab-bar").attr("title",""))},clickThis:function(){var t=u(this),i=t.closest(y),a=i.attr("lay-filter"),e=t.parent(),l=t.siblings("."+v),n="string"==typeof e.attr("lay-unselect");if("javascript:;"!==t.attr("href")&&"_blank"===t.attr("target")||n||l[0]||(i.find("."+r).removeClass(r),e.addClass(r)),i.hasClass(b)){var n=f+"ed",s=!e.hasClass(n),o=function(){u(this).css({display:""}),i.children("."+p).css({opacity:0})};if(l.is(":animated"))return;l.removeClass(g),l[0]&&(s?(l.slideDown(200,o),e.addClass(n)):(e.removeClass(n),l.show().slideUp(200,o)),"string"!=typeof i.attr("lay-accordion")&&"all"!==i.attr("lay-shrink")||((s=e.siblings("."+n)).removeClass(n),s.children("."+v).show().stop().slideUp(200,o)))}layui.event.call(this,c,"nav("+a+")",t)},collapse:function(){var t=u(this),i=t.find(".layui-colla-icon"),a=t.siblings(".layui-colla-content"),e=t.parents(".layui-collapse").eq(0),l=e.attr("lay-filter"),n="none"===a.css("display");"string"==typeof e.attr("lay-accordion")&&((e=e.children(".layui-colla-item").children("."+h)).siblings(".layui-colla-title").children(".layui-colla-icon").html(""),e.removeClass(h)),a[n?"addClass":"removeClass"](h),i.html(n?"":""),layui.event.call(this,c,"collapse("+l+")",{title:t,content:a,show:n})}},a=(i.prototype.render=i.prototype.init=function(t,i){var a=i?'[lay-filter="'+i+'"]':"",i={tab:function(){C.tabAuto.call({})},nav:function(){var s={},o={},c={},r="layui-nav-title";u(y+a).each(function(t){var i=u(this),a=u(''),e=i.find("."+f);i.find("."+p)[0]||(i.append(a),(i.hasClass(b)?e.find("dd,>."+r):e).on("mouseenter",function(){!function(t,i,a){var e,l=u(this),n=l.find("."+v);i.hasClass(b)?n[0]||(e=l.children("."+r),t.css({top:l.offset().top-i.offset().top,height:(e[0]?e:l).outerHeight(),opacity:1})):(n.addClass(g),n.hasClass("layui-nav-child-c")&&n.css({left:-(n.outerWidth()-l.width())/2}),n[0]?t.css({left:t.position().left+t.width()/2,width:0,opacity:0}):t.css({left:l.position().left+parseFloat(l.css("marginLeft")),top:l.position().top+l.height()-t.height()}),s[a]=setTimeout(function(){t.css({width:n[0]?0:l.width(),opacity:n[0]?0:1})},d.ie&&d.ie<10?0:200),clearTimeout(c[a]),"block"===n.css("display")&&clearTimeout(o[a]),o[a]=setTimeout(function(){n.addClass(h),l.find("."+m).addClass(m+"d")},300))}.call(this,a,i,t)}).on("mouseleave",function(){i.hasClass(b)?a.css({height:0,opacity:0}):(clearTimeout(o[t]),o[t]=setTimeout(function(){i.find("."+v).removeClass(h),i.find("."+m).removeClass(m+"d")},300))}),i.on("mouseleave",function(){clearTimeout(s[t]),c[t]=setTimeout(function(){i.hasClass(b)||a.css({width:0,left:a.position().left+a.width()/2,opacity:0})},200)})),e.find("a").each(function(){var t=u(this);t.parent();t.siblings("."+v)[0]&&!t.children("."+m)[0]&&t.append(''),t.off("click",C.clickThis).on("click",C.clickThis)})})},breadcrumb:function(){u(".layui-breadcrumb"+a).each(function(){var t=u(this),i="lay-separator",a=t.attr(i)||"/",e=t.find("a");e.next("span["+i+"]")[0]||(e.each(function(t){t!==e.length-1&&u(this).after(""+a+"")}),t.css("visibility","visible"))})},progress:function(){var e="layui-progress";u("."+e+a).each(function(){var t=u(this),i=t.find(".layui-progress-bar"),a=i.attr("lay-percent");i.css("width",function(){return/^.+\/.+$/.test(a)?100*new Function("return "+a)()+"%":a}),t.attr("lay-showpercent")&&setTimeout(function(){i.html(''+a+"")},350)})},collapse:function(){u(".layui-collapse"+a).each(function(){u(this).find(".layui-colla-item").each(function(){var t=u(this),i=t.find(".layui-colla-title"),t="none"===t.find(".layui-colla-content").css("display");i.find(".layui-colla-icon").remove(),i.append(''+(t?"":"")+""),i.off("click",C.collapse).on("click",C.collapse)})})}};return i[t]?i[t]():layui.each(i,function(t,i){i()})},new i),e=u(document);u(function(){a.render()}),e.on("click",".layui-tab-title li",C.tabClick),u(window).on("resize",C.tabAuto),t(c,a)});layui.define(["lay","layer"],function(e){"use strict";var x=layui.$,a=layui.lay,i=layui.layer,b=layui.device(),t="upload",r="layui_"+t+"_index",o={config:{},index:layui[t]?layui[t].index+1e4:0,set:function(e){var i=this;return i.config=x.extend({},i.config,e),i},on:function(e,i){return layui.onevent.call(this,t,e,i)}},l=function(){var i=this,e=i.config.id;return{upload:function(e){i.upload.call(i,e)},reload:function(e){i.reload.call(i,e)},config:(l.that[e]=i).config}},u="layui-upload-file",f="layui-upload-form",F="layui-upload-iframe",w="layui-upload-choose",L="UPLOADING",j=function(e){var i=this;i.index=++o.index,i.config=x.extend({},i.config,o.config,e),i.render()};j.prototype.config={accept:"images",exts:"",auto:!0,bindAction:"",url:"",force:"",field:"file",acceptMime:"",method:"post",data:{},drag:!0,size:0,number:0,multiple:!1,text:{"cross-domain":"Cross-domain requests are not supported","data-format-error":"Please return JSON data format","check-error":"",error:"","limit-number":null,"limit-size":null}},j.prototype.reload=function(e){var i=this;i.config=x.extend({},i.config,e),i.render(!0)},j.prototype.render=function(e){var i=this,t=i.config,n=x(t.elem);return 1"].join("")),n=i.elem.next();(n.hasClass(u)||n.hasClass(f))&&n.remove(),b.ie&&b.ie<10&&i.elem.wrap('
      '),e.isFile()?(e.elemFile=i.elem,i.field=i.elem[0].name):i.elem.after(t),b.ie&&b.ie<10&&e.initIE()},j.prototype.initIE=function(){var t,e=this.config,i=x(''),n=x(['
      ',"
      "].join(""));x("#"+F)[0]||x("body").append(i),e.elem.next().hasClass(f)||(this.elemFile.wrap(n),e.elem.next("."+f).append((t=[],layui.each(e.data,function(e,i){i="function"==typeof i?i():i,t.push('')}),t.join(""))))},j.prototype.msg=function(e){return i.msg(e,{icon:2,shift:6})},j.prototype.isFile=function(){var e=this.config.elem[0];if(e)return"input"===e.tagName.toLocaleLowerCase()&&"file"===e.type},j.prototype.preview=function(n){window.FileReader&&layui.each(this.chooseFiles,function(e,i){var t=new FileReader;t.readAsDataURL(i),t.onload=function(){n&&n(e,i,this.result)}})},j.prototype.upload=function(e,i){var t,n,a,o,u=this,f=u.config,c=f.text||{},l=u.elemFile[0],s=function(){return e||u.files||u.chooseFiles||l.files},r=function(){var a=0,o=0,l=s(),r=function(){f.multiple&&a+o===u.fileLength&&"function"==typeof f.allDone&&f.allDone({total:u.fileLength,successful:a,failed:o})},t=function(t){var n=new FormData,i=function(e){t.unified?layui.each(l,function(e,i){delete i[L]}):delete e[L]};if(layui.each(f.data,function(e,i){i="function"==typeof i?i():i,n.append(e,i)}),t.unified)layui.each(l,function(e,i){i[L]||(i[L]=!0,n.append(f.field,i))});else{if(t.file[L])return;n.append(f.field,t.file),t.file[L]=!0}var e={url:f.url,type:"post",data:n,dataType:f.dataType||"json",contentType:!1,processData:!1,headers:f.headers||{},success:function(e){f.unified?a+=u.fileLength:a++,p(t.index,e),r(t.index),i(t.file)},error:function(e){f.unified?o+=u.fileLength:o++,u.msg(c.error||["Upload failed, please try again.","status: "+(e.status||"")+" - "+(e.statusText||"error")].join("
      ")),m(t.index),r(t.index),i(t.file)}};"function"==typeof f.progress&&(e.xhr=function(){var e=x.ajaxSettings.xhr();return e.upload.addEventListener("progress",function(e){var i;e.lengthComputable&&(i=Math.floor(e.loaded/e.total*100),f.progress(i,(f.item||f.elem)[0],e,t.index))}),e}),x.ajax(e)};f.unified?t({unified:!0,index:0}):layui.each(l,function(e,i){t({index:e,file:i})})},d=function(){var n=x("#"+F);u.elemFile.parent().submit(),clearInterval(j.timer),j.timer=setInterval(function(){var e,i=n.contents().find("body");try{e=i.text()}catch(t){u.msg(c["cross-domain"]),clearInterval(j.timer),m()}e&&(clearInterval(j.timer),i.html(""),p(0,e))},30)},p=function(e,i){if(u.elemFile.next("."+w).remove(),l.value="","json"===f.force&&"object"!=typeof i)try{i=JSON.parse(i)}catch(t){return i={},u.msg(c["data-format-error"])}"function"==typeof f.done&&f.done(i,e||0,function(e){u.upload(e)})},m=function(e){f.auto&&(l.value=""),"function"==typeof f.error&&f.error(e||0,function(e){u.upload(e)})},h=f.exts,g=(n=[],layui.each(e||u.chooseFiles,function(e,i){n.push(i.name)}),n),v={preview:function(e){u.preview(e)},upload:function(e,i){var t={};t[e]=i,u.upload(t)},pushFile:function(){return u.files=u.files||{},layui.each(u.chooseFiles,function(e,i){u.files[e]=i}),u.files},resetFile:function(e,i,t){i=new File([i],t);u.files=u.files||{},u.files[e]=i}},y={file:"\u6587\u4ef6",images:"\u56fe\u7247",video:"\u89c6\u9891",audio:"\u97f3\u9891"}[f.accept]||"\u6587\u4ef6",g=0===g.length?l.value.match(/[^\/\\]+\..+/g)||[]:g;if(0!==g.length){switch(f.accept){case"file":layui.each(g,function(e,i){if(h&&!RegExp(".\\.("+h+")$","i").test(escape(i)))return t=!0});break;case"video":layui.each(g,function(e,i){if(!RegExp(".\\.("+(h||"avi|mp4|wma|rmvb|rm|flash|3gp|flv")+")$","i").test(escape(i)))return t=!0});break;case"audio":layui.each(g,function(e,i){if(!RegExp(".\\.("+(h||"mp3|wav|mid")+")$","i").test(escape(i)))return t=!0});break;default:layui.each(g,function(e,i){if(!RegExp(".\\.("+(h||"jpg|png|gif|bmp|jpeg|svg")+")$","i").test(escape(i)))return t=!0})}if(t)return u.msg(c["check-error"]||"\u9009\u62e9\u7684"+y+"\u4e2d\u5305\u542b\u4e0d\u652f\u6301\u7684\u683c\u5f0f"),l.value="";if("choose"!==i&&!f.auto||(f.choose&&f.choose(v),"choose"!==i)){if(u.fileLength=(a=0,y=s(),layui.each(y,function(){a++}),a),f.number&&u.fileLength>f.number)return u.msg("function"==typeof c["limit-number"]?c["limit-number"](f,u.fileLength):"\u540c\u65f6\u6700\u591a\u53ea\u80fd\u4e0a\u4f20: "+f.number+" \u4e2a\u6587\u4ef6
      \u60a8\u5f53\u524d\u5df2\u7ecf\u9009\u62e9\u4e86: "+u.fileLength+" \u4e2a\u6587\u4ef6");if(01024*f.size&&(i=1<=(i=f.size/1024)?i.toFixed(2)+"MB":f.size+"KB",l.value="",o=i)}),o)return u.msg("function"==typeof c["limit-size"]?c["limit-size"](f,o):"\u6587\u4ef6\u5927\u5c0f\u4e0d\u80fd\u8d85\u8fc7 "+o);if(!f.before||!1!==f.before(v))b.ie?(9'+e+"")};a.elem.off("upload.start").on("upload.start",function(){var e=x(this);n.config.item=e,n.elemFile[0].click()}),b.ie&&b.ie<10||a.elem.off("upload.over").on("upload.over",function(){x(this).attr("lay-over","")}).off("upload.leave").on("upload.leave",function(){x(this).removeAttr("lay-over")}).off("upload.drop").on("upload.drop",function(e,i){var t=x(this),i=i.originalEvent.dataTransfer.files||[];t.removeAttr("lay-over"),o(i),a.auto?n.upload():l(i)}),n.elemFile.on("change",function(){var e=this.files||[];0!==e.length&&(o(e),a.auto?n.upload():l(e))}),a.bindAction.off("upload.action").on("upload.action",function(){n.upload()}),a.elem.data(r)||(a.elem.on("click",function(){n.isFile()||x(this).trigger("upload.start")}),a.drag&&a.elem.on("dragover",function(e){e.preventDefault(),x(this).trigger("upload.over")}).on("dragleave",function(e){x(this).trigger("upload.leave")}).on("drop",function(e){e.preventDefault(),x(this).trigger("upload.drop",e)}),a.bindAction.on("click",function(){x(this).trigger("upload.action")}),a.elem.data(r,a.id))},l.that={},l.getThis=function(e){var i=l.that[e];return i||hint.error(e?t+" instance with ID '"+e+"' not found":"ID argument required"),i},o.render=function(e){e=new j(e);return l.call(e)},e(t,o)});layui.define(["lay","layer","util"],function(e){"use strict";var C=layui.$,h=layui.layer,d=layui.util,l=layui.hint(),w=(layui.device(),"form"),o=".layui-form",N="layui-this",T="layui-hide",$="layui-disabled",t=function(){this.config={verify:{required:function(e){if(!/[\S]+/.test(e))return"\u5fc5\u586b\u9879\u4e0d\u80fd\u4e3a\u7a7a"},phone:function(e){if(e&&!/^1\d{10}$/.test(e))return"\u624b\u673a\u53f7\u683c\u5f0f\u4e0d\u6b63\u786e"},email:function(e){if(e&&!/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(e))return"\u90ae\u7bb1\u683c\u5f0f\u4e0d\u6b63\u786e"},url:function(e){if(e&&!/^(#|(http(s?)):\/\/|\/\/)[^\s]+\.[^\s]+$/.test(e))return"\u94fe\u63a5\u683c\u5f0f\u4e0d\u6b63\u786e"},number:function(e){if(e&&isNaN(e))return"\u53ea\u80fd\u586b\u5199\u6570\u5b57"},date:function(e){if(e&&!/^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/.test(e))return"\u65e5\u671f\u683c\u5f0f\u4e0d\u6b63\u786e"},identity:function(e){if(e&&!/(^\d{15}$)|(^\d{17}(x|X|\d)$)/.test(e))return"\u8eab\u4efd\u8bc1\u53f7\u683c\u5f0f\u4e0d\u6b63\u786e"}},autocomplete:null}},i=(t.prototype.set=function(e){return C.extend(!0,this.config,e),this},t.prototype.verify=function(e){return C.extend(!0,this.config.verify,e),this},t.prototype.getFormElem=function(e){return C(o+(e?'[lay-filter="'+e+'"]':""))},t.prototype.on=function(e,t){return layui.onevent.call(this,w,e,t)},t.prototype.val=function(e,i){return this.getFormElem(e).each(function(e,t){var a=C(this);layui.each(i,function(e,t){var i,e=a.find('[name="'+e+'"]');e[0]&&("checkbox"===(i=e[0].type)?e[0].checked=t:"radio"===i?e.each(function(){this.checked=this.value==t}):e.val(t))})}),r.render(null,e),this.getValue(e)},t.prototype.getValue=function(e,t){t=t||this.getFormElem(e);var a={},n={},e=t.find("input,select,textarea");return layui.each(e,function(e,t){var i;C(this);t.name=(t.name||"").replace(/^\s*|\s*&/,""),t.name&&(/^.*\[\]$/.test(t.name)&&(i=t.name.match(/^(.*)\[\]$/g)[0],a[i]=0|a[i],i=t.name.replace(/^(.*)\[\]$/,"$1["+a[i]+++"]")),/^(checkbox|radio)$/.test(t.type)&&!t.checked||(n[i||t.name]=t.value))}),n},t.prototype.render=function(e,t){var i=this.config,a=C(o+(t?'[lay-filter="'+t+'"]':"")),n={input:function(e){var e=e||a.find("input,textarea"),t=(i.autocomplete&&e.attr("autocomplete",i.autocomplete),function(e,t){var i=e.val(),a=Number(i),n=Number(e.attr("step"))||1,l=Number(e.attr("min")),r=Number(e.attr("max")),s=Number(e.attr("lay-precision")),o="click"!==t&&""===i,c="init"===t;isNaN(a)||("click"===t&&(a=!!C(this).index()?a-n:a+n),t=function(e){return((e.toString().match(/\.(\d+$)/)||[])[1]||"").length},s=0<=s?s:Math.max(t(n),t(i)),o||(c||r<=(a=a<=l?l:a)&&(a=r),s&&(a=a.toFixed(s)),e.val(a)),e[(a'),e=layui.isArray(i.value)?i.value:[i.value],e=C((a=[],layui.each(e,function(e,t){a.push('')}),a.join(""))),n=(t.append(e),i.split&&t.addClass("layui-input-split"),i.className&&t.addClass(i.className),r.next("."+u)),l=(n[0]&&n.remove(),r.parent().hasClass(o)||r.wrap('
      '),r.next("."+c));l[0]?((n=l.find("."+u))[0]&&n.remove(),l.prepend(t),r.css("padding-right",function(){return(r.closest(".layui-input-group")[0]?0:l.outerWidth())+t.outerWidth()})):(t.addClass(c),r.after(t)),"auto"===i.show&&d(t,r.val()),"function"==typeof i.init&&i.init.call(this,r,i),r.on("input propertychange",function(){var e=this.value;"auto"===i.show&&d(t,e)}),r.on("blur",function(){"function"==typeof i.blur&&i.blur.call(this,r,i)}),e.on("click",function(){var e=r.attr("lay-filter");C(this).hasClass($)||("function"==typeof i.click&&i.click.call(this,r,i),layui.event.call(this,w,"input-affix("+e+")",{elem:r[0],affix:s,options:i}))})},f={eye:{value:"eye-invisible",click:function(e,t){var i="LAY_FORM_INPUT_AFFIX_SHOW",a=e.data(i);e.attr("type",a?"password":"text").data(i,!a),n({value:a?"eye-invisible":"eye"})}},clear:{value:"clear",click:function(e){e.val("").focus(),d(C(this).parent(),null)},show:"auto",disabled:e},number:{value:["up","down"],split:!0,className:"layui-input-number",disabled:r.is("[disabled]"),init:function(e){t.call(this,e,"init")},click:function(e){t.call(this,e,"click")},blur:function(e){t.call(this,e,"blur")}}};n()})},select:function(e){var p,c="\u8bf7\u9009\u62e9",m="layui-form-select",g="layui-select-title",x="layui-select-none",b="",e=e||a.find("select"),k=function(e,t){C(e.target).parent().hasClass(g)&&!t||(C("."+m).removeClass(m+"ed "+m+"up"),p&&b&&p.val(b)),p=null},u=function(a,e,t){var s,r,i,n,o,l,c=C(this),u=a.find("."+g),d=u.find("input"),f=a.find("dl"),h=f.children("dd"),y=f.children("dt"),v=this.selectedIndex;e||(r=c.attr("lay-search"),i=function(){var e=a.offset().top+a.outerHeight()+5-F.scrollTop(),t=f.outerHeight();v=c[0].selectedIndex,a.addClass(m+"ed"),h.removeClass(T),y.removeClass(T),s=null,h.removeClass(N),0<=v&&h.eq(v).addClass(N),e+t>F.height()&&t<=e&&a.addClass(m+"up"),o()},n=function(e){a.removeClass(m+"ed "+m+"up"),d.blur(),s=null,e||l(d.val(),function(e){var t=c[0].selectedIndex;e&&(b=C(c[0].options[t]).html(),0===t&&b===d.attr("placeholder")&&(b=""),d.val(b||""))})},o=function(){var e,t,i=f.children("dd."+N);i[0]&&(e=i.position().top,t=f.height(),i=i.height(),t\u65e0\u5339\u914d\u9879

      '):f.find("."+x).remove()},"keyup"),""===t&&(c.val(""),f.find("."+N).removeClass(N),(c[0].options[0]||{}).value||f.children("dd:eq(0)").addClass(N),f.find("."+x).remove()),o()}).on("blur",function(e){var t=c[0].selectedIndex;p=d,b=C(c[0].options[t]).text(),0===t&&b===d.attr("placeholder")&&(b=""),setTimeout(function(){l(d.val(),function(e){b||d.val("")},"blur")},200)})),h.on("click",function(){var e=C(this),t=e.attr("lay-value"),i=c.attr("lay-filter");return e.hasClass($)||(e.hasClass("layui-select-tips")?d.val(""):(d.val(e.text()),e.addClass(N)),e.siblings().removeClass(N),c.val(t).removeClass("layui-form-danger"),layui.event.call(this,w,"select("+i+")",{elem:c[0],value:t,othis:a}),n(!0)),!1}),a.find("dl>dt").on("click",function(e){return!1}),C(document).off("click",k).on("click",k))};e.each(function(e,t){var i=C(this),a=i.next("."+m),n=this.disabled,l=t.value,r=C(t.options[t.selectedIndex]),t=t.options[0];if("string"==typeof i.attr("lay-ignore"))return i.show();var s,o="string"==typeof i.attr("lay-search"),t=t&&!t.value&&t.innerHTML||c,r=C(['
      ','
      ','','
      ','
      ',(t=i.find("*"),s=[],layui.each(t,function(e,t){var i=t.tagName.toLowerCase();0!==e||t.value||"optgroup"===i?s.push("optgroup"===i?"
      "+t.label+"
      ":'
      '+C.trim(t.innerHTML)+"
      "):s.push('
      '+C.trim(t.innerHTML||c)+"
      ")}),0===s.length&&s.push('
      \u6ca1\u6709\u9009\u9879
      '),s.join("")+"
      "),"
      "].join(""));a[0]&&a.remove(),i.after(r),u.call(this,r,n,o)})},checkbox:function(e){var o={checkbox:["layui-form-checkbox","layui-form-checked","checkbox"],"switch":["layui-form-switch","layui-form-onswitch","switch"],SUBTRA:"layui-icon-indeterminate"},e=e||a.find("input[type=checkbox]");e.each(function(e,t){var i=C(this),a=i.attr("lay-skin")||"primary",n=d.escape(C.trim(t.title||(t.title=i.attr("lay-text")||""))),l=this.disabled,r=o[a]||o.checkbox,s=i.next("."+r[0]);if(s[0]&&s.remove(),i.next("[lay-checkbox]")[0]&&(n=i.next().html()||""),n="switch"===a?n.split("|"):[n],"string"==typeof i.attr("lay-ignore"))return i.show();l=C(['
      ",(s={checkbox:[n[0]?"
      "+n[0]+"
      ":"primary"===a?"":"
      ",''].join(""),"switch":"
      "+((t.checked?n[0]:n[1])||"")+"
      "})[a]||s.checkbox,"
      "].join(""));i.after(l),function(a,n){var l=C(this);a.on("click",function(){var e=C(this),t=l.attr("lay-filter"),e=e.next("*[lay-checkbox]")[0]?e.next().html():l.attr("title")||"",i=l.attr("lay-skin")||"primary",e="switch"===i?e.split("|"):[e];l[0].disabled||(l[0].indeterminate&&(l[0].indeterminate=!1,a.find("."+o.SUBTRA).removeClass(o.SUBTRA).addClass("layui-icon-ok")),l[0].checked?(l[0].checked=!1,a.removeClass(n[1]),"switch"===i&&a.children("div").html(e[1])):(l[0].checked=!0,a.addClass(n[1]),"switch"===i&&a.children("div").html(e[0])),layui.event.call(l[0],w,n[2]+"("+t+")",{elem:l[0],value:l[0].value,othis:a}))})}.call(this,l,r)})},radio:function(e){var r="layui-form-radio",s=["layui-icon-radio","layui-icon-circle"],e=e||a.find("input[type=radio]");e.each(function(e,t){var i=C(this),a=i.next("."+r),n=this.disabled;if("string"==typeof i.attr("lay-ignore"))return i.show();a[0]&&a.remove();n=C(['
      ','',"
      "+(a=d.escape(t.title||""),a=i.next("[lay-radio]")[0]?i.next().html():a)+"
      ","
      "].join(""));i.after(n),function(a){var n=C(this),l="layui-anim-scaleSpring";a.on("click",function(){var e=n[0].name,t=n.parents(o),i=n.attr("lay-filter"),e=t.find("input[name="+e.replace(/(\.|#|\[|\])/g,"\\$1")+"]");n[0].disabled||(layui.each(e,function(){var e=C(this).next("."+r);this.checked=!1,e.removeClass(r+"ed"),e.children(".layui-icon").removeClass(l+" "+s[0]).addClass(s[1])}),n[0].checked=!0,a.addClass(r+"ed"),a.children(".layui-icon").addClass(l+" "+s[0]),layui.event.call(n[0],w,"radio("+i+")",{elem:n[0],value:n[0].value,othis:a}))})}.call(this,n)})}},t=function(){layui.each(n,function(e,t){t()})};return"object"===layui.type(e)?C(e).is(o)?(a=C(e),t()):e.each(function(e,t){var i=C(t);i.closest(o).length&&("SELECT"===t.tagName?n.select(i):"INPUT"===t.tagName&&("checkbox"===(t=t.type)||"radio"===t?n[t](i):n.input(i)))}):e?n[e]?n[e]():l.error('\u4e0d\u652f\u6301\u7684 "'+e+'" \u8868\u5355\u6e32\u67d3'):t(),this},t.prototype.validate=function(e){var u,d=this.config.verify,f="layui-form-danger";return!(e=C(e))[0]||(e.attr("lay-verify")!==undefined||!1!==this.validate(e.find("*[lay-verify]")))&&(layui.each(e,function(e,r){var s=C(this),t=(s.attr("lay-verify")||"").split("|"),o=s.attr("lay-vertype"),c=C.trim(s.val());if(s.removeClass(f),layui.each(t,function(e,t){var i="",a=d[t];if(a){var n="function"==typeof a?i=a(c,r):!a[0].test(c),l="select"===r.tagName.toLowerCase()||/^(checkbox|radio)$/.test(r.type),i=i||a[1];if("required"===t&&(i=s.attr("lay-reqtext")||i),n)return"tips"===o?h.tips(i,"string"!=typeof s.attr("lay-ignore")&&l?s.next():s,{tips:1}):"alert"===o?h.alert(i,{title:"\u63d0\u793a",shadeClose:!0}):/\b(string|number)\b/.test(typeof i)&&h.msg(i,{icon:5,shift:6}),setTimeout(function(){(l?s.next().find("input"):r).focus()},7),s.addClass(f),u=!0}}),u)return u}),!u)},t.prototype.submit=function(e,t){var i={},a=C(this),e="string"==typeof e?e:a.attr("lay-filter"),n=this.getFormElem?this.getFormElem(e):a.parents(o).eq(0),l=n.find("*[lay-verify]");return!!r.validate(l)&&(i=r.getValue(null,n),l={elem:this.getFormElem?window.event&&window.event.target:this,form:(this.getFormElem?n:a.parents("form"))[0],field:i},"function"==typeof t&&t(l),layui.event.call(this,w,"submit("+e+")",l))}),r=new t,t=C(document),F=C(window);C(function(){r.render()}),t.on("reset",o,function(){var e=C(this).attr("lay-filter");setTimeout(function(){r.render(null,e)},50)}),t.on("submit",o,i).on("click","*[lay-submit]",i),e(w,r)});layui.define(["lay","laytpl","laypage","form","util"],function(n){"use strict";var p=layui.$,r=layui.lay,m=layui.laytpl,O=layui.laypage,f=layui.layer,v=layui.form,g=layui.util,x=layui.hint(),b=layui.device(),k={config:{checkName:"LAY_CHECKED",indexName:"LAY_INDEX",numbersName:"LAY_NUM",disabledName:"LAY_DISABLED"},cache:{},index:layui.table?layui.table.index+1e4:0,set:function(e){return this.config=p.extend({},this.config,e),this},on:function(e,t){return layui.onevent.call(this,N,e,t)}},w=function(){var a=this,e=a.config,i=e.id||e.index;return{config:e,reload:function(e,t){a.reload.call(a,e,t)},reloadData:function(e,t){k.reloadData(i,e,t)},setColsWidth:function(){a.setColsWidth.call(a)},resize:function(){a.resize.call(a)}}},C=function(e){var t=w.that[e];return t||x.error(e?"The table instance with ID '"+e+"' not found":"ID argument required"),t||null},l=function(e){var t=w.config[e];return t||x.error(e?"The table instance with ID '"+e+"' not found":"ID argument required"),t||null},T=function(e){var t=this.config||{},a=(e=e||{}).item3,i=e.content;"numbers"===a.type&&(i=e.tplData[k.config.numbersName]);("escape"in a?a:t).escape&&(i=g.escape(i));t=e.text&&a.exportTemplet||a.templet||a.toolbar;return t&&(i="function"==typeof t?t.call(a,e.tplData,e.obj):m(function(e){try{return r(e).html()}catch(t){return e}}(t)||String(i)).render(p.extend({LAY_COL:a},e.tplData))),e.text?p("
      "+i+"
      ").text():i},N="table",t=".layui-table",R="layui-hide",y="layui-hide-v",h="layui-none",D="layui-table-view",o=".layui-table-header",L=".layui-table-body",u=".layui-table-fixed-r",I=".layui-table-pageview",A=".layui-table-sort",E="layui-table-checked",_="layui-table-edit",M="layui-table-hover",P="laytable-cell-group",W="layui-table-col-special",j="layui-table-tool-panel",H="layui-table-expanded",S="LAY_TABLE_MOVE_DICT",e=function(e){return['',"","{{# layui.each(d.data.cols, function(i1, item1){ }}","","{{# layui.each(item1, function(i2, item2){ }}",'{{# if(item2.fixed && item2.fixed !== "right"){ left = true; } }}','{{# if(item2.fixed === "right"){ right = true; } }}',(e=e||{}).fixed&&"right"!==e.fixed?'{{# if(item2.fixed && item2.fixed !== "right"){ }}':"right"===e.fixed?'{{# if(item2.fixed === "right"){ }}':"","{{# var isSort = !(item2.colGroup) && item2.sort; }}",'",e.fixed?"{{# }; }}":"","{{# }); }}","","{{# }); }}","","
      ','
      ','{{# if(item2.type === "checkbox"){ }}','',"{{# } else { }}",'{{-item2.title||""}}',"{{# if(isSort){ }}",'',"{{# } }}","{{# } }}","
      ","
      "].join("")},a=['',"","
      "].join(""),s=[,"{{# if(d.data.toolbar){ }}",'
      ','
      ','
      ',"
      ","{{# } }}",'
      ',"{{# if(d.data.loading){ }}",'
      ','',"
      ","{{# } }}","{{# var left, right; }}",'
      ',e(),"
      ",'
      ',a,"
      ","{{# if(left){ }}",'
      ','
      ',e({fixed:!0}),"
      ",'
      ',a,"
      ","
      ","{{# }; }}","{{# if(right){ }}",'
      ','
      ',e({fixed:"right"}),'
      ',"
      ",'
      ',a,"
      ","
      ","{{# }; }}","
      ","{{# if(d.data.totalRow){ }}",'
      ','','',"
      ","
      ","{{# } }}",'
      ','
      ',"
      "].join(""),d=p(window),F=p(document),i=function(e){this.index=++k.index,this.config=p.extend({},this.config,k.config,e),this.render()},c=(i.prototype.config={limit:10,loading:!0,escape:!0,cellMinWidth:60,cellMaxWidth:Number.MAX_VALUE,editTrigger:"click",defaultToolbar:["filter","exports","print"],defaultContextmenu:!0,autoSort:!0,text:{none:"\u65e0\u6570\u636e"},cols:[]},i.prototype.render=function(e){var t=this,a=t.config,i=(a.elem=p(a.elem),a.where=a.where||{},a.id="id"in a?a.id:a.elem.attr("id")||t.index);if(w.that[i]=t,(w.config[i]=a).request=p.extend({pageName:"page",limitName:"limit"},a.request),a.response=p.extend({statusName:"code",statusCode:0,msgName:"msg",dataName:"data",totalRowName:"totalRow",countName:"count"},a.response),null!==a.page&&"object"==typeof a.page&&(a.limit=a.page.limit||a.limit,a.limits=a.page.limits||a.limits,t.page=a.page.curr=a.page.curr||1,delete a.page.elem,delete a.page.jump),!a.elem[0])return t;if(a.elem.attr("lay-filter")||a.elem.attr("lay-filter",a.id),"reloadData"===e)return t.pullData(t.page,{type:"reloadData"});a.index=t.index,t.key=a.id||a.index,t.setInit(),a.height&&/^full-.+$/.test(a.height)?(t.fullHeightGap=a.height.split("-")[1],a.height=d.height()-(parseFloat(t.fullHeightGap)||0)):a.height&&/^#\w+\S*-.+$/.test(a.height)?(i=a.height.split("-"),t.parentHeightGap=i.pop(),t.parentDiv=i.join("-"),a.height=p(t.parentDiv).height()-(parseFloat(t.parentHeightGap)||0)):"function"==typeof a.height&&(t.customHeightFunc=a.height,a.height=t.customHeightFunc());var l,e=a.elem,i=e.next("."+D),n=t.elem=p("
      ");n.addClass((l=[D,D+"-"+t.index,"layui-form","layui-border-box"],a.className&&l.push(a.className),l.join(" "))).attr({"lay-filter":"LAY-TABLE-FORM-DF-"+t.index,"lay-id":a.id,style:(l=[],a.width&&l.push("width:"+a.width+"px;"),l.join(""))}).html(m(s,{open:"{{",close:"}}"}).render({data:a,index:t.index})),t.renderStyle(),i[0]&&i.remove(),e.after(n),t.layTool=n.find(".layui-table-tool"),t.layBox=n.find(".layui-table-box"),t.layHeader=n.find(o),t.layMain=n.find(".layui-table-main"),t.layBody=n.find(L),t.layFixed=n.find(".layui-table-fixed"),t.layFixLeft=n.find(".layui-table-fixed-l"),t.layFixRight=n.find(u),t.layTotal=n.find(".layui-table-total"),t.layPage=n.find(".layui-table-page"),t.renderToolbar(),t.renderPagebar(),t.fullSize(),t.pullData(t.page),t.events()},i.prototype.initOpts=function(e){this.config;e.checkbox&&(e.type="checkbox"),e.space&&(e.type="space"),e.type||(e.type="normal"),"normal"!==e.type&&(e.unresize=!0,e.width=e.width||{checkbox:50,radio:50,space:30,numbers:60}[e.type])},i.prototype.setInit=function(e){var l,a,d=this,r=d.config;if(r.clientWidth=r.width||(l=function(e){var t,a=(e=e||r.elem.parent()).width();try{t="none"===e.css("display")}catch(i){}return!e[0]||a&&!t?a:l(e.parent())})(),"width"===e)return r.clientWidth;r.height=r.maxHeight||r.height,r.css&&-1===r.css.indexOf(D)&&(a=r.css.split("}"),layui.each(a,function(e,t){t&&(a[e]="."+D+"-"+d.index+" "+t)}),r.css=a.join("}"));var c=function(a,e,i,l){var n,o;l?(l.key=[r.index,a,i].join("-"),l.colspan=l.colspan||0,l.rowspan=l.rowspan||0,d.initOpts(l),(n=a+(parseInt(l.rowspan)||1)) td:hover > .layui-table-cell{overflow: auto;}"].concat(b.ie?[".layui-table-edit{height: "+i+";}","td[data-edit]:hover:after{height: "+i+";}"]:[]),function(e,t){t&&o.push(a+" "+t)})),l.css&&o.push(l.css),r.style({target:this.elem[0],text:o.join(""),id:"DF-table-"+n})},i.prototype.renderToolbar=function(){var e=this.config,t=['
      ','
      ','
      '].join(""),a=this.layTool.find(".layui-table-tool-temp"),i=("default"===e.toolbar?a.html(t):"string"==typeof e.toolbar&&(t=p(e.toolbar).html()||"")&&a.html(m(t).render(e)),{filter:{title:"\u7b5b\u9009\u5217",layEvent:"LAYTABLE_COLS",icon:"layui-icon-cols"},exports:{title:"\u5bfc\u51fa",layEvent:"LAYTABLE_EXPORT",icon:"layui-icon-export"},print:{title:"\u6253\u5370",layEvent:"LAYTABLE_PRINT",icon:"layui-icon-print"}}),l=[];"object"==typeof e.defaultToolbar&&layui.each(e.defaultToolbar,function(e,t){t="string"==typeof t?i[t]:t;t&&l.push('
      ')}),this.layTool.find(".layui-table-tool-self").html(l.join(""))},i.prototype.renderPagebar=function(){var e,t=this.config,a=this.layPagebar=p('
      ');t.pagebar&&((e=p(t.pagebar).html()||"")&&a.append(m(e).render(t)),this.layPage.append(a))},i.prototype.setParentCol=function(e,t){var a=this.config,i=this.layHeader.find('th[data-key="'+t+'"]'),l=parseInt(i.attr("colspan"))||0;i[0]&&(t=t.split("-"),t=a.cols[t[1]][t[2]],e?l--:l++,i.attr("colspan",l),i[l?"removeClass":"addClass"](R),t.colspan2=l,t.hide=l<1,a=i.data("parentkey"))&&this.setParentCol(e,a)},i.prototype.setColsPatch=function(){var a=this,e=a.config;layui.each(e.cols,function(e,t){layui.each(t,function(e,t){t.hide&&a.setParentCol(t.hide,t.parentKey)})})},i.prototype.setGroupWidth=function(i){var e,l=this;l.config.cols.length<=1||((e=l.layHeader.find((i?"th[data-key="+i.data("parentkey")+"]>":"")+"."+P)).css("width",0),layui.each(e.get().reverse(),function(){var e=p(this),t=e.parent().data("key"),a=0;l.layHeader.eq(0).find("th[data-parentkey="+t+"]").width(function(e,t){p(this).hasClass(R)||0 tr:first-child > th:last-child")).data("field")&&e.prev()[0]?t(e.prev()):e})()).data("key"),n.cssRules(e,function(e){var t=e.style.width||a.outerWidth();e.style.width=parseFloat(t)+l+"px",0'+(e||"Error")+"
      ");a[0]&&(t.layNone.remove(),a.remove()),t.layFixed.addClass(R),t.layMain.find("tbody").html(""),t.layMain.append(t.layNone=e),t.layTotal.addClass(y),t.layPage.find(I).addClass(y),k.cache[t.key]=[],t.syncCheckAll(),t.renderForm(),t.setColsWidth()},i.prototype.page=1,i.prototype.pullData=function(a,t){var e,i,l=this,n=l.config,o=(n.HAS_SET_COLS_PATCH||l.setColsPatch(),n.HAS_SET_COLS_PATCH=!0,n.request),d=n.response,r=function(){"object"==typeof n.initSort&&l.sort({field:n.initSort.field,type:n.initSort.type,reloadType:t.type})},c=function(e,t){l.setColsWidth(),"function"==typeof n.done&&n.done(e,a,e[d.countName],t)};t=t||{},"function"==typeof n.before&&n.before(n),l.startTime=(new Date).getTime(),t.renderData?((e={})[d.dataName]=k.cache[l.key],e[d.countName]=n.url?"object"===layui.type(n.page)?n.page.count:e[d.dataName].length:n.data.length,"object"==typeof n.totalRow&&(e[d.totalRowName]=p.extend({},l.totalRow)),l.renderData({res:e,curr:a,count:e[d.countName],type:t.type,sort:!0}),c(e,"renderData")):n.url?(i={},n.page&&(i[o.pageName]=a,i[o.limitName]=n.limit),o=p.extend(i,n.where),n.contentType&&0==n.contentType.indexOf("application/json")&&(o=JSON.stringify(o)),l.loading(),p.ajax({type:n.method||"get",url:n.url,contentType:n.contentType,data:o,dataType:n.dataType||"json",jsonpCallback:n.jsonpCallback,headers:n.headers||{},complete:"function"==typeof n.complete?n.complete:undefined,success:function(e){(e="function"==typeof n.parseData?n.parseData(e)||e:e)[d.statusName]!=d.statusCode?l.errorView(e[d.msgName]||'\u8fd4\u56de\u7684\u6570\u636e\u4e0d\u7b26\u5408\u89c4\u8303\uff0c\u6b63\u786e\u7684\u6210\u529f\u72b6\u6001\u7801\u5e94\u4e3a\uff1a"'+d.statusName+'": '+d.statusCode):(l.totalRow=e[d.totalRowName],l.renderData({res:e,curr:a,count:e[d.countName],type:t.type}),r(),n.time=(new Date).getTime()-l.startTime+" ms"),c(e)},error:function(e,t){l.errorView("\u8bf7\u6c42\u5f02\u5e38\uff0c\u9519\u8bef\u63d0\u793a\uff1a"+t),"function"==typeof n.error&&n.error(e,t)}})):"array"===layui.type(n.data)&&(e={},i=a*n.limit-n.limit,o=n.data.concat(),e[d.dataName]=n.page?o.splice(i,n.limit):o,e[d.countName]=n.data.length,"object"==typeof n.totalRow&&(e[d.totalRowName]=p.extend({},n.totalRow)),l.totalRow=e[d.totalRowName],l.renderData({res:e,curr:a,count:e[d.countName],type:t.type}),r(),c(e))},i.prototype.eachCols=function(e){return k.eachCols(null,e,this.config.cols),this},i.prototype.col=function(e){try{return e=e.split("-"),this.config.cols[e[1]][e[2]]||{}}catch(t){return x.error(t),{}}},i.prototype.getTrHtml=function(a,l,n,e){var s=this,u=s.config,y=e&&e.trs||[],h=e&&e.trs_fixed||[],f=e&&e.trs_fixed_r||[];return n=n||1,layui.each(a,function(e,o){var i=[],d=[],r=[],c=e+u.limit*(n-1)+1;if("object"!=typeof o){a[e]=o={LAY_KEY:o};try{k.cache[s.key][e]=o}catch(t){}}"array"===layui.type(o)&&0===o.length||(o[k.config.numbersName]=c,l||(o[k.config.indexName]=e),s.eachCols(function(e,l){var t,e=l.field||e,a=l.key,n=o[e];n!==undefined&&null!==n||(n=""),l.colGroup||(e=['','
      "+function(){var e,t=p.extend(!0,{LAY_COL:l},o),a=k.config.checkName,i=k.config.disabledName;switch(l.type){case"checkbox":return'';case"radio":return'';case"numbers":return c}return l.toolbar?m(p(l.toolbar).html()||"").render(t):T.call(s,{item3:l,content:n,tplData:t})}(),"
      "].join(""),i.push(e),l.fixed&&"right"!==l.fixed&&d.push(e),"right"===l.fixed&&r.push(e))}),e=['data-index="'+e+'"'],o[k.config.checkName]&&e.push('class="'+E+'"'),e=e.join(" "),y.push(""+i.join("")+""),h.push(""+d.join("")+""),f.push(""+r.join("")+""))}),{trs:y,trs_fixed:h,trs_fixed_r:f}},k.getTrHtml=function(e,t){e=C(e);return e.getTrHtml(t,null,e.page)},i.prototype.renderData=function(e){var a=this,i=a.config,t=e.res,l=e.curr,n=a.count=e.count,o=e.sort,d=t[i.response.dataName]||[],t=t[i.response.totalRowName],r=[],c=[],s=[],u=function(){if(!o&&a.sortKey)return a.sort({field:a.sortKey.field,type:a.sortKey.sort,pull:!0,reloadType:e.type});a.getTrHtml(d,o,l,{trs:r,trs_fixed:c,trs_fixed_r:s}),"fixed"===i.scrollPos&&"reloadData"===e.type||a.layBody.scrollTop(0),"reset"===i.scrollPos&&a.layBody.scrollLeft(0),a.layMain.find("."+h).remove(),a.layMain.find("tbody").html(r.join("")),a.layFixLeft.find("tbody").html(c.join("")),a.layFixRight.find("tbody").html(s.join("")),a.syncCheckAll(),a.renderForm(),a.fullSize(),a.haveInit?a.scrollPatch():setTimeout(function(){a.scrollPatch()},50),a.haveInit=!0,f.close(a.tipsIndex)};return k.cache[a.key]=d,a.layTotal[0==d.length?"addClass":"removeClass"](y),a.layPage[i.page||i.pagebar?"removeClass":"addClass"](R),a.layPage.find(I)[!i.page||0==n||0===d.length&&1==l?"addClass":"removeClass"](y),0===d.length?a.errorView(i.text.none):(a.layFixLeft.removeClass(R),o?u():(u(),a.renderTotal(d,t),a.layTotal&&a.layTotal.removeClass(R),void(i.page&&(i.page=p.extend({elem:"layui-table-page"+i.index,count:n,limit:i.limit,limits:i.limits||[10,20,30,40,50,60,70,80,90],groups:3,layout:["prev","page","next","skip","count","limit"],prev:'',next:'',jump:function(e,t){t||(a.page=e.curr,i.limit=e.limit,a.pullData(e.curr))}},i.page),i.page.count=n,O.render(i.page)))))},k.renderData=function(e){e=C(e);e&&e.pullData(e.page,{renderData:!0,type:"reloadData"})},i.prototype.renderTotal=function(e,o){var d,r=this,c=r.config,s={};c.totalRow&&(layui.each(e,function(e,i){"array"===layui.type(i)&&0===i.length||r.eachCols(function(e,t){var e=t.field||e,a=i[e];t.totalRow&&(s[e]=(s[e]||0)+(parseFloat(a)||0))})}),r.dataTotal=[],d=[],r.eachCols(function(e,t){var a,e=t.field||e,i=o&&o[t.field],l="totalRowDecimals"in t?t.totalRowDecimals:2,l=s[e]?parseFloat(s[e]||0).toFixed(l):"",l=(a=t.totalRowText||"",(n={LAY_COL:t})[e]=l,n=t.totalRow&&T.call(r,{item3:t,content:l,tplData:n})||a,i||n),n=(t.field&&r.dataTotal.push({field:t.field,total:p("
      "+l+"
      ").text()}),['','
      "+("string"==typeof(a=t.totalRow||c.totalRow)?m(a).render(p.extend({TOTAL_NUMS:i||s[e],TOTAL_ROW:o||{},LAY_COL:t},t)):l),"
      "].join(""));d.push(n)}),e=r.layTotal.find(".layui-table-patch"),r.layTotal.find("tbody").html(""+d.join("")+(e.length?e.get(0).outerHTML:"")+""))},i.prototype.getColElem=function(e,t){return e.eq(0).find(".laytable-cell-"+t+":eq(0)")},i.prototype.renderForm=function(e){this.config;var t=this.elem.attr("lay-filter");v.render(e,t)},i.prototype.syncCheckAll=function(){var a,e=this,i=e.config,t=e.layHeader.find('input[name="layTableCheckbox"]'),l=k.checkStatus(e.key);t[0]&&(a=l.isAll,e.eachCols(function(e,t){"checkbox"===t.type&&(t[i.checkName]=a)}),t.prop({checked:l.isAll,indeterminate:!l.isAll&&l.data.length}),v.render(t))},i.prototype.setRowActive=function(e,t,a){this.config;e=this.layBody.find('tr[data-index="'+e+'"]');if(t=t||"layui-table-click",a)return e.removeClass(t);e.addClass(t),e.siblings("tr").removeClass(t)},i.prototype.setRowChecked=function(i){var e=this,l=e.config,n="all"===i.index,o="array"===layui.type(i.index),d=(t=e.layBody.find("tr"),n?t:t.filter(o?function(){var e=p(this).data("index");return-1!==i.index.indexOf(e)}:'[data-index="'+i.index+'"]')),t=(i=p.extend({type:"checkbox"},i),k.cache[e.key]),a="checked"in i,r=function(e){return"radio"===i.type||(a?i.checked:!e)},t=(layui.each(t,function(e,t){var a;"array"===layui.type(t)||t[l.disabledName]||(n||(o?-1!==i.index.indexOf(e):Number(i.index)===e)?(a=t[l.checkName]=r(t[l.checkName]),(e=d.filter('[data-index="'+e+'"]'))[a?"addClass":"removeClass"](E),"radio"===i.type&&e.siblings().removeClass(E)):"radio"===i.type&&delete t[l.checkName])}),d.find('input[lay-type="'+({radio:"layTableRadio",checkbox:"layTableCheckbox"}[i.type]||"checkbox")+'"]:not(:disabled)')),c=t.last(),s=c.closest(u);("radio"===i.type&&s.hasClass(R)?t.first():t).prop("checked",r(c.prop("checked"))),e.syncCheckAll(),e.renderForm(i.type)},i.prototype.sort=function(l){var e,t=this,a={},i=t.config,n=i.elem.attr("lay-filter"),o=k.cache[t.key];"string"==typeof(l=l||{}).field&&(d=l.field,t.layHeader.find("th").each(function(e,t){var a=p(this),i=a.data("field");if(i===l.field)return l.field=a,d=i,!1}));try{var d=d||l.field.data("field"),r=l.field.data("key");if(t.sortKey&&!l.pull&&d===t.sortKey.field&&l.type===t.sortKey.sort)return;var c=t.layHeader.find("th .laytable-cell-"+r).find(A);t.layHeader.find("th").find(A).removeAttr("lay-sort"),c.attr("lay-sort",l.type||null),t.layFixed.find("th")}catch(s){x.error("Table modules: sort field '"+d+"' not matched")}t.sortKey={field:d,sort:l.type},i.autoSort&&("asc"===l.type?e=layui.sort(o,d,null,!0):"desc"===l.type?e=layui.sort(o,d,!0,!0):(e=layui.sort(o,k.config.indexName,null,!0),delete t.sortKey,delete i.initSort)),a[i.response.dataName]=e||o,t.renderData({res:a,curr:t.page,count:t.count,sort:!0,type:l.reloadType}),l.fromEvent&&(i.initSort={field:d,type:l.type},layui.event.call(l.field,N,"sort("+n+")",p.extend({config:i},i.initSort)))},i.prototype.loading=function(e){var t=this;t.config.loading&&(e?(t.layInit&&t.layInit.remove(),delete t.layInit,t.layBox.find(".layui-table-init").remove()):(t.layInit=p(['
      ','',"
      "].join("")),t.layBox.append(t.layInit)))},i.prototype.cssRules=function(t,a){var e=this.elem.children("style")[0];r.getStyleRules(e,function(e){if(e.selectorText===".laytable-cell-"+t)return a(e),!0})},i.prototype.fullSize=function(){var e,a,i=this,t=i.config,l=t.height;i.fullHeightGap?(l=d.height()-i.fullHeightGap)<135&&(l=135):i.parentDiv&&i.parentHeightGap?(l=p(i.parentDiv).height()-i.parentHeightGap)<135&&(l=135):i.customHeightFunc&&(l=i.customHeightFunc())<135&&(l=135),1
      ')).find("div").css({width:a}),e.find("tr").append(t)):e.find(".layui-table-patch").remove()};n(e.layHeader),n(e.layTotal);n=e.layMain.height()-i;e.layFixed.find(L).css("height",t.height()>=n?n:"auto").scrollTop(e.layMain.scrollTop()),e.layFixRight[k.cache[e.key]&&k.cache[e.key].length&&0');a.html(t),u.height&&a.css("max-height",u.height-(s.layTool.outerHeight()||50)),i.find("."+j)[0]||i.append(a),s.renderForm(),a.on("click",function(e){layui.stope(e)}),e.done&&e.done(a,t)};switch(layui.stope(e),F.trigger("table.tool.panel.remove"),f.close(s.tipsIndex),t){case"LAYTABLE_COLS":n({list:(a=[],s.eachCols(function(e,t){t.field&&"normal"==t.type&&a.push('
    • "+(t.fieldTitle||t.title||t.field)+"
    • ").text())+'" lay-filter="LAY_TABLE_TOOL_COLS">')}),a.join("")),done:function(){v.on("checkbox(LAY_TABLE_TOOL_COLS)",function(e){var e=p(e.elem),t=this.checked,a=e.data("key"),i=s.col(a),l=i.hide,e=e.data("parentkey");i.key&&(i.hide=!t,s.elem.find('*[data-key="'+a+'"]')[t?"removeClass":"addClass"](R),l!=i.hide&&s.setParentCol(!t,e),s.resize(),layui.event.call(this,N,"colToggled("+c+")",{col:i,config:u}))})}});break;case"LAYTABLE_EXPORT":if(!l.length)return f.tips("\u5f53\u524d\u8868\u683c\u65e0\u6570\u636e",this,{tips:3});b.ie?f.tips("\u5bfc\u51fa\u529f\u80fd\u4e0d\u652f\u6301 IE\uff0c\u8bf7\u7528 Chrome \u7b49\u9ad8\u7ea7\u6d4f\u89c8\u5668\u5bfc\u51fa",this,{tips:3}):n({list:['
    • \u5bfc\u51fa csv \u683c\u5f0f\u6587\u4ef6
    • ','
    • \u5bfc\u51fa xls \u683c\u5f0f\u6587\u4ef6
    • '].join(""),done:function(e,t){t.on("click",function(){var e=p(this).data("type");k.exportFile.call(s,u.id,null,e)})}});break;case"LAYTABLE_PRINT":if(!l.length)return f.tips("\u5f53\u524d\u8868\u683c\u65e0\u6570\u636e",this,{tips:3});var o=window.open("about:blank","_blank"),d=[""].join(""),r=p(s.layHeader.html());r.append(s.layMain.find("table").html()),r.append(s.layTotal.find("table").html()),r.find("th.layui-table-patch").remove(),r.find("thead>tr>th."+W).filter(function(e,t){return!p(t).children("."+P).length}).remove(),r.find("tbody>tr>td."+W).remove(),o.document.write(d+r.prop("outerHTML")),o.document.close(),layui.device("edg").edg?(o.onafterprint=o.close,o.print()):(o.print(),o.close())}layui.event.call(this,N,"toolbar("+c+")",p.extend({event:t,config:u},{}))}),s.layHeader.on("click","*[lay-event]",function(e){var t=p(this),a=t.attr("lay-event"),t=t.closest("th").data("key"),t=s.col(t);layui.event.call(this,N,"colTool("+c+")",p.extend({event:a,config:u,col:t},{}))}),s.layPagebar.on("click","*[lay-event]",function(e){var t=p(this).attr("lay-event");layui.event.call(this,N,"pagebar("+c+")",p.extend({event:t,config:u},{}))}),e.on("mousemove",function(e){var t=p(this),a=t.offset().left,e=e.clientX-a;t.data("unresize")||w.eventMoveElem||(d.allowResize=t.width()-e<=10,o.css("cursor",d.allowResize?"col-resize":""))}).on("mouseleave",function(){p(this);w.eventMoveElem||o.css("cursor","")}).on("mousedown",function(e){var t,a=p(this);d.allowResize&&(t=a.data("key"),e.preventDefault(),d.offset=[e.clientX,e.clientY],s.cssRules(t,function(e){var t=e.style.width||a.outerWidth();d.rule=e,d.ruleWidth=parseFloat(t),d.minWidth=a.data("minwidth")||u.cellMinWidth,d.maxWidth=a.data("maxwidth")||u.cellMaxWidth}),a.data(S,d),w.eventMoveElem=a)}),w.docEvent||F.on("mousemove",function(e){var t,a;w.eventMoveElem&&(t=w.eventMoveElem.data(S)||{},w.eventMoveElem.data("resizing",1),e.preventDefault(),t.rule)&&(e=t.ruleWidth+e.clientX-t.offset[0],a=w.eventMoveElem.closest("."+D).attr("lay-id"),a=C(a))&&((e=et.maxWidth&&(e=t.maxWidth),t.rule.style.width=e+"px",a.setGroupWidth(w.eventMoveElem),f.close(s.tipsIndex))}).on("mouseup",function(e){var t,a,i,l,n;w.eventMoveElem&&(i=(t=w.eventMoveElem).closest("."+D).attr("lay-id"),a=C(i))&&(i=t.data("key"),l=a.col(i),n=a.config.elem.attr("lay-filter"),d={},o.css("cursor",""),a.scrollPatch(),t.removeData(S),delete w.eventMoveElem,a.cssRules(i,function(e){l.width=parseFloat(e.style.width),layui.event.call(t[0],N,"colResized("+n+")",{col:l,config:a.config})}))}),w.docEvent=!0,e.on("click",function(e){var t=p(this),a=t.find(A),i=a.attr("lay-sort");if(!a[0]||1===t.data("resizing"))return t.removeData("resizing");s.sort({field:t,type:"asc"===i?"desc":"desc"===i?null:"asc",fromEvent:!0})}).find(A+" .layui-edge ").on("click",function(e){var t=p(this),a=t.index(),t=t.parents("th").eq(0).data("field");layui.stope(e),0===a?s.sort({field:t,type:"asc",fromEvent:!0}):s.sort({field:t,type:"desc",fromEvent:!0})}),s.commonMember=function(e){var t=p(this).parents("tr").eq(0).data("index"),r=s.layBody.find('tr[data-index="'+t+'"]'),c=(c=k.cache[s.key]||[])[t]||{},a={tr:r,config:u,data:k.clearCacheKey(c),dataCache:c,index:t,del:function(){k.cache[s.key][t]=[],r.remove(),s.scrollPatch()},update:function(e,d){e=e||{},layui.each(e,function(i,l){var n=r.children('td[data-field="'+i+'"]'),o=n.children(y);c[i]=a.data[i]=l,s.eachCols(function(e,t){var a;t.field==i?(o.html(T.call(s,{item3:t,content:l,tplData:p.extend({LAY_COL:t},c)})),n.data("content",l)):d&&(t.templet||t.toolbar)&&(e=r.children('td[data-field="'+(t.field||e)+'"]'),a=c[t.field],e.children(y).html(T.call(s,{item3:t,content:a,tplData:p.extend({LAY_COL:t},c)})),e.data("content",a))})}),s.renderForm()},setRowChecked:function(e){s.setRowChecked(p.extend({index:t},e))}};return p.extend(a,e)}),a=(s.elem.on("click",'input[name="layTableCheckbox"]+',function(e){var t=p(this),a=t.closest("td"),t=t.prev(),i=(s.layBody.find('input[name="layTableCheckbox"]'),t.parents("tr").eq(0).data("index")),l=t[0].checked,n="layTableAllChoose"===t.attr("lay-filter");t[0].disabled||(n?s.setRowChecked({index:"all",checked:l}):(s.setRowChecked({index:i,checked:l}),layui.stope(e)),layui.event.call(t[0],N,"checkbox("+c+")",r.call(t[0],{checked:l,type:n?"all":"one",getCol:function(){return s.col(a.data("key"))}})))}),s.elem.on("click",'input[lay-type="layTableRadio"]+',function(e){var t=p(this),a=t.closest("td"),t=t.prev(),i=t[0].checked,l=t.parents("tr").eq(0).data("index");if(layui.stope(e),t[0].disabled)return!1;s.setRowChecked({type:"radio",index:l}),layui.event.call(t[0],N,"radio("+c+")",r.call(t[0],{checked:i,getCol:function(){return s.col(a.data("key"))}}))}),s.layBody.on("mouseenter","tr",function(){var e=p(this),t=e.index();e.data("off")||s.layBody.find("tr:eq("+t+")").addClass(M)}).on("mouseleave","tr",function(){var e=p(this),t=e.index();e.data("off")||s.layBody.find("tr:eq("+t+")").removeClass(M)}).on("click","tr",function(e){var t=[".layui-form-checkbox",".layui-form-switch",".layui-form-radio","[lay-unrow]"].join(",");p(e.target).is(t)||p(e.target).closest(t)[0]||a.call(this,"row")}).on("dblclick","tr",function(){a.call(this,"rowDouble")}).on("contextmenu","tr",function(e){u.defaultContextmenu||e.preventDefault(),a.call(this,"rowContextmenu")}),function(e){var t=p(this);t.data("off")||layui.event.call(this,N,e+"("+c+")",r.call(t.children("td")[0]))}),n=function(e,t){var a,i,l;(e=p(e)).data("off")||(l=e.data("field"),i=e.data("key"),i=s.col(i),a=e.closest("tr").data("index"),a=k.cache[s.key][a],e.children(y),(i="function"==typeof i.edit?i.edit(a):i.edit)&&((i=p("textarea"===i?'':''))[0].value=(l=e.data("content")||a[l])===undefined||null===l?"":l,e.find("."+_)[0]||e.append(i),i.focus(),t)&&layui.stope(t))},i=(s.layBody.on("change","."+_,function(){var e=p(this),t=e.parent(),a=this.value,i=e.parent().data("field"),e=e.closest("tr").data("index"),e=k.cache[s.key][e],l=r.call(t[0],{value:a,field:i,oldValue:e[i],td:t,reedit:function(){setTimeout(function(){n(l.td);var e={};e[i]=l.oldValue,l.update(e)})},getCol:function(){return s.col(t.data("key"))}}),e={};e[i]=a,l.update(e),layui.event.call(t[0],N,"edit("+c+")",l)}).on("blur","."+_,function(){p(this).remove()}),s.layBody.on(u.editTrigger,"td",function(e){n(this,e)}).on("mouseenter","td",function(){t.call(this)}).on("mouseleave","td",function(){t.call(this,"hide")}),s.layTotal.on("mouseenter","td",function(){t.call(this)}).on("mouseleave","td",function(){t.call(this,"hide")}),"layui-table-grid-down"),t=function(e){var t=p(this),a=t.children(y);t.data("off")||t.parent().hasClass(H)||(e?t.find(".layui-table-grid-down").remove():!(a.prop("scrollWidth")>a.outerWidth()||0'))},l=function(e,t){var a=p(this),i=a.parent(),l=i.data("key"),n=s.col(l),o=i.parent().data("index"),i=i.children(y),d="layui-table-cell-c",r=p('');"tips"===(t=t||n.expandedMode||u.cellExpandedMode)?s.tipsIndex=f.tips(['
      ',i.html(),"
      ",''].join(""),i[0],{tips:[3,""],time:-1,anim:-1,maxWidth:b.ios||b.android?300:s.elem.width()/2,isOutAnim:!1,skin:"layui-table-tips",success:function(e,t){e.find(".layui-table-tips-c").on("click",function(){f.close(t)})}}):(s.elem.find("."+d).trigger("click"),s.cssRules(l,function(e){var t=e.style.width,a=n.expandedWidth||u.cellExpandedWidth;atr").each(function(i){n.cols[i]=[],p(this).children().each(function(e){var t=p(this),a=t.attr("lay-data"),a=r.options(this,{attr:a?"lay-data":null,errorText:d+(a||t.attr("lay-options"))}),t=p.extend({title:t.text(),colspan:parseInt(t.attr("colspan"))||1,rowspan:parseInt(t.attr("rowspan"))||1},a);n.cols[i].push(t)})}),e.find("tbody>tr")),t=k.render(n);!a.length||o.data||t.config.url||(l=0,k.eachCols(t.config.id,function(e,i){a.each(function(e){n.data[e]=n.data[e]||{};var t=p(this),a=i.field;n.data[e][a]=t.children("td").eq(l).html()}),l++}),t.reloadData({data:n.data}))}),this},w.that={},w.config={},function(a,i,e,l){var n,o;l.colGroup&&(n=0,a++,l.CHILD_COLS=[],o=e+(parseInt(l.rowspan)||1),layui.each(i[o],function(e,t){t.parentKey?t.parentKey===l.key&&(t.PARENT_COL_INDEX=a,l.CHILD_COLS.push(t),c(a,i,o,t)):t.PARENT_COL_INDEX||1<=n&&n==(l.colspan||1)||(t.PARENT_COL_INDEX=a,l.CHILD_COLS.push(t),n+=parseInt(1td').filter('[data-field="'+e+'"]')}}})).replace(/"/g,'""'),n.push(a='"'+a+'"')))}),d.push(n.join(","))}),c&&layui.each(c.dataTotal,function(e,t){r[t.field]||i.push('"'+(t.total||"")+'"')}),o.join(",")+"\r\n"+d.join("\r\n")+"\r\n"+i.join(","))),u.download=(a.title||n.title||"table_"+(n.index||""))+"."+l,document.body.appendChild(u),u.click(),document.body.removeChild(u)},k.getOptions=l,k.hideCol=function(e,l){var n=C(e);n&&("boolean"===layui.type(l)?n.eachCols(function(e,t){var a=t.key,i=n.col(a),t=t.parentKey;i.hide!=l&&(i=i.hide=l,n.elem.find('*[data-key="'+a+'"]')[i?"addClass":"removeClass"](R),n.setParentCol(i,t))}):(l=layui.isArray(l)?l:[l],layui.each(l,function(e,l){n.eachCols(function(e,t){var a,i;l.field===t.field&&(a=t.key,i=n.col(a),t=t.parentKey,"hide"in l)&&i.hide!=l.hide&&(i=i.hide=!!l.hide,n.elem.find('*[data-key="'+a+'"]')[i?"addClass":"removeClass"](R),n.setParentCol(i,t))})})),p("."+j).remove(),n.resize())},k.reload=function(e,t,a,i){if(l(e))return(e=C(e)).reload(t,a,i),w.call(e)},k.reloadData=function(){var a=p.extend([],arguments),i=(a[3]="reloadData",new RegExp("^("+["elem","id","cols","width","height","maxHeight","toolbar","defaultToolbar","className","css","pagebar"].join("|")+")$"));return layui.each(a[1],function(e,t){i.test(e)&&delete a[1][e]}),k.reload.apply(null,a)},k.render=function(e){e=new i(e);return w.call(e)},k.clearCacheKey=function(e){return delete(e=p.extend({},e))[k.config.checkName],delete e[k.config.indexName],delete e[k.config.numbersName],delete e[k.config.disabledName],e},p(function(){k.init()}),n(N,k)});layui.define(["table"],function(e){"use strict";var E=layui.$,x=layui.form,B=layui.table,y=layui.hint(),j={config:{},on:B.on,eachCols:B.eachCols,index:B.index,set:function(e){var t=this;return t.config=E.extend({},t.config,e),t},resize:B.resize,getOptions:B.getOptions,hideCol:B.hideCol,renderData:B.renderData},i=function(){var a=this,e=a.config,n=e.id||e.index;return{config:e,reload:function(e,t){a.reload.call(a,e,t)},reloadData:function(e,t){j.reloadData(n,e,t)}}},P=function(e){var t=i.that[e];return t||y.error(e?"The treeTable instance with ID '"+e+"' not found":"ID argument required"),t||null},F="layui-hide",L=".layui-table-main",q=".layui-table-fixed-l",R=".layui-table-fixed-r",l="layui-table-checked",h="layui-table-tree",Y="LAY_DATA_INDEX",m="LAY_DATA_INDEX_HISTORY",s="LAY_PARENT_INDEX",b="LAY_CHECKBOX_HALF",H="LAY_EXPAND",z="LAY_HAS_EXPANDED",X="LAY_ASYNC_STATUS",n=["all","parent","children","none"],t=function(e){var t=this;t.index=++j.index,t.config=E.extend(!0,{},t.config,j.config,e),t.init(),t.render()},f=function(n,i,e){var l=B.cache[n];layui.each(e||l,function(e,t){var a=t[Y]||"";-1!==a.indexOf("-")&&(l[a]=t),t[i]&&f(n,i,t[i])})},d=function(l,a,e){var d=P(l),r=("reloadData"!==e&&(d.status={expand:{}}),E.extend(!0,{},d.getOptions(),a)),n=r.tree,o=n.customName.children,i=n.customName.id,c=(delete a.hasNumberCol,delete a.hasChecboxCol,delete a.hasRadioCol,B.eachCols(null,function(e,t){"numbers"===t.type?a.hasNumberCol=!0:"checkbox"===t.type?a.hasChecboxCol=!0:"radio"===t.type&&(a.hasRadioCol=!0)},r.cols),a.parseData),u=a.done;r.url?e&&(!c||c.mod)||(a.parseData=function(){var e=this,t=arguments,a=t[0],t=("function"===layui.type(c)&&(a=c.apply(e,t)||t[0]),e.response.dataName);return n.data.isSimpleData&&!n["async"].enable&&(a[t]=d.flatToTree(a[t])),p(a[t],function(e){e[H]=H in e?e[H]:e[i]!==undefined&&d.status.expand[e[i]]},o),e.autoSort&&e.initSort&&e.initSort.type&&layui.sort(a[t],e.initSort.field,"desc"===e.initSort.type,!0),d.initData(a[t]),a},a.parseData.mod=!0):(a.data=a.data||[],n.data.isSimpleData&&(a.data=d.flatToTree(a.data)),d.initData(a.data)),e&&(!u||u.mod)||(a.done=function(){var e,t=arguments,a=t[3],n=(a||delete d.isExpandAll,this.elem.next()),i=(d.updateStatus(null,{LAY_HAS_EXPANDED:!1}),f(l,o),n.find('[name="layTableCheckbox"][lay-filter="layTableAllChoose"]'));if(i.length&&(e=j.checkStatus(l),i.prop({checked:e.isAll&&e.data.length,indeterminate:!e.isAll&&e.data.length})),!a&&r.autoSort&&r.initSort&&r.initSort.type&&j.sort(l),d.renderTreeTable(n),"function"===layui.type(u))return u.apply(this,t)},a.done.mod=!0)};t.prototype.init=function(){var e=this.config,t=e.tree.data.cascade,t=(-1===n.indexOf(t)&&(e.tree.data.cascade="all"),B.render(E.extend({},e,{data:[],url:"",done:null}))),a=t.config.id;(i.that[a]=this).tableIns=t,d(a,e)},t.prototype.config={tree:{customName:{children:"children",isParent:"isParent",name:"name",id:"id",pid:"parentId",icon:"icon"},view:{indent:14,flexIconClose:'',flexIconOpen:'',showIcon:!0,icon:"",iconClose:'',iconOpen:'',iconLeaf:'',showFlexIconIfNotParent:!1,dblClickExpand:!0,expandAllDefault:!1},data:{isSimpleData:!1,rootPid:null,cascade:"all"},"async":{enable:!1,url:"",type:null,contentType:null,headers:null,where:null,autoParam:[]},callback:{beforeExpand:null,onExpand:null}}},t.prototype.getOptions=function(){return this.tableIns?B.getOptions(this.tableIns.config.id):this.config},t.prototype.flatToTree=function(e){var a,n,i,t,l,d,r,o=this.getOptions(),c=o.tree,u=c.customName,o=o.id;return e=e||B.cache[o],o=e,a=u.id,n=u.pid,i=u.children,t=c.data.rootPid,a=a||"id",n=n||"parentId",i=i||"children",r={},layui.each(o,function(e,t){l=a+t[a],r[l]=E.extend({},t),r[l][i]=[]}),layui.each(r,function(e,t){(d=a+t[n])&&r[d]&&r[d][i].push(t)}),Object.keys(r).map(function(e){return r[e]}).filter(function(e){return t?e[n]===t:!e[n]})},t.prototype.treeToFlat=function(e,n,i){var l=this,d=l.getOptions().tree.customName,r=d.children,o=d.pid,c=[];return layui.each(e,function(e,t){var e=(i?i+"-":"")+e,a=E.extend({},t);a[o]=t[o]||n,c.push(a),c=c.concat(l.treeToFlat(t[r],t[d.id],e))}),c},t.prototype.getTreeNode=function(e){var t,a,n=this;return e?(a=(t=n.getOptions()).tree,t.id,a.customName,{data:e,dataIndex:e[Y],getParentNode:function(){return n.getNodeByIndex(e[s])}}):y.error("\u627e\u4e0d\u5230\u8282\u70b9\u6570\u636e")},t.prototype.getNodeByIndex=function(t){var a,e,n=this,i=n.getNodeDataByIndex(t);return i?((e=n.getOptions()).tree.customName.parent,a=e.id,(e={data:i,dataIndex:i[Y],getParentNode:function(){return n.getNodeByIndex(i[s])},update:function(e){return j.updateNode(a,t,e)},remove:function(){return j.removeNode(a,t)},expand:function(e){return j.expandNode(a,E.extend({},e,{index:t}))},setChecked:function(e){return j.setRowChecked(a,E.extend({},e,{index:t}))}}).dataIndex=t,e):y.error("\u627e\u4e0d\u5230\u8282\u70b9\u6570\u636e")},t.prototype.getNodeById=function(a){var e=this.getOptions(),n=e.tree.customName.id,i="",e=j.getData(e.id,!0);if(layui.each(e,function(e,t){if(t[n]===a)return i=t[Y],!0}),i)return this.getNodeByIndex(i)},t.prototype.getNodeDataByIndex=function(e,t,a){var n=this.getOptions(),i=n.tree,n=n.id,n=B.cache[n],l=n[e];if("delete"!==a&&l)return E.extend(l,a),t?E.extend({},l):l;for(var d=n,r=String(e).split("-"),o=0,c=i.customName.children;o
      '),N=function(e){y[X]="success",y[s.children]=e,c.initData(y[s.children],y[Y]),U(t,!0,!p&&n,i,l)},C=m.format,"function"===layui.type(C)?C(y,o,N):(I=E.extend({},m.where||o.where),C=m.autoParam,layui.each(C,function(e,t){t=t.split("=");I[t[0].trim()]=y[(t[1]||t[0]).trim()]}),(C=m.contentType||o.contentType)&&0==C.indexOf("application/json")&&(I=JSON.stringify(I)),w=m.method||o.method,D=m.dataType||o.dataType,T=m.jsonpCallback||o.jsonpCallback,k=m.headers||o.headers,_=m.parseData||o.parseData,O=m.response||o.response,E.ajax({type:w||"get",url:b,contentType:C,data:I,dataType:D||"json",jsonpCallback:T,headers:k||{},success:function(e){(e="function"==typeof _?_.call(o,e)||e:e)[O.statusName]!=O.statusCode?(y[X]="error",g.html('')):N(e[O.dataName])},error:function(e,t){y[X]="error","function"==typeof o.error&&o.error(e,t)}})),h;y[z]=!0,v.length&&(!o.initSort||o.url&&!o.autoSort||((m=o.initSort).type?layui.sort(v,m.field,"desc"===m.type,!0):layui.sort(v,B.config.indexName,null,!0)),c.initData(y[s.children],y[Y]),w=B.getTrHtml(r,v,null,null,e),S={trs:E(w.trs.join("")),trs_fixed:E(w.trs_fixed.join("")),trs_fixed_r:E(w.trs_fixed_r.join(""))},A=(e.split("-").length-1||0)+1,layui.each(v,function(e,t){S.trs.eq(e).attr({"data-index":t[Y],"lay-data-index":t[Y],"data-level":A}),S.trs_fixed.eq(e).attr({"data-index":t[Y],"lay-data-index":t[Y],"data-level":A}),S.trs_fixed_r.eq(e).attr({"data-index":t[Y],"lay-data-index":t[Y],"data-level":A})}),d.find(L).find('tbody tr[lay-data-index="'+e+'"]').after(S.trs),d.find(q).find('tbody tr[lay-data-index="'+e+'"]').after(S.trs_fixed),d.find(R).find('tbody tr[lay-data-index="'+e+'"]').after(S.trs_fixed_r),c.renderTreeTable(S.trs,A),n)&&!p&&layui.each(v,function(e,t){U({dataIndex:t[Y],trElem:d.find('tr[lay-data-index="'+t[Y]+'"]').first(),tableViewElem:d,tableId:r,options:o},a,n,i,l)})}else c.isExpandAll=!1,(n&&!p?(layui.each(v,function(e,t){U({dataIndex:t[Y],trElem:d.find('tr[lay-data-index="'+t[Y]+'"]').first(),tableViewElem:d,tableId:r,options:o},a,n,i,l)}),d.find(v.map(function(e,t,a){return'tr[lay-data-index="'+e[Y]+'"]'}).join(","))):(b=c.treeToFlat(v,y[s.id],e),d.find(b.map(function(e,t,a){return'tr[lay-data-index="'+e[Y]+'"]'}).join(",")))).addClass(F);V("resize-"+r,function(){j.resize(r)},0)(),l&&"loading"!==y[X]&&(C=u.callback.onExpand,"function"===layui.type(C))&&C(r,y,x)}return h},g=(j.expandNode=function(e,t){var a,n,i,e=P(e);if(e)return a=(t=t||{}).index,n=t.expandFlag,i=t.inherit,t=t.callbackFlag,e=e.getOptions().elem.next(),U({trElem:e.find('tr[lay-data-index="'+a+'"]').first()},n,i,null,t)},j.expandAll=function(a,e){if("boolean"!==layui.type(e))return y.error("expandAll \u7684\u5c55\u5f00\u72b6\u6001\u53c2\u6570\u53ea\u63a5\u6536true/false");var t=P(a);if(t){t.isExpandAll=e;var n=t.getOptions(),i=n.tree,l=n.elem.next(),d=i.customName.isParent,r=i.customName.id,o=i.view.showFlexIconIfNotParent;if(e){e=j.getData(a,!0);if(i["async"].enable){var c=!0;if(layui.each(e,function(e,t){if(t[d]&&!t[X])return!(c=!1)}),!c)return void layui.each(j.getData(a),function(e,t){j.expandNode(a,{index:t[Y],expandFlag:!0,inherit:!0})})}var u=!0;if(layui.each(e,function(e,t){if(t[d]&&!t[z])return!(u=!1)}),u)t.updateStatus(null,function(e){(e[d]||o)&&(e[H]=!0,e[r]!==undefined)&&(t.status.expand[e[r]]=!0)}),l.find('tbody tr[data-level!="0"]').removeClass(F),l.find(".layui-table-tree-flexIcon").html(i.view.flexIconOpen),i.view.showIcon&&l.find(".layui-table-tree-nodeIcon:not(.layui-table-tree-iconCustom,.layui-table-tree-iconLeaf)").html(i.view.iconOpen);else{if(t.updateStatus(null,function(e){(e[d]||o)&&(e[H]=!0,e[z]=!0,e[r]!==undefined)&&(t.status.expand[e[r]]=!0)}),n.initSort&&n.initSort.type&&n.autoSort)return j.sort(a);var s,n=B.getTrHtml(a,e),f={trs:E(n.trs.join("")),trs_fixed:E(n.trs_fixed.join("")),trs_fixed_r:E(n.trs_fixed_r.join(""))};layui.each(e,function(e,t){var a=t[Y].split("-").length-1;s={"data-index":t[Y],"lay-data-index":t[Y],"data-level":a},f.trs.eq(e).attr(s),f.trs_fixed.eq(e).attr(s),f.trs_fixed_r.eq(e).attr(s)}),layui.each(["main","fixed-l","fixed-r"],function(e,t){l.find(".layui-table-"+t+" tbody").html(f[["trs","trs_fixed","trs_fixed_r"][e]])}),t.renderTreeTable(l,0,!1)}}else t.updateStatus(null,function(e){(e[d]||o)&&(e[H]=!1,e[r]!==undefined)&&(t.status.expand[e[r]]=!1)}),l.find('.layui-table-box tbody tr[data-level!="0"]').addClass(F),l.find(".layui-table-tree-flexIcon").html(i.view.flexIconClose),i.view.showIcon&&l.find(".layui-table-tree-nodeIcon:not(.layui-table-tree-iconCustom,.layui-table-tree-iconLeaf)").html(i.view.iconClose);j.resize(a)}},t.prototype.renderTreeTable=function(e,t,a){var n=this,i=n.getOptions(),l=i.elem.next(),d=(l.hasClass(h)||l.addClass(h),i.id),r=i.tree||{},o=(r.data,r.view||{}),c=r.customName||{},u=c.isParent,s=(l.attr("lay-filter"),n),f=((t=t||0)||(l.find(".layui-table-body tr:not([data-level])").attr("data-level",t),layui.each(B.cache[d],function(e,t){l.find('.layui-table-main tbody tr[data-level="0"]:eq('+e+")").attr("lay-data-index",t[Y]),l.find('.layui-table-fixed-l tbody tr[data-level="0"]:eq('+e+")").attr("lay-data-index",t[Y]),l.find('.layui-table-fixed-r tbody tr[data-level="0"]:eq('+e+")").attr("lay-data-index",t[Y])})),null),y=c.name,p=o.indent||14;if(layui.each(e.find('td[data-field="'+y+'"]'),function(e,t){var a,n,i=(t=E(t)).closest("tr"),t=t.children(".layui-table-cell");t.hasClass("layui-table-tree-item")||(n=i.attr("lay-data-index"))&&(i=l.find('tr[lay-data-index="'+n+'"]'),(a=s.getNodeDataByIndex(n))[H]&&a[u]&&((f=f||{})[n]=!0),a[b]&&i.find('input[type="checkbox"][name="layTableCheckbox"]').prop("indeterminate",!0),n=t.html(),(t=i.find('td[data-field="'+y+'"]>div.layui-table-cell')).addClass("layui-table-tree-item"),t.html(['
      ',a[H]?o.flexIconOpen:o.flexIconClose,"
      ",o.showIcon?'
      '+(a[c.icon]||o.icon||(a[u]?a[H]?o.iconOpen:o.iconClose:o.iconLeaf)||"")+"
      ":"",n].join("")).find(".layui-table-tree-flexIcon").on("click",function(e){layui.stope(e),U({trElem:i},null,null,null,!0)}))}),!t&&r.view.expandAllDefault&&n.isExpandAll===undefined)return j.expandAll(d,!0);!1!==a&&f?layui.each(f,function(e,t){e=l.find('tr[lay-data-index="'+e+'"]');e.find(".layui-table-tree-flexIcon").html(o.flexIconOpen),U({trElem:e.first()},!0)}):V("renderTreeTable-"+d,function(){i.hasNumberCol&&g(n),x.render(E('.layui-table-tree[lay-id="'+d+'"]'))},0)()},function(a){var e=a.getOptions(),t=e.elem.next(),n=0,i=t.find(".layui-table-main tbody tr"),l=t.find(".layui-table-fixed-l tbody tr"),d=t.find(".layui-table-fixed-r tbody tr");layui.each(a.treeToFlat(B.cache[e.id]),function(e,t){t.LAY_HIDE||(a.getNodeDataByIndex(t[Y]).LAY_NUM=++n,i.eq(e).find(".laytable-cell-numbers").html(n),l.eq(e).find(".laytable-cell-numbers").html(n),d.eq(e).find(".laytable-cell-numbers").html(n))})}),p=(t.prototype.render=function(e){var t=this;t.tableIns=B["reloadData"===e?"reloadData":"reload"](t.tableIns.config.id,E.extend(!0,{},t.config)),t.config=t.tableIns.config},t.prototype.reload=function(e,t,a){var n=this;e=e||{},delete n.haveInit,layui.each(e,function(e,t){"array"===layui.type(t)&&delete n.config[e]}),d(n.getOptions().id,e,a||!0),n.config=E.extend(t,{},n.config,e),n.render(a)},j.reloadData=function(){var e=E.extend(!0,[],arguments);return e[3]="reloadData",j.reload.apply(null,e)},function(e,a,n,i){var l=[];return layui.each(e,function(e,t){"function"===layui.type(a)?a(t):E.extend(t,a),l.push(E.extend({},t)),i||(l=l.concat(p(t[n],a,n,i)))}),l}),o=(t.prototype.updateStatus=function(e,t,a){var n=this.getOptions(),i=n.tree;return e=e||B.cache[n.id],p(e,t,i.customName.children,a)},t.prototype.getTableData=function(){var e=this.getOptions();return B.cache[e.id]},j.updateStatus=function(e,t,a){var e=P(e),n=e.getOptions();return a=a||(n.url?B.cache[n.id]:n.data),e.updateStatus(a,t)},j.sort=function(e){var t=P(e);t&&t.getOptions().autoSort&&(t.initData(),j.renderData(e))},function(n){var t=n.config.id,i=P(t),a=n.data=j.getNodeDataByIndex(t,n.index),l=a[Y],d=(n.dataIndex=l,n.update);n.update=function(){var e=arguments,t=(E.extend(i.getNodeDataByIndex(l),e[0]),d.apply(this,e)),a=n.config.tree.customName.name;return a in e[0]&&n.tr.find('td[data-field="'+a+'"]').children("div.layui-table-cell").removeClass("layui-table-tree-item"),i.renderTreeTable(n.tr,n.tr.attr("data-level"),!1),t},n.del=function(){j.removeNode(t,a)},n.setRowChecked=function(e){j.setRowChecked(t,{index:a,checked:e})}}),u=(j.updateNode=function(e,a,t){var n,i,l,d,r,o=P(e);o&&((d=o.getOptions()).tree,d=(n=d.elem.next()).find('tr[lay-data-index="'+a+'"]'),i=d.attr("data-index"),l=d.attr("data-level"),t)&&(d=o.getNodeDataByIndex(a,!1,t),r=B.getTrHtml(e,[d]),layui.each(["main","fixed-l","fixed-r"],function(e,t){n.find(".layui-table-"+t+' tbody tr[lay-data-index="'+a+'"]').replaceWith(E(r[["trs","trs_fixed","trs_fixed_r"][e]].join("")).attr({"data-index":i,"lay-data-index":a,"data-level":l}))}),o.renderTreeTable(n.find('tr[lay-data-index="'+a+'"]'),l))},j.removeNode=function(e,t){var a,n,i,l,d,r=P(e);r&&(d=(a=r.getOptions()).tree,n=a.elem.next(),i=[],t=r.getNodeDataByIndex("string"===layui.type(t)?t:t[Y],!1,"delete"),l=r.getNodeDataByIndex(t[s]),r.updateCheckStatus(l),l=r.treeToFlat([t],t[d.customName.pid],t[s]),layui.each(l,function(e,t){i.push('tr[lay-data-index="'+t[Y]+'"]')}),n.find(i.join(",")).remove(),d=r.initData(),layui.each(r.treeToFlat(d),function(e,t){t[m]&&t[m]!==t[Y]&&n.find('tr[lay-data-index="'+t[m]+'"]').attr({"data-index":t[Y],"lay-data-index":t[Y]})}),layui.each(B.cache[e],function(e,t){n.find('tr[data-level="0"][lay-data-index="'+t[Y]+'"]').attr("data-index",e)}),a.hasNumberCol&&g(r),j.resize(e))},j.addNodes=function(e,t){var a=P(e);if(a){var n=a.getOptions(),i=n.tree,l=n.elem.next(),d=B.config.checkName,r=(t=t||{}).parentIndex,o=t.index,c=t.data,t=t.focus,u=(r="number"===layui.type(r)?r.toString():r)?a.getNodeDataByIndex(r):null,o="number"===layui.type(o)?o:-1,c=E.extend(!0,[],layui.isArray(c)?c:[c]);layui.each(c,function(e,t){d in t||!u||(t[d]=u[d])}),a.getTableData();if(u){var s=i.customName.isParent,f=i.customName.children;u[s]=!0;var y=(y=u[f])?(p=y.splice(-1===o?y.length:o),u[f]=y.concat(c,p)):u[f]=c,f=(a.updateStatus(y,function(e){(e[s]||i.view.showFlexIconIfNotParent)&&(e[z]=!1)}),a.treeToFlat(y));l.find(f.map(function(e){return'tr[lay-data-index="'+e[Y]+'"]'}).join(",")).remove(),a.initData(),u[z]=!1,u[X]="local",U({trElem:l.find('tr[lay-data-index="'+r+'"]')},!0)}else{var p=B.cache[e].splice(-1===o?B.cache[e].length:o);if(B.cache[e]=B.cache[e].concat(c,p),n.url||(n.page?(y=n.page,n.data.splice.apply(n.data,[y.limit*(y.curr-1),y.limit].concat(B.cache[e]))):n.data=B.cache[e]),a.initData(),l.find(".layui-none").length)return B.renderData(e),c;var x,f=B.getTrHtml(e,c),h={trs:E(f.trs.join("")),trs_fixed:E(f.trs_fixed.join("")),trs_fixed_r:E(f.trs_fixed_r.join(""))},r=(layui.each(c,function(e,t){x={"data-index":t[Y],"lay-data-index":t[Y],"data-level":"0"},h.trs.eq(e).attr(x),h.trs_fixed.eq(e).attr(x),h.trs_fixed_r.eq(e).attr(x)}),parseInt(c[0][Y])-1),y=l.find(L),n=l.find(q),f=l.find(R);-1==r?(y.find('tr[data-level="0"][data-index="0"]').before(h.trs),n.find('tr[data-level="0"][data-index="0"]').before(h.trs_fixed),f.find('tr[data-level="0"][data-index="0"]').before(h.trs_fixed_r)):-1===o?(y.find("tbody").append(h.trs),n.find("tbody").append(h.trs_fixed),f.find("tbody").append(h.trs_fixed_r)):(r=p[0][m],y.find('tr[data-level="0"][data-index="'+r+'"]').before(h.trs),n.find('tr[data-level="0"][data-index="'+r+'"]').before(h.trs_fixed),f.find('tr[data-level="0"][data-index="'+r+'"]').before(h.trs_fixed_r)),layui.each(B.cache[e],function(e,t){l.find('tr[data-level="0"][lay-data-index="'+t[Y]+'"]').attr("data-index",e)}),a.renderTreeTable(l.find(c.map(function(e,t,a){return'tr[lay-data-index="'+e[Y]+'"]'}).join(",")))}return a.updateCheckStatus(u),j.resize(e),t&&l.find(L).find('tr[lay-data-index="'+c[0][Y]+'"]').get(0).scrollIntoViewIfNeeded(),c}},j.checkStatus=function(e,n){var i,t,a,l=P(e);if(l)return l=l.getOptions().tree,i=B.config.checkName,t=j.getData(e,!0).filter(function(e,t,a){return e[i]||n&&e[b]}),a=!0,layui.each("all"===l.data.cascade?B.cache[e]:j.getData(e,!0),function(e,t){if(!t[i])return!(a=!1)}),{data:t,isAll:a}},j.on("sort",function(e){var e=e.config,t=e.elem.next(),e=e.id;t.hasClass(h)&&j.sort(e)}),j.on("row",function(e){e.config.elem.next().hasClass(h)&&o(e)}),j.on("rowDouble",function(e){var t=e.config,a=t.elem.next();t.id;a.hasClass(h)&&(o(e),(t.tree||{}).view.dblClickExpand)&&U({trElem:e.tr.first()},null,null,null,!0)}),j.on("rowContextmenu",function(e){var t=e.config,a=t.elem.next();t.id;a.hasClass(h)&&o(e)}),j.on("tool",function(e){var t=e.config,a=t.elem.next();t.id;a.hasClass(h)&&o(e)}),j.on("edit",function(e){var t=e.config,a=t.elem.next();t.id;a.hasClass(h)&&(o(e),e.field===t.tree.customName.name)&&((a={})[e.field]=e.value,e.update(a))}),j.on("radio",function(e){var t=e.config,a=t.elem.next(),t=t.id;a.hasClass(h)&&(a=P(t),o(e),u.call(a,e.tr,e.checked))}),t.prototype.setRowCheckedClass=function(e,t){var a=this.getOptions(),n=(e.data("index"),a.elem.next());e[t?"addClass":"removeClass"](l),e.each(function(){var e=E(this).data("index");n.find('.layui-table-fixed-r tbody tr[data-index="'+e+'"]')[t?"addClass":"removeClass"](l)})},t.prototype.updateCheckStatus=function(e,t){var a,n,i,l,d,r,o,c=this,u=c.getOptions();return!!u.hasChecboxCol&&(a=u.tree,n=u.id,i=u.elem.next(),l=B.config.checkName,"all"!==(d=a.data.cascade)&&"parent"!==d||!e||(d=c.updateParentCheckStatus(e,"boolean"===layui.type(t)?t:null),layui.each(d,function(e,t){var a=i.find('tr[lay-data-index="'+t[Y]+'"] input[name="layTableCheckbox"]:not(:disabled)'),n=t[l];c.setRowCheckedClass(a.closest("tr"),n),x.render(a.prop({checked:n,indeterminate:t[b]}))})),o=!(r=!0),e=(e="all"===a.data.cascade?B.cache[n]:j.getData(n,!0)).filter(function(e){return!e[u.disabledName]}),layui.each(e,function(e,t){if((t[l]||t[b])&&(o=!0),t[l]||(r=!1),o&&!r)return!0}),o=o&&!r,x.render(i.find('input[name="layTableCheckbox"][lay-filter="layTableAllChoose"]').prop({checked:r,indeterminate:o})),r)},t.prototype.updateParentCheckStatus=function(a,n){var i,e=this.getOptions(),t=e.tree,e=e.id,l=B.config.checkName,t=t.customName.children,d=[];return!(a[b]=!1)===n?a[t].length?layui.each(a[t],function(e,t){if(!t[l])return n=!1,a[b]=!0}):n=!1:!1===n?layui.each(a[t],function(e,t){if(t[l]||t[b])return a[b]=!0}):(n=!1,i=0,layui.each(a[t],function(e,t){t[l]&&i++}),n=a[t].length?a[t].length===i:a[l],a[b]=!n&&0')),n=(e.tree(a),i.elem=p(i.elem));if(n[0]){if(e.key=i.id||e.index,e.elem=a,e.elemNone=p('
      '+i.text.none+"
      "),n.html(e.elem),0==e.elem.find(".layui-tree-set").length)return e.elem.append(e.elemNone);i.showCheckbox&&e.renderForm("checkbox"),e.elem.find(".layui-tree-set").each(function(){var e=p(this);e.parent(".layui-tree-pack")[0]||e.addClass("layui-tree-setHide"),!e.next()[0]&&e.parents(".layui-tree-pack").eq(1).hasClass("layui-tree-lineExtend")&&e.addClass(T),e.next()[0]||e.parents(".layui-tree-set").eq(0).next()[0]||e.addClass(T)}),e.events()}},l.prototype.renderForm=function(e){i.render(e,"LAY-tree-"+this.index)},l.prototype.tree=function(r,e){var d=this,s=d.config,o=s.customName,e=e||s.data;layui.each(e,function(e,i){var a,n,t=i[o.children]&&0"),c=p(['
      ','
      ','
      ',s.showLine?t?'':'':'',s.showCheckbox?'':"",s.isJump&&i.href?''+(i[o.title]||i.label||s.text.defaultNodeName)+"":''+(i[o.title]||i.label||s.text.defaultNodeName)+"","
      ",s.edit?(a={add:'',update:'',del:''},n=['
      '],!0===s.edit&&(s.edit=["update","del"]),"object"==typeof s.edit?(layui.each(s.edit,function(e,i){n.push(a[i]||"")}),n.join("")+"
      "):void 0):"","
      "].join(""));t&&(c.append(l),d.tree(l,i[o.children])),r.append(c),c.prev("."+k)[0]&&c.prev().children(".layui-tree-pack").addClass("layui-tree-showLine"),t||c.parent(".layui-tree-pack").addClass("layui-tree-lineExtend"),d.spread(c,i),s.showCheckbox&&(i.checked&&d.checkids.push(i[o.id]),d.checkClick(c,i)),s.edit&&d.operate(c,i)})},l.prototype.spread=function(n,t){var l=this,c=l.config,e=n.children("."+b),i=e.children("."+g),a=i.find('input[same="layuiTreeCheck"]'),r=e.find("."+C),e=e.find("."+w),d=c.onlyIconControl?r:i,s="";d.on("click",function(e){var i=n.children("."+N),a=(d.children(".layui-icon")[0]?d:d.find(".layui-tree-icon")).children(".layui-icon");i[0]?n.hasClass(F)?(n.removeClass(F),i.slideUp(200),a.removeClass(x).addClass(v),l.updateFieldValue(t,"spread",!1)):(n.addClass(F),i.slideDown(200),a.addClass(x).removeClass(v),l.updateFieldValue(t,"spread",!0),c.accordion&&((i=n.siblings("."+k)).removeClass(F),i.children("."+N).slideUp(200),i.find(".layui-tree-icon").children(".layui-icon").removeClass(x).addClass(v))):s="normal"}),e.on("click",function(){p(this).hasClass(u)||(s=n.hasClass(F)?c.onlyIconControl?"open":"close":c.onlyIconControl?"close":"open",a[0]&&l.updateFieldValue(t,"checked",a.prop("checked")),c.click&&c.click({elem:n,state:s,data:t}))})},l.prototype.updateFieldValue=function(e,i,a){i in e&&(e[i]=a)},l.prototype.setCheckbox=function(e,i,a){var t,n=this,l=n.config.customName,c=a.prop("checked");a.prop("disabled")||("object"!=typeof i[l.children]&&!e.find("."+N)[0]||e.find("."+N).find('input[same="layuiTreeCheck"]').each(function(e){this.disabled||((e=i[l.children][e])&&n.updateFieldValue(e,"checked",c),n.updateFieldValue(this,"checked",c))}),(t=function(e){var i,a,n;e.parents("."+k)[0]&&(a=(e=e.parent("."+N)).parent(),n=e.prev().find('input[same="layuiTreeCheck"]'),c?n.prop("checked",c):(e.find('input[same="layuiTreeCheck"]').each(function(){this.checked&&(i=!0)}),i||n.prop("checked",!1)),t(a))})(e),n.renderForm("checkbox"))},l.prototype.checkClick=function(a,n){var t=this,l=t.config;a.children("."+b).children("."+g).on("click",'input[same="layuiTreeCheck"]+',function(e){layui.stope(e);var e=p(this).prev(),i=e.prop("checked");e.prop("disabled")||(t.setCheckbox(a,n,e),t.updateFieldValue(n,"checked",i),l.oncheck&&l.oncheck({elem:a,checked:i,data:n}))})},l.prototype.operate=function(r,d){var s=this,o=s.config,u=o.customName,e=r.children("."+b),h=e.children("."+g);e.children(".layui-tree-btnGroup").on("click",".layui-icon",function(e){layui.stope(e);var i,e=p(this).data("type"),n=r.children("."+N),t={data:d,type:e,elem:r};if("add"==e){n[0]||(o.showLine?(h.find("."+C).addClass("layui-tree-icon"),h.find("."+C).children(".layui-icon").addClass(v).removeClass("layui-icon-file")):h.find(".layui-tree-iconArrow").removeClass(m),r.append('
      '));var a,l=o.operate&&o.operate(t),c={};if(c[u.title]=o.text.defaultNodeName,c[u.id]=l,s.tree(r.children("."+N),[c]),o.showLine&&(n[0]?(n.hasClass(S)||n.addClass(S),r.find("."+N).each(function(){p(this).children("."+k).last().addClass(T)}),(n.children("."+k).last().prev().hasClass(T)?n.children("."+k).last().prev():n.children("."+k).last()).removeClass(T),!r.parent("."+N)[0]&&r.next()[0]&&n.children("."+k).last().removeClass(T)):(l=r.siblings("."+k),a=1,c=r.parent("."+N),layui.each(l,function(e,i){p(i).children("."+N)[0]||(a=0)}),(1==a?(l.children("."+N).addClass(L),l.children("."+N).children("."+k).removeClass(T),r.children("."+N).addClass(L),c.removeClass(S),c.children("."+k).last().children("."+N).children("."+k).last()):r.children("."+N).children("."+k)).addClass(T))),!o.showCheckbox)return;h.find('input[same="layuiTreeCheck"]')[0].checked&&(r.children("."+N).children("."+k).last().find('input[same="layuiTreeCheck"]')[0].checked=!0),s.renderForm("checkbox")}else"update"==e?(l=h.children("."+w).html(),h.children("."+w).html(""),h.append(''),h.children(".layui-tree-editInput").val(f.unescape(l)).focus(),i=function(e){var i=e.val().trim()||o.text.defaultNodeName;e.remove(),h.children("."+w).html(i),t.data[u.title]=i,o.operate&&o.operate(t)},h.children(".layui-tree-editInput").blur(function(){i(p(this))}),h.children(".layui-tree-editInput").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),i(p(this)))})):y.confirm('\u786e\u8ba4\u5220\u9664\u8be5\u8282\u70b9 "'+(d[u.title]||"")+'" \u5417\uff1f',function(e){var l,a,i;o.operate&&o.operate(t),t.status="remove",y.close(e),r.prev("."+k)[0]||r.next("."+k)[0]||r.parent("."+N)[0]?(r.siblings("."+k).children("."+b)[0]?(o.showCheckbox&&(l=function(e){var i,a,n,t;e.parents("."+k)[0]&&(i=e.siblings("."+k).children("."+b),a=(e=e.parent("."+N).prev()).find('input[same="layuiTreeCheck"]')[0],n=1,(t=0)==a.checked)&&(i.each(function(e,i){i=p(i).find('input[same="layuiTreeCheck"]')[0];0!=i.checked||i.disabled||(n=0),i.disabled||(t=1)}),1==n)&&1==t&&(a.checked=!0,s.renderForm("checkbox"),l(e.parent("."+k)))})(r),o.showLine&&(e=r.siblings("."+k),a=1,i=r.parent("."+N),layui.each(e,function(e,i){p(i).children("."+N)[0]||(a=0)}),1==a?(n[0]||(i.removeClass(S),e.children("."+N).addClass(L),e.children("."+N).children("."+k).removeClass(T)),(r.next()[0]?i.children("."+k).last():r.prev()).children("."+N).children("."+k).last().addClass(T),r.next()[0]||r.parents("."+k)[1]||r.parents("."+k).eq(0).next()[0]||r.prev("."+k).addClass(T)):!r.next()[0]&&r.hasClass(T)&&r.prev().addClass(T))):(e=r.parent("."+N).prev(),o.showLine?(e.find("."+C).removeClass("layui-tree-icon"),e.find("."+C).children(".layui-icon").removeClass(x).addClass("layui-icon-file"),(i=e.parents("."+N).eq(0)).addClass(S),i.children("."+k).each(function(){p(this).children("."+N).children("."+k).last().addClass(T)})):e.find(".layui-tree-iconArrow").addClass(m),r.parents("."+k).eq(0).removeClass(F),r.parent("."+N).remove()),r.remove()):(r.remove(),s.elem.append(s.elemNone))})})},l.prototype.events=function(){var i=this,t=i.config;i.elem.find(".layui-tree-checkedFirst");i.setChecked(i.checkids),i.elem.find(".layui-tree-search").on("keyup",function(){var e=p(this),a=e.val(),e=e.nextAll(),n=[];e.find("."+w).each(function(){var i,e=p(this).parents("."+b);-1!=p(this).html().indexOf(a)&&(n.push(p(this).parent()),(i=function(e){e.addClass("layui-tree-searchShow"),e.parent("."+N)[0]&&i(e.parent("."+N).parent("."+k))})(e.parent("."+k)))}),e.find("."+b).each(function(){var e=p(this).parent("."+k);e.hasClass("layui-tree-searchShow")||e.addClass(m)}),0==e.find(".layui-tree-searchShow").length&&i.elem.append(i.elemNone),t.onsearch&&t.onsearch({elem:n})}),i.elem.find(".layui-tree-search").on("keydown",function(){p(this).nextAll().find("."+b).each(function(){p(this).parent("."+k).removeClass("layui-tree-searchShow "+m)}),p(".layui-tree-emptyText")[0]&&p(".layui-tree-emptyText").remove()})},l.prototype.getChecked=function(){var t=this,e=t.config,l=e.customName,i=[],a=[],c=(t.elem.find(".layui-form-checked").each(function(){i.push(p(this).prev()[0].value)}),function(e,n){layui.each(e,function(e,a){layui.each(i,function(e,i){if(a[l.id]==i)return t.updateFieldValue(a,"checked",!0),delete(i=p.extend({},a))[l.children],n.push(i),a[l.children]&&(i[l.children]=[],c(a[l.children],i[l.children])),!0})})});return c(p.extend({},e.data),a),a},l.prototype.setChecked=function(l){this.config;this.elem.find("."+k).each(function(e,i){var a=p(this).data("id"),n=p(i).children("."+b).find('input[same="layuiTreeCheck"]'),t=n.next();if("number"==typeof l){if(a.toString()==l.toString())return n[0].checked||t.click(),!1}else"object"==typeof l&&layui.each(l,function(e,i){if(i.toString()==a.toString()&&!n[0].checked)return t.click(),!0})})},n.that={},n.config={},t.reload=function(e,i){e=n.that[e];return e.reload(i),n.call(e)},t.getChecked=function(e){return n.that[e].getChecked()},t.setChecked=function(e,i){return n.that[e].setChecked(i)},t.render=function(e){e=new l(e);return n.call(e)},e(a,t)});layui.define(["laytpl","form"],function(e){"use strict";var s=layui.$,n=layui.laytpl,t=layui.form,a="transfer",i={config:{},index:layui[a]?layui[a].index+1e4:0,set:function(e){var t=this;return t.config=s.extend({},t.config,e),t},on:function(e,t){return layui.onevent.call(this,a,e,t)}},l=function(){var t=this,e=t.config,a=e.id||t.index;return l.that[a]=t,{config:l.config[a]=e,reload:function(e){t.reload.call(t,e)},getData:function(){return t.getData.call(t)}}},d="layui-hide",h="layui-btn-disabled",r="layui-none",c="layui-transfer-box",u="layui-transfer-header",o="layui-transfer-search",f="layui-transfer-data",y=function(e){return['
      ','
      ','","
      ","{{# if(d.data.showSearch){ }}",'","{{# } }}",'
        ',"
        "].join("")},p=['
        ',y({index:0,checkAllName:"layTransferLeftCheckAll"}),'
        ','",'","
        ",y({index:1,checkAllName:"layTransferRightCheckAll"}),"
        "].join(""),v=function(e){var t=this;t.index=++i.index,t.config=s.extend({},t.config,i.config,e),t.render()};v.prototype.config={title:["\u5217\u8868\u4e00","\u5217\u8868\u4e8c"],width:200,height:360,data:[],value:[],showSearch:!1,id:"",text:{none:"\u65e0\u6570\u636e",searchNone:"\u65e0\u5339\u914d\u6570\u636e"}},v.prototype.reload=function(e){var t=this;t.config=s.extend({},t.config,e),t.render()},v.prototype.render=function(){var e=this,t=e.config,a=e.elem=s(n(p,{open:"{{",close:"}}"}).render({data:t,index:e.index})),i=t.elem=s(t.elem);i[0]&&(t.data=t.data||[],t.value=t.value||[],t.id="id"in t?t.id:elem.attr("id")||e.index,e.key=t.id,i.html(e.elem),e.layBox=e.elem.find("."+c),e.layHeader=e.elem.find("."+u),e.laySearch=e.elem.find("."+o),e.layData=a.find("."+f),e.layBtn=a.find(".layui-transfer-active .layui-btn"),e.layBox.css({width:t.width,height:t.height}),e.layData.css({height:(i=t.height-e.layHeader.outerHeight(),t.showSearch&&(i-=e.laySearch.outerHeight()),i-2)}),e.renderData(),e.events())},v.prototype.renderData=function(){var e=this,t=e.config,l=[{checkName:"layTransferLeftCheck",views:[]},{checkName:"layTransferRightCheck",views:[]}];e.parseData(function(a){var i=a.selected?1:0,n=["
      • ",'',"
      • "].join("");i?layui.each(t.value,function(e,t){t==a.value&&a.selected&&(l[i].views[e]=n)}):l[i].views.push(n),delete a.selected}),e.layData.eq(0).html(l[0].views.join("")),e.layData.eq(1).html(l[1].views.join("")),e.renderCheckBtn()},v.prototype.renderForm=function(e){t.render(e,"LAY-transfer-"+this.index)},v.prototype.renderCheckBtn=function(r){var c=this,o=c.config;r=r||{},c.layBox.each(function(e){var t=s(this),a=t.find("."+f),t=t.find("."+u).find('input[type="checkbox"]'),i=a.find('input[type="checkbox"]'),n=0,l=!1;i.each(function(){var e=s(this).data("hide");(this.checked||this.disabled||e)&&n++,this.checked&&!e&&(l=!0)}),t.prop("checked",l&&n===i.length),c.layBtn.eq(e)[l?"removeClass":"addClass"](h),r.stopNone||(i=a.children("li:not(."+d+")").length,c.noneView(a,i?"":o.text.none))}),c.renderForm("checkbox")},v.prototype.noneView=function(e,t){var a=s('

        '+(t||"")+"

        ");e.find("."+r)[0]&&e.find("."+r).remove(),t.replace(/\s/g,"")&&e.append(a)},v.prototype.setValue=function(){var e=this.config,t=[];return this.layBox.eq(1).find("."+f+' input[type="checkbox"]').each(function(){s(this).data("hide")||t.push(this.value)}),e.value=t,this},v.prototype.parseData=function(t){var i=this.config,n=[];return layui.each(i.data,function(e,a){a=("function"==typeof i.parseData?i.parseData(a):a)||a,n.push(a=s.extend({},a)),layui.each(i.value,function(e,t){t==a.value&&(a.selected=!0)}),t&&t(a)}),i.data=n,this},v.prototype.getData=function(e){var t=this.config,i=[];return this.setValue(),layui.each(e||t.value,function(e,a){layui.each(t.data,function(e,t){delete t.selected,a==t.value&&i.push(t)})}),i},v.prototype.transfer=function(e,t){var a,i=this,n=i.config,l=i.layBox.eq(e),r=[],t=(t?((a=(t=t).find('input[type="checkbox"]'))[0].checked=!1,l.siblings("."+c).find("."+f).append(t.clone()),t.remove(),r.push(a[0].value),i.setValue()):l.each(function(e){s(this).find("."+f).children("li").each(function(){var e=s(this),t=e.find('input[type="checkbox"]'),a=t.data("hide");t[0].checked&&!a&&(t[0].checked=!1,l.siblings("."+c).find("."+f).append(e.clone()),e.remove(),r.push(t[0].value)),i.setValue()})}),i.renderCheckBtn(),l.siblings("."+c).find("."+o+" input"));""!==t.val()&&t.trigger("keyup"),n.onchange&&n.onchange(i.getData(r),e)},v.prototype.events=function(){var n=this,l=n.config;n.elem.on("click",'input[lay-filter="layTransferCheckbox"]+',function(){var e=s(this).prev(),t=e[0].checked,a=e.parents("."+c).eq(0).find("."+f);e[0].disabled||("all"===e.attr("lay-type")&&a.find('input[type="checkbox"]').each(function(){this.disabled||(this.checked=t)}),setTimeout(function(){n.renderCheckBtn({stopNone:!0})},0))}),n.elem.on("dblclick","."+f+">li",function(e){var t=s(this),a=t.children('input[type="checkbox"]'),i=t.parent().parent();a[0].disabled||n.transfer(i.data("index"),t)}),n.layBtn.on("click",function(){var e=s(this),t=e.data("index");e.hasClass(h)||n.transfer(t)}),n.laySearch.find("input").on("keyup",function(){var i=this.value,e=s(this).parents("."+o).eq(0).siblings("."+f),t=e.children("li"),t=(t.each(function(){var e=s(this),t=e.find('input[type="checkbox"]'),a=t[0].title,a=("cs"!==l.showSearch&&(a=a.toLowerCase(),i=i.toLowerCase()),-1!==a.indexOf(i));e[a?"removeClass":"addClass"](d),t.data("hide",!a)}),n.renderCheckBtn(),t.length===e.children("li."+d).length);n.noneView(e,t?l.text.searchNone:"")})},l.that={},l.config={},i.reload=function(e,t){e=l.that[e];return e.reload(t),l.call(e)},i.getData=function(e){return l.that[e].getData()},i.render=function(e){e=new v(e);return l.call(e)},e(a,i)});layui.define(["jquery","lay"],function(e){"use strict";var a=layui.$,l=layui.lay,t=(layui.hint(),layui.device(),{config:{},set:function(e){var i=this;return i.config=a.extend({},i.config,e),i},on:function(e,i){return layui.onevent.call(this,d,e,i)}}),d="carousel",r="layui-this",s="layui-carousel-left",u="layui-carousel-right",c="layui-carousel-prev",h="layui-carousel-next",o="layui-carousel-arrow",m="layui-carousel-ind",i=function(e){var i=this;i.config=a.extend({},i.config,t.config,e),i.render()};i.prototype.config={width:"600px",height:"280px",full:!1,arrow:"hover",indicator:"inside",autoplay:!0,interval:3e3,anim:"",trigger:"click",index:0},i.prototype.render=function(){var e=this,i=e.config,n=a(i.elem);if(1*[carousel-item]>*"),i.index<0&&(i.index=0),i.index>=e.elemItem.length&&(i.index=e.elemItem.length-1),i.interval<800&&(i.interval=800),i.full?i.elem.css({position:"fixed",width:"100%",height:"100%",zIndex:9999}):i.elem.css({width:i.width,height:i.height}),i.elem.attr("lay-anim",i.anim),e.elemItem.eq(i.index).addClass(r),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},i.prototype.reload=function(e){var i=this;clearInterval(i.timer),i.config=a.extend({},i.config,e),i.render()},i.prototype.prevIndex=function(){var e=this.config.index-1;return e=e<0?this.elemItem.length-1:e},i.prototype.nextIndex=function(){var e=this.config.index+1;return e=e>=this.elemItem.length?0:e},i.prototype.addIndex=function(e){var i=this.config;i.index=i.index+(e=e||1),i.index>=this.elemItem.length&&(i.index=0)},i.prototype.subIndex=function(e){var i=this.config;i.index=i.index-(e=e||1),i.index<0&&(i.index=this.elemItem.length-1)},i.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(clearInterval(e.timer),e.timer=setInterval(function(){e.slide()},i.interval))},i.prototype.arrow=function(){var i=this,e=i.config,n=a(['",'"].join(""));e.elem.attr("lay-arrow",e.arrow),e.elem.find("."+o)[0]&&e.elem.find("."+o).remove(),e.elem.append(n),n.on("click",function(){var e=a(this).attr("lay-type");i.slide(e)})},i.prototype["goto"]=function(e){var i=this,n=i.config;e>n.index?i.slide("add",e-n.index):e
          ',(i=[],layui.each(e.elemItem,function(e){i.push("")}),i.join("")),"
        "].join(""));n.elem.attr("lay-indicator",n.indicator),n.elem.find("."+m)[0]&&n.elem.find("."+m).remove(),n.elem.append(t),"updown"===n.anim&&t.css("margin-top",-t.height()/2),t.find("li").on("hover"===n.trigger?"mouseover":n.trigger,function(){e["goto"](a(this).index())})},i.prototype.slide=function(e,i){var n=this,t=n.elemItem,a=n.config,o=a.index,l=a.elem.attr("lay-filter");n.haveSlide||("sub"===e?(n.subIndex(i),t.eq(a.index).addClass(c),setTimeout(function(){t.eq(o).addClass(u),t.eq(a.index).addClass(u)},50)):(n.addIndex(i),t.eq(a.index).addClass(h),setTimeout(function(){t.eq(o).addClass(s),t.eq(a.index).addClass(s)},50)),setTimeout(function(){t.removeClass(r+" "+c+" "+h+" "+s+" "+u),t.eq(a.index).addClass(r),n.haveSlide=!1},350),n.elemInd.find("li").eq(a.index).addClass(r).siblings().removeClass(r),n.haveSlide=!0,e={index:a.index,prevIndex:o,item:t.eq(a.index)},"function"==typeof a.change&&a.change(e),layui.event.call(this,d,"change("+l+")",e))},i.prototype.events=function(){var t,a,o=this,e=o.config;e.elem.data("haveEvents")||(e.elem.on("mouseenter touchstart",function(){"always"!==o.config.autoplay&&clearInterval(o.timer)}).on("mouseleave touchend",function(){"always"!==o.config.autoplay&&o.autoplay()}),t=e.elem,a="updown"===e.anim,l.touchSwipe(t,{onTouchEnd:function(e,i){var n=Date.now()-i.timeStart,i=a?i.distanceY:i.distanceX;(.25t[a?"height":"width"]()/3)&&o.slide(0a.length&&(a.value=a.length),parseInt(a.value)===a.value||a.half||(a.value=Math.ceil(a.value)-a.value<.5?Math.ceil(a.value):Math.floor(a.value)),'
          "),n=1;n<=a.length;n++){var o='
        • ";a.half&&parseInt(a.value)!==a.value&&n==Math.ceil(a.value)?i=i+'
        • ":i+=o}i+="
        "+(a.text?''+a.value+"\u661f":"")+"";var l=a.elem,s=l.next(".layui-rate");s[0]&&s.remove(),e.elemTemp=u(i),a.span=e.elemTemp.next("span"),a.setText&&a.setText(a.value),l.html(e.elemTemp),l.addClass("layui-inline"),a.readonly||e.action()},a.prototype.setvalue=function(e){this.config.value=e,this.render()},a.prototype.action=function(){var n=this.config,t=this.elemTemp,i=t.find("i").width(),l=t.children("li");l.each(function(e){var a=e+1,l=u(this);l.on("click",function(e){n.value=a,n.half&&e.pageX-u(this).offset().left<=i/2&&(n.value=n.value-.5),n.text&&t.next("span").text(n.value+"\u661f"),n.choose&&n.choose(n.value),n.setText&&n.setText(n.value)}),l.on("mousemove",function(e){t.find("i").each(function(){u(this).addClass(h).removeClass(s)}),t.find("i:lt("+a+")").each(function(){u(this).addClass(f).removeClass(v)}),n.half&&e.pageX-u(this).offset().left<=i/2&&l.children("i").addClass(o).removeClass(f)}),l.on("mouseleave",function(){t.find("i").each(function(){u(this).addClass(h).removeClass(s)}),t.find("i:lt("+Math.floor(n.value)+")").each(function(){u(this).addClass(f).removeClass(v)}),n.half&&parseInt(n.value)!==n.value&&t.children("li:eq("+Math.floor(n.value)+")").children("i").addClass(o).removeClass("layui-icon-rate-solid layui-icon-rate")})}),r.touchSwipe(t,{onTouchMove:function(e,a){var i;Date.now()-a.timeStart<=200||(a=e.touches[0].pageX,e=t.width()/n.length,a=(a-t.offset().left)/e,(i=(i=(e=a%1)<=.5&&n.half?.5+(a-e):Math.ceil(a))>n.length?n.length:i)<0&&(i=0),l.each(function(e){var a=u(this).children("i"),l=Math.ceil(i)-e==1,t=Math.ceil(i)>e,e=i-e==.5;t?(a.addClass(f).removeClass(v),n.half&&e&&a.addClass(o).removeClass(f)):a.addClass(h).removeClass(s),a.toggleClass("layui-rate-hover",l)}),n.value=i,n.setText&&n.setText(n.value))},onTouchEnd:function(e,a){Date.now()-a.timeStart<=200||(t.find("i").removeClass("layui-rate-hover"),n.choose&&n.choose(n.value),n.setText&&n.setText(n.value))}})},a.prototype.events=function(){},c.render=function(e){e=new a(e);return function(){var a=this;return{setvalue:function(e){a.setvalue.call(a,e)},config:a.config}}.call(e)},e(l,c)});layui.define("jquery",function(l){"use strict";var g=layui.$,e=function(l){};e.prototype.load=function(l){var t,i,o,n,e,r,a,c,m,s,u,f,y,d=this,p=0,h=g((l=l||{}).elem);if(h[0])return e=g(l.scrollElem||document),r=l.mb||50,a=!("isAuto"in l)||l.isAuto,c=l.end||"\u6ca1\u6709\u66f4\u591a\u4e86",m=l.scrollElem&&l.scrollElem!==document,u=g('"),h.find(".layui-flow-more")[0]||h.append(u),f=function(l,e){l=g(l),u.before(l),(e=0==e||null)?u.html(c):u.find("a").html(s),i=e,t=null,o&&o()},(y=function(){t=!0,u.find("a").html(''),"function"==typeof l.done&&l.done(++p,f)})(),u.find("a").on("click",function(){g(this);i||t||y()}),l.isLazyimg&&(o=d.lazyimg({elem:l.elem+" img",scrollElem:l.scrollElem})),a&&e.on("scroll",function(){var e=g(this),o=e.scrollTop();n&&clearTimeout(n),!i&&h.width()&&(n=setTimeout(function(){var l=(m?e:g(window)).height();(m?e.prop("scrollHeight"):document.documentElement.scrollHeight)-o-l<=r&&(t||y())},100))}),d},e.prototype.lazyimg=function(l){var e,c=this,m=0,s=g((l=l||{}).scrollElem||document),u=l.elem||"img",f=l.scrollElem&&l.scrollElem!==document,y=function(e,l){var o,t=s.scrollTop(),l=t+l,i=f?e.offset().top-s.offset().top+t:e.offset().top;t<=i&&i<=l&&e.attr("lay-src")&&(o=e.attr("lay-src"),layui.img(o,function(){var l=c.lazyimg.elem.eq(m);e.attr("src",o).removeAttr("lay-src"),l[0]&&n(l),m++},function(){c.lazyimg.elem.eq(m);e.removeAttr("lay-src")}))},n=function(l,e){var o=(f?e||s:g(window)).height(),t=s.scrollTop(),i=t+o;if(c.lazyimg.elem=g(u),l)y(l,o);else for(var n=0;n"),preview:"Preview"},wordWrap:!0,lang:"text",highlighter:!1,langMarker:!1},W=layui.code?layui.code.index+1e4:0,R=function(e){return String(e).replace(/\s+$/,"").replace(/^\n|\n$/,"")};e("code",function(l,e){var o,i,t,a,n,d,c,s,r,u,y,p,E,f,h,v,m,L,_,M,C,g={config:l=x.extend(!0,{},T,l),reload:function(e){layui.code(this.updateOptions(e))},updateOptions:function(e){return delete(e=e||{}).elem,x.extend(!0,l,e)},reloadCode:function(e){layui.code(this.updateOptions(e),"reloadCode")}},w=x(l.elem);return 1',l.ln?['
        ',D.digit(t+1)+".","
        "].join(""):"",'
        ',e||" ","
        ",""].join("")})}},a=l.code,n=function(e){return"function"==typeof l.codeParse?l.codeParse(e,l):e},"reloadCode"===e?o.children(".layui-code-wrap").html(w(n(a)).html):(d=layui.code.index=++W,o.attr("lay-code-index",d),(M=A.CDDE_DATA_CLASS in o.data())&&o.attr("class",o.data(A.CDDE_DATA_CLASS)||""),M||o.data(A.CDDE_DATA_CLASS,o.attr("class")),c={copy:{className:"file-b",title:["\u590d\u5236\u4ee3\u7801"],event:function(e){var t=D.unescape(n(l.code));lay.clipboard.writeText({text:t,done:function(){N.msg("\u5df2\u590d\u5236",{icon:1})},error:function(){N.msg("\u590d\u5236\u5931\u8d25",{icon:2})}}),"function"==typeof l.onCopy&&l.onCopy(t)}}},function b(){var e=o.parent("."+A.ELEM_PREVIEW),t=e.children("."+A.ELEM_TAB),a=e.children("."+A.ELEM_ITEM+"-preview");return t.remove(),a.remove(),e[0]&&o.unwrap(),b}(),l.preview&&(M="LAY-CODE-DF-"+d,f=l.layout||["code","preview"],s="iframe"===l.preview,E=x('
        '),C=x('
        '),r=x('
        '),_=x('
        '),u=x('
        '),l.id&&E.attr("id",l.id),E.addClass(l.className),C.attr("lay-filter",M),layui.each(f,function(e,t){var a=x('
      • ');0===e&&a.addClass("layui-this"),a.html(l.text[t]),r.append(a)}),x.extend(c,{full:{className:"screen-full",title:["\u6700\u5927\u5316\u663e\u793a","\u8fd8\u539f\u663e\u793a"],event:function(e){var e=e.elem,t=e.closest("."+A.ELEM_PREVIEW),a="layui-icon-"+this.className,i="layui-icon-screen-restore",l=this.title,o=x("html,body"),n="layui-scrollbar-hide";e.hasClass(a)?(t.addClass(A.ELEM_FULL),e.removeClass(a).addClass(i),e.attr("title",l[1]),o.addClass(n)):(t.removeClass(A.ELEM_FULL),e.removeClass(i).addClass(a),e.attr("title",l[0]),o.removeClass(n))}},window:{className:"release",title:["\u5728\u65b0\u7a97\u53e3\u9884\u89c8"],event:function(e){D.openWin({content:n(l.code)})}}}),l.copy&&("array"===layui.type(l.tools)?-1===l.tools.indexOf("copy")&&l.tools.unshift("copy"):l.tools=["copy"]),u.on("click",">i",function(){var e=x(this),t=e.data("type"),e={elem:e,type:t,options:l,rawCode:l.code,finalCode:D.unescape(n(l.code))};c[t]&&"function"==typeof c[t].event&&c[t].event(e),"function"==typeof l.toolsEvent&&l.toolsEvent(e)}),l.addTools&&l.tools&&(l.tools=[].concat(l.tools,l.addTools)),layui.each(l.tools,function(e,t){var a="object"==typeof t,i=a?t:c[t]||{className:t,title:[t]},l=i.className||i.type,o=i.title||[""],a=a?i.type||l:t;a&&(c[a]||((t={})[a]=i,x.extend(c,t)),u.append(''))}),o.addClass(A.ELEM_ITEM).wrap(E),C.append(r),l.tools&&C.append(u),o.before(C),s&&_.html(''),y=function(e){var t=e.children("iframe")[0];s&&t?t.srcdoc=n(l.code):e.html(l.code),setTimeout(function(){"function"==typeof l.done&&l.done({container:e,options:l,render:function(){I.render(e.find(".layui-form")),S.render()}})},3)},"preview"===f[0]?(_.addClass(A.ELEM_SHOW),o.before(_),y(_)):o.addClass(A.ELEM_SHOW).after(_),l.previewStyle=[l.style,l.previewStyle].join(""),_.attr("style",l.previewStyle),S.on("tab("+M+")",function(e){var t=x(this),a=x(e.elem).closest("."+A.ELEM_PREVIEW).find("."+A.ELEM_ITEM),e=a.eq(e.index);a.removeClass(A.ELEM_SHOW),e.addClass(A.ELEM_SHOW),"preview"===t.attr("lay-id")&&y(e),L()})),p=x(''),o.addClass((E=["layui-code-view layui-border-box"],l.wordWrap||E.push("layui-code-nowrap"),E.join(" "))),(C=l.theme||l.skin)&&(o.removeClass("layui-code-theme-dark layui-code-theme-light"),o.addClass("layui-code-theme-"+C)),l.highlighter&&o.addClass([l.highlighter,"language-"+l.lang,"layui-code-hl"].join(" ")),f=w(l.encode?D.escape(n(a)):a),h=f.lines,o.html(p.html(f.html)),l.ln&&o.append('
        '),l.height&&p.css("max-height",l.height),l.codeStyle=[l.style,l.codeStyle].join(""),l.codeStyle&&p.attr("style",function(e,t){return(t||"")+l.codeStyle}),v=[{selector:">.layui-code-wrap>.layui-code-line{}",setValue:function(e,t){e.style["padding-left"]=t+"px"}},{selector:">.layui-code-wrap>.layui-code-line>.layui-code-line-number{}",setValue:function(e,t){e.style.width=t+"px"}},{selector:">.layui-code-ln-side{}",setValue:function(e,t){e.style.width=t+"px"}}],m=lay.style({target:o[0],id:"DF-code-"+d,text:x.map(x.map(v,function(e){return e.selector}),function(e,t){return['.layui-code-view[lay-code-index="'+d+'"]',e].join(" ")}).join("")}),L=function b(){var e,i;return l.ln&&(e=Math.floor(h.length/100),i=p.children("."+A.ELEM_LINE).last().children("."+A.ELEM_LINE_NUM).outerWidth(),o.addClass(A.ELEM_LN_MODE),e)&&A.LINE_RAW_WIDTH
      • ')).html(l.title||l.text.code),o.prepend(_)),M=x('
        '),l.copy&&!l.preview&&((C=x(['','',""].join(""))).on("click",function(){c.copy.event()}),M.append(C)),l.langMarker&&M.append(''+l.lang+""),l.about&&M.append(l.about),o.append(M),l.preview||setTimeout(function(){"function"==typeof l.done&&l.done({})},3),l.elem.length===1+d&&"function"==typeof l.allDone&&l.allDone())),g})}),layui["layui.all"]||layui.addcss("modules/code.css?v=6","skincodecss"); \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/logicflow/core/README.md b/demo/thinkphp/frontend/layui_admin_flow/component/logicflow/core/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7e564f149bb9befdcf60a9f8cb42324e8c1d8745 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/logicflow/core/README.md @@ -0,0 +1,170 @@ +

        + + LogicFlow logo + +

        + +

        + + Version + + + Download + + + LICENSE + +

        + +LogicFlow 是一款流程图编辑框架,提供了一系列流程图交互、编辑所必需的功能和简单灵活的节点自定义、插件等拓展机制,方便我们快速在业务系统内满足类流程图的需求。 + +## 特性 + + +- 🛠 高拓展性 + + 兼容各种产品自定义的流程编辑需求,绝大部分模块以插件的形式实现,支持各模块自由插拔。 + +- 🚀 重执行 + + 流程图能完备的表达业务逻辑,不受流程引擎限制。 + +- 🎯 专业 + + 专注于业务流程图编辑的框架 + +## 使用 + +### 安装 + +```sh +# npm +$ npm install @logicflow/core --save + + +# yarn +$ yarn add @logicflow/core +``` + +### 代码示例 + +```js +// 创建容器 +
        ; + +// 准备数据 +const data = { + // 节点 + nodes: [ + { + id: 21, + type: 'rect', + x: 100, + y: 200, + text: { + value: '矩形节点', + x: 100, + y: 200, + }, + }, + { + id: 50, + type: 'circle', + x: 300, + y: 400, + text: { + value: '圆形节点', + x: 300, + y: 400, + }, + }, + ], + // 边 + edges: [ + { + type: 'polyline', + sourceNodeId: 50, + targetNodeId: 21, + }, + ], +}; +// 渲染画布 +const lf = new LogicFlow({ + container: document.querySelector('#container'), + width: 700, + height: 600, +}); + +lf.render(data); +``` + +## 文档 + +[官方文档](https://docs.logic-flow.cn) + +- [快速上手](https://docs.logic-flow.cn/docs/#/zh/guide/start) +- [示例](https://docs.logic-flow.cn/examples/#/gallery) + +## 核心能力 + +### 流程图编辑器快速搭建 + +提供了一个流程图编辑所必需的各项能力,这也是 LogicFlow 的基础能力: + +- 图的绘制能力。基于 SVG 来绘制形状各异的节点和线,并提供了基础的节点(矩形、圆形、多边形等)和线(直线、折线、曲线) +- 各类交互能力,让图动起来。根据节点、线、图的各类鼠标事件(hover、点击、拖拽等)做出反应。比如节点拖拽、拖拽创建边、线的调整、双击节点编辑文本等 +- 提升编辑效率的能力。提供网格、对齐线,上一步、下一步,键盘快捷键,图放大缩小等配套能力,帮助用户提升编辑效率 +- 提供了丰富的 API ,宿主研发通过 API 传参调用和监听事件的方式,与 LogicFlow 完成交互 + + 下面是通过 LogicFlow 内置的节点和配套能力,做的流程图示例 + : + + + +### 基于业务场景拓展 + +当基础能力无法满足业务需求的时候,便需要基于业务场景拓展。 + +- 设置图上所有元素的样式,比如各种节点、线、锚点、箭头、对齐线的大小颜色等,满足对前端样式调整的需求 +- API 拓展。支持在 LogicFlow 上注册自定义的方法,比如通过 API 拓展提供图片下载的方法 +- 自定义节点、线。内置的矩形、圆形等图形类节点往往无法满足实际的业务需求,需要定义具有业务意义的节点。LogicFlow 提供了 的方式让用户定制具有自定义图形、业务数据的节点,比如流程审批场景中的 “审批” 节点 +- 拓展组件。LogicFlow 在 SVG 图层上提供了 HTML 层和一系列坐标转换逻辑,并支持在 HTML 层注册组件。宿主研发可以通过 LogicFlow 的 API,基于任何 View 框架开发组件,比如节点的右键菜单、控制面板等 +- 数据转换 adapter。LogicFlow 默认导出的图数据不一定适合所有业务,此时可以通过 adapter API,在图数据从 LogicFlow 输入、输出的时候做自定义转换,比如转换成 BPMN 规范的图数据 +- 内置部分拓展能力。基于上述拓展能力,我们还单独提供了 extension 的包,用来存放当前业务下沉淀出的具有通用性的节点、组件等,比如面向 BPMN 规范的节点和数据 adapter,默认菜单。注意 extension 可以单独安装,并支持按需引入 + +基于上述拓展的能力,前端研发能够根据实际业务场景的需求,灵活的开发出所需的节点、组件等。下面有两个基于 LogicFlow 拓展能力做出的流程图: + +#### BPMN 规范 + +![图片:bpmn](https://dpubstatic.udache.com/static/dpubimg/CS6S6q9Yxf/lfexample2.gif) + +#### 审批流 + +![图片: 审批流](https://dpubstatic.udache.com/static/dpubimg/uBeSlMEytL/lfexample3.gif) + +#### vue 应用 demo + +[代码地址](https://github.com/xinxin93/logicflow_vue_demo) + +![图片:vue应用](https://dpubstatic.udache.com/static/dpubimg/e35cef10-bb7c-4662-a494-f5aac024c092.gif) + + +#### vue3 node-red风格示例 + +[Logic-Flow/logicflow-node-red-vue3](https://github.com/Logic-Flow/logicflow-node-red-vue3) + +![node-red](https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/core/node-red.png) + +## 联系我们 + +### 加入微信群 + +添加微信号:logic-flow 加入用户群 + +### 加入 QQ 群 + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/logicflow/core/dist/entry.js b/demo/thinkphp/frontend/layui_admin_flow/component/logicflow/core/dist/entry.js new file mode 100644 index 0000000000000000000000000000000000000000..57127cf01a0108a895bc1f9d580c9f377376e573 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/logicflow/core/dist/entry.js @@ -0,0 +1,7 @@ +'use strict' + +if (process.env.NODE_ENV === 'production') { + module.exports = require('./logic-flow.min.js'); +} else { + module.exports = require('./logic-flow.js'); +} diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/logicflow/core/dist/logic-flow.js b/demo/thinkphp/frontend/layui_admin_flow/component/logicflow/core/dist/logic-flow.js new file mode 100644 index 0000000000000000000000000000000000000000..1e4931036e8ae9fa1869e9ba8fa716703beca580 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/logicflow/core/dist/logic-flow.js @@ -0,0 +1,23282 @@ +!function (t, e) { + if ("object" == typeof exports && "object" == typeof module) module.exports = e(); else if ("function" == typeof define && define.amd) define([], e); else { + var r = e(); + for (var n in r) ("object" == typeof exports ? exports : t)[n] = r[n] + } +}(window, (function () { + return function (t) { + var e = {}; + + function r(n) { + if (e[n]) return e[n].exports; + var o = e[n] = {i: n, l: !1, exports: {}}; + return t[n].call(o.exports, o, o.exports, r), o.l = !0, o.exports + } + + return r.m = t, r.c = e, r.d = function (t, e, n) { + r.o(t, e) || Object.defineProperty(t, e, {enumerable: !0, get: n}) + }, r.r = function (t) { + "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, {value: "Module"}), Object.defineProperty(t, "__esModule", {value: !0}) + }, r.t = function (t, e) { + if (1 & e && (t = r(t)), 8 & e) return t; + if (4 & e && "object" == typeof t && t && t.__esModule) return t; + var n = Object.create(null); + if (r.r(n), Object.defineProperty(n, "default", { + enumerable: !0, + value: t + }), 2 & e && "string" != typeof t) for (var o in t) r.d(n, o, function (e) { + return t[e] + }.bind(null, o)); + return n + }, r.n = function (t) { + var e = t && t.__esModule ? function () { + return t.default + } : function () { + return t + }; + return r.d(e, "a", e), e + }, r.o = function (t, e) { + return Object.prototype.hasOwnProperty.call(t, e) + }, r.p = "", r(r.s = 220) + }([function (t, e, r) { + "use strict"; + r.d(e, "a", (function () { + return m + })), r.d(e, "b", (function () { + return b + })), r.d(e, "c", (function () { + return U + })), r.d(e, "d", (function () { + return F + })), r.d(e, "e", (function () { + return y + })), r.d(e, "f", (function () { + return g + })), r.d(e, "g", (function () { + return y + })), r.d(e, "h", (function () { + return B + })), r.d(e, "i", (function () { + return o + })), r.d(e, "j", (function () { + return z + })), r.d(e, "k", (function () { + return S + })); + var n, o, i, u, a, c, s, l = {}, f = [], + p = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i; + + function d(t, e) { + for (var r in e) t[r] = e[r]; + return t + } + + function h(t) { + var e = t.parentNode; + e && e.removeChild(t) + } + + function y(t, e, r) { + var o, i, u, a = {}; + for (u in e) "key" == u ? o = e[u] : "ref" == u ? i = e[u] : a[u] = e[u]; + if (arguments.length > 2 && (a.children = arguments.length > 3 ? n.call(arguments, 2) : r), "function" == typeof t && null != t.defaultProps) for (u in t.defaultProps) void 0 === a[u] && (a[u] = t.defaultProps[u]); + return v(t, a, o, i, null) + } + + function v(t, e, r, n, u) { + var a = { + type: t, + props: e, + key: r, + ref: n, + __k: null, + __: null, + __b: 0, + __e: null, + __d: void 0, + __c: null, + __h: null, + constructor: void 0, + __v: null == u ? ++i : u + }; + return null == u && null != o.vnode && o.vnode(a), a + } + + function g() { + return {current: null} + } + + function b(t) { + return t.children + } + + function m(t, e) { + this.props = t, this.context = e + } + + function O(t, e) { + if (null == e) return t.__ ? O(t.__, t.__.__k.indexOf(t) + 1) : null; + for (var r; e < t.__k.length; e++) if (null != (r = t.__k[e]) && null != r.__e) return r.__e; + return "function" == typeof t.type ? O(t) : null + } + + function _(t) { + var e, r; + if (null != (t = t.__) && null != t.__c) { + for (t.__e = t.__c.base = null, e = 0; e < t.__k.length; e++) if (null != (r = t.__k[e]) && null != r.__e) { + t.__e = t.__c.base = r.__e; + break + } + return _(t) + } + } + + function w(t) { + (!t.__d && (t.__d = !0) && u.push(t) && !x.__r++ || c !== o.debounceRendering) && ((c = o.debounceRendering) || a)(x) + } + + function x() { + for (var t; x.__r = u.length;) t = u.sort((function (t, e) { + return t.__v.__b - e.__v.__b + })), u = [], t.some((function (t) { + var e, r, n, o, i, u; + t.__d && (i = (o = (e = t).__v).__e, (u = e.__P) && (r = [], (n = d({}, o)).__v = o.__v + 1, M(u, o, n, e.__n, void 0 !== u.ownerSVGElement, null != o.__h ? [i] : null, r, null == i ? O(o) : i, o.__h), N(r, o), o.__e != i && _(o))) + })) + } + + function j(t, e, r, n, o, i, u, a, c, s) { + var p, d, h, y, g, m, _, w = n && n.__k || f, x = w.length; + for (r.__k = [], p = 0; p < e.length; p++) if (null != (y = r.__k[p] = null == (y = e[p]) || "boolean" == typeof y ? null : "string" == typeof y || "number" == typeof y || "bigint" == typeof y ? v(null, y, null, null, y) : Array.isArray(y) ? v(b, {children: y}, null, null, null) : y.__b > 0 ? v(y.type, y.props, y.key, null, y.__v) : y)) { + if (y.__ = r, y.__b = r.__b + 1, null === (h = w[p]) || h && y.key == h.key && y.type === h.type) w[p] = void 0; else for (d = 0; d < x; d++) { + if ((h = w[d]) && y.key == h.key && y.type === h.type) { + w[d] = void 0; + break + } + h = null + } + M(t, y, h = h || l, o, i, u, a, c, s), g = y.__e, (d = y.ref) && h.ref != d && (_ || (_ = []), h.ref && _.push(h.ref, null, y), _.push(d, y.__c || g, y)), null != g ? (null == m && (m = g), "function" == typeof y.type && y.__k === h.__k ? y.__d = c = E(y, c, t) : c = P(t, y, h, w, g, c), "function" == typeof r.type && (r.__d = c)) : c && h.__e == c && c.parentNode != t && (c = O(h)) + } + for (r.__e = m, p = x; p--;) null != w[p] && ("function" == typeof r.type && null != w[p].__e && w[p].__e == r.__d && (r.__d = O(n, p + 1)), I(w[p], w[p])); + if (_) for (p = 0; p < _.length; p++) R(_[p], _[++p], _[++p]) + } + + function E(t, e, r) { + for (var n, o = t.__k, i = 0; o && i < o.length; i++) (n = o[i]) && (n.__ = t, e = "function" == typeof n.type ? E(n, e, r) : P(r, n, n, o, n.__e, e)); + return e + } + + function S(t, e) { + return e = e || [], null == t || "boolean" == typeof t || (Array.isArray(t) ? t.some((function (t) { + S(t, e) + })) : e.push(t)), e + } + + function P(t, e, r, n, o, i) { + var u, a, c; + if (void 0 !== e.__d) u = e.__d, e.__d = void 0; else if (null == r || o != i || null == o.parentNode) t:if (null == i || i.parentNode !== t) t.appendChild(o), u = null; else { + for (a = i, c = 0; (a = a.nextSibling) && c < n.length; c += 2) if (a == o) break t; + t.insertBefore(o, i), u = i + } + return void 0 !== u ? u : o.nextSibling + } + + function A(t, e, r) { + "-" === e[0] ? t.setProperty(e, r) : t[e] = null == r ? "" : "number" != typeof r || p.test(e) ? r : r + "px" + } + + function k(t, e, r, n, o) { + var i; + t:if ("style" === e) if ("string" == typeof r) t.style.cssText = r; else { + if ("string" == typeof n && (t.style.cssText = n = ""), n) for (e in n) r && e in r || A(t.style, e, ""); + if (r) for (e in r) n && r[e] === n[e] || A(t.style, e, r[e]) + } else if ("o" === e[0] && "n" === e[1]) i = e !== (e = e.replace(/Capture$/, "")), e = e.toLowerCase() in t ? e.toLowerCase().slice(2) : e.slice(2), t.l || (t.l = {}), t.l[e + i] = r, r ? n || t.addEventListener(e, i ? T : D, i) : t.removeEventListener(e, i ? T : D, i); else if ("dangerouslySetInnerHTML" !== e) { + if (o) e = e.replace(/xlink[H:h]/, "h").replace(/sName$/, "s"); else if ("href" !== e && "list" !== e && "form" !== e && "tabIndex" !== e && "download" !== e && e in t) try { + t[e] = null == r ? "" : r; + break t + } catch (t) { + } + "function" == typeof r || (null != r && (!1 !== r || "a" === e[0] && "r" === e[1]) ? t.setAttribute(e, r) : t.removeAttribute(e)) + } + } + + function D(t) { + this.l[t.type + !1](o.event ? o.event(t) : t) + } + + function T(t) { + this.l[t.type + !0](o.event ? o.event(t) : t) + } + + function M(t, e, r, n, i, u, a, c, s) { + var l, f, p, h, y, v, g, O, _, w, x, E = e.type; + if (void 0 !== e.constructor) return null; + null != r.__h && (s = r.__h, c = e.__e = r.__e, e.__h = null, u = [c]), (l = o.__b) && l(e); + try { + t:if ("function" == typeof E) { + if (O = e.props, _ = (l = E.contextType) && n[l.__c], w = l ? _ ? _.props.value : l.__ : n, r.__c ? g = (f = e.__c = r.__c).__ = f.__E : ("prototype" in E && E.prototype.render ? e.__c = f = new E(O, w) : (e.__c = f = new m(O, w), f.constructor = E, f.render = L), _ && _.sub(f), f.props = O, f.state || (f.state = {}), f.context = w, f.__n = n, p = f.__d = !0, f.__h = []), null == f.__s && (f.__s = f.state), null != E.getDerivedStateFromProps && (f.__s == f.state && (f.__s = d({}, f.__s)), d(f.__s, E.getDerivedStateFromProps(O, f.__s))), h = f.props, y = f.state, p) null == E.getDerivedStateFromProps && null != f.componentWillMount && f.componentWillMount(), null != f.componentDidMount && f.__h.push(f.componentDidMount); else { + if (null == E.getDerivedStateFromProps && O !== h && null != f.componentWillReceiveProps && f.componentWillReceiveProps(O, w), !f.__e && null != f.shouldComponentUpdate && !1 === f.shouldComponentUpdate(O, f.__s, w) || e.__v === r.__v) { + f.props = O, f.state = f.__s, e.__v !== r.__v && (f.__d = !1), f.__v = e, e.__e = r.__e, e.__k = r.__k, e.__k.forEach((function (t) { + t && (t.__ = e) + })), f.__h.length && a.push(f); + break t + } + null != f.componentWillUpdate && f.componentWillUpdate(O, f.__s, w), null != f.componentDidUpdate && f.__h.push((function () { + f.componentDidUpdate(h, y, v) + })) + } + f.context = w, f.props = O, f.state = f.__s, (l = o.__r) && l(e), f.__d = !1, f.__v = e, f.__P = t, l = f.render(f.props, f.state, f.context), f.state = f.__s, null != f.getChildContext && (n = d(d({}, n), f.getChildContext())), p || null == f.getSnapshotBeforeUpdate || (v = f.getSnapshotBeforeUpdate(h, y)), x = null != l && l.type === b && null == l.key ? l.props.children : l, j(t, Array.isArray(x) ? x : [x], e, r, n, i, u, a, c, s), f.base = e.__e, e.__h = null, f.__h.length && a.push(f), g && (f.__E = f.__ = null), f.__e = !1 + } else null == u && e.__v === r.__v ? (e.__k = r.__k, e.__e = r.__e) : e.__e = C(r.__e, e, r, n, i, u, a, s); + (l = o.diffed) && l(e) + } catch (t) { + e.__v = null, (s || null != u) && (e.__e = c, e.__h = !!s, u[u.indexOf(c)] = null), o.__e(t, e, r) + } + } + + function N(t, e) { + o.__c && o.__c(e, t), t.some((function (e) { + try { + t = e.__h, e.__h = [], t.some((function (t) { + t.call(e) + })) + } catch (t) { + o.__e(t, e.__v) + } + })) + } + + function C(t, e, r, o, i, u, a, c) { + var s, f, p, d = r.props, y = e.props, v = e.type, g = 0; + if ("svg" === v && (i = !0), null != u) for (; g < u.length; g++) if ((s = u[g]) && "setAttribute" in s == !!v && (v ? s.localName === v : 3 === s.nodeType)) { + t = s, u[g] = null; + break + } + if (null == t) { + if (null === v) return document.createTextNode(y); + t = i ? document.createElementNS("http://www.w3.org/2000/svg", v) : document.createElement(v, y.is && y), u = null, c = !1 + } + if (null === v) d === y || c && t.data === y || (t.data = y); else { + if (u = u && n.call(t.childNodes), f = (d = r.props || l).dangerouslySetInnerHTML, p = y.dangerouslySetInnerHTML, !c) { + if (null != u) for (d = {}, g = 0; g < t.attributes.length; g++) d[t.attributes[g].name] = t.attributes[g].value; + (p || f) && (p && (f && p.__html == f.__html || p.__html === t.innerHTML) || (t.innerHTML = p && p.__html || "")) + } + if (function (t, e, r, n, o) { + var i; + for (i in r) "children" === i || "key" === i || i in e || k(t, i, null, r[i], n); + for (i in e) o && "function" != typeof e[i] || "children" === i || "key" === i || "value" === i || "checked" === i || r[i] === e[i] || k(t, i, e[i], r[i], n) + }(t, y, d, i, c), p) e.__k = []; else if (g = e.props.children, j(t, Array.isArray(g) ? g : [g], e, r, o, i && "foreignObject" !== v, u, a, u ? u[0] : r.__k && O(r, 0), c), null != u) for (g = u.length; g--;) null != u[g] && h(u[g]); + c || ("value" in y && void 0 !== (g = y.value) && (g !== d.value || g !== t.value || "progress" === v && !g) && k(t, "value", g, d.value, !1), "checked" in y && void 0 !== (g = y.checked) && g !== t.checked && k(t, "checked", g, d.checked, !1)) + } + return t + } + + function R(t, e, r) { + try { + "function" == typeof t ? t(e) : t.current = e + } catch (t) { + o.__e(t, r) + } + } + + function I(t, e, r) { + var n, i; + if (o.unmount && o.unmount(t), (n = t.ref) && (n.current && n.current !== t.__e || R(n, null, e)), null != (n = t.__c)) { + if (n.componentWillUnmount) try { + n.componentWillUnmount() + } catch (t) { + o.__e(t, e) + } + n.base = n.__P = null + } + if (n = t.__k) for (i = 0; i < n.length; i++) n[i] && I(n[i], e, "function" != typeof t.type); + r || null == t.__e || h(t.__e), t.__e = t.__d = void 0 + } + + function L(t, e, r) { + return this.constructor(t, r) + } + + function z(t, e, r) { + var i, u, a; + o.__ && o.__(t, e), u = (i = "function" == typeof r) ? null : r && r.__k || e.__k, a = [], M(e, t = (!i && r || e).__k = y(b, null, [t]), u || l, l, void 0 !== e.ownerSVGElement, !i && r ? [r] : u ? null : e.firstChild ? n.call(e.childNodes) : null, a, !i && r ? r : u ? u.__e : e.firstChild, i), N(a, t) + } + + function B(t, e) { + z(t, e, B) + } + + function U(t, e, r) { + var o, i, u, a = d({}, t.props); + for (u in e) "key" == u ? o = e[u] : "ref" == u ? i = e[u] : a[u] = e[u]; + return arguments.length > 2 && (a.children = arguments.length > 3 ? n.call(arguments, 2) : r), v(t.type, a, o || t.key, i || t.ref, null) + } + + function F(t, e) { + var r = { + __c: e = "__cC" + s++, __: t, Consumer: function (t, e) { + return t.children(e) + }, Provider: function (t) { + var r, n; + return this.getChildContext || (r = [], (n = {})[e] = this, this.getChildContext = function () { + return n + }, this.shouldComponentUpdate = function (t) { + this.props.value !== t.value && r.some(w) + }, this.sub = function (t) { + r.push(t); + var e = t.componentWillUnmount; + t.componentWillUnmount = function () { + r.splice(r.indexOf(t), 1), e && e.call(t) + } + }), t.children + } + }; + return r.Provider.__ = r.Consumer.contextType = r + } + + n = f.slice, o = { + __e: function (t, e) { + for (var r, n, o; e = e.__;) if ((r = e.__c) && !r.__) try { + if ((n = r.constructor) && null != n.getDerivedStateFromError && (r.setState(n.getDerivedStateFromError(t)), o = r.__d), null != r.componentDidCatch && (r.componentDidCatch(t), o = r.__d), o) return r.__E = r + } catch (e) { + t = e + } + throw t + } + }, i = 0, m.prototype.setState = function (t, e) { + var r; + r = null != this.__s && this.__s !== this.state ? this.__s : this.__s = d({}, this.state), "function" == typeof t && (t = t(d({}, r), this.props)), t && d(r, t), null != t && this.__v && (e && this.__h.push(e), w(this)) + }, m.prototype.forceUpdate = function (t) { + this.__v && (this.__e = !0, t && this.__h.push(t), w(this)) + }, m.prototype.render = b, u = [], a = "function" == typeof Promise ? Promise.prototype.then.bind(Promise.resolve()) : setTimeout, x.__r = 0, s = 0 + }, function (t, e, r) { + "use strict"; + (function (t, n) { + r.d(e, "a", (function () { + return _ + })), r.d(e, "b", (function () { + return or + })), r.d(e, "c", (function () { + return Gt + })), r.d(e, "d", (function () { + return xt + })), r.d(e, "e", (function () { + return ht + })), r.d(e, "f", (function () { + return dt + })), r.d(e, "g", (function () { + return wt + })), r.d(e, "h", (function () { + return gr + })), r.d(e, "i", (function () { + return ut + })), r.d(e, "j", (function () { + return _t + })), r.d(e, "k", (function () { + return te + })), r.d(e, "l", (function () { + return oe + })), r.d(e, "m", (function () { + return rt + })), r.d(e, "n", (function () { + return le + })), r.d(e, "o", (function () { + return j + })), r.d(e, "p", (function () { + return Pe + })), r.d(e, "q", (function () { + return fe + })), r.d(e, "r", (function () { + return be + })), r.d(e, "s", (function () { + return vr + })), r.d(e, "t", (function () { + return he + })), r.d(e, "u", (function () { + return re + })), r.d(e, "v", (function () { + return _e + })), r.d(e, "w", (function () { + return we + })), r.d(e, "x", (function () { + return je + })), r.d(e, "y", (function () { + return er + })), r.d(e, "z", (function () { + return ir + })), r.d(e, "A", (function () { + return yr + })), r.d(e, "B", (function () { + return Ee + })), r.d(e, "C", (function () { + return Z + })), r.d(e, "D", (function () { + return ke + })), r.d(e, "E", (function () { + return ce + })), r.d(e, "F", (function () { + return ae + })), r.d(e, "G", (function () { + return ee + })), r.d(e, "H", (function () { + return Zt + })), r.d(e, "I", (function () { + return Ne + })), r.d(e, "J", (function () { + return Re + })), r.d(e, "K", (function () { + return lt + })), r.d(e, "L", (function () { + return Se + })), r.d(e, "M", (function () { + return Ie + })); + var o = []; + Object.freeze(o); + var i = {}; + + function u() { + return ++Rt.mobxGuid + } + + function a(t) { + throw c(!1, t), "X" + } + + function c(t, e) { + if (!t) throw new Error("[mobx] " + (e || "An invariant failed, however the error is obfuscated because this is a production build.")) + } + + Object.freeze(i); + + function s(t) { + var e = !1; + return function () { + if (!e) return e = !0, t.apply(this, arguments) + } + } + + var l = function () { + }; + + function f(t) { + return null !== t && "object" == typeof t + } + + function p(t) { + if (null === t || "object" != typeof t) return !1; + var e = Object.getPrototypeOf(t); + return e === Object.prototype || null === e + } + + function d(t, e, r) { + Object.defineProperty(t, e, {enumerable: !1, writable: !0, configurable: !0, value: r}) + } + + function h(t, e) { + var r = "isMobX" + t; + return e.prototype[r] = !0, function (t) { + return f(t) && !0 === t[r] + } + } + + function y(t) { + return t instanceof Map + } + + function v(t) { + return t instanceof Set + } + + function g(t) { + var e = new Set; + for (var r in t) e.add(r); + return Object.getOwnPropertySymbols(t).forEach((function (r) { + Object.getOwnPropertyDescriptor(t, r).enumerable && e.add(r) + })), Array.from(e) + } + + function b(t) { + return t && t.toString ? t.toString() : new String(t).toString() + } + + function m(t) { + return null === t ? null : "object" == typeof t ? "" + t : t + } + + var O = "undefined" != typeof Reflect && Reflect.ownKeys ? Reflect.ownKeys : Object.getOwnPropertySymbols ? function (t) { + return Object.getOwnPropertyNames(t).concat(Object.getOwnPropertySymbols(t)) + } : Object.getOwnPropertyNames, _ = Symbol("mobx administration"), w = function () { + function t(t) { + void 0 === t && (t = "Atom@" + u()), this.name = t, this.isPendingUnobservation = !1, this.isBeingObserved = !1, this.observers = new Set, this.diffValue = 0, this.lastAccessedBy = 0, this.lowestObserverState = J.NOT_TRACKING + } + + return t.prototype.onBecomeObserved = function () { + this.onBecomeObservedListeners && this.onBecomeObservedListeners.forEach((function (t) { + return t() + })) + }, t.prototype.onBecomeUnobserved = function () { + this.onBecomeUnobservedListeners && this.onBecomeUnobservedListeners.forEach((function (t) { + return t() + })) + }, t.prototype.reportObserved = function () { + return Ft(this) + }, t.prototype.reportChanged = function () { + Bt(), function (t) { + if (t.lowestObserverState === J.STALE) return; + t.lowestObserverState = J.STALE, t.observers.forEach((function (e) { + e.dependenciesState === J.UP_TO_DATE && (e.isTracing !== Q.NONE && Ht(e, t), e.onBecomeStale()), e.dependenciesState = J.STALE + })) + }(this), Ut() + }, t.prototype.toString = function () { + return this.name + }, t + }(), x = h("Atom", w); + + function j(t, e, r) { + void 0 === e && (e = l), void 0 === r && (r = l); + var n, o = new w(t); + return e !== l && se("onBecomeObserved", o, e, n), r !== l && ce(o, r), o + } + + var E = { + identity: function (t, e) { + return t === e + }, structural: function (t, e) { + return mr(t, e) + }, default: function (t, e) { + return Object.is(t, e) + }, shallow: function (t, e) { + return mr(t, e, 1) + } + }, S = function (t, e) { + return S = Object.setPrototypeOf || {__proto__: []} instanceof Array && function (t, e) { + t.__proto__ = e + } || function (t, e) { + for (var r in e) e.hasOwnProperty(r) && (t[r] = e[r]) + }, S(t, e) + }; + /*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + var P = function () { + return P = Object.assign || function (t) { + for (var e, r = 1, n = arguments.length; r < n; r++) for (var o in e = arguments[r]) Object.prototype.hasOwnProperty.call(e, o) && (t[o] = e[o]); + return t + }, P.apply(this, arguments) + }; + + function A(t) { + var e = "function" == typeof Symbol && t[Symbol.iterator], r = 0; + return e ? e.call(t) : { + next: function () { + return t && r >= t.length && (t = void 0), {value: t && t[r++], done: !t} + } + } + } + + function k(t, e) { + var r = "function" == typeof Symbol && t[Symbol.iterator]; + if (!r) return t; + var n, o, i = r.call(t), u = []; + try { + for (; (void 0 === e || e-- > 0) && !(n = i.next()).done;) u.push(n.value) + } catch (t) { + o = {error: t} + } finally { + try { + n && !n.done && (r = i.return) && r.call(i) + } finally { + if (o) throw o.error + } + } + return u + } + + function D() { + for (var t = [], e = 0; e < arguments.length; e++) t = t.concat(k(arguments[e])); + return t + } + + var T = Symbol("mobx did run lazy initializers"), M = Symbol("mobx pending decorators"), N = {}, C = {}; + + function R(t, e) { + var r = e ? N : C; + return r[t] || (r[t] = { + configurable: !0, enumerable: e, get: function () { + return I(this), this[t] + }, set: function (e) { + I(this), this[t] = e + } + }) + } + + function I(t) { + var e, r; + if (!0 !== t[T]) { + var n = t[M]; + if (n) { + d(t, T, !0); + var o = D(Object.getOwnPropertySymbols(n), Object.keys(n)); + try { + for (var i = A(o), u = i.next(); !u.done; u = i.next()) { + var a = n[u.value]; + a.propertyCreator(t, a.prop, a.descriptor, a.decoratorTarget, a.decoratorArguments) + } + } catch (t) { + e = {error: t} + } finally { + try { + u && !u.done && (r = i.return) && r.call(i) + } finally { + if (e) throw e.error + } + } + } + } + } + + function L(t, e) { + return function () { + var r, n = function (n, o, i, u) { + if (!0 === u) return e(n, o, i, n, r), null; + if (!Object.prototype.hasOwnProperty.call(n, M)) { + var a = n[M]; + d(n, M, P({}, a)) + } + return n[M][o] = { + prop: o, + propertyCreator: e, + descriptor: i, + decoratorTarget: n, + decoratorArguments: r + }, R(o, t) + }; + return z(arguments) ? (r = o, n.apply(null, arguments)) : (r = Array.prototype.slice.call(arguments), n) + } + } + + function z(t) { + return (2 === t.length || 3 === t.length) && ("string" == typeof t[1] || "symbol" == typeof t[1]) || 4 === t.length && !0 === t[3] + } + + function B(t, e, r) { + return je(t) ? t : Array.isArray(t) ? Z.array(t, {name: r}) : p(t) ? Z.object(t, void 0, {name: r}) : y(t) ? Z.map(t, {name: r}) : v(t) ? Z.set(t, {name: r}) : t + } + + function U(t) { + return t + } + + function F(e) { + c(e); + var r = L(!0, (function (t, r, n, o, i) { + var u = n ? n.initializer ? n.initializer.call(t) : n.value : void 0; + lr(t).addObservableProp(r, u, e) + })), n = (void 0 !== t && t.env, r); + return n.enhancer = e, n + } + + var H = {deep: !0, name: void 0, defaultDecorator: void 0, proxy: !0}; + + function X(t) { + return null == t ? H : "string" == typeof t ? {name: t, deep: !0, proxy: !0} : t + } + + Object.freeze(H); + var G = F(B), Y = F((function (t, e, r) { + return null == t || yr(t) || er(t) || ir(t) || cr(t) ? t : Array.isArray(t) ? Z.array(t, { + name: r, + deep: !1 + }) : p(t) ? Z.object(t, void 0, {name: r, deep: !1}) : y(t) ? Z.map(t, { + name: r, + deep: !1 + }) : v(t) ? Z.set(t, {name: r, deep: !1}) : a(!1) + })), V = F(U), W = F((function (t, e, r) { + return mr(t, e) ? e : t + })); + + function K(t) { + return t.defaultDecorator ? t.defaultDecorator.enhancer : !1 === t.deep ? U : B + } + + var $ = { + box: function (t, e) { + arguments.length > 2 && q("box"); + var r = X(e); + return new St(t, K(r), r.name, !0, r.equals) + }, array: function (t, e) { + arguments.length > 2 && q("array"); + var r = X(e); + return Ze(t, K(r), r.name) + }, map: function (t, e) { + arguments.length > 2 && q("map"); + var r = X(e); + return new or(t, K(r), r.name) + }, set: function (t, e) { + arguments.length > 2 && q("set"); + var r = X(e); + return new ar(t, K(r), r.name) + }, object: function (t, e, r) { + "string" == typeof arguments[1] && q("object"); + var n = X(r); + if (!1 === n.proxy) return fe({}, t, e, n); + var o = pe(n), i = fe({}, void 0, void 0, n), u = He(i); + return de(u, t, e, o), u + }, ref: V, shallow: Y, deep: G, struct: W + }, Z = function (t, e, r) { + if ("string" == typeof arguments[1] || "symbol" == typeof arguments[1]) return G.apply(null, arguments); + if (je(t)) return t; + var n = p(t) ? Z.object(t, e, r) : Array.isArray(t) ? Z.array(t, e) : y(t) ? Z.map(t, e) : v(t) ? Z.set(t, e) : t; + if (n !== t) return n; + a(!1) + }; + + function q(t) { + a("Expected one or two arguments to observable." + t + ". Did you accidentally try to use observable." + t + " as decorator?") + } + + Object.keys($).forEach((function (t) { + return Z[t] = $[t] + })); + var J, Q, tt = L(!1, (function (t, e, r, n, o) { + var i = r.get, u = r.set, a = o[0] || {}; + lr(t).addComputedProp(t, e, P({get: i, set: u, context: t}, a)) + })), et = tt({equals: E.structural}), rt = function (t, e, r) { + if ("string" == typeof e) return tt.apply(null, arguments); + if (null !== t && "object" == typeof t && 1 === arguments.length) return tt.apply(null, arguments); + var n = "object" == typeof e ? e : {}; + return n.get = t, n.set = "function" == typeof e ? e : n.set, n.name = n.name || t.name || "", new At(n) + }; + rt.struct = et, function (t) { + t[t.NOT_TRACKING = -1] = "NOT_TRACKING", t[t.UP_TO_DATE = 0] = "UP_TO_DATE", t[t.POSSIBLY_STALE = 1] = "POSSIBLY_STALE", t[t.STALE = 2] = "STALE" + }(J || (J = {})), function (t) { + t[t.NONE = 0] = "NONE", t[t.LOG = 1] = "LOG", t[t.BREAK = 2] = "BREAK" + }(Q || (Q = {})); + var nt = function (t) { + this.cause = t + }; + + function ot(t) { + return t instanceof nt + } + + function it(t) { + switch (t.dependenciesState) { + case J.UP_TO_DATE: + return !1; + case J.NOT_TRACKING: + case J.STALE: + return !0; + case J.POSSIBLY_STALE: + for (var e = dt(!0), r = ft(), n = t.observing, o = n.length, i = 0; i < o; i++) { + var u = n[i]; + if (kt(u)) { + if (Rt.disableErrorBoundaries) u.get(); else try { + u.get() + } catch (t) { + return pt(r), ht(e), !0 + } + if (t.dependenciesState === J.STALE) return pt(r), ht(e), !0 + } + } + return yt(t), pt(r), ht(e), !1 + } + } + + function ut() { + return null !== Rt.trackingDerivation + } + + function at(t) { + var e = t.observers.size > 0; + Rt.computationDepth > 0 && e && a(!1), Rt.allowStateChanges || !e && "strict" !== Rt.enforceActions || a(!1) + } + + function ct(t, e, r) { + var n = dt(!0); + yt(t), t.newObserving = new Array(t.observing.length + 100), t.unboundDepsCount = 0, t.runId = ++Rt.runId; + var o, i = Rt.trackingDerivation; + if (Rt.trackingDerivation = t, !0 === Rt.disableErrorBoundaries) o = e.call(r); else try { + o = e.call(r) + } catch (t) { + o = new nt(t) + } + return Rt.trackingDerivation = i, function (t) { + for (var e = t.observing, r = t.observing = t.newObserving, n = J.UP_TO_DATE, o = 0, i = t.unboundDepsCount, u = 0; u < i; u++) { + 0 === (a = r[u]).diffValue && (a.diffValue = 1, o !== u && (r[o] = a), o++), a.dependenciesState > n && (n = a.dependenciesState) + } + r.length = o, t.newObserving = null, i = e.length; + for (; i--;) { + 0 === (a = e[i]).diffValue && Lt(a, t), a.diffValue = 0 + } + for (; o--;) { + var a; + 1 === (a = r[o]).diffValue && (a.diffValue = 0, It(a, t)) + } + n !== J.UP_TO_DATE && (t.dependenciesState = n, t.onBecomeStale()) + }(t), ht(n), o + } + + function st(t) { + var e = t.observing; + t.observing = []; + for (var r = e.length; r--;) Lt(e[r], t); + t.dependenciesState = J.NOT_TRACKING + } + + function lt(t) { + var e = ft(); + try { + return t() + } finally { + pt(e) + } + } + + function ft() { + var t = Rt.trackingDerivation; + return Rt.trackingDerivation = null, t + } + + function pt(t) { + Rt.trackingDerivation = t + } + + function dt(t) { + var e = Rt.allowStateReads; + return Rt.allowStateReads = t, e + } + + function ht(t) { + Rt.allowStateReads = t + } + + function yt(t) { + if (t.dependenciesState !== J.UP_TO_DATE) { + t.dependenciesState = J.UP_TO_DATE; + for (var e = t.observing, r = e.length; r--;) e[r].lowestObserverState = J.UP_TO_DATE + } + } + + var vt = 0, gt = 1, bt = Object.getOwnPropertyDescriptor((function () { + }), "name"); + bt && bt.configurable; + + function mt(t, e, r) { + var n = function () { + return Ot(t, e, r || this, arguments) + }; + return n.isMobxAction = !0, n + } + + function Ot(t, e, r, n) { + var o = _t(t, r, n); + try { + return e.apply(r, n) + } catch (t) { + throw o.error = t, t + } finally { + wt(o) + } + } + + function _t(t, e, r) { + var n = 0, o = ft(); + Bt(); + var i = { + prevDerivation: o, + prevAllowStateChanges: jt(!0), + prevAllowStateReads: dt(!0), + notifySpy: false, + startTime: n, + actionId: gt++, + parentActionId: vt + }; + return vt = i.actionId, i + } + + function wt(t) { + vt !== t.actionId && a("invalid action stack. did you forget to finish an action?"), vt = t.parentActionId, void 0 !== t.error && (Rt.suppressReactionErrors = !0), Et(t.prevAllowStateChanges), ht(t.prevAllowStateReads), Ut(), pt(t.prevDerivation), t.notifySpy, Rt.suppressReactionErrors = !1 + } + + function xt(t, e) { + var r, n = jt(t); + try { + r = e() + } finally { + Et(n) + } + return r + } + + function jt(t) { + var e = Rt.allowStateChanges; + return Rt.allowStateChanges = t, e + } + + function Et(t) { + Rt.allowStateChanges = t + } + + var St = function (t) { + function e(e, r, n, o, i) { + void 0 === n && (n = "ObservableValue@" + u()), void 0 === o && (o = !0), void 0 === i && (i = E.default); + var a = t.call(this, n) || this; + return a.enhancer = r, a.name = n, a.equals = i, a.hasUnreportedChange = !1, a.value = r(e, void 0, n), a + } + + return function (t, e) { + function r() { + this.constructor = t + } + + S(t, e), t.prototype = null === e ? Object.create(e) : (r.prototype = e.prototype, new r) + }(e, t), e.prototype.dehanceValue = function (t) { + return void 0 !== this.dehancer ? this.dehancer(t) : t + }, e.prototype.set = function (t) { + this.value; + if ((t = this.prepareNewValue(t)) !== Rt.UNCHANGED) { + false, this.setNewValue(t) + } + }, e.prototype.prepareNewValue = function (t) { + if (at(this), Xe(this)) { + var e = Ye(this, {object: this, type: "update", newValue: t}); + if (!e) return Rt.UNCHANGED; + t = e.newValue + } + return t = this.enhancer(t, this.value, this.name), this.equals(this.value, t) ? Rt.UNCHANGED : t + }, e.prototype.setNewValue = function (t) { + var e = this.value; + this.value = t, this.reportChanged(), Ve(this) && Ke(this, { + type: "update", + object: this, + newValue: t, + oldValue: e + }) + }, e.prototype.get = function () { + return this.reportObserved(), this.dehanceValue(this.value) + }, e.prototype.intercept = function (t) { + return Ge(this, t) + }, e.prototype.observe = function (t, e) { + return e && t({object: this, type: "update", newValue: this.value, oldValue: void 0}), We(this, t) + }, e.prototype.toJSON = function () { + return this.get() + }, e.prototype.toString = function () { + return this.name + "[" + this.value + "]" + }, e.prototype.valueOf = function () { + return m(this.get()) + }, e.prototype[Symbol.toPrimitive] = function () { + return this.valueOf() + }, e + }(w), Pt = h("ObservableValue", St), At = function () { + function t(t) { + this.dependenciesState = J.NOT_TRACKING, this.observing = [], this.newObserving = null, this.isBeingObserved = !1, this.isPendingUnobservation = !1, this.observers = new Set, this.diffValue = 0, this.runId = 0, this.lastAccessedBy = 0, this.lowestObserverState = J.UP_TO_DATE, this.unboundDepsCount = 0, this.__mapid = "#" + u(), this.value = new nt(null), this.isComputing = !1, this.isRunningSetter = !1, this.isTracing = Q.NONE, c(t.get, "missing option for computed: get"), this.derivation = t.get, this.name = t.name || "ComputedValue@" + u(), t.set && (this.setter = mt(this.name + "-setter", t.set)), this.equals = t.equals || (t.compareStructural || t.struct ? E.structural : E.default), this.scope = t.context, this.requiresReaction = !!t.requiresReaction, this.keepAlive = !!t.keepAlive + } + + return t.prototype.onBecomeStale = function () { + !function (t) { + if (t.lowestObserverState !== J.UP_TO_DATE) return; + t.lowestObserverState = J.POSSIBLY_STALE, t.observers.forEach((function (e) { + e.dependenciesState === J.UP_TO_DATE && (e.dependenciesState = J.POSSIBLY_STALE, e.isTracing !== Q.NONE && Ht(e, t), e.onBecomeStale()) + })) + }(this) + }, t.prototype.onBecomeObserved = function () { + this.onBecomeObservedListeners && this.onBecomeObservedListeners.forEach((function (t) { + return t() + })) + }, t.prototype.onBecomeUnobserved = function () { + this.onBecomeUnobservedListeners && this.onBecomeUnobservedListeners.forEach((function (t) { + return t() + })) + }, t.prototype.get = function () { + this.isComputing && a("Cycle detected in computation " + this.name + ": " + this.derivation), 0 !== Rt.inBatch || 0 !== this.observers.size || this.keepAlive ? (Ft(this), it(this) && this.trackAndCompute() && function (t) { + if (t.lowestObserverState === J.STALE) return; + t.lowestObserverState = J.STALE, t.observers.forEach((function (e) { + e.dependenciesState === J.POSSIBLY_STALE ? e.dependenciesState = J.STALE : e.dependenciesState === J.UP_TO_DATE && (t.lowestObserverState = J.UP_TO_DATE) + })) + }(this)) : it(this) && (this.warnAboutUntrackedRead(), Bt(), this.value = this.computeValue(!1), Ut()); + var t = this.value; + if (ot(t)) throw t.cause; + return t + }, t.prototype.peek = function () { + var t = this.computeValue(!1); + if (ot(t)) throw t.cause; + return t + }, t.prototype.set = function (t) { + if (this.setter) { + c(!this.isRunningSetter, "The setter of computed value '" + this.name + "' is trying to update itself. Did you intend to update an _observable_ value, instead of the computed property?"), this.isRunningSetter = !0; + try { + this.setter.call(this.scope, t) + } finally { + this.isRunningSetter = !1 + } + } else c(!1, !1) + }, t.prototype.trackAndCompute = function () { + var t = this.value, e = this.dependenciesState === J.NOT_TRACKING, r = this.computeValue(!0), + n = e || ot(t) || ot(r) || !this.equals(t, r); + return n && (this.value = r), n + }, t.prototype.computeValue = function (t) { + var e; + if (this.isComputing = !0, Rt.computationDepth++, t) e = ct(this, this.derivation, this.scope); else if (!0 === Rt.disableErrorBoundaries) e = this.derivation.call(this.scope); else try { + e = this.derivation.call(this.scope) + } catch (t) { + e = new nt(t) + } + return Rt.computationDepth--, this.isComputing = !1, e + }, t.prototype.suspend = function () { + this.keepAlive || (st(this), this.value = void 0) + }, t.prototype.observe = function (t, e) { + var r = this, n = !0, o = void 0; + return oe((function () { + var i = r.get(); + if (!n || e) { + var u = ft(); + t({type: "update", object: r, newValue: i, oldValue: o}), pt(u) + } + n = !1, o = i + })) + }, t.prototype.warnAboutUntrackedRead = function () { + }, t.prototype.toJSON = function () { + return this.get() + }, t.prototype.toString = function () { + return this.name + "[" + this.derivation.toString() + "]" + }, t.prototype.valueOf = function () { + return m(this.get()) + }, t.prototype[Symbol.toPrimitive] = function () { + return this.valueOf() + }, t + }(), kt = h("ComputedValue", At), Dt = function () { + this.version = 5, this.UNCHANGED = {}, this.trackingDerivation = null, this.computationDepth = 0, this.runId = 0, this.mobxGuid = 0, this.inBatch = 0, this.pendingUnobservations = [], this.pendingReactions = [], this.isRunningReactions = !1, this.allowStateChanges = !0, this.allowStateReads = !0, this.enforceActions = !1, this.spyListeners = [], this.globalReactionErrorHandlers = [], this.computedRequiresReaction = !1, this.reactionRequiresObservable = !1, this.observableRequiresReaction = !1, this.computedConfigurable = !1, this.disableErrorBoundaries = !1, this.suppressReactionErrors = !1 + }, Tt = {}; + + function Mt() { + return "undefined" != typeof window ? window : void 0 !== n ? n : "undefined" != typeof self ? self : Tt + } + + var Nt = !0, Ct = !1, Rt = function () { + var t = Mt(); + return t.__mobxInstanceCount > 0 && !t.__mobxGlobals && (Nt = !1), t.__mobxGlobals && t.__mobxGlobals.version !== (new Dt).version && (Nt = !1), Nt ? t.__mobxGlobals ? (t.__mobxInstanceCount += 1, t.__mobxGlobals.UNCHANGED || (t.__mobxGlobals.UNCHANGED = {}), t.__mobxGlobals) : (t.__mobxInstanceCount = 1, t.__mobxGlobals = new Dt) : (setTimeout((function () { + Ct || a("There are multiple, different versions of MobX active. Make sure MobX is loaded only once or use `configure({ isolateGlobalState: true })`") + }), 1), new Dt) + }(); + + function It(t, e) { + t.observers.add(e), t.lowestObserverState > e.dependenciesState && (t.lowestObserverState = e.dependenciesState) + } + + function Lt(t, e) { + t.observers.delete(e), 0 === t.observers.size && zt(t) + } + + function zt(t) { + !1 === t.isPendingUnobservation && (t.isPendingUnobservation = !0, Rt.pendingUnobservations.push(t)) + } + + function Bt() { + Rt.inBatch++ + } + + function Ut() { + if (0 == --Rt.inBatch) { + Vt(); + for (var t = Rt.pendingUnobservations, e = 0; e < t.length; e++) { + var r = t[e]; + r.isPendingUnobservation = !1, 0 === r.observers.size && (r.isBeingObserved && (r.isBeingObserved = !1, r.onBecomeUnobserved()), r instanceof At && r.suspend()) + } + Rt.pendingUnobservations = [] + } + } + + function Ft(t) { + var e = Rt.trackingDerivation; + return null !== e ? (e.runId !== t.lastAccessedBy && (t.lastAccessedBy = e.runId, e.newObserving[e.unboundDepsCount++] = t, t.isBeingObserved || (t.isBeingObserved = !0, t.onBecomeObserved())), !0) : (0 === t.observers.size && Rt.inBatch > 0 && zt(t), !1) + } + + function Ht(t, e) { + if (t.isTracing === Q.BREAK) { + var r = []; + Xt(he(t), r, 1), new Function("debugger;\n/*\nTracing '" + t.name + "'\n\nYou are entering this break point because derivation '" + t.name + "' is being traced and '" + e.name + "' is now forcing it to update.\nJust follow the stacktrace you should now see in the devtools to see precisely what piece of your code is causing this update\nThe stackframe you are looking for is at least ~6-8 stack-frames up.\n\n" + (t instanceof At ? t.derivation.toString().replace(/[*]\//g, "/") : "") + "\n\nThe dependencies for this derivation are:\n\n" + r.join("\n") + "\n*/\n ")() + } + } + + function Xt(t, e, r) { + e.length >= 1e3 ? e.push("(and many more)") : (e.push("" + new Array(r).join("\t") + t.name), t.dependencies && t.dependencies.forEach((function (t) { + return Xt(t, e, r + 1) + }))) + } + + var Gt = function () { + function t(t, e, r, n) { + void 0 === t && (t = "Reaction@" + u()), void 0 === n && (n = !1), this.name = t, this.onInvalidate = e, this.errorHandler = r, this.requiresObservable = n, this.observing = [], this.newObserving = [], this.dependenciesState = J.NOT_TRACKING, this.diffValue = 0, this.runId = 0, this.unboundDepsCount = 0, this.__mapid = "#" + u(), this.isDisposed = !1, this._isScheduled = !1, this._isTrackPending = !1, this._isRunning = !1, this.isTracing = Q.NONE + } + + return t.prototype.onBecomeStale = function () { + this.schedule() + }, t.prototype.schedule = function () { + this._isScheduled || (this._isScheduled = !0, Rt.pendingReactions.push(this), Vt()) + }, t.prototype.isScheduled = function () { + return this._isScheduled + }, t.prototype.runReaction = function () { + if (!this.isDisposed) { + if (Bt(), this._isScheduled = !1, it(this)) { + this._isTrackPending = !0; + try { + this.onInvalidate(), this._isTrackPending + } catch (t) { + this.reportExceptionInDerivation(t) + } + } + Ut() + } + }, t.prototype.track = function (t) { + if (!this.isDisposed) { + Bt(); + false, this._isRunning = !0; + var e = ct(this, t, void 0); + this._isRunning = !1, this._isTrackPending = !1, this.isDisposed && st(this), ot(e) && this.reportExceptionInDerivation(e.cause), Ut() + } + }, t.prototype.reportExceptionInDerivation = function (t) { + var e = this; + if (this.errorHandler) this.errorHandler(t, this); else { + if (Rt.disableErrorBoundaries) throw t; + Rt.suppressReactionErrors, Rt.globalReactionErrorHandlers.forEach((function (r) { + return r(t, e) + })) + } + }, t.prototype.dispose = function () { + this.isDisposed || (this.isDisposed = !0, this._isRunning || (Bt(), st(this), Ut())) + }, t.prototype.getDisposer = function () { + var t = this.dispose.bind(this); + return t[_] = this, t + }, t.prototype.toString = function () { + return "Reaction[" + this.name + "]" + }, t.prototype.trace = function (t) { + void 0 === t && (t = !1), function () { + for (var t = [], e = 0; e < arguments.length; e++) t[e] = arguments[e]; + var r = !1; + "boolean" == typeof t[t.length - 1] && (r = t.pop()); + var n = Ce(t); + if (!n) return a(!1); + n.isTracing, Q.NONE; + n.isTracing = r ? Q.BREAK : Q.LOG + }(this, t) + }, t + }(); + var Yt = function (t) { + return t() + }; + + function Vt() { + Rt.inBatch > 0 || Rt.isRunningReactions || Yt(Wt) + } + + function Wt() { + Rt.isRunningReactions = !0; + for (var t = Rt.pendingReactions, e = 0; t.length > 0;) { + 100 == ++e && t.splice(0); + for (var r = t.splice(0), n = 0, o = r.length; n < o; n++) r[n].runReaction() + } + Rt.isRunningReactions = !1 + } + + var Kt = h("Reaction", Gt); + + function $t(t) { + var e = Yt; + Yt = function (r) { + return t((function () { + return e(r) + })) + } + } + + function Zt(t) { + return function () { + } + } + + function qt() { + a(!1) + } + + function Jt(t) { + return function (e, r, n) { + if (n) { + if (n.value) return {value: mt(t, n.value), enumerable: !1, configurable: !0, writable: !0}; + var o = n.initializer; + return { + enumerable: !1, configurable: !0, writable: !0, initializer: function () { + return mt(t, o.call(this)) + } + } + } + return Qt(t).apply(this, arguments) + } + } + + function Qt(t) { + return function (e, r, n) { + Object.defineProperty(e, r, { + configurable: !0, enumerable: !1, get: function () { + }, set: function (e) { + d(this, r, te(t, e)) + } + }) + } + } + + var te = function (t, e, r, n) { + return 1 === arguments.length && "function" == typeof t ? mt(t.name || "", t) : 2 === arguments.length && "function" == typeof e ? mt(t, e) : 1 === arguments.length && "string" == typeof t ? Jt(t) : !0 !== n ? Jt(e).apply(null, arguments) : void d(t, e, mt(t.name || e, r.value, this)) + }; + + function ee(t, e) { + return Ot("string" == typeof t ? t : t.name || "", "function" == typeof t ? t : e, this, void 0) + } + + function re(t) { + return "function" == typeof t && !0 === t.isMobxAction + } + + function ne(t, e, r) { + d(t, e, mt(e, r.bind(t))) + } + + function oe(t, e) { + void 0 === e && (e = i); + var r, n = e && e.name || t.name || "Autorun@" + u(); + if (!e.scheduler && !e.delay) r = new Gt(n, (function () { + this.track(c) + }), e.onError, e.requiresObservable); else { + var o = ue(e), a = !1; + r = new Gt(n, (function () { + a || (a = !0, o((function () { + a = !1, r.isDisposed || r.track(c) + }))) + }), e.onError, e.requiresObservable) + } + + function c() { + t(r) + } + + return r.schedule(), r.getDisposer() + } + + te.bound = function (t, e, r, n) { + return !0 === n ? (ne(t, e, r.value), null) : r ? { + configurable: !0, enumerable: !1, get: function () { + return ne(this, e, r.value || r.initializer.call(this)), this[e] + }, set: qt + } : { + enumerable: !1, configurable: !0, set: function (t) { + ne(this, e, t) + }, get: function () { + } + } + }; + var ie = function (t) { + return t() + }; + + function ue(t) { + return t.scheduler ? t.scheduler : t.delay ? function (e) { + return setTimeout(e, t.delay) + } : ie + } + + function ae(t, e, r) { + void 0 === r && (r = i); + var n, o, a, c = r.name || "Reaction@" + u(), s = te(c, r.onError ? (n = r.onError, o = e, function () { + try { + return o.apply(this, arguments) + } catch (t) { + n.call(this, t) + } + }) : e), l = !r.scheduler && !r.delay, f = ue(r), p = !0, d = !1, + h = r.compareStructural ? E.structural : r.equals || E.default, y = new Gt(c, (function () { + p || l ? v() : d || (d = !0, f(v)) + }), r.onError, r.requiresObservable); + + function v() { + if (d = !1, !y.isDisposed) { + var e = !1; + y.track((function () { + var r = t(y); + e = p || !h(a, r), a = r + })), p && r.fireImmediately && s(a, y), p || !0 !== e || s(a, y), p && (p = !1) + } + } + + return y.schedule(), y.getDisposer() + } + + function ce(t, e, r) { + return se("onBecomeUnobserved", t, e, r) + } + + function se(t, e, r, n) { + var o = "function" == typeof n ? vr(e, r) : vr(e), i = "function" == typeof n ? n : r, + u = t + "Listeners"; + return o[u] ? o[u].add(i) : o[u] = new Set([i]), "function" != typeof o[t] ? a(!1) : function () { + var t = o[u]; + t && (t.delete(i), 0 === t.size && delete o[u]) + } + } + + function le(t) { + var e = t.enforceActions, r = t.computedRequiresReaction, n = t.computedConfigurable, + o = t.disableErrorBoundaries, i = t.reactionScheduler, u = t.reactionRequiresObservable, + c = t.observableRequiresReaction; + if (!0 === t.isolateGlobalState && ((Rt.pendingReactions.length || Rt.inBatch || Rt.isRunningReactions) && a("isolateGlobalState should be called before MobX is running any reactions"), Ct = !0, Nt && (0 == --Mt().__mobxInstanceCount && (Mt().__mobxGlobals = void 0), Rt = new Dt)), void 0 !== e) { + var s = void 0; + switch (e) { + case!0: + case"observed": + s = !0; + break; + case!1: + case"never": + s = !1; + break; + case"strict": + case"always": + s = "strict"; + break; + default: + a("Invalid value for 'enforceActions': '" + e + "', expected 'never', 'always' or 'observed'") + } + Rt.enforceActions = s, Rt.allowStateChanges = !0 !== s && "strict" !== s + } + void 0 !== r && (Rt.computedRequiresReaction = !!r), void 0 !== u && (Rt.reactionRequiresObservable = !!u), void 0 !== c && (Rt.observableRequiresReaction = !!c, Rt.allowStateReads = !Rt.observableRequiresReaction), void 0 !== n && (Rt.computedConfigurable = !!n), void 0 !== o && (Rt.disableErrorBoundaries = !!o), i && $t(i) + } + + function fe(t, e, r, n) { + var o = pe(n = X(n)); + return I(t), lr(t, n.name, o.enhancer), e && de(t, e, r, o), t + } + + function pe(t) { + return t.defaultDecorator || (!1 === t.deep ? V : G) + } + + function de(t, e, r, n) { + var o, i; + Bt(); + try { + var u = O(e); + try { + for (var a = A(u), c = a.next(); !c.done; c = a.next()) { + var s = c.value, l = Object.getOwnPropertyDescriptor(e, s); + 0; + var f = (r && s in r ? r[s] : l.get ? tt : n)(t, s, l, !0); + f && Object.defineProperty(t, s, f) + } + } catch (t) { + o = {error: t} + } finally { + try { + c && !c.done && (i = a.return) && i.call(a) + } finally { + if (o) throw o.error + } + } + } finally { + Ut() + } + } + + function he(t, e) { + return ye(vr(t, e)) + } + + function ye(t) { + var e, r, n = {name: t.name}; + return t.observing && t.observing.length > 0 && (n.dependencies = (e = t.observing, r = [], e.forEach((function (t) { + -1 === r.indexOf(t) && r.push(t) + })), r).map(ye)), n + } + + var ve = 0; + + function ge() { + this.message = "FLOW_CANCELLED" + } + + function be(t) { + 1 !== arguments.length && a("Flow expects 1 argument and cannot be used as decorator"); + var e = t.name || ""; + return function () { + var r, n = this, o = arguments, i = ++ve, u = te(e + " - runid: " + i + " - init", t).apply(n, o), + a = void 0, c = new Promise((function (t, n) { + var o = 0; + + function c(t) { + var r; + a = void 0; + try { + r = te(e + " - runid: " + i + " - yield " + o++, u.next).call(u, t) + } catch (t) { + return n(t) + } + l(r) + } + + function s(t) { + var r; + a = void 0; + try { + r = te(e + " - runid: " + i + " - yield " + o++, u.throw).call(u, t) + } catch (t) { + return n(t) + } + l(r) + } + + function l(e) { + if (!e || "function" != typeof e.then) return e.done ? t(e.value) : (a = Promise.resolve(e.value)).then(c, s); + e.then(l, n) + } + + r = n, c(void 0) + })); + return c.cancel = te(e + " - runid: " + i + " - cancel", (function () { + try { + a && me(a); + var t = u.return(void 0), e = Promise.resolve(t.value); + e.then(l, l), me(e), r(new ge) + } catch (t) { + r(t) + } + })), c + } + } + + function me(t) { + "function" == typeof t.cancel && t.cancel() + } + + function Oe(t, e) { + if (null == t) return !1; + if (void 0 !== e) { + if (!1 === yr(t)) return !1; + if (!t[_].values.has(e)) return !1; + var r = vr(t, e); + return kt(r) + } + return kt(t) + } + + function _e(t) { + return arguments.length > 1 ? a(!1) : Oe(t) + } + + function we(t, e) { + return "string" != typeof e ? a(!1) : Oe(t, e) + } + + function xe(t, e) { + return null != t && (void 0 !== e ? !!yr(t) && t[_].values.has(e) : yr(t) || !!t[_] || x(t) || Kt(t) || kt(t)) + } + + function je(t) { + return 1 !== arguments.length && a(!1), xe(t) + } + + function Ee(t) { + return yr(t) ? t[_].getKeys() : ir(t) || cr(t) ? Array.from(t.keys()) : er(t) ? t.map((function (t, e) { + return e + })) : a(!1) + } + + function Se(t) { + return yr(t) ? Ee(t).map((function (e) { + return t[e] + })) : ir(t) ? Ee(t).map((function (e) { + return t.get(e) + })) : cr(t) ? Array.from(t.values()) : er(t) ? t.slice() : a(!1) + } + + function Pe(t) { + return yr(t) ? Ee(t).map((function (e) { + return [e, t[e]] + })) : ir(t) ? Ee(t).map((function (e) { + return [e, t.get(e)] + })) : cr(t) ? Array.from(t.entries()) : er(t) ? t.map((function (t, e) { + return [e, t] + })) : a(!1) + } + + function Ae(t, e, r) { + if (2 !== arguments.length || cr(t)) if (yr(t)) { + var n = t[_], o = n.values.get(e); + o ? n.write(e, r) : n.addObservableProp(e, r, n.defaultEnhancer) + } else if (ir(t)) t.set(e, r); else if (cr(t)) t.add(e); else { + if (!er(t)) return a(!1); + "number" != typeof e && (e = parseInt(e, 10)), c(e >= 0, "Not a valid index: '" + e + "'"), Bt(), e >= t.length && (t.length = e + 1), t[e] = r, Ut() + } else { + Bt(); + var i = e; + try { + for (var u in i) Ae(t, u, i[u]) + } finally { + Ut() + } + } + } + + function ke(t, e, r, n) { + return "function" == typeof r ? function (t, e, r, n) { + return gr(t, e).observe(r, n) + }(t, e, r, n) : function (t, e, r) { + return gr(t).observe(e, r) + }(t, e, r) + } + + ge.prototype = Object.create(Error.prototype); + var De = {detectCycles: !0, exportMapsAsObjects: !0, recurseEverything: !1}; + + function Te(t, e, r, n) { + return n.detectCycles && t.set(e, r), r + } + + function Me(t, e, r) { + if (!e.recurseEverything && !je(t)) return t; + if ("object" != typeof t) return t; + if (null === t) return null; + if (t instanceof Date) return t; + if (Pt(t)) return Me(t.get(), e, r); + if (je(t) && Ee(t), !0 === e.detectCycles && null !== t && r.has(t)) return r.get(t); + if (er(t) || Array.isArray(t)) { + var n = Te(r, t, [], e), o = t.map((function (t) { + return Me(t, e, r) + })); + n.length = o.length; + for (var i = 0, u = o.length; i < u; i++) n[i] = o[i]; + return n + } + if (cr(t) || Object.getPrototypeOf(t) === Set.prototype) { + if (!1 === e.exportMapsAsObjects) { + var a = Te(r, t, new Set, e); + return t.forEach((function (t) { + a.add(Me(t, e, r)) + })), a + } + var c = Te(r, t, [], e); + return t.forEach((function (t) { + c.push(Me(t, e, r)) + })), c + } + if (ir(t) || Object.getPrototypeOf(t) === Map.prototype) { + if (!1 === e.exportMapsAsObjects) { + var s = Te(r, t, new Map, e); + return t.forEach((function (t, n) { + s.set(n, Me(t, e, r)) + })), s + } + var l = Te(r, t, {}, e); + return t.forEach((function (t, n) { + l[n] = Me(t, e, r) + })), l + } + var f = Te(r, t, {}, e); + return g(t).forEach((function (n) { + f[n] = Me(t[n], e, r) + })), f + } + + function Ne(t, e) { + var r; + return "boolean" == typeof e && (e = {detectCycles: e}), e || (e = De), e.detectCycles = void 0 === e.detectCycles ? !0 === e.recurseEverything : !0 === e.detectCycles, e.detectCycles && (r = new Map), Me(t, e, r) + } + + function Ce(t) { + switch (t.length) { + case 0: + return Rt.trackingDerivation; + case 1: + return vr(t[0]); + case 2: + return vr(t[0], t[1]) + } + } + + function Re(t, e) { + void 0 === e && (e = void 0), Bt(); + try { + return t.apply(e) + } finally { + Ut() + } + } + + function Ie(t, e, r) { + return 1 === arguments.length || e && "object" == typeof e ? ze(t, e) : Le(t, e, r || {}) + } + + function Le(t, e, r) { + var n; + "number" == typeof r.timeout && (n = setTimeout((function () { + if (!i[_].isDisposed) { + i(); + var t = new Error("WHEN_TIMEOUT"); + if (!r.onError) throw t; + r.onError(t) + } + }), r.timeout)), r.name = r.name || "When@" + u(); + var o = mt(r.name + "-effect", e), i = oe((function (e) { + t() && (e.dispose(), n && clearTimeout(n), o()) + }), r); + return i + } + + function ze(t, e) { + var r; + var n = new Promise((function (n, o) { + var i = Le(t, n, P(P({}, e), {onError: o})); + r = function () { + i(), o("WHEN_CANCELLED") + } + })); + return n.cancel = r, n + } + + function Be(t) { + return t[_] + } + + function Ue(t) { + return "string" == typeof t || "number" == typeof t || "symbol" == typeof t + } + + var Fe = { + has: function (t, e) { + if (e === _ || "constructor" === e || e === T) return !0; + var r = Be(t); + return Ue(e) ? r.has(e) : e in t + }, get: function (t, e) { + if (e === _ || "constructor" === e || e === T) return t[e]; + var r = Be(t), n = r.values.get(e); + if (n instanceof w) { + var o = n.get(); + return void 0 === o && r.has(e), o + } + return Ue(e) && r.has(e), t[e] + }, set: function (t, e, r) { + return !!Ue(e) && (Ae(t, e, r), !0) + }, deleteProperty: function (t, e) { + return !!Ue(e) && (Be(t).remove(e), !0) + }, ownKeys: function (t) { + return Be(t).keysAtom.reportObserved(), Reflect.ownKeys(t) + }, preventExtensions: function (t) { + return a("Dynamic observable objects cannot be frozen"), !1 + } + }; + + function He(t) { + var e = new Proxy(t, Fe); + return t[_].proxy = e, e + } + + function Xe(t) { + return void 0 !== t.interceptors && t.interceptors.length > 0 + } + + function Ge(t, e) { + var r = t.interceptors || (t.interceptors = []); + return r.push(e), s((function () { + var t = r.indexOf(e); + -1 !== t && r.splice(t, 1) + })) + } + + function Ye(t, e) { + var r = ft(); + try { + for (var n = D(t.interceptors || []), o = 0, i = n.length; o < i && (c(!(e = n[o](e)) || e.type, "Intercept handlers should return nothing or a change object"), e); o++) ; + return e + } finally { + pt(r) + } + } + + function Ve(t) { + return void 0 !== t.changeListeners && t.changeListeners.length > 0 + } + + function We(t, e) { + var r = t.changeListeners || (t.changeListeners = []); + return r.push(e), s((function () { + var t = r.indexOf(e); + -1 !== t && r.splice(t, 1) + })) + } + + function Ke(t, e) { + var r = ft(), n = t.changeListeners; + if (n) { + for (var o = 0, i = (n = n.slice()).length; o < i; o++) n[o](e); + pt(r) + } + } + + var $e = { + get: function (t, e) { + return e === _ ? t[_] : "length" === e ? t[_].getArrayLength() : "number" == typeof e ? Je.get.call(t, e) : "string" != typeof e || isNaN(e) ? Je.hasOwnProperty(e) ? Je[e] : t[e] : Je.get.call(t, parseInt(e)) + }, set: function (t, e, r) { + return "length" === e && t[_].setArrayLength(r), "number" == typeof e && Je.set.call(t, e, r), "symbol" == typeof e || isNaN(e) ? t[e] = r : Je.set.call(t, parseInt(e), r), !0 + }, preventExtensions: function (t) { + return a("Observable arrays cannot be frozen"), !1 + } + }; + + function Ze(t, e, r, n) { + void 0 === r && (r = "ObservableArray@" + u()), void 0 === n && (n = !1); + var o, i, a, c = new qe(r, e, n); + o = c.values, i = _, a = c, Object.defineProperty(o, i, { + enumerable: !1, + writable: !1, + configurable: !0, + value: a + }); + var s = new Proxy(c.values, $e); + if (c.proxy = s, t && t.length) { + var l = jt(!0); + c.spliceWithArray(0, 0, t), Et(l) + } + return s + } + + var qe = function () { + function t(t, e, r) { + this.owned = r, this.values = [], this.proxy = void 0, this.lastKnownLength = 0, this.atom = new w(t || "ObservableArray@" + u()), this.enhancer = function (r, n) { + return e(r, n, t + "[..]") + } + } + + return t.prototype.dehanceValue = function (t) { + return void 0 !== this.dehancer ? this.dehancer(t) : t + }, t.prototype.dehanceValues = function (t) { + return void 0 !== this.dehancer && t.length > 0 ? t.map(this.dehancer) : t + }, t.prototype.intercept = function (t) { + return Ge(this, t) + }, t.prototype.observe = function (t, e) { + return void 0 === e && (e = !1), e && t({ + object: this.proxy, + type: "splice", + index: 0, + added: this.values.slice(), + addedCount: this.values.length, + removed: [], + removedCount: 0 + }), We(this, t) + }, t.prototype.getArrayLength = function () { + return this.atom.reportObserved(), this.values.length + }, t.prototype.setArrayLength = function (t) { + if ("number" != typeof t || t < 0) throw new Error("[mobx.array] Out of range: " + t); + var e = this.values.length; + if (t !== e) if (t > e) { + for (var r = new Array(t - e), n = 0; n < t - e; n++) r[n] = void 0; + this.spliceWithArray(e, 0, r) + } else this.spliceWithArray(t, e - t) + }, t.prototype.updateArrayLength = function (t, e) { + if (t !== this.lastKnownLength) throw new Error("[mobx] Modification exception: the internal structure of an observable array was changed."); + this.lastKnownLength += e + }, t.prototype.spliceWithArray = function (t, e, r) { + var n = this; + at(this.atom); + var i = this.values.length; + if (void 0 === t ? t = 0 : t > i ? t = i : t < 0 && (t = Math.max(0, i + t)), e = 1 === arguments.length ? i - t : null == e ? 0 : Math.max(0, Math.min(e, i - t)), void 0 === r && (r = o), Xe(this)) { + var u = Ye(this, {object: this.proxy, type: "splice", index: t, removedCount: e, added: r}); + if (!u) return o; + e = u.removedCount, r = u.added + } + r = 0 === r.length ? r : r.map((function (t) { + return n.enhancer(t, void 0) + })); + var a = this.spliceItemsIntoValues(t, e, r); + return 0 === e && 0 === r.length || this.notifyArraySplice(t, r, a), this.dehanceValues(a) + }, t.prototype.spliceItemsIntoValues = function (t, e, r) { + var n; + if (r.length < 1e4) return (n = this.values).splice.apply(n, D([t, e], r)); + var o = this.values.slice(t, t + e); + return this.values = this.values.slice(0, t).concat(r, this.values.slice(t + e)), o + }, t.prototype.notifyArrayChildUpdate = function (t, e, r) { + var n = !this.owned && !1, o = Ve(this), + i = o || n ? {object: this.proxy, type: "update", index: t, newValue: e, oldValue: r} : null; + this.atom.reportChanged(), o && Ke(this, i) + }, t.prototype.notifyArraySplice = function (t, e, r) { + var n = !this.owned && !1, o = Ve(this), i = o || n ? { + object: this.proxy, + type: "splice", + index: t, + removed: r, + added: e, + removedCount: r.length, + addedCount: e.length + } : null; + this.atom.reportChanged(), o && Ke(this, i) + }, t + }(), Je = { + intercept: function (t) { + return this[_].intercept(t) + }, observe: function (t, e) { + return void 0 === e && (e = !1), this[_].observe(t, e) + }, clear: function () { + return this.splice(0) + }, replace: function (t) { + var e = this[_]; + return e.spliceWithArray(0, e.values.length, t) + }, toJS: function () { + return this.slice() + }, toJSON: function () { + return this.toJS() + }, splice: function (t, e) { + for (var r = [], n = 2; n < arguments.length; n++) r[n - 2] = arguments[n]; + var o = this[_]; + switch (arguments.length) { + case 0: + return []; + case 1: + return o.spliceWithArray(t); + case 2: + return o.spliceWithArray(t, e) + } + return o.spliceWithArray(t, e, r) + }, spliceWithArray: function (t, e, r) { + return this[_].spliceWithArray(t, e, r) + }, push: function () { + for (var t = [], e = 0; e < arguments.length; e++) t[e] = arguments[e]; + var r = this[_]; + return r.spliceWithArray(r.values.length, 0, t), r.values.length + }, pop: function () { + return this.splice(Math.max(this[_].values.length - 1, 0), 1)[0] + }, shift: function () { + return this.splice(0, 1)[0] + }, unshift: function () { + for (var t = [], e = 0; e < arguments.length; e++) t[e] = arguments[e]; + var r = this[_]; + return r.spliceWithArray(0, 0, t), r.values.length + }, reverse: function () { + var t = this.slice(); + return t.reverse.apply(t, arguments) + }, sort: function (t) { + var e = this.slice(); + return e.sort.apply(e, arguments) + }, remove: function (t) { + var e = this[_], r = e.dehanceValues(e.values).indexOf(t); + return r > -1 && (this.splice(r, 1), !0) + }, get: function (t) { + var e = this[_]; + if (e && t < e.values.length) return e.atom.reportObserved(), e.dehanceValue(e.values[t]) + }, set: function (t, e) { + var r = this[_], n = r.values; + if (t < n.length) { + at(r.atom); + var o = n[t]; + if (Xe(r)) { + var i = Ye(r, {type: "update", object: r.proxy, index: t, newValue: e}); + if (!i) return; + e = i.newValue + } + (e = r.enhancer(e, o)) !== o && (n[t] = e, r.notifyArrayChildUpdate(t, e, o)) + } else { + if (t !== n.length) throw new Error("[mobx.array] Index out of bounds, " + t + " is larger than " + n.length); + r.spliceWithArray(t, 0, [e]) + } + } + }; + ["concat", "flat", "includes", "indexOf", "join", "lastIndexOf", "slice", "toString", "toLocaleString"].forEach((function (t) { + "function" == typeof Array.prototype[t] && (Je[t] = function () { + var e = this[_]; + e.atom.reportObserved(); + var r = e.dehanceValues(e.values); + return r[t].apply(r, arguments) + }) + })), ["every", "filter", "find", "findIndex", "flatMap", "forEach", "map", "some"].forEach((function (t) { + "function" == typeof Array.prototype[t] && (Je[t] = function (e, r) { + var n = this, o = this[_]; + return o.atom.reportObserved(), o.dehanceValues(o.values)[t]((function (t, o) { + return e.call(r, t, o, n) + }), r) + }) + })), ["reduce", "reduceRight"].forEach((function (t) { + Je[t] = function () { + var e = this, r = this[_]; + r.atom.reportObserved(); + var n = arguments[0]; + return arguments[0] = function (t, o, i) { + return o = r.dehanceValue(o), n(t, o, i, e) + }, r.values[t].apply(r.values, arguments) + } + })); + var Qe, tr = h("ObservableArrayAdministration", qe); + + function er(t) { + return f(t) && tr(t[_]) + } + + var rr, nr = {}, or = function () { + function t(t, e, r) { + if (void 0 === e && (e = B), void 0 === r && (r = "ObservableMap@" + u()), this.enhancer = e, this.name = r, this[Qe] = nr, this._keysAtom = j(this.name + ".keys()"), this[Symbol.toStringTag] = "Map", "function" != typeof Map) throw new Error("mobx.map requires Map polyfill for the current browser. Check babel-polyfill or core-js/es6/map.js"); + this._data = new Map, this._hasMap = new Map, this.merge(t) + } + + return t.prototype._has = function (t) { + return this._data.has(t) + }, t.prototype.has = function (t) { + var e = this; + if (!Rt.trackingDerivation) return this._has(t); + var r = this._hasMap.get(t); + if (!r) { + var n = r = new St(this._has(t), U, this.name + "." + b(t) + "?", !1); + this._hasMap.set(t, n), ce(n, (function () { + return e._hasMap.delete(t) + })) + } + return r.get() + }, t.prototype.set = function (t, e) { + var r = this._has(t); + if (Xe(this)) { + var n = Ye(this, {type: r ? "update" : "add", object: this, newValue: e, name: t}); + if (!n) return this; + e = n.newValue + } + return r ? this._updateValue(t, e) : this._addValue(t, e), this + }, t.prototype.delete = function (t) { + var e = this; + if ((at(this._keysAtom), Xe(this)) && !(n = Ye(this, { + type: "delete", + object: this, + name: t + }))) return !1; + if (this._has(t)) { + var r = Ve(this), + n = r ? {type: "delete", object: this, oldValue: this._data.get(t).value, name: t} : null; + return Re((function () { + e._keysAtom.reportChanged(), e._updateHasMapEntry(t, !1), e._data.get(t).setNewValue(void 0), e._data.delete(t) + })), r && Ke(this, n), !0 + } + return !1 + }, t.prototype._updateHasMapEntry = function (t, e) { + var r = this._hasMap.get(t); + r && r.setNewValue(e) + }, t.prototype._updateValue = function (t, e) { + var r = this._data.get(t); + if ((e = r.prepareNewValue(e)) !== Rt.UNCHANGED) { + var n = !1, o = Ve(this), + i = o ? {type: "update", object: this, oldValue: r.value, name: t, newValue: e} : null; + n, r.setNewValue(e), o && Ke(this, i) + } + }, t.prototype._addValue = function (t, e) { + var r = this; + at(this._keysAtom), Re((function () { + var n = new St(e, r.enhancer, r.name + "." + b(t), !1); + r._data.set(t, n), e = n.value, r._updateHasMapEntry(t, !0), r._keysAtom.reportChanged() + })); + var n = !1, o = Ve(this), i = o ? {type: "add", object: this, name: t, newValue: e} : null; + o && Ke(this, i) + }, t.prototype.get = function (t) { + return this.has(t) ? this.dehanceValue(this._data.get(t).get()) : this.dehanceValue(void 0) + }, t.prototype.dehanceValue = function (t) { + return void 0 !== this.dehancer ? this.dehancer(t) : t + }, t.prototype.keys = function () { + return this._keysAtom.reportObserved(), this._data.keys() + }, t.prototype.values = function () { + var t = this, e = this.keys(); + return xr({ + next: function () { + var r = e.next(), n = r.done, o = r.value; + return {done: n, value: n ? void 0 : t.get(o)} + } + }) + }, t.prototype.entries = function () { + var t = this, e = this.keys(); + return xr({ + next: function () { + var r = e.next(), n = r.done, o = r.value; + return {done: n, value: n ? void 0 : [o, t.get(o)]} + } + }) + }, t.prototype[(Qe = _, Symbol.iterator)] = function () { + return this.entries() + }, t.prototype.forEach = function (t, e) { + var r, n; + try { + for (var o = A(this), i = o.next(); !i.done; i = o.next()) { + var u = k(i.value, 2), a = u[0], c = u[1]; + t.call(e, c, a, this) + } + } catch (t) { + r = {error: t} + } finally { + try { + i && !i.done && (n = o.return) && n.call(o) + } finally { + if (r) throw r.error + } + } + }, t.prototype.merge = function (t) { + var e = this; + return ir(t) && (t = t.toJS()), Re((function () { + var r = jt(!0); + try { + p(t) ? g(t).forEach((function (r) { + return e.set(r, t[r]) + })) : Array.isArray(t) ? t.forEach((function (t) { + var r = k(t, 2), n = r[0], o = r[1]; + return e.set(n, o) + })) : y(t) ? (t.constructor !== Map && a("Cannot initialize from classes that inherit from Map: " + t.constructor.name), t.forEach((function (t, r) { + return e.set(r, t) + }))) : null != t && a("Cannot initialize map from " + t) + } finally { + Et(r) + } + })), this + }, t.prototype.clear = function () { + var t = this; + Re((function () { + lt((function () { + var e, r; + try { + for (var n = A(t.keys()), o = n.next(); !o.done; o = n.next()) { + var i = o.value; + t.delete(i) + } + } catch (t) { + e = {error: t} + } finally { + try { + o && !o.done && (r = n.return) && r.call(n) + } finally { + if (e) throw e.error + } + } + })) + })) + }, t.prototype.replace = function (t) { + var e = this; + return Re((function () { + var r, n, o, i, u = function (t) { + if (y(t) || ir(t)) return t; + if (Array.isArray(t)) return new Map(t); + if (p(t)) { + var e = new Map; + for (var r in t) e.set(r, t[r]); + return e + } + return a("Cannot convert to map from '" + t + "'") + }(t), c = new Map, s = !1; + try { + for (var l = A(e._data.keys()), f = l.next(); !f.done; f = l.next()) { + var d = f.value; + if (!u.has(d)) if (e.delete(d)) s = !0; else { + var h = e._data.get(d); + c.set(d, h) + } + } + } catch (t) { + r = {error: t} + } finally { + try { + f && !f.done && (n = l.return) && n.call(l) + } finally { + if (r) throw r.error + } + } + try { + for (var v = A(u.entries()), g = v.next(); !g.done; g = v.next()) { + var b = k(g.value, 2), m = (d = b[0], h = b[1], e._data.has(d)); + if (e.set(d, h), e._data.has(d)) { + var O = e._data.get(d); + c.set(d, O), m || (s = !0) + } + } + } catch (t) { + o = {error: t} + } finally { + try { + g && !g.done && (i = v.return) && i.call(v) + } finally { + if (o) throw o.error + } + } + if (!s) if (e._data.size !== c.size) e._keysAtom.reportChanged(); else for (var _ = e._data.keys(), w = c.keys(), x = _.next(), j = w.next(); !x.done;) { + if (x.value !== j.value) { + e._keysAtom.reportChanged(); + break + } + x = _.next(), j = w.next() + } + e._data = c + })), this + }, Object.defineProperty(t.prototype, "size", { + get: function () { + return this._keysAtom.reportObserved(), this._data.size + }, enumerable: !0, configurable: !0 + }), t.prototype.toPOJO = function () { + var t, e, r = {}; + try { + for (var n = A(this), o = n.next(); !o.done; o = n.next()) { + var i = k(o.value, 2), u = i[0], a = i[1]; + r["symbol" == typeof u ? u : b(u)] = a + } + } catch (e) { + t = {error: e} + } finally { + try { + o && !o.done && (e = n.return) && e.call(n) + } finally { + if (t) throw t.error + } + } + return r + }, t.prototype.toJS = function () { + return new Map(this) + }, t.prototype.toJSON = function () { + return this.toPOJO() + }, t.prototype.toString = function () { + var t = this; + return this.name + "[{ " + Array.from(this.keys()).map((function (e) { + return b(e) + ": " + t.get(e) + })).join(", ") + " }]" + }, t.prototype.observe = function (t, e) { + return We(this, t) + }, t.prototype.intercept = function (t) { + return Ge(this, t) + }, t + }(), ir = h("ObservableMap", or), ur = {}, ar = function () { + function t(t, e, r) { + if (void 0 === e && (e = B), void 0 === r && (r = "ObservableSet@" + u()), this.name = r, this[rr] = ur, this._data = new Set, this._atom = j(this.name), this[Symbol.toStringTag] = "Set", "function" != typeof Set) throw new Error("mobx.set requires Set polyfill for the current browser. Check babel-polyfill or core-js/es6/set.js"); + this.enhancer = function (t, n) { + return e(t, n, r) + }, t && this.replace(t) + } + + return t.prototype.dehanceValue = function (t) { + return void 0 !== this.dehancer ? this.dehancer(t) : t + }, t.prototype.clear = function () { + var t = this; + Re((function () { + lt((function () { + var e, r; + try { + for (var n = A(t._data.values()), o = n.next(); !o.done; o = n.next()) { + var i = o.value; + t.delete(i) + } + } catch (t) { + e = {error: t} + } finally { + try { + o && !o.done && (r = n.return) && r.call(n) + } finally { + if (e) throw e.error + } + } + })) + })) + }, t.prototype.forEach = function (t, e) { + var r, n; + try { + for (var o = A(this), i = o.next(); !i.done; i = o.next()) { + var u = i.value; + t.call(e, u, u, this) + } + } catch (t) { + r = {error: t} + } finally { + try { + i && !i.done && (n = o.return) && n.call(o) + } finally { + if (r) throw r.error + } + } + }, Object.defineProperty(t.prototype, "size", { + get: function () { + return this._atom.reportObserved(), this._data.size + }, enumerable: !0, configurable: !0 + }), t.prototype.add = function (t) { + var e = this; + if ((at(this._atom), Xe(this)) && !(o = Ye(this, { + type: "add", + object: this, + newValue: t + }))) return this; + if (!this.has(t)) { + Re((function () { + e._data.add(e.enhancer(t, void 0)), e._atom.reportChanged() + })); + var r = !1, n = Ve(this), o = n ? {type: "add", object: this, newValue: t} : null; + r, n && Ke(this, o) + } + return this + }, t.prototype.delete = function (t) { + var e = this; + if (Xe(this) && !(n = Ye(this, {type: "delete", object: this, oldValue: t}))) return !1; + if (this.has(t)) { + var r = Ve(this), n = r ? {type: "delete", object: this, oldValue: t} : null; + return Re((function () { + e._atom.reportChanged(), e._data.delete(t) + })), r && Ke(this, n), !0 + } + return !1 + }, t.prototype.has = function (t) { + return this._atom.reportObserved(), this._data.has(this.dehanceValue(t)) + }, t.prototype.entries = function () { + var t = 0, e = Array.from(this.keys()), r = Array.from(this.values()); + return xr({ + next: function () { + var n = t; + return t += 1, n < r.length ? {value: [e[n], r[n]], done: !1} : {done: !0} + } + }) + }, t.prototype.keys = function () { + return this.values() + }, t.prototype.values = function () { + this._atom.reportObserved(); + var t = this, e = 0, r = Array.from(this._data.values()); + return xr({ + next: function () { + return e < r.length ? {value: t.dehanceValue(r[e++]), done: !1} : {done: !0} + } + }) + }, t.prototype.replace = function (t) { + var e = this; + return cr(t) && (t = t.toJS()), Re((function () { + var r = jt(!0); + try { + Array.isArray(t) || v(t) ? (e.clear(), t.forEach((function (t) { + return e.add(t) + }))) : null != t && a("Cannot initialize set from " + t) + } finally { + Et(r) + } + })), this + }, t.prototype.observe = function (t, e) { + return We(this, t) + }, t.prototype.intercept = function (t) { + return Ge(this, t) + }, t.prototype.toJS = function () { + return new Set(this) + }, t.prototype.toString = function () { + return this.name + "[ " + Array.from(this).join(", ") + " ]" + }, t.prototype[(rr = _, Symbol.iterator)] = function () { + return this.values() + }, t + }(), cr = h("ObservableSet", ar), sr = function () { + function t(t, e, r, n) { + void 0 === e && (e = new Map), this.target = t, this.values = e, this.name = r, this.defaultEnhancer = n, this.keysAtom = new w(r + ".keys") + } + + return t.prototype.read = function (t) { + return this.values.get(t).get() + }, t.prototype.write = function (t, e) { + var r = this.target, n = this.values.get(t); + if (n instanceof At) n.set(e); else { + if (Xe(this)) { + if (!(u = Ye(this, { + type: "update", + object: this.proxy || r, + name: t, + newValue: e + }))) return; + e = u.newValue + } + if ((e = n.prepareNewValue(e)) !== Rt.UNCHANGED) { + var o = Ve(this), i = !1, u = o ? { + type: "update", + object: this.proxy || r, + oldValue: n.value, + name: t, + newValue: e + } : null; + i, n.setNewValue(e), o && Ke(this, u) + } + } + }, t.prototype.has = function (t) { + var e = this.pendingKeys || (this.pendingKeys = new Map), r = e.get(t); + if (r) return r.get(); + var n = !!this.values.get(t); + return r = new St(n, U, this.name + "." + b(t) + "?", !1), e.set(t, r), r.get() + }, t.prototype.addObservableProp = function (t, e, r) { + void 0 === r && (r = this.defaultEnhancer); + var n = this.target; + if (Xe(this)) { + var o = Ye(this, {object: this.proxy || n, name: t, type: "add", newValue: e}); + if (!o) return; + e = o.newValue + } + var i = new St(e, r, this.name + "." + b(t), !1); + this.values.set(t, i), e = i.value, Object.defineProperty(n, t, function (t) { + return fr[t] || (fr[t] = { + configurable: !0, enumerable: !0, get: function () { + return this[_].read(t) + }, set: function (e) { + this[_].write(t, e) + } + }) + }(t)), this.notifyPropertyAddition(t, e) + }, t.prototype.addComputedProp = function (t, e, r) { + var n, o, i, u = this.target; + r.name = r.name || this.name + "." + b(e), this.values.set(e, new At(r)), (t === u || (n = t, o = e, !(i = Object.getOwnPropertyDescriptor(n, o)) || !1 !== i.configurable && !1 !== i.writable)) && Object.defineProperty(t, e, function (t) { + return pr[t] || (pr[t] = { + configurable: Rt.computedConfigurable, + enumerable: !1, + get: function () { + return dr(this).read(t) + }, + set: function (e) { + dr(this).write(t, e) + } + }) + }(e)) + }, t.prototype.remove = function (t) { + if (this.values.has(t)) { + var e = this.target; + if (Xe(this)) if (!(a = Ye(this, {object: this.proxy || e, name: t, type: "remove"}))) return; + try { + Bt(); + var r = Ve(this), n = !1, o = this.values.get(t), i = o && o.get(); + if (o && o.set(void 0), this.keysAtom.reportChanged(), this.values.delete(t), this.pendingKeys) { + var u = this.pendingKeys.get(t); + u && u.set(!1) + } + delete this.target[t]; + var a = r ? {type: "remove", object: this.proxy || e, oldValue: i, name: t} : null; + n, r && Ke(this, a) + } finally { + Ut() + } + } + }, t.prototype.illegalAccess = function (t, e) { + }, t.prototype.observe = function (t, e) { + return We(this, t) + }, t.prototype.intercept = function (t) { + return Ge(this, t) + }, t.prototype.notifyPropertyAddition = function (t, e) { + var r = Ve(this), + n = r ? {type: "add", object: this.proxy || this.target, name: t, newValue: e} : null; + if (r && Ke(this, n), this.pendingKeys) { + var o = this.pendingKeys.get(t); + o && o.set(!0) + } + this.keysAtom.reportChanged() + }, t.prototype.getKeys = function () { + var t, e; + this.keysAtom.reportObserved(); + var r = []; + try { + for (var n = A(this.values), o = n.next(); !o.done; o = n.next()) { + var i = k(o.value, 2), u = i[0]; + i[1] instanceof St && r.push(u) + } + } catch (e) { + t = {error: e} + } finally { + try { + o && !o.done && (e = n.return) && e.call(n) + } finally { + if (t) throw t.error + } + } + return r + }, t + }(); + + function lr(t, e, r) { + if (void 0 === e && (e = ""), void 0 === r && (r = B), Object.prototype.hasOwnProperty.call(t, _)) return t[_]; + p(t) || (e = (t.constructor.name || "ObservableObject") + "@" + u()), e || (e = "ObservableObject@" + u()); + var n = new sr(t, new Map, b(e), r); + return d(t, _, n), n + } + + var fr = Object.create(null), pr = Object.create(null); + + function dr(t) { + var e = t[_]; + return e || (I(t), t[_]) + } + + var hr = h("ObservableObjectAdministration", sr); + + function yr(t) { + return !!f(t) && (I(t), hr(t[_])) + } + + function vr(t, e) { + if ("object" == typeof t && null !== t) { + if (er(t)) return void 0 !== e && a(!1), t[_].atom; + if (cr(t)) return t[_]; + if (ir(t)) { + var r = t; + return void 0 === e ? r._keysAtom : ((n = r._data.get(e) || r._hasMap.get(e)) || a(!1), n) + } + var n; + if (I(t), e && !t[_] && t[e], yr(t)) return e ? ((n = t[_].values.get(e)) || a(!1), n) : a(!1); + if (x(t) || kt(t) || Kt(t)) return t + } else if ("function" == typeof t && Kt(t[_])) return t[_]; + return a(!1) + } + + function gr(t, e) { + return t || a("Expecting some object"), void 0 !== e ? gr(vr(t, e)) : x(t) || kt(t) || Kt(t) || ir(t) || cr(t) ? t : (I(t), t[_] ? t[_] : void a(!1)) + } + + var br = Object.prototype.toString; + + function mr(t, e, r) { + return void 0 === r && (r = -1), Or(t, e, r) + } + + function Or(t, e, r, n, o) { + if (t === e) return 0 !== t || 1 / t == 1 / e; + if (null == t || null == e) return !1; + if (t != t) return e != e; + var i = typeof t; + if ("function" !== i && "object" !== i && "object" != typeof e) return !1; + var u = br.call(t); + if (u !== br.call(e)) return !1; + switch (u) { + case"[object RegExp]": + case"[object String]": + return "" + t == "" + e; + case"[object Number]": + return +t != +t ? +e != +e : 0 == +t ? 1 / +t == 1 / e : +t == +e; + case"[object Date]": + case"[object Boolean]": + return +t == +e; + case"[object Symbol]": + return "undefined" != typeof Symbol && Symbol.valueOf.call(t) === Symbol.valueOf.call(e); + case"[object Map]": + case"[object Set]": + r >= 0 && r++ + } + t = _r(t), e = _r(e); + var a = "[object Array]" === u; + if (!a) { + if ("object" != typeof t || "object" != typeof e) return !1; + var c = t.constructor, s = e.constructor; + if (c !== s && !("function" == typeof c && c instanceof c && "function" == typeof s && s instanceof s) && "constructor" in t && "constructor" in e) return !1 + } + if (0 === r) return !1; + r < 0 && (r = -1), o = o || []; + for (var l = (n = n || []).length; l--;) if (n[l] === t) return o[l] === e; + if (n.push(t), o.push(e), a) { + if ((l = t.length) !== e.length) return !1; + for (; l--;) if (!Or(t[l], e[l], r - 1, n, o)) return !1 + } else { + var f = Object.keys(t), p = void 0; + if (l = f.length, Object.keys(e).length !== l) return !1; + for (; l--;) if (!wr(e, p = f[l]) || !Or(t[p], e[p], r - 1, n, o)) return !1 + } + return n.pop(), o.pop(), !0 + } + + function _r(t) { + return er(t) ? t.slice() : y(t) || ir(t) || v(t) || cr(t) ? Array.from(t.entries()) : t + } + + function wr(t, e) { + return Object.prototype.hasOwnProperty.call(t, e) + } + + function xr(t) { + return t[Symbol.iterator] = jr, t + } + + function jr() { + return this + } + + if ("undefined" == typeof Proxy || "undefined" == typeof Symbol) throw new Error("[mobx] MobX 5+ requires Proxy and Symbol objects. If your environment doesn't support Symbol or Proxy objects, please downgrade to MobX 4. For React Native Android, consider upgrading JSCore."); + "object" == typeof __MOBX_DEVTOOLS_GLOBAL_HOOK__ && __MOBX_DEVTOOLS_GLOBAL_HOOK__.injectMobx({ + spy: Zt, + extras: { + getDebugName: function (t, e) { + return (void 0 !== e ? vr(t, e) : yr(t) || ir(t) || cr(t) ? gr(t) : vr(t)).name + } + }, + $mobx: _ + }) + }).call(this, r(160), r(66)) + }, function (t, e, r) { + var n = r(113), o = r(42), i = r(179); + n || o(Object.prototype, "toString", i, {unsafe: !0}) + }, function (t, e, r) { + "use strict"; + var n = r(41), o = r(100), i = r(78), u = r(58), a = r(116), c = "Array Iterator", s = u.set, + l = u.getterFor(c); + t.exports = a(Array, "Array", (function (t, e) { + s(this, {type: c, target: n(t), index: 0, kind: e}) + }), (function () { + var t = l(this), e = t.target, r = t.kind, n = t.index++; + return !e || n >= e.length ? (t.target = void 0, {value: void 0, done: !0}) : "keys" == r ? { + value: n, + done: !1 + } : "values" == r ? {value: e[n], done: !1} : {value: [n, e[n]], done: !1} + }), "values"), i.Arguments = i.Array, o("keys"), o("values"), o("entries") + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(7), i = r(46), u = r(74), a = r(34), c = r(15), s = r(69), l = r(36), f = r(108), + p = r(18), d = r(35), h = r(96), y = r(30), v = r(33), g = r(54), b = r(87), m = r(32), O = r(40), + _ = r(41), w = r(86), x = r(39), j = r(67), E = r(60), S = r(75), P = r(72), A = r(139), k = r(112), + D = r(50), T = r(38), M = r(84), N = r(98), C = r(42), R = r(89), I = r(93), L = r(70), z = r(90), + B = r(28), U = r(140), F = r(141), H = r(76), X = r(58), G = r(77).forEach, Y = I("hidden"), V = "Symbol", + W = B("toPrimitive"), K = X.set, $ = X.getterFor(V), Z = Object.prototype, q = o.Symbol, + J = q && q.prototype, Q = o.TypeError, tt = o.QObject, et = i("JSON", "stringify"), rt = D.f, nt = T.f, + ot = A.f, it = M.f, ut = c([].push), at = R("symbols"), ct = R("op-symbols"), + st = R("string-to-symbol-registry"), lt = R("symbol-to-string-registry"), ft = R("wks"), + pt = !tt || !tt.prototype || !tt.prototype.findChild, dt = l && p((function () { + return 7 != E(nt({}, "a", { + get: function () { + return nt(this, "a", {value: 7}).a + } + })).a + })) ? function (t, e, r) { + var n = rt(Z, e); + n && delete Z[e], nt(t, e, r), n && t !== Z && nt(Z, e, n) + } : nt, ht = function (t, e) { + var r = at[t] = E(J); + return K(r, {type: V, tag: t, description: e}), l || (r.description = e), r + }, yt = function (t, e, r) { + t === Z && yt(ct, e, r), m(t); + var n = w(e); + return m(r), d(at, n) ? (r.enumerable ? (d(t, Y) && t[Y][n] && (t[Y][n] = !1), r = E(r, {enumerable: j(0, !1)})) : (d(t, Y) || nt(t, Y, j(1, {})), t[Y][n] = !0), dt(t, n, r)) : nt(t, n, r) + }, vt = function (t, e) { + m(t); + var r = _(e), n = S(r).concat(Ot(r)); + return G(n, (function (e) { + l && !a(gt, r, e) || yt(t, e, r[e]) + })), t + }, gt = function (t) { + var e = w(t), r = a(it, this, e); + return !(this === Z && d(at, e) && !d(ct, e)) && (!(r || !d(this, e) || !d(at, e) || d(this, Y) && this[Y][e]) || r) + }, bt = function (t, e) { + var r = _(t), n = w(e); + if (r !== Z || !d(at, n) || d(ct, n)) { + var o = rt(r, n); + return !o || !d(at, n) || d(r, Y) && r[Y][n] || (o.enumerable = !0), o + } + }, mt = function (t) { + var e = ot(_(t)), r = []; + return G(e, (function (t) { + d(at, t) || d(L, t) || ut(r, t) + })), r + }, Ot = function (t) { + var e = t === Z, r = ot(e ? ct : _(t)), n = []; + return G(r, (function (t) { + !d(at, t) || e && !d(Z, t) || ut(n, at[t]) + })), n + }; + (f || (q = function () { + if (g(J, this)) throw Q("Symbol is not a constructor"); + var t = arguments.length && void 0 !== arguments[0] ? x(arguments[0]) : void 0, e = z(t), r = function (t) { + this === Z && a(r, ct, t), d(this, Y) && d(this[Y], e) && (this[Y][e] = !1), dt(this, e, j(1, t)) + }; + return l && pt && dt(Z, e, {configurable: !0, set: r}), ht(e, t) + }, C(J = q.prototype, "toString", (function () { + return $(this).tag + })), C(q, "withoutSetter", (function (t) { + return ht(z(t), t) + })), M.f = gt, T.f = yt, D.f = bt, P.f = A.f = mt, k.f = Ot, U.f = function (t) { + return ht(B(t), t) + }, l && (nt(J, "description", { + configurable: !0, get: function () { + return $(this).description + } + }), s || C(Z, "propertyIsEnumerable", gt, {unsafe: !0}))), n({ + global: !0, + wrap: !0, + forced: !f, + sham: !f + }, {Symbol: q}), G(S(ft), (function (t) { + F(t) + })), n({target: V, stat: !0, forced: !f}, { + for: function (t) { + var e = x(t); + if (d(st, e)) return st[e]; + var r = q(e); + return st[e] = r, lt[r] = e, r + }, keyFor: function (t) { + if (!b(t)) throw Q(t + " is not a symbol"); + if (d(lt, t)) return lt[t] + }, useSetter: function () { + pt = !0 + }, useSimple: function () { + pt = !1 + } + }), n({target: "Object", stat: !0, forced: !f, sham: !l}, { + create: function (t, e) { + return void 0 === e ? E(t) : vt(E(t), e) + }, defineProperty: yt, defineProperties: vt, getOwnPropertyDescriptor: bt + }), n({target: "Object", stat: !0, forced: !f}, { + getOwnPropertyNames: mt, + getOwnPropertySymbols: Ot + }), n({ + target: "Object", stat: !0, forced: p((function () { + k.f(1) + })) + }, { + getOwnPropertySymbols: function (t) { + return k.f(O(t)) + } + }), et) && n({ + target: "JSON", stat: !0, forced: !f || p((function () { + var t = q(); + return "[null]" != et([t]) || "{}" != et({a: t}) || "{}" != et(Object(t)) + })) + }, { + stringify: function (t, e, r) { + var n = N(arguments), o = e; + if ((v(e) || void 0 !== t) && !b(t)) return h(e) || (e = function (t, e) { + if (y(o) && (e = a(o, this, t, e)), !b(e)) return e + }), n[1] = e, u(et, null, n) + } + }); + if (!J[W]) { + var _t = J.valueOf; + C(J, W, (function (t) { + return a(_t, this) + })) + } + H(q, V), L[Y] = !0 + }, function (t, e, r) { + var n = r(7), o = r(152), i = r(153), u = r(3), a = r(57), c = r(28), s = c("iterator"), l = c("toStringTag"), + f = u.values, p = function (t, e) { + if (t) { + if (t[s] !== f) try { + a(t, s, f) + } catch (e) { + t[s] = f + } + if (t[l] || a(t, l, e), o[e]) for (var r in u) if (t[r] !== u[r]) try { + a(t, r, u[r]) + } catch (e) { + t[r] = u[r] + } + } + }; + for (var d in o) p(n[d] && n[d].prototype, d); + p(i, "DOMTokenList") + }, function (t, e, r) { + "use strict"; + var n = r(151).charAt, o = r(39), i = r(58), u = r(116), a = "String Iterator", c = i.set, s = i.getterFor(a); + u(String, "String", (function (t) { + c(this, {type: a, string: o(t), index: 0}) + }), (function () { + var t, e = s(this), r = e.string, o = e.index; + return o >= r.length ? {value: void 0, done: !0} : (t = n(r, o), e.index += t.length, {value: t, done: !1}) + })) + }, function (t, e, r) { + (function (e) { + var r = function (t) { + return t && t.Math == Math && t + }; + t.exports = r("object" == typeof globalThis && globalThis) || r("object" == typeof window && window) || r("object" == typeof self && self) || r("object" == typeof e && e) || function () { + return this + }() || Function("return this")() + }).call(this, r(66)) + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(36), i = r(7), u = r(15), a = r(35), c = r(30), s = r(54), l = r(39), f = r(38).f, + p = r(134), d = i.Symbol, h = d && d.prototype; + if (o && c(d) && (!("description" in h) || void 0 !== d().description)) { + var y = {}, v = function () { + var t = arguments.length < 1 || void 0 === arguments[0] ? void 0 : l(arguments[0]), + e = s(h, this) ? new d(t) : void 0 === t ? d() : d(t); + return "" === t && (y[e] = !0), e + }; + p(v, d), v.prototype = h, h.constructor = v; + var g = "Symbol(test)" == String(d("test")), b = u(h.toString), m = u(h.valueOf), + O = /^Symbol\((.*)\)[^)]+$/, _ = u("".replace), w = u("".slice); + f(h, "description", { + configurable: !0, get: function () { + var t = m(this), e = b(t); + if (a(y, t)) return ""; + var r = g ? w(e, 7, -1) : _(e, O, "$1"); + return "" === r ? void 0 : r + } + }), n({global: !0, forced: !0}, {Symbol: v}) + } + }, function (t, e, r) { + r(141)("iterator") + }, function (t, e, r) { + "use strict"; + r.d(e, "a", (function () { + return u.a + })), r.d(e, "c", (function () { + return u.e + })), r.d(e, "h", (function () { + return O + })), r.d(e, "i", (function () { + return g + })), r.d(e, "j", (function () { + return y + })), r.d(e, "b", (function () { + return D + })), r.d(e, "e", (function () { + return C + })), r.d(e, "f", (function () { + return T + })), r.d(e, "g", (function () { + return at + })); + var n, o, i, u = r(0), a = 0, c = [], s = u.i.__b, l = u.i.__r, f = u.i.diffed, p = u.i.__c, d = u.i.unmount; + + function h(t, e) { + u.i.__h && u.i.__h(o, t, a || e), a = 0; + var r = o.__H || (o.__H = {__: [], __h: []}); + return t >= r.__.length && r.__.push({}), r.__[t] + } + + function y(t) { + return a = 1, v(P, t) + } + + function v(t, e, r) { + var i = h(n++, 2); + return i.t = t, i.__c || (i.__ = [r ? r(e) : P(void 0, e), function (t) { + var e = i.t(i.__[0], t); + i.__[0] !== e && (i.__ = [e, i.__[1]], i.__c.setState({})) + }], i.__c = o), i.__ + } + + function g(t, e) { + var r = h(n++, 3); + !u.i.__s && S(r.__H, e) && (r.__ = t, r.__H = e, o.__H.__h.push(r)) + } + + function b(t, e) { + var r = h(n++, 4); + !u.i.__s && S(r.__H, e) && (r.__ = t, r.__H = e, o.__h.push(r)) + } + + function m(t, e) { + var r = h(n++, 7); + return S(r.__H, e) && (r.__ = t(), r.__H = e, r.__h = t), r.__ + } + + function O(t, e) { + return a = 8, m((function () { + return t + }), e) + } + + function _() { + var t; + for (c.sort((function (t, e) { + return t.__v.__b - e.__v.__b + })); t = c.pop();) if (t.__P) try { + t.__H.__h.forEach(j), t.__H.__h.forEach(E), t.__H.__h = [] + } catch (e) { + t.__H.__h = [], u.i.__e(e, t.__v) + } + } + + u.i.__b = function (t) { + o = null, s && s(t) + }, u.i.__r = function (t) { + l && l(t), n = 0; + var e = (o = t.__c).__H; + e && (e.__h.forEach(j), e.__h.forEach(E), e.__h = []) + }, u.i.diffed = function (t) { + f && f(t); + var e = t.__c; + e && e.__H && e.__H.__h.length && (1 !== c.push(e) && i === u.i.requestAnimationFrame || ((i = u.i.requestAnimationFrame) || x)(_)), o = null + }, u.i.__c = function (t, e) { + e.some((function (t) { + try { + t.__h.forEach(j), t.__h = t.__h.filter((function (t) { + return !t.__ || E(t) + })) + } catch (r) { + e.some((function (t) { + t.__h && (t.__h = []) + })), e = [], u.i.__e(r, t.__v) + } + })), p && p(t, e) + }, u.i.unmount = function (t) { + d && d(t); + var e, r = t.__c; + r && r.__H && (r.__H.__.forEach((function (t) { + try { + j(t) + } catch (t) { + e = t + } + })), e && u.i.__e(e, r.__v)) + }; + var w = "function" == typeof requestAnimationFrame; + + function x(t) { + var e, r = function () { + clearTimeout(n), w && cancelAnimationFrame(e), setTimeout(t) + }, n = setTimeout(r, 100); + w && (e = requestAnimationFrame(r)) + } + + function j(t) { + var e = o, r = t.__c; + "function" == typeof r && (t.__c = void 0, r()), o = e + } + + function E(t) { + var e = o; + t.__c = t.__(), o = e + } + + function S(t, e) { + return !t || t.length !== e.length || e.some((function (e, r) { + return e !== t[r] + })) + } + + function P(t, e) { + return "function" == typeof e ? e(t) : e + } + + function A(t, e) { + for (var r in e) t[r] = e[r]; + return t + } + + function k(t, e) { + for (var r in t) if ("__source" !== r && !(r in e)) return !0; + for (var n in e) if ("__source" !== n && t[n] !== e[n]) return !0; + return !1 + } + + function D(t) { + this.props = t + } + + function T(t, e) { + function r(t) { + var r = this.props.ref, n = r == t.ref; + return !n && r && (r.call ? r(null) : r.current = null), e ? !e(this.props, t) || !n : k(this.props, t) + } + + function n(e) { + return this.shouldComponentUpdate = r, Object(u.e)(t, e) + } + + return n.displayName = "Memo(" + (t.displayName || t.name) + ")", n.prototype.isReactComponent = !0, n.__f = !0, n + } + + (D.prototype = new u.a).isPureReactComponent = !0, D.prototype.shouldComponentUpdate = function (t, e) { + return k(this.props, t) || k(this.state, e) + }; + var M = u.i.__b; + u.i.__b = function (t) { + t.type && t.type.__f && t.ref && (t.props.ref = t.ref, t.ref = null), M && M(t) + }; + var N = "undefined" != typeof Symbol && Symbol.for && Symbol.for("react.forward_ref") || 3911; + + function C(t) { + function e(e, r) { + var n = A({}, e); + return delete n.ref, t(n, !(r = e.ref || r) || "object" == typeof r && !("current" in r) ? null : r) + } + + return e.$$typeof = N, e.render = e, e.prototype.isReactComponent = e.__f = !0, e.displayName = "ForwardRef(" + (t.displayName || t.name) + ")", e + } + + var R = function (t, e) { + return null == t ? null : Object(u.k)(Object(u.k)(t).map(e)) + }, I = { + map: R, forEach: R, count: function (t) { + return t ? Object(u.k)(t).length : 0 + }, only: function (t) { + var e = Object(u.k)(t); + if (1 !== e.length) throw"Children.only"; + return e[0] + }, toArray: u.k + }, L = u.i.__e; + u.i.__e = function (t, e, r) { + if (t.then) for (var n, o = e; o = o.__;) if ((n = o.__c) && n.__c) return null == e.__e && (e.__e = r.__e, e.__k = r.__k), n.__c(t, e); + L(t, e, r) + }; + var z = u.i.unmount; + + function B(t, e, r) { + return t && (t.__c && t.__c.__H && (t.__c.__H.__.forEach((function (t) { + "function" == typeof t.__c && t.__c() + })), t.__c.__H = null), null != (t = A({}, t)).__c && (t.__c.__P === r && (t.__c.__P = e), t.__c = null), t.__k = t.__k && t.__k.map((function (t) { + return B(t, e, r) + }))), t + } + + function U(t, e, r) { + return t && (t.__v = null, t.__k = t.__k && t.__k.map((function (t) { + return U(t, e, r) + })), t.__c && t.__c.__P === e && (t.__e && r.insertBefore(t.__e, t.__d), t.__c.__e = !0, t.__c.__P = r)), t + } + + function F() { + this.__u = 0, this.t = null, this.__b = null + } + + function H(t) { + var e = t.__.__c; + return e && e.__e && e.__e(t) + } + + function X() { + this.u = null, this.o = null + } + + u.i.unmount = function (t) { + var e = t.__c; + e && e.__R && e.__R(), e && !0 === t.__h && (t.type = null), z && z(t) + }, (F.prototype = new u.a).__c = function (t, e) { + var r = e.__c, n = this; + null == n.t && (n.t = []), n.t.push(r); + var o = H(n.__v), i = !1, u = function () { + i || (i = !0, r.__R = null, o ? o(a) : a()) + }; + r.__R = u; + var a = function () { + if (!--n.__u) { + if (n.state.__e) { + var t = n.state.__e; + n.__v.__k[0] = U(t, t.__c.__P, t.__c.__O) + } + var e; + for (n.setState({__e: n.__b = null}); e = n.t.pop();) e.forceUpdate() + } + }, c = !0 === e.__h; + n.__u++ || c || n.setState({__e: n.__b = n.__v.__k[0]}), t.then(u, u) + }, F.prototype.componentWillUnmount = function () { + this.t = [] + }, F.prototype.render = function (t, e) { + if (this.__b) { + if (this.__v.__k) { + var r = document.createElement("div"), n = this.__v.__k[0].__c; + this.__v.__k[0] = B(this.__b, r, n.__O = n.__P) + } + this.__b = null + } + var o = e.__e && Object(u.e)(u.b, null, t.fallback); + return o && (o.__h = null), [Object(u.e)(u.b, null, e.__e ? null : t.children), o] + }; + var G = function (t, e, r) { + if (++r[1] === r[0] && t.o.delete(e), t.props.revealOrder && ("t" !== t.props.revealOrder[0] || !t.o.size)) for (r = t.u; r;) { + for (; r.length > 3;) r.pop()(); + if (r[1] < r[0]) break; + t.u = r = r[2] + } + }; + + function Y(t) { + return this.getChildContext = function () { + return t.context + }, t.children + } + + function V(t) { + var e = this, r = t.i; + e.componentWillUnmount = function () { + Object(u.j)(null, e.l), e.l = null, e.i = null + }, e.i && e.i !== r && e.componentWillUnmount(), t.__v ? (e.l || (e.i = r, e.l = { + nodeType: 1, + parentNode: r, + childNodes: [], + appendChild: function (t) { + this.childNodes.push(t), e.i.appendChild(t) + }, + insertBefore: function (t, r) { + this.childNodes.push(t), e.i.appendChild(t) + }, + removeChild: function (t) { + this.childNodes.splice(this.childNodes.indexOf(t) >>> 1, 1), e.i.removeChild(t) + } + }), Object(u.j)(Object(u.e)(Y, {context: e.context}, t.__v), e.l)) : e.l && e.componentWillUnmount() + } + + (X.prototype = new u.a).__e = function (t) { + var e = this, r = H(e.__v), n = e.o.get(t); + return n[0]++, function (o) { + var i = function () { + e.props.revealOrder ? (n.push(o), G(e, t, n)) : o() + }; + r ? r(i) : i() + } + }, X.prototype.render = function (t) { + this.u = null, this.o = new Map; + var e = Object(u.k)(t.children); + t.revealOrder && "b" === t.revealOrder[0] && e.reverse(); + for (var r = e.length; r--;) this.o.set(e[r], this.u = [1, 0, this.u]); + return t.children + }, X.prototype.componentDidUpdate = X.prototype.componentDidMount = function () { + var t = this; + this.o.forEach((function (e, r) { + G(t, r, e) + })) + }; + var W = "undefined" != typeof Symbol && Symbol.for && Symbol.for("react.element") || 60103, + K = /^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|marker(?!H|W|U)|overline|paint|stop|strikethrough|stroke|text(?!L)|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/, + $ = "undefined" != typeof document, Z = function (t) { + return ("undefined" != typeof Symbol && "symbol" == typeof Symbol() ? /fil|che|rad/i : /fil|che|ra/i).test(t) + }; + u.a.prototype.isReactComponent = {}, ["componentWillMount", "componentWillReceiveProps", "componentWillUpdate"].forEach((function (t) { + Object.defineProperty(u.a.prototype, t, { + configurable: !0, get: function () { + return this["UNSAFE_" + t] + }, set: function (e) { + Object.defineProperty(this, t, {configurable: !0, writable: !0, value: e}) + } + }) + })); + var q = u.i.event; + + function J() { + } + + function Q() { + return this.cancelBubble + } + + function tt() { + return this.defaultPrevented + } + + u.i.event = function (t) { + return q && (t = q(t)), t.persist = J, t.isPropagationStopped = Q, t.isDefaultPrevented = tt, t.nativeEvent = t + }; + var et, rt = { + configurable: !0, get: function () { + return this.class + } + }, nt = u.i.vnode; + u.i.vnode = function (t) { + var e = t.type, r = t.props, n = r; + if ("string" == typeof e) { + var o = -1 === e.indexOf("-"); + for (var i in n = {}, r) { + var a = r[i]; + $ && "children" === i && "noscript" === e || "value" === i && "defaultValue" in r && null == a || ("defaultValue" === i && "value" in r && null == r.value ? i = "value" : "download" === i && !0 === a ? a = "" : /ondoubleclick/i.test(i) ? i = "ondblclick" : /^onchange(textarea|input)/i.test(i + e) && !Z(r.type) ? i = "oninput" : /^onfocus$/i.test(i) ? i = "onfocusin" : /^onblur$/i.test(i) ? i = "onfocusout" : /^on(Ani|Tra|Tou|BeforeInp)/.test(i) ? i = i.toLowerCase() : o && K.test(i) ? i = i.replace(/[A-Z0-9]/, "-$&").toLowerCase() : null === a && (a = void 0), n[i] = a) + } + "select" == e && n.multiple && Array.isArray(n.value) && (n.value = Object(u.k)(r.children).forEach((function (t) { + t.props.selected = -1 != n.value.indexOf(t.props.value) + }))), "select" == e && null != n.defaultValue && (n.value = Object(u.k)(r.children).forEach((function (t) { + t.props.selected = n.multiple ? -1 != n.defaultValue.indexOf(t.props.value) : n.defaultValue == t.props.value + }))), t.props = n, r.class != r.className && (rt.enumerable = "className" in r, null != r.className && (n.class = r.className), Object.defineProperty(n, "className", rt)) + } + t.$$typeof = W, nt && nt(t) + }; + var ot = u.i.__r; + u.i.__r = function (t) { + ot && ot(t), et = t.__c + }; + var it = { + ReactCurrentDispatcher: { + current: { + readContext: function (t) { + return et.__n[t.__c].props.value + } + } + } + }; + + function ut(t) { + return !!t && t.$$typeof === W + } + + var at = function (t, e) { + return t(e) + }, ct = u.b, st = { + useState: y, useReducer: v, useEffect: g, useLayoutEffect: b, useRef: function (t) { + return a = 5, m((function () { + return {current: t} + }), []) + }, useImperativeHandle: function (t, e, r) { + a = 6, b((function () { + "function" == typeof t ? t(e()) : t && (t.current = e()) + }), null == r ? r : r.concat(t)) + }, useMemo: m, useCallback: O, useContext: function (t) { + var e = o.context[t.__c], r = h(n++, 9); + return r.c = t, e ? (null == r.__ && (r.__ = !0, e.sub(o)), e.props.value) : t.__ + }, useDebugValue: function (t, e) { + u.i.useDebugValue && u.i.useDebugValue(e ? e(t) : t) + }, version: "17.0.2", Children: I, render: function (t, e, r) { + return null == e.__k && (e.textContent = ""), Object(u.j)(t, e), "function" == typeof r && r(), t ? t.__c : null + }, hydrate: function (t, e, r) { + return Object(u.h)(t, e), "function" == typeof r && r(), t ? t.__c : null + }, unmountComponentAtNode: function (t) { + return !!t.__k && (Object(u.j)(null, t), !0) + }, createPortal: function (t, e) { + return Object(u.e)(V, {__v: t, i: e}) + }, createElement: u.e, createContext: u.d, createFactory: function (t) { + return u.e.bind(null, t) + }, cloneElement: function (t) { + return ut(t) ? u.c.apply(null, arguments) : t + }, createRef: u.f, Fragment: u.b, isValidElement: ut, findDOMNode: function (t) { + return t && (t.base || 1 === t.nodeType && t) || null + }, Component: u.a, PureComponent: D, memo: T, forwardRef: C, flushSync: function (t, e) { + return t(e) + }, unstable_batchedUpdates: at, StrictMode: ct, Suspense: F, SuspenseList: X, lazy: function (t) { + var e, r, n; + + function o(o) { + if (e || (e = t()).then((function (t) { + r = t.default || t + }), (function (t) { + n = t + })), n) throw n; + if (!r) throw e; + return Object(u.e)(r, o) + } + + return o.displayName = "Lazy", o.__f = !0, o + }, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: it + }; + e.d = st + }, function (t, e, r) { + var n = r(7), o = r(152), i = r(153), u = r(187), a = r(57), c = function (t) { + if (t && t.forEach !== u) try { + a(t, "forEach", u) + } catch (e) { + t.forEach = u + } + }; + for (var s in o) o[s] && c(n[s] && n[s].prototype); + c(i) + }, function (t, e, r) { + r(17)({target: "Object", stat: !0}, {setPrototypeOf: r(102)}) + }, function (t, e, r) { + var n = r(17), o = r(18), i = r(40), u = r(101), a = r(143); + n({ + target: "Object", stat: !0, forced: o((function () { + u(1) + })), sham: !a + }, { + getPrototypeOf: function (t) { + return u(i(t)) + } + }) + }, function (t, e, r) { + var n = r(17), o = r(46), i = r(74), u = r(202), a = r(162), c = r(32), s = r(33), l = r(60), f = r(18), + p = o("Reflect", "construct"), d = Object.prototype, h = [].push, y = f((function () { + function t() { + } + + return !(p((function () { + }), [], t) instanceof t) + })), v = !f((function () { + p((function () { + })) + })), g = y || v; + n({target: "Reflect", stat: !0, forced: g, sham: g}, { + construct: function (t, e) { + a(t), c(e); + var r = arguments.length < 3 ? t : a(arguments[2]); + if (v && !y) return p(t, e, r); + if (t == r) { + switch (e.length) { + case 0: + return new t; + case 1: + return new t(e[0]); + case 2: + return new t(e[0], e[1]); + case 3: + return new t(e[0], e[1], e[2]); + case 4: + return new t(e[0], e[1], e[2], e[3]) + } + var n = [null]; + return i(h, n, e), new (i(u, t, n)) + } + var o = r.prototype, f = l(s(o) ? o : d), g = i(t, f, e); + return s(g) ? g : f + } + }) + }, function (t, e) { + var r = Function.prototype, n = r.bind, o = r.call, i = n && n.bind(o); + t.exports = n ? function (t) { + return t && i(o, t) + } : function (t) { + return t && function () { + return o.apply(t, arguments) + } + } + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(7), i = r(96), u = r(99), a = r(33), c = r(73), s = r(45), l = r(41), f = r(62), p = r(28), + d = r(79), h = r(98), y = d("slice"), v = p("species"), g = o.Array, b = Math.max; + n({target: "Array", proto: !0, forced: !y}, { + slice: function (t, e) { + var r, n, o, p = l(this), d = s(p), y = c(t, d), m = c(void 0 === e ? d : e, d); + if (i(p) && (r = p.constructor, (u(r) && (r === g || i(r.prototype)) || a(r) && null === (r = r[v])) && (r = void 0), r === g || void 0 === r)) return h(p, y, m); + for (n = new (void 0 === r ? g : r)(b(m - y, 0)), o = 0; y < m; y++, o++) y in p && f(n, o, p[y]); + return n.length = o, n + } + }) + }, function (t, e, r) { + var n = r(7), o = r(50).f, i = r(57), u = r(42), a = r(110), c = r(134), s = r(95); + t.exports = function (t, e) { + var r, l, f, p, d, h = t.target, y = t.global, v = t.stat; + if (r = y ? n : v ? n[h] || a(h, {}) : (n[h] || {}).prototype) for (l in e) { + if (p = e[l], f = t.noTargetGet ? (d = o(r, l)) && d.value : r[l], !s(y ? l : h + (v ? "." : "#") + l, t.forced) && void 0 !== f) { + if (typeof p == typeof f) continue; + c(p, f) + } + (t.sham || f && f.sham) && i(p, "sham", !0), u(r, l, p, t) + } + } + }, function (t, e) { + t.exports = function (t) { + try { + return !!t() + } catch (t) { + return !0 + } + } + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(103); + n({target: "RegExp", proto: !0, forced: /./.exec !== o}, {exec: o}) + }, function (t, e, r) { + var n = r(17), o = r(40), i = r(75); + n({ + target: "Object", stat: !0, forced: r(18)((function () { + i(1) + })) + }, { + keys: function (t) { + return i(o(t)) + } + }) + }, function (t, e, r) { + var n = r(36), o = r(71).EXISTS, i = r(15), u = r(38).f, a = Function.prototype, c = i(a.toString), + s = /function\b(?:\s|\/\*[\S\s]*?\*\/|\/\/[^\n\r]*[\n\r]+)*([^\s(/]*)/, l = i(s.exec); + n && !o && u(a, "name", { + configurable: !0, get: function () { + try { + return l(s, c(this))[1] + } catch (t) { + return "" + } + } + }) + }, function (t, e, r) { + var n = r(17), o = r(18), i = r(41), u = r(50).f, a = r(36), c = o((function () { + u(1) + })); + n({target: "Object", stat: !0, forced: !a || c, sham: !a}, { + getOwnPropertyDescriptor: function (t, e) { + return u(i(t), e) + } + }) + }, function (t, e, r) { + var n = r(17), o = r(188); + n({ + target: "Array", stat: !0, forced: !r(120)((function (t) { + Array.from(t) + })) + }, {from: o}) + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(77).filter; + n({target: "Array", proto: !0, forced: !r(79)("filter")}, { + filter: function (t) { + return o(this, t, arguments.length > 1 ? arguments[1] : void 0) + } + }) + }, function (t, e, r) { + var n = r(17), o = r(36), i = r(135), u = r(41), a = r(50), c = r(62); + n({target: "Object", stat: !0, sham: !o}, { + getOwnPropertyDescriptors: function (t) { + for (var e, r, n = u(t), o = a.f, s = i(n), l = {}, f = 0; s.length > f;) void 0 !== (r = o(n, e = s[f++])) && c(l, e, r); + return l + } + }) + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(7), i = r(18), u = r(96), a = r(33), c = r(40), s = r(45), l = r(62), f = r(115), + p = r(79), d = r(28), h = r(68), y = d("isConcatSpreadable"), v = 9007199254740991, + g = "Maximum allowed index exceeded", b = o.TypeError, m = h >= 51 || !i((function () { + var t = []; + return t[y] = !1, t.concat()[0] !== t + })), O = p("concat"), _ = function (t) { + if (!a(t)) return !1; + var e = t[y]; + return void 0 !== e ? !!e : u(t) + }; + n({target: "Array", proto: !0, forced: !m || !O}, { + concat: function (t) { + var e, r, n, o, i, u = c(this), a = f(u, 0), p = 0; + for (e = -1, n = arguments.length; e < n; e++) if (_(i = -1 === e ? u : arguments[e])) { + if (p + (o = s(i)) > v) throw b(g); + for (r = 0; r < o; r++, p++) r in i && l(a, p, i[r]) + } else { + if (p >= v) throw b(g); + l(a, p++, i) + } + return a.length = p, a + } + }) + }, , function (t, e, r) { + var n = r(7), o = r(89), i = r(35), u = r(90), a = r(108), c = r(132), s = o("wks"), l = n.Symbol, + f = l && l.for, p = c ? l : l && l.withoutSetter || u; + t.exports = function (t) { + if (!i(s, t) || !a && "string" != typeof s[t]) { + var e = "Symbol." + t; + a && i(l, t) ? s[t] = l[t] : s[t] = c && f ? f(e) : p(e) + } + return s[t] + } + }, function (t, e, r) { + var n = r(17), o = r(201); + n({target: "Object", stat: !0, forced: Object.assign !== o}, {assign: o}) + }, function (t, e) { + t.exports = function (t) { + return "function" == typeof t + } + }, function (t, e, r) { + "use strict"; + var n = r(106), o = "object" == typeof self && self && self.Object === Object && self, + i = n.a || o || Function("return this")(); + e.a = i + }, function (t, e, r) { + var n = r(7), o = r(33), i = n.String, u = n.TypeError; + t.exports = function (t) { + if (o(t)) return t; + throw u(i(t) + " is not an object") + } + }, function (t, e, r) { + var n = r(30); + t.exports = function (t) { + return "object" == typeof t ? null !== t : n(t) + } + }, function (t, e) { + var r = Function.prototype.call; + t.exports = r.bind ? r.bind(r) : function () { + return r.apply(r, arguments) + } + }, function (t, e, r) { + var n = r(15), o = r(40), i = n({}.hasOwnProperty); + t.exports = Object.hasOwn || function (t, e) { + return i(o(t), e) + } + }, function (t, e, r) { + var n = r(18); + t.exports = !n((function () { + return 7 != Object.defineProperty({}, 1, { + get: function () { + return 7 + } + })[1] + })) + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(77).map; + n({target: "Array", proto: !0, forced: !r(79)("map")}, { + map: function (t) { + return o(this, t, arguments.length > 1 ? arguments[1] : void 0) + } + }) + }, function (t, e, r) { + var n = r(7), o = r(36), i = r(133), u = r(32), a = r(86), c = n.TypeError, s = Object.defineProperty; + e.f = o ? s : function (t, e, r) { + if (u(t), e = a(e), u(r), i) try { + return s(t, e, r) + } catch (t) { + } + if ("get" in r || "set" in r) throw c("Accessors not supported"); + return "value" in r && (t[e] = r.value), t + } + }, function (t, e, r) { + var n = r(7), o = r(97), i = n.String; + t.exports = function (t) { + if ("Symbol" === o(t)) throw TypeError("Cannot convert a Symbol value to a string"); + return i(t) + } + }, function (t, e, r) { + var n = r(7), o = r(44), i = n.Object; + t.exports = function (t) { + return i(o(t)) + } + }, function (t, e, r) { + var n = r(85), o = r(44); + t.exports = function (t) { + return n(o(t)) + } + }, function (t, e, r) { + var n = r(7), o = r(30), i = r(35), u = r(57), a = r(110), c = r(92), s = r(58), l = r(71).CONFIGURABLE, + f = s.get, p = s.enforce, d = String(String).split("String"); + (t.exports = function (t, e, r, c) { + var s, f = !!c && !!c.unsafe, h = !!c && !!c.enumerable, y = !!c && !!c.noTargetGet, + v = c && void 0 !== c.name ? c.name : e; + o(r) && ("Symbol(" === String(v).slice(0, 7) && (v = "[" + String(v).replace(/^Symbol\(([^)]*)\)/, "$1") + "]"), (!i(r, "name") || l && r.name !== v) && u(r, "name", v), (s = p(r)).source || (s.source = d.join("string" == typeof v ? v : ""))), t !== n ? (f ? !y && t[e] && (h = !0) : delete t[e], h ? t[e] = r : u(t, e, r)) : h ? t[e] = r : a(e, r) + })(Function.prototype, "toString", (function () { + return o(this) && f(this).source || c(this) + })) + }, function (t, e, r) { + "use strict"; + (function (t) { + r.d(e, "d", (function () { + return i + })), r.d(e, "c", (function () { + return u + })), r.d(e, "b", (function () { + return a + })), r.d(e, "a", (function () { + return s + })); + var n = r(10), o = function (t, e) { + var r = "function" == typeof Symbol && t[Symbol.iterator]; + if (!r) return t; + var n, o, i = r.call(t), u = []; + try { + for (; (void 0 === e || e-- > 0) && !(n = i.next()).done;) u.push(n.value) + } catch (t) { + o = {error: t} + } finally { + try { + n && !n.done && (r = i.return) && r.call(i) + } finally { + if (o) throw o.error + } + } + return u + }; + + function i() { + var t = o(Object(n.j)(0), 2)[1]; + return Object(n.h)((function () { + t((function (t) { + return t + 1 + })) + }), []) + } + + function u(t) { + if (!t || "object" != typeof t) return !1; + var e = Object.getPrototypeOf(t); + return !e || e === Object.prototype + } + + function a(t) { + return "function" == typeof Symbol ? Symbol.for(t) : "__$mobx-react " + t + "__" + } + + var c = {}; + + function s() { + return "undefined" != typeof window ? window : void 0 !== t ? t : "undefined" != typeof self ? self : c + } + }).call(this, r(66)) + }, function (t, e, r) { + var n = r(7).TypeError; + t.exports = function (t) { + if (null == t) throw n("Can't call method on " + t); + return t + } + }, function (t, e, r) { + var n = r(94); + t.exports = function (t) { + return n(t.length) + } + }, function (t, e, r) { + var n = r(7), o = r(30), i = function (t) { + return o(t) ? t : void 0 + }; + t.exports = function (t, e) { + return arguments.length < 2 ? i(n[t]) : n[t] && n[t][e] + } + }, function (t, e, r) { + var n = r(17), o = r(34), i = r(33), u = r(32), a = r(203), c = r(50), s = r(101); + n({target: "Reflect", stat: !0}, { + get: function t(e, r) { + var n, l, f = arguments.length < 3 ? e : arguments[2]; + return u(e) === f ? e[r] : (n = c.f(e, r)) ? a(n) ? n.value : void 0 === n.get ? void 0 : o(n.get, f) : i(l = s(e)) ? t(l, r, f) : void 0 + } + }) + }, function (t, e, r) { + "use strict"; + (function (t) { + var n = r(31), o = r(171), i = "object" == typeof exports && exports && !exports.nodeType && exports, + u = i && "object" == typeof t && t && !t.nodeType && t, a = u && u.exports === i ? n.a.Buffer : void 0, + c = (a ? a.isBuffer : void 0) || o.a; + e.a = c + }).call(this, r(122)(t)) + }, function (t, e, r) { + "use strict"; + (function (t) { + var n = r(106), o = "object" == typeof exports && exports && !exports.nodeType && exports, + i = o && "object" == typeof t && t && !t.nodeType && t, u = i && i.exports === o && n.a.process, + a = function () { + try { + var t = i && i.require && i.require("util").types; + return t || u && u.binding && u.binding("util") + } catch (t) { + } + }(); + e.a = a + }).call(this, r(122)(t)) + }, function (t, e, r) { + var n = r(36), o = r(34), i = r(84), u = r(67), a = r(41), c = r(86), s = r(35), l = r(133), + f = Object.getOwnPropertyDescriptor; + e.f = n ? f : function (t, e) { + if (t = a(t), e = c(e), l) try { + return f(t, e) + } catch (t) { + } + if (s(t, e)) return u(!o(i.f, t, e), t[e]) + } + }, function (t, e, r) { + var n = r(15), o = n({}.toString), i = n("".slice); + t.exports = function (t) { + return i(o(t), 8, -1) + } + }, function (t, e, r) { + "use strict"; + r(182)("Map", (function (t) { + return function () { + return t(this, arguments.length ? arguments[0] : void 0) + } + }), r(186)) + }, function (t, e, r) { + var n = r(17), o = r(218).entries; + n({target: "Object", stat: !0}, { + entries: function (t) { + return o(t) + } + }) + }, function (t, e, r) { + var n = r(15); + t.exports = n({}.isPrototypeOf) + }, function (t, e, r) { + var n = r(46); + t.exports = n("navigator", "userAgent") || "" + }, function (t, e, r) { + var n = r(7), o = r(30), i = r(88), u = n.TypeError; + t.exports = function (t) { + if (o(t)) return t; + throw u(i(t) + " is not a function") + } + }, function (t, e, r) { + var n = r(36), o = r(38), i = r(67); + t.exports = n ? function (t, e, r) { + return o.f(t, e, i(1, r)) + } : function (t, e, r) { + return t[e] = r, t + } + }, function (t, e, r) { + var n, o, i, u = r(175), a = r(7), c = r(15), s = r(33), l = r(57), f = r(35), p = r(109), d = r(93), h = r(70), + y = "Object already initialized", v = a.TypeError, g = a.WeakMap; + if (u || p.state) { + var b = p.state || (p.state = new g), m = c(b.get), O = c(b.has), _ = c(b.set); + n = function (t, e) { + if (O(b, t)) throw new v(y); + return e.facade = t, _(b, t, e), e + }, o = function (t) { + return m(b, t) || {} + }, i = function (t) { + return O(b, t) + } + } else { + var w = d("state"); + h[w] = !0, n = function (t, e) { + if (f(t, w)) throw new v(y); + return e.facade = t, l(t, w, e), e + }, o = function (t) { + return f(t, w) ? t[w] : {} + }, i = function (t) { + return f(t, w) + } + } + t.exports = { + set: n, get: o, has: i, enforce: function (t) { + return i(t) ? o(t) : n(t, {}) + }, getterFor: function (t) { + return function (e) { + var r; + if (!s(e) || (r = o(e)).type !== t) throw v("Incompatible receiver, " + t + " required"); + return r + } + } + } + }, function (t, e) { + var r = Math.ceil, n = Math.floor; + t.exports = function (t) { + var e = +t; + return e != e || 0 === e ? 0 : (e > 0 ? n : r)(e) + } + }, function (t, e, r) { + var n, o = r(32), i = r(176), u = r(111), a = r(70), c = r(138), s = r(91), l = r(93), f = l("IE_PROTO"), + p = function () { + }, d = function (t) { + return "'; + return html; + } + + function randStrName() { + return 'a' + Math.random().toString(36).substr(9); + } + form.on('submit(formDemo)', function(data) { + layer.msg(JSON.stringify(data.field)); + return false; + }); + exports('design', {}); +}); diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/dtree.css b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/dtree.css new file mode 100644 index 0000000000000000000000000000000000000000..3e5364d4d5fa819bd748d4ce91476300482d68f7 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/dtree.css @@ -0,0 +1,112 @@ + +/**************** 主题换肤 ****************/ +/* 默认风格*/ +.dtree-theme-item-this{background-color: #d2d2d2!important;} +.dtree-theme-item:hover{background-color: #eaeceb!important;} +.dtree-theme-item cite{font-size:12px!important;} +.dtree-theme-item:hover cite{color:#fe7786!important;} + +.dtree-theme-dtreefont{font-size: 16px!important;} +.dtree-theme-ficon{color:#000!important;} +.dtree-theme-icon{color:orange!important;} +.dtree-theme-checkbox:hover{color:#fe7786!important;} +.dtree-theme-choose{color:#fe7786!important;} + +/* layui主题风格*/ +.dtree-layui-item-this{background: none!important;} +.dtree-layui-item:hover{background: none!important;} +.dtree-layui-item cite{font-size:14px!important;} +.dtree-layui-item:hover cite{opacity:0.5;filter:Alpha(opacity=50);text-decoration: underline;} + +.dtree-layui-dtreefont{font-size: 18px!important;} +.dtree-layui-ficon{font-size: 18px!important;color:#393D49!important;} +.dtree-layui-icon{color:#666!important;} +.dtree-layui-checkbox:hover{color:#5FB878!important;} +.dtree-layui-choose{color:#5FB878!important;} + +/* laySimple主题风格*/ +.dtree-laySimple-item-this{background-color: #d2d2d2!important;} +.dtree-laySimple-item:hover{background-color: #eaeceb!important;} +.dtree-laySimple-item cite{font-size:12px!important;} +.dtree-laySimple-item:hover cite{color:#01AAED!important;} + +.dtree-laySimple-dtreefont{font-size: 16px!important;} +.dtree-laySimple-ficon{font-size: 14px!important;color:#393D49!important;} +.dtree-laySimple-icon{color:#393D49!important;} +.dtree-laySimple-checkbox:hover{color:#01AAED!important;} +.dtree-laySimple-choose{color:#01AAED!important;} +/**************** 树基础 ****************/ +/* 菜单栏*/ +.dtree-menubar {padding-left: 10px;} +.dtree-menubar .layui-btn-group .layui-btn-sm{height: 20px;line-height: 20px;padding: 0 5px;font-size: 12px;} +.dtree-menubar .layui-btn-group .layui-btn-sm i{font-size: 12px!important;} + +/* 工具栏*/ +.dtree-toolbar{position: absolute;z-index: 940520;padding: 0;background-color: #eceaeb;} +.dtree-toolbar .layui-nav-child{position: static;} +.dtree-toolbar .layui-nav-child dd{cursor: pointer;} +.dtree-toolbar .layui-nav-child dd a i{font-size:16px;display: inline-block;margin: 0px 1px;color:#fe7786;} +.dtree-toolbar .layui-nav-child dd a i:hover{font-weight: bold;} +.dtree-toolbar .layui-nav-bar{display: none!important;} +.dtree-toolbar-tool{padding: 30px;} + +.dtree-toolbar-fixed{position: absolute;right: 5px;top: 2px;font-style: normal;transition: all .3s;-webkit-transition: all .3s;} +/*.dtree-toolbar-fixed a{border:1px solid #fe7786;}*/ +.dtree-toolbar-fixed a i{font-size:14px;display: inline-block;margin: 0px 1px;color:#fe7786;} +.dtree-toolbar-fixed a i:hover{opacity:0.8;filter:Alpha(opacity=80);} + +/* 树基本*/ +.dtree{width:260px;} +.dtree-nav-item{line-height:33px;padding-left:16px;} +.dtree-nav-ul-sid{display: none;} +.dtree-none-text{font-size: 12px;text-align: center;color: gray;} + +/* 树线*/ +.dtree-nav-first-line,.dtree-nav-line,.dtree-nav-last-line{position: relative;} +.dtree-nav-first-line:before{content:"";position: absolute;height: 0;border-left: 1px dotted #c0c4cc;} +.dtree-nav-first-line:after{content:"";position: absolute;height: 0;border-top: 1px dotted #c0c4cc;} + +.dtree-nav-line:before{content:"";position: absolute;top: 0;left: 7px;width: 0;height: 100%;border-left: 1px dotted #c0c4cc;} +.dtree-nav-line:after{content:"";position: absolute;top: 16px;left: 8px;width: 9px;height: 0;border-top: 1px dotted #c0c4cc;} + +.dtree-nav-last-line:before{content:"";position: absolute;top: 0;left: 7px;width: 0;height: 17px;border-left: 1px dotted #c0c4cc;} +.dtree-nav-last-line:after{content:"";position: absolute;top: 16px;left: 8px;width: 9px;height: 0;border-top: 1px dotted #c0c4cc;} + + +/* 图标及复选框*/ +.dtreefont{cursor: pointer;} +.dtreefont-special{margin: 0 4px;} +.dtree-nav-checkbox-div{display: inline-block;} +.dtree-nav-checkbox-div>i{display: inline-block;margin: 0px 1px;} +.dtree-nav-checkbox-div>i:last-child{margin-right: 4px;} +.dtree-nav-checkbox-div>i:hover{opacity:0.8;filter:Alpha(opacity=80);} + +/* 行 文字*/ +.dtree-nav-div{display:block;vertical-align:top;position:relative;} +.dtree-nav-div cite{font-style: normal;cursor: pointer;} +.dtree-nav-div:hover cite{opacity:0.7;filter:Alpha(opacity=70);transition: all .3s;-webkit-transition: all .3s;} + +/* 规则属性*/ +.dtree-nav-show {display: block!important;} +.dtree-nav-hide {display: none!important;} +.dtree-nav-this {} +.dtree-icon-hide {opacity:0;filter:Alpha(opacity=0);} +.dtree-icon-null-open,.dtree-icon-null-close,.dtree-icon-null{margin: 0 2px;} +.dtree-disabled{cursor: not-allowed; color:#c2c2c2!important;} +.dtree-disabled:hover{color:#c2c2c2!important;} +.dtree-nav-div cite.dtree-disabled{font-style: normal; cursor: not-allowed; color:#c2c2c2!important;} +.dtree-nav-div>cite.dtree-disabled:hover{color:#c2c2c2!important;} + + +/** 下拉树属性*/ +.dtree-select{position: absolute;max-height: 500px;height: 350px;overflow: auto;width: 99%;z-index: 123;display: none;border:1px solid silver;top: 42px;} +.dtree-select-show{display: block!important;} + +/* 简单适配*/ +@media screen and (max-width:1700px) and (min-width:1300px){ + .dtree-nav-item {padding-left: 15px;} +} + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/dtree.js b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/dtree.js new file mode 100644 index 0000000000000000000000000000000000000000..a05b22a8e3798284f8e2f84d4b715d04295a6095 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/dtree.js @@ -0,0 +1,4947 @@ +/** + *@Name dtree 树形组件 + *@Author 智慧的小西瓜 + *@DOCS http://www.wisdomelon.com/DTreeHelper/ + *@License https://www.layui.com/ + *@LASTTIME 2019/10/24 + *@VERSION v2.5.6 + */ +layui.define(['jquery','layer','form'], function(exports) { + var $ = layui.$, + layer = layui.layer, + form = layui.form; + + // 树的公共定义样式汇总 + var LI_NAV_CHILD = "dtree-nav-ul-sid", LI_NAV_ITEM = "dtree-nav-item", + LI_DIV_ITEM = "dtree-nav-div", DTREEFONTSPECIAL="dtreefont-special", NONETITLE="dtree-none-text", + LI_DIV_MENUBAR = "dtree-menubar", + LI_DIV_TOOLBAR = "dtree-toolbar", TOOLBAR_TOOL = "dtree-toolbar-tool", TOOLBAR_TOOL_EM = "dtree-toolbar-fixed", + LI_DIV_CHECKBAR = "dtree-nav-checkbox-div", + LI_CLICK_CHECKBAR = "d-click-checkbar", //绑定点击复选框时需要用到 + LI_DIV_TEXT_CLASS = "t-click", UL_ROOT="dtree", + LI_NAV_FIRST_LINE = "dtree-nav-first-line", LI_NAV_LINE = "dtree-nav-line", LI_NAV_LAST_LINE = "dtree-nav-last-line"; + + + // 树的公共指定 + var NAV_THIS = "dtree-nav-this", //当前节点 + NAV_SHOW = "dtree-nav-show", //显示子节点 + NAV_HIDE = "dtree-nav-hide", //隐藏节点 + NAV_DIS = "dtree-disabled", //禁用节点 + ICON_HIDE = "dtree-icon-hide", //隐藏图标 + $BODY = $("body"), //body选择器 + $WIN = $(window), //window窗口 + $DOC = $(document), //当前文档 + MOD_NAME = "dtree", //模块名称 + VERSION = "v2.5.6", //版本 + OPTIONS = {}, //全局属性配置 + DTrees = {}; //当前被实例化的树的集合 + + // 树的自定义图标 + var DTREEFONT = "dtreefont", //默认使用图标字体 + LI_DIV_CHECKBAR_ON = "dtree-icon-fuxuankuangxuanzhong", //复选框选中图标 + LI_DIV_CHECKBAR_OUT = "dtree-icon-fuxuankuang", //复选框未选中图标 + LI_DIV_CHECKBAR_NOALL = "dtree-icon-fuxuankuang-banxuan", //复选框半选图标 + LI_DIV_MENUBAR_DOWN = "dtree-icon-move-down", //menubar的展开全部的图标 + LI_DIV_MENUBAR_UP = "dtree-icon-move-up", //menubar的收缩全部的图标 + LI_DIV_MENUBAR_REFRESH = "dtree-icon-refresh", //menubar的刷新图标 + LI_DIV_MENUBAR_CHECKALL = "dtree-icon-roundcheckfill", //menubar的全选图标 + LI_DIV_MENUBAR_UNCHECKALL = "dtree-icon-roundclosefill", //menubar的全不选图标 + LI_DIV_MENUBAR_INVERTALL = "dtree-icon-roundcheck", //menubar的反选图标 + LI_DIV_MENUBAR_DELETE = "dtree-icon-delete1", //menubar的删除图标 + LI_DIV_MENUBAR_SEARCH = "dtree-icon-search_list_light", //menubar的搜索图标 + LI_DIV_TOOLBAR_PULLDOWN = "dtree-icon-pulldown", //toolbar的展开图标 + LI_DIV_TOOLBAR_PULLUP = "dtree-icon-pullup", //toolbar的收缩图标 + LI_DIV_TOOLBAR_ADD = "dtree-icon-roundadd", //toolbar的新增图标 + LI_DIV_TOOLBAR_EDIT = "dtree-icon-bianji", //toolbar的编辑图标 + LI_DIV_TOOLBAR_DEL = "dtree-icon-roundclose"; //toolbar的删除图标 + + // 树的非叶子节点图标集合 + var nodeIconArray = { + "-1": {"open": "dtree-icon-null-open", "close": "dtree-icon-null-close"}, //未指定 + "0" : {"open": "dtree-icon-wenjianjiazhankai", "close": "dtree-icon-weibiaoti5"}, //文件夹(二级图标默认样式) + "1" : {"open": "dtree-icon-jian", "close": "dtree-icon-jia"}, //+-图标(一级图标默认样式) + "2" : {"open": "dtree-icon-xiangxia1", "close": "dtree-icon-xiangyou"} //箭头图标 + }; + + // 树的叶子节点图标集合 + var leafIconArray = { + "-1": "dtree-icon-null", //未指定 + "0" : "dtree-icon-weibiaoti5", //文件夹 + "1" : "dtree-icon-yonghu", //人员 + "2" : "dtree-icon-fenzhijigou", //机构 + "3" : "dtree-icon-fenguangbaobiao", //报表 + "4" : "dtree-icon-xinxipilu", //信息 + "5" : "dtree-icon-shuye1", //叶子(二级图标默认样式) + "6" : "dtree-icon-caidan_xunzhang", //勋章 + "7" : "dtree-icon-normal-file", //文件 + "8" : "dtree-icon-dian", //小圆点(一级图标默认样式) + "9" : "dtree-icon-set-sm", //齿轮 + "10" : "dtree-icon-rate" //星星 + }; + + // 树的自定义样式 + var DTREE = "dtree-", //自定义样式前缀 + ITEMTHIS = "-item-this", //自定义样式当前行选中后缀 + ITEM = "-item", //自定义样式当前行后缀 + DFONT = "-dtreefont", //自定义样式图标样式后缀 + FICON = "-ficon", //自定义样式一级图标样式后缀 + ICON = "-icon", //自定义样式二级图标样式后缀 + CBOX = "-checkbox", //自定义样式复选框样式后缀 + CHS = "-choose"; //自定义样式复选框选中样式后缀 + + // 树自定义操作事件名称集合 绑定dtree-click的事件 + var eventName = { + checkNodeClick: "checkNodeClick", //点击复选框 + itemNodeClick: "itemNodeClick" //点击子节点div + }; + + // 树默认toolbar提供的功能集合 绑定dtree-tool的事件 + var defaultTool = { + pulldown: "pulldown", //点击展开当前节点下的全部节点 + pullup: "pullup", //点击收缩当前节点下的全部节点 + addTool: "addToolbar", //点击toolbar新增 + editTool: "editToolbar", //点击toolbar编辑 + delTool: "delToolbar" //点击toolbar删除 + }; + + // 树默认menubar提供的功能集合 绑定dtree-menu的事件 + var defaultMenu = { + moveDown: "moveDown", //menubar展开全部节点 + moveUp: "moveUp", //menubar收缩全部节点 + refresh: "refresh", //menubar刷新树 + checkAll: "checkAll", //menubar全选 + unCheckAll: "unCheckAll", //menubar全不选 + invertAll: "invertAll", //menubar反选 + remove: "remove", //menubar删除选中节点 + searchNode: "searchNode" //menubar查询节点 + }; + + // 树的公共事件 + var event = { + getElemId: function(options){ // 根据传入的参数获取ID + var elem = options.elem || ""; + var obj = options.obj || $(elem); + + if (obj.length == 0) { //页面中未找到绑定id + return ""; + } else { + return $(obj)[0].id; + } + }, + escape: function(html){ + if(typeof html !== 'string') return ''; + return html.replace(entityReg.escape, function(match){return entityMap.escape[match];}); + }, + unescape: function(str){ + if(typeof str !== 'string') return ''; + return str.replace(entityReg.unescape, function(match){return entityMap.unescape[match];}); + }, + cloneObj: function (obj, filter) { //深复制对象方法 + var newObj = {}; + if (obj instanceof Array) { + newObj = []; + } + var str = ""; + if(typeof filter !== 'undefined') {str = filter.join(",");} + for (var key in obj) { + if(str.indexOf(key) == -1){ + var val = obj[key]; + newObj[key] = typeof val === 'object' ? event.cloneObj(val, typeof filter !== undefined ? filter : []): val; + } + + } + return newObj; + }, + trimToDot: function(str){ + return str.replace(/ /g, "."); + } + }; + + // 特殊符号转义 + var keys = Object.keys || function(obj) { + obj = Object(obj); + var arr = []; + for(var a in obj) arr.push(a); + return arr; + }; + var invert = function(obj){ + obj = Object(obj); + var result = {}; + for(var a in obj) result[obj[a]] = a; + return result; + }; + var entityMap = { + escape: { + "&" : "&", + "<" : "<", + ">" : ">", + "'" : "&quo;" + } + }; + entityMap.unescape = invert(entityMap.escape); + var entityReg = { + escape: RegExp('[' + keys(entityMap.escape).join('') + ']', 'g'), + unescape: RegExp('(' + keys(entityMap.unescape).join('|') + ')', 'g') + }; + + //异步加载接口 + var AjaxHelper = { + request : function(config) { + var data = config.data ? config.data : {}; + var async = (typeof (config.async) === "boolean") ? config.async : true; + $.ajax({ + type : config.type ? config.type : "POST", + headers : config.headers, + url : config.url, + dataType : config.dataType ? config.dataType : "json", + data : data, + async : async, + contentType : config.contentType, + xhrFields: {withCredentials: config.withCredentials}, + success : config.success, + error : function(XMLHttpRequest, textStatus, errorThrown) { + if (typeof (config.error) === "function") { + config.error(XMLHttpRequest, textStatus, errorThrown); + } else { + layer.msg("异步加载失败: " + textStatus,{icon:5, shift:6}); + } + }, + statusCode : { + 404 : function() { + layer.msg('未找到指定请求,请检查访问路径!',{icon:5, shift:6}); + }, + 500 : function() { + layer.msg('系统错误!',{icon:5, shift:6}); + } + }, + complete : function(XMLHttpRequest, textStatus) { + if (typeof (config.complete) === "function") { + config.complete(XMLHttpRequest, textStatus); + } + } + }); + }, + serialize: function(param){ //json序列化 key=value&key1=value1 + var p = "?"; + for (var key in param) { + p += key + "=" + param[key] + "&"; + } + p = p.substring(0, p.length-1); + return p; + } + }; + + // 树类 + var DTree = function(options){ + var _this = this; + /** 默认赋值**/ + this.formatter = { // 数据过滤 + title: false // 文字,默认不开启 + }; + this.response = { // 树返回的json格式 + statusName: "code", //返回标识 + statusCode: 200, //返回码 + message: "message", //返回信息 + rootName: "data", //根节点名称 + treeId: "id", //节点ID + parentId: "parentId", //父节点ID + title: "title", //节点名称 + ficonClass: "ficonClass", //自定义一级图标 + iconClass: "iconClass", //自定义二级图标 + childName: "children", //子节点名称 + last: "last", //是否最后一级节点 +// level: "level", //层级 + spread: "spread", //展开 + disabled: "disabled", //禁用 + hide: "hide", //隐藏 + checkArr: "checkArr", //复选框列表 + checked: "checked", //是否选中 + type: "type", //复选框标记 + basicData: "basicData" //表示用户自定义需要存储在树节点中的数据 + }; + this.defaultRequest = { // 树的默认发起请求参数格式,最后会将value作为参数名称传递 + nodeId: "nodeId", //节点ID + parentId: "parentId", //父节点ID + context: "context", //节点内容 + leaf: "leaf", //是否叶子节点 + level: "level", //层级 + spread: "spread", //节点展开状态 + dataType: "dataType", //节点标记 + checked: "checked", //节点复选框选中状态 + initchecked: "initchecked", //节点复选框初始状态 + basicData: "basicData", //用户自定义的记录节点数据 + recordData: "recordData", //当前data数据(排除basicData和children字段) + }; + this.toolbarFun = { + addTreeNode: function(param, $div) { //添加树节点后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + editTreeNode: function(param, $div) { //编辑树节点后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + editTreeLoad: function(param){ // 编辑树的数据回显,用于打开编辑时,回填数据 + return ; + }, + delTreeNode: function(param, $div){ //删除树后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + loadToolbarBefore: function(buttons, param, $div){ // 右键菜单加载前的函数 + return buttons; + } + }; + this.toolbarStyle = { + title: "节点", + area: ["60%","80%"] + }; + this.menubarFun = { + remove: function(checkbarNodes){ //删除复选框选中节点,需要用户自定义,如未指定则树只是页面上做了修改 + return true; + } + }; + this.menubarTips = { + toolbar: [], + group: [defaultMenu.moveDown, defaultMenu.moveUp, defaultMenu.refresh, defaultMenu.checkAll, defaultMenu.unCheckAll, defaultMenu.invertAll, defaultMenu.remove, defaultMenu.searchNode], + freedom: [] + }; + this.checkbarFun = { + chooseBefore: function($i, node){ // 复选框点击前回调 + return true; + }, + chooseDone: function(checkbarNodesParam) { //复选框点击事件完毕后,返回该树关于复选框操作的全部信息,用于用户自定义,如未指定则树只是页面上做了修改 + return ; + } + }; + this.iframeDefaultRequest = { //iframe的默认参数,目的是与加载树的参数不一样 + nodeId: "nodeId", //节点ID + parentId: "parentId", //父节点ID + context: "context", //节点内容 + leaf: "leaf", //是否叶子节点 + level: "level", //层级 + spread: "spread", //节点展开状态 + dataType: "dataType", //节点标记 + checked: "checked", //节点复选框选中状态 + initchecked: "initchecked", //节点复选框初始状态 + basicData: "basicData", //用户自定义的记录节点数据 + recordData: "recordData", //当前data数据(排除basicData和children字段) + }; + + this.iframeFun = { + iframeDone: function(iframeParam){ //iframe加载完毕后,用于用户自定义事件 + return ; + } + }; + this.style = { //树最终使用的样式集合 + item: "", //每一项div的样式 + itemThis: "", //选中div的样式 + dfont: "", //一级图标的样式 + icon: "", //二级图标的样式 + cbox: "", //复选框的样式 + chs: "" //复选框选中的样式 + }; + this.usefontStyle = { //树最终使用的图标集合 + fnode:{ //一级节点 + node:{ //非叶子节点 + open:"", //节点展开 + close:"" //节点关闭 + }, + leaf:"" //叶子节点 + }, + snode:{ //二级节点 + node:{ //非叶子节点 + open:"", //节点展开 + close:"" //节点关闭 + }, + leaf:"" //叶子节点 + }, + checkbox:{ //复选框 + on:"", //复选框选中 + out:"", //未选中 + noall:"" //半选 + }, + menubar:{ //菜单栏 + movedown:"", //全部展开 + moveup:"", //全部收缩 + refresh:"", //刷新 + checkAll:"", //全选 + unCheckAll:"", //全不选 + invertAll:"", //反选 + remove:"", //删除 + search:"" //搜索 + }, + menubarExt:"", //扩展菜单栏 + toolbar:{ //工具栏 + menubar:{ //依附在菜单栏的工具栏 + movedown:"", //全部展开 + moveup:"", //全部收缩 + refresh:"", //刷新 + checkAll:"", //全选 + unCheckAll:"", //全不选 + invertAll:"", //反选 + remove:"", //删除 + search:"" //搜索 + }, + menubarExt:"", //依附在菜单栏的扩展菜单栏 + pulldown:"", //展开 + pullup:"", //收缩 + add:"", //添加 + edit:"", //编辑 + del:"" //删除 + }, + toolbarExt:"" //扩展工具栏 + } + + /** 数据绑定**/ + this.node = { // 树节点选中时,包含当前节点的全部信息 + nodeId: "", //节点ID + parentId: "", //父节点ID + context: "", //节点内容 + leaf: "", //是否叶子节点 + level: "", //层级 + spread: "", //节点展开状态 + dataType: "", //节点标记 + checked: "", //节点复选框选中状态 + initchecked: "", //节点复选框初始状态 + basicData: "", //用户自定义的记录节点数据 + recordData: "", //当前data数据(排除basicData和children字段) + }; + + this.toolbarMenu = {}; // 工具栏右键菜单绑定的所有元素 + this.checkbarNode = []; // 复选框标记的全部节点数据 + this.errData = []; // 记录在渲染节点时有问题的数据 + this.checkArrLen = 0; //添加节点的时判断复选框个数 + this.temp = []; // 临时变量 + this.bak = ""; // 临时变量 + this.setting(options); + }; + + /******************** 初始参数加载 ********************/ + // 设置基本参数值 + DTree.prototype.setting = function(options) { + this.options = options || {}; + + /** 绑定元素参数(必填,2个参数项必填一个)**/ + this.elem = this.options.elem || OPTIONS.elem || ""; //树绑定的元素ID:#elem + if(typeof this.options.obj === 'undefined'){ + if(this.elem) { + if($(this.elem).length > 0) { + this.obj = $(this.elem); + } + } + } else { + this.obj = this.options.obj || OPTIONS.obj || this.obj; //树绑定的jquery元素,用于当元素是延迟加载出来的话,可以用这个找到 + this.elem = "#" + this.obj[0].id; + } + + /** 基本参数**/ + this.scroll = this.options.scroll || OPTIONS.scroll || this.elem; //树的上级div容器,让树可以显示滚动条的div容器的ID + this.accordion = (typeof (this.options.accordion) === "boolean") ? this.options.accordion : (typeof (OPTIONS.accordion) === "boolean") ? OPTIONS.accordion : false; //手风琴加载, 默认false + if(this.accordion) { + this.initLevel = 1; //默认展开节点 1节 + } else { + this.initLevel = this.options.initLevel || OPTIONS.initLevel || 2; //默认展开节点 2节 + } + this.type = this.options.type || OPTIONS.type || "load"; //树的加载方式 all,全量树, load,增量树,默认load + this.cache = (typeof (this.options.cache) === "boolean") ? this.options.cache : (typeof (OPTIONS.cache) === "boolean") ? OPTIONS.cache : true; //数据缓存,默认true + this.record = this.options.record || OPTIONS.record || false; //开启数据记录模式,默认false + this.load = (typeof (this.options.load) === "boolean") ? this.options.load : (typeof (OPTIONS.load) === "boolean") ? OPTIONS.load : true; //开启加载动画,默认true + this.none = this.options.none || OPTIONS.nont || "无数据"; //初始加载无记录时显示文字 + this.tempHeight = this.options.height || OPTIONS.height; //临时转换高度变量 + if(this.tempHeight) { // 设置高度 + if(/^full-\d+$/.test(this.tempHeight)) { + this.fullHeightGap = this.tempHeight.split('-')[1]; + this.height = $WIN.height() - this.fullHeightGap; //设置高度 + } else { + this.fullHeightGap = this.tempHeight; + this.height = this.tempHeight; + } + } else { + this.fullHeightGap = ""; + this.height = ""; + } + this.width = this.options.width || OPTIONS.width || "260"; //宽度 + this.obj.css("width", this.width); + + /** 样式相关参数**/ + this.iconfont = this.options.iconfont || OPTIONS.iconfont || DTREEFONT; //默认图标字体 dtreefont + this.iconfontStyle = this.options.iconfontStyle || OPTIONS.iconfontStyle || {}; //用于自定义树的每个关键部位使用的图标 + this.nodeIconArray = $.extend(nodeIconArray, this.options.nodeIconArray || OPTIONS.nodeIconArray) || nodeIconArray; //用户自定义非叶子节点图标集合,node + this.leafIconArray = $.extend(leafIconArray, this.options.leafIconArray || OPTIONS.leafIconArray) || leafIconArray; //用户自定义叶子节点图标集合,leaf + this.skin = this.options.skin || OPTIONS.skin || "theme"; // 自定义样式 + if(this.skin == "layui"){ // layui主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : (typeof (OPTIONS.line) === "boolean") ? OPTIONS.line : true; //开启树线,默认开启 + this.ficon = this.options.ficon || OPTIONS.ficon || "7"; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'7' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; //一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "-1"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else if(this.skin == "laySimple"){ // laySimple主题 + this.line = this.options.line || OPTIONS.line || false; //开启树线,默认不开启 + this.ficon = this.options.ficon || OPTIONS.ficon || ["2","-1"]; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'-1' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "2") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'2' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "-1"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else { // 默认主题 或者自定义主题 + this.line = this.options.line || OPTIONS.line || false; //开启树线,默认不开启 + this.ficon = this.options.ficon || OPTIONS.ficon || "8"; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'8' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "5"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'5' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "0") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'0' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } + + /** 数据加载参数**/ + this.url = this.options.url || OPTIONS.url || ""; //请求地址 + this.async = (typeof (this.options.async) === "boolean") ? this.options.async : (typeof (OPTIONS.async) === "boolean") ? OPTIONS.async : true; //异步同步加载,默认异步加载 + this.headers = this.options.headers || OPTIONS.headers || {}; //ajax header属性 + this.method = this.options.method || OPTIONS.method || "post"; //请求类型 + this.dataType = this.options.dataType || OPTIONS.dataType || "json"; //参数类型 + this.contentType = this.options.contentType || OPTIONS.contentType || "application/x-www-form-urlencoded"; //发送信息至服务器时内容编码类型 + this.defaultRequest = $.extend(this.defaultRequest, this.options.defaultRequest || OPTIONS.defaultRequest) || this.defaultRequest; //默认请求参数 + this.filterRequest = this.options.filterRequest || OPTIONS.filterRequest || []; //过滤请求参数 + this.request = this.options.request || OPTIONS.request || {}; //用户自定义请求参数 + this.response = $.extend(this.response, this.options.response || OPTIONS.response) || this.response; //返回json格式 + this.data = this.options.data || OPTIONS.data || null; //初始化指定该参数,则不会访问异步接口 + this.dataFormat = this.options.dataFormat || OPTIONS.dataFormat || "levelRelationship"; //用于用户配置的data数据格式,list:列表, levelRelationship:层级关系,默认 + this.dataStyle = this.options.dataStyle || OPTIONS.dataStyle || "defaultStyle"; //用于用户配置layui通用的json数据风格,layuiStyle:layui风格,defaultStyle:默认风格 + this.errDataShow = this.options.errDataShow || OPTIONS.errDataShow || false; //是否在递归数据出现错误后,显示错误信息,默认false + this.withCredentials = this.options.withCredentials || OPTIONS.withCredentials || false; //是否允许跨域请求,默认false + this.success = this.options.success || OPTIONS.success || function(data, obj){}; //树加载完毕后执行解析树之前的回调 + this.done = this.options.done || OPTIONS.done || function(data, obj){}; //树加载完毕后的回调 + this.formatter = $.extend(this.formatter, this.options.formatter || OPTIONS.formatter) || this.formatter; //数据过滤 + this.error = this.options.error || OPTIONS.error || function(XMLHttpRequest, textStatus, errorThrown){}; // 异步加载异常回调 + this.complete = this.options.complete || OPTIONS.complete || function(XMLHttpRequest, textStatus){}; // 异步加载完成回调 + + /** 复选框参数**/ + this.checkbar = this.options.checkbar || OPTIONS.checkbar || false; //是否开启复选框模式 + this.checkbarLoad = this.options.checkbarLoad || OPTIONS.checkbarLoad || "node"; //复选框作用范围,node:所有节点, leaf:最后一级;默认所有节点 + this.checkbarType = this.options.checkbarType || OPTIONS.checkbarType || "all"; //复选框选中形式 all:子集选中父级也选中, no-all:子集选中父级半选中,子集全选父级选中,p-casc:父级选中子集全选,子集无法改变父级选中状态, self:没有任何级联关系,only:只能选中一个复选框。 默认all + this.checkbarData = this.options.checkbarData || OPTIONS.checkbarData || "choose"; //复选框记录数据类型形式, change表示记录变更数据,choose表示记录选中数据,all记录全部数据,halfChoose记录选中和半选中的数据,默认choose + this.checkbarFun = $.extend(this.checkbarFun, this.options.checkbarFun || OPTIONS.checkbarFun) || this.checkbarFun; //checkbar事件加载 + + /** 菜单栏参数**/ + this.menubar = this.options.menubar || OPTIONS.menubar || false; //是否打开菜单栏 + this.menubarTips = $.extend(this.menubarTips, this.options.menubarTips || OPTIONS.menubarTips) || this.menubarTips; //菜单栏吸附, toolbar:依附在工具栏,group:依附在按钮组,freedom,自由 + this.menubarFun = $.extend(this.menubarFun, this.options.menubarFun || OPTIONS.menubarFun) || this.menubarFun; //menubar事件加载 + + /** 工具栏参数**/ + this.toolbar = this.options.toolbar || OPTIONS.toolbar || false; //是否开启可编辑模式 + this.toolbarWay = this.options.toolbarWay || OPTIONS.toolbarWay || "contextmenu"; //工具栏显示方式,contextmenu:右键,follow:跟随节点,fixed:固定在节点右侧 + this.toolbarStyle = $.extend(this.toolbarStyle, this.options.toolbarStyle || OPTIONS.toolbarStyle) || this.toolbarStyle; //toolbar的自定义风格,标题,弹框大小 + this.toolbarLoad = this.options.toolbarLoad || OPTIONS.toolbarLoad || "node"; //toolbar作用范围:node:所有节点,noleaf:非最后一级节点,leaf:最后一级 + this.toolbarShow = this.options.toolbarShow || OPTIONS.toolbarShow || ["add","edit","delete"]; //toolbar三个按钮自定义加载 + this.toolbarBtn = this.options.toolbarBtn || OPTIONS.toolbarBtn || null; //toolbar增删改中内容的自定义加载 + this.toolbarExt = this.options.toolbarExt || OPTIONS.toolbarExt || []; //toolbar按钮扩展 + this.toolbarFun = $.extend(this.toolbarFun, this.options.toolbarFun || OPTIONS.toolbarFun) || this.toolbarFun; //toolbar事件加载 + + /** iframe模式参数**/ + this.useIframe = this.options.useIframe || OPTIONS.useIframe || false; //是否加载iframe 默认false, + this.iframeElem = this.options.iframeElem || OPTIONS.iframeElem || ""; //iframe的ID + this.iframeUrl = this.options.iframeUrl || OPTIONS.iframeUrl || ""; //树关联的iframe地址 + this.iframeLoad = this.options.iframeLoad || OPTIONS.iframeLoad || "leaf"; //点击哪一层加载frame: node:所有节点, leaf:默认,最后一级 + this.iframeDefaultRequest = $.extend(this.iframeDefaultRequest, this.options.iframeDefaultRequest || OPTIONS.iframeDefaultRequest) || this.iframeDefaultRequest; //iframe的默认传递参数 + this.iframeRequest = $.extend(this.iframeRequest, this.options.iframeRequest) || $.extend(this.iframeRequest, OPTIONS.iframeRequest) || this.iframeRequest; //iframe的自定义参数 + this.iframeFun = $.extend(this.iframeFun, this.options.iframeFun) || $.extend(this.iframeFun, OPTIONS.iframeFun) || this.iframeFun; //iframe事件加载 + + /** 下拉树模式参数**/ + this.select = this.options.select || false; + if(this.select) { + // 重置下拉树 + this.selectSetting(); + } + + /** 调用确认最终主题方法*/ + this.ensureTheme(); + }; + + // 设置基本参数值 + DTree.prototype.reloadSetting = function(options) { + this.options = $.extend(this.options, options) || this.options; + + /** 绑定元素参数**/ + this.elem = this.options.elem || this.elem; //树绑定的元素ID:#elem + if(typeof this.options.obj === 'undefined'){ + if(this.elem) { + if($(this.elem).length > 0) { + this.obj = $(this.elem); + } + } + } else { + this.obj = this.options.obj || this.obj; //树绑定的jquery元素,用于当元素是延迟加载出来的话,可以用这个找到 + this.elem = "#" + this.obj[0].id; + } + + /** 基本参数**/ + this.scroll = this.options.scroll || this.scroll; //树的上级div容器,让树可以显示滚动条的div容器 + this.accordion = (typeof (this.options.accordion) === "boolean") ? this.options.accordion : this.accordion; //开启手风琴加载 + if(this.accordion) { + this.initLevel = 1; //默认展开节点 1节 + } else { + this.initLevel = this.options.initLevel || this.initLevel; //默认展开节点 2节 + } + this.type = this.options.type || this.type; //树的加载方式 all,全量树, load,增量树,默认load + this.cache = (typeof (this.options.cache) === "boolean") ? this.options.cache : this.cache; //开启数据缓存 + this.record = (typeof (this.options.record) === "boolean") ? this.options.record : this.record; //开启数据记录模式 + this.load = (typeof (this.options.load) === "boolean") ? this.options.load : this.load; //开启加载动画 + this.none = this.options.none || this.none; //初始节点加载无数据时显示文字 + this.tempHeight = this.options.height || this.height; //临时转换高度变量 + if(this.tempHeight) { //设置高度 + if(/^full-\d+$/.test(this.tempHeight)) { + this.fullHeightGap = this.tempHeight.split('-')[1]; + this.height = $WIN.height() - this.fullHeightGap; + } else { + this.fullHeightGap = this.tempHeight; + this.height = this.tempHeight; + } + } + this.width = this.options.width || this.width; //宽度 + this.obj.css("width", this.width); + + /** 样式相关参数**/ + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : this.line; //开启树线,默认不开启 + this.iconfont = this.options.iconfont || this.iconfont; //默认图标字体 dtreefont + this.iconfontStyle = this.options.iconfontStyle || this.iconfontStyle; //用于自定义树的每个关键部位使用的图标 + this.nodeIconArray = $.extend(nodeIconArray, this.options.nodeIconArray) || this.nodeIconArray; //用户自定义非叶子节点图标集合,node + this.leafIconArray = $.extend(leafIconArray, this.options.leafIconArray) || this.leafIconArray; //用户自定义叶子节点图标集合,leaf + this.skin = this.options.skin || this.skin; //自定义样式 + if(this.skin == "layui"){ //layui主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : true; //开启树线,默认开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'7' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; //一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else if(this.skin == "laySimple"){ //laySimple主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : false; //开启树线,默认不开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'-1' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "2") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'2' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1];//一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else { // 默认主题 或者自定义主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : false; //开启树线,默认不开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'8' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'5' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "0") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'0' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } + + /** 数据加载参数**/ + this.url = this.options.url || this.url; //请求地址 + this.async = (typeof (this.options.async) === "boolean") ? this.options.async : this.async; //异步同步加载,默认异步加载 + this.headers = this.options.headers || this.headers; //ajax header属性 + this.method = this.options.method || this.method; //请求类型 + this.dataType = this.options.dataType || this.dataType; //参数类型 + this.contentType = this.options.contentType || this.contentType; //发送信息至服务器时内容编码类型 + this.defaultRequest = $.extend(this.defaultRequest, this.options.defaultRequest) || this.defaultRequest; //默认请求参数 + this.filterRequest = this.options.filterRequest || this.filterRequest; //过滤请求参数 + this.request = this.options.request || this.request; //用户自定义请求参数 + this.response = $.extend(this.response, this.options.response) || this.response; //返回json格式 + this.data = this.options.data || this.data; //初始化指定该参数,则不会访问异步接口 + this.dataFormat = this.options.dataFormat || this.dataFormat; //用于用户配置的data数据格式,list:列表, levelRelationship:层级关系,默认 + this.dataStyle = this.options.dataStyle || this.dataStyle; //用于用户配置layui通用的json数据风格,layuiStyle:layui风格,defaultStyle:默认风格 + this.errDataShow = (typeof (this.options.errDataShow) === "boolean") ? this.options.errDataShow : this.errDataShow; //是否在使用list模式递归数据出现错误时,显示错误信息 + this.withCredentials = (typeof (this.options.withCredentials) === "boolean") ? this.options.withCredentials : this.withCredentials; //是否允许跨域请求 + this.success = this.options.success || this.success; //树加载完毕后执行解析树之前的回调 + this.done = this.options.done || this.done; //树加载完毕后的回调 + this.formatter = $.extend(this.formatter, this.options.formatter)|| this.formatter; //数据过滤 + this.error = this.options.error || this.error; //异步加载异常回调 + this.complete = this.options.complete || this.complete; //异步加载完成回调 + + /** 复选框参数**/ + this.checkbar = this.options.checkbar || this.checkbar; //是否开启复选框模式 + this.checkbarLoad = this.options.checkbarLoad || this.checkbarLoad; //复选框作用范围,node:所有节点, leaf:最后一级;默认所有节点 + this.checkbarType = this.options.checkbarType || this.checkbarType; //复选框选中形式 all:子集选中父级也选中, no-all:子集选中父级半选中,子集全选父级选中,p-casc:父级选中子集全选,子集无法改变父级选中状态, self:没有任何级联关系,only:只能选中一个复选框。 默认all + this.checkbarData = this.options.checkbarData || this.checkbarData; //复选框记录数据类型形式, change表示记录变更数据,choose表示记录选中数据,all记录全部数据,halfChoose记录选中和半选中的数据,默认choose + this.checkbarFun = $.extend(this.checkbarFun, this.options.checkbarFun)|| this.checkbarFun; //checkbar事件加载 + + /** 菜单栏参数**/ + this.menubar = this.options.menubar || this.menubar; //是否打开菜单栏 + this.menubarTips = $.extend(this.menubarTips, this.options.menubarTips) || this.menubarTips; //菜单栏吸附, toolbar:依附在工具栏,group:依附在按钮组,freedom,自由 + this.menubarFun = $.extend(this.menubarFun, this.options.menubarFun) || this.menubarFun; //menubar事件加载 + + /** 工具栏参数**/ + this.toolbar = this.options.toolbar || this.toolbar; //是否开启工具栏 + this.toolbarWay = this.options.toolbarWay || this.toolbarWay; //工具栏显示方式,contextmenu:右键,follow:跟随节点,fixed:固定在节点右侧 + this.toolbarStyle = $.extend(this.toolbarStyle, this.options.toolbarStyle) || this.toolbarStyle; //toolbar的自定义风格,标题,弹框大小 + this.toolbarLoad = this.options.toolbarLoad || this.toolbarLoad; //toolbar作用范围:node:所有节点,noleaf:非最后一级节点,leaf:最后一级 + this.toolbarShow = this.options.toolbarShow || this.toolbarShow; //toolbar三个按钮 + this.toolbarBtn = this.options.toolbarBtn || this.toolbarBtn; //toolbar增删改中内容的自定义加载 + this.toolbarExt = this.options.toolbarExt || this.toolbarExt; //toolbar按钮扩展 + this.toolbarFun = $.extend(this.toolbarFun, this.options.toolbarFun) || this.toolbarFun; //toolbar事件加载 + + /** iframe模式参数**/ + this.useIframe = this.options.useIframe || this.useIframe;//是否加载iframe 默认false + this.iframeElem = this.options.iframeElem || this.iframeElem; //iframe的ID + this.iframeUrl = this.options.iframeUrl || this.iframeUrl; //树关联的iframe地址 + this.iframeLoad = this.options.iframeLoad || this.iframeLoad; //点击哪一层加载frame: node:所有节点, leaf:默认,最后一级 + this.iframeDefaultRequest = $.extend(this.iframeDefaultRequest, this.options.iframeDefaultRequest) || this.iframeDefaultRequest; //iframe的默认传递参数 + this.iframeRequest = $.extend(this.iframeRequest, this.options.iframeRequest) || this.iframeRequest; //iframe的自定义参数 + this.iframeFun = $.extend(this.iframeFun, this.options.iframeFun) || this.iframeFun; //iframe事件加载 + + /** 下拉树模式参数**/ + if(this.select) { + // 重置下拉树 + this.reloadSelectSetting(); + } + + /** 调用确认最终主题方法*/ + this.ensureTheme(); + + }; + + // 设置下拉树的基本参数值 + DTree.prototype.selectSetting = function() { + /** select模式参数*/ + this.select = true; //配置成select模式 + + this.selectInitVal = this.obj.attr("data-value") || this.options.selectInitVal || ""; //输入框的值 + this.selectTreeDiv = this.obj[0].id + "_tree_div"; // 上级DIV节点 + this.selectCardDiv = this.obj[0].id + "_select_card_div"; // 上级layui卡片节点 + this.selectDiv = this.obj[0].id + "_select_div"; // 模拟的select节点 + this.selectTipsName = this.obj[0].id + "_select_input"; // select的提示输入框名称 + this.selectTips = this.options.selectTips || "请选择"; // 输入框的提示语 + this.selectInputName = this.options.selectInputName || {nodeId: this.obj[0].id + "_select_nodeId"}; // select表单中的元素 + + // 调取下拉树的特殊处理页面元素标识 + this.renderSelectDom(); + } + + // 重新设置下拉树的基本参数值 + DTree.prototype.reloadSelectSetting = function() { + + this.selectInitVal = this.obj.attr("data-value") || this.options.selectInitVal || this.selectInitVal; //输入框的值 + this.selectTips = this.options.selectTips || this.selectTips; // 输入框的提示语 + this.selectInputName = $.extend(this.selectInputName, this.options.selectInputName) || this.selectInputName; // select表单中的元素 + + // 调取下拉树的特殊处理页面元素标识 + this.reloadSelectDom(); + } + + /******************** 下拉树设置区域 ********************/ + // 渲染下拉树的Dom结构 + DTree.prototype.renderSelectDom = function() { + var _this = this; + var rootId = _this.obj[0].id; + + // 设置自定义表单隐藏域 + var selectInputName = _this.selectInputName; + var selectInput = []; + for(var key in selectInputName) { + selectInput.push(''); + } + + // 设置html + var prevHtml = ['
        ', + '
        ', selectInput.join(""), + '', + '', + '
        '].join(''); + + _this.obj.before(prevHtml); + + _this.obj.wrap('
        ').wrap('
        ').wrap('
        '); + + } + + // 重新渲染下拉树的Dom结构 + DTree.prototype.reloadSelectDom = function() { + var _this = this; + var rootId = _this.obj[0].id; + + // 设置自定义表单隐藏域 + var selectInputName = _this.selectInputName; + var selectInput = []; + for(var key in selectInputName) { + selectInput.push(''); + } + + $("div[dtree-id='"+rootId+"'][dtree-select='"+_this.selectDiv+"']").find("div.layui-select-title").html(""); + + // 设置html + var prevHtml = [selectInput.join(""), + '', + ''].join(''); + + $("div[dtree-id='"+rootId+"'][dtree-select='"+_this.selectDiv+"']").find("div.layui-select-title").html(prevHtml); + + } + + // 设置输入框的值 + DTree.prototype.selectVal = function(param) { + var _this = this; + var rootId = _this.obj[0].id; + var selectInputName = _this.selectInputName; + var selectTipsNameValue = ""; + var selectValues = {}; + + // 如果开启了复选框,则此方法用来取值 + if(_this.checkbar) { + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "']").each(function(){ + var name = $(this).attr("name"); + var val = $(this).val(); + selectValues[name] = val; + }); + } else { + if(typeof param === 'undefined') { // 不传,则为当前树中记录的ID + param = _this.getNowParam(); + } + if(typeof param === 'string') { // 传递ID,则查询树节点ID对应的值 + param = _this.getParam(param); + } + + selectTipsNameValue = param["context"]; + for(var key in selectInputName) { + selectValues[selectInputName[key]] = param[key]; + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+selectInputName[key]+"']").val(param[key] || ""); + } + + if(param["nodeId"] && !param["context"]) { + selectTipsNameValue = _this.getParam(param["nodeId"]); + } + + // 返显提示输入框值 + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+_this.selectTipsName+"']").val(selectTipsNameValue || ""); + + } + + + // 返回隐藏域中的值 + return selectValues; + } + + // 设置复选框模式中的下拉树的值 + DTree.prototype.selectCheckboxVal = function() { + var _this = this; + var rootId = _this.obj[0].id; + var selectInputName = _this.selectInputName; + + // 获取全部复选框选中节点 + var param = _this.getCheckbarJsonArrParam(); + + selectTipsNameValue = param["context"]; + var selectValues = {}; + for(var key in selectInputName) { + var value = param[key].join(","); + selectValues[selectInputName[key]] = value; + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+selectInputName[key]+"']").val(value); + } + + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+_this.selectTipsName+"']").val(selectTipsNameValue); + + // 返回隐藏域中的值 + return selectValues; + } + + // 重置下拉树的值 + DTree.prototype.selectResetVal = function() { + var _this = this; + var rootId = _this.obj[0].id; + // 表单清空 + $("input[dtree-id='"+rootId+"']").val(""); + // 节点重置 + _this.cancelNavThis(); + if(_this.checkbar) { + // 复选框重置 + _this.cancelCheckedNode(); + } + } + + + /******************** 字体及图标区域 ********************/ + // 确认最终主题 + DTree.prototype.ensureTheme = function(){ + var _this = this; + + // 确认style + this.style.item = DTREE + this.skin + ITEM; + this.style.itemThis = DTREE + this.skin + ITEMTHIS; + this.style.dfont = DTREE + this.skin + DFONT; + this.style.ficon = DTREE + this.skin + FICON; + this.style.icon = DTREE + this.skin + ICON; + this.style.cbox = DTREE + this.skin + CBOX; + this.style.chs = DTREE + this.skin + CHS; + + // 确认usefontStyle + var iconfont = this.iconfont; + var iconfonts = []; + if(typeof iconfont === 'string') { + iconfonts.push(iconfont); + } else { + iconfonts = iconfont; + } + + var iconfontStyle = this.iconfontStyle; + var iconfontStyles = []; + if(iconfontStyle.length == undefined) { + iconfontStyles.push(iconfontStyle); + } else { + iconfontStyles = iconfontStyle; + } + + for(var i=0; i 0) { + $lis.each(function(){ + _this.showLineLi($(this)); + }); + } else { + _this.obj.find("li[data-id]").each(function(){ + _this.showLineLi($(this)); + }); + } + } + } + + // 真正显示树线的方法 + DTree.prototype.showLineLi = function($li){ + var _this = this; + var $div = $li.children("div"), + $nextLi = $li.next("li"), + $ul = $li.parent("ul"); + if($ul[0].id == _this.obj[0].id) { + // 根节点下的节点 + $li.removeClass(LI_NAV_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_FIRST_LINE); + } else { + // 非根节点下的节点 + var $pnextLi = $ul.parent("li").next("li"); + if($pnextLi.length == 0) { + if($nextLi.length == 0){ + $li.removeClass(LI_NAV_LINE); + $li.removeClass(LI_NAV_FIRST_LINE); + $li.addClass(LI_NAV_LAST_LINE); + } else { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_LINE); + } + }else { + var $pnextdiv = $pnextLi.children("div"); + if($nextLi.length == 0 && $div.children("cite").attr("data-leaf") == "leaf" && $pnextdiv.children("cite").attr("data-leaf") == "leaf") { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LINE); + $li.addClass(LI_NAV_LAST_LINE); + } else { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_LINE); + } + } + } + } + + /******************** 初始化数据区域 ********************/ + // 设置高度 + DTree.prototype.autoHeight = function(){ + var _this = this; + var height = _this.height; + if(height != "") { + if(_this.elem == _this.scroll){ + _this.obj.parent().css("height", height + "px"); + } else { + var $toolbarDiv = _this.obj.closest(_this.scroll); + $toolbarDiv.css("height", height + "px"); + } + } + }; + + // 重载树 + DTree.prototype.reload = function(options){ + var _this = this; + _this.reloadSetting(options); + _this.init(); + }; + + // 初始化树 + DTree.prototype.init = function(){ + var _this = this; + if (typeof _this !== "object") { + //_this.obj.html(_this.getNoneDom().errText("树组件未成功加载,请检查配置")); + layer.msg("树组件未成功加载,请检查配置", {icon:5}); + return ; + } + + // 设置组件高度 + _this.autoHeight(); + + if(_this.data) { + if(typeof _this.data.length === 'undefined'){ + //_this.obj.html(_this.getNoneDom().errText("数据解析异常,data数据格式不正确")); + layer.msg("数据解析异常,data数据格式不正确", {icon:5}); + return ; + } + + if(_this.data.length == 0) { + _this.obj.html(_this.getNoneDom().text()); + return ; + } + + //先将ul中的元素清空 + _this.obj.html(""); + + setTimeout(function () { + // 加载完毕后执行树解析前的回调 + _this.success(_this.data, _this.obj); + + // 第一次解析树 + if (_this.dataFormat == 'list'){ + //1.识别根节点ul中的data-id标签,判断顶级父节点 + var pid = _this.obj.attr("data-id"); + //2.构建一个存放节点的树组 + var rootListData = _this.queryListTreeByPid(pid, _this.data); + _this.loadListTree(rootListData, _this.data, 1); + } else { + _this.loadTree(_this.data, 1); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + // 设置复选框的初始值 + if(_this.select){ + _this.selectVal(_this.selectInitVal); + } + + // 保存树副本 + _this.bak = _this.obj.html(); + + // 加载完毕后的回调 + _this.done(_this.data, _this.obj); + }, 100); + } else { + if (!_this.url) { + //_this.obj.html(_this.getNoneDom().errText("数据请求异常,url参数未指定")); + layer.msg("数据请求异常,url参数未指定", {icon:5}); + return ; + } + + //先将ul中的元素清空 + _this.obj.html(""); + + var index = _this.load ? layer.load(1) : ""; + + AjaxHelper.request({ + async: _this.async, + headers: _this.headers, + type: _this.method, + url: _this.url, + dataType: _this.dataType, + contentType: _this.contentType, + withCredentials: _this.withCredentials, + data: _this.getFilterRequestParam(_this.getRequestParam()), + success: function(result) { + if (typeof result === 'string') { + result = $.parseJSON(result); + } + + // 加载完毕后执行树解析前的回调 + _this.success(result, _this.obj); + + var code = ""; + if (_this.dataStyle == 'layuiStyle'){ + code = result[_this.response.statusName]; + } else { + code = result.status[_this.response.statusName]; + } + + if (code == _this.response.statusCode) { + var d = result[_this.response.rootName]; + + if(typeof d.length === 'undefined'){ + _this.obj.html(_this.getNoneDom().errText("数据解析异常,url回调后的数据格式不正确")); + //layer.msg("数据解析异常,url回调后的数据格式不正确", {icon:5}); + return ; + } + + if(d.length == 0) { + _this.obj.html(_this.getNoneDom().text()); + return ; + } + + // 第一次解析树 + if (_this.dataFormat == 'list'){ + //1.识别根节点ul中的data-id标签,判断顶级父节点 + var pid = _this.obj.attr("data-id"); + //2.构建一个存放节点的树组 + var rootListData = _this.queryListTreeByPid(pid, d); + _this.loadListTree(rootListData, d, 1); + } else { + _this.loadTree(d, 1); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + // 设置复选框的初始值 + if(_this.select){ + _this.selectVal(_this.selectInitVal); + } + + // 保存树副本 + _this.bak = _this.obj.html(); + + // 加载完毕后的回调 + _this.done(result, _this.obj); + } else { + // 如果打印不出任何信息说明是在这里,用了错误的数据格式, 或返回码不正确 + if (_this.dataStyle == 'layuiStyle'){ + _this.obj.html(_this.getNoneDom().errText(result[_this.response.message])); + _this.error(null, code, result[_this.response.message]); + //layer.msg(result[_this.response.message], {icon:2}); + } else { + _this.obj.html(_this.getNoneDom().errText(result.status[_this.response.message])); + _this.error(null, code, result.status[_this.response.message]); + //layer.msg(result.status[_this.response.message], {icon:2}); + } + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown){// 异步加载异常回调 + _this.obj.html(_this.getNoneDom().errText(textStatus + ": " + errorThrown)); + _this.error(XMLHttpRequest, textStatus, errorThrown); + }, + complete: function(XMLHttpRequest, textStatus){// 异步加载完成回调 + if(_this.load){layer.close(index);} + _this.complete(XMLHttpRequest, textStatus); + } + }); + } + }; + + // 加载子节点 + DTree.prototype.getChild = function($div, data) { + var _this = this, $ul = $div.next("ul"); + + _this.setNodeParam($div); + + if(typeof data !== 'undefined') { + if(typeof data.length === 'undefined'){ + //_this.obj.html(_this.getNoneDom().errText("数据解析异常,data数据格式不正确")); + layer.msg("数据解析异常,data数据格式不正确", {icon:5}); + return ; + } + + //先将ul中的元素清空 + $ul.html(""); + + // 解析树 + if (_this.dataFormat == 'list'){ + var pid = _this.node.nodeId; + var level = parseInt(_this.node.level)+1; + + var listData = _this.queryListTreeByPid(pid, data); + _this.loadListTree(listData, _this.data, level); + } else { + _this.loadTree(data, level); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + // 保存树副本 + _this.bak = _this.obj.html(); + + } else { + if (!_this.url) { + //_this.obj.html(_this.getNoneDom().errText("数据请求异常,url参数未指定")); + layer.msg("数据请求异常,url参数未指定", {icon:5}); + return ; + } + + $ul.html(""); + var index = _this.load ? layer.load(1) : ""; + AjaxHelper.request({ + async: _this.async, + headers: _this.headers, + type: _this.method, + url: _this.url, + dataType: _this.dataType, + withCredentials: _this.withCredentials, + data: _this.getFilterRequestParam(_this.getRequestParam()), + success: function(result) { + if (typeof result === 'string') { + result = $.parseJSON(result); + } + var code = ""; + if (_this.dataStyle == 'layuiStyle'){ + code = result[_this.response.statusName]; + } else { + code = result.status[_this.response.statusName]; + } + + if (code == _this.response.statusCode) { + // 解析树 + var pid = _this.node.nodeId; + var level = parseInt(_this.node.level)+1; + if (_this.dataFormat == 'list'){ + var pListData = _this.queryListTreeByPid(pid, result[_this.response.rootName]); + _this.loadListTree(pListData, result[_this.response.rootName], level, $ul); + } else { + _this.loadTree(result[_this.response.rootName], level, $ul); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + $ul.addClass(NAV_SHOW); + + // 保存树副本 + _this.bak = _this.obj.html(); + } else { + if (_this.dataStyle == 'layuiStyle'){ + _this.obj.html(_this.getNoneDom().errText(result[_this.response.message])); + _this.error(null, code, result[_this.response.message]); + //layer.msg(result[_this.response.message], {icon:2}); + } else { + _this.obj.html(_this.getNoneDom().errText(result.status[_this.response.message])); + _this.error(null, code, result.status[_this.response.message]); + //layer.msg(result.status[_this.response.message], {icon:2}); + } + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown){// 异步加载异常回调 + _this.obj.html(_this.getNoneDom().errText(textStatus + ": " + errorThrown)); + _this.error(XMLHttpRequest, textStatus, errorThrown); + }, + complete: function(XMLHttpRequest, textStatus){// 异步加载完成回调 + if(_this.load){layer.close(index);} + _this.complete(XMLHttpRequest, textStatus); + } + }); + } + }; + + // 初始化树或者拼接树 + DTree.prototype.loadListTree = function(pListData, listData, level, $ul){ + var _this = this; + $ul = $ul || _this.getNodeDom().nowOrRootUl(); //当前选中的节点或根节点 + if (pListData.length > 0){ + for (var i = 0; i < pListData.length; i++) { + // 1.获取已知节点的全部数据 + var data = pListData[i]; + if(typeof data !== "object") continue; + var parseData = _this.parseData(data); + var childListData = _this.queryListTreeByPid(parseData.treeId(), listData); // 根据已知数据的id判断该条数据是否还有子数据 + + // 3. 页面元素加载数据 + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(childListData.length), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(level), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), ($ul.hasClass(UL_ROOT) ? "root" : "item"))); + // 4.有子数据的元素加载子节点 + if(childListData.length > 0){ + var cLevel = parseInt(level)+1; + _this.loadListTree(childListData, listData, cLevel, _this.obj.find("ul[data-id='"+parseData.treeId()+"']")); + } + } + } + }; + + // 根据父ID查找list数据中匹配的元素 + DTree.prototype.queryListTreeByPid = function(pid, listData){ + var _this = this; + var rootListData = []; + if (listData) { + for (var i = 0; i < listData.length; i++) { + var data = listData[i]; + if(typeof data !== "object") continue; + if(pid == "null" || pid == null){ + if(data[_this.response.parentId] == null) { rootListData.push(data); } + } else { + if (data[_this.response.parentId] == pid){ + if (data[_this.response.treeId] == pid){ + _this.errData.push(data); + } else { + rootListData.push(data); + } + } + } + } + } + return rootListData; + }; + + // 初始化树或者拼接树 + DTree.prototype.loadTree = function(root, level, $ul){ + var _this = this; + if (root) { + $ul = $ul || _this.getNodeDom().nowOrRootUl(); //当前选中的节点或根节点 + for (var i = 0; i < root.length; i++) { // 遍历跟节点或追加的跟节点 + var data = root[i]; + if(typeof data !== "object") continue; + if(data[_this.response.treeId] == data[_this.response.parentId]) { _this.errData.push(data); } + var parseData = _this.parseData(data); + var children = parseData.children(); + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(children.length), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(level), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), ($ul.hasClass(UL_ROOT) ? "root" : "item"))); + if (children.length != 0) { + var cLevel = parseInt(level)+1; + _this.loadTree(children, cLevel, _this.obj.find("ul[data-id='"+parseData.treeId()+"']")); + } + } + } + }; + + // 判断在数据加载时是否存在错误数据,并是否打印错误数据 + DTree.prototype.msgErrData = function() { + var _this = this; + if(_this.errData.length > 0 && _this.errDataShow) { + var title = ""; + for(var i=0; i<_this.errData.length; i++) { + var edata = _this.errData[i]; + title += "数据:【"+edata[_this.response.title]+"】中节点id和上级id值一致! \n"; + } + layer.msg(title, {icon:2,time:5000}); + } + // 显示之后,将错误数据制空 + _this.errData = []; + }; + + // 解析data数据 + DTree.prototype.parseData = function(data) { + var _this = this; + + return { + treeId: function(){ + return data[_this.response.treeId]; + }, + parentId: function(){ + return data[_this.response.parentId]; + }, + fmtTitle: function(){ + if(typeof _this.formatter.title === 'function'){ + var ftitle = _this.formatter.title(data); + var tt = data[_this.response.title]; + tt = (ftitle == "" || ftitle == undefined || ftitle == null) ? tt : ftitle; + return tt || ""; + } + return data[_this.response.title]; + }, + title: function(){ + return data[_this.response.title]; + }, + level: function(){ + return data[_this.response.level] || ""; + }, + ficonClass: function(){ + return data[_this.response.ficonClass] || ""; + }, + iconClass: function(){ + return data[_this.response.iconClass] || ""; + }, + last: function(len){ + return ((len == 0) ? + ((typeof (data[_this.response.last]) === "boolean") ? data[_this.response.last] : true) : + ((typeof (data[_this.response.last]) === "boolean") ? data[_this.response.last] : false)); + }, + spread: function(level){ + return ((level < _this.initLevel) ? + ((typeof (data[_this.response.spread]) === "boolean") ? data[_this.response.spread] : true) : + ((typeof (data[_this.response.spread]) === "boolean") ? data[_this.response.spread] : false)); + }, + disabled: function(){ + return (typeof (data[_this.response.disabled]) === "boolean") ? data[_this.response.disabled] : false; + }, + hide: function(){ + return (typeof (data[_this.response.hide]) === "boolean") ? data[_this.response.hide] : false; + }, + checkArr: function(){ + var checkArr = []; + var checkArrData = data[_this.response.checkArr]; + if(typeof checkArrData === 'string'){ + if(checkArrData.indexOf("{") > -1 && checkArrData.indexOf("}") > -1){ + checkArrData = JSON.parse(checkArrData); + } else { + checkArrData = {"type":"0","checked":checkArrData}; + } + } + if(typeof checkArrData === 'object'){ + if(typeof checkArrData.length === 'undefined'){ + checkArr.push(checkArrData); + } else { + checkArr = checkArrData; + } + } + + if(checkArr.length > 0 && checkArr.length > _this.checkArrLen){ + _this.checkArrLen = checkArr.length; // 获取复选框个数 + } + return checkArr; + + }, + children: function(){ + return data[_this.response.childName] || []; + }, + basicData: function(){ + return event.escape(JSON.stringify(data[_this.response.basicData])) || JSON.stringify({}); + }, + recordData: function(){ + var recordData = _this.record ? event.cloneObj(data, [_this.response.treeId, + _this.response.parentId, + _this.response.title, + _this.response.iconClass, + _this.response.childName, + _this.response.last, + _this.response.spread, + _this.response.disabled, + _this.response.hide, + _this.response.checkArr, + _this.response.checked, + _this.response.type, + _this.response.basicData]) : {}; + + return event.escape(JSON.stringify(recordData)); + }, + data: function(){ + return data; + } + } + + }; + + //当无节点数据时显示dom + DTree.prototype.getNoneDom = function(){ + var _this = this, + rootId = _this.obj[0].id, + noneTitle = _this.none; + + return { + text: function(){ + return "
        "+noneTitle+"
        "; + }, + errText: function(errInfo){ + return "
        "+errInfo+"
        "; + } + } + }; + + //新增节点的dom值 + DTree.prototype.getDom = function(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide) { + var _this = this, + rootId = _this.obj[0].id, + toolbar = _this.toolbar, + checkbar = _this.checkbar; + + return { + fnode: function() { // + - 图标 + // 获取图标的变量 + var fnodeIcon = _this.fnodeIcon, + fleafIcon = _this.fleafIcon; + + var fleafIconLeaf = _this.usefontStyle.fnode.leaf, + fnodeIconOpen = _this.usefontStyle.fnode.node.open, + fnodeIconClose = _this.usefontStyle.fnode.node.close; + + if(ficonClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + fleafIconLeaf = iconfont + " " + ficonClass; + fnodeIconOpen = iconfont + " " + ficonClass; + fnodeIconClose = iconfont + " " + ficonClass; + } else { + fleafIconLeaf = iconfont[0] + " " + ficonClass; + fnodeIconOpen = iconfont[0] + " " + ficonClass; + fnodeIconClose = iconfont[0] + " " + ficonClass; + } + } + + if(fnodeIcon != "-1" && fleafIcon != "-1"){ // 都加载 + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon != "-1" && fleafIcon == "-1"){ // 加载node 隐藏leaf + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon == "-1" && fleafIcon != "-1"){ // 隐藏node 加载leaf + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon == "-1" && fleafIcon == "-1"){ // 都隐藏 + return last ? "" : + (spread ? "" : ""); + } + }, + node: function() { // 二级图标样式 + // 获取图标的变量 + var nodeIcon = _this.nodeIcon, + leafIcon = _this.leafIcon; + + var sleafIconLeaf = _this.usefontStyle.snode.leaf, + snodeIconOpen = _this.usefontStyle.snode.node.open, + snodeIconClose = _this.usefontStyle.snode.node.close; + if(iconClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + sleafIconLeaf = iconfont + " " + iconClass; + snodeIconOpen = iconfont + " " + iconClass; + snodeIconClose = iconfont + " " + iconClass; + } else { + sleafIconLeaf = iconfont[0] + " " + iconClass; + snodeIconOpen = iconfont[0] + " " + iconClass; + snodeIconClose = iconfont[0] + " " + iconClass; + } + } + + if(nodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + return last ? "" : + (spread ? "" : ""); + } + }, + checkbox: function() { // 复选框 + var flag = false; + if(_this.checkbarLoad == "node"){if (checkbar) {flag = true;}} else {if (last) {if (checkbar) {flag = true;}}} + + if(flag){ + var result = "
        "; + if(checkArr && checkArr.length > 0){ + + for (var i = 0; i < checkArr.length; i++) { + var checkData = checkArr[i]; + var checked = checkData.checked; + var CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + if (checked == "2") { //半选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.noall + " " + _this.style.chs; + } else if (checked == "1") { //选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.on + " " + _this.style.chs; + } else { //未选择或者无值 + CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + } + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + result += ""; + } + } + result += "
        "; + return result; + } + + return ""; + }, + text: function() { // 文字显示 + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + return ""+fmtTitle+""; + }, + ul: function() { //子节点ul + return last ? "
          " : + (spread ? "
            " : "
              "); + } + }; + }; + + //替换节点的dom值,或指定值 + DTree.prototype.replaceDom = function($div, treeId, last, spread, disabled, hide) { + var _this = this, + rootId = _this.obj[0].id, + toolbar = _this.toolbar, + checkbar = _this.checkbar; + + return { + fnode: function(ficonClass) { // + - 图标 + var fnode = ""; + + // 获取图标的变量 + var fnodeIcon = _this.fnodeIcon, + fleafIcon = _this.fleafIcon; + + var fleafIconLeaf = _this.usefontStyle.fnode.leaf, + fnodeIconOpen = _this.usefontStyle.fnode.node.open, + fnodeIconClose = _this.usefontStyle.fnode.node.close; + + if(ficonClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + fleafIconLeaf = iconfont + " " + ficonClass; + fnodeIconOpen = iconfont + " " + ficonClass; + fnodeIconClose = iconfont + " " + ficonClass; + } else { + fleafIconLeaf = iconfont[0] + " " + ficonClass; + fnodeIconOpen = iconfont[0] + " " + ficonClass; + fnodeIconClose = iconfont[0] + " " + ficonClass; + } + } + + if(fnodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + fnode = last ? "" : + (spread ? "" : ""); + } + if(fnode != ""){_this.getNodeDom($div).fnode().replaceWith($(fnode));} + }, + node: function(iconClass) { // 二级图标样式 + var snode = ""; + + // 获取图标的变量 + var nodeIcon = _this.nodeIcon, + leafIcon = _this.leafIcon; + + var sleafIconLeaf = _this.usefontStyle.snode.leaf, + snodeIconOpen = _this.usefontStyle.snode.node.open, + snodeIconClose = _this.usefontStyle.snode.node.close; + if(iconClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + sleafIconLeaf = iconfont + " " + iconClass; + snodeIconOpen = iconfont + " " + iconClass; + snodeIconClose = iconfont + " " + iconClass; + } else { + sleafIconLeaf = iconfont[0] + " " + iconClass; + snodeIconOpen = iconfont[0] + " " + iconClass; + snodeIconClose = iconfont[0] + " " + iconClass; + } + } + + if(nodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + snode = last ? "" : + (spread ? "" : ""); + } + if(snode != ""){_this.getNodeDom($div).snode().replaceWith($(snode));} + }, + checkbox: function(checkArr) { // 复选框 + var flag = false; + if(_this.checkbarLoad == "node"){if (checkbar) {flag = true;}} else {if (last) {if (checkbar) {flag = true;}}} + + if(flag){ + var result = "
              "; + if(checkArr && checkArr.length > 0){ + + for (var i = 0; i < checkArr.length; i++) { + var checkData = checkArr[i]; + var checked = checkData.checked; + var CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + if (checked == "2") { //半选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.noall + " " + _this.style.chs; + } else if (checked == "1") { //选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.on + " " + _this.style.chs; + } else { //未选择或者无值 + CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + } + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + result += ""; + } + } + result += "
              "; + _this.getNodeDom($div).snode().next("div").replaceWith($(result)); + } + }, + text: function(title) { // 文字显示 + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + var cite = ""+title+"" + _this.getNodeDom($div).cite().replaceWith($(cite)); + }, + ul: function() { //子节点ul + var ul = last ? "
                " : + (spread ? "
                  " : "
                    "); + _this.getNodeDom($div).nextUl().replaceWith($(ul)); + }, + div: function(){ + $div.attr("data-id", treeId); + }, + basicData: function(basicData){ + basicData = (basicData == "{}") ? "" : basicData; + $div.attr("data-basic", basicData); + }, + recordData: function(recordData){ + recordData = (recordData == "{}") ? "" : recordData; + $div.attr("data-record", recordData); + }, + p_li: function(pId){ + var $li = $div.parent("li"); + $li.attr("data-id", treeId); + if(pId) { + $li.attr("data-pid", pId); + } + return $li; + } + }; + + }; + + // 获取拼接好的li + DTree.prototype.getLiItemDom = function(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide, basicData, recordData, flag) { + var _this = this, + rootId = _this.obj[0].id; + + var dom = _this.getDom(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide); + basicData = (basicData == "{}") ? "" : basicData; + recordData = (recordData == "{}") ? "" : recordData; + var div = "
                    " + + div , + dom.fnode(), + dom.node(), + dom.checkbox(), + dom.text(), + "
                    ", dom.ul(), ""].join(""); + + return li; + }; + + // 初始化节点,用于数据回显 + DTree.prototype.dataInit = function(chooseId){ + var _this = this; + var $div = _this.obj.find("div[data-id='"+chooseId+"']"); + _this.getNodeDom($div).parentLi().find("."+NAV_THIS).removeClass(NAV_THIS); + _this.getNodeDom($div).parentLi().find("."+_this.style.itemThis).removeClass(_this.style.itemThis); + $div.addClass(NAV_THIS); + $div.addClass(_this.style.itemThis); + _this.setNodeParam($div); + // 将该节点的父节点全部展开 + var $li_parents = $div.parents("."+LI_NAV_ITEM); + $li_parents.children("ul").addClass(NAV_SHOW); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.fnode.node.close)).addClass(_this.usefontStyle.fnode.node.open); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.fnode.node.close)).removeClass(_this.usefontStyle.fnode.node.close); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.snode.node.close)).addClass(_this.usefontStyle.snode.node.open); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.snode.node.close)).removeClass(_this.usefontStyle.snode.node.close); + return _this.getNowParam(); + }; + + // 基于备份的Html数据回滚 + DTree.prototype.rollbackHtml = function(chooseId){ + var _this = this; + if(_this.bak) { + _this.obj.html(_this.bak); + // 取消全部选中状态 + _this.cancelNavThis(); + if(_this.checkbar) { + _this.cancelCheckedNode(); + _this.chooseDataInit(chooseId); + } else { + _this.dataInit(chooseId); + } + + _this.bak = _this.obj.html(); + } + }; + + + /******************** 基础事件区域 ********************/ + // 数据格式化 + DTree.prototype.escape = function(html){ + return event.escape(html); + }; + + // 格式化数据转回正常数据 + DTree.prototype.unescape = function(str){ + return event.unescape(str); + }; + + // 取消选中div + DTree.prototype.cancelNavThis = function(){ + var _this = this; + _this.obj.find("div[data-id]").parent().find("."+NAV_THIS).removeClass(NAV_THIS); + _this.obj.find("div[data-id]").parent().find("."+_this.style.itemThis).removeClass(_this.style.itemThis); + } + + // 选中div + DTree.prototype.navThis = function(id){ + var _this = this; + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null) { + _this.cancelNavThis(); + $div.addClass(NAV_THIS); + $div.addClass(_this.style.itemThis); + } + } + + // 手风琴模式操作其他节点 + DTree.prototype.accordionUL = function($ul) { + var _this = this; + if(_this.accordion) { + $ul.closest("li[data-index]").siblings("li[data-index]").children("ul[data-id]").removeClass(NAV_SHOW); + var $divs = $ul.closest("li[data-index]").siblings("li[data-index]").children("ul[data-id]").prev("div"); + if($divs.length && $divs.length > 0) { + for (var i=0; i<$divs.length; i++) { + var $div = $($divs[i]); + var $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(); + if($i_spread.attr("data-spread") != 'last'){ + _this.operateIcon($i_spread, $i_node).close(); + } + } + } + + } + }; + + // 展开或隐藏节点 作用点: div + DTree.prototype.clickSpread = function($div) { + var _this = this; + var $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + $ul = $div.next("ul"); + + if ($ul.length > 0) { + if (spread == "close") { + if (_this.type=="load") { //增加加载 + if (_this.cache) { //开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + _this.accordionUL($ul); + } else { //加载节点 + _this.getChild($div); + _this.accordionUL($ul); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + _this.accordionUL($ul); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + _this.accordionUL($ul); + } + _this.operateIcon($i_spread, $i_node).open(); + } else if (spread == "open") { + $ul.removeClass(NAV_SHOW); + _this.operateIcon($i_spread, $i_node).close(); + } + } + }; + + // 设置节点为disabled + DTree.prototype.setDisabledNodes = function(disabledIds){ + var _this = this; + var disabledId = disabledIds.split(","); + for (var i=0; i 0) { + _this.getChild($div, data); + } else { + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var level = parseInt($div.parent("li").attr("data-index"))+1; + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(0), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), "item")); + + // 建造完毕后,选中该DIV + $thisDiv = $ul.find("div[data-id='"+parseData.treeId()+"']"); + _this.setNodeParam($thisDiv); + + _this.showLine($ul.find("li")); + } else { + layer.msg("添加失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } + } else { + _this.getChild($div); + } + } + + // 局部刷新树--编辑当前节点选中节点时 + DTree.prototype.partialRefreshEdit = function($div, data){ + var _this = this; + $ul = $div.next("ul"), + $p_li = $div.parent("li"); + + if(data) { + if(typeof data === 'object') { + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var replaceDom = _this.replaceDom($div, parseData.treeId(), parseData.last(0), parseData.spread(), parseData.disabled(), parseData.hide()); + replaceDom.div(); + replaceDom.node(parseData.iconClass()); + replaceDom.checkbox(parseData.checkArr()); + replaceDom.text(parseData.title()); + replaceDom.ul(); + replaceDom.basicData(parseData.basicData()); + replaceDom.recordData(parseData.recordData()); + + var parentId = parseData.parentId(); + var oldParentId = $p_li.attr("data-pid"); + if(parentId && parentId != oldParentId) { + // 变更了父节点 + $p_li = replaceDom.p_li(parentId); + + // 根据parentId找到下挂节点的ul + var $goto_div = _this.getNodeDom(parentId).div(), + $goto_ul = _this.getNodeDom(parentId).nextUl(); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($goto_ul.children("li").length == 0){ + var $icon_i = $goto_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).openWithLeaf(); + $goto_ul.addClass(NAV_SHOW); + } + $goto_ul.append($p_li); + } else { + replaceDom.p_li(); + } + _this.setNodeParam($div); + } else { + layer.msg("编辑失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } else { + _this.getNodeDom($div).cite().html(data); + } + } + } + + // 局部刷新树--当前节点选中被删除时 + DTree.prototype.partialRefreshDel = function($div){ + var _this = this; + $p_li = $div.parent("li"); + $p_ul = _this.getNodeDom($div).parentUl(); + $p_div = _this.getNodeDom($div).parentDiv(); + + $p_li.remove(); + _this.showLine($p_ul.find("li")); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($p_ul.children("li").length == 0){ + var $icon_i = $p_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).closeWithLeaf(); + } + _this.initNodeParam(); + } + + /******************** 复选框区域 ********************/ + // 初始化复选框的值 + DTree.prototype.chooseDataInit = function(chooseIds){ + var _this = this; + var chooseId = chooseIds.split(","); + for (var i=0; i."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + if (flag == 0) { + //把父级去掉选中 + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($item_i).noCheck(); + } + } + } else { + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + //把父级选中 + _this.checkStatus($item_i).check(); + } + } + }; + + //实现复选框点击, no-all 子集选中父级半选中,子集全选父级选中 + DTree.prototype.checkAllOrNoallOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag == 0) { + //把父级去掉选中 + _this.checkStatus($item_i).noCheck(); + } else { + //把父级半选 + _this.checkStatus($item_i).noallCheck(); + } + } + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag1 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var flag2 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag1 != flag2) { + // 父级复选框半选 + _this.checkStatus($item_i).noallCheck(); + } else { + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + }; + + //实现复选框点击,p-casc:父级选中子集全选,子集无法改变父级选中状态 + DTree.prototype.checkAllOrPcascOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + } + }; + + //实现复选框点击,self:各自选中互不影响 + DTree.prototype.checkOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + } + }; + + //实现复选框点击,only:只能选中1个复选框 + DTree.prototype.checkOnly = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + var checked = $i.attr("data-checked"); + // 将全部节点全部设为未选中状态 + var $all_i = _this.obj.find("i[data-checked]"); + _this.checkStatus($all_i).noCheck(); + + if (checked != "1") { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + } + }; + + //实现复选框点击 + DTree.prototype.changeCheck = function($i) { + var _this = this; + var temp = _this.temp; + if(typeof $i === 'undefined') { + $i = temp[0]; + } + // 复选框选中事件 + if (_this.checkbarType == "all") { + _this.checkAllOrNot($i); + } else if(_this.checkbarType == "no-all") { + _this.checkAllOrNoallOrNot($i); + } else if(_this.checkbarType == "p-casc") { + _this.checkAllOrPcascOrNot($i); + } else if(_this.checkbarType == "self") { + _this.checkOrNot($i); + } else if(_this.checkbarType == "only") { + _this.checkOnly($i); + } else { + _this.checkAllOrNot($i); + } + + if(_this.select) { + // 设置复选框模式中的下拉树的值 + _this.selectCheckboxVal(); + } + + // 获取复选框选中节点的内容 + var checkbarNodes = _this.setAndGetCheckbarNodesParam(true); + + // 用户自定义想做的事情 + _this.checkbarFun.chooseDone(checkbarNodes); + layui.event.call(this, MOD_NAME, "chooseDone("+$(_this.obj)[0].id+")", {"checkbarParams": checkbarNodes}); + _this.temp = []; + }; + + //复选框半选状态初始化设置 + DTree.prototype.initNoAllCheck = function(){ + var _this = this; + //1.获取所有选中节点 + var $is = _this.obj.find("i[data-checked='1']"); + if($is.length > 0){ + for ( var key = 0; key < $is.length; key++) { + var $i = $($is[key]), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag1 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var flag2 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag1 != flag2) { + // 父级复选框半选 + _this.checkStatus($item_i).noallCheck(); + } else { + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + } + }; + + //复选框选中状态初始化设置 + DTree.prototype.initAllCheck = function(){ + var _this = this; + //1.获取所有选中节点 + var $is = _this.obj.find("i[data-checked='1']"); + if($is.length > 0){ + for ( var key = 0; key < $is.length; key++) { + var $i = $($is[key]), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + }; + + // 设置复选框选中/未选中/半选 _this.checkStatus($i).check(); _this.checkStatus($i).noCheck(); _this.checkStatus($i).noallCheck(); + DTree.prototype.checkStatus = function($i) { + var _this = this; + return { + check: function(){ + $i.removeClass(_this.usefontStyle.checkbox.out); + $i.removeClass(_this.usefontStyle.checkbox.noall); + $i.addClass(_this.usefontStyle.checkbox.on); + $i.addClass(_this.style.chs); + $i.attr("data-checked","1"); + }, + noCheck: function(){ + $i.removeClass(_this.usefontStyle.checkbox.noall); + $i.removeClass(_this.usefontStyle.checkbox.on); + $i.removeClass(_this.style.chs); + $i.addClass(_this.usefontStyle.checkbox.out); + $i.attr("data-checked","0"); + }, + noallCheck: function(){ + $i.removeClass(_this.usefontStyle.checkbox.out); + $i.removeClass(_this.usefontStyle.checkbox.on); + $i.addClass(_this.usefontStyle.checkbox.noall); + $i.addClass(_this.style.chs); + $i.attr("data-checked","2"); + } + } + }; + + // 设置树的复选框操作值的全部参数,并获取 + DTree.prototype.setAndGetCheckbarNodesParam = function(requestParamFlag) { + var _this = this; + //操作前先清空 + _this.checkbarNode = []; + // 选择所有复选框节点 + if (_this.checkbarData == "change"){ //记录变更数据 + _this.obj.find("i[data-par][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if ($i.attr("data-checked") != $i.attr("data-initchecked")) { + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + } + }); + } else if (_this.checkbarData == "all"){ //记录全部数据 + _this.obj.find("i[data-par][data-checked][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } else if (_this.checkbarData == "choose"){ //记录选中数据 + _this.obj.find("i[data-par][data-checked='1'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } else if (_this.checkbarData == "halfChoose"){ //记录选中和半选数据 + _this.obj.find("i[data-par][data-checked='1'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + _this.obj.find("i[data-par][data-checked='2'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } + return _this.checkbarNode; + }; + + // 获取树的复选框操作值的全部参数 + DTree.prototype.getCheckbarNodesParam = function() { + var _this = this; + return _this.setAndGetCheckbarNodesParam(true); + }; + + // 获取树的一个复选框的参数 + DTree.prototype.getCheckbarNodeParam = function($div, $i){ + var _this = this; + var temp_node = {}; + temp_node.nodeId = $div.attr("data-id"); + temp_node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + temp_node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + temp_node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + temp_node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + temp_node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + temp_node.basicData = basicData; + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + temp_node.recordData = recordData; + + temp_node.dataType = $i.attr("data-type"); + temp_node.checked = $i.attr("data-checked"); + temp_node.initchecked = $i.attr("data-initchecked"); + return temp_node; + }; + + // 获取基于返回参数的树的复选框参数 + DTree.prototype.getCheckbarJsonArrParam = function(){ + var _this = this; + var checkbarJsonArr = { + nodeId: [], //节点ID + parentId: [], //父节点ID + context: [], //节点内容 + leaf: [], //是否叶子节点 + level: [], //层级 + spread: [], //节点展开状态 + dataType: [], //节点标记 + checked: [], //节点复选框选中状态 + initchecked: [], //节点复选框初始状态 + basicData: [], //用户自定义的记录节点数据 + recordData: [], //当前data数据(排除basicData和children字段) + }; + // 获取全部复选框选中节点 + var params = _this.setAndGetCheckbarNodesParam(false); + if(params && params.length > 0) { + for(var i=0; i 0) { _this.checkStatus($i).check(); } + } + + //取消全部复选框选中 + DTree.prototype.cancelCheckedNode = function(nodeId){ + var _this = this; + var $i = _this.obj.find("i[data-par][data-checked!='0']"); + if($i.length > 0) { _this.checkStatus($i).noCheck(); } + } + + //反选复选框 + DTree.prototype.invertCheckedNode = function(nodeId){ + var _this = this; + if(_this.obj.find("i[data-par]").length > 0) { + var b = false; + _this.obj.find("i[data-par]").each(function(){ + var $i = $(this); + if($i.attr("data-checked") == '2'){ + b = true; + }else if($i.attr("data-checked") == '0') { + _this.checkStatus($i).check(); + }else if($i.attr("data-checked") == '1') { + _this.checkStatus($i).noCheck(); + } + }); + + if(b) { + _this.initNoAllCheck(); + } else { + _this.initAllCheck(); + } + } + } + + //删除选中节点 + DTree.prototype.removeCheckedNode = function(nodeId){ + var _this = this; + var len = _this.obj.find("i[data-par][data-checked='1']").length; + if(len == 0){ + layer.msg("请至少选中一个节点",{icon:2}); + }else{ + //操作前先清空 + _this.checkbarNode = []; + // 选择所有复选框节点 + var i_node = {}; + _this.obj.find("i[data-par][data-checked='1']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + }); + + layer.confirm('确定要删除选中节点?', {icon: 3, title:'删除选中节点'}, function(index1){ + var flag = _this.menubarFun.remove(_this.checkbarNode); + if(flag){ + _this.obj.find("i[data-par][data-checked='1']").closest("."+LI_DIV_ITEM).next("ul").remove(); + _this.obj.find("i[data-par][data-checked='1']").closest("."+LI_DIV_ITEM).remove(); + _this.checkbarNode=[]; + } + + layer.close(index1); + }); + } + } + + /******************** 工具栏及菜单栏区域 ********************/ + // 初始化菜单栏和工具栏的div + DTree.prototype.initTreePlus = function(){ + var _this = this; + // 初始化菜单栏和工具栏的div + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).remove(); + _this.toolbarMenu = {}; + if(_this.menubar && _this.menubarTips.group && _this.menubarTips.group.length > 0) _this.obj.before("
                    "); + if(_this.toolbar){ + if(_this.toolbarWay == "contextmenu") { + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).remove(); + _this.obj.before("
                    "); + } + } + + }; + + // 开启工具栏和菜单栏 + DTree.prototype.openTreePlus = function(){ + var _this = this; + // 先对工具栏做处理,因为菜单栏可能会与工具栏产生关联。 + var ggMenu = []; + if(_this.toolbar) _this.getToolbarDom(); + + if(_this.menubar) { + var menubarTips = _this.menubarTips, + mtbar = menubarTips.toolbar, + group = menubarTips.group, + freedom = menubarTips.freedom; + if(mtbar && mtbar.length > 0){ + // 菜单栏吸附工具栏上 + for(var i=0; i 0){ + // 菜单栏吸附在上方的按钮组div中 + for(var i=0; i"; + break; + case defaultMenu.moveUp: + gg = ""; + break; + case defaultMenu.refresh: + gg = ""; + break; + case defaultMenu.checkAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.unCheckAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.invertAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.remove: + gg = (_this.checkbar) ? "" : ""; + break; + case defaultMenu.searchNode: + gg = ""; + break; + } + return gg; + }; + + // 获取扩展菜单栏 + DTree.prototype.getExtMenubarDom = function(menu){ + var _this = this; + return ""; + }; + + // 获取依附在工具栏的菜单栏 + DTree.prototype.getMenubarToolDom = function(menu){ + var _this = this; + var rootId = _this.obj[0].id; + switch (menu) { + case defaultMenu.moveDown: + _this.toolbarMenu[defaultMenu.moveDown] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.moveDown, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.movedown, "展开全部"); + break; + case defaultMenu.moveUp: + _this.toolbarMenu[defaultMenu.moveUp] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.moveUp, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.moveup, "收缩全部"); + break; + case defaultMenu.refresh: + _this.toolbarMenu[defaultMenu.refresh] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.refresh, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.refresh, "刷新"); + break; + case defaultMenu.checkAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.checkAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.checkAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.checkAll, "全选节点"); + break; + case defaultMenu.unCheckAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.unCheckAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.unCheckAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.unCheckAll, "全不选节点"); + break; + case defaultMenu.invertAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.invertAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.invertAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.invertAll, "反选节点"); + break; + case defaultMenu.remove: + if(_this.checkbar) + _this.toolbarMenu[defaultMenu.remove] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.remove, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.remove, "删除选中"); + break; + case defaultMenu.searchNode: + _this.toolbarMenu[defaultMenu.searchNode] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.searchNode, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.searchNode, "查询"); + break; + } + }; + + // 获取依附在工具栏的扩展菜单栏 + DTree.prototype.getExtMenubarToolDom = function(menu){ + var _this = this; + _this.toolbarMenu[menu.menubarId] = _this.setToolbarDom().setMenuToolbarOption(menu.menubarId, menu.title, _this.usefontStyle.toolbar.menubarExt+" "+menu.icon, ""); + }; + + // menubar内置方法 + DTree.prototype.menubarMethod = function(){ + var _this = this; + return { + openAllNode: function(obj){ // 展开所有节点 + var $ulNode = obj || _this.obj.children("li").children("ul"); + // 遍历所有ul子节点 + for (var i = 0; i < $ulNode.length; i++) { + // 获取当前节点的信息 + var $ul = $($ulNode[i]), + $div = $ul.prev("div"), + $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + if (leaf == "leaf") { continue; } // 说明是叶子了,则继续循环下一个 + + if (spread == "open") { + // 说明该节点已经展开了,则进行子节点循环 + } else { + if (_this.type=="load") { //是否全量加载 + if (_this.cache) { //是否开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + } else { //加载节点 + _this.getChild($div); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + } + _this.operateIcon($i_spread, $i_node).open(); + + } + var $childUl = $ul.children("li").children("ul"); + _this.menubarMethod().openAllNode($childUl); + } + }, + closeAllNode: function(){ //收缩所有节点 + _this.obj.find("."+LI_NAV_CHILD).each(function(){ + // 获取当前节点的信息 + var $ul = $(this), + $div = $ul.prev("div"), + $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + $ul.removeClass(NAV_SHOW); + _this.operateIcon($i_spread, $i_node).close(); + }); + }, + refreshTree: function(){// 刷新树 + _this.refreshTree(); + }, + checkAll: function(){ // 全选节点 + _this.checkAllNode(); + }, + unCheckAll: function(){ // 全不选节点 + _this.cancelCheckedNode(); + }, + invertAll: function(){ // 反选节点 + _this.invertCheckedNode(); + }, + remove: function(){// 删除选中节点 + _this.removeCheckedNode(); + }, + searchNode: function(){//模糊查询该值,展开该值节点 + layer.prompt({ + formType: 0, + value: "", + title: '查询节点' + }, function(value, index1, elem){ + if (value) { + var flag = _this.searchNode(value); + if (!flag) { + layer.msg("该名称节点不存在!", {icon:5}); + } + } else { + layer.msg("未指定查询节点名称", {icon:5}); + } + layer.close(index1); + }); + }, + extMethod: function(menuId, $div, flag){ + if(_this.menubar && _this.menubarTips.group && _this.menubarTips.group.length > 0 && flag == "group"){ + for(var i=0; i<_this.menubarTips.group.length; i++){ + var ext = _this.menubarTips.group[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + if(_this.menubar && _this.menubarTips.toolbar && _this.menubarTips.toolbar.length > 0 && flag == "toolbar"){ + for(var i=0; i<_this.menubarTips.toolbar.length; i++){ + var ext = _this.menubarTips.toolbar[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + if(_this.menubar && _this.menubarTips.freedom && _this.menubarTips.freedom.length > 0 && flag == "freedom"){ + for(var i=0; i<_this.menubarTips.freedom.length; i++){ + var ext = _this.menubarTips.freedom[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + } + }; + }; + + // menubar监听方法 + DTree.prototype.menubarListener = function(menuId, flag){ + var _this = this; + var $div = _this.getNodeDom().nowDiv(); + switch (menuId) { + case defaultMenu.moveDown: // 展开全部节点 + _this.menubarMethod().openAllNode(); + break; + case defaultMenu.moveUp: // 收缩全部节点 + _this.menubarMethod().closeAllNode(); + break; + case defaultMenu.refresh: + _this.menubarMethod().refreshTree(); // 刷新树 + break; + case defaultMenu.checkAll: + _this.menubarMethod().checkAll(); + break; + case defaultMenu.unCheckAll: + _this.menubarMethod().unCheckAll(); + break; + case defaultMenu.invertAll: + _this.menubarMethod().invertAll(); + break; + case defaultMenu.remove: + _this.menubarMethod().remove(); + break; + case defaultMenu.searchNode: + _this.menubarMethod().searchNode(); + break; + default: + _this.menubarMethod().extMethod(menuId, $div, flag); + break; + } + }; + + //模糊查询该值,展开该值节点 + DTree.prototype.searchNode = function(value){ + var _this = this; + var b = false; + var $lis = []; + _this.obj.find("cite[data-leaf]").each(function(){ + var $nthis = $(this); + var html = $nthis.html(); + if(html.indexOf(value) > -1){ + if($nthis.attr("data-leaf") == "leaf") { + // 叶子节点提供包含父节点的所有信息 + var title = ""; + $nthis.parents("li").each(function(){ + title = "-" + $(this).find("cite[data-leaf]").html() + title; + }); + title = title.substring(1, title.length); + $nthis.attr("title", title); + } + // 保存当前cite所在的li及父li中包含该值,则只保留父的 + var i = 0; + $nthis.parents("li").each(function(){ + var html2 = $(this).find("cite[data-leaf]").html(); + if(html2.indexOf(value) > -1){ + i++; + } + if(i >= 2){ + return true; + } + }); + if (i < 2){ + $lis.push($nthis.closest("li").prop("outerHTML")); + } + } + }); + if($lis.length > 0) { + b = true; + // 1.将树节点清空 + _this.obj.html(""); + // 2.遍历所有cite节点,展开当前cite节点 + for(var i=0; i<$lis.length; i++){ + _this.obj.append($lis[i]); + } + } + return b; + }; + + + /******************** 工具栏区域 ********************/ + // 获取工具栏 + DTree.prototype.getToolbarDom = function(){ + var _this = this; + var toolbarShow = _this.toolbarShow, + toolbarExt = _this.toolbarExt, + toolbarWay = _this.toolbarWay; + + if(toolbarShow.length > 0){ + for(var i=0; i 0){ + for(var i=0; i "+other +title+""; + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + return ""; + } + }, + setMenuToolbarOption: function(menubarId, title, classId, other){ + var rootId = _this.obj[0].id; + if(toolbarWay == "contextmenu") { + return "
                     "+other +title+"
                    "; + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + return ""; + } + }, + setToolbarPlace: function(toolbarMenu){ + if(toolbarWay == "contextmenu") { + if(toolbarMenu){ + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).find('div.layui-nav-item>dl.layui-nav-child').html(""); + for(var key in toolbarMenu){ + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).find('div.layui-nav-item>dl.layui-nav-child').append(toolbarMenu[key]); + } + } + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + _this.obj.find("cite[data-leaf][dtree-disabled='false']").each(function(){ + var $cite = $(this); + _this.dynamicToolbarDom($cite); + }); + } + } + } + }; + + // 在节点后动态绑定fixed和follow条件的工具栏 + DTree.prototype.dynamicToolbarDom = function($cite){ + var _this = this; + var toolbarWay = _this.toolbarWay; + if($cite.next("em."+TOOLBAR_TOOL_EM).length == 0) { + var $div = $cite.parent("div"); + var param = _this.getRequestParam(_this.getTempNodeParam($div)); + var toolbarMenus = _this.toolbarFun.loadToolbarBefore(event.cloneObj(_this.toolbarMenu), param, $div); + var hideCls = (toolbarWay == "follow") ? NAV_HIDE : ""; + var em = [""]; + if(toolbarMenus){ + for(var key in toolbarMenus){ + em.push(toolbarMenus[key]); + } + } + em.push(""); + $cite.after(em.join('')); + } + } + + // 隐藏toolbar + DTree.prototype.toolbarHide = function() { + var _this = this; + if(_this.toolbar && _this.toolbarWay == "contextmenu") { + var $toolBarDiv = _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id); + $toolBarDiv.find(".layui-nav-child").removeClass('layui-anim-fadein layui-show'); + } + } + + // toolbar内置方法 + DTree.prototype.toolbarMethod = function(){ + var _this = this; + return { + pulldown: function(obj){ // 展开当前点击节点的下面全部节点 + if(!obj) return; + var $ulNode = obj; + // 遍历所有ul子节点 + for (var i = 0; i < $ulNode.length; i++) { + // 获取当前节点的信息 + var $ul = $($ulNode[i]), + $div = $ul.prev("div"), + $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + if (leaf == "leaf") { continue; } // 说明是叶子了,则继续循环下一个 + + if (spread == "open") { + // 说明该节点已经展开了,则进行子节点循环 + } else { + if (_this.type=="load") { //是否全量加载 + if (_this.cache) { //是否开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + } else { //加载节点 + _this.getChild($div); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + } + _this.operateIcon($i_spread, $i_node).open(); + + } + var $childUl = $ul.children("li").children("ul"); + _this.toolbarMethod().pulldown($childUl); + } + }, + pullup: function($li){ // 收缩当前点击节点的下面全部节点 + $li.find("."+LI_NAV_CHILD).each(function(){ + // 获取当前节点的信息 + var $ul = $(this), + $div = $ul.prev("div"), + $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + $ul.removeClass(NAV_SHOW); + _this.operateIcon($i_spread, $i_node).close(); + }); + } + } + }; + + // toolbar监听方法 + DTree.prototype.toolbarListener = function(tool, $div) { + var _this = this; + var $cite = $div.children("cite[data-leaf]"), + $ul = $div.next("ul"), + $p_li = $div.parent("li[data-index]"), //当前选中节点的顶级li节点 + $p_ul = $p_li.parent("ul"), //当前选中节点的顶级li节点的父级ul + $p_div = $p_ul.prev("div"), //当前选中节点的顶级li节点的父级ul的前一个div + title = $cite.html(); + switch (tool) { + case defaultTool.pulldown: + _this.toolbarMethod().pulldown($ul); + break; + case defaultTool.pullup: + _this.toolbarMethod().pullup($p_li); + break; + case defaultTool.addTool: + var content = _this.loadToolBar(title, defaultTool.addTool); + + layer.open({ + title: "新增"+_this.toolbarStyle.title, + type: 1, + area: _this.toolbarStyle.area, + content: content, + success: function(layero, index){ + form.render(); + form.on("submit(dtree_addNode_form)",function(data){ + var data = data.field; + var parentId = $div.attr("data-id"), + id = $div.attr("data-id")+"_node_"+$ul[0].childNodes.length, + leaf = true, + checked = "0", + level = parseInt($p_li.attr("data-index"))+1; + + // 创建子节点的DOM,添加子节点 + var checkArr = []; + if (_this.checkArrLen > 0) { + for (var i = 0; i < _this.checkArrLen; i++) { + checkArr.push({"type":i,"checked":"0"}); + } + } + + $ul.append(_this.getLiItemDom(id, parentId, data.addNodeName, data.addNodeName, true, "", "", checkArr, level, false, false, false, "", "", "item")); + // 先将li节点隐藏 + $ul.find("li[data-id='"+id+"']").hide(); + // 重新赋值 + var $addDiv = $ul.find("div[data-id='"+id+"']"); + node = _this.getNodeParam($addDiv); + + //获取组装后的requestNode,组合参数 + var requestNode = _this.getRequestParam(node); + requestNode = $.extend(requestNode, data); + + _this.temp = [id, $ul, $div, level]; + // 用户自定义想做的事情 + _this.toolbarFun.addTreeNode(requestNode, $div); + + layer.close(index); + return false; + }); + } + }); + break; + case defaultTool.editTool: + var content = _this.loadToolBar(title, defaultTool.editTool); + + layer.open({ + title: "编辑"+_this.toolbarStyle.title, + type: 1, + area: _this.toolbarStyle.area, + content: content, + success: function(layero, index){ + _this.toolbarFun.editTreeLoad(_this.getRequestParam(_this.getNodeParam($div))); + form.render(); + form.on("submit(dtree_editNode_form)",function(data){ + var data = data.field; + $cite.html(data.editNodeName); + node = _this.getNodeParam($div); + var requestNode = _this.getRequestParam(node); + requestNode = $.extend(requestNode, data); + _this.temp = [$cite, $div, title, $p_div]; + _this.toolbarFun.editTreeNode(requestNode, $div); + + layer.close(index); + }); + } + }); + break; + case defaultTool.delTool: + layer.confirm('确定要删除该'+_this.toolbarStyle.title+'?', {icon: 3, title:'删除'+_this.toolbarStyle.title}, function(index){ + var node = _this.getNodeParam($div); + _this.temp = [$p_li, $p_div]; + _this.toolbarFun.delTreeNode(_this.getRequestParam(_this.getNodeParam($div)), $div); + + layer.close(index); + }); + break; + default: + if(_this.toolbarExt.length > 0){ + for(var i=0; i<_this.toolbarExt.length; i++){ + var ext = _this.toolbarExt[i]; + if (tool == ext.toolbarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div)), $div); + break; + } + } + } + break; + } + } + + + // 加载toolBar中的内容 + DTree.prototype.loadToolBar = function(title, name){ + var _this = this; + var toolbarShow = _this.toolbarShow; + var nodeBarContents = _this.toolbarBtn; + + var html = ""; + switch (name) { + case defaultTool.addTool: + var addNodeBarDef = [{"label": "当前选中", "name": "nodeTitle", "type": "text", "value": title, "defElem": "nowChoose", "readonly": true}, + {"label": "新增"+_this.toolbarStyle.title, "name": "addNodeName", "type": "text", "value": "", "defElem": "nowChange", "verify": "required"}, + {"type": "submit", "value": "确认添加", "defElem": "btn", "filter": "dtree_addNode_form"}]; + + //2. 用户自定义的节点内容 + var addNodeBar = ['
                    ']; + + if(nodeBarContents != null && nodeBarContents.length > 0){ + if(nodeBarContents[0] != null && nodeBarContents[0] != undefined && nodeBarContents[0].length > 0){ + var addNodeBarContents = nodeBarContents[0]; + // 1. 检查是否包含了now、newly、btn这三个默认项,将其他元素依次排列,将特殊元素至于栈顶 + for(var i=0; i', '
                    ']; + // 3.遍历生成按钮 + for(var j=0; j
                    '); + addNodeBar.push(addBtn.join('')); + addNodeBar.push('
                    '); + html = addNodeBar.join(''); + break; + + case defaultTool.editTool: + var editNodeBarDef = [{"label": "当前选中", "name": "nodeTitle", "type": "text", "value": title, "defElem": "nowChoose", "readonly": true}, + {"label": "编辑"+_this.toolbarStyle.title, "name": "editNodeName", "type": "text", "value": "", "defElem": "nowChange", "verify": "required"}, + {"type": "submit", "value": "确认编辑", "defElem": "btn", "filter": "dtree_editNode_form"}]; + + var editNodeBar = ['
                    ']; + //2. 用户自定义的节点内容 + if(nodeBarContents != null && nodeBarContents.length > 0){ + + if(nodeBarContents[1] != null && nodeBarContents[1] != undefined && nodeBarContents[1].length > 0){ + var editNodeBarContents = nodeBarContents[1]; + // 1. 检查是否包含了now、newly、btn这三个默认项,将其他元素依次排列,将特殊元素至于栈顶 + for(var i=0; i', '
                    ']; + // 3.遍历生成按钮 + for(var j=0; j
                    '); + editNodeBar.push(editBtn.join('')); + editNodeBar.push('
                    '); + html = editNodeBar.join(''); + break; + } + return html; + }; + + // 获取toolbar详细的标签信息 + DTree.prototype.loadToolBarDetail = function(nodeBarContents){ + var _this = this; + var readonly = (typeof (nodeBarContents.readonly) === "boolean") ? nodeBarContents.readonly : false; + var disabled = (typeof (nodeBarContents.disabled) === "boolean") ? nodeBarContents.disabled : false; + var id = nodeBarContents.id ? nodeBarContents.id : ""; + var name = nodeBarContents.name ? nodeBarContents.name : ""; + var val = nodeBarContents.value ? nodeBarContents.value : ""; + var verify = nodeBarContents.verify ? nodeBarContents.verify : ""; + var placeholder = nodeBarContents.placeholder ? nodeBarContents.placeholder : val; + return{ + text: function(){ + return ['
                    ', + '', + '
                    ', + '', + '
                    ', + '
                    '].join(''); + }, + textarea: function(){ + return ['
                    ', + '', + '
                    ', + '', + '
                    ', + '
                    '].join(''); + }, + hidden: function(){ + return [''].join(''); + }, + select: function(){ + var optionsData = (typeof nodeBarContents.optionsData === 'object') ? nodeBarContents.optionsData : nodeBarContents.optionsData(); + var options = ""; + for(var key in optionsData){ + if(val == optionsData[key]){ + options += ""; + } else { + options += ""; + } + } + return ['
                    ', + '', + '
                    ', + '', '
                    ', '
                    '].join(''); + }, + submit: function(){ + var filter = nodeBarContents.filter; + return [''].join(''); + }, + button: function(){ + return [''].join(''); + }, + reset: function(){ + return [''].join(''); + } + } + }; + + // 新增节点后改变节点内容 + DTree.prototype.changeTreeNodeAdd = function(returnID){ + var _this = this; + var temp = _this.temp; + var id = temp[0], $ul = temp[1], $div = temp[2], level = temp[3]; + var flag = false; + if(returnID){ + var $thisDiv = _this.obj.find("[data-id='"+id+"']"); + if(typeof returnID === "object"){ + // 如果是JSON格式数据,则将当前DIV删除,重新建造DIV + $thisDiv.remove(); + var parseData = _this.parseData(returnID); + + if(parseData.treeId()){ + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(0), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), "item")); + + // 建造完毕后,选中该DIV + $thisDiv = $ul.find("div[data-id='"+parseData.treeId()+"']"); + _this.setNodeParam($thisDiv) + } else { + layer.msg("添加失败,节点ID为undefined!",{icon:5}); + // 将li节点删除 + $ul.find("li[data-id='"+id+"']").remove(); + // 重新赋值 + _this.setNodeParam($div); + // 临时变量制空 + _this.temp = []; + return ; + } + }else if(returnID == 'refresh'){ + // 如果是设置为refresh参数,则向后台发送请求,获取新增节点下的真实参数,局部刷新树。 + flag = true; + } else if(typeof returnID === "string" || typeof returnID === 'number' || returnID == true){ + $thisDiv.attr("data-id", returnID); + // 将li节点展示 + $ul.find("li[data-id='"+returnID+"']").show(); + _this.setNodeParam($thisDiv) + } + + // 判断当前点击的节点是否是最后一级节点,如果是,则需要修改节点的样式 + var $icon_i = $div.find("i[data-spread]"); + if ($icon_i.eq(0).attr("data-spread") == "last") { + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).openWithLeaf(); + } else { //如果不是,也要修改节点样式 + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).open(); + } + $ul.addClass(NAV_SHOW); //展开UL + _this.accordionUL($ul); + if(flag) { + _this.getChild($div); + } else { + // _this.showLine(); + _this.showLine($ul.find("li")); + // 这种情况下需要在新增节点后对节点新增工具栏 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.dynamicToolbarDom($thisDiv.find("cite[data-leaf]")); + } + } + + } else { + // 将li节点删除 + $ul.find("li[data-id='"+id+"']").remove(); + // 重新赋值 + _this.setNodeParam($div); + } + + _this.temp = []; // 临时变量制空 + + }; + + // 编辑页打开后显示编辑页内容 + DTree.prototype.changeTreeNodeDone = function(param){ + var _this = this; + form.val('dtree_editNode_form', param); + form.render(); + }; + + // 修改节点后改变节点内容 + DTree.prototype.changeTreeNodeEdit = function(returnID){ + var _this = this; + var temp = _this.temp; + var $cite = temp[0], $div = temp[1], title = temp[2], $p_div = temp[3]; + var flag = false; + if(returnID){ + if(typeof returnID === "object"){ + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var replaceDom = _this.replaceDom($div, parseData.treeId(), parseData.last(0), parseData.spread(), parseData.disabled(), parseData.hide()); + replaceDom.node(parseData.iconClass()); + replaceDom.checkbox(parseData.checkArr()); + replaceDom.text(parseData.title()); + replaceDom.ul(); + replaceDom.basicData(parseData.basicData()); + replaceDom.recordData(parseData.recordData()); + _this.setNodeParam($div); + } else { + layer.msg("编辑失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } + } else { + $cite.html(title); + _this.getNodeParam($div); + } + + _this.temp = []; // 临时变量制空 + }; + + // 删除节点后改变节点内容 + DTree.prototype.changeTreeNodeDel = function(flag){ + var _this = this; + var temp = _this.temp; + var $p_li = temp[0], + $p_ul = $p_li.parent("ul"), + $p_div = temp[1]; + + if(flag){ + $p_li.remove(); + _this.showLine($p_ul.find("li")); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($p_ul.children("li").length == 0){ + var $icon_i = $p_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).closeWithLeaf(); + } + _this.initNodeParam(); + } + + _this.temp = []; // 临时变量制空 + }; + + /******************** iframe区域 ********************/ + // 加载iframe + DTree.prototype.loadIframe = function($div, iframeParam) { + var _this = this; + var $cite = _this.getNodeDom($div).cite(); + if (!_this.useIframe) { // 启用iframe + return false; + } + var iframeElem = _this.iframeElem, + iframeUrl = _this.iframeUrl, + iframeLoad = _this.iframeLoad; + + var flag = iframeLoad == "leaf" ? (($cite.attr("data-leaf") == "leaf") ? true : false) : true; + + if (flag) { + if ($(iframeElem).length > 0) { //iframe存在 + if (!iframeUrl) { + layer.msg("数据请求异常,iframeUrl参数未指定", {icon:5}); + return false; + } + var param = AjaxHelper.serialize(iframeParam); + if(iframeUrl.indexOf("?")> -1){ + param = "&"+param.substring(1, param.length); + } + var url = iframeUrl + param; + $(iframeElem).attr("src", url); + } else { + layer.msg("iframe绑定异常,请确认页面中是否有iframe页对应的容器", {icon:5}); + return false; + } + } + return flag; + }; + + // 获取传递出去的参数,根据iframe.iframeDefaultRequest、iframe.iframeRequest和node拼出发出请求的参数 + DTree.prototype.getIframeRequestParam = function(nodes){ + var _this = this; + var request = _this.iframeRequest, + defaultRequestNames = _this.iframeDefaultRequest, + node = nodes || _this.node, + requestParam = {}; + + // 先拼用户自定义的,在拼树生成的,这样的话用户可以自定义当树未生成时的节点的初始值 + for ( var key in request) { + requestParam[key] = request[key]; + } + for ( var key in defaultRequestNames) { + var paramName = defaultRequestNames[key]; + var paramValue = node[key]; + if(typeof paramValue === "boolean"){ + requestParam[paramName] = paramValue; + }else { + if(paramValue){ + requestParam[paramName] = paramValue; + } + } + } + + // 解决传递中文的乱码问题 + var reg = /[\u4E00-\u9FA5\uF900-\uFA2D]/; //正则匹配中文 + for(var key in requestParam){ + if(reg.test(requestParam[key])) { + var str = requestParam[key]; + requestParam[key] = encodeURI(encodeURI(str)); + } + } + + return requestParam; + }; + + /******************** 数据回调区域 ********************/ + // 根据具体的id获取基于当前id的div以及对应的其他dom元素 + DTree.prototype.getNodeDom = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + return { + div: function(){ // 获取当前div + return $div; + }, + fnode: function(){ // 获取一级图标元素 + return ($div == null) ? null : $div.find("i[data-spread]").eq(0); + }, + snode: function(){ // 获取二级图标元素 + return ($div == null) ? null : $div.find("i[data-spread]").eq(1); + }, + checkbox: function(){ // 获取复选框元素 + return ($div == null) ? null : $div.find("i[data-par]"); + }, + cite: function(){ // 获取cite元素 + return ($div == null) ? null : $div.find("cite[data-leaf]"); + }, + nextUl: function(){ // 获取相邻的ul元素 + return ($div == null) ? null : $div.next("ul"); + }, + parentLi: function(){ // 获取父级li元素 + return ($div == null) ? null : $div.parent("li"); + }, + parentUl: function(){ // 获取基于当前$div的上级$ul + return ($div == null) ? null : $div.parent("li").parent("ul"); + }, + parentDiv: function(){ // 获取基于当前$div的上级$div + return ($div == null) ? null : $div.parent("li").parent("ul").prev("div"); + }, + nowDiv: function(){ // 获取当前选中节点,没有则返回null + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS); + }, + nowOrRootDiv: function(){ // 获取当前选中节点,没有则返回根节点下的第一个div + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? _this.obj.children("li").eq(0).children("div").eq(0) : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS); + }, + nowOrRootUl: function(){ // 获取当前选中节点下一个UL 或根节点。为了将新节点放入ul下 + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? _this.obj : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).next("ul"); + } + } + }; + + // 获取当前选中节点下一个UL 或根节点。为了将新节点放入ul下 + DTree.prototype.getNowNodeUl = function() { + var _this = this; + return _this.getNodeDom().nowOrRootUl(); + }; + + // 获取当前选中节点 或第一个根节点。 + DTree.prototype.getNowNode = function() { + var _this = this; + return _this.getNodeDom().nowOrRootDiv(); + }; + + // 获取当前选中节点 无则返回null。 + DTree.prototype.getNowNodeOrNull = function() { + var _this = this; + return _this.getNodeDom().nowDiv(); + }; + + // 获取指定节点。 + DTree.prototype.getNode = function(id) { + var _this = this; + return _this.getNodeDom(id).div(); + }; + + // 设置当前选中节点的全部参数 + DTree.prototype.setNodeParam = function($div) { + var _this = this; + _this.node.nodeId = $div.attr("data-id"); + _this.node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + _this.node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + _this.node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + _this.node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + _this.node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + _this.node.basicData = basicData; + + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + _this.node.recordData = recordData; + + if (_this.getNodeDom($div).checkbox()) { + var dataTypes = "", checkeds = "", initcheckeds = ""; + _this.getNodeDom($div).checkbox().each(function(){ + dataTypes += $(this).attr("data-type") + ","; + checkeds += $(this).attr("data-checked") + ","; + initcheckeds += $(this).attr("data-initchecked") + ","; + }); + dataTypes = dataTypes.substring(0, dataTypes.length-1); + checkeds = checkeds.substring(0, checkeds.length-1); + initcheckeds = initcheckeds.substring(0, initcheckeds.length-1); + + _this.node.dataType = dataTypes; + _this.node.checked = checkeds; + _this.node.initchecked = initcheckeds; + } + }; + + // 获取当前选中节点的全部参数 + DTree.prototype.getNodeParam = function($div) { + var _this = this; + if ($div) { + _this.setNodeParam($div); + } else { + if(_this.obj.find("div[data-id]").parent().find("."+NAV_THIS).length == 0){ + _this.initNodeParam(); + } + } + return this.node; + }; + + // 获取一个临时的node参数 + DTree.prototype.getTempNodeParam = function($div) { + var _this = this; + var temp_node = {}; + temp_node.nodeId = $div.attr("data-id"); + temp_node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + temp_node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + temp_node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + temp_node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + temp_node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + temp_node.basicData = basicData; + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + temp_node.recordData = recordData; + + if (_this.getNodeDom($div).checkbox()) { + var dataTypes = "", checkeds = "", initcheckeds = ""; + _this.getNodeDom($div).checkbox().each(function(){ + dataTypes += $(this).attr("data-type") + ","; + checkeds += $(this).attr("data-checked") + ","; + initcheckeds += $(this).attr("data-initchecked") + ","; + }); + dataTypes = dataTypes.substring(0, dataTypes.length-1); + checkeds = checkeds.substring(0, checkeds.length-1); + initcheckeds = initcheckeds.substring(0, initcheckeds.length-1); + + temp_node.dataType = dataTypes; + temp_node.checked = checkeds; + temp_node.initchecked = initcheckeds; + } + return temp_node; + }; + + // 重置参数 + DTree.prototype.initNodeParam = function(){ + var _this = this; + _this.node.nodeId = ""; + _this.node.parentId = ""; + _this.node.context = ""; + _this.node.leaf = ""; + _this.node.level = ""; + _this.node.spread = ""; + _this.node.dataType = ""; + _this.node.checked = ""; + _this.node.initchecked = ""; + _this.node.basicData = ""; + _this.node.recordData = ""; + + if(_this.select) { + _this.selectResetVal(); + } + }; + + // 获取传递出去的参数,根据defaultRequest、request和node拼出发出请求的参数 + DTree.prototype.getRequestParam = function(nodes){ + var _this = this; + var request = _this.request, + defaultRequestNames = _this.defaultRequest, + node = nodes || _this.node, + requestParam = {}; + + // 先拼用户自定义的,在拼树生成的,这样的话用户可以自定义当树未生成时的节点的初始值 + for ( var key in request) { + requestParam[key] = request[key]; + } + for ( var key in defaultRequestNames) { + var paramName = defaultRequestNames[key]; + var paramValue = node[key]; + if(typeof paramValue === "boolean"){ + requestParam[paramName] = paramValue; + }else { + if(paramValue){ + requestParam[paramName] = paramValue; + } + } + + } + return requestParam; + }; + + // 获取filterParam过滤后的requestParam + DTree.prototype.getFilterRequestParam = function(requestParam){ + var _this = this; + var filterRequest = _this.filterRequest; + return event.cloneObj(requestParam, filterRequest); + }; + + // 获取当前选中值 + DTree.prototype.getNowParam = function(){ + var _this = this; + + return _this.getRequestParam(_this.getNodeParam()); + }; + + // 获取指定节点选中值 + DTree.prototype.getParam = function(id){ + var _this = this; + + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null){ return _this.callbackData().node(_this.getTempNodeParam($div)); } else { return {}; } + }; + + // 获取参数的上级节点 + DTree.prototype.getParentParam = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null){ return _this.callbackData().parentNode($div); } else { return {}; } + }; + + // 获取参数的全部上级节点 + DTree.prototype.getAllParentParam = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + var arr = []; + if($div != null){ + var level = _this.getTempNodeParam($div).level; + for(var i=1; i 0){ + $childDivs.each(function(){ + var $cDiv = $(this); + childNode.push(_this.getRequestParam(_this.getTempNodeParam($cDiv))); + }); + } + return childNode; + }, + parentNode: function($div){ // 获取上级节点值 + var pId = _this.getNodeDom($div).parentLi().attr("data-pid"); + var $pdiv = _this.obj.find("div[data-id='"+pId+"']"); + if($pdiv.length > 0) {return _this.getRequestParam(_this.getTempNodeParam($pdiv));} else {return {};} + + } + } + }; + + /******************** 事件回调区域 ********************/ + // 绑定浏览器事件 + DTree.prototype.bindBrowserEvent = function(){ + var _this = this; + var rootId = _this.obj[0].id; + + // 绑定文件夹展开/收缩的图标的点击事件,点击时给当前节点的div添加选中class + _this.obj.on("click", "i[data-spread]", function(event) { + event.stopPropagation(); + var $i = $(this), + $div = $i.parent("div"), + node = _this.getNodeParam($div); + + _this.toolbarHide(); + _this.navThis($div); + _this.clickSpread($div); // 展开或隐藏节点 + + // 树状态改变后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "changeTree("+$(_this.obj)[0].id+")", { + dom: _this.callbackData().dom($i), + param: _this.callbackData().node(node), + show: _this.callbackData().dom($i).attr("data-spread") == "open" ? true : false + }); + }); + + // 绑定所有子节点div的单击事件,点击时触发加载iframe或用户自定义想做的事情 + _this.obj.on("click", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event) { + event.stopPropagation(); + var $div = $(this), + $cite = $div.find("cite"), + node = _this.getNodeParam($div); + _this.toolbarHide(); + _this.navThis($div); + + if(_this.select) { + _this.selectVal(node.nodeId); + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").click(); + } + + if (_this.useIframe) { + var iframeParam = _this.getFilterRequestParam(_this.getIframeRequestParam(node)); + var flag = _this.loadIframe($div, iframeParam); // 加载iframe + if (flag) { + // iframe加载完毕后,用户自定义想做的事情 + _this.iframeFun.iframeDone(iframeParam); + + layui.event.call(this, MOD_NAME, "iframeDone("+$(_this.obj)[0].id+")", { + "iframeParam": iframeParam, + dom: _this.callbackData().dom($div) + }); + } + } else { + // 单击事件执行完毕后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "node("+$(_this.obj)[0].id+")", { + param: _this.callbackData().node(node), + childParams: _this.callbackData().childNode($div), + parentParam: _this.callbackData().parentNode($div), + dom: _this.callbackData().dom($div) + }); + } + }); + + // 绑定所有子节点div的双击事件,暴露on给用户自定义 + _this.obj.on("dblclick", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event) { + event.stopPropagation(); + var $div = $(this), + $cite = $div.find("cite"), + node = _this.getNodeParam($div); + _this.toolbarHide(); + _this.navThis($div); + + if(_this.select) { + _this.selectVal(node.nodeId); + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").click(); + } + + // 双击事件执行完毕后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "nodedblclick("+$(_this.obj)[0].id+")", { + param: _this.callbackData().node(node), + childParams: _this.callbackData().childNode($div), + parentParam: _this.callbackData().parentNode($div), + dom: _this.callbackData().dom($div) + }); + }); + + if(_this.checkbar) { + // 绑定cheboxbar的节点复选框 + _this.obj.on("click", "i[dtree-click='"+eventName.checkNodeClick+"'][dtree-disabled='false']", function(event) { + _this.toolbarHide(); + var $i = $(this), + $div = $i.closest("div[dtree-click='"+eventName.itemNodeClick+"']"), + node = _this.getNodeParam($div); + // 复选框选中前的回调 + var flag = _this.checkbarFun.chooseBefore($i, _this.getRequestParam(node)); + _this.temp = [$i]; + if(flag){_this.changeCheck();} + + event.stopPropagation(); + }); + } + + if(_this.menubar) { + // 绑定menubar的点击事件 + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).on("click", "button[d-menu]", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("d-menu"), "group"); + }); + + // 绑定menubar的点击事件 + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).on("click", "a[d-menu]", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("d-menu"), "toolbar"); + }); + + // 绑定menubar的点击按钮事件 + _this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").on("click", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("dtree-menu"), "freedom"); + }); + } + + if(_this.toolbar) { + if(_this.toolbarWay == "contextmenu") { + //绑定所有子节点div的右键点击事件,用于显示toolbar + _this.obj.on("contextmenu", "div[dtree-click='"+eventName.itemNodeClick+"'][d-contextmenu='true'][dtree-disabled='false']", function(e){ + var $div = $(this), + node = _this.getNodeParam($div); + + _this.toolbarHide(); + // toolbar加载前执行的方法,执行完毕之后创建按钮 + _this.setToolbarDom().setToolbarPlace(_this.toolbarFun.loadToolbarBefore(event.cloneObj(_this.toolbarMenu), _this.getRequestParam(node), $div)); + + var e = e || window.event, + mx = e.pageX - $div.offset().left +45 , + my = $div.offset().top - _this.obj.closest(_this.scroll).offset().top +15; + + _this.navThis($div); + var $toolBarDiv = _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id); + $toolBarDiv.find(".layui-nav-child").addClass('layui-anim-fadein layui-show'); + $toolBarDiv.css({'left':mx+'px','top':my+'px'}); + + e.stopPropagation(); + return false; + }); + + // 绑定装载树的上层出现滚动条的容器,让toolbar隐藏 + _this.obj.closest(_this.scroll).scroll(function() { + _this.toolbarHide(); + }); + + // 绑定toolbar的点击事件 + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $div = _this.getNodeDom().nowOrRootDiv(), + node = _this.getNodeParam($div); + _this.toolbarHide(); + var tool = $(this).attr("dtree-tool"); + _this.toolbarListener(tool, $div); + }); + } else if(_this.toolbarWay == "fixed") { + // 绑定toolbar的点击事件 + _this.obj.on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $a = $(this), + $cite = $a.parent("em."+TOOLBAR_TOOL_EM).prev("cite"), //当前选中节点的text + $div = $cite.parent("div"), + node = _this.getNodeParam($div); + var tool = $a.attr("dtree-tool"); + + _this.toolbarHide(); + _this.navThis($div); + _this.toolbarListener(tool, $div); + }); + } else if(_this.toolbarWay == "follow") { + //绑定所有子节点div的mouseover mouseout事件,用于显示或隐藏toolbar + _this.obj.on("mouseover mouseout", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event){ + var $div = $(this), + $toolBarEm = $div.children("em."+TOOLBAR_TOOL_EM); + if(event.type == "mouseover"){ + $toolBarEm.removeClass(NAV_HIDE); + event.stopPropagation(); + } else if(event.type == "mouseout"){ + $toolBarEm.addClass(NAV_HIDE); + event.stopPropagation(); + } + }); + + // 绑定toolbar的点击事件 + _this.obj.on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $a = $(this), + $cite = $a.parent("em."+TOOLBAR_TOOL_EM).prev("cite"), //当前选中节点的text + $div = $cite.parent("div"), + node = _this.getNodeParam($div); + var tool = $a.attr("dtree-tool"); + + _this.toolbarHide(); + _this.navThis($div); + _this.toolbarListener(tool, $div); + }); + } + } + + if(_this.select) { + // 绑定select的点击事件 + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").on("click", function(event){ + event.stopPropagation(); + $(this).toggleClass("layui-form-selected"); + $("div[dtree-id='" + rootId + "'][dtree-card='"+_this.selectCardDiv+"']").toggleClass("dtree-select-show layui-anim layui-anim-upbit"); + + // 下拉树面板开闭状态改变后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "changeSelect("+$(_this.obj)[0].id+")", { + show: $(this).hasClass("layui-form-selected"), + param: _this.selectVal() + }); + }); + + } + }; + + // 绑定body的单击,让本页面所有的toolbar隐藏 + $BODY.on("click", function(event){ + $("div."+LI_DIV_TOOLBAR).find(".layui-show").removeClass('layui-anim-fadein layui-show'); + // $("div[dtree-id][dtree-select]").removeClass("layui-form-selected"); + // $("div[dtree-id][dtree-card]").removeClass("dtree-select-show layui-anim layui-anim-upbit"); + + }); + + // 解绑浏览器事件 + DTree.prototype.unbindBrowserEvent = function(){ + var _this = this; + + // 本身事件解绑 + _this.obj.unbind(); + // 菜单栏解绑 + if(_this.menubar){ + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).unbind(); + if(_this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").length > 0){ + _this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").unbind(); + } + } + + // 工具栏解绑 + if(_this.toolbar){ + if(_this.toolbarWay == "contextmenu") { + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).unbind(); + if(_this.obj.closest(_this.scroll).length > 0){ + _this.obj.closest(_this.scroll).unbind(); + } + } + } + + // 下拉树解绑 + if(_this.select) { + // 解绑select的点击事件 + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-select='"+_this.selectDiv+"']").removeClass("layui-form-selected"); + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-card='"+_this.selectCardDiv+"']").removeClass("dtree-select-show layui-anim layui-anim-upbit"); + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-select='"+_this.selectDiv+"']").unbind(); + } + }; + + + /** 外部访问 **/ + var dtree = { + set: function(options){ //设置全局属性 + if(typeof options !== 'undefined') { + $.extend(OPTIONS, options); + } + }, + render: function(options){ // 初始化树 + var dTree = null; + var id = event.getElemId(options); + if(id == "") { + layer.msg("页面中未找到绑定id", {icon:5}); + } else { + dTree = DTrees[id]; + if(typeof dTree === 'object'){ + dTree.unbindBrowserEvent(); + } + // 创建树 + dTree = new DTree(options); + // 添加到树数组中去 + DTrees[id] = dTree; + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.init(); + dTree.bindBrowserEvent(); + } + + return dTree; + }, + renderSelect: function(options){ // 初始化下拉树 + var dTree = null; + var id = event.getElemId(options); + if(id == "") { + layer.msg("页面中未找到绑定id", {icon:5}); + } else { + dTree = DTrees[id]; + if(typeof dTree === 'object'){ + dTree.unbindBrowserEvent(); + } + // 创建下拉树 + dTree = new DTree(options); + dTree.selectSetting(); + // 添加到树数组中去 + DTrees[id] = dTree; + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.init(); + dTree.bindBrowserEvent(); + } + + return dTree; + }, + reload: function(dTree, options){ // 重新加载树 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + dTree.reloadSetting(options); + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.initNodeParam(); + dTree.init(); + dTree.unbindBrowserEvent(); + dTree.bindBrowserEvent(); + }, + on: function(events, callback) { // 绑定事件 + if(events.indexOf("'") > 0){ + events = events.replace(/'/g,""); + } + if(events.indexOf('"') > 0) { + events = events.replace(/"/g,""); + } + return layui.onevent.call(this, MOD_NAME, events, callback); + }, + click: function(dTree, id) { // 模拟单击事件 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + $("div[dtree-click='"+eventName.itemNodeClick+"'][dtree-id='"+dTree.obj[0].id+"'][data-id='"+id+"']").click(); + }, + getNowParam: function(dTree){ // 获取当前选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getNowParam(); // 获取当前选中值 + }, + getParam: function(dTree, id){ // 获取指定节点值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getParam(id); // 获取指定节点值 + }, + getParentParam: function(dTree, id){ // 获取参数的上级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getParentParam(id); + }, + getAllParentParam: function(dTree, id){ // 获取参数的全部上级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getAllParentParam(id); + }, + getChildParam: function(dTree, id){ // 获取参数的全部下级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getChildParam(id); + }, + getCheckbarNodesParam: function(dTree){ // 获取复选框选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return {}; + } + return dTree.getCheckbarNodesParam(); // 获取复选框选中值 + }, + dataInit: function(dTree, chooseId){ // 初始化选中树,针对数据反选 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + if(chooseId){ + return dTree.dataInit(chooseId); + } + }, + chooseDataInit: function(dTree, chooseIds){ // 初始化复选框选中,针对数据反选 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + if(chooseIds){ + return dTree.chooseDataInit(chooseIds); + } + }, + changeCheckbarNodes: function(dTree){ //判断复选框是否发生变更 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.changeCheckbarNodes(); + }, + initNoAllCheck: function(dTree) { //复选框半选状态初始化设置 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.initNoAllCheck(); + }, + initAllCheck: function(dTree){ // 复选框选中状态初始化设置 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.initAllCheck(); + }, + selectVal: function(dTree, param){ // select模式设置输入框选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.selectVal(param); // select模式设置输入框选中值 + }, + escape: function(html){ // 字符串格式化 + return event.escape(html); + }, + unescape: function(str){ // 字符串反格式化 + return event.unescape(str); + }, + version: function(){ //获取版本号 + return VERSION; + } + }; + + exports('dtree', dtree); +}); \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.css b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.css new file mode 100644 index 0000000000000000000000000000000000000000..df7af65397abb2d2094f986fb08484d58186d2c2 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.css @@ -0,0 +1,229 @@ +@font-face { + font-family: 'dtreefont'; + src: url('dtreefont.eot?x3m8fp'); + src: url('dtreefont.eot?x3m8fp#iefix') format('embedded-opentype'), + url('dtreefont.ttf?x3m8fp') format('truetype'), + url('dtreefont.woff?x3m8fp') format('woff'), + url('dtreefont.svg?x3m8fp#dtreefont') format('svg'); + font-weight: normal; + font-style: normal; +} + +[class^="dtree-icon-"], [class*=" dtree-icon-"] { + /* use !important to prevent issues with browser extensions that change font */ + font-family: 'dtreefont' !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; +} + +.dtree-icon-xiangxia1:before { + content: "\e771"; +} +.dtree-icon-normal-file:before { + content: "\e60c"; +} +.dtree-icon-xiangyou:before { + content: "\e78f"; +} +.dtree-icon-ok-circle:before { + content: "\1005"; +} +.dtree-icon-close1:before { + content: "\1006"; +} +.dtree-icon-close-fill:before { + content: "\1007"; +} +.dtree-icon-jian1:before { + content: "\e600"; +} +.dtree-icon-jia1:before { + content: "\e601"; +} +.dtree-icon-bianji:before { + content: "\e602"; +} +.dtree-icon-yonghu:before { + content: "\e603"; +} +.dtree-icon-shijian:before { + content: "\e606"; +} +.dtree-icon-fuxuankuang-banxuan:before { + content: "\e607"; +} +.dtree-icon-star:before { + content: "\e608"; +} +.dtree-icon-wenjianjiazhankai:before { + content: "\e60e"; +} +.dtree-icon-xiangmuxiaoxi:before { + content: "\e60f"; +} +.dtree-icon-search2:before { + content: "\e615"; +} +.dtree-icon-weibiaoti5:before { + content: "\e618"; +} +.dtree-icon-layim-theme:before { + content: "\e61b"; +} +.dtree-icon-shuye1:before { + content: "\e61e"; +} +.dtree-icon-add-circle:before { + content: "\e61f"; +} +.dtree-icon-xinxipilu:before { + content: "\e620"; +} +.dtree-icon-set-sm:before { + content: "\e621"; +} +.dtree-icon-about:before { + content: "\e623"; +} +.dtree-icon-chart-screen:before { + content: "\e62a"; +} +.dtree-icon-delete1:before { + content: "\e640"; +} +.dtree-icon-share3:before { + content: "\e641"; +} +.dtree-icon-youjian:before { + content: "\e642"; +} +.dtree-icon-check:before { + content: "\e645"; +} +.dtree-icon-close:before { + content: "\e646"; +} +.dtree-icon-favorfill:before { + content: "\e64b"; +} +.dtree-icon-favor:before { + content: "\e64c"; +} +.dtree-icon-fuxuankuangxuanzhong:before { + content: "\e652"; +} +.dtree-icon-fenguangbaobiao:before { + content: "\e655"; +} +.dtree-icon-jian:before { + content: "\e656"; +} +.dtree-icon-jia:before { + content: "\e657"; +} +.dtree-icon-fenzhijigou:before { + content: "\e658"; +} +.dtree-icon-roundcheckfill:before { + content: "\e659"; +} +.dtree-icon-roundcheck:before { + content: "\e65a"; +} +.dtree-icon-roundclosefill:before { + content: "\e65b"; +} +.dtree-icon-roundclose:before { + content: "\e65c"; +} +.dtree-icon-roundrightfill:before { + content: "\e65d"; +} +.dtree-icon-roundright:before { + content: "\e65e"; +} +.dtree-icon-like:before { + content: "\e66c"; +} +.dtree-icon-samefill:before { + content: "\e671"; +} +.dtree-icon-same:before { + content: "\e672"; +} +.dtree-icon-evaluate:before { + content: "\e674"; +} +.dtree-icon-circle1:before { + content: "\e687"; +} +.dtree-icon-radio:before { + content: "\e688"; +} +.dtree-icon-caidan_xunzhang:before { + content: "\e68e"; +} +.dtree-icon-pulldown:before { + content: "\e6a0"; +} +.dtree-icon-pullup:before { + content: "\e6a1"; +} +.dtree-icon-refresh:before { + content: "\e6a4"; +} +.dtree-icon-qrcode1:before { + content: "\e6b0"; +} +.dtree-icon-profile1:before { + content: "\e6b7"; +} +.dtree-icon-home1:before { + content: "\e6b8"; +} +.dtree-icon-homefill:before { + content: "\e6bb"; +} +.dtree-icon-roundaddfill:before { + content: "\e6d8"; +} +.dtree-icon-roundadd:before { + content: "\e6d9"; +} +.dtree-icon-fuxuankuang:before { + content: "\e6f2"; +} +.dtree-icon-wefill:before { + content: "\e6f5"; +} +.dtree-icon-sort:before { + content: "\e701"; +} +.dtree-icon-repair:before { + content: "\e738"; +} +.dtree-icon-shujudaping:before { + content: "\e742"; +} +.dtree-icon-dian:before { + content: "\e7a5"; +} +.dtree-icon-search_list_light:before { + content: "\e807"; +} +.dtree-icon-round_list_light:before { + content: "\e82b"; +} +.dtree-icon-star-fill:before { + content: "\e832"; +} +.dtree-icon-rate:before { + content: "\e833"; +} +.dtree-icon-move-up:before { + content: "\ea47"; +} +.dtree-icon-move-down:before { + content: "\ea48"; +} diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.eot b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.eot new file mode 100644 index 0000000000000000000000000000000000000000..68bf5f2f2dd33daa67373cca102f8ad764d84c22 Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.eot differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.svg b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.svg new file mode 100644 index 0000000000000000000000000000000000000000..90fe50f041be2e0433b009a20993ec78c8e4e67f --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.svg @@ -0,0 +1,80 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.ttf b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..78bacd13a0a16b55e6b3be536b35e34e147a396a Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.ttf differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.woff b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.woff new file mode 100644 index 0000000000000000000000000000000000000000..2b546450765b8d1368d1858ecc2c353d5529bfa5 Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.woff differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/icons.json b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/icons.json new file mode 100644 index 0000000000000000000000000000000000000000..fca4788566c21d9bcfc9e3bf0c4406d17651a211 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/dtree/font/icons.json @@ -0,0 +1,283 @@ +{ + "data": [{ + "cls": "dtree-icon-xiangxia1", + "uncode": "e771" + }, + { + "cls": "dtree-icon-xiangyou", + "uncode": "e78f" + }, + { + "cls": "dtree-icon-jian", + "uncode": "e656" + }, + { + "cls": "dtree-icon-jia", + "uncode": "e657" + }, + { + "cls": "dtree-icon-weibiaoti5", + "uncode": "e618" + }, + { + "cls": "dtree-icon-wenjianjiazhankai", + "uncode": "e60e" + }, + { + "cls": "dtree-icon-dian", + "uncode": "e7a5" + }, + { + "cls": "dtree-icon-yonghu", + "uncode": "e603" + }, + { + "cls": "dtree-icon-fenzhijigou", + "uncode": "e658" + }, + { + "cls": "dtree-icon-fenguangbaobiao", + "uncode": "e655" + }, + { + "cls": "dtree-icon-xinxipilu", + "uncode": "e620" + }, + { + "cls": "dtree-icon-shuye1", + "uncode": "e61e" + }, + { + "cls": "dtree-icon-caidan_xunzhang", + "uncode": "e68e" + }, + { + "cls": "dtree-icon-normal-file", + "uncode": "e60c" + }, + { + "cls": "dtree-icon-roundclose", + "uncode": "e65c" + }, + { + "cls": "dtree-icon-bianji", + "uncode": "e602" + }, + { + "cls": "dtree-icon-roundadd", + "uncode": "e6d9" + }, + { + "cls": "dtree-icon-fuxuankuangxuanzhong", + "uncode": "e652" + }, + { + "cls": "dtree-icon-fuxuankuang", + "uncode": "e6f2" + }, + { + "cls": "dtree-icon-fuxuankuang-banxuan", + "uncode": "e607" + }, + { + "cls": "dtree-icon-search_list_light", + "uncode": "e807" + }, + { + "cls": "dtree-icon-move-up", + "uncode": "ea47" + }, + { + "cls": "dtree-icon-move-down", + "uncode": "ea48" + }, + { + "cls": "dtree-icon-delete1", + "uncode": "e640" + }, + { + "cls": "dtree-icon-refresh", + "uncode": "e6a4" + }, + { + "cls": "dtree-icon-roundcheckfill", + "uncode": "e659" + }, + { + "cls": "dtree-icon-roundclosefill", + "uncode": "e65b" + }, + { + "cls": "dtree-icon-roundcheck", + "uncode": "e65a" + }, + { + "cls": "dtree-icon-pulldown", + "uncode": "e6a0" + }, + { + "cls": "dtree-icon-pullup", + "uncode": "e6a1" + }, + { + "cls": "dtree-icon-set-sm", + "uncode": "e621" + }, + { + "cls": "dtree-icon-rate", + "uncode": "e833" + }, + { + "cls": "dtree-icon-jian1", + "uncode": "e600" + }, + { + "cls": "dtree-icon-jia1", + "uncode": "e601" + }, + { + "cls": "dtree-icon-shijian", + "uncode": "e606" + }, + { + "cls": "dtree-icon-check", + "uncode": "e645" + }, + { + "cls": "dtree-icon-close", + "uncode": "e646" + }, + { + "cls": "dtree-icon-favorfill", + "uncode": "e64b" + }, + { + "cls": "dtree-icon-favor", + "uncode": "e64c" + }, + { + "cls": "dtree-icon-roundrightfill", + "uncode": "e65d" + }, + { + "cls": "dtree-icon-roundright", + "uncode": "e65e" + }, + { + "cls": "dtree-icon-samefill", + "uncode": "e671" + }, + { + "cls": "dtree-icon-same", + "uncode": "e672" + }, + { + "cls": "dtree-icon-qrcode1", + "uncode": "e6b0" + }, + { + "cls": "dtree-icon-profile1", + "uncode": "e6b7" + }, + { + "cls": "dtree-icon-home1", + "uncode": "e6b8" + }, + { + "cls": "dtree-icon-homefill", + "uncode": "e6bb" + }, + { + "cls": "dtree-icon-roundaddfill", + "uncode": "e6d8" + }, + { + "cls": "dtree-icon-wefill", + "uncode": "e6f5" + }, + { + "cls": "dtree-icon-sort", + "uncode": "e701" + }, + { + "cls": "dtree-icon-round_list_light", + "uncode": "e82b" + }, + { + "cls": "dtree-icon-search2", + "uncode": "e615" + }, + { + "cls": "dtree-icon-close1", + "uncode": "1006" + }, + { + "cls": "dtree-icon-close-fill", + "uncode": "1007" + }, + { + "cls": "dtree-icon-chart-screen", + "uncode": "e62a" + }, + { + "cls": "dtree-icon-star", + "uncode": "e608" + }, + { + "cls": "dtree-icon-ok-circle", + "uncode": "1005" + }, + { + "cls": "dtree-icon-add-circle", + "uncode": "e61f" + }, + { + "cls": "dtree-icon-about", + "uncode": "e623" + }, + { + "cls": "dtree-icon-circle1", + "uncode": "e687" + }, + { + "cls": "dtree-icon-radio", + "uncode": "e688" + }, + { + "cls": "dtree-icon-star-fill", + "uncode": "e832" + }, + { + "cls": "dtree-icon-shujudaping", + "uncode": "e742" + }, + { + "cls": "dtree-icon-share3", + "uncode": "e641" + }, + { + "cls": "dtree-icon-youjian", + "uncode": "e642" + }, + { + "cls": "dtree-icon-repair", + "uncode": "e738" + }, + { + "cls": "dtree-icon-evaluate", + "uncode": "e674" + }, + { + "cls": "dtree-icon-like", + "uncode": "e66c" + }, + { + "cls": "dtree-icon-layim-theme", + "uncode": "e61b" + }, + { + "cls": "dtree-icon-xiangmuxiaoxi", + "uncode": "e60f" + } + ] +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/encrypt.js b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/encrypt.js new file mode 100644 index 0000000000000000000000000000000000000000..9594f1a0f1da95d0a13f19d9b332856d711be1cf --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/encrypt.js @@ -0,0 +1,1775 @@ +/** + layui hash extend +**/ + +layui.define(function (exports) { + /** + * jshashes - https://github.com/h2non/jshashes + * Released under the "New BSD" license + * + * Algorithms specification: + * + * MD5 - http://www.ietf.org/rfc/rfc1321.txt + * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html + * SHA1 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + * HMAC - http://www.ietf.org/rfc/rfc2104.txt + */ + var pearHash; + + function utf8Encode(str) { + var x, y, output = '', + i = -1, + l; + + if (str && str.length) { + l = str.length; + while ((i += 1) < l) { + /* Decode utf-16 surrogate pairs */ + x = str.charCodeAt(i); + y = i + 1 < l ? str.charCodeAt(i + 1) : 0; + if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) { + x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); + i += 1; + } + /* Encode output as utf-8 */ + if (x <= 0x7F) { + output += String.fromCharCode(x); + } else if (x <= 0x7FF) { + output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F), + 0x80 | (x & 0x3F)); + } else if (x <= 0xFFFF) { + output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), + 0x80 | ((x >>> 6) & 0x3F), + 0x80 | (x & 0x3F)); + } else if (x <= 0x1FFFFF) { + output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), + 0x80 | ((x >>> 12) & 0x3F), + 0x80 | ((x >>> 6) & 0x3F), + 0x80 | (x & 0x3F)); + } + } + } + return output; + } + + function utf8Decode(str) { + var i, ac, c1, c2, c3, arr = [], + l; + i = ac = c1 = c2 = c3 = 0; + + if (str && str.length) { + l = str.length; + str += ''; + + while (i < l) { + c1 = str.charCodeAt(i); + ac += 1; + if (c1 < 128) { + arr[ac] = String.fromCharCode(c1); + i += 1; + } else if (c1 > 191 && c1 < 224) { + c2 = str.charCodeAt(i + 1); + arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63)); + i += 2; + } else { + c2 = str.charCodeAt(i + 1); + c3 = str.charCodeAt(i + 2); + arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + } + return arr.join(''); + } + + /** + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ + + function safe_add(x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF), + msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); + } + + /** + * Bitwise rotate a 32-bit number to the left. + */ + + function bit_rol(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)); + } + + /** + * Convert a raw string to a hex string + */ + + function rstr2hex(input, hexcase) { + var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef', + output = '', + x, i = 0, + l = input.length; + for (; i < l; i += 1) { + x = input.charCodeAt(i); + output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F); + } + return output; + } + + /** + * Encode a string as utf-16 + */ + + function str2rstr_utf16le(input) { + var i, l = input.length, + output = ''; + for (i = 0; i < l; i += 1) { + output += String.fromCharCode(input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF); + } + return output; + } + + function str2rstr_utf16be(input) { + var i, l = input.length, + output = ''; + for (i = 0; i < l; i += 1) { + output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF); + } + return output; + } + + /** + * Convert an array of big-endian words to a string + */ + + function binb2rstr(input) { + var i, l = input.length * 32, + output = ''; + for (i = 0; i < l; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF); + } + return output; + } + + /** + * Convert an array of little-endian words to a string + */ + + function binl2rstr(input) { + var i, l = input.length * 32, + output = ''; + for (i = 0; i < l; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); + } + return output; + } + + /** + * Convert a raw string to an array of little-endian words + * Characters >255 have their high-byte silently ignored. + */ + + function rstr2binl(input) { + var i, l = input.length * 8, + output = Array(input.length >> 2), + lo = output.length; + for (i = 0; i < lo; i += 1) { + output[i] = 0; + } + for (i = 0; i < l; i += 8) { + output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32); + } + return output; + } + + /** + * Convert a raw string to an array of big-endian words + * Characters >255 have their high-byte silently ignored. + */ + + function rstr2binb(input) { + var i, l = input.length * 8, + output = Array(input.length >> 2), + lo = output.length; + for (i = 0; i < lo; i += 1) { + output[i] = 0; + } + for (i = 0; i < l; i += 8) { + output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32); + } + return output; + } + + /** + * Convert a raw string to an arbitrary string encoding + */ + + function rstr2any(input, encoding) { + var divisor = encoding.length, + remainders = Array(), + i, q, x, ld, quotient, dividend, output, full_length; + + /* Convert to an array of 16-bit big-endian values, forming the dividend */ + dividend = Array(Math.ceil(input.length / 2)); + ld = dividend.length; + for (i = 0; i < ld; i += 1) { + dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); + } + + /** + * Repeatedly perform a long division. The binary array forms the dividend, + * the length of the encoding is the divisor. Once computed, the quotient + * forms the dividend for the next step. We stop when the dividend is zerHashes. + * All remainders are stored for later use. + */ + while (dividend.length > 0) { + quotient = Array(); + x = 0; + for (i = 0; i < dividend.length; i += 1) { + x = (x << 16) + dividend[i]; + q = Math.floor(x / divisor); + x -= q * divisor; + if (quotient.length > 0 || q > 0) { + quotient[quotient.length] = q; + } + } + remainders[remainders.length] = x; + dividend = quotient; + } + + /* Convert the remainders to the output string */ + output = ''; + for (i = remainders.length - 1; i >= 0; i--) { + output += encoding.charAt(remainders[i]); + } + + /* Append leading zero equivalents */ + full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2))); + for (i = output.length; i < full_length; i += 1) { + output = encoding[0] + output; + } + return output; + } + + /** + * Convert a raw string to a base-64 string + */ + + function rstr2b64(input, b64pad) { + var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', + output = '', + len = input.length, + i, j, triplet; + b64pad = b64pad || '='; + for (i = 0; i < len; i += 3) { + triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0); + for (j = 0; j < 4; j += 1) { + if (i * 8 + j * 6 > input.length * 8) { + output += b64pad; + } else { + output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F); + } + } + } + return output; + } + + pearHash = { + /** + * @property {String} version + * @readonly + */ + VERSION: '1.0.6', + /** + * @member Hashes + * @class Base64 + * @constructor + */ + Base64: function () { + // private properties + var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', + pad = '=', // default pad according with the RFC standard + url = false, // URL encoding support @todo + utf8 = true; // by default enable UTF-8 support encoding + + // public method for encoding + this.encode = function (input) { + var i, j, triplet, + output = '', + len = input.length; + + pad = pad || '='; + input = (utf8) ? utf8Encode(input) : input; + + for (i = 0; i < len; i += 3) { + triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0); + for (j = 0; j < 4; j += 1) { + if (i * 8 + j * 6 > len * 8) { + output += pad; + } else { + output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F); + } + } + } + return output; + }; + + // public method for decoding + this.decode = function (input) { + // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + var i, o1, o2, o3, h1, h2, h3, h4, bits, ac, + dec = '', + arr = []; + if (!input) { + return input; + } + + i = ac = 0; + input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '=' + //input += ''; + + do { // unpack four hexets into three octets using index points in b64 + h1 = tab.indexOf(input.charAt(i += 1)); + h2 = tab.indexOf(input.charAt(i += 1)); + h3 = tab.indexOf(input.charAt(i += 1)); + h4 = tab.indexOf(input.charAt(i += 1)); + + bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; + + o1 = bits >> 16 & 0xff; + o2 = bits >> 8 & 0xff; + o3 = bits & 0xff; + ac += 1; + + if (h3 === 64) { + arr[ac] = String.fromCharCode(o1); + } else if (h4 === 64) { + arr[ac] = String.fromCharCode(o1, o2); + } else { + arr[ac] = String.fromCharCode(o1, o2, o3); + } + } while (i < input.length); + + dec = arr.join(''); + dec = (utf8) ? utf8Decode(dec) : dec; + + return dec; + }; + + // set custom pad string + this.setPad = function (str) { + pad = str || pad; + return this; + }; + // set custom tab string characters + this.setTab = function (str) { + tab = str || tab; + return this; + }; + this.setUTF8 = function (bool) { + if (typeof bool === 'boolean') { + utf8 = bool; + } + return this; + }; + }, + + /** + * CRC-32 calculation + * @member Hashes + * @method CRC32 + * @static + * @param {String} str Input String + * @return {String} + */ + CRC32: function (str) { + var crc = 0, + x = 0, + y = 0, + table, i, iTop; + str = utf8Encode(str); + + table = [ + '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ', + '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ', + '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ', + '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ', + 'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ', + '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ', + 'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ', + '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ', + 'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ', + '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ', + 'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ', + '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ', + 'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ', + '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ', + '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ', + '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ', + '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ', + 'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ', + '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ', + 'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ', + '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ', + 'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ', + '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ', + 'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ', + '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ', + 'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D' + ].join(''); + + crc = crc ^ (-1); + for (i = 0, iTop = str.length; i < iTop; i += 1) { + y = (crc ^ str.charCodeAt(i)) & 0xFF; + x = '0x' + table.substr(y * 9, 8); + crc = (crc >>> 8) ^ x; + } + // always return a positive number (that's what >>> 0 does) + return (crc ^ (-1)) >>> 0; + }, + /** + * @member Hashes + * @class MD5 + * @constructor + * @param {Object} [config] + * + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See for more infHashes. + */ + MD5: function (options) { + /** + * Private config properties. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase} + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase + b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding + + // privileged (public) methods + this.hex = function (s) { + return rstr2hex(rstr(s, utf8), hexcase); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s, utf8), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d), hexcase); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * Enable/disable uppercase hexadecimal returned string + * @param {Boolean} + * @return {Object} this + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * Defines a base64 pad string + * @param {String} Pad + * @return {Object} this + */ + this.setPad = function (a) { + b64pad = a || b64pad; + return this; + }; + /** + * Defines a base64 pad string + * @param {Boolean} + * @return {Object} [this] + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + // private methods + + /** + * Calculate the MD5 of a raw string + */ + + function rstr(s) { + s = (utf8) ? utf8Encode(s) : s; + return binl2rstr(binl(rstr2binl(s), s.length * 8)); + } + + /** + * Calculate the HMAC-MD5, of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + var bkey, ipad, opad, hash, i; + + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + bkey = rstr2binl(key); + if (bkey.length > 16) { + bkey = binl(bkey, key.length * 8); + } + + ipad = Array(16), opad = Array(16); + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8); + return binl2rstr(binl(opad.concat(hash), 512 + 128)); + } + + /** + * Calculate the MD5 of an array of little-endian words, and a bit length. + */ + + function binl(x, len) { + var i, olda, oldb, oldc, oldd, + a = 1732584193, + b = -271733879, + c = -1732584194, + d = 271733878; + + /* append padding */ + x[len >> 5] |= 0x80 << ((len) % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + for (i = 0; i < x.length; i += 16) { + olda = a; + oldb = b; + oldc = c; + oldd = d; + + a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936); + d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); + d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); + d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); + b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); + d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); + d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); + c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); + d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); + c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); + d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); + c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); + d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); + c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); + d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); + d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); + d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); + d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844); + d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); + d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); + d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); + d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + } + return Array(a, b, c, d); + } + + /** + * These functions implement the four basic operations the algorithm uses. + */ + + function md5_cmn(q, a, b, x, s, t) { + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); + } + + function md5_ff(a, b, c, d, x, s, t) { + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); + } + + function md5_gg(a, b, c, d, x, s, t) { + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); + } + + function md5_hh(a, b, c, d, x, s, t) { + return md5_cmn(b ^ c ^ d, a, b, x, s, t); + } + + function md5_ii(a, b, c, d, x, s, t) { + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); + } + }, + /** + * @member Hashes + * @class Hashes.SHA1 + * @param {Object} [config] + * @constructor + * + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1 + * Version 2.2 Copyright Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See http://pajhome.org.uk/crypt/md5 for details. + */ + SHA1: function (options) { + /** + * Private config properties. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase} + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase + b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding + + // public methods + this.hex = function (s) { + return rstr2hex(rstr(s, utf8), hexcase); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s, utf8), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s, utf8), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d)); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + * @public + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * @description Enable/disable uppercase hexadecimal returned string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {string} Pad + * @return {Object} this + * @public + */ + this.setPad = function (a) { + b64pad = a || b64pad; + return this; + }; + /** + * @description Defines a base64 pad string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + // private methods + + /** + * Calculate the SHA-512 of a raw string + */ + + function rstr(s) { + s = (utf8) ? utf8Encode(s) : s; + return binb2rstr(binb(rstr2binb(s), s.length * 8)); + } + + /** + * Calculate the HMAC-SHA1 of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + var bkey, ipad, opad, i, hash; + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + bkey = rstr2binb(key); + + if (bkey.length > 16) { + bkey = binb(bkey, key.length * 8); + } + ipad = Array(16), opad = Array(16); + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8); + return binb2rstr(binb(opad.concat(hash), 512 + 160)); + } + + /** + * Calculate the SHA-1 of an array of big-endian words, and a bit length + */ + + function binb(x, len) { + var i, j, t, olda, oldb, oldc, oldd, olde, + w = Array(80), + a = 1732584193, + b = -271733879, + c = -1732584194, + d = 271733878, + e = -1009589776; + + /* append padding */ + x[len >> 5] |= 0x80 << (24 - len % 32); + x[((len + 64 >> 9) << 4) + 15] = len; + + for (i = 0; i < x.length; i += 16) { + olda = a; + oldb = b; + oldc = c; + oldd = d; + olde = e; + + for (j = 0; j < 80; j += 1) { + if (j < 16) { + w[j] = x[i + j]; + } else { + w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); + } + t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), + safe_add(safe_add(e, w[j]), sha1_kt(j))); + e = d; + d = c; + c = bit_rol(b, 30); + b = a; + a = t; + } + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + e = safe_add(e, olde); + } + return Array(a, b, c, d, e); + } + + /** + * Perform the appropriate triplet combination function for the current + * iteration + */ + + function sha1_ft(t, b, c, d) { + if (t < 20) { + return (b & c) | ((~b) & d); + } + if (t < 40) { + return b ^ c ^ d; + } + if (t < 60) { + return (b & c) | (b & d) | (c & d); + } + return b ^ c ^ d; + } + + /** + * Determine the appropriate additive constant for the current iteration + */ + + function sha1_kt(t) { + return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : + (t < 60) ? -1894007588 : -899497514; + } + }, + /** + * @class Hashes.SHA256 + * @param {config} + * + * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2 + * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See http://pajhome.org.uk/crypt/md5 for details. + * Also http://anmar.eu.org/projects/jssha2/ + */ + SHA256: function (options) { + /** + * Private properties configuration variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * @see this.setUpperCase() method + * @see this.setPad() method + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase */ + b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', + /* base-64 pad character. Default '=' for strict RFC compliance */ + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, + /* enable/disable utf8 encoding */ + sha256_K; + + /* privileged (public) methods */ + this.hex = function (s) { + return rstr2hex(rstr(s, utf8)); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s, utf8), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s, utf8), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d)); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + * @public + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * Enable/disable uppercase hexadecimal returned string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {string} Pad + * @return {Object} this + * @public + */ + this.setPad = function (a) { + b64pad = a || b64pad; + return this; + }; + /** + * Defines a base64 pad string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + // private methods + + /** + * Calculate the SHA-512 of a raw string + */ + + function rstr(s, utf8) { + s = (utf8) ? utf8Encode(s) : s; + return binb2rstr(binb(rstr2binb(s), s.length * 8)); + } + + /** + * Calculate the HMAC-sha256 of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + var hash, i = 0, + bkey = rstr2binb(key), + ipad = Array(16), + opad = Array(16); + + if (bkey.length > 16) { + bkey = binb(bkey, key.length * 8); + } + + for (; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8); + return binb2rstr(binb(opad.concat(hash), 512 + 256)); + } + + /* + * Main sha256 function, with its support functions + */ + + function sha256_S(X, n) { + return (X >>> n) | (X << (32 - n)); + } + + function sha256_R(X, n) { + return (X >>> n); + } + + function sha256_Ch(x, y, z) { + return ((x & y) ^ ((~x) & z)); + } + + function sha256_Maj(x, y, z) { + return ((x & y) ^ (x & z) ^ (y & z)); + } + + function sha256_Sigma0256(x) { + return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22)); + } + + function sha256_Sigma1256(x) { + return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25)); + } + + function sha256_Gamma0256(x) { + return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3)); + } + + function sha256_Gamma1256(x) { + return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10)); + } + + function sha256_Sigma0512(x) { + return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39)); + } + + function sha256_Sigma1512(x) { + return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41)); + } + + function sha256_Gamma0512(x) { + return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7)); + } + + function sha256_Gamma1512(x) { + return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6)); + } + + sha256_K = [ + 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, + 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522, + 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585, + 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, + 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, + 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, + 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998 + ]; + + function binb(m, l) { + var HASH = [1779033703, -1150833019, 1013904242, -1521486534, + 1359893119, -1694144372, 528734635, 1541459225 + ]; + var W = new Array(64); + var a, b, c, d, e, f, g, h; + var i, j, T1, T2; + + /* append padding */ + m[l >> 5] |= 0x80 << (24 - l % 32); + m[((l + 64 >> 9) << 4) + 15] = l; + + for (i = 0; i < m.length; i += 16) { + a = HASH[0]; + b = HASH[1]; + c = HASH[2]; + d = HASH[3]; + e = HASH[4]; + f = HASH[5]; + g = HASH[6]; + h = HASH[7]; + + for (j = 0; j < 64; j += 1) { + if (j < 16) { + W[j] = m[j + i]; + } else { + W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]), + sha256_Gamma0256(W[j - 15])), W[j - 16]); + } + + T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)), + sha256_K[j]), W[j]); + T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c)); + h = g; + g = f; + f = e; + e = safe_add(d, T1); + d = c; + c = b; + b = a; + a = safe_add(T1, T2); + } + + HASH[0] = safe_add(a, HASH[0]); + HASH[1] = safe_add(b, HASH[1]); + HASH[2] = safe_add(c, HASH[2]); + HASH[3] = safe_add(d, HASH[3]); + HASH[4] = safe_add(e, HASH[4]); + HASH[5] = safe_add(f, HASH[5]); + HASH[6] = safe_add(g, HASH[6]); + HASH[7] = safe_add(h, HASH[7]); + } + return HASH; + } + + }, + + /** + * @class Hashes.SHA512 + * @param {config} + * + * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2 + * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See http://pajhome.org.uk/crypt/md5 for details. + */ + SHA512: function (options) { + /** + * Private properties configuration variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * @see this.setUpperCase() method + * @see this.setPad() method + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, + /* hexadecimal output case format. false - lowercase; true - uppercase */ + b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', + /* base-64 pad character. Default '=' for strict RFC compliance */ + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, + /* enable/disable utf8 encoding */ + sha512_k; + + /* privileged (public) methods */ + this.hex = function (s) { + return rstr2hex(rstr(s)); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d)); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + * @public + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * @description Enable/disable uppercase hexadecimal returned string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {string} Pad + * @return {Object} this + * @public + */ + this.setPad = function (a) { + b64pad = a || b64pad; + return this; + }; + /** + * @description Defines a base64 pad string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + /* private methods */ + + /** + * Calculate the SHA-512 of a raw string + */ + + function rstr(s) { + s = (utf8) ? utf8Encode(s) : s; + return binb2rstr(binb(rstr2binb(s), s.length * 8)); + } + /* + * Calculate the HMAC-SHA-512 of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + + var hash, i = 0, + bkey = rstr2binb(key), + ipad = Array(32), + opad = Array(32); + + if (bkey.length > 32) { + bkey = binb(bkey, key.length * 8); + } + + for (; i < 32; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8); + return binb2rstr(binb(opad.concat(hash), 1024 + 512)); + } + + /** + * Calculate the SHA-512 of an array of big-endian dwords, and a bit length + */ + + function binb(x, len) { + var j, i, l, + W = new Array(80), + hash = new Array(16), + //Initial hash values + H = [ + new int64(0x6a09e667, -205731576), + new int64(-1150833019, -2067093701), + new int64(0x3c6ef372, -23791573), + new int64(-1521486534, 0x5f1d36f1), + new int64(0x510e527f, -1377402159), + new int64(-1694144372, 0x2b3e6c1f), + new int64(0x1f83d9ab, -79577749), + new int64(0x5be0cd19, 0x137e2179) + ], + T1 = new int64(0, 0), + T2 = new int64(0, 0), + a = new int64(0, 0), + b = new int64(0, 0), + c = new int64(0, 0), + d = new int64(0, 0), + e = new int64(0, 0), + f = new int64(0, 0), + g = new int64(0, 0), + h = new int64(0, 0), + //Temporary variables not specified by the document + s0 = new int64(0, 0), + s1 = new int64(0, 0), + Ch = new int64(0, 0), + Maj = new int64(0, 0), + r1 = new int64(0, 0), + r2 = new int64(0, 0), + r3 = new int64(0, 0); + + if (sha512_k === undefined) { + //SHA512 constants + sha512_k = [ + new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd), + new int64(-1245643825, -330482897), new int64(-373957723, -2121671748), + new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031), + new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736), + new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe), + new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302), + new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1), + new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428), + new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3), + new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65), + new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483), + new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459), + new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210), + new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340), + new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395), + new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70), + new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926), + new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473), + new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8), + new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b), + new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023), + new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30), + new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910), + new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8), + new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53), + new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016), + new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893), + new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397), + new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60), + new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec), + new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047), + new int64(-1090935817, -1295615723), new int64(-965641998, -479046869), + new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207), + new int64(-354779690, -840897762), new int64(-176337025, -294727304), + new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026), + new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b), + new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493), + new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620), + new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430), + new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817) + ]; + } + + for (i = 0; i < 80; i += 1) { + W[i] = new int64(0, 0); + } + + // append padding to the source string. The format is described in the FIPS. + x[len >> 5] |= 0x80 << (24 - (len & 0x1f)); + x[((len + 128 >> 10) << 5) + 31] = len; + l = x.length; + for (i = 0; i < l; i += 32) { //32 dwords is the block size + int64copy(a, H[0]); + int64copy(b, H[1]); + int64copy(c, H[2]); + int64copy(d, H[3]); + int64copy(e, H[4]); + int64copy(f, H[5]); + int64copy(g, H[6]); + int64copy(h, H[7]); + + for (j = 0; j < 16; j += 1) { + W[j].h = x[i + 2 * j]; + W[j].l = x[i + 2 * j + 1]; + } + + for (j = 16; j < 80; j += 1) { + //sigma1 + int64rrot(r1, W[j - 2], 19); + int64revrrot(r2, W[j - 2], 29); + int64shr(r3, W[j - 2], 6); + s1.l = r1.l ^ r2.l ^ r3.l; + s1.h = r1.h ^ r2.h ^ r3.h; + //sigma0 + int64rrot(r1, W[j - 15], 1); + int64rrot(r2, W[j - 15], 8); + int64shr(r3, W[j - 15], 7); + s0.l = r1.l ^ r2.l ^ r3.l; + s0.h = r1.h ^ r2.h ^ r3.h; + + int64add4(W[j], s1, W[j - 7], s0, W[j - 16]); + } + + for (j = 0; j < 80; j += 1) { + //Ch + Ch.l = (e.l & f.l) ^ (~e.l & g.l); + Ch.h = (e.h & f.h) ^ (~e.h & g.h); + + //Sigma1 + int64rrot(r1, e, 14); + int64rrot(r2, e, 18); + int64revrrot(r3, e, 9); + s1.l = r1.l ^ r2.l ^ r3.l; + s1.h = r1.h ^ r2.h ^ r3.h; + + //Sigma0 + int64rrot(r1, a, 28); + int64revrrot(r2, a, 2); + int64revrrot(r3, a, 7); + s0.l = r1.l ^ r2.l ^ r3.l; + s0.h = r1.h ^ r2.h ^ r3.h; + + //Maj + Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l); + Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h); + + int64add5(T1, h, s1, Ch, sha512_k[j], W[j]); + int64add(T2, s0, Maj); + + int64copy(h, g); + int64copy(g, f); + int64copy(f, e); + int64add(e, d, T1); + int64copy(d, c); + int64copy(c, b); + int64copy(b, a); + int64add(a, T1, T2); + } + int64add(H[0], H[0], a); + int64add(H[1], H[1], b); + int64add(H[2], H[2], c); + int64add(H[3], H[3], d); + int64add(H[4], H[4], e); + int64add(H[5], H[5], f); + int64add(H[6], H[6], g); + int64add(H[7], H[7], h); + } + + //represent the hash as an array of 32-bit dwords + for (i = 0; i < 8; i += 1) { + hash[2 * i] = H[i].h; + hash[2 * i + 1] = H[i].l; + } + return hash; + } + + //A constructor for 64-bit numbers + + function int64(h, l) { + this.h = h; + this.l = l; + //this.toString = int64toString; + } + + //Copies src into dst, assuming both are 64-bit numbers + + function int64copy(dst, src) { + dst.h = src.h; + dst.l = src.l; + } + + //Right-rotates a 64-bit number by shift + //Won't handle cases of shift>=32 + //The function revrrot() is for that + + function int64rrot(dst, x, shift) { + dst.l = (x.l >>> shift) | (x.h << (32 - shift)); + dst.h = (x.h >>> shift) | (x.l << (32 - shift)); + } + + //Reverses the dwords of the source and then rotates right by shift. + //This is equivalent to rotation by 32+shift + + function int64revrrot(dst, x, shift) { + dst.l = (x.h >>> shift) | (x.l << (32 - shift)); + dst.h = (x.l >>> shift) | (x.h << (32 - shift)); + } + + //Bitwise-shifts right a 64-bit number by shift + //Won't handle shift>=32, but it's never needed in SHA512 + + function int64shr(dst, x, shift) { + dst.l = (x.l >>> shift) | (x.h << (32 - shift)); + dst.h = (x.h >>> shift); + } + + //Adds two 64-bit numbers + //Like the original implementation, does not rely on 32-bit operations + + function int64add(dst, x, y) { + var w0 = (x.l & 0xffff) + (y.l & 0xffff); + var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16); + var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16); + var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16); + dst.l = (w0 & 0xffff) | (w1 << 16); + dst.h = (w2 & 0xffff) | (w3 << 16); + } + + //Same, except with 4 addends. Works faster than adding them one by one. + + function int64add4(dst, a, b, c, d) { + var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff); + var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16); + var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16); + var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16); + dst.l = (w0 & 0xffff) | (w1 << 16); + dst.h = (w2 & 0xffff) | (w3 << 16); + } + + //Same, except with 5 addends + + function int64add5(dst, a, b, c, d, e) { + var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff), + w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16), + w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16), + w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16); + dst.l = (w0 & 0xffff) | (w1 << 16); + dst.h = (w2 & 0xffff) | (w3 << 16); + } + }, + /** + * @class Hashes.RMD160 + * @constructor + * @param {Object} [config] + * + * A JavaScript implementation of the RIPEMD-160 Algorithm + * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See http://pajhome.org.uk/crypt/md5 for details. + * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/ + */ + RMD160: function (options) { + /** + * Private properties configuration variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * @see this.setUpperCase() method + * @see this.setPad() method + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, + /* hexadecimal output case format. false - lowercase; true - uppercase */ + b64pad = (options && typeof options.pad === 'string') ? options.pa : '=', + /* base-64 pad character. Default '=' for strict RFC compliance */ + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, + /* enable/disable utf8 encoding */ + rmd160_r1 = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 + ], + rmd160_r2 = [ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 + ], + rmd160_s1 = [ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 + ], + rmd160_s2 = [ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 + ]; + + /* privileged (public) methods */ + this.hex = function (s) { + return rstr2hex(rstr(s, utf8)); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s, utf8), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s, utf8), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d)); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + * @public + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * @description Enable/disable uppercase hexadecimal returned string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {string} Pad + * @return {Object} this + * @public + */ + this.setPad = function (a) { + if (typeof a !== 'undefined') { + b64pad = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + /* private methods */ + + /** + * Calculate the rmd160 of a raw string + */ + + function rstr(s) { + s = (utf8) ? utf8Encode(s) : s; + return binl2rstr(binl(rstr2binl(s), s.length * 8)); + } + + /** + * Calculate the HMAC-rmd160 of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + var i, hash, + bkey = rstr2binl(key), + ipad = Array(16), + opad = Array(16); + + if (bkey.length > 16) { + bkey = binl(bkey, key.length * 8); + } + + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8); + return binl2rstr(binl(opad.concat(hash), 512 + 160)); + } + + /** + * Convert an array of little-endian words to a string + */ + + function binl2rstr(input) { + var i, output = '', + l = input.length * 32; + for (i = 0; i < l; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); + } + return output; + } + + /** + * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length. + */ + + function binl(x, len) { + var T, j, i, l, + h0 = 0x67452301, + h1 = 0xefcdab89, + h2 = 0x98badcfe, + h3 = 0x10325476, + h4 = 0xc3d2e1f0, + A1, B1, C1, D1, E1, + A2, B2, C2, D2, E2; + + /* append padding */ + x[len >> 5] |= 0x80 << (len % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + l = x.length; + + for (i = 0; i < l; i += 16) { + A1 = A2 = h0; + B1 = B2 = h1; + C1 = C2 = h2; + D1 = D2 = h3; + E1 = E2 = h4; + for (j = 0; j <= 79; j += 1) { + T = safe_add(A1, rmd160_f(j, B1, C1, D1)); + T = safe_add(T, x[i + rmd160_r1[j]]); + T = safe_add(T, rmd160_K1(j)); + T = safe_add(bit_rol(T, rmd160_s1[j]), E1); + A1 = E1; + E1 = D1; + D1 = bit_rol(C1, 10); + C1 = B1; + B1 = T; + T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2)); + T = safe_add(T, x[i + rmd160_r2[j]]); + T = safe_add(T, rmd160_K2(j)); + T = safe_add(bit_rol(T, rmd160_s2[j]), E2); + A2 = E2; + E2 = D2; + D2 = bit_rol(C2, 10); + C2 = B2; + B2 = T; + } + + T = safe_add(h1, safe_add(C1, D2)); + h1 = safe_add(h2, safe_add(D1, E2)); + h2 = safe_add(h3, safe_add(E1, A2)); + h3 = safe_add(h4, safe_add(A1, B2)); + h4 = safe_add(h0, safe_add(B1, C2)); + h0 = T; + } + return [h0, h1, h2, h3, h4]; + } + + // specific algorithm methods + + function rmd160_f(j, x, y, z) { + return (0 <= j && j <= 15) ? (x ^ y ^ z) : + (16 <= j && j <= 31) ? (x & y) | (~x & z) : + (32 <= j && j <= 47) ? (x | ~y) ^ z : + (48 <= j && j <= 63) ? (x & z) | (y & ~z) : + (64 <= j && j <= 79) ? x ^ (y | ~z) : + 'rmd160_f: j out of range'; + } + + function rmd160_K1(j) { + return (0 <= j && j <= 15) ? 0x00000000 : + (16 <= j && j <= 31) ? 0x5a827999 : + (32 <= j && j <= 47) ? 0x6ed9eba1 : + (48 <= j && j <= 63) ? 0x8f1bbcdc : + (64 <= j && j <= 79) ? 0xa953fd4e : + 'rmd160_K1: j out of range'; + } + + function rmd160_K2(j) { + return (0 <= j && j <= 15) ? 0x50a28be6 : + (16 <= j && j <= 31) ? 0x5c4dd124 : + (32 <= j && j <= 47) ? 0x6d703ef3 : + (48 <= j && j <= 63) ? 0x7a6d76e9 : + (64 <= j && j <= 79) ? 0x00000000 : + 'rmd160_K2: j out of range'; + } + } + }; + + // new MD5 instance + var MD5 = new pearHash.MD5 + // new SHA1 instance + var SHA1 = new pearHash.SHA1 + // new SHA256 instance + var SHA256 = new pearHash.SHA256 + // new SHA512 instace + var SHA512 = new pearHash.SHA512 + // new RIPEMD-160 instace + var RMD160 = new pearHash.RMD160 + var Base64 = new pearHash.Base64 + + pearHash.md5 = function (str) { + return MD5.hex(str); + } + pearHash.sha1 = function (str) { + return SHA1.hex(str); + } + pearHash.sha256 = function (str) { + return SHA256.hex(str); + } + pearHash.sha512 = function (str) { + return SHA512.hex(str); + } + pearHash.crc32 = pearHash.CRC32; + pearHash.rmd160 = function (str) { + return RMD160.hex(str); + } + pearHash.Base64Encode = function (str) { + return Base64.encode(str); + } + pearHash.Base64Decode = function (str) { + return Base64.decode(str); + } + exports('encrypt', pearHash); +}); \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/iconPicker.js b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/iconPicker.js new file mode 100644 index 0000000000000000000000000000000000000000..bde668d1e9bab8853c91fc2af88445e87cc81283 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/iconPicker.js @@ -0,0 +1,491 @@ +layui.define(['laypage', 'form'], function(exports) { + "use strict"; + + var IconPicker = function() { + this.v = '1.1'; + }, + _MOD = 'iconPicker', + _this = this, + $ = layui.jquery, + laypage = layui.laypage, + form = layui.form, + BODY = 'body', + TIPS = '请选择图标'; + + /** + * 渲染组件 + */ + IconPicker.prototype.render = function(options) { + var opts = options, + // DOM选择器 + elem = opts.elem, + // 数据类型:fontClass/unicode + type = opts.type == null ? 'fontClass' : opts.type, + // 是否分页:true/false + page = opts.page == null ? true : opts.page, + // 每页显示数量 + limit = opts.limit == null ? 12 : opts.limit, + // 是否开启搜索:true/false + search = opts.search == null ? true : opts.search, + // 每个图标格子的宽度:'43px'或'20%' + cellWidth = opts.cellWidth, + // 点击回调 + click = opts.click, + // 渲染成功后的回调 + success = opts.success, + // json数据 + data = {}, + // 唯一标识 + tmp = new Date().getTime(), + // 是否使用的class数据 + isFontClass = opts.type === 'fontClass', + // 初始化时input的值 + ORIGINAL_ELEM_VALUE = $(elem).val(), + TITLE = 'layui-select-title', + TITLE_ID = 'layui-select-title-' + tmp, + ICON_BODY = 'layui-iconpicker-' + tmp, + PICKER_BODY = 'layui-iconpicker-body-' + tmp, + PAGE_ID = 'layui-iconpicker-page-' + tmp, + LIST_BOX = 'layui-iconpicker-list-box', + selected = 'layui-form-selected', + unselect = 'layui-unselect'; + + var a = { + init: function() { + data = common.getData[type](); + + a.hideElem().createSelect().createBody().toggleSelect(); + a.preventEvent().inputListen(); + common.loadCss(); + + if (success) { + success(this.successHandle()); + } + + return a; + }, + successHandle: function() { + var d = { + options: opts, + data: data, + id: tmp, + elem: $('#' + ICON_BODY) + }; + return d; + }, + /** + * 隐藏elem + */ + hideElem: function() { + $(elem).hide(); + return a; + }, + /** + * 绘制select下拉选择框 + */ + createSelect: function() { + var oriIcon = ''; + + // 默认图标 + if (ORIGINAL_ELEM_VALUE === '') { + if (isFontClass) { + ORIGINAL_ELEM_VALUE = 'layui-icon-circle-dot'; + } else { + ORIGINAL_ELEM_VALUE = ''; + } + } + + if (isFontClass) { + oriIcon = ''; + } else { + oriIcon += ORIGINAL_ELEM_VALUE; + } + oriIcon += ''; + + var selectHtml = + '
                    ' + + '
                    ' + + '
                    ' + + '' + + oriIcon + + '' + + '' + + '
                    ' + + '
                    ' + + '
                    ' + + '123' + + '
                    '; + $(elem).after(selectHtml); + return a; + }, + /** + * 展开/折叠下拉框 + */ + toggleSelect: function() { + var item = '#' + TITLE_ID + ' .layui-iconpicker-item,#' + TITLE_ID + + ' .layui-iconpicker-item .layui-edge'; + a.event('click', item, function(e) { + var $icon = $('#' + ICON_BODY); + if ($icon.hasClass(selected)) { + $icon.removeClass(selected).addClass(unselect); + } else { + // 隐藏其他picker + $('.layui-form-select').removeClass(selected); + // 显示当前picker + $icon.addClass(selected).removeClass(unselect); + } + e.stopPropagation(); + }); + return a; + }, + /** + * 绘制主体部分 + */ + createBody: function() { + // 获取数据 + var searchHtml = ''; + + if (search) { + searchHtml = ''; + } + + // 组合dom + var bodyHtml = '
                    ' + + searchHtml + + '
                    ' + + '
                    '; + $('#' + ICON_BODY).find('.layui-anim').eq(0).html(bodyHtml); + a.search().createList().check().page(); + + return a; + }, + /** + * 绘制图标列表 + * @param text 模糊查询关键字 + * @returns {string} + */ + createList: function(text) { + var d = data, + l = d.length, + pageHtml = '', + listHtml = $( + '
                    ') //'
                    '; + + // 计算分页数据 + var _limit = limit, // 每页显示数量 + _pages = l % _limit === 0 ? l / _limit : parseInt(l / _limit + 1), // 总计多少页 + _id = PAGE_ID; + + // 图标列表 + var icons = []; + + for (var i = 0; i < l; i++) { + var obj = d[i]; + + // 判断是否模糊查询 + if (text && obj.indexOf(text) === -1) { + continue; + } + + // 是否自定义格子宽度 + var style = ''; + if (cellWidth !== null) { + style += ' style="width:' + cellWidth + '"'; + } + + // 每个图标dom + var icon = '
                    '; + if (isFontClass) { + icon += ''; + } else { + icon += '' + obj.replace('amp;', '') + ''; + } + icon += '
                    '; + + icons.push(icon); + } + + // 查询出图标后再分页 + l = icons.length; + _pages = l % _limit === 0 ? l / _limit : parseInt(l / _limit + 1); + for (var i = 0; i < _pages; i++) { + // 按limit分块 + var lm = $( + '
                    '); + + for (var j = i * _limit; j < (i + 1) * _limit && j < l; j++) { + lm.append(icons[j]); + } + + listHtml.append(lm); + } + + // 无数据 + if (l === 0) { + listHtml.append('

                    无数据

                    '); + } + + // 判断是否分页 + if (page) { + $('#' + PICKER_BODY).addClass('layui-iconpicker-body-page'); + pageHtml = '
                    ' + + '
                    ' + + '1/' + + '' + _pages + '' + + ' (' + l + ')' + + '
                    ' + + '
                    ' + + ' ' + + ' ' + + '
                    ' + + '
                    '; + } + + + $('#' + ICON_BODY).find('.layui-anim').find('.' + LIST_BOX).html('').append( + listHtml).append(pageHtml); + return a; + }, + // 阻止Layui的一些默认事件 + preventEvent: function() { + var item = '#' + ICON_BODY + ' .layui-anim'; + a.event('click', item, function(e) { + e.stopPropagation(); + }); + return a; + }, + // 分页 + page: function() { + var icon = '#' + PAGE_ID + ' .layui-iconpicker-page-operate .layui-icon'; + + $(icon).unbind('click'); + a.event('click', icon, function(e) { + var elem = e.currentTarget, + total = parseInt($('#' + PAGE_ID + '-pages').html()), + isPrev = $(elem).attr('prev') !== undefined, + // 按钮上标的页码 + index = parseInt($(elem).attr('data-index')), + $cur = $('#' + PAGE_ID + '-current'), + // 点击时正在显示的页码 + current = parseInt($cur.html()); + + // 分页数据 + if (isPrev && current > 1) { + current = current - 1; + $(icon + '[prev]').attr('data-index', current); + } else if (!isPrev && current < total) { + current = current + 1; + $(icon + '[next]').attr('data-index', current); + } + $cur.html(current); + + // 图标数据 + $('#' + ICON_BODY + ' .layui-iconpicker-icon-limit').hide(); + $('#layui-iconpicker-icon-limit-' + tmp + current).show(); + e.stopPropagation(); + }); + return a; + }, + /** + * 搜索 + */ + search: function() { + var item = '#' + PICKER_BODY + ' .layui-iconpicker-search .layui-input'; + a.event('input propertychange', item, function(e) { + var elem = e.target, + t = $(elem).val(); + a.createList(t); + }); + return a; + }, + /** + * 点击选中图标 + */ + check: function() { + var item = '#' + PICKER_BODY + ' .layui-iconpicker-icon-item'; + a.event('click', item, function(e) { + var el = $(e.currentTarget).find('.layui-icon'), + icon = ''; + if (isFontClass) { + var clsArr = el.attr('class').split(/[\s\n]/), + cls = clsArr[1], + icon = cls; + $('#' + TITLE_ID).find('.layui-iconpicker-item .layui-icon').html( + '').attr('class', clsArr.join(' ')); + } else { + var cls = el.html(), + icon = cls; + $('#' + TITLE_ID).find('.layui-iconpicker-item .layui-icon').html( + icon); + } + + $('#' + ICON_BODY).removeClass(selected).addClass(unselect); + $(elem).val(icon).attr('value', icon); + // 回调 + if (click) { + click({ + icon: icon + }); + } + + }); + return a; + }, + // 监听原始input数值改变 + inputListen: function() { + var el = $(elem); + a.event('change', elem, function() { + var value = el.val(); + }) + // el.change(function(){ + + // }); + return a; + }, + event: function(evt, el, fn) { + $(BODY).on(evt, el, fn); + } + }; + + var common = { + /** + * 加载样式表 + */ + loadCss: function() { + var css = + '.layui-iconpicker {max-width: 280px;}.layui-iconpicker .layui-anim{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box;}.layui-iconpicker-item{border:1px solid #e6e6e6;width:90px;height:38px;border-radius:4px;cursor:pointer;position:relative;}.layui-iconpicker-icon{border-right:1px solid #e6e6e6;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;width:60px;height:100%;float:left;text-align:center;background:#fff;transition:all .3s;}.layui-iconpicker-icon i{line-height:38px;font-size:18px;}.layui-iconpicker-item > .layui-edge{left:70px;}.layui-iconpicker-item:hover{border-color:#D2D2D2!important;}.layui-iconpicker-item:hover .layui-iconpicker-icon{border-color:#D2D2D2!important;}.layui-iconpicker.layui-form-selected .layui-anim{display:block;}.layui-iconpicker-body{padding:6px;}.layui-iconpicker .layui-iconpicker-list{background-color:#fff;border:1px solid #ccc;border-radius:4px;}.layui-iconpicker .layui-iconpicker-icon-item{display:inline-block;width:21.1%;line-height:36px;text-align:center;cursor:pointer;vertical-align:top;height:36px;margin:4px;border:1px solid #ddd;border-radius:2px;transition:300ms;}.layui-iconpicker .layui-iconpicker-icon-item i.layui-icon{font-size:17px;}.layui-iconpicker .layui-iconpicker-icon-item:hover{background-color:#eee;border-color:#ccc;-webkit-box-shadow:0 0 2px #aaa,0 0 2px #fff inset;-moz-box-shadow:0 0 2px #aaa,0 0 2px #fff inset;box-shadow:0 0 2px #aaa,0 0 2px #fff inset;text-shadow:0 0 1px #fff;}.layui-iconpicker-search{position:relative;margin:0 0 6px 0;border:1px solid #e6e6e6;border-radius:2px;transition:300ms;}.layui-iconpicker-search:hover{border-color:#D2D2D2!important;}.layui-iconpicker-search .layui-input{cursor:text;display:inline-block;width:86%;border:none;padding-right:0;margin-top:1px;}.layui-iconpicker-search .layui-icon{position:absolute;top:11px;right:4%;}.layui-iconpicker-tips{text-align:center;padding:8px 0;cursor:not-allowed;}.layui-iconpicker-page{margin-top:6px;margin-bottom:-6px;font-size:12px;padding:0 2px;}.layui-iconpicker-page-count{display:inline-block;}.layui-iconpicker-page-operate{display:inline-block;float:right;cursor:default;}.layui-iconpicker-page-operate .layui-icon{font-size:12px;cursor:pointer;}.layui-iconpicker-body-page .layui-iconpicker-icon-limit{display:none;}.layui-iconpicker-body-page .layui-iconpicker-icon-limit:first-child{display:block;}'; + var $style = $('head').find('style[iconpicker]'); + if ($style.length === 0) { + $('head').append(''); + } + }, + /** + * 获取数据 + */ + getData: { + fontClass: function() { + var arr = ["layui-icon-rate-half", "layui-icon-rate", "layui-icon-rate-solid", + "layui-icon-cellphone", "layui-icon-vercode", "layui-icon-login-wechat", + "layui-icon-login-qq", "layui-icon-login-weibo", "layui-icon-password", + "layui-icon-username", "layui-icon-refresh-3", "layui-icon-auz", + "layui-icon-spread-left", "layui-icon-shrink-right", + "layui-icon-snowflake", "layui-icon-tips", "layui-icon-note", + "layui-icon-home", "layui-icon-senior", "layui-icon-refresh", + "layui-icon-refresh-1", "layui-icon-flag", "layui-icon-theme", + "layui-icon-notice", "layui-icon-website", "layui-icon-console", + "layui-icon-face-surprised", "layui-icon-set", "layui-icon-template-1", + "layui-icon-app", "layui-icon-template", "layui-icon-praise", + "layui-icon-tread", "layui-icon-male", "layui-icon-female", + "layui-icon-camera", "layui-icon-camera-fill", "layui-icon-more", + "layui-icon-more-vertical", "layui-icon-rmb", "layui-icon-dollar", + "layui-icon-diamond", "layui-icon-fire", "layui-icon-return", + "layui-icon-location", "layui-icon-read", "layui-icon-survey", + "layui-icon-face-smile", "layui-icon-face-cry", + "layui-icon-cart-simple", "layui-icon-cart", "layui-icon-next", + "layui-icon-prev", "layui-icon-upload-drag", "layui-icon-upload", + "layui-icon-download-circle", "layui-icon-component", + "layui-icon-file-b", "layui-icon-user", "layui-icon-find-fill", + "layui-icon-loading", "layui-icon-loading-1", "layui-icon-add-1", + "layui-icon-play", "layui-icon-pause", "layui-icon-headset", + "layui-icon-video", "layui-icon-voice", "layui-icon-speaker", + "layui-icon-fonts-del", "layui-icon-fonts-code", + "layui-icon-fonts-html", "layui-icon-fonts-strong", "layui-icon-unlink", + "layui-icon-picture", "layui-icon-link", "layui-icon-face-smile-b", + "layui-icon-align-left", "layui-icon-align-right", + "layui-icon-align-center", "layui-icon-fonts-u", "layui-icon-fonts-i", + "layui-icon-tabs", "layui-icon-radio", "layui-icon-circle", + "layui-icon-edit", "layui-icon-share", "layui-icon-delete", + "layui-icon-form", "layui-icon-cellphone-fine", "layui-icon-dialogue", + "layui-icon-fonts-clear", "layui-icon-layer", "layui-icon-date", + "layui-icon-water", "layui-icon-code-circle", "layui-icon-carousel", + "layui-icon-prev-circle", "layui-icon-layouts", "layui-icon-util", + "layui-icon-templeate-1", "layui-icon-upload-circle", "layui-icon-tree", + "layui-icon-table", "layui-icon-chart", "layui-icon-chart-screen", + "layui-icon-engine", "layui-icon-triangle-d", "layui-icon-triangle-r", + "layui-icon-file", "layui-icon-set-sm", "layui-icon-add-circle", + "layui-icon-404", "layui-icon-about", "layui-icon-up", + "layui-icon-down", "layui-icon-left", "layui-icon-right", + "layui-icon-circle-dot", "layui-icon-search", "layui-icon-set-fill", + "layui-icon-group", "layui-icon-friends", "layui-icon-reply-fill", + "layui-icon-menu-fill", "layui-icon-log", "layui-icon-picture-fine", + "layui-icon-face-smile-fine", "layui-icon-list", "layui-icon-release", + "layui-icon-ok", "layui-icon-help", "layui-icon-chat", "layui-icon-top", + "layui-icon-star", "layui-icon-star-fill", "layui-icon-close-fill", + "layui-icon-close", "layui-icon-ok-circle", "layui-icon-add-circle-fine" + ]; + return arr; + }, + unicode: function() { + return ["&#xe6c9;", "&#xe67b;", "&#xe67a;", "&#xe678;", + "&#xe679;", "&#xe677;", "&#xe676;", "&#xe675;", + "&#xe673;", "&#xe66f;", "&#xe9aa;", "&#xe672;", + "&#xe66b;", "&#xe668;", "&#xe6b1;", "&#xe702;", + "&#xe66e;", "&#xe68e;", "&#xe674;", "&#xe669;", + "&#xe666;", "&#xe66c;", "&#xe66a;", "&#xe667;", + "&#xe7ae;", "&#xe665;", "&#xe664;", "&#xe716;", + "&#xe656;", "&#xe653;", "&#xe663;", "&#xe6c6;", + "&#xe6c5;", "&#xe662;", "&#xe661;", "&#xe660;", + "&#xe65d;", "&#xe65f;", "&#xe671;", "&#xe65e;", + "&#xe659;", "&#xe735;", "&#xe756;", "&#xe65c;", + "&#xe715;", "&#xe705;", "&#xe6b2;", "&#xe6af;", + "&#xe69c;", "&#xe698;", "&#xe657;", "&#xe65b;", + "&#xe65a;", "&#xe681;", "&#xe67c;", "&#xe601;", + "&#xe857;", "&#xe655;", "&#xe770;", "&#xe670;", + "&#xe63d;", "&#xe63e;", "&#xe654;", "&#xe652;", + "&#xe651;", "&#xe6fc;", "&#xe6ed;", "&#xe688;", + "&#xe645;", "&#xe64f;", "&#xe64e;", "&#xe64b;", + "&#xe62b;", "&#xe64d;", "&#xe64a;", "&#xe64c;", + "&#xe650;", "&#xe649;", "&#xe648;", "&#xe647;", + "&#xe646;", "&#xe644;", "&#xe62a;", "&#xe643;", + "&#xe63f;", "&#xe642;", "&#xe641;", "&#xe640;", + "&#xe63c;", "&#xe63b;", "&#xe63a;", "&#xe639;", + "&#xe638;", "&#xe637;", "&#xe636;", "&#xe635;", + "&#xe634;", "&#xe633;", "&#xe632;", "&#xe631;", + "&#xe630;", "&#xe62f;", "&#xe62e;", "&#xe62d;", + "&#xe62c;", "&#xe629;", "&#xe628;", "&#xe625;", + "&#xe623;", "&#xe621;", "&#xe620;", "&#xe61f;", + "&#xe61c;", "&#xe60b;", "&#xe619;", "&#xe61a;", + "&#xe603;", "&#xe602;", "&#xe617;", "&#xe615;", + "&#xe614;", "&#xe613;", "&#xe612;", "&#xe611;", + "&#xe60f;", "&#xe60e;", "&#xe60d;", "&#xe60c;", + "&#xe60a;", "&#xe609;", "&#xe605;", "&#xe607;", + "&#xe606;", "&#xe604;", "&#xe600;", "&#xe658;", + "&#x1007;", "&#x1006;", "&#x1005;", "&#xe608;" + ]; + } + } + }; + + a.init(); + return new IconPicker(); + }; + + /** + * 选中图标 + * @param filter lay-filter + * @param iconName 图标名称,自动识别fontClass/unicode + */ + IconPicker.prototype.checkIcon = function(filter, iconName) { + var el = $('*[lay-filter=' + filter + ']'), + p = el.next().find('.layui-iconpicker-item .layui-icon'), + c = iconName; + + if (c.indexOf('#xe') > 0) { + p.html(c); + } else { + p.html('').attr('class', 'layui-icon ' + c); + } + el.attr('value', c).val(c); + }; + + var iconPicker = new IconPicker(); + exports(_MOD, iconPicker); +}); diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/notice.js b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/notice.js new file mode 100644 index 0000000000000000000000000000000000000000..4ea67ec8b3e784abd5b28d103042bd3499bdaf2d --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/notice.js @@ -0,0 +1,489 @@ + +(function(define) { + define(['jquery'], function($) { + return (function() { + var $container; + var listener; + var toastId = 0; + var toastType = { + error: 'error', + info: 'info', + success: 'success', + warning: 'warning' + }; + + var cssStyle = $( + '' + ); + $("body").append(cssStyle); + + var toastr = { + clear: clear, + remove: remove, + error: error, + getContainer: getContainer, + info: info, + options: {}, + subscribe: subscribe, + success: success, + version: '2.1.4', + warning: warning + }; + + var previousToast; + + return toastr; + + function error(message, title, optionsOverride) { + return notify({ + type: toastType.error, + iconClass: getOptions().iconClasses.error, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function getContainer(options, create) { + if (!options) { + options = getOptions(); + } + $container = $('#' + options.containerId); + if ($container.length) { + return $container; + } + if (create) { + $container = createContainer(options); + } + return $container; + } + + function info(message, title, optionsOverride) { + return notify({ + type: toastType.info, + iconClass: getOptions().iconClasses.info, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function subscribe(callback) { + listener = callback; + } + + function success(message, title, optionsOverride) { + return notify({ + type: toastType.success, + iconClass: getOptions().iconClasses.success, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function warning(message, title, optionsOverride) { + return notify({ + type: toastType.warning, + iconClass: getOptions().iconClasses.warning, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function clear($toastElement, clearOptions) { + var options = getOptions(); + if (!$container) { + getContainer(options); + } + if (!clearToast($toastElement, options, clearOptions)) { + clearContainer(options); + } + } + + function remove($toastElement) { + var options = getOptions(); + if (!$container) { + getContainer(options); + } + if ($toastElement && $(':focus', $toastElement).length === 0) { + removeToast($toastElement); + return; + } + if ($container.children().length) { + $container.remove(); + } + } + + // internal functions + + function clearContainer(options) { + var toastsToClear = $container.children(); + for (var i = toastsToClear.length - 1; i >= 0; i--) { + clearToast($(toastsToClear[i]), options); + } + } + + function clearToast($toastElement, options, clearOptions) { + var force = clearOptions && clearOptions.force ? clearOptions.force : false; + if ($toastElement && (force || $(':focus', $toastElement).length === 0)) { + $toastElement[options.hideMethod]({ + duration: options.hideDuration, + easing: options.hideEasing, + complete: function() { + removeToast($toastElement); + } + }); + return true; + } + return false; + } + + function createContainer(options) { + $container = $('
                    ') + .attr('id', options.containerId) + .addClass(options.positionClass); + + $container.appendTo($(options.target)); + return $container; + } + + function getDefaults() { + return { + tapToDismiss: true, + toastClass: 'toast', + containerId: 'toast-container', + debug: false, + + showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery + showDuration: 300, + showEasing: 'swing', //swing and linear are built into jQuery + onShown: undefined, + hideMethod: 'fadeOut', + hideDuration: 1000, + hideEasing: 'swing', + onHidden: undefined, + closeMethod: false, + closeDuration: false, + closeEasing: false, + closeOnHover: true, + + extendedTimeOut: 1000, + iconClasses: { + error: 'toast-error', + info: 'toast-info', + success: 'toast-success', + warning: 'toast-warning' + }, + iconClass: 'toast-info', + positionClass: 'toast-top-right', + timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky + titleClass: 'toast-title', + messageClass: 'toast-message', + escapeHtml: false, + target: 'body', + closeHtml: '', + closeClass: 'toast-close-button', + newestOnTop: true, + preventDuplicates: false, + progressBar: false, + progressClass: 'toast-progress', + rtl: false + }; + } + + function publish(args) { + if (!listener) { + return; + } + listener(args); + } + + function notify(map) { + var options = getOptions(); + var iconClass = map.iconClass || options.iconClass; + + if (typeof(map.optionsOverride) !== 'undefined') { + options = $.extend(options, map.optionsOverride); + iconClass = map.optionsOverride.iconClass || iconClass; + } + + if (shouldExit(options, map)) { + return; + } + + toastId++; + + $container = getContainer(options, true); + + var intervalId = null; + var $toastElement = $('
                    '); + var $titleElement = $('
                    '); + var $messageElement = $('
                    '); + var $progressElement = $('
                    '); + var $closeElement = $(options.closeHtml); + var progressBar = { + intervalId: null, + hideEta: null, + maxHideTime: null + }; + var response = { + toastId: toastId, + state: 'visible', + startTime: new Date(), + options: options, + map: map + }; + + personalizeToast(); + + displayToast(); + + handleEvents(); + + publish(response); + + if (options.debug && console) { + console.log(response); + } + + return $toastElement; + + function escapeHtml(source) { + if (source == null) { + source = ''; + } + + return source + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); + } + + function personalizeToast() { + setIcon(); + setTitle(); + setMessage(); + setCloseButton(); + setProgressBar(); + setRTL(); + setSequence(); + setAria(); + } + + function setAria() { + var ariaValue = ''; + switch (map.iconClass) { + case 'toast-success': + case 'toast-info': + ariaValue = 'polite'; + break; + default: + ariaValue = 'assertive'; + } + $toastElement.attr('aria-live', ariaValue); + } + + function handleEvents() { + if (options.closeOnHover) { + $toastElement.hover(stickAround, delayedHideToast); + } + + if (!options.onclick && options.tapToDismiss) { + $toastElement.click(hideToast); + } + + if (options.closeButton && $closeElement) { + $closeElement.click(function(event) { + if (event.stopPropagation) { + event.stopPropagation(); + } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) { + event.cancelBubble = true; + } + + if (options.onCloseClick) { + options.onCloseClick(event); + } + + hideToast(true); + }); + } + + if (options.onclick) { + $toastElement.click(function(event) { + options.onclick(event); + hideToast(); + }); + } + } + + function displayToast() { + $toastElement.hide(); + + $toastElement[options.showMethod]({ + duration: options.showDuration, + easing: options.showEasing, + complete: options.onShown + }); + + if (options.timeOut > 0) { + intervalId = setTimeout(hideToast, options.timeOut); + progressBar.maxHideTime = parseFloat(options.timeOut); + progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; + if (options.progressBar) { + progressBar.intervalId = setInterval(updateProgress, 10); + } + } + } + + function setIcon() { + if (map.iconClass) { + $toastElement.addClass(options.toastClass).addClass(iconClass); + } + } + + function setSequence() { + if (options.newestOnTop) { + $container.prepend($toastElement); + } else { + $container.append($toastElement); + } + } + + function setTitle() { + if (map.title) { + var suffix = map.title; + if (options.escapeHtml) { + suffix = escapeHtml(map.title); + } + $titleElement.append(suffix).addClass(options.titleClass); + $toastElement.append($titleElement); + } + } + + function setMessage() { + if (map.message) { + var suffix = map.message; + if (options.escapeHtml) { + suffix = escapeHtml(map.message); + } + $messageElement.append(suffix).addClass(options.messageClass); + $toastElement.append($messageElement); + } + } + + function setCloseButton() { + if (options.closeButton) { + $closeElement.addClass(options.closeClass).attr('role', 'button'); + $toastElement.prepend($closeElement); + } + } + + function setProgressBar() { + if (options.progressBar) { + $progressElement.addClass(options.progressClass); + $toastElement.prepend($progressElement); + } + } + + function setRTL() { + if (options.rtl) { + $toastElement.addClass('rtl'); + } + } + + function shouldExit(options, map) { + if (options.preventDuplicates) { + if (map.message === previousToast) { + return true; + } else { + previousToast = map.message; + } + } + return false; + } + + function hideToast(override) { + var method = override && options.closeMethod !== false ? options.closeMethod : options.hideMethod; + var duration = override && options.closeDuration !== false ? + options.closeDuration : options.hideDuration; + var easing = override && options.closeEasing !== false ? options.closeEasing : options.hideEasing; + if ($(':focus', $toastElement).length && !override) { + return; + } + clearTimeout(progressBar.intervalId); + return $toastElement[method]({ + duration: duration, + easing: easing, + complete: function() { + removeToast($toastElement); + clearTimeout(intervalId); + if (options.onHidden && response.state !== 'hidden') { + options.onHidden(); + } + response.state = 'hidden'; + response.endTime = new Date(); + publish(response); + } + }); + } + + function delayedHideToast() { + if (options.timeOut > 0 || options.extendedTimeOut > 0) { + intervalId = setTimeout(hideToast, options.extendedTimeOut); + progressBar.maxHideTime = parseFloat(options.extendedTimeOut); + progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; + } + } + + function stickAround() { + clearTimeout(intervalId); + progressBar.hideEta = 0; + $toastElement.stop(true, true)[options.showMethod]({ + duration: options.showDuration, + easing: options.showEasing + }); + } + + function updateProgress() { + var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100; + $progressElement.width(percentage + '%'); + } + } + + function getOptions() { + return $.extend({}, getDefaults(), toastr.options); + } + + function removeToast($toastElement) { + if (!$container) { + $container = getContainer(); + } + if ($toastElement.is(':visible')) { + return; + } + $toastElement.remove(); + $toastElement = null; + if ($container.children().length === 0) { + $container.remove(); + previousToast = undefined; + } + } + + })(); + }); +}(typeof define === 'function' && define.amd ? define : function(deps, factory) { + if (typeof module !== 'undefined' && module.exports) { //Node + module.exports = factory(require('jquery')); + } else if (window.layui && layui.define) { + layui.define('jquery', function(exports) { //layui加载 + exports('toastr', factory(layui.jquery)); + exports('notice', factory(layui.jquery)); + }); + } else { + window.toastr = factory(window.jQuery); + } +})); diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/theme.js b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/theme.js new file mode 100644 index 0000000000000000000000000000000000000000..c7b3abfd96bd6be08afdd278d976151552b2f74a --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/theme.js @@ -0,0 +1,110 @@ +layui.define(["jquery","layer"], function (exports) { + var MOD_NAME = 'theme', + $ = layui.jquery; + + var theme = {}; + theme.autoHead = false; + + theme.changeTheme = function (target, autoHead) { + this.autoHead = autoHead; + var color = localStorage.getItem("theme-color-color"); + var second = localStorage.getItem("theme-color-second"); + this.colorSet(color, second); + if (target.frames.length == 0) return; + for (var i = 0; i < target.frames.length; i++) { + try { + if(target.frames[i].layui == undefined) continue; + target.frames[i].layui.theme.changeTheme(target.frames[i], autoHead); + } + catch (error) { + console.log(error); + } + } + } + + theme.colorSet = function(color, second) { + var style = ''; + style += '.light-theme .pear-nav-tree .layui-this a:hover,.light-theme .pear-nav-tree .layui-this,.light-theme .pear-nav-tree .layui-this a,.pear-nav-tree .layui-this a,.pear-nav-tree .layui-this{background-color: ' +color + '!important;}'; + style += '.pear-admin .layui-logo .title{color:' + color + '!important;}'; + style += '.pear-frame-title .dot,.pear-tab .layui-this .pear-tab-active{background-color: ' + color +'!important;}'; + style += '.bottom-nav li a:hover{background-color:' + color + '!important;}'; + style += '.pear-btn-primary {border: 1px solid ' + color + '!important;}'; + style += '.pear-admin .layui-header .layui-nav .layui-nav-bar{background-color: ' + color + '!important;}' + style += '.ball-loader>span,.signal-loader>span {background-color: ' + color + '!important;}'; + style += '.layui-header .layui-nav-child .layui-this a{background-color:' + color +'!important;color:white!important;}'; + style += '#preloader{background-color:' + color + '!important;}'; + style += '.pearone-color .color-content li.layui-this:after, .pearone-color .color-content li:hover:after {border: ' +color + ' 3px solid!important;}'; + style += '.layui-nav .layui-nav-child dd.layui-this a, .layui-nav-child dd.layui-this{background-color:' + color + ';color:white;}'; + style += '.pear-social-entrance {background-color:' + color + '!important}'; + style += '.pear-admin .pe-collapse {background-color:' + color + '!important}'; + style += '.layui-fixbar li {background-color:' + color + '!important}'; + style += '.pear-btn-primary {background-color:' + color + '!important}'; + style += '.layui-input:focus,.layui-textarea:focus {border-color: ' + color + '!important;box-shadow: 0 0 0 3px ' + second + ' !important;}' + style += '.layui-form-checkbox[lay-skin=primary]:hover span {background-color: initial;}' + style += '.layui-form-checked[lay-skin=primary] i {border-color: ' + color + '!important;background-color: ' + color + ';}' + style += '.layui-form-checked,.layui-form-checked:hover {border-color: ' + color + '!important;}' + style += '.layui-form-checked span,.layui-form-checked:hover span {background-color: ' + color + ';}' + style += '.layui-form-checked i,.layui-form-checked:hover i {color: ' + color + ';}' + style += '.layui-form-onswitch { border-color: ' + color + '; background-color: ' + color + ';}' + style += '.layui-form-radio>i:hover, .layui-form-radioed>i {color: ' + color + ';}' + style += '.layui-laypage .layui-laypage-curr .layui-laypage-em{background-color:'+ color +'!important}' + style += '.layui-tab-brief>.layui-tab-more li.layui-this:after, .layui-tab-brief>.layui-tab-title .layui-this:after{border-bottom: 3px solid '+color+'!important}' + style += '.layui-tab-brief>.layui-tab-title .layui-this{color:'+color+'!important}' + style += '.layui-progress-bar{background-color:'+color+'}'; + style += '.layui-elem-quote{border-left: 5px solid '+ color +'}'; + style += '.layui-timeline-axis{color:' + color + '}'; + style += '.layui-laydate .layui-this, .layui-laydate .layui-this div{background-color:'+color+'!important}';//变更 + style += 'xm-select .xm-label .xm-label-block{background-color:'+color+'!important}';//变更 + style += 'xm-select{border-color:#EEE !important}';//变更 + style += 'xm-select .xm-body .xm-option.selected .xm-option-icon{border-color:'+color+'!important;color:'+color+'!important;}';//变更 + style += 'xm-select .xm-body .xm-option .xm-option-icon{border-color:'+color+'!important;}';//变更 + style += 'xm-select > .xm-body .xm-option.selected.hide-icon{background-color:'+color+'!important;}';//变更 + style += 'xm-select > .xm-body .xm-toolbar .toolbar-tag:hover{color:'+color+'!important;}';//变更 + style += '.layui-layer-dialog .layui-layer-content .layui-icon-ok{color:'+color+'!important;}';//变更 + style += '.layui-layer-dialog .layui-layer-content .layui-icon-ok{color:'+color+'!important;}';//变更 + style += 'a{color:'+color+';opacity:.8}';//变更 + style += 'a:hover{color:'+color+';opacity:1}';//变更 + style += '.pear-this,.pear-text{color:' + color + '!important}'; + style += '.pear-back{background-color:'+ color +'!important}'; + style += '.pear-collapsed-pe{background-color:'+color+'!important}' + style += '.layui-form-select dl dd.layui-this{color:'+color+'!important;}' + style += '.tag-item-normal{background:'+color+'!important}'; + style += '.step-item-head.step-item-head-active{background-color:'+color+'}' + style += '.step-item-head{border: 3px solid '+color+';}' + style += '.step-item-tail i{background-color:'+color+'}' + style += '.step-item-head{color:' + color + '}' + style += 'div[xm-select-skin=normal] .xm-select-title div.xm-select-label>span i {background-color:'+color+'!important}' + style += 'div[xm-select-skin=normal] .xm-select-title div.xm-select-label>span{border: 1px solid '+color+'!important;background-color:'+color+'!important}' + style += 'div[xm-select-skin=normal] dl dd:not(.xm-dis-disabled) i{border-color:'+color+'!important}' + style += 'div[xm-select-skin=normal] dl dd.xm-select-this:not(.xm-dis-disabled) i{color:'+color+'!important}' + style += 'div[xm-select-skin=normal].xm-form-selected .xm-select, div[xm-select-skin=normal].xm-form-selected .xm-select:hover{border-color:'+color+'!important}' + style += '.layui-layer-btn a:first-child{border-color:'+color+';background-color:'+color+'!important}'; + style += '.layui-form-checkbox[lay-skin=primary]:hover i{border-color:'+color+'!important}' + style += '.pear-tab-menu .item:hover{background-color:'+color+'!important}' + style += '.layui-form-danger:focus {border-color:#FF5722 !important}' + style += '.pear-admin .user .layui-this a:hover{color:white!important}' + style += '.pear-admin .user a:hover{color:'+color+'!important}' + style += '.pear-notice .layui-this{color:'+color+'!important}' + style += '.layui-form-radio:hover *, .layui-form-radioed, .layui-form-radioed>i{color:' + color + ' !important}'; + style += '.pear-btn:hover {color: '+color+';background-color: ' + second + ';}' + style += '.pear-btn-primary[plain] {color: '+ color +' !important;background: ' + second + ' !important;}' + style += '.pear-btn-primary[plain]:hover {background-color: ' + color + '!important}' + style += '.light-theme .pear-nav-tree .layui-this a:hover,.light-theme .pear-nav-tree .layui-this,.light-theme .pear-nav-tree .layui-this a {background-color:'+second+'!important;color:'+color+'!important;}' + style += '.light-theme .pear-nav-tree .layui-this{ border-right: 3px solid '+color+'!important}' + style += '.loader:after {background:'+color+'}' + if(this.autoHead === true || this.autoHead === "true"){ + style += '.pear-admin.banner-layout .layui-header .layui-logo,.pear-admin .layui-header{border:none;background-color:' + color + '!important;}.pear-admin.banner-layout .layui-header .layui-logo .title,.pear-admin .layui-header .layui-nav .layui-nav-item>a{color:whitesmoke!important;}'; + style += '.pear-admin.banner-layout .layui-header{ box-shadow: 2px 0 6px rgb(0 21 41 / 35%) }' + style += '.pear-admin .layui-header .layui-layout-control .layui-this *,.pear-admin.banner-layout .layui-header .layui-layout-control .layui-this *{ background-color: rgba(0,0,0,.1)!important;}' + } + style += '.menu-search-list li:hover,.menu-search-list li.this{background-color:'+ color +'}' + var colorPane = $("#pear-admin-color"); + if(colorPane.length>0){ + colorPane.html(style); + }else{ + $("head").append("") + } + } + + exports(MOD_NAME, theme); +}); \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/xm-select.js b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/xm-select.js new file mode 100644 index 0000000000000000000000000000000000000000..bf44849bf313c152fa1791603e016719ff54e83f --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/other/xm-select.js @@ -0,0 +1,8 @@ +/*! + * @Title: xm-select + * @Version: 1.2.4 + * @Description:基于layui的多选解决方案 + * @Site: https://gitee.com/maplemei/xm-select + * @Author: maplemei + * @License:Apache License 2.0 + */!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="./",n(n.s=214)}({1:function(e,t,n){"use strict";function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e){return function(e){if(Array.isArray(e))return a(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return a(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return a(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,o=new Array(t);n1&&void 0!==arguments[1]?arguments[1]:100,n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],o=this,r=!1;return function(){for(var i=arguments.length,a=new Array(i),l=0;l>>0;for(t&&(n=t),o=new Array(a),r=0;r>>0;if("function"!=typeof e)throw new TypeError(e+" is not a function");for(arguments.length>1&&(n=t),o=0;o>>0;if("function"!=typeof e)throw new TypeError;for(var o=[],r=arguments[1],i=0;i>>0,r=arguments[1],i=0;i .xm-tips {\n color: #999999;\n padding: 0 10px;\n position: absolute;\n display: flex;\n height: 100%;\n align-items: center;\n}\nxm-select > .xm-icon {\n display: inline-block;\n overflow: hidden;\n position: absolute;\n width: 0;\n height: 0;\n right: 10px;\n top: 50%;\n margin-top: -3px;\n cursor: pointer;\n border: 6px dashed transparent;\n border-top-color: #C2C2C2;\n border-top-style: solid;\n transition: all 0.3s;\n -webkit-transition: all 0.3s;\n}\nxm-select > .xm-icon-expand {\n margin-top: -9px;\n transform: rotate(180deg);\n}\nxm-select > .xm-label.single-row {\n position: absolute;\n top: 0;\n bottom: 0px;\n left: 0px;\n right: 30px;\n overflow: auto hidden;\n}\nxm-select > .xm-label.single-row .scroll {\n overflow-y: hidden;\n}\nxm-select > .xm-label.single-row .label-content {\n flex-wrap: nowrap;\n white-space: nowrap;\n}\nxm-select > .xm-label.auto-row .label-content {\n flex-wrap: wrap;\n padding-right: 30px !important;\n}\nxm-select > .xm-label.auto-row .xm-label-block > span {\n white-space: unset;\n height: 100%;\n}\nxm-select > .xm-label .scroll .label-content {\n display: flex;\n padding: 3px 10px;\n}\nxm-select > .xm-label .xm-label-block {\n display: flex;\n position: relative;\n padding: 0px 5px;\n margin: 2px 5px 2px 0;\n border-radius: 3px;\n align-items: baseline;\n color: #FFF;\n}\nxm-select > .xm-label .xm-label-block > span {\n display: flex;\n color: #FFF;\n white-space: nowrap;\n}\nxm-select > .xm-label .xm-label-block > i {\n color: #FFF;\n margin-left: 8px;\n font-size: 12px;\n cursor: pointer;\n display: flex;\n}\nxm-select > .xm-label .xm-label-block.disabled {\n background-color: #C2C2C2 !important;\n cursor: no-drop !important;\n}\nxm-select > .xm-label .xm-label-block.disabled > i {\n cursor: no-drop !important;\n}\nxm-select > .xm-body {\n position: absolute;\n left: 0;\n top: 42px;\n padding: 5px 0;\n z-index: 999;\n width: 100%;\n min-width: fit-content;\n border: 1px solid #E6E6E6;\n background-color: #fff;\n border-radius: 2px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);\n animation-name: xm-upbit;\n animation-duration: 0.3s;\n animation-fill-mode: both;\n}\nxm-select > .xm-body .scroll-body {\n overflow-x: hidden;\n overflow-y: auto;\n}\nxm-select > .xm-body .scroll-body::-webkit-scrollbar {\n width: 8px;\n}\nxm-select > .xm-body .scroll-body::-webkit-scrollbar-track {\n -webkit-border-radius: 2em;\n -moz-border-radius: 2em;\n -ms-border-radius: 2em;\n border-radius: 2em;\n background-color: #FFF;\n}\nxm-select > .xm-body .scroll-body::-webkit-scrollbar-thumb {\n -webkit-border-radius: 2em;\n -moz-border-radius: 2em;\n -ms-border-radius: 2em;\n border-radius: 2em;\n background-color: #C2C2C2;\n}\nxm-select > .xm-body.up {\n top: auto;\n bottom: 42px;\n}\nxm-select > .xm-body.relative {\n position: relative;\n display: block !important;\n top: 0;\n box-shadow: none;\n border: none;\n animation-name: none;\n animation-duration: 0;\n min-width: 100%;\n}\nxm-select > .xm-body .xm-group {\n cursor: default;\n}\nxm-select > .xm-body .xm-group-item {\n display: inline-block;\n cursor: pointer;\n padding: 0 10px;\n color: #999;\n font-size: 12px;\n}\nxm-select > .xm-body .xm-option {\n display: flex;\n align-items: center;\n position: relative;\n padding: 0 10px;\n cursor: pointer;\n}\nxm-select > .xm-body .xm-option-icon {\n color: transparent;\n display: flex;\n border: 1px solid #E6E6E6;\n border-radius: 3px;\n justify-content: center;\n align-items: center;\n}\nxm-select > .xm-body .xm-option-icon.xm-custom-icon {\n color: unset;\n border: unset;\n}\nxm-select > .xm-body .xm-option-icon-hidden {\n margin-right: -10px;\n}\nxm-select > .xm-body .xm-option-icon.xm-icon-danx {\n border-radius: 100%;\n}\nxm-select > .xm-body .xm-option-content {\n display: flex;\n position: relative;\n padding-left: 15px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n color: #666;\n width: calc(100% - 20px);\n}\nxm-select > .xm-body .xm-option.hide-icon .xm-option-content {\n padding-left: 0;\n}\nxm-select > .xm-body .xm-option.selected.hide-icon .xm-option-content {\n color: #FFF !important;\n}\nxm-select > .xm-body .xm-option .loader {\n width: 0.8em;\n height: 0.8em;\n margin-right: 6px;\n color: #C2C2C2;\n}\nxm-select > .xm-body .xm-select-empty {\n text-align: center;\n color: #999;\n}\nxm-select > .xm-body .disabled {\n cursor: no-drop;\n}\nxm-select > .xm-body .disabled:hover {\n background-color: #FFF;\n}\nxm-select > .xm-body .disabled .xm-option-icon {\n border-color: #C2C2C2 !important;\n}\nxm-select > .xm-body .disabled .xm-option-content {\n color: #C2C2C2 !important;\n}\nxm-select > .xm-body .disabled.selected > .xm-option-icon {\n color: #C2C2C2 !important;\n}\nxm-select > .xm-body .xm-search {\n background-color: #FFF !important;\n position: relative;\n padding: 0 10px;\n margin-bottom: 5px;\n cursor: pointer;\n}\nxm-select > .xm-body .xm-search > i {\n position: absolute;\n color: #666;\n}\nxm-select > .xm-body .xm-search-input {\n border: none;\n border-bottom: 1px solid #E6E6E6;\n padding-left: 27px;\n cursor: text;\n}\nxm-select > .xm-body .xm-paging {\n padding: 0 10px;\n display: flex;\n margin-top: 5px;\n}\nxm-select > .xm-body .xm-paging > span:first-child {\n border-radius: 2px 0 0 2px;\n}\nxm-select > .xm-body .xm-paging > span:last-child {\n border-radius: 0 2px 2px 0;\n}\nxm-select > .xm-body .xm-paging > span {\n display: flex;\n flex: auto;\n justify-content: center;\n vertical-align: middle;\n margin: 0 -1px 0 0;\n background-color: #fff;\n color: #333;\n font-size: 12px;\n border: 1px solid #e2e2e2;\n flex-wrap: nowrap;\n width: 100%;\n overflow: hidden;\n min-width: 50px;\n}\nxm-select > .xm-body .xm-toolbar {\n padding: 0 10px;\n display: flex;\n margin: -3px 0;\n cursor: default;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag {\n cursor: pointer;\n display: flex;\n margin-right: 20px;\n color: #666;\n align-items: baseline;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag:hover {\n opacity: 0.8;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag:active {\n opacity: 1;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag > i {\n margin-right: 2px;\n font-size: 14px;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag:last-child {\n margin-right: 0;\n}\nxm-select > .xm-body .xm-body-custom {\n line-height: initial;\n cursor: default;\n}\nxm-select > .xm-body .xm-body-custom * {\n box-sizing: initial;\n}\nxm-select > .xm-body .xm-tree {\n position: relative;\n}\nxm-select > .xm-body .xm-tree-icon {\n display: inline-block;\n margin-right: 3px;\n cursor: pointer;\n border: 6px dashed transparent;\n border-left-color: #C2C2C2;\n border-left-style: solid;\n transition: all 0.3s;\n -webkit-transition: all 0.3s;\n z-index: 2;\n visibility: hidden;\n}\nxm-select > .xm-body .xm-tree-icon.expand {\n margin-top: 3px;\n margin-right: 5px;\n margin-left: -2px;\n transform: rotate(90deg);\n}\nxm-select > .xm-body .xm-tree-icon.xm-visible {\n visibility: visible;\n}\nxm-select > .xm-body .xm-tree .left-line {\n position: absolute;\n left: 13px;\n width: 0;\n z-index: 1;\n border-left: 1px dotted #c0c4cc !important;\n}\nxm-select > .xm-body .xm-tree .top-line {\n position: absolute;\n left: 13px;\n height: 0;\n z-index: 1;\n border-top: 1px dotted #c0c4cc !important;\n}\nxm-select > .xm-body .xm-tree .xm-tree-icon + .top-line {\n margin-left: 1px;\n}\nxm-select > .xm-body .scroll-body > .xm-tree > .xm-option > .top-line,\nxm-select > .xm-body .scroll-body > .xm-option > .top-line {\n width: 0 !important;\n}\nxm-select > .xm-body .xm-cascader-box {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n padding: 5px 0;\n border: 1px solid #E6E6E6;\n background-color: #fff;\n border-radius: 2px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);\n margin: -1px;\n}\nxm-select > .xm-body .xm-cascader-box::before {\n content: ' ';\n position: absolute;\n width: 0;\n height: 0;\n border: 6px solid transparent;\n border-right-color: #E6E6E6;\n top: 10px;\n left: -12px;\n}\nxm-select > .xm-body .xm-cascader-box::after {\n content: ' ';\n position: absolute;\n width: 0;\n height: 0;\n border: 6px solid transparent;\n border-right-color: #fff;\n top: 10px;\n left: -11px;\n}\nxm-select > .xm-body .xm-cascader-scroll {\n height: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n}\nxm-select > .xm-body.cascader {\n width: unset;\n min-width: unset;\n}\nxm-select > .xm-body.cascader .xm-option-content {\n padding-left: 8px;\n}\nxm-select > .xm-body.cascader .disabled .xm-right-arrow {\n color: #C2C2C2 !important;\n}\nxm-select > .xm-body.cascader .hide-icon.disabled .xm-right-arrow {\n color: #999 !important;\n}\nxm-select .xm-input {\n cursor: pointer;\n border-radius: 2px;\n border-width: 1px;\n border-style: solid;\n border-color: #E6E6E6;\n display: block;\n width: 100%;\n box-sizing: border-box;\n background-color: #FFF;\n line-height: 1.3;\n padding-left: 10px;\n outline: 0;\n user-select: text;\n -ms-user-select: text;\n -moz-user-select: text;\n -webkit-user-select: text;\n}\nxm-select .dis {\n display: none;\n}\nxm-select .loading {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(255, 255, 255, 0.6);\n display: flex;\n align-items: center;\n justify-content: center;\n}\nxm-select .loader {\n border: 0.2em dotted currentcolor;\n border-radius: 50%;\n -webkit-animation: 1s loader linear infinite;\n animation: 1s loader linear infinite;\n display: inline-block;\n width: 1em;\n height: 1em;\n color: inherit;\n vertical-align: middle;\n pointer-events: none;\n}\nxm-select .xm-select-default {\n position: absolute;\n width: 100%;\n height: 100%;\n border: none;\n visibility: hidden;\n}\nxm-select .xm-select-disabled {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n cursor: no-drop;\n z-index: 2;\n opacity: 0.3;\n background-color: #FFF;\n}\nxm-select .item--divided {\n border-top: 1px solid #ebeef5;\n width: calc(100% - 20px);\n cursor: initial;\n}\nxm-select .xm-right-arrow {\n position: absolute;\n color: #666;\n right: 5px;\n top: -1px;\n font-weight: 700;\n transform: scale(0.6, 1);\n}\nxm-select .xm-right-arrow::after {\n content: '>';\n}\nxm-select[size='large'] {\n min-height: 40px;\n line-height: 40px;\n}\nxm-select[size='large'] .xm-input {\n height: 40px;\n}\nxm-select[size='large'] .xm-label .scroll .label-content {\n line-height: 34px;\n}\nxm-select[size='large'] .xm-label .xm-label-block {\n height: 30px;\n line-height: 30px;\n}\nxm-select[size='large'] .xm-body .xm-option .xm-option-icon {\n height: 20px;\n width: 20px;\n font-size: 20px;\n}\nxm-select[size='large'] .xm-paging > span {\n height: 34px;\n line-height: 34px;\n}\nxm-select[size='large'] .xm-tree .left-line {\n height: 100%;\n bottom: 20px;\n}\nxm-select[size='large'] .xm-tree .left-line-group {\n height: calc(100% - 40px);\n}\nxm-select[size='large'] .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 19px;\n}\nxm-select[size='large'] .item--divided {\n margin: 10px;\n}\nxm-select {\n min-height: 36px;\n line-height: 36px;\n}\nxm-select .xm-input {\n height: 36px;\n}\nxm-select .xm-label .scroll .label-content {\n line-height: 30px;\n}\nxm-select .xm-label .xm-label-block {\n height: 26px;\n line-height: 26px;\n}\nxm-select .xm-body .xm-option .xm-option-icon {\n height: 18px;\n width: 18px;\n font-size: 18px;\n}\nxm-select .xm-paging > span {\n height: 30px;\n line-height: 30px;\n}\nxm-select .xm-tree .left-line {\n height: 100%;\n bottom: 18px;\n}\nxm-select .xm-tree .left-line-group {\n height: calc(100% - 36px);\n}\nxm-select .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 17px;\n}\nxm-select .item--divided {\n margin: 9px;\n}\nxm-select[size='small'] {\n min-height: 32px;\n line-height: 32px;\n}\nxm-select[size='small'] .xm-input {\n height: 32px;\n}\nxm-select[size='small'] .xm-label .scroll .label-content {\n line-height: 26px;\n}\nxm-select[size='small'] .xm-label .xm-label-block {\n height: 22px;\n line-height: 22px;\n}\nxm-select[size='small'] .xm-body .xm-option .xm-option-icon {\n height: 16px;\n width: 16px;\n font-size: 16px;\n}\nxm-select[size='small'] .xm-paging > span {\n height: 26px;\n line-height: 26px;\n}\nxm-select[size='small'] .xm-tree .left-line {\n height: 100%;\n bottom: 16px;\n}\nxm-select[size='small'] .xm-tree .left-line-group {\n height: calc(100% - 32px);\n}\nxm-select[size='small'] .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 15px;\n}\nxm-select[size='small'] .item--divided {\n margin: 8px;\n}\nxm-select[size='mini'] {\n min-height: 28px;\n line-height: 28px;\n}\nxm-select[size='mini'] .xm-input {\n height: 28px;\n}\nxm-select[size='mini'] .xm-label .scroll .label-content {\n line-height: 22px;\n}\nxm-select[size='mini'] .xm-label .xm-label-block {\n height: 18px;\n line-height: 18px;\n}\nxm-select[size='mini'] .xm-body .xm-option .xm-option-icon {\n height: 14px;\n width: 14px;\n font-size: 14px;\n}\nxm-select[size='mini'] .xm-paging > span {\n height: 22px;\n line-height: 22px;\n}\nxm-select[size='mini'] .xm-tree .left-line {\n height: 100%;\n bottom: 14px;\n}\nxm-select[size='mini'] .xm-tree .left-line-group {\n height: calc(100% - 28px);\n}\nxm-select[size='mini'] .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 13px;\n}\nxm-select[size='mini'] .item--divided {\n margin: 7px;\n}\n.layui-form-pane xm-select {\n margin: -1px -1px -1px 0;\n}\n",""]),e.exports=t},221:function(e,t){(function(t){e.exports=t}).call(this,{})},27:function(e,t,n){"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",o=e[3];if(!o)return n;if(t&&"function"==typeof btoa){var r=function(e){var t=btoa(unescape(encodeURIComponent(JSON.stringify(e)))),n="sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(t);return"/*# ".concat(n," */")}(o),i=o.sources.map((function(e){return"/*# sourceURL=".concat(o.sourceRoot||"").concat(e," */")}));return[n].concat(i).concat([r]).join("\n")}return[n].join("\n")}(t,e);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,o){"string"==typeof e&&(e=[[null,e,""]]);var r={};if(o)for(var i=0;i=0&&p.splice(t,1)}function y(e){var t=document.createElement("style");if(void 0===e.attrs.type&&(e.attrs.type="text/css"),void 0===e.attrs.nonce){var o=function(){0;return n.nc}();o&&(e.attrs.nonce=o)}return x(t,e.attrs),m(e,t),t}function x(e,t){Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])}))}function v(e,t){var n,o,r,i;if(t.transform&&e.css){if(!(i="function"==typeof t.transform?t.transform(e.css):t.transform.default(e.css)))return function(){};e.css=i}if(t.singleton){var a=u++;n=c||(c=y(t)),o=w.bind(null,n,a,!1),r=w.bind(null,n,a,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",x(t,e.attrs),m(e,t),t}(t),o=O.bind(null,n,t),r=function(){b(n),n.href&&URL.revokeObjectURL(n.href)}):(n=y(t),o=k.bind(null,n),r=function(){b(n)});return o(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;o(e=t)}else r()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=a()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=h(e,t);return d(n,t),function(e){for(var o=[],r=0;r3)for(n=[n],o=3;o1&&E(r,t,n),t=O(n,r,r,e.__k,null,r.__e,t),"function"==typeof e.type&&(e.__d=t)))}function A(e,t,n,r,i,a,l,s,c){var u,p,f,h,m,b,v,g,_,w,O,C=t.type;if(void 0!==t.constructor)return null;(u=o.__b)&&u(t);try{e:if("function"==typeof C){if(g=t.props,_=(u=C.contextType)&&r[u.__c],w=u?_?_.props.value:u.__:r,n.__c?v=(p=t.__c=n.__c).__=p.__E:("prototype"in C&&C.prototype.render?t.__c=p=new C(g,w):(t.__c=p=new x(g,w),p.constructor=C,p.render=M),_&&_.sub(p),p.props=g,p.state||(p.state={}),p.context=w,p.__n=r,f=p.__d=!0,p.__h=[]),null==p.__s&&(p.__s=p.state),null!=C.getDerivedStateFromProps&&(p.__s==p.state&&(p.__s=d({},p.__s)),d(p.__s,C.getDerivedStateFromProps(g,p.__s))),h=p.props,m=p.state,f)null==C.getDerivedStateFromProps&&null!=p.componentWillMount&&p.componentWillMount(),null!=p.componentDidMount&&p.__h.push(p.componentDidMount);else{if(null==C.getDerivedStateFromProps&&g!==h&&null!=p.componentWillReceiveProps&&p.componentWillReceiveProps(g,w),!p.__e&&null!=p.shouldComponentUpdate&&!1===p.shouldComponentUpdate(g,p.__s,w)||t.__v===n.__v){p.props=g,p.state=p.__s,t.__v!==n.__v&&(p.__d=!1),p.__v=t,t.__e=n.__e,t.__k=n.__k,p.__h.length&&l.push(p),E(t,s,e);break e}null!=p.componentWillUpdate&&p.componentWillUpdate(g,p.__s,w),null!=p.componentDidUpdate&&p.__h.push((function(){p.componentDidUpdate(h,m,b)}))}p.context=w,p.props=g,p.state=p.__s,(u=o.__r)&&u(t),p.__d=!1,p.__v=t,p.__P=e,u=p.render(p.props,p.state,p.context),p.state=p.__s,null!=p.getChildContext&&(r=d(d({},r),p.getChildContext())),f||null==p.getSnapshotBeforeUpdate||(b=p.getSnapshotBeforeUpdate(h,m)),O=null!=u&&u.type==y&&null==u.key?u.props.children:u,k(e,Array.isArray(O)?O:[O],t,n,r,i,a,l,s,c),p.base=t.__e,p.__h.length&&l.push(p),v&&(p.__E=p.__=null),p.__e=!1}else null==a&&t.__v===n.__v?(t.__k=n.__k,t.__e=n.__e):t.__e=P(n.__e,t,n,r,i,a,l,c);(u=o.diffed)&&u(t)}catch(e){t.__v=null,o.__e(e,t,n)}return t.__e}function R(e,t){o.__c&&o.__c(t,e),e.some((function(t){try{e=t.__h,t.__h=[],e.some((function(e){e.call(t)}))}catch(e){o.__e(e,t.__v)}}))}function P(e,t,n,o,r,i,a,l){var s,c,f,d,h,m=n.props,b=t.props;if(r="svg"===t.type||r,null!=i)for(s=0;se.length)&&(t=e.length);for(var n=0,o=new Array(t);nr?n-r:r,a=this.labelRef.scrollLeft+e.deltaY;a<0&&(a=0),a>i&&(a=i),this.labelRef.scrollLeft=a}}},{key:"blur",value:function(){var e=this.base.querySelector(".label-search-input");e&&e.blur()}},{key:"labelDrag",value:function(e,t){for(var n=t.type,o=t.target;;){if(!o||"I"===o.tagName)return;if("DIV"===o.tagName&&"fixed"!==o.style.position)break;o=o.parentNode}if(console.log(t),"mousedown"===n){var r=o.cloneNode(!0),i=t.pageX,a=t.pageY,l=t.offsetX,s=t.offsetY;console.log(i,a,l,s),r.style.position="fixed",r.style.left=i-l+"px",r.style.top=a-s+"px",o.appendChild(r),console.log(r),r.onmousemove=function(e){r.style.left=e.pageX-l+"px",r.style.top=e.pageY-s+"px"},r.mouseup=function(){r.parentNode.removeChild(r),r.onmousemove=null,r.mouseup=null,r.mouseleave=null},r.mouseleave=function(){console.log("mouseleave")}}else if("mouseup"===n)for(var c=o.childNodes,u=0;ue.length)&&(t=e.length);for(var n=0,o=new Array(t);n0&&void 0!==arguments[0]||this.size;var e=this.state.pageIndex;e<=1||(this.changePageIndex(e-1),this.props.pageRemote&&this.postData(e-1,!0))}},{key:"pageNextClick",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.size,t=this.state.pageIndex;t>=e||(this.changePageIndex(t+1),this.props.pageRemote&&this.postData(t+1,!0))}},{key:"changePageIndex",value:function(e){this.setState({pageIndex:e})}},{key:"labelSearch",value:function(e){"input"==e.type?this.searchInput(e):this.handleComposition(e)}},{key:"searchInput",value:function(e){var t=this,n=e.target.value;n!==this.__value&&(this.searchCid&&clearTimeout(this.searchCid),this.inputOver&&(this.__value=n,this.searchCid=setTimeout((function(){t.callback=!0,t.setState({filterValue:t.__value,remote:!0,pageIndex:1})}),this.props.delay)))}},{key:"focus",value:function(){this.searchInputRef&&this.searchInputRef.focus()}},{key:"blur",value:function(){this.searchInputRef&&this.searchInputRef.blur()}},{key:"handleComposition",value:function(e){var t=e.type;"compositionstart"===t?(this.inputOver=!1,this.searchCid&&clearTimeout(this.searchCid)):"compositionend"===t&&(this.inputOver=!0,this.searchInput(e))}},{key:"postData",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.state.pageIndex,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];(this.state.remote||n)&&(this.callback=!1,this.setState({loading:!0,remote:!1}),this.blur(),this.props.remoteMethod(this.state.filterValue,(function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;setTimeout((function(){e.focus(),e.callback=!0,e.setState({loading:!1,totalSize:n}),e.props.onReset(t,"data")}),10)}),this.props.show,t))}},{key:"keydown",value:function(e,t){var n=this,o=t.keyCode;if("div"===e&&(27===o||9===o?this.props.onReset(!1,"close"):37===o?this.pagePrevClick():39===o&&this.pageNextClick()),this.props.enableKeyboard){var r=this.props.prop,i=r.value,a=r.optgroup,l=r.disabled,s=this.tempData.filter((function(e){return!e[a]&&!e[l]})),c=s.length-1;if(-1===c)return;var u=s.findIndex((function(e){return e[i]===n.state.val}));if(38===o){u<=0?u=c:u>0&&(u-=1);var p=s[u][i];this.setState({val:p}),this.viewTo(p)}else if(40===o){-1===u||u===c?u=0:uM&&(T=M),M>0&&T<=0&&(T=1),!x){var z=(T-1)*e.pageSize,L=z+e.pageSize;S=S.slice(z,L)}var V={cursor:"no-drop",color:"#d2d2d2"},F={},U={};T<=1&&(F=V),T==M&&(U=V),this.state.pageIndex!==T&&this.changePageIndex(T),this.size=M,D=m("div",{class:"xm-paging"},m("span",{style:F,onClick:this.pagePrevClick.bind(this,M)},e.languageProp.paging.prev),m("span",null,this.state.pageIndex," / ",M),m("span",{style:U,onClick:this.pageNextClick.bind(this,M)},e.languageProp.paging.next))}else e.showCount>0&&(S=S.slice(0,e.showCount));var N,B,K=[],H={__tmp:!0};H[j]=!0,S.forEach((function(e){var t=I[e.__group__index];delete e.__group__index,N&&!t&&(t=H),t!=N&&(N=t,t&&K.push(N)),K.push(e)})),S=K,t&&null!=(t=y(this.state.filterValue,Object(c.b)([],S)))&&(B=S).splice.apply(B,[0,0].concat(J((Object(c.d)(t)?t:[t]).map((function(e){return Z(Z({},e),{},{__node:{}})})))));var q=Object(c.b)([],S);this.tempData=q;var Y=m("div",{class:"xm-toolbar"},e.toolbar.list.map((function(t){var o,r=e.languageProp.toolbar[t];o="ALL"===t?{icon:"xm-iconfont xm-icon-quanxuan",name:r,method:function(e){var t=i.optgroup,o=i.disabled,r=e.filter((function(e){return!e[t]})).filter((function(e){return!e[o]})),a=u.filter((function(e){return e[i.disabled]})),l=[];l=s?a.length?a:r.slice(0,1):v>0?a.length>=v?a:Object(c.f)(r.slice(0,v-a.length),a,i):Object(c.f)(r,u,i),n.props.onReset(l,"sels")}}:"CLEAR"===t?{icon:"xm-iconfont xm-icon-qingkong",name:r,method:function(e){n.props.onReset(u.filter((function(e){return e[i.disabled]})),"sels")}}:"REVERSE"===t?{icon:"xm-iconfont xm-icon-fanxuan",name:r,method:function(e){var t=i.optgroup,o=i.disabled,r=e.filter((function(e){return!e[t]})).filter((function(e){return!e[o]})),a=[];u.forEach((function(e){var t=r.findIndex((function(t){return t[k]===e[k]}));-1==t?a.push(e):r.splice(t,1)}));var l=a.filter((function(e){return e[i.disabled]})),p=[];p=s?l.length?l:r.slice(0,1):v>0?l.length>=v?l:Object(c.f)(r.slice(0,v-l.length),l,i):Object(c.f)(r,a,i),n.props.onReset(p,"sels")}}:t;var a=function(e){"mouseenter"===e.type&&(e.target.style.color=l.color),"mouseleave"===e.type&&(e.target.style.color="")};return m("div",{class:"toolbar-tag",style:{},onClick:function(){Object(c.e)(o.method)&&o.method(q),n.focus()},onMouseEnter:a,onMouseLeave:a},e.toolbar.showIcon&&m("i",{class:o.icon}),m("span",null,o.name))})).filter((function(e){return e}))),Q="hidden"!=e.model.icon;return(S=S.map((function(t){return t[j]?t.__tmp?m("div",{class:"item--divided"}):m("div",{class:"xm-group"},m("div",{class:"xm-group-item",onClick:n.groupClick.bind(n,t)},t[w])):function(t){var r=!!u.find((function(e){return e[k]==t[k]})),i=r?{color:l.color,border:"none"}:{borderColor:l.color},c={};g&&t[k]===n.state.val&&(c.backgroundColor=l.hover),!Q&&r&&(c.backgroundColor=l.color,t[O]&&(c.backgroundColor="#C2C2C2"));var p,f,d=["xm-option",t[O]?" disabled":"",r?" selected":"",Q?"show-icon":"hide-icon"].join(" "),h=["xm-option-icon",(p=e.iconfont.select,f=e.iconfont.unselect,(p?!r&&f?f+" xm-custom-icon":p:0)||"xm-iconfont "+(s?"xm-icon-danx":"xm-icon-duox"))].join(" "),b=function(e){"mouseenter"===e.type?t[O]||(g?n.setState({val:t[k]}):e.target.style.backgroundColor=l.hover):"mouseleave"===e.type&&(t[O]||g||(e.target.style.backgroundColor=""))};return m("div",{class:d,style:c,value:t[k],onClick:n.optionClick.bind(n,t,r,t[O]),onMouseEnter:b,onMouseLeave:b},Q&&m("i",{class:h,style:i}),m("div",{class:"xm-option-content",dangerouslySetInnerHTML:{__html:a({data:o,item:t,arr:u,name:t[w],value:t[k]})}}))}(t)}))).length?_&&this.state.val==ne&&this.keydown("div",{keyCode:40}):(!e.pageEmptyShow&&(D=""),S.push(m("div",{class:"xm-select-empty"},p))),m("div",{onClick:this.blockClick,tabindex:"1",style:"outline: none;"},m("div",null,e.toolbar.show&&Y,P,m("div",{class:"scroll-body",style:{maxHeight:e.height}},S),e.paging&&D),this.state.loading&&m("div",{class:"loading"},m("span",{class:"loader"})))}},{key:"componentDidMount",value:function(){var e=this.base.querySelector(".xm-search-input");e&&(e.addEventListener("compositionstart",this.handleComposition.bind(this)),e.addEventListener("compositionupdate",this.handleComposition.bind(this)),e.addEventListener("compositionend",this.handleComposition.bind(this)),e.addEventListener("input",this.searchInput.bind(this)),this.searchInputRef=e),this.base.addEventListener("keydown",this.keydown.bind(this,"div"))}},{key:"componentDidUpdate",value:function(){if(this.callback){this.callback=!1;var e=this.props.filterDone;Object(c.e)(e)&&e(this.state.filterValue,this.tempData||[])}}}])&&G(t.prototype,n),o&&G(t,o),i}(x);function re(e){return(re="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function ie(e,t){for(var n=0;n0||p.lazy&&!1!==e.__node.loading)?"xm-visible":"xm-hidden"].join(" "),j=[];p.showFolderIcon&&(j.push(m("i",{class:C,type:"expand"})),p.showLine&&(o&&j.push(m("i",{class:"left-line",style:{left:t-p.indent+3+"px"}})),j.push(m("i",{class:"top-line",style:{left:t-p.indent+3+"px",width:p.indent+(0===o?10:-2)+"px"}}))));var S=function(t){"mouseenter"===t.type?e[g]||(y?n.setState({val:e[v]}):t.target.style.backgroundColor=a.hover):"mouseleave"===t.type&&(e[g]||y||(t.target.style.backgroundColor=""))};return m("div",{class:w,style:h,value:e[v],onClick:n.optionClick.bind(n,e,r,e[g],"line"),onMouseEnter:S,onMouseLeave:S},j,e.__node.loading&&m("span",{class:"loader"}),k&&m("i",{class:O,style:d,onClick:n.optionClick.bind(n,e,r,e[g],"checkbox")}),m("div",{class:"xm-option-content",dangerouslySetInnerHTML:{__html:s({data:u,item:e,arr:i,name:e[x],value:e[v]})}}))};f&&(d?this.postData():this.filterData(u,this.state.filterValue));var C=Object(c.b)([],u),j=Object(c.b)([],i);this.tempData=C;var S=u.map((function(e){return function e(t,o){if(!t.__node.hidn){var r=t[_];if(o+=p.indent,r){var i=-1!==n.state.expandedKeys.findIndex((function(e){return t[v]===e}));return 0===r.length&&(i=!1),m("div",{class:"xm-tree"},p.showFolderIcon&&p.showLine&&i&&r.length>0&&m("i",{class:"left-line left-line-group",style:{left:o+3+"px"}}),O(t,o,0===r.length&&(!p.lazy||p.lazy&&!1===t.__node.loading)?0:i),i&&m("div",{class:"xm-tree-box"},r.map((function(t){return e(t,o)}))))}return O(t,o,0)}}(e,10-p.indent)})).filter((function(e){return e}));function E(e,t){t.forEach((function(t){t[w]?(p.strict||"hidden"===b.parent||e.push(t),E(e,t[_])):e.push(t)}))}var A=m("div",{class:"xm-toolbar"},e.toolbar.list.map((function(t){var r,s=e.languageProp.toolbar[t];r="ALL"===t?{icon:"xm-iconfont xm-icon-quanxuan",name:s,method:function(e){var t=[];E(t,e),t=t.filter((function(e){return!e[g]&&!e.__node.hidn})),n.props.onReset(l?t.slice(0,1):Object(c.f)(t,i,o),"treeData")}}:"CLEAR"===t?{icon:"xm-iconfont xm-icon-qingkong",name:s,method:function(e){n.props.onReset(i.filter((function(e){return e[o.disabled]})),"treeData")}}:"REVERSE"===t?{icon:"xm-iconfont xm-icon-fanxuan",name:s,method:function(e){var t=[];E(t,e),t=t.filter((function(e){return!e[g]&&!e.__node.hidn}));var r=[];i.forEach((function(e){var n=t.findIndex((function(t){return t[v]===e[v]}));-1==n?r.push(e):t.splice(n,1)})),n.props.onReset(l?r.slice(0,1):Object(c.f)(t,r,o),"treeData")}}:t;var u=function(e){"mouseenter"===e.type&&(e.target.style.color=a.color),"mouseleave"===e.type&&(e.target.style.color="")};return m("div",{class:"toolbar-tag",onClick:function(){Object(c.e)(r.method)&&r.method(C,j)},onMouseEnter:u,onMouseLeave:u},e.toolbar.showIcon&&m("i",{class:r.icon}),m("span",null,r.name))})).filter((function(e){return e}))),R=m("div",{class:f?"xm-search":"xm-search dis"},m("i",{class:"xm-iconfont xm-icon-sousuo"}),m("input",{class:"xm-input xm-search-input",placeholder:h}));return S.length||S.push(m("div",{class:"xm-select-empty"},r)),m("div",{onClick:this.blockClick,class:"xm-body-tree"},e.toolbar.show&&A,R,m("div",{class:"scroll-body",style:{maxHeight:e.height}},S),this.state.loading&&m("div",{class:"loading"},m("span",{class:"loader"})))}},{key:"componentDidMount",value:function(){var e=this.base.querySelector(".xm-search-input");e&&(e.addEventListener("compositionstart",this.handleComposition.bind(this)),e.addEventListener("compositionupdate",this.handleComposition.bind(this)),e.addEventListener("compositionend",this.handleComposition.bind(this)),e.addEventListener("input",this.searchInput.bind(this)),this.searchInputRef=e)}},{key:"componentDidUpdate",value:function(){if(this.callback){this.callback=!1;var e=this.props.filterDone;Object(c.e)(e)&&e(this.state.filterValue,this.tempData||[])}}}])&&fe(t.prototype,n),o&&fe(t,o),i}(x);function ve(e){return(ve="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function ge(e,t){for(var n=0;n0,O={backgroundColor:"transparent"},C=["xm-option",g?" disabled":"",v?" selected":"",y?"show-icon":"hide-icon"].join(" "),j=k&&"hidden"===e.iconfont.parent?"xm-option-icon-hidden":["xm-option-icon",(_?e.iconfont.half?e.iconfont.half+" xm-custom-icon":0:k&&e.iconfont.parent?e.iconfont.parent+" xm-custom-icon":v?e.iconfont.select?e.iconfont.select:0:e.iconfont.unselect?e.iconfont.unselect+" xm-custom-icon":0)||"xm-iconfont "+(l?"xm-icon-danx":u.strict&&_?"xm-icon-banxuan":"xm-icon-duox")].join(" ");t[f]===n.state.val&&(O.backgroundColor=a.hover),!y&&v&&(O.backgroundColor=a.color,g&&(O.backgroundColor="#C2C2C2"));var S={},E={};x&&(S.color=a.color,S.fontWeight=700,E.color=a.color);var A=function(e){"mouseenter"===e.type?t[d]||n.setState({val:t[f]}):"mouseleave"===e.type&&n.setState({val:""})};return m("div",{class:C,style:O,value:t[f],onClick:n.optionClick.bind(n,t,v,g,"line",r),onMouseEnter:A,onMouseLeave:A},y&&m("i",{class:j,style:w,onClick:n.optionClick.bind(n,t,v,g,"checkbox",r)}),m("div",{class:"xm-option-content",style:S,dangerouslySetInnerHTML:{__html:s({data:c,item:t,arr:i,name:t[p],value:t[f]})}}),t[b]&&m("div",{class:"xm-right-arrow",style:E}))}(o,0,v,_)},g=c.map((function(e){return v(e,2,0)})).concat(x).filter((function(e){return e}));return g.length||g.push(m("div",{class:"xm-select-empty"},r)),m("div",{onClick:this.blockClick,class:"xm-body-cascader scroll-body",style:{width:u.indent+"px",maxHeight:e.height}},g)}},{key:"componentDidMount",value:function(){this.props.onReset("cascader","class")}}])&&ge(t.prototype,n),o&&ge(t,o),i}(x);function je(){return(je=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,o=new Array(t);n1&&(n=n.slice(0,1),(l.show&&l.strict||s.show&&s.strict)&&this.clearAndReset(o,n,!1)),this.setState({sels:n,dataObj:c,flatData:u})}return this.setState({data:o}),n}},{key:"upDate",value:function(e,t){var n=this.state.dataObj,o=this.props,r=o.prop,i=o.tree,a=o.cascader,l=r.value,s=r.disabled,u=r.children;e.map((function(e){return n["object"===Ie(e)?e[l]:e]})).filter((function(e){return e})).forEach((function(e){if(e[s]=!t,i.show&&i.strict||a.show&&a.strict){if(t)for(var n=e;n;)n[s]=!1,n=n.__node.parent;!function e(n){n[s]=!t;var o=n[u];o&&Object(c.d)(o)&&o.forEach((function(t){return e(t)}))}(e)}})),this.setState({dataObj:n})}},{key:"exchangeValue",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.state.dataObj,o=this.props,r=o.prop,i=o.tree,a=o.cascader,l=(o.data,r.children),s=r.value,u=e.map((function(e){return"object"===Ie(e)?Re(Re({},e),{},{__node:{}}):n[e]})).filter((function(e){return e})),p=Se(u);if(i.show&&i.strict||a.show&&a.strict){var f=function e(t,n){var o=n[l];o&&Object(c.d)(o)&&o.forEach((function(n){-1===u.findIndex((function(e){return e[s]===n[s]}))&&t.push(n),e(t,n)}))},d={};d[l]=u,f(p,d),p=p.filter((function(e){return!0!==e[t.props.prop.optgroup]}))}return p}},{key:"value",value:function(e,t,n,o){var r=!(arguments.length>4&&void 0!==arguments[4])||arguments[4];!1!==t&&!0!==t&&(t=this.state.show);var i=this.props,a=i.prop,l=i.tree,s=i.cascader,c=this.exchangeValue(e);if(!this.checkMax(c,c,!0)){if(l.show&&l.strict||s.show&&s.strict){var u=this.state.data;this.clearAndReset(u,c,!1),c=this.init({data:u,prop:a},!0)}this.resetSelectValue(c,o||c,r,n),this.setState({show:t})}}},{key:"clearAndReset",value:function(e,t,n){var o=this,r=this.props.prop,i=r.selected,a=r.disabled,l=r.children,s=r.value;e.forEach((function(e){e[i]=-1!=t.findIndex((function(t){return t[s]===e[s]}))||n;var r=e[l];if(r&&Object(c.d)(r)&&r.length>0){o.clearAndReset(r,t,e[i]);var u=r.length,p=r.filter((function(e){return!0===e[i]||!0===e.__node.selected})).length;e.__node.selected=p===u,e.__node.half=p>0&&p0,e.__node.disabled=r.filter((function(e){return!0===e[a]||!0===e.__node.disabled})).length===u}}))}},{key:"load",value:function(e,t,n,o){var r=this,i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,a=arguments.length>5?arguments[5]:void 0,l=this.props,s=l.prop,u=l.tree,p=l.cascader,f=s.children,d=s.optgroup,h=s.value,m=s.selected,b=s.disabled;e.forEach((function(e){e.__node={parent:o,level:i,loading:e.__node&&e.__node.loading},a&&(delete e[m],a.find((function(t){return t===e[h]}))&&(e[m]=!0)),t[e[h]]=e,n.push(e);var l=e[f];if(l&&Object(c.d)(l)){var s=l.length;if(s>0){r.load(l,t,n,e,i+1,a),e[d]=!0,(u.show&&u.strict||p.show&&p.strict)&&(!0===e[m]&&(delete e[m],l.forEach((function(e){return e[m]=!0}))),!0===e[b]&&(delete e[b],l.forEach((function(e){return e[b]=!0}))));var y=l.filter((function(e){return!0===e[m]||!0===e.__node.selected})).length;e.__node.selected=y===s,e.__node.half=y>0&&y0,e.__node.disabled=l.filter((function(e){return!0===e[b]||!0===e.__node.disabled})).length===s}}}))}},{key:"resetSelectValue",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2?arguments[2]:void 0,o=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=this.props.on;if(Object(c.e)(r)&&this.prepare&&o){var i=r({arr:e,change:t,isAdd:n});if(Object(c.d)(i))return this.value(i,null,!1)}this.setState({sels:e})}},{key:"updateBorderColor",value:function(e){this.setState({tmpColor:e})}},{key:"treeHandler",value:function(e,t,n,o,r){var i=this,a=this.props.prop,l=a.value,s=(a.selected,a.disabled),c=a.children,u=a.optgroup,p=t[c];if(p.filter((function(e){return!(e[s]||e.__node.disabled)})).forEach((function(t){if(t[u])i.treeHandler(e,t,n,o,r);else{var a=e.findIndex((function(e){return e[l]==t[l]}));"del"===o?-1!=a&&(e.splice(a,1),n.push(t)):"half"!==o&&"add"!==o||-1==a&&(e.push(t),n.push(t))}})),r){var f=p.length,d=p.filter((function(t){return-1!==e.findIndex((function(e){return e[l]===t[l]}))||!0===t.__node.selected})).length;t.__node.selected=d===f,t.__node.half=d>0&&dl;if(l>0&&s)return this.updateBorderColor(a.maxColor),i&&Object(c.e)(i)&&i(t,e),!0}},{key:"itemClick",value:function(e,t,n,o){var r=this.props,i=(r.theme,r.prop),a=r.radio,l=r.repeat,s=r.clickClose,c=(r.max,r.maxMethod,r.tree),u=r.cascader,p=r.data,f=Se(this.state.sels),d=i.value,h=(i.selected,i.disabled,i.children),m=i.optgroup;if(!n){if(e[m]&&(c.show&&c.strict||u.show&&u.strict)){e[h];var b,y=[],x=!0;if(e.__node.selected?(b="del",x=!1):e.__node.half?(b="half",this.treeHandler(f,e,y,b),0===y.length&&(b="del",x=!1)):b="add","half"!=b&&this.treeHandler(f,e,y,b),this.checkMax(y,f))return;f=Se(this.state.sels),y=[],this.treeHandler(f,e,y,b,!0),this.resetSelectValue(f,y,x),this.setState({data:this.state.data})}else if(!t||l&&!o){if(this.checkMax(e,f))return;f=a?[e]:[].concat(Se(f),[e]),this.clearAndReset(p,f,t),this.resetSelectValue(f,[e],!t)}else{var v=f.findIndex((function(t){return t[d]==e[d]}));-1!=v&&(f.splice(v,1),this.resetSelectValue(f,[e],!t))}var g=e.__node.parent;if(g){for(;g;){var _=g[h],w=_.length,k=_.filter((function(e){return-1!==f.findIndex((function(t){return t[d]===e[d]}))||!0===e.__node.selected})).length;g.__node.selected=k===w,g.__node.half=k>0&&k0,g=g.__node.parent}this.setState({data:this.state.data})}s&&!o&&this.onClick()}}},{key:"onClick",value:function(e){var t=this;if("relative"!==this.props.model.type)if(this.props.disabled)!1!==this.state.show&&this.setState({show:!1});else{var n=!this.state.show;if(n){if(this.props.show&&0==this.props.show())return;Object.keys(Xe).filter((function(e){return e!=t.props.el})).forEach((function(e){return Xe[e].closed()}))}else{if(this.props.hide&&0==this.props.hide())return;this.bodyView.scroll&&this.bodyView.scroll(0,0)}this.setState({show:n}),e&&e.stopPropagation()}}},{key:"onReset",value:function(e,t){var n=this;if("data"===t){var o=e.filter((function(e){return!0===e[n.props.prop.selected]}));this.resetSelectValue(Object(c.f)(o,this.state.sels,this.props.prop),o,!0);var r=[];this.load(e,{},r),this.setState({data:e,flatData:r})}else"sels"===t?this.resetSelectValue(e,e,!0):"append"===t?this.append(e):"delete"===t?this.del(e):"auto"===t?this.auto(e):"treeData"===t?this.value(e,null,!0,!1,!1):"close"===t?this.onClick():"class"===t?this.setState({bodyClass:e}):"labelSearchBlur"===t?this.labelRef.blur(e):"labelSearch"===t&&this.generalRef.labelSearch(e)}},{key:"append",value:function(e){var t=this.exchangeValue(e);this.value(Object(c.f)(t,this.state.sels,this.props.prop),this.props.show,!0,t)}},{key:"del",value:function(e){var t=this.props.prop.value,n=this.state.sels,o=this.exchangeValue(e);o.forEach((function(e){var o=n.findIndex((function(n){return n[t]===e[t]}));-1!=o&&n.splice(o,1)})),this.value(n,this.props.show,!0,o,!1)}},{key:"auto",value:function(e){var t=this,n=this.props.prop.value;e.filter((function(e){return-1!=t.state.sels.findIndex((function(t){return t[n]===e[n]}))})).length==e.length?this.del(e):this.append(e)}},{key:"changeExpandedKeys",value:function(e){var t=this.props,n=t.tree,o=t.prop,r=this.state,i=r.dataObj,a=r.flatData;n.show&&this.treeRef.init({dataObj:i,flatData:a,prop:o,tree:{expandedKeys:e}})}},{key:"calcPosition",value:function(){if(this.state.show&&"fixed"===this.props.model.type){var e=this.base.getBoundingClientRect();return Date.now()-this.state.time>10&&this.setState({time:Date.now()}),{position:"fixed",left:e.x,top:e.y+e.height+4,width:e.width}}return{}}},{key:"componentWillReceiveProps",value:function(e){this.init(e,e.updateData)}},{key:"componentWillMount",value:function(){this.init(this.props,!0)}},{key:"render",value:function(e,t){var n=this,o=e.theme,r=e.prop,i=(e.radio,e.repeat,e.clickClose,e.on,e.max,e.maxMethod,e.content),a=e.disabled,l=e.tree,s=e.submitConversion,u={borderColor:o.color},p=t.data,f=t.dataObj,d=t.flatData,h=t.sels,b=t.show,y=t.tmpColor,x=t.bodyClass;a&&(b=!1);var v={style:Re(Re({},e.style),b?u:{}),onClick:this.onClick.bind(this),ua:Object(c.a)(),size:e.size,tabindex:1};y&&(v.style.borderColor=y,setTimeout((function(){v.style.borderColor="",n.updateBorderColor("")}),300)),r.value;var g=Re(Re({},e),{},{data:p,sels:h,ck:this.itemClick.bind(this),title:h.map((function(e){return e[r.name]})).join(","),onReset:this.onReset.bind(this)}),_=Re(Re({},e),{},{data:p,dataObj:f,flatData:d,sels:h,ck:this.itemClick.bind(this),show:b,onReset:this.onReset.bind(this)}),w=i?m(ue,_):l.show?m(xe,je({},_,{ref:function(e){return n.treeRef=e}})):e.cascader.show?m(Ce,_):m(oe,je({},_,{ref:function(e){return n.generalRef=e}})),k=this.calcPosition();return m("xm-select",v,m("input",{class:"xm-select-default","lay-verify":e.layVerify,"lay-verType":e.layVerType,"lay-reqText":e.layReqText,name:e.name,value:s(h,r)}),m("i",{class:b?"xm-icon xm-icon-expand":"xm-icon"}),0===h.length&&m("div",{class:"xm-tips"},e.tips),m(H,je({},g,{ref:function(e){return n.labelRef=e}})),m("div",{class:["xm-body",x,e.model.type,b?"":"dis"].join(" "),style:k,ref:function(e){return n.bodyView=e}},w),a&&m("div",{class:"xm-select-disabled"}))}},{key:"componentDidMount",value:function(){var e=this;this.prepare=!0,this.base.addEventListener("keydown",(function(t){13===t.keyCode&&e.onClick(t)})),this.input=this.base.querySelector(".xm-select-default");var t=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;t&&new t((function(t){t.forEach((function(t){"attributes"==t.type&&"class"===t.attributeName&&-1!==e.input.className.indexOf("layui-form-danger")&&(e.input.className="xm-select-default",e.base.style.borderColor=e.props.theme.maxColor,e.base.scrollIntoView&&e.base.scrollIntoView({behavior:"smooth"}))}))})).observe(this.input,{attributes:!0});for(var n=this.base;n;){if("FORM"===n.tagName){var o=n.querySelector('button[type="reset"]');o&&o.addEventListener("click",(function(t){e.init(e.props,!0)}));break}n=n.parentElement}var r=this.props.done;r&&r()}},{key:"componentDidUpdate",value:function(){var e=this.props,t=e.direction,n=e.model;if("relative"!==n.type&&"fixed"!==n.type){var o=this.base.getBoundingClientRect();if("auto"===t){this.bodyView.style.display="block",this.bodyView.style.visibility="hidden";var r=this.bodyView.getBoundingClientRect().height;this.bodyView.style.display="",this.bodyView.style.visibility="";var i=o.y||o.top||0,a=document.documentElement.clientHeight-i-o.height-20;t=a>r||i0&&void 0!==arguments[0]?arguments[0]:"zn",t=Ne[e]||Ue;return{language:e,languageProp:t,data:[],content:"",name:"select",layVerify:"",layVerType:"",layReqText:"",size:"medium",disabled:!1,initValue:null,create:null,tips:t.tips,empty:t.empty,delay:500,searchTips:t.searchTips,filterable:!1,filterMethod:function(e,t,n,o){return!e||-1!=t[o.name].indexOf(e)},remoteSearch:!1,remoteMethod:function(e,t){t([])},direction:"auto",style:{},height:"200px",autoRow:!1,paging:!1,pageSize:10,pageEmptyShow:!0,pageRemote:!1,radio:!1,repeat:!1,clickClose:!1,max:0,maxMethod:function(e,t){},showCount:0,enableKeyboard:!0,enableHoverFirst:!0,selectedKeyCode:13,toolbar:{show:!1,showIcon:!0,list:["ALL","CLEAR"]},tree:{show:!1,showFolderIcon:!0,showLine:!0,indent:20,expandedKeys:[],strict:!0,lazy:!1,load:null,simple:!1,nodeType:"__node_type",clickExpand:!0,clickCheck:!0},cascader:{show:!1,indent:100,strict:!0},prop:{name:"name",value:"value",selected:"selected",disabled:"disabled",children:"children",optgroup:"optgroup",click:"click"},theme:{color:"#009688",maxColor:"#e54d42",hover:"#f2f2f2"},model:{label:{type:"block",text:{left:"",right:"",separator:", "},block:{showCount:0,showIcon:!0,template:null},count:{template:function(e,t){return"已选中 ".concat(t.length," 项, 共 ").concat(e.length," 项")}}},icon:"show",type:"absolute"},iconfont:{select:"",unselect:"",half:"",parent:""},show:function(){},hide:function(){},template:function(e){e.item,e.sels;var t=e.name;return e.value,t},on:function(e){e.arr,e.item,e.selected},submitConversion:function(e,t){return e.map((function(e){return e[t.value]})).join(",")},done:function(){}}}(e.language),this.update(e)}},{key:"update",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=!!e.data;this.options=Object(c.b)(this.options,e),this.options.__render_success=!1;var n=this.options.dom;if(n){var o=this.options.data||[];if("function"==typeof o&&(o=o(),this.options.data=o),Object(c.d)(o))return T(m(Fe,qe({},this.options,{__update:Date.now(),updateData:t})),n),this.options.__render_success=!0,this;Object(c.k)("data数据必须为数组类型, 不能是".concat("undefined"==typeof data?"undefined":Ye(data),"类型"))}else Object(c.k)("没有找到渲染对象: ".concat(e.el,", 请检查"))}},{key:"reset",value:function(){var e=this.options.el;return this.init($e[e]),et[e].init(this.options,!0),this}},{key:"opened",value:function(){var e=et[this.options.el];return!e.state.show&&e.onClick(),this}},{key:"closed",value:function(){var e=et[this.options.el];return e.state.show&&e.onClick(),this}},{key:"getValue",value:function(e){var t=this,n=this.options,o=n.tree,r=n.prop,i=n.data,a=et[this.options.el].state.sels,l=a;o.show&&o.strict&&o.simple&&(l=[],Object(c.j)(i,a,l,r));var s=Object(c.c)(l,r.children,["__node"]);return"name"===e?s.map((function(e){return e[t.options.prop.name]})):"nameStr"===e?s.map((function(e){return e[t.options.prop.name]})).join(","):"value"===e?s.map((function(e){return e[t.options.prop.value]})):"valueStr"===e?s.map((function(e){return e[t.options.prop.value]})).join(","):s}},{key:"setValue",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(Object(c.d)(e))return et[this.options.el].value(this.options.radio?e.slice(0,1):e,t,n),this;Object(c.k)("请传入数组结构...")}},{key:"append",value:function(e){if(Object(c.d)(e))return et[this.options.el].append(e),this;Object(c.k)("请传入数组结构...")}},{key:"delete",value:function(e){if(Object(c.d)(e))return et[this.options.el].del(e),this;Object(c.k)("请传入数组结构...")}},{key:"warning",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=e||this.options.theme.maxColor;return!0===t?et[this.options.el].base.style.borderColor=n:et[this.options.el].updateBorderColor(n),this}},{key:"getTreeValue",value:function(e,t){var n=this.options,o=n.tree,r=n.cascader,i=n.prop,a=i.value;if(!o.show&&!r.show)return this.getValue(e);for(var l=et[this.options.el].state.sels,s=[],u=o.nodeType,p=function(e,t){s.find((function(t){return t[a]===e[a]}))||((e=Ke({},e))[u]=t,s.push(e))},f=0;fe.length)&&(t=e.length);for(var n=0,o=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"pid",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"id",o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"children",r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,i={};return safety(e).filter((function(e){var a=e[n],l=e[t],s=i[a],c=i[l];return s&&(e[o]=s[o]),i[a]=e,c||(c=Je({},o,[]),i[l]=c),c.push(e),n==r}))}}}}); \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/page.js b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/page.js new file mode 100644 index 0000000000000000000000000000000000000000..52ff2ef0313154b15ca5e25414513a5d86bb20f6 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/page.js @@ -0,0 +1,119 @@ +layui.define(['jquery', 'element'], function (exports) { + "use strict"; + + var $ = layui.jquery; + var element = layui.element; + + var page = function (opt) { + this.option = opt; + }; + + /** + * @since Pear Admin 4.0 + * + * 创建 Page 页面 + */ + page.prototype.render = function (opt) { + var option = { + elem: opt.elem, + url: opt.url, + width: opt.width || "100%", + height: opt.height || "100%", + title: opt.title + } + renderContent(option); + return new page(option); + } + + /** + * @since Pear Admin 4.0 + * + * 切换 Page 页面 + */ + page.prototype.changePage = function (options) { + const $frame = $(`#${this.option.elem} .pear-page-content`); + if (options.type === "_iframe") { + $frame.html(``); + } else { + $.ajax({ + url: options.href, + type: 'get', + dataType: 'html', + success: function (data) { + $frame.html(data) + }, + error: function (xhr) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + $frame.attr("type", options.type); + $frame.attr("href", options.href); + } + + page.prototype.refresh = function (loading) { + var $frameLoad = $(`#${this.option.elem} .pear-page-loading`); + var $frame = $(`#${this.option.elem} .pear-page-content`); + if (loading) { + $frameLoad.css({ + display: 'block' + }); + } + if ($frame.attr("type") === "_iframe") { + $frame.html(``); + const $contentFrame = $frame.find("iframe"); + $contentFrame.on("load", () => { + $frameLoad.fadeOut(1000); + }) + } else { + $.ajax({ + type: 'get', + url: $frame.attr("href"), + dataType: 'html', + success: function (data) { + $frame.html(data) + $frameLoad.fadeOut(1000); + element.init(); + }, + error: function (xhr) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + } + + function renderContent(option) { + $("#" + option.elem).html(` +
                    +
                    +
                    +
                    + + + + +
                    +
                    +
                    `); + + var $frame = $("#" + option.elem).find(".pear-page-content"); + + if (option.type === "_iframe") { + $frame.html(``); + } else { + $.ajax({ + url: option.url, + type: 'get', + dataType: 'html', + success: function (data) { + $frame.html(data); + }, + error: function (xhr) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + } + + exports('page', new page()); +}); \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/tabPage.js b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/tabPage.js new file mode 100644 index 0000000000000000000000000000000000000000..44cb83c04e9d15a5de4a3e0a2796994dd00c1322 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/tabPage.js @@ -0,0 +1,649 @@ +layui.define(['jquery', 'element', 'dropdown'], function (exports) { + "use strict"; + + var MOD_NAME = 'tabPage', + $ = layui.jquery, + dropdown = layui.dropdown, + element = layui.element; + + var tabPage = function (opt) { + this.option = opt; + }; + + var tabData = new Array(); + var tabDataCurrent = 0; + var contextTabDOM; + + tabPage.prototype.render = function (opt) { + + var option = { + elem: opt.elem, + data: opt.data, + index: opt.index, + tool: opt.tool || true, + roll: opt.roll || true, + success: opt.success ? opt.success : function (id) { }, + session: opt.session ? opt.session : false, + preload: opt.preload ? opt.preload : false, + height: opt.height || "100%", + width: opt.width || "100%", + closeEvent: opt.closeEvent, + tabMax: opt.tabMax, + } + + if (option.session) { + if (sessionStorage.getItem(option.elem + "-pear-tab-page-data") != null) { + tabData = JSON.parse(sessionStorage.getItem(option.elem + "-pear-tab-page-data")); + option.data = JSON.parse(sessionStorage.getItem(option.elem + "-pear-tab-page-data")); + tabDataCurrent = sessionStorage.getItem(option.elem + "-pear-tab-page-data-current"); + tabData.forEach(function (item, index) { + if (item.id == tabDataCurrent) { + option.index = index; + } + }) + } else { + tabData = opt.data; + } + } + + var lastIndex; + var tab = createTab(option); + $("#" + option.elem).html(tab); + $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-prev").click(function () { + rollPage("left", option); + }) + $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-next").click(function () { + rollPage("right", option); + }) + element.init(); + + $("#" + option.elem).width(opt.width); + $("#" + option.elem).height(opt.height); + $("#" + option.elem).css({ + position: "relative" + }); + + closeEvent(option); + + option.success(sessionStorage.getItem(option.elem + "-pear-tab-page-data-current")); + + dropdown.render({ + elem: `#${option.elem} .layui-tab-control > .layui-icon-down`, + trigger: 'hover', + data: [{ + title: '关 闭 当 前', + id: 1 + }, { + title: '关 闭 其 他', + id: 2 + }, { + title: '关 闭 全 部', + id: 3 + }], + click: function (obj) { + + const id = obj.id; + + if (id === 1) { + var currentTab = $(".layui-tab[lay-filter='" + option.elem + + "'] .layui-tab-title .layui-this"); + if (currentTab.find("span").is(".able-close")) { + var currentId = currentTab.attr("lay-id"); + tabDelete(option.elem, currentId, option.closeEvent, option); + } else { + layer.msg("当前页面不允许关闭", { + icon: 3, + time: 1000 + }) + } + } else if (id === 2) { + var currentId = $(".layui-tab[lay-filter='" + option.elem + + "'] .layui-tab-title .layui-this").attr("lay-id"); + var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li"); + $.each(tabtitle, function (i) { + if ($(this).attr("lay-id") != currentId) { + if ($(this).find("span").is(".able-close")) { + tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, + option); + } + } + }) + } else { + var currentId = $(".layui-tab[lay-filter='" + option.elem + + "'] .layui-tab-title .layui-this").attr("lay-id"); + var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li"); + $.each(tabtitle, function (i) { + if ($(this).find("span").is(".able-close")) { + tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, option); + } + }) + } + + } + }) + + $("body .layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title").on("contextmenu", "li", + function (e) { + var top = e.clientY; + var left = e.clientX; + var menuWidth = 100; + var menu = `
                      +
                    • 关闭当前
                    • +
                    • 关闭其他
                    • +
                    • 关闭所有
                    • +
                    `; + + contextTabDOM = $(this); + var isOutsideBounds = (left + menuWidth) > $(window).width(); + if (isOutsideBounds) { + left = $(window).width() - menuWidth; + } + + layer.open({ + type: 1, + title: false, + shade: false, + skin: 'pear-tab-page-menu', + closeBtn: false, + area: [menuWidth + 'px', '108px'], + fixed: true, + anim: false, + isOutAnim: false, + offset: [top, left], + content: menu, + success: function (layero, index) { + layer.close(lastIndex); + lastIndex = index; + menuEvent(option, index); + var timer; + $(layero).on('mouseout', function () { + timer = setTimeout(function () { + layer.close(index); + }, 30) + }); + + $(layero).on('mouseover', function () { + clearTimeout(timer); + }); + + $(layero).on('contextmenu', function () { + return false; + }) + } + }); + return false; + }) + + mousewheelAndTouchmoveHandler(option) + return new tabPage(option); + } + + tabPage.prototype.click = function (callback) { + var option = this.option; + var elem = this.option.elem; + element.on('tab(' + this.option.elem + ')', function (data) { + var id = $("#" + elem + " .layui-tab-title .layui-this").attr("lay-id"); + sessionStorage.setItem(option.elem + "-pear-tab-page-data-current", id); + callback(id); + }); + } + + tabPage.prototype.positionTab = function () { + var $tabTitle = $('.layui-tab[lay-filter=' + this.option.elem + '] .layui-tab-title'); + var autoLeft = 0; + $tabTitle.children("li").each(function () { + if ($(this).hasClass('layui-this')) { + return false; + } else { + autoLeft += $(this).outerWidth(); + } + }); + $tabTitle.animate({ + scrollLeft: autoLeft - $tabTitle.width() / 3 + }, 200); + } + + tabPage.prototype.clear = function () { + sessionStorage.removeItem(this.option.elem + "-pear-tab-page-data"); + sessionStorage.removeItem(this.option.elem + "-pear-tab-page-data-current"); + } + + tabPage.prototype.changeTabTitleById = function (id, title) { + var currentTab = $(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title [lay-id='" + id + "'] .title"); + currentTab.html(title); + } + + /** + * @since Pear Admin 4.0 + * + * 删除指定选项卡 + * + * @param id 编号 + */ + tabPage.prototype.removeTab = function (id) { + var elem = this.option.elem; + if (id != undefined) { + var currentTab = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title [lay-id='" + id + "']"); + if (currentTab.find("span").is(".able-close")) { + tabDelete(elem, id, () => { }); + } + } else { + var tabtitle = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title li"); + $.each(tabtitle, function () { + if ($(this).find("span").is(".able-close")) { + tabDelete(elem, $(this).attr("lay-id"), () => { }); + } + }) + } + } + + /** + * @since Pear Admin 4.0 + * + * 删除其他选项卡 + */ + tabPage.prototype.removeOtherTab = function () { + var elem = this.option.elem; + var currentId = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title .layui-this").attr("lay-id"); + var tabtitle = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title li"); + $.each(tabtitle, function () { + if ($(this).attr("lay-id") != currentId) { + if ($(this).find("span").is(".able-close")) { + tabDelete(elem, $(this).attr("lay-id"), () => { }); + } + } + }) + } + + /** + * @since Pear Admin 4.0 + * + * 删除选中选项卡 + */ + tabPage.prototype.removeCurrentTab = function () { + var currentTab = $(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title .layui-this"); + if (currentTab.find("span").is(".able-close")) { + var currentId = currentTab.attr("lay-id"); + tabDelete(this.option.elem, currentId, () => { }); + } + } + + /** + * @since Pear Admin 4.0 + * + * 切换选项卡 + * + * @param opt 内容 + */ + tabPage.prototype.changePage = function (opt) { + + var title = ` + ${opt.title} + ဆ`; + + if ($(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title li[lay-id]").length <= + 0) { + + var that = this; + + if (opt.type === "_iframe") { + + element.tabAdd(this.option.elem, { + id: opt.id, + title: title, + content: `` + }); + + } else { + + $.ajax({ + url: opt.url, + type: 'get', + dataType: 'html', + async: false, + success: function (data) { + element.tabAdd(that.option.elem, { + id: opt.id, + title: title, + content: `
                    ${data}
                    `, + }); + }, + error: function (xhr, textstatus, thrown) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + + tabData.push(opt); + sessionStorage.setItem(that.option.elem + "-pear-tab-page-data", JSON.stringify(tabData)); + sessionStorage.setItem(that.option.elem + "-pear-tab-page-data-current", opt.id); + + } else { + + var isData = false; + $.each($(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title li[lay-id]"), + function () { + if ($(this).attr("lay-id") == opt.id) { + isData = true; + } + }) + + if (isData == false) { + + if (this.option.tabMax != false) { + if ($(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title li[lay-id]") + .length >= this.option.tabMax) { + layer.msg("最多打开" + this.option.tabMax + "个标签页", { + icon: 2, + time: 1000, + shift: 6 + }); + return false; + } + } + + var that = this; + if (opt.type === "_iframe") { + element.tabAdd(this.option.elem, { + id: opt.id, + title: title, + content: `` + }); + } else { + $.ajax({ + url: opt.url, + type: 'get', + dataType: 'html', + async: false, + success: function (data) { + element.tabAdd(that.option.elem, { + id: opt.id, + title: title, + content: `
                    ${data}
                    `, + }); + }, + error: function (xhr, textstatus, thrown) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + tabData.push(opt); + sessionStorage.setItem(that.option.elem + "-pear-tab-page-data", JSON.stringify(tabData)); + sessionStorage.setItem(that.option.elem + "-pear-tab-page-data-current", opt.id); + } + } + element.tabChange(this.option.elem, opt.id); + sessionStorage.setItem(this.option.elem + "-pear-tab-page-data-current", opt.id); + } + + /** + * 刷新当前选型卡 + * + * @param time 动画时长 + */ + tabPage.prototype.refresh = function (time) { + + var $iframe = $(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-content .layui-show > *"); + var $iframeLoad; + + if (time != false && time != 0) { + $iframeLoad = $("#" + this.option.elem).find(".pear-tab-page-loading"); + $iframeLoad.css({ + display: "block" + }); + } + + if ($iframe.attr("type") === "_iframe") { + $iframe.attr("src", $iframe.attr("src")); + $iframe.on("load", function () { + $iframeLoad.fadeOut(1000, function () { + $iframeLoad.css({ + display: "none" + }); + }); + }) + } else { + $.ajax({ + url: $iframe.attr("src"), + type: 'get', + dataType: 'html', + success: function (data) { + $iframe.html(data); + if ($iframeLoad != undefined) { + $iframeLoad.fadeOut(1000, function () { + $iframeLoad.css({ + display: "none" + }); + }); + } + }, + error: function (xhr) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + } + + function tabDelete(elem, id, callback) { + var tabTitle = $(".layui-tab[lay-filter='" + elem + "']").find(".layui-tab-title"); + var removeTab = tabTitle.find("li[lay-id='" + id + "']"); + var nextNode = removeTab.next("li"); + if (!removeTab.hasClass("layui-this")) { + removeTab.remove(); + var tabContent = $(".layui-tab[lay-filter='" + elem + "']").find("*[id='" + id + "']") + .parent(); + tabContent.remove(); + + tabData = JSON.parse(sessionStorage.getItem(elem + "-pear-tab-page-data")); + tabDataCurrent = sessionStorage.getItem(elem + "-pear-tab-page-data-current"); + tabData = tabData.filter(function (item) { + return item.id != id; + }) + sessionStorage.setItem(elem + "-pear-tab-page-data", JSON.stringify(tabData)); + return false; + } + + var currId; + if (nextNode.length) { + nextNode.addClass("layui-this"); + currId = nextNode.attr("lay-id"); + $("#" + elem + " [id='" + currId + "']").parent().addClass("layui-show"); + } else { + var prevNode = removeTab.prev("li"); + prevNode.addClass("layui-this"); + currId = prevNode.attr("lay-id"); + $("#" + elem + " [id='" + currId + "']").parent().addClass("layui-show"); + } + callback(currId); + tabData = JSON.parse(sessionStorage.getItem(elem + "-pear-tab-page-data")); + tabDataCurrent = sessionStorage.getItem(elem + "-pear-tab-page-data-current"); + tabData = tabData.filter(function (item) { + return item.id != id; + }) + sessionStorage.setItem(elem + "-pear-tab-page-data", JSON.stringify(tabData)); + sessionStorage.setItem(elem + "-pear-tab-page-data-current", currId); + removeTab.remove(); + var tabContent = $(".layui-tab[lay-filter='" + elem + "']").find("*[id='" + id + "']").parent(); + tabContent.remove(); + } + + /** + * @since Pear Admin 4.0 + */ + function createTab(option) { + + var type = ""; + if (option.roll == true) { + type = "layui-tab-roll"; + } + if (option.tool != false) { + type = "layui-tab-tool"; + } + if (option.roll == true && option.tool != false) { + type = "layui-tab-rollTool"; + } + var tab = '
                    '; + + var headers = '
                      '; + var content = '
                      '; + var loading = '
                      ' + var control = `
                      +
                    • +
                    • +
                    • +
                      `; + + // 处 理 选 项 卡 头 部 + var index = 0; + + $.each(option.data, function (i, item) { + + var titleItem = `
                    • + + + ${item.title} + + ဆ
                    • + `; + + headers += titleItem; + + if (item.type === "_iframe") { + + content += `
                      ` + + } else { + + $.ajax({ + url: item.url, + type: 'get', + dataType: 'html', + async: false, + success: function (data) { + content += `
                      ${data}
                      `; + }, + error: function (xhr) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + + index++; + }); + + headers += '
                    '; + content += '
                    '; + + tab += headers; + tab += control; + tab += content; + tab += loading; + tab += '
                    '; + tab += '' + return tab; + } + + function rollPage(d, option) { + var $tabTitle = $('#' + option.elem + ' .layui-tab-title'); + var left = $tabTitle.scrollLeft(); + if ('left' === d) { + $tabTitle.animate({ + scrollLeft: left - 450 + }, 200); + } else { + $tabTitle.animate({ + scrollLeft: left + 450 + }, 200); + } + } + + function closeEvent(option) { + $(".layui-tab[lay-filter='" + option.elem + "']").on("click", ".layui-tab-close", function () { + var layid = $(this).parent().attr("lay-id"); + tabDelete(option.elem, layid, option.closeEvent, option); + }) + } + + function menuEvent(option, index) { + + $("#" + option.elem + "closeThis").click(function () { + var currentTab = contextTabDOM; + + if (currentTab.find("span").is(".able-close")) { + var currentId = currentTab.attr("lay-id"); + tabDelete(option.elem, currentId, option.closeEvent, option); + } else { + layer.msg("当前页面不允许关闭", { + icon: 3, + time: 800 + }) + } + layer.close(index); + }) + + $("#" + option.elem + "closeOther").click(function () { + var currentId = contextTabDOM.attr("lay-id"); + var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li"); + $.each(tabtitle, function (i) { + if ($(this).attr("lay-id") != currentId) { + if ($(this).find("span").is(".able-close")) { + tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, + option); + } + } + }) + layer.close(index); + }) + + $("#" + option.elem + "closeAll").click(function () { + var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li"); + $.each(tabtitle, function (i) { + if ($(this).find("span").is(".able-close")) { + tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, option); + } + }) + layer.close(index); + }) + } + + function mousewheelAndTouchmoveHandler(option) { + var $bodyTab = $("body .layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title") + var $tabTitle = $('#' + option.elem + ' .layui-tab-title'); + var mouseScrollStep = 100 + // 鼠标滚轮 + $bodyTab.on("mousewheel DOMMouseScroll", function (e) { + e.originalEvent.preventDefault() + var delta = (e.originalEvent.wheelDelta && (e.originalEvent.wheelDelta > 0 ? "top" : + "down")) || // chrome & ie + (e.originalEvent.detail && (e.originalEvent.detail > 0 ? "down" : "top")); // firefox + var scrollLeft = $tabTitle.scrollLeft(); + + if (delta === "top") { + scrollLeft -= mouseScrollStep + } else if (delta === "down") { + scrollLeft += mouseScrollStep + } + $tabTitle.scrollLeft(scrollLeft) + }); + + // 触摸移动 + var touchX = 0; + $bodyTab.on("touchstart", function (e) { + var touch = e.originalEvent.targetTouches[0]; + touchX = touch.pageX + }) + $bodyTab.on("touchmove", function (e) { + var event = e.originalEvent; + if (event.targetTouches.length > 1) return; + event.preventDefault(); + var touch = event.targetTouches[0]; + var distanceX = touchX - touch.pageX + var scrollLeft = $tabTitle.scrollLeft(); + touchX = touch.pageX + $tabTitle.scrollLeft(scrollLeft += distanceX) + }); + } + + exports(MOD_NAME, new tabPage()); +}) diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/tools.js b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/tools.js new file mode 100644 index 0000000000000000000000000000000000000000..373ac01ed05ba05a01cefb3bd848a84d0a2ec70f --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/module/tools.js @@ -0,0 +1,40 @@ +layui.define(['jquery', 'element'], + function (exports) { + + var $ = layui.jquery; + var tools = new function () { + + /** + * @since 防抖算法 + * + * @param fn 要执行的方法 + * @param time 防抖时间参数 + */ + this.debounce = function (fn, time) { + var timer = null + return function () { + var arguments = arguments[0] + if (timer) { + clearTimeout(timer) + } + timer = setTimeout(function () { + fn(arguments) + }, time) + } + } + + // image 转 base64 + this.imageToBase64 = function (img) { + var canvas = document.createElement("canvas"); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext("2d"); + ctx.drawImage(img, 0, 0, img.width, img.height); + var ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase(); + var dataURL = canvas.toDataURL("image/" + ext); + return dataURL; + } + }; + + exports('tools', tools); + }) diff --git a/demo/thinkphp/frontend/layui_admin_flow/component/pear/pear.js b/demo/thinkphp/frontend/layui_admin_flow/component/pear/pear.js new file mode 100644 index 0000000000000000000000000000000000000000..7acd256a39fc8ca36aa21a19ad520d6e8e5a8979 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/component/pear/pear.js @@ -0,0 +1,37 @@ +window.rootPath = (function (src) { + src = document.currentScript + ? document.currentScript.src + : document.scripts[document.scripts.length - 1].src; + return src.substring(0, src.lastIndexOf("/") + 1); +})(); + +layui.config({ + base: rootPath + "module/", + version: "4.0.3" +}).extend({ + admin: "admin", + page: "page", + tabPage: "tabPage", + menu: "menu", + fullscreen: "fullscreen", + messageCenter: "messageCenter", + menuSearch: "menuSearch", + button: "button", + tools: "tools", + popup: "extends/popup", + count: "extends/count", + toast: "extends/toast", + nprogress: "extends/nprogress", + echarts: "extends/echarts", + echartsTheme: "extends/echartsTheme", + yaml: "extends/yaml", + encrypt:"extends/encrypt", + theme: "other/theme",//主题 + common: "other/common", + dtree: "other/dtree/dtree",// 树结构 + xmSelect: "other/xm-select", // 下拉多选组件 + iconPicker: "other/iconPicker", + notice: "other/notice", // 消息提示组件 + design: "other/design", // 表单设计 + +}).use([], function () { }); \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/config/common.js b/demo/thinkphp/frontend/layui_admin_flow/config/common.js new file mode 100644 index 0000000000000000000000000000000000000000..c5be556ec7f8183ccab0ffd79b793ee1d48849be --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/config/common.js @@ -0,0 +1,307 @@ +function isString(str) { + if (typeof (str) === 'string') return true; + return false; +} + +/** + * 修正中文乱码问题 + * @param name + * @returns {null|string} + */ +function getQueryString(name) { + let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); + let r = window.location.search.substr(1).match(reg); + if (r != null) return decodeURIComponent(r[2]); + return null; +} + +/** + * 数组in + * @param search + * @param array + * @returns {boolean} + */ +function in_array(search, array) { + for (let i in array) { + if (array[i] == search) { + return true; + } + } + return false; +} + + +/** + * 鹰:OK + */ +//保存、获取 用户信息 +const setUserInfo = (userinfo) => { + //localStorage 持久化存储:layui.data(table, settings),数据会永久存在,除非物理删除。 + //sessionStorage 会话性存储:layui.sessionData(table, settings),页面关闭后即失效。注:layui 2.2.5 新增 + if (userinfo === undefined || userinfo === null) layui.data('lms', { + key: 'userInfo', remove: true + }); else layui.data('lms', { + key: 'userInfo', value: userinfo + }); +} +const getUserInfo = () => { + return layui.data('lms').userInfo; +} + +/** + * 检查登录,没有登录返回false,否则返回 用户信息对象 + * 鹰:OK + * options.nav:为true则没有登录时跳转至登录界面。 + * @return {Boolean} + */ +const checkLogin = (options = {}) => { + const userInfo = getUserInfo(); + if (typeof (userInfo) === 'object' && userInfo !== null) { + return userInfo; + } + + //是否需要自动跳转到login页面 + if (options.nav === true) { + options.nav = './login.html'; + } + if (isString(options.nav)) { + location.href = options.nav; + } + return false; +} + + +//制作菜单 +//rules为服务器返回的所有权限数组(平行) +//type为1则只返回 菜单类型 的菜单,否则也返回 菜单和API 的菜单 +//setKeysById:给特定id新增一个key并赋值value。如果为null则忽略 +// 格式:[ids, key, value] //ids是列表,Permission的id只要在这个列表内就赋值 +const fMakeMenu = function (rules, type = 1, setKeysById = null) { + let retMenu = []; // 返回值(也是顶层menu) + let tmpMenu = new Map(); // 按id为key的menu + rules.forEach((r) => { + if (type === 1 && r.auth_type !== 1) { + // api + return; + } + if (r.is_show !== 1) { + // 是否显示 + return; + } + + // 制作菜单: + let menu = tmpMenu.get(r.id) || {type: 1}; + menu.id = r.id; + menu.title = r.menu_name; + menu.icon = 'layui-icon ' + r.icon; + menu.openType = "_iframe"; + menu.href = r.menu_path; + + // 加入额外的keys + if (setKeysById) { + // 如果这个id在给定的Id列表内 + if (setKeysById[0].includes(r.id.toString())) { + menu[setKeysById[1]] = setKeysById[2]; // 给特定key赋值 + } + } + + if (r.pid === '-1') { + // 顶层 + retMenu.push(menu); + } else { + let parentMenu = tmpMenu.get(r.pid) || {children: []}; // 父菜单 + parentMenu.type = 0; // 菜单 + parentMenu.children = parentMenu.children || []; + parentMenu.children.push(menu); // 加入父菜单 children + tmpMenu.set(r.pid, parentMenu); + } + + tmpMenu.set(r.id, menu); + }); + + return retMenu; +}; + + +const fGetLastNodes = function (rules) { + + let parentNodes = []; + let lastNodes = []; + let allNodes = []; + + + for (let r of rules) { + allNodes.push(r.id); + if (parentNodes.indexOf(r.pid) < 0) parentNodes.push(r.pid); + } + + + lastNodes = allNodes.filter(item => { + //差集 + return !parentNodes.includes(item); + //交集 + //return parentNodes.includes(item) + }); + + return lastNodes; +} + + +function screen() { + if (typeof width !== 'number' || width === 0) { + width = $(window).width() * 0.8; + } + if (typeof height !== 'number' || height === 0) { + height = $(window).height() - 20; + } + return [width + 'px', height + 'px']; +} + +function getColumnValues(data, columnName) { + return data.map(function (item) { + return item[columnName]; + }); +} + +/** + * 递归lay-ui Tree 数据 + * @param data + * @param parentId + * @param idField + * @param titleField + * @param parentField + * @returns {*[]} + */ +function convertToLayuiTree(data, parentId = '0', idField = 'id', titleField = 'title', parentField = 'parent_id') { + let result = []; + + for (let i = 0; i < data.length; i++) { + if (data[i][parentField] === parentId) { + let item = { + id: data[i][idField], + parentId: data[i][parentField], + title: data[i][titleField], + children: convertToLayuiTree(data, data[i][idField], idField, titleField, parentField) + }; + result.push(item); + } + } + + return result; +} + +/** + * 返回Lay-uiTree 最后节点IDS + * @param ids + * @param treeData + * @returns {*[]} + */ +const getSelectedLastNodeIds = function (ids, treeData) { + let lastNodeIds = []; + // 递归遍历树节点 + const traverseTree = function (nodes) { + for (let node of nodes) { + // 如果当前节点有子节点,则继续递归遍历子节点 + if (node.children && node.children.length > 0) { + traverseTree(node.children); + } else { + // 如果当前节点是最后一级节点,并且在ids数组中,则将其id添加到lastNodeIds数组中 + if (ids.includes(node.id)) { + lastNodeIds.push(node.id); + } + } + } + }; + + // 遍历树节点 + traverseTree(treeData); + return lastNodeIds; +}; + +/** + * 提取二维数组字段集合v1.11 + * @param array + * @param column + * @returns {*} + */ +const array_column = function (array, column) { + return array.map(item => item[column]); +} + +/** + * 树形数据追加checkArr 适配dtree v1.11 + * @param data + */ +const appendCheckArr = function (data, level = 0) { + if (!Array.isArray(data)) { + return; + } + data.forEach(function (node) { + node.checkArr = [{"type": "0", "checked": level, 'half': false}]; + if (Array.isArray(node.children) && node.children.length > 0) { + appendCheckArr(node.children, level); + } + }); +} + +/** + * 扁平数组转树形v1.11 + * @param data + * @param parentId + * @param idKey + * @param parentKey + * @param childrenKey + * @returns {*[]} + */ +const flattenToTree = function (data, parentId = '-1', idKey = 'id', parentKey = 'pid', childrenKey = 'children') { + let tree = []; + // 遍历数据,将每个节点添加到对应的父节点下 + layui.$.each(data, function (index, item) { + if (item[parentKey] === parentId) { + let children = flattenToTree(data, item[idKey], idKey, parentKey, childrenKey); + if (children.length > 0) { + item[childrenKey] = children; + } + tree.push(item); + } + }); + return tree; +}; + + +/** + * 浏览页面顶部搜索框展开收回控制 + */ +// function toggleSearchFormShow() { +// let $ = layui.$; +// let items = $('.top-search-from .layui-form-item'); +// if (items.length <= 2) { +// if (items.length <= 1) $('.top-search-from').parent().parent().remove(); +// return; +// } +// let btns = $('.top-search-from .toggle-btn a'); +// let toggle = toggleSearchFormShow; +// if (typeof toggle.hide === 'undefined') { +// btns.on('click', function () { +// toggle(); +// }); +// } +// let countPerRow = parseInt($('.top-search-from').width() / $('.layui-form-item').width()); +// if (items.length <= countPerRow) { +// return; +// } +// btns.removeClass('layui-hide'); +// toggle.hide = !toggle.hide; +// if (toggle.hide) { +// for (let i = countPerRow - 1; i < items.length - 1; i++) { +// $(items[i]).hide(); +// } +// return $('.top-search-from .toggle-btn a:last').addClass('layui-hide'); +// } +// items.show(); +// $('.top-search-from .toggle-btn a:first').addClass('layui-hide'); +// } + +// layui.$(function () { +// toggleSearchFormShow(); +// }); diff --git a/demo/thinkphp/frontend/layui_admin_flow/config/config.js b/demo/thinkphp/frontend/layui_admin_flow/config/config.js new file mode 100644 index 0000000000000000000000000000000000000000..e50a0b030e4f127c286ad451e63e741d5f4ef56d --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/config/config.js @@ -0,0 +1,21 @@ +const config = { + api_url: "http://127.0.0.1:8080", + base_path: "/layui_admin_flow/", +} + +window.errors = function (html) { + let MODULE_PATH = 'view/exception/' + html; + layer.open({ + type: 2, + title: false, + skin: 'layui-layer-win10', // 2.8+ + shadeClose: true, // 点击遮罩区域,关闭弹层 + closeBtn: false, + maxmin: false, + shade: 0.1, + area: ['100%', '100%'], + content: MODULE_PATH, + cancel: function () { + } + }); +} diff --git a/demo/thinkphp/frontend/layui_admin_flow/config/pear.config.json b/demo/thinkphp/frontend/layui_admin_flow/config/pear.config.json new file mode 100644 index 0000000000000000000000000000000000000000..2c1334d50842bc79dbe8555928018dd96537bbe9 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/config/pear.config.json @@ -0,0 +1,70 @@ +{ + "logo": { + "title": "Pear Admin", + "image": "admin/images/logo.png" + }, + "menu": { + "data": "admin/data/menu.json", + "method": "GET", + "accordion": true, + "collapse": false, + "control": false, + "controlWidth": 500, + "select": "10", + "async": true + }, + "tab": { + "enable": true, + "keepState": true, + "session": true, + "preload": false, + "max": "30", + "index": { + "id": "10", + "href": "view/console/console1.html", + "title": "首页" + } + }, + "theme": { + "defaultColor": "2", + "defaultMenu": "dark-theme", + "defaultHeader": "light-theme", + "allowCustom": true, + "banner": false + }, + "colors": [ + { + "id": "1", + "color": "#2d8cf0", + "second": "#ecf5ff" + }, + { + "id": "2", + "color": "#36b368", + "second": "#f0f9eb" + }, + { + "id": "3", + "color": "#f6ad55", + "second": "#fdf6ec" + }, + { + "id": "4", + "color": "#f56c6c", + "second": "#fef0f0" + }, + { + "id": "5", + "color": "#3963bc", + "second": "#ecf5ff" + } + ], + "other": { + "keepLoad": "1200", + "autoHead": false, + "footer": false + }, + "header": { + "message": "admin/data/message.json" + } +} \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/config/pear.config.yml b/demo/thinkphp/frontend/layui_admin_flow/config/pear.config.yml new file mode 100644 index 0000000000000000000000000000000000000000..b8dbe0a6c6bed21e7596c04b0b444af49a3f35ff --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/config/pear.config.yml @@ -0,0 +1,85 @@ +## 网站配置 +logo: + ## 网站名称 + title: "Ingenious 工作流引擎" + ## 网站图标 + image: "admin/images/logo.png" +## 菜单配置 +menu: + ## 菜单数据 + data: "http://127.0.0.1:8080/adminapi/setting/permission" + ##data: "admin/data/menu.json" + ## GET / POST + method: "GET" + ## 菜单手风琴 + accordion: true + ## 默认折叠状态 + collapse: false + ## 多菜单模式 + control: false + ## 默认选中的菜单项 + select: "10" + ## 是否开启异步菜单,false 时 data 属性设置为静态数据,true 时为后端接口 + async: false +## 视图内容配置 +tab: + ## 是否开启多选项卡 + enable: true + ## 保持视图状态 + keepState: true + ## 开启选项卡记忆 + session: true + ## 浏览器刷新时是否预加载非激活标签页 + preload: true + ## 可打开的数量, false 不限制极值 + max: "30" + ## 首页 + index: + id: "10" ## 标识 ID , 建议与菜单项中的 ID 一致 + href: "view/console/index.html" ## 页面地址 + title: "首页" ## 标题 +## 主题配置 +theme: + ## 默认主题色,对应 colors 配置中的 ID 标识 + defaultColor: "2" + ## 默认的菜单主题 dark-theme 黑 / light-theme 白 + defaultMenu: "dark-theme" + ## 默认的顶部主题 dark-theme 黑 / light-theme 白 + defaultHeader: "light-theme" + ## 是否允许用户切换主题,false 时关闭自定义主题面板 + allowCustom: true + ## 通栏配置 + banner: false + dark: false +## 主题色配置列表 +colors: +- id: "1" + color: "#16baaa" + second: "#ecf5ff" +- id: "2" + color: "#009688" + second: "#ecf5ff" +- id: "3" + color: "#36b368" + second: "#f0f9eb" +- id: "4" + color: "#f6ad55" + second: "#fdf6ec" +- id: "5" + color: "#f56c6c" + second: "#fef0f0" +- id: "6" + color: "#3963bc" + second: "#ecf5ff" +## 其他配置 +other: + ## 主页动画时长 + keepLoad: "1200" + ## 布局顶部主题 + autoHead: false + ## 页脚 + footer: false +## 头部配置 +header: + ## 站内消息,通过 false 设置关闭 + message: "admin/data/message.json" \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/config/permission.js b/demo/thinkphp/frontend/layui_admin_flow/config/permission.js new file mode 100644 index 0000000000000000000000000000000000000000..192913e1ae1b20bc5b0a4ffb57231ffd0c652957 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/config/permission.js @@ -0,0 +1,146 @@ +/** + * 获取控制器详细权限,并决定展示哪些按钮或dom元素 + */ +layui.$(function () { + let $ = layui.$; + let userInfo = getUserInfo(); + if (userInfo === undefined) { + return; + } + if (userInfo.isLogin != undefined && userInfo.isLogin === true) { + let style = '' + let isSupperAdmin = false; + let level = userInfo.info.level != undefined && userInfo.info.level === 0 ? true : false; + if (level) { + $("head").append(""); + isSupperAdmin = true; + } + if (isSupperAdmin) return; + + + // 细分权限 + let codes = getUserInfo().unique_auth !== undefined ? getUserInfo().unique_auth : []; + layui.each(codes, function (k, code) { + codes[k] = '*[permission^="' + code + '"]'; + }); + if (codes.length) { + $("head").append(""); + } + } +}); + +const $request = (params) => { + let $ = layui.jquery; + let userinfo = checkLogin({ + nav: true + }); + if (userinfo === false) { + return false; + } + return new Promise((resolve, reject) => { + $.ajax({ + headers: { + "Authori-zation": "Bearer " + userinfo["token"] ?? 'Bearer', + Author: 'Leamus', + 'Access-Control-Allow-Origin': '*', + }, ...params, success(ret) { + // 返回成功 + if (ret && ret.status === 200) { + resolve(ret); + } else { + reject(ret); + } + }, error(ret) { + // 返回Token过期 + if (ret && ret.status === 401) { + if (ret["responseJSON"].code < 0) { + // 需要重新登录 + setUserInfo(null); + location.href = 'login.html'; + } else { + console.log('刷新token'); + // 刷新处理Token + setUserInfo({ + isLogin: true, "token": ret.data.token, info: ret.data.info, rules: ret.data.rules, + }); + // 将原来请求重新发送 + $request(params).then(resolve).catch(reject); + } + } else { + reject(ret); + } + }, + }); + }); +}; + +// 设置请求默认值 +layui.$.ajaxSetup({ + beforeSend: function (xhr) { + if (getUserInfo() == '' || getUserInfo() == null || getUserInfo() == undefined) { + location.href = 'index.html'; + return; + + } + //可以设置自定义标头 + xhr.setRequestHeader('Author', 'Leamus'); + xhr.setRequestHeader('Authori-zation', getUserInfo() != undefined ? "Bearer " + getUserInfo()["token"] : 'Bearer'); + + }, complete: function (xhr) { + // 设置登陆拦截 + if (xhr.status === 401) { + let ret = xhr['responseJSON'] !== undefined ? xhr['responseJSON'] : []; + if (ret['code'] === undefined || ret['code'] != 0) { + setUserInfo(null); + location.href = 'index.html' + } + setUserInfo({ + isLogin: true, "token": ret.data.token, info: ret.data.info, rules: ret.data.rules, + }); + //继续完成当前访问 + layui.$.ajax(this) + } + if (xhr.status === 403) { + window.errors('403.html') + } + if (xhr.status === 404) { + window.errors('404.html') + } + if (xhr.status === 500) { + window.errors('500.html') + } + if (xhr.responseJSON !== undefined && xhr.responseJSON.status !== undefined && xhr.responseJSON.status === 110003) { + setUserInfo(null); + location.href = 'index.html' + } + }, +}); + +/** + * 超时没有操作退出 + * @type {number} + */ +let lastTime = new Date().getTime(); +let currentTime = new Date().getTime(); +let timeOut = 15 * 60 * 1000; //设置超时时间: 15分 + +layui.$(function () { + /* 鼠标移动事件 */ + layui.$(document).mouseover(function () { + lastTime = new Date().getTime(); //更新操作时间 + }); +}); + +function toLoginPage() { + currentTime = new Date().getTime(); //更新当前时间 + if (currentTime - lastTime > timeOut) { //判断是否超时 + window.close();//关闭当前页 + location.href = 'login.html'; + // window.parent.location.replace("toLogin.do");//刷新父级页面; + } +} + +/* 定时器 + * 间隔1秒检测是否长时间未操作页面 + */ +// window.setInterval(toLoginPage, 1000); diff --git a/demo/thinkphp/frontend/layui_admin_flow/favicon.ico b/demo/thinkphp/frontend/layui_admin_flow/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..12b1ca34ac9a0a4d4774d3929adde2fa932a1e99 Binary files /dev/null and b/demo/thinkphp/frontend/layui_admin_flow/favicon.ico differ diff --git a/demo/thinkphp/frontend/layui_admin_flow/index.html b/demo/thinkphp/frontend/layui_admin_flow/index.html new file mode 100644 index 0000000000000000000000000000000000000000..7fc837424f7ef83c8469a178071f289aede814e8 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/index.html @@ -0,0 +1,178 @@ + + + + + Ingenious Admin + + + + + + + + + + + + +
                    + +
                    + + + +
                      +
                    • +
                    • +
                    • +
                    + +
                    + + +
                    + +
                    + + + +
                    +
                    +
                    +
                    + +
                    + +
                    +
                    + + + +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    + + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/login.html b/demo/thinkphp/frontend/layui_admin_flow/login.html new file mode 100644 index 0000000000000000000000000000000000000000..d76643d6c26b2b445db2aca9cfc903e8f5b41fdc --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/login.html @@ -0,0 +1,158 @@ + + + + + + 登录 + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/nginx.htaccess b/demo/thinkphp/frontend/layui_admin_flow/nginx.htaccess new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/console/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/console/index.html new file mode 100644 index 0000000000000000000000000000000000000000..e9f40e0bb9b38ab239135f39833858f0eecc40ae --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/console/index.html @@ -0,0 +1,336 @@ + + + + + + 工作台 + + + + + + + +
                    +
                    +
                    +
                    +
                    +
                    +
                    + 快捷菜单 +
                    +
                    +
                    +
                    +
                    + +
                    + 待办 +
                    +
                    +
                    + +
                    + 已办 +
                    +
                    +
                    + +
                    + 抄送 +
                    +
                    +
                    + +
                    + 发起 +
                    +
                    +
                    + +
                    + 表单 +
                    +
                    +
                    + +
                    + 设计 +
                    +
                    +
                    + +
                    + 追踪 +
                    +
                    +
                    + +
                    + 收藏 +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + 代办任务 +
                    +
                    +
                    +
                    +
                    +
                    我的待办
                    +
                    21
                    +
                    +
                    +
                    +
                    +
                    我的已办
                    +
                    63
                    +
                    +
                    +
                    +
                    +
                    我的待阅
                    +
                    32
                    +
                    +
                    +
                    +
                    +
                    我的申请
                    +
                    14
                    +
                    +
                    + +
                    +
                    +
                    +
                    +
                    + + + + + + + + + +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    留言板
                    +
                    +
                      +
                    • +

                      要不要作为我的家人,搬来我家。

                      + +
                    • +
                    • +

                      快乐的时候不敢尽兴,频繁警戒自己保持清醒。

                      +
                    • +
                    • +

                      夏天真的来了,尽管它还有些犹豫。

                      +
                    • +
                    • +

                      Ingenious 工作流引擎,尽管它还有些犹豫。

                      + + +
                    • +
                    +
                    +
                    +
                    +
                    +
                    + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/exception/403.html b/demo/thinkphp/frontend/layui_admin_flow/view/exception/403.html new file mode 100644 index 0000000000000000000000000000000000000000..4b40a775c5be7771fee51321f37d197b1d43f74b --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/exception/403.html @@ -0,0 +1,30 @@ + + +
                    +
                    +
                    + +
                    +
                    +
                    +

                    403

                    +
                    +
                    + 抱歉, 你无权访问该页面. +
                    +
                    +
                    + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/exception/404.html b/demo/thinkphp/frontend/layui_admin_flow/view/exception/404.html new file mode 100644 index 0000000000000000000000000000000000000000..534c2f736cc793d2188749a32d8e82e53c1bb3d2 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/exception/404.html @@ -0,0 +1,30 @@ + + +
                    +
                    +
                    + +
                    +
                    +
                    +

                    404

                    +
                    +
                    + 抱歉, 你访问的页面不存在. +
                    +
                    +
                    + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/exception/500.html b/demo/thinkphp/frontend/layui_admin_flow/view/exception/500.html new file mode 100644 index 0000000000000000000000000000000000000000..50545070af7522219990a2d27d7d827df26a0a83 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/exception/500.html @@ -0,0 +1,30 @@ + + +
                    +
                    +
                    + +
                    +
                    +
                    +

                    500

                    +
                    +
                    + 抱歉, 服务器出错了. +
                    +
                    +
                    + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/file/category/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/file/category/add.html new file mode 100644 index 0000000000000000000000000000000000000000..b3e4d3a77564e52384948b55b63e218d2db125fd --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/file/category/add.html @@ -0,0 +1,226 @@ + + + + + 新增字典 + + + + + +
                    + +
                    +
                    +
                    +
                    + +
                    +
                      +
                      +
                      +
                      +
                      +
                      + +
                      + +
                      +
                      +
                      + +
                      +
                      + +
                      + +
                      +
                      +
                      + +
                      + +
                      + +
                      +
                      +
                      +
                      + +
                      +
                      + + +
                      +
                      +
                      + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/file/category/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/file/category/index.html new file mode 100644 index 0000000000000000000000000000000000000000..e68a8f27a9c23066e23dea03ad9ff605db16ed90 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/file/category/index.html @@ -0,0 +1,270 @@ + + + + + 附件分类 + + + + + +
                      +
                      +
                      +
                      +
                      + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/file/list/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/file/list/add.html new file mode 100644 index 0000000000000000000000000000000000000000..3bd64b87982942a5817361ca6cedf54ccbd85812 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/file/list/add.html @@ -0,0 +1,236 @@ + + + + + + + + + +
                      +
                      +
                      +
                      + +
                      +
                        +
                        +
                        +
                        + +
                        + +
                        +
                        +
                        +
                        +
                        + + + + + + + + + + + + + + + + +
                        文件名大小文件上传进度操作
                        +
                        +
                        +
                        +
                        +
                        +
                        +
                        + + +
                        +
                        +
                        + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/file/list/edit.html b/demo/thinkphp/frontend/layui_admin_flow/view/file/list/edit.html new file mode 100644 index 0000000000000000000000000000000000000000..0bd2ddb3d71205e975afb045ebfa065a1d208631 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/file/list/edit.html @@ -0,0 +1,170 @@ + + + + + + + + + +
                        +
                        +
                        +
                        + +
                        +
                          +
                          +
                          +
                          + +
                          + +
                          +
                          +
                          +
                          +
                          +
                          + + +
                          +
                          +
                          + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/file/list/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/file/list/index.html new file mode 100644 index 0000000000000000000000000000000000000000..243bfa911230c3cebab5662478f1dd66abcc84ad --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/file/list/index.html @@ -0,0 +1,393 @@ + + + + + 附件管理 + + + + +
                          +
                          +
                          +
                          + +
                          +
                            +
                            +
                            + +
                            + +
                            + +
                            +
                            + +
                            + + + +
                            +
                            +
                            +
                            + + +
                            +
                            +
                            +
                            +
                            + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/country/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/country/add.html new file mode 100644 index 0000000000000000000000000000000000000000..3c6c9eb9477fe13b7a0d4e6fd7d111dc2b99237f --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/country/add.html @@ -0,0 +1,166 @@ + + + + + + + + + + +
                            +
                            +
                            +
                            + +
                            + +
                            例如:中国、香港、德国
                            +
                            +
                            +
                            + +
                            + +
                            浏览器语言识别码
                            +
                            +
                            +
                            + +
                            + +
                            请选择关联语言,语言类型是由您自行添加的
                            +
                            +
                            +
                            +
                            +
                            +
                            + + +
                            +
                            +
                            + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/country/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/country/index.html new file mode 100644 index 0000000000000000000000000000000000000000..a7ae88da6f23fb54d0b19e4e8127460efed599bc --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/country/index.html @@ -0,0 +1,232 @@ + + + + + 地区列表 + + + + +
                            +
                            +
                            +
                            + +
                            + +
                            +
                            +
                            + + + +
                            +
                            + 展开 + 收起 +
                            +
                            +
                            +
                            + + + +
                            +
                            +
                            +
                            +
                            + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/info/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/info/add.html new file mode 100644 index 0000000000000000000000000000000000000000..4194d18a7d5935f7fe9abd6784ed3559fd57a067 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/info/add.html @@ -0,0 +1,286 @@ + + + + + + + + + + +
                            +
                            +
                            +
                            + +
                            + +
                            +
                            +
                            + +
                            + +
                            +
                            + +
                            +
                            + +
                            +
                            +
                            +
                            +
                            + +
                            +
                            +
                            +
                            + + +
                            +
                            +
                            + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/info/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/info/index.html new file mode 100644 index 0000000000000000000000000000000000000000..4622c937c30f2a5e17c3607b3bd24966c77f858b --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/info/index.html @@ -0,0 +1,369 @@ + + + + + 语言详情 + + + + +
                            +
                            +
                            +
                            + +
                            + +
                            +
                            +
                            + +
                            + +
                            +
                            +
                            + +
                            + +
                            +
                            + +
                            + + + + + +
                            +
                            + 展开 + 收起 +
                            +
                            +
                            +
                            + + + +
                            +
                            +
                            +
                            +
                            + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/list/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/list/add.html new file mode 100644 index 0000000000000000000000000000000000000000..e1c4063953c0e5a13a6d4bd7622f66c3e48ef98b --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/list/add.html @@ -0,0 +1,182 @@ + + + + + + + + + + +
                            +
                            +
                            +
                            + +
                            + +
                            +
                            +
                            + +
                            + +
                            +
                            + +
                            + +
                            + + +
                            +
                            +
                            + +
                            + + +
                            +
                            +
                            +
                            +
                            +
                            + + +
                            +
                            +
                            + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/list/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/list/index.html new file mode 100644 index 0000000000000000000000000000000000000000..cadaba7412f1076d566b9155f455e5680bef1d58 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/lang/list/index.html @@ -0,0 +1,277 @@ + + + + + 语言列表 + + + + +
                            +
                            +
                            +
                            + +
                            + +
                            +
                            + +
                            + +
                            + +
                            +
                            + + +
                            + + + +
                            +
                            + 展开 + 收起 +
                            +
                            +
                            +
                            + + + +
                            +
                            +
                            +
                            +
                            + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/org/dept/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/org/dept/add.html new file mode 100644 index 0000000000000000000000000000000000000000..51deae854e30fd61bc50aaad170ec609337f58b5 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/org/dept/add.html @@ -0,0 +1,261 @@ + + + + + 部门新增 + + + + +
                            +
                            +
                            +
                            + +
                            +
                              +
                              +
                              +
                              + +
                              + +
                              +
                              +
                              + +
                              + +
                              +
                              +
                              + +
                              + +
                              +
                              +
                              + +
                              + +
                              +
                              + +
                              + +
                              + + +
                              +
                              + + +
                              +
                              +
                              + +
                              +
                              + +
                              +
                              + 清空 +
                              +
                              +
                              +
                              +
                              + +
                              + +
                              + +
                              +
                              +
                              +
                              +
                              +
                              + + +
                              +
                              +
                              + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/org/dept/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/org/dept/index.html new file mode 100644 index 0000000000000000000000000000000000000000..9fca87d7dfd2bdc9015a107c0231ebb4ccae09ea --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/org/dept/index.html @@ -0,0 +1,313 @@ + + + + + 组织管理 + + + + + +
                              +
                              +
                              +
                              +
                              + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/org/post/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/org/post/add.html new file mode 100644 index 0000000000000000000000000000000000000000..311bba861ebc2b5858d4af7a77ad5dda212dbaea --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/org/post/add.html @@ -0,0 +1,314 @@ + + + + + + + + +
                              +
                              +
                              +
                              + +
                              +
                              +
                                +
                                +
                                +
                                +
                                + +
                                +
                                  +
                                  +
                                  +
                                  + +
                                  + +
                                  +
                                  +
                                  + +
                                  + +
                                  +
                                  + + +
                                  +
                                  +
                                  + +
                                  +
                                  + +
                                  +
                                  + 清空 +
                                  +
                                  +
                                  +
                                  +
                                  + +
                                  + +
                                  + +
                                  +
                                  +
                                  +
                                  +
                                  +
                                  + + +
                                  +
                                  +
                                  + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/org/post/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/org/post/index.html new file mode 100644 index 0000000000000000000000000000000000000000..2216c9277df68eaa5f5bdcbf94352392a2c6abab --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/org/post/index.html @@ -0,0 +1,394 @@ + + + + + 职位管理 + + + + +
                                  +
                                  +
                                  + +
                                  + +
                                  + +
                                  +
                                  + +
                                  + +
                                  + +
                                  +
                                  + +
                                  + + + +
                                  +
                                  + 展开 + 收起 +
                                  +
                                  +
                                  +
                                  + + +
                                  +
                                  +
                                  +
                                  +
                                  +
                                    +
                                    +
                                    +
                                    +
                                    +
                                    +
                                    +
                                    +
                                    +
                                    +
                                    +
                                    +
                                    +
                                    + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_admin/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_admin/add.html new file mode 100644 index 0000000000000000000000000000000000000000..8f854c0edee19c568db9ce1443cd0288b6e08899 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_admin/add.html @@ -0,0 +1,196 @@ + + + + + + + + + + +
                                    +
                                    +
                                    +
                                    + +
                                    + +
                                    +
                                    +
                                    + +
                                    + +
                                    +
                                    +
                                    + +
                                    + +
                                    +
                                    +
                                    + +
                                    + +
                                    +
                                    +
                                    + +
                                    + +
                                    +
                                    +
                                    + +
                                    + +
                                    +
                                    + +
                                    + +
                                    + + +
                                    +
                                    +
                                    + +
                                    + +
                                    +
                                    +
                                    + +
                                    + +
                                    +
                                    +
                                    +
                                    +
                                    +
                                    + + +
                                    +
                                    +
                                    + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_admin/dept.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_admin/dept.html new file mode 100644 index 0000000000000000000000000000000000000000..bbf6614751b40852e4dd12605f7a02bf5fd479aa --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_admin/dept.html @@ -0,0 +1,258 @@ + + + + + 管理员部门设置 + + + + +
                                    +
                                    +
                                    +
                                    + +
                                    + +
                                    +
                                    +
                                    + +
                                    + +
                                    +
                                    +
                                    + +
                                    +
                                      +
                                      +
                                      +
                                      + +
                                      +
                                        +
                                        +
                                        +
                                        +
                                        + +
                                        +
                                        + + +
                                        +
                                        +
                                        + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_admin/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_admin/index.html new file mode 100644 index 0000000000000000000000000000000000000000..c7b294f0b9deed99c15bd8f911b6ce31afe5b79c --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_admin/index.html @@ -0,0 +1,416 @@ + + + + + 用户管理 + + + + +
                                        +
                                        +
                                        +
                                        + +
                                        + +
                                        +
                                        + +
                                        + +
                                        + +
                                        +
                                        + +
                                        + + + +
                                        +
                                        + 展开 + 收起 +
                                        +
                                        +
                                        +
                                        + + + +
                                        +
                                        +
                                        +
                                        +
                                        + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_admin/person.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_admin/person.html new file mode 100644 index 0000000000000000000000000000000000000000..24a3b63a903711e733fdc38cae69aab58bf1f0fd --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_admin/person.html @@ -0,0 +1,219 @@ + + + + + + + + + + + +
                                        +
                                        + +
                                        +
                                          +
                                        • 基本信息
                                        • +
                                        • 安全设置
                                        • +
                                        +
                                        + +
                                        +
                                        +
                                        + +
                                        + +
                                        +
                                        +
                                        + +
                                        + +
                                        +
                                        +
                                        + +
                                        + +
                                        +
                                        +
                                        + +
                                        + +
                                        +
                                        +
                                        + +
                                        + +
                                        +
                                        +
                                        + +
                                        + + +
                                        +
                                        +
                                        + +
                                        + +
                                        +
                                        +
                                        +
                                        + + +
                                        +
                                        +
                                        + +
                                        + +
                                        +
                                        +
                                        + +
                                        + +
                                        +
                                        +
                                        + +
                                        + +
                                        +
                                        +
                                        + +
                                        + +
                                        +
                                        +
                                        +
                                        + + +
                                        +
                                        +
                                        +
                                        +
                                        +
                                        +
                                        +
                                        + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_menus/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_menus/add.html new file mode 100644 index 0000000000000000000000000000000000000000..57217b71342aaa57019186cc8fa5702768452c19 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_menus/add.html @@ -0,0 +1,413 @@ + + + + + 新增页面 + + + + +
                                        +
                                        +
                                        + + + + + + + + + +
                                        + +
                                        + +
                                        +
                                        + +
                                        + +
                                        +
                                          +
                                          +
                                          + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                          + +
                                          +
                                          + +
                                          +
                                          + 清空 +
                                          +
                                          +
                                          + +
                                          + +
                                          + +
                                          +
                                          + +
                                          + +
                                          + + +
                                          +
                                          + +
                                          + +
                                          + +
                                          +
                                          +
                                          +
                                          + +
                                          +
                                          + + +
                                          +
                                          +
                                          + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_menus/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_menus/index.html new file mode 100644 index 0000000000000000000000000000000000000000..6f6fb812c54eb021c34aecc2362b1c7fe49a126e --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_menus/index.html @@ -0,0 +1,358 @@ + + + + + + 权限管理 + + + + + + +
                                          +
                                          +
                                          +
                                          +
                                          + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/add.html new file mode 100644 index 0000000000000000000000000000000000000000..de2a044013ab03aeed6a889bd485634828147351 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/add.html @@ -0,0 +1,294 @@ + + + + + 角色新增 + + + + +
                                          +
                                          +
                                          +
                                          + +
                                          +
                                            +
                                            +
                                            + +
                                            + +
                                            + +
                                            +
                                            + +
                                            + +
                                            + +
                                            +
                                            + +
                                            + +
                                            + + +
                                            +
                                            + + +
                                            +
                                            +
                                            + +
                                            +
                                            + +
                                            +
                                            + 清空 +
                                            +
                                            +
                                            +
                                            +
                                            + +
                                            + +
                                            + +
                                            +
                                            + +
                                            +
                                            + +
                                            +
                                            + + +
                                            +
                                            +
                                            + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/auth.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/auth.html new file mode 100644 index 0000000000000000000000000000000000000000..3fdf138d990fd79714a88aef5be4fa3d3cefd58b --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/auth.html @@ -0,0 +1,169 @@ + + + + + 角色权限 + + + + +
                                            +
                                            +
                                            +
                                            + +
                                            + +
                                            +
                                            +
                                            + +
                                            +
                                              +
                                              +
                                              +
                                              +
                                              + +
                                              +
                                              + + +
                                              +
                                              +
                                              + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/dept.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/dept.html new file mode 100644 index 0000000000000000000000000000000000000000..5de4a2c0833d2f9684616438c9b4fa8e10c440e5 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/dept.html @@ -0,0 +1,163 @@ + + + + + 分配组织 + + + + +
                                              +
                                              +
                                              +
                                              + +
                                              + +
                                              +
                                              +
                                              + +
                                              +
                                                +
                                                +
                                                +
                                                +
                                                + +
                                                +
                                                + + +
                                                +
                                                +
                                                + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/index.html new file mode 100644 index 0000000000000000000000000000000000000000..99ebb7d204476a8095a6dcd489a5784ba0e4e65c --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/index.html @@ -0,0 +1,371 @@ + + + + + 角色管理 + + + + + +
                                                +
                                                +
                                                +
                                                +
                                                + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/post.html b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/post.html new file mode 100644 index 0000000000000000000000000000000000000000..f5a596f29a3278629f267f6f866ba55fc83b0890 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/setting/system_role/post.html @@ -0,0 +1,166 @@ + + + + + 分配职位 + + + + +
                                                +
                                                +
                                                +
                                                + +
                                                + +
                                                +
                                                +
                                                + +
                                                +
                                                  +
                                                  +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  + + +
                                                  +
                                                  +
                                                  + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/start/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/start/index.html new file mode 100644 index 0000000000000000000000000000000000000000..7da7fa24ff2fa3d2cea0596318bebad863fd8f64 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/start/index.html @@ -0,0 +1,57 @@ + + + + + + 成功 + + + + + +
                                                  +
                                                  +   项目地址 + 点亮小星星才可以使用演示系统哦(◠‿◠) +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  +
                                                  + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/backend_routing/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/backend_routing/add.html new file mode 100644 index 0000000000000000000000000000000000000000..37c7d6391bfdb4b9859d05ef5eeab18a66caa48d --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/backend_routing/add.html @@ -0,0 +1,399 @@ + + + + + 接口维护 + + + + + +
                                                  +
                                                  +
                                                  +
                                                  +
                                                  接口信息
                                                  +
                                                  +
                                                  + +
                                                  + +
                                                  +
                                                  +
                                                  + +
                                                  + +
                                                  +
                                                  +
                                                  + +
                                                  + +
                                                  +
                                                  + +
                                                  +
                                                  调用方式
                                                  +
                                                  +
                                                  + +
                                                  + +
                                                  +
                                                  +
                                                  + +
                                                  + +
                                                  +
                                                  +
                                                  + +
                                                  + +
                                                  +
                                                  + +
                                                  + +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  + + +
                                                  + +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  + + +
                                                  + 调用示例 +
                                                  +
                                                  + +
                                                  + +
                                                  +
                                                  +
                                                  + +
                                                  + +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  + + +
                                                  +
                                                  +
                                                  +
                                                  + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/backend_routing/cate.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/backend_routing/cate.html new file mode 100644 index 0000000000000000000000000000000000000000..0b039003822aa0b4c997e7bd70f9e63297ab8a4d --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/backend_routing/cate.html @@ -0,0 +1,95 @@ + + + + + 添加分类 + + + + +
                                                  +
                                                  +
                                                  +
                                                  + +
                                                  + +
                                                  +
                                                  +
                                                  + +
                                                  + +
                                                  +
                                                  +
                                                  +
                                                  +
                                                  + + +
                                                  +
                                                  +
                                                  + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/backend_routing/debug.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/backend_routing/debug.html new file mode 100644 index 0000000000000000000000000000000000000000..dc0b70659475b964d928a6503e84f4490e7f52a9 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/backend_routing/debug.html @@ -0,0 +1,236 @@ + + + + + API 调试页面 + + + + + +
                                                  +
                                                  +
                                                  +
                                                  +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  +
                                                  + + +
                                                  +
                                                  +
                                                    +
                                                  • Params
                                                  • +
                                                  • Body
                                                  • +
                                                  • Header
                                                  • +
                                                  +
                                                  +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  +
                                                  +
                                                  + +
                                                  +
                                                  +
                                                  +
                                                  + +
                                                  + +
                                                  
                                                  +
                                                  + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/backend_routing/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/backend_routing/index.html new file mode 100644 index 0000000000000000000000000000000000000000..f27308f02b14ee5e14cfb4b6965ccedcdf7bf1b9 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/backend_routing/index.html @@ -0,0 +1,529 @@ + + + + + 接口管理 + + + + +
                                                  +
                                                  +
                                                    +
                                                  • 管理端接口
                                                  • +
                                                  • 用户端接口
                                                  • +
                                                  • 对外接口
                                                  • +
                                                  + +
                                                  +
                                                  + + +
                                                  +
                                                  +
                                                  +
                                                  +
                                                  +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    + +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    + +
                                                    +
                                                    +
                                                    + + +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    + +
                                                    + +
                                                    + +
                                                    +
                                                    +
                                                    + +
                                                    + +
                                                    +
                                                    +
                                                    + +
                                                    + +
                                                    +
                                                    + +
                                                    + 调用方式 +
                                                    +
                                                    + +
                                                    + +
                                                    +
                                                    +
                                                    + +
                                                    + +
                                                    +
                                                    +
                                                    + +
                                                    + +
                                                    +
                                                    + +
                                                    + +
                                                    +
                                                    +
                                                    +
                                                    + + +
                                                    + +
                                                    +
                                                    +
                                                    +
                                                    + + +
                                                    + 调用示例 +
                                                    +
                                                    + +
                                                    +
                                                    
                                                    +                                            
                                                    +
                                                    +
                                                    + +
                                                    +
                                                    
                                                    +                                            
                                                    +
                                                    +
                                                    + +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    + +
                                                    +
                                                    +
                                                    +
                                                    + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/clear/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/clear/index.html new file mode 100644 index 0000000000000000000000000000000000000000..34aa8cfddd53401977c5334fc6b49c27b8b6bff3 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/clear/index.html @@ -0,0 +1,97 @@ + + + + + 刷新缓存 + + + +
                                                    +
                                                    +
                                                    + + +
                                                    +
                                                    +
                                                    + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/crontab/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/crontab/add.html new file mode 100644 index 0000000000000000000000000000000000000000..909fc2c23c3b3d7dcfc29eb5b4ad5c4ac4395280 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/crontab/add.html @@ -0,0 +1,548 @@ + + + + + 新增定时任务 + + + + + +
                                                    +
                                                    +
                                                    +
                                                    + +
                                                    + +
                                                    +
                                                    + +
                                                    + +
                                                    +
                                                    + +
                                                    + +
                                                    + + 秒 +
                                                    + +
                                                    +
                                                    + + 分 +
                                                    +
                                                    + + +
                                                    +
                                                    + + 时 +
                                                    +
                                                    + + 分 +
                                                    +
                                                    + + +
                                                    +
                                                    + + 日 +
                                                    +
                                                    + + 时 +
                                                    +
                                                    + + 分 +
                                                    +
                                                    + +
                                                    +
                                                    + + 时 +
                                                    +
                                                    + + 分 +
                                                    +
                                                    + + 秒 +
                                                    +
                                                    + + +
                                                    +
                                                    + +
                                                    +
                                                    + + 时 +
                                                    +
                                                    + + 分 +
                                                    +
                                                    + + 秒 +
                                                    +
                                                    + +
                                                    +
                                                    + + 日 +
                                                    +
                                                    + + 时 +
                                                    +
                                                    + + 分 +
                                                    +
                                                    + + 秒 +
                                                    +
                                                    +
                                                    +
                                                    + +
                                                    +
                                                    + +
                                                    + +
                                                    + +
                                                    +
                                                    + +
                                                    + +
                                                    + +
                                                    +
                                                    +
                                                    +
                                                    + +
                                                    +
                                                    + + +
                                                    +
                                                    +
                                                    + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/crontab/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/crontab/index.html new file mode 100644 index 0000000000000000000000000000000000000000..87ebe70d5ddbf9fb301e20903c2f910ccd84dfc5 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/crontab/index.html @@ -0,0 +1,284 @@ + + + + + 定时任务 + + + + +
                                                    +
                                                    + + 启动定时任务两种方式: +
                                                    + 1、使用命令启动:php think timer start --d;如果更改了执行周期、编辑是否开启、删除定时任务需要重新启动下定时任务确保生效; +
                                                    + 2、使用接口触发定时任务,建议每分钟调用一次,接口地址 https://您的域名/api/crontab/run +
                                                    +
                                                    +
                                                    + + +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/form_build/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/form_build/index.html new file mode 100644 index 0000000000000000000000000000000000000000..dd271b47d990902e69b7be4c3202459890de06b5 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/form_build/index.html @@ -0,0 +1,152 @@ + + + + + + + 表单生成器 + + + +
                                                    +
                                                    +
                                                    + + + + +
                                                    +
                                                    +
                                                    +
                                                    + view +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    html
                                                    +
                                                    + +
                                                    +
                                                    +
                                                    +
                                                    code
                                                    +
                                                    + +
                                                    +
                                                    +
                                                    +
                                                    +
                                                    + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_config/category/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_config/category/add.html new file mode 100644 index 0000000000000000000000000000000000000000..c8ab8298b99df87aeac038bd1f15bf5e16a00a71 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_config/category/add.html @@ -0,0 +1,276 @@ + + + + + + 新增配置分配 + + + + + +
                                                    +
                                                    +
                                                    +
                                                    + +
                                                    +
                                                      +
                                                      +
                                                      +
                                                      + +
                                                      + +
                                                      +
                                                      +
                                                      + +
                                                      + +
                                                      +
                                                      +
                                                      + +
                                                      +
                                                      + +
                                                      +
                                                      + 清空 +
                                                      +
                                                      +
                                                      +
                                                      + +
                                                      + + +
                                                      +
                                                      +
                                                      + +
                                                      + + +
                                                      +
                                                      +
                                                      + +
                                                      + +
                                                      +
                                                      + +
                                                      +
                                                      +
                                                      +
                                                      + + +
                                                      +
                                                      +
                                                      + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_config/category/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_config/category/index.html new file mode 100644 index 0000000000000000000000000000000000000000..11781240ab2b514ca09c05eab0741ed43f560a29 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_config/category/index.html @@ -0,0 +1,289 @@ + + + + + + 配置分类 + + + + + + +
                                                      +
                                                      +
                                                      +
                                                      +
                                                      + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_config/list/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_config/list/add.html new file mode 100644 index 0000000000000000000000000000000000000000..76ce465d0ecda09cb68f3a91d9d0501a34a8f12f --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_config/list/add.html @@ -0,0 +1,366 @@ + + + + + + 新增配置分配 + + + + + +
                                                      +
                                                      +
                                                      +
                                                      +
                                                        +
                                                      • 文本框
                                                      • +
                                                      • 多行文本框
                                                      • +
                                                      • 单选框
                                                      • +
                                                      • 文件上传
                                                      • +
                                                      • 多选框
                                                      • +
                                                      • 下拉框
                                                      • +
                                                      • 开关
                                                      • +
                                                      +
                                                      +
                                                      + +
                                                      + +
                                                      +
                                                        +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + + + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + + +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        + + +
                                                        +
                                                        +
                                                        + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_config/list/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_config/list/index.html new file mode 100644 index 0000000000000000000000000000000000000000..417b10984aa36fff604160267fdda4c6c0aefcf9 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_config/list/index.html @@ -0,0 +1,367 @@ + + + + + 字典列表 + + + + + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + + + +
                                                        +
                                                        + 展开 + 收起 +
                                                        +
                                                        +
                                                        +
                                                        + + +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_databackup/details.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_databackup/details.html new file mode 100644 index 0000000000000000000000000000000000000000..333588d4f4745324273212088c645dcecef37adb --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_databackup/details.html @@ -0,0 +1,163 @@ + + + + + 语言列表 + + + + + + + +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_databackup/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_databackup/index.html new file mode 100644 index 0000000000000000000000000000000000000000..a3af6401cb736bd61e3817277fcbb669dbff4285 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_databackup/index.html @@ -0,0 +1,421 @@ + + + + + 数据库管理 + + + + +
                                                        +
                                                          +
                                                        • 数据库列表
                                                        • +
                                                        • 备份列表
                                                        • +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        + + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_dict/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_dict/add.html new file mode 100644 index 0000000000000000000000000000000000000000..2df932c3c08601143bca43c300fe796de9bf4c53 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_dict/add.html @@ -0,0 +1,260 @@ + + + + + 新增字典 + + + + + + +
                                                        + +
                                                        +
                                                        + +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + + +
                                                        + + + + + + + +
                                                        + + +
                                                        +
                                                        + +
                                                        +
                                                        + + +
                                                        +
                                                        +
                                                        + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_dict/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_dict/index.html new file mode 100644 index 0000000000000000000000000000000000000000..9df30873ea98b2118c0c64cfda5f042629b8dd9c --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_dict/index.html @@ -0,0 +1,296 @@ + + + + + 字典列表 + + + + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        + +
                                                        +
                                                        + +
                                                        + + + +
                                                        +
                                                        + 展开 + 收起 +
                                                        +
                                                        +
                                                        +
                                                        + + +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_file/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_file/index.html new file mode 100644 index 0000000000000000000000000000000000000000..ff91a15c29a80be51f5322d5a14c0957e785cbdf --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_file/index.html @@ -0,0 +1,11 @@ + + + + + Title + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_log/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_log/index.html new file mode 100644 index 0000000000000000000000000000000000000000..9e4df19cf2031105d30129c1fa63a8f08724aa5f --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_log/index.html @@ -0,0 +1,372 @@ + + + + + 系统日志 + + + + + +
                                                        +
                                                        +
                                                        +
                                                        + + +
                                                        + +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                        + + +
                                                        + + + +
                                                        +
                                                        + 展开 + 收起 +
                                                        +
                                                        +
                                                        +
                                                        + + + +
                                                        +
                                                        +
                                                        +
                                                        +
                                                        + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_menus/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_menus/add.html new file mode 100644 index 0000000000000000000000000000000000000000..7acc2ddf15fdc695aa6a154e10fc9cc9016f1bba --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_menus/add.html @@ -0,0 +1,396 @@ + + + + + 新增页面 + + + + +
                                                        +
                                                        +
                                                        +
                                                        + +
                                                        + + + +
                                                        +
                                                        + +
                                                        + +
                                                        + +
                                                        +
                                                        + +
                                                        + +
                                                        +
                                                          +
                                                          +
                                                          + +
                                                          + +
                                                          + +
                                                          +
                                                          + +
                                                          + +
                                                          + +
                                                          +
                                                          + +
                                                          + +
                                                          + +
                                                          +
                                                          + +
                                                          + +
                                                          + +
                                                          +
                                                          + +
                                                          + +
                                                          +
                                                          + +
                                                          +
                                                          + 清空 +
                                                          +
                                                          +
                                                          + +
                                                          + +
                                                          + +
                                                          +
                                                          + +
                                                          + +
                                                          + + +
                                                          +
                                                          + +
                                                          + +
                                                          + +
                                                          +
                                                          +
                                                          +
                                                          + +
                                                          +
                                                          + + +
                                                          +
                                                          +
                                                          + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_menus/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_menus/index.html new file mode 100644 index 0000000000000000000000000000000000000000..7c8fe3ea7de3313fef1c0ecdbc66ccca492d8dd5 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_menus/index.html @@ -0,0 +1,368 @@ + + + + + + 权限管理 + + + + + + +
                                                          +
                                                          +
                                                          +
                                                          +
                                                          + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_menus/rule.html b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_menus/rule.html new file mode 100644 index 0000000000000000000000000000000000000000..0a9678023169834d90ac8513974b6bf9c156f4b2 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/system/maintain/system_menus/rule.html @@ -0,0 +1,330 @@ + + + + + 权限列表 + + + + +
                                                          +
                                                          +
                                                          + + 1.接口可多选,可重复添加; +
                                                          + 2.添加路由按照路由规则进行添加,即可在开发工具->接口管理里面点击同步; +
                                                          + 3.同步完成即可在此选择对应的接口; +
                                                          +
                                                          +
                                                          + +
                                                          +
                                                          +
                                                          +
                                                          +
                                                          + +
                                                          +
                                                          + + +
                                                          +
                                                          +
                                                          +
                                                          +
                                                          + +
                                                          +
                                                          +
                                                          +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + + +
                                                            +
                                                            + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/carbon/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/carbon/index.html new file mode 100644 index 0000000000000000000000000000000000000000..bbb006c9fa2007d7acdc7d89f24961b3e88a9efe --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/carbon/index.html @@ -0,0 +1,368 @@ + + + + + + +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            + + +
                                                            + + +
                                                            + +
                                                            + 展开 + 收起 +
                                                            +
                                                            +
                                                            +
                                                            + + + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/category/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/category/add.html new file mode 100644 index 0000000000000000000000000000000000000000..1fbba557fe106bcbb3dc6685542f6f11c5e08723 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/category/add.html @@ -0,0 +1,134 @@ + + + + + 新增流程类型 + + + + + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            + +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + + +
                                                            +
                                                            +
                                                            + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/category/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/category/index.html new file mode 100644 index 0000000000000000000000000000000000000000..8cf9fdefa2edd853fdaabe866d7ac1c81f8ba693 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/category/index.html @@ -0,0 +1,321 @@ + + + + + 用户管理 + + + + +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            + +
                                                            + + +
                                                            + + +
                                                            + 展开 + 收起 +
                                                            +
                                                            +
                                                            +
                                                            + + + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/approvalProcess.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/approvalProcess.html new file mode 100644 index 0000000000000000000000000000000000000000..feb5a06ffa1b9c90f7ba2907b212bda3109e5e61 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/approvalProcess.html @@ -0,0 +1,294 @@ + + + + + + 审批流程 + + + + + + + +
                                                            +
                                                              +
                                                            • 表单
                                                            • +
                                                            • 流程图
                                                            • +
                                                            • 审批记录
                                                            • +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + +
                                                            +
                                                            + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/approvalProcessHandle.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/approvalProcessHandle.html new file mode 100644 index 0000000000000000000000000000000000000000..27813a5a3f582ddda5c2633dc69aca1351ef0214 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/approvalProcessHandle.html @@ -0,0 +1,385 @@ + + + + + + 审批操作 + + + + + + +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            + +
                                                            + +
                                                            + + + +
                                                            +
                                                            + + + +
                                                            + +
                                                            +
                                                            + + + + + +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/approvalProcessRecord.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/approvalProcessRecord.html new file mode 100644 index 0000000000000000000000000000000000000000..5bb7045e2fce08b0be7a86a5838477d44271e336 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/approvalProcessRecord.html @@ -0,0 +1,78 @@ + + + + + 审批记录 + + + + + + +
                                                            +
                                                            + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/index.html new file mode 100644 index 0000000000000000000000000000000000000000..6cec1848ebddd6d326cfc367550bf53702616b01 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/index.html @@ -0,0 +1,723 @@ + + + + + + 模型设计 + + + + + + + + + + + + +
                                                            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/custom.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/custom.html new file mode 100644 index 0000000000000000000000000000000000000000..31178e7d336de002aaec211b3e95b54237157562 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/custom.html @@ -0,0 +1,243 @@ + + + + + + 属性面板 + + + + + + +
                                                            +
                                                              +
                                                            • 节点属性
                                                            • +
                                                            • 自定义设置
                                                            • +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            基本属性
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            样式设置
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            拦截器
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/decision.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/decision.html new file mode 100644 index 0000000000000000000000000000000000000000..a69de278ab8f36b3093f91f0d49c62ccccb95779 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/decision.html @@ -0,0 +1,109 @@ + + + + + + 属性面板 + + + + + + +
                                                            +
                                                              +
                                                            • 节点属性
                                                            • +
                                                            +
                                                            +
                                                            +
                                                            基本属性
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/detail.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/detail.html new file mode 100644 index 0000000000000000000000000000000000000000..eace5377eae24eb93e239e3d63a9421013d1f6a1 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/detail.html @@ -0,0 +1,104 @@ + + + + + 查看流程数据 + + + + +
                                                            +
                                                            +
                                                            +
                                                            
                                                            +        
                                                            +
                                                            +
                                                            +
                                                            + + +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/end.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/end.html new file mode 100644 index 0000000000000000000000000000000000000000..580f4691296394fcd53c12bee29335ed7eecb176 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/end.html @@ -0,0 +1,194 @@ + + + + + + 属性面板 + + + + + +
                                                            +
                                                              +
                                                            • 节点属性
                                                            • +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            基本属性
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            样式设置
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            拦截器
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/fork.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/fork.html new file mode 100644 index 0000000000000000000000000000000000000000..49a4dcebe3aa230e7f96f0dbac83f5d06e688f34 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/fork.html @@ -0,0 +1,116 @@ + + + + + + 属性面板 + + + + + +
                                                            +
                                                              +
                                                            • 节点属性
                                                            • +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            基本属性
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/import.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/import.html new file mode 100644 index 0000000000000000000000000000000000000000..fe5be2711f8ba9eb0cabbe0120bb20ba1e74cf69 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/import.html @@ -0,0 +1,75 @@ + + + + + 导入流程数据 + + + + +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/join.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/join.html new file mode 100644 index 0000000000000000000000000000000000000000..49a4dcebe3aa230e7f96f0dbac83f5d06e688f34 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/join.html @@ -0,0 +1,116 @@ + + + + + + 属性面板 + + + + + +
                                                            +
                                                              +
                                                            • 节点属性
                                                            • +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            基本属性
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/process.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/process.html new file mode 100644 index 0000000000000000000000000000000000000000..91ff9cb42723ac3745d5e64575ca7d0e9900b153 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/process.html @@ -0,0 +1,117 @@ + + + + + + 属性面板 + + + + + +
                                                            +
                                                              +
                                                            • 流程属性
                                                            • +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            基本属性
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/start.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/start.html new file mode 100644 index 0000000000000000000000000000000000000000..580f4691296394fcd53c12bee29335ed7eecb176 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/start.html @@ -0,0 +1,194 @@ + + + + + + 属性面板 + + + + + +
                                                            +
                                                              +
                                                            • 节点属性
                                                            • +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            基本属性
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            样式设置
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            拦截器
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/task.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/task.html new file mode 100644 index 0000000000000000000000000000000000000000..a95d359e4c2ab6130424c5c281ccf7f76b6858de --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/task.html @@ -0,0 +1,621 @@ + + + + + + 属性面板 + + + + + + +
                                                            +
                                                              +
                                                            • 节点属性
                                                            • +
                                                            • 流程设置
                                                            • +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            基本属性
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                            拦截器
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            审批设置
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            + +
                                                            审批模式
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            + + + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            扩展属性
                                                            +
                                                            +
                                                            + + 添加 + + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/transition.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/transition.html new file mode 100644 index 0000000000000000000000000000000000000000..14e19a5d35fde1934d325278a5fa92d3bf7adebb --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/transition.html @@ -0,0 +1,90 @@ + + + + + + 属性面板 + + + + + +
                                                            +
                                                              +
                                                            • 节点属性
                                                            • +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            基本属性
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/wfSubProcess.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/wfSubProcess.html new file mode 100644 index 0000000000000000000000000000000000000000..e69552522ffdec5ebbeed95fc1e2217ded2b1b6a --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/design/panel/wfSubProcess.html @@ -0,0 +1,199 @@ + + + + + + 属性面板 + + + + + +
                                                            +
                                                              +
                                                            • 节点属性
                                                            • +
                                                            • 流程设置
                                                            • +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            基本属性
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            样式设置
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + \ No newline at end of file diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/launchProcess.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/launchProcess.html new file mode 100644 index 0000000000000000000000000000000000000000..69432d568178cd5a245e1b62d81da4a005a8b0c5 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/launchProcess.html @@ -0,0 +1,240 @@ + + + + + + 发起流程 + + + + + + +
                                                            +
                                                              +
                                                            • 表单
                                                            • +
                                                            • 流程图
                                                            • +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                            + + +
                                                            +
                                                            + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/previewProcess.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/previewProcess.html new file mode 100644 index 0000000000000000000000000000000000000000..e9575450df6767a263771062472b3a7722fd7053 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/previewProcess.html @@ -0,0 +1,177 @@ + + + + + + 查看流程定义 + + + + + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                              +
                                                            • 流程图
                                                            • +
                                                            • 流程数据
                                                            • +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/surrogate.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/surrogate.html new file mode 100644 index 0000000000000000000000000000000000000000..752da268cccc16fc4332c306b96dff7cd8377a4e --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/common/surrogate.html @@ -0,0 +1,121 @@ + + + + + + + + 委托处理 + + + + + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/definition/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/definition/index.html new file mode 100644 index 0000000000000000000000000000000000000000..036d791933c954ba70a58c531eb89adac5d6f5a0 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/definition/index.html @@ -0,0 +1,340 @@ + + + + + + 流程定义 + + + + +
                                                            +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            + +
                                                            +
                                                            + +
                                                            + + + +
                                                            +
                                                            + 展开 + 收起 +
                                                            +
                                                            +
                                                            +
                                                            + + + +
                                                            +
                                                            +
                                                            +
                                                            +
                                                            + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/designer/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/designer/add.html new file mode 100644 index 0000000000000000000000000000000000000000..4b1f7b0e20f42d74b1877c0f7e7dcfb75efe300d --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/designer/add.html @@ -0,0 +1,232 @@ + + + + + 添加流程设计 + + + + + +
                                                            + +
                                                            +
                                                            +
                                                            + +
                                                            +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + + +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/designer/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/designer/index.html new file mode 100644 index 0000000000000000000000000000000000000000..2519d4f6ca8b1202fa37458abf7eda8a8c4381ee --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/designer/index.html @@ -0,0 +1,485 @@ + + + + + + 用户管理 + + + + + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + + + +
                                                              +
                                                              + 展开 + 收起 +
                                                              +
                                                              +
                                                              +
                                                              + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/favorite/add.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/favorite/add.html new file mode 100644 index 0000000000000000000000000000000000000000..78ab7af2e6e50146bdb3b4be2ba35057258612e6 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/favorite/add.html @@ -0,0 +1,237 @@ + + + + + 添加收藏 + + + +
                                                              +
                                                              + 集团流程库 +
                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/favorite/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/favorite/index.html new file mode 100644 index 0000000000000000000000000000000000000000..bea3f5cd05636ae1d2c7bf8804d6986312cbd6ec --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/favorite/index.html @@ -0,0 +1,284 @@ + + + + + + 我的收藏 + + + + +
                                                              +
                                                              + + + +
                                                              +
                                                              + +
                                                              + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/instance/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/instance/index.html new file mode 100644 index 0000000000000000000000000000000000000000..0bc886f37f5900fe39b182ad3db93b0ef01f9123 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/instance/index.html @@ -0,0 +1,438 @@ + + + + + + 发起的申请 + + + + + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + + + +
                                                              +
                                                              + 展开 + 收起 +
                                                              +
                                                              +
                                                              +
                                                              + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/instance/startProcess.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/instance/startProcess.html new file mode 100644 index 0000000000000000000000000000000000000000..d5cd5f8f3bd57d37860fcc63c5fcea5c6787a80e --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/instance/startProcess.html @@ -0,0 +1,401 @@ + + + + + + + + 发起申请 + + + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              +
                                                              +
                                                              + + + +   + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + +ss + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/monitoring/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/monitoring/index.html new file mode 100644 index 0000000000000000000000000000000000000000..124d55b597d14e2e8676f03d1eb47f4cccf1e44d --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/monitoring/index.html @@ -0,0 +1,432 @@ + + + + + + 流程追踪 + + + + + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + + + +
                                                              +
                                                              + 展开 + 收起 +
                                                              +
                                                              +
                                                              +
                                                              + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/task/done/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/task/done/index.html new file mode 100644 index 0000000000000000000000000000000000000000..1db8208e7fea4c0742d040dc5e7d9efca0435be7 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/task/done/index.html @@ -0,0 +1,372 @@ + + + + + + 我的已办 + + + + + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + + +
                                                              + + + +
                                                              +
                                                              + 展开 + 收起 +
                                                              +
                                                              +
                                                              +
                                                              + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/task/todo/index.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/task/todo/index.html new file mode 100644 index 0000000000000000000000000000000000000000..b04ec92075428f66ab80c339f722e83139670662 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/task/todo/index.html @@ -0,0 +1,430 @@ + + + + + + 我的待办 + + + + + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + + +
                                                              + + + +
                                                              +
                                                              + 展开 + 收起 +
                                                              +
                                                              +
                                                              +
                                                              + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/template/leaveForm.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/template/leaveForm.html new file mode 100644 index 0000000000000000000000000000000000000000..dd51d64f4ba81cd63ab53719eedf6309e5763097 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/template/leaveForm.html @@ -0,0 +1,140 @@ + + + + + + 请假申请表单 + + + + + + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + + +
                                                              +
                                                              +
                                                              + +
                                                              + + + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/template/reissueForm.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/template/reissueForm.html new file mode 100644 index 0000000000000000000000000000000000000000..5643e67cef7479f84f48874933ff7f701e8330ea --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/template/reissueForm.html @@ -0,0 +1,120 @@ + + + + + + 补卡审批单 + + + + + + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + + + + + + + + + + + diff --git a/demo/thinkphp/frontend/layui_admin_flow/view/wf/template/test.html b/demo/thinkphp/frontend/layui_admin_flow/view/wf/template/test.html new file mode 100644 index 0000000000000000000000000000000000000000..abc211f16130ba061d555987ad14722c0d7dae31 --- /dev/null +++ b/demo/thinkphp/frontend/layui_admin_flow/view/wf/template/test.html @@ -0,0 +1,28 @@ + + + + + 请假申请单 + + +
                                                              tewagfqadsgfasd测试
                                                              + + + + diff --git a/demo/webman/README.en.md b/demo/webman/README.en.md new file mode 100644 index 0000000000000000000000000000000000000000..d623cb3fa823558d1873f7e99b800b2775545c11 --- /dev/null +++ b/demo/webman/README.en.md @@ -0,0 +1,36 @@ +# webman_ingenious + +#### Description +{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**} + +#### Software Architecture +Software architecture description + +#### Installation + +1. xxxx +2. xxxx +3. xxxx + +#### Instructions + +1. xxxx +2. xxxx +3. xxxx + +#### Contribution + +1. Fork the repository +2. Create Feat_xxx branch +3. Commit your code +4. Create Pull Request + + +#### Gitee Feature + +1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md +2. Gitee blog [blog.gitee.com](https://blog.gitee.com) +3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) +4. The most valuable open source project [GVP](https://gitee.com/gvp) +5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) +6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/demo/webman/README.md b/demo/webman/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9538cd90d3fe97ce2b5999f2bf8ae57075af5c59 --- /dev/null +++ b/demo/webman/README.md @@ -0,0 +1,59 @@ +
                                                              +

                                                              webman

                                                              + +基于workerman开发的超高性能PHP框架 + + +

                                                              学习

                                                              + + + +
                                                              + +

                                                              赞助商

                                                              + +

                                                              特别赞助

                                                              + + + + +

                                                              铂金赞助

                                                              + + + +

                                                              金牌赞助

                                                              + + +
                                                              + + +
                                                              +

                                                              LICENSE

                                                              +The webman is open-sourced software licensed under the MIT. +
                                                              + +
                                                              + + diff --git a/demo/webman/backend/.gitignore b/demo/webman/backend/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..516299c34b89ba107234b9ab6dcf260c8c85629e --- /dev/null +++ b/demo/webman/backend/.gitignore @@ -0,0 +1,8 @@ +/runtime +/.idea +/.vscode +/vendor +*.log +.env +/tests/tmp +/tests/.phpunit.result.cache diff --git a/demo/webman/backend/LICENSE b/demo/webman/backend/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..2c6629291ce54a674ec680817983cc5cab06c113 --- /dev/null +++ b/demo/webman/backend/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 walkor and contributors (see https://github.com/walkor/webman/contributors) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/demo/webman/backend/app/BaseController.php b/demo/webman/backend/app/BaseController.php new file mode 100644 index 0000000000000000000000000000000000000000..40f9dd4bae9d31465cafedadcf3a8d697dc640cf --- /dev/null +++ b/demo/webman/backend/app/BaseController.php @@ -0,0 +1,53 @@ +request = request(); + $this->initialize(); + } + + /** + * @return mixed + */ + abstract protected function initialize(); + +} diff --git a/demo/webman/backend/app/adminapi/config/route.php b/demo/webman/backend/app/adminapi/config/route.php new file mode 100644 index 0000000000000000000000000000000000000000..62a1a2e0f9ba3375e30e769b3ca7ded85af02f5a --- /dev/null +++ b/demo/webman/backend/app/adminapi/config/route.php @@ -0,0 +1,16 @@ +name('用户登录'); + Route::get('/demo/user/page', [\app\adminapi\controller\LoginController::class, 'demoUser'])->name('演示用户列表'); + Route::post('/demo/user/act', [\app\adminapi\controller\LoginController::class, 'actUser'])->name('用户扮演'); +}); + diff --git a/demo/webman/backend/app/adminapi/controller/AuthController.php b/demo/webman/backend/app/adminapi/controller/AuthController.php new file mode 100644 index 0000000000000000000000000000000000000000..2061d4fe54c78e9ceb85f1e6164d047091494d53 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/AuthController.php @@ -0,0 +1,54 @@ +adminId = request()->adminId(); + $this->adminInfo = request()->adminInfo(); + $this->auth = request()->adminInfo['rules'] ?? []; + } +} diff --git a/demo/webman/backend/app/adminapi/controller/LoginController.php b/demo/webman/backend/app/adminapi/controller/LoginController.php new file mode 100644 index 0000000000000000000000000000000000000000..45387ef4a3d74900f5ed7634822b9b3d74898914 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/LoginController.php @@ -0,0 +1,100 @@ +services = new SystemAdminServices(); + } + + protected function initialize() + { + } + + public function login(Request $request): \support\Response + { + [$account, $password, $key, $captchaVerification, $captchaType] = $request->postMore([ + 'account', + 'pwd', + ['key', ''], + ['captchaVerification', ''], + ['captchaType', ''], + ], true); + + if ($captchaVerification != '') { + try { + aj_captcha_check_two($captchaType, $captchaVerification); + } catch (\Exception $e) { + return Json::fail($e->getMessage()); + } + } + if (strlen(trim($password)) < 6 || strlen(trim($password)) > 32) { + return Json::fail('账号密码必须是在6到32位之间'); + } + //导入验证器 + $validate = new \app\adminapi\validate\setting\SystemAdminValidata(); + if (!$validate->scene('get')->check(['account' => $account, 'pwd' => $password])) { + return Json::fail($validate->getError()); + } + $result = $this->services->login($account, $password, 'admin', $key); + if (!$result) { + return Json::fail('账号或密码错误', ['login_captcha' => 1]); + } + return Json::success($result); + } + + public function demoUser(Request $request): \support\Response + { + $where = $this->request->getMore([ + ['name', '', '', 'account_like'], + ['delete_time', null], + ['status', ''], + ['not_account', 'admin'], + ]); + $result = $this->services->getAdministratorsList($where); + //对密码进行销毁 + foreach ($result['list'] as $key => $value) { + unset($result['list'][$key]['pwd']); + } + return Json::success($result); + + } + + /** + * 角色扮演 + * + * @param \support\Request $request + * + * @return \support\Response + * @throws \ReflectionException + * @throws \app\exception\AdminException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function actUser(Request $request): \support\Response + { + $account = $request->input('account'); + if ($account === 'admin') { + return Json::fail('无法扮演超级管理员', ['login_captcha' => 1]); + } + if (empty($account)) { + return Json::fail('传入用户不存在', ['login_captcha' => 1]); + } + + $result = $this->services->login($account, md5('123456'), 'admin', '', false); + if (!$result) { + return Json::fail('账号或密码错误', ['login_captcha' => 1]); + } + return Json::success($result); + } + +} diff --git a/demo/webman/backend/app/adminapi/controller/file/SystemAttachment.php b/demo/webman/backend/app/adminapi/controller/file/SystemAttachment.php new file mode 100644 index 0000000000000000000000000000000000000000..645c9ef8624e31f2eaa8df5ad9b90ae359096bf0 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/file/SystemAttachment.php @@ -0,0 +1,221 @@ +service = Container::make(SystemAttachmentServices::class); + } + + /** + * 显示列表 + */ + public function index(Request $request): \support\Response + { + $where = $request->getMore([ + ['pid', 0], + ['real_name', ''], + ]); + return Json::success($this->service->getImageList($where)); + } + + /** + * 删除指定资源 + * + * @return \support\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function delete(Request $request): \support\Response + { + [$ids] = $request->postMore([ + ['ids', ''], + ], true); + $this->service->del($ids); + return Json::success(100002); + } + + /** + * 图片上传 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function upload(Request $request): \support\Response + { + [$pid, $file, $menuName] = $request->postMore([ + ['pid', '-1'], + ['file', 'file'], + ['name', ''], + ], true); + $upload_type = $request->input('upload_type', 0); + $type = $request->input('type', 0); + $res = $this->service->upload($pid, $file, $upload_type, $type, $menuName); + return Json::success('上传成功', ['src' => $res]); + } + + /** + * 移动图片 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function moveImageCate(Request $request): \support\Response + { + $data = $request->postMore([ + ['pid', 0], + ['images', ''], + ]); + $this->service->move($data); + return Json::success('移动成功'); + } + + /** + * 修改文件名 + * + * @param $id + * + * @return mixed + */ + public function update(Request $request): \support\Response + { + $realName = $request->input('real_name', ''); + $category = $request->input('pid', ''); + $id = $request->input('id'); + if (!$realName) { + return Json::fail(400104); + } + $data = ['real_name' => $realName]; + if ($category) { + $data['pid'] = $category; + } + $this->service->update($id, $data); + return Json::success('修改成功'); + } + + /** + * 获取上传类型 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function uploadType(Request $request): \support\Response + { + $data['upload_type'] = (string)sys_config('upload_type', 1); + return Json::success($data); + } + + /** + * 视频分片上传 + * + * @return mixed + */ + public function videoUpload(Request $request) + { + $data = $request->postMore([ + ['chunkNumber', 0],//第几分片 + ['currentChunkSize', 0],//分片大小 + ['chunkSize', 0],//总大小 + ['totalChunks', 0],//分片总数 + ['file', 'file'],//文件 + ['md5', ''],//MD5 + ['filename', ''],//文件名称 + ]); + $res = $this->service->videoUpload($data, $_FILES['file']); + return Json::success($res); + } + + /** + * 获取扫码上传页面链接以及参数 + * + * @return \support\Response + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/06/13 + */ + public function scanUploadQrcode(Request $request): \support\Response + { + [$pid] = $request->getMore([ + ['pid', 0], + ], true); + $uploadToken = md5(time()); + CacheService::set('scan_upload', $uploadToken, 600); + $url = sys_config('site_url') . '/app/upload?pid=' . $pid . '&token=' . $uploadToken; + return Json::success(['url' => $url]); + } + + /** + * 删除二维码 + * + * @return \support\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/6/26 + */ + public function removeUploadQrcode(Request $request): \support\Response + { + CacheService::delete('scan_upload'); + return Json::success(); + } + + /** + * 获取扫码上传的图片数据 + * + * @param \support\Request $request + * + * @return \support\Response + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/06/13 + */ + public function scanUploadImage(Request $request): \support\Response + { + return Json::success($this->service->scanUploadImage($request)); + } + + /** + * 网络图片上传 + * + * @param \support\Request $request + * + * @return \support\Response + * @throws \Exception + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/06/13 + */ + public function onlineUpload(Request $request): \support\Response + { + $data = $request->postMore([ + ['pid', 0], + ['images', []], + ]); + $this->service->onlineUpload($data); + return Json::success('上传成功'); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/file/SystemAttachmentCategory.php b/demo/webman/backend/app/adminapi/controller/file/SystemAttachmentCategory.php new file mode 100644 index 0000000000000000000000000000000000000000..1e55ed573b2b667947439f8341a0f10ea21c3b72 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/file/SystemAttachmentCategory.php @@ -0,0 +1,130 @@ +service = Container::make(SystemAttachmentCategoryServices::class); + } + + /** + * 显示资源列表 + * + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index(Request $request): \support\Response + { + $where = $this->request->getMore([ + ['name', ''], + ['pid', 0], + ['all', 0], + ]); + if ($where['name'] != '' || $where['all'] == 1) $where['pid'] = ''; + return Json::success($this->service->getAll($where)); + } + + /** + * 保存新增 + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function save(Request $request): \support\Response + { + $data = $this->request->postMore([ + ['pid', '-1'], + ['name', ''], + ['sort', 10], + ['remarks'], + ]); + if (!$data['name']) { + return Json::fail('请填写分类名称'); + } + $this->service->save($data); + return Json::success('添加成功'); + } + + /** + * 获取资源详情 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function read(Request $request): \support\Response + { + $id = $request->input('id'); + return Json::success($this->service->get($id)->toArray()); + } + + /** + * 保存更新的资源 + * + * @param \support\Request $request + * + * @return \support\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function update(Request $request): \support\Response + { + $data = $request->postMore([ + ['pid', '-1'], + ['name', ''], + ['sort', 10], + ['remarks', ''], + ]); + $id = $request->input('id'); + if (is_array($data['pid'])) $data['pid'] = end($data['pid']); + if (!$data['name']) { + return Json::fail('请填写分类名称'); + } + $info = $this->service->get($id); + $count = $this->service->count(['pid' => $id]); + if ($count && $info['pid'] != $data['pid']) return Json::fail('该分类有下级分类,无法修改上级'); + $this->service->update($id, $data); + return Json::success(100001); + } + + /** + * 删除指定资源 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function delete(Request $request): \support\Response + { + $id=$request->input('id'); + $this->service->del($id); + return Json::success('删除成功'); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/LangCode.php b/demo/webman/backend/app/adminapi/controller/setting/LangCode.php new file mode 100644 index 0000000000000000000000000000000000000000..5f4af20f8b9ba274d3a307e3c79a248c6b092295 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/LangCode.php @@ -0,0 +1,134 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\setting; + +use app\adminapi\controller\AuthController; +use app\common\Json; +use app\services\system\lang\LangCodeServices; +use support\Container; +use support\Request; + +class LangCode extends AuthController +{ + public function __construct() + { + parent::__construct(); + $this->services = Container::make(LangCodeServices::class); + } + + /** + * 获取语言列表 + * + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function langCodeList(Request $request): \support\Response + { + $where = $this->request->getMore([ + ['is_admin', 0], + ['type_id', 0], + ['code', ''], + ['remarks', ''], + ]); + return Json::success($this->services->langCodeList($where)); + } + + public function langCodeType(Request $request): \support\Response + { + return Json::success($this->services->langCodeType()); + } + + /** + * 获取语言详情 + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function langCodeInfo(Request $request): \support\Response + { + [$code] = $request->getMore([ + ['code', ''], + ], true); + return Json::success($this->services->langCodeInfo($code)); + } + + /** + * 新增语言 + * + * @return mixed + * @throws \Exception + */ + public function langCodeSave(Request $request): \support\Response + { + $data = $request->postMore([ + ['is_admin', 0], + ['code', ''], + ['remarks', ''], + ['edit', 0], + ['list', []], + ]); + $this->services->langCodeSave($data); + return Json::success('添加成功'); + } + + /** + * 修改语言 + * + * @return mixed + * @throws \Exception + */ + public function langCodeUpdate(Request $request): \support\Response + { + $data = $request->postMore([ + ['is_admin', 0], + ['code', ''], + ['remarks', ''], + ['edit', 1], + ['list', []], + ]); + $this->services->langCodeSave($data); + return Json::success('修改成功'); + } + + /** + * 删除语言 + * + * @param \support\Request $request + * + * @return mixed + */ + public function langCodeDel(Request $request): \support\Response + { + $id = $request->input('id'); + $this->services->langCodeDel($id); + return Json::success(100002); + } + + /** + * 机器翻译 + * + * @param \support\Request $request + * + * @return mixed + */ + public function langCodeTranslate(Request $request): \support\Response + { + [$text] = $request->postMore([ + ['text', ''], + ], true); + if ($text == '') return Json::fail('参数错误'); + return Json::success($this->services->langCodeTranslate($text)); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/LangCountry.php b/demo/webman/backend/app/adminapi/controller/setting/LangCountry.php new file mode 100644 index 0000000000000000000000000000000000000000..5906c9f9cdda1f987904194a3bcf205115a41caa --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/LangCountry.php @@ -0,0 +1,87 @@ +services = Container::make(LangCountryServices::class); + } + + /** + * 国家语言列表 + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function langCountryList(Request $request): \support\Response + { + $where = $request->getMore([ + ['keyword', ''], + ]); + return Json::success($this->services->langCountryList($where)); + } + + /** + * 获取地区详情 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function langCountryDetail(Request $request): \support\Response + { + $id = $request->input('id'); + return Json::success($this->services->get($id)->toArray()); + } + + /** + * 地区语言修改 + * + * @param \support\Request $request + * + * @return mixed + */ + public function langCountrySave(Request $request): \support\Response + { + $id = $request->input('id'); + $data = $request->postMore([ + ['name', ''], + ['code', ''], + ['type_id', 0], + ]); + $this->services->langCountrySave($id, $data); + return Json::success(100000); + } + + /** + * 地区语言删除 + * + * @param \support\Request $request + * + * @return mixed + */ + public function langCountryDel(Request $request): \support\Response + { + $id = $request->input('id'); + $this->services->langCountryDel($id); + return Json::success(100002); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/LangType.php b/demo/webman/backend/app/adminapi/controller/setting/LangType.php new file mode 100644 index 0000000000000000000000000000000000000000..b338bb1f1136bf6d46cd486fa47af0075cf09e7d --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/LangType.php @@ -0,0 +1,97 @@ +services = Container::make(LangTypeServices::class); + } + + /** + * 获取语言类型列表 + * + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function langTypeList(Request $request): \support\Response + { + $where = $this->request->getMore([ + ['language_name', ''], + ['file_name', ''], + ]); + return Json::success($this->services->langTypeList($where)); + } + + /** + * 添加语言类型详情 + * + * @param \support\Request $request + * + * @return mixed + */ + public function langTypeDetail(Request $request): \support\Response + { + $data = $request->getMore([['id']]); + return Json::success($this->services->get($data['id'])->toArray()); + } + + /** + * 保存语言类型 + * + * @return mixed + */ + public function langTypeSave(Request $request): \support\Response + { + $data = $this->request->postMore([ + ['id', 0], + ['language_name', ''], + ['file_name', ''], + ['is_default', 0], + ['status', 0], + ]); + $this->services->langTypeSave($data); + CacheService::delete('lang_type_data'); + return Json::success('保存成功'); + } + + /** + * 修改语言类型状态 + * + * + */ + public function langTypeStatus(Request $request): \support\Response + { + $data = $request->getParams([['id'], ['status']]); + $this->services->langTypeStatus($data['id'], $data['status']); + return Json::success('修改成功'); + } + + /** + * 删除语言类型 + * + * @param \support\Request $request + * + * @return mixed + */ + public function langTypeDel(Request $request): \support\Response + { + $id = $request->input('id'); + $this->services->langTypeDel($id); + CacheService::delete('lang_type_data'); + return Json::success('删除成功'); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/SystemAdmin.php b/demo/webman/backend/app/adminapi/controller/setting/SystemAdmin.php new file mode 100644 index 0000000000000000000000000000000000000000..b62da9191b10f3d915123308f7fb476a32bd79b7 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/SystemAdmin.php @@ -0,0 +1,288 @@ +services = Container::make(SystemAdminServices::class); + } + + /** + * 显示管理员资源列表 + */ + public function index(Request $request): \support\Response + { + $where = $this->request->getMore([ + ['name', '', '', 'account_like'], + ['delete_time', null], + ['status', ''], + ]); + return Json::success($this->services->getAdminList($where)); + } + + /** + * 显示创建表单页 + */ + public function create() + { + + } + + /** + * 保存管理员 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function save(Request $request): \support\Response + { + $data = $this->request->postMore([ + ['account', ''], + ['conf_pwd', ''], + ['pwd', ''], + ['real_name', ''], + ['status', 0], + ['address', ''], + ['cell_phone_number', ''], + ['email', ''], + ['sex', 0], + ['remark', ''], + ]); + if (!empty($data['pwd'])) { + $data['conf_pwd'] = $data['pwd']; + } + $this->validate($data, \app\adminapi\validate\setting\SystemAdminValidata::class); +// $data['level'] = $this->adminInfo['level'] + 1; + $this->services->create($data); + return Json::success(100000); + } + + /** + * 获取管理员详情 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function read(Request $request): \support\Response + { + $id = $request->input('id'); + $ret = $this->services->find($id); + if ($ret) { + unset($ret['pwd']); + return Json::success($ret); + } else { + return Json::fail($ret); + } + } + + /** + * 修改管理员信息 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function update(Request $request): \support\Response + { + $id = $request->input('id'); + $data = $request->postMore([ + ['account', ''], + ['conf_pwd', ''], + ['pwd', ''], + ['real_name', ''], + ['status', 0], + ['address', ''], + ['cell_phone_number', ''], + ['email', ''], + ['sex', 1], + ['remark', ''], + ]); + if (!empty($data['pwd'])) { + $data['conf_pwd'] = $data['pwd']; + } + $this->validate($data, \app\adminapi\validate\setting\SystemAdminValidata::class, 'update'); + if ($this->services->save($id, $data)) { + return Json::success(100001); + } else { + return Json::fail(100007); + } + } + + /** + * 删除管理员 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function delete(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id) return Json::fail(100100); + if ($this->services->update($id, ['delete_time' => time(), 'status' => 0])) + return Json::success(100002); + else + return Json::fail(100008); + } + + /** + * 批量删除管理员 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function batchUpdate(Request $request): \support\Response + { + $data = $this->request->post('data'); + if (empty($data)) { + return Json::fail(100100); + } + if ($this->services->batchUpdate(explode(',', $data), ['delete_time' => time(), 'status' => 0], 'id')) { + return Json::success(100002); + } else { + return Json::fail(100008); + } + } + + /** + * 修改状态 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function set_status(Request $request): \support\Response + { + $id = $request->input('id'); + $status = $request->input('status'); + if ($this->services->update($id, ['status' => $status])) { + return Json::success(100014); + } else { + return Json::fail(100007); + } + } + + public function setPosition(Request $request): \support\Response + { + $id = $request->input('id'); + $data = $request->postMore([ + ['account'], + ['dept_id'], + ['dept_name'], + ['post_id'], + ['post_name'], + ['real_name'], + ]); + $this->services->setPosition($id, $data); + return Json::success(100014); + } + + /** + * 获取当前登陆管理员的信息 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function info(Request $request): \support\Response + { + $result = $this->services->get($this->adminInfo['id'], ['*'])->toArray(); + unset($result['pwd']); + return Json::success($result); + } + + /** + * 修改当前登陆admin信息 + * + * @return \think\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function update_admin(Request $request): \support\Response + { + $data = $request->postMore([ + ['real_name', ''], + ['head_pic', ''], + ['address', ''], + ['email', ''], + ['pwd', ''], + ['cell_phone_number', ''], + ['remarks', ''], + ['sex', '1'], + ['new_pwd', ''], + ['conf_pwd', ''], + ]); + + if ($data['pwd']) { + if (!preg_match('/^(?![^a-zA-Z]+$)(?!\D+$).{6,}$/', $data['new_pwd'])) { + return Json::fail(400183); + } + } + + if ($this->services->updateAdmin($this->adminId, $data)) { + $this->services->cacheDriver()->clear(); + return Json::success(100001); + } else { + return Json::fail(100007); + } + } + + /** + * 修改当前登陆admin的文件管理密码 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function set_file_password(Request $request): \support\Response + { + $data = $request->postMore([ + ['file_pwd', ''], + ['conf_file_pwd', ''], + ]); + if (!preg_match('/^(?![^a-zA-Z]+$)(?!\D+$).{6,}$/', $data['file_pwd'])) { + return Json::fail(400183); + } + if ($this->services->setFilePassword($this->adminId, $data)) { + $this->services->cacheDriver()->clear(); + return Json::success(100001); + } else { + return Json::fail(100007); + } + } + + /** + * 退出登陆 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function logout(Request $request): \support\Response + { + $key = trim(ltrim($request->header(Config('cookie.token_name')), 'Bearer')); + CacheService::delete(md5($key)); + return Json::success(); + } + +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/SystemConfig.php b/demo/webman/backend/app/adminapi/controller/setting/SystemConfig.php new file mode 100644 index 0000000000000000000000000000000000000000..8937f8ea19b4e8452e58a0ae38c629e5e1ce3cbe --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/SystemConfig.php @@ -0,0 +1,452 @@ +services = Container::make(SystemConfigServices::class); + } + + /** + * 显示资源列表 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function index(Request $request): \support\Response + { + $where = $request->getMore([ + ['tab_id', ''], + ['status', -1], + ['info', ''], + ]); + if ($where['status'] == -1) { + unset($where['status']); + } + return Json::success($this->services->getConfigList($where)); + } + + /** + * 显示创建资源表单页. + * + * @return \support\Response + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ +// public function create() +// { +// [$type, $tabId] = $request->getMore([ +// [['type', 'd'], ''], +// [['tab_id', 'd'], 1], +// ], true); +// return Json::success($this->services->createFormRule($type, $tabId)); +// } + + /** + * 保存新建的资源 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function save(Request $request): \support\Response + { + $data = $request->postMore([ + ['menu_name', ''], + ['type', ''], + ['input_type', 'input'], + ['config_tab_id', 0], + ['parameter', ''], + ['upload_type', 1], + ['required', ''], + ['width', 0], + ['high', 0], + ['value', ''], + ['info', ''], + ['desc', ''], + ['sort', 0], + ['status', 0], + ]); + if (is_array($data['config_tab_id'])) $data['config_tab_id'] = end($data['config_tab_id']); + if (!$data['info']) return Json::fail(400274); + if (!$data['menu_name']) return Json::fail(400275); + if (!$data['desc']) return Json::fail(400276); + if ($data['sort'] < 0) { + $data['sort'] = 0; + } + if ($data['type'] == 'text') { + if (!$data['width']) return Json::fail(400277); + if ($data['width'] <= 0) return Json::fail(400278); + } + if ($data['type'] == 'textarea') { + if (!$data['width']) return Json::fail(400279); + if (!$data['high']) return Json::fail(400280); + if ($data['width'] < 0) return Json::fail(400281); + if ($data['high'] < 0) return Json::fail(400282); + } + if ($data['type'] == 'radio' || $data['type'] == 'checkbox') { + if (!$data['parameter']) return Json::fail(400283); + $this->services->valiDateRadioAndCheckbox($data); + } + $data['value'] = json_encode($data['value']); + $config = $this->services->getOne(['menu_name' => $data['menu_name']]); + if ($config) { + $this->services->update($config['id'], $data, 'id'); + } else { + $this->services->save($data); + } + CacheService::clear(); + return Json::success(400284); + } + + /** + * 显示指定的资源 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function read(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id) { + return Json::fail(100100); + } + $data = $this->services->get($id)->toArray(); + return Json::success($data); + } + + /** + * 显示编辑资源表单页. + * + * @param int $id + * + * @return \support\Response + */ +// public function edit(Request $request): \support\Response +// { +// return Json::success($this->services->editConfigForm((int)$id)); +// } + + /** + * 保存更新的资源 + * + * @param $id + * + * @return \support\Response + */ + public function update(Request $request): \support\Response + { + $type = $request->input('type'); + if ($type == 'text' || $type == 'textarea' || $type == 'radio' || ($type == 'upload' && (request()->post('upload_type') == 1 || request()->post('upload_type') == 3))) { + $value = request()->post('value'); + } else { + $value = request()->post('value/a'); + } + if (!$value) $value = request()->post(request()->post('menu_name')); + $data = $request->postMore([ + ['menu_name', ''], + ['type', ''], + ['input_type', 'input'], + ['config_tab_id', 0], + ['parameter', ''], + ['upload_type', 1], + ['required', ''], + ['width', 0], + ['high', 0], + ['value', $value], + ['info', ''], + ['desc', ''], + ['sort', 0], + ['status', 0], + ]); + if (is_array($data['config_tab_id'])) $data['config_tab_id'] = end($data['config_tab_id']); + if (!$this->services->get($id)) { + return Json::fail(100026); + } + $data['value'] = json_encode($data['value']); + $this->services->update($id, $data); + CacheService::clear(); + return Json::success(100001); + } + + /** + * 删除指定资源 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function delete(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$this->services->delete($id)) + return Json::fail(100008); + else { + CacheService::clear(); + return Json::success(100002); + } + } + + /** + * 修改状态 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function set_status(Request $request): \support\Response + { + $status = $request->input('status'); + $id = $request->input('id'); + if ($status == '' || $id == 0) { + return Json::fail(100100); + } + $this->services->update($id, ['status' => $status]); + CacheService::clear(); + return Json::success(100014); + } + + /** + * 批量删除 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function batch_delete(Request $request): \support\Response + { + $data = $request->post('data', []); + if (empty($data)) { + return Json::fail(100100); + } + + foreach ($data as $key => $value) { + $this->services->delete($value); + } + CacheService::clear(); + return Json::success(100002); + } + + /** + * 基础配置 + * */ + public function edit_basics(Request $request): \support\Response + { + $tabId = $request->param('tab_id', 1); + if (!$tabId) { + return Json::fail(100100); + } + $url = $request->baseUrl(); + return Json::success($this->services->getConfigForm($url, $tabId)); + } + + /** + * 保存数据 true + * */ +// public function save_basics(Request $request) +// { +// $post = $request->post(); +// foreach ($post as $k => $v) { +// if (is_array($v)) { +// $res = $this->services->getUploadTypeList($k); +// foreach ($res as $kk => $vv) { +// if ($kk == 'upload') { +// if ($vv == 1 || $vv == 3) { +// $post[$k] = $v[0]; +// } +// } +// } +// } +// } +// $this->validate($post, \app\adminapi\validate\setting\SystemConfigValidata::class); +// if (isset($post['upload_type'])) { +// $this->services->checkThumbParam($post); +// } +// if (isset($post['extract_type']) && !count($post['extract_type'])) { +// return Json::fail(400753); +// } +// if (isset($post['store_brokerage_binding_status'])) { +// $this->services->checkBrokerageBinding($post); +// } +// if (isset($post['store_brokerage_ratio']) && isset($post['store_brokerage_two'])) { +// $num = $post['store_brokerage_ratio'] + $post['store_brokerage_two']; +// if ($num > 100) { +// return Json::fail(400285); +// } +// } +// if (isset($post['spread_banner'])) { +// $num = count($post['spread_banner']); +// if ($num > 5) { +// return Json::fail(400286); +// } +// } +// if (isset($post['user_extract_min_price'])) { +// if (!preg_match('/[0-9]$/', $post['user_extract_min_price'])) { +// return Json::fail(400287); +// } +// } +// if (isset($post['wss_open'])) { +// $this->services->saveSslFilePath((int)$post['wss_open'], $post['wss_local_pk'] ?? '', $post['wss_local_cert'] ?? ''); +// } +// if (isset($post['store_brokerage_price']) && $post['store_brokerage_statu'] == 3) { +// if ($post['store_brokerage_price'] === '') { +// return Json::fail(400288); +// } +// if ($post['store_brokerage_price'] < 0) { +// return Json::fail(400289); +// } +// } +// if (isset($post['store_brokerage_binding_time']) && $post['store_brokerage_binding_status'] == 2) { +// if (!preg_match("/^[0-9][0-9]*$/", $post['store_brokerage_binding_time'])) { +// return Json::fail(400290); +// } +// } +// if (isset($post['uni_brokerage_price']) && $post['uni_brokerage_price'] < 0) { +// return Json::fail(400756); +// } +// if (isset($post['day_brokerage_price_upper']) && $post['day_brokerage_price_upper'] < -1) { +// return Json::fail(400757); +// } +// if (isset($post['pay_new_weixin_open']) && (bool)$post['pay_new_weixin_open']) { +// if (empty($post['pay_new_weixin_mchid'])) { +// return Json::fail(400763); +// } +// } +// if (isset($post['uni_brokerage_price']) && preg_match('/\.[0-9]{2,}[1-9][0-9]*$/', (string)$post['uni_brokerage_price']) > 0) { +// return Json::fail(500029); +// } +// +// if (isset($post['weixin_ckeck_file'])) { +// $from = public_path() . $post['weixin_ckeck_file']; +// $to = public_path() . array_reverse(explode('/', $post['weixin_ckeck_file']))[0]; +// @copy($from, $to); +// } +// if (isset($post['ico_path'])) { +// $from = public_path() . $post['ico_path']; +// $toAdmin = public_path('admin') . 'favicon.ico'; +// $toHome = public_path('home') . 'favicon.ico'; +// $toPublic = public_path() . 'favicon.ico'; +// @copy($from, $toAdmin); +// @copy($from, $toHome); +// @copy($from, $toPublic); +// } +// if (isset($post['reward_integral']) || isset($post['reward_money'])) { +// if ($post['reward_money'] < 0) return Json::fail('赠送余额不能小于0元'); +// if ($post['reward_integral'] < 0) return Json::fail('赠送积分不能小于0'); +// } +// +// if (isset($post['sign_give_point'])) { +// if (!is_int($post['sign_give_point']) || $post['sign_give_point'] < 0) return Json::fail('签到赠送积分请填写大于等于0的整数'); +// } +// if (isset($post['sign_give_exp'])) { +// if (!is_int($post['sign_give_exp']) || $post['sign_give_exp'] < 0) return Json::fail('签到赠送经验请填写大于等于0的整数'); +// } +// if (isset($post['integral_frozen'])) { +// if (!ctype_digit($post['integral_frozen']) || $post['integral_frozen'] < 0) return Json::fail('积分冻结天数请填写大于等于0的整数'); +// } +// if (isset($post['store_free_postage'])) { +// if (!is_int($post['store_free_postage']) || $post['store_free_postage'] < 0) return Json::fail('满额包邮请填写大于等于0的整数'); +// } +// if (isset($post['withdrawal_fee'])) { +// if ($post['withdrawal_fee'] < 0 || $post['withdrawal_fee'] > 100) return Json::fail('提现手续费范围在0-100之间'); +// } +// if (isset($post['routine_auth_type']) && count($post['routine_auth_type']) == 0) return Json::fail('微信和手机号登录开关至少开启一个'); +// if (isset($post['integral_max_num'])) { +// if (!ctype_digit($post['integral_max_num']) || $post['integral_max_num'] < 0) return Json::fail('积分抵扣上限请填写大于等于0的整数'); +// } +// if (isset($post['customer_phone'])) { +// if (!ctype_digit($post['customer_phone']) || strlen($post['customer_phone']) > 11) return Json::fail('客服手机号为11位数字'); +// } +// +// foreach ($post as $k => $v) { +// $config_one = $this->services->getOne(['menu_name' => $k]); +// if ($config_one) { +// $config_one['value'] = $v; +// $this->services->valiDateValue($config_one); +// $this->services->update($k, ['value' => json_encode($v)], 'menu_name'); +// } +// } +// CacheService::clear(); +// return Json::success(100001); +// +// } + + /** + * 获取系统设置头部分类 + * + * @return \support\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function header_basics(Request $request): \support\Response + { + [$type, $pid] = $request->getMore([ + [['type', 'd'], 0], + [['pid', 'd'], 0], + ], true); + if ($type == 3) {//其它分类 + $config_tab = []; + } else { + $services = Container::make(SystemConfigTabServices::class); + $config_tab = $services->getConfigTab($pid); + if (empty($config_tab)) $config_tab[] = $services->get($pid, ['id', 'id as value', 'title as label', 'pid', 'icon', 'type']); + } + return Json::success(compact('config_tab')); + } + + /** + * 获取单个配置的值 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function get_system(Request $request): \support\Response + { + $name = $request->input('name'); + $value = sys_config($name); + return Json::success(compact('value')); + } + + /** + * 获取某个分类下的所有配置 + * + * @param $tabId + * + * @return \support\Response + */ + public function get_config_list(Request $request): \support\Response + { + $tabId = $request->input('tabId'); + $list = $this->services->getConfigTabAllList($tabId); + $data = []; + foreach ($list as $item) { + $data[$item['menu_name']] = json_decode($item['value']); + } + return Json::success($data); + } + +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/SystemConfigTab.php b/demo/webman/backend/app/adminapi/controller/setting/SystemConfigTab.php new file mode 100644 index 0000000000000000000000000000000000000000..f0850a5bef564ec789d03fe23600440321053153 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/SystemConfigTab.php @@ -0,0 +1,150 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\setting; + +use app\adminapi\controller\AuthController; +use app\common\Json; +use app\services\system\config\SystemConfigServices; +use app\services\system\config\SystemConfigTabServices; +use support\Container; +use support\Request; + +/** + * 系统配置分类 + * + * @author Mr.April + * @since 1.0 + */ +class SystemConfigTab extends AuthController +{ + /** + * g构造方法 + * SystemConfigTab constructor. + */ + public function __construct() + { + parent::__construct(); + $this->services = Container::make(SystemConfigTabServices::class); + } + + /** + * 显示资源列表 + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index(Request $request): \support\Response + { + $where = $this->request->getMore([ + ['status', ''], + ['title', ''], + ]); + return Json::success($this->services->getConfgTabList($where)); + } + + /** + * 显示指定资源 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function read(Request $request): \support\Response + { + $id = $request->input('id'); + return Json::success($this->services->get($id)->toArray()); + } + + /** + * 保存新建的资源 + */ + public function save(Request $request): \support\Response + { + $data = $request->postMore([ + 'eng_title', + 'status', + 'title', + 'icon', + ['type', 0], + ['sort', 0], + ['pid', 0], + ]); + if (is_array($data['pid'])) $data['pid'] = end($data['pid']); + if (!$data['title']) return Json::fail(400291); + $this->services->save($data); + return Json::success(400292); + } + + /** + * 保存更新的资源 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function update(Request $request): \support\Response + { + $id = $request->input('id'); + $data = $this->request->postMore([ + 'title', + 'status', + 'eng_title', + 'icon', + ['type', 0], + ['sort', 0], + ['pid', 0], + ]); + if (is_array($data['pid'])) $data['pid'] = end($data['pid']); + if (!$data['title']) return Json::fail(400291); + if (!$data['eng_title']) return Json::fail(400275); + $this->services->update($id, $data); + return Json::success(100001); + } + + /** + * 删除指定资源 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function delete(Request $request): \support\Response + { + $services = Container::make(SystemConfigServices::class); + $id = $request->input('id'); + if ($services->count(['tab_id' => $id])) { + return Json::fail(400293); + } + if (!$this->services->delete($id)) + return Json::fail(100008); + else + return Json::success(100002); + } + + /** + * 修改状态 + * + * @param \support\Request $request + * + * @return mixed + */ + public function set_status(Request $request): \support\Response + { + $id = $request->input('id'); + $status = $request->input('status'); + if ($status == '' || $id == 0) { + return Json::fail(100100); + } + $this->services->update($id, ['status' => $status]); + return Json::success(100014); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/SystemDept.php b/demo/webman/backend/app/adminapi/controller/setting/SystemDept.php new file mode 100644 index 0000000000000000000000000000000000000000..7103a83499df7865c7adb8796f46fe12cd9b80fa --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/SystemDept.php @@ -0,0 +1,181 @@ +services = Container::make(SystemDeptServices::class); + } + + /** + * 显示资源列表 + * + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index(Request $request): \support\Response + { + $where = $this->request->getMore([ + ['status', ''], + ['keyword', ''], + ['dept_type', ''], + ]); + return Json::success($this->services->getList($where, ['*'])); + + } + + /** + * 获取一条信息 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function read(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id) { + return Json::fail(100026); + } + return Json::success($this->services->find($id)); + } + + /** + * 保存新建的资源 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function save(Request $request): \support\Response + { + $data = $this->request->postMore([ + ['dept_code'], + ['dept_name'], + ['dept_type', 1], + ['pid', '-1'], + ['icon', ''], + ['remarks', ''], + ['sort', 10], + ['status', 0], + ]); + + $message = [ + 'dept_name' => '部门名称不能为空', + ]; + + $this->validate($data, [ + 'dept_name' => 'require', + ], $message, true); + + if (!$this->services->save($data)) return Json::fail(100006); + $this->services->cacheDriver()->clear(); + return Json::success(100000); + + } + + /** + * 删除指定资源 + * + * @param \support\Request $request + * + * @return mixed + */ + public function delete(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id) { + return Json::fail(100100); + } + if (!$this->services->delete($id)) { + return Json::fail(100008); + } else { + $this->services->cacheDriver()->clear(); + return Json::success(100002); + } + } + + /** + * 修改部门 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function update(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id || !($role = $this->services->get($id))) { + return Json::fail(100026); + } + $data = $this->request->postMore([ + ['dept_code'], + ['dept_name'], + ['dept_type', 1], + ['pid', '-1'], + ['icon', ''], + ['remarks', ''], + ['sort', 10], + ['status', 0], + ]); + + $message = [ + 'dept_name' => '部门名称不能为空', + ]; + + $this->validate($data, [ + 'dept_name' => 'require', + ], $message, true); + + if ($this->services->update($id, $data)) { + return Json::success(100001); + } else { + return Json::fail(100007); + } + } + + /** + * 修改状态 + * + * @param \support\Request $request + * + * @return mixed + */ + public function set_status(Request $request): \support\Response + { + $id = $request->input('id'); + $status = $request->input('status'); + if (!$id) { + return Json::fail(100100); + } + $role = $this->services->get($id); + if (!$role) { + return Json::fail(400199); + } + $role->status = $status; + if ($role->save()) { + $this->services->cacheDriver()->clear(); + return Json::success(100001); + } else { + return Json::fail(100007); + } + } +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/SystemMenus.php b/demo/webman/backend/app/adminapi/controller/setting/SystemMenus.php new file mode 100644 index 0000000000000000000000000000000000000000..6ac726e67cf565d71d54193ebcbb4e17773ae95f --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/SystemMenus.php @@ -0,0 +1,349 @@ +services = Container::make(SystemMenusServices::class); + } + + /** + * 菜单展示列表 + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/05/06 + */ + public function index(Request $request): \support\Response + { + $where = $this->request->getMore([ + ['is_show', ''], + ['keyword', ''], + ['auth_type', ''], + ]); + return Json::success($this->services->getList($where, ['*'])); + } + + /** + * @param \support\Request $request + * + * @return \support\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/14 + */ + public function unique(Request $request): \support\Response + { + $adminInfo = $this->request->adminInfo(); + [$menus, $uniqueAuth] = Container::make(SystemMenusServices::class)->getMenusList($adminInfo['roles'], (int)$adminInfo['level']); + return Json::success(compact('menus', 'uniqueAuth')); + } + + /** + * 菜单获取 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function permission(Request $request): \support\Response + { + $adminInfo = $this->request->adminInfo(); + [$menus, $uniqueAuth] = Container::make(SystemMenusServices::class)->getMenusList($adminInfo['roles'] , (int)$adminInfo['level']); + return Json::success($menus); + } + + /** + * 保存菜单权限 + */ + public function save(Request $request): \support\Response + { + $data = $this->request->getMore([ + ['menu_name', ''], + ['controller', ''], + ['module', 'admin'], + ['action', ''], + ['icon', ''], + ['params', ''], + ['path', []], + ['menu_path', ''], + ['api_url', ''], + ['methods', ''], + ['unique_auth', ''], + ['header', ''], + ['is_header', 0], + ['pid', 0], + ['sort', 0], + ['auth_type', 0], + ['access', 1], + ['is_show', 0], + ['is_show_path', 0], + ]); + $data['is_show_path'] = $data['is_show']; + if (!$data['menu_name']) + return Json::fail(400198); + $data['path'] = implode('/', $data['path']); + if ($this->services->save($data)) { + return Json::success(100021); + } else { + return Json::fail(100022); + } + } + + /** + * 批量保存权限 + * + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/11 + */ + public function batchSave(Request $request): \support\Response + { + $menus = $this->request->post('menus', []); + if (!$menus) { + return Json::fail(100026); + } + $data = []; + + $uniqueAuthAll = $this->services->getColumn(['delete_time' => null, 'is_show' => 1], 'unique_auth'); + $uniqueAuthAll = array_filter($uniqueAuthAll, function ($item) { + return !!$item; + }); + $uniqueAuthAll = array_unique($uniqueAuthAll); + + $uniqueFn = function ($path) use ($uniqueAuthAll) { + $attPath = explode('/', $path); + $uniqueAuth = ''; + if ($attPath) { + $pathData = []; + foreach ($attPath as $vv) { + if (!str_contains($vv, '<')) { + $pathData[] = $vv; + } + } + $uniqueAuth = implode('-', $pathData); + } + + if (in_array($uniqueAuth, $uniqueAuthAll)) { + $uniqueAuth .= '-' . uniqid(); + } + + $uniqueAuthAll[] = $uniqueAuth; + + return $uniqueAuth; + }; + + foreach ($menus as $menu) { + if (empty($menu['menu_name'])) { + return Json::fail(400198); + } + if (isset($menu['unique_auth']) && $menu['unique_auth']) { + $menu['unique_auth'] = explode('/', $menu['api_url']); + } + $data[] = [ + 'methods' => $menu['method'], + 'menu_name' => $menu['menu_name'], + 'unique_auth' => !empty($menu['unique_auth']) ? $menu['unique_auth'] : $uniqueFn($menu['api_url']), + 'api_url' => $menu['api_url'], + 'pid' => $menu['path'], + 'auth_type' => 2, + 'is_show' => 1, + 'is_show_path' => 1, + ]; + } + $this->services->saveAll($data); + return Json::success(100021); + } + + /** + * 获取一条菜单权限信息 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function read(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id) { + return Json::fail(100026); + } + return Json::success($this->services->find($id)); + } + + /** + * 修改菜单权限表单获取 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function edit(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id) { + return Json::fail(100100); + } + return Json::success($this->services->updateMenus((int)$id)); + } + + /** + * 修改菜单 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function update(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id || !($menu = $this->services->get($id))) + return Json::fail(100026); + $data = $this->request->postMore([ + 'menu_name', + 'controller', + ['module', 'admin'], + 'action', + 'params', + ['icon', ''], + ['menu_path', ''], + ['api_url', ''], + ['methods', ''], + ['unique_auth', ''], + ['path', []], + ['sort', 0], + ['pid', 0], + ['is_header', 0], + ['header', ''], + ['auth_type', 0], + ['access', 1], + ['is_show', 0], + ['is_show_path', 0], + ]); + if (!$data['menu_name']) + return Json::fail(400198); + $data['path'] = implode('/', $data['path']); + if ($this->services->update($id, $data)) + return Json::success(100001); + else + return Json::fail(100007); + } + + /** + * 删除指定资源 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function delete(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id) { + return Json::fail(100100); + } + + if (!$this->services->delete($id)) { + return Json::fail(100008); + } else { + return Json::success(100002); + } + } + + /** + * 权限的开启和关闭,显示和隐藏 + * + * @param $id + * + * @return mixed + */ + public function show(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id) { + return Json::fail(100100); + } + + [$isShow, $isShowPath] = $request->postMore([['is_show', 0], ['is_show_path', 0]], true); + if ($isShow == -1) { + $res = $this->services->update($id, ['is_show_path' => $isShowPath]); + } else { + $res = $this->services->update($id, ['is_show' => $isShow, 'is_show_path' => $isShow]); + } + + if ($res) { + return Json::success(100001); + } else { + return Json::fail(100007); + } + } + + /** + * 获取菜单数据 + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function menus(Request $request): \support\Response + { + [$menus, $unique] = $this->services->getMenusList($this->adminInfo['roles'], (int)$this->adminInfo['level']); + return Json::success(['menus' => $menus, 'unique' => $unique]); + } + + /** + * 获取路由分类 + * + * @param \support\Request $request + * + * @return \support\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/25 + */ + public function ruleCate(Request $request): \support\Response + { + $service = Container::make(SystemRouteCateServices::class); + return Json::success($service->getAllList('adminapi')); + } + + /** + * 获取接口列表 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function ruleList(Request $request): \support\Response + { + $cateId = $request->input('cate_id', 0); + //获取所有的路由 + $services = Container::make(SystemRouteServices::class); + $ruleList = $services->selectList(['cate_id' => $cateId, 'app_name' => 'adminapi'])->toArray(); + return Json::success($ruleList); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/SystemMessage.php b/demo/webman/backend/app/adminapi/controller/setting/SystemMessage.php new file mode 100644 index 0000000000000000000000000000000000000000..6c6fe103be07b8809784f6661597f41c048c6a88 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/SystemMessage.php @@ -0,0 +1,29 @@ +getRootPath() . 'public/lms_admin/admin/data/message.json'); + $ret = !empty($data) ? json_decode($data, 1) : []; + return Json::success('Success',$ret); + } + +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/SystemPost.php b/demo/webman/backend/app/adminapi/controller/setting/SystemPost.php new file mode 100644 index 0000000000000000000000000000000000000000..106b735d1f362e3be90e00ac1023cd70c84c0255 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/SystemPost.php @@ -0,0 +1,153 @@ +services = Container::make(SystemPostServices::class); + } + + /** + * 显示资源列表 + * + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index(Request $request): \support\Response + { + $where = $request->getMore([ + ['dept_id', ''], + ['post_code', ''], + ['post_name', ''], + ]); + return Json::success($this->services->getList($where, ['*'])); + + } + + /** + * 获取一条信息 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function read(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id) { + return Json::fail(100026); + } + return Json::success($this->services->find($id)); + } + + /** + * 保存新建的资源 + */ + public function save(Request $request): \support\Response + { + $data = $request->postMore([ + 'post_code', + 'post_name', + ['dept_id'], + ['pid', '-1'], + ['icon', ''], + ['remarks', ''], + ['sort', 10], + ]); + + $message = [ + 'post_name' => '400187', + 'dept_id' => '所属部门不能为空', + ]; + + $this->validate($data, [ + 'dept_id' => 'require', + 'post_name' => 'require', + ], $message, true); + if (!$this->services->save($data)) { + return Json::fail(100006); + } + $this->services->cacheDriver()->clear(); + return Json::success(100000); + + } + + /** + * 修改角色 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function update(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id || !($role = $this->services->get($id))) { + return Json::fail(100026); + } + $data = $this->request->postMore([ + 'post_code', + 'post_name', + 'dept_id', + ['pid', '-1'], + ['icon', ''], + ['remarks', ''], + ['sort', 10], + ]); + $message = [ + 'post_name' => '400187', + 'dept_id' => '所属部门不能为空', + ]; + + $this->validate($data, [ + 'dept_id' => 'require', + 'post_name' => 'require', + ], $message, true); + + if ($this->services->update($id, $data)) { + return Json::success(100001); + } else { + return Json::fail(100007); + } + } + + /** + * 删除指定资源 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function delete(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id) { + return Json::fail(100100); + } + if (!$this->services->delete($id)) { + return Json::fail(100008); + } else { + $this->services->cacheDriver()->clear(); + return Json::success(100002); + } + } + +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/SystemRole.php b/demo/webman/backend/app/adminapi/controller/setting/SystemRole.php new file mode 100644 index 0000000000000000000000000000000000000000..c1a889317f1498ef1f064ec19019b2b0ed1eb349 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/SystemRole.php @@ -0,0 +1,176 @@ +services = Container::make(SystemRoleServices::class); + } + + /** + * 显示资源列表 + * + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function index(Request $request): \support\Response + { + $where = $this->request->getMore([ + ['status', ''], + ['role_name', ''], + ]); + return Json::success($this->services->getRoleList($where)); + } + + /** + * 获取一条角色信息 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function read(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id) { + return Json::fail(100026); + } + return Json::success($this->services->find($id)); + } + + /** + * 保存新建的资源 + */ + public function save(Request $request): \support\Response + { + + $data = $request->postMore([ + 'role_code', + 'role_name', + ['pid', '-1'], + ['icon', ''], + ['remarks', ''], + ['sort', 10], + ['status', 0], + ]); + + $message = [ + 'role_name' => '400220', + ]; + + $this->validate($data, [ + 'role_name' => 'require', + ], $message, true); + + if (!$this->services->save($data)) return Json::fail(400223); + $this->services->cacheDriver()->clear(); + return Json::success(400222); + + } + + /** + * 删除指定资源 + * + * @param \support\Request $request + * + * @return mixed + */ + public function delete(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id) { + return Json::fail(100100); + } + if (!$this->services->delete($id)) { + return Json::fail(100008); + } else { + $this->services->cacheDriver()->clear(); + return Json::success(100002); + } + } + + /** + * 修改角色 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function update(Request $request): \support\Response + { + $id = $request->input('id'); + if (!$id || !($role = $this->services->get($id))) { + return Json::fail(100026); + } + $data = $this->request->postMore([ + 'role_code', + 'role_name', + ['pid', '-1'], + ['icon', ''], + ['remarks', ''], + ['sort', 10], + ['status', 0], + ]); + if (!$data['role_name']) { + return Json::fail(400220); + } + if ($this->services->update($id, $data)) { + return Json::success(100001); + } else { + return Json::fail(100007); + } + } + + /** + * 修改状态 + * + * @param \support\Request $request + * + * @return mixed + */ + public function set_status(Request $request): \support\Response + { + $id = $request->input('id'); + $status = $request->input('status'); + if (!$id) { + return Json::fail(100100); + } + $role = $this->services->get($id); + if (!$role) { + return Json::fail(400199); + } + $role->status = $status; + if ($role->save()) { + $this->services->cacheDriver()->clear(); + return Json::success(100001); + } else { + return Json::fail(100007); + } + } + + public function menuList(Request $request): \support\Response + { + $services = Container::make(SystemMenusServices::class); + $menus = $services->getMenus($this->adminInfo['level'] == 0 ? [] : $this->adminInfo['role_id']); + return Json::success($menus); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/SystemRoleDept.php b/demo/webman/backend/app/adminapi/controller/setting/SystemRoleDept.php new file mode 100644 index 0000000000000000000000000000000000000000..e8c027f86aea5e20f776d40cf2cea4d290f968b0 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/SystemRoleDept.php @@ -0,0 +1,50 @@ +services = Container::make(SystemRoleDeptServices::class); + } + + /** + * 保存新建的资源 + * + */ + public function save(Request $request): \support\Response + { + $data = $this->request->postMore([ + 'role_id', + 'role_name', + ['checked_dept', []], + ]); + + $message = [ + 'role_id' => '100100', + ]; + + $this->validate($data, [ + 'role_id' => 'require', + ], $message, true); + + if (!$this->services->create($data)) return Json::fail(400223); + $this->services->cacheDriver()->clear(); + return Json::success(400222); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/SystemRoleMenu.php b/demo/webman/backend/app/adminapi/controller/setting/SystemRoleMenu.php new file mode 100644 index 0000000000000000000000000000000000000000..47a194e138b79a310a7ce7d4fc28c41da8a71cb4 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/SystemRoleMenu.php @@ -0,0 +1,49 @@ +services = Container::make(SystemRoleMenuServices::class); + } + + /** + * 保存新建的资源 + */ + public function save(Request $request): \support\Response + { + $data = $this->request->postMore([ + 'role_id', + 'role_name', + ['checked_menus', []], + ]); + + $message = [ + 'role_id' => '100100', + ]; + + $this->validate($data, [ + 'role_id' => 'require', + ], $message, true); + + if (!$this->services->create($data)) return Json::fail(400223); + $this->services->cacheDriver()->clear(); + return Json::success(400222); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/setting/SystemRolePost.php b/demo/webman/backend/app/adminapi/controller/setting/SystemRolePost.php new file mode 100644 index 0000000000000000000000000000000000000000..9abeaa6a0b7307926daba186c99a623c0d841198 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/setting/SystemRolePost.php @@ -0,0 +1,50 @@ +services = Container::make(SystemRolePostServices::class); + } + + /** + * 保存新建的资源 + * + * @throws \Exception + */ + public function save(Request $request): \support\Response + { + $data = $this->request->postMore([ + 'role_id', + 'role_name', + ['checked_post', []], + ]); + $message = [ + 'role_id' => '100100', + ]; + + $this->validate($data, [ + 'role_id' => 'require', + ], $message, true); + + if (!$this->services->create($data)) return Json::fail(400223); + $this->services->cacheDriver()->clear(); + return Json::success(400222); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/system/Clear.php b/demo/webman/backend/app/adminapi/controller/system/Clear.php new file mode 100644 index 0000000000000000000000000000000000000000..dcf6a88fcb681a6fc6d5e0e6358a4e6439ca81d4 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/system/Clear.php @@ -0,0 +1,53 @@ + +// +---------------------------------------------------------------------- +namespace app\adminapi\controller\system; + +use app\common\Json; +use app\services\system\log\ClearServices; +use app\adminapi\controller\AuthController; +use support\Container; +use support\Request; + +/** + * + * 缓存控制类 + * @author Mr.April + * @since 1.0 + */ +class Clear extends AuthController +{ + public function __construct() + { + parent::__construct(); + $this->services = Container::make(ClearServices::class); + } + + /** + * 刷新数据缓存 + */ + public function refresh_cache(Request $request): \support\Response + { + $this->services->refresCache(); + return Json::success(400302); + } + + + /** + * 删除日志 + */ + public function delete_log(Request $request): \support\Response + { + $this->services->deleteLog(); + return Json::success(100002); + } +} + + diff --git a/demo/webman/backend/app/adminapi/controller/system/SystemCrontab.php b/demo/webman/backend/app/adminapi/controller/system/SystemCrontab.php new file mode 100644 index 0000000000000000000000000000000000000000..9362668b7729156a27a09610a73ae6eb149d5683 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/system/SystemCrontab.php @@ -0,0 +1,114 @@ +services = Container::make(SystemCrontabServices::class); + } + + /** + * 获取定时任务列表 + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function getTimerList(Request $request): \support\Response + { + + $where = ['delete_time' => null]; + return Json::success($this->services->getTimerList($where)); + } + + /** + * 获取定时任务详情 + * + * @param \support\Request $request + * + * @return mixed + */ + public function getTimerInfo(Request $request): \support\Response + { + $id = $request->input('id'); + return Json::success($this->services->getTimerInfo($id)); + } + + /** + * 获取定时任务类型 + * + * @return mixed + */ + public function getMarkList(Request $request): \support\Response + { + return Json::success($this->services->getMarkList()); + } + + /** + * 保存更新定时任务 + * + * @return mixed + */ + public function saveTimer(Request $request): \support\Response + { + $data = $this->request->postMore([ + ['id', 0], + ['name', ''], + ['mark', ''], + ['content', ''], + ['type', 0], + ['is_open', 0], + ['week', 0], + ['day', 0], + ['hour', 0], + ['minute', 0], + ['second', 0], + ]); + $this->services->saveTimer($data); + return Json::success(100000); + } + + /** + * 删除定时任务 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function delTimer(Request $request): \support\Response + { + $id = $request->input('id'); + $this->services->delTimer($id); + return Json::success(100002); + } + + /** + * 设置定时任务状态 + * + * @param \support\Request $request + * + * @return mixed + */ + public function setTimerStatus(Request $request): \support\Response + { + $id = $request->input('id'); + $is_open = $request->input('is_open'); + $this->services->setTimerStatus($id, $is_open); + return Json::success(100014); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/system/SystemDatabackup.php b/demo/webman/backend/app/adminapi/controller/system/SystemDatabackup.php new file mode 100644 index 0000000000000000000000000000000000000000..94bc9685851a916ebad1788f03fc8248441c9000 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/system/SystemDatabackup.php @@ -0,0 +1,177 @@ +services = Container::make(SystemDatabackupServices::class); + } + + /** + * 获取数据库表 + */ + public function index(Request $request): \support\Response + { + return Json::success($this->services->getDataList()); + } + + /** + * 查看表结构 详情 + */ + public function read(Request $request): \support\Response + { + $tablename = $request->input('tablename', ''); + return Json::success($this->services->getRead($tablename)); + } + + /** + * 更新数据表或者表字段备注 + * + * @param \support\Request $request + * + * @return \support\Response + * @throws \think\db\exception\BindParamException + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/04/11 + */ + public function updateMark(Request $request): \support\Response + { + [$table, $field, $type, $mark, $is_field] = $request->postMore([ + ['table', ''], + ['field', ''], + ['type', ''], + ['mark', ''], + ['is_field', 0], + ], true); + if ($is_field == 0) { + $sql = "ALTER TABLE $table COMMENT '$mark'"; + } else { + $sql = "ALTER TABLE $table MODIFY COLUMN $field $type COMMENT '$mark'"; + } + Db::execute($sql); + return Json::success(100024); + } + + /** + * 优化表 + */ + public function optimize(Request $request): \support\Response + { + $tables = $this->request->param('tables', '', 'htmlspecialchars'); + $res = $this->services->getDbBackup()->optimize($tables); + return Json::success($res ? 100047 : 100048); + } + + /** + * 修复表 + */ + public function repair(Request $request): \support\Response + { + $tables = $request->input('tables', ''); + $res = $this->services->getDbBackup()->repair($tables); + return Json::success($res ? 100049 : 100050); + } + + /** + * 备份表 + */ + public function backup(Request $request): \support\Response + { + $tables = $request->input('tables', ''); + $data = $this->services->backup($tables); + return Json::success(100051); + } + + /** + * 获取备份记录表 + */ + public function fileList(Request $request): \support\Response + { + return Json::success($this->services->getBackup()); + } + + /** + * 删除备份记录表 + */ + public function delFile(Request $request): \support\Response + { + $filename = intval(request()->post('filename')); + $files = $this->services->getDbBackup()->delFile($filename); + return Json::success(100002); + } + + /** + * 导入备份记录表 + */ + public function import(Request $request): \support\Response + { + [$part, $start, $time] = $this->request->postMore([ + [['part', 'd'], 0], + [['start', 'd'], 0], + [['time', 'd'], 0], + ], true); + $db = $this->services->getDbBackup(); + if (is_numeric($time) && !$start) { + $list = $db->getFile('timeverif', $time); + if (is_array($list)) { + session::set('backup_list', $list); + return Json::success(400307, array('part' => 1, 'start' => 0)); + } else { + return Json::fail(400308); + } + } else if (is_numeric($part) && is_numeric($start) && $part && $start) { + $list = session::get('backup_list'); + $start = $db->setFile($list)->import($start); + if (false === $start) { + return Json::fail(400309); + } elseif (0 === $start) { + if (isset($list[++$part])) { + $data = array('part' => $part, 'start' => 0); + return Json::success(400310, $data); + } else { + session::delete('backup_list'); + return Json::success(400311); + } + } else { + $data = array('part' => $part, 'start' => $start[0]); + if ($start[1]) { + $rate = floor(100 * ($start[0] / $start[1])); + return Json::success(400310, $data); + } else { + $data['gz'] = 1; + return Json::success(400310, $data); + } + } + } else { + return Json::fail(100100); + } + } + + /** + * 下载备份记录表 + */ + public function downloadFile(Request $request): \support\Response + { + $time = intval(request()->param('time')); + return Json::success(['key' => $this->services->getDbBackup()->downloadFile($time, 0, true)]); + } + +} diff --git a/demo/webman/backend/app/adminapi/controller/system/SystemDict.php b/demo/webman/backend/app/adminapi/controller/system/SystemDict.php new file mode 100644 index 0000000000000000000000000000000000000000..0f3dc72b5142e55d75cd9bb5acea9b53ce7f3152 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/system/SystemDict.php @@ -0,0 +1,169 @@ +services = Container::make(SystemDictServices::class); + } + + /** + * index + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function index(Request $request): \support\Response + { + $where = $request->getMore([['name', '']]); + return Json::success($this->services->getDictList($where)); + } + + /** + * 添加字典 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function save(Request $request): \support\Response + { + $data = $request->postMore([ + ['name', ''], + ['value', ''], + ]); + + $message = [ + 'name' => '400220', + ]; + $this->validate($data, [ + 'name' => 'require', + ], $message, true); + if ($this->services->saveDict($data['name'], $data['value'])) { + return Json::success(100000); + } else { + return Json::fail(100006); + } + } + + /** + * 获取详情 + * + * @param \support\Request $request + * + * @return mixed + */ + public function read(Request $request): \support\Response + { + $id = $request->input('id'); + if (empty($id)) { + return Json::fail(100100); + } + return Json::success($this->services->read($id)); + } + + /** + * 更新 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function update(Request $request): \support\Response + { + $id = $request->input('id'); + if (empty($id)) { + return Json::fail(100100); + } + $data = $request->postMore([ + ['name', ''], + ['value', ''], + ]); + + $message = [ + 'name' => '400220', + ]; + $this->validate($data, [ + 'name' => 'require', + ], $message, true); + + if ($this->services->updateDict($id, $data)) { + return Json::success(100000); + } else { + return Json::fail(100006); + } + + } + + /** + * 删除字典 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function delete(Request $request): \support\Response + { + $id = $request->input('id'); + if (empty($id)) { + return Json::fail(100100); + } + if ($this->services->delete($id, 'id')) { + return Json::success(100002); + } else { + return Json::fail(100008); + } + } + + /** + * 批量删除 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function batchDelete(Request $request): \support\Response + { + $data = $request->input('data', []); + if (empty($data)) { + return Json::fail(100100); + } + foreach ($data as $value) { + $this->services->delete($value, 'id'); + } + return Json::success(100002); + } + + /** + * 获取字典详情 + * + * @param \support\Request $request + * + * @return \support\Response + */ + public function get(Request $request): \support\Response + { + $name = $request->input('name'); + $data = $this->services->getName($this->services->dictNameToOptionName($name)); + $data['value'] = json_decode($data['value']); + return Json::success($data); + } + +} diff --git a/demo/webman/backend/app/adminapi/controller/system/SystemLog.php b/demo/webman/backend/app/adminapi/controller/system/SystemLog.php new file mode 100644 index 0000000000000000000000000000000000000000..82af2684f3e76c1715a454db8a2c5c8c0d925cf4 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/system/SystemLog.php @@ -0,0 +1,54 @@ +services = Container::make(SystemLogServices::class); + $this->services->deleteLog(); + } + + /** + * 显示操作记录 + */ + public function index(Request $request): \support\Response + { + $where = $this->request->getMore([ + ['pages', ''], + ['path', ''], + ['ip', ''], + ['admin_id', ''], + ['data', '', '', 'time'], + ]); + return Json::success($this->services->getLogList($where, (int)$this->adminInfo['level'])); + } + + public function search_admin(Request $request): \support\Response + { + $services = Container::make(SystemAdminServices::class); + $info = $services->getOrdAdmin('id,real_name', $this->adminInfo['level']); + return Json::success(compact('info')); + } + +} + diff --git a/demo/webman/backend/app/adminapi/controller/system/SystemRoute.php b/demo/webman/backend/app/adminapi/controller/system/SystemRoute.php new file mode 100644 index 0000000000000000000000000000000000000000..41ec8288d0dded5d7af762b0747d43651c081519 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/system/SystemRoute.php @@ -0,0 +1,166 @@ +services = Container::make(SystemRouteServices::class); + } + + /** + * 同步路由权限 + * + * @param \support\Request $request + * + * @return \support\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function syncRoute(Request $request): \support\Response + { + $appName = $request->input('appName', 'adminapi'); + $this->services->syncRoute($appName); + + return Json::success(100038); + } + + /** + * 列表数据 + * + * @param \support\Request $request + * + * @return \support\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function index(Request $request): \support\Response + { + $where = $request->getMore([ + ['name_like', ''], + ['app_name', 'adminapi'], + ]); + + return Json::success($this->services->getList($where)); + } + + /** + * tree数据 + * + * @param \support\Request $request + * + * @return \support\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function tree(Request $request): \support\Response + { + [$name, $appName] = $request->getMore([ + ['name_like', ''], + ['app_name', 'adminapi'], + ], true); + + return Json::success($this->services->getTreeList($appName, $name)); + } + + /** + * @param \support\Request $request + * + * @return \support\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function save(Request $request): \support\Response + { + $id = $request->input('id', 0); + $data = $this->request->postMore([ + ['cate_id', 0], + ['name', ''], + ['path', ''], + ['method', ''], + ['type', 0], + ['app_name', ''], + ['request', []], + ['response', []], + ['request_example', []], + ['response_example', []], + ['describe', ''], + ]); + +// if (!$data['name']) { +// return Json::fail(500031); +// } +// if (!$data['path']) { +// return Json::fail(500032); +// } +// if (!$data['method']) { +// return Json::fail(500033); +// } +// if (!$data['app_name']) { +// return Json::fail(500034); +// } + if ($id) { + $this->services->update($id, $data); + } else { + $data['add_time'] = date('Y-m-d H:i:s'); + $this->services->save($data); + } + $this->services->cacheDriver()->clear(); + + return Json::success($id ? 100001 : 100021); + } + + /** + * @param \support\Request $request + * + * @return \support\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function read(Request $request): \support\Response + { + $id = $request->input('id'); + return Json::success($this->services->getInfo((int)$id)); + } + + /** + * @param $id + * + * @return \support\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function delete(Request $request): \support\Response + { + $id=$request->input('id'); + if (!$id) { + return Json::fail(500035); + } + $this->services->destroy($id); + return Json::success(100002); + } + +} diff --git a/demo/webman/backend/app/adminapi/controller/system/SystemRouteCate.php b/demo/webman/backend/app/adminapi/controller/system/SystemRouteCate.php new file mode 100644 index 0000000000000000000000000000000000000000..15a0bc9b3dc9f86825342878c15493c12aaa6f26 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/system/SystemRouteCate.php @@ -0,0 +1,145 @@ +services = Container::make(SystemRouteCateServices::class); + } + + /** + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function index(Request $request): \support\Response + { + return Json::success($this->services->getAllList()); + } + + /** + * @param \support\Request $request + * + * @return \support\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function create(Request $request): \support\Response + { + return Json::success($this->services->getFrom(0, $this->request->get('app_name', 'adminapi'))); + } + + /** + * @param Request $request + * + * @return \support\Response + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function save(Request $request): \support\Response + { + $data = $request->postMore([ + ['path', []], + ['name', ''], + ['sort', 0], + ['app_name', ''], + ]); + + if (!$data['name']) { + return Json::fail(500037); + } + + $data['add_time'] = time(); + $data['pid'] = $data['path'][count($data['path']) - 1] ?? 0; + $this->services->save($data); + + return Json::success(100000); + + } + + /** + * @param \support\Request $request + * + * @return \support\Response + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function edit(Request $request): \support\Response + { + $id = $request->input('id'); + return Json::success($this->services->getFrom($id, $this->request->get('app_name', 'adminapi'))); + } + + /** + * @param Request $request + * + * @return \support\Response + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function update(Request $request): \support\Response + { + $id = $request->input('id'); + $data = $request->postMore([ + ['path', []], + ['name', ''], + ['sort', 0], + ['app_name', ''], + ]); + + if (!$data['name']) { + return Json::fail(500037); + } + + $data['pid'] = $data['path'][count($data['path']) - 1] ?? 0; + $this->services->update($id, $data); + + return Json::success(100001); + } + + /** + * @param \support\Request $request + * + * @return \support\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function delete(Request $request): \support\Response + { + $service = Container::make(SystemRouteServices::class); + $id = $request->input('id'); + if (!$id) { + return Json::fail(500035); + } + if ($service->count(['cate_id' => $id])) { + return Json::fail(500038); + } + $this->services->delete($id); + + return Json::success(100002); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/wf/CategoryController.php b/demo/webman/backend/app/adminapi/controller/wf/CategoryController.php new file mode 100644 index 0000000000000000000000000000000000000000..021c23182f8d535315576bcd5d421cb7d8df3e15 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/wf/CategoryController.php @@ -0,0 +1,139 @@ +service = new ProcessEngines(new ConfigurationRewrite([])); + } + + public function select(Request $request): \support\Response + { + $param = $request->getMore([ + ['status', ''], + ['name', ''], + ['is_del', 0], + ['page', 1], + ['limit', 15], + ]); + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processTypesService()->page((object)[]); + return Json::success('获取成功', $result); + } + + public function typeTree(Request $request): \support\Response + { + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processTypesService()->selectTree((object)[]); + return Json::success($result); + + } + + public function read(Request $request): \support\Response + { + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processTypesService()->findById($request->input('id')); + if ($result) { + return Json::success($result->toArray()); + } else { + return Json::fail('参数错误'); + } + } + + public function update(Request $request): \support\Response + { + $id = $request->input('id'); + $ingeniousEngines = $this->service; + if (!$id || !($ingeniousEngines->processTypesService()->findById($id))) { + return Json::fail('资源不存在'); + } + $data = $request->postMore([ + ['id', $id], + ['name', ''], + ['icon', ''], + ['pid', '0'], + ['remark', ''], + ['sort', 10], + ['user_id', $request->adminId()], + ]); + if ($ingeniousEngines->processTypesService()->update((object)$data)) { + return Json::success('更新成功'); + } else { + return Json::fail('更新失败'); + } + + } + + public function delete(Request $request): \support\Response + { + $id = $request->input('id'); + $ingeniousEngines = $this->service; + if (!$id) return Json::fail('参数ID不能为空'); + try { + $ingeniousEngines->processTypesService()->del($id); + return Json::success('删除成功'); + } catch (LFlowException $e) { + return Json::fail('删除失败' . $e->getMessage()); + } + + } + + public function remove(Request $request): \support\Response + { + $ids = $request->input('data'); + if (!$ids) return Json::fail('参数ID不能为空'); + $ingeniousEngines = $this->service; + try { + $ingeniousEngines->processTypesService()->del(explode(',', $ids)); + return Json::success('删除成功'); + } catch (LFlowException $e) { + return Json::fail('删除失败' . $e->getMessage()); + } + + } + + public function save(Request $request): \support\Response + { + $ingeniousEngines = $this->service; + $data = $request->postMore([ + ['name', ''], + ['pid', '0'], + ['icon', ''], + ['remark', ''], + ['sort', 10], + ['create_user', $request->adminId()], + ]); + if (empty($data['name'])) { + return Json::fail('名称不能为空'); + } + if ($ingeniousEngines->processTypesService()->create((object)$data)) { + return Json::success('创建成功'); + } else { + return Json::fail('创建失败'); + } + } +} + diff --git a/demo/webman/backend/app/adminapi/controller/wf/DefineController.php b/demo/webman/backend/app/adminapi/controller/wf/DefineController.php new file mode 100644 index 0000000000000000000000000000000000000000..2badd64a3587ba63b2979a11f17a58ee1b45348c --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/wf/DefineController.php @@ -0,0 +1,170 @@ + new LoginUserHolder(request()), + 'findUserApi' => new UserProcessingApi(), + ]; + + $this->service = new ProcessEngines(new ConfigurationRewrite($config)); + } + + public function index(Request $request): \support\Response + { + $args = $request->getMore([ + ['id', ''], + ['type_id', ''], + ['name', ''], + ['display_name', ''], + ['instance_url', ''], + ['state', ''],//默认全部 + ['version', ''], + ['creator', ''], + ['page', 0], + ['limit', 0], + ]); + $favoriteParam = [ + 'user_id' => $request->adminId(), + 'favorite' => 1, + 'page' => 0, + 'limit' => 0, + ]; + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processDefineService()->page((object)$args); + $favorite = $ingeniousEngines->processDefineService()->favoritePage((object)$favoriteParam); + $favoriteData = isset($favorite['list']) && !empty($favorite['list']) ? $favorite['list'] : []; + + //匹配是否为收藏的流程 + foreach ($result['list'] as $key => $value) { + foreach ($favoriteData as $val) { + $result['list'][$key]['favorite'] = 0; + $result['list'][$key]['process_define_favorite_id'] = ''; + if ($value['id'] === $val['process_define_id']) { + $result['list'][$key]['favorite'] = 1; + $result['list'][$key]['process_define_favorite_id'] = $val['id']; + continue; + } + } + } + return Json::success($result); + } + + public function read(Request $request): \support\Response + { + $id=$request->input('id'); + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processDefineService()->findById($id); + if ($result != null) { + return Json::success($result->toArray()); + } else { + return Json::fail('参数错误'); + } + } + + public function setStatus(Request $request): \support\Response + { + try { + $ingeniousEngines = $this->service; + $id = request()->input('id'); + $state = request()->input('state'); + $ingeniousEngines->processDefineService()->updateState($id, $state, $request->adminId()); + return Json::success('操作成功'); + } catch (LFlowException $e) { + return Json::fail($e->getMessage()); + } + } + + public function startAndExecute(Request $request): \support\Response + { + Db::startTrans(); + try { + $args = ProcessFlowUtils::variableToDict($request->all()); + $args->put(ProcessConst::USER_USER_ID, $request->adminId()); + $processDefineId = request()->input(ProcessConst::PROCESS_DEFINE_ID_KEY); + if (empty($processDefineId)) { + return Json::fail(ProcessConst::PROCESS_DEFINE_ID_KEY + '必须参数不能为空'); + } + $ingeniousEngines = $this->service; + $ingeniousEngines->processInstanceService()->startAndExecute($processDefineId, $args); + Db::commit(); + return Json::success('发起成功'); + } catch (LFlowException $e) { + Db::rollback(); + return Json::fail($e->getMessage()); + } + + } + + public function delete(Request $request): \support\Response + { + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processDefineService()->del($request->input('id')); + if (!$result) { + return Json::fail('操作失败'); + } + return Json::success('删除成功'); + } + + public function processFavorite(Request $request): \support\Response + { + $ingeniousEngines = $this->service; + $param = $request->postMore([ + ['user_id', $request->adminId()], + ['process_define_id'], + ['favorite', 1], + ]); + $result = $ingeniousEngines->processDefineService()->definitionFavorite((object)$param); + if (!$result) { + return Json::fail('收藏失败'); + } + return Json::success('收藏成功'); + } + + public function favoritePage(Request $request): \support\Response + { + $ingeniousEngines = $this->service; + $param = $request->postMore([ + ['user_id', $request->adminId()], + ['process_define_id', ''], + ['favorite', 1], + ['page', 0], + ['limit', 0], + ]); + $result = $ingeniousEngines->processDefineService()->favoritePage((object)$param); + return Json::success($result); + } + + public function favoriteDelete(Request $request): \support\Response + { + $ingeniousEngines = $this->service; + $data = request()->input('data', []); + $result = $ingeniousEngines->processDefineService()->favoriteDel($data); + if (!$result) { + return Json::fail('操作失败'); + } + return Json::success('操作成功'); + } + +} diff --git a/demo/webman/backend/app/adminapi/controller/wf/DesignerController.php b/demo/webman/backend/app/adminapi/controller/wf/DesignerController.php new file mode 100644 index 0000000000000000000000000000000000000000..514c14e3ee33500421872b7878e3fac69dd82a80 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/wf/DesignerController.php @@ -0,0 +1,177 @@ +service = new ProcessEngines(new ConfigurationRewrite([])); + } + + public function index(Request $request): \support\Response + { + $param = $request->getMore([ + ['id', ''], + ['model_key', ''], + ['model_name', ''], + ['model_group_id', ''], + ]); + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processDesignService()->page((object)$param); + return Json::success($result); + } + + public function read(Request $request): \support\Response + { + $ingeniousEngines = $this->service; + $id = $request->input('id'); + $result = $ingeniousEngines->processDesignService()->findById($id); + if ($result != null) { + return Json::success($result->toArray()); + } else { + return Json::fail('参数错误'); + } + } + + public function save(Request $request): \support\Response + { + $ingeniousEngines = $this->service; + $data = $request->postMore([ + ['name', ''], + ['display_name', ''], + ['description', ''], + ['type_id', ''], + ['icon', ''], + ['remark', ''], + ['create_user', $request->adminId()], + ]); + if (empty($data['name'])) { + return Json::fail('唯一编码不能为空'); + } + if (empty($data['display_name'])) { + return Json::fail('显示名称不能为空'); + } + if ($ingeniousEngines->processDesignService()->create((object)$data)) { + return Json::success('添加成功'); + } else { + return Json::fail('添加失败'); + } + } + + public function updateDefine(Request $request): \support\Response + { + $data = $request->all(); + $data[ProcessConst::CREATE_USER] = $request->adminId();//追加用户id + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processDesignService()->updateDefine((object)$data); + if ($result) { + return Json::success('保存成功'); + } else { + return Json::fail('保存失败'); + } + } + + public function delete(Request $request): \support\Response + { + $id = $request->input('id'); + $ingeniousEngines = $this->service; + if (!($ingeniousEngines->processDesignService()->del($id))) { + return Json::fail('数据不存在'); + } + return Json::success('删除成功'); + } + + public function batchRemove(Request $request): \support\Response + { + $data = $request->input('data'); + $ingeniousEngines = $this->service; + $error = []; + foreach (explode(',', $data) as $key => $value) { + $ret = $ingeniousEngines->processDesignService()->del($value); + if (!$ret) { + $error[] = $value . '删除失败'; + } + } + if (count($error) > 0) { + return Json::fail(import(',', $error)); + } + return Json::success('删除成功'); + } + + public function update(Request $request): \support\Response + { + $ingeniousEngines = $this->service; + $id = $request->input('id'); + $data = $request->postMore([ + ['id', $id], + ['name', ''], + ['display_name', ''], + ['description', ''], + ['type_id', ''], + ['icon', ''], + ['remark', ''], + ['update_user', $request->adminId()], + ]); + if ($ingeniousEngines->processDesignService()->update((object)$data)) { + return Json::success('更新成功'); + } else { + return Json::fail('更新失败'); + } + } + + public function deploy(Request $request): \support\Response + { + Db::startTrans(); + try { + $processDesignid = $request->input('id'); + $ingeniousEngines = $this->service; + $ingeniousEngines->processDesignService()->deploy($processDesignid, $request->adminId()); + Db::commit(); + return Json::success('部署成功'); + } catch (LFlowException $e) { + Db::rollback(); + return Json::fail($e->getMessage()); + } + + } + + public function redeploy(Request $request): \support\Response + { + Db::startTrans(); + try { + $processDesignid = $request->input('id'); + $ingeniousEngines = $this->service; + $ingeniousEngines->processDesignService()->redeploy($processDesignid, $request->adminId()); + Db::commit(); + return Json::success('重新部署成功'); + } catch (LFlowException $e) { + Db::rollback(); + return Json::fail($e->getMessage()); + } + + } +} diff --git a/demo/webman/backend/app/adminapi/controller/wf/InstanceController.php b/demo/webman/backend/app/adminapi/controller/wf/InstanceController.php new file mode 100644 index 0000000000000000000000000000000000000000..522648e922c66343cbb8e89778b3c8e646098863 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/wf/InstanceController.php @@ -0,0 +1,143 @@ +service = new ProcessEngines(new ConfigurationRewrite([])); + } + + public function index(Request $request): \support\Response + { + $args = $request->getMore([ + ['operator', $request->adminId()], + ['business_no', ''], + ['display_name', ''], + ['page', 0], + ['limit', 0], + ]); + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processInstanceService()->page((object)$args); + return Json::success($result); + } + + public function management(Request $request): \support\Response + { + $args = $request->getMore([ + ['business_no', ''], + ['display_name', ''], + ['page', 0], + ['limit', 0], + ]); + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processInstanceService()->page((object)$args); + return Json::success($result); + } + + public function detail(Request $request): \support\Response + { + + $ingeniousEngine = $this->service; + $id = $request->input('id'); + $result = $ingeniousEngine->processInstanceService()->findById($id); + if ($result == null) { + return Json::fail('实例不存在或被删除'); + } + return Json::success($result->toArray()); + } + + public function withdraw(Request $request): \support\Response + { + Db::startTrans(); + try { + $ingeniousEngine = $this->service; + $id = $request->input('id', ''); + foreach (explode(',', $id) as $value) { + $ingeniousEngine->processInstanceService()->withdraw($value, $request->adminId()); + } + Db::commit(); + return Json::success('撤回成功'); + } catch (LFlowException $e) { + Db::rollback(); + return Json::fail($e->getMessage()); + } + } + + public function cascadeDelete(Request $request): \support\Response + { + Db::startTrans(); + try { + $ingeniousEngine = $this->service; + $id = $request->input('id', ''); + $ingeniousEngine->processInstanceService()->cascadeDelete($id, $request->adminId()); + Db::commit(); + return Json::success('删除成功'); + } catch (LFlowException $e) { + Db::rollback(); + return Json::fail($e->getMessage()); + } + } + + public function highLightData(Request $request): \support\Response + { + $ingeniousEngine = $this->service; + $id = $request->input('id'); + try { + $result = $ingeniousEngine->processInstanceService()->highLight($id); + + }catch (LFlowException $e){ + var_dump($e->getMessage()); + } + return Json::success($result); + } + + public function approvalRecord(Request $request): \support\Response + { + $ingeniousEngine = $this->service; + $id = $request->input('id'); + $result = $ingeniousEngine->processInstanceService()->approvalRecord($id); + return Json::success($result); + } + + /*流程实例抄送******************************************************************************************************/ + public function ccList(Request $request): \support\Response + { + $args = $request->getMore([ + ['actor_id', $request->adminId()], + ['name', ''], + ['display_name', ''], + ['business_no', ''], + ['page', 0], + ['limit', 0], + ]); + $ingeniousEngines = $this->service; + $result = $ingeniousEngines->processInstanceService()->ccInstancePage((object)$args); + return Json::success($result); + } + +} diff --git a/demo/webman/backend/app/adminapi/controller/wf/OtherHandleController.php b/demo/webman/backend/app/adminapi/controller/wf/OtherHandleController.php new file mode 100644 index 0000000000000000000000000000000000000000..5e77683a256ba935aa7da537575f671301bf0a71 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/wf/OtherHandleController.php @@ -0,0 +1,132 @@ + new LoginUserHolder($request), + 'findUserApi' => new UserProcessingApi(), + ]; + + $this->service = new ProcessEngines(new ConfigurationRewrite($config)); + } + + public function candidatePage(Request $request): \support\Response + { + $ingeniousEngine = $this->service; + $params = $request->getMore(['process_task_id', 'limit', 'page']); + $result = $ingeniousEngine->processTaskService()->candidatePage(ProcessFlowUtils::variableToDict($params)); + return Json::success($result); + } + + public function carbonPage(Request $request): \support\Response + { + $where = $request->getMore([['search', '']]); + $page = $request->input('page', 0); + $limit = $request->input('limit', 0); + $result = []; + $systemAdmin = new SystemAdminServices(new SystemAdminDao()); + $result['list'] = $systemAdmin->selectList($where, '*', $page, $limit, '', [], true)->toArray(); + $result['count'] = $systemAdmin->count($where); + return Json::success($result); + } + + public function userList(Request $request): \support\Response + { + $param = $request->input('search', ''); + $systemAdminServices = Container::make(SystemAdminServices::class); + $result = $systemAdminServices->getAdministratorsList(['account_like' => $param]); + $data = []; + foreach ($result['list'] as $key => $value) { + $data['list'][$key]['name'] = $value['real_name']; + $data['list'][$key]['value'] = $value['id']; + } + $data['count'] = $result['count']; + return Json::success($data); + } + + public function userInfo(Request $request): \support\Response + { + $param = $request->input('search', ''); + if (empty($param)) { + return Json::success([]); + } + $systemAdminServices = Container::make(SystemAdminServices::class); + $result = $systemAdminServices->getAdminList(['id_in' => $param]); + $data = []; + foreach ($result['list'] as $key => $value) { + $data['list'][$key]['name'] = $value['real_name']; + $data['list'][$key]['value'] = $value['id']; + } + $data['count'] = $result['count']; + return Json::success($data); + } + + /** + * 提供设计器对应的参与类 + * + * @return array[] + */ + public function assignmentHandler(): array + { + return [ + [ + 'label' => '直属主管',//注册类的对应名称 + 'value' => AssignmentDirectManager::class, + ], + ]; + } + + /** + * 模拟表单列表 vue 获取html 可以根据自己来操作 + * + * @return \support\Response + */ + public function formHandler(): \support\Response + { + $data = [ + [ + 'label' => '请假申请单', + 'value' => 'leaveForm.html', + ], + [ + 'label' => '补卡申请单', + 'value' => 'reissueForm.html', + ], + [ + 'label' => '测试申请单', + 'value' => 'test.html', + ], + ]; + return Json::success($data); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/wf/TaskController.php b/demo/webman/backend/app/adminapi/controller/wf/TaskController.php new file mode 100644 index 0000000000000000000000000000000000000000..b691e044030841f857ab619a1697ec936d27a90b --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/wf/TaskController.php @@ -0,0 +1,176 @@ + new LoginUserHolder($request), + 'findUserApi' => new UserProcessingApi(), + ]; + + $this->service = new ProcessEngines(new ConfigurationRewrite($config)); + } + + public function doneList(Request $request): \support\Response + { + $ingeniousEngine = $this->service; + $param = $request->getMore([ + ['actor_id', $request->adminId()], + ['display_name', ''], + ['process_define_display_name', ''], + ['page', 0], + ['limit', 0], + ['business_no', ''], + ]); + $result = $ingeniousEngine->processTaskService()->doneList((object)$param); + return Json::success('获取成功', $result); + } + + //我的代办 + public function todoList(Request $request): \support\Response + { + $ingeniousEngine = $this->service; + $where = $request->getMore([ + ['actor_id', $request->adminId()], + ['display_name', ''], + ['business_no', ''], + ]); + $result = $ingeniousEngine->processTaskService()->todoList((object)$where); + return Json::success('获取成功', $result); + } + + public function execute(Request $request): \support\Response + { + Db::startTrans(); + try { + $ingeniousEngine = $this->service; + $scene = $request->input(ProcessConst::SUBMIT_TYPE); + $processTaskId = $request->input(ProcessConst::PROCESS_TASK_ID_KEY); + $args = ProcessFlowUtils::variableToDict((object)$request->input()); + $operator = $request->adminId(); + switch ($scene) { + case ProcessSubmitTypeEnum::AGREE[0]: + //同意申请 + $ingeniousEngine->executeProcessTask($processTaskId, $operator, $args); + break; + case ProcessSubmitTypeEnum::REJECT[0]: + //拒绝申请 + $ingeniousEngine->executeAndJumpToEnd($processTaskId, $operator, $args); + break; + case ProcessSubmitTypeEnum::ROLLBACK[0]: + //退回上一步 + $ingeniousEngine->executeAndJumpTask($processTaskId, $operator, $args); + break; + case ProcessSubmitTypeEnum::JUMP[0]: + // 跳转到指定节点 + $taskName = $args->get(ProcessConst::TASK_NAME); + $ingeniousEngine->executeAndJumpTask($processTaskId, $operator, $args, $taskName); + break; + case ProcessSubmitTypeEnum::ROLLBACK_TO_OPERATOR[0]: + //退回申请人 + $ingeniousEngine->executeAndJumpToFirstTaskNode($processTaskId, $operator, $args); + break; + case ProcessSubmitTypeEnum::COUNTERSIGN_DISAGREE[0]: + //会签不同意 追加不同意标识 + $args->put(ProcessConst::COUNTERSIGN_DISAGREE_FLAG, 1); + $ingeniousEngine->executeProcessTask($processTaskId, $operator, $args); + break; + default: + //默认执行 + $ingeniousEngine->executeProcessTask($processTaskId, $operator, $args); + break; + } + + // 存在抄送 + $ccUserIds = $args->get(ProcessConst::CC_ACTORS); + if (!empty($ccUserIds)) { + $processInstanceId = $args->get(ProcessConst::PROCESS_INSTANCE_ID_KEY); + if (is_array($ccUserIds)) { + $ccUserIds = implode(',', $ccUserIds); + } + //创建抄送列表 + $ingeniousEngine->processInstanceService()->createCCInstance($processInstanceId, $operator, $ccUserIds); + } + Db::commit(); + return Json::success('操作成功'); + } catch (LFlowException $e) { + Db::rollback(); + return Json::fail($e->getMessage()); + } + } + + public function jumpAbleTaskNameList(Request $request): \support\Response + { + $processInstanceId = $request->input(ProcessConst::PROCESS_INSTANCE_ID_KEY); + $ingeniousEngine = $this->service; + $result = $ingeniousEngine->processTaskService()->jumpAbleTaskNameList($processInstanceId); + return Json::success($result); + } + + + + public function userList(Request $request): \support\Response + { + $where = $request->getMore([['name', '', '', 'account_like']]); + $systemAdminServices = new SystemAdminServices(new SystemAdminDao()); + $result = $systemAdminServices->getAdminList($where); + return Json::success($result); + } + + public function surrogate(Request $request): \support\Response + { + try { + $ingeniousEngine = $this->service; + $processTaskId = $request->input('process_task_id'); + $actors = $request->input('actor_ids'); + $ingeniousEngine->processTaskService()->addTaskActor($processTaskId, $actors); + return Json::success('操作成功'); + } catch (LFlowException $e) { + return Json::fail($e->getMessage()); + } + } + + public function detail(Request $request): \support\Response + { + $ingeniousEngine = $this->service; + $id = $request->input('id'); + $result = $ingeniousEngine->processTaskService()->findById($id); + if ($result == null) { + return Json::fail('实例不存在或被删除'); + } + return Json::success($result->toArray()); + } + +} diff --git a/demo/webman/backend/app/adminapi/controller/wf/api/AssignmentDirectManager.php b/demo/webman/backend/app/adminapi/controller/wf/api/AssignmentDirectManager.php new file mode 100644 index 0000000000000000000000000000000000000000..ba9b1c2e152e8702d39bd2f5d499d6230e973f6d --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/wf/api/AssignmentDirectManager.php @@ -0,0 +1,45 @@ +getProcessInstance();//流程实列 + $operator = $processInstance->getData('operator');//申请人ID + $variable = $processInstance->getData('variable');//流程实列变量 + $ext = ProcessFlowUtils::variableToDict($variable); + $deptId = $ext->get(ProcessConst::USER_DEPT_ID, ''); + if (empty($deptId)) { + //如果没有部门id 在此实现逻辑通过发起人找上级部门 待优化 + return $result; + } + $deptServices = new SystemDeptServices(new SystemDeptDao()); + $deptData = $deptServices->get($deptId); + if ($deptData == null) { + return []; + } + $result[] = $deptData->getData('manager_id'); + return $result; + } +} diff --git a/demo/webman/backend/app/adminapi/controller/wf/api/LoginUserHolder.php b/demo/webman/backend/app/adminapi/controller/wf/api/LoginUserHolder.php new file mode 100644 index 0000000000000000000000000000000000000000..582c2fa1f346270c979a4538ad307071dd3f0ef0 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/wf/api/LoginUserHolder.php @@ -0,0 +1,51 @@ +request = $request; + } + + public function getUserId(): string|int + { + return $this->request->adminId() ?? '0'; + } + + public function getUserName(): string + { + $userInfo = $this->request->adminInfo(); + return $userInfo['account'] ?? ''; + } + + public function getRealName(): string + { + $userInfo = $this->request->adminInfo(); + return $userInfo['real_name'] ?? ''; + } + +} diff --git a/demo/webman/backend/app/adminapi/controller/wf/api/UserProcessingApi.php b/demo/webman/backend/app/adminapi/controller/wf/api/UserProcessingApi.php new file mode 100644 index 0000000000000000000000000000000000000000..5c1163cad02a86c118d5b2aabdf8ceff5b9ee6f4 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/wf/api/UserProcessingApi.php @@ -0,0 +1,66 @@ +services = new SystemAdminServices(new SystemAdminDao()); + } + + /** + * 引擎用户API实现类 + * + * @param string|int $id + * + * @return object|null + */ + public function findUser(string|int $id): ?object + { + $result = $this->services->get(['id' => $id], ['id', 'account as user_name', 'real_name'], ['departments', 'positions']); + if (empty($result)) { + return null; + } + $deptList = $result->getData('departments'); + $postList = $result->getData('positions'); + $dept_id = []; + $dept_name = []; + $post_id = []; + $post_name = []; + if (!empty($deptList)) { + foreach ($deptList as $dept) { + $dept_name[] = $dept->getData('dept_name'); + $dept_id[] = $dept->getData('dept_id'); + } + } + if (!empty($postList)) { + foreach ($postList as $post) { + $post_name[] = $post->getData('post_name'); + $post_id[] = $post->getData('post_id'); + } + } + $result->set('dept_name', implode(',', $dept_name)); + $result->set('post_name', implode(',', $post_name)); + $result->set('dept_id', implode(',', $dept_id)); + $result->set('post_id', implode(',', $post_id)); + return (object)$result->hidden(['departments', 'positions'])->toArray(); + } +} diff --git a/demo/webman/backend/app/adminapi/controller/wf/config/ConfigurationRewrite.php b/demo/webman/backend/app/adminapi/controller/wf/config/ConfigurationRewrite.php new file mode 100644 index 0000000000000000000000000000000000000000..25e04f376177d9407a553e9978c5ba6013b75678 --- /dev/null +++ b/demo/webman/backend/app/adminapi/controller/wf/config/ConfigurationRewrite.php @@ -0,0 +1,57 @@ +adminId() || !$request->adminInfo()) { + throw new AuthException('参数错误'); + } + //非超级管理员进行权限验证 + if ($request->adminInfo()['level'] !== 0) { + /** @var SystemRoleServices $services */ + $services = Container::make(SystemRoleServices::class); + $services->verifyAuth($request); + } + return $handler($request); + } +} diff --git a/demo/webman/backend/app/adminapi/middleware/AdminAuthTokenMiddleware.php b/demo/webman/backend/app/adminapi/middleware/AdminAuthTokenMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..f2aefcf94d28984b1c651b8c1c3b2d5faaa54969 --- /dev/null +++ b/demo/webman/backend/app/adminapi/middleware/AdminAuthTokenMiddleware.php @@ -0,0 +1,44 @@ +header(Config('app.token_name', 'Authorization')), 'Bearer')); + if (!$token) { + $token = trim(ltrim($request->get('token'))); + } + /** @var SystemAuthServices $service */ + $service = Container::make(SystemAuthServices::class); + $adminInfo = $service->parseToken($token); + + $request->macro('isAdminLogin', function () use (&$adminInfo) { + return !is_null($adminInfo); + }); + $request->macro('adminId', function () use (&$adminInfo) { + return $adminInfo['id'] ?? ''; + }); + + $request->macro('adminInfo', function () use (&$adminInfo) { + return $adminInfo; + }); + + return $handler($request); + } +} diff --git a/demo/webman/backend/app/adminapi/middleware/AdminLogMiddleware.php b/demo/webman/backend/app/adminapi/middleware/AdminLogMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..484130f79aeaf0842271baea48bdb15d5bb06bb1 --- /dev/null +++ b/demo/webman/backend/app/adminapi/middleware/AdminLogMiddleware.php @@ -0,0 +1,33 @@ +recordAdminLog($request->adminId(), $request->adminInfo()['real_name'], $request->adminInfo()['type']); + } catch (\Exception $e) { + echo($e); + } + return $response; + } +} diff --git a/demo/webman/backend/app/adminapi/middleware/AllowCrossOriginMiddleware.php b/demo/webman/backend/app/adminapi/middleware/AllowCrossOriginMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..7a54768b8206b6788a39377adfb55cf55fc4442a --- /dev/null +++ b/demo/webman/backend/app/adminapi/middleware/AllowCrossOriginMiddleware.php @@ -0,0 +1,56 @@ +getRemoteIp(); + // ip不在允许范围内 返回403 + if (!$this->isAllowedIP($clientIP)) { + if ($request->method() === 'OPTIONS') { + return $this->handlePreflightRequest(); + } + $response = new Response(403); + $this->addCorsHeaders($response); + return $response; + } + // 检查是否为预检请求 + if ($request->method() === 'OPTIONS') { + return $this->handlePreflightRequest(); + } + // 处理实际请求 + $response = $handler($request); + // 添加 CORS 头部信息 + $this->addCorsHeaders($response); + return $response; + } + + protected function handlePreflightRequest(): Response + { + $response = new Response(); + $this->addCorsHeaders($response); + $response->header('Access-Control-Max-Age', '3600'); + return $response; + } + + protected function addCorsHeaders(Response $response): void + { + $response->header('Access-Control-Allow-Origin', '*'); + $response->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); + $response->header('Access-Control-Allow-Headers', 'Content-Type, Authorization,Authori-zation, Author'); + $response->header('Access-Control-Allow-Credentials', 'true'); + } + + protected function isAllowedIP($ip): bool + { + $domain = config('app.domain', []); + return in_array($ip, $domain); + } +} diff --git a/demo/webman/backend/app/adminapi/route/setting.php b/demo/webman/backend/app/adminapi/route/setting.php new file mode 100644 index 0000000000000000000000000000000000000000..1ca88d9264dd1eb25d4247fc57d84edc95927cf1 --- /dev/null +++ b/demo/webman/backend/app/adminapi/route/setting.php @@ -0,0 +1,46 @@ +name('批量删除管理员'); + Route::get('/admin/index', [app\adminapi\controller\setting\SystemAdmin::class, 'index'])->name('获取管理员列表'); + Route::get('/admin/detail', [app\adminapi\controller\setting\SystemAdmin::class, 'read'])->name('获取详情'); + Route::post('/admin/save', [app\adminapi\controller\setting\SystemAdmin::class, 'save'])->name('保存管理员'); + Route::post('/admin/update', [app\adminapi\controller\setting\SystemAdmin::class, 'update'])->name('修改管理员'); + Route::post('/admin/delete', [app\adminapi\controller\setting\SystemAdmin::class, 'delete'])->name('删除管理员'); + Route::get('/admin/logout', [app\adminapi\controller\setting\SystemAdmin::class, 'logout'])->name('退出登陆'); + Route::put('/set_status/:id/:status', [app\adminapi\controller\setting\SystemAdmin::class, 'set_status'])->name('修改管理员状态'); + Route::get('/info', [app\adminapi\controller\setting\SystemAdmin::class, 'info'])->name('获取当前管理员信息'); + Route::put('/update_admin', [app\adminapi\controller\setting\SystemAdmin::class, 'update_admin'])->name('修改当前管理员信息'); + Route::put('/set_file_password', [app\adminapi\controller\setting\SystemAdmin::class, 'set_file_password'])->name('设置文件管理密码'); + Route::put('/set_admin_position/:id', [app\adminapi\controller\setting\SystemAdmin::class, 'setPosition'])->name('设置管理员职位'); + }); + + /** 权限菜单 */ + Route::group(function () { + Route::get('/permission', [app\adminapi\controller\setting\SystemMenus::class, 'permission'])->name('获取菜单'); + Route::get('/menus/unique', [app\adminapi\controller\setting\SystemMenus::class, 'unique'])->name('获取菜单权限和权限标识'); + Route::post('/menus/batch', [app\adminapi\controller\setting\SystemMenus::class, 'batchSave'])->name('批量保存权限'); + + //权限菜单资源路由 + Route::get('/menus/page', [app\adminapi\controller\setting\SystemMenus::class, 'index'])->name('获取权限菜单列表'); + Route::get('/menus/edit', [app\adminapi\controller\setting\SystemMenus::class, 'edit'])->name('获取权限菜单表单'); +// Route::get('/menus/create', [app\adminapi\controller\setting\SystemMenus::class, 'create'])->name('获取修改权限菜单表单'); + Route::get('/menus/detail', [app\adminapi\controller\setting\SystemMenus::class, 'read'])->name('查看权限菜单信息'); + Route::post('/menus/save', [app\adminapi\controller\setting\SystemMenus::class, 'save'])->name('保存权限菜单'); + Route::post('/menus/update', [app\adminapi\controller\setting\SystemMenus::class, 'update'])->name('修改权限菜单'); + Route::post('/menus/delete', [app\adminapi\controller\setting\SystemMenus::class, 'delete'])->name('删除权限菜单'); + + Route::get('/ruleList', [app\adminapi\controller\setting\SystemMenus::class, 'ruleList'])->name('权限规则列表'); + Route::get('/rule_cate', [app\adminapi\controller\setting\SystemMenus::class, 'ruleCate'])->name('权限规则分类'); + Route::post('/menus/show', [app\adminapi\controller\setting\SystemMenus::class, 'show'])->name('修改权限规格显示状态'); + }); + +})->middleware([ + app\adminapi\middleware\AdminAuthTokenMiddleware::class, + app\adminapi\middleware\AdminAuthPermissionMiddleware::class, + app\adminapi\middleware\AdminLogMiddleware::class, +]); + diff --git a/demo/webman/backend/app/adminapi/route/wf.php b/demo/webman/backend/app/adminapi/route/wf.php new file mode 100644 index 0000000000000000000000000000000000000000..739ea120a1c72e79db54ec19de11889ede4baf04 --- /dev/null +++ b/demo/webman/backend/app/adminapi/route/wf.php @@ -0,0 +1,92 @@ +name('获取分类树'); + Route::get('/page', [app\adminapi\controller\wf\CategoryController::class, 'select'])->name('获取列表'); + Route::get('/detail', [app\adminapi\controller\wf\CategoryController::class, 'read'])->name('获取详情'); + Route::post('/save', [app\adminapi\controller\wf\CategoryController::class, 'save'])->name('保存分类'); + Route::post('/update', [app\adminapi\controller\wf\CategoryController::class, 'update'])->name('保存分类'); + Route::post('/delete', [app\adminapi\controller\wf\CategoryController::class, 'delete'])->name('删除分类'); + Route::post('/remove', [app\adminapi\controller\wf\CategoryController::class, 'remove'])->name('批量删除模型分类'); + }); + /**流程设计**/ + Route::group('/designer', function () { + Route::post('/batch_remove', [app\adminapi\controller\wf\DesignerController::class, 'batchRemove'])->name('批量删除模型'); + Route::post('/update_define', [app\adminapi\controller\wf\DesignerController::class, 'updateDefine'])->name('保存模型定义'); + Route::post('/deploy', [app\adminapi\controller\wf\DesignerController::class, 'deploy'])->name('流程部署'); + Route::post('/redeploy', [app\adminapi\controller\wf\DesignerController::class, 'redeploy'])->name('流程重新部署'); + Route::get('/page', [app\adminapi\controller\wf\DesignerController::class, 'index'])->name('获取列表'); + Route::get('/detail', [app\adminapi\controller\wf\DesignerController::class, 'read'])->name('获取详情'); + Route::post('/save', [app\adminapi\controller\wf\DesignerController::class, 'save'])->name('保存设计'); + Route::post('/update', [app\adminapi\controller\wf\DesignerController::class, 'update'])->name('更新设计'); + Route::post('/delete', [app\adminapi\controller\wf\DesignerController::class, 'delete'])->name('删除设计'); + Route::post('/remove', [app\adminapi\controller\wf\DesignerController::class, 'batchRemove'])->name('批量删除模型设计'); + }); + /**流程定义**/ + Route::group('/process_define', function () { + Route::post('/set_status', [app\adminapi\controller\wf\DefineController::class, 'setStatus'])->name('更新流程状态'); + Route::post('/start_and_execute', [app\adminapi\controller\wf\DefineController::class, 'startAndExecute'])->name('启动流程'); + //流程定义收藏 + Route::get('/favorite/page', [app\adminapi\controller\wf\DefineController::class, 'favoritePage'])->name('收藏列表'); + Route::post('/favorite/setting', [app\adminapi\controller\wf\DefineController::class, 'processFavorite'])->name('流程收藏'); + Route::post('/favorite/remove', [app\adminapi\controller\wf\DefineController::class, 'favoriteDelete'])->name('收藏删除'); + //流程定义 + Route::get('/page', [app\adminapi\controller\wf\DefineController::class, 'index'])->name('获取列表'); + Route::get('/detail', [app\adminapi\controller\wf\DefineController::class, 'read'])->name('获取详情'); +// Route::post('/save', [app\adminapi\controller\wf\DefineController::class, 'save'])->name('保存分类'); +// Route::post('/update', [app\adminapi\controller\wf\DefineController::class, 'update'])->name('保存分类'); + Route::post('/delete', [app\adminapi\controller\wf\DefineController::class, 'delete'])->name('删除分类'); +// Route::post('/remove', [app\adminapi\controller\wf\DefineController::class, 'remove'])->name('批量删除模型分类'); + }); + /**流程实例**/ + Route::group('/process_instance', function () { + Route::get('/highlight', [app\adminapi\controller\wf\InstanceController::class, 'highLightData'])->name('获取高亮数据'); + Route::get('/approval_record', [app\adminapi\controller\wf\InstanceController::class, 'approvalRecord'])->name('获取记录'); + Route::post('/withdraw', [app\adminapi\controller\wf\InstanceController::class, 'withdraw'])->name('撤回流程'); +// Route::post('/undo', [app\adminapi\controller\wf\InstanceController::class, 'undo'])->name('作废流程'); + Route::post('/cascade_delete', [app\adminapi\controller\wf\InstanceController::class, 'cascadeDelete'])->name('级联删除流程定义'); + Route::get('/cc_list', [app\adminapi\controller\wf\InstanceController::class, 'ccList'])->name('获取抄送列表'); + + //我发起的申请 + Route::get('/management', [app\adminapi\controller\wf\InstanceController::class, 'management'])->name('流程追踪列表'); + Route::get('/page', [app\adminapi\controller\wf\InstanceController::class, 'index'])->name('获取列表'); + Route::get('/detail', [app\adminapi\controller\wf\InstanceController::class, 'detail'])->name('获取详情'); +// Route::post('/save', [app\adminapi\controller\wf\InstanceController::class, 'save'])->name('保存实例'); +// Route::post('/update', [app\adminapi\controller\wf\InstanceController::class, 'update'])->name('更新实例'); + Route::post('/delete', [app\adminapi\controller\wf\InstanceController::class, 'cascadeDelete'])->name('删除实例'); +// Route::post('/remove', [app\adminapi\controller\wf\InstanceController::class, 'batchCascadeDelete'])->name('批量删除模型实例'); + }); + + /**流程任务**/ + Route::group('/process_task', function () { + Route::get('/done/page', [app\adminapi\controller\wf\TaskController::class, 'doneList'])->name('我的代办'); + Route::get('/todo/page', [app\adminapi\controller\wf\TaskController::class, 'todoList'])->name('我的已办'); + Route::get('/user', [app\adminapi\controller\wf\TaskController::class, 'userList'])->name('获取用户列表'); + Route::post('/execute', [app\adminapi\controller\wf\TaskController::class, 'execute'])->name('执行任务'); + Route::post('/surrogate', [app\adminapi\controller\wf\TaskController::class, 'surrogate'])->name('委托代理'); + Route::get('/detail', [app\adminapi\controller\wf\TaskController::class, 'detail'])->name('获取任务详情'); + Route::post('/jump_able_task_name_list', [app\adminapi\controller\wf\TaskController::class, 'jumpAbleTaskNameList'])->name('获取跳转节点'); + }); + + /**其他**/ + Route::group('/other', function () { + Route::get('/user/list', [app\adminapi\controller\wf\OtherHandleController::class, 'userList'])->name('审批人列表'); + Route::get('/user/info', [app\adminapi\controller\wf\OtherHandleController::class, 'userInfo'])->name('审批人详情'); + Route::get('/assignment_handler', [app\adminapi\controller\wf\OtherHandleController::class, 'assignmentHandler'])->name('处理类列表'); + Route::get('/form/option', [app\adminapi\controller\wf\OtherHandleController::class, 'formHandler'])->name('获取表单实例url'); + Route::get('/candidate_page', [app\adminapi\controller\wf\OtherHandleController::class, 'candidatePage'])->name('获取候选人列表'); + Route::get('/carbon_page', [app\adminapi\controller\wf\OtherHandleController::class, 'carbonPage'])->name('获取候选人列表'); + }); + +})->middleware([ + app\adminapi\middleware\AdminAuthTokenMiddleware::class, + app\adminapi\middleware\AdminAuthPermissionMiddleware::class, + app\adminapi\middleware\AdminLogMiddleware::class, + +]); + +Route::disableDefaultRoute(); diff --git a/demo/webman/backend/app/adminapi/validate/setting/SystemAdminValidata.php b/demo/webman/backend/app/adminapi/validate/setting/SystemAdminValidata.php new file mode 100644 index 0000000000000000000000000000000000000000..6ac3206dacade93ae7f53710613a7809a3d16708 --- /dev/null +++ b/demo/webman/backend/app/adminapi/validate/setting/SystemAdminValidata.php @@ -0,0 +1,42 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'account' => ['require', 'alphaDash'], + 'conf_pwd' => 'require', + 'pwd' => 'require', + 'real_name' => 'require', + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = [ + 'account.require' => '请填写管理员账号', + 'account.alphaDash' => '管理员账号为英文字母', + 'conf_pwd.require' => '请输入确认密码', + 'pwd.require' => '请输入密码', + 'real_name.require' => '请输管理员姓名', + ]; + + protected $scene = [ + 'get' => ['account', 'pwd'], + 'update' => ['account'], + ]; + +} diff --git a/demo/webman/backend/app/adminapi/validate/setting/SystemUserValidata.php b/demo/webman/backend/app/adminapi/validate/setting/SystemUserValidata.php new file mode 100644 index 0000000000000000000000000000000000000000..30efbfb615b016e67722f91d9d59ca958f2d516c --- /dev/null +++ b/demo/webman/backend/app/adminapi/validate/setting/SystemUserValidata.php @@ -0,0 +1,42 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'account' => ['require', 'alphaDash'], + 'password' => 'require', + 'captcha' => 'require', + 'cid' => 'require', + 'captcha_type' => ['require', 'array'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = [ + 'account.require' => '400033', + 'account.alphaDash' => '400034', + 'conf_pwd.require' => '400263', + 'password.require' => '400256', + 'user_name.require' => '400035', + ]; + + protected $scene = [ + 'get' => ['user_id'], + 'update' => ['account','user_id'], + ]; + +} diff --git a/demo/webman/backend/app/common/CacheService.php b/demo/webman/backend/app/common/CacheService.php new file mode 100644 index 0000000000000000000000000000000000000000..d41880ab95fc1057233a1af66beb1ac735c34f03 --- /dev/null +++ b/demo/webman/backend/app/common/CacheService.php @@ -0,0 +1,238 @@ + 'product', + 1 => 'seckill', + 2 => 'bargain', + 3 => 'combination', + 6 => 'advance', + ]; + + protected static int $expire = 3600; + + protected static function getExpire(int $expire = null): int + { + if ($expire == null) { + if (self::$expire) { + return (int)self::$expire; + } + $default = Config('cache.default'); + $expire = Config('cache.stores.' . $default . '.expire'); + if (!is_int($expire)) { + $expire = (int)$expire; + } + } + return self::$expire = $expire; + } + + /** + * 写入缓存 + * + * @param string $name + * @param $value + * @param int|null $expire + * @param string $tag + * + * @return bool + */ + public static function set(string $name, $value, int $expire = null, string $tag = 'ingenious'): bool + { + // 在键名中添加标签信息 +// $key = $tag . '_' . $name; + try { + return Cache::set($name, $value, $expire ?: self::getExpire($expire)); + } catch (\Exception $e) { + return false; + } + } + + /** + * 如果不存在则写入缓存 + * + * @param string $name + * @param \app\common\mixed|null $default + * @param int|null $expire + * @param string $tag + * + * @return mixed|string + */ + public static function remember(string $name, mixed $default = null, int $expire = null, string $tag = 'ingenious') + { +// $key = $tag . '_' . $name; + $cachedValue = Cache::get($name); + if ($cachedValue !== null) { + return $cachedValue; + } + if (is_callable($default)) { + $value = $default(); + Cache::set($name, $value, $expire ?: self::getExpire($expire)); + return $value; + } + Cache::set($name, $default, $expire ?: self::getExpire($expire)); + return $default; + } + + /** + * 读取缓存 + * + * @param string $name + * @param \app\common\mixed|null $default + * @param string $tag + * + * @return mixed + */ + public static function get(string $name, mixed $default = null, string $tag = 'ingenious'): mixed + { +// $key = $tag . '_' . $name; + return Cache::get($name) ?? $default; + } + + /** + * 删除缓存 + * + * @param string $name + * + * @return bool + */ + public static function delete(string $name): bool + { + return Cache::delete($name); + } + + /** + * 清空缓存池 + * + * @param string $tag + * + * @return bool + */ + public static function clear(string $tag = 'ingenious'): bool + { + $keys = Cache::keys($tag . '_*'); + foreach ($keys as $key) { + Cache::delete($key); + } + return true; + } + + /** + * 检查缓存是否存在 + * + * @param string $key + * @param string $tag + * + * @return bool + */ + public static function has(string $key, string $tag = "ingenious"): bool + { + try { +// $keys = Cache::keys($tag . '_*'); + return Cache::has($key); + } catch (\Exception $e) { + return false; + } + } + + /** + * 检查锁 + * + * @param string $key + * @param int $timeout + * + * @return bool + */ + public static function setMutex(string $key, int $timeout = 10): bool + { + $curTime = time(); + $readMutexKey = "redis:mutex:{$key}"; + $redis = Redis::connection(); + + $mutexRes = $redis->setnx($readMutexKey, $curTime + $timeout); + if ($mutexRes) { + return true; + } + // 检查是否发生死锁,即当前时间大于锁定时间 + $time = $redis->get($readMutexKey); + if ($curTime > $time) { + $redis->del($readMutexKey); + return $redis->setnx($readMutexKey, $curTime + $timeout); + } + return false; + } + + /** + * 删除锁 + * + * @param string $key + */ + public static function delMutex(string $key): void + { + $readMutexKey = "redis:mutex:{$key}"; + Cache::delete($readMutexKey); + } + + /** + * Redis句柄 + * + * @param $type + * + * @return mixed + */ + public static function redisHandler($type = null) + { + if ($type) { + return Cache::store('redis')->tag($type); + } else { + return Cache::store('redis'); + } + } + + /** + * 数据库锁 + * + * @param $key + * @param $fn + * @param int $ex + * + * @return mixed|string + */ + public static function lock($key, $fn, int $ex = 6) + { + $redis = Redis::connection(); + $lockKey = "lock:{$key}"; + $lockValue = uniqid(); + + // 尝试获取锁 + $isLocked = $redis->set($lockKey, $lockValue, 'EX', $ex, 'NX'); + + if ($isLocked) { + try { + // 执行回调函数 + return $fn(); + } finally { + // 释放锁 + if ($redis->get($lockKey) === $lockValue) { + $redis->del($lockKey); + } + } + } else { + // 未获取到锁,可以选择等待重试或返回错误信息 + return 'Failed to acquire lock'; + } + } + +} diff --git a/demo/webman/backend/app/common/Json.php b/demo/webman/backend/app/common/Json.php new file mode 100644 index 0000000000000000000000000000000000000000..4a9911aa753d85554f2b3edcf78be21321685149 --- /dev/null +++ b/demo/webman/backend/app/common/Json.php @@ -0,0 +1,55 @@ + 'application/json'], json_encode($res)); + } + + public static function success($msg = 'success', ?array $data = null, ?array $replace = []): Response + { + if (is_array($msg)) { + $data = $msg; + $msg = 'success'; + } + + return self::make(200, $msg, $data, $replace); + } + + public static function fail($msg = 'fail', ?array $data = null, ?array $replace = []): Response + { + if (is_array($msg)) { + $data = $msg; + $msg = 'fail'; + } + + return self::make(400, $msg, $data, $replace); + } + + public static function status($status, $msg, $result = []): Response + { + $status = strtoupper($status); + if (is_array($msg)) { + $result = $msg; + $msg = 'success'; + } + return self::success($msg, compact('status', 'result')); + } +} diff --git a/demo/webman/backend/app/common/JwtAuth.php b/demo/webman/backend/app/common/JwtAuth.php new file mode 100644 index 0000000000000000000000000000000000000000..447eb71eca4a781c62f3c1159d03939b5cc79113 --- /dev/null +++ b/demo/webman/backend/app/common/JwtAuth.php @@ -0,0 +1,101 @@ +host(); + $time = time(); + $exp_time = strtotime('+ 30day'); + $params += [ + 'iss' => $host, + 'aud' => $host, + 'iat' => $time, + 'nbf' => $time, + 'exp' => $exp_time, + ]; + $params['jti'] = compact('id', 'type'); + $token = JWT::encode($params, getenv('app.app_key') ?: 'default', $this->algorithm, $keyId); + return compact('token', 'params'); + } + + /** + * 解析token + * + * @param string $jwt + * + * @return array + */ + public function parseToken(string $jwt): array + { + $this->token = $jwt; + list($headb64, $bodyb64, $cryptob64) = explode('.', $this->token); + $payload = JWT::jsonDecode(JWT::urlsafeB64Decode($bodyb64)); + return [$payload->jti->id, $payload->jti->type, $payload->pwd ?? '', $payload->exp]; + } + + /** + * 验证token + */ + public function verifyToken(): void + { + JWT::$leeway = 60; + JWT::decode($this->token, new Key(getenv('app.app_key') ?: 'default', $this->algorithm)); + } + + /** + * 获取token并放入令牌桶 + * + * @param $id + * @param string $type + * @param array $params + * + * @return array + * @throws \app\exception\AdminException + */ + public function createToken($id, string $type, array $params = []): array + { + $tokenInfo = $this->getToken($id, $type, $params); + $exp = $tokenInfo['params']['exp'] - $tokenInfo['params']['iat'] + 60; + $info = [ + 'uid' => $id, + 'token' => $tokenInfo['token'], + 'exp' => $exp, + ]; + $res = CacheService::set(md5($tokenInfo['token']), $info, (int)$exp,''); + if (!$res) { + throw new AdminException('网络异常请稍后重试'); + } + return $tokenInfo; + } +} \ No newline at end of file diff --git a/demo/webman/backend/app/common/traits/JwtAuthModelTrait.php b/demo/webman/backend/app/common/traits/JwtAuthModelTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..4342d69bff5e5a0007efb1f6998b665ce51be27a --- /dev/null +++ b/demo/webman/backend/app/common/traits/JwtAuthModelTrait.php @@ -0,0 +1,67 @@ + +// +---------------------------------------------------------------------- + +namespace app\common\traits; + + +use Firebase\JWT\BeforeValidException; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\JWT; +use Firebase\JWT\SignatureInvalidException; +use UnexpectedValueException; + +trait JwtAuthModelTrait +{ + /** + * @param string $type + * @param array $params + * @return array + */ + public function getToken(string $type, array $params = []): array + { + $id = $this->{$this->getPk()}; + $host = request()->host(); + $time = time(); + + $params += [ + 'iss' => $host, + 'aud' => $host, + 'iat' => $time, + 'nbf' => $time, + 'exp' => strtotime('+30 days'), + ]; + $params['jti'] = compact('id', 'type'); + $token = JWT::encode($params, getenv('app.app_key', 'default')); + + return compact('token', 'params'); + } + + /** + * @param string $jwt + * @return array + * + * @throws UnexpectedValueException Provided JWT was invalid + * @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed + * @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf' + * @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat' + * @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim + * + */ + public static function parseToken(string $jwt): array + { + JWT::$leeway = 60; + + $data = JWT::decode($jwt, getenv('app.app_key', 'default'), array('HS256')); + + $model = new self(); + return [$model->where($model->getPk(), $data->jti->id)->find(), $data->jti->type]; + } +} diff --git a/src/libs/traits/ModelTrait.php b/demo/webman/backend/app/common/traits/ModelTrait.php similarity index 76% rename from src/libs/traits/ModelTrait.php rename to demo/webman/backend/app/common/traits/ModelTrait.php index 6aaa8ea8345618ffce84a6470ba01332befa8ba7..ae099c48dfe318c8624a2d15eb69695f8b5c666a 100644 --- a/src/libs/traits/ModelTrait.php +++ b/demo/webman/backend/app/common/traits/ModelTrait.php @@ -1,18 +1,18 @@ +// +---------------------------------------------------------------------- -/** - *+------------------ - * Ingenious - *+------------------ - * Copyright (c) https://gitee.com/ingenstream/ingenious All rights reserved. 本版权不可删除,侵权必究 - *+------------------ - * Author: Mr. April (405784684@qq.com) - *+------------------ - * Software Registration Number: 2024SR0694589 - * Official Website: http://www.ingenstream.cn - */ +namespace app\common\traits; -namespace ingenious\libs\traits; +use Ramsey\Uuid\Uuid; +use think\Model; /** * Trait ModelTrait @@ -21,6 +21,20 @@ namespace ingenious\libs\traits; */ trait ModelTrait { + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Uuid::uuid4()->toString(); + $model->{$model->pk} = $uuid; + } + /** * 时间段搜索器 * @@ -37,7 +51,7 @@ trait ModelTrait $endTime = $value[1] ?? 0; if ($startTime || $endTime) { if ($startTime == $endTime || $endTime == strtotime(date('Y-m-d', $endTime))) { - $endTime = $endTime + 86399; + $endTime = $endTime + 86400; } $query->whereBetween($timeKey, [$startTime, $endTime]); } @@ -70,7 +84,7 @@ trait ModelTrait $endTime = trim($endTime) ? strtotime($endTime) : 0; if ($startTime && $endTime) { if ($startTime == $endTime || $endTime == strtotime(date('Y-m-d', $endTime))) { - $endTime = $endTime + 86399; + $endTime = $endTime + 86400; } $query->whereBetween($timeKey, [$startTime, $endTime]); } else if (!$startTime && $endTime) { @@ -122,4 +136,5 @@ trait ModelTrait } return $model->value($valueKey ?: $filed); } + } diff --git a/demo/webman/backend/app/common/traits/ServicesTrait.php b/demo/webman/backend/app/common/traits/ServicesTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..e034ab39489f4df5661bfa8badf2fdf2fb69dfd3 --- /dev/null +++ b/demo/webman/backend/app/common/traits/ServicesTrait.php @@ -0,0 +1,32 @@ +toLayuiUi($data); + } + + /** + * 转化layuiUi需要的key值 + * + * @param array|object $rules + * @param int $type + * @param null $setKeysById + * + * @return array + */ + public function toLayuiUi(array|object $rules, int $type = 1, $setKeysById = null): array + { + $retMenu = []; //返回值(也是顶层menu) + static $tmpMenu = []; // 按id为key的menu 解决作用域问题静态处理 + foreach ($rules as $r) { + if ($type === 1 && $r['auth_type'] !== 1) { + //api + continue; + } + if ($r['is_show'] !== 1) { //是否显示 + continue; + } + + //制作菜单: + if (!isset($tmpMenu[$r['id']])) { //如果还不存在,则创建 + $tmpMenu[$r['id']] = ['type' => 1]; + } + $tmpMenu[$r['id']]['id'] = $r['id']; + $tmpMenu[$r['id']]['title'] = $r['menu_name']; + $tmpMenu[$r['id']]['icon'] = 'layui-icon ' . $r['icon']; +// $tmpMenu[$r['id']]['openType'] = "_iframe"; + $tmpMenu[$r['id']]['openType'] = "_component";//1._component 2._iframe 3._blank 4._layer + $tmpMenu[$r['id']]['href'] = $r['menu_path']; + + //加入额外的keys + if ($setKeysById) { + //如果这个id在给定的Id列表内 + if (in_array($r['id'], $setKeysById[0])) { + $tmpMenu[$r['id']][$setKeysById[1]] = $setKeysById[2]; //给特定key赋值 + } + } + + if ($r['pid'] === '-1') { //顶层 + $retMenu[] = &$tmpMenu[$r['id']]; + continue; + } + if (!isset($tmpMenu[$r['pid']])) { //子菜单 + $tmpMenu[$r['pid']] = ['children' => []]; //创建父菜单 + } elseif (!isset($tmpMenu[$r['pid']]['children'])) { + $tmpMenu[$r['pid']]['children'] = []; + } + $tmpMenu[$r['pid']]['type'] = 0; //菜单 + $tmpMenu[$r['pid']]['children'][] = &$tmpMenu[$r['id']]; //加入父菜单 children + } + $tmpMenu = []; + return $retMenu; + } + + /** + * 获取树型菜单 + * + * @param $data + * @param int $pid + * @param int $level + * + * @return array + */ + public static function getTree($data, $pid = 0, $level = 1) + { + $childs = self::getChild($data, $pid, $level); + $dataSort = array_column($childs, 'sort'); + array_multisort($dataSort, SORT_DESC, $childs); + foreach ($childs as $key => $navItem) { + $resChild = self::getTree($data, $navItem['id']); + if (null != $resChild) { + $childs[$key]['children'] = $resChild; + } + } + return $childs; + } + + /** + * 递归数据 + * + * @param array $data + * @param int|string $pid + * @param string $field1 + * @param string $field2 + * @param string $field3 + * + * @return array + */ + public static function tree(array $data, int|string $pid = 0, string $field1 = 'id', string $field2 = 'pid', string $field3 = 'children'): array + { + $arr = []; + foreach ($data as $k => $v) { + if ($v[$field2] == $pid) { + $v[$field3] = self::tree($data, $v[$field1], $field1, $field2, $field3); + $arr[] = $v; + } + } + return $arr; + } + + /** + * 获取子菜单 + * + * @param $arr + * @param $id + * @param $lev + * + * @return array + */ + private static function getChild(&$arr, $id, $lev) + { + $child = []; + foreach ($arr as $value) { + if ($value['pid'] == $id) { + $value['level'] = $lev; + $child[] = $value; + } + } + return $child; + } + + /** + * 格式化数据 + * + * @param array $array + * @param $value + * @param int $default + * + * @return mixed + */ + public static function setValeTime(array $array, $value, $default = 0) + { + foreach ($array as $item) { + if (!isset($value[$item])) + $value[$item] = $default; + else if (is_string($value[$item])) + $value[$item] = (float)$value[$item]; + } + return $value; + } + + /** + * 获取二维数组中某个值的集合重新组成数组,并判断数组中的每一项是否为真 + * + * @param array $data + * @param string $filed + * + * @return array + */ + public static function getArrayFilterValeu(array $data, string $filed) + { + return array_filter(array_unique(array_column($data, $filed)), function ($item) { + if ($item) { + return $item; + } + }); + } + + /** + * 数组转字符串去重复 + * + * @param array $data + * + * @return false|string[] + */ + public static function unique(array $data) + { + return array_unique(explode(',', implode(',', $data))); + } + + /** + * 获取数组中去重复过后的指定key值 + * + * @param array $list + * @param string $key + * + * @return array + */ + public static function getUniqueKey(array $list, string $key) + { + return array_unique(array_column($list, $key)); + } + + /** + * 获取数组中随机值 + * + * @param array $data + * + * @return bool|mixed + */ + public static function getArrayRandKey(array $data) + { + if (!$data) { + return false; + } + $mun = rand(0, count($data)); + if (!isset($data[$mun])) { + return self::getArrayRandKey($data); + } + return $data[$mun]; + } + + /** + * 选出列字符串 + * + * @param array $array + * @param string $key + * @param string $index + * + * @return string + */ + public static function extractStr(array $array, string $key, string $index): string + { + $names = []; + foreach ($array as $item) { + if (isset($item[$key][$index])) { + $names[] = $item[$key][$index]; + } + } + return implode(',', $names); + } + + /** + * 多个一维索引型数组合并并去重 + * + * @param ...$arrays + * + * @return array + */ + public static function mergeAndUniqueArrays(...$arrays): array + { + $mergedArray = array_merge(...$arrays); + return array_values(array_unique($mergedArray)); + } + + /** + * 多维数组去重并重置KEY + * + * @param $array + * + * @return array + */ + public static function uniqueArrayValues(&$array): array + { + $result = array(); + foreach ($array as $key => $value) { + if (is_array($value)) { + $value = self::uniqueArrayValues($value); + } + if (is_array($value) && count($value) > 0) { + $value = array_values($value); + } + if (!in_array($value, $result)) { + $result[$key] = $value; + } + } + return $result; + } +} diff --git a/src/libs/base/BaseService.php b/demo/webman/backend/app/dao/BaseDao.php similarity index 93% rename from src/libs/base/BaseService.php rename to demo/webman/backend/app/dao/BaseDao.php index ef57818206f823ace4846fe9e26aa7838f0044ff..b49f1d40bb5a2efaa875680deeb2a054dd59fb56 100644 --- a/src/libs/base/BaseService.php +++ b/demo/webman/backend/app/dao/BaseDao.php @@ -1,29 +1,28 @@ make($this->setModel()); - //优化兼容其他框架使用反射实例化 + //优化兼容其他框架使用反射实例化 $className = $this->setModel(); if (class_exists($className)) { $reflectionClass = new ReflectionClass($className); - $instance = $reflectionClass->newInstance(); - return $instance; + return $reflectionClass->newInstance(); } else { - throw new LFlowException($className.'未知模型'); + throw new AdminException($className.'未知模型'); } - } /** @@ -201,13 +199,14 @@ abstract class BaseService * @param $id * @param array|null $field * @param array|null $with + * @param string $order * - * @return array|mixed + * @return array|Model|null * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ - public function get($id, ?array $field = [], ?array $with = []) + public function get($id, ?array $field = [], ?array $with = [], string $order = ''):mixed { if (is_array($id)) { $where = $id; @@ -216,6 +215,8 @@ abstract class BaseService } return $this->getModel()->where($where)->when(count($with), function ($query) use ($with) { $query->with($with); + })->when($order !== '', function ($query) use ($order) { + $query->order($order); })->field($field ?? ['*'])->find(); } @@ -297,19 +298,6 @@ abstract class BaseService return $this->getModel()->where($where)->delete(); } - /** - * 批量删除 - * - * @param array $ids - * @param string|null $key - * - * @return bool - */ - public function batchDelete(array $ids, ?string $key = null): bool - { - return $this->getModel()->whereIn(is_null($key) ? $this->getPk() : $key, $ids)->delete(); - } - /** * 删除记录 * @@ -333,9 +321,9 @@ abstract class BaseService * @param array $data * @param string|null $key * - * @return mixed + * @return BaseModel */ - public function updated(string|int|array $id, array $data, ?string $key = null): mixed + public function update(string|int|array $id, array $data, ?string $key = null): mixed { if (is_array($id)) { $where = $id; @@ -378,13 +366,13 @@ abstract class BaseService /** * 插入数据 * - * @param array $param + * @param array $data * * @return mixed */ - public function save(array $param): mixed + public function save(array $data): mixed { - return $this->getModel()::create($param); + return $this->getModel()::create($data); } /** diff --git a/demo/webman/backend/app/dao/system/admin/AdminAuthDao.php b/demo/webman/backend/app/dao/system/admin/AdminAuthDao.php new file mode 100644 index 0000000000000000000000000000000000000000..199ce5e1cfb18b1b32b56fa72dd67a14702d1def --- /dev/null +++ b/demo/webman/backend/app/dao/system/admin/AdminAuthDao.php @@ -0,0 +1,30 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemAdmin; + +/** + * + * + * @author Mr.April + * @since 1.0 + */ +class AdminAuthDao extends BaseDao +{ + protected function setModel(): string + { + return SystemAdmin::class; + } + +} diff --git a/demo/webman/backend/app/dao/system/admin/SystemAdminDao.php b/demo/webman/backend/app/dao/system/admin/SystemAdminDao.php new file mode 100644 index 0000000000000000000000000000000000000000..36a744d68aa2cc0f8893b3be1a2822957cb55c70 --- /dev/null +++ b/demo/webman/backend/app/dao/system/admin/SystemAdminDao.php @@ -0,0 +1,112 @@ +search($where)->page($page, $limit)->select()->toArray(); + } + + /** + * 用管理员名查找管理员信息 + * + * @param string $account + * + * @return array|\think\Model|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function accountByAdmin(string $account): array|\think\Model|null + { + return $this->search(['account' => $account, 'delete_time' => null])->find(); + } + + /** + * 当前账号是否可用 + * + * ./ + * @param string $account + * @param string $id + * + * @return int + * @throws \ReflectionException + * @throws \think\db\exception\DbException + */ + public function isAccountUsable(string $account, string $id) + { + return $this->search(['account' => $account, 'delete_time' => null])->where('id', '<>', $id)->count(); + } + + /** + * 获取adminid + * + * @param int $level + * + * @return array + */ + public function getAdminIds(int $level) + { + return $this->getModel()->where('level', '>=', $level)->column('id', 'id'); + } + + /** + * 获取低于等级的管理员名称和id + * + * @param string $field + * @param int $level + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getOrdAdmin(string $field = 'real_name,id', int $level = 0): array + { + return $this->getModel()->where('level', '>=', $level)->field($field)->select()->toArray(); + } + + /** + * 条件获取管理员数据 + * + * @param $where + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo($where): mixed + { + return $this->getModel()->where($where)->find(); + } + +} diff --git a/demo/webman/backend/app/dao/system/admin/SystemAdminDeptDao.php b/demo/webman/backend/app/dao/system/admin/SystemAdminDeptDao.php new file mode 100644 index 0000000000000000000000000000000000000000..28424f796abf3470e9ad4b6cd8b7f2eb8f80229f --- /dev/null +++ b/demo/webman/backend/app/dao/system/admin/SystemAdminDeptDao.php @@ -0,0 +1,49 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemAdminDept; + +/** + * 管理员关联-部门 + * + * @author Mr.April + * @since 1.0 + */ +class SystemAdminDeptDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemAdminDept::class; + } + + /** + * 指定条件获取某些角色权限的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } +} diff --git a/demo/webman/backend/app/dao/system/admin/SystemAdminPostDao.php b/demo/webman/backend/app/dao/system/admin/SystemAdminPostDao.php new file mode 100644 index 0000000000000000000000000000000000000000..fee88fee1decbde506a9f33c6eab1e155a8c5cb5 --- /dev/null +++ b/demo/webman/backend/app/dao/system/admin/SystemAdminPostDao.php @@ -0,0 +1,49 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemAdminPost; + +/** + * 管理员关联-职位 + * + * @author Mr.April + * @since 1.0 + */ +class SystemAdminPostDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemAdminPost::class; + } + + /** + * 指定条件获取某些角色权限的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } +} diff --git a/demo/webman/backend/app/dao/system/admin/SystemDeptDao.php b/demo/webman/backend/app/dao/system/admin/SystemDeptDao.php new file mode 100644 index 0000000000000000000000000000000000000000..3a100f7e1c9b4cf27227fcbfe466f657cb67d028 --- /dev/null +++ b/demo/webman/backend/app/dao/system/admin/SystemDeptDao.php @@ -0,0 +1,68 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemDept; + +/** + * 角色管理Dao层 + * + * @author Mr.April + * @since 1.0 + */ +class SystemDeptDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemDept::class; + } + + /** + * 获取组织列表 + * + * @param array $where + * @param int $page + * @param int $limit + * @param string $sort + * + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getDeptList(array $where, int $page, int $limit, string $sort = 'sort asc'): \think\Collection|array + { + return $this->search($where)->page($page, $limit)->order($sort)->select(); + } + + /** + * 指定条件获取某些组织的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + +} diff --git a/demo/webman/backend/app/dao/system/admin/SystemMenusDao.php b/demo/webman/backend/app/dao/system/admin/SystemMenusDao.php new file mode 100644 index 0000000000000000000000000000000000000000..b426215a79d31fdf16a76334289f34b22e9d8030 --- /dev/null +++ b/demo/webman/backend/app/dao/system/admin/SystemMenusDao.php @@ -0,0 +1,183 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemMenus; + +/** + * + * 菜单Dao层 + * @author Mr.April + * @since 1.0 + */ +class SystemMenusDao extends BaseDao +{ + + /** + * 设置模型 + * @return string + */ + protected function setModel(): string + { + return SystemMenus::class; + } + + /** + * + * @param array $menusIds + * + * @return bool + */ + public function deleteMenus(array $menusIds): bool + { + return $this->getModel()->whereIn('id', $menusIds)->delete(); + } + + /** + * 获取菜单列表 + * + * @param array $where + * @param array|null $field + * + * @return \think\Collection + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getMenusRoule(array $where, ?array $field = []): \think\Collection + { + if (!$field) { + $field = ['id', 'menu_name', 'icon', 'pid', 'sort', 'menu_path', 'auth_type','is_show', 'header', 'is_header', 'is_show_path', 'is_show']; + } + return $this->search($where)->field($field)->order('sort ASC')->failException(false)->select(); + } + + /** + * 获取菜单中的唯一权限 + * + * @param array $where + * + * @return array + * @throws \ReflectionException + */ + public function getMenusUnique(array $where): array + { + return $this->search($where)->where('unique_auth', '<>', '')->column('unique_auth', ''); + } + + /** + * 根据访问地址获得菜单名 + * + * @param string $rule + * + * @return mixed + * @throws \ReflectionException + */ + public function getVisitName(string $rule): mixed + { + return $this->search(['url' => $rule])->value('menu_name'); + } + + /** + * 获取后台菜单列表并分页 + * + * @param array $where + * @param array $field + * + * @return \think\Collection + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getMenusList(array $where, array $field = ['*']): \think\Collection + { + $where = array_merge($where, ['delete_time' => null]); + return $this->search($where)->field($field)->order('sort DESC,id ASC')->select(); + } + + /** + * 菜单总数 + * + * @param array $where + * + * @return int + * @throws \ReflectionException + */ + public function countMenus(array $where): int + { + $where = array_merge($where, ['delete' => null]); + return $this->count($where); + } + + /** + * 指定条件获取某些菜单的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + + /**菜单列表 + * + * @param array $where + * @param int $type + * + * @return \think\Collection + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function menusSelect(array $where, $type = 1): \think\Collection + { + if ($type == 1) { + return $this->search($where)->field('id,pid,menu_name,menu_path,unique_auth,sort')->order('sort DESC,id DESC')->select(); + } else { + return $this->search($where)->group('pid')->column('pid'); + } + } + + /** + * 搜索列表 + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function getSearchList(): \think\Collection|array + { + return $this->search(['is_show' => 1, 'auth_type' => 1, 'delete_time' => null, 'is_show_path' => 0]) + ->field('id,pid,menu_name,menu_path,unique_auth,sort')->order('sort DESC,id DESC')->select(); + } + + + /** + * + * @param string $path + * @param string $method + * + * @return bool + */ + public function deleteMenu(string $path, string $method): bool + { + return $this->getModel()->where('api_url', $path)->where('methods', $method)->delete(); + } +} diff --git a/demo/webman/backend/app/dao/system/admin/SystemPostDao.php b/demo/webman/backend/app/dao/system/admin/SystemPostDao.php new file mode 100644 index 0000000000000000000000000000000000000000..5ad9faba96ac046ce639a6d1bca193d2bc7c70e4 --- /dev/null +++ b/demo/webman/backend/app/dao/system/admin/SystemPostDao.php @@ -0,0 +1,67 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemPost; + +/** + * 角色管理Dao层 + * + * @author Mr.April + * @since 1.0 + */ +class SystemPostDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemPost::class; + } + + /** + * 获取职位列表 + * + * @param array $where + * @param int $page + * @param int $limit + * @param string $sort + * + * @return \think\Collection|array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getPostList(array $where, int $page, int $limit, string $sort = 'sort asc'): \think\Collection|array + { + return $this->search($where)->page($page, $limit)->order($sort)->select(); + } + + /** + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + +} diff --git a/demo/webman/backend/app/dao/system/admin/SystemRoleDao.php b/demo/webman/backend/app/dao/system/admin/SystemRoleDao.php new file mode 100644 index 0000000000000000000000000000000000000000..b6d37392b6d7a826f4c83b080f6abf3a4fde1493 --- /dev/null +++ b/demo/webman/backend/app/dao/system/admin/SystemRoleDao.php @@ -0,0 +1,69 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemRole; + +/** + * 角色管理Dao层 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRoleDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemRole::class; + } + + /** + * 获取身份列表 + * + * @param array $where + * @param int $page + * @param int $limit + * @param string $sort + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getRouleList(array $where, int $page, int $limit, string $sort = 'sort asc') + { + return $this->search($where)->page($page, $limit)->order($sort)->select()->toArray(); + } + + /** + * 指定条件获取某些角色的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + +} diff --git a/demo/webman/backend/app/dao/system/admin/SystemRoleDeptDao.php b/demo/webman/backend/app/dao/system/admin/SystemRoleDeptDao.php new file mode 100644 index 0000000000000000000000000000000000000000..2e212d860bfe6c55add0059b6e71b5604c38689c --- /dev/null +++ b/demo/webman/backend/app/dao/system/admin/SystemRoleDeptDao.php @@ -0,0 +1,50 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemRoleDept; + +/** + * 角色权限 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRoleDeptDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemRoleDept::class; + } + + /** + * 指定条件获取某些角色权限的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + +} diff --git a/demo/webman/backend/app/dao/system/admin/SystemRoleMenuDao.php b/demo/webman/backend/app/dao/system/admin/SystemRoleMenuDao.php new file mode 100644 index 0000000000000000000000000000000000000000..bda152963dc6a4a323566cfdfdd0d2a0e8fcce50 --- /dev/null +++ b/demo/webman/backend/app/dao/system/admin/SystemRoleMenuDao.php @@ -0,0 +1,50 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemRoleMenu; + +/** + * 角色权限 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRoleMenuDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemRoleMenu::class; + } + + /** + * 指定条件获取某些角色权限的名称以数组形式返回 + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + +} diff --git a/demo/webman/backend/app/dao/system/admin/SystemRolePostDao.php b/demo/webman/backend/app/dao/system/admin/SystemRolePostDao.php new file mode 100644 index 0000000000000000000000000000000000000000..bbba6706aef1e2f887fe2f865ddceba7daa06b77 --- /dev/null +++ b/demo/webman/backend/app/dao/system/admin/SystemRolePostDao.php @@ -0,0 +1,50 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\admin; + +use app\dao\BaseDao; +use app\model\system\admin\SystemRolePost; + +/** + * 角色关系表职位 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRolePostDao extends BaseDao +{ + /** + * 设置模型名 + * + * @return string + */ + protected function setModel(): string + { + return SystemRolePost::class; + } + + /** + * + * + * @param array $where + * @param string $field + * @param string $key + * + * @return array + * @throws \ReflectionException + */ + public function column(array $where, string $field, string $key = ''): array + { + return $this->search($where)->column($field, $key); + } + +} diff --git a/demo/webman/backend/app/dao/system/attachment/SystemAttachmentCategoryDao.php b/demo/webman/backend/app/dao/system/attachment/SystemAttachmentCategoryDao.php new file mode 100644 index 0000000000000000000000000000000000000000..f5d657a4591022e3eded75ddac259065805879a0 --- /dev/null +++ b/demo/webman/backend/app/dao/system/attachment/SystemAttachmentCategoryDao.php @@ -0,0 +1,72 @@ + +// +---------------------------------------------------------------------- +declare (strict_types=1); + +namespace app\dao\system\attachment; + +use app\dao\BaseDao; +use app\model\system\attachment\SystemAttachmentCategory; + +/** + * + * 附件分类Dao + * @author Mr.April + * @since 1.0 + */ +class SystemAttachmentCategoryDao extends BaseDao +{ + + /** + * 设置模型 + * @return string + */ + protected function setModel(): string + { + return SystemAttachmentCategory::class; + } + + /** + * 获取列表 + * @param array $where + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where) + { + return $this->search($where)->select()->toArray(); + } + + /** + * 获取数量 + * @param array $where + * @return int + */ + public function getCount(array $where) + { + return $this->search($where)->count(); + } + + /** + * 搜索附件分类search + * @param array $where + * @param bool $search + * @return \crmeb\basic\BaseModel|mixed|\think\Model + * @throws \ReflectionException + */ + public function search(array $where = [], bool $search = false) + { + return parent::search($where, $search)->when(isset($where['id']), function ($query) use ($where) { + $query->whereIn('id', $where['id']); + }); + } +} diff --git a/demo/webman/backend/app/dao/system/attachment/SystemAttachmentDao.php b/demo/webman/backend/app/dao/system/attachment/SystemAttachmentDao.php new file mode 100644 index 0000000000000000000000000000000000000000..561fec633fcdfbe136a57e922e6e74d454e45c4d --- /dev/null +++ b/demo/webman/backend/app/dao/system/attachment/SystemAttachmentDao.php @@ -0,0 +1,111 @@ + +// +---------------------------------------------------------------------- +declare (strict_types=1); + +namespace app\dao\system\attachment; + +use app\dao\BaseDao; +use app\model\system\attachment\SystemAttachment; + +/** + * + * Class SystemAttachmentDao + * @package app\dao\attachment + */ +class SystemAttachmentDao extends BaseDao +{ + + /** + * 设置模型 + * @return string + */ + protected function setModel(): string + { + return SystemAttachment::class; + } + + /** + * 获取图片列表 + * @param array $where + * @param int $page + * @param int $limit + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where, int $page, int $limit) + { + return $this->search($where)->where('module_type', 1)->page($page, $limit)->order('att_id DESC')->select()->toArray(); + } + + /** + * 移动图片 + * @param array $data + * @return \crmeb\basic\BaseModel + */ + public function move(array $data) + { + return $this->getModel()->whereIn('att_id', $data['images'])->update(['pid' => $data['pid']]); + } + + /** + * 获取名称 + * @param array $where + * @param int $page + * @param int $limit + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getLikeNameList(array $where, int $page, int $limit) + { + return $this->search($where)->page($page, $limit)->order('att_id desc')->select()->toArray(); + } + + /** + * 获取昨日系统生成 + * @return \think\Collection + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getYesterday() + { + return $this->getModel()->whereTime('time', 'yesterday')->where('module_type', 2)->field(['name', 'att_dir', 'att_id', 'image_type'])->select(); + } + + /** + * 删除昨日生成海报 + * @throws \Exception + */ + public function delYesterday() + { + $this->getModel()->whereTime('time', 'yesterday')->where('module_type', 2)->delete(); + } + + /** + * 获取扫码上传的图片数据 + * @param $scan_token + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/06/13 + */ + public function scanUploadImage($scan_token) + { + return $this->getModel()->where('scan_token', $scan_token)->field('att_dir,att_id')->select()->toArray(); + } +} diff --git a/demo/webman/backend/app/dao/system/config/SystemConfigDao.php b/demo/webman/backend/app/dao/system/config/SystemConfigDao.php new file mode 100644 index 0000000000000000000000000000000000000000..5a8466230f82ed7a1299b17019a62863cc2c8179 --- /dev/null +++ b/demo/webman/backend/app/dao/system/config/SystemConfigDao.php @@ -0,0 +1,100 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\config; + +use app\dao\BaseDao; +use app\model\system\config\SystemConfig; + +/** + * 系统配置 + * Class SystemConfigDao + * @package app\dao\system\config + */ +class SystemConfigDao extends BaseDao +{ + /** + * 设置模型 + * @return string + */ + protected function setModel(): string + { + return SystemConfig::class; + } + + /** + * 获取某个系统配置 + * @param string $configNmae + * @return mixed + * @throws \ReflectionException + */ + public function getConfigValue(string $configNmae) + { + return $this->search(['menu_name' => $configNmae])->value('value'); + } + + /** + * 获取所有配置 + * @param array $configName + * @return array + * @throws \ReflectionException + */ + public function getConfigAll(array $configName = []) + { + if ($configName) { + return $this->search(['menu_name' => $configName])->column('value', 'menu_name'); + } else { + return $this->getModel()->column('value', 'menu_name'); + } + } + + /** + * 获取配置列表分页 + * @param array $where + * @param int $page + * @param int $limit + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfigList(array $where, int $page, int $limit) + { + return $this->search($where)->page($page, $limit)->order('sort desc')->select()->toArray(); + } + + /** + * 获取某些分类配置下的配置列表 + * @param int $tabId + * @param int $status + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfigTabAllList(int $tabId, int $status = 1) + { + $where['tab_id'] = $tabId; + if ($status == 1) $where['status'] = $status; + return $this->search($where)->order('sort desc,id ASC')->select()->toArray(); + } + + /** + * 获取上传配置中的上传类型 + * @param string $configName + * @return array + * @throws \ReflectionException + */ + public function getUploadTypeList(string $configName) + { + return $this->search(['menu_name' => $configName])->column('upload_type', 'type'); + } +} diff --git a/demo/webman/backend/app/dao/system/config/SystemConfigTabDao.php b/demo/webman/backend/app/dao/system/config/SystemConfigTabDao.php new file mode 100644 index 0000000000000000000000000000000000000000..3cfc197203fac12f567a1bc7b6a5a4b63ee08fee --- /dev/null +++ b/demo/webman/backend/app/dao/system/config/SystemConfigTabDao.php @@ -0,0 +1,65 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\config; + + +use app\dao\BaseDao; +use app\model\system\config\SystemConfigTab; + +/** + * 配置分类 + * Class SystemConfigTabDao + * @package app\dao\system\config + */ +class SystemConfigTabDao extends BaseDao +{ + /** + * 设置模型 + * @return string + */ + protected function setModel(): string + { + return SystemConfigTab::class; + } + + /** + * 获取配置分类 + * @param array $where + * @param array $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfigTabAll(array $searchWhere, array $field = ['*'], array $where = []) + { + return $this->search($searchWhere)->when(count($where), function ($query) use ($where) { + $query->where($where); + })->field($field)->order('sort desc,id asc')->select()->toArray(); + } + + /** + * 配置分类列表 + * @param array $where + * @param int $page + * @param int $limit + * @return \think\Collection + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfgTabList(array $where, int $page, int $limit) + { + return $this->search($where)->order('sort desc,id asc')->select(); + } + +} diff --git a/demo/webman/backend/app/dao/system/config/SystemGroupDao.php b/demo/webman/backend/app/dao/system/config/SystemGroupDao.php new file mode 100644 index 0000000000000000000000000000000000000000..8739fb74e276f6401cf0fced5dc519559f0cae01 --- /dev/null +++ b/demo/webman/backend/app/dao/system/config/SystemGroupDao.php @@ -0,0 +1,57 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\config; + +use app\dao\BaseDao; +use app\model\system\config\SystemGroup; + +/** + * Class SystemGroupDao + * @package app\dao\system\config + */ +class SystemGroupDao extends BaseDao +{ + /** + * @return string + */ + protected function setModel(): string + { + return SystemGroup::class; + } + + /** + * 获取组合数据分页列表 + * @param array $where + * @param int $page + * @param int $limit + * @return \think\Collection + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGroupList(array $where, array $field = ['*'], int $page = 0, int $limit = 0) + { + return $this->search($where)->field($field)->when($page && $limit, function ($query) use ($page, $limit) { + $query->page($page, $limit); + })->select()->toArray(); + } + + /** + * 根据配置名称获取配置id + * @param string $configName + * @return mixed + */ + public function getConfigNameId(string $configName) + { + return $this->value(['config_name' => $configName]); + } +} diff --git a/demo/webman/backend/app/dao/system/config/SystemGroupDataDao.php b/demo/webman/backend/app/dao/system/config/SystemGroupDataDao.php new file mode 100644 index 0000000000000000000000000000000000000000..48be28e2241624a7e12b1fb8a4f00e3da10c5002 --- /dev/null +++ b/demo/webman/backend/app/dao/system/config/SystemGroupDataDao.php @@ -0,0 +1,97 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\config; + +use app\dao\BaseDao; +use app\model\system\config\SystemGroupData; + +/** + * 组合数据 + * Class SystemGroupDataDao + * @package app\dao\system\config + */ +class SystemGroupDataDao extends BaseDao +{ + /** + * 设置模型 + * @return string + */ + protected function setModel(): string + { + return SystemGroupData::class; + } + + /** + * 获取组合数据列表 + * @param array $where + * @param int $page + * @param int $limit + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGroupDataList(array $where, int $page, int $limit) + { + return $this->search($where)->page($page, $limit)->order('sort desc,id DESC')->select()->toArray(); + } + + /** + * 获取某个gid下的组合数据 + * @param int $gid + * @param int $limit + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGroupDate(int $gid, int $limit = 0) + { + return $this->search(['gid' => $gid, 'status' => 1])->when($limit, function ($query) use ($limit) { + $query->limit($limit); + })->field('value,id')->order('sort DESC,id DESC')->select()->toArray(); + } + + /** + * 根据id获取秒杀数据 + * @param array $ids + * @param string $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function idByGroupList(array $ids, string $field) + { + return $this->getModel()->whereIn('id', $ids)->field($field)->select()->toArray(); + } + + /** + * 根据gid删除组合数据 + * @param int $gid + * @return bool + */ + public function delGroupDate(int $gid) + { + return $this->getModel()->where('gid', $gid)->delete(); + } + + /** + * 批量保存 + * @param array $data + * @return mixed|\think\Collection + * @throws \Exception + */ + public function saveAll(array $data) + { + return $this->getModel()->saveAll($data); + } +} diff --git a/demo/webman/backend/app/dao/system/config/SystemStorageDao.php b/demo/webman/backend/app/dao/system/config/SystemStorageDao.php new file mode 100644 index 0000000000000000000000000000000000000000..3cf199110a78998fe3770ec5dee048b23d82a76a --- /dev/null +++ b/demo/webman/backend/app/dao/system/config/SystemStorageDao.php @@ -0,0 +1,81 @@ + +// +---------------------------------------------------------------------- + +namespace app\dao\system\config; + + +use app\dao\BaseDao; +use app\model\system\config\SystemStorage; + +/** + * Class SystemStorageDao + * @package app\dao\system\config + */ +class SystemStorageDao extends BaseDao +{ + + /** + * @return string + */ + protected function setModel(): string + { + return SystemStorage::class; + } + + /** + * 获取列表 + * @param array $where + * @param array|string[] $field + * @param int $page + * @param int $limit + * @param null $sort + * @param array $with + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where = [], array $field = ['*'], int $page = 0, int $limit = 0, $sort = null, array $with = []) + { + return $this->search($where)->field($field)->when($page && $limit, function ($query) use ($page, $limit) { + $query->page($page, $limit); + })->when($sort, function ($query) use ($sort) { + if (is_array($sort)) { + foreach ($sort as $v => $k) { + if (is_numeric($v)) { + $query->order($k, 'desc'); + } else { + $query->order($v, $k); + } + } + } else { + $query->order($sort, 'desc'); + } + })->with($with)->select()->toArray(); + } + + /** + * @param array $where + * @param bool $search + * @return \crmeb\basic\BaseModel|mixed|\think\Model + * @throws \ReflectionException + */ + public function search(array $where = [], bool $search = false) + { + return parent::search($where, $search)->when(isset($where['type']), function ($query) use ($where) { + $query->where('type', $where['type']); + })->where('is_delete', 0)->when(isset($where['access_key']), function ($query) use ($where) { + $query->where('access_key', $where['access_key']); + })->when(!empty($where['id']), function ($query) use ($where) { + $query->where('id', $where['id']); + }); + } +} diff --git a/demo/webman/backend/app/dao/system/crontab/SystemCrontabDao.php b/demo/webman/backend/app/dao/system/crontab/SystemCrontabDao.php new file mode 100644 index 0000000000000000000000000000000000000000..3eddc90e862f9f9c513ee0ba363e5c78684f774c --- /dev/null +++ b/demo/webman/backend/app/dao/system/crontab/SystemCrontabDao.php @@ -0,0 +1,24 @@ +getModel()->where('name', $name)->find(); + } +} diff --git a/demo/webman/backend/app/dao/system/lang/LangCodeDao.php b/demo/webman/backend/app/dao/system/lang/LangCodeDao.php new file mode 100644 index 0000000000000000000000000000000000000000..f5253381fa90c2f1a8c13699dfae4e9e1c79c230 --- /dev/null +++ b/demo/webman/backend/app/dao/system/lang/LangCodeDao.php @@ -0,0 +1,18 @@ +getModel()->where('create_time', '<', time() - 7776000)->delete(); + } + + /** + * 获取系统日志列表 + * + * @param array $where + * @param int $page + * @param int $limit + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function getLogList(array $where, int $page, int $limit): array + { + return $this->search($where)->page($page, $limit)->order('create_time DESC')->select()->toArray(); + } + +} diff --git a/demo/webman/backend/app/dao/system/route/SystemRouteCateDao.php b/demo/webman/backend/app/dao/system/route/SystemRouteCateDao.php new file mode 100644 index 0000000000000000000000000000000000000000..67b83b8caf24b2bf7f1f465ce2e41dcb5be5e23f --- /dev/null +++ b/demo/webman/backend/app/dao/system/route/SystemRouteCateDao.php @@ -0,0 +1,40 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\dao\system\route; + + +use app\dao\BaseDao; +use app\model\system\route\SystemRouteCate; + +/** + * Class SystemRouteCateDao + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + * @package app\dao\system + */ +class SystemRouteCateDao extends BaseDao +{ + + /** + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + protected function setModel(): string + { + return SystemRouteCate::class; + } +} diff --git a/demo/webman/backend/app/dao/system/route/SystemRouteDao.php b/demo/webman/backend/app/dao/system/route/SystemRouteDao.php new file mode 100644 index 0000000000000000000000000000000000000000..398ab02d43b2cb3ad4c4e97876ee4c45c941df73 --- /dev/null +++ b/demo/webman/backend/app/dao/system/route/SystemRouteDao.php @@ -0,0 +1,55 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\dao\system\route; + + +use app\dao\BaseDao; +use app\model\system\route\SystemRoute; + + +/** + * Class SystemRouteDao + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + * @package app\dao\system + */ +class SystemRouteDao extends BaseDao +{ + + /** + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + protected function setModel(): string + { + return SystemRoute::class; + } + + /** + * @param array $ids + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/23 + */ + public function deleteRoutes(array $ids) + { + return $this->getModel()::destroy(function ($q) use ($ids) { + $q->whereIn('id', $ids); + }, true); + } +} diff --git a/demo/webman/backend/app/exception/AdminException.php b/demo/webman/backend/app/exception/AdminException.php new file mode 100644 index 0000000000000000000000000000000000000000..d98116ce5bfb57ea24425de415cc2d1fd7ff2696 --- /dev/null +++ b/demo/webman/backend/app/exception/AdminException.php @@ -0,0 +1,25 @@ + 'application/json'], json_encode(['code' => $this->getCode(), 'msg' => $this->getMessage()], JSON_UNESCAPED_UNICODE)); + } +} diff --git a/demo/webman/backend/app/exception/AuthException.php b/demo/webman/backend/app/exception/AuthException.php new file mode 100644 index 0000000000000000000000000000000000000000..5c3c20072ff0a6d851b7ad9da2a8aeb8978510d2 --- /dev/null +++ b/demo/webman/backend/app/exception/AuthException.php @@ -0,0 +1,17 @@ + 'application/json'], json_encode(['code' => $this->getCode(), 'msg' => $this->getMessage()], JSON_UNESCAPED_UNICODE)); + } +} diff --git a/demo/webman/backend/app/functions.php b/demo/webman/backend/app/functions.php new file mode 100644 index 0000000000000000000000000000000000000000..db8cedbaaeacd2c814e82e0faea8db8fe2880045 --- /dev/null +++ b/demo/webman/backend/app/functions.php @@ -0,0 +1,92 @@ +get($name); +// if (is_array($sysConfig)) { +// foreach ($sysConfig as &$item) { +// if (strpos($item, '/uploads/system/') !== false || strpos($item, '/statics/system_images/') !== false) $item = set_file_url($item); +// } +// } else { +// if (strpos($sysConfig, '/uploads/system/') !== false || strpos($sysConfig, '/statics/system_images/') !== false) $sysConfig = set_file_url($sysConfig); +// } +// $config = is_array($sysConfig) ? $sysConfig : trim($sysConfig); +// if ($config === '' || $config === false) { +// return $default; +// } else { +// return $config; +// } +// } +//} +// +//if (!function_exists('sys_data')) { +// /** +// * 获取系统单个配置 +// * +// * @param string $name +// * @param int $limit +// * +// * @return string +// */ +// function sys_data(string $name, int $limit = 0): string +// { +// $services = \support\Container::make(SystemGroupDataServices::class); +// return $services->getData($name, $limit); +// } +//} +// +//if (!function_exists('get_phoenix_version')) { +// /** +// * 获取系统版本号 +// * +// * @param string $default +// * +// * @return string +// */ +// function get_phoenix_version(string $default = 'v1.0.0'): string +// { +// try { +// $version = parse_ini_file(app()->getRootPath() . '.version'); +// return $version['version'] ?? $default; +// } catch (\Throwable $e) { +// return $default; +// } +// } +//} +// +//if (!function_exists('get_file_link')) { +// /** +// * 获取文件带域名的完整路径 +// * +// * @param string $link +// * +// * @return string +// */ +// function get_file_link(string $link): string +// { +// if (!$link) { +// return ''; +// } +// if (strstr('http', $link) === false) { +//// return request()->domain() . $link; +// return ''; +// } else { +// return $link; +// } +// } +//} \ No newline at end of file diff --git a/src/libs/base/BaseModel.php b/demo/webman/backend/app/model/BaseModel.php similarity index 55% rename from src/libs/base/BaseModel.php rename to demo/webman/backend/app/model/BaseModel.php index 5fe7376a4945d6bcf6d3ef622dd74372ffa7f671..46c8d901bd32ffb16d21af8717bedf0c661d6e64 100644 --- a/src/libs/base/BaseModel.php +++ b/demo/webman/backend/app/model/BaseModel.php @@ -1,28 +1,19 @@ getConfig('prefix') . $self->name; } + public static function getTableNameNoPrefix(): string + { + $self = (new static()); + return $self->name; + } + } diff --git a/demo/webman/backend/app/model/system/admin/SystemAdmin.php b/demo/webman/backend/app/model/system/admin/SystemAdmin.php new file mode 100644 index 0000000000000000000000000000000000000000..43ca45f3db5cb9aadc815446855e100db4aa7dea --- /dev/null +++ b/demo/webman/backend/app/model/system/admin/SystemAdmin.php @@ -0,0 +1,182 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; +use think\Model; + +/** + * 管理员模型 + * Class SystemAdmin + * + * @package app\model\system\admin + */ +class SystemAdmin extends BaseModel +{ + use ModelTrait; + use JwtAuthModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_admin'; + + protected array $insert = ['create_time', 'update_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + 'last_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * inID搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIdInAttr(Query $query, $value) + { + if (!empty($value)) { + $query->whereIn('id', $value); + } + } + + /** + * 管理员级别搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchLevelAttr(Query $query, $value) + { + if (is_array($value)) { + $query->where('level', $value[0], $value[1]); + } else { + $query->where('level', $value); + } + } + + /** + * 管理员账号和姓名搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchAccountLikeAttr(Query $query, $value) + { + if ($value) { + $query->whereLike('account|real_name', '%' . $value . '%'); + } + } + + public function searchNotAccountAttr(Query $query, $value) + { + if ($value) { + $query->where('account', '<>', $value); + } + } + + /** + * 管理员账号搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchAccountAttr(Query $query, $value) + { + if ($value) { + $query->where('account', $value); + } + } + + /** + * 管理员账号搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchInAccountAttr(Query $query, $value) + { + if ($value) { + $query->whereIn('account', $value); + } + } + + /** + * 是否删除搜索器 + * + * @param \think\db\Query $query + */ + public function searchIsDelAttr(Query $query) + { + $query->where('delete_time', null); + } + + /** + * 状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + if ($value != '' && $value != null) { + $query->where('status', $value); + } + } + + /** + * 定义多对多远程关联部门模型 + * + * @return \think\model\relation\HasManyThrough + */ + public function departments(): \think\model\relation\HasManyThrough + { + //目标模型 中间模型 关联中间模型字段 关联最终模型字段 当前模型关联中间模型字段 最终模型关联字段 + return $this->hasManyThrough(SystemDept::class, SystemAdminDept::class, 'admin_id', 'dept_id', 'id', 'dept_id'); + } + + /** + * 定义多对多远程关联职位 + */ + public function positions(): \think\model\relation\HasManyThrough + { + return $this->hasManyThrough(SystemPost::class, SystemAdminPost::class, 'admin_id', 'post_id', 'id', 'post_id'); + } + +} diff --git a/demo/webman/backend/app/model/system/admin/SystemAdminDept.php b/demo/webman/backend/app/model/system/admin/SystemAdminDept.php new file mode 100644 index 0000000000000000000000000000000000000000..d27f6f35511f99350fd0eccbbdb88d249d268fc8 --- /dev/null +++ b/demo/webman/backend/app/model/system/admin/SystemAdminDept.php @@ -0,0 +1,69 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; + + +/** + * 管理员关联组织 + * + * @author Mr.April + * @since 1.0 + */ +class SystemAdminDept extends BaseModel +{ + use ModelTrait; + + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_admin_dept'; + + /** + * adminId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchAdminIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('admin_id', $value); + } else { + $query->where('admin_id', $value); + } + } + + /** + * deptId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchDeptIdAttr(Query $query, $value) + { + if ($value) { + if (is_array($value)) { + $query->whereIn('dept_id', $value); + } else { + $query->where('dept_id', $value); + } + } + } +} diff --git a/demo/webman/backend/app/model/system/admin/SystemAdminPost.php b/demo/webman/backend/app/model/system/admin/SystemAdminPost.php new file mode 100644 index 0000000000000000000000000000000000000000..a4430de157f1c26ea40136ccc2f3f30fc3ba8cc3 --- /dev/null +++ b/demo/webman/backend/app/model/system/admin/SystemAdminPost.php @@ -0,0 +1,69 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; +use think\Model; + +/** + * 管理员关联-职位 + * + * @author Mr.April + * @since 1.0 + */ +class SystemAdminPost extends BaseModel +{ + use ModelTrait; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_admin_post'; + + /** + * adminId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchAdminIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('admin_id', $value); + } else { + $query->where('admin_id', $value); + } + } + + /** + * menuId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPostIdAttr(Query $query, $value) + { + if ($value) { + if (is_array($value)) { + $query->whereIn('post_id', $value); + } else { + $query->where('post_id', $value); + } + } + } + +} diff --git a/demo/webman/backend/app/model/system/admin/SystemDept.php b/demo/webman/backend/app/model/system/admin/SystemDept.php new file mode 100644 index 0000000000000000000000000000000000000000..11f581a1de4f6b6be13521451d03184a6eaef0c3 --- /dev/null +++ b/demo/webman/backend/app/model/system/admin/SystemDept.php @@ -0,0 +1,131 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; +use think\Model; + +/** + * 组织管理 + * + * @author Mr.April + * @since 1.0 + */ +class SystemDept extends BaseModel +{ + use ModelTrait; + + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'dept_id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_dept'; + + protected array $insert = ['create_time', 'update_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + 'delete_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 生成字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 权限规格状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + if ($value != '') { + $query->where('status', $value ?: 1); + } + } + + /** + * id搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('role_id', $value); + } else { + $query->where('role_id', $value); + } + } + + /** + * 身份管理搜索 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchDeptNameAttr(Query $query, $value) + { + if ($value) { + $query->whereLike('dept_name', '%' . $value . '%'); + } + } + + /** + * Pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + $query->where('pid', $value ?? '-1'); + } + + /** + * Type搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchDeptTypeAttr(Query $query, $value) + { + if (!empty($value)) { + $query->where('dept_type', $value); + } + } + +} diff --git a/demo/webman/backend/app/model/system/admin/SystemMenus.php b/demo/webman/backend/app/model/system/admin/SystemMenus.php new file mode 100644 index 0000000000000000000000000000000000000000..41b298d0e5dc9764cd807c8a1eba0f1c92150701 --- /dev/null +++ b/demo/webman/backend/app/model/system/admin/SystemMenus.php @@ -0,0 +1,289 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; + +/** + * 菜单规则模型 + * Class SystemMenus + * + * @package app\model\system + */ +class SystemMenus extends BaseModel +{ + use ModelTrait; + + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + protected string $pkType = 'string'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_menus'; + + protected array $insert = ['create_time', 'update_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 参数修改器 + * + * @param $value + * + * @return false|string + */ + public function setParamsAttr($value): bool|string + { + $value = $value ? explode('/', $value) : []; + $params = array_chunk($value, 2); + $data = []; + foreach ($params as $param) { + if (isset($param[0]) && isset($param[1])) $data[$param[0]] = $param[1]; + } + return json_encode($data); + } + + /** + * 参数获取器 + * + * @param $_value + * + * @return mixed + */ + public function getParamsAttr($_value): mixed + { + return json_decode($_value, true); + } + + /** + * pid获取器 + * + * @param $value + * + * @return mixed|string + */ + public function getPidStrAttr($value): mixed + { + return !$value ? '顶级' : $this->where('pid', $value)->value('menu_name'); + } + + /** + * 默认条件查询器 + * + * @param \think\db\Query $query + */ + public function searchDefaultAttr(Query $query) + { + $query->where(['is_show' => 1, 'access' => 1]); + } + + /** + * 是否显示搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIsShowAttr(Query $query, $value) + { + if ($value != '') { + $query->where('is_show', $value); + } + } + + /** + * 是否删除搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIsDelAttr(Query $query, $value) + { + $query->where('delete_time', $value); + } + + /** + * Pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + $query->where('pid', $value ?? '-1'); + } + + /** + * 规格搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRuleAttr(Query $query, $value) + { + $query->whereIn('id', $value)->where('delete_time', null); + } + + /** + * 搜索菜单 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchKeywordAttr(Query $query, $value) + { + if ($value != '') { + $query->whereLike('menu_name|id|pid', "%$value%"); + } + } + + /** + * 方法搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchActionAttr(Query $query, $value) + { + $query->where('action', $value); + } + + /** + * 控制器搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchControllerAttr(Query $query, $value) + { + $query->where('controller', lcfirst($value)); + } + + /** + * 访问地址搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchUrlAttr(Query $query, $value) + { + $query->where('api_url|menu_path', $value); + } + + /** + * 参数搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchParamsAttr(Query $query, $value) + { + $query->where(function ($query) use ($value) { + $query->where('params', $value)->whereOr('params', "'[]'"); + }); + } + + /** + * 权限标识搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchUniqueAttr(Query $query, $value) + { + $query->where('delete_time', null); + if ($value) { + $query->whereIn('id', $value); + } + } + + /** + * 菜单规格搜索 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRouteAttr(Query $query, $value) + { + $query->where('auth_type', 1)->where('delete_time', null); + if ($value) { + $query->whereIn('id', $value); + } + } + + /** + * Id搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIdAttr(Query $query, $value) + { + $query->whereIn('id', $value); + } + + /** + * is_show_path + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIsShowPathAttr(Query $query, $value) + { + $query->where('is_show_path', $value); + } + + /** + * auth_type + * + * @param \think\db\Query $query + * @param $value + */ + public function searchAuthTypeAttr(Query $query, $value) + { + if ($value !== '') { + if ($value == 3) { + $query->whereIn('auth_type', [1, 3]); + } else { + $query->where('auth_type', $value); + } + } + } +} diff --git a/demo/webman/backend/app/model/system/admin/SystemPost.php b/demo/webman/backend/app/model/system/admin/SystemPost.php new file mode 100644 index 0000000000000000000000000000000000000000..a7c1f9b37135e707a0c918da7b11e19d41cecb39 --- /dev/null +++ b/demo/webman/backend/app/model/system/admin/SystemPost.php @@ -0,0 +1,128 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; +use think\Model; + +/** + * 职位管理 + * + * @author Mr.April + * @since 1.0 + */ +class SystemPost extends BaseModel +{ + use ModelTrait; + + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'post_id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_post'; + + protected array $insert = ['create_time', 'update_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + 'delete_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 生成字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 权限规格状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + if ($value != '') { + $query->where('status', $value ?: 1); + } + } + + /** + * post_code搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPostCodeAttr(Query $query, $value) + { + if (!empty($value)) { + $query->whereLike('post_code', '%' . $value . '%'); + } + } + + /** + * post_name搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPostNameAttr(Query $query, $value) + { + if (!empty($value)) { + $query->whereLike('post_name', '%' . $value . '%'); + } + } + + /** + * 关联部门搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchDeptIdAttr(Query $query, $value) + { + if (!empty($value)) { + $query->where('dept_id', $value); + } + } + + /** + * Pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + $query->where('pid', $value ?? '-1'); + } +} diff --git a/demo/webman/backend/app/model/system/admin/SystemRole.php b/demo/webman/backend/app/model/system/admin/SystemRole.php new file mode 100644 index 0000000000000000000000000000000000000000..3128ba8c079c8610854c83960a01aa11a0b4f0c9 --- /dev/null +++ b/demo/webman/backend/app/model/system/admin/SystemRole.php @@ -0,0 +1,116 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; +use think\Model; + +/** + * 管理员权限规则 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRole extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'role_id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_role'; + + protected array $insert = ['create_time', 'update_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + 'delete_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 生成字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 权限规格状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + if ($value != '') { + $query->where('status', $value ?: 1); + } + } + + /** + * id搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('role_id', $value); + } else { + $query->where('role_id', $value); + } + } + + /** + * 身份管理搜索 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRoleNameAttr(Query $query, $value) + { + if ($value) { + $query->whereLike('role_name', '%' . $value . '%'); + } + } + + /** + * Pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + $query->where('pid', $value ?? '-1'); + } +} diff --git a/demo/webman/backend/app/model/system/admin/SystemRoleDept.php b/demo/webman/backend/app/model/system/admin/SystemRoleDept.php new file mode 100644 index 0000000000000000000000000000000000000000..1a84ea65e657812480a9486f6d7565abdad7b9d8 --- /dev/null +++ b/demo/webman/backend/app/model/system/admin/SystemRoleDept.php @@ -0,0 +1,70 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; + + +/** + * 角色关联组织 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRoleDept extends BaseModel +{ + use ModelTrait; + + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_role_dept'; + + + /** + * roleId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRoleIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('role_id', $value); + } else { + $query->where('role_id', $value); + } + } + + /** + * menuId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchDeptIdAttr(Query $query, $value) + { + if ($value) { + if (is_array($value)) { + $query->whereIn('dept_id', $value); + } else { + $query->where('dept_id', $value); + } + } + } +} diff --git a/demo/webman/backend/app/model/system/admin/SystemRoleMenu.php b/demo/webman/backend/app/model/system/admin/SystemRoleMenu.php new file mode 100644 index 0000000000000000000000000000000000000000..0576a04bef19f54055f8c65a1ab92e0f6123ad3f --- /dev/null +++ b/demo/webman/backend/app/model/system/admin/SystemRoleMenu.php @@ -0,0 +1,71 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; + + +/** + * 管理员权限规则 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRoleMenu extends BaseModel +{ + use ModelTrait; + + + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_role_menu'; + + + /** + * roleId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRoleIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('role_id', $value); + } else { + $query->where('role_id', $value); + } + } + + /** + * menuId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchMenuIdAttr(Query $query, $value) + { + if ($value) { + if (is_array($value)) { + $query->whereIn('menu_id', $value); + } else { + $query->where('menu_id', $value); + } + } + } +} diff --git a/demo/webman/backend/app/model/system/admin/SystemRolePost.php b/demo/webman/backend/app/model/system/admin/SystemRolePost.php new file mode 100644 index 0000000000000000000000000000000000000000..e68fd53e4295f18d0ab66f4bd75aed387427a16f --- /dev/null +++ b/demo/webman/backend/app/model/system/admin/SystemRolePost.php @@ -0,0 +1,70 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\admin; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; + + +/** + * 角色关联组织 + * + * @author Mr.April + * @since 1.0 + */ +class SystemRolePost extends BaseModel +{ + use ModelTrait; + + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_role_post'; + + + /** + * roleId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRoleIdAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('role_id', $value); + } else { + $query->where('role_id', $value); + } + } + + /** + * menuId搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPostIdAttr(Query $query, $value) + { + if ($value) { + if (is_array($value)) { + $query->whereIn('post_id', $value); + } else { + $query->where('post_id', $value); + } + } + } +} diff --git a/demo/webman/backend/app/model/system/attachment/SystemAttachment.php b/demo/webman/backend/app/model/system/attachment/SystemAttachment.php new file mode 100644 index 0000000000000000000000000000000000000000..7b8b35bfce4aec1467447564b6f2272fc8337344 --- /dev/null +++ b/demo/webman/backend/app/model/system/attachment/SystemAttachment.php @@ -0,0 +1,100 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\attachment; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; +use think\Model; + +/** + * 附件管理模型 + * + * @author Mr.April + * @since 1.0 + */ +class SystemAttachment extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'att_id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_attachment'; + + /** + * ID 生成 + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 图片类型搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchModuleTypeAttr(Query $query, $value) + { + $query->where('module_type', $value ?: 1); + } + + /** + * pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + if ($value) $query->where('pid', $value); + } + + /** + * name模糊搜索 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchLikeNameAttr(Query $query, $value) + { + if ($value) $query->where('name', 'LIKE', "$value%"); + } + + /** + * real_name模糊搜索 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchRealNameAttr(Query $query, $value) + { + if ($value != '') $query->where('real_name', 'LIKE', "%$value%"); + } +} diff --git a/demo/webman/backend/app/model/system/attachment/SystemAttachmentCategory.php b/demo/webman/backend/app/model/system/attachment/SystemAttachmentCategory.php new file mode 100644 index 0000000000000000000000000000000000000000..0af947013d6836303a181e74d9a7e23367436a91 --- /dev/null +++ b/demo/webman/backend/app/model/system/attachment/SystemAttachmentCategory.php @@ -0,0 +1,79 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\attachment; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; +use think\Model; + +/** + * + * 附件管理分类模型 + * @author Mr.April + * @since 1.0 + */ +class SystemAttachmentCategory extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_attachment_category'; + + /** + * ID 生成 + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 附件分类昵称搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchNameAttr(Query $query, $value) + { + if ($value != '') $query->where('name', 'like', '%' . $value . '%'); + } + + /** + * pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + if ($value !== '') $query->where('pid', $value); + } + +} diff --git a/demo/webman/backend/app/model/system/config/SystemConfig.php b/demo/webman/backend/app/model/system/config/SystemConfig.php new file mode 100644 index 0000000000000000000000000000000000000000..6435a906f7568e83951db682b46619c91540c608 --- /dev/null +++ b/demo/webman/backend/app/model/system/config/SystemConfig.php @@ -0,0 +1,119 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\config; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; + +/** + * 系统配置模型 + * + * @author Mr.April + * @since 1.0 + */ +class SystemConfig extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_config'; + + /** + * 模型ID触发器 + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 菜单名搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchMenuNameAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('menu_name', $value); + } else { + if (!empty($value)) { + $query->where('menu_name', $value); + } + } + } + + /** + * Info搜索 + * @param \think\db\Query $query + * @param $value + */ + public function searchInfoAttr(Query $query, $value) + { + if (!empty($value)) { + $query->whereLike('info', $value . '%'); + } + } + + /** + * tab id 搜索 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchTabIdAttr(Query $query, $value) + { + if (!empty($value)) { + $query->where('config_tab_id', $value); + } + } + + /** + * 状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + $query->where('status', $value ?: 1); + } + + /** + * value搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchValueAttr(Query $query, $value) + { + $query->where('value', $value); + } +} diff --git a/demo/webman/backend/app/model/system/config/SystemConfigTab.php b/demo/webman/backend/app/model/system/config/SystemConfigTab.php new file mode 100644 index 0000000000000000000000000000000000000000..7633a6b2df7dc9b97b66bb4912b7377edefe03e2 --- /dev/null +++ b/demo/webman/backend/app/model/system/config/SystemConfigTab.php @@ -0,0 +1,111 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\config; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; +use think\Model; + + +/** + * + * 配置分类模型 + * @author Mr.April + * @since 1.0 + */ +class SystemConfigTab extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_config_tab'; + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * 状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + if ($value != '') { + $query->where('status', $value); + } + } + + /** + * pid搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchPidAttr(Query $query, $value) + { + if (is_array($value)) { + $query->whereIn('pid', $value); + } else { + $value && $query->where('pid', $value); + } + } + + /** + * 类型搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchTypeAttr(Query $query, $value) + { + $query->where('status', 1); + if ($value > -1) { + $query->where(['type' => $value, 'pid' => 0]); + } + } + + /** + * 分类名称搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchTitleAttr(Query $query, $value) + { + $query->whereLike('title', '%' . $value . '%'); + } + +} diff --git a/demo/webman/backend/app/model/system/config/SystemGroup.php b/demo/webman/backend/app/model/system/config/SystemGroup.php new file mode 100644 index 0000000000000000000000000000000000000000..7fc919122ab98747f7386dd434ef33bbac618bec --- /dev/null +++ b/demo/webman/backend/app/model/system/config/SystemGroup.php @@ -0,0 +1,70 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\config; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\Model; + +/** + * 组合数据配置模型 + * Class SystemGroup + * @package app\model\system\config + */ +class SystemGroup extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * @var string + */ + protected $name = 'system_group'; + + /** + * 配置名搜索器 + * @param Model $query + * @param $value + */ + public function searchConfigNameAttr($query, $value) + { + $query->where('config_name', $value); + } + + /** + * @param Model $query + * @param $value + */ + public function searchTitleAttr($query, $value) + { + if ($value != '') { + $query->whereLIke('id|name|info|config_name', "%$value%"); + } + } + + /** + * 查询分类 + * @param Model $query + * @param $value + */ + public function searchCateIdAttr($query, $value) + { + $query->where('cate_id', $value); + } +} diff --git a/demo/webman/backend/app/model/system/config/SystemGroupData.php b/demo/webman/backend/app/model/system/config/SystemGroupData.php new file mode 100644 index 0000000000000000000000000000000000000000..b83cff124dc14846736f90e0bbb74b21c4fc4657 --- /dev/null +++ b/demo/webman/backend/app/model/system/config/SystemGroupData.php @@ -0,0 +1,65 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\config; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\Model; + +/** + * 组合数据数据列表模型 + * Class SystemGroupData + * @package app\model\system\config + */ +class SystemGroupData extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * @var string + */ + protected $name = 'system_group_data'; + + /** + * 状态搜索器 + * @param $query + * @param $value + */ + public function searchStatusAttr($query, $value) + { + if ($value != '') { + $query->where('status', $value); + } + } + + /** + * Gid搜索器 + * @param Model $query + * @param $value + */ + public function searchGidAttr($query, $value) + { + if (is_array($value)) { + $query->whereIn('gid', $value); + } else { + $query->where('gid', $value); + } + } +} diff --git a/demo/webman/backend/app/model/system/config/SystemStorage.php b/demo/webman/backend/app/model/system/config/SystemStorage.php new file mode 100644 index 0000000000000000000000000000000000000000..5d615c7c760a98de6a646a3bfafdea4a33cb29d0 --- /dev/null +++ b/demo/webman/backend/app/model/system/config/SystemStorage.php @@ -0,0 +1,71 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\config; + + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; + + +/** + * 云存储 + * Class SystemStorage + * @package app\model\system\config + */ +class SystemStorage extends BaseModel +{ + + /** + * @var string + */ + protected $name = 'system_storage'; + + /** + * @var string + */ + protected $pk = 'id'; + + /** + * @var bool + */ + protected $autoWriteTimestamp = false; + + /** + * @param $query + * @param $value + */ + public function searchNameAttr($query, $value) + { + $query->where('name', $value); + } + + /** + * 类型搜索器 + * @param $query + * @param $value + */ + public function searchTypeAttr($query, $value) + { + if ($value) $query->where('type', $value); + } + + /** + * 状态搜索器 + * @param $query + * @param $value + */ + public function searchStatusAttr($query, $value) + { + if ($value !== '') $query->where('status', $value); + } +} diff --git a/demo/webman/backend/app/model/system/crontab/SystemCrontab.php b/demo/webman/backend/app/model/system/crontab/SystemCrontab.php new file mode 100644 index 0000000000000000000000000000000000000000..5c2ddae261cadc64fd847d4ceec6f98678a3b87c --- /dev/null +++ b/demo/webman/backend/app/model/system/crontab/SystemCrontab.php @@ -0,0 +1,51 @@ + 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + 'delete_time' => 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + +} diff --git a/demo/webman/backend/app/model/system/dict/SystemDict.php b/demo/webman/backend/app/model/system/dict/SystemDict.php new file mode 100644 index 0000000000000000000000000000000000000000..5f4b86811bed55a60881877276f8cffa14239039 --- /dev/null +++ b/demo/webman/backend/app/model/system/dict/SystemDict.php @@ -0,0 +1,127 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\dict; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\db\Query; +use think\Model; + +/** + * 字典选项模型 + * Class SystemLog + * + * @package app\model\system\log + */ +class SystemDict extends BaseModel +{ + use ModelTrait; + + protected $connection = 'rbac'; + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_options'; + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + protected array $insert = ['create_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + 'update_time' => 'timestamp:Y-m-d H:i:s', + ]; + + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + protected function setCreateTimeAttr(): int + { + return time(); + } + + /** + * name搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchNameAttr(Query $query, $value) + { + if ($value !== '') { + $query->whereLike('name', $value . '%'); + } + } + + /** + * Id搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchIdAttr(Query $query, $value) + { + if ($value !== '') { + if (in_array($value)) { + $query->whereIn('id', $value); + + } else { + $query->where('id', $value); + } + } + } + + /** + * ip搜索器 + * + * @param Model $query + * @param $value + */ + public function searchIpAttr($query, $value) + { + if ($value !== '') { + $query->where('ip', 'LIKE', "%$value%"); + } + } + + /** + * 管理员id搜索器 + * + * @param Model $query + * @param $value + */ + public function searchAdminIdAttr($query, $value) + { + if (!empty($value)) { + $query->whereIn('admin_id', $value); + } + } +} diff --git a/demo/webman/backend/app/model/system/lang/LangCode.php b/demo/webman/backend/app/model/system/lang/LangCode.php new file mode 100644 index 0000000000000000000000000000000000000000..aef42020121554908747f137655a6f99566ddb3a --- /dev/null +++ b/demo/webman/backend/app/model/system/lang/LangCode.php @@ -0,0 +1,84 @@ +{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * type_id搜索器 + * + * @param $query + * @param $value + */ + public function searchTypeIdAttr($query, $value) + { + if ($value !== '' && $value !== 0) $query->where('type_id', $value); + } + + /** + * code搜索器 + * + * @param $query + * @param $value + */ + public function searchCodeAttr($query, $value) + { + if ($value !== '') $query->where('code', 'like', '%' . $value . '%'); + } + + /** + * remarks搜索器 + * + * @param $query + * @param $value + */ + public function searchRemarksAttr($query, $value) + { + if ($value !== '') $query->where('remarks|code|lang_explain', 'like', '%' . $value . '%'); + } + + /** + * is_admin搜索器 + * + * @param $query + * @param $value + */ + public function searchIsAdminAttr($query, $value) + { + if ($value !== '') $query->where('is_admin', $value); + } +} diff --git a/demo/webman/backend/app/model/system/lang/LangCountry.php b/demo/webman/backend/app/model/system/lang/LangCountry.php new file mode 100644 index 0000000000000000000000000000000000000000..3297e0ac1e84fcaeef1d0a6278067c4b1ca4bdfe --- /dev/null +++ b/demo/webman/backend/app/model/system/lang/LangCountry.php @@ -0,0 +1,62 @@ +{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * type_id搜索器 + * + * @param $query + * @param $value + */ + public function searchTypeIdAttr($query, $value) + { + if ($value !== '') $query->where('type_id', $value); + } + + /** + * code/name搜索器 + * + * @param $query + * @param $value + */ + public function searchKeywordAttr($query, $value) + { + if ($value !== '') $query->where('name|code', 'like', '%' . $value . '%'); + } +} diff --git a/demo/webman/backend/app/model/system/lang/LangType.php b/demo/webman/backend/app/model/system/lang/LangType.php new file mode 100644 index 0000000000000000000000000000000000000000..8407a18cd2e4e17d65ebd5adae0c1ab7f9d5692c --- /dev/null +++ b/demo/webman/backend/app/model/system/lang/LangType.php @@ -0,0 +1,94 @@ + 'timestamp:Y-m-d H:i:s', + ]; + + /** + * 新增自动创建字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Str::uuid(); + $model->{$model->pk} = $uuid; + } + + /** + * is_del搜索器 + * + * @param $query + * @param $value + */ + public function searchIsDelAttr($query, $value) + { + if ($value !== '') $query->where('is_del', $value); + } + + /** + * status搜索器 + * + * @param $query + * @param $value + */ + public function searchStatusAttr($query, $value) + { + if ($value !== '') $query->where('status', $value); + } + + /** + * language-name搜索器 + * + * @param $query + * @param $value + */ + public function searchLanguageNameAttr($query, $value) + { + if ($value !== '') $query->where('language_name', 'like', $value . '%'); + } + + /** + * file_name 搜索器 + * + * @param $query + * @param $value + */ + public function searchFileNameAttr($query, $value) + { + if ($value !== '') $query->where('file_name', $value); + } + +} diff --git a/demo/webman/backend/app/model/system/log/SystemFile.php b/demo/webman/backend/app/model/system/log/SystemFile.php new file mode 100644 index 0000000000000000000000000000000000000000..11168953d11bac1ed46ea464a0f728cad9104b36 --- /dev/null +++ b/demo/webman/backend/app/model/system/log/SystemFile.php @@ -0,0 +1,39 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\log; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; + +/** + * 文件校验模型 + * Class SystemFile + * @package app\model\system\log + */ +class SystemFile extends BaseModel +{ + use ModelTrait; + + /** + * 数据表主键 + * @var string + */ + protected $pk = 'id'; + + /** + * 模型名称 + * @var string + */ + protected $name = 'system_file'; + +} diff --git a/demo/webman/backend/app/model/system/log/SystemFileInfo.php b/demo/webman/backend/app/model/system/log/SystemFileInfo.php new file mode 100644 index 0000000000000000000000000000000000000000..bbf7334ff61af728f3bc9d9e0e8c4a2b6c03bf70 --- /dev/null +++ b/demo/webman/backend/app/model/system/log/SystemFileInfo.php @@ -0,0 +1,29 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\system\log; + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\Model; + +/** + * 日志模型 + * Class SystemLog + * + * @package app\model\system\log + */ +class SystemLog extends BaseModel +{ + use ModelTrait; + + + /** + * 模型名称 + * + * @var string + */ + protected $name = 'system_log'; + /** + * 数据表主键 + * + * @var string + */ + protected $pk = 'id'; + + protected array $insert = ['create_time']; + + protected $type = [ + 'create_time' => 'timestamp:Y-m-d H:i:s', + ]; + + protected function setCreateTimeAttr(): int + { + return time(); + } + + /** + * 访问方式搜索器 + * + * @param Model $query + * @param $value + */ + public function searchPagesAttr($query, $value) + { + if ($value !== '') { + $query->whereLike('page', '%' . $value . '%'); + } + } + + /** + * 访问路径搜索器 + * + * @param Model $query + * @param $value + */ + public function searchPathAttr($query, $value) + { + if ($value !== '') { + $query->whereLike('path', '%' . $value . '%'); + } + } + + /** + * ip搜索器 + * + * @param Model $query + * @param $value + */ + public function searchIpAttr($query, $value) + { + if ($value !== '') { + $query->where('ip', 'LIKE', "%$value%"); + } + } + + /** + * 管理员id搜索器 + * + * @param Model $query + * @param $value + */ + public function searchAdminIdAttr($query, $value) + { + if (!empty($value)) { + $query->whereIn('admin_id', $value); + } + } +} diff --git a/demo/webman/backend/app/model/system/route/SystemRoute.php b/demo/webman/backend/app/model/system/route/SystemRoute.php new file mode 100644 index 0000000000000000000000000000000000000000..3b3900287d74b53b0fe8b3c9cdf1f47db98357b6 --- /dev/null +++ b/demo/webman/backend/app/model/system/route/SystemRoute.php @@ -0,0 +1,91 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\model\system\route; + + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; +use think\model\concern\SoftDelete; + +/** + * Class SystemRoute + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + * @package app\model\system + */ +class SystemRoute extends BaseModel +{ + + use SoftDelete; + + /** + * @var string + */ + protected $name = 'system_route'; + + /** + * @var string + */ + protected $key = 'id'; + + public function searchNameLikeAttr($query, $value) + { + if ('' !== $value) { + $query->where('name|path', 'LIKE', '%' . $value . '%'); + } + } + + public function setRequestAttr($value): bool|string + { + return json_encode($value); + } + + public function getRequestAttr($value) + { + return json_decode($value, true); + } + + public function setResponseAttr($value): bool|string + { + return json_encode($value); + } + + public function getResponseAttr($value) + { + return json_decode($value, true); + } + + public function setRequestExampleAttr($value): bool|string + { + return json_encode($value); + } + + public function getRequestExampleAttr($value) + { + return json_decode($value, true); + } + + + public function setResponseExampleAttr($value): bool|string + { + return json_encode($value); + } + + public function getResponseExampleAttr($value) + { + return json_decode($value, true); + } +} diff --git a/demo/webman/backend/app/model/system/route/SystemRouteCate.php b/demo/webman/backend/app/model/system/route/SystemRouteCate.php new file mode 100644 index 0000000000000000000000000000000000000000..7cc7a6cff6459c5beee572bc1b8c52ab0c98277d --- /dev/null +++ b/demo/webman/backend/app/model/system/route/SystemRouteCate.php @@ -0,0 +1,46 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\model\system\route; + + +use app\common\traits\JwtAuthModelTrait; +use app\common\traits\ModelTrait; +use app\model\BaseModel; + +class SystemRouteCate extends BaseModel +{ + + /** + * @var string + */ + protected $name = 'system_route_cate'; + + /** + * @var string + */ + protected $pk = 'id'; + + protected $autoWriteTimestamp = false; + + /** + * @return \think\model\relation\HasMany + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function children() + { + return $this->hasMany(SystemRoute::class, 'cate_id', 'id')->field(['id', 'type', 'cate_id', 'name', 'name as real_name', 'path', 'method'])->order('create_time desc'); + } +} diff --git a/demo/webman/backend/app/model/system/setting/SystemConfig.php b/demo/webman/backend/app/model/system/setting/SystemConfig.php new file mode 100644 index 0000000000000000000000000000000000000000..f1911bcd6879c66018e76993f5923e8a58495bc6 --- /dev/null +++ b/demo/webman/backend/app/model/system/setting/SystemConfig.php @@ -0,0 +1,49 @@ +whereLike('name', $value . '%'); + + } + } +} diff --git a/demo/webman/backend/app/model/system/setting/SystemOrganization.php b/demo/webman/backend/app/model/system/setting/SystemOrganization.php new file mode 100644 index 0000000000000000000000000000000000000000..0ac9a11d124bc216ff84b1a1c2158cb0bfcde790 --- /dev/null +++ b/demo/webman/backend/app/model/system/setting/SystemOrganization.php @@ -0,0 +1,75 @@ +hasMany(SystemUserPost::class, 'org_id'); + } + + /** + * 新增前添加字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Uuid::uuid4()->toString(); + $model->{$model->pk} = $uuid; + } + + /** + * 部门Aidin搜索器 + * + * @param $query + * @param $value + * @param $data + */ + public function searchOrgIdInAttr($query, $value, $data) + { + if (!empty($value)) { + $query->whereIn('org_id', 'in', $value); + } + } +} diff --git a/demo/webman/backend/app/model/system/setting/SystemPermission.php b/demo/webman/backend/app/model/system/setting/SystemPermission.php new file mode 100644 index 0000000000000000000000000000000000000000..02af838c7005492ae6ab7a051690f236f0d2fb43 --- /dev/null +++ b/demo/webman/backend/app/model/system/setting/SystemPermission.php @@ -0,0 +1,284 @@ +where('parent_id', $menuId)->select(); + foreach ($subMenus as $subMenu) { + $this->deleteSubMenu($subMenu['id']); + $subMenu->delete(); + } + } + + /** + * 参数修改器 + * + * @param $value + * + * @return false|string + */ + public function setParamsAttr($value) + { + $value = $value ? explode('/', $value) : []; + $params = array_chunk($value, 2); + $data = []; + foreach ($params as $param) { + if (isset($param[0]) && isset($param[1])) $data[$param[0]] = $param[1]; + } + return json_encode($data); + } + + /** + * 参数获取器 + * + * @param $_value + * + * @return mixed + */ + public function getParamsAttr($_value) + { + return json_decode($_value, true); + } + + /** + * pid获取器 + * + * @param $value + * + * @return mixed|string + */ + public function getPidStrAttr($value) + { + return !$value ? '顶级' : $this->where('parent_id', $value)->value('menu_name'); + } + + /** + * 默认条件查询器 + * + * @param Model $query + * @param $value + */ + public function searchDefaultAttr($query) + { + $query->where(['is_show' => 1, 'status' => 1]); + } + + /** + * 是否显示搜索器 + * + * @param Model $query + * @param $value + */ + public function searchIsShowAttr($query, $value) + { + if ($value != '') { + $query->where('is_show', $value); + } + } + + /** + * 是否删除搜索器 + * + * @param Model $query + * @param $value + */ + public function searchIsDelAttr($query, $value) + { + $query->where('delete_time', $value); + } + + /** + * Pid搜索器 + * + * @param Model $query + * @param $value + */ + public function searchPidAttr($query, $value) + { + $query->where('parent_id', $value ?? '-1'); + } + + /** + * 规格搜索器 + * + * @param Model $query + * @param $value + */ + public function searchRuleAttr($query, $value) + { + $query->whereIn('permission_id', $value)->where('delete_time', null)->whereOr('parent_id', '-1'); + } + + /** + * 搜索菜单 + * + * @param Model $query + * @param $value + */ + public function searchKeywordAttr($query, $value) + { + if ($value != '') { + $query->whereLike('menu_name|permission_id|parent_id', "%$value%"); + } + } + + /** + * 方法搜索器 + * + * @param Model $query + * @param $value + */ + public function searchActionAttr($query, $value) + { + $query->where('action', $value); + } + + /** + * 控制器搜索器 + * + * @param Model $query + * @param $value + */ + public function searchControllerAttr($query, $value) + { + $query->where('controller', lcfirst($value)); + } + + /** + * 访问地址搜索器 + * + * @param Model $query + * @param $value + */ + public function searchUrlAttr($query, $value) + { + $query->where('api_path', $value); + } + + /** + * 参数搜索器 + * + * @param Model $query + * @param $value + */ + public function searchParamsAttr($query, $value) + { + $query->where(function ($query) use ($value) { + $query->where('params', $value)->whereOr('params', "'[]'"); + }); + } + + /** + * 权限标识搜索器 + * + * @param Model $query + * @param $value + */ + public function searchUniqueAttr($query, $value) + { + $query->where('delete_time', null); + if ($value) { + $query->whereIn('permission_id', $value); + } + } + + /** + * 菜单规格搜索 + * + * @param Model $query + * @param $value + */ + public function searchRouteAttr($query, $value) + { + $query->where('auth_type', 1);//菜单 + if ($value) { + $query->whereIn('permission_id', $value); + } + } + + /** + * Id搜索器 + * + * @param Model $query + * @param $value + */ + public function searchIdAttr($query, $value) + { + $query->whereIn('permission_id', $value); + } + + /** + * is_show_path + * + * @param Model $query + * @param $value + */ + public function searchIsShowPathAttr($query, $value) + { + $query->where('is_show_path', $value); + } + + /** + * auth_type + * + * @param Model $query + * @param $value + */ + public function searchAuthTypeAttr($query, $value) + { + if ($value !== '') { + if ($value == 3) { + $query->whereIn('auth_type', [1, 3]); + } else { + $query->where('auth_type', $value); + } + } + } + +} diff --git a/demo/webman/backend/app/model/system/setting/SystemPost.php b/demo/webman/backend/app/model/system/setting/SystemPost.php new file mode 100644 index 0000000000000000000000000000000000000000..18d15d5402dad4a75d27495b05ddcf0742df74fa --- /dev/null +++ b/demo/webman/backend/app/model/system/setting/SystemPost.php @@ -0,0 +1,54 @@ +{$model->pk}) ? $model->{$model->pk} : Uuid::uuid4()->toString(); + $model->{$model->pk} = $uuid; + } + + /** + * 定义与UserPost模型的一对多关联关系0808 + * + * @return \think\model\relation\HasMany + */ + public function userPosts(): HasMany + { + return $this->hasMany(SystemUserPost::class, 'post_id'); + } + +} diff --git a/demo/webman/backend/app/model/system/setting/SystemRoleOrganization.php b/demo/webman/backend/app/model/system/setting/SystemRoleOrganization.php new file mode 100644 index 0000000000000000000000000000000000000000..d3ad5ad3f8c8c1b8bcfb1b7d9acd4d0cc3c604e2 --- /dev/null +++ b/demo/webman/backend/app/model/system/setting/SystemRoleOrganization.php @@ -0,0 +1,29 @@ +whereIn('role_id', $value); + } + } + +} diff --git a/demo/webman/backend/app/model/system/setting/SystemRolePost.php b/demo/webman/backend/app/model/system/setting/SystemRolePost.php new file mode 100644 index 0000000000000000000000000000000000000000..61d8ee6a000b570d3be1069a7bb7842ebe113d7f --- /dev/null +++ b/demo/webman/backend/app/model/system/setting/SystemRolePost.php @@ -0,0 +1,30 @@ +whereIn('post_id',$value); + } + } + +} diff --git a/demo/webman/backend/app/model/system/setting/SystemRoles.php b/demo/webman/backend/app/model/system/setting/SystemRoles.php new file mode 100644 index 0000000000000000000000000000000000000000..38f00d3bd445c4e86bd363d039e60ac266bdedf3 --- /dev/null +++ b/demo/webman/backend/app/model/system/setting/SystemRoles.php @@ -0,0 +1,79 @@ + 'string', + 'role_name' => 'string', + 'role_code' => 'int', + 'parent_id' => 'string', + 'status' => 'int', + 'weight' => 'int', + 'icon' => 'string', + 'is_super' => 'int', + 'create_time' => 'datetime', + 'update_time' => 'datetime', + 'remarks' => 'string', + ]; + + // 设置字段自动转换类型 + protected $type = []; + + // 设置废弃字段 + protected $disuse = []; + + /** + * 新增前添加字符串id + * + * @param $model + * + * @return void + */ + protected static function onBeforeInsert($model): void + { + $uuid = !empty($model->{$model->pk}) ? $model->{$model->pk} : Uuid::uuid4()->toString(); + $model->{$model->pk} = $uuid; + } + +} diff --git a/demo/webman/backend/app/model/system/setting/SystemUser.php b/demo/webman/backend/app/model/system/setting/SystemUser.php new file mode 100644 index 0000000000000000000000000000000000000000..4dbe1cd65a3a7af83a5f146067eb57da8638a921 --- /dev/null +++ b/demo/webman/backend/app/model/system/setting/SystemUser.php @@ -0,0 +1,178 @@ +{$model->pk}) ? $model->{$model->pk} : Uuid::uuid4()->toString(); + $model->{$model->pk} = $uuid; + } + + /** + * UserPost模型的一对多关联关系 + * + * @return \think\model\relation\HasMany + */ + public function userPosts(): HasMany + { + return $this->hasMany(SystemUserPost::class, 'user_id'); + } + + /** + * UserOrganization 模型的一对多关联关系 + * + * @return \think\model\relation\HasMany + */ + public function userOrgz(): HasMany + { + return $this->hasMany(SystemUserOrganization::class, 'user_id'); + } + + /** + * 用户账号搜索器 + * + * @param \think\db\Query $query + * @param $value + * @param $data + */ + public function searchAccountAttr(Query $query, $value, $data) + { + if (!empty($value)) { + $query->where('account', 'like', $value . '%'); + } + } + + /** + * 用户名搜索器 + * + * @param \think\db\Query $query + * @param $value + * @param $data + */ + public function searchNameAttr(Query $query, $value, $data) + { + if (!empty($value)) { + $query->where('user_name', 'like', $value . '%'); + } + } + + /** + * 权限数据 + * + * @param $value + * + * @return false|string[] + */ + public static function getRolesAttr($value): array|bool + { + return explode(',', $value); + } + + /** + * 管理员级别搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchLevelAttr(Query $query, $value) + { + if (is_array($value)) { + $query->where('level', $value[0], $value[1]); + } else { + $query->where('level', $value); + } + } + + /** + * 管理员账号和姓名搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchAccountLikeAttr(Query $query, $value) + { + if ($value) { + $query->whereLike('account|user_name', '%' . $value . '%'); + } + } + + /** + * 管理员权限搜索器 + * + * @param \think\db\Query $query + * @param $roles + */ + public function searchRolesAttr(Query $query, $roles) + { + if ($roles) { + $query->where("CONCAT(',',roles,',') LIKE '%,$roles,%'"); + } + } + + /** + * 是否删除搜索器 + * + * @param \think\db\Query $query + */ + public function searchIsDelAttr(Query $query) + { + $query->where('delete_time', null); + } + + /** + * 状态搜索器 + * + * @param \think\db\Query $query + * @param $value + */ + public function searchStatusAttr(Query $query, $value) + { + if ($value != '' && $value != null) { + $query->where('is_enable', $value); + } + } + + /** + * 手机号搜索器 + * @param $query + * @param $value + * @param $data + */ + public function searchPhoneAttr($query, $value, $data) + { + if ($value != '' && $value != null) { + $query->where('cell_phone_number', $value); + } + } +} diff --git a/demo/webman/backend/app/model/system/setting/SystemUserOrganization.php b/demo/webman/backend/app/model/system/setting/SystemUserOrganization.php new file mode 100644 index 0000000000000000000000000000000000000000..d285a3c6c14bc87d78a464bead3df6ed8f3add78 --- /dev/null +++ b/demo/webman/backend/app/model/system/setting/SystemUserOrganization.php @@ -0,0 +1,29 @@ +belongsTo(SystemOrganization::class, 'org_id'); + } + +} diff --git a/demo/webman/backend/app/model/system/setting/SystemUserPost.php b/demo/webman/backend/app/model/system/setting/SystemUserPost.php new file mode 100644 index 0000000000000000000000000000000000000000..38149b48a84d45744e407ddd1e681da2ca25e884 --- /dev/null +++ b/demo/webman/backend/app/model/system/setting/SystemUserPost.php @@ -0,0 +1,28 @@ +belongsTo(SystemPost::class, 'post_id'); + } +} diff --git a/demo/webman/backend/app/services/BaseServices.php b/demo/webman/backend/app/services/BaseServices.php new file mode 100644 index 0000000000000000000000000000000000000000..be4e368283f2d7a32923d10ff28114e23a033c10 --- /dev/null +++ b/demo/webman/backend/app/services/BaseServices.php @@ -0,0 +1,122 @@ +dao->getTableName()); + } + + /** + * 获取分页配置 + * + * @param bool $isPage + * @param bool $isRelieve + * + * @return int[] + */ + public function getPageValue(bool $isPage = true, bool $isRelieve = true): array + { + // 获取请求实例 + $request = request(); + $page = $limit = 0; + if ($isPage) { + $page = $request->input(Config('thinkorm.page.pageKey', 'page') . '/d', 0); + $limit = $request->input(Config('thinkorm.page.limitKey', 'limit') . '/d', 0); + } + $limitMax = Config('thinkorm.page.limitMax'); + $defaultLimit = Config('thinkorm.page.defaultLimit', 10); + if ($limit > $limitMax && $isRelieve) { + $limit = $limitMax; + } + return [(int)$page, (int)$limit, (int)$defaultLimit, (int)$limitMax]; + } + + /** + * 数据库事务操作 + * + * @param callable $closure + * @param bool $isTran + * + * @return mixed + */ + public function transaction(callable $closure, bool $isTran = true): mixed + { + return $isTran ? DB::transaction($closure) : $closure(); + } + + /** + * 创建token + * + * @param int|string $id + * @param string $type + * @param string $pwd + * + * @return array + * @throws \app\exception\AdminException + */ + public function createToken(int|string $id, string $type, string $pwd = ''): array + { + /** @var JwtAuth $jwtAuth */ + $jwtAuth = Container::make(JwtAuth::class); + return $jwtAuth->createToken($id, $type, ['pwd' => md5($pwd)]); + } + + /** + * 获取路由地址 + * + * @param string $path + * @param array $params + * @param bool $suffix + * @param bool $isDomain + * + * @return \think\route\Url + */ +// public function url(string $path, array $params = [], bool $suffix = false, bool $isDomain = false) +// { +// return Url::buildUrl($path, $params)->suffix($suffix)->domain($isDomain)->build(); +// } + + /** + * 密码hash加密 + * + * @param string $password + * + * @return false|string|null + */ + public function passwordHash(string $password) + { + return password_hash($password, PASSWORD_BCRYPT); + } + + /** + * @param $name + * @param $arguments + * + * @return mixed + */ + public function __call($name, $arguments) + { + return call_user_func_array([$this->dao, $name], $arguments); + } +} \ No newline at end of file diff --git a/demo/webman/backend/app/services/system/admin/SystemAdminDeptServices.php b/demo/webman/backend/app/services/system/admin/SystemAdminDeptServices.php new file mode 100644 index 0000000000000000000000000000000000000000..850aaf6ec1fadcd8b8fbf8c529b8cf5179ceb3a6 --- /dev/null +++ b/demo/webman/backend/app/services/system/admin/SystemAdminDeptServices.php @@ -0,0 +1,41 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\SystemAdminDeptDao; +use app\services\BaseServices; +use support\Container; + +/** + * Class SystemRoleServices + * + * @package app\services\system\admin + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取数据 + */ +class SystemAdminDeptServices extends BaseServices +{ + + /** + * 当前管理员权限缓存前缀 + */ + const ADMIN_RULES_LEVEL = 'Admin_admin_dept_level_'; + + /** + * SystemRoleServices constructor. + */ + public function __construct() + { + $this->dao = Container::make(SystemAdminDeptDao::class); + } +} diff --git a/demo/webman/backend/app/services/system/admin/SystemAdminPostServices.php b/demo/webman/backend/app/services/system/admin/SystemAdminPostServices.php new file mode 100644 index 0000000000000000000000000000000000000000..7526820145124b391ecb07ecb2b6f7bd8a8af155 --- /dev/null +++ b/demo/webman/backend/app/services/system/admin/SystemAdminPostServices.php @@ -0,0 +1,42 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\SystemAdminPostDao; +use app\services\BaseServices; +use support\Container; + +/** + * Class SystemRoleServices + * + * @package app\services\system\admin + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取数据 + */ +class SystemAdminPostServices extends BaseServices +{ + + /** + * 当前管理员权限缓存前缀 + */ + const ADMIN_RULES_LEVEL = 'Admin_admin_post_level_'; + + /** + * SystemRoleServices constructor. + */ + public function __construct() + { + $this->dao = Container::make(SystemAdminPostDao::class); + } + +} diff --git a/demo/webman/backend/app/services/system/admin/SystemAdminServices.php b/demo/webman/backend/app/services/system/admin/SystemAdminServices.php new file mode 100644 index 0000000000000000000000000000000000000000..c14d00ed9c1e64ab4f21f7324e15f315e44912a6 --- /dev/null +++ b/demo/webman/backend/app/services/system/admin/SystemAdminServices.php @@ -0,0 +1,596 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\SystemAdminDao; +use app\exception\AdminException; +use app\services\BaseServices; +use support\Container; +use think\Model; + +/** + * 管理员service + * Class SystemAdminServices + * + * @package app\services\system\admin + * @method getAdminIds(int $level) 根据管理员等级获取管理员id + * @method getOrdAdmin(string $field, int $level) 获取低于等级的管理员名称和id + */ +class SystemAdminServices extends BaseServices +{ + + public function __construct() + { + $this->dao = Container::make(SystemAdminDao::class); + } + + /** + * 获取管理员详情 + * + * @param string $id + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\app\exception\AdminException + */ + public function find(string $id): array + { + $adminInfo = $this->dao->get($id); + if (!$adminInfo) { + throw new AdminException('数据不存在'); + } + + /** @var SystemAdminDeptServices $systemAdminDeptServices */ + // 解析 SystemAdminDeptServices 类的实例 + $systemAdminDeptServices = Container::make(SystemAdminDeptServices::class); + $adminInfo->dept_id = $systemAdminDeptServices->column(['admin_id' => $id], 'dept_id')[0] ?? ''; + + /** @var SystemAdminPostServices $systemAdminPostServices */ + $systemAdminPostServices = Container::make(SystemAdminPostServices::class); + $adminInfo->post_id = $systemAdminPostServices->column(['admin_id' => $id], 'post_id')[0] ?? ''; + + return $adminInfo->getData(); + } + + /** + * 管理员登陆 + * + * @param string $account + * @param string $password + * @param bool $isPwd + * + * @return array|bool|Model + * @throws \app\exception\AdminException + */ + public function verifyLogin(string $account, string $password, $isPwd = true): bool|array|Model + { + $adminInfo = $this->dao->accountByAdmin($account); + if (!$adminInfo) return false; + if ($isPwd) { + if (!password_verify($password, $adminInfo->pwd)) return false; + } + if (!$adminInfo->status) { + throw new AdminException(400595); + } + /** @var SystemAdminDeptServices $systemAdminDeptServices */ + $systemAdminDeptServices = Container::make(SystemAdminDeptServices::class); + $adminInfo->dept_id = $systemAdminDeptServices->column(['admin_id' => $adminInfo->id], 'dept_id')[0] ?? ''; + + /** @var SystemAdminPostServices $systemAdminPostServices */ + $systemAdminPostServices = Container::make(SystemAdminPostServices::class); + $adminInfo->post_id = $systemAdminPostServices->column(['admin_id' => $adminInfo->id], 'post_id')[0] ?? ''; + + if (!empty($adminInfo->dept_id)) { + /** @var SystemRoleDeptServices $systemRoleDeptServices */ + $systemRoleDeptServices = Container::make(SystemRoleDeptServices::class); + $deptRoleId = $systemRoleDeptServices->column(['dept_id' => $adminInfo->dept_id], 'role_id'); + } + + if (!empty($adminInfo->post_id)) { + /** @var SystemRolePostServices $systemRolePostServices */ + $systemRolePostServices = Container::make(SystemRolePostServices::class); + $postRoleId = $systemRolePostServices->column(['post_id' => $adminInfo->post_id], 'role_id'); + } + + $adminInfo->role_id = array_merge_recursive($deptRoleId ?? [], $postRoleId ?? []); + + /** @var SystemRoleMenuServices $systemRoleMenuServices */ + $systemRoleMenuServices = Container::make(SystemRoleMenuServices::class); + $adminInfo->roles = $systemRoleMenuServices->column(['role_id' => $adminInfo->role_id], 'menu_id'); + // 获取客户端 IP 地址 + $clientIp = request()->header('x-real-ip') ?? request()->header('x-forwarded-for') ?? $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'; + + $adminInfo->last_time = time(); + $adminInfo->last_ip = $clientIp; + $adminInfo->login_count++; + $adminInfo->save(); + return $adminInfo; + } + + /** + * 文件管理员登陆 + * + * @param string $account + * @param string $password + * + * @return array|Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function verifyFileLogin(string $account, string $password) + { + $adminInfo = $this->dao->accountByAdmin($account); + if (!$adminInfo) { + throw new AdminException(400594); + } + if (!$adminInfo->status) { + throw new AdminException(400595); + } + if (!password_verify($password, $adminInfo->file_pwd)) { + throw new AdminException(400140); + } + $adminInfo->last_time = time(); + $adminInfo->last_ip = app('request')->ip(); + $adminInfo->login_count++; + $adminInfo->save(); + return $adminInfo; + } + + /** + * 后台登陆获取菜单获取token + * + * @param string $account + * @param string $password + * @param string $type + * @param string $key + * + * @return array|bool + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\app\exception\AdminException + */ + public function login(string $account, string $password, string $type, string $key = '', $isPwd = true) + { + $adminInfo = $this->verifyLogin($account, $password, $isPwd); + if (!$adminInfo) return false; + $tokenInfo = $this->createToken($adminInfo->id, $type, $adminInfo->pwd); + /** @var SystemMenusServices $services */ + $services = Container::make(SystemMenusServices::class); + [$menus, $uniqueAuth] = $services->getMenusList($adminInfo->roles, (int)$adminInfo->level); + //获取队列状态 + $remind = Config('app.console_remind', false); + + return [ + 'token' => $tokenInfo['token'], + 'expires_time' => $tokenInfo['params']['exp'], + 'menus' => $menus, + 'unique_auth' => $uniqueAuth, + 'user_info' => [ + 'id' => $adminInfo->getData('id'), + 'account' => $adminInfo->getData('account'), + 'head_pic' => '', + 'level' => $adminInfo->getData('level'), + 'real_name' => $adminInfo->getData('real_name'), + ], + 'logo' => '', + 'logo_square' => '', + 'version' => 8.0, +// 'newOrderAudioLink' => get_file_link(sys_config('new_order_audio_link', '')), + 'queue' => $queue ?? true, + 'timer' => $timer ?? true, + 'site_name' => '', + ]; + } + + /** + * 获取登陆前的login等信息 + * + * @return array + */ + public function getLoginInfo() + { + $key = uniqid(); + CheckQueueJob::dispatch([$key]); + $data = [ + 'slide' => sys_data('admin_login_slide') ?? [], + 'logo_square' => sys_config('site_logo_square'),//透明 + 'logo_rectangle' => sys_config('site_logo'),//方形 + 'login_logo' => sys_config('login_logo'),//登陆 + 'site_name' => sys_config('site_name'), + 'copyright' => sys_config('nncnL_crmeb_copyright', ''), + 'version' => get_crmeb_version(), + 'key' => $key, + 'login_captcha' => 0, + ]; + if (CacheService::get('login_captcha', 1) > 1) { + $data['login_captcha'] = 1; + } + return $data; + } + + /** + * 管理员列表 + * + * @param array $where + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAdminList(array $where) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getList($where, $page, $limit); + $count = $this->dao->count($where); +// /** @var SystemRoleServices $service */ +// $service = Container::make(SystemRoleServices::class); +// $allRole = $service->getRoleArray(); +// foreach ($list as &$item) { +// if ($item['roles']) { +// $roles = []; +// foreach ($item['roles'] as $id) { +// if (isset($allRole[$id])) $roles[] = $allRole[$id]; +// } +// if ($roles) { +// $item['roles'] = implode(',', $roles); +// } else { +// $item['roles'] = ''; +// } +// } +// $item['_add_time'] = date('Y-m-d H:i:s', $item['add_time']); +// $item['_last_time'] = $item['last_time'] ? date('Y-m-d H:i:s', $item['last_time']) : ''; +// } + return compact('list', 'count'); + } + + /** + * 创建管理员表单 + * + * @param int $level + * @param array $formData + * + * @return mixed + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createAdminForm(int $level, array $formData = []) + { + $f[] = $this->builder->input('account', '管理员账号', $formData['account'] ?? '')->required('请填写管理员账号'); + $f[] = $this->builder->input('pwd', '管理员密码')->type('password')->required('请填写管理员密码'); + $f[] = $this->builder->input('conf_pwd', '确认密码')->type('password')->required('请输入确认密码'); + $f[] = $this->builder->input('real_name', '管理员姓名', $formData['real_name'] ?? '')->required('请输入管理员姓名'); + + /** @var SystemRoleServices $service */ + $service = Container::make(SystemRoleServices::class); + $options = $service->getRoleFormSelect($level); + if (isset($formData['roles'])) { + foreach ($formData['roles'] as &$item) { + $item = intval($item); + } + } + $f[] = $this->builder->select('roles', '管理员身份', $formData['roles'] ?? [])->setOptions(FormBuilder::setOptions($options))->multiple(true)->required('请选择管理员身份'); + $f[] = $this->builder->radio('status', '状态', $formData['status'] ?? 1)->options([['label' => '开启', 'value' => 1], ['label' => '关闭', 'value' => 0]]); + return $f; + } + + /** + * 添加管理员form表单获取 + * + * @param int $level + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createForm(int $level) + { + return create_form('管理员添加', $this->createAdminForm($level), $this->url('/setting/admin')); + } + + /** + * 创建管理员 + * + * @param array $data + * + * @return bool + * @throws \ReflectionException + */ + public function create(array $data): bool + { + if ($data['conf_pwd'] != $data['pwd']) { + throw new AdminException(400264); + } + unset($data['conf_pwd']); + + if (strlen(trim($data['pwd'])) < 6 || strlen(trim($data['pwd'])) > 32) { + throw new AdminException(400762); + } + + if ($this->dao->count(['account' => $data['account'], 'is_del' => 0])) { + throw new AdminException(400596); + } + + $data['pwd'] = $this->passwordHash($data['pwd']); + $data['create_time'] = time(); + $data['head_pic'] = '/statics/system_images/admin_head_pic.png'; + + return $this->transaction(function () use ($data) { + if ($this->dao->save($data)) { + CacheService::clear(); + return true; + } else { + throw new AdminException(100022); + } + }); + } + + /** + * 修改管理员表单 + * + * @param int $level + * @param int $id + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function updateForm(int $level, int $id) + { + $adminInfo = $this->dao->get($id); + if (!$adminInfo) { + throw new AdminException(400594); + } + if ($adminInfo->is_del) { + throw new AdminException(400452); + } + return create_form('管理员修改', $this->createAdminForm($level, $adminInfo->toArray()), $this->url('/setting/admin/' . $id), 'PUT'); + } + + /** + * 修改管理员 + * + * @param string $id + * @param array $data + * + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function save(string $id, array $data): bool + { + if (!$adminInfo = $this->dao->get($id)) { + throw new AdminException(400594); + } + if ($adminInfo->delete_time) { + throw new AdminException(400452); + } + //修改密码 + if ($data['pwd']) { + + if (!$data['conf_pwd']) { + throw new AdminException(400263); + } + + if ($data['conf_pwd'] != $data['pwd']) { + throw new AdminException(400264); + } + + if (strlen(trim($data['pwd'])) < 6 || strlen(trim($data['pwd'])) > 32) { + throw new AdminException(400762); + } + + $adminInfo->pwd = $this->passwordHash($data['pwd']); + } + //修改账号 + if (isset($data['account']) && $data['account'] != $adminInfo->account && $this->dao->isAccountUsable($data['account'], $id)) { + throw new AdminException(400596); + } + $adminInfo->real_name = $data['real_name'] ?? $adminInfo->real_name; + $adminInfo->account = $data['account'] ?? $adminInfo->account; + $adminInfo->status = $data['status']; + $adminInfo->remark = $data['remark']; + $adminInfo->cell_phone_number = $data['cell_phone_number']; + $adminInfo->email = $data['email']; + $adminInfo->sex = $data['sex']; + $adminInfo->address = $data['address']; + if ($adminInfo->save()) { + return true; + } else { + return false; + } + } + + /** + * 设置管理员-部门/职位 + * + * @param string $id + * @param array $data + * + * @return true + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function setPosition(string $id, array $data = []): bool + { + $adminInfo = $this->dao->get($id); + if (!$adminInfo) { + throw new AdminException(400451); + } + if ($adminInfo->delete_time) { + throw new AdminException(400452); + } + $adminInfo->dept_id = $data['dept_id'] ?? ''; + $adminInfo->post_id = $data['post_id'] ?? ''; + + /** @var SystemAdminDeptServices $systemAdminDeptServices */ + $systemAdminDeptServices = Container::make(SystemAdminDeptServices::class); + $systemAdminDeptServices->delete($adminInfo->id, 'admin_id'); + if ($adminInfo->dept_id) { + $systemAdminDeptServices->save(['dept_id' => $adminInfo->dept_id, 'admin_id' => $adminInfo->id]); + } + /** @var SystemAdminPostServices $systemAdminPostServices */ + $systemAdminPostServices = Container::make(SystemAdminPostServices::class); + $systemAdminPostServices->delete($adminInfo->id, 'admin_id'); + if ($adminInfo->post_id) { + $systemAdminPostServices->save(['post_id' => $adminInfo->post_id, 'admin_id' => $adminInfo->id]); + } + return true; + } + + /** + * 修改当前管理员信息 + * + * @param int $id + * @param array $data + * + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function updateAdmin(string $id, array $data): bool + { + $adminInfo = $this->dao->get($id); + if (!$adminInfo) + throw new AdminException(400451); + if ($adminInfo->delete_time) { + throw new AdminException(400452); + } + if (!empty($data['real_name'])) { + $adminInfo->real_name = $data['real_name']; + } + if ($data['pwd']) { + if (!password_verify($data['pwd'], $adminInfo['pwd'])) + throw new AdminException(400597); + if (!$data['new_pwd']) + throw new AdminException(400598); + if (!$data['conf_pwd']) + throw new AdminException(400263); + if ($data['new_pwd'] != $data['conf_pwd']) + throw new AdminException(400264); + $adminInfo->pwd = $this->passwordHash($data['new_pwd']); + } + if (!empty($data['head_pic'])) { + $adminInfo->head_pic = $data['head_pic']; + } + $adminInfo->remarks = $data['remarks']; + $adminInfo->cell_phone_number = $data['cell_phone_number']; + $adminInfo->email = $data['email']; + $adminInfo->sex = $data['sex']; + $adminInfo->address = $data['address']; + + if ($adminInfo->save()) { + CacheService::clear(); + return true; + } else { + return false; + } + } + + /** + * 设置当前管理员文件管理密码 + * + * @param int $id + * @param array $data + * + * @return bool + */ + public function setFilePassword(int $id, array $data) + { + $adminInfo = $this->dao->get($id); + if (!$adminInfo) + throw new AdminException(400451); + if ($adminInfo->is_del) { + throw new AdminException(400452); + } + if ($data['file_pwd']) { + if ($adminInfo->level != 0) throw new AdminException(400611); + if (!$data['conf_file_pwd']) + throw new AdminException(400263); + if ($data['file_pwd'] != $data['conf_file_pwd']) + throw new AdminException(400264); + $adminInfo->file_pwd = $this->passwordHash($data['file_pwd']); + } + if ($adminInfo->save()) + return true; + else + return false; + } + + /** 后台订单下单,评论,支付成功,后台消息提醒 + * + * @param $event + */ + public function adminNewPush() + { + try { + /** @var StoreOrderServices $orderServices */ + $orderServices = Container::make(StoreOrderServices::class); + $data['ordernum'] = $orderServices->count(['is_del' => 0, 'status' => 1, 'shipping_type' => 1]); + /** @var StoreProductServices $productServices */ + $productServices = Container::make(StoreProductServices::class); + $data['inventory'] = $productServices->count(['type' => 5]); + /** @var StoreProductReplyServices $replyServices */ + $replyServices = Container::make(StoreProductReplyServices::class); + $data['commentnum'] = $replyServices->count(['is_reply' => 0]); + /** @var UserExtractServices $extractServices */ + $extractServices = Container::make(UserExtractServices::class); + $data['reflectnum'] = $extractServices->getCount(['status' => 0]);//提现 + $data['msgcount'] = intval($data['ordernum']) + intval($data['inventory']) + intval($data['commentnum']) + intval($data['reflectnum']); + ChannelService::instance()->send('ADMIN_NEW_PUSH', $data); + } catch (\Exception $e) { + } + } + + public function getAdministratorsList(array $where): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->selectList($where, '*', $page, $limit, '', ['departments', 'positions'], true); + foreach ($list as $value) { + $deptList = $value->getData('departments'); + $postList = $value->getData('positions'); + $dept_id = []; + $dept_name = []; + $post_id = []; + $post_name = []; + if (!empty($deptList)) { + foreach ($deptList as $dept) { + $dept_name[] = $dept->getData('dept_name'); + $dept_id[] = $dept->getData('dept_id'); + } + } + if (!empty($postList)) { + foreach ($postList as $post) { + $post_name[] = $post->getData('post_name'); + $post_id[] = $post->getData('post_id'); + } + } + $value->set('dept_name', implode(',', $dept_name)); + $value->set('post_name', implode(',', $post_name)); + $value->set('dept_id', implode(',', $dept_id)); + $value->set('post_id', implode(',', $post_id)); + } + if ($list != null) { + $list->hidden(['pwd']); + $list = $list->toArray(); + } else { + $list = []; + } + $count = $this->dao->count($where); + return compact('list', 'count'); + + } +} diff --git a/demo/webman/backend/app/services/system/admin/SystemAuthServices.php b/demo/webman/backend/app/services/system/admin/SystemAuthServices.php new file mode 100644 index 0000000000000000000000000000000000000000..091172df0316ce96b8ee2bff71dd65189c2ba68b --- /dev/null +++ b/demo/webman/backend/app/services/system/admin/SystemAuthServices.php @@ -0,0 +1,174 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\common\CacheService; +use app\common\JwtAuth; +use app\dao\system\admin\AdminAuthDao; +use app\exception\AuthException; +use app\services\BaseServices; +use support\Container; + +/** + * admin授权service + * Class AdminAuthServices + * + * @package app\services\system\admin + */ +class SystemAuthServices extends BaseServices +{ + + public function __construct() + { + $this->dao = Container::make(AdminAuthDao::class); + } + + /** + * 获取Admin授权信息 + * + * @param string $token + * @param int $code + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @throws \app\exception\AuthException + */ + public function parseToken(string $token, int $code = 110003): array + { + /** @var CacheService $cacheService */ + $cacheService = Container::make(CacheService::class); + if (!$token || $token === 'undefined') { + throw new AuthException($code); + } + /** @var JwtAuth $jwtAuth */ + $jwtAuth = Container::make(JwtAuth::class); + //设置解析token + [$id, $type, $pwd, $exp] = $jwtAuth->parseToken($token); + + //检测token是否过期 + $md5Token = md5($token); + if (!$cacheService->has($md5Token) || !$cacheService->get($md5Token, '', '', $type)) { + $this->authFailAfter($id, $type); + throw new AuthException($code); + } + //验证token + try { + $jwtAuth->verifyToken(); + } catch (\Throwable $e) { + if (!request()->isCli()) { + $cacheService->delete($md5Token); + } + $this->authFailAfter($id, $type); + throw new AuthException($code); + } + + //获取管理员信息 + $validTime = $this->timestamp_diff(time(), $exp); +// $adminInfo = $this->cacheDriver()->remember($md5Token, $this->infoAdmin($id), $validTime + 60); + $adminInfo = $this->infoAdmin($id); + if (!$adminInfo || !$adminInfo->id) { + if (!request()->isCli()) { + $cacheService->delete($md5Token); + } + $this->authFailAfter($id, $type); + throw new AuthException($code); + } + $adminInfo->type = $type; + return $adminInfo->hidden(['pwd', 'delete_time', 'status'])->toArray(); + } + + /** + * token验证失败后事件 + */ + protected function authFailAfter($id, $type) + { + try { + //token 验证失败后处理事件 + } catch (\Throwable $e) { + } + } + + /** + * 保存提交数据 + * + * @param $adminId + * @param $postData + */ + protected function saveProduct($adminId, $postData) + { + /** @var CacheServices $cacheService */ + $cacheService = Container::make(CacheServices::class); + $cacheService->setDbCache($adminId . '_product_data', $postData, 68400); + } + + /** + * 获取管理员信息 + * + * @param string|int $id + * + * @return array|\think\Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function infoAdmin(string|int $id): array|\think\Model + { + $adminInfo = $this->get($id); + if (!$adminInfo) { + throw new AuthException(400595); + } + if (!$adminInfo->status) { + throw new AuthException(400595); + } + /** @var SystemAdminDeptServices $systemAdminDeptServices */ + $systemAdminDeptServices = Container::make(SystemAdminDeptServices::class); + $adminInfo->dept_id = $systemAdminDeptServices->column(['admin_id' => $adminInfo->id], 'dept_id')[0] ?? ''; + + /** @var SystemAdminPostServices $systemAdminPostServices */ + $systemAdminPostServices = Container::make(SystemAdminPostServices::class); + $adminInfo->post_id = $systemAdminPostServices->column(['admin_id' => $adminInfo->id], 'post_id')[0] ?? ''; + + if (!empty($adminInfo->dept_id)) { + /** @var SystemRoleDeptServices $systemRoleDeptServices */ + $systemRoleDeptServices = Container::make(SystemRoleDeptServices::class); + $deptRoleId = $systemRoleDeptServices->column(['dept_id' => $adminInfo->dept_id], 'role_id'); + } + + if (!empty($adminInfo->post_id)) { + /** @var SystemRolePostServices $systemRolePostServices */ + $systemRolePostServices = Container::make(SystemRolePostServices::class); + $postRoleId = $systemRolePostServices->column(['post_id' => $adminInfo->post_id], 'role_id'); + } + $adminInfo->role_id = array_merge_recursive($deptRoleId ?? [], $postRoleId ?? []); + + /** @var SystemRoleMenuServices $systemRoleMenuServices */ + $systemRoleMenuServices = Container::make(SystemRoleMenuServices::class); + $adminInfo->roles = $systemRoleMenuServices->column(['role_id' => $adminInfo->role_id], 'menu_id'); + return $adminInfo; + } + + /** + * 有效时间 + * + * @param int $timestamp1 + * @param int $timestamp2 + * + * @return int + */ + private function timestamp_diff(int $timestamp1, int $timestamp2): int + { + $diff = $timestamp2 - $timestamp1; + return max(0, $diff); + } +} diff --git a/demo/webman/backend/app/services/system/admin/SystemDeptServices.php b/demo/webman/backend/app/services/system/admin/SystemDeptServices.php new file mode 100644 index 0000000000000000000000000000000000000000..0c22ba29ba02863866c9298712ec87791d5c90cb --- /dev/null +++ b/demo/webman/backend/app/services/system/admin/SystemDeptServices.php @@ -0,0 +1,123 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\SystemDeptDao; +use support\Container; + +/** + * Class SystemRoleServices + * + * @package app\services\system\admin + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取数据 + */ +class SystemDeptServices extends BaseServices +{ + + /** + * 当前管理员权限缓存前缀 + */ + const ADMIN_RULES_LEVEL = 'Admin_dept_level_'; + + /** + * SystemRoleServices constructor. + */ + public function __construct() + { + $this->dao = Container::make(SystemDeptDao::class); + } + + /** + * 获取后台菜单树型结构列表 + * + * @param array $where + * @param array $field + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where, array $field = ['*']): array + { + [$page, $limit] = $this->getPageValue(false); + $deptList = $this->dao->getDeptList($where, $page, $limit); + $deptList = $this->getDeptsData($deptList); + return get_tree_children($deptList, 'children', 'dept_id', 'pid'); + } + + /** + * 获取一条数据 + * + * @param string $id + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function find(string $id): mixed + { + $roleInfo = $this->dao->get($id); + if (!$roleInfo) { + throw new AdminException(100026); + } + /** @var StoreOrderServices $orderServices */ +// $systemRoleMenu = app()->make(SystemRoleMenuServices::class); +// $roleInfo->rules = $systemRoleMenu->column(['role_id' => $id], 'menu_id'); + return $roleInfo->getData(); + } + + /** + * 删除部门 + * + * @param string $id + * + * @return mixed + * @throws \ReflectionException + */ + public function delete(string $id): mixed + { + $ids = $this->dao->column(['pid' => $id], 'dept_id'); + if (count($ids)) { + foreach ($ids as $value) { + $this->delete($value); + } + } + return $this->dao->delete($id); + } + + /** + * 获取组织没有被修改器修改的数据 + * + * @param $deptList + * + * @return array + */ + private function getDeptsData($deptList): array + { + + $data = []; + foreach ($deptList as $item) { + $item = $item->getData(); +// if (isset($item['menu_path'])) { +// $item['menu_path'] = '/' . config('app.admin_prefix', 'admin') . $item['menu_path']; +// } + $data[] = $item; + } + + return $data; + } +} diff --git a/demo/webman/backend/app/services/system/admin/SystemMenusServices.php b/demo/webman/backend/app/services/system/admin/SystemMenusServices.php new file mode 100644 index 0000000000000000000000000000000000000000..5389ac0a40b1bfb6d0dcc4eb519274f4015b2e78 --- /dev/null +++ b/demo/webman/backend/app/services/system/admin/SystemMenusServices.php @@ -0,0 +1,280 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\common\Json; +use app\common\utils\Arr; +use app\dao\system\admin\SystemMenusDao; +use app\exception\AdminException; +use app\services\BaseServices; +use app\services\system\setting\SystemRoleServices; +use support\Container; + +/** + * 权限菜单 + * Class SystemMenusServices + * + * @package app\services\system + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取数据 + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method getSearchList() 主页搜索 + * @method getColumn(array $where, string $field, ?string $key = '') 主页搜索 + * @method getVisitName(string $rule) 根据访问地址获得菜单名 + */ +class SystemMenusServices extends BaseServices +{ + + /** + * 初始化 + * SystemMenusServices constructor. + */ + public function __construct() + { + $this->dao = Container::make(SystemMenusDao::class); + } + + /** + * 获取菜单没有被修改器修改的数据 + * + * @param $menusList + * + * @return array + */ + public function getMenusData($menusList): array + { + $data = []; + + $result=$menusList->toArray(); + + foreach ($menusList as $item) { + $item = $item->getData(); +// if (isset($item['menu_path'])) { +// $item['menu_path'] = '/' . config('app.admin_prefix', 'admin') . $item['menu_path']; +// } + $data[] = $item; + } + + return $data; + } + + /** + * 获取后台权限菜单和权限 + * + * @param array|string $menuId + * @param int $level + * + + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getMenusList(array|string $menuId, int $level = 1) + { + /** @var SystemRoleServices $systemRoleServices */ + $menusList = $this->dao->getMenusRoule(['route' => $level != 0 ? $menuId : '', 'is_show' => 1]); + $unique = $this->dao->getMenusUnique(['unique' => $level != 0 ? $menuId : '']); + return [Arr::getMenuLayuiViewList($this->getMenusData($menusList)), $unique]; + + } + + /** + * 获取后台菜单树型结构列表 + * + * @param array $where + * @param array $field + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where, array $field = ['*']): array + { + $menusList = $this->dao->getMenusList($where, $field); + $menusList = $this->getMenusData($menusList); + return get_tree_children($menusList); + } + + /** + * 获取form表单所需要的所要的菜单列表 + * + * @return array[] + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + protected function getFormSelectMenus(): array + { + $menuList = $this->dao->getMenusRoule(['delete_time' => null], ['id', 'pid', 'menu_name']); + $list = sort_list_tier($this->getMenusData($menuList), '0', 'pid', 'id'); + $menus = [['value' => 0, 'label' => '顶级按钮']]; + foreach ($list as $menu) { + $menus[] = ['value' => $menu['id'], 'label' => $menu['html'] . $menu['menu_name']]; + } + return $menus; + } + + /** + * @param string $value + * @param int $auth_type + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + protected function getFormCascaderMenus(string $value = '-1', int $auth_type = 0): array + { + $where = ['delete_time' => null]; + $menuList = $this->dao->getMenusRoule($where, ['id as value', 'pid', 'menu_name as label']); + $menuList = $this->getMenusData($menuList); + if ($value) { + $data = get_tree_value($menuList, $value); + } else { + $data = []; + } + return [get_tree_children($menuList, 'children', 'value'), array_reverse($data)]; + } + + /** + * 修改权限菜单 + * + * @param string $id + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function updateMenus(string $id): array + { + $menusInfo = $this->dao->get($id); + if (!$menusInfo) { + throw new AdminException('数据不存在'); + } + return create_form('修改权限', $this->createMenusForm($menusInfo->getData()), $this->url('/setting/update/' . $id), 'PUT'); + } + + /** + * 获取一条数据 + * + * @param string $id + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function find(string $id): mixed + { + $menusInfo = $this->dao->get($id); + if (!$menusInfo) { + throw new AdminException(100026); + } + $menu = $menusInfo->getData(); + $menu['pid'] = $menu['pid']; + $menu['auth_type'] = (int)$menu['auth_type']; + $menu['is_header'] = (int)$menu['is_header']; + $menu['is_show'] = (int)$menu['is_show']; + $menu['is_show_path'] = (int)$menu['is_show_path']; + if (!$menu['path']) { + [$menuList, $data] = $this->getFormCascaderMenus($menu['pid']); + $menu['path'] = $data; + } else { + $menu['path'] = explode('/', $menu['path']); + if (is_array($menu['path'])) { + $menu['path'] = array_map(function ($item) { + return (int)$item; + }, $menu['path']); + } + } + return $menu; + } + + /** + * 删除菜单 + * + * @param string $id + * + * @return mixed + * @throws \ReflectionException + */ + public function delete(string $id): mixed + { + $ids = $this->dao->column(['pid' => $id], 'id'); + if (count($ids)) { + foreach ($ids as $value) { + $this->delete($value); + } + } + return $this->dao->delete($id); + } + + /** + * 获取添加身份规格 + * + * @param $roleId + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getMenus($roleId): array + { + $field = ['menu_name', 'pid', 'id']; + $where = ['delete_time' => null, 'is_show' => 1]; + if (!$roleId) { + $menus = $this->dao->getMenusRoule($where, $field); + } else { + /** @var SystemRoleServices $service */ + $service = Container::make(SystemRoleMenuServices::class); + $roles = is_string($roleId) ? explode(',', $roleId) : $roleId; + $ids = $service->getRoleIds($roles); + $menus = $this->dao->getMenusRoule(['rule' => $ids] + $where, $field); + } + return $this->tidyMenuTier(false, $menus); + } + + /** + * 组合菜单数据 + * + * @param bool $adminFilter + * @param array|object $menusList + * @param string $pid + * @param array $navList + * + * @return array + */ + public function tidyMenuTier(bool $adminFilter = false, array|object $menusList = [], string $pid = '-1', array $navList = []): array + { + foreach ($menusList as $k => $menu) { + $menu = $menu->getData(); + $menu['title'] = $menu['menu_name']; + unset($menu['menu_name']); + if ($menu['pid'] == $pid) { + unset($menusList[$k]); + $menu['children'] = $this->tidyMenuTier($adminFilter, $menusList, $menu['id']); + if ($pid == 0 && !count($menu['children'])) continue; + if ($menu['children']) $menu['expand'] = true; + $navList[] = $menu; + } + } + return $navList; + } +} diff --git a/demo/webman/backend/app/services/system/admin/SystemPostServices.php b/demo/webman/backend/app/services/system/admin/SystemPostServices.php new file mode 100644 index 0000000000000000000000000000000000000000..d0c91483944f025fe4ab9a80a814ca0839009ed6 --- /dev/null +++ b/demo/webman/backend/app/services/system/admin/SystemPostServices.php @@ -0,0 +1,125 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\SystemPostDao; +use app\exception\AdminException; +use app\services\BaseServices; +use support\Container; + +/** + * Class SystemRoleServices + * + * @package app\services\system\admin + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取数据 + */ +class SystemPostServices extends BaseServices +{ + + /** + * 当前管理员权限缓存前缀 + */ + const ADMIN_RULES_LEVEL = 'Admin_post_level_'; + + /** + * SystemRoleServices constructor. + */ + public function __construct() + { + $this->dao = Container::make(SystemPostDao::class); + } + + /** + * 获取职位树型结构列表 + * + * @param array $where + * @param array $field + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where, array $field = ['*']): array + { + [$page, $limit,$defaultLimit,$limitMax] = $this->getPageValue(false); + $deptList = $this->dao->getPostList($where, $page,$limitMax); + $deptList = $this->getPostsData($deptList); + return get_tree_children($deptList, 'children', 'post_id', 'pid'); + } + + /** + * 获取一条数据 + * + * @param string $id + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException|\app\exception\AdminException + */ + public function find(string $id): mixed + { + $roleInfo = $this->dao->get($id); + if (!$roleInfo) { + throw new AdminException('数据不存在'); + } + /** @var StoreOrderServices $orderServices */ +// $systemRoleMenu = app()->make(SystemRoleMenuServices::class); +// $roleInfo->rules = $systemRoleMenu->column(['role_id' => $id], 'menu_id'); + return $roleInfo->getData(); + } + + /** + * 删除职位 + * + * @param string $id + * + * @return mixed + * @throws \ReflectionException + */ + public function delete(string $id): mixed + { + $ids = $this->dao->column(['pid' => $id], 'post_id'); + if (count($ids)) { + foreach ($ids as $value) { + $this->delete($value); + } + } + return $this->dao->delete($id); + } + + /** + * 获取组织没有被修改器修改的数据 + * + * @param $deptList + * + * @return array + */ + private function getPostsData($deptList): array + { + + $data = []; + foreach ($deptList as $item) { + $item = $item->getData(); +// if (isset($item['menu_path'])) { +// $item['menu_path'] = '/' . config('app.admin_prefix', 'admin') . $item['menu_path']; +// } + $data[] = $item; + } + + return $data; + } +} diff --git a/demo/webman/backend/app/services/system/admin/SystemRoleDeptServices.php b/demo/webman/backend/app/services/system/admin/SystemRoleDeptServices.php new file mode 100644 index 0000000000000000000000000000000000000000..34bd2451b90f0cd1dca5fbc1295cc2c7388dbf06 --- /dev/null +++ b/demo/webman/backend/app/services/system/admin/SystemRoleDeptServices.php @@ -0,0 +1,56 @@ +dao = Container::make(SystemRoleDeptDao::class); + } + + + /** + * 角色分配组织 + * @param array $data + * + * @return mixed + * @throws \Exception + */ + public function create(array $data) + { + return $this->transaction(function () use ($data) { + + $this->delete($data['role_id'], 'role_id'); + if (empty($data['checked_dept'])) { + return true; + } + $list = []; + foreach ($data['checked_dept'] as $key => $value) { + $list[$key]['role_id'] = $data['role_id']; + $list[$key]['dept_id'] = $value; + } + if ($this->dao->saveAll($list)) { + CacheService::clear(); + return true; + } else { + throw new AdminException('添加失败'); + } + }); + } +} diff --git a/demo/webman/backend/app/services/system/admin/SystemRoleMenuServices.php b/demo/webman/backend/app/services/system/admin/SystemRoleMenuServices.php new file mode 100644 index 0000000000000000000000000000000000000000..40d62f7270d3b1b2da14b35dd5677d75235154f2 --- /dev/null +++ b/demo/webman/backend/app/services/system/admin/SystemRoleMenuServices.php @@ -0,0 +1,70 @@ +dao = Container::make(SystemRoleMenuDao::class); + } + + /** + * 添加角色规则 + * + * @param array $data + * + * @return mixed + * @throws \Exception + */ + public function create(array $data) + { + return $this->transaction(function () use ($data) { + + $this->delete($data['role_id'], 'role_id'); + if (empty($data['checked_menus'])) { + return true; + } + $list = []; + foreach ($data['checked_menus'] as $key => $value) { + $list[$key]['role_id'] = $data['role_id']; + $list[$key]['menu_id'] = $value; + } + if ($this->dao->saveAll($list)) { + CacheService::clear(); + return true; + } else { + throw new AdminException('添加失败'); + } + }); + } + + /** + * 获取权限id + * + * @param array $rules 角色Id + * + * @return array + */ + public function getRoleIds(array $rules): array + { + $result = $this->dao->getColumn([['role_id', 'IN', $rules]], 'menu_id'); + return array_unique($result); + } +} diff --git a/demo/webman/backend/app/services/system/admin/SystemRolePostServices.php b/demo/webman/backend/app/services/system/admin/SystemRolePostServices.php new file mode 100644 index 0000000000000000000000000000000000000000..9ae199dc0ed6ca167e2eb08f5eeb4d799ac77644 --- /dev/null +++ b/demo/webman/backend/app/services/system/admin/SystemRolePostServices.php @@ -0,0 +1,57 @@ +dao = Container::make(SystemRolePostDao::class); + } + + + /** + * 角色分配组织 + * @param array $data + * + * @return mixed + * @throws \Exception + */ + public function create(array $data) + { + return $this->transaction(function () use ($data) { + + $this->delete($data['role_id'], 'role_id'); + if (empty($data['checked_post'])) { + return true; + } + $list = []; + foreach ($data['checked_post'] as $key => $value) { + $list[$key]['role_id'] = $data['role_id']; + $list[$key]['post_id'] = $value; + } + if ($this->dao->saveAll($list)) { + CacheService::clear(); + return true; + } else { + throw new AdminException('添加失败'); + } + }); + } +} diff --git a/demo/webman/backend/app/services/system/admin/SystemRoleServices.php b/demo/webman/backend/app/services/system/admin/SystemRoleServices.php new file mode 100644 index 0000000000000000000000000000000000000000..abf8ed66c71735fba01aed3d3b496c63c8456de1 --- /dev/null +++ b/demo/webman/backend/app/services/system/admin/SystemRoleServices.php @@ -0,0 +1,233 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\admin; + +use app\dao\system\admin\SystemRoleDao; +use app\exception\AdminException; +use app\exception\AuthException; +use app\services\BaseServices; +use support\Container; +use support\Request; + +/** + * Class SystemRoleServices + * + * @package app\services\system\admin + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取数据 + */ +class SystemRoleServices extends BaseServices +{ + + /** + * 当前管理员权限缓存前缀 + */ + const ADMIN_RULES_LEVEL = 'Admin_rules_level_'; + + /** + * SystemRoleServices constructor. + */ + public function __construct() + { + $this->dao = Container::make(SystemRoleDao::class); + } + + /** + * 获取一条数据 + * + * @param string $id + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function find(string $id): mixed + { + $roleInfo = $this->dao->get($id); + if (!$roleInfo) { + throw new AdminException('数据不存在'); + } + + /** @var SystemRoleMenuServices $systemRoleMenu */ + $systemRoleMenu = Container::make(SystemRoleMenuServices::class); + $roleInfo->rules = $systemRoleMenu->column(['role_id' => $id], 'menu_id'); + + /** @var SystemRoleDeptServices $systemRoleDept */ + $systemRoleDept = Container::make(SystemRoleDeptServices::class); + $roleInfo->depts = $systemRoleDept->column(['role_id' => $id], 'dept_id'); + + /** @var SystemRolePostServices $systemRolePost */ + $systemRolePost = Container::make(SystemRolePostServices::class); + $roleInfo->posts = $systemRolePost->column(['role_id' => $id], 'post_id'); + return $roleInfo->getData(); + } + + /** + * 获取权限 + * + * @return mixed + */ + public function getRoleArray(array $where = [], string $field = '', string $key = '') + { + return $this->dao->getRoule($where, $field, $key); + } + + /** + * 获取表单所需的权限名称列表 + * + * @param int $level + * + * @return array + */ + public function getRoleFormSelect(int $level) + { + $list = $this->getRoleArray(['level' => $level, 'status' => 1]); + $options = []; + foreach ($list as $id => $roleName) { + $options[] = ['label' => $roleName, 'value' => $id]; + } + return $options; + } + + /** + * 身份管理列表 + * + * @param array $where + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getRoleList(array $where): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getRouleList($where, $page, $limit); + $count = $this->dao->count($where); + return compact('count', 'list'); + } + + /** + * 后台验证权限 + * + * @param Request $request + * + * @return bool + * @throws \throwable + */ + public function verifyAuth(Request $request): bool + { + // 获取当前的接口于接口类型 + $isPath = strpos($request->path(), $request->app); + $rule = $request->path(); + if ($isPath !== false) { + $rule = substr($request->path(), $isPath + strlen($request->app) + 1); + $rule = ltrim($rule, '/'); + } + $method = trim(strtolower($request->method())); + + // 判断接口是一下两种的时候放行 + if (in_array($rule, ['setting/admin/logout', 'menuslist'])) { + return true; + } + // 获取所有接口类型以及对应的接口 + $allAuth = $this->cacheDriver()->remember('all_auth', function () { + /** @var SystemMenusServices $menusService */ + $menusService = Container::make(SystemMenusServices::class); + $allList = $menusService->getColumn([['api_url', '<>', ''], ['auth_type', '=', 2]], 'api_url,methods'); + $allAuth = []; + foreach ($allList as $item) { + $allAuth[trim(strtolower($item['methods']))][] = trim(strtolower(str_replace(' ', '', $item['api_url']))); + } + return $allAuth; + }); + + // 权限菜单未添加时放行 + if (!in_array($rule, $allAuth[$method] ?? [])) return true; + + // 获取管理员的接口权限列表,存在时放行 + $auth = $this->getRolesByAuth($request->adminInfo()['role_id'], 2); + if (isset($auth[$method]) && in_array($rule, $auth[$method])) { + return true; + } else { + throw new AuthException('您暂时没有访问权限'); + } + } + + /** + * 获取指定权限 + * + * @param array $rules + * @param int $type + * @param string $cachePrefix + * + * @return array|mixed + * @throws \throwable + */ + public function getRolesByAuth(array $rules, int $type = 1, string $cachePrefix = self::ADMIN_RULES_LEVEL): mixed + { + if (empty($rules)) return []; + $authAll = []; + foreach ($rules as $value) { + $cacheName = md5($cachePrefix . '_' . $type . '_' . $value); + $rolesAuth = $this->cacheDriver()->remember($cacheName, function () use ($value, $type) { + $menusService = Container::make(SystemMenusServices::class); + $authList = $menusService->getColumn([['auth_type', '=', $type]], 'api_url,methods'); + $rolesAuth = []; + foreach ($authList as $item) { + $rolesAuth[trim(strtolower($item['methods']))][] = trim(strtolower(str_replace(' ', '', $item['api_url']))); + } + return $rolesAuth; + }); + $authAll = array_merge($authAll, $rolesAuth); + } + return Arr::uniqueArrayValues($authAll); + } + + /** + * 删除角色 + * + * @param string $id + * + * @return mixed + * @throws \ReflectionException + */ + public + function delete(string $id): mixed + { + $ids = $this->dao->column(['pid' => $id], 'role_id'); + if (count($ids)) { + foreach ($ids as $value) { + $this->delete($value); + } + } + return $this->dao->delete($id); + } + + /** + * 获取权限id + * + * @param string $rules + * + * @return array + */ + public + function getRoleIds(string $rules): array + { + $systemRoleMenuService = Container::make(SystemRoleMenuServices::class); + $rules = $systemRoleMenuService->dao->getColumn([['role_id', '=', $rules]], 'menu_id'); + return array_unique(explode(',', implode(',', $rules))); + } +} diff --git a/demo/webman/backend/app/services/system/attachment/SystemAttachmentCategoryServices.php b/demo/webman/backend/app/services/system/attachment/SystemAttachmentCategoryServices.php new file mode 100644 index 0000000000000000000000000000000000000000..cc86dbb6bd0640a58c8a53e1b3d8009b54955606 --- /dev/null +++ b/demo/webman/backend/app/services/system/attachment/SystemAttachmentCategoryServices.php @@ -0,0 +1,168 @@ + +// +---------------------------------------------------------------------- +declare (strict_types=1); + +namespace app\services\system\attachment; + +use app\services\BaseServices; +use app\dao\system\attachment\SystemAttachmentCategoryDao; +use phoenix\exceptions\AdminException; + + +/** + * SystemAttachmentCategoryServices + * + * @author Mr.April + * @since 1.0 + * @method get($id) 获取一条数据 + * @method count($where) 获取条件下数据总数 + */ +class SystemAttachmentCategoryServices extends BaseServices +{ + + /** + * SystemAttachmentCategoryServices constructor. + * + * @param SystemAttachmentCategoryDao $dao + */ + public function __construct(SystemAttachmentCategoryDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取分类列表 + * + * @param array $where + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAll(array $where): array + { + $list = $this->dao->getList($where); + if ($where['all'] == 1) { + $list = $this->tidyMenuTier($list); + } else { + foreach ($list as &$item) { + $item['title'] = $item['name']; + if ($where['name'] == '' && $this->dao->count(['pid' => $item['id']])) { + $item['loading'] = false; + $item['children'] = []; + } + } + } + return compact('list'); + } + + /** + * 格式化列表 + * + * @param $menusList + * @param string $pid + * @param array $navList + * + * @return array + */ + public function tidyMenuTier($menusList, string $pid = '-1', array $navList = []): array + { + foreach ($menusList as $k => $menu) { + $menu['title'] = $menu['name']; + if ($menu['pid'] == $pid) { + unset($menusList[$k]); + $menu['children'] = $this->tidyMenuTier($menusList, $menu['id']); + if (count($menu['children'])) { + $menu['expand'] = true; + } else { + unset($menu['children']); + } + $navList[] = $menu; + } + } + return $navList; + } + + /** + * 保存新建的资源 + * + * @param array $data + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function save(array $data): mixed + { + if ($this->dao->getOne(['name' => $data['name']])) { + throw new AdminException(400101); + } + $res = $this->dao->save($data); + if (!$res) throw new AdminException(100022); + return $res; + } + + /** + * 保存修改的资源 + * + * @param string $id + * @param array $data + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function update(string $id, array $data) + { + $attachment = $this->dao->getOne(['name' => $data['name']]); + if ($attachment && $attachment['id'] != $id) { + throw new AdminException(400101); + } + $res = $this->dao->update($id, $data); + if (!$res) { + throw new AdminException(100007); + } + } + + /** + * 删除分类 + * + * @param string $id + */ + public function del(string $id): void + { + $count = $this->dao->getCount(['pid' => $id]); + if ($count) { + throw new AdminException(400102); + } else { + $res = $this->dao->delete($id); + if (!$res) throw new AdminException(400102); + } + } + + /** + * 获取一条数据 + * + * @param $where + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getOne($where) + { + return $this->dao->getOne($where); + } +} diff --git a/demo/webman/backend/app/services/system/attachment/SystemAttachmentServices.php b/demo/webman/backend/app/services/system/attachment/SystemAttachmentServices.php new file mode 100644 index 0000000000000000000000000000000000000000..1b38c4af38c7d26178171b065f61aafb9d909170 --- /dev/null +++ b/demo/webman/backend/app/services/system/attachment/SystemAttachmentServices.php @@ -0,0 +1,368 @@ + +// +---------------------------------------------------------------------- +declare (strict_types=1); + +namespace app\services\system\attachment; + +use app\services\BaseServices; +use app\dao\system\attachment\SystemAttachmentDao; +use app\services\product\product\CopyTaobaoServices; +use phoenix\exceptions\AdminException; +use phoenix\exceptions\ApiException; +use app\services\other\UploadService; +use phoenix\exceptions\UploadException; + +/** + * Class SystemAttachmentServices + * + * @package app\services\attachment + * @method getYesterday() 获取昨日生成数据 + * @method delYesterday() 删除昨日生成数据 + * @method scanUploadImage($scan_token) 获取扫码上传的图片数据 + */ +class SystemAttachmentServices extends BaseServices +{ + + /** + * SystemAttachmentServices constructor. + * + * @param SystemAttachmentDao $dao + */ + public function __construct(SystemAttachmentDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取单个资源 + * + * @param array $where + * @param string $field + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo(array $where, string $field = '*') + { + return $this->dao->getOne($where, $field); + } + + /** + * 获取图片列表 + * + * @param array $where + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getImageList(array $where) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getList($where, $page, $limit); + $site_url = sys_config('site_url'); + foreach ($list as &$item) { + if ($site_url) { + $item['satt_dir'] = (str_contains($item['satt_dir'], $site_url) || str_contains($item['satt_dir'], 'http')) ? $item['satt_dir'] : $site_url . $item['satt_dir']; + $item['att_dir'] = (str_contains($item['att_dir'], $site_url) || str_contains($item['att_dir'], 'http')) ? $item['satt_dir'] : $site_url . $item['att_dir']; + $item['time'] = date('Y-m-d H:i:s', $item['time']); + } + } + $where['module_type'] = 1; + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * 删除图片 + * + * @param string $ids + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function del(string $ids) + { + $ids = explode(',', $ids); + if (empty($ids)) throw new AdminException(400599); + foreach ($ids as $v) { + $attinfo = $this->dao->get($v); + if ($attinfo) { + try { + $upload = UploadService::init($attinfo['image_type']); + if ($attinfo['image_type'] == 1) { + if (strpos($attinfo['att_dir'], '/') == 0) { + $attinfo['att_dir'] = substr($attinfo['att_dir'], 1); + } + if ($attinfo['att_dir']) $upload->delete($attinfo['att_dir']); + } else { + if ($attinfo['name']) $upload->delete($attinfo['name']); + } + } catch (\Throwable $e) { + } + $this->dao->delete($v); + } + } + } + + /** + * 图片上传 + * + * @param int $pid + * @param string $file + * @param int $upload_type + * @param int $type + * @param $menuName + * @param string $uploadToken + * + * @return mixed + */ + public function upload(string $pid, string $file, int $upload_type, int $type, $menuName, string $uploadToken = ''): mixed + { + $realName = false; + if ($upload_type == 0) { + $upload_type = sys_config('upload_type', 1); + } + if ($menuName == 'weixin_ckeck_file' || $menuName == 'ico_path') { + $upload_type = 1; + $realName = true; + } + try { + $path = make_path('attach', 2, true); + $upload = UploadService::init($upload_type); + $res = $upload->to($path)->validate()->move($file, $realName); + if ($res === false) { + throw new UploadException($upload->getError()); + } else { + $fileInfo = $upload->getUploadInfo(); + $fileType = pathinfo($fileInfo['name'], PATHINFO_EXTENSION); +// if ($fileInfo && $type == 0 && !in_array($fileType, ['xlsx', 'xls', 'mp4'])) { + if ($fileInfo && $type == 0) { + $data['name'] = $fileInfo['name']; + $data['real_name'] = $fileInfo['real_name']; + $data['att_dir'] = $fileInfo['dir']; + $data['satt_dir'] = $fileInfo['thumb_path']; + $data['att_size'] = $fileInfo['size']; + $data['att_type'] = $fileInfo['type']; + $data['ext'] = $fileInfo['ext']; + $data['image_type'] = $upload_type; + $data['module_type'] = 1; + $data['time'] = $fileInfo['time'] ?? time(); + $data['pid'] = $pid; + $data['scan_token'] = $uploadToken; + $this->dao->save($data); + } + return $res->filePath; + } + } catch (\Exception $e) { + throw new UploadException($e->getMessage()); + } + } + + /** + * @param array $data + * + * @return \crmeb\basic\BaseModel + */ + public function move(array $data) + { + $this->dao->move($data); + } + + /** + * 添加信息 + * + * @param array $data + */ + public function save(array $data) + { + $this->dao->save($data); + } + + /** + * TODO 添加附件记录 + * + * @param $name + * @param $att_size + * @param $att_type + * @param $att_dir + * @param string $satt_dir + * @param int $pid + * @param int $imageType + * @param int $time + * + * @return SystemAttachment + */ + public function attachmentAdd($name, $att_size, $att_type, $att_dir, $satt_dir = '', $pid = 0, $imageType = 1, $time = 0, $module_type = 1) + { + $data['name'] = $name; + $data['att_dir'] = $att_dir; + $data['satt_dir'] = $satt_dir; + $data['att_size'] = $att_size; + $data['att_type'] = $att_type; + $data['image_type'] = $imageType; + $data['module_type'] = $module_type; + $data['time'] = $time ?: time(); + $data['pid'] = $pid; + if (!$this->dao->save($data)) { + throw new ApiException(100022); + } + return true; + } + + /** + * 推广名片生成 + * + * @param $name + */ + public function getLikeNameList($name) + { + return $this->dao->getLikeNameList(['like_name' => $name], 0, 0); + } + + /** + * 清除昨日海报 + * + * @return bool + * @throws \Exception + */ + public function emptyYesterdayAttachment(): bool + { + try { + $list = $this->dao->getYesterday(); + foreach ($list as $key => $item) { + $upload = UploadService::init((int)$item['image_type']); + if ($item['image_type'] == 1) { + $att_dir = $item['att_dir']; + if ($att_dir && strstr($att_dir, 'uploads') !== false) { + if (strstr($att_dir, 'http') === false) + $upload->delete($att_dir); + else { + $filedir = substr($att_dir, strpos($att_dir, 'uploads')); + if ($filedir) $upload->delete($filedir); + } + } + } else { + if ($item['name']) $upload->delete($item['name']); + } + } + $this->dao->delYesterday(); + return true; + } catch (\Exception $e) { + $this->dao->delYesterday(); + return true; + } + } + + /** + * 视频分片上传 + * + * @param $data + * @param $file + * + * @return mixed + */ + public function videoUpload($data, $file) + { + $pathinfo = pathinfo($data['filename']); + if (isset($pathinfo['extension']) && !in_array($pathinfo['extension'], ['avi', 'mp4', 'wmv', 'rm', 'mpg', 'mpeg', 'mov', 'flv', 'swf'])) { + throw new AdminException(400558); + } + $public_dir = app()->getRootPath() . 'public'; + $dir = '/uploads/attach/' . date('Y') . DIRECTORY_SEPARATOR . date('m') . DIRECTORY_SEPARATOR . date('d'); + $all_dir = $public_dir . $dir; + if (!is_dir($all_dir)) mkdir($all_dir, 0777, true); + $filename = $all_dir . '/' . $data['filename'] . '__' . $data['chunkNumber']; + move_uploaded_file($file['tmp_name'], $filename); + $res['code'] = 0; + $res['msg'] = 'error'; + $res['file_path'] = ''; + if ($data['chunkNumber'] == $data['totalChunks']) { + $blob = ''; + for ($i = 1; $i <= $data['totalChunks']; $i++) { + $blob .= file_get_contents($all_dir . '/' . $data['filename'] . '__' . $i); + } + file_put_contents($all_dir . '/' . $data['filename'], $blob); + for ($i = 1; $i <= $data['totalChunks']; $i++) { + @unlink($all_dir . '/' . $data['filename'] . '__' . $i); + } + if (file_exists($all_dir . '/' . $data['filename'])) { + $res['code'] = 2; + $res['msg'] = 'success'; + $res['file_path'] = sys_config('site_url') . $dir . '/' . $data['filename']; + } + } else { + if (file_exists($all_dir . '/' . $data['filename'] . '__' . $data['chunkNumber'])) { + $res['code'] = 1; + $res['msg'] = 'waiting'; + $res['file_path'] = ''; + } + } + return $res; + } + + /** + * 网络图片上传 + * + * @param $data + * + * @return bool + * @throws \Exception + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/06/13 + */ + public function onlineUpload($data) + { + //生成附件目录 + if (make_path('attach', 3, true) === '') { + throw new AdminException(400555); + } + + //上传图片 + /** @var SystemAttachmentServices $systemAttachmentService */ + $systemAttachmentService = app()->make(SystemAttachmentServices::class); + $siteUrl = sys_config('site_url'); + + foreach ($data['images'] as $image) { + $uploadValue = app()->make(CopyTaobaoServices::class)->downloadImage($image); + if (is_array($uploadValue)) { + //TODO 拼接图片地址 + if ($uploadValue['image_type'] == 1) { + $imagePath = $siteUrl . $uploadValue['path']; + } else { + $imagePath = $uploadValue['path']; + } + //写入数据库 + if (!$uploadValue['is_exists']) { + $systemAttachmentService->save([ + 'name' => $uploadValue['name'], + 'real_name' => $uploadValue['name'], + 'att_dir' => $imagePath, + 'satt_dir' => $imagePath, + 'att_size' => $uploadValue['size'], + 'att_type' => $uploadValue['mime'], + 'image_type' => $uploadValue['image_type'], + 'module_type' => 1, + 'time' => time(), + 'pid' => $data['pid'], + ]); + } + } + } + return true; + } +} diff --git a/demo/webman/backend/app/services/system/config/SystemConfigServices.php b/demo/webman/backend/app/services/system/config/SystemConfigServices.php new file mode 100644 index 0000000000000000000000000000000000000000..2490a9270630bc050cecb2e5eb8030eb16cbc8b5 --- /dev/null +++ b/demo/webman/backend/app/services/system/config/SystemConfigServices.php @@ -0,0 +1,1315 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\config; + +use app\dao\system\config\SystemConfigDao; +use app\services\BaseServices; +use support\Container; + +/** + * 系统配置 + * Class SystemConfigServices + * + * @package app\services\system\config + * @method count(array $where = []) 获取指定条件下的count + * @method save(array $data) 保存数据 + * @method get(int $id, ?array $field = []) 获取一条数据 + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method delete(int $id, ?string $key = null) 删除数据 + * @method getUploadTypeList(string $configName) 获取上传配置中的上传类型 + */ +class SystemConfigServices extends BaseServices +{ + /** + * form表单句柄 + * + * @var FormBuilder + */ + protected $builder; + + /** + * 表单数据切割符号 + * + * @var string + */ + protected string $cuttingStr = '=>'; + + /** + * 表单提交url + * + * @var string[] + */ + protected array $postUrl = [ + 'setting' => [ + 'url' => '/setting/config/save_basics', + 'auth' => [], + ], + 'serve' => [ + 'url' => '/serve/sms_config/save_basics', + 'auth' => ['short_letter_switch'], + ], + 'freight' => [ + 'url' => '/freight/config/save_basics', + 'auth' => ['express'], + ], + 'agent' => [ + 'url' => '/agent/config/save_basics', + 'auth' => ['fenxiao'], + ], + 'marketing' => [ + 'url' => '/marketing/integral_config/save_basics', + 'auth' => ['point'], + ], + ]; + + /** + * 子集控制规则 + * + * @var array[] + */ + protected array $relatedRule = [ + 'brokerage_func_status' => [ + 'son_type' => [ + 'store_brokerage_statu' => [ + 'son_type' => ['store_brokerage_price' => ''], + 'show_value' => 3, + ], + 'brokerage_bindind' => '', + 'store_brokerage_binding_status' => [ + 'son_type' => ['store_brokerage_binding_time' => ''], + 'show_value' => 2, + ], + 'spread_banner' => '', + 'brokerage_level' => '', + 'division_status' => '', + ], + 'show_value' => 1, + ], + 'brokerage_user_status' => [ + 'son_type' => [ + 'uni_brokerage_price' => '', + 'day_brokerage_price_upper' => '', + ], + 'show_value' => 1, + ], + 'invoice_func_status' => [ + 'son_type' => [ + 'special_invoice_status' => '', + ], + 'show_value' => 1, + ], + 'member_func_status' => [ + 'son_type' => [ + 'order_give_exp' => '', + 'sign_give_exp' => '', + 'invite_user_exp' => '', + ], + 'show_value' => 1, + ], + 'balance_func_status' => [ + 'son_type' => [ + 'recharge_attention' => '', + 'recharge_switch' => '', + 'store_user_min_recharge' => '', + ], + 'show_value' => 1, + ], + 'pay_wechat_type' => [ + 'son_type' => [ + 'pay_weixin_key' => '', + ], + 'show_value' => 0, + ], + 'pay_wechat_type@' => [ + 'son_type' => [ + 'pay_weixin_serial_no' => '', + 'pay_weixin_key_v3' => '', + ], + 'show_value' => 1, + ], + 'image_watermark_status' => [ + 'son_type' => [ + 'watermark_type' => [ + 'son_type' => [ + 'watermark_image' => '', + 'watermark_opacity' => '', + 'watermark_rotate' => '', + ], + 'show_value' => 1, + ], + 'watermark_position' => '', + 'watermark_x' => '', + 'watermark_y' => '', + 'watermark_type@' => [ + 'son_type' => [ + 'watermark_text' => '', + 'watermark_text_size' => '', + 'watermark_text_color' => '', + 'watermark_text_angle' => '', + ], + 'show_value' => 2, + ], + ], + 'show_value' => 1, + ], + 'customer_type' => [ + 'son_type' => [ + 'customer_phone' => '', + ], + 'show_value' => 1, + ], + 'customer_type@' => [ + 'son_type' => [ + 'customer_url' => '', + 'customer_corpId' => '', + ], + 'show_value' => 2, + ], + 'pay_new_weixin_open' => [ + 'son_type' => [ + 'pay_new_weixin_mchid' => '', + ], + 'show_value' => 1, + ], + ]; + + public function __construct() + { + $this->dao = Container::make(SystemConfigDao::class); + $this->builder = Container::make(FormBuilder::class); + } + + /** + * @return array|int[]|string[] + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/04/12 + */ + public function getSonConfig(): array + { + $sonConfig = []; + $rolateRule = $this->relatedRule; + if ($rolateRule) { + foreach ($rolateRule as $key => $value) { + $sonConfig = array_merge($sonConfig, array_keys($value['son_type'])); + foreach ($value['son_type'] as $k => $v) { + if (isset($v['son_type'])) { + $sonConfig = array_merge($sonConfig, array_keys($v['son_type'])); + } + } + } + } + return $sonConfig; + } + + /** + * 获取单个系统配置 + * + * @param string $configName + * @param null $default + * + * @return mixed|null + * @throws \ReflectionException + */ + public function getConfigValue(string $configName, $default = null): mixed + { + $value = $this->dao->getConfigValue($configName); + return is_null($value) ? $default : json_decode($value, true); + } + + /** + * 获取全部配置 + * + * @param array $configName + * + * @return array + * @throws \ReflectionException + */ + public function getConfigAll(array $configName = []) + { + return array_map(function ($item) { + return json_decode($item, true); + }, $this->dao->getConfigAll($configName)); + } + + /** + * 获取配置并分页 + * + * @param array $where + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function getConfigList(array $where): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getConfigList($where, $page, $limit); + $count = $this->dao->count($where); + $tidy_srr = []; + foreach ($list as &$item) { + $item['value'] = $item['value'] ? json_decode($item['value'], true) ?: '' : ''; + if ($item['type'] == 'radio' || $item['type'] == 'checkbox') { + $item['value'] = $this->getRadioOrCheckboxValueInfo($item['menu_name'], $item['value']); + } + if ($item['type'] == 'upload' && !empty($item['value'])) { + if ($item['upload_type'] == 1 || $item['upload_type'] == 3) { + $item['value'] = [set_file_url($item['value'])]; + } elseif ($item['upload_type'] == 2) { + $item['value'] = set_file_url($item['value']); + } + foreach ($item['value'] as $key => $value) { + $tidy_srr[$key]['filepath'] = $value; + $tidy_srr[$key]['filename'] = basename($value); + } + $item['value'] = $tidy_srr; + } + } + return compact('count', 'list'); + } + + /** + * 获取单选按钮或者多选按钮的显示值 + * + * @param $menu_name + * @param $value + * + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException|\think\db\exception\DbException + */ + public function getRadioOrCheckboxValueInfo(string $menu_name, $value): string + { + $option = []; + $config_one = $this->dao->getOne(['menu_name' => $menu_name]); + if (!$config_one) { + return ''; + } + $parameter = explode("\n", $config_one['parameter']); + foreach ($parameter as $k => $v) { + if (isset($v) && strlen($v) > 0) { + $data = explode('=>', $v); + $option[$data[0]] = $data[1]; + } + } + $str = ''; + if (is_array($value)) { + foreach ($value as $v) { + $str .= $option[$v] . ','; + } + } else { + $str .= !empty($value) ? $option[$value] ?? '' : $option[0] ?? ''; + } + return $str; + } + + /** + * 获取系统配置信息 + * + * @param int $tabId + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getReadList($tabId): array + { + $info = $this->dao->getConfigTabAllList($tabId); + foreach ($info as $k => $v) { + if (!is_null(json_decode($v['value']))) + $info[$k]['value'] = json_decode($v['value'], true); + if ($v['type'] == 'upload' && !empty($v['value'])) { + if ($v['upload_type'] == 1 || $v['upload_type'] == 3) $info[$k]['value'] = explode(',', $v['value']); + } + } + return $info; + } + + /** + * 创建单行表单 + * + * @param string $type + * @param array $data + * + * @return array + */ + public function createTextForm(string $type, array $data): array + { + $formbuider = []; + switch ($type) { + case 'number': + $data['value'] = isset($data['value']) ? json_decode($data['value'], true) : 0; + $formbuider[] = $this->builder->number($data['menu_name'], $data['info'], (float)$data['value'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ]); + break; + case 'dateTime': + $formbuider[] = $this->builder->dateTime($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ]); + break; + case 'color': + $data['value'] = isset($data['value']) ? json_decode($data['value'], true) : ''; + $formbuider[] = $this->builder->color($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ]); + break; + default: + $data['value'] = isset($data['value']) ? json_decode($data['value'], true) : ''; + if ($data['menu_name'] == 'api') { + $formbuider[] = $this->builder->input($data['menu_name'], $data['info'], strpos($data['value'], 'http') === false ? sys_config('site_url') . $data['value'] : $data['value'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ])->col(13)->readonly(true); + } else { + $formbuider[] = $this->builder->input($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ])->col(13); + } + break; + } + return $formbuider; + } + + /** + * 创建多行文本框 + * + * @param array $data + * + * @return mixed + */ + public function createTextareaForm(array $data): mixed + { + $data['value'] = json_decode($data['value'], true) ?: ''; + $formbuider[] = $this->builder->textarea($data['menu_name'], $data['info'], $data['value'])->placeholder($data['desc'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ])->rows(6)->col(13); + return $formbuider; + } + + /** + * 创建当选表单 + * + * @param array $data + * @param array $control + * @param array $control_two + * + * @return array + */ + public function createRadioForm(array $data, $control = [], $control_two = []): array + { + $formbuider = []; + $data['value'] = json_decode($data['value'], true) ?: '0'; + $parameter = explode("\n", $data['parameter']); + $options = []; + if ($parameter) { + foreach ($parameter as $v) { + if (strstr($v, $this->cuttingStr) !== false) { + $pdata = explode($this->cuttingStr, $v); + $res = preg_match('/^[0-9]$/', $pdata[0]); + $options[] = ['label' => $pdata[1], 'value' => $res ? (int)$pdata[0] : $pdata[0]]; + } + } + $res = preg_match('/^[0-9]$/', $data['value']); + $formbuider[] = $radio = $this->builder->radio($data['menu_name'], $data['info'], $res ? (int)$data['value'] : $data['value'])->options($options)->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ])->col(13); + if ($control) { + $radio->appendControl($data['show_value'] ?? 1, is_array($control) ? $control : [$control]); + } + if ($control_two && isset($data['show_value2'])) { + $radio->appendControl($data['show_value2'] ?? 2, is_array($control_two) ? $control_two : [$control_two]); + } + return $formbuider; + } + } + + /** + * 创建上传组件表单 + * + * @param int $type + * @param array $data + * + * @return array + */ + public function createUploadForm(int $type, array $data): array + { + $formbuider = []; + switch ($type) { + case 1: + $data['value'] = json_decode($data['value'], true) ?: ''; + if ($data['value'] != '') $data['value'] = set_file_url($data['value']); + $formbuider[] = $this->builder->frameImage($data['menu_name'], $data['info'], $this->url(config('app.admin_prefix', 'admin') . '/widget.images/index', ['fodder' => $data['menu_name']], true), $data['value']) + ->icon('ios-image')->width('950px')->height('560px')->modal(['footer-hide' => true])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ])->col(13); + break; + case 2: + $data['value'] = json_decode($data['value'], true) ?: []; + if ($data['value']) + $data['value'] = set_file_url($data['value']); + $formbuider[] = $this->builder->frameImages($data['menu_name'], $data['info'], $this->url(config('app.admin_prefix', 'admin') . '/widget.images/index', ['fodder' => $data['menu_name'], 'type' => 'many', 'maxLength' => 5], true), $data['value']) + ->maxLength(5)->icon('ios-images')->width('950px')->height('560px')->modal(['footer-hide' => true]) + ->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ])->col(13); + break; + case 3: + $data['value'] = json_decode($data['value'], true) ?: ''; + if ($data['value'] != '') $data['value'] = set_file_url($data['value']); + $formbuider[] = $this->builder->uploadFile($data['menu_name'], $data['info'], $this->url('/adminapi/file/upload/1', ['type' => 1], false, true), $data['value']) + ->name('file')->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ])->col(13)->data(['menu_name' => $data['menu_name']])->headers([ + 'Authori-zation' => app()->request->header('Authori-zation'), + ]); + break; + } + return $formbuider; + } + + /** + * 创建单选框 + * + * @param array $data + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createCheckboxForm(array $data): array + { + $formbuider = []; + $data['value'] = json_decode($data['value'], true) ?: []; + $parameter = explode("\n", $data['parameter']); + $options = []; + if ($parameter) { + foreach ($parameter as $v) { + if (strstr($v, $this->cuttingStr) !== false) { + $pdata = explode($this->cuttingStr, $v); + $options[] = ['label' => $pdata[1], 'value' => $pdata[0]]; + } + } + $formbuider[] = $this->builder->checkbox($data['menu_name'], $data['info'], $data['value'])->options($options)->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ])->col(13); + } + return $formbuider; + } + + /** + * 创建选择框表单 + * + * @param array $data + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createSelectForm(array $data): array + { + $formbuider = []; + $data['value'] = json_decode($data['value'], true) ?: []; + $parameter = explode("\n", $data['parameter']); + $options = []; + if ($parameter) { + foreach ($parameter as $v) { + if (strstr($v, $this->cuttingStr) !== false) { + $pdata = explode($this->cuttingStr, $v); + $options[] = ['label' => $pdata[1], 'value' => $pdata[0]]; + } + } + $formbuider[] = $this->builder->select($data['menu_name'], $data['info'], $data['value'])->options($options)->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ])->col(13); + } + return $formbuider; + } + + /** + * 创建颜色选择器 + * + * @param array $data + * + * @return mixed + */ + public function createColorForm(array $data): mixed + { + $data['value'] = json_decode($data['value'], true) ?: ''; + $formbuider[] = $this->builder->color($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [ + 'type' => 'div', + 'class' => 'tips-info', + 'domProps' => ['innerHTML' => $data['desc']], + ])->col(13); + return $formbuider; + } + + public function bindBuilderData($data, $relatedRule): bool|array + { + if (!$data) return false; + $p_list = array(); + foreach ($relatedRule as $rk => $rv) { + $p_list[$rk] = $data[$rk]; + if (isset($rv['son_type']) && is_array($rv['son_type'])) { + foreach ($rv['son_type'] as $sk => $sv) { + if (is_array($sv) && isset($sv['son_type'])) { + foreach ($sv['son_type'] as $ssk => $ssv) { + $tmp = $data[$sk]; + $tmp['console'] = $data[$ssk]; + $p_list[$rk]['console'][] = $tmp; + } + } else { + $p_list[$rk]['console'][] = $data[$sk]; + } + } + } + + } + return array_values($p_list); + } + + /** + * 获取系统配置表单 + * + * @param $data + * @param bool $control + * @param array $controle_two + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function formTypeShine($data, $control = false, $controle_two = []): array + { + + switch ($data['type']) { + case 'text'://文本框 + return $this->createTextForm($data['input_type'], $data); + case 'radio'://单选框 + return $this->createRadioForm($data, $control, $controle_two); + case 'textarea'://多行文本框 + return $this->createTextareaForm($data); + case 'upload'://文件上传 + return $this->createUploadForm((int)$data['upload_type'], $data); + case 'checkbox'://多选框 + return $this->createCheckboxForm($data); + case 'select'://多选框 + return $this->createSelectForm($data); + case 'color': + return $this->createColorForm($data); + } + } + + /** + * @param int $tabId + * @param array $formData + * @param array $relatedRule + * + * @return array|bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function createConfigForm(int $tabId, array $relatedRule): bool|array + { + $list = $this->dao->getConfigTabAllList($tabId); + if (!$relatedRule) { + $formbuider = $this->createNoCrontrolForm($list); + } else { + $formbuider = $this->createBindCrontrolForm($list, $relatedRule); + } + return $formbuider; + } + + /** + * 创建 + * + * @param array $list + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function createForm(array $list): array + { + if (!$list) return []; + $list = array_combine(array_column($list, 'menu_name'), $list); + $formbuider = []; + $relateRule = $this->relatedRule; + $sonConfig = $this->getSonConfig(); + foreach ($list as $key => $data) { + if (in_array($key, $sonConfig)) { + continue; + } + switch ($data['type']) { + case 'text'://文本框 + $formbuider = array_merge($formbuider, $this->createTextForm($data['input_type'], $data)); + break; + case 'radio'://单选框 + $builder = []; + if (isset($relateRule[$key])) { + $role = $relateRule[$key]; + $data['show_value'] = $role['show_value']; + foreach ($role['son_type'] as $sk => $sv) { + if (isset($list[$sk])) { + $son_data = $list[$sk]; + $son_data['show_value'] = $role['show_value']; + $son_build = []; + if (isset($sv['son_type'])) { + foreach ($sv['son_type'] as $ssk => $ssv) { + $son_data['show_value'] = $sv['show_value']; + $son_build[] = $this->formTypeShine($list[$ssk])[0]; + unset($list[$ssk]); + } + } + $son_build_two = []; + if (isset($role['son_type'][$sk . '@'])) { + $son_type_two = $role['son_type'][$sk . '@']; + $son_data['show_value2'] = $son_type_two['show_value']; + if (isset($son_type_two['son_type'])) { + foreach ($son_type_two['son_type'] as $ssk => $ssv) { + if (isset($list[$ssk]['menu_name']) && $list[$ssk]['menu_name'] == 'watermark_text_color') $list[$ssk]['type'] = 'color'; + $son_build_two[] = $this->formTypeShine($list[$ssk])[0]; + unset($list[$ssk]); + } + } + } + $builder[] = $this->formTypeShine($son_data, $son_build, $son_build_two)[0]; + unset($list[$sk]); + } + } + $data['show_value'] = $role['show_value']; + } + $builder_two = []; + if (isset($relateRule[$key . '@'])) { + $role = $relateRule[$key . '@']; + $data['show_value2'] = $role['show_value']; + foreach ($role['son_type'] as $sk => $sv) { + $son_data = $list[$sk]; + $son_data['show_value'] = $role['show_value']; + $builder_two[] = $this->formTypeShine($son_data)[0]; + } + } + $formbuider = array_merge($formbuider, $this->createRadioForm($data, $builder, $builder_two)); + break; + case 'textarea'://多行文本框 + $formbuider = array_merge($formbuider, $this->createTextareaForm($data)); + break; + case 'upload'://文件上传 + $formbuider = array_merge($formbuider, $this->createUploadForm((int)$data['upload_type'], $data)); + break; + case 'checkbox'://多选框 + $formbuider = array_merge($formbuider, $this->createCheckboxForm($data)); + break; + case 'select'://多选框 + $formbuider = array_merge($formbuider, $this->createSelectForm($data)); + break; + } + } + return $formbuider; + } + + /**无组件绑定规则 + * + * @param array $list + * + * @return array|bool + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function createNoCrontrolForm(array $list) + { + if (!$list) return false; + $formbuider = []; + foreach ($list as $key => $data) { + + switch ($data['type']) { + case 'text'://文本框 + $formbuider = array_merge($formbuider, $this->createTextForm($data['input_type'], $data)); + break; + case 'radio'://单选框 + $formbuider = array_merge($formbuider, $this->createRadioForm($data)); + break; + case 'textarea'://多行文本框 + $formbuider = array_merge($formbuider, $this->createTextareaForm($data)); + break; + case 'upload'://文件上传 + $formbuider = array_merge($formbuider, $this->createUploadForm((int)$data['upload_type'], $data)); + break; + case 'checkbox'://多选框 + $formbuider = array_merge($formbuider, $this->createCheckboxForm($data)); + break; + case 'select'://多选框 + $formbuider = array_merge($formbuider, $this->createSelectForm($data)); + break; + } + } + return $formbuider; + } + + /** + * 有组件绑定规则 + * + * @param array $list + * @param array $relatedRule + * + * @return array|bool + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function createBindCrontrolForm(array $list, array $relatedRule) + { + if (!$list || !$relatedRule) return false; + $formbuider = []; + $new_data = array(); + foreach ($list as $dk => $dv) { + $new_data[$dv['menu_name']] = $dv; + } + foreach ($relatedRule as $rk => $rv) { + if (isset($rv['son_type'])) { + $data = $new_data[$rk]; + switch ($data['type']) { + case 'text'://文本框 + $formbuider = array_merge($formbuider, $this->createTextForm($data['input_type'], $data)); + break; + case 'radio'://单选框 + $son_builder = array(); + foreach ($rv['son_type'] as $sk => $sv) { + if (isset($sv['son_type'])) { + foreach ($sv['son_type'] as $ssk => $ssv) { + $son_data = $new_data[$sk]; + $son_data['show_value'] = $sv['show_value']; + $son_builder[] = $this->formTypeShine($son_data, $this->formTypeShine($new_data[$ssk])[0])[0]; + } + } else { + $son_data = $new_data[$sk]; + $son_data['show_value'] = $rv['show_value']; + $son_builder[] = $this->formTypeShine($son_data)[0]; + } + + } + $formbuider = array_merge($formbuider, $this->createRadioForm($data, $son_builder)); + break; + case 'textarea'://多行文本框 + $formbuider = array_merge($formbuider, $this->createTextareaForm($data)); + break; + case 'upload'://文件上传 + $formbuider = array_merge($formbuider, $this->createUploadForm((int)$data['upload_type'], $data)); + break; + case 'checkbox'://多选框 + $formbuider = array_merge($formbuider, $this->createCheckboxForm($data)); + break; + case 'select'://多选框 + $formbuider = array_merge($formbuider, $this->createSelectForm($data)); + break; + } + } + } + return $formbuider; + } + + /** + * 系统配置form表单创建 + * + * @param $url + * @param int $tabId + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ +// public function getConfigForm($url, int $tabId) +// { +// /** @var SystemConfigTabServices $service */ +// $service = app()->make(SystemConfigTabServices::class); +// $title = $service->value(['id' => $tabId], 'title'); +// $list = $this->dao->getConfigTabAllList($tabId); +// $formbuider = $this->createForm($list); +// $name = 'setting'; +// if ($url) { +// $name = explode('/', $url)[2] ?? $name; +// } +// $postUrl = $this->postUrl[$name]['url'] ?? '/setting/config/save_basics'; +// return create_form($title, $formbuider, $this->url($postUrl), 'POST'); +// } + + /** + * 新增路由增加设置项验证 + * + * @param $url + * @param $post + * + * @return bool + */ + public function checkParam($url, $post) + { + $name = ''; + if ($url) { + $name = explode('/', $url)[2] ?? $name; + } + $auth = $this->postUrl[$name]['auth'] ?? false; + if ($auth === false) { + throw new AdminException(400601); + } + if ($auth) { + /** @var SystemConfigTabServices $systemConfigTabServices */ + $systemConfigTabServices = app()->make(SystemConfigTabServices::class); + foreach ($post as $key => $value) { + $tab_ids = $systemConfigTabServices->getColumn([['eng_title', 'IN', $auth]], 'id'); + if (!$tab_ids || !in_array($key, $this->dao->getColumn([['config_tab_id', 'IN', $tab_ids]], 'menu_name'))) { + throw new AdminException(400602); + } + } + } + return true; + } + + /** + * 修改配置获取form表单 + * + * @param int $id + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function editConfigForm(int $id) + { + $menu = $this->dao->get($id)->getData(); + if (!$menu) { + throw new AdminException(100026); + } + /** @var SystemConfigTabServices $service */ + $service = app()->make(SystemConfigTabServices::class); + $formbuider = []; + $formbuider[] = $this->builder->input('menu_name', '字段变量', $menu['menu_name'])->disabled(1); + $formbuider[] = $this->builder->hidden('type', $menu['type']); + $formbuider[] = $this->builder->select('config_tab_id', '分类', (int)$menu['config_tab_id'])->setOptions($service->getSelectForm()); + $formbuider[] = $this->builder->input('info', '配置名称', $menu['info'])->autofocus(1); + $formbuider[] = $this->builder->input('desc', '配置简介', $menu['desc']); + switch ($menu['type']) { + case 'text': + $menu['value'] = json_decode($menu['value'], true); + $formbuider[] = $this->builder->select('input_type', '类型', $menu['input_type'])->setOptions([ + ['value' => 'input', 'label' => '文本框'] + , ['value' => 'dateTime', 'label' => '时间'] + , ['value' => 'color', 'label' => '颜色'] + , ['value' => 'number', 'label' => '数字'], + ]); + //输入框验证规则 + $formbuider[] = $this->builder->input('value', '默认值', $menu['value']); + if (!empty($menu['required'])) { + $formbuider[] = $this->builder->number('width', '文本框宽(%)', (int)$menu['width']); + $formbuider[] = $this->builder->input('required', '验证规则', $menu['required'])->placeholder('多个请用,隔开例如:required:true,url:true'); + } + break; + case 'textarea': + $menu['value'] = json_decode($menu['value'], true); + //多行文本 + if (!empty($menu['high'])) { + $formbuider[] = $this->builder->textarea('value', '默认值', $menu['value'])->rows(5); + $formbuider[] = $this->builder->number('width', '文本框宽(%)', (int)$menu['width']); + $formbuider[] = $this->builder->number('high', '多行文本框高(%)', (int)$menu['high']); + } else { + $formbuider[] = $this->builder->input('value', '默认值', $menu['value']); + } + break; + case 'radio': + $formbuider = array_merge($formbuider, $this->createRadioForm($menu)); + //单选和多选参数配置 + if (!empty($menu['parameter'])) { + $formbuider[] = $this->builder->textarea('parameter', '配置参数', $menu['parameter'])->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色"); + } + break; + case 'checkbox': + $formbuider = array_merge($formbuider, $this->createCheckboxForm($menu)); + //单选和多选参数配置 + if (!empty($menu['parameter'])) { + $formbuider[] = $this->builder->textarea('parameter', '配置参数', $menu['parameter'])->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色"); + } + break; + case 'upload': + $formbuider = array_merge($formbuider, $this->createUploadForm(($menu['upload_type']), $menu)); + //上传类型选择 + if (!empty($menu['upload_type'])) { + $formbuider[] = $this->builder->radio('upload_type', '上传类型', $menu['upload_type'])->options([['value' => 1, 'label' => '单图'], ['value' => 2, 'label' => '多图'], ['value' => 3, 'label' => '文件']]); + } + break; + } + $formbuider[] = $this->builder->number('sort', '排序', (int)$menu['sort']); + $formbuider[] = $this->builder->radio('status', '状态', $menu['status'])->options([['value' => 1, 'label' => '显示'], ['value' => 0, 'label' => '隐藏']]); + return create_form('编辑字段', $formbuider, $this->url('/setting/config/' . $id), 'PUT'); + } + + /** + * 字段状态 + * + * @return array + */ + public function formStatus(): array + { + return [['value' => 1, 'label' => '显示'], ['value' => 0, 'label' => '隐藏']]; + } + + /** + * 选择文文件类型 + * + * @return array + */ + public function uploadType(): array + { + return [ + ['value' => 1, 'label' => '单图'] + , ['value' => 2, 'label' => '多图'] + , ['value' => 3, 'label' => '文件'], + ]; + } + + /** + * 选择文本框类型 + * + * @return array + */ + public function textType(): array + { + return [ + ['value' => 'input', 'label' => '文本框'] + , ['value' => 'dateTime', 'label' => '时间'] + , ['value' => 'color', 'label' => '颜色'] + , ['value' => 'number', 'label' => '数字'], + ]; + } + + /** + * 获取创建配置规格表单 + * + * @param int $type + * @param int $tab_id + * + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function createFormRule(int $type, int $tab_id): array + { + /** @var SystemConfigTabServices $service */ + $service = app()->make(SystemConfigTabServices::class); + $formbuider = []; + $form_type = ''; + $info_type = []; + $parameter = []; + switch ($type) { + case 0://文本框 + $form_type = 'text'; + $info_type = $this->builder->select('input_type', '类型')->setOptions($this->textType()); + $parameter[] = $this->builder->input('value', '默认值'); + $parameter[] = $this->builder->number('width', '文本框宽(%)', 100); + $parameter[] = $this->builder->input('required', '验证规则')->placeholder('多个请用,隔开例如:required:true,url:true'); + break; + case 1://多行文本框 + $form_type = 'textarea'; + $parameter[] = $this->builder->textarea('value', '默认值'); + $parameter[] = $this->builder->number('width', '文本框宽(%)', 100); + $parameter[] = $this->builder->number('high', '多行文本框高(%)', 5); + break; + case 2://单选框 + $form_type = 'radio'; + $parameter[] = $this->builder->textarea('parameter', '配置参数')->placeholder("参数方式例如:\n1=>男\n2=>女\n3=>保密"); + $parameter[] = $this->builder->input('value', '默认值'); + break; + case 3://文件上传 + $form_type = 'upload'; + $parameter[] = $this->builder->radio('upload_type', '上传类型', 1)->options($this->uploadType()); + break; + case 4://多选框 + $form_type = 'checkbox'; + $parameter[] = $this->builder->textarea('parameter', '配置参数')->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色"); + break; + case 5://下拉框 + $form_type = 'select'; + $parameter[] = $this->builder->textarea('parameter', '配置参数')->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色"); + break; + } + if ($form_type) { + $formbuider[] = $this->builder->hidden('type', $form_type); + $formbuider[] = $this->builder->select('config_tab_id', '分类', $tab_id)->setOptions($service->getSelectForm()); + if ($info_type) { + $formbuider[] = $info_type; + } + $formbuider[] = $this->builder->input('info', '配置名称')->autofocus(1); + $formbuider[] = $this->builder->input('menu_name', '字段变量')->placeholder('例如:site_url'); + $formbuider[] = $this->builder->input('desc', '配置简介'); + $formbuider = array_merge($formbuider, $parameter); + $formbuider[] = $this->builder->number('sort', '排序', 0); + $formbuider[] = $this->builder->radio('status', '状态', 1)->options($this->formStatus()); + } + return create_form('添加字段', $formbuider, $this->url('/setting/config'), 'POST'); + } + + /** + * radio 和 checkbox规则的判断 + * + * @param $data + * + * @return bool + */ + public function valiDateRadioAndCheckbox($data) + { + $option = []; + $option_new = []; + $data['parameter'] = str_replace("\r\n", "\n", $data['parameter']);//防止不兼容 + $parameter = explode("\n", $data['parameter']); + if (count($parameter) < 2) { + throw new AdminException(400603); + } + foreach ($parameter as $k => $v) { + if (isset($v) && !empty($v)) { + $option[$k] = explode('=>', $v); + } + } + if (count($option) < 2) { + throw new AdminException(400603); + } + $bool = 1; + foreach ($option as $k => $v) { + $option_new[$k] = $option[$k][0]; + foreach ($v as $kk => $vv) { + $vv_num = strlen($vv); + if (!$vv_num) { + $bool = 0; + } + } + } + if (!$bool) { + throw new AdminException(400603); + } + $num1 = count($option_new);//提取该数组的数目 + $arr2 = array_unique($option_new);//合并相同的元素 + $num2 = count($arr2);//提取合并后数组个数 + if ($num1 > $num2) { + throw new AdminException(400603); + } + return true; + } + + /** + * 验证参数 + * + * @param $data + * + * @return bool + */ + public function valiDateValue($data) + { + if (!$data || !isset($data['required']) || !$data['required']) { + return true; + } + $valids = explode(',', $data['required']); + foreach ($valids as $valid) { + $valid = explode(':', $valid); + if (isset($valid[0]) && isset($valid[1])) { + $k = strtolower(trim($valid[0])); + $v = strtolower(trim($valid[1])); + switch ($k) { + case 'required': + if ($v == 'true' && $data['value'] === '') { + throw new AdminException(400604, ['name' => $data['info'] ?? '']); + } + break; + case 'url': + if ($v == 'true' && !check_link($data['value'])) { + throw new AdminException(400605, ['name' => $data['info'] ?? '']); + } + break; + } + } + } + } + + /** + * 保存平台电子面单打印信息 + * + * @param array $data + * + * @return bool + */ + public function saveExpressInfo(array $data) + { + if (!is_array($data) || !$data) return false; + // config_export_id 快递公司id + // config_export_temp_id 快递公司模板id + // config_export_com 快递公司编码 + // config_export_to_name 发货人姓名 + // config_export_to_tel 发货人电话 + // config_export_to_address 发货人详细地址 + // config_export_siid 电子面单打印机编号 + foreach ($data as $key => $value) { + $this->dao->update(['menu_name' => 'config_export_' . $key], ['value' => json_encode($value)]); + } + $this->cacheDriver()->clear(); + return true; + } + + /** + * 获取分享海报 兼容方法 + */ + public function getSpreadBanner() + { + //配置 + $banner = sys_config('spread_banner', []); + if (!$banner) { + //组合数据 + $banner = sys_data('routine_spread_banner'); + if ($banner) { + $banner = array_column($banner, 'pic'); + $this->dao->update(['menu_name' => 'spread_banner'], ['value' => json_encode($banner)]); + $this->cacheDriver()->clear(); + } + } + return $banner; + } + + /** + * 保存wss配置 + * + * @param int $wssOpen + * @param string $wssLocalpk + * @param string $wssLocalCert + */ + public function saveSslFilePath(int $wssOpen, string $wssLocalpk, string $wssLocalCert) + { + $wssFile = root_path() . '.wss'; + $content = <<make(SystemConfigTabServices::class); + //上传配置->基础配置 + $tab_id = $systemConfigTabServices->getColumn(['eng_title' => 'base_config'], 'id'); + if ($tab_id) { + $all = $this->dao->getColumn(['config_tab_id' => $tab_id], 'value', 'menu_name'); + if (array_intersect(array_keys($all), array_keys($post))) { + foreach ($post as $key => $item) { + //配置更改删除原来生成的缩略图 + if (isset($all[$key]) && $item != json_decode($all[$key], true)) { + try { + FileService::delDir(public_path('uploads/thumb_water')); + break; + } catch (\Throwable $e) { + + } + } + } + } + } + return true; + } + + /** + * 变更分销绑定关系模式 + * + * @param array $post + * + * @return bool + */ + public function checkBrokerageBinding(array $post) + { + try { + $config_data = $post['store_brokerage_binding_status']; + $config_one = $this->dao->getOne(['menu_name' => 'store_brokerage_binding_status']); + $config_old = json_decode($config_one['value'], true); + if ($config_old != 2 && $config_data == 2) { + //自动解绑上级绑定 + + /** @var AgentManageServices $agentManage */ + $agentManage = app()->make(AgentManageServices::class); + $agentManage->resetSpreadTime(); + } + } catch (\Throwable $e) { + Log::error('变更分销绑定模式重置绑定时间失败,失败原因:' . $e->getMessage()); + return false; + } + return true; + } +} diff --git a/demo/webman/backend/app/services/system/config/SystemConfigTabServices.php b/demo/webman/backend/app/services/system/config/SystemConfigTabServices.php new file mode 100644 index 0000000000000000000000000000000000000000..6635550bd2bdd19c6e804efe7332ba9a0eb8fbfb --- /dev/null +++ b/demo/webman/backend/app/services/system/config/SystemConfigTabServices.php @@ -0,0 +1,138 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\config; + + +use app\dao\system\config\SystemConfigTabDao; +use app\exception\AdminException; +use app\services\BaseServices; + + +/** + * 系统配置分类 + * Class SystemConfigTabServices + * @package app\services\system\config + * @method save(array $data) 写入数据 + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method delete($id, ?string $key = null) 删除数据 + */ +class SystemConfigTabServices extends BaseServices +{ + /** + * SystemConfigTabServices constructor. + */ + public function __construct() + { + $this->dao = Container::make(SystemConfigTabDao::class); + } + + /** + * 系统设置头部分类读取 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfigTab(int $pid) + { + $list = $this->dao->getConfigTabAll(['status' => 1, 'pid' => $pid], ['id', 'id as value', 'title as label', 'pid', 'icon', 'type'], $pid ? [] : [['type', '=', '0']]); + return get_tree_children($list); + } + + /** + * 获取配置分类列表 + * @param array $where + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfgTabList(array $where) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getConfgTabList($where, $page, $limit); + $count = $this->dao->count($where); + $menusValue = []; + foreach ($list as $item) { + $menusValue[] = $item->getData(); + } + $list = get_tree_children($menusValue); + return compact('list', 'count'); + } + + /** + * 获取配置分类选择下拉树 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getSelectForm() + { + $menuList = $this->dao->getConfigTabAll([], ['id', 'pid', 'title']); + $list = sort_list_tier($menuList, 0, 'pid', 'id'); + $menus = [['value' => 0, 'label' => '顶级按钮']]; + foreach ($list as $menu) { + $menus[] = ['value' => $menu['id'], 'label' => $menu['html'] . $menu['title']]; + } + return $menus; + } + + /** + * 创建form表单 + * @param array $formData + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function createConfigTabForm(array $formData = []) + { + $form[] = Form::select('pid', '父级分类', isset($formData['pid']) ? (string)$formData['pid'] : '')->setOptions($this->getSelectForm())->filterable(true); + $form[] = Form::input('title', '分类名称', $formData['title'] ?? ''); + $form[] = Form::input('eng_title', '分类字段英文', $formData['eng_title'] ?? ''); + $form[] = Form::frameInput('icon', '图标', $this->url(config('app.admin_prefix', 'admin') . '/widget.widgets/icon', ['fodder' => 'icon'], true), $formData['icon'] ?? '')->icon('ios-ionic')->height('560px')->modal(['footer-hide' => true]); + $form[] = Form::radio('type', '类型', $formData['type'] ?? 0)->options([ + ['value' => 0, 'label' => '系统'], + ['value' => 3, 'label' => '其它'] + ]); + $form[] = Form::radio('status', '状态', $formData['status'] ?? 1)->options([['value' => 1, 'label' => '显示'], ['value' => 2, 'label' => '隐藏']]); + $form[] = Form::number('sort', '排序', (int)($formData['sort'] ?? 0))->precision(0); + return $form; + } + + /** + * 添加配置分类表单 + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createForm() + { + return create_form('添加配置分类', $this->createConfigTabForm(), $this->url('/setting/config_class')); + } + + /** + * 修改配置分类表单 + * @param int $id + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function updateForm(int $id) + { + $configTabInfo = $this->dao->get($id); + if (!$configTabInfo) { + throw new AdminException('数据不存在'); + } + return create_form('编辑配置分类', $this->createConfigTabForm($configTabInfo->toArray()), $this->url('/setting/config_class/' . $id), 'PUT'); + } +} diff --git a/demo/webman/backend/app/services/system/config/SystemGroupDataServices.php b/demo/webman/backend/app/services/system/config/SystemGroupDataServices.php new file mode 100644 index 0000000000000000000000000000000000000000..2ef614d37b41ca51360b7dd82574b7e2bd5a4fd7 --- /dev/null +++ b/demo/webman/backend/app/services/system/config/SystemGroupDataServices.php @@ -0,0 +1,390 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\config; + +use app\dao\system\config\SystemGroupDataDao; +use app\services\BaseServices; +use support\Container; + +/** + * 组合数据数据集 + * Class SystemGroupDataServices + * @package app\services\system\config + * @method delete($id, ?string $key = null) 删除数据 + * @method get(int $id, ?array $field = []) 获取一条数据 + * @method save(array $data) 保存数据 + * @method update($id, array $data, ?string $key = null) 修改数据 + */ +class SystemGroupDataServices extends BaseServices +{ + /** + * SystemGroupDataServices constructor. + */ + public function __construct() + { + $this->dao = Container::make(SystemGroupDataDao::class); + } + + /** + * 获取某个配置下的数据从新组合成新得数据返回 + * @param string $configName + * @param int $limit + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getConfigNameValue(string $configName, int $limit = 0): array + { + /** @var SystemGroupServices $systemGroupServices */ + $systemGroupServices = Container::make(SystemGroupServices::class); + $value = $this->dao->getGroupDate((int)$systemGroupServices->getConfigNameId($configName), $limit); + $data = []; + foreach ($value as $key => $item) { + $data[$key]["id"] = $item["id"]; + if (isset($item['status'])) $data[$key]["status"] = $item["status"]; + $fields = json_decode($item["value"], true) ?: []; + foreach ($fields as $index => $field) { + if ($field['type'] == 'upload') { + $data[$key][$index] = set_file_url($field['value']); + } else { + $data[$key][$index] = $field["value"]; + } + } + } + return $data; + } + + /** + * 获取组合数据列表 + * @param array $where + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGroupDataList(array $where) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getGroupDataList($where, $page, $limit); + $count = $this->dao->count($where); + $type = ''; + $gid = (int)$where['gid']; + /** @var SystemGroupServices $services */ + $services = app()->make(SystemGroupServices::class); + $group = $services->getOne(['id' => $gid], 'id,config_name,fields'); + + $header = json_decode($group['fields'], true) ?? []; + $title = []; + $param = []; + foreach ($header as $item) { + if ($group['config_name'] == 'order_details_images' && $item['title'] == 'order_status') { + $status = str_replace("\r\n", "\n", $item["param"]);//防止不兼容 + $status = explode("\n", $status); + if (is_array($status) && !empty($status)) { + foreach ($status as $index => $v) { + $vl = explode('=>', $v); + if (isset($vl[0]) && isset($vl[1])) { + $param[$vl[0]] = $vl[1]; + } + } + } + } + if ($item['type'] == 'upload' || $item['type'] == 'uploads') { + $title[$item['title']] = []; + $type = $item['title']; + } else { + $title[$item['title']] = ''; + } + } + foreach ($list as $key => $value) { + $list[$key] = array_merge($value, $title); + $infos = json_decode($value['value'], true) ?: []; + foreach ($infos as $index => $info) { + if ($group['config_name'] == 'order_details_images' && $index == 'order_status') { + $list[$key][$index] = ($param[$info['value']] ?? '') . '/' . $info['value']; + } else { + if ($info['type'] == 'upload') { + $list[$key][$index] = [set_file_url($info['value'])]; + } elseif ($info['type'] == 'checkbox') { + $list[$key][$index] = implode(",", $info["value"]); + } else { + $list[$key][$index] = $info['value']; + } + } + } + unset($list[$key]['value']); + } + return compact('list', 'count', 'type'); + } + + /** + * 根据gid判断出是否能再次添加组合数据 + * @param int $gid + * @param int $count + * @param string $key + * @return bool + */ + public function isGroupGidSave(int $gid, int $count, string $key): bool + { + /** @var SystemGroupServices $services */ + $services = app()->make(SystemGroupServices::class); + $configName = $services->value(['id' => $gid], 'config_name'); + if ($configName == $key) { + return $this->dao->count(['gid' => $gid]) >= $count; + } else { + return false; + } + } + + /** + * 创建表单 + * @param int $gid + * @param array $groupData + * @return mixed + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createGroupForm(int $gid, array $groupData = []) + { + $groupDataValue = isset($groupData["value"]) ? json_decode($groupData["value"], true) : []; + /** @var SystemGroupServices $services */ + $services = app()->make(SystemGroupServices::class); + $fields = $services->getValueFields($gid); + $f[] = Form::hidden('gid', $gid); + foreach ($fields as $key => $value) { + $info = []; + if (isset($value["param"])) { + $value["param"] = str_replace("\r\n", "\n", $value["param"]);//防止不兼容 + $params = explode("\n", $value["param"]); + if (is_array($params) && !empty($params)) { + foreach ($params as $index => $v) { + $vl = explode('=>', $v); + if (isset($vl[0]) && isset($vl[1])) { + $info[$index]["value"] = $vl[0]; + $info[$index]["label"] = $vl[1]; + } + } + } + } + $fvalue = $groupDataValue[$value['title']]['value'] ?? ''; + switch ($value["type"]) { + case 'input': + if ($gid == 55 && $value['title'] == 'sign_num') { + $f[] = Form::number($value["title"], $value["name"], (int)$fvalue)->precision(0); + } else { + $f[] = Form::input($value["title"], $value["name"], $fvalue); + } + break; + case 'textarea': + $f[] = Form::input($value["title"], $value["name"], $fvalue)->type('textarea')->placeholder($value['param']); + break; + case 'radio': + $f[] = Form::radio($value["title"], $value["name"], $fvalue ?: (int)$info[0]["value"] ?? '')->options($info); + break; + case 'checkbox': + $f[] = Form::checkbox($value["title"], $value["name"], $fvalue ?: $info[0] ?? '')->options($info); + break; + case 'select': + $f[] = Form::select($value["title"], $value["name"], $fvalue !== '' ? $fvalue : $info[0] ?? '')->options($info)->multiple(false); + break; + case 'upload': + if (!empty($fvalue)) { + $image = is_string($fvalue) ? $fvalue : $fvalue[0]; + } else { + $image = ''; + } + $f[] = Form::frameImage($value["title"], $value["name"], $this->url(config('app.admin_prefix', 'admin') . '/widget.images/index', ['fodder' => $value["title"], 'big' => 1], true), $image)->icon('ios-image')->width('950px')->height('560px')->modal(['footer-hide' => true]); + break; + case 'uploads': + if ($fvalue) { + if (is_string($fvalue)) $fvalue = [$fvalue]; + $images = !empty($fvalue) ? $fvalue : []; + } else { + $images = []; + } + $f[] = Form::frameImages($value["title"], $value["name"], $this->url(config('app.admin_prefix', 'admin') . '/widget.images/index', ['fodder' => $value["title"], 'big' => 1, 'type' => 'many', 'maxLength' => 5], true), $images)->maxLength(5)->icon('ios-images')->width('950px')->height('560px')->modal(['footer-hide' => true])->spin(0); + break; + default: + $f[] = Form::input($value["title"], $value["name"], $fvalue); + break; + + } + } + $f[] = Form::number('sort', '排序', (int)($groupData["sort"] ?? 1))->precision(0); + $f[] = Form::radio('status', '状态', (int)($groupData["status"] ?? 1))->options([['value' => 1, 'label' => '显示'], ['value' => 0, 'label' => '隐藏']]); + return $f; + } + + /** + * 获取添加组合数据表单 + * @param int $gid + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function createForm(int $gid) + { + return create_form('添加数据', $this->createGroupForm($gid), $this->url('/setting/group_data')); + } + + /** + * 获取修改组合数据表单 + * @param int $gid + * @param int $id + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function updateForm(int $gid, int $id) + { + $groupData = $this->dao->get($id); + if (!$groupData) { + throw new AdminException(100026); + } + return create_form('编辑数据', $this->createGroupForm($gid, $groupData->toArray()), $this->url('/setting/group_data/' . $id), 'PUT'); + } + + /** + * 根据id获取当前记录中的数据 + * @param $id + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function getDateValue($id) + { + $value = $this->dao->get($id); + $data["id"] = $value["id"]; + $data["status"] = $value["status"]; + $fields = json_decode($value["value"], true); + foreach ($fields as $index => $field) { + $data[$index] = $field["value"]; + } + return $data; + } + + /** + * 根据id获取数据 + * @param array $ids + * @param string $field + */ + public function getGroupDataColumn(array $ids) + { + $systemGroup = []; + if (!empty($ids)) { + $systemGroupData = $this->dao->idByGroupList($ids); + if (!empty($systemGroupData)) + $systemGroup = array_combine(array_column($systemGroupData, 'id'), $systemGroupData); + } + return $systemGroup; + } + + /** + * 根据gid删除数据 + * @param int $gid + * @return mixed + */ + public function delGroupDate(int $gid) + { + return $this->dao->delGroupDate($gid); + } + + /** + * 批量保存 + * @param array $params + * @param string $config_name + * @return bool + * @throws \Exception + */ + public function saveAllData(array $params, string $config_name) + { + /** @var SystemGroupServices $systemGroupServices */ + $systemGroupServices = app()->make(SystemGroupServices::class); + $gid = $systemGroupServices->value(['config_name' => $config_name], 'id'); + if (!$gid) throw new AdminException(100026); + $group = $systemGroupServices->getOne(['id' => $gid], 'id,config_name,fields'); + $fields = json_decode($group['fields'], true) ?? []; + $this->transaction(function () use ($gid, $params, $fields) { + $this->delGroupDate($gid); + $data = []; + $sort = count($params); + foreach ($params as $k => $v) { + $value = []; + foreach ($v as $key => $param) { + foreach ($fields as $index => $field) { + if ($key == $field["title"]) { + if ($param == "") { + throw new AdminException(400607, ['name' => $field["name"]]); + } else { + $value[$key]["type"] = $field["type"]; + $value[$key]["value"] = $param; + } + } + } + } + $data[$k] = [ + "gid" => $gid, + "add_time" => time(), + "value" => json_encode($value), + "sort" => $sort, + "status" => $v["status"] ?? 1 + ]; + $sort--; + } + $this->dao->saveAll($data); + }); + \crmeb\services\CacheService::clear(); + return true; + } + + /** + * 检查秒杀时间段 + * @param SystemGroupServices $services + * @param $gid + * @param $params + * @param int $id + * @return mixed + */ + public function checkSeckillTime(SystemGroupServices $services, $gid, $params, $id = 0) + { + $name = $services->value(['id' => $gid], 'config_name'); + if ($name == 'routine_seckill_time') { + if ($params['time'] == '') { + throw new AdminException(400190); + } + if (!$params['continued']) { + throw new AdminException(400191); + } + if (!preg_match('/^(\d|1\d|2[0-3])$/', $params['time'])) { + throw new AdminException(400192); + } + if (!preg_match('/^([1-9]|1\d|2[0-4])$/', $params['continued'])) { + throw new AdminException(400193); + } + if (($params['time'] + $params['continued']) > 24) throw new AdminException(400194); + $list = $this->dao->getColumn(['gid' => $gid], 'value', 'id'); + if ($id) unset($list[$id]); + $times = $time = []; + foreach ($list as $item) { + $info = json_decode($item, true); + for ($i = 0; $i < $info['continued']['value']; $i++) { + $times[] = $info['time']['value'] + $i; + } + } + for ($i = 0; $i < $params['continued']; $i++) { + $time[] = $params['time'] + $i; + } + foreach ($time as $v) { + if (in_array($v, $times)) throw new AdminException(400195); + } + } + } +} diff --git a/demo/webman/backend/app/services/system/config/SystemGroupServices.php b/demo/webman/backend/app/services/system/config/SystemGroupServices.php new file mode 100644 index 0000000000000000000000000000000000000000..6e1c9227aca0ee788a019e877999a1087a9bca7e --- /dev/null +++ b/demo/webman/backend/app/services/system/config/SystemGroupServices.php @@ -0,0 +1,101 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\config; + +use app\dao\system\config\SystemGroupDao; +use app\services\BaseServices; +use support\Container; + +/** + * 组合数据 + * Class SystemGroupServices + * @package app\services\system\config + * @method getConfigNameId(string $configName) 获取配置id + * @method save(array $data) 新增数据 + * @method get(int $id, ?array $field = []) 获取一条数据 + * @method count(array $where = []): int 根据条件获取条数 + * @method update($id, array $data, ?string $key = null) 修改数据 + * @method delete($id, ?string $key = null) 删除数据 + * @method value(array $where, ?string $field = '') 获取某个值 + */ +class SystemGroupServices extends BaseServices +{ + + /** + * SystemGroupServices constructor. + */ + public function __construct() + { + $this->dao = Container::make(SystemGroupDao::class); + } + + /** + * 获取组合数据列表 + * + * @param array $where + * @param array $field + * + * @return array + */ + public function getGroupList(array $where, array $field = ['*']) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getGroupList($where, $field, $page, $limit); + $count = $this->dao->count($where); + foreach ($list as $key => $value) { + if (isset($value['fields'])) { + $list[$key]['typelist'] = $value['fields']; + unset($list[$key]['fields']); + } + } + return compact('list', 'count'); + } + + /** + * 获取组合数据tab下的header头部 + * @param int $id + * @return array + */ + public function getGroupDataTabHeader(int $id): array + { + $data = $this->getValueFields($id); + $header = []; + foreach ($data as $key => $item) { + if ($item['type'] == 'upload' || $item['type'] == 'uploads') { + $header[$key]['key'] = $item['title']; + $header[$key]['minWidth'] = 60; + $header[$key]['type'] = 'img'; + } elseif ($item['title'] == 'url' || $item['title'] == 'wap_url' || $item['title'] == 'link' || $item['title'] == 'wap_link') { + $header[$key]['key'] = $item['title']; + $header[$key]['minWidth'] = 200; + } else { + $header[$key]['key'] = $item['title']; + $header[$key]['minWidth'] = 100; + } + $header[$key]['title'] = $item['name']; + } + array_unshift($header, ['key' => 'id', 'title' => '编号', 'minWidth' => 35]); + array_push($header, ['slot' => 'status', 'title' => '是否可用', 'minWidth' => 80], ['key' => 'sort', 'title' => '排序', 'minWidth' => 80], ['slot' => 'action', 'fixed' => 'right', 'title' => '操作', 'minWidth' => 120]); + return compact('header'); + } + + /** + * 获取组合数据fields字段 + * @param int $id + * @return array|mixed + */ + public function getValueFields(int $id) + { + return json_decode($this->dao->value(['id' => $id], 'fields'), true) ?: []; + } + +} diff --git a/demo/webman/backend/app/services/system/config/SystemStorageServices.php b/demo/webman/backend/app/services/system/config/SystemStorageServices.php new file mode 100644 index 0000000000000000000000000000000000000000..68d824fb50e2b462ad9a44a32e993b395efbf7b2 --- /dev/null +++ b/demo/webman/backend/app/services/system/config/SystemStorageServices.php @@ -0,0 +1,569 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\config; + + +use app\dao\system\config\SystemStorageDao; +use app\services\BaseServices; +use support\Container; + +/** + * Class SystemStorageServices + * + * @author Mr.April + * @since 1.0 + */ +class SystemStorageServices extends BaseServices +{ + + /** + * SystemStorageServices constructor. + */ + public function __construct() + { + $this->dao = Container::make(SystemStorageDao::class); + } + + /** + * @param array $where + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $where) + { + [$page, $limit] = $this->getPageValue(); + $config = $this->getStorageConfig((int)$where['type']); + $where['access_key'] = $config['accessKey']; + $list = $this->dao->getList($where, ['*'], $page, $limit, 'add_time'); + foreach ($list as &$item) { + $item['cname'] = str_replace('https://', '', $item['domain']); + $item['_add_time'] = date('Y-m-d H:i:s', $item['add_time']); + $item['_update_time'] = date('Y-m-d H:i:s', $item['update_time']); + $service = UploadService::init($item['type']); + $region = $service->getRegion(); + foreach ($region as $value) { + if (strstr($item['region'], $value['value'])) { + $item['_region'] = $value['label']; + } + } + } + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * @param int $type + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function getFormStorage(int $type) + { + $upload = UploadService::init($type); + + $config = $this->getStorageConfig($type); + $ruleConfig = []; + if (!$config['accessKey']) { + $ruleConfig = [ + FormBuilder::input('accessKey', 'AccessKeyId:', $config['accessKey'] ?? '')->required(), + FormBuilder::input('secretKey', 'AccessKeySecret::', $config['secretKey'] ?? '')->required(), + ]; + } + + if ($type === 4 && isset($config['appid']) && !$config['appid']) { + $ruleConfig[] = FormBuilder::input('appid', 'APPID', $config['appid'] ?? '')->required(); + } + + $rule = [ + FormBuilder::input('name', '空间名称')->required(), + FormBuilder::select('region', '空间区域')->options($upload->getRegion())->required(), + FormBuilder::radio('acl', '读写权限', 'public-read')->options([ + ['label' => '公共读(推荐)', 'value' => 'public-read'], + ['label' => '公共读写', 'value' => 'public-read-write'], + ])->required(), + ]; + + $rule = array_merge($ruleConfig, $rule); + return create_form('添加云空间', $rule, '/system/config/storage/' . $type); + } + + /** + * @param int $type + * @return array + */ + public function getStorageConfig(int $type) + { + $config = [ + 'accessKey' => '', + 'secretKey' => '' + ]; + switch ($type) { + case 2://七牛 + $config = [ + 'accessKey' => sys_config('qiniu_accessKey', ''), + 'secretKey' => sys_config('qiniu_secretKey', ''), + ]; + break; + case 3:// oss 阿里云 + $config = [ + 'accessKey' => sys_config('accessKey', ''), + 'secretKey' => sys_config('secretKey', ''), + ]; + break; + case 4:// cos 腾讯云 + $config = [ + 'accessKey' => sys_config('tengxun_accessKey', ''), + 'secretKey' => sys_config('tengxun_secretKey', ''), + 'appid' => sys_config('tengxun_appid', ''), + ]; + break; + case 5:// cos 京东云 + $config = [ + 'accessKey' => sys_config('jd_accessKey', ''), + 'secretKey' => sys_config('jd_secretKey', ''), + ]; + break; + case 6:// cos 华为云 + $config = [ + 'accessKey' => sys_config('hw_accessKey', ''), + 'secretKey' => sys_config('hw_secretKey', ''), + ]; + break; + case 7:// cos 天翼云 + $config = [ + 'accessKey' => sys_config('ty_accessKey', ''), + 'secretKey' => sys_config('ty_secretKey', ''), + ]; + break; + } + return $config; + } + + /** + * @param int $type + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function getFormStorageConfig(int $type) + { + $config = $this->getStorageConfig($type); + $rule = [ + FormBuilder::hidden('type', $type), + FormBuilder::input('accessKey', 'AccessKeyId:', $config['accessKey'] ?? '')->required(), + FormBuilder::input('secretKey', 'AccessKeySecret:', $config['secretKey'] ?? '')->required(), + ]; + + if ($type === 4) { + $rule[] = FormBuilder::input('appid', 'APPID', $config['appid'] ?? '')->required(); + } + + + return create_form('配置信息', $rule, '/system/config/storage/config'); + } + + /** + * 删除空间 + * @param int $id + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function deleteStorage(int $id) + { + $storageInfo = $this->dao->get(['is_delete' => 0, 'id' => $id]); + if (!$storageInfo) { + throw new AdminException(400608); + } + if ($storageInfo->status) { + throw new AdminException(400609); + } + + try { + $upload = UploadService::init($storageInfo->type); + $res = $upload->deleteBucket($storageInfo->name, $storageInfo->region); + if (false === $res) { + throw new AdminException($upload->getError()); + } + } catch (\Throwable $e) { + throw new AdminException($e->getMessage()); + } + $storageInfo->is_delete = 1; + $storageInfo->save(); + + $this->cacheDriver()->clear(); + + return true; + } + + public function saveConfig(int $type, array $data) + { + //保存配置信息 + if (1 !== $type) { + $accessKey = $secretKey = $appid = ''; + if (isset($data['accessKey']) && isset($data['secretKey']) && $data['accessKey'] && $data['secretKey']) { + $accessKey = $data['accessKey']; + $secretKey = $data['secretKey']; + unset($data['accessKey'], $data['secretKey']); + } + if (isset($data['appid']) && $data['appid']) { + $appid = $data['appid']; + unset($data['appid']); + } + if (!$accessKey || !$secretKey) { + return true; + } + /** @var SystemConfigServices $make */ + $make = app()->make(SystemConfigServices::class); + switch ($type) { + case 2://七牛 + $make->update('qiniu_accessKey', ['value' => json_encode($accessKey)], 'menu_name'); + $make->update('qiniu_secretKey', ['value' => json_encode($secretKey)], 'menu_name'); + break; + case 3:// oss 阿里云 + $make->update('accessKey', ['value' => json_encode($accessKey)], 'menu_name'); + $make->update('secretKey', ['value' => json_encode($secretKey)], 'menu_name'); + break; + case 4:// cos 腾讯云 + $make->update('tengxun_accessKey', ['value' => json_encode($accessKey)], 'menu_name'); + $make->update('tengxun_secretKey', ['value' => json_encode($secretKey)], 'menu_name'); + $make->update('tengxun_appid', ['value' => json_encode($appid)], 'menu_name'); + break; + case 5:// oss 京东云 + $make->update('jd_accessKey', ['value' => json_encode($accessKey)], 'menu_name'); + $make->update('jd_secretKey', ['value' => json_encode($secretKey)], 'menu_name'); + break; + case 6:// oss 华为云 + $make->update('hw_accessKey', ['value' => json_encode($accessKey)], 'menu_name'); + $make->update('hw_secretKey', ['value' => json_encode($secretKey)], 'menu_name'); + break; + case 7:// oss 天翼云 + $make->update('ty_accessKey', ['value' => json_encode($accessKey)], 'menu_name'); + $make->update('ty_secretKey', ['value' => json_encode($secretKey)], 'menu_name'); + break; + } + $make->cacheDriver()->clear(); + } + } + + /** + * 保存云存储 + * @param int $type + * @param array $data + * @return mixed + */ + public function saveStorage(int $type, array $data) + { + //保存配置信息 + $this->saveConfig($type, $data); + if ($this->dao->count(['name' => $data['name']])) { + throw new AdminException(400610); + } + //保存云存储 + $data['type'] = $type; + $upload = UploadService::init($type); + $res = $upload->createBucket($data['name'], $data['region'], $data['acl']); + if (false === $res) { + throw new AdminException($upload->getError()); + } + if (3 === $type) { + $data['region'] = $this->getReagionHost($type, $data['region']); + } + $data['domain'] = $this->getDomain($type, $data['name'], $data['region'], sys_config('tengxun_appid')); + if (2 === $type) { + $domianList = $upload->getDomian($data['name']); + $data['domain'] = $domianList[count($domianList) - 1]; + } else { + $data['cname'] = $data['domain']; + } + $data['add_time'] = time(); + $data['update_time'] = time(); + $config = $this->getStorageConfig($type); + $data['access_key'] = $config['accessKey']; + + $this->cacheDriver()->clear(); + + return $this->dao->save($data); + } + + /** + * 同步云储存桶 + * @param int $type + * @return bool + */ + public function synchronization(int $type) + { + $data = []; + switch ($type) { + case 2://七牛 + $config = $this->getStorageConfig($type); + $upload = UploadService::init($type); + $list = $upload->listbuckets(); + foreach ($list as $item) { + if (!$this->dao->count(['name' => $item['id'], 'access_key' => $config['accessKey']])) { + $data[] = [ + 'type' => $type, + 'access_key' => $config['accessKey'], + 'name' => $item['id'], + 'region' => $item['region'], + 'acl' => $item['private'] == 0 ? 'public-read' : 'private', + 'status' => 0, + 'is_delete' => 0, + 'add_time' => time(), + 'update_time' => time() + ]; + } + } + break; + case 3:// oss 阿里云 + $upload = UploadService::init($type); + $list = $upload->listbuckets(); + $config = $this->getStorageConfig($type); + foreach ($list as $item) { + if (!$this->dao->count(['name' => $item['name'], 'access_key' => $config['accessKey']])) { + $region = $this->getReagionHost($type, $item['location']); + $data[] = [ + 'type' => $type, + 'access_key' => $config['accessKey'], + 'name' => $item['name'], + 'region' => $region, + 'acl' => 'public-read', + 'domain' => $this->getDomain($type, $item['name'], $region), + 'status' => 0, + 'is_delete' => 0, + 'add_time' => strtotime($item['createTime']), + 'update_time' => time() + ]; + } + } + break; + case 4:// cos 腾讯云 + $upload = UploadService::init($type); + $list = $upload->listbuckets(); + if (!empty($list['Name'])) { + $newList = $list; + $list = []; + $list[] = $newList; + } + $config = $this->getStorageConfig($type); + foreach ($list as $item) { + if (!$this->dao->count(['name' => $item['Name'], 'access_key' => $config['accessKey']])) { + $data[] = [ + 'type' => $type, + 'access_key' => $config['accessKey'], + 'name' => $item['Name'], + 'region' => $item['Location'], + 'acl' => 'public-read', + 'status' => 0, + 'domain' => sys_config('tengxun_appid') ? $this->getDomain($type, $item['Name'], $item['Location']) : '', + 'is_delete' => 0, + 'add_time' => strtotime($item['CreationDate']), + 'update_time' => time() + ]; + } + } + break; + case 5:// cos 京东云 + $upload = UploadService::init($type); + $res = $upload->listbuckets(); + $list = $res['Buckets']; + $location = explode('.', $res['@metadata']['effectiveUri'])[1] ?? 'cn-north-1'; + $config = $this->getStorageConfig($type); + foreach ($list as $item) { + if (!$this->dao->count(['name' => $item['Name'], 'access_key' => $config['accessKey']])) { + $data[] = [ + 'type' => $type, + 'access_key' => $config['accessKey'], + 'name' => $item['Name'], + 'region' => $location, + 'acl' => 'public-read', + 'status' => 0, + 'domain' => $this->getDomain($type, $item['Name'], $location), + 'is_delete' => 0, + 'add_time' => time(), + 'update_time' => time() + ]; + } + } + break; + case 6:// cos 华为云 + case 7:// cos 天翼云 + $upload = UploadService::init($type); + $list = $upload->listbuckets(); + if (!empty($list['Name'])) { + $newList = $list; + $list = []; + $list[] = $newList; + } + $config = $this->getStorageConfig($type); + foreach ($list as $item) { + if (!$this->dao->count(['name' => $item['Name'], 'access_key' => $config['accessKey']])) { + $data[] = [ + 'type' => $type, + 'access_key' => $config['accessKey'], + 'name' => $item['Name'], + 'region' => $item['Location'], + 'acl' => 'public-read', + 'status' => 0, + 'domain' => $this->getDomain($type, $item['Name'], $item['Location']), + 'is_delete' => 0, + 'add_time' => strtotime($item['CreationDate']), + 'update_time' => time() + ]; + } + } + break; + } + if ($data) { + $this->dao->saveAll($data); + } + + $this->cacheDriver()->clear(); + + return true; + } + + /** + * @param int $type + * @param string $reagion + * @return mixed|string + */ + public function getReagionHost(int $type, string $reagion) + { + $upload = UploadService::init($type); + $reagionList = $upload->getRegion(); + foreach ($reagionList as $item) { + if (strstr($item['value'], $reagion) !== false) { + return $item['value']; + } + } + return ''; + } + + /** + * 获取域名 + * @param int $type + * @param string $name + * @param string $reagion + * @param string $appid + * @return string + */ + public function getDomain(int $type, string $name, string $reagion, string $appid = '') + { + $domainName = ''; + switch ($type) { + case 3:// oss 阿里云 + $domainName = 'https://' . $name . '.' . $reagion; + break; + case 4:// cos 腾讯云 + $domainName = 'https://' . $name . ($appid ? '-' . $appid : '') . '.cos.' . $reagion . '.myqcloud.com'; + break; + case 5:// cos 京东云 + $domainName = 'https://' . $name . '.s3.' . $reagion . '.jdcloud-oss.com'; + break; + case 6:// cos 华为云 + $domainName = 'https://' . $name . '.obs.' . $reagion . '.myhuaweicloud.com'; + break; + case 7:// cos 天翼云 + $domainName = 'https://' . $name . '.obs.' . $reagion . '.ctyun.cn'; + break; + } + return $domainName; + } + + + /** + * 获取云存储配置 + * @param int $type + * @return array|string[] + */ + public function getConfig(int $type) + { + $res = ['name' => '', 'region' => '', 'domain' => '', 'cdn' => '']; + try { + $config = $this->dao->get(['type' => $type, 'status' => 1, 'is_delete' => 0]); + if ($config) { + return ['name' => $config->name, 'region' => $config->region, 'domain' => $config->domain, 'cdn' => $config->cdn]; + } + } catch (\Throwable $e) { + } + return $res; + + } + + /** + * 获取修改域名表单 + * @param int $id + * @return array + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function getUpdateDomainForm(int $id) + { + $storage = $this->dao->get(['id' => $id], ['domain', 'cdn']); + $rule = [ + FormBuilder::input('domain', '空间域名', $storage['domain']), + FormBuilder::input('cdn', 'cdn域名', $storage['cdn']), + ]; + return create_form('修改空间域名', $rule, '/system/config/storage/domain/' . $id); + } + + /** + * 修改域名并绑定 + * @param int $id + * @param string $domain + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function updateDomain(int $id, string $domain, array $data = []) + { + $info = $this->dao->get($id); + if (!$info) { + throw new AdminException(100026); + } + if ($info->domain != $domain) { + $info->domain = $domain; + $upload = UploadService::init($info->type); + //是否添加过域名不存在需要绑定域名 + $domainList = $upload->getDomian($info->name, $info->region); + $domainParse = parse_url($domain); + if (false === $domainParse) { + throw new AdminException('域名输入有误'); + } + if (!in_array($domainParse['host'], $domainList)) { + //绑定域名到云储存桶 + $res = $upload->bindDomian($info->name, $domain, $info->region); + if (false === $res) { + throw new AdminException($upload->getError()); + } + } + //七牛云需要通过接口获取cname + if (2 === ((int)$info->type)) { + $resDomain = $upload->getDomianInfo($domain); + $info->cname = $resDomain['cname'] ?? ''; + } + $info->save(); + } + if ($info->cdn != $data['cdn']) { + $info->cdn = $data['cdn']; + $info->save(); + } + + $this->cacheDriver()->clear(); + + return true; + } +} diff --git a/demo/webman/backend/app/services/system/crontab/CrontabRunServices.php b/demo/webman/backend/app/services/system/crontab/CrontabRunServices.php new file mode 100644 index 0000000000000000000000000000000000000000..56d972ae689f3c9d65957c5587d234a14d3a0ef0 --- /dev/null +++ b/demo/webman/backend/app/services/system/crontab/CrontabRunServices.php @@ -0,0 +1,232 @@ + '未支付自动取消订单', + 'pinkExpiration' => '拼团到期订单处理', + 'agentUnbind' => '到期自动解绑上级', + 'liveProductStatus' => '自动更新直播商品状态', + 'liveRoomStatus' => '自动更新直播间状态', + 'takeDelivery' => '订单自动收货', + 'advanceOff' => '预售商品到期自动下架', + 'productReplay' => '订单商品自动好评', + 'clearPoster' => '清除昨日海报', + ]; + + /** + * 调用不存在的方法 + * + * @param $name + * @param $arguments + * + * @return mixed|void + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function __call($name, $arguments) + { + $this->crontabLog($name . '方法不存在'); + } + + /** + * 定时任务日志 + * + * @param $msg + */ + protected function crontabLog($msg) + { + $timer_log_open = config("log.timer_log", false); + if ($timer_log_open) { + $date = date('Y-m-d H:i:s', time()); + Log::write($date . $msg, 'crontab'); + } + } + + /** + * 未支付自动取消订单 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function orderCancel() + { + echo '测试定时任务\n'; +// try { +// app()->make(StoreOrderServices::class)->orderUnpaidCancel(); +// $this->crontabLog(' 执行未支付自动取消订单'); +// } catch (\Throwable $e) { +// $this->crontabLog('自动取消订单失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 拼团到期订单处理 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function pinkExpiration() + { + echo '拼团\n'; +// try { +// app()->make(StorePinkServices::class)->statusPink(); +// $this->crontabLog(' 执行拼团到期订单处理'); +// } catch (\Throwable $e) { +// $this->crontabLog('拼团到期订单处理失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 自动解除上级绑定 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function agentUnbind() + { + echo '自动解除上级绑定\n'; +// try { +// app()->make(AgentManageServices::class)->removeSpread(); +// $this->crontabLog(' 执行自动解绑上级绑定'); +// } catch (\Throwable $e) { +// $this->crontabLog('自动解除上级绑定失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 更新直播商品状态 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function liveProductStatus() + { + echo '更新直播\n'; +// try { +// app()->make(LiveGoodsServices::class)->syncGoodStatus(); +// $this->crontabLog(' 执行更新直播商品状态'); +// } catch (\Throwable $e) { +// $this->crontabLog('更新直播商品状态失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 更新直播间状态 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function liveRoomStatus() + { + echo '更新直播状态\n'; +// try { +// app()->make(LiveRoomServices::class)->syncRoomStatus(); +// $this->crontabLog(' 执行更新直播间状态'); +// } catch (\Throwable $e) { +// $this->crontabLog('更新直播间状态失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 自动收货 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function takeDelivery() + { + echo '自动收货\n'; +// try { +// app()->make(StoreOrderTakeServices::class)->autoTakeOrder(); +// $this->crontabLog(' 执行自动收货'); +// } catch (\Throwable $e) { +// $this->crontabLog('自动收货失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 预售到期商品自动下架 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function advanceOff() + { + echo '自动下架\n'; +// try { +// app()->make(StoreProductServices::class)->downAdvance(); +// $this->crontabLog(' 执行预售到期商品自动下架'); +// } catch (\Throwable $e) { +// $this->crontabLog('预售到期商品自动下架失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 自动好评 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function productReplay() + { + echo '自动好评\n'; +// try { +// app()->make(StoreOrderServices::class)->autoComment(); +// $this->crontabLog(' 执行自动好评'); +// } catch (\Throwable $e) { +// $this->crontabLog('自动好评失败,失败原因:' . $e->getMessage()); +// } + } + + /** + * 清除昨日海报 + * + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/01 + */ + public function clearPoster() + { + echo '自动清楚\n'; +// try { +// app()->make(SystemAttachmentServices::class)->emptyYesterdayAttachment(); +// $this->crontabLog(' 执行清除昨日海报'); +// } catch (\Throwable $e) { +// $this->crontabLog('清除昨日海报失败,失败原因:' . $e->getMessage()); +// } + } +} diff --git a/demo/webman/backend/app/services/system/crontab/SystemCrontabServices.php b/demo/webman/backend/app/services/system/crontab/SystemCrontabServices.php new file mode 100644 index 0000000000000000000000000000000000000000..3034a7abcbb09751f48e326806b1cc11789bf498 --- /dev/null +++ b/demo/webman/backend/app/services/system/crontab/SystemCrontabServices.php @@ -0,0 +1,214 @@ +dao = $dao; + } + + /** + * 定时任务列表 + * + * @param array $where + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function getTimerList(array $where = []): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->selectList($where, '*', $page, $limit, 'create_time desc'); + foreach ($list as &$item) { + $item['next_execution_time'] = date('Y-m-d H:i:s', $item['next_execution_time']); + $item['last_execution_time'] = $item['last_execution_time'] != 0 ? date('Y-m-d H:i:s', $item['last_execution_time']) : '暂未执行'; + } + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * 定时任务详情 + * + * @param $id + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getTimerInfo($id) + { + $info = $this->dao->get($id); + if (!$info) throw new AdminException(100026); + return $info->toArray(); + } + + /** + * 定时任务类型 + * + * @return string[] + */ + public function getMarkList(): array + { + return app()->make(CrontabRunServices::class)->markList; + } + + /** + * 保存定时任务 + * + * @param array $data + * + * @return bool + */ + public function saveTimer(array $data = []): bool + { + if (!$data['id'] && $this->dao->getCount(['mark' => $data['mark'], 'delete_time' => null])) { + throw new AdminException('该定时任务已存在,请勿重复添加'); + } + $data['name'] = $this->getMarkList()[$data['mark']]; + $data['create_time'] = time(); + if (!$data['id']) { + unset($data['id']); + $res = $this->dao->save($data); + } else { + $res = $this->dao->update(['id' => $data['id']], $data); + if (!$res) throw new AdminException(100006); + } + return true; + } + + /** + * 删除定时任务 + * + * @param $id + * + * @return bool + */ + public function delTimer($id): bool + { + $res = $this->dao->destroy($id); + if (!$res) throw new AdminException(100008); + return true; + } + + /** + * 设置定时任务状态 + * + * @param $id + * @param $is_open + * + * @return bool + */ + public function setTimerStatus($id, $is_open) + { + $res = $this->dao->update(['id' => $id], ['is_open' => $is_open]); + if (!$res) throw new AdminException(100014); + return true; + } + + /** + * 计算定时任务下次执行时间 + * + * @param $data + * @param int $time + * + * @return false|float|int|mixed + */ + public function getTimerCycleTime($data, $time = 0) + { + if (!$time) $time = time(); + switch ($data['type']) { + case 1: // 每隔几秒 + $cycle_time = $time + $data['second']; + break; + case 2: // 每隔几分 + $cycle_time = $time + ($data['minute'] * 60); + break; + case 3: // 每隔几时 + $cycle_time = $time + ($data['hour'] * 3600) + ($data['minute'] * 60); + break; + case 4: // 每隔几日 + $cycle_time = $time + ($data['day'] * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60); + break; + case 5: // 每日几时几分几秒 + $cycle_time = strtotime(date('Y-m-d ' . $data['hour'] . ':' . $data['minute'] . ':' . $data['second'], time())); + if ($time >= $cycle_time) { + $cycle_time = $cycle_time + 86400; + } + break; + case 6: // 每周周几几时几分几秒 + $todayStart = strtotime(date('Y-m-d 00:00:00', time())); + $w = date("w"); + if ($w > $data['week']) { + $cycle_time = $todayStart + ((7 - $w + $data['week']) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } else if ($w == $data['week']) { + $cycle_time = $todayStart + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + if ($time >= $cycle_time) { + $cycle_time = $cycle_time + (7 * 86400); + } + } else { + $cycle_time = $todayStart + (($data['week'] - $w) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } + break; + case 7: // 每月几日几时几分几秒 + $d = date("d"); + $firstDate = date('Y-m-01', time()); + $maxDay = date('d', strtotime("$firstDate + 1 month -1 day")); + $todayStart = strtotime(date('Y-m-d 00:00:00', time())); + if ($d > $data['day']) { + $cycle_time = $todayStart + (($maxDay - $d + $data['day']) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } elseif ($d == $data['day']) { + $cycle_time = $todayStart + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + if ($time >= $cycle_time) { + $cycle_time = $cycle_time + (($maxDay - $d + $data['day']) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } + } else { + $cycle_time = $todayStart + (($data['day'] - $d) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } + break; + default: + $cycle_time = 0; + break; + } + return $cycle_time; + } + + /** + * 执行任务 + * + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/02/17 + */ + public function crontabRun() + { + $crontabRunServices = app()->make(CrontabRunServices::class); + $time = time(); + file_put_contents(root_path() . 'runtime/.timer', $time); //检测定时任务是否正常 + $list = $this->dao->selectList(['is_open' => 1, 'delete_time' => null])->toArray(); + foreach ($list as $item) { + if ($item['next_execution_time'] < $time) { + //转化小驼峰方法名 + $functionName = Str::camel($item['mark']); + //执行定时任务 + $crontabRunServices->$functionName(); + //写入本次执行时间和下次执行时间 + $this->dao->update(['mark' => $item['mark']], ['last_execution_time' => $time, 'next_execution_time' => $this->getTimerCycleTime($item)]); + } + } + } +} diff --git a/demo/webman/backend/app/services/system/databackup/SystemDatabackupServices.php b/demo/webman/backend/app/services/system/databackup/SystemDatabackupServices.php new file mode 100644 index 0000000000000000000000000000000000000000..71711e409f05fd83897641bbbd6b9b546f6a8d17 --- /dev/null +++ b/demo/webman/backend/app/services/system/databackup/SystemDatabackupServices.php @@ -0,0 +1,125 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\databackup; + + +use app\services\BaseServices; +use phoenix\services\MysqlBackupService; +use think\facade\Db; +use think\facade\Env; + +/** + * 数据库备份 + * Class SystemDatabackupServices + * @package app\services\system + */ +class SystemDatabackupServices extends BaseServices +{ + + /** + * + * @var MysqlBackupService + */ + protected $dbBackup; + + /** + * 构造方法 + * SystemDatabackupServices constructor. + */ + public function __construct() + { + $this->dbBackup = app()->make(MysqlBackupService::class, [[ + //数据库备份卷大小 + 'compress' => 1, + //数据库备份文件是否启用压缩 0不压缩 1 压缩 + 'level' => 5, + ]]); + } + + /** + * 获取数据库列表 + * @return array + */ + public function getDataList(): array + { + $list = $this->dbBackup->dataList(); + $count = count($list); + return compact('list', 'count'); + } + + /** + * 获取表详情 + * + * @param string|null $tablename + * + * @return array + */ + public function getRead(?string $tablename): array + { + $database = Env::get("database.database"); + $list = Db::query("select * from information_schema.columns where table_name = '" . $tablename . "' and table_schema = '" . $database . "'"); + $count = count($list); + foreach ($list as $key => $f) { + $list[$key]['EXTRA'] = ($f['EXTRA'] == 'auto_increment' ? '是' : ' '); + } + return compact('list', 'count'); + } + + /** + * @return MysqlBackupService + */ + public function getDbBackup(): MysqlBackupService + { + return $this->dbBackup; + } + + /** + * 备份表 + * @param string $tables + * @return string + * @throws \think\db\exception\BindParamException + */ + public function backup(string $tables): string + { + $tables = explode(',', $tables); + $data = ''; + ini_set ("memory_limit","-1"); + foreach ($tables as $t) { + $res = $this->dbBackup->backup($t, 0); + if ($res == false && $res != 0) { + $data .= $t . '|'; + } + } + return $data; + } + + /** + * 获取备份列表 + * @return array + */ + public function getBackup(): array + { + $files = $this->dbBackup->fileList(); + $data = []; + foreach ($files as $key => $t) { + $data[$key]['filename'] = $t['filename']; + $data[$key]['part'] = $t['part']; + $data[$key]['size'] = $t['size'] . 'B'; + $data[$key]['compress'] = $t['compress']; + $data[$key]['backtime'] = $key; + $data[$key]['time'] = $t['time']; + } + krsort($data);//根据时间降序 + return ['count' => count($data), 'list' => array_values($data)]; + } + +} diff --git a/demo/webman/backend/app/services/system/dict/SystemDictServices.php b/demo/webman/backend/app/services/system/dict/SystemDictServices.php new file mode 100644 index 0000000000000000000000000000000000000000..a05e160633aabf0307b8328fbb55e23b1210f226 --- /dev/null +++ b/demo/webman/backend/app/services/system/dict/SystemDictServices.php @@ -0,0 +1,162 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\dict; + +use app\dao\system\dict\SystemDictDao; +use app\services\BaseServices; +use phoenix\exceptions\AdminException; + +class SystemDictServices extends BaseServices +{ + + /** + * 构造方法 + * SystemLogServices constructor. + * + * @param \app\dao\system\dict\SystemDictDao $dao + */ + public function __construct(SystemDictDao $dao) + { + $this->dao = $dao; + } + + /** + * 获取字典选项列表 + * + * @param array $where + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getDictList(array $where): array + { + [$page, $limit] = $this->getPageValue(); + $where['name'] = $this->dictNameToOptionName($where['name']); + $list = $this->dao->selectList($where, '*', $page, $limit, 'create_time asc', [], true); + //去除字典前缀 + foreach ($list as $key => $value) { + $position = strpos($value['name'], "dict_") + 5; + $list[$key]['name'] = substr($value['name'], $position); + } + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * 字典保存 + * + * @param string $name + * @param $values + * + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function saveDict(string $name, $values): mixed + { + if (!preg_match('/[a-zA-Z]/', $name)) { + throw new AdminException('字典名只能包含字母'); + } + $option_name = $this->dictNameToOptionName($name); + if ($this->dao->getName($option_name)) { + return app('json')->fail(400188); + } + $format_values = $this->filterValue($values); + $data = [ + 'name' => $option_name, + 'value' => json_encode($format_values), + ]; + return $this->save($data); + } + + /** + * 字典名到option名转换 + * + * @param string $name + * + * @return string + */ + public function dictNameToOptionName(string $name): string + { + return "dict_$name"; + } + + /** + * 过滤值 + * + * @param array $values + * + * @return array + * @throws BusinessException + */ + public function filterValue(array $values): array + { + $format_values = []; + foreach ($values as $item) { + if (!isset($item['value']) || !isset($item['name'])) { + throw new AdminException('字典格式错误'); + } + $format_values[] = ['value' => $item['value'], 'name' => $item['name']]; + } + return $format_values; + } + + /** + * 字典详情 + * + * @param $id + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function read($id): array + { + $data = $this->dao->get($id); + $position = strpos($data->name, "dict_") + 5; + $data->name = substr($data->name, $position); + $data->value = json_decode($data->value, 1); + return $data->getData(); + } + + /** + * 更新字典 + * + * @param $id + * @param $data + * + * @return mixed + */ + public function updateDict($id, $data): mixed + { + if (!preg_match('/[a-zA-Z]/', $data['name'])) { + throw new AdminException('字典名只能包含字母'); + } + $option_name = $this->dictNameToOptionName($data['name']); + $where = [['name', '=', $option_name], ['id', '<>', $id]]; + if ($this->dao->getCount($where)) { + throw new AdminException(400188); + } + + $format_values = $this->filterValue($data['value']); + $upd = [ + 'name' => $option_name, + 'value' => json_encode($format_values), + ]; + return $this->update($id, $upd); + } +} diff --git a/demo/webman/backend/app/services/system/lang/LangCodeServices.php b/demo/webman/backend/app/services/system/lang/LangCodeServices.php new file mode 100644 index 0000000000000000000000000000000000000000..0b5029c4fd50f03bdf0c72c636008c6379537cdb --- /dev/null +++ b/demo/webman/backend/app/services/system/lang/LangCodeServices.php @@ -0,0 +1,223 @@ +dao = $dao; + } + + /** + * 语言列表 + * + * @param array $where + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function langCodeList(array $where = []): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->selectList($where, '*', $page, $limit, 'id desc', [], true)->toArray(); + /** @var LangTypeServices $langTypeServices */ + $langTypeServices = app()->make(LangTypeServices::class); + $typeList = $langTypeServices->getColumn([['status', '=', 1], ['delete_time', '=', null]], 'language_name,file_name,id', 'id'); + $langType = [ + 'isAdmin' => [ + ['title' => '用户端页面', 'value' => 0], + ['title' => '后端接口', 'value' => 1], + ], + ]; + foreach ($typeList as $value) { + $langType['langType'][] = ['title' => $value['language_name'] . '(' . $value['file_name'] . ')', 'value' => $value['id']]; + } + foreach ($list as &$item) { + $item['language_name'] = isset($typeList[$item['type_id']]['language_name']) && $typeList[$item['type_id']]['file_name'] ? $typeList[$item['type_id']]['language_name'] . '(' . $typeList[$item['type_id']]['file_name'] . ')' : ''; + } + $count = $this->dao->count($where); + return compact('list', 'count', 'langType'); + } + + /** + * 语言详情 + * + * @param $code + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function langCodeInfo($code): array + { + if (!$code) throw new AdminException(100026); + /** @var LangTypeServices $langTypeServices */ + $langTypeServices = app()->make(LangTypeServices::class); + $typeList = $langTypeServices->getColumn([['status', '=', 1], ['delete_time', '=', null]], 'language_name,file_name,id', 'id'); + $list = $this->dao->selectList([['code', '=', $code], ['type_id', 'in', array_column($typeList, 'id')]])->toArray(); + foreach ($list as &$item) { + $item['language_name'] = $typeList[$item['type_id']]['language_name'] . '(' . $typeList[$item['type_id']]['file_name'] . ')'; + } + $remarks = $list[0]['remarks']??''; + return compact('list', 'code', 'remarks'); + } + + /** + * 保存修改语言 + * + * @param $data + * + * @return bool + * @throws \Exception + */ + public function langCodeSave($data): bool + { + if ($data['edit'] == 0) { + if ($data['is_admin'] == 1) { + $code = $this->dao->getMax(['is_admin' => 1], 'code'); + if ($code < 500000) { + $code = 500000; + } else { + $code = $code + 1; + } + } else { + $code = $data['remarks']; + } + } else { + $code = $data['code']; + } + $saveData = []; + foreach ($data['list'] as $key => $item) { + $saveData[$key] = [ + 'code' => $code, + 'remarks' => $data['remarks'], + 'lang_explain' => $item['lang_explain'], + 'type_id' => $item['type_id'], + 'is_admin' => $data['is_admin'], + ]; + if (isset($item['id']) && $item['id'] != 0) { + $saveData[$key]['id'] = $item['id']; + } + } + $this->dao->saveAll($saveData); + $this->clearLangCache(); + return true; + } + + /** + * 删除语言 + * + * @param $id + * + * @return bool + */ + public function langCodeDel($id): bool + { + $code = $this->dao->value(['id' => $id], 'code'); + $res = $this->dao->delete(['code' => $code]); + $this->clearLangCache(); + if ($res) return true; + throw new AdminException(100008); + } + + /** + * 清除语言缓存 + * + * @return bool + */ + public function clearLangCache(): bool + { + /** @var LangTypeServices $langTypeServices */ + $langTypeServices = app()->make(LangTypeServices::class); + $typeList = $langTypeServices->getColumn(['status' => 1, 'delete_time' => null], 'file_name'); + foreach ($typeList as $value) { + $langStr = 'api_lang_' . str_replace('-', '_', $value); + CacheService::delete($langStr); + } + $this->cacheDriver()->clear(); + return true; + } + + /** + * 机器翻译 + * + * @param string $text + * + * @return array + * @throws \Throwable + */ + public function langCodeTranslate(string $text = ''): array + { +// if (sys_config('hs_accesskey') == '' || sys_config('hs_secretkey') == '') { +// throw new AdminException('请先配置火山翻译key'); +// } + $translator = Translate::getInstance(); + $translator->setAccessKey('AKLTMzkzZTEzNjg3OTg2NDViM2IwNmFlYzhmNzE4MmI4YmI'); + $translator->setSecretKey("TVRneU16STFOVFV4WVRkbE5ERTJaV0pqWm1aaU1UaGlNVFppWldZeE1HUQ=="); +// $translator->setAccessKey(sys_config('hs_accesskey')); +// $translator->setSecretKey(sys_config('hs_secretkey')); + /** @var LangTypeServices $langTypeServices */ + $langTypeServices = app()->make(LangTypeServices::class); + $typeList = $langTypeServices->getColumn([['status', '=', 1], ['delete_time', '=', null]], 'language_name,file_name,id', 'id'); + $data = []; + foreach ($typeList as $item) { + if ($item['file_name'] == 'zh-Hant') { + $lang = 'zh-Hant'; + } else { + $lang = substr($item['file_name'], 0, 2); + } + $data[$item['id']] = $translator->translateText("", $lang, array($text))[0]['Translation']; + } + return $data; + } + + /** + * 获取多语言缓存 + * + * @return mixed + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/03/06 + */ + public function getLangVersion() + { + return $this->cacheDriver()->remember('lang_version', function () { + return [ + 'version' => uniqid(), + ]; + }); + } + + /** + * @return array + */ + public function langCodeType(): array + { + $langTypeServices = app()->make(LangTypeServices::class); + $typeList = $langTypeServices->getColumn([['status', '=', 1], ['delete_time', '=', null]], 'language_name,file_name,id', 'id'); + $list = [ + 'is_admin' => [ + ['title' => '用户端页面', 'value' => 0], + ['title' => '后端接口', 'value' => 1], + ], + ]; + foreach ($typeList as $value) { + $list['lang_type'][] = ['title' => $value['language_name'] . '(' . $value['file_name'] . ')', 'value' => $value['id']]; + } + + return compact('list'); + } +} diff --git a/demo/webman/backend/app/services/system/lang/LangCountryServices.php b/demo/webman/backend/app/services/system/lang/LangCountryServices.php new file mode 100644 index 0000000000000000000000000000000000000000..547aac40fb67e65975d3300b86ed8900001027ce --- /dev/null +++ b/demo/webman/backend/app/services/system/lang/LangCountryServices.php @@ -0,0 +1,83 @@ +dao = $dao; + } + + /** + * 地区语言列表 + * + * @param array $where + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function LangCountryList(array $where = []): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->selectList($where, '*', $page, $limit, 'id desc', [], true)->toArray(); + /** @var LangTypeServices $langTypeServices */ + $langTypeServices = app()->make(LangTypeServices::class); + $langTypeList = $langTypeServices->getColumn([], 'language_name,file_name,id', 'id'); + foreach ($list as &$item) { + if (isset($langTypeList[$item['type_id']])) { + $item['link_lang'] = $langTypeList[$item['type_id']]['language_name'] . '(' . $langTypeList[$item['type_id']]['file_name'] . ')'; + } else { + $item['link_lang'] = ''; + } + } + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * 保存语言地区 + * + * @param $id + * @param $data + * + * @return bool + */ + public function LangCountrySave($id, $data): bool + { + if ($id) { + $res = $this->dao->update(['id' => $id], $data); + } else { + $res = $this->dao->save($data); + } + if (!$res) throw new AdminException(100007); + $this->cacheDriver()->clear(); + return true; + } + + /** + * 删除语言地区 + * + * @param $id + * + * @return bool + */ + public function langCountryDel($id): bool + { + $res = $this->dao->delete($id); + if (!$res) throw new AdminException(100008); + $this->cacheDriver()->clear(); + return true; + } +} diff --git a/demo/webman/backend/app/services/system/lang/LangTypeServices.php b/demo/webman/backend/app/services/system/lang/LangTypeServices.php new file mode 100644 index 0000000000000000000000000000000000000000..2c61cd6edf7570b5c159c7b97b6dd7d566e37666 --- /dev/null +++ b/demo/webman/backend/app/services/system/lang/LangTypeServices.php @@ -0,0 +1,123 @@ +dao = $dao; + } + + /** + * 获取语言类型列表 + * + * @param array $where + * + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException|\ReflectionException + */ + public function langTypeList(array $where = []): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->selectList($where, '*', $page, $limit, '', [], true); + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * 保存语言类型 + * + * @param array $data + * + * @return bool + */ + public function langTypeSave(array $data): bool + { + if ($data['id']) { + $this->dao->update($data['id'], $data); + $id = $data['id']; + } else { + unset($data['id']); + $res = $this->dao->save($data); + if ($res) { + //同步语言 + /** @var LangCodeServices $codeServices */ + $codeServices = app()->make(LangCodeServices::class); + $list = $codeServices->selectList(['type_id' => 1])->toArray(); + foreach ($list as $key => $item) { + unset($list[$key]['id']); + $list[$key]['type_id'] = $res->id; + } + $codeServices->saveAll($list); + } else { + throw new AdminException(100006); + } + $id = $res->id; + } + //设置默认 + if ($data['is_default'] == 1) $this->dao->update([['id', '<>', $id]], ['is_default' => 0]); + $this->setDefaultLangName(); + return true; + } + + /** + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/2/10 + */ + public function setDefaultLangName() + { + $fileName = $this->dao->value(['is_default' => 1], 'file_name'); + $this->cacheDriver()->set('range_name', $fileName); + app()->make(LangCodeServices::class)->cacheDriver()->clear(); + } + + /** + * 修改语言类型状态 + * + * @param $id + * @param $status + * + * @return bool + */ + public function langTypeStatus($id, $status): bool + { + $res = $this->dao->update(['id' => $id], ['status' => $status]); + if (!$res) throw new AdminException(100015); + $this->setDefaultLangName(); + return true; + } + + /** + * 删除语言类型 + * + * @param string $id + * + * @return bool + */ + public function langTypeDel(string $id='0'): bool + { + $this->dao->update(['id' => $id], ['delete_time' => time()]); + /** @var LangCountryServices $countryServices */ + $countryServices = app()->make(LangCountryServices::class); + $countryServices->update(['type_id' => $id], ['type_id' => 0]); + /** @var LangCodeServices $codeServices */ + $codeServices = app()->make(LangCodeServices::class); + $codeServices->delete(['type_id' => $id]); + $this->setDefaultLangName(); + return true; + } +} diff --git a/demo/webman/backend/app/services/system/log/ClearServices.php b/demo/webman/backend/app/services/system/log/ClearServices.php new file mode 100644 index 0000000000000000000000000000000000000000..b524cefd022b9861ffbab4d004a4b58b143310a6 --- /dev/null +++ b/demo/webman/backend/app/services/system/log/ClearServices.php @@ -0,0 +1,83 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\log; + +use app\services\BaseServices; +use think\facade\Cache; + +/** + * Class ClearServices + * + * @package app\services\system\log + */ +class ClearServices extends BaseServices +{ + /** 递归删除文件 + * + * @param $dirName + */ + protected function delDirAndFile($dirName) + { + $list = glob($dirName . '*'); + foreach ($list as $file) { + if (is_dir($file)) + $this->delDirAndFile($file . DS); + else + @unlink($file); + } + @rmdir($dirName); + } + + /** + * 删除日志 + */ + public function deleteLog() + { + $root = app()->getRootPath() . 'runtime' . DS; + $this->delDirAndFile($root . 'admin' . DS . 'log' . DS); + $this->delDirAndFile($root . 'api' . DS . 'log' . DS); + $this->delDirAndFile($root . 'log' . DS); + } + + /** + * 刷新数据缓存 + */ + public function refresCache() + { + $root = app()->getRootPath() . 'runtime' . DS; + $adminRoute = $root . 'admin'; + $apiRoute = $root . 'api'; + $cacheRoute = $root . 'cache'; + $cache = []; + + if (is_dir($adminRoute)) + $cache[$adminRoute] = scandir($adminRoute); + if (is_dir($apiRoute)) + $cache[$apiRoute] = scandir($apiRoute); + if (is_dir($cacheRoute)) + $cache[$cacheRoute] = scandir($cacheRoute); + + foreach ($cache as $p => $list) { + foreach ($list as $file) { + if (!in_array($file, ['.', '..', 'log', 'schema', 'route.php'])) { + $path = $p . DS . $file; + if (is_file($path)) { + @unlink($path); + } else { + $this->delDirAndFile($path . DS); + } + } + } + } + Cache::clear(); + } +} diff --git a/demo/webman/backend/app/services/system/log/SystemLogServices.php b/demo/webman/backend/app/services/system/log/SystemLogServices.php new file mode 100644 index 0000000000000000000000000000000000000000..393790d74b907e935709dc4c1381e53fcaf20af3 --- /dev/null +++ b/demo/webman/backend/app/services/system/log/SystemLogServices.php @@ -0,0 +1,94 @@ + +// +---------------------------------------------------------------------- + +namespace app\services\system\log; + +use app\dao\system\log\SystemLogDao; +use app\services\BaseServices; +use app\services\system\admin\SystemMenusServices; +use support\Container; + +/** + * 系统日志 + * Class SystemLogServices + * + * @package app\services\system\log + * @method deleteLog() 定期删除日志 + */ +class SystemLogServices extends BaseServices +{ + + /** + * 构造方法 + * SystemLogServices constructor. + */ + public function __construct() + { + $this->dao = Container::make(SystemLogDao::class); + } + + /** + * 记录访问日志 + * + * @param string|int $adminId + * @param string $adminName + * @param string $type + * + * @return bool + */ + public function recordAdminLog(string|int $adminId, string $adminName, string $type): bool + { + $request = request(); + $isPath = strpos($request->path(), $request->app); + $path = $request->path(); + if ($isPath !== false) { + $path = substr($request->path(), $isPath + strlen($request->app) + 1); + $path = ltrim($path, '/'); + } + /** @var SystemMenusServices $service */ + $service = Container::make(SystemMenusServices::class); + $data = [ + 'method' => $request->app, + 'admin_id' => $adminId??'', + 'add_time' => time(), + 'admin_name' => $adminName, + 'path' => $request->path(), + 'page' => $service->getVisitName($path) ?: '未知', + 'ip' => $request->getRemoteIp(), + 'type' => $type, + ]; + if ($this->dao->save($data)) { + return true; + } else { + return false; + } + } + + /** + * 获取系统日志列表 + * + * @param array $where + * @param int $level + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getLogList(array $where, int $level): array + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->getLogList($where, $page, $limit); + $count = $this->dao->count($where); + return compact('list', 'count'); + } +} diff --git a/demo/webman/backend/app/services/system/route/SystemRouteCateServices.php b/demo/webman/backend/app/services/system/route/SystemRouteCateServices.php new file mode 100644 index 0000000000000000000000000000000000000000..5f2ffbcc24f229339bdf5e4cd0d5ef408fff7cb8 --- /dev/null +++ b/demo/webman/backend/app/services/system/route/SystemRouteCateServices.php @@ -0,0 +1,120 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\services\system\route; + + +use app\dao\system\route\SystemRouteCateDao; +use app\services\BaseServices; +use phoenix\services\FormBuilder; + +/** + * Class SystemRouteCateServices + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + * @package app\services\system + */ +class SystemRouteCateServices extends BaseServices +{ + + /** + * SystemRouteCateServices constructor. + * @param SystemRouteCateDao $dao + */ + public function __construct(SystemRouteCateDao $dao) + { + $this->dao = $dao; + } + + public function getPathValue(array $path) + { + $pathAttr = explode('/', $path); + $pathData = []; + foreach ($pathAttr as $item) { + if (!$item) { + $pathData[] = $item; + } + } + return $pathAttr; + } + + /** + * @param array $path + * @param int $id + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function setPathValue(array $path, int $id) + { + return ($path ? '/' . implode('/', $path) : '') . '/' . $id . '/'; + } + + /** + * @param string $appName + * @param string $field + * @param string $order + * + * @return array + * @throws \ReflectionException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function getAllList(string $appName = 'outapi', string $field = '*', string $order = ''): array + { + $list = $this->dao->selectList(['app_name' => $appName], $field, 0, 0, $order)->toArray(); + return get_tree_children($list); + } + + /** + * @param int $id + * @param string $appName + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function getFrom(int $id = 0, string $appName = 'outapi') + { + $url = '/system/route_cate'; + $cateInfo = []; + $path = []; + if ($id) { + $cateInfo = $this->dao->get($id); + $cateInfo = $cateInfo ? $cateInfo->toArray() : []; + $url .= '/' . $id; + $path = explode('/', $cateInfo['path']); + $newPath = []; + foreach ($path as $item) { + if ($item) { + $newPath[] = $item; + } + } + $path = $newPath; + } + $options = $this->dao->selectList(['app_name' => $appName], 'name as label,id as value,id,pid')->toArray(); + $rule = [ +// FormBuilder::cascader('path', '上级分类', $path)->data(get_tree_children($options)), + FormBuilder::input('name', '分类名称', $cateInfo['name'] ?? '')->required(), + FormBuilder::number('sort', '排序', (int)($cateInfo['sort'] ?? 0)), + FormBuilder::hidden('app_name', $appName) + ]; + + return create_form($id ? '修改分类' : '添加分类', $rule, $url, $id ? 'PUT' : 'POST'); + } +} diff --git a/demo/webman/backend/app/services/system/route/SystemRouteServices.php b/demo/webman/backend/app/services/system/route/SystemRouteServices.php new file mode 100644 index 0000000000000000000000000000000000000000..1390941cff211e956727db6bd491df39dcc9d458 --- /dev/null +++ b/demo/webman/backend/app/services/system/route/SystemRouteServices.php @@ -0,0 +1,388 @@ + + * +---------------------------------------------------------------------- + */ + +namespace app\services\system\route; + + +use app\dao\system\route\SystemRouteDao; +use app\services\BaseServices; +use phoenix\services\FormBuilder; +use think\exception\ValidateException; +use think\helper\Str; + +/** + * Class SystemRouteServices + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + * @package app\services\system + */ +class SystemRouteServices extends BaseServices +{ + + /** + * SystemRouteServices constructor. + * @param SystemRouteDao $dao + */ + public function __construct(SystemRouteDao $dao) + { + $this->dao = $dao; + } + + /** + * @param array $where + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function getList(array $where) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->selectList($where, 'name,path,method', $page, $limit)->toArray(); + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * @param int $id + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/10 + */ + public function getInfo(int $id) + { + $routeInfo = $this->dao->get($id); + if (!$routeInfo) { + throw new ValidateException(500036); + } + + $routeInfo = $routeInfo->toArray(); + $routeInfo['cate_tree'] = app()->make(SystemRouteCateServices::class)->getAllList($routeInfo['app_name'], '*', 'id asc,sort desc'); + return $routeInfo; + } + + /** + * 获取tree数据 + * @param string $appName + * @param string $name + * @return mixed + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/05/06 + */ + public function getTreeList(string $appName = 'adminapi', string $name = '') + { +// return $this->cacheDriver()->remember('ROUTE_LIST' . strtoupper($appName), function () use ($name, $appName) { + + $list = app()->make(SystemRouteCateServices::class) + ->selectList(['app_name' => $appName], '*', 0, 0, 'id asc,sort desc', [ + 'children' => function ($query) use ($name, $appName) { + $query->where('app_name', $appName) + ->when('' !== $name, function ($q) use ($name) { + $q->where('name|path', 'LIKE', '%' . $name . '%'); + }); + } + ]) + ->toArray(); + + foreach ($list as $key => $item) { + if (!empty($item['children'])) { + foreach ($item['children'] as $k => $v) { + if (isset($v['cate_id']) && isset($v['method'])) { + if ($v['method'] === 'DELETE') { + $v['method'] = 'DEL'; + } + $v['pid'] = $v['cate_id']; + $list[$key]['children'][$k] = $v; + } + } + } + } + + return get_tree_children($list,'children','id','pid'); +// }, 600); + } + + /** + * @param array $importData + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/26 + */ + public function importData(array $importData) + { + foreach ($importData as $item) { + $id = $this->dao->value(['method' => $item['method'], 'path' => $item['path']], 'id'); + if ($id) { + $this->dao->update($id, [ + 'request' => $item['request'], + 'response' => $item['response'], + 'request_type' => $item['request_type'], + ]); + } + } + return true; + } + + /** + * 获取某个应用下的所有路由权限 + * @param string $app + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function getRouteListAll(string $app = 'adminapi') + { + //获取所有的路由 + $this->app = app(); + $this->app->route->setTestMode(true); + $this->app->route->clear(); + $path = $this->app->getRootPath() . 'app' . DS . $app . DS . 'route' . DS; + $files = is_dir($path) ? scandir($path) : []; + foreach ($files as $file) { + if (strpos($file, '.php')) { + include $path . $file; + } + } + + $route = $this->app->route->getRuleList(); + $action_arr = ['index', 'read', 'create', 'save', 'edit', 'update', 'delete']; + + + foreach ($route as $key => $item) { + $real_name = $item['option']['real_name'] ?? ''; + if (is_array($real_name)) { + foreach ($action_arr as $a) { + if (Str::contains($item['route'], $a)) { + $real_name = $real_name[$a] ?? ''; + } + } + } + $item['option']['real_name'] = $real_name; + $route[$key] = $item; + $except = $item['option']['except'] ?? []; + + $router = is_string($item['route']) ? explode('/', $item['route']) : []; + $action = $router[count($router) - 1] ?? null; + //去除不需要的路由 + if ($except && $action && in_array($action, $except)) { + unset($route[$key]); + } + $only = $item['option']['only'] ?? []; + if ($only && $action && !in_array($action, $only)) { + unset($route[$key]); + } + } + + return $route; + } + + /** + * 获取顶级id + * + * @param string $app + * @param string $cateName + * @param int $pid + * + * @return mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/11 + */ + public function topCateId(string $app, string $cateName, int $pid = 0) + { + $oneId = app()->make(SystemRouteCateServices::class)->value(['app_name' => $app, 'name' => $cateName, 'pid' => 0], 'id'); + if (!$oneId) { + $res = app()->make(SystemRouteCateServices::class)->save([ + 'app_name' => $app, + 'name' => $cateName, + 'pid' => $pid, + 'create_time' => time(), + ]); + return $res->id; + } + return $oneId; + } + + /** + * 同步路由 + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + public function syncRoute(string $app = 'adminapi') + { + //路由列表 + $listAll = $this->getRouteListAll($app); + $list = []; + foreach ($listAll as $item) { + if (!isset($item['option']['mark_name']) || strstr($item['rule'], '') !== false) { + continue; + } else { + $list[$item['option']['mark_name']][] = $item; + } + } + + + $newsList = [];; + foreach ($list as $key => $item) { + $newItem = []; + foreach ($item as $value) { + if (isset($value['option']['cate_name'])) { + $newItem[$value['option']['cate_name']][] = $value; + } else { + $newItem[$key][] = $value; + } + } + $newsList[$key] = $newItem; + } + + $list = []; + foreach ($newsList as $key => $item) { + $keys = array_keys($item); + $pid = $this->topCateId($app, $key, 0); + if ($keys == 1 && $key == $keys[0]) { + foreach ($item[$key] as $value) { + $list[$pid][] = $value; + } + } else { + foreach ($item as $i => $k) { + $cateId = $this->topCateId($app, $i, $pid); + foreach ($k as $value) { + $list[$cateId][] = $value; + } + } + } + } + + //保持新增的权限路由 + $data = $this->dao->selectList(['app_name' => $app], 'path,method')->toArray(); + $save = []; + foreach ($list as $key => $value) { + foreach ($value as $item) { + if (!$this->diffRoute($data, $item['rule'], $item['method']) && strstr($item['rule'], '') === false) { + $pathAndAction = explode('/', $item['route']); + $save[] = [ + 'name' => $item['option']['real_name'] ?? $item['name'], + 'path' => $item['rule'], + 'cate_id' => $key, + 'app_name' => $app, + 'file_path' => 'app/' . $app . '/controller/' . str_replace('.', '/', $pathAndAction[0]) . '.php', + 'action' => $pathAndAction[1], + 'type' => isset($item['option']['is_common']) && $item['option']['is_common'] ? 1 : 0, + 'method' => $item['method'], + 'create_time' => date('Y-m-d H:i:s'), + ]; + } + } + } + + if ($save) { + $this->dao->saveAll($save); + } + //删除不存在的权限路由 + $data = $this->dao->selectList(['app_name' => $app], 'path,method,id')->toArray(); + $delete = []; + $deleteData = []; + foreach ($data as $item) { + if (!$this->diffRoute($listAll, $item['path'], $item['method'], 'rule') && $item['path'] !== '') { + $delete[] = $item['id']; + $deleteData[] = [ + 'path' => $item['path'], + 'method' => $item['method'] + ]; + } + } + //删除不存在的路由 + if ($delete) { + $this->dao->delete([['id', 'in', $delete]]); + } + //删除不存在的权限 +// if ($deleteData) { +// foreach ($deleteData as $item) { +// app()->make(SystemMenusServices::class)->deleteMenu($item['path'], $item['method']); +// } +// } + $this->cacheDriver()->clear(); + } + + /** + * 对比路由 + * @param array $data + * @param string $path + * @param string $method + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/6 + */ + protected function diffRoute(array $data, string $path, string $method, string $key = 'path') + { + $res = false; + foreach ($data as $item) { + if (strtolower($item['method']) == strtolower($method) && strtolower($item[$key]) == strtolower($path)) { + $res = true; + break; + } else if ($method === '*' && strtolower($item[$key]) == strtolower($path)) { + $res = true; + break; + } + } + return $res; + } + + /** + * 添加和修改路由 + * @param int $id + * @return array + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/7 + */ + public function getFrom(int $id = 0, string $appName = 'adminapi') + { + $cateList = app()->make(SystemRouteCateServices::class)->getAllList($appName, 'name as label,path as value'); + + $url = '/system/route'; + $routeInfo = []; + if ($id) { + $routeInfo = $this->dao->get($id); + $routeInfo = $routeInfo ? $routeInfo->toArray() : []; + $url .= '/' . $id; + } + + $rule = [ + FormBuilder::cascader('cate_id', '分类', $routeInfo['cate_id'] ?? 0)->data($cateList), + FormBuilder::input('name', '路由名称', $routeInfo['name'] ?? '')->required(), + FormBuilder::input('path', '路由路径', $routeInfo['path'] ?? '')->required(), + FormBuilder::select('method', '请求方式', $routeInfo['method'] ?? '')->options([ + ['value' => 'POST', 'label' => 'POST'], + ['value' => 'GET', 'label' => 'GET'], + ['value' => 'DELETE', 'label' => 'DELETE'], + ['value' => 'PUT', 'label' => 'PUT'], + ['value' => '*', 'label' => '*'], + ])->required(), + FormBuilder::radio('type', '类型', $routeInfo['type'] ?? 0)->options([ + ['value' => 0, 'lable' => '普通路由'], + ['value' => 1, 'lable' => '公共路由'], + ]), + FormBuilder::hidden('app_name', $appName), + ]; + + return create_form($id ? '修改路由' : '添加路由', $rule, $url, $id ? 'PUT' : 'POST'); + } +} diff --git a/demo/webman/backend/composer.json b/demo/webman/backend/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..7eeda651faa3c41381f3a1b8e28346876489f91c --- /dev/null +++ b/demo/webman/backend/composer.json @@ -0,0 +1,70 @@ +{ + "name": "workerman/webman", + "type": "project", + "keywords": [ + "high performance", + "http service" + ], + "homepage": "https://www.workerman.net", + "license": "MIT", + "description": "High performance HTTP Service Framework.", + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "https://www.workerman.net", + "role": "Developer" + } + ], + "support": { + "email": "walkor@workerman.net", + "issues": "https://github.com/walkor/webman/issues", + "forum": "https://wenda.workerman.net/", + "wiki": "https://workerman.net/doc/webman", + "source": "https://github.com/walkor/webman" + }, + "repositories": { + }, + "require": { + "php": ">=7.2", + "workerman/webman-framework": "^1.5.0", + "monolog/monolog": "^2.0", + "webman/admin": "^0.6.24", + "karka/ingenious": "@dev", + "webman/think-orm": "^1.1", + "spatie/macroable": "^2.0", + "firebase/php-jwt": "^6.10", + "illuminate/redis": "^9.52", + "illuminate/events": "^9.52", + "symfony/cache": "^6.0", + "topthink/think-validate": "^2.0", + "ramsey/uuid": "^4.7", + "webman/cors": "^1.0", + "ingen/ingenious": "^1.0" + }, + "suggest": { + "ext-event": "For better performance. " + }, + "autoload": { + "psr-4": { + "": "./", + "app\\": "./app", + "App\\": "./app", + "app\\View\\Components\\": "./app/view/components" + }, + "files": [ + "./support/helpers.php" + ] + }, + "scripts": { + "post-package-install": [ + "support\\Plugin::install" + ], + "post-package-update": [ + "support\\Plugin::install" + ], + "pre-package-uninstall": [ + "support\\Plugin::uninstall" + ] + } +} diff --git a/demo/webman/backend/composer.lock b/demo/webman/backend/composer.lock new file mode 100644 index 0000000000000000000000000000000000000000..36cc6508f93dae39f0bdbfbadbf146fa51eab027 --- /dev/null +++ b/demo/webman/backend/composer.lock @@ -0,0 +1,5849 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "b69b324360bd155cac9757d2c00b462a", + "packages": [ + { + "name": "brick/math", + "version": "0.11.0", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478", + "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^9.0", + "vimeo/psalm": "5.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "brick", + "math" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.11.0" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2023-01-15T23:15:59+00:00" + }, + { + "name": "carbonphp/carbon-doctrine-types", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", + "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "doctrine/dbal": "<3.7.0 || >=4.0.0" + }, + "require-dev": { + "doctrine/dbal": "^3.7.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2023-12-11T17:09:12+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.10", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.10" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2024-02-18T20:23:39+00:00" + }, + { + "name": "firebase/php-jwt", + "version": "v6.10.0", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "a49db6f0a5033aef5143295342f1c95521b075ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/a49db6f0a5033aef5143295342f1c95521b075ff", + "reference": "a49db6f0a5033aef5143295342f1c95521b075ff", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.4||^8.0" + }, + "require-dev": { + "guzzlehttp/guzzle": "^6.5||^7.4", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psr/cache": "^1.0||^2.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0" + }, + "suggest": { + "ext-sodium": "Support EdDSA (Ed25519) signatures", + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "support": { + "issues": "https://github.com/firebase/php-jwt/issues", + "source": "https://github.com/firebase/php-jwt/tree/v6.10.0" + }, + "time": "2023-12-01T16:26:39+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.8.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:35:24+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:19:20+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.6.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:05:35+00:00" + }, + { + "name": "hoa/compiler", + "version": "3.17.08.08", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Compiler.git", + "reference": "aa09caf0bf28adae6654ca6ee415ee2f522672de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Compiler/zipball/aa09caf0bf28adae6654ca6ee415ee2f522672de", + "reference": "aa09caf0bf28adae6654ca6ee415ee2f522672de", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0", + "hoa/file": "~1.0", + "hoa/iterator": "~2.0", + "hoa/math": "~1.0", + "hoa/protocol": "~1.0", + "hoa/regex": "~1.0", + "hoa/visitor": "~2.0" + }, + "require-dev": { + "hoa/json": "~2.0", + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Compiler\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Compiler library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "algebraic", + "ast", + "compiler", + "context-free", + "coverage", + "exhaustive", + "grammar", + "isotropic", + "language", + "lexer", + "library", + "ll1", + "llk", + "parser", + "pp", + "random", + "regular", + "rule", + "sampler", + "syntax", + "token", + "trace", + "uniform" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Compiler", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Compiler/issues", + "source": "https://central.hoa-project.net/Resource/Library/Compiler" + }, + "abandoned": true, + "time": "2017-08-08T07:44:07+00:00" + }, + { + "name": "hoa/consistency", + "version": "1.17.05.02", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Consistency.git", + "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Consistency/zipball/fd7d0adc82410507f332516faf655b6ed22e4c2f", + "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/exception": "~1.0", + "php": ">=5.5.0" + }, + "require-dev": { + "hoa/stream": "~1.0", + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "files": [ + "Prelude.php" + ], + "psr-4": { + "Hoa\\Consistency\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Consistency library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "autoloader", + "callable", + "consistency", + "entity", + "flex", + "keyword", + "library" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Consistency", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Consistency/issues", + "source": "https://central.hoa-project.net/Resource/Library/Consistency" + }, + "abandoned": true, + "time": "2017-05-02T12:18:12+00:00" + }, + { + "name": "hoa/event", + "version": "1.17.01.13", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Event.git", + "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Event/zipball/6c0060dced212ffa3af0e34bb46624f990b29c54", + "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Event\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Event library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "event", + "library", + "listener", + "observer" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Event", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Event/issues", + "source": "https://central.hoa-project.net/Resource/Library/Event" + }, + "abandoned": true, + "time": "2017-01-13T15:30:50+00:00" + }, + { + "name": "hoa/exception", + "version": "1.17.01.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Exception.git", + "reference": "091727d46420a3d7468ef0595651488bfc3a458f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Exception/zipball/091727d46420a3d7468ef0595651488bfc3a458f", + "reference": "091727d46420a3d7468ef0595651488bfc3a458f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/event": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Exception\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Exception library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "exception", + "library" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Exception", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Exception/issues", + "source": "https://central.hoa-project.net/Resource/Library/Exception" + }, + "abandoned": true, + "time": "2017-01-16T07:53:27+00:00" + }, + { + "name": "hoa/file", + "version": "1.17.07.11", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/File.git", + "reference": "35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/File/zipball/35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca", + "reference": "35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/event": "~1.0", + "hoa/exception": "~1.0", + "hoa/iterator": "~2.0", + "hoa/stream": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\File\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\File library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "Socket", + "directory", + "file", + "finder", + "library", + "link", + "temporary" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/File", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/File/issues", + "source": "https://central.hoa-project.net/Resource/Library/File" + }, + "abandoned": true, + "time": "2017-07-11T07:42:15+00:00" + }, + { + "name": "hoa/iterator", + "version": "2.17.01.10", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Iterator.git", + "reference": "d1120ba09cb4ccd049c86d10058ab94af245f0cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Iterator/zipball/d1120ba09cb4ccd049c86d10058ab94af245f0cc", + "reference": "d1120ba09cb4ccd049c86d10058ab94af245f0cc", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Iterator\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Iterator library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "iterator", + "library" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Iterator", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Iterator/issues", + "source": "https://central.hoa-project.net/Resource/Library/Iterator" + }, + "abandoned": true, + "time": "2017-01-10T10:34:47+00:00" + }, + { + "name": "hoa/math", + "version": "1.17.05.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Math.git", + "reference": "7150785d30f5d565704912116a462e9f5bc83a0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Math/zipball/7150785d30f5d565704912116a462e9f5bc83a0c", + "reference": "7150785d30f5d565704912116a462e9f5bc83a0c", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/compiler": "~3.0", + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0", + "hoa/iterator": "~2.0", + "hoa/protocol": "~1.0", + "hoa/zformat": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Math\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Math library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "arrangement", + "combination", + "combinatorics", + "counting", + "library", + "math", + "permutation", + "sampler", + "set" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Math", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Math/issues", + "source": "https://central.hoa-project.net/Resource/Library/Math" + }, + "abandoned": true, + "time": "2017-05-16T08:02:17+00:00" + }, + { + "name": "hoa/protocol", + "version": "1.17.01.14", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Protocol.git", + "reference": "5c2cf972151c45f373230da170ea015deecf19e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Protocol/zipball/5c2cf972151c45f373230da170ea015deecf19e2", + "reference": "5c2cf972151c45f373230da170ea015deecf19e2", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "files": [ + "Wrapper.php" + ], + "psr-4": { + "Hoa\\Protocol\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Protocol library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "library", + "protocol", + "resource", + "stream", + "wrapper" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Protocol", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Protocol/issues", + "source": "https://central.hoa-project.net/Resource/Library/Protocol" + }, + "abandoned": true, + "time": "2017-01-14T12:26:10+00:00" + }, + { + "name": "hoa/regex", + "version": "1.17.01.13", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Regex.git", + "reference": "7e263a61b6fb45c1d03d8e5ef77668518abd5bec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Regex/zipball/7e263a61b6fb45c1d03d8e5ef77668518abd5bec", + "reference": "7e263a61b6fb45c1d03d8e5ef77668518abd5bec", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0", + "hoa/math": "~1.0", + "hoa/protocol": "~1.0", + "hoa/ustring": "~4.0", + "hoa/visitor": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Regex\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Regex library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "compiler", + "library", + "regex" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Regex", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Regex/issues", + "source": "https://central.hoa-project.net/Resource/Library/Regex" + }, + "abandoned": true, + "time": "2017-01-13T16:10:24+00:00" + }, + { + "name": "hoa/ruler", + "version": "2.17.05.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Ruler.git", + "reference": "696835daf8336dfd490f032da7af444050e52dfc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Ruler/zipball/696835daf8336dfd490f032da7af444050e52dfc", + "reference": "696835daf8336dfd490f032da7af444050e52dfc", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/compiler": "~3.0", + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0", + "hoa/file": "~1.0", + "hoa/protocol": "~1.0", + "hoa/visitor": "~2.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Ruler\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Ruler library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "library", + "ruler" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Ruler", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Ruler/issues", + "source": "https://central.hoa-project.net/Resource/Library/Ruler" + }, + "abandoned": true, + "time": "2017-05-16T07:52:21+00:00" + }, + { + "name": "hoa/stream", + "version": "1.17.02.21", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Stream.git", + "reference": "3293cfffca2de10525df51436adf88a559151d82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Stream/zipball/3293cfffca2de10525df51436adf88a559151d82", + "reference": "3293cfffca2de10525df51436adf88a559151d82", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/event": "~1.0", + "hoa/exception": "~1.0", + "hoa/protocol": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Stream\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Stream library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "Context", + "bucket", + "composite", + "filter", + "in", + "library", + "out", + "protocol", + "stream", + "wrapper" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Stream", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Stream/issues", + "source": "https://central.hoa-project.net/Resource/Library/Stream" + }, + "abandoned": true, + "time": "2017-02-21T16:01:06+00:00" + }, + { + "name": "hoa/ustring", + "version": "4.17.01.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Ustring.git", + "reference": "e6326e2739178799b1fe3fdd92029f9517fa17a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Ustring/zipball/e6326e2739178799b1fe3fdd92029f9517fa17a0", + "reference": "e6326e2739178799b1fe3fdd92029f9517fa17a0", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "suggest": { + "ext-iconv": "ext/iconv must be present (or a third implementation) to use Hoa\\Ustring::transcode().", + "ext-intl": "To get a better Hoa\\Ustring::toAscii() and Hoa\\Ustring::compareTo()." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Ustring\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Ustring library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "library", + "search", + "string", + "unicode" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Ustring", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Ustring/issues", + "source": "https://central.hoa-project.net/Resource/Library/Ustring" + }, + "abandoned": true, + "time": "2017-01-16T07:08:25+00:00" + }, + { + "name": "hoa/visitor", + "version": "2.17.01.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Visitor.git", + "reference": "c18fe1cbac98ae449e0d56e87469103ba08f224a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Visitor/zipball/c18fe1cbac98ae449e0d56e87469103ba08f224a", + "reference": "c18fe1cbac98ae449e0d56e87469103ba08f224a", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/consistency": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Visitor\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Visitor library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "library", + "structure", + "visit", + "visitor" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Visitor", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Visitor/issues", + "source": "https://central.hoa-project.net/Resource/Library/Visitor" + }, + "abandoned": true, + "time": "2017-01-16T07:02:03+00:00" + }, + { + "name": "hoa/zformat", + "version": "1.17.01.10", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Zformat.git", + "reference": "522c381a2a075d4b9dbb42eb4592dd09520e4ac2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Zformat/zipball/522c381a2a075d4b9dbb42eb4592dd09520e4ac2", + "reference": "522c381a2a075d4b9dbb42eb4592dd09520e4ac2", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Zformat\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Zformat library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "library", + "parameter", + "zformat" + ], + "support": { + "docs": "https://central.hoa-project.net/Documentation/Library/Zformat", + "email": "support@hoa-project.net", + "forum": "https://users.hoa-project.net/", + "irc": "irc://chat.freenode.net/hoaproject", + "issues": "https://github.com/hoaproject/Zformat/issues", + "source": "https://central.hoa-project.net/Resource/Library/Zformat" + }, + "abandoned": true, + "time": "2017-01-10T10:39:54+00:00" + }, + { + "name": "illuminate/bus", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/bus.git", + "reference": "4c719a19c3d8c34b2494a7206f8ffde3eff3f983" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/bus/zipball/4c719a19c3d8c34b2494a7206f8ffde3eff3f983", + "reference": "4c719a19c3d8c34b2494a7206f8ffde3eff3f983", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "illuminate/collections": "^9.0", + "illuminate/contracts": "^9.0", + "illuminate/pipeline": "^9.0", + "illuminate/support": "^9.0", + "php": "^8.0.2" + }, + "suggest": { + "illuminate/queue": "Required to use closures when chaining jobs (^7.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Bus\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Bus package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-04-18T13:42:14+00:00" + }, + { + "name": "illuminate/collections", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/collections.git", + "reference": "d3710b0b244bfc62c288c1a87eaa62dd28352d1f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/collections/zipball/d3710b0b244bfc62c288c1a87eaa62dd28352d1f", + "reference": "d3710b0b244bfc62c288c1a87eaa62dd28352d1f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "illuminate/conditionable": "^9.0", + "illuminate/contracts": "^9.0", + "illuminate/macroable": "^9.0", + "php": "^8.0.2" + }, + "suggest": { + "symfony/var-dumper": "Required to use the dump method (^6.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "files": [ + "helpers.php" + ], + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Collections package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-06-11T21:17:10+00:00" + }, + { + "name": "illuminate/conditionable", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/conditionable.git", + "reference": "bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/conditionable/zipball/bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364", + "reference": "bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Conditionable package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-02-01T21:42:32+00:00" + }, + { + "name": "illuminate/container", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/container.git", + "reference": "1641dda2d0750b68bb1264a3b37ff3973f2e6265" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/container/zipball/1641dda2d0750b68bb1264a3b37ff3973f2e6265", + "reference": "1641dda2d0750b68bb1264a3b37ff3973f2e6265", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "illuminate/contracts": "^9.0", + "php": "^8.0.2", + "psr/container": "^1.1.1|^2.0.1" + }, + "provide": { + "psr/container-implementation": "1.1|2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Container\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Container package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-01-24T16:54:18+00:00" + }, + { + "name": "illuminate/contracts", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/contracts.git", + "reference": "44f65d723b13823baa02ff69751a5948bde60c22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/44f65d723b13823baa02ff69751a5948bde60c22", + "reference": "44f65d723b13823baa02ff69751a5948bde60c22", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^8.0.2", + "psr/container": "^1.1.1|^2.0.1", + "psr/simple-cache": "^1.0|^2.0|^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Contracts\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Contracts package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-02-08T14:36:30+00:00" + }, + { + "name": "illuminate/database", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/database.git", + "reference": "93cfc8e1f9ac147e6a2851ecabe8d8f21ad85182" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/database/zipball/93cfc8e1f9ac147e6a2851ecabe8d8f21ad85182", + "reference": "93cfc8e1f9ac147e6a2851ecabe8d8f21ad85182", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "brick/math": "^0.9.3|^0.10.2|^0.11", + "ext-pdo": "*", + "illuminate/collections": "^9.0", + "illuminate/container": "^9.0", + "illuminate/contracts": "^9.0", + "illuminate/macroable": "^9.0", + "illuminate/support": "^9.0", + "php": "^8.0.2", + "symfony/console": "^6.0.9" + }, + "suggest": { + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.4).", + "ext-filter": "Required to use the Postgres database driver.", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.21).", + "illuminate/console": "Required to use the database commands (^9.0).", + "illuminate/events": "Required to use the observers with Eloquent (^9.0).", + "illuminate/filesystem": "Required to use the migrations (^9.0).", + "illuminate/pagination": "Required to paginate the result set (^9.0).", + "symfony/finder": "Required to use Eloquent model factories (^6.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Database\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Database package.", + "homepage": "https://laravel.com", + "keywords": [ + "database", + "laravel", + "orm", + "sql" + ], + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-06-11T21:17:10+00:00" + }, + { + "name": "illuminate/events", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/events.git", + "reference": "8e534676bac23bc17925f5c74c128f9c09b98f69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/events/zipball/8e534676bac23bc17925f5c74c128f9c09b98f69", + "reference": "8e534676bac23bc17925f5c74c128f9c09b98f69", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "illuminate/bus": "^9.0", + "illuminate/collections": "^9.0", + "illuminate/container": "^9.0", + "illuminate/contracts": "^9.0", + "illuminate/macroable": "^9.0", + "illuminate/support": "^9.0", + "php": "^8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "files": [ + "functions.php" + ], + "psr-4": { + "Illuminate\\Events\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Events package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2022-09-15T13:14:12+00:00" + }, + { + "name": "illuminate/macroable", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/macroable.git", + "reference": "e3bfaf6401742a9c6abca61b9b10e998e5b6449a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/macroable/zipball/e3bfaf6401742a9c6abca61b9b10e998e5b6449a", + "reference": "e3bfaf6401742a9c6abca61b9b10e998e5b6449a", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Macroable package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2022-08-09T13:29:29+00:00" + }, + { + "name": "illuminate/pagination", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/pagination.git", + "reference": "0c913d6af303ae0060d94d74d68d537637f7e6d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/pagination/zipball/0c913d6af303ae0060d94d74d68d537637f7e6d4", + "reference": "0c913d6af303ae0060d94d74d68d537637f7e6d4", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-filter": "*", + "illuminate/collections": "^9.0", + "illuminate/contracts": "^9.0", + "illuminate/support": "^9.0", + "php": "^8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Pagination\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Pagination package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-02-06T02:52:41+00:00" + }, + { + "name": "illuminate/pipeline", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/pipeline.git", + "reference": "e0be3f3f79f8235ad7334919ca4094d5074e02f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/pipeline/zipball/e0be3f3f79f8235ad7334919ca4094d5074e02f6", + "reference": "e0be3f3f79f8235ad7334919ca4094d5074e02f6", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "illuminate/contracts": "^9.0", + "illuminate/support": "^9.0", + "php": "^8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Pipeline\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Pipeline package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2022-06-09T14:13:53+00:00" + }, + { + "name": "illuminate/redis", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/redis.git", + "reference": "d4702b8d6a64a48cfab7259248ecbecf3b6135e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/redis/zipball/d4702b8d6a64a48cfab7259248ecbecf3b6135e2", + "reference": "d4702b8d6a64a48cfab7259248ecbecf3b6135e2", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "illuminate/collections": "^9.0", + "illuminate/contracts": "^9.0", + "illuminate/macroable": "^9.0", + "illuminate/support": "^9.0", + "php": "^8.0.2" + }, + "suggest": { + "ext-redis": "Required to use the phpredis connector (^4.0|^5.0).", + "predis/predis": "Required to use the predis connector (^1.1.9|^2.0.2)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Redis\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Redis package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-07-31T15:01:27+00:00" + }, + { + "name": "illuminate/support", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/support.git", + "reference": "223c608dbca27232df6213f776bfe7bdeec24874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/support/zipball/223c608dbca27232df6213f776bfe7bdeec24874", + "reference": "223c608dbca27232df6213f776bfe7bdeec24874", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "doctrine/inflector": "^2.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-mbstring": "*", + "illuminate/collections": "^9.0", + "illuminate/conditionable": "^9.0", + "illuminate/contracts": "^9.0", + "illuminate/macroable": "^9.0", + "nesbot/carbon": "^2.62.1", + "php": "^8.0.2", + "voku/portable-ascii": "^2.0" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "suggest": { + "illuminate/filesystem": "Required to use the composer class (^9.0).", + "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.0.2).", + "ramsey/uuid": "Required to use Str::uuid() (^4.7).", + "symfony/process": "Required to use the composer class (^6.0).", + "symfony/uid": "Required to use Str::ulid() (^6.0).", + "symfony/var-dumper": "Required to use the dd function (^6.0).", + "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.4.1)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "files": [ + "helpers.php" + ], + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Support package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-06-11T21:11:53+00:00" + }, + { + "name": "ingen/ingenious", + "version": "v1.0.5", + "source": { + "type": "git", + "url": "https://gitee.com/ingenstream/ingenious.git", + "reference": "64fca9413af8b40df27a2c499d3c405421b5ccb7" + }, + "require": { + "ext-redis": "*", + "kphoen/rulerz": "^0.21.1", + "monolog/monolog": "*", + "php": ">=8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "ingenious\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mr.April", + "email": "405784684@qq.com", + "homepage": "https://gitee.com/ingenstream" + } + ], + "description": "a php work flow engine base on ingenious-php", + "time": "2024-05-22T13:21:50+00:00" + }, + { + "name": "intervention/image", + "version": "2.7.2", + "source": { + "type": "git", + "url": "https://github.com/Intervention/image.git", + "reference": "04be355f8d6734c826045d02a1079ad658322dad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Intervention/image/zipball/04be355f8d6734c826045d02a1079ad658322dad", + "reference": "04be355f8d6734c826045d02a1079ad658322dad", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-fileinfo": "*", + "guzzlehttp/psr7": "~1.1 || ^2.0", + "php": ">=5.4.0" + }, + "require-dev": { + "mockery/mockery": "~0.9.2", + "phpunit/phpunit": "^4.8 || ^5.7 || ^7.5.15" + }, + "suggest": { + "ext-gd": "to use GD library based image processing.", + "ext-imagick": "to use Imagick based image processing.", + "intervention/imagecache": "Caching extension for the Intervention Image library" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + }, + "laravel": { + "providers": [ + "Intervention\\Image\\ImageServiceProvider" + ], + "aliases": { + "Image": "Intervention\\Image\\Facades\\Image" + } + } + }, + "autoload": { + "psr-4": { + "Intervention\\Image\\": "src/Intervention/Image" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Vogel", + "email": "oliver@intervention.io", + "homepage": "https://intervention.io/" + } + ], + "description": "Image handling and manipulation library with support for Laravel integration", + "homepage": "http://image.intervention.io/", + "keywords": [ + "gd", + "image", + "imagick", + "laravel", + "thumbnail", + "watermark" + ], + "support": { + "issues": "https://github.com/Intervention/image/issues", + "source": "https://github.com/Intervention/image/tree/2.7.2" + }, + "funding": [ + { + "url": "https://paypal.me/interventionio", + "type": "custom" + }, + { + "url": "https://github.com/Intervention", + "type": "github" + } + ], + "time": "2022-05-21T17:30:32+00:00" + }, + { + "name": "karka/ingenious", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://gitee.com/liu_guan_qing/ingenious.git", + "reference": "0554ec96576e0a1f6821d0fb2e7db272cc2a96db" + }, + "default-branch": true, + "type": "library", + "autoload": { + "psr-4": { + "ingenious\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mr.April", + "email": "liuguanqin.g@163.com" + } + ], + "description": "测试软件包", + "time": "2024-02-25T13:14:52+00:00" + }, + { + "name": "kphoen/rulerz", + "version": "0.21.1", + "source": { + "type": "git", + "url": "https://github.com/K-Phoen/rulerz.git", + "reference": "d28a1bd59b4e66cc9fcdeee965f13f685eb9ce41" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/K-Phoen/rulerz/zipball/d28a1bd59b4e66cc9fcdeee965f13f685eb9ce41", + "reference": "d28a1bd59b4e66cc9fcdeee965f13f685eb9ce41", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "hoa/ruler": "~2.0", + "php": ">=7.1", + "symfony/property-access": "~3.0|~4.0" + }, + "require-dev": { + "behat/behat": "~3.0", + "coduo/phpspec-data-provider-extension": "~1.0,!=1.0.2", + "doctrine/orm": "~2.4", + "elasticsearch/elasticsearch": "~1.0", + "illuminate/database": "~5.0", + "kphoen/rusty": "dev-master", + "liip/rmt": "^1.2", + "mikey179/vfsstream": "~1.4", + "phpspec/phpspec": "~2.0,>=2.4-dev", + "pomm-project/cli": "~2.0@dev", + "pomm-project/foundation": "~2.0@dev", + "pomm-project/model-manager": "~2.0.@dev", + "ruflin/elastica": "~1.0", + "solarium/solarium": "~3.0", + "vlucas/phpdotenv": "~2.1" + }, + "suggest": { + "doctrine/orm": "To execute rules as Doctrine queries", + "elasticsearch/elasticsearch": "To execute rules as Elasticsearch queries", + "kphoen/rulerz-spec-builder": "If you want a specification builder", + "pomm-project/model-manager": "To execute rules as Pomm queries", + "solarium/solarium": "To execute rules as Solr queries" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "RulerZ\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Gomez", + "email": "contact@kevingomez.fr" + } + ], + "description": "Powerful implementation of the Specification pattern", + "homepage": "https://github.com/K-Phoen/RulerZ", + "keywords": [ + "doctrine", + "specification" + ], + "support": { + "issues": "https://github.com/K-Phoen/rulerz/issues", + "source": "https://github.com/K-Phoen/rulerz/tree/0.21.1" + }, + "time": "2018-09-18T15:15:42+00:00" + }, + { + "name": "monolog/monolog", + "version": "2.9.2", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/437cb3628f4cf6042cc10ae97fc2b8472e48ca1f", + "reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "guzzlehttp/guzzle": "^7.4", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpspec/prophecy": "^1.15", + "phpstan/phpstan": "^0.12.91", + "phpunit/phpunit": "^8.5.14", + "predis/predis": "^1.1 || ^2.0", + "rollbar/rollbar": "^1.3 || ^2 || ^3", + "ruflin/elastica": "^7", + "swiftmailer/swiftmailer": "^5.3|^6.0", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/2.9.2" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2023-10-27T15:25:26+00:00" + }, + { + "name": "nesbot/carbon", + "version": "2.72.3", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "0c6fd108360c562f6e4fd1dedb8233b423e91c83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/0c6fd108360c562f6e4fd1dedb8233b423e91c83", + "reference": "0c6fd108360c562f6e4fd1dedb8233b423e91c83", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "carbonphp/carbon-doctrine-types": "*", + "ext-json": "*", + "php": "^7.1.8 || ^8.0", + "psr/clock": "^1.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "doctrine/dbal": "^2.0 || ^3.1.4 || ^4.0", + "doctrine/orm": "^2.7 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.0", + "kylekatarnls/multi-tester": "^2.0", + "ondrejmirtes/better-reflection": "*", + "phpmd/phpmd": "^2.9", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.99 || ^1.7.14", + "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", + "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", + "squizlabs/php_codesniffer": "^3.4" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-3.x": "3.x-dev", + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/briannesbitt/Carbon/issues", + "source": "https://github.com/briannesbitt/Carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2024-01-25T10:35:09+00:00" + }, + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "FastRoute\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "support": { + "issues": "https://github.com/nikic/FastRoute/issues", + "source": "https://github.com/nikic/FastRoute/tree/master" + }, + "time": "2018-02-13T20:26:39+00:00" + }, + { + "name": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "time": "2021-02-03T23:26:27+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + }, + "time": "2023-04-10T20:10:41+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "ramsey/collection", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/ad7475d1c9e70b190ecffc58f2d989416af339b4", + "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.4 || ^8.0", + "symfony/polyfill-php81": "^1.23" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.28.3", + "fakerphp/faker": "^1.21", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^1.0", + "mockery/mockery": "^1.5", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcsstandards/phpcsutils": "^1.0.0-rc1", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18.4", + "ramsey/coding-standard": "^2.0.3", + "ramsey/conventional-commits": "^1.3", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/1.3.0" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2022-12-27T19:12:24+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.7.5", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e", + "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11", + "ext-json": "*", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^8.5 || ^9", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.7.5" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "type": "tidelift" + } + ], + "time": "2023-11-08T05:53:05+00:00" + }, + { + "name": "spatie/macroable", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/macroable.git", + "reference": "ec2c320f932e730607aff8052c44183cf3ecb072" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/macroable/zipball/ec2c320f932e730607aff8052c44183cf3ecb072", + "reference": "ec2c320f932e730607aff8052c44183cf3ecb072", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.0|^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Macroable\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "A trait to dynamically add methods to a class", + "homepage": "https://github.com/spatie/macroable", + "keywords": [ + "macroable", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/macroable/issues", + "source": "https://github.com/spatie/macroable/tree/2.0.0" + }, + "time": "2021-03-26T22:39:02+00:00" + }, + { + "name": "symfony/cache", + "version": "v6.0.19", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "81ca309f056e836480928b20280ec52ce8369bb3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/81ca309f056e836480928b20280ec52ce8369bb3", + "reference": "81ca309f056e836480928b20280ec52ce8369bb3", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2", + "psr/cache": "^2.0|^3.0", + "psr/log": "^1.1|^2|^3", + "symfony/cache-contracts": "^1.1.7|^2|^3", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/var-exporter": "^5.4|^6.0" + }, + "conflict": { + "doctrine/dbal": "<2.13.1", + "symfony/dependency-injection": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/var-dumper": "<5.4" + }, + "provide": { + "psr/cache-implementation": "2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0", + "symfony/cache-implementation": "1.1|2.0|3.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/dbal": "^2.13.1|^3.0", + "predis/predis": "^1.1", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/filesystem": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/messenger": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "support": { + "source": "https://github.com/symfony/cache/tree/v6.0.19" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-20T17:44:14+00:00" + }, + { + "name": "symfony/cache-contracts", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "1c0a181c9ee221afe4fa55b2d13fc63c5ae14348" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/1c0a181c9ee221afe4fa55b2d13fc63c5ae14348", + "reference": "1c0a181c9ee221afe4fa55b2d13fc63c5ae14348", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2", + "psr/cache": "^3.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/cache-contracts/tree/v3.0.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:55:41+00:00" + }, + { + "name": "symfony/console", + "version": "v6.0.19", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/c3ebc83d031b71c39da318ca8b7a07ecc67507ed", + "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.0.19" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-01T08:36:10+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:55:41+00:00" + }, + { + "name": "symfony/inflector", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/inflector.git", + "reference": "d56964e2b19253ba331a829c20d911dd27aa61b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/inflector/zipball/d56964e2b19253ba331a829c20d911dd27aa61b6", + "reference": "d56964e2b19253ba331a829c20d911dd27aa61b6", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16", + "symfony/string": "^5.3.10|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Inflector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts words between their singular and plural forms (English only)", + "homepage": "https://symfony.com", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string", + "symfony", + "words" + ], + "support": { + "source": "https://github.com/symfony/inflector/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "abandoned": "EnglishInflector from the String component", + "time": "2023-02-14T08:03:56+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "42292d99c55abe617799667f454222c54c60e229" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-07-28T09:04:16+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/property-access", + "version": "v4.4.44", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-access.git", + "reference": "d49682f6f0764df725c95128213a38f7e0a9f358" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-access/zipball/d49682f6f0764df725c95128213a38f7e0a9f358", + "reference": "d49682f6f0764df725c95128213a38f7e0a9f358", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1.3", + "symfony/inflector": "^3.4|^4.0|^5.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "symfony/cache": "^3.4|^4.0|^5.0" + }, + "suggest": { + "psr/cache-implementation": "To cache access methods." + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides functions to read and write from/to an object or array using a simple string notation", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property path", + "reflection" + ], + "support": { + "source": "https://github.com/symfony/property-access/tree/v4.4.44" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-06-27T13:16:42+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2", + "psr/container": "^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.0.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-30T19:17:58+00:00" + }, + { + "name": "symfony/string", + "version": "v6.0.19", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/d9e72497367c23e08bf94176d2be45b00a9d232a", + "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.0" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v6.0.19" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-01T08:36:10+00:00" + }, + { + "name": "symfony/translation", + "version": "v6.0.19", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", + "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.3|^3.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-client-contracts": "^1.1|^2.0|^3.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/service-contracts": "^1.1.2|^2|^3", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v6.0.19" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-01T08:36:10+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/acbfbb274e730e5a0236f619b6168d9dedb3e282", + "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.0.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-06-27T17:10:44+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v6.0.19", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "df56f53818c2d5d9f683f4ad2e365ba73a3b69d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/df56f53818c2d5d9f683f4ad2e365ba73a3b69d2", + "reference": "df56f53818c2d5d9f683f4ad2e365ba73a3b69d2", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2" + }, + "require-dev": { + "symfony/var-dumper": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v6.0.19" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-13T08:34:10+00:00" + }, + { + "name": "topthink/think-container", + "version": "v2.0.5", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-container.git", + "reference": "2189b39e42af2c14203ed4372b92e38989e9dabb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-container/zipball/2189b39e42af2c14203ed4372b92e38989e9dabb", + "reference": "2189b39e42af2c14203ed4372b92e38989e9dabb", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2.0", + "psr/container": "^1.0|^2.0", + "topthink/think-helper": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0|^8.0" + }, + "type": "library", + "autoload": { + "files": [], + "psr-4": { + "think\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "liu21st", + "email": "liu21st@gmail.com" + } + ], + "description": "PHP Container & Facade Manager", + "support": { + "issues": "https://github.com/top-think/think-container/issues", + "source": "https://github.com/top-think/think-container/tree/v2.0.5" + }, + "time": "2022-05-23T06:24:54+00:00" + }, + { + "name": "topthink/think-helper", + "version": "v3.1.6", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-helper.git", + "reference": "769acbe50a4274327162f9c68ec2e89a38eb2aff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-helper/zipball/769acbe50a4274327162f9c68ec2e89a38eb2aff", + "reference": "769acbe50a4274327162f9c68ec2e89a38eb2aff", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/helper.php" + ], + "psr-4": { + "think\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "yunwuxin", + "email": "448901948@qq.com" + } + ], + "description": "The ThinkPHP6 Helper Package", + "support": { + "issues": "https://github.com/top-think/think-helper/issues", + "source": "https://github.com/top-think/think-helper/tree/v3.1.6" + }, + "time": "2021-12-15T04:27:55+00:00" + }, + { + "name": "topthink/think-orm", + "version": "v3.0.14", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-orm.git", + "reference": "7b0b8ea6ca5e020217f6ba7ae34d547e148a675b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-orm/zipball/7b0b8ea6ca5e020217f6ba7ae34d547e148a675b", + "reference": "7b0b8ea6ca5e020217f6ba7ae34d547e148a675b", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "ext-pdo": "*", + "php": ">=8.0.0", + "psr/log": ">=1.0", + "psr/simple-cache": ">=1.0", + "topthink/think-helper": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^8|^9.5|^10" + }, + "type": "library", + "autoload": { + "files": [ + "stubs/load_stubs.php" + ], + "psr-4": { + "think\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "liu21st", + "email": "liu21st@gmail.com" + } + ], + "description": "the PHP Database&ORM Framework", + "keywords": [ + "database", + "orm" + ], + "support": { + "issues": "https://github.com/top-think/think-orm/issues", + "source": "https://github.com/top-think/think-orm/tree/v3.0.14" + }, + "time": "2023-09-24T13:15:07+00:00" + }, + { + "name": "topthink/think-validate", + "version": "v2.0.2", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-validate.git", + "reference": "857f9bffc1a09a41e3969a19726cb04315848f0f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-validate/zipball/857f9bffc1a09a41e3969a19726cb04315848f0f", + "reference": "857f9bffc1a09a41e3969a19726cb04315848f0f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1.0", + "topthink/think-container": "~2.0" + }, + "type": "library", + "autoload": { + "files": [], + "psr-4": { + "think\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "liu21st", + "email": "liu21st@gmail.com" + } + ], + "description": "think validate", + "support": { + "issues": "https://github.com/top-think/think-validate/issues", + "source": "https://github.com/top-think/think-validate/tree/2.0" + }, + "time": "2019-05-15T06:58:23+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b56450eed252f6801410d810c8e1727224ae0743" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743", + "reference": "b56450eed252f6801410d810c8e1727224ae0743", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "http://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.1" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2022-03-08T17:03:00+00:00" + }, + { + "name": "webman/admin", + "version": "v0.6.24", + "source": { + "type": "git", + "url": "https://github.com/webman-php/admin.git", + "reference": "02499473daf6f7dde5a6d742259c9135f95b71d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webman-php/admin/zipball/02499473daf6f7dde5a6d742259c9135f95b71d1", + "reference": "02499473daf6f7dde5a6d742259c9135f95b71d1", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "guzzlehttp/guzzle": "^7.5", + "illuminate/database": ">=7.30", + "illuminate/events": ">=7.30", + "illuminate/pagination": ">=7.30", + "intervention/image": "^2.7", + "webman/captcha": "^1.0.0", + "webman/event": "^1.0", + "workerman/webman-framework": ">=1.4" + }, + "type": "project", + "autoload": { + "psr-4": { + "Webman\\Admin\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Webman Admin", + "support": { + "issues": "https://github.com/webman-php/admin/issues", + "source": "https://github.com/webman-php/admin/tree/v0.6.24" + }, + "time": "2024-01-23T03:24:54+00:00" + }, + { + "name": "webman/captcha", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/webman-php/captcha.git", + "reference": "e80f271af99cb337406118fa7d90c0699ee1f3bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webman-php/captcha/zipball/e80f271af99cb337406118fa7d90c0699ee1f3bc", + "reference": "e80f271af99cb337406118fa7d90c0699ee1f3bc", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-gd": "*", + "ext-mbstring": "*", + "php": ">=5.6.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Webman\\Captcha\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net" + }, + { + "name": "Grégoire Passault", + "email": "g.passault@gmail.com", + "homepage": "http://www.gregwar.com/" + }, + { + "name": "Jeremy Livingston", + "email": "jeremy.j.livingston@gmail.com" + } + ], + "description": "Captcha generator", + "keywords": [ + "bot", + "captcha", + "spam" + ], + "support": { + "source": "https://github.com/webman-php/captcha/tree/v1.0.3" + }, + "time": "2024-03-28T07:54:04+00:00" + }, + { + "name": "webman/cors", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/webman-php/cors.git", + "reference": "a5396634fd2ee4e7b15abba0bab45f28e1c1ad02" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webman-php/cors/zipball/a5396634fd2ee4e7b15abba0bab45f28e1c1ad02", + "reference": "a5396634fd2ee4e7b15abba0bab45f28e1c1ad02", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "type": "library", + "autoload": { + "psr-4": { + "Webman\\Cors\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "support": { + "issues": "https://github.com/webman-php/cors/issues", + "source": "https://github.com/webman-php/cors/tree/v1.0.1" + }, + "time": "2022-11-05T11:16:20+00:00" + }, + { + "name": "webman/event", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/webman-php/event.git", + "reference": "f4478941c3b7efa4d7e9c063f2f6efd7ee3071a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webman-php/event/zipball/f4478941c3b7efa4d7e9c063f2f6efd7ee3071a7", + "reference": "f4478941c3b7efa4d7e9c063f2f6efd7ee3071a7", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "type": "library", + "autoload": { + "psr-4": { + "Webman\\Event\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Webman event plugin", + "support": { + "issues": "https://github.com/webman-php/event/issues", + "source": "https://github.com/webman-php/event/tree/v1.0.4" + }, + "time": "2023-03-28T04:01:23+00:00" + }, + { + "name": "webman/think-orm", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/webman-php/think-orm.git", + "reference": "9f1e525c5c4b5a2e1eee6a4f82ef5d23c69139a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webman-php/think-orm/zipball/9f1e525c5c4b5a2e1eee6a4f82ef5d23c69139a2", + "reference": "9f1e525c5c4b5a2e1eee6a4f82ef5d23c69139a2", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "topthink/think-orm": "^2.0.53 || ^3.0.0", + "workerman/webman-framework": "^1.2.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Webman\\ThinkOrm\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "support": { + "issues": "https://github.com/webman-php/think-orm/issues", + "source": "https://github.com/webman-php/think-orm/tree/v1.1.1" + }, + "time": "2023-04-23T14:40:18+00:00" + }, + { + "name": "workerman/webman-framework", + "version": "v1.5.16", + "source": { + "type": "git", + "url": "https://github.com/walkor/webman-framework.git", + "reference": "84335520a340ee60adf7cf17aeb0edb9536c24e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/walkor/webman-framework/zipball/84335520a340ee60adf7cf17aeb0edb9536c24e8", + "reference": "84335520a340ee60adf7cf17aeb0edb9536c24e8", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "nikic/fast-route": "^1.3", + "php": ">=7.2", + "psr/container": ">=1.0", + "workerman/workerman": "^4.0.4 || ^5.0.0" + }, + "suggest": { + "ext-event": "For better performance. " + }, + "type": "library", + "autoload": { + "psr-4": { + "Webman\\": "./src", + "Support\\": "./src/support", + "support\\": "./src/support", + "Support\\View\\": "./src/support/view", + "Support\\Bootstrap\\": "./src/support/bootstrap", + "Support\\Exception\\": "./src/support/exception" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "https://www.workerman.net", + "role": "Developer" + } + ], + "description": "High performance HTTP Service Framework.", + "homepage": "https://www.workerman.net", + "keywords": [ + "High Performance", + "http service" + ], + "support": { + "email": "walkor@workerman.net", + "forum": "https://wenda.workerman.net/", + "issues": "https://github.com/walkor/webman/issues", + "source": "https://github.com/walkor/webman-framework", + "wiki": "https://doc.workerman.net/" + }, + "time": "2024-01-15T12:11:49+00:00" + }, + { + "name": "workerman/workerman", + "version": "v4.1.15", + "source": { + "type": "git", + "url": "https://github.com/walkor/workerman.git", + "reference": "afc8242fc769ab7cf22eb4ac22b97cb59d465e4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/walkor/workerman/zipball/afc8242fc769ab7cf22eb4ac22b97cb59d465e4e", + "reference": "afc8242fc769ab7cf22eb4ac22b97cb59d465e4e", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.0" + }, + "suggest": { + "ext-event": "For better performance. " + }, + "type": "library", + "autoload": { + "psr-4": { + "Workerman\\": "./" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "http://www.workerman.net", + "role": "Developer" + } + ], + "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.", + "homepage": "http://www.workerman.net", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "email": "walkor@workerman.net", + "forum": "http://wenda.workerman.net/", + "issues": "https://github.com/walkor/workerman/issues", + "source": "https://github.com/walkor/workerman", + "wiki": "http://doc.workerman.net/" + }, + "funding": [ + { + "url": "https://opencollective.com/workerman", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/walkor", + "type": "patreon" + } + ], + "time": "2024-02-19T02:10:39+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "karka/ingenious": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=7.2" + }, + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/demo/webman/backend/config/app.php b/demo/webman/backend/config/app.php new file mode 100644 index 0000000000000000000000000000000000000000..4bdfabba3231753dfbff84a8f968ee819b294a44 --- /dev/null +++ b/demo/webman/backend/config/app.php @@ -0,0 +1,27 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use support\Request; + +return [ + 'debug' => true, + 'error_reporting' => E_ALL, + 'default_timezone' => 'Asia/Shanghai', + 'request_class' => Request::class, + 'public_path' => base_path() . DIRECTORY_SEPARATOR . 'public', + 'runtime_path' => base_path(false) . DIRECTORY_SEPARATOR . 'runtime', + 'controller_suffix' => 'Controller', + 'controller_reuse' => false, + 'domain' => ['127.0.0.1'],//允许跨域ip + 'token_name' => 'Authorization',//token名称 +]; diff --git a/demo/webman/backend/config/autoload.php b/demo/webman/backend/config/autoload.php new file mode 100644 index 0000000000000000000000000000000000000000..69a8135e4228a4d35111f72c60eba14adc81d5cf --- /dev/null +++ b/demo/webman/backend/config/autoload.php @@ -0,0 +1,21 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'files' => [ + base_path() . '/app/functions.php', + base_path() . '/support/Request.php', + base_path() . '/support/Response.php', + ] +]; diff --git a/demo/webman/backend/config/bootstrap.php b/demo/webman/backend/config/bootstrap.php new file mode 100644 index 0000000000000000000000000000000000000000..3257ec5df06098155416412aa85517fd8d1c8506 --- /dev/null +++ b/demo/webman/backend/config/bootstrap.php @@ -0,0 +1,19 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + support\bootstrap\Session::class, + support\bootstrap\LaravelDb::class, + Webman\ThinkOrm\ThinkOrm::class, +]; diff --git a/demo/webman/backend/config/container.php b/demo/webman/backend/config/container.php new file mode 100644 index 0000000000000000000000000000000000000000..106b7b4a37e0066b5cf515240a65ee9caf0d747a --- /dev/null +++ b/demo/webman/backend/config/container.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return new Webman\Container; \ No newline at end of file diff --git a/demo/webman/backend/config/database.php b/demo/webman/backend/config/database.php new file mode 100644 index 0000000000000000000000000000000000000000..7dc463a6ca95328d889c19e8adb3e61d639d09b8 --- /dev/null +++ b/demo/webman/backend/config/database.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return []; diff --git a/demo/webman/backend/config/dependence.php b/demo/webman/backend/config/dependence.php new file mode 100644 index 0000000000000000000000000000000000000000..8e964edabcb6ba3ebce02219fb84067c36380824 --- /dev/null +++ b/demo/webman/backend/config/dependence.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return []; \ No newline at end of file diff --git a/demo/webman/backend/config/event.php b/demo/webman/backend/config/event.php new file mode 100644 index 0000000000000000000000000000000000000000..28a3b2ccab10264dea24dc3641fd8d2656e88943 --- /dev/null +++ b/demo/webman/backend/config/event.php @@ -0,0 +1,5 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + '' => support\exception\Handler::class, + 'api' => app\api\exception\Handler::class, +]; \ No newline at end of file diff --git a/demo/webman/backend/config/ingenious.php b/demo/webman/backend/config/ingenious.php new file mode 100644 index 0000000000000000000000000000000000000000..ea50d7490835b80142909870f954ab0ce2cd8000 --- /dev/null +++ b/demo/webman/backend/config/ingenious.php @@ -0,0 +1,16 @@ + str_replace('\\', '/', dirname(__DIR__)) . '/runtime/ingenious/log/',//日志路径tp可以直接助手函数 + 'is_debug' => true,//是否调试模式 + 'redis' => [ + 'host' => '127.0.0.1', + 'port' => '6379', + 'password' => '', + 'expire' => 0, + 'prefix' => 'l:', + 'tag_prefix' => 'ingenious:', + 'select' => 0, + 'timeout' => 0, + ], +]; diff --git a/demo/webman/backend/config/log.php b/demo/webman/backend/config/log.php new file mode 100644 index 0000000000000000000000000000000000000000..7f05de574f38580b47324bd4d65e4dbedd05f994 --- /dev/null +++ b/demo/webman/backend/config/log.php @@ -0,0 +1,32 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'default' => [ + 'handlers' => [ + [ + 'class' => Monolog\Handler\RotatingFileHandler::class, + 'constructor' => [ + runtime_path() . '/logs/webman.log', + 7, //$maxFiles + Monolog\Logger::DEBUG, + ], + 'formatter' => [ + 'class' => Monolog\Formatter\LineFormatter::class, + 'constructor' => [null, 'Y-m-d H:i:s', true], + ], + ] + ], + ], +]; diff --git a/demo/webman/backend/config/middleware.php b/demo/webman/backend/config/middleware.php new file mode 100644 index 0000000000000000000000000000000000000000..61bcbddf6a4675c320df7816c02d26616058a560 --- /dev/null +++ b/demo/webman/backend/config/middleware.php @@ -0,0 +1,18 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + '@' => [ + app\adminapi\middleware\AllowCrossOriginMiddleware::class,//跨域处理 + ], +]; diff --git a/demo/webman/backend/config/plugin/webman/cors/app.php b/demo/webman/backend/config/plugin/webman/cors/app.php new file mode 100644 index 0000000000000000000000000000000000000000..8f9c4260bd2e2c4de071170b4ca5b08c61dc02a1 --- /dev/null +++ b/demo/webman/backend/config/plugin/webman/cors/app.php @@ -0,0 +1,4 @@ + true, +]; \ No newline at end of file diff --git a/demo/webman/backend/config/plugin/webman/cors/middleware.php b/demo/webman/backend/config/plugin/webman/cors/middleware.php new file mode 100644 index 0000000000000000000000000000000000000000..67b99b4d38246fd2f0261bb1d2ee0b73ce431b71 --- /dev/null +++ b/demo/webman/backend/config/plugin/webman/cors/middleware.php @@ -0,0 +1,19 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + '' => [ + \Webman\Cors\CORS::class + ] +]; \ No newline at end of file diff --git a/demo/webman/backend/config/plugin/webman/event/app.php b/demo/webman/backend/config/plugin/webman/event/app.php new file mode 100644 index 0000000000000000000000000000000000000000..8f9c4260bd2e2c4de071170b4ca5b08c61dc02a1 --- /dev/null +++ b/demo/webman/backend/config/plugin/webman/event/app.php @@ -0,0 +1,4 @@ + true, +]; \ No newline at end of file diff --git a/demo/webman/backend/config/plugin/webman/event/bootstrap.php b/demo/webman/backend/config/plugin/webman/event/bootstrap.php new file mode 100644 index 0000000000000000000000000000000000000000..e5b09ba23bbbc658d2b3f66ac18af958e766c4ba --- /dev/null +++ b/demo/webman/backend/config/plugin/webman/event/bootstrap.php @@ -0,0 +1,17 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + Webman\Event\BootStrap::class, +]; diff --git a/demo/webman/backend/config/plugin/webman/event/command.php b/demo/webman/backend/config/plugin/webman/event/command.php new file mode 100644 index 0000000000000000000000000000000000000000..e860cf75aaf55e3fd1f2bf2bd9cdbc1031a862b3 --- /dev/null +++ b/demo/webman/backend/config/plugin/webman/event/command.php @@ -0,0 +1,7 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +global $argv; + +return [ + // File update detection and automatic reload + 'monitor' => [ + 'handler' => process\Monitor::class, + 'reloadable' => false, + 'constructor' => [ + // Monitor these directories + 'monitorDir' => array_merge([ + app_path(), + config_path(), + base_path() . '/process', + base_path() . '/support', + base_path() . '/resource', + base_path() . '/.env', + ], glob(base_path() . '/plugin/*/app'), glob(base_path() . '/plugin/*/config'), glob(base_path() . '/plugin/*/api')), + // Files with these suffixes will be monitored + 'monitorExtensions' => [ + 'php', 'html', 'htm', 'env' + ], + 'options' => [ + 'enable_file_monitor' => !in_array('-d', $argv) && DIRECTORY_SEPARATOR === '/', + 'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/', + ] + ] + ] +]; diff --git a/demo/webman/backend/config/redis.php b/demo/webman/backend/config/redis.php new file mode 100644 index 0000000000000000000000000000000000000000..2f9757a8d47d2f2569dc53c5717a855facb04771 --- /dev/null +++ b/demo/webman/backend/config/redis.php @@ -0,0 +1,22 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'default' => [ + 'host' => '127.0.0.1', + 'password' => null, + 'port' => 6379, + 'database' => 0, + ], +]; diff --git a/demo/webman/backend/config/route.php b/demo/webman/backend/config/route.php new file mode 100644 index 0000000000000000000000000000000000000000..9ca902f15b62c3d4df1562e1894a27ae2dee7d04 --- /dev/null +++ b/demo/webman/backend/config/route.php @@ -0,0 +1,30 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use support\Response; +use Webman\Route; + +// 加载adminapi应用下的路由配置 +require_once app_path('adminapi/config/route.php'); + +//所有预检路由通过 +Route::options('[{path:.+}]', function () { + return response(''); +}); + + +Route::fallback(function (\support\Request $request) { + return json(['code' => 404, 'msg' => '404 not found']); +}); + +Route::disableDefaultRoute(); diff --git a/demo/webman/backend/config/server.php b/demo/webman/backend/config/server.php new file mode 100644 index 0000000000000000000000000000000000000000..84ea0ef690461412d65ff1a224797578a69bcd1c --- /dev/null +++ b/demo/webman/backend/config/server.php @@ -0,0 +1,31 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'listen' => 'http://0.0.0.0:8787', + 'transport' => 'tcp', + 'context' => [], + 'name' => 'webman', + 'count' => cpu_count() * 4, + 'user' => '', + 'group' => '', + 'reusePort' => false, + 'event_loop' => '', + 'stop_timeout' => 2, + 'pid_file' => runtime_path() . '/webman.pid', + 'status_file' => runtime_path() . '/webman.status', + 'stdout_file' => runtime_path() . '/logs/stdout.log', + 'log_file' => runtime_path() . '/logs/workerman.log', + 'max_package_size' => 10 * 1024 * 1024 +]; diff --git a/demo/webman/backend/config/session.php b/demo/webman/backend/config/session.php new file mode 100644 index 0000000000000000000000000000000000000000..043f8c4545fc471758c939f0b27e34b955dfadc4 --- /dev/null +++ b/demo/webman/backend/config/session.php @@ -0,0 +1,65 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use Webman\Session\FileSessionHandler; +use Webman\Session\RedisSessionHandler; +use Webman\Session\RedisClusterSessionHandler; + +return [ + + 'type' => 'file', // or redis or redis_cluster + + 'handler' => FileSessionHandler::class, + + 'config' => [ + 'file' => [ + 'save_path' => runtime_path() . '/sessions', + ], + 'redis' => [ + 'host' => '127.0.0.1', + 'port' => 6379, + 'auth' => '', + 'timeout' => 2, + 'database' => '', + 'prefix' => 'redis_session_', + ], + 'redis_cluster' => [ + 'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'], + 'timeout' => 2, + 'auth' => '', + 'prefix' => 'redis_session_', + ] + ], + + 'session_name' => 'PHPSID', + + 'auto_update_timestamp' => false, + + 'lifetime' => 7*24*60*60, + + 'cookie_lifetime' => 365*24*60*60, + + 'cookie_path' => '/', + + 'domain' => '', + + 'http_only' => true, + + 'secure' => false, + + 'same_site' => '', + + 'gc_probability' => [1, 1000], + +]; diff --git a/demo/webman/backend/config/static.php b/demo/webman/backend/config/static.php new file mode 100644 index 0000000000000000000000000000000000000000..6313679646163f823c041c8e242539dd5d9e3fc8 --- /dev/null +++ b/demo/webman/backend/config/static.php @@ -0,0 +1,23 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Static file settings + */ +return [ + 'enable' => true, + 'middleware' => [ // Static file Middleware + //app\middleware\StaticFile::class, + ], +]; \ No newline at end of file diff --git a/demo/webman/backend/config/thinkorm.php b/demo/webman/backend/config/thinkorm.php new file mode 100644 index 0000000000000000000000000000000000000000..fe2a6dff83cfadf0124a8e54bb583788586895d3 --- /dev/null +++ b/demo/webman/backend/config/thinkorm.php @@ -0,0 +1,36 @@ + 'mysql', + 'connections' => [ + 'mysql' => [ + // 数据库类型 + 'type' => 'mysql', + // 服务器地址 + 'hostname' => '127.0.0.1', + // 数据库名 + 'database' => 'thinkphp_flow', + // 数据库用户名 + 'username' => 'root', + // 数据库密码 + 'password' => 'root', + // 数据库连接端口 + 'hostport' => '3306', + // 数据库连接参数 + 'params' => [ + // 连接超时3秒 + \PDO::ATTR_TIMEOUT => 3, + ], + // 数据库编码默认采用utf8 + 'charset' => 'utf8', + // 数据库表前缀 + 'prefix' => 'lms_clx_', + // 断线重连 + 'break_reconnect' => true, + // 关闭SQL监听日志 + 'trigger_sql' => true, + // 自定义分页类 + 'bootstrap' => '' + ], + ], +]; diff --git a/demo/webman/backend/config/translation.php b/demo/webman/backend/config/translation.php new file mode 100644 index 0000000000000000000000000000000000000000..96589b2b4c2c7ea58e43014a783101ad7ae30ffa --- /dev/null +++ b/demo/webman/backend/config/translation.php @@ -0,0 +1,25 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Multilingual configuration + */ +return [ + // Default language + 'locale' => 'zh_CN', + // Fallback language + 'fallback_locale' => ['zh_CN', 'en'], + // Folder where language files are stored + 'path' => base_path() . '/resource/translations', +]; \ No newline at end of file diff --git a/demo/webman/backend/config/view.php b/demo/webman/backend/config/view.php new file mode 100644 index 0000000000000000000000000000000000000000..e3a7b8561c31e5b9960c6cc13fdc6a5396a9444e --- /dev/null +++ b/demo/webman/backend/config/view.php @@ -0,0 +1,22 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use support\view\Raw; +use support\view\Twig; +use support\view\Blade; +use support\view\ThinkPHP; + +return [ + 'handler' => Raw::class +]; diff --git a/demo/webman/backend/plugin/admin/api/Auth.php b/demo/webman/backend/plugin/admin/api/Auth.php new file mode 100644 index 0000000000000000000000000000000000000000..afe0c801f48f560dc5e708320cb2cf52ef6215f3 --- /dev/null +++ b/demo/webman/backend/plugin/admin/api/Auth.php @@ -0,0 +1,127 @@ +getDefaultProperties(); + $noNeedLogin = $properties['noNeedLogin'] ?? []; + $noNeedAuth = $properties['noNeedAuth'] ?? []; + + // 不需要登录 + if (in_array($action, $noNeedLogin)) { + return true; + } + + // 获取登录信息 + $admin = admin(); + if (!$admin) { + $msg = '请登录'; + // 401是未登录固定的返回码 + $code = 401; + return false; + } + + // 不需要鉴权 + if (in_array($action, $noNeedAuth)) { + return true; + } + + // 当前管理员无角色 + $roles = $admin['roles']; + if (!$roles) { + $msg = '无权限'; + $code = 2; + return false; + } + + // 角色没有规则 + $rules = Role::whereIn('id', $roles)->pluck('rules'); + $rule_ids = []; + foreach ($rules as $rule_string) { + if (!$rule_string) { + continue; + } + $rule_ids = array_merge($rule_ids, explode(',', $rule_string)); + } + if (!$rule_ids) { + $msg = '无权限'; + $code = 2; + return false; + } + + // 超级管理员 + if (in_array('*', $rule_ids)){ + return true; + } + + // 如果action为index,规则里有任意一个以$controller开头的权限即可 + if (strtolower($action) === 'index') { + $rule = Rule::where(function ($query) use ($controller, $action) { + $controller_like = str_replace('\\', '\\\\', $controller); + $query->where('key', 'like', "$controller_like@%")->orWhere('key', $controller); + })->whereIn('id', $rule_ids)->first(); + if ($rule) { + return true; + } + $msg = '无权限'; + $code = 2; + return false; + } + + // 查询是否有当前控制器的规则 + $rule = Rule::where(function ($query) use ($controller, $action) { + $query->where('key', "$controller@$action")->orWhere('key', $controller); + })->whereIn('id', $rule_ids)->first(); + + if (!$rule) { + $msg = '无权限'; + $code = 2; + return false; + } + + return true; + } + +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/api/Install.php b/demo/webman/backend/plugin/admin/api/Install.php new file mode 100644 index 0000000000000000000000000000000000000000..4741becb993b81b5ac683cc86cbe1157705c93d6 --- /dev/null +++ b/demo/webman/backend/plugin/admin/api/Install.php @@ -0,0 +1,93 @@ + static::getMenus()]; + } + + /** + * 获取菜单 + * + * @return array|mixed + */ + public static function getMenus() + { + clearstatcache(); + if (is_file($menu_file = __DIR__ . '/../config/menu.php')) { + $menus = include $menu_file; + return $menus ?: []; + } + return []; + } + + /** + * 删除不需要的菜单 + * + * @param $previous_menus + * @return void + */ + public static function removeUnnecessaryMenus($previous_menus) + { + $menus_to_remove = array_diff(Menu::column($previous_menus, 'name'), Menu::column(static::getMenus(), 'name')); + foreach ($menus_to_remove as $name) { + Menu::delete($name); + } + } + +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/api/Menu.php b/demo/webman/backend/plugin/admin/api/Menu.php new file mode 100644 index 0000000000000000000000000000000000000000..c482657dc0fe2eed8981526dc5c5207adbbfbf58 --- /dev/null +++ b/demo/webman/backend/plugin/admin/api/Menu.php @@ -0,0 +1,150 @@ +first(); + return $menu ? $menu->toArray() : null; + } + + /** + * 根据id获得菜单 + * @param $id + * @return array + */ + public static function find($id): array + { + return Rule::find($id)->toArray(); + } + + /** + * 添加菜单 + * @param array $menu + * @return int + */ + public static function add(array $menu) + { + $item = new Rule; + foreach ($menu as $key => $value) { + $item->$key = $value; + } + $item->save(); + return $item->id; + } + + /** + * 导入菜单 + * @param array $menu_tree + * @return void + */ + public static function import(array $menu_tree) + { + if (is_numeric(key($menu_tree)) && !isset($menu_tree['key'])) { + foreach ($menu_tree as $item) { + static::import($item); + } + return; + } + $children = $menu_tree['children'] ?? []; + unset($menu_tree['children']); + if ($old_menu = Menu::get($menu_tree['key'])) { + $pid = $old_menu['id']; + Rule::where('key', $menu_tree['key'])->update($menu_tree); + } else { + $pid = static::add($menu_tree); + } + foreach ($children as $menu) { + $menu['pid'] = $pid; + static::import($menu); + } + } + + /** + * 删除菜单 + * @param $key + * @return void + */ + public static function delete($key) + { + $item = Rule::where('key', $key)->first(); + if (!$item) { + return; + } + // 子规则一起删除 + $delete_ids = $children_ids = [$item['id']]; + while($children_ids) { + $children_ids = Rule::whereIn('pid', $children_ids)->pluck('id')->toArray(); + $delete_ids = array_merge($delete_ids, $children_ids); + } + Rule::whereIn('id', $delete_ids)->delete(); + } + + + /** + * 获取菜单中某个(些)字段的值 + * @param $menu + * @param null $column + * @param null $index + * @return array|mixed + */ + public static function column($menu, $column = null, $index = null) + { + $values = []; + if (is_numeric(key($menu)) && !isset($menu['key'])) { + foreach ($menu as $item) { + $values = array_merge($values, static::column($item, $column, $index)); + } + return $values; + } + + $children = $menu['children'] ?? []; + unset($menu['children']); + if ($column === null) { + if ($index) { + $values[$menu[$index]] = $menu; + } else { + $values[] = $menu; + } + } else { + if (is_array($column)) { + $item = []; + foreach ($column as $f) { + $item[$f] = $menu[$f] ?? null; + } + if ($index) { + $values[$menu[$index]] = $item; + } else { + $values[] = $item; + } + } else { + $value = $menu[$column] ?? null; + if ($index) { + $values[$menu[$index]] = $value; + } else { + $values[] = $value; + } + } + } + foreach ($children as $child) { + $values = array_merge($values, static::column($child, $column, $index)); + } + return $values; + } + +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/api/Middleware.php b/demo/webman/backend/plugin/admin/api/Middleware.php new file mode 100644 index 0000000000000000000000000000000000000000..20d5540e50729e75152af2e863a3dc7d1316672c --- /dev/null +++ b/demo/webman/backend/plugin/admin/api/Middleware.php @@ -0,0 +1,55 @@ +controller; + $action = $request->action; + + $code = 0; + $msg = ''; + if (!Auth::canAccess($controller, $action, $code, $msg)) { + if ($request->expectsJson()) { + $response = json(['code' => $code, 'msg' => $msg, 'type' => 'error']); + } else { + if ($code === 401) { + $response = response(<< + if (self !== top) { + parent.location.reload(); + } + +EOF + ); + } else { + $request->app = ''; + $request->plugin = 'admin'; + $response = view('common/error/403')->withStatus(403); + } + } + } else { + $response = $request->method() == 'OPTIONS' ? response('') : $handler($request); + } + return $response; + } + +} diff --git a/demo/webman/backend/plugin/admin/app/common/Auth.php b/demo/webman/backend/plugin/admin/app/common/Auth.php new file mode 100644 index 0000000000000000000000000000000000000000..b6d5d7159b260db97444558a970ff064212adf26 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/common/Auth.php @@ -0,0 +1,67 @@ +pluck('rules')->toArray(); + if ($rules && in_array('*', $rules)) { + return Role::pluck('id')->toArray(); + } + + $roles = Role::get(); + $tree = new Tree($roles); + $descendants = $tree->getDescendant($role_ids, $with_self); + return array_column($descendants, 'id'); + } + + /** + * 获取权限范围内的所有管理员id + * @param bool $with_self + * @return array + */ + public static function getScopeAdminIds(bool $with_self = false): array + { + $role_ids = static::getScopeRoleIds(); + $admin_ids = AdminRole::whereIn('role_id', $role_ids)->pluck('admin_id')->toArray(); + if ($with_self) { + $admin_ids[] = admin_id(); + } + return array_unique($admin_ids); + } + + /** + * 是否是超级管理员 + * @param int $admin_id + * @return bool + */ + public static function isSupperAdmin(int $admin_id = 0): bool + { + if (!$admin_id) { + if (!$roles = admin('roles')) { + return false; + } + } else { + $roles = AdminRole::where('admin_id', $admin_id)->pluck('role_id'); + } + $rules = Role::whereIn('id', $roles)->pluck('rules'); + return $rules && in_array('*', $rules->toArray()); + } + +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/app/common/Layui.php b/demo/webman/backend/plugin/admin/app/common/Layui.php new file mode 100644 index 0000000000000000000000000000000000000000..5778bc56c1b7fe581731430ee06866110e5fa2db --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/common/Layui.php @@ -0,0 +1,1154 @@ +htmlContent); + } + + /** + * 获取生成的js代码 + * @param $indent + * @return string + */ + public function js($indent = 0): string + { + return str_replace("\n", "\n" . str_repeat(' ', $indent), $this->jsContent); + } + + /** + * 获取控件及相关参数 + * @param $options + * @return array + */ + protected function options($options): array + { + array_walk_recursive($options, function(&$item, $key){ + if (is_string($item)) { + $item = htmlspecialchars($item); + if ($key === 'url') { + $item = str_replace('&', '&', $item); + } + } + }); + $field = $options['field']??''; + $props = !empty($options['props']) ? $options['props'] : []; + $verify_string = !empty($props['lay-verify']) ? ' lay-verify="'.$props['lay-verify'].'"' : ''; + $required_string = strpos($verify_string, 'required') ? ' required' : ''; + $label = !empty($options['label']) ? '' : ''; + $value = $props['value'] ?? ''; + $class = $props['class'] ?? 'layui-input-block'; + + return [$label, $field, $value, $props, $verify_string, $required_string, $class]; + } + + /** + * input输入框 + * @param $options + * @return void + */ + public function input($options) + { + [$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options); + + $placeholder_string = !empty($props['placeholder']) ? ' placeholder="'.$props['placeholder'].'"' : ''; + $autocomplete_string = !empty($props['autocomplete']) ? ' autocomplete="'.$props['autocomplete'].'"' : ''; + $disabled_string = !empty($props['disabled']) ? ' disabled' : ''; + $type = $props['type'] ?? 'text'; + + $this->htmlContent .= << + $label +
                                                              + +
                                                              +
                                                              + +EOF; + } + + /** + * input数字输入框 + * @param $options + * @return void + */ + public function inputNumber($options) + { + $options['props']['type'] = 'number'; + $this->input($options); + } + + /** + * 输入框范围 + * @param $options + * @return void + */ + public function inputRange($options) + { + [$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options); + $type = $props['type'] ?? 'text'; + + $this->htmlContent .= << + $label +
                                                              +
                                                              + + - + +
                                                              +
                                                              +
                                                              + +EOF; + } + + /** + * 输入框模糊查询 + * @param $options + * @return void + */ + public function inputLike($options) + { + [$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options); + $type = $props['type'] ?? 'text'; + + $this->htmlContent .= << + $label +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + +EOF; + } + + /** + * 数字输入框范围 + * @param $options + * @return void + */ + public function inputNumberRange($options) + { + $options['props']['type'] = 'number'; + $this->inputRange($options); + } + + /** + * 数字输入框模糊查询 + * @param $options + * @return void + */ + public function inputNumberLike($options) + { + $options['props']['type'] = 'number'; + $this->inputLike($options); + } + + /** + * 密码输入框 + * @param $options + * @return void + */ + public function inputPassword($options) + { + $options['props']['type'] = 'password'; + $this->input($options); + } + + /** + * 文本域 + * @param $options + * @return void + */ + public function textArea($options) + { + [$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options); + + $placeholder_string = !empty($props['placeholder']) ? ' placeholder="'.$props['placeholder'].'"' : ''; + $disabled_string = !empty($props['disabled']) ? ' disabled' : ''; + + $this->htmlContent .= << + $label +
                                                              + +
                                                              +
                                                              + +EOF; + } + + /** + * 富文本 + * @param $options + * @return void + */ + public function richText($options) + { + [$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options); + + $placeholder_string = !empty($props['placeholder']) ? ' placeholder="'.$props['placeholder'].'"' : ''; + $disabled_string = !empty($props['disabled']) ? ' disabled' : ''; + $id = $field; + + $this->htmlContent .= << + $label +
                                                              + +
                                                              +
                                                              + +EOF; + + $options_string = ''; + if (!isset($props['images_upload_url'])) { + $props['images_upload_url'] = '/app/admin/upload/image'; + } + foreach ($props as $key => $item) { + if (is_array($item)) { + $item = json_encode($item, JSON_UNESCAPED_UNICODE); + $options_string .= "\n '$key': $item,"; + } else { + $options_string .= "\n '$key': \"$item\","; + } + } + $this->jsContent .= <<options($options); + + $placeholder_string = !empty($props['placeholder']) ? ' placeholder="'.$props['placeholder'].'"' : ''; + $autocomplete_string = !empty($props['autocomplete']) ? ' autocomplete="'.$props['autocomplete'].'"' : ''; + $disabled_string = !empty($props['disabled']) ? ' disabled' : ''; + $type = $props['type'] ?? 'text'; + if (empty($value)){ + $value='{}'; + } + $this->htmlContent .= << + $label +
                                                              + +
                                                              +
                                                              +EOF; + $this->jsContent .= <<options($options); + + $props['accept'] = $props['accept'] ?? 'file'; + $props['url'] = $props['url'] ?? '/app/admin/upload/file'; + $id = $this->createId($field); + + $props['field'] = $props['field'] ?? '__file__'; + unset($props['lay-verify']); + $options_string = ''; + foreach ($props as $key => $item) { + if (is_array($item)) { + $item = json_encode($item, JSON_UNESCAPED_UNICODE); + $options_string .= "\n $key: $item,"; + } else { + $options_string .= "\n $key: \"$item\","; + } + } + + $this->htmlContent .= << + $label +
                                                              + $value + + + +
                                                              +
                                                              + +EOF; + $this->jsContent .= <<options($options); + $props['acceptMime'] = $props['acceptMime'] ?? 'image/gif,image/jpeg,image/jpg,image/png'; + $props['url'] = $props['url'] ?? '/app/admin/upload/image'; + $id = $this->createId($field); + + unset($props['lay-verify']); + $props['field'] = $props['field'] ?? '__file__'; + $options_string = ''; + foreach ($props as $key => $item) { + if (is_array($item)) { + $item = json_encode($item, JSON_UNESCAPED_UNICODE); + $options_string .= "\n $key: $item,"; + } else { + $options_string .= "\n $key: \"$item\","; + } + } + + $this->htmlContent .= << + $label +
                                                              + + + + +
                                                              +
                                                              + +EOF; + $this->jsContent .= << 0) return layui.layer.msg(res.msg); + this.item.prev().val(res.data.url).prev().attr("src", res.data.url); + } + }); +}); + +EOF; + + } + + /** + * 日期时间选择组件 + * @param $options + * @return void + */ + public function dateTimePicker($options) + { + $options['props']['type'] = 'datetime'; + $this->datePicker($options); + } + + /** + * 日期选择组件 + * @param $options + * @return void + */ + public function datePicker($options) + { + [$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options); + $value_string = $value ? ' value="'.$value.'"' : ''; + $options_string = ''; + unset($props['required'], $props['lay-verify'], $props['value']); + foreach ($props as $key => $item) { + if (is_array($item)) { + continue; + } + $options_string .= "\n $key: \"$item\","; + } + $id = $this->createId($field); + + $this->htmlContent .= << + $label +
                                                              + +
                                                              +
                                                              + +EOF; + $this->jsContent .= <<datePickerRange($options); + } + + /** + * 日期范围选择组件 + * @param $options + * @return void + */ + public function datePickerRange($options) + { + [$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options); + if (!isset($options['props']['type'])) { + $options['props']['type'] = 'date'; + } + $options_string = ''; + unset($props['required'], $props['lay-verify'], $props['value']); + foreach ($props as $key => $item) { + if (is_array($item)) { + continue; + } + $options_string .= "\n $key: \"$item\","; + } + $id = $this->createId($field); + $id_start = "$id-date-start"; + $id_end = "$id-date-end"; + $this->htmlContent .= << + $label +
                                                              +
                                                              + + - + +
                                                              +
                                                              +
                                                              + +EOF; + $this->jsContent .= <<options($options); + + $value_string = $value ? ' value="'.$value.'"' : ''; + $id = $this->createId($field); + $options_string = ''; + foreach ($props as $key => $item) { + if (is_array($item)) { + $item = json_encode($item, JSON_UNESCAPED_UNICODE); + $options_string .= "\n $key: $item,"; + } else { + $options_string .= "\n $key: \"$item\","; + } + } + + $this->htmlContent .= << + $label +
                                                              + +
                                                              +
                                                              + +EOF; + + $this->jsContent .= <<options($options); + + $value = (int)$value; + $disabled_string = !empty($props['disabled']) ? ' disabled' : ''; + $lay_text = !empty($props['lay-text']) ? "lay-text=\"{$props['lay-text']}\"" : ''; + + $id = $this->createId($field); + + $this->htmlContent .= << + $label +
                                                              + + +
                                                              +
                                                              + +EOF; + + $this->jsContent .= << 'hidden', + 'label' => [ + 'type' => 'text', + ] + ], $options['props']['model'] ?? []); + $options['props']['clickClose'] = $options['props']['clickClose'] ?? true; + $options['props']['radio'] = $options['props']['radio'] ?? true; + $this->apiSelect($options); + } + + /** + * 下拉多选组件 + * @return void + */ + public function selectMulti($options) + { + $options['props']['toolbar'] = array_merge_recursive([ + 'show' => true, + 'list' => [ 'ALL', 'CLEAR', 'REVERSE' ] + ], $options['props']['toolbar'] ?? []); + $this->apiSelect($options); + } + + /** + * 树单选组件 + * @return void + */ + public function treeSelect($options) + { + $options['props']['model'] = array_merge_recursive([ + 'icon' => 'hidden', + 'label' => [ + 'type' => 'text', + ] + ], $options['props']['model'] ?? []); + $options['props']['clickClose'] = $options['props']['clickClose'] ?? true; + $options['props']['radio'] = $options['props']['radio'] ?? true; + $options['props']['tree'] = array_merge_recursive([ + '$show' => true, + '$strict' => false, + '$clickCheck' => true, + '$clickExpand' => false, + '$expandedKeys' => '$initValue' + ], $options['props']['tree'] ?? []); + $this->apiSelect($options); + } + + /** + * 树多选组件 + * @return void + */ + public function treeSelectMulti($options) + { + $options['props']['tree'] = array_merge_recursive(['show' => true, + '$expandedKeys' => '$initValue'], $options['props']['tree'] ?? []); + $options['props']['toolbar'] = array_merge_recursive([ + '$show' => true, + '$list' => [ 'ALL', 'CLEAR', 'REVERSE' ] + ], $options['props']['toolbar'] ?? []); + $this->apiSelect($options); + } + + /** + * 选择框,支持单选、多选、树形选择 + * @see https://maplemei.gitee.io/xm-select/ + * @param $options + * @return void + */ + public function apiSelect($options) + { + [$select_label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options); + + $default_value_string = isset($props['initValue']) && $props['initValue'] != '' ? $props['initValue'] : $value; + $url = $props['url'] ?? ''; + $options_string = ''; + if (isset($props['lay-verify'])) { + $props['layVerify'] = $props['lay-verify']; + } + unset($props['lay-verify'], $props['url']); + foreach ($props as $key => $item) { + if (is_array($item)) { + $item = json_encode($item, JSON_UNESCAPED_UNICODE); + $item = preg_replace('/"\$([^"]+)"/', '$1', $item); + $options_string .= "\n".($url?' ':' ')."$key: $item,"; + } else if (is_string($item)) { + $options_string .= "\n".($url?' ':' ')."$key: \"$item\","; + } else { + $options_string .= "\n".($url?' ':' ')."$key: ".var_export($item, true).","; + } + } + + $id = $this->createId($field); + if ($url) { + $this->jsContent .= <<jsContent .= <<htmlContent .= << + $select_label +
                                                              +
                                                              +
                                                              + + +EOF; + + } + + /** + * 构建表单 + * @param $table + * @param string $type + * @return Layui + * @throws BusinessException + */ + public static function buildForm($table, string $type = 'insert'): Layui + { + if (!in_array($type, ['insert', 'update', 'search'])) { + $type = 'insert'; + } + $filter = $type === 'search' ? 'searchable' : 'form_show'; + $form = new Layui(); + $schema = Util::getSchema($table); + $forms = $schema['forms']; + $columns = $schema['columns']; + $primary_key = $schema['table']['primary_key'][0] ?? null; + + foreach ($forms as $key => $info) { + if (empty($info[$filter])) { + continue; + } + $field = $info['field']; + $default = $columns[$key]['default']; + $control = strtolower($info['control']); + $auto_increment = $columns[$key]['auto_increment']; + // 搜索框里上传组件替换为input + if ($type == 'search' && in_array($control, ['upload', 'uploadimg'])) { + $control = 'input'; + $info['control_args'] = ''; + } + if ($type === 'search' && $control === 'switch') { + $control = 'select'; + if (preg_match('/lay-text:(.+?)\|([^;]+)/', $info['control_args'], $matches)) { + $info['control_args'] = 'data:1:' . $matches[1] . ',0:' . $matches[2]; + } else { + $info['control_args'] = 'data:1:是,0:否'; + } + } + + $props = Util::getControlProps($control, $info['control_args']); + // 增加修改记录验证必填项 + if ($filter == 'form_show' && !$columns[$key]['nullable'] && $default === null && ($field !== 'password' || $type === 'insert')) { + if (!isset($props['lay-verify'])) { + $props['lay-verify'] = 'required'; + // 非类似字符串类型不允许传空 + } elseif (!in_array($columns[$key]['type'], ['string', 'text', 'mediumText', 'longText', 'char', 'binary', 'json']) + && strpos($props['lay-verify'], 'required') === false) { + $props['lay-verify'] = 'required|' . $props['lay-verify']; + } + } + // 增加记录显示默认值 + if ($type === 'insert' && !isset($props['value']) && $default !== null) { + $props['value'] = $default; + } + // 主键是自增字段或者表单是更新类型不显示主键 + if ($primary_key && $field == $primary_key && (($type == 'insert' && $auto_increment) || $type == 'update')) { + continue; + } + // 查询类型 + if ($type == 'search') { + if ($info['search_type'] == 'between' && method_exists($form, "{$control}Range")) { + $control = "{$control}Range"; + } elseif ($info['search_type'] == 'like' && method_exists($form, "{$control}Like")) { + $control = "{$control}Like"; + } + } + // 查询类型移除lay-verify + if ($type == 'search' && !empty($props['lay-verify'])) { + $props['lay-verify'] = ''; + } + + $options = [ + 'label' => $info['comment'] ?: $field, + 'field' => $field, + 'props' => $props, + ]; + + $form->{$control}($options); + } + return $form; + } + + /** + * 构建表格 + * @param $table + * @param int $indent + * @return array|string|string[] + * @throws BusinessException + */ + public static function buildTable($table, int $indent = 0) + { + $schema = Util::getSchema($table); + $forms = $schema['forms']; + + $codes = ''; + $cols = ''; + $api = ''; + $api_result = ''; + + foreach ($forms as $info) { + $title = $info['comment'] ?: $info['field']; + $hide_str = $info['list_show'] ? '' : "\n hide: true,"; + $sort_str = $info['enable_sort'] ? "\n sort: true," : ''; + $field = $info['field']; + $templet = ''; + $schema = <<'; + } +EOF; + break; + + case 'iconpicker': + $templet = <<
                                                              '; + } +EOF; + break; + case 'upload': + $templet = <<' + util.escape(d['$field']) + ''; + } +EOF; + break; + case 'uploadimage': + $templet = <<' + } +EOF; + break; + + } + + if (in_array($control, ['select', 'selectmulti', 'treeselect', 'treeselectmulti'])) { + $props = Util::getControlProps($info['control'], $info['control_args']); + + if (isset($props['url'])) { + $api .= "\napis.push([\"$field\", \"{$props['url']}\"]);"; + $api_result .= "\napiResults[\"$field\"] = [];"; + } else if (!empty($props['data'])) { + $options = []; + foreach ($props['data'] as $option) { + if (isset($option['value']) && isset($option['name'])) { + $options[$option['value']] = $option['name']; + } + } + $api_result .= "\napiResults[\"$field\"] = " . json_encode($options, JSON_UNESCAPED_UNICODE) . ";"; + } else { + $api_result .= "\napiResults[\"$field\"] = [];"; + } + + $templet = <<pidName = $pid_name; + if (is_object($data) && method_exists($data, 'toArray')) { + $this->data = $data->toArray(); + } else { + $this->data = (array)$data; + $this->data = array_map(function ($item) { + if (is_object($item) && method_exists($item, 'toArray')) { + return $item->toArray(); + } + return $item; + }, $this->data); + } + $this->hashTree = $this->getHashTree(); + } + + /** + * 获取子孙节点 + * @param array $include + * @param bool $with_self + * @return array + */ + public function getDescendant(array $include, bool $with_self = false): array + { + $items = []; + foreach ($include as $id) { + if (!isset($this->hashTree[$id])) { + return []; + } + if ($with_self) { + $item = $this->hashTree[$id]; + unset($item['children']); + $items[$item['id']] = $item; + } + foreach ($this->hashTree[$id]['children'] ?? [] as $item) { + unset($item['children']); + $items[$item['id']] = $item; + foreach ($this->getDescendant([$item['id']]) as $it) { + $items[$it['id']] = $it; + } + } + } + return array_values($items); + } + + /** + * 获取哈希树 + * @param array $data + * @return array + */ + protected function getHashTree(array $data = []): array + { + $data = $data ?: $this->data; + $hash_tree = []; + foreach ($data as $item) { + $hash_tree[$item['id']] = $item; + } + foreach ($hash_tree as $index => $item) { + if ($item[$this->pidName] && isset($hash_tree[$item[$this->pidName]])) { + $hash_tree[$item[$this->pidName]]['children'][$hash_tree[$index]['id']] = &$hash_tree[$index]; + } + } + return $hash_tree; + } + + /** + * 获取树 + * @param array $include + * @param int $type + * @return array|null + */ + public function getTree(array $include = [], int $type = 1): ?array + { + // $type === static::EXCLUDE_ANCESTORS + if ($type === static::EXCLUDE_ANCESTORS) { + $items = []; + $include = array_unique($include); + foreach ($include as $id) { + if (!isset($this->hashTree[$id])) { + return []; + } + $items[] = $this->hashTree[$id]; + } + return static::arrayValues($items); + } + + // $type === static::INCLUDE_ANCESTORS + $hash_tree = $this->hashTree; + $items = []; + if ($include) { + $map = []; + foreach ($include as $id) { + if (!isset($hash_tree[$id])) { + continue; + } + $item = $hash_tree[$id]; + $max_depth = 100; + while ($max_depth-- > 0 && $item[$this->pidName] && isset($hash_tree[$item[$this->pidName]])) { + $last_item = $item; + $pid = $item[$this->pidName]; + $item = $hash_tree[$pid]; + $item_id = $item['id']; + if (empty($map[$item_id])) { + $map[$item_id] = 1; + $hash_tree[$pid]['children'] = []; + } + $hash_tree[$pid]['children'][$last_item['id']] = $last_item; + $item = $hash_tree[$pid]; + } + $items[$item['id']] = $item; + } + } else { + $items = $hash_tree; + } + $formatted_items = []; + foreach ($items as $item) { + if (!$item[$this->pidName] || !isset($hash_tree[$item[$this->pidName]])) { + $formatted_items[] = $item; + } + } + + return static::arrayValues($formatted_items); + } + + /** + * 递归重建数组下标 + * @param $array + * @return array + */ + public static function arrayValues($array): array + { + if (!$array) { + return []; + } + if (!isset($array['children'])) { + $current = current($array); + if (!is_array($current)) { + return $array; + } + $tree = array_values($array); + foreach ($tree as $index => $item) { + $tree[$index] = static::arrayValues($item); + } + return $tree; + } + $array['children'] = array_values($array['children']); + foreach ($array['children'] as $index => $child) { + $array['children'][$index] = static::arrayValues($child); + } + return $array; + } + +} diff --git a/demo/webman/backend/plugin/admin/app/common/Util.php b/demo/webman/backend/plugin/admin/app/common/Util.php new file mode 100644 index 0000000000000000000000000000000000000000..cacabfe3f196476840e4c36d26a330e7413cb566 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/common/Util.php @@ -0,0 +1,567 @@ +getPdo()->quote($var, \PDO::PARAM_STR); + } + + /** + * 检查表名是否合法 + * @param string $table + * @return string + * @throws BusinessException + */ + public static function checkTableName(string $table): string + { + if (!preg_match('/^[a-zA-Z_0-9]+$/', $table)) { + throw new BusinessException('表名不合法'); + } + return $table; + } + + /** + * 变量或数组中的元素只能是字母数字下划线组合 + * @param $var + * @return mixed + * @throws BusinessException + */ + public static function filterAlphaNum($var) + { + $vars = (array)$var; + array_walk_recursive($vars, function ($item) { + if (is_string($item) && !preg_match('/^[a-zA-Z_0-9]+$/', $item)) { + throw new BusinessException('参数不合法'); + } + }); + return $var; + } + + /** + * 变量或数组中的元素只能是字母数字 + * @param $var + * @return mixed + * @throws BusinessException + */ + public static function filterNum($var) + { + $vars = (array)$var; + array_walk_recursive($vars, function ($item) { + if (is_string($item) && !preg_match('/^[0-9]+$/', $item)) { + throw new BusinessException('参数不合法'); + } + }); + return $var; + } + + /** + * 检测是否是合法URL Path + * @param $var + * @return string + * @throws BusinessException + */ + public static function filterUrlPath($var): string + { + if (!is_string($var) || !preg_match('/^[a-zA-Z0-9_\-\/&?.]+$/', $var)) { + throw new BusinessException('参数不合法'); + } + return $var; + } + + /** + * 检测是否是合法Path + * @param $var + * @return string + * @throws BusinessException + */ + public static function filterPath($var): string + { + if (!is_string($var) || !preg_match('/^[a-zA-Z0-9_\-\/]+$/', $var)) { + throw new BusinessException('参数不合法'); + } + return $var; + } + + /** + * 类转换为url path + * @param $controller_class + * @return false|string + */ + static function controllerToUrlPath($controller_class) + { + $key = strtolower($controller_class); + $action = ''; + if (strpos($key, '@')) { + [$key, $action] = explode( '@', $key, 2); + } + $prefix = 'plugin'; + $paths = explode('\\', $key); + if (count($paths) < 2) { + return false; + } + $base = ''; + if (strpos($key, "$prefix\\") === 0) { + if (count($paths) < 4) { + return false; + } + array_shift($paths); + $plugin = array_shift($paths); + $base = "/app/$plugin/"; + } + array_shift($paths); + foreach ($paths as $index => $path) { + if ($path === 'controller') { + unset($paths[$index]); + } + } + $suffix = 'controller'; + $code = $base . implode('/', $paths); + if (substr($code, -strlen($suffix)) === $suffix) { + $code = substr($code, 0, -strlen($suffix)); + } + return $action ? "$code/$action" : $code; + } + + /** + * 转换为驼峰 + * @param string $value + * @return string + */ + public static function camel(string $value): string + { + static $cache = []; + $key = $value; + + if (isset($cache[$key])) { + return $cache[$key]; + } + + $value = ucwords(str_replace(['-', '_'], ' ', $value)); + + return $cache[$key] = str_replace(' ', '', $value); + } + + /** + * 转换为小驼峰 + * @param $value + * @return string + */ + public static function smCamel($value): string + { + return lcfirst(static::camel($value)); + } + + /** + * 获取注释中第一行 + * @param $comment + * @return false|mixed|string + */ + public static function getCommentFirstLine($comment) + { + if ($comment === false) { + return false; + } + foreach (explode("\n", $comment) as $str) { + if ($s = trim($str, "*/\ \t\n\r\0\x0B")) { + return $s; + } + } + return $comment; + } + + /** + * 表单类型到插件的映射 + * @return \string[][] + */ + public static function methodControlMap(): array + { + return [ + //method=>[控件] + 'integer' => ['InputNumber'], + 'string' => ['Input'], + 'text' => ['TextArea'], + 'date' => ['DatePicker'], + 'enum' => ['Select'], + 'float' => ['Input'], + + 'tinyInteger' => ['InputNumber'], + 'smallInteger' => ['InputNumber'], + 'mediumInteger' => ['InputNumber'], + 'bigInteger' => ['InputNumber'], + + 'unsignedInteger' => ['InputNumber'], + 'unsignedTinyInteger' => ['InputNumber'], + 'unsignedSmallInteger' => ['InputNumber'], + 'unsignedMediumInteger' => ['InputNumber'], + 'unsignedBigInteger' => ['InputNumber'], + + 'decimal' => ['Input'], + 'double' => ['Input'], + + 'mediumText' => ['TextArea'], + 'longText' => ['TextArea'], + + 'dateTime' => ['DateTimePicker'], + + 'time' => ['DateTimePicker'], + 'timestamp' => ['DateTimePicker'], + + 'char' => ['Input'], + + 'binary' => ['Input'], + + 'json' => ['input'] + ]; + } + + /** + * 数据库类型到插件的转换 + * @param $type + * @return string + */ + public static function typeToControl($type): string + { + if (stripos($type, 'int') !== false) { + return 'inputNumber'; + } + if (stripos($type, 'time') !== false || stripos($type, 'date') !== false) { + return 'dateTimePicker'; + } + if (stripos($type, 'text') !== false) { + return 'textArea'; + } + if ($type === 'enum') { + return 'select'; + } + return 'input'; + } + + /** + * 数据库类型到表单类型的转换 + * @param $type + * @param $unsigned + * @return string + */ + public static function typeToMethod($type, $unsigned = false) + { + if (stripos($type, 'int') !== false) { + $type = str_replace('int', 'Integer', $type); + return $unsigned ? "unsigned" . ucfirst($type) : lcfirst($type); + } + $map = [ + 'int' => 'integer', + 'varchar' => 'string', + 'mediumtext' => 'mediumText', + 'longtext' => 'longText', + 'datetime' => 'dateTime', + ]; + return $map[$type] ?? $type; + } + + /** + * 按表获取摘要 + * @param $table + * @param null $section + * @return array|mixed + * @throws BusinessException + */ + public static function getSchema($table, $section = null) + { + Util::checkTableName($table); + $database = config('database.connections')['plugin.admin.mysql']['database']; + $schema_raw = $section !== 'table' ? Util::db()->select("select * from information_schema.COLUMNS where TABLE_SCHEMA = '$database' and table_name = '$table' order by ORDINAL_POSITION") : []; + $forms = []; + $columns = []; + foreach ($schema_raw as $item) { + $field = $item->COLUMN_NAME; + $columns[$field] = [ + 'field' => $field, + 'type' => Util::typeToMethod($item->DATA_TYPE, (bool)strpos($item->COLUMN_TYPE, 'unsigned')), + 'comment' => $item->COLUMN_COMMENT, + 'default' => $item->COLUMN_DEFAULT, + 'length' => static::getLengthValue($item), + 'nullable' => $item->IS_NULLABLE !== 'NO', + 'primary_key' => $item->COLUMN_KEY === 'PRI', + 'auto_increment' => strpos($item->EXTRA, 'auto_increment') !== false + ]; + + $forms[$field] = [ + 'field' => $field, + 'comment' => $item->COLUMN_COMMENT, + 'control' => static::typeToControl($item->DATA_TYPE), + 'form_show' => $item->COLUMN_KEY !== 'PRI', + 'list_show' => true, + 'enable_sort' => false, + 'searchable' => false, + 'search_type' => 'normal', + 'control_args' => '', + ]; + } + $table_schema = $section == 'table' || !$section ? Util::db()->select("SELECT TABLE_COMMENT FROM information_schema.`TABLES` WHERE TABLE_SCHEMA='$database' and TABLE_NAME='$table'") : []; + $indexes = !$section || in_array($section, ['keys', 'table']) ? Util::db()->select("SHOW INDEX FROM `$table`") : []; + $keys = []; + $primary_key = []; + foreach ($indexes as $index) { + $key_name = $index->Key_name; + if ($key_name == 'PRIMARY') { + $primary_key[] = $index->Column_name; + continue; + } + if (!isset($keys[$key_name])) { + $keys[$key_name] = [ + 'name' => $key_name, + 'columns' => [], + 'type' => $index->Non_unique == 0 ? 'unique' : 'normal' + ]; + } + $keys[$key_name]['columns'][] = $index->Column_name; + } + + $data = [ + 'table' => ['name' => $table, 'comment' => $table_schema[0]->TABLE_COMMENT ?? '', 'primary_key' => $primary_key], + 'columns' => $columns, + 'forms' => $forms, + 'keys' => array_reverse($keys, true) + ]; + + $schema = Option::where('name', "table_form_schema_$table")->value('value'); + $form_schema_map = $schema ? json_decode($schema, true) : []; + + foreach ($data['forms'] as $field => $item) { + if (isset($form_schema_map[$field])) { + $data['forms'][$field] = $form_schema_map[$field]; + } + } + + return $section ? $data[$section] : $data; + } + + /** + * 获取字段长度或默认值 + * @param $schema + * @return mixed|string + */ + public static function getLengthValue($schema) + { + $type = $schema->DATA_TYPE; + if (in_array($type, ['float', 'decimal', 'double'])) { + return "{$schema->NUMERIC_PRECISION},{$schema->NUMERIC_SCALE}"; + } + if ($type === 'enum') { + return implode(',', array_map(function($item){ + return trim($item, "'"); + }, explode(',', substr($schema->COLUMN_TYPE, 5, -1)))); + } + if (in_array($type, ['varchar', 'text', 'char'])) { + return $schema->CHARACTER_MAXIMUM_LENGTH; + } + if (in_array($type, ['time', 'datetime', 'timestamp'])) { + return $schema->CHARACTER_MAXIMUM_LENGTH; + } + return ''; + } + + /** + * 获取控件参数 + * @param $control + * @param $control_args + * @return array + */ + public static function getControlProps($control, $control_args): array + { + if (!$control_args) { + return []; + } + $control = strtolower($control); + $props = []; + $split = explode(';', $control_args); + foreach ($split as $item) { + $pos = strpos($item, ':'); + if ($pos === false) { + continue; + } + $name = trim(substr($item, 0, $pos)); + $values = trim(substr($item, $pos + 1)); + // values = a:v,c:d + $pos = strpos($values, ':'); + if ($pos !== false) { + $options = explode(',', $values); + $values = []; + foreach ($options as $option) { + [$v, $n] = explode(':', $option); + if (in_array($control, ['select', 'selectmulti', 'treeselect', 'treemultiselect']) && $name == 'data') { + $values[] = ['value' => $v, 'name' => $n]; + } else { + $values[$v] = $n; + } + } + } + $props[$name] = $values; + } + return $props; + + } + + /** + * 获取某个composer包的版本 + * @param string $package + * @return mixed|string + */ + public static function getPackageVersion(string $package) + { + $installed_php = base_path('vendor/composer/installed.php'); + if (is_file($installed_php)) { + $packages = include $installed_php; + } + return substr($packages['versions'][$package]['version'] ?? 'unknown ', 0, -2); + } + + + /** + * Reload webman + * @return bool + */ + public static function reloadWebman() + { + if (function_exists('posix_kill')) { + try { + posix_kill(posix_getppid(), SIGUSR1); + return true; + } catch (Throwable $e) {} + } else { + Timer::add(1, function () { + Worker::stopAll(); + }); + } + return false; + } + + /** + * Pause file monitor + * @return void + */ + public static function pauseFileMonitor() + { + if (method_exists(Monitor::class, 'pause')) { + Monitor::pause(); + } + } + + /** + * Resume file monitor + * @return void + */ + public static function resumeFileMonitor() + { + if (method_exists(Monitor::class, 'resume')) { + Monitor::resume(); + } + } + +} diff --git a/demo/webman/backend/plugin/admin/app/controller/AccountController.php b/demo/webman/backend/plugin/admin/app/controller/AccountController.php new file mode 100644 index 0000000000000000000000000000000000000000..bb0e14c6585d2fe582b3c8814cd12d13546dc62c --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/AccountController.php @@ -0,0 +1,260 @@ +model = new Admin; + } + + /** + * 账户设置 + * @return Response + * @throws Throwable + */ + public function index() + { + return raw_view('account/index'); + } + + /** + * 登录 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function login(Request $request): Response + { + $this->checkDatabaseAvailable(); + $captcha = $request->post('captcha', ''); + if (strtolower($captcha) !== session('captcha-login')) { + return $this->json(1, '验证码错误'); + } + $request->session()->forget('captcha-login'); + $username = $request->post('username', ''); + $password = $request->post('password', ''); + if (!$username) { + return $this->json(1, '用户名不能为空'); + } + $this->checkLoginLimit($username); + $admin = Admin::where('username', $username)->first(); + if (!$admin || !Util::passwordVerify($password, $admin->password)) { + return $this->json(1, '账户不存在或密码错误'); + } + if ($admin->status != 0) { + return $this->json(1, '当前账户暂时无法登录'); + } + $admin->login_at = date('Y-m-d H:i:s'); + $admin->save(); + $this->removeLoginLimit($username); + $admin = $admin->toArray(); + $session = $request->session(); + $admin['password'] = md5($admin['password']); + $session->set('admin', $admin); + return $this->json(0, '登录成功', [ + 'nickname' => $admin['nickname'], + 'token' => $request->sessionId(), + ]); + } + + /** + * 退出 + * @param Request $request + * @return Response + */ + public function logout(Request $request): Response + { + $request->session()->delete('admin'); + return $this->json(0); + } + + /** + * 获取登录信息 + * @param Request $request + * @return Response + */ + public function info(Request $request): Response + { + $admin = admin(); + if (!$admin) { + return $this->json(1); + } + $info = [ + 'id' => $admin['id'], + 'username' => $admin['username'], + 'nickname' => $admin['nickname'], + 'avatar' => $admin['avatar'], + 'email' => $admin['email'], + 'mobile' => $admin['mobile'], + 'isSupperAdmin' => Auth::isSupperAdmin(), + 'token' => $request->sessionId(), + ]; + return $this->json(0, 'ok', $info); + } + + /** + * 更新 + * @param Request $request + * @return Response + */ + public function update(Request $request): Response + { + $allow_column = [ + 'nickname' => 'nickname', + 'avatar' => 'avatar', + 'email' => 'email', + 'mobile' => 'mobile', + ]; + + $data = $request->post(); + $update_data = []; + foreach ($allow_column as $key => $column) { + if (isset($data[$key])) { + $update_data[$column] = $data[$key]; + } + } + if (isset($update_data['password'])) { + $update_data['password'] = Util::passwordHash($update_data['password']); + } + Admin::where('id', admin_id())->update($update_data); + $admin = admin(); + unset($update_data['password']); + foreach ($update_data as $key => $value) { + $admin[$key] = $value; + } + $request->session()->set('admin', $admin); + return $this->json(0); + } + + /** + * 修改密码 + * @param Request $request + * @return Response + */ + public function password(Request $request): Response + { + $hash = Admin::find(admin_id())['password']; + $password = $request->post('password'); + if (!$password) { + return $this->json(2, '密码不能为空'); + } + if ($request->post('password_confirm') !== $password) { + return $this->json(3, '两次密码输入不一致'); + } + if (!Util::passwordVerify($request->post('old_password'), $hash)) { + return $this->json(1, '原始密码不正确'); + } + $update_data = [ + 'password' => Util::passwordHash($password) + ]; + Admin::where('id', admin_id())->update($update_data); + return $this->json(0); + } + + /** + * 验证码 + * @param Request $request + * @param string $type + * @return Response + */ + public function captcha(Request $request, string $type = 'login'): Response + { + $builder = new PhraseBuilder(4, 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ'); + $captcha = new CaptchaBuilder(null, $builder); + $captcha->build(120); + $request->session()->set("captcha-$type", strtolower($captcha->getPhrase())); + $img_content = $captcha->get(); + return response($img_content, 200, ['Content-Type' => 'image/jpeg']); + } + + /** + * 检查登录频率限制 + * @param $username + * @return void + * @throws BusinessException + */ + protected function checkLoginLimit($username) + { + $limit_log_path = runtime_path() . '/login'; + if (!is_dir($limit_log_path)) { + mkdir($limit_log_path, 0777, true); + } + $limit_file = $limit_log_path . '/' . md5($username) . '.limit'; + $time = date('YmdH') . ceil(date('i')/5); + $limit_info = []; + if (is_file($limit_file)) { + $json_str = file_get_contents($limit_file); + $limit_info = json_decode($json_str, true); + } + + if (!$limit_info || $limit_info['time'] != $time) { + $limit_info = [ + 'username' => $username, + 'count' => 0, + 'time' => $time + ]; + } + $limit_info['count']++; + file_put_contents($limit_file, json_encode($limit_info)); + if ($limit_info['count'] >= 5) { + throw new BusinessException('登录失败次数过多,请5分钟后再试'); + } + } + + /** + * 解除登录频率限制 + * @param $username + * @return void + */ + protected function removeLoginLimit($username) + { + $limit_log_path = runtime_path() . '/login'; + $limit_file = $limit_log_path . '/' . md5($username) . '.limit'; + if (is_file($limit_file)) { + unlink($limit_file); + } + } + + protected function checkDatabaseAvailable() + { + if (!config('plugin.admin.database')) { + throw new BusinessException('请重启webman'); + } + } + +} diff --git a/demo/webman/backend/plugin/admin/app/controller/AdminController.php b/demo/webman/backend/plugin/admin/app/controller/AdminController.php new file mode 100644 index 0000000000000000000000000000000000000000..5c0fe8dd725571c4fe8594dd081540be8c90dfa3 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/AdminController.php @@ -0,0 +1,221 @@ +model = new Admin; + } + + /** + * 浏览 + * @return Response + * @throws Throwable + */ + public function index(): Response + { + return raw_view('admin/index'); + } + + /** + * 查询 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function select(Request $request): Response + { + [$where, $format, $limit, $field, $order] = $this->selectInput($request); + $query = $this->doSelect($where, $field, $order); + if ($format === 'select') { + return $this->formatSelect($query->get()); + } + $paginator = $query->paginate($limit); + $items = $paginator->items(); + $admin_ids = array_column($items, 'id'); + $roles = AdminRole::whereIn('admin_id', $admin_ids)->get(); + $roles_map = []; + foreach ($roles as $role) { + $roles_map[$role['admin_id']][] = $role['role_id']; + } + $login_admin_id = admin_id(); + foreach ($items as $index => $item) { + $admin_id = $item['id']; + $items[$index]['roles'] = isset($roles_map[$admin_id]) ? implode(',', $roles_map[$admin_id]) : ''; + $items[$index]['show_toolbar'] = $admin_id != $login_admin_id; + } + return json(['code' => 0, 'msg' => 'ok', 'count' => $paginator->total(), 'data' => $items]); + } + + /** + * 插入 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function insert(Request $request): Response + { + if ($request->method() === 'POST') { + $data = $this->insertInput($request); + $admin_id = $this->doInsert($data); + $role_ids = $request->post('roles'); + $role_ids = $role_ids ? explode(',', $role_ids) : []; + if (!$role_ids) { + return $this->json(1, '至少选择一个角色组'); + } + if (!Auth::isSupperAdmin() && array_diff($role_ids, Auth::getScopeRoleIds())) { + return $this->json(1, '角色超出权限范围'); + } + AdminRole::where('admin_id', $admin_id)->delete(); + foreach ($role_ids as $id) { + $admin_role = new AdminRole; + $admin_role->admin_id = $admin_id; + $admin_role->role_id = $id; + $admin_role->save(); + } + return $this->json(0, 'ok', ['id' => $admin_id]); + } + return raw_view('admin/insert'); + } + + /** + * 更新 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function update(Request $request): Response + { + if ($request->method() === 'POST') { + + [$id, $data] = $this->updateInput($request); + $admin_id = $request->post('id'); + if (!$admin_id) { + return $this->json(1, '缺少参数'); + } + + // 不能禁用自己 + if (isset($data['status']) && $data['status'] == 1 && $id == admin_id()) { + return $this->json(1, '不能禁用自己'); + } + + // 需要更新角色 + $role_ids = $request->post('roles'); + if ($role_ids !== null) { + if (!$role_ids) { + return $this->json(1, '至少选择一个角色组'); + } + $role_ids = explode(',', $role_ids); + + $is_supper_admin = Auth::isSupperAdmin(); + $exist_role_ids = AdminRole::where('admin_id', $admin_id)->pluck('role_id')->toArray(); + $scope_role_ids = Auth::getScopeRoleIds(); + if (!$is_supper_admin && !array_intersect($exist_role_ids, $scope_role_ids)) { + return $this->json(1, '无权限更改该记录'); + } + if (!$is_supper_admin && array_diff($role_ids, $scope_role_ids)) { + return $this->json(1, '角色超出权限范围'); + } + + // 删除账户角色 + $delete_ids = array_diff($exist_role_ids, $role_ids); + AdminRole::whereIn('role_id', $delete_ids)->where('admin_id', $admin_id)->delete(); + // 添加账户角色 + $add_ids = array_diff($role_ids, $exist_role_ids); + foreach ($add_ids as $role_id) { + $admin_role = new AdminRole; + $admin_role->admin_id = $admin_id; + $admin_role->role_id = $role_id; + $admin_role->save(); + } + } + + $this->doUpdate($id, $data); + return $this->json(0); + } + + return raw_view('admin/update'); + } + + /** + * 删除 + * @param Request $request + * @return Response + */ + public function delete(Request $request): Response + { + $primary_key = $this->model->getKeyName(); + $ids = $request->post($primary_key); + if (!$ids) { + return $this->json(0); + } + $ids = (array)$ids; + if (in_array(admin_id(), $ids)) { + return $this->json(1, '不能删除自己'); + } + if (!Auth::isSupperAdmin() && array_diff($ids, Auth::getScopeAdminIds())) { + return $this->json(1, '无数据权限'); + } + $this->model->whereIn($primary_key, $ids)->delete(); + AdminRole::whereIn('admin_id', $ids)->delete(); + return $this->json(0); + } + + /** + * 格式化下拉列表 + * @param $items + * @return Response + */ + protected function formatSelect($items): Response + { + $formatted_items = []; + foreach ($items as $item) { + $formatted_items[] = [ + 'name' => $item->nickname, + 'value' => $item->id + ]; + } + return $this->json(0, 'ok', $formatted_items); + } + +} diff --git a/demo/webman/backend/plugin/admin/app/controller/Base.php b/demo/webman/backend/plugin/admin/app/controller/Base.php new file mode 100644 index 0000000000000000000000000000000000000000..d045ca0db34c28ef3bfba84359aa11900d8020f4 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/Base.php @@ -0,0 +1,65 @@ + $code, 'data' => $data, 'msg' => $msg]); + } + + protected function success(string $msg = '成功', array $data = []): Response + { + return $this->json(0, $msg, $data); + } + + protected function fail(string $msg = '失败', array $data = []): Response + { + return $this->json(1, $msg, $data); + } +} diff --git a/demo/webman/backend/plugin/admin/app/controller/ConfigController.php b/demo/webman/backend/plugin/admin/app/controller/ConfigController.php new file mode 100644 index 0000000000000000000000000000000000000000..485ec11e62778b62356910830c68efd04e128c93 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/ConfigController.php @@ -0,0 +1,148 @@ +getByDefault()); + } + + /** + * 基于配置文件获取默认权限 + * @return mixed + */ + protected function getByDefault() + { + $name = 'system_config'; + $config = Option::where('name', $name)->value('value'); + if (empty($config)) { + $config = file_get_contents(base_path('plugin/admin/public/config/pear.config.json')); + if ($config) { + $option = new Option(); + $option->name = $name; + $option->value = $config; + $option->save(); + } + } + return json_decode($config, true); + } + + /** + * 更改 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function update(Request $request): Response + { + $post = $request->post(); + $config = $this->getByDefault(); + $data = []; + foreach ($post as $section => $items) { + if (!isset($config[$section])) { + continue; + } + switch ($section) { + case 'logo': + $data[$section]['title'] = htmlspecialchars($items['title'] ?? ''); + $data[$section]['image'] = Util::filterUrlPath($items['image'] ?? ''); + $data[$section]['icp'] = htmlspecialchars($items['icp'] ?? ''); + $data[$section]['beian'] = htmlspecialchars($items['beian'] ?? ''); + $data[$section]['footer_txt'] = htmlspecialchars($items['footer_txt'] ?? ''); + break; + case 'menu': + $data[$section]['data'] = Util::filterUrlPath($items['data'] ?? ''); + $data[$section]['accordion'] = !empty($items['accordion']); + $data[$section]['collapse'] = !empty($items['collapse']); + $data[$section]['control'] = !empty($items['control']); + $data[$section]['controlWidth'] = (int)$items['controlWidth'] ?? 500; + $data[$section]['select'] = (int)$items['select'] ?? 0; + $data[$section]['async'] = true; + break; + case 'tab': + $data[$section]['enable'] = true; + $data[$section]['keepState'] = !empty($items['keepState']); + $data[$section]['preload'] = !empty($items['preload']); + $data[$section]['session'] = !empty($items['session']); + $data[$section]['max'] = Util::filterNum($items['max'] ?? '30'); + $data[$section]['index']['id'] = Util::filterNum($items['index']['id'] ?? '0'); + $data[$section]['index']['href'] = Util::filterUrlPath($items['index']['href'] ?? ''); + $data[$section]['index']['title'] = htmlspecialchars($items['index']['title'] ?? '首页'); + break; + case 'theme': + $data[$section]['defaultColor'] = Util::filterNum($items['defaultColor'] ?? '2'); + $data[$section]['defaultMenu'] = $items['defaultMenu'] ?? '' == 'dark-theme' ? 'dark-theme' : 'light-theme'; + $data[$section]['defaultHeader'] = $items['defaultHeader'] ?? '' == 'dark-theme' ? 'dark-theme' : 'light-theme'; + $data[$section]['allowCustom'] = !empty($items['allowCustom']); + $data[$section]['banner'] = !empty($items['banner']); + break; + case 'colors': + foreach ($config['colors'] as $index => $item) { + if (!isset($items[$index])) { + $config['colors'][$index] = $item; + continue; + } + $data_item = $items[$index]; + $data[$section][$index]['id'] = $index + 1; + $data[$section][$index]['color'] = $this->filterColor($data_item['color'] ?? ''); + $data[$section][$index]['second'] = $this->filterColor($data_item['second'] ?? ''); + } + break; + + } + } + $config = array_merge($config, $data); + $name = 'system_config'; + Option::where('name', $name)->update([ + 'value' => json_encode($config) + ]); + return $this->json(0); + } + + /** + * 颜色检查 + * @param string $color + * @return string + * @throws BusinessException + */ + protected function filterColor(string $color): string + { + if (!preg_match('/\#[a-zA-Z]6/', $color)) { + throw new BusinessException('参数错误'); + } + return $color; + } + +} diff --git a/demo/webman/backend/plugin/admin/app/controller/Crud.php b/demo/webman/backend/plugin/admin/app/controller/Crud.php new file mode 100644 index 0000000000000000000000000000000000000000..5642f145c02134e862e32724bedfb19b3d6adcde --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/Crud.php @@ -0,0 +1,429 @@ +selectInput($request); + $query = $this->doSelect($where, $field, $order); + return $this->doFormat($query, $format, $limit); + } + + /** + * 添加 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function insert(Request $request): Response + { + $data = $this->insertInput($request); + $id = $this->doInsert($data); + return $this->json(0, 'ok', ['id' => $id]); + } + + /** + * 更新 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function update(Request $request): Response + { + [$id, $data] = $this->updateInput($request); + $this->doUpdate($id, $data); + return $this->json(0); + } + + /** + * 删除 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function delete(Request $request): Response + { + $ids = $this->deleteInput($request); + $this->doDelete($ids); + return $this->json(0); + } + + /** + * 查询前置 + * @param Request $request + * @return array + * @throws BusinessException + */ + protected function selectInput(Request $request): array + { + $field = $request->get('field'); + $order = $request->get('order', 'asc'); + $format = $request->get('format', 'normal'); + $limit = (int)$request->get('limit', $format === 'tree' ? 1000 : 10); + $limit = $limit <= 0 ? 10 : $limit; + $order = $order === 'asc' ? 'asc' : 'desc'; + $where = $request->get(); + $page = (int)$request->get('page'); + $page = $page > 0 ? $page : 1; + $table = config('plugin.admin.database.connections.mysql.prefix') . $this->model->getTable(); + + $allow_column = Util::db()->select("desc `$table`"); + if (!$allow_column) { + throw new BusinessException('表不存在'); + } + $allow_column = array_column($allow_column, 'Field', 'Field'); + if (!in_array($field, $allow_column)) { + $field = null; + } + foreach ($where as $column => $value) { + if ( + $value === '' || !isset($allow_column[$column]) || + is_array($value) && (empty($value) || !in_array($value[0], ['null', 'not null']) && !isset($value[1])) + ) { + unset($where[$column]); + } + } + // 按照数据限制字段返回数据 + if ($this->dataLimit === 'personal') { + $where[$this->dataLimitField] = admin_id(); + } elseif ($this->dataLimit === 'auth') { + $primary_key = $this->model->getKeyName(); + if (!Auth::isSupperAdmin() && (!isset($where[$primary_key]) || $this->dataLimitField != $primary_key)) { + $where[$this->dataLimitField] = ['in', Auth::getScopeAdminIds(true)]; + } + } + return [$where, $format, $limit, $field, $order, $page]; + } + + /** + * 指定查询where条件,并没有真正的查询数据库操作 + * @param array $where + * @param string|null $field + * @param string $order + * @return EloquentBuilder|QueryBuilder|Model + */ + protected function doSelect(array $where, string $field = null, string $order= 'desc') + { + $model = $this->model; + foreach ($where as $column => $value) { + if (is_array($value)) { + if ($value[0] === 'like' || $value[0] === 'not like') { + $model = $model->where($column, $value[0], "%$value[1]%"); + } elseif (in_array($value[0], ['>', '=', '<', '<>'])) { + $model = $model->where($column, $value[0], $value[1]); + } elseif ($value[0] == 'in' && !empty($value[1])) { + $valArr = $value[1]; + if (is_string($value[1])) { + $valArr = explode(",", trim($value[1])); + } + $model = $model->whereIn($column, $valArr); + } elseif ($value[0] == 'not in' && !empty($value[1])) { + $valArr = $value[1]; + if (is_string($value[1])) { + $valArr = explode(",", trim($value[1])); + } + $model = $model->whereNotIn($column, $valArr); + }elseif ($value[0] == 'null') { + $model = $model->whereNull($column); + } elseif ($value[0] == 'not null') { + $model = $model->whereNotNull($column); + } elseif ($value[0] !== '' || $value[1] !== '') { + $model = $model->whereBetween($column, $value); + } + } else { + $model = $model->where($column, $value); + } + } + if ($field) { + $model = $model->orderBy($field, $order); + } + return $model; + } + + /** + * 执行真正查询,并返回格式化数据 + * @param $query + * @param $format + * @param $limit + * @return Response + */ + protected function doFormat($query, $format, $limit): Response + { + $methods = [ + 'select' => 'formatSelect', + 'tree' => 'formatTree', + 'table_tree' => 'formatTableTree', + 'normal' => 'formatNormal', + ]; + $paginator = $query->paginate($limit); + $total = $paginator->total(); + $items = $paginator->items(); + if (method_exists($this, "afterQuery")) { + $items = call_user_func([$this, "afterQuery"], $items); + } + $format_function = $methods[$format] ?? 'formatNormal'; + return call_user_func([$this, $format_function], $items, $total); + } + + /** + * 插入前置方法 + * @param Request $request + * @return array + * @throws BusinessException + */ + protected function insertInput(Request $request): array + { + $data = $this->inputFilter($request->post()); + $password_filed = 'password'; + if (isset($data[$password_filed])) { + $data[$password_filed] = Util::passwordHash($data[$password_filed]); + } + + if (!Auth::isSupperAdmin() && $this->dataLimit) { + if (!empty($data[$this->dataLimitField])) { + $admin_id = $data[$this->dataLimitField]; + if (!in_array($admin_id, Auth::getScopeAdminIds(true))) { + throw new BusinessException('无数据权限'); + } + } + } + return $data; + } + + /** + * 执行插入 + * @param array $data + * @return mixed|null + */ + protected function doInsert(array $data) + { + $primary_key = $this->model->getKeyName(); + $model_class = get_class($this->model); + $model = new $model_class; + foreach ($data as $key => $val) { + $model->{$key} = $val; + } + $model->save(); + return $primary_key ? $model->$primary_key : null; + } + + /** + * 更新前置方法 + * @param Request $request + * @return array + * @throws BusinessException + */ + protected function updateInput(Request $request): array + { + $primary_key = $this->model->getKeyName(); + $id = $request->post($primary_key); + $data = $this->inputFilter($request->post()); + $model = $this->model->find($id); + if (!$model) { + throw new BusinessException('记录不存在', 2); + } + if (!Auth::isSupperAdmin() && $this->dataLimit) { + $scopeAdminIds = Auth::getScopeAdminIds(true); + $admin_ids = [ + $data[$this->dataLimitField] ?? false, // 检查要更新的数据admin_id是否是有权限的值 + $model->{$this->dataLimitField} ?? false // 检查要更新的记录的admin_id是否有权限 + ]; + foreach ($admin_ids as $admin_id) { + if ($admin_id && !in_array($admin_id, $scopeAdminIds)) { + throw new BusinessException('无数据权限'); + } + } + } + $password_filed = 'password'; + if (isset($data[$password_filed])) { + // 密码为空,则不更新密码 + if ($data[$password_filed] === '') { + unset($data[$password_filed]); + } else { + $data[$password_filed] = Util::passwordHash($data[$password_filed]); + } + } + unset($data[$primary_key]); + return [$id, $data]; + } + + /** + * 执行更新 + * @param $id + * @param $data + * @return void + */ + protected function doUpdate($id, $data) + { + $model = $this->model->find($id); + foreach ($data as $key => $val) { + $model->{$key} = $val; + } + $model->save(); + } + + /** + * 对用户输入表单过滤 + * @param array $data + * @return array + * @throws BusinessException + */ + protected function inputFilter(array $data): array + { + $table = config('plugin.admin.database.connections.mysql.prefix') . $this->model->getTable(); + $allow_column = $this->model->getConnection()->select("desc `$table`"); + if (!$allow_column) { + throw new BusinessException('表不存在', 2); + } + $columns = array_column($allow_column, 'Type', 'Field'); + foreach ($data as $col => $item) { + if (!isset($columns[$col])) { + unset($data[$col]); + continue; + } + // 非字符串类型传空则为null + if ($item === '' && strpos(strtolower($columns[$col]), 'varchar') === false && strpos(strtolower($columns[$col]), 'text') === false) { + $data[$col] = null; + } + if (is_array($item)) { + $data[$col] = implode(',', $item); + } + } + if (empty($data['created_at'])) { + unset($data['created_at']); + } + if (empty($data['updated_at'])) { + unset($data['updated_at']); + } + return $data; + } + + /** + * 删除前置方法 + * @param Request $request + * @return array + * @throws BusinessException + */ + protected function deleteInput(Request $request): array + { + $primary_key = $this->model->getKeyName(); + if (!$primary_key) { + throw new BusinessException('该表无主键,不支持删除'); + } + $ids = (array)$request->post($primary_key, []); + if (!Auth::isSupperAdmin() && $this->dataLimit) { + $admin_ids = $this->model->where($primary_key, $ids)->pluck($this->dataLimitField)->toArray(); + if (array_diff($admin_ids, Auth::getScopeAdminIds(true))) { + throw new BusinessException('无数据权限'); + } + } + return $ids; + } + + /** + * 执行删除 + * @param array $ids + * @return void + */ + protected function doDelete(array $ids) + { + if (!$ids) { + return; + } + $primary_key = $this->model->getKeyName(); + $this->model->whereIn($primary_key, $ids)->delete(); + } + + /** + * 格式化树 + * @param $items + * @return Response + */ + protected function formatTree($items): Response + { + $format_items = []; + foreach ($items as $item) { + $format_items[] = [ + 'name' => $item->title ?? $item->name ?? $item->id, + 'value' => (string)$item->id, + 'id' => $item->id, + 'pid' => $item->pid, + ]; + } + $tree = new Tree($format_items); + return $this->json(0, 'ok', $tree->getTree()); + } + + /** + * 格式化表格树 + * @param $items + * @return Response + */ + protected function formatTableTree($items): Response + { + $tree = new Tree($items); + return $this->json(0, 'ok', $tree->getTree()); + } + + /** + * 格式化下拉列表 + * @param $items + * @return Response + */ + protected function formatSelect($items): Response + { + $formatted_items = []; + foreach ($items as $item) { + $formatted_items[] = [ + 'name' => $item->title ?? $item->name ?? $item->id, + 'value' => $item->id + ]; + } + return $this->json(0, 'ok', $formatted_items); + } + + /** + * 通用格式化 + * @param $items + * @param $total + * @return Response + */ + protected function formatNormal($items, $total): Response + { + return json(['code' => 0, 'msg' => 'ok', 'count' => $total, 'data' => $items]); + } + + /** + * 查询数据库后置方法,可用于修改数据 + * @param mixed $items 原数据 + * @return mixed 修改后数据 + */ + protected function afterQuery($items) + { + return $items; + } +} diff --git a/demo/webman/backend/plugin/admin/app/controller/DevController.php b/demo/webman/backend/plugin/admin/app/controller/DevController.php new file mode 100644 index 0000000000000000000000000000000000000000..28d7a15e9993b22128884e7725628b4e1090c2d7 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/DevController.php @@ -0,0 +1,24 @@ +get('name', ''); + if ($name && is_string($name)) { + $items = Option::where('name', 'like', "dict_$name%")->get()->toArray(); + } else { + $items = Option::where('name', 'like', 'dict_%')->get()->toArray(); + } + foreach ($items as &$item) { + $item['name'] = Dict::optionNameTodictName($item['name']); + } + return $this->json(0, 'ok', $items); + } + + /** + * 插入 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function insert(Request $request): Response + { + if ($request->method() === 'POST') { + $name = $request->post('name'); + if (Dict::get($name)) { + return $this->json(1, '字典已经存在'); + } + $values = (array)$request->post('value', []); + Dict::save($name, $values); + } + return raw_view('dict/insert'); + } + + /** + * 更新 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function update(Request $request): Response + { + if ($request->method() === 'POST') { + $name = $request->post('name'); + if (!Dict::get($name)) { + return $this->json(1, '字典不存在'); + } + Dict::save($name, $request->post('value')); + } + return raw_view('dict/update'); + } + + /** + * 删除 + * @param Request $request + * @return Response + */ + public function delete(Request $request): Response + { + $names = (array)$request->post('name'); + Dict::delete($names); + return $this->json(0); + } + + /** + * 获取 + * @param Request $request + * @param $name + * @return Response + */ + public function get(Request $request, $name): Response + { + return $this->json(0, 'ok', Dict::get($name)); + } + +} diff --git a/demo/webman/backend/plugin/admin/app/controller/IndexController.php b/demo/webman/backend/plugin/admin/app/controller/IndexController.php new file mode 100644 index 0000000000000000000000000000000000000000..cbc49a72202217d2a8007334dcc834e8ac5fb61d --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/IndexController.php @@ -0,0 +1,91 @@ +', date('Y-m-d') . ' 00:00:00')->count(); + // 7天内新增用户数 + $day7_user_count = User::where('created_at', '>', date('Y-m-d H:i:s', time() - 7 * 24 * 60 * 60))->count(); + // 30天内新增用户数 + $day30_user_count = User::where('created_at', '>', date('Y-m-d H:i:s', time() - 30 * 24 * 60 * 60))->count(); + // 总用户数 + $user_count = User::count(); + // mysql版本 + $version = Util::db()->select('select VERSION() as version'); + $mysql_version = $version[0]->version ?? 'unknown'; + + $day7_detail = []; + $now = time(); + for ($i = 0; $i < 7; $i++) { + $date = date('Y-m-d', $now - 24 * 60 * 60 * $i); + $day7_detail[substr($date, 5)] = User::where('created_at', '>', "$date 00:00:00") + ->where('created_at', '<', "$date 23:59:59")->count(); + } + + return raw_view('index/dashboard', [ + 'today_user_count' => $today_user_count, + 'day7_user_count' => $day7_user_count, + 'day30_user_count' => $day30_user_count, + 'user_count' => $user_count, + 'php_version' => PHP_VERSION, + 'workerman_version' => Worker::VERSION, + 'webman_version' => Util::getPackageVersion('workerman/webman-framework'), + 'admin_version' => config('plugin.admin.app.version'), + 'mysql_version' => $mysql_version, + 'os' => PHP_OS, + 'day7_detail' => array_reverse($day7_detail), + ]); + } + +} diff --git a/demo/webman/backend/plugin/admin/app/controller/InstallController.php b/demo/webman/backend/plugin/admin/app/controller/InstallController.php new file mode 100644 index 0000000000000000000000000000000000000000..3a31a66a48be8263c335452495d63860cc7824c4 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/InstallController.php @@ -0,0 +1,392 @@ +json(1, '管理后台已经安装!如需重新安装,请删除该插件数据库配置文件并重启'); + } + + if (!class_exists(CaptchaBuilder::class) || !class_exists(Manager::class)) { + return $this->json(1, '请先restart重启webman后再进行此页面的设置'); + } + + $user = $request->post('user'); + $password = $request->post('password'); + $database = $request->post('database'); + $host = $request->post('host'); + $port = (int)$request->post('port') ?: 3306; + $overwrite = $request->post('overwrite'); + + try { + $db = $this->getPdo($host, $user, $password, $port); + $smt = $db->query("show databases like '$database'"); + if (empty($smt->fetchAll())) { + $db->exec("create database $database"); + } + $db->exec("use $database"); + $smt = $db->query("show tables"); + $tables = $smt->fetchAll(); + } catch (\Throwable $e) { + if (stripos($e, 'Access denied for user')) { + return $this->json(1, '数据库用户名或密码错误'); + } + if (stripos($e, 'Connection refused')) { + return $this->json(1, 'Connection refused. 请确认数据库IP端口是否正确,数据库已经启动'); + } + if (stripos($e, 'timed out')) { + return $this->json(1, '数据库连接超时,请确认数据库IP端口是否正确,安全组及防火墙已经放行端口'); + } + throw $e; + } + + $tables_to_install = [ + 'wa_admins', + 'wa_admin_roles', + 'wa_roles', + 'wa_rules', + 'wa_options', + 'wa_users', + 'wa_uploads', + ]; + + $tables_exist = []; + foreach ($tables as $table) { + $tables_exist[] = current($table); + } + $tables_conflict = array_intersect($tables_to_install, $tables_exist); + if (!$overwrite) { + if ($tables_conflict) { + return $this->json(1, '以下表' . implode(',', $tables_conflict) . '已经存在,如需覆盖请选择强制覆盖'); + } + } else { + foreach ($tables_conflict as $table) { + $db->exec("DROP TABLE `$table`"); + } + } + + $sql_file = base_path() . '/plugin/admin/install.sql'; + if (!is_file($sql_file)) { + return $this->json(1, '数据库SQL文件不存在'); + } + + $sql_query = file_get_contents($sql_file); + $sql_query = $this->removeComments($sql_query); + $sql_query = $this->splitSqlFile($sql_query, ';'); + foreach ($sql_query as $sql) { + $db->exec($sql); + } + + // 导入菜单 + $menus = include base_path() . '/plugin/admin/config/menu.php'; + // 安装过程中没有数据库配置,无法使用api\Menu::import()方法 + $this->importMenu($menus, $db); + + $config_content = << 'mysql', + 'connections' => [ + 'mysql' => [ + 'driver' => 'mysql', + 'host' => '$host', + 'port' => '$port', + 'database' => '$database', + 'username' => '$user', + 'password' => '$password', + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_general_ci', + 'prefix' => '', + 'strict' => true, + 'engine' => null, + ], + ], +]; +EOF; + + file_put_contents($database_config_file, $config_content); + + $think_orm_config = << 'mysql', + 'connections' => [ + 'mysql' => [ + // 数据库类型 + 'type' => 'mysql', + // 服务器地址 + 'hostname' => '$host', + // 数据库名 + 'database' => '$database', + // 数据库用户名 + 'username' => '$user', + // 数据库密码 + 'password' => '$password', + // 数据库连接端口 + 'hostport' => $port, + // 数据库连接参数 + 'params' => [ + // 连接超时3秒 + \PDO::ATTR_TIMEOUT => 3, + ], + // 数据库编码默认采用utf8 + 'charset' => 'utf8mb4', + // 数据库表前缀 + 'prefix' => '', + // 断线重连 + 'break_reconnect' => true, + // 关闭SQL监听日志 + 'trigger_sql' => true, + // 自定义分页类 + 'bootstrap' => '' + ], + ], +]; +EOF; + file_put_contents(base_path() . '/plugin/admin/config/thinkorm.php', $think_orm_config); + + + // 尝试reload + if (function_exists('posix_kill')) { + set_error_handler(function () {}); + posix_kill(posix_getppid(), SIGUSR1); + restore_error_handler(); + } + + return $this->json(0); + } + + /** + * 设置管理员 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function step2(Request $request): Response + { + $username = $request->post('username'); + $password = $request->post('password'); + $password_confirm = $request->post('password_confirm'); + if ($password != $password_confirm) { + return $this->json(1, '两次密码不一致'); + } + if (!is_file($config_file = base_path() . '/plugin/admin/config/database.php')) { + return $this->json(1, '请先完成第一步数据库配置'); + } + $config = include $config_file; + $connection = $config['connections']['mysql']; + $pdo = $this->getPdo($connection['host'], $connection['username'], $connection['password'], $connection['port'], $connection['database']); + + if ($pdo->query('select * from `wa_admins`')->fetchAll()) { + return $this->json(1, '后台已经安装完毕,无法通过此页面创建管理员'); + } + + $smt = $pdo->prepare("insert into `wa_admins` (`username`, `password`, `nickname`, `created_at`, `updated_at`) values (:username, :password, :nickname, :created_at, :updated_at)"); + $time = date('Y-m-d H:i:s'); + $data = [ + 'username' => $username, + 'password' => Util::passwordHash($password), + 'nickname' => '超级管理员', + 'created_at' => $time, + 'updated_at' => $time + ]; + foreach ($data as $key => $value) { + $smt->bindValue($key, $value); + } + $smt->execute(); + $admin_id = $pdo->lastInsertId(); + + $smt = $pdo->prepare("insert into `wa_admin_roles` (`role_id`, `admin_id`) values (:role_id, :admin_id)"); + $smt->bindValue('role_id', 1); + $smt->bindValue('admin_id', $admin_id); + $smt->execute(); + + $request->session()->flush(); + return $this->json(0); + } + + /** + * 添加菜单 + * @param array $menu + * @param \PDO $pdo + * @return int + */ + protected function addMenu(array $menu, \PDO $pdo): int + { + $allow_columns = ['title', 'key', 'icon', 'href', 'pid', 'weight', 'type']; + $data = []; + foreach ($allow_columns as $column) { + if (isset($menu[$column])) { + $data[$column] = $menu[$column]; + } + } + $time = date('Y-m-d H:i:s'); + $data['created_at'] = $data['updated_at'] = $time; + $values = []; + foreach ($data as $k => $v) { + $values[] = ":$k"; + } + $columns = array_keys($data); + foreach ($columns as $k => $column) { + $columns[$k] = "`$column`"; + } + $sql = "insert into wa_rules (" .implode(',', $columns). ") values (" . implode(',', $values) . ")"; + $smt = $pdo->prepare($sql); + foreach ($data as $key => $value) { + $smt->bindValue($key, $value); + } + $smt->execute(); + return $pdo->lastInsertId(); + } + + /** + * 导入菜单 + * @param array $menu_tree + * @param \PDO $pdo + * @return void + */ + protected function importMenu(array $menu_tree, \PDO $pdo) + { + if (is_numeric(key($menu_tree)) && !isset($menu_tree['key'])) { + foreach ($menu_tree as $item) { + $this->importMenu($item, $pdo); + } + return; + } + $children = $menu_tree['children'] ?? []; + unset($menu_tree['children']); + $smt = $pdo->prepare("select * from wa_rules where `key`=:key limit 1"); + $smt->execute(['key' => $menu_tree['key']]); + $old_menu = $smt->fetch(); + if ($old_menu) { + $pid = $old_menu['id']; + $params = [ + 'title' => $menu_tree['title'], + 'icon' => $menu_tree['icon'] ?? '', + 'key' => $menu_tree['key'], + ]; + $sql = "update wa_rules set title=:title, icon=:icon where `key`=:key"; + $smt = $pdo->prepare($sql); + $smt->execute($params); + } else { + $pid = $this->addMenu($menu_tree, $pdo); + } + foreach ($children as $menu) { + $menu['pid'] = $pid; + $this->importMenu($menu, $pdo); + } + } + + /** + * 去除sql文件中的注释 + * @param $sql + * @return string + */ + protected function removeComments($sql): string + { + return preg_replace("/(\n--[^\n]*)/","", $sql); + } + + /** + * 分割sql文件 + * @param $sql + * @param $delimiter + * @return array + */ + function splitSqlFile($sql, $delimiter): array + { + $tokens = explode($delimiter, $sql); + $output = array(); + $matches = array(); + $token_count = count($tokens); + for ($i = 0; $i < $token_count; $i++) { + if (($i != ($token_count - 1)) || (strlen($tokens[$i] > 0))) { + $total_quotes = preg_match_all("/'/", $tokens[$i], $matches); + $escaped_quotes = preg_match_all("/(? "set names utf8mb4", + \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, + \PDO::ATTR_EMULATE_PREPARES => false, + \PDO::ATTR_TIMEOUT => 5, + \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, + ]; + return new \PDO($dsn, $username, $password, $params); + } + +} diff --git a/demo/webman/backend/plugin/admin/app/controller/PluginController.php b/demo/webman/backend/plugin/admin/app/controller/PluginController.php new file mode 100644 index 0000000000000000000000000000000000000000..924946e675e21e45dac217d796fb7a5be4781a38 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/PluginController.php @@ -0,0 +1,549 @@ +httpClient(); + $response = $client->get("/webman-admin/apps"); + return (string)$response->getBody(); + } + + /** + * 列表 + * @param Request $request + * @return Response + * @throws GuzzleException + */ + public function list(Request $request): Response + { + $installed = $this->getLocalPlugins(); + + $client = $this->httpClient(); + $query = $request->get(); + $query['version'] = $this->getAdminVersion(); + $response = $client->get('/api/app/list', ['query' => $query]); + $content = $response->getBody()->getContents(); + $data = json_decode($content, true); + if (!$data) { + $msg = "/api/app/list return $content"; + echo "msg\r\n"; + Log::error($msg); + return $this->json(1, '获取数据出错'); + } + $disabled = is_phar(); + foreach ($data['data']['items'] as $key => $item) { + $name = $item['name']; + $data['data']['items'][$key]['installed'] = $installed[$name] ?? 0; + $data['data']['items'][$key]['disabled'] = $disabled; + } + $items = $data['data']['items']; + $count = $data['data']['total']; + return json(['code' => 0, 'msg' => 'ok', 'data' => $items, 'count' => $count]); + } + + /** + * 安装 + * @param Request $request + * @return Response + * @throws GuzzleException|BusinessException + */ + public function install(Request $request): Response + { + $name = $request->post('name'); + $version = $request->post('version'); + $installed_version = $this->getPluginVersion($name); + if (!$name || !$version) { + return $this->json(1, '缺少参数'); + } + + $user = session('app-plugin-user'); + if (!$user) { + return $this->json(-1, '请登录'); + } + + // 获取下载zip文件url + $data = $this->getDownloadUrl($name, $version); + if ($data['code'] != 0) { + return $this->json($data['code'], $data['msg'], $data['data'] ?? []); + } + + // 下载zip文件 + $base_path = base_path() . "/plugin/$name"; + $zip_file = "$base_path.zip"; + $extract_to = base_path() . '/plugin/'; + $this->downloadZipFile($data['data']['url'], $zip_file); + + $has_zip_archive = class_exists(ZipArchive::class, false); + if (!$has_zip_archive) { + $cmd = $this->getUnzipCmd($zip_file, $extract_to); + if (!$cmd) { + throw new BusinessException('请给php安装zip模块或者给系统安装unzip命令'); + } + if (!function_exists('proc_open')) { + throw new BusinessException('请解除proc_open函数的禁用或者给php安装zip模块'); + } + } + + Util::pauseFileMonitor(); + try { + // 解压zip到plugin目录 + if ($has_zip_archive) { + $zip = new ZipArchive; + $zip->open($zip_file, ZIPARCHIVE::CHECKCONS); + } + + $context = null; + $install_class = "\\plugin\\$name\\api\\Install"; + if ($installed_version) { + // 执行beforeUpdate + if (class_exists($install_class) && method_exists($install_class, 'beforeUpdate')) { + $context = call_user_func([$install_class, 'beforeUpdate'], $installed_version, $version); + } + } + + if (!empty($zip)) { + $zip->extractTo(base_path() . '/plugin/'); + unset($zip); + } else { + $this->unzipWithCmd($cmd); + } + + unlink($zip_file); + + if ($installed_version) { + // 执行update更新 + if (class_exists($install_class) && method_exists($install_class, 'update')) { + call_user_func([$install_class, 'update'], $installed_version, $version, $context); + } + } else { + // 执行install安装 + if (class_exists($install_class) && method_exists($install_class, 'install')) { + call_user_func([$install_class, 'install'], $version); + } + } + } finally { + Util::resumeFileMonitor(); + } + + Util::reloadWebman(); + + return $this->json(0); + } + + /** + * 卸载 + * @param Request $request + * @return Response + */ + public function uninstall(Request $request): Response + { + $name = $request->post('name'); + $version = $request->post('version'); + if (!$name || !preg_match('/^[a-zA-Z0-9_]+$/', $name)) { + return $this->json(1, '参数错误'); + } + + // 获得插件路径 + clearstatcache(); + $path = get_realpath(base_path() . "/plugin/$name"); + if (!$path || !is_dir($path)) { + return $this->json(1, '已经删除'); + } + + // 执行uninstall卸载 + $install_class = "\\plugin\\$name\\api\\Install"; + if (class_exists($install_class) && method_exists($install_class, 'uninstall')) { + call_user_func([$install_class, 'uninstall'], $version); + } + + // 删除目录 + clearstatcache(); + if (is_dir($path)) { + $monitor_support_pause = method_exists(Monitor::class, 'pause'); + if ($monitor_support_pause) { + Monitor::pause(); + } + try { + $this->rmDir($path); + } finally { + if ($monitor_support_pause) { + Monitor::resume(); + } + } + } + clearstatcache(); + + Util::reloadWebman(); + + return $this->json(0); + } + + /** + * 支付 + * @param Request $request + * @return string|Response + * @throws GuzzleException + */ + public function pay(Request $request) + { + $app = $request->get('app'); + if (!$app) { + return response('app not found'); + } + $token = session('app-plugin-token'); + if (!$token) { + return 'Please login workerman.net'; + } + $client = $this->httpClient(); + $response = $client->get("/payment/app/$app/$token"); + return (string)$response->getBody(); + } + + /** + * 登录验证码 + * @param Request $request + * @return Response + * @throws GuzzleException + */ + public function captcha(Request $request): Response + { + $client = $this->httpClient(); + $response = $client->get('/user/captcha?type=login'); + $sid_str = $response->getHeaderLine('Set-Cookie'); + if (preg_match('/PHPSID=([a-zA-Z_0-9]+?);/', $sid_str, $match)) { + $sid = $match[1]; + session()->set('app-plugin-token', $sid); + } + return response($response->getBody()->getContents())->withHeader('Content-Type', 'image/jpeg'); + } + + /** + * 登录官网 + * @param Request $request + * @return Response|string + * @throws GuzzleException + */ + public function login(Request $request) + { + $client = $this->httpClient(); + if ($request->method() === 'GET') { + $response = $client->get("/webman-admin/login"); + return (string)$response->getBody(); + } + + $response = $client->post('/api/user/login', [ + 'form_params' => [ + 'email' => $request->post('username'), + 'password' => $request->post('password'), + 'captcha' => $request->post('captcha') + ] + ]); + $content = $response->getBody()->getContents(); + $data = json_decode($content, true); + if (!$data) { + $msg = "/api/user/login return $content"; + echo "msg\r\n"; + Log::error($msg); + return $this->json(1, '发生错误'); + } + if ($data['code'] != 0) { + return $this->json($data['code'], $data['msg']); + } + session()->set('app-plugin-user', [ + 'uid' => $data['data']['uid'] + ]); + return $this->json(0); + } + + /** + * 获取zip下载url + * @param $name + * @param $version + * @return mixed + * @throws BusinessException + * @throws GuzzleException + */ + protected function getDownloadUrl($name, $version) + { + $client = $this->httpClient(); + $response = $client->get("/app/download/$name?version=$version"); + + $content = $response->getBody()->getContents(); + $data = json_decode($content, true); + if (!$data) { + $msg = "/api/app/download return $content"; + Log::error($msg); + throw new BusinessException('访问官方接口失败 ' . $response->getStatusCode() . ' ' . $response->getReasonPhrase()); + } + if ($data['code'] && $data['code'] != -1 && $data['code'] != -2) { + throw new BusinessException($data['msg']); + } + if ($data['code'] == 0 && !isset($data['data']['url'])) { + throw new BusinessException('官方接口返回数据错误'); + } + return $data; + } + + /** + * 下载zip + * @param $url + * @param $file + * @return void + * @throws BusinessException + * @throws GuzzleException + */ + protected function downloadZipFile($url, $file) + { + $client = $this->downloadClient(); + $response = $client->get($url); + $body = $response->getBody(); + $status = $response->getStatusCode(); + if ($status == 404) { + throw new BusinessException('安装包不存在'); + } + $zip_content = $body->getContents(); + if (empty($zip_content)) { + throw new BusinessException('安装包不存在'); + } + file_put_contents($file, $zip_content); + } + + /** + * 获取系统支持的解压命令 + * @param $zip_file + * @param $extract_to + * @return mixed|string|null + */ + protected function getUnzipCmd($zip_file, $extract_to) + { + if ($cmd = $this->findCmd('unzip')) { + $cmd = "$cmd -o -qq $zip_file -d $extract_to"; + } else if ($cmd = $this->findCmd('7z')) { + $cmd = "$cmd x -bb0 -y $zip_file -o$extract_to"; + } else if ($cmd = $this->findCmd('7zz')) { + $cmd = "$cmd x -bb0 -y $zip_file -o$extract_to"; + } + return $cmd; + } + + /** + * 使用解压命令解压 + * @param $cmd + * @return void + * @throws BusinessException + */ + protected function unzipWithCmd($cmd) + { + $desc = [ + 0 => ["pipe", "r"], + 1 => ["pipe", "w"], + 2 => ["pipe", "w"], + ]; + $handler = proc_open($cmd, $desc, $pipes); + if (!is_resource($handler)) { + throw new BusinessException("解压zip时出错:proc_open调用失败"); + } + $err = fread($pipes[2], 1024); + fclose($pipes[2]); + proc_close($handler); + if ($err) { + throw new BusinessException("解压zip时出错:$err"); + } + } + + /** + * 获取已安装的插件列表 + * @return array + */ + protected function getLocalPlugins(): array + { + clearstatcache(); + $installed = []; + $plugin_names = array_diff(scandir(base_path() . '/plugin/'), array('.', '..')) ?: []; + foreach ($plugin_names as $plugin_name) { + if (is_dir(base_path() . "/plugin/$plugin_name") && $version = $this->getPluginVersion($plugin_name)) { + $installed[$plugin_name] = $version; + } + } + return $installed; + } + + /** + * 获取已安装的插件列表 + * @param Request $request + * @return Response + */ + public function getInstalledPlugins(Request $request): Response + { + return $this->json(0, 'ok', $this->getLocalPlugins()); + } + + + /** + * 获取本地插件版本 + * @param $name + * @return array|mixed|null + */ + protected function getPluginVersion($name) + { + if (!is_file($file = base_path() . "/plugin/$name/config/app.php")) { + return null; + } + $config = include $file; + return $config['version'] ?? null; + } + + /** + * 获取webman/admin版本 + * @return string + */ + protected function getAdminVersion(): string + { + return config('plugin.admin.app.version', ''); + } + + /** + * 删除目录 + * @param $src + * @return void + */ + protected function rmDir($src) + { + $dir = opendir($src); + while (false !== ($file = readdir($dir))) { + if (($file != '.') && ($file != '..')) { + $full = $src . '/' . $file; + if (is_dir($full)) { + $this->rmDir($full); + } else { + unlink($full); + } + } + } + closedir($dir); + rmdir($src); + } + + /** + * 获取httpclient + * @return Client + */ + protected function httpClient(): Client + { + // 下载zip + $options = [ + 'base_uri' => config('plugin.admin.app.plugin_market_host'), + 'timeout' => 60, + 'connect_timeout' => 5, + 'verify' => false, + 'http_errors' => false, + 'headers' => [ + 'Referer' => \request()->fullUrl(), + 'User-Agent' => 'webman-app-plugin', + 'Accept' => 'application/json;charset=UTF-8', + ] + ]; + if ($token = session('app-plugin-token')) { + $options['headers']['Cookie'] = "PHPSID=$token;"; + } + return new Client($options); + } + + /** + * 获取下载httpclient + * @return Client + */ + protected function downloadClient(): Client + { + // 下载zip + $options = [ + 'timeout' => 59, + 'connect_timeout' => 5, + 'verify' => false, + 'http_errors' => false, + 'headers' => [ + 'Referer' => \request()->fullUrl(), + 'User-Agent' => 'webman-app-plugin', + ] + ]; + if ($token = session('app-plugin-token')) { + $options['headers']['Cookie'] = "PHPSID=$token;"; + } + return new Client($options); + } + + /** + * 查找系统命令 + * @param string $name + * @param string|null $default + * @param array $extraDirs + * @return mixed|string|null + */ + protected function findCmd(string $name, string $default = null, array $extraDirs = []) + { + if (ini_get('open_basedir')) { + $searchPath = array_merge(explode(PATH_SEPARATOR, ini_get('open_basedir')), $extraDirs); + $dirs = []; + foreach ($searchPath as $path) { + if (@is_dir($path)) { + $dirs[] = $path; + } else { + if (basename($path) == $name && @is_executable($path)) { + return $path; + } + } + } + } else { + $dirs = array_merge( + explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), + $extraDirs + ); + } + + $suffixes = ['']; + if ('\\' === DIRECTORY_SEPARATOR) { + $pathExt = getenv('PATHEXT'); + $suffixes = array_merge($pathExt ? explode(PATH_SEPARATOR, $pathExt) : ['.exe', '.bat', '.cmd', '.com'], $suffixes); + } + foreach ($suffixes as $suffix) { + foreach ($dirs as $dir) { + if (@is_file($file = $dir . DIRECTORY_SEPARATOR . $name . $suffix) && ('\\' === DIRECTORY_SEPARATOR || @is_executable($file))) { + return $file; + } + } + } + + return $default; + } + +} diff --git a/demo/webman/backend/plugin/admin/app/controller/RoleController.php b/demo/webman/backend/plugin/admin/app/controller/RoleController.php new file mode 100644 index 0000000000000000000000000000000000000000..f465cf4bd3b150d0eec512a173910698c8e890e0 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/RoleController.php @@ -0,0 +1,255 @@ +model = new Role; + } + + /** + * 浏览 + * @return Response + * @throws Throwable + */ + public function index(): Response + { + return raw_view('role/index'); + } + + /** + * 查询 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function select(Request $request): Response + { + $id = $request->get('id'); + [$where, $format, $limit, $field, $order] = $this->selectInput($request); + $role_ids = Auth::getScopeRoleIds(true); + if (!$id) { + $where['id'] = ['in', $role_ids]; + } elseif (!in_array($id, $role_ids)) { + throw new BusinessException('无权限'); + } + $query = $this->doSelect($where, $field, $order); + return $this->doFormat($query, $format, $limit); + } + + /** + * 插入 + * @param Request $request + * @return Response + * @throws BusinessException + * @throws Throwable + */ + public function insert(Request $request): Response + { + if ($request->method() === 'POST') { + $data = $this->insertInput($request); + $pid = $data['pid'] ?? null; + if (!$pid) { + return $this->json(1, '请选择父级角色组'); + } + if (!Auth::isSupperAdmin() && !in_array($pid, Auth::getScopeRoleIds(true))) { + return $this->json(1, '父级角色组超出权限范围'); + } + $this->checkRules($pid, $data['rules'] ?? ''); + + $id = $this->doInsert($data); + return $this->json(0, 'ok', ['id' => $id]); + } + return raw_view('role/insert'); + } + + /** + * 更新 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function update(Request $request): Response + { + if ($request->method() === 'GET') { + return raw_view('role/update'); + } + [$id, $data] = $this->updateInput($request); + $is_supper_admin = Auth::isSupperAdmin(); + $descendant_role_ids = Auth::getScopeRoleIds(); + if (!$is_supper_admin && !in_array($id, $descendant_role_ids)) { + return $this->json(1, '无数据权限'); + } + + $role = Role::find($id); + if (!$role) { + return $this->json(1, '数据不存在'); + } + $is_supper_role = $role->rules === '*'; + + // 超级角色组不允许更改rules pid 字段 + if ($is_supper_role) { + unset($data['rules'], $data['pid']); + } + + if (key_exists('pid', $data)) { + $pid = $data['pid']; + if (!$pid) { + return $this->json(1, '请选择父级角色组'); + } + if ($pid == $id) { + return $this->json(1, '父级不能是自己'); + } + if (!$is_supper_admin && !in_array($pid, Auth::getScopeRoleIds(true))) { + return $this->json(1, '父级超出权限范围'); + } + } else { + $pid = $role->pid; + } + + if (!$is_supper_role) { + $this->checkRules($pid, $data['rules'] ?? ''); + } + + $this->doUpdate($id, $data); + + // 删除所有子角色组中已经不存在的权限 + if (!$is_supper_role) { + $tree = new Tree(Role::select(['id', 'pid'])->get()); + $descendant_roles = $tree->getDescendant([$id]); + $descendant_role_ids = array_column($descendant_roles, 'id'); + $rule_ids = $data['rules'] ? explode(',', $data['rules']) : []; + foreach ($descendant_role_ids as $role_id) { + $tmp_role = Role::find($role_id); + $tmp_rule_ids = $role->getRuleIds(); + $tmp_rule_ids = array_intersect(explode(',',$tmp_role->rules), $tmp_rule_ids); + $tmp_role->rules = implode(',', $tmp_rule_ids); + $tmp_role->save(); + } + } + + return $this->json(0); + } + + /** + * 删除 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function delete(Request $request): Response + { + $ids = $this->deleteInput($request); + if (in_array(1, $ids)) { + return $this->json(1, '无法删除超级管理员角色'); + } + if (!Auth::isSupperAdmin() && array_diff($ids, Auth::getScopeRoleIds())) { + return $this->json(1, '无删除权限'); + } + $tree = new Tree(Role::get()); + $descendants = $tree->getDescendant($ids); + if ($descendants) { + $ids = array_merge($ids, array_column($descendants, 'id')); + } + $this->doDelete($ids); + return $this->json(0); + } + + /** + * 获取角色权限 + * @param Request $request + * @return Response + */ + public function rules(Request $request): Response + { + $role_id = $request->get('id'); + if (empty($role_id)) { + return $this->json(0, 'ok', []); + } + if (!Auth::isSupperAdmin() && !in_array($role_id, Auth::getScopeRoleIds(true))) { + return $this->json(1, '角色组超出权限范围'); + } + $rule_id_string = Role::where('id', $role_id)->value('rules'); + if ($rule_id_string === '') { + return $this->json(0, 'ok', []); + } + $rules = Rule::get(); + $include = []; + if ($rule_id_string !== '*') { + $include = explode(',', $rule_id_string); + } + $items = []; + foreach ($rules as $item) { + $items[] = [ + 'name' => $item->title ?? $item->name ?? $item->id, + 'value' => (string)$item->id, + 'id' => $item->id, + 'pid' => $item->pid, + ]; + } + $tree = new Tree($items); + return $this->json(0, 'ok', $tree->getTree($include)); + } + + /** + * 检查权限字典是否合法 + * @param int $role_id + * @param $rule_ids + * @return void + * @throws BusinessException + */ + protected function checkRules(int $role_id, $rule_ids) + { + if ($rule_ids) { + $rule_ids = explode(',', $rule_ids); + if (in_array('*', $rule_ids)) { + throw new BusinessException('非法数据'); + } + $rule_exists = Rule::whereIn('id', $rule_ids)->pluck('id'); + if (count($rule_exists) != count($rule_ids)) { + throw new BusinessException('权限不存在'); + } + $rule_id_string = Role::where('id', $role_id)->value('rules'); + if ($rule_id_string === '') { + throw new BusinessException('数据超出权限范围'); + } + if ($rule_id_string === '*') { + return; + } + $legal_rule_ids = explode(',', $rule_id_string); + if (array_diff($rule_ids, $legal_rule_ids)) { + throw new BusinessException('数据超出权限范围'); + } + } + } + + +} diff --git a/demo/webman/backend/plugin/admin/app/controller/RuleController.php b/demo/webman/backend/plugin/admin/app/controller/RuleController.php new file mode 100644 index 0000000000000000000000000000000000000000..cf77b994aa537323aa55d3148317f1e46a729e09 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/RuleController.php @@ -0,0 +1,350 @@ +model = new Rule; + } + + /** + * 浏览 + * @return Response + * @throws Throwable + */ + public function index(): Response + { + return raw_view('rule/index'); + } + + /** + * 查询 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function select(Request $request): Response + { + $this->syncRules(); + return parent::select($request); + } + + /** + * 获取菜单 + * @param Request $request + * @return Response + */ + function get(Request $request): Response + { + $rules = $this->getRules(admin('roles')); + $types = $request->get('type', '0,1'); + $types = is_string($types) ? explode(',', $types) : [0, 1]; + $items = Rule::orderBy('weight', 'desc')->get()->toArray(); + + $formatted_items = []; + foreach ($items as $item) { + $item['pid'] = (int)$item['pid']; + $item['name'] = $item['title']; + $item['value'] = $item['id']; + $item['icon'] = $item['icon'] ? "layui-icon {$item['icon']}" : ''; + $formatted_items[] = $item; + } + + $tree = new Tree($formatted_items); + $tree_items = $tree->getTree(); + // 超级管理员权限为 * + if (!in_array('*', $rules)) { + $this->removeNotContain($tree_items, 'id', $rules); + } + $this->removeNotContain($tree_items, 'type', $types); + $menus = $this->empty_filter(Tree::arrayValues($tree_items)); + return $this->json(0, 'ok', $menus); + } + + private function empty_filter($menus) + { + return array_map( + function ($menu) { + if (isset($menu['children'])) { + $menu['children'] = $this->empty_filter($menu['children']); + } + return $menu; + }, + array_values(array_filter( + $menus, + function ($menu) { + return $menu['type'] != 0 || isset($menu['children']) && count($this->empty_filter($menu['children'])) > 0; + } + )) + ); + } + + /** + * 获取权限 + * @param Request $request + * @return Response + */ + public function permission(Request $request): Response + { + $rules = $this->getRules(admin('roles')); + // 超级管理员 + if (in_array('*', $rules)) { + return $this->json(0, 'ok', ['*']); + } + $keys = Rule::whereIn('id', $rules)->pluck('key'); + $permissions = []; + foreach ($keys as $key) { + if (!$key = Util::controllerToUrlPath($key)) { + continue; + } + $code = str_replace('/', '.', trim($key, '/')); + $permissions[] = $code; + } + return $this->json(0, 'ok', $permissions); + } + + /** + * 根据类同步规则到数据库 + * @return void + */ + protected function syncRules() + { + $items = $this->model->where('key', 'like', '%\\\\%')->get()->keyBy('key'); + $methods_in_db = []; + $methods_in_files = []; + foreach ($items as $item) { + $class = $item->key; + if (strpos($class, '@')) { + $methods_in_db[$class] = $class; + continue; + } + if (class_exists($class)) { + $reflection = new \ReflectionClass($class); + $properties = $reflection->getDefaultProperties(); + $no_need_auth = array_merge($properties['noNeedLogin'] ?? [], $properties['noNeedAuth'] ?? []); + $class = $reflection->getName(); + $pid = $item->id; + $methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC); + foreach ($methods as $method) { + $method_name = $method->getName(); + if (strtolower($method_name) === 'index' || strpos($method_name, '__') === 0 || in_array($method_name, $no_need_auth)) { + continue; + } + $name = "$class@$method_name"; + + $methods_in_files[$name] = $name; + $title = Util::getCommentFirstLine($method->getDocComment()) ?: $method_name; + $menu = $items[$name] ?? []; + if ($menu) { + if ($menu->title != $title) { + Rule::where('key', $name)->update(['title' => $title]); + } + continue; + } + $menu = new Rule; + $menu->pid = $pid; + $menu->key = $name; + $menu->title = $title; + $menu->type = 2; + $menu->save(); + } + } + } + // 从数据库中删除已经不存在的方法 + $menu_names_to_del = array_diff($methods_in_db, $methods_in_files); + if ($menu_names_to_del) { + //Rule::whereIn('key', $menu_names_to_del)->delete(); + } + } + + /** + * 查询前置方法 + * @param Request $request + * @return array + * @throws BusinessException + */ + protected function selectInput(Request $request): array + { + [$where, $format, $limit, $field, $order] = parent::selectInput($request); + // 允许通过type=0,1格式传递菜单类型 + $types = $request->get('type'); + if ($types && is_string($types)) { + $where['type'] = ['in', explode(',', $types)]; + } + // 默认weight排序 + if (!$field) { + $field = 'weight'; + $order = 'desc'; + } + return [$where, $format, $limit, $field, $order]; + } + + /** + * 添加 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function insert(Request $request): Response + { + if ($request->method() === 'GET') { + return raw_view('rule/insert'); + } + $data = $this->insertInput($request); + if (empty($data['type'])) { + $data['type'] = strpos($data['key'], '\\') ? 1 : 0; + } + $data['key'] = str_replace('\\\\', '\\', $data['key']); + $key = $data['key'] ?? ''; + if ($this->model->where('key', $key)->first()) { + return $this->json(1, "菜单标识 $key 已经存在"); + } + $data['pid'] = empty($data['pid']) ? 0 : $data['pid']; + $this->doInsert($data); + return $this->json(0); + } + + /** + * 更新 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function update(Request $request): Response + { + if ($request->method() === 'GET') { + return raw_view('rule/update'); + } + [$id, $data] = $this->updateInput($request); + if (!$row = $this->model->find($id)) { + return $this->json(2, '记录不存在'); + } + if (isset($data['pid'])) { + $data['pid'] = $data['pid'] ?: 0; + if ($data['pid'] == $row['id']) { + return $this->json(2, '不能将自己设置为上级菜单'); + } + } + if (isset($data['key'])) { + $data['key'] = str_replace('\\\\', '\\', $data['key']); + } + $this->doUpdate($id, $data); + return $this->json(0); + } + + /** + * 删除 + * @param Request $request + * @return Response + */ + public function delete(Request $request): Response + { + $ids = $this->deleteInput($request); + // 子规则一起删除 + $delete_ids = $children_ids = $ids; + while($children_ids) { + $children_ids = $this->model->whereIn('pid', $children_ids)->pluck('id')->toArray(); + $delete_ids = array_merge($delete_ids, $children_ids); + } + $this->doDelete($delete_ids); + return $this->json(0); + } + + /** + * 移除不包含某些数据的数组 + * @param $array + * @param $key + * @param $values + * @return void + */ + protected function removeNotContain(&$array, $key, $values) + { + foreach ($array as $k => &$item) { + if (!is_array($item)) { + continue; + } + if (!$this->arrayContain($item, $key, $values)) { + unset($array[$k]); + } else { + if (!isset($item['children'])) { + continue; + } + $this->removeNotContain($item['children'], $key, $values); + } + } + } + + /** + * 判断数组是否包含某些数据 + * @param $array + * @param $key + * @param $values + * @return bool + */ + protected function arrayContain(&$array, $key, $values): bool + { + if (!is_array($array)) { + return false; + } + if (isset($array[$key]) && in_array($array[$key], $values)) { + return true; + } + if (!isset($array['children'])) { + return false; + } + foreach ($array['children'] as $item) { + if ($this->arrayContain($item, $key, $values)) { + return true; + } + } + return false; + } + + /** + * 获取权限规则 + * @param $roles + * @return array + */ + protected function getRules($roles): array + { + $rules_strings = $roles ? Role::whereIn('id', $roles)->pluck('rules') : []; + $rules = []; + foreach ($rules_strings as $rule_string) { + if (!$rule_string) { + continue; + } + $rules = array_merge($rules, explode(',', $rule_string)); + } + return $rules; + } + +} diff --git a/demo/webman/backend/plugin/admin/app/controller/TableController.php b/demo/webman/backend/plugin/admin/app/controller/TableController.php new file mode 100644 index 0000000000000000000000000000000000000000..ba4bb25dc2a2a68edf4019ee49e4ce30f08cf5a8 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/TableController.php @@ -0,0 +1,1671 @@ +get('table'); + $table = Util::filterAlphaNum($table); + $form = Layui::buildForm($table, 'search'); + $table_info = Util::getSchema($table, 'table'); + $primary_key = $table_info['primary_key'][0] ?? null; + return raw_view("table/view", [ + 'form' => $form, + 'table' => $table, + 'primary_key' => $primary_key, + ]); + } + + /** + * 查询表 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function show(Request $request): Response + { + $table_name = $request->get('table_name',''); + $limit = (int)$request->get('limit', 10); + $page = (int)$request->get('page', 1); + $offset = ($page - 1) * $limit; + $database = config('database.connections')['plugin.admin.mysql']['database']; + $field = $request->get('field', 'TABLE_NAME'); + $field = Util::filterAlphaNum($field); + $order = $request->get('order', 'asc'); + $allow_column = ['TABLE_NAME', 'TABLE_COMMENT', 'ENGINE', 'TABLE_ROWS', 'CREATE_TIME', 'UPDATE_TIME', 'TABLE_COLLATION']; + if (!in_array($field, $allow_column)) { + $field = 'TABLE_NAME'; + } + $order = $order === 'asc' ? 'asc' : 'desc'; + $total = Util::db()->select("SELECT count(*)total FROM information_schema.`TABLES` WHERE TABLE_SCHEMA='$database' AND TABLE_NAME like '%{$table_name}%'")[0]->total ?? 0; + $tables = Util::db()->select("SELECT TABLE_NAME,TABLE_COMMENT,ENGINE,TABLE_ROWS,CREATE_TIME,UPDATE_TIME,TABLE_COLLATION FROM information_schema.`TABLES` WHERE TABLE_SCHEMA='$database' AND TABLE_NAME like '%{$table_name}%' order by $field $order limit $offset,$limit"); + + if ($tables) { + $table_names = array_column($tables, 'TABLE_NAME'); + $table_rows_count = []; + foreach ($table_names as $table_name) { + $table_rows_count[$table_name] = Util::db()->table($table_name)->count(); + } + foreach ($tables as $key => $table) { + $tables[$key]->TABLE_ROWS = $table_rows_count[$table->TABLE_NAME] ?? $table->TABLE_ROWS; + } + } + + return json(['code' => 0, 'msg' => 'ok', 'count' => $total, 'data' => $tables]); + } + + /** + * 创建表 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function create(Request $request): Response + { + if ($request->method() === 'GET') { + return raw_view("table/create", []); + } + $data = $request->post(); + $table_name = Util::filterAlphaNum($data['table']); + $table_comment = Util::pdoQuote($data['table_comment']); + $columns = $data['columns']; + $forms = $data['forms']; + $keys = $data['keys']; + + $primary_key_count = 0; + foreach ($columns as $index => $item) { + $columns[$index]['field'] = trim($item['field']); + if (!$item['field']) { + unset($columns[$index]); + continue; + } + $columns[$index]['primary_key'] = !empty($item['primary_key']); + if ($columns[$index]['primary_key']) { + $primary_key_count++; + } + $columns[$index]['auto_increment'] = !empty($item['auto_increment']); + $columns[$index]['nullable'] = !empty($item['nullable']); + if ($item['default'] === '') { + $columns[$index]['default'] = null; + } else if ($item['default'] === "''") { + $columns[$index]['default'] = ''; + } + } + + if ($primary_key_count > 1) { + throw new BusinessException('不支持复合主键'); + } + + foreach ($forms as $index => $item) { + if (!$item['field']) { + unset($forms[$index]); + continue; + } + $forms[$index]['form_show'] = !empty($item['form_show']); + $forms[$index]['list_show'] = !empty($item['list_show']); + $forms[$index]['enable_sort'] = !empty($item['enable_sort']); + $forms[$index]['searchable'] = !empty($item['searchable']); + } + + foreach ($keys as $index => $item) { + if (!$item['name'] || !$item['columns']) { + unset($keys[$index]); + } + } + + Util::schema()->create($table_name, function (Blueprint $table) use ($columns) { + $type_method_map = Util::methodControlMap(); + foreach ($columns as $column) { + if (!isset($column['type'])) { + throw new BusinessException("请为{$column['field']}选择类型"); + } + if (!isset($type_method_map[$column['type']])) { + throw new BusinessException("不支持的类型{$column['type']}"); + } + $this->createColumn($column, $table); + } + $table->charset = 'utf8mb4'; + $table->collation = 'utf8mb4_general_ci'; + $table->engine = 'InnoDB'; + }); + + Util::db()->statement("ALTER TABLE `$table_name` COMMENT $table_comment"); + + // 索引 + Util::schema()->table($table_name, function (Blueprint $table) use ($keys) { + foreach ($keys as $key) { + $name = $key['name']; + $columns = is_array($key['columns']) ? $key['columns'] : explode(',', $key['columns']); + $type = $key['type']; + if ($type == 'unique') { + $table->unique($columns, $name); + continue; + } + $table->index($columns, $name); + } + }); + $form_schema_map = []; + foreach ($forms as $item) { + $form_schema_map[$item['field']] = $item; + } + $form_schema_map = json_encode($form_schema_map, JSON_UNESCAPED_UNICODE); + $this->updateSchemaOption($table_name, $form_schema_map); + return $this->json(0, 'ok'); + } + + /** + * 修改表 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function modify(Request $request): Response + { + if ($request->method() === 'GET') { + return raw_view("table/modify", ['table' => $request->get('table')]); + } + $data = $request->post(); + $old_table_name = Util::filterAlphaNum($data['old_table']); + $table_name = Util::filterAlphaNum($data['table']); + $table_comment = $data['table_comment']; + $columns = $data['columns']; + $forms = $data['forms']; + $keys = $data['keys']; + $primary_key = null; + $auto_increment_column = null; + $schema = Util::getSchema($old_table_name); + $old_columns = $schema['columns']; + $old_primary_key = $schema['table']['primary_key'][0] ?? null; + + $primary_key_count = $auto_increment_count = 0; + foreach ($columns as $index => $item) { + $columns[$index]['field'] = trim($item['field']); + if (!$item['field']) { + unset($columns[$index]); + continue; + } + $field = $item['field']; + $columns[$index]['auto_increment'] = !empty($item['auto_increment']); + $columns[$index]['nullable'] = !empty($item['nullable']); + $columns[$index]['primary_key'] = !empty($item['primary_key']); + if ($columns[$index]['primary_key']) { + $primary_key = $item['field']; + $columns[$index]['nullable'] = false; + $primary_key_count++; + } + if ($item['default'] === '') { + $columns[$index]['default'] = null; + } else if ($item['default'] === "''") { + $columns[$index]['default'] = ''; + } + if ($columns[$index]['auto_increment']) { + $auto_increment_count++; + if (!isset($old_columns[$field]) || !$old_columns[$field]['auto_increment']) { + $auto_increment_column = $columns[$index]; + unset($auto_increment_column['old_field']); + $columns[$index]['auto_increment'] = false; + } + } + } + + if ($primary_key_count > 1) { + throw new BusinessException('不支持复合主键'); + } + + if ($auto_increment_count > 1) { + throw new BusinessException('一个表只能有一个自增字段,并且必须为key'); + } + + foreach ($forms as $index => $item) { + if (!$item['field']) { + unset($forms[$index]); + continue; + } + $forms[$index]['form_show'] = !empty($item['form_show']); + $forms[$index]['list_show'] = !empty($item['list_show']); + $forms[$index]['enable_sort'] = !empty($item['enable_sort']); + $forms[$index]['searchable'] = !empty($item['searchable']); + } + + foreach ($keys as $index => $item) { + if (!$item['name'] || !$item['columns']) { + unset($keys[$index]); + } + } + + // 改表名 + if ($table_name != $old_table_name) { + Util::schema()->rename($old_table_name, $table_name); + } + + $type_method_map = Util::methodControlMap(); + + foreach ($columns as $column) { + if (!isset($type_method_map[$column['type']])) { + throw new BusinessException("不支持的类型{$column['type']}"); + } + $field = $column['old_field'] ?? $column['field'] ; + $old_column = $old_columns[$field] ?? []; + // 类型更改 + foreach ($old_column as $key => $value) { + if (key_exists($key, $column) && ($column[$key] != $value || ($key === 'default' && $column[$key] !== $value))) { + $this->modifyColumn($column, $table_name); + break; + } + } + } + + $table = Util::getSchema($table_name, 'table'); + if ($table_comment !== $table['comment']) { + $table_comment = Util::pdoQuote($table_comment); + Util::db()->statement("ALTER TABLE `$table_name` COMMENT $table_comment"); + } + + $old_columns = Util::getSchema($table_name, 'columns'); + Util::schema()->table($table_name, function (Blueprint $table) use ($columns, $old_columns, $keys, $table_name) { + foreach ($columns as $column) { + $field = $column['field']; + // 新字段 + if (!isset($old_columns[$field])) { + $this->createColumn($column, $table); + } + } + // 更新索引名字 + foreach ($keys as $key) { + if (!empty($key['old_name']) && $key['old_name'] !== $key['name']) { + $table->renameIndex($key['old_name'], $key['name']); + } + } + }); + + // 找到删除的字段 + $old_columns = Util::getSchema($table_name, 'columns'); + $exists_column_names = array_column($columns, 'field', 'field'); + $old_columns_names = array_column($old_columns, 'field'); + $drop_column_names = array_diff($old_columns_names, $exists_column_names); + $drop_column_names = Util::filterAlphaNum($drop_column_names); + foreach ($drop_column_names as $drop_column_name) { + Util::db()->statement("ALTER TABLE $table_name DROP COLUMN `$drop_column_name`"); + } + + $old_keys = Util::getSchema($table_name, 'keys'); + Util::schema()->table($table_name, function (Blueprint $table) use ($keys, $old_keys, $table_name) { + foreach ($keys as $key) { + $key_name = $key['name']; + $old_key = $old_keys[$key_name] ?? []; + // 如果索引有变动,则删除索引,重新建立索引 + if ($old_key && ($key['type'] != $old_key['type'] || $key['columns'] != implode(',', $old_key['columns']))) { + $old_key = []; + unset($old_keys[$key_name]); + echo "Drop Index $key_name\n"; + $table->dropIndex($key_name); + } + // 重新建立索引 + if (!$old_key) { + $name = $key['name']; + $columns = is_array($key['columns']) ? $key['columns'] : explode(',', $key['columns']); + $type = $key['type']; + if ($type == 'unique') { + $table->unique($columns, $name); + continue; + } + echo "Create Index $key_name\n"; + $table->index($columns, $name); + } + } + + // 找到删除的索引 + $exists_key_names = array_column($keys, 'name', 'name'); + $old_keys_names = array_column($old_keys, 'name'); + $drop_keys_names = array_diff($old_keys_names, $exists_key_names); + foreach ($drop_keys_names as $name) { + echo "Drop Index $name\n"; + $table->dropIndex($name); + } + }); + + // 变更主键 + if ($old_primary_key != $primary_key) { + if ($old_primary_key) { + Util::db()->statement("ALTER TABLE `$table_name` DROP PRIMARY KEY"); + } + if ($primary_key) { + $primary_key = Util::filterAlphaNum($primary_key); + Util::db()->statement("ALTER TABLE `$table_name` ADD PRIMARY KEY(`$primary_key`)"); + } + } + + // 一个表只能有一个 auto_increment 字段,并且是key,所以需要在最后设置 + if ($auto_increment_column) { + $this->modifyColumn($auto_increment_column, $table_name); + } + + $form_schema_map = []; + foreach ($forms as $item) { + $form_schema_map[$item['field']] = $item; + } + $form_schema_map = json_encode($form_schema_map, JSON_UNESCAPED_UNICODE); + $option_name = $this->updateSchemaOption($table_name, $form_schema_map); + + return $this->json(0,$option_name); + } + + + + /** + * 一键菜单 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function crud(Request $request): Response + { + $table_name = $request->input('table'); + Util::checkTableName($table_name); + $prefix = 'wa_'; + $table_basename = strpos($table_name, $prefix) === 0 ? substr($table_name, strlen($prefix)) : $table_name; + $inflector = InflectorFactory::create()->build(); + $model_class = $inflector->classify($inflector->singularize($table_basename)); + $base_path = '/plugin/admin/app'; + if ($request->method() === 'GET') { + return raw_view("table/crud", [ + 'table' => $table_name, + 'model' => "$base_path/model/$model_class.php", + 'controller' => "$base_path/controller/{$model_class}Controller.php", + ]); + } + $title = $request->post('title'); + $pid = $request->post('pid', 0); + $icon = $request->post('icon', ''); + $controller_file = '/' . trim($request->post('controller', ''), '/'); + $model_file = '/' . trim($request->post('model', ''), '/'); + $overwrite = $request->post('overwrite'); + if ($controller_file === '/' || $model_file === '/') { + return $this->json(1, '控制器和model不能为空'); + } + + $controller_info = pathinfo($controller_file); + $model_info = pathinfo($model_file); + $controller_path = Util::filterPath($controller_info['dirname'] ?? ''); + $model_path = Util::filterPath($model_info['dirname'] ?? ''); + + $controller_file_name = Util::filterAlphaNum($controller_info['filename'] ?? ''); + $model_file_name = Util::filterAlphaNum($model_info['filename'] ?? ''); + + if ($controller_info['extension'] !== 'php' || $model_info['extension'] !== 'php' ) { + return $this->json(1, '控制器和model必须以.php为后缀'); + } + + $pid = (int)$pid; + if ($pid) { + $parent_menu = Rule::find($pid); + if (!$parent_menu) { + return $this->json(1, '父菜单不存在'); + } + } + + if (!$overwrite) { + if (is_file(base_path($controller_file))) { + return $this->json(1, "$controller_file 已经存在"); + } + if (is_file(base_path($model_file))) { + return $this->json(1, "$model_file 已经存在"); + } + } + + $explode = explode('/', trim($controller_path, '/')); + $plugin = ''; + if (strpos(strtolower($controller_file), '/controller/') === false) { + return $this->json(2, '控制器必须在controller目录下'); + } + if ($explode[0] === 'plugin') { + if (count($explode) < 4) { + return $this->json(2, '控制器参数非法'); + } + $plugin = $explode[1]; + if (strtolower($explode[2]) !== 'app') { + return $this->json(2, '控制器必须在app目录'); + } + $app = strtolower($explode[3]) !== 'controller' ? $explode[3] : ''; + } else { + if (count($explode) < 2) { + return $this->json(3, '控制器参数非法'); + } + if (strtolower($explode[0]) !== 'app') { + return $this->json(3, '控制器必须在app目录'); + } + $app = strtolower($explode[1]) !== 'controller' ? $explode[1] : ''; + } + + Util::pauseFileMonitor(); + try { + $model_class = $model_file_name; + $model_namespace = str_replace('/', '\\', trim($model_path, '/')); + + // 创建model + $this->createModel($model_class, $model_namespace, base_path($model_file), $table_name); + + $controller_suffix = $plugin ? config("plugin.$plugin.app.controller_suffix") : config('app.controller_suffix'); + $controller_class = $controller_file_name; + $controller_namespace = str_replace('/', '\\', trim($controller_path, '/')); + // 创建controller + $controller_url_name = $controller_suffix && substr($controller_class, -strlen($controller_suffix)) === $controller_suffix ? substr($controller_class, 0, -strlen($controller_suffix)) : $controller_class; + $controller_url_name = str_replace('_', '-', $inflector->tableize($controller_url_name)); + + if ($plugin) { + array_splice($explode, 0, 2); + } + array_shift($explode); + if ($app) { + array_shift($explode); + } + foreach ($explode as $index => $item) { + if (strtolower($item) === 'controller') { + unset($explode[$index]); + } + } + + $controller_base = implode('/', $explode); + $controller_class_with_namespace = "$controller_namespace\\$controller_class"; + $template_path = $controller_base ? "$controller_base/$controller_url_name" : $controller_url_name; + $this->createController($controller_class, $controller_namespace, base_path($controller_file), $model_class, $model_namespace, $title, $template_path); + + // 创建模版 + $template_file_path = ($plugin ? "/plugin/$plugin" : '') . '/app/' . ($app ? "$app/" : '') . 'view/' . $template_path; + + $model_class_with_namespace = "$model_namespace\\$model_class"; + $primary_key = (new $model_class_with_namespace)->getKeyName(); + $url_path_base = ($plugin ? "/app/$plugin/" : '/') . ($app ? "$app/" : '') . $template_path; + $this->createTemplate(base_path($template_file_path), $table_name, $url_path_base, $primary_key, "$controller_namespace\\$controller_class"); + } finally { + Util::resumeFileMonitor(); + } + + $menu = Rule::where('key', $controller_class_with_namespace)->first(); + if (!$menu) { + $menu = new Rule; + } + $menu->pid = $pid; + $menu->key = $controller_class_with_namespace; + $menu->title = $title; + $menu->icon = $icon; + $menu->href = "$url_path_base/index"; + $menu->save(); + + $roles = admin('roles'); + $rules = Role::whereIn('id', $roles)->pluck('rules'); + $rule_ids = []; + foreach ($rules as $rule_string) { + if (!$rule_string) { + continue; + } + $rule_ids = array_merge($rule_ids, explode(',', $rule_string)); + } + + // 不是超级管理员,则需要给当前管理员这个菜单的权限 + if (!in_array('*', $rule_ids) && $roles){ + $role = Role::find(current($roles)); + if ($role) { + $role->rules .= ",{$menu->id}"; + } + $role->save(); + } + + return $this->json(0); + } + + /** + * 创建model + * @param $class + * @param $namespace + * @param $file + * @param $table + * @return void + */ + protected function createModel($class, $namespace, $file, $table) + { + $this->mkdir($file); + $table_val = "'$table'"; + $pk = 'id'; + $properties = ''; + $timestamps = ''; + $incrementing = ''; + $columns = []; + try { + $database = config('database.connections')['plugin.admin.mysql']['database']; + //plugin.admin.mysql + foreach (Util::db()->select("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database' order by ORDINAL_POSITION") as $item) { + if ($item->COLUMN_KEY === 'PRI') { + $pk = $item->COLUMN_NAME; + $item->COLUMN_COMMENT .= "(主键)"; + if (strpos(strtolower($item->DATA_TYPE), 'int') === false) { + $incrementing = <<getType($item->DATA_TYPE); + $properties .= " * @property $type \${$item->COLUMN_NAME} {$item->COLUMN_COMMENT}\n"; + $columns[$item->COLUMN_NAME] = $item->COLUMN_NAME; + } + } catch (Throwable $e) {echo $e;} + if (!isset($columns['created_at']) || !isset($columns['updated_at'])) { + $timestamps = <<mkdir($file); + $controller_content = <<model = new $model_class; + } + + /** + * 浏览 + * @return Response + */ + public function index(): Response + { + return view('$template_path/index'); + } + + /** + * 插入 + * @param Request \$request + * @return Response + * @throws BusinessException + */ + public function insert(Request \$request): Response + { + if (\$request->method() === 'POST') { + return parent::insert(\$request); + } + return view('$template_path/insert'); + } + + /** + * 更新 + * @param Request \$request + * @return Response + * @throws BusinessException + */ + public function update(Request \$request): Response + { + if (\$request->method() === 'POST') { + return parent::update(\$request); + } + return view('$template_path/update'); + } + +} + +EOF; + file_put_contents($file, $controller_content); + } + + /** + * 创建控制器 + * @param $template_file_path + * @param $table + * @param $template_path + * @param $url_path_base + * @param $primary_key + * @param $controller_class_with_namespace + * @return void + */ + protected function createTemplate($template_file_path, $table, $url_path_base, $primary_key, $controller_class_with_namespace) + { + $this->mkdir($template_file_path . '/index.html'); + $code_base = Util::controllerToUrlPath($controller_class_with_namespace); + $code_base = str_replace('/', '.', trim($code_base, '/')); + $form = Layui::buildForm($table, 'search'); + $html = $form->html(3); + $html = $html ? << +
                                                              +
                                                              + $html +
                                                              + + + +
                                                              +
                                                              + 展开 + 收起 +
                                                              +
                                                              +
                                                              + +EOF + : ''; + $html = str_replace("\n", "\n" . str_repeat(' ', 2), $html); + $js = $form->js(3); + $table_js = Layui::buildTable($table, 4); + $template_content = << + + + + 浏览页面 + + + + + + + $html + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + + + + +EOF; + file_put_contents("$template_file_path/index.html", $template_content); + + $form = Layui::buildForm($table); + $html = $form->html(5); + $js = $form->js(3); + $template_content = << + + + + 新增页面 + + + + + + +
                                                              + +
                                                              +
                                                              + $html +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              + +
                                                              + + + + + + + + + + + +EOF; + + file_put_contents("$template_file_path/insert.html", $template_content); + + $form = Layui::buildForm($table, 'update'); + $html = $form->html(5); + $js = $form->js(6); + $template_content = << + + + + 更新页面 + + + + + + + +
                                                              + +
                                                              +
                                                              + $html +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              + +
                                                              + + + + + + + + + + + + +EOF; + + file_put_contents("$template_file_path/update.html", $template_content); + + } + + /** + * 创建目录 + * @param $file + * @return void + */ + protected function mkdir($file) + { + $path = pathinfo($file, PATHINFO_DIRNAME); + if (!is_dir($path)) { + mkdir($path, 0777, true); + } + } + + + /** + * 查询记录 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function select(Request $request): Response + { + $page = $request->get('page', 1); + $field = $request->get('field'); + $order = $request->get('order', 'asc'); + $table = Util::filterAlphaNum($request->get('table', '')); + $format = $request->get('format', 'normal'); + $limit = $request->get('limit', $format === 'tree' ? 5000 : 10); + + $allow_column = Util::db()->select("desc $table"); + if (!$allow_column) { + return $this->json(2, '表不存在'); + } + $allow_column = array_column($allow_column, 'Field', 'Field'); + if (!in_array($field, $allow_column)) { + $field = current($allow_column); + } + $order = $order === 'asc' ? 'asc' : 'desc'; + $paginator = Util::db()->table($table); + foreach ($request->get() as $column => $value) { + if ($value === '') { + continue; + } + if (isset($allow_column[$column])) { + if (is_array($value)) { + if ($value[0] === 'like') { + $paginator = $paginator->where($column, 'like', "%$value[1]%"); + } elseif (in_array($value[0], ['>', '=', '<', '<>', 'not like'])) { + $paginator = $paginator->where($column, $value[0], $value[1]); + } else { + if($value[0] !== '' || $value[1] !== '') { + $paginator = $paginator->whereBetween($column, $value); + } + } + } else { + $paginator = $paginator->where($column, $value); + } + } + } + $paginator = $paginator->orderBy($field, $order)->paginate($limit, '*', 'page', $page); + $items = $paginator->items(); + if ($format == 'tree') { + $items_map = []; + foreach ($items as $item) { + $items_map[$item->id] = (array)$item; + } + $formatted_items = []; + foreach ($items_map as $index => $item) { + if ($item['pid'] && isset($items_map[$item['pid']])) { + $items_map[$item['pid']]['children'][] = &$items_map[$index]; + } + } + foreach ($items_map as $item) { + if (!$item['pid']) { + $formatted_items[] = $item; + } + } + $items = $formatted_items; + } + + return json(['code' => 0, 'msg' => 'ok', 'count' => $paginator->total(), 'data' => $items]); + + } + + /** + * 插入记录 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function insert(Request $request): Response + { + if ($request->method() === 'GET') { + $table = $request->get('table'); + $form = Layui::buildForm($table); + return raw_view("table/insert", [ + 'form' => $form, + 'table' => $table + ]); + } + $table = Util::filterAlphaNum($request->input('table', '')); + $data = $request->post(); + $allow_column = Util::db()->select("desc `$table`"); + if (!$allow_column) { + throw new BusinessException('表不存在', 2); + } + $columns = array_column($allow_column, 'Type', 'Field'); + foreach ($data as $col => $item) { + if (!isset($columns[$col])) { + unset($data[$col]); + continue; + } + // 非字符串类型传空则为null + if ($item === '' && strpos(strtolower($columns[$col]), 'varchar') === false && strpos(strtolower($columns[$col]), 'text') === false) { + $data[$col] = null; + } + if (is_array($item)) { + $data[$col] = implode(',', $item); + continue; + } + if ($col === 'password') { + $data[$col] = Util::passwordHash($item); + } + } + $datetime = date('Y-m-d H:i:s'); + if (isset($columns['created_at']) && empty($data['created_at'])) { + $data['created_at'] = $datetime; + } + if (isset($columns['updated_at']) && empty($data['updated_at'])) { + $data['updated_at'] = $datetime; + } + $id = Util::db()->table($table)->insertGetId($data); + return $this->json(0, $id); + } + + /** + * 更新记录 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function update(Request $request): Response + { + if ($request->method() === 'GET') { + $table = $request->get('table'); + $table_info = Util::getSchema($table, 'table'); + $primary_key = $table_info['primary_key'][0] ?? null; + $value = htmlspecialchars($request->get($primary_key, '')); + $form = Layui::buildForm($table,'update'); + return raw_view("table/update", [ + 'primary_key' => $primary_key, + 'value' => $value, + 'form' => $form, + 'table' => $table + ]); + } + $table = Util::filterAlphaNum($request->post('table')); + $table_info = Util::getSchema($table, 'table'); + $primary_keys = $table_info['primary_key']; + if (empty($primary_keys)) { + return $this->json(1, '该表没有主键,无法执行更新操作'); + } + if (count($primary_keys) > 1) { + return $this->json(1, '不支持复合主键更新'); + } + $primary_key = $primary_keys[0]; + $value = $request->post($primary_key); + $data = $request->post(); + $allow_column = Util::db()->select("desc `$table`"); + if (!$allow_column) { + throw new BusinessException('表不存在', 2); + } + $columns = array_column($allow_column, 'Type', 'Field'); + foreach ($data as $col => $item) { + if (!isset($columns[$col])) { + unset($data[$col]); + continue; + } + // 非字符串类型传空则为null + if ($item === '' && strpos(strtolower($columns[$col]), 'varchar') === false && strpos(strtolower($columns[$col]), 'text') === false) { + $data[$col] = null; + } + if (is_array($item)) { + $data[$col] = implode(',', $item); + } + if ($col === 'password') { + // 密码为空,则不更新密码 + if ($item == '') { + unset($data[$col]); + continue; + } + $data[$col] = Util::passwordHash($item); + } + } + $datetime = date('Y-m-d H:i:s'); + if (isset($columns['updated_at']) && empty($data['updated_at'])) { + $data['updated_at'] = $datetime; + } + Util::db()->table($table)->where($primary_key, $value)->update($data); + return $this->json(0); + } + + /** + * 删除记录 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function delete(Request $request): Response + { + $table = $request->post('table'); + $table_info = Util::getSchema($table, 'table'); + $primary_keys = $table_info['primary_key']; + if (empty($primary_keys)) { + return $this->json(1, '该表没有主键,无法执行删除操作'); + } + if (count($primary_keys) > 1) { + return $this->json(1, '不支持复合主键删除'); + } + $primary_key = $primary_keys[0]; + $value = (array)$request->post($primary_key); + Util::db()->table($table)->whereIn($primary_key, $value)->delete(); + return $this->json(0); + } + + + /** + * 删除表 + * @param Request $request + * @return Response + */ + public function drop(Request $request): Response + { + $tables = $request->post('tables'); + if (!$tables) { + return $this->json(0, 'not found'); + } + $prefix = 'wa_'; + $table_not_allow_drop = ["{$prefix}admins", "{$prefix}users", "{$prefix}options", "{$prefix}roles", "{$prefix}rules", "{$prefix}admin_roles", "{$prefix}uploads"]; + if ($found = array_intersect($tables, $table_not_allow_drop)) { + return $this->json(400, implode(',', $found) . '不允许删除'); + } + foreach ($tables as $table) { + Util::schema()->drop($table); + // 删除schema + Util::db()->table('wa_options')->where('name', "table_form_schema_$table")->delete(); + } + return $this->json(0, 'ok'); + } + + /** + * 表摘要 + * @param Request $request + * @return Response + */ + public function schema(Request $request): Response + { + $table = $request->get('table'); + $data = Util::getSchema($table); + + return $this->json(0, 'ok', [ + 'table' => $data['table'], + 'columns' => array_values($data['columns']), + 'forms' => array_values($data['forms']), + 'keys' => array_values($data['keys']), + ]); + } + + /** + * 创建字段 + * @param $column + * @param Blueprint $table + * @return mixed + */ + protected function createColumn($column, Blueprint $table) + { + $method = $column['type']; + $args = [$column['field']]; + if (stripos($method, 'int') !== false) { + // auto_increment 会自动成为主键 + if ($column['auto_increment']) { + $column['nullable'] = false; + $column['default'] = null; + $args[] = true; + } + } elseif (in_array($method, ['string', 'char']) || stripos($method, 'time') !== false) { + if ($column['length']) { + $args[] = $column['length']; + } + } elseif ($method === 'enum') { + $args[] = array_map('trim', explode(',', $column['length'])); + } elseif (in_array($method, ['float', 'decimal', 'double'])) { + if ($column['length']) { + $args = array_merge($args, array_map('trim', explode(',', $column['length']))); + } + } else { + $column['auto_increment'] = false; + } + + $column_def = call_user_func_array([$table, $method], $args); + if (!empty($column['comment'])) { + $column_def = $column_def->comment($column['comment']); + } + + if (!$column['auto_increment'] && $column['primary_key']) { + $column_def = $column_def->primary(true); + } + + if ($column['auto_increment'] && !$column['primary_key']) { + $column_def = $column_def->primary(false); + } + $column_def = $column_def->nullable($column['nullable']); + + if ($column['primary_key']) { + $column_def = $column_def->nullable(false); + } + + if ($method != 'text' && $column['default'] !== null) { + $column_def->default($column['default']); + } + return $column_def; + } + + /** + * 更改字段 + * @param $column + * @param $table + * @return mixed + * @throws BusinessException + */ + protected function modifyColumn($column, $table) + { + $table = Util::filterAlphaNum($table); + $method = Util::filterAlphaNum($column['type']); + $field = Util::filterAlphaNum($column['field']); + $old_field = Util::filterAlphaNum($column['old_field'] ?? null); + $nullable = $column['nullable']; + $default = $column['default'] !== null ? Util::pdoQuote($column['default']) : null; + $comment = Util::pdoQuote($column['comment']); + $auto_increment = $column['auto_increment']; + $length = (int)$column['length']; + + if ($column['primary_key']) { + $default = null; + } + + if ($old_field && $old_field !== $field) { + $sql = "ALTER TABLE `$table` CHANGE COLUMN `$old_field` `$field` "; + } else { + $sql = "ALTER TABLE `$table` MODIFY `$field` "; + } + + if (stripos($method, 'integer') !== false) { + $type = str_ireplace('integer', 'int', $method); + if (stripos($method, 'unsigned') !== false) { + $type = str_ireplace('unsigned', '', $type); + $sql .= "$type "; + $sql .= 'unsigned '; + } else { + $sql .= "$type "; + } + if ($auto_increment) { + $column['nullable'] = false; + $column['default'] = null; + $sql .= 'AUTO_INCREMENT '; + } + } else { + switch ($method) { + case 'string': + $length = $length ?: 255; + $sql .= "varchar($length) "; + break; + case 'char': + case 'time': + $sql .= $length ? "$method($length) " : "$method "; + break; + case 'enum': + $args = array_map('trim', explode(',', (string)$column['length'])); + foreach ($args as $key => $value) { + $args[$key] = Util::pdoQuote($value); + } + $sql .= 'enum(' . implode(',', $args) . ') '; + break; + case 'double': + case 'float': + case 'decimal': + if (trim($column['length'])) { + $args = array_map('intval', explode(',', $column['length'])); + $args[1] = $args[1] ?? $args[0]; + $sql .= "$method($args[0], $args[1]) "; + break; + } + $sql .= "$method "; + break; + default : + $sql .= "$method "; + + } + } + + if (!$nullable) { + $sql .= "NOT NULL "; + } + + if ($method != 'text' && $default !== null) { + $sql .= "DEFAULT $default "; + } + + if ($comment !== null) { + $sql .= "COMMENT $comment "; + } + + echo "$sql\n"; + Util::db()->statement($sql); + } + + /** + * 字段类型列表 + * @param Request $request + * @return Response + */ + public function types(Request $request): Response + { + $types = Util::methodControlMap(); + return $this->json(0, 'ok', $types); + } + + + /** + * 更新表的form schema信息 + * @param $table_name + * @param $data + * @return string + */ + protected function updateSchemaOption($table_name, $data): string + { + $option_name = "table_form_schema_$table_name"; + $option = Option::where('name', $option_name)->first(); + if ($option) { + Option::where('name', $option_name)->update(['value' => $data]); + } else { + Option::insert(['name' => $option_name, 'value' => $data]); + } + return $option_name; + } + + /** + * 字段类型到php类型映射 + * @param string $type + * @return string + */ + protected function getType(string $type): string + { + if (strpos($type, 'int') !== false) { + return 'integer'; + } + switch ($type) { + case 'varchar': + case 'string': + case 'text': + case 'date': + case 'time': + case 'guid': + case 'datetimetz': + case 'datetime': + case 'decimal': + case 'enum': + return 'string'; + case 'boolean': + return 'integer'; + case 'float': + return 'float'; + default: + return 'mixed'; + } + } + +} diff --git a/demo/webman/backend/plugin/admin/app/controller/UploadController.php b/demo/webman/backend/plugin/admin/app/controller/UploadController.php new file mode 100644 index 0000000000000000000000000000000000000000..0071f7509c09b421edab5039df6e6269680bfb30 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/UploadController.php @@ -0,0 +1,319 @@ +model = new Upload; + } + + /** + * 浏览 + * @return Response + * @throws Throwable + */ + public function index(): Response + { + return raw_view('upload/index'); + } + + /** + * 浏览附件 + * @return Response + * @throws Throwable + */ + public function attachment(): Response + { + return raw_view('upload/attachment'); + } + + /** + * 查询附件 + * @param Request $request + * @return Response + * @throws BusinessException + */ + public function select(Request $request): Response + { + [$where, $format, $limit, $field, $order] = $this->selectInput($request); + if (!empty($where['ext']) && is_string($where['ext'])) { + $where['ext'] = ['in', explode(',', $where['ext'])]; + } + if (!empty($where['name']) && is_string($where['name'])) { + $where['name'] = ['like', "%{$where['name']}%"]; + } + $query = $this->doSelect($where, $field, $order); + return $this->doFormat($query, $format, $limit); + } + + /** + * 更新附件 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function update(Request $request): Response + { + if ($request->method() === 'GET') { + return raw_view('upload/update'); + } + return parent::update($request); + } + + /** + * 添加附件 + * @param Request $request + * @return Response + * @throws Exception|Throwable + */ + public function insert(Request $request): Response + { + if ($request->method() === 'GET') { + return raw_view('upload/insert'); + } + $file = current($request->file()); + if (!$file || !$file->isValid()) { + return $this->json(1, '未找到文件'); + } + $data = $this->base($request, '/upload/files/'.date('Ymd')); + $upload = new Upload; + $upload->admin_id = admin_id(); + $upload->name = $data['name']; + [ + $upload->url, + $upload->name, + $_, + $upload->file_size, + $upload->mime_type, + $upload->image_width, + $upload->image_height, + $upload->ext + ] = array_values($data); + $upload->category = $request->post('category'); + $upload->save(); + return $this->json(0, '上传成功', [ + 'url' => $data['url'], + 'name' => $data['name'], + 'size' => $data['size'], + ]); + } + + /** + * 上传文件 + * @param Request $request + * @return Response + * @throws Exception + */ + public function file(Request $request): Response + { + $file = current($request->file()); + if (!$file || !$file->isValid()) { + return $this->json(1, '未找到文件'); + } + $img_exts = [ + 'jpg', + 'jpeg', + 'png', + 'gif' + ]; + if (in_array($file->getUploadExtension(), $img_exts)) { + return $this->image($request); + } + $data = $this->base($request, '/upload/files/'.date('Ymd')); + return $this->json(0, '上传成功', [ + 'url' => $data['url'], + 'name' => $data['name'], + 'size' => $data['size'], + ]); + } + + /** + * 上传图片 + * @param Request $request + * @return Response + * @throws Exception + */ + public function image(Request $request): Response + { + $data = $this->base($request, '/upload/img/'.date('Ymd')); + $realpath = $data['realpath']; + try { + $img = Image::make($realpath); + $max_height = 1170; + $max_width = 1170; + $width = $img->width(); + $height = $img->height(); + $ratio = 1; + if ($height > $max_height || $width > $max_width) { + $ratio = $width > $height ? $max_width / $width : $max_height / $height; + } + $img->resize($width*$ratio, $height*$ratio)->save($realpath); + } catch (Exception $e) { + unlink($realpath); + return json( [ + 'code' => 500, + 'msg' => '处理图片发生错误' + ]); + } + return json( [ + 'code' => 0, + 'msg' => '上传成功', + 'data' => [ + 'url' => $data['url'], + 'name' => $data['name'], + 'size' => $data['size'], + ] + ]); + } + + /** + * 上传头像 + * @param Request $request + * @return Response + * @throws Exception + */ + public function avatar(Request $request): Response + { + $file = current($request->file()); + if ($file && $file->isValid()) { + $ext = strtolower($file->getUploadExtension()); + if (!in_array($ext, ['jpg', 'jpeg', 'gif', 'png'])) { + return json(['code' => 2, 'msg' => '仅支持 jpg jpeg gif png格式']); + } + $image = Image::make($file); + $width = $image->width(); + $height = $image->height(); + $size = min($width, $height); + $relative_path = 'upload/avatar/' . date('Ym'); + $real_path = base_path() . "/plugin/admin/public/$relative_path"; + if (!is_dir($real_path)) { + mkdir($real_path, 0777, true); + } + $name = bin2hex(pack('Nn',time(), random_int(1, 65535))); + $ext = $file->getUploadExtension(); + + $image->crop($size, $size)->resize(300, 300); + $path = base_path() . "/plugin/admin/public/$relative_path/$name.lg.$ext"; + $image->save($path); + + $image->resize(120, 120); + $path = base_path() . "/plugin/admin/public/$relative_path/$name.md.$ext"; + $image->save($path); + + $image->resize(60, 60); + $path = base_path() . "/plugin/admin/public/$relative_path/$name.$ext"; + $image->save($path); + + $image->resize(30, 30); + $path = base_path() . "/plugin/admin/public/$relative_path/$name.sm.$ext"; + $image->save($path); + + return json([ + 'code' => 0, + 'msg' => '上传成功', + 'data' => [ + 'url' => "/app/admin/$relative_path/$name.md.$ext" + ] + ]); + } + return json(['code' => 1, 'msg' => 'file not found']); + } + + /** + * 删除附件 + * @param Request $request + * @return Response + */ + public function delete(Request $request): Response + { + return parent::delete($request); + } + + /** + * 获取上传数据 + * @param Request $request + * @param $relative_dir + * @return array + * @throws BusinessException + */ + protected function base(Request $request, $relative_dir): array + { + $relative_dir = ltrim($relative_dir, '/'); + $file = current($request->file()); + if (!$file || !$file->isValid()) { + throw new BusinessException('未找到上传文件', 400); + } + + $base_dir = base_path() . '/plugin/admin/public/'; + $full_dir = $base_dir . $relative_dir; + if (!is_dir($full_dir)) { + mkdir($full_dir, 0777, true); + } + + $ext = $file->getUploadExtension() ?: null; + $mime_type = $file->getUploadMimeType(); + $file_name = $file->getUploadName(); + $file_size = $file->getSize(); + + if (!$ext && $file_name === 'blob') { + [$___image, $ext] = explode('/', $mime_type); + unset($___image); + } + + $ext = strtolower($ext); + $ext_forbidden_map = ['php', 'php3', 'php5', 'css', 'js', 'html', 'htm', 'asp', 'jsp']; + if (in_array($ext, $ext_forbidden_map)) { + throw new BusinessException('不支持该格式的文件上传', 400); + } + + $relative_path = $relative_dir . '/' . bin2hex(pack('Nn',time(), random_int(1, 65535))) . ".$ext"; + $full_path = $base_dir . $relative_path; + $file->move($full_path); + $image_with = $image_height = 0; + if ($img_info = getimagesize($full_path)) { + [$image_with, $image_height] = $img_info; + $mime_type = $img_info['mime']; + } + return [ + 'url' => "/app/admin/$relative_path", + 'name' => $file_name, + 'realpath' => $full_path, + 'size' => $file_size, + 'mime_type' => $mime_type, + 'image_with' => $image_with, + 'image_height' => $image_height, + 'ext' => $ext, + ]; + } + +} diff --git a/demo/webman/backend/plugin/admin/app/controller/UserController.php b/demo/webman/backend/plugin/admin/app/controller/UserController.php new file mode 100644 index 0000000000000000000000000000000000000000..35d21c0b5b7107c9945d9882b9fafe2e18efd86f --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/controller/UserController.php @@ -0,0 +1,71 @@ +model = new User; + } + + /** + * 浏览 + * @return Response + * @throws Throwable + */ + public function index(): Response + { + return raw_view('user/index'); + } + + /** + * 插入 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function insert(Request $request): Response + { + if ($request->method() === 'POST') { + return parent::insert($request); + } + return raw_view('user/insert'); + } + + /** + * 更新 + * @param Request $request + * @return Response + * @throws BusinessException|Throwable + */ + public function update(Request $request): Response + { + if ($request->method() === 'POST') { + return parent::update($request); + } + return raw_view('user/update'); + } + +} diff --git a/demo/webman/backend/plugin/admin/app/exception/Handler.php b/demo/webman/backend/plugin/admin/app/exception/Handler.php new file mode 100644 index 0000000000000000000000000000000000000000..63da273a4613c637898dfe513b8e033de04871ce --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/exception/Handler.php @@ -0,0 +1,40 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace plugin\admin\app\exception; + +use Throwable; +use Webman\Http\Request; +use Webman\Http\Response; + +/** + * Class Handler + * @package support\exception + */ +class Handler extends \support\exception\Handler +{ + public function render(Request $request, Throwable $exception): Response + { + $code = $exception->getCode(); + $debug = $this->_debug ?? $this->debug; + if ($request->expectsJson()) { + $json = ['code' => $code ?: 500, 'msg' => $debug ? $exception->getMessage() : 'Server internal error', 'type' => 'failed']; + $debug && $json['traces'] = (string)$exception; + return new Response(200, ['Content-Type' => 'application/json'], + \json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); + } + $error = $debug ? \nl2br((string)$exception) : 'Server internal error'; + return new Response(500, [], $error); + } +} diff --git a/demo/webman/backend/plugin/admin/app/functions.php b/demo/webman/backend/plugin/admin/app/functions.php new file mode 100644 index 0000000000000000000000000000000000000000..2fd9b03b7854d0cc3993bef837a948fb940bdf14 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/functions.php @@ -0,0 +1,146 @@ +session(); + $admin = Admin::find($admin_id); + if (!$admin) { + $session->forget('admin'); + return null; + } + $admin = $admin->toArray(); + $admin['password'] = md5($admin['password']); + $admin_session['password'] = $admin_session['password'] ?? ''; + if ($admin['password'] != $admin_session['password']) { + $session->forget('admin'); + return null; + } + // 账户被禁用 + if ($admin['status'] != 0) { + $session->forget('admin'); + return; + } + $admin['roles'] = AdminRole::where('admin_id', $admin_id)->pluck('role_id')->toArray(); + $admin['session_last_update_time'] = $time_now; + $session->set('admin', $admin); +} + + +/** + * 刷新当前用户session + * @param bool $force + * @return void + */ +function refresh_user_session(bool $force = false) +{ + if (!$user_id = user_id()) { + return null; + } + $time_now = time(); + // session在2秒内不刷新 + $session_ttl = 2; + $session_last_update_time = session('user.session_last_update_time', 0); + if (!$force && $time_now - $session_last_update_time < $session_ttl) { + return null; + } + $session = request()->session(); + $user = User::find($user_id); + if (!$user) { + $session->forget('user'); + return null; + } + $user = $user->toArray(); + unset($user['password']); + $user['session_last_update_time'] = $time_now; + $session->set('user', $user); +} diff --git a/demo/webman/backend/plugin/admin/app/middleware/AccessControl.php b/demo/webman/backend/plugin/admin/app/middleware/AccessControl.php new file mode 100644 index 0000000000000000000000000000000000000000..081d0eeaef31d636b19f4b93fed48b3d9bd2818a --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/middleware/AccessControl.php @@ -0,0 +1,54 @@ +controller; + $action = $request->action; + + $code = 0; + $msg = ''; + if (!Auth::canAccess($controller, $action, $code, $msg)) { + if ($request->expectsJson()) { + $response = json(['code' => $code, 'msg' => $msg, 'data' => []]); + } else { + if ($code === 401) { + $response = response(<< + if (self !== top) { + parent.location.reload(); + } + +EOF + ); + } else { + $request->app = ''; + $request->plugin = 'admin'; + $response = view('common/error/403')->withStatus(403); + } + } + + } else { + $response = $request->method() == 'OPTIONS' ? response('') : $handler($request); + } + + return $response; + + } + +} diff --git a/demo/webman/backend/plugin/admin/app/model/Admin.php b/demo/webman/backend/plugin/admin/app/model/Admin.php new file mode 100644 index 0000000000000000000000000000000000000000..f55e93218ce268c4f09aebe3520dad7f8d4d1008 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/model/Admin.php @@ -0,0 +1,40 @@ +format('Y-m-d H:i:s'); + } +} diff --git a/demo/webman/backend/plugin/admin/app/model/Dict.php b/demo/webman/backend/plugin/admin/app/model/Dict.php new file mode 100644 index 0000000000000000000000000000000000000000..8178868482ca6c414c9087ce312fce816d3d7546 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/model/Dict.php @@ -0,0 +1,96 @@ +value('value'); + return $value ? json_decode($value, true) : null; + } + + /** + * 保存字典 + * @param $name + * @param $values + * @return void + * @throws BusinessException + */ + public static function save($name, $values) + { + if (!preg_match('/[a-zA-Z]/', $name)) { + throw new BusinessException('字典名只能包含字母'); + } + $option_name = static::dictNameToOptionName($name); + if (!$option = Option::where('name', $option_name)->first()) { + $option = new Option; + } + $format_values = static::filterValue($values); + $option->name = $option_name; + $option->value = json_encode($format_values, JSON_UNESCAPED_UNICODE); + $option->save(); + } + + /** + * 删除字典 + * @param array $names + * @return void + */ + public static function delete(array $names) + { + foreach ($names as $index => $name) { + $names[$index] = static::dictNameToOptionName($name); + } + Option::whereIn('name', $names)->delete(); + } + + /** + * 字典名到option名转换 + * @param string $name + * @return string + */ + public static function dictNameToOptionName(string $name): string + { + return "dict_$name"; + } + + /** + * option名到字典名转换 + * @param string $name + * @return string + */ + public static function optionNameToDictName(string $name): string + { + return substr($name, 5); + } + + /** + * 过滤值 + * @param array $values + * @return array + * @throws BusinessException + */ + public static function filterValue(array $values): array + { + $format_values = []; + foreach ($values as $item) { + if (!isset($item['value']) || !isset($item['name'])) { + throw new BusinessException('字典格式错误', 1); + } + $format_values[] = ['value' => $item['value'], 'name' => $item['name']]; + } + return $format_values; + } +} diff --git a/demo/webman/backend/plugin/admin/app/model/Option.php b/demo/webman/backend/plugin/admin/app/model/Option.php new file mode 100644 index 0000000000000000000000000000000000000000..97018b02ec67c3834b8f6c97d26cc92656fe4e38 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/model/Option.php @@ -0,0 +1,29 @@ +rules ? explode(',', $this->rules) : []; + } + +} diff --git a/demo/webman/backend/plugin/admin/app/model/Rule.php b/demo/webman/backend/plugin/admin/app/model/Rule.php new file mode 100644 index 0000000000000000000000000000000000000000..ebc7dd14840945e61ddde885cc8209cd7e71355e --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/model/Rule.php @@ -0,0 +1,38 @@ + + + + + + + + + + + + +
                                                              +
                                                              + +
                                                              +
                                                                +
                                                              • 基本信息
                                                              • +
                                                              • 安全设置
                                                              • +
                                                              +
                                                              + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/account/login.html b/demo/webman/backend/plugin/admin/app/view/account/login.html new file mode 100644 index 0000000000000000000000000000000000000000..8ecf43663d8d9bbb4c1fabd3f8f3bc8991ad38b4 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/account/login.html @@ -0,0 +1,80 @@ + + + + + + 登录 + + + + + + +
                                                              +
                                                              + +
                                                              webman admin
                                                              +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              + +
                                                              +
                                                              + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/admin/index.html b/demo/webman/backend/plugin/admin/app/view/admin/index.html new file mode 100644 index 0000000000000000000000000000000000000000..965bd8a1e0e2fb5bca020ce8ded86a307fca66bc --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/admin/index.html @@ -0,0 +1,404 @@ + + + + + + 浏览页面 + + + + + + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + + - + +
                                                              +
                                                              +
                                                              + +
                                                              + + + +
                                                              +
                                                              + 展开 + 收起 +
                                                              +
                                                              +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/admin/insert.html b/demo/webman/backend/plugin/admin/app/view/admin/insert.html new file mode 100644 index 0000000000000000000000000000000000000000..2529d64ecd01bb6636809cab4b0708ef876b1a33 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/admin/insert.html @@ -0,0 +1,181 @@ + + + + + 新增页面 + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + + + + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              + +
                                                              + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/admin/update.html b/demo/webman/backend/plugin/admin/app/view/admin/update.html new file mode 100644 index 0000000000000000000000000000000000000000..df52be29caa995b7916f9a21e5ce1bbdccf0c3d9 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/admin/update.html @@ -0,0 +1,215 @@ + + + + + 更新页面 + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + + + + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              + +
                                                              + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/common/error/403.html b/demo/webman/backend/plugin/admin/app/view/common/error/403.html new file mode 100644 index 0000000000000000000000000000000000000000..1790830e1376ad8988ee2ccdf7c6dd49eb8c2350 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/common/error/403.html @@ -0,0 +1,21 @@ + + + + + + + + + +
                                                              + +
                                                              +

                                                              403

                                                              +

                                                              抱歉,你无权访问该页面

                                                              +
                                                              +
                                                              + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/app/view/config/index.html b/demo/webman/backend/plugin/admin/app/view/config/index.html new file mode 100644 index 0000000000000000000000000000000000000000..ba2999ba7204b5d5c3a1f38b458ff2b064270906 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/config/index.html @@ -0,0 +1,332 @@ + + + + + + + + + + + + +
                                                              +
                                                              + +
                                                              +
                                                                +
                                                              • 基本信息
                                                              • +
                                                              • 菜单配置
                                                              • +
                                                              • 页面配置
                                                              • +
                                                              +
                                                              + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + + + + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + + +
                                                              + +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/dev/form-build.html b/demo/webman/backend/plugin/admin/app/view/dev/form-build.html new file mode 100644 index 0000000000000000000000000000000000000000..b17dac9ca760fd7b78fbf723fefb9c328b6b2236 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/dev/form-build.html @@ -0,0 +1,113 @@ + + + + + + + 表单生成器 + + + + +
                                                              +
                                                              +
                                                              + + + + +
                                                              +
                                                              +
                                                              +
                                                              + view +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              html
                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              code
                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/dict/index.html b/demo/webman/backend/plugin/admin/app/view/dict/index.html new file mode 100644 index 0000000000000000000000000000000000000000..a2d2f778e75961487d2f823770856f86187fb248 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/dict/index.html @@ -0,0 +1,260 @@ + + + + + + 浏览页面 + + + + + + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + + + +
                                                              +
                                                              + 展开 + 收起 +
                                                              +
                                                              +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/dict/insert.html b/demo/webman/backend/plugin/admin/app/view/dict/insert.html new file mode 100644 index 0000000000000000000000000000000000000000..803285d8b04bca2a406678c98f964ff34d21ef93 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/dict/insert.html @@ -0,0 +1,224 @@ + + + + + 新增字典 + + + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + + +
                                                              + + + + + + + +
                                                              + + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/dict/update.html b/demo/webman/backend/plugin/admin/app/view/dict/update.html new file mode 100644 index 0000000000000000000000000000000000000000..11a912defd7c27e48ef35fcfede40a5fa07862f4 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/dict/update.html @@ -0,0 +1,240 @@ + + + + + 更新字典 + + + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + + +
                                                              + + + + + + + +
                                                              + + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/index/dashboard.html b/demo/webman/backend/plugin/admin/app/view/index/dashboard.html new file mode 100644 index 0000000000000000000000000000000000000000..f3b713a070f8dbbaaf807abfd8e93d5afbb53987 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/index/dashboard.html @@ -0,0 +1,358 @@ + + + + + 控制后台 + + + + + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              今日注册
                                                              +
                                                              +
                                                              +
                                                              + 0 +
                                                              +
                                                              + + + + + + + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              7日内注册
                                                              +
                                                              +
                                                              +
                                                              + 0 +
                                                              +
                                                              + + + + + + + + + + + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              30日内注册
                                                              +
                                                              +
                                                              +
                                                              + 0 +
                                                              +
                                                              + + + + + + + + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              总注册
                                                              +
                                                              +
                                                              +
                                                              + 0 +
                                                              +
                                                              + + + + + + + + + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              系统信息
                                                              +
                                                              + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              Workerman版本
                                                              Webman版本
                                                              WebmanAdmin版本
                                                              PHP版本
                                                              MYSQL版本
                                                              操作系统
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/index/index.html b/demo/webman/backend/plugin/admin/app/view/index/index.html new file mode 100644 index 0000000000000000000000000000000000000000..52317bd0960cb91894973d50dd71670171b88d04 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/index/index.html @@ -0,0 +1,144 @@ + + + + + + 主页 + + + + + + + + + + + + +
                                                              + +
                                                              + + + +
                                                                +
                                                              • +
                                                              • +
                                                              + +
                                                              + + +
                                                              + +
                                                              + + + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + + + +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/index/install.html b/demo/webman/backend/plugin/admin/app/view/index/install.html new file mode 100644 index 0000000000000000000000000000000000000000..a72845a8efdb28e5ecbe889698f9797d644d8901 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/index/install.html @@ -0,0 +1,214 @@ + + + + + Webman Admin 安装 + + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +

                                                              Webman Admin 安装

                                                              + + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/role/index.html b/demo/webman/backend/plugin/admin/app/view/role/index.html new file mode 100644 index 0000000000000000000000000000000000000000..892be0c2d31671ae86c8af6cc1f54b3081110607 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/role/index.html @@ -0,0 +1,298 @@ + + + + + + 浏览页面 + + + + + + + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/role/insert.html b/demo/webman/backend/plugin/admin/app/view/role/insert.html new file mode 100644 index 0000000000000000000000000000000000000000..ef0089b6d141d3972e4aa2787a6272bdcf9769ef --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/role/insert.html @@ -0,0 +1,149 @@ + + + + + 新增页面 + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              + +
                                                              + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/role/update.html b/demo/webman/backend/plugin/admin/app/view/role/update.html new file mode 100644 index 0000000000000000000000000000000000000000..51d9e917884aed2cbe398dbca5fb3fbd08e860ec --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/role/update.html @@ -0,0 +1,188 @@ + + + + + 更新页面 + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              + +
                                                              + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/rule/index.html b/demo/webman/backend/plugin/admin/app/view/rule/index.html new file mode 100644 index 0000000000000000000000000000000000000000..f603004d72c69f8694374d49bc72c4e7d1362384 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/rule/index.html @@ -0,0 +1,280 @@ + + + + + + + + + + + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/rule/insert.html b/demo/webman/backend/plugin/admin/app/view/rule/insert.html new file mode 100644 index 0000000000000000000000000000000000000000..096e1f51b504875586ff2737f40468925bdcdfac --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/rule/insert.html @@ -0,0 +1,174 @@ + + + + + + 新增页面 + + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/rule/update.html b/demo/webman/backend/plugin/admin/app/view/rule/update.html new file mode 100644 index 0000000000000000000000000000000000000000..721cf49587ce15c165b325af4d063074ebf0fe01 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/rule/update.html @@ -0,0 +1,207 @@ + + + + + + 更新页面 + + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/table/create.html b/demo/webman/backend/plugin/admin/app/view/table/create.html new file mode 100644 index 0000000000000000000000000000000000000000..43270b833f6712f1922541918f5513ee5426e00c --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/table/create.html @@ -0,0 +1,744 @@ + + + + + 新增页面 + + + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              +
                                                                +
                                                              • 字段属性
                                                              • +
                                                              • 表单属性
                                                              • +
                                                              • 索引
                                                              • +
                                                              +
                                                              + +
                                                              + + +
                                                              + + + + + + + + + + + + + + + + + + + +
                                                              + + +
                                                              + +
                                                              + + + + + + + + + + + + + + + + + + + +
                                                              + + +
                                                              +
                                                              + +
                                                              + + + + + + + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/table/crud.html b/demo/webman/backend/plugin/admin/app/view/table/crud.html new file mode 100644 index 0000000000000000000000000000000000000000..0a8dc31466ecfe92dcfcaf6c2541af3fdb167784 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/table/crud.html @@ -0,0 +1,139 @@ + + + + + 一键菜单 + + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/table/index.html b/demo/webman/backend/plugin/admin/app/view/table/index.html new file mode 100644 index 0000000000000000000000000000000000000000..e19b9c147ab5af1776708e28d73a00ff06fac4b6 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/table/index.html @@ -0,0 +1,285 @@ + + + + + admin管理 + + + + + + + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + + + +
                                                              +
                                                              + 展开 + 收起 +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/table/insert.html b/demo/webman/backend/plugin/admin/app/view/table/insert.html new file mode 100644 index 0000000000000000000000000000000000000000..8766b60c8e4e883828cc48753e6d25293f08a5db --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/table/insert.html @@ -0,0 +1,80 @@ + + + + + 新增页面 + + + + + + +
                                                              + +
                                                              +
                                                              + + html(5)?> +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/table/modify.html b/demo/webman/backend/plugin/admin/app/view/table/modify.html new file mode 100644 index 0000000000000000000000000000000000000000..4b3372007ae26617fe4ef730cc17f8511cedc0b0 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/table/modify.html @@ -0,0 +1,714 @@ + + + + + 新增页面 + + + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              + + +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              + +
                                                              +
                                                                +
                                                              • 字段属性
                                                              • +
                                                              • 表单属性
                                                              • +
                                                              • 索引
                                                              • +
                                                              +
                                                              + +
                                                              + + +
                                                              + + + + + + + + + + + + + + + + + + + +
                                                              + + + + +
                                                              + +
                                                              + + + + + + + + + + + + + + + + + + + +
                                                              + + +
                                                              +
                                                              + +
                                                              + + + + + + + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/table/update.html b/demo/webman/backend/plugin/admin/app/view/table/update.html new file mode 100644 index 0000000000000000000000000000000000000000..b3bd51ac65a7648978a47684ba5d434b530441f8 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/table/update.html @@ -0,0 +1,115 @@ + + + + + 新增页面 + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + html(5)?> + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/table/view.html b/demo/webman/backend/plugin/admin/app/view/table/view.html new file mode 100644 index 0000000000000000000000000000000000000000..762a8672dc842f54dbbda2f8fcafdab8949f947a --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/table/view.html @@ -0,0 +1,382 @@ + + + + + 表详情 + + + + +
                                                              +
                                                              +
                                                              + + html(5)?> + +
                                                              + + + +
                                                              + +
                                                              + 展开 + 收起 +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/upload/attachment.html b/demo/webman/backend/plugin/admin/app/view/upload/attachment.html new file mode 100644 index 0000000000000000000000000000000000000000..4db5bef5612976ec3897eeedc98e92d02f4dc44b --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/upload/attachment.html @@ -0,0 +1,442 @@ + + + + + + 浏览页面 + + + + + + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + + - + +
                                                              +
                                                              +
                                                              + +
                                                              + + + +
                                                              +
                                                              + 展开 + 收起 +
                                                              +
                                                              +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/upload/index.html b/demo/webman/backend/plugin/admin/app/view/upload/index.html new file mode 100644 index 0000000000000000000000000000000000000000..1a07a0c66286a83261e23db2836c1003a8a3ae2b --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/upload/index.html @@ -0,0 +1,424 @@ + + + + + + 浏览页面 + + + + + + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + + - + +
                                                              +
                                                              +
                                                              + +
                                                              + + + +
                                                              +
                                                              + 展开 + 收起 +
                                                              +
                                                              +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/upload/insert.html b/demo/webman/backend/plugin/admin/app/view/upload/insert.html new file mode 100644 index 0000000000000000000000000000000000000000..73630fdda58a62fdb0f7145778b4a06fce74fa1b --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/upload/insert.html @@ -0,0 +1,91 @@ + + + + + 新增页面 + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + + + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/upload/update.html b/demo/webman/backend/plugin/admin/app/view/upload/update.html new file mode 100644 index 0000000000000000000000000000000000000000..4944f3672b9ab9a84d4ff3c95c3ec0ba9b4d7bff --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/upload/update.html @@ -0,0 +1,139 @@ + + + + + 更新页面 + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              + +
                                                              + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/user/index.html b/demo/webman/backend/plugin/admin/app/view/user/index.html new file mode 100644 index 0000000000000000000000000000000000000000..83e3561af2261f75d68ab2f6c6b281d7397555ec --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/user/index.html @@ -0,0 +1,546 @@ + + + + + + 浏览页面 + + + + + + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + + - + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + + - + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              + + - + +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + + + +
                                                              +
                                                              + 展开 + 收起 +
                                                              +
                                                              +
                                                              +
                                                              + + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/user/insert.html b/demo/webman/backend/plugin/admin/app/view/user/insert.html new file mode 100644 index 0000000000000000000000000000000000000000..5191b08dcb283685cd66e67dcbf04d36d7a104c0 --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/user/insert.html @@ -0,0 +1,272 @@ + + + + + 新增页面 + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + + + + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              + +
                                                              + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/app/view/user/update.html b/demo/webman/backend/plugin/admin/app/view/user/update.html new file mode 100644 index 0000000000000000000000000000000000000000..442331f4ab642061f24583bfce48d09b578ca31c --- /dev/null +++ b/demo/webman/backend/plugin/admin/app/view/user/update.html @@ -0,0 +1,306 @@ + + + + + 更新页面 + + + + + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +
                                                              + +
                                                              + + + + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + +
                                                              +
                                                              + +
                                                              + +
                                                              + + +
                                                              +
                                                              + +
                                                              +
                                                              + +
                                                              +
                                                              + + +
                                                              +
                                                              + +
                                                              + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/config/app.php b/demo/webman/backend/plugin/admin/config/app.php new file mode 100644 index 0000000000000000000000000000000000000000..ab838efd637bb6c9cf6488961898e341c84f6b1f --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/app.php @@ -0,0 +1,21 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'debug' => true, + 'controller_suffix' => 'Controller', + 'controller_reuse' => false, + 'plugin_market_host' => 'https://www.workerman.net', + 'version' => '0.6.20' +]; diff --git a/demo/webman/backend/plugin/admin/config/autoload.php b/demo/webman/backend/plugin/admin/config/autoload.php new file mode 100644 index 0000000000000000000000000000000000000000..23b49800138d46004dee5140d297f434d6e8d4b2 --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/autoload.php @@ -0,0 +1,19 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'files' => [ + base_path() . '/plugin/admin/app/functions.php', + ] +]; diff --git a/demo/webman/backend/plugin/admin/config/bootstrap.php b/demo/webman/backend/plugin/admin/config/bootstrap.php new file mode 100644 index 0000000000000000000000000000000000000000..7dc463a6ca95328d889c19e8adb3e61d639d09b8 --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/bootstrap.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return []; diff --git a/demo/webman/backend/plugin/admin/config/container.php b/demo/webman/backend/plugin/admin/config/container.php new file mode 100644 index 0000000000000000000000000000000000000000..7857701aacc636f133cae4864316b4f06ae12031 --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/container.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return new Webman\Container; diff --git a/demo/webman/backend/plugin/admin/config/database.php b/demo/webman/backend/plugin/admin/config/database.php new file mode 100644 index 0000000000000000000000000000000000000000..82bbc4a2336a80877d3e3a018b5446287de30c13 --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/database.php @@ -0,0 +1,19 @@ + 'mysql', + 'connections' => [ + 'mysql' => [ + 'driver' => 'mysql', + 'host' => '127.0.0.1', + 'port' => '3306', + 'database' => 'webman_admin', + 'username' => 'root', + 'password' => 'root', + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_general_ci', + 'prefix' => '', + 'strict' => true, + 'engine' => null, + ], + ], +]; \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/config/dependence.php b/demo/webman/backend/plugin/admin/config/dependence.php new file mode 100644 index 0000000000000000000000000000000000000000..8e964edabcb6ba3ebce02219fb84067c36380824 --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/dependence.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return []; \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/config/event.php b/demo/webman/backend/plugin/admin/config/event.php new file mode 100644 index 0000000000000000000000000000000000000000..639e43539362b4a49aa95d9bcdb20ec2954a3ddf --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/event.php @@ -0,0 +1,5 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use plugin\admin\app\exception\Handler; + +return [ + '' => Handler::class, +]; \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/config/log.php b/demo/webman/backend/plugin/admin/config/log.php new file mode 100644 index 0000000000000000000000000000000000000000..7f05de574f38580b47324bd4d65e4dbedd05f994 --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/log.php @@ -0,0 +1,32 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'default' => [ + 'handlers' => [ + [ + 'class' => Monolog\Handler\RotatingFileHandler::class, + 'constructor' => [ + runtime_path() . '/logs/webman.log', + 7, //$maxFiles + Monolog\Logger::DEBUG, + ], + 'formatter' => [ + 'class' => Monolog\Formatter\LineFormatter::class, + 'constructor' => [null, 'Y-m-d H:i:s', true], + ], + ] + ], + ], +]; diff --git a/demo/webman/backend/plugin/admin/config/menu.php b/demo/webman/backend/plugin/admin/config/menu.php new file mode 100644 index 0000000000000000000000000000000000000000..9bdc7e1e23e1b9df7314a51efc646191c48a14d8 --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/menu.php @@ -0,0 +1,433 @@ + '数据库', + 'key' => 'database', + 'icon' => 'layui-icon-template-1', + 'weight' => 1000, + 'type' => 0, + 'children' => [ + [ + 'title' => '所有表', + 'key' => 'plugin\\admin\\app\\controller\\TableController', + 'href' => '/app/admin/table/index', + 'type' => 1, + 'weight' => 800, + ] + ] + ], + [ + 'title' => '权限管理', + 'key' => 'auth', + 'icon' => 'layui-icon-vercode', + 'weight' => 900, + 'type' => 0, + 'children' => [ + [ + 'title' => '账户管理', + 'key' => 'plugin\\admin\\app\\controller\\AdminController', + 'href' => '/app/admin/admin/index', + 'type' => 1, + 'weight' => 1000, + ], + [ + 'title' => '角色管理', + 'key' => 'plugin\\admin\\app\\controller\\RoleController', + 'href' => '/app/admin/role/index', + 'type' => 1, + 'weight' => 900, + ], + [ + 'title' => '菜单管理', + 'key' => 'plugin\\admin\\app\\controller\\RuleController', + 'href' => '/app/admin/rule/index', + 'type' => 1, + 'weight' => 800, + ], + ] + ], + [ + 'title' => '会员管理', + 'key' => 'user', + 'icon' => 'layui-icon-username', + 'weight' => 800, + 'type' => 0, + 'children' => [ + [ + 'title' => '用户', + 'key' => 'plugin\\admin\\app\\controller\\UserController', + 'href' => '/app/admin/user/index', + 'type' => 1, + 'weight' => 800, + ] + ] + ], + [ + 'title' => '通用设置', + 'key' => 'common', + 'icon' => 'layui-icon-set', + 'weight' => 700, + 'type' => 0, + 'children' => [ + [ + 'title' => '个人资料', + 'key' => 'plugin\\admin\\app\\controller\\AccountController', + 'href' => '/app/admin/account/index', + 'type' => 1, + 'weight' => 800, + ], + [ + 'title' => '附件管理', + 'key' => 'plugin\\admin\\app\\controller\\UploadController', + 'href' => '/app/admin/upload/index', + 'type' => 1, + 'weight' => 700, + ], + [ + 'title' => '字典设置', + 'key' => 'plugin\\admin\\app\\controller\\DictController', + 'href' => '/app/admin/dict/index', + 'type' => 1, + 'weight' => 600, + ], + [ + 'title' => '系统设置', + 'key' => 'plugin\\admin\\app\\controller\\ConfigController', + 'href' => '/app/admin/config/index', + 'type' => 1, + 'weight' => 500, + ], + ] + ], + [ + 'title' => '插件管理', + 'key' => 'plugin', + 'icon' => 'layui-icon-app', + 'weight' => 600, + 'type' => 0, + 'children' => [ + [ + 'title' => '应用插件', + 'key' => 'plugin\\admin\\app\\controller\\PluginController', + 'href' => '/app/admin/plugin/index', + 'weight' => 800, + 'type' => 1, + ] + ] + ], + [ + 'title' => '开发辅助', + 'key' => 'dev', + 'icon' => 'layui-icon-fonts-code', + 'weight' => 500, + 'type' => 0, + 'children' => [ + [ + 'title' => '表单构建', + 'key' => 'plugin\\admin\\app\\controller\\DevController', + 'href' => '/app/admin/dev/form-build', + 'weight' => 800, + 'type' => 1, + ], + ] + ], + [ + 'title' => '示例页面', + 'key' => 'demos', + 'icon' => 'layui-icon-templeate-1', + 'weight' => 400, + 'type' => 0, + 'children' => [ + [ + 'key' => 'demo1', + 'title' => '工作空间', + 'type' => 0, + 'icon' => 'layui-icon-console', + 'href' => '', + 'children' => [ + [ + 'key' => 'demo10', + 'title' => '控制后台', + 'icon' => 'layui-icon-console', + 'type' => 1, + 'href' => '/app/admin/demos/console/console1.html' + ], [ + 'key' => 'demo13', + 'title' => '数据分析', + 'icon' => 'layui-icon-console', + 'type' => 1, + 'href' => '/app/admin/demos/console/console2.html' + ], [ + 'key' => 'demo14', + 'title' => '百度一下', + 'icon' => 'layui-icon-console', + 'type' => 1, + 'href' => 'http://www.baidu.com' + ], [ + 'key' => 'demo15', + 'title' => '主题预览', + 'icon' => 'layui-icon-console', + 'type' => 1, + 'href' => '/app/admin/demos/system/theme.html' + ] + ] + ], + [ + 'key' => 'demo20', + 'title' => '常用组件', + 'icon' => 'layui-icon-component', + 'type' => 0, + 'href' => '', + 'children' => [ + [ + 'key' => 'demo2011', + 'title' => '功能按钮', + 'icon' => 'layui-icon-face-smile', + 'type' => 1, + 'href' => '/app/admin/demos/document/button.html' + ], [ + 'key' => 'demo2014', + 'title' => '表单集合', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/form.html' + ], [ + 'key' => 'demo2010', + 'title' => '字体图标', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/icon.html' + ], [ + 'key' => 'demo2012', + 'title' => '多选下拉', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/select.html' + ], [ + 'key' => 'demo2013', + 'title' => '动态标签', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/tag.html' + ], [ + 'key' => 'demo2031', + 'title' => '数据表格', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/table.html' + ], [ + 'key' => 'demo2032', + 'title' => '分布表单', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/step.html' + ], [ + 'key' => 'demo2033', + 'title' => '树形表格', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/treetable.html' + ], [ + 'key' => 'demo2034', + 'title' => '树状结构', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/dtree.html' + ], [ + 'key' => 'demo2035', + 'title' => '文本编辑', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/tinymce.html' + ], [ + 'key' => 'demo2036', + 'title' => '卡片组件', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/card.html' + ], [ + 'key' => 'demo2021', + 'title' => '抽屉组件', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/drawer.html' + ], [ + 'key' => 'demo2022', + 'title' => '消息通知', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/notice.html' + ], [ + 'key' => 'demo2024', + 'title' => '加载组件', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/loading.html' + ], [ + 'key' => 'demo2023', + 'title' => '弹层组件', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/popup.html' + ], [ + 'key' => 'demo60131', + 'title' => '多选项卡', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/tab.html' + ], [ + 'key' => 'demo60132', + 'title' => '数据菜单', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/menu.html' + ], [ + 'key' => 'demo2041', + 'title' => '哈希加密', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/encrypt.html' + ], [ + 'key' => 'demo2042', + 'title' => '图标选择', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/iconPicker.html' + ], [ + 'key' => 'demo2043', + 'title' => '省市级联', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/area.html' + ], [ + 'key' => 'demo2044', + 'title' => '数字滚动', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/count.html' + ], [ + 'key' => 'demo2045', + 'title' => '顶部返回', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/document/topBar.html' + ] + ] + ], + [ + 'key' => 'demo666', + 'title' => '结果页面', + 'icon' => 'layui-icon-auz', + 'type' => 0, + 'href' => '', + 'children' => [ + [ + 'key' => 'demo667', + 'title' => '成功', + 'icon' => 'layui-icon-face-smile', + 'type' => 1, + 'href' => '/app/admin/demos/result/success.html' + ], [ + 'key' => 'demo668', + 'title' => '失败', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/result/error.html' + ] + ] + ], + [ + 'key' => 'demo-error', + 'title' => '错误页面', + 'icon' => 'layui-icon-face-cry', + 'type' => 0, + 'href' => '', + 'children' => [ + [ + 'key' => 'demo403', + 'title' => '403', + 'icon' => 'layui-icon-face-smile', + 'type' => 1, + 'href' => '/app/admin/demos/error/403.html' + ], [ + 'key' => 'demo404', + 'title' => '404', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/error/404.html' + ], [ + 'key' => 'demo500', + 'title' => '500', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/error/500.html' + ] + + ] + ], + [ + 'key' => 'demo-system', + 'title' => '系统管理', + 'icon' => 'layui-icon-set-fill', + 'type' => 0, + 'href' => '', + 'children' => [ + [ + 'key' => 'demo601', + 'title' => '用户管理', + 'icon' => 'layui-icon-face-smile', + 'type' => 1, + 'href' => '/app/admin/demos/system/user.html' + ], [ + 'key' => 'demo602', + 'title' => '角色管理', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/system/role.html' + ], [ + 'key' => 'demo603', + 'title' => '权限管理', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/system/power.html' + ], [ + 'key' => 'demo604', + 'title' => '部门管理', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/system/deptment.html' + ], [ + 'key' => 'demo605', + 'title' => '行为日志', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/system/log.html' + ], [ + 'key' => 'demo606', + 'title' => '数据字典', + 'icon' => 'layui-icon-face-cry', + 'type' => 1, + 'href' => '/app/admin/demos/system/dict.html' + ] + ] + ], + [ + 'key' => 'demo-common', + 'title' => '常用页面', + 'icon' => 'layui-icon-template-1', + 'type' => 0, + 'href' => '', + 'children' => [ + [ + 'key' => 'demo702', + 'title' => '空白页面', + 'icon' => 'layui-icon-face-smile', + 'type' => 1, + 'href' => '/app/admin/demos/system/space.html' + ] + ] + ] + ] + ] +]; diff --git a/demo/webman/backend/plugin/admin/config/middleware.php b/demo/webman/backend/plugin/admin/config/middleware.php new file mode 100644 index 0000000000000000000000000000000000000000..7be60acaba782334e5d3be768389d5ce150efb6e --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/middleware.php @@ -0,0 +1,21 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use plugin\admin\app\middleware\AccessControl; + +return [ + '' => [ + AccessControl::class, + ] +]; \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/config/redis.php b/demo/webman/backend/plugin/admin/config/redis.php new file mode 100644 index 0000000000000000000000000000000000000000..2f9757a8d47d2f2569dc53c5717a855facb04771 --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/redis.php @@ -0,0 +1,22 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'default' => [ + 'host' => '127.0.0.1', + 'password' => null, + 'port' => 6379, + 'database' => 0, + ], +]; diff --git a/demo/webman/backend/plugin/admin/config/route.php b/demo/webman/backend/plugin/admin/config/route.php new file mode 100644 index 0000000000000000000000000000000000000000..ca57fd9e910af8619e951fb58448dd14a60c9d3f --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/route.php @@ -0,0 +1,26 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use plugin\admin\app\controller\AccountController; +use plugin\admin\app\controller\DictController; +use Webman\Route; +use support\Request; + +Route::any('/app/admin/account/captcha/{type}', [AccountController::class, 'captcha']); + +Route::any('/app/admin/dict/get/{name}', [DictController::class, 'get']); + +Route::fallback(function (Request $request) { + return response($request->uri() . ' not found' , 404); +}, 'admin'); diff --git a/demo/webman/backend/plugin/admin/config/static.php b/demo/webman/backend/plugin/admin/config/static.php new file mode 100644 index 0000000000000000000000000000000000000000..6313679646163f823c041c8e242539dd5d9e3fc8 --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/static.php @@ -0,0 +1,23 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Static file settings + */ +return [ + 'enable' => true, + 'middleware' => [ // Static file Middleware + //app\middleware\StaticFile::class, + ], +]; \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/config/thinkorm.php b/demo/webman/backend/plugin/admin/config/thinkorm.php new file mode 100644 index 0000000000000000000000000000000000000000..c0689417e02c51cc3b78e8fbceadabfb7223d2b3 --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/thinkorm.php @@ -0,0 +1,35 @@ + 'mysql', + 'connections' => [ + 'mysql' => [ + // 数据库类型 + 'type' => 'mysql', + // 服务器地址 + 'hostname' => '127.0.0.1', + // 数据库名 + 'database' => 'webman_admin', + // 数据库用户名 + 'username' => 'root', + // 数据库密码 + 'password' => 'root', + // 数据库连接端口 + 'hostport' => 3306, + // 数据库连接参数 + 'params' => [ + // 连接超时3秒 + \PDO::ATTR_TIMEOUT => 3, + ], + // 数据库编码默认采用utf8 + 'charset' => 'utf8mb4', + // 数据库表前缀 + 'prefix' => '', + // 断线重连 + 'break_reconnect' => true, + // 关闭SQL监听日志 + 'trigger_sql' => true, + // 自定义分页类 + 'bootstrap' => '' + ], + ], +]; \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/config/translation.php b/demo/webman/backend/plugin/admin/config/translation.php new file mode 100644 index 0000000000000000000000000000000000000000..800ec0a9d2bca346ac02b35ef19619d2435d1dd5 --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/translation.php @@ -0,0 +1,25 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Multilingual configuration + */ +return [ + // Default language + 'locale' => 'zh_CN', + // Fallback language + 'fallback_locale' => ['zh_CN', 'en'], + // Folder where language files are stored + 'path' => base_path() . '/plugin/admin/resource/translations' +]; diff --git a/demo/webman/backend/plugin/admin/config/view.php b/demo/webman/backend/plugin/admin/config/view.php new file mode 100644 index 0000000000000000000000000000000000000000..e3a7b8561c31e5b9960c6cc13fdc6a5396a9444e --- /dev/null +++ b/demo/webman/backend/plugin/admin/config/view.php @@ -0,0 +1,22 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use support\view\Raw; +use support\view\Twig; +use support\view\Blade; +use support\view\ThinkPHP; + +return [ + 'handler' => Raw::class +]; diff --git a/demo/webman/backend/plugin/admin/install.sql b/demo/webman/backend/plugin/admin/install.sql new file mode 100644 index 0000000000000000000000000000000000000000..739ee72e3720f222acc558c1bf7dc6c01d7471d1 --- /dev/null +++ b/demo/webman/backend/plugin/admin/install.sql @@ -0,0 +1,117 @@ + +CREATE TABLE IF NOT EXISTS `wa_admin_roles` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', + `role_id` int(11) NOT NULL COMMENT '角色id', + `admin_id` int(11) NOT NULL COMMENT '管理员id', + PRIMARY KEY (`id`), + UNIQUE KEY `role_admin_id` (`role_id`,`admin_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='管理员角色表'; + +CREATE TABLE IF NOT EXISTS `wa_admins` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', + `username` varchar(32) NOT NULL COMMENT '用户名', + `nickname` varchar(40) NOT NULL COMMENT '昵称', + `password` varchar(255) NOT NULL COMMENT '密码', + `avatar` varchar(255) DEFAULT '/app/admin/avatar.png' COMMENT '头像', + `email` varchar(100) DEFAULT NULL COMMENT '邮箱', + `mobile` varchar(16) DEFAULT NULL COMMENT '手机', + `created_at` datetime DEFAULT NULL COMMENT '创建时间', + `updated_at` datetime DEFAULT NULL COMMENT '更新时间', + `login_at` datetime DEFAULT NULL COMMENT '登录时间', + `status` tinyint(4) DEFAULT NULL COMMENT '禁用', + PRIMARY KEY (`id`), + UNIQUE KEY `username` (`username`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='管理员表'; + +CREATE TABLE IF NOT EXISTS `wa_options` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL COMMENT '键', + `value` longtext NOT NULL COMMENT '值', + `created_at` datetime NOT NULL DEFAULT '2022-08-15 00:00:00' COMMENT '创建时间', + `updated_at` datetime NOT NULL DEFAULT '2022-08-15 00:00:00' COMMENT '更新时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='选项表'; + + +LOCK TABLES `wa_options` WRITE; +INSERT INTO `wa_options` VALUES (1,'system_config','{\"logo\":{\"title\":\"Webman Admin\",\"image\":\"\\/app\\/admin\\/admin\\/images\\/logo.png\"},\"menu\":{\"data\":\"\\/app\\/admin\\/rule\\/get\",\"method\":\"GET\",\"accordion\":true,\"collapse\":false,\"control\":false,\"controlWidth\":500,\"select\":\"0\",\"async\":true},\"tab\":{\"enable\":true,\"keepState\":true,\"preload\":false,\"session\":true,\"max\":\"30\",\"index\":{\"id\":\"0\",\"href\":\"\\/app\\/admin\\/index\\/dashboard\",\"title\":\"\\u4eea\\u8868\\u76d8\"}},\"theme\":{\"defaultColor\":\"2\",\"defaultMenu\":\"light-theme\",\"defaultHeader\":\"light-theme\",\"allowCustom\":true,\"banner\":false},\"colors\":[{\"id\":\"1\",\"color\":\"#36b368\",\"second\":\"#f0f9eb\"},{\"id\":\"2\",\"color\":\"#2d8cf0\",\"second\":\"#ecf5ff\"},{\"id\":\"3\",\"color\":\"#f6ad55\",\"second\":\"#fdf6ec\"},{\"id\":\"4\",\"color\":\"#f56c6c\",\"second\":\"#fef0f0\"},{\"id\":\"5\",\"color\":\"#3963bc\",\"second\":\"#ecf5ff\"}],\"other\":{\"keepLoad\":\"500\",\"autoHead\":false,\"footer\":false},\"header\":{\"message\":false}}','2022-12-05 14:49:01','2022-12-08 20:20:28'),(2,'table_form_schema_wa_users','{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"主键\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"enable_sort\":true,\"searchable\":true,\"search_type\":\"normal\",\"form_show\":false},\"username\":{\"field\":\"username\",\"_field_id\":\"1\",\"comment\":\"用户名\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"nickname\":{\"field\":\"nickname\",\"_field_id\":\"2\",\"comment\":\"昵称\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"password\":{\"field\":\"password\",\"_field_id\":\"3\",\"comment\":\"密码\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"sex\":{\"field\":\"sex\",\"_field_id\":\"4\",\"comment\":\"性别\",\"control\":\"select\",\"control_args\":\"url:\\/app\\/admin\\/dict\\/get\\/sex\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"avatar\":{\"field\":\"avatar\",\"_field_id\":\"5\",\"comment\":\"头像\",\"control\":\"uploadImage\",\"control_args\":\"url:\\/app\\/admin\\/upload\\/avatar\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"email\":{\"field\":\"email\",\"_field_id\":\"6\",\"comment\":\"邮箱\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"mobile\":{\"field\":\"mobile\",\"_field_id\":\"7\",\"comment\":\"手机\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"level\":{\"field\":\"level\",\"_field_id\":\"8\",\"comment\":\"等级\",\"control\":\"inputNumber\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false},\"birthday\":{\"field\":\"birthday\",\"_field_id\":\"9\",\"comment\":\"生日\",\"control\":\"datePicker\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"between\",\"list_show\":false,\"enable_sort\":false},\"money\":{\"field\":\"money\",\"_field_id\":\"10\",\"comment\":\"余额(元)\",\"control\":\"inputNumber\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false},\"score\":{\"field\":\"score\",\"_field_id\":\"11\",\"comment\":\"积分\",\"control\":\"inputNumber\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false},\"last_time\":{\"field\":\"last_time\",\"_field_id\":\"12\",\"comment\":\"登录时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"between\",\"list_show\":false,\"enable_sort\":false},\"last_ip\":{\"field\":\"last_ip\",\"_field_id\":\"13\",\"comment\":\"登录ip\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false},\"join_time\":{\"field\":\"join_time\",\"_field_id\":\"14\",\"comment\":\"注册时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"between\",\"list_show\":false,\"enable_sort\":false},\"join_ip\":{\"field\":\"join_ip\",\"_field_id\":\"15\",\"comment\":\"注册ip\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false},\"token\":{\"field\":\"token\",\"_field_id\":\"16\",\"comment\":\"token\",\"control\":\"input\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"17\",\"comment\":\"创建时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"search_type\":\"between\",\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"18\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"between\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"role\":{\"field\":\"role\",\"_field_id\":\"19\",\"comment\":\"角色\",\"control\":\"inputNumber\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"status\":{\"field\":\"status\",\"_field_id\":\"20\",\"comment\":\"禁用\",\"control\":\"switch\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}','2022-08-15 00:00:00','2022-12-23 15:28:13'),(3,'table_form_schema_wa_roles','{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"主键\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"name\":{\"field\":\"name\",\"_field_id\":\"1\",\"comment\":\"角色组\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"rules\":{\"field\":\"rules\",\"_field_id\":\"2\",\"comment\":\"权限\",\"control\":\"treeSelectMulti\",\"control_args\":\"url:\\/app\\/admin\\/rule\\/get?type=0,1,2\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"3\",\"comment\":\"创建时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"4\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"pid\":{\"field\":\"pid\",\"_field_id\":\"5\",\"comment\":\"父级\",\"control\":\"select\",\"control_args\":\"url:\\/app\\/admin\\/role\\/select?format=tree\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}','2022-08-15 00:00:00','2022-12-19 14:24:25'),(4,'table_form_schema_wa_rules','{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"主键\",\"control\":\"inputNumber\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"title\":{\"field\":\"title\",\"_field_id\":\"1\",\"comment\":\"标题\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"icon\":{\"field\":\"icon\",\"_field_id\":\"2\",\"comment\":\"图标\",\"control\":\"iconPicker\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"key\":{\"field\":\"key\",\"_field_id\":\"3\",\"comment\":\"标识\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"pid\":{\"field\":\"pid\",\"_field_id\":\"4\",\"comment\":\"上级菜单\",\"control\":\"treeSelect\",\"control_args\":\"\\/app\\/admin\\/rule\\/select?format=tree&type=0,1\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"5\",\"comment\":\"创建时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"6\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"href\":{\"field\":\"href\",\"_field_id\":\"7\",\"comment\":\"url\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"type\":{\"field\":\"type\",\"_field_id\":\"8\",\"comment\":\"类型\",\"control\":\"select\",\"control_args\":\"data:0:目录,1:菜单,2:权限\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"weight\":{\"field\":\"weight\",\"_field_id\":\"9\",\"comment\":\"排序\",\"control\":\"inputNumber\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}','2022-08-15 00:00:00','2022-12-08 11:44:45'),(5,'table_form_schema_wa_admins','{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"ID\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"enable_sort\":true,\"search_type\":\"between\",\"form_show\":false,\"searchable\":false},\"username\":{\"field\":\"username\",\"_field_id\":\"1\",\"comment\":\"用户名\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"nickname\":{\"field\":\"nickname\",\"_field_id\":\"2\",\"comment\":\"昵称\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"password\":{\"field\":\"password\",\"_field_id\":\"3\",\"comment\":\"密码\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"avatar\":{\"field\":\"avatar\",\"_field_id\":\"4\",\"comment\":\"头像\",\"control\":\"uploadImage\",\"control_args\":\"url:\\/app\\/admin\\/upload\\/avatar\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"email\":{\"field\":\"email\",\"_field_id\":\"5\",\"comment\":\"邮箱\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"mobile\":{\"field\":\"mobile\",\"_field_id\":\"6\",\"comment\":\"手机\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"7\",\"comment\":\"创建时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"searchable\":true,\"search_type\":\"between\",\"list_show\":false,\"enable_sort\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"8\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"search_type\":\"normal\",\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"login_at\":{\"field\":\"login_at\",\"_field_id\":\"9\",\"comment\":\"登录时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"between\",\"enable_sort\":false,\"searchable\":false},\"status\":{\"field\":\"status\",\"_field_id\":\"10\",\"comment\":\"禁用\",\"control\":\"switch\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}','2022-08-15 00:00:00','2022-12-23 15:36:48'),(6,'table_form_schema_wa_options','{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"name\":{\"field\":\"name\",\"_field_id\":\"1\",\"comment\":\"键\",\"control\":\"input\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"value\":{\"field\":\"value\",\"_field_id\":\"2\",\"comment\":\"值\",\"control\":\"textArea\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"3\",\"comment\":\"创建时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"4\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false}}','2022-08-15 00:00:00','2022-12-08 11:36:57'),(7,'table_form_schema_wa_uploads','{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"主键\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"enable_sort\":true,\"search_type\":\"normal\",\"form_show\":false,\"searchable\":false},\"name\":{\"field\":\"name\",\"_field_id\":\"1\",\"comment\":\"名称\",\"control\":\"input\",\"control_args\":\"\",\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false},\"url\":{\"field\":\"url\",\"_field_id\":\"2\",\"comment\":\"文件\",\"control\":\"upload\",\"control_args\":\"url:\\/app\\/admin\\/upload\\/file\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"admin_id\":{\"field\":\"admin_id\",\"_field_id\":\"3\",\"comment\":\"管理员\",\"control\":\"select\",\"control_args\":\"url:\\/app\\/admin\\/admin\\/select?format=select\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"file_size\":{\"field\":\"file_size\",\"_field_id\":\"4\",\"comment\":\"文件大小\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"between\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"mime_type\":{\"field\":\"mime_type\",\"_field_id\":\"5\",\"comment\":\"mime类型\",\"control\":\"input\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"image_width\":{\"field\":\"image_width\",\"_field_id\":\"6\",\"comment\":\"图片宽度\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"image_height\":{\"field\":\"image_height\",\"_field_id\":\"7\",\"comment\":\"图片高度\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"ext\":{\"field\":\"ext\",\"_field_id\":\"8\",\"comment\":\"扩展名\",\"control\":\"input\",\"control_args\":\"\",\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false},\"storage\":{\"field\":\"storage\",\"_field_id\":\"9\",\"comment\":\"存储位置\",\"control\":\"input\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"10\",\"comment\":\"上传时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"searchable\":true,\"search_type\":\"between\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false},\"category\":{\"field\":\"category\",\"_field_id\":\"11\",\"comment\":\"类别\",\"control\":\"select\",\"control_args\":\"url:\\/app\\/admin\\/dict\\/get\\/upload\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"12\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}','2022-08-15 00:00:00','2022-12-08 11:47:45'),(8,'table_form_schema_wa_uploads','{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"主键\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"enable_sort\":true,\"search_type\":\"normal\",\"form_show\":false,\"searchable\":false},\"name\":{\"field\":\"name\",\"_field_id\":\"1\",\"comment\":\"名称\",\"control\":\"input\",\"control_args\":\"\",\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false},\"url\":{\"field\":\"url\",\"_field_id\":\"2\",\"comment\":\"文件\",\"control\":\"upload\",\"control_args\":\"url:\\/app\\/admin\\/upload\\/file\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"admin_id\":{\"field\":\"admin_id\",\"_field_id\":\"3\",\"comment\":\"管理员\",\"control\":\"select\",\"control_args\":\"url:\\/app\\/admin\\/admin\\/select?format=select\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"file_size\":{\"field\":\"file_size\",\"_field_id\":\"4\",\"comment\":\"文件大小\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"between\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"mime_type\":{\"field\":\"mime_type\",\"_field_id\":\"5\",\"comment\":\"mime类型\",\"control\":\"input\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"image_width\":{\"field\":\"image_width\",\"_field_id\":\"6\",\"comment\":\"图片宽度\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"image_height\":{\"field\":\"image_height\",\"_field_id\":\"7\",\"comment\":\"图片高度\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false,\"searchable\":false},\"ext\":{\"field\":\"ext\",\"_field_id\":\"8\",\"comment\":\"扩展名\",\"control\":\"input\",\"control_args\":\"\",\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"form_show\":false,\"enable_sort\":false},\"storage\":{\"field\":\"storage\",\"_field_id\":\"9\",\"comment\":\"存储位置\",\"control\":\"input\",\"control_args\":\"\",\"search_type\":\"normal\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false,\"searchable\":false},\"created_at\":{\"field\":\"created_at\",\"_field_id\":\"10\",\"comment\":\"上传时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"searchable\":true,\"search_type\":\"between\",\"form_show\":false,\"list_show\":false,\"enable_sort\":false},\"category\":{\"field\":\"category\",\"_field_id\":\"11\",\"comment\":\"类别\",\"control\":\"select\",\"control_args\":\"url:\\/app\\/admin\\/dict\\/get\\/upload\",\"form_show\":true,\"list_show\":true,\"searchable\":true,\"search_type\":\"normal\",\"enable_sort\":false},\"updated_at\":{\"field\":\"updated_at\",\"_field_id\":\"12\",\"comment\":\"更新时间\",\"control\":\"dateTimePicker\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}','2022-08-15 00:00:00','2022-12-08 11:47:45'),(9,'dict_upload','[{\"value\":\"1\",\"name\":\"分类1\"},{\"value\":\"2\",\"name\":\"分类2\"},{\"value\":\"3\",\"name\":\"分类3\"}]','2022-12-04 16:24:13','2022-12-04 16:24:13'),(10,'dict_sex','[{\"value\":\"0\",\"name\":\"女\"},{\"value\":\"1\",\"name\":\"男\"}]','2022-12-04 15:04:40','2022-12-04 15:04:40'),(11,'dict_status','[{\"value\":\"0\",\"name\":\"正常\"},{\"value\":\"1\",\"name\":\"禁用\"}]','2022-12-04 15:05:09','2022-12-04 15:05:09'),(17,'table_form_schema_wa_admin_roles','{\"id\":{\"field\":\"id\",\"_field_id\":\"0\",\"comment\":\"主键\",\"control\":\"inputNumber\",\"control_args\":\"\",\"list_show\":true,\"enable_sort\":true,\"searchable\":true,\"search_type\":\"normal\",\"form_show\":false},\"role_id\":{\"field\":\"role_id\",\"_field_id\":\"1\",\"comment\":\"角色id\",\"control\":\"inputNumber\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false},\"admin_id\":{\"field\":\"admin_id\",\"_field_id\":\"2\",\"comment\":\"管理员id\",\"control\":\"inputNumber\",\"control_args\":\"\",\"form_show\":true,\"list_show\":true,\"search_type\":\"normal\",\"enable_sort\":false,\"searchable\":false}}','2022-08-15 00:00:00','2022-12-20 19:42:51'); +UNLOCK TABLES; + +CREATE TABLE IF NOT EXISTS `wa_roles` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `name` varchar(80) NOT NULL COMMENT '角色组', + `rules` text COMMENT '权限', + `created_at` datetime NOT NULL COMMENT '创建时间', + `updated_at` datetime NOT NULL COMMENT '更新时间', + `pid` int(10) unsigned DEFAULT NULL COMMENT '父级', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='管理员角色'; + +LOCK TABLES `wa_roles` WRITE; +INSERT INTO `wa_roles` VALUES (1,'超级管理员','*','2022-08-13 16:15:01','2022-12-23 12:05:07',NULL); +UNLOCK TABLES; + +CREATE TABLE IF NOT EXISTS `wa_rules` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `title` varchar(255) NOT NULL COMMENT '标题', + `icon` varchar(255) DEFAULT NULL COMMENT '图标', + `key` varchar(255) NOT NULL COMMENT '标识', + `pid` int(10) unsigned DEFAULT '0' COMMENT '上级菜单', + `created_at` datetime NOT NULL COMMENT '创建时间', + `updated_at` datetime NOT NULL COMMENT '更新时间', + `href` varchar(255) DEFAULT NULL COMMENT 'url', + `type` int(11) NOT NULL DEFAULT '1' COMMENT '类型', + `weight` int(11) DEFAULT '0' COMMENT '排序', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='权限规则'; + + +CREATE TABLE IF NOT EXISTS `wa_uploads` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', + `name` varchar(128) NOT NULL COMMENT '名称', + `url` varchar(255) NOT NULL COMMENT '文件', + `admin_id` int(11) DEFAULT NULL COMMENT '管理员', + `file_size` int(11) NOT NULL COMMENT '文件大小', + `mime_type` varchar(255) NOT NULL COMMENT 'mime类型', + `image_width` int(11) DEFAULT NULL COMMENT '图片宽度', + `image_height` int(11) DEFAULT NULL COMMENT '图片高度', + `ext` varchar(128) NOT NULL COMMENT '扩展名', + `storage` varchar(255) NOT NULL DEFAULT 'local' COMMENT '存储位置', + `created_at` date DEFAULT NULL COMMENT '上传时间', + `category` varchar(128) DEFAULT NULL COMMENT '类别', + `updated_at` date DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `category` (`category`), + KEY `admin_id` (`admin_id`), + KEY `name` (`name`), + KEY `ext` (`ext`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='附件'; + +CREATE TABLE IF NOT EXISTS `wa_users` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `username` varchar(32) NOT NULL COMMENT '用户名', + `nickname` varchar(40) NOT NULL COMMENT '昵称', + `password` varchar(255) NOT NULL COMMENT '密码', + `sex` enum('0','1') NOT NULL DEFAULT '1' COMMENT '性别', + `avatar` varchar(255) DEFAULT NULL COMMENT '头像', + `email` varchar(128) DEFAULT NULL COMMENT '邮箱', + `mobile` varchar(16) DEFAULT NULL COMMENT '手机', + `level` tinyint(4) NOT NULL DEFAULT '0' COMMENT '等级', + `birthday` date DEFAULT NULL COMMENT '生日', + `money` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '余额(元)', + `score` int(11) NOT NULL DEFAULT '0' COMMENT '积分', + `last_time` datetime DEFAULT NULL COMMENT '登录时间', + `last_ip` varchar(50) DEFAULT NULL COMMENT '登录ip', + `join_time` datetime DEFAULT NULL COMMENT '注册时间', + `join_ip` varchar(50) DEFAULT NULL COMMENT '注册ip', + `token` varchar(50) DEFAULT NULL COMMENT 'token', + `created_at` datetime DEFAULT NULL COMMENT '创建时间', + `updated_at` datetime DEFAULT NULL COMMENT '更新时间', + `role` int(11) NOT NULL DEFAULT '1' COMMENT '角色', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '禁用', + PRIMARY KEY (`id`), + UNIQUE KEY `username` (`username`), + KEY `join_time` (`join_time`), + KEY `mobile` (`mobile`), + KEY `email` (`email`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户表'; diff --git a/demo/webman/backend/plugin/admin/public/admin/css/admin.css b/demo/webman/backend/plugin/admin/public/admin/css/admin.css new file mode 100644 index 0000000000000000000000000000000000000000..a6651d8089e3f421cbe06d95ebff33decf7ddd6c --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/admin/css/admin.css @@ -0,0 +1,558 @@ +html, +body, +.layui-layout { + height: 100%; +} + +.pear-admin .layui-header, +.pear-admin .layui-body, +.pear-admin .layui-logo, +.pear-admin .layui-side, +.pear-admin .layui-header .layui-layout-left { + transition: all .3s; +} + +.pear-admin.banner-layout .layui-side { + top: 60px!important; +} + +.pear-admin.banner-layout .layui-side .layui-logo { + display: none; +} + +.pear-admin.banner-layout .layui-header .layui-logo { + display: inline-block; +} + +.pear-admin.banner-layout .layui-side .layui-side-scroll { + height: 100%!important; +} + +.pear-admin.banner-layout .layui-side .layui-side-scroll { + height: 100%!important; +} + +.pear-admin .layui-header.dark-theme .layui-layout-control .layui-this *{ + background-color: rgba(0,0,0,.1)!important; +} + +.pear-admin.banner-layout .layui-header { + z-index: 99999; + width: 100%; + left: 0px; +} + +.pear-admin.banner-layout .layui-header .layui-layout-left { + left: 230px; +} + +.pear-admin.banner-layout .layui-header .layui-logo .title { + top: 2px; +} + +.pear-admin.banner-layout .layui-header .layui-layout-control { + display: inline-block; + left: 370px; +} + +.pear-admin.banner-layout .layui-header.dark-theme { + box-shadow: 2px 0 6px rgb(0 21 41 / 35%); +} + +.pear-admin .layui-header .layui-logo { + display: none; +} + +.pear-admin .layui-logo .title { + font-size: 20px; +} + +.pear-admin .layui-layout-right .layui-nav-child { + border: 1px solid whitesmoke; + border-radius: 4px; + width: auto; + left: auto; + right: -23px; +} + +.pear-admin .layui-header { + left: 230px; + width: calc(100% - 230px); + background-color: white; + border-bottom: 1px solid whitesmoke; +} + +.pear-admin .layui-layout-control { + left: 140px; + position: absolute; +} + +.pear-admin .layui-layout-control .layui-nav { + padding: 0px; +} + +.pear-admin .layui-logo { + width: 230px; + height: 59px; + line-height: 59px; + position: relative; + background-color: #001529; + border-bottom: 1px solid rgba(0, 0, 0, .12); +} + +.pear-admin .layui-logo img { + width: 34px; + height: 34px; +} + +.pear-admin .layui-logo .title { + font-size: 21px; + font-weight: 550; + color: #5FB878; + position: relative; + top: 5px; + margin-left: 5px; +} + +.pear-admin .layui-logo .logo { + display: none; +} + +.pear-admin .layui-side { + top: 0px; + width: 230px; + box-shadow: 2px 0 6px rgba(0, 21, 41, .20); + z-index: 9999; +} + +.pear-admin .layui-side-scroll::-webkit-scrollbar { + width: 0px; + height: 0px; +} + +.pear-admin .layui-side-scroll { + height: calc(100% - 60px) !important; + background-color: #001529; + width: 247px; + +} + +.pear-admin .layui-header .layui-nav .layui-nav-item>a { + color: black; + font-size: 15px; +} + +.pear-admin .layui-body { + left: 230px; + bottom: 0px; + padding-bottom: 0px; +} + +.pear-admin .layui-layout-left { + left: 0px; +} + +.pear-admin .layui-footer { + position: absolute; + display: flex; + justify-content: space-between; + left: 230px; + background: #fff; + border-top: 1px solid #F2F2F2; + box-shadow: none; + -webkit-transition: left .3s; + transition: left .3s; + overflow: hidden; + color: #3c3c3cb3; + font-weight: 300; + font-size: 13.6px; +} + +.pear-admin .layui-footer.close { + display: none; +} + +/** 收缩布局 */ +.pear-mini .layui-side .layui-logo .title { + display: none; +} + +.pear-mini .layui-side .layui-logo .logo { + display: inline-block; +} + +.pear-mini .layui-side { + width: 60px; +} + +.pear-mini .layui-header { + left: 60px; + width: calc(100% - 60px); +} + +.pear-mini .layui-body { + left: 60px; +} + +.pear-mini .layui-side .layui-logo { + width: 60px; +} + +.pear-mini .layui-footer { + left: 60px; +} + +.pear-mini .layui-nav-tree .layui-nav-item span { + display: none; +} + +.pear-mini .bottom-nav li { + width: 100% !important; +} + +.pear-mini .layui-side-scroll { + height: calc(100% - 60px); +} + +.pear-admin .layui-header .layui-nav .layui-nav-bar { + top: 0px !important; + height: 2px !important; + background-color: #5FB878; +} + +.pear-admin .layui-header .layui-nav .layui-this:after { + display: none; +} + +.pear-admin .layui-header .layui-nav-more { + display: none; +} + +.pear-collapsed-pe { + display: none; + width: 50px; + position: absolute; + z-index: 400000; + bottom: 30px; + right: 30px; + background-color: #5FB878 !important; + height: 50px; + line-height: 50px; + text-align: center; + border-radius: 50px; + box-shadow: 2px 0 6px rgba(0, 21, 41, .35); +} + +.pear-collapsed-pe a { + color: white !important; +} + +@media screen and (min-width: 768px) { + .layui-hide-sm { + display: inline-block !important; + } +} + +@media screen and (min-width: 769px) { + .layui-hide-sm { + display: none !important; + } +} + +/** 新增兼容 */ +@media screen and (max-width:768px) { + .collapse { + display: none !important; + } + + .pear-collapsed-pe { + display: inline-block !important; + } + + .layui-layout-control { + left: 45px !important; + } + + .layui-layout-left { + padding-left: 10px; + padding-right: 10px; + } + + .pear-mini .bottom-nav { + display: none; + } + + .pear-mini .layui-side-scroll { + height: calc(100% - 62px); + } + + .pear-mini .layui-side { + width: 0px; + } + + .pear-mini .layui-header { + left: 0px; + width: 100%; + } + + .pear-mini .layui-body { + left: 0px; + } + + .pear-mini .layui-footer { + left: 0px; + } + + .pear-mini .layui-logo { + width: 0px; + } + + .pear-admin .layui-body { + left: 0px; + } + + .pear-admin .layui-header { + left: 0px; + width: 100%; + } + + .pear-admin .pear-cover { + width: 100%; + height: 100%; + background-color: #1E1E1E; + display: block; + position: absolute; + z-index: 1000; + opacity: 0; + margin-top: -60px; + } + + .pear-mini .pear-cover { + display: none; + } +} + +@-webkit-keyframes am-horizontal-roll_show { + 0% { + opacity: 1; + -webkit-transform: translateX(2000px); + transform: translateX(2000px) + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0) + } +} + +@keyframes am-horizontal-roll_show { + 0% { + opacity: 1; + -webkit-transform: translateX(800px); + -ms-transform: translateX(800px); + transform: translateX(800px) + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0) + } +} + +.layer-anim-right { + -webkit-animation: am-horizontal-roll_show .6s ease-out; + animation: am-horizontal-roll_show .6s ease-out; + +} + +/** 侧边主题 (亮) */ +.light-theme.layui-side { + box-shadow: 2px 0 8px 0 rgba(29, 35, 41, .05) !important; +} + +.light-theme.layui-side .layui-logo { + background-color: white !important; + color: black !important; + border-bottom: 1px whitesmoke solid; +} + +.light-theme.layui-side .layui-side-scroll { + background-color: white !important; + color: black !important; +} + +.dark-theme.layui-header { + border-bottom: none; + background-color: #001529; + color: whitesmoke; +} + +.dark-theme.layui-header li>a{ + color: whitesmoke!important; +} + +.dark-theme.layui-header .layui-logo { + box-shadow: none; + border: none; +} + + +/** 顶部主题 (白) */ +.light-theme.layui-header .layui-logo { + background-color: white; + border: none; + box-shadow: none; +} + +/** 主题面板 */ +.pearone-color .set-text { + height: 42px; + line-height: 42px; +} + +.pearone-color .color-title { + padding: 15px 0 0px 20px; + margin-bottom: 4px; +} + +.pearone-color .color-content { + padding: 15px 10px 0 20px; +} + +.pearone-color .color-content ul { + list-style: none; + padding: 0px; +} + +.pearone-color .color-content ul li { + position: relative; + display: inline-block; + vertical-align: top; + width: 70px; + height: 50px; + margin: 0 20px 20px 0; + padding: 2px 2px 2px 2px; + background-color: #f2f2f2; + cursor: pointer; + font-size: 12px; + color: #666; +} + +.pearone-color .color-content li.layui-this:after, +.pearone-color .color-content li:hover:after { + width: 100%; + height: 100%; + padding: 4px; + top: -5px; + left: -5px; + border: #5FB878 2px solid; + opacity: 1; + border-radius: 4px; +} + +.pearone-color .color-content li:after { + content: ''; + position: absolute; + z-index: 20; + top: 50%; + left: 50%; + width: 1px; + height: 0; + border: 2px solid #F2F2F2; + transition: all .3s; + -webkit-transition: all .3s; + opacity: 0; +} + +.select-color { + margin-bottom: 30px; +} + +.select-color .select-color-title { + padding: 15px 0 0px 20px; + margin-bottom: 4px; +} + +.select-color .select-color-content { + padding: 20px 0 0px 0px; + margin-bottom: 4px; +} + +.select-color .select-color-content .select-color-item { + background-color: gray; + width: 30px; + height: 30px; + border-radius: 3px; + float: left; + margin-left: 20px; + color: white; + font-size: 18px; + text-align: center; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .15); + line-height: 30px; +} + +.message .layui-tab-title li:not(:last-child) { + border-right: 1px solid #eee; +} + +/* 搜索面板 */ +.menu-search-content .layui-input { + padding-left: 30px; +} + +.menu-search-content { + display: flex; + flex-wrap: wrap; + justify-content: center; +} + +.menu-search-input-wrapper { + width: 100%; + padding: 15px 15px; +} + +.menu-search-no-data { + display: flex; + justify-content: center; + width: 100%; + height: 122px; + align-items: center; +} + +.menu-search-list { + width: 100%; + padding: 5px 15px; +} + +.menu-search-list li { + position: relative; + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: nowrap; + height: 50px; + margin-bottom: 8px; + padding: 0px 10px; + color: currentColor; + font-size: 14px; + border-radius: 4px; + box-shadow: 0 1px 3px #d4d9e1; + cursor: pointer; + background-color: #fff; +} + +.menu-search-list li:hover { + background-color: #5FB878; + color: white; +} + +.menu-search-list li.this { + background-color: #5FB878; + color: white; +} + +/* 搜索面板结束 */ \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/admin/css/loader.css b/demo/webman/backend/plugin/admin/public/admin/css/loader.css new file mode 100644 index 0000000000000000000000000000000000000000..0f6d247c93675402b9d965ce2c206d661a569cb0 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/admin/css/loader.css @@ -0,0 +1,105 @@ +.loader-main{ + position: fixed; + width: 100%; + height: 100%; + background-color: whitesmoke; + z-index: 9999999; +} +.loader { + width: 50px; + height: 50px; + margin: 30px auto 40px; + margin-top: 20%; + position: relative; + z-index: 999999; + background-color: whitesmoke; +} +.loader:before { + content: ""; + width: 50px; + height: 7px; + border-radius: 50%; + background: #000; + opacity: 0.1; + position: absolute; + top: 59px; + left: 0; + animation: shadow .5s linear infinite; +} +.loader:after { + content: ""; + width: 50px; + height: 50px; + border-radius: 3px; + background-color: #5FB878; + position: absolute; + top: 0; + left: 0; + animation: loading .5s linear infinite; +} +@-webkit-keyframes loading { + 17% { + border-bottom-right-radius: 3px; + } + + 25% { + transform: translateY(9px) rotate(22.5deg); + } + + 50% { + transform: translateY(18px) scale(1, 0.9) rotate(45deg); + border-bottom-right-radius: 40px; + } + + 75% { + transform: translateY(9px) rotate(67.5deg); + } + + 100% { + transform: translateY(0) rotate(90deg); + } +} +@keyframes loading { + 17% { + border-bottom-right-radius: 3px; + } + + 25% { + transform: translateY(9px) rotate(22.5deg); + } + + 50% { + transform: translateY(18px) scale(1, 0.9) rotate(45deg); + border-bottom-right-radius: 40px; + } + + 75% { + transform: translateY(9px) rotate(67.5deg); + } + + 100% { + transform: translateY(0) rotate(90deg); + } +} +@-webkit-keyframes shadow { + + 0%, + 100% { + transform: scale(1, 1); + } + + 50% { + transform: scale(1.2, 1); + } +} +@keyframes shadow { + + 0%, + 100% { + transform: scale(1, 1); + } + + 50% { + transform: scale(1.2, 1); + } +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/admin/css/pages/error.css b/demo/webman/backend/plugin/admin/public/admin/css/pages/error.css new file mode 100644 index 0000000000000000000000000000000000000000..7f6cc836ca55c583f1934076983605b89c26380d --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/admin/css/pages/error.css @@ -0,0 +1,76 @@ +* { + padding: 0; + margin: 0; + font-size: 0.38rem; +} + +ul { + list-style: none; +} + +a { + text-decoration: none; + -webkit-tap-highlight-color: transparent +} + +.clearfix:after { + content: ''; + width: 0; + height: 0; + display: block; + clear: both; +} + +html { + height: 100%; + width: 100%; +} + +body { + font-size: 0.28rem; + height: 100%; + width: 100%; + display: flex; + flex-direction: column; + position: relative; + background-color: white !important; +} + +.content { + position: absolute; + top: 50%; + transform: translateY(-50%); + width: 100%; + text-align: center; +} + +.content>img { + height: 300px; + max-width: 370px; + margin-right: 80px; +} + +.content>* { + display: inline-block; +} + +.content-r { + vertical-align: top; +} + +.content-r>h1 { + font-size: 72px; + color: #434e59; + margin-bottom: 24px; + font-weight: 600; +} + +.content-r>p { + font-size: 20px; + color: rgba(0, 0, 0, .45); + margin-bottom: 16px; +} + +button { + margin-top: 20px; +} diff --git a/demo/webman/backend/plugin/admin/public/admin/css/pages/login.css b/demo/webman/backend/plugin/admin/public/admin/css/pages/login.css new file mode 100644 index 0000000000000000000000000000000000000000..0f9ce8ec5e9c9d0f67e449da1448e7252e7fbf0f --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/admin/css/pages/login.css @@ -0,0 +1,91 @@ +.layui-form { + width: 320px !important; + margin: auto !important; + margin-top: 160px !important; +} + +.layui-form button { + width: 100% !important; + height: 44px !important; + line-height: 44px !important; + font-size: 16px !important; + font-weight: 550 !important; +} + +.layui-form-checked[lay-skin=primary] i { + color: #fff !important; +} + +.layui-tab-content { + margin-top: 15px !important; + padding-left: 0px !important; + padding-right: 0px !important; +} + +.layui-form-item { + margin-top: 20px !important; +} + +.layui-input { + height: 44px !important; + line-height: 44px !important; + padding-left: 15px !important; + border-radius: 3px !important; +} + +.layui-form-danger:focus{ + box-shadow: 0px 0px 2px 1px #f56c6c !important; +} + +.logo { + width: 60px !important; + margin-top: 10px !important; + margin-bottom: 10px !important; + margin-left: 20px !important; +} + +.title { + font-size: 30px !important; + font-weight: 550 !important; + margin-left: 20px !important; + display: inline-block !important; + height: 60px !important; + line-height: 60px !important; + margin-top: 10px !important; + position: absolute !important; +} + +.desc { + width: 100% !important; + text-align: center !important; + color: gray !important; + height: 60px !important; + line-height: 60px !important; +} + +body { + background-repeat:no-repeat; + background-color: whitesmoke; + background-size: 100%; + height: 100%; + } + +.code { + float: left; + margin-right: 13px; + margin: 0px !important; + border: #e6e6e6 1px solid; + display: inline-block!important; +} + +.codeImage { + float: right; + height: 42px; + border: #e6e6e6 1px solid; +} + +@media (max-width:768px){ + body{ + background-position:center; + } +} diff --git a/demo/webman/backend/plugin/admin/public/admin/css/reset.css b/demo/webman/backend/plugin/admin/public/admin/css/reset.css new file mode 100644 index 0000000000000000000000000000000000000000..fac189da8d4642bcfa0d0e5a0a8299e87948639a --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/admin/css/reset.css @@ -0,0 +1,228 @@ +button { + line-height: 100% !important; +} + +.pear-btn-md, .pear-btn-sm, .pear-btn-xs, .pear-btn { + line-height: 100%; + letter-spacing: 2px; + padding: 0 15px; + font-weight: 400; + font-size: 14px; +} + +.layui-layer-btn { + padding: 0 15px 19px; + letter-spacing: 2px; +} + +.pear-btn i { + font-size: 14px; +} + +.layui-table-cell .pear-btn i { + font-size: 15px; +} + +.layui-table-tips-main { + overflow: hidden; +} + +.layui-table th { + font-weight: 500; +} + +.layui-laypage a, .layui-laypage span { + font-size: 14px; +} + +.layui-table-tool .layui-inline[lay-event], .layui-table-tool .layui-inline[lay-event]:hover { + border:none; +} + +.layui-table-tool-self .layui-icon { + font-size: 18px; +} + +.layui-table, .pear-tab .layui-tab-title li { + color: #333; +} + +.tool-btn.pear-btn-xs { + background: transparent; + font-weight: normal; + font-size: 14px; + color: #333; + border: none; + padding: 0 2px; + height: auto !important; +} + +.layui-iconpicker { + max-width: 290px !important; +} + +.layui-iconpicker .layui-anim { + max-height: 220px !important; +} + +.layui-input:disabled { + color: rgba(0,0,0,.25); + background: #f5f5f5; + cursor: not-allowed; +} + +.layui-form-label.required:after { + content: "*"; + color: red; + display: inline-block; + padding: 7px 5px; + line-height: 20px; + text-align: right; + position: absolute; + right: 0; + top: 5px; +} + +.layui-bg-green { + background-color: #36b368 !important; +} + +a { + cursor: pointer; +} + +*[permission] { + display: none; +} + +@media screen and (max-width:768px) { + /** **/ + .layui-table-tool-self .layui-inline:nth-child(3){ + display: none; + } +} + +/** 右间隔 **/ +.mr-1 +{ + margin-right: 4px; +} +.mr-2 +{ + margin-right: 8px; +} +.mr-3 +{ + margin-right: 16px; +} +.mr-4 +{ + margin-right: 24px; +} +.mr-5 +{ + margin-right: 48px; +} + +/** 图片尺寸 **/ +.img-1 +{ + max-width: 16px; + max-height: 16px; + border-radius: 6px; +} +.img-2 +{ + max-width: 32px; + max-height: 32px; + border-radius: 6px; +} +.img-3 +{ + max-width: 64px; + max-height: 64px; + border-radius: 6px; +} +.img-4 +{ + max-width: 128px; + max-height: 128px; + border-radius: 6px; +} + +/** 左侧菜单 Start **/ + +.pear-nav-tree .layui-nav-item a span { + font-size: 14px; + letter-spacing: 1.5px; +} + +.light-theme .pear-nav-tree a, .light-theme .pear-nav-tree .layui-nav-more { + color: #333; +} + +/** 左侧菜单 End **/ + + +/** 表详情顶部搜索框 Start **/ + +.top-search-from .layui-form-item { + position: relative; + display: inline-block; + *display: inline; + *zoom: 1; + vertical-align: middle; +} +.top-search-from .layui-form-item .layui-input-block { + float: left; + width: 270px; + margin-right: 10px; + margin-left: 0; + display: inline-block; + vertical-align: middle; + position: relative; +} +.top-search-from .layui-input, .top-search-from .layui-select, .top-search-from .layui-textarea { + width: 270px; +} +.top-search-from .item-inline .layui-form-item .layui-input-block { + width: 270px; +} +.top-search-from .layui-form-mid { + margin-left: 7px; + margin-right: 7px; +} +.top-search-from .layui-form-label { + width: 60px; + white-space: nowrap; +} +.top-search-from .inline-block { + width:128px; + display:inline-block +} +.top-search-from .layui-form-item { + width: 370px; +} +.top-search-from .toggle-btn { + text-align: center; +} +.top-search-from .toggle-btn a { + cursor: pointer; + color: #999; +} +.top-search-from .toggle-btn a:hover { + color: #333; +} +@media screen and (max-width:768px) { + .top-search-from .layui-input { + max-width: 234px; + } + .top-search-from .layui-input.inline-block { + max-width: 110px; + } + .layui-table-tool-self .layui-inline:nth-child(3){ + display: none; + } +} + +/** 表详情顶部搜索框 End **/ \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/admin/images/403.svg b/demo/webman/backend/plugin/admin/public/admin/images/403.svg new file mode 100644 index 0000000000000000000000000000000000000000..610f136fd004f889d25152c3918754988c85f8ca --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/admin/images/403.svg @@ -0,0 +1,508 @@ + + + + Group 9 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/admin/images/404.svg b/demo/webman/backend/plugin/admin/public/admin/images/404.svg new file mode 100644 index 0000000000000000000000000000000000000000..5531d05cffbddd0980b51d1d378671b5520530c7 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/admin/images/404.svg @@ -0,0 +1,314 @@ + + + + Group 4 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/admin/images/500.svg b/demo/webman/backend/plugin/admin/public/admin/images/500.svg new file mode 100644 index 0000000000000000000000000000000000000000..de723b1e321432ebe63004f2bc85d3ef6d17132a --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/admin/images/500.svg @@ -0,0 +1,208 @@ + + + + Group 4 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/admin/images/background.svg b/demo/webman/backend/plugin/admin/public/admin/images/background.svg new file mode 100644 index 0000000000000000000000000000000000000000..2f4b63b9996b80d9a60d8ab0eb93de0344ad0c52 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/admin/images/background.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/admin/images/logo.png b/demo/webman/backend/plugin/admin/public/admin/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bc0d9e9e95827c828aa0e76156920d4b7f330afd Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/admin/images/logo.png differ diff --git a/demo/webman/backend/plugin/admin/public/admin/js/common.js b/demo/webman/backend/plugin/admin/public/admin/js/common.js new file mode 100644 index 0000000000000000000000000000000000000000..3b8fb23ff7be376d55703912abfddd0cf32ca265 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/admin/js/common.js @@ -0,0 +1,38 @@ +/** + * 浏览页面顶部搜索框展开收回控制 + */ +function toggleSearchFormShow() +{ + let $ = layui.$; + let items = $('.top-search-from .layui-form-item'); + if (items.length <= 2) { + if (items.length <= 1) $('.top-search-from').parent().parent().remove(); + return; + } + let btns = $('.top-search-from .toggle-btn a'); + let toggle = toggleSearchFormShow; + if (typeof toggle.hide === 'undefined') { + btns.on('click', function () { + toggle(); + }); + } + let countPerRow = parseInt($('.top-search-from').width()/$('.layui-form-item').width()); + if (items.length <= countPerRow) { + return; + } + btns.removeClass('layui-hide'); + toggle.hide = !toggle.hide; + if (toggle.hide) { + for (let i = countPerRow - 1; i < items.length - 1; i++) { + $(items[i]).hide(); + } + return $('.top-search-from .toggle-btn a:last').addClass('layui-hide'); + } + items.show(); + $('.top-search-from .toggle-btn a:first').addClass('layui-hide'); +} + +layui.$(function () { + toggleSearchFormShow(); +}); + diff --git a/demo/webman/backend/plugin/admin/public/admin/js/permission.js b/demo/webman/backend/plugin/admin/public/admin/js/permission.js new file mode 100644 index 0000000000000000000000000000000000000000..9ba8e19dc9057fa6ac561393dc6fc179938fdc5f --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/admin/js/permission.js @@ -0,0 +1,34 @@ +/** + * 获取控制器详细权限,并决定展示哪些按钮或dom元素 + */ +layui.$(function () { + let $ = layui.$; + $.ajax({ + url: "/app/admin/rule/permission", + dataType: "json", + success: function (res) { + let style = ''; + let codes = res.data || []; + let isSupperAdmin = false; + // codes里有*,说明是超级管理员,拥有所有权限 + if (codes.indexOf('*') !== -1) { + $("head").append(""); + isSupperAdmin = true; + } + if (self !== top) { + top.Admin.Account.isSupperAdmin = isSupperAdmin; + } else { + window.Admin.Account.isSupperAdmin = isSupperAdmin; + } + if (isSupperAdmin) return; + + // 细分权限 + layui.each(codes, function (k, code) { + codes[k] = '*[permission^="'+code+'"]'; + }); + if (codes.length) { + $("head").append(""); + } + } + }); +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/avatar.png b/demo/webman/backend/plugin/admin/public/avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..319ca4ac3cee9426c73f44dc896e6d21f6358fa1 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/avatar.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/code/css/style.css b/demo/webman/backend/plugin/admin/public/component/code/css/style.css new file mode 100644 index 0000000000000000000000000000000000000000..5d460a5454845a1adbb1d442d051df37d2ce805f --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/code/css/style.css @@ -0,0 +1,9 @@ +html,body{background-color: whitesmoke} +.layui-fluid{margin-top: 15px;} +.content{min-height: 796px;} +.nav{text-align: center;} +.nav button{margin-bottom: 3px;width: 100%;margin-top: 3px;margin-bottom: 3px;border-radius: 1px;} +.nav button:hover{background-color: #5FB878;border: 1px solid #5FB878;color: white;} +.layui-card-body .layui-btn+.layui-btn{margin-left: 0px;} +.code-show{min-height: 454px;} +.js-show{min-height: 200px;} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/code/index.html b/demo/webman/backend/plugin/admin/public/component/code/index.html new file mode 100644 index 0000000000000000000000000000000000000000..ba02488d8aa7035358ac4376a81f7b836980ef08 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/code/index.html @@ -0,0 +1,81 @@ + + + + + + + layui表单生成器 + + + + +
                                                              +
                                                              +
                                                              + + + + +
                                                              +
                                                              +
                                                              +
                                                              + view +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              html
                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              code
                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              +
                                                              + + + + + diff --git a/demo/webman/backend/plugin/admin/public/component/jsoneditor/css/jsoneditor-icons.png b/demo/webman/backend/plugin/admin/public/component/jsoneditor/css/jsoneditor-icons.png new file mode 100644 index 0000000000000000000000000000000000000000..1a41fa2be92c24a442ec5771ecba858b7c8495d9 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/jsoneditor/css/jsoneditor-icons.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/jsoneditor/css/jsoneditor.css b/demo/webman/backend/plugin/admin/public/component/jsoneditor/css/jsoneditor.css new file mode 100644 index 0000000000000000000000000000000000000000..70c8eeaf8b81066456702d71c16fed8e1fe77b5c --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/jsoneditor/css/jsoneditor.css @@ -0,0 +1,434 @@ +.jsoneditor-field, .jsoneditor-value, .jsoneditor-field-readonly, .jsoneditor-readonly { + border: 1px solid transparent; + min-height: 16px; + min-width: 24px; + padding: 2px; + margin: 1px; + outline: none; + word-wrap: break-word; + float: left; +} + +/* adjust margin of p elements inside editable divs, needed for Opera, IE */ +.jsoneditor-field p, .jsoneditor-value p { + margin: 0; +} + +.jsoneditor-value { + word-break: break-word; +} + +.jsoneditor-empty { + background-color: #E5E5E5; + border-radius: 2px; +} + +.jsoneditor-separator { + padding: 3px 0; + vertical-align: top; +} + +.jsoneditor-value:focus, .jsoneditor-field:focus, +.jsoneditor-value:hover, .jsoneditor-field:hover, +.jsoneditor-search-highlight { + background-color: #FFFFAB; + border: 1px solid yellow; + border-radius: 2px; +} + +.jsoneditor-search-highlight-active, +.jsoneditor-search-highlight-active:focus, +.jsoneditor-search-highlight-active:hover { + background-color: #ffee00; + border: 1px solid #ffc700; + border-radius: 2px; +} + +.jsoneditor-field-readonly:hover { + border: 1px solid white; +} + +.jsoneditor-readonly { + color: gray; +} + +button.jsoneditor-remove, button.jsoneditor-append, button.jsoneditor-duplicate, +button.jsoneditor-collapsed, button.jsoneditor-expanded, +button.jsoneditor-invisible, button.jsoneditor-dragarea, +button.jsoneditor-type-auto, button.jsoneditor-type-string, +button.jsoneditor-type-array, button.jsoneditor-type-object { + width: 24px; + height: 24px; + padding: 0; + margin: 0; + border: none; + cursor: pointer; + background: url('jsoneditor-icons.png'); +} + +button:disabled { + color: #808080; +} + +button.jsoneditor-collapsed { + background-position: -168px 0; +} + +button.jsoneditor-expanded { + background-position: -168px -24px; +} + +button.jsoneditor-invisible { + visibility: hidden; + background: none; +} + +button.jsoneditor-collapsed, button.jsoneditor-expanded, +button.jsoneditor-invisible { + float: left; +} + +button.jsoneditor-remove { + background-position: -24px -24px; +} +button.jsoneditor-remove:hover { + background-position: -24px 0; +} + +button.jsoneditor-append { + background-position: 0 -24px; +} +button.jsoneditor-append:hover { + background-position: 0 0; +} + +button.jsoneditor-duplicate { + background-position: -48px -24px; +} +button.jsoneditor-duplicate:hover { + background-position: -48px 0; +} + +button.jsoneditor-type-string { + background-position: -144px -24px; +} +button.jsoneditor-type-string:hover { + background-position: -144px 0; +} + +button.jsoneditor-type-auto { + background-position: -120px -24px; +} +button.jsoneditor-type-auto:hover { + background-position: -120px 0; +} + +button.jsoneditor-type-object { + background-position: -72px -24px; +} +button.jsoneditor-type-object:hover { + background-position: -72px 0; +} + +button.jsoneditor-type-array { + background-position: -96px -24px; +} +button.jsoneditor-type-array:hover { + background-position: -96px 0; +} + +div.jsoneditor-select { + border: 1px solid gray; + background-color: white; + box-shadow: 4px 4px 10px rgba(128, 128, 128, 0.5); +} + +div.jsoneditor-option { + color: #4D4D4D; + background-color: white; + + border: none; + margin: 0; + display: block; + text-align: left; + cursor: pointer; +} +div.jsoneditor-option:hover { + background-color: #FFFFAB; + color: #1A1A1A; +} +div.jsoneditor-option-selected { + background-color: #C1C1C1; +} +div.jsoneditor-option-text { + height: 24px; + line-height: 24px; + padding: 0 12px 0 0; + display: inline-block; +} + +div.jsoneditor-option-string, div.jsoneditor-option-auto, +div.jsoneditor-option-object, div.jsoneditor-option-array { + float: left; + width: 24px; + height: 24px; + display: inline-block; + background: url('jsoneditor-icons.png'); +} +div.jsoneditor-option-string { + background-position: -144px 0; +} +div.jsoneditor-option-auto { + background-position: -120px 0; +} +div.jsoneditor-option-object { + background-position: -72px 0; +} +div.jsoneditor-option-array { + background-position: -96px 0; +} + + +div.jsoneditor-frame { + color: #1A1A1A; + border: 1px solid #C1C1C1; + box-sizing: border-box; + width: 100%; + height: 100%; + overflow: auto; + position: relative; + padding: 0; +} + +table.jsoneditor-table { + border-collapse: collapse; + border-spacing: 0; + width: 100%; + margin: 0; +} + +div.jsoneditor-content-outer, div.jsonformatter-content { + width: 100%; + height: 100%; + margin: -35px 0 0 0; + padding: 35px 0 0 0; + + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + + overflow: hidden; +} + +div.jsoneditor-content { + width: 100%; + height: 100%; + position: relative; + overflow: auto; +} + +textarea.jsonformatter-textarea { + width: 100%; + height: 100%; + margin: 0; + + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + + border: none; + background-color: white; + resize: none; +} + +tr.jsoneditor-tr-highlight { + background-color: #FFFFAB; +} + +button.jsoneditor-dragarea { + width: 16px; + height: 24px; + /* + margin: 3px 0; + background: url('img/dots_gray.gif') top center; + background-repeat: repeat-y; + */ + background: url('jsoneditor-icons.png') -220px 0; + + display: block; + cursor: move; +} + +div.jsoneditor-menu { + width: 100%; + height: 35px; + padding: 2px; + margin: 0; + overflow: hidden; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + + color: #1A1A1A; + border-bottom: 1px solid #C1C1C1; +} + +table.jsoneditor-search { + position: absolute; + right: 2px; + top: 2px; +} + +table.jsoneditor-search-input { + border-collapse: collapse; +} + +div.jsoneditor-search { + border: 1px solid #C1C1C1; + background-color: white; + padding: 0 2px; + margin: 0; +} + +input.jsoneditor-search { + width: 120px; + border: none; + outline: none; + margin: 1px; +} + +div.jsoneditor-search-results { + color: #4d4d4d; + padding-right: 5px; +} + +button.jsoneditor-search-refresh, button.jsoneditor-search-next, +button.jsoneditor-search-previous { + width: 16px; + height: 24px; + padding: 0; + margin: 0; + border: none; + background: url('jsoneditor-icons.png'); + vertical-align: top; +} + +button.jsoneditor-search-refresh { + width: 18px; + background-position: -243px -25px; +} + +button.jsoneditor-search-next { + cursor: pointer; + background-position: -268px -25px; +} +button.jsoneditor-search-next:hover { + background-position: -268px -1px; +} + +button.jsoneditor-search-previous { + cursor: pointer; + background-position: -292px -25px; + margin-right: 2px; +} +button.jsoneditor-search-previous:hover { + background-position: -292px -1px; +} + + +button.jsoneditor-menu { + width: 26px; + height: 26px; + margin: 2px; + padding: 2px; + border-radius: 2px; + border: 1px solid #aec0f8; + background: #D0F0EF url('jsoneditor-icons.png'); +} + +button.jsoneditor-menu:hover { + background-color: #FFFFFF; +} +button.jsoneditor-menu:active { + background-color: #ffffff; +} +button.jsoneditor-menu:disabled { + background-color: #D0F0EF; +} + +button.jsoneditor-collapse-all { + background-position: -312px 0; +} +button.jsoneditor-expand-all { + background-position: -312px -24px; +} +button.jsoneditor-undo { + background-position: -336px 0; +} +button.jsoneditor-redo { + background-position: -360px 0; +} +button.jsoneditor-undo:disabled { + background-position: -336px -24px; +} +button.jsoneditor-redo:disabled { + background-position: -360px -24px; +} +/* TODO: css for button:disabled is not supported by IE8 */ +button.jsoneditor-compact { + background-position: -384px 0; +} +button.jsoneditor-format { + background-position: -384px -24px; +} + + +tr, th, td { + padding: 0; + margin: 0; +} + +td.jsoneditor-td { + vertical-align: top; +} + +td.jsoneditor-td { + padding: 0 3px; +} + +td.jsoneditor-td-edit { + background-color: #F5F5F5; + padding: 0; +} + +td.jsoneditor-td-tree { + vertical-align: top; +} + +td.jsoneditor-droparea { + height: 24px; + + border-top: 1px dashed gray; + border-bottom: 1px dashed gray; + background-color: #FFFF80; +} + +.jsoneditor-field, .jsoneditor-value, .jsoneditor-td, .jsoneditor-th, +.jsoneditor-type, +.jsonformatter-textarea { + font-family: droid sans mono, monospace, courier new, courier, sans-serif; + font-size: 10pt; + color: #1A1A1A; +} + +.jsoneditor-hidden-focus { + position: absolute; + left: -1000px; + top: -1000px; + border: none; + outline: none; +} + +#by-jsonlint{ + text-align: right; +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/jsoneditor/jsoneditor.js b/demo/webman/backend/plugin/admin/public/component/jsoneditor/jsoneditor.js new file mode 100644 index 0000000000000000000000000000000000000000..bd7cf13a1a32369477f9fb5e6296196a602efd62 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/jsoneditor/jsoneditor.js @@ -0,0 +1,3898 @@ +/** + * @file jsoneditor.js + * + * @brief + * JSONEditor is a web-based tool to view, edit, and format JSON. + * It shows data a clear, editable treeview. + * + * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ + * + * @license + * This json editor is open sourced with the intention to use the editor as + * a component in your own application. Not to just copy and monetize the editor + * as it is. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + * + * Copyright (c) 2011-2012 Jos de Jong, http://jsoneditoronline.org + * + * @author Jos de Jong, + * @date 2012-12-08 + */ +// Internet Explorer 8 and older does not support Array.indexOf, +// so we define it here in that case +// http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/ +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function(obj) { + for (var i = 0; i < this.length; i++) { + if (this[i] == obj) { + return i; + } + } + return -1; + }; +} + +// Internet Explorer 8 and older does not support Array.forEach, +// so we define it here in that case +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(fn, scope) { + for (var i = 0, len = this.length; i < len; ++i) { + fn.call(scope || this, this[i], i, this); + } + }; +} + +// define variable JSON, needed for correct error handling on IE7 and older +var JSON; + +/** + * JSONEditor + * @param {Element} container Container element + * @param {Object} [options] Object with options. available options: + * {String} mode Editor mode. Available values: + * 'editor' (default), 'viewer'. + * {Boolean} search Enable search box. + * True by default + * {Boolean} history Enable history (undo/redo). + * True by default + * {function} change Callback method, triggered + * on change of contents + * {String} name Field name for the root node. + * @param {Object | undefined} json JSON object + */ +JSONEditor = function(container, options, json) { + // check availability of JSON parser (not available in IE7 and older) + if (!JSON) { + throw new Error( + "鎮ㄥ綋鍓嶄娇鐢ㄧ殑娴忚鍣ㄤ笉鏀寔 JSON. \n\n" + + "璇蜂笅杞藉畨瑁呮渶鏂扮増鏈殑娴忚鍣�, 鏈珯鎺ㄨ崘Google Chrome.\n" + + "(PS: 褰撳墠涓绘祦娴忚鍣ㄩ兘鏀寔JSON)." + ); + } + + if (!container) { + throw new Error("娌℃湁鎻愪緵瀹瑰櫒鍏冪礌."); + } + this.container = container; + this.dom = {}; + + this._setOptions(options); + + if (this.options.history && this.editable) { + this.history = new JSONEditor.History(this); + } + + this._createFrame(); + this._createTable(); + + this.set(json || {}); +}; + +/** + * Initialize and set default options + * @param {Object} [options] Object with options. available options: + * {String} mode Editor mode. Available values: + * 'editor' (default), 'viewer'. + * {Boolean} search Enable search box. + * True by default. + * {Boolean} history Enable history (undo/redo). + * True by default. + * {function} change Callback method, triggered + * on change of contents. + * {String} name Field name for the root node. + * @private + */ +JSONEditor.prototype._setOptions = function(options) { + this.options = { + search: true, + history: true, + mode: "editor", + name: undefined // field name of root node + }; + + // copy all options + if (options) { + for (var prop in options) { + if (options.hasOwnProperty(prop)) { + this.options[prop] = options[prop]; + } + } + + // check for deprecated options + if (options.enableSearch) { + // deprecated since version 1.6.0, 2012-11-03 + this.options.search = options.enableSearch; + // console.log('WARNING: Option "enableSearch" is deprecated. Use "search" instead.'); + } + if (options.enableHistory) { + // deprecated since version 1.6.0, 2012-11-03 + this.options.search = options.enableHistory; + // console.log('WARNING: Option "enableHistory" is deprecated. Use "history" instead.'); + } + } + + // interpret the options + this.editable = this.options.mode != "viewer"; +}; + +// node currently being edited +JSONEditor.focusNode = undefined; + +/** + * Set JSON object in editor + * @param {Object | undefined} json JSON data + * @param {String} [name] Optional field name for the root node. + * Can also be set using setName(name). + */ +JSONEditor.prototype.set = function(json, name) { + // adjust field name for root node + if (name) { + this.options.name = name; + } + + // verify if json is valid JSON, ignore when a function + if (json instanceof Function || json === undefined) { + this.clear(); + } else { + this.content.removeChild(this.table); // Take the table offline + + // replace the root node + var params = { + field: this.options.name, + value: json + }; + var node = new JSONEditor.Node(this, params); + this._setRoot(node); + + // expand + var recurse = false; + this.node.expand(recurse); + + this.content.appendChild(this.table); // Put the table online again + } + + // TODO: maintain history, store last state and previous document + if (this.history) { + this.history.clear(); + } +}; + +/** + * Get JSON object from editor + * @return {Object | undefined} json + */ +JSONEditor.prototype.get = function() { + // remove focus from currently edited node + if (JSONEditor.focusNode) { + JSONEditor.focusNode.blur(); + } + + if (this.node) { + return this.node.getValue(); + } else { + return undefined; + } +}; + +/** + * Set a field name for the root node. + * @param {String | undefined} name + */ +JSONEditor.prototype.setName = function(name) { + this.options.name = name; + if (this.node) { + this.node.updateField(this.options.name); + } +}; + +/** + * Get the field name for the root node. + * @return {String | undefined} name + */ +JSONEditor.prototype.getName = function() { + return this.options.name; +}; + +/** + * Remove the root node from the editor + */ +JSONEditor.prototype.clear = function() { + if (this.node) { + this.node.collapse(); + this.tbody.removeChild(this.node.getDom()); + delete this.node; + } +}; + +/** + * Set the root node for the json editor + * @param {JSONEditor.Node} node + * @private + */ +JSONEditor.prototype._setRoot = function(node) { + this.clear(); + + this.node = node; + + // append to the dom + this.tbody.appendChild(node.getDom()); +}; + +/** + * Search text in all nodes + * The nodes will be expanded when the text is found one of its childs, + * else it will be collapsed. Searches are case insensitive. + * @param {String} text + * @return {Object[]} results Array with nodes containing the search results + * The result objects contains fields: + * - {JSONEditor.Node} node, + * - {String} elem the dom element name where + * the result is found ('field' or + * 'value') + */ +JSONEditor.prototype.search = function(text) { + var results; + if (this.node) { + this.content.removeChild(this.table); // Take the table offline + results = this.node.search(text); + this.content.appendChild(this.table); // Put the table online again + } else { + results = []; + } + + return results; +}; + +/** + * Expand all nodes + */ +JSONEditor.prototype.expandAll = function() { + if (this.node) { + this.content.removeChild(this.table); // Take the table offline + this.node.expand(); + this.content.appendChild(this.table); // Put the table online again + } +}; + +/** + * Collapse all nodes + */ +JSONEditor.prototype.collapseAll = function() { + if (this.node) { + this.content.removeChild(this.table); // Take the table offline + this.node.collapse(); + this.content.appendChild(this.table); // Put the table online again + } +}; + +/** + * The method onChange is called whenever a field or value is changed, created, + * deleted, duplicated, etc. + * @param {String} action Change action. Available values: "editField", + * "editValue", "changeType", "appendNode", + * "removeNode", "duplicateNode", "moveNode", "expand", + * "collapse". + * @param {Object} params Object containing parameters describing the change. + * The parameters in params depend on the action (for + * example for "editValue" the Node, old value, and new + * value are provided). params contains all information + * needed to undo or redo the action. + */ +JSONEditor.prototype.onAction = function(action, params) { + // add an action to the history + if (this.history) { + this.history.add(action, params); + } + + // trigger the onChange callback + if (this.options.change) { + try { + this.options.change(); + } catch (err) { + //console.log('Error in change callback: ', err); + } + } +}; + +/** + * Set the focus to the JSONEditor. A hidden input field will be created + * which captures key events + */ +// TODO: use the focus method? +JSONEditor.prototype.focus = function() { + /* + if (!this.dom.focus) { + this.dom.focus = document.createElement('input'); + this.dom.focus.className = 'jsoneditor-hidden-focus'; + + var editor = this; + this.dom.focus.onblur = function () { + // remove itself + if (editor.dom.focus) { + var focus = editor.dom.focus; + delete editor.dom.focus; + editor.frame.removeChild(focus); + } + }; + + // attach the hidden input box to the DOM + if (this.frame.firstChild) { + this.frame.insertBefore(this.dom.focus, this.frame.firstChild); + } + else { + this.frame.appendChild(this.dom.focus); + } + } + this.dom.focus.focus(); + */ +}; + +/** + * Adjust the scroll position such that given top position is shown at 1/4 + * of the window height. + * @param {Number} top + */ +JSONEditor.prototype.scrollTo = function(top) { + var content = this.content; + if (content) { + // cancel any running animation + var editor = this; + if (editor.animateTimeout) { + clearTimeout(editor.animateTimeout); + delete editor.animateTimeout; + } + + // calculate final scroll position + var height = content.clientHeight; + var bottom = content.scrollHeight - height; + var finalScrollTop = Math.min(Math.max(top - height / 4, 0), bottom); + + // animate towards the new scroll position + var animate = function() { + var scrollTop = content.scrollTop; + var diff = finalScrollTop - scrollTop; + if (Math.abs(diff) > 3) { + content.scrollTop += diff / 3; + editor.animateTimeout = setTimeout(animate, 50); + } + }; + animate(); + } +}; + +/** + * @constructor JSONEditor.History + * Store action history, enables undo and redo + * @param {JSONEditor} editor + */ +JSONEditor.History = function(editor) { + this.editor = editor; + this.clear(); + + // map with all supported actions + this.actions = { + editField: { + undo: function(obj) { + obj.params.node.updateField(obj.params.oldValue); + }, + redo: function(obj) { + obj.params.node.updateField(obj.params.newValue); + } + }, + editValue: { + undo: function(obj) { + obj.params.node.updateValue(obj.params.oldValue); + }, + redo: function(obj) { + obj.params.node.updateValue(obj.params.newValue); + } + }, + appendNode: { + undo: function(obj) { + obj.params.parent.removeChild(obj.params.node); + }, + redo: function(obj) { + obj.params.parent.appendChild(obj.params.node); + } + }, + removeNode: { + undo: function(obj) { + var parent = obj.params.parent; + var beforeNode = parent.childs[obj.params.index] || parent.append; + parent.insertBefore(obj.params.node, beforeNode); + }, + redo: function(obj) { + obj.params.parent.removeChild(obj.params.node); + } + }, + duplicateNode: { + undo: function(obj) { + obj.params.parent.removeChild(obj.params.clone); + }, + redo: function(obj) { + // TODO: insert after instead of insert before + obj.params.parent.insertBefore(obj.params.clone, obj.params.node); + } + }, + changeType: { + undo: function(obj) { + obj.params.node.changeType(obj.params.oldType); + }, + redo: function(obj) { + obj.params.node.changeType(obj.params.newType); + } + }, + moveNode: { + undo: function(obj) { + obj.params.startParent.moveTo(obj.params.node, obj.params.startIndex); + }, + redo: function(obj) { + obj.params.endParent.moveTo(obj.params.node, obj.params.endIndex); + } + } + + // TODO: restore the original caret position and selection with each undo + // TODO: implement history for actions "expand", "collapse", "scroll", "setDocument" + }; +}; + +/** + * The method onChange is executed when the History is changed, and can + * be overloaded. + */ +JSONEditor.History.prototype.onChange = function() {}; + +/** + * Add a new action to the history + * @param {String} action The executed action. Available actions: "editField", + * "editValue", "changeType", "appendNode", + * "removeNode", "duplicateNode", "moveNode" + * @param {Object} params Object containing parameters describing the change. + * The parameters in params depend on the action (for + * example for "editValue" the Node, old value, and new + * value are provided). params contains all information + * needed to undo or redo the action. + */ +JSONEditor.History.prototype.add = function(action, params) { + this.index++; + this.history[this.index] = { + action: action, + params: params, + timestamp: new Date() + }; + + // remove redo actions which are invalid now + if (this.index < this.history.length - 1) { + this.history.splice(this.index + 1, this.history.length - this.index - 1); + } + + // fire onchange event + this.onChange(); +}; + +/** + * Clear history + */ +JSONEditor.History.prototype.clear = function() { + this.history = []; + this.index = -1; + + // fire onchange event + this.onChange(); +}; + +/** + * Check if there is an action available for undo + * @return {Boolean} canUndo + */ +JSONEditor.History.prototype.canUndo = function() { + return this.index >= 0; +}; + +/** + * Check if there is an action available for redo + * @return {Boolean} canRedo + */ +JSONEditor.History.prototype.canRedo = function() { + return this.index < this.history.length - 1; +}; + +/** + * Undo the last action + */ +JSONEditor.History.prototype.undo = function() { + if (this.canUndo()) { + var obj = this.history[this.index]; + if (obj) { + var action = this.actions[obj.action]; + if (action && action.undo) { + action.undo(obj); + } else { + //console.log('Error: unknown action "' + obj.action + '"'); + } + } + this.index--; + + // fire onchange event + this.onChange(); + } +}; + +/** + * Redo the last action + */ +JSONEditor.History.prototype.redo = function() { + if (this.canRedo()) { + this.index++; + + var obj = this.history[this.index]; + if (obj) { + if (obj) { + var action = this.actions[obj.action]; + if (action && action.redo) { + action.redo(obj); + } else { + //console.log('Error: unknown action "' + obj.action + '"'); + } + } + } + + // fire onchange event + this.onChange(); + } +}; + +/** + * @constructor JSONEditor.Node + * Create a new Node + * @param {JSONEditor} editor + * @param {Object} params Can contain parameters: field, fieldEditable, value. + */ +JSONEditor.Node = function(editor, params) { + this.editor = editor; + this.dom = {}; + this.expanded = false; + + if (params && params instanceof Object) { + this.setField(params.field, params.fieldEditable); + this.setValue(params.value); + } else { + this.setField(); + this.setValue(); + } +}; + +/** + * Set parent node + * @param {JSONEditor.Node} parent + */ +JSONEditor.Node.prototype.setParent = function(parent) { + this.parent = parent; +}; + +/** + * Get parent node. Returns undefined when no parent node is set. + * @return {JSONEditor.Node} parent + */ +JSONEditor.Node.prototype.getParent = function() { + return this.parent; +}; + +/** + * Set field + * @param {String} field + * @param {boolean} fieldEditable + */ +JSONEditor.Node.prototype.setField = function(field, fieldEditable) { + this.field = field; + this.fieldEditable = fieldEditable == true; +}; + +/** + * Get field + * @return {String} + */ +JSONEditor.Node.prototype.getField = function() { + if (this.field === undefined) { + this._getDomField(); + } + + return this.field; +}; + +/** + * Set value. Value is a JSON structure or an element String, Boolean, etc. + * @param {*} value + */ +JSONEditor.Node.prototype.setValue = function(value) { + var childValue, child; + + // first clear all current childs (if any) + var childs = this.childs; + if (childs) { + while (childs.length) { + this.removeChild(childs[0]); + } + } + + // TODO: remove the DOM of this Node + + this.type = this._getType(value); + if (this.type == "array") { + // array + this.childs = []; + for (var i = 0, iMax = value.length; i < iMax; i++) { + childValue = value[i]; + if (childValue !== undefined && !(childValue instanceof Function)) { + // ignore undefined and functions + child = new JSONEditor.Node(this.editor, { + value: childValue + }); + this.appendChild(child); + } + } + this.value = ""; + } else if (this.type == "object") { + // object + this.childs = []; + for (var childField in value) { + if (value.hasOwnProperty(childField)) { + childValue = value[childField]; + if (childValue !== undefined && !(childValue instanceof Function)) { + // ignore undefined and functions + child = new JSONEditor.Node(this.editor, { + field: childField, + value: childValue + }); + this.appendChild(child); + } + } + } + this.value = ""; + } else { + // value + this.childs = undefined; + this.value = value; + /* TODO + if (typeof(value) == 'string') { + var escValue = JSON.stringify(value); + this.value = escValue.substring(1, escValue.length - 1); + console.log('check', value, this.value); + } + else { + this.value = value; + } + */ + } +}; + +/** + * Get value. Value is a JSON structure + * @return {*} value + */ +JSONEditor.Node.prototype.getValue = function() { + //var childs, i, iMax; + + if (this.type == "array") { + var arr = []; + this.childs.forEach(function(child) { + arr.push(child.getValue()); + }); + return arr; + } else if (this.type == "object") { + var obj = {}; + this.childs.forEach(function(child) { + obj[child.getField()] = child.getValue(); + }); + return obj; + } else { + if (this.value === undefined) { + this._getDomValue(); + } + + return this.value; + } +}; + +/** + * Get the nesting level of this node + * @return {Number} level + */ +JSONEditor.Node.prototype.getLevel = function() { + return this.parent ? this.parent.getLevel() + 1 : 0; +}; + +/** + * Create a clone of a node + * The complete state of a clone is copied, including whether it is expanded or + * not. The DOM elements are not cloned. + * @return {JSONEditor.Node} clone + */ +JSONEditor.Node.prototype.clone = function() { + var clone = new JSONEditor.Node(this.editor); + clone.type = this.type; + clone.field = this.field; + clone.fieldInnerText = this.fieldInnerText; + clone.fieldEditable = this.fieldEditable; + clone.value = this.value; + clone.valueInnerText = this.valueInnerText; + clone.expanded = this.expanded; + + if (this.childs) { + // an object or array + var cloneChilds = []; + this.childs.forEach(function(child) { + var childClone = child.clone(); + childClone.setParent(clone); + cloneChilds.push(childClone); + }); + clone.childs = cloneChilds; + } else { + // a value + clone.childs = undefined; + } + + return clone; +}; + +/** + * Expand this node and optionally its childs. + * @param {boolean} recurse Optional recursion, true by default. When + * true, all childs will be expanded recursively + */ +JSONEditor.Node.prototype.expand = function(recurse) { + if (!this.childs) { + return; + } + + // set this node expanded + this.expanded = true; + if (this.dom.expand) { + this.dom.expand.className = "jsoneditor-expanded"; + } + + this.showChilds(); + + if (recurse != false) { + this.childs.forEach(function(child) { + child.expand(recurse); + }); + } +}; + +/** + * Collapse this node and optionally its childs. + * @param {Number} recurse Optional recursion, true by default. When + * true, all childs will be collapsed recursively + */ +JSONEditor.Node.prototype.collapse = function(recurse) { + if (!this.childs) { + return; + } + + this.hideChilds(); + + // collapse childs in case of recurse + if (recurse != false) { + this.childs.forEach(function(child) { + child.collapse(recurse); + }); + } + + // make this node collapsed + if (this.dom.expand) { + this.dom.expand.className = "jsoneditor-collapsed"; + } + this.expanded = false; +}; + +/** + * Recursively show all childs when they are expanded + */ +JSONEditor.Node.prototype.showChilds = function() { + var childs = this.childs; + if (!childs) { + return; + } + if (!this.expanded) { + return; + } + + var tr = this.dom.tr; + var table = tr ? tr.parentNode : undefined; + if (table) { + // show row with append button + var append = this.getAppend(); + var nextTr = tr.nextSibling; + if (nextTr) { + table.insertBefore(append, nextTr); + } else { + table.appendChild(append); + } + + // show childs + this.childs.forEach(function(child) { + table.insertBefore(child.getDom(), append); + child.showChilds(); + }); + } +}; + +/** + * Hide the node with all its childs + */ +JSONEditor.Node.prototype.hide = function() { + var tr = this.dom.tr; + var table = tr ? tr.parentNode : undefined; + if (table) { + table.removeChild(tr); + } + this.hideChilds(); +}; + +/** + * Recursively hide all childs + */ +JSONEditor.Node.prototype.hideChilds = function() { + var childs = this.childs; + if (!childs) { + return; + } + if (!this.expanded) { + return; + } + + // hide append row + var append = this.getAppend(); + if (append.parentNode) { + append.parentNode.removeChild(append); + } + + // hide childs + this.childs.forEach(function(child) { + child.hide(); + }); +}; + +/** + * Add a new child to the node. + * Only applicable when Node value is of type array or object + * @param {JSONEditor.Node} node + */ +JSONEditor.Node.prototype.appendChild = function(node) { + if (this.type == "array" || this.type == "object") { + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = this.type == "object"; + if (this.type == "array") { + node.index = this.childs.length; + } + this.childs.push(node); + + if (this.expanded) { + // insert into the DOM, before the appendRow + var newtr = node.getDom(); + var appendTr = this.getAppend(); + var table = appendTr ? appendTr.parentNode : undefined; + if (appendTr && table) { + table.insertBefore(newtr, appendTr); + } + + node.showChilds(); + } + + this.updateDom({ + updateIndexes: true + }); + node.updateDom({ + recurse: true + }); + } +}; + +/** + * Move a node from its current parent to this node + * Only applicable when Node value is of type array or object + * @param {JSONEditor.Node} node + * @param {JSONEditor.Node} beforeNode + */ +JSONEditor.Node.prototype.moveBefore = function(node, beforeNode) { + if (this.type == "array" || this.type == "object") { + // create a temporary row, to prevent the scroll position from jumping + // when removing the node + var tbody = this.dom.tr ? this.dom.tr.parentNode : undefined; + if (tbody) { + var trTemp = document.createElement("tr"); + trTemp.style.height = tbody.clientHeight + "px"; + tbody.appendChild(trTemp); + } + + var parent = node.getParent(); + if (parent) { + parent.removeChild(node); + } + if (beforeNode instanceof JSONEditor.AppendNode) { + this.appendChild(node); + } else { + this.insertBefore(node, beforeNode); + } + + if (tbody) { + tbody.removeChild(trTemp); + } + } +}; + +/** + * Move a node from its current parent to this node + * Only applicable when Node value is of type array or object. + * If index is out of range, the node will be appended to the end + * @param {JSONEditor.Node} node + * @param {Number} index + */ +JSONEditor.Node.prototype.moveTo = function(node, index) { + if (node.parent == this) { + // same parent + var currentIndex = this.childs.indexOf(node); + if (currentIndex < index) { + // compensate the index for removal of the node itself + index++; + } + } + + var beforeNode = this.childs[index] || this.append; + this.moveBefore(node, beforeNode); +}; + +/** + * Insert a new child before a given node + * Only applicable when Node value is of type array or object + * @param {JSONEditor.Node} node + * @param {JSONEditor.Node} beforeNode + */ +JSONEditor.Node.prototype.insertBefore = function(node, beforeNode) { + if (this.type == "array" || this.type == "object") { + if (beforeNode == this.append) { + // append to the child nodes + + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = this.type == "object"; + this.childs.push(node); + } else { + // insert before a child node + var index = this.childs.indexOf(beforeNode); + if (index == -1) { + throw new Error("鑺傜偣鏈壘鍒�."); + } + + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = this.type == "object"; + this.childs.splice(index, 0, node); + } + + if (this.expanded) { + // insert into the DOM + var newTr = node.getDom(); + var nextTr = beforeNode.getDom(); + var table = nextTr ? nextTr.parentNode : undefined; + if (nextTr && table) { + table.insertBefore(newTr, nextTr); + } + + node.showChilds(); + } + + this.updateDom({ + updateIndexes: true + }); + node.updateDom({ + recurse: true + }); + } +}; + +/** + * Search in this node + * The node will be expanded when the text is found one of its childs, else + * it will be collapsed. Searches are case insensitive. + * @param {String} text + * @return {JSONEditor.Node[]} results Array with nodes containing the search text + */ +JSONEditor.Node.prototype.search = function(text) { + var results = []; + var index; + var search = text ? text.toLowerCase() : undefined; + + // delete old search data + delete this.searchField; + delete this.searchValue; + + // search in field + if (this.field != undefined) { + var field = String(this.field).toLowerCase(); + index = field.indexOf(search); + if (index != -1) { + this.searchField = true; + results.push({ + node: this, + elem: "field" + }); + } + + // update dom + this._updateDomField(); + } + + // search in value + if (this.type == "array" || this.type == "object") { + // array, object + + // search the nodes childs + if (this.childs) { + var childResults = []; + this.childs.forEach(function(child) { + childResults = childResults.concat(child.search(text)); + }); + results = results.concat(childResults); + } + + // update dom + if (search != undefined) { + var recurse = false; + if (childResults.length == 0) { + this.collapse(recurse); + } else { + this.expand(recurse); + } + } + } else { + // string, auto + if (this.value != undefined) { + var value = String(this.value).toLowerCase(); + index = value.indexOf(search); + if (index != -1) { + this.searchValue = true; + results.push({ + node: this, + elem: "value" + }); + } + } + + // update dom + this._updateDomValue(); + } + + return results; +}; + +/** + * Move the scroll position such that this node is in the visible area. + * The node will not get the focus + */ +JSONEditor.Node.prototype.scrollTo = function() { + if (!this.dom.tr || !this.dom.tr.parentNode) { + // if the node is not visible, expand its parents + var parent = this.parent; + var recurse = false; + while (parent) { + parent.expand(recurse); + parent = parent.parent; + } + } + + if (this.dom.tr && this.dom.tr.parentNode) { + this.editor.scrollTo(this.dom.tr.offsetTop); + } +}; + +/** + * Set focus to the value of this node + * @param {String} [field] The field name of the element to get the focus + * available values: 'field', 'value' + */ +JSONEditor.Node.prototype.focus = function(field) { + if (this.dom.tr && this.dom.tr.parentNode) { + if (field != "value" && this.fieldEditable) { + var domField = this.dom.field; + if (domField) { + domField.focus(); + } + } else { + var domValue = this.dom.value; + if (domValue) { + domValue.focus(); + } + } + } +}; + +/** + * Update the values from the DOM field and value of this node + */ +JSONEditor.Node.prototype.blur = function() { + // retrieve the actual field and value from the DOM. + this._getDomValue(false); + this._getDomField(false); +}; + +/** + * Duplicate given child node + * new structure will be added right before the cloned node + * @param {JSONEditor.Node} node the childNode to be duplicated + * @return {JSONEditor.Node} clone the clone of the node + * @private + */ +JSONEditor.Node.prototype._duplicate = function(node) { + var clone = node.clone(); + + /* TODO: adjust the field name (to prevent equal field names) + if (this.type == 'object') { + } + */ + + // TODO: insert after instead of insert before + this.insertBefore(clone, node); + + return clone; +}; + +/** + * Check if given node is a child. The method will check recursively to find + * this node. + * @param {JSONEditor.Node} node + * @return {boolean} containsNode + */ +JSONEditor.Node.prototype.containsNode = function(node) { + if (this == node) { + return true; + } + + var childs = this.childs; + if (childs) { + // TOOD: use the js5 Array.some() here? + for (var i = 0, iMax = childs.length; i < iMax; i++) { + if (childs[i].containsNode(node)) { + return true; + } + } + } + + return false; +}; + +/** + * Move given node into this node + * @param {JSONEditor.Node} node the childNode to be moved + * @param {JSONEditor.Node} beforeNode node will be inserted before given + * node. If no beforeNode is given, + * the node is appended at the end + * @private + */ +JSONEditor.Node.prototype._move = function(node, beforeNode) { + if (node == beforeNode) { + // nothing to do... + return; + } + + // check if this node is not a child of the node to be moved here + if (node.containsNode(this)) { + throw new Error("涓嶈兘鎶婂尯鍩熺Щ鍔ㄥ埌鑷韩鐨勫瓙鑺傜偣."); + } + + // remove the original node + if (node.parent) { + node.parent.removeChild(node); + } + + // create a clone of the node + var clone = node.clone(); + node.clearDom(); + + // insert or append the node + if (beforeNode) { + this.insertBefore(clone, beforeNode); + } else { + this.appendChild(clone); + } + + /* TODO: adjust the field name (to prevent equal field names) + if (this.type == 'object') { + } + */ +}; + +/** + * Remove a child from the node. + * Only applicable when Node value is of type array or object + * @param {JSONEditor.Node} node The child node to be removed; + * @return {JSONEditor.Node | undefined} node The removed node on success, + * else undefined + */ +JSONEditor.Node.prototype.removeChild = function(node) { + if (this.childs) { + var index = this.childs.indexOf(node); + + if (index != -1) { + node.hide(); + + // delete old search results + delete node.searchField; + delete node.searchValue; + + var removedNode = this.childs.splice(index, 1)[0]; + + this.updateDom({ + updateIndexes: true + }); + + return removedNode; + } + } + + return undefined; +}; + +/** + * Remove a child node node from this node + * This method is equal to Node.removeChild, except that _remove firex an + * onChange event. + * @param {JSONEditor.Node} node + * @private + */ +JSONEditor.Node.prototype._remove = function(node) { + this.removeChild(node); +}; + +/** + * Change the type of the value of this Node + * @param {String} newType + */ +JSONEditor.Node.prototype.changeType = function(newType) { + var oldType = this.type; + + if ( + (newType == "string" || newType == "auto") && + (oldType == "string" || oldType == "auto") + ) { + // this is an easy change + this.type = newType; + } else { + // change from array to object, or from string/auto to object/array + + var table = this.dom.tr ? this.dom.tr.parentNode : undefined; + var lastTr; + if (this.expanded) { + lastTr = this.getAppend(); + } else { + lastTr = this.getDom(); + } + var nextTr = lastTr && lastTr.parentNode ? lastTr.nextSibling : undefined; + + // hide current field and all its childs + this.hide(); + this.clearDom(); + + // adjust the field and the value + this.type = newType; + + // adjust childs + if (newType == "object") { + if (!this.childs) { + this.childs = []; + } + + this.childs.forEach(function(child, index) { + child.clearDom(); + delete child.index; + child.fieldEditable = true; + if (child.field == undefined) { + child.field = index; + } + }); + + if (oldType == "string" || oldType == "auto") { + this.expanded = true; + } + } else if (newType == "array") { + if (!this.childs) { + this.childs = []; + } + + this.childs.forEach(function(child, index) { + child.clearDom(); + child.fieldEditable = false; + child.index = index; + }); + + if (oldType == "string" || oldType == "auto") { + this.expanded = true; + } + } else { + this.expanded = false; + } + + // create new DOM + if (table) { + if (nextTr) { + table.insertBefore(this.getDom(), nextTr); + } else { + table.appendChild(this.getDom()); + } + } + this.showChilds(); + } + + if (newType == "auto" || newType == "string") { + // cast value to the correct type + if (newType == "string") { + this.value = String(this.value); + } else { + this.value = this._stringCast(String(this.value)); + } + + this.focus(); + } + + this.updateDom({ + updateIndexes: true + }); +}; + +/** + * Retrieve value from DOM + * @param {boolean} silent. If true (default), no errors will be thrown in + * case of invalid data + * @private + */ +JSONEditor.Node.prototype._getDomValue = function(silent) { + if (this.dom.value && this.type != "array" && this.type != "object") { + this.valueInnerText = JSONEditor.getInnerText(this.dom.value); + } + + if (this.valueInnerText != undefined) { + try { + // retrieve the value + var value; + if (this.type == "string") { + value = this._unescapeHTML(this.valueInnerText); + } else { + var str = this._unescapeHTML(this.valueInnerText); + value = this._stringCast(str); + } + if (value !== this.value) { + var oldValue = this.value; + this.value = value; + this.editor.onAction("editValue", { + node: this, + oldValue: oldValue, + newValue: value + }); + } + } catch (err) { + this.value = undefined; + // TODO: sent an action with the new, invalid value? + if (silent != true) { + throw err; + } + } + } +}; + +/** + * Update dom value: + * - the text color of the value, depending on the type of the value + * - the height of the field, depending on the width + * - background color in case it is empty + * @private + */ +JSONEditor.Node.prototype._updateDomValue = function() { + var domValue = this.dom.value; + if (domValue) { + // set text color depending on value type + var v = this.value; + var t = this.type == "auto" ? typeof v : this.type; + var color = ""; + if (t == "string") { + color = "green"; + } else if (t == "number") { + color = "red"; + } else if (t == "boolean") { + color = "blue"; + } else if (this.type == "object" || this.type == "array") { + // note: typeof(null)=="object", therefore check this.type instead of t + color = ""; + } else if (v === null) { + color = "purple"; + } else if (v === undefined) { + // invalid value + color = "green"; + } + domValue.style.color = color; + + // make backgound color lightgray when empty + var isEmpty = + String(this.value) == "" && this.type != "array" && this.type != "object"; + if (isEmpty) { + JSONEditor.addClassName(domValue, "jsoneditor-empty"); + } else { + JSONEditor.removeClassName(domValue, "jsoneditor-empty"); + } + + // highlight when there is a search result + if (this.searchValueActive) { + JSONEditor.addClassName(domValue, "jsoneditor-search-highlight-active"); + } else { + JSONEditor.removeClassName( + domValue, + "jsoneditor-search-highlight-active" + ); + } + if (this.searchValue) { + JSONEditor.addClassName(domValue, "jsoneditor-search-highlight"); + } else { + JSONEditor.removeClassName(domValue, "jsoneditor-search-highlight"); + } + + // strip formatting from the contents of the editable div + JSONEditor.stripFormatting(domValue); + } +}; + +/** + * Update dom field: + * - the text color of the field, depending on the text + * - the height of the field, depending on the width + * - background color in case it is empty + * @private + */ +JSONEditor.Node.prototype._updateDomField = function() { + var domField = this.dom.field; + if (domField) { + // make backgound color lightgray when empty + var isEmpty = String(this.field) == ""; + if (isEmpty) { + JSONEditor.addClassName(domField, "jsoneditor-empty"); + } else { + JSONEditor.removeClassName(domField, "jsoneditor-empty"); + } + + // highlight when there is a search result + if (this.searchFieldActive) { + JSONEditor.addClassName(domField, "jsoneditor-search-highlight-active"); + } else { + JSONEditor.removeClassName( + domField, + "jsoneditor-search-highlight-active" + ); + } + if (this.searchField) { + JSONEditor.addClassName(domField, "jsoneditor-search-highlight"); + } else { + JSONEditor.removeClassName(domField, "jsoneditor-search-highlight"); + } + + // strip formatting from the contents of the editable div + JSONEditor.stripFormatting(domField); + } +}; + +/** + * Retrieve field from DOM + * @param {boolean} silent. If true (default), no errors will be thrown in + * case of invalid data + * @private + */ +JSONEditor.Node.prototype._getDomField = function(silent) { + if (this.dom.field && this.fieldEditable) { + this.fieldInnerText = JSONEditor.getInnerText(this.dom.field); + } + + if (this.fieldInnerText != undefined) { + try { + var field = this._unescapeHTML(this.fieldInnerText); + + if (field !== this.field) { + var oldField = this.field; + this.field = field; + this.editor.onAction("editField", { + node: this, + oldValue: oldField, + newValue: field + }); + } + } catch (err) { + this.field = undefined; + // TODO: sent an action here, with the new, invalid value? + if (silent != true) { + throw err; + } + } + } +}; + +/** + * Clear the dom of the node + */ +JSONEditor.Node.prototype.clearDom = function() { + // TODO: hide the node first? + //this.hide(); + // TOOD: recursively clear dom? + + this.dom = {}; +}; + +/** + * Get the HTML DOM TR element of the node. + * The dom will be generated when not yet created + * @return {Element} tr HTML DOM TR Element + */ +JSONEditor.Node.prototype.getDom = function() { + var dom = this.dom; + if (dom.tr) { + return dom.tr; + } + + // create row + dom.tr = document.createElement("tr"); + dom.tr.className = "jsoneditor-tr"; + dom.tr.node = this; + + if (this.editor.editable) { + // create draggable area + var tdDrag = document.createElement("td"); + tdDrag.className = "jsoneditor-td"; + dom.drag = this._createDomDragArea(); + if (dom.drag) { + tdDrag.appendChild(dom.drag); + } + dom.tr.appendChild(tdDrag); + } + + // create tree and field + var tdField = document.createElement("td"); + tdField.className = "jsoneditor-td"; + dom.tr.appendChild(tdField); + dom.expand = this._createDomExpandButton(); + dom.field = this._createDomField(); + dom.value = this._createDomValue(); + dom.tree = this._createDomTree(dom.expand, dom.field, dom.value); + tdField.appendChild(dom.tree); + + if (this.editor.editable) { + // create type select box + var tdType = document.createElement("td"); + tdType.className = "jsoneditor-td jsoneditor-td-edit"; + dom.tr.appendChild(tdType); + dom.type = this._createDomTypeButton(); + tdType.appendChild(dom.type); + + // create duplicate button + var tdDuplicate = document.createElement("td"); + tdDuplicate.className = "jsoneditor-td jsoneditor-td-edit"; + dom.tr.appendChild(tdDuplicate); + dom.duplicate = this._createDomDuplicateButton(); + if (dom.duplicate) { + tdDuplicate.appendChild(dom.duplicate); + } + + // create remove button + var tdRemove = document.createElement("td"); + tdRemove.className = "jsoneditor-td jsoneditor-td-edit"; + dom.tr.appendChild(tdRemove); + dom.remove = this._createDomRemoveButton(); + if (dom.remove) { + tdRemove.appendChild(dom.remove); + } + } + + this.updateDom(); // TODO: recurse here? + + return dom.tr; +}; + +/** + * DragStart event, fired on mousedown on the dragarea at the left side of a Node + * @param {Event} event + * @private + */ +JSONEditor.Node.prototype._onDragStart = function(event) { + event = event || window.event; + + var node = this; + if (!this.mousemove) { + this.mousemove = JSONEditor.Events.addEventListener( + document, + "mousemove", + + function(event) { + node._onDrag(event); + } + ); + } + + if (!this.mouseup) { + this.mouseup = JSONEditor.Events.addEventListener( + document, + "mouseup", + + function(event) { + node._onDragEnd(event); + } + ); + } + + /* TODO: correct highlighting when the TypeDropDown is visible (And has highlighting locked) + if (JSONEditor.freezeHighlight) { + console.log('heee'); + JSONEditor.freezeHighlight = false; + this.setHighlight(true); + } + */ + JSONEditor.freezeHighlight = true; + this.drag = { + oldCursor: document.body.style.cursor, + startParent: this.parent, + startIndex: this.parent.childs.indexOf(this) + }; + document.body.style.cursor = "move"; + + JSONEditor.Events.preventDefault(event); +}; + +/** + * Drag event, fired when moving the mouse while dragging a Node + * @param {Event} event + * @private + */ +JSONEditor.Node.prototype._onDrag = function(event) { + event = event || window.event; + var trThis = this.dom.tr; + + // TODO: add an ESC option, which resets to the original position + + var topThis = JSONEditor.getAbsoluteTop(trThis); + var heightThis = trThis.offsetHeight; + var mouseY = event.pageY || event.clientY + document.body.scrollTop; + if (mouseY < topThis) { + // move up + var trPrev = trThis.previousSibling; + var topPrev = JSONEditor.getAbsoluteTop(trPrev); + var nodePrev = JSONEditor.getNodeFromTarget(trPrev); + while (trPrev && mouseY < topPrev) { + nodePrev = JSONEditor.getNodeFromTarget(trPrev); + trPrev = trPrev.previousSibling; + topPrev = JSONEditor.getAbsoluteTop(trPrev); + } + + if (nodePrev) { + trPrev = nodePrev.dom.tr; + topPrev = JSONEditor.getAbsoluteTop(trPrev); + if (mouseY > topPrev + heightThis) { + nodePrev = undefined; + } + } + + if (nodePrev && nodePrev.parent) { + nodePrev.parent.moveBefore(this, nodePrev); + } + } else { + // move down + var trLast = + this.expanded && this.append ? this.append.getDom() : this.dom.tr; + var trFirst = trLast ? trLast.nextSibling : undefined; + if (trFirst) { + var topFirst = JSONEditor.getAbsoluteTop(trFirst); + + var nodeNext = undefined; + var trNext = trFirst.nextSibling; + var topNext = JSONEditor.getAbsoluteTop(trNext); + var heightNext = trNext ? topNext - topFirst : 0; + while (trNext && mouseY > topThis + heightNext) { + nodeNext = JSONEditor.getNodeFromTarget(trNext); + trNext = trNext.nextSibling; + topNext = JSONEditor.getAbsoluteTop(trNext); + heightNext = trNext ? topNext - topFirst : 0; + } + + if (nodeNext && nodeNext.parent) { + nodeNext.parent.moveBefore(this, nodeNext); + } + } + } + JSONEditor.Events.preventDefault(event); +}; + +/** + * Drag event, fired on mouseup after having dragged a node + * @param {Event} event + * @private + */ +JSONEditor.Node.prototype._onDragEnd = function(event) { + event = event || window.event; + + var params = { + node: this, + startParent: this.drag.startParent, + startIndex: this.drag.startIndex, + endParent: this.parent, + endIndex: this.parent.childs.indexOf(this) + }; + if ( + params.startParent != params.endParent || + params.startIndex != params.endIndex + ) { + // only register this action if the node is actually moved to another place + this.editor.onAction("moveNode", params); + } + + document.body.style.cursor = this.drag.oldCursor; + delete JSONEditor.freezeHighlight; + delete this.drag; + this.setHighlight(false); + + if (this.mousemove) { + JSONEditor.Events.removeEventListener( + document, + "mousemove", + this.mousemove + ); + delete this.mousemove; + } + if (this.mouseup) { + JSONEditor.Events.removeEventListener(document, "mouseup", this.mouseup); + delete this.mouseup; + } + + JSONEditor.Events.preventDefault(event); +}; + +/** + * Create a drag area, displayed at the left side of the node + * @return {Element | undefined} domDrag + * @private + */ +JSONEditor.Node.prototype._createDomDragArea = function() { + if (!this.parent) { + return undefined; + } + + var domDrag = document.createElement("button"); + domDrag.className = "jsoneditor-dragarea"; + domDrag.title = "Move field (drag and drop)"; + + return domDrag; +}; + +/** + * Create an editable field + * @return {Element} domField + * @private + */ +JSONEditor.Node.prototype._createDomField = function() { + return document.createElement("div"); +}; + +/** + * Set highlighting for this node and all its childs. + * Only applied to the currently visible (expanded childs) + * @param {boolean} highlight + */ +JSONEditor.Node.prototype.setHighlight = function(highlight) { + if (JSONEditor.freezeHighlight) { + return; + } + + if (this.dom.tr) { + this.dom.tr.className = + "jsoneditor-tr" + (highlight ? " jsoneditor-tr-highlight" : ""); + + if (this.append) { + this.append.setHighlight(highlight); + } + + if (this.childs) { + this.childs.forEach(function(child) { + child.setHighlight(highlight); + }); + } + } +}; + +/** + * Update the value of the node. Only primitive types are allowed, no Object + * or Array is allowed. + * @param {String | Number | Boolean | null} value + */ +JSONEditor.Node.prototype.updateValue = function(value) { + this.value = value; + this.updateDom(); +}; + +/** + * Update the field of the node. + * @param {String} field + */ +JSONEditor.Node.prototype.updateField = function(field) { + this.field = field; + this.updateDom(); +}; + +/** + * Update the HTML DOM, optionally recursing through the childs + * @param {Object} [options] Available parameters: + * {boolean} [recurse] If true, the + * DOM of the childs will be updated recursively. + * False by default. + * {boolean} [updateIndexes] If true, the childs + * indexes of the node will be updated too. False by + * default. + */ +JSONEditor.Node.prototype.updateDom = function(options) { + // update level indentation + var domTree = this.dom.tree; + if (domTree) { + domTree.style.marginLeft = this.getLevel() * 24 + "px"; + } + + // update field + var domField = this.dom.field; + if (domField) { + if (this.fieldEditable == true) { + // parent is an object + domField.contentEditable = this.editor.editable; + domField.spellcheck = false; + domField.className = "jsoneditor-field"; + } else { + // parent is an array this is the root node + domField.className = "jsoneditor-readonly"; + } + + var field; + if (this.index != undefined) { + field = this.index; + } else if (this.field != undefined) { + field = this.field; + } else if (this.type == "array" || this.type == "object") { + field = this.type; + } else { + field = "field"; + } + domField.innerHTML = this._escapeHTML(field); + } + + // update value + var domValue = this.dom.value; + if (domValue) { + var count = this.childs ? this.childs.length : 0; + if (this.type == "array") { + domValue.innerHTML = "[" + count + "]"; + domValue.title = this.type + " containing " + count + " items"; + } else if (this.type == "object") { + domValue.innerHTML = "{" + count + "}"; + domValue.title = this.type + " containing " + count + " items"; + } else { + domValue.innerHTML = this._escapeHTML(this.value); + delete domValue.title; + } + } + + // update field and value + this._updateDomField(); + this._updateDomValue(); + + // update childs indexes + if (options && options.updateIndexes == true) { + // updateIndexes is true or undefined + this._updateDomIndexes(); + } + + if (options && options.recurse == true) { + // recurse is true or undefined. update childs recursively + if (this.childs) { + this.childs.forEach(function(child) { + child.updateDom(options); + }); + } + + // update row with append button + if (this.append) { + this.append.updateDom(); + } + } +}; + +/** + * Update the DOM of the childs of a node: update indexes and undefined field + * names. + * Only applicable when structure is an array or object + * @private + */ +JSONEditor.Node.prototype._updateDomIndexes = function() { + var domValue = this.dom.value; + var childs = this.childs; + if (domValue && childs) { + if (this.type == "array") { + childs.forEach(function(child, index) { + child.index = index; + var childField = child.dom.field; + if (childField) { + childField.innerHTML = index; + } + }); + } else if (this.type == "object") { + childs.forEach(function(child) { + if (child.index != undefined) { + delete child.index; + + if (child.field == undefined) { + child.field = "field"; + } + } + }); + } + } +}; + +/** + * Create an editable value + * @private + */ +JSONEditor.Node.prototype._createDomValue = function() { + var domValue; + + if (this.type == "array") { + domValue = document.createElement("div"); + domValue.className = "jsoneditor-readonly"; + domValue.innerHTML = "[...]"; + } else if (this.type == "object") { + domValue = document.createElement("div"); + domValue.className = "jsoneditor-readonly"; + domValue.innerHTML = "{...}"; + } else if (this.type == "string") { + domValue = document.createElement("div"); + domValue.contentEditable = this.editor.editable; + domValue.spellcheck = false; + domValue.className = "jsoneditor-value"; + domValue.innerHTML = this._escapeHTML(this.value); + } else { + domValue = document.createElement("div"); + domValue.contentEditable = this.editor.editable; + domValue.spellcheck = false; + domValue.className = "jsoneditor-value"; + domValue.innerHTML = this._escapeHTML(this.value); + } + + // TODO: in FF spel/check of editable divs is done via the body. quite ugly + // document.body.spellcheck = false; + + return domValue; +}; + +/** + * Create an expand/collapse button + * @return {Element} expand + * @private + */ +JSONEditor.Node.prototype._createDomExpandButton = function() { + // create expand button + var expand = document.createElement("button"); + var expandable = this.type == "array" || this.type == "object"; + if (expandable) { + expand.className = this.expanded + ? "jsoneditor-expanded" + : "jsoneditor-collapsed"; + expand.title = + "Click to expand/collapse this field. \n" + + "Ctrl+Click to expand/collapse including all childs."; + } else { + expand.className = "jsoneditor-invisible"; + expand.title = ""; + } + + return expand; +}; + +/** + * Create a DOM tree element, containing the expand/collapse button + * @param {Element} domExpand + * @param {Element} domField + * @param {Element} domValue + * @return {Element} domTree + * @private + */ +JSONEditor.Node.prototype._createDomTree = function( + domExpand, + domField, + domValue +) { + var dom = this.dom; + var domTree = document.createElement("table"); + var tbody = document.createElement("tbody"); + domTree.style.borderCollapse = "collapse"; // TODO: put in css + domTree.appendChild(tbody); + var tr = document.createElement("tr"); + tbody.appendChild(tr); + + // create expand button + var tdExpand = document.createElement("td"); + tdExpand.className = "jsoneditor-td-tree"; + tr.appendChild(tdExpand); + tdExpand.appendChild(domExpand); + dom.tdExpand = tdExpand; + + // add the field + var tdField = document.createElement("td"); + tdField.className = "jsoneditor-td-tree"; + tr.appendChild(tdField); + tdField.appendChild(domField); + dom.tdField = tdField; + + // add a separator + var tdSeparator = document.createElement("td"); + tdSeparator.className = "jsoneditor-td-tree"; + tr.appendChild(tdSeparator); + if (this.type != "object" && this.type != "array") { + tdSeparator.appendChild(document.createTextNode(":")); + tdSeparator.className = "jsoneditor-separator"; + } + dom.tdSeparator = tdSeparator; + + // add the value + var tdValue = document.createElement("td"); + tdValue.className = "jsoneditor-td-tree"; + tr.appendChild(tdValue); + tdValue.appendChild(domValue); + dom.tdValue = tdValue; + + return domTree; +}; + +/** + * Handle an event. The event is catched centrally by the editor + * @param {Event} event + */ +JSONEditor.Node.prototype.onEvent = function(event) { + var type = event.type; + var target = event.target || event.srcElement; + var dom = this.dom; + var node = this; + var expandable = this.type == "array" || this.type == "object"; + + // value events + var domValue = dom.value; + if (target == domValue) { + switch (type) { + case "focus": + JSONEditor.focusNode = this; + break; + + case "blur": + case "change": + this._getDomValue(true); + this._updateDomValue(); + if (this.value) { + domValue.innerHTML = this._escapeHTML(this.value); + } + break; + + case "keyup": + this._getDomValue(true); + this._updateDomValue(); + break; + + case "cut": + case "paste": + setTimeout(function() { + node._getDomValue(true); + node._updateDomValue(); + }, 1); + break; + } + } + + // field events + var domField = dom.field; + if (target == domField) { + switch (type) { + case "focus": + JSONEditor.focusNode = this; + break; + + case "change": + case "blur": + this._getDomField(true); + this._updateDomField(); + if (this.field) { + domField.innerHTML = this._escapeHTML(this.field); + } + break; + + case "keyup": + this._getDomField(true); + this._updateDomField(); + break; + + case "cut": + case "paste": + setTimeout(function() { + node._getDomField(true); + node._updateDomField(); + }, 1); + break; + } + } + + // drag events + var domDrag = dom.drag; + if (target == domDrag) { + switch (type) { + case "mousedown": + this._onDragStart(event); + break; + case "mouseover": + this.setHighlight(true); + break; + case "mouseout": + this.setHighlight(false); + break; + } + } + + // expand events + var domExpand = dom.expand; + if (target == domExpand) { + if (type == "click") { + if (expandable) { + this._onExpand(event); + } + } + } + + // duplicate button + var domDuplicate = dom.duplicate; + if (target == domDuplicate) { + switch (type) { + case "click": + var clone = this.parent._duplicate(this); + + this.editor.onAction("duplicateNode", { + node: this, + clone: clone, + parent: this.parent + }); + break; + case "mouseover": + this.setHighlight(true); + break; + case "mouseout": + this.setHighlight(false); + break; + } + } + + // remove button + var domRemove = dom.remove; + if (target == domRemove) { + switch (type) { + case "click": + this._onRemove(); + break; + case "mouseover": + this.setHighlight(true); + break; + case "mouseout": + this.setHighlight(false); + break; + } + } + + // type button + var domType = dom.type; + if (target == domType) { + switch (type) { + case "click": + this._onChangeType(event); + break; + case "mouseover": + this.setHighlight(true); + break; + case "mouseout": + this.setHighlight(false); + break; + } + } + + // focus + // when clicked in whitespace left or right from the field or value, set focus + var domTree = dom.tree; + if (target == domTree.parentNode) { + switch (type) { + case "click": + var left = + event.offsetX != undefined + ? event.offsetX < (this.getLevel() + 1) * 24 + : event.clientX < JSONEditor.getAbsoluteLeft(dom.tdSeparator); // for FF + if (left || expandable) { + // node is expandable when it is an object or array + if (domField) { + JSONEditor.setEndOfContentEditable(domField); + domField.focus(); + } + } else { + if (domValue) { + JSONEditor.setEndOfContentEditable(domValue); + domValue.focus(); + } + } + break; + } + } + + if ( + (target == dom.tdExpand && !expandable) || + target == dom.tdField || + target == dom.tdSeparator + ) { + switch (type) { + case "click": + if (domField) { + JSONEditor.setEndOfContentEditable(domField); + domField.focus(); + } + break; + } + } +}; + +/** + * Handle the expand event, when clicked on the expand button + * @param {Event} event + * @private + */ +JSONEditor.Node.prototype._onExpand = function(event) { + event = event || window.event; + var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all + + if (recurse) { + // Take the table offline + var table = this.dom.tr.parentNode; // TODO: not nice to access the main table like this + var frame = table.parentNode; + var scrollTop = frame.scrollTop; + frame.removeChild(table); + } + + if (this.expanded) { + this.collapse(recurse); + } else { + this.expand(recurse); + } + + if (recurse) { + // Put the table online again + frame.appendChild(table); + frame.scrollTop = scrollTop; + } +}; + +JSONEditor.Node.types = [ + { + value: "array", + className: "jsoneditor-option-array", + title: '"array" 绫诲瀷: 涓€涓寘鍚簡鏈夊簭鍊奸泦鍚堢殑鏁扮粍.' + }, + { + value: "auto", + className: "jsoneditor-option-auto", + title: + '"auto" 绫诲瀷: 鑺傜偣绫诲瀷灏嗚嚜鍔ㄤ粠鍊间腑鑾峰彇, 鍙互鏄�: string, number, boolean, 鎴栬€� null.' + }, + { + value: "object", + className: "jsoneditor-option-object", + title: '"object" 绫诲瀷: 瀵硅薄鍖呭惈浜嗕竴浜涙棤搴忕殑閿�/鍊煎.' + }, + { + value: "string", + className: "jsoneditor-option-string", + title: '"string" 绫诲瀷: 鑺傜偣绫诲瀷涓嶄粠鍊间腑鑷姩鑾峰彇, 浣嗘案杩滆繑鍥� string.' + } +]; + +/** + * Create a DOM select box containing the node type + * @return {Element} domType + * @private + */ +JSONEditor.Node.prototype._createDomTypeButton = function() { + var node = this; + var domType = document.createElement("button"); + domType.className = "jsoneditor-type-" + node.type; + domType.title = "鏀瑰彉鑺傜偣绫诲瀷"; + + return domType; +}; + +/** + * Remove this node + * @private + */ +JSONEditor.Node.prototype._onRemove = function() { + this.setHighlight(false); + var index = this.parent.childs.indexOf(this); + + this.parent._remove(this); + + this.editor.onAction("removeNode", { + node: this, + parent: this.parent, + index: index + }); +}; + +/** + * Handle a click on the Type-button + * @param {Event} event + * @private + */ +JSONEditor.Node.prototype._onChangeType = function(event) { + JSONEditor.Events.stopPropagation(event); + + var domType = this.dom.type; + + var node = this; + var x = JSONEditor.getAbsoluteLeft(domType); + var y = JSONEditor.getAbsoluteTop(domType) + domType.clientHeight; + var callback = function(newType) { + var oldType = node.type; + node.changeType(newType); + node.editor.onAction("changeType", { + node: node, + oldType: oldType, + newType: newType + }); + domType.className = "jsoneditor-type-" + node.type; + }; + JSONEditor.showDropDownList({ + x: x, + y: y, + node: node, + value: node.type, + values: JSONEditor.Node.types, + className: "jsoneditor-select", + optionSelectedClassName: "jsoneditor-option-selected", + optionClassName: "jsoneditor-option", + callback: callback + }); +}; + +/** + * Show a dropdown list + * @param {Object} params Available parameters: + * {Number} x The absolute horizontal position + * {Number} y The absolute vertical position + * {JSONEditor.Node} node node used for highlighting + * {String} value current selected value + * {Object[]} values the available values. Each object + * contains a value, title, and + * className + * {String} optionSelectedClassName + * {String} optionClassName + * {function} callback Callback method, called when + * the selected value changed. + */ +JSONEditor.showDropDownList = function(params) { + var select = document.createElement("div"); + select.className = params.className || ""; + select.style.position = "absolute"; + select.style.left = (params.x || 0) + "px"; + select.style.top = (params.y || 0) + "px"; + + params.values.forEach(function(v) { + var text = v.value || String(v); + var className = "jsoneditor-option"; + var selected = text == params.value; + if (selected) { + className += " " + params.optionSelectedClassName; + } + var option = document.createElement("div"); + option.className = className; + if (v.title) { + option.title = v.title; + } + + var divIcon = document.createElement("div"); + divIcon.className = v.className || ""; + option.appendChild(divIcon); + + var divText = document.createElement("div"); + divText.className = "jsoneditor-option-text"; + divText.innerHTML = "
                                                              " + text + "
                                                              "; + option.appendChild(divText); + + option.onmousedown = (function(value) { + return function() { + params.callback(value); + }; + })(v.value); + select.appendChild(option); + }); + + document.body.appendChild(select); + params.node.setHighlight(true); + JSONEditor.freezeHighlight = true; + + // TODO: change to onclick? -> but be sure to remove existing dropdown first + var onmousedown = JSONEditor.Events.addEventListener( + document, + "mousedown", + function() { + JSONEditor.freezeHighlight = false; + params.node.setHighlight(false); + if (select && select.parentNode) { + select.parentNode.removeChild(select); + } + JSONEditor.Events.removeEventListener(document, "mousedown", onmousedown); + } + ); + var onmousewheel = JSONEditor.Events.addEventListener( + document, + "mousewheel", + function() { + JSONEditor.freezeHighlight = false; + params.node.setHighlight(false); + if (select && select.parentNode) { + select.parentNode.removeChild(select); + } + JSONEditor.Events.removeEventListener( + document, + "mousewheel", + onmousewheel + ); + } + ); +}; + +/** + * Create a table row with an append button. + * @return {Element | undefined} buttonAppend or undefined when inapplicable + */ +JSONEditor.Node.prototype.getAppend = function() { + if (!this.append) { + this.append = new JSONEditor.AppendNode(this.editor); + this.append.setParent(this); + } + return this.append.getDom(); +}; + +/** + * Create a remove button. Returns undefined when the structure cannot + * be removed + * @return {Element | undefined} removeButton, or undefined when inapplicable + * @private + */ +JSONEditor.Node.prototype._createDomRemoveButton = function() { + if ( + this.parent && + (this.parent.type == "array" || this.parent.type == "object") + ) { + var buttonRemove = document.createElement("button"); + buttonRemove.className = "jsoneditor-remove"; + buttonRemove.title = "鍒犻櫎鑺傜偣 (鍖呮嫭鎵€鏈夊瓙鑺傜偣)"; + + return buttonRemove; + } else { + return undefined; + } +}; + +/** + * Create a duplicate button. + * If the Node is the root node, no duplicate button is available and undefined + * will be returned + * @return {Element | undefined} buttonDuplicate + * @private + */ +JSONEditor.Node.prototype._createDomDuplicateButton = function() { + if ( + this.parent && + (this.parent.type == "array" || this.parent.type == "object") + ) { + var buttonDupliate = document.createElement("button"); + buttonDupliate.className = "jsoneditor-duplicate"; + buttonDupliate.title = "澶嶅埗鑺傜偣 (鍖呮嫭鎵€鏈夊瓙鑺傜偣)"; + + return buttonDupliate; + } else { + return undefined; + } +}; + +/** + * get the type of a value + * @param {*} value + * @return {String} type Can be 'object', 'array', 'string', 'auto' + * @private + */ +JSONEditor.Node.prototype._getType = function(value) { + if (value instanceof Array) { + return "array"; + } + if (value instanceof Object) { + return "object"; + } + if (typeof value == "string" && typeof this._stringCast(value) != "string") { + return "string"; + } + + return "auto"; +}; + +/** + * cast contents of a string to the correct type. This can be a string, + * a number, a boolean, etc + * @param {String} str + * @return {*} castedStr + * @private + */ +JSONEditor.Node.prototype._stringCast = function(str) { + var lower = str.toLowerCase(), + num = Number(str), // will nicely fail with '123ab' + numFloat = parseFloat(str); // will nicely fail with ' ' + + if (str == "") { + return ""; + } else if (lower == "null") { + return null; + } else if (lower == "true") { + return true; + } else if (lower == "false") { + return false; + } else if (!isNaN(num) && !isNaN(numFloat)) { + return num; + } else { + return str; + } +}; + +/** + * escape a text, such that it can be displayed safely in an HTML element + * @param {String} text + * @return {String} escapedText + * @private + */ +JSONEditor.Node.prototype._escapeHTML = function(text) { + var htmlEscaped = String(text) + .replace(//g, ">") + .replace(/ /g, "  ") // replace double space with an nbsp and space + .replace(/^ /, " ") // space at start + .replace(/ $/, " "); // space at end + + var json = JSON.stringify(htmlEscaped); + return json.substring(1, json.length - 1); +}; + +/** + * unescape a string. + * @param {String} escapedText + * @return {String} text + * @private + */ +JSONEditor.Node.prototype._unescapeHTML = function(escapedText) { + var json = '"' + this._escapeJSON(escapedText) + '"'; + var htmlEscaped = JSONEditor.parse(json); + return htmlEscaped + .replace(/</g, "<") + .replace(/>/g, ">") + .replace(/ /g, " "); +}; + +/** + * escape a text to make it a valid JSON string. The method will: + * - replace unescaped double quotes with '\"' + * - replace unescaped backslash with '\\' + * - replace returns with '\n' + * @param {String} text + * @return {String} escapedText + * @private + */ +JSONEditor.Node.prototype._escapeJSON = function(text) { + // TODO: replace with some smart regex (only when a new solution is faster!) + var escaped = ""; + var i = 0, + iMax = text.length; + while (i < iMax) { + var c = text.charAt(i); + if (c == "\n") { + escaped += "\\n"; + } else if (c == "\\") { + escaped += c; + i++; + + c = text.charAt(i); + if ('"\\/bfnrtu'.indexOf(c) == -1) { + escaped += "\\"; // no valid escape character + } + escaped += c; + } else if (c == '"') { + escaped += '\\"'; + } else { + escaped += c; + } + i++; + } + + return escaped; +}; + +/** + * @constructor JSONEditor.AppendNode + * @extends JSONEditor.Node + * @param {JSONEditor} editor + * Create a new AppendNode. This is a special node which is created at the + * end of the list with childs for an object or array + */ +JSONEditor.AppendNode = function(editor) { + this.editor = editor; + this.dom = {}; +}; + +JSONEditor.AppendNode.prototype = new JSONEditor.Node(); + +/** + * Return a table row with an append button. + * @return {Element} dom TR element + */ +JSONEditor.AppendNode.prototype.getDom = function() { + if (this.dom.tr) { + return this.dom.tr; + } + + /** + * Create a TD element, and give it the provided class name (if any) + * @param {String} [className] + * @return {Element} td + */ + function newTd(className) { + var td = document.createElement("td"); + td.className = className || ""; + return td; + } + + // a row for the append button + var trAppend = document.createElement("tr"); + trAppend.node = this; + + // TODO: do not create an appendNode at all when in viewer mode + if (!this.editor.editable) { + return trAppend; + } + + // a cell for the drag area column + trAppend.appendChild(newTd("jsoneditor-td")); + + // a cell for the append button + var tdAppend = document.createElement("td"); + trAppend.appendChild(tdAppend); + tdAppend.className = "jsoneditor-td"; + + // create the append button + var buttonAppend = document.createElement("button"); + buttonAppend.className = "jsoneditor-append"; + buttonAppend.title = "娣诲姞"; + this.dom.append = buttonAppend; + tdAppend.appendChild(buttonAppend); + + trAppend.appendChild(newTd("jsoneditor-td jsoneditor-td-edit")); + trAppend.appendChild(newTd("jsoneditor-td jsoneditor-td-edit")); + trAppend.appendChild(newTd("jsoneditor-td jsoneditor-td-edit")); + + this.dom.tr = trAppend; + this.dom.td = tdAppend; + + this.updateDom(); + + return trAppend; +}; + +/** + * Update the HTML dom of the Node + */ +JSONEditor.AppendNode.prototype.updateDom = function() { + var tdAppend = this.dom.td; + if (tdAppend) { + tdAppend.style.paddingLeft = this.getLevel() * 24 + 26 + "px"; + // TODO: not so nice hard coded offset + } +}; + +/** + * Handle an event. The event is catched centrally by the editor + * @param {Event} event + */ +JSONEditor.AppendNode.prototype.onEvent = function(event) { + var type = event.type; + var target = event.target || event.srcElement; + var dom = this.dom; + + var domAppend = dom.append; + if (target == domAppend) { + switch (type) { + case "click": + this._onAppend(); + break; + + case "mouseover": + this.parent.setHighlight(true); + break; + + case "mouseout": + this.parent.setHighlight(false); + } + } +}; + +/** + * Handle append event + * @private + */ +JSONEditor.AppendNode.prototype._onAppend = function() { + var newNode = new JSONEditor.Node(this.editor, { + field: "field", + value: "value" + }); + this.parent.appendChild(newNode); + this.parent.setHighlight(false); + newNode.focus(); + + this.editor.onAction("appendNode", { + node: newNode, + parent: this.parent + }); +}; + +/** + * Create main frame + * @private + */ +JSONEditor.prototype._createFrame = function() { + // create the frame + this.container.innerHTML = ""; + this.frame = document.createElement("div"); + this.frame.className = "jsoneditor-frame"; + this.container.appendChild(this.frame); + + // create one global event listener to handle all events from all nodes + var editor = this; + // TODO: move this onEvent to JSONEditor.prototype.onEvent + var onEvent = function(event) { + event = event || window.event; + var target = event.target || event.srcElement; + + /* TODO: Enable quickkeys Ctrl+F and F3. + // Requires knowing whether the JSONEditor has focus or not + // (use a global event listener for that?) + // Check for search quickkeys, Ctrl+F and F3 + if (editor.options.search) { + if (event.type == 'keydown') { + var keynum = event.which || event.keyCode; + if (keynum == 70 && event.ctrlKey) { // Ctrl+F + if (editor.searchBox) { + editor.searchBox.dom.search.focus(); + editor.searchBox.dom.search.select(); + JSONEditor.Events.preventDefault(event); + JSONEditor.Events.stopPropagation(event); + } + } + else if (keynum == 114) { // F3 + if (!event.shiftKey) { + // select next search result + editor.searchBox.next(); + } + else { + // select previous search result + editor.searchBox.previous(); + } + editor.searchBox.focusActiveResult(); + + // set selection to the current + JSONEditor.Events.preventDefault(event); + JSONEditor.Events.stopPropagation(event); + } + } + } + */ + + var node = JSONEditor.getNodeFromTarget(target); + if (node) { + node.onEvent(event); + } + }; + this.frame.onclick = function(event) { + onEvent(event); + + // prevent default submit action when JSONEditor is located inside a form + JSONEditor.Events.preventDefault(event); + }; + this.frame.onchange = onEvent; + this.frame.onkeydown = onEvent; + this.frame.onkeyup = onEvent; + this.frame.oncut = onEvent; + this.frame.onpaste = onEvent; + this.frame.onmousedown = onEvent; + this.frame.onmouseup = onEvent; + this.frame.onmouseover = onEvent; + this.frame.onmouseout = onEvent; + // Note: focus and blur events do not propagate, therefore they defined + // using an eventListener with useCapture=true + // see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html + JSONEditor.Events.addEventListener(this.frame, "focus", onEvent, true); + JSONEditor.Events.addEventListener(this.frame, "blur", onEvent, true); + this.frame.onfocusin = onEvent; // for IE + this.frame.onfocusout = onEvent; // for IE + + // create menu + this.menu = document.createElement("div"); + this.menu.className = "jsoneditor-menu"; + this.frame.appendChild(this.menu); + + // create expand all button + var expandAll = document.createElement("button"); + expandAll.className = "jsoneditor-menu jsoneditor-expand-all"; + expandAll.title = "灞曞紑"; + expandAll.onclick = function() { + editor.expandAll(); + }; + this.menu.appendChild(expandAll); + + // create expand all button + var collapseAll = document.createElement("button"); + collapseAll.title = "鎶樺彔"; + collapseAll.className = "jsoneditor-menu jsoneditor-collapse-all"; + collapseAll.onclick = function() { + editor.collapseAll(); + }; + this.menu.appendChild(collapseAll); + + // create expand/collapse buttons + if (this.history) { + // create separator + var separator = document.createElement("span"); + separator.innerHTML = " "; + this.menu.appendChild(separator); + + // create undo button + var undo = document.createElement("button"); + undo.className = "jsoneditor-menu jsoneditor-undo"; + undo.title = "鎾ら攢"; + undo.onclick = function() { + // undo last action + editor.history.undo(); + + // trigger change callback + if (editor.options.change) { + editor.options.change(); + } + }; + this.menu.appendChild(undo); + this.dom.undo = undo; + + // create redo button + var redo = document.createElement("button"); + redo.className = "jsoneditor-menu jsoneditor-redo"; + redo.title = "閲嶅仛"; + redo.onclick = function() { + // redo last action + editor.history.redo(); + + // trigger change callback + if (editor.options.change) { + editor.options.change(); + } + }; + this.menu.appendChild(redo); + this.dom.redo = redo; + + // register handler for onchange of history + this.history.onChange = function() { + undo.disabled = !editor.history.canUndo(); + redo.disabled = !editor.history.canRedo(); + }; + this.history.onChange(); + } + + // create search box + if (this.options.search) { + this.searchBox = new JSONEditor.SearchBox(this, this.menu); + } +}; + +/** + * Create main table + * @private + */ +JSONEditor.prototype._createTable = function() { + var contentOuter = document.createElement("div"); + contentOuter.className = "jsoneditor-content-outer"; + this.contentOuter = contentOuter; + + this.content = document.createElement("div"); + this.content.className = "jsoneditor-content"; + contentOuter.appendChild(this.content); + + this.table = document.createElement("table"); + this.table.className = "jsoneditor-table"; + this.content.appendChild(this.table); + + // IE8 does not handle overflow='auto' correctly. + // Therefore, set overflow to 'scroll' + var ieVersion = JSONEditor.getInternetExplorerVersion(); + if (ieVersion == 8) { + this.content.style.overflow = "scroll"; + } + + // create colgroup where the first two columns don't have a fixed + // width, and the edit columns do have a fixed width + var col; + this.colgroupContent = document.createElement("colgroup"); + col = document.createElement("col"); + col.width = "24px"; + this.colgroupContent.appendChild(col); + col = document.createElement("col"); + this.colgroupContent.appendChild(col); + col = document.createElement("col"); + col.width = "24px"; + this.colgroupContent.appendChild(col); + col = document.createElement("col"); + col.width = "24px"; + this.colgroupContent.appendChild(col); + col = document.createElement("col"); + col.width = "24px"; + this.colgroupContent.appendChild(col); + this.table.appendChild(this.colgroupContent); + + this.tbody = document.createElement("tbody"); + this.table.appendChild(this.tbody); + + this.frame.appendChild(contentOuter); +}; + +/** + * Find the node from an event target + * @param {Element} target + * @return {JSONEditor.Node | undefined} node or undefined when not found + */ +JSONEditor.getNodeFromTarget = function(target) { + while (target) { + if (target.node) { + return target.node; + } + target = target.parentNode; + } + + return undefined; +}; + +/** + * Create a JSONFormatter and attach it to given container + * @constructor JSONFormatter + * @param {Element} container + * @param {Object} [options] Object with options. available options: + * {Number} indentation Number of indentation + * spaces. 4 by default. + * {function} change Callback method + * triggered on change + * @param {JSON | String} [json] initial contents of the formatter + */ +JSONFormatter = function(container, options, json) { + // check availability of JSON parser (not available in IE7 and older) + if (!JSON) { + throw new Error( + "鎮ㄥ綋鍓嶄娇鐢ㄧ殑娴忚鍣ㄤ笉鏀寔 JSON. \n\n" + + "璇蜂笅杞藉畨瑁呮渶鏂扮増鏈殑娴忚鍣�, 鏈珯鎺ㄨ崘Google Chrome.\n" + + "(PS: 褰撳墠涓绘祦娴忚鍣ㄩ兘鏀寔JSON)." + ); + } + + this.container = container; + this.indentation = 4; // number of spaces + + this.width = container.clientWidth; + this.height = container.clientHeight; + + this.frame = document.createElement("div"); + this.frame.className = "jsoneditor-frame"; + this.frame.onclick = function(event) { + // prevent default submit action when JSONFormatter is located inside a form + JSONEditor.Events.preventDefault(event); + }; + + // create menu + this.menu = document.createElement("div"); + this.menu.className = "jsoneditor-menu"; + this.frame.appendChild(this.menu); + + // create format button + var buttonFormat = document.createElement("button"); + //buttonFormat.innerHTML = 'Format'; + buttonFormat.className = "jsoneditor-menu jsoneditor-format"; + buttonFormat.title = "鏍煎紡鍖朖SON鏁版嵁"; + //buttonFormat.className = 'jsoneditor-button'; + this.menu.appendChild(buttonFormat); + + // create compact button + var buttonCompact = document.createElement("button"); + //buttonCompact.innerHTML = 'Compact'; + buttonCompact.className = "jsoneditor-menu jsoneditor-compact"; + buttonCompact.title = "鍘嬬缉JSON鏁版嵁, 娓呴櫎鎵€鏈夌┖鐧藉瓧绗�"; + //buttonCompact.className = 'jsoneditor-button'; + this.menu.appendChild(buttonCompact); + + this.content = document.createElement("div"); + this.content.className = "jsonformatter-content"; + this.frame.appendChild(this.content); + + this.textarea = document.createElement("textarea"); + this.textarea.className = "jsonformatter-textarea"; + this.textarea.spellcheck = false; + this.content.appendChild(this.textarea); + + var textarea = this.textarea; + + // read the options + if (options) { + if (options.change) { + // register on change event + if (this.textarea.oninput === null) { + this.textarea.oninput = function() { + options.change(); + }; + } else { + // oninput is undefined. For IE8- + this.textarea.onchange = function() { + options.change(); + }; + } + } + if (options.indentation) { + this.indentation = Number(options.indentation); + } + } + + var me = this; + buttonFormat.onclick = function() { + try { + var json = JSONEditor.parse(textarea.value); + textarea.value = JSON.stringify(json, null, me.indentation); + } catch (err) { + me.onError(err); + } + }; + buttonCompact.onclick = function() { + try { + var json = JSONEditor.parse(textarea.value); + textarea.value = JSON.stringify(json); + } catch (err) { + me.onError(err); + } + }; + + this.container.appendChild(this.frame); + + // load initial json object or string + if (typeof json == "string") { + this.setText(json); + } else { + this.set(json); + } +}; + +/** + * This method is executed on error. + * It can be overwritten for each instance of the JSONFormatter + * @param {String} err + */ +JSONFormatter.prototype.onError = function(err) { + // action should be implemented for the instance +}; + +/** + * Set json data in the formatter + * @param {Object} json + */ +JSONFormatter.prototype.set = function(json) { + this.textarea.value = JSON.stringify(json, null, this.indentation); +}; + +/** + * Get json data from the formatter + * @return {Object} json + */ +JSONFormatter.prototype.get = function() { + return JSONEditor.parse(this.textarea.value); +}; + +/** + * Get the text contents of the JSONFormatter + * @return {String} text + */ +JSONFormatter.prototype.getText = function() { + return this.textarea.value; +}; + +/** + * Set the text contents of the JSONFormatter + * @param {String} text + */ +JSONFormatter.prototype.setText = function(text) { + this.textarea.value = text; +}; + +/** + * @constructor JSONEditor.SearchBox + * Create a search box in given HTML container + * @param {JSONEditor} editor The JSON Editor to attach to + * @param {Element} container HTML container element of where to create the + * search box + */ +JSONEditor.SearchBox = function(editor, container) { + var searchBox = this; + + this.editor = editor; + this.timeout = undefined; + this.delay = 200; // ms + this.lastText = undefined; + + this.dom = {}; + this.dom.container = container; + + var table = document.createElement("table"); + this.dom.table = table; + table.className = "jsoneditor-search"; + container.appendChild(table); + var tbody = document.createElement("tbody"); + this.dom.tbody = tbody; + table.appendChild(tbody); + var tr = document.createElement("tr"); + tbody.appendChild(tr); + + var td = document.createElement("td"); + td.className = "jsoneditor-search"; + tr.appendChild(td); + var results = document.createElement("div"); + this.dom.results = results; + results.className = "jsoneditor-search-results"; + td.appendChild(results); + + td = document.createElement("td"); + td.className = "jsoneditor-search"; + tr.appendChild(td); + var divInput = document.createElement("div"); + this.dom.input = divInput; + divInput.className = "jsoneditor-search"; + divInput.title = "鏌ユ壘鍖哄潡鍜屽€�"; + td.appendChild(divInput); + + // table to contain the text input and search button + var tableInput = document.createElement("table"); + tableInput.className = "jsoneditor-search-input"; + divInput.appendChild(tableInput); + var tbodySearch = document.createElement("tbody"); + tableInput.appendChild(tbodySearch); + tr = document.createElement("tr"); + tbodySearch.appendChild(tr); + + var refreshSearch = document.createElement("button"); + refreshSearch.className = "jsoneditor-search-refresh"; + td = document.createElement("td"); + td.appendChild(refreshSearch); + tr.appendChild(td); + + var search = document.createElement("input"); + this.dom.search = search; + search.className = "jsoneditor-search"; + search.oninput = function(event) { + searchBox.onDelayedSearch(event); + }; + search.onchange = function(event) { + // For IE 8 + searchBox.onSearch(event); + }; + search.onkeydown = function(event) { + searchBox.onKeyDown(event); + }; + search.onkeyup = function(event) { + searchBox.onKeyUp(event); + }; + refreshSearch.onclick = function(event) { + search.select(); + }; + + // TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819 + td = document.createElement("td"); + td.appendChild(search); + tr.appendChild(td); + + var searchNext = document.createElement("button"); + searchNext.title = "涓嬩竴涓� (Enter)"; + searchNext.className = "jsoneditor-search-next"; + searchNext.onclick = function() { + searchBox.next(); + }; + td = document.createElement("td"); + td.appendChild(searchNext); + tr.appendChild(td); + + var searchPrevious = document.createElement("button"); + searchPrevious.title = "涓婁竴涓� (Shift+Enter)"; + searchPrevious.className = "jsoneditor-search-previous"; + searchPrevious.onclick = function() { + searchBox.previous(); + }; + td = document.createElement("td"); + td.appendChild(searchPrevious); + tr.appendChild(td); +}; + +/** + * Go to the next search result + */ +JSONEditor.SearchBox.prototype.next = function() { + if (this.results != undefined) { + var index = this.resultIndex != undefined ? this.resultIndex + 1 : 0; + if (index > this.results.length - 1) { + index = 0; + } + this.setActiveResult(index); + } +}; + +/** + * Go to the prevous search result + */ +JSONEditor.SearchBox.prototype.previous = function() { + if (this.results != undefined) { + var max = this.results.length - 1; + var index = this.resultIndex != undefined ? this.resultIndex - 1 : max; + if (index < 0) { + index = max; + } + this.setActiveResult(index); + } +}; + +/** + * Set new value for the current active result + * @param {Number} index + */ +JSONEditor.SearchBox.prototype.setActiveResult = function(index) { + // de-activate current active result + if (this.activeResult) { + var prevNode = this.activeResult.node; + var prevElem = this.activeResult.elem; + if (prevElem == "field") { + delete prevNode.searchFieldActive; + } else { + delete prevNode.searchValueActive; + } + prevNode.updateDom(); + } + + if (!this.results || !this.results[index]) { + // out of range, set to undefined + this.resultIndex = undefined; + this.activeResult = undefined; + return; + } + + this.resultIndex = index; + + // set new node active + var node = this.results[this.resultIndex].node; + var elem = this.results[this.resultIndex].elem; + if (elem == "field") { + node.searchFieldActive = true; + } else { + node.searchValueActive = true; + } + this.activeResult = this.results[this.resultIndex]; + node.updateDom(); + + node.scrollTo(); +}; + +/** + * Set the focus to the currently active result. If there is no currently + * active result, the next search result will get focus + */ +JSONEditor.SearchBox.prototype.focusActiveResult = function() { + if (!this.activeResult) { + this.next(); + } + + if (this.activeResult) { + this.activeResult.node.focus(this.activeResult.elem); + } +}; + +/** + * Cancel any running onDelayedSearch. + */ +JSONEditor.SearchBox.prototype.clearDelay = function() { + if (this.timeout != undefined) { + clearTimeout(this.timeout); + delete this.timeout; + } +}; + +/** + * Start a timer to execute a search after a short delay. + * Used for reducing the number of searches while typing. + * @param {Event} event + */ +JSONEditor.SearchBox.prototype.onDelayedSearch = function(event) { + // execute the search after a short delay (reduces the number of + // search actions while typing in the search text box) + this.clearDelay(); + var searchBox = this; + this.timeout = setTimeout(function(event) { + searchBox.onSearch(event); + }, this.delay); +}; + +/** + * Handle onSearch event + * @param {Event} event + * @param {boolean} [forceSearch] If true, search will be executed again even + * when the search text is not changed. + * Default is false. + */ +JSONEditor.SearchBox.prototype.onSearch = function(event, forceSearch) { + this.clearDelay(); + + var value = this.dom.search.value; + var text = value.length > 0 ? value : undefined; + if (text != this.lastText || forceSearch) { + // only search again when changed + this.lastText = text; + this.results = this.editor.search(text); + this.setActiveResult(undefined); + + // display search results + if (text != undefined) { + var resultCount = this.results.length; + switch (resultCount) { + case 0: + this.dom.results.innerHTML = "鍖哄潡/鍊兼湭鎵惧埌"; + break; + default: + this.dom.results.innerHTML = + "鎵惧埌 " + resultCount + " 涓粨鏋�"; + break; + } + } else { + this.dom.results.innerHTML = ""; + } + } +}; + +/** + * Handle onKeyDown event in the input box + * @param {Event} event + */ +JSONEditor.SearchBox.prototype.onKeyDown = function(event) { + event = event || window.event; + var keynum = event.which || event.keyCode; + if (keynum == 27) { + // ESC + this.dom.search.value = ""; // clear search + this.onSearch(event); + JSONEditor.Events.preventDefault(event); + JSONEditor.Events.stopPropagation(event); + } else if (keynum == 13) { + // Enter + if (event.ctrlKey) { + // force to search again + this.onSearch(event, true); + } else if (event.shiftKey) { + // move to the previous search result + this.previous(); + } else { + // move to the next search result + this.next(); + } + JSONEditor.Events.preventDefault(event); + JSONEditor.Events.stopPropagation(event); + } +}; + +/** + * Handle onKeyUp event in the input box + * @param {Event} event + */ +JSONEditor.SearchBox.prototype.onKeyUp = function(event) { + event = event || window.event; + var keynum = event.which || event.keyCode; + if (keynum != 27 && keynum != 13) { + // !ESC and !Enter + this.onDelayedSearch(event); // For IE 8 + } +}; + +// create namespace for event methods +JSONEditor.Events = {}; + +/** + * Add and event listener. Works for all browsers + * @param {Element} element An html element + * @param {string} action The action, for example "click", + * without the prefix "on" + * @param {function} listener The callback function to be executed + * @param {boolean} useCapture + * @return {function} the created event listener + */ +JSONEditor.Events.addEventListener = function( + element, + action, + listener, + useCapture +) { + if (element.addEventListener) { + if (useCapture === undefined) useCapture = false; + + if ( + action === "mousewheel" && + navigator.userAgent.indexOf("Firefox") >= 0 + ) { + action = "DOMMouseScroll"; // For Firefox + } + + element.addEventListener(action, listener, useCapture); + return listener; + } else { + // IE browsers + var f = function() { + return listener.call(element, window.event); + }; + element.attachEvent("on" + action, f); + return f; + } +}; + +/** + * Remove an event listener from an element + * @param {Element} element An html dom element + * @param {string} action The name of the event, for example "mousedown" + * @param {function} listener The listener function + * @param {boolean} useCapture + */ +JSONEditor.Events.removeEventListener = function( + element, + action, + listener, + useCapture +) { + if (element.removeEventListener) { + // non-IE browsers + if (useCapture === undefined) useCapture = false; + + if ( + action === "mousewheel" && + navigator.userAgent.indexOf("Firefox") >= 0 + ) { + action = "DOMMouseScroll"; // For Firefox + } + + element.removeEventListener(action, listener, useCapture); + } else { + // IE browsers + element.detachEvent("on" + action, listener); + } +}; + +/** + * Stop event propagation + * @param {Event} event + */ +JSONEditor.Events.stopPropagation = function(event) { + if (!event) event = window.event; + + if (event.stopPropagation) { + event.stopPropagation(); // non-IE browsers + } else { + event.cancelBubble = true; // IE browsers + } +}; + +/** + * Cancels the event if it is cancelable, without stopping further propagation of the event. + * @param {Event} event + */ +JSONEditor.Events.preventDefault = function(event) { + if (!event) event = window.event; + + if (event.preventDefault) { + event.preventDefault(); // non-IE browsers + } else { + event.returnValue = false; // IE browsers + } +}; + +/** + * Retrieve the absolute left value of a DOM element + * @param {Element} elem A dom element, for example a div + * @return {Number} left The absolute left position of this element + * in the browser page. + */ +JSONEditor.getAbsoluteLeft = function(elem) { + var left = 0; + var body = document.body; + while (elem != null && elem != body) { + left += elem.offsetLeft; + left -= elem.scrollLeft; + elem = elem.offsetParent; + } + return left; +}; + +/** + * Retrieve the absolute top value of a DOM element + * @param {Element} elem A dom element, for example a div + * @return {Number} top The absolute top position of this element + * in the browser page. + */ +JSONEditor.getAbsoluteTop = function(elem) { + var top = 0; + var body = document.body; + while (elem != null && elem != body) { + top += elem.offsetTop; + top -= elem.scrollTop; + elem = elem.offsetParent; + } + return top; +}; + +/** + * add a className to the given elements style + * @param {Element} elem + * @param {String} className + */ +JSONEditor.addClassName = function(elem, className) { + var classes = elem.className.split(" "); + if (classes.indexOf(className) == -1) { + classes.push(className); // add the class to the array + elem.className = classes.join(" "); + } +}; + +/** + * add a className to the given elements style + * @param {Element} elem + * @param {String} className + */ +JSONEditor.removeClassName = function(elem, className) { + var classes = elem.className.split(" "); + var index = classes.indexOf(className); + if (index != -1) { + classes.splice(index, 1); // remove the class from the array + elem.className = classes.join(" "); + } +}; + +/** + * Strip the formatting from the contents of a div + * the formatting from the div itself is not stripped, only from its childs. + * @param {Element} divElement + */ +JSONEditor.stripFormatting = function(divElement) { + var childs = divElement.childNodes; + for (var i = 0, iMax = childs.length; i < iMax; i++) { + var child = childs[i]; + + // remove the style + if (child.style) { + // TODO: test if child.attributes does contain style + child.removeAttribute("style"); + } + + // remove all attributes + var attributes = child.attributes; + if (attributes) { + for (var j = attributes.length - 1; j >= 0; j--) { + var attribute = attributes[j]; + if (attribute.specified == true) { + child.removeAttribute(attribute.name); + } + } + } + + // recursively strip childs + JSONEditor.stripFormatting(child); + } +}; + +/** + * Set focus to the end of an editable div + * code from Nico Burns + * http://stackoverflow.com/users/140293/nico-burns + * http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity + * @param {Element} contentEditableElement + */ +JSONEditor.setEndOfContentEditable = function(contentEditableElement) { + var range, selection; + if (document.createRange) { + //Firefox, Chrome, Opera, Safari, IE 9+ + range = document.createRange(); //Create a range (a range is a like the selection but invisible) + range.selectNodeContents(contentEditableElement); //Select the entire contents of the element with the range + range.collapse(false); //collapse the range to the end point. false means collapse to end rather than the start + selection = window.getSelection(); //get the selection object (allows you to change selection) + selection.removeAllRanges(); //remove any selections already made + selection.addRange(range); //make the range you have just created the visible selection + } else if (document.selection) { + //IE 8 and lower + range = document.body.createTextRange(); //Create a range (a range is a like the selection but invisible) + range.moveToElementText(contentEditableElement); //Select the entire contents of the element with the range + range.collapse(false); //collapse the range to the end point. false means collapse to end rather than the start + range.select(); //Select the range (make it the visible selection + } +}; + +/** + * Get the inner text of an HTML element (for example a div element) + * @param {Element} element + * @param {Object} [buffer] + * @return {String} innerText + */ +JSONEditor.getInnerText = function(element, buffer) { + var first = buffer == undefined; + if (first) { + buffer = { + text: "", + flush: function() { + var text = this.text; + this.text = ""; + return text; + }, + set: function(text) { + this.text = text; + } + }; + } + + // text node + if (element.nodeValue) { + return buffer.flush() + element.nodeValue; + } + + // divs or other HTML elements + if (element.hasChildNodes()) { + var childNodes = element.childNodes; + var innerText = ""; + + for (var i = 0, iMax = childNodes.length; i < iMax; i++) { + var child = childNodes[i]; + + if (child.nodeName == "DIV" || child.nodeName == "P") { + var prevChild = childNodes[i - 1]; + var prevName = prevChild ? prevChild.nodeName : undefined; + if ( + prevName && + prevName != "DIV" && + prevName != "P" && + prevName != "BR" + ) { + innerText += "\n"; + buffer.flush(); + } + innerText += JSONEditor.getInnerText(child, buffer); + buffer.set("\n"); + } else if (child.nodeName == "BR") { + innerText += buffer.flush(); + buffer.set("\n"); + } else { + innerText += JSONEditor.getInnerText(child, buffer); + } + } + + return innerText; + } else { + if ( + element.nodeName == "P" && + JSONEditor.getInternetExplorerVersion() != -1 + ) { + // On Internet Explorer, a

                                                              with hasChildNodes()==false is + // rendered with a new line. Note that a

                                                              with + // hasChildNodes()==true is rendered without a new line + // Other browsers always ensure there is a
                                                              inside the

                                                              , + // and if not, the

                                                              does not render a new line + return buffer.flush(); + } + } + + // br or unknown + return ""; +}; + +/** + * Returns the version of Internet Explorer or a -1 + * (indicating the use of another browser). + * Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx + * @return {Number} Internet Explorer version, or -1 in case of an other browser + */ +JSONEditor._ieVersion = undefined; +JSONEditor.getInternetExplorerVersion = function() { + if (JSONEditor._ieVersion == undefined) { + var rv = -1; // Return value assumes failure. + if (navigator.appName == "Microsoft Internet Explorer") { + var ua = navigator.userAgent; + var re = new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})"); + if (re.exec(ua) != null) { + rv = parseFloat(RegExp.$1); + } + } + + JSONEditor._ieVersion = rv; + } + + return JSONEditor._ieVersion; +}; + +JSONEditor.ieVersion = JSONEditor.getInternetExplorerVersion(); + +/** + * Parse JSON using the parser built-in in the browser. + * On exception, the jsonString is validated and a detailed error is thrown. + * @param {String} jsonString + */ +JSONEditor.parse = function(jsonString) { + try { + return JSON.parse(jsonString); + } catch (err) { + // get a detailed error message using validate + var message = JSONEditor.validate(jsonString) || err; + throw new Error(message); + } +}; + +/** + * Validate a string containing a JSON object + * This method uses JSONLint to validate the String. If JSONLint is not + * available, the built-in JSON parser of the browser is used. + * @param {String} jsonString String with an (invalid) JSON object + * @return {String | undefined} Returns undefined when the string is valid JSON, + * returns a string with an error message when + * the data is invalid + */ +JSONEditor.validate = function(jsonString) { + var message = undefined; + + try { + if (window.jsonlint) { + window.jsonlint.parse(jsonString); + } else { + JSON.parse(jsonString); + } + } catch (err) { + message = '

                                                              ' + err.toString() + "
                                                              "; + if (window.jsonlint) { + message += + '
                                                              鐢� ' + + "JSONLint" + + " 鎻愪緵楠岃瘉.
                                                              "; + } + } + + return message; +}; + +function jsonArea(ob) { + let inputEle = ob.el; + let insert = ob.insert; + let nth = ob.nth; + let change = ob.change; + let thisare = new Object(); + if (!inputEle) { + throw new Error("娌℃湁鎻愪緵鏁版嵁婧�."); + } + // if target to multi dom + if (nth) { + thisare.data = document.querySelectorAll(inputEle)[nth - 1]; + } else { + let all = document.querySelectorAll(inputEle); + for (var i = 0; i < all.length; i++) { + jsonArea({ el: inputEle, insert: insert, nth: i + 1, change: change }); + } + // thisare.data = document.querySelector(inputEle); + return; + } + // create container + thisare.container = document.createElement("div"); + thisare.container.style.width = "100%"; + thisare.container.style.height = "auto"; + thisare.data.parentElement.insertBefore(thisare.container, thisare.data); + // check wether is a json + thisare.isJson = function(str) { + if (!isNaN(str)) return false; + if (str == "") return false; + if (str == '""') return false; + if (typeof str == "string") { + try { + JSON.parse(str); + return true; + } catch (e) { + // console.log(e); + return false; + } + } + console.log("涓嶆槸涓€涓猻tringify"); + }; + // json data + thisare.jsonval = "{}"; + // callback when change + thisare.syn = function() {}; + // whether is textarea or input + if (thisare.data.tagName == "TEXTAREA") { + thisare.jsonval = thisare.data.innerHTML; + thisare.syn = function() { + thisare.data.innerHTML = JSON.stringify(thisare.jsonEditor.get()); + change(thisare.jsonEditor.get()); + }; + } else if (thisare.data.tagName == "INPUT") { + thisare.jsonval = thisare.data.value; + thisare.syn = function() { + thisare.data.value = JSON.stringify(thisare.jsonEditor.get()); + change(thisare.jsonEditor.get()); + }; + } + // if not json, and not insert ,then json editer + thisare.hashJson = thisare.isJson(thisare.jsonval); + if (!thisare.hashJson && !insert) return; + thisare.data.style.display = "none"; + // create jsoneditor for father + thisare.jsonEditor = new JSONEditor(thisare.container, { + change: function() { + thisare.lastChanged = thisare.jsonEditor; + thisare.syn(); + } + }); + if (thisare.hashJson) { + thisare.jsonEditor.set(JSON.parse(thisare.jsonval)); + } + console.log("in jsonArea"); + return thisare; +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/layui/css/layui.css b/demo/webman/backend/plugin/admin/public/component/layui/css/layui.css new file mode 100644 index 0000000000000000000000000000000000000000..8ff67ccafcbe9db108fc60e832ad9f6379990caa --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/layui/css/layui.css @@ -0,0 +1 @@ +blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:active,a:hover{outline:0}img{display:inline-block;border:none;vertical-align:middle}li{list-style:none}table{border-collapse:collapse;border-spacing:0}h1,h2,h3,h4{font-weight:700}h5,h6{font-weight:500;font-size:100%}button,input,select,textarea{font-size:100%}button,input,optgroup,option,select,textarea{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;outline:0}pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}body{line-height:1.6;color:#333;color:rgba(0,0,0,.85);font:14px Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif}hr{height:0;line-height:0;margin:10px 0;padding:0;border:none!important;border-bottom:1px solid #eee!important;clear:both;overflow:hidden;background:0 0}a{color:#333;text-decoration:none}a:hover{color:#777}a cite{font-style:normal;*cursor:pointer}.layui-border-box,.layui-border-box *{box-sizing:border-box}.layui-box,.layui-box *{box-sizing:content-box}.layui-clear{clear:both;*zoom:1}.layui-clear:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-clear-space{word-spacing:-5px}.layui-inline{position:relative;display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.layui-edge{position:relative;display:inline-block;vertical-align:middle;width:0;height:0;border-width:6px;border-style:dashed;border-color:transparent;overflow:hidden}.layui-edge-top{top:-4px;border-bottom-color:#999;border-bottom-style:solid}.layui-edge-right{border-left-color:#999;border-left-style:solid}.layui-edge-bottom{top:2px;border-top-color:#999;border-top-style:solid}.layui-edge-left{border-right-color:#999;border-right-style:solid}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-disabled,.layui-icon,.layui-unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-disabled,.layui-disabled:hover{color:#d2d2d2!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-show-v{visibility:visible!important}.layui-hide-v{visibility:hidden!important}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=282);src:url(../font/iconfont.eot?v=282#iefix) format('embedded-opentype'),url(../font/iconfont.woff2?v=282) format('woff2'),url(../font/iconfont.woff?v=282) format('woff'),url(../font/iconfont.ttf?v=282) format('truetype'),url(../font/iconfont.svg?v=282#layui-icon) format('svg')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-icon-leaf:before{content:"\e701"}.layui-icon-folder:before{content:"\eabe"}.layui-icon-folder-open:before{content:"\eac1"}.layui-icon-gitee:before{content:"\e69b"}.layui-icon-github:before{content:"\e6a7"}.layui-icon-disabled:before{content:"\e6cc"}.layui-icon-moon:before{content:"\e6c2"}.layui-icon-error:before{content:"\e693"}.layui-icon-success:before{content:"\e697"}.layui-icon-question:before{content:"\e699"}.layui-icon-lock:before{content:"\e69a"}.layui-icon-eye:before{content:"\e695"}.layui-icon-eye-invisible:before{content:"\e696"}.layui-icon-backspace:before{content:"\e694"}.layui-icon-tips-fill:before{content:"\eb2e"}.layui-icon-test:before{content:"\e692"}.layui-icon-clear:before{content:"\e788"}.layui-icon-heart-fill:before{content:"\e68f"}.layui-icon-light:before{content:"\e748"}.layui-icon-music:before{content:"\e690"}.layui-icon-time:before{content:"\e68d"}.layui-icon-ie:before{content:"\e7bb"}.layui-icon-firefox:before{content:"\e686"}.layui-icon-at:before{content:"\e687"}.layui-icon-bluetooth:before{content:"\e689"}.layui-icon-chrome:before{content:"\e68a"}.layui-icon-edge:before{content:"\e68b"}.layui-icon-heart:before{content:"\e68c"}.layui-icon-key:before{content:"\e683"}.layui-icon-android:before{content:"\e684"}.layui-icon-mike:before{content:"\e6dc"}.layui-icon-mute:before{content:"\e685"}.layui-icon-gift:before{content:"\e627"}.layui-icon-windows:before{content:"\e67f"}.layui-icon-ios:before{content:"\e680"}.layui-icon-logout:before{content:"\e682"}.layui-icon-wifi:before{content:"\e7e0"}.layui-icon-rss:before{content:"\e808"}.layui-icon-email:before{content:"\e618"}.layui-icon-reduce-circle:before{content:"\e616"}.layui-icon-transfer:before{content:"\e691"}.layui-icon-service:before{content:"\e626"}.layui-icon-addition:before{content:"\e624"}.layui-icon-subtraction:before{content:"\e67e"}.layui-icon-slider:before{content:"\e714"}.layui-icon-print:before{content:"\e66d"}.layui-icon-export:before{content:"\e67d"}.layui-icon-cols:before{content:"\e610"}.layui-icon-screen-full:before{content:"\e622"}.layui-icon-screen-restore:before{content:"\e758"}.layui-icon-rate-half:before{content:"\e6c9"}.layui-icon-rate-solid:before{content:"\e67a"}.layui-icon-rate:before{content:"\e67b"}.layui-icon-cellphone:before{content:"\e678"}.layui-icon-vercode:before{content:"\e679"}.layui-icon-login-weibo:before{content:"\e675"}.layui-icon-login-qq:before{content:"\e676"}.layui-icon-login-wechat:before{content:"\e677"}.layui-icon-username:before{content:"\e66f"}.layui-icon-password:before{content:"\e673"}.layui-icon-refresh-3:before{content:"\e9aa"}.layui-icon-auz:before{content:"\e672"}.layui-icon-shrink-right:before{content:"\e668"}.layui-icon-spread-left:before{content:"\e66b"}.layui-icon-snowflake:before{content:"\e6b1"}.layui-icon-tips:before{content:"\e702"}.layui-icon-note:before{content:"\e66e"}.layui-icon-senior:before{content:"\e674"}.layui-icon-refresh-1:before{content:"\e666"}.layui-icon-refresh:before{content:"\e669"}.layui-icon-flag:before{content:"\e66c"}.layui-icon-theme:before{content:"\e66a"}.layui-icon-notice:before{content:"\e667"}.layui-icon-console:before{content:"\e665"}.layui-icon-website:before{content:"\e7ae"}.layui-icon-face-surprised:before{content:"\e664"}.layui-icon-set:before{content:"\e716"}.layui-icon-template:before{content:"\e663"}.layui-icon-app:before{content:"\e653"}.layui-icon-template-1:before{content:"\e656"}.layui-icon-home:before{content:"\e68e"}.layui-icon-female:before{content:"\e661"}.layui-icon-male:before{content:"\e662"}.layui-icon-tread:before{content:"\e6c5"}.layui-icon-praise:before{content:"\e6c6"}.layui-icon-rmb:before{content:"\e65e"}.layui-icon-more:before{content:"\e65f"}.layui-icon-camera:before{content:"\e660"}.layui-icon-cart-simple:before{content:"\e698"}.layui-icon-face-cry:before{content:"\e69c"}.layui-icon-face-smile:before{content:"\e6af"}.layui-icon-survey:before{content:"\e6b2"}.layui-icon-read:before{content:"\e705"}.layui-icon-location:before{content:"\e715"}.layui-icon-dollar:before{content:"\e659"}.layui-icon-diamond:before{content:"\e735"}.layui-icon-return:before{content:"\e65c"}.layui-icon-camera-fill:before{content:"\e65d"}.layui-icon-fire:before{content:"\e756"}.layui-icon-more-vertical:before{content:"\e671"}.layui-icon-cart:before{content:"\e657"}.layui-icon-star-fill:before{content:"\e658"}.layui-icon-prev:before{content:"\e65a"}.layui-icon-next:before{content:"\e65b"}.layui-icon-upload:before{content:"\e67c"}.layui-icon-upload-drag:before{content:"\e681"}.layui-icon-user:before{content:"\e770"}.layui-icon-file-b:before{content:"\e655"}.layui-icon-component:before{content:"\e857"}.layui-icon-find-fill:before{content:"\e670"}.layui-icon-loading:before{content:"\e63d"}.layui-icon-loading-1:before{content:"\e63e"}.layui-icon-add-1:before{content:"\e654"}.layui-icon-pause:before{content:"\e651"}.layui-icon-play:before{content:"\e652"}.layui-icon-video:before{content:"\e6ed"}.layui-icon-headset:before{content:"\e6fc"}.layui-icon-voice:before{content:"\e688"}.layui-icon-speaker:before{content:"\e645"}.layui-icon-fonts-del:before{content:"\e64f"}.layui-icon-fonts-html:before{content:"\e64b"}.layui-icon-fonts-code:before{content:"\e64e"}.layui-icon-fonts-strong:before{content:"\e62b"}.layui-icon-unlink:before{content:"\e64d"}.layui-icon-picture:before{content:"\e64a"}.layui-icon-link:before{content:"\e64c"}.layui-icon-face-smile-b:before{content:"\e650"}.layui-icon-align-center:before{content:"\e647"}.layui-icon-align-right:before{content:"\e648"}.layui-icon-align-left:before{content:"\e649"}.layui-icon-fonts-u:before{content:"\e646"}.layui-icon-fonts-i:before{content:"\e644"}.layui-icon-tabs:before{content:"\e62a"}.layui-icon-circle:before{content:"\e63f"}.layui-icon-radio:before{content:"\e643"}.layui-icon-share:before{content:"\e641"}.layui-icon-edit:before{content:"\e642"}.layui-icon-delete:before{content:"\e640"}.layui-icon-engine:before{content:"\e628"}.layui-icon-chart-screen:before{content:"\e629"}.layui-icon-chart:before{content:"\e62c"}.layui-icon-table:before{content:"\e62d"}.layui-icon-tree:before{content:"\e62e"}.layui-icon-upload-circle:before{content:"\e62f"}.layui-icon-templeate-1:before{content:"\e630"}.layui-icon-util:before{content:"\e631"}.layui-icon-layouts:before{content:"\e632"}.layui-icon-prev-circle:before{content:"\e633"}.layui-icon-carousel:before{content:"\e634"}.layui-icon-code-circle:before{content:"\e635"}.layui-icon-water:before{content:"\e636"}.layui-icon-date:before{content:"\e637"}.layui-icon-layer:before{content:"\e638"}.layui-icon-fonts-clear:before{content:"\e639"}.layui-icon-dialogue:before{content:"\e63a"}.layui-icon-cellphone-fine:before{content:"\e63b"}.layui-icon-form:before{content:"\e63c"}.layui-icon-file:before{content:"\e621"}.layui-icon-triangle-r:before{content:"\e623"}.layui-icon-triangle-d:before{content:"\e625"}.layui-icon-set-sm:before{content:"\e620"}.layui-icon-add-circle:before{content:"\e61f"}.layui-icon-layim-download:before{content:"\e61e"}.layui-icon-layim-uploadfile:before{content:"\e61d"}.layui-icon-404:before{content:"\e61c"}.layui-icon-about:before{content:"\e60b"}.layui-icon-layim-theme:before{content:"\e61b"}.layui-icon-down:before{content:"\e61a"}.layui-icon-up:before{content:"\e619"}.layui-icon-circle-dot:before{content:"\e617"}.layui-icon-set-fill:before{content:"\e614"}.layui-icon-search:before{content:"\e615"}.layui-icon-friends:before{content:"\e612"}.layui-icon-group:before{content:"\e613"}.layui-icon-reply-fill:before{content:"\e611"}.layui-icon-menu-fill:before{content:"\e60f"}.layui-icon-face-smile-fine:before{content:"\e60c"}.layui-icon-picture-fine:before{content:"\e60d"}.layui-icon-log:before{content:"\e60e"}.layui-icon-list:before{content:"\e60a"}.layui-icon-release:before{content:"\e609"}.layui-icon-add-circle-fine:before{content:"\e608"}.layui-icon-ok:before{content:"\e605"}.layui-icon-help:before{content:"\e607"}.layui-icon-chat:before{content:"\e606"}.layui-icon-top:before{content:"\e604"}.layui-icon-right:before{content:"\e602"}.layui-icon-left:before{content:"\e603"}.layui-icon-star:before{content:"\e600"}.layui-icon-download-circle:before{content:"\e601"}.layui-icon-close:before{content:"\1006"}.layui-icon-close-fill:before{content:"\1007"}.layui-icon-ok-circle:before{content:"\1005"}.layui-main{position:relative;width:1160px;margin:0 auto}.layui-header{position:relative;z-index:1000;height:60px}.layui-header a:hover{transition:all .5s;-webkit-transition:all .5s}.layui-side{position:fixed;left:0;top:0;bottom:0;z-index:999;width:200px;overflow-x:hidden}.layui-side-scroll{position:relative;width:220px;height:100%;overflow-x:hidden}.layui-body{position:relative;left:200px;right:0;top:0;bottom:0;z-index:900;width:auto;box-sizing:border-box}.layui-layout-body{overflow-x:hidden}.layui-layout-admin .layui-header{position:fixed;top:0;left:0;right:0;background-color:#23292e}.layui-layout-admin .layui-side{top:60px;width:200px;overflow-x:hidden}.layui-layout-admin .layui-body{position:absolute;top:60px;padding-bottom:44px}.layui-layout-admin .layui-main{width:auto;margin:0 15px}.layui-layout-admin .layui-footer{position:fixed;left:200px;right:0;bottom:0;z-index:990;height:44px;line-height:44px;padding:0 15px;box-shadow:-1px 0 4px rgb(0 0 0 / 12%);background-color:#fafafa}.layui-layout-admin .layui-logo{position:absolute;left:0;top:0;width:200px;height:100%;line-height:60px;text-align:center;color:#16baaa;font-size:16px;box-shadow:0 1px 2px 0 rgb(0 0 0 / 15%)}.layui-layout-admin .layui-header .layui-nav{background:0 0}.layui-layout-left{position:absolute!important;left:200px;top:0}.layui-layout-right{position:absolute!important;right:0;top:0}.layui-container{position:relative;margin:0 auto;box-sizing:border-box}.layui-fluid{position:relative;margin:0 auto;padding:0 15px}.layui-row:after,.layui-row:before{content:"";display:block;clear:both}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9,.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9,.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9,.layui-col-xl1,.layui-col-xl10,.layui-col-xl11,.layui-col-xl12,.layui-col-xl2,.layui-col-xl3,.layui-col-xl4,.layui-col-xl5,.layui-col-xl6,.layui-col-xl7,.layui-col-xl8,.layui-col-xl9,.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{position:relative;display:block;box-sizing:border-box}.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{float:left}.layui-col-xs1{width:8.33333333%}.layui-col-xs2{width:16.66666667%}.layui-col-xs3{width:25%}.layui-col-xs4{width:33.33333333%}.layui-col-xs5{width:41.66666667%}.layui-col-xs6{width:50%}.layui-col-xs7{width:58.33333333%}.layui-col-xs8{width:66.66666667%}.layui-col-xs9{width:75%}.layui-col-xs10{width:83.33333333%}.layui-col-xs11{width:91.66666667%}.layui-col-xs12{width:100%}.layui-col-xs-offset1{margin-left:8.33333333%}.layui-col-xs-offset2{margin-left:16.66666667%}.layui-col-xs-offset3{margin-left:25%}.layui-col-xs-offset4{margin-left:33.33333333%}.layui-col-xs-offset5{margin-left:41.66666667%}.layui-col-xs-offset6{margin-left:50%}.layui-col-xs-offset7{margin-left:58.33333333%}.layui-col-xs-offset8{margin-left:66.66666667%}.layui-col-xs-offset9{margin-left:75%}.layui-col-xs-offset10{margin-left:83.33333333%}.layui-col-xs-offset11{margin-left:91.66666667%}.layui-col-xs-offset12{margin-left:100%}@media screen and (max-width:767.98px){.layui-container{padding:0 15px}.layui-hide-xs{display:none!important}.layui-show-xs-block{display:block!important}.layui-show-xs-inline{display:inline!important}.layui-show-xs-inline-block{display:inline-block!important}}@media screen and (min-width:768px){.layui-container{width:720px}.layui-hide-sm{display:none!important}.layui-show-sm-block{display:block!important}.layui-show-sm-inline{display:inline!important}.layui-show-sm-inline-block{display:inline-block!important}.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9{float:left}.layui-col-sm1{width:8.33333333%}.layui-col-sm2{width:16.66666667%}.layui-col-sm3{width:25%}.layui-col-sm4{width:33.33333333%}.layui-col-sm5{width:41.66666667%}.layui-col-sm6{width:50%}.layui-col-sm7{width:58.33333333%}.layui-col-sm8{width:66.66666667%}.layui-col-sm9{width:75%}.layui-col-sm10{width:83.33333333%}.layui-col-sm11{width:91.66666667%}.layui-col-sm12{width:100%}.layui-col-sm-offset1{margin-left:8.33333333%}.layui-col-sm-offset2{margin-left:16.66666667%}.layui-col-sm-offset3{margin-left:25%}.layui-col-sm-offset4{margin-left:33.33333333%}.layui-col-sm-offset5{margin-left:41.66666667%}.layui-col-sm-offset6{margin-left:50%}.layui-col-sm-offset7{margin-left:58.33333333%}.layui-col-sm-offset8{margin-left:66.66666667%}.layui-col-sm-offset9{margin-left:75%}.layui-col-sm-offset10{margin-left:83.33333333%}.layui-col-sm-offset11{margin-left:91.66666667%}.layui-col-sm-offset12{margin-left:100%}}@media screen and (min-width:992px){.layui-container{width:960px}.layui-hide-md{display:none!important}.layui-show-md-block{display:block!important}.layui-show-md-inline{display:inline!important}.layui-show-md-inline-block{display:inline-block!important}.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9{float:left}.layui-col-md1{width:8.33333333%}.layui-col-md2{width:16.66666667%}.layui-col-md3{width:25%}.layui-col-md4{width:33.33333333%}.layui-col-md5{width:41.66666667%}.layui-col-md6{width:50%}.layui-col-md7{width:58.33333333%}.layui-col-md8{width:66.66666667%}.layui-col-md9{width:75%}.layui-col-md10{width:83.33333333%}.layui-col-md11{width:91.66666667%}.layui-col-md12{width:100%}.layui-col-md-offset1{margin-left:8.33333333%}.layui-col-md-offset2{margin-left:16.66666667%}.layui-col-md-offset3{margin-left:25%}.layui-col-md-offset4{margin-left:33.33333333%}.layui-col-md-offset5{margin-left:41.66666667%}.layui-col-md-offset6{margin-left:50%}.layui-col-md-offset7{margin-left:58.33333333%}.layui-col-md-offset8{margin-left:66.66666667%}.layui-col-md-offset9{margin-left:75%}.layui-col-md-offset10{margin-left:83.33333333%}.layui-col-md-offset11{margin-left:91.66666667%}.layui-col-md-offset12{margin-left:100%}}@media screen and (min-width:1200px){.layui-container{width:1150px}.layui-hide-lg{display:none!important}.layui-show-lg-block{display:block!important}.layui-show-lg-inline{display:inline!important}.layui-show-lg-inline-block{display:inline-block!important}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9{float:left}.layui-col-lg1{width:8.33333333%}.layui-col-lg2{width:16.66666667%}.layui-col-lg3{width:25%}.layui-col-lg4{width:33.33333333%}.layui-col-lg5{width:41.66666667%}.layui-col-lg6{width:50%}.layui-col-lg7{width:58.33333333%}.layui-col-lg8{width:66.66666667%}.layui-col-lg9{width:75%}.layui-col-lg10{width:83.33333333%}.layui-col-lg11{width:91.66666667%}.layui-col-lg12{width:100%}.layui-col-lg-offset1{margin-left:8.33333333%}.layui-col-lg-offset2{margin-left:16.66666667%}.layui-col-lg-offset3{margin-left:25%}.layui-col-lg-offset4{margin-left:33.33333333%}.layui-col-lg-offset5{margin-left:41.66666667%}.layui-col-lg-offset6{margin-left:50%}.layui-col-lg-offset7{margin-left:58.33333333%}.layui-col-lg-offset8{margin-left:66.66666667%}.layui-col-lg-offset9{margin-left:75%}.layui-col-lg-offset10{margin-left:83.33333333%}.layui-col-lg-offset11{margin-left:91.66666667%}.layui-col-lg-offset12{margin-left:100%}}@media screen and (min-width:1400px){.layui-container{width:1330px}.layui-hide-xl{display:none!important}.layui-show-xl-block{display:block!important}.layui-show-xl-inline{display:inline!important}.layui-show-xl-inline-block{display:inline-block!important}.layui-col-xl1,.layui-col-xl10,.layui-col-xl11,.layui-col-xl12,.layui-col-xl2,.layui-col-xl3,.layui-col-xl4,.layui-col-xl5,.layui-col-xl6,.layui-col-xl7,.layui-col-xl8,.layui-col-xl9{float:left}.layui-col-xl1{width:8.33333333%}.layui-col-xl2{width:16.66666667%}.layui-col-xl3{width:25%}.layui-col-xl4{width:33.33333333%}.layui-col-xl5{width:41.66666667%}.layui-col-xl6{width:50%}.layui-col-xl7{width:58.33333333%}.layui-col-xl8{width:66.66666667%}.layui-col-xl9{width:75%}.layui-col-xl10{width:83.33333333%}.layui-col-xl11{width:91.66666667%}.layui-col-xl12{width:100%}.layui-col-xl-offset1{margin-left:8.33333333%}.layui-col-xl-offset2{margin-left:16.66666667%}.layui-col-xl-offset3{margin-left:25%}.layui-col-xl-offset4{margin-left:33.33333333%}.layui-col-xl-offset5{margin-left:41.66666667%}.layui-col-xl-offset6{margin-left:50%}.layui-col-xl-offset7{margin-left:58.33333333%}.layui-col-xl-offset8{margin-left:66.66666667%}.layui-col-xl-offset9{margin-left:75%}.layui-col-xl-offset10{margin-left:83.33333333%}.layui-col-xl-offset11{margin-left:91.66666667%}.layui-col-xl-offset12{margin-left:100%}}.layui-col-space1{margin:-.5px}.layui-col-space1>*{padding:.5px}.layui-col-space2{margin:-1px}.layui-col-space2>*{padding:1px}.layui-col-space4{margin:-2px}.layui-col-space4>*{padding:2px}.layui-col-space5{margin:-2.5px}.layui-col-space5>*{padding:2.5px}.layui-col-space6{margin:-3px}.layui-col-space6>*{padding:3px}.layui-col-space8{margin:-4px}.layui-col-space8>*{padding:4px}.layui-col-space10{margin:-5px}.layui-col-space10>*{padding:5px}.layui-col-space12{margin:-6px}.layui-col-space12>*{padding:6px}.layui-col-space14{margin:-7px}.layui-col-space14>*{padding:7px}.layui-col-space15{margin:-7.5px}.layui-col-space15>*{padding:7.5px}.layui-col-space16{margin:-8px}.layui-col-space16>*{padding:8px}.layui-col-space18{margin:-9px}.layui-col-space18>*{padding:9px}.layui-col-space20{margin:-10px}.layui-col-space20>*{padding:10px}.layui-col-space22{margin:-11px}.layui-col-space22>*{padding:11px}.layui-col-space24{margin:-12px}.layui-col-space24>*{padding:12px}.layui-col-space25{margin:-12.5px}.layui-col-space25>*{padding:12.5px}.layui-col-space26{margin:-13px}.layui-col-space26>*{padding:13px}.layui-col-space28{margin:-14px}.layui-col-space28>*{padding:14px}.layui-col-space30{margin:-15px}.layui-col-space30>*{padding:15px}.layui-col-space32{margin:-16px}.layui-col-space32>*{padding:16px}.layui-btn,.layui-input,.layui-select,.layui-textarea,.layui-upload-button{outline:0;-webkit-appearance:none;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-elem-quote{margin-bottom:10px;padding:15px;line-height:1.8;border-left:5px solid #16b777;border-radius:0 2px 2px 0;background-color:#fafafa}.layui-quote-nm{border-style:solid;border-width:1px;border-left-width:5px;background:0 0}.layui-elem-field{margin-bottom:10px;padding:0;border-width:1px;border-style:solid}.layui-elem-field legend{margin-left:20px;padding:0 10px;font-size:20px}.layui-field-title{margin:16px 0;border-width:0;border-top-width:1px}.layui-field-box{padding:15px}.layui-field-title .layui-field-box{padding:10px 0}.layui-progress{position:relative;height:6px;border-radius:20px;background-color:#eee}.layui-progress-bar{position:absolute;left:0;top:0;width:0;max-width:100%;height:6px;border-radius:20px;text-align:right;background-color:#16b777;transition:all .3s;-webkit-transition:all .3s}.layui-progress-big,.layui-progress-big .layui-progress-bar{height:18px;line-height:18px}.layui-progress-text{position:relative;top:-20px;line-height:18px;font-size:12px;color:#5f5f5f}.layui-progress-big .layui-progress-text{position:static;padding:0 10px;color:#fff}.layui-collapse{border-width:1px;border-style:solid;border-radius:2px}.layui-colla-content,.layui-colla-item{border-top-width:1px;border-top-style:solid}.layui-colla-item:first-child{border-top:none}.layui-colla-title{position:relative;height:42px;line-height:42px;padding:0 15px 0 35px;color:#333;background-color:#fafafa;cursor:pointer;font-size:14px;overflow:hidden}.layui-colla-content{display:none;padding:10px 15px;line-height:1.6;color:#5f5f5f}.layui-colla-icon{position:absolute;left:15px;top:0;font-size:14px}.layui-card{margin-bottom:15px;border-radius:2px;background-color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.layui-card:last-child{margin-bottom:0}.layui-card-header{position:relative;height:42px;line-height:42px;padding:0 15px;border-bottom:1px solid #f8f8f8;color:#333;border-radius:2px 2px 0 0;font-size:14px}.layui-card-body{position:relative;padding:10px 15px;line-height:24px}.layui-card-body[pad15]{padding:15px}.layui-card-body[pad20]{padding:20px}.layui-card-body .layui-table{margin:5px 0}.layui-card .layui-tab{margin:0}.layui-panel{position:relative;border-width:1px;border-style:solid;border-radius:2px;box-shadow:1px 1px 4px rgb(0 0 0 / 8%);background-color:#fff;color:#5f5f5f}.layui-panel-window{position:relative;padding:15px;border-radius:0;border-top:5px solid #eee;background-color:#fff}.layui-auxiliar-moving{position:fixed;left:0;right:0;top:0;bottom:0;width:100%;height:100%;background:0 0;z-index:9999999999}.layui-scrollbar-hide{overflow:hidden!important}.layui-bg-red{background-color:#ff5722!important;color:#fff!important}.layui-bg-orange{background-color:#ffb800!important;color:#fff!important}.layui-bg-green{background-color:#16baaa!important;color:#fff!important}.layui-bg-cyan{background-color:#2f4056!important;color:#fff!important}.layui-bg-blue{background-color:#1e9fff!important;color:#fff!important}.layui-bg-purple{background-color:#a233c6!important;color:#fff!important}.layui-bg-black{background-color:#2f363c!important;color:#fff!important}.layui-bg-gray{background-color:#fafafa!important;color:#5f5f5f!important}.layui-badge-rim,.layui-border,.layui-colla-content,.layui-colla-item,.layui-collapse,.layui-elem-field,.layui-form-pane .layui-form-item[pane],.layui-form-pane .layui-form-label,.layui-input,.layui-input-split,.layui-panel,.layui-quote-nm,.layui-select,.layui-tab-bar,.layui-tab-card,.layui-tab-title,.layui-tab-title .layui-this:after,.layui-textarea{border-color:#eee}.layui-border{border-width:1px;border-style:solid;color:#5f5f5f!important}.layui-border-red{border-width:1px;border-style:solid;border-color:#ff5722!important;color:#ff5722!important}.layui-border-orange{border-width:1px;border-style:solid;border-color:#ffb800!important;color:#ffb800!important}.layui-border-green{border-width:1px;border-style:solid;border-color:#16baaa!important;color:#16baaa!important}.layui-border-cyan{border-width:1px;border-style:solid;border-color:#2f4056!important;color:#2f4056!important}.layui-border-blue{border-width:1px;border-style:solid;border-color:#1e9fff!important;color:#1e9fff!important}.layui-border-purple{border-width:1px;border-style:solid;border-color:#a233c6!important;color:#a233c6!important}.layui-border-black{border-width:1px;border-style:solid;border-color:#2f363c!important;color:#2f363c!important}.layui-timeline-item:before{background-color:#eee}.layui-text{line-height:1.8;font-size:14px}.layui-text h1,.layui-text h2,.layui-text h3,.layui-text h4,.layui-text h5,.layui-text h6{color:#3a3a3a}.layui-text h1{font-size:32px}.layui-text h2{font-size:24px}.layui-text h3{font-size:18px}.layui-text h4{font-size:16px}.layui-text h5{font-size:14px}.layui-text h6{font-size:13px}.layui-text ol,.layui-text ul{padding-left:15px}.layui-text ul li{margin-top:5px;list-style-type:disc}.layui-text ol li{margin-top:5px;list-style-type:decimal}.layui-text-em,.layui-word-aux{color:#999!important;padding-left:5px!important;padding-right:5px!important}.layui-text p{margin:15px 0}.layui-text p:first-child{margin-top:0}.layui-text p:last-child{margin-bottom:0}.layui-text a:not(.layui-btn){color:#01aaed}.layui-text a:not(.layui-btn):hover{text-decoration:underline}.layui-text blockquote:not(.layui-elem-quote){padding:5px 15px;border-left:5px solid #eee}.layui-text pre>code:not(.layui-code){padding:15px;font-family:Courier New,Lucida Console,Consolas;background-color:#fafafa}.layui-font-12{font-size:12px!important}.layui-font-13{font-size:13px!important}.layui-font-14{font-size:14px!important}.layui-font-16{font-size:16px!important}.layui-font-18{font-size:18px!important}.layui-font-20{font-size:20px!important}.layui-font-22{font-size:22px!important}.layui-font-24{font-size:24px!important}.layui-font-26{font-size:26px!important}.layui-font-28{font-size:28px!important}.layui-font-30{font-size:30px!important}.layui-font-32{font-size:32px!important}.layui-font-red{color:#ff5722!important}.layui-font-orange{color:#ffb800!important}.layui-font-green{color:#16baaa!important}.layui-font-cyan{color:#2f4056!important}.layui-font-blue{color:#01aaed!important}.layui-font-purple{color:#a233c6!important}.layui-font-black{color:#000!important}.layui-font-gray{color:#c2c2c2!important}.layui-btn{display:inline-block;vertical-align:middle;height:38px;line-height:38px;border:1px solid transparent;padding:0 18px;background-color:#16baaa;color:#fff;white-space:nowrap;text-align:center;font-size:14px;border-radius:2px;cursor:pointer;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-btn:hover{opacity:.8;filter:alpha(opacity=80);color:#fff}.layui-btn:active{opacity:1;filter:alpha(opacity=100)}.layui-btn+.layui-btn{margin-left:10px}.layui-btn-container{word-spacing:-5px}.layui-btn-container .layui-btn{margin-right:10px;margin-bottom:10px;word-spacing:normal}.layui-btn-container .layui-btn+.layui-btn{margin-left:0}.layui-table .layui-btn-container .layui-btn{margin-bottom:9px}.layui-btn-radius{border-radius:100px}.layui-btn .layui-icon{padding:0 2px;vertical-align:middle\0;vertical-align:bottom}.layui-btn-primary{border-color:#d2d2d2;background:0 0;color:#5f5f5f}.layui-btn-primary:hover{border-color:#16baaa;color:#333}.layui-btn-normal{background-color:#1e9fff}.layui-btn-warm{background-color:#ffb800}.layui-btn-danger{background-color:#ff5722}.layui-btn-checked{background-color:#16b777}.layui-btn-disabled,.layui-btn-disabled:active,.layui-btn-disabled:hover{border-color:#eee!important;background-color:#fbfbfb!important;color:#d2d2d2!important;cursor:not-allowed!important;opacity:1}.layui-btn-lg{height:44px;line-height:44px;padding:0 25px;font-size:16px}.layui-btn-sm{height:30px;line-height:30px;padding:0 10px;font-size:12px}.layui-btn-xs{height:22px;line-height:22px;padding:0 5px;font-size:12px}.layui-btn-xs i{font-size:12px!important}.layui-btn-group{display:inline-block;vertical-align:middle;font-size:0}.layui-btn-group .layui-btn{margin-left:0!important;margin-right:0!important;border-left:1px solid rgba(255,255,255,.5);border-radius:0}.layui-btn-group .layui-btn-primary{border-left:none}.layui-btn-group .layui-btn-primary:hover{border-color:#d2d2d2;color:#16baaa}.layui-btn-group .layui-btn:first-child{border-left:none;border-radius:2px 0 0 2px}.layui-btn-group .layui-btn-primary:first-child{border-left:1px solid #d2d2d2}.layui-btn-group .layui-btn:last-child{border-radius:0 2px 2px 0}.layui-btn-group .layui-btn+.layui-btn{margin-left:0}.layui-btn-group+.layui-btn-group{margin-left:10px}.layui-btn-fluid{width:100%}.layui-input,.layui-select,.layui-textarea{height:38px;line-height:1.3;line-height:38px\9;border-width:1px;border-style:solid;background-color:#fff;color:rgba(0,0,0,.85);border-radius:2px}.layui-input::-webkit-input-placeholder,.layui-select::-webkit-input-placeholder,.layui-textarea::-webkit-input-placeholder{line-height:1.3}.layui-input,.layui-textarea{display:block;width:100%;padding-left:10px}.layui-input:hover,.layui-textarea:hover{border-color:#d2d2d2!important}.layui-input:focus,.layui-textarea:focus{border-color:#16b777!important;box-shadow:0 0 0 3px rgba(22,183,119,.08)}.layui-textarea{position:relative;min-height:100px;height:auto;line-height:20px;padding:6px 10px;resize:vertical}.layui-input[disabled],.layui-textarea[disabled]{background-color:#fafafa}.layui-select{padding:0 10px}.layui-form input[type=checkbox],.layui-form input[type=radio],.layui-form select{display:none}.layui-form [lay-ignore]{display:initial}.layui-form-item{position:relative;margin-bottom:15px;clear:both;*zoom:1}.layui-form-item:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-form-label{position:relative;float:left;display:block;padding:9px 15px;width:80px;font-weight:400;line-height:20px;text-align:right}.layui-form-label-col{display:block;float:none;padding:9px 0;line-height:20px;text-align:left}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block,.layui-input-inline{position:relative}.layui-input-block{margin-left:110px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{position:relative;float:left;display:block;padding:9px 0!important;line-height:20px;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border-color:#ff5722!important;box-shadow:0 0 0 3px rgba(255,87,34,.08)}.layui-input-prefix,.layui-input-split,.layui-input-suffix,.layui-input-suffix .layui-input-affix{position:absolute;right:0;top:0;padding:0 10px;width:35px;height:100%;text-align:center;transition:all .3s;box-sizing:border-box}.layui-input-prefix{left:0;border-radius:2px 0 0 2px}.layui-input-suffix{right:0;border-radius:0 2px 2px 0}.layui-input-split{border-width:1px;border-style:solid}.layui-input-prefix .layui-icon,.layui-input-split .layui-icon,.layui-input-suffix .layui-icon{position:relative;font-size:16px;color:#5f5f5f;transition:all .3s}.layui-input-group{position:relative;display:table;box-sizing:border-box}.layui-input-group>*{display:table-cell;vertical-align:middle;position:relative}.layui-input-group .layui-input{padding-right:15px}.layui-input-group>.layui-input-prefix{width:auto;border-right:0}.layui-input-group>.layui-input-suffix{width:auto;border-left:0}.layui-input-group .layui-input-split{white-space:nowrap}.layui-input-wrap{position:relative;line-height:38px}.layui-input-wrap .layui-input{padding-right:35px}.layui-input-wrap .layui-input::-ms-clear,.layui-input-wrap .layui-input::-ms-reveal{display:none}.layui-input-wrap .layui-input-prefix+.layui-input,.layui-input-wrap .layui-input-prefix~* .layui-input{padding-left:35px}.layui-input-wrap .layui-input-split+.layui-input,.layui-input-wrap .layui-input-split~* .layui-input{padding-left:45px}.layui-input-wrap .layui-input-prefix~.layui-form-select{position:static}.layui-input-wrap .layui-input-prefix,.layui-input-wrap .layui-input-split,.layui-input-wrap .layui-input-suffix{pointer-events:none}.layui-input-wrap .layui-input:hover+.layui-input-split{border-color:#d2d2d2}.layui-input-wrap .layui-input:focus+.layui-input-split{border-color:#16b777}.layui-input-wrap .layui-input-prefix.layui-input-split{border-width:0;border-right-width:1px}.layui-input-affix{line-height:38px}.layui-input-suffix .layui-input-affix{right:auto;left:-35px}.layui-input-affix .layui-icon{color:rgba(0,0,0,.8);pointer-events:auto!important;cursor:pointer}.layui-input-affix .layui-icon-clear{color:rgba(0,0,0,.3)}.layui-input-affix .layui-icon:hover{color:rgba(0,0,0,.6)}.layui-input-wrap .layui-input-number{width:24px;padding:0}.layui-input-wrap .layui-input-number .layui-icon{position:absolute;right:0;width:100%;height:50%;line-height:normal;font-size:12px}.layui-input-wrap .layui-input-number .layui-icon:before{position:absolute;left:50%;top:50%;margin-top:-6px;margin-left:-6px}.layui-input-wrap .layui-input-number .layui-icon:first-child{top:0;border-bottom:1px solid #eee}.layui-input-wrap .layui-input-number .layui-icon:last-child{bottom:0}.layui-input-wrap .layui-input-number .layui-icon:hover{font-weight:700}.layui-input-wrap .layui-input[type=number]::-webkit-inner-spin-button,.layui-input-wrap .layui-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none!important}.layui-input-wrap .layui-input[type=number]{-moz-appearance:textfield}.layui-form-select{position:relative;color:#5f5f5f}.layui-form-select .layui-input{padding-right:30px;cursor:pointer}.layui-form-select .layui-edge{position:absolute;right:10px;top:50%;margin-top:-3px;cursor:pointer;border-width:6px;border-top-color:#c2c2c2;border-top-style:solid;transition:all .3s;-webkit-transition:all .3s}.layui-form-select dl{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #eee;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:1px 1px 4px rgb(0 0 0 / 8%);box-sizing:border-box}.layui-form-select dl dd,.layui-form-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-form-select dl dt{font-size:12px;color:#999}.layui-form-select dl dd{cursor:pointer}.layui-form-select dl dd:hover{background-color:#f8f8f8;-webkit-transition:.5s all;transition:.5s all}.layui-form-select .layui-select-group dd{padding-left:20px}.layui-form-select dl dd.layui-select-tips{padding-left:10px!important;color:#999}.layui-form-select dl dd.layui-this{background-color:#f8f8f8;color:#16b777;font-weight:700}.layui-form-select dl dd.layui-disabled{background-color:#fff}.layui-form-selected dl{display:block}.layui-form-selected .layui-edge{margin-top:-9px;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.layui-form-selected .layui-edge{margin-top:-3px\0}:root .layui-form-selected .layui-edge{margin-top:-9px\0/IE9}.layui-form-selectup dl{top:auto;bottom:42px}.layui-select-none{margin:5px 0;text-align:center;color:#999}.layui-select-disabled .layui-disabled{border-color:#eee!important}.layui-select-disabled .layui-edge{border-top-color:#d2d2d2}.layui-form-checkbox{position:relative;display:inline-block;vertical-align:middle;height:30px;line-height:30px;margin-right:10px;padding-right:30px;background-color:#fff;cursor:pointer;font-size:0;-webkit-transition:.1s linear;transition:.1s linear;box-sizing:border-box}.layui-form-checkbox>*{display:inline-block;vertical-align:middle}.layui-form-checkbox>div{padding:0 11px;font-size:14px;border-radius:2px 0 0 2px;background-color:#d2d2d2;color:#fff;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.layui-form-checkbox>div>.layui-icon{line-height:normal}.layui-form-checkbox:hover>div{background-color:#c2c2c2}.layui-form-checkbox>i{position:absolute;right:0;top:0;width:30px;height:100%;border:1px solid #d2d2d2;border-left:none;border-radius:0 2px 2px 0;color:#fff;color:rgba(255,255,255,0);font-size:20px;text-align:center;box-sizing:border-box}.layui-form-checkbox:hover>i{border-color:#c2c2c2;color:#c2c2c2}.layui-form-checked,.layui-form-checked:hover{border-color:#16b777}.layui-form-checked:hover>div,.layui-form-checked>div{background-color:#16b777}.layui-form-checked:hover>i,.layui-form-checked>i{color:#16b777}.layui-form-item .layui-form-checkbox{margin-top:4px}.layui-form-checkbox.layui-checkbox-disabled>div{background-color:#eee!important}.layui-form [lay-checkbox]{display:none}.layui-form-checkbox[lay-skin=primary]{height:auto!important;line-height:normal!important;min-width:18px;min-height:18px;border:none!important;margin-right:0;padding-left:24px;padding-right:0;background:0 0}.layui-form-checkbox[lay-skin=primary]>div{margin-top:-1px;padding-left:0;padding-right:15px;line-height:18px;background:0 0;color:#5f5f5f}.layui-form-checkbox[lay-skin=primary]>i{right:auto;left:0;width:16px;height:16px;line-height:14px;border:1px solid #d2d2d2;font-size:12px;border-radius:2px;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-checkbox[lay-skin=primary]:hover>i{border-color:#16b777;color:#fff}.layui-form-checked[lay-skin=primary]>i{border-color:#16b777!important;background-color:#16b777;color:#fff}.layui-checkbox-disabled[lay-skin=primary]>div{background:0 0!important}.layui-form-checked.layui-checkbox-disabled[lay-skin=primary]>i{background:#eee!important;border-color:#eee!important}.layui-checkbox-disabled[lay-skin=primary]:hover>i{border-color:#d2d2d2}.layui-form-item .layui-form-checkbox[lay-skin=primary]{margin-top:10px}.layui-form-checkbox[lay-skin=primary]>.layui-icon-indeterminate{border-color:#16b777}.layui-form-checkbox[lay-skin=primary]>.layui-icon-indeterminate:before{content:'';display:inline-block;vertical-align:middle;position:relative;width:50%;height:1px;margin:-1px auto 0;background-color:#16b777}.layui-form-switch{position:relative;display:inline-block;vertical-align:middle;height:24px;line-height:22px;min-width:44px;padding:0 5px;margin-top:8px;border:1px solid #d2d2d2;border-radius:20px;cursor:pointer;box-sizing:border-box;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch>i{position:absolute;left:5px;top:3px;width:16px;height:16px;border-radius:20px;background-color:#d2d2d2;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch>div{position:relative;top:0;margin-left:21px;padding:0!important;text-align:center!important;color:#999!important;font-style:normal!important;font-size:12px}.layui-form-onswitch{border-color:#16b777;background-color:#16b777}.layui-form-onswitch>i{left:100%;margin-left:-21px;background-color:#fff}.layui-form-onswitch>div{margin-left:0;margin-right:21px;color:#fff!important}.layui-checkbox-disabled{border-color:#eee!important}.layui-checkbox-disabled>div{color:#c2c2c2!important}.layui-checkbox-disabled>i{border-color:#eee!important}.layui-checkbox-disabled:hover>i{color:#fff!important}.layui-form-radio{display:inline-block;vertical-align:middle;line-height:28px;margin:6px 10px 0 0;padding-right:10px;cursor:pointer;font-size:0}.layui-form-radio>*{display:inline-block;vertical-align:middle;font-size:14px}.layui-form-radio>i{margin-right:8px;font-size:22px;color:#c2c2c2}.layui-form-radio:hover>*,.layui-form-radioed,.layui-form-radioed>i{color:#16b777}.layui-radio-disabled>i{color:#eee!important}.layui-radio-disabled>*{color:#c2c2c2!important}.layui-form [lay-radio]{display:none}.layui-form-pane .layui-form-label{width:110px;padding:8px 15px;height:38px;line-height:20px;border-width:1px;border-style:solid;border-radius:2px 0 0 2px;text-align:center;background-color:#fafafa;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;box-sizing:border-box}.layui-form-pane .layui-input-inline{margin-left:-1px}.layui-form-pane .layui-input-block{margin-left:110px;left:-1px}.layui-form-pane .layui-input{border-radius:0 2px 2px 0}.layui-form-pane .layui-form-text .layui-form-label{float:none;width:100%;border-radius:2px;box-sizing:border-box;text-align:left}.layui-form-pane .layui-form-text .layui-input-inline{display:block;margin:0;top:-1px;clear:both}.layui-form-pane .layui-form-text .layui-input-block{margin:0;left:0;top:-1px}.layui-form-pane .layui-form-text .layui-textarea{min-height:100px;border-radius:0 0 2px 2px}.layui-form-pane .layui-form-checkbox{margin:4px 0 4px 10px}.layui-form-pane .layui-form-radio,.layui-form-pane .layui-form-switch{margin-top:6px;margin-left:10px}.layui-form-pane .layui-form-item[pane]{position:relative;border-width:1px;border-style:solid}.layui-form-pane .layui-form-item[pane] .layui-form-label{position:absolute;left:0;top:0;height:100%;border-width:0;border-right-width:1px}.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left:110px}@media screen and (max-width:450px){.layui-form-item .layui-form-label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-form-item .layui-inline{display:block;margin-right:0;margin-bottom:20px;clear:both}.layui-form-item .layui-inline:after{content:'\20';clear:both;display:block;height:0}.layui-form-item .layui-input-inline{display:block;float:none;left:-3px;width:auto!important;margin:0 0 10px 112px}.layui-form-item .layui-input-inline+.layui-form-mid{margin-left:110px;top:-5px;padding:0}.layui-form-item .layui-form-checkbox{margin-right:5px;margin-bottom:5px}}.layui-laypage{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;margin:10px 0;font-size:0}.layui-laypage>a:first-child,.layui-laypage>a:first-child em{border-radius:2px 0 0 2px}.layui-laypage>a:last-child,.layui-laypage>a:last-child em{border-radius:0 2px 2px 0}.layui-laypage>:first-child{margin-left:0!important}.layui-laypage>:last-child{margin-right:0!important}.layui-laypage a,.layui-laypage button,.layui-laypage input,.layui-laypage select,.layui-laypage span{border:1px solid #eee}.layui-laypage a,.layui-laypage span{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding:0 15px;height:28px;line-height:28px;margin:0 -1px 5px 0;background-color:#fff;color:#333;font-size:12px}.layui-laypage a[data-page]{color:#333}.layui-laypage a{text-decoration:none!important;cursor:pointer}.layui-laypage a:hover{color:#16baaa}.layui-laypage em{font-style:normal}.layui-laypage .layui-laypage-spr{color:#999;font-weight:700}.layui-laypage .layui-laypage-curr{position:relative}.layui-laypage .layui-laypage-curr em{position:relative;color:#fff}.layui-laypage .layui-laypage-curr .layui-laypage-em{position:absolute;left:-1px;top:-1px;padding:1px;width:100%;height:100%;background-color:#16baaa}.layui-laypage-em{border-radius:2px}.layui-laypage-next em,.layui-laypage-prev em{font-family:Sim sun;font-size:16px}.layui-laypage .layui-laypage-count,.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh,.layui-laypage .layui-laypage-skip{margin-left:10px;margin-right:10px;padding:0;border:none}.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh{vertical-align:top}.layui-laypage .layui-laypage-refresh i{font-size:18px;cursor:pointer}.layui-laypage select{height:22px;padding:3px;border-radius:2px;cursor:pointer}.layui-laypage .layui-laypage-skip{height:30px;line-height:30px;color:#999}.layui-laypage button,.layui-laypage input{height:30px;line-height:30px;border-radius:2px;vertical-align:top;background-color:#fff;box-sizing:border-box}.layui-laypage input{display:inline-block;width:40px;margin:0 10px;padding:0 3px;text-align:center}.layui-laypage input:focus,.layui-laypage select:focus{border-color:#16baaa!important}.layui-laypage button{margin-left:10px;padding:0 10px;cursor:pointer}.layui-flow-more{margin:10px 0;text-align:center;color:#999;font-size:14px;clear:both}.layui-flow-more a{height:32px;line-height:32px}.layui-flow-more a *{display:inline-block;vertical-align:top}.layui-flow-more a cite{padding:0 20px;border-radius:3px;background-color:#eee;color:#333;font-style:normal}.layui-flow-more a cite:hover{opacity:.8}.layui-flow-more a i{font-size:30px;color:#737383}.layui-table{width:100%;margin:10px 0;background-color:#fff;color:#5f5f5f}.layui-table tr{transition:all .3s;-webkit-transition:all .3s}.layui-table th{text-align:left;font-weight:600}.layui-table-mend{background-color:#fff}.layui-table-click,.layui-table-hover,.layui-table[lay-even] tbody tr:nth-child(even){background-color:#f8f8f8}.layui-table-checked{background-color:#dbfbf0}.layui-table-checked.layui-table-click,.layui-table-checked.layui-table-hover{background-color:#abf8dd}.layui-table td,.layui-table th,.layui-table-col-set,.layui-table-fixed-r,.layui-table-grid-down,.layui-table-header,.layui-table-mend,.layui-table-page,.layui-table-tips-main,.layui-table-tool,.layui-table-total,.layui-table-view,.layui-table[lay-skin=line],.layui-table[lay-skin=row]{border-width:1px;border-style:solid;border-color:#eee}.layui-table td,.layui-table th{position:relative;padding:9px 15px;min-height:20px;line-height:20px;font-size:14px}.layui-table[lay-skin=line] td,.layui-table[lay-skin=line] th{border-width:0;border-bottom-width:1px}.layui-table[lay-skin=row] td,.layui-table[lay-skin=row] th{border-width:0;border-right-width:1px}.layui-table[lay-skin=nob] td,.layui-table[lay-skin=nob] th{border:none}.layui-table img{max-width:100px}.layui-table[lay-size=lg] td,.layui-table[lay-size=lg] th{padding-top:15px;padding-right:30px;padding-bottom:15px;padding-left:30px}.layui-table-view .layui-table[lay-size=lg] .layui-table-cell{height:50px;line-height:40px}.layui-table[lay-size=sm] td,.layui-table[lay-size=sm] th{padding-top:5px;padding-right:10px;padding-bottom:5px;padding-left:10px;font-size:12px}.layui-table-view .layui-table[lay-size=sm] .layui-table-cell{height:30px;line-height:20px;padding-top:5px;padding-left:11px;padding-right:11px}.layui-table[lay-data],.layui-table[lay-options]{display:none}.layui-table-box{position:relative;overflow:hidden}.layui-table-view{clear:both}.layui-table-view .layui-table{position:relative;width:auto;margin:0;border:0;border-collapse:separate}.layui-table-view .layui-table[lay-skin=line]{border-width:0;border-right-width:1px}.layui-table-view .layui-table[lay-skin=row]{border-width:0;border-bottom-width:1px}.layui-table-view .layui-table td,.layui-table-view .layui-table th{padding:0;border-top:none;border-left:none}.layui-table-view .layui-table th [lay-event],.layui-table-view .layui-table th.layui-unselect .layui-table-cell span{cursor:pointer}.layui-table-view .layui-table td,.layui-table-view .layui-table th span{cursor:default}.layui-table-view .layui-table td[data-edit]{cursor:text}.layui-table-view .layui-table td[data-edit]:hover:after{position:absolute;left:0;top:0;width:100%;height:100%;box-sizing:border-box;border:1px solid #16b777;pointer-events:none;content:""}.layui-table-view .layui-form-checkbox[lay-skin=primary] i{width:18px;height:18px;line-height:16px}.layui-table-view .layui-form-radio{line-height:0;padding:0}.layui-table-view .layui-form-radio>i{margin:0;font-size:20px}.layui-table-init{position:absolute;left:0;top:0;width:100%;height:100%;text-align:center;z-index:199}.layui-table-init .layui-icon{position:absolute;left:50%;top:50%;margin:-15px 0 0 -15px;font-size:30px;color:#c2c2c2}.layui-table-header{border-width:0;border-bottom-width:1px;overflow:hidden}.layui-table-header .layui-table{margin-bottom:-1px}.layui-table-column{position:relative;width:100%;min-height:41px;padding:8px 16px;border-width:0;border-bottom-width:1px}.layui-table-column .layui-btn-container{margin-bottom:-8px}.layui-table-column .layui-btn-container .layui-btn{margin-right:8px;margin-bottom:8px}.layui-table-tool .layui-inline[lay-event]{position:relative;width:26px;height:26px;padding:5px;line-height:16px;margin-right:10px;text-align:center;color:#333;border:1px solid #ccc;cursor:pointer;-webkit-transition:.5s all;transition:.5s all}.layui-table-tool .layui-inline[lay-event]:hover{border:1px solid #999}.layui-table-tool-temp{padding-right:120px}.layui-table-tool-self{position:absolute;right:17px;top:10px}.layui-table-tool .layui-table-tool-self .layui-inline[lay-event]{margin:0 0 0 10px}.layui-table-tool-panel{position:absolute;top:29px;left:-1px;z-index:399;padding:5px 0!important;min-width:150px;min-height:40px;border:1px solid #d2d2d2;text-align:left;overflow-y:auto;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-table-tool-panel li{padding:0 10px;margin:0!important;line-height:30px;list-style-type:none!important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-transition:.5s all;transition:.5s all}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary]{width:100%}.layui-table-tool-panel li:hover{background-color:#f8f8f8}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary]{padding-left:28px}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] i{position:absolute;left:0;top:0}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] span{padding:0}.layui-table-tool .layui-table-tool-self .layui-table-tool-panel{left:auto;right:-1px}.layui-table-col-set{position:absolute;right:0;top:0;width:20px;height:100%;border-width:0;border-left-width:1px;background-color:#fff}.layui-table-sort{width:10px;height:20px;margin-left:5px;cursor:pointer!important}.layui-table-sort .layui-edge{position:absolute;left:5px;border-width:5px}.layui-table-sort .layui-table-sort-asc{top:3px;border-top:none;border-bottom-style:solid;border-bottom-color:#b2b2b2}.layui-table-sort .layui-table-sort-asc:hover{border-bottom-color:#5f5f5f}.layui-table-sort .layui-table-sort-desc{bottom:5px;border-bottom:none;border-top-style:solid;border-top-color:#b2b2b2}.layui-table-sort .layui-table-sort-desc:hover{border-top-color:#5f5f5f}.layui-table-sort[lay-sort=asc] .layui-table-sort-asc{border-bottom-color:#000}.layui-table-sort[lay-sort=desc] .layui-table-sort-desc{border-top-color:#000}.layui-table-cell{height:38px;line-height:28px;padding:6px 15px;position:relative;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;box-sizing:border-box}.layui-table-cell .layui-form-checkbox[lay-skin=primary]{top:-1px;padding:0}.layui-table-cell .layui-table-link{color:#01aaed}.layui-table-cell .layui-btn{vertical-align:inherit}.layui-table-cell[align=center]{-webkit-box-pack:center}.layui-table-cell[align=right]{-webkit-box-pack:end}.laytable-cell-checkbox,.laytable-cell-numbers,.laytable-cell-radio,.laytable-cell-space{text-align:center;-webkit-box-pack:center}.layui-table-body{position:relative;overflow:auto;margin-right:-1px;margin-bottom:-1px}.layui-table-body .layui-none{line-height:26px;padding:30px 15px;text-align:center;color:#999}.layui-table-fixed{position:absolute;left:0;top:0;z-index:101}.layui-table-fixed .layui-table-body{overflow:hidden}.layui-table-fixed-l{box-shadow:1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r{left:auto;right:-1px;border-width:0;border-left-width:1px;box-shadow:-1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r .layui-table-header{position:relative;overflow:visible}.layui-table-mend{position:absolute;right:-49px;top:0;height:100%;width:50px;border-width:0;border-left-width:1px}.layui-table-tool{position:relative;width:100%;min-height:50px;line-height:30px;padding:10px 15px;border-width:0;border-bottom-width:1px}.layui-table-tool .layui-btn-container{margin-bottom:-10px}.layui-table-total{margin-bottom:-1px;border-width:0;border-top-width:1px;overflow:hidden}.layui-table-page{border-width:0;border-top-width:1px;margin-bottom:-1px;white-space:nowrap;overflow:hidden}.layui-table-page>div{height:26px}.layui-table-page .layui-laypage{margin:0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span{height:26px;line-height:26px;margin-bottom:10px;border:none;background:0 0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span.layui-laypage-curr{padding:0 12px}.layui-table-page .layui-laypage span{margin-left:0;padding:0}.layui-table-page .layui-laypage .layui-laypage-prev{margin-left:-11px!important}.layui-table-page .layui-laypage .layui-laypage-curr .layui-laypage-em{left:0;top:0;padding:0}.layui-table-page .layui-laypage button,.layui-table-page .layui-laypage input{height:26px;line-height:26px}.layui-table-page .layui-laypage input{width:40px}.layui-table-page .layui-laypage button{padding:0 10px}.layui-table-page select{height:18px}.layui-table-pagebar{float:right;line-height:23px}.layui-table-pagebar .layui-btn-sm{margin-top:-1px}.layui-table-pagebar .layui-btn-xs{margin-top:2px}.layui-table-view select[lay-ignore]{display:inline-block}.layui-table-patch .layui-table-cell{padding:0;width:30px}.layui-table-edit{position:absolute;left:0;top:0;z-index:189;min-width:100%;min-height:100%;padding:5px 14px;border-radius:0;box-shadow:1px 1px 20px rgba(0,0,0,.15);background-color:#fff}.layui-table-edit:focus{border-color:#16b777!important}input.layui-input.layui-table-edit{height:100%}select.layui-table-edit{padding:0 0 0 10px;border-color:#d2d2d2}.layui-table-view .layui-form-checkbox,.layui-table-view .layui-form-radio,.layui-table-view .layui-form-switch{top:0;margin:0}.layui-table-view .layui-form-checkbox{top:-1px;height:26px;line-height:26px}.layui-table-view .layui-form-checkbox i{height:26px}.layui-table-grid .layui-table-cell{overflow:visible}.layui-table-grid-down{position:absolute;top:0;right:0;width:26px;height:100%;padding:5px 0;border-width:0;border-left-width:1px;text-align:center;background-color:#fff;color:#999;cursor:pointer}.layui-table-grid-down .layui-icon{position:absolute;top:50%;left:50%;margin:-8px 0 0 -8px}.layui-table-grid-down:hover{background-color:#fbfbfb}body .layui-table-tips .layui-layer-content{background:0 0;padding:0;box-shadow:0 1px 6px rgba(0,0,0,.12)}.layui-table-tips-main{margin:-49px 0 0 -1px;max-height:150px;padding:8px 15px;font-size:14px;overflow-y:scroll;background-color:#fff;color:#5f5f5f}.layui-table-tips-c{position:absolute;right:-3px;top:-13px;width:20px;height:20px;padding:3px;cursor:pointer;background-color:#5f5f5f;border-radius:50%;color:#fff}.layui-table-tips-c:hover{background-color:#777}.layui-table-tips-c:before{position:relative;right:-2px}.layui-table-tree-nodeIcon{max-width:20px}.layui-table-tree-nodeIcon>*{width:100%}.layui-table-tree-flexIcon,.layui-table-tree-nodeIcon{margin-right:2px}.layui-table-tree-flexIcon{cursor:pointer}.layui-upload-file{display:none!important;opacity:.01;filter:Alpha(opacity=1)}.layui-upload-list{margin:11px 0}.layui-upload-choose{max-width:200px;padding:0 10px;color:#999;font-size:14px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-upload-drag{position:relative;display:inline-block;padding:30px;border:1px dashed #e2e2e2;background-color:#fff;text-align:center;cursor:pointer;color:#999}.layui-upload-drag .layui-icon{font-size:50px;color:#16baaa}.layui-upload-drag[lay-over]{border-color:#16baaa}.layui-upload-form{display:inline-block}.layui-upload-iframe{position:absolute;width:0;height:0;border:0;visibility:hidden}.layui-upload-wrap{position:relative;display:inline-block;vertical-align:middle}.layui-upload-wrap .layui-upload-file{display:block!important;position:absolute;left:0;top:0;z-index:10;font-size:100px;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-btn-container .layui-upload-choose{padding-left:0}.layui-menu{position:relative;margin:5px 0;background-color:#fff;box-sizing:border-box}.layui-menu *{box-sizing:border-box}.layui-menu li,.layui-menu-body-title,.layui-menu-body-title a{padding:5px 15px;color:initial}.layui-menu li{position:relative;margin:1px 0;line-height:26px;color:rgba(0,0,0,.8);font-size:14px;white-space:nowrap;cursor:pointer;transition:all .3s}.layui-menu li:hover{background-color:#f8f8f8}.layui-menu li.layui-disabled,.layui-menu li.layui-disabled *{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important}.layui-menu-item-parent:hover>.layui-menu-body-panel{display:block;animation-name:layui-fadein;animation-duration:.3s;animation-fill-mode:both;animation-delay:.2s}.layui-menu-item-group>.layui-menu-body-title,.layui-menu-item-parent>.layui-menu-body-title{padding-right:38px}.layui-menu .layui-menu-item-divider:hover,.layui-menu .layui-menu-item-group:hover,.layui-menu .layui-menu-item-none:hover{background:0 0;cursor:default}.layui-menu .layui-menu-item-group>ul{margin:5px 0 -5px}.layui-menu .layui-menu-item-group>.layui-menu-body-title{color:rgba(0,0,0,.35);user-select:none}.layui-menu .layui-menu-item-none{color:rgba(0,0,0,.35);cursor:default}.layui-menu .layui-menu-item-none{text-align:center}.layui-menu .layui-menu-item-divider{margin:5px 0;padding:0;height:0;line-height:0;border-bottom:1px solid #eee;overflow:hidden}.layui-menu .layui-menu-item-down:hover,.layui-menu .layui-menu-item-up:hover{cursor:pointer}.layui-menu .layui-menu-item-up>.layui-menu-body-title{color:rgba(0,0,0,.8)}.layui-menu .layui-menu-item-up>ul{visibility:hidden;height:0;overflow:hidden}.layui-menu .layui-menu-item-down:hover>.layui-menu-body-title>.layui-icon,.layui-menu .layui-menu-item-up>.layui-menu-body-title:hover>.layui-icon{color:#000}.layui-menu .layui-menu-item-down>ul{visibility:visible;height:auto}.layui-menu .layui-menu-item-checked,.layui-menu .layui-menu-item-checked2{background-color:#f8f8f8!important;color:#16b777}.layui-menu .layui-menu-item-checked a,.layui-menu .layui-menu-item-checked2 a{color:#16b777}.layui-menu .layui-menu-item-checked:after{position:absolute;right:-1px;top:0;bottom:0;border-right:3px solid #16b777;content:""}.layui-menu-body-title{position:relative;margin:-5px -15px;overflow:hidden;text-overflow:ellipsis}.layui-menu-body-title a{display:block;margin:-5px -15px;color:rgba(0,0,0,.8)}.layui-menu-body-title a:hover{transition:all .3s}.layui-menu-body-title>.layui-icon{position:absolute;right:15px;top:50%;margin-top:-6px;line-height:normal;font-size:14px}.layui-menu-body-title>.layui-icon:hover{transition:all .3s}.layui-menu-body-title>.layui-icon-right{right:14px}.layui-menu-body-panel{display:none;position:absolute;top:-7px;left:100%;z-index:1000;margin-left:13px;padding:5px 0}.layui-menu-body-panel:before{content:"";position:absolute;width:20px;left:-16px;top:0;bottom:0}.layui-menu-body-panel-left{left:auto;right:100%;margin:0 13px 0}.layui-menu-body-panel-left:before{left:auto;right:-16px}.layui-menu-lg li{line-height:32px}.layui-menu-lg .layui-menu-body-title a:hover,.layui-menu-lg li:hover{background:0 0;color:#16b777}.layui-menu-lg li .layui-menu-body-panel{margin-left:14px}.layui-menu-lg li .layui-menu-body-panel-left{margin:0 15px 0}.layui-dropdown{position:absolute;left:-999999px;top:-999999px;z-index:77777777;margin:5px 0;min-width:100px}.layui-dropdown:before{content:"";position:absolute;width:100%;height:6px;left:0;top:-6px}.layui-dropdown-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px");position:fixed;_position:absolute;pointer-events:auto}.layui-nav{position:relative;padding:0 15px;background-color:#2f363c;color:#fff;border-radius:2px;font-size:0;box-sizing:border-box}.layui-nav *{font-size:14px}.layui-nav .layui-nav-item{position:relative;display:inline-block;*display:inline;*zoom:1;margin-top:0;list-style:none;vertical-align:middle;line-height:60px}.layui-nav .layui-nav-item a{display:block;padding:0 20px;color:#fff;color:rgba(255,255,255,.7);transition:all .3s;-webkit-transition:all .3s}.layui-nav .layui-this:after,.layui-nav-bar{content:"";position:absolute;left:0;top:0;width:0;height:3px;background-color:#16b777;transition:all .2s;-webkit-transition:all .2s;pointer-events:none}.layui-nav-bar{z-index:1000}.layui-nav[lay-bar=disabled] .layui-nav-bar{display:none}.layui-nav .layui-nav-item a:hover,.layui-nav .layui-this a{color:#fff;text-decoration:none}.layui-nav .layui-this:after{top:auto;bottom:0;width:100%}.layui-nav-img{width:30px;height:30px;margin-right:10px;border-radius:50%}.layui-nav .layui-nav-more{position:absolute;top:0;right:3px;left:auto!important;margin-top:0;font-size:12px;cursor:pointer;transition:all .2s;-webkit-transition:all .2s}.layui-nav .layui-nav-mored,.layui-nav-itemed>a .layui-nav-more{transform:rotate(180deg)}.layui-nav-child{display:none;position:absolute;left:0;top:65px;min-width:100%;line-height:36px;padding:5px 0;box-shadow:0 2px 4px rgba(0,0,0,.12);border:1px solid #eee;background-color:#fff;z-index:100;border-radius:2px;white-space:nowrap;box-sizing:border-box}.layui-nav .layui-nav-child a{color:#5f5f5f;color:rgba(0,0,0,.8)}.layui-nav .layui-nav-child a:hover{background-color:#f8f8f8;color:rgba(0,0,0,.8)}.layui-nav-child dd{margin:1px 0;position:relative}.layui-nav-child dd.layui-this{background-color:#f8f8f8;color:#000}.layui-nav-child dd.layui-this:after{display:none}.layui-nav-child-r{left:auto;right:0}.layui-nav-child-c{text-align:center}.layui-nav.layui-nav-tree{width:200px;padding:0}.layui-nav-tree .layui-nav-item{display:block;width:100%;line-height:40px}.layui-nav-tree .layui-nav-item a{position:relative;height:40px;line-height:40px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-nav-tree .layui-nav-item>a{padding-top:5px;padding-bottom:5px}.layui-nav-tree .layui-nav-more{right:15px}.layui-nav-tree .layui-nav-item>a .layui-nav-more{padding:5px 0}.layui-nav-tree .layui-nav-bar{width:5px;height:0}.layui-side .layui-nav-tree .layui-nav-bar{width:2px}.layui-nav-tree .layui-nav-child dd.layui-this,.layui-nav-tree .layui-nav-child dd.layui-this a,.layui-nav-tree .layui-this,.layui-nav-tree .layui-this>a,.layui-nav-tree .layui-this>a:hover{background-color:#16baaa;color:#fff}.layui-nav-tree .layui-this:after{display:none}.layui-nav-itemed>a,.layui-nav-tree .layui-nav-title a,.layui-nav-tree .layui-nav-title a:hover{color:#fff!important}.layui-nav-tree .layui-nav-bar{background-color:#16baaa}.layui-nav-tree .layui-nav-child{position:relative;z-index:0;top:0;border:none;box-shadow:none}.layui-nav-tree .layui-nav-child dd{margin:0}.layui-nav-tree .layui-nav-child a{color:#fff;color:rgba(255,255,255,.7)}.layui-nav-tree .layui-nav-child,.layui-nav-tree .layui-nav-child a:hover{background:0 0;color:#fff}.layui-nav-itemed>.layui-nav-child{display:block;background-color:rgba(0,0,0,.3)!important}.layui-nav-itemed>.layui-nav-child>.layui-this>.layui-nav-child{display:block}.layui-nav-side{position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;z-index:999}.layui-nav-tree.layui-bg-gray a,.layui-nav.layui-bg-gray .layui-nav-item a{color:rgba(0,0,0,.8)}.layui-nav-tree.layui-bg-gray{padding:6px 0}.layui-nav-tree.layui-bg-gray .layui-nav-itemed>a{color:#000!important}.layui-nav.layui-bg-gray .layui-this a{color:#16b777}.layui-nav-tree.layui-bg-gray .layui-nav-itemed>.layui-nav-child{padding-left:11px;background:0 0!important}.layui-nav-tree.layui-bg-gray .layui-nav-item>a{padding-top:0;padding-bottom:0}.layui-nav-tree.layui-bg-gray .layui-nav-item>a .layui-nav-more{padding:0}.layui-nav-tree.layui-bg-gray .layui-nav-child dd.layui-this,.layui-nav-tree.layui-bg-gray .layui-nav-child dd.layui-this a,.layui-nav-tree.layui-bg-gray .layui-this,.layui-nav-tree.layui-bg-gray .layui-this>a{background:0 0!important;color:#16b777!important;font-weight:700}.layui-nav-tree.layui-bg-gray .layui-nav-bar{background-color:#16b777}.layui-breadcrumb{visibility:hidden;font-size:0}.layui-breadcrumb>*{font-size:14px}.layui-breadcrumb a{color:#999!important}.layui-breadcrumb a:hover{color:#16b777!important}.layui-breadcrumb a cite{color:#5f5f5f;font-style:normal}.layui-breadcrumb span[lay-separator]{margin:0 10px;color:#999}.layui-tab{margin:10px 0;text-align:left!important}.layui-tab[overflow]>.layui-tab-title{overflow:hidden}.layui-tab .layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom-width:1px;border-bottom-style:solid;transition:all .2s;-webkit-transition:all .2s}.layui-tab .layui-tab-title li{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;font-size:14px;transition:all .2s;-webkit-transition:all .2s}.layui-tab .layui-tab-title li{position:relative;line-height:40px;min-width:65px;margin:0;padding:0 15px;text-align:center;cursor:pointer}.layui-tab .layui-tab-title li a{display:block;padding:0 15px;margin:0 -15px}.layui-tab-title .layui-this{color:#000}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:"";width:100%;height:41px;border-width:1px;border-style:solid;border-bottom-color:#fff;border-radius:2px 2px 0 0;box-sizing:border-box;pointer-events:none}.layui-tab-bar{position:absolute;right:0;top:0;z-index:10;width:30px;height:39px;line-height:39px;border-width:1px;border-style:solid;border-radius:2px;text-align:center;background-color:#fff;cursor:pointer}.layui-tab-bar .layui-icon{position:relative;display:inline-block;top:3px;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item{display:none}.layui-tab-more{padding-right:30px;height:auto!important;white-space:normal!important}.layui-tab-more li.layui-this:after{border-bottom-color:#eee;border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;top:3px\0;-webkit-transform:rotate(180deg);transform:rotate(180deg)}:root .layui-tab-more .layui-tab-bar .layui-icon{top:-2px\0/IE9}.layui-tab-content{padding:15px 0}.layui-tab-title li .layui-tab-close{position:relative;display:inline-block;width:18px;height:18px;line-height:20px;margin-left:8px;top:1px;text-align:center;font-size:14px;color:#c2c2c2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li .layui-tab-close:hover{border-radius:2px;background-color:#ff5722;color:#fff}.layui-tab-brief>.layui-tab-title .layui-this{color:#16baaa}.layui-tab-brief>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-title .layui-this:after{border:none;border-radius:0;border-bottom:2px solid #16b777}.layui-tab-brief[overflow]>.layui-tab-title .layui-this:after{top:-1px}.layui-tab-card{border-width:1px;border-style:solid;border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1)}.layui-tab-card>.layui-tab-title{background-color:#fafafa}.layui-tab-card>.layui-tab-title li{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-title .layui-this{background-color:#fff}.layui-tab-card>.layui-tab-title .layui-this:after{border-top:none;border-width:1px;border-bottom-color:#fff}.layui-tab-card>.layui-tab-title .layui-tab-bar{height:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:#16b777}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-timeline{padding-left:5px}.layui-timeline-item{position:relative;padding-bottom:20px}.layui-timeline-axis{position:absolute;left:-5px;top:0;z-index:10;width:20px;height:20px;line-height:20px;background-color:#fff;color:#16b777;border-radius:50%;text-align:center;cursor:pointer}.layui-timeline-axis:hover{color:#ff5722}.layui-timeline-item:before{content:"";position:absolute;left:5px;top:0;z-index:0;width:1px;height:100%}.layui-timeline-item:first-child:before{display:block}.layui-timeline-item:last-child:before{display:none}.layui-timeline-content{padding-left:25px}.layui-timeline-title{position:relative;margin-bottom:10px;line-height:22px}.layui-badge,.layui-badge-dot,.layui-badge-rim{position:relative;display:inline-block;padding:0 6px;font-size:12px;text-align:center;background-color:#ff5722;color:#fff;border-radius:2px}.layui-badge{height:18px;line-height:18px}.layui-badge-dot{width:8px;height:8px;padding:0;border-radius:50%}.layui-badge-rim{height:18px;line-height:18px;border-width:1px;border-style:solid;background-color:#fff;color:#5f5f5f}.layui-btn .layui-badge,.layui-btn .layui-badge-dot{margin-left:5px}.layui-nav .layui-badge,.layui-nav .layui-badge-dot{position:absolute;top:50%;margin:-5px 6px 0}.layui-nav .layui-badge{margin-top:-10px}.layui-tab-title .layui-badge,.layui-tab-title .layui-badge-dot{left:5px;top:-2px}.layui-carousel{position:relative;left:0;top:0;background-color:#f8f8f8}.layui-carousel>[carousel-item]{position:relative;width:100%;height:100%;overflow:hidden}.layui-carousel>[carousel-item]:before{position:absolute;content:'\e63d';left:50%;top:50%;width:100px;line-height:20px;margin:-10px 0 0 -50px;text-align:center;color:#c2c2c2;font-family:layui-icon!important;font-size:30px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-carousel>[carousel-item]>*{display:none;position:absolute;left:0;top:0;width:100%;height:100%;background-color:#f8f8f8;transition-duration:.3s;-webkit-transition-duration:.3s}.layui-carousel-updown>*{-webkit-transition:.3s ease-in-out up;transition:.3s ease-in-out up}.layui-carousel-arrow{display:none\0;opacity:0;position:absolute;left:10px;top:50%;margin-top:-18px;width:36px;height:36px;line-height:36px;text-align:center;font-size:20px;border:none 0;border-radius:50%;background-color:rgba(0,0,0,.2);color:#fff;-webkit-transition-duration:.3s;transition-duration:.3s;cursor:pointer}.layui-carousel-arrow[lay-type=add]{left:auto!important;right:10px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow{opacity:1;left:20px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel[lay-arrow=none] .layui-carousel-arrow{display:none}.layui-carousel-arrow:hover,.layui-carousel-ind ul:hover{background-color:rgba(0,0,0,.35)}.layui-carousel:hover .layui-carousel-arrow{display:block\0;opacity:1;left:20px}.layui-carousel:hover .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel-ind{position:relative;top:-35px;width:100%;line-height:0!important;text-align:center;font-size:0}.layui-carousel[lay-indicator=outside]{margin-bottom:30px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind{top:10px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind ul{background-color:rgba(0,0,0,.5)}.layui-carousel[lay-indicator=none] .layui-carousel-ind{display:none}.layui-carousel-ind ul{display:inline-block;padding:5px;background-color:rgba(0,0,0,.2);border-radius:10px;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind ul li{display:inline-block;width:10px;height:10px;margin:0 3px;font-size:14px;background-color:#eee;background-color:rgba(255,255,255,.5);border-radius:50%;cursor:pointer;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind ul li:hover{background-color:rgba(255,255,255,.7)}.layui-carousel-ind ul li.layui-this{background-color:#fff}.layui-carousel>[carousel-item]>.layui-carousel-next,.layui-carousel>[carousel-item]>.layui-carousel-prev,.layui-carousel>[carousel-item]>.layui-this{display:block}.layui-carousel>[carousel-item]>.layui-this{left:0}.layui-carousel>[carousel-item]>.layui-carousel-prev{left:-100%}.layui-carousel>[carousel-item]>.layui-carousel-next{left:100%}.layui-carousel>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel>[carousel-item]>.layui-carousel-prev.layui-carousel-right{left:0}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-left{left:-100%}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-right{left:100%}.layui-carousel[lay-anim=updown] .layui-carousel-arrow{left:50%!important;top:20px;margin:0 0 0 -18px}.layui-carousel[lay-anim=updown] .layui-carousel-arrow[lay-type=add]{top:auto!important;bottom:20px}.layui-carousel[lay-anim=updown] .layui-carousel-ind{position:absolute;top:50%;right:20px;width:auto;height:auto}.layui-carousel[lay-anim=updown] .layui-carousel-ind ul{padding:3px 5px}.layui-carousel[lay-anim=updown] .layui-carousel-ind li{display:block;margin:6px 0}.layui-carousel[lay-anim=updown]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next{top:100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-left{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-right{top:100%}.layui-carousel[lay-anim=fade]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev{opacity:0}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{opacity:1}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-right{opacity:0}.layui-fixbar{position:fixed;right:16px;bottom:16px;z-index:999999}.layui-fixbar li{width:50px;height:50px;line-height:50px;margin-bottom:1px;text-align:center;cursor:pointer;font-size:30px;background-color:#9f9f9f;color:#fff;border-radius:2px;opacity:.95}.layui-fixbar li:hover{opacity:.85}.layui-fixbar li:active{opacity:1}.layui-fixbar .layui-fixbar-top{display:none;font-size:40px}body .layui-util-face{border:none;background:0 0}body .layui-util-face .layui-layer-content{padding:0;background-color:#fff;color:#5f5f5f;box-shadow:none}.layui-util-face .layui-layer-TipsG{display:none}.layui-util-face ul{position:relative;width:372px;padding:10px;border:1px solid #d9d9d9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-util-face ul li{cursor:pointer;float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px;text-align:center}.layui-util-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layui-code{position:relative;margin:10px 0;padding:15px;line-height:20px;border:1px solid #eee;border-left-width:6px;background-color:#fafafa;color:#333;font-family:Courier New,Lucida Console,Consolas;font-size:12px}.layui-transfer-box,.layui-transfer-header,.layui-transfer-search{border-width:0;border-style:solid;border-color:#eee}.layui-transfer-box{position:relative;display:inline-block;vertical-align:middle;border-width:1px;width:200px;height:360px;border-radius:2px;background-color:#fff}.layui-transfer-box .layui-form-checkbox{width:100%;margin:0!important}.layui-transfer-header{height:38px;line-height:38px;padding:0 11px;border-bottom-width:1px}.layui-transfer-search{position:relative;padding:11px;border-bottom-width:1px}.layui-transfer-search .layui-input{height:32px;padding-left:30px;font-size:12px}.layui-transfer-search .layui-icon-search{position:absolute;left:20px;top:50%;line-height:normal;margin-top:-8px;color:#5f5f5f}.layui-transfer-active{margin:0 15px;display:inline-block;vertical-align:middle}.layui-transfer-active .layui-btn{display:block;margin:0;padding:0 15px;background-color:#16b777;border-color:#16b777;color:#fff}.layui-transfer-active .layui-btn-disabled{background-color:#fbfbfb;border-color:#eee;color:#d2d2d2}.layui-transfer-active .layui-btn:first-child{margin-bottom:15px}.layui-transfer-active .layui-btn .layui-icon{margin:0;font-size:14px!important}.layui-transfer-data{padding:5px 0;overflow:auto}.layui-transfer-data li{height:32px;line-height:32px;margin-top:0!important;padding:0 11px;list-style-type:none!important}.layui-transfer-data li:hover{background-color:#f8f8f8;transition:.5s all}.layui-transfer-data .layui-none{padding:15px 11px;text-align:center;color:#999}.layui-rate,.layui-rate *{display:inline-block;vertical-align:middle}.layui-rate{padding:11px 6px 11px 0;font-size:0}.layui-rate li{margin-top:0!important}.layui-rate li i.layui-icon{font-size:20px;color:#ffb800}.layui-rate li i.layui-icon{margin-right:5px;transition:all .3s;-webkit-transition:all .3s}.layui-rate li i:hover{cursor:pointer;transform:scale(1.12);-webkit-transform:scale(1.12)}.layui-rate[readonly] li i:hover{cursor:default;transform:scale(1)}.layui-colorpicker{width:38px;height:38px;border:1px solid #eee;padding:5px;border-radius:2px;line-height:24px;display:inline-block;cursor:pointer;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-colorpicker:hover{border-color:#d2d2d2}.layui-colorpicker.layui-colorpicker-lg{width:44px;height:44px;line-height:30px}.layui-colorpicker.layui-colorpicker-sm{width:30px;height:30px;line-height:20px;padding:3px}.layui-colorpicker.layui-colorpicker-xs{width:22px;height:22px;line-height:16px;padding:1px}.layui-colorpicker-trigger-bgcolor{display:block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);border-radius:2px}.layui-colorpicker-trigger-span{display:block;height:100%;box-sizing:border-box;border:1px solid rgba(0,0,0,.15);border-radius:2px;text-align:center}.layui-colorpicker-trigger-i{display:inline-block;color:#fff;font-size:12px}.layui-colorpicker-trigger-i.layui-icon-close{color:#999}.layui-colorpicker-main{position:absolute;left:-999999px;top:-999999px;z-index:77777777;width:280px;margin:5px 0;padding:7px;background:#fff;border:1px solid #d2d2d2;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-colorpicker-main-wrapper{height:180px;position:relative}.layui-colorpicker-basis{width:260px;height:100%;position:relative}.layui-colorpicker-basis-white{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(90deg,#fff,hsla(0,0%,100%,0))}.layui-colorpicker-basis-black{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(0deg,#000,transparent)}.layui-colorpicker-basis-cursor{width:10px;height:10px;border:1px solid #fff;border-radius:50%;position:absolute;top:-3px;right:-3px;cursor:pointer}.layui-colorpicker-side{position:absolute;top:0;right:0;width:12px;height:100%;background:linear-gradient(red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.layui-colorpicker-side-slider{width:100%;height:5px;box-shadow:0 0 1px #888;box-sizing:border-box;background:#fff;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;left:0}.layui-colorpicker-main-alpha{display:none;height:12px;margin-top:7px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-alpha-bgcolor{height:100%;position:relative}.layui-colorpicker-alpha-slider{width:5px;height:100%;box-shadow:0 0 1px #888;box-sizing:border-box;background:#fff;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;top:0}.layui-colorpicker-main-pre{padding-top:7px;font-size:0}.layui-colorpicker-pre{width:20px;height:20px;border-radius:2px;display:inline-block;margin-left:6px;margin-bottom:7px;cursor:pointer}.layui-colorpicker-pre:nth-child(11n+1){margin-left:0}.layui-colorpicker-pre-isalpha{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-pre.layui-this{box-shadow:0 0 3px 2px rgba(0,0,0,.15)}.layui-colorpicker-pre>div{height:100%;border-radius:2px}.layui-colorpicker-main-input{text-align:right;padding-top:7px}.layui-colorpicker-main-input .layui-btn-container .layui-btn{margin:0 0 0 10px}.layui-colorpicker-main-input div.layui-inline{float:left;margin-right:10px;font-size:14px}.layui-colorpicker-main-input input.layui-input{width:150px;height:30px;color:#5f5f5f}.layui-slider{height:4px;background:#eee;border-radius:3px;position:relative;cursor:pointer}.layui-slider-bar{border-radius:3px;position:absolute;height:100%}.layui-slider-step{position:absolute;top:0;width:4px;height:4px;border-radius:50%;background:#fff;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.layui-slider-wrap{width:36px;height:36px;position:absolute;top:-16px;-webkit-transform:translateX(-50%);transform:translateX(-50%);z-index:10;text-align:center}.layui-slider-wrap-btn{width:12px;height:12px;border-radius:50%;background:#fff;display:inline-block;vertical-align:middle;cursor:pointer;transition:.3s}.layui-slider-wrap:after{content:"";height:100%;display:inline-block;vertical-align:middle}.layui-slider-wrap-btn.layui-slider-hover,.layui-slider-wrap-btn:hover{transform:scale(1.2)}.layui-slider-wrap-btn.layui-disabled:hover{transform:scale(1)!important}.layui-slider-tips{position:absolute;top:-42px;z-index:77777777;white-space:nowrap;display:none;-webkit-transform:translateX(-50%);transform:translateX(-50%);color:#fff;background:#000;border-radius:3px;height:25px;line-height:25px;padding:0 10px}.layui-slider-tips:after{content:"";position:absolute;bottom:-12px;left:50%;margin-left:-6px;width:0;height:0;border-width:6px;border-style:solid;border-color:#000 transparent transparent transparent}.layui-slider-input{width:70px;height:32px;border:1px solid #eee;border-radius:3px;font-size:16px;line-height:32px;position:absolute;right:0;top:-14px;box-sizing:border-box}.layui-slider-input-btn{position:absolute;top:0;right:0;width:20px;height:100%;border-left:1px solid #eee}.layui-slider-input-btn i{cursor:pointer;position:absolute;right:0;bottom:0;width:20px;height:50%;font-size:12px;line-height:16px;text-align:center;color:#999}.layui-slider-input-btn i:first-child{top:0;border-bottom:1px solid #eee}.layui-slider-input-txt{height:100%;font-size:14px}.layui-slider-input-txt input{height:100%;border:none;padding-right:21px}.layui-slider-input-btn i:hover{color:#16baaa}.layui-slider-vertical{width:4px;margin-left:33px}.layui-slider-vertical .layui-slider-bar{width:4px}.layui-slider-vertical .layui-slider-step{top:auto;left:0;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-wrap{top:auto;left:-16px;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-tips{top:auto;left:2px}@media \0screen{.layui-slider-wrap-btn{margin-left:-20px}.layui-slider-vertical .layui-slider-wrap-btn{margin-left:0;margin-bottom:-20px}.layui-slider-vertical .layui-slider-tips{margin-left:-8px}.layui-slider>span{margin-left:8px}}.layui-tree{line-height:22px}.layui-tree .layui-form-checkbox{margin:0!important}.layui-tree-set{width:100%;position:relative}.layui-tree-pack{display:none;padding-left:20px;position:relative}.layui-tree-line .layui-tree-pack{padding-left:27px}.layui-tree-line .layui-tree-set .layui-tree-set:after{content:"";position:absolute;top:14px;left:-9px;width:17px;height:0;border-top:1px dotted #c0c4cc}.layui-tree-entry{position:relative;padding:3px 0;height:20px;white-space:nowrap}.layui-tree-entry:hover{background-color:#eee}.layui-tree-line .layui-tree-entry:hover{background-color:rgba(0,0,0,0)}.layui-tree-line .layui-tree-entry:hover .layui-tree-txt{color:#999;text-decoration:underline;transition:.3s}.layui-tree-main{display:inline-block;vertical-align:middle;cursor:pointer;padding-right:10px}.layui-tree-line .layui-tree-set:before{content:"";position:absolute;top:0;left:-9px;width:0;height:100%;border-left:1px dotted #c0c4cc}.layui-tree-line .layui-tree-set.layui-tree-setLineShort:before{height:13px}.layui-tree-line .layui-tree-set.layui-tree-setHide:before{height:0}.layui-tree-iconClick{display:inline-block;vertical-align:middle;position:relative;height:20px;line-height:20px;margin:0 10px;color:#c0c4cc}.layui-tree-icon{height:12px;line-height:12px;width:12px;text-align:center;border:1px solid #c0c4cc}.layui-tree-iconClick .layui-icon{font-size:18px}.layui-tree-icon .layui-icon{font-size:12px;color:#5f5f5f}.layui-tree-iconArrow{padding:0 5px}.layui-tree-iconArrow:after{content:"";position:absolute;left:4px;top:3px;z-index:100;width:0;height:0;border-width:5px;border-style:solid;border-color:transparent transparent transparent #c0c4cc;transition:.5s}.layui-tree-spread>.layui-tree-entry .layui-tree-iconClick>.layui-tree-iconArrow:after{transform:rotate(90deg) translate(3px,4px)}.layui-tree-txt{display:inline-block;vertical-align:middle;color:#555}.layui-tree-search{margin-bottom:15px;color:#5f5f5f}.layui-tree-btnGroup{visibility:hidden;display:inline-block;vertical-align:middle;position:relative}.layui-tree-btnGroup .layui-icon{display:inline-block;vertical-align:middle;padding:0 2px;cursor:pointer}.layui-tree-btnGroup .layui-icon:hover{color:#999;transition:.3s}.layui-tree-entry:hover .layui-tree-btnGroup{visibility:visible}.layui-tree-editInput{position:relative;display:inline-block;vertical-align:middle;height:20px;line-height:20px;padding:0 3px;border:none;background-color:rgba(0,0,0,.05)}.layui-tree-emptyText{text-align:center;color:#999}.layui-anim{-webkit-animation-duration:.3s;-webkit-animation-fill-mode:both;animation-duration:.3s;animation-fill-mode:both}.layui-anim.layui-icon{display:inline-block}.layui-anim-loop{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.layui-trans,.layui-trans a{transition:all .2s;-webkit-transition:all .2s}@-webkit-keyframes layui-rotate{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes layui-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}.layui-anim-rotate{-webkit-animation-name:layui-rotate;animation-name:layui-rotate;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes layui-up{from{-webkit-transform:translate3d(0,100%,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-up{from{transform:translate3d(0,100%,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-up{-webkit-animation-name:layui-up;animation-name:layui-up}@-webkit-keyframes layui-upbit{from{-webkit-transform:translate3d(0,15px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-upbit{from{transform:translate3d(0,15px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-upbit{-webkit-animation-name:layui-upbit;animation-name:layui-upbit}@keyframes layui-down{0%{opacity:.3;transform:translate3d(0,-100%,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-anim-down{animation-name:layui-down}@keyframes layui-downbit{0%{opacity:.3;transform:translate3d(0,-5px,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-anim-downbit{animation-name:layui-downbit}@-webkit-keyframes layui-scale{0%{opacity:.3;-webkit-transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale{0%{opacity:.3;-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scale{-webkit-animation-name:layui-scale;animation-name:layui-scale}@-webkit-keyframes layui-scale-spring{0%{opacity:.5;-webkit-transform:scale(.5)}80%{opacity:.8;-webkit-transform:scale(1.1)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale-spring{0%{opacity:.5;transform:scale(.5)}80%{opacity:.8;transform:scale(1.1)}100%{opacity:1;transform:scale(1)}}.layui-anim-scaleSpring{-webkit-animation-name:layui-scale-spring;animation-name:layui-scale-spring}@keyframes layui-scalesmall{0%{opacity:.3;transform:scale(1.5)}100%{opacity:1;transform:scale(1)}}.layui-anim-scalesmall{animation-name:layui-scalesmall}@keyframes layui-scalesmall-spring{0%{opacity:.3;transform:scale(1.5)}80%{opacity:.8;transform:scale(.9)}100%{opacity:1;transform:scale(1)}}.layui-anim-scalesmall-spring{animation-name:layui-scalesmall-spring}@-webkit-keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}@keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}.layui-anim-fadein{-webkit-animation-name:layui-fadein;animation-name:layui-fadein}@-webkit-keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}@keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}.layui-anim-fadeout{-webkit-animation-name:layui-fadeout;animation-name:layui-fadeout}html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-view{display:block;position:relative;margin:11px 0;padding:0;border:1px solid #eee;border-left-width:6px;background-color:#fafafa;color:#333;font-family:Courier New;font-size:13px}.layui-code-title{position:relative;padding:0 10px;height:40px;line-height:40px;border-bottom:1px solid #eee;font-size:12px}.layui-code-title>.layui-code-about{position:absolute;right:10px;top:0;color:#b7b7b7}.layui-code-about>a{padding-left:10px}.layui-code-view>.layui-code-ol,.layui-code-view>.layui-code-ul{max-height:100%;padding:0!important;position:relative;overflow:auto}.layui-code-view>.layui-code-ol>li{position:relative;margin-top:0!important;margin-left:45px!important;line-height:20px;padding:0 10px!important;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view>.layui-code-ol>li:first-child,.layui-code-view>.layui-code-ul>li:first-child{padding-top:10px!important}.layui-code-view>.layui-code-ol>li:last-child,.layui-code-view>.layui-code-ul>li:last-child{padding-bottom:10px!important}.layui-code-view>.layui-code-ul>li{position:relative;line-height:20px;padding:0 10px!important;list-style-type:none;*list-style-type:none;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-dark{border:1px solid #0c0c0c;border-left-color:#3f3f3f;background-color:#0c0c0c;color:#c2be9e}.layui-code-dark>.layui-code-title{border-bottom:none}.layui-code-dark>.layui-code-ol>li,.layui-code-dark>.layui-code-ul>li{background-color:#3f3f3f;border-left:none}.layui-code-dark>.layui-code-ul>li{margin-left:6px}.layui-code textarea{display:none}.layui-code-preview>.layui-code{margin:0}.layui-code-preview>.layui-tab{position:relative;z-index:1;margin-bottom:0}.layui-code-preview>.layui-tab>.layui-tab-title{border-bottom:none}.layui-code-preview>.layui-code>.layui-code-title{display:none}.layui-code-preview .layui-code-item{display:none}.layui-code-item-preview{position:relative;padding:16px}.layui-code-item-preview>iframe{position:absolute;top:0;left:0;width:100%;height:100%;border:none}.layui-code-tools{position:absolute;right:11px;top:3px}.layui-code-tools>i{display:inline-block;margin-left:6px;padding:3px;cursor:pointer}.layui-code-tools>i.layui-icon-file-b{color:#999}.layui-code-tools>i:hover{color:#16b777}.layui-code-copy{position:absolute;right:6px;top:6px;cursor:pointer;display:none}.layui-code-copy .layui-icon{color:#777;transition:all .3s}.layui-code-copy:hover .layui-icon{color:#16b777}.layui-code-view:hover>.layui-code-copy{display:block}.layui-code-copy-offset{margin-right:17px}.layui-code-preview>.layui-code-view>.layui-code-copy{display:none!important}.layui-code-full{position:fixed;left:0;top:0;z-index:1111111;width:100%;height:100%;background-color:#fff}.layui-code-full .layui-code-item{width:100%!important;border-width:0!important;border-top-width:1px!important}.layui-code-full .layui-code-item,.layui-code-full .layui-code-ol,.layui-code-full .layui-code-ul{height:calc(100vh - 51px)!important;box-sizing:border-box}html #layuicss-laydate{display:none;position:absolute;width:1989px}.layui-laydate *{margin:0;padding:0}.layui-laydate,.layui-laydate *{box-sizing:border-box}.layui-laydate{position:absolute;z-index:99999999;margin:5px 0;border-radius:2px;font-size:14px;line-height:normal;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-laydate-main{width:272px}.layui-laydate-content td,.layui-laydate-header *,.layui-laydate-list li{transition-duration:.3s;-webkit-transition-duration:.3s}.layui-laydate-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px");position:fixed;_position:absolute;pointer-events:auto}@keyframes laydate-downbit{0%{opacity:.3;transform:translate3d(0,-5px,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-laydate{animation-name:laydate-downbit}.layui-laydate-static{position:relative;z-index:0;display:inline-block;margin:0;-webkit-animation:none;animation:none}.laydate-ym-show .laydate-next-m,.laydate-ym-show .laydate-prev-m{display:none!important}.laydate-ym-show .laydate-next-y,.laydate-ym-show .laydate-prev-y{display:inline-block!important}.laydate-ym-show .laydate-set-ym span[lay-type=month]{display:none!important}.laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-time-show .layui-laydate-header .layui-icon{display:none!important}.layui-laydate-header{position:relative;line-height:30px;padding:10px 70px 5px}.layui-laydate-header *{display:inline-block;vertical-align:bottom}.layui-laydate-header i{position:absolute;top:10px;padding:0 5px;color:#999;font-size:18px;cursor:pointer}.layui-laydate-header i.laydate-prev-y{left:15px}.layui-laydate-header i.laydate-prev-m{left:45px}.layui-laydate-header i.laydate-next-y{right:15px}.layui-laydate-header i.laydate-next-m{right:45px}.laydate-set-ym{width:100%;text-align:center;box-sizing:border-box;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate-set-ym span{padding:0 10px;cursor:pointer}.laydate-time-text{cursor:default!important}.layui-laydate-content{position:relative;padding:10px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content table{border-collapse:collapse;border-spacing:0}.layui-laydate-content td,.layui-laydate-content th{width:36px;height:30px;padding:0;text-align:center}.layui-laydate-content th{font-weight:400}.layui-laydate-content td{position:relative;cursor:pointer}.laydate-day-mark{position:absolute;left:0;top:0;width:100%;line-height:30px;font-size:12px;overflow:hidden}.laydate-day-mark::after{position:absolute;content:'';right:2px;top:2px;width:5px;height:5px;border-radius:50%}.laydate-day-holidays:before{position:absolute;left:0;top:0;font-size:12px;transform:scale(.7)}.laydate-day-holidays:before{content:'\4F11';color:#ff5722}.laydate-day-holidays[type=work]:before{content:'\73ED';color:inherit}.layui-laydate .layui-this .laydate-day-holidays:before{color:#fff}.layui-laydate-footer{position:relative;height:46px;line-height:26px;padding:10px}.layui-laydate-footer span{display:inline-block;vertical-align:top;height:26px;line-height:24px;padding:0 10px;border:1px solid #c9c9c9;border-radius:2px;background-color:#fff;font-size:12px;cursor:pointer;white-space:nowrap;transition:all .3s}.layui-laydate-footer span:hover{color:#16b777}.layui-laydate-footer span.layui-laydate-preview{cursor:default;border-color:transparent!important}.layui-laydate-footer span.layui-laydate-preview:hover{color:#777}.layui-laydate-footer span:first-child.layui-laydate-preview{padding-left:0}.laydate-footer-btns{position:absolute;right:10px;top:10px}.laydate-footer-btns span{margin:0 0 0 -1px;border-radius:0}.laydate-footer-btns span:first-child{border-radius:2px 0 0 2px}.laydate-footer-btns span:last-child{border-radius:0 2px 2px 0}.layui-laydate-shortcut{width:80px;padding:6px 0;display:inline-block;vertical-align:top;overflow:auto;max-height:276px;text-align:center}.layui-laydate-shortcut+.layui-laydate-main{display:inline-block;border-left:1px solid #e2e2e2}.layui-laydate-shortcut>li{padding:5px 8px;cursor:pointer;line-height:18px}.layui-laydate .layui-laydate-list{position:absolute;left:0;top:0;width:100%;height:100%;padding:10px;box-sizing:border-box;background-color:#fff}.layui-laydate .layui-laydate-list>li{position:relative;display:inline-block;width:33.3%;height:36px;line-height:36px;margin:3px 0;vertical-align:middle;text-align:center;cursor:pointer;list-style:none}.layui-laydate .laydate-month-list>li{width:25%;margin:17px 0}.layui-laydate .laydate-time-list>li{height:100%;margin:0;line-height:normal;cursor:default}.layui-laydate .laydate-time-list p{position:relative;top:-4px;margin:0;line-height:29px}.layui-laydate .laydate-time-list ol{height:181px;overflow:hidden}.layui-laydate .laydate-time-list>li:hover ol{overflow-y:auto}.layui-laydate .laydate-time-list ol li{width:130%;padding-left:33px;height:30px;line-height:30px;text-align:left;cursor:pointer}.layui-laydate-hint{position:absolute;top:115px;left:50%;width:250px;margin-left:-125px;line-height:20px;padding:15px;text-align:center;font-size:12px;color:#ff5722}.layui-laydate-range{width:546px}.layui-laydate-range .layui-laydate-main{display:inline-block;vertical-align:middle;max-width:50%}.layui-laydate-range .laydate-main-list-1 .layui-laydate-content,.layui-laydate-range .laydate-main-list-1 .layui-laydate-header{border-left:1px solid #e2e2e2}.layui-laydate-range.layui-laydate-linkage .laydate-main-list-0 .laydate-next-m,.layui-laydate-range.layui-laydate-linkage .laydate-main-list-0 .laydate-next-y,.layui-laydate-range.layui-laydate-linkage .laydate-main-list-1 .laydate-prev-m,.layui-laydate-range.layui-laydate-linkage .laydate-main-list-1 .laydate-prev-y{display:none}.layui-laydate,.layui-laydate-hint{border:1px solid #d2d2d2;box-shadow:0 2px 4px rgba(0,0,0,.12);background-color:#fff;color:#777}.layui-laydate-header{border-bottom:1px solid #e2e2e2}.layui-laydate-header i:hover,.layui-laydate-header span:hover{color:#16b777}.layui-laydate-content{border-top:none 0;border-bottom:none 0}.layui-laydate-content th{color:#333}.layui-laydate-content td{color:#777}.layui-laydate-content td.laydate-day-now{color:#16b777}.layui-laydate-content td.laydate-day-now:after{content:'';position:absolute;width:100%;height:30px;left:0;top:0;border:1px solid #16b777;box-sizing:border-box}.layui-laydate-linkage .layui-laydate-content td.laydate-selected>div{background-color:#00f7de}.layui-laydate-linkage .laydate-selected:hover>div{background-color:#00f7de!important}.layui-laydate-content td.laydate-selected:after,.layui-laydate-content td:hover:after{content:none}.layui-laydate-content td>div:hover,.layui-laydate-list li:hover,.layui-laydate-shortcut>li:hover{background-color:#eee;color:#333}.laydate-time-list li ol{margin:0;padding:0;border:1px solid #e2e2e2;border-left-width:0}.laydate-time-list li:first-child ol{border-left-width:1px}.laydate-time-list>li:hover{background:0 0}.layui-laydate-content .laydate-day-next,.layui-laydate-content .laydate-day-prev{color:#d2d2d2}.layui-laydate-linkage .laydate-selected.laydate-day-next>div,.layui-laydate-linkage .laydate-selected.laydate-day-prev>div{background-color:#f8f8f8!important}.layui-laydate-footer{border-top:1px solid #e2e2e2}.layui-laydate-hint{color:#ff5722}.laydate-day-mark::after{background-color:#16b777}.layui-laydate-content td.layui-this .laydate-day-mark::after{display:none}.layui-laydate-footer span[lay-type=date]{color:#16b777}.layui-laydate .layui-this,.layui-laydate .layui-this>div{background-color:#16baaa!important;color:#fff!important}.layui-laydate .laydate-disabled,.layui-laydate .laydate-disabled:hover{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content td>div{padding:7px 0;height:100%}.laydate-theme-molv{border:none}.laydate-theme-molv.layui-laydate-range{width:548px}.laydate-theme-molv .layui-laydate-main{width:274px}.laydate-theme-molv .layui-laydate-header{border:none;background-color:#16baaa}.laydate-theme-molv .layui-laydate-header i,.laydate-theme-molv .layui-laydate-header span{color:#f6f6f6}.laydate-theme-molv .layui-laydate-header i:hover,.laydate-theme-molv .layui-laydate-header span:hover{color:#fff}.laydate-theme-molv .layui-laydate-content{border:1px solid #e2e2e2;border-top:none;border-bottom:none}.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content{border-left:none}.laydate-theme-molv .layui-laydate-footer{border:1px solid #e2e2e2}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li,.laydate-theme-grid .layui-laydate-content td,.laydate-theme-grid .layui-laydate-content thead{border:1px solid #e2e2e2}.layui-laydate-linkage.laydate-theme-grid .laydate-selected,.layui-laydate-linkage.laydate-theme-grid .laydate-selected:hover{background-color:#f2f2f2!important;color:#16baaa!important}.layui-laydate-linkage.laydate-theme-grid .laydate-selected.laydate-day-next,.layui-laydate-linkage.laydate-theme-grid .laydate-selected.laydate-day-prev{color:#d2d2d2!important}.laydate-theme-grid .laydate-month-list,.laydate-theme-grid .laydate-year-list{margin:1px 0 0 1px}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li{margin:0 -1px -1px 0}.laydate-theme-grid .laydate-year-list>li{height:43px;line-height:43px}.laydate-theme-grid .laydate-month-list>li{height:71px;line-height:71px}.laydate-theme-grid .layui-laydate-content td>div{height:29px;margin-top:-1px}.laydate-theme-circle .layui-laydate-content td.layui-this>div,.laydate-theme-circle .layui-laydate-content td>div{width:28px;height:28px;line-height:28px;border-radius:14px;margin:0 4px;padding:0}.layui-laydate.laydate-theme-circle .layui-laydate-content table td.layui-this{background-color:transparent!important}.laydate-theme-grid.laydate-theme-circle .layui-laydate-content td>div{margin:0 3.5px}.laydate-theme-fullpanel .layui-laydate-main{width:526px}.laydate-theme-fullpanel .layui-laydate-list{width:252px;left:272px}.laydate-theme-fullpanel .laydate-set-ym span{display:none}.laydate-theme-fullpanel .laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-theme-fullpanel .laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-theme-fullpanel .laydate-time-show .layui-laydate-header .layui-icon{display:inline-block!important}.laydate-theme-fullpanel .laydate-btns-time{display:none}html #layuicss-layer{display:none;position:absolute;width:1989px}.layui-layer,.layui-layer-shade{position:fixed;_position:absolute;pointer-events:auto}.layui-layer-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px")}.layui-layer{-webkit-overflow-scrolling:touch}.layui-layer{top:150px;left:0;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;border-radius:2px;box-shadow:1px 1px 50px rgba(0,0,0,.3)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #b2b2b2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-btn a,.layui-layer-setwin span{display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-move{display:none;position:fixed;*position:absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layer-anim{-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-00{-webkit-animation-name:layer-bounceIn;animation-name:layer-bounceIn}@-webkit-keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:layer-zoomInDown;animation-name:layer-zoomInDown}@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}@-webkit-keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:layer-zoomInLeft;animation-name:layer-zoomInLeft}@-webkit-keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}@keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);-ms-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}.layer-anim-04{-webkit-animation-name:layer-rollIn;animation-name:layer-rollIn}@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}@-webkit-keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layer-anim-06{-webkit-animation-name:layer-shake;animation-name:layer-shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes layer-slide-down{from{transform:translate3d(0,-100%,0)}to{transform:translate3d(0,0,0)}}@keyframes layer-slide-down-out{from{transform:translate3d(0,0,0)}to{transform:translate3d(0,-100%,0)}}.layer-anim-slide-down{animation-name:layer-slide-down}.layer-anim-slide-down-out{animation-name:layer-slide-down-out}@keyframes layer-slide-left{from{transform:translate3d(100%,0,0)}to{transform:translate3d(0,0,0)}}@keyframes layer-slide-left-out{from{transform:translate3d(0,0,0)}to{transform:translate3d(100%,0,0)}}.layer-anim-slide-left{animation-name:layer-slide-left}.layer-anim-slide-left-out{animation-name:layer-slide-left-out}@keyframes layer-slide-up{from{transform:translate3d(0,100%,0)}to{transform:translate3d(0,0,0)}}@keyframes layer-slide-up-out{from{transform:translate3d(0,0,0)}to{transform:translate3d(0,100%,0)}}.layer-anim-slide-up{animation-name:layer-slide-up}.layer-anim-slide-up-out{animation-name:layer-slide-up-out}@keyframes layer-slide-right{from{transform:translate3d(-100%,0,0)}to{transform:translate3d(0,0,0)}}@keyframes layer-slide-right-out{from{transform:translate3d(0,0,0)}to{transform:translate3d(-100%,0,0)}}.layer-anim-slide-right{animation-name:layer-slide-right}.layer-anim-slide-right-out{animation-name:layer-slide-right-out}.layui-layer-title{padding:0 81px 0 16px;height:50px;line-height:50px;border-bottom:1px solid #f0f0f0;font-size:14px;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:2px 2px 0 0}.layui-layer-setwin{position:absolute;right:15px;*right:0;top:16px;font-size:0;line-height:initial}.layui-layer-setwin span{position:relative;width:16px;height:16px;line-height:18px;margin-left:10px;text-align:center;font-size:16px;cursor:pointer;color:#000;_overflow:hidden}.layui-layer-setwin .layui-layer-min:before{content:'';position:absolute;width:12px;height:1px;left:50%;top:50%;margin:-.5px 0 0 -6px;background-color:#2e2d3c;cursor:pointer;_overflow:hidden}.layui-layer-setwin .layui-layer-min:hover:before{background-color:#2d93ca}.layui-layer-setwin .layui-layer-max:after,.layui-layer-setwin .layui-layer-max:before{content:'';position:absolute;left:50%;top:50%;z-index:1;width:9px;height:9px;margin:-5px 0 0 -5px;border:1px solid #2e2d3c}.layui-layer-setwin .layui-layer-max:hover:after,.layui-layer-setwin .layui-layer-max:hover:before{border-color:#2d93ca}.layui-layer-setwin .layui-layer-min:hover:before{background-color:#2d93ca}.layui-layer-setwin .layui-layer-maxmin:after,.layui-layer-setwin .layui-layer-maxmin:before{width:7px;height:7px;margin:-3px 0 0 -3px;background-color:#fff}.layui-layer-setwin .layui-layer-maxmin:after{z-index:0;margin:-5px 0 0 -1px}.layui-layer-setwin .layui-layer-close{cursor:pointer}.layui-layer-setwin .layui-layer-close:hover{opacity:.7}.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;color:#fff;background-color:#787878;padding:3px;border:3px solid;width:18px;height:18px;font-size:18px;font-weight:bolder;border-radius:50%;margin-left:0;*right:-18px;_display:none}.layui-layer-setwin .layui-layer-close2:hover{opacity:unset;background-color:#3888f6}.layui-layer-btn{text-align:right;padding:0 15px 12px;pointer-events:auto;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:28px;line-height:28px;margin:5px 5px 0;padding:0 15px;border:1px solid #dedede;background-color:#fff;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none}.layui-layer-btn a:hover{opacity:.9;text-decoration:none}.layui-layer-btn a:active{opacity:.8}.layui-layer-btn .layui-layer-btn0{border-color:#1e9fff;background-color:#1e9fff;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.layui-layer-dialog{min-width:240px}.layui-layer-dialog .layui-layer-content{position:relative;padding:16px;line-height:24px;word-break:break-all;overflow:hidden;font-size:14px;overflow-x:hidden;overflow-y:auto}.layui-layer-dialog .layui-layer-content .layui-layer-face{position:absolute;top:18px;left:16px;color:#959595;font-size:32px;_left:-40px}.layui-layer-dialog .layui-layer-content .layui-icon-tips{color:#f39b12}.layui-layer-dialog .layui-layer-content .layui-icon-success{color:#16b777}.layui-layer-dialog .layui-layer-content .layui-icon-error{top:19px;color:#ff5722}.layui-layer-dialog .layui-layer-content .layui-icon-question{color:#ffb800}.layui-layer-dialog .layui-layer-content .layui-icon-lock{color:#787878}.layui-layer-dialog .layui-layer-content .layui-icon-face-cry{color:#ff5722}.layui-layer-dialog .layui-layer-content .layui-icon-face-smile{color:#16b777}.layui-layer-rim{border:6px solid #8d8d8d;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #d3d4d3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:rgba(0,0,0,.6);color:#fff;border:none}.layui-layer-hui .layui-layer-close{color:#fff}.layui-layer-hui .layui-layer-content{padding:11px 24px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:18px 24px 18px 58px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-iframe .layui-layer-btn,.layui-layer-page .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:0 0}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:0 0;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:76px;height:38px;line-height:38px;text-align:center}.layui-layer-loading-icon{font-size:38px;color:#959595}.layui-layer-loading2{text-align:center}.layui-layer-loading-2{position:relative;height:38px}.layui-layer-loading-2:after,.layui-layer-loading-2:before{content:'';position:absolute;left:50%;top:50%;width:38px;height:38px;margin:-19px 0 0 -19px;border-radius:50%;border:3px solid #d2d2d2;box-sizing:border-box}.layui-layer-loading-2:after{border-color:transparent;border-left-color:#1e9fff}.layui-layer-tips{background:0 0;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:8px 15px;font-size:12px;_float:left;border-radius:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow:hidden}.layui-layer-tips i.layui-layer-TipsB,.layui-layer-tips i.layui-layer-TipsT{left:5px;border-right-style:solid;border-right-color:#000}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layui-layer-TipsB{top:-8px}.layui-layer-tips i.layui-layer-TipsL,.layui-layer-tips i.layui-layer-TipsR{top:5px;border-bottom-style:solid;border-bottom-color:#000}.layui-layer-tips i.layui-layer-TipsR{left:-8px}.layui-layer-tips i.layui-layer-TipsL{right:-8px}.layui-layer-lan .layui-layer-title{background:#4476a7;color:#fff;border:none}.layui-layer-lan .layui-layer-btn{padding:5px 10px 10px;border-top:1px solid #e9e7e7}.layui-layer-lan .layui-layer-btn a{background:#fff;border-color:#e9e7e7;color:#333}.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#c9c5c5}.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}.layui-layer-molv .layui-layer-btn a{background:#009f95;border-color:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92b8b1}.layui-layer-lan .layui-layer-setwin .layui-icon,.layui-layer-molv .layui-layer-setwin .layui-icon{color:#fff}.layui-layer-win10{border:1px solid #aaa;box-shadow:1px 1px 6px rgba(0,0,0,.3);border-radius:none}.layui-layer-win10 .layui-layer-title{height:32px;line-height:32px;padding-left:8px;border-bottom:none;font-size:12px}.layui-layer-win10 .layui-layer-setwin{right:0;top:0}.layui-layer-win10 .layui-layer-setwin span{margin-left:0;padding:8px}.layui-layer-win10.layui-layer-page .layui-layer-setwin span{padding:8px 11px}.layui-layer-win10 .layui-layer-setwin span:hover{background-color:#e5e5e5}.layui-layer-win10 .layui-layer-setwin span.layui-icon-close:hover{background-color:#e81123;color:#fff}.layui-layer-win10.layui-layer-dialog .layui-layer-content{padding:8px 16px 32px;color:#0033bc}.layui-layer-win10.layui-layer-dialog .layui-layer-padding{padding-top:18px;padding-left:58px}.layui-layer-win10 .layui-layer-btn{padding:5px 5px 10px;border-top:1px solid #dfdfdf;background-color:#f0f0f0}.layui-layer-win10 .layui-layer-btn a{height:18px;line-height:18px;background-color:#e1e1e1;border-color:#adadad;color:#000;font-size:12px;transition:all .3s}.layui-layer-win10 .layui-layer-btn a:hover{border-color:#2a8edd;background-color:#e5f1fb}.layui-layer-win10 .layui-layer-btn .layui-layer-btn0{border-color:#0078d7}.layui-layer-prompt .layui-layer-input{display:block;width:260px;height:36px;margin:0 auto;line-height:30px;padding-left:10px;border:1px solid #e6e6e6;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px;padding:6px 10px}.layui-layer-prompt .layui-layer-content{padding:16px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;display:inline-block;vertical-align:top;border-left:1px solid transparent;border-right:1px solid transparent;min-width:80px;max-width:300px;padding:0 16px;text-align:center;cursor:default;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;cursor:pointer}.layui-layer-tab .layui-layer-title span.layui-this{height:51px;border-left-color:#eee;border-right-color:#eee;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left-color:transparent}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.layui-this{display:block}.layui-layer-photos{background:0 0;box-shadow:none}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-imgnext,.layui-layer-imgprev{position:fixed;top:50%;width:52px;height:52px;line-height:52px;margin-top:-26px;cursor:pointer;font-size:52px;color:#717171}.layui-layer-imgprev{left:32px}.layui-layer-imgnext{right:32px}.layui-layer-imgnext:hover,.layui-layer-imgprev:hover{color:#959595}.layui-layer-imgbar{position:fixed;left:0;right:0;bottom:0;width:100%;height:40px;line-height:40px;background-color:#000\9;filter:Alpha(opacity=60);background-color:rgba(2,0,0,.35);color:#fff;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;font-size:0}.layui-layer-imgtit *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;padding:0 5px;font-size:12px;color:#fff}.layui-layer-imgtit h3{max-width:65%;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;font-weight:300}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{font-style:normal}@-webkit-keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:layer-bounceOut;animation-name:layer-bounceOut;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.eot b/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..3f5e98bb584b80ae0ce0d39b598fb37423ea8220 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.eot differ diff --git a/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.svg b/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.svg new file mode 100644 index 0000000000000000000000000000000000000000..4f1920deddba24bdb57bdc74a8abcc160f4d960f --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.svg @@ -0,0 +1,405 @@ + + + + Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.ttf b/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6e84a89e031247509801ae5d65cc8d20323cb766 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.ttf differ diff --git a/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.woff b/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..acd7ed6082729ae968e44aa9f676cd50a37e8eb6 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.woff differ diff --git a/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.woff2 b/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..5badd6e38ec077cd5b50da3d41f029f7534be086 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/layui/font/iconfont.woff2 differ diff --git a/demo/webman/backend/plugin/admin/public/component/layui/layui.js b/demo/webman/backend/plugin/admin/public/component/layui/layui.js new file mode 100644 index 0000000000000000000000000000000000000000..9bdd7d01111152e45a997ad98553d779bc1f9a5c --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/layui/layui.js @@ -0,0 +1 @@ +/** v2.8.12 | MIT Licensed */;!function(d){"use strict";var t,h=d.document,m={modules:{},status:{},timeout:10,event:{}},o=function(){this.v="2.8.12"},e=d.LAYUI_GLOBAL||{},v=(t=h.currentScript?h.currentScript.src:function(){for(var t,e=h.scripts,n=e.length-1,o=n;01e3*m.timeout/4?g(u+" is not a valid module","error"):void(m.status[u]?c():setTimeout(o,4))}())}function c(){e.push(layui[u]),11e3*m.timeout/4?g(u+" is not a valid module","error"):void("string"==typeof m.modules[u]&&m.status[u]?c():setTimeout(f,4))}():((p=h.createElement("script"))["async"]=!0,p.charset="utf-8",p.src=y+((i=!0===m.version?m.v||(new Date).getTime():m.version||"")?"?v="+i:""),a.appendChild(p),!p.attachEvent||p.attachEvent.toString&&p.attachEvent.toString().indexOf("[native code")<0||b?p.addEventListener("load",function(t){s(t,y)},!1):p.attachEvent("onreadystatechange",function(t){s(t,y)}),m.modules[u]=y),r},o.prototype.disuse=function(t){var n=this;return t=n.isArray(t)?t:[t],n.each(t,function(t,e){m.status[e],delete n[e],delete N[e],delete n.modules[e],delete m.status[e],delete m.modules[e]}),n},o.prototype.getStyle=function(t,e){t=t.currentStyle||d.getComputedStyle(t,null);return t[t.getPropertyValue?"getPropertyValue":"getAttribute"](e)},o.prototype.link=function(n,o,t){var r=this,e=h.getElementsByTagName("head")[0],i=h.createElement("link"),a="layuicss-"+((t="string"==typeof o?o:t)||n).replace(/\.|\//g,""),u="creating",l=0;return i.href=n+(m.debug?"?v="+(new Date).getTime():""),i.rel="stylesheet",i.id=a,i.media="all",h.getElementById(a)||e.appendChild(i),"function"!=typeof o||function s(t){var e=h.getElementById(a);return++l>1e3*m.timeout/100?g(n+" timeout"):void(1989===parseInt(r.getStyle(e,"width"))?(t===u&&e.removeAttribute("lay-status"),e.getAttribute("lay-status")===u?setTimeout(s,100):o()):(e.setAttribute("lay-status",u),setTimeout(function(){s(u)},100)))}(),r},o.prototype.addcss=function(t,e,n){return layui.link(m.dir+"css/"+t,e,n)},m.callback={},o.prototype.factory=function(t){if(layui[t])return"function"==typeof m.callback[t]?m.callback[t]:null},o.prototype.img=function(t,e,n){var o=new Image;if(o.src=t,o.complete)return e(o);o.onload=function(){o.onload=null,"function"==typeof e&&e(o)},o.onerror=function(t){o.onerror=null,"function"==typeof n&&n(t)}},o.prototype.config=function(t){for(var e in t=t||{})m[e]=t[e];return this},o.prototype.modules=function(){var t,e={};for(t in N)e[t]=N[t];return e}(),o.prototype.extend=function(t){for(var e in t=t||{})this[e]||this.modules[e]?g(e+" Module already exists","error"):this.modules[e]=t[e];return this},o.prototype.router=o.prototype.hash=function(t){var n={path:[],search:{},hash:((t=t||location.hash).match(/[^#](#.*$)/)||[])[1]||""};return/^#\//.test(t)&&(t=t.replace(/^#\//,""),n.href="/"+t,t=t.replace(/([^#])(#.*$)/,"$1").split("/")||[],this.each(t,function(t,e){/^\w+=/.test(e)?(e=e.split("="),n.search[e[0]]=e[1]):n.path.push(e)})),n},o.prototype.url=function(t){var r,e,n=this;return{pathname:(t?((t.match(/\.[^.]+?\/.+/)||[])[0]||"").replace(/^[^\/]+/,"").replace(/\?.+/,""):location.pathname).replace(/^\//,"").split("/"),search:(r={},e=(t?((t.match(/\?.+/)||[])[0]||"").replace(/\#.+/,""):location.search).replace(/^\?+/,"").split("&"),n.each(e,function(t,e){var n=e.indexOf("="),o=n<0?e.substr(0,e.length):0!==n&&e.substr(0,n);o&&(r[o]=0(s.innerHeight||l.documentElement.clientHeight)},h.position=function(t,e,n){var i,r,o,c,u,a,f;e&&(n=n||{},t!==l&&t!==h("body")[0]||(n.clickType="right"),u="right"===n.clickType?{left:(u=n.e||s.event||{}).clientX,top:u.clientY,right:u.clientX,bottom:u.clientY}:t.getBoundingClientRect(),a=e.offsetWidth,f=e.offsetHeight,i=function(t){return l.body[t=t?"scrollLeft":"scrollTop"]|l.documentElement[t]},o=u.left,c=u.bottom,"center"===n.align?o-=(a-t.offsetWidth)/2:"right"===n.align&&(o=o-a+t.offsetWidth),(o=o+a+5>(r=function(t){return l.documentElement[t?"clientWidth":"clientHeight"]})("width")?r("width")-a-5:o)<5&&(o=5),c+f+5>r()&&(u.top>f+5?c=u.top-f-10:"right"===n.clickType?(c=r()-f-10)<0&&(c=0):c=5),(a=n.position)&&(e.style.position=a),e.style.left=o+("fixed"===a?0:i(1))+"px",e.style.top=c+("fixed"===a?0:i())+"px",h.hasScrollbar()||(f=e.getBoundingClientRect(),!n.SYSTEM_RELOAD&&f.bottom+5>r()&&(n.SYSTEM_RELOAD=!0,setTimeout(function(){h.position(t,e,n)},50))))},h.options=function(t,e){if(e="object"==typeof e?e:{attr:e},t===l)return{};var t=h(t),n=e.attr||"lay-options",t=t.attr(n);try{return new Function("return "+(t||"{}"))()}catch(i){return layui.hint().error(e.errorText||[n+'="'+t+'"',"\n parseerror: "+i].join("\n"),"error"),{}}},h.isTopElem=function(n){var t=[l,h("body")[0]],i=!1;return h.each(t,function(t,e){if(e===n)return i=!0}),i},r.addStr=function(n,t){return n=n.replace(/\s+/," "),t=t.replace(/\s+/," ").split(" "),h.each(t,function(t,e){new RegExp("\\b"+e+"\\b").test(n)||(n=n+" "+e)}),n.replace(/^\s|\s$/,"")},r.removeStr=function(n,t){return n=n.replace(/\s+/," "),t=t.replace(/\s+/," ").split(" "),h.each(t,function(t,e){e=new RegExp("\\b"+e+"\\b");e.test(n)&&(n=n.replace(e,""))}),n.replace(/\s+/," ").replace(/^\s|\s$/,"")},r.fn.find=function(n){var i=[],r="object"==typeof n;return this.each(function(t,e){e=r&&e.contains(n)?n:e.querySelectorAll(n||null);h.each(e,function(t,e){i.push(e)})}),h(i)},r.fn.each=function(t){return h.each.call(this,this,t)},r.fn.addClass=function(n,i){return this.each(function(t,e){e.className=r[i?"removeStr":"addStr"](e.className,n)})},r.fn.removeClass=function(t){return this.addClass(t,!0)},r.fn.hasClass=function(n){var i=!1;return this.each(function(t,e){new RegExp("\\b"+n+"\\b").test(e.className)&&(i=!0)}),i},r.fn.css=function(e,i){var t=this,r=function(t){return isNaN(t)?t:t+"px"};return"string"!=typeof e||i!==undefined?t.each(function(t,n){"object"==typeof e?h.each(e,function(t,e){n.style[t]=r(e)}):n.style[e]=r(i)}):0]|&(?=#[a-zA-Z0-9]+)/g.test(e+="")?e.replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,"""):e}},i=function(e){return new RegExp(e,"g")},u=function(e,r){var n="Laytpl Error: ";return"object"==typeof console&&console.error(n+e+"\n"+(r||"")),n+e},n=function(e,r){var n=this,e=(n.config=n.config||{},n.template=e,function(e){for(var r in e)n.config[r]=e[r]});e(c),e(r)},r=(n.prototype.tagExp=function(e,r,n){var c=this.config;return i((r||"")+c.open+["#([\\s\\S])+?","([^{#}])*?"][e||0]+c.close+(n||""))},n.prototype.parse=function(e,r){var n=this,c=n.config,t=e,o=i("^"+c.open+"#",""),p=i(c.close+"$","");if("string"!=typeof e)return e;e='"use strict";var view = "'+(e=e.replace(/\s+|\r|\t|\n/g," ").replace(i(c.open+"#"),c.open+"# ").replace(i(c.close+"}"),"} "+c.close).replace(/\\/g,"\\\\").replace(i(c.open+"!(.+?)!"+c.close),function(e){return e=e.replace(i("^"+c.open+"!"),"").replace(i("!"+c.close),"").replace(i(c.open+"|"+c.close),function(e){return e.replace(/(.)/g,"\\$1")})}).replace(/(?="|')/g,"\\").replace(n.tagExp(),function(e){return'";'+(e=e.replace(o,"").replace(p,"")).replace(/\\(.)/g,"$1")+';view+="'}).replace(n.tagExp(1),function(e){var r='"+laytpl.escape(';return e.replace(/\s/g,"")===c.open+c.close?"":(e=e.replace(i(c.open+"|"+c.close),""),/^=/.test(e)?e=e.replace(/^=/,""):/^-/.test(e)&&(e=e.replace(/^-/,""),r='"+('),r+e.replace(/\\(.)/g,"$1")+')+"')}))+'";return view;';try{return n.cache=e=new Function("d, laytpl",e),e(r,l)}catch(a){return delete n.cache,u(a,t)}},n.prototype.render=function(e,r){e=e||{};var n=this,e=n.cache?n.cache(e,l):n.parse(n.template,e);return"function"==typeof r&&r(e),e},function(e,r){return new n(e,r)});r.config=function(e){for(var r in e=e||{})c[r]=e[r]},r.v="2.0.0",e("laytpl",r)});layui.define(function(e){"use strict";var r=document,u="getElementById",c="getElementsByTagName",a="layui-disabled",t=function(e){var a=this;a.config=e||{},a.config.index=++o.index,a.render(!0)},o=(t.prototype.type=function(){var e=this.config;if("object"==typeof e.elem)return e.elem.length===undefined?2:3},t.prototype.view=function(){var t,i,n=this.config,r=n.groups="groups"in n?Number(n.groups)||0:5,u=(n.layout="object"==typeof n.layout?n.layout:["prev","page","next"],n.count=Number(n.count)||0,n.curr=Number(n.curr)||1,n.limits="object"==typeof n.limits?n.limits:[10,20,30,40,50],n.limit=Number(n.limit)||10,n.pages=Math.ceil(n.count/n.limit)||1,n.curr>n.pages?n.curr=n.pages:n.curr<1&&(n.curr=1),r<0?r=1:r>n.pages&&(r=n.pages),n.prev="prev"in n?n.prev:"上一页",n.next="next"in n?n.next:"下一页",n.pages>r?Math.ceil((n.curr+(1'+n.prev+"":"",page:function(){var e=[];if(n.count<1)return"";1'+(n.first||1)+"");var a=Math.floor((r-1)/2),t=1n.pages?n.pages:a:r;for(i-t…');t<=i;t++)t===n.curr?e.push('"+t+""):e.push(''+t+"");return n.pages>r&&n.pages>i&&!1!==n.last&&(i+1…'),0!==r&&e.push(''+(n.last||n.pages)+"")),e.join("")}(),next:n.next?''+n.next+"":"",count:'\u5171 '+n.count+" \u6761",limit:(t=['"),refresh:['','',""].join(""),skip:['到第','','页',""].join("")};return['
                                                              ',(i=[],layui.each(n.layout,function(e,a){l[a]&&i.push(l[a])}),i.join("")),"
                                                              "].join("")},t.prototype.jump=function(e,a){if(e){var t=this,i=t.config,n=e.children,r=e[c]("button")[0],u=e[c]("input")[0],e=e[c]("select")[0],l=function(){var e=Number(u.value.replace(/\s|\D/g,""));e&&(i.curr=e,t.render())};if(a)return l();for(var s=0,p=n.length;si.pages||(i.curr=e,t.render())});e&&o.on(e,"change",function(){var e=this.value;i.curr*e>i.count&&(i.curr=Math.ceil(i.count/e)),i.limit=e,t.render()}),r&&o.on(r,"click",function(){l()})}},t.prototype.skip=function(t){var i,e;t&&(i=this,(e=t[c]("input")[0])&&o.on(e,"keyup",function(e){var a=this.value,e=e.keyCode;/^(37|38|39|40)$/.test(e)||(/\D/.test(a)&&(this.value=a.replace(/\D/,"")),13===e&&i.jump(t,!0))}))},t.prototype.render=function(e){var a=this,t=a.config,i=a.type(),n=a.view(),i=(2===i?t.elem&&(t.elem.innerHTML=n):3===i?t.elem.html(n):r[u](t.elem)&&(r[u](t.elem).innerHTML=n),t.jump&&t.jump(t,e),r[u]("layui-laypage-"+t.index));a.jump(i),t.hash&&!e&&(location.hash="!"+t.hash+"="+t.curr),a.skip(i)},{render:function(e){return new t(e).index},index:layui.laypage?layui.laypage.index+1e4:0,on:function(a,e,t){return a.attachEvent?a.attachEvent("on"+e,function(e){e.target=e.srcElement,t.call(a,e)}):a.addEventListener(e,t,!1),this}});e("laypage",o)});!function(i,v){"use strict";var n=i.layui&&layui.define,l={getPath:i.lay&&lay.getPath?lay.getPath:"",link:function(e,t,a){D.path&&i.lay&&lay.layui&&lay.layui.link(D.path+e,t,a)}},e=i.LAYUI_GLOBAL||{},d="layui-laydate-id",D={v:"5.5.0",config:{weekStart:0},index:i.laydate&&i.laydate.v?1e5:0,path:e.laydate_dir||l.getPath,set:function(e){var t=this;return t.config=lay.extend({},t.config,e),t},ready:function(e){var t="laydate",a=(n?"modules/":"")+"laydate.css?v="+D.v;return n?layui["layui.all"]?"function"==typeof e&&e():layui.addcss(a,e,t):l.link(a,e,t),this}},s=function(){var t=this,e=t.config.id;return(s.that[e]=t).inst={hint:function(e){t.hint.call(t,e)},reload:function(e){t.reload.call(t,e)},config:t.config}},a="laydate",x="layui-this",k="laydate-disabled",h=[100,2e5],T="layui-laydate-static",w="layui-laydate-list",o="laydate-selected",r="layui-laydate-hint",y="laydate-day-prev",m="laydate-day-next",C=".laydate-btns-confirm",M="laydate-time-text",L="laydate-btns-time",E="layui-laydate-preview",S="layui-laydate-shade",I=function(e){var t,a=this,n=(a.index=++D.index,a.config=lay.extend({},a.config,D.config,e),lay(e.elem||a.config.elem));return 1\u8bf7\u91cd\u65b0\u9009\u62e9",invalidDate:"\u4e0d\u5728\u6709\u6548\u65e5\u671f\u6216\u65f6\u95f4\u8303\u56f4\u5185",formatError:["\u65e5\u671f\u683c\u5f0f\u4e0d\u5408\u6cd5
                                                              \u5fc5\u987b\u9075\u5faa\u4e0b\u8ff0\u683c\u5f0f\uff1a
                                                              ","
                                                              \u5df2\u4e3a\u4f60\u91cd\u7f6e"],preview:"\u5f53\u524d\u9009\u4e2d\u7684\u7ed3\u679c"},en:{weeks:["Su","Mo","Tu","We","Th","Fr","Sa"],time:["Hours","Minutes","Seconds"],timeTips:"Select Time",startTime:"Start Time",endTime:"End Time",dateTips:"Select Date",month:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],tools:{confirm:"Confirm",clear:"Clear",now:"Now"},timeout:"End time cannot be less than start Time
                                                              Please re-select",invalidDate:"Invalid date",formatError:["The date format error
                                                              Must be followed\uff1a
                                                              ","
                                                              It has been reset"],preview:"The selected result"}};return e[this.config.lang]||e.cn},I.prototype.reload=function(e){this.config=lay.extend({},this.config,e),this.init()},I.prototype.init=function(){var r=this,o=r.config,e="static"===o.position,t={year:"yyyy",month:"yyyy-MM",date:"yyyy-MM-dd",time:"HH:mm:ss",datetime:"yyyy-MM-dd HH:mm:ss"};o.elem=lay(o.elem),o.eventElem=lay(o.eventElem),o.elem[0]&&("array"!==layui.type(o.theme)&&(o.theme=[o.theme]),o.fullPanel&&("datetime"!==o.type||o.range)&&delete o.fullPanel,r.rangeStr=o.range?"string"==typeof o.range?o.range:"-":"",r.rangeLinked=!(!o.range||!o.rangeLinked||"date"!==o.type&&"datetime"!==o.type),r.autoCalendarModel=function(){var e=r.rangeLinked;return r.rangeLinked=o.range&&("date"===o.type||"datetime"===o.type)&&(!r.startDate||!r.endDate||r.startDate&&r.endDate&&r.startDate.year===r.endDate.year&&r.startDate.month===r.endDate.month),lay(r.elem)[r.rangeLinked?"addClass":"removeClass"]("layui-laydate-linkage"),r.rangeLinked!=e},r.autoCalendarModel.auto=r.rangeLinked&&"auto"===o.rangeLinked,"array"===layui.type(o.range)&&(r.rangeElem=[lay(o.range[0]),lay(o.range[1])]),t[o.type]||(i.console&&console.error&&console.error("laydate type error:'"+o.type+"' is not supported"),o.type="date"),o.format===t.date&&(o.format=t[o.type]||t.date),r.format=s.formatArr(o.format),o.weekStart&&!/^[0-6]$/.test(o.weekStart)&&(t=r.lang(),o.weekStart=t.weeks.indexOf(o.weekStart),-1===o.weekStart&&(o.weekStart=0)),r.EXP_IF="",r.EXP_SPLIT="",lay.each(r.format,function(e,t){e=new RegExp(c).test(t)?"\\d{"+(new RegExp(c).test(r.format[0===e?e+1:e-1]||"")?/^yyyy|y$/.test(t)?4:t.length:/^yyyy$/.test(t)?"1,4":/^y$/.test(t)?"1,308":"1,2")+"}":"\\"+t;r.EXP_IF=r.EXP_IF+e,r.EXP_SPLIT=r.EXP_SPLIT+"("+e+")"}),r.EXP_IF_ONE=new RegExp("^"+r.EXP_IF+"$"),r.EXP_IF=new RegExp("^"+(o.range?r.EXP_IF+"\\s\\"+r.rangeStr+"\\s"+r.EXP_IF:r.EXP_IF)+"$"),r.EXP_SPLIT=new RegExp("^"+r.EXP_SPLIT+"$",""),r.isInput(o.elem[0])||"focus"===o.trigger&&(o.trigger="click"),o.elem.attr("lay-key",r.index),o.eventElem.attr("lay-key",r.index),o.elem.attr(d,o.id),o.mark=lay.extend({},o.calendar&&"cn"===o.lang?{"0-1-1":"\u5143\u65e6","0-2-14":"\u60c5\u4eba","0-3-8":"\u5987\u5973","0-3-12":"\u690d\u6811","0-4-1":"\u611a\u4eba","0-5-1":"\u52b3\u52a8","0-5-4":"\u9752\u5e74","0-6-1":"\u513f\u7ae5","0-9-10":"\u6559\u5e08","0-10-1":"\u56fd\u5e86","0-12-25":"\u5723\u8bde"}:{},o.mark),lay.each(["min","max"],function(e,t){var a=[],n=[];if("number"==typeof o[t])var i=o[t],l=new Date,l=r.newDate({year:l.getFullYear(),month:l.getMonth(),date:l.getDate(),hours:e?23:0,minutes:e?59:0,seconds:e?59:0}).getTime(),e=new Date(i?i<864e5?l+864e5*i:i:l),a=[e.getFullYear(),e.getMonth()+1,e.getDate()],n=[e.getHours(),e.getMinutes(),e.getSeconds()];else if("string"==typeof o[t])a=(o[t].match(/\d+-\d+-\d+/)||[""])[0].split("-"),n=(o[t].match(/\d+:\d+:\d+/)||[""])[0].split(":");else if("object"==typeof o[t])return o[t];o[t]={year:0|a[0]||(new Date).getFullYear(),month:a[1]?(0|a[1])-1:(new Date).getMonth(),date:0|a[2]||(new Date).getDate(),hours:0|n[0],minutes:0|n[1],seconds:0|n[2]}}),r.elemID="layui-laydate"+o.elem.attr("lay-key"),(o.show||e)&&r.render(),e||r.events(),o.value&&o.isInitValue&&("date"===layui.type(o.value)?r.setValue(r.parse(0,r.systemDate(o.value))):r.setValue(o.value)))},I.prototype.render=function(){var a,n,i,l,r=this,o=r.config,d=r.lang(),s="static"===o.position,y=r.elem=lay.elem("div",{id:r.elemID,"class":["layui-laydate",o.range?" layui-laydate-range":"",r.rangeLinked?" layui-laydate-linkage":"",s?" "+T:"",o.fullPanel?" laydate-theme-fullpanel":"",(a="",lay.each(o.theme,function(e,t){"default"===t||/^#/.test(t)||(a+=" laydate-theme-"+t)}),a)].join("")}),m=r.elemMain=[],c=r.elemHeader=[],u=r.elemCont=[],h=r.table=[],e=r.footer=lay.elem("div",{"class":"layui-laydate-footer"}),t=r.shortcut=lay.elem("ul",{"class":"layui-laydate-shortcut"}),f=(o.zIndex&&(y.style.zIndex=o.zIndex),lay.each(new Array(2),function(e){if(!o.range&&0'+d.timeTips+""),(o.range||"datetime"!==o.type||o.fullPanel)&&f.push(''),lay.each(o.btns,function(e,t){var a=d.tools[t]||"btn";o.range&&"now"===t||(s&&"clear"===t&&(a="cn"===o.lang?"\u91cd\u7f6e":"Reset"),n.push(''+a+""))}),f.push('"),f.join(""))),o.shortcuts&&(y.appendChild(t),lay(t).html((i=[],lay.each(o.shortcuts,function(e,t){i.push('
                                                            • '+t.text+"
                                                            • ")}),i.join(""))).find("li").on("click",function(e){var t=(o.shortcuts[this.dataset.index]||{}).value||[],n=(layui.isArray(t)||(t=[t]),o.type),t=(lay.each(t,function(e,t){var a=[o.dateTime,r.endDate][e];"time"===n&&"date"!==layui.type(t)?r.EXP_IF.test(t)&&(t=(t.match(r.EXP_SPLIT)||[]).slice(1),lay.extend(a,{hours:0|t[0],minutes:0|t[2],seconds:0|t[4]})):lay.extend(a,r.systemDate("date"===layui.type(t)?t:new Date(t))),"time"!==n&&"datetime"!==n||(r[["startTime","endTime"][e]]={hours:a.hours,minutes:a.minutes,seconds:a.seconds}),0===e?r.startDate=lay.extend({},a):r.endState=!0,"year"===n||"month"===n||"time"===n?r.listYM[e]=[a.year,a.month+1]:e&&r.autoCalendarModel.auto&&r.autoCalendarModel()}),r.checkDate("limit").calendar(null,null,"init"),lay(r.footer).find("."+L).removeClass(k));t&&"date"===t.attr("lay-type")&&t[0].click(),r.done(null,"change"),lay(this).addClass(x),"static"!==o.position&&r.setValue(r.parse()).done().remove()})),lay.each(m,function(e,t){y.appendChild(t)}),o.showBottom&&y.appendChild(e),lay.elem("style")),p=[],g=!0,t=(lay.each(o.theme,function(e,t){if(g&&/^#/.test(t))return g=!(l=!0),void p.push(["#{{id}} .layui-laydate-header{background-color:{{theme}};}","#{{id}} li.layui-this,#{{id}} td.layui-this>div{background-color:{{theme}} !important;}",-1!==o.theme.indexOf("circle")?"":"#{{id}} .layui-this{background-color:{{theme}} !important;}","#{{id}} .laydate-day-now{color:{{theme}} !important;}","#{{id}} .laydate-day-now:after{border-color:{{theme}} !important;}"].join("").replace(/{{id}}/g,r.elemID).replace(/{{theme}}/g,t));!g&&/^#/.test(t)&&p.push(["#{{id}} .laydate-selected>div{background-color:{{theme}} !important;}","#{{id}} .laydate-selected:hover>div{background-color:{{theme}} !important;}"].join("").replace(/{{id}}/g,r.elemID).replace(/{{theme}}/g,t))}),o.shortcuts&&o.range&&p.push("#{{id}}.layui-laydate-range{width: 628px;}".replace(/{{id}}/g,r.elemID)),p.length&&(p=p.join(""),"styleSheet"in f?(f.setAttribute("type","text/css"),f.styleSheet.cssText=p):f.innerHTML=p,l&&lay(y).addClass("laydate-theme-molv"),y.appendChild(f)),r.remove(I.thisElemDate),D.thisId=o.id,s?o.elem.append(y):(v.body.appendChild(y),r.position()),o.shade?'
                                                              ':"");y.insertAdjacentHTML("beforebegin",t),r.checkDate().calendar(null,0,"init"),r.changeEvent(),I.thisElemDate=r.elemID,r.renderAdditional(),"function"==typeof o.ready&&o.ready(lay.extend({},o.dateTime,{month:o.dateTime.month+1})),r.preview()},I.prototype.remove=function(e){var t=this,a=t.config,n=lay("#"+(e||t.elemID));return n[0]&&(n.hasClass(T)||t.checkDate(function(){n.remove(),delete t.startDate,delete t.endDate,delete t.endState,delete t.startTime,delete t.endTime,delete D.thisId,"function"==typeof a.close&&a.close(t)}),lay("."+S).remove()),t},I.prototype.position=function(){var e=this.config;return lay.position(e.elem[0],this.elem,{position:e.position}),this},I.prototype.hint=function(e){var t=this,a=(t.config,lay.elem("div",{"class":r}));t.elem&&(a.innerHTML=(e="object"==typeof e?e||{}:{content:e}).content||"",lay(t.elem).find("."+r).remove(),t.elem.appendChild(a),clearTimeout(t.hinTimer),t.hinTimer=setTimeout(function(){lay(t.elem).find("."+r).remove()},"ms"in e?e.ms:3e3))},I.prototype.getAsYM=function(e,t,a){return a?t--:t++,t<0&&(t=11,e--),11h[1]&&(e.year=h[1],o=!0),11t&&(e.date=t,o=!0))},r=function(n,i,l){var r=["startTime","endTime"];i=(i.match(d.EXP_SPLIT)||[]).slice(1),l=l||0,s.range&&(d[r[l]]=d[r[l]]||{}),lay.each(d.format,function(e,t){var a=parseFloat(i[e]);i[e].lengthd.getDateTime(s.max)?(n=s.dateTime=lay.extend({},s.max),c=!0):d.getDateTime(n)d.getDateTime(s.max))&&(d.endDate=lay.extend({},s.max),c=!0),d.startTime={hours:s.dateTime.hours,minutes:s.dateTime.minutes,seconds:s.dateTime.seconds},d.endTime={hours:d.endDate.hours,minutes:d.endDate.minutes,seconds:d.endDate.seconds},"month"===s.type&&(s.dateTime.date=1,d.endDate.date=1)),c&&l&&(d.setValue(d.parse()),d.hint("value "+a.invalidDate+a.formatError[1])),d.startDate=d.startDate||l&&lay.extend({},s.dateTime),d.autoCalendarModel.auto&&d.autoCalendarModel(),d.endState=!s.range||!d.rangeLinked||!(!d.startDate||!d.endDate),e&&e(),d},I.prototype.mark=function(e,a){var n,t=this.config;return lay.each(t.mark,function(e,t){e=e.split("-");e[0]!=a[0]&&0!=e[0]||e[1]!=a[1]&&0!=e[1]||e[2]!=a[2]||(n=t||a[2])}),n&&e.find("div").html(''+n+""),this},I.prototype.holidays=function(n,i){var e=this.config,l=["","work"];return"array"!==layui.type(e.holidays)||lay.each(e.holidays,function(a,e){lay.each(e,function(e,t){t===n.attr("lay-ymd")&&n.find("div").html('"+i[2]+"")})}),this},I.prototype.limit=function(t){t=t||{};var i=this,e=i.config,l={},a=t.index>(t.time?0:41)?i.endDate:e.dateTime;return lay.each({now:lay.extend({},a,t.date||{}),min:e.min,max:e.max},function(e,a){var n;l[e]=i.newDate(lay.extend({year:a.year,month:"year"===t.type?0:a.month,date:"year"===t.type||"month"===t.type?1:a.date},(n={},lay.each(t.time,function(e,t){n[t]=a[t]}),n))).getTime()}),a=l.nowl.max,t.elem&&t.elem[a?"addClass":"removeClass"](k),a},I.prototype.thisDateTime=function(e){var t=this.config;return e?this.endDate:t.dateTime},I.prototype.calendar=function(e,t,a){var i,l,r,o=this,n=o.config,t=t?1:0,d=e||o.thisDateTime(t),s=new Date,y=o.lang(),m="date"!==n.type&&"datetime"!==n.type,c=lay(o.table[t]).find("td"),u=lay(o.elemHeader[t][2]).find("span");return d.yearh[1]&&(d.year=h[1],o.hint(y.invalidDate)),o.firstDate||(o.firstDate=lay.extend({},d)),s.setFullYear(d.year,d.month,1),i=(s.getDay()+(7-n.weekStart))%7,l=D.getEndDate(d.month||12,d.year),r=D.getEndDate(d.month+1,d.year),lay.each(c,function(e,t){var a=[d.year,d.month],n=0;(t=lay(t)).removeAttr("class"),e"+a[2]+""),o.mark(t,a).holidays(t,a).limit({elem:t,date:{year:a[0],month:a[1]-1,date:a[2]},index:e})}),lay(u[0]).attr("lay-ym",d.year+"-"+(d.month+1)),lay(u[1]).attr("lay-ym",d.year+"-"+(d.month+1)),"cn"===n.lang?(lay(u[0]).attr("lay-type","year").html(d.year+" \u5e74"),lay(u[1]).attr("lay-type","month").html(d.month+1+" \u6708")):(lay(u[0]).attr("lay-type","month").html(y.month[d.month]),lay(u[1]).attr("lay-type","year").html(d.year)),m&&(n.range?!e&&"init"===a||(o.listYM=[[(o.startDate||n.dateTime).year,(o.startDate||n.dateTime).month+1],[o.endDate.year,o.endDate.month+1]],o.list(n.type,0).list(n.type,1),"time"===n.type?o.setBtnStatus("\u65f6\u95f4",lay.extend({},o.systemDate(),o.startTime),lay.extend({},o.systemDate(),o.endTime)):o.setBtnStatus(!0)):(o.listYM=[[d.year,d.month+1]],o.list(n.type,0))),n.range&&"init"===a&&(o.rangeLinked?(s=o.getAsYM(d.year,d.month,t?"sub":null),o.calendar(lay.extend({},d,{year:s[0],month:s[1]}),1-t)):o.calendar(null,1-t)),n.range||(c=["hours","minutes","seconds"],o.limit({elem:lay(o.footer).find(".laydate-btns-now"),date:o.systemDate(),index:0,time:c}),o.limit({elem:lay(o.footer).find(C),index:0,time:c})),o.setBtnStatus(),lay(o.shortcut).find("li."+x).removeClass(x),n.range&&!m&&"init"!==a&&o.stampRange(),o},I.prototype.list=function(n,i){var l,r,e,o,d=this,s=d.config,y=d.rangeLinked?s.dateTime:[s.dateTime,d.endDate][i],m=d.lang(),t=s.range&&"date"!==s.type&&"datetime"!==s.type,c=lay.elem("ul",{"class":w+" "+{year:"laydate-year-list",month:"laydate-month-list",time:"laydate-time-list"}[n]}),a=d.elemHeader[i],u=lay(a[2]).find("span"),h=d.elemCont[i||0],f=lay(h).find("."+w)[0],p="cn"===s.lang,g=p?"\u5e74":"",v=d.listYM[i]||{},D=["hours","minutes","seconds"],T=["startTime","endTime"][i];return v[0]<1&&(v[0]=1),"year"===n?(e=l=v[0]-7,l<1&&(e=l=1),lay.each(new Array(15),function(e){var t=lay.elem("li",{"lay-ym":l}),a={year:l,month:0,date:1};l==v[0]&&lay(t).addClass(x),t.innerHTML=l+g,c.appendChild(t),d.limit({elem:lay(t),date:a,index:i,type:n}),l++}),lay(u[p?0:1]).attr("lay-ym",l-8+"-"+v[1]).html(e+g+" - "+(l-1)+g)):"month"===n?(lay.each(new Array(12),function(e){var t=lay.elem("li",{"lay-ym":e}),a={year:v[0],month:e,date:1};e+1==v[1]&&lay(t).addClass(x),t.innerHTML=m.month[e]+(p?"\u6708":""),c.appendChild(t),d.limit({elem:lay(t),date:a,index:i,type:n})}),lay(u[p?0:1]).attr("lay-ym",v[0]+"-"+v[1]).html(v[0]+g)):"time"===n&&(r=function(){lay(c).find("ol").each(function(a,e){lay(e).find("li").each(function(e,t){d.limit({elem:lay(t),date:[{hours:e},{hours:d[T].hours,minutes:e},{hours:d[T].hours,minutes:d[T].minutes,seconds:e}][a],index:i,time:[["hours"],["hours","minutes"],["hours","minutes","seconds"]][a]})})}),s.range||d.limit({elem:lay(d.footer).find(C),date:d[T],inedx:0,time:["hours","minutes","seconds"]})},s.range?d[T]||(d[T]="startTime"===T?y:d.endDate):d[T]=y,lay.each([24,60,60],function(t,e){var a=lay.elem("li"),n=["

                                                              "+m.time[t]+"

                                                                "];lay.each(new Array(e),function(e){n.push(""+lay.digit(e,2)+"")}),a.innerHTML=n.join("")+"
                                                              ",c.appendChild(a)}),r()),f&&h.removeChild(f),h.appendChild(c),"year"===n||"month"===n?(lay(d.elemMain[i]).addClass("laydate-ym-show"),lay(c).find("li").on("click",function(){var e=0|lay(this).attr("lay-ym");lay(this).hasClass(k)||(d.rangeLinked?lay.extend(y,{year:"year"===n?e:v[0],month:"year"===n?v[1]-1:e}):y[n]=e,"year"===s.type||"month"===s.type?(lay(c).find("."+x).removeClass(x),lay(this).addClass(x),"month"===s.type&&"year"===n&&(d.listYM[i][0]=e,t&&((i?d.endDate:y).year=e),d.list("month",i))):(d.checkDate("limit").calendar(y,i,"init"),d.closeList()),d.setBtnStatus(),!s.range&&s.autoConfirm&&("month"===s.type&&"month"===n||"year"===s.type&&"year"===n)&&d.setValue(d.parse()).done().remove(),d.autoCalendarModel.auto&&!d.rangeLinked?d.choose(lay(h).find("td.layui-this"),i):d.endState&&d.done(null,"change"),lay(d.footer).find("."+L).removeClass(k))})):(e=lay.elem("span",{"class":M}),o=function(){lay(c).find("ol").each(function(e){var a=this,t=lay(a).find("li");a.scrollTop=30*(d[T][D[e]]-2),a.scrollTop<=0&&t.each(function(e,t){if(!lay(this).hasClass(k))return a.scrollTop=30*(e-2),!0})})},u=lay(a[2]).find("."+M),o(),e.innerHTML=s.range?[m.startTime,m.endTime][i]:m.timeTips,lay(d.elemMain[i]).addClass("laydate-time-show"),u[0]&&u.remove(),a[2].appendChild(e),lay(c).find("ol").each(function(t){var a=this;lay(a).find("li").on("click",function(){var e=0|this.innerHTML;lay(this).hasClass(k)||(s.range?d[T][D[t]]=e:y[D[t]]=e,lay(a).find("."+x).removeClass(x),lay(this).addClass(x),r(),o(),(d.endDate||"time"===s.type||"datetime"===s.type&&s.fullPanel)&&d.done(null,"change"),d.setBtnStatus())})})),d},I.prototype.listYM=[],I.prototype.closeList=function(){var a=this;a.config;lay.each(a.elemCont,function(e,t){lay(this).find("."+w).remove(),lay(a.elemMain[e]).removeClass("laydate-ym-show laydate-time-show")}),lay(a.elem).find("."+M).remove()},I.prototype.setBtnStatus=function(e,t,a){var n=this,i=n.config,l=n.lang(),r=lay(n.footer).find(C);i.range&&"time"!==i.type&&(t=t||(n.rangeLinked?n.startDate:i.dateTime),a=a||n.endDate,i=!n.endState||n.newDate(t).getTime()>n.newDate(a).getTime(),n.limit({date:t})||n.limit({date:a})?r.addClass(k):r[i?"addClass":"removeClass"](k),e&&i&&n.hint("string"==typeof e?l.timeout.replace(/\u65e5\u671f/g,e):l.timeout))},I.prototype.parse=function(e,t){var a=this,n=a.config,t=t||("end"==e?lay.extend({},a.endDate,a.endTime):n.range?lay.extend({},a.rangeLinked?a.startDate:n.dateTime,a.startTime):n.dateTime),t=D.parse(t,a.format,1);return n.range&&e===undefined?t+" "+a.rangeStr+" "+a.parse("end"):t},I.prototype.newDate=function(e){return e=e||{},new Date(e.year||1,e.month||0,e.date||1,e.hours||0,e.minutes||0,e.seconds||0)},I.prototype.getDateTime=function(e){return this.newDate(e).getTime()},I.prototype.setValue=function(e){var t=this,a=t.config,n=a.elem[0];return"static"===a.position||(e=e||"",t.isInput(n)?lay(n).val(e):(a=t.rangeElem)?("array"!==layui.type(e)&&(e=e.split(" "+t.rangeStr+" ")),a[0].val(e[0]||""),a[1].val(e[1]||"")):(0===lay(n).find("*").length&&lay(n).html(e),lay(n).attr("lay-date",e))),t},I.prototype.preview=function(){var e,t=this,a=t.config;a.isPreview&&(e=lay(t.elem).find("."+E),a=!a.range||(t.rangeLinked?t.endState:t.endDate)?t.parse():"",e.html(a),e.html()&&(e.css({color:"#16b777"}),setTimeout(function(){e.css({color:"#777"})},300)))},I.prototype.renderAdditional=function(){this.config.fullPanel&&this.list("time",0)},I.prototype.stampRange=function(){var n,i=this,l=i.config,r=i.rangeLinked?i.startDate:l.dateTime,e=lay(i.elem).find("td");l.range&&!i.endState&&lay(i.footer).find(C).addClass(k),r=r&&i.newDate({year:r.year,month:r.month,date:r.date}).getTime(),n=i.endState&&i.endDate&&i.newDate({year:i.endDate.year,month:i.endDate.month,date:i.endDate.date}).getTime(),lay.each(e,function(e,t){var a=lay(t).attr("lay-ymd").split("-"),a=i.newDate({year:a[0],month:a[1]-1,date:a[2]}).getTime();l.rangeLinked&&!i.startDate&&a===i.newDate(i.systemDate()).getTime()&&lay(t).addClass(lay(t).hasClass(y)||lay(t).hasClass(m)?"":"laydate-day-now"),lay(t).removeClass(o+" "+x),a!==r&&a!==n||(i.rangeLinked||!i.rangeLinked&&(e<42?a===r:a===n))&&lay(t).addClass(lay(t).hasClass(y)||lay(t).hasClass(m)?o:x),rn.getDateTime(i.max)&&(n[t]={hours:i.max.hours,minutes:i.max.minutes,seconds:i.max.seconds},lay.extend(l,n[t])))}),a||(n.startDate=lay.extend({},l)),n.endState&&!n.limit({date:n.thisDateTime(1-a)})&&(((r=n.endState&&n.autoCalendarModel.auto?n.autoCalendarModel():r)||n.rangeLinked&&n.endState)&&n.newDate(n.startDate)>n.newDate(n.endDate)&&(e=n.startDate.year===n.endDate.year&&n.startDate.month===n.endDate.month&&n.startDate.date===n.endDate.date,o=n.startDate,n.startDate=lay.extend({},n.endDate,e?{}:n.startTime),i.dateTime=lay.extend({},n.startDate),n.endDate=lay.extend({},o,e?{}:n.endTime),e&&(o=n.startTime,n.startTime=n.endTime,n.endTime=o)),r&&(i.dateTime=lay.extend({},n.startDate))),n.rangeLinked?(e=lay.extend({},l),!t||a||r||(o=n.getAsYM(l.year,l.month,"sub"),lay.extend(i.dateTime,{year:o[0],month:o[1]})),n.calendar(e,t,r?"init":null)):n.calendar(null,a,r?"init":null),n.endState&&n.done(null,"change")):"static"===i.position?n.calendar().done().done(null,"change"):"date"===i.type?i.autoConfirm?n.setValue(n.parse()).done().remove():n.calendar().done(null,"change"):"datetime"===i.type&&n.calendar().done(null,"change"))},I.prototype.tool=function(t,e){var a=this,n=a.config,i=a.lang(),l=n.dateTime,r="static"===n.position,o={datetime:function(){lay(t).hasClass(k)||(a.list("time",0),n.range&&a.list("time",1),lay(t).attr("lay-type","date").html(a.lang().dateTips))},date:function(){a.closeList(),lay(t).attr("lay-type","datetime").html(a.lang().timeTips)},clear:function(){r&&(lay.extend(l,a.firstDate),a.calendar()),n.range&&(delete n.dateTime,delete a.endDate,delete a.startTime,delete a.endTime),a.setValue(""),a.done(null,"onClear").done(["",{},{}]).remove()},now:function(){var e=new Date;if(lay(t).hasClass(k))return a.hint(i.tools.now+", "+i.invalidDate);lay.extend(l,a.systemDate(),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()}),a.setValue(a.parse()),r&&a.calendar(),a.done(null,"onNow").done().remove()},confirm:function(){if(n.range){if(lay(t).hasClass(k))return a.hint("time"===n.type?i.timeout.replace(/\u65e5\u671f/g,"\u65f6\u95f4"):i.timeout)}else if(lay(t).hasClass(k))return a.hint(i.invalidDate);a.setValue(a.parse()),a.done(null,"onConfirm").done().remove()}};o[e]&&o[e]()},I.prototype.change=function(n){var i=this,l=i.config,r=i.thisDateTime(n),o=l.range&&("year"===l.type||"month"===l.type),d=i.elemCont[n||0],s=i.listYM[n],e=function(e){var t=lay(d).find(".laydate-year-list")[0],a=lay(d).find(".laydate-month-list")[0];return t&&(s[0]=e?s[0]-15:s[0]+15,i.list("year",n)),a&&(e?s[0]--:s[0]++,i.list("month",n)),(t||a)&&(lay.extend(r,{year:s[0]}),o&&(r.year=s[0]),l.range||i.done(null,"change"),l.range||i.limit({elem:lay(i.footer).find(C),date:{year:s[0]}})),i.setBtnStatus(),t||a};return{prevYear:function(){e("sub")||(i.rangeLinked?(l.dateTime.year--,i.checkDate("limit").calendar(null,null,"init")):(r.year--,i.checkDate("limit").calendar(null,n),i.autoCalendarModel.auto?i.choose(lay(d).find("td.layui-this"),n):i.done(null,"change")))},prevMonth:function(){i.rangeLinked&&(r=l.dateTime);var e=i.getAsYM(r.year,r.month,"sub");lay.extend(r,{year:e[0],month:e[1]}),i.checkDate("limit").calendar(null,null,"init"),i.rangeLinked||(i.autoCalendarModel.auto?i.choose(lay(d).find("td.layui-this"),n):i.done(null,"change"))},nextMonth:function(){i.rangeLinked&&(r=l.dateTime);var e=i.getAsYM(r.year,r.month);lay.extend(r,{year:e[0],month:e[1]}),i.checkDate("limit").calendar(null,null,"init"),i.rangeLinked||(i.autoCalendarModel.auto?i.choose(lay(d).find("td.layui-this"),n):i.done(null,"change"))},nextYear:function(){e()||(i.rangeLinked?(l.dateTime.year++,i.checkDate("limit").calendar(null,0,"init")):(r.year++,i.checkDate("limit").calendar(null,n),i.autoCalendarModel.auto?i.choose(lay(d).find("td.layui-this"),n):i.done(null,"change")))}}},I.prototype.changeEvent=function(){var i=this;i.config;lay(i.elem).on("click",function(e){lay.stope(e)}).on("mousedown",function(e){lay.stope(e)}),lay.each(i.elemHeader,function(n,e){lay(e[0]).on("click",function(e){i.change(n).prevYear()}),lay(e[1]).on("click",function(e){i.change(n).prevMonth()}),lay(e[2]).find("span").on("click",function(e){var t=lay(this),a=t.attr("lay-ym"),t=t.attr("lay-type");a&&(a=a.split("-"),i.listYM[n]=[0|a[0],0|a[1]],i.list(t,n),lay(i.footer).find("."+L).addClass(k))}),lay(e[3]).on("click",function(e){i.change(n).nextMonth()}),lay(e[4]).on("click",function(e){i.change(n).nextYear()})}),lay.each(i.table,function(e,t){lay(t).find("td").on("click",function(){i.choose(lay(this),e)})}),lay(i.footer).find("span").on("click",function(){var e=lay(this).attr("lay-type");i.tool(this,e)})},I.prototype.isInput=function(e){return/input|textarea/.test(e.tagName.toLocaleLowerCase())||/INPUT|TEXTAREA/.test(e.tagName)},I.prototype.events=function(){var e,t=this,a=t.config;a.elem[0]&&!a.elem[0].eventHandler&&(a.elem.on(a.trigger,e=function(){D.thisId!==a.id&&t.render()}),a.elem[0].eventHandler=!0,a.eventElem.on(a.trigger,e),t.unbind=function(){t.remove(),a.elem.off(a.trigger,e),a.elem.removeAttr("lay-key"),a.elem.removeAttr(d),a.elem[0].eventHandler=!1,a.eventElem.off(a.trigger,e),a.eventElem.removeAttr("lay-key"),delete s.that[a.id]})},s.that={},s.getThis=function(e){var t=s.that[e];return!t&&n&&layui.hint().error(e?a+" instance with ID '"+e+"' not found":"ID argument required"),t},l.run=function(n){n(v).on("mousedown",function(e){var t,a;!D.thisId||(t=s.getThis(D.thisId))&&(a=t.config,e.target!==a.elem[0]&&e.target!==a.eventElem[0]&&e.target!==n(a.closeStop)[0]&&t.remove())}).on("keydown",function(e){var t;!D.thisId||(t=s.getThis(D.thisId))&&"static"!==t.config.position&&13===e.keyCode&&n("#"+t.elemID)[0]&&t.elemID===I.thisElemDate&&(e.preventDefault(),n(t.footer).find(C)[0].click())}),n(i).on("resize",function(){if(D.thisId){var e=s.getThis(D.thisId);if(e)return!(!e.elem||!n(".layui-laydate")[0])&&void e.position()}})},D.render=function(e){e=new I(e);return s.call(e)},D.reload=function(e,t){e=s.getThis(e);if(e)return e.reload(t)},D.getInst=function(e){e=s.getThis(e);if(e)return e.inst},D.hint=function(e,t){e=s.getThis(e);if(e)return e.hint(t)},D.unbind=function(e){e=s.getThis(e);if(e)return e.unbind()},D.close=function(e){e=s.getThis(e||D.thisId);if(e)return e.remove()},D.parse=function(a,n,i){return a=a||{},n=((n="string"==typeof n?s.formatArr(n):n)||[]).concat(),lay.each(n,function(e,t){/yyyy|y/.test(t)?n[e]=lay.digit(a.year,t.length):/MM|M/.test(t)?n[e]=lay.digit(a.month+(i||0),t.length):/dd|d/.test(t)?n[e]=lay.digit(a.date,t.length):/HH|H/.test(t)?n[e]=lay.digit(a.hours,t.length):/mm|m/.test(t)?n[e]=lay.digit(a.minutes,t.length):/ss|s/.test(t)&&(n[e]=lay.digit(a.seconds,t.length))}),n.join("")},D.getEndDate=function(e,t){var a=new Date;return a.setFullYear(t||a.getFullYear(),e||a.getMonth()+1,1),new Date(a.getTime()-864e5).getDate()},n?(D.ready(),layui.define("lay",function(e){D.path=layui.cache.dir,l.run(lay),e(a,D)})):"function"==typeof define&&define.amd?define(function(){return l.run(lay),D}):(D.ready(),l.run(i.lay),i.laydate=D)}(window,window.document);!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e):function(e){if(e.document)return t(e);throw new Error("jQuery requires a window with a document")}:t(e)}("undefined"!=typeof window?window:this,function(T,M){var f=[],g=T.document,c=f.slice,O=f.concat,R=f.push,P=f.indexOf,B={},W=B.toString,m=B.hasOwnProperty,y={},e="1.12.4",C=function(e,t){return new C.fn.init(e,t)},I=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,$=/^-ms-/,z=/-([\da-z])/gi,X=function(e,t){return t.toUpperCase()};function U(e){var t=!!e&&"length"in e&&e.length,n=C.type(e);return"function"!==n&&!C.isWindow(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+a+")"+a+"*"),ee=new RegExp("="+a+"*([^\\]'\"]*?)"+a+"*\\]","g"),te=new RegExp(G),ne=new RegExp("^"+s+"$"),f={ID:new RegExp("^#("+s+")"),CLASS:new RegExp("^\\.("+s+")"),TAG:new RegExp("^("+s+"|[*])"),ATTR:new RegExp("^"+J),PSEUDO:new RegExp("^"+G),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+a+"*(even|odd|(([+-]|)(\\d*)n|)"+a+"*(?:([+-]|)"+a+"*(\\d+)|))"+a+"*\\)|)","i"),bool:new RegExp("^(?:"+Y+")$","i"),needsContext:new RegExp("^"+a+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+a+"*((?:-\\d)?\\d*)"+a+"*\\)|)(?=[^-]|$)","i")},re=/^(?:input|select|textarea|button)$/i,ie=/^h\d$/i,c=/^[^{]+\{\s*\[native \w/,oe=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ae=/[+~]/,se=/'|\\/g,d=new RegExp("\\\\([\\da-f]{1,6}"+a+"?|("+a+")|.)","ig"),p=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(65536+r):String.fromCharCode(r>>10|55296,1023&r|56320)},ue=function(){C()};try{D.apply(n=V.call(v.childNodes),v.childNodes),n[v.childNodes.length].nodeType}catch(F){D={apply:n.length?function(e,t){U.apply(e,V.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function H(e,t,n,r){var i,o,a,s,u,l,c,f,d=t&&t.ownerDocument,p=t?t.nodeType:9;if(n=n||[],"string"!=typeof e||!e||1!==p&&9!==p&&11!==p)return n;if(!r&&((t?t.ownerDocument||t:v)!==E&&C(t),t=t||E,N)){if(11!==p&&(l=oe.exec(e)))if(i=l[1]){if(9===p){if(!(a=t.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(d&&(a=d.getElementById(i))&&y(t,a)&&a.id===i)return n.push(a),n}else{if(l[2])return D.apply(n,t.getElementsByTagName(e)),n;if((i=l[3])&&g.getElementsByClassName&&t.getElementsByClassName)return D.apply(n,t.getElementsByClassName(i)),n}if(g.qsa&&!A[e+" "]&&(!m||!m.test(e))){if(1!==p)d=t,f=e;else if("object"!==t.nodeName.toLowerCase()){for((s=t.getAttribute("id"))?s=s.replace(se,"\\$&"):t.setAttribute("id",s=k),o=(c=w(e)).length,u=ne.test(s)?"#"+s:"[id='"+s+"']";o--;)c[o]=u+" "+_(c[o]);f=c.join(","),d=ae.test(e)&&de(t.parentNode)||t}if(f)try{return D.apply(n,d.querySelectorAll(f)),n}catch(h){}finally{s===k&&t.removeAttribute("id")}}}return P(e.replace(L,"$1"),t,n,r)}function le(){var n=[];function r(e,t){return n.push(e+" ")>b.cacheLength&&delete r[n.shift()],r[e+" "]=t}return r}function q(e){return e[k]=!0,e}function h(e){var t=E.createElement("div");try{return!!e(t)}catch(F){return!1}finally{t.parentNode&&t.parentNode.removeChild(t)}}function ce(e,t){for(var n=e.split("|"),r=n.length;r--;)b.attrHandle[n[r]]=t}function fe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||1<<31)-(~e.sourceIndex||1<<31);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function x(a){return q(function(o){return o=+o,q(function(e,t){for(var n,r=a([],e.length,o),i=r.length;i--;)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function de(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in g=H.support={},O=H.isXML=function(e){e=e&&(e.ownerDocument||e).documentElement;return!!e&&"HTML"!==e.nodeName},C=H.setDocument=function(e){var e=e?e.ownerDocument||e:v;return e!==E&&9===e.nodeType&&e.documentElement&&(t=(E=e).documentElement,N=!O(E),(e=E.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",ue,!1):e.attachEvent&&e.attachEvent("onunload",ue)),g.attributes=h(function(e){return e.className="i",!e.getAttribute("className")}),g.getElementsByTagName=h(function(e){return e.appendChild(E.createComment("")),!e.getElementsByTagName("*").length}),g.getElementsByClassName=c.test(E.getElementsByClassName),g.getById=h(function(e){return t.appendChild(e).id=k,!E.getElementsByName||!E.getElementsByName(k).length}),g.getById?(b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&N)return(e=t.getElementById(e))?[e]:[]},b.filter.ID=function(e){var t=e.replace(d,p);return function(e){return e.getAttribute("id")===t}}):(delete b.find.ID,b.filter.ID=function(e){var t=e.replace(d,p);return function(e){e="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return e&&e.value===t}}),b.find.TAG=g.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):g.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"!==e)return o;for(;n=o[i++];)1===n.nodeType&&r.push(n);return r},b.find.CLASS=g.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&N)return t.getElementsByClassName(e)},r=[],m=[],(g.qsa=c.test(E.querySelectorAll))&&(h(function(e){t.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&m.push("[*^$]="+a+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||m.push("\\["+a+"*(?:value|"+Y+")"),e.querySelectorAll("[id~="+k+"-]").length||m.push("~="),e.querySelectorAll(":checked").length||m.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||m.push(".#.+[+~]")}),h(function(e){var t=E.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&m.push("name"+a+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||m.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),m.push(",.*:")})),(g.matchesSelector=c.test(i=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.msMatchesSelector))&&h(function(e){g.disconnectedMatch=i.call(e,"div"),i.call(e,"[s!='']:x"),r.push("!=",G)}),m=m.length&&new RegExp(m.join("|")),r=r.length&&new RegExp(r.join("|")),e=c.test(t.compareDocumentPosition),y=e||c.test(t.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},$=e?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!g.sortDetached&&t.compareDocumentPosition(e)===n?e===E||e.ownerDocument===v&&y(v,e)?-1:t===E||t.ownerDocument===v&&y(v,t)?1:u?j(u,e)-j(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===E?-1:t===E?1:i?-1:o?1:u?j(u,e)-j(u,t):0;if(i===o)return fe(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?fe(a[r],s[r]):a[r]===v?-1:s[r]===v?1:0}),E},H.matches=function(e,t){return H(e,null,null,t)},H.matchesSelector=function(e,t){if((e.ownerDocument||e)!==E&&C(e),t=t.replace(ee,"='$1']"),g.matchesSelector&&N&&!A[t+" "]&&(!r||!r.test(t))&&(!m||!m.test(t)))try{var n=i.call(e,t);if(n||g.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(F){}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(d,p),e[3]=(e[3]||e[4]||e[5]||"").replace(d,p),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||H.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&H.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return f.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&te.test(n)&&(t=w(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(d,p).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=W[e+" "];return t||(t=new RegExp("(^|"+a+")"+e+"("+a+"|$)"))&&W(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(t,n,r){return function(e){e=H.attr(e,t);return null==e?"!="===n:!n||(e+="","="===n?e===r:"!="===n?e!==r:"^="===n?r&&0===e.indexOf(r):"*="===n?r&&-1(?:<\/\1>|)$/,G=/^.[^:#\[\.,]*$/;function K(e,n,r){if(C.isFunction(n))return C.grep(e,function(e,t){return!!n.call(e,t,e)!==r});if(n.nodeType)return C.grep(e,function(e){return e===n!==r});if("string"==typeof n){if(G.test(n))return C.filter(n,e,r);n=C.filter(n,e)}return C.grep(e,function(e){return-1)[^>]*|#([\w-]*))$/,ee=((C.fn.init=function(e,t,n){if(!e)return this;if(n=n||Q,"string"!=typeof e)return e.nodeType?(this.context=this[0]=e,this.length=1,this):C.isFunction(e)?"undefined"!=typeof n.ready?n.ready(e):e(C):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),C.makeArray(e,this));if(!(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&3<=e.length?[null,e,null]:Z.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof C?t[0]:t,C.merge(this,C.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:g,!0)),J.test(r[1])&&C.isPlainObject(t))for(var r in t)C.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if((n=g.getElementById(r[2]))&&n.parentNode){if(n.id!==r[2])return Q.find(e);this.length=1,this[0]=n}return this.context=g,this.selector=e,this}).prototype=C.fn,Q=C(g),/^(?:parents|prev(?:Until|All))/),te={children:!0,contents:!0,next:!0,prev:!0};function ne(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}C.fn.extend({has:function(e){var t,n=C(e,this),r=n.length;return this.filter(function(){for(t=0;t
                                                              a",y.leadingWhitespace=3===S.firstChild.nodeType,y.tbody=!S.getElementsByTagName("tbody").length,y.htmlSerialize=!!S.getElementsByTagName("link").length,y.html5Clone="<:nav>"!==g.createElement("nav").cloneNode(!0).outerHTML,q.type="checkbox",q.checked=!0,k.appendChild(q),y.appendChecked=q.checked,S.innerHTML="",y.noCloneChecked=!!S.cloneNode(!0).lastChild.defaultValue,k.appendChild(S),(q=g.createElement("input")).setAttribute("type","radio"),q.setAttribute("checked","checked"),q.setAttribute("name","t"),S.appendChild(q),y.checkClone=S.cloneNode(!0).cloneNode(!0).lastChild.checked,y.noCloneEvent=!!S.addEventListener,S[C.expando]=1,y.attributes=!S.getAttribute(C.expando);var x={option:[1,""],legend:[1,"
                                                              ","
                                                              "],area:[1,"",""],param:[1,"",""],thead:[1,"","
                                                              "],tr:[2,"","
                                                              "],col:[2,"","
                                                              "],td:[3,"","
                                                              "],_default:y.htmlSerialize?[0,"",""]:[1,"X
                                                              ","
                                                              "]};function b(e,t){var n,r,i=0,o="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):undefined;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||C.nodeName(r,t)?o.push(r):C.merge(o,b(r,t));return t===undefined||t&&C.nodeName(e,t)?C.merge([e],o):o}function we(e,t){for(var n,r=0;null!=(n=e[r]);r++)C._data(n,"globalEval",!t||C._data(t[r],"globalEval"))}x.optgroup=x.option,x.tbody=x.tfoot=x.colgroup=x.caption=x.thead,x.th=x.td;var Te=/<|&#?\w+;/,Ce=/"!==f[1]||Ce.test(a)?0:u:u.firstChild)&&a.childNodes.length;o--;)C.nodeName(c=a.childNodes[o],"tbody")&&!c.childNodes.length&&a.removeChild(c);for(C.merge(h,u.childNodes),u.textContent="";u.firstChild;)u.removeChild(u.firstChild);u=p.lastChild}else h.push(t.createTextNode(a));for(u&&p.removeChild(u),y.appendChecked||C.grep(b(h,"input"),Ee),g=0;a=h[g++];)if(r&&-1]","i"),Pe=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,Be=/\s*$/g,ze=be(g).appendChild(g.createElement("div"));function Xe(e,t){return C.nodeName(e,"table")&&C.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ue(e){return e.type=(null!==C.find.attr(e,"type"))+"/"+e.type,e}function Ve(e){var t=Ie.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Ye(e,t){if(1===t.nodeType&&C.hasData(e)){var n,r,i,e=C._data(e),o=C._data(t,e),a=e.events;if(a)for(n in delete o.handle,o.events={},a)for(r=0,i=a[n].length;r")},clone:function(e,t,n){var r,i,o,a,s,u=C.contains(e.ownerDocument,e);if(y.html5Clone||C.isXMLDoc(e)||!Re.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(ze.innerHTML=e.outerHTML,ze.removeChild(o=ze.firstChild)),!(y.noCloneEvent&&y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||C.isXMLDoc(e)))for(r=b(o),s=b(e),a=0;null!=(i=s[a]);++a)if(r[a]){f=c=l=p=d=void 0;var l,c,f,d=i,p=r[a];if(1===p.nodeType){if(l=p.nodeName.toLowerCase(),!y.noCloneEvent&&p[C.expando]){for(c in(f=C._data(p)).events)C.removeEvent(p,c,f.handle);p.removeAttribute(C.expando)}"script"===l&&p.text!==d.text?(Ue(p).text=d.text,Ve(p)):"object"===l?(p.parentNode&&(p.outerHTML=d.outerHTML),y.html5Clone&&d.innerHTML&&!C.trim(p.innerHTML)&&(p.innerHTML=d.innerHTML)):"input"===l&&ge.test(d.type)?(p.defaultChecked=p.checked=d.checked,p.value!==d.value&&(p.value=d.value)):"option"===l?p.defaultSelected=p.selected=d.defaultSelected:"input"!==l&&"textarea"!==l||(p.defaultValue=d.defaultValue)}}if(t)if(n)for(s=s||b(e),r=r||b(o),a=0;null!=(i=s[a]);a++)Ye(i,r[a]);else Ye(e,o);return 0<(r=b(o,"script")).length&&we(r,!u&&b(e,"script")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=C.expando,u=C.cache,l=y.attributes,c=C.event.special;null!=(n=e[a]);a++)if((t||v(n))&&(o=(i=n[s])&&u[i])){if(o.events)for(r in o.events)c[r]?C.event.remove(n,r):C.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||"undefined"==typeof n.removeAttribute?n[s]=undefined:n.removeAttribute(s),f.push(i))}}}),C.fn.extend({domManip:w,detach:function(e){return Je(this,e,!0)},remove:function(e){return Je(this,e)},text:function(e){return d(this,function(e){return e===undefined?C.text(this):this.empty().append((this[0]&&this[0].ownerDocument||g).createTextNode(e))},null,e,arguments.length)},append:function(){return w(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Xe(this,e).appendChild(e)})},prepend:function(){return w(this,arguments,function(e){var t;1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(t=Xe(this,e)).insertBefore(e,t.firstChild)})},before:function(){return w(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return w(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&C.cleanData(b(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&C.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return C.clone(this,e,t)})},html:function(e){return d(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined)return 1===t.nodeType?t.innerHTML.replace(Oe,""):undefined;if("string"==typeof e&&!Be.test(e)&&(y.htmlSerialize||!Re.test(e))&&(y.leadingWhitespace||!ve.test(e))&&!x[(me.exec(e)||["",""])[1].toLowerCase()]){e=C.htmlPrefilter(e);try{for(;n")).appendTo(t.documentElement))[0].contentWindow||Ge[0].contentDocument).document).write(),t.close(),n=Qe(e,t),Ge.detach()),Ke[e]=n),n}var n,et,tt,nt,rt,it,ot,a,at=/^margin/,st=new RegExp("^("+e+")(?!px)[a-z%]+$","i"),ut=function(e,t,n,r){var i,o={};for(i in t)o[i]=e.style[i],e.style[i]=t[i];for(i in r=n.apply(e,r||[]),t)e.style[i]=o[i];return r},lt=g.documentElement;function t(){var e,t=g.documentElement;t.appendChild(ot),a.style.cssText="-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",n=tt=it=!1,et=rt=!0,T.getComputedStyle&&(e=T.getComputedStyle(a),n="1%"!==(e||{}).top,it="2px"===(e||{}).marginLeft,tt="4px"===(e||{width:"4px"}).width,a.style.marginRight="50%",et="4px"===(e||{marginRight:"4px"}).marginRight,(e=a.appendChild(g.createElement("div"))).style.cssText=a.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",e.style.marginRight=e.style.width="0",a.style.width="1px",rt=!parseFloat((T.getComputedStyle(e)||{}).marginRight),a.removeChild(e)),a.style.display="none",(nt=0===a.getClientRects().length)&&(a.style.display="",a.innerHTML="
                                                              t
                                                              ",a.childNodes[0].style.borderCollapse="separate",(e=a.getElementsByTagName("td"))[0].style.cssText="margin:0;border:0;padding:0;display:none",(nt=0===e[0].offsetHeight)&&(e[0].style.display="",e[1].style.display="none",nt=0===e[0].offsetHeight)),t.removeChild(ot)}ot=g.createElement("div"),(a=g.createElement("div")).style&&(a.style.cssText="float:left;opacity:.5",y.opacity="0.5"===a.style.opacity,y.cssFloat=!!a.style.cssFloat,a.style.backgroundClip="content-box",a.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===a.style.backgroundClip,(ot=g.createElement("div")).style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",a.innerHTML="",ot.appendChild(a),y.boxSizing=""===a.style.boxSizing||""===a.style.MozBoxSizing||""===a.style.WebkitBoxSizing,C.extend(y,{reliableHiddenOffsets:function(){return null==n&&t(),nt},boxSizingReliable:function(){return null==n&&t(),tt},pixelMarginRight:function(){return null==n&&t(),et},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),rt},reliableMarginLeft:function(){return null==n&&t(),it}}));var l,p,ct=/^(top|right|bottom|left)$/;function ft(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}T.getComputedStyle?(l=function(e){var t=e.ownerDocument.defaultView;return(t=t&&t.opener?t:T).getComputedStyle(e)},p=function(e,t,n){var r,i,o=e.style;return""!==(i=(n=n||l(e))?n.getPropertyValue(t)||n[t]:undefined)&&i!==undefined||C.contains(e.ownerDocument,e)||(i=C.style(e,t)),n&&!y.pixelMarginRight()&&st.test(i)&&at.test(t)&&(e=o.width,t=o.minWidth,r=o.maxWidth,o.minWidth=o.maxWidth=o.width=i,i=n.width,o.width=e,o.minWidth=t,o.maxWidth=r),i===undefined?i:i+""}):lt.currentStyle&&(l=function(e){return e.currentStyle},p=function(e,t,n){var r,i,o,a=e.style;return null==(n=(n=n||l(e))?n[t]:undefined)&&a&&a[t]&&(n=a[t]),st.test(n)&&!ct.test(t)&&(r=a.left,(o=(i=e.runtimeStyle)&&i.left)&&(i.left=e.currentStyle.left),a.left="fontSize"===t?"1em":n,n=a.pixelLeft+"px",a.left=r,o&&(i.left=o)),n===undefined?n:n+""||"auto"});var dt=/alpha\([^)]*\)/i,pt=/opacity\s*=\s*([^)]*)/i,ht=/^(none|table(?!-c[ea]).+)/,gt=new RegExp("^("+e+")(.*)$","i"),mt={position:"absolute",visibility:"hidden",display:"block"},yt={letterSpacing:"0",fontWeight:"400"},vt=["Webkit","O","Moz","ms"],xt=g.createElement("div").style;function bt(e){if(e in xt)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=vt.length;n--;)if((e=vt[n]+t)in xt)return e}function wt(e,t){for(var n,r,i,o=[],a=0,s=e.length;a
                                                              a",F=q.getElementsByTagName("a")[0],k.setAttribute("type","checkbox"),q.appendChild(k),(F=q.getElementsByTagName("a")[0]).style.cssText="top:1px",y.getSetAttribute="t"!==q.className,y.style=/top/.test(F.getAttribute("style")),y.hrefNormalized="/a"===F.getAttribute("href"),y.checkOn=!!k.value,y.optSelected=e.selected,y.enctype=!!g.createElement("form").enctype,S.disabled=!0,y.optDisabled=!e.disabled,(k=g.createElement("input")).setAttribute("value",""),y.input=""===k.getAttribute("value"),k.value="t",k.setAttribute("type","radio"),y.radioValue="t"===k.value;var Lt=/\r/g,Ht=/[\x20\t\r\n\f]+/g;C.fn.extend({val:function(t){var n,e,r,i=this[0];return arguments.length?(r=C.isFunction(t),this.each(function(e){1===this.nodeType&&(null==(e=r?t.call(this,e,C(this).val()):t)?e="":"number"==typeof e?e+="":C.isArray(e)&&(e=C.map(e,function(e){return null==e?"":e+""})),(n=C.valHooks[this.type]||C.valHooks[this.nodeName.toLowerCase()])&&"set"in n&&n.set(this,e,"value")!==undefined||(this.value=e))})):i?(n=C.valHooks[i.type]||C.valHooks[i.nodeName.toLowerCase()])&&"get"in n&&(e=n.get(i,"value"))!==undefined?e:"string"==typeof(e=i.value)?e.replace(Lt,""):null==e?"":e:void 0}}),C.extend({valHooks:{option:{get:function(e){var t=C.find.attr(e,"value");return null!=t?t:C.trim(C.text(e)).replace(Ht," ")}},select:{get:function(e){for(var t,n=e.options,r=e.selectedIndex,i="select-one"===e.type||r<0,o=i?null:[],a=i?r+1:n.length,s=r<0?a:i?r:0;s").append(C.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},C.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){C.fn[t]=function(e){return this.on(t,e)}}),C.expr.filters.animated=function(t){return C.grep(C.timers,function(e){return t===e.elem}).length},C.offset={setOffset:function(e,t,n){var r,i,o,a,s=C.css(e,"position"),u=C(e),l={};"static"===s&&(e.style.position="relative"),o=u.offset(),r=C.css(e,"top"),a=C.css(e,"left"),s=("absolute"===s||"fixed"===s)&&-1'+(s?a.title[0]:a.title)+"":"";return a.zIndex=o,t([a.shade?'
                                                              ':"",'
                                                              '+(e&&2!=a.type?"":s)+"'+(n=["layui-icon-tips","layui-icon-success","layui-icon-error","layui-icon-question","layui-icon-lock","layui-icon-face-cry","layui-icon-face-smile"],o="layui-anim layui-anim-rotate layui-anim-loop",0==a.type&&-1!==a.icon?'':3==a.type?(i=["layui-icon-loading","layui-icon-loading-1"],2==a.icon?'
                                                              ':''):"")+((1!=a.type||!e)&&a.content||"")+'
                                                              '+(n=[],l&&(n.push(''),n.push('')),a.closeBtn&&n.push(''),n.join(""))+"
                                                              "+(a.btn?function(){var e="";"string"==typeof a.btn&&(a.btn=[a.btn]);for(var t=0,i=a.btn.length;t'+a.btn[t]+"";return'
                                                              '+e+"
                                                              "}():"")+(a.resize?'':"")+""],s,m('
                                                              ')),this},t.pt.creat=function(){var e,t,i,n,a,o=this,s=o.config,l=o.index,r="object"==typeof(f=s.content),c=m("body");if(s.id&&m("."+y[0]).find("#"+s.id)[0])return e=m("#"+s.id).closest("."+y[0]),t=e.attr("times"),i=e.data("config"),n=m("#"+y.SHADE+t),void("min"===(e.data("maxminStatus")||{})?h.restore(t):i.hideOnClose&&(n.show(),e.show()));switch(s.removeFocus&&document.activeElement.blur(),"string"==typeof s.area&&(s.area="auto"===s.area?["",""]:[s.area,""]),s.shift&&(s.anim=s.shift),6==h.ie&&(s.fixed=!1),s.type){case 0:s.btn="btn"in s?s.btn:u.btn[0],h.closeAll("dialog");break;case 2:var f=s.content=r?s.content:[s.content||"","auto"];s.content='';break;case 3:delete s.title,delete s.closeBtn,-1===s.icon&&s.icon,h.closeAll("loading");break;case 4:r||(s.content=[s.content,"body"]),s.follow=s.content[1],s.content=s.content[0]+'',delete s.title,s.tips="object"==typeof s.tips?s.tips:[s.tips,!0],s.tipsMore||h.closeAll("tips")}o.vessel(r,function(e,t,i){c.append(e[0]),r?2==s.type||4==s.type?m("body").append(e[1]):f.parents("."+y[0])[0]||(f.data("display",f.css("display")).show().addClass("layui-layer-wrap").wrap(e[1]),m("#"+y[0]+l).find("."+y[5]).before(t)):c.append(e[1]),m("#"+y.MOVE)[0]||c.append(u.moveElem=i),o.layero=m("#"+y[0]+l),o.shadeo=m("#"+y.SHADE+l),s.scrollbar||u.setScrollbar(l)}).auto(l),o.shadeo.css({"background-color":s.shade[1]||"#000",opacity:s.shade[0]||s.shade}),2==s.type&&6==h.ie&&o.layero.find("iframe").attr("src",f[0]),4==s.type?o.tips():(o.offset(),parseInt(u.getStyle(document.getElementById(y.MOVE),"z-index"))||(o.layero.css("visibility","hidden"),h.ready(function(){o.offset(),o.layero.css("visibility","visible")}))),s.fixed&&!u.events.resize[o.index]&&(u.events.resize[o.index]=function(){o.resize()},d.on("resize",u.events.resize[o.index])),s.time<=0||setTimeout(function(){h.close(o.index)},s.time),o.move().callback(),y.anim[s.anim]&&(a="layer-anim "+y.anim[s.anim],o.layero.addClass(a).one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){m(this).removeClass(a)})),o.layero.data("config",s)},t.pt.resize=function(){var e=this,t=e.config;e.offset(),(/^\d+%$/.test(t.area[0])||/^\d+%$/.test(t.area[1]))&&e.auto(e.index),4==t.type&&e.tips()},t.pt.auto=function(e){var t=this.config,i=m("#"+y[0]+e),n=(""===t.area[0]&&0t.maxWidth&&i.width(t.maxWidth)),[i.innerWidth(),i.innerHeight()]),a=i.find(y[1]).outerHeight()||0,o=i.find("."+y[6]).outerHeight()||0,e=function(e){(e=i.find(e)).height(n[1]-a-o-2*(0|parseFloat(e.css("padding-top"))))};return 2===t.type?e("iframe"):""===t.area[1]?0t.maxHeight?(n[1]=t.maxHeight,e("."+y[5])):t.fixed&&n[1]>=d.height()&&(n[1]=d.height(),e("."+y[5])):e("."+y[5]),this},t.pt.offset=function(){var e=this,t=e.config,i=e.layero,n=[i.outerWidth(),i.outerHeight()],a="object"==typeof t.offset;e.offsetTop=(d.height()-n[1])/2,e.offsetLeft=(d.width()-n[0])/2,a?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):"auto"!==t.offset&&("t"===t.offset?e.offsetTop=0:"r"===t.offset?e.offsetLeft=d.width()-n[0]:"b"===t.offset?e.offsetTop=d.height()-n[1]:"l"===t.offset?e.offsetLeft=0:"lt"===t.offset?(e.offsetTop=0,e.offsetLeft=0):"lb"===t.offset?(e.offsetTop=d.height()-n[1],e.offsetLeft=0):"rt"===t.offset?(e.offsetTop=0,e.offsetLeft=d.width()-n[0]):"rb"===t.offset?(e.offsetTop=d.height()-n[1],e.offsetLeft=d.width()-n[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?d.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?d.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=d.scrollTop(),e.offsetLeft+=d.scrollLeft()),"min"===i.data("maxminStatus")&&(e.offsetTop=d.height()-(i.find(y[1]).outerHeight()||0),e.offsetLeft=i.css("left")),i.css({top:e.offsetTop,left:e.offsetLeft})},t.pt.tips=function(){var e=this.config,t=this.layero,i=[t.outerWidth(),t.outerHeight()],n=m(e.follow),a={width:(n=n[0]?n:m("body")).outerWidth(),height:n.outerHeight(),top:n.offset().top,left:n.offset().left},o=t.find(".layui-layer-TipsG"),n=e.tips[0];e.tips[1]||o.remove(),a.autoLeft=function(){0d.width()&&(o=d.width()-180-(u.minStackArr.edgeIndex=u.minStackArr.edgeIndex||0,u.minStackArr.edgeIndex+=3))<0&&(o=0),t.minStack&&(l.left=o,l.top=d.height()-n,a||u.minStackIndex++,r.attr("minLeft",o)),r.attr("position",s),h.style(e,l,!0),i.hide(),"page"===r.attr("type")&&r.find(y[4]).hide(),u.restScrollbar(e),c.hide())},h.restore=function(e){var t=m("#"+y[0]+e),i=m("#"+y.SHADE+e),n=t.attr("area").split(","),a=t.attr("type"),o=t.data("config")||{};t.removeData("maxminStatus"),h.style(e,{width:n[0],height:n[1],top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr("position"),overflow:"visible"},!0),t.find(".layui-layer-max").removeClass("layui-layer-maxmin"),t.find(".layui-layer-min").show(),"page"===a&&t.find(y[4]).show(),o.scrollbar?u.restScrollbar(e):u.setScrollbar(e),i.show()},h.full=function(t){var i=m("#"+y[0]+t),e=i.data("maxminStatus");"max"!==e&&("min"===e&&h.restore(t),i.data("maxminStatus","max"),u.record(i),y.html.attr("layer-full")||u.setScrollbar(t),setTimeout(function(){var e="fixed"===i.css("position");h.style(t,{top:e?0:d.scrollTop(),left:e?0:d.scrollLeft(),width:"100%",height:"100%"},!0),i.find(".layui-layer-min").hide()},100))},h.title=function(e,t){m("#"+y[0]+(t||h.index)).find(y[1]).html(e)},h.close=function(o,s){var l,e,r=(t=m("."+y[0]).children("#"+o).closest("."+y[0]))[0]?(o=t.attr("times"),t):m("#"+y[0]+o),c=r.attr("type"),t=r.data("config")||{},f=t.id&&t.hideOnClose;r[0]&&(l={slideDown:"layer-anim-slide-down-out",slideLeft:"layer-anim-slide-left-out",slideUp:"layer-anim-slide-up-out",slideRight:"layer-anim-slide-right-out"}[t.anim]||"layer-anim-close",e=function(){var e="layui-layer-wrap";if(f)return r.removeClass("layer-anim "+l),r.hide();if(c===u.type[1]&&"object"===r.attr("conType")){r.children(":not(."+y[5]+")").remove();for(var t=r.find("."+e),i=0;i<2;i++)t.unwrap();t.css("display",t.data("display")).removeClass(e)}else{if(c===u.type[2])try{var n=m("#"+y[4]+o)[0];n.contentWindow.document.write(""),n.contentWindow.close(),r.find("."+y[5])[0].removeChild(n)}catch(a){}r[0].innerHTML="",r.remove()}"function"==typeof u.end[o]&&u.end[o](),delete u.end[o],"function"==typeof s&&s(),u.events.resize[o]&&(d.off("resize",u.events.resize[o]),delete u.events.resize[o])},m("#"+y.SHADE+o)[f?"hide":"remove"](),t.isOutAnim&&r.addClass("layer-anim "+l),6==h.ie&&u.reselect(),u.restScrollbar(o),"string"==typeof r.attr("minLeft")&&(u.minStackIndex--,u.minStackArr.push(r.attr("minLeft"))),h.ie&&h.ie<10||!t.isOutAnim?e():setTimeout(function(){e()},200))},h.closeAll=function(n,a){"function"==typeof n&&(a=n,n=null);var o=m("."+y[0]);m.each(o,function(e){var t=m(this),i=n?t.attr("type")===n:1;i&&h.close(t.attr("times"),e===o.length-1?a:null)}),0===o.length&&"function"==typeof a&&a()},h.closeLast=function(e){h.close(m(".layui-layer-"+(e=e||"page")+":last").attr("times"))},h.cache||{}),g=function(e){return i.skin?" "+i.skin+" "+i.skin+"-"+e:""};h.prompt=function(i,n){var e="",t="";"function"==typeof(i=i||{})&&(n=i),i.area&&(e='style="width: '+(o=i.area)[0]+"; height: "+o[1]+';"',delete i.area),i.placeholder&&(t=' placeholder="'+i.placeholder+'"');var a,o=2==i.formType?'":'",s=i.success;return delete i.success,h.open(m.extend({type:1,btn:["确定","取消"],content:o,skin:"layui-layer-prompt"+g("prompt"),maxWidth:d.width(),success:function(e){(a=e.find(".layui-layer-input")).val(i.value||"").focus(),"function"==typeof s&&s(e)},resize:!1,yes:function(e){var t=a.val();t.length>(i.maxlength||500)?h.tips("最多输入"+(i.maxlength||500)+"个字数",a,{tips:1}):n&&n(t,e,a)}},i))},h.tab=function(n){var a=(n=n||{}).tab||{},o="layui-this",s=n.success;return delete n.success,h.open(m.extend({type:1,skin:"layui-layer-tab"+g("tab"),resize:!1,title:function(){var e=a.length,t=1,i="";if(0'+a[0].title+"";t"+a[t].title+"";return i}(),content:'
                                                                '+function(){var e=a.length,t=1,i="";if(0'+(a[0].content||"no content")+"";t'+(a[t].content||"no content")+"";return i}()+"
                                                              ",success:function(e){var t=e.find(".layui-layer-title").children(),i=e.find(".layui-layer-tabmain").children();t.on("mousedown",function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0;var e=m(this),t=e.index();e.addClass(o).siblings().removeClass(o),i.eq(t).show().siblings().hide(),"function"==typeof n.change&&n.change(t)}),"function"==typeof s&&s(e)}},n))},h.photos=function(n,e,a){var o={};if((n=n||{}).photos){var t=!("string"==typeof n.photos||n.photos instanceof m),i=t?n.photos:{},s=i.data||[],l=i.start||0,r=(o.imgIndex=1+(0|l),n.img=n.img||"img",n.success);if(delete n.success,t){if(0===s.length)return h.msg("没有图片")}else{var c=m(n.photos),f=function(){s=[],c.find(n.img).each(function(e){var t=m(this);t.attr("layer-index",e),s.push({alt:t.attr("alt"),pid:t.attr("layer-pid"),src:t.attr("lay-src")||t.attr("layer-src")||t.attr("src"),thumb:t.attr("src")})})};if(f(),0===s.length)return;if(e||c.on("click",n.img,function(){f();var e=m(this).attr("layer-index");h.photos(m.extend(n,{photos:{start:e,data:s,tab:n.tab},full:n.full}),!0)}),!e)return}o.imgprev=function(e){o.imgIndex--,o.imgIndex<1&&(o.imgIndex=s.length),o.tabimg(e)},o.imgnext=function(e,t){o.imgIndex++,o.imgIndex>s.length&&(o.imgIndex=1,t)||o.tabimg(e)},o.keyup=function(e){var t;o.end||(t=e.keyCode,e.preventDefault(),37===t?o.imgprev(!0):39===t?o.imgnext(!0):27===t&&h.close(o.index))},o.tabimg=function(e){if(!(s.length<=1))return i.start=o.imgIndex-1,h.close(o.index),h.photos(n,!0,e)},o.event=function(){o.bigimg.find(".layui-layer-imgprev").on("click",function(e){e.preventDefault(),o.imgprev(!0)}),o.bigimg.find(".layui-layer-imgnext").on("click",function(e){e.preventDefault(),o.imgnext(!0)}),m(document).on("keyup",o.keyup)},o.loadi=h.load(1,{shade:!("shade"in n)&&.9,scrollbar:!1});var t=s[l].src,d=function(e){h.close(o.loadi);var t,i=s[l].alt||"";a&&(n.anim=-1),o.index=h.open(m.extend({type:1,id:"layui-layer-photos",area:(e=[e.width,e.height],t=[m(p).width()-100,m(p).height()-100],!n.full&&(e[0]>t[0]||e[1]>t[1])&&((t=[e[0]/t[0],e[1]/t[1]])[1]'+i+''+(t=['
                                                              '],1','','',"
                                                              "].join("")),n.hideFooter||t.push(['
                                                              ','
                                                              ',"

                                                              "+i+"

                                                              ",""+o.imgIndex+" / "+s.length+"",'\u67e5\u770b\u539f\u56fe',"
                                                              ","
                                                              "].join("")),t.push(""),t.join(""))+"",success:function(e,t){o.bigimg=e.find(".layui-layer-phimg"),o.imgsee=e.find(".layui-layer-imgbar"),o.event(e),n.tab&&n.tab(s[l],e),"function"==typeof r&&r(e)},end:function(){o.end=!0,m(document).off("keyup",o.keyup)}},n))},u=function(){h.close(o.loadi),h.msg("当前图片地址异常
                                                              是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){1").addClass(a));layui.each(o.bars,function(e,t){var n=s('
                                                            • ');n.addClass(t.icon).attr({"lay-type":t.type,style:t.style||(o.bgcolor?"background-color: "+o.bgcolor:"")}).html(t.content),n.on("click",function(){var e=s(this).attr("lay-type");"top"===e&&("body"===o.target?s("html,body"):c).animate({scrollTop:0},o.duration),"function"==typeof o.click&&o.click.call(this,e)}),"object"===layui.type(o.on)&&layui.each(o.on,function(e,t){n.on(e,function(){var e=s(this).attr("lay-type");"function"==typeof t&&t.call(this,e)})}),"top"===t.type&&(n.addClass("layui-fixbar-top"),i=n),u.append(n)}),l.find("."+a).remove(),"object"==typeof o.css&&u.css(o.css),l.append(u),i&&(t=function t(){return c.scrollTop()>=o.margin?e||(i.show(),e=1):e&&(i.hide(),e=0),t}()),c.on("scroll",function(){t&&(clearTimeout(n),n=setTimeout(function(){t()},100))})},countdown:function(o){o=s.extend(!0,{date:new Date,now:new Date},o);var i=arguments,a=(1]|&(?=#[a-zA-Z0-9]+)/g.test(e+="")?e.replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,"""):e},unescape:function(e){return e!==undefined&&null!==e||(e=""),(e+="").replace(/\&/g,"&").replace(/\</g,"<").replace(/\>/g,">").replace(/\'/g,"'").replace(/\"/g,'"')},openWin:function(e){var t=(e=e||{}).window||window.open(e.url||"",e.target,e.specs);e.url||(t.document.open("text/html","replace"),t.document.write(e.content||""),t.document.close())},toVisibleArea:function(e){var t,n,o,i,a,r,l,c;(e=s.extend({margin:160,duration:200,type:"y"},e)).scrollElem[0]&&e.thisElem[0]&&(t=e.scrollElem,l=e.thisElem,o=(a="y"===e.type)?"top":"left",i=t[n=a?"scrollTop":"scrollLeft"](),a=t[a?"height":"width"](),r=t.offset()[o],c={},((l=l.offset()[o]-r)>a-e.margin||l."+h,k=function(e){var i=this;i.index=++p.index,i.config=s.extend({},i.config,p.config,e),i.init()};k.prototype.config={trigger:"click",content:"",className:"",style:"",show:!1,isAllowSpread:!0,isSpreadItem:!0,data:[],delay:300,shade:0},k.prototype.reload=function(e,i){var t=this;t.config=s.extend({},t.config,e),t.init(!0,i)},k.prototype.init=function(e,i){var t,n=this,a=n.config,l=s(a.elem);return 1');return 0No data
                                                            • '),e},u=function(r,e){return layui.each(e,function(e,i){var t,n=i.child&&0",(t="href"in i?''+l+"":l,n?'
                                                              '+t+("parent"===o?'':"group"===o&&d.isAllowSpread?'':"")+"
                                                              ":'
                                                              '+t+"
                                                              "),""].join(""))).data("item",i),n&&(a=s('
                                                              '),t=s("
                                                                "),"parent"===o?(a.append(u(t,i.child)),l.append(a)):l.append(u(t,i.child))),r.append(l))}),r},a=['
                                                                ',"
                                                                "].join("");!(e="contextmenu"!==d.trigger&&!lay.isTopElem(d.elem[0])?e:!0)&&d.elem.data(m+"_opened")||(l.elemView=s("."+f+'[lay-id="'+d.id+'"]'),"reloadData"===i&&l.elemView.length?l.elemView.html(d.content||n()):(l.elemView=s(a),l.elemView.append(d.content||n()),d.className&&l.elemView.addClass(d.className),d.style&&l.elemView.attr("style",d.style),p.thisId=d.id,l.remove(),t.append(l.elemView),d.elem.data(m+"_opened",!0),e=d.shade?'
                                                                ':"",l.elemView.before(e),"mouseenter"===d.trigger&&l.elemView.on("mouseenter",function(){clearTimeout(y.timer)}).on("mouseleave",function(){l.delayRemove()})),l.position(),(y.prevElem=l.elemView).data("prevElem",d.elem),l.elemView.find(".layui-menu").on(o,function(e){layui.stope(e)}),l.elemView.find(".layui-menu li").on("click",function(e){var i=s(this),t=i.data("item")||{},n=t.child&&0n.width()&&(t.addClass(V),(i=t[0].getBoundingClientRect()).left<0&&t.removeClass(V)),i.bottom>n.height()&&t.eq(0).css("margin-top",-(i.bottom-n.height()+5)))}).on("mouseleave",t,function(e){var i=s(this).children("."+C);i.removeClass(V),i.css("margin-top",0)}),p.close=function(e){e=y.getThis(e);return e?(e.remove(),y.call(e)):this},p.reload=function(e,i,t){e=y.getThis(e);return e?(e.reload(i,t),y.call(e)):this},p.reloadData=function(){var t=s.extend([],arguments),n=(t[2]="reloadData",new RegExp("^("+["data","templet","content"].join("|")+")$"));return layui.each(t[1],function(e,i){n.test(e)||delete t[1][e]}),p.reload.apply(null,t)},p.render=function(e){e=new k(e);return y.call(e)},e(r,p)});layui.define(["jquery","lay"],function(e){"use strict";var g=layui.$,c=layui.lay,m={config:{},index:layui.slider?layui.slider.index+1e4:0,set:function(e){var i=this;return i.config=g.extend({},i.config,e),i},on:function(e,i){return layui.onevent.call(this,t,e,i)}},t="slider",v="layui-disabled",x="layui-slider-bar",b="layui-slider-wrap",T="layui-slider-wrap-btn",w="layui-slider-tips",M="layui-slider-input-txt",L="layui-slider-hover",i=function(e){var i=this;i.index=++m.index,i.config=g.extend({},i.config,m.config,e),i.render()};i.prototype.config={type:"default",min:0,max:100,value:0,step:1,showstep:!1,tips:!0,input:!1,range:!1,height:200,disabled:!1,theme:"#16baaa"},i.prototype.render=function(){var a=this,n=a.config,e=g(n.elem);if(1n.min?e:n.min,n.value[1]=i>n.min?i:n.min,n.value[0]=n.value[0]>n.max?n.max:n.value[0],n.value[1]=n.value[1]>n.max?n.max:n.value[1],i=Math.floor((n.value[0]-n.min)/(n.max-n.min)*100),t=(s=Math.floor((n.value[1]-n.min)/(n.max-n.min)*100))-i+"%",i+="%",s+="%"):("object"==typeof n.value&&(n.value=Math.min.apply(null,n.value)),n.valuen.max&&(n.value=n.max),t=Math.floor((n.value-n.min)/(n.max-n.min)*100)+"%");var l,e=n.disabled?"#c2c2c2":n.theme,i='
                                                                '+(n.tips?'
                                                                ':"")+'
                                                                '+(n.range?'
                                                                ':"")+"
                                                                ",t=g(n.elem),s=t.next(".layui-slider");if(s[0]&&s.remove(),a.elemTemp=g(i),n.range?(a.elemTemp.find("."+b).eq(0).data("value",n.value[0]),a.elemTemp.find("."+b).eq(1).data("value",n.value[1])):a.elemTemp.find("."+b).data("value",n.value),t.html(a.elemTemp),"vertical"===n.type&&a.elemTemp.height(n.height+"px"),n.showstep){for(var o=(n.max-n.min)/n.step,r="",u=1;u<1+o;u++){var d=100*u/o;d<100&&(r+='
                                                                ')}a.elemTemp.append(r)}n.input&&!n.range&&(e=g('
                                                                '),t.css("position","relative"),t.append(e),t.find("."+M).children("input").val(n.value),"vertical"===n.type?e.css({left:0,top:-48}):a.elemTemp.css("margin-right",e.outerWidth()+15)),n.disabled?(a.elemTemp.addClass(v),a.elemTemp.find("."+T).addClass(v)):a.slide(),a.elemTemp.find("."+T).on("mouseover",function(){var e="vertical"===n.type?n.height:a.elemTemp[0].offsetWidth,i=a.elemTemp.find("."+b),t=("vertical"===n.type?e-g(this).parent()[0].offsetTop-i.height():g(this).parent()[0].offsetLeft)/e*100,i=g(this).parent().data("value"),e=n.setTips?n.setTips(i):i;a.elemTemp.find("."+w).html(e),clearTimeout(l),l=setTimeout(function(){"vertical"===n.type?a.elemTemp.find("."+w).css({bottom:t+"%","margin-bottom":"20px",display:"inline-block"}):a.elemTemp.find("."+w).css({left:t+"%",display:"inline-block"})},300)}).on("mouseout",function(){clearTimeout(l),a.elemTemp.find("."+w).css("display","none")})},i.prototype.slide=function(e,i,t){var o=this,r=o.config,u=o.elemTemp,d=function(){return"vertical"===r.type?r.height:u[0].offsetWidth},c=u.find("."+b),m=u.next(".layui-slider-input"),v=m.children("."+M).children("input").val(),p=100/((r.max-r.min)/Math.ceil(r.step)),f=function(e,i,t){e=(e=100<(e=100a[1]&&a.reverse(),o.value=r.range?a:l,r.change&&r.change(o.value),"done"===t&&r.done&&r.done(o.value)},h=function(e){var i=e/d()*100/p,t=Math.round(i)*p;return t=e==d()?Math.ceil(i)*p:t},y=g(['
                                                                d()?d():i)/d()*100/p;f(i,l),s.addClass(L),u.find("."+w).show(),e.preventDefault()},i=function(){s.removeClass(L),u.find("."+w).hide()},t=function(){i&&i(),y.remove(),r.done&&r.done(o.value)},g("#LAY-slider-moving")[0]||g("body").append(y),y.on("mousemove",e),y.on("mouseup",t).on("mouseleave",t)})}),u.on("click",function(e){var i=g("."+T),t=g(this);!i.is(event.target)&&0===i.has(event.target).length&&i.length&&(t=(i=(i=(i="vertical"===r.type?d()-e.clientY+t.offset().top-g(window).scrollTop():e.clientX-t.offset().left-g(window).scrollLeft())<0?0:i)>d()?d():i)/d()*100/p,i=r.range?"vertical"===r.type?Math.abs(i-parseInt(g(c[0]).css("bottom")))>Math.abs(i-parseInt(g(c[1]).css("bottom")))?1:0:Math.abs(i-c[0].offsetLeft)>Math.abs(i-c[1].offsetLeft)?1:0:0,f(t,i,"done"),e.preventDefault())}),m.children(".layui-slider-input-btn").children("i").each(function(i){g(this).on("click",function(){v=m.children("."+M).children("input").val();var e=((v=1==i?v-r.stepr.max?r.max:Number(v)+r.step)-r.min)/(r.max-r.min)*100/p;f(e,0,"done")})});var a=function(){var e=this.value,e=(e=(e=(e=isNaN(e)?0:e)r.max?r.max:e,((this.value=e)-r.min)/(r.max-r.min)*100/p);f(e,0,"done")};m.children("."+M).children("input").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),a.call(this))}).on("change",a)},i.prototype.events=function(){this.config},m.render=function(e){e=new i(e);return function(){var t=this,a=t.config;return{setValue:function(e,i){return e=(e=e>a.max?a.max:e)',"",'','',"","","
                                                                "].join("")),r=i.elem=m(i.elem);i.size&&o.addClass("layui-colorpicker-"+i.size),r.addClass("layui-inline").html(e.elemColorBox=o),i.id="id"in i?i.id:r.attr("id")||e.index,e.color=e.elemColorBox.find("."+C)[0].style.background,e.events()},d.prototype.renderPicker=function(){var o,e=this,i=e.config,r=e.elemColorBox[0],t=e.elemPicker=m(['
                                                                ','
                                                                ','
                                                                ','
                                                                ','
                                                                ','
                                                                ',"
                                                                ",'
                                                                ','
                                                                ',"
                                                                ","
                                                                ",'
                                                                ','
                                                                ','
                                                                ',"
                                                                ","
                                                                ",i.predefine?(o=['
                                                                '],layui.each(i.colors,function(e,i){o.push(['
                                                                ','
                                                                ',"
                                                                "].join(""))}),o.push("
                                                                "),o.join("")):"",'
                                                                ','
                                                                ','',"
                                                                ",'
                                                                ','','',"","
                                                                "].join(""));e.elemColorBox.find("."+C)[0];m(a)[0]&&m(a).data("index")==e.index?e.removePicker(d.thisElemInd):(e.removePicker(d.thisElemInd),m("body").append(t)),n.thisId=i.id,d.thisElemInd=e.index,d.thisColor=r.style.background,e.position(),e.pickerEvents()},d.prototype.removePicker=function(e){var i=this.config,e=m("#layui-colorpicker"+(e||this.index));return e[0]&&(e.remove(),delete n.thisId,"function"==typeof i.close&&i.close(this.color)),this},d.prototype.position=function(){var e=this,i=e.config;return t.position(e.bindElem||e.elemColorBox[0],e.elemPicker[0],{position:i.position,align:"center"}),e},d.prototype.val=function(){var e,i=this,o=(i.config,i.elemColorBox.find("."+C)),r=i.elemPicker.find("."+M),t=o[0].style.backgroundColor;t?(e=Y(L(t)),o=o.attr("lay-type"),i.select(e.h,e.s,e.b),"torgb"===o?r.find("input").val(t):"rgba"===o?(o=L(t),3===(t.match(/[0-9]{1,3}/g)||[]).length?(r.find("input").val("rgba("+o.r+", "+o.g+", "+o.b+", 1)"),i.elemPicker.find("."+T).css("left",280)):(r.find("input").val(t),t=280*t.slice(t.lastIndexOf(",")+1,t.length-1),i.elemPicker.find("."+T).css("left",t)),i.elemPicker.find("."+D)[0].style.background="linear-gradient(to right, rgba("+o.r+", "+o.g+", "+o.b+", 0), rgb("+o.r+", "+o.g+", "+o.b+"))"):r.find("input").val("#"+F(e))):(i.select(0,100,100),r.find("input").val(""),i.elemPicker.find("."+D)[0].style.background="",i.elemPicker.find("."+T).css("left",280))},d.prototype.side=function(){var n=this,l=n.config,c=n.elemColorBox.find("."+C),a=c.attr("lay-type"),s=n.elemPicker.find(".layui-colorpicker-side"),e=n.elemPicker.find("."+B),d=n.elemPicker.find("."+I),r=n.elemPicker.find("."+E),f=n.elemPicker.find("."+D),u=n.elemPicker.find("."+T),g=e[0].offsetTop/180*360,p=100-(r[0].offsetTop+3)/180*100,h=(r[0].offsetLeft+3)/260*100,v=Math.round(u[0].offsetLeft/280*100)/100,b=n.elemColorBox.find("."+w),i=n.elemPicker.find(".layui-colorpicker-pre").children("div"),y=function(e,i,o,r){n.select(e,i,o);var t=j({h:e,s:i,b:o}),e=F({h:e,s:i,b:o}),i=n.elemPicker.find("."+M).find("input");b.addClass(x).removeClass(P),c[0].style.background="rgb("+t.r+", "+t.g+", "+t.b+")","torgb"===a?i.val("rgb("+t.r+", "+t.g+", "+t.b+")"):"rgba"===a?(u.css("left",280*r),i.val("rgba("+t.r+", "+t.g+", "+t.b+", "+r+")"),c[0].style.background="rgba("+t.r+", "+t.g+", "+t.b+", "+r+")",f[0].style.background="linear-gradient(to right, rgba("+t.r+", "+t.g+", "+t.b+", 0), rgb("+t.r+", "+t.g+", "+t.b+"))"):i.val("#"+e),l.change&&l.change(n.elemPicker.find("."+M).find("input").val())},o=m(['
                                                                '].join("")),k=function(e){m("#LAY-colorpicker-moving")[0]||m("body").append(o),o.on("mousemove",e),o.on("mouseup",function(){o.remove()}).on("mouseleave",function(){o.remove()})};e.on("mousedown",function(e){var r=this.offsetTop,t=e.clientY;k(function(e){var i=r+(e.clientY-t),o=s[0].offsetHeight,o=(i=o<(i=i<0?0:i)?o:i)/180*360;y(g=o,h,p,v),e.preventDefault()}),e.preventDefault()}),s.on("click",function(e){var i=e.clientY-m(this).offset().top+H.scrollTop(),i=(i=(i=i<0?0:i)>this.offsetHeight?this.offsetHeight:i)/180*360;y(g=i,h,p,v),e.preventDefault()}),r.on("mousedown",function(e){var n=this.offsetTop,l=this.offsetLeft,c=e.clientY,a=e.clientX;layui.stope(e),k(function(e){var i=n+(e.clientY-c),o=l+(e.clientX-a),r=d[0].offsetHeight-3,t=d[0].offsetWidth-3,t=((o=t<(o=o<-3?-3:o)?t:o)+3)/260*100,o=100-((i=r<(i=i<-3?-3:i)?r:i)+3)/180*100;y(g,h=t,p=o,v),e.preventDefault()}),e.preventDefault()}),d.on("mousedown",function(e){var i=e.clientY-m(this).offset().top-3+H.scrollTop(),o=e.clientX-m(this).offset().left-3+H.scrollLeft(),o=((i=i<-3?-3:i)>this.offsetHeight-3&&(i=this.offsetHeight-3),((o=(o=o<-3?-3:o)>this.offsetWidth-3?this.offsetWidth-3:o)+3)/260*100),i=100-(i+3)/180*100;y(g,h=o,p=i,v),layui.stope(e),e.preventDefault(),r.trigger(e,"mousedown")}),u.on("mousedown",function(e){var r=this.offsetLeft,t=e.clientX;k(function(e){var i=r+(e.clientX-t),o=f[0].offsetWidth,o=(o<(i=i<0?0:i)&&(i=o),Math.round(i/280*100)/100);y(g,h,p,v=o),e.preventDefault()}),e.preventDefault()}),f.on("click",function(e){var i=e.clientX-m(this).offset().left,i=((i=i<0?0:i)>this.offsetWidth&&(i=this.offsetWidth),Math.round(i/280*100)/100);y(g,h,p,v=i),e.preventDefault()}),i.each(function(){m(this).on("click",function(){m(this).parent(".layui-colorpicker-pre").addClass("selected").siblings().removeClass("selected");var e=this.style.backgroundColor,i=Y(L(e)),o=e.slice(e.lastIndexOf(",")+1,e.length-1);g=i.h,h=i.s,p=i.b,3===(e.match(/[0-9]{1,3}/g)||[]).length&&(o=1),v=o,y(i.h,i.s,i.b,o)})})},d.prototype.select=function(e,i,o,r){this.config;var t=F({h:e,s:100,b:100}),e=(F({h:e,s:i,b:o}),e/360*180),o=180-o/100*180-3,i=i/100*260-3;this.elemPicker.find("."+B).css("top",e),this.elemPicker.find("."+I)[0].style.background="#"+t,this.elemPicker.find("."+E).css({top:o,left:i})},d.prototype.pickerEvents=function(){var c=this,a=c.config,s=c.elemColorBox.find("."+C),d=c.elemPicker.find("."+M+" input"),o={clear:function(e){s[0].style.background="",c.elemColorBox.find("."+w).removeClass(x).addClass(P),c.color="",a.done&&a.done(""),c.removePicker()},confirm:function(e,i){var o,r,t,n,l=d.val();if(-1>16,g:(65280&t)>>8,b:255&t},r=Y(n),s[0].style.background=o="#"+F(r),c.elemColorBox.find("."+w).removeClass(P).addClass(x)),"change"===i)return c.select(r.h,r.s,r.b,i),void(a.change&&a.change(o));c.color=l,a.done&&a.done(l),c.removePicker()}};c.elemPicker.on("click","*[colorpicker-events]",function(){var e=m(this),i=e.attr("colorpicker-events");o[i]&&o[i].call(this,e)}),d.on("keyup",function(e){var i=m(this);o.confirm.call(this,i,13===e.keyCode?null:"change")})},d.prototype.events=function(){var e=this;e.config;e.elemColorBox.on("click",function(){e.renderPicker(),m(a)[0]&&(e.val(),e.side())})},s.on(i,function(e){var i,o,r;!n.thisId||(i=l.getThis(n.thisId))&&(o=i.config,r=i.elemColorBox.find("."+C),m(e.target).hasClass(c)||m(e.target).parents("."+c)[0]||m(e.target).hasClass(a.replace(/\./g,""))||m(e.target).parents(a)[0]||i.elemPicker&&(i.color?(e=Y(L(i.color)),i.select(e.h,e.s,e.b)):i.elemColorBox.find("."+w).removeClass(x).addClass(P),r[0].style.background=i.color||"","function"==typeof o.cancel&&o.cancel(i.color),i.removePicker()))}),H.on("resize",function(){if(n.thisId){var e=l.getThis(n.thisId);if(e)return!(!e.elemPicker||!m(a)[0])&&void e.position()}}),l.that={},l.getThis=function(e){var i=l.that[e];return i||o.error(e?r+" instance with ID '"+e+"' not found":"ID argument required"),i},n.render=function(e){e=new d(e);return l.call(e)},e(r,n)});layui.define("jquery",function(t){"use strict";var u=layui.$,d=(layui.hint(),layui.device()),o="element",c="layui-this",h="layui-show",r=".layui-tab-title",i=function(){this.config={}},y=(i.prototype.set=function(t){return u.extend(!0,this.config,t),this},i.prototype.on=function(t,i){return layui.onevent.call(this,o,t,i)},i.prototype.tabAdd=function(t,i){var a,e=u(".layui-tab[lay-filter="+t+"]"),l=e.children(r),n=l.children(".layui-tab-bar"),e=e.children(".layui-tab-content"),s=""+(i.title||"unnaming")+"";return n[0]?n.before(s):l.append(s),e.append('
                                                                '+(i.content||"")+"
                                                                "),i.change&&this.tabChange(t,i.id),l.data("LAY_TAB_CHANGE",i.change),g.tabAuto(i.change?"change":null),this},i.prototype.tabDelete=function(t,i){t=u(".layui-tab[lay-filter="+t+"]").children(r).find('>li[lay-id="'+i+'"]');return g.tabDelete(null,t),this},i.prototype.tabChange=function(t,i){t=u(".layui-tab[lay-filter="+t+"]").children(r).find('>li[lay-id="'+i+'"]');return g.tabClick.call(t[0],{liElem:t}),this},i.prototype.tab=function(a){a=a||{},e.on("click",a.headerElem,function(t){var i=u(this).index();g.tabClick.call(this,{index:i,options:a})})},i.prototype.progress=function(t,i){var a="layui-progress",t=u("."+a+"[lay-filter="+t+"]").find("."+a+"-bar"),a=t.find("."+a+"-text");return t.css("width",function(){return/^.+\/.+$/.test(i)?100*new Function("return "+i)()+"%":i}).attr("lay-percent",i),a.text(i),this},".layui-nav"),f="layui-nav-item",l="layui-nav-bar",p="layui-nav-tree",b="layui-nav-child",v="layui-nav-more",m="layui-anim layui-anim-upbit",g={tabClick:function(t){var i=(t=t||{}).options||{},a=t.liElem||u(this),e=i.headerElem?a.parent():a.parents(".layui-tab").eq(0),i=i.bodyElem?u(i.bodyElem):e.children(".layui-tab-content").children(".layui-tab-item"),l=a.find("a"),l="javascript:;"!==l.attr("href")&&"_blank"===l.attr("target"),n="string"==typeof a.attr("lay-unselect"),s=e.attr("lay-filter"),t="index"in t?t.index:a.parent().children("li").index(a);l||n||(a.addClass(c).siblings().removeClass(c),i.eq(t).addClass(h).siblings().removeClass(h)),layui.event.call(this,o,"tab("+s+")",{elem:e,index:t})},tabDelete:function(t,i){var i=i||u(this).parent(),a=i.parent().children("li").index(i),e=i.closest(".layui-tab"),l=e.children(".layui-tab-content").children(".layui-tab-item"),n=e.attr("lay-filter");i.hasClass(c)&&(i.next()[0]&&i.next().is("li")?g.tabClick.call(i.next()[0],{index:a+1}):i.prev()[0]&&i.prev().is("li")&&g.tabClick.call(i.prev()[0],null,a-1)),i.remove(),l.eq(a).remove(),setTimeout(function(){g.tabAuto()},50),layui.event.call(this,o,"tabDelete("+n+")",{elem:e,index:a})},tabAuto:function(l){var n="layui-tab-more",s="layui-tab-bar",o="layui-tab-close",c=this;u(".layui-tab").each(function(){var t,i=u(this),a=i.children(".layui-tab-title"),e=(i.children(".layui-tab-content").children(".layui-tab-item"),'lay-stope="tabmore"'),e=u('');c===window&&d.ie,i.attr("lay-allowclose")&&a.find("li").each(function(){var t,i=u(this);i.find("."+o)[0]||((t=u('')).on("click",g.tabDelete),i.append(t))}),"string"!=typeof i.attr("lay-unauto")&&(a.prop("scrollWidth")>a.outerWidth()+1||a.find("li").length&&a.height()>(t=a.find("li").eq(0).height())+t/2?("change"===l&&a.data("LAY_TAB_CHANGE")&&a.addClass(n),a.find("."+s)[0]||(a.append(e),i.attr("overflow",""),e.on("click",function(t){var i=a.hasClass(n);a[i?"removeClass":"addClass"](n)}))):(a.find("."+s).remove(),i.removeAttr("overflow")))})},hideTabMore:function(t){var i=u(".layui-tab-title");!0!==t&&"tabmore"===u(t.target).attr("lay-stope")||(i.removeClass("layui-tab-more"),i.find(".layui-tab-bar").attr("title",""))},clickThis:function(){var t=u(this),i=t.parents(y),a=i.attr("lay-filter"),e=t.parent(),l=t.siblings("."+b),n="string"==typeof e.attr("lay-unselect");"javascript:;"!==t.attr("href")&&"_blank"===t.attr("target")||n||l[0]||(i.find("."+c).removeClass(c),e.addClass(c)),i.hasClass(p)&&(l.removeClass(m),l[0]&&(e["none"===l.css("display")?"addClass":"removeClass"](f+"ed"),"all"===i.attr("lay-shrink")&&e.siblings().removeClass(f+"ed"))),layui.event.call(this,o,"nav("+a+")",t)},collapse:function(){var t=u(this),i=t.find(".layui-colla-icon"),a=t.siblings(".layui-colla-content"),e=t.parents(".layui-collapse").eq(0),l=e.attr("lay-filter"),n="none"===a.css("display");"string"==typeof e.attr("lay-accordion")&&((e=e.children(".layui-colla-item").children("."+h)).siblings(".layui-colla-title").children(".layui-colla-icon").html(""),e.removeClass(h)),a[n?"addClass":"removeClass"](h),i.html(n?"":""),layui.event.call(this,o,"collapse("+l+")",{title:t,content:a,show:n})}},a=(i.prototype.render=i.prototype.init=function(t,i){var a=i?'[lay-filter="'+i+'"]':"",i={tab:function(){g.tabAuto.call({})},nav:function(){var s={},o={},c={},r="layui-nav-title";u(y+a).each(function(t){var i=u(this),a=u(''),e=i.find("."+f);i.find("."+l)[0]||(i.append(a),(i.hasClass(p)?e.find("dd,>."+r):e).on("mouseenter",function(){!function(t,i,a){var e,l=u(this),n=l.find("."+b);i.hasClass(p)?n[0]||(e=l.children("."+r),t.css({top:l.offset().top-i.offset().top,height:(e[0]?e:l).outerHeight(),opacity:1})):(n.addClass(m),n.hasClass("layui-nav-child-c")&&n.css({left:-(n.outerWidth()-l.width())/2}),n[0]?t.css({left:t.position().left+t.width()/2,width:0,opacity:0}):t.css({left:l.position().left+parseFloat(l.css("marginLeft")),top:l.position().top+l.height()-t.height()}),s[a]=setTimeout(function(){t.css({width:n[0]?0:l.width(),opacity:n[0]?0:1})},d.ie&&d.ie<10?0:200),clearTimeout(c[a]),"block"===n.css("display")&&clearTimeout(o[a]),o[a]=setTimeout(function(){n.addClass(h),l.find("."+v).addClass(v+"d")},300))}.call(this,a,i,t)}).on("mouseleave",function(){i.hasClass(p)?a.css({height:0,opacity:0}):(clearTimeout(o[t]),o[t]=setTimeout(function(){i.find("."+b).removeClass(h),i.find("."+v).removeClass(v+"d")},300))}),i.on("mouseleave",function(){clearTimeout(s[t]),c[t]=setTimeout(function(){i.hasClass(p)||a.css({width:0,left:a.position().left+a.width()/2,opacity:0})},200)})),e.find("a").each(function(){var t=u(this);t.parent();t.siblings("."+b)[0]&&!t.children("."+v)[0]&&t.append(''),t.off("click",g.clickThis).on("click",g.clickThis)})})},breadcrumb:function(){u(".layui-breadcrumb"+a).each(function(){var t=u(this),i="lay-separator",a=t.attr(i)||"/",e=t.find("a");e.next("span["+i+"]")[0]||(e.each(function(t){t!==e.length-1&&u(this).after(""+a+"")}),t.css("visibility","visible"))})},progress:function(){var e="layui-progress";u("."+e+a).each(function(){var t=u(this),i=t.find(".layui-progress-bar"),a=i.attr("lay-percent");i.css("width",function(){return/^.+\/.+$/.test(a)?100*new Function("return "+a)()+"%":a}),t.attr("lay-showpercent")&&setTimeout(function(){i.html(''+a+"")},350)})},collapse:function(){u(".layui-collapse"+a).each(function(){u(this).find(".layui-colla-item").each(function(){var t=u(this),i=t.find(".layui-colla-title"),t="none"===t.find(".layui-colla-content").css("display");i.find(".layui-colla-icon").remove(),i.append(''+(t?"":"")+""),i.off("click",g.collapse).on("click",g.collapse)})})}};return i[t]?i[t]():layui.each(i,function(t,i){i()})},new i),e=u(document);u(function(){a.render()}),e.on("click",".layui-tab-title li",g.tabClick),u(window).on("resize",g.tabAuto),t(o,a)});layui.define(["lay","layer"],function(e){"use strict";var x=layui.$,i=layui.layer,b=layui.device(),t={config:{},set:function(e){var i=this;return i.config=x.extend({},i.config,e),i},on:function(e,i){return layui.onevent.call(this,n,e,i)}},n="upload",a="layui-upload-file",o="layui-upload-form",F="layui-upload-iframe",w="layui-upload-choose",L=function(e){var i=this;i.config=x.extend({},i.config,t.config,e),i.render()};L.prototype.config={accept:"images",exts:"",auto:!0,bindAction:"",url:"",force:"",field:"file",acceptMime:"",method:"post",data:{},drag:!0,size:0,number:0,multiple:!1,text:{"cross-domain":"Cross-domain requests are not supported","data-format-error":"Please return JSON data format","check-error":"",error:"","limit-number":null,"limit-size":null}},L.prototype.render=function(e){var i=this;(e=i.config).elem=x(e.elem),e.bindAction=x(e.bindAction),i.file(),i.events()},L.prototype.file=function(){var e=this,i=e.config,t=e.elemFile=x(['"].join("")),n=i.elem.next();(n.hasClass(a)||n.hasClass(o))&&n.remove(),b.ie&&b.ie<10&&i.elem.wrap('
                                                                '),e.isFile()?(e.elemFile=i.elem,i.field=i.elem[0].name):i.elem.after(t),b.ie&&b.ie<10&&e.initIE()},L.prototype.initIE=function(){var t,e=this.config,i=x(''),n=x(['
                                                                ',"
                                                                "].join(""));x("#"+F)[0]||x("body").append(i),e.elem.next().hasClass(o)||(this.elemFile.wrap(n),e.elem.next("."+o).append((t=[],layui.each(e.data,function(e,i){i="function"==typeof i?i():i,t.push('')}),t.join(""))))},L.prototype.msg=function(e){return i.msg(e,{icon:2,shift:6})},L.prototype.isFile=function(){var e=this.config.elem[0];if(e)return"input"===e.tagName.toLocaleLowerCase()&&"file"===e.type},L.prototype.preview=function(n){window.FileReader&&layui.each(this.chooseFiles,function(e,i){var t=new FileReader;t.readAsDataURL(i),t.onload=function(){n&&n(e,i,this.result)}})},L.prototype.upload=function(e,i){var t,n,a,o,r=this,u=r.config,c=u.text||{},l=r.elemFile[0],f=function(){return e||r.files||r.chooseFiles||l.files},s=function(){var i=0,a=0,o=f(),l=function(){u.multiple&&i+a===r.fileLength&&"function"==typeof u.allDone&&u.allDone({total:r.fileLength,successful:i,failed:a})},t=function(t){var n=new FormData,e=(layui.each(u.data,function(e,i){i="function"==typeof i?i():i,n.append(e,i)}),t.unified?layui.each(o,function(e,i){n.append(u.field,i)}):n.append(u.field,t.file),{url:u.url,type:"post",data:n,contentType:!1,processData:!1,dataType:"json",headers:u.headers||{},success:function(e){u.unified?i+=r.fileLength:i++,d(t.index,e),l()},error:function(e){u.unified?a+=r.fileLength:a++,r.msg(c.error||["Upload failed, please try again.","status: "+(e.status||"")+" - "+(e.statusText||"error")].join("
                                                                ")),m(t.index),l()}});"function"==typeof u.progress&&(e.xhr=function(){var e=x.ajaxSettings.xhr();return e.upload.addEventListener("progress",function(e){var i;e.lengthComputable&&(i=Math.floor(e.loaded/e.total*100),u.progress(i,(u.item||u.elem)[0],e,t.index))}),e}),x.ajax(e)};u.unified?t({unified:!0,index:0}):layui.each(o,function(e,i){t({index:e,file:i})})},p=function(){var n=x("#"+F);r.elemFile.parent().submit(),clearInterval(L.timer),L.timer=setInterval(function(){var e,i=n.contents().find("body");try{e=i.text()}catch(t){r.msg(c["cross-domain"]),clearInterval(L.timer),m()}e&&(clearInterval(L.timer),i.html(""),d(0,e))},30)},d=function(e,i){if(r.elemFile.next("."+w).remove(),l.value="","json"===u.force&&"object"!=typeof i)try{i=JSON.parse(i)}catch(t){return i={},r.msg(c["data-format-error"])}"function"==typeof u.done&&u.done(i,e||0,function(e){r.upload(e)})},m=function(e){u.auto&&(l.value=""),"function"==typeof u.error&&u.error(e||0,function(e){r.upload(e)})},h=u.exts,g=(n=[],layui.each(e||r.chooseFiles,function(e,i){n.push(i.name)}),n),v={preview:function(e){r.preview(e)},upload:function(e,i){var t={};t[e]=i,r.upload(t)},pushFile:function(){return r.files=r.files||{},layui.each(r.chooseFiles,function(e,i){r.files[e]=i}),r.files},resetFile:function(e,i,t){i=new File([i],t);r.files=r.files||{},r.files[e]=i}},y={file:"\u6587\u4ef6",images:"\u56fe\u7247",video:"\u89c6\u9891",audio:"\u97f3\u9891"}[u.accept]||"\u6587\u4ef6",g=0===g.length?l.value.match(/[^\/\\]+\..+/g)||[]||"":g;if(0!==g.length){switch(u.accept){case"file":layui.each(g,function(e,i){if(h&&!RegExp(".\\.("+h+")$","i").test(escape(i)))return t=!0});break;case"video":layui.each(g,function(e,i){if(!RegExp(".\\.("+(h||"avi|mp4|wma|rmvb|rm|flash|3gp|flv")+")$","i").test(escape(i)))return t=!0});break;case"audio":layui.each(g,function(e,i){if(!RegExp(".\\.("+(h||"mp3|wav|mid")+")$","i").test(escape(i)))return t=!0});break;default:layui.each(g,function(e,i){if(!RegExp(".\\.("+(h||"jpg|png|gif|bmp|jpeg|svg")+")$","i").test(escape(i)))return t=!0})}if(t)return r.msg(c["check-error"]||"\u9009\u62e9\u7684"+y+"\u4e2d\u5305\u542b\u4e0d\u652f\u6301\u7684\u683c\u5f0f"),l.value="";if("choose"!==i&&!u.auto||(u.choose&&u.choose(v),"choose"!==i)){if(r.fileLength=(a=0,y=f(),layui.each(y,function(){a++}),a),u.number&&r.fileLength>u.number)return r.msg("function"==typeof c["limit-number"]?c["limit-number"](u,r.fileLength):"\u540c\u65f6\u6700\u591a\u53ea\u80fd\u4e0a\u4f20: "+u.number+" \u4e2a\u6587\u4ef6
                                                                \u60a8\u5f53\u524d\u5df2\u7ecf\u9009\u62e9\u4e86: "+r.fileLength+" \u4e2a\u6587\u4ef6");if(01024*u.size&&(i=1<=(i=u.size/1024)?i.toFixed(2)+"MB":u.size+"KB",l.value="",o=i)}),o)return r.msg("function"==typeof c["limit-size"]?c["limit-size"](u,o):"\u6587\u4ef6\u5927\u5c0f\u4e0d\u80fd\u8d85\u8fc7 "+o);if(!u.before||!1!==u.before(v))b.ie?(9'+e+"")},r=function(){var e=x(this);(e.attr("lay-data")||e.attr("lay-options"))&&(n.config=x.extend({},a,lay.options(this,{attr:e.attr("lay-data")?"lay-data":null})))};a.elem.off("upload.start").on("upload.start",function(){var e=x(this);r.call(this),n.config.item=e,n.elemFile[0].click()}),b.ie&&b.ie<10||a.elem.off("upload.over").on("upload.over",function(){x(this).attr("lay-over","")}).off("upload.leave").on("upload.leave",function(){x(this).removeAttr("lay-over")}).off("upload.drop").on("upload.drop",function(e,i){var t=x(this),i=i.originalEvent.dataTransfer.files||[];t.removeAttr("lay-over"),r.call(this),o(i),a.auto?n.upload():l(i)}),n.elemFile.off("upload.change").on("upload.change",function(){var e=this.files||[];0!==e.length&&(r.call(this),o(e),a.auto?n.upload():l(e))}),a.bindAction.off("upload.action").on("upload.action",function(){n.upload()}),a.elem.data("haveEvents")||(n.elemFile.on("change",function(){x(this).trigger("upload.change")}),a.elem.on("click",function(){n.isFile()||x(this).trigger("upload.start")}),a.drag&&a.elem.on("dragover",function(e){e.preventDefault(),x(this).trigger("upload.over")}).on("dragleave",function(e){x(this).trigger("upload.leave")}).on("drop",function(e){e.preventDefault(),x(this).trigger("upload.drop",e)}),a.bindAction.on("click",function(){x(this).trigger("upload.action")}),a.elem.data("haveEvents",!0))},t.render=function(e){e=new L(e);return function(){var i=this;return{upload:function(e){i.upload.call(i,e)},reload:function(e){i.reload.call(i,e)},config:i.config}}.call(e)},e(n,t)});layui.define(["lay","layer","util"],function(e){"use strict";var C=layui.$,y=layui.layer,d=layui.util,n=layui.hint(),w=(layui.device(),"form"),o=".layui-form",T="layui-this",N="layui-hide",$="layui-disabled",t=function(){this.config={verify:{required:[/[\S]+/,"\u5fc5\u586b\u9879\u4e0d\u80fd\u4e3a\u7a7a"],phone:[/^1\d{10}$/,"\u8bf7\u8f93\u5165\u6b63\u786e\u7684\u624b\u673a\u53f7"],email:[/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,"\u90ae\u7bb1\u683c\u5f0f\u4e0d\u6b63\u786e"],url:[/^(#|(http(s?)):\/\/|\/\/)[^\s]+\.[^\s]+$/,"\u94fe\u63a5\u683c\u5f0f\u4e0d\u6b63\u786e"],number:function(e){if(isNaN(e))return"\u53ea\u80fd\u586b\u5199\u6570\u5b57"},date:[/^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/,"\u65e5\u671f\u683c\u5f0f\u4e0d\u6b63\u786e"],identity:[/(^\d{15}$)|(^\d{17}(x|X|\d)$)/,"\u8bf7\u8f93\u5165\u6b63\u786e\u7684\u8eab\u4efd\u8bc1\u53f7"]},verIncludeRequired:!1,autocomplete:null}},i=(t.prototype.set=function(e){return C.extend(!0,this.config,e),this},t.prototype.verify=function(e){return C.extend(!0,this.config.verify,e),this},t.prototype.getFormElem=function(e){return C(o+(e?'[lay-filter="'+e+'"]':""))},t.prototype.on=function(e,t){return layui.onevent.call(this,w,e,t)},t.prototype.val=function(e,i){return this.getFormElem(e).each(function(e,t){var a=C(this);layui.each(i,function(e,t){var i,e=a.find('[name="'+e+'"]');e[0]&&("checkbox"===(i=e[0].type)?e[0].checked=t:"radio"===i?e.each(function(){this.checked=this.value==t}):e.val(t))})}),r.render(null,e),this.getValue(e)},t.prototype.getValue=function(e,t){t=t||this.getFormElem(e);var a={},l={},e=t.find("input,select,textarea");return layui.each(e,function(e,t){var i;C(this);t.name=(t.name||"").replace(/^\s*|\s*&/,""),t.name&&(/^.*\[\]$/.test(t.name)&&(i=t.name.match(/^(.*)\[\]$/g)[0],a[i]=0|a[i],i=t.name.replace(/^(.*)\[\]$/,"$1["+a[i]+++"]")),/^(checkbox|radio)$/.test(t.type)&&!t.checked||(l[i||t.name]=t.value))}),l},t.prototype.render=function(e,t){var i=this.config,a=C(o+(t?'[lay-filter="'+t+'"]':"")),l={input:function(e){e=e||a.find("input,textarea");i.autocomplete&&e.attr("autocomplete",i.autocomplete),a.find("input[lay-affix],textarea[lay-affix]").each(function(){var r=C(this),s=r.attr("lay-affix"),o="layui-input-wrap",c="layui-input-suffix",u="layui-input-affix",e=r.is("[disabled]")||r.is("[readonly]"),d=function(e,t){(e=C(e))[0]&&e[C.trim(t)?"removeClass":"addClass"](N)},l=function(i){i=C.extend({},f[s]||{value:s},i,lay.options(r[0]));var a,t=C('
                                                                '),e=layui.isArray(i.value)?i.value:[i.value],e=C((a=[],layui.each(e,function(e,t){a.push('')}),a.join(""))),l=(t.append(e),i.split&&t.addClass("layui-input-split"),i.className&&t.addClass(i.className),r.next("."+u)),n=(l[0]&&l.remove(),r.parent().hasClass(o)||r.wrap('
                                                                '),r.next("."+c));n[0]?((l=n.find("."+u))[0]&&l.remove(),n.prepend(t),r.css("padding-right",function(){return(r.closest(".layui-input-group")[0]?0:n.outerWidth())+t.outerWidth()})):(t.addClass(c),r.after(t)),"auto"===i.show&&d(t,r.val()),r.on("input propertychange",function(){var e=this.value;"auto"===i.show&&d(t,e)}),e.on("click",function(){var e=r.attr("lay-filter");C(this).hasClass($)||("function"==typeof i.click&&i.click.call(this,r,i),layui.event.call(this,w,"input-affix("+e+")",{elem:r[0],affix:s,options:i}))})},f={eye:{value:"eye-invisible",click:function(e,t){var i="LAY_FORM_INPUT_AFFIX_SHOW",a=e.data(i);e.attr("type",a?"password":"text").data(i,!a),l({value:a?"eye-invisible":"eye"})}},clear:{value:"clear",click:function(e){e.val("").focus(),d(C(this).parent(),null)},show:"auto",disabled:e},number:{value:["up","down"],split:!0,className:"layui-input-number",disabled:r.is("[disabled]"),click:function(e){var t=C(this).index(),i=e.val(),a=i,l=Number(e.attr("step"))||1,n=Number(e.attr("min")),r=Number(e.attr("max"));isNaN(i)||(i=Number(i),r<(i=(i=t?i-l:i+l)q.height()&&t<=e&&a.addClass(m+"up"),o()},l=function(e){a.removeClass(m+"ed "+m+"up"),d.blur(),s=null,e||n(d.val(),function(e){var t=c[0].selectedIndex;e&&(k=C(c[0].options[t]).html(),0===t&&k===d.attr("placeholder")&&(k=""),d.val(k||""))})},o=function(){var e,t,i=f.children("dd."+T);i[0]&&(e=i.position().top,t=f.height(),i=i.height(),t\u65e0\u5339\u914d\u9879

                                                                '):f.find("."+x).remove()},"keyup"),""===t&&(c.val(""),f.find("."+T).removeClass(T),(c[0].options[0]||{}).value||f.children("dd:eq(0)").addClass(T),f.find("."+x).remove()),o()}).on("blur",function(e){var t=c[0].selectedIndex;p=d,k=C(c[0].options[t]).text(),0===t&&k===d.attr("placeholder")&&(k=""),setTimeout(function(){n(d.val(),function(e){k||d.val("")},"blur")},200)}),h.on("click",function(){var e=C(this),t=e.attr("lay-value"),i=c.attr("lay-filter");return e.hasClass($)||(e.hasClass("layui-select-tips")?d.val(""):(d.val(e.text()),e.addClass(T)),e.siblings().removeClass(T),c.val(t).removeClass("layui-form-danger"),layui.event.call(this,w,"select("+i+")",{elem:c[0],value:t,othis:a}),l(!0)),!1}),a.find("dl>dt").on("click",function(e){return!1}),C(document).off("click",b).on("click",b))};e.each(function(e,t){var i=C(this),a=i.next("."+m),l=this.disabled,n=t.value,r=C(t.options[t.selectedIndex]),t=t.options[0];if("string"==typeof i.attr("lay-ignore"))return i.show();var s,o="string"==typeof i.attr("lay-search"),t=t&&!t.value&&t.innerHTML||c,r=C(['
                                                                ','
                                                                ','','
                                                                ','
                                                                ',(t=i.find("*"),s=[],layui.each(t,function(e,t){var i=t.tagName.toLowerCase();0!==e||t.value||"optgroup"===i?"optgroup"===i?s.push("
                                                                "+t.label+"
                                                                "):s.push('
                                                                '+C.trim(t.innerHTML)+"
                                                                "):s.push('
                                                                '+C.trim(t.innerHTML||c)+"
                                                                ")}),0===s.length&&s.push('
                                                                \u6ca1\u6709\u9009\u9879
                                                                '),s.join("")+"
                                                                "),"
                                                                "].join(""));a[0]&&a.remove(),i.after(r),u.call(this,r,l,o)})},checkbox:function(e){var o={checkbox:["layui-form-checkbox","layui-form-checked","checkbox"],"switch":["layui-form-switch","layui-form-onswitch","switch"],SUBTRA:"layui-icon-indeterminate"},e=e||a.find("input[type=checkbox]");e.each(function(e,t){var i=C(this),a=i.attr("lay-skin")||"primary",l=d.escape(C.trim(t.title||(t.title=i.attr("lay-text")||""))),n=this.disabled,r=o[a]||o.checkbox,s=i.next("."+r[0]);if(s[0]&&s.remove(),i.next("[lay-checkbox]")[0]&&(l=i.next().html()||""),l="switch"===a?l.split("|"):[l],"string"==typeof i.attr("lay-ignore"))return i.show();n=C(['
                                                                ",(s={checkbox:[l[0]?"
                                                                "+l[0]+"
                                                                ":"primary"===a?"":"
                                                                ",''].join(""),"switch":"
                                                                "+((t.checked?l[0]:l[1])||"")+"
                                                                "})[a]||s.checkbox,"
                                                                "].join(""));i.after(n),function(a,l){var n=C(this);a.on("click",function(){var e=C(this),t=n.attr("lay-filter"),e=e.next("*[lay-checkbox]")[0]?e.next().html():n.attr("title")||"",i=n.attr("lay-skin")||"primary",e="switch"===i?e.split("|"):[e];n[0].disabled||(n[0].indeterminate&&(n[0].indeterminate=!1,a.find("."+o.SUBTRA).removeClass(o.SUBTRA).addClass("layui-icon-ok")),n[0].checked?(n[0].checked=!1,a.removeClass(l[1]),"switch"===i&&a.children("div").html(e[1])):(n[0].checked=!0,a.addClass(l[1]),"switch"===i&&a.children("div").html(e[0])),layui.event.call(n[0],w,l[2]+"("+t+")",{elem:n[0],value:n[0].value,othis:a}))})}.call(this,n,r)})},radio:function(e){var r="layui-form-radio",s=["layui-icon-radio","layui-icon-circle"],e=e||a.find("input[type=radio]");e.each(function(e,t){var i=C(this),a=i.next("."+r),l=this.disabled;if("string"==typeof i.attr("lay-ignore"))return i.show();a[0]&&a.remove();l=C(['
                                                                ','',"
                                                                "+(a=d.escape(t.title||""),a=i.next("[lay-radio]")[0]?i.next().html():a)+"
                                                                ","
                                                                "].join(""));i.after(l),function(a){var l=C(this),n="layui-anim-scaleSpring";a.on("click",function(){var e=l[0].name,t=l.parents(o),i=l.attr("lay-filter"),e=t.find("input[name="+e.replace(/(\.|#|\[|\])/g,"\\$1")+"]");l[0].disabled||(layui.each(e,function(){var e=C(this).next("."+r);this.checked=!1,e.removeClass(r+"ed"),e.children(".layui-icon").removeClass(n+" "+s[0]).addClass(s[1])}),l[0].checked=!0,a.addClass(r+"ed"),a.children(".layui-icon").addClass(n+" "+s[0]),layui.event.call(l[0],w,"radio("+i+")",{elem:l[0],value:l[0].value,othis:a}))})}.call(this,l)})}},t=function(){layui.each(l,function(e,t){t()})};return"object"===layui.type(e)?C(e).is(o)?(a=C(e),t()):e.each(function(e,t){var i=C(t);i.closest(o).length&&("SELECT"===t.tagName?l.select(i):"INPUT"===t.tagName&&("checkbox"===(t=t.type)||"radio"===t?l[t](i):l.input(i)))}):e?l[e]?l[e]():n.error('\u4e0d\u652f\u6301\u7684 "'+e+'" \u8868\u5355\u6e32\u67d3'):t(),this},t.prototype.validate=function(e){var u=null,d=this.config,f=d.verify,h="layui-form-danger";return!(e=C(e))[0]||(e.attr("lay-verify")!==undefined||!1!==this.validate(e.find("*[lay-verify]")))&&(layui.each(e,function(e,r){var s=C(this),t=(s.attr("lay-verify")||"").split("|"),o=s.attr("lay-vertype"),c=C.trim(s.val());if(s.removeClass(h),layui.each(t,function(e,t){var i="",a=f[t];if(a){var l="function"==typeof a?i=a(c,r):!a[0].test(c),n="select"===r.tagName.toLowerCase()||/^(checkbox|radio)$/.test(r.type),i=i||a[1];if("required"===t&&(i=s.attr("lay-reqtext")||i),l&&(d.verIncludeRequired||"required"===t||c&&"required"!==t))return"tips"===o?y.tips(i,"string"!=typeof s.attr("lay-ignore")&&n?s.next():s,{tips:1}):"alert"===o?y.alert(i,{title:"\u63d0\u793a",shadeClose:!0}):/\b(string|number)\b/.test(typeof i)&&y.msg(i,{icon:5,shift:6}),setTimeout(function(){(n?s.next().find("input"):r).focus()},7),s.addClass(h),u=!0}}),u)return u}),!u)},t.prototype.submit=function(e,t){var i=C(this),e="string"==typeof e?e:i.attr("lay-filter"),a=this.getFormElem?this.getFormElem(e):i.parents(o).eq(0),l=a.find("*[lay-verify]");if(!r.validate(l))return!1;l=r.getValue(null,a),a={elem:this.getFormElem?window.event&&window.event.target:this,form:(this.getFormElem?a:i.parents("form"))[0],field:l};return"function"==typeof t&&t(a),layui.event.call(this,w,"submit("+e+")",a)}),r=new t,t=C(document),q=C(window);C(function(){r.render()}),t.on("reset",o,function(){var e=C(this).attr("lay-filter");setTimeout(function(){r.render(null,e)},50)}),t.on("submit",o,i).on("click","*[lay-submit]",i),e(w,r)});layui.define(["lay","laytpl","laypage","form","util"],function(n){"use strict";var p=layui.$,r=layui.lay,m=layui.laytpl,z=layui.laypage,f=layui.layer,v=layui.form,g=layui.util,y=layui.hint(),b=layui.device(),x={config:{checkName:"LAY_CHECKED",indexName:"LAY_INDEX",numbersName:"LAY_NUM",disabledName:"LAY_DISABLED"},cache:{},index:layui.table?layui.table.index+1e4:0,set:function(e){var t=this;return t.config=p.extend({},t.config,e),t},on:function(e,t){return layui.onevent.call(this,T,e,t)}},k=function(){var a=this,e=a.config,i=e.id||e.index;return{config:e,reload:function(e,t){a.reload.call(a,e,t)},reloadData:function(e,t){x.reloadData(i,e,t)},setColsWidth:function(){a.setColsWidth.call(a)},resize:function(){a.resize.call(a)}}},C=function(e){var t=k.that[e];return t||y.error(e?"The table instance with ID '"+e+"' not found":"ID argument required"),t||null},l=function(e){var t=k.config[e];return t||y.error(e?"The table instance with ID '"+e+"' not found":"ID argument required"),t||null},w=function(e){var t=this.config||{},a=(e=e||{}).item3,i=e.content;"numbers"===a.type&&(i=e.tplData[x.config.numbersName]);("escape"in a?a:t).escape&&(i=g.escape(i));t=e.text&&a.exportTemplet||a.templet||a.toolbar;return t&&(i="function"==typeof t?t.call(a,e.tplData,e.obj):m(p(t).html()||String(i)).render(p.extend({LAY_COL:a},e.tplData))),e.text?p("
                                                                "+i+"
                                                                ").text():i},T="table",t=".layui-table",N="layui-hide",h="layui-hide-v",L="layui-none",R="layui-table-view",o=".layui-table-header",D=".layui-table-body",_=".layui-table-pageview",A=".layui-table-sort",E="layui-table-checked",W="layui-table-edit",j="layui-table-hover",H="laytable-cell-group",M="layui-table-col-special",S="layui-table-tool-panel",I="LAY_TABLE_MOVE_DICT",e=function(e){return['',"","{{# layui.each(d.data.cols, function(i1, item1){ }}","","{{# layui.each(item1, function(i2, item2){ }}",'{{# if(item2.fixed && item2.fixed !== "right"){ left = true; } }}','{{# if(item2.fixed === "right"){ right = true; } }}',(e=e||{}).fixed&&"right"!==e.fixed?'{{# if(item2.fixed && item2.fixed !== "right"){ }}':"right"===e.fixed?'{{# if(item2.fixed === "right"){ }}':"","{{# var isSort = !(item2.colGroup) && item2.sort; }}",'",e.fixed?"{{# }; }}":"","{{# }); }}","","{{# }); }}","","
                                                                ','
                                                                ','{{# if(item2.type === "checkbox"){ }}','',"{{# } else { }}",'{{-item2.title||""}}',"{{# if(isSort){ }}",'',"{{# } }}","{{# } }}","
                                                                ","
                                                                "].join("")},a=['',"","
                                                                "].join(""),c=[,"{{# if(d.data.toolbar){ }}",'
                                                                ','
                                                                ','
                                                                ',"
                                                                ","{{# } }}",'
                                                                ',"{{# if(d.data.loading){ }}",'
                                                                ','',"
                                                                ","{{# } }}","{{# var left, right; }}",'
                                                                ',e(),"
                                                                ",'
                                                                ',a,"
                                                                ","{{# if(left){ }}",'
                                                                ','
                                                                ',e({fixed:!0}),"
                                                                ",'
                                                                ',a,"
                                                                ","
                                                                ","{{# }; }}","{{# if(right){ }}",'
                                                                ','
                                                                ',e({fixed:"right"}),'
                                                                ',"
                                                                ",'
                                                                ',a,"
                                                                ","
                                                                ","{{# }; }}","
                                                                ","{{# if(d.data.totalRow){ }}",'
                                                                ','','',"
                                                                ","
                                                                ","{{# } }}",'
                                                                ','
                                                                ',"
                                                                ",""].join(""),O=p(window),P=p(document),i=function(e){this.index=++x.index,this.config=p.extend({},this.config,x.config,e),this.render()},d=(i.prototype.config={limit:10,loading:!0,escape:!0,cellMinWidth:60,cellMaxWidth:Number.MAX_VALUE,editTrigger:"click",defaultToolbar:["filter","exports","print"],defaultContextmenu:!0,autoSort:!0,text:{none:"\u65e0\u6570\u636e"},cols:[]},i.prototype.render=function(e){var t=this,a=t.config,i=(a.elem=p(a.elem),a.where=a.where||{},a.id="id"in a?a.id:a.elem.attr("id")||t.index);if(k.that[i]=t,(k.config[i]=a).request=p.extend({pageName:"page",limitName:"limit"},a.request),a.response=p.extend({statusName:"code",statusCode:0,msgName:"msg",dataName:"data",totalRowName:"totalRow",countName:"count"},a.response),null!==a.page&&"object"==typeof a.page&&(a.limit=a.page.limit||a.limit,a.limits=a.page.limits||a.limits,t.page=a.page.curr=a.page.curr||1,delete a.page.elem,delete a.page.jump),!a.elem[0])return t;if(a.elem.attr("lay-filter")||a.elem.attr("lay-filter",a.id),"reloadData"===e)return t.pullData(t.page,{type:"reloadData"});a.index=t.index,t.key=a.id||a.index,t.setInit(),a.height&&/^full-\d+$/.test(a.height)?(t.fullHeightGap=a.height.split("-")[1],a.height=O.height()-t.fullHeightGap):a.height&&/^#\w+\S*-\d+$/.test(a.height)&&(i=a.height.split("-"),t.parentHeightGap=i.pop(),t.parentDiv=i.join("-"),a.height=p(t.parentDiv).height()-t.parentHeightGap);var l,e=a.elem,i=e.next("."+R),n=t.elem=p("
                                                                ");n.addClass((l=[R,R+"-"+t.index,"layui-form","layui-border-box"],a.className&&l.push(a.className),l.join(" "))).attr({"lay-filter":"LAY-TABLE-FORM-DF-"+t.index,"lay-id":a.id,style:(l=[],a.width&&l.push("width:"+a.width+"px;"),l.join(""))}).html(m(c,{open:"{{",close:"}}"}).render({data:a,index:t.index})),i[0]&&i.remove(),e.after(n),t.layTool=n.find(".layui-table-tool"),t.layBox=n.find(".layui-table-box"),t.layHeader=n.find(o),t.layMain=n.find(".layui-table-main"),t.layBody=n.find(D),t.layFixed=n.find(".layui-table-fixed"),t.layFixLeft=n.find(".layui-table-fixed-l"),t.layFixRight=n.find(".layui-table-fixed-r"),t.layTotal=n.find(".layui-table-total"),t.layPage=n.find(".layui-table-page"),t.renderToolbar(),t.renderPagebar(),t.fullSize(),t.pullData(t.page),t.events()},i.prototype.initOpts=function(e){this.config;e.checkbox&&(e.type="checkbox"),e.space&&(e.type="space"),e.type||(e.type="normal"),"normal"!==e.type&&(e.unresize=!0,e.width=e.width||{checkbox:50,radio:50,space:30,numbers:60}[e.type])},i.prototype.setInit=function(e){var l,a,d=this,r=d.config;if(r.clientWidth=r.width||(l=function(e){var t,a=(e=e||r.elem.parent()).width();try{t="none"===e.css("display")}catch(i){}return!e[0]||a&&!t?a:l(e.parent())})(),"width"===e)return r.clientWidth;r.height=r.maxHeight||r.height,r.css&&-1===r.css.indexOf(R)&&(a=r.css.split("}"),layui.each(a,function(e,t){t&&(a[e]="."+R+"-"+d.index+" "+t)}),r.css=a.join("}"));var c=function(a,e,i,l){var n,o;l?(l.key=[r.index,a,i].join("-"),l.colspan=l.colspan||0,l.rowspan=l.rowspan||0,d.initOpts(l),(n=a+(parseInt(l.rowspan)||1))
                                                                ','
                                                                ','
                                                                '].join(""),a=this.layTool.find(".layui-table-tool-temp"),i=("default"===e.toolbar?a.html(t):"string"==typeof e.toolbar&&(t=p(e.toolbar).html()||"")&&a.html(m(t).render(e)),{filter:{title:"\u7b5b\u9009\u5217",layEvent:"LAYTABLE_COLS",icon:"layui-icon-cols"},exports:{title:"\u5bfc\u51fa",layEvent:"LAYTABLE_EXPORT",icon:"layui-icon-export"},print:{title:"\u6253\u5370",layEvent:"LAYTABLE_PRINT",icon:"layui-icon-print"}}),l=[];"object"==typeof e.defaultToolbar&&layui.each(e.defaultToolbar,function(e,t){t="string"==typeof t?i[t]:t;t&&l.push('
                                                                ')}),this.layTool.find(".layui-table-tool-self").html(l.join(""))},i.prototype.renderPagebar=function(){var e,t=this.config,a=this.layPagebar=p('
                                                                ');t.pagebar&&((e=p(t.pagebar).html()||"")&&a.append(m(e).render(t)),this.layPage.append(a))},i.prototype.setParentCol=function(e,t){var a=this.config,i=this.layHeader.find('th[data-key="'+t+'"]'),l=parseInt(i.attr("colspan"))||0;i[0]&&(t=t.split("-"),t=a.cols[t[1]][t[2]],e?l--:l++,i.attr("colspan",l),i[l?"removeClass":"addClass"](N),t.colspan2=l,t.hide=l<1,(a=i.data("parentkey"))&&this.setParentCol(e,a))},i.prototype.setColsPatch=function(){var a=this,e=a.config;layui.each(e.cols,function(e,t){layui.each(t,function(e,t){t.hide&&a.setParentCol(t.hide,t.parentKey)})})},i.prototype.setGroupWidth=function(i){var e,l=this;l.config.cols.length<=1||((e=l.layHeader.find((i?"th[data-key="+i.data("parentkey")+"]>":"")+"."+H)).css("width",0),layui.each(e.get().reverse(),function(){var e=p(this),t=e.parent().data("key"),a=0;l.layHeader.eq(0).find("th[data-parentkey="+t+"]").width(function(e,t){p(this).hasClass(N)||0 tr:first-child > th:last-child")).data("field")&&e.prev()[0]?t(e.prev()):e})()).data("key"),n.getCssRule(e,function(e){var t=e.style.width||a.outerWidth();e.style.width=parseFloat(t)+l+"px",0'+(e||"Error")+"
                                                                ");a[0]&&(t.layNone.remove(),a.remove()),t.layFixed.addClass(N),t.layMain.find("tbody").html(""),t.layMain.append(t.layNone=e),t.layTotal.addClass(h),t.layPage.find(_).addClass(h),x.cache[t.key]=[],t.syncCheckAll(),t.renderForm(),t.setColsWidth()},i.prototype.page=1,i.prototype.pullData=function(a,t){var e,i,l=this,n=l.config,o=(n.HAS_SET_COLS_PATCH||l.setColsPatch(),n.HAS_SET_COLS_PATCH=!0,n.request),d=n.response,r=function(){"object"==typeof n.initSort&&l.sort({field:n.initSort.field,type:n.initSort.type,reloadType:t.type})},c=function(e,t){l.setColsWidth(),"function"==typeof n.done&&n.done(e,a,e[d.countName],t)};t=t||{},"function"==typeof n.before&&n.before(n),l.startTime=(new Date).getTime(),t.renderData?((e={})[d.dataName]=x.cache[l.key],e[d.countName]=n.url?"object"===layui.type(n.page)?n.page.count:e[d.dataName].length:n.data.length,"object"==typeof n.totalRow&&(e[d.totalRowName]=p.extend({},l.totalRow)),l.renderData({res:e,curr:a,count:e[d.countName],type:t.type}),r(),c(e,"renderData")):n.url?(i={},n.page&&(i[o.pageName]=a,i[o.limitName]=n.limit),o=p.extend(i,n.where),n.contentType&&0==n.contentType.indexOf("application/json")&&(o=JSON.stringify(o)),l.loading(),p.ajax({type:n.method||"get",url:n.url,contentType:n.contentType,data:o,dataType:n.dataType||"json",jsonpCallback:n.jsonpCallback,headers:n.headers||{},success:function(e){(e="function"==typeof n.parseData?n.parseData(e)||e:e)[d.statusName]!=d.statusCode?l.errorView(e[d.msgName]||'\u8fd4\u56de\u7684\u6570\u636e\u4e0d\u7b26\u5408\u89c4\u8303\uff0c\u6b63\u786e\u7684\u6210\u529f\u72b6\u6001\u7801\u5e94\u4e3a\uff1a"'+d.statusName+'": '+d.statusCode):(l.totalRow=e[d.totalRowName],l.renderData({res:e,curr:a,count:e[d.countName],type:t.type}),r(),n.time=(new Date).getTime()-l.startTime+" ms"),c(e)},error:function(e,t){l.errorView("\u8bf7\u6c42\u5f02\u5e38\uff0c\u9519\u8bef\u63d0\u793a\uff1a"+t),"function"==typeof n.error&&n.error(e,t)}})):"array"===layui.type(n.data)&&(e={},i=a*n.limit-n.limit,o=n.data.concat(),e[d.dataName]=n.page?o.splice(i,n.limit):o,e[d.countName]=n.data.length,"object"==typeof n.totalRow&&(e[d.totalRowName]=p.extend({},n.totalRow)),l.totalRow=e[d.totalRowName],l.renderData({res:e,curr:a,count:e[d.countName],type:t.type}),r(),c(e))},i.prototype.eachCols=function(e){return x.eachCols(null,e,this.config.cols),this},i.prototype.col=function(e){try{return e=e.split("-"),this.config.cols[e[1]][e[2]]||{}}catch(t){return y.error(t),{}}},i.prototype.getTrHtml=function(a,l,n,e){var s=this,u=s.config,y=e&&e.trs||[],h=e&&e.trs_fixed||[],f=e&&e.trs_fixed_r||[];return n=n||1,layui.each(a,function(e,o){var i=[],d=[],r=[],c=e+u.limit*(n-1)+1;if("object"!=typeof o){a[e]=o={LAY_KEY:o};try{x.cache[s.key][e]=o}catch(t){}}"array"===layui.type(o)&&0===o.length||(o[x.config.numbersName]=c,l||(o[x.config.indexName]=e),s.eachCols(function(e,l){var t,e=l.field||e,a=l.key,n=o[e];n!==undefined&&null!==n||(n=""),l.colGroup||(t=['','
                                                                "+function(){var e,t=p.extend(!0,{LAY_COL:l},o),a=x.config.checkName,i=x.config.disabledName;switch(l.type){case"checkbox":return'';case"radio":return'';case"numbers":return c}return l.toolbar?m(p(l.toolbar).html()||"").render(t):w.call(s,{item3:l,content:n,tplData:t})}(),"
                                                                "].join(""),i.push(t),l.fixed&&"right"!==l.fixed&&d.push(t),"right"===l.fixed&&r.push(t))}),e=['data-index="'+e+'"'],o[x.config.checkName]&&e.push('class="'+E+'"'),e=e.join(" "),y.push(""+i.join("")+""),h.push(""+d.join("")+""),f.push(""+r.join("")+""))}),{trs:y,trs_fixed:h,trs_fixed_r:f}},x.getTrHtml=function(e,t){e=C(e);return e.getTrHtml(t,null,e.page)},i.prototype.renderData=function(e){var a=this,i=a.config,t=e.res,l=e.curr,n=a.count=e.count,o=e.sort,d=t[i.response.dataName]||[],t=t[i.response.totalRowName],r=[],c=[],s=[],u=function(){if(!o&&a.sortKey)return a.sort({field:a.sortKey.field,type:a.sortKey.sort,pull:!0,reloadType:e.type});a.getTrHtml(d,o,l,{trs:r,trs_fixed:c,trs_fixed_r:s}),"fixed"===i.scrollPos&&"reloadData"===e.type||a.layBody.scrollTop(0),"reset"===i.scrollPos&&a.layBody.scrollLeft(0),a.layMain.find("."+L).remove(),a.layMain.find("tbody").html(r.join("")),a.layFixLeft.find("tbody").html(c.join("")),a.layFixRight.find("tbody").html(s.join("")),a.syncCheckAll(),a.renderForm(),a.fullSize(),a.haveInit?a.scrollPatch():setTimeout(function(){a.scrollPatch()},50),a.haveInit=!0,f.close(a.tipsIndex)};return x.cache[a.key]=d,a.layTotal[0==d.length?"addClass":"removeClass"](h),a.layPage[i.page||i.pagebar?"removeClass":"addClass"](N),a.layPage.find(_)[!i.page||0==n||0===d.length&&1==l?"addClass":"removeClass"](h),0===d.length?a.errorView(i.text.none):(a.layFixLeft.removeClass(N),o?u():(u(),a.renderTotal(d,t),a.layTotal&&a.layTotal.removeClass(N),void(i.page&&(i.page=p.extend({elem:"layui-table-page"+i.index,count:n,limit:i.limit,limits:i.limits||[10,20,30,40,50,60,70,80,90],groups:3,layout:["prev","page","next","skip","count","limit"],prev:'',next:'',jump:function(e,t){t||(a.page=e.curr,i.limit=e.limit,a.pullData(e.curr))}},i.page),i.page.count=n,z.render(i.page)))))},x.renderData=function(e){e=C(e);e&&e.pullData(e.page,{renderData:!0,type:"reloadData"})},i.prototype.renderTotal=function(e,o){var d,r=this,c=r.config,s={};c.totalRow&&(layui.each(e,function(e,i){"array"===layui.type(i)&&0===i.length||r.eachCols(function(e,t){var e=t.field||e,a=i[e];t.totalRow&&(s[e]=(s[e]||0)+(parseFloat(a)||0))})}),r.dataTotal=[],d=[],r.eachCols(function(e,t){var a,e=t.field||e,i=o&&o[t.field],l="totalRowDecimals"in t?t.totalRowDecimals:2,l=s[e]?parseFloat(s[e]||0).toFixed(l):"",l=(a=t.totalRowText||"",(n={LAY_COL:t})[e]=l,n=t.totalRow&&w.call(r,{item3:t,content:l,tplData:n})||a,i||n),n=(t.field&&r.dataTotal.push({field:t.field,total:p("
                                                                "+l+"
                                                                ").text()}),['','
                                                                "+("string"==typeof(a=t.totalRow||c.totalRow)?m(a).render(p.extend({TOTAL_NUMS:i||s[e],TOTAL_ROW:o||{},LAY_COL:t},t)):l),"
                                                                "].join(""));d.push(n)}),e=r.layTotal.find(".layui-table-patch"),r.layTotal.find("tbody").html(""+d.join("")+(e.length?e.get(0).outerHTML:"")+""))},i.prototype.getColElem=function(e,t){this.config;return e.eq(0).find(".laytable-cell-"+t+":eq(0)")},i.prototype.renderForm=function(e){this.config;var t=this.elem.attr("lay-filter");v.render(e,t)},i.prototype.syncCheckAll=function(){var a,e=this,i=e.config,t=e.layHeader.find('input[name="layTableCheckbox"]'),l=x.checkStatus(e.key);t[0]&&(a=l.isAll,e.eachCols(function(e,t){"checkbox"===t.type&&(t[i.checkName]=a)}),t.prop({checked:l.isAll,indeterminate:!l.isAll&&l.data.length}),v.render(t))},i.prototype.setRowActive=function(e,t){this.config;this.layBody.find('tr[data-index="'+e+'"]').addClass(t=t||"layui-table-click").siblings("tr").removeClass(t)},i.prototype.setRowChecked=function(a){var e=this,i=e.config,l=e.layBody.find("tr"+("all"===a.index?"":'[data-index="'+a.index+'"]')),t=(a=p.extend({type:"checkbox"},a),x.cache[e.key]),n="checked"in a,o=function(e){return"radio"===a.type||(n?a.checked:!e)},t=(layui.each(t,function(e,t){"array"!==layui.type(t)&&(Number(a.index)===e||"all"===a.index?(e=t[i.checkName]=o(t[i.checkName]),l[e?"addClass":"removeClass"](E),"radio"===a.type&&l.siblings().removeClass(E)):"radio"===a.type&&delete t[i.checkName])}),l.find('input[lay-type="'+({radio:"layTableRadio",checkbox:"layTableCheckbox"}[a.type]||"checkbox")+'"]'));t.prop("checked",o(t.last().prop("checked"))),e.syncCheckAll(),e.renderForm(a.type)},i.prototype.sort=function(l){var e,t=this,a={},i=t.config,n=i.elem.attr("lay-filter"),o=x.cache[t.key];"string"==typeof(l=l||{}).field&&(d=l.field,t.layHeader.find("th").each(function(e,t){var a=p(this),i=a.data("field");if(i===l.field)return l.field=a,d=i,!1}));try{var d=d||l.field.data("field"),r=l.field.data("key");if(t.sortKey&&!l.pull&&d===t.sortKey.field&&l.type===t.sortKey.sort)return;var c=t.layHeader.find("th .laytable-cell-"+r).find(A);t.layHeader.find("th").find(A).removeAttr("lay-sort"),c.attr("lay-sort",l.type||null),t.layFixed.find("th")}catch(s){y.error("Table modules: sort field '"+d+"' not matched")}t.sortKey={field:d,sort:l.type},i.autoSort&&("asc"===l.type?e=layui.sort(o,d,null,!0):"desc"===l.type?e=layui.sort(o,d,!0,!0):(e=layui.sort(o,x.config.indexName,null,!0),delete t.sortKey,delete i.initSort)),a[i.response.dataName]=e||o,t.renderData({res:a,curr:t.page,count:t.count,sort:!0,type:l.reloadType}),l.fromEvent&&(i.initSort={field:d,type:l.type},layui.event.call(l.field,T,"sort("+n+")",p.extend({config:i},i.initSort)))},i.prototype.loading=function(e){var t=this;t.config.loading&&(e?(t.layInit&&t.layInit.remove(),delete t.layInit,t.layBox.find(".layui-table-init").remove()):(t.layInit=p(['
                                                                ','',"
                                                                "].join("")),t.layBox.append(t.layInit)))},i.prototype.getCssRule=function(a,i){var e=this.elem.find("style")[0],e=e.sheet||e.styleSheet||{},e=e.cssRules||e.rules;layui.each(e,function(e,t){if(t.selectorText===".laytable-cell-"+a)return i(t),!0})},i.prototype.fullSize=function(){var e,a,i=this,t=i.config,l=t.height;i.fullHeightGap?(l=O.height()-i.fullHeightGap)<135&&(l=135):i.parentDiv&&i.parentHeightGap&&(l=p(i.parentDiv).height()-i.parentHeightGap)<135&&(l=135),1
                                                                ')).find("div").css({width:a}),e.find("tr").append(t)):e.find(".layui-table-patch").remove()};n(e.layHeader),n(e.layTotal);n=e.layMain.height()-i;e.layFixed.find(D).css("height",t.height()>=n?n:"auto").scrollTop(e.layMain.scrollTop()),e.layFixRight[x.cache[e.key]&&x.cache[e.key].length&&0');a.html(t),u.height&&a.css("max-height",u.height-(s.layTool.outerHeight()||50)),i.find("."+S)[0]||i.append(a),s.renderForm(),a.on("click",function(e){layui.stope(e)}),e.done&&e.done(a,t)};switch(layui.stope(e),P.trigger("table.tool.panel.remove"),f.close(s.tipsIndex),t){case"LAYTABLE_COLS":l({list:(a=[],s.eachCols(function(e,t){t.field&&"normal"==t.type&&a.push('
                                                              • "+(t.fieldTitle||t.title||t.field)+"
                                                              • ").text())+'" lay-filter="LAY_TABLE_TOOL_COLS">')}),a.join("")),done:function(){v.on("checkbox(LAY_TABLE_TOOL_COLS)",function(e){var e=p(e.elem),t=this.checked,a=e.data("key"),i=s.col(a),l=i.hide,e=e.data("parentkey");i.key&&(i.hide=!t,s.elem.find('*[data-key="'+a+'"]')[t?"removeClass":"addClass"](N),l!=i.hide&&s.setParentCol(!t,e),s.resize(),layui.event.call(this,T,"colToggled("+r+")",{col:i,config:u}))})}});break;case"LAYTABLE_EXPORT":b.ie?f.tips("\u5bfc\u51fa\u529f\u80fd\u4e0d\u652f\u6301 IE\uff0c\u8bf7\u7528 Chrome \u7b49\u9ad8\u7ea7\u6d4f\u89c8\u5668\u5bfc\u51fa",this,{tips:3}):l({list:['
                                                              • \u5bfc\u51fa csv \u683c\u5f0f\u6587\u4ef6
                                                              • ','
                                                              • \u5bfc\u51fa xls \u683c\u5f0f\u6587\u4ef6
                                                              • '].join(""),done:function(e,t){t.on("click",function(){var e=p(this).data("type");x.exportFile.call(s,u.id,null,e)})}});break;case"LAYTABLE_PRINT":var n=window.open("about:blank","_blank"),o=[""].join(""),d=p(s.layHeader.html());d.append(s.layMain.find("table").html()),d.append(s.layTotal.find("table").html()),d.find("th.layui-table-patch").remove(),d.find("thead>tr>th."+M).filter(function(e,t){return!p(t).children("."+H).length}).remove(),d.find("tbody>tr>td."+M).remove(),n.document.write(o+d.prop("outerHTML")),n.document.close(),layui.device("edg").edg?(n.onafterprint=n.close,n.print()):(n.print(),n.close())}layui.event.call(this,T,"toolbar("+r+")",p.extend({event:t,config:u},{}))}),s.layHeader.on("click","*[lay-event]",function(e){var t=p(this),a=t.attr("lay-event"),t=t.closest("th").data("key"),t=s.col(t);layui.event.call(this,T,"colTool("+r+")",p.extend({event:a,config:u,col:t},{}))}),s.layPagebar.on("click","*[lay-event]",function(e){var t=p(this).attr("lay-event");layui.event.call(this,T,"pagebar("+r+")",p.extend({event:t,config:u},{}))}),e.on("mousemove",function(e){var t=p(this),a=t.offset().left,e=e.clientX-a;t.data("unresize")||k.eventMoveElem||(d.allowResize=t.width()-e<=10,o.css("cursor",d.allowResize?"col-resize":""))}).on("mouseleave",function(){p(this);k.eventMoveElem||o.css("cursor","")}).on("mousedown",function(e){var t,a=p(this);d.allowResize&&(t=a.data("key"),e.preventDefault(),d.offset=[e.clientX,e.clientY],s.getCssRule(t,function(e){var t=e.style.width||a.outerWidth();d.rule=e,d.ruleWidth=parseFloat(t),d.minWidth=a.data("minwidth")||u.cellMinWidth,d.maxWidth=a.data("maxwidth")||u.cellMaxWidth}),a.data(I,d),k.eventMoveElem=a)}),k.docEvent||P.on("mousemove",function(e){var t,a;k.eventMoveElem&&(t=k.eventMoveElem.data(I)||{},k.eventMoveElem.data("resizing",1),e.preventDefault(),t.rule&&(e=t.ruleWidth+e.clientX-t.offset[0],a=k.eventMoveElem.closest("."+R).attr("lay-id"),(a=C(a))&&((e=et.maxWidth&&(e=t.maxWidth),t.rule.style.width=e+"px",a.setGroupWidth(k.eventMoveElem),f.close(s.tipsIndex))))}).on("mouseup",function(e){var t,a,i,l,n;k.eventMoveElem&&(i=(t=k.eventMoveElem).closest("."+R).attr("lay-id"),(a=C(i))&&(i=t.data("key"),l=a.col(i),n=a.config.elem.attr("lay-filter"),d={},o.css("cursor",""),a.scrollPatch(),t.removeData(I),delete k.eventMoveElem,a.getCssRule(i,function(e){l.width=parseFloat(e.style.width),layui.event.call(t[0],T,"colResized("+n+")",{col:l,config:a.config})})))}),k.docEvent=!0,e.on("click",function(e){var t=p(this),a=t.find(A),i=a.attr("lay-sort");if(!a[0]||1===t.data("resizing"))return t.removeData("resizing");s.sort({field:t,type:"asc"===i?"desc":"desc"===i?null:"asc",fromEvent:!0})}).find(A+" .layui-edge ").on("click",function(e){var t=p(this),a=t.index(),t=t.parents("th").eq(0).data("field");layui.stope(e),0===a?s.sort({field:t,type:"asc",fromEvent:!0}):s.sort({field:t,type:"desc",fromEvent:!0})}),s.commonMember=function(e){var t=p(this).parents("tr").eq(0).data("index"),r=s.layBody.find('tr[data-index="'+t+'"]'),c=(c=x.cache[s.key]||[])[t]||{},a={tr:r,config:u,data:x.clearCacheKey(c),dataCache:c,index:t,del:function(){x.cache[s.key][t]=[],r.remove(),s.scrollPatch()},update:function(e,d){e=e||{},layui.each(e,function(i,l){var n=r.children('td[data-field="'+i+'"]'),o=n.children(y);c[i]=a.data[i]=l,s.eachCols(function(e,t){var a;t.field==i?(o.html(w.call(s,{item3:t,content:l,tplData:p.extend({LAY_COL:t},c)})),n.data("content",l)):d&&(t.templet||t.toolbar)&&(e=r.children('td[data-field="'+(t.field||e)+'"]'),a=c[t.field],e.children(y).html(w.call(s,{item3:t,content:a,tplData:p.extend({LAY_COL:t},c)})),e.data("content",a))})}),s.renderForm()},setRowChecked:function(e){s.setRowChecked(p.extend({index:t},e))}};return p.extend(a,e)}),a=(s.elem.on("click",'input[name="layTableCheckbox"]+',function(e){var t=p(this),a=t.closest("td"),t=t.prev(),i=(s.layBody.find('input[name="layTableCheckbox"]'),t.parents("tr").eq(0).data("index")),l=t[0].checked,n="layTableAllChoose"===t.attr("lay-filter");t[0].disabled||(n?s.setRowChecked({index:"all",checked:l}):(s.setRowChecked({index:i,checked:l}),layui.stope(e)),layui.event.call(t[0],T,"checkbox("+r+")",c.call(t[0],{checked:l,type:n?"all":"one",getCol:function(){return s.col(a.data("key"))}})))}),s.elem.on("click",'input[lay-type="layTableRadio"]+',function(e){var t=p(this),a=t.closest("td"),t=t.prev(),i=t[0].checked,l=t.parents("tr").eq(0).data("index");if(layui.stope(e),t[0].disabled)return!1;s.setRowChecked({type:"radio",index:l}),layui.event.call(t[0],T,"radio("+r+")",c.call(t[0],{checked:i,getCol:function(){return s.col(a.data("key"))}}))}),s.layBody.on("mouseenter","tr",function(){var e=p(this),t=e.index();e.data("off")||s.layBody.find("tr:eq("+t+")").addClass(j)}).on("mouseleave","tr",function(){var e=p(this),t=e.index();e.data("off")||s.layBody.find("tr:eq("+t+")").removeClass(j)}).on("click","tr",function(e){var t=".layui-form-checkbox,.layui-form-switch,.layui-form-radio,[lay-unrow]";p(e.target).is(t)||p(e.target).closest(t)[0]||a.call(this,"row")}).on("dblclick","tr",function(){a.call(this,"rowDouble")}).on("contextmenu","tr",function(e){u.defaultContextmenu||e.preventDefault(),a.call(this,"rowContextmenu")}),function(e){var t=p(this);t.data("off")||layui.event.call(this,T,e+"("+r+")",c.call(t.children("td")[0]))}),n=function(e,t){var a,i,l,n;(e=p(e)).data("off")||(a=e.data("field"),n=e.data("key"),n=s.col(n),i=e.closest("tr").data("index"),i=x.cache[s.key][i],l=e.children(y),(n="function"==typeof n.edit?n.edit(i):n.edit)&&((n=p("textarea"===n?'':''))[0].value=e.data("content")||i[a]||l.text(),e.find("."+W)[0]||e.append(n),n.focus(),t&&layui.stope(t)))},i=(s.layBody.on("change","."+W,function(){var e=p(this),t=e.parent(),a=this.value,i=e.parent().data("field"),e=e.closest("tr").data("index"),e=x.cache[s.key][e],l=c.call(t[0],{value:a,field:i,oldValue:e[i],td:t,reedit:function(){setTimeout(function(){n(l.td);var e={};e[i]=l.oldValue,l.update(e)})},getCol:function(){return s.col(t.data("key"))}}),e={};e[i]=a,l.update(e),layui.event.call(t[0],T,"edit("+r+")",l)}).on("blur","."+W,function(){p(this).remove()}),s.layBody.on(u.editTrigger,"td",function(e){n(this,e)}).on("mouseenter","td",function(){t.call(this)}).on("mouseleave","td",function(){t.call(this,"hide")}),s.layTotal.on("mouseenter","td",function(){t.call(this)}).on("mouseleave","td",function(){t.call(this,"hide")}),"layui-table-grid-down"),t=function(e){var t=p(this),a=t.children(y);t.data("off")||(e?t.find(".layui-table-grid-down").remove():!(a.prop("scrollWidth")>a.outerWidth()||0'))},l=function(e){var t=p(this).parent().children(y);s.tipsIndex=f.tips(['
                                                                ',t.html(),"
                                                                ",''].join(""),t[0],{tips:[3,""],time:-1,anim:-1,maxWidth:b.ios||b.android?300:s.elem.width()/2,isOutAnim:!1,skin:"layui-table-tips",success:function(e,t){e.find(".layui-table-tips-c").on("click",function(){f.close(t)})}}),layui.stope(e)},h=(s.layBody.on("click","."+i,function(e){l.call(this,e)}),s.layTotal.on("click","."+i,function(e){l.call(this,e)}),function(e){var t=p(this),a=t.closest("td"),i=t.parents("tr").eq(0).data("index");s.setRowActive(i),layui.event.call(this,T,(e||"tool")+"("+r+")",c.call(this,{event:t.attr("lay-event"),getCol:function(){return s.col(a.data("key"))}}))});s.layBody.on("click","*[lay-event]",function(e){h.call(this),layui.stope(e)}).on("dblclick","*[lay-event]",function(e){h.call(this,"toolDouble"),layui.stope(e)}),s.layMain.on("scroll",function(){var e=p(this),t=e.scrollLeft(),e=e.scrollTop();s.layHeader.scrollLeft(t),s.layTotal.scrollLeft(t),s.layFixed.find(D).scrollTop(e),f.close(s.tipsIndex)}),O.on("resize",function(){s.resize()})},P.on("click",function(){P.trigger("table.remove.tool.panel")}),P.on("table.remove.tool.panel",function(){p("."+S).remove()}),x.init=function(i,o){o=o||{};var e="object"==typeof i?i:p("string"==typeof i?'table[lay-filter="'+i+'"]':t+"[lay-data], "+t+"[lay-options]"),d="Table element property lay-data configuration item has a syntax error: ";return e.each(function(){var l,e=p(this),t=e.attr("lay-data"),t=r.options(this,{attr:t?"lay-data":null,errorText:d+(t||e.attr("lay-options"))}),n=p.extend({elem:this,cols:[],data:[],skin:e.attr("lay-skin"),size:e.attr("lay-size"),even:"string"==typeof e.attr("lay-even")},x.config,o,t),a=(i&&e.hide(),e.find("thead>tr").each(function(i){n.cols[i]=[],p(this).children().each(function(e){var t=p(this),a=t.attr("lay-data"),a=r.options(this,{attr:a?"lay-data":null,errorText:d+(a||t.attr("lay-options"))}),t=p.extend({title:t.text(),colspan:parseInt(t.attr("colspan"))||1,rowspan:parseInt(t.attr("rowspan"))||1},a);n.cols[i].push(t)})}),e.find("tbody>tr")),t=x.render(n);!a.length||o.data||t.config.url||(l=0,x.eachCols(t.config.id,function(e,i){a.each(function(e){n.data[e]=n.data[e]||{};var t=p(this),a=i.field;n.data[e][a]=t.children("td").eq(l).html()}),l++}),t.reloadData({data:n.data}))}),this},k.that={},k.config={},function(a,i,e,l){var n,o;l.colGroup&&(n=0,a++,l.CHILD_COLS=[],o=e+(parseInt(l.rowspan)||1),layui.each(i[o],function(e,t){t.parentKey?t.parentKey===l.key&&(t.PARENT_COL_INDEX=a,l.CHILD_COLS.push(t),d(a,i,o,t)):t.PARENT_COL_INDEX||1<=n&&n==(l.colspan||1)||(t.PARENT_COL_INDEX=a,l.CHILD_COLS.push(t),n+=parseInt(1td').filter('[data-field="'+e+'"]')}}})).replace(/"/g,'""'),n.push(a='"'+a+'"')))}),d.push(n.join(","))}),c&&layui.each(c.dataTotal,function(e,t){r[t.field]||i.push('"'+(t.total||"")+'"')}),o.join(",")+"\r\n"+d.join("\r\n")+"\r\n"+i.join(","))),u.download=(a.title||n.title||"table_"+(n.index||""))+"."+l,document.body.appendChild(u),u.click(),document.body.removeChild(u)},x.getOptions=l,x.hideCol=function(e,l){var n=C(e);n&&("boolean"===layui.type(l)?n.eachCols(function(e,t){var a=t.key,i=n.col(a),t=t.parentKey;i.hide!=l&&(i=i.hide=l,n.elem.find('*[data-key="'+a+'"]')[i?"addClass":"removeClass"](N),n.setParentCol(i,t))}):(l=layui.isArray(l)?l:[l],layui.each(l,function(e,l){n.eachCols(function(e,t){var a,i;l.field===t.field&&(a=t.key,i=n.col(a),t=t.parentKey,"hide"in l&&i.hide!=l.hide&&(i=i.hide=!!l.hide,n.elem.find('*[data-key="'+a+'"]')[i?"addClass":"removeClass"](N),n.setParentCol(i,t)))})})),p("."+S).remove(),n.resize())},x.reload=function(e,t,a,i){if(l(e))return e=C(e),e.reload(t,a,i),k.call(e)},x.reloadData=function(){var a=p.extend([],arguments),i=(a[3]="reloadData",new RegExp("^("+["elem","id","cols","width","height","maxHeight","toolbar","defaultToolbar","className","css","totalRow","pagebar"].join("|")+")$"));return layui.each(a[1],function(e,t){i.test(e)&&delete a[1][e]}),x.reload.apply(null,a)},x.render=function(e){e=new i(e);return k.call(e)},x.clearCacheKey=function(e){return delete(e=p.extend({},e))[x.config.checkName],delete e[x.config.indexName],delete e[x.config.numbersName],delete e[x.config.disabledName],e},p(function(){x.init()}),n(T,x)});layui.define(["table"],function(e){"use strict";var B=layui.$,x=layui.form,j=layui.table,y=layui.hint(),P={config:{},on:j.on,eachCols:j.eachCols,index:j.index,set:function(e){var t=this;return t.config=B.extend({},t.config,e),t},resize:j.resize,getOptions:j.getOptions,hideCol:j.hideCol,renderData:j.renderData},i=function(){var a=this,e=a.config,n=e.id||e.index;return{config:e,reload:function(e,t){a.reload.call(a,e,t)},reloadData:function(e,t){P.reloadData(n,e,t)}}},F=function(e){var t=i.that[e];return t||y.error(e?"The treeTable instance with ID '"+e+"' not found":"ID argument required"),t||null},q="layui-hide",L=".layui-table-main",R=".layui-table-fixed-l",Y=".layui-table-fixed-r",l="layui-table-checked",h="layui-table-tree",H="LAY_DATA_INDEX",m="LAY_DATA_INDEX_HISTORY",s="LAY_PARENT_INDEX",b="LAY_CHECKBOX_HALF",X="LAY_EXPAND",z="LAY_HAS_EXPANDED",V="LAY_ASYNC_STATUS",t=function(e){var t=this;t.index=++P.index,t.config=B.extend(!0,{},t.config,P.config,e),t.init(),t.render()},u=function(n,i,e){var l=j.cache[n];layui.each(e||l,function(e,t){var a=t[H];-1!==a.indexOf("-")&&(l[a]=t),t[i]&&u(n,i,t[i])})},r=function(i,a,e){var l=F(i),t=("reloadData"!==e&&(l.status={expand:{}}),B.extend(!0,{},l.getOptions(),a)),n=t.tree,r=n.customName.children,d=n.customName.id,o=(delete a.hasNumberCol,delete a.hasChecboxCol,delete a.hasRadioCol,j.eachCols(null,function(e,t){"numbers"===t.type?a.hasNumberCol=!0:"checkbox"===t.type?a.hasChecboxCol=!0:"radio"===t.type&&(a.hasRadioCol=!0)},t.cols),a.parseData),c=a.done;t.url?e&&(!o||o.mod)||(a.parseData=function(){var e=this,t=arguments,a=t[0],t=("function"===layui.type(o)&&(a=o.apply(e,t)||t[0]),e.response.dataName);return n.data.isSimpleData&&!n["async"].enable&&(a[t]=l.flatToTree(a[t])),f(a[t],function(e){e[X]=X in e?e[X]:e[d]!==undefined&&l.status.expand[e[d]]},r),e.autoSort&&e.initSort&&e.initSort.type&&layui.sort(a[t],e.initSort.field,"desc"===e.initSort.type,!0),l.initData(a[t]),a},a.parseData.mod=!0):(a.data=a.data||[],n.data.isSimpleData&&(a.data=l.flatToTree(a.data)),l.initData(a.data)),e&&(!c||c.mod)||(a.done=function(){var e,t=arguments,a=(t[3]||delete l.isExpandAll,this.elem.next()),n=(l.updateStatus(null,{LAY_HAS_EXPANDED:!1}),u(i,r),a.find('[name="layTableCheckbox"][lay-filter="layTableAllChoose"]'));if(n.length&&(e=P.checkStatus(i),n.prop({checked:e.isAll&&e.data.length,indeterminate:!e.isAll&&e.data.length})),l.renderTreeTable(a),"function"===layui.type(c))return c.apply(this,t)},a.done.mod=!0)};t.prototype.init=function(){var e=this.config,t=e.tree.data.cascade,t=("parent"!==t&&"children"!==t&&(e.tree.data.cascade="all"),j.render(B.extend({},e,{data:[],url:"",done:null}))),a=t.config.id;(i.that[a]=this).tableIns=t,r(a,e)},t.prototype.config={tree:{customName:{children:"children",isParent:"isParent",name:"name",id:"id",pid:"parentId",icon:"icon"},view:{indent:14,flexIconClose:'',flexIconOpen:'',showIcon:!0,icon:"",iconClose:'',iconOpen:'',iconLeaf:'',showFlexIconIfNotParent:!1,dblClickExpand:!0,expandAllDefault:!1},data:{isSimpleData:!1,rootPid:null,cascade:"all"},"async":{enable:!1,url:"",type:null,contentType:null,headers:null,where:null,autoParam:[]},callback:{beforeExpand:null,onExpand:null}}},t.prototype.getOptions=function(){return this.tableIns?j.getOptions(this.tableIns.config.id):this.config},t.prototype.flatToTree=function(e){var a,n,i,t,l,r,d,o=this.getOptions(),c=o.tree,u=c.customName,o=o.id;return e=e||j.cache[o],o=e,a=u.id,n=u.pid,i=u.children,t=c.data.rootPid,a=a||"id",n=n||"parentId",i=i||"children",d={},layui.each(o,function(e,t){l=a+t[a],d[l]=B.extend({},t),d[l][i]=[]}),layui.each(d,function(e,t){(r=a+t[n])&&d[r]&&d[r][i].push(t)}),Object.values(d).filter(function(e){return t?e[n]===t:!e[n]})},t.prototype.treeToFlat=function(e,n,i){var l=this,r=l.getOptions().tree.customName,d=r.children,o=r.pid,c=[];return layui.each(e,function(e,t){var e=(i?i+"-":"")+e,a=B.extend({},t);a[o]=t[o]||n,c.push(a),c=c.concat(l.treeToFlat(t[d],t[r.id],e))}),c},t.prototype.getTreeNode=function(e){var t=this;if(!e)return y.error("\u627e\u4e0d\u5230\u8282\u70b9\u6570\u636e");var a=t.getOptions(),n=a.tree;a.id,n.customName;return{data:e,dataIndex:e[H],getParentNode:function(){return t.getNodeByIndex(e[s])}}},t.prototype.getNodeByIndex=function(t){var e=this,a=e.getNodeDataByIndex(t);if(!a)return y.error("\u627e\u4e0d\u5230\u8282\u70b9\u6570\u636e");var n=e.getOptions(),i=(n.tree.customName.parent,n.id),n={data:a,dataIndex:a[H],getParentNode:function(){return e.getNodeByIndex(a[s])},update:function(e){return P.updateNode(i,t,e)},remove:function(){return P.removeNode(i,t)},expand:function(e){return P.expandNode(i,B.extend({},e,{index:t}))},setChecked:function(e){return P.setRowChecked(i,B.extend({},e,{index:t}))}};return n.dataIndex=t,n},t.prototype.getNodeById=function(a){var e=this.getOptions(),n=e.tree.customName.id,i="",e=P.getData(e.id,!0);if(layui.each(e,function(e,t){if(t[n]===a)return i=t[H],!0}),i)return this.getNodeByIndex(i)},t.prototype.getNodeDataByIndex=function(a,e,t){var n=this.getOptions(),i=n.tree,l=n.id,r=j.cache[l][a];if("delete"!==t&&r)return B.extend(r,t),e?B.extend({},r):r;for(var r=this.getTableData(),d=(a+="").split("-"),o=r,c=n.url||1');var D=function(e){y[V]="success",y[s.children]=e,c.initData(y[s.children],y[H]),J(t,!0,!p&&n,i,l)},T=b.format;if("function"===layui.type(T))return T(y,o,D),h;var k=B.extend({},b.where||o.where),T=b.autoParam,T=(layui.each(T,function(e,t){t=t.split("=");k[t[0].trim()]=y[(t[1]||t[0]).trim()]}),b.contentType||o.contentType),_=(T&&0==T.indexOf("application/json")&&(k=JSON.stringify(k)),b.method||o.method),w=b.dataType||o.dataType,O=b.jsonpCallback||o.jsonpCallback,S=b.headers||o.headers,A=b.parseData||o.parseData,E=b.response||o.response;return B.ajax({type:_||"get",url:I,contentType:T,data:k,dataType:w||"json",jsonpCallback:O,headers:S||{},success:function(e){(e="function"==typeof A?A.call(o,e)||e:e)[E.statusName]!=E.statusCode?(y[V]="error",g.html('')):D(e[E.dataName])},error:function(e,t){y[V]="error","function"==typeof o.error&&o.error(e,t)}}),h}m=y[z]=!0,v.length&&(!o.initSort||o.url&&!o.autoSort||((b=o.initSort).type?layui.sort(v,b.field,"desc"===b.type,!0):layui.sort(v,j.config.indexName,null,!0)),c.initData(y[s.children],y[H]),_=j.getTrHtml(d,v,null,null,e),N={trs:B(_.trs.join("")),trs_fixed:B(_.trs_fixed.join("")),trs_fixed_r:B(_.trs_fixed_r.join(""))},C=(e.split("-").length-1||0)+1,layui.each(v,function(e,t){N.trs.eq(e).attr({"data-index":t[H],"lay-data-index":t[H],"data-level":C}),N.trs_fixed.eq(e).attr({"data-index":t[H],"lay-data-index":t[H],"data-level":C}),N.trs_fixed_r.eq(e).attr({"data-index":t[H],"lay-data-index":t[H],"data-level":C})}),r.find(L).find('tbody tr[lay-data-index="'+e+'"]').after(N.trs),r.find(R).find('tbody tr[lay-data-index="'+e+'"]').after(N.trs_fixed),r.find(Y).find('tbody tr[lay-data-index="'+e+'"]').after(N.trs_fixed_r),c.renderTreeTable(N.trs,C),n&&!p&&layui.each(v,function(e,t){J({dataIndex:t[H],trElem:r.find('tr[lay-data-index="'+t[H]+'"]').first(),tableViewElem:r,tableId:d,options:o},a,n,i,l)}))}else c.isExpandAll=!1,n&&!p?(layui.each(v,function(e,t){J({dataIndex:t[H],trElem:r.find('tr[lay-data-index="'+t[H]+'"]').first(),tableViewElem:r,tableId:d,options:o},a,n,i,l)}),r.find(v.map(function(e,t,a){return'tr[lay-data-index="'+e[H]+'"]'}).join(",")).addClass(q)):(I=c.treeToFlat(v,y[s.id],e),r.find(I.map(function(e,t,a){return'tr[lay-data-index="'+e[H]+'"]'}).join(",")).addClass(q));return U("resize-"+d,function(){P.resize(d)},0)(),l&&"loading"!==y[V]&&(T=u.callback.onExpand,"function"===layui.type(T)&&T(d,y,x)),h},g=(P.expandNode=function(e,t){var a,n,i,e=F(e);if(e)return a=(t=t||{}).index,n=t.expandFlag,i=t.inherit,t=t.callbackFlag,e=e.getOptions().elem.next(),J({trElem:e.find('tr[lay-data-index="'+a+'"]').first()},n,i,null,t)},P.expandAll=function(a,e){if("boolean"!==layui.type(e))return y.error("expandAll \u7684\u5c55\u5f00\u72b6\u6001\u53c2\u6570\u53ea\u63a5\u6536true/false");var t=F(a);if(t){t.isExpandAll=e;var n=t.getOptions(),i=n.tree,l=n.elem.next(),r=i.customName.isParent,d=i.customName.id,o=i.view.showFlexIconIfNotParent;if(e){e=P.getData(a,!0);if(i["async"].enable){var c=!0;if(layui.each(e,function(e,t){if(t[r]&&!t[V])return!(c=!1)}),!c)return void layui.each(P.getData(a),function(e,t){P.expandNode(a,{index:t[H],expandFlag:!0,inherit:!0})})}var u=!0;if(layui.each(e,function(e,t){if(t[r]&&!t[z])return!(u=!1)}),u)t.updateStatus(null,function(e){(e[r]||o)&&(e[X]=!0,e[d]!==undefined&&(t.status.expand[e[d]]=!0))}),l.find('tbody tr[data-level!="0"]').removeClass(q),l.find(".layui-table-tree-flexIcon").html(i.view.flexIconOpen),i.view.showIcon&&l.find(".layui-table-tree-nodeIcon:not(.layui-table-tree-iconCustom,.layui-table-tree-iconLeaf)").html(i.view.iconOpen);else{if(t.updateStatus(null,function(e){(e[r]||o)&&(e[X]=!0,e[z]=!0,e[d]!==undefined&&(t.status.expand[e[d]]=!0))}),n.initSort&&n.initSort.type&&(!n.url||n.autoSort))return P.sort(a);var s,n=j.getTrHtml(a,e),f={trs:B(n.trs.join("")),trs_fixed:B(n.trs_fixed.join("")),trs_fixed_r:B(n.trs_fixed_r.join(""))};layui.each(e,function(e,t){var a=t[H].split("-").length-1;s={"data-index":t[H],"lay-data-index":t[H],"data-level":a},f.trs.eq(e).attr(s),f.trs_fixed.eq(e).attr(s),f.trs_fixed_r.eq(e).attr(s)}),layui.each(["main","fixed-l","fixed-r"],function(e,t){l.find(".layui-table-"+t+" tbody").html(f[["trs","trs_fixed","trs_fixed_r"][e]])}),t.renderTreeTable(l,0,!1)}}else t.updateStatus(null,function(e){(e[r]||o)&&(e[X]=!1,e[d]!==undefined&&(t.status.expand[e[d]]=!1))}),l.find('.layui-table-box tbody tr[data-level!="0"]').addClass(q),l.find(".layui-table-tree-flexIcon").html(i.view.flexIconClose),i.view.showIcon&&l.find(".layui-table-tree-nodeIcon:not(.layui-table-tree-iconCustom,.layui-table-tree-iconLeaf)").html(i.view.iconClose);P.resize(a)}},t.prototype.renderTreeTable=function(e,t,a){var n=this,i=n.getOptions(),l=i.elem.next(),r=(l.hasClass(h)||l.addClass(h),i.id),d=i.tree||{},o=(d.data,d.view||{}),c=d.customName||{},u=c.isParent,s=(l.attr("lay-filter"),n),f=((t=t||0)||(l.find(".layui-table-body tr:not([data-level])").attr("data-level",t),layui.each(j.cache[r],function(e,t){l.find('.layui-table-main tbody tr[data-level="0"]:eq('+e+")").attr("lay-data-index",t[H]),l.find('.layui-table-fixed-l tbody tr[data-level="0"]:eq('+e+")").attr("lay-data-index",t[H]),l.find('.layui-table-fixed-r tbody tr[data-level="0"]:eq('+e+")").attr("lay-data-index",t[H])})),null),y=c.name,p=o.indent||14;if(layui.each(e.find('td[data-field="'+y+'"]'),function(e,t){var a,n,i=(t=B(t)).closest("tr"),t=t.children(".layui-table-cell");t.hasClass("layui-table-tree-item")||(n=i.attr("lay-data-index"))&&(i=l.find('tr[lay-data-index="'+n+'"]'),(a=s.getNodeDataByIndex(n))[X]&&a[u]&&((f=f||{})[n]=!0),a[b]&&i.find('input[type="checkbox"][name="layTableCheckbox"]').prop("indeterminate",!0),n=t.html(),(t=i.find('td[data-field="'+y+'"]>div.layui-table-cell')).addClass("layui-table-tree-item"),t.html(['
                                                                ',a[X]?o.flexIconOpen:o.flexIconClose,"
                                                                ",o.showIcon?'
                                                                '+(a[c.icon]||o.icon||(a[u]?a[X]?o.iconOpen:o.iconClose:o.iconLeaf)||"")+"
                                                                ":"",n].join("")).find(".layui-table-tree-flexIcon").on("click",function(e){layui.stope(e),J({trElem:i},null,null,null,!0)}))}),!t&&d.view.expandAllDefault&&n.isExpandAll===undefined)return P.expandAll(r,!0);!1!==a&&f?layui.each(f,function(e,t){e=l.find('tr[lay-data-index="'+e+'"]');e.find(".layui-table-tree-flexIcon").html(o.flexIconOpen),J({trElem:e.first()},!0)}):U("renderTreeTable-"+r,function(){i.hasNumberCol&&g(n),x.render(B('.layui-table-tree[lay-id="'+r+'"]'))},0)()},function(a){var e=a.getOptions(),t=e.elem.next(),n=0,i=t.find(".layui-table-main tbody tr"),l=t.find(".layui-table-fixed-l tbody tr"),r=t.find(".layui-table-fixed-r tbody tr");layui.each(a.treeToFlat(j.cache[e.id]),function(e,t){a.getNodeDataByIndex(t[H]).LAY_NUM=++n,i.eq(e).find(".laytable-cell-numbers").html(n),l.eq(e).find(".laytable-cell-numbers").html(n),r.eq(e).find(".laytable-cell-numbers").html(n)})}),f=(t.prototype.render=function(e){var t=this;t.tableIns=j["reloadData"===e?"reloadData":"reload"](t.tableIns.config.id,B.extend(!0,{},t.config)),t.config=t.tableIns.config},t.prototype.reload=function(e,t,a){var n=this;e=e||{},delete n.haveInit,layui.each(e,function(e,t){"array"===layui.type(t)&&delete n.config[e]}),r(n.getOptions().id,e,a||!0),n.config=B.extend(t,{},n.config,e),n.render(a)},P.reloadData=function(){var e=B.extend(!0,[],arguments);return e[3]="reloadData",P.reload.apply(null,e)},function(e,a,n,i){var l=[];return layui.each(e,function(e,t){"function"===layui.type(a)?a(t):B.extend(t,a),l.push(B.extend({},t)),i||(l=l.concat(f(t[n],a,n,i)))}),l}),d=(t.prototype.updateStatus=function(e,t,a){var n=this.getOptions(),i=n.tree;return e=e||j.cache[n.id],f(e,t,i.customName.children,a)},t.prototype.getTableData=function(){var e=this.getOptions();return e.url?j.cache[e.id]:e.data},P.updateStatus=function(e,t,a){var e=F(e),n=e.getOptions();return a=a||(n.url?j.cache[n.id]:n.data),e.updateStatus(a,t)},P.sort=function(e){var t,a=F(e);!a||(t=a.getOptions()).url&&!t.autoSort||(a.initData(),P.renderData(e))},function(n){var t=n.config.id,i=F(t),a=n.data=P.getNodeDataByIndex(t,n.index),l=a[H],r=(n.dataIndex=l,n.update);n.update=function(){var e=arguments,t=(B.extend(i.getNodeDataByIndex(l),e[0]),r.apply(this,e)),a=n.config.tree.customName.name;return a in e[0]&&n.tr.find('td[data-field="'+a+'"]').children("div.layui-table-cell").removeClass("layui-table-tree-item"),i.renderTreeTable(n.tr,n.tr.attr("data-level"),!1),t},n.del=function(){P.removeNode(t,a)},n.setRowChecked=function(e){P.setRowChecked(t,{index:a,checked:e})}}),o=(P.updateNode=function(e,a,t){var n,i,l,r,d,o=F(e);o&&((r=o.getOptions()).tree,r=(n=r.elem.next()).find('tr[lay-data-index="'+a+'"]'),i=r.attr("data-index"),l=r.attr("data-level"),t&&(r=o.getNodeDataByIndex(a,!1,t),d=j.getTrHtml(e,[r]),layui.each(["main","fixed-l","fixed-r"],function(e,t){n.find(".layui-table-"+t+' tbody tr[lay-data-index="'+a+'"]').replaceWith(B(d[["trs","trs_fixed","trs_fixed_r"][e]].join("")).attr({"data-index":i,"lay-data-index":a,"data-level":l}))}),o.renderTreeTable(n.find('tr[lay-data-index="'+a+'"]'),l)))},P.removeNode=function(e,t){var a,n,i,l,r,d=F(e);d&&(r=(a=d.getOptions()).tree,n=a.elem.next(),i=[],t=d.getNodeDataByIndex("string"===layui.type(t)?t:t[H],!1,"delete"),l=d.getNodeDataByIndex(t[s]),d.updateCheckStatus(l),l=d.treeToFlat([t],t[r.customName.pid],t[s]),layui.each(l,function(e,t){i.push('tr[lay-data-index="'+t[H]+'"]')}),n.find(i.join(",")).remove(),r=d.initData(),layui.each(d.treeToFlat(r),function(e,t){t[m]&&t[m]!==t[H]&&n.find('tr[lay-data-index="'+t[m]+'"]').attr({"data-index":t[H],"lay-data-index":t[H]})}),layui.each(j.cache[e],function(e,t){n.find('tr[data-level="0"][lay-data-index="'+t[H]+'"]').attr("data-index",e)}),a.hasNumberCol&&g(d))},P.addNodes=function(e,t){var a=F(e);if(a){var n=a.getOptions(),i=n.tree,l=n.elem.next(),r=(t=t||{}).parentIndex,d=t.index,o=t.data,t=t.focus,c=(r="number"===layui.type(r)?r.toString():r)?a.getNodeDataByIndex(r):null,d="number"===layui.type(d)?d:-1,o=B.extend(!0,[],layui.isArray(o)?o:[o]);a.getTableData();if(c){var u=i.customName.isParent,s=i.customName.children;c[u]=!0;var f=(f=c[s])?(y=f.splice(-1===d?f.length:d),c[s]=f.concat(o,y)):c[s]=o,s=(a.updateStatus(f,function(e){(e[u]||i.view.showFlexIconIfNotParent)&&(e[z]=!1)}),a.treeToFlat(f));l.find(s.map(function(e){return'tr[lay-data-index="'+e[H]+'"]'}).join(",")).remove(),a.initData(),c[z]=!1,c[V]="local",J({trElem:l.find('tr[lay-data-index="'+r+'"]')},!0)}else{var y=j.cache[e].splice(-1===d?j.cache[e].length:d);if(j.cache[e]=j.cache[e].concat(o,y),n.url||(n.page?(f=n.page,n.data.splice.apply(n.data,[f.limit*(f.curr-1),f.limit].concat(j.cache[e]))):n.data=j.cache[e]),a.initData(),l.find(".layui-none").length)return j.renderData(e),o;var p,s=j.getTrHtml(e,o),x={trs:B(s.trs.join("")),trs_fixed:B(s.trs_fixed.join("")),trs_fixed_r:B(s.trs_fixed_r.join(""))},r=(layui.each(o,function(e,t){p={"data-index":t[H],"lay-data-index":t[H],"data-level":"0"},x.trs.eq(e).attr(p),x.trs_fixed.eq(e).attr(p),x.trs_fixed_r.eq(e).attr(p)}),parseInt(o[0][H])-1),f=l.find(L),n=l.find(R),s=l.find(Y);-1==r?(f.find('tr[data-level="0"][data-index="0"]').before(x.trs),n.find('tr[data-level="0"][data-index="0"]').before(x.trs_fixed),s.find('tr[data-level="0"][data-index="0"]').before(x.trs_fixed_r)):-1===d?(f.find("tbody").append(x.trs),n.find("tbody").append(x.trs_fixed),s.find("tbody").append(x.trs_fixed_r)):(r=y[0][m],f.find('tr[data-level="0"][data-index="'+r+'"]').before(x.trs),n.find('tr[data-level="0"][data-index="'+r+'"]').before(x.trs_fixed),s.find('tr[data-level="0"][data-index="'+r+'"]').before(x.trs_fixed_r)),layui.each(j.cache[e],function(e,t){l.find('tr[data-level="0"][lay-data-index="'+t[H]+'"]').attr("data-index",e)}),a.renderTreeTable(l.find(o.map(function(e,t,a){return'tr[lay-data-index="'+e[H]+'"]'}).join(",")))}return a.updateCheckStatus(c),P.resize(e),t&&l.find(L).find('tr[lay-data-index="'+o[0][H]+'"]').get(0).scrollIntoViewIfNeeded(),o}},P.checkStatus=function(e,n){var i,t,a,l=F(e);if(l)return l=l.getOptions().tree,i=j.config.checkName,t=P.getData(e,!0).filter(function(e,t,a){return e[i]||n&&e[b]}),a=!0,layui.each("all"===l.data.cascade?j.cache[e]:P.getData(e,!0),function(e,t){if(!t[i])return!(a=!1)}),{data:t,isAll:a}},P.on("sort",function(e){var e=e.config,t=e.elem.next(),e=e.id;t.hasClass(h)&&P.sort(e)}),P.on("row",function(e){e.config.elem.next().hasClass(h)&&d(e)}),P.on("rowDouble",function(e){var t=e.config,a=t.elem.next();t.id;a.hasClass(h)&&(d(e),(t.tree||{}).view.dblClickExpand&&J({trElem:e.tr.first()},null,null,null,!0))}),P.on("rowContextmenu",function(e){var t=e.config,a=t.elem.next();t.id;a.hasClass(h)&&d(e)}),P.on("tool",function(e){var t=e.config,a=t.elem.next();t.id;a.hasClass(h)&&d(e)}),P.on("edit",function(e){var t=e.config,a=t.elem.next();t.id;a.hasClass(h)&&(d(e),e.field===t.tree.customName.name&&((a={})[e.field]=e.value,e.update(a)))}),P.on("radio",function(e){var t=e.config,a=t.elem.next(),t=t.id;a.hasClass(h)&&(a=F(t),d(e),o.call(a,e.tr,e.checked))}),t.prototype.setRowCheckedClass=function(e,t){var a=this.getOptions(),n=(e.data("index"),a.elem.next());e[t?"addClass":"removeClass"](l),e.each(function(){var e=B(this).data("index");n.find('.layui-table-fixed-r tbody tr[data-index="'+e+'"]')[t?"addClass":"removeClass"](l)})},t.prototype.updateCheckStatus=function(e,t){var i=this,a=i.getOptions(),n=a.tree,l=a.id,r=a.elem.next(),d=j.config.checkName,a=n.data.cascade,o=(("all"===a||"parent"===a)&&e&&(a=i.updateParentCheckStatus(e,"boolean"===layui.type(t)?t:null),layui.each(a,function(e,t){var a=r.find('tr[lay-data-index="'+t[H]+'"] input[name="layTableCheckbox"]:not(:disabled)'),n=t[d];i.setRowCheckedClass(a.closest("tr"),n),x.render(a.prop({checked:n,indeterminate:t[b]}))})),!0),c=!1;return layui.each("all"===n.data.cascade?j.cache[l]:P.getData(l,!0),function(e,t){if((t[d]||t[b])&&(c=!0),t[d]||(o=!1),c&&!o)return!0}),c=c&&!o,x.render(r.find('input[name="layTableCheckbox"][lay-filter="layTableAllChoose"]').prop({checked:o,indeterminate:c})),o},t.prototype.updateParentCheckStatus=function(a,n){var i,e=this.getOptions(),t=e.tree,e=e.id,l=j.config.checkName,t=t.customName.children,r=[];return!(a[b]=!1)===n?a[t].length?layui.each(a[t],function(e,t){if(!t[l])return n=!1,a[b]=!0}):n=!1:!1===n?layui.each(a[t],function(e,t){if(t[l]||t[b])return a[b]=!0}):(n=!1,i=0,layui.each(a[t],function(e,t){t[l]&&i++}),n=a[t].length?a[t].length===i:a[l],a[b]=!n&&0')),n=(e.tree(a),i.elem=h(i.elem));if(n[0]){if(e.key=i.id||e.index,e.elem=a,e.elemNone=h('
                                                                '+i.text.none+"
                                                                "),n.html(e.elem),0==e.elem.find(".layui-tree-set").length)return e.elem.append(e.elemNone);i.showCheckbox&&e.renderForm("checkbox"),e.elem.find(".layui-tree-set").each(function(){var e=h(this);e.parent(".layui-tree-pack")[0]||e.addClass("layui-tree-setHide"),!e.next()[0]&&e.parents(".layui-tree-pack").eq(1).hasClass("layui-tree-lineExtend")&&e.addClass(F),e.next()[0]||e.parents(".layui-tree-set").eq(0).next()[0]||e.addClass(F)}),e.events()}},l.prototype.renderForm=function(e){i.render(e,"LAY-tree-"+this.index)},l.prototype.tree=function(l,e){var r=this,c=r.config,e=e||c.data;layui.each(e,function(e,i){var a=i.children&&0"),t=h(['
                                                                ','
                                                                ','
                                                                ',c.showLine?a?'':'':'',c.showCheckbox?'':"",c.isJump&&i.href?''+(i.title||i.label||c.text.defaultNodeName)+"":''+(i.title||i.label||c.text.defaultNodeName)+"","
                                                                ",function(){if(!c.edit)return"";var a={add:'',update:'',del:''},n=['
                                                                '];return!0===c.edit&&(c.edit=["update","del"]),"object"==typeof c.edit?(layui.each(c.edit,function(e,i){n.push(a[i]||"")}),n.join("")+"
                                                                "):void 0}(),"
                                                                "].join(""));a&&(t.append(n),r.tree(n,i.children)),l.append(t),t.prev("."+f)[0]&&t.prev().children(".layui-tree-pack").addClass("layui-tree-showLine"),a||t.parent(".layui-tree-pack").addClass("layui-tree-lineExtend"),r.spread(t,i),c.showCheckbox&&(i.checked&&r.checkids.push(i.id),r.checkClick(t,i)),c.edit&&r.operate(t,i)})},l.prototype.spread=function(n,t){var l=this,r=l.config,e=n.children("."+m),i=e.children("."+x),a=i.find('input[same="layuiTreeCheck"]'),c=e.find("."+k),e=e.find("."+b),d=r.onlyIconControl?c:i,s="";d.on("click",function(e){var i=n.children("."+g),a=(d.children(".layui-icon")[0]?d:d.find(".layui-tree-icon")).children(".layui-icon");i[0]?n.hasClass(w)?(n.removeClass(w),i.slideUp(200),a.removeClass(v).addClass(C),l.updateFieldValue(t,"spread",!1)):(n.addClass(w),i.slideDown(200),a.addClass(v).removeClass(C),l.updateFieldValue(t,"spread",!0),r.accordion&&((i=n.siblings("."+f)).removeClass(w),i.children("."+g).slideUp(200),i.find(".layui-tree-icon").children(".layui-icon").removeClass(v).addClass(C))):s="normal"}),e.on("click",function(){h(this).hasClass(o)||(s=n.hasClass(w)?r.onlyIconControl?"open":"close":r.onlyIconControl?"close":"open",a[0]&&l.updateFieldValue(t,"checked",a.prop("checked")),r.click&&r.click({elem:n,state:s,data:t}))})},l.prototype.updateFieldValue=function(e,i,a){i in e&&(e[i]=a)},l.prototype.setCheckbox=function(e,i,a){var t,n=this,l=(n.config,a.prop("checked"));a.prop("disabled")||("object"!=typeof i.children&&!e.find("."+g)[0]||e.find("."+g).find('input[same="layuiTreeCheck"]').each(function(e){this.disabled||((e=i.children[e])&&n.updateFieldValue(e,"checked",l),n.updateFieldValue(this,"checked",l))}),(t=function(e){var i,a,n;e.parents("."+f)[0]&&(a=(e=e.parent("."+g)).parent(),n=e.prev().find('input[same="layuiTreeCheck"]'),l?n.prop("checked",l):(e.find('input[same="layuiTreeCheck"]').each(function(){this.checked&&(i=!0)}),i||n.prop("checked",!1)),t(a))})(e),n.renderForm("checkbox"))},l.prototype.checkClick=function(a,n){var t=this,l=t.config;a.children("."+m).children("."+x).on("click",'input[same="layuiTreeCheck"]+',function(e){layui.stope(e);var e=h(this).prev(),i=e.prop("checked");e.prop("disabled")||(t.setCheckbox(a,n,e),t.updateFieldValue(n,"checked",i),l.oncheck&&l.oncheck({elem:a,checked:i,data:n}))})},l.prototype.operate=function(c,d){var s=this,o=s.config,e=c.children("."+m),u=e.children("."+x);e.children(".layui-tree-btnGroup").on("click",".layui-icon",function(e){layui.stope(e);var i,e=h(this).data("type"),n=c.children("."+g),t={data:d,type:e,elem:c};if("add"==e){n[0]||(o.showLine?(u.find("."+k).addClass("layui-tree-icon"),u.find("."+k).children(".layui-icon").addClass(C).removeClass("layui-icon-file")):u.find(".layui-tree-iconArrow").removeClass(y),c.append('
                                                                '));var a,l=o.operate&&o.operate(t),r={};if(r.title=o.text.defaultNodeName,r.id=l,s.tree(c.children("."+g),[r]),o.showLine&&(n[0]?(n.hasClass(N)||n.addClass(N),c.find("."+g).each(function(){h(this).children("."+f).last().addClass(F)}),(n.children("."+f).last().prev().hasClass(F)?n.children("."+f).last().prev():n.children("."+f).last()).removeClass(F),!c.parent("."+g)[0]&&c.next()[0]&&n.children("."+f).last().removeClass(F)):(l=c.siblings("."+f),a=1,r=c.parent("."+g),layui.each(l,function(e,i){h(i).children("."+g)[0]||(a=0)}),1==a?(l.children("."+g).addClass(T),l.children("."+g).children("."+f).removeClass(F),c.children("."+g).addClass(T),r.removeClass(N),r.children("."+f).last().children("."+g).children("."+f).last().addClass(F)):c.children("."+g).children("."+f).addClass(F))),!o.showCheckbox)return;u.find('input[same="layuiTreeCheck"]')[0].checked&&(c.children("."+g).children("."+f).last().find('input[same="layuiTreeCheck"]')[0].checked=!0),s.renderForm("checkbox")}else"update"==e?(l=u.children("."+b).html(),u.children("."+b).html(""),u.append(''),u.children(".layui-tree-editInput").val(l).focus(),i=function(e){var i=(i=e.val().trim())||o.text.defaultNodeName;e.remove(),u.children("."+b).html(i),t.data.title=i,o.operate&&o.operate(t)},u.children(".layui-tree-editInput").blur(function(){i(h(this))}),u.children(".layui-tree-editInput").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),i(h(this)))})):p.confirm('\u786e\u8ba4\u5220\u9664\u8be5\u8282\u70b9 "'+(d.title||"")+'" \u5417\uff1f',function(e){if(o.operate&&o.operate(t),t.status="remove",p.close(e),!c.prev("."+f)[0]&&!c.next("."+f)[0]&&!c.parent("."+g)[0])return c.remove(),void s.elem.append(s.elemNone);var l,a,i;c.siblings("."+f).children("."+m)[0]?(o.showCheckbox&&(l=function(e){var i,a,n,t;e.parents("."+f)[0]&&(i=e.siblings("."+f).children("."+m),a=(e=e.parent("."+g).prev()).find('input[same="layuiTreeCheck"]')[0],n=1,(t=0)==a.checked&&(i.each(function(e,i){i=h(i).find('input[same="layuiTreeCheck"]')[0];0!=i.checked||i.disabled||(n=0),i.disabled||(t=1)}),1==n&&1==t&&(a.checked=!0,s.renderForm("checkbox"),l(e.parent("."+f)))))})(c),o.showLine&&(e=c.siblings("."+f),a=1,i=c.parent("."+g),layui.each(e,function(e,i){h(i).children("."+g)[0]||(a=0)}),1==a?(n[0]||(i.removeClass(N),e.children("."+g).addClass(T),e.children("."+g).children("."+f).removeClass(F)),(c.next()[0]?i.children("."+f).last():c.prev()).children("."+g).children("."+f).last().addClass(F),c.next()[0]||c.parents("."+f)[1]||c.parents("."+f).eq(0).next()[0]||c.prev("."+f).addClass(F)):!c.next()[0]&&c.hasClass(F)&&c.prev().addClass(F))):(e=c.parent("."+g).prev(),o.showLine?(e.find("."+k).removeClass("layui-tree-icon"),e.find("."+k).children(".layui-icon").removeClass(v).addClass("layui-icon-file"),(i=e.parents("."+g).eq(0)).addClass(N),i.children("."+f).each(function(){h(this).children("."+g).children("."+f).last().addClass(F)})):e.find(".layui-tree-iconArrow").addClass(y),c.parents("."+f).eq(0).removeClass(w),c.parent("."+g).remove()),c.remove()})})},l.prototype.events=function(){var i=this,t=i.config;i.elem.find(".layui-tree-checkedFirst");i.setChecked(i.checkids),i.elem.find(".layui-tree-search").on("keyup",function(){var e=h(this),a=e.val(),e=e.nextAll(),n=[];e.find("."+b).each(function(){var i,e=h(this).parents("."+m);-1!=h(this).html().indexOf(a)&&(n.push(h(this).parent()),(i=function(e){e.addClass("layui-tree-searchShow"),e.parent("."+g)[0]&&i(e.parent("."+g).parent("."+f))})(e.parent("."+f)))}),e.find("."+m).each(function(){var e=h(this).parent("."+f);e.hasClass("layui-tree-searchShow")||e.addClass(y)}),0==e.find(".layui-tree-searchShow").length&&i.elem.append(i.elemNone),t.onsearch&&t.onsearch({elem:n})}),i.elem.find(".layui-tree-search").on("keydown",function(){h(this).nextAll().find("."+m).each(function(){h(this).parent("."+f).removeClass("layui-tree-searchShow "+y)}),h(".layui-tree-emptyText")[0]&&h(".layui-tree-emptyText").remove()})},l.prototype.getChecked=function(){var t=this,e=t.config,i=[],a=[],l=(t.elem.find(".layui-form-checked").each(function(){i.push(h(this).prev()[0].value)}),function(e,n){layui.each(e,function(e,a){layui.each(i,function(e,i){if(a.id==i)return t.updateFieldValue(a,"checked",!0),delete(i=h.extend({},a)).children,n.push(i),a.children&&(i.children=[],l(a.children,i.children)),!0})})});return l(h.extend({},e.data),a),a},l.prototype.setChecked=function(l){this.config;this.elem.find("."+f).each(function(e,i){var a=h(this).data("id"),n=h(i).children("."+m).find('input[same="layuiTreeCheck"]'),t=n.next();if("number"==typeof l){if(a.toString()==l.toString())return n[0].checked||t.click(),!1}else"object"==typeof l&&layui.each(l,function(e,i){if(i.toString()==a.toString()&&!n[0].checked)return t.click(),!0})})},t.that={},t.config={},n.reload=function(e,i){e=t.that[e];return e.reload(i),t.call(e)},n.getChecked=function(e){return t.that[e].getChecked()},n.setChecked=function(e,i){return t.that[e].setChecked(i)},n.render=function(e){e=new l(e);return t.call(e)},e(a,n)});layui.define(["laytpl","form"],function(e){"use strict";var s=layui.$,n=layui.laytpl,t=layui.form,a="transfer",i={config:{},index:layui[a]?layui[a].index+1e4:0,set:function(e){var t=this;return t.config=s.extend({},t.config,e),t},on:function(e,t){return layui.onevent.call(this,a,e,t)}},l=function(){var t=this,e=t.config,a=e.id||t.index;return l.that[a]=t,{config:l.config[a]=e,reload:function(e){t.reload.call(t,e)},getData:function(){return t.getData.call(t)}}},d="layui-hide",h="layui-btn-disabled",r="layui-none",c="layui-transfer-box",u="layui-transfer-header",o="layui-transfer-search",f="layui-transfer-data",y=function(e){return['
                                                                ','
                                                                ','","
                                                                ","{{# if(d.data.showSearch){ }}",'","{{# } }}",'
                                                                  ',"
                                                                  "].join("")},p=['
                                                                  ',y({index:0,checkAllName:"layTransferLeftCheckAll"}),'
                                                                  ','",'","
                                                                  ",y({index:1,checkAllName:"layTransferRightCheckAll"}),"
                                                                  "].join(""),v=function(e){var t=this;t.index=++i.index,t.config=s.extend({},t.config,i.config,e),t.render()};v.prototype.config={title:["\u5217\u8868\u4e00","\u5217\u8868\u4e8c"],width:200,height:360,data:[],value:[],showSearch:!1,id:"",text:{none:"\u65e0\u6570\u636e",searchNone:"\u65e0\u5339\u914d\u6570\u636e"}},v.prototype.reload=function(e){var t=this;t.config=s.extend({},t.config,e),t.render()},v.prototype.render=function(){var e=this,t=e.config,a=e.elem=s(n(p,{open:"{{",close:"}}"}).render({data:t,index:e.index})),i=t.elem=s(t.elem);i[0]&&(t.data=t.data||[],t.value=t.value||[],t.id="id"in t?t.id:elem.attr("id")||e.index,e.key=t.id,i.html(e.elem),e.layBox=e.elem.find("."+c),e.layHeader=e.elem.find("."+u),e.laySearch=e.elem.find("."+o),e.layData=a.find("."+f),e.layBtn=a.find(".layui-transfer-active .layui-btn"),e.layBox.css({width:t.width,height:t.height}),e.layData.css({height:(i=t.height-e.layHeader.outerHeight(),t.showSearch&&(i-=e.laySearch.outerHeight()),i-2)}),e.renderData(),e.events())},v.prototype.renderData=function(){var e=this,t=e.config,l=[{checkName:"layTransferLeftCheck",views:[]},{checkName:"layTransferRightCheck",views:[]}];e.parseData(function(a){var i=a.selected?1:0,n=["
                                                                • ",'',"
                                                                • "].join("");i?layui.each(t.value,function(e,t){t==a.value&&a.selected&&(l[i].views[e]=n)}):l[i].views.push(n),delete a.selected}),e.layData.eq(0).html(l[0].views.join("")),e.layData.eq(1).html(l[1].views.join("")),e.renderCheckBtn()},v.prototype.renderForm=function(e){t.render(e,"LAY-transfer-"+this.index)},v.prototype.renderCheckBtn=function(r){var c=this,o=c.config;r=r||{},c.layBox.each(function(e){var t=s(this),a=t.find("."+f),t=t.find("."+u).find('input[type="checkbox"]'),i=a.find('input[type="checkbox"]'),n=0,l=!1;i.each(function(){var e=s(this).data("hide");(this.checked||this.disabled||e)&&n++,this.checked&&!e&&(l=!0)}),t.prop("checked",l&&n===i.length),c.layBtn.eq(e)[l?"removeClass":"addClass"](h),r.stopNone||(i=a.children("li:not(."+d+")").length,c.noneView(a,i?"":o.text.none))}),c.renderForm("checkbox")},v.prototype.noneView=function(e,t){var a=s('

                                                                  '+(t||"")+"

                                                                  ");e.find("."+r)[0]&&e.find("."+r).remove(),t.replace(/\s/g,"")&&e.append(a)},v.prototype.setValue=function(){var e=this.config,t=[];return this.layBox.eq(1).find("."+f+' input[type="checkbox"]').each(function(){s(this).data("hide")||t.push(this.value)}),e.value=t,this},v.prototype.parseData=function(t){var i=this.config,n=[];return layui.each(i.data,function(e,a){a=("function"==typeof i.parseData?i.parseData(a):a)||a,n.push(a=s.extend({},a)),layui.each(i.value,function(e,t){t==a.value&&(a.selected=!0)}),t&&t(a)}),i.data=n,this},v.prototype.getData=function(e){var t=this.config,i=[];return this.setValue(),layui.each(e||t.value,function(e,a){layui.each(t.data,function(e,t){delete t.selected,a==t.value&&i.push(t)})}),i},v.prototype.transfer=function(e,t){var a,i=this,n=i.config,l=i.layBox.eq(e),r=[],t=(t?((a=(t=t).find('input[type="checkbox"]'))[0].checked=!1,l.siblings("."+c).find("."+f).append(t.clone()),t.remove(),r.push(a[0].value),i.setValue()):l.each(function(e){s(this).find("."+f).children("li").each(function(){var e=s(this),t=e.find('input[type="checkbox"]'),a=t.data("hide");t[0].checked&&!a&&(t[0].checked=!1,l.siblings("."+c).find("."+f).append(e.clone()),e.remove(),r.push(t[0].value)),i.setValue()})}),i.renderCheckBtn(),l.siblings("."+c).find("."+o+" input"));""!==t.val()&&t.trigger("keyup"),n.onchange&&n.onchange(i.getData(r),e)},v.prototype.events=function(){var n=this,l=n.config;n.elem.on("click",'input[lay-filter="layTransferCheckbox"]+',function(){var e=s(this).prev(),t=e[0].checked,a=e.parents("."+c).eq(0).find("."+f);e[0].disabled||("all"===e.attr("lay-type")&&a.find('input[type="checkbox"]').each(function(){this.disabled||(this.checked=t)}),setTimeout(function(){n.renderCheckBtn({stopNone:!0})},0))}),n.elem.on("dblclick","."+f+">li",function(e){var t=s(this),a=t.children('input[type="checkbox"]'),i=t.parent().parent();a[0].disabled||n.transfer(i.data("index"),t)}),n.layBtn.on("click",function(){var e=s(this),t=e.data("index");e.hasClass(h)||n.transfer(t)}),n.laySearch.find("input").on("keyup",function(){var i=this.value,e=s(this).parents("."+o).eq(0).siblings("."+f),t=e.children("li"),t=(t.each(function(){var e=s(this),t=e.find('input[type="checkbox"]'),a=t[0].title,a=("cs"!==l.showSearch&&(a=a.toLowerCase(),i=i.toLowerCase()),-1!==a.indexOf(i));e[a?"removeClass":"addClass"](d),t.data("hide",!a)}),n.renderCheckBtn(),t.length===e.children("li."+d).length);n.noneView(e,t?l.text.searchNone:"")})},l.that={},l.config={},i.reload=function(e,t){e=l.that[e];return e.reload(t),l.call(e)},i.getData=function(e){return l.that[e].getData()},i.render=function(e){e=new v(e);return l.call(e)},e(a,i)});layui.define(["jquery","lay"],function(e){"use strict";var a=layui.$,t=layui.lay,o=(layui.hint(),layui.device(),{config:{},set:function(e){var i=this;return i.config=a.extend({},i.config,e),i},on:function(e,i){return layui.onevent.call(this,r,e,i)}}),r="carousel",d="layui-this",s="layui-carousel-left",u="layui-carousel-right",c="layui-carousel-prev",m="layui-carousel-next",l="layui-carousel-arrow",f="layui-carousel-ind",i=function(e){var i=this;i.config=a.extend({},i.config,o.config,e),i.render()};i.prototype.config={width:"600px",height:"280px",full:!1,arrow:"hover",indicator:"inside",autoplay:!0,interval:3e3,anim:"",trigger:"click",index:0},i.prototype.render=function(){var e=this,i=e.config,n=a(i.elem);if(1*[carousel-item]>*"),i.index<0&&(i.index=0),i.index>=e.elemItem.length&&(i.index=e.elemItem.length-1),i.interval<800&&(i.interval=800),i.full?i.elem.css({position:"fixed",width:"100%",height:"100%",zIndex:9999}):i.elem.css({width:i.width,height:i.height}),i.elem.attr("lay-anim",i.anim),e.elemItem.eq(i.index).addClass(d),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},i.prototype.reload=function(e){var i=this;clearInterval(i.timer),i.config=a.extend({},i.config,e),i.render()},i.prototype.prevIndex=function(){var e=this.config.index-1;return e=e<0?this.elemItem.length-1:e},i.prototype.nextIndex=function(){var e=this.config.index+1;return e=e>=this.elemItem.length?0:e},i.prototype.addIndex=function(e){var i=this.config;i.index=i.index+(e=e||1),i.index>=this.elemItem.length&&(i.index=0)},i.prototype.subIndex=function(e){var i=this.config;i.index=i.index-(e=e||1),i.index<0&&(i.index=this.elemItem.length-1)},i.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(clearInterval(e.timer),e.timer=setInterval(function(){e.slide()},i.interval))},i.prototype.arrow=function(){var i=this,e=i.config,n=a(['",'"].join(""));e.elem.attr("lay-arrow",e.arrow),e.elem.find("."+l)[0]&&e.elem.find("."+l).remove(),e.elem.append(n),n.on("click",function(){var e=a(this).attr("lay-type");i.slide(e)})},i.prototype["goto"]=function(e){var i=this,n=i.config;e>n.index?i.slide("add",e-n.index):e
                                                                    ',(i=[],layui.each(e.elemItem,function(e){i.push("")}),i.join("")),"
                                                                  "].join(""));n.elem.attr("lay-indicator",n.indicator),n.elem.find("."+f)[0]&&n.elem.find("."+f).remove(),n.elem.append(t),"updown"===n.anim&&t.css("margin-top",-t.height()/2),t.find("li").on("hover"===n.trigger?"mouseover":n.trigger,function(){e["goto"](a(this).index())})},i.prototype.slide=function(e,i){var n=this,t=n.elemItem,a=n.config,o=a.index,l=a.elem.attr("lay-filter");n.haveSlide||("sub"===e?(n.subIndex(i),t.eq(a.index).addClass(c),setTimeout(function(){t.eq(o).addClass(u),t.eq(a.index).addClass(u)},50)):(n.addIndex(i),t.eq(a.index).addClass(m),setTimeout(function(){t.eq(o).addClass(s),t.eq(a.index).addClass(s)},50)),setTimeout(function(){t.removeClass(d+" "+c+" "+m+" "+s+" "+u),t.eq(a.index).addClass(d),n.haveSlide=!1},300),n.elemInd.find("li").eq(a.index).addClass(d).siblings().removeClass(d),n.haveSlide=!0,e={index:a.index,prevIndex:o,item:t.eq(a.index)},"function"==typeof a.change&&a.change(e),layui.event.call(this,r,"change("+l+")",e))},i.prototype.events=function(){var e=this,i=e.config;i.elem.data("haveEvents")||(i.elem.on("mouseenter",function(){"always"!==e.config.autoplay&&clearInterval(e.timer)}).on("mouseleave",function(){"always"!==e.config.autoplay&&e.autoplay()}),i.elem.data("haveEvents",!0))},o.render=function(e){return new i(e)},e(r,o)});layui.define(["jquery","lay"],function(e){"use strict";var s=layui.jquery,r=layui.lay,c={config:{},index:layui.rate?layui.rate.index+1e4:0,set:function(e){var a=this;return a.config=s.extend({},a.config,e),a},on:function(e,a){return layui.onevent.call(this,l,e,a)}},l="rate",f="layui-icon-rate",h="layui-icon-rate-solid",o="layui-icon-rate-half",u="layui-icon-rate-solid layui-icon-rate-half",v="layui-icon-rate layui-icon-rate-half",a=function(e){var a=this;a.index=++c.index,a.config=s.extend({},a.config,c.config,e),a.render()};a.prototype.config={length:5,text:!1,readonly:!1,half:!1,value:0,theme:""},a.prototype.render=function(){var e=this,a=e.config,l=s(a.elem);if(1a.length&&(a.value=a.length),parseInt(a.value)===a.value||a.half||(a.value=Math.ceil(a.value)-a.value<.5?Math.ceil(a.value):Math.floor(a.value)),'
                                                                    "),t=1;t<=a.length;t++){var o='
                                                                  • ";a.half&&parseInt(a.value)!==a.value&&t==Math.ceil(a.value)?n=n+'
                                                                  • ":n+=o}n+="
                                                                  "+(a.text?''+a.value+"\u661f":"")+"";var l=a.elem,u=l.next(".layui-rate");u[0]&&u.remove(),e.elemTemp=s(n),a.span=e.elemTemp.next("span"),a.setText&&a.setText(a.value),l.html(e.elemTemp),l.addClass("layui-inline"),a.readonly||e.action()},a.prototype.setvalue=function(e){this.config.value=e,this.render()},a.prototype.action=function(){var i=this.config,n=this.elemTemp,t=n.find("i").width();n.children("li").each(function(e){var a=e+1,l=s(this);l.on("click",function(e){i.value=a,i.half&&e.pageX-s(this).offset().left<=t/2&&(i.value=i.value-.5),i.text&&n.next("span").text(i.value+"\u661f"),i.choose&&i.choose(i.value),i.setText&&i.setText(i.value)}),l.on("mousemove",function(e){n.find("i").each(function(){s(this).addClass(f).removeClass(u)}),n.find("i:lt("+a+")").each(function(){s(this).addClass(h).removeClass(v)}),i.half&&e.pageX-s(this).offset().left<=t/2&&l.children("i").addClass(o).removeClass(h)}),l.on("mouseleave",function(){n.find("i").each(function(){s(this).addClass(f).removeClass(u)}),n.find("i:lt("+Math.floor(i.value)+")").each(function(){s(this).addClass(h).removeClass(v)}),i.half&&parseInt(i.value)!==i.value&&n.children("li:eq("+Math.floor(i.value)+")").children("i").addClass(o).removeClass("layui-icon-rate-solid layui-icon-rate")})})},a.prototype.events=function(){this.config},c.render=function(e){e=new a(e);return function(){var a=this;return{setvalue:function(e){a.setvalue.call(a,e)},config:a.config}}.call(e)},e(l,c)});layui.define("jquery",function(l){"use strict";var g=layui.$,e=function(l){};e.prototype.load=function(l){var t,i,n,e,r,o,a,c,m,s,u,f,y,d=this,p=0,h=g((l=l||{}).elem);if(h[0])return e=g(l.scrollElem||document),r=l.mb||50,o=!("isAuto"in l)||l.isAuto,a=l.end||"\u6ca1\u6709\u66f4\u591a\u4e86",c=l.scrollElem&&l.scrollElem!==document,m="\u52a0\u8f7d\u66f4\u591a",s=g('"),h.find(".layui-flow-more")[0]||h.append(s),u=function(l,e){l=g(l),s.before(l),(e=0==e||null)?s.html(a):s.find("a").html(m),i=e,t=null,y&&y()},f=function(){t=!0,s.find("a").html(''),"function"==typeof l.done&&l.done(++p,u)},f(),s.find("a").on("click",function(){g(this);i||t||f()}),l.isLazyimg&&(y=d.lazyimg({elem:l.elem+" img",scrollElem:l.scrollElem})),o&&e.on("scroll",function(){var e=g(this),o=e.scrollTop();n&&clearTimeout(n),!i&&h.width()&&(n=setTimeout(function(){var l=(c?e:g(window)).height();(c?e.prop("scrollHeight"):document.documentElement.scrollHeight)-o-l<=r&&(t||f())},100))}),d},e.prototype.lazyimg=function(l){var e,c=this,m=0,s=g((l=l||{}).scrollElem||document),u=l.elem||"img",f=l.scrollElem&&l.scrollElem!==document,y=function(e,l){var o,t=s.scrollTop(),l=t+l,i=f?e.offset().top-s.offset().top+t:e.offset().top;t<=i&&i<=l&&e.attr("lay-src")&&(o=e.attr("lay-src"),layui.img(o,function(){var l=c.lazyimg.elem.eq(m);e.attr("src",o).removeAttr("lay-src"),l[0]&&n(l),m++},function(){c.lazyimg.elem.eq(m);e.removeAttr("lay-src")}))},n=function(l,e){var o=(f?e||s:g(window)).height(),t=s.scrollTop(),i=t+o;if(c.lazyimg.elem=g(u),l)y(l,o);else for(var n=0;n"),preview:"Preview"}},I=function(e){return C.trim(e).replace(/^\n|\n$/,"")};e("code",function(e){var _=e=C.extend(!0,{},a,e);e.elem=C(e.elem),e.elem[0]&&layui.each(e.elem.get().reverse(),function(e,a){var t,l,i,o,n,s,c,d,r,u,y,E,p=C(a),f=C.extend(!0,{},_,lay.options(a),(t={},layui.each(["title","height","encode","skin","about"],function(e,a){var i=p.attr("lay-"+a);"string"==typeof i&&(t[a]=i)}),t)),v=p.data("code")||(i=[],p.children("textarea").each(function(){i.push(I(this.value))}),0===i.length&&i.push(I(p.html())),i),a=(p.data("code",v),l=v.join("")),h=("function"==typeof f.codeParse&&(a=l=f.codeParse(a)),{copy:{className:"file-b",title:["\u590d\u5236\u4ee3\u7801"],event:function(e,a){if("function"==typeof f.onCopy)f.onCopy(l);else try{navigator.clipboard.writeText(w.unescape(l)).then(function(){T.msg("\u5df2\u590d\u5236",{icon:1})})}catch(i){T.msg("\u590d\u5236\u5931\u8d25",{icon:2})}}}}),m=(f.preview&&(o="LAY-CODE-DF-"+e,E=f.layout||["code","preview"],n="iframe"===f.preview,u=C('
                                                                  '),y=C('
                                                                  '),s=C('
                                                                  '),c=C('
                                                                  '),d=C('
                                                                  '),M=p.parent("."+x.ELEM_PREVIEW),m=p.prev("."+x.ELEM_TAB),L=p.next("."+x.ELEM_ITEM+"-preview"),f.id&&u.attr("id",f.id),u.addClass(f.className),y.attr("lay-filter",o),f.encode=!0,layui.each(E,function(e,a){var i=C('
                                                                • ');0===e&&i.addClass("layui-this"),i.html(f.text[a]),s.append(i)}),C.extend(h,{full:{className:"screen-full",title:["\u6700\u5927\u5316\u663e\u793a","\u8fd8\u539f\u663e\u793a"],event:function(e,a){var i=e.closest("."+x.ELEM_PREVIEW),t="layui-icon-"+this.className,l="layui-icon-screen-restore",o=this.title,n=C("html,body"),s="layui-scrollbar-hide";e.hasClass(t)?(i.addClass(x.ELEM_FULL),e.removeClass(t).addClass(l),e.attr("title",o[1]),n.addClass(s)):(i.removeClass(x.ELEM_FULL),e.removeClass(l).addClass(t),e.attr("title",o[0]),n.removeClass(s))}},window:{className:"release",title:["\u5728\u65b0\u7a97\u53e3\u9884\u89c8"],event:function(e,a){w.openWin({content:l})}}}),f.copy&&("array"===layui.type(f.tools)?-1===f.tools.indexOf("copy")&&f.tools.unshift("copy"):f.tools=["copy"]),d.on("click",">i",function(){var e=C(this),a=e.data("type");"function"==typeof h[a].event&&h[a].event(e,a),"function"==typeof f.toolsEvent&&f.toolsEvent(e,a)}),layui.each(f.tools,function(e,a){var i=h[a]&&h[a].className||a,t=h[a].title||[""];d.append('')}),m[0]&&m.remove(),L[0]&&L.remove(),M[0]&&p.unwrap(),y.append(s),f.tools&&y.append(d),p.wrap(u).addClass(x.ELEM_ITEM).before(y),n&&c.html(''),r=function(e){var a=e.children("iframe")[0],i=(n&&a?a.srcdoc=l:e.html(v.join("")),{container:e,render:function(){g.render(e.find(".layui-form")),b.render()}});setTimeout(function(){"function"==typeof f.done&&f.done(i)},3)},"preview"===E[0]?(c.addClass(x.ELEM_SHOW),p.before(c),r(c)):p.addClass(x.ELEM_SHOW).after(c),f.codeStyle=[f.style,f.codeStyle].join(""),f.previewStyle=[f.style,f.previewStyle].join(""),c.attr("style",f.previewStyle),b.on("tab("+o+")",function(e){var a=C(this),i=C(e.elem).closest("."+x.ELEM_PREVIEW).find("."+x.ELEM_ITEM),e=i.eq(e.index);i.removeClass(x.ELEM_SHOW),e.addClass(x.ELEM_SHOW),"preview"===a.attr("lay-id")&&r(e)})),f.ln?"ol":"ul"),L=C("<"+m+' class="layui-code-'+m+'">'),M=C('
                                                                  ');p.addClass("layui-code-view layui-box"),f.skin&&("notepad"===f.skin&&(f.skin="dark"),p.removeClass("layui-code-dark layui-code-light"),p.addClass("layui-code-"+f.skin)),a=(a=f.encode?w.escape(a):a).replace(/[\r\t\n]+/g,"
                                                                • "),p.html(L.html("
                                                                • "+a+"
                                                                • ")),f.header&&!p.children("."+x.ELEM_TITLE)[0]&&(M.html((f.title||f.text.code)+(f.about?'
                                                                  '+f.about+"
                                                                  ":"")),p.prepend(M)),f.elem.length===e+1&&"function"==typeof f.allDone&&f.allDone(),0<(u=Math.floor(L.find("li").length/100))&&L.css("margin-left",u+"px"),f.height&&L.css("max-height",f.height),L.attr("style",f.codeStyle),f.copy&&!f.preview&&(y=C(['','',""].join("")),E=p.children("."+x.ELEM_COPY),(L[0].style.height||L[0].style.maxHeight)&&y.addClass(x.ELEM_COPY+"-offset"),E[0]&&E.remove(),p.append(y),y.on("click",function(){h.copy.event()}))})})}),layui["layui.all"]||layui.addcss("modules/code.css?v=3","skincodecss"); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/button.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/button.css new file mode 100644 index 0000000000000000000000000000000000000000..fcc6ba32ccefc78484aa18545fa737d6024f3c24 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/button.css @@ -0,0 +1,169 @@ +.pear-btn { + display: inline-block; + line-height: 38px; + white-space: nowrap; + cursor: pointer; + text-align: center; + box-sizing: border-box; + outline: none; + transition: 0.1s; + font-weight: 500; + padding: 0 18px; + height: 38px; + font-size: 14px; + background-color: white; + border: 1px solid #dcdfe6; + border-radius: 2px; +} + +.pear-btn i { + font-size: 13px; +} + +.pear-btn:hover { + opacity: .8; + filter: alpha(opacity=80); + color: #409eff; + background-color: #ECF5FF; +} + +.pear-btn-danger, +.pear-btn-warming, +.pear-btn-success, +.pear-btn-primary { + height: 37px; + line-height: 37px; + color: #fff !important +} + +/** Button 主题 */ +.pear-btn-primary { + border: 1px solid #2D8CF0; + background-color: #2D8CF0 !important; +} +.pear-btn-danger { + border: 1px solid #f56c6c; + background-color: #f56c6c !important; +} +.pear-btn-warming { + border: 1px solid #f6ad55; + background-color: #f6ad55 !important; +} +.pear-btn-success { + border: 1px solid #36b368; + background-color: #36b368 !important; +} + +.pear-btn[round] { + border-radius: 50px; +} + +.pear-btn-primary[plain] { + color: #409eff !important; + background: #ecf5ff 10% !important; +} + +.pear-btn-primary[plain]:hover { + color: #fff !important; + background-color: #2d8cf0!important +} + +.pear-btn-success[plain] { + color: #36b368 !important; + background: #f0f9eb !important; +} + +.pear-btn-success[plain]:hover { + color: white !important; + background-color: #36b368 !important +} + +.pear-btn-warming[plain] { + color: #e6a23c !important; + background: #fdf6ec !important; +} + +.pear-btn-warming[plain]:hover { + color: white !important; + background-color: #e6a23c !important +} + +.pear-btn-danger[plain] { + color: #f56c6c !important; + background: #fef0f0 !important; +} + +.pear-btn-danger[plain]:hover { + color: white !important; + background-color: #f56c6c !important +} + +/** Button Group */ +.pear-btn-group { + display: inline-block; + vertical-align: middle; +} + +.pear-btn-group .pear-btn { + float: left; + position: relative; + border-radius: 0px; + margin-left: 1px; + margin-right: 1px; +} + +.pear-btn-md { + height: 34px; + line-height: 34px; + padding: 0 10px; + font-size: 12.5px; +} + +.pear-btn-group .pear-btn:first-child { + border-top-left-radius: 4px !important; + border-bottom-left-radius: 4px !important; +} + +.pear-btn-group .pear-btn:last-child { + border-top-right-radius: 4px !important; + border-bottom-right-radius: 4px !important; +} + +.pear-btn-group .pear-btn[round]:first-child { + border-top-left-radius: 50px !important; + border-bottom-left-radius: 50px !important; +} + +.pear-btn-group .pear-btn[round]:last-child { + border-top-right-radius: 50px !important; + border-bottom-right-radius: 50px !important; +} + +/** Button Size*/ +.pear-btn-sm { + height: 32px; + line-height: 32px; + padding: 0 10px; + font-size: 12px; +} + +.pear-btn-xs { + height: 28px; + line-height: 28px; + padding: 0 8px; + font-size: 12px; +} + +.pear-btn-md { + height: 34px; + line-height: 34px; + padding: 0 10px; + font-size: 12.5px; +} + +.pear-btn-lg { + height: 44px; + line-height: 44px; + padding: 0 25px; + font-size: 16px; +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/card.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/card.css new file mode 100644 index 0000000000000000000000000000000000000000..39b4ed28ec3a169084d39f0a64e883b6912c03e3 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/card.css @@ -0,0 +1,93 @@ +.project-list-item { + background-color: #fff; + border-radius: 4px; + cursor: pointer; + transition: all .2s; +} + +.project-list-item:hover { + box-shadow: 2px 0 4px rgba(0, 21, 41, .35); +} + +.project-list-item .project-list-item-cover { + width: 100%; + height: 180px; + display: block; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +.project-list-item-body { + padding: 20px; + border: 1px solid #e8e8e8; +} + +.project-list-item .project-list-item-body>h2 { + font-size: 16px; + color: #333; + margin-bottom: 12px; +} + +.project-list-item .project-list-item-text { + height: 40px; + overflow: hidden; + margin-bottom: 12px; +} + +.project-list-item .project-list-item-desc { + position: relative; +} + +.project-list-item .project-list-item-desc .time { + color: #999; + font-size: 12px; +} + +.project-list-item .project-list-item-desc .ew-head-list { + position: absolute; + right: 0; + top: 0; +} + +.ew-head-list .ew-head-list-item:first-child { + margin-left: 0; +} + +.ew-head-list .ew-head-list-item { + width: 22px; + height: 22px; + border-radius: 50%; + border: 1px solid #fff; + margin-left: -10px; +} + +.ew-head-list .ew-head-list-item { + width: 22px; + height: 22px; + border-radius: 50%; + border: 1px solid #fff; + margin-left: -10px; +} + +.cloud-card-component { + padding: 20px; +} + +.cloud-card-component .layui-table-click { + border-radius: 6px!important; +} + +.ew-table-loading { + padding: 10px 0; + text-align: center; +} +.ew-table-loading > i { + color: #999; + font-size: 30px; +} +.ew-table-loading.ew-loading-float { + position: absolute; + top: 0; + left: 0; + right: 0; +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/code.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/code.css new file mode 100644 index 0000000000000000000000000000000000000000..4bde0d3d69692553fce81f4057991084372c499a --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/code.css @@ -0,0 +1,9 @@ +.layui-colla-content{ + padding: 0px; +} +.layui-code-view{ + margin: 0px!important; +} +.layui-code-h3{ + display: none!important; +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/cropper.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/cropper.css new file mode 100644 index 0000000000000000000000000000000000000000..2c6404269ec581593a1f3bca286fcb4107b3ae8d --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/cropper.css @@ -0,0 +1,272 @@ +.cropper-container { + position: relative; + overflow: hidden; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: transparent; + -webkit-touch-callout: none +} + +.cropper-container img { + display: block; + width: 100%; + min-width: 0 !important; + max-width: none !important; + height: 100%; + min-height: 0 !important; + max-height: none !important; + image-orientation: 0deg !important +} + +.cropper-canvas, +.cropper-crop-box, +.cropper-drag-box, +.cropper-modal { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0 +} + +.cropper-drag-box { + background-color: #fff; + filter: alpha(opacity=0); + opacity: 0 +} + +.cropper-modal { + background-color: #000; + filter: alpha(opacity=50); + opacity: .5 +} + +.cropper-view-box { + display: block; + width: 100%; + height: 100%; + overflow: hidden; + outline: #69f solid 1px; + outline-color: rgba(102, 153, 255, .75) +} + +.cropper-dashed { + position: absolute; + display: block; + filter: alpha(opacity=50); + border: 0 dashed #fff; + opacity: .5 +} + +.cropper-dashed.dashed-h { + top: 33.33333333%; + left: 0; + width: 100%; + height: 33.33333333%; + border-top-width: 1px; + border-bottom-width: 1px +} + +.cropper-dashed.dashed-v { + top: 0; + left: 33.33333333%; + width: 33.33333333%; + height: 100%; + border-right-width: 1px; + border-left-width: 1px +} + +.cropper-face, +.cropper-line, +.cropper-point { + position: absolute; + display: block; + width: 100%; + height: 100%; + filter: alpha(opacity=10); + opacity: .1 +} + +.cropper-face { + top: 0; + left: 0; + cursor: move; + background-color: #fff +} + +.cropper-line { + background-color: #69f +} + +.cropper-line.line-e { + top: 0; + right: -3px; + width: 5px; + cursor: e-resize +} + +.cropper-line.line-n { + top: -3px; + left: 0; + height: 5px; + cursor: n-resize +} + +.cropper-line.line-w { + top: 0; + left: -3px; + width: 5px; + cursor: w-resize +} + +.cropper-line.line-s { + bottom: -3px; + left: 0; + height: 5px; + cursor: s-resize +} + +.cropper-point { + width: 5px; + height: 5px; + background-color: #69f; + filter: alpha(opacity=75); + opacity: .75 +} + +.cropper-point.point-e { + top: 50%; + right: -3px; + margin-top: -3px; + cursor: e-resize +} + +.cropper-point.point-n { + top: -3px; + left: 50%; + margin-left: -3px; + cursor: n-resize +} + +.cropper-point.point-w { + top: 50%; + left: -3px; + margin-top: -3px; + cursor: w-resize +} + +.cropper-point.point-s { + bottom: -3px; + left: 50%; + margin-left: -3px; + cursor: s-resize +} + +.cropper-point.point-ne { + top: -3px; + right: -3px; + cursor: ne-resize +} + +.cropper-point.point-nw { + top: -3px; + left: -3px; + cursor: nw-resize +} + +.cropper-point.point-sw { + bottom: -3px; + left: -3px; + cursor: sw-resize +} + +.cropper-point.point-se { + right: -3px; + bottom: -3px; + width: 20px; + height: 20px; + cursor: se-resize; + filter: alpha(opacity=100); + opacity: 1 +} + +.cropper-point.point-se:before { + position: absolute; + right: -50%; + bottom: -50%; + display: block; + width: 200%; + height: 200%; + content: " "; + background-color: #69f; + filter: alpha(opacity=0); + opacity: 0 +} + +@media (min-width:768px) { + .cropper-point.point-se { + width: 15px; + height: 15px + } +} + +@media (min-width:992px) { + .cropper-point.point-se { + width: 10px; + height: 10px + } +} + +@media (min-width:1200px) { + .cropper-point.point-se { + width: 5px; + height: 5px; + filter: alpha(opacity=75); + opacity: .75 + } +} + +.cropper-bg { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC) +} + +.cropper-invisible { + filter: alpha(opacity=0); + opacity: 0 +} + +.cropper-hide { + position: fixed; + top: 0; + left: 0; + z-index: -1; + width: auto !important; + min-width: 0 !important; + max-width: none !important; + height: auto !important; + min-height: 0 !important; + max-height: none !important; + filter: alpha(opacity=0); + opacity: 0 +} + +.cropper-hidden { + display: none !important +} + +.cropper-move { + cursor: move +} + +.cropper-crop { + cursor: crosshair +} + +.cropper-disabled .cropper-canvas, +.cropper-disabled .cropper-face, +.cropper-disabled .cropper-line, +.cropper-disabled .cropper-point { + cursor: not-allowed +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/dtree.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/dtree.css new file mode 100644 index 0000000000000000000000000000000000000000..3e5364d4d5fa819bd748d4ce91476300482d68f7 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/dtree.css @@ -0,0 +1,112 @@ + +/**************** 主题换肤 ****************/ +/* 默认风格*/ +.dtree-theme-item-this{background-color: #d2d2d2!important;} +.dtree-theme-item:hover{background-color: #eaeceb!important;} +.dtree-theme-item cite{font-size:12px!important;} +.dtree-theme-item:hover cite{color:#fe7786!important;} + +.dtree-theme-dtreefont{font-size: 16px!important;} +.dtree-theme-ficon{color:#000!important;} +.dtree-theme-icon{color:orange!important;} +.dtree-theme-checkbox:hover{color:#fe7786!important;} +.dtree-theme-choose{color:#fe7786!important;} + +/* layui主题风格*/ +.dtree-layui-item-this{background: none!important;} +.dtree-layui-item:hover{background: none!important;} +.dtree-layui-item cite{font-size:14px!important;} +.dtree-layui-item:hover cite{opacity:0.5;filter:Alpha(opacity=50);text-decoration: underline;} + +.dtree-layui-dtreefont{font-size: 18px!important;} +.dtree-layui-ficon{font-size: 18px!important;color:#393D49!important;} +.dtree-layui-icon{color:#666!important;} +.dtree-layui-checkbox:hover{color:#5FB878!important;} +.dtree-layui-choose{color:#5FB878!important;} + +/* laySimple主题风格*/ +.dtree-laySimple-item-this{background-color: #d2d2d2!important;} +.dtree-laySimple-item:hover{background-color: #eaeceb!important;} +.dtree-laySimple-item cite{font-size:12px!important;} +.dtree-laySimple-item:hover cite{color:#01AAED!important;} + +.dtree-laySimple-dtreefont{font-size: 16px!important;} +.dtree-laySimple-ficon{font-size: 14px!important;color:#393D49!important;} +.dtree-laySimple-icon{color:#393D49!important;} +.dtree-laySimple-checkbox:hover{color:#01AAED!important;} +.dtree-laySimple-choose{color:#01AAED!important;} +/**************** 树基础 ****************/ +/* 菜单栏*/ +.dtree-menubar {padding-left: 10px;} +.dtree-menubar .layui-btn-group .layui-btn-sm{height: 20px;line-height: 20px;padding: 0 5px;font-size: 12px;} +.dtree-menubar .layui-btn-group .layui-btn-sm i{font-size: 12px!important;} + +/* 工具栏*/ +.dtree-toolbar{position: absolute;z-index: 940520;padding: 0;background-color: #eceaeb;} +.dtree-toolbar .layui-nav-child{position: static;} +.dtree-toolbar .layui-nav-child dd{cursor: pointer;} +.dtree-toolbar .layui-nav-child dd a i{font-size:16px;display: inline-block;margin: 0px 1px;color:#fe7786;} +.dtree-toolbar .layui-nav-child dd a i:hover{font-weight: bold;} +.dtree-toolbar .layui-nav-bar{display: none!important;} +.dtree-toolbar-tool{padding: 30px;} + +.dtree-toolbar-fixed{position: absolute;right: 5px;top: 2px;font-style: normal;transition: all .3s;-webkit-transition: all .3s;} +/*.dtree-toolbar-fixed a{border:1px solid #fe7786;}*/ +.dtree-toolbar-fixed a i{font-size:14px;display: inline-block;margin: 0px 1px;color:#fe7786;} +.dtree-toolbar-fixed a i:hover{opacity:0.8;filter:Alpha(opacity=80);} + +/* 树基本*/ +.dtree{width:260px;} +.dtree-nav-item{line-height:33px;padding-left:16px;} +.dtree-nav-ul-sid{display: none;} +.dtree-none-text{font-size: 12px;text-align: center;color: gray;} + +/* 树线*/ +.dtree-nav-first-line,.dtree-nav-line,.dtree-nav-last-line{position: relative;} +.dtree-nav-first-line:before{content:"";position: absolute;height: 0;border-left: 1px dotted #c0c4cc;} +.dtree-nav-first-line:after{content:"";position: absolute;height: 0;border-top: 1px dotted #c0c4cc;} + +.dtree-nav-line:before{content:"";position: absolute;top: 0;left: 7px;width: 0;height: 100%;border-left: 1px dotted #c0c4cc;} +.dtree-nav-line:after{content:"";position: absolute;top: 16px;left: 8px;width: 9px;height: 0;border-top: 1px dotted #c0c4cc;} + +.dtree-nav-last-line:before{content:"";position: absolute;top: 0;left: 7px;width: 0;height: 17px;border-left: 1px dotted #c0c4cc;} +.dtree-nav-last-line:after{content:"";position: absolute;top: 16px;left: 8px;width: 9px;height: 0;border-top: 1px dotted #c0c4cc;} + + +/* 图标及复选框*/ +.dtreefont{cursor: pointer;} +.dtreefont-special{margin: 0 4px;} +.dtree-nav-checkbox-div{display: inline-block;} +.dtree-nav-checkbox-div>i{display: inline-block;margin: 0px 1px;} +.dtree-nav-checkbox-div>i:last-child{margin-right: 4px;} +.dtree-nav-checkbox-div>i:hover{opacity:0.8;filter:Alpha(opacity=80);} + +/* 行 文字*/ +.dtree-nav-div{display:block;vertical-align:top;position:relative;} +.dtree-nav-div cite{font-style: normal;cursor: pointer;} +.dtree-nav-div:hover cite{opacity:0.7;filter:Alpha(opacity=70);transition: all .3s;-webkit-transition: all .3s;} + +/* 规则属性*/ +.dtree-nav-show {display: block!important;} +.dtree-nav-hide {display: none!important;} +.dtree-nav-this {} +.dtree-icon-hide {opacity:0;filter:Alpha(opacity=0);} +.dtree-icon-null-open,.dtree-icon-null-close,.dtree-icon-null{margin: 0 2px;} +.dtree-disabled{cursor: not-allowed; color:#c2c2c2!important;} +.dtree-disabled:hover{color:#c2c2c2!important;} +.dtree-nav-div cite.dtree-disabled{font-style: normal; cursor: not-allowed; color:#c2c2c2!important;} +.dtree-nav-div>cite.dtree-disabled:hover{color:#c2c2c2!important;} + + +/** 下拉树属性*/ +.dtree-select{position: absolute;max-height: 500px;height: 350px;overflow: auto;width: 99%;z-index: 123;display: none;border:1px solid silver;top: 42px;} +.dtree-select-show{display: block!important;} + +/* 简单适配*/ +@media screen and (max-width:1700px) and (min-width:1300px){ + .dtree-nav-item {padding-left: 15px;} +} + + + + diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/dtree.js b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/dtree.js new file mode 100644 index 0000000000000000000000000000000000000000..a05b22a8e3798284f8e2f84d4b715d04295a6095 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/dtree.js @@ -0,0 +1,4947 @@ +/** + *@Name dtree 树形组件 + *@Author 智慧的小西瓜 + *@DOCS http://www.wisdomelon.com/DTreeHelper/ + *@License https://www.layui.com/ + *@LASTTIME 2019/10/24 + *@VERSION v2.5.6 + */ +layui.define(['jquery','layer','form'], function(exports) { + var $ = layui.$, + layer = layui.layer, + form = layui.form; + + // 树的公共定义样式汇总 + var LI_NAV_CHILD = "dtree-nav-ul-sid", LI_NAV_ITEM = "dtree-nav-item", + LI_DIV_ITEM = "dtree-nav-div", DTREEFONTSPECIAL="dtreefont-special", NONETITLE="dtree-none-text", + LI_DIV_MENUBAR = "dtree-menubar", + LI_DIV_TOOLBAR = "dtree-toolbar", TOOLBAR_TOOL = "dtree-toolbar-tool", TOOLBAR_TOOL_EM = "dtree-toolbar-fixed", + LI_DIV_CHECKBAR = "dtree-nav-checkbox-div", + LI_CLICK_CHECKBAR = "d-click-checkbar", //绑定点击复选框时需要用到 + LI_DIV_TEXT_CLASS = "t-click", UL_ROOT="dtree", + LI_NAV_FIRST_LINE = "dtree-nav-first-line", LI_NAV_LINE = "dtree-nav-line", LI_NAV_LAST_LINE = "dtree-nav-last-line"; + + + // 树的公共指定 + var NAV_THIS = "dtree-nav-this", //当前节点 + NAV_SHOW = "dtree-nav-show", //显示子节点 + NAV_HIDE = "dtree-nav-hide", //隐藏节点 + NAV_DIS = "dtree-disabled", //禁用节点 + ICON_HIDE = "dtree-icon-hide", //隐藏图标 + $BODY = $("body"), //body选择器 + $WIN = $(window), //window窗口 + $DOC = $(document), //当前文档 + MOD_NAME = "dtree", //模块名称 + VERSION = "v2.5.6", //版本 + OPTIONS = {}, //全局属性配置 + DTrees = {}; //当前被实例化的树的集合 + + // 树的自定义图标 + var DTREEFONT = "dtreefont", //默认使用图标字体 + LI_DIV_CHECKBAR_ON = "dtree-icon-fuxuankuangxuanzhong", //复选框选中图标 + LI_DIV_CHECKBAR_OUT = "dtree-icon-fuxuankuang", //复选框未选中图标 + LI_DIV_CHECKBAR_NOALL = "dtree-icon-fuxuankuang-banxuan", //复选框半选图标 + LI_DIV_MENUBAR_DOWN = "dtree-icon-move-down", //menubar的展开全部的图标 + LI_DIV_MENUBAR_UP = "dtree-icon-move-up", //menubar的收缩全部的图标 + LI_DIV_MENUBAR_REFRESH = "dtree-icon-refresh", //menubar的刷新图标 + LI_DIV_MENUBAR_CHECKALL = "dtree-icon-roundcheckfill", //menubar的全选图标 + LI_DIV_MENUBAR_UNCHECKALL = "dtree-icon-roundclosefill", //menubar的全不选图标 + LI_DIV_MENUBAR_INVERTALL = "dtree-icon-roundcheck", //menubar的反选图标 + LI_DIV_MENUBAR_DELETE = "dtree-icon-delete1", //menubar的删除图标 + LI_DIV_MENUBAR_SEARCH = "dtree-icon-search_list_light", //menubar的搜索图标 + LI_DIV_TOOLBAR_PULLDOWN = "dtree-icon-pulldown", //toolbar的展开图标 + LI_DIV_TOOLBAR_PULLUP = "dtree-icon-pullup", //toolbar的收缩图标 + LI_DIV_TOOLBAR_ADD = "dtree-icon-roundadd", //toolbar的新增图标 + LI_DIV_TOOLBAR_EDIT = "dtree-icon-bianji", //toolbar的编辑图标 + LI_DIV_TOOLBAR_DEL = "dtree-icon-roundclose"; //toolbar的删除图标 + + // 树的非叶子节点图标集合 + var nodeIconArray = { + "-1": {"open": "dtree-icon-null-open", "close": "dtree-icon-null-close"}, //未指定 + "0" : {"open": "dtree-icon-wenjianjiazhankai", "close": "dtree-icon-weibiaoti5"}, //文件夹(二级图标默认样式) + "1" : {"open": "dtree-icon-jian", "close": "dtree-icon-jia"}, //+-图标(一级图标默认样式) + "2" : {"open": "dtree-icon-xiangxia1", "close": "dtree-icon-xiangyou"} //箭头图标 + }; + + // 树的叶子节点图标集合 + var leafIconArray = { + "-1": "dtree-icon-null", //未指定 + "0" : "dtree-icon-weibiaoti5", //文件夹 + "1" : "dtree-icon-yonghu", //人员 + "2" : "dtree-icon-fenzhijigou", //机构 + "3" : "dtree-icon-fenguangbaobiao", //报表 + "4" : "dtree-icon-xinxipilu", //信息 + "5" : "dtree-icon-shuye1", //叶子(二级图标默认样式) + "6" : "dtree-icon-caidan_xunzhang", //勋章 + "7" : "dtree-icon-normal-file", //文件 + "8" : "dtree-icon-dian", //小圆点(一级图标默认样式) + "9" : "dtree-icon-set-sm", //齿轮 + "10" : "dtree-icon-rate" //星星 + }; + + // 树的自定义样式 + var DTREE = "dtree-", //自定义样式前缀 + ITEMTHIS = "-item-this", //自定义样式当前行选中后缀 + ITEM = "-item", //自定义样式当前行后缀 + DFONT = "-dtreefont", //自定义样式图标样式后缀 + FICON = "-ficon", //自定义样式一级图标样式后缀 + ICON = "-icon", //自定义样式二级图标样式后缀 + CBOX = "-checkbox", //自定义样式复选框样式后缀 + CHS = "-choose"; //自定义样式复选框选中样式后缀 + + // 树自定义操作事件名称集合 绑定dtree-click的事件 + var eventName = { + checkNodeClick: "checkNodeClick", //点击复选框 + itemNodeClick: "itemNodeClick" //点击子节点div + }; + + // 树默认toolbar提供的功能集合 绑定dtree-tool的事件 + var defaultTool = { + pulldown: "pulldown", //点击展开当前节点下的全部节点 + pullup: "pullup", //点击收缩当前节点下的全部节点 + addTool: "addToolbar", //点击toolbar新增 + editTool: "editToolbar", //点击toolbar编辑 + delTool: "delToolbar" //点击toolbar删除 + }; + + // 树默认menubar提供的功能集合 绑定dtree-menu的事件 + var defaultMenu = { + moveDown: "moveDown", //menubar展开全部节点 + moveUp: "moveUp", //menubar收缩全部节点 + refresh: "refresh", //menubar刷新树 + checkAll: "checkAll", //menubar全选 + unCheckAll: "unCheckAll", //menubar全不选 + invertAll: "invertAll", //menubar反选 + remove: "remove", //menubar删除选中节点 + searchNode: "searchNode" //menubar查询节点 + }; + + // 树的公共事件 + var event = { + getElemId: function(options){ // 根据传入的参数获取ID + var elem = options.elem || ""; + var obj = options.obj || $(elem); + + if (obj.length == 0) { //页面中未找到绑定id + return ""; + } else { + return $(obj)[0].id; + } + }, + escape: function(html){ + if(typeof html !== 'string') return ''; + return html.replace(entityReg.escape, function(match){return entityMap.escape[match];}); + }, + unescape: function(str){ + if(typeof str !== 'string') return ''; + return str.replace(entityReg.unescape, function(match){return entityMap.unescape[match];}); + }, + cloneObj: function (obj, filter) { //深复制对象方法 + var newObj = {}; + if (obj instanceof Array) { + newObj = []; + } + var str = ""; + if(typeof filter !== 'undefined') {str = filter.join(",");} + for (var key in obj) { + if(str.indexOf(key) == -1){ + var val = obj[key]; + newObj[key] = typeof val === 'object' ? event.cloneObj(val, typeof filter !== undefined ? filter : []): val; + } + + } + return newObj; + }, + trimToDot: function(str){ + return str.replace(/ /g, "."); + } + }; + + // 特殊符号转义 + var keys = Object.keys || function(obj) { + obj = Object(obj); + var arr = []; + for(var a in obj) arr.push(a); + return arr; + }; + var invert = function(obj){ + obj = Object(obj); + var result = {}; + for(var a in obj) result[obj[a]] = a; + return result; + }; + var entityMap = { + escape: { + "&" : "&", + "<" : "<", + ">" : ">", + "'" : "&quo;" + } + }; + entityMap.unescape = invert(entityMap.escape); + var entityReg = { + escape: RegExp('[' + keys(entityMap.escape).join('') + ']', 'g'), + unescape: RegExp('(' + keys(entityMap.unescape).join('|') + ')', 'g') + }; + + //异步加载接口 + var AjaxHelper = { + request : function(config) { + var data = config.data ? config.data : {}; + var async = (typeof (config.async) === "boolean") ? config.async : true; + $.ajax({ + type : config.type ? config.type : "POST", + headers : config.headers, + url : config.url, + dataType : config.dataType ? config.dataType : "json", + data : data, + async : async, + contentType : config.contentType, + xhrFields: {withCredentials: config.withCredentials}, + success : config.success, + error : function(XMLHttpRequest, textStatus, errorThrown) { + if (typeof (config.error) === "function") { + config.error(XMLHttpRequest, textStatus, errorThrown); + } else { + layer.msg("异步加载失败: " + textStatus,{icon:5, shift:6}); + } + }, + statusCode : { + 404 : function() { + layer.msg('未找到指定请求,请检查访问路径!',{icon:5, shift:6}); + }, + 500 : function() { + layer.msg('系统错误!',{icon:5, shift:6}); + } + }, + complete : function(XMLHttpRequest, textStatus) { + if (typeof (config.complete) === "function") { + config.complete(XMLHttpRequest, textStatus); + } + } + }); + }, + serialize: function(param){ //json序列化 key=value&key1=value1 + var p = "?"; + for (var key in param) { + p += key + "=" + param[key] + "&"; + } + p = p.substring(0, p.length-1); + return p; + } + }; + + // 树类 + var DTree = function(options){ + var _this = this; + /** 默认赋值**/ + this.formatter = { // 数据过滤 + title: false // 文字,默认不开启 + }; + this.response = { // 树返回的json格式 + statusName: "code", //返回标识 + statusCode: 200, //返回码 + message: "message", //返回信息 + rootName: "data", //根节点名称 + treeId: "id", //节点ID + parentId: "parentId", //父节点ID + title: "title", //节点名称 + ficonClass: "ficonClass", //自定义一级图标 + iconClass: "iconClass", //自定义二级图标 + childName: "children", //子节点名称 + last: "last", //是否最后一级节点 +// level: "level", //层级 + spread: "spread", //展开 + disabled: "disabled", //禁用 + hide: "hide", //隐藏 + checkArr: "checkArr", //复选框列表 + checked: "checked", //是否选中 + type: "type", //复选框标记 + basicData: "basicData" //表示用户自定义需要存储在树节点中的数据 + }; + this.defaultRequest = { // 树的默认发起请求参数格式,最后会将value作为参数名称传递 + nodeId: "nodeId", //节点ID + parentId: "parentId", //父节点ID + context: "context", //节点内容 + leaf: "leaf", //是否叶子节点 + level: "level", //层级 + spread: "spread", //节点展开状态 + dataType: "dataType", //节点标记 + checked: "checked", //节点复选框选中状态 + initchecked: "initchecked", //节点复选框初始状态 + basicData: "basicData", //用户自定义的记录节点数据 + recordData: "recordData", //当前data数据(排除basicData和children字段) + }; + this.toolbarFun = { + addTreeNode: function(param, $div) { //添加树节点后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + editTreeNode: function(param, $div) { //编辑树节点后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + editTreeLoad: function(param){ // 编辑树的数据回显,用于打开编辑时,回填数据 + return ; + }, + delTreeNode: function(param, $div){ //删除树后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + loadToolbarBefore: function(buttons, param, $div){ // 右键菜单加载前的函数 + return buttons; + } + }; + this.toolbarStyle = { + title: "节点", + area: ["60%","80%"] + }; + this.menubarFun = { + remove: function(checkbarNodes){ //删除复选框选中节点,需要用户自定义,如未指定则树只是页面上做了修改 + return true; + } + }; + this.menubarTips = { + toolbar: [], + group: [defaultMenu.moveDown, defaultMenu.moveUp, defaultMenu.refresh, defaultMenu.checkAll, defaultMenu.unCheckAll, defaultMenu.invertAll, defaultMenu.remove, defaultMenu.searchNode], + freedom: [] + }; + this.checkbarFun = { + chooseBefore: function($i, node){ // 复选框点击前回调 + return true; + }, + chooseDone: function(checkbarNodesParam) { //复选框点击事件完毕后,返回该树关于复选框操作的全部信息,用于用户自定义,如未指定则树只是页面上做了修改 + return ; + } + }; + this.iframeDefaultRequest = { //iframe的默认参数,目的是与加载树的参数不一样 + nodeId: "nodeId", //节点ID + parentId: "parentId", //父节点ID + context: "context", //节点内容 + leaf: "leaf", //是否叶子节点 + level: "level", //层级 + spread: "spread", //节点展开状态 + dataType: "dataType", //节点标记 + checked: "checked", //节点复选框选中状态 + initchecked: "initchecked", //节点复选框初始状态 + basicData: "basicData", //用户自定义的记录节点数据 + recordData: "recordData", //当前data数据(排除basicData和children字段) + }; + + this.iframeFun = { + iframeDone: function(iframeParam){ //iframe加载完毕后,用于用户自定义事件 + return ; + } + }; + this.style = { //树最终使用的样式集合 + item: "", //每一项div的样式 + itemThis: "", //选中div的样式 + dfont: "", //一级图标的样式 + icon: "", //二级图标的样式 + cbox: "", //复选框的样式 + chs: "" //复选框选中的样式 + }; + this.usefontStyle = { //树最终使用的图标集合 + fnode:{ //一级节点 + node:{ //非叶子节点 + open:"", //节点展开 + close:"" //节点关闭 + }, + leaf:"" //叶子节点 + }, + snode:{ //二级节点 + node:{ //非叶子节点 + open:"", //节点展开 + close:"" //节点关闭 + }, + leaf:"" //叶子节点 + }, + checkbox:{ //复选框 + on:"", //复选框选中 + out:"", //未选中 + noall:"" //半选 + }, + menubar:{ //菜单栏 + movedown:"", //全部展开 + moveup:"", //全部收缩 + refresh:"", //刷新 + checkAll:"", //全选 + unCheckAll:"", //全不选 + invertAll:"", //反选 + remove:"", //删除 + search:"" //搜索 + }, + menubarExt:"", //扩展菜单栏 + toolbar:{ //工具栏 + menubar:{ //依附在菜单栏的工具栏 + movedown:"", //全部展开 + moveup:"", //全部收缩 + refresh:"", //刷新 + checkAll:"", //全选 + unCheckAll:"", //全不选 + invertAll:"", //反选 + remove:"", //删除 + search:"" //搜索 + }, + menubarExt:"", //依附在菜单栏的扩展菜单栏 + pulldown:"", //展开 + pullup:"", //收缩 + add:"", //添加 + edit:"", //编辑 + del:"" //删除 + }, + toolbarExt:"" //扩展工具栏 + } + + /** 数据绑定**/ + this.node = { // 树节点选中时,包含当前节点的全部信息 + nodeId: "", //节点ID + parentId: "", //父节点ID + context: "", //节点内容 + leaf: "", //是否叶子节点 + level: "", //层级 + spread: "", //节点展开状态 + dataType: "", //节点标记 + checked: "", //节点复选框选中状态 + initchecked: "", //节点复选框初始状态 + basicData: "", //用户自定义的记录节点数据 + recordData: "", //当前data数据(排除basicData和children字段) + }; + + this.toolbarMenu = {}; // 工具栏右键菜单绑定的所有元素 + this.checkbarNode = []; // 复选框标记的全部节点数据 + this.errData = []; // 记录在渲染节点时有问题的数据 + this.checkArrLen = 0; //添加节点的时判断复选框个数 + this.temp = []; // 临时变量 + this.bak = ""; // 临时变量 + this.setting(options); + }; + + /******************** 初始参数加载 ********************/ + // 设置基本参数值 + DTree.prototype.setting = function(options) { + this.options = options || {}; + + /** 绑定元素参数(必填,2个参数项必填一个)**/ + this.elem = this.options.elem || OPTIONS.elem || ""; //树绑定的元素ID:#elem + if(typeof this.options.obj === 'undefined'){ + if(this.elem) { + if($(this.elem).length > 0) { + this.obj = $(this.elem); + } + } + } else { + this.obj = this.options.obj || OPTIONS.obj || this.obj; //树绑定的jquery元素,用于当元素是延迟加载出来的话,可以用这个找到 + this.elem = "#" + this.obj[0].id; + } + + /** 基本参数**/ + this.scroll = this.options.scroll || OPTIONS.scroll || this.elem; //树的上级div容器,让树可以显示滚动条的div容器的ID + this.accordion = (typeof (this.options.accordion) === "boolean") ? this.options.accordion : (typeof (OPTIONS.accordion) === "boolean") ? OPTIONS.accordion : false; //手风琴加载, 默认false + if(this.accordion) { + this.initLevel = 1; //默认展开节点 1节 + } else { + this.initLevel = this.options.initLevel || OPTIONS.initLevel || 2; //默认展开节点 2节 + } + this.type = this.options.type || OPTIONS.type || "load"; //树的加载方式 all,全量树, load,增量树,默认load + this.cache = (typeof (this.options.cache) === "boolean") ? this.options.cache : (typeof (OPTIONS.cache) === "boolean") ? OPTIONS.cache : true; //数据缓存,默认true + this.record = this.options.record || OPTIONS.record || false; //开启数据记录模式,默认false + this.load = (typeof (this.options.load) === "boolean") ? this.options.load : (typeof (OPTIONS.load) === "boolean") ? OPTIONS.load : true; //开启加载动画,默认true + this.none = this.options.none || OPTIONS.nont || "无数据"; //初始加载无记录时显示文字 + this.tempHeight = this.options.height || OPTIONS.height; //临时转换高度变量 + if(this.tempHeight) { // 设置高度 + if(/^full-\d+$/.test(this.tempHeight)) { + this.fullHeightGap = this.tempHeight.split('-')[1]; + this.height = $WIN.height() - this.fullHeightGap; //设置高度 + } else { + this.fullHeightGap = this.tempHeight; + this.height = this.tempHeight; + } + } else { + this.fullHeightGap = ""; + this.height = ""; + } + this.width = this.options.width || OPTIONS.width || "260"; //宽度 + this.obj.css("width", this.width); + + /** 样式相关参数**/ + this.iconfont = this.options.iconfont || OPTIONS.iconfont || DTREEFONT; //默认图标字体 dtreefont + this.iconfontStyle = this.options.iconfontStyle || OPTIONS.iconfontStyle || {}; //用于自定义树的每个关键部位使用的图标 + this.nodeIconArray = $.extend(nodeIconArray, this.options.nodeIconArray || OPTIONS.nodeIconArray) || nodeIconArray; //用户自定义非叶子节点图标集合,node + this.leafIconArray = $.extend(leafIconArray, this.options.leafIconArray || OPTIONS.leafIconArray) || leafIconArray; //用户自定义叶子节点图标集合,leaf + this.skin = this.options.skin || OPTIONS.skin || "theme"; // 自定义样式 + if(this.skin == "layui"){ // layui主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : (typeof (OPTIONS.line) === "boolean") ? OPTIONS.line : true; //开启树线,默认开启 + this.ficon = this.options.ficon || OPTIONS.ficon || "7"; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'7' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; //一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "-1"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else if(this.skin == "laySimple"){ // laySimple主题 + this.line = this.options.line || OPTIONS.line || false; //开启树线,默认不开启 + this.ficon = this.options.ficon || OPTIONS.ficon || ["2","-1"]; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'-1' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "2") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'2' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "-1"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else { // 默认主题 或者自定义主题 + this.line = this.options.line || OPTIONS.line || false; //开启树线,默认不开启 + this.ficon = this.options.ficon || OPTIONS.ficon || "8"; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'8' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "5"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'5' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "0") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'0' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } + + /** 数据加载参数**/ + this.url = this.options.url || OPTIONS.url || ""; //请求地址 + this.async = (typeof (this.options.async) === "boolean") ? this.options.async : (typeof (OPTIONS.async) === "boolean") ? OPTIONS.async : true; //异步同步加载,默认异步加载 + this.headers = this.options.headers || OPTIONS.headers || {}; //ajax header属性 + this.method = this.options.method || OPTIONS.method || "post"; //请求类型 + this.dataType = this.options.dataType || OPTIONS.dataType || "json"; //参数类型 + this.contentType = this.options.contentType || OPTIONS.contentType || "application/x-www-form-urlencoded"; //发送信息至服务器时内容编码类型 + this.defaultRequest = $.extend(this.defaultRequest, this.options.defaultRequest || OPTIONS.defaultRequest) || this.defaultRequest; //默认请求参数 + this.filterRequest = this.options.filterRequest || OPTIONS.filterRequest || []; //过滤请求参数 + this.request = this.options.request || OPTIONS.request || {}; //用户自定义请求参数 + this.response = $.extend(this.response, this.options.response || OPTIONS.response) || this.response; //返回json格式 + this.data = this.options.data || OPTIONS.data || null; //初始化指定该参数,则不会访问异步接口 + this.dataFormat = this.options.dataFormat || OPTIONS.dataFormat || "levelRelationship"; //用于用户配置的data数据格式,list:列表, levelRelationship:层级关系,默认 + this.dataStyle = this.options.dataStyle || OPTIONS.dataStyle || "defaultStyle"; //用于用户配置layui通用的json数据风格,layuiStyle:layui风格,defaultStyle:默认风格 + this.errDataShow = this.options.errDataShow || OPTIONS.errDataShow || false; //是否在递归数据出现错误后,显示错误信息,默认false + this.withCredentials = this.options.withCredentials || OPTIONS.withCredentials || false; //是否允许跨域请求,默认false + this.success = this.options.success || OPTIONS.success || function(data, obj){}; //树加载完毕后执行解析树之前的回调 + this.done = this.options.done || OPTIONS.done || function(data, obj){}; //树加载完毕后的回调 + this.formatter = $.extend(this.formatter, this.options.formatter || OPTIONS.formatter) || this.formatter; //数据过滤 + this.error = this.options.error || OPTIONS.error || function(XMLHttpRequest, textStatus, errorThrown){}; // 异步加载异常回调 + this.complete = this.options.complete || OPTIONS.complete || function(XMLHttpRequest, textStatus){}; // 异步加载完成回调 + + /** 复选框参数**/ + this.checkbar = this.options.checkbar || OPTIONS.checkbar || false; //是否开启复选框模式 + this.checkbarLoad = this.options.checkbarLoad || OPTIONS.checkbarLoad || "node"; //复选框作用范围,node:所有节点, leaf:最后一级;默认所有节点 + this.checkbarType = this.options.checkbarType || OPTIONS.checkbarType || "all"; //复选框选中形式 all:子集选中父级也选中, no-all:子集选中父级半选中,子集全选父级选中,p-casc:父级选中子集全选,子集无法改变父级选中状态, self:没有任何级联关系,only:只能选中一个复选框。 默认all + this.checkbarData = this.options.checkbarData || OPTIONS.checkbarData || "choose"; //复选框记录数据类型形式, change表示记录变更数据,choose表示记录选中数据,all记录全部数据,halfChoose记录选中和半选中的数据,默认choose + this.checkbarFun = $.extend(this.checkbarFun, this.options.checkbarFun || OPTIONS.checkbarFun) || this.checkbarFun; //checkbar事件加载 + + /** 菜单栏参数**/ + this.menubar = this.options.menubar || OPTIONS.menubar || false; //是否打开菜单栏 + this.menubarTips = $.extend(this.menubarTips, this.options.menubarTips || OPTIONS.menubarTips) || this.menubarTips; //菜单栏吸附, toolbar:依附在工具栏,group:依附在按钮组,freedom,自由 + this.menubarFun = $.extend(this.menubarFun, this.options.menubarFun || OPTIONS.menubarFun) || this.menubarFun; //menubar事件加载 + + /** 工具栏参数**/ + this.toolbar = this.options.toolbar || OPTIONS.toolbar || false; //是否开启可编辑模式 + this.toolbarWay = this.options.toolbarWay || OPTIONS.toolbarWay || "contextmenu"; //工具栏显示方式,contextmenu:右键,follow:跟随节点,fixed:固定在节点右侧 + this.toolbarStyle = $.extend(this.toolbarStyle, this.options.toolbarStyle || OPTIONS.toolbarStyle) || this.toolbarStyle; //toolbar的自定义风格,标题,弹框大小 + this.toolbarLoad = this.options.toolbarLoad || OPTIONS.toolbarLoad || "node"; //toolbar作用范围:node:所有节点,noleaf:非最后一级节点,leaf:最后一级 + this.toolbarShow = this.options.toolbarShow || OPTIONS.toolbarShow || ["add","edit","delete"]; //toolbar三个按钮自定义加载 + this.toolbarBtn = this.options.toolbarBtn || OPTIONS.toolbarBtn || null; //toolbar增删改中内容的自定义加载 + this.toolbarExt = this.options.toolbarExt || OPTIONS.toolbarExt || []; //toolbar按钮扩展 + this.toolbarFun = $.extend(this.toolbarFun, this.options.toolbarFun || OPTIONS.toolbarFun) || this.toolbarFun; //toolbar事件加载 + + /** iframe模式参数**/ + this.useIframe = this.options.useIframe || OPTIONS.useIframe || false; //是否加载iframe 默认false, + this.iframeElem = this.options.iframeElem || OPTIONS.iframeElem || ""; //iframe的ID + this.iframeUrl = this.options.iframeUrl || OPTIONS.iframeUrl || ""; //树关联的iframe地址 + this.iframeLoad = this.options.iframeLoad || OPTIONS.iframeLoad || "leaf"; //点击哪一层加载frame: node:所有节点, leaf:默认,最后一级 + this.iframeDefaultRequest = $.extend(this.iframeDefaultRequest, this.options.iframeDefaultRequest || OPTIONS.iframeDefaultRequest) || this.iframeDefaultRequest; //iframe的默认传递参数 + this.iframeRequest = $.extend(this.iframeRequest, this.options.iframeRequest) || $.extend(this.iframeRequest, OPTIONS.iframeRequest) || this.iframeRequest; //iframe的自定义参数 + this.iframeFun = $.extend(this.iframeFun, this.options.iframeFun) || $.extend(this.iframeFun, OPTIONS.iframeFun) || this.iframeFun; //iframe事件加载 + + /** 下拉树模式参数**/ + this.select = this.options.select || false; + if(this.select) { + // 重置下拉树 + this.selectSetting(); + } + + /** 调用确认最终主题方法*/ + this.ensureTheme(); + }; + + // 设置基本参数值 + DTree.prototype.reloadSetting = function(options) { + this.options = $.extend(this.options, options) || this.options; + + /** 绑定元素参数**/ + this.elem = this.options.elem || this.elem; //树绑定的元素ID:#elem + if(typeof this.options.obj === 'undefined'){ + if(this.elem) { + if($(this.elem).length > 0) { + this.obj = $(this.elem); + } + } + } else { + this.obj = this.options.obj || this.obj; //树绑定的jquery元素,用于当元素是延迟加载出来的话,可以用这个找到 + this.elem = "#" + this.obj[0].id; + } + + /** 基本参数**/ + this.scroll = this.options.scroll || this.scroll; //树的上级div容器,让树可以显示滚动条的div容器 + this.accordion = (typeof (this.options.accordion) === "boolean") ? this.options.accordion : this.accordion; //开启手风琴加载 + if(this.accordion) { + this.initLevel = 1; //默认展开节点 1节 + } else { + this.initLevel = this.options.initLevel || this.initLevel; //默认展开节点 2节 + } + this.type = this.options.type || this.type; //树的加载方式 all,全量树, load,增量树,默认load + this.cache = (typeof (this.options.cache) === "boolean") ? this.options.cache : this.cache; //开启数据缓存 + this.record = (typeof (this.options.record) === "boolean") ? this.options.record : this.record; //开启数据记录模式 + this.load = (typeof (this.options.load) === "boolean") ? this.options.load : this.load; //开启加载动画 + this.none = this.options.none || this.none; //初始节点加载无数据时显示文字 + this.tempHeight = this.options.height || this.height; //临时转换高度变量 + if(this.tempHeight) { //设置高度 + if(/^full-\d+$/.test(this.tempHeight)) { + this.fullHeightGap = this.tempHeight.split('-')[1]; + this.height = $WIN.height() - this.fullHeightGap; + } else { + this.fullHeightGap = this.tempHeight; + this.height = this.tempHeight; + } + } + this.width = this.options.width || this.width; //宽度 + this.obj.css("width", this.width); + + /** 样式相关参数**/ + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : this.line; //开启树线,默认不开启 + this.iconfont = this.options.iconfont || this.iconfont; //默认图标字体 dtreefont + this.iconfontStyle = this.options.iconfontStyle || this.iconfontStyle; //用于自定义树的每个关键部位使用的图标 + this.nodeIconArray = $.extend(nodeIconArray, this.options.nodeIconArray) || this.nodeIconArray; //用户自定义非叶子节点图标集合,node + this.leafIconArray = $.extend(leafIconArray, this.options.leafIconArray) || this.leafIconArray; //用户自定义叶子节点图标集合,leaf + this.skin = this.options.skin || this.skin; //自定义样式 + if(this.skin == "layui"){ //layui主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : true; //开启树线,默认开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'7' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; //一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else if(this.skin == "laySimple"){ //laySimple主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : false; //开启树线,默认不开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'-1' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "2") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'2' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1];//一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else { // 默认主题 或者自定义主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : false; //开启树线,默认不开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'8' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'5' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "0") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'0' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } + + /** 数据加载参数**/ + this.url = this.options.url || this.url; //请求地址 + this.async = (typeof (this.options.async) === "boolean") ? this.options.async : this.async; //异步同步加载,默认异步加载 + this.headers = this.options.headers || this.headers; //ajax header属性 + this.method = this.options.method || this.method; //请求类型 + this.dataType = this.options.dataType || this.dataType; //参数类型 + this.contentType = this.options.contentType || this.contentType; //发送信息至服务器时内容编码类型 + this.defaultRequest = $.extend(this.defaultRequest, this.options.defaultRequest) || this.defaultRequest; //默认请求参数 + this.filterRequest = this.options.filterRequest || this.filterRequest; //过滤请求参数 + this.request = this.options.request || this.request; //用户自定义请求参数 + this.response = $.extend(this.response, this.options.response) || this.response; //返回json格式 + this.data = this.options.data || this.data; //初始化指定该参数,则不会访问异步接口 + this.dataFormat = this.options.dataFormat || this.dataFormat; //用于用户配置的data数据格式,list:列表, levelRelationship:层级关系,默认 + this.dataStyle = this.options.dataStyle || this.dataStyle; //用于用户配置layui通用的json数据风格,layuiStyle:layui风格,defaultStyle:默认风格 + this.errDataShow = (typeof (this.options.errDataShow) === "boolean") ? this.options.errDataShow : this.errDataShow; //是否在使用list模式递归数据出现错误时,显示错误信息 + this.withCredentials = (typeof (this.options.withCredentials) === "boolean") ? this.options.withCredentials : this.withCredentials; //是否允许跨域请求 + this.success = this.options.success || this.success; //树加载完毕后执行解析树之前的回调 + this.done = this.options.done || this.done; //树加载完毕后的回调 + this.formatter = $.extend(this.formatter, this.options.formatter)|| this.formatter; //数据过滤 + this.error = this.options.error || this.error; //异步加载异常回调 + this.complete = this.options.complete || this.complete; //异步加载完成回调 + + /** 复选框参数**/ + this.checkbar = this.options.checkbar || this.checkbar; //是否开启复选框模式 + this.checkbarLoad = this.options.checkbarLoad || this.checkbarLoad; //复选框作用范围,node:所有节点, leaf:最后一级;默认所有节点 + this.checkbarType = this.options.checkbarType || this.checkbarType; //复选框选中形式 all:子集选中父级也选中, no-all:子集选中父级半选中,子集全选父级选中,p-casc:父级选中子集全选,子集无法改变父级选中状态, self:没有任何级联关系,only:只能选中一个复选框。 默认all + this.checkbarData = this.options.checkbarData || this.checkbarData; //复选框记录数据类型形式, change表示记录变更数据,choose表示记录选中数据,all记录全部数据,halfChoose记录选中和半选中的数据,默认choose + this.checkbarFun = $.extend(this.checkbarFun, this.options.checkbarFun)|| this.checkbarFun; //checkbar事件加载 + + /** 菜单栏参数**/ + this.menubar = this.options.menubar || this.menubar; //是否打开菜单栏 + this.menubarTips = $.extend(this.menubarTips, this.options.menubarTips) || this.menubarTips; //菜单栏吸附, toolbar:依附在工具栏,group:依附在按钮组,freedom,自由 + this.menubarFun = $.extend(this.menubarFun, this.options.menubarFun) || this.menubarFun; //menubar事件加载 + + /** 工具栏参数**/ + this.toolbar = this.options.toolbar || this.toolbar; //是否开启工具栏 + this.toolbarWay = this.options.toolbarWay || this.toolbarWay; //工具栏显示方式,contextmenu:右键,follow:跟随节点,fixed:固定在节点右侧 + this.toolbarStyle = $.extend(this.toolbarStyle, this.options.toolbarStyle) || this.toolbarStyle; //toolbar的自定义风格,标题,弹框大小 + this.toolbarLoad = this.options.toolbarLoad || this.toolbarLoad; //toolbar作用范围:node:所有节点,noleaf:非最后一级节点,leaf:最后一级 + this.toolbarShow = this.options.toolbarShow || this.toolbarShow; //toolbar三个按钮 + this.toolbarBtn = this.options.toolbarBtn || this.toolbarBtn; //toolbar增删改中内容的自定义加载 + this.toolbarExt = this.options.toolbarExt || this.toolbarExt; //toolbar按钮扩展 + this.toolbarFun = $.extend(this.toolbarFun, this.options.toolbarFun) || this.toolbarFun; //toolbar事件加载 + + /** iframe模式参数**/ + this.useIframe = this.options.useIframe || this.useIframe;//是否加载iframe 默认false + this.iframeElem = this.options.iframeElem || this.iframeElem; //iframe的ID + this.iframeUrl = this.options.iframeUrl || this.iframeUrl; //树关联的iframe地址 + this.iframeLoad = this.options.iframeLoad || this.iframeLoad; //点击哪一层加载frame: node:所有节点, leaf:默认,最后一级 + this.iframeDefaultRequest = $.extend(this.iframeDefaultRequest, this.options.iframeDefaultRequest) || this.iframeDefaultRequest; //iframe的默认传递参数 + this.iframeRequest = $.extend(this.iframeRequest, this.options.iframeRequest) || this.iframeRequest; //iframe的自定义参数 + this.iframeFun = $.extend(this.iframeFun, this.options.iframeFun) || this.iframeFun; //iframe事件加载 + + /** 下拉树模式参数**/ + if(this.select) { + // 重置下拉树 + this.reloadSelectSetting(); + } + + /** 调用确认最终主题方法*/ + this.ensureTheme(); + + }; + + // 设置下拉树的基本参数值 + DTree.prototype.selectSetting = function() { + /** select模式参数*/ + this.select = true; //配置成select模式 + + this.selectInitVal = this.obj.attr("data-value") || this.options.selectInitVal || ""; //输入框的值 + this.selectTreeDiv = this.obj[0].id + "_tree_div"; // 上级DIV节点 + this.selectCardDiv = this.obj[0].id + "_select_card_div"; // 上级layui卡片节点 + this.selectDiv = this.obj[0].id + "_select_div"; // 模拟的select节点 + this.selectTipsName = this.obj[0].id + "_select_input"; // select的提示输入框名称 + this.selectTips = this.options.selectTips || "请选择"; // 输入框的提示语 + this.selectInputName = this.options.selectInputName || {nodeId: this.obj[0].id + "_select_nodeId"}; // select表单中的元素 + + // 调取下拉树的特殊处理页面元素标识 + this.renderSelectDom(); + } + + // 重新设置下拉树的基本参数值 + DTree.prototype.reloadSelectSetting = function() { + + this.selectInitVal = this.obj.attr("data-value") || this.options.selectInitVal || this.selectInitVal; //输入框的值 + this.selectTips = this.options.selectTips || this.selectTips; // 输入框的提示语 + this.selectInputName = $.extend(this.selectInputName, this.options.selectInputName) || this.selectInputName; // select表单中的元素 + + // 调取下拉树的特殊处理页面元素标识 + this.reloadSelectDom(); + } + + /******************** 下拉树设置区域 ********************/ + // 渲染下拉树的Dom结构 + DTree.prototype.renderSelectDom = function() { + var _this = this; + var rootId = _this.obj[0].id; + + // 设置自定义表单隐藏域 + var selectInputName = _this.selectInputName; + var selectInput = []; + for(var key in selectInputName) { + selectInput.push(''); + } + + // 设置html + var prevHtml = ['
                                                                  ', + '
                                                                  ', selectInput.join(""), + '', + '', + '
                                                                  '].join(''); + + _this.obj.before(prevHtml); + + _this.obj.wrap('
                                                                  ').wrap('
                                                                  ').wrap('
                                                                  '); + + } + + // 重新渲染下拉树的Dom结构 + DTree.prototype.reloadSelectDom = function() { + var _this = this; + var rootId = _this.obj[0].id; + + // 设置自定义表单隐藏域 + var selectInputName = _this.selectInputName; + var selectInput = []; + for(var key in selectInputName) { + selectInput.push(''); + } + + $("div[dtree-id='"+rootId+"'][dtree-select='"+_this.selectDiv+"']").find("div.layui-select-title").html(""); + + // 设置html + var prevHtml = [selectInput.join(""), + '', + ''].join(''); + + $("div[dtree-id='"+rootId+"'][dtree-select='"+_this.selectDiv+"']").find("div.layui-select-title").html(prevHtml); + + } + + // 设置输入框的值 + DTree.prototype.selectVal = function(param) { + var _this = this; + var rootId = _this.obj[0].id; + var selectInputName = _this.selectInputName; + var selectTipsNameValue = ""; + var selectValues = {}; + + // 如果开启了复选框,则此方法用来取值 + if(_this.checkbar) { + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "']").each(function(){ + var name = $(this).attr("name"); + var val = $(this).val(); + selectValues[name] = val; + }); + } else { + if(typeof param === 'undefined') { // 不传,则为当前树中记录的ID + param = _this.getNowParam(); + } + if(typeof param === 'string') { // 传递ID,则查询树节点ID对应的值 + param = _this.getParam(param); + } + + selectTipsNameValue = param["context"]; + for(var key in selectInputName) { + selectValues[selectInputName[key]] = param[key]; + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+selectInputName[key]+"']").val(param[key] || ""); + } + + if(param["nodeId"] && !param["context"]) { + selectTipsNameValue = _this.getParam(param["nodeId"]); + } + + // 返显提示输入框值 + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+_this.selectTipsName+"']").val(selectTipsNameValue || ""); + + } + + + // 返回隐藏域中的值 + return selectValues; + } + + // 设置复选框模式中的下拉树的值 + DTree.prototype.selectCheckboxVal = function() { + var _this = this; + var rootId = _this.obj[0].id; + var selectInputName = _this.selectInputName; + + // 获取全部复选框选中节点 + var param = _this.getCheckbarJsonArrParam(); + + selectTipsNameValue = param["context"]; + var selectValues = {}; + for(var key in selectInputName) { + var value = param[key].join(","); + selectValues[selectInputName[key]] = value; + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+selectInputName[key]+"']").val(value); + } + + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+_this.selectTipsName+"']").val(selectTipsNameValue); + + // 返回隐藏域中的值 + return selectValues; + } + + // 重置下拉树的值 + DTree.prototype.selectResetVal = function() { + var _this = this; + var rootId = _this.obj[0].id; + // 表单清空 + $("input[dtree-id='"+rootId+"']").val(""); + // 节点重置 + _this.cancelNavThis(); + if(_this.checkbar) { + // 复选框重置 + _this.cancelCheckedNode(); + } + } + + + /******************** 字体及图标区域 ********************/ + // 确认最终主题 + DTree.prototype.ensureTheme = function(){ + var _this = this; + + // 确认style + this.style.item = DTREE + this.skin + ITEM; + this.style.itemThis = DTREE + this.skin + ITEMTHIS; + this.style.dfont = DTREE + this.skin + DFONT; + this.style.ficon = DTREE + this.skin + FICON; + this.style.icon = DTREE + this.skin + ICON; + this.style.cbox = DTREE + this.skin + CBOX; + this.style.chs = DTREE + this.skin + CHS; + + // 确认usefontStyle + var iconfont = this.iconfont; + var iconfonts = []; + if(typeof iconfont === 'string') { + iconfonts.push(iconfont); + } else { + iconfonts = iconfont; + } + + var iconfontStyle = this.iconfontStyle; + var iconfontStyles = []; + if(iconfontStyle.length == undefined) { + iconfontStyles.push(iconfontStyle); + } else { + iconfontStyles = iconfontStyle; + } + + for(var i=0; i 0) { + $lis.each(function(){ + _this.showLineLi($(this)); + }); + } else { + _this.obj.find("li[data-id]").each(function(){ + _this.showLineLi($(this)); + }); + } + } + } + + // 真正显示树线的方法 + DTree.prototype.showLineLi = function($li){ + var _this = this; + var $div = $li.children("div"), + $nextLi = $li.next("li"), + $ul = $li.parent("ul"); + if($ul[0].id == _this.obj[0].id) { + // 根节点下的节点 + $li.removeClass(LI_NAV_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_FIRST_LINE); + } else { + // 非根节点下的节点 + var $pnextLi = $ul.parent("li").next("li"); + if($pnextLi.length == 0) { + if($nextLi.length == 0){ + $li.removeClass(LI_NAV_LINE); + $li.removeClass(LI_NAV_FIRST_LINE); + $li.addClass(LI_NAV_LAST_LINE); + } else { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_LINE); + } + }else { + var $pnextdiv = $pnextLi.children("div"); + if($nextLi.length == 0 && $div.children("cite").attr("data-leaf") == "leaf" && $pnextdiv.children("cite").attr("data-leaf") == "leaf") { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LINE); + $li.addClass(LI_NAV_LAST_LINE); + } else { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_LINE); + } + } + } + } + + /******************** 初始化数据区域 ********************/ + // 设置高度 + DTree.prototype.autoHeight = function(){ + var _this = this; + var height = _this.height; + if(height != "") { + if(_this.elem == _this.scroll){ + _this.obj.parent().css("height", height + "px"); + } else { + var $toolbarDiv = _this.obj.closest(_this.scroll); + $toolbarDiv.css("height", height + "px"); + } + } + }; + + // 重载树 + DTree.prototype.reload = function(options){ + var _this = this; + _this.reloadSetting(options); + _this.init(); + }; + + // 初始化树 + DTree.prototype.init = function(){ + var _this = this; + if (typeof _this !== "object") { + //_this.obj.html(_this.getNoneDom().errText("树组件未成功加载,请检查配置")); + layer.msg("树组件未成功加载,请检查配置", {icon:5}); + return ; + } + + // 设置组件高度 + _this.autoHeight(); + + if(_this.data) { + if(typeof _this.data.length === 'undefined'){ + //_this.obj.html(_this.getNoneDom().errText("数据解析异常,data数据格式不正确")); + layer.msg("数据解析异常,data数据格式不正确", {icon:5}); + return ; + } + + if(_this.data.length == 0) { + _this.obj.html(_this.getNoneDom().text()); + return ; + } + + //先将ul中的元素清空 + _this.obj.html(""); + + setTimeout(function () { + // 加载完毕后执行树解析前的回调 + _this.success(_this.data, _this.obj); + + // 第一次解析树 + if (_this.dataFormat == 'list'){ + //1.识别根节点ul中的data-id标签,判断顶级父节点 + var pid = _this.obj.attr("data-id"); + //2.构建一个存放节点的树组 + var rootListData = _this.queryListTreeByPid(pid, _this.data); + _this.loadListTree(rootListData, _this.data, 1); + } else { + _this.loadTree(_this.data, 1); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + // 设置复选框的初始值 + if(_this.select){ + _this.selectVal(_this.selectInitVal); + } + + // 保存树副本 + _this.bak = _this.obj.html(); + + // 加载完毕后的回调 + _this.done(_this.data, _this.obj); + }, 100); + } else { + if (!_this.url) { + //_this.obj.html(_this.getNoneDom().errText("数据请求异常,url参数未指定")); + layer.msg("数据请求异常,url参数未指定", {icon:5}); + return ; + } + + //先将ul中的元素清空 + _this.obj.html(""); + + var index = _this.load ? layer.load(1) : ""; + + AjaxHelper.request({ + async: _this.async, + headers: _this.headers, + type: _this.method, + url: _this.url, + dataType: _this.dataType, + contentType: _this.contentType, + withCredentials: _this.withCredentials, + data: _this.getFilterRequestParam(_this.getRequestParam()), + success: function(result) { + if (typeof result === 'string') { + result = $.parseJSON(result); + } + + // 加载完毕后执行树解析前的回调 + _this.success(result, _this.obj); + + var code = ""; + if (_this.dataStyle == 'layuiStyle'){ + code = result[_this.response.statusName]; + } else { + code = result.status[_this.response.statusName]; + } + + if (code == _this.response.statusCode) { + var d = result[_this.response.rootName]; + + if(typeof d.length === 'undefined'){ + _this.obj.html(_this.getNoneDom().errText("数据解析异常,url回调后的数据格式不正确")); + //layer.msg("数据解析异常,url回调后的数据格式不正确", {icon:5}); + return ; + } + + if(d.length == 0) { + _this.obj.html(_this.getNoneDom().text()); + return ; + } + + // 第一次解析树 + if (_this.dataFormat == 'list'){ + //1.识别根节点ul中的data-id标签,判断顶级父节点 + var pid = _this.obj.attr("data-id"); + //2.构建一个存放节点的树组 + var rootListData = _this.queryListTreeByPid(pid, d); + _this.loadListTree(rootListData, d, 1); + } else { + _this.loadTree(d, 1); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + // 设置复选框的初始值 + if(_this.select){ + _this.selectVal(_this.selectInitVal); + } + + // 保存树副本 + _this.bak = _this.obj.html(); + + // 加载完毕后的回调 + _this.done(result, _this.obj); + } else { + // 如果打印不出任何信息说明是在这里,用了错误的数据格式, 或返回码不正确 + if (_this.dataStyle == 'layuiStyle'){ + _this.obj.html(_this.getNoneDom().errText(result[_this.response.message])); + _this.error(null, code, result[_this.response.message]); + //layer.msg(result[_this.response.message], {icon:2}); + } else { + _this.obj.html(_this.getNoneDom().errText(result.status[_this.response.message])); + _this.error(null, code, result.status[_this.response.message]); + //layer.msg(result.status[_this.response.message], {icon:2}); + } + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown){// 异步加载异常回调 + _this.obj.html(_this.getNoneDom().errText(textStatus + ": " + errorThrown)); + _this.error(XMLHttpRequest, textStatus, errorThrown); + }, + complete: function(XMLHttpRequest, textStatus){// 异步加载完成回调 + if(_this.load){layer.close(index);} + _this.complete(XMLHttpRequest, textStatus); + } + }); + } + }; + + // 加载子节点 + DTree.prototype.getChild = function($div, data) { + var _this = this, $ul = $div.next("ul"); + + _this.setNodeParam($div); + + if(typeof data !== 'undefined') { + if(typeof data.length === 'undefined'){ + //_this.obj.html(_this.getNoneDom().errText("数据解析异常,data数据格式不正确")); + layer.msg("数据解析异常,data数据格式不正确", {icon:5}); + return ; + } + + //先将ul中的元素清空 + $ul.html(""); + + // 解析树 + if (_this.dataFormat == 'list'){ + var pid = _this.node.nodeId; + var level = parseInt(_this.node.level)+1; + + var listData = _this.queryListTreeByPid(pid, data); + _this.loadListTree(listData, _this.data, level); + } else { + _this.loadTree(data, level); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + // 保存树副本 + _this.bak = _this.obj.html(); + + } else { + if (!_this.url) { + //_this.obj.html(_this.getNoneDom().errText("数据请求异常,url参数未指定")); + layer.msg("数据请求异常,url参数未指定", {icon:5}); + return ; + } + + $ul.html(""); + var index = _this.load ? layer.load(1) : ""; + AjaxHelper.request({ + async: _this.async, + headers: _this.headers, + type: _this.method, + url: _this.url, + dataType: _this.dataType, + withCredentials: _this.withCredentials, + data: _this.getFilterRequestParam(_this.getRequestParam()), + success: function(result) { + if (typeof result === 'string') { + result = $.parseJSON(result); + } + var code = ""; + if (_this.dataStyle == 'layuiStyle'){ + code = result[_this.response.statusName]; + } else { + code = result.status[_this.response.statusName]; + } + + if (code == _this.response.statusCode) { + // 解析树 + var pid = _this.node.nodeId; + var level = parseInt(_this.node.level)+1; + if (_this.dataFormat == 'list'){ + var pListData = _this.queryListTreeByPid(pid, result[_this.response.rootName]); + _this.loadListTree(pListData, result[_this.response.rootName], level, $ul); + } else { + _this.loadTree(result[_this.response.rootName], level, $ul); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + $ul.addClass(NAV_SHOW); + + // 保存树副本 + _this.bak = _this.obj.html(); + } else { + if (_this.dataStyle == 'layuiStyle'){ + _this.obj.html(_this.getNoneDom().errText(result[_this.response.message])); + _this.error(null, code, result[_this.response.message]); + //layer.msg(result[_this.response.message], {icon:2}); + } else { + _this.obj.html(_this.getNoneDom().errText(result.status[_this.response.message])); + _this.error(null, code, result.status[_this.response.message]); + //layer.msg(result.status[_this.response.message], {icon:2}); + } + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown){// 异步加载异常回调 + _this.obj.html(_this.getNoneDom().errText(textStatus + ": " + errorThrown)); + _this.error(XMLHttpRequest, textStatus, errorThrown); + }, + complete: function(XMLHttpRequest, textStatus){// 异步加载完成回调 + if(_this.load){layer.close(index);} + _this.complete(XMLHttpRequest, textStatus); + } + }); + } + }; + + // 初始化树或者拼接树 + DTree.prototype.loadListTree = function(pListData, listData, level, $ul){ + var _this = this; + $ul = $ul || _this.getNodeDom().nowOrRootUl(); //当前选中的节点或根节点 + if (pListData.length > 0){ + for (var i = 0; i < pListData.length; i++) { + // 1.获取已知节点的全部数据 + var data = pListData[i]; + if(typeof data !== "object") continue; + var parseData = _this.parseData(data); + var childListData = _this.queryListTreeByPid(parseData.treeId(), listData); // 根据已知数据的id判断该条数据是否还有子数据 + + // 3. 页面元素加载数据 + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(childListData.length), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(level), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), ($ul.hasClass(UL_ROOT) ? "root" : "item"))); + // 4.有子数据的元素加载子节点 + if(childListData.length > 0){ + var cLevel = parseInt(level)+1; + _this.loadListTree(childListData, listData, cLevel, _this.obj.find("ul[data-id='"+parseData.treeId()+"']")); + } + } + } + }; + + // 根据父ID查找list数据中匹配的元素 + DTree.prototype.queryListTreeByPid = function(pid, listData){ + var _this = this; + var rootListData = []; + if (listData) { + for (var i = 0; i < listData.length; i++) { + var data = listData[i]; + if(typeof data !== "object") continue; + if(pid == "null" || pid == null){ + if(data[_this.response.parentId] == null) { rootListData.push(data); } + } else { + if (data[_this.response.parentId] == pid){ + if (data[_this.response.treeId] == pid){ + _this.errData.push(data); + } else { + rootListData.push(data); + } + } + } + } + } + return rootListData; + }; + + // 初始化树或者拼接树 + DTree.prototype.loadTree = function(root, level, $ul){ + var _this = this; + if (root) { + $ul = $ul || _this.getNodeDom().nowOrRootUl(); //当前选中的节点或根节点 + for (var i = 0; i < root.length; i++) { // 遍历跟节点或追加的跟节点 + var data = root[i]; + if(typeof data !== "object") continue; + if(data[_this.response.treeId] == data[_this.response.parentId]) { _this.errData.push(data); } + var parseData = _this.parseData(data); + var children = parseData.children(); + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(children.length), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(level), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), ($ul.hasClass(UL_ROOT) ? "root" : "item"))); + if (children.length != 0) { + var cLevel = parseInt(level)+1; + _this.loadTree(children, cLevel, _this.obj.find("ul[data-id='"+parseData.treeId()+"']")); + } + } + } + }; + + // 判断在数据加载时是否存在错误数据,并是否打印错误数据 + DTree.prototype.msgErrData = function() { + var _this = this; + if(_this.errData.length > 0 && _this.errDataShow) { + var title = ""; + for(var i=0; i<_this.errData.length; i++) { + var edata = _this.errData[i]; + title += "数据:【"+edata[_this.response.title]+"】中节点id和上级id值一致! \n"; + } + layer.msg(title, {icon:2,time:5000}); + } + // 显示之后,将错误数据制空 + _this.errData = []; + }; + + // 解析data数据 + DTree.prototype.parseData = function(data) { + var _this = this; + + return { + treeId: function(){ + return data[_this.response.treeId]; + }, + parentId: function(){ + return data[_this.response.parentId]; + }, + fmtTitle: function(){ + if(typeof _this.formatter.title === 'function'){ + var ftitle = _this.formatter.title(data); + var tt = data[_this.response.title]; + tt = (ftitle == "" || ftitle == undefined || ftitle == null) ? tt : ftitle; + return tt || ""; + } + return data[_this.response.title]; + }, + title: function(){ + return data[_this.response.title]; + }, + level: function(){ + return data[_this.response.level] || ""; + }, + ficonClass: function(){ + return data[_this.response.ficonClass] || ""; + }, + iconClass: function(){ + return data[_this.response.iconClass] || ""; + }, + last: function(len){ + return ((len == 0) ? + ((typeof (data[_this.response.last]) === "boolean") ? data[_this.response.last] : true) : + ((typeof (data[_this.response.last]) === "boolean") ? data[_this.response.last] : false)); + }, + spread: function(level){ + return ((level < _this.initLevel) ? + ((typeof (data[_this.response.spread]) === "boolean") ? data[_this.response.spread] : true) : + ((typeof (data[_this.response.spread]) === "boolean") ? data[_this.response.spread] : false)); + }, + disabled: function(){ + return (typeof (data[_this.response.disabled]) === "boolean") ? data[_this.response.disabled] : false; + }, + hide: function(){ + return (typeof (data[_this.response.hide]) === "boolean") ? data[_this.response.hide] : false; + }, + checkArr: function(){ + var checkArr = []; + var checkArrData = data[_this.response.checkArr]; + if(typeof checkArrData === 'string'){ + if(checkArrData.indexOf("{") > -1 && checkArrData.indexOf("}") > -1){ + checkArrData = JSON.parse(checkArrData); + } else { + checkArrData = {"type":"0","checked":checkArrData}; + } + } + if(typeof checkArrData === 'object'){ + if(typeof checkArrData.length === 'undefined'){ + checkArr.push(checkArrData); + } else { + checkArr = checkArrData; + } + } + + if(checkArr.length > 0 && checkArr.length > _this.checkArrLen){ + _this.checkArrLen = checkArr.length; // 获取复选框个数 + } + return checkArr; + + }, + children: function(){ + return data[_this.response.childName] || []; + }, + basicData: function(){ + return event.escape(JSON.stringify(data[_this.response.basicData])) || JSON.stringify({}); + }, + recordData: function(){ + var recordData = _this.record ? event.cloneObj(data, [_this.response.treeId, + _this.response.parentId, + _this.response.title, + _this.response.iconClass, + _this.response.childName, + _this.response.last, + _this.response.spread, + _this.response.disabled, + _this.response.hide, + _this.response.checkArr, + _this.response.checked, + _this.response.type, + _this.response.basicData]) : {}; + + return event.escape(JSON.stringify(recordData)); + }, + data: function(){ + return data; + } + } + + }; + + //当无节点数据时显示dom + DTree.prototype.getNoneDom = function(){ + var _this = this, + rootId = _this.obj[0].id, + noneTitle = _this.none; + + return { + text: function(){ + return "
                                                                  "+noneTitle+"
                                                                  "; + }, + errText: function(errInfo){ + return "
                                                                  "+errInfo+"
                                                                  "; + } + } + }; + + //新增节点的dom值 + DTree.prototype.getDom = function(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide) { + var _this = this, + rootId = _this.obj[0].id, + toolbar = _this.toolbar, + checkbar = _this.checkbar; + + return { + fnode: function() { // + - 图标 + // 获取图标的变量 + var fnodeIcon = _this.fnodeIcon, + fleafIcon = _this.fleafIcon; + + var fleafIconLeaf = _this.usefontStyle.fnode.leaf, + fnodeIconOpen = _this.usefontStyle.fnode.node.open, + fnodeIconClose = _this.usefontStyle.fnode.node.close; + + if(ficonClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + fleafIconLeaf = iconfont + " " + ficonClass; + fnodeIconOpen = iconfont + " " + ficonClass; + fnodeIconClose = iconfont + " " + ficonClass; + } else { + fleafIconLeaf = iconfont[0] + " " + ficonClass; + fnodeIconOpen = iconfont[0] + " " + ficonClass; + fnodeIconClose = iconfont[0] + " " + ficonClass; + } + } + + if(fnodeIcon != "-1" && fleafIcon != "-1"){ // 都加载 + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon != "-1" && fleafIcon == "-1"){ // 加载node 隐藏leaf + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon == "-1" && fleafIcon != "-1"){ // 隐藏node 加载leaf + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon == "-1" && fleafIcon == "-1"){ // 都隐藏 + return last ? "" : + (spread ? "" : ""); + } + }, + node: function() { // 二级图标样式 + // 获取图标的变量 + var nodeIcon = _this.nodeIcon, + leafIcon = _this.leafIcon; + + var sleafIconLeaf = _this.usefontStyle.snode.leaf, + snodeIconOpen = _this.usefontStyle.snode.node.open, + snodeIconClose = _this.usefontStyle.snode.node.close; + if(iconClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + sleafIconLeaf = iconfont + " " + iconClass; + snodeIconOpen = iconfont + " " + iconClass; + snodeIconClose = iconfont + " " + iconClass; + } else { + sleafIconLeaf = iconfont[0] + " " + iconClass; + snodeIconOpen = iconfont[0] + " " + iconClass; + snodeIconClose = iconfont[0] + " " + iconClass; + } + } + + if(nodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + return last ? "" : + (spread ? "" : ""); + } + }, + checkbox: function() { // 复选框 + var flag = false; + if(_this.checkbarLoad == "node"){if (checkbar) {flag = true;}} else {if (last) {if (checkbar) {flag = true;}}} + + if(flag){ + var result = "
                                                                  "; + if(checkArr && checkArr.length > 0){ + + for (var i = 0; i < checkArr.length; i++) { + var checkData = checkArr[i]; + var checked = checkData.checked; + var CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + if (checked == "2") { //半选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.noall + " " + _this.style.chs; + } else if (checked == "1") { //选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.on + " " + _this.style.chs; + } else { //未选择或者无值 + CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + } + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + result += ""; + } + } + result += "
                                                                  "; + return result; + } + + return ""; + }, + text: function() { // 文字显示 + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + return ""+fmtTitle+""; + }, + ul: function() { //子节点ul + return last ? "
                                                                    " : + (spread ? "
                                                                      " : "
                                                                        "); + } + }; + }; + + //替换节点的dom值,或指定值 + DTree.prototype.replaceDom = function($div, treeId, last, spread, disabled, hide) { + var _this = this, + rootId = _this.obj[0].id, + toolbar = _this.toolbar, + checkbar = _this.checkbar; + + return { + fnode: function(ficonClass) { // + - 图标 + var fnode = ""; + + // 获取图标的变量 + var fnodeIcon = _this.fnodeIcon, + fleafIcon = _this.fleafIcon; + + var fleafIconLeaf = _this.usefontStyle.fnode.leaf, + fnodeIconOpen = _this.usefontStyle.fnode.node.open, + fnodeIconClose = _this.usefontStyle.fnode.node.close; + + if(ficonClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + fleafIconLeaf = iconfont + " " + ficonClass; + fnodeIconOpen = iconfont + " " + ficonClass; + fnodeIconClose = iconfont + " " + ficonClass; + } else { + fleafIconLeaf = iconfont[0] + " " + ficonClass; + fnodeIconOpen = iconfont[0] + " " + ficonClass; + fnodeIconClose = iconfont[0] + " " + ficonClass; + } + } + + if(fnodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + fnode = last ? "" : + (spread ? "" : ""); + } + if(fnode != ""){_this.getNodeDom($div).fnode().replaceWith($(fnode));} + }, + node: function(iconClass) { // 二级图标样式 + var snode = ""; + + // 获取图标的变量 + var nodeIcon = _this.nodeIcon, + leafIcon = _this.leafIcon; + + var sleafIconLeaf = _this.usefontStyle.snode.leaf, + snodeIconOpen = _this.usefontStyle.snode.node.open, + snodeIconClose = _this.usefontStyle.snode.node.close; + if(iconClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + sleafIconLeaf = iconfont + " " + iconClass; + snodeIconOpen = iconfont + " " + iconClass; + snodeIconClose = iconfont + " " + iconClass; + } else { + sleafIconLeaf = iconfont[0] + " " + iconClass; + snodeIconOpen = iconfont[0] + " " + iconClass; + snodeIconClose = iconfont[0] + " " + iconClass; + } + } + + if(nodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + snode = last ? "" : + (spread ? "" : ""); + } + if(snode != ""){_this.getNodeDom($div).snode().replaceWith($(snode));} + }, + checkbox: function(checkArr) { // 复选框 + var flag = false; + if(_this.checkbarLoad == "node"){if (checkbar) {flag = true;}} else {if (last) {if (checkbar) {flag = true;}}} + + if(flag){ + var result = "
                                                                        "; + if(checkArr && checkArr.length > 0){ + + for (var i = 0; i < checkArr.length; i++) { + var checkData = checkArr[i]; + var checked = checkData.checked; + var CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + if (checked == "2") { //半选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.noall + " " + _this.style.chs; + } else if (checked == "1") { //选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.on + " " + _this.style.chs; + } else { //未选择或者无值 + CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + } + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + result += ""; + } + } + result += "
                                                                        "; + _this.getNodeDom($div).snode().next("div").replaceWith($(result)); + } + }, + text: function(title) { // 文字显示 + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + var cite = ""+title+"" + _this.getNodeDom($div).cite().replaceWith($(cite)); + }, + ul: function() { //子节点ul + var ul = last ? "
                                                                          " : + (spread ? "
                                                                            " : "
                                                                              "); + _this.getNodeDom($div).nextUl().replaceWith($(ul)); + }, + div: function(){ + $div.attr("data-id", treeId); + }, + basicData: function(basicData){ + basicData = (basicData == "{}") ? "" : basicData; + $div.attr("data-basic", basicData); + }, + recordData: function(recordData){ + recordData = (recordData == "{}") ? "" : recordData; + $div.attr("data-record", recordData); + }, + p_li: function(pId){ + var $li = $div.parent("li"); + $li.attr("data-id", treeId); + if(pId) { + $li.attr("data-pid", pId); + } + return $li; + } + }; + + }; + + // 获取拼接好的li + DTree.prototype.getLiItemDom = function(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide, basicData, recordData, flag) { + var _this = this, + rootId = _this.obj[0].id; + + var dom = _this.getDom(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide); + basicData = (basicData == "{}") ? "" : basicData; + recordData = (recordData == "{}") ? "" : recordData; + var div = "
                                                                              " + + div , + dom.fnode(), + dom.node(), + dom.checkbox(), + dom.text(), + "
                                                                              ", dom.ul(), ""].join(""); + + return li; + }; + + // 初始化节点,用于数据回显 + DTree.prototype.dataInit = function(chooseId){ + var _this = this; + var $div = _this.obj.find("div[data-id='"+chooseId+"']"); + _this.getNodeDom($div).parentLi().find("."+NAV_THIS).removeClass(NAV_THIS); + _this.getNodeDom($div).parentLi().find("."+_this.style.itemThis).removeClass(_this.style.itemThis); + $div.addClass(NAV_THIS); + $div.addClass(_this.style.itemThis); + _this.setNodeParam($div); + // 将该节点的父节点全部展开 + var $li_parents = $div.parents("."+LI_NAV_ITEM); + $li_parents.children("ul").addClass(NAV_SHOW); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.fnode.node.close)).addClass(_this.usefontStyle.fnode.node.open); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.fnode.node.close)).removeClass(_this.usefontStyle.fnode.node.close); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.snode.node.close)).addClass(_this.usefontStyle.snode.node.open); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.snode.node.close)).removeClass(_this.usefontStyle.snode.node.close); + return _this.getNowParam(); + }; + + // 基于备份的Html数据回滚 + DTree.prototype.rollbackHtml = function(chooseId){ + var _this = this; + if(_this.bak) { + _this.obj.html(_this.bak); + // 取消全部选中状态 + _this.cancelNavThis(); + if(_this.checkbar) { + _this.cancelCheckedNode(); + _this.chooseDataInit(chooseId); + } else { + _this.dataInit(chooseId); + } + + _this.bak = _this.obj.html(); + } + }; + + + /******************** 基础事件区域 ********************/ + // 数据格式化 + DTree.prototype.escape = function(html){ + return event.escape(html); + }; + + // 格式化数据转回正常数据 + DTree.prototype.unescape = function(str){ + return event.unescape(str); + }; + + // 取消选中div + DTree.prototype.cancelNavThis = function(){ + var _this = this; + _this.obj.find("div[data-id]").parent().find("."+NAV_THIS).removeClass(NAV_THIS); + _this.obj.find("div[data-id]").parent().find("."+_this.style.itemThis).removeClass(_this.style.itemThis); + } + + // 选中div + DTree.prototype.navThis = function(id){ + var _this = this; + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null) { + _this.cancelNavThis(); + $div.addClass(NAV_THIS); + $div.addClass(_this.style.itemThis); + } + } + + // 手风琴模式操作其他节点 + DTree.prototype.accordionUL = function($ul) { + var _this = this; + if(_this.accordion) { + $ul.closest("li[data-index]").siblings("li[data-index]").children("ul[data-id]").removeClass(NAV_SHOW); + var $divs = $ul.closest("li[data-index]").siblings("li[data-index]").children("ul[data-id]").prev("div"); + if($divs.length && $divs.length > 0) { + for (var i=0; i<$divs.length; i++) { + var $div = $($divs[i]); + var $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(); + if($i_spread.attr("data-spread") != 'last'){ + _this.operateIcon($i_spread, $i_node).close(); + } + } + } + + } + }; + + // 展开或隐藏节点 作用点: div + DTree.prototype.clickSpread = function($div) { + var _this = this; + var $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + $ul = $div.next("ul"); + + if ($ul.length > 0) { + if (spread == "close") { + if (_this.type=="load") { //增加加载 + if (_this.cache) { //开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + _this.accordionUL($ul); + } else { //加载节点 + _this.getChild($div); + _this.accordionUL($ul); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + _this.accordionUL($ul); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + _this.accordionUL($ul); + } + _this.operateIcon($i_spread, $i_node).open(); + } else if (spread == "open") { + $ul.removeClass(NAV_SHOW); + _this.operateIcon($i_spread, $i_node).close(); + } + } + }; + + // 设置节点为disabled + DTree.prototype.setDisabledNodes = function(disabledIds){ + var _this = this; + var disabledId = disabledIds.split(","); + for (var i=0; i 0) { + _this.getChild($div, data); + } else { + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var level = parseInt($div.parent("li").attr("data-index"))+1; + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(0), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), "item")); + + // 建造完毕后,选中该DIV + $thisDiv = $ul.find("div[data-id='"+parseData.treeId()+"']"); + _this.setNodeParam($thisDiv); + + _this.showLine($ul.find("li")); + } else { + layer.msg("添加失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } + } else { + _this.getChild($div); + } + } + + // 局部刷新树--编辑当前节点选中节点时 + DTree.prototype.partialRefreshEdit = function($div, data){ + var _this = this; + $ul = $div.next("ul"), + $p_li = $div.parent("li"); + + if(data) { + if(typeof data === 'object') { + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var replaceDom = _this.replaceDom($div, parseData.treeId(), parseData.last(0), parseData.spread(), parseData.disabled(), parseData.hide()); + replaceDom.div(); + replaceDom.node(parseData.iconClass()); + replaceDom.checkbox(parseData.checkArr()); + replaceDom.text(parseData.title()); + replaceDom.ul(); + replaceDom.basicData(parseData.basicData()); + replaceDom.recordData(parseData.recordData()); + + var parentId = parseData.parentId(); + var oldParentId = $p_li.attr("data-pid"); + if(parentId && parentId != oldParentId) { + // 变更了父节点 + $p_li = replaceDom.p_li(parentId); + + // 根据parentId找到下挂节点的ul + var $goto_div = _this.getNodeDom(parentId).div(), + $goto_ul = _this.getNodeDom(parentId).nextUl(); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($goto_ul.children("li").length == 0){ + var $icon_i = $goto_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).openWithLeaf(); + $goto_ul.addClass(NAV_SHOW); + } + $goto_ul.append($p_li); + } else { + replaceDom.p_li(); + } + _this.setNodeParam($div); + } else { + layer.msg("编辑失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } else { + _this.getNodeDom($div).cite().html(data); + } + } + } + + // 局部刷新树--当前节点选中被删除时 + DTree.prototype.partialRefreshDel = function($div){ + var _this = this; + $p_li = $div.parent("li"); + $p_ul = _this.getNodeDom($div).parentUl(); + $p_div = _this.getNodeDom($div).parentDiv(); + + $p_li.remove(); + _this.showLine($p_ul.find("li")); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($p_ul.children("li").length == 0){ + var $icon_i = $p_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).closeWithLeaf(); + } + _this.initNodeParam(); + } + + /******************** 复选框区域 ********************/ + // 初始化复选框的值 + DTree.prototype.chooseDataInit = function(chooseIds){ + var _this = this; + var chooseId = chooseIds.split(","); + for (var i=0; i."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + if (flag == 0) { + //把父级去掉选中 + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($item_i).noCheck(); + } + } + } else { + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + //把父级选中 + _this.checkStatus($item_i).check(); + } + } + }; + + //实现复选框点击, no-all 子集选中父级半选中,子集全选父级选中 + DTree.prototype.checkAllOrNoallOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag == 0) { + //把父级去掉选中 + _this.checkStatus($item_i).noCheck(); + } else { + //把父级半选 + _this.checkStatus($item_i).noallCheck(); + } + } + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag1 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var flag2 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag1 != flag2) { + // 父级复选框半选 + _this.checkStatus($item_i).noallCheck(); + } else { + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + }; + + //实现复选框点击,p-casc:父级选中子集全选,子集无法改变父级选中状态 + DTree.prototype.checkAllOrPcascOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + } + }; + + //实现复选框点击,self:各自选中互不影响 + DTree.prototype.checkOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + } + }; + + //实现复选框点击,only:只能选中1个复选框 + DTree.prototype.checkOnly = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + var checked = $i.attr("data-checked"); + // 将全部节点全部设为未选中状态 + var $all_i = _this.obj.find("i[data-checked]"); + _this.checkStatus($all_i).noCheck(); + + if (checked != "1") { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + } + }; + + //实现复选框点击 + DTree.prototype.changeCheck = function($i) { + var _this = this; + var temp = _this.temp; + if(typeof $i === 'undefined') { + $i = temp[0]; + } + // 复选框选中事件 + if (_this.checkbarType == "all") { + _this.checkAllOrNot($i); + } else if(_this.checkbarType == "no-all") { + _this.checkAllOrNoallOrNot($i); + } else if(_this.checkbarType == "p-casc") { + _this.checkAllOrPcascOrNot($i); + } else if(_this.checkbarType == "self") { + _this.checkOrNot($i); + } else if(_this.checkbarType == "only") { + _this.checkOnly($i); + } else { + _this.checkAllOrNot($i); + } + + if(_this.select) { + // 设置复选框模式中的下拉树的值 + _this.selectCheckboxVal(); + } + + // 获取复选框选中节点的内容 + var checkbarNodes = _this.setAndGetCheckbarNodesParam(true); + + // 用户自定义想做的事情 + _this.checkbarFun.chooseDone(checkbarNodes); + layui.event.call(this, MOD_NAME, "chooseDone("+$(_this.obj)[0].id+")", {"checkbarParams": checkbarNodes}); + _this.temp = []; + }; + + //复选框半选状态初始化设置 + DTree.prototype.initNoAllCheck = function(){ + var _this = this; + //1.获取所有选中节点 + var $is = _this.obj.find("i[data-checked='1']"); + if($is.length > 0){ + for ( var key = 0; key < $is.length; key++) { + var $i = $($is[key]), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag1 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var flag2 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag1 != flag2) { + // 父级复选框半选 + _this.checkStatus($item_i).noallCheck(); + } else { + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + } + }; + + //复选框选中状态初始化设置 + DTree.prototype.initAllCheck = function(){ + var _this = this; + //1.获取所有选中节点 + var $is = _this.obj.find("i[data-checked='1']"); + if($is.length > 0){ + for ( var key = 0; key < $is.length; key++) { + var $i = $($is[key]), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + }; + + // 设置复选框选中/未选中/半选 _this.checkStatus($i).check(); _this.checkStatus($i).noCheck(); _this.checkStatus($i).noallCheck(); + DTree.prototype.checkStatus = function($i) { + var _this = this; + return { + check: function(){ + $i.removeClass(_this.usefontStyle.checkbox.out); + $i.removeClass(_this.usefontStyle.checkbox.noall); + $i.addClass(_this.usefontStyle.checkbox.on); + $i.addClass(_this.style.chs); + $i.attr("data-checked","1"); + }, + noCheck: function(){ + $i.removeClass(_this.usefontStyle.checkbox.noall); + $i.removeClass(_this.usefontStyle.checkbox.on); + $i.removeClass(_this.style.chs); + $i.addClass(_this.usefontStyle.checkbox.out); + $i.attr("data-checked","0"); + }, + noallCheck: function(){ + $i.removeClass(_this.usefontStyle.checkbox.out); + $i.removeClass(_this.usefontStyle.checkbox.on); + $i.addClass(_this.usefontStyle.checkbox.noall); + $i.addClass(_this.style.chs); + $i.attr("data-checked","2"); + } + } + }; + + // 设置树的复选框操作值的全部参数,并获取 + DTree.prototype.setAndGetCheckbarNodesParam = function(requestParamFlag) { + var _this = this; + //操作前先清空 + _this.checkbarNode = []; + // 选择所有复选框节点 + if (_this.checkbarData == "change"){ //记录变更数据 + _this.obj.find("i[data-par][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if ($i.attr("data-checked") != $i.attr("data-initchecked")) { + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + } + }); + } else if (_this.checkbarData == "all"){ //记录全部数据 + _this.obj.find("i[data-par][data-checked][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } else if (_this.checkbarData == "choose"){ //记录选中数据 + _this.obj.find("i[data-par][data-checked='1'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } else if (_this.checkbarData == "halfChoose"){ //记录选中和半选数据 + _this.obj.find("i[data-par][data-checked='1'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + _this.obj.find("i[data-par][data-checked='2'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } + return _this.checkbarNode; + }; + + // 获取树的复选框操作值的全部参数 + DTree.prototype.getCheckbarNodesParam = function() { + var _this = this; + return _this.setAndGetCheckbarNodesParam(true); + }; + + // 获取树的一个复选框的参数 + DTree.prototype.getCheckbarNodeParam = function($div, $i){ + var _this = this; + var temp_node = {}; + temp_node.nodeId = $div.attr("data-id"); + temp_node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + temp_node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + temp_node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + temp_node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + temp_node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + temp_node.basicData = basicData; + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + temp_node.recordData = recordData; + + temp_node.dataType = $i.attr("data-type"); + temp_node.checked = $i.attr("data-checked"); + temp_node.initchecked = $i.attr("data-initchecked"); + return temp_node; + }; + + // 获取基于返回参数的树的复选框参数 + DTree.prototype.getCheckbarJsonArrParam = function(){ + var _this = this; + var checkbarJsonArr = { + nodeId: [], //节点ID + parentId: [], //父节点ID + context: [], //节点内容 + leaf: [], //是否叶子节点 + level: [], //层级 + spread: [], //节点展开状态 + dataType: [], //节点标记 + checked: [], //节点复选框选中状态 + initchecked: [], //节点复选框初始状态 + basicData: [], //用户自定义的记录节点数据 + recordData: [], //当前data数据(排除basicData和children字段) + }; + // 获取全部复选框选中节点 + var params = _this.setAndGetCheckbarNodesParam(false); + if(params && params.length > 0) { + for(var i=0; i 0) { _this.checkStatus($i).check(); } + } + + //取消全部复选框选中 + DTree.prototype.cancelCheckedNode = function(nodeId){ + var _this = this; + var $i = _this.obj.find("i[data-par][data-checked!='0']"); + if($i.length > 0) { _this.checkStatus($i).noCheck(); } + } + + //反选复选框 + DTree.prototype.invertCheckedNode = function(nodeId){ + var _this = this; + if(_this.obj.find("i[data-par]").length > 0) { + var b = false; + _this.obj.find("i[data-par]").each(function(){ + var $i = $(this); + if($i.attr("data-checked") == '2'){ + b = true; + }else if($i.attr("data-checked") == '0') { + _this.checkStatus($i).check(); + }else if($i.attr("data-checked") == '1') { + _this.checkStatus($i).noCheck(); + } + }); + + if(b) { + _this.initNoAllCheck(); + } else { + _this.initAllCheck(); + } + } + } + + //删除选中节点 + DTree.prototype.removeCheckedNode = function(nodeId){ + var _this = this; + var len = _this.obj.find("i[data-par][data-checked='1']").length; + if(len == 0){ + layer.msg("请至少选中一个节点",{icon:2}); + }else{ + //操作前先清空 + _this.checkbarNode = []; + // 选择所有复选框节点 + var i_node = {}; + _this.obj.find("i[data-par][data-checked='1']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + }); + + layer.confirm('确定要删除选中节点?', {icon: 3, title:'删除选中节点'}, function(index1){ + var flag = _this.menubarFun.remove(_this.checkbarNode); + if(flag){ + _this.obj.find("i[data-par][data-checked='1']").closest("."+LI_DIV_ITEM).next("ul").remove(); + _this.obj.find("i[data-par][data-checked='1']").closest("."+LI_DIV_ITEM).remove(); + _this.checkbarNode=[]; + } + + layer.close(index1); + }); + } + } + + /******************** 工具栏及菜单栏区域 ********************/ + // 初始化菜单栏和工具栏的div + DTree.prototype.initTreePlus = function(){ + var _this = this; + // 初始化菜单栏和工具栏的div + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).remove(); + _this.toolbarMenu = {}; + if(_this.menubar && _this.menubarTips.group && _this.menubarTips.group.length > 0) _this.obj.before("
                                                                              "); + if(_this.toolbar){ + if(_this.toolbarWay == "contextmenu") { + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).remove(); + _this.obj.before("
                                                                              "); + } + } + + }; + + // 开启工具栏和菜单栏 + DTree.prototype.openTreePlus = function(){ + var _this = this; + // 先对工具栏做处理,因为菜单栏可能会与工具栏产生关联。 + var ggMenu = []; + if(_this.toolbar) _this.getToolbarDom(); + + if(_this.menubar) { + var menubarTips = _this.menubarTips, + mtbar = menubarTips.toolbar, + group = menubarTips.group, + freedom = menubarTips.freedom; + if(mtbar && mtbar.length > 0){ + // 菜单栏吸附工具栏上 + for(var i=0; i 0){ + // 菜单栏吸附在上方的按钮组div中 + for(var i=0; i"; + break; + case defaultMenu.moveUp: + gg = ""; + break; + case defaultMenu.refresh: + gg = ""; + break; + case defaultMenu.checkAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.unCheckAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.invertAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.remove: + gg = (_this.checkbar) ? "" : ""; + break; + case defaultMenu.searchNode: + gg = ""; + break; + } + return gg; + }; + + // 获取扩展菜单栏 + DTree.prototype.getExtMenubarDom = function(menu){ + var _this = this; + return ""; + }; + + // 获取依附在工具栏的菜单栏 + DTree.prototype.getMenubarToolDom = function(menu){ + var _this = this; + var rootId = _this.obj[0].id; + switch (menu) { + case defaultMenu.moveDown: + _this.toolbarMenu[defaultMenu.moveDown] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.moveDown, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.movedown, "展开全部"); + break; + case defaultMenu.moveUp: + _this.toolbarMenu[defaultMenu.moveUp] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.moveUp, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.moveup, "收缩全部"); + break; + case defaultMenu.refresh: + _this.toolbarMenu[defaultMenu.refresh] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.refresh, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.refresh, "刷新"); + break; + case defaultMenu.checkAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.checkAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.checkAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.checkAll, "全选节点"); + break; + case defaultMenu.unCheckAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.unCheckAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.unCheckAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.unCheckAll, "全不选节点"); + break; + case defaultMenu.invertAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.invertAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.invertAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.invertAll, "反选节点"); + break; + case defaultMenu.remove: + if(_this.checkbar) + _this.toolbarMenu[defaultMenu.remove] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.remove, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.remove, "删除选中"); + break; + case defaultMenu.searchNode: + _this.toolbarMenu[defaultMenu.searchNode] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.searchNode, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.searchNode, "查询"); + break; + } + }; + + // 获取依附在工具栏的扩展菜单栏 + DTree.prototype.getExtMenubarToolDom = function(menu){ + var _this = this; + _this.toolbarMenu[menu.menubarId] = _this.setToolbarDom().setMenuToolbarOption(menu.menubarId, menu.title, _this.usefontStyle.toolbar.menubarExt+" "+menu.icon, ""); + }; + + // menubar内置方法 + DTree.prototype.menubarMethod = function(){ + var _this = this; + return { + openAllNode: function(obj){ // 展开所有节点 + var $ulNode = obj || _this.obj.children("li").children("ul"); + // 遍历所有ul子节点 + for (var i = 0; i < $ulNode.length; i++) { + // 获取当前节点的信息 + var $ul = $($ulNode[i]), + $div = $ul.prev("div"), + $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + if (leaf == "leaf") { continue; } // 说明是叶子了,则继续循环下一个 + + if (spread == "open") { + // 说明该节点已经展开了,则进行子节点循环 + } else { + if (_this.type=="load") { //是否全量加载 + if (_this.cache) { //是否开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + } else { //加载节点 + _this.getChild($div); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + } + _this.operateIcon($i_spread, $i_node).open(); + + } + var $childUl = $ul.children("li").children("ul"); + _this.menubarMethod().openAllNode($childUl); + } + }, + closeAllNode: function(){ //收缩所有节点 + _this.obj.find("."+LI_NAV_CHILD).each(function(){ + // 获取当前节点的信息 + var $ul = $(this), + $div = $ul.prev("div"), + $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + $ul.removeClass(NAV_SHOW); + _this.operateIcon($i_spread, $i_node).close(); + }); + }, + refreshTree: function(){// 刷新树 + _this.refreshTree(); + }, + checkAll: function(){ // 全选节点 + _this.checkAllNode(); + }, + unCheckAll: function(){ // 全不选节点 + _this.cancelCheckedNode(); + }, + invertAll: function(){ // 反选节点 + _this.invertCheckedNode(); + }, + remove: function(){// 删除选中节点 + _this.removeCheckedNode(); + }, + searchNode: function(){//模糊查询该值,展开该值节点 + layer.prompt({ + formType: 0, + value: "", + title: '查询节点' + }, function(value, index1, elem){ + if (value) { + var flag = _this.searchNode(value); + if (!flag) { + layer.msg("该名称节点不存在!", {icon:5}); + } + } else { + layer.msg("未指定查询节点名称", {icon:5}); + } + layer.close(index1); + }); + }, + extMethod: function(menuId, $div, flag){ + if(_this.menubar && _this.menubarTips.group && _this.menubarTips.group.length > 0 && flag == "group"){ + for(var i=0; i<_this.menubarTips.group.length; i++){ + var ext = _this.menubarTips.group[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + if(_this.menubar && _this.menubarTips.toolbar && _this.menubarTips.toolbar.length > 0 && flag == "toolbar"){ + for(var i=0; i<_this.menubarTips.toolbar.length; i++){ + var ext = _this.menubarTips.toolbar[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + if(_this.menubar && _this.menubarTips.freedom && _this.menubarTips.freedom.length > 0 && flag == "freedom"){ + for(var i=0; i<_this.menubarTips.freedom.length; i++){ + var ext = _this.menubarTips.freedom[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + } + }; + }; + + // menubar监听方法 + DTree.prototype.menubarListener = function(menuId, flag){ + var _this = this; + var $div = _this.getNodeDom().nowDiv(); + switch (menuId) { + case defaultMenu.moveDown: // 展开全部节点 + _this.menubarMethod().openAllNode(); + break; + case defaultMenu.moveUp: // 收缩全部节点 + _this.menubarMethod().closeAllNode(); + break; + case defaultMenu.refresh: + _this.menubarMethod().refreshTree(); // 刷新树 + break; + case defaultMenu.checkAll: + _this.menubarMethod().checkAll(); + break; + case defaultMenu.unCheckAll: + _this.menubarMethod().unCheckAll(); + break; + case defaultMenu.invertAll: + _this.menubarMethod().invertAll(); + break; + case defaultMenu.remove: + _this.menubarMethod().remove(); + break; + case defaultMenu.searchNode: + _this.menubarMethod().searchNode(); + break; + default: + _this.menubarMethod().extMethod(menuId, $div, flag); + break; + } + }; + + //模糊查询该值,展开该值节点 + DTree.prototype.searchNode = function(value){ + var _this = this; + var b = false; + var $lis = []; + _this.obj.find("cite[data-leaf]").each(function(){ + var $nthis = $(this); + var html = $nthis.html(); + if(html.indexOf(value) > -1){ + if($nthis.attr("data-leaf") == "leaf") { + // 叶子节点提供包含父节点的所有信息 + var title = ""; + $nthis.parents("li").each(function(){ + title = "-" + $(this).find("cite[data-leaf]").html() + title; + }); + title = title.substring(1, title.length); + $nthis.attr("title", title); + } + // 保存当前cite所在的li及父li中包含该值,则只保留父的 + var i = 0; + $nthis.parents("li").each(function(){ + var html2 = $(this).find("cite[data-leaf]").html(); + if(html2.indexOf(value) > -1){ + i++; + } + if(i >= 2){ + return true; + } + }); + if (i < 2){ + $lis.push($nthis.closest("li").prop("outerHTML")); + } + } + }); + if($lis.length > 0) { + b = true; + // 1.将树节点清空 + _this.obj.html(""); + // 2.遍历所有cite节点,展开当前cite节点 + for(var i=0; i<$lis.length; i++){ + _this.obj.append($lis[i]); + } + } + return b; + }; + + + /******************** 工具栏区域 ********************/ + // 获取工具栏 + DTree.prototype.getToolbarDom = function(){ + var _this = this; + var toolbarShow = _this.toolbarShow, + toolbarExt = _this.toolbarExt, + toolbarWay = _this.toolbarWay; + + if(toolbarShow.length > 0){ + for(var i=0; i 0){ + for(var i=0; i "+other +title+""; + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + return ""; + } + }, + setMenuToolbarOption: function(menubarId, title, classId, other){ + var rootId = _this.obj[0].id; + if(toolbarWay == "contextmenu") { + return "
                                                                               "+other +title+"
                                                                              "; + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + return ""; + } + }, + setToolbarPlace: function(toolbarMenu){ + if(toolbarWay == "contextmenu") { + if(toolbarMenu){ + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).find('div.layui-nav-item>dl.layui-nav-child').html(""); + for(var key in toolbarMenu){ + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).find('div.layui-nav-item>dl.layui-nav-child').append(toolbarMenu[key]); + } + } + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + _this.obj.find("cite[data-leaf][dtree-disabled='false']").each(function(){ + var $cite = $(this); + _this.dynamicToolbarDom($cite); + }); + } + } + } + }; + + // 在节点后动态绑定fixed和follow条件的工具栏 + DTree.prototype.dynamicToolbarDom = function($cite){ + var _this = this; + var toolbarWay = _this.toolbarWay; + if($cite.next("em."+TOOLBAR_TOOL_EM).length == 0) { + var $div = $cite.parent("div"); + var param = _this.getRequestParam(_this.getTempNodeParam($div)); + var toolbarMenus = _this.toolbarFun.loadToolbarBefore(event.cloneObj(_this.toolbarMenu), param, $div); + var hideCls = (toolbarWay == "follow") ? NAV_HIDE : ""; + var em = [""]; + if(toolbarMenus){ + for(var key in toolbarMenus){ + em.push(toolbarMenus[key]); + } + } + em.push(""); + $cite.after(em.join('')); + } + } + + // 隐藏toolbar + DTree.prototype.toolbarHide = function() { + var _this = this; + if(_this.toolbar && _this.toolbarWay == "contextmenu") { + var $toolBarDiv = _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id); + $toolBarDiv.find(".layui-nav-child").removeClass('layui-anim-fadein layui-show'); + } + } + + // toolbar内置方法 + DTree.prototype.toolbarMethod = function(){ + var _this = this; + return { + pulldown: function(obj){ // 展开当前点击节点的下面全部节点 + if(!obj) return; + var $ulNode = obj; + // 遍历所有ul子节点 + for (var i = 0; i < $ulNode.length; i++) { + // 获取当前节点的信息 + var $ul = $($ulNode[i]), + $div = $ul.prev("div"), + $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + if (leaf == "leaf") { continue; } // 说明是叶子了,则继续循环下一个 + + if (spread == "open") { + // 说明该节点已经展开了,则进行子节点循环 + } else { + if (_this.type=="load") { //是否全量加载 + if (_this.cache) { //是否开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + } else { //加载节点 + _this.getChild($div); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + } + _this.operateIcon($i_spread, $i_node).open(); + + } + var $childUl = $ul.children("li").children("ul"); + _this.toolbarMethod().pulldown($childUl); + } + }, + pullup: function($li){ // 收缩当前点击节点的下面全部节点 + $li.find("."+LI_NAV_CHILD).each(function(){ + // 获取当前节点的信息 + var $ul = $(this), + $div = $ul.prev("div"), + $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + $ul.removeClass(NAV_SHOW); + _this.operateIcon($i_spread, $i_node).close(); + }); + } + } + }; + + // toolbar监听方法 + DTree.prototype.toolbarListener = function(tool, $div) { + var _this = this; + var $cite = $div.children("cite[data-leaf]"), + $ul = $div.next("ul"), + $p_li = $div.parent("li[data-index]"), //当前选中节点的顶级li节点 + $p_ul = $p_li.parent("ul"), //当前选中节点的顶级li节点的父级ul + $p_div = $p_ul.prev("div"), //当前选中节点的顶级li节点的父级ul的前一个div + title = $cite.html(); + switch (tool) { + case defaultTool.pulldown: + _this.toolbarMethod().pulldown($ul); + break; + case defaultTool.pullup: + _this.toolbarMethod().pullup($p_li); + break; + case defaultTool.addTool: + var content = _this.loadToolBar(title, defaultTool.addTool); + + layer.open({ + title: "新增"+_this.toolbarStyle.title, + type: 1, + area: _this.toolbarStyle.area, + content: content, + success: function(layero, index){ + form.render(); + form.on("submit(dtree_addNode_form)",function(data){ + var data = data.field; + var parentId = $div.attr("data-id"), + id = $div.attr("data-id")+"_node_"+$ul[0].childNodes.length, + leaf = true, + checked = "0", + level = parseInt($p_li.attr("data-index"))+1; + + // 创建子节点的DOM,添加子节点 + var checkArr = []; + if (_this.checkArrLen > 0) { + for (var i = 0; i < _this.checkArrLen; i++) { + checkArr.push({"type":i,"checked":"0"}); + } + } + + $ul.append(_this.getLiItemDom(id, parentId, data.addNodeName, data.addNodeName, true, "", "", checkArr, level, false, false, false, "", "", "item")); + // 先将li节点隐藏 + $ul.find("li[data-id='"+id+"']").hide(); + // 重新赋值 + var $addDiv = $ul.find("div[data-id='"+id+"']"); + node = _this.getNodeParam($addDiv); + + //获取组装后的requestNode,组合参数 + var requestNode = _this.getRequestParam(node); + requestNode = $.extend(requestNode, data); + + _this.temp = [id, $ul, $div, level]; + // 用户自定义想做的事情 + _this.toolbarFun.addTreeNode(requestNode, $div); + + layer.close(index); + return false; + }); + } + }); + break; + case defaultTool.editTool: + var content = _this.loadToolBar(title, defaultTool.editTool); + + layer.open({ + title: "编辑"+_this.toolbarStyle.title, + type: 1, + area: _this.toolbarStyle.area, + content: content, + success: function(layero, index){ + _this.toolbarFun.editTreeLoad(_this.getRequestParam(_this.getNodeParam($div))); + form.render(); + form.on("submit(dtree_editNode_form)",function(data){ + var data = data.field; + $cite.html(data.editNodeName); + node = _this.getNodeParam($div); + var requestNode = _this.getRequestParam(node); + requestNode = $.extend(requestNode, data); + _this.temp = [$cite, $div, title, $p_div]; + _this.toolbarFun.editTreeNode(requestNode, $div); + + layer.close(index); + }); + } + }); + break; + case defaultTool.delTool: + layer.confirm('确定要删除该'+_this.toolbarStyle.title+'?', {icon: 3, title:'删除'+_this.toolbarStyle.title}, function(index){ + var node = _this.getNodeParam($div); + _this.temp = [$p_li, $p_div]; + _this.toolbarFun.delTreeNode(_this.getRequestParam(_this.getNodeParam($div)), $div); + + layer.close(index); + }); + break; + default: + if(_this.toolbarExt.length > 0){ + for(var i=0; i<_this.toolbarExt.length; i++){ + var ext = _this.toolbarExt[i]; + if (tool == ext.toolbarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div)), $div); + break; + } + } + } + break; + } + } + + + // 加载toolBar中的内容 + DTree.prototype.loadToolBar = function(title, name){ + var _this = this; + var toolbarShow = _this.toolbarShow; + var nodeBarContents = _this.toolbarBtn; + + var html = ""; + switch (name) { + case defaultTool.addTool: + var addNodeBarDef = [{"label": "当前选中", "name": "nodeTitle", "type": "text", "value": title, "defElem": "nowChoose", "readonly": true}, + {"label": "新增"+_this.toolbarStyle.title, "name": "addNodeName", "type": "text", "value": "", "defElem": "nowChange", "verify": "required"}, + {"type": "submit", "value": "确认添加", "defElem": "btn", "filter": "dtree_addNode_form"}]; + + //2. 用户自定义的节点内容 + var addNodeBar = ['
                                                                              ']; + + if(nodeBarContents != null && nodeBarContents.length > 0){ + if(nodeBarContents[0] != null && nodeBarContents[0] != undefined && nodeBarContents[0].length > 0){ + var addNodeBarContents = nodeBarContents[0]; + // 1. 检查是否包含了now、newly、btn这三个默认项,将其他元素依次排列,将特殊元素至于栈顶 + for(var i=0; i', '
                                                                              ']; + // 3.遍历生成按钮 + for(var j=0; j
                                                                              '); + addNodeBar.push(addBtn.join('')); + addNodeBar.push('
                                                                              '); + html = addNodeBar.join(''); + break; + + case defaultTool.editTool: + var editNodeBarDef = [{"label": "当前选中", "name": "nodeTitle", "type": "text", "value": title, "defElem": "nowChoose", "readonly": true}, + {"label": "编辑"+_this.toolbarStyle.title, "name": "editNodeName", "type": "text", "value": "", "defElem": "nowChange", "verify": "required"}, + {"type": "submit", "value": "确认编辑", "defElem": "btn", "filter": "dtree_editNode_form"}]; + + var editNodeBar = ['
                                                                              ']; + //2. 用户自定义的节点内容 + if(nodeBarContents != null && nodeBarContents.length > 0){ + + if(nodeBarContents[1] != null && nodeBarContents[1] != undefined && nodeBarContents[1].length > 0){ + var editNodeBarContents = nodeBarContents[1]; + // 1. 检查是否包含了now、newly、btn这三个默认项,将其他元素依次排列,将特殊元素至于栈顶 + for(var i=0; i', '
                                                                              ']; + // 3.遍历生成按钮 + for(var j=0; j
                                                                              '); + editNodeBar.push(editBtn.join('')); + editNodeBar.push('
                                                                              '); + html = editNodeBar.join(''); + break; + } + return html; + }; + + // 获取toolbar详细的标签信息 + DTree.prototype.loadToolBarDetail = function(nodeBarContents){ + var _this = this; + var readonly = (typeof (nodeBarContents.readonly) === "boolean") ? nodeBarContents.readonly : false; + var disabled = (typeof (nodeBarContents.disabled) === "boolean") ? nodeBarContents.disabled : false; + var id = nodeBarContents.id ? nodeBarContents.id : ""; + var name = nodeBarContents.name ? nodeBarContents.name : ""; + var val = nodeBarContents.value ? nodeBarContents.value : ""; + var verify = nodeBarContents.verify ? nodeBarContents.verify : ""; + var placeholder = nodeBarContents.placeholder ? nodeBarContents.placeholder : val; + return{ + text: function(){ + return ['
                                                                              ', + '', + '
                                                                              ', + '', + '
                                                                              ', + '
                                                                              '].join(''); + }, + textarea: function(){ + return ['
                                                                              ', + '', + '
                                                                              ', + '', + '
                                                                              ', + '
                                                                              '].join(''); + }, + hidden: function(){ + return [''].join(''); + }, + select: function(){ + var optionsData = (typeof nodeBarContents.optionsData === 'object') ? nodeBarContents.optionsData : nodeBarContents.optionsData(); + var options = ""; + for(var key in optionsData){ + if(val == optionsData[key]){ + options += ""; + } else { + options += ""; + } + } + return ['
                                                                              ', + '', + '
                                                                              ', + '', '
                                                                              ', '
                                                                              '].join(''); + }, + submit: function(){ + var filter = nodeBarContents.filter; + return [''].join(''); + }, + button: function(){ + return [''].join(''); + }, + reset: function(){ + return [''].join(''); + } + } + }; + + // 新增节点后改变节点内容 + DTree.prototype.changeTreeNodeAdd = function(returnID){ + var _this = this; + var temp = _this.temp; + var id = temp[0], $ul = temp[1], $div = temp[2], level = temp[3]; + var flag = false; + if(returnID){ + var $thisDiv = _this.obj.find("[data-id='"+id+"']"); + if(typeof returnID === "object"){ + // 如果是JSON格式数据,则将当前DIV删除,重新建造DIV + $thisDiv.remove(); + var parseData = _this.parseData(returnID); + + if(parseData.treeId()){ + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(0), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), "item")); + + // 建造完毕后,选中该DIV + $thisDiv = $ul.find("div[data-id='"+parseData.treeId()+"']"); + _this.setNodeParam($thisDiv) + } else { + layer.msg("添加失败,节点ID为undefined!",{icon:5}); + // 将li节点删除 + $ul.find("li[data-id='"+id+"']").remove(); + // 重新赋值 + _this.setNodeParam($div); + // 临时变量制空 + _this.temp = []; + return ; + } + }else if(returnID == 'refresh'){ + // 如果是设置为refresh参数,则向后台发送请求,获取新增节点下的真实参数,局部刷新树。 + flag = true; + } else if(typeof returnID === "string" || typeof returnID === 'number' || returnID == true){ + $thisDiv.attr("data-id", returnID); + // 将li节点展示 + $ul.find("li[data-id='"+returnID+"']").show(); + _this.setNodeParam($thisDiv) + } + + // 判断当前点击的节点是否是最后一级节点,如果是,则需要修改节点的样式 + var $icon_i = $div.find("i[data-spread]"); + if ($icon_i.eq(0).attr("data-spread") == "last") { + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).openWithLeaf(); + } else { //如果不是,也要修改节点样式 + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).open(); + } + $ul.addClass(NAV_SHOW); //展开UL + _this.accordionUL($ul); + if(flag) { + _this.getChild($div); + } else { + // _this.showLine(); + _this.showLine($ul.find("li")); + // 这种情况下需要在新增节点后对节点新增工具栏 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.dynamicToolbarDom($thisDiv.find("cite[data-leaf]")); + } + } + + } else { + // 将li节点删除 + $ul.find("li[data-id='"+id+"']").remove(); + // 重新赋值 + _this.setNodeParam($div); + } + + _this.temp = []; // 临时变量制空 + + }; + + // 编辑页打开后显示编辑页内容 + DTree.prototype.changeTreeNodeDone = function(param){ + var _this = this; + form.val('dtree_editNode_form', param); + form.render(); + }; + + // 修改节点后改变节点内容 + DTree.prototype.changeTreeNodeEdit = function(returnID){ + var _this = this; + var temp = _this.temp; + var $cite = temp[0], $div = temp[1], title = temp[2], $p_div = temp[3]; + var flag = false; + if(returnID){ + if(typeof returnID === "object"){ + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var replaceDom = _this.replaceDom($div, parseData.treeId(), parseData.last(0), parseData.spread(), parseData.disabled(), parseData.hide()); + replaceDom.node(parseData.iconClass()); + replaceDom.checkbox(parseData.checkArr()); + replaceDom.text(parseData.title()); + replaceDom.ul(); + replaceDom.basicData(parseData.basicData()); + replaceDom.recordData(parseData.recordData()); + _this.setNodeParam($div); + } else { + layer.msg("编辑失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } + } else { + $cite.html(title); + _this.getNodeParam($div); + } + + _this.temp = []; // 临时变量制空 + }; + + // 删除节点后改变节点内容 + DTree.prototype.changeTreeNodeDel = function(flag){ + var _this = this; + var temp = _this.temp; + var $p_li = temp[0], + $p_ul = $p_li.parent("ul"), + $p_div = temp[1]; + + if(flag){ + $p_li.remove(); + _this.showLine($p_ul.find("li")); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($p_ul.children("li").length == 0){ + var $icon_i = $p_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).closeWithLeaf(); + } + _this.initNodeParam(); + } + + _this.temp = []; // 临时变量制空 + }; + + /******************** iframe区域 ********************/ + // 加载iframe + DTree.prototype.loadIframe = function($div, iframeParam) { + var _this = this; + var $cite = _this.getNodeDom($div).cite(); + if (!_this.useIframe) { // 启用iframe + return false; + } + var iframeElem = _this.iframeElem, + iframeUrl = _this.iframeUrl, + iframeLoad = _this.iframeLoad; + + var flag = iframeLoad == "leaf" ? (($cite.attr("data-leaf") == "leaf") ? true : false) : true; + + if (flag) { + if ($(iframeElem).length > 0) { //iframe存在 + if (!iframeUrl) { + layer.msg("数据请求异常,iframeUrl参数未指定", {icon:5}); + return false; + } + var param = AjaxHelper.serialize(iframeParam); + if(iframeUrl.indexOf("?")> -1){ + param = "&"+param.substring(1, param.length); + } + var url = iframeUrl + param; + $(iframeElem).attr("src", url); + } else { + layer.msg("iframe绑定异常,请确认页面中是否有iframe页对应的容器", {icon:5}); + return false; + } + } + return flag; + }; + + // 获取传递出去的参数,根据iframe.iframeDefaultRequest、iframe.iframeRequest和node拼出发出请求的参数 + DTree.prototype.getIframeRequestParam = function(nodes){ + var _this = this; + var request = _this.iframeRequest, + defaultRequestNames = _this.iframeDefaultRequest, + node = nodes || _this.node, + requestParam = {}; + + // 先拼用户自定义的,在拼树生成的,这样的话用户可以自定义当树未生成时的节点的初始值 + for ( var key in request) { + requestParam[key] = request[key]; + } + for ( var key in defaultRequestNames) { + var paramName = defaultRequestNames[key]; + var paramValue = node[key]; + if(typeof paramValue === "boolean"){ + requestParam[paramName] = paramValue; + }else { + if(paramValue){ + requestParam[paramName] = paramValue; + } + } + } + + // 解决传递中文的乱码问题 + var reg = /[\u4E00-\u9FA5\uF900-\uFA2D]/; //正则匹配中文 + for(var key in requestParam){ + if(reg.test(requestParam[key])) { + var str = requestParam[key]; + requestParam[key] = encodeURI(encodeURI(str)); + } + } + + return requestParam; + }; + + /******************** 数据回调区域 ********************/ + // 根据具体的id获取基于当前id的div以及对应的其他dom元素 + DTree.prototype.getNodeDom = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + return { + div: function(){ // 获取当前div + return $div; + }, + fnode: function(){ // 获取一级图标元素 + return ($div == null) ? null : $div.find("i[data-spread]").eq(0); + }, + snode: function(){ // 获取二级图标元素 + return ($div == null) ? null : $div.find("i[data-spread]").eq(1); + }, + checkbox: function(){ // 获取复选框元素 + return ($div == null) ? null : $div.find("i[data-par]"); + }, + cite: function(){ // 获取cite元素 + return ($div == null) ? null : $div.find("cite[data-leaf]"); + }, + nextUl: function(){ // 获取相邻的ul元素 + return ($div == null) ? null : $div.next("ul"); + }, + parentLi: function(){ // 获取父级li元素 + return ($div == null) ? null : $div.parent("li"); + }, + parentUl: function(){ // 获取基于当前$div的上级$ul + return ($div == null) ? null : $div.parent("li").parent("ul"); + }, + parentDiv: function(){ // 获取基于当前$div的上级$div + return ($div == null) ? null : $div.parent("li").parent("ul").prev("div"); + }, + nowDiv: function(){ // 获取当前选中节点,没有则返回null + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS); + }, + nowOrRootDiv: function(){ // 获取当前选中节点,没有则返回根节点下的第一个div + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? _this.obj.children("li").eq(0).children("div").eq(0) : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS); + }, + nowOrRootUl: function(){ // 获取当前选中节点下一个UL 或根节点。为了将新节点放入ul下 + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? _this.obj : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).next("ul"); + } + } + }; + + // 获取当前选中节点下一个UL 或根节点。为了将新节点放入ul下 + DTree.prototype.getNowNodeUl = function() { + var _this = this; + return _this.getNodeDom().nowOrRootUl(); + }; + + // 获取当前选中节点 或第一个根节点。 + DTree.prototype.getNowNode = function() { + var _this = this; + return _this.getNodeDom().nowOrRootDiv(); + }; + + // 获取当前选中节点 无则返回null。 + DTree.prototype.getNowNodeOrNull = function() { + var _this = this; + return _this.getNodeDom().nowDiv(); + }; + + // 获取指定节点。 + DTree.prototype.getNode = function(id) { + var _this = this; + return _this.getNodeDom(id).div(); + }; + + // 设置当前选中节点的全部参数 + DTree.prototype.setNodeParam = function($div) { + var _this = this; + _this.node.nodeId = $div.attr("data-id"); + _this.node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + _this.node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + _this.node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + _this.node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + _this.node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + _this.node.basicData = basicData; + + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + _this.node.recordData = recordData; + + if (_this.getNodeDom($div).checkbox()) { + var dataTypes = "", checkeds = "", initcheckeds = ""; + _this.getNodeDom($div).checkbox().each(function(){ + dataTypes += $(this).attr("data-type") + ","; + checkeds += $(this).attr("data-checked") + ","; + initcheckeds += $(this).attr("data-initchecked") + ","; + }); + dataTypes = dataTypes.substring(0, dataTypes.length-1); + checkeds = checkeds.substring(0, checkeds.length-1); + initcheckeds = initcheckeds.substring(0, initcheckeds.length-1); + + _this.node.dataType = dataTypes; + _this.node.checked = checkeds; + _this.node.initchecked = initcheckeds; + } + }; + + // 获取当前选中节点的全部参数 + DTree.prototype.getNodeParam = function($div) { + var _this = this; + if ($div) { + _this.setNodeParam($div); + } else { + if(_this.obj.find("div[data-id]").parent().find("."+NAV_THIS).length == 0){ + _this.initNodeParam(); + } + } + return this.node; + }; + + // 获取一个临时的node参数 + DTree.prototype.getTempNodeParam = function($div) { + var _this = this; + var temp_node = {}; + temp_node.nodeId = $div.attr("data-id"); + temp_node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + temp_node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + temp_node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + temp_node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + temp_node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + temp_node.basicData = basicData; + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + temp_node.recordData = recordData; + + if (_this.getNodeDom($div).checkbox()) { + var dataTypes = "", checkeds = "", initcheckeds = ""; + _this.getNodeDom($div).checkbox().each(function(){ + dataTypes += $(this).attr("data-type") + ","; + checkeds += $(this).attr("data-checked") + ","; + initcheckeds += $(this).attr("data-initchecked") + ","; + }); + dataTypes = dataTypes.substring(0, dataTypes.length-1); + checkeds = checkeds.substring(0, checkeds.length-1); + initcheckeds = initcheckeds.substring(0, initcheckeds.length-1); + + temp_node.dataType = dataTypes; + temp_node.checked = checkeds; + temp_node.initchecked = initcheckeds; + } + return temp_node; + }; + + // 重置参数 + DTree.prototype.initNodeParam = function(){ + var _this = this; + _this.node.nodeId = ""; + _this.node.parentId = ""; + _this.node.context = ""; + _this.node.leaf = ""; + _this.node.level = ""; + _this.node.spread = ""; + _this.node.dataType = ""; + _this.node.checked = ""; + _this.node.initchecked = ""; + _this.node.basicData = ""; + _this.node.recordData = ""; + + if(_this.select) { + _this.selectResetVal(); + } + }; + + // 获取传递出去的参数,根据defaultRequest、request和node拼出发出请求的参数 + DTree.prototype.getRequestParam = function(nodes){ + var _this = this; + var request = _this.request, + defaultRequestNames = _this.defaultRequest, + node = nodes || _this.node, + requestParam = {}; + + // 先拼用户自定义的,在拼树生成的,这样的话用户可以自定义当树未生成时的节点的初始值 + for ( var key in request) { + requestParam[key] = request[key]; + } + for ( var key in defaultRequestNames) { + var paramName = defaultRequestNames[key]; + var paramValue = node[key]; + if(typeof paramValue === "boolean"){ + requestParam[paramName] = paramValue; + }else { + if(paramValue){ + requestParam[paramName] = paramValue; + } + } + + } + return requestParam; + }; + + // 获取filterParam过滤后的requestParam + DTree.prototype.getFilterRequestParam = function(requestParam){ + var _this = this; + var filterRequest = _this.filterRequest; + return event.cloneObj(requestParam, filterRequest); + }; + + // 获取当前选中值 + DTree.prototype.getNowParam = function(){ + var _this = this; + + return _this.getRequestParam(_this.getNodeParam()); + }; + + // 获取指定节点选中值 + DTree.prototype.getParam = function(id){ + var _this = this; + + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null){ return _this.callbackData().node(_this.getTempNodeParam($div)); } else { return {}; } + }; + + // 获取参数的上级节点 + DTree.prototype.getParentParam = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null){ return _this.callbackData().parentNode($div); } else { return {}; } + }; + + // 获取参数的全部上级节点 + DTree.prototype.getAllParentParam = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + var arr = []; + if($div != null){ + var level = _this.getTempNodeParam($div).level; + for(var i=1; i 0){ + $childDivs.each(function(){ + var $cDiv = $(this); + childNode.push(_this.getRequestParam(_this.getTempNodeParam($cDiv))); + }); + } + return childNode; + }, + parentNode: function($div){ // 获取上级节点值 + var pId = _this.getNodeDom($div).parentLi().attr("data-pid"); + var $pdiv = _this.obj.find("div[data-id='"+pId+"']"); + if($pdiv.length > 0) {return _this.getRequestParam(_this.getTempNodeParam($pdiv));} else {return {};} + + } + } + }; + + /******************** 事件回调区域 ********************/ + // 绑定浏览器事件 + DTree.prototype.bindBrowserEvent = function(){ + var _this = this; + var rootId = _this.obj[0].id; + + // 绑定文件夹展开/收缩的图标的点击事件,点击时给当前节点的div添加选中class + _this.obj.on("click", "i[data-spread]", function(event) { + event.stopPropagation(); + var $i = $(this), + $div = $i.parent("div"), + node = _this.getNodeParam($div); + + _this.toolbarHide(); + _this.navThis($div); + _this.clickSpread($div); // 展开或隐藏节点 + + // 树状态改变后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "changeTree("+$(_this.obj)[0].id+")", { + dom: _this.callbackData().dom($i), + param: _this.callbackData().node(node), + show: _this.callbackData().dom($i).attr("data-spread") == "open" ? true : false + }); + }); + + // 绑定所有子节点div的单击事件,点击时触发加载iframe或用户自定义想做的事情 + _this.obj.on("click", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event) { + event.stopPropagation(); + var $div = $(this), + $cite = $div.find("cite"), + node = _this.getNodeParam($div); + _this.toolbarHide(); + _this.navThis($div); + + if(_this.select) { + _this.selectVal(node.nodeId); + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").click(); + } + + if (_this.useIframe) { + var iframeParam = _this.getFilterRequestParam(_this.getIframeRequestParam(node)); + var flag = _this.loadIframe($div, iframeParam); // 加载iframe + if (flag) { + // iframe加载完毕后,用户自定义想做的事情 + _this.iframeFun.iframeDone(iframeParam); + + layui.event.call(this, MOD_NAME, "iframeDone("+$(_this.obj)[0].id+")", { + "iframeParam": iframeParam, + dom: _this.callbackData().dom($div) + }); + } + } else { + // 单击事件执行完毕后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "node("+$(_this.obj)[0].id+")", { + param: _this.callbackData().node(node), + childParams: _this.callbackData().childNode($div), + parentParam: _this.callbackData().parentNode($div), + dom: _this.callbackData().dom($div) + }); + } + }); + + // 绑定所有子节点div的双击事件,暴露on给用户自定义 + _this.obj.on("dblclick", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event) { + event.stopPropagation(); + var $div = $(this), + $cite = $div.find("cite"), + node = _this.getNodeParam($div); + _this.toolbarHide(); + _this.navThis($div); + + if(_this.select) { + _this.selectVal(node.nodeId); + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").click(); + } + + // 双击事件执行完毕后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "nodedblclick("+$(_this.obj)[0].id+")", { + param: _this.callbackData().node(node), + childParams: _this.callbackData().childNode($div), + parentParam: _this.callbackData().parentNode($div), + dom: _this.callbackData().dom($div) + }); + }); + + if(_this.checkbar) { + // 绑定cheboxbar的节点复选框 + _this.obj.on("click", "i[dtree-click='"+eventName.checkNodeClick+"'][dtree-disabled='false']", function(event) { + _this.toolbarHide(); + var $i = $(this), + $div = $i.closest("div[dtree-click='"+eventName.itemNodeClick+"']"), + node = _this.getNodeParam($div); + // 复选框选中前的回调 + var flag = _this.checkbarFun.chooseBefore($i, _this.getRequestParam(node)); + _this.temp = [$i]; + if(flag){_this.changeCheck();} + + event.stopPropagation(); + }); + } + + if(_this.menubar) { + // 绑定menubar的点击事件 + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).on("click", "button[d-menu]", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("d-menu"), "group"); + }); + + // 绑定menubar的点击事件 + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).on("click", "a[d-menu]", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("d-menu"), "toolbar"); + }); + + // 绑定menubar的点击按钮事件 + _this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").on("click", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("dtree-menu"), "freedom"); + }); + } + + if(_this.toolbar) { + if(_this.toolbarWay == "contextmenu") { + //绑定所有子节点div的右键点击事件,用于显示toolbar + _this.obj.on("contextmenu", "div[dtree-click='"+eventName.itemNodeClick+"'][d-contextmenu='true'][dtree-disabled='false']", function(e){ + var $div = $(this), + node = _this.getNodeParam($div); + + _this.toolbarHide(); + // toolbar加载前执行的方法,执行完毕之后创建按钮 + _this.setToolbarDom().setToolbarPlace(_this.toolbarFun.loadToolbarBefore(event.cloneObj(_this.toolbarMenu), _this.getRequestParam(node), $div)); + + var e = e || window.event, + mx = e.pageX - $div.offset().left +45 , + my = $div.offset().top - _this.obj.closest(_this.scroll).offset().top +15; + + _this.navThis($div); + var $toolBarDiv = _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id); + $toolBarDiv.find(".layui-nav-child").addClass('layui-anim-fadein layui-show'); + $toolBarDiv.css({'left':mx+'px','top':my+'px'}); + + e.stopPropagation(); + return false; + }); + + // 绑定装载树的上层出现滚动条的容器,让toolbar隐藏 + _this.obj.closest(_this.scroll).scroll(function() { + _this.toolbarHide(); + }); + + // 绑定toolbar的点击事件 + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $div = _this.getNodeDom().nowOrRootDiv(), + node = _this.getNodeParam($div); + _this.toolbarHide(); + var tool = $(this).attr("dtree-tool"); + _this.toolbarListener(tool, $div); + }); + } else if(_this.toolbarWay == "fixed") { + // 绑定toolbar的点击事件 + _this.obj.on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $a = $(this), + $cite = $a.parent("em."+TOOLBAR_TOOL_EM).prev("cite"), //当前选中节点的text + $div = $cite.parent("div"), + node = _this.getNodeParam($div); + var tool = $a.attr("dtree-tool"); + + _this.toolbarHide(); + _this.navThis($div); + _this.toolbarListener(tool, $div); + }); + } else if(_this.toolbarWay == "follow") { + //绑定所有子节点div的mouseover mouseout事件,用于显示或隐藏toolbar + _this.obj.on("mouseover mouseout", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event){ + var $div = $(this), + $toolBarEm = $div.children("em."+TOOLBAR_TOOL_EM); + if(event.type == "mouseover"){ + $toolBarEm.removeClass(NAV_HIDE); + event.stopPropagation(); + } else if(event.type == "mouseout"){ + $toolBarEm.addClass(NAV_HIDE); + event.stopPropagation(); + } + }); + + // 绑定toolbar的点击事件 + _this.obj.on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $a = $(this), + $cite = $a.parent("em."+TOOLBAR_TOOL_EM).prev("cite"), //当前选中节点的text + $div = $cite.parent("div"), + node = _this.getNodeParam($div); + var tool = $a.attr("dtree-tool"); + + _this.toolbarHide(); + _this.navThis($div); + _this.toolbarListener(tool, $div); + }); + } + } + + if(_this.select) { + // 绑定select的点击事件 + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").on("click", function(event){ + event.stopPropagation(); + $(this).toggleClass("layui-form-selected"); + $("div[dtree-id='" + rootId + "'][dtree-card='"+_this.selectCardDiv+"']").toggleClass("dtree-select-show layui-anim layui-anim-upbit"); + + // 下拉树面板开闭状态改变后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "changeSelect("+$(_this.obj)[0].id+")", { + show: $(this).hasClass("layui-form-selected"), + param: _this.selectVal() + }); + }); + + } + }; + + // 绑定body的单击,让本页面所有的toolbar隐藏 + $BODY.on("click", function(event){ + $("div."+LI_DIV_TOOLBAR).find(".layui-show").removeClass('layui-anim-fadein layui-show'); + // $("div[dtree-id][dtree-select]").removeClass("layui-form-selected"); + // $("div[dtree-id][dtree-card]").removeClass("dtree-select-show layui-anim layui-anim-upbit"); + + }); + + // 解绑浏览器事件 + DTree.prototype.unbindBrowserEvent = function(){ + var _this = this; + + // 本身事件解绑 + _this.obj.unbind(); + // 菜单栏解绑 + if(_this.menubar){ + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).unbind(); + if(_this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").length > 0){ + _this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").unbind(); + } + } + + // 工具栏解绑 + if(_this.toolbar){ + if(_this.toolbarWay == "contextmenu") { + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).unbind(); + if(_this.obj.closest(_this.scroll).length > 0){ + _this.obj.closest(_this.scroll).unbind(); + } + } + } + + // 下拉树解绑 + if(_this.select) { + // 解绑select的点击事件 + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-select='"+_this.selectDiv+"']").removeClass("layui-form-selected"); + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-card='"+_this.selectCardDiv+"']").removeClass("dtree-select-show layui-anim layui-anim-upbit"); + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-select='"+_this.selectDiv+"']").unbind(); + } + }; + + + /** 外部访问 **/ + var dtree = { + set: function(options){ //设置全局属性 + if(typeof options !== 'undefined') { + $.extend(OPTIONS, options); + } + }, + render: function(options){ // 初始化树 + var dTree = null; + var id = event.getElemId(options); + if(id == "") { + layer.msg("页面中未找到绑定id", {icon:5}); + } else { + dTree = DTrees[id]; + if(typeof dTree === 'object'){ + dTree.unbindBrowserEvent(); + } + // 创建树 + dTree = new DTree(options); + // 添加到树数组中去 + DTrees[id] = dTree; + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.init(); + dTree.bindBrowserEvent(); + } + + return dTree; + }, + renderSelect: function(options){ // 初始化下拉树 + var dTree = null; + var id = event.getElemId(options); + if(id == "") { + layer.msg("页面中未找到绑定id", {icon:5}); + } else { + dTree = DTrees[id]; + if(typeof dTree === 'object'){ + dTree.unbindBrowserEvent(); + } + // 创建下拉树 + dTree = new DTree(options); + dTree.selectSetting(); + // 添加到树数组中去 + DTrees[id] = dTree; + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.init(); + dTree.bindBrowserEvent(); + } + + return dTree; + }, + reload: function(dTree, options){ // 重新加载树 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + dTree.reloadSetting(options); + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.initNodeParam(); + dTree.init(); + dTree.unbindBrowserEvent(); + dTree.bindBrowserEvent(); + }, + on: function(events, callback) { // 绑定事件 + if(events.indexOf("'") > 0){ + events = events.replace(/'/g,""); + } + if(events.indexOf('"') > 0) { + events = events.replace(/"/g,""); + } + return layui.onevent.call(this, MOD_NAME, events, callback); + }, + click: function(dTree, id) { // 模拟单击事件 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + $("div[dtree-click='"+eventName.itemNodeClick+"'][dtree-id='"+dTree.obj[0].id+"'][data-id='"+id+"']").click(); + }, + getNowParam: function(dTree){ // 获取当前选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getNowParam(); // 获取当前选中值 + }, + getParam: function(dTree, id){ // 获取指定节点值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getParam(id); // 获取指定节点值 + }, + getParentParam: function(dTree, id){ // 获取参数的上级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getParentParam(id); + }, + getAllParentParam: function(dTree, id){ // 获取参数的全部上级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getAllParentParam(id); + }, + getChildParam: function(dTree, id){ // 获取参数的全部下级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getChildParam(id); + }, + getCheckbarNodesParam: function(dTree){ // 获取复选框选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return {}; + } + return dTree.getCheckbarNodesParam(); // 获取复选框选中值 + }, + dataInit: function(dTree, chooseId){ // 初始化选中树,针对数据反选 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + if(chooseId){ + return dTree.dataInit(chooseId); + } + }, + chooseDataInit: function(dTree, chooseIds){ // 初始化复选框选中,针对数据反选 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + if(chooseIds){ + return dTree.chooseDataInit(chooseIds); + } + }, + changeCheckbarNodes: function(dTree){ //判断复选框是否发生变更 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.changeCheckbarNodes(); + }, + initNoAllCheck: function(dTree) { //复选框半选状态初始化设置 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.initNoAllCheck(); + }, + initAllCheck: function(dTree){ // 复选框选中状态初始化设置 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.initAllCheck(); + }, + selectVal: function(dTree, param){ // select模式设置输入框选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.selectVal(param); // select模式设置输入框选中值 + }, + escape: function(html){ // 字符串格式化 + return event.escape(html); + }, + unescape: function(str){ // 字符串反格式化 + return event.unescape(str); + }, + version: function(){ //获取版本号 + return VERSION; + } + }; + + exports('dtree', dtree); +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.css new file mode 100644 index 0000000000000000000000000000000000000000..df7af65397abb2d2094f986fb08484d58186d2c2 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.css @@ -0,0 +1,229 @@ +@font-face { + font-family: 'dtreefont'; + src: url('dtreefont.eot?x3m8fp'); + src: url('dtreefont.eot?x3m8fp#iefix') format('embedded-opentype'), + url('dtreefont.ttf?x3m8fp') format('truetype'), + url('dtreefont.woff?x3m8fp') format('woff'), + url('dtreefont.svg?x3m8fp#dtreefont') format('svg'); + font-weight: normal; + font-style: normal; +} + +[class^="dtree-icon-"], [class*=" dtree-icon-"] { + /* use !important to prevent issues with browser extensions that change font */ + font-family: 'dtreefont' !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; +} + +.dtree-icon-xiangxia1:before { + content: "\e771"; +} +.dtree-icon-normal-file:before { + content: "\e60c"; +} +.dtree-icon-xiangyou:before { + content: "\e78f"; +} +.dtree-icon-ok-circle:before { + content: "\1005"; +} +.dtree-icon-close1:before { + content: "\1006"; +} +.dtree-icon-close-fill:before { + content: "\1007"; +} +.dtree-icon-jian1:before { + content: "\e600"; +} +.dtree-icon-jia1:before { + content: "\e601"; +} +.dtree-icon-bianji:before { + content: "\e602"; +} +.dtree-icon-yonghu:before { + content: "\e603"; +} +.dtree-icon-shijian:before { + content: "\e606"; +} +.dtree-icon-fuxuankuang-banxuan:before { + content: "\e607"; +} +.dtree-icon-star:before { + content: "\e608"; +} +.dtree-icon-wenjianjiazhankai:before { + content: "\e60e"; +} +.dtree-icon-xiangmuxiaoxi:before { + content: "\e60f"; +} +.dtree-icon-search2:before { + content: "\e615"; +} +.dtree-icon-weibiaoti5:before { + content: "\e618"; +} +.dtree-icon-layim-theme:before { + content: "\e61b"; +} +.dtree-icon-shuye1:before { + content: "\e61e"; +} +.dtree-icon-add-circle:before { + content: "\e61f"; +} +.dtree-icon-xinxipilu:before { + content: "\e620"; +} +.dtree-icon-set-sm:before { + content: "\e621"; +} +.dtree-icon-about:before { + content: "\e623"; +} +.dtree-icon-chart-screen:before { + content: "\e62a"; +} +.dtree-icon-delete1:before { + content: "\e640"; +} +.dtree-icon-share3:before { + content: "\e641"; +} +.dtree-icon-youjian:before { + content: "\e642"; +} +.dtree-icon-check:before { + content: "\e645"; +} +.dtree-icon-close:before { + content: "\e646"; +} +.dtree-icon-favorfill:before { + content: "\e64b"; +} +.dtree-icon-favor:before { + content: "\e64c"; +} +.dtree-icon-fuxuankuangxuanzhong:before { + content: "\e652"; +} +.dtree-icon-fenguangbaobiao:before { + content: "\e655"; +} +.dtree-icon-jian:before { + content: "\e656"; +} +.dtree-icon-jia:before { + content: "\e657"; +} +.dtree-icon-fenzhijigou:before { + content: "\e658"; +} +.dtree-icon-roundcheckfill:before { + content: "\e659"; +} +.dtree-icon-roundcheck:before { + content: "\e65a"; +} +.dtree-icon-roundclosefill:before { + content: "\e65b"; +} +.dtree-icon-roundclose:before { + content: "\e65c"; +} +.dtree-icon-roundrightfill:before { + content: "\e65d"; +} +.dtree-icon-roundright:before { + content: "\e65e"; +} +.dtree-icon-like:before { + content: "\e66c"; +} +.dtree-icon-samefill:before { + content: "\e671"; +} +.dtree-icon-same:before { + content: "\e672"; +} +.dtree-icon-evaluate:before { + content: "\e674"; +} +.dtree-icon-circle1:before { + content: "\e687"; +} +.dtree-icon-radio:before { + content: "\e688"; +} +.dtree-icon-caidan_xunzhang:before { + content: "\e68e"; +} +.dtree-icon-pulldown:before { + content: "\e6a0"; +} +.dtree-icon-pullup:before { + content: "\e6a1"; +} +.dtree-icon-refresh:before { + content: "\e6a4"; +} +.dtree-icon-qrcode1:before { + content: "\e6b0"; +} +.dtree-icon-profile1:before { + content: "\e6b7"; +} +.dtree-icon-home1:before { + content: "\e6b8"; +} +.dtree-icon-homefill:before { + content: "\e6bb"; +} +.dtree-icon-roundaddfill:before { + content: "\e6d8"; +} +.dtree-icon-roundadd:before { + content: "\e6d9"; +} +.dtree-icon-fuxuankuang:before { + content: "\e6f2"; +} +.dtree-icon-wefill:before { + content: "\e6f5"; +} +.dtree-icon-sort:before { + content: "\e701"; +} +.dtree-icon-repair:before { + content: "\e738"; +} +.dtree-icon-shujudaping:before { + content: "\e742"; +} +.dtree-icon-dian:before { + content: "\e7a5"; +} +.dtree-icon-search_list_light:before { + content: "\e807"; +} +.dtree-icon-round_list_light:before { + content: "\e82b"; +} +.dtree-icon-star-fill:before { + content: "\e832"; +} +.dtree-icon-rate:before { + content: "\e833"; +} +.dtree-icon-move-up:before { + content: "\ea47"; +} +.dtree-icon-move-down:before { + content: "\ea48"; +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.eot b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.eot new file mode 100644 index 0000000000000000000000000000000000000000..68bf5f2f2dd33daa67373cca102f8ad764d84c22 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.eot differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.svg b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.svg new file mode 100644 index 0000000000000000000000000000000000000000..90fe50f041be2e0433b009a20993ec78c8e4e67f --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.svg @@ -0,0 +1,80 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.ttf b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..78bacd13a0a16b55e6b3be536b35e34e147a396a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.ttf differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.woff b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.woff new file mode 100644 index 0000000000000000000000000000000000000000..2b546450765b8d1368d1858ecc2c353d5529bfa5 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/dtreefont.woff differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/icons.json b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/icons.json new file mode 100644 index 0000000000000000000000000000000000000000..fca4788566c21d9bcfc9e3bf0c4406d17651a211 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/dtree/font/icons.json @@ -0,0 +1,283 @@ +{ + "data": [{ + "cls": "dtree-icon-xiangxia1", + "uncode": "e771" + }, + { + "cls": "dtree-icon-xiangyou", + "uncode": "e78f" + }, + { + "cls": "dtree-icon-jian", + "uncode": "e656" + }, + { + "cls": "dtree-icon-jia", + "uncode": "e657" + }, + { + "cls": "dtree-icon-weibiaoti5", + "uncode": "e618" + }, + { + "cls": "dtree-icon-wenjianjiazhankai", + "uncode": "e60e" + }, + { + "cls": "dtree-icon-dian", + "uncode": "e7a5" + }, + { + "cls": "dtree-icon-yonghu", + "uncode": "e603" + }, + { + "cls": "dtree-icon-fenzhijigou", + "uncode": "e658" + }, + { + "cls": "dtree-icon-fenguangbaobiao", + "uncode": "e655" + }, + { + "cls": "dtree-icon-xinxipilu", + "uncode": "e620" + }, + { + "cls": "dtree-icon-shuye1", + "uncode": "e61e" + }, + { + "cls": "dtree-icon-caidan_xunzhang", + "uncode": "e68e" + }, + { + "cls": "dtree-icon-normal-file", + "uncode": "e60c" + }, + { + "cls": "dtree-icon-roundclose", + "uncode": "e65c" + }, + { + "cls": "dtree-icon-bianji", + "uncode": "e602" + }, + { + "cls": "dtree-icon-roundadd", + "uncode": "e6d9" + }, + { + "cls": "dtree-icon-fuxuankuangxuanzhong", + "uncode": "e652" + }, + { + "cls": "dtree-icon-fuxuankuang", + "uncode": "e6f2" + }, + { + "cls": "dtree-icon-fuxuankuang-banxuan", + "uncode": "e607" + }, + { + "cls": "dtree-icon-search_list_light", + "uncode": "e807" + }, + { + "cls": "dtree-icon-move-up", + "uncode": "ea47" + }, + { + "cls": "dtree-icon-move-down", + "uncode": "ea48" + }, + { + "cls": "dtree-icon-delete1", + "uncode": "e640" + }, + { + "cls": "dtree-icon-refresh", + "uncode": "e6a4" + }, + { + "cls": "dtree-icon-roundcheckfill", + "uncode": "e659" + }, + { + "cls": "dtree-icon-roundclosefill", + "uncode": "e65b" + }, + { + "cls": "dtree-icon-roundcheck", + "uncode": "e65a" + }, + { + "cls": "dtree-icon-pulldown", + "uncode": "e6a0" + }, + { + "cls": "dtree-icon-pullup", + "uncode": "e6a1" + }, + { + "cls": "dtree-icon-set-sm", + "uncode": "e621" + }, + { + "cls": "dtree-icon-rate", + "uncode": "e833" + }, + { + "cls": "dtree-icon-jian1", + "uncode": "e600" + }, + { + "cls": "dtree-icon-jia1", + "uncode": "e601" + }, + { + "cls": "dtree-icon-shijian", + "uncode": "e606" + }, + { + "cls": "dtree-icon-check", + "uncode": "e645" + }, + { + "cls": "dtree-icon-close", + "uncode": "e646" + }, + { + "cls": "dtree-icon-favorfill", + "uncode": "e64b" + }, + { + "cls": "dtree-icon-favor", + "uncode": "e64c" + }, + { + "cls": "dtree-icon-roundrightfill", + "uncode": "e65d" + }, + { + "cls": "dtree-icon-roundright", + "uncode": "e65e" + }, + { + "cls": "dtree-icon-samefill", + "uncode": "e671" + }, + { + "cls": "dtree-icon-same", + "uncode": "e672" + }, + { + "cls": "dtree-icon-qrcode1", + "uncode": "e6b0" + }, + { + "cls": "dtree-icon-profile1", + "uncode": "e6b7" + }, + { + "cls": "dtree-icon-home1", + "uncode": "e6b8" + }, + { + "cls": "dtree-icon-homefill", + "uncode": "e6bb" + }, + { + "cls": "dtree-icon-roundaddfill", + "uncode": "e6d8" + }, + { + "cls": "dtree-icon-wefill", + "uncode": "e6f5" + }, + { + "cls": "dtree-icon-sort", + "uncode": "e701" + }, + { + "cls": "dtree-icon-round_list_light", + "uncode": "e82b" + }, + { + "cls": "dtree-icon-search2", + "uncode": "e615" + }, + { + "cls": "dtree-icon-close1", + "uncode": "1006" + }, + { + "cls": "dtree-icon-close-fill", + "uncode": "1007" + }, + { + "cls": "dtree-icon-chart-screen", + "uncode": "e62a" + }, + { + "cls": "dtree-icon-star", + "uncode": "e608" + }, + { + "cls": "dtree-icon-ok-circle", + "uncode": "1005" + }, + { + "cls": "dtree-icon-add-circle", + "uncode": "e61f" + }, + { + "cls": "dtree-icon-about", + "uncode": "e623" + }, + { + "cls": "dtree-icon-circle1", + "uncode": "e687" + }, + { + "cls": "dtree-icon-radio", + "uncode": "e688" + }, + { + "cls": "dtree-icon-star-fill", + "uncode": "e832" + }, + { + "cls": "dtree-icon-shujudaping", + "uncode": "e742" + }, + { + "cls": "dtree-icon-share3", + "uncode": "e641" + }, + { + "cls": "dtree-icon-youjian", + "uncode": "e642" + }, + { + "cls": "dtree-icon-repair", + "uncode": "e738" + }, + { + "cls": "dtree-icon-evaluate", + "uncode": "e674" + }, + { + "cls": "dtree-icon-like", + "uncode": "e66c" + }, + { + "cls": "dtree-icon-layim-theme", + "uncode": "e61b" + }, + { + "cls": "dtree-icon-xiangmuxiaoxi", + "uncode": "e60f" + } + ] +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/form.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/form.css new file mode 100644 index 0000000000000000000000000000000000000000..b6a8c8d311dd00765e461d0966a23f992517dcc7 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/form.css @@ -0,0 +1,74 @@ +.layui-card-body .layui-form{ + margin-top: 15px; +} + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #ccc; +} + +.layui-input:hover, +.layui-textarea:hover, +.layui-input:focus, +.layui-textarea:focus { + border-color: #eee; +} + +.layui-input:focus, +.layui-textarea:focus { + border-color: #5FB878 !important; + box-shadow: 0 0 0 3px #f0f9eb !important; +} + +.layui-input[success] { + box-shadow: 0px 0px 0px 3px #f0f9eb !important; + border: #5FB878 1px solid!important; +} + +.layui-input[failure], +.layui-form-item .layui-form-danger:focus { + box-shadow: 0px 0px 0px 3px #fef0f0 !important; + border: #F56C6C 1px solid!important; +} + +.layui-input, +.layui-select, +.layui-textarea { + border-radius: 4px; + border-color: #eee; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +.layui-form-select dl::-webkit-scrollbar { + width: 0px; + height: 0px; +} + +.layui-form-select dl::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +.layui-form-select dl::-webkit-scrollbar-track { + background: white; + border-radius: 3px; +} + +.layui-form-select dl::-webkit-scrollbar-thumb { + background: #E6E6E6; + border-radius: 3px; +} + +.layui-form-select dl::-webkit-scrollbar-thumb:hover { + background: #E6E6E6; +} + +.layui-form-select dl::-webkit-scrollbar-corner { + background: #f6f6f6; +} + +/* layui 2.6.9 样式变化 */ +.layui-form-select dl dd.layui-this{ + background-color: #F6F6F6; + font-weight: 700; +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/frame.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/frame.css new file mode 100644 index 0000000000000000000000000000000000000000..09a1423f2b330d5c89a34bb11dddabb5e0f651d7 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/frame.css @@ -0,0 +1,158 @@ +.pear-frame { + width: 100%; + height: 100%; + position: relative; + overflow: hidden; +} + +.pear-frame .dot { + width: 5px; + height: 24px; + background-color: #5FB878; + margin-top: 8px; + margin-left: 15px; + border-radius: 2px; + display: inline-block; +} + +.pear-frame .title { + position: absolute; + margin-top: 0px; + margin-left: 12px; + color: dimgray; + display: inline-block; + letter-spacing: 2px; +} + +.pear-frame .pear-frame-title { + height: 40px; + line-height: 40px; + background-color: white; + border: whitesmoke 1px solid; +} + +.pear-frame .pear-frame-content { + width: 100%; + height: calc(100% - 0px) !important; +} + +.pear-frame-loading { + position: absolute; + display: none; + width: 100%; + height: calc(100% - 0px) !important; + top: 0px; + z-index: 19; + background-color: #fff +} + +.pear-frame-loading.close { + animation: close 1s; + -webkit-animation: close 1s; + animation-fill-mode: forwards; +} + +.ball-loader { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + -ms-transform: translate(-50%, -50%); + -webkit-transform: translate(-50%, -50%) +} + +.ball-loader>span, +.signal-loader>span { + background-color: #4aca85; + display: inline-block +} + +.ball-loader>span:nth-child(1), +.ball-loader.sm>span:nth-child(1), +.signal-loader>span:nth-child(1), +.signal-loader.sm>span:nth-child(1) { + -webkit-animation-delay: 0s; + animation-delay: 0s +} + +.ball-loader>span:nth-child(2), +.ball-loader.sm>span:nth-child(2), +.signal-loader>span:nth-child(2), +.signal-loader.sm>span:nth-child(2) { + -webkit-animation-delay: .1s; + animation-delay: .1s +} + +.ball-loader>span:nth-child(3), +.ball-loader.sm>span:nth-child(3), +.signal-loader>span:nth-child(3), +.signal-loader.sm>span:nth-child(3) { + -webkit-animation-delay: .15s; + animation-delay: .15s +} + +.ball-loader>span:nth-child(4), +.ball-loader.sm>span:nth-child(4), +.signal-loader>span:nth-child(4), +.signal-loader.sm>span:nth-child(4) { + -webkit-animation-delay: .2s; + animation-delay: .2s +} + +.ball-loader>span { + width: 20px; + height: 20px; + margin: 0 3px; + border-radius: 50%; + transform: scale(0); + -ms-transform: scale(0); + -webkit-transform: scale(0); + animation: ball-load 1s ease-in-out infinite; + -webkit-animation: 1s ball-load ease-in-out infinite +} + +@-webkit-keyframes ball-load { + 0% { + transform: scale(0); + -webkit-transform: scale(0) + } + + 50% { + transform: scale(1); + -webkit-transform: scale(1) + } + + 100% { + transform: scale(0); + -webkit-transform: scale(0) + } +} + +@keyframes ball-load { + 0% { + transform: scale(0); + -webkit-transform: scale(0) + } + + 50% { + transform: scale(1); + -webkit-transform: scale(1) + } + + 100% { + transform: scale(0); + -webkit-transform: scale(0) + } +} + +@-webkit-keyframes close { + 0% { + opacity: 1; + /*display: block;*/ + } + + 100% { + opacity: 0; + /*display: none;*/ + } +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/fullscreen.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/fullscreen.css new file mode 100644 index 0000000000000000000000000000000000000000..63f7775413c722efed1600a0cb236fd0e2302623 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/fullscreen.css @@ -0,0 +1,22 @@ +html:-moz-full-screen { + background: grey; +} +html:-webkit-full-screen { + background: grey; + width: 100%; + height: 100%; +} +html:fullscreen{ + background: grey; + width: 100% !important; + height: 100% !important; +} + +:not(:root):fullscreen::backdrop{ + background:whitesmoke; +} + +.pear-full-screen { + width: 100% !important; + height: 100% !important; +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/iconPicker.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/iconPicker.css new file mode 100644 index 0000000000000000000000000000000000000000..5d80b0b951fe91636eb775855528c45765273d56 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/iconPicker.css @@ -0,0 +1,11 @@ +.layui-iconpicker { + width: 295px; +} + +.layui-iconpicker .layui-iconpicker-search .layui-input:focus{ + box-shadow: none!important; +} + +.layui-iconpicker-search .layui-icon { + top: 8px; +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/label.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/label.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/layer.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/layer.css new file mode 100644 index 0000000000000000000000000000000000000000..0ca669f57aa1e750dc3e566af7dfabfde7fb8036 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/layer.css @@ -0,0 +1,324 @@ +.layui-layer-msg { + border-color: transparent !important; + box-shadow: 2px 0 6px rgb(0 21 41 / 0.04) !important; +} + +/* 扩展动画开始 */ +.pear-drawer.layui-layer { + border-radius: 0 !important; + overflow: auto; +} + +.pear-drawer.layui-layer.position-absolute { + position: absolute !important; +} +.pear-drawer-anim, +.pear-drawer-anim.layui-anim { + -webkit-animation-duration: .3s; + animation-duration: .3s; + -webkit-animation-timing-function: cubic-bezier(0.7, 0.3, 0.1, 1); + animation-timing-function: cubic-bezier(0.7, 0.3, 0.1, 1); +} + +/* right to left */ +@keyframes layer-rl { + from { + -webkit-transform: translate3d(100%, 0, 0); + -ms-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + opacity: 1; + + } + + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@-webkit-keyframes layer-rl { + from { + -webkit-transform: translate3d(100%, 0, 0); + -ms-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + opacity: 1; + + } + + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.layer-anim-rl { + -webkit-animation-name: layer-rl; + animation-name: layer-rl; +} + +/* right to left close */ +@keyframes layer-rl-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + -webkit-transform: translate3d(100%, 0, 0); + -ms-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +@-webkit-keyframes layer-rl-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + + } + + to { + -webkit-transform: translate3d(100%, 0, 0); + -ms-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +.layer-anim-rl-close, +.layer-anim-rl.layer-anim-close { + -webkit-animation-name: layer-rl-close; + animation-name: layer-rl-close; +} + +/* left to right */ +@-webkit-keyframes layer-lr { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1 + } + + to { + -webkit-transform: translate3d(-100%, 0, 0); + -ms-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + opacity: 1 + } +} + +@keyframes layer-lr { + from { + -webkit-transform: translate3d(-100%, 0, 0); + -ms-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + opacity: 1 + } + + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1 + } +} + +.layer-anim-lr { + -webkit-animation-name: layer-lr; + animation-name: layer-lr +} + +/* left to right close */ +@-webkit-keyframes layer-lr-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + -webkit-transform: translate3d(-100%, 0, 0); + -ms-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +@keyframes layer-lr-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + -webkit-transform: translate3d(-100%, 0, 0); + -ms-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +.layer-anim-lr-close, +.layer-anim-lr.layer-anim-close { + -webkit-animation-name: layer-lr-close; + animation-name: layer-lr-close +} + +/* top to bottom */ +@-webkit-keyframes layer-tb { + from { + -webkit-transform: translate3d(0, -100%, 0); + -ms-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + opacity: 1; + animation-timing-function: cubic-bezier(0.7, 0.3, 0.1, 1); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + animation-timing-function: cubic-bezier(0.7, 0.3, 0.1, 1); + } +} + +@keyframes layer-tb { + from { + -webkit-transform: translate3d(0, -100%, 0); + -ms-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + opacity: 1; + animation-timing-function: cubic-bezier(0.7, 0.3, 0.1, 1); + } + + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + animation-timing-function: cubic-bezier(0.7, 0.3, 0.1, 1); + } +} + +.layer-anim-tb { + -webkit-animation-name: layer-tb; + animation-name: layer-tb +} + +/* top to bottom close */ +@-webkit-keyframes layer-tb-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + -webkit-transform: translate3d(0, -100%, 0); + -ms-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@keyframes layer-tb-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + -webkit-transform: translate3d(0, -100%, 0); + -ms-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +.layer-anim-tb-close, +.layer-anim-tb.layer-anim-close { + -webkit-animation-name: layer-tb-close; + animation-name: layer-tb-close +} + +/* bottom to top */ +@-webkit-keyframes layer-bt { + from { + -webkit-transform: translate3d(0, 100%, 0); + -ms-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + opacity: 1 + } + + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1 + } +} + +@keyframes layer-bt { + from { + -webkit-transform: translate3d(0, 100%, 0); + -ms-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + opacity: 1 + } + + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1 + } +} + +.layer-anim-bt { + -webkit-animation-name: layer-bt; + animation-name: layer-bt +} + +/* bottom to top close */ +@-webkit-keyframes layer-bt-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + to { + -webkit-transform: translate3d(0, 100%, 0); + -ms-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@keyframes layer-bt-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + + } + + to { + -webkit-transform: translate3d(0, 100%, 0); + -ms-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + + } +} + +.layer-anim-bt-close, +.layer-anim-bt.layer-anim-close { + -webkit-animation-name: layer-bt-close; + animation-name: layer-bt-close +} + +/* 扩展动画结束 */ \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/layout.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/layout.css new file mode 100644 index 0000000000000000000000000000000000000000..9c4d082247860738a0b115c17b9798520bcec5e5 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/layout.css @@ -0,0 +1,1041 @@ +.pear-container { + margin: 10px; + background-color: whitesmoke; + width: calc(100vw - 20px); +} + +body::-webkit-scrollbar { + width: 0px; + height: 0px; +} + +body::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +body::-webkit-scrollbar-track { + background: white; + border-radius: 2px; +} + +body::-webkit-scrollbar-thumb { + background: #E6E6E6; + border-radius: 2px; +} + +body::-webkit-scrollbar-thumb:hover { + background: #E6E6E6; +} + +body::-webkit-scrollbar-corner { + background: #f6f6f6; +} + +.mainBox::-webkit-scrollbar { + width: 0px; + height: 0px; +} + +.mainBox::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +.mainBox::-webkit-scrollbar-track { + background: white; + border-radius: 2px; +} + +.mainBox::-webkit-scrollbar-thumb { + background: #E6E6E6; + border-radius: 2px; +} + +.mainBox::-webkit-scrollbar-thumb:hover { + background: #E6E6E6; +} + +.mainBox::-webkit-scrollbar-corner { + background: #f6f6f6; +} + +.mainBox { + width: 100%; + position: absolute; + top: 0px; + left: 0px; + bottom: 50px; + overflow: auto; +} + +.bottom { + width: 100%; + position: absolute; + bottom: 0px; + left: 0px; + height: 50px; + line-height: 50px; + background-color: #F8F8F8; + border-top: 1px solid #eee; +} + +.button-container { + position: absolute; + right: 15px; +} + +.main-container { + margin: 15px; +} + +.main-container .layui-form-item { + margin-bottom: 15px !important; + margin-top: 10px !important; +} + +.pear-row::before, +.pear-row::after { + content: ""; + display: table; + clear: both; +} + +.pear-col { + float: left; + min-height: 1px; +} + +.pear-row * { + box-sizing: border-box +} + +.pear-col-md1 { + width: 4.16%; +} + +.pear-col-md2 { + width: 8.33%; +} + +.pear-col-md3 { + width: 12.5%; +} + +.pear-col-md4 { + width: 16.66%; +} + +.pear-col-md5 { + width: 20.83%; +} + +.pear-col-md6 { + width: 25%; +} + +.pear-col-md7 { + width: 29.16%; +} + +.pear-col-md8 { + width: 33.33%; +} + +.pear-col-md9 { + width: 37.5%; +} + +.pear-col-md10 { + width: 41.66%; +} + +.pear-col-md11 { + width: 45.83%; +} + +.pear-col-md12 { + width: 50%; +} + +.pear-col-md13 { + width: 54.16%; +} + +.pear-col-md14 { + width: 58.33%; +} + +.pear-col-md15 { + width: 62.5%; +} + +.pear-col-md16 { + width: 66.66%; +} + +.pear-col-md17 { + width: 70.83%; +} + +.pear-col-md18 { + width: 75%; +} + +.pear-col-md19 { + width: 79.16%; +} + +.pear-col-md20 { + width: 83.33%; +} + +.pear-col-md21 { + width: 87.5%; +} + +.pear-col-md22 { + width: 91.66%; +} + +.pear-col-md23 { + width: 95.83%; +} + +.pear-col-md24 { + width: 100%; +} + +@media all and (min-width:993px) and (max-width:1199px) { + + .pear-col-md-offset1 { + margin-left: 4.16%; + } + + .pear-col-md-offset2 { + margin-left: 8.33%; + } + + .pear-col-md-offset3 { + margin-left: 12.5%; + } + + .pear-col-md-offset4 { + margin-left: 16.66%; + } + + .pear-col-md-offset5 { + margin-left: 20.83%; + } + + .pear-col-md-offset6 { + margin-left: 25%; + } + + .pear-col-md-offset7 { + margin-left: 29.16%; + } + + .pear-col-md-offset8 { + margin-left: 33.33%; + } + + .pear-col-md-offset9 { + margin-left: 37.5%; + } + + .pear-col-md-offset10 { + margin-left: 41.66%; + } + + .pear-col-md-offset11 { + margin-left: 45.83%; + } + + .pear-col-md-offset12 { + margin-left: 50%; + } + + .pear-col-md-offset13 { + margin-left: 54.16%; + } + + .pear-col-md-offset14 { + margin-left: 58.33%; + } + + .pear-col-md-offset15 { + margin-left: 62.5%; + } + + .pear-col-md-offset16 { + margin-left: 66.66%; + } + + .pear-col-md-offset17 { + margin-left: 70.83%; + } + + .pear-col-md-offset18 { + margin-left: 75%; + } + + .pear-col-md-offset19 { + margin-left: 79.16%; + } + + .pear-col-md-offset20 { + margin-left: 83.33%; + } + + .pear-col-md-offset21 { + margin-left: 87.5%; + } + + .pear-col-md-offset22 { + margin-left: 91.66%; + } + + .pear-col-md-offset23 { + margin-left: 95.83%; + } + + .pear-col-md-offset24 { + margin-left: 100%; + } +} + + +@media all and (max-width:768px) { + .pear-col-xs1 { + width: 4.16%; + } + + .pear-col-xs2 { + width: 8.33%; + } + + .pear-col-xs3 { + width: 12.5%; + } + + .pear-col-xs4 { + width: 16.66%; + } + + .pear-col-xs5 { + width: 20.83%; + } + + .pear-col-xs6 { + width: 25%; + } + + .pear-col-xs7 { + width: 29.16%; + } + + .pear-col-xs8 { + width: 33.33%; + } + + .pear-col-xs9 { + width: 37.5%; + } + + .pear-col-xs10 { + width: 41.66%; + } + + .pear-col-xs11 { + width: 45.83%; + } + + .pear-col-xs12 { + width: 50%; + } + + .pear-col-xs13 { + width: 54.16%; + } + + .pear-col-xs14 { + width: 58.33%; + } + + .pear-col-xs15 { + width: 62.5%; + } + + .pear-col-xs16 { + width: 66.66%; + } + + .pear-col-xs17 { + width: 70.83%; + } + + .pear-col-xs18 { + width: 75%; + } + + .pear-col-xs19 { + width: 79.16%; + } + + .pear-col-xs20 { + width: 83.33%; + } + + .pear-col-xs21 { + width: 87.5%; + } + + .pear-col-xs22 { + width: 91.66%; + } + + .pear-col-xs23 { + width: 95.83%; + } + + .pear-col-xs24 { + width: 100%; + } + + .pear-col-xs-offset1 { + margin-left: 4.16%; + } + + .pear-col-xs-offset2 { + margin-left: 8.33%; + } + + .pear-col-xs-offset3 { + margin-left: 12.5%; + } + + .pear-col-xs-offset4 { + margin-left: 16.66%; + } + + .pear-col-xs-offset5 { + margin-left: 20.83%; + } + + .pear-col-xs-offset6 { + margin-left: 25%; + } + + .pear-col-xs-offset7 { + margin-left: 29.16%; + } + + .pear-col-xs-offset8 { + margin-left: 33.33%; + } + + .pear-col-xs-offset9 { + margin-left: 37.5%; + } + + .pear-col-xs-offset10 { + margin-left: 41.66%; + } + + .pear-col-xs-offset11 { + margin-left: 45.83%; + } + + .pear-col-xs-offset12 { + margin-left: 50%; + } + + .pear-col-xs-offset13 { + margin-left: 54.16%; + } + + .pear-col-xs-offset14 { + margin-left: 58.33%; + } + + .pear-col-xs-offset15 { + margin-left: 62.5%; + } + + .pear-col-xs-offset16 { + margin-left: 66.66%; + } + + .pear-col-xs-offset17 { + margin-left: 70.83%; + } + + .pear-col-xs-offset18 { + margin-left: 75%; + } + + .pear-col-xs-offset19 { + margin-left: 79.16%; + } + + .pear-col-xs-offset20 { + margin-left: 83.33%; + } + + .pear-col-xs-offset21 { + margin-left: 87.5%; + } + + .pear-col-xs-offset22 { + margin-left: 91.66%; + } + + .pear-col-xs-offset23 { + margin-left: 95.83%; + } + + .pear-col-xs-offset24 { + margin-left: 100%; + } +} + +@media all and (min-width:768px) and (max-width:992px) { + .pear-col-sm1 { + width: 4.16%; + } + + .pear-col-sm2 { + width: 8.33%; + } + + .pear-col-sm3 { + width: 12.5%; + } + + .pear-col-sm4 { + width: 16.66%; + } + + .pear-col-sm5 { + width: 20.83%; + } + + .pear-col-sm6 { + width: 25%; + } + + .pear-col-sm7 { + width: 29.16%; + } + + .pear-col-sm8 { + width: 33.33%; + } + + .pear-col-sm9 { + width: 37.5%; + } + + .pear-col-sm10 { + width: 41.66%; + } + + .pear-col-sm11 { + width: 45.83%; + } + + .pear-col-sm12 { + width: 50%; + } + + .pear-col-sm13 { + width: 54.16%; + } + + .pear-col-sm14 { + width: 58.33%; + } + + .pear-col-sm15 { + width: 62.5%; + } + + .pear-col-sm16 { + width: 66.66%; + } + + .pear-col-sm17 { + width: 70.83%; + } + + .pear-col-sm18 { + width: 75%; + } + + .pear-col-sm19 { + width: 79.16%; + } + + .pear-col-sm20 { + width: 83.33%; + } + + .pear-col-sm21 { + width: 87.5%; + } + + .pear-col-sm22 { + width: 91.66%; + } + + .pear-col-sm23 { + width: 95.83%; + } + + .pear-col-sm24 { + width: 100%; + } + + .pear-col-sm-offset1 { + margin-left: 4.16%; + } + + .pear-col-sm-offset2 { + margin-left: 8.33%; + } + + .pear-col-sm-offset3 { + margin-left: 12.5%; + } + + .pear-col-sm-offset4 { + margin-left: 16.66%; + } + + .pear-col-sm-offset5 { + margin-left: 20.83%; + } + + .pear-col-sm-offset6 { + margin-left: 25%; + } + + .pear-col-sm-offset7 { + margin-left: 29.16%; + } + + .pear-col-sm-offset8 { + margin-left: 33.33%; + } + + .pear-col-sm-offset9 { + margin-left: 37.5%; + } + + .pear-col-sm-offset10 { + margin-left: 41.66%; + } + + .pear-col-sm-offset11 { + margin-left: 45.83%; + } + + .pear-col-sm-offset12 { + margin-left: 50%; + } + + .pear-col-sm-offset13 { + margin-left: 54.16%; + } + + .pear-col-sm-offset14 { + margin-left: 58.33%; + } + + .pear-col-sm-offset15 { + margin-left: 62.5%; + } + + .pear-col-sm-offset16 { + margin-left: 66.66%; + } + + .pear-col-sm-offset17 { + margin-left: 70.83%; + } + + .pear-col-sm-offset18 { + margin-left: 75%; + } + + .pear-col-sm-offset19 { + margin-left: 79.16%; + } + + .pear-col-sm-offset20 { + margin-left: 83.33%; + } + + .pear-col-sm-offset21 { + margin-left: 87.5%; + } + + .pear-col-sm-offset22 { + margin-left: 91.66%; + } + + .pear-col-sm-offset23 { + margin-left: 95.83%; + } + + .pear-col-sm-offset24 { + margin-left: 100%; + } +} + +@media all and (min-width:1200px) { + .pear-col-lg1 { + width: 4.16%; + } + + .pear-col-lg2 { + width: 8.33%; + } + + .pear-col-lg3 { + width: 12.5%; + } + + .pear-col-lg4 { + width: 16.66%; + } + + .pear-col-lg5 { + width: 20.83%; + } + + .pear-col-lg6 { + width: 25%; + } + + .pear-col-lg7 { + width: 29.16%; + } + + .pear-col-lg8 { + width: 33.33%; + } + + .pear-col-lg9 { + width: 37.5%; + } + + .pear-col-lg10 { + width: 41.66%; + } + + .pear-col-lg11 { + width: 45.83%; + } + + .pear-col-lg12 { + width: 50%; + } + + .pear-col-lg13 { + width: 54.16%; + } + + .pear-col-lg14 { + width: 58.33%; + } + + .pear-col-lg15 { + width: 62.5%; + } + + .pear-col-lg16 { + width: 66.66%; + } + + .pear-col-lg17 { + width: 70.83%; + } + + .pear-col-lg18 { + width: 75%; + } + + .pear-col-lg19 { + width: 79.16%; + } + + .pear-col-lg20 { + width: 83.33%; + } + + .pear-col-lg21 { + width: 87.5%; + } + + .pear-col-lg22 { + width: 91.66%; + } + + .pear-col-lg23 { + width: 95.83%; + } + + .pear-col-lg24 { + width: 100%; + } + + .pear-col-lg-offset1 { + margin-left: 4.16%; + } + + .pear-col-lg-offset2 { + margin-left: 8.33%; + } + + .pear-col-lg-offset3 { + margin-left: 12.5%; + } + + .pear-col-lg-offset4 { + margin-left: 16.66%; + } + + .pear-col-lg-offset5 { + margin-left: 20.83%; + } + + .pear-col-lg-offset6 { + margin-left: 25%; + } + + .pear-col-lg-offset7 { + margin-left: 29.16%; + } + + .pear-col-lg-offset8 { + margin-left: 33.33%; + } + + .pear-col-lg-offset9 { + margin-left: 37.5%; + } + + .pear-col-lg-offset10 { + margin-left: 41.66%; + } + + .pear-col-lg-offset11 { + margin-left: 45.83%; + } + + .pear-col-lg-offset12 { + margin-left: 50%; + } + + .pear-col-lg-offset13 { + margin-left: 54.16%; + } + + .pear-col-lg-offset14 { + margin-left: 58.33%; + } + + .pear-col-lg-offset15 { + margin-left: 62.5%; + } + + .pear-col-lg-offset16 { + margin-left: 66.66%; + } + + .pear-col-lg-offset17 { + margin-left: 70.83%; + } + + .pear-col-lg-offset18 { + margin-left: 75%; + } + + .pear-col-lg-offset19 { + margin-left: 79.16%; + } + + .pear-col-lg-offset20 { + margin-left: 83.33%; + } + + .pear-col-lg-offset21 { + margin-left: 87.5%; + } + + .pear-col-lg-offset22 { + margin-left: 91.66%; + } + + .pear-col-lg-offset23 { + margin-left: 95.83%; + } + + .pear-col-lg-offset24 { + margin-left: 100%; + } +} + +.pear-col-space1 { + margin: -.5px +} + +.pear-col-space1>* { + padding: .5px +} + +.pear-col-space2 { + margin: -1px +} + +.pear-col-space2>* { + padding: 1px +} + +.pear-col-space4 { + margin: -2px +} + +.pear-col-space4>* { + padding: 2px +} + +.pear-col-space5 { + margin: -2.5px +} + +.pear-col-space5>* { + padding: 2.5px +} + +.pear-col-space6 { + margin: -3px +} + +.pear-col-space6>* { + padding: 3px +} + +.pear-col-space8 { + margin: -4px +} + +.pear-col-space8>* { + padding: 4px +} + +.pear-col-space10 { + margin: -5px +} + +.pear-col-space10>* { + padding: 5px +} + +.pear-col-space12 { + margin: -6px +} + +.pear-col-space12>* { + padding: 6px +} + +.pear-col-space14 { + margin: -7px +} + +.pear-col-space14>* { + padding: 7px +} + +.pear-col-space15 { + margin: -7.5px +} + +.pear-col-space15>* { + padding: 7.5px +} + +.pear-col-space16 { + margin: -8px +} + +.pear-col-space16>* { + padding: 8px +} + +.pear-col-space18 { + margin: -9px +} + +.pear-col-space18>* { + padding: 9px +} + +.pear-col-space20 { + margin: -10px +} + +.pear-col-space20>* { + padding: 10px +} + +.pear-col-space22 { + margin: -11px +} + +.pear-col-space22>* { + padding: 11px +} + +.pear-col-space24 { + margin: -12px +} + +.pear-col-space24>* { + padding: 12px +} + +.pear-col-space25 { + margin: -12.5px +} + +.pear-col-space25>* { + padding: 12.5px +} + +.pear-col-space26 { + margin: -13px +} + +.pear-col-space26>* { + padding: 13px +} + +.pear-col-space28 { + margin: -14px +} + +.pear-col-space28>* { + padding: 14px +} + +.pear-col-space30 { + margin: -15px +} + +.pear-col-space30>* { + padding: 15px +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/link.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/link.css new file mode 100644 index 0000000000000000000000000000000000000000..380351c5f3541a7407252e56c6d90a740f3cdd95 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/link.css @@ -0,0 +1,20 @@ +.pear-link{ + font-size: 15px!important; +} + +.pear-link.pear-link-primary{ + color : #5FB878 ; +} + +.pear-link.pear-link-success{ + color : #5FB878 ; +} + +.pear-link .pear-link-warming{ + + +} + +.pear-link .pear-link-danger{ + +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/loading.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/loading.css new file mode 100644 index 0000000000000000000000000000000000000000..4abb57d3d823f926cbb83838244a2721618b7b81 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/loading.css @@ -0,0 +1,987 @@ +/*! +* Notiflix ('https://www.notiflix.com') +* Version: 2.0.0 +* Author: Furkan MT ('https://github.com/furcan') +* Copyright 2020 Notiflix, MIT Licence ('https://opensource.org/licenses/MIT') +*/ + +/* Notiflix: Notify wrap on */ +[id^=NotiflixNotifyWrap] { +position: fixed; +z-index:4001; +opacity:1; +right: 10px; +top: 10px; +width: 280px; +max-width:96%; +box-sizing:border-box; +background: transparent;} + +[id^=NotiflixNotifyWrap] * { +box-sizing:border-box;} +/* Notiflix: Notify wrap off */ + +/* Notiflix: Notify content on */ +[id^=NotiflixNotifyWrap] > div { +-webkit-user-select: none; +-moz-user-select: none; +-ms-user-select: none; +user-select: none; +font-family: 'Quicksand', sans-serif; +width:100%; +display: inline-block; +position:relative; +margin:0 0 10px; +border-radius:5px; +background: #1e1e1e; +color: #fff; +padding: 10px 12px; +font-size: 14px; +line-height: 1.4;} + +[id^=NotiflixNotifyWrap] > div:last-child { +margin:0;} + +[id^=NotiflixNotifyWrap] > div.with-callback { +cursor:pointer;} + +[id^=NotiflixNotifyWrap] *::selection { +background:inherit;} + +[id^=NotiflixNotifyWrap] > div.with-icon { +padding: 8px;} + +[id^=NotiflixNotifyWrap] > div.click-to-close { +cursor: pointer;} + +[id^=NotiflixNotifyWrap] > div.with-close-button { +padding: 10px 30px 10px 12px;} +[id^=NotiflixNotifyWrap] > div.with-icon.with-close-button { +padding: 6px 30px 6px 6px;} + +[id^=NotiflixNotifyWrap] > div > span.the-message { +font-weight: 500; +font-family:inherit !important; +word-break: break-all; +word-break: break-word;} + +[id^=NotiflixNotifyWrap] > div > span.notify-close-button { +cursor:pointer; +transition:all .2s ease-in-out; +position: absolute; +right: 8px; +top: 0; +bottom:0; +margin:auto; +color:inherit; +width: 16px; +height: 16px;} +[id^=NotiflixNotifyWrap] > div > span.notify-close-button:hover { +transform:rotate(90deg);} +[id^=NotiflixNotifyWrap] > div > span.notify-close-button > svg { +position: absolute; +width: 16px; +height: 16px; +right: 0; +top: 0;} +/* Notiflix: Notify content off */ + +/* Notiflix: Notify icon on */ +[id^=NotiflixNotifyWrap] > div > .nmi { +position: absolute; +width: 40px; +height: 40px; +font-size: 30px; +line-height: 40px; +text-align: center; +left: 8px; +top: 0; +bottom: 0; +margin: auto; +border-radius: inherit;} + +[id^=NotiflixNotifyWrap] > div > .wfa.shadow { +color: inherit; +background: rgba(0, 0, 0, 0.15); +box-shadow: inset 0 0 34px rgba(0, 0, 0, 0.2); +text-shadow: 0 0 10px rgba(0, 0, 0, 0.3);} + +[id^=NotiflixNotifyWrap] > div > span.with-icon { +position: relative; +float: left; +width: calc(100% - 40px); +margin:0 0 0 40px; +padding:0 0 0 10px; +box-sizing: border-box;} +/* Notiflix: Notify icon off */ + +/* Notiflix: Notify rtl on */ +[id^=NotiflixNotifyWrap] > div.rtl-on > .nmi { +left:auto; +right:8px;} + +[id^=NotiflixNotifyWrap] > div.rtl-on > span.with-icon { +padding:0 10px 0 0; +margin:0 40px 0 0;} + +[id^=NotiflixNotifyWrap] > div.rtl-on > span.notify-close-button { +right: auto; +left: 8px;} + +[id^=NotiflixNotifyWrap] > div.with-icon.with-close-button.rtl-on { +padding: 6px 6px 6px 30px;} + +[id^=NotiflixNotifyWrap] > div.with-close-button.rtl-on { +padding: 10px 12px 10px 30px;} +/* Notiflix: Notify rtl off */ + +/* Notiflix: Notify animation => fade on */ +[id^=NotiflixNotifyOverlay].with-animation, +[id^=NotiflixNotifyWrap] > div.with-animation.nx-fade { +animation: notify-animation-fade .3s ease-in-out 0s normal; +-webkit-animation: notify-animation-fade .3s ease-in-out 0s normal;} + +@keyframes notify-animation-fade { +0% {opacity:0;} +100% {opacity:1;} +} + +@-webkit-keyframes notify-animation-fade { +0% {opacity:0;} +100% {opacity:1;} +} +/* Notiflix: Notify animation => fade off */ + +/* Notiflix: Notify animation => zoom on */ +[id^=NotiflixNotifyWrap] > div.with-animation.nx-zoom { +animation: notify-animation-zoom .3s ease-in-out 0s normal; +-webkit-animation: notify-animation-zoom .3s ease-in-out 0s normal;} + +@keyframes notify-animation-zoom { +0% {transform:scale(0);} +50% {transform:scale(1.05);} +100% {transform:scale(1);} +} + +@-webkit-keyframes notify-animation-zoom { +0% {transform:scale(0);} +50% {transform:scale(1.05);} +100% {transform:scale(1);} +} +/* Notiflix: Notify animation => zoom off */ + +/* Notiflix: Notify animation => from right on */ +[id^=NotiflixNotifyWrap] > div.with-animation.nx-from-right { +animation: notify-animation-from-right .3s ease-in-out 0s normal; +-webkit-animation: notify-animation-from-right .3s ease-in-out 0s normal;} + +@keyframes notify-animation-from-right { +0% {right:-300px; opacity:0;} +50% {right:8px; opacity:1;} +100% {right:0px; opacity:1;} +} + +@-webkit-keyframes notify-animation-from-right { +0% {right:-300px; opacity:0;} +50% {right:8px; opacity:1;} +100% {right:0px; opacity:1;} +} +/* Notiflix: Notify animation => from right off */ + +/* Notiflix: Notify animation => from left on */ +[id^=NotiflixNotifyWrap] > div.with-animation.nx-from-left { +animation: notify-animation-from-left .3s ease-in-out 0s normal; +-webkit-animation: notify-animation-from-left .3s ease-in-out 0s normal;} + +@keyframes notify-animation-from-left { +0% {left:-300px; opacity:0;} +50% {left:8px; opacity:1;} +100% {left:0px; opacity:1;} +} + +@-webkit-keyframes notify-animation-from-left { +0% {left:-300px; opacity:0;} +50% {left:8px; opacity:1;} +100% {left:0px; opacity:1;} +} +/* Notiflix: Notify animation => from left off */ + +/* Notiflix: Notify animation => from top on */ +[id^=NotiflixNotifyWrap] > div.with-animation.nx-from-top { +animation: notify-animation-from-top .3s ease-in-out 0s normal; +-webkit-animation: notify-animation-from-top .3s ease-in-out 0s normal;} + +@keyframes notify-animation-from-top { +0% {top:-50px; opacity:0;} +50% {top:8px; opacity:1;} +100% {top:0px; opacity:1;} +} + +@-webkit-keyframes notify-animation-from-top { +0% {top:-50px; opacity:0;} +50% {top:8px; opacity:1;} +100% {top:0px; opacity:1;} +} +/* Notiflix: Notify animation => from top off */ + +/* Notiflix: Notify animation => from bottom on */ +[id^=NotiflixNotifyWrap] > div.with-animation.nx-from-bottom { +animation: notify-animation-from-bottom .3s ease-in-out 0s normal; +-webkit-animation: notify-animation-from-bottom .3s ease-in-out 0s normal;} + +@keyframes notify-animation-from-bottom { +0% {bottom:-50px; opacity:0;} +50% {bottom:8px; opacity:1;} +100% {bottom:0px; opacity:1;} +} + +@-webkit-keyframes notify-animation-from-bottom { +0% {bottom:-50px; opacity:0;} +50% {bottom:8px; opacity:1;} +100% {bottom:0px; opacity:1;} +} +/* Notiflix: Notify animation => from bottom off */ + +/* Notiflix: Notify animation remove => fade on */ +[id^=NotiflixNotifyOverlay].with-animation.remove, +[id^=NotiflixNotifyWrap] > div.with-animation.nx-fade.remove { +opacity:0; +animation: notify-remove-fade .3s ease-in-out 0s normal; +-webkit-animation: notify-remove-fade .3s ease-in-out 0s normal;} + +@keyframes notify-remove-fade { +0% {opacity:1;} +100% {opacity:0;} +} + +@-webkit-keyframes notify-remove-fade { +0% {opacity:1;} +100% {opacity:0;} +} +/* Notiflix: Notify animation remove => fade off */ + +/* Notiflix: Notify animation remove => zoom on */ +[id^=NotiflixNotifyWrap] > div.with-animation.nx-zoom.remove { +transform:scale(0); +animation: notify-remove-zoom .3s ease-in-out 0s normal; +-webkit-animation: notify-remove-zoom .3s ease-in-out 0s normal;} + +@keyframes notify-remove-zoom { +0% {transform:scale(1);} +50% {transform:scale(1.05);} +100% {transform:scale(0);} +} + +@-webkit-keyframes notify-remove-zoom { +0% {transform:scale(1);} +50% {transform:scale(1.05);} +100% {transform:scale(0);} +} +/* Notiflix: Notify animation remove => zoom off */ + +/* Notiflix: Notify animation remove => from top on */ +[id^=NotiflixNotifyWrap] > div.with-animation.nx-from-top.remove { +opacity:0; +animation: notify-remove-to-top .3s ease-in-out 0s normal; +-webkit-animation: notify-remove-to-top .3s ease-in-out 0s normal;} + +@keyframes notify-remove-to-top { +0% {top:0px; opacity:1;} +50% {top:8px; opacity:1;} +100% {top:-50px; opacity:0;} +} + +@-webkit-keyframes notify-remove-to-top { +0% {top:0px; opacity:1;} +50% {top:8px; opacity:1;} +100% {top:-50px; opacity:0;} +} +/* Notiflix: Notify animation remove => from top off */ + +/* Notiflix: Notify animation remove => from right on */ +[id^=NotiflixNotifyWrap] > div.with-animation.nx-from-right.remove { +opacity:0; +animation: notify-remove-to-right .3s ease-in-out 0s normal; +-webkit-animation: notify-remove-to-right .3s ease-in-out 0s normal;} + +@keyframes notify-remove-to-right { +0% {right:0px; opacity:1;} +50% {right:8px; opacity:1;} +100% {right:-300px; opacity:0;} +} + +@-webkit-keyframes notify-remove-to-right { +0% {right:0px; opacity:1;} +50% {right:8px; opacity:1;} +100% {right:-300px; opacity:0;} +} +/* Notiflix: Notify animation remove => from right off */ + +/* Notiflix: Notify animation remove => from bottom on */ +[id^=NotiflixNotifyWrap] > div.with-animation.nx-from-bottom.remove { +opacity:0; +animation: notify-remove-to-bottom .3s ease-in-out 0s normal; +-webkit-animation: notify-remove-to-bottom .3s ease-in-out 0s normal;} + +@keyframes notify-remove-to-bottom { +0% {bottom:0px; opacity:1;} +50% {bottom:8px; opacity:1;} +100% {bottom:-50px; opacity:0;} +} + +@-webkit-keyframes notify-remove-to-bottom { +0% {bottom:0px; opacity:1;} +50% {bottom:8px; opacity:1;} +100% {bottom:-50px; opacity:0;} +} +/* Notiflix: Notify animation remove => from bottom off */ + +/* Notiflix: Notify animation remove => from left on */ +[id^=NotiflixNotifyWrap] > div.with-animation.nx-from-left.remove { +opacity:0; +animation: notify-remove-to-left .3s ease-in-out 0s normal; +-webkit-animation: notify-remove-to-left .3s ease-in-out 0s normal;} + +@keyframes notify-remove-to-left { +0% {left:0px; opacity:1;} +50% {left:8px; opacity:1;} +100% {left:-300px; opacity:0;} +} + +@-webkit-keyframes notify-remove-to-left { +0% {left:0px; opacity:1;} +50% {left:8px; opacity:1;} +100% {left:-300px; opacity:0;} +} +/* Notiflix: Notify animation remove => from left off */ + + +/* Notiflix: Report wrap on */ +[id^=NotiflixReportWrap] { +position: fixed; +z-index:4002; +width: 320px; +max-width:96%; +box-sizing:border-box; +font-family: "Quicksand", sans-serif; +left: 0; +right: 0; +top: 20px; +color:#1e1e1e; +border-radius: 25px; +background: transparent; +margin: auto;} + +[id^=NotiflixReportWrap] * { +box-sizing:border-box;} +/* Notiflix: Report wrap off */ + +/* Notiflix: Report content on */ +[id^=NotiflixReportWrap] > div[class*="-overlay"] { +width:100%; +height:100%; +left:0; +top:0; +background: rgba(255, 255, 255, .5); +position:fixed; +z-index:0;} + +[id^=NotiflixReportWrap] > div[class*="-content"] { +width:100%; +float:left; +border-radius: inherit; +padding:10px; +filter: drop-shadow(0 0 5px rgba(0,0,0,.1)); +border: 1px solid rgba(0,0,0,.03); +background: #f8f8f8; +position:relative; +z-index:1;} + +[id^=NotiflixReportWrap] > div[class*="-content"] > div[class$="-icon"] { +-webkit-user-select: none; +-moz-user-select: none; +-ms-user-select: none; +user-select: none; +width:110px; +height:110px; +display:block; +margin:6px auto 12px;} + +[id^=NotiflixReportWrap] > div[class*="-content"] > div[class$="-icon"] svg { +min-width:100%; +max-width:100%; +height:auto;} + +[id^=NotiflixReportWrap] > * > h5 { +word-break: break-all; +word-break: break-word; +font-family:inherit !important; +font-size:16px; +font-weight:500; +line-height: 1.4; +margin: 0 0 10px; +padding: 0 0 10px; +border-bottom: 1px solid rgba(0, 0, 0, 0.1); +float: left; +width: 100%; +text-align: center;} + +[id^=NotiflixReportWrap] > * > p { +word-break: break-all; +word-break: break-word; +font-family:inherit !important; +font-size:13px; +line-height: 1.4; +float: left; +width: 100%; +padding:0 10px; +margin: 0 0 10px;} + +[id^=NotiflixReportWrap] a#NXReportButton { +word-break: break-all; +word-break: break-word; +-webkit-user-select: none; +-moz-user-select: none; +-ms-user-select: none; +user-select: none; +font-family:inherit !important; +transition:all .25s ease-in-out; +cursor:pointer; +float: right; +padding: 7px 17px; +background: #32c682; +font-size:14px; +line-height: 1.4; +font-weight: 500; +border-radius: inherit !important; +color: #fff;} + +[id^=NotiflixReportWrap] a#NXReportButton:hover { +box-shadow:inset 0 -60px 5px -5px rgba(0, 0, 0, 0.25);} + +[id^=NotiflixReportWrap].rtl-on a#NXReportButton { +float:left;} +/* Notiflix: Report content off */ + +/* Notiflix: Report overlay animation => fade on */ +[id^=NotiflixReportWrap] > div[class*="-overlay"].with-animation { +animation: report-overlay-animation .3s ease-in-out 0s normal; +-webkit-animation: report-overlay-animation .3s ease-in-out 0s normal;} + +@keyframes report-overlay-animation { +0% {opacity:0;} +100% {opacity:1;} +} + +@-webkit-keyframes report-overlay-animation { +0% {opacity:0;} +100% {opacity:1;} +} +/* Notiflix: Report overlay animation => fade off */ + +/* Notiflix: Report content animation => fade on */ +[id^=NotiflixReportWrap] > div[class*="-content"].with-animation.nx-fade { +animation: report-animation-fade .3s ease-in-out 0s normal; +-webkit-animation: report-animation-fade .3s ease-in-out 0s normal;} + +@keyframes report-animation-fade { +0% {opacity:0;} +100% {opacity:1;} +} + +@-webkit-keyframes report-animation-fade { +0% {opacity:0;} +100% {opacity:1;} +} +/* Notiflix: Report content animation => fade off */ + +/* Notiflix: Report content animation => zoom on */ +[id^=NotiflixReportWrap] > div[class*="-content"].with-animation.nx-zoom { +animation: report-animation-zoom .3s ease-in-out 0s normal; +-webkit-animation: report-animation-zoom .3s ease-in-out 0s normal;} + +@keyframes report-animation-zoom { +0% {opacity:0; transform:scale(0.5);} +50% {opacity:1; transform:scale(1.05);} +100% {opacity:1; transform:scale(1);} +} + +@-webkit-keyframes report-animation-zoom { +0% {opacity:0; transform:scale(0.5);} +50% {opacity:1; transform:scale(1.05);} +100% {opacity:1; transform:scale(1);} +} +/* Notiflix: Report content animation => zoom off */ + +/* Notiflix: Report overlay animation remove => fade on */ +[id^=NotiflixReportWrap].remove > div[class*="-overlay"].with-animation { +opacity:0; +animation: report-overlay-animation-remove .3s ease-in-out 0s normal; +-webkit-animation: report-overlay-animation-remove .3s ease-in-out 0s normal;} + +@keyframes report-overlay-animation-remove { +0% {opacity:1;} +100% {opacity:0;} +} + +@-webkit-keyframes report-overlay-animation-remove { +0% {opacity:1;} +100% {opacity:0;} +} +/* Notiflix: Report overlay animation remove => fade off */ + +/* Notiflix: Report content animation remove => fade on */ +[id^=NotiflixReportWrap].remove > div[class*="-content"].with-animation.nx-fade { +opacity:0; +animation: report-animation-fade-remove .3s ease-in-out 0s normal; +-webkit-animation: report-animation-fade-remove .3s ease-in-out 0s normal;} + +@keyframes report-animation-fade-remove { +0% {opacity:1;} +100% {opacity:0;} +} + +@-webkit-keyframes report-animation-fade-remove { +0% {opacity:1;} +100% {opacity:0;} +} +/* Notiflix: Report content animation remove => fade off */ + +/* Notiflix: Report content animation remove => zoom on */ +[id^=NotiflixReportWrap].remove > div[class*="-content"].with-animation.nx-zoom { +opacity:0; +animation: report-animation-zoom-remove .3s ease-in-out 0s normal; +-webkit-animation: report-animation-zoom-remove .3s ease-in-out 0s normal;} + +@keyframes report-animation-zoom-remove { +0% {opacity:1; transform:scale(1);} +50% {opacity:0.5; transform:scale(1.05);} +100% {opacity:0; transform:scale(0);} +} + +@-webkit-keyframes report-animation-zoom-remove { +0% {opacity:1; transform:scale(1);} +50% {opacity:0.5; transform:scale(1.05);} +100% {opacity:0; transform:scale(0);} +} +/* Notiflix: Report content animation remove => zoom off */ + + +/* Notiflix: Confirm wrap on */ +[id^=NotiflixConfirmWrap] { +position: fixed; +z-index: 4003; +width: 300px; +max-width:98%; +left: 10px; +right: 10px; +top: 10px; +margin:auto; +text-align: center; +box-sizing:border-box; +background:transparent; +font-family: "Quicksand", sans-serif;} + +[id^=NotiflixConfirmWrap] * { +box-sizing:border-box;} +/* Notiflix: Confirm wrap off */ + +/* Notiflix: Confirm content on */ +[id^=NotiflixConfirmWrap] > div[class*="-overlay"] { +width:100%; +height:100%; +left:0; +top:0; +background: rgba(255, 255, 255, .5); +position:fixed; +z-index:0;} + +[id^=NotiflixConfirmWrap] > div[class*="-content"] { +width:100%; +float:left; +border-radius: 25px; +padding:10px; +margin:0; +filter: drop-shadow(0 0 5px rgba(0,0,0,.1)); +background: #f8f8f8; +color:#1e1e1e; +position:relative; +z-index:1;} + +[id^=NotiflixConfirmWrap] > div[class*="-content"] > div[class*="-head"] { +float:left; +width:100%;} + +[id^=NotiflixConfirmWrap] > div[class*="-content"] > div[class*="-head"] > h5 { +float:left; +width:100%; +margin:0; +padding:0 0 10px; +border-bottom:1px solid rgba(0,0,0,0.1); +color: #32c682; +font-family:inherit !important; +font-size:16px; +line-height:1.4; +font-weight:500;} + +[id^=NotiflixConfirmWrap] > div[class*="-content"] > div[class*="-head"] > p { +font-family:inherit !important; +margin: 15px 0 20px; +padding: 0 10px; +float:left; +width:100%; +font-size: 14px; +line-height: 1.4; +color: inherit;} + +[id^=NotiflixConfirmWrap] > div[class*="-content"] > div[class*="-buttons"] { +-webkit-user-select: none; +-moz-user-select: none; +-ms-user-select: none; +user-select: none; +border-radius:inherit; +float:left; +width:100%;} + +[id^=NotiflixConfirmWrap] > div[class*="-content"] > div[class*="-buttons"] > a { +cursor:pointer; +font-family:inherit !important; +transition:all .25s ease-in-out; +float: left; +width: 48%; +padding: 9px 5px; +border-radius:inherit !important; +font-weight: 500; +font-size: 15px; +line-height: 1.4; +color:#f8f8f8;} + +[id^=NotiflixConfirmWrap] > div[class*="-content"] > div[class*="-buttons"] > a.confirm-button-ok { +margin:0 2% 0 0; +background:#32c682;} + +[id^=NotiflixConfirmWrap] > div[class*="-content"] > div[class*="-buttons"] > a.confirm-button-cancel { +margin:0 0 0 2%; +background:#a9a9a9;} + +[id^=NotiflixConfirmWrap] > div[class*="-content"] > div[class*="-buttons"] > a.full { +margin:0; +width:100%;} + +[id^=NotiflixConfirmWrap] > div[class*="-content"] > div[class*="-buttons"] > a:hover { +box-shadow:inset 0 -60px 5px -5px rgba(0, 0, 0, 0.25);} +/* Notiflix: Confirm content off */ + +/* Notiflix: Confirm rtl on */ +[id^=NotiflixConfirmWrap].rtl-on > div[class*="-content"] > div[class*="-buttons"], +[id^=NotiflixConfirmWrap].rtl-on > div[class*="-content"] > div[class*="-buttons"] > a { +transform:rotateY(180deg);} +/* Notiflix: Confirm rtl off */ + +/* Notiflix: Confirm overlay animation => fade on */ +[id^=NotiflixConfirmWrap] > div[class*="-overlay"].with-animation { +animation: confirm-overlay-animation .3s ease-in-out 0s normal; +-webkit-animation: confirm-overlay-animation .3s ease-in-out 0s normal;} + +@keyframes confirm-overlay-animation { +0% {opacity:0;} +100% {opacity:1;} +} + +@-webkit-keyframes confirm-overlay-animation { +0% {opacity:0;} +100% {opacity:1;} +} +/* Notiflix: Confirm overlay animation => fade off */ + +/* Notiflix: Confirm overlay animation remove => fade on */ +[id^=NotiflixConfirmWrap].remove > div[class*="-overlay"].with-animation { +opacity:0; +animation: confirm-overlay-animation-remove .3s ease-in-out 0s normal; +-webkit-animation: confirm-overlay-animation-remove .3s ease-in-out 0s normal;} + +@keyframes confirm-overlay-animation-remove { +0% {opacity:1;} +100% {opacity:0;} +} + +@-webkit-keyframes confirm-overlay-animation-remove { +0% {opacity:1;} +100% {opacity:0;} +} +/* Notiflix: Confirm overlay animation remove => fade off */ + +/* Notiflix: Confirm content animation => fade on */ +[id^=NotiflixConfirmWrap].with-animation.nx-fade > div[class*="-content"] { +animation: confirm-animation-fade .3s ease-in-out 0s normal; +-webkit-animation: confirm-animation-fade .3s ease-in-out 0s normal;} + +@keyframes confirm-animation-fade { +0% {opacity:0;} +100% {opacity:1;} +} + +@-webkit-keyframes confirm-animation-fade { +0% {opacity:0;} +100% {opacity:1;} +} +/* Notiflix: Confirm content animation => fade off */ + +/* Notiflix: Confirm content animation => zoom on */ +[id^=NotiflixConfirmWrap].with-animation.nx-zoom > div[class*="-content"] { +animation: confirm-animation-zoom .3s ease-in-out 0s normal; +-webkit-animation: confirm-animation-zoom .3s ease-in-out 0s normal;} + +@keyframes confirm-animation-zoom { +0% {opacity:0; transform:scale(0.5);} +50% {opacity:1; transform:scale(1.05);} +100% {opacity:1; transform:scale(1);} +} + +@-webkit-keyframes confirm-animation-zoom { +0% {opacity:0; transform:scale(0.5);} +50% {opacity:1; transform:scale(1.05);} +100% {opacity:1; transform:scale(1);} +} +/* Notiflix: Confirm content animation => zoom off */ + +/* Notiflix: Confirm content animation remove => fade on */ +[id^=NotiflixConfirmWrap].with-animation.nx-fade.remove > div[class*="-content"] { +opacity:0; +animation: confirm-animation-fade-remove .3s ease-in-out 0s normal; +-webkit-animation: confirm-animation-fade-remove .3s ease-in-out 0s normal;} + +@keyframes confirm-animation-fade-remove { +0% {opacity:1;} +100% {opacity:0;} +} + +@-webkit-keyframes confirm-animation-fade-remove { +0% {opacity:1;} +100% {opacity:0;} +} +/* Notiflix: Confirm content animation remove => fade off */ + +/* Notiflix: Confirm content animation remove => zoom on */ +[id^=NotiflixConfirmWrap].with-animation.nx-zoom.remove > div[class*="-content"] { +opacity:0; +animation: confirm-animation-zoom-remove .3s ease-in-out 0s normal; +-webkit-animation: confirm-animation-zoom-remove .3s ease-in-out 0s normal;} + +@keyframes confirm-animation-zoom-remove { +0% {opacity:1; transform:scale(1);} +50% {opacity:0.5; transform:scale(1.05);} +100% {opacity:0; transform:scale(0);} +} + +@-webkit-keyframes confirm-animation-zoom-remove { +0% {opacity:1; transform:scale(1);} +50% {opacity:0.5; transform:scale(1.05);} +100% {opacity:0; transform:scale(0);} +} +/* Notiflix: Confirm content animation remove => zoom off */ + + +/* Notiflix: Loading wrap on */ +[id^=NotiflixLoadingWrap] { +-webkit-user-select: none; +-moz-user-select: none; +-ms-user-select: none; +user-select: none; +position: fixed; +z-index: 4000; +width: 100%; +height: 100%; +left: 0; +top: 0; +right:0; +bottom:0; +margin:auto; +text-align: center; +box-sizing:border-box; +background: white!important; +font-family: "Quicksand", sans-serif;} + +[id^=NotiflixLoadingWrap] * { +box-sizing:border-box;} + +[id^=NotiflixLoadingWrap].click-to-close { +cursor:pointer;} +/* Notiflix: Loading wrap off */ + +/* Notiflix: Loading content on */ +[id^=NotiflixLoadingWrap] > div[class*="-icon"] { +width:60px; +height:60px; +position:fixed; +background-color: white!important; +transition:top .2s ease-in-out; +left: 0; +top: 0; +right:0; +bottom:0; +margin:auto;} + +[id^=NotiflixLoadingWrap] > div[class*="-icon"] img, +[id^=NotiflixLoadingWrap] > div[class*="-icon"] svg { +max-width:unset; +max-height:unset; +width: 100%; +height: 100%; +position:absolute; +left: 0; +top: 0;} + +[id^=NotiflixLoadingWrap] > div[class*="-icon"].with-message { +top:-42px;} + +[id^=NotiflixLoadingWrap] > p { +position: fixed; +left: 0; +right: 0; +top: 42px; +bottom: 0; +margin: auto; +font-family: inherit !important; +font-weight: 500; +line-height: 1.4; +padding: 0 10px; +width: 100%; +font-size:15px; +height: 18px;} +/* Notiflix: Loading content off */ + +/* Notiflix: Loading animation => fade on */ +[id^=NotiflixLoadingWrap].with-animation { +animation: loading-animation-fade .3s ease-in-out 0s normal; +-webkit-animation: loading-animation-fade .3s ease-in-out 0s normal;} + +@keyframes loading-animation-fade { +0% {opacity:0;} +100% {opacity:1;} +} + +@-webkit-keyframes loading-animation-fade { +0% {opacity:0;} +100% {opacity:1;} +} +/* Notiflix: Loading animation => fade off */ + +/* Notiflix: Loading animation remove => fade on */ +[id^=NotiflixLoadingWrap].with-animation.remove { +opacity:0; +animation: loading-animation-fade-remove .3s ease-in-out 0s normal; +-webkit-animation: loading-animation-fade-remove .3s ease-in-out 0s normal;} + +@keyframes loading-animation-fade-remove { +0% {opacity:1;} +100% {opacity:0;} +} + +@-webkit-keyframes loading-animation-fade-remove { +0% {opacity:1;} +100% {opacity:0;} +} +/* Notiflix: Loading animation remove => fade off */ + +/* Notiflix: Loading animation new message => fade on */ +[id^=NotiflixLoadingWrap] > p.new { +animation: loading-new-message-fade .3s ease-in-out 0s normal; +-webkit-animation: loading-new-message-fade .3s ease-in-out 0s normal;} + +@keyframes loading-new-message-fade { +0% {opacity:0;} +100% {opacity:1;} +} + +@-webkit-keyframes loading-new-message-fade { +0% {opacity:0;} +100% {opacity:1;} +} +/* Notiflix: Loading animation new message => fade off */ + + +/* Notiflix: Block wrap on */ +[id^=NotiflixBlockWrap] { +-webkit-user-select: none; +-moz-user-select: none; +-ms-user-select: none; +user-select: none; +box-sizing: border-box; +position: absolute; +z-index: 1000; +font-family: "Quicksand", sans-serif; +background: rgba(255, 255, 255, 0.9); +text-align: center; +animation-duration: 400ms; +width: 100%; +height: 100%; +left: 0; +top: 0; +border-radius: inherit;} + +[id^=NotiflixBlockWrap] * { +box-sizing: border-box;} +/* Notiflix: Block wrap off */ + +/* Notiflix: Block content on */ +[id^=NotiflixBlockWrap] > span[class*="-icon"] { +width: 45px; +height: 45px; +position: absolute; +left: 0; +top: 0; +right: 0; +bottom: 0; +margin: auto;} + +[id^=NotiflixBlockWrap] > span[class*="-message"] { +position: absolute; +left: 0; +right: 0; +top: 50px; +bottom: 0; +margin: auto; +font-family: inherit !important; +font-weight: 500; +font-size: 14px; +line-height: 1.4; +padding: 0 10px; +width: 100%; +height: 20px; +overflow: hidden;} +/* Notiflix: Block content off */ + +/* Notiflix: Block animation => fade on */ +[id^=NotiflixBlockWrap].with-animation { +animation: block-animation-fade .3s ease-in-out 0s normal; +-webkit-animation: block-animation-fade .3s ease-in-out 0s normal;} + +@keyframes block-animation-fade { +0% {opacity: 0;} +100% {opacity: 1;} +} + +@-webkit-keyframes block-animation-fade { +0% {opacity: 0;} +100% {opacity: 1;} +} +/* Notiflix: Block animation => fade off */ + +/* Notiflix: Block animation remove => fade on */ +[id^=NotiflixBlockWrap].with-animation.remove { +opacity: 0; +animation: block-animation-fade-remove .3s ease-in-out 0s normal; +-webkit-animation: block-animation-fade-remove .3s ease-in-out 0s normal;} + +@keyframes block-animation-fade-remove { +0% {opacity: 1;} +100% {opacity: 0;} +} + +@-webkit-keyframes block-animation-fade-remove { +0% {opacity: 1;} +100% {opacity: 0;} +} +/* Notiflix: Block animation remove => fade off */ + diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/menu.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/menu.css new file mode 100644 index 0000000000000000000000000000000000000000..d0345ba06a4a7793fee7e699c22ed2862c227eba --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/menu.css @@ -0,0 +1,267 @@ +.pear-nav-tree { + width: 230px; + border-radius: 0px; + background-color: #001529; +} + +.pear-nav-tree .layui-nav-item>a { + height: 56px; + line-height: 56px; + padding-top: 0px; + padding-bottom: 0px; +} + +.pear-nav-tree .layui-nav-item dd a { + height: 48px; + line-height: 48px; +} + +.pear-nav-tree .layui-nav-item>a .layui-nav-more { + padding: 0px; +} + +.pear-side-scroll::-webkit-scrollbar { + width: 0px; + height: 0px; +} +.pear-side-scroll{ + width: 230px; +} + +.pear-nav-tree .layui-nav-child dd.layui-this, +.layui-nav-tree .layui-nav-child dd.layui-this a, +.layui-nav-tree .layui-this, +.layui-nav-tree .layui-this>a, +.layui-nav-tree .layui-this>a:hover { + background-color: #5FB878; +} + +.pear-nav-tree .toast { + font-size: 14px; + margin: 5px; + margin-right: 8px; + text-align: center; + height: 40px; + line-height: 40px; + color: lightgray; +} + + +.pear-nav-tree .layui-nav-item a i { + margin-right: 12px; +} + +.pear-nav-tree .layui-nav-item a span { + letter-spacing: 2px; + font-size: 13.5px; +} + +.pear-nav-tree .layui-nav-item a:hover { + background-color: transparent; +} + +.pear-nav-tree .layui-nav-more { + margin-right: 5px; +} + +.pear-nav-tree .layui-nav-bar { + display: none; +} + +.pear-nav-tree .layui-nav-item a .layui-badge-dot { + float: right; + right: 13px; +} + +.pear-nav-tree .layui-nav-item a .layui-badge { + float: right; + right: 10px; +} + +/** 实 现 菜 单 隐 藏 */ +.pear-nav-mini { + overflow: hidden; +} + +.pear-nav-mini .layui-nav-item a span { + display: none; +} + +.pear-nav-mini .layui-nav-child { + display: none; +} + +.pear-nav-mini .layui-nav-more { + display: none !important; +} + +.pear-nav-control.pc a { + font-weight: 500; + font-size: 14px; +} + +.pear-nav-control.pc li{ + display: inline-block; +} + +.pear-nav-control.pc .layui-nav-bar { + top: 0px !important; +} + +.pear-nav-control.pc .layui-this * { + background-color: whitesmoke; +} + +.pear-nav-control.pc *{ + color: darkslategray!important; +} + +.pear-nav-control.pc .layui-nav-bar{ + display: none!important; +} + +.pear-nav-control .layui-nav-child{ + border: 1px solid whitesmoke; + border-radius: 6px; + width: 150px; +} + +/** 隐 藏 后 子 级 悬 浮 菜 单 */ +.pear-nav-tree .layui-nav-hover { + position: fixed; + min-width: 130px; + padding: 4px; + display: block !important; + background: transparent !important; +} +.pear-nav-tree .layui-nav-hover:before { + content: ''; + position: absolute; + right: 4px; + left: 4px; + bottom: 0; + top: 0; + border-radius: 4px; + overflow: hidden; + background-color: #001529; + display: block; + box-shadow: 0px 0px 3px lightgray; +} +.pear-nav-tree .layui-nav-hover a span { + display: inline-block !important; +} +.pear-nav-tree .layui-nav-hover a i { + display: none; +} +.pear-nav-tree .layui-nav-child dd a span { + margin-left: 26px !important; +} +.pear-nav-tree .layui-nav-child dd a i { + display: none; +} +.pear-nav-tree .layui-nav-hover dd a span { + margin-left: 0px !important; +} +.pear-nav-tree dl { + padding-top: 0; + padding-bottom: 0; +} +/** 亮 样 式*/ +.dark-theme .layui-nav-tree{ + background-color: #001529!important; +} + +.light-theme{ + background-color: white!important; +} + +.light-theme .pear-nav-tree, +.light-theme .pear-nav-tree .layui-nav-hover:before, +.light-theme .pear-nav-tree .layui-nav-child{ + background-color: white!important; +} + +.light-theme .pear-nav-tree a, +.light-theme .pear-nav-tree .layui-nav-more{ + color: dimgray!important; + border-top-color: dimgray; +} + +.light-theme .pear-nav-tree .layui-nav-itemed>a>.layui-nav-more{ + border-top-color: white!important; + border-bottom-color: dimgray!important; +} + +.light-theme .pear-nav-tree .layui-this a, +.light-theme .pear-nav-tree .layui-this{ + color: white!important; + background-color: #5FB878!important; + +} + +.light-theme .pear-nav-tree .layui-this a:hover{ + background-color: #5FB878!important; + +} + +.light-theme .pear-nav-tree .layui-nav-bar{ + display: none; + +} + +/** 下 拉 图 标 */ +.pear-nav-tree.arrow .layui-nav-more { + font-family: layui-icon !important; + font-size: 10px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + overflow: hidden; + width: auto; + height: auto; + line-height: normal; + border: none; + top: 23px; + margin-right: 2px !important; + margin: 0; + padding: 0; + display: inline-block; + transition: all .2s; + -webkit-transition: all .2s; +} + +.pear-nav-tree.arrow .layui-nav-child .layui-nav-more { + top: 17px; +} + +.pear-nav-tree.arrow .layui-nav-more:before { + content: "\e61a"; +} + +.pear-nav-tree.arrow .layui-nav-itemed>a>.layui-nav-more { + transform: rotate(180deg); + -ms-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -o-transform: rotate(180deg); + width: 12px; + text-align: center; +} +.pear-nav-tree.arrow .layui-nav-child.layui-nav-hover>dd>a>.layui-nav-more { + display: inline-block !important; + transform: rotate(270deg); + -ms-transform: rotate(270deg); + -moz-transform: rotate(270deg); + -webkit-transform: rotate(270deg); + -o-transform: rotate(270deg); + width: 12px; + text-align: center; + background-color: transparent !important; +} + +.pear-nav-tree.arrow .layui-nav-child.layui-nav-hover>a>.layui-nav-more:before, +.pear-nav-tree.arrow .layui-nav-itemed>a>.layui-nav-more:before { + content: '\e61a'; + display: inline-block; + vertical-align: middle; +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/message.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/message.css new file mode 100644 index 0000000000000000000000000000000000000000..0a61d092a45c05a5ee8c0d3fb52150f9aaeb40ea --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/message.css @@ -0,0 +1,133 @@ +.pear-notice .layui-this { + color: #5FB878 !important; + font-weight: 500; +} + +.pear-notice { + box-shadow: 0 6px 16px -8px rgb(0 0 0 / 8%), 0 9px 28px 0 rgb(0 0 0 / 5%), 0 12px 48px 16px rgb(0 0 0 / 3%)!important; +} + +.pear-notice .layui-tab-title { + display: flex; + text-align: center; + border-right: 1px solid whitesmoke; +} + +.pear-notice .layui-tab-title li { + flex: 1; + text-align: center; + border-right: 1px solid whitesmoke; +} +/*排除最后一个 li 右边框*/ +.pear-notice .layui-tab-title li:last-child { + border-right: none; +} + +.pear-notice * { + color: dimgray !important; +} + +.pear-notice { + width: 360px !important; +} + +.pear-notice img { + margin-left: 8px; + width: 33px !important; + height: 33px !important; + border-radius: 50px; + margin-right: 15px; +} + +.pear-notice-item { + height: 45px !important; + line-height: 45px !important; + padding-right: 20px; + padding-left: 20px; + border-bottom: 1px solid whitesmoke; + padding-top: 10px; + padding-bottom: 15px; +} +.pear-notice-end { + float: right; + right: 10px; +} + +.pear-notice-item span{ + height: 40px; + line-height: 40px; +} + +/** 滚动条样式 */ +.pear-notice *::-webkit-scrollbar { + width: 0px; + height: 0px; +} + +.pear-notice *::-webkit-scrollbar-track { + background: white; + border-radius: 2px; +} + +.pear-notice *::-webkit-scrollbar-thumb { + background: #E6E6E6; + border-radius: 2px; +} + +.pear-notice *::-webkit-scrollbar-thumb:hover { + background: #E6E6E6; +} + +.pear-notice *::-webkit-scrollbar-corner { + background: #f6f6f6; +} +/** 增加 empty 样式 */ +.pear-empty { + font-size: 14px; + line-height: 1.5715; + min-height: 200px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} +.pear-empty-normal { + margin: 32px 0; + color: #00000040; +} +.pear-empty-normal .pear-empty-image { + height: 40px; +} + +.pear-empty-image { + height: 100px; + margin-bottom: 8px; +} +.pear-empty-image svg { + height: 100%; + margin: auto; +} + +.pear-empty-img-simple-g { + stroke: #d9d9d9; +} +.pear-empty-img-default-g { + fill: #fff; +} +.pear-empty-img-simple-path { + fill: #fafafa; +} +.pear-empty-img-default-path-1 { + fill: #aeb8c2; +} +.pear-empty-img-default-path-2 { + fill: url(#linearGradient-1); +} +.pear-empty-img-default-path-3 { + fill: #f5f5f7; +} +.pear-empty-img-default-path-4, .pear-empty-img-default-path-5 { + fill: #dce0e6; +} + + diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/notice.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/notice.css new file mode 100644 index 0000000000000000000000000000000000000000..65c9feacaae238abc377e560a5d4fa8e619f9b5e --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/notice.css @@ -0,0 +1,228 @@ +.toast-title { + font-weight: bold; +} +.toast-message { + -ms-word-wrap: break-word; + word-wrap: break-word; +} +.toast-message a, +.toast-message label { + color: #FFFFFF; +} +.toast-message a:hover { + color: #CCCCCC; + text-decoration: none; +} +.toast-close-button { + position: relative; + right: -0.3em; + top: -0.3em; + float: right; + font-size: 20px; + font-weight: bold; + color: #FFFFFF; + -webkit-text-shadow: 0 1px 0 #ffffff; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.8; + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); + filter: alpha(opacity=80); + line-height: 1; +} +.toast-close-button:hover, +.toast-close-button:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); + filter: alpha(opacity=40); +} +.rtl .toast-close-button { + left: -0.3em; + float: left; + right: 0.3em; +} +/*Additional properties for button version + iOS requires the button element instead of an anchor tag. + If you want the anchor version, it requires `href="#"`.*/ +button.toast-close-button { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.toast-top-center { + top: 0; + right: 0; + width: 100%; +} +.toast-bottom-center { + bottom: 0; + right: 0; + width: 100%; +} +.toast-top-full-width { + top: 0; + right: 0; + width: 100%; +} +.toast-bottom-full-width { + bottom: 0; + right: 0; + width: 100%; +} +.toast-top-left { + top: 12px; + left: 12px; +} +.toast-top-right { + top: 12px; + right: 12px; +} +.toast-bottom-right { + right: 12px; + bottom: 12px; +} +.toast-bottom-left { + bottom: 12px; + left: 12px; +} +#toast-container { + position: fixed; + z-index: 999999; + pointer-events: none; + /*overrides*/ +} +#toast-container * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +#toast-container > div { + position: relative; + pointer-events: auto; + overflow: hidden; + margin: 0 0 6px; + padding: 15px 15px 15px 50px; + width: 300px; + -moz-border-radius: 3px 3px 3px 3px; + -webkit-border-radius: 3px 3px 3px 3px; + border-radius: 3px 3px 3px 3px; + background-position: 15px center; + background-repeat: no-repeat; + -moz-box-shadow: 0 0 12px #999999; + -webkit-box-shadow: 0 0 12px #999999; + box-shadow: 0 0 12px #999999; + color: #FFFFFF; + opacity: 0.8; + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); + filter: alpha(opacity=80); +} +#toast-container > div.rtl { + direction: rtl; + padding: 15px 50px 15px 15px; + background-position: right 15px center; +} +#toast-container > div:hover { + -moz-box-shadow: 0 0 12px #000000; + -webkit-box-shadow: 0 0 12px #000000; + box-shadow: 0 0 12px #000000; + opacity: 1; + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); + filter: alpha(opacity=100); + cursor: pointer; +} +#toast-container > .toast-info { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important; +} +#toast-container > .toast-error { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important; +} +#toast-container > .toast-success { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important; +} +#toast-container > .toast-warning { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important; +} +#toast-container.toast-top-center > div, +#toast-container.toast-bottom-center > div { + width: 300px; + margin-left: auto; + margin-right: auto; +} +#toast-container.toast-top-full-width > div, +#toast-container.toast-bottom-full-width > div { + width: 96%; + margin-left: auto; + margin-right: auto; +} +.toast { + background-color: #030303; +} +.toast-success { + background-color: #51A351; +} +.toast-error { + background-color: #BD362F; +} +.toast-info { + background-color: #2F96B4; +} +.toast-warning { + background-color: #F89406; +} +.toast-progress { + position: absolute; + left: 0; + bottom: 0; + height: 4px; + background-color: #000000; + opacity: 0.4; + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); + filter: alpha(opacity=40); +} +/*Responsive Design*/ +@media all and (max-width: 240px) { + #toast-container > div { + padding: 8px 8px 8px 50px; + width: 11em; + } + #toast-container > div.rtl { + padding: 8px 50px 8px 8px; + } + #toast-container .toast-close-button { + right: -0.2em; + top: -0.2em; + } + #toast-container .rtl .toast-close-button { + left: -0.2em; + right: 0.2em; + } +} +@media all and (min-width: 241px) and (max-width: 480px) { + #toast-container > div { + padding: 8px 8px 8px 50px; + width: 18em; + } + #toast-container > div.rtl { + padding: 8px 50px 8px 8px; + } + #toast-container .toast-close-button { + right: -0.2em; + top: -0.2em; + } + #toast-container .rtl .toast-close-button { + left: -0.2em; + right: 0.2em; + } +} +@media all and (min-width: 481px) and (max-width: 768px) { + #toast-container > div { + padding: 15px 15px 15px 50px; + width: 25em; + } + #toast-container > div.rtl { + padding: 15px 50px 15px 15px; + } +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/nprogress.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/nprogress.css new file mode 100644 index 0000000000000000000000000000000000000000..24c5cf192b81ef4523001c04086c6adf826bb4e5 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/nprogress.css @@ -0,0 +1,73 @@ +/* Make clicks pass-through */ +#nprogress { + pointer-events: none; +} + +#nprogress .bar { + background: #29d; + + position: fixed; + z-index: 999999; + top: 0; + left: 0; + + width: 100%; + height: 2px; +} + +/* Fancy blur effect */ +#nprogress .peg { + display: block; + position: absolute; + right: 0px; + width: 100px; + height: 100%; + box-shadow: 0 0 10px #29d, 0 0 5px #29d; + opacity: 1.0; + + -webkit-transform: rotate(3deg) translate(0px, -4px); + -ms-transform: rotate(3deg) translate(0px, -4px); + transform: rotate(3deg) translate(0px, -4px); +} + +/* Remove these to get rid of the spinner */ +#nprogress .spinner { + display: block; + position: fixed; + z-index: 1031; + top: 15px; + right: 15px; +} + +#nprogress .spinner-icon { + width: 18px; + height: 18px; + box-sizing: border-box; + + border: solid 2px transparent; + border-top-color: #29d; + border-left-color: #29d; + border-radius: 50%; + + -webkit-animation: nprogress-spinner 400ms linear infinite; + animation: nprogress-spinner 400ms linear infinite; +} + +.nprogress-custom-parent { + overflow: hidden; + position: relative; +} + +.nprogress-custom-parent #nprogress .spinner, +.nprogress-custom-parent #nprogress .bar { + position: absolute; +} + +@-webkit-keyframes nprogress-spinner { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} +@keyframes nprogress-spinner { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/popover.min.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/popover.min.css new file mode 100644 index 0000000000000000000000000000000000000000..453a50fad00258cd432ec6a0a58b3634c7335ffe --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/popover.min.css @@ -0,0 +1 @@ +.webui-popover-content{display:none}.webui-popover-rtl{direction:rtl;text-align:right}.webui-popover{position:absolute;top:0;left:0;z-index:9999;display:none;min-width:50px;min-height:32px;padding:1px;text-align:left;white-space:normal;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.webui-popover.top,.webui-popover.top-left,.webui-popover.top-right{margin-top:-10px}.webui-popover.right,.webui-popover.right-top,.webui-popover.right-bottom{margin-left:10px}.webui-popover.bottom,.webui-popover.bottom-left,.webui-popover.bottom-right{margin-top:10px}.webui-popover.left,.webui-popover.left-top,.webui-popover.left-bottom{margin-left:-10px}.webui-popover.pop{-webkit-transform:scale(0.8);-o-transform:scale(0.8);transform:scale(0.8);-webkit-transition:transform .15s cubic-bezier(0.3,0,0,1.5);-o-transition:transform .15s cubic-bezier(0.3,0,0,1.5);transition:transform .15s cubic-bezier(0.3,0,0,1.5);opacity:0;filter:alpha(opacity=0)}.webui-popover.pop-out{-webkit-transition-property:"opacity,transform";-o-transition-property:"opacity,transform";transition-property:"opacity,transform";-webkit-transition:.15s linear;-o-transition:.15s linear;transition:.15s linear;opacity:0;filter:alpha(opacity=0)}.webui-popover.fade,.webui-popover.fade-out{-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear;opacity:0;filter:alpha(opacity=0)}.webui-popover.out{opacity:0;filter:alpha(opacity=0)}.webui-popover.in{-webkit-transform:none;-o-transform:none;transform:none;opacity:1;filter:alpha(opacity=100)}.webui-popover .webui-popover-content{padding:9px 14px;overflow:auto;display:block}.webui-popover .webui-popover-content>div:first-child{width:99%}.webui-popover-inner .close{font-family:arial;margin:8px 10px 0 0;float:right;font-size:16px;font-weight:700;line-height:16px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20);text-decoration:none}.webui-popover-inner .close:hover,.webui-popover-inner .close:focus{opacity:.5;filter:alpha(opacity=50)}.webui-popover-inner .close:after{content:"\00D7";width:.8em;height:.8em;padding:4px;position:relative}.webui-popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:700;line-height:18px;background-color:#fff;border-bottom:1px solid #f2f2f2;border-radius:5px 5px 0 0}.webui-popover-content{padding:9px 14px;overflow:auto;display:none}.webui-popover-inverse{background-color:#333;color:#eee}.webui-popover-inverse .webui-popover-title{background:#333;border-bottom:1px solid #3b3b3b;color:#eee}.webui-no-padding .webui-popover-content{padding:0}.webui-no-padding .list-group-item{border-right:none;border-left:none}.webui-no-padding .list-group-item:first-child{border-top:0}.webui-no-padding .list-group-item:last-child{border-bottom:0}.webui-popover>.webui-arrow,.webui-popover>.webui-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.webui-popover>.webui-arrow{border-width:11px}.webui-popover>.webui-arrow:after{border-width:10px;content:""}.webui-popover.top>.webui-arrow,.webui-popover.top-right>.webui-arrow,.webui-popover.top-left>.webui-arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.webui-popover.top>.webui-arrow:after,.webui-popover.top-right>.webui-arrow:after,.webui-popover.top-left>.webui-arrow:after{content:" ";bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.webui-popover.right>.webui-arrow,.webui-popover.right-top>.webui-arrow,.webui-popover.right-bottom>.webui-arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.webui-popover.right>.webui-arrow:after,.webui-popover.right-top>.webui-arrow:after,.webui-popover.right-bottom>.webui-arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.webui-popover.bottom>.webui-arrow,.webui-popover.bottom-right>.webui-arrow,.webui-popover.bottom-left>.webui-arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);border-top-width:0}.webui-popover.bottom>.webui-arrow:after,.webui-popover.bottom-right>.webui-arrow:after,.webui-popover.bottom-left>.webui-arrow:after{content:" ";top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.webui-popover.left>.webui-arrow,.webui-popover.left-top>.webui-arrow,.webui-popover.left-bottom>.webui-arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.webui-popover.left>.webui-arrow:after,.webui-popover.left-top>.webui-arrow:after,.webui-popover.left-bottom>.webui-arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.webui-popover-inverse.top>.webui-arrow,.webui-popover-inverse.top-left>.webui-arrow,.webui-popover-inverse.top-right>.webui-arrow,.webui-popover-inverse.top>.webui-arrow:after,.webui-popover-inverse.top-left>.webui-arrow:after,.webui-popover-inverse.top-right>.webui-arrow:after{border-top-color:#333}.webui-popover-inverse.right>.webui-arrow,.webui-popover-inverse.right-top>.webui-arrow,.webui-popover-inverse.right-bottom>.webui-arrow,.webui-popover-inverse.right>.webui-arrow:after,.webui-popover-inverse.right-top>.webui-arrow:after,.webui-popover-inverse.right-bottom>.webui-arrow:after{border-right-color:#333}.webui-popover-inverse.bottom>.webui-arrow,.webui-popover-inverse.bottom-left>.webui-arrow,.webui-popover-inverse.bottom-right>.webui-arrow,.webui-popover-inverse.bottom>.webui-arrow:after,.webui-popover-inverse.bottom-left>.webui-arrow:after,.webui-popover-inverse.bottom-right>.webui-arrow:after{border-bottom-color:#333}.webui-popover-inverse.left>.webui-arrow,.webui-popover-inverse.left-top>.webui-arrow,.webui-popover-inverse.left-bottom>.webui-arrow,.webui-popover-inverse.left>.webui-arrow:after,.webui-popover-inverse.left-top>.webui-arrow:after,.webui-popover-inverse.left-bottom>.webui-arrow:after{border-left-color:#333}.webui-popover i.icon-refresh:before{content:""}.webui-popover i.icon-refresh{display:block;width:30px;height:30px;font-size:20px;top:50%;left:50%;position:absolute;margin-left:-15px;margin-right:-15px;background:url(../img/loading.gif) no-repeat}@-webkit-keyframes rotate{100%{-webkit-transform:rotate(360deg)}}@keyframes rotate{100%{transform:rotate(360deg)}}.webui-popover-backdrop{background-color:rgba(0,0,0,.65);width:100%;height:100%;position:fixed;top:0;left:0;z-index:9998}.webui-popover .dropdown-menu{display:block;position:relative;top:0;border:none;box-shadow:none;float:none} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/select.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/select.css new file mode 100644 index 0000000000000000000000000000000000000000..53285a6881bce8189bd05d23e4f2757f31ea8e43 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/select.css @@ -0,0 +1,822 @@ +/* formSelects多选css */ +select[xm-select] { + display: none !important; +} + +.xm-select-parent * { + margin: 0; + padding: 0; + font-family: "Helvetica Neue", Helvetica, "PingFang SC", 微软雅黑, Tahoma, Arial, sans-serif; + box-sizing: initial; +} + +.xm-select-parent { + text-align: left; +} + +.xm-select-parent select { + display: none; +} + +.xm-select-parent .xm-select-title { + position: relative; + min-height: 36px; +} + +.xm-select-parent .xm-input { + cursor: pointer; + border-radius: 2px; + border-width: 1px; + border-style: solid; + border-color: #E6E6E6; + display: block; + width: 100%; + box-sizing: border-box; + background-color: #FFF; + height: 36px; + line-height: 1.3; + padding-left: 10px; + outline: 0 +} + +.xm-select-parent .xm-select-sj { + display: inline-block; + width: 0; + height: 0; + border-style: dashed; + border-color: transparent; + overflow: hidden; + position: absolute; + right: 10px; + top: 50%; + margin-top: -3px; + cursor: pointer; + border-width: 6px; + border-top-color: #C2C2C2; + border-top-style: solid; + transition: all .3s; + -webkit-transition: all .3s +} + +.xm-select-parent .xm-form-selected .xm-select-sj { + margin-top: -9px; + transform: rotate(180deg) +} + +.xm-select-parent .xm-form-select dl { + display: none; + position: absolute; + left: 0; + top: 42px; + padding: 5px 0; + z-index: 999; + min-width: 100%; + border: 1px solid #d2d2d2; + max-height: 300px; + overflow-y: auto; + background-color: #fff; + border-radius: 2px; + box-shadow: 0 2px 4px rgba(0, 0, 0, .12); + box-sizing: border-box; + animation-fill-mode: both; + -webkit-animation-name: layui-upbit; + animation-name: layui-upbit; + -webkit-animation-duration: .3s; + animation-duration: .3s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both +} + +@-webkit-keyframes layui-upbit { + from { + -webkit-transform: translate3d(0, 30px, 0); + opacity: .3 + } + + to { + -webkit-transform: translate3d(0, 0, 0); + opacity: 1 + } +} + +@keyframes layui-upbit { + from { + transform: translate3d(0, 30px, 0); + opacity: .3 + } + + to { + transform: translate3d(0, 0, 0); + opacity: 1 + } +} + +.xm-select-parent .xm-form-selected dl { + display: block +} + +.xm-select-parent .xm-form-select dl dd, +.xm-select-parent .xm-form-select dl dt { + padding: 0 10px; + line-height: 36px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis +} + +.xm-select-parent .xm-form-select dl dd { + cursor: pointer; + height: 36px; +} + +.xm-select-parent .xm-form-select dl dd:hover { + background-color: #f2f2f2 +} + +.xm-select-parent .xm-form-select dl dt { + font-size: 12px; + color: #999 +} + +.layui-select-disabled .xm-dis-disabled { + border-color: #eee !important +} + +.xm-select-parent .xm-form-select dl .xm-select-tips { + padding-left: 10px !important; + color: #999; + font-size: 14px +} + +.xm-unselect { + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none +} + +.xm-form-checkbox { + position: relative; + display: block; + vertical-align: middle; + cursor: pointer; + font-size: 0; + -webkit-transition: .1s linear; + transition: .1s linear; + box-sizing: border-box; + height: auto !important; + line-height: normal !important; + border: none !important; + margin-right: 0; + padding-right: 0; + background: 0 0; +} + +.xm-form-checkbox>i { + color: #FFF; + font-size: 16px; + width: 16px; + height: 16px; + position: absolute; + top: 9px; + border: 1px solid #5FB878; + border-radius: 3px; + z-index: 2; +} + +.xm-form-checkbox:hover>i { + border-color: #5FB878; +} + +.xm-form-checkbox>span { + display: block; + position: relative; + padding: 0 15px 0 30px; + height: 100%; + font-size: 14px; + border-radius: 2px 0 0 2px; + background-color: #d2d2d2; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + background: 0 0; + color: #666; + line-height: 36px; +} + +.xm-select-parent dl { + width: 100%; +} + +.xm-select-parent dl dd { + position: relative; +} + +.xm-select-parent dl dd>i:not(.icon-sousuo) { + position: absolute; + right: 10px; + top: 0; + color: #AAAAAA; +} + +.xm-select-parent dl dd.xm-select-this div i { + border: none; + color: #5FB878; + font-size: 18px; +} + +.xm-select-parent dl dd.xm-select-this div i:after { + content: '\e613'; +} + +.xm-select-parent dl dd.xm-dis-disabled div i { + border-color: #C2C2C2; +} + +.xm-select-parent dl dd.xm-dis-disabled.xm-select-this div i { + color: #C2C2C2; +} + +.xm-select-radio div.xm-form-checkbox>i { + border-radius: 20px; +} + +.xm-select-parent dl.xm-select-radio dd.xm-select-this div i:after { + content: '\e62b'; +} + +.xm-dis-disabled, +.xm-dis-disabled:hover { + cursor: not-allowed !important +} + +.xm-form-select dl dd.xm-dis-disabled { + background-color: #fff !important +} + +.xm-form-select dl dd.xm-dis-disabled span { + color: #C2C2C2 +} + +.xm-form-select dl dd.xm-dis-disabled .xm-icon-yes { + border-color: #C2C2C2 +} + +.xm-select-parent { + position: relative; + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none +} + +.xm-select-parent .xm-select { + line-height: normal; + height: auto; + padding: 4px 10px 1px 10px; + overflow: hidden; + min-height: 36px; + left: 0; + z-index: 99; + position: absolute; + background: 0 0; + padding-right: 20px +} + +.xm-select-parent .xm-select:hover { + border-color: #C0C4CC +} + +.xm-select-parent .xm-select .xm-select-label { + display: inline-block; + margin: 0; + vertical-align: middle +} + +.xm-select-parent .xm-select-title div.xm-select-label>span { + position: relative; + padding: 2px 5px; + background-color: #5FB878; + border-radius: 2px; + color: #FFF; + display: inline-block; + line-height: 18px; + height: 18px; + margin: 2px 5px 2px 0; + cursor: initial; + user-select: none; + font-size: 14px; + padding-right: 25px; + -webkit-user-select: none; +} + +.xm-select-parent .xm-select-title div.xm-select-label>span i { + position: absolute; + margin-left: 8px; + font-size: 12px; + cursor: pointer; + line-height: 20px; +} + +.xm-select-parent .xm-select .xm-select-input { + border: none; + height: 28px; + background-color: transparent; + padding: 0; + vertical-align: middle; + display: inline-block; + width: 50px +} + +.xm-select-parent .xm-select--suffix input { + border: none +} + +.xm-form-selected .xm-select, +.xm-form-selected .xm-select:hover { + border-color: #67c23a !important +} + +.xm-select--suffix+div { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0 +} + +.xm-select-dis .xm-select--suffix+div { + z-index: 100; + cursor: no-drop !important; + opacity: .2; + background-color: #FFF; +} + +.xm-select-disabled, +.xm-select-disabled:hover { + color: #d2d2d2 !important; + cursor: not-allowed !important; + background-color: #fff +} + +.xm-select-none { + display: none; + margin: 5px 0; + text-align: center; +} + +.xm-select-none:hover { + background-color: #FFF !important +} + +.xm-select-empty { + display: block +} + +.xm-span-hide { + display: none !important; +} + +.layui-form-pane .xm-select, +.layui-form-pane .xm-select:hover { + border: none !important; + top: 0px +} + +.layui-form-pane .xm-select-title { + border: 1px solid #e6e6e6 !important +} + +.xm-select-hide { + display: none !important; +} + +div[xm-hg] .xm-select-label { + white-space: nowrap; + overflow: hidden; + position: absolute; + right: 30px; + left: 0; + padding-left: 10px; +} + +/* 颜色相关 */ +div[xm-select-skin] .xm-select-title div.xm-select-label>span { + border: 1px solid #67c23a +} + +div[xm-select-skin] .xm-select-title div.xm-select-label>span i:hover { + opacity: .8; + filter: alpha(opacity=80); + cursor: pointer +} + +div[xm-select-skin=default] .xm-select-title div.xm-select-label>span { + background-color: #F0F2F5; + color: #909399; + border: 1px solid #F0F2F5 +} + +div[xm-select-skin=default] .xm-select-title div.xm-select-label>span i { + color: #C0C4CC +} + +div[xm-select-skin=default] .xm-select-title div.xm-select-label>span i:before { + content: '\e60b'; + font-size: 16px; + margin-left: -3px; +} + +div[xm-select-skin=default] dl dd:not(.xm-dis-disabled) i { + border-color: #5FB878 +} + +div[xm-select-skin=default] dl dd.xm-select-this:not(.xm-dis-disabled) i { + color: #5FB878 +} + +div[xm-select-skin=default].xm-form-selected .xm-select, +div[xm-select-skin=default].xm-form-selected .xm-select:hover { + border-color: #C0C4CC!important +} + +div[xm-select-skin=primary] .xm-select-title div.xm-select-label>span { + background-color: #5FB878!important; + color: #FFF; + border: 1px solid #5FB878!important +} + +div[xm-select-skin=primary] .xm-select-title div.xm-select-label>span i { + background-color: #5FB878!important; + color: #FFF +} + +div[xm-select-skin=primary] dl dd:not(.xm-dis-disabled) i { + border-color: #5FB878!important +} + +div[xm-select-skin=primary] dl dd.xm-select-this:not(.xm-dis-disabled) i { + color: #5FB878!important +} + +div[xm-select-skin=primary].xm-form-selected .xm-select, +div[xm-select-skin=primary].xm-form-selected .xm-select:hover { + border-color: #5FB878!important +} + +div[xm-select-skin=normal] .xm-select-title div.xm-select-label>span { + background-color: #2D8CF0!important; + color: #FFF; + border: 1px solid #2D8CF0!important; +} + +div[xm-select-skin=normal] .xm-select-title div.xm-select-label>span i { + background-color: #2D8CF0!important; + color: #FFF +} + +div[xm-select-skin=normal] dl dd:not(.xm-dis-disabled) i { + border-color: #2D8CF0!important; +} + +div[xm-select-skin=normal] dl dd.xm-select-this:not(.xm-dis-disabled) i { + color:#2D8CF0 !important; +} + +div[xm-select-skin=normal].xm-form-selected .xm-select, +div[xm-select-skin=normal].xm-form-selected .xm-select:hover { + border-color:#2D8CF0!important; +} + +div[xm-select-skin=warm] .xm-select-title div.xm-select-label>span { + background-color: #e6a23c!important; + color: #FFF; + border: 1px solid #e6a23c!important; +} + +div[xm-select-skin=warm] .xm-select-title div.xm-select-label>span i { + background-color: #e6a23c!important; + color: #FFF +} + +div[xm-select-skin=warm] dl dd:not(.xm-dis-disabled) i { + border-color:#e6a23c!important +} + +div[xm-select-skin=warm] dl dd.xm-select-this:not(.xm-dis-disabled) i { + color:#e6a23c!important +} + +div[xm-select-skin=warm].xm-form-selected .xm-select, +div[xm-select-skin=warm].xm-form-selected .xm-select:hover { + border-color: #e6a23c!important +} + +div[xm-select-skin=danger] .xm-select-title div.xm-select-label>span { + background-color: #f56c6c!important; + color: #FFF; + border: 1px solid #f56c6c!important; +} + +div[xm-select-skin=danger] .xm-select-title div.xm-select-label>span i { + background-color:#f56c6c!important; + color: #FFF +} + +div[xm-select-skin=danger] dl dd:not(.xm-dis-disabled) i { + border-color: #f56c6c!important +} + +div[xm-select-skin=danger] dl dd.xm-select-this:not(.xm-dis-disabled) i { + color: #f56c6c!important +} + +div[xm-select-skin=danger].xm-form-selected .xm-select, +div[xm-select-skin=danger].xm-form-selected .xm-select:hover { + border-color: #f56c6c!important +} + + +/* 多选联动 */ +.xm-select-parent .layui-form-danger+.xm-select-title .xm-select { + border-color: #f56c6c!important +} + +.xm-select-linkage li { + padding: 10px 0px; + cursor: pointer; +} + +.xm-select-linkage li span { + padding-left: 20px; + padding-right: 30px; + display: inline-block; + height: 20px; + overflow: hidden; + text-overflow: ellipsis; +} + +.xm-select-linkage li.xm-select-this span { + border-left: 5px solid #009688; + color: #009688; + padding-left: 15px; +} + +.xm-select-linkage-group { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + overflow-x: hidden; + overflow-y: auto; +} + +.xm-select-linkage-group li:hover { + border-left: 1px solid #009688; +} + +.xm-select-linkage-group li:hover span { + padding-left: 19px; +} + +.xm-select-linkage-group li.xm-select-this:hover span { + padding-left: 15px; + border-left-width: 4px; +} + +.xm-select-linkage-group:nth-child(4n+1) { + background-color: #EFEFEF; + left: 0; +} + +.xm-select-linkage-group:nth-child(4n+1) li.xm-select-active { + background-color: #F5F5F5; +} + +.xm-select-linkage-group:nth-child(4n+2) { + background-color: #F5F5F5; + left: 100px; +} + +.xm-select-linkage-group:nth-child(4n+3) li.xm-select-active { + background-color: #FAFAFA; +} + +.xm-select-linkage-group:nth-child(4n+3) { + background-color: #FAFAFA; + left: 200px; +} + +.xm-select-linkage-group:nth-child(4n+3) li.xm-select-active { + background-color: #FFFFFF; +} + +.xm-select-linkage-group:nth-child(4n+4) { + background-color: #FFFFFF; + left: 300px; +} + +.xm-select-linkage-group:nth-child(4n+4) li.xm-select-active { + background-color: #EFEFEF; +} + +.xm-select-linkage li { + list-style: none; +} + +.xm-select-linkage-hide { + display: none; +} + +.xm-select-linkage-show { + display: block; +} + +div[xm-select-skin='default'] .xm-select-linkage li.xm-select-this span { + border-left-color: #5FB878; + color: #5FB878; +} + +div[xm-select-skin='default'] .xm-select-linkage-group li:hover { + border-left-color: #5FB878; +} + +div[xm-select-skin='primary'] .xm-select-linkage li.xm-select-this span { + border-left-color: #1E9FFF; + color: #1E9FFF; +} + +div[xm-select-skin='primary'] .xm-select-linkage-group li:hover { + border-left-color: #1E9FFF; +} + +div[xm-select-skin='normal'] .xm-select-linkage li.xm-select-this span { + border-left-color: #1E9FFF; + color: #1E9FFF; +} + +div[xm-select-skin='normal'] .xm-select-linkage-group li:hover { + border-left-color: #1E9FFF; +} + +div[xm-select-skin='warm'] .xm-select-linkage li.xm-select-this span { + border-left-color: #FFB800; + color: #FFB800; +} + +div[xm-select-skin='warm'] .xm-select-linkage-group li:hover { + border-left-color: #FFB800; +} + +div[xm-select-skin='danger'] .xm-select-linkage li.xm-select-this span { + border-left-color: #FF5722; + color: #FF5722; +} + +div[xm-select-skin='danger'] .xm-select-linkage-group li:hover { + border-left-color: #FF5722; +} + + +/* 快捷操作 */ +.xm-select-tips[style]:hover { + background-color: #FFF !important; +} + +.xm-select-parent dd>.xm-cz { + position: absolute; + top: 0px; + right: 10px; +} + +.xm-select-parent dd>.xm-cz-group { + margin-right: 30px; + border-right: 2px solid #ddd; + height: 16px; + margin-top: 10px; + line-height: 16px; + overflow: hidden; +} + +.xm-select-parent dd>.xm-cz-group .xm-cz { + display: inline-block; + margin-right: 30px; +} + +.xm-select-parent dd>.xm-cz-group .xm-cz i { + margin-right: 10px; +} + +.xm-select-parent dd>.xm-cz-group[show='name'] .xm-cz i { + display: none; +} + +.xm-select-parent dd>.xm-cz-group[show='icon'] .xm-cz span { + display: none; +} + +.xm-select-parent dd .xm-cz:hover { + color: #009688; +} + +div[xm-select-skin='default'] dd .xm-cz:hover { + color: #C0C4CC; +} + +div[xm-select-skin='primary'] dd .xm-cz:hover { + color: #009688; +} + +div[xm-select-skin='normal'] dd .xm-cz:hover { + color: #1E9FFF; +} + +div[xm-select-skin='warm'] dd .xm-cz:hover { + color: #FFB800; +} + +div[xm-select-skin='danger'] dd .xm-cz:hover { + color: #FF5722; +} + +.xm-select-tips .xm-input { + border: none; + border-bottom: 1px solid #E6E6E6; + padding-left: 27px; +} + +.xm-select-tips .icon-sousuo { + position: absolute; +} + +.xm-select-tips.xm-dl-input { + display: none; +} + +div[xm-select-search-type="1"] .xm-select-tips.xm-dl-input { + display: block; +} + +div[xm-select-search-type="1"] .xm-select .xm-select-input { + display: none !important; +} + +@font-face { + font-family: "xm-iconfont"; + src: url('//at.alicdn.com/t/font_792691_qxv28s6g1l9.eot?t=1534240067831'); + /* IE9*/ + src: url('//at.alicdn.com/t/font_792691_qxv28s6g1l9.eot?t=1534240067831#iefix') format('embedded-opentype'), + /* IE6-IE8 */ + url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAsYAAsAAAAAEQwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFY8ukovY21hcAAAAYAAAACrAAACPBtV6wxnbHlmAAACLAAABnEAAAmMovtEvWhlYWQAAAigAAAAMQAAADYSctBCaGhlYQAACNQAAAAgAAAAJAgBA69obXR4AAAI9AAAABsAAAAwMCX//WxvY2EAAAkQAAAAGgAAABoN8gwubWF4cAAACSwAAAAeAAAAIAEiAM9uYW1lAAAJTAAAAUUAAAJtPlT+fXBvc3QAAAqUAAAAhAAAALJ1LunfeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2BkYWacwMDKwMHUyXSGgYGhH0IzvmYwYuRgYGBiYGVmwAoC0lxTGByeMbwwZ27438AQw9zMcAQozAiSAwDk4AxmeJzlks0JwzAMhZ8bN/1xD4GU0h2Se26BbJMJOkkn6KmTPbJF8mT5UGg3qMRn0EPIRs8A9gAq0YsIhDcCLF5SQ9YrnLMe8VB9RSMlMjCxYcueIyfOy7CuAFHU7lP9iqApt5L3ksBJbzlgZ9PVkXDUvbWa6x8T/i0u+XyWKtmmHW0NDI55yeRok2DjaKdg65jX7Bzzm71jXnN08vzJkQvg7Ng/WAYH9Qb3wzM/AHicjVVvbFzFEd/Zfbv7/vn9uXf33vl8Pt/dO99BHOzEZ9/DKTImRS0KjUoLDUFCjtpCMGkT1D9qldQmhkiUSv2G1BBB1VYqilGREOIDViWEGzttqkpI/cAXqyL5gFRALVIF+VCJe9fZd+fEpR/o6d3s7G9mZ2dmZ3aJIKR3h0ZYmVgkIjGZJV8mDxECtenOTDOu1UU+hJoD+TCqzcNMk2V8O5OCbDVRPgZhEt4JCNTZ/4HA3+DfuWIxl8pcFFErG3K7oD7fvev8UaMUmEu259lrRjBsfs6cLhYbRfzSbSjGRVAkfQYihUXsyPkHTVyyZDNmXzSHg3Tl+aPKxpJFqbWGdtLl8w8iYDxuDTQIx7yc1YCdIx7Jk3HSwbwQwGBcyMKZVtG0ZCuJxjFJBb+foMSfhJaPOSr4FYgwSwqIx2MHJALtAdBi/7xcSMJL+fxmmBS2guD61tZm96X02mgcj0J1NAaIR9UMmhXIV24FuLUC71+r1AEmK1AYrQHUK/Tly/m8MrOZz2+FSf7jzc3NK9XR9F2lVq+gmRp0r+HK9B+VJmR263Rgd7ALwR/FOFfx/FeJS0YxQh9drakgMJhaBVizkwgqWxLD6eQ0Qo8f7p44fJziSH9x+PjLZUO+/jZ9+K35X37ljn/Rv+yW4Ziuf2nl4PfS5/LrP47OHTsFJULYjf369UZAEBmSqEOSJmG4Me6LeznA0BFkcDoJlGynVzmH2vY21DhPr25v9DjvbfTp2TXG1s5mlK0q4S7lT++6obbRox/s6CHF2LMEsHvoFfSFQIKnKQMZJVFCD6WH0p0PVvvcRx8uph8eUks0jOFNtskOkpDsJ18k9+NqVRg3qqMCSSerjyRuYUi1/vFH7YIqikGVcD+ehFl/pqPSPKZ6DG6mHisljFhBFvU/PoRkSNd/JHO6Ja5JOXcfwIGJbm/igBq/hn8Kfb57YbYUxyX4cwkLKH1u4gD9GVSL6USxCjjCO2p8VdcvH9XRYIQWqUblu3pR/v2BvXMAc3tTmJiDAQ895B9NL0C9BFdKqqRKczDX/Whg7O1irVbcqZ8/sbfYBOZwihC+6wSDzszUf+dF7rRO1O+fKaDO+nXOr6+vf8L5J44Qe4UvnlyRntwrxMoKzpFdeRJBNb9dGyiur1+nE59R+uwi9M1G395jb9KP0bcK2YM9nJB5cojcS75OFskxclzdc+pW699z8iYbtf14BGKf77ruZNyXKC0e50OEBI+V/Aug5Dex/9WjJfipuqnS00gfybjXbNe1f762tXmRPp3Bdl/l6g5JXyqXR0bK8J3PR+jvwYs8/GBnTM+kr8FX4ZknwC16XtG9iH9QfNn1vDHPe2GAj3ieV3XdF2+IPdeteh62Ra+HfQrsKWKSBtlHSOBgM7KkKQBLWnZoq1mVwotCLRGhOtSkMzMuqq2ml3SqUehdnZtynbtPLB88/Dy9dDrYVzoy/MTT6Svnlpd/AHueon5wpnGsEae/PZm+d3Jp6SSUTy7R3xw4f9/B5RN3O+5t3VNncjm6Cnt+uLx8DpedGj4yvD84HceNxTcG6ku4VPmZ9n6nNdj95BHyB3IJKxBPsKm6rpn4QopmqzlFm1MwqdxO5rPGnIc7aSfCGg1Vqyo6nUlQhnh7WiFhXzgGhVC4qjPRki9xdGCc4zXeSWb9BG1ktlqz2Q5Y7S2sIJfivkpVKCCDpyCWdbQzECj76qMVqvyJ/LxyI2rTv1bTC25lSM9xAUJ4Lc+U0wXTsKXDmaA8tHX+hvDt4Wa9IHLcMUBz9VwpL4xi2aGasAPPKNUbbmD/2jAtk0uXY4eJx8zRgj9iAnVNt5X+BL5vlHTOaiOmG7g6+7ZBNUOaefNXuJF3u25RjVvBLeW8E4wV7ZJBpbAXXGnqrwgupWVTAKqZjq5HbW44fMguNJhgwmw8oOk8GCqE8F3GhLB0uS/UDVt4lgjtqGxK/rpwuaDAqKHZNuWmJjVKuWUxbpg2B9DtoRdN3TKF9B0hw4p41C5i3CI9w4civP3aQLlmLMK3wpJpaI7BvmlhPtH3nPWCKQAdE2hK9zyuUeAm921qCA2kvqY8N1yDMq4beJlG+4XQqHDCQnqPlJIyyN579S4tIGcRv/82BbFfK9SgnVHkZzMeaSQjqR5/fP5XF2Chh+sW0g0gn27snqXv3/bsszsfJbCAIiTdjRTVCBL6jV0K5D8H/8xVAAAAeJxjYGRgYADi16c/vIvnt/nKwM3CAALXZxxzhtH///23YVFhbgZyORiYQKIAm34OJQAAAHicY2BkYGBu+N/AEMOi/P/f//8sKgxAERTAAwCmuAa3eJxjYWBgYAFhRiiNFf//z6L8/x+IDQAkCQRQAAAAAAAAjAEAATgBfgGaAiACbgMMA2AEhATGAAB4nGNgZGBg4GE4DMQgwATEXEDIwPAfzGcAAB2tAfIAAHicZY9NTsMwEIVf+gekEqqoYIfkBWIBKP0Rq25YVGr3XXTfpk6bKokjx63UA3AejsAJOALcgDvwSCebNpbH37x5Y08A3OAHHo7fLfeRPVwyO3INF7gXrlN/EG6QX4SbaONVuEX9TdjHM6bCbXRheYPXuGL2hHdhDx18CNdwjU/hOvUv4Qb5W7iJO/wKt9Dx6sI+5l5XuI1HL/bHVi+cXqnlQcWhySKTOb+CmV7vkoWt0uqca1vEJlODoF9JU51pW91T7NdD5yIVWZOqCas6SYzKrdnq0AUb5/JRrxeJHoQm5Vhj/rbGAo5xBYUlDowxQhhkiMro6DtVZvSvsUPCXntWPc3ndFsU1P9zhQEC9M9cU7qy0nk6T4E9XxtSdXQrbsuelDSRXs1JErJCXta2VELqATZlV44RelzRiT8oZ0j/AAlabsgAAAB4nG2L3QqCQBCFZ9RWU7sOfAeh8IFi3N10EHYUG1p8+gSjqz44F+cPEjgo4T81Jphihic0mGOBZyyxwhovUCxKIe4ylthRuDqV+I22UcLQ6+QH4ubWdZZkU3m4o/0tUqtSvT33TPLits12fzc+zhRcvoquo0o281OLhcMw7Q+AD8sULE0=') format('woff'), + url('//at.alicdn.com/t/font_792691_qxv28s6g1l9.ttf?t=1534240067831') format('truetype'), + /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ + url('//at.alicdn.com/t/font_792691_qxv28s6g1l9.svg?t=1534240067831#iconfont') format('svg'); + /* iOS 4.1- */ +} + +.xm-iconfont { + font-family: "xm-iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-quanxuan:before { + content: "\e62c"; +} + +.icon-caidan:before { + content: "\e610"; +} + +.icon-fanxuan:before { + content: "\e837"; +} + +.icon-pifu:before { + content: "\e668"; +} + +.icon-qingkong:before { + content: "\e63e"; +} + +.icon-sousuo:before { + content: "\e600"; +} + +.icon-danx:before { + content: "\e62b"; +} + +.icon-duox:before { + content: "\e613"; +} + +.icon-close:before { + content: "\e601"; +} + +.icon-expand:before { + content: "\e641"; +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/step.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/step.css new file mode 100644 index 0000000000000000000000000000000000000000..da5bbce7467de45ea60349d4ac29944a4e86588d --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/step.css @@ -0,0 +1,88 @@ +.lay-step { + font-size: 0; + margin: 0 auto; + max-width: 100%; + width: 60%; + padding-left: 15%; + +} + +.step-item { + display: inline-block; + line-height: 35px; + position: relative; + font-size: 15px; + vertical-align: top; +} + +.step-item-tail { + width: 100%; + padding: 0 10px; + position: absolute; + left: 0; + top: 13px; +} + +.step-item-tail i { + display: inline-block; + width: 100%; + height: 3px; + margin-top: 4px; + vertical-align: top; + background: #5FB878; + position: relative; +} + +.step-item-tail .step-item-tail-done { + /**background: #5FB878; */ + height: 3px; + margin-top: 4px; +} + +.step-item-head { + position: relative; + display: inline-block; + height: 35px; + width: 35px; + text-align: center; + vertical-align: top; + color: #5FB878; + border: 3px solid #5FB878; + border-radius: 50%; + background: #ffffff; +} + +.step-item-head.step-item-head-active { + background: #5FB878; + color: #ffffff; +} + +.step-item-main { + display: block; + position: relative; + margin-left: -50%; + margin-right: 50%; + padding-left: 26px; + text-align: center; +} + +.step-item-main-title { + font-weight: bolder; + color: #555555; +} + +.step-item-main-desc { + color: #aaaaaa; +} + +.step-item-main-time { + color: #aaaaaa; +} + +.lay-step + [carousel-item]:before { + display: none; +} + +.lay-step + [carousel-item] > * { + background-color: transparent; +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/tab.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/tab.css new file mode 100644 index 0000000000000000000000000000000000000000..3161f3e4449006f78b43ee38ed6124bb3ded9626 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/tab.css @@ -0,0 +1,308 @@ +.pear-tab { + margin: 0px; + overflow: hidden; + height: 100% !important; +} + +.pear-tab .layui-tab-content { + height: calc(100% - 42px) !important; +} + +.pear-tab .layui-tab-content .layui-tab-item { + height: 100%; +} + +.pear-tab-menu{ + box-shadow: 0 2px 8px #f0f1f2!important; + border: 1px solid whitesmoke!important; + border-radius: 4px!important; +} + +.pear-tab-menu .item{ + height: 20px; + padding-left: 18px; + padding-top: 7px; + padding-bottom: 7px; + color: #333; + font-size: 13.5px; + line-height: 20px; + cursor:pointer; +} +.pear-tab-menu .item:hover{ + background: #36b368; + color: white; +} + +.pear-tab .layui-tab-content { + padding: 0px; +} + +.pear-tab .layui-tab-title { + border: none; + border: 1px solid whitesmoke; + background-color: white; +} + +.pear-tab .layui-tab-title li { + border-right: 1px solid whitesmoke; + color: dimgray; + font-size: 13.5px; +} + +.pear-tab .layui-tab-title .layui-tab-bar { + display: none; +} + +.pear-tab .layui-tab-title .layui-this:after { + display: none; +} + +.pear-tab .layui-tab-title .pear-tab-active { + display: inline-block; + background-color: lightgray; + width: 8px; + height: 8px; + border-radius: 30px; + margin-right: 12px; +} + +.pear-tab .layui-tab-title .layui-this .pear-tab-active { + background-color: #5FB878; +} + +.pear-tab .layui-tab-title .layui-tab-close:hover { + background-color: white; + line-height: 19px; + color: gray; +} + +.pear-tab .layui-tab-title .disable-close+.layui-tab-close { + display: none; +} + +.pear-tab .layui-tab-title .able-close+.layui-tab-close { + display: inline-block; +} + +.pear-tab .layui-tab-close{ + font-size: 13px; +} + +.pear-tab .layui-tab-control>li { + position: absolute; + top: 0px; + height: 40px; + line-height: 40px; + width: 40px; + text-align: center; + background-color: white; + border-top: whitesmoke 1px solid; + border-bottom: whitesmoke 1px solid; +} + +.pear-tab .layui-tab-prev { + left: 0px; + border-right: whitesmoke 1px solid; +} + +.pear-tab .layui-tab-next { + right: 40px; + border-left: 1px solid whitesmoke; +} + +.pear-tab .layui-tab-tool { + right: 0px; + border-left: 1px solid whitesmoke; +} + +.pear-tab .layui-tab-control .layui-tab-tool, +.pear-tab .layui-tab-control .layui-tab-prev, +.pear-tab .layui-tab-control .layui-tab-next { + display: none; +} + +.pear-tab.layui-tab-roll .layui-tab-control .layui-tab-prev, +.pear-tab.layui-tab-roll .layui-tab-control .layui-tab-next { + display: block; +} + +.pear-tab.layui-tab-roll .layui-tab-control .layui-tab-next { + right: 0px; + border-right: 1px solid whitesmoke; +} + +.pear-tab.layui-tab-roll .layui-tab-title { + padding-left: 40px; + padding-right: 40px; +} + +.pear-tab.layui-tab-tool .layui-tab-control .layui-tab-tool { + display: block; +} + +.pear-tab.layui-tab-tool .layui-tab-title { + padding-left: 0px; + padding-right: 40px; +} + +.pear-tab.layui-tab-rollTool .layui-tab-title { + padding-left: 40px; + padding-right: 80px; +} + +.pear-tab.layui-tab-rollTool .layui-tab-control .layui-tab-prev, +.pear-tab.layui-tab-rollTool .layui-tab-control .layui-tab-next, +.pear-tab.layui-tab-rollTool .layui-tab-control .layui-tab-tool { + display: block; +} + +.pear-tab .layui-tab-tool .layui-nav { + position: absolute; + height: 43px !important; + top: 0; + width: 100%; + height: 100%; + padding: 0; + background: 0 0; +} + +.pear-tab .layui-tab-tool .layui-nav-item { + height: 40px; +} + +.pear-tab .layui-tab-tool .layui-nav-bar { + display: none; +} + +.pear-tab .layui-tab-tool .layui-nav-child { + left: auto; + top: 45px; + right: 3px; + width: 120px; + border: 1px solid whitesmoke; +} + +.pear-tab .layui-tab-tool .layui-this a { + background-color: #009688; +} + +.pear-tab-loading { + position: absolute; + display: none; + width: 100%; + height: calc(100% - 42px); + top: 42px; + z-index: 19; + background-color: #fff +} + +.pear-tab-loading.close { + animation: close 1s; + -webkit-animation: close 1s; + animation-fill-mode: forwards; +} + +.ball-loader { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + -ms-transform: translate(-50%, -50%); + -webkit-transform: translate(-50%, -50%) +} + +.ball-loader>span, +.signal-loader>span { + background-color: #4aca85 !important; + display: inline-block +} + +.ball-loader>span:nth-child(1), +.ball-loader.sm>span:nth-child(1), +.signal-loader>span:nth-child(1), +.signal-loader.sm>span:nth-child(1) { + -webkit-animation-delay: 0s; + animation-delay: 0s +} + +.ball-loader>span:nth-child(2), +.ball-loader.sm>span:nth-child(2), +.signal-loader>span:nth-child(2), +.signal-loader.sm>span:nth-child(2) { + -webkit-animation-delay: .1s; + animation-delay: .1s +} + +.ball-loader>span:nth-child(3), +.ball-loader.sm>span:nth-child(3), +.signal-loader>span:nth-child(3), +.signal-loader.sm>span:nth-child(3) { + -webkit-animation-delay: .15s; + animation-delay: .15s +} + +.ball-loader>span:nth-child(4), +.ball-loader.sm>span:nth-child(4), +.signal-loader>span:nth-child(4), +.signal-loader.sm>span:nth-child(4) { + -webkit-animation-delay: .2s; + animation-delay: .2s +} + +.ball-loader>span { + width: 20px; + height: 20px; + margin: 0 3px; + border-radius: 50%; + transform: scale(0); + -ms-transform: scale(0); + -webkit-transform: scale(0); + animation: ball-load 1s ease-in-out infinite; + -webkit-animation: 1s ball-load ease-in-out infinite +} + +@-webkit-keyframes ball-load { + 0% { + transform: scale(0); + -webkit-transform: scale(0) + } + + 50% { + transform: scale(1); + -webkit-transform: scale(1) + } + + 100% { + transform: scale(0); + -webkit-transform: scale(0) + } +} + +@keyframes ball-load { + 0% { + transform: scale(0); + -webkit-transform: scale(0) + } + + 50% { + transform: scale(1); + -webkit-transform: scale(1) + } + + 100% { + transform: scale(0); + -webkit-transform: scale(0) + } +} + +@-webkit-keyframes close { + 0% { + opacity: 1; + /*display: block;*/ + } + + 100% { + opacity: 0; + /*display: none;*/ + } +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/table.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/table.css new file mode 100644 index 0000000000000000000000000000000000000000..c4f5d4ca2b43644d16f11e9f98764903264ed435 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/table.css @@ -0,0 +1,108 @@ +.layui-table-tool-panel { + margin-top: 10px !important; +} + +.layui-table-tool { + background-color: white !important; + border-bottom: none !important; + padding-bottom: 10px !important; +} + +.layui-table-header, +.layui-table-header th { + background-color: white !important; +} + +.layui-table-view { + border: none !important; +} + +/** 兼容 layui 2.7.0 升级 table cell 单元格边距的调整 */ +.layui-table-view .layui-table td, .layui-table-view .layui-table th { + padding: 5px 0px; +} + +.layui-table-cell { + height: 34px; + line-height: 34px; +} + +.layui-table .layui-laypage .layui-laypage-curr .layui-laypage-em { + border-radius: 50px !important; + border-radius: 4px!important; + background-color: #5FB878 !important; +} + +.layui-table-view .layui-table{ + width: 100%; +} + +.layui-table tr { + height: 34px; + line-height: 34px; +} + +.layui-table-cell { + padding-top: 1px !important; +} + +.layui-table-box * { + font-size: 13px !important; +} + +.layui-table-page .layui-laypage input { + width: 40px; + height: 26.5px!important; +} + +.layui-table-box button { + font-size: 15px !important; +} + +.layui-table-page { + height: 45px !important; + padding-top: 10px !important; +} + +.layui-table-tool .layui-inline { + border-radius: 3px !important; + width: 30px !important; + height: 30px !important; + line-height: 20px !important; +} + +.layui-table-view .layui-table[lay-skin=line] { + border: none !important; +} + +.layui-table-init .layui-icon{ + font-size: 40px !important; + margin: -15px 0 0 -15px; +} + +.layui-table-body::-webkit-scrollbar { + width: 0px; + height: 0px; +} + +.layui-table-body::-webkit-scrollbar { + width: 6px; + height: 6px; +} +.layui-table-body::-webkit-scrollbar-track { + background: white; + border-radius: 2px; +} + +.layui-table-body::-webkit-scrollbar-thumb { + background: #E6E6E6; + border-radius: 2px; +} + +.layui-table-body::-webkit-scrollbar-thumb:hover { + background: #E6E6E6; +} + +.layui-table-body::-webkit-scrollbar-corner { + background: #f6f6f6; +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/tag.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/tag.css new file mode 100644 index 0000000000000000000000000000000000000000..7c244bc2094a5dab4eb72ff1ca47369414706a9d --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/tag.css @@ -0,0 +1,85 @@ +.input-new-tag { + width: 90px; +} + +.input-new-tag input { + height: 100%!important; + border: none; + padding-left: 0px; +} + +.tag .layui-btn .tag-close:hover { + border-radius: 2px; + color: #fff; +} + +.tag .layui-btn .tag-close { + margin-left: 8px; + transition: all .2s; + -webkit-transition: all .2s; +} +.tag-item { + background-color: #5FB878; + color: white; + border: none; +} + +.tag-item:hover { + + color: white; + +} +.tag-item-normal { + background-color: #5FB878; + color: white; + border: none; +} + +.tag-item-warm { + background-color: #f6ad55; + color: white; + border: none; +} + +.tag-item-danger { + background-color: #f56c6c; + color: white; + border: none; +} + +.tag-item-dark { + background-color: #525252; + color: white; + border: none; +} + +.tag-item-primary { + background-color: white !important; + color: dimgray; + border: 1px solid dimgray; +} + +.tag-item-normal:hover { + + color: white !important; +} + +.tag-item-warm:hover { + + color: white; +} + +.tag-item-danger:hover { + + color: white; +} + +.tag-item-dark:hover { + + color: white; +} + +.tag-item-primary:hover { + color: dimgray; + border: 1px solid dimgray; +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/toast.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/toast.css new file mode 100644 index 0000000000000000000000000000000000000000..5472da53e9f8d9f310903b5fa7026b32491f689e --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/toast.css @@ -0,0 +1,1929 @@ +.iziToast-capsule { + font-size: 0; + height: 0; + width: 100%; + transform: translateZ(0); + backface-visibility: hidden; + transition: transform 0.5s cubic-bezier(0.25, 0.8, 0.25, 1), height 0.5s cubic-bezier(0.25, 0.8, 0.25, 1); +} + +.iziToast-capsule, .iziToast-capsule * { + box-sizing: border-box; +} + +.iziToast-overlay { + display: block; + position: fixed; + top: -100px; + left: 0; + right: 0; + bottom: -100px; + z-index: 19891100; +} + +.iziToast { + display: inline-block; + clear: both; + position: relative; + font-family: 'Lato', Tahoma, Arial; + font-size: 14px; + padding: 8px 45px 9px 0; + background: #fff; + border-color: #fff; + width: 100%; + pointer-events: all; + cursor: default; + transform: translateX(0); + -webkit-touch-callout: none /* iOS Safari */; + -webkit-user-select: none /* Chrome/Safari/Opera */; + -khtml-user-select: none /* Konqueror */; + -moz-user-select: none /* Firefox */; + -ms-user-select: none /* Internet Explorer/Edge */; + user-select: none; + min-height: 45px; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1); + max-width: 90%; + margin: 5px 0; + border-radius: 4px; +} + +.iziToast > .iziToast-progressbar { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + z-index: 1; + background: rgba(255, 255, 255, 0.5); +} + +.iziToast > .iziToast-progressbar > div { + height: 2px; + width: 100%; + background: #dddddd; + border-radius: 0 0 3px 3px; +} + +.iziToast.iziToast-theme-dark > .iziToast-progressbar > div { + background: #fff; +} + +.iziToast.iziToast-balloon:before { + content: ''; + position: absolute; + right: 8px; + left: auto; + width: 0px; + height: 0px; + top: 100%; + border-right: 0px solid transparent; + border-left: 15px solid transparent; + border-top: 10px solid #000; + border-top-color: inherit; + border-radius: 0; +} + +.iziToast.iziToast-balloon .iziToast-progressbar { + top: 0; + bottom: auto; +} + +.iziToast.iziToast-balloon > div { + border-radius: 0 0 0 3px; +} + +.iziToast > .iziToast-cover { + position: absolute; + left: 0; + top: 0; + bottom: 0; + height: 100%; + margin: 0; + background-size: 100%; + background-position: 50% 50%; + background-repeat: no-repeat; +} + +.iziToast > .iziToast-close { + position: absolute; + right: 0; + top: 0; + border: 0; + padding: 0; + opacity: 0.6; + width: 42px; + height: 100%; + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAJPAAACTwBcGfW0QAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAD3SURBVFiF1ZdtDoMgDEBfdi4PwAX8vLFn0qT7wxantojKupmQmCi8R4tSACpgjC2ICCUbEBa8ingjsU1AXRBeR8aLN64FiknswN8CYefBBDQ3whuFESy7WyQMeC0ipEI0A+0FeBvHUFN8xPaUhAH/iKoWsnXHGegy4J0yxialOfaHJAz4bhRzQzgDvdGnz4GbAonZbCQMuBm1K/kcFu8Mp1N2cFFpsxsMuJqqbIGExGl4loARajU1twskJLLhIsID7+tvUoDnIjTg5T9DPH9EBrz8rxjPzciAl9+O8SxI8CzJ8CxKFfh3ynK8Dyb8wNHM/XDqejx/AtNyPO87tNybAAAAAElFTkSuQmCC") no-repeat 50% 50%; + background-size: 8px; + cursor: pointer; + outline: none; +} + +.iziToast > .iziToast-close:hover { + opacity: 1; +} + +.iziToast > .iziToast-body { + position: relative; + padding: 0 0 0 10px; + height: auto; + min-height: 28px; + margin: 0 0 0 15px; + text-align: left; +} + +.iziToast > .iziToast-body:after { + content: ""; + display: table; + clear: both; +} + +.iziToast > .iziToast-body .iziToast-texts { + margin: 6px 0; + padding-right: 2px; + display: inline-block; + float: left; +} + +.iziToast > .iziToast-body .iziToast-inputs { + min-height: 19px; + float: left; + margin: 3px -2px; +} + +.iziToast > .iziToast-body .iziToast-inputs > input:not([type=checkbox]):not([type=radio]), +.iziToast > .iziToast-body .iziToast-inputs > select { + position: relative; + display: inline-block; + margin: 2px; + border-radius: 2px; + border: 0; + padding: 4px 7px; + font-size: 13px; + letter-spacing: 0.02em; + background: rgba(0, 0, 0, 0.1); + color: #000; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2); + min-height: 26px; +} + +.iziToast > .iziToast-body .iziToast-inputs > input:not([type=checkbox]):not([type=radio]):focus, +.iziToast > .iziToast-body .iziToast-inputs > select:focus { + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6); +} + +.iziToast > .iziToast-body .iziToast-buttons { + min-height: 17px; + float: left; + margin: 4px 0 0 0; +} + +.iziToast > .iziToast-body .iziToast-buttons > a, +.iziToast > .iziToast-body .iziToast-buttons > button, +.iziToast > .iziToast-body .iziToast-buttons > input:not([type=checkbox]):not([type=radio]) { + position: relative; + display: inline-block; + margin: 2px; + border-radius: 2px; + border: 0; + padding: 5px 10px; + font-size: 12px; + letter-spacing: 0.02em; + cursor: pointer; + background: rgba(0, 0, 0, 0.1); + color: #555; +} + +.iziToast > .iziToast-body .iziToast-buttons > a:hover, +.iziToast > .iziToast-body .iziToast-buttons > button:hover, +.iziToast > .iziToast-body .iziToast-buttons > input:not([type=checkbox]):not([type=radio]):hover { + background: rgba(0, 0, 0, 0.15); +} + +.iziToast > .iziToast-body .iziToast-buttons > a:focus, +.iziToast > .iziToast-body .iziToast-buttons > button:focus, +.iziToast > .iziToast-body .iziToast-buttons > input:not([type=checkbox]):not([type=radio]):focus { + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6); +} + +.iziToast > .iziToast-body .iziToast-buttons > a:active, +.iziToast > .iziToast-body .iziToast-buttons > button:active, +.iziToast > .iziToast-body .iziToast-buttons > input:not([type=checkbox]):not([type=radio]):active { + top: 1px; +} + +.iziToast > .iziToast-body .iziToast-icon { + height: 100%; + position: absolute; + left: 0; + top: 50%; + display: table; + font-size: 23px; + line-height: 24px; + margin-top: -11px; + color: #000; + width: 24px; + height: 24px; +} + +.iziToast > .iziToast-body .iziToast-icon.ico-info { + background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTU1NzcxMTk5MzYwIiBjbGFzcz0iaWNvbiIgc3R5bGU9IiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjEwODAzIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiPjxkZWZzPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PC9zdHlsZT48L2RlZnM+PHBhdGggZD0iTTUxMiAyOC40MTZjLTI2Ny40Njg4IDAtNDg0LjI0OTYgMjE2LjgzMi00ODQuMjQ5NiA0ODQuMjQ5NiAwIDI2Ny40MTc2IDIxNi44MzIgNDg0LjI0OTYgNDg0LjI0OTYgNDg0LjI0OTYgMjY3LjQxNzYgMCA0ODQuMzAwOC0yMTYuODMyIDQ4NC4zMDA4LTQ4NC4yNDk2Qzk5Ni4zMDA4IDI0NS4yNDggNzc5LjQxNzYgMjguNDE2IDUxMiAyOC40MTZ6TTQ1NS41MjY0IDI0NS4wOTQ0QzQ3MC4zMjMyIDIyOS44ODggNDkwLjcwMDggMjIxLjMzNzYgNTExLjc5NTIgMjIxLjY0NDhjMjEuMTk2OC0wLjIwNDggNDEuNzc5MiA4LjI0MzIgNTYuNTI0OCAyMy40NDk2IDE1LjAwMTYgMTQuNzk2OCAyMy4yOTYgMzUuMTIzMiAyMy4wOTEyIDU2LjExNTIgMC4yMDQ4IDIxLjE5NjgtOC4yOTQ0IDQxLjU3NDQtMjMuMzk4NCA1Ni4yMTc2LTE0LjY5NDQgMTQuNjk0NC0zNC43MTM2IDIzLjA0LTU1LjM5ODQgMjMuMDRMNTExLjc5NTIgMzgwLjQ2NzJjLTIwLjk5MiAwLjIwNDgtNDEuMzY5Ni04LjE0MDgtNTYuMDY0LTIzLjE0MjRDNDQwLjY3ODQgMzQyLjY4MTYgNDMyLjMzMjggMzIyLjMwNCA0MzIuNTM3NiAzMDEuMjA5NiA0MzIuMzMyOCAyODAuMjE3NiA0NDAuNjc4NCAyNTkuODkxMiA0NTUuNTI2NCAyNDUuMDk0NHpNNjI3LjYwOTYgNzY4LjE1MzZsMCAxMy40MTQ0IDAgMjIuMjIwOEwzOTYuMjg4IDgwMy43ODg4bDAtNTcuMTM5MiAyMS42MDY0LTAuNzY4YzEwLjI0LTAuNDYwOCAxNC41OTItMi43MTM2IDE2Ljk5ODQtNC43NjE2bDEuMjI4OC01LjQyNzJjMC45NzI4LTUuNTgwOCAxLjYzODQtMTQuNDM4NCAxLjU4NzItMjUuOTA3Mkw0MzcuNzA4OCA1MDcuOTA0YzAuMjU2LTE3Ljc2NjQtMi4zNTUyLTI5LjkwMDgtMy40ODE2LTMyLjU2MzJsMCAwTDQzMS42MTYgNDc0LjA2MDhDNDI4Ljg1MTIgNDczLjA4OCA0MjMuOTM2IDQ3Mi4wNjQgNDE3LjE3NzYgNDcxLjY1NDRMMzk2LjI4OCA0NzAuMzc0NCAzOTYuMjg4IDQxMy40OTEybDE4OS40OTEyIDAgMCAyOTYuMjk0NGMtMC4zMDcyIDE3LjcxNTIgMi40MDY0IDI5Ljc5ODQgMy40MzA0IDMyLjU2MzJsMC4wNTEyIDAgMi43MTM2IDEuMTc3NmMyLjgxNiAwLjk3MjggNy43ODI0IDEuOTk2OCAxNC42OTQ0IDIuMzU1MmwyMC44ODk2IDEuMjhMNjI3LjU1ODQgNzY4LjE1MzZ6IiBwLWlkPSIxMDgwNCIgZmlsbD0iIzQwOUVGRiI+PC9wYXRoPjwvc3ZnPg==") no-repeat 50% 50%; + background-size: 85%; +} + +.iziToast > .iziToast-body .iziToast-icon.ico-warning { + background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTU1NzcwODczNzUzIiBjbGFzcz0iaWNvbiIgc3R5bGU9IiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjUxMTgiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNNTEyLjAyMzI3MyAxMDI0Qzc5NC43NjM2MzYgMTAyNCAxMDI0IDc5NC43ODY5MDkgMTAyNCA1MTEuOTc2NzI3IDEwMjQgMjI5LjIzNjM2NCA3OTQuNzg2OTA5LTAuMDIzMjczIDUxMi4wMjMyNzMtMC4wMjMyNzNTMCAyMjkuMjEzMDkxIDAgNTExLjk3NjcyN0MwIDc5NC43ODY5MDkgMjI5LjIzNjM2NCAxMDI0IDUxMi4wMjMyNzMgMTAyNE00NjkuMzQxMDkxIDc2OGMwLTIzLjU1MiAxOC45MjA3MjctNDIuNjU4OTA5IDQyLjcwNTQ1NS00Mi42NTg5MDkgMjMuNTUyIDAgNDIuNjU4OTA5IDE4LjkyMDcyNyA0Mi42NTg5MDkgNDIuNjU4OTA5IDAgMjMuNTc1MjczLTE4LjkyMDcyNyA0Mi43MDU0NTUtNDIuNjU4OTA5IDQyLjcwNTQ1NUM0ODguNDcxMjczIDgxMC43MDU0NTUgNDY5LjM0MTA5MSA3OTEuNzM4MTgyIDQ2OS4zNDEwOTEgNzY4TTQ2OS4zNDEwOTEgMjU1LjgxMzgxOGMwLTIzLjQ1ODkwOSAxOC45MjA3MjctNDIuNDcyNzI3IDQyLjcwNTQ1NS00Mi40NzI3MjcgMjMuNTUyIDAgNDIuNjU4OTA5IDE5LjQzMjcyNyA0Mi42NTg5MDkgNDIuNDcyNzI3bDAgMzQxLjczNjcyN2MwIDIzLjQ1ODkwOS0xOC45MjA3MjcgNDIuNDcyNzI3LTQyLjY1ODkwOSA0Mi40NzI3MjctMjMuNTc1MjczIDAtNDIuNzA1NDU1LTE5LjQzMjcyNy00Mi43MDU0NTUtNDIuNDcyNzI3TDQ2OS4zNDEwOTEgMjU1LjgxMzgxOHoiIHAtaWQ9IjUxMTkiIGZpbGw9IiNmZjk5MDAiPjwvcGF0aD48L3N2Zz4=") no-repeat 50% 50%; + background-size: 85%; +} + +.iziToast > .iziToast-body .iziToast-icon.ico-error { + background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTU1NzcwNDI1NDkwIiBjbGFzcz0iaWNvbiIgc3R5bGU9IiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjEyNjUiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNNTExLjk5NjQxOCAyMy41MjA2OTNjLTI2OS43NjcwNSAwLTQ4OC40NTQ3NDggMjE4LjY4ODcyMS00ODguNDU0NzQ4IDQ4OC40NTQ3NDggMCAyNjkuNzY4MDczIDIxOC42ODg3MjEgNDg4LjQ1MzcyNCA0ODguNDU0NzQ4IDQ4OC40NTM3MjQgMjY5Ljc2NjAyNyAwIDQ4OC40NTQ3NDgtMjE4LjY4NTY1MSA0ODguNDU0NzQ4LTQ4OC40NTM3MjRDMTAwMC40NTExNjYgMjQyLjIwOTQxNCA3ODEuNzYyNDQ1IDIzLjUyMDY5MyA1MTEuOTk2NDE4IDIzLjUyMDY5M3pNNzY5LjMzNDM5MSA3MTUuMTU1OTU2bC01NC4xNTY0MzQgNTQuMTU2NDM0TDUxMS45OTY0MTggNTY2LjEyOTgyOCAzMDguODEzODU2IDc2OS4zMTIzOWwtNTQuMTU1NDExLTU0LjE1NjQzNEw0NTcuODQxMDA4IDUxMS45NzU0NDEgMjU0LjY1ODQ0NiAzMDguNzkyODc4bDU0LjE1NTQxMS01NC4xNTU0MTFMNTExLjk5NjQxOCA0NTcuODIwMDNsMjAzLjE4MjU2Mi0yMDMuMTgyNTYyIDU0LjE1NjQzNCA1NC4xNTU0MTFMNTY2LjE1MTgyOSA1MTEuOTc1NDQxIDc2OS4zMzQzOTEgNzE1LjE1NTk1NnoiIHAtaWQ9IjEyNjYiIGZpbGw9IiNGNTZDNkMiPjwvcGF0aD48L3N2Zz4=") no-repeat 50% 50%; + background-size: 80%; +} + +.iziToast > .iziToast-body .iziToast-icon.ico-success { + background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTU1NzcwNTI2MjA3IiBjbGFzcz0iaWNvbiIgc3R5bGU9IiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjQ5NjUiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNMTAyNCA1MTEuOTk5NTAyYzAgMjgyLjc3MDU1Ny0yMjkuMjI5OTQxIDUxMi4wMDA0OTgtNTExLjk5OTUwMiA1MTIuMDAwNDk4LTI4Mi43Njk1NjEgMC01MTIuMDAwNDk4LTIyOS4yMjk5NDEtNTEyLjAwMDQ5OC01MTIuMDAwNDk4IDAtMjgyLjc2ODU2NiAyMjkuMjMwOTM2LTUxMS45OTk1MDIgNTEyLjAwMDQ5OC01MTEuOTk5NTAyQzc5NC43NjkwNjQgMCAxMDI0IDIyOS4yMzA5MzYgMTAyNCA1MTEuOTk5NTAyek03OTYuNTc3MDgxIDM3OC4zMTc3MTNsLTQ4LjQ1OTA1MS00OC40NTkwNTEtMjk3LjA3ODM4NyAyOTcuMDc3MzkyTDI3Ny4yNjc4NTIgNDUzLjE2NTI1OGwtNDguNDU4MDU2IDQ4LjQ1ODA1NiAyMjIuMjI4ODUxIDIyMi4yMzA4NDJMNzk2LjU3NzA4MSAzNzguMzE3NzEzeiIgcC1pZD0iNDk2NiIgZmlsbD0iIzY3YzIzYSI+PC9wYXRoPjwvc3ZnPg==") no-repeat 50% 50%; + background-size: 85%; +} + +.iziToast > .iziToast-body .iziToast-icon.ico-question { + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAQAAAAAYLlVAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfhCQkUEhFovxTxAAAEDklEQVRo3s2ZTWgTQRTHf03ipTRUqghNSgsRjHgQrFUQC6JgD1Kak3gQUUoPqRdBglf1oBehBws9Cn4cGk+1SOmh2upBxAYVoeJHrR9tgq0i1Cq0lqYeks7MbpPdmU00/c8hm9n33v/t7Nt5M2+qMEWQI0QIibZKRrQpHvLL2KI2wnQzzBKrDm2RIeKEy01dTYKUI7G1ZRknQXV5yP10kTYgly1NF/5S6duZ8ES+1iZodyaocrjXxE0OFeifYYgp0mRIkwFChAkRJsIxGgrIP+I0n82fvZW5dc/zkss0O2o1c5mX6/TmaDWl77RFe5YkUW3tKEmyFv0lOvXJ/fTYnmCEFuMRbGHEZqVHLyT9DFjUJmkzJl9DG5MWWwM6Llif/gF1nukB6nhgGwUXdFrE+wiURA8QoM9i0zEWWpXQW+ZsyeRrOMuyEo5Fv4gmy4dXPvqcC+pH2VRYaMwy+OWG+iLGCgm0W0Kv9HdvR8ASjmKCXpuK/bxiV/76A/v5UdDIZuKcJGjrnec5KZ7wwsWFOp6xPX/9mt2sqDe7FO+Kf/fXHBPPDWpdXGhTpLvUG9VKwh1xMDDjkvu+cNDFBTk7ptX1QkKZ850m3duu6fcrWxwdaFFyREJ2j4vOpKP6Du6z4uJCv8sYJIVkCnJBGGZaBONO3roY2EqNrSfIPi7SKP4fdXyNUd6I6wbSAHEl33tFLe+FlSsusnK90A0+oEPcuufZgXnOi+u9LrKSJQZQw6LwqBnv2CKsfHORbFbyQhA6xN/pEuihSdj56Co7LWRjPiKie6gkB2LiKuUqK5kiPkLiz1QJ9K1cNXBAMoUCigNpQ9IqDtMI1HKA4/jyvUsaoSyZLA5kjOjDPFZen8Ql5TsvBskUgjciIPSX3QAXC86DT7VWvlEh/xZ+ij9BDVWJ0QL0SbZq6QaFxoLPcXPmBLveLCc4wXdDK6s+6/vwhCSniFLPXW0NJe5UB8zKCsviqpc7vGPVQFcyZbyPwGD+d5ZnxmNWlhG4xSBZZjivjIWHEQgoDkSMjMwTo54569JSE5IpA7EyJSMTyGTUAUFlO1ZKOtaHTMeL1PhYYFTcihmY2cQ5+ullj7EDkiVfVez2sCTz8yiv84djhg7IJVk81xFWJlPdfHBG0flkRC/zQFZ+DSllNtfDdUsOMCliyGX5uOzU3ZhIXFDof4m1gDuKbEx0t2YS25gVGpcMnr/I1kx3c6piB8P8ZoqEwfMX3ZyCXynJTmq/U7NUXqfUzCbWL1wqVKBQUeESzQYoUlW8TAcVL1RCxUu1G6BYXfFyfQ4VPbDI4T8d2WzgQ6sc/vmxnTsqfHCZQzUJxm1h5dxS5Tu6lQgTZ0ipqRVqSwzTbbLHMt+c19iO76tsx/cLZub+Ali+tYC93olEAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTA5LTA5VDIwOjE4OjE3KzAyOjAwjKtfjgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wOS0wOVQyMDoxODoxNyswMjowMP325zIAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC") no-repeat 50% 50%; + background-size: 85%; +} + +.iziToast > .iziToast-body .iziToast-icon.ico-load { + background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTQ1NTUyMzAyOTE3IiBjbGFzcz0iaWNvbiIgc3R5bGU9IiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjQyNDAiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNNTEyIDY0YzI0Ny4yIDAgNDQ4IDIwMC44IDQ0OCA0NDhoLTY0YzAtMjEyLTE3Mi0zODQtMzg0LTM4NFY2NHogbTAgODMyYy0yMTIgMC0zODQtMTcyLTM4NC0zODRINjRjMCAyNDcuMiAyMDAuOCA0NDggNDQ4IDQ0OHYtNjR6IiBwLWlkPSI0MjQxIiBmaWxsPSIjMUU5RkZGIj48L3BhdGg+PC9zdmc+') no-repeat 50% 50%; + background-size: 85%; + animation: rotating 1.2s linear infinite +} + +@keyframes rotating { + from { + transform: rotate(0) + } + to { + transform: rotate(360deg) + } +} + +.iziToast > .iziToast-body .iziToast-title { + padding: 0; + margin: 0 0 10px 0; + line-height: 16px; + font-size: 14px; + text-align: left; + float: left; + color: #303133; + white-space: normal; +} + +.iziToast > .iziToast-body .iziToast-message { + padding: 0; + margin: 0; + font-size: 14px; + line-height: 16px; + text-align: left; + float: left; + color: #606266; + white-space: normal; +} + +.iziToast.iziToast-animateInside .iziToast-title, +.iziToast.iziToast-animateInside .iziToast-message, +.iziToast.iziToast-animateInside .iziToast-icon, +.iziToast.iziToast-animateInside .iziToast-buttons-child, +.iziToast.iziToast-animateInside .iziToast-inputs-child { + opacity: 0; +} + +.iziToast-target { + position: relative; + width: 100%; + margin: 0 auto; +} + +.iziToast-target .iziToast-capsule { + overflow: hidden; +} + +.iziToast-target .iziToast-capsule:after { + visibility: hidden; + display: block; + font-size: 0; + content: " "; + clear: both; + height: 0; +} + +.iziToast-target .iziToast-capsule .iziToast { + width: 100%; + float: left; +} + +.iziToast-wrapper { + z-index: 19891101; + position: fixed; + width: 100%; + pointer-events: none; + display: flex; + flex-direction: column; +} + +.iziToast-wrapper .iziToast.iziToast-balloon:before { + border-right: 0 solid transparent; + border-left: 15px solid transparent; + border-top: 10px solid #000; + border-top-color: inherit; + right: 8px; + left: auto; +} + +.iziToast-wrapper-bottomLeft { + left: 0; + bottom: 0; + text-align: left; +} + +.iziToast-wrapper-bottomLeft .iziToast.iziToast-balloon:before { + border-right: 15px solid transparent; + border-left: 0 solid transparent; + right: auto; + left: 8px; +} + +.iziToast-wrapper-bottomRight { + right: 0; + bottom: 0; + text-align: right; +} + +.iziToast-wrapper-topLeft { + left: 0; + top: 0; + text-align: left; +} + +.iziToast-wrapper-topLeft .iziToast.iziToast-balloon:before { + border-right: 15px solid transparent; + border-left: 0 solid transparent; + right: auto; + left: 8px; +} + +.iziToast-wrapper-topRight { + top: 0; + right: 0; + text-align: right; +} + +.iziToast-wrapper-topCenter { + top: 0; + left: 0; + right: 0; + text-align: center; +} + +.iziToast-wrapper-bottomCenter { + bottom: 0; + left: 0; + right: 0; + text-align: center; +} + +.iziToast-wrapper-center { + top: 0; + bottom: 0; + left: 0; + right: 0; + text-align: center; + justify-content: center; + flex-flow: column; + align-items: center; +} + +.iziToast-rtl { + direction: rtl; + padding: 8px 0 9px 45px; + font-family: Tahoma, 'Lato', Arial; +} + +.iziToast-rtl .iziToast-cover { + left: auto; + right: 0; +} + +.iziToast-rtl .iziToast-close { + right: auto; + left: 0; +} + +.iziToast-rtl .iziToast-body { + padding: 0 10px 0 0; + margin: 0 16px 0 0; + text-align: right; +} + +.iziToast-rtl .iziToast-body .iziToast-buttons, +.iziToast-rtl .iziToast-body .iziToast-inputs, +.iziToast-rtl .iziToast-body .iziToast-texts, +.iziToast-rtl .iziToast-body .iziToast-title, +.iziToast-rtl .iziToast-body .iziToast-message { + float: right; + text-align: right; +} + +.iziToast-rtl .iziToast-body .iziToast-icon { + left: auto; + right: 0; +} + +@media only screen and (min-width: 568px) { + .iziToast-wrapper { + padding: 10px 15px; + } + + .iziToast { + width: auto; + } + + .iziToast:not(.iziToast-rtl) .iziToast-cover { + border-radius: 3px 0 0 3px; + } + + .iziToast.iziToast-rtl .iziToast-cover { + border-radius: 0 3px 3px 0; + } + + .iziToast.iziToast-color-dark:after { + box-shadow: inset 0 -10px 20px -10px rgba(255, 255, 255, 0.3), 0 10px 10px -5px rgba(0, 0, 0, 0.25); + } + + .iziToast.iziToast-balloon .iziToast-progressbar { + background: transparent; + } + + .iziToast.iziToast-balloon:after { + box-shadow: 0 10px 10px -5px rgba(0, 0, 0, 0.25), inset 0 10px 20px -5px rgba(0, 0, 0, 0.25); + } + + .iziToast-target .iziToast:after { + box-shadow: inset 0 -10px 20px -10px rgba(0, 0, 0, 0.2), inset 0 0 5px rgba(0, 0, 0, 0.1); + } +} + +.iziToast.iziToast-theme-dark { + background: #565c70; + border-color: #565c70; +} + +.iziToast.iziToast-theme-dark .iziToast-title { + color: #fff; +} + +.iziToast.iziToast-theme-dark .iziToast-message { + color: rgba(255, 255, 255, 0.9); + font-weight: 300; +} + +.iziToast.iziToast-theme-dark .iziToast-close { + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfgCR4OIQIPSao6AAAAwElEQVRIx72VUQ6EIAwFmz2XB+AConhjzqTJ7JeGKhLYlyx/BGdoBVpjIpMJNjgIZDKTkQHYmYfwmR2AfAqGFBcO2QjXZCd24bEggvd1KBx+xlwoDpYmvnBUUy68DYXD77ESr8WDtYqvxRex7a8oHP4Wo1Mkt5I68Mc+qYqv1h5OsZmZsQ3gj/02h6cO/KEYx29hu3R+VTTwz6D3TymIP1E8RvEiiVdZfEzicxYLiljSxKIqlnW5seitTW6uYnv/Aqh4whX3mEUrAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTA5LTMwVDE0OjMzOjAyKzAyOjAwl6RMVgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNi0wOS0zMFQxNDozMzowMiswMjowMOb59OoAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC") no-repeat 50% 50%; + background-size: 8px; +} + +.iziToast.iziToast-theme-dark .iziToast-icon { + color: #fff; +} + +.iziToast.iziToast-theme-dark .iziToast-icon.ico-info { + background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTQxNjQ5NjA1MTc2IiBjbGFzcz0iaWNvbiIgc3R5bGU9IiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjM1MzIiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNODUxLjE3MTU1NiA3MTcuOTM3Nzc4YzMuMjQyNjY3IDExLjk0NjY2NyAyLjg0NDQ0NCAyNC40NjIyMjItMS40MjIyMjMgMzYuNDA4ODg5YTYyLjkxOTExMSA2Mi45MTkxMTEgMCAwIDEtMjEuOTU5MTExIDI5LjUyNTMzMyA2NS4yNTE1NTYgNjUuMjUxNTU2IDAgMCAxLTM4LjkxMiAxMi41MTU1NTZIMTc4LjExOTExMWE2NC44NTMzMzMgNjQuODUzMzMzIDAgMCAxLTM4Ljc5ODIyMi0xMi41NzI0NDUgNjIuMjM2NDQ0IDYyLjIzNjQ0NCAwIDAgMS0yMi4wMTYtMjkuNTI1MzMzIDYwLjY0MzU1NiA2MC42NDM1NTYgMCAwIDEtMS4zNjUzMzMtMzYuNDA4ODg5YzMuNTg0LTEzLjE0MTMzMyAxMS40MzQ2NjctMjQuNTc2IDIyLjY5ODY2Ni0zMy4xMDkzMzNsNTguNDgxNzc4LTQ0LjAzMmE0MC43MzI0NDQgNDAuNzMyNDQ0IDAgMCAwIDE2LjQ5Nzc3OC0zMi43MTExMTJ2LTIwMy4wOTMzMzNjMC0zNS4yMTQyMjIgNy4xNjgtNjkuNTE4MjIyIDIxLjIxOTU1NS0xMDEuNzE3MzMzIDEzLjY1MzMzMy0zMS4xNzUxMTEgMzMuMTA5MzMzLTU5LjE2NDQ0NCA1Ny44NTYtODMuMTE0NjY3QTI2OC44NTY4ODkgMjY4Ljg1Njg4OSAwIDAgMSA0MTQuNzIgMTUyLjA2NHYtMjguNTAxMzMzQzQxNC43MiA4Ni44MTI0NDQgNDQ1LjYxMDY2NyA1Ni44ODg4ODkgNDgzLjU1NTU1NiA1Ni44ODg4ODljMzcuOTQ0ODg5IDAgNjguODM1NTU2IDI5LjkyMzU1NiA2OC44MzU1NTUgNjYuNjczNzc4djI4LjUwMTMzM2MxMi4zNDQ4ODkgMy4xODU3NzggMjQuNDYyMjIyIDcuMTY4IDM2LjIzODIyMiAxMi4wMDM1NTZhMjY4LjY4NjIyMiAyNjguNjg2MjIyIDAgMCAxIDg1Ljc4ODQ0NSA1Ni4wMzU1NTVjMjQuNzQ2NjY3IDI0LjAwNzExMSA0NC4yMDI2NjcgNTEuOTM5NTU2IDU3Ljc5OTExMSA4My4wNTc3NzggMTQuMTA4NDQ0IDMyLjMxMjg4OSAyMS4yMTk1NTYgNjYuNTYgMjEuMjE5NTU1IDEwMS44MzExMTF2MjAzLjA5MzMzM2MwIDEyLjg1Njg4OSA2LjAzMDIyMiAyNC44NjA0NDQgMTYuNTU0NjY3IDMyLjcxMTExMWw1OC40ODE3NzggNDQuMDMyYzExLjIwNzExMSA4LjUzMzMzMyAxOS4wNTc3NzggMTkuOTExMTExIDIyLjc1NTU1NSAzMy4wNTI0NDV6TTM5OC4yMjIyMjIgODU2LjE3Nzc3OFY4NTMuMzMzMzMzaDE3MC42NjY2Njd2Mi44NDQ0NDVDNTY4Ljg4ODg4OSA5MzUuOTM2IDUzMC42MDI2NjcgOTY3LjExMTExMSA0ODMuNTU1NTU2IDk2Ny4xMTExMTFTMzk4LjIyMjIyMiA5MzUuOTM2IDM5OC4yMjIyMjIgODU2LjE3Nzc3OHoiIHAtaWQ9IjM1MzMiIGZpbGw9IiNmZmZmZmYiPjwvcGF0aD48L3N2Zz4=") no-repeat 50% 50%; + background-size: 85%; +} + +.iziToast.iziToast-theme-dark .iziToast-icon.ico-warning { + background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTQxNjUxMTE1OTQ4IiBjbGFzcz0iaWNvbiIgc3R5bGU9IiIgdmlld0JveD0iMCAwIDEwMjUgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjUwOTYiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTI4LjEyNSIgaGVpZ2h0PSIxMjgiPjxkZWZzPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PC9zdHlsZT48L2RlZnM+PHBhdGggZD0iTTk4NC4wMjI5NTAwMiA3NDYuODc1NDk3NUw2NDEuOTY0NjA3NTIgMTMwLjM4MDY1Yy0zMC40OTE4NDI1LTU0Ljg2MTUwMjUtNzcuOTMxMzE1LTg2LjMzNTY3MjUtMTMwLjE0MzUxLTg2LjMzNTY3MjUtNTIuMjkxNTc1IDAtOTkuNzQwOTcgMzEuNTEzODYtMTMwLjE0MzUxIDg2LjQzNDg5NzVMMzkuOTc2NDU1MDIgNzQ2LjgyNTg4NUM5Ljk2MDg5MjUyIDgwMC45NjMwNDUgNy45MTY4NTc1MiA4NTguMDE3NDIgMzQuMzUwMzk3NTIgOTAzLjM1MzMyMjVjMjYuNTEyOTIgNDUuNDc0ODE3NSA3Ny4xOTcwNSA3MS41NjEwNyAxMzkuMDczNzYgNzEuNTYxMDdoNjc3LjIyMDU0NzVjNjEuOTA2NDc3NSAwIDExMi41OTA2MDc1LTI2LjA4NjI1MjUgMTM5LjAxNDIyNS03MS40OTE2MTI1IDI2LjQ4MzE1MjUtNDUuMjc2MzY3NSAyNC40MjkxOTUtMTAyLjM0MDY2NS01LjYzNTk4LTE1Ni41NDcyODI1ek05MTEuNzU3MzgyNTIgODU3Ljk5NzU3NWMtOS44OTI3MzI1IDE2Ljk4NzMyLTMyLjE1ODgyMjUgMjYuNzMxMjE1LTYxLjExMjY3NzUgMjYuNzMxMjE1SDE3My40MjQxNTc1MmMtMjguOTQzOTMyNSAwLTUxLjIyOTg2NzUtOS43NjM3NC02MS4xNjIyOS0yNi43OTA3NS0xMC4wMjE3MjUtMTcuMTg1NzctNy42MTA1NTc1LTQxLjc0Mzk1NzUgNi41ODg1NC02Ny4zNzM3NzVsMzQxLjcxMTA1NS02MTYuMzY1ODU1YzE0LjA2MDE4MjUtMjUuMzkxNjc3NSAzMi43NTQxNzI1LTM5Ljk1NzkwNzUgNTEuMjU5NjM1LTM5Ljk1NzkwNzUgMTguNDk1NTQgMCAzNy4xOTk0NTI1IDE0LjU2NjIzIDUxLjMwOTI0NzUgMzkuOTM4MDYyNWwzNDIuMDI4NTc1IDYxNi40NDUyMzVjMTQuMjI4ODY1IDI1LjY0OTY2MjUgMTYuNjQwMDMyNSA1MC4xODgwMDUgNi41OTg0NjI1IDY3LjM3Mzc3NXoiIGZpbGw9IiNmZmZmZmYiIHAtaWQ9IjUwOTciPjwvcGF0aD48cGF0aCBkPSJNNTEyLjAxOTU0NzUyIDYzMC4yODYxMjI1YTQ1LjA4Nzg0IDQ1LjA4Nzg0IDAgMCAwIDQ1LjA5Nzc2MjUtNDUuMDA4NDZWMzc0LjY1Mjc1NWE0NS4wNzc5MTc1IDQ1LjA3NzkxNzUgMCAwIDAtNDUuMDk3NzYyNS00NS4wMDg0NiA0NS4wODc4NCA0NS4wODc4NCAwIDAgMC00NS4wOTc3NjI1IDQ1LjAwODQ2djIxMC42MTQ5ODVhNDUuMDg3ODQgNDUuMDg3ODQgMCAwIDAgNDUuMDk3NzYyNSA0NS4wMTgzODI1ek01MTIuMDE5NTQ3NTIgNjc1LjM3Mzk2MjVhNjAuMTcwMDQgNjAuMTcwMDQgMCAwIDAtNjAuMTMwMzUgNjAuMTMwMzVjMCAzMy4xNDExNSAyNi45MTk3NDI1IDYwLjEzMDM1IDYwLjEzMDM1IDYwLjEzMDM1IDMzLjE0MTE1IDAgNjAuMTMwMzUtMjYuOTE5NzQyNSA2MC4xMzAzNS02MC4xMzAzNSAwLTMzLjE0MTE1LTI2LjkxOTc0MjUtNjAuMTMwMzUtNjAuMTMwMzUtNjAuMTMwMzV6IiBmaWxsPSIjZmZmZmZmIiBwLWlkPSI1MDk4Ij48L3BhdGg+PC9zdmc+") no-repeat 50% 50%; + background-size: 85%; +} + +.iziToast.iziToast-theme-dark .iziToast-icon.ico-error { + background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTQxNjUxMzE1NTQ3IiBjbGFzcz0iaWNvbiIgc3R5bGU9IiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjY4MDYiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNNzcyLjI2NjY2NyA4ODMuMmMyNS42IDI1LjYgNjQgMjUuNiA4OS42IDAgMjUuNi0yNS42IDI1LjYtNjQgMC04OS42TDIzMC40IDE2Mi4xMzMzMzNjLTI1LjYtMjUuNi02NC0yNS42LTg5LjYgMC0yNS42IDI1LjYtMjUuNiA2NCAwIDg5LjZsNjMxLjQ2NjY2NyA2MzEuNDY2NjY3eiIgcC1pZD0iNjgwNyIgZmlsbD0iI2ZmZmZmZiI+PC9wYXRoPjxwYXRoIGQ9Ik04NjEuODY2NjY3IDI1MS43MzMzMzNjMjUuNi0yNS42IDI1LjYtNjQgMC04OS42LTI1LjYtMjUuNi02NC0yNS42LTg5LjYgMEwxNDAuOCA3OTMuNmMtMjUuNiAyNS42LTI1LjYgNjQgMCA4OS42czY0IDI1LjYgODkuNiAwbDYzMS40NjY2NjctNjMxLjQ2NjY2N3oiIHAtaWQ9IjY4MDgiIGZpbGw9IiNmZmZmZmYiPjwvcGF0aD48L3N2Zz4=") no-repeat 50% 50%; + background-size: 80%; +} + +.iziToast.iziToast-theme-dark .iziToast-icon.ico-success { + background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTQxNjUxMjQyNTMxIiBjbGFzcz0iaWNvbiIgc3R5bGU9IiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjYwMjMiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNNDA0LjI1MTQyOCA4MDkuNjEwN2MtMTEuNjY0MTAyIDAtMjMuMzI3MTc5LTQuNDQ4NzgyLTMyLjIyNTc2Ny0xMy4zNDczNjlMODMuOTgwMDk4IDUwOC4yMTk4MTVjLTE3Ljc5ODE5OS0xNy43OTcxNzUtMTcuNzk4MTk5LTQ2LjY1MzMzNSAwLTY0LjQ1MTUzM3M0Ni42NTMzMzUtMTcuNzk4MTk5IDY0LjQ1MTUzNCAwbDI4OC4wNDQ1MzkgMjg4LjA0MjQ5MWMxNy43OTgxOTkgMTcuNzk4MTk5IDE3Ljc5ODE5OSA0Ni42NTQzNTkgMCA2NC40NTI1NTgtOC44OTc1NjMgOC44OTg1ODctMjAuNTYxNjY1IDEzLjM0NzM2OS0zMi4yMjQ3NDMgMTMuMzQ3MzY5eiIgcC1pZD0iNjAyNCIgZmlsbD0iI2ZmZmZmZiI+PC9wYXRoPjxwYXRoIGQ9Ik00MDQuMjczOTUzIDgwOS42MTE3MjNjLTExLjY2NDEwMiAwLTIzLjMyNjE1NS00LjQ0OTgwNi0zMi4yMjU3NjYtMTMuMzQ4MzkyLTE3Ljc5ODE5OS0xNy43OTcxNzUtMTcuNzk5MjIyLTQ2LjY1MzMzNS0wLjAwMTAyNC02NC40NTE1MzRMODc2LjEwMTgxMyAyMjcuNzM1NjQ2YzE3Ljc5NjE1MS0xNy43OTgxOTkgNDYuNjUzMzM1LTE3Ljc5OTIyMiA2NC40NTE1MzMtMC4wMDEwMjQgMTcuNzk4MTk5IDE3Ljc5NzE3NSAxNy43OTkyMjIgNDYuNjUzMzM1IDAuMDAxMDI0IDY0LjQ1MTUzM0w0MzYuNTAwNzQ0IDc5Ni4yNjIzMDdjLTguODk4NTg3IDguODk4NTg3LTIwLjU2MjY4OSAxMy4zNDk0MTctMzIuMjI2NzkxIDEzLjM0OTQxNnoiIHAtaWQ9IjYwMjUiIGZpbGw9IiNmZmZmZmYiPjwvcGF0aD48L3N2Zz4=") no-repeat 50% 50%; + background-size: 85%; +} + +.iziToast.iziToast-theme-dark .iziToast-icon.ico-question { + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAQAAAAAYLlVAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfhCQkUEg18vki+AAAETUlEQVRo3s1ZTWhbRxD+VlIuxsLFCYVIIQYVopBDoK5bKDWUBupDMNbJ5FBKg/FBziUQdE9yaC+FHBrwsdCfQ9RTGoLxwWl+DqHEojUFFydxnB9bInZDqOsErBrr6yGvs/ueX97bldTKo4Pe7puZb3Z33s7srIIjMY1jyCEjP6ImvyX8pF64arSHznKC06wzijY5xSKz7YbuYokV2lODsyyxqz3gSY6z6gCuqcpxJluFH+Z8U+D/0jyHoxFUBHgfvsGHIS9WMIUlVFFDFTUAGWSRQRY5HMeBEP6b+Ew9dh/7INd2jGeO59kfKdXP85zbIbfGQVf4sYC3N1hm3lo6zzIbPvk6x+zBk7wQGMEMB5xncIAzAS0XrFySSV72iS1yyBVcdA1x0afrsoUJgdFfY2+z8ADAXl7zz0KcwJiPfZKpVuABgClO+nRG+QIHDdfb4qlWwUXvKW4Z7vi6L4J9vg+vbfCeCeZH2RfOdMOc/HbCA4BvIW6EMQz7XK/ltd+hP+VzR9mgva2YSfyGI17fA7ynnocqeQNFfIJ0oHsdv6CC2+rXGBN6cQdveY3fcVRtmy/HDete+93zy8jA8zV7YkwYMrjHzRddRsCdiVCwwmh6wg9iTNC7Y9XIF1iS7kbUpsvvGEdPuTfSgAEjRpR096x0liPFD/Eqt2NMuBQzB2XhrACAApjFsuQFh9XdGAX70B3oSuNdnMVBaX+sopYxjwVpHFBVACyKTXNoktjD+6Ll8xhenS9MAAkAI/Lux2YNUOs4I413Ypg1SgEAu7kpFvWjaeJe0fJHDGe/cNaZBkekudw8PMA+0fMwlndZeAsJ5KR/qhUDUJCnSiyvRsolkJHGUgvjH8QXDgZopEzKMKDqCKrwEQ4C6MH7GEXC665buLJG8hlQc4LP4paxfJrOqYVYYY2UARfEIazTbgDg2dB98GebzJd54b8L/iWNdLyooeR6CHyZ+6xk0yKxkYg6nEVSUG4VJ9QJ9cxRCxO+9WiOyvgUeexXP1hLGH5nGuBWVtiSp4vqe3VP0UFWI9Wan4Er3v8q7jjPWVtm4FtcQQMrOKO2nOQCM5AyDMi56FDrKHA/1nyppS1ppBpYaE8wciEjGI2AaeM41kI4doDX4XiT3Qm1gevyruCgZg9P8xIv8m1nCzTKq6oiJ9xTMiZ505P5m8cdZ0CnZMVXHVljM7WMBzxpyDxygtdxoCEFTaMIWbZU85UvBjgUMYy0fBaAF8V1Lj9qWQ1aMZ5f4k9r+AGMSkMP1vZoZih6k6sicc5h/OFHM9vDqU/VIU7zJZdYYsKGH4g4nAJMGiXZRds1pVMoZ69RM5vfkbh0qkBhsnS2RLMLilQdL9MBHS9UAh0v1e6CYnXHy/WeeCcvLDwl/9OVze69tPKM+M+v7eJN6OzFpWdEF0ucDbhVNFXadnVrmJFlkVNGTS2M6pzmhMvltfPhnN2B63sVuL7fcNP3D1TSk2ihosPrAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTA5LTA5VDIwOjE4OjEzKzAyOjAweOR7nQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wOS0wOVQyMDoxODoxMyswMjowMAm5wyEAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC") no-repeat 50% 50%; + background-size: 85%; +} + +.iziToast.iziToast-theme-dark .iziToast-buttons > a, +.iziToast.iziToast-theme-dark .iziToast-buttons > button, +.iziToast.iziToast-theme-dark .iziToast-buttons > input { + color: #fff; + background: rgba(255, 255, 255, 0.1); +} + +.iziToast.iziToast-theme-dark .iziToast-buttons > a:hover, +.iziToast.iziToast-theme-dark .iziToast-buttons > button:hover, +.iziToast.iziToast-theme-dark .iziToast-buttons > input:hover { + background: rgba(255, 255, 255, 0.2); +} + +.iziToast.iziToast-theme-dark .iziToast-buttons > a:focus, +.iziToast.iziToast-theme-dark .iziToast-buttons > button:focus, +.iziToast.iziToast-theme-dark .iziToast-buttons > input:focus { + box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.6); +} + +.iziToast.iziToast-theme-dark.iziToast-color-red { + background: #F56C6C; + border-color: #F56C6C; +} + +.iziToast.iziToast-theme-dark.iziToast-color-orange { + background: #E6A23C; + border-color: #E6A23C; +} + +.iziToast.iziToast-theme-dark.iziToast-color-yellow { + background: rgba(255, 249, 178, 0.9); + border-color: rgba(255, 249, 178, 0.9); +} + +.iziToast.iziToast-theme-dark.iziToast-color-blue { + background: #409EFF; + border-color: #409EFF; +} + +.iziToast.iziToast-theme-dark.iziToast-color-green { + background: #67C23A; + border-color: #67C23A; +} + +.iziToast.iziToast-layout2 .iziToast-body .iziToast-texts, +.iziToast.iziToast-layout2 .iziToast-body .iziToast-message { + width: 100%; +} + +.iziToast.iziToast-layout3 { + border-radius: 2px; +} + +.iziToast.iziToast-layout3::after { + display: none; +} + +.iziToast.revealIn, +.iziToast .revealIn { + -webkit-animation: iziT-revealIn 1s cubic-bezier(0.25, 1.6, 0.25, 1) both; + -moz-animation: iziT-revealIn 1s cubic-bezier(0.25, 1.6, 0.25, 1) both; + animation: iziT-revealIn 1s cubic-bezier(0.25, 1.6, 0.25, 1) both; +} + +.iziToast.slideIn, +.iziToast .slideIn { + -webkit-animation: iziT-slideIn 1s cubic-bezier(0.16, 0.81, 0.32, 1) both; + -moz-animation: iziT-slideIn 1s cubic-bezier(0.16, 0.81, 0.32, 1) both; + animation: iziT-slideIn 1s cubic-bezier(0.16, 0.81, 0.32, 1) both; +} + +.iziToast.bounceInLeft { + -webkit-animation: iziT-bounceInLeft 0.7s ease-in-out both; + animation: iziT-bounceInLeft 0.7s ease-in-out both; +} + +.iziToast.bounceInRight { + -webkit-animation: iziT-bounceInRight 0.85s ease-in-out both; + animation: iziT-bounceInRight 0.85s ease-in-out both; +} + +.iziToast.bounceInDown { + -webkit-animation: iziT-bounceInDown 0.7s ease-in-out both; + animation: iziT-bounceInDown 0.7s ease-in-out both; +} + +.iziToast.bounceInUp { + -webkit-animation: iziT-bounceInUp 0.7s ease-in-out both; + animation: iziT-bounceInUp 0.7s ease-in-out both; +} + +.iziToast.fadeIn, +.iziToast .fadeIn { + -webkit-animation: iziT-fadeIn 0.5s ease both; + animation: iziT-fadeIn 0.5s ease both; +} + +.iziToast.fadeInUp { + -webkit-animation: iziT-fadeInUp 0.7s ease both; + animation: iziT-fadeInUp 0.7s ease both; +} + +.iziToast.fadeInDown { + -webkit-animation: iziT-fadeInDown 0.7s ease both; + animation: iziT-fadeInDown 0.7s ease both; +} + +.iziToast.fadeInLeft { + -webkit-animation: iziT-fadeInLeft 0.85s cubic-bezier(0.25, 0.8, 0.25, 1) both; + animation: iziT-fadeInLeft 0.85s cubic-bezier(0.25, 0.8, 0.25, 1) both; +} + +.iziToast.fadeInRight { + -webkit-animation: iziT-fadeInRight 0.85s cubic-bezier(0.25, 0.8, 0.25, 1) both; + animation: iziT-fadeInRight 0.85s cubic-bezier(0.25, 0.8, 0.25, 1) both; +} + +.iziToast.flipInX { + -webkit-animation: iziT-flipInX 0.85s cubic-bezier(0.35, 0, 0.25, 1) both; + animation: iziT-flipInX 0.85s cubic-bezier(0.35, 0, 0.25, 1) both; +} + +.iziToast.fadeOut { + -webkit-animation: iziT-fadeOut 0.7s ease both; + animation: iziT-fadeOut 0.7s ease both; +} + +.iziToast.fadeOutDown { + -webkit-animation: iziT-fadeOutDown 0.7s cubic-bezier(0.4, 0.45, 0.15, 0.91) both; + animation: iziT-fadeOutDown 0.7s cubic-bezier(0.4, 0.45, 0.15, 0.91) both; +} + +.iziToast.fadeOutUp { + -webkit-animation: iziT-fadeOutUp 0.7s cubic-bezier(0.4, 0.45, 0.15, 0.91) both; + animation: iziT-fadeOutUp 0.7s cubic-bezier(0.4, 0.45, 0.15, 0.91) both; +} + +.iziToast.fadeOutLeft { + -webkit-animation: iziT-fadeOutLeft 0.5s ease both; + animation: iziT-fadeOutLeft 0.5s ease both; +} + +.iziToast.fadeOutRight { + -webkit-animation: iziT-fadeOutRight 0.5s ease both; + animation: iziT-fadeOutRight 0.5s ease both; +} + +.iziToast.flipOutX { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation: iziT-flipOutX 0.7s cubic-bezier(0.4, 0.45, 0.15, 0.91) both; + animation: iziT-flipOutX 0.7s cubic-bezier(0.4, 0.45, 0.15, 0.91) both; +} + +.iziToast-overlay.fadeIn { + -webkit-animation: iziT-fadeIn 0.5s ease both; + animation: iziT-fadeIn 0.5s ease both; +} + +.iziToast-overlay.fadeOut { + -webkit-animation: iziT-fadeOut 0.7s ease both; + animation: iziT-fadeOut 0.7s ease both; +} + +@-webkit-keyframes iziT-revealIn { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 1); + } + 100% { + opacity: 1; + } +} + +@-moz-keyframes iziT-revealIn { + 0% { + opacity: 0; + -moz-transform: scale3d(0.3, 0.3, 1); + } + 100% { + opacity: 1; + } +} + +@-webkit-keyframes iziT-slideIn { + 0% { + opacity: 0; + -webkit-transform: translateX(50px); + } + 100% { + opacity: 1; + -webkit-transform: translateX(0); + } +} + +@-moz-keyframes iziT-slideIn { + 0% { + opacity: 0; + -moz-transform: translateX(50px); + } + 100% { + opacity: 1; + -moz-transform: translateX(0); + } +} + +@-webkit-keyframes iziT-bounceInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(280px); + } + 50% { + opacity: 1; + -webkit-transform: translateX(-20px); + } + 70% { + -webkit-transform: translateX(10px); + } + 100% { + -webkit-transform: translateX(0); + } +} + +@-webkit-keyframes iziT-bounceInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(-280px); + } + 50% { + opacity: 1; + -webkit-transform: translateX(20px); + } + 70% { + -webkit-transform: translateX(-10px); + } + 100% { + -webkit-transform: translateX(0); + } +} + +@-webkit-keyframes iziT-bounceInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-200px); + } + 50% { + opacity: 1; + -webkit-transform: translateY(10px); + } + 70% { + -webkit-transform: translateY(-5px); + } + 100% { + -webkit-transform: translateY(0); + } +} + +@-webkit-keyframes iziT-bounceInUp { + 0% { + opacity: 0; + -webkit-transform: translateY(200px); + } + 50% { + opacity: 1; + -webkit-transform: translateY(-10px); + } + 70% { + -webkit-transform: translateY(5px); + } + 100% { + -webkit-transform: translateY(0); + } +} + +@-webkit-keyframes iziT-fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@-webkit-keyframes iziT-fadeInUp { + from { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-webkit-keyframes iziT-fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-webkit-keyframes iziT-fadeInLeft { + from { + opacity: 0; + -webkit-transform: translate3d(300px, 0, 0); + transform: translate3d(300px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-webkit-keyframes iziT-fadeInRight { + from { + opacity: 0; + -webkit-transform: translate3d(-300px, 0, 0); + transform: translate3d(-300px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-webkit-keyframes iziT-flipInX { + from { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + } + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1; + } + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +@-webkit-keyframes iziT-fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@-webkit-keyframes iziT-fadeOutDown { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@-webkit-keyframes iziT-fadeOutUp { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@-webkit-keyframes iziT-fadeOutLeft { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(-200px, 0, 0); + transform: translate3d(-200px, 0, 0); + } +} + +@-webkit-keyframes iziT-fadeOutRight { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(200px, 0, 0); + transform: translate3d(200px, 0, 0); + } +} + +@-webkit-keyframes iziT-flipOutX { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1; + } + to { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } +} + +@-moz-keyframes iziT-revealIn { + 0% { + opacity: 0; + transform: scale3d(0.3, 0.3, 1); + } + 100% { + opacity: 1; + } +} + +@-webkit-keyframes iziT-revealIn { + 0% { + opacity: 0; + transform: scale3d(0.3, 0.3, 1); + } + 100% { + opacity: 1; + } +} + +@-o-keyframes iziT-revealIn { + 0% { + opacity: 0; + transform: scale3d(0.3, 0.3, 1); + } + 100% { + opacity: 1; + } +} + +@keyframes iziT-revealIn { + 0% { + opacity: 0; + transform: scale3d(0.3, 0.3, 1); + } + 100% { + opacity: 1; + } +} + +@-moz-keyframes iziT-slideIn { + 0% { + opacity: 0; + transform: translateX(50px); + } + 100% { + opacity: 1; + transform: translateX(0); + } +} + +@-webkit-keyframes iziT-slideIn { + 0% { + opacity: 0; + transform: translateX(50px); + } + 100% { + opacity: 1; + transform: translateX(0); + } +} + +@-o-keyframes iziT-slideIn { + 0% { + opacity: 0; + transform: translateX(50px); + } + 100% { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes iziT-slideIn { + 0% { + opacity: 0; + transform: translateX(50px); + } + 100% { + opacity: 1; + transform: translateX(0); + } +} + +@-moz-keyframes iziT-bounceInLeft { + 0% { + opacity: 0; + transform: translateX(280px); + } + 50% { + opacity: 1; + transform: translateX(-20px); + } + 70% { + transform: translateX(10px); + } + 100% { + transform: translateX(0); + } +} + +@-webkit-keyframes iziT-bounceInLeft { + 0% { + opacity: 0; + transform: translateX(280px); + } + 50% { + opacity: 1; + transform: translateX(-20px); + } + 70% { + transform: translateX(10px); + } + 100% { + transform: translateX(0); + } +} + +@-o-keyframes iziT-bounceInLeft { + 0% { + opacity: 0; + transform: translateX(280px); + } + 50% { + opacity: 1; + transform: translateX(-20px); + } + 70% { + transform: translateX(10px); + } + 100% { + transform: translateX(0); + } +} + +@keyframes iziT-bounceInLeft { + 0% { + opacity: 0; + transform: translateX(280px); + } + 50% { + opacity: 1; + transform: translateX(-20px); + } + 70% { + transform: translateX(10px); + } + 100% { + transform: translateX(0); + } +} + +@-moz-keyframes iziT-bounceInRight { + 0% { + opacity: 0; + transform: translateX(-280px); + } + 50% { + opacity: 1; + transform: translateX(20px); + } + 70% { + transform: translateX(-10px); + } + 100% { + transform: translateX(0); + } +} + +@-webkit-keyframes iziT-bounceInRight { + 0% { + opacity: 0; + transform: translateX(-280px); + } + 50% { + opacity: 1; + transform: translateX(20px); + } + 70% { + transform: translateX(-10px); + } + 100% { + transform: translateX(0); + } +} + +@-o-keyframes iziT-bounceInRight { + 0% { + opacity: 0; + transform: translateX(-280px); + } + 50% { + opacity: 1; + transform: translateX(20px); + } + 70% { + transform: translateX(-10px); + } + 100% { + transform: translateX(0); + } +} + +@keyframes iziT-bounceInRight { + 0% { + opacity: 0; + transform: translateX(-280px); + } + 50% { + opacity: 1; + transform: translateX(20px); + } + 70% { + transform: translateX(-10px); + } + 100% { + transform: translateX(0); + } +} + +@-moz-keyframes iziT-bounceInDown { + 0% { + opacity: 0; + transform: translateY(-200px); + } + 50% { + opacity: 1; + transform: translateY(10px); + } + 70% { + transform: translateY(-5px); + } + 100% { + transform: translateY(0); + } +} + +@-webkit-keyframes iziT-bounceInDown { + 0% { + opacity: 0; + transform: translateY(-200px); + } + 50% { + opacity: 1; + transform: translateY(10px); + } + 70% { + transform: translateY(-5px); + } + 100% { + transform: translateY(0); + } +} + +@-o-keyframes iziT-bounceInDown { + 0% { + opacity: 0; + transform: translateY(-200px); + } + 50% { + opacity: 1; + transform: translateY(10px); + } + 70% { + transform: translateY(-5px); + } + 100% { + transform: translateY(0); + } +} + +@keyframes iziT-bounceInDown { + 0% { + opacity: 0; + transform: translateY(-200px); + } + 50% { + opacity: 1; + transform: translateY(10px); + } + 70% { + transform: translateY(-5px); + } + 100% { + transform: translateY(0); + } +} + +@-moz-keyframes iziT-bounceInUp { + 0% { + opacity: 0; + transform: translateY(200px); + } + 50% { + opacity: 1; + transform: translateY(-10px); + } + 70% { + transform: translateY(5px); + } + 100% { + transform: translateY(0); + } +} + +@-webkit-keyframes iziT-bounceInUp { + 0% { + opacity: 0; + transform: translateY(200px); + } + 50% { + opacity: 1; + transform: translateY(-10px); + } + 70% { + transform: translateY(5px); + } + 100% { + transform: translateY(0); + } +} + +@-o-keyframes iziT-bounceInUp { + 0% { + opacity: 0; + transform: translateY(200px); + } + 50% { + opacity: 1; + transform: translateY(-10px); + } + 70% { + transform: translateY(5px); + } + 100% { + transform: translateY(0); + } +} + +@keyframes iziT-bounceInUp { + 0% { + opacity: 0; + transform: translateY(200px); + } + 50% { + opacity: 1; + transform: translateY(-10px); + } + 70% { + transform: translateY(5px); + } + 100% { + transform: translateY(0); + } +} + +@-moz-keyframes iziT-fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@-webkit-keyframes iziT-fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@-o-keyframes iziT-fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes iziT-fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@-moz-keyframes iziT-fadeInUp { + from { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-webkit-keyframes iziT-fadeInUp { + from { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-o-keyframes iziT-fadeInUp { + from { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes iziT-fadeInUp { + from { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-moz-keyframes iziT-fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-webkit-keyframes iziT-fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-o-keyframes iziT-fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes iziT-fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-moz-keyframes iziT-fadeInLeft { + from { + opacity: 0; + -webkit-transform: translate3d(300px, 0, 0); + transform: translate3d(300px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-webkit-keyframes iziT-fadeInLeft { + from { + opacity: 0; + -webkit-transform: translate3d(300px, 0, 0); + transform: translate3d(300px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-o-keyframes iziT-fadeInLeft { + from { + opacity: 0; + -webkit-transform: translate3d(300px, 0, 0); + transform: translate3d(300px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes iziT-fadeInLeft { + from { + opacity: 0; + -webkit-transform: translate3d(300px, 0, 0); + transform: translate3d(300px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-moz-keyframes iziT-fadeInRight { + from { + opacity: 0; + -webkit-transform: translate3d(-300px, 0, 0); + transform: translate3d(-300px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-webkit-keyframes iziT-fadeInRight { + from { + opacity: 0; + -webkit-transform: translate3d(-300px, 0, 0); + transform: translate3d(-300px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-o-keyframes iziT-fadeInRight { + from { + opacity: 0; + -webkit-transform: translate3d(-300px, 0, 0); + transform: translate3d(-300px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes iziT-fadeInRight { + from { + opacity: 0; + -webkit-transform: translate3d(-300px, 0, 0); + transform: translate3d(-300px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@-moz-keyframes iziT-flipInX { + from { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + } + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1; + } + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +@-webkit-keyframes iziT-flipInX { + from { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + } + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1; + } + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +@-o-keyframes iziT-flipInX { + from { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + } + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1; + } + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +@keyframes iziT-flipInX { + from { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + } + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1; + } + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +@-moz-keyframes iziT-fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@-webkit-keyframes iziT-fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@-o-keyframes iziT-fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@keyframes iziT-fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@-moz-keyframes iziT-fadeOutDown { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@-webkit-keyframes iziT-fadeOutDown { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@-o-keyframes iziT-fadeOutDown { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@keyframes iziT-fadeOutDown { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@-moz-keyframes iziT-fadeOutUp { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@-webkit-keyframes iziT-fadeOutUp { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@-o-keyframes iziT-fadeOutUp { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@keyframes iziT-fadeOutUp { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@-moz-keyframes iziT-fadeOutLeft { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(-200px, 0, 0); + transform: translate3d(-200px, 0, 0); + } +} + +@-webkit-keyframes iziT-fadeOutLeft { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(-200px, 0, 0); + transform: translate3d(-200px, 0, 0); + } +} + +@-o-keyframes iziT-fadeOutLeft { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(-200px, 0, 0); + transform: translate3d(-200px, 0, 0); + } +} + +@keyframes iziT-fadeOutLeft { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(-200px, 0, 0); + transform: translate3d(-200px, 0, 0); + } +} + +@-moz-keyframes iziT-fadeOutRight { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(200px, 0, 0); + transform: translate3d(200px, 0, 0); + } +} + +@-webkit-keyframes iziT-fadeOutRight { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(200px, 0, 0); + transform: translate3d(200px, 0, 0); + } +} + +@-o-keyframes iziT-fadeOutRight { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(200px, 0, 0); + transform: translate3d(200px, 0, 0); + } +} + +@keyframes iziT-fadeOutRight { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(200px, 0, 0); + transform: translate3d(200px, 0, 0); + } +} + +@-moz-keyframes iziT-flipOutX { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1; + } + to { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } +} + +@-webkit-keyframes iziT-flipOutX { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1; + } + to { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } +} + +@-o-keyframes iziT-flipOutX { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1; + } + to { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } +} + +@keyframes iziT-flipOutX { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1; + } + to { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/topBar.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/topBar.css new file mode 100644 index 0000000000000000000000000000000000000000..c3d5becac6bcd414ba7ce409560d3742b872a005 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/topBar.css @@ -0,0 +1,5 @@ +.layui-fixbar li { + border-radius: 4px; + background-color: #5FB878; + color: white; +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/module/treetable.css b/demo/webman/backend/plugin/admin/public/component/pear/css/module/treetable.css new file mode 100644 index 0000000000000000000000000000000000000000..da849b89ae83d09e7c8ee5c73954df9ed9cb9ce1 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/module/treetable.css @@ -0,0 +1,25 @@ +.treeTable-icon i:last-child{ + display: none!important; +} + +.treeTable-empty{ + margin-left: -3px; +} +.treeTable-empty { + width: 20px; + display: inline-block; +} + +.treeTable-icon { + cursor: pointer; +} + +.treeTable-icon .layui-icon-triangle-d:before { + content: "\e623"; +} + +.treeTable-icon.open .layui-icon-triangle-d:before { + content: "\e625"; + background-color: transparent; +} + diff --git a/demo/webman/backend/plugin/admin/public/component/pear/css/pear.css b/demo/webman/backend/plugin/admin/public/component/pear/css/pear.css new file mode 100644 index 0000000000000000000000000000000000000000..279afd9f0c7be2bede3d37286e903b4dbfa1abcc --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/css/pear.css @@ -0,0 +1,30 @@ +@import url("../../layui/css/layui.css"); +@import url("../font/iconfont.css"); + +@import url("module/dtree/font/dtreefont.css"); +@import url("module/dtree/dtree.css"); +@import url("module/iconPicker.css"); +@import url("module/treetable.css"); +@import url("module/nprogress.css"); +@import url("module/message.css"); +@import url("module/cropper.css"); +@import url("module/loading.css"); +@import url("module/topBar.css"); +@import url("module/select.css"); +@import url("module/layout.css"); +@import url("module/notice.css"); +@import url("module/button.css"); +/*@import url("module/table.css");//变更*/ +@import url("module/frame.css"); +@import url("module/layer.css"); +@import url("module/toast.css"); +@import url("module/menu.css"); +@import url("module/form.css"); +@import url("module/link.css"); +@import url("module/code.css"); +@import url("module/step.css"); +@import url("module/card.css"); +@import url("module/tab.css"); +@import url("module/tag.css"); +@import url("module/fullscreen.css"); +@import url("module/popover.min.css"); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.css b/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.css new file mode 100644 index 0000000000000000000000000000000000000000..5f6eb5fdd0f54dc8c1c1347ea95d8cb0ff28418c --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.css @@ -0,0 +1,579 @@ +@font-face { + font-family: "pear-icon"; /* Project id 2654996 */ + src: url('iconfont.woff2?t=1625555217253') format('woff2'), + url('iconfont.woff?t=1625555217253') format('woff'), + url('iconfont.ttf?t=1625555217253') format('truetype'); +} + +.pear-icon { + font-family: "pear-icon" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.pear-icon-load:before { + content: "\e6f0"; +} + +.pear-icon-download:before { + content: "\e68d"; +} + +.pear-icon-electronics:before { + content: "\e68e"; +} + +.pear-icon-drag:before { + content: "\e68f"; +} + +.pear-icon-elipsis:before { + content: "\e690"; +} + +.pear-icon-export:before { + content: "\e691"; +} + +.pear-icon-explain:before { + content: "\e692"; +} + +.pear-icon-edit:before { + content: "\e693"; +} + +.pear-icon-eye-close:before { + content: "\e694"; +} + +.pear-icon-email:before { + content: "\e695"; +} + +.pear-icon-error:before { + content: "\e696"; +} + +.pear-icon-favorite:before { + content: "\e697"; +} + +.pear-icon-file-common:before { + content: "\e698"; +} + +.pear-icon-file-delete:before { + content: "\e699"; +} + +.pear-icon-file-add:before { + content: "\e69a"; +} + +.pear-icon-film:before { + content: "\e69b"; +} + +.pear-icon-fabulous:before { + content: "\e69c"; +} + +.pear-icon-file:before { + content: "\e69d"; +} + +.pear-icon-folder-close:before { + content: "\e69e"; +} + +.pear-icon-filter:before { + content: "\e69f"; +} + +.pear-icon-good:before { + content: "\e6a0"; +} + +.pear-icon-hide:before { + content: "\e6a1"; +} + +.pear-icon-home:before { + content: "\e6a2"; +} + +.pear-icon-history:before { + content: "\e6a3"; +} + +.pear-icon-file-open:before { + content: "\e6a4"; +} + +.pear-icon-forward:before { + content: "\e6a5"; +} + +.pear-icon-import:before { + content: "\e6a6"; +} + +.pear-icon-image-text:before { + content: "\e6a7"; +} + +.pear-icon-keyboard-26:before { + content: "\e6a8"; +} + +.pear-icon-keyboard-9:before { + content: "\e6a9"; +} + +.pear-icon-link:before { + content: "\e6aa"; +} + +.pear-icon-layout:before { + content: "\e6ab"; +} + +.pear-icon-fullscreen-shrink:before { + content: "\e6ac"; +} + +.pear-icon-layers:before { + content: "\e6ad"; +} + +.pear-icon-lock:before { + content: "\e6ae"; +} + +.pear-icon-fullscreen-expand:before { + content: "\e6af"; +} + +.pear-icon-map:before { + content: "\e6b0"; +} + +.pear-icon-meh:before { + content: "\e6b1"; +} + +.pear-icon-menu:before { + content: "\e6b2"; +} + +.pear-icon-loading:before { + content: "\e6b3"; +} + +.pear-icon-help:before { + content: "\e6b4"; +} + +.pear-icon-minus-circle:before { + content: "\e6b5"; +} + +.pear-icon-modular:before { + content: "\e6b6"; +} + +.pear-icon-notification:before { + content: "\e6b7"; +} + +.pear-icon-mic:before { + content: "\e6b8"; +} + +.pear-icon-more:before { + content: "\e6b9"; +} + +.pear-icon-pad:before { + content: "\e6ba"; +} + +.pear-icon-operation:before { + content: "\e6bb"; +} + +.pear-icon-play:before { + content: "\e6bc"; +} + +.pear-icon-print:before { + content: "\e6bd"; +} + +.pear-icon-mobile-phone:before { + content: "\e6be"; +} + +.pear-icon-minus:before { + content: "\e6bf"; +} + +.pear-icon-navigation:before { + content: "\e6c0"; +} + +.pear-icon-pdf:before { + content: "\e6c1"; +} + +.pear-icon-prompt:before { + content: "\e6c2"; +} + +.pear-icon-move:before { + content: "\e6c3"; +} + +.pear-icon-refresh:before { + content: "\e6c4"; +} + +.pear-icon-run-up:before { + content: "\e6c5"; +} + +.pear-icon-picture:before { + content: "\e6c6"; +} + +.pear-icon-run-in:before { + content: "\e6c7"; +} + +.pear-icon-pin:before { + content: "\e6c8"; +} + +.pear-icon-save:before { + content: "\e6c9"; +} + +.pear-icon-search:before { + content: "\e6ca"; +} + +.pear-icon-share:before { + content: "\e6cb"; +} + +.pear-icon-scanning:before { + content: "\e6cc"; +} + +.pear-icon-security:before { + content: "\e6cd"; +} + +.pear-icon-sign-out:before { + content: "\e6ce"; +} + +.pear-icon-select:before { + content: "\e6cf"; +} + +.pear-icon-stop:before { + content: "\e6d0"; +} + +.pear-icon-success:before { + content: "\e6d1"; +} + +.pear-icon-smile:before { + content: "\e6d2"; +} + +.pear-icon-switch:before { + content: "\e6d3"; +} + +.pear-icon-setting:before { + content: "\e6d4"; +} + +.pear-icon-survey:before { + content: "\e6d5"; +} + +.pear-icon-task:before { + content: "\e6d6"; +} + +.pear-icon-skip:before { + content: "\e6d7"; +} + +.pear-icon-text:before { + content: "\e6d8"; +} + +.pear-icon-time:before { + content: "\e6d9"; +} + +.pear-icon-telephone-out:before { + content: "\e6da"; +} + +.pear-icon-toggle-left:before { + content: "\e6db"; +} + +.pear-icon-toggle-right:before { + content: "\e6dc"; +} + +.pear-icon-telephone:before { + content: "\e6dd"; +} + +.pear-icon-top:before { + content: "\e6de"; +} + +.pear-icon-unlock:before { + content: "\e6df"; +} + +.pear-icon-user:before { + content: "\e6e0"; +} + +.pear-icon-upload:before { + content: "\e6e1"; +} + +.pear-icon-work:before { + content: "\e6e2"; +} + +.pear-icon-training:before { + content: "\e6e3"; +} + +.pear-icon-warning:before { + content: "\e6e4"; +} + +.pear-icon-zoom-in:before { + content: "\e6e5"; +} + +.pear-icon-zoom-out:before { + content: "\e6e6"; +} + +.pear-icon-add-bold:before { + content: "\e6e7"; +} + +.pear-icon-arrow-left-bold:before { + content: "\e6e8"; +} + +.pear-icon-arrow-up-bold:before { + content: "\e6e9"; +} + +.pear-icon-close-bold:before { + content: "\e6ea"; +} + +.pear-icon-arrow-down-bold:before { + content: "\e6eb"; +} + +.pear-icon-minus-bold:before { + content: "\e6ec"; +} + +.pear-icon-arrow-right-bold:before { + content: "\e6ed"; +} + +.pear-icon-select-bold:before { + content: "\e6ee"; +} + +.pear-icon-3column:before { + content: "\e663"; +} + +.pear-icon-column-4:before { + content: "\e664"; +} + +.pear-icon-add:before { + content: "\e665"; +} + +.pear-icon-add-circle:before { + content: "\e666"; +} + +.pear-icon-adjust:before { + content: "\e667"; +} + +.pear-icon-arrow-up-circle:before { + content: "\e668"; +} + +.pear-icon-arrow-right-circle:before { + content: "\e669"; +} + +.pear-icon-arrow-down:before { + content: "\e66a"; +} + +.pear-icon-ashbin:before { + content: "\e66b"; +} + +.pear-icon-arrow-right:before { + content: "\e66c"; +} + +.pear-icon-browse:before { + content: "\e66d"; +} + +.pear-icon-bottom:before { + content: "\e66e"; +} + +.pear-icon-back:before { + content: "\e66f"; +} + +.pear-icon-bad:before { + content: "\e670"; +} + +.pear-icon-arrow-double-left:before { + content: "\e671"; +} + +.pear-icon-arrow-left-circle:before { + content: "\e672"; +} + +.pear-icon-arrow-double-right:before { + content: "\e673"; +} + +.pear-icon-caps-lock:before { + content: "\e674"; +} + +.pear-icon-camera:before { + content: "\e675"; +} + +.pear-icon-chart-bar:before { + content: "\e676"; +} + +.pear-icon-attachment:before { + content: "\e677"; +} + +.pear-icon-code:before { + content: "\e678"; +} + +.pear-icon-close:before { + content: "\e679"; +} + +.pear-icon-check-item:before { + content: "\e67a"; +} + +.pear-icon-calendar:before { + content: "\e67b"; +} + +.pear-icon-comment:before { + content: "\e67c"; +} + +.pear-icon-column-vertical:before { + content: "\e67d"; +} + +.pear-icon-column-horizontal:before { + content: "\e67e"; +} + +.pear-icon-complete:before { + content: "\e67f"; +} + +.pear-icon-chart-pie:before { + content: "\e680"; +} + +.pear-icon-cry:before { + content: "\e681"; +} + +.pear-icon-customer-service:before { + content: "\e682"; +} + +.pear-icon-delete:before { + content: "\e683"; +} + +.pear-icon-direction-down:before { + content: "\e684"; +} + +.pear-icon-copy:before { + content: "\e685"; +} + +.pear-icon-cut:before { + content: "\e686"; +} + +.pear-icon-data-view:before { + content: "\e687"; +} + +.pear-icon-direction-down-circle:before { + content: "\e688"; +} + +.pear-icon-direction-right:before { + content: "\e689"; +} + +.pear-icon-direction-up:before { + content: "\e68a"; +} + +.pear-icon-discount:before { + content: "\e68b"; +} + +.pear-icon-direction-left:before { + content: "\e68c"; +} + diff --git a/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.js b/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.js new file mode 100644 index 0000000000000000000000000000000000000000..4cc2abda5882c574d06afe5ab8991d6205cfaa3d --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.js @@ -0,0 +1 @@ +!function(c){var h,l,o,a,s,p,t='',v=(v=document.getElementsByTagName("script"))[v.length-1].getAttribute("data-injectcss");if(v&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}function i(){s||(s=!0,o())}h=function(){var c,h,l;(l=document.createElement("div")).innerHTML=t,t=null,(h=l.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",c=h,(l=document.body).firstChild?(h=l.firstChild).parentNode.insertBefore(c,h):l.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(h,0):(l=function(){document.removeEventListener("DOMContentLoaded",l,!1),h()},document.addEventListener("DOMContentLoaded",l,!1)):document.attachEvent&&(o=h,a=c.document,s=!1,(p=function(){try{a.documentElement.doScroll("left")}catch(c){return void setTimeout(p,50)}i()})(),a.onreadystatechange=function(){"complete"==a.readyState&&(a.onreadystatechange=null,i())})}(window); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.json b/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.json new file mode 100644 index 0000000000000000000000000000000000000000..cb96655a99abb02f3dffe545e21f3c9241f538b2 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.json @@ -0,0 +1,996 @@ +{ + "id": "2654996", + "name": "pear-admin-layui", + "font_family": "pear-icon", + "css_prefix_text": "pear-icon-", + "description": "", + "glyphs": [ + { + "icon_id": "22697089", + "name": "加载", + "font_class": "load", + "unicode": "e6f0", + "unicode_decimal": 59120 + }, + { + "icon_id": "15838464", + "name": "download", + "font_class": "download", + "unicode": "e68d", + "unicode_decimal": 59021 + }, + { + "icon_id": "15838465", + "name": "electronics", + "font_class": "electronics", + "unicode": "e68e", + "unicode_decimal": 59022 + }, + { + "icon_id": "15838466", + "name": "drag", + "font_class": "drag", + "unicode": "e68f", + "unicode_decimal": 59023 + }, + { + "icon_id": "15838467", + "name": "elipsis", + "font_class": "elipsis", + "unicode": "e690", + "unicode_decimal": 59024 + }, + { + "icon_id": "15838468", + "name": "export", + "font_class": "export", + "unicode": "e691", + "unicode_decimal": 59025 + }, + { + "icon_id": "15838469", + "name": "explain", + "font_class": "explain", + "unicode": "e692", + "unicode_decimal": 59026 + }, + { + "icon_id": "15838470", + "name": "edit", + "font_class": "edit", + "unicode": "e693", + "unicode_decimal": 59027 + }, + { + "icon_id": "15838471", + "name": "eye-close", + "font_class": "eye-close", + "unicode": "e694", + "unicode_decimal": 59028 + }, + { + "icon_id": "15838472", + "name": "email", + "font_class": "email", + "unicode": "e695", + "unicode_decimal": 59029 + }, + { + "icon_id": "15838473", + "name": "error", + "font_class": "error", + "unicode": "e696", + "unicode_decimal": 59030 + }, + { + "icon_id": "15838474", + "name": "favorite", + "font_class": "favorite", + "unicode": "e697", + "unicode_decimal": 59031 + }, + { + "icon_id": "15838475", + "name": "file-common", + "font_class": "file-common", + "unicode": "e698", + "unicode_decimal": 59032 + }, + { + "icon_id": "15838476", + "name": "file-delete", + "font_class": "file-delete", + "unicode": "e699", + "unicode_decimal": 59033 + }, + { + "icon_id": "15838477", + "name": "file-add", + "font_class": "file-add", + "unicode": "e69a", + "unicode_decimal": 59034 + }, + { + "icon_id": "15838478", + "name": "film", + "font_class": "film", + "unicode": "e69b", + "unicode_decimal": 59035 + }, + { + "icon_id": "15838479", + "name": "fabulous", + "font_class": "fabulous", + "unicode": "e69c", + "unicode_decimal": 59036 + }, + { + "icon_id": "15838480", + "name": "file", + "font_class": "file", + "unicode": "e69d", + "unicode_decimal": 59037 + }, + { + "icon_id": "15838481", + "name": "folder-close", + "font_class": "folder-close", + "unicode": "e69e", + "unicode_decimal": 59038 + }, + { + "icon_id": "15838482", + "name": "filter", + "font_class": "filter", + "unicode": "e69f", + "unicode_decimal": 59039 + }, + { + "icon_id": "15838483", + "name": "good", + "font_class": "good", + "unicode": "e6a0", + "unicode_decimal": 59040 + }, + { + "icon_id": "15838484", + "name": "hide", + "font_class": "hide", + "unicode": "e6a1", + "unicode_decimal": 59041 + }, + { + "icon_id": "15838485", + "name": "home", + "font_class": "home", + "unicode": "e6a2", + "unicode_decimal": 59042 + }, + { + "icon_id": "15838486", + "name": "history", + "font_class": "history", + "unicode": "e6a3", + "unicode_decimal": 59043 + }, + { + "icon_id": "15838487", + "name": "file-open", + "font_class": "file-open", + "unicode": "e6a4", + "unicode_decimal": 59044 + }, + { + "icon_id": "15838488", + "name": "forward", + "font_class": "forward", + "unicode": "e6a5", + "unicode_decimal": 59045 + }, + { + "icon_id": "15838489", + "name": "import", + "font_class": "import", + "unicode": "e6a6", + "unicode_decimal": 59046 + }, + { + "icon_id": "15838490", + "name": "image-text", + "font_class": "image-text", + "unicode": "e6a7", + "unicode_decimal": 59047 + }, + { + "icon_id": "15838491", + "name": "keyboard-26", + "font_class": "keyboard-26", + "unicode": "e6a8", + "unicode_decimal": 59048 + }, + { + "icon_id": "15838492", + "name": "keyboard-9", + "font_class": "keyboard-9", + "unicode": "e6a9", + "unicode_decimal": 59049 + }, + { + "icon_id": "15838493", + "name": "link", + "font_class": "link", + "unicode": "e6aa", + "unicode_decimal": 59050 + }, + { + "icon_id": "15838494", + "name": "layout", + "font_class": "layout", + "unicode": "e6ab", + "unicode_decimal": 59051 + }, + { + "icon_id": "15838495", + "name": "fullscreen-shrink", + "font_class": "fullscreen-shrink", + "unicode": "e6ac", + "unicode_decimal": 59052 + }, + { + "icon_id": "15838496", + "name": "layers", + "font_class": "layers", + "unicode": "e6ad", + "unicode_decimal": 59053 + }, + { + "icon_id": "15838497", + "name": "lock", + "font_class": "lock", + "unicode": "e6ae", + "unicode_decimal": 59054 + }, + { + "icon_id": "15838498", + "name": "fullscreen-expand", + "font_class": "fullscreen-expand", + "unicode": "e6af", + "unicode_decimal": 59055 + }, + { + "icon_id": "15838499", + "name": "map", + "font_class": "map", + "unicode": "e6b0", + "unicode_decimal": 59056 + }, + { + "icon_id": "15838500", + "name": "meh", + "font_class": "meh", + "unicode": "e6b1", + "unicode_decimal": 59057 + }, + { + "icon_id": "15838501", + "name": "menu", + "font_class": "menu", + "unicode": "e6b2", + "unicode_decimal": 59058 + }, + { + "icon_id": "15838502", + "name": "loading", + "font_class": "loading", + "unicode": "e6b3", + "unicode_decimal": 59059 + }, + { + "icon_id": "15838503", + "name": "help", + "font_class": "help", + "unicode": "e6b4", + "unicode_decimal": 59060 + }, + { + "icon_id": "15838504", + "name": "minus-circle", + "font_class": "minus-circle", + "unicode": "e6b5", + "unicode_decimal": 59061 + }, + { + "icon_id": "15838505", + "name": "modular", + "font_class": "modular", + "unicode": "e6b6", + "unicode_decimal": 59062 + }, + { + "icon_id": "15838506", + "name": "notification", + "font_class": "notification", + "unicode": "e6b7", + "unicode_decimal": 59063 + }, + { + "icon_id": "15838507", + "name": "mic", + "font_class": "mic", + "unicode": "e6b8", + "unicode_decimal": 59064 + }, + { + "icon_id": "15838508", + "name": "more", + "font_class": "more", + "unicode": "e6b9", + "unicode_decimal": 59065 + }, + { + "icon_id": "15838509", + "name": "pad", + "font_class": "pad", + "unicode": "e6ba", + "unicode_decimal": 59066 + }, + { + "icon_id": "15838510", + "name": "operation", + "font_class": "operation", + "unicode": "e6bb", + "unicode_decimal": 59067 + }, + { + "icon_id": "15838511", + "name": "play", + "font_class": "play", + "unicode": "e6bc", + "unicode_decimal": 59068 + }, + { + "icon_id": "15838512", + "name": "print", + "font_class": "print", + "unicode": "e6bd", + "unicode_decimal": 59069 + }, + { + "icon_id": "15838513", + "name": "mobile-phone", + "font_class": "mobile-phone", + "unicode": "e6be", + "unicode_decimal": 59070 + }, + { + "icon_id": "15838514", + "name": "minus", + "font_class": "minus", + "unicode": "e6bf", + "unicode_decimal": 59071 + }, + { + "icon_id": "15838515", + "name": "navigation", + "font_class": "navigation", + "unicode": "e6c0", + "unicode_decimal": 59072 + }, + { + "icon_id": "15838516", + "name": "pdf", + "font_class": "pdf", + "unicode": "e6c1", + "unicode_decimal": 59073 + }, + { + "icon_id": "15838517", + "name": "prompt", + "font_class": "prompt", + "unicode": "e6c2", + "unicode_decimal": 59074 + }, + { + "icon_id": "15838518", + "name": "move", + "font_class": "move", + "unicode": "e6c3", + "unicode_decimal": 59075 + }, + { + "icon_id": "15838519", + "name": "refresh", + "font_class": "refresh", + "unicode": "e6c4", + "unicode_decimal": 59076 + }, + { + "icon_id": "15838520", + "name": "run-up", + "font_class": "run-up", + "unicode": "e6c5", + "unicode_decimal": 59077 + }, + { + "icon_id": "15838521", + "name": "picture", + "font_class": "picture", + "unicode": "e6c6", + "unicode_decimal": 59078 + }, + { + "icon_id": "15838522", + "name": "run-in", + "font_class": "run-in", + "unicode": "e6c7", + "unicode_decimal": 59079 + }, + { + "icon_id": "15838523", + "name": "pin", + "font_class": "pin", + "unicode": "e6c8", + "unicode_decimal": 59080 + }, + { + "icon_id": "15838524", + "name": "save", + "font_class": "save", + "unicode": "e6c9", + "unicode_decimal": 59081 + }, + { + "icon_id": "15838525", + "name": "search", + "font_class": "search", + "unicode": "e6ca", + "unicode_decimal": 59082 + }, + { + "icon_id": "15838526", + "name": "share", + "font_class": "share", + "unicode": "e6cb", + "unicode_decimal": 59083 + }, + { + "icon_id": "15838527", + "name": "scanning", + "font_class": "scanning", + "unicode": "e6cc", + "unicode_decimal": 59084 + }, + { + "icon_id": "15838528", + "name": "security", + "font_class": "security", + "unicode": "e6cd", + "unicode_decimal": 59085 + }, + { + "icon_id": "15838529", + "name": "sign-out", + "font_class": "sign-out", + "unicode": "e6ce", + "unicode_decimal": 59086 + }, + { + "icon_id": "15838530", + "name": "select", + "font_class": "select", + "unicode": "e6cf", + "unicode_decimal": 59087 + }, + { + "icon_id": "15838531", + "name": "stop", + "font_class": "stop", + "unicode": "e6d0", + "unicode_decimal": 59088 + }, + { + "icon_id": "15838532", + "name": "success", + "font_class": "success", + "unicode": "e6d1", + "unicode_decimal": 59089 + }, + { + "icon_id": "15838533", + "name": "smile", + "font_class": "smile", + "unicode": "e6d2", + "unicode_decimal": 59090 + }, + { + "icon_id": "15838534", + "name": "switch", + "font_class": "switch", + "unicode": "e6d3", + "unicode_decimal": 59091 + }, + { + "icon_id": "15838535", + "name": "setting", + "font_class": "setting", + "unicode": "e6d4", + "unicode_decimal": 59092 + }, + { + "icon_id": "15838536", + "name": "survey", + "font_class": "survey", + "unicode": "e6d5", + "unicode_decimal": 59093 + }, + { + "icon_id": "15838537", + "name": "task", + "font_class": "task", + "unicode": "e6d6", + "unicode_decimal": 59094 + }, + { + "icon_id": "15838538", + "name": "skip", + "font_class": "skip", + "unicode": "e6d7", + "unicode_decimal": 59095 + }, + { + "icon_id": "15838539", + "name": "text", + "font_class": "text", + "unicode": "e6d8", + "unicode_decimal": 59096 + }, + { + "icon_id": "15838540", + "name": "time", + "font_class": "time", + "unicode": "e6d9", + "unicode_decimal": 59097 + }, + { + "icon_id": "15838541", + "name": "telephone-out", + "font_class": "telephone-out", + "unicode": "e6da", + "unicode_decimal": 59098 + }, + { + "icon_id": "15838542", + "name": "toggle-left", + "font_class": "toggle-left", + "unicode": "e6db", + "unicode_decimal": 59099 + }, + { + "icon_id": "15838543", + "name": "toggle-right", + "font_class": "toggle-right", + "unicode": "e6dc", + "unicode_decimal": 59100 + }, + { + "icon_id": "15838544", + "name": "telephone", + "font_class": "telephone", + "unicode": "e6dd", + "unicode_decimal": 59101 + }, + { + "icon_id": "15838545", + "name": "top", + "font_class": "top", + "unicode": "e6de", + "unicode_decimal": 59102 + }, + { + "icon_id": "15838546", + "name": "unlock", + "font_class": "unlock", + "unicode": "e6df", + "unicode_decimal": 59103 + }, + { + "icon_id": "15838547", + "name": "user", + "font_class": "user", + "unicode": "e6e0", + "unicode_decimal": 59104 + }, + { + "icon_id": "15838548", + "name": "upload", + "font_class": "upload", + "unicode": "e6e1", + "unicode_decimal": 59105 + }, + { + "icon_id": "15838549", + "name": "work", + "font_class": "work", + "unicode": "e6e2", + "unicode_decimal": 59106 + }, + { + "icon_id": "15838550", + "name": "training", + "font_class": "training", + "unicode": "e6e3", + "unicode_decimal": 59107 + }, + { + "icon_id": "15838551", + "name": "warning", + "font_class": "warning", + "unicode": "e6e4", + "unicode_decimal": 59108 + }, + { + "icon_id": "15838552", + "name": "zoom-in", + "font_class": "zoom-in", + "unicode": "e6e5", + "unicode_decimal": 59109 + }, + { + "icon_id": "15838554", + "name": "zoom-out", + "font_class": "zoom-out", + "unicode": "e6e6", + "unicode_decimal": 59110 + }, + { + "icon_id": "15838560", + "name": "add-bold", + "font_class": "add-bold", + "unicode": "e6e7", + "unicode_decimal": 59111 + }, + { + "icon_id": "15838561", + "name": "arrow-left-bold", + "font_class": "arrow-left-bold", + "unicode": "e6e8", + "unicode_decimal": 59112 + }, + { + "icon_id": "15838562", + "name": "arrow-up-bold", + "font_class": "arrow-up-bold", + "unicode": "e6e9", + "unicode_decimal": 59113 + }, + { + "icon_id": "15838563", + "name": "close-bold", + "font_class": "close-bold", + "unicode": "e6ea", + "unicode_decimal": 59114 + }, + { + "icon_id": "15838564", + "name": "arrow-down-bold", + "font_class": "arrow-down-bold", + "unicode": "e6eb", + "unicode_decimal": 59115 + }, + { + "icon_id": "15838565", + "name": "minus-bold", + "font_class": "minus-bold", + "unicode": "e6ec", + "unicode_decimal": 59116 + }, + { + "icon_id": "15838566", + "name": "arrow-right-bold", + "font_class": "arrow-right-bold", + "unicode": "e6ed", + "unicode_decimal": 59117 + }, + { + "icon_id": "15838567", + "name": "select-bold", + "font_class": "select-bold", + "unicode": "e6ee", + "unicode_decimal": 59118 + }, + { + "icon_id": "15838406", + "name": "column-3", + "font_class": "3column", + "unicode": "e663", + "unicode_decimal": 58979 + }, + { + "icon_id": "15838423", + "name": "column-4", + "font_class": "column-4", + "unicode": "e664", + "unicode_decimal": 58980 + }, + { + "icon_id": "15838424", + "name": "add", + "font_class": "add", + "unicode": "e665", + "unicode_decimal": 58981 + }, + { + "icon_id": "15838425", + "name": "add-circle", + "font_class": "add-circle", + "unicode": "e666", + "unicode_decimal": 58982 + }, + { + "icon_id": "15838426", + "name": "adjust", + "font_class": "adjust", + "unicode": "e667", + "unicode_decimal": 58983 + }, + { + "icon_id": "15838427", + "name": "arrow-up-circle", + "font_class": "arrow-up-circle", + "unicode": "e668", + "unicode_decimal": 58984 + }, + { + "icon_id": "15838428", + "name": "arrow-right-circle", + "font_class": "arrow-right-circle", + "unicode": "e669", + "unicode_decimal": 58985 + }, + { + "icon_id": "15838429", + "name": "arrow-down", + "font_class": "arrow-down", + "unicode": "e66a", + "unicode_decimal": 58986 + }, + { + "icon_id": "15838430", + "name": "ashbin", + "font_class": "ashbin", + "unicode": "e66b", + "unicode_decimal": 58987 + }, + { + "icon_id": "15838431", + "name": "arrow-right", + "font_class": "arrow-right", + "unicode": "e66c", + "unicode_decimal": 58988 + }, + { + "icon_id": "15838432", + "name": "browse", + "font_class": "browse", + "unicode": "e66d", + "unicode_decimal": 58989 + }, + { + "icon_id": "15838433", + "name": "bottom", + "font_class": "bottom", + "unicode": "e66e", + "unicode_decimal": 58990 + }, + { + "icon_id": "15838434", + "name": "back", + "font_class": "back", + "unicode": "e66f", + "unicode_decimal": 58991 + }, + { + "icon_id": "15838435", + "name": "bad", + "font_class": "bad", + "unicode": "e670", + "unicode_decimal": 58992 + }, + { + "icon_id": "15838436", + "name": "arrow-double-left", + "font_class": "arrow-double-left", + "unicode": "e671", + "unicode_decimal": 58993 + }, + { + "icon_id": "15838437", + "name": "arrow-left-circle", + "font_class": "arrow-left-circle", + "unicode": "e672", + "unicode_decimal": 58994 + }, + { + "icon_id": "15838438", + "name": "arrow-double-right", + "font_class": "arrow-double-right", + "unicode": "e673", + "unicode_decimal": 58995 + }, + { + "icon_id": "15838439", + "name": "caps-lock", + "font_class": "caps-lock", + "unicode": "e674", + "unicode_decimal": 58996 + }, + { + "icon_id": "15838440", + "name": "camera", + "font_class": "camera", + "unicode": "e675", + "unicode_decimal": 58997 + }, + { + "icon_id": "15838441", + "name": "chart-bar", + "font_class": "chart-bar", + "unicode": "e676", + "unicode_decimal": 58998 + }, + { + "icon_id": "15838442", + "name": "attachment", + "font_class": "attachment", + "unicode": "e677", + "unicode_decimal": 58999 + }, + { + "icon_id": "15838443", + "name": "code", + "font_class": "code", + "unicode": "e678", + "unicode_decimal": 59000 + }, + { + "icon_id": "15838444", + "name": "close", + "font_class": "close", + "unicode": "e679", + "unicode_decimal": 59001 + }, + { + "icon_id": "15838445", + "name": "check-item", + "font_class": "check-item", + "unicode": "e67a", + "unicode_decimal": 59002 + }, + { + "icon_id": "15838446", + "name": "calendar", + "font_class": "calendar", + "unicode": "e67b", + "unicode_decimal": 59003 + }, + { + "icon_id": "15838447", + "name": "comment", + "font_class": "comment", + "unicode": "e67c", + "unicode_decimal": 59004 + }, + { + "icon_id": "15838448", + "name": "column-vertical", + "font_class": "column-vertical", + "unicode": "e67d", + "unicode_decimal": 59005 + }, + { + "icon_id": "15838449", + "name": "column-horizontal", + "font_class": "column-horizontal", + "unicode": "e67e", + "unicode_decimal": 59006 + }, + { + "icon_id": "15838450", + "name": "complete", + "font_class": "complete", + "unicode": "e67f", + "unicode_decimal": 59007 + }, + { + "icon_id": "15838451", + "name": "chart-pie", + "font_class": "chart-pie", + "unicode": "e680", + "unicode_decimal": 59008 + }, + { + "icon_id": "15838452", + "name": "cry", + "font_class": "cry", + "unicode": "e681", + "unicode_decimal": 59009 + }, + { + "icon_id": "15838453", + "name": "customer-service", + "font_class": "customer-service", + "unicode": "e682", + "unicode_decimal": 59010 + }, + { + "icon_id": "15838454", + "name": "delete", + "font_class": "delete", + "unicode": "e683", + "unicode_decimal": 59011 + }, + { + "icon_id": "15838455", + "name": "direction-down", + "font_class": "direction-down", + "unicode": "e684", + "unicode_decimal": 59012 + }, + { + "icon_id": "15838456", + "name": "copy", + "font_class": "copy", + "unicode": "e685", + "unicode_decimal": 59013 + }, + { + "icon_id": "15838457", + "name": "cut", + "font_class": "cut", + "unicode": "e686", + "unicode_decimal": 59014 + }, + { + "icon_id": "15838458", + "name": "data-view", + "font_class": "data-view", + "unicode": "e687", + "unicode_decimal": 59015 + }, + { + "icon_id": "15838459", + "name": "direction-down-circle", + "font_class": "direction-down-circle", + "unicode": "e688", + "unicode_decimal": 59016 + }, + { + "icon_id": "15838460", + "name": "direction-right", + "font_class": "direction-right", + "unicode": "e689", + "unicode_decimal": 59017 + }, + { + "icon_id": "15838461", + "name": "direction-up", + "font_class": "direction-up", + "unicode": "e68a", + "unicode_decimal": 59018 + }, + { + "icon_id": "15838462", + "name": "discount", + "font_class": "discount", + "unicode": "e68b", + "unicode_decimal": 59019 + }, + { + "icon_id": "15838463", + "name": "direction-left", + "font_class": "direction-left", + "unicode": "e68c", + "unicode_decimal": 59020 + } + ] +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.ttf b/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f40ab3acea096b8096b94762a26da9c9ca1baf99 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.ttf differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.woff b/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..869e1a06606fb68a0e13c408d75919a343cc06f7 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.woff differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.woff2 b/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..4a3ea5e4eda162e70b54ba932a3950a45297c374 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/font/iconfont.woff2 differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/admin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/admin.js new file mode 100644 index 0000000000000000000000000000000000000000..33d600c0f9ef863fb744479d5207b4864451a091 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/admin.js @@ -0,0 +1,997 @@ +layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'menu', 'frame', 'theme', 'convert','fullscreen'], + function(exports) { + "use strict"; + + var $ = layui.jquery, + form = layui.form, + element = layui.element, + yaml = layui.yaml, + pearTab = layui.tab, + convert = layui.convert, + pearMenu = layui.menu, + pearFrame = layui.frame, + pearTheme = layui.theme, + message = layui.message, + fullscreen=layui.fullscreen; + + var bodyFrame; + var sideMenu; + var bodyTab; + var config; + var logout = function() {}; + var msgInstance; + var body = $('body'); + + var pearAdmin = new function() { + + var configType = 'yml'; + var configPath = 'pear.config.yml'; + + this.setConfigPath = function(path) { + configPath = path; + } + + this.setConfigType = function(type) { + configType = type; + } + + this.render = function(initConfig) { + if (initConfig !== undefined) { + applyConfig(initConfig); + } else { + applyConfig(pearAdmin.readConfig()); + } + } + + this.readConfig = function() { + if (configType === "yml") { + return yaml.load(configPath); + } else { + var data; + $.ajax({ + url: configPath, + type: 'get', + dataType: 'json', + async: false, + success: function(result) { + data = result; + } + }) + return data; + } + } + + this.messageRender = function(option) { + var option = { + elem: '.message', + url: option.header.message, + height: '250px' + }; + msgInstance = message.render(option); + } + + this.logoRender = function(param) { + $(".layui-logo .logo").attr("src", param.logo.image); + $(".layui-logo .title").html(param.logo.title); + $("title").html(param.logo.title); //变更 + } + + this.menuRender = function(param) { + sideMenu = pearMenu.render({ + elem: 'sideMenu', + async: param.menu.async !== undefined ? param.menu.async : true, + theme: "dark-theme", + height: '100%', + method: param.menu.method, + control: isControl(param) === 'true' || isControl(param) === true ? 'control' : false, // control + controlWidth: param.menu.controlWidth, + defaultMenu: 0, + accordion: param.menu.accordion, + url: param.menu.data, + data: param.menu.data, + parseData: false, + change: function() { + compatible(); + }, + done: function() { + sideMenu.isCollapse = param.menu.collapse; + sideMenu.selectItem(param.menu.select); + pearAdmin.collapse(param); + } + }); + } + + this.bodyRender = function(param) { + + body.on("click", ".refresh", function() { + refresh(); + }) + + if (isMuiltTab(param) === "true" || isMuiltTab(param) === true) { + bodyTab = pearTab.render({ + elem: 'content', + roll: true, + tool: true, + width: '100%', + height: '100%', + session: param.tab.session, + index: 0, + tabMax: param.tab.max, + preload: param.tab.preload, + closeEvent: function(id) { + sideMenu.selectItem(id); + }, + data: [{ + id: param.tab.index.id, + url: param.tab.index.href, + title: param.tab.index.title, + close: false + }], + success: function(id) { + if (param.tab.session) { + setTimeout(function() { + sideMenu.selectItem(id); + bodyTab.positionTab(); + }, 500) + } + } + }); + + bodyTab.click(function(id) { + if (!param.tab.keepState) { + bodyTab.refresh(false); + } + bodyTab.positionTab(); + sideMenu.selectItem(id); + }) + + sideMenu.click(function(dom, data) { + bodyTab.addTabOnly({ + id: data.menuId, + title: data.menuTitle, + url: data.menuUrl, + icon: data.menuIcon, + close: true + }, 300); + compatible(); + }) + } else { + bodyFrame = pearFrame.render({ + elem: 'content', + title: '首页', + url: param.tab.index.href, + width: '100%', + height: '100%' + }); + + sideMenu.click(function(dom, data) { + bodyFrame.changePage(data.menuUrl, true); + compatible() + }) + } + } + + this.keepLoad = function(param) { + compatible() + setTimeout(function() { + $(".loader-main").fadeOut(200); + }, param.other.keepLoad) + } + + this.themeRender = function(option) { + if (option.theme.allowCustom === false) { + $(".setting").remove(); + } + var colorId = localStorage.getItem("theme-color"); + var currentColor = getColorById(colorId); + localStorage.setItem("theme-color", currentColor.id); + localStorage.setItem("theme-color-color", currentColor.color); + localStorage.setItem("theme-color-second", currentColor.second); + pearTheme.changeTheme(window, isAutoHead(config)); + + var menu = localStorage.getItem("theme-menu"); + if (menu === null) { + menu = option.theme.defaultMenu; + } else { + if (option.theme.allowCustom === false) { + menu = option.theme.defaultMenu; + } + } + + var header = localStorage.getItem("theme-header"); + if (header === null) { + header = option.theme.defaultHeader; + } else { + if (option.theme.allowCustom === false) { + header = option.theme.defaultHeader; + } + } + + var banner = localStorage.getItem("theme-banner"); + if (banner === null) { + banner = option.theme.banner; + } else { + if (option.theme.allowCustom === false) { + banner = option.theme.banner; + } + } + + var autoHead = localStorage.getItem("auto-head"); + if (autoHead === null) { + autoHead = option.other.autoHead; + } else { + if (option.theme.allowCustom === false) { + autoHead = option.other.autoHead; + } + } + + var muiltTab = localStorage.getItem("muilt-tab"); + if (muiltTab === null) { + muiltTab = option.tab.enable; + } else { + if (option.theme.allowCustom === false) { + muiltTab = option.tab.enable; + } + } + + var control = localStorage.getItem("control"); + if (control === null) { + control = option.menu.control; + } else { + if (option.theme.allowCustom === false) { + control = option.menu.control; + } + } + + var footer = localStorage.getItem("footer"); + if( footer === null) { + footer = option.other.footer; + }else{ + if (option.theme.allowCustom === false) { + footer = option.other.footer; + } + } + + localStorage.setItem("muilt-tab", muiltTab); + localStorage.setItem("theme-banner", banner); + localStorage.setItem("theme-menu", menu); + localStorage.setItem("theme-header", header); + localStorage.setItem("auto-head", autoHead); + localStorage.setItem("control", control); + localStorage.setItem("footer", footer); + this.menuSkin(menu); + this.headerSkin(header); + this.bannerSkin(banner); + this.footer(footer); + } + + this.footer = function(footer){ + var bodyDOM = $(".pear-admin .layui-body"); + var footerDOM = $(".pear-admin .layui-footer"); + if (footer === true || footer === "true") { + footerDOM.removeClass("close"); + bodyDOM.css("bottom", footerDOM.outerHeight()); + } else { + footerDOM.addClass("close"); + bodyDOM.css("bottom", ""); + } + } + + this.bannerSkin = function(theme) { + var pearAdmin = $(".pear-admin"); + pearAdmin.removeClass("banner-layout"); + if (theme === true || theme === "true") { + pearAdmin.addClass("banner-layout"); + } + } + + this.collapse = function(param) { + if (param.menu.collapse) { + if ($(window).width() >= 768) { + collapse() + } + } + } + + this.menuSkin = function(theme) { + var pearAdmin = $(".pear-admin .layui-side"); + pearAdmin.removeClass("light-theme"); + pearAdmin.removeClass("dark-theme"); + pearAdmin.addClass(theme); + } + + this.headerSkin = function(theme) { + var pearAdmin = $(".pear-admin .layui-header"); + pearAdmin.removeClass("light-theme"); + pearAdmin.removeClass("dark-theme"); + pearAdmin.addClass(theme); + } + + this.logout = function(callback) { + logout = callback; + } + + this.message = function(callback) { + if (callback != null) { + msgInstance.click(callback); + } + } + + this.collapseSide = function() { + collapse() + } + + this.refreshThis = function() { + refresh() + } + + this.refresh = function(id) { + $("iframe[id='"+ id +"']").attr('src', $("iframe[id='"+ id +"']").attr('src')); + } + + this.addTab = function(id, title, url) { + if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) { + bodyTab.addTabOnly({ + id: id, + title: title, + url: url, + icon: null, + close: true + }, 400); + } else { + return; + } + } + + this.closeTab = function(id) { + if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) { + pearTab.delTabByElem('content', id, function(currentId){ + sideMenu.selectItem(currentId); + }); + } else { + return; + } + } + + this.closeCurrentTab = function() { + if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) { + pearTab.delCurrentTabByElem('content', function(id){ + sideMenu.selectItem(id); + }); + } else { + return; + } + } + + this.closeOtherTab = function() { + if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) { + pearTab.delOtherTabByElem('content', function(id){ + sideMenu.selectItem(id); + }); + } else { + return; + } + } + + this.closeAllTab = function() { + if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) { + pearTab.delAllTabByElem('content', function(id){ + sideMenu.selectItem(id); + }); + } else { + return; + } + } + + this.changeTabTitle = function(id, title) { + pearTab.changeTabTitleById('content', id ,title); + } + + this.changeIframe = function(id, title, url) { + if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) { + return; + } else { + sideMenu.selectItem(id); + bodyFrame.changePage(url, true); + } + } + + this.jump = function(id, title, url) { + if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) { + pearAdmin.addTab(id, title, url) + } else { + pearAdmin.changeIframe(id, title, url) + } + } + + this.fullScreen = function() { + if ($(".fullScreen").hasClass("layui-icon-screen-restore")) { + screenFun(2).then(function() { + $(".fullScreen").eq(0).removeClass("layui-icon-screen-restore"); + }); + } else { + screenFun(1).then(function() { + $(".fullScreen").eq(0).addClass("layui-icon-screen-restore"); + }); + } + } + }; + + function refresh() { + var refreshA = $(".refresh a"); + refreshA.removeClass("layui-icon-refresh-1"); + refreshA.addClass("layui-anim"); + refreshA.addClass("layui-anim-rotate"); + refreshA.addClass("layui-anim-loop"); + refreshA.addClass("layui-icon-loading"); + if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) bodyTab.refresh(true); + else bodyFrame.refresh(true); + setTimeout(function() { + refreshA.addClass("layui-icon-refresh-1"); + refreshA.removeClass("layui-anim"); + refreshA.removeClass("layui-anim-rotate"); + refreshA.removeClass("layui-anim-loop"); + refreshA.removeClass("layui-icon-loading"); + }, 600) + } + + function collapse() { + sideMenu.collapse(); + var admin = $(".pear-admin"); + var left = $(".layui-icon-spread-left") + var right = $(".layui-icon-shrink-right") + if (admin.is(".pear-mini")) { + left.addClass("layui-icon-shrink-right") + left.removeClass("layui-icon-spread-left") + admin.removeClass("pear-mini"); + sideMenu.isCollapse = false; + } else { + right.addClass("layui-icon-spread-left") + right.removeClass("layui-icon-shrink-right") + admin.addClass("pear-mini"); + sideMenu.isCollapse = true; + } + } + + body.on("click", ".logout", function() { + if (logout() && bodyTab) { + bodyTab.clear(); + } + }) + + body.on("click", ".collapse,.pear-cover", function() { + collapse(); + }); + + body.on("click", ".menuSearch", function () { + // 过滤菜单 + var filterHandle = function (filterData, val) { + if (!val) return []; + var filteredMenus = []; + filterData = $.extend(true, {}, filterData); + $.each(filterData, function (index, item) { + if (item.children && item.children.length) { + var children = filterHandle(item.children, val) + var obj = $.extend({}, item, { children: children }); + if (children && children.length) { + filteredMenus.push(obj); + } else if (item.title.indexOf(val) >= 0) { + item.children = []; // 父级匹配但子级不匹配,就去除子级 + filteredMenus.push($.extend({}, item)); + } + } else if (item.title.indexOf(val) >= 0) { + filteredMenus.push(item); + } + }) + return filteredMenus; + } + + // 树转路径 + var tiledHandle = function (data) { + var tiledMenus = []; + var treeTiled = function (data, content) { + var path = ""; + var separator = " / "; + // 上级路径 + if (!content) content = ""; + $.each(data, function (index, item) { + if (item.children && item.children.length) { + path += content + item.title + separator; + var childPath = treeTiled(item.children, path); + path += childPath; + if (!childPath) path = ""; // 重置路径 + } else { + path += content + item.title + tiledMenus.push({ path: path, info: item }); + path = ""; //重置路径 + } + }) + return path; + }; + treeTiled(data); + + return tiledMenus; + } + + // 创建搜索列表 + var createList = function (data) { + var _listHtml = ''; + $.each(data, function (index, item) { + _listHtml += '
                                                                            • '; + _listHtml += ' ' + item.path + ''; + _listHtml += ' '; + _listHtml += '
                                                                            • ' + }) + return _listHtml; + } + + var _html = [ + '' + ].join(''); + + layer.open({ + type: 1, + offset: "10%", + area: ['600px'], + title: false, + closeBtn: 0, + shadeClose: true, + anim: 0, + move: false, + content: _html, + success: function(layero,layeridx){ + var $layer = layero; + var $content = $(layero).children('.layui-layer-content'); + var $input = $(".menu-search-input-wrapper input"); + var $noData = $(".menu-search-no-data"); + var $list = $(".menu-search-list"); + var menuData = sideMenu.option.data; + + + $layer.css("border-radius", "6px"); + $input.off("focus").focus(); + // 搜索菜单 + $input.off("input").on("input", debounce(function(){ + var keywords = $input.val().trim(); + var filteredMenus = filterHandle(menuData, keywords); + + if(filteredMenus.length){ + var tiledMenus = tiledHandle(filteredMenus); + var listHtml = createList(tiledMenus); + $noData.css("display", "none"); + $list.html("").append(listHtml).children(":first").addClass("this") + }else{ + $list.html(""); + $noData.css("display", "flex"); + } + var currentHeight = $(".menu-search-content").outerHeight() + $layer.css("height", currentHeight); + $content.css("height", currentHeight); + }, 500) + ) + // 搜索列表点击事件 + $list.off("click").on("click", "li", function () { + var menuId = $(this).attr("smenu-id"); + var menuUrl = $(this).attr("smenu-url"); + var menuIcon = $(this).attr("smenu-icon"); + var menuTitle = $(this).attr("smenu-title"); + var menuType = $(this).attr("smenu-type"); + var openableWindow = menuType === "1" || menuType === 1; + + if(sideMenu.isCollapse){ + collapse(); + } + if (openableWindow) { + pearAdmin.jump(menuId, menuTitle, menuUrl) + } else { + sideMenu.selectItem(menuId); + } + compatible(); + layer.close(layeridx); + }) + + $list.off('mouseenter').on("mouseenter", "li", function () { + $(".menu-search-list li.this").removeClass("this"); + $(this).addClass("this"); + }).off("mouseleave").on("mouseleave", "li", function(){ + $(this).removeClass("this"); + }) + + // 监听键盘事件 + // Enter:13 Spacebar:32 UpArrow:38 DownArrow:40 Esc:27 + $(document).off("keydown").keydown(function (e) { + if (e.keyCode === 13 || e.keyCode === 32) { + e.preventDefault(); + var menuId = $(".menu-search-list li.this").attr("smenu-id"); + var menuUrl = $(".menu-search-list li.this").attr("smenu-url"); + var menuTitle = $(".menu-search-list li.this").attr("smenu-title"); + var menuType = $(".menu-search-list li.this").attr("smenu-type"); + var openableWindow = menuType === "1" || menuType === 1; + if (sideMenu.isCollapse) { + collapse(); + } + if (openableWindow) { + pearAdmin.jump(menuId, menuTitle, menuUrl) + } else { + sideMenu.selectItem(menuId); + } + compatible(); + layer.close(layeridx); + }else if(e.keyCode === 38){ + e.preventDefault(); + var prevEl = $(".menu-search-list li.this").prev(); + $(".menu-search-list li.this").removeClass("this"); + if(prevEl.length !== 0){ + prevEl.addClass("this"); + }else{ + $list.children().last().addClass("this"); + } + }else if(e.keyCode === 40){ + e.preventDefault(); + var nextEl = $(".menu-search-list li.this").next(); + $(".menu-search-list li.this").removeClass("this"); + if(nextEl.length !== 0){ + nextEl.addClass("this"); + }else{ + $list.children().first().addClass("this"); + } + }else if(e.keyCode === 27){ + e.preventDefault(); + layer.close(layeridx); + } + }) + } + }) + }); + + + body.on("click", ".fullScreen", function() { + if ($(this).hasClass("layui-icon-screen-restore")) { + fullscreen.fullClose().then(function() { + $(".fullScreen").eq(0).removeClass("layui-icon-screen-restore"); + }); + } else { + fullscreen.fullScreen().then(function() { + $(".fullScreen").eq(0).addClass("layui-icon-screen-restore"); + }); + } + }); + + body.on("click", '[user-menu-id]', function() { + if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) { + bodyTab.addTabOnly({ + id: $(this).attr("user-menu-id"), + title: $(this).attr("user-menu-title"), + url: $(this).attr("user-menu-url"), + icon: "", + close: true + }, 300); + } else { + bodyFrame.changePage($(this).attr("user-menu-url"), true); + } + }); + + body.on("click", ".setting", function() { + + var menuItem = + '
                                                                            • ' + + '' + + '
                                                                              ' + + '
                                                                              ' + + '
                                                                              ' + + '
                                                                            • '; + + menuItem += + '
                                                                            • ' + + '' + + '
                                                                              ' + + '
                                                                              ' + + '
                                                                              ' + + '
                                                                            • '; + + var menuHtml = + '
                                                                              \n' + + '
                                                                              菜单风格
                                                                              \n' + + '
                                                                              \n' + + '
                                                                                \n' + menuItem + '
                                                                              \n' + + '
                                                                              \n' + + '
                                                                              '; + + var headItem = + '
                                                                            • ' + + '' + + '
                                                                              ' + + '
                                                                              ' + + '
                                                                              ' + + '
                                                                            • '; + + headItem += + '
                                                                            • ' + + '' + + '
                                                                              ' + + '
                                                                              ' + + '
                                                                              ' + + '
                                                                            • '; + + var headHtml = + '
                                                                              \n' + + '
                                                                              顶部风格
                                                                              \n' + + '
                                                                              \n' + + '
                                                                                \n' + headItem + '
                                                                              \n' + + '
                                                                              \n' + + '
                                                                              '; + + var moreItem = + '
                                                                              菜单
                                                                              '; + + moreItem += + '
                                                                              视图
                                                                              '; + + moreItem += + '
                                                                              通栏
                                                                              '; + + moreItem += + '
                                                                              通色
                                                                              '; + + moreItem += + '
                                                                              页脚
                                                                              '; + + var moreHtml = '
                                                                              \n' + + '
                                                                              更多设置
                                                                              \n' + + '
                                                                              \n' + + '
                                                                              \n' + moreItem + '
                                                                              \n' + + '
                                                                              \n' + + '
                                                                              '; + + layer.open({ + type: 1, + offset: 'r', + area: ['320px', '100%'], + title: false, + shade: 0.1, + closeBtn: 0, + shadeClose: false, + anim: -1, + skin: 'layer-anim-right', + move: false, + content: menuHtml + headHtml + buildColorHtml() + moreHtml, + success: function(layero, index) { + + form.render(); + + var color = localStorage.getItem("theme-color"); + var menu = localStorage.getItem("theme-menu"); + var header = localStorage.getItem("theme-header"); + + if (color !== "null") { + $(".select-color-item").removeClass("layui-icon").removeClass("layui-icon-ok"); + $("*[color-id='" + color + "']").addClass("layui-icon").addClass("layui-icon-ok"); + } + + if (menu !== "null") { + $("*[data-select-bgcolor]").removeClass("layui-this"); + $("[data-select-bgcolor='" + menu + "']").addClass("layui-this"); + } + + if (header !== "null") { + $("*[data-select-header]").removeClass("layui-this"); + $("[data-select-header='" + header + "']").addClass("layui-this"); + } + + $('#layui-layer-shade' + index).click(function() { + var $layero = $('#layui-layer' + index); + $layero.animate({ + left: $layero.offset().left + $layero.width() + }, 200, function() { + layer.close(index); + }); + }) + + form.on('switch(control)', function(data) { + localStorage.setItem("control", this.checked); + window.location.reload(); + }) + + form.on('switch(muilt-tab)', function(data) { + localStorage.setItem("muilt-tab", this.checked); + window.location.reload(); + }) + + form.on('switch(auto-head)', function(data) { + localStorage.setItem("auto-head", this.checked); + pearTheme.changeTheme(window, this.checked); + }) + + form.on('switch(banner)', function(data) { + localStorage.setItem("theme-banner", this.checked); + pearAdmin.bannerSkin(this.checked); + }) + + form.on('switch(footer)', function (data) { + localStorage.setItem("footer", this.checked); + pearAdmin.footer(this.checked); + }) + + if (localStorage.getItem('theme-banner') === 'true') { + $('input[name="banner"]').attr('checked', 'checked') + } else { + $('input[name="banner"]').removeAttr('checked') + } + + if (localStorage.getItem('control') === 'true') { + $('input[name="control"]').attr('checked', 'checked') + } else { + $('input[name="control"]').removeAttr('checked') + } + + if (localStorage.getItem('muilt-tab') === 'true') { + $('input[name="muilt-tab"]').attr('checked', 'checked') + } else { + $('input[name="muilt-tab"]').removeAttr('checked') + } + + if (localStorage.getItem('auto-head') === 'true') { + $('input[name="auto-head"]').attr('checked', 'checked') + } else { + $('input[name="auto-head"]').removeAttr('checked') + } + + if (localStorage.getItem('footer') === 'true') { + $('input[name="footer"]').attr('checked', 'checked') + } else { + $('input[name="footer"]').removeAttr('checked') + } + + form.render('checkbox'); + } + }); + }); + + body.on('click', '[data-select-bgcolor]', function() { + var theme = $(this).attr('data-select-bgcolor'); + $('[data-select-bgcolor]').removeClass("layui-this"); + $(this).addClass("layui-this"); + localStorage.setItem("theme-menu", theme); + pearAdmin.menuSkin(theme); + }); + + body.on('click', '[data-select-header]', function() { + var theme = $(this).attr('data-select-header'); + $('[data-select-header]').removeClass("layui-this"); + $(this).addClass("layui-this"); + localStorage.setItem("theme-header", theme); + pearAdmin.headerSkin(theme); + }); + + body.on('click', '.select-color-item', function() { + $(".select-color-item").removeClass("layui-icon").removeClass("layui-icon-ok"); + $(this).addClass("layui-icon").addClass("layui-icon-ok"); + var colorId = $(".select-color-item.layui-icon-ok").attr("color-id"); + var currentColor = getColorById(colorId); + localStorage.setItem("theme-color", currentColor.id); + localStorage.setItem("theme-color-color", currentColor.color); + localStorage.setItem("theme-color-second", currentColor.second); + pearTheme.changeTheme(window, isAutoHead(config)); + }); + + function applyConfig(param) { + config = param; + pearAdmin.logoRender(param); + pearAdmin.menuRender(param); + pearAdmin.bodyRender(param); + pearAdmin.themeRender(param); + pearAdmin.keepLoad(param); + if (param.header.message != false) { + pearAdmin.messageRender(param); + } + } + + function getColorById(id) { + var color; + var flag = false; + $.each(config.colors, function(i, value) { + if (value.id === id) { + color = value; + flag = true; + } + }) + if (flag === false || config.theme.allowCustom === false) { + $.each(config.colors, function(i, value) { + if (value.id === config.theme.defaultColor) { + color = value; + } + }) + } + return color; + } + + function buildColorHtml() { + var colors = ""; + $.each(config.colors, function(i, value) { + colors += ""; + }) + return "
                                                                              主题配色
                                                                              " + + colors + "
                                                                              " + } + + function compatible() { + if ($(window).width() <= 768) { + collapse() + } + } + + function isControl(option) { + if (option.theme.allowCustom) { + if (localStorage.getItem("control") != null) { + return localStorage.getItem("control") + } else { + return option.menu.control + } + } else { + return option.menu.control + } + } + + function isAutoHead(option) { + if (option.theme.allowCustom) { + if (localStorage.getItem("auto-head") != null) { + return localStorage.getItem("auto-head"); + } else { + return option.other.autoHead; + } + } else { + return option.other.autoHead; + } + } + + function isMuiltTab(option) { + if (option.theme.allowCustom) { + if (localStorage.getItem("muilt-tab") != null) { + return localStorage.getItem("muilt-tab") + } else { + return option.tab.enable + } + } else { + return option.tab.enable + } + } + + window.onresize = function() { + if (!fullscreen.isFullscreen()) { + $(".fullScreen").eq(0).removeClass("layui-icon-screen-restore"); + } + } + + $(window).on('resize', debounce(function () { + if (sideMenu && !sideMenu.isCollapse && $(window).width() <= 768) { + collapse(); + } + },50)); + + function debounce(fn, awaitTime) { + var timerID = null + return function () { + var arg = arguments[0] + if (timerID) { + clearTimeout(timerID) + } + timerID = setTimeout(function () { + fn(arg) + }, awaitTime) + } + } + exports('admin', pearAdmin); + }) diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/area.js b/demo/webman/backend/plugin/admin/public/component/pear/module/area.js new file mode 100644 index 0000000000000000000000000000000000000000..604c91e9167bba0253b2124f17dc417441e47492 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/area.js @@ -0,0 +1,4070 @@ +layui.define(['layer', 'form', 'laytpl'], function (exports) { + "use strict"; + + let $ = layui.$ + , form = layui.form + , layarea = { + _id: 0 + , config: {} + , set: function (options) { + let that = this; + that.config = $.extend({}, that.config, options); + return that; + } + , on: function (events, callback) { + return layui.onevent.call(this, 'layarea', events, callback); + } + } + , thisArea = function () { + let that = this; + return { + layarea: function (files) { + that.layarea.call(that, files); + } + , config: that.config + , reload: that.reload + , events: that.events + } + } + , Class = function (options) { + let that = this; + that.config = $.extend({}, { + elem: '', + data: { + province: '', + city: '', + county: '', + provinceCode: 0, + cityCode: 0, + countyCode: 0, + } + }, options); + that.render(); + }; + + let areaList = { + province_list: { + 110000: '北京市', + 120000: '天津市', + 130000: '河北省', + 140000: '山西省', + 150000: '内蒙古自治区', + 210000: '辽宁省', + 220000: '吉林省', + 230000: '黑龙江省', + 310000: '上海市', + 320000: '江苏省', + 330000: '浙江省', + 340000: '安徽省', + 350000: '福建省', + 360000: '江西省', + 370000: '山东省', + 410000: '河南省', + 420000: '湖北省', + 430000: '湖南省', + 440000: '广东省', + 450000: '广西壮族自治区', + 460000: '海南省', + 500000: '重庆市', + 510000: '四川省', + 520000: '贵州省', + 530000: '云南省', + 540000: '西藏自治区', + 610000: '陕西省', + 620000: '甘肃省', + 630000: '青海省', + 640000: '宁夏回族自治区', + 650000: '新疆维吾尔自治区', + 710000: '台湾省', + 810000: '香港特别行政区', + 820000: '澳门特别行政区', + 900000: '海外' + }, + city_list: { + 110100: '北京市', + 120100: '天津市', + 130100: '石家庄市', + 130200: '唐山市', + 130300: '秦皇岛市', + 130400: '邯郸市', + 130500: '邢台市', + 130600: '保定市', + 130700: '张家口市', + 130800: '承德市', + 130900: '沧州市', + 131000: '廊坊市', + 131100: '衡水市', + 139000: '省直辖县', + 140100: '太原市', + 140200: '大同市', + 140300: '阳泉市', + 140400: '长治市', + 140500: '晋城市', + 140600: '朔州市', + 140700: '晋中市', + 140800: '运城市', + 140900: '忻州市', + 141000: '临汾市', + 141100: '吕梁市', + 150100: '呼和浩特市', + 150200: '包头市', + 150300: '乌海市', + 150400: '赤峰市', + 150500: '通辽市', + 150600: '鄂尔多斯市', + 150700: '呼伦贝尔市', + 150800: '巴彦淖尔市', + 150900: '乌兰察布市', + 152200: '兴安盟', + 152500: '锡林郭勒盟', + 152900: '阿拉善盟', + 210100: '沈阳市', + 210200: '大连市', + 210300: '鞍山市', + 210400: '抚顺市', + 210500: '本溪市', + 210600: '丹东市', + 210700: '锦州市', + 210800: '营口市', + 210900: '阜新市', + 211000: '辽阳市', + 211100: '盘锦市', + 211200: '铁岭市', + 211300: '朝阳市', + 211400: '葫芦岛市', + 220100: '长春市', + 220200: '吉林市', + 220300: '四平市', + 220400: '辽源市', + 220500: '通化市', + 220600: '白山市', + 220700: '松原市', + 220800: '白城市', + 222400: '延边朝鲜族自治州', + 230100: '哈尔滨市', + 230200: '齐齐哈尔市', + 230300: '鸡西市', + 230400: '鹤岗市', + 230500: '双鸭山市', + 230600: '大庆市', + 230700: '伊春市', + 230800: '佳木斯市', + 230900: '七台河市', + 231000: '牡丹江市', + 231100: '黑河市', + 231200: '绥化市', + 232700: '大兴安岭地区', + 310100: '上海市', + 320100: '南京市', + 320200: '无锡市', + 320300: '徐州市', + 320400: '常州市', + 320500: '苏州市', + 320600: '南通市', + 320700: '连云港市', + 320800: '淮安市', + 320900: '盐城市', + 321000: '扬州市', + 321100: '镇江市', + 321200: '泰州市', + 321300: '宿迁市', + 330100: '杭州市', + 330200: '宁波市', + 330300: '温州市', + 330400: '嘉兴市', + 330500: '湖州市', + 330600: '绍兴市', + 330700: '金华市', + 330800: '衢州市', + 330900: '舟山市', + 331000: '台州市', + 331100: '丽水市', + 340100: '合肥市', + 340200: '芜湖市', + 340300: '蚌埠市', + 340400: '淮南市', + 340500: '马鞍山市', + 340600: '淮北市', + 340700: '铜陵市', + 340800: '安庆市', + 341000: '黄山市', + 341100: '滁州市', + 341200: '阜阳市', + 341300: '宿州市', + 341500: '六安市', + 341600: '亳州市', + 341700: '池州市', + 341800: '宣城市', + 350100: '福州市', + 350200: '厦门市', + 350300: '莆田市', + 350400: '三明市', + 350500: '泉州市', + 350600: '漳州市', + 350700: '南平市', + 350800: '龙岩市', + 350900: '宁德市', + 360100: '南昌市', + 360200: '景德镇市', + 360300: '萍乡市', + 360400: '九江市', + 360500: '新余市', + 360600: '鹰潭市', + 360700: '赣州市', + 360800: '吉安市', + 360900: '宜春市', + 361000: '抚州市', + 361100: '上饶市', + 370100: '济南市', + 370200: '青岛市', + 370300: '淄博市', + 370400: '枣庄市', + 370500: '东营市', + 370600: '烟台市', + 370700: '潍坊市', + 370800: '济宁市', + 370900: '泰安市', + 371000: '威海市', + 371100: '日照市', + 371200: '莱芜市', + 371300: '临沂市', + 371400: '德州市', + 371500: '聊城市', + 371600: '滨州市', + 371700: '菏泽市', + 410100: '郑州市', + 410200: '开封市', + 410300: '洛阳市', + 410400: '平顶山市', + 410500: '安阳市', + 410600: '鹤壁市', + 410700: '新乡市', + 410800: '焦作市', + 410900: '濮阳市', + 411000: '许昌市', + 411100: '漯河市', + 411200: '三门峡市', + 411300: '南阳市', + 411400: '商丘市', + 411500: '信阳市', + 411600: '周口市', + 411700: '驻马店市', + 419000: '省直辖县', + 420100: '武汉市', + 420200: '黄石市', + 420300: '十堰市', + 420500: '宜昌市', + 420600: '襄阳市', + 420700: '鄂州市', + 420800: '荆门市', + 420900: '孝感市', + 421000: '荆州市', + 421100: '黄冈市', + 421200: '咸宁市', + 421300: '随州市', + 422800: '恩施土家族苗族自治州', + 429000: '省直辖县', + 430100: '长沙市', + 430200: '株洲市', + 430300: '湘潭市', + 430400: '衡阳市', + 430500: '邵阳市', + 430600: '岳阳市', + 430700: '常德市', + 430800: '张家界市', + 430900: '益阳市', + 431000: '郴州市', + 431100: '永州市', + 431200: '怀化市', + 431300: '娄底市', + 433100: '湘西土家族苗族自治州', + 440100: '广州市', + 440200: '韶关市', + 440300: '深圳市', + 440400: '珠海市', + 440500: '汕头市', + 440600: '佛山市', + 440700: '江门市', + 440800: '湛江市', + 440900: '茂名市', + 441200: '肇庆市', + 441300: '惠州市', + 441400: '梅州市', + 441500: '汕尾市', + 441600: '河源市', + 441700: '阳江市', + 441800: '清远市', + 441900: '东莞市', + 442000: '中山市', + 445100: '潮州市', + 445200: '揭阳市', + 445300: '云浮市', + 450100: '南宁市', + 450200: '柳州市', + 450300: '桂林市', + 450400: '梧州市', + 450500: '北海市', + 450600: '防城港市', + 450700: '钦州市', + 450800: '贵港市', + 450900: '玉林市', + 451000: '百色市', + 451100: '贺州市', + 451200: '河池市', + 451300: '来宾市', + 451400: '崇左市', + 460100: '海口市', + 460200: '三亚市', + 460300: '三沙市', + 460400: '儋州市', + 469000: '省直辖县', + 500100: '重庆市', + 500200: '县', + 510100: '成都市', + 510300: '自贡市', + 510400: '攀枝花市', + 510500: '泸州市', + 510600: '德阳市', + 510700: '绵阳市', + 510800: '广元市', + 510900: '遂宁市', + 511000: '内江市', + 511100: '乐山市', + 511300: '南充市', + 511400: '眉山市', + 511500: '宜宾市', + 511600: '广安市', + 511700: '达州市', + 511800: '雅安市', + 511900: '巴中市', + 512000: '资阳市', + 513200: '阿坝藏族羌族自治州', + 513300: '甘孜藏族自治州', + 513400: '凉山彝族自治州', + 520100: '贵阳市', + 520200: '六盘水市', + 520300: '遵义市', + 520400: '安顺市', + 520500: '毕节市', + 520600: '铜仁市', + 522300: '黔西南布依族苗族自治州', + 522600: '黔东南苗族侗族自治州', + 522700: '黔南布依族苗族自治州', + 530100: '昆明市', + 530300: '曲靖市', + 530400: '玉溪市', + 530500: '保山市', + 530600: '昭通市', + 530700: '丽江市', + 530800: '普洱市', + 530900: '临沧市', + 532300: '楚雄彝族自治州', + 532500: '红河哈尼族彝族自治州', + 532600: '文山壮族苗族自治州', + 532800: '西双版纳傣族自治州', + 532900: '大理白族自治州', + 533100: '德宏傣族景颇族自治州', + 533300: '怒江傈僳族自治州', + 533400: '迪庆藏族自治州', + 540100: '拉萨市', + 540200: '日喀则市', + 540300: '昌都市', + 540400: '林芝市', + 540500: '山南市', + 540600: '那曲市', + 542500: '阿里地区', + 610100: '西安市', + 610200: '铜川市', + 610300: '宝鸡市', + 610400: '咸阳市', + 610500: '渭南市', + 610600: '延安市', + 610700: '汉中市', + 610800: '榆林市', + 610900: '安康市', + 611000: '商洛市', + 620100: '兰州市', + 620200: '嘉峪关市', + 620300: '金昌市', + 620400: '白银市', + 620500: '天水市', + 620600: '武威市', + 620700: '张掖市', + 620800: '平凉市', + 620900: '酒泉市', + 621000: '庆阳市', + 621100: '定西市', + 621200: '陇南市', + 622900: '临夏回族自治州', + 623000: '甘南藏族自治州', + 630100: '西宁市', + 630200: '海东市', + 632200: '海北藏族自治州', + 632300: '黄南藏族自治州', + 632500: '海南藏族自治州', + 632600: '果洛藏族自治州', + 632700: '玉树藏族自治州', + 632800: '海西蒙古族藏族自治州', + 640100: '银川市', + 640200: '石嘴山市', + 640300: '吴忠市', + 640400: '固原市', + 640500: '中卫市', + 650100: '乌鲁木齐市', + 650200: '克拉玛依市', + 650400: '吐鲁番市', + 650500: '哈密市', + 652300: '昌吉回族自治州', + 652700: '博尔塔拉蒙古自治州', + 652800: '巴音郭楞蒙古自治州', + 652900: '阿克苏地区', + 653000: '克孜勒苏柯尔克孜自治州', + 653100: '喀什地区', + 653200: '和田地区', + 654000: '伊犁哈萨克自治州', + 654200: '塔城地区', + 654300: '阿勒泰地区', + 659000: '自治区直辖县级行政区划', + 710100: '台北市', + 710200: '高雄市', + 710300: '台南市', + 710400: '台中市', + 710500: '金门县', + 710600: '南投县', + 710700: '基隆市', + 710800: '新竹市', + 710900: '嘉义市', + 711100: '新北市', + 711200: '宜兰县', + 711300: '新竹县', + 711400: '桃园县', + 711500: '苗栗县', + 711700: '彰化县', + 711900: '嘉义县', + 712100: '云林县', + 712400: '屏东县', + 712500: '台东县', + 712600: '花莲县', + 712700: '澎湖县', + 712800: '连江县', + 810100: '香港岛', + 810200: '九龙', + 810300: '新界', + 820100: '澳门半岛', + 820200: '离岛', + 912400: '加拿大', + 941000: '韩国', + 984000: '美国' + }, + county_list: { + 110101: '东城区', + 110102: '西城区', + 110105: '朝阳区', + 110106: '丰台区', + 110107: '石景山区', + 110108: '海淀区', + 110109: '门头沟区', + 110111: '房山区', + 110112: '通州区', + 110113: '顺义区', + 110114: '昌平区', + 110115: '大兴区', + 110116: '怀柔区', + 110117: '平谷区', + 110118: '密云区', + 110119: '延庆区', + 120101: '和平区', + 120102: '河东区', + 120103: '河西区', + 120104: '南开区', + 120105: '河北区', + 120106: '红桥区', + 120110: '东丽区', + 120111: '西青区', + 120112: '津南区', + 120113: '北辰区', + 120114: '武清区', + 120115: '宝坻区', + 120116: '滨海新区', + 120117: '宁河区', + 120118: '静海区', + 120119: '蓟州区', + 130102: '长安区', + 130104: '桥西区', + 130105: '新华区', + 130107: '井陉矿区', + 130108: '裕华区', + 130109: '藁城区', + 130110: '鹿泉区', + 130111: '栾城区', + 130121: '井陉县', + 130123: '正定县', + 130125: '行唐县', + 130126: '灵寿县', + 130127: '高邑县', + 130128: '深泽县', + 130129: '赞皇县', + 130130: '无极县', + 130131: '平山县', + 130132: '元氏县', + 130133: '赵县', + 130181: '辛集市', + 130183: '晋州市', + 130184: '新乐市', + 130202: '路南区', + 130203: '路北区', + 130204: '古冶区', + 130205: '开平区', + 130207: '丰南区', + 130208: '丰润区', + 130209: '曹妃甸区', + 130223: '滦县', + 130224: '滦南县', + 130225: '乐亭县', + 130227: '迁西县', + 130229: '玉田县', + 130281: '遵化市', + 130283: '迁安市', + 130302: '海港区', + 130303: '山海关区', + 130304: '北戴河区', + 130306: '抚宁区', + 130321: '青龙满族自治县', + 130322: '昌黎县', + 130324: '卢龙县', + 130390: '经济技术开发区', + 130402: '邯山区', + 130403: '丛台区', + 130404: '复兴区', + 130406: '峰峰矿区', + 130407: '肥乡区', + 130408: '永年区', + 130423: '临漳县', + 130424: '成安县', + 130425: '大名县', + 130426: '涉县', + 130427: '磁县', + 130430: '邱县', + 130431: '鸡泽县', + 130432: '广平县', + 130433: '馆陶县', + 130434: '魏县', + 130435: '曲周县', + 130481: '武安市', + 130502: '桥东区', + 130503: '桥西区', + 130521: '邢台县', + 130522: '临城县', + 130523: '内丘县', + 130524: '柏乡县', + 130525: '隆尧县', + 130526: '任县', + 130527: '南和县', + 130528: '宁晋县', + 130529: '巨鹿县', + 130530: '新河县', + 130531: '广宗县', + 130532: '平乡县', + 130533: '威县', + 130534: '清河县', + 130535: '临西县', + 130581: '南宫市', + 130582: '沙河市', + 130602: '竞秀区', + 130606: '莲池区', + 130607: '满城区', + 130608: '清苑区', + 130609: '徐水区', + 130623: '涞水县', + 130624: '阜平县', + 130626: '定兴县', + 130627: '唐县', + 130628: '高阳县', + 130629: '容城县', + 130630: '涞源县', + 130631: '望都县', + 130632: '安新县', + 130633: '易县', + 130634: '曲阳县', + 130635: '蠡县', + 130636: '顺平县', + 130637: '博野县', + 130638: '雄县', + 130681: '涿州市', + 130682: '定州市', + 130683: '安国市', + 130684: '高碑店市', + 130702: '桥东区', + 130703: '桥西区', + 130705: '宣化区', + 130706: '下花园区', + 130708: '万全区', + 130709: '崇礼区', + 130722: '张北县', + 130723: '康保县', + 130724: '沽源县', + 130725: '尚义县', + 130726: '蔚县', + 130727: '阳原县', + 130728: '怀安县', + 130730: '怀来县', + 130731: '涿鹿县', + 130732: '赤城县', + 130802: '双桥区', + 130803: '双滦区', + 130804: '鹰手营子矿区', + 130821: '承德县', + 130822: '兴隆县', + 130824: '滦平县', + 130825: '隆化县', + 130826: '丰宁满族自治县', + 130827: '宽城满族自治县', + 130828: '围场满族蒙古族自治县', + 130881: '平泉市', + 130902: '新华区', + 130903: '运河区', + 130921: '沧县', + 130922: '青县', + 130923: '东光县', + 130924: '海兴县', + 130925: '盐山县', + 130926: '肃宁县', + 130927: '南皮县', + 130928: '吴桥县', + 130929: '献县', + 130930: '孟村回族自治县', + 130981: '泊头市', + 130982: '任丘市', + 130983: '黄骅市', + 130984: '河间市', + 131002: '安次区', + 131003: '广阳区', + 131022: '固安县', + 131023: '永清县', + 131024: '香河县', + 131025: '大城县', + 131026: '文安县', + 131028: '大厂回族自治县', + 131081: '霸州市', + 131082: '三河市', + 131090: '开发区', + 131102: '桃城区', + 131103: '冀州区', + 131121: '枣强县', + 131122: '武邑县', + 131123: '武强县', + 131124: '饶阳县', + 131125: '安平县', + 131126: '故城县', + 131127: '景县', + 131128: '阜城县', + 131182: '深州市', + 140105: '小店区', + 140106: '迎泽区', + 140107: '杏花岭区', + 140108: '尖草坪区', + 140109: '万柏林区', + 140110: '晋源区', + 140121: '清徐县', + 140122: '阳曲县', + 140123: '娄烦县', + 140181: '古交市', + 140202: '城区', + 140203: '矿区', + 140211: '南郊区', + 140212: '新荣区', + 140221: '阳高县', + 140222: '天镇县', + 140223: '广灵县', + 140224: '灵丘县', + 140225: '浑源县', + 140226: '左云县', + 140227: '大同县', + 140302: '城区', + 140303: '矿区', + 140311: '郊区', + 140321: '平定县', + 140322: '盂县', + 140402: '城区', + 140411: '郊区', + 140421: '长治县', + 140423: '襄垣县', + 140424: '屯留县', + 140425: '平顺县', + 140426: '黎城县', + 140427: '壶关县', + 140428: '长子县', + 140429: '武乡县', + 140430: '沁县', + 140431: '沁源县', + 140481: '潞城市', + 140502: '城区', + 140521: '沁水县', + 140522: '阳城县', + 140524: '陵川县', + 140525: '泽州县', + 140581: '高平市', + 140602: '朔城区', + 140603: '平鲁区', + 140621: '山阴县', + 140622: '应县', + 140623: '右玉县', + 140624: '怀仁县', + 140702: '榆次区', + 140721: '榆社县', + 140722: '左权县', + 140723: '和顺县', + 140724: '昔阳县', + 140725: '寿阳县', + 140726: '太谷县', + 140727: '祁县', + 140728: '平遥县', + 140729: '灵石县', + 140781: '介休市', + 140802: '盐湖区', + 140821: '临猗县', + 140822: '万荣县', + 140823: '闻喜县', + 140824: '稷山县', + 140825: '新绛县', + 140826: '绛县', + 140827: '垣曲县', + 140828: '夏县', + 140829: '平陆县', + 140830: '芮城县', + 140881: '永济市', + 140882: '河津市', + 140902: '忻府区', + 140921: '定襄县', + 140922: '五台县', + 140923: '代县', + 140924: '繁峙县', + 140925: '宁武县', + 140926: '静乐县', + 140927: '神池县', + 140928: '五寨县', + 140929: '岢岚县', + 140930: '河曲县', + 140931: '保德县', + 140932: '偏关县', + 140981: '原平市', + 141002: '尧都区', + 141021: '曲沃县', + 141022: '翼城县', + 141023: '襄汾县', + 141024: '洪洞县', + 141025: '古县', + 141026: '安泽县', + 141027: '浮山县', + 141028: '吉县', + 141029: '乡宁县', + 141030: '大宁县', + 141031: '隰县', + 141032: '永和县', + 141033: '蒲县', + 141034: '汾西县', + 141081: '侯马市', + 141082: '霍州市', + 141102: '离石区', + 141121: '文水县', + 141122: '交城县', + 141123: '兴县', + 141124: '临县', + 141125: '柳林县', + 141126: '石楼县', + 141127: '岚县', + 141128: '方山县', + 141129: '中阳县', + 141130: '交口县', + 141181: '孝义市', + 141182: '汾阳市', + 150102: '新城区', + 150103: '回民区', + 150104: '玉泉区', + 150105: '赛罕区', + 150121: '土默特左旗', + 150122: '托克托县', + 150123: '和林格尔县', + 150124: '清水河县', + 150125: '武川县', + 150202: '东河区', + 150203: '昆都仑区', + 150204: '青山区', + 150205: '石拐区', + 150206: '白云鄂博矿区', + 150207: '九原区', + 150221: '土默特右旗', + 150222: '固阳县', + 150223: '达尔罕茂明安联合旗', + 150302: '海勃湾区', + 150303: '海南区', + 150304: '乌达区', + 150402: '红山区', + 150403: '元宝山区', + 150404: '松山区', + 150421: '阿鲁科尔沁旗', + 150422: '巴林左旗', + 150423: '巴林右旗', + 150424: '林西县', + 150425: '克什克腾旗', + 150426: '翁牛特旗', + 150428: '喀喇沁旗', + 150429: '宁城县', + 150430: '敖汉旗', + 150502: '科尔沁区', + 150521: '科尔沁左翼中旗', + 150522: '科尔沁左翼后旗', + 150523: '开鲁县', + 150524: '库伦旗', + 150525: '奈曼旗', + 150526: '扎鲁特旗', + 150581: '霍林郭勒市', + 150602: '东胜区', + 150603: '康巴什区', + 150621: '达拉特旗', + 150622: '准格尔旗', + 150623: '鄂托克前旗', + 150624: '鄂托克旗', + 150625: '杭锦旗', + 150626: '乌审旗', + 150627: '伊金霍洛旗', + 150702: '海拉尔区', + 150703: '扎赉诺尔区', + 150721: '阿荣旗', + 150722: '莫力达瓦达斡尔族自治旗', + 150723: '鄂伦春自治旗', + 150724: '鄂温克族自治旗', + 150725: '陈巴尔虎旗', + 150726: '新巴尔虎左旗', + 150727: '新巴尔虎右旗', + 150781: '满洲里市', + 150782: '牙克石市', + 150783: '扎兰屯市', + 150784: '额尔古纳市', + 150785: '根河市', + 150802: '临河区', + 150821: '五原县', + 150822: '磴口县', + 150823: '乌拉特前旗', + 150824: '乌拉特中旗', + 150825: '乌拉特后旗', + 150826: '杭锦后旗', + 150902: '集宁区', + 150921: '卓资县', + 150922: '化德县', + 150923: '商都县', + 150924: '兴和县', + 150925: '凉城县', + 150926: '察哈尔右翼前旗', + 150927: '察哈尔右翼中旗', + 150928: '察哈尔右翼后旗', + 150929: '四子王旗', + 150981: '丰镇市', + 152201: '乌兰浩特市', + 152202: '阿尔山市', + 152221: '科尔沁右翼前旗', + 152222: '科尔沁右翼中旗', + 152223: '扎赉特旗', + 152224: '突泉县', + 152501: '二连浩特市', + 152502: '锡林浩特市', + 152522: '阿巴嘎旗', + 152523: '苏尼特左旗', + 152524: '苏尼特右旗', + 152525: '东乌珠穆沁旗', + 152526: '西乌珠穆沁旗', + 152527: '太仆寺旗', + 152528: '镶黄旗', + 152529: '正镶白旗', + 152530: '正蓝旗', + 152531: '多伦县', + 152921: '阿拉善左旗', + 152922: '阿拉善右旗', + 152923: '额济纳旗', + 210102: '和平区', + 210103: '沈河区', + 210104: '大东区', + 210105: '皇姑区', + 210106: '铁西区', + 210111: '苏家屯区', + 210112: '浑南区', + 210113: '沈北新区', + 210114: '于洪区', + 210115: '辽中区', + 210123: '康平县', + 210124: '法库县', + 210181: '新民市', + 210190: '经济技术开发区', + 210202: '中山区', + 210203: '西岗区', + 210204: '沙河口区', + 210211: '甘井子区', + 210212: '旅顺口区', + 210213: '金州区', + 210214: '普兰店区', + 210224: '长海县', + 210281: '瓦房店市', + 210283: '庄河市', + 210302: '铁东区', + 210303: '铁西区', + 210304: '立山区', + 210311: '千山区', + 210321: '台安县', + 210323: '岫岩满族自治县', + 210381: '海城市', + 210390: '高新区', + 210402: '新抚区', + 210403: '东洲区', + 210404: '望花区', + 210411: '顺城区', + 210421: '抚顺县', + 210422: '新宾满族自治县', + 210423: '清原满族自治县', + 210502: '平山区', + 210503: '溪湖区', + 210504: '明山区', + 210505: '南芬区', + 210521: '本溪满族自治县', + 210522: '桓仁满族自治县', + 210602: '元宝区', + 210603: '振兴区', + 210604: '振安区', + 210624: '宽甸满族自治县', + 210681: '东港市', + 210682: '凤城市', + 210702: '古塔区', + 210703: '凌河区', + 210711: '太和区', + 210726: '黑山县', + 210727: '义县', + 210781: '凌海市', + 210782: '北镇市', + 210793: '经济技术开发区', + 210802: '站前区', + 210803: '西市区', + 210804: '鲅鱼圈区', + 210811: '老边区', + 210881: '盖州市', + 210882: '大石桥市', + 210902: '海州区', + 210903: '新邱区', + 210904: '太平区', + 210905: '清河门区', + 210911: '细河区', + 210921: '阜新蒙古族自治县', + 210922: '彰武县', + 211002: '白塔区', + 211003: '文圣区', + 211004: '宏伟区', + 211005: '弓长岭区', + 211011: '太子河区', + 211021: '辽阳县', + 211081: '灯塔市', + 211102: '双台子区', + 211103: '兴隆台区', + 211104: '大洼区', + 211122: '盘山县', + 211202: '银州区', + 211204: '清河区', + 211221: '铁岭县', + 211223: '西丰县', + 211224: '昌图县', + 211281: '调兵山市', + 211282: '开原市', + 211302: '双塔区', + 211303: '龙城区', + 211321: '朝阳县', + 211322: '建平县', + 211324: '喀喇沁左翼蒙古族自治县', + 211381: '北票市', + 211382: '凌源市', + 211402: '连山区', + 211403: '龙港区', + 211404: '南票区', + 211421: '绥中县', + 211422: '建昌县', + 211481: '兴城市', + 215090: '工业园区', + 220102: '南关区', + 220103: '宽城区', + 220104: '朝阳区', + 220105: '二道区', + 220106: '绿园区', + 220112: '双阳区', + 220113: '九台区', + 220122: '农安县', + 220182: '榆树市', + 220183: '德惠市', + 220192: '经济技术开发区', + 220202: '昌邑区', + 220203: '龙潭区', + 220204: '船营区', + 220211: '丰满区', + 220221: '永吉县', + 220281: '蛟河市', + 220282: '桦甸市', + 220283: '舒兰市', + 220284: '磐石市', + 220302: '铁西区', + 220303: '铁东区', + 220322: '梨树县', + 220323: '伊通满族自治县', + 220381: '公主岭市', + 220382: '双辽市', + 220402: '龙山区', + 220403: '西安区', + 220421: '东丰县', + 220422: '东辽县', + 220502: '东昌区', + 220503: '二道江区', + 220521: '通化县', + 220523: '辉南县', + 220524: '柳河县', + 220581: '梅河口市', + 220582: '集安市', + 220602: '浑江区', + 220605: '江源区', + 220621: '抚松县', + 220622: '靖宇县', + 220623: '长白朝鲜族自治县', + 220681: '临江市', + 220702: '宁江区', + 220721: '前郭尔罗斯蒙古族自治县', + 220722: '长岭县', + 220723: '乾安县', + 220781: '扶余市', + 220802: '洮北区', + 220821: '镇赉县', + 220822: '通榆县', + 220881: '洮南市', + 220882: '大安市', + 221090: '工业园区', + 222401: '延吉市', + 222402: '图们市', + 222403: '敦化市', + 222404: '珲春市', + 222405: '龙井市', + 222406: '和龙市', + 222424: '汪清县', + 222426: '安图县', + 230102: '道里区', + 230103: '南岗区', + 230104: '道外区', + 230108: '平房区', + 230109: '松北区', + 230110: '香坊区', + 230111: '呼兰区', + 230112: '阿城区', + 230113: '双城区', + 230123: '依兰县', + 230124: '方正县', + 230125: '宾县', + 230126: '巴彦县', + 230127: '木兰县', + 230128: '通河县', + 230129: '延寿县', + 230183: '尚志市', + 230184: '五常市', + 230202: '龙沙区', + 230203: '建华区', + 230204: '铁锋区', + 230205: '昂昂溪区', + 230206: '富拉尔基区', + 230207: '碾子山区', + 230208: '梅里斯达斡尔族区', + 230221: '龙江县', + 230223: '依安县', + 230224: '泰来县', + 230225: '甘南县', + 230227: '富裕县', + 230229: '克山县', + 230230: '克东县', + 230231: '拜泉县', + 230281: '讷河市', + 230302: '鸡冠区', + 230303: '恒山区', + 230304: '滴道区', + 230305: '梨树区', + 230306: '城子河区', + 230307: '麻山区', + 230321: '鸡东县', + 230381: '虎林市', + 230382: '密山市', + 230402: '向阳区', + 230403: '工农区', + 230404: '南山区', + 230405: '兴安区', + 230406: '东山区', + 230407: '兴山区', + 230421: '萝北县', + 230422: '绥滨县', + 230502: '尖山区', + 230503: '岭东区', + 230505: '四方台区', + 230506: '宝山区', + 230521: '集贤县', + 230522: '友谊县', + 230523: '宝清县', + 230524: '饶河县', + 230602: '萨尔图区', + 230603: '龙凤区', + 230604: '让胡路区', + 230605: '红岗区', + 230606: '大同区', + 230621: '肇州县', + 230622: '肇源县', + 230623: '林甸县', + 230624: '杜尔伯特蒙古族自治县', + 230702: '伊春区', + 230703: '南岔区', + 230704: '友好区', + 230705: '西林区', + 230706: '翠峦区', + 230707: '新青区', + 230708: '美溪区', + 230709: '金山屯区', + 230710: '五营区', + 230711: '乌马河区', + 230712: '汤旺河区', + 230713: '带岭区', + 230714: '乌伊岭区', + 230715: '红星区', + 230716: '上甘岭区', + 230722: '嘉荫县', + 230781: '铁力市', + 230803: '向阳区', + 230804: '前进区', + 230805: '东风区', + 230811: '郊区', + 230822: '桦南县', + 230826: '桦川县', + 230828: '汤原县', + 230881: '同江市', + 230882: '富锦市', + 230883: '抚远市', + 230902: '新兴区', + 230903: '桃山区', + 230904: '茄子河区', + 230921: '勃利县', + 231002: '东安区', + 231003: '阳明区', + 231004: '爱民区', + 231005: '西安区', + 231025: '林口县', + 231081: '绥芬河市', + 231083: '海林市', + 231084: '宁安市', + 231085: '穆棱市', + 231086: '东宁市', + 231102: '爱辉区', + 231121: '嫩江县', + 231123: '逊克县', + 231124: '孙吴县', + 231181: '北安市', + 231182: '五大连池市', + 231202: '北林区', + 231221: '望奎县', + 231222: '兰西县', + 231223: '青冈县', + 231224: '庆安县', + 231225: '明水县', + 231226: '绥棱县', + 231281: '安达市', + 231282: '肇东市', + 231283: '海伦市', + 232721: '呼玛县', + 232722: '塔河县', + 232723: '漠河县', + 232790: '松岭区', + 232791: '呼中区', + 232792: '加格达奇区', + 232793: '新林区', + 310101: '黄浦区', + 310104: '徐汇区', + 310105: '长宁区', + 310106: '静安区', + 310107: '普陀区', + 310109: '虹口区', + 310110: '杨浦区', + 310112: '闵行区', + 310113: '宝山区', + 310114: '嘉定区', + 310115: '浦东新区', + 310116: '金山区', + 310117: '松江区', + 310118: '青浦区', + 310120: '奉贤区', + 310151: '崇明区', + 320102: '玄武区', + 320104: '秦淮区', + 320105: '建邺区', + 320106: '鼓楼区', + 320111: '浦口区', + 320113: '栖霞区', + 320114: '雨花台区', + 320115: '江宁区', + 320116: '六合区', + 320117: '溧水区', + 320118: '高淳区', + 320205: '锡山区', + 320206: '惠山区', + 320211: '滨湖区', + 320213: '梁溪区', + 320214: '新吴区', + 320281: '江阴市', + 320282: '宜兴市', + 320302: '鼓楼区', + 320303: '云龙区', + 320305: '贾汪区', + 320311: '泉山区', + 320312: '铜山区', + 320321: '丰县', + 320322: '沛县', + 320324: '睢宁县', + 320381: '新沂市', + 320382: '邳州市', + 320391: '工业园区', + 320402: '天宁区', + 320404: '钟楼区', + 320411: '新北区', + 320412: '武进区', + 320413: '金坛区', + 320481: '溧阳市', + 320505: '虎丘区', + 320506: '吴中区', + 320507: '相城区', + 320508: '姑苏区', + 320509: '吴江区', + 320581: '常熟市', + 320582: '张家港市', + 320583: '昆山市', + 320585: '太仓市', + 320590: '工业园区', + 320591: '高新区', + 320602: '崇川区', + 320611: '港闸区', + 320612: '通州区', + 320621: '海安县', + 320623: '如东县', + 320681: '启东市', + 320682: '如皋市', + 320684: '海门市', + 320691: '高新区', + 320703: '连云区', + 320706: '海州区', + 320707: '赣榆区', + 320722: '东海县', + 320723: '灌云县', + 320724: '灌南县', + 320803: '淮安区', + 320804: '淮阴区', + 320812: '清江浦区', + 320813: '洪泽区', + 320826: '涟水县', + 320830: '盱眙县', + 320831: '金湖县', + 320890: '经济开发区', + 320902: '亭湖区', + 320903: '盐都区', + 320904: '大丰区', + 320921: '响水县', + 320922: '滨海县', + 320923: '阜宁县', + 320924: '射阳县', + 320925: '建湖县', + 320981: '东台市', + 321002: '广陵区', + 321003: '邗江区', + 321012: '江都区', + 321023: '宝应县', + 321081: '仪征市', + 321084: '高邮市', + 321090: '经济开发区', + 321102: '京口区', + 321111: '润州区', + 321112: '丹徒区', + 321181: '丹阳市', + 321182: '扬中市', + 321183: '句容市', + 321202: '海陵区', + 321203: '高港区', + 321204: '姜堰区', + 321281: '兴化市', + 321282: '靖江市', + 321283: '泰兴市', + 321302: '宿城区', + 321311: '宿豫区', + 321322: '沭阳县', + 321323: '泗阳县', + 321324: '泗洪县', + 330102: '上城区', + 330103: '下城区', + 330104: '江干区', + 330105: '拱墅区', + 330106: '西湖区', + 330108: '滨江区', + 330109: '萧山区', + 330110: '余杭区', + 330111: '富阳区', + 330112: '临安区', + 330122: '桐庐县', + 330127: '淳安县', + 330182: '建德市', + 330203: '海曙区', + 330205: '江北区', + 330206: '北仑区', + 330211: '镇海区', + 330212: '鄞州区', + 330213: '奉化区', + 330225: '象山县', + 330226: '宁海县', + 330281: '余姚市', + 330282: '慈溪市', + 330302: '鹿城区', + 330303: '龙湾区', + 330304: '瓯海区', + 330305: '洞头区', + 330324: '永嘉县', + 330326: '平阳县', + 330327: '苍南县', + 330328: '文成县', + 330329: '泰顺县', + 330381: '瑞安市', + 330382: '乐清市', + 330402: '南湖区', + 330411: '秀洲区', + 330421: '嘉善县', + 330424: '海盐县', + 330481: '海宁市', + 330482: '平湖市', + 330483: '桐乡市', + 330502: '吴兴区', + 330503: '南浔区', + 330521: '德清县', + 330522: '长兴县', + 330523: '安吉县', + 330602: '越城区', + 330603: '柯桥区', + 330604: '上虞区', + 330624: '新昌县', + 330681: '诸暨市', + 330683: '嵊州市', + 330702: '婺城区', + 330703: '金东区', + 330723: '武义县', + 330726: '浦江县', + 330727: '磐安县', + 330781: '兰溪市', + 330782: '义乌市', + 330783: '东阳市', + 330784: '永康市', + 330802: '柯城区', + 330803: '衢江区', + 330822: '常山县', + 330824: '开化县', + 330825: '龙游县', + 330881: '江山市', + 330902: '定海区', + 330903: '普陀区', + 330921: '岱山县', + 330922: '嵊泗县', + 331002: '椒江区', + 331003: '黄岩区', + 331004: '路桥区', + 331022: '三门县', + 331023: '天台县', + 331024: '仙居县', + 331081: '温岭市', + 331082: '临海市', + 331083: '玉环市', + 331102: '莲都区', + 331121: '青田县', + 331122: '缙云县', + 331123: '遂昌县', + 331124: '松阳县', + 331125: '云和县', + 331126: '庆元县', + 331127: '景宁畲族自治县', + 331181: '龙泉市', + 340102: '瑶海区', + 340103: '庐阳区', + 340104: '蜀山区', + 340111: '包河区', + 340121: '长丰县', + 340122: '肥东县', + 340123: '肥西县', + 340124: '庐江县', + 340181: '巢湖市', + 340190: '高新技术开发区', + 340191: '经济技术开发区', + 340202: '镜湖区', + 340203: '弋江区', + 340207: '鸠江区', + 340208: '三山区', + 340221: '芜湖县', + 340222: '繁昌县', + 340223: '南陵县', + 340225: '无为县', + 340302: '龙子湖区', + 340303: '蚌山区', + 340304: '禹会区', + 340311: '淮上区', + 340321: '怀远县', + 340322: '五河县', + 340323: '固镇县', + 340402: '大通区', + 340403: '田家庵区', + 340404: '谢家集区', + 340405: '八公山区', + 340406: '潘集区', + 340421: '凤台县', + 340422: '寿县', + 340503: '花山区', + 340504: '雨山区', + 340506: '博望区', + 340521: '当涂县', + 340522: '含山县', + 340523: '和县', + 340602: '杜集区', + 340603: '相山区', + 340604: '烈山区', + 340621: '濉溪县', + 340705: '铜官区', + 340706: '义安区', + 340711: '郊区', + 340722: '枞阳县', + 340802: '迎江区', + 340803: '大观区', + 340811: '宜秀区', + 340822: '怀宁县', + 340824: '潜山县', + 340825: '太湖县', + 340826: '宿松县', + 340827: '望江县', + 340828: '岳西县', + 340881: '桐城市', + 341002: '屯溪区', + 341003: '黄山区', + 341004: '徽州区', + 341021: '歙县', + 341022: '休宁县', + 341023: '黟县', + 341024: '祁门县', + 341102: '琅琊区', + 341103: '南谯区', + 341122: '来安县', + 341124: '全椒县', + 341125: '定远县', + 341126: '凤阳县', + 341181: '天长市', + 341182: '明光市', + 341202: '颍州区', + 341203: '颍东区', + 341204: '颍泉区', + 341221: '临泉县', + 341222: '太和县', + 341225: '阜南县', + 341226: '颍上县', + 341282: '界首市', + 341302: '埇桥区', + 341321: '砀山县', + 341322: '萧县', + 341323: '灵璧县', + 341324: '泗县', + 341390: '经济开发区', + 341502: '金安区', + 341503: '裕安区', + 341504: '叶集区', + 341522: '霍邱县', + 341523: '舒城县', + 341524: '金寨县', + 341525: '霍山县', + 341602: '谯城区', + 341621: '涡阳县', + 341622: '蒙城县', + 341623: '利辛县', + 341702: '贵池区', + 341721: '东至县', + 341722: '石台县', + 341723: '青阳县', + 341802: '宣州区', + 341821: '郎溪县', + 341822: '广德县', + 341823: '泾县', + 341824: '绩溪县', + 341825: '旌德县', + 341881: '宁国市', + 350102: '鼓楼区', + 350103: '台江区', + 350104: '仓山区', + 350105: '马尾区', + 350111: '晋安区', + 350112: '长乐区', + 350121: '闽侯县', + 350122: '连江县', + 350123: '罗源县', + 350124: '闽清县', + 350125: '永泰县', + 350128: '平潭县', + 350181: '福清市', + 350203: '思明区', + 350205: '海沧区', + 350206: '湖里区', + 350211: '集美区', + 350212: '同安区', + 350213: '翔安区', + 350302: '城厢区', + 350303: '涵江区', + 350304: '荔城区', + 350305: '秀屿区', + 350322: '仙游县', + 350402: '梅列区', + 350403: '三元区', + 350421: '明溪县', + 350423: '清流县', + 350424: '宁化县', + 350425: '大田县', + 350426: '尤溪县', + 350427: '沙县', + 350428: '将乐县', + 350429: '泰宁县', + 350430: '建宁县', + 350481: '永安市', + 350502: '鲤城区', + 350503: '丰泽区', + 350504: '洛江区', + 350505: '泉港区', + 350521: '惠安县', + 350524: '安溪县', + 350525: '永春县', + 350526: '德化县', + 350527: '金门县', + 350581: '石狮市', + 350582: '晋江市', + 350583: '南安市', + 350602: '芗城区', + 350603: '龙文区', + 350622: '云霄县', + 350623: '漳浦县', + 350624: '诏安县', + 350625: '长泰县', + 350626: '东山县', + 350627: '南靖县', + 350628: '平和县', + 350629: '华安县', + 350681: '龙海市', + 350702: '延平区', + 350703: '建阳区', + 350721: '顺昌县', + 350722: '浦城县', + 350723: '光泽县', + 350724: '松溪县', + 350725: '政和县', + 350781: '邵武市', + 350782: '武夷山市', + 350783: '建瓯市', + 350802: '新罗区', + 350803: '永定区', + 350821: '长汀县', + 350823: '上杭县', + 350824: '武平县', + 350825: '连城县', + 350881: '漳平市', + 350902: '蕉城区', + 350921: '霞浦县', + 350922: '古田县', + 350923: '屏南县', + 350924: '寿宁县', + 350925: '周宁县', + 350926: '柘荣县', + 350981: '福安市', + 350982: '福鼎市', + 360102: '东湖区', + 360103: '西湖区', + 360104: '青云谱区', + 360105: '湾里区', + 360111: '青山湖区', + 360112: '新建区', + 360121: '南昌县', + 360123: '安义县', + 360124: '进贤县', + 360190: '经济技术开发区', + 360192: '高新区', + 360202: '昌江区', + 360203: '珠山区', + 360222: '浮梁县', + 360281: '乐平市', + 360302: '安源区', + 360313: '湘东区', + 360321: '莲花县', + 360322: '上栗县', + 360323: '芦溪县', + 360402: '濂溪区', + 360403: '浔阳区', + 360404: '柴桑区', + 360423: '武宁县', + 360424: '修水县', + 360425: '永修县', + 360426: '德安县', + 360428: '都昌县', + 360429: '湖口县', + 360430: '彭泽县', + 360481: '瑞昌市', + 360482: '共青城市', + 360483: '庐山市', + 360490: '经济技术开发区', + 360502: '渝水区', + 360521: '分宜县', + 360602: '月湖区', + 360622: '余江县', + 360681: '贵溪市', + 360702: '章贡区', + 360703: '南康区', + 360704: '赣县区', + 360722: '信丰县', + 360723: '大余县', + 360724: '上犹县', + 360725: '崇义县', + 360726: '安远县', + 360727: '龙南县', + 360728: '定南县', + 360729: '全南县', + 360730: '宁都县', + 360731: '于都县', + 360732: '兴国县', + 360733: '会昌县', + 360734: '寻乌县', + 360735: '石城县', + 360781: '瑞金市', + 360802: '吉州区', + 360803: '青原区', + 360821: '吉安县', + 360822: '吉水县', + 360823: '峡江县', + 360824: '新干县', + 360825: '永丰县', + 360826: '泰和县', + 360827: '遂川县', + 360828: '万安县', + 360829: '安福县', + 360830: '永新县', + 360881: '井冈山市', + 360902: '袁州区', + 360921: '奉新县', + 360922: '万载县', + 360923: '上高县', + 360924: '宜丰县', + 360925: '靖安县', + 360926: '铜鼓县', + 360981: '丰城市', + 360982: '樟树市', + 360983: '高安市', + 361002: '临川区', + 361003: '东乡区', + 361021: '南城县', + 361022: '黎川县', + 361023: '南丰县', + 361024: '崇仁县', + 361025: '乐安县', + 361026: '宜黄县', + 361027: '金溪县', + 361028: '资溪县', + 361030: '广昌县', + 361102: '信州区', + 361103: '广丰区', + 361121: '上饶县', + 361123: '玉山县', + 361124: '铅山县', + 361125: '横峰县', + 361126: '弋阳县', + 361127: '余干县', + 361128: '鄱阳县', + 361129: '万年县', + 361130: '婺源县', + 361181: '德兴市', + 370102: '历下区', + 370103: '市中区', + 370104: '槐荫区', + 370105: '天桥区', + 370112: '历城区', + 370113: '长清区', + 370114: '章丘区', + 370124: '平阴县', + 370125: '济阳县', + 370126: '商河县', + 370190: '高新区', + 370202: '市南区', + 370203: '市北区', + 370211: '黄岛区', + 370212: '崂山区', + 370213: '李沧区', + 370214: '城阳区', + 370215: '即墨区', + 370281: '胶州市', + 370283: '平度市', + 370285: '莱西市', + 370290: '开发区', + 370302: '淄川区', + 370303: '张店区', + 370304: '博山区', + 370305: '临淄区', + 370306: '周村区', + 370321: '桓台县', + 370322: '高青县', + 370323: '沂源县', + 370402: '市中区', + 370403: '薛城区', + 370404: '峄城区', + 370405: '台儿庄区', + 370406: '山亭区', + 370481: '滕州市', + 370502: '东营区', + 370503: '河口区', + 370505: '垦利区', + 370522: '利津县', + 370523: '广饶县', + 370602: '芝罘区', + 370611: '福山区', + 370612: '牟平区', + 370613: '莱山区', + 370634: '长岛县', + 370681: '龙口市', + 370682: '莱阳市', + 370683: '莱州市', + 370684: '蓬莱市', + 370685: '招远市', + 370686: '栖霞市', + 370687: '海阳市', + 370690: '开发区', + 370702: '潍城区', + 370703: '寒亭区', + 370704: '坊子区', + 370705: '奎文区', + 370724: '临朐县', + 370725: '昌乐县', + 370781: '青州市', + 370782: '诸城市', + 370783: '寿光市', + 370784: '安丘市', + 370785: '高密市', + 370786: '昌邑市', + 370790: '开发区', + 370791: '高新区', + 370811: '任城区', + 370812: '兖州区', + 370826: '微山县', + 370827: '鱼台县', + 370828: '金乡县', + 370829: '嘉祥县', + 370830: '汶上县', + 370831: '泗水县', + 370832: '梁山县', + 370881: '曲阜市', + 370883: '邹城市', + 370890: '高新区', + 370902: '泰山区', + 370911: '岱岳区', + 370921: '宁阳县', + 370923: '东平县', + 370982: '新泰市', + 370983: '肥城市', + 371002: '环翠区', + 371003: '文登区', + 371082: '荣成市', + 371083: '乳山市', + 371091: '经济技术开发区', + 371102: '东港区', + 371103: '岚山区', + 371121: '五莲县', + 371122: '莒县', + 371202: '莱城区', + 371203: '钢城区', + 371302: '兰山区', + 371311: '罗庄区', + 371312: '河东区', + 371321: '沂南县', + 371322: '郯城县', + 371323: '沂水县', + 371324: '兰陵县', + 371325: '费县', + 371326: '平邑县', + 371327: '莒南县', + 371328: '蒙阴县', + 371329: '临沭县', + 371402: '德城区', + 371403: '陵城区', + 371422: '宁津县', + 371423: '庆云县', + 371424: '临邑县', + 371425: '齐河县', + 371426: '平原县', + 371427: '夏津县', + 371428: '武城县', + 371481: '乐陵市', + 371482: '禹城市', + 371502: '东昌府区', + 371521: '阳谷县', + 371522: '莘县', + 371523: '茌平县', + 371524: '东阿县', + 371525: '冠县', + 371526: '高唐县', + 371581: '临清市', + 371602: '滨城区', + 371603: '沾化区', + 371621: '惠民县', + 371622: '阳信县', + 371623: '无棣县', + 371625: '博兴县', + 371626: '邹平县', + 371702: '牡丹区', + 371703: '定陶区', + 371721: '曹县', + 371722: '单县', + 371723: '成武县', + 371724: '巨野县', + 371725: '郓城县', + 371726: '鄄城县', + 371728: '东明县', + 410102: '中原区', + 410103: '二七区', + 410104: '管城回族区', + 410105: '金水区', + 410106: '上街区', + 410108: '惠济区', + 410122: '中牟县', + 410181: '巩义市', + 410182: '荥阳市', + 410183: '新密市', + 410184: '新郑市', + 410185: '登封市', + 410190: '高新技术开发区', + 410191: '经济技术开发区', + 410202: '龙亭区', + 410203: '顺河回族区', + 410204: '鼓楼区', + 410205: '禹王台区', + 410212: '祥符区', + 410221: '杞县', + 410222: '通许县', + 410223: '尉氏县', + 410225: '兰考县', + 410302: '老城区', + 410303: '西工区', + 410304: '瀍河回族区', + 410305: '涧西区', + 410306: '吉利区', + 410311: '洛龙区', + 410322: '孟津县', + 410323: '新安县', + 410324: '栾川县', + 410325: '嵩县', + 410326: '汝阳县', + 410327: '宜阳县', + 410328: '洛宁县', + 410329: '伊川县', + 410381: '偃师市', + 410402: '新华区', + 410403: '卫东区', + 410404: '石龙区', + 410411: '湛河区', + 410421: '宝丰县', + 410422: '叶县', + 410423: '鲁山县', + 410425: '郏县', + 410481: '舞钢市', + 410482: '汝州市', + 410502: '文峰区', + 410503: '北关区', + 410505: '殷都区', + 410506: '龙安区', + 410522: '安阳县', + 410523: '汤阴县', + 410526: '滑县', + 410527: '内黄县', + 410581: '林州市', + 410590: '开发区', + 410602: '鹤山区', + 410603: '山城区', + 410611: '淇滨区', + 410621: '浚县', + 410622: '淇县', + 410702: '红旗区', + 410703: '卫滨区', + 410704: '凤泉区', + 410711: '牧野区', + 410721: '新乡县', + 410724: '获嘉县', + 410725: '原阳县', + 410726: '延津县', + 410727: '封丘县', + 410728: '长垣县', + 410781: '卫辉市', + 410782: '辉县市', + 410802: '解放区', + 410803: '中站区', + 410804: '马村区', + 410811: '山阳区', + 410821: '修武县', + 410822: '博爱县', + 410823: '武陟县', + 410825: '温县', + 410882: '沁阳市', + 410883: '孟州市', + 410902: '华龙区', + 410922: '清丰县', + 410923: '南乐县', + 410926: '范县', + 410927: '台前县', + 410928: '濮阳县', + 411002: '魏都区', + 411003: '建安区', + 411024: '鄢陵县', + 411025: '襄城县', + 411081: '禹州市', + 411082: '长葛市', + 411102: '源汇区', + 411103: '郾城区', + 411104: '召陵区', + 411121: '舞阳县', + 411122: '临颍县', + 411202: '湖滨区', + 411203: '陕州区', + 411221: '渑池县', + 411224: '卢氏县', + 411281: '义马市', + 411282: '灵宝市', + 411302: '宛城区', + 411303: '卧龙区', + 411321: '南召县', + 411322: '方城县', + 411323: '西峡县', + 411324: '镇平县', + 411325: '内乡县', + 411326: '淅川县', + 411327: '社旗县', + 411328: '唐河县', + 411329: '新野县', + 411330: '桐柏县', + 411381: '邓州市', + 411402: '梁园区', + 411403: '睢阳区', + 411421: '民权县', + 411422: '睢县', + 411423: '宁陵县', + 411424: '柘城县', + 411425: '虞城县', + 411426: '夏邑县', + 411481: '永城市', + 411502: '浉河区', + 411503: '平桥区', + 411521: '罗山县', + 411522: '光山县', + 411523: '新县', + 411524: '商城县', + 411525: '固始县', + 411526: '潢川县', + 411527: '淮滨县', + 411528: '息县', + 411602: '川汇区', + 411621: '扶沟县', + 411622: '西华县', + 411623: '商水县', + 411624: '沈丘县', + 411625: '郸城县', + 411626: '淮阳县', + 411627: '太康县', + 411628: '鹿邑县', + 411681: '项城市', + 411690: '经济开发区', + 411702: '驿城区', + 411721: '西平县', + 411722: '上蔡县', + 411723: '平舆县', + 411724: '正阳县', + 411725: '确山县', + 411726: '泌阳县', + 411727: '汝南县', + 411728: '遂平县', + 411729: '新蔡县', + 419001: '济源市', + 420102: '江岸区', + 420103: '江汉区', + 420104: '硚口区', + 420105: '汉阳区', + 420106: '武昌区', + 420107: '青山区', + 420111: '洪山区', + 420112: '东西湖区', + 420113: '汉南区', + 420114: '蔡甸区', + 420115: '江夏区', + 420116: '黄陂区', + 420117: '新洲区', + 420202: '黄石港区', + 420203: '西塞山区', + 420204: '下陆区', + 420205: '铁山区', + 420222: '阳新县', + 420281: '大冶市', + 420302: '茅箭区', + 420303: '张湾区', + 420304: '郧阳区', + 420322: '郧西县', + 420323: '竹山县', + 420324: '竹溪县', + 420325: '房县', + 420381: '丹江口市', + 420502: '西陵区', + 420503: '伍家岗区', + 420504: '点军区', + 420505: '猇亭区', + 420506: '夷陵区', + 420525: '远安县', + 420526: '兴山县', + 420527: '秭归县', + 420528: '长阳土家族自治县', + 420529: '五峰土家族自治县', + 420581: '宜都市', + 420582: '当阳市', + 420583: '枝江市', + 420590: '经济开发区', + 420602: '襄城区', + 420606: '樊城区', + 420607: '襄州区', + 420624: '南漳县', + 420625: '谷城县', + 420626: '保康县', + 420682: '老河口市', + 420683: '枣阳市', + 420684: '宜城市', + 420702: '梁子湖区', + 420703: '华容区', + 420704: '鄂城区', + 420802: '东宝区', + 420804: '掇刀区', + 420821: '京山县', + 420822: '沙洋县', + 420881: '钟祥市', + 420902: '孝南区', + 420921: '孝昌县', + 420922: '大悟县', + 420923: '云梦县', + 420981: '应城市', + 420982: '安陆市', + 420984: '汉川市', + 421002: '沙市区', + 421003: '荆州区', + 421022: '公安县', + 421023: '监利县', + 421024: '江陵县', + 421081: '石首市', + 421083: '洪湖市', + 421087: '松滋市', + 421102: '黄州区', + 421121: '团风县', + 421122: '红安县', + 421123: '罗田县', + 421124: '英山县', + 421125: '浠水县', + 421126: '蕲春县', + 421127: '黄梅县', + 421181: '麻城市', + 421182: '武穴市', + 421202: '咸安区', + 421221: '嘉鱼县', + 421222: '通城县', + 421223: '崇阳县', + 421224: '通山县', + 421281: '赤壁市', + 421303: '曾都区', + 421321: '随县', + 421381: '广水市', + 422801: '恩施市', + 422802: '利川市', + 422822: '建始县', + 422823: '巴东县', + 422825: '宣恩县', + 422826: '咸丰县', + 422827: '来凤县', + 422828: '鹤峰县', + 429004: '仙桃市', + 429005: '潜江市', + 429006: '天门市', + 429021: '神农架林区', + 430102: '芙蓉区', + 430103: '天心区', + 430104: '岳麓区', + 430105: '开福区', + 430111: '雨花区', + 430112: '望城区', + 430121: '长沙县', + 430181: '浏阳市', + 430182: '宁乡市', + 430202: '荷塘区', + 430203: '芦淞区', + 430204: '石峰区', + 430211: '天元区', + 430221: '株洲县', + 430223: '攸县', + 430224: '茶陵县', + 430225: '炎陵县', + 430281: '醴陵市', + 430302: '雨湖区', + 430304: '岳塘区', + 430321: '湘潭县', + 430381: '湘乡市', + 430382: '韶山市', + 430405: '珠晖区', + 430406: '雁峰区', + 430407: '石鼓区', + 430408: '蒸湘区', + 430412: '南岳区', + 430421: '衡阳县', + 430422: '衡南县', + 430423: '衡山县', + 430424: '衡东县', + 430426: '祁东县', + 430481: '耒阳市', + 430482: '常宁市', + 430502: '双清区', + 430503: '大祥区', + 430511: '北塔区', + 430521: '邵东县', + 430522: '新邵县', + 430523: '邵阳县', + 430524: '隆回县', + 430525: '洞口县', + 430527: '绥宁县', + 430528: '新宁县', + 430529: '城步苗族自治县', + 430581: '武冈市', + 430602: '岳阳楼区', + 430603: '云溪区', + 430611: '君山区', + 430621: '岳阳县', + 430623: '华容县', + 430624: '湘阴县', + 430626: '平江县', + 430681: '汨罗市', + 430682: '临湘市', + 430702: '武陵区', + 430703: '鼎城区', + 430721: '安乡县', + 430722: '汉寿县', + 430723: '澧县', + 430724: '临澧县', + 430725: '桃源县', + 430726: '石门县', + 430781: '津市市', + 430802: '永定区', + 430811: '武陵源区', + 430821: '慈利县', + 430822: '桑植县', + 430902: '资阳区', + 430903: '赫山区', + 430921: '南县', + 430922: '桃江县', + 430923: '安化县', + 430981: '沅江市', + 431002: '北湖区', + 431003: '苏仙区', + 431021: '桂阳县', + 431022: '宜章县', + 431023: '永兴县', + 431024: '嘉禾县', + 431025: '临武县', + 431026: '汝城县', + 431027: '桂东县', + 431028: '安仁县', + 431081: '资兴市', + 431102: '零陵区', + 431103: '冷水滩区', + 431121: '祁阳县', + 431122: '东安县', + 431123: '双牌县', + 431124: '道县', + 431125: '江永县', + 431126: '宁远县', + 431127: '蓝山县', + 431128: '新田县', + 431129: '江华瑶族自治县', + 431202: '鹤城区', + 431221: '中方县', + 431222: '沅陵县', + 431223: '辰溪县', + 431224: '溆浦县', + 431225: '会同县', + 431226: '麻阳苗族自治县', + 431227: '新晃侗族自治县', + 431228: '芷江侗族自治县', + 431229: '靖州苗族侗族自治县', + 431230: '通道侗族自治县', + 431281: '洪江市', + 431302: '娄星区', + 431321: '双峰县', + 431322: '新化县', + 431381: '冷水江市', + 431382: '涟源市', + 433101: '吉首市', + 433122: '泸溪县', + 433123: '凤凰县', + 433124: '花垣县', + 433125: '保靖县', + 433126: '古丈县', + 433127: '永顺县', + 433130: '龙山县', + 440103: '荔湾区', + 440104: '越秀区', + 440105: '海珠区', + 440106: '天河区', + 440111: '白云区', + 440112: '黄埔区', + 440113: '番禺区', + 440114: '花都区', + 440115: '南沙区', + 440117: '从化区', + 440118: '增城区', + 440203: '武江区', + 440204: '浈江区', + 440205: '曲江区', + 440222: '始兴县', + 440224: '仁化县', + 440229: '翁源县', + 440232: '乳源瑶族自治县', + 440233: '新丰县', + 440281: '乐昌市', + 440282: '南雄市', + 440303: '罗湖区', + 440304: '福田区', + 440305: '南山区', + 440306: '宝安区', + 440307: '龙岗区', + 440308: '盐田区', + 440309: '龙华区', + 440310: '坪山区', + 440402: '香洲区', + 440403: '斗门区', + 440404: '金湾区', + 440507: '龙湖区', + 440511: '金平区', + 440512: '濠江区', + 440513: '潮阳区', + 440514: '潮南区', + 440515: '澄海区', + 440523: '南澳县', + 440604: '禅城区', + 440605: '南海区', + 440606: '顺德区', + 440607: '三水区', + 440608: '高明区', + 440703: '蓬江区', + 440704: '江海区', + 440705: '新会区', + 440781: '台山市', + 440783: '开平市', + 440784: '鹤山市', + 440785: '恩平市', + 440802: '赤坎区', + 440803: '霞山区', + 440804: '坡头区', + 440811: '麻章区', + 440823: '遂溪县', + 440825: '徐闻县', + 440881: '廉江市', + 440882: '雷州市', + 440883: '吴川市', + 440890: '经济技术开发区', + 440902: '茂南区', + 440904: '电白区', + 440981: '高州市', + 440982: '化州市', + 440983: '信宜市', + 441202: '端州区', + 441203: '鼎湖区', + 441204: '高要区', + 441223: '广宁县', + 441224: '怀集县', + 441225: '封开县', + 441226: '德庆县', + 441284: '四会市', + 441302: '惠城区', + 441303: '惠阳区', + 441322: '博罗县', + 441323: '惠东县', + 441324: '龙门县', + 441402: '梅江区', + 441403: '梅县区', + 441422: '大埔县', + 441423: '丰顺县', + 441424: '五华县', + 441426: '平远县', + 441427: '蕉岭县', + 441481: '兴宁市', + 441502: '城区', + 441521: '海丰县', + 441523: '陆河县', + 441581: '陆丰市', + 441602: '源城区', + 441621: '紫金县', + 441622: '龙川县', + 441623: '连平县', + 441624: '和平县', + 441625: '东源县', + 441702: '江城区', + 441704: '阳东区', + 441721: '阳西县', + 441781: '阳春市', + 441802: '清城区', + 441803: '清新区', + 441821: '佛冈县', + 441823: '阳山县', + 441825: '连山壮族瑶族自治县', + 441826: '连南瑶族自治县', + 441881: '英德市', + 441882: '连州市', + 441901: '中堂镇', + 441903: '南城区', + 441904: '长安镇', + 441905: '东坑镇', + 441906: '樟木头镇', + 441907: '莞城区', + 441908: '石龙镇', + 441909: '桥头镇', + 441910: '万江区', + 441911: '麻涌镇', + 441912: '虎门镇', + 441913: '谢岗镇', + 441914: '石碣镇', + 441915: '茶山镇', + 441916: '东城区', + 441917: '洪梅镇', + 441918: '道滘镇', + 441919: '高埗镇', + 441920: '企石镇', + 441921: '凤岗镇', + 441922: '大岭山镇', + 441923: '松山湖', + 441924: '清溪镇', + 441925: '望牛墩镇', + 441926: '厚街镇', + 441927: '常平镇', + 441928: '寮步镇', + 441929: '石排镇', + 441930: '横沥镇', + 441931: '塘厦镇', + 441932: '黄江镇', + 441933: '大朗镇', + 441990: '沙田镇', + 442001: '南头镇', + 442002: '神湾镇', + 442003: '东凤镇', + 442004: '五桂山镇', + 442005: '黄圃镇', + 442006: '小榄镇', + 442007: '石岐区街道', + 442008: '横栏镇', + 442009: '三角镇', + 442010: '三乡镇', + 442011: '港口镇', + 442012: '沙溪镇', + 442013: '板芙镇', + 442014: '沙朗镇', + 442015: '东升镇', + 442016: '阜沙镇', + 442017: '民众镇', + 442018: '东区街道', + 442019: '火炬开发区', + 442020: '西区街道', + 442021: '南区街道', + 442022: '古镇', + 442023: '坦洲镇', + 442024: '大涌镇', + 442025: '南朗镇', + 445102: '湘桥区', + 445103: '潮安区', + 445122: '饶平县', + 445202: '榕城区', + 445203: '揭东区', + 445222: '揭西县', + 445224: '惠来县', + 445281: '普宁市', + 445302: '云城区', + 445303: '云安区', + 445321: '新兴县', + 445322: '郁南县', + 445381: '罗定市', + 450102: '兴宁区', + 450103: '青秀区', + 450105: '江南区', + 450107: '西乡塘区', + 450108: '良庆区', + 450109: '邕宁区', + 450110: '武鸣区', + 450123: '隆安县', + 450124: '马山县', + 450125: '上林县', + 450126: '宾阳县', + 450127: '横县', + 450202: '城中区', + 450203: '鱼峰区', + 450204: '柳南区', + 450205: '柳北区', + 450206: '柳江区', + 450222: '柳城县', + 450223: '鹿寨县', + 450224: '融安县', + 450225: '融水苗族自治县', + 450226: '三江侗族自治县', + 450302: '秀峰区', + 450303: '叠彩区', + 450304: '象山区', + 450305: '七星区', + 450311: '雁山区', + 450312: '临桂区', + 450321: '阳朔县', + 450323: '灵川县', + 450324: '全州县', + 450325: '兴安县', + 450326: '永福县', + 450327: '灌阳县', + 450328: '龙胜各族自治县', + 450329: '资源县', + 450330: '平乐县', + 450331: '荔浦县', + 450332: '恭城瑶族自治县', + 450403: '万秀区', + 450405: '长洲区', + 450406: '龙圩区', + 450421: '苍梧县', + 450422: '藤县', + 450423: '蒙山县', + 450481: '岑溪市', + 450502: '海城区', + 450503: '银海区', + 450512: '铁山港区', + 450521: '合浦县', + 450602: '港口区', + 450603: '防城区', + 450621: '上思县', + 450681: '东兴市', + 450702: '钦南区', + 450703: '钦北区', + 450721: '灵山县', + 450722: '浦北县', + 450802: '港北区', + 450803: '港南区', + 450804: '覃塘区', + 450821: '平南县', + 450881: '桂平市', + 450902: '玉州区', + 450903: '福绵区', + 450921: '容县', + 450922: '陆川县', + 450923: '博白县', + 450924: '兴业县', + 450981: '北流市', + 451002: '右江区', + 451021: '田阳县', + 451022: '田东县', + 451023: '平果县', + 451024: '德保县', + 451026: '那坡县', + 451027: '凌云县', + 451028: '乐业县', + 451029: '田林县', + 451030: '西林县', + 451031: '隆林各族自治县', + 451081: '靖西市', + 451102: '八步区', + 451103: '平桂区', + 451121: '昭平县', + 451122: '钟山县', + 451123: '富川瑶族自治县', + 451202: '金城江区', + 451203: '宜州区', + 451221: '南丹县', + 451222: '天峨县', + 451223: '凤山县', + 451224: '东兰县', + 451225: '罗城仫佬族自治县', + 451226: '环江毛南族自治县', + 451227: '巴马瑶族自治县', + 451228: '都安瑶族自治县', + 451229: '大化瑶族自治县', + 451302: '兴宾区', + 451321: '忻城县', + 451322: '象州县', + 451323: '武宣县', + 451324: '金秀瑶族自治县', + 451381: '合山市', + 451402: '江州区', + 451421: '扶绥县', + 451422: '宁明县', + 451423: '龙州县', + 451424: '大新县', + 451425: '天等县', + 451481: '凭祥市', + 460105: '秀英区', + 460106: '龙华区', + 460107: '琼山区', + 460108: '美兰区', + 460202: '海棠区', + 460203: '吉阳区', + 460204: '天涯区', + 460205: '崖州区', + 460321: '西沙群岛', + 460322: '南沙群岛', + 460323: '中沙群岛的岛礁及其海域', + 460401: '那大镇', + 460402: '和庆镇', + 460403: '南丰镇', + 460404: '大成镇', + 460405: '雅星镇', + 460406: '兰洋镇', + 460407: '光村镇', + 460408: '木棠镇', + 460409: '海头镇', + 460410: '峨蔓镇', + 460411: '王五镇', + 460412: '白马井镇', + 460413: '中和镇', + 460414: '排浦镇', + 460415: '东成镇', + 460416: '新州镇', + 469001: '五指山市', + 469002: '琼海市', + 469005: '文昌市', + 469006: '万宁市', + 469007: '东方市', + 469021: '定安县', + 469022: '屯昌县', + 469023: '澄迈县', + 469024: '临高县', + 469025: '白沙黎族自治县', + 469026: '昌江黎族自治县', + 469027: '乐东黎族自治县', + 469028: '陵水黎族自治县', + 469029: '保亭黎族苗族自治县', + 469030: '琼中黎族苗族自治县', + 500101: '万州区', + 500102: '涪陵区', + 500103: '渝中区', + 500104: '大渡口区', + 500105: '江北区', + 500106: '沙坪坝区', + 500107: '九龙坡区', + 500108: '南岸区', + 500109: '北碚区', + 500110: '綦江区', + 500111: '大足区', + 500112: '渝北区', + 500113: '巴南区', + 500114: '黔江区', + 500115: '长寿区', + 500116: '江津区', + 500117: '合川区', + 500118: '永川区', + 500119: '南川区', + 500120: '璧山区', + 500151: '铜梁区', + 500152: '潼南区', + 500153: '荣昌区', + 500154: '开州区', + 500155: '梁平区', + 500156: '武隆区', + 500229: '城口县', + 500230: '丰都县', + 500231: '垫江县', + 500233: '忠县', + 500235: '云阳县', + 500236: '奉节县', + 500237: '巫山县', + 500238: '巫溪县', + 500240: '石柱土家族自治县', + 500241: '秀山土家族苗族自治县', + 500242: '酉阳土家族苗族自治县', + 500243: '彭水苗族土家族自治县', + 510104: '锦江区', + 510105: '青羊区', + 510106: '金牛区', + 510107: '武侯区', + 510108: '成华区', + 510112: '龙泉驿区', + 510113: '青白江区', + 510114: '新都区', + 510115: '温江区', + 510116: '双流区', + 510117: '郫都区', + 510121: '金堂县', + 510129: '大邑县', + 510131: '蒲江县', + 510132: '新津县', + 510181: '都江堰市', + 510182: '彭州市', + 510183: '邛崃市', + 510184: '崇州市', + 510185: '简阳市', + 510191: '高新区', + 510302: '自流井区', + 510303: '贡井区', + 510304: '大安区', + 510311: '沿滩区', + 510321: '荣县', + 510322: '富顺县', + 510402: '东区', + 510403: '西区', + 510411: '仁和区', + 510421: '米易县', + 510422: '盐边县', + 510502: '江阳区', + 510503: '纳溪区', + 510504: '龙马潭区', + 510521: '泸县', + 510522: '合江县', + 510524: '叙永县', + 510525: '古蔺县', + 510603: '旌阳区', + 510604: '罗江区', + 510623: '中江县', + 510681: '广汉市', + 510682: '什邡市', + 510683: '绵竹市', + 510703: '涪城区', + 510704: '游仙区', + 510705: '安州区', + 510722: '三台县', + 510723: '盐亭县', + 510725: '梓潼县', + 510726: '北川羌族自治县', + 510727: '平武县', + 510781: '江油市', + 510791: '高新区', + 510802: '利州区', + 510811: '昭化区', + 510812: '朝天区', + 510821: '旺苍县', + 510822: '青川县', + 510823: '剑阁县', + 510824: '苍溪县', + 510903: '船山区', + 510904: '安居区', + 510921: '蓬溪县', + 510922: '射洪县', + 510923: '大英县', + 511002: '市中区', + 511011: '东兴区', + 511024: '威远县', + 511025: '资中县', + 511083: '隆昌市', + 511102: '市中区', + 511111: '沙湾区', + 511112: '五通桥区', + 511113: '金口河区', + 511123: '犍为县', + 511124: '井研县', + 511126: '夹江县', + 511129: '沐川县', + 511132: '峨边彝族自治县', + 511133: '马边彝族自治县', + 511181: '峨眉山市', + 511302: '顺庆区', + 511303: '高坪区', + 511304: '嘉陵区', + 511321: '南部县', + 511322: '营山县', + 511323: '蓬安县', + 511324: '仪陇县', + 511325: '西充县', + 511381: '阆中市', + 511402: '东坡区', + 511403: '彭山区', + 511421: '仁寿县', + 511423: '洪雅县', + 511424: '丹棱县', + 511425: '青神县', + 511502: '翠屏区', + 511503: '南溪区', + 511521: '宜宾县', + 511523: '江安县', + 511524: '长宁县', + 511525: '高县', + 511526: '珙县', + 511527: '筠连县', + 511528: '兴文县', + 511529: '屏山县', + 511602: '广安区', + 511603: '前锋区', + 511621: '岳池县', + 511622: '武胜县', + 511623: '邻水县', + 511681: '华蓥市', + 511702: '通川区', + 511703: '达川区', + 511722: '宣汉县', + 511723: '开江县', + 511724: '大竹县', + 511725: '渠县', + 511781: '万源市', + 511802: '雨城区', + 511803: '名山区', + 511822: '荥经县', + 511823: '汉源县', + 511824: '石棉县', + 511825: '天全县', + 511826: '芦山县', + 511827: '宝兴县', + 511902: '巴州区', + 511903: '恩阳区', + 511921: '通江县', + 511922: '南江县', + 511923: '平昌县', + 512002: '雁江区', + 512021: '安岳县', + 512022: '乐至县', + 513201: '马尔康市', + 513221: '汶川县', + 513222: '理县', + 513223: '茂县', + 513224: '松潘县', + 513225: '九寨沟县', + 513226: '金川县', + 513227: '小金县', + 513228: '黑水县', + 513230: '壤塘县', + 513231: '阿坝县', + 513232: '若尔盖县', + 513233: '红原县', + 513301: '康定市', + 513322: '泸定县', + 513323: '丹巴县', + 513324: '九龙县', + 513325: '雅江县', + 513326: '道孚县', + 513327: '炉霍县', + 513328: '甘孜县', + 513329: '新龙县', + 513330: '德格县', + 513331: '白玉县', + 513332: '石渠县', + 513333: '色达县', + 513334: '理塘县', + 513335: '巴塘县', + 513336: '乡城县', + 513337: '稻城县', + 513338: '得荣县', + 513401: '西昌市', + 513422: '木里藏族自治县', + 513423: '盐源县', + 513424: '德昌县', + 513425: '会理县', + 513426: '会东县', + 513427: '宁南县', + 513428: '普格县', + 513429: '布拖县', + 513430: '金阳县', + 513431: '昭觉县', + 513432: '喜德县', + 513433: '冕宁县', + 513434: '越西县', + 513435: '甘洛县', + 513436: '美姑县', + 513437: '雷波县', + 520102: '南明区', + 520103: '云岩区', + 520111: '花溪区', + 520112: '乌当区', + 520113: '白云区', + 520115: '观山湖区', + 520121: '开阳县', + 520122: '息烽县', + 520123: '修文县', + 520181: '清镇市', + 520201: '钟山区', + 520203: '六枝特区', + 520221: '水城县', + 520281: '盘州市', + 520302: '红花岗区', + 520303: '汇川区', + 520304: '播州区', + 520322: '桐梓县', + 520323: '绥阳县', + 520324: '正安县', + 520325: '道真仡佬族苗族自治县', + 520326: '务川仡佬族苗族自治县', + 520327: '凤冈县', + 520328: '湄潭县', + 520329: '余庆县', + 520330: '习水县', + 520381: '赤水市', + 520382: '仁怀市', + 520402: '西秀区', + 520403: '平坝区', + 520422: '普定县', + 520423: '镇宁布依族苗族自治县', + 520424: '关岭布依族苗族自治县', + 520425: '紫云苗族布依族自治县', + 520502: '七星关区', + 520521: '大方县', + 520522: '黔西县', + 520523: '金沙县', + 520524: '织金县', + 520525: '纳雍县', + 520526: '威宁彝族回族苗族自治县', + 520527: '赫章县', + 520602: '碧江区', + 520603: '万山区', + 520621: '江口县', + 520622: '玉屏侗族自治县', + 520623: '石阡县', + 520624: '思南县', + 520625: '印江土家族苗族自治县', + 520626: '德江县', + 520627: '沿河土家族自治县', + 520628: '松桃苗族自治县', + 522301: '兴义市', + 522322: '兴仁县', + 522323: '普安县', + 522324: '晴隆县', + 522325: '贞丰县', + 522326: '望谟县', + 522327: '册亨县', + 522328: '安龙县', + 522601: '凯里市', + 522622: '黄平县', + 522623: '施秉县', + 522624: '三穗县', + 522625: '镇远县', + 522626: '岑巩县', + 522627: '天柱县', + 522628: '锦屏县', + 522629: '剑河县', + 522630: '台江县', + 522631: '黎平县', + 522632: '榕江县', + 522633: '从江县', + 522634: '雷山县', + 522635: '麻江县', + 522636: '丹寨县', + 522701: '都匀市', + 522702: '福泉市', + 522722: '荔波县', + 522723: '贵定县', + 522725: '瓮安县', + 522726: '独山县', + 522727: '平塘县', + 522728: '罗甸县', + 522729: '长顺县', + 522730: '龙里县', + 522731: '惠水县', + 522732: '三都水族自治县', + 530102: '五华区', + 530103: '盘龙区', + 530111: '官渡区', + 530112: '西山区', + 530113: '东川区', + 530114: '呈贡区', + 530115: '晋宁区', + 530124: '富民县', + 530125: '宜良县', + 530126: '石林彝族自治县', + 530127: '嵩明县', + 530128: '禄劝彝族苗族自治县', + 530129: '寻甸回族彝族自治县', + 530181: '安宁市', + 530302: '麒麟区', + 530303: '沾益区', + 530321: '马龙县', + 530322: '陆良县', + 530323: '师宗县', + 530324: '罗平县', + 530325: '富源县', + 530326: '会泽县', + 530381: '宣威市', + 530402: '红塔区', + 530403: '江川区', + 530422: '澄江县', + 530423: '通海县', + 530424: '华宁县', + 530425: '易门县', + 530426: '峨山彝族自治县', + 530427: '新平彝族傣族自治县', + 530428: '元江哈尼族彝族傣族自治县', + 530502: '隆阳区', + 530521: '施甸县', + 530523: '龙陵县', + 530524: '昌宁县', + 530581: '腾冲市', + 530602: '昭阳区', + 530621: '鲁甸县', + 530622: '巧家县', + 530623: '盐津县', + 530624: '大关县', + 530625: '永善县', + 530626: '绥江县', + 530627: '镇雄县', + 530628: '彝良县', + 530629: '威信县', + 530630: '水富县', + 530702: '古城区', + 530721: '玉龙纳西族自治县', + 530722: '永胜县', + 530723: '华坪县', + 530724: '宁蒗彝族自治县', + 530802: '思茅区', + 530821: '宁洱哈尼族彝族自治县', + 530822: '墨江哈尼族自治县', + 530823: '景东彝族自治县', + 530824: '景谷傣族彝族自治县', + 530825: '镇沅彝族哈尼族拉祜族自治县', + 530826: '江城哈尼族彝族自治县', + 530827: '孟连傣族拉祜族佤族自治县', + 530828: '澜沧拉祜族自治县', + 530829: '西盟佤族自治县', + 530902: '临翔区', + 530921: '凤庆县', + 530922: '云县', + 530923: '永德县', + 530924: '镇康县', + 530925: '双江拉祜族佤族布朗族傣族自治县', + 530926: '耿马傣族佤族自治县', + 530927: '沧源佤族自治县', + 532301: '楚雄市', + 532322: '双柏县', + 532323: '牟定县', + 532324: '南华县', + 532325: '姚安县', + 532326: '大姚县', + 532327: '永仁县', + 532328: '元谋县', + 532329: '武定县', + 532331: '禄丰县', + 532501: '个旧市', + 532502: '开远市', + 532503: '蒙自市', + 532504: '弥勒市', + 532523: '屏边苗族自治县', + 532524: '建水县', + 532525: '石屏县', + 532527: '泸西县', + 532528: '元阳县', + 532529: '红河县', + 532530: '金平苗族瑶族傣族自治县', + 532531: '绿春县', + 532532: '河口瑶族自治县', + 532601: '文山市', + 532622: '砚山县', + 532623: '西畴县', + 532624: '麻栗坡县', + 532625: '马关县', + 532626: '丘北县', + 532627: '广南县', + 532628: '富宁县', + 532801: '景洪市', + 532822: '勐海县', + 532823: '勐腊县', + 532901: '大理市', + 532922: '漾濞彝族自治县', + 532923: '祥云县', + 532924: '宾川县', + 532925: '弥渡县', + 532926: '南涧彝族自治县', + 532927: '巍山彝族回族自治县', + 532928: '永平县', + 532929: '云龙县', + 532930: '洱源县', + 532931: '剑川县', + 532932: '鹤庆县', + 533102: '瑞丽市', + 533103: '芒市', + 533122: '梁河县', + 533123: '盈江县', + 533124: '陇川县', + 533301: '泸水市', + 533323: '福贡县', + 533324: '贡山独龙族怒族自治县', + 533325: '兰坪白族普米族自治县', + 533401: '香格里拉市', + 533422: '德钦县', + 533423: '维西傈僳族自治县', + 540102: '城关区', + 540103: '堆龙德庆区', + 540104: '达孜区', + 540121: '林周县', + 540122: '当雄县', + 540123: '尼木县', + 540124: '曲水县', + 540127: '墨竹工卡县', + 540202: '桑珠孜区', + 540221: '南木林县', + 540222: '江孜县', + 540223: '定日县', + 540224: '萨迦县', + 540225: '拉孜县', + 540226: '昂仁县', + 540227: '谢通门县', + 540228: '白朗县', + 540229: '仁布县', + 540230: '康马县', + 540231: '定结县', + 540232: '仲巴县', + 540233: '亚东县', + 540234: '吉隆县', + 540235: '聂拉木县', + 540236: '萨嘎县', + 540237: '岗巴县', + 540302: '卡若区', + 540321: '江达县', + 540322: '贡觉县', + 540323: '类乌齐县', + 540324: '丁青县', + 540325: '察雅县', + 540326: '八宿县', + 540327: '左贡县', + 540328: '芒康县', + 540329: '洛隆县', + 540330: '边坝县', + 540402: '巴宜区', + 540421: '工布江达县', + 540422: '米林县', + 540423: '墨脱县', + 540424: '波密县', + 540425: '察隅县', + 540426: '朗县', + 540502: '乃东区', + 540521: '扎囊县', + 540522: '贡嘎县', + 540523: '桑日县', + 540524: '琼结县', + 540525: '曲松县', + 540526: '措美县', + 540527: '洛扎县', + 540528: '加查县', + 540529: '隆子县', + 540530: '错那县', + 540531: '浪卡子县', + 540602: '色尼区', + 542421: '那曲县', + 542422: '嘉黎县', + 542423: '比如县', + 542424: '聂荣县', + 542425: '安多县', + 542426: '申扎县', + 542427: '索县', + 542428: '班戈县', + 542429: '巴青县', + 542430: '尼玛县', + 542431: '双湖县', + 542521: '普兰县', + 542522: '札达县', + 542523: '噶尔县', + 542524: '日土县', + 542525: '革吉县', + 542526: '改则县', + 542527: '措勤县', + 610102: '新城区', + 610103: '碑林区', + 610104: '莲湖区', + 610111: '灞桥区', + 610112: '未央区', + 610113: '雁塔区', + 610114: '阎良区', + 610115: '临潼区', + 610116: '长安区', + 610117: '高陵区', + 610118: '鄠邑区', + 610122: '蓝田县', + 610124: '周至县', + 610202: '王益区', + 610203: '印台区', + 610204: '耀州区', + 610222: '宜君县', + 610302: '渭滨区', + 610303: '金台区', + 610304: '陈仓区', + 610322: '凤翔县', + 610323: '岐山县', + 610324: '扶风县', + 610326: '眉县', + 610327: '陇县', + 610328: '千阳县', + 610329: '麟游县', + 610330: '凤县', + 610331: '太白县', + 610402: '秦都区', + 610403: '杨陵区', + 610404: '渭城区', + 610422: '三原县', + 610423: '泾阳县', + 610424: '乾县', + 610425: '礼泉县', + 610426: '永寿县', + 610427: '彬县', + 610428: '长武县', + 610429: '旬邑县', + 610430: '淳化县', + 610431: '武功县', + 610481: '兴平市', + 610502: '临渭区', + 610503: '华州区', + 610522: '潼关县', + 610523: '大荔县', + 610524: '合阳县', + 610525: '澄城县', + 610526: '蒲城县', + 610527: '白水县', + 610528: '富平县', + 610581: '韩城市', + 610582: '华阴市', + 610602: '宝塔区', + 610603: '安塞区', + 610621: '延长县', + 610622: '延川县', + 610623: '子长县', + 610625: '志丹县', + 610626: '吴起县', + 610627: '甘泉县', + 610628: '富县', + 610629: '洛川县', + 610630: '宜川县', + 610631: '黄龙县', + 610632: '黄陵县', + 610702: '汉台区', + 610703: '南郑区', + 610722: '城固县', + 610723: '洋县', + 610724: '西乡县', + 610725: '勉县', + 610726: '宁强县', + 610727: '略阳县', + 610728: '镇巴县', + 610729: '留坝县', + 610730: '佛坪县', + 610802: '榆阳区', + 610803: '横山区', + 610822: '府谷县', + 610824: '靖边县', + 610825: '定边县', + 610826: '绥德县', + 610827: '米脂县', + 610828: '佳县', + 610829: '吴堡县', + 610830: '清涧县', + 610831: '子洲县', + 610881: '神木市', + 610902: '汉滨区', + 610921: '汉阴县', + 610922: '石泉县', + 610923: '宁陕县', + 610924: '紫阳县', + 610925: '岚皋县', + 610926: '平利县', + 610927: '镇坪县', + 610928: '旬阳县', + 610929: '白河县', + 611002: '商州区', + 611021: '洛南县', + 611022: '丹凤县', + 611023: '商南县', + 611024: '山阳县', + 611025: '镇安县', + 611026: '柞水县', + 620102: '城关区', + 620103: '七里河区', + 620104: '西固区', + 620105: '安宁区', + 620111: '红古区', + 620121: '永登县', + 620122: '皋兰县', + 620123: '榆中县', + 620201: '市辖区', + 620290: '雄关区', + 620291: '长城区', + 620292: '镜铁区', + 620293: '新城镇', + 620294: '峪泉镇', + 620295: '文殊镇', + 620302: '金川区', + 620321: '永昌县', + 620402: '白银区', + 620403: '平川区', + 620421: '靖远县', + 620422: '会宁县', + 620423: '景泰县', + 620502: '秦州区', + 620503: '麦积区', + 620521: '清水县', + 620522: '秦安县', + 620523: '甘谷县', + 620524: '武山县', + 620525: '张家川回族自治县', + 620602: '凉州区', + 620621: '民勤县', + 620622: '古浪县', + 620623: '天祝藏族自治县', + 620702: '甘州区', + 620721: '肃南裕固族自治县', + 620722: '民乐县', + 620723: '临泽县', + 620724: '高台县', + 620725: '山丹县', + 620802: '崆峒区', + 620821: '泾川县', + 620822: '灵台县', + 620823: '崇信县', + 620824: '华亭县', + 620825: '庄浪县', + 620826: '静宁县', + 620902: '肃州区', + 620921: '金塔县', + 620922: '瓜州县', + 620923: '肃北蒙古族自治县', + 620924: '阿克塞哈萨克族自治县', + 620981: '玉门市', + 620982: '敦煌市', + 621002: '西峰区', + 621021: '庆城县', + 621022: '环县', + 621023: '华池县', + 621024: '合水县', + 621025: '正宁县', + 621026: '宁县', + 621027: '镇原县', + 621102: '安定区', + 621121: '通渭县', + 621122: '陇西县', + 621123: '渭源县', + 621124: '临洮县', + 621125: '漳县', + 621126: '岷县', + 621202: '武都区', + 621221: '成县', + 621222: '文县', + 621223: '宕昌县', + 621224: '康县', + 621225: '西和县', + 621226: '礼县', + 621227: '徽县', + 621228: '两当县', + 622901: '临夏市', + 622921: '临夏县', + 622922: '康乐县', + 622923: '永靖县', + 622924: '广河县', + 622925: '和政县', + 622926: '东乡族自治县', + 622927: '积石山保安族东乡族撒拉族自治县', + 623001: '合作市', + 623021: '临潭县', + 623022: '卓尼县', + 623023: '舟曲县', + 623024: '迭部县', + 623025: '玛曲县', + 623026: '碌曲县', + 623027: '夏河县', + 630102: '城东区', + 630103: '城中区', + 630104: '城西区', + 630105: '城北区', + 630121: '大通回族土族自治县', + 630122: '湟中县', + 630123: '湟源县', + 630202: '乐都区', + 630203: '平安区', + 630222: '民和回族土族自治县', + 630223: '互助土族自治县', + 630224: '化隆回族自治县', + 630225: '循化撒拉族自治县', + 632221: '门源回族自治县', + 632222: '祁连县', + 632223: '海晏县', + 632224: '刚察县', + 632321: '同仁县', + 632322: '尖扎县', + 632323: '泽库县', + 632324: '河南蒙古族自治县', + 632521: '共和县', + 632522: '同德县', + 632523: '贵德县', + 632524: '兴海县', + 632525: '贵南县', + 632621: '玛沁县', + 632622: '班玛县', + 632623: '甘德县', + 632624: '达日县', + 632625: '久治县', + 632626: '玛多县', + 632701: '玉树市', + 632722: '杂多县', + 632723: '称多县', + 632724: '治多县', + 632725: '囊谦县', + 632726: '曲麻莱县', + 632801: '格尔木市', + 632802: '德令哈市', + 632821: '乌兰县', + 632822: '都兰县', + 632823: '天峻县', + 640104: '兴庆区', + 640105: '西夏区', + 640106: '金凤区', + 640121: '永宁县', + 640122: '贺兰县', + 640181: '灵武市', + 640202: '大武口区', + 640205: '惠农区', + 640221: '平罗县', + 640302: '利通区', + 640303: '红寺堡区', + 640323: '盐池县', + 640324: '同心县', + 640381: '青铜峡市', + 640402: '原州区', + 640422: '西吉县', + 640423: '隆德县', + 640424: '泾源县', + 640425: '彭阳县', + 640502: '沙坡头区', + 640521: '中宁县', + 640522: '海原县', + 650102: '天山区', + 650103: '沙依巴克区', + 650104: '新市区', + 650105: '水磨沟区', + 650106: '头屯河区', + 650107: '达坂城区', + 650109: '米东区', + 650121: '乌鲁木齐县', + 650202: '独山子区', + 650203: '克拉玛依区', + 650204: '白碱滩区', + 650205: '乌尔禾区', + 650402: '高昌区', + 650421: '鄯善县', + 650422: '托克逊县', + 650502: '伊州区', + 650521: '巴里坤哈萨克自治县', + 650522: '伊吾县', + 652301: '昌吉市', + 652302: '阜康市', + 652323: '呼图壁县', + 652324: '玛纳斯县', + 652325: '奇台县', + 652327: '吉木萨尔县', + 652328: '木垒哈萨克自治县', + 652701: '博乐市', + 652702: '阿拉山口市', + 652722: '精河县', + 652723: '温泉县', + 652801: '库尔勒市', + 652822: '轮台县', + 652823: '尉犁县', + 652824: '若羌县', + 652825: '且末县', + 652826: '焉耆回族自治县', + 652827: '和静县', + 652828: '和硕县', + 652829: '博湖县', + 652901: '阿克苏市', + 652922: '温宿县', + 652923: '库车县', + 652924: '沙雅县', + 652925: '新和县', + 652926: '拜城县', + 652927: '乌什县', + 652928: '阿瓦提县', + 652929: '柯坪县', + 653001: '阿图什市', + 653022: '阿克陶县', + 653023: '阿合奇县', + 653024: '乌恰县', + 653101: '喀什市', + 653121: '疏附县', + 653122: '疏勒县', + 653123: '英吉沙县', + 653124: '泽普县', + 653125: '莎车县', + 653126: '叶城县', + 653127: '麦盖提县', + 653128: '岳普湖县', + 653129: '伽师县', + 653130: '巴楚县', + 653131: '塔什库尔干塔吉克自治县', + 653201: '和田市', + 653221: '和田县', + 653222: '墨玉县', + 653223: '皮山县', + 653224: '洛浦县', + 653225: '策勒县', + 653226: '于田县', + 653227: '民丰县', + 654002: '伊宁市', + 654003: '奎屯市', + 654004: '霍尔果斯市', + 654021: '伊宁县', + 654022: '察布查尔锡伯自治县', + 654023: '霍城县', + 654024: '巩留县', + 654025: '新源县', + 654026: '昭苏县', + 654027: '特克斯县', + 654028: '尼勒克县', + 654201: '塔城市', + 654202: '乌苏市', + 654221: '额敏县', + 654223: '沙湾县', + 654224: '托里县', + 654225: '裕民县', + 654226: '和布克赛尔蒙古自治县', + 654301: '阿勒泰市', + 654321: '布尔津县', + 654322: '富蕴县', + 654323: '福海县', + 654324: '哈巴河县', + 654325: '青河县', + 654326: '吉木乃县', + 659001: '石河子市', + 659002: '阿拉尔市', + 659003: '图木舒克市', + 659004: '五家渠市', + 659005: '北屯市', + 659006: '铁门关市', + 659007: '双河市', + 659008: '可克达拉市', + 659009: '昆玉市', + 710101: '中正区', + 710102: '大同区', + 710103: '中山区', + 710104: '松山区', + 710105: '大安区', + 710106: '万华区', + 710107: '信义区', + 710108: '士林区', + 710109: '北投区', + 710110: '内湖区', + 710111: '南港区', + 710112: '文山区', + 710199: '其它区', + 710201: '新兴区', + 710202: '前金区', + 710203: '芩雅区', + 710204: '盐埕区', + 710205: '鼓山区', + 710206: '旗津区', + 710207: '前镇区', + 710208: '三民区', + 710209: '左营区', + 710210: '楠梓区', + 710211: '小港区', + 710241: '苓雅区', + 710242: '仁武区', + 710243: '大社区', + 710244: '冈山区', + 710245: '路竹区', + 710246: '阿莲区', + 710247: '田寮区', + 710248: '燕巢区', + 710249: '桥头区', + 710250: '梓官区', + 710251: '弥陀区', + 710252: '永安区', + 710253: '湖内区', + 710254: '凤山区', + 710255: '大寮区', + 710256: '林园区', + 710257: '鸟松区', + 710258: '大树区', + 710259: '旗山区', + 710260: '美浓区', + 710261: '六龟区', + 710262: '内门区', + 710263: '杉林区', + 710264: '甲仙区', + 710265: '桃源区', + 710266: '那玛夏区', + 710267: '茂林区', + 710268: '茄萣区', + 710299: '其它区', + 710301: '中西区', + 710302: '东区', + 710303: '南区', + 710304: '北区', + 710305: '安平区', + 710306: '安南区', + 710339: '永康区', + 710340: '归仁区', + 710341: '新化区', + 710342: '左镇区', + 710343: '玉井区', + 710344: '楠西区', + 710345: '南化区', + 710346: '仁德区', + 710347: '关庙区', + 710348: '龙崎区', + 710349: '官田区', + 710350: '麻豆区', + 710351: '佳里区', + 710352: '西港区', + 710353: '七股区', + 710354: '将军区', + 710355: '学甲区', + 710356: '北门区', + 710357: '新营区', + 710358: '后壁区', + 710359: '白河区', + 710360: '东山区', + 710361: '六甲区', + 710362: '下营区', + 710363: '柳营区', + 710364: '盐水区', + 710365: '善化区', + 710366: '大内区', + 710367: '山上区', + 710368: '新市区', + 710369: '安定区', + 710399: '其它区', + 710401: '中区', + 710402: '东区', + 710403: '南区', + 710404: '西区', + 710405: '北区', + 710406: '北屯区', + 710407: '西屯区', + 710408: '南屯区', + 710431: '太平区', + 710432: '大里区', + 710433: '雾峰区', + 710434: '乌日区', + 710435: '丰原区', + 710436: '后里区', + 710437: '石冈区', + 710438: '东势区', + 710439: '和平区', + 710440: '新社区', + 710441: '潭子区', + 710442: '大雅区', + 710443: '神冈区', + 710444: '大肚区', + 710445: '沙鹿区', + 710446: '龙井区', + 710447: '梧栖区', + 710448: '清水区', + 710449: '大甲区', + 710450: '外埔区', + 710451: '大安区', + 710499: '其它区', + 710507: '金沙镇', + 710508: '金湖镇', + 710509: '金宁乡', + 710510: '金城镇', + 710511: '烈屿乡', + 710512: '乌坵乡', + 710614: '南投市', + 710615: '中寮乡', + 710616: '草屯镇', + 710617: '国姓乡', + 710618: '埔里镇', + 710619: '仁爱乡', + 710620: '名间乡', + 710621: '集集镇', + 710622: '水里乡', + 710623: '鱼池乡', + 710624: '信义乡', + 710625: '竹山镇', + 710626: '鹿谷乡', + 710701: '仁爱区', + 710702: '信义区', + 710703: '中正区', + 710704: '中山区', + 710705: '安乐区', + 710706: '暖暖区', + 710707: '七堵区', + 710799: '其它区', + 710801: '东区', + 710802: '北区', + 710803: '香山区', + 710899: '其它区', + 710901: '东区', + 710902: '西区', + 710999: '其它区', + 711130: '万里区', + 711132: '板桥区', + 711133: '汐止区', + 711134: '深坑区', + 711136: '瑞芳区', + 711137: '平溪区', + 711138: '双溪区', + 711140: '新店区', + 711141: '坪林区', + 711142: '乌来区', + 711143: '永和区', + 711144: '中和区', + 711145: '土城区', + 711146: '三峡区', + 711147: '树林区', + 711149: '三重区', + 711150: '新庄区', + 711151: '泰山区', + 711152: '林口区', + 711154: '五股区', + 711155: '八里区', + 711156: '淡水区', + 711157: '三芝区', + 711287: '宜兰市', + 711288: '头城镇', + 711289: '礁溪乡', + 711290: '壮围乡', + 711291: '员山乡', + 711292: '罗东镇', + 711293: '三星乡', + 711294: '大同乡', + 711295: '五结乡', + 711296: '冬山乡', + 711297: '苏澳镇', + 711298: '南澳乡', + 711299: '钓鱼台', + 711387: '竹北市', + 711388: '湖口乡', + 711389: '新丰乡', + 711390: '新埔镇', + 711391: '关西镇', + 711392: '芎林乡', + 711393: '宝山乡', + 711394: '竹东镇', + 711395: '五峰乡', + 711396: '横山乡', + 711397: '尖石乡', + 711398: '北埔乡', + 711399: '峨眉乡', + 711487: '中坜市', + 711488: '平镇市', + 711489: '龙潭乡', + 711490: '杨梅市', + 711491: '新屋乡', + 711492: '观音乡', + 711493: '桃园市', + 711494: '龟山乡', + 711495: '八德市', + 711496: '大溪镇', + 711497: '复兴乡', + 711498: '大园乡', + 711499: '芦竹乡', + 711582: '竹南镇', + 711583: '头份镇', + 711584: '三湾乡', + 711585: '南庄乡', + 711586: '狮潭乡', + 711587: '后龙镇', + 711588: '通霄镇', + 711589: '苑里镇', + 711590: '苗栗市', + 711591: '造桥乡', + 711592: '头屋乡', + 711593: '公馆乡', + 711594: '大湖乡', + 711595: '泰安乡', + 711596: '铜锣乡', + 711597: '三义乡', + 711598: '西湖乡', + 711599: '卓兰镇', + 711774: '彰化市', + 711775: '芬园乡', + 711776: '花坛乡', + 711777: '秀水乡', + 711778: '鹿港镇', + 711779: '福兴乡', + 711780: '线西乡', + 711781: '和美镇', + 711782: '伸港乡', + 711783: '员林镇', + 711784: '社头乡', + 711785: '永靖乡', + 711786: '埔心乡', + 711787: '溪湖镇', + 711788: '大村乡', + 711789: '埔盐乡', + 711790: '田中镇', + 711791: '北斗镇', + 711792: '田尾乡', + 711793: '埤头乡', + 711794: '溪州乡', + 711795: '竹塘乡', + 711796: '二林镇', + 711797: '大城乡', + 711798: '芳苑乡', + 711799: '二水乡', + 711982: '番路乡', + 711983: '梅山乡', + 711984: '竹崎乡', + 711985: '阿里山乡', + 711986: '中埔乡', + 711987: '大埔乡', + 711988: '水上乡', + 711989: '鹿草乡', + 711990: '太保市', + 711991: '朴子市', + 711992: '东石乡', + 711993: '六脚乡', + 711994: '新港乡', + 711995: '民雄乡', + 711996: '大林镇', + 711997: '溪口乡', + 711998: '义竹乡', + 711999: '布袋镇', + 712180: '斗南镇', + 712181: '大埤乡', + 712182: '虎尾镇', + 712183: '土库镇', + 712184: '褒忠乡', + 712185: '东势乡', + 712186: '台西乡', + 712187: '仑背乡', + 712188: '麦寮乡', + 712189: '斗六市', + 712190: '林内乡', + 712191: '古坑乡', + 712192: '莿桐乡', + 712193: '西螺镇', + 712194: '二仑乡', + 712195: '北港镇', + 712196: '水林乡', + 712197: '口湖乡', + 712198: '四湖乡', + 712199: '元长乡', + 712467: '屏东市', + 712468: '三地门乡', + 712469: '雾台乡', + 712470: '玛家乡', + 712471: '九如乡', + 712472: '里港乡', + 712473: '高树乡', + 712474: '盐埔乡', + 712475: '长治乡', + 712476: '麟洛乡', + 712477: '竹田乡', + 712478: '内埔乡', + 712479: '万丹乡', + 712480: '潮州镇', + 712481: '泰武乡', + 712482: '来义乡', + 712483: '万峦乡', + 712484: '莰顶乡', + 712485: '新埤乡', + 712486: '南州乡', + 712487: '林边乡', + 712488: '东港镇', + 712489: '琉球乡', + 712490: '佳冬乡', + 712491: '新园乡', + 712492: '枋寮乡', + 712493: '枋山乡', + 712494: '春日乡', + 712495: '狮子乡', + 712496: '车城乡', + 712497: '牡丹乡', + 712498: '恒春镇', + 712499: '满州乡', + 712584: '台东市', + 712585: '绿岛乡', + 712586: '兰屿乡', + 712587: '延平乡', + 712588: '卑南乡', + 712589: '鹿野乡', + 712590: '关山镇', + 712591: '海端乡', + 712592: '池上乡', + 712593: '东河乡', + 712594: '成功镇', + 712595: '长滨乡', + 712596: '金峰乡', + 712597: '大武乡', + 712598: '达仁乡', + 712599: '太麻里乡', + 712686: '花莲市', + 712687: '新城乡', + 712688: '太鲁阁', + 712689: '秀林乡', + 712690: '吉安乡', + 712691: '寿丰乡', + 712692: '凤林镇', + 712693: '光复乡', + 712694: '丰滨乡', + 712695: '瑞穗乡', + 712696: '万荣乡', + 712697: '玉里镇', + 712698: '卓溪乡', + 712699: '富里乡', + 712794: '马公市', + 712795: '西屿乡', + 712796: '望安乡', + 712797: '七美乡', + 712798: '白沙乡', + 712799: '湖西乡', + 712896: '南竿乡', + 712897: '北竿乡', + 712898: '东引乡', + 712899: '莒光乡', + 810101: '中西区', + 810102: '湾仔', + 810103: '东区', + 810104: '南区', + 810201: '九龙城区', + 810202: '油尖旺区', + 810203: '深水埗区', + 810204: '黄大仙区', + 810205: '观塘区', + 810301: '北区', + 810302: '大埔区', + 810303: '沙田区', + 810304: '西贡区', + 810305: '元朗区', + 810306: '屯门区', + 810307: '荃湾区', + 810308: '葵青区', + 810309: '离岛区', + 820101: '澳门半岛', + 820201: '离岛' + } + }; + + + Class.prototype.config = { + elem: '', + data: { + province: '', + city: '', + county: '', + provinceCode: 0, + cityCode: 0, + countyCode: 0, + }, + change: function(result){} + }; + + Class.prototype.index = 0; + + Class.prototype.render = function () { + let that = this, options = that.config; + options.elem = $(options.elem); + + that.events(); + }; + + Class.prototype.reload = function (op) { + let options = this.config; + options.data = $.extend(options.data, op.data || {}); + this.events(true); + }; + + Class.prototype.events = function (reload = false) { + let that = this, options = that.config; + let provinceFilter = 'province-' + layarea._id; + let cityFilter = 'city-' + layarea._id; + let countyFilter = 'county-' + layarea._id; + + let provinceEl = options.elem.find('.province-selector'); + let cityEl = options.elem.find('.city-selector'); + let countyEl = options.elem.find('.county-selector'); + + if (reload){ + options.data.provinceCode = getCode('province', options.data.province); + let code = getCode('city', options.data.city, options.data.provinceCode.slice(0, 2)); + options.data.cityCode = code; + options.data.countyCode = getCode('county', options.data.county, options.data.cityCode.slice(0, 4)); + renderProvince(); + return; + } + //filter + if(provinceEl.attr('lay-filter')){ + provinceFilter = provinceEl.attr('lay-filter'); + } + if(cityEl.attr('lay-filter')){ + cityFilter = cityEl.attr('lay-filter'); + } + if(countyEl.attr('lay-filter')){ + countyFilter = countyEl.attr('lay-filter'); + } + provinceEl.attr('lay-filter', provinceFilter); + cityEl.attr('lay-filter', cityFilter); + countyEl.attr('lay-filter', countyFilter); + + //获取默认值 + if(provinceEl.data('value')){ + options.data.province = provinceEl.data('value'); + options.data.provinceCode = getCode('province', options.data.province); + } else if (!options.data.province) { + options.data.province = ''; + } + if(cityEl.data('value')){ + options.data.city = cityEl.data('value'); + let code = getCode('city', options.data.city, options.data.provinceCode.slice(0, 2)); + options.data.cityCode = code; + } else if (!options.data.city) { + options.data.city = ''; + } + if(countyEl.data('value')){ + options.data.county = countyEl.data('value'); + options.data.countyCode = getCode('county', options.data.county, options.data.cityCode.slice(0, 4)); + } else if (!options.data.county) { + options.data.county = ''; + } + provinceEl.attr('lay-filter', provinceFilter); + cityEl.attr('lay-filter', cityFilter); + countyEl.attr('lay-filter', countyFilter); + + //监听结果 + form.on('select('+provinceFilter+')', function(data){ + options.data.province = data.value; + options.data.provinceCode = getCode('province', data.value); + renderCity(options.data.provinceCode); + + options.change(options.data); + }); + form.on('select('+cityFilter+')', function(data){ + options.data.city = data.value; + if(options.data.provinceCode){ + options.data.cityCode = getCode('city', data.value, options.data.provinceCode.slice(0, 2)); + renderCounty(options.data.cityCode); + } + + options.change(options.data); + }); + form.on('select('+countyFilter+')', function(data){ + options.data.county = data.value; + if(options.data.cityCode){ + options.data.countyCode = getCode('county', data.value, options.data.cityCode.slice(0, 4)); + } + options.change(options.data); + }); + + renderProvince(); + + //查找province + function renderProvince(){ + let tpl = ''; + let provinceList = getList("province"); + let currentCode = ''; + let currentName = ''; + provinceList.forEach(function(_item){ + // if (!currentCode){ + // currentCode = _item.code; + // currentName = _item.name; + // } + if(_item.name === options.data.province){ + currentCode = _item.code; + currentName = _item.name; + } + tpl += ''; + }); + provinceEl.html(tpl); + provinceEl.val(options.data.province); + form.render('select'); + renderCity(currentCode); + } + + function renderCity(provinceCode){ + let tpl = ''; + let cityList = getList('city', provinceCode.slice(0, 2)); + let currentCode = ''; + let currentName = ''; + cityList.forEach(function(_item){ + // if (!currentCode){ + // currentCode = _item.code; + // currentName = _item.name; + // } + if(_item.name === options.data.city){ + currentCode = _item.code; + currentName = _item.name; + } + tpl += ''; + }); + options.data.city = currentName; + cityEl.html(tpl); + cityEl.val(options.data.city); + form.render('select'); + renderCounty(currentCode); + } + + function renderCounty(cityCode){ + let tpl = ''; + let countyList = getList('county', cityCode.slice(0, 4)); + let currentCode = ''; + let currentName = ''; + countyList.forEach(function(_item){ + // if (!currentCode){ + // currentCode = _item.code; + // currentName = _item.name; + // } + if(_item.name === options.data.county){ + currentCode = _item.code; + currentName = _item.name; + } + tpl += ''; + }); + options.data.county = currentName; + countyEl.html(tpl); + countyEl.val(options.data.county); + + form.render('select'); + } + + function getList(type, code) { + let result = []; + + if (type !== 'province' && !code) { + return result; + } + + let list = areaList[type + "_list"] || {}; + result = Object.keys(list).map(function (code) { + return { + code: code, + name: list[code] + }; + }); + + if (code) { + // oversea code + if (code[0] === '9' && type === 'city') { + code = '9'; + } + + result = result.filter(function (item) { + return item.code.indexOf(code) === 0; + }); + } + + return result; + } + + function getCode(type, name, parentCode = 0){ + let code = ''; + let list = areaList[type + "_list"] || {}; + let result = {}; + Object.keys(list).map(function (_code) { + if(parentCode){ + if(_code.indexOf(parentCode) === 0){ + result[_code] = list[_code]; + } + }else{ + result[_code] = list[_code]; + } + }); + layui.each(result, function(_code, _name){ + if(_name === name){ + code = _code; + } + }); + + return code; + } + }; + + layarea.render = function (options) { + let inst = new Class(options); + layarea._id++; + return thisArea.call(inst); + }; + + exports('area', layarea); + }); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/button.js b/demo/webman/backend/plugin/admin/public/component/pear/module/button.js new file mode 100644 index 0000000000000000000000000000000000000000..d77c18d2f3850ed307d0e418dfbafccc58d0a444 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/button.js @@ -0,0 +1,53 @@ +layui.define(['jquery'], function(exports) { + "use strict"; + + /** + * Button component + * */ + var MOD_NAME = 'button', + $ = layui.jquery; + + var button = function(opt) { + this.option = opt; + }; + + /** + * Button start loading + * */ + button.prototype.load = function(opt) { + + var option = { + elem: opt.elem, + time: opt.time ? opt.time : false, + done: opt.done ? opt.done : function(){} + } + var text = $(option.elem).html(); + + $(option.elem).html(""); + + $(option.elem).attr("disabled", "disabled"); + + var buttons = $(option.elem); + + if (option.time != "" || option.time !=false) { + setTimeout(function() { + $(option.elem).attr("disabled", false); + buttons.html(text); + option.done(); + }, option.time); + } + option.text = text; + return new button(option); + } + + /** + * Button stop loaded + * */ + button.prototype.stop = function(success) { + $(this.option.elem).attr("disabled", false); + $(this.option.elem).html(this.option.text); + success && success(); + } + + exports(MOD_NAME, new button()); +}); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/card.js b/demo/webman/backend/plugin/admin/public/component/pear/module/card.js new file mode 100644 index 0000000000000000000000000000000000000000..c8d4aeb0f4da0e1e689bf35c62280515d59381aa --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/card.js @@ -0,0 +1,267 @@ +layui.define(['table', 'laypage','jquery', 'element'], function(exports) { + "use strict"; + + var MOD_NAME = 'card', + $ = layui.jquery, + element = layui.element, + laypage = layui.laypage; + + var _instances = {}; // 记录所有实例 + + var defaultOption = { + elem: "#currentTableId",// 构建的模型 + url: "",// 数据 url 连接 + loading: true,//是否加载 + limit: 0, //每页数量默认是每行数量的双倍 + linenum: 4, //每行数量 2,3,4,6 + currentPage: 1,//当前页 + data:[], //静态数据 + limits:[], //页码 + page: true, //是否分页 + layout: ['count', 'prev', 'page', 'next','limit', 'skip'],//分页控件 + request: { + pageName: 'page' //页码的参数名称,默认:page + , limitName: 'limit' //每页数据量的参数名,默认:limit + , idName: 'id' //主键名称,默认:id + , titleName: 'title' //标题名称,默认:title + , imageName: 'image' //图片地址,默认:image + , remarkName: 'remark' //备注名称,默认:remark + , timeName: 'time' //时间名称,默认:time + }, + response: { + statusName: 'code' //规定数据状态的字段名称,默认:code + , statusCode: 0 //规定成功的状态码,默认:0 + , msgName: 'msg' //规定状态信息的字段名称,默认:msg + , countName: 'count' //规定数据总数的字段名称,默认:count + , dataName: 'data' //规定数据列表的字段名称,默认:data + }, + clickItem: function(data){}, + done: function () { + + } + }; + + var card = function(opt) { + _instances[opt.elem.substring(1)] = this; + this.reload(opt); + }; + card.prototype.initOptions = function (opt) { + this.option = $.extend(true, {}, defaultOption, opt); + if (!this.option.limit || this.option.limit == 0) { + this.option.limit = this.option.linenum * 2; + } + if (!this.option.limits || this.option.limits.length == 0) { + this.option.limits = [this.option.limit]; + } + }; + + card.prototype.init = function () { + var option = this.option; + var url = option.url; + var html = ""; + html += option.loading == true ? '
                                                                              ' : '
                                                                              '; + html += ''; + html += '
                                                                              '; + $(option.elem).html(html); + html = ""; + if (!!url) { + if (url.indexOf("?") >= 0) { + url = url + '&v=1.0.0'; + } + else { + url = url + '?v=1.0.0'; + } + if (!!option.page) { + url = url + '&' + option.request.limitName + '=' + option.limit; + url = url + '&' + option.request.pageName + '=' + option.currentPage; + } + if (!!option.where) { + for (let key in option.where) { + url = url + '&' + key + '=' + option.where[key]; + } + } + getData(url).then(function(data){ + data = initData(data, option); + if (data.code != option.response.statusCode) { + option.data = []; + option.count = 0; + } else { + option.data = data.data; + option.count = data.count; + } + + if (!!option.data && option.data.length > 0) { + html = createComponent(option.elem.substring(1), option.linenum, option.data); + html += "
                                                                              "; + } + else { + html = "

                                                                              没有数据

                                                                              "; + } + $(option.elem).html(html); + if (option.page) { + laypage.render({ + elem: 'cardpage' + , count: option.count, limit: option.limit, limits: option.limits, curr: option.currentPage + , layout: option.layout + , jump: function (obj, first) { + option.limit = obj.limit; + option.currentPage = obj.curr; + if (!first) { + _instances[option.elem.substring(1)].reload(option); + } + } + }); + } + }); + } + else { + if (!option.alldata) { + option.alldata = option.data; + } + if (option.page) { + var data = []; + option.count = option.alldata.length; + for (var i = (option.currentPage - 1) * option.limit; i < option.currentPage * option.limit && i 0) { + html = createComponent(option.elem.substring(1), option.linenum, option.data); + html += "
                                                                              "; + } + else { + html = "

                                                                              没有数据

                                                                              "; + } + $(option.elem).html(html); + if (option.page) { + laypage.render({ + elem: 'cardpage' + , count: option.count, limit: option.limit, limits: option.limits, curr: option.currentPage + , layout: option.layout + , jump: function (obj, first) { + option.limit = obj.limit; + option.currentPage = obj.curr; + if (!first) { + _instances[option.elem.substring(1)].reload(option); + } + } + }); + } + } + } + + card.prototype.reload = function (opt) { + this.initOptions(this.option ? $.extend(true, this.option, opt) : opt); + this.init(); // 初始化表格 + } + + function createComponent(elem,linenum,data) { + var html = "
                                                                              " + var content = createCards(elem, linenum,data); + var page = ""; + content = content + page; + html += content + "
                                                                              " + return html; + } + + function createCards(elem, linenum,data) { + var content = "
                                                                              "; + for (var i = 0; i < data.length; i++) { + content += createCard(elem, linenum,data[i],i); + } + content += "
                                                                              "; + return content; + } + + function createCard(elem, linenum, item, no) { + var line = 12 / linenum; + var card = + '

                                                                              ' + item.title + '

                                                                              ' + item.remark + '
                                                                              ' +item.time + '
                                                                              ' + return card; + } + + function initData(tempData, option) { + var data = {}; + data.code = tempData[option.response.statusName]; + data.msg = tempData[option.response.msgName]; + data.count = tempData[option.response.countName]; + var dataList = tempData[option.response.dataName]; + data.data = []; + for (var i = 0; i < dataList.length; i++) { + var item = {}; + item.id = dataList[i][option.request.idName]; + item.image = dataList[i][option.request.imageName]; + item.title = dataList[i][option.request.titleName]; + item.remark = dataList[i][option.request.remarkName]; + item.time = dataList[i][option.request.timeName]; + data.data.push(item); + } + return data; + } + + function getData(url) { + var defer = $.Deferred(); + $.get(url + (url.indexOf("?") ? "&" : "?") + "fresh=" + Math.random(), function(result) { + defer.resolve(result) + }); + return defer.promise(); + } + + window.cardTableCheckedCard = function (elem,obj) { + $(obj).addClass('layui-table-click').siblings().removeClass('layui-table-click'); + var item = {}; + item.id = obj.id; + item.image = $(obj).find('.project-list-item-cover')[0].src; + item.title = $(obj).find('h2')[0].innerHTML; + item.remark = $(obj).find('.project-list-item-text')[0].innerHTML; + item.time = $(obj).find('.time')[0].innerHTML; + _instances[elem.id].option.checkedItem = item; + _instances[elem.id].option.clickItem(item); + } + + /** 对外提供的方法 */ + var tt = { + + render: function (options) { + return new card(options); + }, + + reload: function (id, opt) { + _instances[id].option.checkedItem = null; + _instances[id].reload(opt); + }, + + getChecked: function (id) { + var option = _instances[id].option; + var data = option.checkedItem; + var item = {}; + if (!data) { + return null; + } + item[option.request.idName] = data.id; + item[option.request.imageName] = data.image; + item[option.request.titleName] = data.title; + item[option.request.remarkName] = data.remark; + item[option.request.timeName] = data.time; + return item; + }, + + getAllData: function (id) { + var option = _instances[id].option; + var data = []; + for (var i = 0; i < option.data.length; i++) { + var item = {}; + item[option.request.idName] = option.data[i].id; + item[option.request.imageName] = option.data[i].image; + item[option.request.titleName] = option.data[i].title; + item[option.request.remarkName] = option.data[i].remark; + item[option.request.timeName] = option.data[i].time; + data.push(item); + } + return data; + }, + } + + exports(MOD_NAME, tt); +}) \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/common.js b/demo/webman/backend/plugin/admin/public/component/pear/module/common.js new file mode 100644 index 0000000000000000000000000000000000000000..6f1eac8c4536213820980c8f3664281dd044f3ab --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/common.js @@ -0,0 +1,71 @@ +layui.define(['jquery', 'element','table'], function(exports) { + "use strict"; + + /** + * 常用封装类 + * */ + var MOD_NAME = 'common', + $ = layui.jquery, + table = layui.table, + element = layui.element; + + var common = new function() { + + /** + * 获取当前表格选中字段 + * @param obj 表格回调参数 + * @param field 要获取的字段 + * */ + this.checkField = function(obj, field) { + let data = table.checkStatus(obj.config.id).data; + if (data.length === 0) { + return ""; + } + let ids = ""; + for (let i = 0; i < data.length; i++) { + ids += data[i][field] + ","; + } + ids = ids.substr(0, ids.length - 1); + return ids; + } + + /** + * 当前是否为与移动端 + * */ + this.isModile = function(){ + if ($(window).width() <= 768) { + return true; + } + return false; + } + + + /** + * 提交 json 数据 + * @param data 提交数据 + * @param href 提交接口 + * @param table 刷新父级表 + * + * */ + this.submit = function(data,href,table,callback){ + $.ajax({ + url:href, + data:JSON.stringify(data), + dataType:'json', + contentType:'application/json', + type:'post', + success:callback !=null?callback(result):function(result){ + if(result.success){ + layer.msg(result.msg,{icon:1,time:1000},function(){ + parent.layer.close(parent.layer.getFrameIndex(window.name));//关闭当前页 + parent.layui.table.reload(table); + }); + }else{ + layer.msg(result.msg,{icon:2,time:1000}); + } + } + }) + } + } + exports(MOD_NAME, common); +}); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/context.js b/demo/webman/backend/plugin/admin/public/component/pear/module/context.js new file mode 100644 index 0000000000000000000000000000000000000000..a803e02b883d48cf93b29553de4f845ee40eab06 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/context.js @@ -0,0 +1,19 @@ +layui.define(['jquery', 'element'], function(exports) { + "use strict"; + + var MOD_NAME = 'context', + $ = layui.jquery, + element = layui.element; + + var context = new function() { + + this.put = function(key,value){ + localStorage.setItem(key,value); + } + + this.get = function(key){ + return localStorage.getItem(key); + } + } + exports(MOD_NAME, context); +}); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/convert.js b/demo/webman/backend/plugin/admin/public/component/pear/module/convert.js new file mode 100644 index 0000000000000000000000000000000000000000..1f86ba5af31f0ce9a218509ecc1cd4b75add1147 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/convert.js @@ -0,0 +1,27 @@ +layui.define(['jquery', 'element'], function(exports) { + "use strict"; + + /** + * 类 型 转 换 工 具 类 + * */ + var MOD_NAME = 'convert', + $ = layui.jquery, + element = layui.element; + + var convert = new function() { + + // image 转 base64 + this.imageToBase64 = function(img) { + var canvas = document.createElement("canvas"); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext("2d"); + ctx.drawImage(img, 0, 0, img.width, img.height); + var ext = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase(); + var dataURL = canvas.toDataURL("image/"+ext); + return dataURL; + } + + } + exports(MOD_NAME, convert); +}); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/count.js b/demo/webman/backend/plugin/admin/public/component/pear/module/count.js new file mode 100644 index 0000000000000000000000000000000000000000..c9a659f09545e19b3cd888d919b73842c24dfde9 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/count.js @@ -0,0 +1,37 @@ +layui.define(['jquery', 'element'], function(exports) { + "use strict"; + + var MOD_NAME = 'count', + $ = layui.jquery, + element = layui.element; + + var count = new function() { + + this.up = function(targetEle, options) { + + options = options || {}; + + var $this = document.getElementById(targetEle), + time = options.time, + finalNum = options.num, + regulator = options.regulator, + step = finalNum / (time / regulator), + count = 0.00, + initial = 0; + + var timer = setInterval(function() { + count = count + step; + if (count >= finalNum) { + clearInterval(timer); + count = finalNum; + } + var t = count.toFixed(options.bit?options.bit:0);; + if (t == initial) return; + initial = t; + $this.innerHTML = initial; + }, 30); + } + + } + exports(MOD_NAME, count); +}); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/cropper.js b/demo/webman/backend/plugin/admin/public/component/pear/module/cropper.js new file mode 100644 index 0000000000000000000000000000000000000000..6d774977cbafa228bd022693c5e939aa68f919a1 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/cropper.js @@ -0,0 +1,3087 @@ +/*! + * Cropper v3.0.0 + */ + +layui.define(['jquery'], function (exports) { + var $ = layui.jquery; + $ = $ && $.hasOwnProperty('default') ? $['default'] : $; + + var DEFAULTS = { + // Define the view mode of the cropper + viewMode: 0, // 0, 1, 2, 3 + + // Define the dragging mode of the cropper + dragMode: 'crop', // 'crop', 'move' or 'none' + + // Define the aspect ratio of the crop box + aspectRatio: NaN, + + // An object with the previous cropping result data + data: null, + + // A selector for adding extra containers to preview + preview: '', + + // Re-render the cropper when resize the window + responsive: true, + + // Restore the cropped area after resize the window + restore: true, + + // Check if the current image is a cross-origin image + checkCrossOrigin: true, + + // Check the current image's Exif Orientation information + checkOrientation: true, + + // Show the black modal + modal: true, + + // Show the dashed lines for guiding + guides: true, + + // Show the center indicator for guiding + center: true, + + // Show the white modal to highlight the crop box + highlight: true, + + // Show the grid background + background: true, + + // Enable to crop the image automatically when initialize + autoCrop: true, + + // Define the percentage of automatic cropping area when initializes + autoCropArea: 0.8, + + // Enable to move the image + movable: true, + + // Enable to rotate the image + rotatable: true, + + // Enable to scale the image + scalable: true, + + // Enable to zoom the image + zoomable: true, + + // Enable to zoom the image by dragging touch + zoomOnTouch: true, + + // Enable to zoom the image by wheeling mouse + zoomOnWheel: true, + + // Define zoom ratio when zoom the image by wheeling mouse + wheelZoomRatio: 0.1, + + // Enable to move the crop box + cropBoxMovable: true, + + // Enable to resize the crop box + cropBoxResizable: true, + + // Toggle drag mode between "crop" and "move" when click twice on the cropper + toggleDragModeOnDblclick: true, + + // Size limitation + minCanvasWidth: 0, + minCanvasHeight: 0, + minCropBoxWidth: 0, + minCropBoxHeight: 0, + minContainerWidth: 200, + minContainerHeight: 100, + + // Shortcuts of events + ready: null, + cropstart: null, + cropmove: null, + cropend: null, + crop: null, + zoom: null + }; + + var TEMPLATE = '
                                                                              ' + '
                                                                              ' + '
                                                                              ' + '
                                                                              ' + '
                                                                              ' + '
                                                                              ' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '
                                                                              ' + '
                                                                              '; + + var REGEXP_DATA_URL_HEAD = /^data:.*,/; + var REGEXP_USERAGENT = /(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i; + var navigator = typeof window !== 'undefined' ? window.navigator : null; + var IS_SAFARI_OR_UIWEBVIEW = navigator && REGEXP_USERAGENT.test(navigator.userAgent); + var fromCharCode = String.fromCharCode; + + function isNumber(n) { + return typeof n === 'number' && !isNaN(n); + } + + function isUndefined(n) { + return typeof n === 'undefined'; + } + + function toArray(obj, offset) { + var args = []; + + // This is necessary for IE8 + if (isNumber(offset)) { + args.push(offset); + } + + return args.slice.apply(obj, args); + } + + // Custom proxy to avoid jQuery's guid + function proxy(fn, context) { + for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { + args[_key - 2] = arguments[_key]; + } + + return function () { + for (var _len2 = arguments.length, args2 = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args2[_key2] = arguments[_key2]; + } + + return fn.apply(context, args.concat(toArray(args2))); + }; + } + + function objectKeys(obj) { + var keys = []; + + $.each(obj, function (key) { + keys.push(key); + }); + + return keys; + } + + function isCrossOriginURL(url) { + var parts = url.match(/^(https?:)\/\/([^:/?#]+):?(\d*)/i); + + return parts && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port); + } + + function addTimestamp(url) { + var timestamp = 'timestamp=' + new Date().getTime(); + + return url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp; + } + + function getImageSize(image, callback) { + // Modern browsers (ignore Safari, #120 & #509) + if (image.naturalWidth && !IS_SAFARI_OR_UIWEBVIEW) { + callback(image.naturalWidth, image.naturalHeight); + return; + } + + // IE8: Don't use `new Image()` here (#319) + var newImage = document.createElement('img'); + + newImage.onload = function load() { + callback(this.width, this.height); + }; + + newImage.src = image.src; + } + + function getTransform(options) { + var transforms = []; + var translateX = options.translateX; + var translateY = options.translateY; + var rotate = options.rotate; + var scaleX = options.scaleX; + var scaleY = options.scaleY; + + if (isNumber(translateX) && translateX !== 0) { + transforms.push('translateX(' + translateX + 'px)'); + } + + if (isNumber(translateY) && translateY !== 0) { + transforms.push('translateY(' + translateY + 'px)'); + } + + // Rotate should come first before scale to match orientation transform + if (isNumber(rotate) && rotate !== 0) { + transforms.push('rotate(' + rotate + 'deg)'); + } + + if (isNumber(scaleX) && scaleX !== 1) { + transforms.push('scaleX(' + scaleX + ')'); + } + + if (isNumber(scaleY) && scaleY !== 1) { + transforms.push('scaleY(' + scaleY + ')'); + } + + return transforms.length ? transforms.join(' ') : 'none'; + } + + function getRotatedSizes(data, isReversed) { + var deg = Math.abs(data.degree) % 180; + var arc = (deg > 90 ? 180 - deg : deg) * Math.PI / 180; + var sinArc = Math.sin(arc); + var cosArc = Math.cos(arc); + var width = data.width; + var height = data.height; + var aspectRatio = data.aspectRatio; + var newWidth = void 0; + var newHeight = void 0; + + if (!isReversed) { + newWidth = width * cosArc + height * sinArc; + newHeight = width * sinArc + height * cosArc; + } else { + newWidth = width / (cosArc + sinArc / aspectRatio); + newHeight = newWidth / aspectRatio; + } + + return { + width: newWidth, + height: newHeight + }; + } + + function getSourceCanvas(image, data, options) { + var canvas = $('')[0]; + var context = canvas.getContext('2d'); + var dstX = 0; + var dstY = 0; + var dstWidth = data.naturalWidth; + var dstHeight = data.naturalHeight; + var rotate = data.rotate; + var scaleX = data.scaleX; + var scaleY = data.scaleY; + var scalable = isNumber(scaleX) && isNumber(scaleY) && (scaleX !== 1 || scaleY !== 1); + var rotatable = isNumber(rotate) && rotate !== 0; + var advanced = rotatable || scalable; + var canvasWidth = dstWidth * Math.abs(scaleX || 1); + var canvasHeight = dstHeight * Math.abs(scaleY || 1); + var translateX = void 0; + var translateY = void 0; + var rotated = void 0; + + if (scalable) { + translateX = canvasWidth / 2; + translateY = canvasHeight / 2; + } + + if (rotatable) { + rotated = getRotatedSizes({ + width: canvasWidth, + height: canvasHeight, + degree: rotate + }); + + canvasWidth = rotated.width; + canvasHeight = rotated.height; + translateX = canvasWidth / 2; + translateY = canvasHeight / 2; + } + + canvas.width = canvasWidth; + canvas.height = canvasHeight; + + if (options.fillColor) { + context.fillStyle = options.fillColor; + context.fillRect(0, 0, canvasWidth, canvasHeight); + } + + if (advanced) { + dstX = -dstWidth / 2; + dstY = -dstHeight / 2; + + context.save(); + context.translate(translateX, translateY); + } + + // Rotate should come first before scale as in the "getTransform" function + if (rotatable) { + context.rotate(rotate * Math.PI / 180); + } + + if (scalable) { + context.scale(scaleX, scaleY); + } + + context.imageSmoothingEnabled = !!options.imageSmoothingEnabled; + + if (options.imageSmoothingQuality) { + context.imageSmoothingQuality = options.imageSmoothingQuality; + } + + context.drawImage(image, Math.floor(dstX), Math.floor(dstY), Math.floor(dstWidth), Math.floor(dstHeight)); + + if (advanced) { + context.restore(); + } + + return canvas; + } + + function getStringFromCharCode(dataView, start, length) { + var str = ''; + var i = void 0; + + for (i = start, length += start; i < length; i += 1) { + str += fromCharCode(dataView.getUint8(i)); + } + + return str; + } + + function getOrientation(arrayBuffer) { + var dataView = new DataView(arrayBuffer); + var length = dataView.byteLength; + var orientation = void 0; + var exifIDCode = void 0; + var tiffOffset = void 0; + var firstIFDOffset = void 0; + var littleEndian = void 0; + var endianness = void 0; + var app1Start = void 0; + var ifdStart = void 0; + var offset = void 0; + var i = void 0; + + // Only handle JPEG image (start by 0xFFD8) + if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) { + offset = 2; + + while (offset < length) { + if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) { + app1Start = offset; + break; + } + + offset += 1; + } + } + + if (app1Start) { + exifIDCode = app1Start + 4; + tiffOffset = app1Start + 10; + + if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') { + endianness = dataView.getUint16(tiffOffset); + littleEndian = endianness === 0x4949; + + if (littleEndian || endianness === 0x4D4D /* bigEndian */) { + if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) { + firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); + + if (firstIFDOffset >= 0x00000008) { + ifdStart = tiffOffset + firstIFDOffset; + } + } + } + } + } + + if (ifdStart) { + length = dataView.getUint16(ifdStart, littleEndian); + + for (i = 0; i < length; i += 1) { + offset = ifdStart + i * 12 + 2; + + if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) { + // 8 is the offset of the current tag's value + offset += 8; + + // Get the original orientation value + orientation = dataView.getUint16(offset, littleEndian); + + // Override the orientation with its default value for Safari (#120) + if (IS_SAFARI_OR_UIWEBVIEW) { + dataView.setUint16(offset, 1, littleEndian); + } + + break; + } + } + } + + return orientation; + } + + function dataURLToArrayBuffer(dataURL) { + var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, ''); + var binary = atob(base64); + var length = binary.length; + var arrayBuffer = new ArrayBuffer(length); + var dataView = new Uint8Array(arrayBuffer); + var i = void 0; + + for (i = 0; i < length; i += 1) { + dataView[i] = binary.charCodeAt(i); + } + + return arrayBuffer; + } + + // Only available for JPEG image + function arrayBufferToDataURL(arrayBuffer) { + var dataView = new Uint8Array(arrayBuffer); + var length = dataView.length; + var base64 = ''; + var i = void 0; + + for (i = 0; i < length; i += 1) { + base64 += fromCharCode(dataView[i]); + } + + return 'data:image/jpeg;base64,' + btoa(base64); + } + + var render = { + render: function render() { + var self = this; + + self.initContainer(); + self.initCanvas(); + self.initCropBox(); + + self.renderCanvas(); + + if (self.cropped) { + self.renderCropBox(); + } + }, + initContainer: function initContainer() { + var self = this; + var options = self.options; + var $this = self.$element; + var $container = self.$container; + var $cropper = self.$cropper; + var hidden = 'cropper-hidden'; + + $cropper.addClass(hidden); + $this.removeClass(hidden); + + $cropper.css(self.container = { + width: Math.max($container.width(), Number(options.minContainerWidth) || 200), + height: Math.max($container.height(), Number(options.minContainerHeight) || 100) + }); + + $this.addClass(hidden); + $cropper.removeClass(hidden); + }, + + + // Canvas (image wrapper) + initCanvas: function initCanvas() { + var self = this; + var viewMode = self.options.viewMode; + var container = self.container; + var containerWidth = container.width; + var containerHeight = container.height; + var image = self.image; + var imageNaturalWidth = image.naturalWidth; + var imageNaturalHeight = image.naturalHeight; + var is90Degree = Math.abs(image.rotate) % 180 === 90; + var naturalWidth = is90Degree ? imageNaturalHeight : imageNaturalWidth; + var naturalHeight = is90Degree ? imageNaturalWidth : imageNaturalHeight; + var aspectRatio = naturalWidth / naturalHeight; + var canvasWidth = containerWidth; + var canvasHeight = containerHeight; + + if (containerHeight * aspectRatio > containerWidth) { + if (viewMode === 3) { + canvasWidth = containerHeight * aspectRatio; + } else { + canvasHeight = containerWidth / aspectRatio; + } + } else if (viewMode === 3) { + canvasHeight = containerWidth / aspectRatio; + } else { + canvasWidth = containerHeight * aspectRatio; + } + + var canvas = { + naturalWidth: naturalWidth, + naturalHeight: naturalHeight, + aspectRatio: aspectRatio, + width: canvasWidth, + height: canvasHeight + }; + + canvas.left = (containerWidth - canvasWidth) / 2; + canvas.top = (containerHeight - canvasHeight) / 2; + canvas.oldLeft = canvas.left; + canvas.oldTop = canvas.top; + + self.canvas = canvas; + self.limited = viewMode === 1 || viewMode === 2; + self.limitCanvas(true, true); + self.initialImage = $.extend({}, image); + self.initialCanvas = $.extend({}, canvas); + }, + limitCanvas: function limitCanvas(isSizeLimited, isPositionLimited) { + var self = this; + var options = self.options; + var viewMode = options.viewMode; + var container = self.container; + var containerWidth = container.width; + var containerHeight = container.height; + var canvas = self.canvas; + var aspectRatio = canvas.aspectRatio; + var cropBox = self.cropBox; + var cropped = self.cropped && cropBox; + + if (isSizeLimited) { + var minCanvasWidth = Number(options.minCanvasWidth) || 0; + var minCanvasHeight = Number(options.minCanvasHeight) || 0; + + if (viewMode) { + if (viewMode > 1) { + minCanvasWidth = Math.max(minCanvasWidth, containerWidth); + minCanvasHeight = Math.max(minCanvasHeight, containerHeight); + + if (viewMode === 3) { + if (minCanvasHeight * aspectRatio > minCanvasWidth) { + minCanvasWidth = minCanvasHeight * aspectRatio; + } else { + minCanvasHeight = minCanvasWidth / aspectRatio; + } + } + } else if (minCanvasWidth) { + minCanvasWidth = Math.max(minCanvasWidth, cropped ? cropBox.width : 0); + } else if (minCanvasHeight) { + minCanvasHeight = Math.max(minCanvasHeight, cropped ? cropBox.height : 0); + } else if (cropped) { + minCanvasWidth = cropBox.width; + minCanvasHeight = cropBox.height; + + if (minCanvasHeight * aspectRatio > minCanvasWidth) { + minCanvasWidth = minCanvasHeight * aspectRatio; + } else { + minCanvasHeight = minCanvasWidth / aspectRatio; + } + } + } + + if (minCanvasWidth && minCanvasHeight) { + if (minCanvasHeight * aspectRatio > minCanvasWidth) { + minCanvasHeight = minCanvasWidth / aspectRatio; + } else { + minCanvasWidth = minCanvasHeight * aspectRatio; + } + } else if (minCanvasWidth) { + minCanvasHeight = minCanvasWidth / aspectRatio; + } else if (minCanvasHeight) { + minCanvasWidth = minCanvasHeight * aspectRatio; + } + + canvas.minWidth = minCanvasWidth; + canvas.minHeight = minCanvasHeight; + canvas.maxWidth = Infinity; + canvas.maxHeight = Infinity; + } + + if (isPositionLimited) { + if (viewMode) { + var newCanvasLeft = containerWidth - canvas.width; + var newCanvasTop = containerHeight - canvas.height; + + canvas.minLeft = Math.min(0, newCanvasLeft); + canvas.minTop = Math.min(0, newCanvasTop); + canvas.maxLeft = Math.max(0, newCanvasLeft); + canvas.maxTop = Math.max(0, newCanvasTop); + + if (cropped && self.limited) { + canvas.minLeft = Math.min(cropBox.left, cropBox.left + cropBox.width - canvas.width); + canvas.minTop = Math.min(cropBox.top, cropBox.top + cropBox.height - canvas.height); + canvas.maxLeft = cropBox.left; + canvas.maxTop = cropBox.top; + + if (viewMode === 2) { + if (canvas.width >= containerWidth) { + canvas.minLeft = Math.min(0, newCanvasLeft); + canvas.maxLeft = Math.max(0, newCanvasLeft); + } + + if (canvas.height >= containerHeight) { + canvas.minTop = Math.min(0, newCanvasTop); + canvas.maxTop = Math.max(0, newCanvasTop); + } + } + } + } else { + canvas.minLeft = -canvas.width; + canvas.minTop = -canvas.height; + canvas.maxLeft = containerWidth; + canvas.maxTop = containerHeight; + } + } + }, + renderCanvas: function renderCanvas(isChanged) { + var self = this; + var canvas = self.canvas; + var image = self.image; + var rotate = image.rotate; + var naturalWidth = image.naturalWidth; + var naturalHeight = image.naturalHeight; + + if (self.rotated) { + self.rotated = false; + + // Computes rotated sizes with image sizes + var rotated = getRotatedSizes({ + width: image.width, + height: image.height, + degree: rotate + }); + var aspectRatio = rotated.width / rotated.height; + var isSquareImage = image.aspectRatio === 1; + + if (isSquareImage || aspectRatio !== canvas.aspectRatio) { + canvas.left -= (rotated.width - canvas.width) / 2; + canvas.top -= (rotated.height - canvas.height) / 2; + canvas.width = rotated.width; + canvas.height = rotated.height; + canvas.aspectRatio = aspectRatio; + canvas.naturalWidth = naturalWidth; + canvas.naturalHeight = naturalHeight; + + // Computes rotated sizes with natural image sizes + if (isSquareImage && rotate % 90 || rotate % 180) { + var rotated2 = getRotatedSizes({ + width: naturalWidth, + height: naturalHeight, + degree: rotate + }); + + canvas.naturalWidth = rotated2.width; + canvas.naturalHeight = rotated2.height; + } + + self.limitCanvas(true, false); + } + } + + if (canvas.width > canvas.maxWidth || canvas.width < canvas.minWidth) { + canvas.left = canvas.oldLeft; + } + + if (canvas.height > canvas.maxHeight || canvas.height < canvas.minHeight) { + canvas.top = canvas.oldTop; + } + + canvas.width = Math.min(Math.max(canvas.width, canvas.minWidth), canvas.maxWidth); + canvas.height = Math.min(Math.max(canvas.height, canvas.minHeight), canvas.maxHeight); + + self.limitCanvas(false, true); + + canvas.left = Math.min(Math.max(canvas.left, canvas.minLeft), canvas.maxLeft); + canvas.top = Math.min(Math.max(canvas.top, canvas.minTop), canvas.maxTop); + canvas.oldLeft = canvas.left; + canvas.oldTop = canvas.top; + + self.$canvas.css({ + width: canvas.width, + height: canvas.height, + transform: getTransform({ + translateX: canvas.left, + translateY: canvas.top + }) + }); + + self.renderImage(); + + if (self.cropped && self.limited) { + self.limitCropBox(true, true); + } + + if (isChanged) { + self.output(); + } + }, + renderImage: function renderImage(isChanged) { + var self = this; + var canvas = self.canvas; + var image = self.image; + var reversed = void 0; + + if (image.rotate) { + reversed = getRotatedSizes({ + width: canvas.width, + height: canvas.height, + degree: image.rotate, + aspectRatio: image.aspectRatio + }, true); + } + + $.extend(image, reversed ? { + width: reversed.width, + height: reversed.height, + left: (canvas.width - reversed.width) / 2, + top: (canvas.height - reversed.height) / 2 + } : { + width: canvas.width, + height: canvas.height, + left: 0, + top: 0 + }); + + self.$clone.css({ + width: image.width, + height: image.height, + transform: getTransform($.extend({ + translateX: image.left, + translateY: image.top + }, image)) + }); + + if (isChanged) { + self.output(); + } + }, + initCropBox: function initCropBox() { + var self = this; + var options = self.options; + var canvas = self.canvas; + var aspectRatio = options.aspectRatio; + var autoCropArea = Number(options.autoCropArea) || 0.8; + var cropBox = { + width: canvas.width, + height: canvas.height + }; + + if (aspectRatio) { + if (canvas.height * aspectRatio > canvas.width) { + cropBox.height = cropBox.width / aspectRatio; + } else { + cropBox.width = cropBox.height * aspectRatio; + } + } + + self.cropBox = cropBox; + self.limitCropBox(true, true); + + // Initialize auto crop area + cropBox.width = Math.min(Math.max(cropBox.width, cropBox.minWidth), cropBox.maxWidth); + cropBox.height = Math.min(Math.max(cropBox.height, cropBox.minHeight), cropBox.maxHeight); + + // The width of auto crop area must large than "minWidth", and the height too. (#164) + cropBox.width = Math.max(cropBox.minWidth, cropBox.width * autoCropArea); + cropBox.height = Math.max(cropBox.minHeight, cropBox.height * autoCropArea); + cropBox.left = canvas.left + (canvas.width - cropBox.width) / 2; + cropBox.top = canvas.top + (canvas.height - cropBox.height) / 2; + cropBox.oldLeft = cropBox.left; + cropBox.oldTop = cropBox.top; + + self.initialCropBox = $.extend({}, cropBox); + }, + limitCropBox: function limitCropBox(isSizeLimited, isPositionLimited) { + var self = this; + var options = self.options; + var aspectRatio = options.aspectRatio; + var container = self.container; + var containerWidth = container.width; + var containerHeight = container.height; + var canvas = self.canvas; + var cropBox = self.cropBox; + var limited = self.limited; + + if (isSizeLimited) { + var minCropBoxWidth = Number(options.minCropBoxWidth) || 0; + var minCropBoxHeight = Number(options.minCropBoxHeight) || 0; + var maxCropBoxWidth = Math.min(containerWidth, limited ? canvas.width : containerWidth); + var maxCropBoxHeight = Math.min(containerHeight, limited ? canvas.height : containerHeight); + + // The min/maxCropBoxWidth/Height must be less than containerWidth/Height + minCropBoxWidth = Math.min(minCropBoxWidth, containerWidth); + minCropBoxHeight = Math.min(minCropBoxHeight, containerHeight); + + if (aspectRatio) { + if (minCropBoxWidth && minCropBoxHeight) { + if (minCropBoxHeight * aspectRatio > minCropBoxWidth) { + minCropBoxHeight = minCropBoxWidth / aspectRatio; + } else { + minCropBoxWidth = minCropBoxHeight * aspectRatio; + } + } else if (minCropBoxWidth) { + minCropBoxHeight = minCropBoxWidth / aspectRatio; + } else if (minCropBoxHeight) { + minCropBoxWidth = minCropBoxHeight * aspectRatio; + } + + if (maxCropBoxHeight * aspectRatio > maxCropBoxWidth) { + maxCropBoxHeight = maxCropBoxWidth / aspectRatio; + } else { + maxCropBoxWidth = maxCropBoxHeight * aspectRatio; + } + } + + // The minWidth/Height must be less than maxWidth/Height + cropBox.minWidth = Math.min(minCropBoxWidth, maxCropBoxWidth); + cropBox.minHeight = Math.min(minCropBoxHeight, maxCropBoxHeight); + cropBox.maxWidth = maxCropBoxWidth; + cropBox.maxHeight = maxCropBoxHeight; + } + + if (isPositionLimited) { + if (limited) { + cropBox.minLeft = Math.max(0, canvas.left); + cropBox.minTop = Math.max(0, canvas.top); + cropBox.maxLeft = Math.min(containerWidth, canvas.left + canvas.width) - cropBox.width; + cropBox.maxTop = Math.min(containerHeight, canvas.top + canvas.height) - cropBox.height; + } else { + cropBox.minLeft = 0; + cropBox.minTop = 0; + cropBox.maxLeft = containerWidth - cropBox.width; + cropBox.maxTop = containerHeight - cropBox.height; + } + } + }, + renderCropBox: function renderCropBox() { + var self = this; + var options = self.options; + var container = self.container; + var containerWidth = container.width; + var containerHeight = container.height; + var cropBox = self.cropBox; + + if (cropBox.width > cropBox.maxWidth || cropBox.width < cropBox.minWidth) { + cropBox.left = cropBox.oldLeft; + } + + if (cropBox.height > cropBox.maxHeight || cropBox.height < cropBox.minHeight) { + cropBox.top = cropBox.oldTop; + } + + cropBox.width = Math.min(Math.max(cropBox.width, cropBox.minWidth), cropBox.maxWidth); + cropBox.height = Math.min(Math.max(cropBox.height, cropBox.minHeight), cropBox.maxHeight); + + self.limitCropBox(false, true); + + cropBox.left = Math.min(Math.max(cropBox.left, cropBox.minLeft), cropBox.maxLeft); + cropBox.top = Math.min(Math.max(cropBox.top, cropBox.minTop), cropBox.maxTop); + cropBox.oldLeft = cropBox.left; + cropBox.oldTop = cropBox.top; + + if (options.movable && options.cropBoxMovable) { + // Turn to move the canvas when the crop box is equal to the container + self.$face.data('action', cropBox.width === containerWidth && cropBox.height === containerHeight ? 'move' : 'all'); + } + + self.$cropBox.css({ + width: cropBox.width, + height: cropBox.height, + transform: getTransform({ + translateX: cropBox.left, + translateY: cropBox.top + }) + }); + + if (self.cropped && self.limited) { + self.limitCanvas(true, true); + } + + if (!self.disabled) { + self.output(); + } + }, + output: function output() { + var self = this; + + self.preview(); + + if (self.completed) { + self.trigger('crop', self.getData()); + } + } + }; + + var DATA_PREVIEW = 'preview'; + + var preview = { + initPreview: function initPreview() { + var self = this; + var crossOrigin = self.crossOrigin; + var url = crossOrigin ? self.crossOriginUrl : self.url; + var image = document.createElement('img'); + + if (crossOrigin) { + image.crossOrigin = crossOrigin; + } + + image.src = url; + + var $clone2 = $(image); + + self.$preview = $(self.options.preview); + self.$clone2 = $clone2; + self.$viewBox.html($clone2); + self.$preview.each(function (i, element) { + var $this = $(element); + var img = document.createElement('img'); + + // Save the original size for recover + $this.data(DATA_PREVIEW, { + width: $this.width(), + height: $this.height(), + html: $this.html() + }); + + if (crossOrigin) { + img.crossOrigin = crossOrigin; + } + + img.src = url; + + /** + * Override img element styles + * Add `display:block` to avoid margin top issue + * Add `height:auto` to override `height` attribute on IE8 + * (Occur only when margin-top <= -height) + */ + img.style.cssText = 'display:block;' + 'width:100%;' + 'height:auto;' + 'min-width:0!important;' + 'min-height:0!important;' + 'max-width:none!important;' + 'max-height:none!important;' + 'image-orientation:0deg!important;"'; + + $this.html(img); + }); + }, + resetPreview: function resetPreview() { + this.$preview.each(function (i, element) { + var $this = $(element); + var data = $this.data(DATA_PREVIEW); + + $this.css({ + width: data.width, + height: data.height + }).html(data.html).removeData(DATA_PREVIEW); + }); + }, + preview: function preview() { + var self = this; + var image = self.image; + var canvas = self.canvas; + var cropBox = self.cropBox; + var cropBoxWidth = cropBox.width; + var cropBoxHeight = cropBox.height; + var width = image.width; + var height = image.height; + var left = cropBox.left - canvas.left - image.left; + var top = cropBox.top - canvas.top - image.top; + + if (!self.cropped || self.disabled) { + return; + } + + self.$clone2.css({ + width: width, + height: height, + transform: getTransform($.extend({ + translateX: -left, + translateY: -top + }, image)) + }); + + self.$preview.each(function (i, element) { + var $this = $(element); + var data = $this.data(DATA_PREVIEW); + var originalWidth = data.width; + var originalHeight = data.height; + var newWidth = originalWidth; + var newHeight = originalHeight; + var ratio = 1; + + if (cropBoxWidth) { + ratio = originalWidth / cropBoxWidth; + newHeight = cropBoxHeight * ratio; + } + + if (cropBoxHeight && newHeight > originalHeight) { + ratio = originalHeight / cropBoxHeight; + newWidth = cropBoxWidth * ratio; + newHeight = originalHeight; + } + + $this.css({ + width: newWidth, + height: newHeight + }).find('img').css({ + width: width * ratio, + height: height * ratio, + transform: getTransform($.extend({ + translateX: -left * ratio, + translateY: -top * ratio + }, image)) + }); + }); + } + }; + + // Globals + var PointerEvent = typeof window !== 'undefined' ? window.PointerEvent : null; + + // Events + var EVENT_POINTER_DOWN = PointerEvent ? 'pointerdown' : 'touchstart mousedown'; + var EVENT_POINTER_MOVE = PointerEvent ? 'pointermove' : 'touchmove mousemove'; + var EVENT_POINTER_UP = PointerEvent ? ' pointerup pointercancel' : 'touchend touchcancel mouseup'; + var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll'; + var EVENT_DBLCLICK = 'dblclick'; + var EVENT_RESIZE = 'resize'; + var EVENT_CROP_START = 'cropstart'; + var EVENT_CROP_MOVE = 'cropmove'; + var EVENT_CROP_END = 'cropend'; + var EVENT_CROP = 'crop'; + var EVENT_ZOOM = 'zoom'; + + var events = { + bind: function bind() { + var self = this; + var options = self.options; + var $this = self.$element; + var $cropper = self.$cropper; + + if ($.isFunction(options.cropstart)) { + $this.on(EVENT_CROP_START, options.cropstart); + } + + if ($.isFunction(options.cropmove)) { + $this.on(EVENT_CROP_MOVE, options.cropmove); + } + + if ($.isFunction(options.cropend)) { + $this.on(EVENT_CROP_END, options.cropend); + } + + if ($.isFunction(options.crop)) { + $this.on(EVENT_CROP, options.crop); + } + + if ($.isFunction(options.zoom)) { + $this.on(EVENT_ZOOM, options.zoom); + } + + $cropper.on(EVENT_POINTER_DOWN, proxy(self.cropStart, this)); + + if (options.zoomable && options.zoomOnWheel) { + $cropper.on(EVENT_WHEEL, proxy(self.wheel, this)); + } + + if (options.toggleDragModeOnDblclick) { + $cropper.on(EVENT_DBLCLICK, proxy(self.dblclick, this)); + } + + $(document).on(EVENT_POINTER_MOVE, self.onCropMove = proxy(self.cropMove, this)).on(EVENT_POINTER_UP, self.onCropEnd = proxy(self.cropEnd, this)); + + if (options.responsive) { + $(window).on(EVENT_RESIZE, self.onResize = proxy(self.resize, this)); + } + }, + unbind: function unbind() { + var self = this; + var options = self.options; + var $this = self.$element; + var $cropper = self.$cropper; + + if ($.isFunction(options.cropstart)) { + $this.off(EVENT_CROP_START, options.cropstart); + } + + if ($.isFunction(options.cropmove)) { + $this.off(EVENT_CROP_MOVE, options.cropmove); + } + + if ($.isFunction(options.cropend)) { + $this.off(EVENT_CROP_END, options.cropend); + } + + if ($.isFunction(options.crop)) { + $this.off(EVENT_CROP, options.crop); + } + + if ($.isFunction(options.zoom)) { + $this.off(EVENT_ZOOM, options.zoom); + } + + $cropper.off(EVENT_POINTER_DOWN, self.cropStart); + + if (options.zoomable && options.zoomOnWheel) { + $cropper.off(EVENT_WHEEL, self.wheel); + } + + if (options.toggleDragModeOnDblclick) { + $cropper.off(EVENT_DBLCLICK, self.dblclick); + } + + $(document).off(EVENT_POINTER_MOVE, self.onCropMove).off(EVENT_POINTER_UP, self.onCropEnd); + + if (options.responsive) { + $(window).off(EVENT_RESIZE, self.onResize); + } + } + }; + + var REGEXP_ACTIONS = /^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/; + + function getPointer(_ref, endOnly) { + var pageX = _ref.pageX, + pageY = _ref.pageY; + + var end = { + endX: pageX, + endY: pageY + }; + + if (endOnly) { + return end; + } + + return $.extend({ + startX: pageX, + startY: pageY + }, end); + } + + var handlers = { + resize: function resize() { + var self = this; + var options = self.options; + var $container = self.$container; + var container = self.container; + var minContainerWidth = Number(options.minContainerWidth) || 200; + var minContainerHeight = Number(options.minContainerHeight) || 100; + + if (self.disabled || container.width === minContainerWidth || container.height === minContainerHeight) { + return; + } + + var ratio = $container.width() / container.width; + + // Resize when width changed or height changed + if (ratio !== 1 || $container.height() !== container.height) { + var canvasData = void 0; + var cropBoxData = void 0; + + if (options.restore) { + canvasData = self.getCanvasData(); + cropBoxData = self.getCropBoxData(); + } + + self.render(); + + if (options.restore) { + self.setCanvasData($.each(canvasData, function (i, n) { + canvasData[i] = n * ratio; + })); + self.setCropBoxData($.each(cropBoxData, function (i, n) { + cropBoxData[i] = n * ratio; + })); + } + } + }, + dblclick: function dblclick() { + var self = this; + + if (self.disabled || self.options.dragMode === 'none') { + return; + } + + self.setDragMode(self.$dragBox.hasClass('cropper-crop') ? 'move' : 'crop'); + }, + wheel: function wheel(event) { + var self = this; + var e = event.originalEvent || event; + var ratio = Number(self.options.wheelZoomRatio) || 0.1; + + if (self.disabled) { + return; + } + + event.preventDefault(); + + // Limit wheel speed to prevent zoom too fast + if (self.wheeling) { + return; + } + + self.wheeling = true; + + setTimeout(function () { + self.wheeling = false; + }, 50); + + var delta = 1; + + if (e.deltaY) { + delta = e.deltaY > 0 ? 1 : -1; + } else if (e.wheelDelta) { + delta = -e.wheelDelta / 120; + } else if (e.detail) { + delta = e.detail > 0 ? 1 : -1; + } + + self.zoom(-delta * ratio, event); + }, + cropStart: function cropStart(e) { + var self = this; + + if (self.disabled) { + return; + } + + var options = self.options; + var pointers = self.pointers; + var originalEvent = e.originalEvent; + var action = void 0; + + if (originalEvent && originalEvent.changedTouches) { + // Handle touch event + $.each(originalEvent.changedTouches, function (i, touch) { + pointers[touch.identifier] = getPointer(touch); + }); + } else { + // Handle mouse event and pointer event + pointers[originalEvent && originalEvent.pointerId || 0] = getPointer(originalEvent || e); + } + + if (objectKeys(pointers).length > 1 && options.zoomable && options.zoomOnTouch) { + action = 'zoom'; + } else { + action = $(e.target).data('action'); + } + + if (!REGEXP_ACTIONS.test(action)) { + return; + } + + if (self.trigger('cropstart', { + originalEvent: originalEvent, + action: action + }).isDefaultPrevented()) { + return; + } + + e.preventDefault(); + + self.action = action; + self.cropping = false; + + if (action === 'crop') { + self.cropping = true; + self.$dragBox.addClass('cropper-modal'); + } + }, + cropMove: function cropMove(e) { + var self = this; + var action = self.action; + + if (self.disabled || !action) { + return; + } + + var pointers = self.pointers; + var originalEvent = e.originalEvent; + + e.preventDefault(); + + if (self.trigger('cropmove', { + originalEvent: originalEvent, + action: action + }).isDefaultPrevented()) { + return; + } + + if (originalEvent && originalEvent.changedTouches) { + $.each(originalEvent.changedTouches, function (i, touch) { + $.extend(pointers[touch.identifier], getPointer(touch, true)); + }); + } else { + $.extend(pointers[originalEvent && originalEvent.pointerId || 0], getPointer(originalEvent || e, true)); + } + + self.change(e); + }, + cropEnd: function cropEnd(e) { + var self = this; + + if (self.disabled) { + return; + } + + var action = self.action; + var pointers = self.pointers; + var originalEvent = e.originalEvent; + + if (originalEvent && originalEvent.changedTouches) { + $.each(originalEvent.changedTouches, function (i, touch) { + delete pointers[touch.identifier]; + }); + } else { + delete pointers[originalEvent && originalEvent.pointerId || 0]; + } + + if (!action) { + return; + } + + e.preventDefault(); + + if (!objectKeys(pointers).length) { + self.action = ''; + } + + if (self.cropping) { + self.cropping = false; + self.$dragBox.toggleClass('cropper-modal', self.cropped && self.options.modal); + } + + self.trigger('cropend', { + originalEvent: originalEvent, + action: action + }); + } + }; + + // Actions + var ACTION_EAST = 'e'; + var ACTION_WEST = 'w'; + var ACTION_SOUTH = 's'; + var ACTION_NORTH = 'n'; + var ACTION_SOUTH_EAST = 'se'; + var ACTION_SOUTH_WEST = 'sw'; + var ACTION_NORTH_EAST = 'ne'; + var ACTION_NORTH_WEST = 'nw'; + + function getMaxZoomRatio(pointers) { + var pointers2 = $.extend({}, pointers); + var ratios = []; + + $.each(pointers, function (pointerId, pointer) { + delete pointers2[pointerId]; + + $.each(pointers2, function (pointerId2, pointer2) { + var x1 = Math.abs(pointer.startX - pointer2.startX); + var y1 = Math.abs(pointer.startY - pointer2.startY); + var x2 = Math.abs(pointer.endX - pointer2.endX); + var y2 = Math.abs(pointer.endY - pointer2.endY); + var z1 = Math.sqrt(x1 * x1 + y1 * y1); + var z2 = Math.sqrt(x2 * x2 + y2 * y2); + var ratio = (z2 - z1) / z1; + + ratios.push(ratio); + }); + }); + + ratios.sort(function (a, b) { + return Math.abs(a) < Math.abs(b); + }); + + return ratios[0]; + } + + var change = { + change: function change(e) { + var self = this; + var options = self.options; + var pointers = self.pointers; + var pointer = pointers[objectKeys(pointers)[0]]; + var container = self.container; + var canvas = self.canvas; + var cropBox = self.cropBox; + var action = self.action; + var aspectRatio = options.aspectRatio; + var width = cropBox.width; + var height = cropBox.height; + var left = cropBox.left; + var top = cropBox.top; + var right = left + width; + var bottom = top + height; + var minLeft = 0; + var minTop = 0; + var maxWidth = container.width; + var maxHeight = container.height; + var renderable = true; + var offset = void 0; + + // Locking aspect ratio in "free mode" by holding shift key (#259) + if (!aspectRatio && e.shiftKey) { + aspectRatio = width && height ? width / height : 1; + } + + if (self.limited) { + minLeft = cropBox.minLeft; + minTop = cropBox.minTop; + maxWidth = minLeft + Math.min(container.width, canvas.width, canvas.left + canvas.width); + maxHeight = minTop + Math.min(container.height, canvas.height, canvas.top + canvas.height); + } + + var range = { + x: pointer.endX - pointer.startX, + y: pointer.endY - pointer.startY + }; + + switch (action) { + // Move crop box + case 'all': + left += range.x; + top += range.y; + break; + + // Resize crop box + case ACTION_EAST: + if (range.x >= 0 && (right >= maxWidth || aspectRatio && (top <= minTop || bottom >= maxHeight))) { + renderable = false; + break; + } + + if (right + range.x > maxWidth) { + range.x = maxWidth - right; + } + + width += range.x; + + if (aspectRatio) { + height = width / aspectRatio; + top -= range.x / aspectRatio / 2; + } + + if (width < 0) { + action = ACTION_WEST; + width = 0; + } + + break; + + case ACTION_NORTH: + if (range.y <= 0 && (top <= minTop || aspectRatio && (left <= minLeft || right >= maxWidth))) { + renderable = false; + break; + } + + if (top + range.y < minTop) { + range.y = minTop - top; + } + + height -= range.y; + top += range.y; + + if (aspectRatio) { + width = height * aspectRatio; + left += range.y * aspectRatio / 2; + } + + if (height < 0) { + action = ACTION_SOUTH; + height = 0; + } + + break; + + case ACTION_WEST: + if (range.x <= 0 && (left <= minLeft || aspectRatio && (top <= minTop || bottom >= maxHeight))) { + renderable = false; + break; + } + + if (left + range.x < minLeft) { + range.x = minLeft - left; + } + + width -= range.x; + left += range.x; + + if (aspectRatio) { + height = width / aspectRatio; + top += range.x / aspectRatio / 2; + } + + if (width < 0) { + action = ACTION_EAST; + width = 0; + } + + break; + + case ACTION_SOUTH: + if (range.y >= 0 && (bottom >= maxHeight || aspectRatio && (left <= minLeft || right >= maxWidth))) { + renderable = false; + break; + } + + if (bottom + range.y > maxHeight) { + range.y = maxHeight - bottom; + } + + height += range.y; + + if (aspectRatio) { + width = height * aspectRatio; + left -= range.y * aspectRatio / 2; + } + + if (height < 0) { + action = ACTION_NORTH; + height = 0; + } + + break; + + case ACTION_NORTH_EAST: + if (aspectRatio) { + if (range.y <= 0 && (top <= minTop || right >= maxWidth)) { + renderable = false; + break; + } + + height -= range.y; + top += range.y; + width = height * aspectRatio; + } else { + if (range.x >= 0) { + if (right < maxWidth) { + width += range.x; + } else if (range.y <= 0 && top <= minTop) { + renderable = false; + } + } else { + width += range.x; + } + + if (range.y <= 0) { + if (top > minTop) { + height -= range.y; + top += range.y; + } + } else { + height -= range.y; + top += range.y; + } + } + + if (width < 0 && height < 0) { + action = ACTION_SOUTH_WEST; + height = 0; + width = 0; + } else if (width < 0) { + action = ACTION_NORTH_WEST; + width = 0; + } else if (height < 0) { + action = ACTION_SOUTH_EAST; + height = 0; + } + + break; + + case ACTION_NORTH_WEST: + if (aspectRatio) { + if (range.y <= 0 && (top <= minTop || left <= minLeft)) { + renderable = false; + break; + } + + height -= range.y; + top += range.y; + width = height * aspectRatio; + left += range.y * aspectRatio; + } else { + if (range.x <= 0) { + if (left > minLeft) { + width -= range.x; + left += range.x; + } else if (range.y <= 0 && top <= minTop) { + renderable = false; + } + } else { + width -= range.x; + left += range.x; + } + + if (range.y <= 0) { + if (top > minTop) { + height -= range.y; + top += range.y; + } + } else { + height -= range.y; + top += range.y; + } + } + + if (width < 0 && height < 0) { + action = ACTION_SOUTH_EAST; + height = 0; + width = 0; + } else if (width < 0) { + action = ACTION_NORTH_EAST; + width = 0; + } else if (height < 0) { + action = ACTION_SOUTH_WEST; + height = 0; + } + + break; + + case ACTION_SOUTH_WEST: + if (aspectRatio) { + if (range.x <= 0 && (left <= minLeft || bottom >= maxHeight)) { + renderable = false; + break; + } + + width -= range.x; + left += range.x; + height = width / aspectRatio; + } else { + if (range.x <= 0) { + if (left > minLeft) { + width -= range.x; + left += range.x; + } else if (range.y >= 0 && bottom >= maxHeight) { + renderable = false; + } + } else { + width -= range.x; + left += range.x; + } + + if (range.y >= 0) { + if (bottom < maxHeight) { + height += range.y; + } + } else { + height += range.y; + } + } + + if (width < 0 && height < 0) { + action = ACTION_NORTH_EAST; + height = 0; + width = 0; + } else if (width < 0) { + action = ACTION_SOUTH_EAST; + width = 0; + } else if (height < 0) { + action = ACTION_NORTH_WEST; + height = 0; + } + + break; + + case ACTION_SOUTH_EAST: + if (aspectRatio) { + if (range.x >= 0 && (right >= maxWidth || bottom >= maxHeight)) { + renderable = false; + break; + } + + width += range.x; + height = width / aspectRatio; + } else { + if (range.x >= 0) { + if (right < maxWidth) { + width += range.x; + } else if (range.y >= 0 && bottom >= maxHeight) { + renderable = false; + } + } else { + width += range.x; + } + + if (range.y >= 0) { + if (bottom < maxHeight) { + height += range.y; + } + } else { + height += range.y; + } + } + + if (width < 0 && height < 0) { + action = ACTION_NORTH_WEST; + height = 0; + width = 0; + } else if (width < 0) { + action = ACTION_SOUTH_WEST; + width = 0; + } else if (height < 0) { + action = ACTION_NORTH_EAST; + height = 0; + } + + break; + + // Move canvas + case 'move': + self.move(range.x, range.y); + renderable = false; + break; + + // Zoom canvas + case 'zoom': + self.zoom(getMaxZoomRatio(pointers), e.originalEvent); + renderable = false; + break; + + // Create crop box + case 'crop': + if (!range.x || !range.y) { + renderable = false; + break; + } + + offset = self.$cropper.offset(); + left = pointer.startX - offset.left; + top = pointer.startY - offset.top; + width = cropBox.minWidth; + height = cropBox.minHeight; + + if (range.x > 0) { + action = range.y > 0 ? ACTION_SOUTH_EAST : ACTION_NORTH_EAST; + } else if (range.x < 0) { + left -= width; + action = range.y > 0 ? ACTION_SOUTH_WEST : ACTION_NORTH_WEST; + } + + if (range.y < 0) { + top -= height; + } + + // Show the crop box if is hidden + if (!self.cropped) { + self.$cropBox.removeClass('cropper-hidden'); + self.cropped = true; + + if (self.limited) { + self.limitCropBox(true, true); + } + } + + break; + + default: + } + + if (renderable) { + cropBox.width = width; + cropBox.height = height; + cropBox.left = left; + cropBox.top = top; + self.action = action; + self.renderCropBox(); + } + + // Override + $.each(pointers, function (i, p) { + p.startX = p.endX; + p.startY = p.endY; + }); + } + }; + + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length) ; i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + + function getPointersCenter(pointers) { + var pageX = 0; + var pageY = 0; + var count = 0; + + $.each(pointers, function (i, _ref) { + var startX = _ref.startX, + startY = _ref.startY; + + pageX += startX; + pageY += startY; + count += 1; + }); + + pageX /= count; + pageY /= count; + + return { + pageX: pageX, + pageY: pageY + }; + } + + var methods = { + // Show the crop box manually + crop: function crop() { + var self = this; + + if (!self.ready || self.disabled) { + return; + } + + if (!self.cropped) { + self.cropped = true; + self.limitCropBox(true, true); + + if (self.options.modal) { + self.$dragBox.addClass('cropper-modal'); + } + + self.$cropBox.removeClass('cropper-hidden'); + } + + self.setCropBoxData(self.initialCropBox); + }, + + + // Reset the image and crop box to their initial states + reset: function reset() { + var self = this; + + if (!self.ready || self.disabled) { + return; + } + + self.image = $.extend({}, self.initialImage); + self.canvas = $.extend({}, self.initialCanvas); + self.cropBox = $.extend({}, self.initialCropBox); + + self.renderCanvas(); + + if (self.cropped) { + self.renderCropBox(); + } + }, + + + // Clear the crop box + clear: function clear() { + var self = this; + + if (!self.cropped || self.disabled) { + return; + } + + $.extend(self.cropBox, { + left: 0, + top: 0, + width: 0, + height: 0 + }); + + self.cropped = false; + self.renderCropBox(); + + self.limitCanvas(true, true); + + // Render canvas after crop box rendered + self.renderCanvas(); + + self.$dragBox.removeClass('cropper-modal'); + self.$cropBox.addClass('cropper-hidden'); + }, + + + /** + * Replace the image's src and rebuild the cropper + * + * @param {String} url + * @param {Boolean} onlyColorChanged (optional) + */ + replace: function replace(url, onlyColorChanged) { + var self = this; + + if (!self.disabled && url) { + if (self.isImg) { + self.$element.attr('src', url); + } + + if (onlyColorChanged) { + self.url = url; + self.$clone.attr('src', url); + + if (self.ready) { + self.$preview.find('img').add(self.$clone2).attr('src', url); + } + } else { + if (self.isImg) { + self.replaced = true; + } + + // Clear previous data + self.options.data = null; + self.load(url); + } + } + }, + + + // Enable (unfreeze) the cropper + enable: function enable() { + var self = this; + + if (self.ready) { + self.disabled = false; + self.$cropper.removeClass('cropper-disabled'); + } + }, + + + // Disable (freeze) the cropper + disable: function disable() { + var self = this; + + if (self.ready) { + self.disabled = true; + self.$cropper.addClass('cropper-disabled'); + } + }, + + + // Destroy the cropper and remove the instance from the image + destroy: function destroy() { + var self = this; + var $this = self.$element; + + if (self.loaded) { + if (self.isImg && self.replaced) { + $this.attr('src', self.originalUrl); + } + + self.unbuild(); + $this.removeClass('cropper-hidden'); + } else if (self.isImg) { + $this.off('load', self.start); + } else if (self.$clone) { + self.$clone.remove(); + } + + $this.removeData('cropper'); + }, + + + /** + * Move the canvas with relative offsets + * + * @param {Number} offsetX + * @param {Number} offsetY (optional) + */ + move: function move(offsetX, offsetY) { + var self = this; + var canvas = self.canvas; + + self.moveTo(isUndefined(offsetX) ? offsetX : canvas.left + Number(offsetX), isUndefined(offsetY) ? offsetY : canvas.top + Number(offsetY)); + }, + + + /** + * Move the canvas to an absolute point + * + * @param {Number} x + * @param {Number} y (optional) + */ + moveTo: function moveTo(x, y) { + var self = this; + var canvas = self.canvas; + var changed = false; + + // If "y" is not present, its default value is "x" + if (isUndefined(y)) { + y = x; + } + + x = Number(x); + y = Number(y); + + if (self.ready && !self.disabled && self.options.movable) { + if (isNumber(x)) { + canvas.left = x; + changed = true; + } + + if (isNumber(y)) { + canvas.top = y; + changed = true; + } + + if (changed) { + self.renderCanvas(true); + } + } + }, + + + /** + * Zoom the canvas with a relative ratio + * + * @param {Number} ratio + * @param {jQuery Event} _event (private) + */ + zoom: function zoom(ratio, _event) { + var self = this; + var canvas = self.canvas; + + ratio = Number(ratio); + + if (ratio < 0) { + ratio = 1 / (1 - ratio); + } else { + ratio = 1 + ratio; + } + + self.zoomTo(canvas.width * ratio / canvas.naturalWidth, _event); + }, + + + /** + * Zoom the canvas to an absolute ratio + * + * @param {Number} ratio + * @param {jQuery Event} _event (private) + */ + zoomTo: function zoomTo(ratio, _event) { + var self = this; + var options = self.options; + var pointers = self.pointers; + var canvas = self.canvas; + var width = canvas.width; + var height = canvas.height; + var naturalWidth = canvas.naturalWidth; + var naturalHeight = canvas.naturalHeight; + + ratio = Number(ratio); + + if (ratio >= 0 && self.ready && !self.disabled && options.zoomable) { + var newWidth = naturalWidth * ratio; + var newHeight = naturalHeight * ratio; + var originalEvent = void 0; + + if (_event) { + originalEvent = _event.originalEvent; + } + + if (self.trigger('zoom', { + originalEvent: originalEvent, + oldRatio: width / naturalWidth, + ratio: newWidth / naturalWidth + }).isDefaultPrevented()) { + return; + } + + if (originalEvent) { + var offset = self.$cropper.offset(); + var center = pointers && objectKeys(pointers).length ? getPointersCenter(pointers) : { + pageX: _event.pageX || originalEvent.pageX || 0, + pageY: _event.pageY || originalEvent.pageY || 0 + }; + + // Zoom from the triggering point of the event + canvas.left -= (newWidth - width) * ((center.pageX - offset.left - canvas.left) / width); + canvas.top -= (newHeight - height) * ((center.pageY - offset.top - canvas.top) / height); + } else { + // Zoom from the center of the canvas + canvas.left -= (newWidth - width) / 2; + canvas.top -= (newHeight - height) / 2; + } + + canvas.width = newWidth; + canvas.height = newHeight; + self.renderCanvas(true); + } + }, + + + /** + * Rotate the canvas with a relative degree + * + * @param {Number} degree + */ + rotate: function rotate(degree) { + var self = this; + + self.rotateTo((self.image.rotate || 0) + Number(degree)); + }, + + + /** + * Rotate the canvas to an absolute degree + * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#rotate() + * + * @param {Number} degree + */ + rotateTo: function rotateTo(degree) { + var self = this; + + degree = Number(degree); + + if (isNumber(degree) && self.ready && !self.disabled && self.options.rotatable) { + self.image.rotate = degree % 360; + self.rotated = true; + self.renderCanvas(true); + } + }, + + + /** + * Scale the image + * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#scale() + * + * @param {Number} scaleX + * @param {Number} scaleY (optional) + */ + scale: function scale(scaleX, scaleY) { + var self = this; + var image = self.image; + var changed = false; + + // If "scaleY" is not present, its default value is "scaleX" + if (isUndefined(scaleY)) { + scaleY = scaleX; + } + + scaleX = Number(scaleX); + scaleY = Number(scaleY); + + if (self.ready && !self.disabled && self.options.scalable) { + if (isNumber(scaleX)) { + image.scaleX = scaleX; + changed = true; + } + + if (isNumber(scaleY)) { + image.scaleY = scaleY; + changed = true; + } + + if (changed) { + self.renderImage(true); + } + } + }, + + + /** + * Scale the abscissa of the image + * + * @param {Number} scaleX + */ + scaleX: function scaleX(_scaleX) { + var self = this; + var scaleY = self.image.scaleY; + + self.scale(_scaleX, isNumber(scaleY) ? scaleY : 1); + }, + + + /** + * Scale the ordinate of the image + * + * @param {Number} scaleY + */ + scaleY: function scaleY(_scaleY) { + var self = this; + var scaleX = self.image.scaleX; + + self.scale(isNumber(scaleX) ? scaleX : 1, _scaleY); + }, + + + /** + * Get the cropped area position and size data (base on the original image) + * + * @param {Boolean} isRounded (optional) + * @return {Object} data + */ + getData: function getData(isRounded) { + var self = this; + var options = self.options; + var image = self.image; + var canvas = self.canvas; + var cropBox = self.cropBox; + var ratio = void 0; + var data = void 0; + + if (self.ready && self.cropped) { + data = { + x: cropBox.left - canvas.left, + y: cropBox.top - canvas.top, + width: cropBox.width, + height: cropBox.height + }; + + ratio = image.width / image.naturalWidth; + + $.each(data, function (i, n) { + n /= ratio; + data[i] = isRounded ? Math.round(n) : n; + }); + } else { + data = { + x: 0, + y: 0, + width: 0, + height: 0 + }; + } + + if (options.rotatable) { + data.rotate = image.rotate || 0; + } + + if (options.scalable) { + data.scaleX = image.scaleX || 1; + data.scaleY = image.scaleY || 1; + } + + return data; + }, + + + /** + * Set the cropped area position and size with new data + * + * @param {Object} data + */ + setData: function setData(data) { + var self = this; + var options = self.options; + var image = self.image; + var canvas = self.canvas; + var cropBoxData = {}; + var rotated = void 0; + var isScaled = void 0; + var ratio = void 0; + + if ($.isFunction(data)) { + data = data.call(self.element); + } + + if (self.ready && !self.disabled && $.isPlainObject(data)) { + if (options.rotatable) { + if (isNumber(data.rotate) && data.rotate !== image.rotate) { + image.rotate = data.rotate; + rotated = true; + self.rotated = rotated; + } + } + + if (options.scalable) { + if (isNumber(data.scaleX) && data.scaleX !== image.scaleX) { + image.scaleX = data.scaleX; + isScaled = true; + } + + if (isNumber(data.scaleY) && data.scaleY !== image.scaleY) { + image.scaleY = data.scaleY; + isScaled = true; + } + } + + if (rotated) { + self.renderCanvas(); + } else if (isScaled) { + self.renderImage(); + } + + ratio = image.width / image.naturalWidth; + + if (isNumber(data.x)) { + cropBoxData.left = data.x * ratio + canvas.left; + } + + if (isNumber(data.y)) { + cropBoxData.top = data.y * ratio + canvas.top; + } + + if (isNumber(data.width)) { + cropBoxData.width = data.width * ratio; + } + + if (isNumber(data.height)) { + cropBoxData.height = data.height * ratio; + } + + self.setCropBoxData(cropBoxData); + } + }, + + + /** + * Get the container size data + * + * @return {Object} data + */ + getContainerData: function getContainerData() { + return this.ready ? this.container : {}; + }, + + + /** + * Get the image position and size data + * + * @return {Object} data + */ + getImageData: function getImageData() { + return this.loaded ? this.image : {}; + }, + + + /** + * Get the canvas position and size data + * + * @return {Object} data + */ + getCanvasData: function getCanvasData() { + var self = this; + var canvas = self.canvas; + var data = {}; + + if (self.ready) { + $.each(['left', 'top', 'width', 'height', 'naturalWidth', 'naturalHeight'], function (i, n) { + data[n] = canvas[n]; + }); + } + + return data; + }, + + + /** + * Set the canvas position and size with new data + * + * @param {Object} data + */ + setCanvasData: function setCanvasData(data) { + var self = this; + var canvas = self.canvas; + var aspectRatio = canvas.aspectRatio; + + if ($.isFunction(data)) { + data = data.call(self.$element); + } + + if (self.ready && !self.disabled && $.isPlainObject(data)) { + if (isNumber(data.left)) { + canvas.left = data.left; + } + + if (isNumber(data.top)) { + canvas.top = data.top; + } + + if (isNumber(data.width)) { + canvas.width = data.width; + canvas.height = data.width / aspectRatio; + } else if (isNumber(data.height)) { + canvas.height = data.height; + canvas.width = data.height * aspectRatio; + } + + self.renderCanvas(true); + } + }, + + + /** + * Get the crop box position and size data + * + * @return {Object} data + */ + getCropBoxData: function getCropBoxData() { + var self = this; + var cropBox = self.cropBox; + + return self.ready && self.cropped ? { + left: cropBox.left, + top: cropBox.top, + width: cropBox.width, + height: cropBox.height + } : {}; + }, + + + /** + * Set the crop box position and size with new data + * + * @param {Object} data + */ + setCropBoxData: function setCropBoxData(data) { + var self = this; + var cropBox = self.cropBox; + var aspectRatio = self.options.aspectRatio; + var widthChanged = void 0; + var heightChanged = void 0; + + if ($.isFunction(data)) { + data = data.call(self.$element); + } + + if (self.ready && self.cropped && !self.disabled && $.isPlainObject(data)) { + if (isNumber(data.left)) { + cropBox.left = data.left; + } + + if (isNumber(data.top)) { + cropBox.top = data.top; + } + + if (isNumber(data.width) && data.width !== cropBox.width) { + widthChanged = true; + cropBox.width = data.width; + } + + if (isNumber(data.height) && data.height !== cropBox.height) { + heightChanged = true; + cropBox.height = data.height; + } + + if (aspectRatio) { + if (widthChanged) { + cropBox.height = cropBox.width / aspectRatio; + } else if (heightChanged) { + cropBox.width = cropBox.height * aspectRatio; + } + } + + self.renderCropBox(); + } + }, + + + /** + * Get a canvas drawn the cropped image + * + * @param {Object} options (optional) + * @return {HTMLCanvasElement} canvas + */ + getCroppedCanvas: function getCroppedCanvas(options) { + var self = this; + + if (!self.ready || !window.HTMLCanvasElement) { + return null; + } + + if (!$.isPlainObject(options)) { + options = {}; + } + + if (!self.cropped) { + return getSourceCanvas(self.$clone[0], self.image, options); + } + + var data = self.getData(); + var originalWidth = data.width; + var originalHeight = data.height; + var aspectRatio = originalWidth / originalHeight; + var scaledWidth = void 0; + var scaledHeight = void 0; + var scaledRatio = void 0; + + if ($.isPlainObject(options)) { + scaledWidth = options.width; + scaledHeight = options.height; + + if (scaledWidth) { + scaledHeight = scaledWidth / aspectRatio; + scaledRatio = scaledWidth / originalWidth; + } else if (scaledHeight) { + scaledWidth = scaledHeight * aspectRatio; + scaledRatio = scaledHeight / originalHeight; + } + } + + // The canvas element will use `Math.Math.floor` on a float number, so Math.floor first + var canvasWidth = Math.floor(scaledWidth || originalWidth); + var canvasHeight = Math.floor(scaledHeight || originalHeight); + + var canvas = $('')[0]; + var context = canvas.getContext('2d'); + + canvas.width = canvasWidth; + canvas.height = canvasHeight; + + if (options.fillColor) { + context.fillStyle = options.fillColor; + context.fillRect(0, 0, canvasWidth, canvasHeight); + } + + // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.drawImage + var parameters = function () { + var source = getSourceCanvas(self.$clone[0], self.image, options); + var sourceWidth = source.width; + var sourceHeight = source.height; + var canvasData = self.canvas; + var params = [source]; + + // Source canvas + var srcX = data.x + canvasData.naturalWidth * (Math.abs(data.scaleX || 1) - 1) / 2; + var srcY = data.y + canvasData.naturalHeight * (Math.abs(data.scaleY || 1) - 1) / 2; + var srcWidth = void 0; + var srcHeight = void 0; + + // Destination canvas + var dstX = void 0; + var dstY = void 0; + var dstWidth = void 0; + var dstHeight = void 0; + + if (srcX <= -originalWidth || srcX > sourceWidth) { + srcX = 0; + srcWidth = 0; + dstX = 0; + dstWidth = 0; + } else if (srcX <= 0) { + dstX = -srcX; + srcX = 0; + dstWidth = Math.min(sourceWidth, originalWidth + srcX); + srcWidth = dstWidth; + } else if (srcX <= sourceWidth) { + dstX = 0; + dstWidth = Math.min(originalWidth, sourceWidth - srcX); + srcWidth = dstWidth; + } + + if (srcWidth <= 0 || srcY <= -originalHeight || srcY > sourceHeight) { + srcY = 0; + srcHeight = 0; + dstY = 0; + dstHeight = 0; + } else if (srcY <= 0) { + dstY = -srcY; + srcY = 0; + dstHeight = Math.min(sourceHeight, originalHeight + srcY); + srcHeight = dstHeight; + } else if (srcY <= sourceHeight) { + dstY = 0; + dstHeight = Math.min(originalHeight, sourceHeight - srcY); + srcHeight = dstHeight; + } + + // All the numerical parameters should be integer for `drawImage` (#476) + params.push(Math.floor(srcX), Math.floor(srcY), Math.floor(srcWidth), Math.floor(srcHeight)); + + // Scale destination sizes + if (scaledRatio) { + dstX *= scaledRatio; + dstY *= scaledRatio; + dstWidth *= scaledRatio; + dstHeight *= scaledRatio; + } + + // Avoid "IndexSizeError" in IE and Firefox + if (dstWidth > 0 && dstHeight > 0) { + params.push(Math.floor(dstX), Math.floor(dstY), Math.floor(dstWidth), Math.floor(dstHeight)); + } + + return params; + }(); + + context.imageSmoothingEnabled = !!options.imageSmoothingEnabled; + + if (options.imageSmoothingQuality) { + context.imageSmoothingQuality = options.imageSmoothingQuality; + } + + context.drawImage.apply(context, _toConsumableArray(parameters)); + + return canvas; + }, + + + /** + * Change the aspect ratio of the crop box + * + * @param {Number} aspectRatio + */ + setAspectRatio: function setAspectRatio(aspectRatio) { + var self = this; + var options = self.options; + + if (!self.disabled && !isUndefined(aspectRatio)) { + // 0 -> NaN + options.aspectRatio = Math.max(0, aspectRatio) || NaN; + + if (self.ready) { + self.initCropBox(); + + if (self.cropped) { + self.renderCropBox(); + } + } + } + }, + + + /** + * Change the drag mode + * + * @param {String} mode (optional) + */ + setDragMode: function setDragMode(mode) { + var self = this; + var options = self.options; + var croppable = void 0; + var movable = void 0; + + if (self.loaded && !self.disabled) { + croppable = mode === 'crop'; + movable = options.movable && mode === 'move'; + mode = croppable || movable ? mode : 'none'; + + self.$dragBox.data('action', mode).toggleClass('cropper-crop', croppable).toggleClass('cropper-move', movable); + + if (!options.cropBoxMovable) { + // Sync drag mode to crop box when it is not movable(#300) + self.$face.data('action', mode).toggleClass('cropper-crop', croppable).toggleClass('cropper-move', movable); + } + } + } + }; + + var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + var CLASS_HIDDEN = 'cropper-hidden'; + var REGEXP_DATA_URL = /^data:/; + var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg;base64,/; + + var Cropper = function () { + function Cropper(element, options) { + _classCallCheck(this, Cropper); + + var self = this; + + self.$element = $(element); + self.options = $.extend({}, DEFAULTS, $.isPlainObject(options) && options); + self.loaded = false; + self.ready = false; + self.completed = false; + self.rotated = false; + self.cropped = false; + self.disabled = false; + self.replaced = false; + self.limited = false; + self.wheeling = false; + self.isImg = false; + self.originalUrl = ''; + self.canvas = null; + self.cropBox = null; + self.pointers = {}; + self.init(); + } + + _createClass(Cropper, [{ + key: 'init', + value: function init() { + var self = this; + var $this = self.$element; + var url = void 0; + + if ($this.is('img')) { + self.isImg = true; + + // Should use `$.fn.attr` here. e.g.: "img/picture.jpg" + url = $this.attr('src'); + self.originalUrl = url; + + // Stop when it's a blank image + if (!url) { + return; + } + + // Should use `$.fn.prop` here. e.g.: "http://example.com/img/picture.jpg" + url = $this.prop('src'); + } else if ($this.is('canvas') && window.HTMLCanvasElement) { + url = $this[0].toDataURL(); + } + + self.load(url); + } + + // A shortcut for triggering custom events + + }, { + key: 'trigger', + value: function trigger(type, data) { + var e = $.Event(type, data); + + this.$element.trigger(e); + + return e; + } + }, { + key: 'load', + value: function load(url) { + var self = this; + var options = self.options; + var $this = self.$element; + + if (!url) { + return; + } + + self.url = url; + self.image = {}; + + if (!options.checkOrientation || !window.ArrayBuffer) { + self.clone(); + return; + } + + // XMLHttpRequest disallows to open a Data URL in some browsers like IE11 and Safari + if (REGEXP_DATA_URL.test(url)) { + if (REGEXP_DATA_URL_JPEG.test(url)) { + self.read(dataURLToArrayBuffer(url)); + } else { + self.clone(); + } + return; + } + + var xhr = new XMLHttpRequest(); + + xhr.onerror = $.proxy(function () { + self.clone(); + }, this); + + xhr.onload = function load() { + self.read(this.response); + }; + + if (options.checkCrossOrigin && isCrossOriginURL(url) && $this.prop('crossOrigin')) { + url = addTimestamp(url); + } + + xhr.open('get', url); + xhr.responseType = 'arraybuffer'; + xhr.withCredentials = $this.prop('crossOrigin') === 'use-credentials'; + xhr.send(); + } + }, { + key: 'read', + value: function read(arrayBuffer) { + var self = this; + var options = self.options; + var orientation = getOrientation(arrayBuffer); + var image = self.image; + var rotate = 0; + var scaleX = 1; + var scaleY = 1; + + if (orientation > 1) { + self.url = arrayBufferToDataURL(arrayBuffer); + + switch (orientation) { + // flip horizontal + case 2: + scaleX = -1; + break; + + // rotate left 180° + case 3: + rotate = -180; + break; + + // flip vertical + case 4: + scaleY = -1; + break; + + // flip vertical + rotate right 90° + case 5: + rotate = 90; + scaleY = -1; + break; + + // rotate right 90° + case 6: + rotate = 90; + break; + + // flip horizontal + rotate right 90° + case 7: + rotate = 90; + scaleX = -1; + break; + + // rotate left 90° + case 8: + rotate = -90; + break; + + default: + } + } + + if (options.rotatable) { + image.rotate = rotate; + } + + if (options.scalable) { + image.scaleX = scaleX; + image.scaleY = scaleY; + } + + self.clone(); + } + }, { + key: 'clone', + value: function clone() { + var self = this; + var options = self.options; + var $this = self.$element; + var url = self.url; + var crossOrigin = ''; + var crossOriginUrl = void 0; + + if (options.checkCrossOrigin && isCrossOriginURL(url)) { + crossOrigin = $this.prop('crossOrigin'); + + if (crossOrigin) { + crossOriginUrl = url; + } else { + crossOrigin = 'anonymous'; + + // Bust cache (#148) when there is not a "crossOrigin" property + crossOriginUrl = addTimestamp(url); + } + } + + self.crossOrigin = crossOrigin; + self.crossOriginUrl = crossOriginUrl; + + var image = document.createElement('img'); + + if (crossOrigin) { + image.crossOrigin = crossOrigin; + } + + image.src = crossOriginUrl || url; + + var $clone = $(image); + + self.$clone = $clone; + + if (self.isImg) { + if ($this[0].complete) { + self.start(); + } else { + $this.one('load', $.proxy(self.start, this)); + } + } else { + $clone.one('load', $.proxy(self.start, this)).one('error', $.proxy(self.stop, this)).addClass('cropper-hide').insertAfter($this); + } + } + }, { + key: 'start', + value: function start() { + var self = this; + var $clone = self.$clone; + var $image = self.$element; + + if (!self.isImg) { + $clone.off('error', self.stop); + $image = $clone; + } + + getImageSize($image[0], function (naturalWidth, naturalHeight) { + $.extend(self.image, { + naturalWidth: naturalWidth, + naturalHeight: naturalHeight, + aspectRatio: naturalWidth / naturalHeight + }); + + self.loaded = true; + self.build(); + }); + } + }, { + key: 'stop', + value: function stop() { + var self = this; + + self.$clone.remove(); + self.$clone = null; + } + }, { + key: 'build', + value: function build() { + var self = this; + var options = self.options; + var $this = self.$element; + var $clone = self.$clone; + + if (!self.loaded) { + return; + } + + // Unbuild first when replace + if (self.ready) { + self.unbuild(); + } + + var $cropper = $(TEMPLATE); + var $cropBox = $cropper.find('.cropper-crop-box'); + var $face = $cropBox.find('.cropper-face'); + + // Create cropper elements + self.$container = $this.parent(); + self.$cropper = $cropper; + self.$canvas = $cropper.find('.cropper-canvas').append($clone); + self.$dragBox = $cropper.find('.cropper-drag-box'); + self.$cropBox = $cropBox; + self.$viewBox = $cropper.find('.cropper-view-box'); + self.$face = $face; + + // Hide the original image + $this.addClass(CLASS_HIDDEN).after($cropper); + + // Show the clone image if is hidden + if (!self.isImg) { + $clone.removeClass('cropper-hide'); + } + + self.initPreview(); + self.bind(); + + options.aspectRatio = Math.max(0, options.aspectRatio) || NaN; + options.viewMode = Math.max(0, Math.min(3, Math.round(options.viewMode))) || 0; + + self.cropped = options.autoCrop; + + if (options.autoCrop) { + if (options.modal) { + self.$dragBox.addClass('cropper-modal'); + } + } else { + $cropBox.addClass(CLASS_HIDDEN); + } + + if (!options.guides) { + $cropBox.find('.cropper-dashed').addClass(CLASS_HIDDEN); + } + + if (!options.center) { + $cropBox.find('.cropper-center').addClass(CLASS_HIDDEN); + } + + if (options.cropBoxMovable) { + $face.addClass('cropper-move').data('action', 'all'); + } + + if (!options.highlight) { + $face.addClass('cropper-invisible'); + } + + if (options.background) { + $cropper.addClass('cropper-bg'); + } + + if (!options.cropBoxResizable) { + $cropBox.find('.cropper-line, .cropper-point').addClass(CLASS_HIDDEN); + } + + self.setDragMode(options.dragMode); + self.render(); + self.ready = true; + self.setData(options.data); + + // Trigger the ready event asynchronously to keep `data('cropper')` is defined + self.completing = setTimeout(function () { + if ($.isFunction(options.ready)) { + $this.one('ready', options.ready); + } + + self.trigger('ready'); + self.trigger('crop', self.getData()); + self.completed = true; + }, 0); + } + }, { + key: 'unbuild', + value: function unbuild() { + var self = this; + + if (!self.ready) { + return; + } + + if (!self.completed) { + clearTimeout(self.completing); + } + + self.ready = false; + self.completed = false; + self.initialImage = null; + + // Clear `initialCanvas` is necessary when replace + self.initialCanvas = null; + self.initialCropBox = null; + self.container = null; + self.canvas = null; + + // Clear `cropBox` is necessary when replace + self.cropBox = null; + self.unbind(); + + self.resetPreview(); + self.$preview = null; + + self.$viewBox = null; + self.$cropBox = null; + self.$dragBox = null; + self.$canvas = null; + self.$container = null; + + self.$cropper.remove(); + self.$cropper = null; + } + }], [{ + key: 'setDefaults', + value: function setDefaults(options) { + $.extend(DEFAULTS, $.isPlainObject(options) && options); + } + }]); + + return Cropper; + }(); + + $.extend(Cropper.prototype, render); + $.extend(Cropper.prototype, preview); + $.extend(Cropper.prototype, events); + $.extend(Cropper.prototype, handlers); + $.extend(Cropper.prototype, change); + $.extend(Cropper.prototype, methods); + + var NAMESPACE = 'cropper'; + var OtherCropper = $.fn.cropper; + + $.fn.cropper = function jQueryCropper(option) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var result = void 0; + + this.each(function (i, element) { + var $this = $(element); + var data = $this.data(NAMESPACE); + + if (!data) { + if (/destroy/.test(option)) { + return; + } + + var options = $.extend({}, $this.data(), $.isPlainObject(option) && option); + $this.data(NAMESPACE, data = new Cropper(element, options)); + } + + if (typeof option === 'string') { + var fn = data[option]; + + if ($.isFunction(fn)) { + result = fn.apply(data, args); + } + } + }); + + return typeof result !== 'undefined' ? result : this; + }; + + $.fn.cropper.Constructor = Cropper; + $.fn.cropper.setDefaults = Cropper.setDefaults; + + // No conflict + $.fn.cropper.noConflict = function noConflict() { + $.fn.cropper = OtherCropper; + return this; + }; + + exports('cropper', $.fn.cropper); +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/design.js b/demo/webman/backend/plugin/admin/public/component/pear/module/design.js new file mode 100644 index 0000000000000000000000000000000000000000..5029d997f38f277d3d256f4b8c6a7b1f24dc7b51 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/design.js @@ -0,0 +1,467 @@ +layui.define(['layer', 'form'], function(exports) { + var layer = layui.layer, + form = layui.form, + $ = layui.$, + key = '', + allJS = '', + allHtml = ''; + let module = ["form"]; + delHtml() + $('button').on('click', function() { + var _this = $(this), + size = _this.data('size'), + type = _this.data('type'), + html = ''; + key = randStrName(); + switch (type) { + case 'text': + html = input(type, size) + break; + case 'password': + html = input(type, size) + break; + case 'select': + html = select(size) + break; + case 'checkbox_a': + html = checkbox_a(size) + break; + case 'checkbox_b': + html = checkbox_b(size) + break; + case 'radio': + html = radio(size) + break; + case 'textarea': + html = textarea(size) + break; + case 'icon': + html = icon(size) + $('form').append(html); + form.render(); + setHtml(html); + layui.use(['iconPicker'], function() { + layui.iconPicker.render({ + elem: "#" + key, + type: "fontClass", + }); + }); + if (module.indexOf('iconPicker') === -1) module.push('iconPicker'); + allJS += ' // 图标选择\n' + + ' layui.iconPicker.render({\n' + + ' elem: "#' + key + '",\n' + + ' type: "fontClass",\n' + + ' });\n'; + $('.js-show').text(jscode()) + return; + case 'multiSelect': + html = multiSelect(size) + $('form').append(html); + form.render(); + setHtml(html); + layui.use(['xmSelect'], function() { + layui.xmSelect.render({ + el: "#" + key, + name: key, + data: [{value: 1, name: "深圳"},{value: 2, name: "上海"},{value: 3, name: "广州"}], + }); + }); + if (module.indexOf('xmSelect') === -1) module.push('xmSelect'); + allJS += ' // 下拉多选\n' + + ' layui.xmSelect.render({\n' + + ' el: "#' + key + '",\n' + + ' name: "' + key + '",\n' + + ' data: [{value: 1, name: "深圳"},{value: 2, name: "上海"},{value: 3, name: "广州"}],\n' + + ' });\n'; + $('.js-show').text(jscode()) + return; + case 'tree': + html = tree(size) + $('form').append(html); + form.render(); + setHtml(html); + layui.use(['xmSelect'], function() { + layui.xmSelect.render({ + el: "#" + key, + name: key, + tree: {show: true}, + data: [{value: 1, name: "广东省", children:[{value: 2, name: "深圳"},{value: 3, name: "广州"}]},{value: 4, name: "福建省", children:[{value: 5, name: "厦门"},{value: 6, name: "福州"}]}], + }); + }); + if (module.indexOf('xmSelect') === -1) module.push('xmSelect'); + allJS += ' // 树多选\n' + + ' layui.xmSelect.render({\n' + + ' el: "#' + key + '",\n' + + ' name: "' + key + '",\n' + + ' tree: {show: true},\n' + + ' data: [{value: 1, name: "广东省", children:[{value: 2, name: "深圳"},{value: 3, name: "广州"}]},{value: 4, name: "福建省", children:[{value: 5, name: "厦门"},{value: 6, name: "福州"}]}],\n' + + ' });\n'; + $('.js-show').text(jscode()) + return; + case 'treeSelectOne': + html = treeSelectOne(size) + $('form').append(html); + form.render(); + setHtml(html); + layui.use(['xmSelect'], function() { + layui.xmSelect.render({ + el: "#" + key, + name: key, + model: {"icon":"hidden","label":{"type":"text"}}, + clickClose: true, + radio: true, + tree: {show: true, strict: false, clickCheck: true, clickExpand: false}, + data: [{value: 1, name: "广东省", children:[{value: 2, name: "深圳"},{value: 3, name: "广州"}]},{value: 4, name: "福建省", children:[{value: 5, name: "厦门"},{value: 6, name: "福州"}]}], + }); + }); + if (module.indexOf('xmSelect') === -1) module.push('xmSelect'); + allJS += ' // 树多选\n' + + ' layui.xmSelect.render({\n' + + ' el: "#' + key + '",\n' + + ' name: "' + key + '",\n' + + ' model: {"icon":"hidden","label":{"type":"text"}},\n' + + ' clickClose: true,\n' + + ' radio: true,\n' + + ' tree: {show: true, strict: false, clickCheck: true, clickExpand: false},\n' + + ' data: [{value: 1, name: "广东省", children:[{value: 2, name: "深圳"},{value: 3, name: "广州"}]},{value: 4, name: "福建省", children:[{value: 5, name: "厦门"},{value: 6, name: "福州"}]}],\n' + + ' });\n'; + $('.js-show').text(jscode()) + return; + case 'upload': + html = upload(size) + $('form').append(html); + form.render(); + setHtml(html); + layui.use(['upload'], function() { + let input = layui.$('#' + key).prev(); + input.prev().html(layui.util.escape(input.val())); + layui.$("#attachment-choose-" + key).on('click', function() { + parent.layer.open({ + type: 2, + title: "选择附件", + content: "/app/admin/upload/attachment", + area: ["95%", "90%"], + success: function (layero, index) { + parent.layui.$("#layui-layer" + index).data("callback", function (data) { + input.val(data.url).prev().html(layui.util.escape(data.url)); + }); + } + }); + }); + layui.upload.render({ + elem: "#" + key, + url: "/app/admin/upload/file", + accept: "file", + field: "__file__", + done: function (res) { + this.item.prev().val(res.data.url).prev().html(layui.util.escape(res.data.url)); + } + }); + }); + if (module.indexOf('upload') === -1) module.push('upload'); + if (module.indexOf('util') === -1) module.push('util'); + allJS += ' // 上传文件\n' + + ' layui.use([\'upload\'], function() {\n' + + ' let input = layui.$("#'+key+'").prev();\n' + + ' input.prev().html(layui.util.escape(input.val()));\n' + + ' layui.$("#attachment-choose-'+key+'").on("click", function() {\n' + + ' parent.layer.open({\n' + + ' type: 2,\n' + + ' title: "选择附件",\n' + + ' content: "/app/admin/upload/attachment",\n' + + ' area: ["95%", "90%"],\n' + + ' success: function (layero, index) {\n' + + ' parent.layui.$("#layui-layer" + index).data("callback", function (data) {\n' + + ' input.val(data.url).prev().html(layui.util.escape(data.url));\n' + + ' });\n' + + ' }\n' + + ' });\n' + + ' });\n' + + ' });\n' + + ' layui.upload.render({\n' + + ' elem: "#' + key + '",\n' + + ' url: "/app/admin/upload/file",\n' + + ' accept: "file",\n' + + ' field: "__file__",\n' + + ' done: function (res) {\n' + + ' this.item.prev().val(res.data.url).prev().html(layui.util.escape(res.data.url));\n' + + ' }\n' + + ' });\n'; + $('.js-show').text(jscode()) + return; + case 'uploadImg': + html = uploadImg(size) + $('form').append(html); + form.render(); + setHtml(html); + layui.use(['upload'], function() { + let input = layui.$('#' + key).prev(); + input.prev().attr('src', input.val()); + layui.$('#attachment-choose-' + key).on('click', function() { + parent.layer.open({ + type: 2, + title: '选择附件', + content: '/app/admin/upload/attachment?ext=jpg,jpeg,png,gif,bmp', + area: ["95%", "90%"], + success: function (layero, index) { + parent.layui.$("#layui-layer" + index).data("callback", function (data) { + input.val(data.url).prev().attr("src", data.url); + }); + } + }); + }); + layui.upload.render({ + elem: "#" + key, + url: "/app/admin/upload/image", + acceptMime: "image/gif,image/jpeg,image/jpg,image/png", + field: "__file__", + done: function (res) { + this.item.prev().val(res.data.url).prev().attr('src', res.data.url); + } + }); + }); + if (module.indexOf('upload') === -1) module.push('upload'); + allJS += ' // 上传图片\n' + + ' layui.use([\'upload\'], function() {\n' + + ' let input = layui.$("#'+key+'").prev();\n' + + ' input.prev().attr(\'src\', input.val());\n' + + ' layui.$("#attachment-choose-'+key+'").on("click", function() {\n' + + ' parent.layer.open({\n' + + ' type: 2,\n' + + ' title: "选择附件",\n' + + ' content: "/app/admin/upload/attachment?ext=jpg,jpeg,png,gif,bmp",\n' + + ' area: ["95%", "90%"],\n' + + ' success: function (layero, index) {\n' + + ' parent.layui.$("#layui-layer" + index).data("callback", function (data) {\n' + + ' input.val(data.url).prev().attr("src", data.url);\n' + + ' });\n' + + ' }\n' + + ' });\n' + + ' });\n' + + ' layui.upload.render({\n' + + ' elem: "#' + key + '",\n' + + ' url: "/app/admin/upload/image",\n' + + ' acceptMime: "image/gif,image/jpeg,image/jpg,image/png",\n' + + ' field: "__file__",\n' + + ' done: function (res) {\n' + + ' this.item.prev().val(res.data.url).prev().attr(\'src\', res.data.url);\n' + + ' }\n' + + ' });\n' + + ' });\n'; + $('.js-show').text(jscode()) + return; + case 'submit': + html = submits(size) + break; + case 'del': + $('form').html("\n") + delHtml() + return false; + default: + layer.msg('类型错误', { + icon: 2 + }) + } + + $('form').append(html); + form.render(); + setHtml(html); + $('.js-show').text(jscode()) + }) + + function delHtml() { + allHtml = ''; + allJS = ''; + $('.code-show').text(''); + $('.js-show').text(jscode()); + } + + function setHtml(html) { + allHtml += html; + $('.code-show').text('
                                                                              \n' + allHtml + '
                                                                              ') + } + + function icon(size) { + var html = '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function multiSelect(size) { + var html = '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + '
                                                                              \n' + + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function tree(size) { + var html = '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + '
                                                                              \n' + + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function treeSelectOne(size) { + var html = '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + '
                                                                              \n' + + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function upload(size) { + let uploadWords = size === "block" ? "上传文件" : "上传"; + let selectWords = size === "block" ? "选择文件" : "选择"; + var html = '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function uploadImg(size) { + let uploadWords = size === "block" ? "上传文件" : "上传"; + let selectWords = size === "block" ? "选择图片" : "选择"; + var html = '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function input(type, size) { + var name = type === 'text' ? '输入框' : (type === 'password' ? '密码框' : ''); + var html = '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function select(size) { + var html = '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function checkbox_a(size) { + var html = '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + ' \n' + + ' \n' + + ' \n' + + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function checkbox_b(size) { + var html = '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function radio(size) { + var html = '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + ' \n' + + ' \n' + + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function textarea(size) { + var html = '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + ' \n' + + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function submits(size) { + var html = '
                                                                              \n' + + '
                                                                              \n' + + ' \n' + //变更 + ' \n' + //变更 + '
                                                                              \n' + + '
                                                                              \n'; + return html; + } + + function jscode() { + var html = ''; + return html; + } + + function randStrName() { + return 'a' + Math.random().toString(36).substr(9); + } + form.on('submit(formDemo)', function(data) { + layer.msg(JSON.stringify(data.field)); + return false; + }); + exports('design', {}); +}); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/drawer.js b/demo/webman/backend/plugin/admin/public/component/pear/module/drawer.js new file mode 100644 index 0000000000000000000000000000000000000000..a95e41ac375dae0e25831131a97eda3488c45ac8 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/drawer.js @@ -0,0 +1,420 @@ +layui.define(['jquery', 'element', 'layer', 'loading'], function (exports) { + "use strict"; + + /** + * Drawer component + * */ + var MOD_NAME = 'drawer', + $ = layui.jquery, + element = layui.element, + layer = layui.layer, + loading = layui.loading; + + + var drawer = new function () { + + /** + * open drawer + * */ + this.open = function (option) { + // 默认使用 legacy 模式 + if (option.legacy === undefined) { + option.legacy = true; + }; + if (option.legacy) { + var obj = new mSlider({ + target: option.target, + dom: option.dom, + direction: option.direction, + distance: option.distance, + time: option.time ? option.time : 0, + maskClose: option.maskClose, + callback: option.success + }); + obj.open(); + return obj; + } else { + return layerDrawer(option); + } + } + this.title = layer.title; + this.style = layer.style; + this.close = layer.close; + this.closeAll = layer.closeAll; + } + + /** + * + * 封装 layer.open + * type,anim,move,fixed不可用,其它参数和 layer.open 一致 + * @param {LayerOption} option + * @returns 原生 layer 的 index + */ + function layerDrawer(option) { + var opt = normalizeOption(option) + if (opt.target) appendToTarget(opt); + if (opt.url) loadFragment(opt); + var layerIndex = layer.open(opt); + + return layerIndex; + } + + /** + * 加载 HTML 片段到 layer content + * @param {*} option + */ + function loadFragment(option) { + option.success = Aspect(option.success, function (layero, index) { + var layerID = "#" + layero.attr("id"); + loading.block({ + type: 1, + elem: layerID, + msg: '' + }); + $.ajax({ + url: option.url, + dataType: "html", + success: function (result) { + layero.children('.layui-layer-content').html(result); + loading.blockRemove(layerID); + } + }) + }) + } + + /** + *将 layer 挂载到指定节点 + * @param {object} opt + */ + function appendToTarget(opt) { + var targetDOM = $(opt.target); + var contentDOM = $(opt.content); + contentDOM.appendTo(targetDOM); + opt.skin = getDrawerAnimationClass(opt.offset, true); + opt.offset = calcOffset(opt.offset, opt.area, targetDOM); + // 处理关闭后偶现 DOM 仍显示的问题,layer 的 BUG + opt.end = Aspect(opt.end, function () { + contentDOM.css("display", "none"); + }) + if (opt.shade) { + opt.success = Aspect(opt.success, function (layero, index) { + var shadeDOM = $("#layui-layer-shade" + index); + shadeDOM.css("position", "absolute"); + shadeDOM.appendTo(layero.parent()); + }) + } + } + + /** + * 规格化 layer.open 选项,兼容原版 Drawer 所有选项 + * @param {LayerOption} option layer.open 的选项 + * @returns 规格化后的 layer.open 选项 + */ + function normalizeOption(option) { + if (option.direction && !option.offset) { + if (option.direction === "right") { + option.offset = "r"; + } else if (option.direction === "left") { + option.offset = "l"; + } else if (option.direction === "top") { + option.offset = "t"; + } else if (option.direction === "bottom") { + option.offset = "b"; + } else { + option.offset = "r"; + } + } + if (option.distance && !option.area) { + option.area = option.distance; + } + if (option.dom && !option.content) { + option.content = $(option.dom); + } + if (option.maskClose && option.shadeClose === undefined) { + option.shadeClose = (option.maskClose + "").toString() !== "false" ? true : false; + } + + option.type = 1 + option.anim = -1; + option.move = false; + option.fixed = true; + if (option.iframe) { + option.type = 2; + option.content = option.iframe; + } + if (option.offset === undefined) option.offset = "r"; + option.area = calcDrawerArea(option.offset, option.area); + if (option.title === undefined) option.title = false; + if (option.closeBtn === undefined) option.closeBtn = false; + if (option.shade === undefined) option.shade = 0.3; + if (option.shadeClose === undefined) option.shadeClose = true; + if (option.skin === undefined) option.skin = getDrawerAnimationClass(option.offset); + if (option.resize === undefined) option.resize = false; + if (option.success === undefined) option.success = function () { }; // 处理遮罩需要 + if (option.end === undefined) option.end = function () { }; + + return option; + } + + /** + * 计算抽屉宽高 + * @param {string} offset 抽屉方向 l = 左, r = 右, t = 上, b = 下 + * @param {string[] | string} drawerArea 抽屉大小,字符串数组格式:[width, height],字符串格式:百分比或单位 px。 + * @returns 抽屉宽高数组 + */ + function calcDrawerArea(offset, drawerArea) { + if (drawerArea instanceof Array) { + return drawerArea; + } + if (drawerArea === undefined || drawerArea === "auto") { + drawerArea = "30%"; + } + if (offset === "l" || offset === "r") { + return [drawerArea, "100%"]; + } else if (offset === "t" || offset === "b") { + return ["100%", drawerArea]; + } + return [drawerArea, "100%"]; + } + + /** + * 获取抽屉动画类 + * @param {string} offset 抽屉方向 + * @param {boolean} 是否 absolute 布局 + * @returns 抽屉入场动画类 + */ + function getDrawerAnimationClass(offset, isAbsolute) { + var positionAbsoluteClass = "position-absolute "; + var prefixClass = "pear-drawer pear-drawer-anim layui-anim layer-anim-"; + var suffix = "rl"; + + if (isAbsolute) { + prefixClass = positionAbsoluteClass + prefixClass; + } + if (offset === "l") { + suffix = "lr"; + } else if (offset === "r") { + suffix = "rl"; + } else if (offset === "t") { + suffix = "tb"; + } else if (offset === "b") { + suffix = "bt"; + } + return prefixClass + suffix; + } + + /** + * 指定挂载容器重新计算 offset + * @param {*} offset 位置 + * @param {*} area 范围大小 + * @param {*} targetEl 挂载节点 + * @returns 包含抽屉位置信息的数组,[top,left] + */ + function calcOffset(offset, area, targetEl) { + if (offset === undefined || offset === "l" || offset === "t") { + offset = "lt"; + } else if (offset === "r") { + var left; + if (area instanceof Array) { + area = area[0]; + } + if (area.indexOf("%") != -1) { + left = targetEl.innerWidth() * (1 - area.replace("%", "") / 100); + } else { + left = targetEl.innerWidth() - area; + } + offset = [0, left]; + } else if (offset === "b") { + var top; + if (area instanceof Array) { + area = area[1]; + } + if (area.indexOf("%") != -1) { + top = targetEl.innerHeight() * (1 - area.replace("%", "") / 100); + } else { + top = targetEl.innerHeight() - area; + } + offset = [top, 0]; + } + + return offset; + } + + /** + * 简易的切面 + * @param {Function} func 被通知的对象,原函数 + * @param {Function | undefined} before 前置通知 + * @param {Function | undefined} after 后置通知 + * @returns 代理函数 + */ + function Aspect(target, before, after) { + function proxyFunc() { + if (before && typeof before === "function") { + before.apply(this, arguments) + } + target.apply(this, arguments); + if (after && typeof after === "function") { + after.apply(this, arguments) + } + } + return proxyFunc; + } + + exports(MOD_NAME, drawer); +}); + +/** + * 源码 + * */ +(function (b, c) { + function a(d) { + this.opts = { + "target": d.target || "body", + "direction": d.direction || "left", + "distance": d.distance || "60%", + "dom": this.Q(d.dom), + "time": d.time || "", + "maskClose": (d.maskClose + "").toString() !== "false" ? true : false, + "callback": d.callback || "" + }; + this.rnd = this.rnd(); + this.target = this.opts.target; + this.dom = this.opts.dom[0]; + this.wrap = ""; + this.inner = ""; + this.mask = ""; + this.init() + } + a.prototype = { + Q: function (d) { + return document.querySelectorAll(d) + }, + isMobile: function () { + return navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i) ? true : false + }, + addEvent: function (f, e, d) { + if (f.attachEvent) { + f.attachEvent("on" + e, d) + } else { + f.addEventListener(e, d, false) + } + }, + rnd: function () { + return Math.random().toString(36).substr(2, 6) + }, + init: function () { + var g = this; + if (!g.dom) { + console.log("未正确绑定弹窗容器"); + return + } + g.dom.style.display = "block"; // 兼容 layer 捕获层 + var d = document.createElement("div"); + var e = document.createElement("div"); + var f = document.createElement("div"); + d.setAttribute("class", "mSlider-main ms-" + g.rnd); + e.setAttribute("class", "mSlider-inner"); + f.setAttribute("class", "mSlider-mask"); + g.Q(g.target)[0].appendChild(d); + g.Q(".ms-" + g.rnd)[0].appendChild(e); + g.Q(".ms-" + g.rnd)[0].appendChild(f); + g.wrap = g.Q(".ms-" + g.rnd)[0]; + g.inner = g.Q(".ms-" + g.rnd + " .mSlider-inner")[0]; + g.mask = g.Q(".ms-" + g.rnd + " .mSlider-mask")[0]; + g.inner.appendChild(g.dom); + switch (g.opts.direction) { + case "top": + g.top = "0"; + g.left = "0"; + g.width = "100%"; + g.height = g.opts.distance; + g.translate = "0,-100%,0"; + break; + case "bottom": + g.bottom = "0"; + g.left = "0"; + g.width = "100%"; + g.height = g.opts.distance; + g.translate = "0,100%,0"; + break; + case "right": + g.top = "0"; + g.right = "0"; + g.width = g.opts.distance; + g.height = document.documentElement.clientHeight + "px"; + g.translate = "100%,0,0"; + break; + default: + g.top = "0"; + g.left = "0"; + g.width = g.opts.distance; + g.height = document.documentElement.clientHeight + "px"; + g.translate = "-100%,0,0" + } + g.wrap.style.display = "none"; + g.wrap.style.position = (g.target === "body" ? "fixed" : "absolute"); + g.wrap.style.top = "0"; + g.wrap.style.left = "0"; + g.wrap.style.width = "100%"; + g.wrap.style.height = "100%"; + g.wrap.style.zIndex = 9999999; + g.inner.style.position = "absolute"; + g.inner.style.top = g.top; + g.inner.style.bottom = g.bottom; + g.inner.style.left = g.left; + g.inner.style.right = g.right; + g.inner.style.width = g.width; + g.inner.style.height = (g.target === "body" ? g.height : "100%"); + g.inner.style.backgroundColor = "#fff"; + g.inner.style.transform = "translate3d(" + g.translate + ")"; + g.inner.style.webkitTransition = "all .2s ease-out"; + g.inner.style.transition = "all .2s ease-out"; + g.inner.style.zIndex = 10000000; + g.mask.style.width = "100%"; + g.mask.style.height = "100%"; + g.mask.style.opacity = "0.1"; + g.mask.style.backgroundColor = "black"; + g.mask.style.zIndex = "9999998"; + g.mask.style.webkitBackfaceVisibility = "hidden"; + g.events() + }, + open: function () { + var d = this; + d.wrap.style.display = "block"; + setTimeout(function () { + d.inner.style.transform = "translate3d(0,0,0)"; + d.inner.style.webkitTransform = "translate3d(0,0,0)"; + d.mask.style.opacity = 0.1 + }, 30); + if (d.opts.time) { + d.timer = setTimeout(function () { + d.close() + }, d.opts.time) + } + }, + close: function () { + var d = this; + d.timer && clearTimeout(d.timer); + d.inner.style.webkitTransform = "translate3d(" + d.translate + ")"; + d.inner.style.transform = "translate3d(" + d.translate + ")"; + d.mask.style.opacity = 0; + setTimeout(function () { + d.wrap.style.display = "none"; + d.timer = null; + d.opts.callback && d.opts.callback() + }, 300) + }, + events: function () { + var d = this; + d.addEvent(d.mask, "touchmove", function (f) { + f.preventDefault() + }); + d.addEvent(d.mask, (d.isMobile() ? "touchend" : "click"), function (f) { + if (d.opts.maskClose) { + d.close() + } + }) + } + }; + b.mSlider = a +})(window); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/dtree.js b/demo/webman/backend/plugin/admin/public/component/pear/module/dtree.js new file mode 100644 index 0000000000000000000000000000000000000000..e4f2d2dd8670722d69846298c6d7f676082b03c0 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/dtree.js @@ -0,0 +1,5530 @@ +layui.define(['jquery','layer','form'], function(exports) { + var $ = layui.$, + layer = layui.layer, + form = layui.form; + + // 树的公共定义样式汇总 + var LI_NAV_CHILD = "dtree-nav-ul-sid", LI_NAV_ITEM = "dtree-nav-item", + LI_DIV_ITEM = "dtree-nav-div", DTREEFONTSPECIAL="dtreefont-special", NONETITLE="dtree-none-text", + LI_DIV_MENUBAR = "dtree-menubar", + LI_DIV_TOOLBAR = "dtree-toolbar", TOOLBAR_TOOL = "dtree-toolbar-tool", TOOLBAR_TOOL_EM = "dtree-toolbar-fixed", + LI_DIV_CHECKBAR = "dtree-nav-checkbox-div", + LI_CLICK_CHECKBAR = "d-click-checkbar", //绑定点击复选框时需要用到 + LI_DIV_TEXT_CLASS = "t-click", UL_ROOT="dtree", + LI_NAV_FIRST_LINE = "dtree-nav-first-line", LI_NAV_LINE = "dtree-nav-line", LI_NAV_LAST_LINE = "dtree-nav-last-line"; + + + // 树的公共指定 + var NAV_THIS = "dtree-nav-this", //当前节点 + NAV_SHOW = "dtree-nav-show", //显示子节点 + NAV_HIDE = "dtree-nav-hide", //隐藏节点 + NAV_DIS = "dtree-disabled", //禁用节点 + ICON_HIDE = "dtree-icon-hide", //隐藏图标 + $BODY = $("body"), //body选择器 + $WIN = $(window), //window窗口 + $DOC = $(document), //当前文档 + MOD_NAME = "dtree", //模块名称 + VERSION = "v2.5.8", //版本 + OPTIONS = {}, //全局属性配置 + DTrees = {}; //当前被实例化的树的集合 + + // 树的自定义图标 + var DTREEFONT = "dtreefont", //默认使用图标字体 + LI_DIV_CHECKBAR_ON = "dtree-icon-fuxuankuangxuanzhong", //复选框选中图标 + LI_DIV_CHECKBAR_OUT = "dtree-icon-fuxuankuang", //复选框未选中图标 + LI_DIV_CHECKBAR_NOALL = "dtree-icon-fuxuankuang-banxuan", //复选框半选图标 + LI_DIV_MENUBAR_DOWN = "dtree-icon-move-down", //menubar的展开全部的图标 + LI_DIV_MENUBAR_UP = "dtree-icon-move-up", //menubar的收缩全部的图标 + LI_DIV_MENUBAR_REFRESH = "dtree-icon-refresh", //menubar的刷新图标 + LI_DIV_MENUBAR_CHECKALL = "dtree-icon-roundcheckfill", //menubar的全选图标 + LI_DIV_MENUBAR_UNCHECKALL = "dtree-icon-roundclosefill", //menubar的全不选图标 + LI_DIV_MENUBAR_INVERTALL = "dtree-icon-roundcheck", //menubar的反选图标 + LI_DIV_MENUBAR_DELETE = "dtree-icon-delete1", //menubar的删除图标 + LI_DIV_MENUBAR_SEARCH = "dtree-icon-search_list_light", //menubar的搜索图标 + LI_DIV_TOOLBAR_PULLDOWN = "dtree-icon-pulldown", //toolbar的展开图标 + LI_DIV_TOOLBAR_PULLUP = "dtree-icon-pullup", //toolbar的收缩图标 + LI_DIV_TOOLBAR_ADD = "dtree-icon-roundadd", //toolbar的新增图标 + LI_DIV_TOOLBAR_EDIT = "dtree-icon-bianji", //toolbar的编辑图标 + LI_DIV_TOOLBAR_DEL = "dtree-icon-roundclose"; //toolbar的删除图标 + + // 树的非叶子节点图标集合 + var nodeIconArray = { + "-1": {"open": "dtree-icon-null-open", "close": "dtree-icon-null-close"}, //未指定 + "0" : {"open": "dtree-icon-wenjianjiazhankai", "close": "dtree-icon-weibiaoti5"}, //文件夹(二级图标默认样式) + "1" : {"open": "dtree-icon-jian", "close": "dtree-icon-jia"}, //+-图标(一级图标默认样式) + "2" : {"open": "dtree-icon-xiangxia1", "close": "dtree-icon-xiangyou"} //箭头图标 + }; + + // 树的叶子节点图标集合 + var leafIconArray = { + "-1": "dtree-icon-null", //未指定 + "0" : "dtree-icon-weibiaoti5", //文件夹 + "1" : "dtree-icon-yonghu", //人员 + "2" : "dtree-icon-fenzhijigou", //机构 + "3" : "dtree-icon-fenguangbaobiao", //报表 + "4" : "dtree-icon-xinxipilu", //信息 + "5" : "dtree-icon-shuye1", //叶子(二级图标默认样式) + "6" : "dtree-icon-caidan_xunzhang", //勋章 + "7" : "dtree-icon-normal-file", //文件 + "8" : "dtree-icon-dian", //小圆点(一级图标默认样式) + "9" : "dtree-icon-set-sm", //齿轮 + "10" : "dtree-icon-rate" //星星 + }; + + // 树的自定义样式 + var DTREE = "dtree-", //自定义样式前缀 + ITEMTHIS = "-item-this", //自定义样式当前行选中后缀 + ITEM = "-item", //自定义样式当前行后缀 + DFONT = "-dtreefont", //自定义样式图标样式后缀 + FICON = "-ficon", //自定义样式一级图标样式后缀 + ICON = "-icon", //自定义样式二级图标样式后缀 + CBOX = "-checkbox", //自定义样式复选框样式后缀 + CHS = "-choose"; //自定义样式复选框选中样式后缀 + + // 树自定义操作事件名称集合 绑定dtree-click的事件 + var eventName = { + checkNodeClick: "checkNodeClick", //点击复选框 + itemNodeClick: "itemNodeClick" //点击子节点div + }; + + // 树默认toolbar提供的功能集合 绑定dtree-tool的事件 + var defaultTool = { + pulldown: "pulldown", //点击展开当前节点下的全部节点 + pullup: "pullup", //点击收缩当前节点下的全部节点 + addTool: "addToolbar", //点击toolbar新增 + editTool: "editToolbar", //点击toolbar编辑 + delTool: "delToolbar" //点击toolbar删除 + }; + + // 树默认menubar提供的功能集合 绑定dtree-menu的事件 + var defaultMenu = { + moveDown: "moveDown", //menubar展开全部节点 + moveUp: "moveUp", //menubar收缩全部节点 + refresh: "refresh", //menubar刷新树 + checkAll: "checkAll", //menubar全选 + unCheckAll: "unCheckAll", //menubar全不选 + invertAll: "invertAll", //menubar反选 + remove: "remove", //menubar删除选中节点 + searchNode: "searchNode" //menubar查询节点 + }; + + // 树的公共事件 + var event = { + getElemId: function(options){ // 根据传入的参数获取ID + var elem = options.elem || ""; + var obj = options.obj || $(elem); + + if (obj.length == 0) { //页面中未找到绑定id + return ""; + } else { + return $(obj)[0].id; + } + }, + escape: function(html){ // 编码 + if(typeof html !== 'string') return ''; + return html.replace(entityReg.escape, function(match){return entityMap.escape[match];}); + }, + unescape: function(str){ // 解码 + if(typeof str !== 'string') return ''; + return str.replace(entityReg.unescape, function(match){return entityMap.unescape[match];}); + }, + cloneObj: function (obj, filter) { //深复制对象方法 + var newObj = {}; + if (obj instanceof Array) { + newObj = []; + } + var str = ""; + if(typeof filter !== 'undefined') {str = filter.join(",");} + for (var key in obj) { + if(str.indexOf(key) == -1){ + var val = obj[key]; + newObj[key] = typeof val === 'object' ? event.cloneObj(val, typeof filter !== undefined ? filter : []): val; + } + + } + return newObj; + }, + trimToDot: function(str){ + return str.replace(/ /g, "."); + } + }; + + // 特殊符号转义 + var keys = Object.keys || function(obj) { + obj = Object(obj); + var arr = []; + for(var a in obj) arr.push(a); + return arr; + }; + var invert = function(obj){ + obj = Object(obj); + var result = {}; + for(var a in obj) result[obj[a]] = a; + return result; + }; + var entityMap = { + escape: { + "&" : "&", + "<" : "<", + ">" : ">", + "'" : "&quo;" + } + }; + entityMap.unescape = invert(entityMap.escape); + var entityReg = { + escape: RegExp('[' + keys(entityMap.escape).join('') + ']', 'g'), + unescape: RegExp('(' + keys(entityMap.unescape).join('|') + ')', 'g') + }; + + //异步加载接口 + var AjaxHelper = { + request : function(config) { + var data = config.data ? config.data : {}; + var async = (typeof (config.async) === "boolean") ? config.async : true; + $.ajax({ + type : config.type ? config.type : "POST", + headers : config.headers, + url : config.url, + dataType : config.dataType ? config.dataType : "json", + data : data, + async : async, + contentType : config.contentType, + xhrFields: {withCredentials: config.withCredentials}, + beforeSend: function (XMLHttpRequest, self) { + if (typeof (config.beforeSend) === "function") { + return config.beforeSend(XMLHttpRequest, self); + } + return true; + }, + success : config.success, + error : function(XMLHttpRequest, textStatus, errorThrown) { + if (typeof (config.error) === "function") { + config.error(XMLHttpRequest, textStatus, errorThrown); + } else { + layer.msg("异步加载失败: " + textStatus,{icon:5, shift:6}); + } + }, + statusCode : { + 404 : function() { + layer.msg('未找到指定请求,请检查访问路径!',{icon:5, shift:6}); + }, + 500 : function() { + layer.msg('系统错误!',{icon:5, shift:6}); + } + }, + complete : function(XMLHttpRequest, textStatus) { + if (typeof (config.complete) === "function") { + config.complete(XMLHttpRequest, textStatus); + } + } + }); + }, + serialize: function(first, param){ //json序列化 key=value&key1=value1 + var p = first; + for (var key in param) { + p += key + "=" + param[key] + "&"; + } + p = p.substring(0, p.length-1); + return p; + } + }; + + /** 树类 Class定义 */ + var DTree = function(options){ + var _this = this; + /** 默认赋值**/ + this.formatter = { // 数据过滤 + title: false // 文字,默认不开启 + }; + this.response = { // 树返回的json格式 + statusName: "code", //返回标识 + statusCode: 200, //返回码 + message: "message", //返回信息 + rootName: "data", //根节点名称 + treeId: "id", //节点ID + parentId: "parentId", //父节点ID + title: "title", //节点名称 + ficonClass: "ficonClass", //自定义一级图标 + iconClass: "iconClass", //自定义二级图标 + childName: "children", //子节点名称 + last: "last", //是否最后一级节点 +// level: "level", //层级 + spread: "spread", //展开 + disabled: "disabled", //禁用 + hide: "hide", //隐藏 + checkArr: "checkArr", //复选框列表 + checked: "checked", //是否选中 + type: "type", //复选框标记 + basicData: "basicData" //表示用户自定义需要存储在树节点中的数据 + }; + this.defaultRequest = { // 树的默认发起请求参数格式,最后会将value作为参数名称传递 + nodeId: "nodeId", //节点ID + parentId: "parentId", //父节点ID + context: "context", //节点内容 + leaf: "leaf", //是否叶子节点 + level: "level", //层级 + spread: "spread", //节点展开状态 + dataType: "dataType", //节点标记 + checked: "checked", //节点复选框选中状态 + initchecked: "initchecked", //节点复选框初始状态 + basicData: "basicData", //用户自定义的记录节点数据 + recordData: "recordData", //当前data数据(排除basicData和children字段) + }; + this.toolbarFun = { + addTreeNode: function(param, $div) { //添加树节点后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + editTreeNode: function(param, $div) { //编辑树节点后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + editTreeLoad: function(param){ // 编辑树的数据回显,用于打开编辑时,回填数据 + return ; + }, + delTreeNode: function(param, $div){ //删除树后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + loadToolbarBefore: function(buttons, param, $div){ // 右键菜单加载前的函数 + return buttons; + } + }; + this.toolbarStyle = { // 工具栏弹出层的自定义样式 + title: "节点", + area: ["60%","80%"] + }; + this.menubarFun = { + remove: function(checkbarNodes){ //删除复选框选中节点,需要用户自定义,如未指定则树只是页面上做了修改 + return true; + } + }; + this.menubarTips = { // 菜单栏的默认显示 + toolbar: [], + group: [defaultMenu.moveDown, defaultMenu.moveUp, defaultMenu.refresh, defaultMenu.checkAll, defaultMenu.unCheckAll, defaultMenu.invertAll, defaultMenu.remove, defaultMenu.searchNode], + freedom: [] + }; + this.checkbarFun = { + chooseBefore: function($i, node){ // 复选框点击前回调 + return true; + }, + chooseDone: function(checkbarNodesParam) { //复选框点击事件完毕后,返回该树关于复选框操作的全部信息,用于用户自定义,如未指定则树只是页面上做了修改 + return ; + } + }; + this.iframeDefaultRequest = { //iframe的默认参数,目的是与加载树的参数不一样 + nodeId: "nodeId", //节点ID + parentId: "parentId", //父节点ID + context: "context", //节点内容 + leaf: "leaf", //是否叶子节点 + level: "level", //层级 + spread: "spread", //节点展开状态 + dataType: "dataType", //节点标记 + checked: "checked", //节点复选框选中状态 + initchecked: "initchecked", //节点复选框初始状态 + basicData: "basicData", //用户自定义的记录节点数据 + recordData: "recordData", //当前data数据(排除basicData和children字段) + }; + + this.iframeFun = { + iframeDone: function(iframeParam){ //iframe加载完毕后,用于用户自定义事件 + return ; + } + }; + this.style = { //树最终使用的样式集合 + item: "", //每一项div的样式 + itemThis: "", //选中div的样式 + dfont: "", //一级图标的样式 + icon: "", //二级图标的样式 + cbox: "", //复选框的样式 + chs: "" //复选框选中的样式 + }; + this.usefontStyle = { //树最终使用的图标集合 + fnode:{ //一级节点 + node:{ //非叶子节点 + open:"", //节点展开 + close:"" //节点关闭 + }, + leaf:"" //叶子节点 + }, + snode:{ //二级节点 + node:{ //非叶子节点 + open:"", //节点展开 + close:"" //节点关闭 + }, + leaf:"" //叶子节点 + }, + checkbox:{ //复选框 + on:"", //复选框选中 + out:"", //未选中 + noall:"" //半选 + }, + menubar:{ //菜单栏 + movedown:"", //全部展开 + moveup:"", //全部收缩 + refresh:"", //刷新 + checkAll:"", //全选 + unCheckAll:"", //全不选 + invertAll:"", //反选 + remove:"", //删除 + search:"" //搜索 + }, + menubarExt:"", //扩展菜单栏 + toolbar:{ //工具栏 + menubar:{ //依附在菜单栏的工具栏 + movedown:"", //全部展开 + moveup:"", //全部收缩 + refresh:"", //刷新 + checkAll:"", //全选 + unCheckAll:"", //全不选 + invertAll:"", //反选 + remove:"", //删除 + search:"" //搜索 + }, + menubarExt:"", //依附在菜单栏的扩展菜单栏 + pulldown:"", //展开 + pullup:"", //收缩 + add:"", //添加 + edit:"", //编辑 + del:"" //删除 + }, + toolbarExt:"" //扩展工具栏 + } + + /** 数据绑定**/ + this.node = { // 树节点选中时,包含当前节点的全部信息 + nodeId: "", //节点ID + parentId: "", //父节点ID + context: "", //节点内容 + leaf: "", //是否叶子节点 + level: "", //层级 + spread: "", //节点展开状态 + dataType: "", //节点标记 + checked: "", //节点复选框选中状态 + initchecked: "", //节点复选框初始状态 + basicData: "", //用户自定义的记录节点数据 + recordData: "", //当前data数据(排除basicData和children字段) + }; + + this.toolbarMenu = {}; // 工具栏右键菜单绑定的所有元素 + this.checkbarNode = []; // 复选框标记的全部节点数据 + this.errData = []; // 记录在渲染节点时有问题的数据 + this.checkArrLen = 0; // 添加节点的时判断复选框个数 + this.temp = []; // 临时变量 + this.bak = ""; // 临时变量 + this.setting(options); + }; + + /******************** 初始参数加载 ********************/ + /** + * @Desc: 设置基本属性值 + * @Param: options:JSON对象,初始设置dtree所需的全部属性 + */ + DTree.prototype.setting = function(options) { + this.options = options || {}; + + /** 绑定元素参数(必填,2个参数项必填一个)**/ + this.elem = this.options.elem || OPTIONS.elem || ""; //树绑定的元素ID:#elem + if(typeof this.options.obj === 'undefined'){ + if(this.elem) { + if($(this.elem).length > 0) { + this.obj = $(this.elem); + } + } + } else { + this.obj = this.options.obj || OPTIONS.obj || this.obj; //树绑定的jquery元素,用于当元素是延迟加载出来的话,可以用这个找到 + this.elem = "#" + this.obj[0].id; + } + + /** 基本参数**/ + this.scroll = this.options.scroll || OPTIONS.scroll || this.elem; //树的上级div容器,让树可以显示滚动条的div容器的ID + this.accordion = (typeof (this.options.accordion) === "boolean") ? this.options.accordion : (typeof (OPTIONS.accordion) === "boolean") ? OPTIONS.accordion : false; //手风琴加载, 默认false + if(this.accordion) { + this.initLevel = 1; //默认展开节点 1节 + } else { + this.initLevel = this.options.initLevel || OPTIONS.initLevel || 2; //默认展开节点 2节 + } + this.type = this.options.type || OPTIONS.type || "load"; //树的加载方式 all,全量树, load,增量树,默认load + this.cache = (typeof (this.options.cache) === "boolean") ? this.options.cache : (typeof (OPTIONS.cache) === "boolean") ? OPTIONS.cache : true; //数据缓存,默认true + this.record = this.options.record || OPTIONS.record || false; //开启数据记录模式,默认false + this.load = (typeof (this.options.load) === "boolean") ? this.options.load : (typeof (OPTIONS.load) === "boolean") ? OPTIONS.load : true; //开启加载动画,默认true + this.none = this.options.none || OPTIONS.nont || "无数据"; //初始加载无记录时显示文字 + this.tempHeight = this.options.height || OPTIONS.height; //临时转换高度变量 + if(this.tempHeight) { // 设置高度 + if(/^full-\d+$/.test(this.tempHeight)) { + this.fullHeightGap = this.tempHeight.split('-')[1]; + this.height = $WIN.height() - this.fullHeightGap; //设置高度 + } else { + this.fullHeightGap = this.tempHeight; + this.height = this.tempHeight; + } + } else { + this.fullHeightGap = ""; + this.height = ""; + } + this.width = this.options.width || OPTIONS.width || "260"; //宽度 + this.obj.css("width", this.width); + + /** 样式相关参数**/ + this.iconfont = this.options.iconfont || OPTIONS.iconfont || DTREEFONT; //默认图标字体 dtreefont + this.iconfontStyle = this.options.iconfontStyle || OPTIONS.iconfontStyle || {}; //用于自定义树的每个关键部位使用的图标 + this.nodeIconArray = $.extend(nodeIconArray, this.options.nodeIconArray || OPTIONS.nodeIconArray) || nodeIconArray; //用户自定义非叶子节点图标集合,node + this.leafIconArray = $.extend(leafIconArray, this.options.leafIconArray || OPTIONS.leafIconArray) || leafIconArray; //用户自定义叶子节点图标集合,leaf + this.skin = this.options.skin || OPTIONS.skin || "theme"; // 自定义样式 + if(this.skin == "layui"){ // layui主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : (typeof (OPTIONS.line) === "boolean") ? OPTIONS.line : true; //开启树线,默认开启 + this.ficon = this.options.ficon || OPTIONS.ficon || "7"; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'7' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; //一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "-1"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else if(this.skin == "laySimple"){ // laySimple主题 + this.line = this.options.line || OPTIONS.line || false; //开启树线,默认不开启 + this.ficon = this.options.ficon || OPTIONS.ficon || ["2","-1"]; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'-1' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "2") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'2' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "-1"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else { // 默认主题 或者自定义主题 + this.line = this.options.line || OPTIONS.line || false; //开启树线,默认不开启 + this.ficon = this.options.ficon || OPTIONS.ficon || "8"; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'8' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "5"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'5' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "0") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'0' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } + + /** 数据加载参数**/ + this.url = this.options.url || OPTIONS.url || ""; //请求地址 + this.async = (typeof (this.options.async) === "boolean") ? this.options.async : (typeof (OPTIONS.async) === "boolean") ? OPTIONS.async : true; //异步同步加载,默认异步加载 + this.asyncLoad = this.options.asyncLoad || OPTIONS.asyncLoad || []; //初始异步加载层级数据 + this.headers = this.options.headers || OPTIONS.headers || {}; //ajax header属性 + this.method = this.options.method || OPTIONS.method || "post"; //请求类型 + this.dataType = this.options.dataType || OPTIONS.dataType || "json"; //参数类型 + this.contentType = this.options.contentType || OPTIONS.contentType || "application/x-www-form-urlencoded"; //发送信息至服务器时内容编码类型 + this.defaultRequest = $.extend(this.defaultRequest, this.options.defaultRequest || OPTIONS.defaultRequest) || this.defaultRequest; //默认请求参数 + this.filterRequest = this.options.filterRequest || OPTIONS.filterRequest || []; //过滤请求参数 + this.request = this.options.request || OPTIONS.request || {}; //用户自定义请求参数 + this.response = $.extend(this.response, this.options.response || OPTIONS.response) || this.response; //返回json格式 + this.data = this.options.data || OPTIONS.data || null; //初始化指定该参数,则不会访问异步接口 + this.dataFormat = this.options.dataFormat || OPTIONS.dataFormat || "levelRelationship"; //用于用户配置的data数据格式,list:列表, levelRelationship:层级关系,默认 + this.dataStyle = this.options.dataStyle || OPTIONS.dataStyle || "defaultStyle"; //用于用户配置layui通用的json数据风格,layuiStyle:layui风格,defaultStyle:默认风格 + this.errDataShow = this.options.errDataShow || OPTIONS.errDataShow || false; //是否在递归数据出现错误后,显示错误信息,默认false + this.withCredentials = this.options.withCredentials || OPTIONS.withCredentials || false; //是否允许跨域请求,默认false + this.beforeSend = this.options.beforeSend || OPTIONS.beforeSend || function(ajax, XMLHttpRequest, self){return true}; //异步加载之前的回调 + this.success = this.options.success || OPTIONS.success || function(data, obj, first){}; //树加载完毕后执行解析树之前的回调 + this.done = this.options.done || OPTIONS.done || function(data, obj, first){}; //树加载完毕后的回调 + this.formatter = $.extend(this.formatter, this.options.formatter || OPTIONS.formatter) || this.formatter; //数据过滤 + this.error = this.options.error || OPTIONS.error || function(XMLHttpRequest, textStatus, errorThrown){}; // 异步加载异常回调 + this.complete = this.options.complete || OPTIONS.complete || function(XMLHttpRequest, textStatus){}; // 异步加载完成回调 + + /** 复选框参数**/ + this.checkbar = this.options.checkbar || OPTIONS.checkbar || false; //是否开启复选框模式 + this.checkbarLoad = this.options.checkbarLoad || OPTIONS.checkbarLoad || "node"; //复选框作用范围,node:所有节点, leaf:最后一级;默认所有节点 + this.checkbarType = this.options.checkbarType || OPTIONS.checkbarType || "all"; //复选框选中形式 all:子集选中父级也选中, no-all:子集选中父级半选中,子集全选父级选中,p-casc:父级选中子集全选,子集无法改变父级选中状态, self:没有任何级联关系,only:只能选中一个复选框。 默认all + this.checkbarData = this.options.checkbarData || OPTIONS.checkbarData || "choose"; //复选框记录数据类型形式, change表示记录变更数据,choose表示记录选中数据,all记录全部数据,halfChoose记录选中和半选中的数据,默认choose + this.checkbarFun = $.extend(this.checkbarFun, this.options.checkbarFun || OPTIONS.checkbarFun) || this.checkbarFun; //checkbar事件加载 + + /** 菜单栏参数**/ + this.menubar = this.options.menubar || OPTIONS.menubar || false; //是否打开菜单栏 + this.menubarTips = $.extend(this.menubarTips, this.options.menubarTips || OPTIONS.menubarTips) || this.menubarTips; //菜单栏吸附, toolbar:依附在工具栏,group:依附在按钮组,freedom,自由 + this.menubarFun = $.extend(this.menubarFun, this.options.menubarFun || OPTIONS.menubarFun) || this.menubarFun; //menubar事件加载 + + /** 工具栏参数**/ + this.toolbar = this.options.toolbar || OPTIONS.toolbar || false; //是否开启可编辑模式 + this.toolbarWay = this.options.toolbarWay || OPTIONS.toolbarWay || "contextmenu"; //工具栏显示方式,contextmenu:右键,follow:跟随节点,fixed:固定在节点右侧 + this.toolbarStyle = $.extend(this.toolbarStyle, this.options.toolbarStyle || OPTIONS.toolbarStyle) || this.toolbarStyle; //toolbar的自定义风格,标题,弹框大小 + this.toolbarLoad = this.options.toolbarLoad || OPTIONS.toolbarLoad || "node"; //toolbar作用范围:node:所有节点,noleaf:非最后一级节点,leaf:最后一级 + this.toolbarShow = this.options.toolbarShow || OPTIONS.toolbarShow || ["add","edit","delete"]; //toolbar三个按钮自定义加载 + this.toolbarBtn = this.options.toolbarBtn || OPTIONS.toolbarBtn || null; //toolbar增删改中内容的自定义加载 + this.toolbarExt = this.options.toolbarExt || OPTIONS.toolbarExt || []; //toolbar按钮扩展 + this.toolbarFun = $.extend(this.toolbarFun, this.options.toolbarFun || OPTIONS.toolbarFun) || this.toolbarFun; //toolbar事件加载 + + /** iframe模式参数**/ + this.useIframe = this.options.useIframe || OPTIONS.useIframe || false; //是否加载iframe 默认false, + this.iframeElem = this.options.iframeElem || OPTIONS.iframeElem || ""; //iframe的ID + this.iframeUrl = this.options.iframeUrl || OPTIONS.iframeUrl || ""; //树关联的iframe地址 + this.iframeLoad = this.options.iframeLoad || OPTIONS.iframeLoad || "leaf"; //点击哪一层加载frame: node:所有节点, leaf:默认,最后一级 + this.iframeDefaultRequest = $.extend(this.iframeDefaultRequest, this.options.iframeDefaultRequest || OPTIONS.iframeDefaultRequest) || this.iframeDefaultRequest; //iframe的默认传递参数 + this.iframeRequest = $.extend(this.iframeRequest, this.options.iframeRequest) || $.extend(this.iframeRequest, OPTIONS.iframeRequest) || this.iframeRequest; //iframe的自定义参数 + this.iframeFun = $.extend(this.iframeFun, this.options.iframeFun) || $.extend(this.iframeFun, OPTIONS.iframeFun) || this.iframeFun; //iframe事件加载 + + /** 下拉树模式参数**/ + this.select = this.options.select || false; + if(this.select) { + // 重置下拉树 + this.selectSetting(); + } + + /** 调用确认最终主题方法*/ + this.ensureTheme(); + }; + + /** + * @Desc: 重置基本属性值 + * @Param: options:JSON对象,重置dtree所需的全部属性 + */ + DTree.prototype.reloadSetting = function(options) { + this.options = $.extend(this.options, options) || this.options; + + /** 绑定元素参数**/ + this.elem = this.options.elem || this.elem; //树绑定的元素ID:#elem + if(typeof this.options.obj === 'undefined'){ + if(this.elem) { + if($(this.elem).length > 0) { + this.obj = $(this.elem); + } + } + } else { + this.obj = this.options.obj || this.obj; //树绑定的jquery元素,用于当元素是延迟加载出来的话,可以用这个找到 + this.elem = "#" + this.obj[0].id; + } + + /** 基本参数**/ + this.scroll = this.options.scroll || this.scroll; //树的上级div容器,让树可以显示滚动条的div容器 + this.accordion = (typeof (this.options.accordion) === "boolean") ? this.options.accordion : this.accordion; //开启手风琴加载 + if(this.accordion) { + this.initLevel = 1; //默认展开节点 1节 + } else { + this.initLevel = this.options.initLevel || this.initLevel; //默认展开节点 2节 + } + this.type = this.options.type || this.type; //树的加载方式 all,全量树, load,增量树,默认load + this.cache = (typeof (this.options.cache) === "boolean") ? this.options.cache : this.cache; //开启数据缓存 + this.record = (typeof (this.options.record) === "boolean") ? this.options.record : this.record; //开启数据记录模式 + this.load = (typeof (this.options.load) === "boolean") ? this.options.load : this.load; //开启加载动画 + this.none = this.options.none || this.none; //初始节点加载无数据时显示文字 + this.tempHeight = this.options.height || this.height; //临时转换高度变量 + if(this.tempHeight) { //设置高度 + if(/^full-\d+$/.test(this.tempHeight)) { + this.fullHeightGap = this.tempHeight.split('-')[1]; + this.height = $WIN.height() - this.fullHeightGap; + } else { + this.fullHeightGap = this.tempHeight; + this.height = this.tempHeight; + } + } + this.width = this.options.width || this.width; //宽度 + this.obj.css("width", this.width); + + /** 样式相关参数**/ + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : this.line; //开启树线,默认不开启 + this.iconfont = this.options.iconfont || this.iconfont; //默认图标字体 dtreefont + this.iconfontStyle = this.options.iconfontStyle || this.iconfontStyle; //用于自定义树的每个关键部位使用的图标 + this.nodeIconArray = $.extend(nodeIconArray, this.options.nodeIconArray) || this.nodeIconArray; //用户自定义非叶子节点图标集合,node + this.leafIconArray = $.extend(leafIconArray, this.options.leafIconArray) || this.leafIconArray; //用户自定义叶子节点图标集合,leaf + this.skin = this.options.skin || this.skin; //自定义样式 + if(this.skin == "layui"){ //layui主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : true; //开启树线,默认开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'7' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; //一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else if(this.skin == "laySimple"){ //laySimple主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : false; //开启树线,默认不开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'-1' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "2") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'2' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1];//一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else { // 默认主题 或者自定义主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : false; //开启树线,默认不开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'8' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'5' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "0") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'0' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } + + /** 数据加载参数**/ + this.url = this.options.url || this.url; //请求地址 + this.async = (typeof (this.options.async) === "boolean") ? this.options.async : this.async; //异步同步加载,默认异步加载 + this.asyncLoad = this.options.asyncLoad || this.asyncLoad; //初始异步加载层级数据 + this.headers = this.options.headers || this.headers; //ajax header属性 + this.method = this.options.method || this.method; //请求类型 + this.dataType = this.options.dataType || this.dataType; //参数类型 + this.contentType = this.options.contentType || this.contentType; //发送信息至服务器时内容编码类型 + this.defaultRequest = $.extend(this.defaultRequest, this.options.defaultRequest) || this.defaultRequest; //默认请求参数 + this.filterRequest = this.options.filterRequest || this.filterRequest; //过滤请求参数 + this.request = this.options.request || this.request; //用户自定义请求参数 + this.response = $.extend(this.response, this.options.response) || this.response; //返回json格式 + this.data = this.options.data || this.data; //初始化指定该参数,则不会访问异步接口 + this.dataFormat = this.options.dataFormat || this.dataFormat; //用于用户配置的data数据格式,list:列表, levelRelationship:层级关系,默认 + this.dataStyle = this.options.dataStyle || this.dataStyle; //用于用户配置layui通用的json数据风格,layuiStyle:layui风格,defaultStyle:默认风格 + this.errDataShow = (typeof (this.options.errDataShow) === "boolean") ? this.options.errDataShow : this.errDataShow; //是否在使用list模式递归数据出现错误时,显示错误信息 + this.withCredentials = (typeof (this.options.withCredentials) === "boolean") ? this.options.withCredentials : this.withCredentials; //是否允许跨域请求 + this.beforeSend = this.options.beforeSend || this.beforeSend; //异步加载之前的回调 + this.success = this.options.success || this.success; //树加载完毕后执行解析树之前的回调 + this.done = this.options.done || this.done; //树加载完毕后的回调 + this.formatter = $.extend(this.formatter, this.options.formatter)|| this.formatter; //数据过滤 + this.error = this.options.error || this.error; //异步加载异常回调 + this.complete = this.options.complete || this.complete; //异步加载完成回调 + + /** 复选框参数**/ + this.checkbar = this.options.checkbar || this.checkbar; //是否开启复选框模式 + this.checkbarLoad = this.options.checkbarLoad || this.checkbarLoad; //复选框作用范围,node:所有节点, leaf:最后一级;默认所有节点 + this.checkbarType = this.options.checkbarType || this.checkbarType; //复选框选中形式 all:子集选中父级也选中, no-all:子集选中父级半选中,子集全选父级选中,p-casc:父级选中子集全选,子集无法改变父级选中状态, self:没有任何级联关系,only:只能选中一个复选框。 默认all + this.checkbarData = this.options.checkbarData || this.checkbarData; //复选框记录数据类型形式, change表示记录变更数据,choose表示记录选中数据,all记录全部数据,halfChoose记录选中和半选中的数据,默认choose + this.checkbarFun = $.extend(this.checkbarFun, this.options.checkbarFun)|| this.checkbarFun; //checkbar事件加载 + + /** 菜单栏参数**/ + this.menubar = this.options.menubar || this.menubar; //是否打开菜单栏 + this.menubarTips = $.extend(this.menubarTips, this.options.menubarTips) || this.menubarTips; //菜单栏吸附, toolbar:依附在工具栏,group:依附在按钮组,freedom,自由 + this.menubarFun = $.extend(this.menubarFun, this.options.menubarFun) || this.menubarFun; //menubar事件加载 + + /** 工具栏参数**/ + this.toolbar = this.options.toolbar || this.toolbar; //是否开启工具栏 + this.toolbarWay = this.options.toolbarWay || this.toolbarWay; //工具栏显示方式,contextmenu:右键,follow:跟随节点,fixed:固定在节点右侧 + this.toolbarStyle = $.extend(this.toolbarStyle, this.options.toolbarStyle) || this.toolbarStyle; //toolbar的自定义风格,标题,弹框大小 + this.toolbarLoad = this.options.toolbarLoad || this.toolbarLoad; //toolbar作用范围:node:所有节点,noleaf:非最后一级节点,leaf:最后一级 + this.toolbarShow = this.options.toolbarShow || this.toolbarShow; //toolbar三个按钮 + this.toolbarBtn = this.options.toolbarBtn || this.toolbarBtn; //toolbar增删改中内容的自定义加载 + this.toolbarExt = this.options.toolbarExt || this.toolbarExt; //toolbar按钮扩展 + this.toolbarFun = $.extend(this.toolbarFun, this.options.toolbarFun) || this.toolbarFun; //toolbar事件加载 + + /** iframe模式参数**/ + this.useIframe = this.options.useIframe || this.useIframe;//是否加载iframe 默认false + this.iframeElem = this.options.iframeElem || this.iframeElem; //iframe的ID + this.iframeUrl = this.options.iframeUrl || this.iframeUrl; //树关联的iframe地址 + this.iframeLoad = this.options.iframeLoad || this.iframeLoad; //点击哪一层加载frame: node:所有节点, leaf:默认,最后一级 + this.iframeDefaultRequest = $.extend(this.iframeDefaultRequest, this.options.iframeDefaultRequest) || this.iframeDefaultRequest; //iframe的默认传递参数 + this.iframeRequest = $.extend(this.iframeRequest, this.options.iframeRequest) || this.iframeRequest; //iframe的自定义参数 + this.iframeFun = $.extend(this.iframeFun, this.options.iframeFun) || this.iframeFun; //iframe事件加载 + + /** 下拉树模式参数**/ + if(this.select) { + // 重置下拉树 + this.reloadSelectSetting(); + } + + /** 调用确认最终主题方法*/ + this.ensureTheme(); + + }; + + /** + * @Desc: 设置下拉树的基本参数值 + */ + DTree.prototype.selectSetting = function() { + /** select模式参数*/ + this.select = true; //配置成select模式 + + this.selectInitVal = this.obj.attr("data-value") || this.options.selectInitVal || ""; //输入框的值 + this.selectTreeDiv = this.obj[0].id + "_tree_div"; // 上级DIV节点 + this.selectCardDiv = this.obj[0].id + "_select_card_div"; // 上级layui卡片节点 + this.selectDiv = this.obj[0].id + "_select_div"; // 模拟的select节点 + this.selectTipsName = this.obj[0].id + "_select_input"; // select的提示输入框名称 + this.selectTips = this.options.selectTips || "请选择"; // 输入框的提示语 + this.selectCardHeight = this.options.selectCardHeight || "350"; // 下拉面板的高度 + this.selectInputName = this.options.selectInputName || {nodeId: this.obj[0].id + "_select_nodeId"}; // select表单中的元素 + + // 调取下拉树的特殊处理页面元素标识 + this.renderSelectDom(); + } + + /** + * @Desc: 重置下拉树的基本参数值 + */ + DTree.prototype.reloadSelectSetting = function() { + + this.selectInitVal = this.obj.attr("data-value") || this.options.selectInitVal || this.selectInitVal; //输入框的值 + this.selectTips = this.options.selectTips || this.selectTips; // 输入框的提示语 + this.selectCardHeight = this.options.selectCardHeight || this.selectCardHeight; // 下拉面板的高度 + this.selectInputName = $.extend(this.selectInputName, this.options.selectInputName) || this.selectInputName; // select表单中的元素 + + // 调取下拉树的特殊处理页面元素标识 + this.reloadSelectDom(); + } + + /******************** 下拉树设置区域 ********************/ + /** + * @Desc: 渲染下拉树的Dom结构 + */ + DTree.prototype.renderSelectDom = function() { + var _this = this; + var rootId = _this.obj[0].id; + + // 设置自定义表单隐藏域 + var selectInputName = _this.selectInputName; + var selectInput = []; + for(var key in selectInputName) { + selectInput.push(''); + } + + // 设置html + var prevHtml = ['
                                                                              ', + '
                                                                              ', selectInput.join(""), + '', + '', + '
                                                                              '].join(''); + + _this.obj.before(prevHtml); + + var cardStyle = "style="; + if(this.selectCardHeight) { + cardStyle += "'height:"+_this.selectCardHeight+"px'"; + } + _this.obj.wrap('
                                                                              ').wrap('
                                                                              ').wrap('
                                                                              '); + + } + + /** + * @Desc: 重新渲染下拉树的Dom结构 + */ + DTree.prototype.reloadSelectDom = function() { + var _this = this; + var rootId = _this.obj[0].id; + + // 设置自定义表单隐藏域 + var selectInputName = _this.selectInputName; + var selectInput = []; + for(var key in selectInputName) { + selectInput.push(''); + } + + $("div[dtree-id='"+rootId+"'][dtree-select='"+_this.selectDiv+"']").find("div.layui-select-title").html(""); + + // 设置html + var prevHtml = [selectInput.join(""), + '', + ''].join(''); + + $("div[dtree-id='"+rootId+"'][dtree-select='"+_this.selectDiv+"']").find("div.layui-select-title").html(prevHtml); + + var cardStyle = "style="; + if(this.selectCardHeight) { + cardStyle += "'height:"+_this.selectCardHeight+"px'"; + } + $("div[dtree-id='"+rootId+"'][dtree-card='"+_this.selectCardDiv+"']").attr("style", cardStyle); + } + + /** + * @Desc: 设置下拉树模式中,input输入框的值 + * @Param: param: input中的值对应树数据的ID值\当前树选中的数据JSON对象,可不传,不传的话则树内部读取 + */ + DTree.prototype.selectVal = function(param) { + var _this = this; + var rootId = _this.obj[0].id; + var selectInputName = _this.selectInputName; + var selectTipsNameValue = ""; + var selectValues = {}; + + // 如果开启了复选框,则此方法用来取值 + if(_this.checkbar) { + return _this.selectCheckboxVal(); + } + + if(typeof param === 'undefined') { // 不传,则为当前树中记录的ID + param = _this.getNowParam(); + } + if(typeof param === 'string') { // 传递ID,则查询树节点ID对应的值 + param = _this.getParam(param); + } + + selectTipsNameValue = param["context"]; + for(var key in selectInputName) { + selectValues[selectInputName[key]] = param[key]; + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+selectInputName[key]+"']").val(param[key] || ""); + } + + if(param["nodeId"] && !param["context"]) { + selectTipsNameValue = _this.getParam(param["nodeId"]); + } + + // 返显提示输入框值 + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+_this.selectTipsName+"']").val(selectTipsNameValue || ""); + + // 返回隐藏域中的值 + return selectValues; + } + + /** + * @Desc: 设置复选框模式中的下拉树的选中值 + */ + DTree.prototype.selectCheckboxVal = function() { + var _this = this; + var rootId = _this.obj[0].id; + var selectInputName = _this.selectInputName; + + // 获取全部复选框选中节点 + var param = _this.getCheckbarJsonArrParam(); + + selectTipsNameValue = param["context"]; + var selectValues = {}; + for(var key in selectInputName) { + var value = param[key].join(","); + selectValues[selectInputName[key]] = value; + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+selectInputName[key]+"']").val(value); + } + + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+_this.selectTipsName+"']").val(selectTipsNameValue); + + // 返回隐藏域中的值 + return selectValues; + } + + /** + * @Desc: 重置下拉树的值,1.表单清空;2.节点重置;3.复选框重置 + */ + DTree.prototype.selectResetVal = function() { + var _this = this; + var rootId = _this.obj[0].id; + // 表单清空 + $("input[dtree-id='"+rootId+"']").val(""); + // 节点重置 + _this.cancelNavThis(); + if(_this.checkbar) { + // 复选框重置 + _this.cancelCheckedNode(); + } + } + + + /******************** 字体及图标区域 ********************/ + /** + * @Desc: 树使用的最终主题方案 + */ + DTree.prototype.ensureTheme = function(){ + var _this = this; + + // 确认style + this.style.item = DTREE + this.skin + ITEM; + this.style.itemThis = DTREE + this.skin + ITEMTHIS; + this.style.dfont = DTREE + this.skin + DFONT; + this.style.ficon = DTREE + this.skin + FICON; + this.style.icon = DTREE + this.skin + ICON; + this.style.cbox = DTREE + this.skin + CBOX; + this.style.chs = DTREE + this.skin + CHS; + + // 确认usefontStyle + var iconfont = this.iconfont; + var iconfonts = []; + if(typeof iconfont === 'string') { + iconfonts.push(iconfont); + } else { + iconfonts = iconfont; + } + + var iconfontStyle = this.iconfontStyle; + var iconfontStyles = []; + if(iconfontStyle.length == undefined) { + iconfontStyles.push(iconfontStyle); + } else { + iconfontStyles = iconfontStyle; + } + + for(var i=0; i 0) { + $lis.each(function(){ + _this.showLineLi($(this)); + }); + } else { + _this.obj.find("li[data-id]").each(function(){ + _this.showLineLi($(this)); + }); + } + } + } + + /** + * @Desc: 真正显示树线的方法 + * @Param: $li: JQuery对象,表示组成树的li节点 + */ + DTree.prototype.showLineLi = function($li){ + var _this = this; + var $div = $li.children("div"), + $nextLi = $li.next("li"), + $ul = $li.parent("ul"); + if($ul[0].id == _this.obj[0].id) { + // 根节点下的节点 + $li.removeClass(LI_NAV_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_FIRST_LINE); + } else { + // 非根节点下的节点 + var $pnextLi = $ul.parent("li").next("li"); + if($pnextLi.length == 0) { + if($nextLi.length == 0){ + $li.removeClass(LI_NAV_LINE); + $li.removeClass(LI_NAV_FIRST_LINE); + $li.addClass(LI_NAV_LAST_LINE); + } else { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_LINE); + } + }else { + var $pnextdiv = $pnextLi.children("div"); + if($nextLi.length == 0 && $div.children("cite").attr("data-leaf") == "leaf" && $pnextdiv.children("cite").attr("data-leaf") == "leaf") { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LINE); + $li.addClass(LI_NAV_LAST_LINE); + } else { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_LINE); + } + } + } + } + + /******************** 初始化数据区域 ********************/ + /** + * @Desc: 设置高度 + */ + DTree.prototype.autoHeight = function(){ + var _this = this; + var height = _this.height; + if(height != "") { + if(_this.elem == _this.scroll){ + _this.obj.parent().css("height", height + "px"); + } else { + var $toolbarDiv = _this.obj.closest(_this.scroll); + $toolbarDiv.css("height", height + "px"); + } + } + }; + + /** + * @Desc: 重载树 + * @Param: options: dtree的所有属性的json对象 + */ + DTree.prototype.reload = function(options){ + var _this = this; + _this.reloadSetting(options); + _this.init(); + }; + + /** + * @Desc: 初始化加载 + */ + DTree.prototype.loadTreeInit = function(){ + var _this = this; + var asyncLoad = _this.asyncLoad; + // 初始化加载 + _this.init(function(){ + // ajax加载之后的回调 + if(asyncLoad && asyncLoad.length > 0) { + _this.obj.addClass(NAV_SHOW); + + // 说明此时要异步加载子节点 + _this.loadChildTreeInit(asyncLoad, 0); + } + }) + } + + /** + * @Desc: 初始化加载子节点 + * @Param: asyncLoad: 需异步加载的层级,在基础属性中配置 + * @Param: i: 已经加载到的层级 + */ + DTree.prototype.loadChildTreeInit = function(asyncLoad, i){ + var _this = this; + if(i == asyncLoad.length) { // 满足条件,终止递归 + return ; + } + + var $div = _this.getNode(asyncLoad[i]); + + if($div && $div.length > 0) { + // 设置节点状态 + var $ul = $div.next("ul"), + $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(); + + $ul.addClass(NAV_SHOW); + _this.accordionUL($ul); + _this.operateIcon($i_fnode, $i_snode).open(); + // 加载子节点 + _this.getChild($div, undefined, function(){ + // 继续递归 + _this.loadChildTreeInit(asyncLoad, ++i); + }); + } + + } + + /** + * @Desc: 初始化树 + * @Param: callback: 异步加载完成之后的回调函数 + */ + DTree.prototype.init = function(callback){ + var _this = this; + if (typeof _this !== "object") { + layer.msg("树组件未成功加载,请检查配置", {icon:5}); + return ; + } + + // 设置组件高度 + _this.autoHeight(); + + if(_this.data) { + _this.dataLoadTree(true, _this.obj, _this.data); + } else { + _this.asyncLoadTree(true, _this.obj, callback); + } + }; + + /** + * @Desc: 加载子节点 + * @Param: $div: JQuery对象,代表当前子节点的父节点div + * @Param: data: data方式加载的数据 + * @Param: callback: 子节点加载完成之后的回调喊出 + */ + DTree.prototype.getChild = function($div, data, callback) { + var _this = this, $ul = $div.next("ul"); + + _this.setNodeParam($div); + + if(typeof data !== 'undefined') { + _this.dataLoadTree(false, $ul, data); + } else { + _this.asyncLoadTree(false, $ul, callback); + } + }; + + /** + * @Desc: 用data加载树 + * @Param: first: 表示是否第一次加载 + * @Param: $ul: JQuery对象,代表当前数据加载到的ul标签里 + * @Param: data: data加载的数据 + */ + DTree.prototype.dataLoadTree = function(first, $ul, data){ + var _this = this; + + if(typeof data.length === 'undefined'){ + layer.msg("数据解析异常,data数据格式不正确", {icon:5}); + return ; + } + + if(first && data.length == 0) { + $ul.html(_this.getNoneDom().text()); + return ; + } + + //先将ul中的元素清空 + $ul.html(""); + + var index = _this.load ? layer.load(1) : ""; + + setTimeout(function () { + // 加载完毕后执行树解析前的回调 + var returnData = _this.success(data, $ul, first); + if(returnData) { + data = returnData; + } + + var pid = (first == true) ? $ul.attr("data-id") : _this.node.nodeId; + var level = (first == true) ? 1 : parseInt(_this.node.level)+1; + + // 解析树 + if (_this.dataFormat == 'list'){ + //1.构建一个存放节点的树组 + var rootListData = _this.queryListTreeByPid(pid, data); + _this.loadListTree(rootListData, _this.data, level); + } else { + _this.loadTree(data, level); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + // 设置下拉树的初始值 + if(first && _this.select && _this.selectInitVal){ + if(_this.checkbar) { // 复选框模式下 + _this.chooseDataInit(_this.selectInitVal); + _this.selectCheckboxVal(_this.selectInitVal); + } else { // 普通模式下 + _this.dataInit(_this.selectInitVal); + _this.selectVal(_this.selectInitVal); + } + } + + // 保存树副本 + _this.bak = _this.obj.html(); + + // 加载完毕后的回调 + _this.done(_this.data, $ul, first); + + if(_this.load){layer.close(index);} + }, 100); + } + + /** + * @Desc: 异步加载树 + * @Param: first: 表示是否第一次加载 + * @Param: $ul: JQuery对象,代表当前数据加载到的ul标签里 + * @Param: callback: 异步加载完成之后的回调函数 + */ + DTree.prototype.asyncLoadTree = function(first, $ul, callback){ + var _this = this; + + if (!_this.url) { + layer.msg("数据请求异常,url参数未指定", {icon:5}); + return ; + } + + //先将ul中的元素清空 + $ul.html(""); + + var index = ""; + + AjaxHelper.request({ + async: _this.async, + headers: _this.headers, + type: _this.method, + url: _this.url, + dataType: _this.dataType, + contentType: _this.contentType, + withCredentials: _this.withCredentials, + data: _this.getFilterRequestParam(_this.getRequestParam()), + beforeSend: function(XMLHttpRequest, self){ + index = _this.load ? layer.load(1) : ""; + var returnFlag = _this.beforeSend(this, XMLHttpRequest, self); + if(!returnFlag) { + if(_this.load){layer.close(index);} + } + return returnFlag; + }, + success: function(result) { + if (typeof result === 'string') { + result = $.parseJSON(result); + } + + // 加载完毕后执行树解析前的回调 + var returnData = _this.success(result, $ul, first); + if(returnData) { + result = returnData; + } + + var code = ""; + if (_this.dataStyle == 'layuiStyle'){ + code = result[_this.response.statusName]; + } else { + code = result.status[_this.response.statusName]; + } + + if (code == _this.response.statusCode) { + + var d = result[_this.response.rootName]; + + if(first && typeof d.length === 'undefined'){ + $ul.html(_this.getNoneDom().errText("数据解析异常,url回调后的数据格式不正确")); + //layer.msg("数据解析异常,url回调后的数据格式不正确", {icon:5}); + return ; + } + + if(first && d.length == 0) { + $ul.html(_this.getNoneDom().text()); + return ; + } + + //1.识别根节点ul中的data-id标签,判断顶级父节点 + var pid = (first == true) ? $ul.attr("data-id") : _this.node.nodeId; + var level = (first == true) ? 1 : parseInt(_this.node.level)+1; + + // 第一次解析树 + if (_this.dataFormat == 'list'){ + //1.构建一个存放节点的树组 + var rootListData = _this.queryListTreeByPid(pid, d); + if(first) { + _this.loadListTree(rootListData, d, level); + } else { + _this.loadListTree(rootListData, d, level, $ul); + } + } else { + if(first) { + _this.loadTree(d, level); + } else { + _this.loadTree(d, level, $ul); + } + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + if(!first) { + $ul.addClass(NAV_SHOW); + } + + // 设置下拉树的初始值 + if(first && _this.select && _this.selectInitVal){ + if(_this.checkbar) { // 复选框模式下 + _this.chooseDataInit(_this.selectInitVal); + _this.selectCheckboxVal(_this.selectInitVal); + } else { // 普通模式下 + _this.dataInit(_this.selectInitVal); + _this.selectVal(_this.selectInitVal); + } + } + + // 保存树副本 + _this.bak = _this.obj.html(); + + // 加载完毕后的回调 + _this.done(result, $ul, first); + + callback && callback(); + } else { + // 如果打印不出任何信息说明是在这里,用了错误的数据格式, 或返回码不正确 + if (_this.dataStyle == 'layuiStyle'){ + _this.obj.html(_this.getNoneDom().errText(result[_this.response.message])); + _this.error(null, code, result[_this.response.message]); + } else { + _this.obj.html(_this.getNoneDom().errText(result.status[_this.response.message])); + _this.error(null, code, result.status[_this.response.message]); + } + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown){// 异步加载异常回调 + _this.obj.html(_this.getNoneDom().errText(textStatus + ": " + errorThrown)); + _this.error(XMLHttpRequest, textStatus, errorThrown); + }, + complete: function(XMLHttpRequest, textStatus){// 异步加载完成回调 + if(_this.load){layer.close(index);} + _this.complete(XMLHttpRequest, textStatus); + } + }); + + } + + /** + * @Desc: 初始化渲染树或者拼接渲染树,list模式下 + * @Param: nowListData: 表示当前需要被渲染的数据 + * @Param: listData: 表示全部数据 + * @Param: level: 当前渲染的层级 + * @Param: $ul: JQuery对象,代表当前数据加载到的ul标签里 + */ + DTree.prototype.loadListTree = function(nowListData, listData, level, $ul){ + var _this = this; + $ul = $ul || _this.getNodeDom().nowOrRootUl(); //当前选中的节点或根节点 + if (nowListData.length > 0){ + for (var i = 0; i < nowListData.length; i++) { + // 1.获取已知节点的全部数据 + var data = nowListData[i]; + if(typeof data !== "object") continue; + var parseData = _this.parseData(data); + var childListData = _this.queryListTreeByPid(parseData.treeId(), listData); // 根据已知数据的id判断该条数据是否还有子数据 + + // 3. 页面元素加载数据 + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(childListData.length), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(level), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), ($ul.hasClass(UL_ROOT) ? "root" : "item"))); + // 4.有子数据的元素加载子节点 + if(childListData.length > 0){ + var cLevel = parseInt(level)+1; + _this.loadListTree(childListData, listData, cLevel, _this.obj.find("ul[data-id='"+parseData.treeId()+"']")); + } + } + } + }; + + /** + * @Desc: 根据父ID查找list数据中匹配的元素 + * @Param: pid: 表示父ID + * @Param: listData: 表示全部数据 + */ + DTree.prototype.queryListTreeByPid = function(pid, listData){ + var _this = this; + var rootListData = []; + if (listData) { + for (var i = 0; i < listData.length; i++) { + var data = listData[i]; + if(typeof data !== "object") continue; + if(pid == "null" || pid == null){ + if(data[_this.response.parentId] == null) { rootListData.push(data); } + } else { + if (data[_this.response.parentId] == pid){ + if (data[_this.response.treeId] == pid){ + _this.errData.push(data); + } else { + rootListData.push(data); + } + } + } + } + } + return rootListData; + }; + + /** + * @Desc: 初始化渲染树或者拼接渲染树,层级关系模式下 + * @Param: listData: 表示全部数据 + * @Param: level: 当前渲染的层级 + * @Param: $ul: JQuery对象,代表当前数据加载到的ul标签里 + */ + DTree.prototype.loadTree = function(listData, level, $ul){ + var _this = this; + if (listData) { + $ul = $ul || _this.getNodeDom().nowOrRootUl(); //当前选中的节点或根节点 + for (var i = 0; i < listData.length; i++) { // 遍历跟节点或追加的跟节点 + var data = listData[i]; + if(typeof data !== "object") continue; + if(data[_this.response.treeId] == data[_this.response.parentId]) { _this.errData.push(data); } + var parseData = _this.parseData(data); + var children = parseData.children(); + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(children.length), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(level), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), ($ul.hasClass(UL_ROOT) ? "root" : "item"))); + if (children.length != 0) { + var cLevel = parseInt(level)+1; + _this.loadTree(children, cLevel, _this.obj.find("ul[data-id='"+parseData.treeId()+"']")); + } + } + } + }; + + /** + * @Desc: 判断在数据加载时是否存在错误数据,并是否打印错误数据 + * @Param: + */ + DTree.prototype.msgErrData = function() { + var _this = this; + if(_this.errData.length > 0 && _this.errDataShow) { + var title = ""; + for(var i=0; i<_this.errData.length; i++) { + var edata = _this.errData[i]; + title += "数据:【"+edata[_this.response.title]+"】中节点id和上级id值一致! \n"; + } + layer.msg(title, {icon:2,time:5000}); + } + // 显示之后,将错误数据制空 + _this.errData = []; + }; + + /** + * @Desc: 解析单个数据 + * @Param: data: 被解析的单个数据对象 + */ + DTree.prototype.parseData = function(data) { + var _this = this; + + return { + treeId: function(){ + return data[_this.response.treeId]; + }, + parentId: function(){ + return data[_this.response.parentId]; + }, + fmtTitle: function(){ + if(typeof _this.formatter.title === 'function'){ + var ftitle = _this.formatter.title(data); + var tt = data[_this.response.title]; + tt = (ftitle == "" || ftitle == undefined || ftitle == null) ? tt : ftitle; + return tt || ""; + } + return data[_this.response.title]; + }, + title: function(){ + return data[_this.response.title]; + }, + level: function(){ + return data[_this.response.level] || ""; + }, + ficonClass: function(){ + return data[_this.response.ficonClass] || ""; + }, + iconClass: function(){ + return data[_this.response.iconClass] || ""; + }, + last: function(len){ + return ((len == 0) ? + ((typeof (data[_this.response.last]) === "boolean") ? data[_this.response.last] : true) : + ((typeof (data[_this.response.last]) === "boolean") ? data[_this.response.last] : false)); + }, + spread: function(level){ + return ((level < _this.initLevel) ? + ((typeof (data[_this.response.spread]) === "boolean") ? data[_this.response.spread] : true) : + ((typeof (data[_this.response.spread]) === "boolean") ? data[_this.response.spread] : false)); + }, + disabled: function(){ + return (typeof (data[_this.response.disabled]) === "boolean") ? data[_this.response.disabled] : false; + }, + hide: function(){ + return (typeof (data[_this.response.hide]) === "boolean") ? data[_this.response.hide] : false; + }, + checkArr: function(){ + var checkArr = []; + var checkArrData = data[_this.response.checkArr]; + if(typeof checkArrData === 'string'){ + if(checkArrData.indexOf("{") > -1 && checkArrData.indexOf("}") > -1){ + checkArrData = JSON.parse(checkArrData); + } else { + checkArrData = {"type":"0","checked":checkArrData}; + } + } + if((typeof checkArrData === 'object') && (checkArrData !== null)){ + if(typeof checkArrData.length === 'undefined'){ + checkArr.push(checkArrData); + } else { + checkArr = checkArrData; + } + } + + if(checkArr.length > 0 && checkArr.length > _this.checkArrLen){ + _this.checkArrLen = checkArr.length; // 获取复选框个数 + } + return checkArr; + + }, + children: function(){ + return data[_this.response.childName] || []; + }, + basicData: function(){ + return event.escape(JSON.stringify(data[_this.response.basicData])) || JSON.stringify({}); + }, + recordData: function(){ + var recordData = _this.record ? event.cloneObj(data, [_this.response.treeId, + _this.response.parentId, + _this.response.title, + _this.response.iconClass, + _this.response.childName, + _this.response.last, + _this.response.spread, + _this.response.disabled, + _this.response.hide, + _this.response.checkArr, + _this.response.checked, + _this.response.type, + _this.response.basicData]) : {}; + + return event.escape(JSON.stringify(recordData)); + }, + data: function(){ + return data; + } + } + + }; + + /** + * @Desc: 无节点数据、节点数据异常时显示dom + */ + DTree.prototype.getNoneDom = function(){ + var _this = this, + rootId = _this.obj[0].id, + noneTitle = _this.none; + + return { + text: function(){ + return "
                                                                              "+noneTitle+"
                                                                              "; + }, + errText: function(errInfo){ + return "
                                                                              "+errInfo+"
                                                                              "; + } + } + }; + + /** + * @Desc: 新增节点的dom值 + * @Param: treeId: 节点ID + * @Param: parentId: 节点父ID + * @Param: title: 节点标题 + * @Param: fmtTitle: 节点附加标题 + * @Param: last: 是否最后一级节点 + * @Param: ficonClass: 一级图标class + * @Param: iconClass: 二级图标class + * @Param: checkArr: 复选框 + * @Param: spread: 是否展开 + * @Param: disabled: 是否禁用 + * @Param: hide: 是否隐藏 + */ + DTree.prototype.getDom = function(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide) { + var _this = this, + rootId = _this.obj[0].id, + toolbar = _this.toolbar, + checkbar = _this.checkbar; + + return { + fnode: function() { // + - 图标 + // 获取图标的变量 + var fnodeIcon = _this.fnodeIcon, + fleafIcon = _this.fleafIcon; + + var fleafIconLeaf = _this.usefontStyle.fnode.leaf, + fnodeIconOpen = _this.usefontStyle.fnode.node.open, + fnodeIconClose = _this.usefontStyle.fnode.node.close; + + if(ficonClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + fleafIconLeaf = iconfont + " " + ficonClass; + fnodeIconOpen = iconfont + " " + ficonClass; + fnodeIconClose = iconfont + " " + ficonClass; + } else { + fleafIconLeaf = iconfont[0] + " " + ficonClass; + fnodeIconOpen = iconfont[0] + " " + ficonClass; + fnodeIconClose = iconfont[0] + " " + ficonClass; + } + } + + if(fnodeIcon != "-1" && fleafIcon != "-1"){ // 都加载 + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon != "-1" && fleafIcon == "-1"){ // 加载node 隐藏leaf + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon == "-1" && fleafIcon != "-1"){ // 隐藏node 加载leaf + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon == "-1" && fleafIcon == "-1"){ // 都隐藏 + return last ? "" : + (spread ? "" : ""); + } + }, + node: function() { // 二级图标样式 + // 获取图标的变量 + var nodeIcon = _this.nodeIcon, + leafIcon = _this.leafIcon; + + var sleafIconLeaf = _this.usefontStyle.snode.leaf, + snodeIconOpen = _this.usefontStyle.snode.node.open, + snodeIconClose = _this.usefontStyle.snode.node.close; + if(iconClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + sleafIconLeaf = iconfont + " " + iconClass; + snodeIconOpen = iconfont + " " + iconClass; + snodeIconClose = iconfont + " " + iconClass; + } else { + sleafIconLeaf = iconfont[0] + " " + iconClass; + snodeIconOpen = iconfont[0] + " " + iconClass; + snodeIconClose = iconfont[0] + " " + iconClass; + } + } + + if(nodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + return last ? "" : + (spread ? "" : ""); + } + }, + checkbox: function() { // 复选框 + var flag = false; + if(_this.checkbarLoad == "node"){if (checkbar) {flag = true;}} else {if (last) {if (checkbar) {flag = true;}}} + + if(flag){ + var result = "
                                                                              "; + if(checkArr && checkArr.length > 0){ + + for (var i = 0; i < checkArr.length; i++) { + var checkData = checkArr[i]; + var checked = checkData[_this.response.checked]; + var type = checkData[_this.response.type]; + var CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + if (checked == "2") { //半选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.noall + " " + _this.style.chs; + } else if (checked == "1") { //选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.on + " " + _this.style.chs; + } else { //未选择或者无值 + CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + } + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + result += ""; + } + } + result += "
                                                                              "; + return result; + } + + return ""; + }, + text: function() { // 文字显示 + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + return ""+fmtTitle+""; + }, + ul: function() { //子节点ul + return last ? "
                                                                                " : + (spread ? "
                                                                                  " : "
                                                                                    "); + } + }; + }; + + /** + * @Desc: 替换节点的dom值,或指定这些值 + * @Param: $div: JQuery对象,表示当前被操作的节点 + * @Param: treeId: 节点ID + * @Param: last: 是否最后一级节点 + * @Param: spread: 是否展开 + * @Param: disabled: 是否禁用 + * @Param: hide: 是否隐藏 + */ + DTree.prototype.replaceDom = function($div, treeId, last, spread, disabled, hide) { + var _this = this, + rootId = _this.obj[0].id, + toolbar = _this.toolbar, + checkbar = _this.checkbar; + + return { + fnode: function(ficonClass) { // + - 图标 + var fnode = ""; + + // 获取图标的变量 + var fnodeIcon = _this.fnodeIcon, + fleafIcon = _this.fleafIcon; + + var fleafIconLeaf = _this.usefontStyle.fnode.leaf, + fnodeIconOpen = _this.usefontStyle.fnode.node.open, + fnodeIconClose = _this.usefontStyle.fnode.node.close; + + if(ficonClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + fleafIconLeaf = iconfont + " " + ficonClass; + fnodeIconOpen = iconfont + " " + ficonClass; + fnodeIconClose = iconfont + " " + ficonClass; + } else { + fleafIconLeaf = iconfont[0] + " " + ficonClass; + fnodeIconOpen = iconfont[0] + " " + ficonClass; + fnodeIconClose = iconfont[0] + " " + ficonClass; + } + } + + if(fnodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + fnode = last ? "" : + (spread ? "" : ""); + } + if(fnode != ""){_this.getNodeDom($div).fnode().replaceWith($(fnode));} + }, + node: function(iconClass) { // 二级图标样式 + var snode = ""; + + // 获取图标的变量 + var nodeIcon = _this.nodeIcon, + leafIcon = _this.leafIcon; + + var sleafIconLeaf = _this.usefontStyle.snode.leaf, + snodeIconOpen = _this.usefontStyle.snode.node.open, + snodeIconClose = _this.usefontStyle.snode.node.close; + if(iconClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + sleafIconLeaf = iconfont + " " + iconClass; + snodeIconOpen = iconfont + " " + iconClass; + snodeIconClose = iconfont + " " + iconClass; + } else { + sleafIconLeaf = iconfont[0] + " " + iconClass; + snodeIconOpen = iconfont[0] + " " + iconClass; + snodeIconClose = iconfont[0] + " " + iconClass; + } + } + + if(nodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + snode = last ? "" : + (spread ? "" : ""); + } + if(snode != ""){_this.getNodeDom($div).snode().replaceWith($(snode));} + }, + checkbox: function(checkArr) { // 复选框 + var flag = false; + if(_this.checkbarLoad == "node"){if (checkbar) {flag = true;}} else {if (last) {if (checkbar) {flag = true;}}} + + if(flag){ + var result = "
                                                                                    "; + if(checkArr && checkArr.length > 0){ + + for (var i = 0; i < checkArr.length; i++) { + var checkData = checkArr[i]; + var checked = checkData[_this.response.checked]; + var type = checkData[_this.response.type]; + var CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + if (checked == "2") { //半选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.noall + " " + _this.style.chs; + } else if (checked == "1") { //选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.on + " " + _this.style.chs; + } else { //未选择或者无值 + CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + } + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + result += ""; + } + } + result += "
                                                                                    "; + _this.getNodeDom($div).snode().next("div").replaceWith($(result)); + } + }, + text: function(title) { // 文字显示 + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + var cite = ""+title+"" + _this.getNodeDom($div).cite().replaceWith($(cite)); + }, + ul: function() { //子节点ul + var ul = last ? "
                                                                                      " : + (spread ? "
                                                                                        " : "
                                                                                          "); + _this.getNodeDom($div).nextUl().replaceWith($(ul)); + }, + div: function(){ + $div.attr("data-id", treeId); + }, + basicData: function(basicData){ + basicData = (basicData == "{}") ? "" : basicData; + $div.attr("data-basic", basicData); + }, + recordData: function(recordData){ + recordData = (recordData == "{}") ? "" : recordData; + $div.attr("data-record", recordData); + }, + p_li: function(pId){ + var $li = $div.parent("li"); + $li.attr("data-id", treeId); + if(pId) { + $li.attr("data-pid", pId); + } + return $li; + } + }; + + }; + + /** + * @Desc: 获取拼接好的li的dom + * @Param: treeId: 节点ID + * @Param: parentId: 节点父ID + * @Param: title: 节点标题 + * @Param: fmtTitle: 节点附加标题 + * @Param: last: 是否最后一级节点 + * @Param: ficonClass: 一级图标class + * @Param: iconClass: 二级图标class + * @Param: checkArr: 复选框 + * @Param: level: 当前li的层级 + * @Param: spread: 是否展开 + * @Param: disabled: 是否禁用 + * @Param: hide: 是否隐藏 + * @Param: basicData: 自定义的扩展字段值(转义后的JSON字符) + * @Param: recordData: 开启记录模式的记录值(转义后的JSON字符) + * @Param: isRoot: 当前节点是否是根节点下的节点 + */ + DTree.prototype.getLiItemDom = function(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide, basicData, recordData, isRoot) { + var _this = this, + rootId = _this.obj[0].id; + + var dom = _this.getDom(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide); + basicData = (basicData == "{}") ? "" : basicData; + recordData = (recordData == "{}") ? "" : recordData; + var div = "
                                                                                          " + + div , + dom.fnode(), + dom.node(), + dom.checkbox(), + dom.text(), + "
                                                                                          ", dom.ul(), ""].join(""); + + return li; + }; + + /** + * @Desc: 初始化节点,用于数据回显 + * @Param: chooseId: 节点ID + */ + DTree.prototype.dataInit = function(chooseId){ + var _this = this; + var $div = _this.obj.find("div[data-id='"+chooseId+"']"); + if($div && $div.length > 0) { + _this.obj.find("."+NAV_THIS).removeClass(NAV_THIS); + _this.obj.find("."+_this.style.itemThis).removeClass(_this.style.itemThis); + $div.addClass(NAV_THIS); + $div.addClass(_this.style.itemThis); + _this.setNodeParam($div); + // 将该节点的父节点全部展开 + var $li_parents = $div.parents("."+LI_NAV_ITEM); + $li_parents.children("ul").addClass(NAV_SHOW); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.fnode.node.close)).addClass(_this.usefontStyle.fnode.node.open); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.fnode.node.close)).removeClass(_this.usefontStyle.fnode.node.close); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.snode.node.close)).addClass(_this.usefontStyle.snode.node.open); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.snode.node.close)).removeClass(_this.usefontStyle.snode.node.close); + } + return _this.getNowParam(); + }; + + /** + * @Desc: 基于备份的Html数据回滚 + * @Param: chooseId: 节点ID + */ + DTree.prototype.rollbackHtml = function(chooseId){ + var _this = this; + if(_this.bak) { + _this.obj.html(_this.bak); + // 取消全部选中状态 + _this.cancelNavThis(); + if(_this.checkbar) { + _this.cancelCheckedNode(); + _this.chooseDataInit(chooseId); + } else { + _this.dataInit(chooseId); + } + + _this.bak = _this.obj.html(); + } + }; + + + /******************** 基础事件区域 ********************/ + /** + * @Desc: 数据格式化 + * @Param: html: 需要格式化的数据 + */ + DTree.prototype.escape = function(html){ + return event.escape(html); + }; + + /** + * @Desc: 格式化数据转回正常数据 + * @Param: str: 需要转回的数据 + */ + DTree.prototype.unescape = function(str){ + return event.unescape(str); + }; + + /** + * @Desc: 取消选中当前选中的div + */ + DTree.prototype.cancelNavThis = function(){ + var _this = this; + _this.obj.find("div[data-id]").parent().find("."+NAV_THIS).removeClass(NAV_THIS); + _this.obj.find("div[data-id]").parent().find("."+_this.style.itemThis).removeClass(_this.style.itemThis); + } + + /** + * @Desc: 选中div + * @Param: id: 当前div本身 / 当前选中div的id值 + */ + DTree.prototype.navThis = function(id){ + var _this = this; + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null) { + _this.cancelNavThis(); + $div.addClass(NAV_THIS); + $div.addClass(_this.style.itemThis); + } + } + + /** + * @Desc: 手风琴模式操作其他节点 + * @Param: $ul: JQuery对象,表示dtree中的ul节点 + */ + DTree.prototype.accordionUL = function($ul) { + var _this = this; + if(_this.accordion) { + $ul.closest("li[data-index]").siblings("li[data-index]").children("ul[data-id]").removeClass(NAV_SHOW); + var $divs = $ul.closest("li[data-index]").siblings("li[data-index]").children("ul[data-id]").prev("div"); + if($divs.length && $divs.length > 0) { + for (var i=0; i<$divs.length; i++) { + var $div = $($divs[i]); + var $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(); + if($i_fnode.attr("data-spread") != 'last'){ + _this.operateIcon($i_fnode, $i_snode).close(); + } + } + } + + } + }; + + /** + * @Desc: 展开或隐藏节点 作用点: div + * @Param: $div: JQuery对象,表示当前操作的div节点 + */ + DTree.prototype.clickSpread = function($div) { + var _this = this; + var $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_fnode.attr("data-spread"), + $ul = $div.next("ul"); + + if ($ul.length > 0) { + if (spread == "close") { + if (_this.type=="load") { //增加加载 + if (_this.cache) { //开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + _this.accordionUL($ul); + } else { //加载节点 + _this.getChild($div); + _this.accordionUL($ul); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + _this.accordionUL($ul); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + _this.accordionUL($ul); + } + _this.operateIcon($i_fnode, $i_snode).open(); + } else if (spread == "open") { + $ul.removeClass(NAV_SHOW); + _this.operateIcon($i_fnode, $i_snode).close(); + } + } + }; + + /** + * @Desc: 设置节点为disabled + * @Param: disabledIds: 需要设置禁用的节点id字符串集合(用,分割)/id数组 + */ + DTree.prototype.setDisabledNodes = function(disabledIds){ + var _this = this; + var disabledId = []; + if(typeof disabledIds === "string") { + disabledId = disabledIds.split(","); + } else { + disabledId = disabledIds; + } + + if(disabledIds.length) { + for (var i=0; i 0) { + _this.getChild($div, data); + } else { + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var level = parseInt($div.parent("li").attr("data-index"))+1; + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(0), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), "item")); + + // 建造完毕后,选中该DIV + $thisDiv = $ul.find("div[data-id='"+parseData.treeId()+"']"); + _this.setNodeParam($thisDiv); + + _this.showLine($ul.find("li")); + } else { + layer.msg("添加失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } + } else { + _this.getChild($div); + } + } + + /** + * @Desc: 局部刷新树--编辑当前节点选中节点时 + * @Param: $div: JQuery对象,当前编辑节点的Div + * @Param: data: 当前需要渲染的数据,JSON对象、字符串 + */ + DTree.prototype.partialRefreshEdit = function($div, data){ + var _this = this; + $ul = $div.next("ul"), + $p_li = $div.parent("li"); + + if(data) { + if(typeof data === 'object') { + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var replaceDom = _this.replaceDom($div, parseData.treeId(), parseData.last(0), parseData.spread(), parseData.disabled(), parseData.hide()); + replaceDom.div(); + replaceDom.node(parseData.iconClass()); + replaceDom.checkbox(parseData.checkArr()); + replaceDom.text(parseData.title()); + replaceDom.ul(); + replaceDom.basicData(parseData.basicData()); + replaceDom.recordData(parseData.recordData()); + + var parentId = parseData.parentId(); + var oldParentId = $p_li.attr("data-pid"); + if(parentId && parentId != oldParentId) { + // 变更了父节点 + $p_li = replaceDom.p_li(parentId); + + // 根据parentId找到下挂节点的ul + var $goto_div = _this.getNodeDom(parentId).div(), + $goto_ul = _this.getNodeDom(parentId).nextUl(); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($goto_ul.children("li").length == 0){ + var $icon_i = $goto_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).openWithLeaf(); + $goto_ul.addClass(NAV_SHOW); + } + $goto_ul.append($p_li); + } else { + replaceDom.p_li(); + } + _this.setNodeParam($div); + } else { + layer.msg("编辑失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } else { + _this.getNodeDom($div).cite().html(data); + } + } + } + + /** + * @Desc: 局部刷新树--当前节点选中被删除时 + * @Param: $div: JQuery对象,当前被删除节点的Div + */ + DTree.prototype.partialRefreshDel = function($div){ + var _this = this; + $p_li = $div.parent("li"); + $p_ul = _this.getNodeDom($div).parentUl(); + $p_div = _this.getNodeDom($div).parentDiv(); + + $p_li.remove(); + _this.showLine($p_ul.find("li")); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($p_ul.children("li").length == 0){ + var $icon_i = $p_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).closeWithLeaf(); + } + _this.initNodeParam(); + } + + /*** + * @Desc: 搜索节点,保留上级节点 + * @param: value: 传入的节点名称 + * layui-dtree群友: 没水平的水瓶提供。 + */ + DTree.prototype.fuzzySearch = function (value) { + var _this = this; + // + if (value.trim() == '') { + _this.obj.find("li").removeClass("layui-hide").attr("dtree-hide", false) + return + } + _this.obj.find("li").addClass("layui-hide").attr("dtree-hide", true) + + var cites = [] + var filterMode = _this.filterMode + /*if (filterMode == 'default') { + cites = _this.obj.find("li>div cite:contains('" + value + "')"); + }*/ + cites = _this.obj.find("li>div cite:contains('" + value + "')"); + cites.each(function (index, cite) { + var li = $(cite).parent().parent(); + var curNode = _this.getParam(li.attr("data-id")); + li.removeClass("layui-hide").attr("dtree-hide", false); + // 显示所有子级 + li.find('ul li').removeClass("layui-hide").attr("dtree-hide", false); + // 显示所有父级 + li.parents('li').removeClass("layui-hide").attr("dtree-hide", false); + }) + } + + /******************** 复选框区域 ********************/ + /** + * @Desc: 初始化复选框的值 + * @Param: chooseIds: 需要被选中的节点id字符串集合(用,分割)/id数组/id二维数组(多级复选框) + */ + DTree.prototype.chooseDataInit = function(chooseIds){ + var _this = this; + // 多级复选框二维数组 + var chooseIdArrs = []; + var chooseId = []; + if(typeof chooseIds === "string") { + chooseId = chooseIds.split(","); + } else { + chooseId = chooseIds; + } + if(chooseId.length) { + // 说明是数组 + for (var i=0; i."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + if (flag == 0) { + //把父级去掉选中 + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($item_i).noCheck(); + } + } + } else { + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + //把父级选中 + _this.checkStatus($item_i).check(); + } + } + }; + + /** + * @Desc: 实现复选框点击, no-all 子集选中父级半选中,子集全选父级选中 + * @Param: $i: JQuery对象,表示当前点击的checkbox节点 + */ + DTree.prototype.checkAllOrNoallOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag == 0) { + //把父级去掉选中 + _this.checkStatus($item_i).noCheck(); + } else { + //把父级半选 + _this.checkStatus($item_i).noallCheck(); + } + } + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag1 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var flag2 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag1 != flag2) { + // 父级复选框半选 + _this.checkStatus($item_i).noallCheck(); + } else { + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + }; + + /** + * @Desc: 实现复选框点击,p-casc:父级选中子集全选,子集无法改变父级选中状态 + * @Param: $i: JQuery对象,表示当前点击的checkbox节点 + */ + DTree.prototype.checkAllOrPcascOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + } + }; + + /** + * @Desc: 实现复选框点击,self:各自选中互不影响 + * @Param: $i: JQuery对象,表示当前点击的checkbox节点 + */ + DTree.prototype.checkOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + } + }; + + /** + * @Desc: 实现复选框点击,only:只能选中1个复选框 + * @Param: $i: JQuery对象,表示当前点击的checkbox节点 + */ + DTree.prototype.checkOnly = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + var checked = $i.attr("data-checked"); + // 将全部节点全部设为未选中状态 + var $all_i = _this.obj.find("i[data-checked]"); + _this.checkStatus($all_i).noCheck(); + + if (checked != "1") { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + } + }; + + /** + * @Desc: 实现复选框点击汇总,分派具体的点击方式 + * @Param: $i: JQuery对象,表示当前点击的checkbox节点 + */ + DTree.prototype.changeCheck = function($i) { + var _this = this; + var temp = _this.temp; + if(typeof $i === 'undefined') { + $i = temp[0]; + } + // 复选框选中事件 + if (_this.checkbarType == "all") { + _this.checkAllOrNot($i); + } else if(_this.checkbarType == "no-all") { + _this.checkAllOrNoallOrNot($i); + } else if(_this.checkbarType == "p-casc") { + _this.checkAllOrPcascOrNot($i); + } else if(_this.checkbarType == "self") { + _this.checkOrNot($i); + } else if(_this.checkbarType == "only") { + _this.checkOnly($i); + } else { + _this.checkAllOrNot($i); + } + + if(_this.select) { + // 设置复选框模式中的下拉树的值 + _this.selectCheckboxVal(); + } + + // 获取复选框选中节点的内容 + var checkbarNodes = _this.setAndGetCheckbarNodesParam(true); + + // 用户自定义想做的事情 + _this.checkbarFun.chooseDone(checkbarNodes); + layui.event.call(this, MOD_NAME, "chooseDone("+$(_this.obj)[0].id+")", {"checkbarParams": checkbarNodes}); + _this.temp = []; + }; + + /** + * @Desc: 复选框半选状态初始化设置,树节点渲染完毕后重置半选状态 + */ + DTree.prototype.initNoAllCheck = function(){ + var _this = this; + //1.获取所有选中节点 + var $is = _this.obj.find("i[data-checked='1']"); + if($is.length > 0){ + for ( var key = 0; key < $is.length; key++) { + var $i = $($is[key]), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag1 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var flag2 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag1 != flag2) { + // 父级复选框半选 + _this.checkStatus($item_i).noallCheck(); + } else { + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + } + }; + + /** + * @Desc: 复选框选中状态初始化设置,树节点渲染完毕后重置选中状态 + */ + DTree.prototype.initAllCheck = function(){ + var _this = this; + //1.获取所有选中节点 + var $is = _this.obj.find("i[data-checked='1']"); + if($is.length > 0){ + for ( var key = 0; key < $is.length; key++) { + var $i = $($is[key]), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + }; + + /** + * @Desc: 设置复选框选中/未选中/半选 _this.checkStatus($i).check(); _this.checkStatus($i).noCheck(); _this.checkStatus($i).noallCheck(); + * @Param: $i: JQuery对象,表示当前点击的checkbox节点 + */ + DTree.prototype.checkStatus = function($i) { + var _this = this; + return { + check: function(){ + $i.removeClass(_this.usefontStyle.checkbox.out); + $i.removeClass(_this.usefontStyle.checkbox.noall); + $i.addClass(_this.usefontStyle.checkbox.on); + $i.addClass(_this.style.chs); + $i.attr("data-checked","1"); + }, + noCheck: function(){ + $i.removeClass(_this.usefontStyle.checkbox.noall); + $i.removeClass(_this.usefontStyle.checkbox.on); + $i.removeClass(_this.style.chs); + $i.addClass(_this.usefontStyle.checkbox.out); + $i.attr("data-checked","0"); + }, + noallCheck: function(){ + $i.removeClass(_this.usefontStyle.checkbox.out); + $i.removeClass(_this.usefontStyle.checkbox.on); + $i.addClass(_this.usefontStyle.checkbox.noall); + $i.addClass(_this.style.chs); + $i.attr("data-checked","2"); + } + } + }; + + /** + * @Desc: 设置树的复选框操作值的全部参数,并获取 + * @Param: requestParamFlag: 设置复选框返回值的数据结构, true:基于请求类型的返回对象数组, false:原始的节点返回对象数组 + */ + DTree.prototype.setAndGetCheckbarNodesParam = function(requestParamFlag) { + var _this = this; + //操作前先清空 + _this.checkbarNode = []; + // 选择所有复选框节点 + if (_this.checkbarData == "change"){ //记录变更数据 + _this.obj.find("i[data-par][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if ($i.attr("data-checked") != $i.attr("data-initchecked")) { + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + } + }); + } else if (_this.checkbarData == "all"){ //记录全部数据 + _this.obj.find("i[data-par][data-checked][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } else if (_this.checkbarData == "choose"){ //记录选中数据 + _this.obj.find("i[data-par][data-checked='1'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } else if (_this.checkbarData == "halfChoose"){ //记录选中和半选数据 + _this.obj.find("i[data-par][data-checked='1'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + _this.obj.find("i[data-par][data-checked='2'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } + return _this.checkbarNode; + }; + + /** + * @Desc: 获取树的复选框操作值的全部参数 + */ + DTree.prototype.getCheckbarNodesParam = function() { + var _this = this; + return _this.setAndGetCheckbarNodesParam(true); + }; + + /** + * @Desc: 获取树的一个复选框的参数 + * @Param: $div: JQuery对象,表示当前选中节点 + * @Param: $i: JQuery对象,表示当前选中的复选框节点 + */ + DTree.prototype.getCheckbarNodeParam = function($div, $i){ + var _this = this; + var temp_node = {}; + temp_node.nodeId = $div.attr("data-id"); + temp_node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + temp_node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + temp_node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + temp_node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + temp_node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + temp_node.basicData = basicData; + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + temp_node.recordData = recordData; + + temp_node.dataType = $i.attr("data-type"); + temp_node.checked = $i.attr("data-checked"); + temp_node.initchecked = $i.attr("data-initchecked"); + return temp_node; + }; + + /** + * @Desc: 获取基于返回参数的树的复选框参数,选中数据横向存储 + */ + DTree.prototype.getCheckbarJsonArrParam = function(){ + var _this = this; + var checkbarJsonArr = { + nodeId: [], //节点ID + parentId: [], //父节点ID + context: [], //节点内容 + leaf: [], //是否叶子节点 + level: [], //层级 + spread: [], //节点展开状态 + dataType: [], //节点标记 + checked: [], //节点复选框选中状态 + initchecked: [], //节点复选框初始状态 + basicData: [], //用户自定义的记录节点数据 + recordData: [], //当前data数据(排除basicData和children字段) + }; + // 获取全部复选框选中节点 + var params = _this.setAndGetCheckbarNodesParam(false); + if(params && params.length > 0) { + for(var i=0; i 0) { _this.checkStatus($i).check(); } + } + + /** + * @Desc: 取消全部复选框选中 + */ + DTree.prototype.cancelCheckedNode = function(){ + var _this = this; + var $i = _this.obj.find("i[data-par][data-checked!='0']"); + if($i.length > 0) { _this.checkStatus($i).noCheck(); } + } + + /** + * @Desc: 反选复选框 + */ + DTree.prototype.invertCheckedNode = function(){ + var _this = this; + if(_this.obj.find("i[data-par]").length > 0) { + var flag = false; + _this.obj.find("i[data-par]").each(function(){ + var $i = $(this); + if($i.attr("data-checked") == '2'){ + flag = true; + }else if($i.attr("data-checked") == '0') { + _this.checkStatus($i).check(); + }else if($i.attr("data-checked") == '1') { + _this.checkStatus($i).noCheck(); + } + }); + + if(flag) { + _this.initNoAllCheck(); + } else { + _this.initAllCheck(); + } + } + } + + /** + * @Desc: 删除选中节点 + */ + DTree.prototype.removeCheckedNode = function(){ + var _this = this; + var len = _this.obj.find("i[data-par][data-checked='1']").length; + if(len == 0){ + layer.msg("请至少选中一个节点",{icon:2}); + }else{ + //操作前先清空 + _this.checkbarNode = []; + // 选择所有复选框节点 + var i_node = {}; + _this.obj.find("i[data-par][data-checked='1']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + }); + + layer.confirm('确定要删除选中节点?', {icon: 3, title:'删除选中节点'}, function(index1){ + var flag = _this.menubarFun.remove(_this.checkbarNode); + if(flag){ + _this.obj.find("i[data-par][data-checked='1']").closest("."+LI_DIV_ITEM).next("ul").remove(); + _this.obj.find("i[data-par][data-checked='1']").closest("."+LI_DIV_ITEM).remove(); + _this.checkbarNode=[]; + } + + layer.close(index1); + }); + } + } + + /******************** 工具栏及菜单栏区域 ********************/ + /** + * @Desc: 初始化菜单栏和工具栏的div + */ + DTree.prototype.initTreePlus = function(){ + var _this = this; + // 初始化菜单栏和工具栏的div + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).remove(); + _this.toolbarMenu = {}; + if(_this.menubar && _this.menubarTips.group && _this.menubarTips.group.length > 0) _this.obj.before("
                                                                                          "); + if(_this.toolbar){ + if(_this.toolbarWay == "contextmenu") { + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).remove(); + if(_this.toolbarShow && _this.toolbarShow.length > 0) { + _this.obj.before("
                                                                                          "); + } + } + } + + }; + + /** + * @Desc: 开启工具栏和菜单栏 + */ + DTree.prototype.openTreePlus = function(){ + var _this = this; + // 先对工具栏做处理,因为菜单栏可能会与工具栏产生关联。 + var ggMenu = []; + if(_this.toolbar) _this.getToolbarDom(); + + if(_this.menubar) { + var menubarTips = _this.menubarTips, + mtbar = menubarTips.toolbar, + group = menubarTips.group, + freedom = menubarTips.freedom; + if(mtbar && mtbar.length > 0){ + // 菜单栏吸附工具栏上 + for(var i=0; i 0){ + // 菜单栏吸附在上方的按钮组div中 + for(var i=0; i"; + break; + case defaultMenu.moveUp: + gg = ""; + break; + case defaultMenu.refresh: + gg = ""; + break; + case defaultMenu.checkAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.unCheckAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.invertAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.remove: + gg = (_this.checkbar) ? "" : ""; + break; + case defaultMenu.searchNode: + gg = ""; + break; + } + return gg; + }; + + /** + * @Desc: 获取扩展菜单栏 + * @Param: menu: 扩展菜单栏的Json对象 + */ + DTree.prototype.getExtMenubarDom = function(menu){ + var _this = this; + return ""; + }; + + /** + * @Desc: 获取依附在工具栏的菜单栏 + * @Param: menu: 菜单栏的具体操作字符串 + */ + DTree.prototype.getMenubarToolDom = function(menu){ + var _this = this; + var rootId = _this.obj[0].id; + switch (menu) { + case defaultMenu.moveDown: + _this.toolbarMenu[defaultMenu.moveDown] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.moveDown, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.movedown, "展开全部"); + break; + case defaultMenu.moveUp: + _this.toolbarMenu[defaultMenu.moveUp] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.moveUp, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.moveup, "收缩全部"); + break; + case defaultMenu.refresh: + _this.toolbarMenu[defaultMenu.refresh] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.refresh, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.refresh, "刷新"); + break; + case defaultMenu.checkAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.checkAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.checkAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.checkAll, "全选节点"); + break; + case defaultMenu.unCheckAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.unCheckAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.unCheckAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.unCheckAll, "全不选节点"); + break; + case defaultMenu.invertAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.invertAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.invertAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.invertAll, "反选节点"); + break; + case defaultMenu.remove: + if(_this.checkbar) + _this.toolbarMenu[defaultMenu.remove] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.remove, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.remove, "删除选中"); + break; + case defaultMenu.searchNode: + _this.toolbarMenu[defaultMenu.searchNode] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.searchNode, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.searchNode, "查询"); + break; + } + }; + + /** + * @Desc: 获取依附在工具栏的扩展菜单栏 + * @Param: menu: 扩展菜单栏的Json对象 + */ + DTree.prototype.getExtMenubarToolDom = function(menu){ + var _this = this; + _this.toolbarMenu[menu.menubarId] = _this.setToolbarDom().setMenuToolbarOption(menu.menubarId, menu.title, _this.usefontStyle.toolbar.menubarExt+" "+menu.icon, ""); + }; + + /** + * @Desc: menubar内置方法 + */ + DTree.prototype.menubarMethod = function(){ + var _this = this; + return { + openAllNode: function(obj){ // 展开所有节点 + var $ulNode = obj || _this.obj.children("li").children("ul"); + // 遍历所有ul子节点 + for (var i = 0; i < $ulNode.length; i++) { + // 获取当前节点的信息 + var $ul = $($ulNode[i]), + $div = $ul.prev("div"), + $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_fnode.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + if (leaf == "leaf") { + continue; + } // 说明是叶子了,则继续循环下一个 + + if (spread == "open") { + // 说明该节点已经展开了,则进行子节点循环 + } else { + if (_this.type=="load") { //是否全量加载 + if (_this.cache) { //是否开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + } else { //加载节点 + _this.getChild($div); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + } + _this.operateIcon($i_fnode, $i_snode).open(); + + } + var $childUl = $ul.children("li").children("ul"); + _this.menubarMethod().openAllNode($childUl); + } + }, + closeAllNode: function(){ //收缩所有节点 + _this.obj.find("."+LI_NAV_CHILD).each(function(){ + // 获取当前节点的信息 + var $ul = $(this), + $div = $ul.prev("div"), + $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_fnode.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + $ul.removeClass(NAV_SHOW); + if(leaf !== "leaf") { + _this.operateIcon($i_fnode, $i_snode).close(); + } + }); + }, + refreshTree: function(){// 刷新树 + _this.refreshTree(); + }, + checkAll: function(){ // 全选节点 + _this.checkAllNode(); + }, + unCheckAll: function(){ // 全不选节点 + _this.cancelCheckedNode(); + }, + invertAll: function(){ // 反选节点 + _this.invertCheckedNode(); + }, + remove: function(){// 删除选中节点 + _this.removeCheckedNode(); + }, + searchNode: function(){//模糊查询该值,展开该值节点 + layer.prompt({ + formType: 0, + value: "", + title: '查询节点' + }, function(value, index1, elem){ + if (value) { + var flag = _this.searchNode(value); + if (!flag) { + layer.msg("该名称节点不存在!", {icon:5}); + } + } else { + layer.msg("未指定查询节点名称", {icon:5}); + } + layer.close(index1); + }); + }, + extMethod: function(menuId, $div, flag){ + if(_this.menubar && _this.menubarTips.group && _this.menubarTips.group.length > 0 && flag == "group"){ + for(var i=0; i<_this.menubarTips.group.length; i++){ + var ext = _this.menubarTips.group[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + if(_this.menubar && _this.menubarTips.toolbar && _this.menubarTips.toolbar.length > 0 && flag == "toolbar"){ + for(var i=0; i<_this.menubarTips.toolbar.length; i++){ + var ext = _this.menubarTips.toolbar[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + if(_this.menubar && _this.menubarTips.freedom && _this.menubarTips.freedom.length > 0 && flag == "freedom"){ + for(var i=0; i<_this.menubarTips.freedom.length; i++){ + var ext = _this.menubarTips.freedom[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + } + }; + }; + + /** + * @Desc: menubar监听方法 + * @Param: menuId:菜单栏的具体操作字符串 + * @Param: flag:菜单栏的显示方式 + */ + DTree.prototype.menubarListener = function(menuId, flag){ + var _this = this; + var $div = _this.getNodeDom().nowDiv(); + switch (menuId) { + case defaultMenu.moveDown: // 展开全部节点 + _this.menubarMethod().openAllNode(); + break; + case defaultMenu.moveUp: // 收缩全部节点 + _this.menubarMethod().closeAllNode(); + break; + case defaultMenu.refresh: + _this.menubarMethod().refreshTree(); // 刷新树 + break; + case defaultMenu.checkAll: + _this.menubarMethod().checkAll(); + break; + case defaultMenu.unCheckAll: + _this.menubarMethod().unCheckAll(); + break; + case defaultMenu.invertAll: + _this.menubarMethod().invertAll(); + break; + case defaultMenu.remove: + _this.menubarMethod().remove(); + break; + case defaultMenu.searchNode: + _this.menubarMethod().searchNode(); + break; + default: + _this.menubarMethod().extMethod(menuId, $div, flag); + break; + } + }; + + /** + * @Desc: 模糊查询该值,展开该值节点 + * @Param: value: 模糊查询的值 + */ + DTree.prototype.searchNode = function(value){ + var _this = this; + var b = false; + var $lis = []; + _this.obj.find("cite[data-leaf]").each(function(){ + var $nthis = $(this); + var html = $nthis.html(); + if(html.indexOf(value) > -1){ + if($nthis.attr("data-leaf") == "leaf") { + // 叶子节点提供包含父节点的所有信息 + var title = ""; + $nthis.parents("li").each(function(){ + title = "-" + $(this).find("cite[data-leaf]").html() + title; + }); + title = title.substring(1, title.length); + $nthis.attr("title", title); + } + // 保存当前cite所在的li及父li中包含该值,则只保留父的 + var i = 0; + $nthis.parents("li").each(function(){ + var html2 = $(this).find("cite[data-leaf]").html(); + if(html2.indexOf(value) > -1){ + i++; + } + if(i >= 2){ + return true; + } + }); + if (i < 2){ + $lis.push($nthis.closest("li").prop("outerHTML")); + } + } + }); + if($lis.length > 0) { + b = true; + // 1.将树节点清空 + _this.obj.html(""); + // 2.遍历所有cite节点,展开当前cite节点 + for(var i=0; i<$lis.length; i++){ + _this.obj.append($lis[i]); + } + } + return b; + }; + + + /******************** 工具栏区域 ********************/ + /** + * @Desc: 获取工具栏 + */ + DTree.prototype.getToolbarDom = function(){ + var _this = this; + var toolbarShow = _this.toolbarShow, + toolbarExt = _this.toolbarExt, + toolbarWay = _this.toolbarWay; + + if(toolbarShow.length > 0){ + for(var i=0; i 0){ + for(var i=0; i "+other +title+""; + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + return ""; + } + }, + setMenuToolbarOption: function(menubarId, title, classId, other){ + var rootId = _this.obj[0].id; + if(toolbarWay == "contextmenu") { + return "
                                                                                           "+other +title+"
                                                                                          "; + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + return ""; + } + }, + setToolbarPlace: function(toolbarMenu){ + if(toolbarWay == "contextmenu") { + if(toolbarMenu){ + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).find('div.layui-nav-item>dl.layui-nav-child').html(""); + for(var key in toolbarMenu){ + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).find('div.layui-nav-item>dl.layui-nav-child').append(toolbarMenu[key]); + } + } + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + _this.obj.find("cite[data-leaf][dtree-disabled='false']").each(function(){ + var $cite = $(this); + _this.dynamicToolbarDom($cite); + }); + } + } + } + }; + + /** + * @Desc: 在节点后动态绑定fixed和follow条件的工具栏 + * @Param: $cite: JQuery对象,表示当前文本节点 + */ + DTree.prototype.dynamicToolbarDom = function($cite){ + var _this = this; + var toolbarWay = _this.toolbarWay; + if($cite.next("em."+TOOLBAR_TOOL_EM).length == 0) { + var $div = $cite.parent("div"); + var param = _this.getRequestParam(_this.getTempNodeParam($div)); + var toolbarMenus = _this.toolbarFun.loadToolbarBefore(event.cloneObj(_this.toolbarMenu), param, $div); + var hideCls = (toolbarWay == "follow") ? NAV_HIDE : ""; + var em = [""]; + if(toolbarMenus){ + for(var key in toolbarMenus){ + em.push(toolbarMenus[key]); + } + } + em.push(""); + $cite.after(em.join('')); + } + } + + /** + * @Desc: 隐藏toolbar + */ + DTree.prototype.toolbarHide = function() { + var _this = this; + if(_this.toolbar && _this.toolbarWay == "contextmenu") { + var $toolBarDiv = _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id); + $toolBarDiv.find(".layui-nav-child").removeClass('layui-anim-fadein layui-show'); + } + } + + /** + * @Desc: toolbar内置方法 + */ + DTree.prototype.toolbarMethod = function(){ + var _this = this; + return { + pulldown: function(obj){ // 展开当前点击节点的下面全部节点 + if(!obj) return; + var $ulNode = obj; + // 遍历所有ul子节点 + for (var i = 0; i < $ulNode.length; i++) { + // 获取当前节点的信息 + var $ul = $($ulNode[i]), + $div = $ul.prev("div"), + $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_fnode.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + if (leaf == "leaf") { continue; } // 说明是叶子了,则继续循环下一个 + + if (spread == "open") { + // 说明该节点已经展开了,则进行子节点循环 + } else { + if (_this.type=="load") { //是否全量加载 + if (_this.cache) { //是否开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + } else { //加载节点 + _this.getChild($div); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + } + _this.operateIcon($i_fnode, $i_snode).open(); + + } + var $childUl = $ul.children("li").children("ul"); + _this.toolbarMethod().pulldown($childUl); + } + }, + pullup: function($li){ // 收缩当前点击节点的下面全部节点 + $li.find("."+LI_NAV_CHILD).each(function(){ + // 获取当前节点的信息 + var $ul = $(this), + $div = $ul.prev("div"), + $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_fnode.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + $ul.removeClass(NAV_SHOW); + if(leaf !== "leaf") { + _this.operateIcon($i_fnode, $i_snode).close(); + } + }); + } + } + }; + + /** + * @Desc: toolbar监听方法 + * @Param: tool: 工具栏的具体操作字符串 + * @Param: $div: JQuery对象,表示当前操作节点 + */ + DTree.prototype.toolbarListener = function(tool, $div) { + var _this = this; + var $cite = $div.children("cite[data-leaf]"), + $ul = $div.next("ul"), + $p_li = $div.parent("li[data-index]"), //当前选中节点的顶级li节点 + $p_ul = $p_li.parent("ul"), //当前选中节点的顶级li节点的父级ul + $p_div = $p_ul.prev("div"), //当前选中节点的顶级li节点的父级ul的前一个div + title = (typeof _this.formatter.title === 'function') ? $cite.attr("data-title") : $cite.text(); + + switch (tool) { + case defaultTool.pulldown: + _this.toolbarMethod().pulldown($ul); + break; + case defaultTool.pullup: + _this.toolbarMethod().pullup($p_li); + break; + case defaultTool.addTool: + var content = _this.loadToolBar(title, defaultTool.addTool); + + layer.open({ + title: "新增"+_this.toolbarStyle.title, + type: 1, + area: _this.toolbarStyle.area, + content: content, + success: function(layero, index){ + form.render(); + form.on("submit(dtree_addNode_" + _this.obj[0].id + "_form)",function(data){ + var data = data.field; + var parentId = $div.attr("data-id"), + id = $div.attr("data-id")+"_node_"+$ul[0].childNodes.length, + leaf = true, + checked = "0", + level = parseInt($p_li.attr("data-index"))+1; + + var type = _this.response.type; + var checked = _this.response.checked; + // 创建子节点的DOM,添加子节点 + var checkArr = []; + if (_this.checkArrLen > 0) { + for (var i = 0; i < _this.checkArrLen; i++) { + checkArr.push({type: i, checked: "0"}); + } + } + + $ul.append(_this.getLiItemDom(id, parentId, data.addNodeName, data.addNodeName, true, "", "", checkArr, level, false, false, false, "", "", "item")); + // 先将li节点隐藏 + $ul.find("li[data-id='"+id+"']").hide(); + // 重新赋值 + var $addDiv = $ul.find("div[data-id='"+id+"']"); + node = _this.getNodeParam($addDiv); + + //获取组装后的requestNode,组合参数 + var requestNode = _this.getRequestParam(node); + requestNode = $.extend(requestNode, data); + + _this.temp = [id, $ul, $div, level]; + // 用户自定义想做的事情 + _this.toolbarFun.addTreeNode(requestNode, $div); + + layer.close(index); + return false; + }); + } + }); + break; + case defaultTool.editTool: + var content = _this.loadToolBar(title, defaultTool.editTool); + + layer.open({ + title: "编辑"+_this.toolbarStyle.title, + type: 1, + area: _this.toolbarStyle.area, + content: content, + success: function(layero, index){ + _this.toolbarFun.editTreeLoad(_this.getRequestParam(_this.getNodeParam($div))); + form.render(); + form.on("submit(dtree_editNode_" + _this.obj[0].id + "_form)",function(data){ + var data = data.field; + $cite.html(data.editNodeName); + node = _this.getNodeParam($div); + var requestNode = _this.getRequestParam(node); + requestNode = $.extend(requestNode, data); + _this.temp = [$cite, $div, title, $p_div]; + _this.toolbarFun.editTreeNode(requestNode, $div); + + layer.close(index); + }); + } + }); + break; + case defaultTool.delTool: + layer.confirm('确定要删除该'+_this.toolbarStyle.title+'?', {icon: 3, title:'删除'+_this.toolbarStyle.title}, function(index){ + var node = _this.getNodeParam($div); + _this.temp = [$p_li, $p_div]; + _this.toolbarFun.delTreeNode(_this.getRequestParam(_this.getNodeParam($div)), $div); + + layer.close(index); + }); + break; + default: + if(_this.toolbarExt.length > 0){ + for(var i=0; i<_this.toolbarExt.length; i++){ + var ext = _this.toolbarExt[i]; + if (tool == ext.toolbarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div)), $div); + break; + } + } + } + break; + } + } + + + /** + * @Desc: 加载toolbar中的内容 + * @Param: title: 默认操作中的input输入框的值 + * @Param: name: 工具栏的具体操作字符串 + */ + DTree.prototype.loadToolBar = function(title, name){ + var _this = this; + var toolbarShow = _this.toolbarShow; + var nodeBarContents = _this.toolbarBtn; + + var html = ""; + switch (name) { + case defaultTool.addTool: + var addNodeBarDef = [{"label": "当前选中", "name": "nodeTitle", "type": "text", "value": title, "defElem": "nowChoose", "readonly": true}, + {"label": "新增"+_this.toolbarStyle.title, "name": "addNodeName", "type": "text", "value": "", "defElem": "nowChange", "verify": "required"}, + {"type": "submit", "value": "确认添加", "defElem": "btn", "filter": "dtree_addNode_" + _this.obj[0].id + "_form"}]; + + //2. 用户自定义的节点内容 + var addNodeBar = ['
                                                                                          ']; + + if(nodeBarContents != null && nodeBarContents.length > 0){ + if(nodeBarContents[0] != null && nodeBarContents[0] != undefined && nodeBarContents[0].length > 0){ + var addNodeBarContents = nodeBarContents[0]; + // 1. 检查是否包含了now、newly、btn这三个默认项,将其他元素依次排列,将特殊元素至于栈顶 + for(var i=0; i', '
                                                                                          ']; + // 3.遍历生成按钮 + for(var j=0; j
                                                                                          '); + addNodeBar.push(addBtn.join('')); + addNodeBar.push('
                                                                                          '); + html = addNodeBar.join(''); + break; + + case defaultTool.editTool: + var editNodeBarDef = [{"label": "当前选中", "name": "nodeTitle", "type": "text", "value": title, "defElem": "nowChoose", "readonly": true}, + {"label": "编辑"+_this.toolbarStyle.title, "name": "editNodeName", "type": "text", "value": "", "defElem": "nowChange", "verify": "required"}, + {"type": "submit", "value": "确认编辑", "defElem": "btn", "filter": "dtree_editNode_" + _this.obj[0].id + "_form"}]; + + var editNodeBar = ['
                                                                                          ']; + //2. 用户自定义的节点内容 + if(nodeBarContents != null && nodeBarContents.length > 0){ + + if(nodeBarContents[1] != null && nodeBarContents[1] != undefined && nodeBarContents[1].length > 0){ + var editNodeBarContents = nodeBarContents[1]; + // 1. 检查是否包含了now、newly、btn这三个默认项,将其他元素依次排列,将特殊元素至于栈顶 + for(var i=0; i', '
                                                                                          ']; + // 3.遍历生成按钮 + for(var j=0; j
                                                                                          '); + editNodeBar.push(editBtn.join('')); + editNodeBar.push('
                                                                                          '); + html = editNodeBar.join(''); + break; + } + return html; + }; + + /** + * @Desc: 获取toolbar详细的标签信息 + * @Param: nodeBarContents: 工具栏中的数据渲染内容JSON对象 + */ + DTree.prototype.loadToolBarDetail = function(nodeBarContents){ + var _this = this; + var readonly = (typeof (nodeBarContents.readonly) === "boolean") ? nodeBarContents.readonly : false; + var disabled = (typeof (nodeBarContents.disabled) === "boolean") ? nodeBarContents.disabled : false; + var id = nodeBarContents.id ? nodeBarContents.id : ""; + var name = nodeBarContents.name ? nodeBarContents.name : ""; + var val = nodeBarContents.value ? nodeBarContents.value : ""; + var verify = nodeBarContents.verify ? nodeBarContents.verify : ""; + var placeholder = nodeBarContents.placeholder ? nodeBarContents.placeholder : val; + return{ + text: function(){ + return ['
                                                                                          ', + '', + '
                                                                                          ', + '', + '
                                                                                          ', + '
                                                                                          '].join(''); + }, + textarea: function(){ + return ['
                                                                                          ', + '', + '
                                                                                          ', + '', + '
                                                                                          ', + '
                                                                                          '].join(''); + }, + hidden: function(){ + return [''].join(''); + }, + select: function(){ + var optionsData = (typeof nodeBarContents.optionsData === 'object') ? nodeBarContents.optionsData : nodeBarContents.optionsData(); + var options = ""; + for(var key in optionsData){ + if(val == optionsData[key]){ + options += ""; + } else { + options += ""; + } + } + return ['
                                                                                          ', + '', + '
                                                                                          ', + '', '
                                                                                          ', '
                                                                                          '].join(''); + }, + submit: function(){ + var filter = nodeBarContents.filter; + return [''].join(''); + }, + button: function(){ + return [''].join(''); + }, + reset: function(){ + return [''].join(''); + } + } + }; + + /** + * @Desc: 新增节点后改变节点内容 + * @Param: returnID: 当前需要加载的内容,JSON对象、字符串、指定字符串("refresh")、true + */ + DTree.prototype.changeTreeNodeAdd = function(returnID){ + var _this = this; + var temp = _this.temp; + var id = temp[0], $ul = temp[1], $div = temp[2], level = temp[3]; + var flag = false; + if(returnID){ + var $thisDiv = _this.obj.find("[data-id='"+id+"']"); + if(typeof returnID === "object"){ + // 如果是JSON格式数据,则将当前DIV删除,重新建造DIV + $thisDiv.remove(); + var parseData = _this.parseData(returnID); + + if(parseData.treeId()){ + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(0), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), "item")); + + // 建造完毕后,选中该DIV + $thisDiv = $ul.find("div[data-id='"+parseData.treeId()+"']"); + _this.setNodeParam($thisDiv) + } else { + layer.msg("添加失败,节点ID为undefined!",{icon:5}); + // 将li节点删除 + $ul.find("li[data-id='"+id+"']").remove(); + // 重新赋值 + _this.setNodeParam($div); + // 临时变量制空 + _this.temp = []; + return ; + } + }else if(returnID == 'refresh' || returnID == true){ + // 如果是设置为refresh参数,则向后台发送请求,获取新增节点下的真实参数,局部刷新树。 + flag = true; + } else if(typeof returnID === "string" || typeof returnID === 'number'){ + $thisDiv.attr("data-id", returnID); + // 将li节点展示 + $ul.find("li[data-id='"+returnID+"']").show(); + _this.setNodeParam($thisDiv) + } + + // 判断当前点击的节点是否是最后一级节点,如果是,则需要修改节点的样式 + var $icon_i = $div.find("i[data-spread]"); + if ($icon_i.eq(0).attr("data-spread") == "last") { + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).openWithLeaf(); + } else { //如果不是,也要修改节点样式 + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).open(); + } + $ul.addClass(NAV_SHOW); //展开UL + _this.accordionUL($ul); + if(flag) { + _this.getChild($div); + } else { + // _this.showLine(); + _this.showLine($ul.find("li")); + // 这种情况下需要在新增节点后对节点新增工具栏 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.dynamicToolbarDom($thisDiv.find("cite[data-leaf]")); + } + } + + } else { + // 将li节点删除 + $ul.find("li[data-id='"+id+"']").remove(); + // 重新赋值 + _this.setNodeParam($div); + } + + _this.temp = []; // 临时变量制空 + + }; + + /** + * @Desc: 编辑页打开后显示编辑页内容 + * @Param: param: 编辑页打开之后回显的数据集 + */ + DTree.prototype.changeTreeNodeDone = function(param){ + var _this = this; + form.val('dtree_editNode_' + _this.obj[0].id + '_form', param); + form.render(); + }; + + /** + * @Desc: 修改节点后改变节点内容 + * @Param: returnID: 当前需要变更的内容,JSON对象 + */ + DTree.prototype.changeTreeNodeEdit = function(returnID){ + var _this = this; + var temp = _this.temp; + var $cite = temp[0], $div = temp[1], title = temp[2], $p_div = temp[3]; + var flag = false; + if(returnID){ + if(typeof returnID === "object"){ + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var replaceDom = _this.replaceDom($div, parseData.treeId(), parseData.last(0), parseData.spread(), parseData.disabled(), parseData.hide()); + replaceDom.node(parseData.iconClass()); + replaceDom.checkbox(parseData.checkArr()); + replaceDom.text(parseData.title()); + replaceDom.ul(); + replaceDom.basicData(parseData.basicData()); + replaceDom.recordData(parseData.recordData()); + _this.setNodeParam($div); + } else { + layer.msg("编辑失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } + } else { + $cite.html(title); + _this.getNodeParam($div); + } + + _this.temp = []; // 临时变量制空 + }; + + /** + * @Desc: 删除节点后改变节点内容 + * @Param: flag: 是否要删除节点 + */ + DTree.prototype.changeTreeNodeDel = function(flag){ + var _this = this; + var temp = _this.temp; + var $p_li = temp[0], + $p_ul = $p_li.parent("ul"), + $p_div = temp[1]; + + if(flag){ + $p_li.remove(); + _this.showLine($p_ul.find("li")); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($p_ul.children("li").length == 0){ + var $icon_i = $p_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).closeWithLeaf(); + } + _this.initNodeParam(); + } + + _this.temp = []; // 临时变量制空 + }; + + /******************** iframe区域 ********************/ + /** + * @Desc: 加载iframe + * @Param: $div: JQuery对象,表示当前节点 + * @Param: iframeParam: iframe加载的参数 + */ + DTree.prototype.loadIframe = function($div, iframeParam) { + var _this = this; + var $cite = _this.getNodeDom($div).cite(); + if (!_this.useIframe) { // 启用iframe + return false; + } + var iframeElem = _this.iframeElem, + iframeUrl = _this.iframeUrl, + iframeLoad = _this.iframeLoad; + + var flag = iframeLoad == "leaf" ? (($cite.attr("data-leaf") == "leaf") ? true : false) : true; + + if (flag) { + if ($(iframeElem).length > 0) { //iframe存在 + if (!iframeUrl) { + layer.msg("数据请求异常,iframeUrl参数未指定", {icon:5}); + return false; + } + var param = AjaxHelper.serialize("?", iframeParam); + if(iframeUrl.indexOf("?")> -1){ + param = "&"+param.substring(1, param.length); + } + var url = iframeUrl + param; + $(iframeElem).attr("src", url); + } else { + layer.msg("iframe绑定异常,请确认页面中是否有iframe页对应的容器", {icon:5}); + return false; + } + } + return flag; + }; + + /** + * @Desc: 获取传递出去的参数,根据iframe.iframeDefaultRequest、iframe.iframeRequest和node拼出发出请求的参数 + * @Param: nodes: 需要传递出去的参数 + */ + DTree.prototype.getIframeRequestParam = function(nodes){ + var _this = this; + var request = _this.iframeRequest, + defaultRequestNames = _this.iframeDefaultRequest, + node = nodes || _this.node, + requestParam = {}; + + // 先拼用户自定义的,在拼树生成的,这样的话用户可以自定义当树未生成时的节点的初始值 + for ( var key in request) { + requestParam[key] = request[key]; + } + for ( var key in defaultRequestNames) { + var paramName = defaultRequestNames[key]; + var paramValue = node[key]; + if(typeof paramValue === "boolean"){ + requestParam[paramName] = paramValue; + }else { + if(paramValue){ + requestParam[paramName] = paramValue; + } + } + } + + // 解决传递中文的乱码问题 + var reg = /[\u4E00-\u9FA5\uF900-\uFA2D]/; //正则匹配中文 + for(var key in requestParam){ + if(reg.test(requestParam[key])) { + var str = requestParam[key]; + requestParam[key] = encodeURI(encodeURI(str)); + } + } + + return requestParam; + }; + + /******************** 数据回调区域 ********************/ + /** + * @Desc: 根据具体的id获取基于当前id的div以及对应的其他dom元素 + * @Param: id: 节点的ID值 + */ + DTree.prototype.getNodeDom = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + return { + div: function(){ // 获取当前div + return $div; + }, + fnode: function(){ // 获取一级图标元素 + return ($div == null) ? null : $div.find("i[data-spread]").eq(0); + }, + snode: function(){ // 获取二级图标元素 + return ($div == null) ? null : $div.find("i[data-spread]").eq(1); + }, + checkbox: function(){ // 获取复选框元素 + return ($div == null) ? null : $div.find("i[data-par]"); + }, + cite: function(){ // 获取cite元素 + return ($div == null) ? null : $div.find("cite[data-leaf]"); + }, + nextUl: function(){ // 获取相邻的ul元素 + return ($div == null) ? null : $div.next("ul"); + }, + parentLi: function(){ // 获取父级li元素 + return ($div == null) ? null : $div.parent("li"); + }, + parentUl: function(){ // 获取基于当前$div的上级$ul + return ($div == null) ? null : $div.parent("li").parent("ul"); + }, + parentDiv: function(){ // 获取基于当前$div的上级$div + return ($div == null) ? null : $div.parent("li").parent("ul").prev("div"); + }, + nowDiv: function(){ // 获取当前选中节点,没有则返回null + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS); + }, + nowOrRootDiv: function(){ // 获取当前选中节点,没有则返回根节点下的第一个div + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? _this.obj.children("li").eq(0).children("div").eq(0) : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS); + }, + nowOrRootUl: function(){ // 获取当前选中节点下一个UL 或根节点。为了将新节点放入ul下 + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? _this.obj : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).next("ul"); + } + } + }; + + /** + * @Desc: 获取当前选中节点下一个ul节点 或根节点。为了将新节点放入ul下 + */ + DTree.prototype.getNowNodeUl = function() { + var _this = this; + return _this.getNodeDom().nowOrRootUl(); + }; + + /** + * @Desc: 获取当前选中div节点 或第一个根div节点。 + */ + DTree.prototype.getNowNode = function() { + var _this = this; + return _this.getNodeDom().nowOrRootDiv(); + }; + + /** + * @Desc: 获取当前选中div节点 无则返回null。 + */ + DTree.prototype.getNowNodeOrNull = function() { + var _this = this; + return _this.getNodeDom().nowDiv(); + }; + + /** + * @Desc: 根据获取指定div节点。 + * @Param: id: 指定节点的ID + */ + DTree.prototype.getNode = function(id) { + var _this = this; + return _this.getNodeDom(id).div(); + }; + + /** + * @Desc: 设置当前选中节点的全部参数 + * @Param: $div: 当前选中的节点 + */ + DTree.prototype.setNodeParam = function($div) { + var _this = this; + _this.node.nodeId = $div.attr("data-id"); + _this.node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + _this.node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + _this.node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + _this.node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + _this.node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + _this.node.basicData = basicData; + + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + _this.node.recordData = recordData; + + if (_this.getNodeDom($div).checkbox()) { + var dataTypes = "", checkeds = "", initcheckeds = ""; + _this.getNodeDom($div).checkbox().each(function(){ + dataTypes += $(this).attr("data-type") + ","; + checkeds += $(this).attr("data-checked") + ","; + initcheckeds += $(this).attr("data-initchecked") + ","; + }); + dataTypes = dataTypes.substring(0, dataTypes.length-1); + checkeds = checkeds.substring(0, checkeds.length-1); + initcheckeds = initcheckeds.substring(0, initcheckeds.length-1); + + _this.node.dataType = dataTypes; + _this.node.checked = checkeds; + _this.node.initchecked = initcheckeds; + } + }; + + /** + * @Desc: 获取当前选中节点的全部参数 + * @Param: $div: 当前选中的节点 + */ + DTree.prototype.getNodeParam = function($div) { + var _this = this; + if ($div) { + _this.setNodeParam($div); + } else { + if(_this.obj.find("div[data-id]").parent().find("."+NAV_THIS).length == 0){ + _this.initNodeParam(); + } + } + return this.node; + }; + + /** + * @Desc: 获取一个临时的node参数 + * @Param: $div: 当前选中的节点 + */ + DTree.prototype.getTempNodeParam = function($div) { + var _this = this; + var temp_node = {}; + temp_node.nodeId = $div.attr("data-id"); + temp_node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + temp_node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + temp_node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + temp_node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + temp_node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + temp_node.basicData = basicData; + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + temp_node.recordData = recordData; + + if (_this.getNodeDom($div).checkbox()) { + var dataTypes = "", checkeds = "", initcheckeds = ""; + _this.getNodeDom($div).checkbox().each(function(){ + dataTypes += $(this).attr("data-type") + ","; + checkeds += $(this).attr("data-checked") + ","; + initcheckeds += $(this).attr("data-initchecked") + ","; + }); + dataTypes = dataTypes.substring(0, dataTypes.length-1); + checkeds = checkeds.substring(0, checkeds.length-1); + initcheckeds = initcheckeds.substring(0, initcheckeds.length-1); + + temp_node.dataType = dataTypes; + temp_node.checked = checkeds; + temp_node.initchecked = initcheckeds; + } + return temp_node; + }; + + /** + * @Desc: 重置内置参数 + */ + DTree.prototype.initNodeParam = function(){ + var _this = this; + _this.node.nodeId = ""; + _this.node.parentId = ""; + _this.node.context = ""; + _this.node.leaf = ""; + _this.node.level = ""; + _this.node.spread = ""; + _this.node.dataType = ""; + _this.node.checked = ""; + _this.node.initchecked = ""; + _this.node.basicData = ""; + _this.node.recordData = ""; + + if(_this.select) { + _this.selectResetVal(); + } + }; + + /** + * @Desc: 获取传递出去的参数,根据defaultRequest、request和node拼出发出请求的参数 + * @Param: nodes:需要传递出去的参数 + */ + DTree.prototype.getRequestParam = function(nodes){ + var _this = this; + var request = _this.request, + defaultRequestNames = _this.defaultRequest, + node = nodes || _this.node, + requestParam = {}; + + // 先拼用户自定义的,在拼树生成的,这样的话用户可以自定义当树未生成时的节点的初始值 + for ( var key in request) { + requestParam[key] = request[key]; + } + for ( var key in defaultRequestNames) { + var paramName = defaultRequestNames[key]; + var paramValue = node[key]; + if(typeof paramValue === "boolean"){ + requestParam[paramName] = paramValue; + }else { + if(paramValue){ + requestParam[paramName] = paramValue; + } + } + + } + return requestParam; + }; + + /** + * @Desc: 获取filterParam过滤后的requestParam + * @Param: requestParam:请求参数 + */ + DTree.prototype.getFilterRequestParam = function(requestParam){ + var _this = this; + var filterRequest = _this.filterRequest; + return event.cloneObj(requestParam, filterRequest); + }; + + /** + * @Desc: 获取当前选中的请求参数 + */ + DTree.prototype.getNowParam = function(){ + var _this = this; + + return _this.getRequestParam(_this.getNodeParam()); + }; + + /** + * @Desc: 根据id获取指定div节点选中参数 + * @Param: id:节点的ID值 + */ + DTree.prototype.getParam = function(id){ + var _this = this; + + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null){ return _this.callbackData().node(_this.getTempNodeParam($div)); } else { return {}; } + }; + + /** + * @Desc: 根据id获取节点上级节点参数 + * @Param: id:节点的ID值 + */ + DTree.prototype.getParentParam = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null){ return _this.callbackData().parentNode($div); } else { return {}; } + }; + + /** + * @Desc: 根据id获取节点的全部上级节点参数值 + * @Param: id:节点的ID值 + */ + DTree.prototype.getAllParentParam = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + var arr = []; + if($div != null){ + var level = _this.getTempNodeParam($div).level; + for(var i=1; i 0){ + $childDivs.each(function(){ + var $cDiv = $(this); + childNode.push(_this.getRequestParam(_this.getTempNodeParam($cDiv))); + }); + } + return childNode; + }, + parentNode: function($div){ // 获取上级节点值 + var pId = _this.getNodeDom($div).parentLi().attr("data-pid"); + var $pdiv = _this.obj.find("div[data-id='"+pId+"']"); + if($pdiv.length > 0) {return _this.getRequestParam(_this.getTempNodeParam($pdiv));} else {return {};} + + } + } + }; + + /******************** 事件回调区域 ********************/ + /** + * @Desc: 绑定浏览器事件 + */ + DTree.prototype.bindBrowserEvent = function(){ + var _this = this; + var rootId = _this.obj[0].id; + + // 绑定文件夹展开/收缩的图标的点击事件,点击时给当前节点的div添加选中class + _this.obj.on("click", "i[data-spread]", function(event) { + event.stopPropagation(); + var $i = $(this), + $div = $i.parent("div"), + node = _this.getNodeParam($div); + + _this.toolbarHide(); + _this.navThis($div); + _this.clickSpread($div); // 展开或隐藏节点 + + // 树状态改变后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "changeTree("+$(_this.obj)[0].id+")", { + dom: _this.callbackData().dom($i), + param: _this.callbackData().node(node), + show: _this.callbackData().dom($i).attr("data-spread") == "open" ? true : false + }); + }); + + // 绑定所有子节点div的单击事件,点击时触发加载iframe或用户自定义想做的事情 + _this.obj.on("click", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event) { + event.stopPropagation(); + var $div = $(this), + $cite = $div.find("cite"), + node = _this.getNodeParam($div); + _this.toolbarHide(); + _this.navThis($div); + + if(_this.select) { + _this.selectVal(node.nodeId); + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").click(); + } + + if (_this.useIframe) { + var iframeParam = _this.getFilterRequestParam(_this.getIframeRequestParam(node)); + var flag = _this.loadIframe($div, iframeParam); // 加载iframe + if (flag) { + // iframe加载完毕后,用户自定义想做的事情 + _this.iframeFun.iframeDone(iframeParam); + + layui.event.call(this, MOD_NAME, "iframeDone("+$(_this.obj)[0].id+")", { + "iframeParam": iframeParam, + dom: _this.callbackData().dom($div) + }); + } + } else { + // 单击事件执行完毕后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "node("+$(_this.obj)[0].id+")", { + param: _this.callbackData().node(node), + childParams: _this.callbackData().childNode($div), + parentParam: _this.callbackData().parentNode($div), + dom: _this.callbackData().dom($div) + }); + } + }); + + // 绑定所有子节点div的双击事件,暴露on给用户自定义 + _this.obj.on("dblclick", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event) { + event.stopPropagation(); + var $div = $(this), + $cite = $div.find("cite"), + node = _this.getNodeParam($div); + _this.toolbarHide(); + _this.navThis($div); + + if(_this.select) { + _this.selectVal(node.nodeId); + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").click(); + } + + // 双击事件执行完毕后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "nodedblclick("+$(_this.obj)[0].id+")", { + param: _this.callbackData().node(node), + childParams: _this.callbackData().childNode($div), + parentParam: _this.callbackData().parentNode($div), + dom: _this.callbackData().dom($div) + }); + }); + + if(_this.checkbar) { + // 绑定cheboxbar的节点复选框 + _this.obj.on("click", "i[dtree-click='"+eventName.checkNodeClick+"'][dtree-disabled='false']", function(event) { + _this.toolbarHide(); + var $i = $(this), + $div = $i.closest("div[dtree-click='"+eventName.itemNodeClick+"']"), + node = _this.getNodeParam($div); + // 复选框选中前的回调 + var flag = _this.checkbarFun.chooseBefore($i, _this.getRequestParam(node)); + _this.temp = [$i]; + if(flag){_this.changeCheck();} + + event.stopPropagation(); + }); + } + + if(_this.menubar) { + // 绑定menubar的点击事件 + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).on("click", "button[d-menu]", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("d-menu"), "group"); + }); + + // 绑定menubar的点击事件 + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).on("click", "a[d-menu]", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("d-menu"), "toolbar"); + }); + + // 绑定menubar的点击按钮事件 + _this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").on("click", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("dtree-menu"), "freedom"); + }); + } + + if(_this.toolbar) { + if(_this.toolbarWay == "contextmenu") { + //绑定所有子节点div的右键点击事件,用于显示toolbar + _this.obj.on("contextmenu", "div[dtree-click='"+eventName.itemNodeClick+"'][d-contextmenu='true'][dtree-disabled='false']", function(e){ + var $div = $(this), + node = _this.getNodeParam($div); + + _this.toolbarHide(); + // toolbar加载前执行的方法,执行完毕之后创建按钮 + _this.setToolbarDom().setToolbarPlace(_this.toolbarFun.loadToolbarBefore(event.cloneObj(_this.toolbarMenu), _this.getRequestParam(node), $div)); + + var e = e || window.event, + mx = e.pageX - $div.offset().left +45 , + my = $div.offset().top - _this.obj.closest(_this.scroll).offset().top +15; + + _this.navThis($div); + var $toolBarDiv = _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id); + $toolBarDiv.find(".layui-nav-child").addClass('layui-anim-fadein layui-show'); + $toolBarDiv.css({'left':mx+'px','top':my+'px'}); + + e.stopPropagation(); + return false; + }); + + // 绑定装载树的上层出现滚动条的容器,让toolbar隐藏 + _this.obj.closest(_this.scroll).scroll(function() { + _this.toolbarHide(); + }); + + // 绑定toolbar的点击事件 + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $div = _this.getNodeDom().nowOrRootDiv(), + node = _this.getNodeParam($div); + _this.toolbarHide(); + var tool = $(this).attr("dtree-tool"); + _this.toolbarListener(tool, $div); + }); + } else if(_this.toolbarWay == "fixed") { + // 绑定toolbar的点击事件 + _this.obj.on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $a = $(this), + $cite = $a.parent("em."+TOOLBAR_TOOL_EM).prev("cite"), //当前选中节点的text + $div = $cite.parent("div"), + node = _this.getNodeParam($div); + var tool = $a.attr("dtree-tool"); + + _this.toolbarHide(); + _this.navThis($div); + _this.toolbarListener(tool, $div); + }); + } else if(_this.toolbarWay == "follow") { + //绑定所有子节点div的mouseover mouseout事件,用于显示或隐藏toolbar + _this.obj.on("mouseover mouseout", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event){ + var $div = $(this), + $toolBarEm = $div.children("em."+TOOLBAR_TOOL_EM); + if(event.type == "mouseover"){ + $toolBarEm.removeClass(NAV_HIDE); + event.stopPropagation(); + } else if(event.type == "mouseout"){ + $toolBarEm.addClass(NAV_HIDE); + event.stopPropagation(); + } + }); + + // 绑定toolbar的点击事件 + _this.obj.on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $a = $(this), + $cite = $a.parent("em."+TOOLBAR_TOOL_EM).prev("cite"), //当前选中节点的text + $div = $cite.parent("div"), + node = _this.getNodeParam($div); + var tool = $a.attr("dtree-tool"); + + _this.toolbarHide(); + _this.navThis($div); + _this.toolbarListener(tool, $div); + }); + } + } + + if(_this.select) { + // 绑定select的点击事件 + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").on("click", function(event){ + event.stopPropagation(); + var dl = $(this).find('dl'); + //debugger; + $(this).toggleClass("layui-form-selected"); + + var $card = $("div[dtree-id='" + rootId + "'][dtree-card='"+_this.selectCardDiv+"']"); + + $card.toggleClass("dtree-select-show layui-anim layui-anim-upbit"); + var top = $(this).offset().top + $(this).outerHeight() - $WIN.scrollTop() - 5, + cardHeight = $card.height(), + winHeight = $WIN.height(); +// console.log("top = $(this).offset().top: " + $(this).offset().top + " + $(this).outerHeight(): " + $(this).outerHeight() + " - $WIN.scrollTop(): " + $WIN.scrollTop() + " - 5 =" + top); +// console.log("winHeight = " + winHeight); + if($card.hasClass('dtree-select-up')) { + $card.removeClass('dtree-select-up'); + } + + //上下定位识别 + if(top + cardHeight > $WIN.height() && top >= cardHeight){ + console.log(" top + cardHeight : "+ top + " + " + cardHeight + " > $WIN.height() :" + $WIN.height() + " && top >= cardHeight :" + top + " > " + cardHeight); + if($card.hasClass('dtree-select-up')) { + $card.removeClass('dtree-select-up'); + } else { + $card.addClass('dtree-select-up'); + } + } else { + $card.removeClass('dtree-select-up'); + } + + // 下拉树面板开闭状态改变后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "changeSelect("+$(_this.obj)[0].id+")", { + show: $(this).hasClass("layui-form-selected"), + param: _this.selectVal() + }); + }); + + } + }; + + // 绑定body的单击,让本页面所有的toolbar隐藏 + $BODY.on("click", function(event){ + $("div."+LI_DIV_TOOLBAR).find(".layui-show").removeClass('layui-anim-fadein layui-show'); + // $("div[dtree-id][dtree-select]").removeClass("layui-form-selected"); + // $("div[dtree-id][dtree-card]").removeClass("dtree-select-show layui-anim layui-anim-upbit"); + + }); + + // 解绑浏览器事件 + DTree.prototype.unbindBrowserEvent = function(){ + var _this = this; + + // 本身事件解绑 + _this.obj.unbind(); + // 菜单栏解绑 + if(_this.menubar){ + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).unbind(); + if(_this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").length > 0){ + _this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").unbind(); + } + } + + // 工具栏解绑 + if(_this.toolbar){ + if(_this.toolbarWay == "contextmenu") { + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).unbind(); + if(_this.obj.closest(_this.scroll).length > 0){ + _this.obj.closest(_this.scroll).unbind(); + } + } + } + + // 下拉树解绑 + if(_this.select) { + // 解绑select的点击事件 + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-select='"+_this.selectDiv+"']").removeClass("layui-form-selected"); + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-card='"+_this.selectCardDiv+"']").removeClass("dtree-select-show layui-anim layui-anim-upbit"); + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-select='"+_this.selectDiv+"']").unbind(); + } + }; + + + /** 外部访问 **/ + var dtree = { + set: function(options){ //设置全局属性 + if(typeof options !== 'undefined') { + $.extend(OPTIONS, options); + } + }, + render: function(options){ // 初始化树 + var dTree = null; + var id = event.getElemId(options); + if(id == "") { + layer.msg("页面中未找到绑定id", {icon:5}); + } else { + dTree = DTrees[id]; + if(typeof dTree === 'object'){ + dTree.unbindBrowserEvent(); + } + // 创建树 + dTree = new DTree(options); + // 添加到树数组中去 + DTrees[id] = dTree; + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.loadTreeInit(); + dTree.bindBrowserEvent(); + } + + return dTree; + }, + renderSelect: function(options){ // 初始化下拉树 + var dTree = null; + var id = event.getElemId(options); + if(id == "") { + layer.msg("页面中未找到绑定id", {icon:5}); + } else { + dTree = DTrees[id]; + if(typeof dTree === 'object'){ + dTree.unbindBrowserEvent(); + } + // 创建下拉树 + dTree = new DTree(options); + dTree.selectSetting(); + // 添加到树数组中去 + DTrees[id] = dTree; + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.loadTreeInit(); + dTree.bindBrowserEvent(); + } + + return dTree; + }, + reload: function(dTree, options){ // 重新加载树 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + dTree.reloadSetting(options); + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.initNodeParam(); + dTree.loadTreeInit(); + dTree.unbindBrowserEvent(); + dTree.bindBrowserEvent(); + }, + on: function(events, callback) { // 绑定事件 + if(events.indexOf("'") > 0){ + events = events.replace(/'/g,""); + } + if(events.indexOf('"') > 0) { + events = events.replace(/"/g,""); + } + return layui.onevent.call(this, MOD_NAME, events, callback); + }, + click: function(dTree, id) { // 模拟单击事件 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + $("div[dtree-click='"+eventName.itemNodeClick+"'][dtree-id='"+dTree.obj[0].id+"'][data-id='"+id+"']").click(); + }, + getNowParam: function(dTree){ // 获取当前选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getNowParam(); // 获取当前选中值 + }, + getParam: function(dTree, id){ // 获取指定节点值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getParam(id); // 获取指定节点值 + }, + getParentParam: function(dTree, id){ // 获取参数的上级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getParentParam(id); + }, + getAllParentParam: function(dTree, id){ // 获取参数的全部上级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getAllParentParam(id); + }, + getChildParam: function(dTree, id){ // 获取参数的全部下级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getChildParam(id); + }, + getCheckbarNodesParam: function(dTree){ // 获取复选框选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return {}; + } + return dTree.getCheckbarNodesParam(); // 获取复选框选中值 + }, + getCheckbarJsonArrParam: function(dTree){ // 获取复选框选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return {}; + } + return dTree.getCheckbarJsonArrParam(); // 获取复选框选中值 + }, + dataInit: function(dTree, chooseId){ // 初始化选中树,针对数据反选 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + if(chooseId){ + return dTree.dataInit(chooseId); + } + }, + chooseDataInit: function(dTree, chooseIds){ // 初始化复选框选中,针对数据反选 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + if(chooseIds){ + return dTree.chooseDataInit(chooseIds); + } + }, + changeCheckbarNodes: function(dTree){ //判断复选框是否发生变更 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.changeCheckbarNodes(); + }, + initNoAllCheck: function(dTree) { //复选框半选状态初始化设置 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.initNoAllCheck(); + }, + initAllCheck: function(dTree){ // 复选框选中状态初始化设置 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.initAllCheck(); + }, + selectVal: function(dTree, param){ // select模式设置输入框选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.selectVal(param); // select模式设置输入框选中值 + }, + escape: function(html){ // 字符串格式化 + return event.escape(html); + }, + unescape: function(str){ // 字符串反格式化 + return event.unescape(str); + }, + serialize: function(first, param) { // 序列化JSON对象 + return AjaxHelper.serialize(first, param); + }, + version: function(){ //获取版本号 + return VERSION; + } + }; + + exports('dtree', dtree); +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/echarts.js b/demo/webman/backend/plugin/admin/public/component/pear/module/echarts.js new file mode 100644 index 0000000000000000000000000000000000000000..e97eb7b79c79d006f108eff017ae7553a19c9ff5 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/echarts.js @@ -0,0 +1,95172 @@ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.echarts = {})); +}(this, (function (exports) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var Browser = (function () { + function Browser() { + this.firefox = false; + this.ie = false; + this.edge = false; + this.newEdge = false; + this.weChat = false; + } + return Browser; + }()); + var Env = (function () { + function Env() { + this.browser = new Browser(); + this.node = false; + this.wxa = false; + this.worker = false; + this.svgSupported = false; + this.touchEventsSupported = false; + this.pointerEventsSupported = false; + this.domSupported = false; + this.transformSupported = false; + this.transform3dSupported = false; + this.hasGlobalWindow = typeof window !== 'undefined'; + } + return Env; + }()); + var env = new Env(); + if (typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function') { + env.wxa = true; + env.touchEventsSupported = true; + } + else if (typeof document === 'undefined' && typeof self !== 'undefined') { + env.worker = true; + } + else if (typeof navigator === 'undefined') { + env.node = true; + env.svgSupported = true; + } + else { + detect(navigator.userAgent, env); + } + function detect(ua, env) { + var browser = env.browser; + var firefox = ua.match(/Firefox\/([\d.]+)/); + var ie = ua.match(/MSIE\s([\d.]+)/) + || ua.match(/Trident\/.+?rv:(([\d.]+))/); + var edge = ua.match(/Edge?\/([\d.]+)/); + var weChat = (/micromessenger/i).test(ua); + if (firefox) { + browser.firefox = true; + browser.version = firefox[1]; + } + if (ie) { + browser.ie = true; + browser.version = ie[1]; + } + if (edge) { + browser.edge = true; + browser.version = edge[1]; + browser.newEdge = +edge[1].split('.')[0] > 18; + } + if (weChat) { + browser.weChat = true; + } + env.svgSupported = typeof SVGRect !== 'undefined'; + env.touchEventsSupported = 'ontouchstart' in window && !browser.ie && !browser.edge; + env.pointerEventsSupported = 'onpointerdown' in window + && (browser.edge || (browser.ie && +browser.version >= 11)); + env.domSupported = typeof document !== 'undefined'; + var style = document.documentElement.style; + env.transform3dSupported = ((browser.ie && 'transition' in style) + || browser.edge + || (('WebKitCSSMatrix' in window) && ('m11' in new WebKitCSSMatrix())) + || 'MozPerspective' in style) + && !('OTransition' in style); + env.transformSupported = env.transform3dSupported + || (browser.ie && +browser.version >= 9); + } + + var DEFAULT_FONT_SIZE = 12; + var DEFAULT_FONT_FAMILY = 'sans-serif'; + var DEFAULT_FONT = DEFAULT_FONT_SIZE + "px " + DEFAULT_FONT_FAMILY; + var OFFSET = 20; + var SCALE = 100; + var defaultWidthMapStr = "007LLmW'55;N0500LLLLLLLLLL00NNNLzWW\\\\WQb\\0FWLg\\bWb\\WQ\\WrWWQ000CL5LLFLL0LL**F*gLLLL5F0LF\\FFF5.5N"; + function getTextWidthMap(mapStr) { + var map = {}; + if (typeof JSON === 'undefined') { + return map; + } + for (var i = 0; i < mapStr.length; i++) { + var char = String.fromCharCode(i + 32); + var size = (mapStr.charCodeAt(i) - OFFSET) / SCALE; + map[char] = size; + } + return map; + } + var DEFAULT_TEXT_WIDTH_MAP = getTextWidthMap(defaultWidthMapStr); + var platformApi = { + createCanvas: function () { + return typeof document !== 'undefined' + && document.createElement('canvas'); + }, + measureText: (function () { + var _ctx; + var _cachedFont; + return function (text, font) { + if (!_ctx) { + var canvas = platformApi.createCanvas(); + _ctx = canvas && canvas.getContext('2d'); + } + if (_ctx) { + if (_cachedFont !== font) { + _cachedFont = _ctx.font = font || DEFAULT_FONT; + } + return _ctx.measureText(text); + } + else { + text = text || ''; + font = font || DEFAULT_FONT; + var res = /^([0-9]*?)px$/.exec(font); + var fontSize = +(res && res[1]) || DEFAULT_FONT_SIZE; + var width = 0; + if (font.indexOf('mono') >= 0) { + width = fontSize * text.length; + } + else { + for (var i = 0; i < text.length; i++) { + var preCalcWidth = DEFAULT_TEXT_WIDTH_MAP[text[i]]; + width += preCalcWidth == null ? fontSize : (preCalcWidth * fontSize); + } + } + return { width: width }; + } + }; + })(), + loadImage: function (src, onload, onerror) { + var image = new Image(); + image.onload = onload; + image.onerror = onerror; + image.src = src; + return image; + } + }; + function setPlatformAPI(newPlatformApis) { + for (var key in platformApi) { + if (newPlatformApis[key]) { + platformApi[key] = newPlatformApis[key]; + } + } + } + + var BUILTIN_OBJECT = reduce([ + 'Function', + 'RegExp', + 'Date', + 'Error', + 'CanvasGradient', + 'CanvasPattern', + 'Image', + 'Canvas' + ], function (obj, val) { + obj['[object ' + val + ']'] = true; + return obj; + }, {}); + var TYPED_ARRAY = reduce([ + 'Int8', + 'Uint8', + 'Uint8Clamped', + 'Int16', + 'Uint16', + 'Int32', + 'Uint32', + 'Float32', + 'Float64' + ], function (obj, val) { + obj['[object ' + val + 'Array]'] = true; + return obj; + }, {}); + var objToString = Object.prototype.toString; + var arrayProto = Array.prototype; + var nativeForEach = arrayProto.forEach; + var nativeFilter = arrayProto.filter; + var nativeSlice = arrayProto.slice; + var nativeMap = arrayProto.map; + var ctorFunction = function () { }.constructor; + var protoFunction = ctorFunction ? ctorFunction.prototype : null; + var protoKey = '__proto__'; + var idStart = 0x0907; + function guid() { + return idStart++; + } + function logError() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + if (typeof console !== 'undefined') { + console.error.apply(console, args); + } + } + function clone(source) { + if (source == null || typeof source !== 'object') { + return source; + } + var result = source; + var typeStr = objToString.call(source); + if (typeStr === '[object Array]') { + if (!isPrimitive(source)) { + result = []; + for (var i = 0, len = source.length; i < len; i++) { + result[i] = clone(source[i]); + } + } + } + else if (TYPED_ARRAY[typeStr]) { + if (!isPrimitive(source)) { + var Ctor = source.constructor; + if (Ctor.from) { + result = Ctor.from(source); + } + else { + result = new Ctor(source.length); + for (var i = 0, len = source.length; i < len; i++) { + result[i] = source[i]; + } + } + } + } + else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) { + result = {}; + for (var key in source) { + if (source.hasOwnProperty(key) && key !== protoKey) { + result[key] = clone(source[key]); + } + } + } + return result; + } + function merge(target, source, overwrite) { + if (!isObject(source) || !isObject(target)) { + return overwrite ? clone(source) : target; + } + for (var key in source) { + if (source.hasOwnProperty(key) && key !== protoKey) { + var targetProp = target[key]; + var sourceProp = source[key]; + if (isObject(sourceProp) + && isObject(targetProp) + && !isArray(sourceProp) + && !isArray(targetProp) + && !isDom(sourceProp) + && !isDom(targetProp) + && !isBuiltInObject(sourceProp) + && !isBuiltInObject(targetProp) + && !isPrimitive(sourceProp) + && !isPrimitive(targetProp)) { + merge(targetProp, sourceProp, overwrite); + } + else if (overwrite || !(key in target)) { + target[key] = clone(source[key]); + } + } + } + return target; + } + function mergeAll(targetAndSources, overwrite) { + var result = targetAndSources[0]; + for (var i = 1, len = targetAndSources.length; i < len; i++) { + result = merge(result, targetAndSources[i], overwrite); + } + return result; + } + function extend(target, source) { + if (Object.assign) { + Object.assign(target, source); + } + else { + for (var key in source) { + if (source.hasOwnProperty(key) && key !== protoKey) { + target[key] = source[key]; + } + } + } + return target; + } + function defaults(target, source, overlay) { + var keysArr = keys(source); + for (var i = 0; i < keysArr.length; i++) { + var key = keysArr[i]; + if ((overlay ? source[key] != null : target[key] == null)) { + target[key] = source[key]; + } + } + return target; + } + var createCanvas = platformApi.createCanvas; + function indexOf(array, value) { + if (array) { + if (array.indexOf) { + return array.indexOf(value); + } + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + } + return -1; + } + function inherits(clazz, baseClazz) { + var clazzPrototype = clazz.prototype; + function F() { } + F.prototype = baseClazz.prototype; + clazz.prototype = new F(); + for (var prop in clazzPrototype) { + if (clazzPrototype.hasOwnProperty(prop)) { + clazz.prototype[prop] = clazzPrototype[prop]; + } + } + clazz.prototype.constructor = clazz; + clazz.superClass = baseClazz; + } + function mixin(target, source, override) { + target = 'prototype' in target ? target.prototype : target; + source = 'prototype' in source ? source.prototype : source; + if (Object.getOwnPropertyNames) { + var keyList = Object.getOwnPropertyNames(source); + for (var i = 0; i < keyList.length; i++) { + var key = keyList[i]; + if (key !== 'constructor') { + if ((override ? source[key] != null : target[key] == null)) { + target[key] = source[key]; + } + } + } + } + else { + defaults(target, source, override); + } + } + function isArrayLike(data) { + if (!data) { + return false; + } + if (typeof data === 'string') { + return false; + } + return typeof data.length === 'number'; + } + function each(arr, cb, context) { + if (!(arr && cb)) { + return; + } + if (arr.forEach && arr.forEach === nativeForEach) { + arr.forEach(cb, context); + } + else if (arr.length === +arr.length) { + for (var i = 0, len = arr.length; i < len; i++) { + cb.call(context, arr[i], i, arr); + } + } + else { + for (var key in arr) { + if (arr.hasOwnProperty(key)) { + cb.call(context, arr[key], key, arr); + } + } + } + } + function map(arr, cb, context) { + if (!arr) { + return []; + } + if (!cb) { + return slice(arr); + } + if (arr.map && arr.map === nativeMap) { + return arr.map(cb, context); + } + else { + var result = []; + for (var i = 0, len = arr.length; i < len; i++) { + result.push(cb.call(context, arr[i], i, arr)); + } + return result; + } + } + function reduce(arr, cb, memo, context) { + if (!(arr && cb)) { + return; + } + for (var i = 0, len = arr.length; i < len; i++) { + memo = cb.call(context, memo, arr[i], i, arr); + } + return memo; + } + function filter(arr, cb, context) { + if (!arr) { + return []; + } + if (!cb) { + return slice(arr); + } + if (arr.filter && arr.filter === nativeFilter) { + return arr.filter(cb, context); + } + else { + var result = []; + for (var i = 0, len = arr.length; i < len; i++) { + if (cb.call(context, arr[i], i, arr)) { + result.push(arr[i]); + } + } + return result; + } + } + function find(arr, cb, context) { + if (!(arr && cb)) { + return; + } + for (var i = 0, len = arr.length; i < len; i++) { + if (cb.call(context, arr[i], i, arr)) { + return arr[i]; + } + } + } + function keys(obj) { + if (!obj) { + return []; + } + if (Object.keys) { + return Object.keys(obj); + } + var keyList = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + keyList.push(key); + } + } + return keyList; + } + function bindPolyfill(func, context) { + var args = []; + for (var _i = 2; _i < arguments.length; _i++) { + args[_i - 2] = arguments[_i]; + } + return function () { + return func.apply(context, args.concat(nativeSlice.call(arguments))); + }; + } + var bind = (protoFunction && isFunction(protoFunction.bind)) + ? protoFunction.call.bind(protoFunction.bind) + : bindPolyfill; + function curry(func) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + return function () { + return func.apply(this, args.concat(nativeSlice.call(arguments))); + }; + } + function isArray(value) { + if (Array.isArray) { + return Array.isArray(value); + } + return objToString.call(value) === '[object Array]'; + } + function isFunction(value) { + return typeof value === 'function'; + } + function isString(value) { + return typeof value === 'string'; + } + function isStringSafe(value) { + return objToString.call(value) === '[object String]'; + } + function isNumber(value) { + return typeof value === 'number'; + } + function isObject(value) { + var type = typeof value; + return type === 'function' || (!!value && type === 'object'); + } + function isBuiltInObject(value) { + return !!BUILTIN_OBJECT[objToString.call(value)]; + } + function isTypedArray(value) { + return !!TYPED_ARRAY[objToString.call(value)]; + } + function isDom(value) { + return typeof value === 'object' + && typeof value.nodeType === 'number' + && typeof value.ownerDocument === 'object'; + } + function isGradientObject(value) { + return value.colorStops != null; + } + function isImagePatternObject(value) { + return value.image != null; + } + function isRegExp(value) { + return objToString.call(value) === '[object RegExp]'; + } + function eqNaN(value) { + return value !== value; + } + function retrieve() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + for (var i = 0, len = args.length; i < len; i++) { + if (args[i] != null) { + return args[i]; + } + } + } + function retrieve2(value0, value1) { + return value0 != null + ? value0 + : value1; + } + function retrieve3(value0, value1, value2) { + return value0 != null + ? value0 + : value1 != null + ? value1 + : value2; + } + function slice(arr) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + return nativeSlice.apply(arr, args); + } + function normalizeCssArray(val) { + if (typeof (val) === 'number') { + return [val, val, val, val]; + } + var len = val.length; + if (len === 2) { + return [val[0], val[1], val[0], val[1]]; + } + else if (len === 3) { + return [val[0], val[1], val[2], val[1]]; + } + return val; + } + function assert(condition, message) { + if (!condition) { + throw new Error(message); + } + } + function trim(str) { + if (str == null) { + return null; + } + else if (typeof str.trim === 'function') { + return str.trim(); + } + else { + return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + } + } + var primitiveKey = '__ec_primitive__'; + function setAsPrimitive(obj) { + obj[primitiveKey] = true; + } + function isPrimitive(obj) { + return obj[primitiveKey]; + } + var HashMap = (function () { + function HashMap(obj) { + this.data = {}; + var isArr = isArray(obj); + this.data = {}; + var thisMap = this; + (obj instanceof HashMap) + ? obj.each(visit) + : (obj && each(obj, visit)); + function visit(value, key) { + isArr ? thisMap.set(value, key) : thisMap.set(key, value); + } + } + HashMap.prototype.get = function (key) { + return this.data.hasOwnProperty(key) ? this.data[key] : null; + }; + HashMap.prototype.set = function (key, value) { + return (this.data[key] = value); + }; + HashMap.prototype.each = function (cb, context) { + for (var key in this.data) { + if (this.data.hasOwnProperty(key)) { + cb.call(context, this.data[key], key); + } + } + }; + HashMap.prototype.keys = function () { + return keys(this.data); + }; + HashMap.prototype.removeKey = function (key) { + delete this.data[key]; + }; + return HashMap; + }()); + function createHashMap(obj) { + return new HashMap(obj); + } + function concatArray(a, b) { + var newArray = new a.constructor(a.length + b.length); + for (var i = 0; i < a.length; i++) { + newArray[i] = a[i]; + } + var offset = a.length; + for (var i = 0; i < b.length; i++) { + newArray[i + offset] = b[i]; + } + return newArray; + } + function createObject(proto, properties) { + var obj; + if (Object.create) { + obj = Object.create(proto); + } + else { + var StyleCtor = function () { }; + StyleCtor.prototype = proto; + obj = new StyleCtor(); + } + if (properties) { + extend(obj, properties); + } + return obj; + } + function disableUserSelect(dom) { + var domStyle = dom.style; + domStyle.webkitUserSelect = 'none'; + domStyle.userSelect = 'none'; + domStyle.webkitTapHighlightColor = 'rgba(0,0,0,0)'; + domStyle['-webkit-touch-callout'] = 'none'; + } + function hasOwn(own, prop) { + return own.hasOwnProperty(prop); + } + function noop() { } + var RADIAN_TO_DEGREE = 180 / Math.PI; + + var util = /*#__PURE__*/Object.freeze({ + __proto__: null, + guid: guid, + logError: logError, + clone: clone, + merge: merge, + mergeAll: mergeAll, + extend: extend, + defaults: defaults, + createCanvas: createCanvas, + indexOf: indexOf, + inherits: inherits, + mixin: mixin, + isArrayLike: isArrayLike, + each: each, + map: map, + reduce: reduce, + filter: filter, + find: find, + keys: keys, + bind: bind, + curry: curry, + isArray: isArray, + isFunction: isFunction, + isString: isString, + isStringSafe: isStringSafe, + isNumber: isNumber, + isObject: isObject, + isBuiltInObject: isBuiltInObject, + isTypedArray: isTypedArray, + isDom: isDom, + isGradientObject: isGradientObject, + isImagePatternObject: isImagePatternObject, + isRegExp: isRegExp, + eqNaN: eqNaN, + retrieve: retrieve, + retrieve2: retrieve2, + retrieve3: retrieve3, + slice: slice, + normalizeCssArray: normalizeCssArray, + assert: assert, + trim: trim, + setAsPrimitive: setAsPrimitive, + isPrimitive: isPrimitive, + HashMap: HashMap, + createHashMap: createHashMap, + concatArray: concatArray, + createObject: createObject, + disableUserSelect: disableUserSelect, + hasOwn: hasOwn, + noop: noop, + RADIAN_TO_DEGREE: RADIAN_TO_DEGREE + }); + + function create(x, y) { + if (x == null) { + x = 0; + } + if (y == null) { + y = 0; + } + return [x, y]; + } + function copy(out, v) { + out[0] = v[0]; + out[1] = v[1]; + return out; + } + function clone$1(v) { + return [v[0], v[1]]; + } + function set(out, a, b) { + out[0] = a; + out[1] = b; + return out; + } + function add(out, v1, v2) { + out[0] = v1[0] + v2[0]; + out[1] = v1[1] + v2[1]; + return out; + } + function scaleAndAdd(out, v1, v2, a) { + out[0] = v1[0] + v2[0] * a; + out[1] = v1[1] + v2[1] * a; + return out; + } + function sub(out, v1, v2) { + out[0] = v1[0] - v2[0]; + out[1] = v1[1] - v2[1]; + return out; + } + function len(v) { + return Math.sqrt(lenSquare(v)); + } + var length = len; + function lenSquare(v) { + return v[0] * v[0] + v[1] * v[1]; + } + var lengthSquare = lenSquare; + function mul(out, v1, v2) { + out[0] = v1[0] * v2[0]; + out[1] = v1[1] * v2[1]; + return out; + } + function div(out, v1, v2) { + out[0] = v1[0] / v2[0]; + out[1] = v1[1] / v2[1]; + return out; + } + function dot(v1, v2) { + return v1[0] * v2[0] + v1[1] * v2[1]; + } + function scale(out, v, s) { + out[0] = v[0] * s; + out[1] = v[1] * s; + return out; + } + function normalize(out, v) { + var d = len(v); + if (d === 0) { + out[0] = 0; + out[1] = 0; + } + else { + out[0] = v[0] / d; + out[1] = v[1] / d; + } + return out; + } + function distance(v1, v2) { + return Math.sqrt((v1[0] - v2[0]) * (v1[0] - v2[0]) + + (v1[1] - v2[1]) * (v1[1] - v2[1])); + } + var dist = distance; + function distanceSquare(v1, v2) { + return (v1[0] - v2[0]) * (v1[0] - v2[0]) + + (v1[1] - v2[1]) * (v1[1] - v2[1]); + } + var distSquare = distanceSquare; + function negate(out, v) { + out[0] = -v[0]; + out[1] = -v[1]; + return out; + } + function lerp(out, v1, v2, t) { + out[0] = v1[0] + t * (v2[0] - v1[0]); + out[1] = v1[1] + t * (v2[1] - v1[1]); + return out; + } + function applyTransform(out, v, m) { + var x = v[0]; + var y = v[1]; + out[0] = m[0] * x + m[2] * y + m[4]; + out[1] = m[1] * x + m[3] * y + m[5]; + return out; + } + function min(out, v1, v2) { + out[0] = Math.min(v1[0], v2[0]); + out[1] = Math.min(v1[1], v2[1]); + return out; + } + function max(out, v1, v2) { + out[0] = Math.max(v1[0], v2[0]); + out[1] = Math.max(v1[1], v2[1]); + return out; + } + + var vector = /*#__PURE__*/Object.freeze({ + __proto__: null, + create: create, + copy: copy, + clone: clone$1, + set: set, + add: add, + scaleAndAdd: scaleAndAdd, + sub: sub, + len: len, + length: length, + lenSquare: lenSquare, + lengthSquare: lengthSquare, + mul: mul, + div: div, + dot: dot, + scale: scale, + normalize: normalize, + distance: distance, + dist: dist, + distanceSquare: distanceSquare, + distSquare: distSquare, + negate: negate, + lerp: lerp, + applyTransform: applyTransform, + min: min, + max: max + }); + + var Param = (function () { + function Param(target, e) { + this.target = target; + this.topTarget = e && e.topTarget; + } + return Param; + }()); + var Draggable = (function () { + function Draggable(handler) { + this.handler = handler; + handler.on('mousedown', this._dragStart, this); + handler.on('mousemove', this._drag, this); + handler.on('mouseup', this._dragEnd, this); + } + Draggable.prototype._dragStart = function (e) { + var draggingTarget = e.target; + while (draggingTarget && !draggingTarget.draggable) { + draggingTarget = draggingTarget.parent || draggingTarget.__hostTarget; + } + if (draggingTarget) { + this._draggingTarget = draggingTarget; + draggingTarget.dragging = true; + this._x = e.offsetX; + this._y = e.offsetY; + this.handler.dispatchToElement(new Param(draggingTarget, e), 'dragstart', e.event); + } + }; + Draggable.prototype._drag = function (e) { + var draggingTarget = this._draggingTarget; + if (draggingTarget) { + var x = e.offsetX; + var y = e.offsetY; + var dx = x - this._x; + var dy = y - this._y; + this._x = x; + this._y = y; + draggingTarget.drift(dx, dy, e); + this.handler.dispatchToElement(new Param(draggingTarget, e), 'drag', e.event); + var dropTarget = this.handler.findHover(x, y, draggingTarget).target; + var lastDropTarget = this._dropTarget; + this._dropTarget = dropTarget; + if (draggingTarget !== dropTarget) { + if (lastDropTarget && dropTarget !== lastDropTarget) { + this.handler.dispatchToElement(new Param(lastDropTarget, e), 'dragleave', e.event); + } + if (dropTarget && dropTarget !== lastDropTarget) { + this.handler.dispatchToElement(new Param(dropTarget, e), 'dragenter', e.event); + } + } + } + }; + Draggable.prototype._dragEnd = function (e) { + var draggingTarget = this._draggingTarget; + if (draggingTarget) { + draggingTarget.dragging = false; + } + this.handler.dispatchToElement(new Param(draggingTarget, e), 'dragend', e.event); + if (this._dropTarget) { + this.handler.dispatchToElement(new Param(this._dropTarget, e), 'drop', e.event); + } + this._draggingTarget = null; + this._dropTarget = null; + }; + return Draggable; + }()); + + var Eventful = (function () { + function Eventful(eventProcessors) { + if (eventProcessors) { + this._$eventProcessor = eventProcessors; + } + } + Eventful.prototype.on = function (event, query, handler, context) { + if (!this._$handlers) { + this._$handlers = {}; + } + var _h = this._$handlers; + if (typeof query === 'function') { + context = handler; + handler = query; + query = null; + } + if (!handler || !event) { + return this; + } + var eventProcessor = this._$eventProcessor; + if (query != null && eventProcessor && eventProcessor.normalizeQuery) { + query = eventProcessor.normalizeQuery(query); + } + if (!_h[event]) { + _h[event] = []; + } + for (var i = 0; i < _h[event].length; i++) { + if (_h[event][i].h === handler) { + return this; + } + } + var wrap = { + h: handler, + query: query, + ctx: (context || this), + callAtLast: handler.zrEventfulCallAtLast + }; + var lastIndex = _h[event].length - 1; + var lastWrap = _h[event][lastIndex]; + (lastWrap && lastWrap.callAtLast) + ? _h[event].splice(lastIndex, 0, wrap) + : _h[event].push(wrap); + return this; + }; + Eventful.prototype.isSilent = function (eventName) { + var _h = this._$handlers; + return !_h || !_h[eventName] || !_h[eventName].length; + }; + Eventful.prototype.off = function (eventType, handler) { + var _h = this._$handlers; + if (!_h) { + return this; + } + if (!eventType) { + this._$handlers = {}; + return this; + } + if (handler) { + if (_h[eventType]) { + var newList = []; + for (var i = 0, l = _h[eventType].length; i < l; i++) { + if (_h[eventType][i].h !== handler) { + newList.push(_h[eventType][i]); + } + } + _h[eventType] = newList; + } + if (_h[eventType] && _h[eventType].length === 0) { + delete _h[eventType]; + } + } + else { + delete _h[eventType]; + } + return this; + }; + Eventful.prototype.trigger = function (eventType) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + if (!this._$handlers) { + return this; + } + var _h = this._$handlers[eventType]; + var eventProcessor = this._$eventProcessor; + if (_h) { + var argLen = args.length; + var len = _h.length; + for (var i = 0; i < len; i++) { + var hItem = _h[i]; + if (eventProcessor + && eventProcessor.filter + && hItem.query != null + && !eventProcessor.filter(eventType, hItem.query)) { + continue; + } + switch (argLen) { + case 0: + hItem.h.call(hItem.ctx); + break; + case 1: + hItem.h.call(hItem.ctx, args[0]); + break; + case 2: + hItem.h.call(hItem.ctx, args[0], args[1]); + break; + default: + hItem.h.apply(hItem.ctx, args); + break; + } + } + } + eventProcessor && eventProcessor.afterTrigger + && eventProcessor.afterTrigger(eventType); + return this; + }; + Eventful.prototype.triggerWithContext = function (type) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + if (!this._$handlers) { + return this; + } + var _h = this._$handlers[type]; + var eventProcessor = this._$eventProcessor; + if (_h) { + var argLen = args.length; + var ctx = args[argLen - 1]; + var len = _h.length; + for (var i = 0; i < len; i++) { + var hItem = _h[i]; + if (eventProcessor + && eventProcessor.filter + && hItem.query != null + && !eventProcessor.filter(type, hItem.query)) { + continue; + } + switch (argLen) { + case 0: + hItem.h.call(ctx); + break; + case 1: + hItem.h.call(ctx, args[0]); + break; + case 2: + hItem.h.call(ctx, args[0], args[1]); + break; + default: + hItem.h.apply(ctx, args.slice(1, argLen - 1)); + break; + } + } + } + eventProcessor && eventProcessor.afterTrigger + && eventProcessor.afterTrigger(type); + return this; + }; + return Eventful; + }()); + + var LN2 = Math.log(2); + function determinant(rows, rank, rowStart, rowMask, colMask, detCache) { + var cacheKey = rowMask + '-' + colMask; + var fullRank = rows.length; + if (detCache.hasOwnProperty(cacheKey)) { + return detCache[cacheKey]; + } + if (rank === 1) { + var colStart = Math.round(Math.log(((1 << fullRank) - 1) & ~colMask) / LN2); + return rows[rowStart][colStart]; + } + var subRowMask = rowMask | (1 << rowStart); + var subRowStart = rowStart + 1; + while (rowMask & (1 << subRowStart)) { + subRowStart++; + } + var sum = 0; + for (var j = 0, colLocalIdx = 0; j < fullRank; j++) { + var colTag = 1 << j; + if (!(colTag & colMask)) { + sum += (colLocalIdx % 2 ? -1 : 1) * rows[rowStart][j] + * determinant(rows, rank - 1, subRowStart, subRowMask, colMask | colTag, detCache); + colLocalIdx++; + } + } + detCache[cacheKey] = sum; + return sum; + } + function buildTransformer(src, dest) { + var mA = [ + [src[0], src[1], 1, 0, 0, 0, -dest[0] * src[0], -dest[0] * src[1]], + [0, 0, 0, src[0], src[1], 1, -dest[1] * src[0], -dest[1] * src[1]], + [src[2], src[3], 1, 0, 0, 0, -dest[2] * src[2], -dest[2] * src[3]], + [0, 0, 0, src[2], src[3], 1, -dest[3] * src[2], -dest[3] * src[3]], + [src[4], src[5], 1, 0, 0, 0, -dest[4] * src[4], -dest[4] * src[5]], + [0, 0, 0, src[4], src[5], 1, -dest[5] * src[4], -dest[5] * src[5]], + [src[6], src[7], 1, 0, 0, 0, -dest[6] * src[6], -dest[6] * src[7]], + [0, 0, 0, src[6], src[7], 1, -dest[7] * src[6], -dest[7] * src[7]] + ]; + var detCache = {}; + var det = determinant(mA, 8, 0, 0, 0, detCache); + if (det === 0) { + return; + } + var vh = []; + for (var i = 0; i < 8; i++) { + for (var j = 0; j < 8; j++) { + vh[j] == null && (vh[j] = 0); + vh[j] += ((i + j) % 2 ? -1 : 1) + * determinant(mA, 7, i === 0 ? 1 : 0, 1 << i, 1 << j, detCache) + / det * dest[i]; + } + } + return function (out, srcPointX, srcPointY) { + var pk = srcPointX * vh[6] + srcPointY * vh[7] + 1; + out[0] = (srcPointX * vh[0] + srcPointY * vh[1] + vh[2]) / pk; + out[1] = (srcPointX * vh[3] + srcPointY * vh[4] + vh[5]) / pk; + }; + } + + var EVENT_SAVED_PROP = '___zrEVENTSAVED'; + var _calcOut = []; + function transformLocalCoord(out, elFrom, elTarget, inX, inY) { + return transformCoordWithViewport(_calcOut, elFrom, inX, inY, true) + && transformCoordWithViewport(out, elTarget, _calcOut[0], _calcOut[1]); + } + function transformCoordWithViewport(out, el, inX, inY, inverse) { + if (el.getBoundingClientRect && env.domSupported && !isCanvasEl(el)) { + var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {}); + var markers = prepareCoordMarkers(el, saved); + var transformer = preparePointerTransformer(markers, saved, inverse); + if (transformer) { + transformer(out, inX, inY); + return true; + } + } + return false; + } + function prepareCoordMarkers(el, saved) { + var markers = saved.markers; + if (markers) { + return markers; + } + markers = saved.markers = []; + var propLR = ['left', 'right']; + var propTB = ['top', 'bottom']; + for (var i = 0; i < 4; i++) { + var marker = document.createElement('div'); + var stl = marker.style; + var idxLR = i % 2; + var idxTB = (i >> 1) % 2; + stl.cssText = [ + 'position: absolute', + 'visibility: hidden', + 'padding: 0', + 'margin: 0', + 'border-width: 0', + 'user-select: none', + 'width:0', + 'height:0', + propLR[idxLR] + ':0', + propTB[idxTB] + ':0', + propLR[1 - idxLR] + ':auto', + propTB[1 - idxTB] + ':auto', + '' + ].join('!important;'); + el.appendChild(marker); + markers.push(marker); + } + return markers; + } + function preparePointerTransformer(markers, saved, inverse) { + var transformerName = inverse ? 'invTrans' : 'trans'; + var transformer = saved[transformerName]; + var oldSrcCoords = saved.srcCoords; + var srcCoords = []; + var destCoords = []; + var oldCoordTheSame = true; + for (var i = 0; i < 4; i++) { + var rect = markers[i].getBoundingClientRect(); + var ii = 2 * i; + var x = rect.left; + var y = rect.top; + srcCoords.push(x, y); + oldCoordTheSame = oldCoordTheSame && oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1]; + destCoords.push(markers[i].offsetLeft, markers[i].offsetTop); + } + return (oldCoordTheSame && transformer) + ? transformer + : (saved.srcCoords = srcCoords, + saved[transformerName] = inverse + ? buildTransformer(destCoords, srcCoords) + : buildTransformer(srcCoords, destCoords)); + } + function isCanvasEl(el) { + return el.nodeName.toUpperCase() === 'CANVAS'; + } + + var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/; + var _calcOut$1 = []; + var firefoxNotSupportOffsetXY = env.browser.firefox + && +env.browser.version.split('.')[0] < 39; + function clientToLocal(el, e, out, calculate) { + out = out || {}; + if (calculate) { + calculateZrXY(el, e, out); + } + else if (firefoxNotSupportOffsetXY + && e.layerX != null + && e.layerX !== e.offsetX) { + out.zrX = e.layerX; + out.zrY = e.layerY; + } + else if (e.offsetX != null) { + out.zrX = e.offsetX; + out.zrY = e.offsetY; + } + else { + calculateZrXY(el, e, out); + } + return out; + } + function calculateZrXY(el, e, out) { + if (env.domSupported && el.getBoundingClientRect) { + var ex = e.clientX; + var ey = e.clientY; + if (isCanvasEl(el)) { + var box = el.getBoundingClientRect(); + out.zrX = ex - box.left; + out.zrY = ey - box.top; + return; + } + else { + if (transformCoordWithViewport(_calcOut$1, el, ex, ey)) { + out.zrX = _calcOut$1[0]; + out.zrY = _calcOut$1[1]; + return; + } + } + } + out.zrX = out.zrY = 0; + } + function getNativeEvent(e) { + return e + || window.event; + } + function normalizeEvent(el, e, calculate) { + e = getNativeEvent(e); + if (e.zrX != null) { + return e; + } + var eventType = e.type; + var isTouch = eventType && eventType.indexOf('touch') >= 0; + if (!isTouch) { + clientToLocal(el, e, e, calculate); + var wheelDelta = getWheelDeltaMayPolyfill(e); + e.zrDelta = wheelDelta ? wheelDelta / 120 : -(e.detail || 0) / 3; + } + else { + var touch = eventType !== 'touchend' + ? e.targetTouches[0] + : e.changedTouches[0]; + touch && clientToLocal(el, touch, e, calculate); + } + var button = e.button; + if (e.which == null && button !== undefined && MOUSE_EVENT_REG.test(e.type)) { + e.which = (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0))); + } + return e; + } + function getWheelDeltaMayPolyfill(e) { + var rawWheelDelta = e.wheelDelta; + if (rawWheelDelta) { + return rawWheelDelta; + } + var deltaX = e.deltaX; + var deltaY = e.deltaY; + if (deltaX == null || deltaY == null) { + return rawWheelDelta; + } + var delta = deltaY !== 0 ? Math.abs(deltaY) : Math.abs(deltaX); + var sign = deltaY > 0 ? -1 + : deltaY < 0 ? 1 + : deltaX > 0 ? -1 + : 1; + return 3 * delta * sign; + } + function addEventListener(el, name, handler, opt) { + el.addEventListener(name, handler, opt); + } + function removeEventListener(el, name, handler, opt) { + el.removeEventListener(name, handler, opt); + } + var stop = function (e) { + e.preventDefault(); + e.stopPropagation(); + e.cancelBubble = true; + }; + function isMiddleOrRightButtonOnMouseUpDown(e) { + return e.which === 2 || e.which === 3; + } + + var GestureMgr = (function () { + function GestureMgr() { + this._track = []; + } + GestureMgr.prototype.recognize = function (event, target, root) { + this._doTrack(event, target, root); + return this._recognize(event); + }; + GestureMgr.prototype.clear = function () { + this._track.length = 0; + return this; + }; + GestureMgr.prototype._doTrack = function (event, target, root) { + var touches = event.touches; + if (!touches) { + return; + } + var trackItem = { + points: [], + touches: [], + target: target, + event: event + }; + for (var i = 0, len = touches.length; i < len; i++) { + var touch = touches[i]; + var pos = clientToLocal(root, touch, {}); + trackItem.points.push([pos.zrX, pos.zrY]); + trackItem.touches.push(touch); + } + this._track.push(trackItem); + }; + GestureMgr.prototype._recognize = function (event) { + for (var eventName in recognizers) { + if (recognizers.hasOwnProperty(eventName)) { + var gestureInfo = recognizers[eventName](this._track, event); + if (gestureInfo) { + return gestureInfo; + } + } + } + }; + return GestureMgr; + }()); + function dist$1(pointPair) { + var dx = pointPair[1][0] - pointPair[0][0]; + var dy = pointPair[1][1] - pointPair[0][1]; + return Math.sqrt(dx * dx + dy * dy); + } + function center(pointPair) { + return [ + (pointPair[0][0] + pointPair[1][0]) / 2, + (pointPair[0][1] + pointPair[1][1]) / 2 + ]; + } + var recognizers = { + pinch: function (tracks, event) { + var trackLen = tracks.length; + if (!trackLen) { + return; + } + var pinchEnd = (tracks[trackLen - 1] || {}).points; + var pinchPre = (tracks[trackLen - 2] || {}).points || pinchEnd; + if (pinchPre + && pinchPre.length > 1 + && pinchEnd + && pinchEnd.length > 1) { + var pinchScale = dist$1(pinchEnd) / dist$1(pinchPre); + !isFinite(pinchScale) && (pinchScale = 1); + event.pinchScale = pinchScale; + var pinchCenter = center(pinchEnd); + event.pinchX = pinchCenter[0]; + event.pinchY = pinchCenter[1]; + return { + type: 'pinch', + target: tracks[0].target, + event: event + }; + } + } + }; + + var SILENT = 'silent'; + function makeEventPacket(eveType, targetInfo, event) { + return { + type: eveType, + event: event, + target: targetInfo.target, + topTarget: targetInfo.topTarget, + cancelBubble: false, + offsetX: event.zrX, + offsetY: event.zrY, + gestureEvent: event.gestureEvent, + pinchX: event.pinchX, + pinchY: event.pinchY, + pinchScale: event.pinchScale, + wheelDelta: event.zrDelta, + zrByTouch: event.zrByTouch, + which: event.which, + stop: stopEvent + }; + } + function stopEvent() { + stop(this.event); + } + var EmptyProxy = (function (_super) { + __extends(EmptyProxy, _super); + function EmptyProxy() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.handler = null; + return _this; + } + EmptyProxy.prototype.dispose = function () { }; + EmptyProxy.prototype.setCursor = function () { }; + return EmptyProxy; + }(Eventful)); + var HoveredResult = (function () { + function HoveredResult(x, y) { + this.x = x; + this.y = y; + } + return HoveredResult; + }()); + var handlerNames = [ + 'click', 'dblclick', 'mousewheel', 'mouseout', + 'mouseup', 'mousedown', 'mousemove', 'contextmenu' + ]; + var Handler = (function (_super) { + __extends(Handler, _super); + function Handler(storage, painter, proxy, painterRoot) { + var _this = _super.call(this) || this; + _this._hovered = new HoveredResult(0, 0); + _this.storage = storage; + _this.painter = painter; + _this.painterRoot = painterRoot; + proxy = proxy || new EmptyProxy(); + _this.proxy = null; + _this.setHandlerProxy(proxy); + _this._draggingMgr = new Draggable(_this); + return _this; + } + Handler.prototype.setHandlerProxy = function (proxy) { + if (this.proxy) { + this.proxy.dispose(); + } + if (proxy) { + each(handlerNames, function (name) { + proxy.on && proxy.on(name, this[name], this); + }, this); + proxy.handler = this; + } + this.proxy = proxy; + }; + Handler.prototype.mousemove = function (event) { + var x = event.zrX; + var y = event.zrY; + var isOutside = isOutsideBoundary(this, x, y); + var lastHovered = this._hovered; + var lastHoveredTarget = lastHovered.target; + if (lastHoveredTarget && !lastHoveredTarget.__zr) { + lastHovered = this.findHover(lastHovered.x, lastHovered.y); + lastHoveredTarget = lastHovered.target; + } + var hovered = this._hovered = isOutside ? new HoveredResult(x, y) : this.findHover(x, y); + var hoveredTarget = hovered.target; + var proxy = this.proxy; + proxy.setCursor && proxy.setCursor(hoveredTarget ? hoveredTarget.cursor : 'default'); + if (lastHoveredTarget && hoveredTarget !== lastHoveredTarget) { + this.dispatchToElement(lastHovered, 'mouseout', event); + } + this.dispatchToElement(hovered, 'mousemove', event); + if (hoveredTarget && hoveredTarget !== lastHoveredTarget) { + this.dispatchToElement(hovered, 'mouseover', event); + } + }; + Handler.prototype.mouseout = function (event) { + var eventControl = event.zrEventControl; + if (eventControl !== 'only_globalout') { + this.dispatchToElement(this._hovered, 'mouseout', event); + } + if (eventControl !== 'no_globalout') { + this.trigger('globalout', { type: 'globalout', event: event }); + } + }; + Handler.prototype.resize = function () { + this._hovered = new HoveredResult(0, 0); + }; + Handler.prototype.dispatch = function (eventName, eventArgs) { + var handler = this[eventName]; + handler && handler.call(this, eventArgs); + }; + Handler.prototype.dispose = function () { + this.proxy.dispose(); + this.storage = null; + this.proxy = null; + this.painter = null; + }; + Handler.prototype.setCursorStyle = function (cursorStyle) { + var proxy = this.proxy; + proxy.setCursor && proxy.setCursor(cursorStyle); + }; + Handler.prototype.dispatchToElement = function (targetInfo, eventName, event) { + targetInfo = targetInfo || {}; + var el = targetInfo.target; + if (el && el.silent) { + return; + } + var eventKey = ('on' + eventName); + var eventPacket = makeEventPacket(eventName, targetInfo, event); + while (el) { + el[eventKey] + && (eventPacket.cancelBubble = !!el[eventKey].call(el, eventPacket)); + el.trigger(eventName, eventPacket); + el = el.__hostTarget ? el.__hostTarget : el.parent; + if (eventPacket.cancelBubble) { + break; + } + } + if (!eventPacket.cancelBubble) { + this.trigger(eventName, eventPacket); + if (this.painter && this.painter.eachOtherLayer) { + this.painter.eachOtherLayer(function (layer) { + if (typeof (layer[eventKey]) === 'function') { + layer[eventKey].call(layer, eventPacket); + } + if (layer.trigger) { + layer.trigger(eventName, eventPacket); + } + }); + } + } + }; + Handler.prototype.findHover = function (x, y, exclude) { + var list = this.storage.getDisplayList(); + var out = new HoveredResult(x, y); + for (var i = list.length - 1; i >= 0; i--) { + var hoverCheckResult = void 0; + if (list[i] !== exclude + && !list[i].ignore + && (hoverCheckResult = isHover(list[i], x, y))) { + !out.topTarget && (out.topTarget = list[i]); + if (hoverCheckResult !== SILENT) { + out.target = list[i]; + break; + } + } + } + return out; + }; + Handler.prototype.processGesture = function (event, stage) { + if (!this._gestureMgr) { + this._gestureMgr = new GestureMgr(); + } + var gestureMgr = this._gestureMgr; + stage === 'start' && gestureMgr.clear(); + var gestureInfo = gestureMgr.recognize(event, this.findHover(event.zrX, event.zrY, null).target, this.proxy.dom); + stage === 'end' && gestureMgr.clear(); + if (gestureInfo) { + var type = gestureInfo.type; + event.gestureEvent = type; + var res = new HoveredResult(); + res.target = gestureInfo.target; + this.dispatchToElement(res, type, gestureInfo.event); + } + }; + return Handler; + }(Eventful)); + each(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) { + Handler.prototype[name] = function (event) { + var x = event.zrX; + var y = event.zrY; + var isOutside = isOutsideBoundary(this, x, y); + var hovered; + var hoveredTarget; + if (name !== 'mouseup' || !isOutside) { + hovered = this.findHover(x, y); + hoveredTarget = hovered.target; + } + if (name === 'mousedown') { + this._downEl = hoveredTarget; + this._downPoint = [event.zrX, event.zrY]; + this._upEl = hoveredTarget; + } + else if (name === 'mouseup') { + this._upEl = hoveredTarget; + } + else if (name === 'click') { + if (this._downEl !== this._upEl + || !this._downPoint + || dist(this._downPoint, [event.zrX, event.zrY]) > 4) { + return; + } + this._downPoint = null; + } + this.dispatchToElement(hovered, name, event); + }; + }); + function isHover(displayable, x, y) { + if (displayable[displayable.rectHover ? 'rectContain' : 'contain'](x, y)) { + var el = displayable; + var isSilent = void 0; + var ignoreClip = false; + while (el) { + if (el.ignoreClip) { + ignoreClip = true; + } + if (!ignoreClip) { + var clipPath = el.getClipPath(); + if (clipPath && !clipPath.contain(x, y)) { + return false; + } + if (el.silent) { + isSilent = true; + } + } + var hostEl = el.__hostTarget; + el = hostEl ? hostEl : el.parent; + } + return isSilent ? SILENT : true; + } + return false; + } + function isOutsideBoundary(handlerInstance, x, y) { + var painter = handlerInstance.painter; + return x < 0 || x > painter.getWidth() || y < 0 || y > painter.getHeight(); + } + + var DEFAULT_MIN_MERGE = 32; + var DEFAULT_MIN_GALLOPING = 7; + function minRunLength(n) { + var r = 0; + while (n >= DEFAULT_MIN_MERGE) { + r |= n & 1; + n >>= 1; + } + return n + r; + } + function makeAscendingRun(array, lo, hi, compare) { + var runHi = lo + 1; + if (runHi === hi) { + return 1; + } + if (compare(array[runHi++], array[lo]) < 0) { + while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) { + runHi++; + } + reverseRun(array, lo, runHi); + } + else { + while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) { + runHi++; + } + } + return runHi - lo; + } + function reverseRun(array, lo, hi) { + hi--; + while (lo < hi) { + var t = array[lo]; + array[lo++] = array[hi]; + array[hi--] = t; + } + } + function binaryInsertionSort(array, lo, hi, start, compare) { + if (start === lo) { + start++; + } + for (; start < hi; start++) { + var pivot = array[start]; + var left = lo; + var right = start; + var mid; + while (left < right) { + mid = left + right >>> 1; + if (compare(pivot, array[mid]) < 0) { + right = mid; + } + else { + left = mid + 1; + } + } + var n = start - left; + switch (n) { + case 3: + array[left + 3] = array[left + 2]; + case 2: + array[left + 2] = array[left + 1]; + case 1: + array[left + 1] = array[left]; + break; + default: + while (n > 0) { + array[left + n] = array[left + n - 1]; + n--; + } + } + array[left] = pivot; + } + } + function gallopLeft(value, array, start, length, hint, compare) { + var lastOffset = 0; + var maxOffset = 0; + var offset = 1; + if (compare(value, array[start + hint]) > 0) { + maxOffset = length - hint; + while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + if (offset <= 0) { + offset = maxOffset; + } + } + if (offset > maxOffset) { + offset = maxOffset; + } + lastOffset += hint; + offset += hint; + } + else { + maxOffset = hint + 1; + while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + if (offset <= 0) { + offset = maxOffset; + } + } + if (offset > maxOffset) { + offset = maxOffset; + } + var tmp = lastOffset; + lastOffset = hint - offset; + offset = hint - tmp; + } + lastOffset++; + while (lastOffset < offset) { + var m = lastOffset + (offset - lastOffset >>> 1); + if (compare(value, array[start + m]) > 0) { + lastOffset = m + 1; + } + else { + offset = m; + } + } + return offset; + } + function gallopRight(value, array, start, length, hint, compare) { + var lastOffset = 0; + var maxOffset = 0; + var offset = 1; + if (compare(value, array[start + hint]) < 0) { + maxOffset = hint + 1; + while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + if (offset <= 0) { + offset = maxOffset; + } + } + if (offset > maxOffset) { + offset = maxOffset; + } + var tmp = lastOffset; + lastOffset = hint - offset; + offset = hint - tmp; + } + else { + maxOffset = length - hint; + while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + if (offset <= 0) { + offset = maxOffset; + } + } + if (offset > maxOffset) { + offset = maxOffset; + } + lastOffset += hint; + offset += hint; + } + lastOffset++; + while (lastOffset < offset) { + var m = lastOffset + (offset - lastOffset >>> 1); + if (compare(value, array[start + m]) < 0) { + offset = m; + } + else { + lastOffset = m + 1; + } + } + return offset; + } + function TimSort(array, compare) { + var minGallop = DEFAULT_MIN_GALLOPING; + var length = 0; + var runStart; + var runLength; + var stackSize = 0; + length = array.length; + var tmp = []; + runStart = []; + runLength = []; + function pushRun(_runStart, _runLength) { + runStart[stackSize] = _runStart; + runLength[stackSize] = _runLength; + stackSize += 1; + } + function mergeRuns() { + while (stackSize > 1) { + var n = stackSize - 2; + if ((n >= 1 && runLength[n - 1] <= runLength[n] + runLength[n + 1]) + || (n >= 2 && runLength[n - 2] <= runLength[n] + runLength[n - 1])) { + if (runLength[n - 1] < runLength[n + 1]) { + n--; + } + } + else if (runLength[n] > runLength[n + 1]) { + break; + } + mergeAt(n); + } + } + function forceMergeRuns() { + while (stackSize > 1) { + var n = stackSize - 2; + if (n > 0 && runLength[n - 1] < runLength[n + 1]) { + n--; + } + mergeAt(n); + } + } + function mergeAt(i) { + var start1 = runStart[i]; + var length1 = runLength[i]; + var start2 = runStart[i + 1]; + var length2 = runLength[i + 1]; + runLength[i] = length1 + length2; + if (i === stackSize - 3) { + runStart[i + 1] = runStart[i + 2]; + runLength[i + 1] = runLength[i + 2]; + } + stackSize--; + var k = gallopRight(array[start2], array, start1, length1, 0, compare); + start1 += k; + length1 -= k; + if (length1 === 0) { + return; + } + length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare); + if (length2 === 0) { + return; + } + if (length1 <= length2) { + mergeLow(start1, length1, start2, length2); + } + else { + mergeHigh(start1, length1, start2, length2); + } + } + function mergeLow(start1, length1, start2, length2) { + var i = 0; + for (i = 0; i < length1; i++) { + tmp[i] = array[start1 + i]; + } + var cursor1 = 0; + var cursor2 = start2; + var dest = start1; + array[dest++] = array[cursor2++]; + if (--length2 === 0) { + for (i = 0; i < length1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + return; + } + if (length1 === 1) { + for (i = 0; i < length2; i++) { + array[dest + i] = array[cursor2 + i]; + } + array[dest + length2] = tmp[cursor1]; + return; + } + var _minGallop = minGallop; + var count1; + var count2; + var exit; + while (1) { + count1 = 0; + count2 = 0; + exit = false; + do { + if (compare(array[cursor2], tmp[cursor1]) < 0) { + array[dest++] = array[cursor2++]; + count2++; + count1 = 0; + if (--length2 === 0) { + exit = true; + break; + } + } + else { + array[dest++] = tmp[cursor1++]; + count1++; + count2 = 0; + if (--length1 === 1) { + exit = true; + break; + } + } + } while ((count1 | count2) < _minGallop); + if (exit) { + break; + } + do { + count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare); + if (count1 !== 0) { + for (i = 0; i < count1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + dest += count1; + cursor1 += count1; + length1 -= count1; + if (length1 <= 1) { + exit = true; + break; + } + } + array[dest++] = array[cursor2++]; + if (--length2 === 0) { + exit = true; + break; + } + count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare); + if (count2 !== 0) { + for (i = 0; i < count2; i++) { + array[dest + i] = array[cursor2 + i]; + } + dest += count2; + cursor2 += count2; + length2 -= count2; + if (length2 === 0) { + exit = true; + break; + } + } + array[dest++] = tmp[cursor1++]; + if (--length1 === 1) { + exit = true; + break; + } + _minGallop--; + } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); + if (exit) { + break; + } + if (_minGallop < 0) { + _minGallop = 0; + } + _minGallop += 2; + } + minGallop = _minGallop; + minGallop < 1 && (minGallop = 1); + if (length1 === 1) { + for (i = 0; i < length2; i++) { + array[dest + i] = array[cursor2 + i]; + } + array[dest + length2] = tmp[cursor1]; + } + else if (length1 === 0) { + throw new Error(); + } + else { + for (i = 0; i < length1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + } + } + function mergeHigh(start1, length1, start2, length2) { + var i = 0; + for (i = 0; i < length2; i++) { + tmp[i] = array[start2 + i]; + } + var cursor1 = start1 + length1 - 1; + var cursor2 = length2 - 1; + var dest = start2 + length2 - 1; + var customCursor = 0; + var customDest = 0; + array[dest--] = array[cursor1--]; + if (--length1 === 0) { + customCursor = dest - (length2 - 1); + for (i = 0; i < length2; i++) { + array[customCursor + i] = tmp[i]; + } + return; + } + if (length2 === 1) { + dest -= length1; + cursor1 -= length1; + customDest = dest + 1; + customCursor = cursor1 + 1; + for (i = length1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + array[dest] = tmp[cursor2]; + return; + } + var _minGallop = minGallop; + while (true) { + var count1 = 0; + var count2 = 0; + var exit = false; + do { + if (compare(tmp[cursor2], array[cursor1]) < 0) { + array[dest--] = array[cursor1--]; + count1++; + count2 = 0; + if (--length1 === 0) { + exit = true; + break; + } + } + else { + array[dest--] = tmp[cursor2--]; + count2++; + count1 = 0; + if (--length2 === 1) { + exit = true; + break; + } + } + } while ((count1 | count2) < _minGallop); + if (exit) { + break; + } + do { + count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare); + if (count1 !== 0) { + dest -= count1; + cursor1 -= count1; + length1 -= count1; + customDest = dest + 1; + customCursor = cursor1 + 1; + for (i = count1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + if (length1 === 0) { + exit = true; + break; + } + } + array[dest--] = tmp[cursor2--]; + if (--length2 === 1) { + exit = true; + break; + } + count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare); + if (count2 !== 0) { + dest -= count2; + cursor2 -= count2; + length2 -= count2; + customDest = dest + 1; + customCursor = cursor2 + 1; + for (i = 0; i < count2; i++) { + array[customDest + i] = tmp[customCursor + i]; + } + if (length2 <= 1) { + exit = true; + break; + } + } + array[dest--] = array[cursor1--]; + if (--length1 === 0) { + exit = true; + break; + } + _minGallop--; + } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); + if (exit) { + break; + } + if (_minGallop < 0) { + _minGallop = 0; + } + _minGallop += 2; + } + minGallop = _minGallop; + if (minGallop < 1) { + minGallop = 1; + } + if (length2 === 1) { + dest -= length1; + cursor1 -= length1; + customDest = dest + 1; + customCursor = cursor1 + 1; + for (i = length1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + array[dest] = tmp[cursor2]; + } + else if (length2 === 0) { + throw new Error(); + } + else { + customCursor = dest - (length2 - 1); + for (i = 0; i < length2; i++) { + array[customCursor + i] = tmp[i]; + } + } + } + return { + mergeRuns: mergeRuns, + forceMergeRuns: forceMergeRuns, + pushRun: pushRun + }; + } + function sort(array, compare, lo, hi) { + if (!lo) { + lo = 0; + } + if (!hi) { + hi = array.length; + } + var remaining = hi - lo; + if (remaining < 2) { + return; + } + var runLength = 0; + if (remaining < DEFAULT_MIN_MERGE) { + runLength = makeAscendingRun(array, lo, hi, compare); + binaryInsertionSort(array, lo, hi, lo + runLength, compare); + return; + } + var ts = TimSort(array, compare); + var minRun = minRunLength(remaining); + do { + runLength = makeAscendingRun(array, lo, hi, compare); + if (runLength < minRun) { + var force = remaining; + if (force > minRun) { + force = minRun; + } + binaryInsertionSort(array, lo, lo + force, lo + runLength, compare); + runLength = force; + } + ts.pushRun(lo, runLength); + ts.mergeRuns(); + remaining -= runLength; + lo += runLength; + } while (remaining !== 0); + ts.forceMergeRuns(); + } + + var REDRAW_BIT = 1; + var STYLE_CHANGED_BIT = 2; + var SHAPE_CHANGED_BIT = 4; + + var invalidZErrorLogged = false; + function logInvalidZError() { + if (invalidZErrorLogged) { + return; + } + invalidZErrorLogged = true; + console.warn('z / z2 / zlevel of displayable is invalid, which may cause unexpected errors'); + } + function shapeCompareFunc(a, b) { + if (a.zlevel === b.zlevel) { + if (a.z === b.z) { + return a.z2 - b.z2; + } + return a.z - b.z; + } + return a.zlevel - b.zlevel; + } + var Storage = (function () { + function Storage() { + this._roots = []; + this._displayList = []; + this._displayListLen = 0; + this.displayableSortFunc = shapeCompareFunc; + } + Storage.prototype.traverse = function (cb, context) { + for (var i = 0; i < this._roots.length; i++) { + this._roots[i].traverse(cb, context); + } + }; + Storage.prototype.getDisplayList = function (update, includeIgnore) { + includeIgnore = includeIgnore || false; + var displayList = this._displayList; + if (update || !displayList.length) { + this.updateDisplayList(includeIgnore); + } + return displayList; + }; + Storage.prototype.updateDisplayList = function (includeIgnore) { + this._displayListLen = 0; + var roots = this._roots; + var displayList = this._displayList; + for (var i = 0, len = roots.length; i < len; i++) { + this._updateAndAddDisplayable(roots[i], null, includeIgnore); + } + displayList.length = this._displayListLen; + sort(displayList, shapeCompareFunc); + }; + Storage.prototype._updateAndAddDisplayable = function (el, clipPaths, includeIgnore) { + if (el.ignore && !includeIgnore) { + return; + } + el.beforeUpdate(); + el.update(); + el.afterUpdate(); + var userSetClipPath = el.getClipPath(); + if (el.ignoreClip) { + clipPaths = null; + } + else if (userSetClipPath) { + if (clipPaths) { + clipPaths = clipPaths.slice(); + } + else { + clipPaths = []; + } + var currentClipPath = userSetClipPath; + var parentClipPath = el; + while (currentClipPath) { + currentClipPath.parent = parentClipPath; + currentClipPath.updateTransform(); + clipPaths.push(currentClipPath); + parentClipPath = currentClipPath; + currentClipPath = currentClipPath.getClipPath(); + } + } + if (el.childrenRef) { + var children = el.childrenRef(); + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (el.__dirty) { + child.__dirty |= REDRAW_BIT; + } + this._updateAndAddDisplayable(child, clipPaths, includeIgnore); + } + el.__dirty = 0; + } + else { + var disp = el; + if (clipPaths && clipPaths.length) { + disp.__clipPaths = clipPaths; + } + else if (disp.__clipPaths && disp.__clipPaths.length > 0) { + disp.__clipPaths = []; + } + if (isNaN(disp.z)) { + logInvalidZError(); + disp.z = 0; + } + if (isNaN(disp.z2)) { + logInvalidZError(); + disp.z2 = 0; + } + if (isNaN(disp.zlevel)) { + logInvalidZError(); + disp.zlevel = 0; + } + this._displayList[this._displayListLen++] = disp; + } + var decalEl = el.getDecalElement && el.getDecalElement(); + if (decalEl) { + this._updateAndAddDisplayable(decalEl, clipPaths, includeIgnore); + } + var textGuide = el.getTextGuideLine(); + if (textGuide) { + this._updateAndAddDisplayable(textGuide, clipPaths, includeIgnore); + } + var textEl = el.getTextContent(); + if (textEl) { + this._updateAndAddDisplayable(textEl, clipPaths, includeIgnore); + } + }; + Storage.prototype.addRoot = function (el) { + if (el.__zr && el.__zr.storage === this) { + return; + } + this._roots.push(el); + }; + Storage.prototype.delRoot = function (el) { + if (el instanceof Array) { + for (var i = 0, l = el.length; i < l; i++) { + this.delRoot(el[i]); + } + return; + } + var idx = indexOf(this._roots, el); + if (idx >= 0) { + this._roots.splice(idx, 1); + } + }; + Storage.prototype.delAllRoots = function () { + this._roots = []; + this._displayList = []; + this._displayListLen = 0; + return; + }; + Storage.prototype.getRoots = function () { + return this._roots; + }; + Storage.prototype.dispose = function () { + this._displayList = null; + this._roots = null; + }; + return Storage; + }()); + + var requestAnimationFrame; + requestAnimationFrame = (env.hasGlobalWindow + && ((window.requestAnimationFrame && window.requestAnimationFrame.bind(window)) + || (window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window)) + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame)) || function (func) { + return setTimeout(func, 16); + }; + var requestAnimationFrame$1 = requestAnimationFrame; + + var easingFuncs = { + linear: function (k) { + return k; + }, + quadraticIn: function (k) { + return k * k; + }, + quadraticOut: function (k) { + return k * (2 - k); + }, + quadraticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k; + } + return -0.5 * (--k * (k - 2) - 1); + }, + cubicIn: function (k) { + return k * k * k; + }, + cubicOut: function (k) { + return --k * k * k + 1; + }, + cubicInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k; + } + return 0.5 * ((k -= 2) * k * k + 2); + }, + quarticIn: function (k) { + return k * k * k * k; + }, + quarticOut: function (k) { + return 1 - (--k * k * k * k); + }, + quarticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k * k; + } + return -0.5 * ((k -= 2) * k * k * k - 2); + }, + quinticIn: function (k) { + return k * k * k * k * k; + }, + quinticOut: function (k) { + return --k * k * k * k * k + 1; + }, + quinticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k * k * k; + } + return 0.5 * ((k -= 2) * k * k * k * k + 2); + }, + sinusoidalIn: function (k) { + return 1 - Math.cos(k * Math.PI / 2); + }, + sinusoidalOut: function (k) { + return Math.sin(k * Math.PI / 2); + }, + sinusoidalInOut: function (k) { + return 0.5 * (1 - Math.cos(Math.PI * k)); + }, + exponentialIn: function (k) { + return k === 0 ? 0 : Math.pow(1024, k - 1); + }, + exponentialOut: function (k) { + return k === 1 ? 1 : 1 - Math.pow(2, -10 * k); + }, + exponentialInOut: function (k) { + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if ((k *= 2) < 1) { + return 0.5 * Math.pow(1024, k - 1); + } + return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2); + }, + circularIn: function (k) { + return 1 - Math.sqrt(1 - k * k); + }, + circularOut: function (k) { + return Math.sqrt(1 - (--k * k)); + }, + circularInOut: function (k) { + if ((k *= 2) < 1) { + return -0.5 * (Math.sqrt(1 - k * k) - 1); + } + return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1); + }, + elasticIn: function (k) { + var s; + var a = 0.1; + var p = 0.4; + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if (!a || a < 1) { + a = 1; + s = p / 4; + } + else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + return -(a * Math.pow(2, 10 * (k -= 1)) + * Math.sin((k - s) * (2 * Math.PI) / p)); + }, + elasticOut: function (k) { + var s; + var a = 0.1; + var p = 0.4; + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if (!a || a < 1) { + a = 1; + s = p / 4; + } + else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + return (a * Math.pow(2, -10 * k) + * Math.sin((k - s) * (2 * Math.PI) / p) + 1); + }, + elasticInOut: function (k) { + var s; + var a = 0.1; + var p = 0.4; + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if (!a || a < 1) { + a = 1; + s = p / 4; + } + else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + if ((k *= 2) < 1) { + return -0.5 * (a * Math.pow(2, 10 * (k -= 1)) + * Math.sin((k - s) * (2 * Math.PI) / p)); + } + return a * Math.pow(2, -10 * (k -= 1)) + * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1; + }, + backIn: function (k) { + var s = 1.70158; + return k * k * ((s + 1) * k - s); + }, + backOut: function (k) { + var s = 1.70158; + return --k * k * ((s + 1) * k + s) + 1; + }, + backInOut: function (k) { + var s = 1.70158 * 1.525; + if ((k *= 2) < 1) { + return 0.5 * (k * k * ((s + 1) * k - s)); + } + return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2); + }, + bounceIn: function (k) { + return 1 - easingFuncs.bounceOut(1 - k); + }, + bounceOut: function (k) { + if (k < (1 / 2.75)) { + return 7.5625 * k * k; + } + else if (k < (2 / 2.75)) { + return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75; + } + else if (k < (2.5 / 2.75)) { + return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375; + } + else { + return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375; + } + }, + bounceInOut: function (k) { + if (k < 0.5) { + return easingFuncs.bounceIn(k * 2) * 0.5; + } + return easingFuncs.bounceOut(k * 2 - 1) * 0.5 + 0.5; + } + }; + + var mathPow = Math.pow; + var mathSqrt = Math.sqrt; + var EPSILON = 1e-8; + var EPSILON_NUMERIC = 1e-4; + var THREE_SQRT = mathSqrt(3); + var ONE_THIRD = 1 / 3; + var _v0 = create(); + var _v1 = create(); + var _v2 = create(); + function isAroundZero(val) { + return val > -EPSILON && val < EPSILON; + } + function isNotAroundZero(val) { + return val > EPSILON || val < -EPSILON; + } + function cubicAt(p0, p1, p2, p3, t) { + var onet = 1 - t; + return onet * onet * (onet * p0 + 3 * t * p1) + + t * t * (t * p3 + 3 * onet * p2); + } + function cubicDerivativeAt(p0, p1, p2, p3, t) { + var onet = 1 - t; + return 3 * (((p1 - p0) * onet + 2 * (p2 - p1) * t) * onet + + (p3 - p2) * t * t); + } + function cubicRootAt(p0, p1, p2, p3, val, roots) { + var a = p3 + 3 * (p1 - p2) - p0; + var b = 3 * (p2 - p1 * 2 + p0); + var c = 3 * (p1 - p0); + var d = p0 - val; + var A = b * b - 3 * a * c; + var B = b * c - 9 * a * d; + var C = c * c - 3 * b * d; + var n = 0; + if (isAroundZero(A) && isAroundZero(B)) { + if (isAroundZero(b)) { + roots[0] = 0; + } + else { + var t1 = -c / b; + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + } + else { + var disc = B * B - 4 * A * C; + if (isAroundZero(disc)) { + var K = B / A; + var t1 = -b / a + K; + var t2 = -K / 2; + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + roots[n++] = t2; + } + } + else if (disc > 0) { + var discSqrt = mathSqrt(disc); + var Y1 = A * b + 1.5 * a * (-B + discSqrt); + var Y2 = A * b + 1.5 * a * (-B - discSqrt); + if (Y1 < 0) { + Y1 = -mathPow(-Y1, ONE_THIRD); + } + else { + Y1 = mathPow(Y1, ONE_THIRD); + } + if (Y2 < 0) { + Y2 = -mathPow(-Y2, ONE_THIRD); + } + else { + Y2 = mathPow(Y2, ONE_THIRD); + } + var t1 = (-b - (Y1 + Y2)) / (3 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + else { + var T = (2 * A * b - 3 * a * B) / (2 * mathSqrt(A * A * A)); + var theta = Math.acos(T) / 3; + var ASqrt = mathSqrt(A); + var tmp = Math.cos(theta); + var t1 = (-b - 2 * ASqrt * tmp) / (3 * a); + var t2 = (-b + ASqrt * (tmp + THREE_SQRT * Math.sin(theta))) / (3 * a); + var t3 = (-b + ASqrt * (tmp - THREE_SQRT * Math.sin(theta))) / (3 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + roots[n++] = t2; + } + if (t3 >= 0 && t3 <= 1) { + roots[n++] = t3; + } + } + } + return n; + } + function cubicExtrema(p0, p1, p2, p3, extrema) { + var b = 6 * p2 - 12 * p1 + 6 * p0; + var a = 9 * p1 + 3 * p3 - 3 * p0 - 9 * p2; + var c = 3 * p1 - 3 * p0; + var n = 0; + if (isAroundZero(a)) { + if (isNotAroundZero(b)) { + var t1 = -c / b; + if (t1 >= 0 && t1 <= 1) { + extrema[n++] = t1; + } + } + } + else { + var disc = b * b - 4 * a * c; + if (isAroundZero(disc)) { + extrema[0] = -b / (2 * a); + } + else if (disc > 0) { + var discSqrt = mathSqrt(disc); + var t1 = (-b + discSqrt) / (2 * a); + var t2 = (-b - discSqrt) / (2 * a); + if (t1 >= 0 && t1 <= 1) { + extrema[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + extrema[n++] = t2; + } + } + } + return n; + } + function cubicSubdivide(p0, p1, p2, p3, t, out) { + var p01 = (p1 - p0) * t + p0; + var p12 = (p2 - p1) * t + p1; + var p23 = (p3 - p2) * t + p2; + var p012 = (p12 - p01) * t + p01; + var p123 = (p23 - p12) * t + p12; + var p0123 = (p123 - p012) * t + p012; + out[0] = p0; + out[1] = p01; + out[2] = p012; + out[3] = p0123; + out[4] = p0123; + out[5] = p123; + out[6] = p23; + out[7] = p3; + } + function cubicProjectPoint(x0, y0, x1, y1, x2, y2, x3, y3, x, y, out) { + var t; + var interval = 0.005; + var d = Infinity; + var prev; + var next; + var d1; + var d2; + _v0[0] = x; + _v0[1] = y; + for (var _t = 0; _t < 1; _t += 0.05) { + _v1[0] = cubicAt(x0, x1, x2, x3, _t); + _v1[1] = cubicAt(y0, y1, y2, y3, _t); + d1 = distSquare(_v0, _v1); + if (d1 < d) { + t = _t; + d = d1; + } + } + d = Infinity; + for (var i = 0; i < 32; i++) { + if (interval < EPSILON_NUMERIC) { + break; + } + prev = t - interval; + next = t + interval; + _v1[0] = cubicAt(x0, x1, x2, x3, prev); + _v1[1] = cubicAt(y0, y1, y2, y3, prev); + d1 = distSquare(_v1, _v0); + if (prev >= 0 && d1 < d) { + t = prev; + d = d1; + } + else { + _v2[0] = cubicAt(x0, x1, x2, x3, next); + _v2[1] = cubicAt(y0, y1, y2, y3, next); + d2 = distSquare(_v2, _v0); + if (next <= 1 && d2 < d) { + t = next; + d = d2; + } + else { + interval *= 0.5; + } + } + } + if (out) { + out[0] = cubicAt(x0, x1, x2, x3, t); + out[1] = cubicAt(y0, y1, y2, y3, t); + } + return mathSqrt(d); + } + function cubicLength(x0, y0, x1, y1, x2, y2, x3, y3, iteration) { + var px = x0; + var py = y0; + var d = 0; + var step = 1 / iteration; + for (var i = 1; i <= iteration; i++) { + var t = i * step; + var x = cubicAt(x0, x1, x2, x3, t); + var y = cubicAt(y0, y1, y2, y3, t); + var dx = x - px; + var dy = y - py; + d += Math.sqrt(dx * dx + dy * dy); + px = x; + py = y; + } + return d; + } + function quadraticAt(p0, p1, p2, t) { + var onet = 1 - t; + return onet * (onet * p0 + 2 * t * p1) + t * t * p2; + } + function quadraticDerivativeAt(p0, p1, p2, t) { + return 2 * ((1 - t) * (p1 - p0) + t * (p2 - p1)); + } + function quadraticRootAt(p0, p1, p2, val, roots) { + var a = p0 - 2 * p1 + p2; + var b = 2 * (p1 - p0); + var c = p0 - val; + var n = 0; + if (isAroundZero(a)) { + if (isNotAroundZero(b)) { + var t1 = -c / b; + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + } + else { + var disc = b * b - 4 * a * c; + if (isAroundZero(disc)) { + var t1 = -b / (2 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + else if (disc > 0) { + var discSqrt = mathSqrt(disc); + var t1 = (-b + discSqrt) / (2 * a); + var t2 = (-b - discSqrt) / (2 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + roots[n++] = t2; + } + } + } + return n; + } + function quadraticExtremum(p0, p1, p2) { + var divider = p0 + p2 - 2 * p1; + if (divider === 0) { + return 0.5; + } + else { + return (p0 - p1) / divider; + } + } + function quadraticSubdivide(p0, p1, p2, t, out) { + var p01 = (p1 - p0) * t + p0; + var p12 = (p2 - p1) * t + p1; + var p012 = (p12 - p01) * t + p01; + out[0] = p0; + out[1] = p01; + out[2] = p012; + out[3] = p012; + out[4] = p12; + out[5] = p2; + } + function quadraticProjectPoint(x0, y0, x1, y1, x2, y2, x, y, out) { + var t; + var interval = 0.005; + var d = Infinity; + _v0[0] = x; + _v0[1] = y; + for (var _t = 0; _t < 1; _t += 0.05) { + _v1[0] = quadraticAt(x0, x1, x2, _t); + _v1[1] = quadraticAt(y0, y1, y2, _t); + var d1 = distSquare(_v0, _v1); + if (d1 < d) { + t = _t; + d = d1; + } + } + d = Infinity; + for (var i = 0; i < 32; i++) { + if (interval < EPSILON_NUMERIC) { + break; + } + var prev = t - interval; + var next = t + interval; + _v1[0] = quadraticAt(x0, x1, x2, prev); + _v1[1] = quadraticAt(y0, y1, y2, prev); + var d1 = distSquare(_v1, _v0); + if (prev >= 0 && d1 < d) { + t = prev; + d = d1; + } + else { + _v2[0] = quadraticAt(x0, x1, x2, next); + _v2[1] = quadraticAt(y0, y1, y2, next); + var d2 = distSquare(_v2, _v0); + if (next <= 1 && d2 < d) { + t = next; + d = d2; + } + else { + interval *= 0.5; + } + } + } + if (out) { + out[0] = quadraticAt(x0, x1, x2, t); + out[1] = quadraticAt(y0, y1, y2, t); + } + return mathSqrt(d); + } + function quadraticLength(x0, y0, x1, y1, x2, y2, iteration) { + var px = x0; + var py = y0; + var d = 0; + var step = 1 / iteration; + for (var i = 1; i <= iteration; i++) { + var t = i * step; + var x = quadraticAt(x0, x1, x2, t); + var y = quadraticAt(y0, y1, y2, t); + var dx = x - px; + var dy = y - py; + d += Math.sqrt(dx * dx + dy * dy); + px = x; + py = y; + } + return d; + } + + var regexp = /cubic-bezier\(([0-9,\.e ]+)\)/; + function createCubicEasingFunc(cubicEasingStr) { + var cubic = cubicEasingStr && regexp.exec(cubicEasingStr); + if (cubic) { + var points = cubic[1].split(','); + var a_1 = +trim(points[0]); + var b_1 = +trim(points[1]); + var c_1 = +trim(points[2]); + var d_1 = +trim(points[3]); + if (isNaN(a_1 + b_1 + c_1 + d_1)) { + return; + } + var roots_1 = []; + return function (p) { + return p <= 0 + ? 0 : p >= 1 + ? 1 + : cubicRootAt(0, a_1, c_1, 1, p, roots_1) && cubicAt(0, b_1, d_1, 1, roots_1[0]); + }; + } + } + + var Clip = (function () { + function Clip(opts) { + this._inited = false; + this._startTime = 0; + this._pausedTime = 0; + this._paused = false; + this._life = opts.life || 1000; + this._delay = opts.delay || 0; + this.loop = opts.loop || false; + this.onframe = opts.onframe || noop; + this.ondestroy = opts.ondestroy || noop; + this.onrestart = opts.onrestart || noop; + opts.easing && this.setEasing(opts.easing); + } + Clip.prototype.step = function (globalTime, deltaTime) { + if (!this._inited) { + this._startTime = globalTime + this._delay; + this._inited = true; + } + if (this._paused) { + this._pausedTime += deltaTime; + return; + } + var life = this._life; + var elapsedTime = globalTime - this._startTime - this._pausedTime; + var percent = elapsedTime / life; + if (percent < 0) { + percent = 0; + } + percent = Math.min(percent, 1); + var easingFunc = this.easingFunc; + var schedule = easingFunc ? easingFunc(percent) : percent; + this.onframe(schedule); + if (percent === 1) { + if (this.loop) { + var remainder = elapsedTime % life; + this._startTime = globalTime - remainder; + this._pausedTime = 0; + this.onrestart(); + } + else { + return true; + } + } + return false; + }; + Clip.prototype.pause = function () { + this._paused = true; + }; + Clip.prototype.resume = function () { + this._paused = false; + }; + Clip.prototype.setEasing = function (easing) { + this.easing = easing; + this.easingFunc = isFunction(easing) + ? easing + : easingFuncs[easing] || createCubicEasingFunc(easing); + }; + return Clip; + }()); + + var Entry = (function () { + function Entry(val) { + this.value = val; + } + return Entry; + }()); + var LinkedList = (function () { + function LinkedList() { + this._len = 0; + } + LinkedList.prototype.insert = function (val) { + var entry = new Entry(val); + this.insertEntry(entry); + return entry; + }; + LinkedList.prototype.insertEntry = function (entry) { + if (!this.head) { + this.head = this.tail = entry; + } + else { + this.tail.next = entry; + entry.prev = this.tail; + entry.next = null; + this.tail = entry; + } + this._len++; + }; + LinkedList.prototype.remove = function (entry) { + var prev = entry.prev; + var next = entry.next; + if (prev) { + prev.next = next; + } + else { + this.head = next; + } + if (next) { + next.prev = prev; + } + else { + this.tail = prev; + } + entry.next = entry.prev = null; + this._len--; + }; + LinkedList.prototype.len = function () { + return this._len; + }; + LinkedList.prototype.clear = function () { + this.head = this.tail = null; + this._len = 0; + }; + return LinkedList; + }()); + var LRU = (function () { + function LRU(maxSize) { + this._list = new LinkedList(); + this._maxSize = 10; + this._map = {}; + this._maxSize = maxSize; + } + LRU.prototype.put = function (key, value) { + var list = this._list; + var map = this._map; + var removed = null; + if (map[key] == null) { + var len = list.len(); + var entry = this._lastRemovedEntry; + if (len >= this._maxSize && len > 0) { + var leastUsedEntry = list.head; + list.remove(leastUsedEntry); + delete map[leastUsedEntry.key]; + removed = leastUsedEntry.value; + this._lastRemovedEntry = leastUsedEntry; + } + if (entry) { + entry.value = value; + } + else { + entry = new Entry(value); + } + entry.key = key; + list.insertEntry(entry); + map[key] = entry; + } + return removed; + }; + LRU.prototype.get = function (key) { + var entry = this._map[key]; + var list = this._list; + if (entry != null) { + if (entry !== list.tail) { + list.remove(entry); + list.insertEntry(entry); + } + return entry.value; + } + }; + LRU.prototype.clear = function () { + this._list.clear(); + this._map = {}; + }; + LRU.prototype.len = function () { + return this._list.len(); + }; + return LRU; + }()); + + var kCSSColorTable = { + 'transparent': [0, 0, 0, 0], 'aliceblue': [240, 248, 255, 1], + 'antiquewhite': [250, 235, 215, 1], 'aqua': [0, 255, 255, 1], + 'aquamarine': [127, 255, 212, 1], 'azure': [240, 255, 255, 1], + 'beige': [245, 245, 220, 1], 'bisque': [255, 228, 196, 1], + 'black': [0, 0, 0, 1], 'blanchedalmond': [255, 235, 205, 1], + 'blue': [0, 0, 255, 1], 'blueviolet': [138, 43, 226, 1], + 'brown': [165, 42, 42, 1], 'burlywood': [222, 184, 135, 1], + 'cadetblue': [95, 158, 160, 1], 'chartreuse': [127, 255, 0, 1], + 'chocolate': [210, 105, 30, 1], 'coral': [255, 127, 80, 1], + 'cornflowerblue': [100, 149, 237, 1], 'cornsilk': [255, 248, 220, 1], + 'crimson': [220, 20, 60, 1], 'cyan': [0, 255, 255, 1], + 'darkblue': [0, 0, 139, 1], 'darkcyan': [0, 139, 139, 1], + 'darkgoldenrod': [184, 134, 11, 1], 'darkgray': [169, 169, 169, 1], + 'darkgreen': [0, 100, 0, 1], 'darkgrey': [169, 169, 169, 1], + 'darkkhaki': [189, 183, 107, 1], 'darkmagenta': [139, 0, 139, 1], + 'darkolivegreen': [85, 107, 47, 1], 'darkorange': [255, 140, 0, 1], + 'darkorchid': [153, 50, 204, 1], 'darkred': [139, 0, 0, 1], + 'darksalmon': [233, 150, 122, 1], 'darkseagreen': [143, 188, 143, 1], + 'darkslateblue': [72, 61, 139, 1], 'darkslategray': [47, 79, 79, 1], + 'darkslategrey': [47, 79, 79, 1], 'darkturquoise': [0, 206, 209, 1], + 'darkviolet': [148, 0, 211, 1], 'deeppink': [255, 20, 147, 1], + 'deepskyblue': [0, 191, 255, 1], 'dimgray': [105, 105, 105, 1], + 'dimgrey': [105, 105, 105, 1], 'dodgerblue': [30, 144, 255, 1], + 'firebrick': [178, 34, 34, 1], 'floralwhite': [255, 250, 240, 1], + 'forestgreen': [34, 139, 34, 1], 'fuchsia': [255, 0, 255, 1], + 'gainsboro': [220, 220, 220, 1], 'ghostwhite': [248, 248, 255, 1], + 'gold': [255, 215, 0, 1], 'goldenrod': [218, 165, 32, 1], + 'gray': [128, 128, 128, 1], 'green': [0, 128, 0, 1], + 'greenyellow': [173, 255, 47, 1], 'grey': [128, 128, 128, 1], + 'honeydew': [240, 255, 240, 1], 'hotpink': [255, 105, 180, 1], + 'indianred': [205, 92, 92, 1], 'indigo': [75, 0, 130, 1], + 'ivory': [255, 255, 240, 1], 'khaki': [240, 230, 140, 1], + 'lavender': [230, 230, 250, 1], 'lavenderblush': [255, 240, 245, 1], + 'lawngreen': [124, 252, 0, 1], 'lemonchiffon': [255, 250, 205, 1], + 'lightblue': [173, 216, 230, 1], 'lightcoral': [240, 128, 128, 1], + 'lightcyan': [224, 255, 255, 1], 'lightgoldenrodyellow': [250, 250, 210, 1], + 'lightgray': [211, 211, 211, 1], 'lightgreen': [144, 238, 144, 1], + 'lightgrey': [211, 211, 211, 1], 'lightpink': [255, 182, 193, 1], + 'lightsalmon': [255, 160, 122, 1], 'lightseagreen': [32, 178, 170, 1], + 'lightskyblue': [135, 206, 250, 1], 'lightslategray': [119, 136, 153, 1], + 'lightslategrey': [119, 136, 153, 1], 'lightsteelblue': [176, 196, 222, 1], + 'lightyellow': [255, 255, 224, 1], 'lime': [0, 255, 0, 1], + 'limegreen': [50, 205, 50, 1], 'linen': [250, 240, 230, 1], + 'magenta': [255, 0, 255, 1], 'maroon': [128, 0, 0, 1], + 'mediumaquamarine': [102, 205, 170, 1], 'mediumblue': [0, 0, 205, 1], + 'mediumorchid': [186, 85, 211, 1], 'mediumpurple': [147, 112, 219, 1], + 'mediumseagreen': [60, 179, 113, 1], 'mediumslateblue': [123, 104, 238, 1], + 'mediumspringgreen': [0, 250, 154, 1], 'mediumturquoise': [72, 209, 204, 1], + 'mediumvioletred': [199, 21, 133, 1], 'midnightblue': [25, 25, 112, 1], + 'mintcream': [245, 255, 250, 1], 'mistyrose': [255, 228, 225, 1], + 'moccasin': [255, 228, 181, 1], 'navajowhite': [255, 222, 173, 1], + 'navy': [0, 0, 128, 1], 'oldlace': [253, 245, 230, 1], + 'olive': [128, 128, 0, 1], 'olivedrab': [107, 142, 35, 1], + 'orange': [255, 165, 0, 1], 'orangered': [255, 69, 0, 1], + 'orchid': [218, 112, 214, 1], 'palegoldenrod': [238, 232, 170, 1], + 'palegreen': [152, 251, 152, 1], 'paleturquoise': [175, 238, 238, 1], + 'palevioletred': [219, 112, 147, 1], 'papayawhip': [255, 239, 213, 1], + 'peachpuff': [255, 218, 185, 1], 'peru': [205, 133, 63, 1], + 'pink': [255, 192, 203, 1], 'plum': [221, 160, 221, 1], + 'powderblue': [176, 224, 230, 1], 'purple': [128, 0, 128, 1], + 'red': [255, 0, 0, 1], 'rosybrown': [188, 143, 143, 1], + 'royalblue': [65, 105, 225, 1], 'saddlebrown': [139, 69, 19, 1], + 'salmon': [250, 128, 114, 1], 'sandybrown': [244, 164, 96, 1], + 'seagreen': [46, 139, 87, 1], 'seashell': [255, 245, 238, 1], + 'sienna': [160, 82, 45, 1], 'silver': [192, 192, 192, 1], + 'skyblue': [135, 206, 235, 1], 'slateblue': [106, 90, 205, 1], + 'slategray': [112, 128, 144, 1], 'slategrey': [112, 128, 144, 1], + 'snow': [255, 250, 250, 1], 'springgreen': [0, 255, 127, 1], + 'steelblue': [70, 130, 180, 1], 'tan': [210, 180, 140, 1], + 'teal': [0, 128, 128, 1], 'thistle': [216, 191, 216, 1], + 'tomato': [255, 99, 71, 1], 'turquoise': [64, 224, 208, 1], + 'violet': [238, 130, 238, 1], 'wheat': [245, 222, 179, 1], + 'white': [255, 255, 255, 1], 'whitesmoke': [245, 245, 245, 1], + 'yellow': [255, 255, 0, 1], 'yellowgreen': [154, 205, 50, 1] + }; + function clampCssByte(i) { + i = Math.round(i); + return i < 0 ? 0 : i > 255 ? 255 : i; + } + function clampCssAngle(i) { + i = Math.round(i); + return i < 0 ? 0 : i > 360 ? 360 : i; + } + function clampCssFloat(f) { + return f < 0 ? 0 : f > 1 ? 1 : f; + } + function parseCssInt(val) { + var str = val; + if (str.length && str.charAt(str.length - 1) === '%') { + return clampCssByte(parseFloat(str) / 100 * 255); + } + return clampCssByte(parseInt(str, 10)); + } + function parseCssFloat(val) { + var str = val; + if (str.length && str.charAt(str.length - 1) === '%') { + return clampCssFloat(parseFloat(str) / 100); + } + return clampCssFloat(parseFloat(str)); + } + function cssHueToRgb(m1, m2, h) { + if (h < 0) { + h += 1; + } + else if (h > 1) { + h -= 1; + } + if (h * 6 < 1) { + return m1 + (m2 - m1) * h * 6; + } + if (h * 2 < 1) { + return m2; + } + if (h * 3 < 2) { + return m1 + (m2 - m1) * (2 / 3 - h) * 6; + } + return m1; + } + function lerpNumber(a, b, p) { + return a + (b - a) * p; + } + function setRgba(out, r, g, b, a) { + out[0] = r; + out[1] = g; + out[2] = b; + out[3] = a; + return out; + } + function copyRgba(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; + } + var colorCache = new LRU(20); + var lastRemovedArr = null; + function putToCache(colorStr, rgbaArr) { + if (lastRemovedArr) { + copyRgba(lastRemovedArr, rgbaArr); + } + lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || (rgbaArr.slice())); + } + function parse(colorStr, rgbaArr) { + if (!colorStr) { + return; + } + rgbaArr = rgbaArr || []; + var cached = colorCache.get(colorStr); + if (cached) { + return copyRgba(rgbaArr, cached); + } + colorStr = colorStr + ''; + var str = colorStr.replace(/ /g, '').toLowerCase(); + if (str in kCSSColorTable) { + copyRgba(rgbaArr, kCSSColorTable[str]); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + var strLen = str.length; + if (str.charAt(0) === '#') { + if (strLen === 4 || strLen === 5) { + var iv = parseInt(str.slice(1, 4), 16); + if (!(iv >= 0 && iv <= 0xfff)) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + setRgba(rgbaArr, ((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8), (iv & 0xf0) | ((iv & 0xf0) >> 4), (iv & 0xf) | ((iv & 0xf) << 4), strLen === 5 ? parseInt(str.slice(4), 16) / 0xf : 1); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + else if (strLen === 7 || strLen === 9) { + var iv = parseInt(str.slice(1, 7), 16); + if (!(iv >= 0 && iv <= 0xffffff)) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + setRgba(rgbaArr, (iv & 0xff0000) >> 16, (iv & 0xff00) >> 8, iv & 0xff, strLen === 9 ? parseInt(str.slice(7), 16) / 0xff : 1); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + return; + } + var op = str.indexOf('('); + var ep = str.indexOf(')'); + if (op !== -1 && ep + 1 === strLen) { + var fname = str.substr(0, op); + var params = str.substr(op + 1, ep - (op + 1)).split(','); + var alpha = 1; + switch (fname) { + case 'rgba': + if (params.length !== 4) { + return params.length === 3 + ? setRgba(rgbaArr, +params[0], +params[1], +params[2], 1) + : setRgba(rgbaArr, 0, 0, 0, 1); + } + alpha = parseCssFloat(params.pop()); + case 'rgb': + if (params.length !== 3) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + setRgba(rgbaArr, parseCssInt(params[0]), parseCssInt(params[1]), parseCssInt(params[2]), alpha); + putToCache(colorStr, rgbaArr); + return rgbaArr; + case 'hsla': + if (params.length !== 4) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + params[3] = parseCssFloat(params[3]); + hsla2rgba(params, rgbaArr); + putToCache(colorStr, rgbaArr); + return rgbaArr; + case 'hsl': + if (params.length !== 3) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + hsla2rgba(params, rgbaArr); + putToCache(colorStr, rgbaArr); + return rgbaArr; + default: + return; + } + } + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + function hsla2rgba(hsla, rgba) { + var h = (((parseFloat(hsla[0]) % 360) + 360) % 360) / 360; + var s = parseCssFloat(hsla[1]); + var l = parseCssFloat(hsla[2]); + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + rgba = rgba || []; + setRgba(rgba, clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255), clampCssByte(cssHueToRgb(m1, m2, h) * 255), clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255), 1); + if (hsla.length === 4) { + rgba[3] = hsla[3]; + } + return rgba; + } + function rgba2hsla(rgba) { + if (!rgba) { + return; + } + var R = rgba[0] / 255; + var G = rgba[1] / 255; + var B = rgba[2] / 255; + var vMin = Math.min(R, G, B); + var vMax = Math.max(R, G, B); + var delta = vMax - vMin; + var L = (vMax + vMin) / 2; + var H; + var S; + if (delta === 0) { + H = 0; + S = 0; + } + else { + if (L < 0.5) { + S = delta / (vMax + vMin); + } + else { + S = delta / (2 - vMax - vMin); + } + var deltaR = (((vMax - R) / 6) + (delta / 2)) / delta; + var deltaG = (((vMax - G) / 6) + (delta / 2)) / delta; + var deltaB = (((vMax - B) / 6) + (delta / 2)) / delta; + if (R === vMax) { + H = deltaB - deltaG; + } + else if (G === vMax) { + H = (1 / 3) + deltaR - deltaB; + } + else if (B === vMax) { + H = (2 / 3) + deltaG - deltaR; + } + if (H < 0) { + H += 1; + } + if (H > 1) { + H -= 1; + } + } + var hsla = [H * 360, S, L]; + if (rgba[3] != null) { + hsla.push(rgba[3]); + } + return hsla; + } + function lift(color, level) { + var colorArr = parse(color); + if (colorArr) { + for (var i = 0; i < 3; i++) { + if (level < 0) { + colorArr[i] = colorArr[i] * (1 - level) | 0; + } + else { + colorArr[i] = ((255 - colorArr[i]) * level + colorArr[i]) | 0; + } + if (colorArr[i] > 255) { + colorArr[i] = 255; + } + else if (colorArr[i] < 0) { + colorArr[i] = 0; + } + } + return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb'); + } + } + function toHex(color) { + var colorArr = parse(color); + if (colorArr) { + return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + (+colorArr[2])).toString(16).slice(1); + } + } + function fastLerp(normalizedValue, colors, out) { + if (!(colors && colors.length) + || !(normalizedValue >= 0 && normalizedValue <= 1)) { + return; + } + out = out || []; + var value = normalizedValue * (colors.length - 1); + var leftIndex = Math.floor(value); + var rightIndex = Math.ceil(value); + var leftColor = colors[leftIndex]; + var rightColor = colors[rightIndex]; + var dv = value - leftIndex; + out[0] = clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)); + out[1] = clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)); + out[2] = clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)); + out[3] = clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv)); + return out; + } + var fastMapToColor = fastLerp; + function lerp$1(normalizedValue, colors, fullOutput) { + if (!(colors && colors.length) + || !(normalizedValue >= 0 && normalizedValue <= 1)) { + return; + } + var value = normalizedValue * (colors.length - 1); + var leftIndex = Math.floor(value); + var rightIndex = Math.ceil(value); + var leftColor = parse(colors[leftIndex]); + var rightColor = parse(colors[rightIndex]); + var dv = value - leftIndex; + var color = stringify([ + clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)), + clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)), + clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)), + clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv)) + ], 'rgba'); + return fullOutput + ? { + color: color, + leftIndex: leftIndex, + rightIndex: rightIndex, + value: value + } + : color; + } + var mapToColor = lerp$1; + function modifyHSL(color, h, s, l) { + var colorArr = parse(color); + if (color) { + colorArr = rgba2hsla(colorArr); + h != null && (colorArr[0] = clampCssAngle(h)); + s != null && (colorArr[1] = parseCssFloat(s)); + l != null && (colorArr[2] = parseCssFloat(l)); + return stringify(hsla2rgba(colorArr), 'rgba'); + } + } + function modifyAlpha(color, alpha) { + var colorArr = parse(color); + if (colorArr && alpha != null) { + colorArr[3] = clampCssFloat(alpha); + return stringify(colorArr, 'rgba'); + } + } + function stringify(arrColor, type) { + if (!arrColor || !arrColor.length) { + return; + } + var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2]; + if (type === 'rgba' || type === 'hsva' || type === 'hsla') { + colorStr += ',' + arrColor[3]; + } + return type + '(' + colorStr + ')'; + } + function lum(color, backgroundLum) { + var arr = parse(color); + return arr + ? (0.299 * arr[0] + 0.587 * arr[1] + 0.114 * arr[2]) * arr[3] / 255 + + (1 - arr[3]) * backgroundLum + : 0; + } + function random() { + return stringify([ + Math.round(Math.random() * 255), + Math.round(Math.random() * 255), + Math.round(Math.random() * 255) + ], 'rgb'); + } + + var color = /*#__PURE__*/Object.freeze({ + __proto__: null, + parse: parse, + lift: lift, + toHex: toHex, + fastLerp: fastLerp, + fastMapToColor: fastMapToColor, + lerp: lerp$1, + mapToColor: mapToColor, + modifyHSL: modifyHSL, + modifyAlpha: modifyAlpha, + stringify: stringify, + lum: lum, + random: random + }); + + var mathRound = Math.round; + function normalizeColor(color) { + var opacity; + if (!color || color === 'transparent') { + color = 'none'; + } + else if (typeof color === 'string' && color.indexOf('rgba') > -1) { + var arr = parse(color); + if (arr) { + color = 'rgb(' + arr[0] + ',' + arr[1] + ',' + arr[2] + ')'; + opacity = arr[3]; + } + } + return { + color: color, + opacity: opacity == null ? 1 : opacity + }; + } + var EPSILON$1 = 1e-4; + function isAroundZero$1(transform) { + return transform < EPSILON$1 && transform > -EPSILON$1; + } + function round3(transform) { + return mathRound(transform * 1e3) / 1e3; + } + function round4(transform) { + return mathRound(transform * 1e4) / 1e4; + } + function getMatrixStr(m) { + return 'matrix(' + + round3(m[0]) + ',' + + round3(m[1]) + ',' + + round3(m[2]) + ',' + + round3(m[3]) + ',' + + round4(m[4]) + ',' + + round4(m[5]) + + ')'; + } + var TEXT_ALIGN_TO_ANCHOR = { + left: 'start', + right: 'end', + center: 'middle', + middle: 'middle' + }; + function adjustTextY(y, lineHeight, textBaseline) { + if (textBaseline === 'top') { + y += lineHeight / 2; + } + else if (textBaseline === 'bottom') { + y -= lineHeight / 2; + } + return y; + } + function hasShadow(style) { + return style + && (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY); + } + function getShadowKey(displayable) { + var style = displayable.style; + var globalScale = displayable.getGlobalScale(); + return [ + style.shadowColor, + (style.shadowBlur || 0).toFixed(2), + (style.shadowOffsetX || 0).toFixed(2), + (style.shadowOffsetY || 0).toFixed(2), + globalScale[0], + globalScale[1] + ].join(','); + } + function isImagePattern(val) { + return val && (!!val.image); + } + function isSVGPattern(val) { + return val && (!!val.svgElement); + } + function isPattern(val) { + return isImagePattern(val) || isSVGPattern(val); + } + function isLinearGradient(val) { + return val.type === 'linear'; + } + function isRadialGradient(val) { + return val.type === 'radial'; + } + function isGradient(val) { + return val && (val.type === 'linear' + || val.type === 'radial'); + } + function getIdURL(id) { + return "url(#" + id + ")"; + } + function getPathPrecision(el) { + var scale = el.getGlobalScale(); + var size = Math.max(scale[0], scale[1]); + return Math.max(Math.ceil(Math.log(size) / Math.log(10)), 1); + } + function getSRTTransformString(transform) { + var x = transform.x || 0; + var y = transform.y || 0; + var rotation = (transform.rotation || 0) * RADIAN_TO_DEGREE; + var scaleX = retrieve2(transform.scaleX, 1); + var scaleY = retrieve2(transform.scaleY, 1); + var skewX = transform.skewX || 0; + var skewY = transform.skewY || 0; + var res = []; + if (x || y) { + res.push("translate(" + x + "px," + y + "px)"); + } + if (rotation) { + res.push("rotate(" + rotation + ")"); + } + if (scaleX !== 1 || scaleY !== 1) { + res.push("scale(" + scaleX + "," + scaleY + ")"); + } + if (skewX || skewY) { + res.push("skew(" + mathRound(skewX * RADIAN_TO_DEGREE) + "deg, " + mathRound(skewY * RADIAN_TO_DEGREE) + "deg)"); + } + return res.join(' '); + } + var encodeBase64 = (function () { + if (env.hasGlobalWindow && isFunction(window.btoa)) { + return function (str) { + return window.btoa(unescape(str)); + }; + } + if (typeof Buffer !== 'undefined') { + return function (str) { + return Buffer.from(str).toString('base64'); + }; + } + return function (str) { + if ("development" !== 'production') { + logError('Base64 isn\'t natively supported in the current environment.'); + } + return null; + }; + })(); + + var arraySlice = Array.prototype.slice; + function interpolateNumber(p0, p1, percent) { + return (p1 - p0) * percent + p0; + } + function interpolate1DArray(out, p0, p1, percent) { + var len = p0.length; + for (var i = 0; i < len; i++) { + out[i] = interpolateNumber(p0[i], p1[i], percent); + } + return out; + } + function interpolate2DArray(out, p0, p1, percent) { + var len = p0.length; + var len2 = len && p0[0].length; + for (var i = 0; i < len; i++) { + if (!out[i]) { + out[i] = []; + } + for (var j = 0; j < len2; j++) { + out[i][j] = interpolateNumber(p0[i][j], p1[i][j], percent); + } + } + return out; + } + function add1DArray(out, p0, p1, sign) { + var len = p0.length; + for (var i = 0; i < len; i++) { + out[i] = p0[i] + p1[i] * sign; + } + return out; + } + function add2DArray(out, p0, p1, sign) { + var len = p0.length; + var len2 = len && p0[0].length; + for (var i = 0; i < len; i++) { + if (!out[i]) { + out[i] = []; + } + for (var j = 0; j < len2; j++) { + out[i][j] = p0[i][j] + p1[i][j] * sign; + } + } + return out; + } + function fillColorStops(val0, val1) { + var len0 = val0.length; + var len1 = val1.length; + var shorterArr = len0 > len1 ? val1 : val0; + var shorterLen = Math.min(len0, len1); + var last = shorterArr[shorterLen - 1] || { color: [0, 0, 0, 0], offset: 0 }; + for (var i = shorterLen; i < Math.max(len0, len1); i++) { + shorterArr.push({ + offset: last.offset, + color: last.color.slice() + }); + } + } + function fillArray(val0, val1, arrDim) { + var arr0 = val0; + var arr1 = val1; + if (!arr0.push || !arr1.push) { + return; + } + var arr0Len = arr0.length; + var arr1Len = arr1.length; + if (arr0Len !== arr1Len) { + var isPreviousLarger = arr0Len > arr1Len; + if (isPreviousLarger) { + arr0.length = arr1Len; + } + else { + for (var i = arr0Len; i < arr1Len; i++) { + arr0.push(arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i])); + } + } + } + var len2 = arr0[0] && arr0[0].length; + for (var i = 0; i < arr0.length; i++) { + if (arrDim === 1) { + if (isNaN(arr0[i])) { + arr0[i] = arr1[i]; + } + } + else { + for (var j = 0; j < len2; j++) { + if (isNaN(arr0[i][j])) { + arr0[i][j] = arr1[i][j]; + } + } + } + } + } + function cloneValue(value) { + if (isArrayLike(value)) { + var len = value.length; + if (isArrayLike(value[0])) { + var ret = []; + for (var i = 0; i < len; i++) { + ret.push(arraySlice.call(value[i])); + } + return ret; + } + return arraySlice.call(value); + } + return value; + } + function rgba2String(rgba) { + rgba[0] = Math.floor(rgba[0]) || 0; + rgba[1] = Math.floor(rgba[1]) || 0; + rgba[2] = Math.floor(rgba[2]) || 0; + rgba[3] = rgba[3] == null ? 1 : rgba[3]; + return 'rgba(' + rgba.join(',') + ')'; + } + function guessArrayDim(value) { + return isArrayLike(value && value[0]) ? 2 : 1; + } + var VALUE_TYPE_NUMBER = 0; + var VALUE_TYPE_1D_ARRAY = 1; + var VALUE_TYPE_2D_ARRAY = 2; + var VALUE_TYPE_COLOR = 3; + var VALUE_TYPE_LINEAR_GRADIENT = 4; + var VALUE_TYPE_RADIAL_GRADIENT = 5; + var VALUE_TYPE_UNKOWN = 6; + function isGradientValueType(valType) { + return valType === VALUE_TYPE_LINEAR_GRADIENT || valType === VALUE_TYPE_RADIAL_GRADIENT; + } + function isArrayValueType(valType) { + return valType === VALUE_TYPE_1D_ARRAY || valType === VALUE_TYPE_2D_ARRAY; + } + var tmpRgba = [0, 0, 0, 0]; + var Track = (function () { + function Track(propName) { + this.keyframes = []; + this.discrete = false; + this._invalid = false; + this._needsSort = false; + this._lastFr = 0; + this._lastFrP = 0; + this.propName = propName; + } + Track.prototype.isFinished = function () { + return this._finished; + }; + Track.prototype.setFinished = function () { + this._finished = true; + if (this._additiveTrack) { + this._additiveTrack.setFinished(); + } + }; + Track.prototype.needsAnimate = function () { + return this.keyframes.length >= 1; + }; + Track.prototype.getAdditiveTrack = function () { + return this._additiveTrack; + }; + Track.prototype.addKeyframe = function (time, rawValue, easing) { + this._needsSort = true; + var keyframes = this.keyframes; + var len = keyframes.length; + var discrete = false; + var valType = VALUE_TYPE_UNKOWN; + var value = rawValue; + if (isArrayLike(rawValue)) { + var arrayDim = guessArrayDim(rawValue); + valType = arrayDim; + if (arrayDim === 1 && !isNumber(rawValue[0]) + || arrayDim === 2 && !isNumber(rawValue[0][0])) { + discrete = true; + } + } + else { + if (isNumber(rawValue) && !eqNaN(rawValue)) { + valType = VALUE_TYPE_NUMBER; + } + else if (isString(rawValue)) { + if (!isNaN(+rawValue)) { + valType = VALUE_TYPE_NUMBER; + } + else { + var colorArray = parse(rawValue); + if (colorArray) { + value = colorArray; + valType = VALUE_TYPE_COLOR; + } + } + } + else if (isGradientObject(rawValue)) { + var parsedGradient = extend({}, value); + parsedGradient.colorStops = map(rawValue.colorStops, function (colorStop) { return ({ + offset: colorStop.offset, + color: parse(colorStop.color) + }); }); + if (isLinearGradient(rawValue)) { + valType = VALUE_TYPE_LINEAR_GRADIENT; + } + else if (isRadialGradient(rawValue)) { + valType = VALUE_TYPE_RADIAL_GRADIENT; + } + value = parsedGradient; + } + } + if (len === 0) { + this.valType = valType; + } + else if (valType !== this.valType || valType === VALUE_TYPE_UNKOWN) { + discrete = true; + } + this.discrete = this.discrete || discrete; + var kf = { + time: time, + value: value, + rawValue: rawValue, + percent: 0 + }; + if (easing) { + kf.easing = easing; + kf.easingFunc = isFunction(easing) + ? easing + : easingFuncs[easing] || createCubicEasingFunc(easing); + } + keyframes.push(kf); + return kf; + }; + Track.prototype.prepare = function (maxTime, additiveTrack) { + var kfs = this.keyframes; + if (this._needsSort) { + kfs.sort(function (a, b) { + return a.time - b.time; + }); + } + var valType = this.valType; + var kfsLen = kfs.length; + var lastKf = kfs[kfsLen - 1]; + var isDiscrete = this.discrete; + var isArr = isArrayValueType(valType); + var isGradient = isGradientValueType(valType); + for (var i = 0; i < kfsLen; i++) { + var kf = kfs[i]; + var value = kf.value; + var lastValue = lastKf.value; + kf.percent = kf.time / maxTime; + if (!isDiscrete) { + if (isArr && i !== kfsLen - 1) { + fillArray(value, lastValue, valType); + } + else if (isGradient) { + fillColorStops(value.colorStops, lastValue.colorStops); + } + } + } + if (!isDiscrete + && valType !== VALUE_TYPE_RADIAL_GRADIENT + && additiveTrack + && this.needsAnimate() + && additiveTrack.needsAnimate() + && valType === additiveTrack.valType + && !additiveTrack._finished) { + this._additiveTrack = additiveTrack; + var startValue = kfs[0].value; + for (var i = 0; i < kfsLen; i++) { + if (valType === VALUE_TYPE_NUMBER) { + kfs[i].additiveValue = kfs[i].value - startValue; + } + else if (valType === VALUE_TYPE_COLOR) { + kfs[i].additiveValue = + add1DArray([], kfs[i].value, startValue, -1); + } + else if (isArrayValueType(valType)) { + kfs[i].additiveValue = valType === VALUE_TYPE_1D_ARRAY + ? add1DArray([], kfs[i].value, startValue, -1) + : add2DArray([], kfs[i].value, startValue, -1); + } + } + } + }; + Track.prototype.step = function (target, percent) { + if (this._finished) { + return; + } + if (this._additiveTrack && this._additiveTrack._finished) { + this._additiveTrack = null; + } + var isAdditive = this._additiveTrack != null; + var valueKey = isAdditive ? 'additiveValue' : 'value'; + var valType = this.valType; + var keyframes = this.keyframes; + var kfsNum = keyframes.length; + var propName = this.propName; + var isValueColor = valType === VALUE_TYPE_COLOR; + var frameIdx; + var lastFrame = this._lastFr; + var mathMin = Math.min; + var frame; + var nextFrame; + if (kfsNum === 1) { + frame = nextFrame = keyframes[0]; + } + else { + if (percent < 0) { + frameIdx = 0; + } + else if (percent < this._lastFrP) { + var start = mathMin(lastFrame + 1, kfsNum - 1); + for (frameIdx = start; frameIdx >= 0; frameIdx--) { + if (keyframes[frameIdx].percent <= percent) { + break; + } + } + frameIdx = mathMin(frameIdx, kfsNum - 2); + } + else { + for (frameIdx = lastFrame; frameIdx < kfsNum; frameIdx++) { + if (keyframes[frameIdx].percent > percent) { + break; + } + } + frameIdx = mathMin(frameIdx - 1, kfsNum - 2); + } + nextFrame = keyframes[frameIdx + 1]; + frame = keyframes[frameIdx]; + } + if (!(frame && nextFrame)) { + return; + } + this._lastFr = frameIdx; + this._lastFrP = percent; + var interval = (nextFrame.percent - frame.percent); + var w = interval === 0 ? 1 : mathMin((percent - frame.percent) / interval, 1); + if (nextFrame.easingFunc) { + w = nextFrame.easingFunc(w); + } + var targetArr = isAdditive ? this._additiveValue + : (isValueColor ? tmpRgba : target[propName]); + if ((isArrayValueType(valType) || isValueColor) && !targetArr) { + targetArr = this._additiveValue = []; + } + if (this.discrete) { + target[propName] = w < 1 ? frame.rawValue : nextFrame.rawValue; + } + else if (isArrayValueType(valType)) { + valType === VALUE_TYPE_1D_ARRAY + ? interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w) + : interpolate2DArray(targetArr, frame[valueKey], nextFrame[valueKey], w); + } + else if (isGradientValueType(valType)) { + var val = frame[valueKey]; + var nextVal_1 = nextFrame[valueKey]; + var isLinearGradient_1 = valType === VALUE_TYPE_LINEAR_GRADIENT; + target[propName] = { + type: isLinearGradient_1 ? 'linear' : 'radial', + x: interpolateNumber(val.x, nextVal_1.x, w), + y: interpolateNumber(val.y, nextVal_1.y, w), + colorStops: map(val.colorStops, function (colorStop, idx) { + var nextColorStop = nextVal_1.colorStops[idx]; + return { + offset: interpolateNumber(colorStop.offset, nextColorStop.offset, w), + color: rgba2String(interpolate1DArray([], colorStop.color, nextColorStop.color, w)) + }; + }), + global: nextVal_1.global + }; + if (isLinearGradient_1) { + target[propName].x2 = interpolateNumber(val.x2, nextVal_1.x2, w); + target[propName].y2 = interpolateNumber(val.y2, nextVal_1.y2, w); + } + else { + target[propName].r = interpolateNumber(val.r, nextVal_1.r, w); + } + } + else if (isValueColor) { + interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w); + if (!isAdditive) { + target[propName] = rgba2String(targetArr); + } + } + else { + var value = interpolateNumber(frame[valueKey], nextFrame[valueKey], w); + if (isAdditive) { + this._additiveValue = value; + } + else { + target[propName] = value; + } + } + if (isAdditive) { + this._addToTarget(target); + } + }; + Track.prototype._addToTarget = function (target) { + var valType = this.valType; + var propName = this.propName; + var additiveValue = this._additiveValue; + if (valType === VALUE_TYPE_NUMBER) { + target[propName] = target[propName] + additiveValue; + } + else if (valType === VALUE_TYPE_COLOR) { + parse(target[propName], tmpRgba); + add1DArray(tmpRgba, tmpRgba, additiveValue, 1); + target[propName] = rgba2String(tmpRgba); + } + else if (valType === VALUE_TYPE_1D_ARRAY) { + add1DArray(target[propName], target[propName], additiveValue, 1); + } + else if (valType === VALUE_TYPE_2D_ARRAY) { + add2DArray(target[propName], target[propName], additiveValue, 1); + } + }; + return Track; + }()); + var Animator = (function () { + function Animator(target, loop, allowDiscreteAnimation, additiveTo) { + this._tracks = {}; + this._trackKeys = []; + this._maxTime = 0; + this._started = 0; + this._clip = null; + this._target = target; + this._loop = loop; + if (loop && additiveTo) { + logError('Can\' use additive animation on looped animation.'); + return; + } + this._additiveAnimators = additiveTo; + this._allowDiscrete = allowDiscreteAnimation; + } + Animator.prototype.getMaxTime = function () { + return this._maxTime; + }; + Animator.prototype.getDelay = function () { + return this._delay; + }; + Animator.prototype.getLoop = function () { + return this._loop; + }; + Animator.prototype.getTarget = function () { + return this._target; + }; + Animator.prototype.changeTarget = function (target) { + this._target = target; + }; + Animator.prototype.when = function (time, props, easing) { + return this.whenWithKeys(time, props, keys(props), easing); + }; + Animator.prototype.whenWithKeys = function (time, props, propNames, easing) { + var tracks = this._tracks; + for (var i = 0; i < propNames.length; i++) { + var propName = propNames[i]; + var track = tracks[propName]; + if (!track) { + track = tracks[propName] = new Track(propName); + var initialValue = void 0; + var additiveTrack = this._getAdditiveTrack(propName); + if (additiveTrack) { + var addtiveTrackKfs = additiveTrack.keyframes; + var lastFinalKf = addtiveTrackKfs[addtiveTrackKfs.length - 1]; + initialValue = lastFinalKf && lastFinalKf.value; + if (additiveTrack.valType === VALUE_TYPE_COLOR && initialValue) { + initialValue = rgba2String(initialValue); + } + } + else { + initialValue = this._target[propName]; + } + if (initialValue == null) { + continue; + } + if (time > 0) { + track.addKeyframe(0, cloneValue(initialValue), easing); + } + this._trackKeys.push(propName); + } + track.addKeyframe(time, cloneValue(props[propName]), easing); + } + this._maxTime = Math.max(this._maxTime, time); + return this; + }; + Animator.prototype.pause = function () { + this._clip.pause(); + this._paused = true; + }; + Animator.prototype.resume = function () { + this._clip.resume(); + this._paused = false; + }; + Animator.prototype.isPaused = function () { + return !!this._paused; + }; + Animator.prototype.duration = function (duration) { + this._maxTime = duration; + this._force = true; + return this; + }; + Animator.prototype._doneCallback = function () { + this._setTracksFinished(); + this._clip = null; + var doneList = this._doneCbs; + if (doneList) { + var len = doneList.length; + for (var i = 0; i < len; i++) { + doneList[i].call(this); + } + } + }; + Animator.prototype._abortedCallback = function () { + this._setTracksFinished(); + var animation = this.animation; + var abortedList = this._abortedCbs; + if (animation) { + animation.removeClip(this._clip); + } + this._clip = null; + if (abortedList) { + for (var i = 0; i < abortedList.length; i++) { + abortedList[i].call(this); + } + } + }; + Animator.prototype._setTracksFinished = function () { + var tracks = this._tracks; + var tracksKeys = this._trackKeys; + for (var i = 0; i < tracksKeys.length; i++) { + tracks[tracksKeys[i]].setFinished(); + } + }; + Animator.prototype._getAdditiveTrack = function (trackName) { + var additiveTrack; + var additiveAnimators = this._additiveAnimators; + if (additiveAnimators) { + for (var i = 0; i < additiveAnimators.length; i++) { + var track = additiveAnimators[i].getTrack(trackName); + if (track) { + additiveTrack = track; + } + } + } + return additiveTrack; + }; + Animator.prototype.start = function (easing) { + if (this._started > 0) { + return; + } + this._started = 1; + var self = this; + var tracks = []; + var maxTime = this._maxTime || 0; + for (var i = 0; i < this._trackKeys.length; i++) { + var propName = this._trackKeys[i]; + var track = this._tracks[propName]; + var additiveTrack = this._getAdditiveTrack(propName); + var kfs = track.keyframes; + var kfsNum = kfs.length; + track.prepare(maxTime, additiveTrack); + if (track.needsAnimate()) { + if (!this._allowDiscrete && track.discrete) { + var lastKf = kfs[kfsNum - 1]; + if (lastKf) { + self._target[track.propName] = lastKf.rawValue; + } + track.setFinished(); + } + else { + tracks.push(track); + } + } + } + if (tracks.length || this._force) { + var clip = new Clip({ + life: maxTime, + loop: this._loop, + delay: this._delay || 0, + onframe: function (percent) { + self._started = 2; + var additiveAnimators = self._additiveAnimators; + if (additiveAnimators) { + var stillHasAdditiveAnimator = false; + for (var i = 0; i < additiveAnimators.length; i++) { + if (additiveAnimators[i]._clip) { + stillHasAdditiveAnimator = true; + break; + } + } + if (!stillHasAdditiveAnimator) { + self._additiveAnimators = null; + } + } + for (var i = 0; i < tracks.length; i++) { + tracks[i].step(self._target, percent); + } + var onframeList = self._onframeCbs; + if (onframeList) { + for (var i = 0; i < onframeList.length; i++) { + onframeList[i](self._target, percent); + } + } + }, + ondestroy: function () { + self._doneCallback(); + } + }); + this._clip = clip; + if (this.animation) { + this.animation.addClip(clip); + } + if (easing) { + clip.setEasing(easing); + } + } + else { + this._doneCallback(); + } + return this; + }; + Animator.prototype.stop = function (forwardToLast) { + if (!this._clip) { + return; + } + var clip = this._clip; + if (forwardToLast) { + clip.onframe(1); + } + this._abortedCallback(); + }; + Animator.prototype.delay = function (time) { + this._delay = time; + return this; + }; + Animator.prototype.during = function (cb) { + if (cb) { + if (!this._onframeCbs) { + this._onframeCbs = []; + } + this._onframeCbs.push(cb); + } + return this; + }; + Animator.prototype.done = function (cb) { + if (cb) { + if (!this._doneCbs) { + this._doneCbs = []; + } + this._doneCbs.push(cb); + } + return this; + }; + Animator.prototype.aborted = function (cb) { + if (cb) { + if (!this._abortedCbs) { + this._abortedCbs = []; + } + this._abortedCbs.push(cb); + } + return this; + }; + Animator.prototype.getClip = function () { + return this._clip; + }; + Animator.prototype.getTrack = function (propName) { + return this._tracks[propName]; + }; + Animator.prototype.getTracks = function () { + var _this = this; + return map(this._trackKeys, function (key) { return _this._tracks[key]; }); + }; + Animator.prototype.stopTracks = function (propNames, forwardToLast) { + if (!propNames.length || !this._clip) { + return true; + } + var tracks = this._tracks; + var tracksKeys = this._trackKeys; + for (var i = 0; i < propNames.length; i++) { + var track = tracks[propNames[i]]; + if (track && !track.isFinished()) { + if (forwardToLast) { + track.step(this._target, 1); + } + else if (this._started === 1) { + track.step(this._target, 0); + } + track.setFinished(); + } + } + var allAborted = true; + for (var i = 0; i < tracksKeys.length; i++) { + if (!tracks[tracksKeys[i]].isFinished()) { + allAborted = false; + break; + } + } + if (allAborted) { + this._abortedCallback(); + } + return allAborted; + }; + Animator.prototype.saveTo = function (target, trackKeys, firstOrLast) { + if (!target) { + return; + } + trackKeys = trackKeys || this._trackKeys; + for (var i = 0; i < trackKeys.length; i++) { + var propName = trackKeys[i]; + var track = this._tracks[propName]; + if (!track || track.isFinished()) { + continue; + } + var kfs = track.keyframes; + var kf = kfs[firstOrLast ? 0 : kfs.length - 1]; + if (kf) { + target[propName] = cloneValue(kf.rawValue); + } + } + }; + Animator.prototype.__changeFinalValue = function (finalProps, trackKeys) { + trackKeys = trackKeys || keys(finalProps); + for (var i = 0; i < trackKeys.length; i++) { + var propName = trackKeys[i]; + var track = this._tracks[propName]; + if (!track) { + continue; + } + var kfs = track.keyframes; + if (kfs.length > 1) { + var lastKf = kfs.pop(); + track.addKeyframe(lastKf.time, finalProps[propName]); + track.prepare(this._maxTime, track.getAdditiveTrack()); + } + } + }; + return Animator; + }()); + + function getTime() { + return new Date().getTime(); + } + var Animation = (function (_super) { + __extends(Animation, _super); + function Animation(opts) { + var _this = _super.call(this) || this; + _this._running = false; + _this._time = 0; + _this._pausedTime = 0; + _this._pauseStart = 0; + _this._paused = false; + opts = opts || {}; + _this.stage = opts.stage || {}; + return _this; + } + Animation.prototype.addClip = function (clip) { + if (clip.animation) { + this.removeClip(clip); + } + if (!this._head) { + this._head = this._tail = clip; + } + else { + this._tail.next = clip; + clip.prev = this._tail; + clip.next = null; + this._tail = clip; + } + clip.animation = this; + }; + Animation.prototype.addAnimator = function (animator) { + animator.animation = this; + var clip = animator.getClip(); + if (clip) { + this.addClip(clip); + } + }; + Animation.prototype.removeClip = function (clip) { + if (!clip.animation) { + return; + } + var prev = clip.prev; + var next = clip.next; + if (prev) { + prev.next = next; + } + else { + this._head = next; + } + if (next) { + next.prev = prev; + } + else { + this._tail = prev; + } + clip.next = clip.prev = clip.animation = null; + }; + Animation.prototype.removeAnimator = function (animator) { + var clip = animator.getClip(); + if (clip) { + this.removeClip(clip); + } + animator.animation = null; + }; + Animation.prototype.update = function (notTriggerFrameAndStageUpdate) { + var time = getTime() - this._pausedTime; + var delta = time - this._time; + var clip = this._head; + while (clip) { + var nextClip = clip.next; + var finished = clip.step(time, delta); + if (finished) { + clip.ondestroy(); + this.removeClip(clip); + clip = nextClip; + } + else { + clip = nextClip; + } + } + this._time = time; + if (!notTriggerFrameAndStageUpdate) { + this.trigger('frame', delta); + this.stage.update && this.stage.update(); + } + }; + Animation.prototype._startLoop = function () { + var self = this; + this._running = true; + function step() { + if (self._running) { + requestAnimationFrame$1(step); + !self._paused && self.update(); + } + } + requestAnimationFrame$1(step); + }; + Animation.prototype.start = function () { + if (this._running) { + return; + } + this._time = getTime(); + this._pausedTime = 0; + this._startLoop(); + }; + Animation.prototype.stop = function () { + this._running = false; + }; + Animation.prototype.pause = function () { + if (!this._paused) { + this._pauseStart = getTime(); + this._paused = true; + } + }; + Animation.prototype.resume = function () { + if (this._paused) { + this._pausedTime += getTime() - this._pauseStart; + this._paused = false; + } + }; + Animation.prototype.clear = function () { + var clip = this._head; + while (clip) { + var nextClip = clip.next; + clip.prev = clip.next = clip.animation = null; + clip = nextClip; + } + this._head = this._tail = null; + }; + Animation.prototype.isFinished = function () { + return this._head == null; + }; + Animation.prototype.animate = function (target, options) { + options = options || {}; + this.start(); + var animator = new Animator(target, options.loop); + this.addAnimator(animator); + return animator; + }; + return Animation; + }(Eventful)); + + var TOUCH_CLICK_DELAY = 300; + var globalEventSupported = env.domSupported; + var localNativeListenerNames = (function () { + var mouseHandlerNames = [ + 'click', 'dblclick', 'mousewheel', 'wheel', 'mouseout', + 'mouseup', 'mousedown', 'mousemove', 'contextmenu' + ]; + var touchHandlerNames = [ + 'touchstart', 'touchend', 'touchmove' + ]; + var pointerEventNameMap = { + pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1 + }; + var pointerHandlerNames = map(mouseHandlerNames, function (name) { + var nm = name.replace('mouse', 'pointer'); + return pointerEventNameMap.hasOwnProperty(nm) ? nm : name; + }); + return { + mouse: mouseHandlerNames, + touch: touchHandlerNames, + pointer: pointerHandlerNames + }; + })(); + var globalNativeListenerNames = { + mouse: ['mousemove', 'mouseup'], + pointer: ['pointermove', 'pointerup'] + }; + var wheelEventSupported = false; + function isPointerFromTouch(event) { + var pointerType = event.pointerType; + return pointerType === 'pen' || pointerType === 'touch'; + } + function setTouchTimer(scope) { + scope.touching = true; + if (scope.touchTimer != null) { + clearTimeout(scope.touchTimer); + scope.touchTimer = null; + } + scope.touchTimer = setTimeout(function () { + scope.touching = false; + scope.touchTimer = null; + }, 700); + } + function markTouch(event) { + event && (event.zrByTouch = true); + } + function normalizeGlobalEvent(instance, event) { + return normalizeEvent(instance.dom, new FakeGlobalEvent(instance, event), true); + } + function isLocalEl(instance, el) { + var elTmp = el; + var isLocal = false; + while (elTmp && elTmp.nodeType !== 9 + && !(isLocal = elTmp.domBelongToZr + || (elTmp !== el && elTmp === instance.painterRoot))) { + elTmp = elTmp.parentNode; + } + return isLocal; + } + var FakeGlobalEvent = (function () { + function FakeGlobalEvent(instance, event) { + this.stopPropagation = noop; + this.stopImmediatePropagation = noop; + this.preventDefault = noop; + this.type = event.type; + this.target = this.currentTarget = instance.dom; + this.pointerType = event.pointerType; + this.clientX = event.clientX; + this.clientY = event.clientY; + } + return FakeGlobalEvent; + }()); + var localDOMHandlers = { + mousedown: function (event) { + event = normalizeEvent(this.dom, event); + this.__mayPointerCapture = [event.zrX, event.zrY]; + this.trigger('mousedown', event); + }, + mousemove: function (event) { + event = normalizeEvent(this.dom, event); + var downPoint = this.__mayPointerCapture; + if (downPoint && (event.zrX !== downPoint[0] || event.zrY !== downPoint[1])) { + this.__togglePointerCapture(true); + } + this.trigger('mousemove', event); + }, + mouseup: function (event) { + event = normalizeEvent(this.dom, event); + this.__togglePointerCapture(false); + this.trigger('mouseup', event); + }, + mouseout: function (event) { + event = normalizeEvent(this.dom, event); + var element = event.toElement || event.relatedTarget; + if (!isLocalEl(this, element)) { + if (this.__pointerCapturing) { + event.zrEventControl = 'no_globalout'; + } + this.trigger('mouseout', event); + } + }, + wheel: function (event) { + wheelEventSupported = true; + event = normalizeEvent(this.dom, event); + this.trigger('mousewheel', event); + }, + mousewheel: function (event) { + if (wheelEventSupported) { + return; + } + event = normalizeEvent(this.dom, event); + this.trigger('mousewheel', event); + }, + touchstart: function (event) { + event = normalizeEvent(this.dom, event); + markTouch(event); + this.__lastTouchMoment = new Date(); + this.handler.processGesture(event, 'start'); + localDOMHandlers.mousemove.call(this, event); + localDOMHandlers.mousedown.call(this, event); + }, + touchmove: function (event) { + event = normalizeEvent(this.dom, event); + markTouch(event); + this.handler.processGesture(event, 'change'); + localDOMHandlers.mousemove.call(this, event); + }, + touchend: function (event) { + event = normalizeEvent(this.dom, event); + markTouch(event); + this.handler.processGesture(event, 'end'); + localDOMHandlers.mouseup.call(this, event); + if (+new Date() - (+this.__lastTouchMoment) < TOUCH_CLICK_DELAY) { + localDOMHandlers.click.call(this, event); + } + }, + pointerdown: function (event) { + localDOMHandlers.mousedown.call(this, event); + }, + pointermove: function (event) { + if (!isPointerFromTouch(event)) { + localDOMHandlers.mousemove.call(this, event); + } + }, + pointerup: function (event) { + localDOMHandlers.mouseup.call(this, event); + }, + pointerout: function (event) { + if (!isPointerFromTouch(event)) { + localDOMHandlers.mouseout.call(this, event); + } + } + }; + each(['click', 'dblclick', 'contextmenu'], function (name) { + localDOMHandlers[name] = function (event) { + event = normalizeEvent(this.dom, event); + this.trigger(name, event); + }; + }); + var globalDOMHandlers = { + pointermove: function (event) { + if (!isPointerFromTouch(event)) { + globalDOMHandlers.mousemove.call(this, event); + } + }, + pointerup: function (event) { + globalDOMHandlers.mouseup.call(this, event); + }, + mousemove: function (event) { + this.trigger('mousemove', event); + }, + mouseup: function (event) { + var pointerCaptureReleasing = this.__pointerCapturing; + this.__togglePointerCapture(false); + this.trigger('mouseup', event); + if (pointerCaptureReleasing) { + event.zrEventControl = 'only_globalout'; + this.trigger('mouseout', event); + } + } + }; + function mountLocalDOMEventListeners(instance, scope) { + var domHandlers = scope.domHandlers; + if (env.pointerEventsSupported) { + each(localNativeListenerNames.pointer, function (nativeEventName) { + mountSingleDOMEventListener(scope, nativeEventName, function (event) { + domHandlers[nativeEventName].call(instance, event); + }); + }); + } + else { + if (env.touchEventsSupported) { + each(localNativeListenerNames.touch, function (nativeEventName) { + mountSingleDOMEventListener(scope, nativeEventName, function (event) { + domHandlers[nativeEventName].call(instance, event); + setTouchTimer(scope); + }); + }); + } + each(localNativeListenerNames.mouse, function (nativeEventName) { + mountSingleDOMEventListener(scope, nativeEventName, function (event) { + event = getNativeEvent(event); + if (!scope.touching) { + domHandlers[nativeEventName].call(instance, event); + } + }); + }); + } + } + function mountGlobalDOMEventListeners(instance, scope) { + if (env.pointerEventsSupported) { + each(globalNativeListenerNames.pointer, mount); + } + else if (!env.touchEventsSupported) { + each(globalNativeListenerNames.mouse, mount); + } + function mount(nativeEventName) { + function nativeEventListener(event) { + event = getNativeEvent(event); + if (!isLocalEl(instance, event.target)) { + event = normalizeGlobalEvent(instance, event); + scope.domHandlers[nativeEventName].call(instance, event); + } + } + mountSingleDOMEventListener(scope, nativeEventName, nativeEventListener, { capture: true }); + } + } + function mountSingleDOMEventListener(scope, nativeEventName, listener, opt) { + scope.mounted[nativeEventName] = listener; + scope.listenerOpts[nativeEventName] = opt; + addEventListener(scope.domTarget, nativeEventName, listener, opt); + } + function unmountDOMEventListeners(scope) { + var mounted = scope.mounted; + for (var nativeEventName in mounted) { + if (mounted.hasOwnProperty(nativeEventName)) { + removeEventListener(scope.domTarget, nativeEventName, mounted[nativeEventName], scope.listenerOpts[nativeEventName]); + } + } + scope.mounted = {}; + } + var DOMHandlerScope = (function () { + function DOMHandlerScope(domTarget, domHandlers) { + this.mounted = {}; + this.listenerOpts = {}; + this.touching = false; + this.domTarget = domTarget; + this.domHandlers = domHandlers; + } + return DOMHandlerScope; + }()); + var HandlerDomProxy = (function (_super) { + __extends(HandlerDomProxy, _super); + function HandlerDomProxy(dom, painterRoot) { + var _this = _super.call(this) || this; + _this.__pointerCapturing = false; + _this.dom = dom; + _this.painterRoot = painterRoot; + _this._localHandlerScope = new DOMHandlerScope(dom, localDOMHandlers); + if (globalEventSupported) { + _this._globalHandlerScope = new DOMHandlerScope(document, globalDOMHandlers); + } + mountLocalDOMEventListeners(_this, _this._localHandlerScope); + return _this; + } + HandlerDomProxy.prototype.dispose = function () { + unmountDOMEventListeners(this._localHandlerScope); + if (globalEventSupported) { + unmountDOMEventListeners(this._globalHandlerScope); + } + }; + HandlerDomProxy.prototype.setCursor = function (cursorStyle) { + this.dom.style && (this.dom.style.cursor = cursorStyle || 'default'); + }; + HandlerDomProxy.prototype.__togglePointerCapture = function (isPointerCapturing) { + this.__mayPointerCapture = null; + if (globalEventSupported + && ((+this.__pointerCapturing) ^ (+isPointerCapturing))) { + this.__pointerCapturing = isPointerCapturing; + var globalHandlerScope = this._globalHandlerScope; + isPointerCapturing + ? mountGlobalDOMEventListeners(this, globalHandlerScope) + : unmountDOMEventListeners(globalHandlerScope); + } + }; + return HandlerDomProxy; + }(Eventful)); + + var dpr = 1; + if (env.hasGlobalWindow) { + dpr = Math.max(window.devicePixelRatio + || (window.screen && window.screen.deviceXDPI / window.screen.logicalXDPI) + || 1, 1); + } + var devicePixelRatio = dpr; + var DARK_MODE_THRESHOLD = 0.4; + var DARK_LABEL_COLOR = '#333'; + var LIGHT_LABEL_COLOR = '#ccc'; + var LIGHTER_LABEL_COLOR = '#eee'; + + function create$1() { + return [1, 0, 0, 1, 0, 0]; + } + function identity(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + out[4] = 0; + out[5] = 0; + return out; + } + function copy$1(out, m) { + out[0] = m[0]; + out[1] = m[1]; + out[2] = m[2]; + out[3] = m[3]; + out[4] = m[4]; + out[5] = m[5]; + return out; + } + function mul$1(out, m1, m2) { + var out0 = m1[0] * m2[0] + m1[2] * m2[1]; + var out1 = m1[1] * m2[0] + m1[3] * m2[1]; + var out2 = m1[0] * m2[2] + m1[2] * m2[3]; + var out3 = m1[1] * m2[2] + m1[3] * m2[3]; + var out4 = m1[0] * m2[4] + m1[2] * m2[5] + m1[4]; + var out5 = m1[1] * m2[4] + m1[3] * m2[5] + m1[5]; + out[0] = out0; + out[1] = out1; + out[2] = out2; + out[3] = out3; + out[4] = out4; + out[5] = out5; + return out; + } + function translate(out, a, v) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4] + v[0]; + out[5] = a[5] + v[1]; + return out; + } + function rotate(out, a, rad) { + var aa = a[0]; + var ac = a[2]; + var atx = a[4]; + var ab = a[1]; + var ad = a[3]; + var aty = a[5]; + var st = Math.sin(rad); + var ct = Math.cos(rad); + out[0] = aa * ct + ab * st; + out[1] = -aa * st + ab * ct; + out[2] = ac * ct + ad * st; + out[3] = -ac * st + ct * ad; + out[4] = ct * atx + st * aty; + out[5] = ct * aty - st * atx; + return out; + } + function scale$1(out, a, v) { + var vx = v[0]; + var vy = v[1]; + out[0] = a[0] * vx; + out[1] = a[1] * vy; + out[2] = a[2] * vx; + out[3] = a[3] * vy; + out[4] = a[4] * vx; + out[5] = a[5] * vy; + return out; + } + function invert(out, a) { + var aa = a[0]; + var ac = a[2]; + var atx = a[4]; + var ab = a[1]; + var ad = a[3]; + var aty = a[5]; + var det = aa * ad - ab * ac; + if (!det) { + return null; + } + det = 1.0 / det; + out[0] = ad * det; + out[1] = -ab * det; + out[2] = -ac * det; + out[3] = aa * det; + out[4] = (ac * aty - ad * atx) * det; + out[5] = (ab * atx - aa * aty) * det; + return out; + } + function clone$2(a) { + var b = create$1(); + copy$1(b, a); + return b; + } + + var matrix = /*#__PURE__*/Object.freeze({ + __proto__: null, + create: create$1, + identity: identity, + copy: copy$1, + mul: mul$1, + translate: translate, + rotate: rotate, + scale: scale$1, + invert: invert, + clone: clone$2 + }); + + var mIdentity = identity; + var EPSILON$2 = 5e-5; + function isNotAroundZero$1(val) { + return val > EPSILON$2 || val < -EPSILON$2; + } + var scaleTmp = []; + var tmpTransform = []; + var originTransform = create$1(); + var abs = Math.abs; + var Transformable = (function () { + function Transformable() { + } + Transformable.prototype.getLocalTransform = function (m) { + return Transformable.getLocalTransform(this, m); + }; + Transformable.prototype.setPosition = function (arr) { + this.x = arr[0]; + this.y = arr[1]; + }; + Transformable.prototype.setScale = function (arr) { + this.scaleX = arr[0]; + this.scaleY = arr[1]; + }; + Transformable.prototype.setSkew = function (arr) { + this.skewX = arr[0]; + this.skewY = arr[1]; + }; + Transformable.prototype.setOrigin = function (arr) { + this.originX = arr[0]; + this.originY = arr[1]; + }; + Transformable.prototype.needLocalTransform = function () { + return isNotAroundZero$1(this.rotation) + || isNotAroundZero$1(this.x) + || isNotAroundZero$1(this.y) + || isNotAroundZero$1(this.scaleX - 1) + || isNotAroundZero$1(this.scaleY - 1) + || isNotAroundZero$1(this.skewX) + || isNotAroundZero$1(this.skewY); + }; + Transformable.prototype.updateTransform = function () { + var parentTransform = this.parent && this.parent.transform; + var needLocalTransform = this.needLocalTransform(); + var m = this.transform; + if (!(needLocalTransform || parentTransform)) { + m && mIdentity(m); + return; + } + m = m || create$1(); + if (needLocalTransform) { + this.getLocalTransform(m); + } + else { + mIdentity(m); + } + if (parentTransform) { + if (needLocalTransform) { + mul$1(m, parentTransform, m); + } + else { + copy$1(m, parentTransform); + } + } + this.transform = m; + this._resolveGlobalScaleRatio(m); + }; + Transformable.prototype._resolveGlobalScaleRatio = function (m) { + var globalScaleRatio = this.globalScaleRatio; + if (globalScaleRatio != null && globalScaleRatio !== 1) { + this.getGlobalScale(scaleTmp); + var relX = scaleTmp[0] < 0 ? -1 : 1; + var relY = scaleTmp[1] < 0 ? -1 : 1; + var sx = ((scaleTmp[0] - relX) * globalScaleRatio + relX) / scaleTmp[0] || 0; + var sy = ((scaleTmp[1] - relY) * globalScaleRatio + relY) / scaleTmp[1] || 0; + m[0] *= sx; + m[1] *= sx; + m[2] *= sy; + m[3] *= sy; + } + this.invTransform = this.invTransform || create$1(); + invert(this.invTransform, m); + }; + Transformable.prototype.getComputedTransform = function () { + var transformNode = this; + var ancestors = []; + while (transformNode) { + ancestors.push(transformNode); + transformNode = transformNode.parent; + } + while (transformNode = ancestors.pop()) { + transformNode.updateTransform(); + } + return this.transform; + }; + Transformable.prototype.setLocalTransform = function (m) { + if (!m) { + return; + } + var sx = m[0] * m[0] + m[1] * m[1]; + var sy = m[2] * m[2] + m[3] * m[3]; + var rotation = Math.atan2(m[1], m[0]); + var shearX = Math.PI / 2 + rotation - Math.atan2(m[3], m[2]); + sy = Math.sqrt(sy) * Math.cos(shearX); + sx = Math.sqrt(sx); + this.skewX = shearX; + this.skewY = 0; + this.rotation = -rotation; + this.x = +m[4]; + this.y = +m[5]; + this.scaleX = sx; + this.scaleY = sy; + this.originX = 0; + this.originY = 0; + }; + Transformable.prototype.decomposeTransform = function () { + if (!this.transform) { + return; + } + var parent = this.parent; + var m = this.transform; + if (parent && parent.transform) { + mul$1(tmpTransform, parent.invTransform, m); + m = tmpTransform; + } + var ox = this.originX; + var oy = this.originY; + if (ox || oy) { + originTransform[4] = ox; + originTransform[5] = oy; + mul$1(tmpTransform, m, originTransform); + tmpTransform[4] -= ox; + tmpTransform[5] -= oy; + m = tmpTransform; + } + this.setLocalTransform(m); + }; + Transformable.prototype.getGlobalScale = function (out) { + var m = this.transform; + out = out || []; + if (!m) { + out[0] = 1; + out[1] = 1; + return out; + } + out[0] = Math.sqrt(m[0] * m[0] + m[1] * m[1]); + out[1] = Math.sqrt(m[2] * m[2] + m[3] * m[3]); + if (m[0] < 0) { + out[0] = -out[0]; + } + if (m[3] < 0) { + out[1] = -out[1]; + } + return out; + }; + Transformable.prototype.transformCoordToLocal = function (x, y) { + var v2 = [x, y]; + var invTransform = this.invTransform; + if (invTransform) { + applyTransform(v2, v2, invTransform); + } + return v2; + }; + Transformable.prototype.transformCoordToGlobal = function (x, y) { + var v2 = [x, y]; + var transform = this.transform; + if (transform) { + applyTransform(v2, v2, transform); + } + return v2; + }; + Transformable.prototype.getLineScale = function () { + var m = this.transform; + return m && abs(m[0] - 1) > 1e-10 && abs(m[3] - 1) > 1e-10 + ? Math.sqrt(abs(m[0] * m[3] - m[2] * m[1])) + : 1; + }; + Transformable.prototype.copyTransform = function (source) { + copyTransform(this, source); + }; + Transformable.getLocalTransform = function (target, m) { + m = m || []; + var ox = target.originX || 0; + var oy = target.originY || 0; + var sx = target.scaleX; + var sy = target.scaleY; + var ax = target.anchorX; + var ay = target.anchorY; + var rotation = target.rotation || 0; + var x = target.x; + var y = target.y; + var skewX = target.skewX ? Math.tan(target.skewX) : 0; + var skewY = target.skewY ? Math.tan(-target.skewY) : 0; + if (ox || oy || ax || ay) { + var dx = ox + ax; + var dy = oy + ay; + m[4] = -dx * sx - skewX * dy * sy; + m[5] = -dy * sy - skewY * dx * sx; + } + else { + m[4] = m[5] = 0; + } + m[0] = sx; + m[3] = sy; + m[1] = skewY * sx; + m[2] = skewX * sy; + rotation && rotate(m, m, rotation); + m[4] += ox + x; + m[5] += oy + y; + return m; + }; + Transformable.initDefaultProps = (function () { + var proto = Transformable.prototype; + proto.scaleX = + proto.scaleY = + proto.globalScaleRatio = 1; + proto.x = + proto.y = + proto.originX = + proto.originY = + proto.skewX = + proto.skewY = + proto.rotation = + proto.anchorX = + proto.anchorY = 0; + })(); + return Transformable; + }()); + var TRANSFORMABLE_PROPS = [ + 'x', 'y', 'originX', 'originY', 'anchorX', 'anchorY', 'rotation', 'scaleX', 'scaleY', 'skewX', 'skewY' + ]; + function copyTransform(target, source) { + for (var i = 0; i < TRANSFORMABLE_PROPS.length; i++) { + var propName = TRANSFORMABLE_PROPS[i]; + target[propName] = source[propName]; + } + } + + var Point = (function () { + function Point(x, y) { + this.x = x || 0; + this.y = y || 0; + } + Point.prototype.copy = function (other) { + this.x = other.x; + this.y = other.y; + return this; + }; + Point.prototype.clone = function () { + return new Point(this.x, this.y); + }; + Point.prototype.set = function (x, y) { + this.x = x; + this.y = y; + return this; + }; + Point.prototype.equal = function (other) { + return other.x === this.x && other.y === this.y; + }; + Point.prototype.add = function (other) { + this.x += other.x; + this.y += other.y; + return this; + }; + Point.prototype.scale = function (scalar) { + this.x *= scalar; + this.y *= scalar; + }; + Point.prototype.scaleAndAdd = function (other, scalar) { + this.x += other.x * scalar; + this.y += other.y * scalar; + }; + Point.prototype.sub = function (other) { + this.x -= other.x; + this.y -= other.y; + return this; + }; + Point.prototype.dot = function (other) { + return this.x * other.x + this.y * other.y; + }; + Point.prototype.len = function () { + return Math.sqrt(this.x * this.x + this.y * this.y); + }; + Point.prototype.lenSquare = function () { + return this.x * this.x + this.y * this.y; + }; + Point.prototype.normalize = function () { + var len = this.len(); + this.x /= len; + this.y /= len; + return this; + }; + Point.prototype.distance = function (other) { + var dx = this.x - other.x; + var dy = this.y - other.y; + return Math.sqrt(dx * dx + dy * dy); + }; + Point.prototype.distanceSquare = function (other) { + var dx = this.x - other.x; + var dy = this.y - other.y; + return dx * dx + dy * dy; + }; + Point.prototype.negate = function () { + this.x = -this.x; + this.y = -this.y; + return this; + }; + Point.prototype.transform = function (m) { + if (!m) { + return; + } + var x = this.x; + var y = this.y; + this.x = m[0] * x + m[2] * y + m[4]; + this.y = m[1] * x + m[3] * y + m[5]; + return this; + }; + Point.prototype.toArray = function (out) { + out[0] = this.x; + out[1] = this.y; + return out; + }; + Point.prototype.fromArray = function (input) { + this.x = input[0]; + this.y = input[1]; + }; + Point.set = function (p, x, y) { + p.x = x; + p.y = y; + }; + Point.copy = function (p, p2) { + p.x = p2.x; + p.y = p2.y; + }; + Point.len = function (p) { + return Math.sqrt(p.x * p.x + p.y * p.y); + }; + Point.lenSquare = function (p) { + return p.x * p.x + p.y * p.y; + }; + Point.dot = function (p0, p1) { + return p0.x * p1.x + p0.y * p1.y; + }; + Point.add = function (out, p0, p1) { + out.x = p0.x + p1.x; + out.y = p0.y + p1.y; + }; + Point.sub = function (out, p0, p1) { + out.x = p0.x - p1.x; + out.y = p0.y - p1.y; + }; + Point.scale = function (out, p0, scalar) { + out.x = p0.x * scalar; + out.y = p0.y * scalar; + }; + Point.scaleAndAdd = function (out, p0, p1, scalar) { + out.x = p0.x + p1.x * scalar; + out.y = p0.y + p1.y * scalar; + }; + Point.lerp = function (out, p0, p1, t) { + var onet = 1 - t; + out.x = onet * p0.x + t * p1.x; + out.y = onet * p0.y + t * p1.y; + }; + return Point; + }()); + + var mathMin = Math.min; + var mathMax = Math.max; + var lt = new Point(); + var rb = new Point(); + var lb = new Point(); + var rt = new Point(); + var minTv = new Point(); + var maxTv = new Point(); + var BoundingRect = (function () { + function BoundingRect(x, y, width, height) { + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + BoundingRect.prototype.union = function (other) { + var x = mathMin(other.x, this.x); + var y = mathMin(other.y, this.y); + if (isFinite(this.x) && isFinite(this.width)) { + this.width = mathMax(other.x + other.width, this.x + this.width) - x; + } + else { + this.width = other.width; + } + if (isFinite(this.y) && isFinite(this.height)) { + this.height = mathMax(other.y + other.height, this.y + this.height) - y; + } + else { + this.height = other.height; + } + this.x = x; + this.y = y; + }; + BoundingRect.prototype.applyTransform = function (m) { + BoundingRect.applyTransform(this, this, m); + }; + BoundingRect.prototype.calculateTransform = function (b) { + var a = this; + var sx = b.width / a.width; + var sy = b.height / a.height; + var m = create$1(); + translate(m, m, [-a.x, -a.y]); + scale$1(m, m, [sx, sy]); + translate(m, m, [b.x, b.y]); + return m; + }; + BoundingRect.prototype.intersect = function (b, mtv) { + if (!b) { + return false; + } + if (!(b instanceof BoundingRect)) { + b = BoundingRect.create(b); + } + var a = this; + var ax0 = a.x; + var ax1 = a.x + a.width; + var ay0 = a.y; + var ay1 = a.y + a.height; + var bx0 = b.x; + var bx1 = b.x + b.width; + var by0 = b.y; + var by1 = b.y + b.height; + var overlap = !(ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0); + if (mtv) { + var dMin = Infinity; + var dMax = 0; + var d0 = Math.abs(ax1 - bx0); + var d1 = Math.abs(bx1 - ax0); + var d2 = Math.abs(ay1 - by0); + var d3 = Math.abs(by1 - ay0); + var dx = Math.min(d0, d1); + var dy = Math.min(d2, d3); + if (ax1 < bx0 || bx1 < ax0) { + if (dx > dMax) { + dMax = dx; + if (d0 < d1) { + Point.set(maxTv, -d0, 0); + } + else { + Point.set(maxTv, d1, 0); + } + } + } + else { + if (dx < dMin) { + dMin = dx; + if (d0 < d1) { + Point.set(minTv, d0, 0); + } + else { + Point.set(minTv, -d1, 0); + } + } + } + if (ay1 < by0 || by1 < ay0) { + if (dy > dMax) { + dMax = dy; + if (d2 < d3) { + Point.set(maxTv, 0, -d2); + } + else { + Point.set(maxTv, 0, d3); + } + } + } + else { + if (dx < dMin) { + dMin = dx; + if (d2 < d3) { + Point.set(minTv, 0, d2); + } + else { + Point.set(minTv, 0, -d3); + } + } + } + } + if (mtv) { + Point.copy(mtv, overlap ? minTv : maxTv); + } + return overlap; + }; + BoundingRect.prototype.contain = function (x, y) { + var rect = this; + return x >= rect.x + && x <= (rect.x + rect.width) + && y >= rect.y + && y <= (rect.y + rect.height); + }; + BoundingRect.prototype.clone = function () { + return new BoundingRect(this.x, this.y, this.width, this.height); + }; + BoundingRect.prototype.copy = function (other) { + BoundingRect.copy(this, other); + }; + BoundingRect.prototype.plain = function () { + return { + x: this.x, + y: this.y, + width: this.width, + height: this.height + }; + }; + BoundingRect.prototype.isFinite = function () { + return isFinite(this.x) + && isFinite(this.y) + && isFinite(this.width) + && isFinite(this.height); + }; + BoundingRect.prototype.isZero = function () { + return this.width === 0 || this.height === 0; + }; + BoundingRect.create = function (rect) { + return new BoundingRect(rect.x, rect.y, rect.width, rect.height); + }; + BoundingRect.copy = function (target, source) { + target.x = source.x; + target.y = source.y; + target.width = source.width; + target.height = source.height; + }; + BoundingRect.applyTransform = function (target, source, m) { + if (!m) { + if (target !== source) { + BoundingRect.copy(target, source); + } + return; + } + if (m[1] < 1e-5 && m[1] > -1e-5 && m[2] < 1e-5 && m[2] > -1e-5) { + var sx = m[0]; + var sy = m[3]; + var tx = m[4]; + var ty = m[5]; + target.x = source.x * sx + tx; + target.y = source.y * sy + ty; + target.width = source.width * sx; + target.height = source.height * sy; + if (target.width < 0) { + target.x += target.width; + target.width = -target.width; + } + if (target.height < 0) { + target.y += target.height; + target.height = -target.height; + } + return; + } + lt.x = lb.x = source.x; + lt.y = rt.y = source.y; + rb.x = rt.x = source.x + source.width; + rb.y = lb.y = source.y + source.height; + lt.transform(m); + rt.transform(m); + rb.transform(m); + lb.transform(m); + target.x = mathMin(lt.x, rb.x, lb.x, rt.x); + target.y = mathMin(lt.y, rb.y, lb.y, rt.y); + var maxX = mathMax(lt.x, rb.x, lb.x, rt.x); + var maxY = mathMax(lt.y, rb.y, lb.y, rt.y); + target.width = maxX - target.x; + target.height = maxY - target.y; + }; + return BoundingRect; + }()); + + var textWidthCache = {}; + function getWidth(text, font) { + font = font || DEFAULT_FONT; + var cacheOfFont = textWidthCache[font]; + if (!cacheOfFont) { + cacheOfFont = textWidthCache[font] = new LRU(500); + } + var width = cacheOfFont.get(text); + if (width == null) { + width = platformApi.measureText(text, font).width; + cacheOfFont.put(text, width); + } + return width; + } + function innerGetBoundingRect(text, font, textAlign, textBaseline) { + var width = getWidth(text, font); + var height = getLineHeight(font); + var x = adjustTextX(0, width, textAlign); + var y = adjustTextY$1(0, height, textBaseline); + var rect = new BoundingRect(x, y, width, height); + return rect; + } + function getBoundingRect(text, font, textAlign, textBaseline) { + var textLines = ((text || '') + '').split('\n'); + var len = textLines.length; + if (len === 1) { + return innerGetBoundingRect(textLines[0], font, textAlign, textBaseline); + } + else { + var uniondRect = new BoundingRect(0, 0, 0, 0); + for (var i = 0; i < textLines.length; i++) { + var rect = innerGetBoundingRect(textLines[i], font, textAlign, textBaseline); + i === 0 ? uniondRect.copy(rect) : uniondRect.union(rect); + } + return uniondRect; + } + } + function adjustTextX(x, width, textAlign) { + if (textAlign === 'right') { + x -= width; + } + else if (textAlign === 'center') { + x -= width / 2; + } + return x; + } + function adjustTextY$1(y, height, verticalAlign) { + if (verticalAlign === 'middle') { + y -= height / 2; + } + else if (verticalAlign === 'bottom') { + y -= height; + } + return y; + } + function getLineHeight(font) { + return getWidth('国', font); + } + function parsePercent(value, maxValue) { + if (typeof value === 'string') { + if (value.lastIndexOf('%') >= 0) { + return parseFloat(value) / 100 * maxValue; + } + return parseFloat(value); + } + return value; + } + function calculateTextPosition(out, opts, rect) { + var textPosition = opts.position || 'inside'; + var distance = opts.distance != null ? opts.distance : 5; + var height = rect.height; + var width = rect.width; + var halfHeight = height / 2; + var x = rect.x; + var y = rect.y; + var textAlign = 'left'; + var textVerticalAlign = 'top'; + if (textPosition instanceof Array) { + x += parsePercent(textPosition[0], rect.width); + y += parsePercent(textPosition[1], rect.height); + textAlign = null; + textVerticalAlign = null; + } + else { + switch (textPosition) { + case 'left': + x -= distance; + y += halfHeight; + textAlign = 'right'; + textVerticalAlign = 'middle'; + break; + case 'right': + x += distance + width; + y += halfHeight; + textVerticalAlign = 'middle'; + break; + case 'top': + x += width / 2; + y -= distance; + textAlign = 'center'; + textVerticalAlign = 'bottom'; + break; + case 'bottom': + x += width / 2; + y += height + distance; + textAlign = 'center'; + break; + case 'inside': + x += width / 2; + y += halfHeight; + textAlign = 'center'; + textVerticalAlign = 'middle'; + break; + case 'insideLeft': + x += distance; + y += halfHeight; + textVerticalAlign = 'middle'; + break; + case 'insideRight': + x += width - distance; + y += halfHeight; + textAlign = 'right'; + textVerticalAlign = 'middle'; + break; + case 'insideTop': + x += width / 2; + y += distance; + textAlign = 'center'; + break; + case 'insideBottom': + x += width / 2; + y += height - distance; + textAlign = 'center'; + textVerticalAlign = 'bottom'; + break; + case 'insideTopLeft': + x += distance; + y += distance; + break; + case 'insideTopRight': + x += width - distance; + y += distance; + textAlign = 'right'; + break; + case 'insideBottomLeft': + x += distance; + y += height - distance; + textVerticalAlign = 'bottom'; + break; + case 'insideBottomRight': + x += width - distance; + y += height - distance; + textAlign = 'right'; + textVerticalAlign = 'bottom'; + break; + } + } + out = out || {}; + out.x = x; + out.y = y; + out.align = textAlign; + out.verticalAlign = textVerticalAlign; + return out; + } + + var PRESERVED_NORMAL_STATE = '__zr_normal__'; + var PRIMARY_STATES_KEYS = TRANSFORMABLE_PROPS.concat(['ignore']); + var DEFAULT_ANIMATABLE_MAP = reduce(TRANSFORMABLE_PROPS, function (obj, key) { + obj[key] = true; + return obj; + }, { ignore: false }); + var tmpTextPosCalcRes = {}; + var tmpBoundingRect = new BoundingRect(0, 0, 0, 0); + var Element = (function () { + function Element(props) { + this.id = guid(); + this.animators = []; + this.currentStates = []; + this.states = {}; + this._init(props); + } + Element.prototype._init = function (props) { + this.attr(props); + }; + Element.prototype.drift = function (dx, dy, e) { + switch (this.draggable) { + case 'horizontal': + dy = 0; + break; + case 'vertical': + dx = 0; + break; + } + var m = this.transform; + if (!m) { + m = this.transform = [1, 0, 0, 1, 0, 0]; + } + m[4] += dx; + m[5] += dy; + this.decomposeTransform(); + this.markRedraw(); + }; + Element.prototype.beforeUpdate = function () { }; + Element.prototype.afterUpdate = function () { }; + Element.prototype.update = function () { + this.updateTransform(); + if (this.__dirty) { + this.updateInnerText(); + } + }; + Element.prototype.updateInnerText = function (forceUpdate) { + var textEl = this._textContent; + if (textEl && (!textEl.ignore || forceUpdate)) { + if (!this.textConfig) { + this.textConfig = {}; + } + var textConfig = this.textConfig; + var isLocal = textConfig.local; + var innerTransformable = textEl.innerTransformable; + var textAlign = void 0; + var textVerticalAlign = void 0; + var textStyleChanged = false; + innerTransformable.parent = isLocal ? this : null; + var innerOrigin = false; + innerTransformable.copyTransform(textEl); + if (textConfig.position != null) { + var layoutRect = tmpBoundingRect; + if (textConfig.layoutRect) { + layoutRect.copy(textConfig.layoutRect); + } + else { + layoutRect.copy(this.getBoundingRect()); + } + if (!isLocal) { + layoutRect.applyTransform(this.transform); + } + if (this.calculateTextPosition) { + this.calculateTextPosition(tmpTextPosCalcRes, textConfig, layoutRect); + } + else { + calculateTextPosition(tmpTextPosCalcRes, textConfig, layoutRect); + } + innerTransformable.x = tmpTextPosCalcRes.x; + innerTransformable.y = tmpTextPosCalcRes.y; + textAlign = tmpTextPosCalcRes.align; + textVerticalAlign = tmpTextPosCalcRes.verticalAlign; + var textOrigin = textConfig.origin; + if (textOrigin && textConfig.rotation != null) { + var relOriginX = void 0; + var relOriginY = void 0; + if (textOrigin === 'center') { + relOriginX = layoutRect.width * 0.5; + relOriginY = layoutRect.height * 0.5; + } + else { + relOriginX = parsePercent(textOrigin[0], layoutRect.width); + relOriginY = parsePercent(textOrigin[1], layoutRect.height); + } + innerOrigin = true; + innerTransformable.originX = -innerTransformable.x + relOriginX + (isLocal ? 0 : layoutRect.x); + innerTransformable.originY = -innerTransformable.y + relOriginY + (isLocal ? 0 : layoutRect.y); + } + } + if (textConfig.rotation != null) { + innerTransformable.rotation = textConfig.rotation; + } + var textOffset = textConfig.offset; + if (textOffset) { + innerTransformable.x += textOffset[0]; + innerTransformable.y += textOffset[1]; + if (!innerOrigin) { + innerTransformable.originX = -textOffset[0]; + innerTransformable.originY = -textOffset[1]; + } + } + var isInside = textConfig.inside == null + ? (typeof textConfig.position === 'string' && textConfig.position.indexOf('inside') >= 0) + : textConfig.inside; + var innerTextDefaultStyle = this._innerTextDefaultStyle || (this._innerTextDefaultStyle = {}); + var textFill = void 0; + var textStroke = void 0; + var autoStroke = void 0; + if (isInside && this.canBeInsideText()) { + textFill = textConfig.insideFill; + textStroke = textConfig.insideStroke; + if (textFill == null || textFill === 'auto') { + textFill = this.getInsideTextFill(); + } + if (textStroke == null || textStroke === 'auto') { + textStroke = this.getInsideTextStroke(textFill); + autoStroke = true; + } + } + else { + textFill = textConfig.outsideFill; + textStroke = textConfig.outsideStroke; + if (textFill == null || textFill === 'auto') { + textFill = this.getOutsideFill(); + } + if (textStroke == null || textStroke === 'auto') { + textStroke = this.getOutsideStroke(textFill); + autoStroke = true; + } + } + textFill = textFill || '#000'; + if (textFill !== innerTextDefaultStyle.fill + || textStroke !== innerTextDefaultStyle.stroke + || autoStroke !== innerTextDefaultStyle.autoStroke + || textAlign !== innerTextDefaultStyle.align + || textVerticalAlign !== innerTextDefaultStyle.verticalAlign) { + textStyleChanged = true; + innerTextDefaultStyle.fill = textFill; + innerTextDefaultStyle.stroke = textStroke; + innerTextDefaultStyle.autoStroke = autoStroke; + innerTextDefaultStyle.align = textAlign; + innerTextDefaultStyle.verticalAlign = textVerticalAlign; + textEl.setDefaultTextStyle(innerTextDefaultStyle); + } + textEl.__dirty |= REDRAW_BIT; + if (textStyleChanged) { + textEl.dirtyStyle(true); + } + } + }; + Element.prototype.canBeInsideText = function () { + return true; + }; + Element.prototype.getInsideTextFill = function () { + return '#fff'; + }; + Element.prototype.getInsideTextStroke = function (textFill) { + return '#000'; + }; + Element.prototype.getOutsideFill = function () { + return this.__zr && this.__zr.isDarkMode() ? LIGHT_LABEL_COLOR : DARK_LABEL_COLOR; + }; + Element.prototype.getOutsideStroke = function (textFill) { + var backgroundColor = this.__zr && this.__zr.getBackgroundColor(); + var colorArr = typeof backgroundColor === 'string' && parse(backgroundColor); + if (!colorArr) { + colorArr = [255, 255, 255, 1]; + } + var alpha = colorArr[3]; + var isDark = this.__zr.isDarkMode(); + for (var i = 0; i < 3; i++) { + colorArr[i] = colorArr[i] * alpha + (isDark ? 0 : 255) * (1 - alpha); + } + colorArr[3] = 1; + return stringify(colorArr, 'rgba'); + }; + Element.prototype.traverse = function (cb, context) { }; + Element.prototype.attrKV = function (key, value) { + if (key === 'textConfig') { + this.setTextConfig(value); + } + else if (key === 'textContent') { + this.setTextContent(value); + } + else if (key === 'clipPath') { + this.setClipPath(value); + } + else if (key === 'extra') { + this.extra = this.extra || {}; + extend(this.extra, value); + } + else { + this[key] = value; + } + }; + Element.prototype.hide = function () { + this.ignore = true; + this.markRedraw(); + }; + Element.prototype.show = function () { + this.ignore = false; + this.markRedraw(); + }; + Element.prototype.attr = function (keyOrObj, value) { + if (typeof keyOrObj === 'string') { + this.attrKV(keyOrObj, value); + } + else if (isObject(keyOrObj)) { + var obj = keyOrObj; + var keysArr = keys(obj); + for (var i = 0; i < keysArr.length; i++) { + var key = keysArr[i]; + this.attrKV(key, keyOrObj[key]); + } + } + this.markRedraw(); + return this; + }; + Element.prototype.saveCurrentToNormalState = function (toState) { + this._innerSaveToNormal(toState); + var normalState = this._normalState; + for (var i = 0; i < this.animators.length; i++) { + var animator = this.animators[i]; + var fromStateTransition = animator.__fromStateTransition; + if (animator.getLoop() || fromStateTransition && fromStateTransition !== PRESERVED_NORMAL_STATE) { + continue; + } + var targetName = animator.targetName; + var target = targetName + ? normalState[targetName] : normalState; + animator.saveTo(target); + } + }; + Element.prototype._innerSaveToNormal = function (toState) { + var normalState = this._normalState; + if (!normalState) { + normalState = this._normalState = {}; + } + if (toState.textConfig && !normalState.textConfig) { + normalState.textConfig = this.textConfig; + } + this._savePrimaryToNormal(toState, normalState, PRIMARY_STATES_KEYS); + }; + Element.prototype._savePrimaryToNormal = function (toState, normalState, primaryKeys) { + for (var i = 0; i < primaryKeys.length; i++) { + var key = primaryKeys[i]; + if (toState[key] != null && !(key in normalState)) { + normalState[key] = this[key]; + } + } + }; + Element.prototype.hasState = function () { + return this.currentStates.length > 0; + }; + Element.prototype.getState = function (name) { + return this.states[name]; + }; + Element.prototype.ensureState = function (name) { + var states = this.states; + if (!states[name]) { + states[name] = {}; + } + return states[name]; + }; + Element.prototype.clearStates = function (noAnimation) { + this.useState(PRESERVED_NORMAL_STATE, false, noAnimation); + }; + Element.prototype.useState = function (stateName, keepCurrentStates, noAnimation, forceUseHoverLayer) { + var toNormalState = stateName === PRESERVED_NORMAL_STATE; + var hasStates = this.hasState(); + if (!hasStates && toNormalState) { + return; + } + var currentStates = this.currentStates; + var animationCfg = this.stateTransition; + if (indexOf(currentStates, stateName) >= 0 && (keepCurrentStates || currentStates.length === 1)) { + return; + } + var state; + if (this.stateProxy && !toNormalState) { + state = this.stateProxy(stateName); + } + if (!state) { + state = (this.states && this.states[stateName]); + } + if (!state && !toNormalState) { + logError("State " + stateName + " not exists."); + return; + } + if (!toNormalState) { + this.saveCurrentToNormalState(state); + } + var useHoverLayer = !!((state && state.hoverLayer) || forceUseHoverLayer); + if (useHoverLayer) { + this._toggleHoverLayerFlag(true); + } + this._applyStateObj(stateName, state, this._normalState, keepCurrentStates, !noAnimation && !this.__inHover && animationCfg && animationCfg.duration > 0, animationCfg); + var textContent = this._textContent; + var textGuide = this._textGuide; + if (textContent) { + textContent.useState(stateName, keepCurrentStates, noAnimation, useHoverLayer); + } + if (textGuide) { + textGuide.useState(stateName, keepCurrentStates, noAnimation, useHoverLayer); + } + if (toNormalState) { + this.currentStates = []; + this._normalState = {}; + } + else { + if (!keepCurrentStates) { + this.currentStates = [stateName]; + } + else { + this.currentStates.push(stateName); + } + } + this._updateAnimationTargets(); + this.markRedraw(); + if (!useHoverLayer && this.__inHover) { + this._toggleHoverLayerFlag(false); + this.__dirty &= ~REDRAW_BIT; + } + return state; + }; + Element.prototype.useStates = function (states, noAnimation, forceUseHoverLayer) { + if (!states.length) { + this.clearStates(); + } + else { + var stateObjects = []; + var currentStates = this.currentStates; + var len = states.length; + var notChange = len === currentStates.length; + if (notChange) { + for (var i = 0; i < len; i++) { + if (states[i] !== currentStates[i]) { + notChange = false; + break; + } + } + } + if (notChange) { + return; + } + for (var i = 0; i < len; i++) { + var stateName = states[i]; + var stateObj = void 0; + if (this.stateProxy) { + stateObj = this.stateProxy(stateName, states); + } + if (!stateObj) { + stateObj = this.states[stateName]; + } + if (stateObj) { + stateObjects.push(stateObj); + } + } + var lastStateObj = stateObjects[len - 1]; + var useHoverLayer = !!((lastStateObj && lastStateObj.hoverLayer) || forceUseHoverLayer); + if (useHoverLayer) { + this._toggleHoverLayerFlag(true); + } + var mergedState = this._mergeStates(stateObjects); + var animationCfg = this.stateTransition; + this.saveCurrentToNormalState(mergedState); + this._applyStateObj(states.join(','), mergedState, this._normalState, false, !noAnimation && !this.__inHover && animationCfg && animationCfg.duration > 0, animationCfg); + var textContent = this._textContent; + var textGuide = this._textGuide; + if (textContent) { + textContent.useStates(states, noAnimation, useHoverLayer); + } + if (textGuide) { + textGuide.useStates(states, noAnimation, useHoverLayer); + } + this._updateAnimationTargets(); + this.currentStates = states.slice(); + this.markRedraw(); + if (!useHoverLayer && this.__inHover) { + this._toggleHoverLayerFlag(false); + this.__dirty &= ~REDRAW_BIT; + } + } + }; + Element.prototype._updateAnimationTargets = function () { + for (var i = 0; i < this.animators.length; i++) { + var animator = this.animators[i]; + if (animator.targetName) { + animator.changeTarget(this[animator.targetName]); + } + } + }; + Element.prototype.removeState = function (state) { + var idx = indexOf(this.currentStates, state); + if (idx >= 0) { + var currentStates = this.currentStates.slice(); + currentStates.splice(idx, 1); + this.useStates(currentStates); + } + }; + Element.prototype.replaceState = function (oldState, newState, forceAdd) { + var currentStates = this.currentStates.slice(); + var idx = indexOf(currentStates, oldState); + var newStateExists = indexOf(currentStates, newState) >= 0; + if (idx >= 0) { + if (!newStateExists) { + currentStates[idx] = newState; + } + else { + currentStates.splice(idx, 1); + } + } + else if (forceAdd && !newStateExists) { + currentStates.push(newState); + } + this.useStates(currentStates); + }; + Element.prototype.toggleState = function (state, enable) { + if (enable) { + this.useState(state, true); + } + else { + this.removeState(state); + } + }; + Element.prototype._mergeStates = function (states) { + var mergedState = {}; + var mergedTextConfig; + for (var i = 0; i < states.length; i++) { + var state = states[i]; + extend(mergedState, state); + if (state.textConfig) { + mergedTextConfig = mergedTextConfig || {}; + extend(mergedTextConfig, state.textConfig); + } + } + if (mergedTextConfig) { + mergedState.textConfig = mergedTextConfig; + } + return mergedState; + }; + Element.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) { + var needsRestoreToNormal = !(state && keepCurrentStates); + if (state && state.textConfig) { + this.textConfig = extend({}, keepCurrentStates ? this.textConfig : normalState.textConfig); + extend(this.textConfig, state.textConfig); + } + else if (needsRestoreToNormal) { + if (normalState.textConfig) { + this.textConfig = normalState.textConfig; + } + } + var transitionTarget = {}; + var hasTransition = false; + for (var i = 0; i < PRIMARY_STATES_KEYS.length; i++) { + var key = PRIMARY_STATES_KEYS[i]; + var propNeedsTransition = transition && DEFAULT_ANIMATABLE_MAP[key]; + if (state && state[key] != null) { + if (propNeedsTransition) { + hasTransition = true; + transitionTarget[key] = state[key]; + } + else { + this[key] = state[key]; + } + } + else if (needsRestoreToNormal) { + if (normalState[key] != null) { + if (propNeedsTransition) { + hasTransition = true; + transitionTarget[key] = normalState[key]; + } + else { + this[key] = normalState[key]; + } + } + } + } + if (!transition) { + for (var i = 0; i < this.animators.length; i++) { + var animator = this.animators[i]; + var targetName = animator.targetName; + if (!animator.getLoop()) { + animator.__changeFinalValue(targetName + ? (state || normalState)[targetName] + : (state || normalState)); + } + } + } + if (hasTransition) { + this._transitionState(stateName, transitionTarget, animationCfg); + } + }; + Element.prototype._attachComponent = function (componentEl) { + if (componentEl.__zr && !componentEl.__hostTarget) { + if ("development" !== 'production') { + throw new Error('Text element has been added to zrender.'); + } + return; + } + if (componentEl === this) { + if ("development" !== 'production') { + throw new Error('Recursive component attachment.'); + } + return; + } + var zr = this.__zr; + if (zr) { + componentEl.addSelfToZr(zr); + } + componentEl.__zr = zr; + componentEl.__hostTarget = this; + }; + Element.prototype._detachComponent = function (componentEl) { + if (componentEl.__zr) { + componentEl.removeSelfFromZr(componentEl.__zr); + } + componentEl.__zr = null; + componentEl.__hostTarget = null; + }; + Element.prototype.getClipPath = function () { + return this._clipPath; + }; + Element.prototype.setClipPath = function (clipPath) { + if (this._clipPath && this._clipPath !== clipPath) { + this.removeClipPath(); + } + this._attachComponent(clipPath); + this._clipPath = clipPath; + this.markRedraw(); + }; + Element.prototype.removeClipPath = function () { + var clipPath = this._clipPath; + if (clipPath) { + this._detachComponent(clipPath); + this._clipPath = null; + this.markRedraw(); + } + }; + Element.prototype.getTextContent = function () { + return this._textContent; + }; + Element.prototype.setTextContent = function (textEl) { + var previousTextContent = this._textContent; + if (previousTextContent === textEl) { + return; + } + if (previousTextContent && previousTextContent !== textEl) { + this.removeTextContent(); + } + if ("development" !== 'production') { + if (textEl.__zr && !textEl.__hostTarget) { + throw new Error('Text element has been added to zrender.'); + } + } + textEl.innerTransformable = new Transformable(); + this._attachComponent(textEl); + this._textContent = textEl; + this.markRedraw(); + }; + Element.prototype.setTextConfig = function (cfg) { + if (!this.textConfig) { + this.textConfig = {}; + } + extend(this.textConfig, cfg); + this.markRedraw(); + }; + Element.prototype.removeTextConfig = function () { + this.textConfig = null; + this.markRedraw(); + }; + Element.prototype.removeTextContent = function () { + var textEl = this._textContent; + if (textEl) { + textEl.innerTransformable = null; + this._detachComponent(textEl); + this._textContent = null; + this._innerTextDefaultStyle = null; + this.markRedraw(); + } + }; + Element.prototype.getTextGuideLine = function () { + return this._textGuide; + }; + Element.prototype.setTextGuideLine = function (guideLine) { + if (this._textGuide && this._textGuide !== guideLine) { + this.removeTextGuideLine(); + } + this._attachComponent(guideLine); + this._textGuide = guideLine; + this.markRedraw(); + }; + Element.prototype.removeTextGuideLine = function () { + var textGuide = this._textGuide; + if (textGuide) { + this._detachComponent(textGuide); + this._textGuide = null; + this.markRedraw(); + } + }; + Element.prototype.markRedraw = function () { + this.__dirty |= REDRAW_BIT; + var zr = this.__zr; + if (zr) { + if (this.__inHover) { + zr.refreshHover(); + } + else { + zr.refresh(); + } + } + if (this.__hostTarget) { + this.__hostTarget.markRedraw(); + } + }; + Element.prototype.dirty = function () { + this.markRedraw(); + }; + Element.prototype._toggleHoverLayerFlag = function (inHover) { + this.__inHover = inHover; + var textContent = this._textContent; + var textGuide = this._textGuide; + if (textContent) { + textContent.__inHover = inHover; + } + if (textGuide) { + textGuide.__inHover = inHover; + } + }; + Element.prototype.addSelfToZr = function (zr) { + if (this.__zr === zr) { + return; + } + this.__zr = zr; + var animators = this.animators; + if (animators) { + for (var i = 0; i < animators.length; i++) { + zr.animation.addAnimator(animators[i]); + } + } + if (this._clipPath) { + this._clipPath.addSelfToZr(zr); + } + if (this._textContent) { + this._textContent.addSelfToZr(zr); + } + if (this._textGuide) { + this._textGuide.addSelfToZr(zr); + } + }; + Element.prototype.removeSelfFromZr = function (zr) { + if (!this.__zr) { + return; + } + this.__zr = null; + var animators = this.animators; + if (animators) { + for (var i = 0; i < animators.length; i++) { + zr.animation.removeAnimator(animators[i]); + } + } + if (this._clipPath) { + this._clipPath.removeSelfFromZr(zr); + } + if (this._textContent) { + this._textContent.removeSelfFromZr(zr); + } + if (this._textGuide) { + this._textGuide.removeSelfFromZr(zr); + } + }; + Element.prototype.animate = function (key, loop, allowDiscreteAnimation) { + var target = key ? this[key] : this; + if ("development" !== 'production') { + if (!target) { + logError('Property "' + + key + + '" is not existed in element ' + + this.id); + return; + } + } + var animator = new Animator(target, loop, allowDiscreteAnimation); + key && (animator.targetName = key); + this.addAnimator(animator, key); + return animator; + }; + Element.prototype.addAnimator = function (animator, key) { + var zr = this.__zr; + var el = this; + animator.during(function () { + el.updateDuringAnimation(key); + }).done(function () { + var animators = el.animators; + var idx = indexOf(animators, animator); + if (idx >= 0) { + animators.splice(idx, 1); + } + }); + this.animators.push(animator); + if (zr) { + zr.animation.addAnimator(animator); + } + zr && zr.wakeUp(); + }; + Element.prototype.updateDuringAnimation = function (key) { + this.markRedraw(); + }; + Element.prototype.stopAnimation = function (scope, forwardToLast) { + var animators = this.animators; + var len = animators.length; + var leftAnimators = []; + for (var i = 0; i < len; i++) { + var animator = animators[i]; + if (!scope || scope === animator.scope) { + animator.stop(forwardToLast); + } + else { + leftAnimators.push(animator); + } + } + this.animators = leftAnimators; + return this; + }; + Element.prototype.animateTo = function (target, cfg, animationProps) { + animateTo(this, target, cfg, animationProps); + }; + Element.prototype.animateFrom = function (target, cfg, animationProps) { + animateTo(this, target, cfg, animationProps, true); + }; + Element.prototype._transitionState = function (stateName, target, cfg, animationProps) { + var animators = animateTo(this, target, cfg, animationProps); + for (var i = 0; i < animators.length; i++) { + animators[i].__fromStateTransition = stateName; + } + }; + Element.prototype.getBoundingRect = function () { + return null; + }; + Element.prototype.getPaintRect = function () { + return null; + }; + Element.initDefaultProps = (function () { + var elProto = Element.prototype; + elProto.type = 'element'; + elProto.name = ''; + elProto.ignore = + elProto.silent = + elProto.isGroup = + elProto.draggable = + elProto.dragging = + elProto.ignoreClip = + elProto.__inHover = false; + elProto.__dirty = REDRAW_BIT; + var logs = {}; + function logDeprecatedError(key, xKey, yKey) { + if (!logs[key + xKey + yKey]) { + console.warn("DEPRECATED: '" + key + "' has been deprecated. use '" + xKey + "', '" + yKey + "' instead"); + logs[key + xKey + yKey] = true; + } + } + function createLegacyProperty(key, privateKey, xKey, yKey) { + Object.defineProperty(elProto, key, { + get: function () { + if ("development" !== 'production') { + logDeprecatedError(key, xKey, yKey); + } + if (!this[privateKey]) { + var pos = this[privateKey] = []; + enhanceArray(this, pos); + } + return this[privateKey]; + }, + set: function (pos) { + if ("development" !== 'production') { + logDeprecatedError(key, xKey, yKey); + } + this[xKey] = pos[0]; + this[yKey] = pos[1]; + this[privateKey] = pos; + enhanceArray(this, pos); + } + }); + function enhanceArray(self, pos) { + Object.defineProperty(pos, 0, { + get: function () { + return self[xKey]; + }, + set: function (val) { + self[xKey] = val; + } + }); + Object.defineProperty(pos, 1, { + get: function () { + return self[yKey]; + }, + set: function (val) { + self[yKey] = val; + } + }); + } + } + if (Object.defineProperty) { + createLegacyProperty('position', '_legacyPos', 'x', 'y'); + createLegacyProperty('scale', '_legacyScale', 'scaleX', 'scaleY'); + createLegacyProperty('origin', '_legacyOrigin', 'originX', 'originY'); + } + })(); + return Element; + }()); + mixin(Element, Eventful); + mixin(Element, Transformable); + function animateTo(animatable, target, cfg, animationProps, reverse) { + cfg = cfg || {}; + var animators = []; + animateToShallow(animatable, '', animatable, target, cfg, animationProps, animators, reverse); + var finishCount = animators.length; + var doneHappened = false; + var cfgDone = cfg.done; + var cfgAborted = cfg.aborted; + var doneCb = function () { + doneHappened = true; + finishCount--; + if (finishCount <= 0) { + doneHappened + ? (cfgDone && cfgDone()) + : (cfgAborted && cfgAborted()); + } + }; + var abortedCb = function () { + finishCount--; + if (finishCount <= 0) { + doneHappened + ? (cfgDone && cfgDone()) + : (cfgAborted && cfgAborted()); + } + }; + if (!finishCount) { + cfgDone && cfgDone(); + } + if (animators.length > 0 && cfg.during) { + animators[0].during(function (target, percent) { + cfg.during(percent); + }); + } + for (var i = 0; i < animators.length; i++) { + var animator = animators[i]; + if (doneCb) { + animator.done(doneCb); + } + if (abortedCb) { + animator.aborted(abortedCb); + } + if (cfg.force) { + animator.duration(cfg.duration); + } + animator.start(cfg.easing); + } + return animators; + } + function copyArrShallow(source, target, len) { + for (var i = 0; i < len; i++) { + source[i] = target[i]; + } + } + function is2DArray(value) { + return isArrayLike(value[0]); + } + function copyValue(target, source, key) { + if (isArrayLike(source[key])) { + if (!isArrayLike(target[key])) { + target[key] = []; + } + if (isTypedArray(source[key])) { + var len = source[key].length; + if (target[key].length !== len) { + target[key] = new (source[key].constructor)(len); + copyArrShallow(target[key], source[key], len); + } + } + else { + var sourceArr = source[key]; + var targetArr = target[key]; + var len0 = sourceArr.length; + if (is2DArray(sourceArr)) { + var len1 = sourceArr[0].length; + for (var i = 0; i < len0; i++) { + if (!targetArr[i]) { + targetArr[i] = Array.prototype.slice.call(sourceArr[i]); + } + else { + copyArrShallow(targetArr[i], sourceArr[i], len1); + } + } + } + else { + copyArrShallow(targetArr, sourceArr, len0); + } + targetArr.length = sourceArr.length; + } + } + else { + target[key] = source[key]; + } + } + function isValueSame(val1, val2) { + return val1 === val2 + || isArrayLike(val1) && isArrayLike(val2) && is1DArraySame(val1, val2); + } + function is1DArraySame(arr0, arr1) { + var len = arr0.length; + if (len !== arr1.length) { + return false; + } + for (var i = 0; i < len; i++) { + if (arr0[i] !== arr1[i]) { + return false; + } + } + return true; + } + function animateToShallow(animatable, topKey, animateObj, target, cfg, animationProps, animators, reverse) { + var targetKeys = keys(target); + var duration = cfg.duration; + var delay = cfg.delay; + var additive = cfg.additive; + var setToFinal = cfg.setToFinal; + var animateAll = !isObject(animationProps); + var existsAnimators = animatable.animators; + var animationKeys = []; + for (var k = 0; k < targetKeys.length; k++) { + var innerKey = targetKeys[k]; + var targetVal = target[innerKey]; + if (targetVal != null && animateObj[innerKey] != null + && (animateAll || animationProps[innerKey])) { + if (isObject(targetVal) + && !isArrayLike(targetVal) + && !isGradientObject(targetVal)) { + if (topKey) { + if (!reverse) { + animateObj[innerKey] = targetVal; + animatable.updateDuringAnimation(topKey); + } + continue; + } + animateToShallow(animatable, innerKey, animateObj[innerKey], targetVal, cfg, animationProps && animationProps[innerKey], animators, reverse); + } + else { + animationKeys.push(innerKey); + } + } + else if (!reverse) { + animateObj[innerKey] = targetVal; + animatable.updateDuringAnimation(topKey); + animationKeys.push(innerKey); + } + } + var keyLen = animationKeys.length; + if (!additive && keyLen) { + for (var i = 0; i < existsAnimators.length; i++) { + var animator = existsAnimators[i]; + if (animator.targetName === topKey) { + var allAborted = animator.stopTracks(animationKeys); + if (allAborted) { + var idx = indexOf(existsAnimators, animator); + existsAnimators.splice(idx, 1); + } + } + } + } + if (!cfg.force) { + animationKeys = filter(animationKeys, function (key) { return !isValueSame(target[key], animateObj[key]); }); + keyLen = animationKeys.length; + } + if (keyLen > 0 + || (cfg.force && !animators.length)) { + var revertedSource = void 0; + var reversedTarget = void 0; + var sourceClone = void 0; + if (reverse) { + reversedTarget = {}; + if (setToFinal) { + revertedSource = {}; + } + for (var i = 0; i < keyLen; i++) { + var innerKey = animationKeys[i]; + reversedTarget[innerKey] = animateObj[innerKey]; + if (setToFinal) { + revertedSource[innerKey] = target[innerKey]; + } + else { + animateObj[innerKey] = target[innerKey]; + } + } + } + else if (setToFinal) { + sourceClone = {}; + for (var i = 0; i < keyLen; i++) { + var innerKey = animationKeys[i]; + sourceClone[innerKey] = cloneValue(animateObj[innerKey]); + copyValue(animateObj, target, innerKey); + } + } + var animator = new Animator(animateObj, false, false, additive ? filter(existsAnimators, function (animator) { return animator.targetName === topKey; }) : null); + animator.targetName = topKey; + if (cfg.scope) { + animator.scope = cfg.scope; + } + if (setToFinal && revertedSource) { + animator.whenWithKeys(0, revertedSource, animationKeys); + } + if (sourceClone) { + animator.whenWithKeys(0, sourceClone, animationKeys); + } + animator.whenWithKeys(duration == null ? 500 : duration, reverse ? reversedTarget : target, animationKeys).delay(delay || 0); + animatable.addAnimator(animator, topKey); + animators.push(animator); + } + } + + var Group = (function (_super) { + __extends(Group, _super); + function Group(opts) { + var _this = _super.call(this) || this; + _this.isGroup = true; + _this._children = []; + _this.attr(opts); + return _this; + } + Group.prototype.childrenRef = function () { + return this._children; + }; + Group.prototype.children = function () { + return this._children.slice(); + }; + Group.prototype.childAt = function (idx) { + return this._children[idx]; + }; + Group.prototype.childOfName = function (name) { + var children = this._children; + for (var i = 0; i < children.length; i++) { + if (children[i].name === name) { + return children[i]; + } + } + }; + Group.prototype.childCount = function () { + return this._children.length; + }; + Group.prototype.add = function (child) { + if (child) { + if (child !== this && child.parent !== this) { + this._children.push(child); + this._doAdd(child); + } + if ("development" !== 'production') { + if (child.__hostTarget) { + throw 'This elemenet has been used as an attachment'; + } + } + } + return this; + }; + Group.prototype.addBefore = function (child, nextSibling) { + if (child && child !== this && child.parent !== this + && nextSibling && nextSibling.parent === this) { + var children = this._children; + var idx = children.indexOf(nextSibling); + if (idx >= 0) { + children.splice(idx, 0, child); + this._doAdd(child); + } + } + return this; + }; + Group.prototype.replace = function (oldChild, newChild) { + var idx = indexOf(this._children, oldChild); + if (idx >= 0) { + this.replaceAt(newChild, idx); + } + return this; + }; + Group.prototype.replaceAt = function (child, index) { + var children = this._children; + var old = children[index]; + if (child && child !== this && child.parent !== this && child !== old) { + children[index] = child; + old.parent = null; + var zr = this.__zr; + if (zr) { + old.removeSelfFromZr(zr); + } + this._doAdd(child); + } + return this; + }; + Group.prototype._doAdd = function (child) { + if (child.parent) { + child.parent.remove(child); + } + child.parent = this; + var zr = this.__zr; + if (zr && zr !== child.__zr) { + child.addSelfToZr(zr); + } + zr && zr.refresh(); + }; + Group.prototype.remove = function (child) { + var zr = this.__zr; + var children = this._children; + var idx = indexOf(children, child); + if (idx < 0) { + return this; + } + children.splice(idx, 1); + child.parent = null; + if (zr) { + child.removeSelfFromZr(zr); + } + zr && zr.refresh(); + return this; + }; + Group.prototype.removeAll = function () { + var children = this._children; + var zr = this.__zr; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (zr) { + child.removeSelfFromZr(zr); + } + child.parent = null; + } + children.length = 0; + return this; + }; + Group.prototype.eachChild = function (cb, context) { + var children = this._children; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + cb.call(context, child, i); + } + return this; + }; + Group.prototype.traverse = function (cb, context) { + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + var stopped = cb.call(context, child); + if (child.isGroup && !stopped) { + child.traverse(cb, context); + } + } + return this; + }; + Group.prototype.addSelfToZr = function (zr) { + _super.prototype.addSelfToZr.call(this, zr); + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + child.addSelfToZr(zr); + } + }; + Group.prototype.removeSelfFromZr = function (zr) { + _super.prototype.removeSelfFromZr.call(this, zr); + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + child.removeSelfFromZr(zr); + } + }; + Group.prototype.getBoundingRect = function (includeChildren) { + var tmpRect = new BoundingRect(0, 0, 0, 0); + var children = includeChildren || this._children; + var tmpMat = []; + var rect = null; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (child.ignore || child.invisible) { + continue; + } + var childRect = child.getBoundingRect(); + var transform = child.getLocalTransform(tmpMat); + if (transform) { + BoundingRect.applyTransform(tmpRect, childRect, transform); + rect = rect || tmpRect.clone(); + rect.union(tmpRect); + } + else { + rect = rect || childRect.clone(); + rect.union(childRect); + } + } + return rect || tmpRect; + }; + return Group; + }(Element)); + Group.prototype.type = 'group'; + + /*! + * ZRender, a high performance 2d drawing library. + * + * Copyright (c) 2013, Baidu Inc. + * All rights reserved. + * + * LICENSE + * https://github.com/ecomfe/zrender/blob/master/LICENSE.txt + */ + var painterCtors = {}; + var instances = {}; + function delInstance(id) { + delete instances[id]; + } + function isDarkMode(backgroundColor) { + if (!backgroundColor) { + return false; + } + if (typeof backgroundColor === 'string') { + return lum(backgroundColor, 1) < DARK_MODE_THRESHOLD; + } + else if (backgroundColor.colorStops) { + var colorStops = backgroundColor.colorStops; + var totalLum = 0; + var len = colorStops.length; + for (var i = 0; i < len; i++) { + totalLum += lum(colorStops[i].color, 1); + } + totalLum /= len; + return totalLum < DARK_MODE_THRESHOLD; + } + return false; + } + var ZRender = (function () { + function ZRender(id, dom, opts) { + var _this = this; + this._sleepAfterStill = 10; + this._stillFrameAccum = 0; + this._needsRefresh = true; + this._needsRefreshHover = true; + this._darkMode = false; + opts = opts || {}; + this.dom = dom; + this.id = id; + var storage = new Storage(); + var rendererType = opts.renderer || 'canvas'; + if (!painterCtors[rendererType]) { + rendererType = keys(painterCtors)[0]; + } + if ("development" !== 'production') { + if (!painterCtors[rendererType]) { + throw new Error("Renderer '" + rendererType + "' is not imported. Please import it first."); + } + } + opts.useDirtyRect = opts.useDirtyRect == null + ? false + : opts.useDirtyRect; + var painter = new painterCtors[rendererType](dom, storage, opts, id); + var ssrMode = opts.ssr || painter.ssrOnly; + this.storage = storage; + this.painter = painter; + var handerProxy = (!env.node && !env.worker && !ssrMode) + ? new HandlerDomProxy(painter.getViewportRoot(), painter.root) + : null; + this.handler = new Handler(storage, painter, handerProxy, painter.root); + this.animation = new Animation({ + stage: { + update: ssrMode ? null : function () { return _this._flush(true); } + } + }); + if (!ssrMode) { + this.animation.start(); + } + } + ZRender.prototype.add = function (el) { + if (!el) { + return; + } + this.storage.addRoot(el); + el.addSelfToZr(this); + this.refresh(); + }; + ZRender.prototype.remove = function (el) { + if (!el) { + return; + } + this.storage.delRoot(el); + el.removeSelfFromZr(this); + this.refresh(); + }; + ZRender.prototype.configLayer = function (zLevel, config) { + if (this.painter.configLayer) { + this.painter.configLayer(zLevel, config); + } + this.refresh(); + }; + ZRender.prototype.setBackgroundColor = function (backgroundColor) { + if (this.painter.setBackgroundColor) { + this.painter.setBackgroundColor(backgroundColor); + } + this.refresh(); + this._backgroundColor = backgroundColor; + this._darkMode = isDarkMode(backgroundColor); + }; + ZRender.prototype.getBackgroundColor = function () { + return this._backgroundColor; + }; + ZRender.prototype.setDarkMode = function (darkMode) { + this._darkMode = darkMode; + }; + ZRender.prototype.isDarkMode = function () { + return this._darkMode; + }; + ZRender.prototype.refreshImmediately = function (fromInside) { + if (!fromInside) { + this.animation.update(true); + } + this._needsRefresh = false; + this.painter.refresh(); + this._needsRefresh = false; + }; + ZRender.prototype.refresh = function () { + this._needsRefresh = true; + this.animation.start(); + }; + ZRender.prototype.flush = function () { + this._flush(false); + }; + ZRender.prototype._flush = function (fromInside) { + var triggerRendered; + var start = getTime(); + if (this._needsRefresh) { + triggerRendered = true; + this.refreshImmediately(fromInside); + } + if (this._needsRefreshHover) { + triggerRendered = true; + this.refreshHoverImmediately(); + } + var end = getTime(); + if (triggerRendered) { + this._stillFrameAccum = 0; + this.trigger('rendered', { + elapsedTime: end - start + }); + } + else if (this._sleepAfterStill > 0) { + this._stillFrameAccum++; + if (this._stillFrameAccum > this._sleepAfterStill) { + this.animation.stop(); + } + } + }; + ZRender.prototype.setSleepAfterStill = function (stillFramesCount) { + this._sleepAfterStill = stillFramesCount; + }; + ZRender.prototype.wakeUp = function () { + this.animation.start(); + this._stillFrameAccum = 0; + }; + ZRender.prototype.refreshHover = function () { + this._needsRefreshHover = true; + }; + ZRender.prototype.refreshHoverImmediately = function () { + this._needsRefreshHover = false; + if (this.painter.refreshHover && this.painter.getType() === 'canvas') { + this.painter.refreshHover(); + } + }; + ZRender.prototype.resize = function (opts) { + opts = opts || {}; + this.painter.resize(opts.width, opts.height); + this.handler.resize(); + }; + ZRender.prototype.clearAnimation = function () { + this.animation.clear(); + }; + ZRender.prototype.getWidth = function () { + return this.painter.getWidth(); + }; + ZRender.prototype.getHeight = function () { + return this.painter.getHeight(); + }; + ZRender.prototype.setCursorStyle = function (cursorStyle) { + this.handler.setCursorStyle(cursorStyle); + }; + ZRender.prototype.findHover = function (x, y) { + return this.handler.findHover(x, y); + }; + ZRender.prototype.on = function (eventName, eventHandler, context) { + this.handler.on(eventName, eventHandler, context); + return this; + }; + ZRender.prototype.off = function (eventName, eventHandler) { + this.handler.off(eventName, eventHandler); + }; + ZRender.prototype.trigger = function (eventName, event) { + this.handler.trigger(eventName, event); + }; + ZRender.prototype.clear = function () { + var roots = this.storage.getRoots(); + for (var i = 0; i < roots.length; i++) { + if (roots[i] instanceof Group) { + roots[i].removeSelfFromZr(this); + } + } + this.storage.delAllRoots(); + this.painter.clear(); + }; + ZRender.prototype.dispose = function () { + this.animation.stop(); + this.clear(); + this.storage.dispose(); + this.painter.dispose(); + this.handler.dispose(); + this.animation = + this.storage = + this.painter = + this.handler = null; + delInstance(this.id); + }; + return ZRender; + }()); + function init(dom, opts) { + var zr = new ZRender(guid(), dom, opts); + instances[zr.id] = zr; + return zr; + } + function dispose(zr) { + zr.dispose(); + } + function disposeAll() { + for (var key in instances) { + if (instances.hasOwnProperty(key)) { + instances[key].dispose(); + } + } + instances = {}; + } + function getInstance(id) { + return instances[id]; + } + function registerPainter(name, Ctor) { + painterCtors[name] = Ctor; + } + var version = '5.3.0'; + + var zrender = /*#__PURE__*/Object.freeze({ + __proto__: null, + init: init, + dispose: dispose, + disposeAll: disposeAll, + getInstance: getInstance, + registerPainter: registerPainter, + version: version + }); + + var RADIAN_EPSILON = 1e-4; // Although chrome already enlarge this number to 100 for `toFixed`, but + // we sill follow the spec for compatibility. + + var ROUND_SUPPORTED_PRECISION_MAX = 20; + + function _trim(str) { + return str.replace(/^\s+|\s+$/g, ''); + } + /** + * Linear mapping a value from domain to range + * @param val + * @param domain Domain extent domain[0] can be bigger than domain[1] + * @param range Range extent range[0] can be bigger than range[1] + * @param clamp Default to be false + */ + + + function linearMap(val, domain, range, clamp) { + var d0 = domain[0]; + var d1 = domain[1]; + var r0 = range[0]; + var r1 = range[1]; + var subDomain = d1 - d0; + var subRange = r1 - r0; + + if (subDomain === 0) { + return subRange === 0 ? r0 : (r0 + r1) / 2; + } // Avoid accuracy problem in edge, such as + // 146.39 - 62.83 === 83.55999999999999. + // See echarts/test/ut/spec/util/number.js#linearMap#accuracyError + // It is a little verbose for efficiency considering this method + // is a hotspot. + + + if (clamp) { + if (subDomain > 0) { + if (val <= d0) { + return r0; + } else if (val >= d1) { + return r1; + } + } else { + if (val >= d0) { + return r0; + } else if (val <= d1) { + return r1; + } + } + } else { + if (val === d0) { + return r0; + } + + if (val === d1) { + return r1; + } + } + + return (val - d0) / subDomain * subRange + r0; + } + /** + * Convert a percent string to absolute number. + * Returns NaN if percent is not a valid string or number + */ + + function parsePercent$1(percent, all) { + switch (percent) { + case 'center': + case 'middle': + percent = '50%'; + break; + + case 'left': + case 'top': + percent = '0%'; + break; + + case 'right': + case 'bottom': + percent = '100%'; + break; + } + + if (isString(percent)) { + if (_trim(percent).match(/%$/)) { + return parseFloat(percent) / 100 * all; + } + + return parseFloat(percent); + } + + return percent == null ? NaN : +percent; + } + function round(x, precision, returnStr) { + if (precision == null) { + precision = 10; + } // Avoid range error + + + precision = Math.min(Math.max(0, precision), ROUND_SUPPORTED_PRECISION_MAX); // PENDING: 1.005.toFixed(2) is '1.00' rather than '1.01' + + x = (+x).toFixed(precision); + return returnStr ? x : +x; + } + /** + * Inplacd asc sort arr. + * The input arr will be modified. + */ + + function asc(arr) { + arr.sort(function (a, b) { + return a - b; + }); + return arr; + } + /** + * Get precision. + */ + + function getPrecision(val) { + val = +val; + + if (isNaN(val)) { + return 0; + } // It is much faster than methods converting number to string as follows + // let tmp = val.toString(); + // return tmp.length - 1 - tmp.indexOf('.'); + // especially when precision is low + // Notice: + // (1) If the loop count is over about 20, it is slower than `getPrecisionSafe`. + // (see https://jsbench.me/2vkpcekkvw/1) + // (2) If the val is less than for example 1e-15, the result may be incorrect. + // (see test/ut/spec/util/number.test.ts `getPrecision_equal_random`) + + + if (val > 1e-14) { + var e = 1; + + for (var i = 0; i < 15; i++, e *= 10) { + if (Math.round(val * e) / e === val) { + return i; + } + } + } + + return getPrecisionSafe(val); + } + /** + * Get precision with slow but safe method + */ + + function getPrecisionSafe(val) { + // toLowerCase for: '3.4E-12' + var str = val.toString().toLowerCase(); // Consider scientific notation: '3.4e-12' '3.4e+12' + + var eIndex = str.indexOf('e'); + var exp = eIndex > 0 ? +str.slice(eIndex + 1) : 0; + var significandPartLen = eIndex > 0 ? eIndex : str.length; + var dotIndex = str.indexOf('.'); + var decimalPartLen = dotIndex < 0 ? 0 : significandPartLen - 1 - dotIndex; + return Math.max(0, decimalPartLen - exp); + } + /** + * Minimal dicernible data precisioin according to a single pixel. + */ + + function getPixelPrecision(dataExtent, pixelExtent) { + var log = Math.log; + var LN10 = Math.LN10; + var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10); + var sizeQuantity = Math.round(log(Math.abs(pixelExtent[1] - pixelExtent[0])) / LN10); // toFixed() digits argument must be between 0 and 20. + + var precision = Math.min(Math.max(-dataQuantity + sizeQuantity, 0), 20); + return !isFinite(precision) ? 20 : precision; + } + /** + * Get a data of given precision, assuring the sum of percentages + * in valueList is 1. + * The largest remainer method is used. + * https://en.wikipedia.org/wiki/Largest_remainder_method + * + * @param valueList a list of all data + * @param idx index of the data to be processed in valueList + * @param precision integer number showing digits of precision + * @return percent ranging from 0 to 100 + */ + + function getPercentWithPrecision(valueList, idx, precision) { + if (!valueList[idx]) { + return 0; + } + + var sum = reduce(valueList, function (acc, val) { + return acc + (isNaN(val) ? 0 : val); + }, 0); + + if (sum === 0) { + return 0; + } + + var digits = Math.pow(10, precision); + var votesPerQuota = map(valueList, function (val) { + return (isNaN(val) ? 0 : val) / sum * digits * 100; + }); + var targetSeats = digits * 100; + var seats = map(votesPerQuota, function (votes) { + // Assign automatic seats. + return Math.floor(votes); + }); + var currentSum = reduce(seats, function (acc, val) { + return acc + val; + }, 0); + var remainder = map(votesPerQuota, function (votes, idx) { + return votes - seats[idx]; + }); // Has remainding votes. + + while (currentSum < targetSeats) { + // Find next largest remainder. + var max = Number.NEGATIVE_INFINITY; + var maxId = null; + + for (var i = 0, len = remainder.length; i < len; ++i) { + if (remainder[i] > max) { + max = remainder[i]; + maxId = i; + } + } // Add a vote to max remainder. + + + ++seats[maxId]; + remainder[maxId] = 0; + ++currentSum; + } + + return seats[idx] / digits; + } + /** + * Solve the floating point adding problem like 0.1 + 0.2 === 0.30000000000000004 + * See + */ + + function addSafe(val0, val1) { + var maxPrecision = Math.max(getPrecision(val0), getPrecision(val1)); // const multiplier = Math.pow(10, maxPrecision); + // return (Math.round(val0 * multiplier) + Math.round(val1 * multiplier)) / multiplier; + + var sum = val0 + val1; // // PENDING: support more? + + return maxPrecision > ROUND_SUPPORTED_PRECISION_MAX ? sum : round(sum, maxPrecision); + } // Number.MAX_SAFE_INTEGER, ie do not support. + + var MAX_SAFE_INTEGER = 9007199254740991; + /** + * To 0 - 2 * PI, considering negative radian. + */ + + function remRadian(radian) { + var pi2 = Math.PI * 2; + return (radian % pi2 + pi2) % pi2; + } + /** + * @param {type} radian + * @return {boolean} + */ + + function isRadianAroundZero(val) { + return val > -RADIAN_EPSILON && val < RADIAN_EPSILON; + } // eslint-disable-next-line + + var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d{1,2})(?::(\d{1,2})(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/; // jshint ignore:line + + /** + * @param value valid type: number | string | Date, otherwise return `new Date(NaN)` + * These values can be accepted: + * + An instance of Date, represent a time in its own time zone. + * + Or string in a subset of ISO 8601, only including: + * + only year, month, date: '2012-03', '2012-03-01', '2012-03-01 05', '2012-03-01 05:06', + * + separated with T or space: '2012-03-01T12:22:33.123', '2012-03-01 12:22:33.123', + * + time zone: '2012-03-01T12:22:33Z', '2012-03-01T12:22:33+8000', '2012-03-01T12:22:33-05:00', + * all of which will be treated as local time if time zone is not specified + * (see ). + * + Or other string format, including (all of which will be treated as loacal time): + * '2012', '2012-3-1', '2012/3/1', '2012/03/01', + * '2009/6/12 2:00', '2009/6/12 2:05:08', '2009/6/12 2:05:08.123' + * + a timestamp, which represent a time in UTC. + * @return date Never be null/undefined. If invalid, return `new Date(NaN)`. + */ + + function parseDate(value) { + if (value instanceof Date) { + return value; + } else if (isString(value)) { + // Different browsers parse date in different way, so we parse it manually. + // Some other issues: + // new Date('1970-01-01') is UTC, + // new Date('1970/01/01') and new Date('1970-1-01') is local. + // See issue #3623 + var match = TIME_REG.exec(value); + + if (!match) { + // return Invalid Date. + return new Date(NaN); + } // Use local time when no timezone offset specifed. + + + if (!match[8]) { + // match[n] can only be string or undefined. + // But take care of '12' + 1 => '121'. + return new Date(+match[1], +(match[2] || 1) - 1, +match[3] || 1, +match[4] || 0, +(match[5] || 0), +match[6] || 0, match[7] ? +match[7].substring(0, 3) : 0); + } // Timezoneoffset of Javascript Date has considered DST (Daylight Saving Time, + // https://tc39.github.io/ecma262/#sec-daylight-saving-time-adjustment). + // For example, system timezone is set as "Time Zone: America/Toronto", + // then these code will get different result: + // `new Date(1478411999999).getTimezoneOffset(); // get 240` + // `new Date(1478412000000).getTimezoneOffset(); // get 300` + // So we should not use `new Date`, but use `Date.UTC`. + else { + var hour = +match[4] || 0; + + if (match[8].toUpperCase() !== 'Z') { + hour -= +match[8].slice(0, 3); + } + + return new Date(Date.UTC(+match[1], +(match[2] || 1) - 1, +match[3] || 1, hour, +(match[5] || 0), +match[6] || 0, match[7] ? +match[7].substring(0, 3) : 0)); + } + } else if (value == null) { + return new Date(NaN); + } + + return new Date(Math.round(value)); + } + /** + * Quantity of a number. e.g. 0.1, 1, 10, 100 + * + * @param val + * @return + */ + + function quantity(val) { + return Math.pow(10, quantityExponent(val)); + } + /** + * Exponent of the quantity of a number + * e.g., 1234 equals to 1.234*10^3, so quantityExponent(1234) is 3 + * + * @param val non-negative value + * @return + */ + + function quantityExponent(val) { + if (val === 0) { + return 0; + } + + var exp = Math.floor(Math.log(val) / Math.LN10); + /** + * exp is expected to be the rounded-down result of the base-10 log of val. + * But due to the precision loss with Math.log(val), we need to restore it + * using 10^exp to make sure we can get val back from exp. #11249 + */ + + if (val / Math.pow(10, exp) >= 10) { + exp++; + } + + return exp; + } + /** + * find a “nice” number approximately equal to x. Round the number if round = true, + * take ceiling if round = false. The primary observation is that the “nicest” + * numbers in decimal are 1, 2, and 5, and all power-of-ten multiples of these numbers. + * + * See "Nice Numbers for Graph Labels" of Graphic Gems. + * + * @param val Non-negative value. + * @param round + * @return Niced number + */ + + function nice(val, round) { + var exponent = quantityExponent(val); + var exp10 = Math.pow(10, exponent); + var f = val / exp10; // 1 <= f < 10 + + var nf; + + if (round) { + if (f < 1.5) { + nf = 1; + } else if (f < 2.5) { + nf = 2; + } else if (f < 4) { + nf = 3; + } else if (f < 7) { + nf = 5; + } else { + nf = 10; + } + } else { + if (f < 1) { + nf = 1; + } else if (f < 2) { + nf = 2; + } else if (f < 3) { + nf = 3; + } else if (f < 5) { + nf = 5; + } else { + nf = 10; + } + } + + val = nf * exp10; // Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754). + // 20 is the uppper bound of toFixed. + + return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val; + } + /** + * This code was copied from "d3.js" + * . + * See the license statement at the head of this file. + * @param ascArr + */ + + function quantile(ascArr, p) { + var H = (ascArr.length - 1) * p + 1; + var h = Math.floor(H); + var v = +ascArr[h - 1]; + var e = H - h; + return e ? v + e * (ascArr[h] - v) : v; + } + /** + * Order intervals asc, and split them when overlap. + * expect(numberUtil.reformIntervals([ + * {interval: [18, 62], close: [1, 1]}, + * {interval: [-Infinity, -70], close: [0, 0]}, + * {interval: [-70, -26], close: [1, 1]}, + * {interval: [-26, 18], close: [1, 1]}, + * {interval: [62, 150], close: [1, 1]}, + * {interval: [106, 150], close: [1, 1]}, + * {interval: [150, Infinity], close: [0, 0]} + * ])).toEqual([ + * {interval: [-Infinity, -70], close: [0, 0]}, + * {interval: [-70, -26], close: [1, 1]}, + * {interval: [-26, 18], close: [0, 1]}, + * {interval: [18, 62], close: [0, 1]}, + * {interval: [62, 150], close: [0, 1]}, + * {interval: [150, Infinity], close: [0, 0]} + * ]); + * @param list, where `close` mean open or close + * of the interval, and Infinity can be used. + * @return The origin list, which has been reformed. + */ + + function reformIntervals(list) { + list.sort(function (a, b) { + return littleThan(a, b, 0) ? -1 : 1; + }); + var curr = -Infinity; + var currClose = 1; + + for (var i = 0; i < list.length;) { + var interval = list[i].interval; + var close_1 = list[i].close; + + for (var lg = 0; lg < 2; lg++) { + if (interval[lg] <= curr) { + interval[lg] = curr; + close_1[lg] = !lg ? 1 - currClose : 1; + } + + curr = interval[lg]; + currClose = close_1[lg]; + } + + if (interval[0] === interval[1] && close_1[0] * close_1[1] !== 1) { + list.splice(i, 1); + } else { + i++; + } + } + + return list; + + function littleThan(a, b, lg) { + return a.interval[lg] < b.interval[lg] || a.interval[lg] === b.interval[lg] && (a.close[lg] - b.close[lg] === (!lg ? 1 : -1) || !lg && littleThan(a, b, 1)); + } + } + /** + * [Numberic is defined as]: + * `parseFloat(val) == val` + * For example: + * numeric: + * typeof number except NaN, '-123', '123', '2e3', '-2e3', '011', 'Infinity', Infinity, + * and they rounded by white-spaces or line-terminal like ' -123 \n ' (see es spec) + * not-numeric: + * null, undefined, [], {}, true, false, 'NaN', NaN, '123ab', + * empty string, string with only white-spaces or line-terminal (see es spec), + * 0x12, '0x12', '-0x12', 012, '012', '-012', + * non-string, ... + * + * @test See full test cases in `test/ut/spec/util/number.js`. + * @return Must be a typeof number. If not numeric, return NaN. + */ + + function numericToNumber(val) { + var valFloat = parseFloat(val); + return valFloat == val // eslint-disable-line eqeqeq + && (valFloat !== 0 || !isString(val) || val.indexOf('x') <= 0) // For case ' 0x0 '. + ? valFloat : NaN; + } + /** + * Definition of "numeric": see `numericToNumber`. + */ + + function isNumeric(val) { + return !isNaN(numericToNumber(val)); + } + /** + * Use random base to prevent users hard code depending on + * this auto generated marker id. + * @return An positive integer. + */ + + function getRandomIdBase() { + return Math.round(Math.random() * 9); + } + /** + * Get the greatest common dividor + * + * @param {number} a one number + * @param {number} b the other number + */ + + function getGreatestCommonDividor(a, b) { + if (b === 0) { + return a; + } + + return getGreatestCommonDividor(b, a % b); + } + /** + * Get the least common multiple + * + * @param {number} a one number + * @param {number} b the other number + */ + + function getLeastCommonMultiple(a, b) { + if (a == null) { + return b; + } + + if (b == null) { + return a; + } + + return a * b / getGreatestCommonDividor(a, b); + } + + var ECHARTS_PREFIX = '[ECharts] '; + var storedLogs = {}; + var hasConsole = typeof console !== 'undefined' // eslint-disable-next-line + && console.warn && console.log; + + function outputLog(type, str, onlyOnce) { + if (hasConsole) { + if (onlyOnce) { + if (storedLogs[str]) { + return; + } + + storedLogs[str] = true; + } // eslint-disable-next-line + + + console[type](ECHARTS_PREFIX + str); + } + } + + function log(str, onlyOnce) { + outputLog('log', str, onlyOnce); + } + function warn(str, onlyOnce) { + outputLog('warn', str, onlyOnce); + } + function error(str, onlyOnce) { + outputLog('error', str, onlyOnce); + } + function deprecateLog(str) { + if ("development" !== 'production') { + // Not display duplicate message. + outputLog('warn', 'DEPRECATED: ' + str, true); + } + } + function deprecateReplaceLog(oldOpt, newOpt, scope) { + if ("development" !== 'production') { + deprecateLog((scope ? "[" + scope + "]" : '') + (oldOpt + " is deprecated, use " + newOpt + " instead.")); + } + } + /** + * If in __DEV__ environment, get console printable message for users hint. + * Parameters are separated by ' '. + * @usuage + * makePrintable('This is an error on', someVar, someObj); + * + * @param hintInfo anything about the current execution context to hint users. + * @throws Error + */ + + function makePrintable() { + var hintInfo = []; + + for (var _i = 0; _i < arguments.length; _i++) { + hintInfo[_i] = arguments[_i]; + } + + var msg = ''; + + if ("development" !== 'production') { + // Fuzzy stringify for print. + // This code only exist in dev environment. + var makePrintableStringIfPossible_1 = function (val) { + return val === void 0 ? 'undefined' : val === Infinity ? 'Infinity' : val === -Infinity ? '-Infinity' : eqNaN(val) ? 'NaN' : val instanceof Date ? 'Date(' + val.toISOString() + ')' : isFunction(val) ? 'function () { ... }' : isRegExp(val) ? val + '' : null; + }; + + msg = map(hintInfo, function (arg) { + if (isString(arg)) { + // Print without quotation mark for some statement. + return arg; + } else { + var printableStr = makePrintableStringIfPossible_1(arg); + + if (printableStr != null) { + return printableStr; + } else if (typeof JSON !== 'undefined' && JSON.stringify) { + try { + return JSON.stringify(arg, function (n, val) { + var printableStr = makePrintableStringIfPossible_1(val); + return printableStr == null ? val : printableStr; + }); // In most cases the info object is small, so do not line break. + } catch (err) { + return '?'; + } + } else { + return '?'; + } + } + }).join(' '); + } + + return msg; + } + /** + * @throws Error + */ + + function throwError(msg) { + throw new Error(msg); + } + + function interpolateNumber$1(p0, p1, percent) { + return (p1 - p0) * percent + p0; + } + /** + * Make the name displayable. But we should + * make sure it is not duplicated with user + * specified name, so use '\0'; + */ + + + var DUMMY_COMPONENT_NAME_PREFIX = 'series\0'; + var INTERNAL_COMPONENT_ID_PREFIX = '\0_ec_\0'; + /** + * If value is not array, then translate it to array. + * @param {*} value + * @return {Array} [value] or value + */ + + function normalizeToArray(value) { + return value instanceof Array ? value : value == null ? [] : [value]; + } + /** + * Sync default option between normal and emphasis like `position` and `show` + * In case some one will write code like + * label: { + * show: false, + * position: 'outside', + * fontSize: 18 + * }, + * emphasis: { + * label: { show: true } + * } + */ + + function defaultEmphasis(opt, key, subOpts) { + // Caution: performance sensitive. + if (opt) { + opt[key] = opt[key] || {}; + opt.emphasis = opt.emphasis || {}; + opt.emphasis[key] = opt.emphasis[key] || {}; // Default emphasis option from normal + + for (var i = 0, len = subOpts.length; i < len; i++) { + var subOptName = subOpts[i]; + + if (!opt.emphasis[key].hasOwnProperty(subOptName) && opt[key].hasOwnProperty(subOptName)) { + opt.emphasis[key][subOptName] = opt[key][subOptName]; + } + } + } + } + var TEXT_STYLE_OPTIONS = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'rich', 'tag', 'color', 'textBorderColor', 'textBorderWidth', 'width', 'height', 'lineHeight', 'align', 'verticalAlign', 'baseline', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY', 'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY', 'backgroundColor', 'borderColor', 'borderWidth', 'borderRadius', 'padding']; // modelUtil.LABEL_OPTIONS = modelUtil.TEXT_STYLE_OPTIONS.concat([ + // 'position', 'offset', 'rotate', 'origin', 'show', 'distance', 'formatter', + // 'fontStyle', 'fontWeight', 'fontSize', 'fontFamily', + // // FIXME: deprecated, check and remove it. + // 'textStyle' + // ]); + + /** + * The method do not ensure performance. + * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}] + * This helper method retieves value from data. + */ + + function getDataItemValue(dataItem) { + return isObject(dataItem) && !isArray(dataItem) && !(dataItem instanceof Date) ? dataItem.value : dataItem; + } + /** + * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}] + * This helper method determine if dataItem has extra option besides value + */ + + function isDataItemOption(dataItem) { + return isObject(dataItem) && !(dataItem instanceof Array); // // markLine data can be array + // && !(dataItem[0] && isObject(dataItem[0]) && !(dataItem[0] instanceof Array)); + } + /** + * Mapping to existings for merge. + * + * Mode "normalMege": + * The mapping result (merge result) will keep the order of the existing + * component, rather than the order of new option. Because we should ensure + * some specified index reference (like xAxisIndex) keep work. + * And in most cases, "merge option" is used to update partial option but not + * be expected to change the order. + * + * Mode "replaceMege": + * (1) Only the id mapped components will be merged. + * (2) Other existing components (except internal compoonets) will be removed. + * (3) Other new options will be used to create new component. + * (4) The index of the existing compoents will not be modified. + * That means their might be "hole" after the removal. + * The new components are created first at those available index. + * + * Mode "replaceAll": + * This mode try to support that reproduce an echarts instance from another + * echarts instance (via `getOption`) in some simple cases. + * In this senario, the `result` index are exactly the consistent with the `newCmptOptions`, + * which ensures the compoennt index referring (like `xAxisIndex: ?`) corrent. That is, + * the "hole" in `newCmptOptions` will also be kept. + * On the contrary, other modes try best to eliminate holes. + * PENDING: This is an experimental mode yet. + * + * @return See the comment of . + */ + + function mappingToExists(existings, newCmptOptions, mode) { + var isNormalMergeMode = mode === 'normalMerge'; + var isReplaceMergeMode = mode === 'replaceMerge'; + var isReplaceAllMode = mode === 'replaceAll'; + existings = existings || []; + newCmptOptions = (newCmptOptions || []).slice(); + var existingIdIdxMap = createHashMap(); // Validate id and name on user input option. + + each(newCmptOptions, function (cmptOption, index) { + if (!isObject(cmptOption)) { + newCmptOptions[index] = null; + return; + } + + if ("development" !== 'production') { + // There is some legacy case that name is set as `false`. + // But should work normally rather than throw error. + if (cmptOption.id != null && !isValidIdOrName(cmptOption.id)) { + warnInvalidateIdOrName(cmptOption.id); + } + + if (cmptOption.name != null && !isValidIdOrName(cmptOption.name)) { + warnInvalidateIdOrName(cmptOption.name); + } + } + }); + var result = prepareResult(existings, existingIdIdxMap, mode); + + if (isNormalMergeMode || isReplaceMergeMode) { + mappingById(result, existings, existingIdIdxMap, newCmptOptions); + } + + if (isNormalMergeMode) { + mappingByName(result, newCmptOptions); + } + + if (isNormalMergeMode || isReplaceMergeMode) { + mappingByIndex(result, newCmptOptions, isReplaceMergeMode); + } else if (isReplaceAllMode) { + mappingInReplaceAllMode(result, newCmptOptions); + } + + makeIdAndName(result); // The array `result` MUST NOT contain elided items, otherwise the + // forEach will ommit those items and result in incorrect result. + + return result; + } + + function prepareResult(existings, existingIdIdxMap, mode) { + var result = []; + + if (mode === 'replaceAll') { + return result; + } // Do not use native `map` to in case that the array `existings` + // contains elided items, which will be ommited. + + + for (var index = 0; index < existings.length; index++) { + var existing = existings[index]; // Because of replaceMerge, `existing` may be null/undefined. + + if (existing && existing.id != null) { + existingIdIdxMap.set(existing.id, index); + } // For non-internal-componnets: + // Mode "normalMerge": all existings kept. + // Mode "replaceMerge": all existing removed unless mapped by id. + // For internal-components: + // go with "replaceMerge" approach in both mode. + + + result.push({ + existing: mode === 'replaceMerge' || isComponentIdInternal(existing) ? null : existing, + newOption: null, + keyInfo: null, + brandNew: null + }); + } + + return result; + } + + function mappingById(result, existings, existingIdIdxMap, newCmptOptions) { + // Mapping by id if specified. + each(newCmptOptions, function (cmptOption, index) { + if (!cmptOption || cmptOption.id == null) { + return; + } + + var optionId = makeComparableKey(cmptOption.id); + var existingIdx = existingIdIdxMap.get(optionId); + + if (existingIdx != null) { + var resultItem = result[existingIdx]; + assert(!resultItem.newOption, 'Duplicated option on id "' + optionId + '".'); + resultItem.newOption = cmptOption; // In both mode, if id matched, new option will be merged to + // the existings rather than creating new component model. + + resultItem.existing = existings[existingIdx]; + newCmptOptions[index] = null; + } + }); + } + + function mappingByName(result, newCmptOptions) { + // Mapping by name if specified. + each(newCmptOptions, function (cmptOption, index) { + if (!cmptOption || cmptOption.name == null) { + return; + } + + for (var i = 0; i < result.length; i++) { + var existing = result[i].existing; + + if (!result[i].newOption // Consider name: two map to one. + // Can not match when both ids existing but different. + && existing && (existing.id == null || cmptOption.id == null) && !isComponentIdInternal(cmptOption) && !isComponentIdInternal(existing) && keyExistAndEqual('name', existing, cmptOption)) { + result[i].newOption = cmptOption; + newCmptOptions[index] = null; + return; + } + } + }); + } + + function mappingByIndex(result, newCmptOptions, brandNew) { + each(newCmptOptions, function (cmptOption) { + if (!cmptOption) { + return; + } // Find the first place that not mapped by id and not internal component (consider the "hole"). + + + var resultItem; + var nextIdx = 0; + + while ( // Be `!resultItem` only when `nextIdx >= result.length`. + (resultItem = result[nextIdx]) && ( // (1) Existing models that already have id should be able to mapped to. Because + // after mapping performed, model will always be assigned with an id if user not given. + // After that all models have id. + // (2) If new option has id, it can only set to a hole or append to the last. It should + // not be merged to the existings with different id. Because id should not be overwritten. + // (3) Name can be overwritten, because axis use name as 'show label text'. + resultItem.newOption || isComponentIdInternal(resultItem.existing) || // In mode "replaceMerge", here no not-mapped-non-internal-existing. + resultItem.existing && cmptOption.id != null && !keyExistAndEqual('id', cmptOption, resultItem.existing))) { + nextIdx++; + } + + if (resultItem) { + resultItem.newOption = cmptOption; + resultItem.brandNew = brandNew; + } else { + result.push({ + newOption: cmptOption, + brandNew: brandNew, + existing: null, + keyInfo: null + }); + } + + nextIdx++; + }); + } + + function mappingInReplaceAllMode(result, newCmptOptions) { + each(newCmptOptions, function (cmptOption) { + // The feature "reproduce" requires "hole" will also reproduced + // in case that compoennt index referring are broken. + result.push({ + newOption: cmptOption, + brandNew: true, + existing: null, + keyInfo: null + }); + }); + } + /** + * Make id and name for mapping result (result of mappingToExists) + * into `keyInfo` field. + */ + + + function makeIdAndName(mapResult) { + // We use this id to hash component models and view instances + // in echarts. id can be specified by user, or auto generated. + // The id generation rule ensures new view instance are able + // to mapped to old instance when setOption are called in + // no-merge mode. So we generate model id by name and plus + // type in view id. + // name can be duplicated among components, which is convenient + // to specify multi components (like series) by one name. + // Ensure that each id is distinct. + var idMap = createHashMap(); + each(mapResult, function (item) { + var existing = item.existing; + existing && idMap.set(existing.id, item); + }); + each(mapResult, function (item) { + var opt = item.newOption; // Force ensure id not duplicated. + + assert(!opt || opt.id == null || !idMap.get(opt.id) || idMap.get(opt.id) === item, 'id duplicates: ' + (opt && opt.id)); + opt && opt.id != null && idMap.set(opt.id, item); + !item.keyInfo && (item.keyInfo = {}); + }); // Make name and id. + + each(mapResult, function (item, index) { + var existing = item.existing; + var opt = item.newOption; + var keyInfo = item.keyInfo; + + if (!isObject(opt)) { + return; + } // name can be overwitten. Consider case: axis.name = '20km'. + // But id generated by name will not be changed, which affect + // only in that case: setOption with 'not merge mode' and view + // instance will be recreated, which can be accepted. + + + keyInfo.name = opt.name != null ? makeComparableKey(opt.name) : existing ? existing.name // Avoid diffferent series has the same name, + // because name may be used like in color pallet. + : DUMMY_COMPONENT_NAME_PREFIX + index; + + if (existing) { + keyInfo.id = makeComparableKey(existing.id); + } else if (opt.id != null) { + keyInfo.id = makeComparableKey(opt.id); + } else { + // Consider this situatoin: + // optionA: [{name: 'a'}, {name: 'a'}, {..}] + // optionB [{..}, {name: 'a'}, {name: 'a'}] + // Series with the same name between optionA and optionB + // should be mapped. + var idNum = 0; + + do { + keyInfo.id = '\0' + keyInfo.name + '\0' + idNum++; + } while (idMap.get(keyInfo.id)); + } + + idMap.set(keyInfo.id, item); + }); + } + + function keyExistAndEqual(attr, obj1, obj2) { + var key1 = convertOptionIdName(obj1[attr], null); + var key2 = convertOptionIdName(obj2[attr], null); // See `MappingExistingItem`. `id` and `name` trade string equals to number. + + return key1 != null && key2 != null && key1 === key2; + } + /** + * @return return null if not exist. + */ + + + function makeComparableKey(val) { + if ("development" !== 'production') { + if (val == null) { + throw new Error(); + } + } + + return convertOptionIdName(val, ''); + } + + function convertOptionIdName(idOrName, defaultValue) { + if (idOrName == null) { + return defaultValue; + } + + return isString(idOrName) ? idOrName : isNumber(idOrName) || isStringSafe(idOrName) ? idOrName + '' : defaultValue; + } + + function warnInvalidateIdOrName(idOrName) { + if ("development" !== 'production') { + warn('`' + idOrName + '` is invalid id or name. Must be a string or number.'); + } + } + + function isValidIdOrName(idOrName) { + return isStringSafe(idOrName) || isNumeric(idOrName); + } + + function isNameSpecified(componentModel) { + var name = componentModel.name; // Is specified when `indexOf` get -1 or > 0. + + return !!(name && name.indexOf(DUMMY_COMPONENT_NAME_PREFIX)); + } + /** + * @public + * @param {Object} cmptOption + * @return {boolean} + */ + + function isComponentIdInternal(cmptOption) { + return cmptOption && cmptOption.id != null && makeComparableKey(cmptOption.id).indexOf(INTERNAL_COMPONENT_ID_PREFIX) === 0; + } + function makeInternalComponentId(idSuffix) { + return INTERNAL_COMPONENT_ID_PREFIX + idSuffix; + } + function setComponentTypeToKeyInfo(mappingResult, mainType, componentModelCtor) { + // Set mainType and complete subType. + each(mappingResult, function (item) { + var newOption = item.newOption; + + if (isObject(newOption)) { + item.keyInfo.mainType = mainType; + item.keyInfo.subType = determineSubType(mainType, newOption, item.existing, componentModelCtor); + } + }); + } + + function determineSubType(mainType, newCmptOption, existComponent, componentModelCtor) { + var subType = newCmptOption.type ? newCmptOption.type : existComponent ? existComponent.subType // Use determineSubType only when there is no existComponent. + : componentModelCtor.determineSubType(mainType, newCmptOption); // tooltip, markline, markpoint may always has no subType + + return subType; + } + /** + * A helper for removing duplicate items between batchA and batchB, + * and in themselves, and categorize by series. + * + * @param batchA Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...] + * @param batchB Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...] + * @return result: [resultBatchA, resultBatchB] + */ + + + function compressBatches(batchA, batchB) { + var mapA = {}; + var mapB = {}; + makeMap(batchA || [], mapA); + makeMap(batchB || [], mapB, mapA); + return [mapToArray(mapA), mapToArray(mapB)]; + + function makeMap(sourceBatch, map, otherMap) { + for (var i = 0, len = sourceBatch.length; i < len; i++) { + var seriesId = convertOptionIdName(sourceBatch[i].seriesId, null); + + if (seriesId == null) { + return; + } + + var dataIndices = normalizeToArray(sourceBatch[i].dataIndex); + var otherDataIndices = otherMap && otherMap[seriesId]; + + for (var j = 0, lenj = dataIndices.length; j < lenj; j++) { + var dataIndex = dataIndices[j]; + + if (otherDataIndices && otherDataIndices[dataIndex]) { + otherDataIndices[dataIndex] = null; + } else { + (map[seriesId] || (map[seriesId] = {}))[dataIndex] = 1; + } + } + } + } + + function mapToArray(map, isData) { + var result = []; + + for (var i in map) { + if (map.hasOwnProperty(i) && map[i] != null) { + if (isData) { + result.push(+i); + } else { + var dataIndices = mapToArray(map[i], true); + dataIndices.length && result.push({ + seriesId: i, + dataIndex: dataIndices + }); + } + } + } + + return result; + } + } + /** + * @param payload Contains dataIndex (means rawIndex) / dataIndexInside / name + * each of which can be Array or primary type. + * @return dataIndex If not found, return undefined/null. + */ + + function queryDataIndex(data, payload) { + if (payload.dataIndexInside != null) { + return payload.dataIndexInside; + } else if (payload.dataIndex != null) { + return isArray(payload.dataIndex) ? map(payload.dataIndex, function (value) { + return data.indexOfRawIndex(value); + }) : data.indexOfRawIndex(payload.dataIndex); + } else if (payload.name != null) { + return isArray(payload.name) ? map(payload.name, function (value) { + return data.indexOfName(value); + }) : data.indexOfName(payload.name); + } + } + /** + * Enable property storage to any host object. + * Notice: Serialization is not supported. + * + * For example: + * let inner = zrUitl.makeInner(); + * + * function some1(hostObj) { + * inner(hostObj).someProperty = 1212; + * ... + * } + * function some2() { + * let fields = inner(this); + * fields.someProperty1 = 1212; + * fields.someProperty2 = 'xx'; + * ... + * } + * + * @return {Function} + */ + + function makeInner() { + var key = '__ec_inner_' + innerUniqueIndex++; + return function (hostObj) { + return hostObj[key] || (hostObj[key] = {}); + }; + } + var innerUniqueIndex = getRandomIdBase(); + /** + * The same behavior as `component.getReferringComponents`. + */ + + function parseFinder(ecModel, finderInput, opt) { + var _a = preParseFinder(finderInput, opt), + mainTypeSpecified = _a.mainTypeSpecified, + queryOptionMap = _a.queryOptionMap, + others = _a.others; + + var result = others; + var defaultMainType = opt ? opt.defaultMainType : null; + + if (!mainTypeSpecified && defaultMainType) { + queryOptionMap.set(defaultMainType, {}); + } + + queryOptionMap.each(function (queryOption, mainType) { + var queryResult = queryReferringComponents(ecModel, mainType, queryOption, { + useDefault: defaultMainType === mainType, + enableAll: opt && opt.enableAll != null ? opt.enableAll : true, + enableNone: opt && opt.enableNone != null ? opt.enableNone : true + }); + result[mainType + 'Models'] = queryResult.models; + result[mainType + 'Model'] = queryResult.models[0]; + }); + return result; + } + function preParseFinder(finderInput, opt) { + var finder; + + if (isString(finderInput)) { + var obj = {}; + obj[finderInput + 'Index'] = 0; + finder = obj; + } else { + finder = finderInput; + } + + var queryOptionMap = createHashMap(); + var others = {}; + var mainTypeSpecified = false; + each(finder, function (value, key) { + // Exclude 'dataIndex' and other illgal keys. + if (key === 'dataIndex' || key === 'dataIndexInside') { + others[key] = value; + return; + } + + var parsedKey = key.match(/^(\w+)(Index|Id|Name)$/) || []; + var mainType = parsedKey[1]; + var queryType = (parsedKey[2] || '').toLowerCase(); + + if (!mainType || !queryType || opt && opt.includeMainTypes && indexOf(opt.includeMainTypes, mainType) < 0) { + return; + } + + mainTypeSpecified = mainTypeSpecified || !!mainType; + var queryOption = queryOptionMap.get(mainType) || queryOptionMap.set(mainType, {}); + queryOption[queryType] = value; + }); + return { + mainTypeSpecified: mainTypeSpecified, + queryOptionMap: queryOptionMap, + others: others + }; + } + var SINGLE_REFERRING = { + useDefault: true, + enableAll: false, + enableNone: false + }; + var MULTIPLE_REFERRING = { + useDefault: false, + enableAll: true, + enableNone: true + }; + function queryReferringComponents(ecModel, mainType, userOption, opt) { + opt = opt || SINGLE_REFERRING; + var indexOption = userOption.index; + var idOption = userOption.id; + var nameOption = userOption.name; + var result = { + models: null, + specified: indexOption != null || idOption != null || nameOption != null + }; + + if (!result.specified) { + // Use the first as default if `useDefault`. + var firstCmpt = void 0; + result.models = opt.useDefault && (firstCmpt = ecModel.getComponent(mainType)) ? [firstCmpt] : []; + return result; + } + + if (indexOption === 'none' || indexOption === false) { + assert(opt.enableNone, '`"none"` or `false` is not a valid value on index option.'); + result.models = []; + return result; + } // `queryComponents` will return all components if + // both all of index/id/name are null/undefined. + + + if (indexOption === 'all') { + assert(opt.enableAll, '`"all"` is not a valid value on index option.'); + indexOption = idOption = nameOption = null; + } + + result.models = ecModel.queryComponents({ + mainType: mainType, + index: indexOption, + id: idOption, + name: nameOption + }); + return result; + } + function setAttribute(dom, key, value) { + dom.setAttribute ? dom.setAttribute(key, value) : dom[key] = value; + } + function getAttribute(dom, key) { + return dom.getAttribute ? dom.getAttribute(key) : dom[key]; + } + function getTooltipRenderMode(renderModeOption) { + if (renderModeOption === 'auto') { + // Using html when `document` exists, use richText otherwise + return env.domSupported ? 'html' : 'richText'; + } else { + return renderModeOption || 'html'; + } + } + /** + * Group a list by key. + */ + + function groupData(array, getKey // return key + ) { + var buckets = createHashMap(); + var keys = []; + each(array, function (item) { + var key = getKey(item); + (buckets.get(key) || (keys.push(key), buckets.set(key, []))).push(item); + }); + return { + keys: keys, + buckets: buckets + }; + } + /** + * Interpolate raw values of a series with percent + * + * @param data data + * @param labelModel label model of the text element + * @param sourceValue start value. May be null/undefined when init. + * @param targetValue end value + * @param percent 0~1 percentage; 0 uses start value while 1 uses end value + * @return interpolated values + * If `sourceValue` and `targetValue` are `number`, return `number`. + * If `sourceValue` and `targetValue` are `string`, return `string`. + * If `sourceValue` and `targetValue` are `(string | number)[]`, return `(string | number)[]`. + * Other cases do not supported. + */ + + function interpolateRawValues(data, precision, sourceValue, targetValue, percent) { + var isAutoPrecision = precision == null || precision === 'auto'; + + if (targetValue == null) { + return targetValue; + } + + if (isNumber(targetValue)) { + var value = interpolateNumber$1(sourceValue || 0, targetValue, percent); + return round(value, isAutoPrecision ? Math.max(getPrecision(sourceValue || 0), getPrecision(targetValue)) : precision); + } else if (isString(targetValue)) { + return percent < 1 ? sourceValue : targetValue; + } else { + var interpolated = []; + var leftArr = sourceValue; + var rightArr = targetValue; + var length_1 = Math.max(leftArr ? leftArr.length : 0, rightArr.length); + + for (var i = 0; i < length_1; ++i) { + var info = data.getDimensionInfo(i); // Don't interpolate ordinal dims + + if (info && info.type === 'ordinal') { + // In init, there is no `sourceValue`, but should better not to get undefined result. + interpolated[i] = (percent < 1 && leftArr ? leftArr : rightArr)[i]; + } else { + var leftVal = leftArr && leftArr[i] ? leftArr[i] : 0; + var rightVal = rightArr[i]; + var value = interpolateNumber$1(leftVal, rightVal, percent); + interpolated[i] = round(value, isAutoPrecision ? Math.max(getPrecision(leftVal), getPrecision(rightVal)) : precision); + } + } + + return interpolated; + } + } + + var TYPE_DELIMITER = '.'; + var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___'; + var IS_EXTENDED_CLASS = '___EC__EXTENDED_CLASS___'; + /** + * Notice, parseClassType('') should returns {main: '', sub: ''} + * @public + */ + + function parseClassType(componentType) { + var ret = { + main: '', + sub: '' + }; + + if (componentType) { + var typeArr = componentType.split(TYPE_DELIMITER); + ret.main = typeArr[0] || ''; + ret.sub = typeArr[1] || ''; + } + + return ret; + } + /** + * @public + */ + + function checkClassType(componentType) { + assert(/^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType), 'componentType "' + componentType + '" illegal'); + } + + function isExtendedClass(clz) { + return !!(clz && clz[IS_EXTENDED_CLASS]); + } + /** + * Implements `ExtendableConstructor` for `rootClz`. + * + * @usage + * ```ts + * class Xxx {} + * type XxxConstructor = typeof Xxx & ExtendableConstructor + * enableClassExtend(Xxx as XxxConstructor); + * ``` + */ + + function enableClassExtend(rootClz, mandatoryMethods) { + rootClz.$constructor = rootClz; // FIXME: not necessary? + + rootClz.extend = function (proto) { + if ("development" !== 'production') { + each(mandatoryMethods, function (method) { + if (!proto[method]) { + console.warn('Method `' + method + '` should be implemented' + (proto.type ? ' in ' + proto.type : '') + '.'); + } + }); + } + + var superClass = this; + var ExtendedClass; + + if (isESClass(superClass)) { + ExtendedClass = + /** @class */ + function (_super) { + __extends(class_1, _super); + + function class_1() { + return _super.apply(this, arguments) || this; + } + + return class_1; + }(superClass); + } else { + // For backward compat, we both support ts class inheritance and this + // "extend" approach. + // The constructor should keep the same behavior as ts class inheritance: + // If this constructor/$constructor is not declared, auto invoke the super + // constructor. + // If this constructor/$constructor is declared, it is responsible for + // calling the super constructor. + ExtendedClass = function () { + (proto.$constructor || superClass).apply(this, arguments); + }; + + inherits(ExtendedClass, this); + } + + extend(ExtendedClass.prototype, proto); + ExtendedClass[IS_EXTENDED_CLASS] = true; + ExtendedClass.extend = this.extend; + ExtendedClass.superCall = superCall; + ExtendedClass.superApply = superApply; + ExtendedClass.superClass = superClass; + return ExtendedClass; + }; + } + + function isESClass(fn) { + return isFunction(fn) && /^class\s/.test(Function.prototype.toString.call(fn)); + } + /** + * A work around to both support ts extend and this extend mechanism. + * on sub-class. + * @usage + * ```ts + * class Component { ... } + * classUtil.enableClassExtend(Component); + * classUtil.enableClassManagement(Component, {registerWhenExtend: true}); + * + * class Series extends Component { ... } + * // Without calling `markExtend`, `registerWhenExtend` will not work. + * Component.markExtend(Series); + * ``` + */ + + + function mountExtend(SubClz, SupperClz) { + SubClz.extend = SupperClz.extend; + } // A random offset. + + var classBase = Math.round(Math.random() * 10); + /** + * Implements `CheckableConstructor` for `target`. + * Can not use instanceof, consider different scope by + * cross domain or es module import in ec extensions. + * Mount a method "isInstance()" to Clz. + * + * @usage + * ```ts + * class Xxx {} + * type XxxConstructor = typeof Xxx & CheckableConstructor; + * enableClassCheck(Xxx as XxxConstructor) + * ``` + */ + + function enableClassCheck(target) { + var classAttr = ['__\0is_clz', classBase++].join('_'); + target.prototype[classAttr] = true; + + if ("development" !== 'production') { + assert(!target.isInstance, 'The method "is" can not be defined.'); + } + + target.isInstance = function (obj) { + return !!(obj && obj[classAttr]); + }; + } // superCall should have class info, which can not be fetch from 'this'. + // Consider this case: + // class A has method f, + // class B inherits class A, overrides method f, f call superApply('f'), + // class C inherits class B, do not overrides method f, + // then when method of class C is called, dead loop occured. + + function superCall(context, methodName) { + var args = []; + + for (var _i = 2; _i < arguments.length; _i++) { + args[_i - 2] = arguments[_i]; + } + + return this.superClass.prototype[methodName].apply(context, args); + } + + function superApply(context, methodName, args) { + return this.superClass.prototype[methodName].apply(context, args); + } + /** + * Implements `ClassManager` for `target` + * + * @usage + * ```ts + * class Xxx {} + * type XxxConstructor = typeof Xxx & ClassManager + * enableClassManagement(Xxx as XxxConstructor); + * ``` + */ + + + function enableClassManagement(target) { + /** + * Component model classes + * key: componentType, + * value: + * componentClass, when componentType is 'xxx' + * or Object., when componentType is 'xxx.yy' + */ + var storage = {}; + + target.registerClass = function (clz) { + // `type` should not be a "instance memeber". + // If using TS class, should better declared as `static type = 'series.pie'`. + // otherwise users have to mount `type` on prototype manually. + // For backward compat and enable instance visit type via `this.type`, + // we stil support fetch `type` from prototype. + var componentFullType = clz.type || clz.prototype.type; + + if (componentFullType) { + checkClassType(componentFullType); // If only static type declared, we assign it to prototype mandatorily. + + clz.prototype.type = componentFullType; + var componentTypeInfo = parseClassType(componentFullType); + + if (!componentTypeInfo.sub) { + if ("development" !== 'production') { + if (storage[componentTypeInfo.main]) { + console.warn(componentTypeInfo.main + ' exists.'); + } + } + + storage[componentTypeInfo.main] = clz; + } else if (componentTypeInfo.sub !== IS_CONTAINER) { + var container = makeContainer(componentTypeInfo); + container[componentTypeInfo.sub] = clz; + } + } + + return clz; + }; + + target.getClass = function (mainType, subType, throwWhenNotFound) { + var clz = storage[mainType]; + + if (clz && clz[IS_CONTAINER]) { + clz = subType ? clz[subType] : null; + } + + if (throwWhenNotFound && !clz) { + throw new Error(!subType ? mainType + '.' + 'type should be specified.' : 'Component ' + mainType + '.' + (subType || '') + ' is used but not imported.'); + } + + return clz; + }; + + target.getClassesByMainType = function (componentType) { + var componentTypeInfo = parseClassType(componentType); + var result = []; + var obj = storage[componentTypeInfo.main]; + + if (obj && obj[IS_CONTAINER]) { + each(obj, function (o, type) { + type !== IS_CONTAINER && result.push(o); + }); + } else { + result.push(obj); + } + + return result; + }; + + target.hasClass = function (componentType) { + // Just consider componentType.main. + var componentTypeInfo = parseClassType(componentType); + return !!storage[componentTypeInfo.main]; + }; + /** + * @return Like ['aa', 'bb'], but can not be ['aa.xx'] + */ + + + target.getAllClassMainTypes = function () { + var types = []; + each(storage, function (obj, type) { + types.push(type); + }); + return types; + }; + /** + * If a main type is container and has sub types + */ + + + target.hasSubTypes = function (componentType) { + var componentTypeInfo = parseClassType(componentType); + var obj = storage[componentTypeInfo.main]; + return obj && obj[IS_CONTAINER]; + }; + + function makeContainer(componentTypeInfo) { + var container = storage[componentTypeInfo.main]; + + if (!container || !container[IS_CONTAINER]) { + container = storage[componentTypeInfo.main] = {}; + container[IS_CONTAINER] = true; + } + + return container; + } + } // /** + // * @param {string|Array.} properties + // */ + // export function setReadOnly(obj, properties) { + // FIXME It seems broken in IE8 simulation of IE11 + // if (!zrUtil.isArray(properties)) { + // properties = properties != null ? [properties] : []; + // } + // zrUtil.each(properties, function (prop) { + // let value = obj[prop]; + // Object.defineProperty + // && Object.defineProperty(obj, prop, { + // value: value, writable: false + // }); + // zrUtil.isArray(obj[prop]) + // && Object.freeze + // && Object.freeze(obj[prop]); + // }); + // } + + function makeStyleMapper(properties, ignoreParent) { + // Normalize + for (var i = 0; i < properties.length; i++) { + if (!properties[i][1]) { + properties[i][1] = properties[i][0]; + } + } + + ignoreParent = ignoreParent || false; + return function (model, excludes, includes) { + var style = {}; + + for (var i = 0; i < properties.length; i++) { + var propName = properties[i][1]; + + if (excludes && indexOf(excludes, propName) >= 0 || includes && indexOf(includes, propName) < 0) { + continue; + } + + var val = model.getShallow(propName, ignoreParent); + + if (val != null) { + style[properties[i][0]] = val; + } + } // TODO Text or image? + + + return style; + }; + } + + var AREA_STYLE_KEY_MAP = [['fill', 'color'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['opacity'], ['shadowColor'] // Option decal is in `DecalObject` but style.decal is in `PatternObject`. + // So do not transfer decal directly. + ]; + var getAreaStyle = makeStyleMapper(AREA_STYLE_KEY_MAP); + + var AreaStyleMixin = + /** @class */ + function () { + function AreaStyleMixin() {} + + AreaStyleMixin.prototype.getAreaStyle = function (excludes, includes) { + return getAreaStyle(this, excludes, includes); + }; + + return AreaStyleMixin; + }(); + + var globalImageCache = new LRU(50); + function findExistImage(newImageOrSrc) { + if (typeof newImageOrSrc === 'string') { + var cachedImgObj = globalImageCache.get(newImageOrSrc); + return cachedImgObj && cachedImgObj.image; + } + else { + return newImageOrSrc; + } + } + function createOrUpdateImage(newImageOrSrc, image, hostEl, onload, cbPayload) { + if (!newImageOrSrc) { + return image; + } + else if (typeof newImageOrSrc === 'string') { + if ((image && image.__zrImageSrc === newImageOrSrc) || !hostEl) { + return image; + } + var cachedImgObj = globalImageCache.get(newImageOrSrc); + var pendingWrap = { hostEl: hostEl, cb: onload, cbPayload: cbPayload }; + if (cachedImgObj) { + image = cachedImgObj.image; + !isImageReady(image) && cachedImgObj.pending.push(pendingWrap); + } + else { + var image_1 = platformApi.loadImage(newImageOrSrc, imageOnLoad, imageOnLoad); + image_1.__zrImageSrc = newImageOrSrc; + globalImageCache.put(newImageOrSrc, image_1.__cachedImgObj = { + image: image_1, + pending: [pendingWrap] + }); + } + return image; + } + else { + return newImageOrSrc; + } + } + function imageOnLoad() { + var cachedImgObj = this.__cachedImgObj; + this.onload = this.onerror = this.__cachedImgObj = null; + for (var i = 0; i < cachedImgObj.pending.length; i++) { + var pendingWrap = cachedImgObj.pending[i]; + var cb = pendingWrap.cb; + cb && cb(this, pendingWrap.cbPayload); + pendingWrap.hostEl.dirty(); + } + cachedImgObj.pending.length = 0; + } + function isImageReady(image) { + return image && image.width && image.height; + } + + var STYLE_REG = /\{([a-zA-Z0-9_]+)\|([^}]*)\}/g; + function truncateText(text, containerWidth, font, ellipsis, options) { + if (!containerWidth) { + return ''; + } + var textLines = (text + '').split('\n'); + options = prepareTruncateOptions(containerWidth, font, ellipsis, options); + for (var i = 0, len = textLines.length; i < len; i++) { + textLines[i] = truncateSingleLine(textLines[i], options); + } + return textLines.join('\n'); + } + function prepareTruncateOptions(containerWidth, font, ellipsis, options) { + options = options || {}; + var preparedOpts = extend({}, options); + preparedOpts.font = font; + ellipsis = retrieve2(ellipsis, '...'); + preparedOpts.maxIterations = retrieve2(options.maxIterations, 2); + var minChar = preparedOpts.minChar = retrieve2(options.minChar, 0); + preparedOpts.cnCharWidth = getWidth('国', font); + var ascCharWidth = preparedOpts.ascCharWidth = getWidth('a', font); + preparedOpts.placeholder = retrieve2(options.placeholder, ''); + var contentWidth = containerWidth = Math.max(0, containerWidth - 1); + for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) { + contentWidth -= ascCharWidth; + } + var ellipsisWidth = getWidth(ellipsis, font); + if (ellipsisWidth > contentWidth) { + ellipsis = ''; + ellipsisWidth = 0; + } + contentWidth = containerWidth - ellipsisWidth; + preparedOpts.ellipsis = ellipsis; + preparedOpts.ellipsisWidth = ellipsisWidth; + preparedOpts.contentWidth = contentWidth; + preparedOpts.containerWidth = containerWidth; + return preparedOpts; + } + function truncateSingleLine(textLine, options) { + var containerWidth = options.containerWidth; + var font = options.font; + var contentWidth = options.contentWidth; + if (!containerWidth) { + return ''; + } + var lineWidth = getWidth(textLine, font); + if (lineWidth <= containerWidth) { + return textLine; + } + for (var j = 0;; j++) { + if (lineWidth <= contentWidth || j >= options.maxIterations) { + textLine += options.ellipsis; + break; + } + var subLength = j === 0 + ? estimateLength(textLine, contentWidth, options.ascCharWidth, options.cnCharWidth) + : lineWidth > 0 + ? Math.floor(textLine.length * contentWidth / lineWidth) + : 0; + textLine = textLine.substr(0, subLength); + lineWidth = getWidth(textLine, font); + } + if (textLine === '') { + textLine = options.placeholder; + } + return textLine; + } + function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) { + var width = 0; + var i = 0; + for (var len = text.length; i < len && width < contentWidth; i++) { + var charCode = text.charCodeAt(i); + width += (0 <= charCode && charCode <= 127) ? ascCharWidth : cnCharWidth; + } + return i; + } + function parsePlainText(text, style) { + text != null && (text += ''); + var overflow = style.overflow; + var padding = style.padding; + var font = style.font; + var truncate = overflow === 'truncate'; + var calculatedLineHeight = getLineHeight(font); + var lineHeight = retrieve2(style.lineHeight, calculatedLineHeight); + var bgColorDrawn = !!(style.backgroundColor); + var truncateLineOverflow = style.lineOverflow === 'truncate'; + var width = style.width; + var lines; + if (width != null && (overflow === 'break' || overflow === 'breakAll')) { + lines = text ? wrapText(text, style.font, width, overflow === 'breakAll', 0).lines : []; + } + else { + lines = text ? text.split('\n') : []; + } + var contentHeight = lines.length * lineHeight; + var height = retrieve2(style.height, contentHeight); + if (contentHeight > height && truncateLineOverflow) { + var lineCount = Math.floor(height / lineHeight); + lines = lines.slice(0, lineCount); + } + if (text && truncate && width != null) { + var options = prepareTruncateOptions(width, font, style.ellipsis, { + minChar: style.truncateMinChar, + placeholder: style.placeholder + }); + for (var i = 0; i < lines.length; i++) { + lines[i] = truncateSingleLine(lines[i], options); + } + } + var outerHeight = height; + var contentWidth = 0; + for (var i = 0; i < lines.length; i++) { + contentWidth = Math.max(getWidth(lines[i], font), contentWidth); + } + if (width == null) { + width = contentWidth; + } + var outerWidth = contentWidth; + if (padding) { + outerHeight += padding[0] + padding[2]; + outerWidth += padding[1] + padding[3]; + width += padding[1] + padding[3]; + } + if (bgColorDrawn) { + outerWidth = width; + } + return { + lines: lines, + height: height, + outerWidth: outerWidth, + outerHeight: outerHeight, + lineHeight: lineHeight, + calculatedLineHeight: calculatedLineHeight, + contentWidth: contentWidth, + contentHeight: contentHeight, + width: width + }; + } + var RichTextToken = (function () { + function RichTextToken() { + } + return RichTextToken; + }()); + var RichTextLine = (function () { + function RichTextLine(tokens) { + this.tokens = []; + if (tokens) { + this.tokens = tokens; + } + } + return RichTextLine; + }()); + var RichTextContentBlock = (function () { + function RichTextContentBlock() { + this.width = 0; + this.height = 0; + this.contentWidth = 0; + this.contentHeight = 0; + this.outerWidth = 0; + this.outerHeight = 0; + this.lines = []; + } + return RichTextContentBlock; + }()); + function parseRichText(text, style) { + var contentBlock = new RichTextContentBlock(); + text != null && (text += ''); + if (!text) { + return contentBlock; + } + var topWidth = style.width; + var topHeight = style.height; + var overflow = style.overflow; + var wrapInfo = (overflow === 'break' || overflow === 'breakAll') && topWidth != null + ? { width: topWidth, accumWidth: 0, breakAll: overflow === 'breakAll' } + : null; + var lastIndex = STYLE_REG.lastIndex = 0; + var result; + while ((result = STYLE_REG.exec(text)) != null) { + var matchedIndex = result.index; + if (matchedIndex > lastIndex) { + pushTokens(contentBlock, text.substring(lastIndex, matchedIndex), style, wrapInfo); + } + pushTokens(contentBlock, result[2], style, wrapInfo, result[1]); + lastIndex = STYLE_REG.lastIndex; + } + if (lastIndex < text.length) { + pushTokens(contentBlock, text.substring(lastIndex, text.length), style, wrapInfo); + } + var pendingList = []; + var calculatedHeight = 0; + var calculatedWidth = 0; + var stlPadding = style.padding; + var truncate = overflow === 'truncate'; + var truncateLine = style.lineOverflow === 'truncate'; + function finishLine(line, lineWidth, lineHeight) { + line.width = lineWidth; + line.lineHeight = lineHeight; + calculatedHeight += lineHeight; + calculatedWidth = Math.max(calculatedWidth, lineWidth); + } + outer: for (var i = 0; i < contentBlock.lines.length; i++) { + var line = contentBlock.lines[i]; + var lineHeight = 0; + var lineWidth = 0; + for (var j = 0; j < line.tokens.length; j++) { + var token = line.tokens[j]; + var tokenStyle = token.styleName && style.rich[token.styleName] || {}; + var textPadding = token.textPadding = tokenStyle.padding; + var paddingH = textPadding ? textPadding[1] + textPadding[3] : 0; + var font = token.font = tokenStyle.font || style.font; + token.contentHeight = getLineHeight(font); + var tokenHeight = retrieve2(tokenStyle.height, token.contentHeight); + token.innerHeight = tokenHeight; + textPadding && (tokenHeight += textPadding[0] + textPadding[2]); + token.height = tokenHeight; + token.lineHeight = retrieve3(tokenStyle.lineHeight, style.lineHeight, tokenHeight); + token.align = tokenStyle && tokenStyle.align || style.align; + token.verticalAlign = tokenStyle && tokenStyle.verticalAlign || 'middle'; + if (truncateLine && topHeight != null && calculatedHeight + token.lineHeight > topHeight) { + if (j > 0) { + line.tokens = line.tokens.slice(0, j); + finishLine(line, lineWidth, lineHeight); + contentBlock.lines = contentBlock.lines.slice(0, i + 1); + } + else { + contentBlock.lines = contentBlock.lines.slice(0, i); + } + break outer; + } + var styleTokenWidth = tokenStyle.width; + var tokenWidthNotSpecified = styleTokenWidth == null || styleTokenWidth === 'auto'; + if (typeof styleTokenWidth === 'string' && styleTokenWidth.charAt(styleTokenWidth.length - 1) === '%') { + token.percentWidth = styleTokenWidth; + pendingList.push(token); + token.contentWidth = getWidth(token.text, font); + } + else { + if (tokenWidthNotSpecified) { + var textBackgroundColor = tokenStyle.backgroundColor; + var bgImg = textBackgroundColor && textBackgroundColor.image; + if (bgImg) { + bgImg = findExistImage(bgImg); + if (isImageReady(bgImg)) { + token.width = Math.max(token.width, bgImg.width * tokenHeight / bgImg.height); + } + } + } + var remainTruncWidth = truncate && topWidth != null + ? topWidth - lineWidth : null; + if (remainTruncWidth != null && remainTruncWidth < token.width) { + if (!tokenWidthNotSpecified || remainTruncWidth < paddingH) { + token.text = ''; + token.width = token.contentWidth = 0; + } + else { + token.text = truncateText(token.text, remainTruncWidth - paddingH, font, style.ellipsis, { minChar: style.truncateMinChar }); + token.width = token.contentWidth = getWidth(token.text, font); + } + } + else { + token.contentWidth = getWidth(token.text, font); + } + } + token.width += paddingH; + lineWidth += token.width; + tokenStyle && (lineHeight = Math.max(lineHeight, token.lineHeight)); + } + finishLine(line, lineWidth, lineHeight); + } + contentBlock.outerWidth = contentBlock.width = retrieve2(topWidth, calculatedWidth); + contentBlock.outerHeight = contentBlock.height = retrieve2(topHeight, calculatedHeight); + contentBlock.contentHeight = calculatedHeight; + contentBlock.contentWidth = calculatedWidth; + if (stlPadding) { + contentBlock.outerWidth += stlPadding[1] + stlPadding[3]; + contentBlock.outerHeight += stlPadding[0] + stlPadding[2]; + } + for (var i = 0; i < pendingList.length; i++) { + var token = pendingList[i]; + var percentWidth = token.percentWidth; + token.width = parseInt(percentWidth, 10) / 100 * contentBlock.width; + } + return contentBlock; + } + function pushTokens(block, str, style, wrapInfo, styleName) { + var isEmptyStr = str === ''; + var tokenStyle = styleName && style.rich[styleName] || {}; + var lines = block.lines; + var font = tokenStyle.font || style.font; + var newLine = false; + var strLines; + var linesWidths; + if (wrapInfo) { + var tokenPadding = tokenStyle.padding; + var tokenPaddingH = tokenPadding ? tokenPadding[1] + tokenPadding[3] : 0; + if (tokenStyle.width != null && tokenStyle.width !== 'auto') { + var outerWidth_1 = parsePercent(tokenStyle.width, wrapInfo.width) + tokenPaddingH; + if (lines.length > 0) { + if (outerWidth_1 + wrapInfo.accumWidth > wrapInfo.width) { + strLines = str.split('\n'); + newLine = true; + } + } + wrapInfo.accumWidth = outerWidth_1; + } + else { + var res = wrapText(str, font, wrapInfo.width, wrapInfo.breakAll, wrapInfo.accumWidth); + wrapInfo.accumWidth = res.accumWidth + tokenPaddingH; + linesWidths = res.linesWidths; + strLines = res.lines; + } + } + else { + strLines = str.split('\n'); + } + for (var i = 0; i < strLines.length; i++) { + var text = strLines[i]; + var token = new RichTextToken(); + token.styleName = styleName; + token.text = text; + token.isLineHolder = !text && !isEmptyStr; + if (typeof tokenStyle.width === 'number') { + token.width = tokenStyle.width; + } + else { + token.width = linesWidths + ? linesWidths[i] + : getWidth(text, font); + } + if (!i && !newLine) { + var tokens = (lines[lines.length - 1] || (lines[0] = new RichTextLine())).tokens; + var tokensLen = tokens.length; + (tokensLen === 1 && tokens[0].isLineHolder) + ? (tokens[0] = token) + : ((text || !tokensLen || isEmptyStr) && tokens.push(token)); + } + else { + lines.push(new RichTextLine([token])); + } + } + } + function isLatin(ch) { + var code = ch.charCodeAt(0); + return code >= 0x21 && code <= 0x17F; + } + var breakCharMap = reduce(',&?/;] '.split(''), function (obj, ch) { + obj[ch] = true; + return obj; + }, {}); + function isWordBreakChar(ch) { + if (isLatin(ch)) { + if (breakCharMap[ch]) { + return true; + } + return false; + } + return true; + } + function wrapText(text, font, lineWidth, isBreakAll, lastAccumWidth) { + var lines = []; + var linesWidths = []; + var line = ''; + var currentWord = ''; + var currentWordWidth = 0; + var accumWidth = 0; + for (var i = 0; i < text.length; i++) { + var ch = text.charAt(i); + if (ch === '\n') { + if (currentWord) { + line += currentWord; + accumWidth += currentWordWidth; + } + lines.push(line); + linesWidths.push(accumWidth); + line = ''; + currentWord = ''; + currentWordWidth = 0; + accumWidth = 0; + continue; + } + var chWidth = getWidth(ch, font); + var inWord = isBreakAll ? false : !isWordBreakChar(ch); + if (!lines.length + ? lastAccumWidth + accumWidth + chWidth > lineWidth + : accumWidth + chWidth > lineWidth) { + if (!accumWidth) { + if (inWord) { + lines.push(currentWord); + linesWidths.push(currentWordWidth); + currentWord = ch; + currentWordWidth = chWidth; + } + else { + lines.push(ch); + linesWidths.push(chWidth); + } + } + else if (line || currentWord) { + if (inWord) { + if (!line) { + line = currentWord; + currentWord = ''; + currentWordWidth = 0; + accumWidth = currentWordWidth; + } + lines.push(line); + linesWidths.push(accumWidth - currentWordWidth); + currentWord += ch; + currentWordWidth += chWidth; + line = ''; + accumWidth = currentWordWidth; + } + else { + if (currentWord) { + line += currentWord; + currentWord = ''; + currentWordWidth = 0; + } + lines.push(line); + linesWidths.push(accumWidth); + line = ch; + accumWidth = chWidth; + } + } + continue; + } + accumWidth += chWidth; + if (inWord) { + currentWord += ch; + currentWordWidth += chWidth; + } + else { + if (currentWord) { + line += currentWord; + currentWord = ''; + currentWordWidth = 0; + } + line += ch; + } + } + if (!lines.length && !line) { + line = text; + currentWord = ''; + currentWordWidth = 0; + } + if (currentWord) { + line += currentWord; + } + if (line) { + lines.push(line); + linesWidths.push(accumWidth); + } + if (lines.length === 1) { + accumWidth += lastAccumWidth; + } + return { + accumWidth: accumWidth, + lines: lines, + linesWidths: linesWidths + }; + } + + var STYLE_MAGIC_KEY = '__zr_style_' + Math.round((Math.random() * 10)); + var DEFAULT_COMMON_STYLE = { + shadowBlur: 0, + shadowOffsetX: 0, + shadowOffsetY: 0, + shadowColor: '#000', + opacity: 1, + blend: 'source-over' + }; + var DEFAULT_COMMON_ANIMATION_PROPS = { + style: { + shadowBlur: true, + shadowOffsetX: true, + shadowOffsetY: true, + shadowColor: true, + opacity: true + } + }; + DEFAULT_COMMON_STYLE[STYLE_MAGIC_KEY] = true; + var PRIMARY_STATES_KEYS$1 = ['z', 'z2', 'invisible']; + var PRIMARY_STATES_KEYS_IN_HOVER_LAYER = ['invisible']; + var Displayable = (function (_super) { + __extends(Displayable, _super); + function Displayable(props) { + return _super.call(this, props) || this; + } + Displayable.prototype._init = function (props) { + var keysArr = keys(props); + for (var i = 0; i < keysArr.length; i++) { + var key = keysArr[i]; + if (key === 'style') { + this.useStyle(props[key]); + } + else { + _super.prototype.attrKV.call(this, key, props[key]); + } + } + if (!this.style) { + this.useStyle({}); + } + }; + Displayable.prototype.beforeBrush = function () { }; + Displayable.prototype.afterBrush = function () { }; + Displayable.prototype.innerBeforeBrush = function () { }; + Displayable.prototype.innerAfterBrush = function () { }; + Displayable.prototype.shouldBePainted = function (viewWidth, viewHeight, considerClipPath, considerAncestors) { + var m = this.transform; + if (this.ignore + || this.invisible + || this.style.opacity === 0 + || (this.culling + && isDisplayableCulled(this, viewWidth, viewHeight)) + || (m && !m[0] && !m[3])) { + return false; + } + if (considerClipPath && this.__clipPaths) { + for (var i = 0; i < this.__clipPaths.length; ++i) { + if (this.__clipPaths[i].isZeroArea()) { + return false; + } + } + } + if (considerAncestors && this.parent) { + var parent_1 = this.parent; + while (parent_1) { + if (parent_1.ignore) { + return false; + } + parent_1 = parent_1.parent; + } + } + return true; + }; + Displayable.prototype.contain = function (x, y) { + return this.rectContain(x, y); + }; + Displayable.prototype.traverse = function (cb, context) { + cb.call(context, this); + }; + Displayable.prototype.rectContain = function (x, y) { + var coord = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + return rect.contain(coord[0], coord[1]); + }; + Displayable.prototype.getPaintRect = function () { + var rect = this._paintRect; + if (!this._paintRect || this.__dirty) { + var transform = this.transform; + var elRect = this.getBoundingRect(); + var style = this.style; + var shadowSize = style.shadowBlur || 0; + var shadowOffsetX = style.shadowOffsetX || 0; + var shadowOffsetY = style.shadowOffsetY || 0; + rect = this._paintRect || (this._paintRect = new BoundingRect(0, 0, 0, 0)); + if (transform) { + BoundingRect.applyTransform(rect, elRect, transform); + } + else { + rect.copy(elRect); + } + if (shadowSize || shadowOffsetX || shadowOffsetY) { + rect.width += shadowSize * 2 + Math.abs(shadowOffsetX); + rect.height += shadowSize * 2 + Math.abs(shadowOffsetY); + rect.x = Math.min(rect.x, rect.x + shadowOffsetX - shadowSize); + rect.y = Math.min(rect.y, rect.y + shadowOffsetY - shadowSize); + } + var tolerance = this.dirtyRectTolerance; + if (!rect.isZero()) { + rect.x = Math.floor(rect.x - tolerance); + rect.y = Math.floor(rect.y - tolerance); + rect.width = Math.ceil(rect.width + 1 + tolerance * 2); + rect.height = Math.ceil(rect.height + 1 + tolerance * 2); + } + } + return rect; + }; + Displayable.prototype.setPrevPaintRect = function (paintRect) { + if (paintRect) { + this._prevPaintRect = this._prevPaintRect || new BoundingRect(0, 0, 0, 0); + this._prevPaintRect.copy(paintRect); + } + else { + this._prevPaintRect = null; + } + }; + Displayable.prototype.getPrevPaintRect = function () { + return this._prevPaintRect; + }; + Displayable.prototype.animateStyle = function (loop) { + return this.animate('style', loop); + }; + Displayable.prototype.updateDuringAnimation = function (targetKey) { + if (targetKey === 'style') { + this.dirtyStyle(); + } + else { + this.markRedraw(); + } + }; + Displayable.prototype.attrKV = function (key, value) { + if (key !== 'style') { + _super.prototype.attrKV.call(this, key, value); + } + else { + if (!this.style) { + this.useStyle(value); + } + else { + this.setStyle(value); + } + } + }; + Displayable.prototype.setStyle = function (keyOrObj, value) { + if (typeof keyOrObj === 'string') { + this.style[keyOrObj] = value; + } + else { + extend(this.style, keyOrObj); + } + this.dirtyStyle(); + return this; + }; + Displayable.prototype.dirtyStyle = function (notRedraw) { + if (!notRedraw) { + this.markRedraw(); + } + this.__dirty |= STYLE_CHANGED_BIT; + if (this._rect) { + this._rect = null; + } + }; + Displayable.prototype.dirty = function () { + this.dirtyStyle(); + }; + Displayable.prototype.styleChanged = function () { + return !!(this.__dirty & STYLE_CHANGED_BIT); + }; + Displayable.prototype.styleUpdated = function () { + this.__dirty &= ~STYLE_CHANGED_BIT; + }; + Displayable.prototype.createStyle = function (obj) { + return createObject(DEFAULT_COMMON_STYLE, obj); + }; + Displayable.prototype.useStyle = function (obj) { + if (!obj[STYLE_MAGIC_KEY]) { + obj = this.createStyle(obj); + } + if (this.__inHover) { + this.__hoverStyle = obj; + } + else { + this.style = obj; + } + this.dirtyStyle(); + }; + Displayable.prototype.isStyleObject = function (obj) { + return obj[STYLE_MAGIC_KEY]; + }; + Displayable.prototype._innerSaveToNormal = function (toState) { + _super.prototype._innerSaveToNormal.call(this, toState); + var normalState = this._normalState; + if (toState.style && !normalState.style) { + normalState.style = this._mergeStyle(this.createStyle(), this.style); + } + this._savePrimaryToNormal(toState, normalState, PRIMARY_STATES_KEYS$1); + }; + Displayable.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) { + _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg); + var needsRestoreToNormal = !(state && keepCurrentStates); + var targetStyle; + if (state && state.style) { + if (transition) { + if (keepCurrentStates) { + targetStyle = state.style; + } + else { + targetStyle = this._mergeStyle(this.createStyle(), normalState.style); + this._mergeStyle(targetStyle, state.style); + } + } + else { + targetStyle = this._mergeStyle(this.createStyle(), keepCurrentStates ? this.style : normalState.style); + this._mergeStyle(targetStyle, state.style); + } + } + else if (needsRestoreToNormal) { + targetStyle = normalState.style; + } + if (targetStyle) { + if (transition) { + var sourceStyle = this.style; + this.style = this.createStyle(needsRestoreToNormal ? {} : sourceStyle); + if (needsRestoreToNormal) { + var changedKeys = keys(sourceStyle); + for (var i = 0; i < changedKeys.length; i++) { + var key = changedKeys[i]; + if (key in targetStyle) { + targetStyle[key] = targetStyle[key]; + this.style[key] = sourceStyle[key]; + } + } + } + var targetKeys = keys(targetStyle); + for (var i = 0; i < targetKeys.length; i++) { + var key = targetKeys[i]; + this.style[key] = this.style[key]; + } + this._transitionState(stateName, { + style: targetStyle + }, animationCfg, this.getAnimationStyleProps()); + } + else { + this.useStyle(targetStyle); + } + } + var statesKeys = this.__inHover ? PRIMARY_STATES_KEYS_IN_HOVER_LAYER : PRIMARY_STATES_KEYS$1; + for (var i = 0; i < statesKeys.length; i++) { + var key = statesKeys[i]; + if (state && state[key] != null) { + this[key] = state[key]; + } + else if (needsRestoreToNormal) { + if (normalState[key] != null) { + this[key] = normalState[key]; + } + } + } + }; + Displayable.prototype._mergeStates = function (states) { + var mergedState = _super.prototype._mergeStates.call(this, states); + var mergedStyle; + for (var i = 0; i < states.length; i++) { + var state = states[i]; + if (state.style) { + mergedStyle = mergedStyle || {}; + this._mergeStyle(mergedStyle, state.style); + } + } + if (mergedStyle) { + mergedState.style = mergedStyle; + } + return mergedState; + }; + Displayable.prototype._mergeStyle = function (targetStyle, sourceStyle) { + extend(targetStyle, sourceStyle); + return targetStyle; + }; + Displayable.prototype.getAnimationStyleProps = function () { + return DEFAULT_COMMON_ANIMATION_PROPS; + }; + Displayable.initDefaultProps = (function () { + var dispProto = Displayable.prototype; + dispProto.type = 'displayable'; + dispProto.invisible = false; + dispProto.z = 0; + dispProto.z2 = 0; + dispProto.zlevel = 0; + dispProto.culling = false; + dispProto.cursor = 'pointer'; + dispProto.rectHover = false; + dispProto.incremental = false; + dispProto._rect = null; + dispProto.dirtyRectTolerance = 0; + dispProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT; + })(); + return Displayable; + }(Element)); + var tmpRect = new BoundingRect(0, 0, 0, 0); + var viewRect = new BoundingRect(0, 0, 0, 0); + function isDisplayableCulled(el, width, height) { + tmpRect.copy(el.getBoundingRect()); + if (el.transform) { + tmpRect.applyTransform(el.transform); + } + viewRect.width = width; + viewRect.height = height; + return !tmpRect.intersect(viewRect); + } + + var mathMin$1 = Math.min; + var mathMax$1 = Math.max; + var mathSin = Math.sin; + var mathCos = Math.cos; + var PI2 = Math.PI * 2; + var start = create(); + var end = create(); + var extremity = create(); + function fromPoints(points, min, max) { + if (points.length === 0) { + return; + } + var p = points[0]; + var left = p[0]; + var right = p[0]; + var top = p[1]; + var bottom = p[1]; + for (var i = 1; i < points.length; i++) { + p = points[i]; + left = mathMin$1(left, p[0]); + right = mathMax$1(right, p[0]); + top = mathMin$1(top, p[1]); + bottom = mathMax$1(bottom, p[1]); + } + min[0] = left; + min[1] = top; + max[0] = right; + max[1] = bottom; + } + function fromLine(x0, y0, x1, y1, min, max) { + min[0] = mathMin$1(x0, x1); + min[1] = mathMin$1(y0, y1); + max[0] = mathMax$1(x0, x1); + max[1] = mathMax$1(y0, y1); + } + var xDim = []; + var yDim = []; + function fromCubic(x0, y0, x1, y1, x2, y2, x3, y3, min, max) { + var cubicExtrema$1 = cubicExtrema; + var cubicAt$1 = cubicAt; + var n = cubicExtrema$1(x0, x1, x2, x3, xDim); + min[0] = Infinity; + min[1] = Infinity; + max[0] = -Infinity; + max[1] = -Infinity; + for (var i = 0; i < n; i++) { + var x = cubicAt$1(x0, x1, x2, x3, xDim[i]); + min[0] = mathMin$1(x, min[0]); + max[0] = mathMax$1(x, max[0]); + } + n = cubicExtrema$1(y0, y1, y2, y3, yDim); + for (var i = 0; i < n; i++) { + var y = cubicAt$1(y0, y1, y2, y3, yDim[i]); + min[1] = mathMin$1(y, min[1]); + max[1] = mathMax$1(y, max[1]); + } + min[0] = mathMin$1(x0, min[0]); + max[0] = mathMax$1(x0, max[0]); + min[0] = mathMin$1(x3, min[0]); + max[0] = mathMax$1(x3, max[0]); + min[1] = mathMin$1(y0, min[1]); + max[1] = mathMax$1(y0, max[1]); + min[1] = mathMin$1(y3, min[1]); + max[1] = mathMax$1(y3, max[1]); + } + function fromQuadratic(x0, y0, x1, y1, x2, y2, min, max) { + var quadraticExtremum$1 = quadraticExtremum; + var quadraticAt$1 = quadraticAt; + var tx = mathMax$1(mathMin$1(quadraticExtremum$1(x0, x1, x2), 1), 0); + var ty = mathMax$1(mathMin$1(quadraticExtremum$1(y0, y1, y2), 1), 0); + var x = quadraticAt$1(x0, x1, x2, tx); + var y = quadraticAt$1(y0, y1, y2, ty); + min[0] = mathMin$1(x0, x2, x); + min[1] = mathMin$1(y0, y2, y); + max[0] = mathMax$1(x0, x2, x); + max[1] = mathMax$1(y0, y2, y); + } + function fromArc(x, y, rx, ry, startAngle, endAngle, anticlockwise, min$1, max$1) { + var vec2Min = min; + var vec2Max = max; + var diff = Math.abs(startAngle - endAngle); + if (diff % PI2 < 1e-4 && diff > 1e-4) { + min$1[0] = x - rx; + min$1[1] = y - ry; + max$1[0] = x + rx; + max$1[1] = y + ry; + return; + } + start[0] = mathCos(startAngle) * rx + x; + start[1] = mathSin(startAngle) * ry + y; + end[0] = mathCos(endAngle) * rx + x; + end[1] = mathSin(endAngle) * ry + y; + vec2Min(min$1, start, end); + vec2Max(max$1, start, end); + startAngle = startAngle % (PI2); + if (startAngle < 0) { + startAngle = startAngle + PI2; + } + endAngle = endAngle % (PI2); + if (endAngle < 0) { + endAngle = endAngle + PI2; + } + if (startAngle > endAngle && !anticlockwise) { + endAngle += PI2; + } + else if (startAngle < endAngle && anticlockwise) { + startAngle += PI2; + } + if (anticlockwise) { + var tmp = endAngle; + endAngle = startAngle; + startAngle = tmp; + } + for (var angle = 0; angle < endAngle; angle += Math.PI / 2) { + if (angle > startAngle) { + extremity[0] = mathCos(angle) * rx + x; + extremity[1] = mathSin(angle) * ry + y; + vec2Min(min$1, extremity, min$1); + vec2Max(max$1, extremity, max$1); + } + } + } + + var CMD = { + M: 1, + L: 2, + C: 3, + Q: 4, + A: 5, + Z: 6, + R: 7 + }; + var tmpOutX = []; + var tmpOutY = []; + var min$1 = []; + var max$1 = []; + var min2 = []; + var max2 = []; + var mathMin$2 = Math.min; + var mathMax$2 = Math.max; + var mathCos$1 = Math.cos; + var mathSin$1 = Math.sin; + var mathAbs = Math.abs; + var PI = Math.PI; + var PI2$1 = PI * 2; + var hasTypedArray = typeof Float32Array !== 'undefined'; + var tmpAngles = []; + function modPI2(radian) { + var n = Math.round(radian / PI * 1e8) / 1e8; + return (n % 2) * PI; + } + function normalizeArcAngles(angles, anticlockwise) { + var newStartAngle = modPI2(angles[0]); + if (newStartAngle < 0) { + newStartAngle += PI2$1; + } + var delta = newStartAngle - angles[0]; + var newEndAngle = angles[1]; + newEndAngle += delta; + if (!anticlockwise && newEndAngle - newStartAngle >= PI2$1) { + newEndAngle = newStartAngle + PI2$1; + } + else if (anticlockwise && newStartAngle - newEndAngle >= PI2$1) { + newEndAngle = newStartAngle - PI2$1; + } + else if (!anticlockwise && newStartAngle > newEndAngle) { + newEndAngle = newStartAngle + (PI2$1 - modPI2(newStartAngle - newEndAngle)); + } + else if (anticlockwise && newStartAngle < newEndAngle) { + newEndAngle = newStartAngle - (PI2$1 - modPI2(newEndAngle - newStartAngle)); + } + angles[0] = newStartAngle; + angles[1] = newEndAngle; + } + var PathProxy = (function () { + function PathProxy(notSaveData) { + this.dpr = 1; + this._xi = 0; + this._yi = 0; + this._x0 = 0; + this._y0 = 0; + this._len = 0; + if (notSaveData) { + this._saveData = false; + } + if (this._saveData) { + this.data = []; + } + } + PathProxy.prototype.increaseVersion = function () { + this._version++; + }; + PathProxy.prototype.getVersion = function () { + return this._version; + }; + PathProxy.prototype.setScale = function (sx, sy, segmentIgnoreThreshold) { + segmentIgnoreThreshold = segmentIgnoreThreshold || 0; + if (segmentIgnoreThreshold > 0) { + this._ux = mathAbs(segmentIgnoreThreshold / devicePixelRatio / sx) || 0; + this._uy = mathAbs(segmentIgnoreThreshold / devicePixelRatio / sy) || 0; + } + }; + PathProxy.prototype.setDPR = function (dpr) { + this.dpr = dpr; + }; + PathProxy.prototype.setContext = function (ctx) { + this._ctx = ctx; + }; + PathProxy.prototype.getContext = function () { + return this._ctx; + }; + PathProxy.prototype.beginPath = function () { + this._ctx && this._ctx.beginPath(); + this.reset(); + return this; + }; + PathProxy.prototype.reset = function () { + if (this._saveData) { + this._len = 0; + } + if (this._pathSegLen) { + this._pathSegLen = null; + this._pathLen = 0; + } + this._version++; + }; + PathProxy.prototype.moveTo = function (x, y) { + this._drawPendingPt(); + this.addData(CMD.M, x, y); + this._ctx && this._ctx.moveTo(x, y); + this._x0 = x; + this._y0 = y; + this._xi = x; + this._yi = y; + return this; + }; + PathProxy.prototype.lineTo = function (x, y) { + var dx = mathAbs(x - this._xi); + var dy = mathAbs(y - this._yi); + var exceedUnit = dx > this._ux || dy > this._uy; + this.addData(CMD.L, x, y); + if (this._ctx && exceedUnit) { + this._ctx.lineTo(x, y); + } + if (exceedUnit) { + this._xi = x; + this._yi = y; + this._pendingPtDist = 0; + } + else { + var d2 = dx * dx + dy * dy; + if (d2 > this._pendingPtDist) { + this._pendingPtX = x; + this._pendingPtY = y; + this._pendingPtDist = d2; + } + } + return this; + }; + PathProxy.prototype.bezierCurveTo = function (x1, y1, x2, y2, x3, y3) { + this._drawPendingPt(); + this.addData(CMD.C, x1, y1, x2, y2, x3, y3); + if (this._ctx) { + this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); + } + this._xi = x3; + this._yi = y3; + return this; + }; + PathProxy.prototype.quadraticCurveTo = function (x1, y1, x2, y2) { + this._drawPendingPt(); + this.addData(CMD.Q, x1, y1, x2, y2); + if (this._ctx) { + this._ctx.quadraticCurveTo(x1, y1, x2, y2); + } + this._xi = x2; + this._yi = y2; + return this; + }; + PathProxy.prototype.arc = function (cx, cy, r, startAngle, endAngle, anticlockwise) { + this._drawPendingPt(); + tmpAngles[0] = startAngle; + tmpAngles[1] = endAngle; + normalizeArcAngles(tmpAngles, anticlockwise); + startAngle = tmpAngles[0]; + endAngle = tmpAngles[1]; + var delta = endAngle - startAngle; + this.addData(CMD.A, cx, cy, r, r, startAngle, delta, 0, anticlockwise ? 0 : 1); + this._ctx && this._ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise); + this._xi = mathCos$1(endAngle) * r + cx; + this._yi = mathSin$1(endAngle) * r + cy; + return this; + }; + PathProxy.prototype.arcTo = function (x1, y1, x2, y2, radius) { + this._drawPendingPt(); + if (this._ctx) { + this._ctx.arcTo(x1, y1, x2, y2, radius); + } + return this; + }; + PathProxy.prototype.rect = function (x, y, w, h) { + this._drawPendingPt(); + this._ctx && this._ctx.rect(x, y, w, h); + this.addData(CMD.R, x, y, w, h); + return this; + }; + PathProxy.prototype.closePath = function () { + this._drawPendingPt(); + this.addData(CMD.Z); + var ctx = this._ctx; + var x0 = this._x0; + var y0 = this._y0; + if (ctx) { + ctx.closePath(); + } + this._xi = x0; + this._yi = y0; + return this; + }; + PathProxy.prototype.fill = function (ctx) { + ctx && ctx.fill(); + this.toStatic(); + }; + PathProxy.prototype.stroke = function (ctx) { + ctx && ctx.stroke(); + this.toStatic(); + }; + PathProxy.prototype.len = function () { + return this._len; + }; + PathProxy.prototype.setData = function (data) { + var len = data.length; + if (!(this.data && this.data.length === len) && hasTypedArray) { + this.data = new Float32Array(len); + } + for (var i = 0; i < len; i++) { + this.data[i] = data[i]; + } + this._len = len; + }; + PathProxy.prototype.appendPath = function (path) { + if (!(path instanceof Array)) { + path = [path]; + } + var len = path.length; + var appendSize = 0; + var offset = this._len; + for (var i = 0; i < len; i++) { + appendSize += path[i].len(); + } + if (hasTypedArray && (this.data instanceof Float32Array)) { + this.data = new Float32Array(offset + appendSize); + } + for (var i = 0; i < len; i++) { + var appendPathData = path[i].data; + for (var k = 0; k < appendPathData.length; k++) { + this.data[offset++] = appendPathData[k]; + } + } + this._len = offset; + }; + PathProxy.prototype.addData = function (cmd, a, b, c, d, e, f, g, h) { + if (!this._saveData) { + return; + } + var data = this.data; + if (this._len + arguments.length > data.length) { + this._expandData(); + data = this.data; + } + for (var i = 0; i < arguments.length; i++) { + data[this._len++] = arguments[i]; + } + }; + PathProxy.prototype._drawPendingPt = function () { + if (this._pendingPtDist > 0) { + this._ctx && this._ctx.lineTo(this._pendingPtX, this._pendingPtY); + this._pendingPtDist = 0; + } + }; + PathProxy.prototype._expandData = function () { + if (!(this.data instanceof Array)) { + var newData = []; + for (var i = 0; i < this._len; i++) { + newData[i] = this.data[i]; + } + this.data = newData; + } + }; + PathProxy.prototype.toStatic = function () { + if (!this._saveData) { + return; + } + this._drawPendingPt(); + var data = this.data; + if (data instanceof Array) { + data.length = this._len; + if (hasTypedArray && this._len > 11) { + this.data = new Float32Array(data); + } + } + }; + PathProxy.prototype.getBoundingRect = function () { + min$1[0] = min$1[1] = min2[0] = min2[1] = Number.MAX_VALUE; + max$1[0] = max$1[1] = max2[0] = max2[1] = -Number.MAX_VALUE; + var data = this.data; + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + var i; + for (i = 0; i < this._len;) { + var cmd = data[i++]; + var isFirst = i === 1; + if (isFirst) { + xi = data[i]; + yi = data[i + 1]; + x0 = xi; + y0 = yi; + } + switch (cmd) { + case CMD.M: + xi = x0 = data[i++]; + yi = y0 = data[i++]; + min2[0] = x0; + min2[1] = y0; + max2[0] = x0; + max2[1] = y0; + break; + case CMD.L: + fromLine(xi, yi, data[i], data[i + 1], min2, max2); + xi = data[i++]; + yi = data[i++]; + break; + case CMD.C: + fromCubic(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], min2, max2); + xi = data[i++]; + yi = data[i++]; + break; + case CMD.Q: + fromQuadratic(xi, yi, data[i++], data[i++], data[i], data[i + 1], min2, max2); + xi = data[i++]; + yi = data[i++]; + break; + case CMD.A: + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var startAngle = data[i++]; + var endAngle = data[i++] + startAngle; + i += 1; + var anticlockwise = !data[i++]; + if (isFirst) { + x0 = mathCos$1(startAngle) * rx + cx; + y0 = mathSin$1(startAngle) * ry + cy; + } + fromArc(cx, cy, rx, ry, startAngle, endAngle, anticlockwise, min2, max2); + xi = mathCos$1(endAngle) * rx + cx; + yi = mathSin$1(endAngle) * ry + cy; + break; + case CMD.R: + x0 = xi = data[i++]; + y0 = yi = data[i++]; + var width = data[i++]; + var height = data[i++]; + fromLine(x0, y0, x0 + width, y0 + height, min2, max2); + break; + case CMD.Z: + xi = x0; + yi = y0; + break; + } + min(min$1, min$1, min2); + max(max$1, max$1, max2); + } + if (i === 0) { + min$1[0] = min$1[1] = max$1[0] = max$1[1] = 0; + } + return new BoundingRect(min$1[0], min$1[1], max$1[0] - min$1[0], max$1[1] - min$1[1]); + }; + PathProxy.prototype._calculateLength = function () { + var data = this.data; + var len = this._len; + var ux = this._ux; + var uy = this._uy; + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + if (!this._pathSegLen) { + this._pathSegLen = []; + } + var pathSegLen = this._pathSegLen; + var pathTotalLen = 0; + var segCount = 0; + for (var i = 0; i < len;) { + var cmd = data[i++]; + var isFirst = i === 1; + if (isFirst) { + xi = data[i]; + yi = data[i + 1]; + x0 = xi; + y0 = yi; + } + var l = -1; + switch (cmd) { + case CMD.M: + xi = x0 = data[i++]; + yi = y0 = data[i++]; + break; + case CMD.L: { + var x2 = data[i++]; + var y2 = data[i++]; + var dx = x2 - xi; + var dy = y2 - yi; + if (mathAbs(dx) > ux || mathAbs(dy) > uy || i === len - 1) { + l = Math.sqrt(dx * dx + dy * dy); + xi = x2; + yi = y2; + } + break; + } + case CMD.C: { + var x1 = data[i++]; + var y1 = data[i++]; + var x2 = data[i++]; + var y2 = data[i++]; + var x3 = data[i++]; + var y3 = data[i++]; + l = cubicLength(xi, yi, x1, y1, x2, y2, x3, y3, 10); + xi = x3; + yi = y3; + break; + } + case CMD.Q: { + var x1 = data[i++]; + var y1 = data[i++]; + var x2 = data[i++]; + var y2 = data[i++]; + l = quadraticLength(xi, yi, x1, y1, x2, y2, 10); + xi = x2; + yi = y2; + break; + } + case CMD.A: + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var startAngle = data[i++]; + var delta = data[i++]; + var endAngle = delta + startAngle; + i += 1; + var anticlockwise = !data[i++]; + if (isFirst) { + x0 = mathCos$1(startAngle) * rx + cx; + y0 = mathSin$1(startAngle) * ry + cy; + } + l = mathMax$2(rx, ry) * mathMin$2(PI2$1, Math.abs(delta)); + xi = mathCos$1(endAngle) * rx + cx; + yi = mathSin$1(endAngle) * ry + cy; + break; + case CMD.R: { + x0 = xi = data[i++]; + y0 = yi = data[i++]; + var width = data[i++]; + var height = data[i++]; + l = width * 2 + height * 2; + break; + } + case CMD.Z: { + var dx = x0 - xi; + var dy = y0 - yi; + l = Math.sqrt(dx * dx + dy * dy); + xi = x0; + yi = y0; + break; + } + } + if (l >= 0) { + pathSegLen[segCount++] = l; + pathTotalLen += l; + } + } + this._pathLen = pathTotalLen; + return pathTotalLen; + }; + PathProxy.prototype.rebuildPath = function (ctx, percent) { + var d = this.data; + var ux = this._ux; + var uy = this._uy; + var len = this._len; + var x0; + var y0; + var xi; + var yi; + var x; + var y; + var drawPart = percent < 1; + var pathSegLen; + var pathTotalLen; + var accumLength = 0; + var segCount = 0; + var displayedLength; + var pendingPtDist = 0; + var pendingPtX; + var pendingPtY; + if (drawPart) { + if (!this._pathSegLen) { + this._calculateLength(); + } + pathSegLen = this._pathSegLen; + pathTotalLen = this._pathLen; + displayedLength = percent * pathTotalLen; + if (!displayedLength) { + return; + } + } + lo: for (var i = 0; i < len;) { + var cmd = d[i++]; + var isFirst = i === 1; + if (isFirst) { + xi = d[i]; + yi = d[i + 1]; + x0 = xi; + y0 = yi; + } + if (cmd !== CMD.L && pendingPtDist > 0) { + ctx.lineTo(pendingPtX, pendingPtY); + pendingPtDist = 0; + } + switch (cmd) { + case CMD.M: + x0 = xi = d[i++]; + y0 = yi = d[i++]; + ctx.moveTo(xi, yi); + break; + case CMD.L: { + x = d[i++]; + y = d[i++]; + var dx = mathAbs(x - xi); + var dy = mathAbs(y - yi); + if (dx > ux || dy > uy) { + if (drawPart) { + var l = pathSegLen[segCount++]; + if (accumLength + l > displayedLength) { + var t = (displayedLength - accumLength) / l; + ctx.lineTo(xi * (1 - t) + x * t, yi * (1 - t) + y * t); + break lo; + } + accumLength += l; + } + ctx.lineTo(x, y); + xi = x; + yi = y; + pendingPtDist = 0; + } + else { + var d2 = dx * dx + dy * dy; + if (d2 > pendingPtDist) { + pendingPtX = x; + pendingPtY = y; + pendingPtDist = d2; + } + } + break; + } + case CMD.C: { + var x1 = d[i++]; + var y1 = d[i++]; + var x2 = d[i++]; + var y2 = d[i++]; + var x3 = d[i++]; + var y3 = d[i++]; + if (drawPart) { + var l = pathSegLen[segCount++]; + if (accumLength + l > displayedLength) { + var t = (displayedLength - accumLength) / l; + cubicSubdivide(xi, x1, x2, x3, t, tmpOutX); + cubicSubdivide(yi, y1, y2, y3, t, tmpOutY); + ctx.bezierCurveTo(tmpOutX[1], tmpOutY[1], tmpOutX[2], tmpOutY[2], tmpOutX[3], tmpOutY[3]); + break lo; + } + accumLength += l; + } + ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); + xi = x3; + yi = y3; + break; + } + case CMD.Q: { + var x1 = d[i++]; + var y1 = d[i++]; + var x2 = d[i++]; + var y2 = d[i++]; + if (drawPart) { + var l = pathSegLen[segCount++]; + if (accumLength + l > displayedLength) { + var t = (displayedLength - accumLength) / l; + quadraticSubdivide(xi, x1, x2, t, tmpOutX); + quadraticSubdivide(yi, y1, y2, t, tmpOutY); + ctx.quadraticCurveTo(tmpOutX[1], tmpOutY[1], tmpOutX[2], tmpOutY[2]); + break lo; + } + accumLength += l; + } + ctx.quadraticCurveTo(x1, y1, x2, y2); + xi = x2; + yi = y2; + break; + } + case CMD.A: + var cx = d[i++]; + var cy = d[i++]; + var rx = d[i++]; + var ry = d[i++]; + var startAngle = d[i++]; + var delta = d[i++]; + var psi = d[i++]; + var anticlockwise = !d[i++]; + var r = (rx > ry) ? rx : ry; + var isEllipse = mathAbs(rx - ry) > 1e-3; + var endAngle = startAngle + delta; + var breakBuild = false; + if (drawPart) { + var l = pathSegLen[segCount++]; + if (accumLength + l > displayedLength) { + endAngle = startAngle + delta * (displayedLength - accumLength) / l; + breakBuild = true; + } + accumLength += l; + } + if (isEllipse && ctx.ellipse) { + ctx.ellipse(cx, cy, rx, ry, psi, startAngle, endAngle, anticlockwise); + } + else { + ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise); + } + if (breakBuild) { + break lo; + } + if (isFirst) { + x0 = mathCos$1(startAngle) * rx + cx; + y0 = mathSin$1(startAngle) * ry + cy; + } + xi = mathCos$1(endAngle) * rx + cx; + yi = mathSin$1(endAngle) * ry + cy; + break; + case CMD.R: + x0 = xi = d[i]; + y0 = yi = d[i + 1]; + x = d[i++]; + y = d[i++]; + var width = d[i++]; + var height = d[i++]; + if (drawPart) { + var l = pathSegLen[segCount++]; + if (accumLength + l > displayedLength) { + var d_1 = displayedLength - accumLength; + ctx.moveTo(x, y); + ctx.lineTo(x + mathMin$2(d_1, width), y); + d_1 -= width; + if (d_1 > 0) { + ctx.lineTo(x + width, y + mathMin$2(d_1, height)); + } + d_1 -= height; + if (d_1 > 0) { + ctx.lineTo(x + mathMax$2(width - d_1, 0), y + height); + } + d_1 -= width; + if (d_1 > 0) { + ctx.lineTo(x, y + mathMax$2(height - d_1, 0)); + } + break lo; + } + accumLength += l; + } + ctx.rect(x, y, width, height); + break; + case CMD.Z: + if (drawPart) { + var l = pathSegLen[segCount++]; + if (accumLength + l > displayedLength) { + var t = (displayedLength - accumLength) / l; + ctx.lineTo(xi * (1 - t) + x0 * t, yi * (1 - t) + y0 * t); + break lo; + } + accumLength += l; + } + ctx.closePath(); + xi = x0; + yi = y0; + } + } + }; + PathProxy.prototype.clone = function () { + var newProxy = new PathProxy(); + var data = this.data; + newProxy.data = data.slice ? data.slice() + : Array.prototype.slice.call(data); + newProxy._len = this._len; + return newProxy; + }; + PathProxy.CMD = CMD; + PathProxy.initDefaultProps = (function () { + var proto = PathProxy.prototype; + proto._saveData = true; + proto._ux = 0; + proto._uy = 0; + proto._pendingPtDist = 0; + proto._version = 0; + })(); + return PathProxy; + }()); + + function containStroke(x0, y0, x1, y1, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + var _a = 0; + var _b = x0; + if ((y > y0 + _l && y > y1 + _l) + || (y < y0 - _l && y < y1 - _l) + || (x > x0 + _l && x > x1 + _l) + || (x < x0 - _l && x < x1 - _l)) { + return false; + } + if (x0 !== x1) { + _a = (y0 - y1) / (x0 - x1); + _b = (x0 * y1 - x1 * y0) / (x0 - x1); + } + else { + return Math.abs(x - x0) <= _l / 2; + } + var tmp = _a * x - y + _b; + var _s = tmp * tmp / (_a * _a + 1); + return _s <= _l / 2 * _l / 2; + } + + function containStroke$1(x0, y0, x1, y1, x2, y2, x3, y3, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + if ((y > y0 + _l && y > y1 + _l && y > y2 + _l && y > y3 + _l) + || (y < y0 - _l && y < y1 - _l && y < y2 - _l && y < y3 - _l) + || (x > x0 + _l && x > x1 + _l && x > x2 + _l && x > x3 + _l) + || (x < x0 - _l && x < x1 - _l && x < x2 - _l && x < x3 - _l)) { + return false; + } + var d = cubicProjectPoint(x0, y0, x1, y1, x2, y2, x3, y3, x, y, null); + return d <= _l / 2; + } + + function containStroke$2(x0, y0, x1, y1, x2, y2, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + if ((y > y0 + _l && y > y1 + _l && y > y2 + _l) + || (y < y0 - _l && y < y1 - _l && y < y2 - _l) + || (x > x0 + _l && x > x1 + _l && x > x2 + _l) + || (x < x0 - _l && x < x1 - _l && x < x2 - _l)) { + return false; + } + var d = quadraticProjectPoint(x0, y0, x1, y1, x2, y2, x, y, null); + return d <= _l / 2; + } + + var PI2$2 = Math.PI * 2; + function normalizeRadian(angle) { + angle %= PI2$2; + if (angle < 0) { + angle += PI2$2; + } + return angle; + } + + var PI2$3 = Math.PI * 2; + function containStroke$3(cx, cy, r, startAngle, endAngle, anticlockwise, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + x -= cx; + y -= cy; + var d = Math.sqrt(x * x + y * y); + if ((d - _l > r) || (d + _l < r)) { + return false; + } + if (Math.abs(startAngle - endAngle) % PI2$3 < 1e-4) { + return true; + } + if (anticlockwise) { + var tmp = startAngle; + startAngle = normalizeRadian(endAngle); + endAngle = normalizeRadian(tmp); + } + else { + startAngle = normalizeRadian(startAngle); + endAngle = normalizeRadian(endAngle); + } + if (startAngle > endAngle) { + endAngle += PI2$3; + } + var angle = Math.atan2(y, x); + if (angle < 0) { + angle += PI2$3; + } + return (angle >= startAngle && angle <= endAngle) + || (angle + PI2$3 >= startAngle && angle + PI2$3 <= endAngle); + } + + function windingLine(x0, y0, x1, y1, x, y) { + if ((y > y0 && y > y1) || (y < y0 && y < y1)) { + return 0; + } + if (y1 === y0) { + return 0; + } + var t = (y - y0) / (y1 - y0); + var dir = y1 < y0 ? 1 : -1; + if (t === 1 || t === 0) { + dir = y1 < y0 ? 0.5 : -0.5; + } + var x_ = t * (x1 - x0) + x0; + return x_ === x ? Infinity : x_ > x ? dir : 0; + } + + var CMD$1 = PathProxy.CMD; + var PI2$4 = Math.PI * 2; + var EPSILON$3 = 1e-4; + function isAroundEqual(a, b) { + return Math.abs(a - b) < EPSILON$3; + } + var roots = [-1, -1, -1]; + var extrema = [-1, -1]; + function swapExtrema() { + var tmp = extrema[0]; + extrema[0] = extrema[1]; + extrema[1] = tmp; + } + function windingCubic(x0, y0, x1, y1, x2, y2, x3, y3, x, y) { + if ((y > y0 && y > y1 && y > y2 && y > y3) + || (y < y0 && y < y1 && y < y2 && y < y3)) { + return 0; + } + var nRoots = cubicRootAt(y0, y1, y2, y3, y, roots); + if (nRoots === 0) { + return 0; + } + else { + var w = 0; + var nExtrema = -1; + var y0_ = void 0; + var y1_ = void 0; + for (var i = 0; i < nRoots; i++) { + var t = roots[i]; + var unit = (t === 0 || t === 1) ? 0.5 : 1; + var x_ = cubicAt(x0, x1, x2, x3, t); + if (x_ < x) { + continue; + } + if (nExtrema < 0) { + nExtrema = cubicExtrema(y0, y1, y2, y3, extrema); + if (extrema[1] < extrema[0] && nExtrema > 1) { + swapExtrema(); + } + y0_ = cubicAt(y0, y1, y2, y3, extrema[0]); + if (nExtrema > 1) { + y1_ = cubicAt(y0, y1, y2, y3, extrema[1]); + } + } + if (nExtrema === 2) { + if (t < extrema[0]) { + w += y0_ < y0 ? unit : -unit; + } + else if (t < extrema[1]) { + w += y1_ < y0_ ? unit : -unit; + } + else { + w += y3 < y1_ ? unit : -unit; + } + } + else { + if (t < extrema[0]) { + w += y0_ < y0 ? unit : -unit; + } + else { + w += y3 < y0_ ? unit : -unit; + } + } + } + return w; + } + } + function windingQuadratic(x0, y0, x1, y1, x2, y2, x, y) { + if ((y > y0 && y > y1 && y > y2) + || (y < y0 && y < y1 && y < y2)) { + return 0; + } + var nRoots = quadraticRootAt(y0, y1, y2, y, roots); + if (nRoots === 0) { + return 0; + } + else { + var t = quadraticExtremum(y0, y1, y2); + if (t >= 0 && t <= 1) { + var w = 0; + var y_ = quadraticAt(y0, y1, y2, t); + for (var i = 0; i < nRoots; i++) { + var unit = (roots[i] === 0 || roots[i] === 1) ? 0.5 : 1; + var x_ = quadraticAt(x0, x1, x2, roots[i]); + if (x_ < x) { + continue; + } + if (roots[i] < t) { + w += y_ < y0 ? unit : -unit; + } + else { + w += y2 < y_ ? unit : -unit; + } + } + return w; + } + else { + var unit = (roots[0] === 0 || roots[0] === 1) ? 0.5 : 1; + var x_ = quadraticAt(x0, x1, x2, roots[0]); + if (x_ < x) { + return 0; + } + return y2 < y0 ? unit : -unit; + } + } + } + function windingArc(cx, cy, r, startAngle, endAngle, anticlockwise, x, y) { + y -= cy; + if (y > r || y < -r) { + return 0; + } + var tmp = Math.sqrt(r * r - y * y); + roots[0] = -tmp; + roots[1] = tmp; + var dTheta = Math.abs(startAngle - endAngle); + if (dTheta < 1e-4) { + return 0; + } + if (dTheta >= PI2$4 - 1e-4) { + startAngle = 0; + endAngle = PI2$4; + var dir = anticlockwise ? 1 : -1; + if (x >= roots[0] + cx && x <= roots[1] + cx) { + return dir; + } + else { + return 0; + } + } + if (startAngle > endAngle) { + var tmp_1 = startAngle; + startAngle = endAngle; + endAngle = tmp_1; + } + if (startAngle < 0) { + startAngle += PI2$4; + endAngle += PI2$4; + } + var w = 0; + for (var i = 0; i < 2; i++) { + var x_ = roots[i]; + if (x_ + cx > x) { + var angle = Math.atan2(y, x_); + var dir = anticlockwise ? 1 : -1; + if (angle < 0) { + angle = PI2$4 + angle; + } + if ((angle >= startAngle && angle <= endAngle) + || (angle + PI2$4 >= startAngle && angle + PI2$4 <= endAngle)) { + if (angle > Math.PI / 2 && angle < Math.PI * 1.5) { + dir = -dir; + } + w += dir; + } + } + } + return w; + } + function containPath(path, lineWidth, isStroke, x, y) { + var data = path.data; + var len = path.len(); + var w = 0; + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + var x1; + var y1; + for (var i = 0; i < len;) { + var cmd = data[i++]; + var isFirst = i === 1; + if (cmd === CMD$1.M && i > 1) { + if (!isStroke) { + w += windingLine(xi, yi, x0, y0, x, y); + } + } + if (isFirst) { + xi = data[i]; + yi = data[i + 1]; + x0 = xi; + y0 = yi; + } + switch (cmd) { + case CMD$1.M: + x0 = data[i++]; + y0 = data[i++]; + xi = x0; + yi = y0; + break; + case CMD$1.L: + if (isStroke) { + if (containStroke(xi, yi, data[i], data[i + 1], lineWidth, x, y)) { + return true; + } + } + else { + w += windingLine(xi, yi, data[i], data[i + 1], x, y) || 0; + } + xi = data[i++]; + yi = data[i++]; + break; + case CMD$1.C: + if (isStroke) { + if (containStroke$1(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], lineWidth, x, y)) { + return true; + } + } + else { + w += windingCubic(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], x, y) || 0; + } + xi = data[i++]; + yi = data[i++]; + break; + case CMD$1.Q: + if (isStroke) { + if (containStroke$2(xi, yi, data[i++], data[i++], data[i], data[i + 1], lineWidth, x, y)) { + return true; + } + } + else { + w += windingQuadratic(xi, yi, data[i++], data[i++], data[i], data[i + 1], x, y) || 0; + } + xi = data[i++]; + yi = data[i++]; + break; + case CMD$1.A: + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var theta = data[i++]; + var dTheta = data[i++]; + i += 1; + var anticlockwise = !!(1 - data[i++]); + x1 = Math.cos(theta) * rx + cx; + y1 = Math.sin(theta) * ry + cy; + if (!isFirst) { + w += windingLine(xi, yi, x1, y1, x, y); + } + else { + x0 = x1; + y0 = y1; + } + var _x = (x - cx) * ry / rx + cx; + if (isStroke) { + if (containStroke$3(cx, cy, ry, theta, theta + dTheta, anticlockwise, lineWidth, _x, y)) { + return true; + } + } + else { + w += windingArc(cx, cy, ry, theta, theta + dTheta, anticlockwise, _x, y); + } + xi = Math.cos(theta + dTheta) * rx + cx; + yi = Math.sin(theta + dTheta) * ry + cy; + break; + case CMD$1.R: + x0 = xi = data[i++]; + y0 = yi = data[i++]; + var width = data[i++]; + var height = data[i++]; + x1 = x0 + width; + y1 = y0 + height; + if (isStroke) { + if (containStroke(x0, y0, x1, y0, lineWidth, x, y) + || containStroke(x1, y0, x1, y1, lineWidth, x, y) + || containStroke(x1, y1, x0, y1, lineWidth, x, y) + || containStroke(x0, y1, x0, y0, lineWidth, x, y)) { + return true; + } + } + else { + w += windingLine(x1, y0, x1, y1, x, y); + w += windingLine(x0, y1, x0, y0, x, y); + } + break; + case CMD$1.Z: + if (isStroke) { + if (containStroke(xi, yi, x0, y0, lineWidth, x, y)) { + return true; + } + } + else { + w += windingLine(xi, yi, x0, y0, x, y); + } + xi = x0; + yi = y0; + break; + } + } + if (!isStroke && !isAroundEqual(yi, y0)) { + w += windingLine(xi, yi, x0, y0, x, y) || 0; + } + return w !== 0; + } + function contain(pathProxy, x, y) { + return containPath(pathProxy, 0, false, x, y); + } + function containStroke$4(pathProxy, lineWidth, x, y) { + return containPath(pathProxy, lineWidth, true, x, y); + } + + var DEFAULT_PATH_STYLE = defaults({ + fill: '#000', + stroke: null, + strokePercent: 1, + fillOpacity: 1, + strokeOpacity: 1, + lineDashOffset: 0, + lineWidth: 1, + lineCap: 'butt', + miterLimit: 10, + strokeNoScale: false, + strokeFirst: false + }, DEFAULT_COMMON_STYLE); + var DEFAULT_PATH_ANIMATION_PROPS = { + style: defaults({ + fill: true, + stroke: true, + strokePercent: true, + fillOpacity: true, + strokeOpacity: true, + lineDashOffset: true, + lineWidth: true, + miterLimit: true + }, DEFAULT_COMMON_ANIMATION_PROPS.style) + }; + var pathCopyParams = TRANSFORMABLE_PROPS.concat(['invisible', + 'culling', 'z', 'z2', 'zlevel', 'parent' + ]); + var Path = (function (_super) { + __extends(Path, _super); + function Path(opts) { + return _super.call(this, opts) || this; + } + Path.prototype.update = function () { + var _this = this; + _super.prototype.update.call(this); + var style = this.style; + if (style.decal) { + var decalEl = this._decalEl = this._decalEl || new Path(); + if (decalEl.buildPath === Path.prototype.buildPath) { + decalEl.buildPath = function (ctx) { + _this.buildPath(ctx, _this.shape); + }; + } + decalEl.silent = true; + var decalElStyle = decalEl.style; + for (var key in style) { + if (decalElStyle[key] !== style[key]) { + decalElStyle[key] = style[key]; + } + } + decalElStyle.fill = style.fill ? style.decal : null; + decalElStyle.decal = null; + decalElStyle.shadowColor = null; + style.strokeFirst && (decalElStyle.stroke = null); + for (var i = 0; i < pathCopyParams.length; ++i) { + decalEl[pathCopyParams[i]] = this[pathCopyParams[i]]; + } + decalEl.__dirty |= REDRAW_BIT; + } + else if (this._decalEl) { + this._decalEl = null; + } + }; + Path.prototype.getDecalElement = function () { + return this._decalEl; + }; + Path.prototype._init = function (props) { + var keysArr = keys(props); + this.shape = this.getDefaultShape(); + var defaultStyle = this.getDefaultStyle(); + if (defaultStyle) { + this.useStyle(defaultStyle); + } + for (var i = 0; i < keysArr.length; i++) { + var key = keysArr[i]; + var value = props[key]; + if (key === 'style') { + if (!this.style) { + this.useStyle(value); + } + else { + extend(this.style, value); + } + } + else if (key === 'shape') { + extend(this.shape, value); + } + else { + _super.prototype.attrKV.call(this, key, value); + } + } + if (!this.style) { + this.useStyle({}); + } + }; + Path.prototype.getDefaultStyle = function () { + return null; + }; + Path.prototype.getDefaultShape = function () { + return {}; + }; + Path.prototype.canBeInsideText = function () { + return this.hasFill(); + }; + Path.prototype.getInsideTextFill = function () { + var pathFill = this.style.fill; + if (pathFill !== 'none') { + if (isString(pathFill)) { + var fillLum = lum(pathFill, 0); + if (fillLum > 0.5) { + return DARK_LABEL_COLOR; + } + else if (fillLum > 0.2) { + return LIGHTER_LABEL_COLOR; + } + return LIGHT_LABEL_COLOR; + } + else if (pathFill) { + return LIGHT_LABEL_COLOR; + } + } + return DARK_LABEL_COLOR; + }; + Path.prototype.getInsideTextStroke = function (textFill) { + var pathFill = this.style.fill; + if (isString(pathFill)) { + var zr = this.__zr; + var isDarkMode = !!(zr && zr.isDarkMode()); + var isDarkLabel = lum(textFill, 0) < DARK_MODE_THRESHOLD; + if (isDarkMode === isDarkLabel) { + return pathFill; + } + } + }; + Path.prototype.buildPath = function (ctx, shapeCfg, inBatch) { }; + Path.prototype.pathUpdated = function () { + this.__dirty &= ~SHAPE_CHANGED_BIT; + }; + Path.prototype.getUpdatedPathProxy = function (inBatch) { + !this.path && this.createPathProxy(); + this.path.beginPath(); + this.buildPath(this.path, this.shape, inBatch); + return this.path; + }; + Path.prototype.createPathProxy = function () { + this.path = new PathProxy(false); + }; + Path.prototype.hasStroke = function () { + var style = this.style; + var stroke = style.stroke; + return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0)); + }; + Path.prototype.hasFill = function () { + var style = this.style; + var fill = style.fill; + return fill != null && fill !== 'none'; + }; + Path.prototype.getBoundingRect = function () { + var rect = this._rect; + var style = this.style; + var needsUpdateRect = !rect; + if (needsUpdateRect) { + var firstInvoke = false; + if (!this.path) { + firstInvoke = true; + this.createPathProxy(); + } + var path = this.path; + if (firstInvoke || (this.__dirty & SHAPE_CHANGED_BIT)) { + path.beginPath(); + this.buildPath(path, this.shape, false); + this.pathUpdated(); + } + rect = path.getBoundingRect(); + } + this._rect = rect; + if (this.hasStroke() && this.path && this.path.len() > 0) { + var rectStroke = this._rectStroke || (this._rectStroke = rect.clone()); + if (this.__dirty || needsUpdateRect) { + rectStroke.copy(rect); + var lineScale = style.strokeNoScale ? this.getLineScale() : 1; + var w = style.lineWidth; + if (!this.hasFill()) { + var strokeContainThreshold = this.strokeContainThreshold; + w = Math.max(w, strokeContainThreshold == null ? 4 : strokeContainThreshold); + } + if (lineScale > 1e-10) { + rectStroke.width += w / lineScale; + rectStroke.height += w / lineScale; + rectStroke.x -= w / lineScale / 2; + rectStroke.y -= w / lineScale / 2; + } + } + return rectStroke; + } + return rect; + }; + Path.prototype.contain = function (x, y) { + var localPos = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + var style = this.style; + x = localPos[0]; + y = localPos[1]; + if (rect.contain(x, y)) { + var pathProxy = this.path; + if (this.hasStroke()) { + var lineWidth = style.lineWidth; + var lineScale = style.strokeNoScale ? this.getLineScale() : 1; + if (lineScale > 1e-10) { + if (!this.hasFill()) { + lineWidth = Math.max(lineWidth, this.strokeContainThreshold); + } + if (containStroke$4(pathProxy, lineWidth / lineScale, x, y)) { + return true; + } + } + } + if (this.hasFill()) { + return contain(pathProxy, x, y); + } + } + return false; + }; + Path.prototype.dirtyShape = function () { + this.__dirty |= SHAPE_CHANGED_BIT; + if (this._rect) { + this._rect = null; + } + if (this._decalEl) { + this._decalEl.dirtyShape(); + } + this.markRedraw(); + }; + Path.prototype.dirty = function () { + this.dirtyStyle(); + this.dirtyShape(); + }; + Path.prototype.animateShape = function (loop) { + return this.animate('shape', loop); + }; + Path.prototype.updateDuringAnimation = function (targetKey) { + if (targetKey === 'style') { + this.dirtyStyle(); + } + else if (targetKey === 'shape') { + this.dirtyShape(); + } + else { + this.markRedraw(); + } + }; + Path.prototype.attrKV = function (key, value) { + if (key === 'shape') { + this.setShape(value); + } + else { + _super.prototype.attrKV.call(this, key, value); + } + }; + Path.prototype.setShape = function (keyOrObj, value) { + var shape = this.shape; + if (!shape) { + shape = this.shape = {}; + } + if (typeof keyOrObj === 'string') { + shape[keyOrObj] = value; + } + else { + extend(shape, keyOrObj); + } + this.dirtyShape(); + return this; + }; + Path.prototype.shapeChanged = function () { + return !!(this.__dirty & SHAPE_CHANGED_BIT); + }; + Path.prototype.createStyle = function (obj) { + return createObject(DEFAULT_PATH_STYLE, obj); + }; + Path.prototype._innerSaveToNormal = function (toState) { + _super.prototype._innerSaveToNormal.call(this, toState); + var normalState = this._normalState; + if (toState.shape && !normalState.shape) { + normalState.shape = extend({}, this.shape); + } + }; + Path.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) { + _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg); + var needsRestoreToNormal = !(state && keepCurrentStates); + var targetShape; + if (state && state.shape) { + if (transition) { + if (keepCurrentStates) { + targetShape = state.shape; + } + else { + targetShape = extend({}, normalState.shape); + extend(targetShape, state.shape); + } + } + else { + targetShape = extend({}, keepCurrentStates ? this.shape : normalState.shape); + extend(targetShape, state.shape); + } + } + else if (needsRestoreToNormal) { + targetShape = normalState.shape; + } + if (targetShape) { + if (transition) { + this.shape = extend({}, this.shape); + var targetShapePrimaryProps = {}; + var shapeKeys = keys(targetShape); + for (var i = 0; i < shapeKeys.length; i++) { + var key = shapeKeys[i]; + if (typeof targetShape[key] === 'object') { + this.shape[key] = targetShape[key]; + } + else { + targetShapePrimaryProps[key] = targetShape[key]; + } + } + this._transitionState(stateName, { + shape: targetShapePrimaryProps + }, animationCfg); + } + else { + this.shape = targetShape; + this.dirtyShape(); + } + } + }; + Path.prototype._mergeStates = function (states) { + var mergedState = _super.prototype._mergeStates.call(this, states); + var mergedShape; + for (var i = 0; i < states.length; i++) { + var state = states[i]; + if (state.shape) { + mergedShape = mergedShape || {}; + this._mergeStyle(mergedShape, state.shape); + } + } + if (mergedShape) { + mergedState.shape = mergedShape; + } + return mergedState; + }; + Path.prototype.getAnimationStyleProps = function () { + return DEFAULT_PATH_ANIMATION_PROPS; + }; + Path.prototype.isZeroArea = function () { + return false; + }; + Path.extend = function (defaultProps) { + var Sub = (function (_super) { + __extends(Sub, _super); + function Sub(opts) { + var _this = _super.call(this, opts) || this; + defaultProps.init && defaultProps.init.call(_this, opts); + return _this; + } + Sub.prototype.getDefaultStyle = function () { + return clone(defaultProps.style); + }; + Sub.prototype.getDefaultShape = function () { + return clone(defaultProps.shape); + }; + return Sub; + }(Path)); + for (var key in defaultProps) { + if (typeof defaultProps[key] === 'function') { + Sub.prototype[key] = defaultProps[key]; + } + } + return Sub; + }; + Path.initDefaultProps = (function () { + var pathProto = Path.prototype; + pathProto.type = 'path'; + pathProto.strokeContainThreshold = 5; + pathProto.segmentIgnoreThreshold = 0; + pathProto.subPixelOptimize = false; + pathProto.autoBatch = false; + pathProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT; + })(); + return Path; + }(Displayable)); + + var DEFAULT_TSPAN_STYLE = defaults({ + strokeFirst: true, + font: DEFAULT_FONT, + x: 0, + y: 0, + textAlign: 'left', + textBaseline: 'top', + miterLimit: 2 + }, DEFAULT_PATH_STYLE); + var TSpan = (function (_super) { + __extends(TSpan, _super); + function TSpan() { + return _super !== null && _super.apply(this, arguments) || this; + } + TSpan.prototype.hasStroke = function () { + var style = this.style; + var stroke = style.stroke; + return stroke != null && stroke !== 'none' && style.lineWidth > 0; + }; + TSpan.prototype.hasFill = function () { + var style = this.style; + var fill = style.fill; + return fill != null && fill !== 'none'; + }; + TSpan.prototype.createStyle = function (obj) { + return createObject(DEFAULT_TSPAN_STYLE, obj); + }; + TSpan.prototype.setBoundingRect = function (rect) { + this._rect = rect; + }; + TSpan.prototype.getBoundingRect = function () { + var style = this.style; + if (!this._rect) { + var text = style.text; + text != null ? (text += '') : (text = ''); + var rect = getBoundingRect(text, style.font, style.textAlign, style.textBaseline); + rect.x += style.x || 0; + rect.y += style.y || 0; + if (this.hasStroke()) { + var w = style.lineWidth; + rect.x -= w / 2; + rect.y -= w / 2; + rect.width += w; + rect.height += w; + } + this._rect = rect; + } + return this._rect; + }; + TSpan.initDefaultProps = (function () { + var tspanProto = TSpan.prototype; + tspanProto.dirtyRectTolerance = 10; + })(); + return TSpan; + }(Displayable)); + TSpan.prototype.type = 'tspan'; + + var DEFAULT_IMAGE_STYLE = defaults({ + x: 0, + y: 0 + }, DEFAULT_COMMON_STYLE); + var DEFAULT_IMAGE_ANIMATION_PROPS = { + style: defaults({ + x: true, + y: true, + width: true, + height: true, + sx: true, + sy: true, + sWidth: true, + sHeight: true + }, DEFAULT_COMMON_ANIMATION_PROPS.style) + }; + function isImageLike(source) { + return !!(source + && typeof source !== 'string' + && source.width && source.height); + } + var ZRImage = (function (_super) { + __extends(ZRImage, _super); + function ZRImage() { + return _super !== null && _super.apply(this, arguments) || this; + } + ZRImage.prototype.createStyle = function (obj) { + return createObject(DEFAULT_IMAGE_STYLE, obj); + }; + ZRImage.prototype._getSize = function (dim) { + var style = this.style; + var size = style[dim]; + if (size != null) { + return size; + } + var imageSource = isImageLike(style.image) + ? style.image : this.__image; + if (!imageSource) { + return 0; + } + var otherDim = dim === 'width' ? 'height' : 'width'; + var otherDimSize = style[otherDim]; + if (otherDimSize == null) { + return imageSource[dim]; + } + else { + return imageSource[dim] / imageSource[otherDim] * otherDimSize; + } + }; + ZRImage.prototype.getWidth = function () { + return this._getSize('width'); + }; + ZRImage.prototype.getHeight = function () { + return this._getSize('height'); + }; + ZRImage.prototype.getAnimationStyleProps = function () { + return DEFAULT_IMAGE_ANIMATION_PROPS; + }; + ZRImage.prototype.getBoundingRect = function () { + var style = this.style; + if (!this._rect) { + this._rect = new BoundingRect(style.x || 0, style.y || 0, this.getWidth(), this.getHeight()); + } + return this._rect; + }; + return ZRImage; + }(Displayable)); + ZRImage.prototype.type = 'image'; + + function buildPath(ctx, shape) { + var x = shape.x; + var y = shape.y; + var width = shape.width; + var height = shape.height; + var r = shape.r; + var r1; + var r2; + var r3; + var r4; + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } + if (typeof r === 'number') { + r1 = r2 = r3 = r4 = r; + } + else if (r instanceof Array) { + if (r.length === 1) { + r1 = r2 = r3 = r4 = r[0]; + } + else if (r.length === 2) { + r1 = r3 = r[0]; + r2 = r4 = r[1]; + } + else if (r.length === 3) { + r1 = r[0]; + r2 = r4 = r[1]; + r3 = r[2]; + } + else { + r1 = r[0]; + r2 = r[1]; + r3 = r[2]; + r4 = r[3]; + } + } + else { + r1 = r2 = r3 = r4 = 0; + } + var total; + if (r1 + r2 > width) { + total = r1 + r2; + r1 *= width / total; + r2 *= width / total; + } + if (r3 + r4 > width) { + total = r3 + r4; + r3 *= width / total; + r4 *= width / total; + } + if (r2 + r3 > height) { + total = r2 + r3; + r2 *= height / total; + r3 *= height / total; + } + if (r1 + r4 > height) { + total = r1 + r4; + r1 *= height / total; + r4 *= height / total; + } + ctx.moveTo(x + r1, y); + ctx.lineTo(x + width - r2, y); + r2 !== 0 && ctx.arc(x + width - r2, y + r2, r2, -Math.PI / 2, 0); + ctx.lineTo(x + width, y + height - r3); + r3 !== 0 && ctx.arc(x + width - r3, y + height - r3, r3, 0, Math.PI / 2); + ctx.lineTo(x + r4, y + height); + r4 !== 0 && ctx.arc(x + r4, y + height - r4, r4, Math.PI / 2, Math.PI); + ctx.lineTo(x, y + r1); + r1 !== 0 && ctx.arc(x + r1, y + r1, r1, Math.PI, Math.PI * 1.5); + } + + var round$1 = Math.round; + function subPixelOptimizeLine(outputShape, inputShape, style) { + if (!inputShape) { + return; + } + var x1 = inputShape.x1; + var x2 = inputShape.x2; + var y1 = inputShape.y1; + var y2 = inputShape.y2; + outputShape.x1 = x1; + outputShape.x2 = x2; + outputShape.y1 = y1; + outputShape.y2 = y2; + var lineWidth = style && style.lineWidth; + if (!lineWidth) { + return outputShape; + } + if (round$1(x1 * 2) === round$1(x2 * 2)) { + outputShape.x1 = outputShape.x2 = subPixelOptimize(x1, lineWidth, true); + } + if (round$1(y1 * 2) === round$1(y2 * 2)) { + outputShape.y1 = outputShape.y2 = subPixelOptimize(y1, lineWidth, true); + } + return outputShape; + } + function subPixelOptimizeRect(outputShape, inputShape, style) { + if (!inputShape) { + return; + } + var originX = inputShape.x; + var originY = inputShape.y; + var originWidth = inputShape.width; + var originHeight = inputShape.height; + outputShape.x = originX; + outputShape.y = originY; + outputShape.width = originWidth; + outputShape.height = originHeight; + var lineWidth = style && style.lineWidth; + if (!lineWidth) { + return outputShape; + } + outputShape.x = subPixelOptimize(originX, lineWidth, true); + outputShape.y = subPixelOptimize(originY, lineWidth, true); + outputShape.width = Math.max(subPixelOptimize(originX + originWidth, lineWidth, false) - outputShape.x, originWidth === 0 ? 0 : 1); + outputShape.height = Math.max(subPixelOptimize(originY + originHeight, lineWidth, false) - outputShape.y, originHeight === 0 ? 0 : 1); + return outputShape; + } + function subPixelOptimize(position, lineWidth, positiveOrNegative) { + if (!lineWidth) { + return position; + } + var doubledPosition = round$1(position * 2); + return (doubledPosition + round$1(lineWidth)) % 2 === 0 + ? doubledPosition / 2 + : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2; + } + + var RectShape = (function () { + function RectShape() { + this.x = 0; + this.y = 0; + this.width = 0; + this.height = 0; + } + return RectShape; + }()); + var subPixelOptimizeOutputShape = {}; + var Rect = (function (_super) { + __extends(Rect, _super); + function Rect(opts) { + return _super.call(this, opts) || this; + } + Rect.prototype.getDefaultShape = function () { + return new RectShape(); + }; + Rect.prototype.buildPath = function (ctx, shape) { + var x; + var y; + var width; + var height; + if (this.subPixelOptimize) { + var optimizedShape = subPixelOptimizeRect(subPixelOptimizeOutputShape, shape, this.style); + x = optimizedShape.x; + y = optimizedShape.y; + width = optimizedShape.width; + height = optimizedShape.height; + optimizedShape.r = shape.r; + shape = optimizedShape; + } + else { + x = shape.x; + y = shape.y; + width = shape.width; + height = shape.height; + } + if (!shape.r) { + ctx.rect(x, y, width, height); + } + else { + buildPath(ctx, shape); + } + }; + Rect.prototype.isZeroArea = function () { + return !this.shape.width || !this.shape.height; + }; + return Rect; + }(Path)); + Rect.prototype.type = 'rect'; + + var DEFAULT_RICH_TEXT_COLOR = { + fill: '#000' + }; + var DEFAULT_STROKE_LINE_WIDTH = 2; + var DEFAULT_TEXT_ANIMATION_PROPS = { + style: defaults({ + fill: true, + stroke: true, + fillOpacity: true, + strokeOpacity: true, + lineWidth: true, + fontSize: true, + lineHeight: true, + width: true, + height: true, + textShadowColor: true, + textShadowBlur: true, + textShadowOffsetX: true, + textShadowOffsetY: true, + backgroundColor: true, + padding: true, + borderColor: true, + borderWidth: true, + borderRadius: true + }, DEFAULT_COMMON_ANIMATION_PROPS.style) + }; + var ZRText = (function (_super) { + __extends(ZRText, _super); + function ZRText(opts) { + var _this = _super.call(this) || this; + _this.type = 'text'; + _this._children = []; + _this._defaultStyle = DEFAULT_RICH_TEXT_COLOR; + _this.attr(opts); + return _this; + } + ZRText.prototype.childrenRef = function () { + return this._children; + }; + ZRText.prototype.update = function () { + _super.prototype.update.call(this); + if (this.styleChanged()) { + this._updateSubTexts(); + } + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + child.zlevel = this.zlevel; + child.z = this.z; + child.z2 = this.z2; + child.culling = this.culling; + child.cursor = this.cursor; + child.invisible = this.invisible; + } + }; + ZRText.prototype.updateTransform = function () { + var innerTransformable = this.innerTransformable; + if (innerTransformable) { + innerTransformable.updateTransform(); + if (innerTransformable.transform) { + this.transform = innerTransformable.transform; + } + } + else { + _super.prototype.updateTransform.call(this); + } + }; + ZRText.prototype.getLocalTransform = function (m) { + var innerTransformable = this.innerTransformable; + return innerTransformable + ? innerTransformable.getLocalTransform(m) + : _super.prototype.getLocalTransform.call(this, m); + }; + ZRText.prototype.getComputedTransform = function () { + if (this.__hostTarget) { + this.__hostTarget.getComputedTransform(); + this.__hostTarget.updateInnerText(true); + } + return _super.prototype.getComputedTransform.call(this); + }; + ZRText.prototype._updateSubTexts = function () { + this._childCursor = 0; + normalizeTextStyle(this.style); + this.style.rich + ? this._updateRichTexts() + : this._updatePlainTexts(); + this._children.length = this._childCursor; + this.styleUpdated(); + }; + ZRText.prototype.addSelfToZr = function (zr) { + _super.prototype.addSelfToZr.call(this, zr); + for (var i = 0; i < this._children.length; i++) { + this._children[i].__zr = zr; + } + }; + ZRText.prototype.removeSelfFromZr = function (zr) { + _super.prototype.removeSelfFromZr.call(this, zr); + for (var i = 0; i < this._children.length; i++) { + this._children[i].__zr = null; + } + }; + ZRText.prototype.getBoundingRect = function () { + if (this.styleChanged()) { + this._updateSubTexts(); + } + if (!this._rect) { + var tmpRect = new BoundingRect(0, 0, 0, 0); + var children = this._children; + var tmpMat = []; + var rect = null; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + var childRect = child.getBoundingRect(); + var transform = child.getLocalTransform(tmpMat); + if (transform) { + tmpRect.copy(childRect); + tmpRect.applyTransform(transform); + rect = rect || tmpRect.clone(); + rect.union(tmpRect); + } + else { + rect = rect || childRect.clone(); + rect.union(childRect); + } + } + this._rect = rect || tmpRect; + } + return this._rect; + }; + ZRText.prototype.setDefaultTextStyle = function (defaultTextStyle) { + this._defaultStyle = defaultTextStyle || DEFAULT_RICH_TEXT_COLOR; + }; + ZRText.prototype.setTextContent = function (textContent) { + if ("development" !== 'production') { + throw new Error('Can\'t attach text on another text'); + } + }; + ZRText.prototype._mergeStyle = function (targetStyle, sourceStyle) { + if (!sourceStyle) { + return targetStyle; + } + var sourceRich = sourceStyle.rich; + var targetRich = targetStyle.rich || (sourceRich && {}); + extend(targetStyle, sourceStyle); + if (sourceRich && targetRich) { + this._mergeRich(targetRich, sourceRich); + targetStyle.rich = targetRich; + } + else if (targetRich) { + targetStyle.rich = targetRich; + } + return targetStyle; + }; + ZRText.prototype._mergeRich = function (targetRich, sourceRich) { + var richNames = keys(sourceRich); + for (var i = 0; i < richNames.length; i++) { + var richName = richNames[i]; + targetRich[richName] = targetRich[richName] || {}; + extend(targetRich[richName], sourceRich[richName]); + } + }; + ZRText.prototype.getAnimationStyleProps = function () { + return DEFAULT_TEXT_ANIMATION_PROPS; + }; + ZRText.prototype._getOrCreateChild = function (Ctor) { + var child = this._children[this._childCursor]; + if (!child || !(child instanceof Ctor)) { + child = new Ctor(); + } + this._children[this._childCursor++] = child; + child.__zr = this.__zr; + child.parent = this; + return child; + }; + ZRText.prototype._updatePlainTexts = function () { + var style = this.style; + var textFont = style.font || DEFAULT_FONT; + var textPadding = style.padding; + var text = getStyleText(style); + var contentBlock = parsePlainText(text, style); + var needDrawBg = needDrawBackground(style); + var bgColorDrawn = !!(style.backgroundColor); + var outerHeight = contentBlock.outerHeight; + var outerWidth = contentBlock.outerWidth; + var contentWidth = contentBlock.contentWidth; + var textLines = contentBlock.lines; + var lineHeight = contentBlock.lineHeight; + var defaultStyle = this._defaultStyle; + var baseX = style.x || 0; + var baseY = style.y || 0; + var textAlign = style.align || defaultStyle.align || 'left'; + var verticalAlign = style.verticalAlign || defaultStyle.verticalAlign || 'top'; + var textX = baseX; + var textY = adjustTextY$1(baseY, contentBlock.contentHeight, verticalAlign); + if (needDrawBg || textPadding) { + var boxX = adjustTextX(baseX, outerWidth, textAlign); + var boxY = adjustTextY$1(baseY, outerHeight, verticalAlign); + needDrawBg && this._renderBackground(style, style, boxX, boxY, outerWidth, outerHeight); + } + textY += lineHeight / 2; + if (textPadding) { + textX = getTextXForPadding(baseX, textAlign, textPadding); + if (verticalAlign === 'top') { + textY += textPadding[0]; + } + else if (verticalAlign === 'bottom') { + textY -= textPadding[2]; + } + } + var defaultLineWidth = 0; + var useDefaultFill = false; + var textFill = getFill('fill' in style + ? style.fill + : (useDefaultFill = true, defaultStyle.fill)); + var textStroke = getStroke('stroke' in style + ? style.stroke + : (!bgColorDrawn + && (!defaultStyle.autoStroke || useDefaultFill)) + ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke) + : null); + var hasShadow = style.textShadowBlur > 0; + var fixedBoundingRect = style.width != null + && (style.overflow === 'truncate' || style.overflow === 'break' || style.overflow === 'breakAll'); + var calculatedLineHeight = contentBlock.calculatedLineHeight; + for (var i = 0; i < textLines.length; i++) { + var el = this._getOrCreateChild(TSpan); + var subElStyle = el.createStyle(); + el.useStyle(subElStyle); + subElStyle.text = textLines[i]; + subElStyle.x = textX; + subElStyle.y = textY; + if (textAlign) { + subElStyle.textAlign = textAlign; + } + subElStyle.textBaseline = 'middle'; + subElStyle.opacity = style.opacity; + subElStyle.strokeFirst = true; + if (hasShadow) { + subElStyle.shadowBlur = style.textShadowBlur || 0; + subElStyle.shadowColor = style.textShadowColor || 'transparent'; + subElStyle.shadowOffsetX = style.textShadowOffsetX || 0; + subElStyle.shadowOffsetY = style.textShadowOffsetY || 0; + } + subElStyle.stroke = textStroke; + subElStyle.fill = textFill; + if (textStroke) { + subElStyle.lineWidth = style.lineWidth || defaultLineWidth; + subElStyle.lineDash = style.lineDash; + subElStyle.lineDashOffset = style.lineDashOffset || 0; + } + subElStyle.font = textFont; + setSeparateFont(subElStyle, style); + textY += lineHeight; + if (fixedBoundingRect) { + el.setBoundingRect(new BoundingRect(adjustTextX(subElStyle.x, style.width, subElStyle.textAlign), adjustTextY$1(subElStyle.y, calculatedLineHeight, subElStyle.textBaseline), contentWidth, calculatedLineHeight)); + } + } + }; + ZRText.prototype._updateRichTexts = function () { + var style = this.style; + var text = getStyleText(style); + var contentBlock = parseRichText(text, style); + var contentWidth = contentBlock.width; + var outerWidth = contentBlock.outerWidth; + var outerHeight = contentBlock.outerHeight; + var textPadding = style.padding; + var baseX = style.x || 0; + var baseY = style.y || 0; + var defaultStyle = this._defaultStyle; + var textAlign = style.align || defaultStyle.align; + var verticalAlign = style.verticalAlign || defaultStyle.verticalAlign; + var boxX = adjustTextX(baseX, outerWidth, textAlign); + var boxY = adjustTextY$1(baseY, outerHeight, verticalAlign); + var xLeft = boxX; + var lineTop = boxY; + if (textPadding) { + xLeft += textPadding[3]; + lineTop += textPadding[0]; + } + var xRight = xLeft + contentWidth; + if (needDrawBackground(style)) { + this._renderBackground(style, style, boxX, boxY, outerWidth, outerHeight); + } + var bgColorDrawn = !!(style.backgroundColor); + for (var i = 0; i < contentBlock.lines.length; i++) { + var line = contentBlock.lines[i]; + var tokens = line.tokens; + var tokenCount = tokens.length; + var lineHeight = line.lineHeight; + var remainedWidth = line.width; + var leftIndex = 0; + var lineXLeft = xLeft; + var lineXRight = xRight; + var rightIndex = tokenCount - 1; + var token = void 0; + while (leftIndex < tokenCount + && (token = tokens[leftIndex], !token.align || token.align === 'left')) { + this._placeToken(token, style, lineHeight, lineTop, lineXLeft, 'left', bgColorDrawn); + remainedWidth -= token.width; + lineXLeft += token.width; + leftIndex++; + } + while (rightIndex >= 0 + && (token = tokens[rightIndex], token.align === 'right')) { + this._placeToken(token, style, lineHeight, lineTop, lineXRight, 'right', bgColorDrawn); + remainedWidth -= token.width; + lineXRight -= token.width; + rightIndex--; + } + lineXLeft += (contentWidth - (lineXLeft - xLeft) - (xRight - lineXRight) - remainedWidth) / 2; + while (leftIndex <= rightIndex) { + token = tokens[leftIndex]; + this._placeToken(token, style, lineHeight, lineTop, lineXLeft + token.width / 2, 'center', bgColorDrawn); + lineXLeft += token.width; + leftIndex++; + } + lineTop += lineHeight; + } + }; + ZRText.prototype._placeToken = function (token, style, lineHeight, lineTop, x, textAlign, parentBgColorDrawn) { + var tokenStyle = style.rich[token.styleName] || {}; + tokenStyle.text = token.text; + var verticalAlign = token.verticalAlign; + var y = lineTop + lineHeight / 2; + if (verticalAlign === 'top') { + y = lineTop + token.height / 2; + } + else if (verticalAlign === 'bottom') { + y = lineTop + lineHeight - token.height / 2; + } + var needDrawBg = !token.isLineHolder && needDrawBackground(tokenStyle); + needDrawBg && this._renderBackground(tokenStyle, style, textAlign === 'right' + ? x - token.width + : textAlign === 'center' + ? x - token.width / 2 + : x, y - token.height / 2, token.width, token.height); + var bgColorDrawn = !!tokenStyle.backgroundColor; + var textPadding = token.textPadding; + if (textPadding) { + x = getTextXForPadding(x, textAlign, textPadding); + y -= token.height / 2 - textPadding[0] - token.innerHeight / 2; + } + var el = this._getOrCreateChild(TSpan); + var subElStyle = el.createStyle(); + el.useStyle(subElStyle); + var defaultStyle = this._defaultStyle; + var useDefaultFill = false; + var defaultLineWidth = 0; + var textFill = getFill('fill' in tokenStyle ? tokenStyle.fill + : 'fill' in style ? style.fill + : (useDefaultFill = true, defaultStyle.fill)); + var textStroke = getStroke('stroke' in tokenStyle ? tokenStyle.stroke + : 'stroke' in style ? style.stroke + : (!bgColorDrawn + && !parentBgColorDrawn + && (!defaultStyle.autoStroke || useDefaultFill)) ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke) + : null); + var hasShadow = tokenStyle.textShadowBlur > 0 + || style.textShadowBlur > 0; + subElStyle.text = token.text; + subElStyle.x = x; + subElStyle.y = y; + if (hasShadow) { + subElStyle.shadowBlur = tokenStyle.textShadowBlur || style.textShadowBlur || 0; + subElStyle.shadowColor = tokenStyle.textShadowColor || style.textShadowColor || 'transparent'; + subElStyle.shadowOffsetX = tokenStyle.textShadowOffsetX || style.textShadowOffsetX || 0; + subElStyle.shadowOffsetY = tokenStyle.textShadowOffsetY || style.textShadowOffsetY || 0; + } + subElStyle.textAlign = textAlign; + subElStyle.textBaseline = 'middle'; + subElStyle.font = token.font || DEFAULT_FONT; + subElStyle.opacity = retrieve3(tokenStyle.opacity, style.opacity, 1); + setSeparateFont(subElStyle, tokenStyle); + if (textStroke) { + subElStyle.lineWidth = retrieve3(tokenStyle.lineWidth, style.lineWidth, defaultLineWidth); + subElStyle.lineDash = retrieve2(tokenStyle.lineDash, style.lineDash); + subElStyle.lineDashOffset = style.lineDashOffset || 0; + subElStyle.stroke = textStroke; + } + if (textFill) { + subElStyle.fill = textFill; + } + var textWidth = token.contentWidth; + var textHeight = token.contentHeight; + el.setBoundingRect(new BoundingRect(adjustTextX(subElStyle.x, textWidth, subElStyle.textAlign), adjustTextY$1(subElStyle.y, textHeight, subElStyle.textBaseline), textWidth, textHeight)); + }; + ZRText.prototype._renderBackground = function (style, topStyle, x, y, width, height) { + var textBackgroundColor = style.backgroundColor; + var textBorderWidth = style.borderWidth; + var textBorderColor = style.borderColor; + var isImageBg = textBackgroundColor && textBackgroundColor.image; + var isPlainOrGradientBg = textBackgroundColor && !isImageBg; + var textBorderRadius = style.borderRadius; + var self = this; + var rectEl; + var imgEl; + if (isPlainOrGradientBg || style.lineHeight || (textBorderWidth && textBorderColor)) { + rectEl = this._getOrCreateChild(Rect); + rectEl.useStyle(rectEl.createStyle()); + rectEl.style.fill = null; + var rectShape = rectEl.shape; + rectShape.x = x; + rectShape.y = y; + rectShape.width = width; + rectShape.height = height; + rectShape.r = textBorderRadius; + rectEl.dirtyShape(); + } + if (isPlainOrGradientBg) { + var rectStyle = rectEl.style; + rectStyle.fill = textBackgroundColor || null; + rectStyle.fillOpacity = retrieve2(style.fillOpacity, 1); + } + else if (isImageBg) { + imgEl = this._getOrCreateChild(ZRImage); + imgEl.onload = function () { + self.dirtyStyle(); + }; + var imgStyle = imgEl.style; + imgStyle.image = textBackgroundColor.image; + imgStyle.x = x; + imgStyle.y = y; + imgStyle.width = width; + imgStyle.height = height; + } + if (textBorderWidth && textBorderColor) { + var rectStyle = rectEl.style; + rectStyle.lineWidth = textBorderWidth; + rectStyle.stroke = textBorderColor; + rectStyle.strokeOpacity = retrieve2(style.strokeOpacity, 1); + rectStyle.lineDash = style.borderDash; + rectStyle.lineDashOffset = style.borderDashOffset || 0; + rectEl.strokeContainThreshold = 0; + if (rectEl.hasFill() && rectEl.hasStroke()) { + rectStyle.strokeFirst = true; + rectStyle.lineWidth *= 2; + } + } + var commonStyle = (rectEl || imgEl).style; + commonStyle.shadowBlur = style.shadowBlur || 0; + commonStyle.shadowColor = style.shadowColor || 'transparent'; + commonStyle.shadowOffsetX = style.shadowOffsetX || 0; + commonStyle.shadowOffsetY = style.shadowOffsetY || 0; + commonStyle.opacity = retrieve3(style.opacity, topStyle.opacity, 1); + }; + ZRText.makeFont = function (style) { + var font = ''; + if (hasSeparateFont(style)) { + font = [ + style.fontStyle, + style.fontWeight, + parseFontSize(style.fontSize), + style.fontFamily || 'sans-serif' + ].join(' '); + } + return font && trim(font) || style.textFont || style.font; + }; + return ZRText; + }(Displayable)); + var VALID_TEXT_ALIGN = { left: true, right: 1, center: 1 }; + var VALID_TEXT_VERTICAL_ALIGN = { top: 1, bottom: 1, middle: 1 }; + var FONT_PARTS = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily']; + function parseFontSize(fontSize) { + if (typeof fontSize === 'string' + && (fontSize.indexOf('px') !== -1 + || fontSize.indexOf('rem') !== -1 + || fontSize.indexOf('em') !== -1)) { + return fontSize; + } + else if (!isNaN(+fontSize)) { + return fontSize + 'px'; + } + else { + return DEFAULT_FONT_SIZE + 'px'; + } + } + function setSeparateFont(targetStyle, sourceStyle) { + for (var i = 0; i < FONT_PARTS.length; i++) { + var fontProp = FONT_PARTS[i]; + var val = sourceStyle[fontProp]; + if (val != null) { + targetStyle[fontProp] = val; + } + } + } + function hasSeparateFont(style) { + return style.fontSize != null || style.fontFamily || style.fontWeight; + } + function normalizeTextStyle(style) { + normalizeStyle(style); + each(style.rich, normalizeStyle); + return style; + } + function normalizeStyle(style) { + if (style) { + style.font = ZRText.makeFont(style); + var textAlign = style.align; + textAlign === 'middle' && (textAlign = 'center'); + style.align = (textAlign == null || VALID_TEXT_ALIGN[textAlign]) ? textAlign : 'left'; + var verticalAlign = style.verticalAlign; + verticalAlign === 'center' && (verticalAlign = 'middle'); + style.verticalAlign = (verticalAlign == null || VALID_TEXT_VERTICAL_ALIGN[verticalAlign]) ? verticalAlign : 'top'; + var textPadding = style.padding; + if (textPadding) { + style.padding = normalizeCssArray(style.padding); + } + } + } + function getStroke(stroke, lineWidth) { + return (stroke == null || lineWidth <= 0 || stroke === 'transparent' || stroke === 'none') + ? null + : (stroke.image || stroke.colorStops) + ? '#000' + : stroke; + } + function getFill(fill) { + return (fill == null || fill === 'none') + ? null + : (fill.image || fill.colorStops) + ? '#000' + : fill; + } + function getTextXForPadding(x, textAlign, textPadding) { + return textAlign === 'right' + ? (x - textPadding[1]) + : textAlign === 'center' + ? (x + textPadding[3] / 2 - textPadding[1] / 2) + : (x + textPadding[3]); + } + function getStyleText(style) { + var text = style.text; + text != null && (text += ''); + return text; + } + function needDrawBackground(style) { + return !!(style.backgroundColor + || style.lineHeight + || (style.borderWidth && style.borderColor)); + } + + var getECData = makeInner(); + var setCommonECData = function (seriesIndex, dataType, dataIdx, el) { + if (el) { + var ecData = getECData(el); // Add data index and series index for indexing the data by element + // Useful in tooltip + + ecData.dataIndex = dataIdx; + ecData.dataType = dataType; + ecData.seriesIndex = seriesIndex; // TODO: not store dataIndex on children. + + if (el.type === 'group') { + el.traverse(function (child) { + var childECData = getECData(child); + childECData.seriesIndex = seriesIndex; + childECData.dataIndex = dataIdx; + childECData.dataType = dataType; + }); + } + } + }; + + var _highlightNextDigit = 1; + var _highlightKeyMap = {}; + var getSavedStates = makeInner(); + var getComponentStates = makeInner(); + var HOVER_STATE_NORMAL = 0; + var HOVER_STATE_BLUR = 1; + var HOVER_STATE_EMPHASIS = 2; + var SPECIAL_STATES = ['emphasis', 'blur', 'select']; + var DISPLAY_STATES = ['normal', 'emphasis', 'blur', 'select']; + var Z2_EMPHASIS_LIFT = 10; + var Z2_SELECT_LIFT = 9; + var HIGHLIGHT_ACTION_TYPE = 'highlight'; + var DOWNPLAY_ACTION_TYPE = 'downplay'; + var SELECT_ACTION_TYPE = 'select'; + var UNSELECT_ACTION_TYPE = 'unselect'; + var TOGGLE_SELECT_ACTION_TYPE = 'toggleSelect'; + + function hasFillOrStroke(fillOrStroke) { + return fillOrStroke != null && fillOrStroke !== 'none'; + } // Most lifted color are duplicated. + + + var liftedColorCache = new LRU(100); + + function liftColor(color$1) { + if (isString(color$1)) { + var liftedColor = liftedColorCache.get(color$1); + + if (!liftedColor) { + liftedColor = lift(color$1, -0.1); + liftedColorCache.put(color$1, liftedColor); + } + + return liftedColor; + } else if (isGradientObject(color$1)) { + var ret = extend({}, color$1); + ret.colorStops = map(color$1.colorStops, function (stop) { + return { + offset: stop.offset, + color: lift(stop.color, -0.1) + }; + }); + return ret; + } // Change nothing. + + + return color$1; + } + + function doChangeHoverState(el, stateName, hoverStateEnum) { + if (el.onHoverStateChange && (el.hoverState || 0) !== hoverStateEnum) { + el.onHoverStateChange(stateName); + } + + el.hoverState = hoverStateEnum; + } + + function singleEnterEmphasis(el) { + // Only mark the flag. + // States will be applied in the echarts.ts in next frame. + doChangeHoverState(el, 'emphasis', HOVER_STATE_EMPHASIS); + } + + function singleLeaveEmphasis(el) { + // Only mark the flag. + // States will be applied in the echarts.ts in next frame. + if (el.hoverState === HOVER_STATE_EMPHASIS) { + doChangeHoverState(el, 'normal', HOVER_STATE_NORMAL); + } + } + + function singleEnterBlur(el) { + doChangeHoverState(el, 'blur', HOVER_STATE_BLUR); + } + + function singleLeaveBlur(el) { + if (el.hoverState === HOVER_STATE_BLUR) { + doChangeHoverState(el, 'normal', HOVER_STATE_NORMAL); + } + } + + function singleEnterSelect(el) { + el.selected = true; + } + + function singleLeaveSelect(el) { + el.selected = false; + } + + function updateElementState(el, updater, commonParam) { + updater(el, commonParam); + } + + function traverseUpdateState(el, updater, commonParam) { + updateElementState(el, updater, commonParam); + el.isGroup && el.traverse(function (child) { + updateElementState(child, updater, commonParam); + }); + } + + function setStatesFlag(el, stateName) { + switch (stateName) { + case 'emphasis': + el.hoverState = HOVER_STATE_EMPHASIS; + break; + + case 'normal': + el.hoverState = HOVER_STATE_NORMAL; + break; + + case 'blur': + el.hoverState = HOVER_STATE_BLUR; + break; + + case 'select': + el.selected = true; + } + } + + function getFromStateStyle(el, props, toStateName, defaultValue) { + var style = el.style; + var fromState = {}; + + for (var i = 0; i < props.length; i++) { + var propName = props[i]; + var val = style[propName]; + fromState[propName] = val == null ? defaultValue && defaultValue[propName] : val; + } + + for (var i = 0; i < el.animators.length; i++) { + var animator = el.animators[i]; + + if (animator.__fromStateTransition // Dont consider the animation to emphasis state. + && animator.__fromStateTransition.indexOf(toStateName) < 0 && animator.targetName === 'style') { + animator.saveTo(fromState, props); + } + } + + return fromState; + } + + function createEmphasisDefaultState(el, stateName, targetStates, state) { + var hasSelect = targetStates && indexOf(targetStates, 'select') >= 0; + var cloned = false; + + if (el instanceof Path) { + var store = getSavedStates(el); + var fromFill = hasSelect ? store.selectFill || store.normalFill : store.normalFill; + var fromStroke = hasSelect ? store.selectStroke || store.normalStroke : store.normalStroke; + + if (hasFillOrStroke(fromFill) || hasFillOrStroke(fromStroke)) { + state = state || {}; + var emphasisStyle = state.style || {}; // inherit case + + if (emphasisStyle.fill === 'inherit') { + cloned = true; + state = extend({}, state); + emphasisStyle = extend({}, emphasisStyle); + emphasisStyle.fill = fromFill; + } // Apply default color lift + else if (!hasFillOrStroke(emphasisStyle.fill) && hasFillOrStroke(fromFill)) { + cloned = true; // Not modify the original value. + + state = extend({}, state); + emphasisStyle = extend({}, emphasisStyle); // Already being applied 'emphasis'. DON'T lift color multiple times. + + emphasisStyle.fill = liftColor(fromFill); + } // Not highlight stroke if fill has been highlighted. + else if (!hasFillOrStroke(emphasisStyle.stroke) && hasFillOrStroke(fromStroke)) { + if (!cloned) { + state = extend({}, state); + emphasisStyle = extend({}, emphasisStyle); + } + + emphasisStyle.stroke = liftColor(fromStroke); + } + + state.style = emphasisStyle; + } + } + + if (state) { + // TODO Share with textContent? + if (state.z2 == null) { + if (!cloned) { + state = extend({}, state); + } + + var z2EmphasisLift = el.z2EmphasisLift; + state.z2 = el.z2 + (z2EmphasisLift != null ? z2EmphasisLift : Z2_EMPHASIS_LIFT); + } + } + + return state; + } + + function createSelectDefaultState(el, stateName, state) { + // const hasSelect = indexOf(el.currentStates, stateName) >= 0; + if (state) { + // TODO Share with textContent? + if (state.z2 == null) { + state = extend({}, state); + var z2SelectLift = el.z2SelectLift; + state.z2 = el.z2 + (z2SelectLift != null ? z2SelectLift : Z2_SELECT_LIFT); + } + } + + return state; + } + + function createBlurDefaultState(el, stateName, state) { + var hasBlur = indexOf(el.currentStates, stateName) >= 0; + var currentOpacity = el.style.opacity; + var fromState = !hasBlur ? getFromStateStyle(el, ['opacity'], stateName, { + opacity: 1 + }) : null; + state = state || {}; + var blurStyle = state.style || {}; + + if (blurStyle.opacity == null) { + // clone state + state = extend({}, state); + blurStyle = extend({ + // Already being applied 'emphasis'. DON'T mul opacity multiple times. + opacity: hasBlur ? currentOpacity : fromState.opacity * 0.1 + }, blurStyle); + state.style = blurStyle; + } + + return state; + } + + function elementStateProxy(stateName, targetStates) { + var state = this.states[stateName]; + + if (this.style) { + if (stateName === 'emphasis') { + return createEmphasisDefaultState(this, stateName, targetStates, state); + } else if (stateName === 'blur') { + return createBlurDefaultState(this, stateName, state); + } else if (stateName === 'select') { + return createSelectDefaultState(this, stateName, state); + } + } + + return state; + } + /**FI + * Set hover style (namely "emphasis style") of element. + * @param el Should not be `zrender/graphic/Group`. + * @param focus 'self' | 'selfInSeries' | 'series' + */ + + + function setDefaultStateProxy(el) { + el.stateProxy = elementStateProxy; + var textContent = el.getTextContent(); + var textGuide = el.getTextGuideLine(); + + if (textContent) { + textContent.stateProxy = elementStateProxy; + } + + if (textGuide) { + textGuide.stateProxy = elementStateProxy; + } + } + function enterEmphasisWhenMouseOver(el, e) { + !shouldSilent(el, e) // "emphasis" event highlight has higher priority than mouse highlight. + && !el.__highByOuter && traverseUpdateState(el, singleEnterEmphasis); + } + function leaveEmphasisWhenMouseOut(el, e) { + !shouldSilent(el, e) // "emphasis" event highlight has higher priority than mouse highlight. + && !el.__highByOuter && traverseUpdateState(el, singleLeaveEmphasis); + } + function enterEmphasis(el, highlightDigit) { + el.__highByOuter |= 1 << (highlightDigit || 0); + traverseUpdateState(el, singleEnterEmphasis); + } + function leaveEmphasis(el, highlightDigit) { + !(el.__highByOuter &= ~(1 << (highlightDigit || 0))) && traverseUpdateState(el, singleLeaveEmphasis); + } + function enterBlur(el) { + traverseUpdateState(el, singleEnterBlur); + } + function leaveBlur(el) { + traverseUpdateState(el, singleLeaveBlur); + } + function enterSelect(el) { + traverseUpdateState(el, singleEnterSelect); + } + function leaveSelect(el) { + traverseUpdateState(el, singleLeaveSelect); + } + + function shouldSilent(el, e) { + return el.__highDownSilentOnTouch && e.zrByTouch; + } + + function allLeaveBlur(api) { + var model = api.getModel(); + var leaveBlurredSeries = []; + var allComponentViews = []; + model.eachComponent(function (componentType, componentModel) { + var componentStates = getComponentStates(componentModel); + var isSeries = componentType === 'series'; + var view = isSeries ? api.getViewOfSeriesModel(componentModel) : api.getViewOfComponentModel(componentModel); + !isSeries && allComponentViews.push(view); + + if (componentStates.isBlured) { + // Leave blur anyway + view.group.traverse(function (child) { + singleLeaveBlur(child); + }); + isSeries && leaveBlurredSeries.push(componentModel); + } + + componentStates.isBlured = false; + }); + each(allComponentViews, function (view) { + if (view && view.toggleBlurSeries) { + view.toggleBlurSeries(leaveBlurredSeries, false, model); + } + }); + } + function blurSeries(targetSeriesIndex, focus, blurScope, api) { + var ecModel = api.getModel(); + blurScope = blurScope || 'coordinateSystem'; + + function leaveBlurOfIndices(data, dataIndices) { + for (var i = 0; i < dataIndices.length; i++) { + var itemEl = data.getItemGraphicEl(dataIndices[i]); + itemEl && leaveBlur(itemEl); + } + } + + if (targetSeriesIndex == null) { + return; + } + + if (!focus || focus === 'none') { + return; + } + + var targetSeriesModel = ecModel.getSeriesByIndex(targetSeriesIndex); + var targetCoordSys = targetSeriesModel.coordinateSystem; + + if (targetCoordSys && targetCoordSys.master) { + targetCoordSys = targetCoordSys.master; + } + + var blurredSeries = []; + ecModel.eachSeries(function (seriesModel) { + var sameSeries = targetSeriesModel === seriesModel; + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && coordSys.master) { + coordSys = coordSys.master; + } + + var sameCoordSys = coordSys && targetCoordSys ? coordSys === targetCoordSys : sameSeries; // If there is no coordinate system. use sameSeries instead. + + if (!( // Not blur other series if blurScope series + blurScope === 'series' && !sameSeries // Not blur other coordinate system if blurScope is coordinateSystem + || blurScope === 'coordinateSystem' && !sameCoordSys // Not blur self series if focus is series. + || focus === 'series' && sameSeries // TODO blurScope: coordinate system + )) { + var view = api.getViewOfSeriesModel(seriesModel); + view.group.traverse(function (child) { + singleEnterBlur(child); + }); + + if (isArrayLike(focus)) { + leaveBlurOfIndices(seriesModel.getData(), focus); + } else if (isObject(focus)) { + var dataTypes = keys(focus); + + for (var d = 0; d < dataTypes.length; d++) { + leaveBlurOfIndices(seriesModel.getData(dataTypes[d]), focus[dataTypes[d]]); + } + } + + blurredSeries.push(seriesModel); + getComponentStates(seriesModel).isBlured = true; + } + }); + ecModel.eachComponent(function (componentType, componentModel) { + if (componentType === 'series') { + return; + } + + var view = api.getViewOfComponentModel(componentModel); + + if (view && view.toggleBlurSeries) { + view.toggleBlurSeries(blurredSeries, true, ecModel); + } + }); + } + function blurComponent(componentMainType, componentIndex, api) { + if (componentMainType == null || componentIndex == null) { + return; + } + + var componentModel = api.getModel().getComponent(componentMainType, componentIndex); + + if (!componentModel) { + return; + } + + getComponentStates(componentModel).isBlured = true; + var view = api.getViewOfComponentModel(componentModel); + + if (!view || !view.focusBlurEnabled) { + return; + } + + view.group.traverse(function (child) { + singleEnterBlur(child); + }); + } + function blurSeriesFromHighlightPayload(seriesModel, payload, api) { + var seriesIndex = seriesModel.seriesIndex; + var data = seriesModel.getData(payload.dataType); + + if (!data) { + if ("development" !== 'production') { + error("Unknown dataType " + payload.dataType); + } + + return; + } + + var dataIndex = queryDataIndex(data, payload); // Pick the first one if there is multiple/none exists. + + dataIndex = (isArray(dataIndex) ? dataIndex[0] : dataIndex) || 0; + var el = data.getItemGraphicEl(dataIndex); + + if (!el) { + var count = data.count(); + var current = 0; // If data on dataIndex is NaN. + + while (!el && current < count) { + el = data.getItemGraphicEl(current++); + } + } + + if (el) { + var ecData = getECData(el); + blurSeries(seriesIndex, ecData.focus, ecData.blurScope, api); + } else { + // If there is no element put on the data. Try getting it from raw option + // TODO Should put it on seriesModel? + var focus_1 = seriesModel.get(['emphasis', 'focus']); + var blurScope = seriesModel.get(['emphasis', 'blurScope']); + + if (focus_1 != null) { + blurSeries(seriesIndex, focus_1, blurScope, api); + } + } + } + function findComponentHighDownDispatchers(componentMainType, componentIndex, name, api) { + var ret = { + focusSelf: false, + dispatchers: null + }; + + if (componentMainType == null || componentMainType === 'series' || componentIndex == null || name == null) { + return ret; + } + + var componentModel = api.getModel().getComponent(componentMainType, componentIndex); + + if (!componentModel) { + return ret; + } + + var view = api.getViewOfComponentModel(componentModel); + + if (!view || !view.findHighDownDispatchers) { + return ret; + } + + var dispatchers = view.findHighDownDispatchers(name); // At presnet, the component (like Geo) only blur inside itself. + // So we do not use `blurScope` in component. + + var focusSelf; + + for (var i = 0; i < dispatchers.length; i++) { + if ("development" !== 'production' && !isHighDownDispatcher(dispatchers[i])) { + error('param should be highDownDispatcher'); + } + + if (getECData(dispatchers[i]).focus === 'self') { + focusSelf = true; + break; + } + } + + return { + focusSelf: focusSelf, + dispatchers: dispatchers + }; + } + function handleGlobalMouseOverForHighDown(dispatcher, e, api) { + if ("development" !== 'production' && !isHighDownDispatcher(dispatcher)) { + error('param should be highDownDispatcher'); + } + + var ecData = getECData(dispatcher); + + var _a = findComponentHighDownDispatchers(ecData.componentMainType, ecData.componentIndex, ecData.componentHighDownName, api), + dispatchers = _a.dispatchers, + focusSelf = _a.focusSelf; // If `findHighDownDispatchers` is supported on the component, + // highlight/downplay elements with the same name. + + + if (dispatchers) { + if (focusSelf) { + blurComponent(ecData.componentMainType, ecData.componentIndex, api); + } + + each(dispatchers, function (dispatcher) { + return enterEmphasisWhenMouseOver(dispatcher, e); + }); + } else { + // Try blur all in the related series. Then emphasis the hoverred. + // TODO. progressive mode. + blurSeries(ecData.seriesIndex, ecData.focus, ecData.blurScope, api); + + if (ecData.focus === 'self') { + blurComponent(ecData.componentMainType, ecData.componentIndex, api); + } // Other than series, component that not support `findHighDownDispatcher` will + // also use it. But in this case, highlight/downplay are only supported in + // mouse hover but not in dispatchAction. + + + enterEmphasisWhenMouseOver(dispatcher, e); + } + } + function handleGlobalMouseOutForHighDown(dispatcher, e, api) { + if ("development" !== 'production' && !isHighDownDispatcher(dispatcher)) { + error('param should be highDownDispatcher'); + } + + allLeaveBlur(api); + var ecData = getECData(dispatcher); + var dispatchers = findComponentHighDownDispatchers(ecData.componentMainType, ecData.componentIndex, ecData.componentHighDownName, api).dispatchers; + + if (dispatchers) { + each(dispatchers, function (dispatcher) { + return leaveEmphasisWhenMouseOut(dispatcher, e); + }); + } else { + leaveEmphasisWhenMouseOut(dispatcher, e); + } + } + function toggleSelectionFromPayload(seriesModel, payload, api) { + if (!isSelectChangePayload(payload)) { + return; + } + + var dataType = payload.dataType; + var data = seriesModel.getData(dataType); + var dataIndex = queryDataIndex(data, payload); + + if (!isArray(dataIndex)) { + dataIndex = [dataIndex]; + } + + seriesModel[payload.type === TOGGLE_SELECT_ACTION_TYPE ? 'toggleSelect' : payload.type === SELECT_ACTION_TYPE ? 'select' : 'unselect'](dataIndex, dataType); + } + function updateSeriesElementSelection(seriesModel) { + var allData = seriesModel.getAllData(); + each(allData, function (_a) { + var data = _a.data, + type = _a.type; + data.eachItemGraphicEl(function (el, idx) { + seriesModel.isSelected(idx, type) ? enterSelect(el) : leaveSelect(el); + }); + }); + } + function getAllSelectedIndices(ecModel) { + var ret = []; + ecModel.eachSeries(function (seriesModel) { + var allData = seriesModel.getAllData(); + each(allData, function (_a) { + var data = _a.data, + type = _a.type; + var dataIndices = seriesModel.getSelectedDataIndices(); + + if (dataIndices.length > 0) { + var item = { + dataIndex: dataIndices, + seriesIndex: seriesModel.seriesIndex + }; + + if (type != null) { + item.dataType = type; + } + + ret.push(item); + } + }); + }); + return ret; + } + /** + * Enable the function that mouseover will trigger the emphasis state. + * + * NOTE: + * This function should be used on the element with dataIndex, seriesIndex. + * + */ + + function enableHoverEmphasis(el, focus, blurScope) { + setAsHighDownDispatcher(el, true); + traverseUpdateState(el, setDefaultStateProxy); + enableHoverFocus(el, focus, blurScope); + } + function disableHoverEmphasis(el) { + setAsHighDownDispatcher(el, false); + } + function toggleHoverEmphasis(el, focus, blurScope, isDisabled) { + isDisabled ? disableHoverEmphasis(el) : enableHoverEmphasis(el, focus, blurScope); + } + function enableHoverFocus(el, focus, blurScope) { + var ecData = getECData(el); + + if (focus != null) { + // TODO dataIndex may be set after this function. This check is not useful. + // if (ecData.dataIndex == null) { + // if (__DEV__) { + // console.warn('focus can only been set on element with dataIndex'); + // } + // } + // else { + ecData.focus = focus; + ecData.blurScope = blurScope; // } + } else if (ecData.focus) { + ecData.focus = null; + } + } + var OTHER_STATES = ['emphasis', 'blur', 'select']; + var defaultStyleGetterMap = { + itemStyle: 'getItemStyle', + lineStyle: 'getLineStyle', + areaStyle: 'getAreaStyle' + }; + /** + * Set emphasis/blur/selected states of element. + */ + + function setStatesStylesFromModel(el, itemModel, styleType, // default itemStyle + getter) { + styleType = styleType || 'itemStyle'; + + for (var i = 0; i < OTHER_STATES.length; i++) { + var stateName = OTHER_STATES[i]; + var model = itemModel.getModel([stateName, styleType]); + var state = el.ensureState(stateName); // Let it throw error if getterType is not found. + + state.style = getter ? getter(model) : model[defaultStyleGetterMap[styleType]](); + } + } + /** + * + * Set element as highlight / downplay dispatcher. + * It will be checked when element recieved mouseover event or from highlight action. + * It's in change of all highlight/downplay behavior of it's children. + * + * @param el + * @param el.highDownSilentOnTouch + * In touch device, mouseover event will be trigger on touchstart event + * (see module:zrender/dom/HandlerProxy). By this mechanism, we can + * conveniently use hoverStyle when tap on touch screen without additional + * code for compatibility. + * But if the chart/component has select feature, which usually also use + * hoverStyle, there might be conflict between 'select-highlight' and + * 'hover-highlight' especially when roam is enabled (see geo for example). + * In this case, `highDownSilentOnTouch` should be used to disable + * hover-highlight on touch device. + * @param asDispatcher If `false`, do not set as "highDownDispatcher". + */ + + function setAsHighDownDispatcher(el, asDispatcher) { + var disable = asDispatcher === false; + var extendedEl = el; // Make `highDownSilentOnTouch` and `onStateChange` only work after + // `setAsHighDownDispatcher` called. Avoid it is modified by user unexpectedly. + + if (el.highDownSilentOnTouch) { + extendedEl.__highDownSilentOnTouch = el.highDownSilentOnTouch; + } // Simple optimize, since this method might be + // called for each elements of a group in some cases. + + + if (!disable || extendedEl.__highDownDispatcher) { + // Emphasis, normal can be triggered manually by API or other components like hover link. + // el[method]('emphasis', onElementEmphasisEvent)[method]('normal', onElementNormalEvent); + // Also keep previous record. + extendedEl.__highByOuter = extendedEl.__highByOuter || 0; + extendedEl.__highDownDispatcher = !disable; + } + } + function isHighDownDispatcher(el) { + return !!(el && el.__highDownDispatcher); + } + /** + * Enable component highlight/downplay features: + * + hover link (within the same name) + * + focus blur in component + */ + + function enableComponentHighDownFeatures(el, componentModel, componentHighDownName) { + var ecData = getECData(el); + ecData.componentMainType = componentModel.mainType; + ecData.componentIndex = componentModel.componentIndex; + ecData.componentHighDownName = componentHighDownName; + } + /** + * Support hightlight/downplay record on each elements. + * For the case: hover highlight/downplay (legend, visualMap, ...) and + * user triggerred hightlight/downplay should not conflict. + * Only all of the highlightDigit cleared, return to normal. + * @param {string} highlightKey + * @return {number} highlightDigit + */ + + function getHighlightDigit(highlightKey) { + var highlightDigit = _highlightKeyMap[highlightKey]; + + if (highlightDigit == null && _highlightNextDigit <= 32) { + highlightDigit = _highlightKeyMap[highlightKey] = _highlightNextDigit++; + } + + return highlightDigit; + } + function isSelectChangePayload(payload) { + var payloadType = payload.type; + return payloadType === SELECT_ACTION_TYPE || payloadType === UNSELECT_ACTION_TYPE || payloadType === TOGGLE_SELECT_ACTION_TYPE; + } + function isHighDownPayload(payload) { + var payloadType = payload.type; + return payloadType === HIGHLIGHT_ACTION_TYPE || payloadType === DOWNPLAY_ACTION_TYPE; + } + function savePathStates(el) { + var store = getSavedStates(el); + store.normalFill = el.style.fill; + store.normalStroke = el.style.stroke; + var selectState = el.states.select || {}; + store.selectFill = selectState.style && selectState.style.fill || null; + store.selectStroke = selectState.style && selectState.style.stroke || null; + } + + var CMD$2 = PathProxy.CMD; + var points = [[], [], []]; + var mathSqrt$1 = Math.sqrt; + var mathAtan2 = Math.atan2; + function transformPath(path, m) { + if (!m) { + return; + } + var data = path.data; + var len = path.len(); + var cmd; + var nPoint; + var i; + var j; + var k; + var p; + var M = CMD$2.M; + var C = CMD$2.C; + var L = CMD$2.L; + var R = CMD$2.R; + var A = CMD$2.A; + var Q = CMD$2.Q; + for (i = 0, j = 0; i < len;) { + cmd = data[i++]; + j = i; + nPoint = 0; + switch (cmd) { + case M: + nPoint = 1; + break; + case L: + nPoint = 1; + break; + case C: + nPoint = 3; + break; + case Q: + nPoint = 2; + break; + case A: + var x = m[4]; + var y = m[5]; + var sx = mathSqrt$1(m[0] * m[0] + m[1] * m[1]); + var sy = mathSqrt$1(m[2] * m[2] + m[3] * m[3]); + var angle = mathAtan2(-m[1] / sy, m[0] / sx); + data[i] *= sx; + data[i++] += x; + data[i] *= sy; + data[i++] += y; + data[i++] *= sx; + data[i++] *= sy; + data[i++] += angle; + data[i++] += angle; + i += 2; + j = i; + break; + case R: + p[0] = data[i++]; + p[1] = data[i++]; + applyTransform(p, p, m); + data[j++] = p[0]; + data[j++] = p[1]; + p[0] += data[i++]; + p[1] += data[i++]; + applyTransform(p, p, m); + data[j++] = p[0]; + data[j++] = p[1]; + } + for (k = 0; k < nPoint; k++) { + var p_1 = points[k]; + p_1[0] = data[i++]; + p_1[1] = data[i++]; + applyTransform(p_1, p_1, m); + data[j++] = p_1[0]; + data[j++] = p_1[1]; + } + } + path.increaseVersion(); + } + + var mathSqrt$2 = Math.sqrt; + var mathSin$2 = Math.sin; + var mathCos$2 = Math.cos; + var PI$1 = Math.PI; + function vMag(v) { + return Math.sqrt(v[0] * v[0] + v[1] * v[1]); + } + function vRatio(u, v) { + return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v)); + } + function vAngle(u, v) { + return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) + * Math.acos(vRatio(u, v)); + } + function processArc(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg, cmd, path) { + var psi = psiDeg * (PI$1 / 180.0); + var xp = mathCos$2(psi) * (x1 - x2) / 2.0 + + mathSin$2(psi) * (y1 - y2) / 2.0; + var yp = -1 * mathSin$2(psi) * (x1 - x2) / 2.0 + + mathCos$2(psi) * (y1 - y2) / 2.0; + var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry); + if (lambda > 1) { + rx *= mathSqrt$2(lambda); + ry *= mathSqrt$2(lambda); + } + var f = (fa === fs ? -1 : 1) + * mathSqrt$2((((rx * rx) * (ry * ry)) + - ((rx * rx) * (yp * yp)) + - ((ry * ry) * (xp * xp))) / ((rx * rx) * (yp * yp) + + (ry * ry) * (xp * xp))) || 0; + var cxp = f * rx * yp / ry; + var cyp = f * -ry * xp / rx; + var cx = (x1 + x2) / 2.0 + + mathCos$2(psi) * cxp + - mathSin$2(psi) * cyp; + var cy = (y1 + y2) / 2.0 + + mathSin$2(psi) * cxp + + mathCos$2(psi) * cyp; + var theta = vAngle([1, 0], [(xp - cxp) / rx, (yp - cyp) / ry]); + var u = [(xp - cxp) / rx, (yp - cyp) / ry]; + var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry]; + var dTheta = vAngle(u, v); + if (vRatio(u, v) <= -1) { + dTheta = PI$1; + } + if (vRatio(u, v) >= 1) { + dTheta = 0; + } + if (dTheta < 0) { + var n = Math.round(dTheta / PI$1 * 1e6) / 1e6; + dTheta = PI$1 * 2 + (n % 2) * PI$1; + } + path.addData(cmd, cx, cy, rx, ry, theta, dTheta, psi, fs); + } + var commandReg = /([mlvhzcqtsa])([^mlvhzcqtsa]*)/ig; + var numberReg = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g; + function createPathProxyFromString(data) { + var path = new PathProxy(); + if (!data) { + return path; + } + var cpx = 0; + var cpy = 0; + var subpathX = cpx; + var subpathY = cpy; + var prevCmd; + var CMD = PathProxy.CMD; + var cmdList = data.match(commandReg); + if (!cmdList) { + return path; + } + for (var l = 0; l < cmdList.length; l++) { + var cmdText = cmdList[l]; + var cmdStr = cmdText.charAt(0); + var cmd = void 0; + var p = cmdText.match(numberReg) || []; + var pLen = p.length; + for (var i = 0; i < pLen; i++) { + p[i] = parseFloat(p[i]); + } + var off = 0; + while (off < pLen) { + var ctlPtx = void 0; + var ctlPty = void 0; + var rx = void 0; + var ry = void 0; + var psi = void 0; + var fa = void 0; + var fs = void 0; + var x1 = cpx; + var y1 = cpy; + var len = void 0; + var pathData = void 0; + switch (cmdStr) { + case 'l': + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'L': + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'm': + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.M; + path.addData(cmd, cpx, cpy); + subpathX = cpx; + subpathY = cpy; + cmdStr = 'l'; + break; + case 'M': + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.M; + path.addData(cmd, cpx, cpy); + subpathX = cpx; + subpathY = cpy; + cmdStr = 'L'; + break; + case 'h': + cpx += p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'H': + cpx = p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'v': + cpy += p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'V': + cpy = p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'C': + cmd = CMD.C; + path.addData(cmd, p[off++], p[off++], p[off++], p[off++], p[off++], p[off++]); + cpx = p[off - 2]; + cpy = p[off - 1]; + break; + case 'c': + cmd = CMD.C; + path.addData(cmd, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy); + cpx += p[off - 2]; + cpy += p[off - 1]; + break; + case 'S': + ctlPtx = cpx; + ctlPty = cpy; + len = path.len(); + pathData = path.data; + if (prevCmd === CMD.C) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cmd = CMD.C; + x1 = p[off++]; + y1 = p[off++]; + cpx = p[off++]; + cpy = p[off++]; + path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy); + break; + case 's': + ctlPtx = cpx; + ctlPty = cpy; + len = path.len(); + pathData = path.data; + if (prevCmd === CMD.C) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cmd = CMD.C; + x1 = cpx + p[off++]; + y1 = cpy + p[off++]; + cpx += p[off++]; + cpy += p[off++]; + path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy); + break; + case 'Q': + x1 = p[off++]; + y1 = p[off++]; + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.Q; + path.addData(cmd, x1, y1, cpx, cpy); + break; + case 'q': + x1 = p[off++] + cpx; + y1 = p[off++] + cpy; + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.Q; + path.addData(cmd, x1, y1, cpx, cpy); + break; + case 'T': + ctlPtx = cpx; + ctlPty = cpy; + len = path.len(); + pathData = path.data; + if (prevCmd === CMD.Q) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.Q; + path.addData(cmd, ctlPtx, ctlPty, cpx, cpy); + break; + case 't': + ctlPtx = cpx; + ctlPty = cpy; + len = path.len(); + pathData = path.data; + if (prevCmd === CMD.Q) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.Q; + path.addData(cmd, ctlPtx, ctlPty, cpx, cpy); + break; + case 'A': + rx = p[off++]; + ry = p[off++]; + psi = p[off++]; + fa = p[off++]; + fs = p[off++]; + x1 = cpx, y1 = cpy; + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.A; + processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path); + break; + case 'a': + rx = p[off++]; + ry = p[off++]; + psi = p[off++]; + fa = p[off++]; + fs = p[off++]; + x1 = cpx, y1 = cpy; + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.A; + processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path); + break; + } + } + if (cmdStr === 'z' || cmdStr === 'Z') { + cmd = CMD.Z; + path.addData(cmd); + cpx = subpathX; + cpy = subpathY; + } + prevCmd = cmd; + } + path.toStatic(); + return path; + } + var SVGPath = (function (_super) { + __extends(SVGPath, _super); + function SVGPath() { + return _super !== null && _super.apply(this, arguments) || this; + } + SVGPath.prototype.applyTransform = function (m) { }; + return SVGPath; + }(Path)); + function isPathProxy(path) { + return path.setData != null; + } + function createPathOptions(str, opts) { + var pathProxy = createPathProxyFromString(str); + var innerOpts = extend({}, opts); + innerOpts.buildPath = function (path) { + if (isPathProxy(path)) { + path.setData(pathProxy.data); + var ctx = path.getContext(); + if (ctx) { + path.rebuildPath(ctx, 1); + } + } + else { + var ctx = path; + pathProxy.rebuildPath(ctx, 1); + } + }; + innerOpts.applyTransform = function (m) { + transformPath(pathProxy, m); + this.dirtyShape(); + }; + return innerOpts; + } + function createFromString(str, opts) { + return new SVGPath(createPathOptions(str, opts)); + } + function extendFromString(str, defaultOpts) { + var innerOpts = createPathOptions(str, defaultOpts); + var Sub = (function (_super) { + __extends(Sub, _super); + function Sub(opts) { + var _this = _super.call(this, opts) || this; + _this.applyTransform = innerOpts.applyTransform; + _this.buildPath = innerOpts.buildPath; + return _this; + } + return Sub; + }(SVGPath)); + return Sub; + } + function mergePath(pathEls, opts) { + var pathList = []; + var len = pathEls.length; + for (var i = 0; i < len; i++) { + var pathEl = pathEls[i]; + pathList.push(pathEl.getUpdatedPathProxy(true)); + } + var pathBundle = new Path(opts); + pathBundle.createPathProxy(); + pathBundle.buildPath = function (path) { + if (isPathProxy(path)) { + path.appendPath(pathList); + var ctx = path.getContext(); + if (ctx) { + path.rebuildPath(ctx, 1); + } + } + }; + return pathBundle; + } + function clonePath(sourcePath, opts) { + opts = opts || {}; + var path = new Path(); + if (sourcePath.shape) { + path.setShape(sourcePath.shape); + } + path.setStyle(sourcePath.style); + if (opts.bakeTransform) { + transformPath(path.path, sourcePath.getComputedTransform()); + } + else { + if (opts.toLocal) { + path.setLocalTransform(sourcePath.getComputedTransform()); + } + else { + path.copyTransform(sourcePath); + } + } + path.buildPath = sourcePath.buildPath; + path.applyTransform = path.applyTransform; + path.z = sourcePath.z; + path.z2 = sourcePath.z2; + path.zlevel = sourcePath.zlevel; + return path; + } + + var CircleShape = (function () { + function CircleShape() { + this.cx = 0; + this.cy = 0; + this.r = 0; + } + return CircleShape; + }()); + var Circle = (function (_super) { + __extends(Circle, _super); + function Circle(opts) { + return _super.call(this, opts) || this; + } + Circle.prototype.getDefaultShape = function () { + return new CircleShape(); + }; + Circle.prototype.buildPath = function (ctx, shape) { + ctx.moveTo(shape.cx + shape.r, shape.cy); + ctx.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2); + }; + return Circle; + }(Path)); + Circle.prototype.type = 'circle'; + + var EllipseShape = (function () { + function EllipseShape() { + this.cx = 0; + this.cy = 0; + this.rx = 0; + this.ry = 0; + } + return EllipseShape; + }()); + var Ellipse = (function (_super) { + __extends(Ellipse, _super); + function Ellipse(opts) { + return _super.call(this, opts) || this; + } + Ellipse.prototype.getDefaultShape = function () { + return new EllipseShape(); + }; + Ellipse.prototype.buildPath = function (ctx, shape) { + var k = 0.5522848; + var x = shape.cx; + var y = shape.cy; + var a = shape.rx; + var b = shape.ry; + var ox = a * k; + var oy = b * k; + ctx.moveTo(x - a, y); + ctx.bezierCurveTo(x - a, y - oy, x - ox, y - b, x, y - b); + ctx.bezierCurveTo(x + ox, y - b, x + a, y - oy, x + a, y); + ctx.bezierCurveTo(x + a, y + oy, x + ox, y + b, x, y + b); + ctx.bezierCurveTo(x - ox, y + b, x - a, y + oy, x - a, y); + ctx.closePath(); + }; + return Ellipse; + }(Path)); + Ellipse.prototype.type = 'ellipse'; + + var PI$2 = Math.PI; + var PI2$5 = PI$2 * 2; + var mathSin$3 = Math.sin; + var mathCos$3 = Math.cos; + var mathACos = Math.acos; + var mathATan2 = Math.atan2; + var mathAbs$1 = Math.abs; + var mathSqrt$3 = Math.sqrt; + var mathMax$3 = Math.max; + var mathMin$3 = Math.min; + var e = 1e-4; + function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { + var dx10 = x1 - x0; + var dy10 = y1 - y0; + var dx32 = x3 - x2; + var dy32 = y3 - y2; + var t = dy32 * dx10 - dx32 * dy10; + if (t * t < e) { + return; + } + t = (dx32 * (y0 - y2) - dy32 * (x0 - x2)) / t; + return [x0 + t * dx10, y0 + t * dy10]; + } + function computeCornerTangents(x0, y0, x1, y1, radius, cr, clockwise) { + var x01 = x0 - x1; + var y01 = y0 - y1; + var lo = (clockwise ? cr : -cr) / mathSqrt$3(x01 * x01 + y01 * y01); + var ox = lo * y01; + var oy = -lo * x01; + var x11 = x0 + ox; + var y11 = y0 + oy; + var x10 = x1 + ox; + var y10 = y1 + oy; + var x00 = (x11 + x10) / 2; + var y00 = (y11 + y10) / 2; + var dx = x10 - x11; + var dy = y10 - y11; + var d2 = dx * dx + dy * dy; + var r = radius - cr; + var s = x11 * y10 - x10 * y11; + var d = (dy < 0 ? -1 : 1) * mathSqrt$3(mathMax$3(0, r * r * d2 - s * s)); + var cx0 = (s * dy - dx * d) / d2; + var cy0 = (-s * dx - dy * d) / d2; + var cx1 = (s * dy + dx * d) / d2; + var cy1 = (-s * dx + dy * d) / d2; + var dx0 = cx0 - x00; + var dy0 = cy0 - y00; + var dx1 = cx1 - x00; + var dy1 = cy1 - y00; + if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) { + cx0 = cx1; + cy0 = cy1; + } + return { + cx: cx0, + cy: cy0, + x0: -ox, + y0: -oy, + x1: cx0 * (radius / r - 1), + y1: cy0 * (radius / r - 1) + }; + } + function normalizeCornerRadius(cr) { + var arr; + if (isArray(cr)) { + var len = cr.length; + if (!len) { + return cr; + } + if (len === 1) { + arr = [cr[0], cr[0], 0, 0]; + } + else if (len === 2) { + arr = [cr[0], cr[0], cr[1], cr[1]]; + } + else if (len === 3) { + arr = cr.concat(cr[2]); + } + else { + arr = cr; + } + } + else { + arr = [cr, cr, cr, cr]; + } + return arr; + } + function buildPath$1(ctx, shape) { + var _a; + var radius = mathMax$3(shape.r, 0); + var innerRadius = mathMax$3(shape.r0 || 0, 0); + var hasRadius = radius > 0; + var hasInnerRadius = innerRadius > 0; + if (!hasRadius && !hasInnerRadius) { + return; + } + if (!hasRadius) { + radius = innerRadius; + innerRadius = 0; + } + if (innerRadius > radius) { + var tmp = radius; + radius = innerRadius; + innerRadius = tmp; + } + var startAngle = shape.startAngle, endAngle = shape.endAngle; + if (isNaN(startAngle) || isNaN(endAngle)) { + return; + } + var cx = shape.cx, cy = shape.cy; + var clockwise = !!shape.clockwise; + var arc = mathAbs$1(endAngle - startAngle); + var mod = arc > PI2$5 && arc % PI2$5; + mod > e && (arc = mod); + if (!(radius > e)) { + ctx.moveTo(cx, cy); + } + else if (arc > PI2$5 - e) { + ctx.moveTo(cx + radius * mathCos$3(startAngle), cy + radius * mathSin$3(startAngle)); + ctx.arc(cx, cy, radius, startAngle, endAngle, !clockwise); + if (innerRadius > e) { + ctx.moveTo(cx + innerRadius * mathCos$3(endAngle), cy + innerRadius * mathSin$3(endAngle)); + ctx.arc(cx, cy, innerRadius, endAngle, startAngle, clockwise); + } + } + else { + var icrStart = void 0; + var icrEnd = void 0; + var ocrStart = void 0; + var ocrEnd = void 0; + var ocrs = void 0; + var ocre = void 0; + var icrs = void 0; + var icre = void 0; + var ocrMax = void 0; + var icrMax = void 0; + var limitedOcrMax = void 0; + var limitedIcrMax = void 0; + var xre = void 0; + var yre = void 0; + var xirs = void 0; + var yirs = void 0; + var xrs = radius * mathCos$3(startAngle); + var yrs = radius * mathSin$3(startAngle); + var xire = innerRadius * mathCos$3(endAngle); + var yire = innerRadius * mathSin$3(endAngle); + var hasArc = arc > e; + if (hasArc) { + var cornerRadius = shape.cornerRadius; + if (cornerRadius) { + _a = normalizeCornerRadius(cornerRadius), icrStart = _a[0], icrEnd = _a[1], ocrStart = _a[2], ocrEnd = _a[3]; + } + var halfRd = mathAbs$1(radius - innerRadius) / 2; + ocrs = mathMin$3(halfRd, ocrStart); + ocre = mathMin$3(halfRd, ocrEnd); + icrs = mathMin$3(halfRd, icrStart); + icre = mathMin$3(halfRd, icrEnd); + limitedOcrMax = ocrMax = mathMax$3(ocrs, ocre); + limitedIcrMax = icrMax = mathMax$3(icrs, icre); + if (ocrMax > e || icrMax > e) { + xre = radius * mathCos$3(endAngle); + yre = radius * mathSin$3(endAngle); + xirs = innerRadius * mathCos$3(startAngle); + yirs = innerRadius * mathSin$3(startAngle); + if (arc < PI$2) { + var it_1 = intersect(xrs, yrs, xirs, yirs, xre, yre, xire, yire); + if (it_1) { + var x0 = xrs - it_1[0]; + var y0 = yrs - it_1[1]; + var x1 = xre - it_1[0]; + var y1 = yre - it_1[1]; + var a = 1 / mathSin$3(mathACos((x0 * x1 + y0 * y1) / (mathSqrt$3(x0 * x0 + y0 * y0) * mathSqrt$3(x1 * x1 + y1 * y1))) / 2); + var b = mathSqrt$3(it_1[0] * it_1[0] + it_1[1] * it_1[1]); + limitedOcrMax = mathMin$3(ocrMax, (radius - b) / (a + 1)); + limitedIcrMax = mathMin$3(icrMax, (innerRadius - b) / (a - 1)); + } + } + } + } + if (!hasArc) { + ctx.moveTo(cx + xrs, cy + yrs); + } + else if (limitedOcrMax > e) { + var crStart = mathMin$3(ocrStart, limitedOcrMax); + var crEnd = mathMin$3(ocrEnd, limitedOcrMax); + var ct0 = computeCornerTangents(xirs, yirs, xrs, yrs, radius, crStart, clockwise); + var ct1 = computeCornerTangents(xre, yre, xire, yire, radius, crEnd, clockwise); + ctx.moveTo(cx + ct0.cx + ct0.x0, cy + ct0.cy + ct0.y0); + if (limitedOcrMax < ocrMax && crStart === crEnd) { + ctx.arc(cx + ct0.cx, cy + ct0.cy, limitedOcrMax, mathATan2(ct0.y0, ct0.x0), mathATan2(ct1.y0, ct1.x0), !clockwise); + } + else { + crStart > 0 && ctx.arc(cx + ct0.cx, cy + ct0.cy, crStart, mathATan2(ct0.y0, ct0.x0), mathATan2(ct0.y1, ct0.x1), !clockwise); + ctx.arc(cx, cy, radius, mathATan2(ct0.cy + ct0.y1, ct0.cx + ct0.x1), mathATan2(ct1.cy + ct1.y1, ct1.cx + ct1.x1), !clockwise); + crEnd > 0 && ctx.arc(cx + ct1.cx, cy + ct1.cy, crEnd, mathATan2(ct1.y1, ct1.x1), mathATan2(ct1.y0, ct1.x0), !clockwise); + } + } + else { + ctx.moveTo(cx + xrs, cy + yrs); + ctx.arc(cx, cy, radius, startAngle, endAngle, !clockwise); + } + if (!(innerRadius > e) || !hasArc) { + ctx.lineTo(cx + xire, cy + yire); + } + else if (limitedIcrMax > e) { + var crStart = mathMin$3(icrStart, limitedIcrMax); + var crEnd = mathMin$3(icrEnd, limitedIcrMax); + var ct0 = computeCornerTangents(xire, yire, xre, yre, innerRadius, -crEnd, clockwise); + var ct1 = computeCornerTangents(xrs, yrs, xirs, yirs, innerRadius, -crStart, clockwise); + ctx.lineTo(cx + ct0.cx + ct0.x0, cy + ct0.cy + ct0.y0); + if (limitedIcrMax < icrMax && crStart === crEnd) { + ctx.arc(cx + ct0.cx, cy + ct0.cy, limitedIcrMax, mathATan2(ct0.y0, ct0.x0), mathATan2(ct1.y0, ct1.x0), !clockwise); + } + else { + crEnd > 0 && ctx.arc(cx + ct0.cx, cy + ct0.cy, crEnd, mathATan2(ct0.y0, ct0.x0), mathATan2(ct0.y1, ct0.x1), !clockwise); + ctx.arc(cx, cy, innerRadius, mathATan2(ct0.cy + ct0.y1, ct0.cx + ct0.x1), mathATan2(ct1.cy + ct1.y1, ct1.cx + ct1.x1), clockwise); + crStart > 0 && ctx.arc(cx + ct1.cx, cy + ct1.cy, crStart, mathATan2(ct1.y1, ct1.x1), mathATan2(ct1.y0, ct1.x0), !clockwise); + } + } + else { + ctx.lineTo(cx + xire, cy + yire); + ctx.arc(cx, cy, innerRadius, endAngle, startAngle, clockwise); + } + } + ctx.closePath(); + } + + var SectorShape = (function () { + function SectorShape() { + this.cx = 0; + this.cy = 0; + this.r0 = 0; + this.r = 0; + this.startAngle = 0; + this.endAngle = Math.PI * 2; + this.clockwise = true; + this.cornerRadius = 0; + } + return SectorShape; + }()); + var Sector = (function (_super) { + __extends(Sector, _super); + function Sector(opts) { + return _super.call(this, opts) || this; + } + Sector.prototype.getDefaultShape = function () { + return new SectorShape(); + }; + Sector.prototype.buildPath = function (ctx, shape) { + buildPath$1(ctx, shape); + }; + Sector.prototype.isZeroArea = function () { + return this.shape.startAngle === this.shape.endAngle + || this.shape.r === this.shape.r0; + }; + return Sector; + }(Path)); + Sector.prototype.type = 'sector'; + + var RingShape = (function () { + function RingShape() { + this.cx = 0; + this.cy = 0; + this.r = 0; + this.r0 = 0; + } + return RingShape; + }()); + var Ring = (function (_super) { + __extends(Ring, _super); + function Ring(opts) { + return _super.call(this, opts) || this; + } + Ring.prototype.getDefaultShape = function () { + return new RingShape(); + }; + Ring.prototype.buildPath = function (ctx, shape) { + var x = shape.cx; + var y = shape.cy; + var PI2 = Math.PI * 2; + ctx.moveTo(x + shape.r, y); + ctx.arc(x, y, shape.r, 0, PI2, false); + ctx.moveTo(x + shape.r0, y); + ctx.arc(x, y, shape.r0, 0, PI2, true); + }; + return Ring; + }(Path)); + Ring.prototype.type = 'ring'; + + function smoothBezier(points, smooth, isLoop, constraint) { + var cps = []; + var v = []; + var v1 = []; + var v2 = []; + var prevPoint; + var nextPoint; + var min$1; + var max$1; + if (constraint) { + min$1 = [Infinity, Infinity]; + max$1 = [-Infinity, -Infinity]; + for (var i = 0, len = points.length; i < len; i++) { + min(min$1, min$1, points[i]); + max(max$1, max$1, points[i]); + } + min(min$1, min$1, constraint[0]); + max(max$1, max$1, constraint[1]); + } + for (var i = 0, len = points.length; i < len; i++) { + var point = points[i]; + if (isLoop) { + prevPoint = points[i ? i - 1 : len - 1]; + nextPoint = points[(i + 1) % len]; + } + else { + if (i === 0 || i === len - 1) { + cps.push(clone$1(points[i])); + continue; + } + else { + prevPoint = points[i - 1]; + nextPoint = points[i + 1]; + } + } + sub(v, nextPoint, prevPoint); + scale(v, v, smooth); + var d0 = distance(point, prevPoint); + var d1 = distance(point, nextPoint); + var sum = d0 + d1; + if (sum !== 0) { + d0 /= sum; + d1 /= sum; + } + scale(v1, v, -d0); + scale(v2, v, d1); + var cp0 = add([], point, v1); + var cp1 = add([], point, v2); + if (constraint) { + max(cp0, cp0, min$1); + min(cp0, cp0, max$1); + max(cp1, cp1, min$1); + min(cp1, cp1, max$1); + } + cps.push(cp0); + cps.push(cp1); + } + if (isLoop) { + cps.push(cps.shift()); + } + return cps; + } + + function buildPath$2(ctx, shape, closePath) { + var smooth = shape.smooth; + var points = shape.points; + if (points && points.length >= 2) { + if (smooth) { + var controlPoints = smoothBezier(points, smooth, closePath, shape.smoothConstraint); + ctx.moveTo(points[0][0], points[0][1]); + var len = points.length; + for (var i = 0; i < (closePath ? len : len - 1); i++) { + var cp1 = controlPoints[i * 2]; + var cp2 = controlPoints[i * 2 + 1]; + var p = points[(i + 1) % len]; + ctx.bezierCurveTo(cp1[0], cp1[1], cp2[0], cp2[1], p[0], p[1]); + } + } + else { + ctx.moveTo(points[0][0], points[0][1]); + for (var i = 1, l = points.length; i < l; i++) { + ctx.lineTo(points[i][0], points[i][1]); + } + } + closePath && ctx.closePath(); + } + } + + var PolygonShape = (function () { + function PolygonShape() { + this.points = null; + this.smooth = 0; + this.smoothConstraint = null; + } + return PolygonShape; + }()); + var Polygon = (function (_super) { + __extends(Polygon, _super); + function Polygon(opts) { + return _super.call(this, opts) || this; + } + Polygon.prototype.getDefaultShape = function () { + return new PolygonShape(); + }; + Polygon.prototype.buildPath = function (ctx, shape) { + buildPath$2(ctx, shape, true); + }; + return Polygon; + }(Path)); + Polygon.prototype.type = 'polygon'; + + var PolylineShape = (function () { + function PolylineShape() { + this.points = null; + this.percent = 1; + this.smooth = 0; + this.smoothConstraint = null; + } + return PolylineShape; + }()); + var Polyline = (function (_super) { + __extends(Polyline, _super); + function Polyline(opts) { + return _super.call(this, opts) || this; + } + Polyline.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + Polyline.prototype.getDefaultShape = function () { + return new PolylineShape(); + }; + Polyline.prototype.buildPath = function (ctx, shape) { + buildPath$2(ctx, shape, false); + }; + return Polyline; + }(Path)); + Polyline.prototype.type = 'polyline'; + + var subPixelOptimizeOutputShape$1 = {}; + var LineShape = (function () { + function LineShape() { + this.x1 = 0; + this.y1 = 0; + this.x2 = 0; + this.y2 = 0; + this.percent = 1; + } + return LineShape; + }()); + var Line = (function (_super) { + __extends(Line, _super); + function Line(opts) { + return _super.call(this, opts) || this; + } + Line.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + Line.prototype.getDefaultShape = function () { + return new LineShape(); + }; + Line.prototype.buildPath = function (ctx, shape) { + var x1; + var y1; + var x2; + var y2; + if (this.subPixelOptimize) { + var optimizedShape = subPixelOptimizeLine(subPixelOptimizeOutputShape$1, shape, this.style); + x1 = optimizedShape.x1; + y1 = optimizedShape.y1; + x2 = optimizedShape.x2; + y2 = optimizedShape.y2; + } + else { + x1 = shape.x1; + y1 = shape.y1; + x2 = shape.x2; + y2 = shape.y2; + } + var percent = shape.percent; + if (percent === 0) { + return; + } + ctx.moveTo(x1, y1); + if (percent < 1) { + x2 = x1 * (1 - percent) + x2 * percent; + y2 = y1 * (1 - percent) + y2 * percent; + } + ctx.lineTo(x2, y2); + }; + Line.prototype.pointAt = function (p) { + var shape = this.shape; + return [ + shape.x1 * (1 - p) + shape.x2 * p, + shape.y1 * (1 - p) + shape.y2 * p + ]; + }; + return Line; + }(Path)); + Line.prototype.type = 'line'; + + var out = []; + var BezierCurveShape = (function () { + function BezierCurveShape() { + this.x1 = 0; + this.y1 = 0; + this.x2 = 0; + this.y2 = 0; + this.cpx1 = 0; + this.cpy1 = 0; + this.percent = 1; + } + return BezierCurveShape; + }()); + function someVectorAt(shape, t, isTangent) { + var cpx2 = shape.cpx2; + var cpy2 = shape.cpy2; + if (cpx2 != null || cpy2 != null) { + return [ + (isTangent ? cubicDerivativeAt : cubicAt)(shape.x1, shape.cpx1, shape.cpx2, shape.x2, t), + (isTangent ? cubicDerivativeAt : cubicAt)(shape.y1, shape.cpy1, shape.cpy2, shape.y2, t) + ]; + } + else { + return [ + (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.x1, shape.cpx1, shape.x2, t), + (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.y1, shape.cpy1, shape.y2, t) + ]; + } + } + var BezierCurve = (function (_super) { + __extends(BezierCurve, _super); + function BezierCurve(opts) { + return _super.call(this, opts) || this; + } + BezierCurve.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + BezierCurve.prototype.getDefaultShape = function () { + return new BezierCurveShape(); + }; + BezierCurve.prototype.buildPath = function (ctx, shape) { + var x1 = shape.x1; + var y1 = shape.y1; + var x2 = shape.x2; + var y2 = shape.y2; + var cpx1 = shape.cpx1; + var cpy1 = shape.cpy1; + var cpx2 = shape.cpx2; + var cpy2 = shape.cpy2; + var percent = shape.percent; + if (percent === 0) { + return; + } + ctx.moveTo(x1, y1); + if (cpx2 == null || cpy2 == null) { + if (percent < 1) { + quadraticSubdivide(x1, cpx1, x2, percent, out); + cpx1 = out[1]; + x2 = out[2]; + quadraticSubdivide(y1, cpy1, y2, percent, out); + cpy1 = out[1]; + y2 = out[2]; + } + ctx.quadraticCurveTo(cpx1, cpy1, x2, y2); + } + else { + if (percent < 1) { + cubicSubdivide(x1, cpx1, cpx2, x2, percent, out); + cpx1 = out[1]; + cpx2 = out[2]; + x2 = out[3]; + cubicSubdivide(y1, cpy1, cpy2, y2, percent, out); + cpy1 = out[1]; + cpy2 = out[2]; + y2 = out[3]; + } + ctx.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x2, y2); + } + }; + BezierCurve.prototype.pointAt = function (t) { + return someVectorAt(this.shape, t, false); + }; + BezierCurve.prototype.tangentAt = function (t) { + var p = someVectorAt(this.shape, t, true); + return normalize(p, p); + }; + return BezierCurve; + }(Path)); + BezierCurve.prototype.type = 'bezier-curve'; + + var ArcShape = (function () { + function ArcShape() { + this.cx = 0; + this.cy = 0; + this.r = 0; + this.startAngle = 0; + this.endAngle = Math.PI * 2; + this.clockwise = true; + } + return ArcShape; + }()); + var Arc = (function (_super) { + __extends(Arc, _super); + function Arc(opts) { + return _super.call(this, opts) || this; + } + Arc.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + Arc.prototype.getDefaultShape = function () { + return new ArcShape(); + }; + Arc.prototype.buildPath = function (ctx, shape) { + var x = shape.cx; + var y = shape.cy; + var r = Math.max(shape.r, 0); + var startAngle = shape.startAngle; + var endAngle = shape.endAngle; + var clockwise = shape.clockwise; + var unitX = Math.cos(startAngle); + var unitY = Math.sin(startAngle); + ctx.moveTo(unitX * r + x, unitY * r + y); + ctx.arc(x, y, r, startAngle, endAngle, !clockwise); + }; + return Arc; + }(Path)); + Arc.prototype.type = 'arc'; + + var CompoundPath = (function (_super) { + __extends(CompoundPath, _super); + function CompoundPath() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.type = 'compound'; + return _this; + } + CompoundPath.prototype._updatePathDirty = function () { + var paths = this.shape.paths; + var dirtyPath = this.shapeChanged(); + for (var i = 0; i < paths.length; i++) { + dirtyPath = dirtyPath || paths[i].shapeChanged(); + } + if (dirtyPath) { + this.dirtyShape(); + } + }; + CompoundPath.prototype.beforeBrush = function () { + this._updatePathDirty(); + var paths = this.shape.paths || []; + var scale = this.getGlobalScale(); + for (var i = 0; i < paths.length; i++) { + if (!paths[i].path) { + paths[i].createPathProxy(); + } + paths[i].path.setScale(scale[0], scale[1], paths[i].segmentIgnoreThreshold); + } + }; + CompoundPath.prototype.buildPath = function (ctx, shape) { + var paths = shape.paths || []; + for (var i = 0; i < paths.length; i++) { + paths[i].buildPath(ctx, paths[i].shape, true); + } + }; + CompoundPath.prototype.afterBrush = function () { + var paths = this.shape.paths || []; + for (var i = 0; i < paths.length; i++) { + paths[i].pathUpdated(); + } + }; + CompoundPath.prototype.getBoundingRect = function () { + this._updatePathDirty.call(this); + return Path.prototype.getBoundingRect.call(this); + }; + return CompoundPath; + }(Path)); + + var Gradient = (function () { + function Gradient(colorStops) { + this.colorStops = colorStops || []; + } + Gradient.prototype.addColorStop = function (offset, color) { + this.colorStops.push({ + offset: offset, + color: color + }); + }; + return Gradient; + }()); + + var LinearGradient = (function (_super) { + __extends(LinearGradient, _super); + function LinearGradient(x, y, x2, y2, colorStops, globalCoord) { + var _this = _super.call(this, colorStops) || this; + _this.x = x == null ? 0 : x; + _this.y = y == null ? 0 : y; + _this.x2 = x2 == null ? 1 : x2; + _this.y2 = y2 == null ? 0 : y2; + _this.type = 'linear'; + _this.global = globalCoord || false; + return _this; + } + return LinearGradient; + }(Gradient)); + + var RadialGradient = (function (_super) { + __extends(RadialGradient, _super); + function RadialGradient(x, y, r, colorStops, globalCoord) { + var _this = _super.call(this, colorStops) || this; + _this.x = x == null ? 0.5 : x; + _this.y = y == null ? 0.5 : y; + _this.r = r == null ? 0.5 : r; + _this.type = 'radial'; + _this.global = globalCoord || false; + return _this; + } + return RadialGradient; + }(Gradient)); + + var extent = [0, 0]; + var extent2 = [0, 0]; + var minTv$1 = new Point(); + var maxTv$1 = new Point(); + var OrientedBoundingRect = (function () { + function OrientedBoundingRect(rect, transform) { + this._corners = []; + this._axes = []; + this._origin = [0, 0]; + for (var i = 0; i < 4; i++) { + this._corners[i] = new Point(); + } + for (var i = 0; i < 2; i++) { + this._axes[i] = new Point(); + } + if (rect) { + this.fromBoundingRect(rect, transform); + } + } + OrientedBoundingRect.prototype.fromBoundingRect = function (rect, transform) { + var corners = this._corners; + var axes = this._axes; + var x = rect.x; + var y = rect.y; + var x2 = x + rect.width; + var y2 = y + rect.height; + corners[0].set(x, y); + corners[1].set(x2, y); + corners[2].set(x2, y2); + corners[3].set(x, y2); + if (transform) { + for (var i = 0; i < 4; i++) { + corners[i].transform(transform); + } + } + Point.sub(axes[0], corners[1], corners[0]); + Point.sub(axes[1], corners[3], corners[0]); + axes[0].normalize(); + axes[1].normalize(); + for (var i = 0; i < 2; i++) { + this._origin[i] = axes[i].dot(corners[0]); + } + }; + OrientedBoundingRect.prototype.intersect = function (other, mtv) { + var overlapped = true; + var noMtv = !mtv; + minTv$1.set(Infinity, Infinity); + maxTv$1.set(0, 0); + if (!this._intersectCheckOneSide(this, other, minTv$1, maxTv$1, noMtv, 1)) { + overlapped = false; + if (noMtv) { + return overlapped; + } + } + if (!this._intersectCheckOneSide(other, this, minTv$1, maxTv$1, noMtv, -1)) { + overlapped = false; + if (noMtv) { + return overlapped; + } + } + if (!noMtv) { + Point.copy(mtv, overlapped ? minTv$1 : maxTv$1); + } + return overlapped; + }; + OrientedBoundingRect.prototype._intersectCheckOneSide = function (self, other, minTv, maxTv, noMtv, inverse) { + var overlapped = true; + for (var i = 0; i < 2; i++) { + var axis = this._axes[i]; + this._getProjMinMaxOnAxis(i, self._corners, extent); + this._getProjMinMaxOnAxis(i, other._corners, extent2); + if (extent[1] < extent2[0] || extent[0] > extent2[1]) { + overlapped = false; + if (noMtv) { + return overlapped; + } + var dist0 = Math.abs(extent2[0] - extent[1]); + var dist1 = Math.abs(extent[0] - extent2[1]); + if (Math.min(dist0, dist1) > maxTv.len()) { + if (dist0 < dist1) { + Point.scale(maxTv, axis, -dist0 * inverse); + } + else { + Point.scale(maxTv, axis, dist1 * inverse); + } + } + } + else if (minTv) { + var dist0 = Math.abs(extent2[0] - extent[1]); + var dist1 = Math.abs(extent[0] - extent2[1]); + if (Math.min(dist0, dist1) < minTv.len()) { + if (dist0 < dist1) { + Point.scale(minTv, axis, dist0 * inverse); + } + else { + Point.scale(minTv, axis, -dist1 * inverse); + } + } + } + } + return overlapped; + }; + OrientedBoundingRect.prototype._getProjMinMaxOnAxis = function (dim, corners, out) { + var axis = this._axes[dim]; + var origin = this._origin; + var proj = corners[0].dot(axis) + origin[dim]; + var min = proj; + var max = proj; + for (var i = 1; i < corners.length; i++) { + var proj_1 = corners[i].dot(axis) + origin[dim]; + min = Math.min(proj_1, min); + max = Math.max(proj_1, max); + } + out[0] = min; + out[1] = max; + }; + return OrientedBoundingRect; + }()); + + var m = []; + var IncrementalDisplayable = (function (_super) { + __extends(IncrementalDisplayable, _super); + function IncrementalDisplayable() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.notClear = true; + _this.incremental = true; + _this._displayables = []; + _this._temporaryDisplayables = []; + _this._cursor = 0; + return _this; + } + IncrementalDisplayable.prototype.traverse = function (cb, context) { + cb.call(context, this); + }; + IncrementalDisplayable.prototype.useStyle = function () { + this.style = {}; + }; + IncrementalDisplayable.prototype.getCursor = function () { + return this._cursor; + }; + IncrementalDisplayable.prototype.innerAfterBrush = function () { + this._cursor = this._displayables.length; + }; + IncrementalDisplayable.prototype.clearDisplaybles = function () { + this._displayables = []; + this._temporaryDisplayables = []; + this._cursor = 0; + this.markRedraw(); + this.notClear = false; + }; + IncrementalDisplayable.prototype.clearTemporalDisplayables = function () { + this._temporaryDisplayables = []; + }; + IncrementalDisplayable.prototype.addDisplayable = function (displayable, notPersistent) { + if (notPersistent) { + this._temporaryDisplayables.push(displayable); + } + else { + this._displayables.push(displayable); + } + this.markRedraw(); + }; + IncrementalDisplayable.prototype.addDisplayables = function (displayables, notPersistent) { + notPersistent = notPersistent || false; + for (var i = 0; i < displayables.length; i++) { + this.addDisplayable(displayables[i], notPersistent); + } + }; + IncrementalDisplayable.prototype.getDisplayables = function () { + return this._displayables; + }; + IncrementalDisplayable.prototype.getTemporalDisplayables = function () { + return this._temporaryDisplayables; + }; + IncrementalDisplayable.prototype.eachPendingDisplayable = function (cb) { + for (var i = this._cursor; i < this._displayables.length; i++) { + cb && cb(this._displayables[i]); + } + for (var i = 0; i < this._temporaryDisplayables.length; i++) { + cb && cb(this._temporaryDisplayables[i]); + } + }; + IncrementalDisplayable.prototype.update = function () { + this.updateTransform(); + for (var i = this._cursor; i < this._displayables.length; i++) { + var displayable = this._displayables[i]; + displayable.parent = this; + displayable.update(); + displayable.parent = null; + } + for (var i = 0; i < this._temporaryDisplayables.length; i++) { + var displayable = this._temporaryDisplayables[i]; + displayable.parent = this; + displayable.update(); + displayable.parent = null; + } + }; + IncrementalDisplayable.prototype.getBoundingRect = function () { + if (!this._rect) { + var rect = new BoundingRect(Infinity, Infinity, -Infinity, -Infinity); + for (var i = 0; i < this._displayables.length; i++) { + var displayable = this._displayables[i]; + var childRect = displayable.getBoundingRect().clone(); + if (displayable.needLocalTransform()) { + childRect.applyTransform(displayable.getLocalTransform(m)); + } + rect.union(childRect); + } + this._rect = rect; + } + return this._rect; + }; + IncrementalDisplayable.prototype.contain = function (x, y) { + var localPos = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + if (rect.contain(localPos[0], localPos[1])) { + for (var i = 0; i < this._displayables.length; i++) { + var displayable = this._displayables[i]; + if (displayable.contain(x, y)) { + return true; + } + } + } + return false; + }; + return IncrementalDisplayable; + }(Displayable)); + + var transitionStore = makeInner(); + /** + * Return null if animation is disabled. + */ + + function getAnimationConfig(animationType, animatableModel, dataIndex, // Extra opts can override the option in animatable model. + extraOpts, // TODO It's only for pictorial bar now. + extraDelayParams) { + var animationPayload; // Check if there is global animation configuration from dataZoom/resize can override the config in option. + // If animation is enabled. Will use this animation config in payload. + // If animation is disabled. Just ignore it. + + if (animatableModel && animatableModel.ecModel) { + var updatePayload = animatableModel.ecModel.getUpdatePayload(); + animationPayload = updatePayload && updatePayload.animation; + } + + var animationEnabled = animatableModel && animatableModel.isAnimationEnabled(); + var isUpdate = animationType === 'update'; + + if (animationEnabled) { + var duration = void 0; + var easing = void 0; + var delay = void 0; + + if (extraOpts) { + duration = retrieve2(extraOpts.duration, 200); + easing = retrieve2(extraOpts.easing, 'cubicOut'); + delay = 0; + } else { + duration = animatableModel.getShallow(isUpdate ? 'animationDurationUpdate' : 'animationDuration'); + easing = animatableModel.getShallow(isUpdate ? 'animationEasingUpdate' : 'animationEasing'); + delay = animatableModel.getShallow(isUpdate ? 'animationDelayUpdate' : 'animationDelay'); + } // animation from payload has highest priority. + + + if (animationPayload) { + animationPayload.duration != null && (duration = animationPayload.duration); + animationPayload.easing != null && (easing = animationPayload.easing); + animationPayload.delay != null && (delay = animationPayload.delay); + } + + if (isFunction(delay)) { + delay = delay(dataIndex, extraDelayParams); + } + + if (isFunction(duration)) { + duration = duration(dataIndex); + } + + var config = { + duration: duration || 0, + delay: delay, + easing: easing + }; + return config; + } else { + return null; + } + } + + function animateOrSetProps(animationType, el, props, animatableModel, dataIndex, cb, during) { + var isFrom = false; + var removeOpt; + + if (isFunction(dataIndex)) { + during = cb; + cb = dataIndex; + dataIndex = null; + } else if (isObject(dataIndex)) { + cb = dataIndex.cb; + during = dataIndex.during; + isFrom = dataIndex.isFrom; + removeOpt = dataIndex.removeOpt; + dataIndex = dataIndex.dataIndex; + } + + var isRemove = animationType === 'leave'; + + if (!isRemove) { + // Must stop the remove animation. + el.stopAnimation('leave'); + } + + var animationConfig = getAnimationConfig(animationType, animatableModel, dataIndex, isRemove ? removeOpt || {} : null, animatableModel && animatableModel.getAnimationDelayParams ? animatableModel.getAnimationDelayParams(el, dataIndex) : null); + + if (animationConfig && animationConfig.duration > 0) { + var duration = animationConfig.duration; + var animationDelay = animationConfig.delay; + var animationEasing = animationConfig.easing; + var animateConfig = { + duration: duration, + delay: animationDelay || 0, + easing: animationEasing, + done: cb, + force: !!cb || !!during, + // Set to final state in update/init animation. + // So the post processing based on the path shape can be done correctly. + setToFinal: !isRemove, + scope: animationType, + during: during + }; + isFrom ? el.animateFrom(props, animateConfig) : el.animateTo(props, animateConfig); + } else { + el.stopAnimation(); // If `isFrom`, the props is the "from" props. + + !isFrom && el.attr(props); // Call during at least once. + + during && during(1); + cb && cb(); + } + } + /** + * Update graphic element properties with or without animation according to the + * configuration in series. + * + * Caution: this method will stop previous animation. + * So do not use this method to one element twice before + * animation starts, unless you know what you are doing. + * @example + * graphic.updateProps(el, { + * position: [100, 100] + * }, seriesModel, dataIndex, function () { console.log('Animation done!'); }); + * // Or + * graphic.updateProps(el, { + * position: [100, 100] + * }, seriesModel, function () { console.log('Animation done!'); }); + */ + + + function updateProps(el, props, // TODO: TYPE AnimatableModel + animatableModel, dataIndex, cb, during) { + animateOrSetProps('update', el, props, animatableModel, dataIndex, cb, during); + } + /** + * Init graphic element properties with or without animation according to the + * configuration in series. + * + * Caution: this method will stop previous animation. + * So do not use this method to one element twice before + * animation starts, unless you know what you are doing. + */ + + function initProps(el, props, animatableModel, dataIndex, cb, during) { + animateOrSetProps('enter', el, props, animatableModel, dataIndex, cb, during); + } + /** + * If element is removed. + * It can determine if element is having remove animation. + */ + + function isElementRemoved(el) { + if (!el.__zr) { + return true; + } + + for (var i = 0; i < el.animators.length; i++) { + var animator = el.animators[i]; + + if (animator.scope === 'leave') { + return true; + } + } + + return false; + } + /** + * Remove graphic element + */ + + function removeElement(el, props, animatableModel, dataIndex, cb, during) { + // Don't do remove animation twice. + if (isElementRemoved(el)) { + return; + } + + animateOrSetProps('leave', el, props, animatableModel, dataIndex, cb, during); + } + + function fadeOutDisplayable(el, animatableModel, dataIndex, done) { + el.removeTextContent(); + el.removeTextGuideLine(); + removeElement(el, { + style: { + opacity: 0 + } + }, animatableModel, dataIndex, done); + } + + function removeElementWithFadeOut(el, animatableModel, dataIndex) { + function doRemove() { + el.parent && el.parent.remove(el); + } // Hide label and labelLine first + // TODO Also use fade out animation? + + + if (!el.isGroup) { + fadeOutDisplayable(el, animatableModel, dataIndex, doRemove); + } else { + el.traverse(function (disp) { + if (!disp.isGroup) { + // Can invoke doRemove multiple times. + fadeOutDisplayable(disp, animatableModel, dataIndex, doRemove); + } + }); + } + } + /** + * Save old style for style transition in universalTransition module. + * It's used when element will be reused in each render. + * For chart like map, heatmap, which will always create new element. + * We don't need to save this because universalTransition can get old style from the old element + */ + + function saveOldStyle(el) { + transitionStore(el).oldStyle = el.style; + } + function getOldStyle(el) { + return transitionStore(el).oldStyle; + } + + var mathMax$4 = Math.max; + var mathMin$4 = Math.min; + var _customShapeMap = {}; + /** + * Extend shape with parameters + */ + + function extendShape(opts) { + return Path.extend(opts); + } + var extendPathFromString = extendFromString; + /** + * Extend path + */ + + function extendPath(pathData, opts) { + return extendPathFromString(pathData, opts); + } + /** + * Register a user defined shape. + * The shape class can be fetched by `getShapeClass` + * This method will overwrite the registered shapes, including + * the registered built-in shapes, if using the same `name`. + * The shape can be used in `custom series` and + * `graphic component` by declaring `{type: name}`. + * + * @param name + * @param ShapeClass Can be generated by `extendShape`. + */ + + function registerShape(name, ShapeClass) { + _customShapeMap[name] = ShapeClass; + } + /** + * Find shape class registered by `registerShape`. Usually used in + * fetching user defined shape. + * + * [Caution]: + * (1) This method **MUST NOT be used inside echarts !!!**, unless it is prepared + * to use user registered shapes. + * Because the built-in shape (see `getBuiltInShape`) will be registered by + * `registerShape` by default. That enables users to get both built-in + * shapes as well as the shapes belonging to themsleves. But users can overwrite + * the built-in shapes by using names like 'circle', 'rect' via calling + * `registerShape`. So the echarts inner featrues should not fetch shapes from here + * in case that it is overwritten by users, except that some features, like + * `custom series`, `graphic component`, do it deliberately. + * + * (2) In the features like `custom series`, `graphic component`, the user input + * `{tpye: 'xxx'}` does not only specify shapes but also specify other graphic + * elements like `'group'`, `'text'`, `'image'` or event `'path'`. Those names + * are reserved names, that is, if some user register a shape named `'image'`, + * the shape will not be used. If we intending to add some more reserved names + * in feature, that might bring break changes (disable some existing user shape + * names). But that case probably rearly happen. So we dont make more mechanism + * to resolve this issue here. + * + * @param name + * @return The shape class. If not found, return nothing. + */ + + function getShapeClass(name) { + if (_customShapeMap.hasOwnProperty(name)) { + return _customShapeMap[name]; + } + } + /** + * Create a path element from path data string + * @param pathData + * @param opts + * @param rect + * @param layout 'center' or 'cover' default to be cover + */ + + function makePath(pathData, opts, rect, layout) { + var path = createFromString(pathData, opts); + + if (rect) { + if (layout === 'center') { + rect = centerGraphic(rect, path.getBoundingRect()); + } + + resizePath(path, rect); + } + + return path; + } + /** + * Create a image element from image url + * @param imageUrl image url + * @param opts options + * @param rect constrain rect + * @param layout 'center' or 'cover'. Default to be 'cover' + */ + + function makeImage(imageUrl, rect, layout) { + var zrImg = new ZRImage({ + style: { + image: imageUrl, + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + onload: function (img) { + if (layout === 'center') { + var boundingRect = { + width: img.width, + height: img.height + }; + zrImg.setStyle(centerGraphic(rect, boundingRect)); + } + } + }); + return zrImg; + } + /** + * Get position of centered element in bounding box. + * + * @param rect element local bounding box + * @param boundingRect constraint bounding box + * @return element position containing x, y, width, and height + */ + + function centerGraphic(rect, boundingRect) { + // Set rect to center, keep width / height ratio. + var aspect = boundingRect.width / boundingRect.height; + var width = rect.height * aspect; + var height; + + if (width <= rect.width) { + height = rect.height; + } else { + width = rect.width; + height = width / aspect; + } + + var cx = rect.x + rect.width / 2; + var cy = rect.y + rect.height / 2; + return { + x: cx - width / 2, + y: cy - height / 2, + width: width, + height: height + }; + } + + var mergePath$1 = mergePath; + /** + * Resize a path to fit the rect + * @param path + * @param rect + */ + + function resizePath(path, rect) { + if (!path.applyTransform) { + return; + } + + var pathRect = path.getBoundingRect(); + var m = pathRect.calculateTransform(rect); + path.applyTransform(m); + } + /** + * Sub pixel optimize line for canvas + */ + + function subPixelOptimizeLine$1(param) { + subPixelOptimizeLine(param.shape, param.shape, param.style); + return param; + } + /** + * Sub pixel optimize rect for canvas + */ + + function subPixelOptimizeRect$1(param) { + subPixelOptimizeRect(param.shape, param.shape, param.style); + return param; + } + /** + * Sub pixel optimize for canvas + * + * @param position Coordinate, such as x, y + * @param lineWidth Should be nonnegative integer. + * @param positiveOrNegative Default false (negative). + * @return Optimized position. + */ + + var subPixelOptimize$1 = subPixelOptimize; + /** + * Get transform matrix of target (param target), + * in coordinate of its ancestor (param ancestor) + * + * @param target + * @param [ancestor] + */ + + function getTransform(target, ancestor) { + var mat = identity([]); + + while (target && target !== ancestor) { + mul$1(mat, target.getLocalTransform(), mat); + target = target.parent; + } + + return mat; + } + /** + * Apply transform to an vertex. + * @param target [x, y] + * @param transform Can be: + * + Transform matrix: like [1, 0, 0, 1, 0, 0] + * + {position, rotation, scale}, the same as `zrender/Transformable`. + * @param invert Whether use invert matrix. + * @return [x, y] + */ + + function applyTransform$1(target, transform, invert$1) { + if (transform && !isArrayLike(transform)) { + transform = Transformable.getLocalTransform(transform); + } + + if (invert$1) { + transform = invert([], transform); + } + + return applyTransform([], target, transform); + } + /** + * @param direction 'left' 'right' 'top' 'bottom' + * @param transform Transform matrix: like [1, 0, 0, 1, 0, 0] + * @param invert Whether use invert matrix. + * @return Transformed direction. 'left' 'right' 'top' 'bottom' + */ + + function transformDirection(direction, transform, invert) { + // Pick a base, ensure that transform result will not be (0, 0). + var hBase = transform[4] === 0 || transform[5] === 0 || transform[0] === 0 ? 1 : Math.abs(2 * transform[4] / transform[0]); + var vBase = transform[4] === 0 || transform[5] === 0 || transform[2] === 0 ? 1 : Math.abs(2 * transform[4] / transform[2]); + var vertex = [direction === 'left' ? -hBase : direction === 'right' ? hBase : 0, direction === 'top' ? -vBase : direction === 'bottom' ? vBase : 0]; + vertex = applyTransform$1(vertex, transform, invert); + return Math.abs(vertex[0]) > Math.abs(vertex[1]) ? vertex[0] > 0 ? 'right' : 'left' : vertex[1] > 0 ? 'bottom' : 'top'; + } + + function isNotGroup(el) { + return !el.isGroup; + } + + function isPath(el) { + return el.shape != null; + } + /** + * Apply group transition animation from g1 to g2. + * If no animatableModel, no animation. + */ + + + function groupTransition(g1, g2, animatableModel) { + if (!g1 || !g2) { + return; + } + + function getElMap(g) { + var elMap = {}; + g.traverse(function (el) { + if (isNotGroup(el) && el.anid) { + elMap[el.anid] = el; + } + }); + return elMap; + } + + function getAnimatableProps(el) { + var obj = { + x: el.x, + y: el.y, + rotation: el.rotation + }; + + if (isPath(el)) { + obj.shape = extend({}, el.shape); + } + + return obj; + } + + var elMap1 = getElMap(g1); + g2.traverse(function (el) { + if (isNotGroup(el) && el.anid) { + var oldEl = elMap1[el.anid]; + + if (oldEl) { + var newProp = getAnimatableProps(el); + el.attr(getAnimatableProps(oldEl)); + updateProps(el, newProp, animatableModel, getECData(el).dataIndex); + } + } + }); + } + function clipPointsByRect(points, rect) { + // FIXME: this way migth be incorrect when grpahic clipped by a corner. + // and when element have border. + return map(points, function (point) { + var x = point[0]; + x = mathMax$4(x, rect.x); + x = mathMin$4(x, rect.x + rect.width); + var y = point[1]; + y = mathMax$4(y, rect.y); + y = mathMin$4(y, rect.y + rect.height); + return [x, y]; + }); + } + /** + * Return a new clipped rect. If rect size are negative, return undefined. + */ + + function clipRectByRect(targetRect, rect) { + var x = mathMax$4(targetRect.x, rect.x); + var x2 = mathMin$4(targetRect.x + targetRect.width, rect.x + rect.width); + var y = mathMax$4(targetRect.y, rect.y); + var y2 = mathMin$4(targetRect.y + targetRect.height, rect.y + rect.height); // If the total rect is cliped, nothing, including the border, + // should be painted. So return undefined. + + if (x2 >= x && y2 >= y) { + return { + x: x, + y: y, + width: x2 - x, + height: y2 - y + }; + } + } + function createIcon(iconStr, // Support 'image://' or 'path://' or direct svg path. + opt, rect) { + var innerOpts = extend({ + rectHover: true + }, opt); + var style = innerOpts.style = { + strokeNoScale: true + }; + rect = rect || { + x: -1, + y: -1, + width: 2, + height: 2 + }; + + if (iconStr) { + return iconStr.indexOf('image://') === 0 ? (style.image = iconStr.slice(8), defaults(style, rect), new ZRImage(innerOpts)) : makePath(iconStr.replace('path://', ''), innerOpts, rect, 'center'); + } + } + /** + * Return `true` if the given line (line `a`) and the given polygon + * are intersect. + * Note that we do not count colinear as intersect here because no + * requirement for that. We could do that if required in future. + */ + + function linePolygonIntersect(a1x, a1y, a2x, a2y, points) { + for (var i = 0, p2 = points[points.length - 1]; i < points.length; i++) { + var p = points[i]; + + if (lineLineIntersect(a1x, a1y, a2x, a2y, p[0], p[1], p2[0], p2[1])) { + return true; + } + + p2 = p; + } + } + /** + * Return `true` if the given two lines (line `a` and line `b`) + * are intersect. + * Note that we do not count colinear as intersect here because no + * requirement for that. We could do that if required in future. + */ + + function lineLineIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) { + // let `vec_m` to be `vec_a2 - vec_a1` and `vec_n` to be `vec_b2 - vec_b1`. + var mx = a2x - a1x; + var my = a2y - a1y; + var nx = b2x - b1x; + var ny = b2y - b1y; // `vec_m` and `vec_n` are parallel iff + // exising `k` such that `vec_m = k · vec_n`, equivalent to `vec_m X vec_n = 0`. + + var nmCrossProduct = crossProduct2d(nx, ny, mx, my); + + if (nearZero(nmCrossProduct)) { + return false; + } // `vec_m` and `vec_n` are intersect iff + // existing `p` and `q` in [0, 1] such that `vec_a1 + p * vec_m = vec_b1 + q * vec_n`, + // such that `q = ((vec_a1 - vec_b1) X vec_m) / (vec_n X vec_m)` + // and `p = ((vec_a1 - vec_b1) X vec_n) / (vec_n X vec_m)`. + + + var b1a1x = a1x - b1x; + var b1a1y = a1y - b1y; + var q = crossProduct2d(b1a1x, b1a1y, mx, my) / nmCrossProduct; + + if (q < 0 || q > 1) { + return false; + } + + var p = crossProduct2d(b1a1x, b1a1y, nx, ny) / nmCrossProduct; + + if (p < 0 || p > 1) { + return false; + } + + return true; + } + /** + * Cross product of 2-dimension vector. + */ + + function crossProduct2d(x1, y1, x2, y2) { + return x1 * y2 - x2 * y1; + } + + function nearZero(val) { + return val <= 1e-6 && val >= -1e-6; + } + + function setTooltipConfig(opt) { + var itemTooltipOption = opt.itemTooltipOption; + var componentModel = opt.componentModel; + var itemName = opt.itemName; + var itemTooltipOptionObj = isString(itemTooltipOption) ? { + formatter: itemTooltipOption + } : itemTooltipOption; + var mainType = componentModel.mainType; + var componentIndex = componentModel.componentIndex; + var formatterParams = { + componentType: mainType, + name: itemName, + $vars: ['name'] + }; + formatterParams[mainType + 'Index'] = componentIndex; + var formatterParamsExtra = opt.formatterParamsExtra; + + if (formatterParamsExtra) { + each(keys(formatterParamsExtra), function (key) { + if (!hasOwn(formatterParams, key)) { + formatterParams[key] = formatterParamsExtra[key]; + formatterParams.$vars.push(key); + } + }); + } + + var ecData = getECData(opt.el); + ecData.componentMainType = mainType; + ecData.componentIndex = componentIndex; + ecData.tooltipConfig = { + name: itemName, + option: defaults({ + content: itemName, + formatterParams: formatterParams + }, itemTooltipOptionObj) + }; + } + + function traverseElement(el, cb) { + var stopped; // TODO + // Polyfill for fixing zrender group traverse don't visit it's root issue. + + if (el.isGroup) { + stopped = cb(el); + } + + if (!stopped) { + el.traverse(cb); + } + } + + function traverseElements(els, cb) { + if (els) { + if (isArray(els)) { + for (var i = 0; i < els.length; i++) { + traverseElement(els[i], cb); + } + } else { + traverseElement(els, cb); + } + } + } // Register built-in shapes. These shapes might be overwirtten + // by users, although we do not recommend that. + + registerShape('circle', Circle); + registerShape('ellipse', Ellipse); + registerShape('sector', Sector); + registerShape('ring', Ring); + registerShape('polygon', Polygon); + registerShape('polyline', Polyline); + registerShape('rect', Rect); + registerShape('line', Line); + registerShape('bezierCurve', BezierCurve); + registerShape('arc', Arc); + + var graphic = /*#__PURE__*/Object.freeze({ + __proto__: null, + updateProps: updateProps, + initProps: initProps, + removeElement: removeElement, + removeElementWithFadeOut: removeElementWithFadeOut, + isElementRemoved: isElementRemoved, + extendShape: extendShape, + extendPath: extendPath, + registerShape: registerShape, + getShapeClass: getShapeClass, + makePath: makePath, + makeImage: makeImage, + mergePath: mergePath$1, + resizePath: resizePath, + subPixelOptimizeLine: subPixelOptimizeLine$1, + subPixelOptimizeRect: subPixelOptimizeRect$1, + subPixelOptimize: subPixelOptimize$1, + getTransform: getTransform, + applyTransform: applyTransform$1, + transformDirection: transformDirection, + groupTransition: groupTransition, + clipPointsByRect: clipPointsByRect, + clipRectByRect: clipRectByRect, + createIcon: createIcon, + linePolygonIntersect: linePolygonIntersect, + lineLineIntersect: lineLineIntersect, + setTooltipConfig: setTooltipConfig, + traverseElements: traverseElements, + Group: Group, + Image: ZRImage, + Text: ZRText, + Circle: Circle, + Ellipse: Ellipse, + Sector: Sector, + Ring: Ring, + Polygon: Polygon, + Polyline: Polyline, + Rect: Rect, + Line: Line, + BezierCurve: BezierCurve, + Arc: Arc, + IncrementalDisplayable: IncrementalDisplayable, + CompoundPath: CompoundPath, + LinearGradient: LinearGradient, + RadialGradient: RadialGradient, + BoundingRect: BoundingRect, + OrientedBoundingRect: OrientedBoundingRect, + Point: Point, + Path: Path + }); + + var EMPTY_OBJ = {}; + function setLabelText(label, labelTexts) { + for (var i = 0; i < SPECIAL_STATES.length; i++) { + var stateName = SPECIAL_STATES[i]; + var text = labelTexts[stateName]; + var state = label.ensureState(stateName); + state.style = state.style || {}; + state.style.text = text; + } + + var oldStates = label.currentStates.slice(); + label.clearStates(true); + label.setStyle({ + text: labelTexts.normal + }); + label.useStates(oldStates, true); + } + + function getLabelText(opt, stateModels, interpolatedValue) { + var labelFetcher = opt.labelFetcher; + var labelDataIndex = opt.labelDataIndex; + var labelDimIndex = opt.labelDimIndex; + var normalModel = stateModels.normal; + var baseText; + + if (labelFetcher) { + baseText = labelFetcher.getFormattedLabel(labelDataIndex, 'normal', null, labelDimIndex, normalModel && normalModel.get('formatter'), interpolatedValue != null ? { + interpolatedValue: interpolatedValue + } : null); + } + + if (baseText == null) { + baseText = isFunction(opt.defaultText) ? opt.defaultText(labelDataIndex, opt, interpolatedValue) : opt.defaultText; + } + + var statesText = { + normal: baseText + }; + + for (var i = 0; i < SPECIAL_STATES.length; i++) { + var stateName = SPECIAL_STATES[i]; + var stateModel = stateModels[stateName]; + statesText[stateName] = retrieve2(labelFetcher ? labelFetcher.getFormattedLabel(labelDataIndex, stateName, null, labelDimIndex, stateModel && stateModel.get('formatter')) : null, baseText); + } + + return statesText; + } + + function setLabelStyle(targetEl, labelStatesModels, opt, stateSpecified // TODO specified position? + ) { + opt = opt || EMPTY_OBJ; + var isSetOnText = targetEl instanceof ZRText; + var needsCreateText = false; + + for (var i = 0; i < DISPLAY_STATES.length; i++) { + var stateModel = labelStatesModels[DISPLAY_STATES[i]]; + + if (stateModel && stateModel.getShallow('show')) { + needsCreateText = true; + break; + } + } + + var textContent = isSetOnText ? targetEl : targetEl.getTextContent(); + + if (needsCreateText) { + if (!isSetOnText) { + // Reuse the previous + if (!textContent) { + textContent = new ZRText(); + targetEl.setTextContent(textContent); + } // Use same state proxy + + + if (targetEl.stateProxy) { + textContent.stateProxy = targetEl.stateProxy; + } + } + + var labelStatesTexts = getLabelText(opt, labelStatesModels); + var normalModel = labelStatesModels.normal; + var showNormal = !!normalModel.getShallow('show'); + var normalStyle = createTextStyle(normalModel, stateSpecified && stateSpecified.normal, opt, false, !isSetOnText); + normalStyle.text = labelStatesTexts.normal; + + if (!isSetOnText) { + // Always create new + targetEl.setTextConfig(createTextConfig(normalModel, opt, false)); + } + + for (var i = 0; i < SPECIAL_STATES.length; i++) { + var stateName = SPECIAL_STATES[i]; + var stateModel = labelStatesModels[stateName]; + + if (stateModel) { + var stateObj = textContent.ensureState(stateName); + var stateShow = !!retrieve2(stateModel.getShallow('show'), showNormal); + + if (stateShow !== showNormal) { + stateObj.ignore = !stateShow; + } + + stateObj.style = createTextStyle(stateModel, stateSpecified && stateSpecified[stateName], opt, true, !isSetOnText); + stateObj.style.text = labelStatesTexts[stateName]; + + if (!isSetOnText) { + var targetElEmphasisState = targetEl.ensureState(stateName); + targetElEmphasisState.textConfig = createTextConfig(stateModel, opt, true); + } + } + } // PENDING: if there is many requirements that emphasis position + // need to be different from normal position, we might consider + // auto slient is those cases. + + + textContent.silent = !!normalModel.getShallow('silent'); // Keep x and y + + if (textContent.style.x != null) { + normalStyle.x = textContent.style.x; + } + + if (textContent.style.y != null) { + normalStyle.y = textContent.style.y; + } + + textContent.ignore = !showNormal; // Always create new style. + + textContent.useStyle(normalStyle); + textContent.dirty(); + + if (opt.enableTextSetter) { + labelInner(textContent).setLabelText = function (interpolatedValue) { + var labelStatesTexts = getLabelText(opt, labelStatesModels, interpolatedValue); + setLabelText(textContent, labelStatesTexts); + }; + } + } else if (textContent) { + // Not display rich text. + textContent.ignore = true; + } + + targetEl.dirty(); + } + function getLabelStatesModels(itemModel, labelName) { + labelName = labelName || 'label'; + var statesModels = { + normal: itemModel.getModel(labelName) + }; + + for (var i = 0; i < SPECIAL_STATES.length; i++) { + var stateName = SPECIAL_STATES[i]; + statesModels[stateName] = itemModel.getModel([stateName, labelName]); + } + + return statesModels; + } + /** + * Set basic textStyle properties. + */ + + function createTextStyle(textStyleModel, specifiedTextStyle, // Fixed style in the code. Can't be set by model. + opt, isNotNormal, isAttached // If text is attached on an element. If so, auto color will handling in zrender. + ) { + var textStyle = {}; + setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal, isAttached); + specifiedTextStyle && extend(textStyle, specifiedTextStyle); // textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false); + + return textStyle; + } + function createTextConfig(textStyleModel, opt, isNotNormal) { + opt = opt || {}; + var textConfig = {}; + var labelPosition; + var labelRotate = textStyleModel.getShallow('rotate'); + var labelDistance = retrieve2(textStyleModel.getShallow('distance'), isNotNormal ? null : 5); + var labelOffset = textStyleModel.getShallow('offset'); + labelPosition = textStyleModel.getShallow('position') || (isNotNormal ? null : 'inside'); // 'outside' is not a valid zr textPostion value, but used + // in bar series, and magric type should be considered. + + labelPosition === 'outside' && (labelPosition = opt.defaultOutsidePosition || 'top'); + + if (labelPosition != null) { + textConfig.position = labelPosition; + } + + if (labelOffset != null) { + textConfig.offset = labelOffset; + } + + if (labelRotate != null) { + labelRotate *= Math.PI / 180; + textConfig.rotation = labelRotate; + } + + if (labelDistance != null) { + textConfig.distance = labelDistance; + } // fill and auto is determined by the color of path fill if it's not specified by developers. + + + textConfig.outsideFill = textStyleModel.get('color') === 'inherit' ? opt.inheritColor || null : 'auto'; + return textConfig; + } + /** + * The uniform entry of set text style, that is, retrieve style definitions + * from `model` and set to `textStyle` object. + * + * Never in merge mode, but in overwrite mode, that is, all of the text style + * properties will be set. (Consider the states of normal and emphasis and + * default value can be adopted, merge would make the logic too complicated + * to manage.) + */ + + function setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal, isAttached) { + // Consider there will be abnormal when merge hover style to normal style if given default value. + opt = opt || EMPTY_OBJ; + var ecModel = textStyleModel.ecModel; + var globalTextStyle = ecModel && ecModel.option.textStyle; // Consider case: + // { + // data: [{ + // value: 12, + // label: { + // rich: { + // // no 'a' here but using parent 'a'. + // } + // } + // }], + // rich: { + // a: { ... } + // } + // } + + var richItemNames = getRichItemNames(textStyleModel); + var richResult; + + if (richItemNames) { + richResult = {}; + + for (var name_1 in richItemNames) { + if (richItemNames.hasOwnProperty(name_1)) { + // Cascade is supported in rich. + var richTextStyle = textStyleModel.getModel(['rich', name_1]); // In rich, never `disableBox`. + // FIXME: consider `label: {formatter: '{a|xx}', color: 'blue', rich: {a: {}}}`, + // the default color `'blue'` will not be adopted if no color declared in `rich`. + // That might confuses users. So probably we should put `textStyleModel` as the + // root ancestor of the `richTextStyle`. But that would be a break change. + + setTokenTextStyle(richResult[name_1] = {}, richTextStyle, globalTextStyle, opt, isNotNormal, isAttached, false, true); + } + } + } + + if (richResult) { + textStyle.rich = richResult; + } + + var overflow = textStyleModel.get('overflow'); + + if (overflow) { + textStyle.overflow = overflow; + } + + var margin = textStyleModel.get('minMargin'); + + if (margin != null) { + textStyle.margin = margin; + } + + setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isNotNormal, isAttached, true, false); + } // Consider case: + // { + // data: [{ + // value: 12, + // label: { + // rich: { + // // no 'a' here but using parent 'a'. + // } + // } + // }], + // rich: { + // a: { ... } + // } + // } + // TODO TextStyleModel + + + function getRichItemNames(textStyleModel) { + // Use object to remove duplicated names. + var richItemNameMap; + + while (textStyleModel && textStyleModel !== textStyleModel.ecModel) { + var rich = (textStyleModel.option || EMPTY_OBJ).rich; + + if (rich) { + richItemNameMap = richItemNameMap || {}; + var richKeys = keys(rich); + + for (var i = 0; i < richKeys.length; i++) { + var richKey = richKeys[i]; + richItemNameMap[richKey] = 1; + } + } + + textStyleModel = textStyleModel.parentModel; + } + + return richItemNameMap; + } + + var TEXT_PROPS_WITH_GLOBAL = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY']; + var TEXT_PROPS_SELF = ['align', 'lineHeight', 'width', 'height', 'tag', 'verticalAlign']; + var TEXT_PROPS_BOX = ['padding', 'borderWidth', 'borderRadius', 'borderDashOffset', 'backgroundColor', 'borderColor', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY']; + + function setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isNotNormal, isAttached, isBlock, inRich) { + // In merge mode, default value should not be given. + globalTextStyle = !isNotNormal && globalTextStyle || EMPTY_OBJ; + var inheritColor = opt && opt.inheritColor; + var fillColor = textStyleModel.getShallow('color'); + var strokeColor = textStyleModel.getShallow('textBorderColor'); + var opacity = retrieve2(textStyleModel.getShallow('opacity'), globalTextStyle.opacity); + + if (fillColor === 'inherit' || fillColor === 'auto') { + if ("development" !== 'production') { + if (fillColor === 'auto') { + deprecateReplaceLog('color: \'auto\'', 'color: \'inherit\''); + } + } + + if (inheritColor) { + fillColor = inheritColor; + } else { + fillColor = null; + } + } + + if (strokeColor === 'inherit' || strokeColor === 'auto') { + if ("development" !== 'production') { + if (strokeColor === 'auto') { + deprecateReplaceLog('color: \'auto\'', 'color: \'inherit\''); + } + } + + if (inheritColor) { + strokeColor = inheritColor; + } else { + strokeColor = null; + } + } + + if (!isAttached) { + // Only use default global textStyle.color if text is individual. + // Otherwise it will use the strategy of attached text color because text may be on a path. + fillColor = fillColor || globalTextStyle.color; + strokeColor = strokeColor || globalTextStyle.textBorderColor; + } + + if (fillColor != null) { + textStyle.fill = fillColor; + } + + if (strokeColor != null) { + textStyle.stroke = strokeColor; + } + + var textBorderWidth = retrieve2(textStyleModel.getShallow('textBorderWidth'), globalTextStyle.textBorderWidth); + + if (textBorderWidth != null) { + textStyle.lineWidth = textBorderWidth; + } + + var textBorderType = retrieve2(textStyleModel.getShallow('textBorderType'), globalTextStyle.textBorderType); + + if (textBorderType != null) { + textStyle.lineDash = textBorderType; + } + + var textBorderDashOffset = retrieve2(textStyleModel.getShallow('textBorderDashOffset'), globalTextStyle.textBorderDashOffset); + + if (textBorderDashOffset != null) { + textStyle.lineDashOffset = textBorderDashOffset; + } + + if (!isNotNormal && opacity == null && !inRich) { + opacity = opt && opt.defaultOpacity; + } + + if (opacity != null) { + textStyle.opacity = opacity; + } // TODO + + + if (!isNotNormal && !isAttached) { + // Set default finally. + if (textStyle.fill == null && opt.inheritColor) { + textStyle.fill = opt.inheritColor; + } + } // Do not use `getFont` here, because merge should be supported, where + // part of these properties may be changed in emphasis style, and the + // others should remain their original value got from normal style. + + + for (var i = 0; i < TEXT_PROPS_WITH_GLOBAL.length; i++) { + var key = TEXT_PROPS_WITH_GLOBAL[i]; + var val = retrieve2(textStyleModel.getShallow(key), globalTextStyle[key]); + + if (val != null) { + textStyle[key] = val; + } + } + + for (var i = 0; i < TEXT_PROPS_SELF.length; i++) { + var key = TEXT_PROPS_SELF[i]; + var val = textStyleModel.getShallow(key); + + if (val != null) { + textStyle[key] = val; + } + } + + if (textStyle.verticalAlign == null) { + var baseline = textStyleModel.getShallow('baseline'); + + if (baseline != null) { + textStyle.verticalAlign = baseline; + } + } + + if (!isBlock || !opt.disableBox) { + for (var i = 0; i < TEXT_PROPS_BOX.length; i++) { + var key = TEXT_PROPS_BOX[i]; + var val = textStyleModel.getShallow(key); + + if (val != null) { + textStyle[key] = val; + } + } + + var borderType = textStyleModel.getShallow('borderType'); + + if (borderType != null) { + textStyle.borderDash = borderType; + } + + if ((textStyle.backgroundColor === 'auto' || textStyle.backgroundColor === 'inherit') && inheritColor) { + if ("development" !== 'production') { + if (textStyle.backgroundColor === 'auto') { + deprecateReplaceLog('backgroundColor: \'auto\'', 'backgroundColor: \'inherit\''); + } + } + + textStyle.backgroundColor = inheritColor; + } + + if ((textStyle.borderColor === 'auto' || textStyle.borderColor === 'inherit') && inheritColor) { + if ("development" !== 'production') { + if (textStyle.borderColor === 'auto') { + deprecateReplaceLog('borderColor: \'auto\'', 'borderColor: \'inherit\''); + } + } + + textStyle.borderColor = inheritColor; + } + } + } + + function getFont(opt, ecModel) { + var gTextStyleModel = ecModel && ecModel.getModel('textStyle'); + return trim([// FIXME in node-canvas fontWeight is before fontStyle + opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '', opt.fontWeight || gTextStyleModel && gTextStyleModel.getShallow('fontWeight') || '', (opt.fontSize || gTextStyleModel && gTextStyleModel.getShallow('fontSize') || 12) + 'px', opt.fontFamily || gTextStyleModel && gTextStyleModel.getShallow('fontFamily') || 'sans-serif'].join(' ')); + } + var labelInner = makeInner(); + function setLabelValueAnimation(label, labelStatesModels, value, getDefaultText) { + if (!label) { + return; + } + + var obj = labelInner(label); + obj.prevValue = obj.value; + obj.value = value; + var normalLabelModel = labelStatesModels.normal; + obj.valueAnimation = normalLabelModel.get('valueAnimation'); + + if (obj.valueAnimation) { + obj.precision = normalLabelModel.get('precision'); + obj.defaultInterpolatedText = getDefaultText; + obj.statesModels = labelStatesModels; + } + } + function animateLabelValue(textEl, dataIndex, data, animatableModel, labelFetcher) { + var labelInnerStore = labelInner(textEl); + + if (!labelInnerStore.valueAnimation || labelInnerStore.prevValue === labelInnerStore.value) { + // Value not changed, no new label animation + return; + } + + var defaultInterpolatedText = labelInnerStore.defaultInterpolatedText; // Consider the case that being animating, do not use the `obj.value`, + // Otherwise it will jump to the `obj.value` when this new animation started. + + var currValue = retrieve2(labelInnerStore.interpolatedValue, labelInnerStore.prevValue); + var targetValue = labelInnerStore.value; + + function during(percent) { + var interpolated = interpolateRawValues(data, labelInnerStore.precision, currValue, targetValue, percent); + labelInnerStore.interpolatedValue = percent === 1 ? null : interpolated; + var labelText = getLabelText({ + labelDataIndex: dataIndex, + labelFetcher: labelFetcher, + defaultText: defaultInterpolatedText ? defaultInterpolatedText(interpolated) : interpolated + '' + }, labelInnerStore.statesModels, interpolated); + setLabelText(textEl, labelText); + } + + textEl.percent = 0; + (labelInnerStore.prevValue == null ? initProps : updateProps)(textEl, { + // percent is used to prevent animation from being aborted #15916 + percent: 1 + }, animatableModel, dataIndex, null, during); + } + + var PATH_COLOR = ['textStyle', 'color']; + var textStyleParams = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'padding', 'lineHeight', 'rich', 'width', 'height', 'overflow']; // TODO Performance improvement? + + var tmpText = new ZRText(); + + var TextStyleMixin = + /** @class */ + function () { + function TextStyleMixin() {} + /** + * Get color property or get color from option.textStyle.color + */ + // TODO Callback + + + TextStyleMixin.prototype.getTextColor = function (isEmphasis) { + var ecModel = this.ecModel; + return this.getShallow('color') || (!isEmphasis && ecModel ? ecModel.get(PATH_COLOR) : null); + }; + /** + * Create font string from fontStyle, fontWeight, fontSize, fontFamily + * @return {string} + */ + + + TextStyleMixin.prototype.getFont = function () { + return getFont({ + fontStyle: this.getShallow('fontStyle'), + fontWeight: this.getShallow('fontWeight'), + fontSize: this.getShallow('fontSize'), + fontFamily: this.getShallow('fontFamily') + }, this.ecModel); + }; + + TextStyleMixin.prototype.getTextRect = function (text) { + var style = { + text: text, + verticalAlign: this.getShallow('verticalAlign') || this.getShallow('baseline') + }; + + for (var i = 0; i < textStyleParams.length; i++) { + style[textStyleParams[i]] = this.getShallow(textStyleParams[i]); + } + + tmpText.useStyle(style); + tmpText.update(); + return tmpText.getBoundingRect(); + }; + + return TextStyleMixin; + }(); + + var LINE_STYLE_KEY_MAP = [['lineWidth', 'width'], ['stroke', 'color'], ['opacity'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor'], ['lineDash', 'type'], ['lineDashOffset', 'dashOffset'], ['lineCap', 'cap'], ['lineJoin', 'join'], ['miterLimit'] // Option decal is in `DecalObject` but style.decal is in `PatternObject`. + // So do not transfer decal directly. + ]; + var getLineStyle = makeStyleMapper(LINE_STYLE_KEY_MAP); + + var LineStyleMixin = + /** @class */ + function () { + function LineStyleMixin() {} + + LineStyleMixin.prototype.getLineStyle = function (excludes) { + return getLineStyle(this, excludes); + }; + + return LineStyleMixin; + }(); + + var ITEM_STYLE_KEY_MAP = [['fill', 'color'], ['stroke', 'borderColor'], ['lineWidth', 'borderWidth'], ['opacity'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor'], ['lineDash', 'borderType'], ['lineDashOffset', 'borderDashOffset'], ['lineCap', 'borderCap'], ['lineJoin', 'borderJoin'], ['miterLimit', 'borderMiterLimit'] // Option decal is in `DecalObject` but style.decal is in `PatternObject`. + // So do not transfer decal directly. + ]; + var getItemStyle = makeStyleMapper(ITEM_STYLE_KEY_MAP); + + var ItemStyleMixin = + /** @class */ + function () { + function ItemStyleMixin() {} + + ItemStyleMixin.prototype.getItemStyle = function (excludes, includes) { + return getItemStyle(this, excludes, includes); + }; + + return ItemStyleMixin; + }(); + + var Model = + /** @class */ + function () { + function Model(option, parentModel, ecModel) { + this.parentModel = parentModel; + this.ecModel = ecModel; + this.option = option; // Simple optimization + // if (this.init) { + // if (arguments.length <= 4) { + // this.init(option, parentModel, ecModel, extraOpt); + // } + // else { + // this.init.apply(this, arguments); + // } + // } + } + + Model.prototype.init = function (option, parentModel, ecModel) { + var rest = []; + + for (var _i = 3; _i < arguments.length; _i++) { + rest[_i - 3] = arguments[_i]; + } + }; + /** + * Merge the input option to me. + */ + + + Model.prototype.mergeOption = function (option, ecModel) { + merge(this.option, option, true); + }; // `path` can be 'xxx.yyy.zzz', so the return value type have to be `ModelOption` + // TODO: TYPE strict key check? + // get(path: string | string[], ignoreParent?: boolean): ModelOption; + + + Model.prototype.get = function (path, ignoreParent) { + if (path == null) { + return this.option; + } + + return this._doGet(this.parsePath(path), !ignoreParent && this.parentModel); + }; + + Model.prototype.getShallow = function (key, ignoreParent) { + var option = this.option; + var val = option == null ? option : option[key]; + + if (val == null && !ignoreParent) { + var parentModel = this.parentModel; + + if (parentModel) { + // FIXME:TS do not know how to make it works + val = parentModel.getShallow(key); + } + } + + return val; + }; // `path` can be 'xxx.yyy.zzz', so the return value type have to be `Model` + // getModel(path: string | string[], parentModel?: Model): Model; + // TODO 'xxx.yyy.zzz' is deprecated + + + Model.prototype.getModel = function (path, parentModel) { + var hasPath = path != null; + var pathFinal = hasPath ? this.parsePath(path) : null; + var obj = hasPath ? this._doGet(pathFinal) : this.option; + parentModel = parentModel || this.parentModel && this.parentModel.getModel(this.resolveParentPath(pathFinal)); + return new Model(obj, parentModel, this.ecModel); + }; + /** + * If model has option + */ + + + Model.prototype.isEmpty = function () { + return this.option == null; + }; + + Model.prototype.restoreData = function () {}; // Pending + + + Model.prototype.clone = function () { + var Ctor = this.constructor; + return new Ctor(clone(this.option)); + }; // setReadOnly(properties): void { + // clazzUtil.setReadOnly(this, properties); + // } + // If path is null/undefined, return null/undefined. + + + Model.prototype.parsePath = function (path) { + if (typeof path === 'string') { + return path.split('.'); + } + + return path; + }; // Resolve path for parent. Perhaps useful when parent use a different property. + // Default to be a identity resolver. + // Can be modified to a different resolver. + + + Model.prototype.resolveParentPath = function (path) { + return path; + }; // FIXME:TS check whether put this method here + + + Model.prototype.isAnimationEnabled = function () { + if (!env.node && this.option) { + if (this.option.animation != null) { + return !!this.option.animation; + } else if (this.parentModel) { + return this.parentModel.isAnimationEnabled(); + } + } + }; + + Model.prototype._doGet = function (pathArr, parentModel) { + var obj = this.option; + + if (!pathArr) { + return obj; + } + + for (var i = 0; i < pathArr.length; i++) { + // Ignore empty + if (!pathArr[i]) { + continue; + } // obj could be number/string/... (like 0) + + + obj = obj && typeof obj === 'object' ? obj[pathArr[i]] : null; + + if (obj == null) { + break; + } + } + + if (obj == null && parentModel) { + obj = parentModel._doGet(this.resolveParentPath(pathArr), parentModel.parentModel); + } + + return obj; + }; + + return Model; + }(); + + enableClassExtend(Model); + enableClassCheck(Model); + mixin(Model, LineStyleMixin); + mixin(Model, ItemStyleMixin); + mixin(Model, AreaStyleMixin); + mixin(Model, TextStyleMixin); + + var base = Math.round(Math.random() * 10); + /** + * @public + * @param {string} type + * @return {string} + */ + + function getUID(type) { + // Considering the case of crossing js context, + // use Math.random to make id as unique as possible. + return [type || '', base++].join('_'); + } + /** + * Implements `SubTypeDefaulterManager` for `target`. + */ + + function enableSubTypeDefaulter(target) { + var subTypeDefaulters = {}; + + target.registerSubTypeDefaulter = function (componentType, defaulter) { + var componentTypeInfo = parseClassType(componentType); + subTypeDefaulters[componentTypeInfo.main] = defaulter; + }; + + target.determineSubType = function (componentType, option) { + var type = option.type; + + if (!type) { + var componentTypeMain = parseClassType(componentType).main; + + if (target.hasSubTypes(componentType) && subTypeDefaulters[componentTypeMain]) { + type = subTypeDefaulters[componentTypeMain](option); + } + } + + return type; + }; + } + /** + * Implements `TopologicalTravelable` for `entity`. + * + * Topological travel on Activity Network (Activity On Vertices). + * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis']. + * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology. + * If there is circular dependencey, Error will be thrown. + */ + + function enableTopologicalTravel(entity, dependencyGetter) { + /** + * @param targetNameList Target Component type list. + * Can be ['aa', 'bb', 'aa.xx'] + * @param fullNameList By which we can build dependency graph. + * @param callback Params: componentType, dependencies. + * @param context Scope of callback. + */ + entity.topologicalTravel = function (targetNameList, fullNameList, callback, context) { + if (!targetNameList.length) { + return; + } + + var result = makeDepndencyGraph(fullNameList); + var graph = result.graph; + var noEntryList = result.noEntryList; + var targetNameSet = {}; + each(targetNameList, function (name) { + targetNameSet[name] = true; + }); + + while (noEntryList.length) { + var currComponentType = noEntryList.pop(); + var currVertex = graph[currComponentType]; + var isInTargetNameSet = !!targetNameSet[currComponentType]; + + if (isInTargetNameSet) { + callback.call(context, currComponentType, currVertex.originalDeps.slice()); + delete targetNameSet[currComponentType]; + } + + each(currVertex.successor, isInTargetNameSet ? removeEdgeAndAdd : removeEdge); + } + + each(targetNameSet, function () { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = makePrintable('Circular dependency may exists: ', targetNameSet, targetNameList, fullNameList); + } + + throw new Error(errMsg); + }); + + function removeEdge(succComponentType) { + graph[succComponentType].entryCount--; + + if (graph[succComponentType].entryCount === 0) { + noEntryList.push(succComponentType); + } + } // Consider this case: legend depends on series, and we call + // chart.setOption({series: [...]}), where only series is in option. + // If we do not have 'removeEdgeAndAdd', legendModel.mergeOption will + // not be called, but only sereis.mergeOption is called. Thus legend + // have no chance to update its local record about series (like which + // name of series is available in legend). + + + function removeEdgeAndAdd(succComponentType) { + targetNameSet[succComponentType] = true; + removeEdge(succComponentType); + } + }; + + function makeDepndencyGraph(fullNameList) { + var graph = {}; + var noEntryList = []; + each(fullNameList, function (name) { + var thisItem = createDependencyGraphItem(graph, name); + var originalDeps = thisItem.originalDeps = dependencyGetter(name); + var availableDeps = getAvailableDependencies(originalDeps, fullNameList); + thisItem.entryCount = availableDeps.length; + + if (thisItem.entryCount === 0) { + noEntryList.push(name); + } + + each(availableDeps, function (dependentName) { + if (indexOf(thisItem.predecessor, dependentName) < 0) { + thisItem.predecessor.push(dependentName); + } + + var thatItem = createDependencyGraphItem(graph, dependentName); + + if (indexOf(thatItem.successor, dependentName) < 0) { + thatItem.successor.push(name); + } + }); + }); + return { + graph: graph, + noEntryList: noEntryList + }; + } + + function createDependencyGraphItem(graph, name) { + if (!graph[name]) { + graph[name] = { + predecessor: [], + successor: [] + }; + } + + return graph[name]; + } + + function getAvailableDependencies(originalDeps, fullNameList) { + var availableDeps = []; + each(originalDeps, function (dep) { + indexOf(fullNameList, dep) >= 0 && availableDeps.push(dep); + }); + return availableDeps; + } + } + function inheritDefaultOption(superOption, subOption) { + // See also `model/Component.ts#getDefaultOption` + return merge(merge({}, superOption, true), subOption, true); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + /** + * Language: English. + */ + var langEN = { + time: { + month: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + monthAbbr: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + dayOfWeek: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + dayOfWeekAbbr: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] + }, + legend: { + selector: { + all: 'All', + inverse: 'Inv' + } + }, + toolbox: { + brush: { + title: { + rect: 'Box Select', + polygon: 'Lasso Select', + lineX: 'Horizontally Select', + lineY: 'Vertically Select', + keep: 'Keep Selections', + clear: 'Clear Selections' + } + }, + dataView: { + title: 'Data View', + lang: ['Data View', 'Close', 'Refresh'] + }, + dataZoom: { + title: { + zoom: 'Zoom', + back: 'Zoom Reset' + } + }, + magicType: { + title: { + line: 'Switch to Line Chart', + bar: 'Switch to Bar Chart', + stack: 'Stack', + tiled: 'Tile' + } + }, + restore: { + title: 'Restore' + }, + saveAsImage: { + title: 'Save as Image', + lang: ['Right Click to Save Image'] + } + }, + series: { + typeNames: { + pie: 'Pie chart', + bar: 'Bar chart', + line: 'Line chart', + scatter: 'Scatter plot', + effectScatter: 'Ripple scatter plot', + radar: 'Radar chart', + tree: 'Tree', + treemap: 'Treemap', + boxplot: 'Boxplot', + candlestick: 'Candlestick', + k: 'K line chart', + heatmap: 'Heat map', + map: 'Map', + parallel: 'Parallel coordinate map', + lines: 'Line graph', + graph: 'Relationship graph', + sankey: 'Sankey diagram', + funnel: 'Funnel chart', + gauge: 'Gauge', + pictorialBar: 'Pictorial bar', + themeRiver: 'Theme River Map', + sunburst: 'Sunburst' + } + }, + aria: { + general: { + withTitle: 'This is a chart about "{title}"', + withoutTitle: 'This is a chart' + }, + series: { + single: { + prefix: '', + withName: ' with type {seriesType} named {seriesName}.', + withoutName: ' with type {seriesType}.' + }, + multiple: { + prefix: '. It consists of {seriesCount} series count.', + withName: ' The {seriesId} series is a {seriesType} representing {seriesName}.', + withoutName: ' The {seriesId} series is a {seriesType}.', + separator: { + middle: '', + end: '' + } + } + }, + data: { + allData: 'The data is as follows: ', + partialData: 'The first {displayCnt} items are: ', + withName: 'the data for {name} is {value}', + withoutName: '{value}', + separator: { + middle: ', ', + end: '. ' + } + } + } + }; + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var langZH = { + time: { + month: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], + monthAbbr: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], + dayOfWeek: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], + dayOfWeekAbbr: ['日', '一', '二', '三', '四', '五', '六'] + }, + legend: { + selector: { + all: '全选', + inverse: '反选' + } + }, + toolbox: { + brush: { + title: { + rect: '矩形选择', + polygon: '圈选', + lineX: '横向选择', + lineY: '纵向选择', + keep: '保持选择', + clear: '清除选择' + } + }, + dataView: { + title: '数据视图', + lang: ['数据视图', '关闭', '刷新'] + }, + dataZoom: { + title: { + zoom: '区域缩放', + back: '区域缩放还原' + } + }, + magicType: { + title: { + line: '切换为折线图', + bar: '切换为柱状图', + stack: '切换为堆叠', + tiled: '切换为平铺' + } + }, + restore: { + title: '还原' + }, + saveAsImage: { + title: '保存为图片', + lang: ['右键另存为图片'] + } + }, + series: { + typeNames: { + pie: '饼图', + bar: '柱状图', + line: '折线图', + scatter: '散点图', + effectScatter: '涟漪散点图', + radar: '雷达图', + tree: '树图', + treemap: '矩形树图', + boxplot: '箱型图', + candlestick: 'K线图', + k: 'K线图', + heatmap: '热力图', + map: '地图', + parallel: '平行坐标图', + lines: '线图', + graph: '关系图', + sankey: '桑基图', + funnel: '漏斗图', + gauge: '仪表盘图', + pictorialBar: '象形柱图', + themeRiver: '主题河流图', + sunburst: '旭日图' + } + }, + aria: { + general: { + withTitle: '这是一个关于“{title}”的图表。', + withoutTitle: '这是一个图表,' + }, + series: { + single: { + prefix: '', + withName: '图表类型是{seriesType},表示{seriesName}。', + withoutName: '图表类型是{seriesType}。' + }, + multiple: { + prefix: '它由{seriesCount}个图表系列组成。', + withName: '第{seriesId}个系列是一个表示{seriesName}的{seriesType},', + withoutName: '第{seriesId}个系列是一个{seriesType},', + separator: { + middle: ';', + end: '。' + } + } + }, + data: { + allData: '其数据是——', + partialData: '其中,前{displayCnt}项是——', + withName: '{name}的数据是{value}', + withoutName: '{value}', + separator: { + middle: ',', + end: '' + } + } + } + }; + + var LOCALE_ZH = 'ZH'; + var LOCALE_EN = 'EN'; + var DEFAULT_LOCALE = LOCALE_EN; + var localeStorage = {}; + var localeModels = {}; + var SYSTEM_LANG = !env.domSupported ? DEFAULT_LOCALE : function () { + var langStr = ( + /* eslint-disable-next-line */ + document.documentElement.lang || navigator.language || navigator.browserLanguage).toUpperCase(); + return langStr.indexOf(LOCALE_ZH) > -1 ? LOCALE_ZH : DEFAULT_LOCALE; + }(); + function registerLocale(locale, localeObj) { + locale = locale.toUpperCase(); + localeModels[locale] = new Model(localeObj); + localeStorage[locale] = localeObj; + } // export function getLocale(locale: string) { + // return localeStorage[locale]; + // } + + function createLocaleObject(locale) { + if (isString(locale)) { + var localeObj = localeStorage[locale.toUpperCase()] || {}; + + if (locale === LOCALE_ZH || locale === LOCALE_EN) { + return clone(localeObj); + } else { + return merge(clone(localeObj), clone(localeStorage[DEFAULT_LOCALE]), false); + } + } else { + return merge(clone(locale), clone(localeStorage[DEFAULT_LOCALE]), false); + } + } + function getLocaleModel(lang) { + return localeModels[lang]; + } + function getDefaultLocaleModel() { + return localeModels[DEFAULT_LOCALE]; + } // Default locale + + registerLocale(LOCALE_EN, langEN); + registerLocale(LOCALE_ZH, langZH); + + var ONE_SECOND = 1000; + var ONE_MINUTE = ONE_SECOND * 60; + var ONE_HOUR = ONE_MINUTE * 60; + var ONE_DAY = ONE_HOUR * 24; + var ONE_YEAR = ONE_DAY * 365; + var defaultLeveledFormatter = { + year: '{yyyy}', + month: '{MMM}', + day: '{d}', + hour: '{HH}:{mm}', + minute: '{HH}:{mm}', + second: '{HH}:{mm}:{ss}', + millisecond: '{HH}:{mm}:{ss} {SSS}', + none: '{yyyy}-{MM}-{dd} {HH}:{mm}:{ss} {SSS}' + }; + var fullDayFormatter = '{yyyy}-{MM}-{dd}'; + var fullLeveledFormatter = { + year: '{yyyy}', + month: '{yyyy}-{MM}', + day: fullDayFormatter, + hour: fullDayFormatter + ' ' + defaultLeveledFormatter.hour, + minute: fullDayFormatter + ' ' + defaultLeveledFormatter.minute, + second: fullDayFormatter + ' ' + defaultLeveledFormatter.second, + millisecond: defaultLeveledFormatter.none + }; + var primaryTimeUnits = ['year', 'month', 'day', 'hour', 'minute', 'second', 'millisecond']; + var timeUnits = ['year', 'half-year', 'quarter', 'month', 'week', 'half-week', 'day', 'half-day', 'quarter-day', 'hour', 'minute', 'second', 'millisecond']; + function pad(str, len) { + str += ''; + return '0000'.substr(0, len - str.length) + str; + } + function getPrimaryTimeUnit(timeUnit) { + switch (timeUnit) { + case 'half-year': + case 'quarter': + return 'month'; + + case 'week': + case 'half-week': + return 'day'; + + case 'half-day': + case 'quarter-day': + return 'hour'; + + default: + // year, minutes, second, milliseconds + return timeUnit; + } + } + function isPrimaryTimeUnit(timeUnit) { + return timeUnit === getPrimaryTimeUnit(timeUnit); + } + function getDefaultFormatPrecisionOfInterval(timeUnit) { + switch (timeUnit) { + case 'year': + case 'month': + return 'day'; + + case 'millisecond': + return 'millisecond'; + + default: + // Also for day, hour, minute, second + return 'second'; + } + } + function format( // Note: The result based on `isUTC` are totally different, which can not be just simply + // substituted by the result without `isUTC`. So we make the param `isUTC` mandatory. + time, template, isUTC, lang) { + var date = parseDate(time); + var y = date[fullYearGetterName(isUTC)](); + var M = date[monthGetterName(isUTC)]() + 1; + var q = Math.floor((M - 1) / 4) + 1; + var d = date[dateGetterName(isUTC)](); + var e = date['get' + (isUTC ? 'UTC' : '') + 'Day'](); + var H = date[hoursGetterName(isUTC)](); + var h = (H - 1) % 12 + 1; + var m = date[minutesGetterName(isUTC)](); + var s = date[secondsGetterName(isUTC)](); + var S = date[millisecondsGetterName(isUTC)](); + var localeModel = lang instanceof Model ? lang : getLocaleModel(lang || SYSTEM_LANG) || getDefaultLocaleModel(); + var timeModel = localeModel.getModel('time'); + var month = timeModel.get('month'); + var monthAbbr = timeModel.get('monthAbbr'); + var dayOfWeek = timeModel.get('dayOfWeek'); + var dayOfWeekAbbr = timeModel.get('dayOfWeekAbbr'); + return (template || '').replace(/{yyyy}/g, y + '').replace(/{yy}/g, y % 100 + '').replace(/{Q}/g, q + '').replace(/{MMMM}/g, month[M - 1]).replace(/{MMM}/g, monthAbbr[M - 1]).replace(/{MM}/g, pad(M, 2)).replace(/{M}/g, M + '').replace(/{dd}/g, pad(d, 2)).replace(/{d}/g, d + '').replace(/{eeee}/g, dayOfWeek[e]).replace(/{ee}/g, dayOfWeekAbbr[e]).replace(/{e}/g, e + '').replace(/{HH}/g, pad(H, 2)).replace(/{H}/g, H + '').replace(/{hh}/g, pad(h + '', 2)).replace(/{h}/g, h + '').replace(/{mm}/g, pad(m, 2)).replace(/{m}/g, m + '').replace(/{ss}/g, pad(s, 2)).replace(/{s}/g, s + '').replace(/{SSS}/g, pad(S, 3)).replace(/{S}/g, S + ''); + } + function leveledFormat(tick, idx, formatter, lang, isUTC) { + var template = null; + + if (isString(formatter)) { + // Single formatter for all units at all levels + template = formatter; + } else if (isFunction(formatter)) { + // Callback formatter + template = formatter(tick.value, idx, { + level: tick.level + }); + } else { + var defaults$1 = extend({}, defaultLeveledFormatter); + + if (tick.level > 0) { + for (var i = 0; i < primaryTimeUnits.length; ++i) { + defaults$1[primaryTimeUnits[i]] = "{primary|" + defaults$1[primaryTimeUnits[i]] + "}"; + } + } + + var mergedFormatter = formatter ? formatter.inherit === false ? formatter // Use formatter with bigger units + : defaults(formatter, defaults$1) : defaults$1; + var unit = getUnitFromValue(tick.value, isUTC); + + if (mergedFormatter[unit]) { + template = mergedFormatter[unit]; + } else if (mergedFormatter.inherit) { + // Unit formatter is not defined and should inherit from bigger units + var targetId = timeUnits.indexOf(unit); + + for (var i = targetId - 1; i >= 0; --i) { + if (mergedFormatter[unit]) { + template = mergedFormatter[unit]; + break; + } + } + + template = template || defaults$1.none; + } + + if (isArray(template)) { + var levelId = tick.level == null ? 0 : tick.level >= 0 ? tick.level : template.length + tick.level; + levelId = Math.min(levelId, template.length - 1); + template = template[levelId]; + } + } + + return format(new Date(tick.value), template, isUTC, lang); + } + function getUnitFromValue(value, isUTC) { + var date = parseDate(value); + var M = date[monthGetterName(isUTC)]() + 1; + var d = date[dateGetterName(isUTC)](); + var h = date[hoursGetterName(isUTC)](); + var m = date[minutesGetterName(isUTC)](); + var s = date[secondsGetterName(isUTC)](); + var S = date[millisecondsGetterName(isUTC)](); + var isSecond = S === 0; + var isMinute = isSecond && s === 0; + var isHour = isMinute && m === 0; + var isDay = isHour && h === 0; + var isMonth = isDay && d === 1; + var isYear = isMonth && M === 1; + + if (isYear) { + return 'year'; + } else if (isMonth) { + return 'month'; + } else if (isDay) { + return 'day'; + } else if (isHour) { + return 'hour'; + } else if (isMinute) { + return 'minute'; + } else if (isSecond) { + return 'second'; + } else { + return 'millisecond'; + } + } + function getUnitValue(value, unit, isUTC) { + var date = isNumber(value) ? parseDate(value) : value; + unit = unit || getUnitFromValue(value, isUTC); + + switch (unit) { + case 'year': + return date[fullYearGetterName(isUTC)](); + + case 'half-year': + return date[monthGetterName(isUTC)]() >= 6 ? 1 : 0; + + case 'quarter': + return Math.floor((date[monthGetterName(isUTC)]() + 1) / 4); + + case 'month': + return date[monthGetterName(isUTC)](); + + case 'day': + return date[dateGetterName(isUTC)](); + + case 'half-day': + return date[hoursGetterName(isUTC)]() / 24; + + case 'hour': + return date[hoursGetterName(isUTC)](); + + case 'minute': + return date[minutesGetterName(isUTC)](); + + case 'second': + return date[secondsGetterName(isUTC)](); + + case 'millisecond': + return date[millisecondsGetterName(isUTC)](); + } + } + function fullYearGetterName(isUTC) { + return isUTC ? 'getUTCFullYear' : 'getFullYear'; + } + function monthGetterName(isUTC) { + return isUTC ? 'getUTCMonth' : 'getMonth'; + } + function dateGetterName(isUTC) { + return isUTC ? 'getUTCDate' : 'getDate'; + } + function hoursGetterName(isUTC) { + return isUTC ? 'getUTCHours' : 'getHours'; + } + function minutesGetterName(isUTC) { + return isUTC ? 'getUTCMinutes' : 'getMinutes'; + } + function secondsGetterName(isUTC) { + return isUTC ? 'getUTCSeconds' : 'getSeconds'; + } + function millisecondsGetterName(isUTC) { + return isUTC ? 'getUTCMilliseconds' : 'getMilliseconds'; + } + function fullYearSetterName(isUTC) { + return isUTC ? 'setUTCFullYear' : 'setFullYear'; + } + function monthSetterName(isUTC) { + return isUTC ? 'setUTCMonth' : 'setMonth'; + } + function dateSetterName(isUTC) { + return isUTC ? 'setUTCDate' : 'setDate'; + } + function hoursSetterName(isUTC) { + return isUTC ? 'setUTCHours' : 'setHours'; + } + function minutesSetterName(isUTC) { + return isUTC ? 'setUTCMinutes' : 'setMinutes'; + } + function secondsSetterName(isUTC) { + return isUTC ? 'setUTCSeconds' : 'setSeconds'; + } + function millisecondsSetterName(isUTC) { + return isUTC ? 'setUTCMilliseconds' : 'setMilliseconds'; + } + + function getTextRect(text, font, align, verticalAlign, padding, rich, truncate, lineHeight) { + var textEl = new ZRText({ + style: { + text: text, + font: font, + align: align, + verticalAlign: verticalAlign, + padding: padding, + rich: rich, + overflow: truncate ? 'truncate' : null, + lineHeight: lineHeight + } + }); + return textEl.getBoundingRect(); + } + + /** + * Add a comma each three digit. + */ + + function addCommas(x) { + if (!isNumeric(x)) { + return isString(x) ? x : '-'; + } + + var parts = (x + '').split('.'); + return parts[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,') + (parts.length > 1 ? '.' + parts[1] : ''); + } + function toCamelCase(str, upperCaseFirst) { + str = (str || '').toLowerCase().replace(/-(.)/g, function (match, group1) { + return group1.toUpperCase(); + }); + + if (upperCaseFirst && str) { + str = str.charAt(0).toUpperCase() + str.slice(1); + } + + return str; + } + var normalizeCssArray$1 = normalizeCssArray; + var replaceReg = /([&<>"'])/g; + var replaceMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '\'': ''' + }; + function encodeHTML(source) { + return source == null ? '' : (source + '').replace(replaceReg, function (str, c) { + return replaceMap[c]; + }); + } + /** + * Make value user readable for tooltip and label. + * "User readable": + * Try to not print programmer-specific text like NaN, Infinity, null, undefined. + * Avoid to display an empty string, which users can not recognize there is + * a value and it might look like a bug. + */ + + function makeValueReadable(value, valueType, useUTC) { + var USER_READABLE_DEFUALT_TIME_PATTERN = '{yyyy}-{MM}-{dd} {HH}:{mm}:{ss}'; + + function stringToUserReadable(str) { + return str && trim(str) ? str : '-'; + } + + function isNumberUserReadable(num) { + return !!(num != null && !isNaN(num) && isFinite(num)); + } + + var isTypeTime = valueType === 'time'; + var isValueDate = value instanceof Date; + + if (isTypeTime || isValueDate) { + var date = isTypeTime ? parseDate(value) : value; + + if (!isNaN(+date)) { + return format(date, USER_READABLE_DEFUALT_TIME_PATTERN, useUTC); + } else if (isValueDate) { + return '-'; + } // In other cases, continue to try to display the value in the following code. + + } + + if (valueType === 'ordinal') { + return isStringSafe(value) ? stringToUserReadable(value) : isNumber(value) ? isNumberUserReadable(value) ? value + '' : '-' : '-'; + } // By default. + + + var numericResult = numericToNumber(value); + return isNumberUserReadable(numericResult) ? addCommas(numericResult) : isStringSafe(value) ? stringToUserReadable(value) : typeof value === 'boolean' ? value + '' : '-'; + } + var TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; + + var wrapVar = function (varName, seriesIdx) { + return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}'; + }; + /** + * Template formatter + * @param {Array.|Object} paramsList + */ + + + function formatTpl(tpl, paramsList, encode) { + if (!isArray(paramsList)) { + paramsList = [paramsList]; + } + + var seriesLen = paramsList.length; + + if (!seriesLen) { + return ''; + } + + var $vars = paramsList[0].$vars || []; + + for (var i = 0; i < $vars.length; i++) { + var alias = TPL_VAR_ALIAS[i]; + tpl = tpl.replace(wrapVar(alias), wrapVar(alias, 0)); + } + + for (var seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) { + for (var k = 0; k < $vars.length; k++) { + var val = paramsList[seriesIdx][$vars[k]]; + tpl = tpl.replace(wrapVar(TPL_VAR_ALIAS[k], seriesIdx), encode ? encodeHTML(val) : val); + } + } + + return tpl; + } + /** + * simple Template formatter + */ + + function formatTplSimple(tpl, param, encode) { + each(param, function (value, key) { + tpl = tpl.replace('{' + key + '}', encode ? encodeHTML(value) : value); + }); + return tpl; + } + function getTooltipMarker(inOpt, extraCssText) { + var opt = isString(inOpt) ? { + color: inOpt, + extraCssText: extraCssText + } : inOpt || {}; + var color = opt.color; + var type = opt.type; + extraCssText = opt.extraCssText; + var renderMode = opt.renderMode || 'html'; + + if (!color) { + return ''; + } + + if (renderMode === 'html') { + return type === 'subItem' ? '' : ''; + } else { + // Should better not to auto generate style name by auto-increment number here. + // Because this util is usually called in tooltip formatter, which is probably + // called repeatly when mouse move and the auto-increment number increases fast. + // Users can make their own style name by theirselves, make it unique and readable. + var markerId = opt.markerId || 'markerX'; + return { + renderMode: renderMode, + content: '{' + markerId + '|} ', + style: type === 'subItem' ? { + width: 4, + height: 4, + borderRadius: 2, + backgroundColor: color + } : { + width: 10, + height: 10, + borderRadius: 5, + backgroundColor: color + } + }; + } + } + /** + * @deprecated Use `time/format` instead. + * ISO Date format + * @param {string} tpl + * @param {number} value + * @param {boolean} [isUTC=false] Default in local time. + * see `module:echarts/scale/Time` + * and `module:echarts/util/number#parseDate`. + * @inner + */ + + function formatTime(tpl, value, isUTC) { + if ("development" !== 'production') { + deprecateReplaceLog('echarts.format.formatTime', 'echarts.time.format'); + } + + if (tpl === 'week' || tpl === 'month' || tpl === 'quarter' || tpl === 'half-year' || tpl === 'year') { + tpl = 'MM-dd\nyyyy'; + } + + var date = parseDate(value); + var getUTC = isUTC ? 'getUTC' : 'get'; + var y = date[getUTC + 'FullYear'](); + var M = date[getUTC + 'Month']() + 1; + var d = date[getUTC + 'Date'](); + var h = date[getUTC + 'Hours'](); + var m = date[getUTC + 'Minutes'](); + var s = date[getUTC + 'Seconds'](); + var S = date[getUTC + 'Milliseconds'](); + tpl = tpl.replace('MM', pad(M, 2)).replace('M', M).replace('yyyy', y).replace('yy', y % 100 + '').replace('dd', pad(d, 2)).replace('d', d).replace('hh', pad(h, 2)).replace('h', h).replace('mm', pad(m, 2)).replace('m', m).replace('ss', pad(s, 2)).replace('s', s).replace('SSS', pad(S, 3)); + return tpl; + } + /** + * Capital first + * @param {string} str + * @return {string} + */ + + function capitalFirst(str) { + return str ? str.charAt(0).toUpperCase() + str.substr(1) : str; + } + /** + * @return Never be null/undefined. + */ + + function convertToColorString(color, defaultColor) { + defaultColor = defaultColor || 'transparent'; + return isString(color) ? color : isObject(color) ? color.colorStops && (color.colorStops[0] || {}).color || defaultColor : defaultColor; + } + /** + * open new tab + * @param link url + * @param target blank or self + */ + + function windowOpen(link, target) { + /* global window */ + if (target === '_blank' || target === 'blank') { + var blank = window.open(); + blank.opener = null; + blank.location.href = link; + } else { + window.open(link, target); + } + } + + var each$1 = each; + /** + * @public + */ + + var LOCATION_PARAMS = ['left', 'right', 'top', 'bottom', 'width', 'height']; + /** + * @public + */ + + var HV_NAMES = [['width', 'left', 'right'], ['height', 'top', 'bottom']]; + + function boxLayout(orient, group, gap, maxWidth, maxHeight) { + var x = 0; + var y = 0; + + if (maxWidth == null) { + maxWidth = Infinity; + } + + if (maxHeight == null) { + maxHeight = Infinity; + } + + var currentLineMaxSize = 0; + group.eachChild(function (child, idx) { + var rect = child.getBoundingRect(); + var nextChild = group.childAt(idx + 1); + var nextChildRect = nextChild && nextChild.getBoundingRect(); + var nextX; + var nextY; + + if (orient === 'horizontal') { + var moveX = rect.width + (nextChildRect ? -nextChildRect.x + rect.x : 0); + nextX = x + moveX; // Wrap when width exceeds maxWidth or meet a `newline` group + // FIXME compare before adding gap? + + if (nextX > maxWidth || child.newline) { + x = 0; + nextX = moveX; + y += currentLineMaxSize + gap; + currentLineMaxSize = rect.height; + } else { + // FIXME: consider rect.y is not `0`? + currentLineMaxSize = Math.max(currentLineMaxSize, rect.height); + } + } else { + var moveY = rect.height + (nextChildRect ? -nextChildRect.y + rect.y : 0); + nextY = y + moveY; // Wrap when width exceeds maxHeight or meet a `newline` group + + if (nextY > maxHeight || child.newline) { + x += currentLineMaxSize + gap; + y = 0; + nextY = moveY; + currentLineMaxSize = rect.width; + } else { + currentLineMaxSize = Math.max(currentLineMaxSize, rect.width); + } + } + + if (child.newline) { + return; + } + + child.x = x; + child.y = y; + child.markRedraw(); + orient === 'horizontal' ? x = nextX + gap : y = nextY + gap; + }); + } + /** + * VBox or HBox layouting + * @param {string} orient + * @param {module:zrender/graphic/Group} group + * @param {number} gap + * @param {number} [width=Infinity] + * @param {number} [height=Infinity] + */ + + + var box = boxLayout; + /** + * VBox layouting + * @param {module:zrender/graphic/Group} group + * @param {number} gap + * @param {number} [width=Infinity] + * @param {number} [height=Infinity] + */ + + var vbox = curry(boxLayout, 'vertical'); + /** + * HBox layouting + * @param {module:zrender/graphic/Group} group + * @param {number} gap + * @param {number} [width=Infinity] + * @param {number} [height=Infinity] + */ + + var hbox = curry(boxLayout, 'horizontal'); + /** + * If x or x2 is not specified or 'center' 'left' 'right', + * the width would be as long as possible. + * If y or y2 is not specified or 'middle' 'top' 'bottom', + * the height would be as long as possible. + */ + + function getAvailableSize(positionInfo, containerRect, margin) { + var containerWidth = containerRect.width; + var containerHeight = containerRect.height; + var x = parsePercent$1(positionInfo.left, containerWidth); + var y = parsePercent$1(positionInfo.top, containerHeight); + var x2 = parsePercent$1(positionInfo.right, containerWidth); + var y2 = parsePercent$1(positionInfo.bottom, containerHeight); + (isNaN(x) || isNaN(parseFloat(positionInfo.left))) && (x = 0); + (isNaN(x2) || isNaN(parseFloat(positionInfo.right))) && (x2 = containerWidth); + (isNaN(y) || isNaN(parseFloat(positionInfo.top))) && (y = 0); + (isNaN(y2) || isNaN(parseFloat(positionInfo.bottom))) && (y2 = containerHeight); + margin = normalizeCssArray$1(margin || 0); + return { + width: Math.max(x2 - x - margin[1] - margin[3], 0), + height: Math.max(y2 - y - margin[0] - margin[2], 0) + }; + } + /** + * Parse position info. + */ + + function getLayoutRect(positionInfo, containerRect, margin) { + margin = normalizeCssArray$1(margin || 0); + var containerWidth = containerRect.width; + var containerHeight = containerRect.height; + var left = parsePercent$1(positionInfo.left, containerWidth); + var top = parsePercent$1(positionInfo.top, containerHeight); + var right = parsePercent$1(positionInfo.right, containerWidth); + var bottom = parsePercent$1(positionInfo.bottom, containerHeight); + var width = parsePercent$1(positionInfo.width, containerWidth); + var height = parsePercent$1(positionInfo.height, containerHeight); + var verticalMargin = margin[2] + margin[0]; + var horizontalMargin = margin[1] + margin[3]; + var aspect = positionInfo.aspect; // If width is not specified, calculate width from left and right + + if (isNaN(width)) { + width = containerWidth - right - horizontalMargin - left; + } + + if (isNaN(height)) { + height = containerHeight - bottom - verticalMargin - top; + } + + if (aspect != null) { + // If width and height are not given + // 1. Graph should not exceeds the container + // 2. Aspect must be keeped + // 3. Graph should take the space as more as possible + // FIXME + // Margin is not considered, because there is no case that both + // using margin and aspect so far. + if (isNaN(width) && isNaN(height)) { + if (aspect > containerWidth / containerHeight) { + width = containerWidth * 0.8; + } else { + height = containerHeight * 0.8; + } + } // Calculate width or height with given aspect + + + if (isNaN(width)) { + width = aspect * height; + } + + if (isNaN(height)) { + height = width / aspect; + } + } // If left is not specified, calculate left from right and width + + + if (isNaN(left)) { + left = containerWidth - right - width - horizontalMargin; + } + + if (isNaN(top)) { + top = containerHeight - bottom - height - verticalMargin; + } // Align left and top + + + switch (positionInfo.left || positionInfo.right) { + case 'center': + left = containerWidth / 2 - width / 2 - margin[3]; + break; + + case 'right': + left = containerWidth - width - horizontalMargin; + break; + } + + switch (positionInfo.top || positionInfo.bottom) { + case 'middle': + case 'center': + top = containerHeight / 2 - height / 2 - margin[0]; + break; + + case 'bottom': + top = containerHeight - height - verticalMargin; + break; + } // If something is wrong and left, top, width, height are calculated as NaN + + + left = left || 0; + top = top || 0; + + if (isNaN(width)) { + // Width may be NaN if only one value is given except width + width = containerWidth - horizontalMargin - left - (right || 0); + } + + if (isNaN(height)) { + // Height may be NaN if only one value is given except height + height = containerHeight - verticalMargin - top - (bottom || 0); + } + + var rect = new BoundingRect(left + margin[3], top + margin[0], width, height); + rect.margin = margin; + return rect; + } + /** + * Position a zr element in viewport + * Group position is specified by either + * {left, top}, {right, bottom} + * If all properties exists, right and bottom will be igonred. + * + * Logic: + * 1. Scale (against origin point in parent coord) + * 2. Rotate (against origin point in parent coord) + * 3. Traslate (with el.position by this method) + * So this method only fixes the last step 'Traslate', which does not affect + * scaling and rotating. + * + * If be called repeatly with the same input el, the same result will be gotten. + * + * Return true if the layout happend. + * + * @param el Should have `getBoundingRect` method. + * @param positionInfo + * @param positionInfo.left + * @param positionInfo.top + * @param positionInfo.right + * @param positionInfo.bottom + * @param positionInfo.width Only for opt.boundingModel: 'raw' + * @param positionInfo.height Only for opt.boundingModel: 'raw' + * @param containerRect + * @param margin + * @param opt + * @param opt.hv Only horizontal or only vertical. Default to be [1, 1] + * @param opt.boundingMode + * Specify how to calculate boundingRect when locating. + * 'all': Position the boundingRect that is transformed and uioned + * both itself and its descendants. + * This mode simplies confine the elements in the bounding + * of their container (e.g., using 'right: 0'). + * 'raw': Position the boundingRect that is not transformed and only itself. + * This mode is useful when you want a element can overflow its + * container. (Consider a rotated circle needs to be located in a corner.) + * In this mode positionInfo.width/height can only be number. + */ + + function positionElement(el, positionInfo, containerRect, margin, opt, out) { + var h = !opt || !opt.hv || opt.hv[0]; + var v = !opt || !opt.hv || opt.hv[1]; + var boundingMode = opt && opt.boundingMode || 'all'; + out = out || el; + out.x = el.x; + out.y = el.y; + + if (!h && !v) { + return false; + } + + var rect; + + if (boundingMode === 'raw') { + rect = el.type === 'group' ? new BoundingRect(0, 0, +positionInfo.width || 0, +positionInfo.height || 0) : el.getBoundingRect(); + } else { + rect = el.getBoundingRect(); + + if (el.needLocalTransform()) { + var transform = el.getLocalTransform(); // Notice: raw rect may be inner object of el, + // which should not be modified. + + rect = rect.clone(); + rect.applyTransform(transform); + } + } // The real width and height can not be specified but calculated by the given el. + + + var layoutRect = getLayoutRect(defaults({ + width: rect.width, + height: rect.height + }, positionInfo), containerRect, margin); // Because 'tranlate' is the last step in transform + // (see zrender/core/Transformable#getLocalTransform), + // we can just only modify el.position to get final result. + + var dx = h ? layoutRect.x - rect.x : 0; + var dy = v ? layoutRect.y - rect.y : 0; + + if (boundingMode === 'raw') { + out.x = dx; + out.y = dy; + } else { + out.x += dx; + out.y += dy; + } + + if (out === el) { + el.markRedraw(); + } + + return true; + } + /** + * @param option Contains some of the properties in HV_NAMES. + * @param hvIdx 0: horizontal; 1: vertical. + */ + + function sizeCalculable(option, hvIdx) { + return option[HV_NAMES[hvIdx][0]] != null || option[HV_NAMES[hvIdx][1]] != null && option[HV_NAMES[hvIdx][2]] != null; + } + function fetchLayoutMode(ins) { + var layoutMode = ins.layoutMode || ins.constructor.layoutMode; + return isObject(layoutMode) ? layoutMode : layoutMode ? { + type: layoutMode + } : null; + } + /** + * Consider Case: + * When default option has {left: 0, width: 100}, and we set {right: 0} + * through setOption or media query, using normal zrUtil.merge will cause + * {right: 0} does not take effect. + * + * @example + * ComponentModel.extend({ + * init: function () { + * ... + * let inputPositionParams = layout.getLayoutParams(option); + * this.mergeOption(inputPositionParams); + * }, + * mergeOption: function (newOption) { + * newOption && zrUtil.merge(thisOption, newOption, true); + * layout.mergeLayoutParam(thisOption, newOption); + * } + * }); + * + * @param targetOption + * @param newOption + * @param opt + */ + + function mergeLayoutParam(targetOption, newOption, opt) { + var ignoreSize = opt && opt.ignoreSize; + !isArray(ignoreSize) && (ignoreSize = [ignoreSize, ignoreSize]); + var hResult = merge(HV_NAMES[0], 0); + var vResult = merge(HV_NAMES[1], 1); + copy(HV_NAMES[0], targetOption, hResult); + copy(HV_NAMES[1], targetOption, vResult); + + function merge(names, hvIdx) { + var newParams = {}; + var newValueCount = 0; + var merged = {}; + var mergedValueCount = 0; + var enoughParamNumber = 2; + each$1(names, function (name) { + merged[name] = targetOption[name]; + }); + each$1(names, function (name) { + // Consider case: newOption.width is null, which is + // set by user for removing width setting. + hasProp(newOption, name) && (newParams[name] = merged[name] = newOption[name]); + hasValue(newParams, name) && newValueCount++; + hasValue(merged, name) && mergedValueCount++; + }); + + if (ignoreSize[hvIdx]) { + // Only one of left/right is premitted to exist. + if (hasValue(newOption, names[1])) { + merged[names[2]] = null; + } else if (hasValue(newOption, names[2])) { + merged[names[1]] = null; + } + + return merged; + } // Case: newOption: {width: ..., right: ...}, + // or targetOption: {right: ...} and newOption: {width: ...}, + // There is no conflict when merged only has params count + // little than enoughParamNumber. + + + if (mergedValueCount === enoughParamNumber || !newValueCount) { + return merged; + } // Case: newOption: {width: ..., right: ...}, + // Than we can make sure user only want those two, and ignore + // all origin params in targetOption. + else if (newValueCount >= enoughParamNumber) { + return newParams; + } else { + // Chose another param from targetOption by priority. + for (var i = 0; i < names.length; i++) { + var name_1 = names[i]; + + if (!hasProp(newParams, name_1) && hasProp(targetOption, name_1)) { + newParams[name_1] = targetOption[name_1]; + break; + } + } + + return newParams; + } + } + + function hasProp(obj, name) { + return obj.hasOwnProperty(name); + } + + function hasValue(obj, name) { + return obj[name] != null && obj[name] !== 'auto'; + } + + function copy(names, target, source) { + each$1(names, function (name) { + target[name] = source[name]; + }); + } + } + /** + * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object. + */ + + function getLayoutParams(source) { + return copyLayoutParams({}, source); + } + /** + * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object. + * @param {Object} source + * @return {Object} Result contains those props. + */ + + function copyLayoutParams(target, source) { + source && target && each$1(LOCATION_PARAMS, function (name) { + source.hasOwnProperty(name) && (target[name] = source[name]); + }); + return target; + } + + var inner = makeInner(); + + var ComponentModel = + /** @class */ + function (_super) { + __extends(ComponentModel, _super); + + function ComponentModel(option, parentModel, ecModel) { + var _this = _super.call(this, option, parentModel, ecModel) || this; + + _this.uid = getUID('ec_cpt_model'); + return _this; + } + + ComponentModel.prototype.init = function (option, parentModel, ecModel) { + this.mergeDefaultAndTheme(option, ecModel); + }; + + ComponentModel.prototype.mergeDefaultAndTheme = function (option, ecModel) { + var layoutMode = fetchLayoutMode(this); + var inputPositionParams = layoutMode ? getLayoutParams(option) : {}; + var themeModel = ecModel.getTheme(); + merge(option, themeModel.get(this.mainType)); + merge(option, this.getDefaultOption()); + + if (layoutMode) { + mergeLayoutParam(option, inputPositionParams, layoutMode); + } + }; + + ComponentModel.prototype.mergeOption = function (option, ecModel) { + merge(this.option, option, true); + var layoutMode = fetchLayoutMode(this); + + if (layoutMode) { + mergeLayoutParam(this.option, option, layoutMode); + } + }; + /** + * Called immediately after `init` or `mergeOption` of this instance called. + */ + + + ComponentModel.prototype.optionUpdated = function (newCptOption, isInit) {}; + /** + * [How to declare defaultOption]: + * + * (A) If using class declaration in typescript (since echarts 5): + * ```ts + * import {ComponentOption} from '../model/option.js'; + * export interface XxxOption extends ComponentOption { + * aaa: number + * } + * export class XxxModel extends Component { + * static type = 'xxx'; + * static defaultOption: XxxOption = { + * aaa: 123 + * } + * } + * Component.registerClass(XxxModel); + * ``` + * ```ts + * import {inheritDefaultOption} from '../util/component.js'; + * import {XxxModel, XxxOption} from './XxxModel.js'; + * export interface XxxSubOption extends XxxOption { + * bbb: number + * } + * class XxxSubModel extends XxxModel { + * static defaultOption: XxxSubOption = inheritDefaultOption(XxxModel.defaultOption, { + * bbb: 456 + * }) + * fn() { + * let opt = this.getDefaultOption(); + * // opt is {aaa: 123, bbb: 456} + * } + * } + * ``` + * + * (B) If using class extend (previous approach in echarts 3 & 4): + * ```js + * let XxxComponent = Component.extend({ + * defaultOption: { + * xx: 123 + * } + * }) + * ``` + * ```js + * let XxxSubComponent = XxxComponent.extend({ + * defaultOption: { + * yy: 456 + * }, + * fn: function () { + * let opt = this.getDefaultOption(); + * // opt is {xx: 123, yy: 456} + * } + * }) + * ``` + */ + + + ComponentModel.prototype.getDefaultOption = function () { + var ctor = this.constructor; // If using class declaration, it is different to travel super class + // in legacy env and auto merge defaultOption. So if using class + // declaration, defaultOption should be merged manually. + + if (!isExtendedClass(ctor)) { + // When using ts class, defaultOption must be declared as static. + return ctor.defaultOption; + } // FIXME: remove this approach? + + + var fields = inner(this); + + if (!fields.defaultOption) { + var optList = []; + var clz = ctor; + + while (clz) { + var opt = clz.prototype.defaultOption; + opt && optList.push(opt); + clz = clz.superClass; + } + + var defaultOption = {}; + + for (var i = optList.length - 1; i >= 0; i--) { + defaultOption = merge(defaultOption, optList[i], true); + } + + fields.defaultOption = defaultOption; + } + + return fields.defaultOption; + }; + /** + * Notice: always force to input param `useDefault` in case that forget to consider it. + * The same behavior as `modelUtil.parseFinder`. + * + * @param useDefault In many cases like series refer axis and axis refer grid, + * If axis index / axis id not specified, use the first target as default. + * In other cases like dataZoom refer axis, if not specified, measn no refer. + */ + + + ComponentModel.prototype.getReferringComponents = function (mainType, opt) { + var indexKey = mainType + 'Index'; + var idKey = mainType + 'Id'; + return queryReferringComponents(this.ecModel, mainType, { + index: this.get(indexKey, true), + id: this.get(idKey, true) + }, opt); + }; + + ComponentModel.prototype.getBoxLayoutParams = function () { + // Consider itself having box layout configs. + var boxLayoutModel = this; + return { + left: boxLayoutModel.get('left'), + top: boxLayoutModel.get('top'), + right: boxLayoutModel.get('right'), + bottom: boxLayoutModel.get('bottom'), + width: boxLayoutModel.get('width'), + height: boxLayoutModel.get('height') + }; + }; + /** + * Get key for zlevel. + * If developers don't configure zlevel. We will assign zlevel to series based on the key. + * For example, lines with trail effect and progressive series will in an individual zlevel. + */ + + + ComponentModel.prototype.getZLevelKey = function () { + return ''; + }; + + ComponentModel.prototype.setZLevel = function (zlevel) { + this.option.zlevel = zlevel; + }; + + ComponentModel.protoInitialize = function () { + var proto = ComponentModel.prototype; + proto.type = 'component'; + proto.id = ''; + proto.name = ''; + proto.mainType = ''; + proto.subType = ''; + proto.componentIndex = 0; + }(); + + return ComponentModel; + }(Model); + + mountExtend(ComponentModel, Model); + enableClassManagement(ComponentModel); + enableSubTypeDefaulter(ComponentModel); + enableTopologicalTravel(ComponentModel, getDependencies); + + function getDependencies(componentType) { + var deps = []; + each(ComponentModel.getClassesByMainType(componentType), function (clz) { + deps = deps.concat(clz.dependencies || clz.prototype.dependencies || []); + }); // Ensure main type. + + deps = map(deps, function (type) { + return parseClassType(type).main; + }); // Hack dataset for convenience. + + if (componentType !== 'dataset' && indexOf(deps, 'dataset') <= 0) { + deps.unshift('dataset'); + } + + return deps; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var platform = ''; // Navigator not exists in node + + if (typeof navigator !== 'undefined') { + /* global navigator */ + platform = navigator.platform || ''; + } + + var decalColor = 'rgba(0, 0, 0, 0.2)'; + var globalDefault = { + darkMode: 'auto', + // backgroundColor: 'rgba(0,0,0,0)', + colorBy: 'series', + color: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'], + gradientColor: ['#f6efa6', '#d88273', '#bf444c'], + aria: { + decal: { + decals: [{ + color: decalColor, + dashArrayX: [1, 0], + dashArrayY: [2, 5], + symbolSize: 1, + rotation: Math.PI / 6 + }, { + color: decalColor, + symbol: 'circle', + dashArrayX: [[8, 8], [0, 8, 8, 0]], + dashArrayY: [6, 0], + symbolSize: 0.8 + }, { + color: decalColor, + dashArrayX: [1, 0], + dashArrayY: [4, 3], + rotation: -Math.PI / 4 + }, { + color: decalColor, + dashArrayX: [[6, 6], [0, 6, 6, 0]], + dashArrayY: [6, 0] + }, { + color: decalColor, + dashArrayX: [[1, 0], [1, 6]], + dashArrayY: [1, 0, 6, 0], + rotation: Math.PI / 4 + }, { + color: decalColor, + symbol: 'triangle', + dashArrayX: [[9, 9], [0, 9, 9, 0]], + dashArrayY: [7, 2], + symbolSize: 0.75 + }] + } + }, + // If xAxis and yAxis declared, grid is created by default. + // grid: {}, + textStyle: { + // color: '#000', + // decoration: 'none', + // PENDING + fontFamily: platform.match(/^Win/) ? 'Microsoft YaHei' : 'sans-serif', + // fontFamily: 'Arial, Verdana, sans-serif', + fontSize: 12, + fontStyle: 'normal', + fontWeight: 'normal' + }, + // http://blogs.adobe.com/webplatform/2014/02/24/using-blend-modes-in-html-canvas/ + // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation + // Default is source-over + blendMode: null, + stateAnimation: { + duration: 300, + easing: 'cubicOut' + }, + animation: 'auto', + animationDuration: 1000, + animationDurationUpdate: 500, + animationEasing: 'cubicInOut', + animationEasingUpdate: 'cubicInOut', + animationThreshold: 2000, + // Configuration for progressive/incremental rendering + progressiveThreshold: 3000, + progressive: 400, + // Threshold of if use single hover layer to optimize. + // It is recommended that `hoverLayerThreshold` is equivalent to or less than + // `progressiveThreshold`, otherwise hover will cause restart of progressive, + // which is unexpected. + // see example . + hoverLayerThreshold: 3000, + // See: module:echarts/scale/Time + useUTC: false + }; + + var VISUAL_DIMENSIONS = createHashMap(['tooltip', 'label', 'itemName', 'itemId', 'itemGroupId', 'seriesName']); + var SOURCE_FORMAT_ORIGINAL = 'original'; + var SOURCE_FORMAT_ARRAY_ROWS = 'arrayRows'; + var SOURCE_FORMAT_OBJECT_ROWS = 'objectRows'; + var SOURCE_FORMAT_KEYED_COLUMNS = 'keyedColumns'; + var SOURCE_FORMAT_TYPED_ARRAY = 'typedArray'; + var SOURCE_FORMAT_UNKNOWN = 'unknown'; + var SERIES_LAYOUT_BY_COLUMN = 'column'; + var SERIES_LAYOUT_BY_ROW = 'row'; + + var BE_ORDINAL = { + Must: 1, + Might: 2, + Not: 3 // Other cases + + }; + var innerGlobalModel = makeInner(); + /** + * MUST be called before mergeOption of all series. + */ + + function resetSourceDefaulter(ecModel) { + // `datasetMap` is used to make default encode. + innerGlobalModel(ecModel).datasetMap = createHashMap(); + } + /** + * [The strategy of the arrengment of data dimensions for dataset]: + * "value way": all axes are non-category axes. So series one by one take + * several (the number is coordSysDims.length) dimensions from dataset. + * The result of data arrengment of data dimensions like: + * | ser0_x | ser0_y | ser1_x | ser1_y | ser2_x | ser2_y | + * "category way": at least one axis is category axis. So the the first data + * dimension is always mapped to the first category axis and shared by + * all of the series. The other data dimensions are taken by series like + * "value way" does. + * The result of data arrengment of data dimensions like: + * | ser_shared_x | ser0_y | ser1_y | ser2_y | + * + * @return encode Never be `null/undefined`. + */ + + function makeSeriesEncodeForAxisCoordSys(coordDimensions, seriesModel, source) { + var encode = {}; + var datasetModel = querySeriesUpstreamDatasetModel(seriesModel); // Currently only make default when using dataset, util more reqirements occur. + + if (!datasetModel || !coordDimensions) { + return encode; + } + + var encodeItemName = []; + var encodeSeriesName = []; + var ecModel = seriesModel.ecModel; + var datasetMap = innerGlobalModel(ecModel).datasetMap; + var key = datasetModel.uid + '_' + source.seriesLayoutBy; + var baseCategoryDimIndex; + var categoryWayValueDimStart; + coordDimensions = coordDimensions.slice(); + each(coordDimensions, function (coordDimInfoLoose, coordDimIdx) { + var coordDimInfo = isObject(coordDimInfoLoose) ? coordDimInfoLoose : coordDimensions[coordDimIdx] = { + name: coordDimInfoLoose + }; + + if (coordDimInfo.type === 'ordinal' && baseCategoryDimIndex == null) { + baseCategoryDimIndex = coordDimIdx; + categoryWayValueDimStart = getDataDimCountOnCoordDim(coordDimInfo); + } + + encode[coordDimInfo.name] = []; + }); + var datasetRecord = datasetMap.get(key) || datasetMap.set(key, { + categoryWayDim: categoryWayValueDimStart, + valueWayDim: 0 + }); // TODO + // Auto detect first time axis and do arrangement. + + each(coordDimensions, function (coordDimInfo, coordDimIdx) { + var coordDimName = coordDimInfo.name; + var count = getDataDimCountOnCoordDim(coordDimInfo); // In value way. + + if (baseCategoryDimIndex == null) { + var start = datasetRecord.valueWayDim; + pushDim(encode[coordDimName], start, count); + pushDim(encodeSeriesName, start, count); + datasetRecord.valueWayDim += count; // ??? TODO give a better default series name rule? + // especially when encode x y specified. + // consider: when mutiple series share one dimension + // category axis, series name should better use + // the other dimsion name. On the other hand, use + // both dimensions name. + } // In category way, the first category axis. + else if (baseCategoryDimIndex === coordDimIdx) { + pushDim(encode[coordDimName], 0, count); + pushDim(encodeItemName, 0, count); + } // In category way, the other axis. + else { + var start = datasetRecord.categoryWayDim; + pushDim(encode[coordDimName], start, count); + pushDim(encodeSeriesName, start, count); + datasetRecord.categoryWayDim += count; + } + }); + + function pushDim(dimIdxArr, idxFrom, idxCount) { + for (var i = 0; i < idxCount; i++) { + dimIdxArr.push(idxFrom + i); + } + } + + function getDataDimCountOnCoordDim(coordDimInfo) { + var dimsDef = coordDimInfo.dimsDef; + return dimsDef ? dimsDef.length : 1; + } + + encodeItemName.length && (encode.itemName = encodeItemName); + encodeSeriesName.length && (encode.seriesName = encodeSeriesName); + return encode; + } + /** + * Work for data like [{name: ..., value: ...}, ...]. + * + * @return encode Never be `null/undefined`. + */ + + function makeSeriesEncodeForNameBased(seriesModel, source, dimCount) { + var encode = {}; + var datasetModel = querySeriesUpstreamDatasetModel(seriesModel); // Currently only make default when using dataset, util more reqirements occur. + + if (!datasetModel) { + return encode; + } + + var sourceFormat = source.sourceFormat; + var dimensionsDefine = source.dimensionsDefine; + var potentialNameDimIndex; + + if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS || sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) { + each(dimensionsDefine, function (dim, idx) { + if ((isObject(dim) ? dim.name : dim) === 'name') { + potentialNameDimIndex = idx; + } + }); + } + + var idxResult = function () { + var idxRes0 = {}; + var idxRes1 = {}; + var guessRecords = []; // 5 is an experience value. + + for (var i = 0, len = Math.min(5, dimCount); i < len; i++) { + var guessResult = doGuessOrdinal(source.data, sourceFormat, source.seriesLayoutBy, dimensionsDefine, source.startIndex, i); + guessRecords.push(guessResult); + var isPureNumber = guessResult === BE_ORDINAL.Not; // [Strategy of idxRes0]: find the first BE_ORDINAL.Not as the value dim, + // and then find a name dim with the priority: + // "BE_ORDINAL.Might|BE_ORDINAL.Must" > "other dim" > "the value dim itself". + + if (isPureNumber && idxRes0.v == null && i !== potentialNameDimIndex) { + idxRes0.v = i; + } + + if (idxRes0.n == null || idxRes0.n === idxRes0.v || !isPureNumber && guessRecords[idxRes0.n] === BE_ORDINAL.Not) { + idxRes0.n = i; + } + + if (fulfilled(idxRes0) && guessRecords[idxRes0.n] !== BE_ORDINAL.Not) { + return idxRes0; + } // [Strategy of idxRes1]: if idxRes0 not satisfied (that is, no BE_ORDINAL.Not), + // find the first BE_ORDINAL.Might as the value dim, + // and then find a name dim with the priority: + // "other dim" > "the value dim itself". + // That is for backward compat: number-like (e.g., `'3'`, `'55'`) can be + // treated as number. + + + if (!isPureNumber) { + if (guessResult === BE_ORDINAL.Might && idxRes1.v == null && i !== potentialNameDimIndex) { + idxRes1.v = i; + } + + if (idxRes1.n == null || idxRes1.n === idxRes1.v) { + idxRes1.n = i; + } + } + } + + function fulfilled(idxResult) { + return idxResult.v != null && idxResult.n != null; + } + + return fulfilled(idxRes0) ? idxRes0 : fulfilled(idxRes1) ? idxRes1 : null; + }(); + + if (idxResult) { + encode.value = [idxResult.v]; // `potentialNameDimIndex` has highest priority. + + var nameDimIndex = potentialNameDimIndex != null ? potentialNameDimIndex : idxResult.n; // By default, label use itemName in charts. + // So we dont set encodeLabel here. + + encode.itemName = [nameDimIndex]; + encode.seriesName = [nameDimIndex]; + } + + return encode; + } + /** + * @return If return null/undefined, indicate that should not use datasetModel. + */ + + function querySeriesUpstreamDatasetModel(seriesModel) { + // Caution: consider the scenario: + // A dataset is declared and a series is not expected to use the dataset, + // and at the beginning `setOption({series: { noData })` (just prepare other + // option but no data), then `setOption({series: {data: [...]}); In this case, + // the user should set an empty array to avoid that dataset is used by default. + var thisData = seriesModel.get('data', true); + + if (!thisData) { + return queryReferringComponents(seriesModel.ecModel, 'dataset', { + index: seriesModel.get('datasetIndex', true), + id: seriesModel.get('datasetId', true) + }, SINGLE_REFERRING).models[0]; + } + } + /** + * @return Always return an array event empty. + */ + + function queryDatasetUpstreamDatasetModels(datasetModel) { + // Only these attributes declared, we by defualt reference to `datasetIndex: 0`. + // Otherwise, no reference. + if (!datasetModel.get('transform', true) && !datasetModel.get('fromTransformResult', true)) { + return []; + } + + return queryReferringComponents(datasetModel.ecModel, 'dataset', { + index: datasetModel.get('fromDatasetIndex', true), + id: datasetModel.get('fromDatasetId', true) + }, SINGLE_REFERRING).models; + } + /** + * The rule should not be complex, otherwise user might not + * be able to known where the data is wrong. + * The code is ugly, but how to make it neat? + */ + + function guessOrdinal(source, dimIndex) { + return doGuessOrdinal(source.data, source.sourceFormat, source.seriesLayoutBy, source.dimensionsDefine, source.startIndex, dimIndex); + } // dimIndex may be overflow source data. + // return {BE_ORDINAL} + + function doGuessOrdinal(data, sourceFormat, seriesLayoutBy, dimensionsDefine, startIndex, dimIndex) { + var result; // Experience value. + + var maxLoop = 5; + + if (isTypedArray(data)) { + return BE_ORDINAL.Not; + } // When sourceType is 'objectRows' or 'keyedColumns', dimensionsDefine + // always exists in source. + + + var dimName; + var dimType; + + if (dimensionsDefine) { + var dimDefItem = dimensionsDefine[dimIndex]; + + if (isObject(dimDefItem)) { + dimName = dimDefItem.name; + dimType = dimDefItem.type; + } else if (isString(dimDefItem)) { + dimName = dimDefItem; + } + } + + if (dimType != null) { + return dimType === 'ordinal' ? BE_ORDINAL.Must : BE_ORDINAL.Not; + } + + if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) { + var dataArrayRows = data; + + if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) { + var sample = dataArrayRows[dimIndex]; + + for (var i = 0; i < (sample || []).length && i < maxLoop; i++) { + if ((result = detectValue(sample[startIndex + i])) != null) { + return result; + } + } + } else { + for (var i = 0; i < dataArrayRows.length && i < maxLoop; i++) { + var row = dataArrayRows[startIndex + i]; + + if (row && (result = detectValue(row[dimIndex])) != null) { + return result; + } + } + } + } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) { + var dataObjectRows = data; + + if (!dimName) { + return BE_ORDINAL.Not; + } + + for (var i = 0; i < dataObjectRows.length && i < maxLoop; i++) { + var item = dataObjectRows[i]; + + if (item && (result = detectValue(item[dimName])) != null) { + return result; + } + } + } else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) { + var dataKeyedColumns = data; + + if (!dimName) { + return BE_ORDINAL.Not; + } + + var sample = dataKeyedColumns[dimName]; + + if (!sample || isTypedArray(sample)) { + return BE_ORDINAL.Not; + } + + for (var i = 0; i < sample.length && i < maxLoop; i++) { + if ((result = detectValue(sample[i])) != null) { + return result; + } + } + } else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) { + var dataOriginal = data; + + for (var i = 0; i < dataOriginal.length && i < maxLoop; i++) { + var item = dataOriginal[i]; + var val = getDataItemValue(item); + + if (!isArray(val)) { + return BE_ORDINAL.Not; + } + + if ((result = detectValue(val[dimIndex])) != null) { + return result; + } + } + } + + function detectValue(val) { + var beStr = isString(val); // Consider usage convenience, '1', '2' will be treated as "number". + // `isFinit('')` get `true`. + + if (val != null && isFinite(val) && val !== '') { + return beStr ? BE_ORDINAL.Might : BE_ORDINAL.Not; + } else if (beStr && val !== '-') { + return BE_ORDINAL.Must; + } + } + + return BE_ORDINAL.Not; + } + + var internalOptionCreatorMap = createHashMap(); + function registerInternalOptionCreator(mainType, creator) { + assert(internalOptionCreatorMap.get(mainType) == null && creator); + internalOptionCreatorMap.set(mainType, creator); + } + function concatInternalOptions(ecModel, mainType, newCmptOptionList) { + var internalOptionCreator = internalOptionCreatorMap.get(mainType); + + if (!internalOptionCreator) { + return newCmptOptionList; + } + + var internalOptions = internalOptionCreator(ecModel); + + if (!internalOptions) { + return newCmptOptionList; + } + + if ("development" !== 'production') { + for (var i = 0; i < internalOptions.length; i++) { + assert(isComponentIdInternal(internalOptions[i])); + } + } + + return newCmptOptionList.concat(internalOptions); + } + + var innerColor = makeInner(); + var innerDecal = makeInner(); + + var PaletteMixin = + /** @class */ + function () { + function PaletteMixin() {} + + PaletteMixin.prototype.getColorFromPalette = function (name, scope, requestNum) { + var defaultPalette = normalizeToArray(this.get('color', true)); + var layeredPalette = this.get('colorLayer', true); + return getFromPalette(this, innerColor, defaultPalette, layeredPalette, name, scope, requestNum); + }; + + PaletteMixin.prototype.clearColorPalette = function () { + clearPalette(this, innerColor); + }; + + return PaletteMixin; + }(); + + function getDecalFromPalette(ecModel, name, scope, requestNum) { + var defaultDecals = normalizeToArray(ecModel.get(['aria', 'decal', 'decals'])); + return getFromPalette(ecModel, innerDecal, defaultDecals, null, name, scope, requestNum); + } + + function getNearestPalette(palettes, requestColorNum) { + var paletteNum = palettes.length; // TODO palettes must be in order + + for (var i = 0; i < paletteNum; i++) { + if (palettes[i].length > requestColorNum) { + return palettes[i]; + } + } + + return palettes[paletteNum - 1]; + } + /** + * @param name MUST NOT be null/undefined. Otherwise call this function + * twise with the same parameters will get different result. + * @param scope default this. + * @return Can be null/undefined + */ + + + function getFromPalette(that, inner, defaultPalette, layeredPalette, name, scope, requestNum) { + scope = scope || that; + var scopeFields = inner(scope); + var paletteIdx = scopeFields.paletteIdx || 0; + var paletteNameMap = scopeFields.paletteNameMap = scopeFields.paletteNameMap || {}; // Use `hasOwnProperty` to avoid conflict with Object.prototype. + + if (paletteNameMap.hasOwnProperty(name)) { + return paletteNameMap[name]; + } + + var palette = requestNum == null || !layeredPalette ? defaultPalette : getNearestPalette(layeredPalette, requestNum); // In case can't find in layered color palette. + + palette = palette || defaultPalette; + + if (!palette || !palette.length) { + return; + } + + var pickedPaletteItem = palette[paletteIdx]; + + if (name) { + paletteNameMap[name] = pickedPaletteItem; + } + + scopeFields.paletteIdx = (paletteIdx + 1) % palette.length; + return pickedPaletteItem; + } + + function clearPalette(that, inner) { + inner(that).paletteIdx = 0; + inner(that).paletteNameMap = {}; + } + + // Internal method names: + // ----------------------- + + var reCreateSeriesIndices; + var assertSeriesInitialized; + var initBase; + var OPTION_INNER_KEY = '\0_ec_inner'; + var OPTION_INNER_VALUE = 1; + var BUITIN_COMPONENTS_MAP = { + grid: 'GridComponent', + polar: 'PolarComponent', + geo: 'GeoComponent', + singleAxis: 'SingleAxisComponent', + parallel: 'ParallelComponent', + calendar: 'CalendarComponent', + graphic: 'GraphicComponent', + toolbox: 'ToolboxComponent', + tooltip: 'TooltipComponent', + axisPointer: 'AxisPointerComponent', + brush: 'BrushComponent', + title: 'TitleComponent', + timeline: 'TimelineComponent', + markPoint: 'MarkPointComponent', + markLine: 'MarkLineComponent', + markArea: 'MarkAreaComponent', + legend: 'LegendComponent', + dataZoom: 'DataZoomComponent', + visualMap: 'VisualMapComponent', + // aria: 'AriaComponent', + // dataset: 'DatasetComponent', + // Dependencies + xAxis: 'GridComponent', + yAxis: 'GridComponent', + angleAxis: 'PolarComponent', + radiusAxis: 'PolarComponent' + }; + var BUILTIN_CHARTS_MAP = { + line: 'LineChart', + bar: 'BarChart', + pie: 'PieChart', + scatter: 'ScatterChart', + radar: 'RadarChart', + map: 'MapChart', + tree: 'TreeChart', + treemap: 'TreemapChart', + graph: 'GraphChart', + gauge: 'GaugeChart', + funnel: 'FunnelChart', + parallel: 'ParallelChart', + sankey: 'SankeyChart', + boxplot: 'BoxplotChart', + candlestick: 'CandlestickChart', + effectScatter: 'EffectScatterChart', + lines: 'LinesChart', + heatmap: 'HeatmapChart', + pictorialBar: 'PictorialBarChart', + themeRiver: 'ThemeRiverChart', + sunburst: 'SunburstChart', + custom: 'CustomChart' + }; + var componetsMissingLogPrinted = {}; + + function checkMissingComponents(option) { + each(option, function (componentOption, mainType) { + if (!ComponentModel.hasClass(mainType)) { + var componentImportName = BUITIN_COMPONENTS_MAP[mainType]; + + if (componentImportName && !componetsMissingLogPrinted[componentImportName]) { + error("Component " + mainType + " is used but not imported.\nimport { " + componentImportName + " } from 'echarts/components';\necharts.use([" + componentImportName + "]);"); + componetsMissingLogPrinted[componentImportName] = true; + } + } + }); + } + + var GlobalModel = + /** @class */ + function (_super) { + __extends(GlobalModel, _super); + + function GlobalModel() { + return _super !== null && _super.apply(this, arguments) || this; + } + + GlobalModel.prototype.init = function (option, parentModel, ecModel, theme, locale, optionManager) { + theme = theme || {}; + this.option = null; // Mark as not initialized. + + this._theme = new Model(theme); + this._locale = new Model(locale); + this._optionManager = optionManager; + }; + + GlobalModel.prototype.setOption = function (option, opts, optionPreprocessorFuncs) { + if ("development" !== 'production') { + assert(option != null, 'option is null/undefined'); + assert(option[OPTION_INNER_KEY] !== OPTION_INNER_VALUE, 'please use chart.getOption()'); + } + + var innerOpt = normalizeSetOptionInput(opts); + + this._optionManager.setOption(option, optionPreprocessorFuncs, innerOpt); + + this._resetOption(null, innerOpt); + }; + /** + * @param type null/undefined: reset all. + * 'recreate': force recreate all. + * 'timeline': only reset timeline option + * 'media': only reset media query option + * @return Whether option changed. + */ + + + GlobalModel.prototype.resetOption = function (type, opt) { + return this._resetOption(type, normalizeSetOptionInput(opt)); + }; + + GlobalModel.prototype._resetOption = function (type, opt) { + var optionChanged = false; + var optionManager = this._optionManager; + + if (!type || type === 'recreate') { + var baseOption = optionManager.mountOption(type === 'recreate'); + + if ("development" !== 'production') { + checkMissingComponents(baseOption); + } + + if (!this.option || type === 'recreate') { + initBase(this, baseOption); + } else { + this.restoreData(); + + this._mergeOption(baseOption, opt); + } + + optionChanged = true; + } + + if (type === 'timeline' || type === 'media') { + this.restoreData(); + } // By design, if `setOption(option2)` at the second time, and `option2` is a `ECUnitOption`, + // it should better not have the same props with `MediaUnit['option']`. + // Becuase either `option2` or `MediaUnit['option']` will be always merged to "current option" + // rather than original "baseOption". If they both override a prop, the result might be + // unexpected when media state changed after `setOption` called. + // If we really need to modify a props in each `MediaUnit['option']`, use the full version + // (`{baseOption, media}`) in `setOption`. + // For `timeline`, the case is the same. + + + if (!type || type === 'recreate' || type === 'timeline') { + var timelineOption = optionManager.getTimelineOption(this); + + if (timelineOption) { + optionChanged = true; + + this._mergeOption(timelineOption, opt); + } + } + + if (!type || type === 'recreate' || type === 'media') { + var mediaOptions = optionManager.getMediaOption(this); + + if (mediaOptions.length) { + each(mediaOptions, function (mediaOption) { + optionChanged = true; + + this._mergeOption(mediaOption, opt); + }, this); + } + } + + return optionChanged; + }; + + GlobalModel.prototype.mergeOption = function (option) { + this._mergeOption(option, null); + }; + + GlobalModel.prototype._mergeOption = function (newOption, opt) { + var option = this.option; + var componentsMap = this._componentsMap; + var componentsCount = this._componentsCount; + var newCmptTypes = []; + var newCmptTypeMap = createHashMap(); + var replaceMergeMainTypeMap = opt && opt.replaceMergeMainTypeMap; + resetSourceDefaulter(this); // If no component class, merge directly. + // For example: color, animaiton options, etc. + + each(newOption, function (componentOption, mainType) { + if (componentOption == null) { + return; + } + + if (!ComponentModel.hasClass(mainType)) { + // globalSettingTask.dirty(); + option[mainType] = option[mainType] == null ? clone(componentOption) : merge(option[mainType], componentOption, true); + } else if (mainType) { + newCmptTypes.push(mainType); + newCmptTypeMap.set(mainType, true); + } + }); + + if (replaceMergeMainTypeMap) { + // If there is a mainType `xxx` in `replaceMerge` but not declared in option, + // we trade it as it is declared in option as `{xxx: []}`. Because: + // (1) for normal merge, `{xxx: null/undefined}` are the same meaning as `{xxx: []}`. + // (2) some preprocessor may convert some of `{xxx: null/undefined}` to `{xxx: []}`. + replaceMergeMainTypeMap.each(function (val, mainTypeInReplaceMerge) { + if (ComponentModel.hasClass(mainTypeInReplaceMerge) && !newCmptTypeMap.get(mainTypeInReplaceMerge)) { + newCmptTypes.push(mainTypeInReplaceMerge); + newCmptTypeMap.set(mainTypeInReplaceMerge, true); + } + }); + } + + ComponentModel.topologicalTravel(newCmptTypes, ComponentModel.getAllClassMainTypes(), visitComponent, this); + + function visitComponent(mainType) { + var newCmptOptionList = concatInternalOptions(this, mainType, normalizeToArray(newOption[mainType])); + var oldCmptList = componentsMap.get(mainType); + var mergeMode = // `!oldCmptList` means init. See the comment in `mappingToExists` + !oldCmptList ? 'replaceAll' : replaceMergeMainTypeMap && replaceMergeMainTypeMap.get(mainType) ? 'replaceMerge' : 'normalMerge'; + var mappingResult = mappingToExists(oldCmptList, newCmptOptionList, mergeMode); // Set mainType and complete subType. + + setComponentTypeToKeyInfo(mappingResult, mainType, ComponentModel); // Empty it before the travel, in order to prevent `this._componentsMap` + // from being used in the `init`/`mergeOption`/`optionUpdated` of some + // components, which is probably incorrect logic. + + option[mainType] = null; + componentsMap.set(mainType, null); + componentsCount.set(mainType, 0); + var optionsByMainType = []; + var cmptsByMainType = []; + var cmptsCountByMainType = 0; + var tooltipExists; + var tooltipWarningLogged; + each(mappingResult, function (resultItem, index) { + var componentModel = resultItem.existing; + var newCmptOption = resultItem.newOption; + + if (!newCmptOption) { + if (componentModel) { + // Consider where is no new option and should be merged using {}, + // see removeEdgeAndAdd in topologicalTravel and + // ComponentModel.getAllClassMainTypes. + componentModel.mergeOption({}, this); + componentModel.optionUpdated({}, false); + } // If no both `resultItem.exist` and `resultItem.option`, + // either it is in `replaceMerge` and not matched by any id, + // or it has been removed in previous `replaceMerge` and left a "hole" in this component index. + + } else { + var isSeriesType = mainType === 'series'; + var ComponentModelClass = ComponentModel.getClass(mainType, resultItem.keyInfo.subType, !isSeriesType // Give a more detailed warn later if series don't exists + ); + + if (!ComponentModelClass) { + if ("development" !== 'production') { + var subType = resultItem.keyInfo.subType; + var seriesImportName = BUILTIN_CHARTS_MAP[subType]; + + if (!componetsMissingLogPrinted[subType]) { + componetsMissingLogPrinted[subType] = true; + + if (seriesImportName) { + error("Series " + subType + " is used but not imported.\nimport { " + seriesImportName + " } from 'echarts/charts';\necharts.use([" + seriesImportName + "]);"); + } else { + error("Unkown series " + subType); + } + } + } + + return; + } // TODO Before multiple tooltips get supported, we do this check to avoid unexpected exception. + + + if (mainType === 'tooltip') { + if (tooltipExists) { + if ("development" !== 'production') { + if (!tooltipWarningLogged) { + warn('Currently only one tooltip component is allowed.'); + tooltipWarningLogged = true; + } + } + + return; + } + + tooltipExists = true; + } + + if (componentModel && componentModel.constructor === ComponentModelClass) { + componentModel.name = resultItem.keyInfo.name; // componentModel.settingTask && componentModel.settingTask.dirty(); + + componentModel.mergeOption(newCmptOption, this); + componentModel.optionUpdated(newCmptOption, false); + } else { + // PENDING Global as parent ? + var extraOpt = extend({ + componentIndex: index + }, resultItem.keyInfo); + componentModel = new ComponentModelClass(newCmptOption, this, this, extraOpt); // Assign `keyInfo` + + extend(componentModel, extraOpt); + + if (resultItem.brandNew) { + componentModel.__requireNewView = true; + } + + componentModel.init(newCmptOption, this, this); // Call optionUpdated after init. + // newCmptOption has been used as componentModel.option + // and may be merged with theme and default, so pass null + // to avoid confusion. + + componentModel.optionUpdated(null, true); + } + } + + if (componentModel) { + optionsByMainType.push(componentModel.option); + cmptsByMainType.push(componentModel); + cmptsCountByMainType++; + } else { + // Always do assign to avoid elided item in array. + optionsByMainType.push(void 0); + cmptsByMainType.push(void 0); + } + }, this); + option[mainType] = optionsByMainType; + componentsMap.set(mainType, cmptsByMainType); + componentsCount.set(mainType, cmptsCountByMainType); // Backup series for filtering. + + if (mainType === 'series') { + reCreateSeriesIndices(this); + } + } // If no series declared, ensure `_seriesIndices` initialized. + + + if (!this._seriesIndices) { + reCreateSeriesIndices(this); + } + }; + /** + * Get option for output (cloned option and inner info removed) + */ + + + GlobalModel.prototype.getOption = function () { + var option = clone(this.option); + each(option, function (optInMainType, mainType) { + if (ComponentModel.hasClass(mainType)) { + var opts = normalizeToArray(optInMainType); // Inner cmpts need to be removed. + // Inner cmpts might not be at last since ec5.0, but still + // compatible for users: if inner cmpt at last, splice the returned array. + + var realLen = opts.length; + var metNonInner = false; + + for (var i = realLen - 1; i >= 0; i--) { + // Remove options with inner id. + if (opts[i] && !isComponentIdInternal(opts[i])) { + metNonInner = true; + } else { + opts[i] = null; + !metNonInner && realLen--; + } + } + + opts.length = realLen; + option[mainType] = opts; + } + }); + delete option[OPTION_INNER_KEY]; + return option; + }; + + GlobalModel.prototype.getTheme = function () { + return this._theme; + }; + + GlobalModel.prototype.getLocaleModel = function () { + return this._locale; + }; + + GlobalModel.prototype.setUpdatePayload = function (payload) { + this._payload = payload; + }; + + GlobalModel.prototype.getUpdatePayload = function () { + return this._payload; + }; + /** + * @param idx If not specified, return the first one. + */ + + + GlobalModel.prototype.getComponent = function (mainType, idx) { + var list = this._componentsMap.get(mainType); + + if (list) { + var cmpt = list[idx || 0]; + + if (cmpt) { + return cmpt; + } else if (idx == null) { + for (var i = 0; i < list.length; i++) { + if (list[i]) { + return list[i]; + } + } + } + } + }; + /** + * @return Never be null/undefined. + */ + + + GlobalModel.prototype.queryComponents = function (condition) { + var mainType = condition.mainType; + + if (!mainType) { + return []; + } + + var index = condition.index; + var id = condition.id; + var name = condition.name; + + var cmpts = this._componentsMap.get(mainType); + + if (!cmpts || !cmpts.length) { + return []; + } + + var result; + + if (index != null) { + result = []; + each(normalizeToArray(index), function (idx) { + cmpts[idx] && result.push(cmpts[idx]); + }); + } else if (id != null) { + result = queryByIdOrName('id', id, cmpts); + } else if (name != null) { + result = queryByIdOrName('name', name, cmpts); + } else { + // Return all non-empty components in that mainType + result = filter(cmpts, function (cmpt) { + return !!cmpt; + }); + } + + return filterBySubType(result, condition); + }; + /** + * The interface is different from queryComponents, + * which is convenient for inner usage. + * + * @usage + * let result = findComponents( + * {mainType: 'dataZoom', query: {dataZoomId: 'abc'}} + * ); + * let result = findComponents( + * {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}} + * ); + * let result = findComponents( + * {mainType: 'series', + * filter: function (model, index) {...}} + * ); + * // result like [component0, componnet1, ...] + */ + + + GlobalModel.prototype.findComponents = function (condition) { + var query = condition.query; + var mainType = condition.mainType; + var queryCond = getQueryCond(query); + var result = queryCond ? this.queryComponents(queryCond) // Retrieve all non-empty components. + : filter(this._componentsMap.get(mainType), function (cmpt) { + return !!cmpt; + }); + return doFilter(filterBySubType(result, condition)); + + function getQueryCond(q) { + var indexAttr = mainType + 'Index'; + var idAttr = mainType + 'Id'; + var nameAttr = mainType + 'Name'; + return q && (q[indexAttr] != null || q[idAttr] != null || q[nameAttr] != null) ? { + mainType: mainType, + // subType will be filtered finally. + index: q[indexAttr], + id: q[idAttr], + name: q[nameAttr] + } : null; + } + + function doFilter(res) { + return condition.filter ? filter(res, condition.filter) : res; + } + }; + + GlobalModel.prototype.eachComponent = function (mainType, cb, context) { + var componentsMap = this._componentsMap; + + if (isFunction(mainType)) { + var ctxForAll_1 = cb; + var cbForAll_1 = mainType; + componentsMap.each(function (cmpts, componentType) { + for (var i = 0; cmpts && i < cmpts.length; i++) { + var cmpt = cmpts[i]; + cmpt && cbForAll_1.call(ctxForAll_1, componentType, cmpt, cmpt.componentIndex); + } + }); + } else { + var cmpts = isString(mainType) ? componentsMap.get(mainType) : isObject(mainType) ? this.findComponents(mainType) : null; + + for (var i = 0; cmpts && i < cmpts.length; i++) { + var cmpt = cmpts[i]; + cmpt && cb.call(context, cmpt, cmpt.componentIndex); + } + } + }; + /** + * Get series list before filtered by name. + */ + + + GlobalModel.prototype.getSeriesByName = function (name) { + var nameStr = convertOptionIdName(name, null); + return filter(this._componentsMap.get('series'), function (oneSeries) { + return !!oneSeries && nameStr != null && oneSeries.name === nameStr; + }); + }; + /** + * Get series list before filtered by index. + */ + + + GlobalModel.prototype.getSeriesByIndex = function (seriesIndex) { + return this._componentsMap.get('series')[seriesIndex]; + }; + /** + * Get series list before filtered by type. + * FIXME: rename to getRawSeriesByType? + */ + + + GlobalModel.prototype.getSeriesByType = function (subType) { + return filter(this._componentsMap.get('series'), function (oneSeries) { + return !!oneSeries && oneSeries.subType === subType; + }); + }; + /** + * Get all series before filtered. + */ + + + GlobalModel.prototype.getSeries = function () { + return filter(this._componentsMap.get('series'), function (oneSeries) { + return !!oneSeries; + }); + }; + /** + * Count series before filtered. + */ + + + GlobalModel.prototype.getSeriesCount = function () { + return this._componentsCount.get('series'); + }; + /** + * After filtering, series may be different + * frome raw series. + */ + + + GlobalModel.prototype.eachSeries = function (cb, context) { + assertSeriesInitialized(this); + each(this._seriesIndices, function (rawSeriesIndex) { + var series = this._componentsMap.get('series')[rawSeriesIndex]; + + cb.call(context, series, rawSeriesIndex); + }, this); + }; + /** + * Iterate raw series before filtered. + * + * @param {Function} cb + * @param {*} context + */ + + + GlobalModel.prototype.eachRawSeries = function (cb, context) { + each(this._componentsMap.get('series'), function (series) { + series && cb.call(context, series, series.componentIndex); + }); + }; + /** + * After filtering, series may be different. + * frome raw series. + */ + + + GlobalModel.prototype.eachSeriesByType = function (subType, cb, context) { + assertSeriesInitialized(this); + each(this._seriesIndices, function (rawSeriesIndex) { + var series = this._componentsMap.get('series')[rawSeriesIndex]; + + if (series.subType === subType) { + cb.call(context, series, rawSeriesIndex); + } + }, this); + }; + /** + * Iterate raw series before filtered of given type. + */ + + + GlobalModel.prototype.eachRawSeriesByType = function (subType, cb, context) { + return each(this.getSeriesByType(subType), cb, context); + }; + + GlobalModel.prototype.isSeriesFiltered = function (seriesModel) { + assertSeriesInitialized(this); + return this._seriesIndicesMap.get(seriesModel.componentIndex) == null; + }; + + GlobalModel.prototype.getCurrentSeriesIndices = function () { + return (this._seriesIndices || []).slice(); + }; + + GlobalModel.prototype.filterSeries = function (cb, context) { + assertSeriesInitialized(this); + var newSeriesIndices = []; + each(this._seriesIndices, function (seriesRawIdx) { + var series = this._componentsMap.get('series')[seriesRawIdx]; + + cb.call(context, series, seriesRawIdx) && newSeriesIndices.push(seriesRawIdx); + }, this); + this._seriesIndices = newSeriesIndices; + this._seriesIndicesMap = createHashMap(newSeriesIndices); + }; + + GlobalModel.prototype.restoreData = function (payload) { + reCreateSeriesIndices(this); + var componentsMap = this._componentsMap; + var componentTypes = []; + componentsMap.each(function (components, componentType) { + if (ComponentModel.hasClass(componentType)) { + componentTypes.push(componentType); + } + }); + ComponentModel.topologicalTravel(componentTypes, ComponentModel.getAllClassMainTypes(), function (componentType) { + each(componentsMap.get(componentType), function (component) { + if (component && (componentType !== 'series' || !isNotTargetSeries(component, payload))) { + component.restoreData(); + } + }); + }); + }; + + GlobalModel.internalField = function () { + reCreateSeriesIndices = function (ecModel) { + var seriesIndices = ecModel._seriesIndices = []; + each(ecModel._componentsMap.get('series'), function (series) { + // series may have been removed by `replaceMerge`. + series && seriesIndices.push(series.componentIndex); + }); + ecModel._seriesIndicesMap = createHashMap(seriesIndices); + }; + + assertSeriesInitialized = function (ecModel) { + // Components that use _seriesIndices should depends on series component, + // which make sure that their initialization is after series. + if ("development" !== 'production') { + if (!ecModel._seriesIndices) { + throw new Error('Option should contains series.'); + } + } + }; + + initBase = function (ecModel, baseOption) { + // Using OPTION_INNER_KEY to mark that this option can not be used outside, + // i.e. `chart.setOption(chart.getModel().option);` is forbiden. + ecModel.option = {}; + ecModel.option[OPTION_INNER_KEY] = OPTION_INNER_VALUE; // Init with series: [], in case of calling findSeries method + // before series initialized. + + ecModel._componentsMap = createHashMap({ + series: [] + }); + ecModel._componentsCount = createHashMap(); // If user spefied `option.aria`, aria will be enable. This detection should be + // performed before theme and globalDefault merge. + + var airaOption = baseOption.aria; + + if (isObject(airaOption) && airaOption.enabled == null) { + airaOption.enabled = true; + } + + mergeTheme(baseOption, ecModel._theme.option); // TODO Needs clone when merging to the unexisted property + + merge(baseOption, globalDefault, false); + + ecModel._mergeOption(baseOption, null); + }; + }(); + + return GlobalModel; + }(Model); + + function isNotTargetSeries(seriesModel, payload) { + if (payload) { + var index = payload.seriesIndex; + var id = payload.seriesId; + var name_1 = payload.seriesName; + return index != null && seriesModel.componentIndex !== index || id != null && seriesModel.id !== id || name_1 != null && seriesModel.name !== name_1; + } + } + + function mergeTheme(option, theme) { + // PENDING + // NOT use `colorLayer` in theme if option has `color` + var notMergeColorLayer = option.color && !option.colorLayer; + each(theme, function (themeItem, name) { + if (name === 'colorLayer' && notMergeColorLayer) { + return; + } // If it is component model mainType, the model handles that merge later. + // otherwise, merge them here. + + + if (!ComponentModel.hasClass(name)) { + if (typeof themeItem === 'object') { + option[name] = !option[name] ? clone(themeItem) : merge(option[name], themeItem, false); + } else { + if (option[name] == null) { + option[name] = themeItem; + } + } + } + }); + } + + function queryByIdOrName(attr, idOrName, cmpts) { + // Here is a break from echarts4: string and number are + // treated as equal. + if (isArray(idOrName)) { + var keyMap_1 = createHashMap(); + each(idOrName, function (idOrNameItem) { + if (idOrNameItem != null) { + var idName = convertOptionIdName(idOrNameItem, null); + idName != null && keyMap_1.set(idOrNameItem, true); + } + }); + return filter(cmpts, function (cmpt) { + return cmpt && keyMap_1.get(cmpt[attr]); + }); + } else { + var idName_1 = convertOptionIdName(idOrName, null); + return filter(cmpts, function (cmpt) { + return cmpt && idName_1 != null && cmpt[attr] === idName_1; + }); + } + } + + function filterBySubType(components, condition) { + // Using hasOwnProperty for restrict. Consider + // subType is undefined in user payload. + return condition.hasOwnProperty('subType') ? filter(components, function (cmpt) { + return cmpt && cmpt.subType === condition.subType; + }) : components; + } + + function normalizeSetOptionInput(opts) { + var replaceMergeMainTypeMap = createHashMap(); + opts && each(normalizeToArray(opts.replaceMerge), function (mainType) { + if ("development" !== 'production') { + assert(ComponentModel.hasClass(mainType), '"' + mainType + '" is not valid component main type in "replaceMerge"'); + } + + replaceMergeMainTypeMap.set(mainType, true); + }); + return { + replaceMergeMainTypeMap: replaceMergeMainTypeMap + }; + } + + mixin(GlobalModel, PaletteMixin); + + var availableMethods = ['getDom', 'getZr', 'getWidth', 'getHeight', 'getDevicePixelRatio', 'dispatchAction', 'isSSR', 'isDisposed', 'on', 'off', 'getDataURL', 'getConnectedDataURL', // 'getModel', + 'getOption', // 'getViewOfComponentModel', + // 'getViewOfSeriesModel', + 'getId', 'updateLabelLayout']; + + var ExtensionAPI = + /** @class */ + function () { + function ExtensionAPI(ecInstance) { + each(availableMethods, function (methodName) { + this[methodName] = bind(ecInstance[methodName], ecInstance); + }, this); + } + + return ExtensionAPI; + }(); + + var coordinateSystemCreators = {}; + + var CoordinateSystemManager = + /** @class */ + function () { + function CoordinateSystemManager() { + this._coordinateSystems = []; + } + + CoordinateSystemManager.prototype.create = function (ecModel, api) { + var coordinateSystems = []; + each(coordinateSystemCreators, function (creater, type) { + var list = creater.create(ecModel, api); + coordinateSystems = coordinateSystems.concat(list || []); + }); + this._coordinateSystems = coordinateSystems; + }; + + CoordinateSystemManager.prototype.update = function (ecModel, api) { + each(this._coordinateSystems, function (coordSys) { + coordSys.update && coordSys.update(ecModel, api); + }); + }; + + CoordinateSystemManager.prototype.getCoordinateSystems = function () { + return this._coordinateSystems.slice(); + }; + + CoordinateSystemManager.register = function (type, creator) { + coordinateSystemCreators[type] = creator; + }; + + CoordinateSystemManager.get = function (type) { + return coordinateSystemCreators[type]; + }; + + return CoordinateSystemManager; + }(); + + var QUERY_REG = /^(min|max)?(.+)$/; // Key: mainType + // type FakeComponentsMap = HashMap<(MappingExistingItem & { subType: string })[]>; + + /** + * TERM EXPLANATIONS: + * See `ECOption` and `ECUnitOption` in `src/util/types.ts`. + */ + + var OptionManager = + /** @class */ + function () { + // timeline.notMerge is not supported in ec3. Firstly there is rearly + // case that notMerge is needed. Secondly supporting 'notMerge' requires + // rawOption cloned and backuped when timeline changed, which does no + // good to performance. What's more, that both timeline and setOption + // method supply 'notMerge' brings complex and some problems. + // Consider this case: + // (step1) chart.setOption({timeline: {notMerge: false}, ...}, false); + // (step2) chart.setOption({timeline: {notMerge: true}, ...}, false); + function OptionManager(api) { + this._timelineOptions = []; + this._mediaList = []; + /** + * -1, means default. + * empty means no media. + */ + + this._currentMediaIndices = []; + this._api = api; + } + + OptionManager.prototype.setOption = function (rawOption, optionPreprocessorFuncs, opt) { + if (rawOption) { + // That set dat primitive is dangerous if user reuse the data when setOption again. + each(normalizeToArray(rawOption.series), function (series) { + series && series.data && isTypedArray(series.data) && setAsPrimitive(series.data); + }); + each(normalizeToArray(rawOption.dataset), function (dataset) { + dataset && dataset.source && isTypedArray(dataset.source) && setAsPrimitive(dataset.source); + }); + } // Caution: some series modify option data, if do not clone, + // it should ensure that the repeat modify correctly + // (create a new object when modify itself). + + + rawOption = clone(rawOption); // FIXME + // If some property is set in timeline options or media option but + // not set in baseOption, a warning should be given. + + var optionBackup = this._optionBackup; + var newParsedOption = parseRawOption(rawOption, optionPreprocessorFuncs, !optionBackup); + this._newBaseOption = newParsedOption.baseOption; // For setOption at second time (using merge mode); + + if (optionBackup) { + // FIXME + // the restore merge solution is essentially incorrect. + // the mapping can not be 100% consistent with ecModel, which probably brings + // potential bug! + // The first merge is delayed, becuase in most cases, users do not call `setOption` twice. + // let fakeCmptsMap = this._fakeCmptsMap; + // if (!fakeCmptsMap) { + // fakeCmptsMap = this._fakeCmptsMap = createHashMap(); + // mergeToBackupOption(fakeCmptsMap, null, optionBackup.baseOption, null); + // } + // mergeToBackupOption( + // fakeCmptsMap, optionBackup.baseOption, newParsedOption.baseOption, opt + // ); + // For simplicity, timeline options and media options do not support merge, + // that is, if you `setOption` twice and both has timeline options, the latter + // timeline opitons will not be merged to the formers, but just substitude them. + if (newParsedOption.timelineOptions.length) { + optionBackup.timelineOptions = newParsedOption.timelineOptions; + } + + if (newParsedOption.mediaList.length) { + optionBackup.mediaList = newParsedOption.mediaList; + } + + if (newParsedOption.mediaDefault) { + optionBackup.mediaDefault = newParsedOption.mediaDefault; + } + } else { + this._optionBackup = newParsedOption; + } + }; + + OptionManager.prototype.mountOption = function (isRecreate) { + var optionBackup = this._optionBackup; + this._timelineOptions = optionBackup.timelineOptions; + this._mediaList = optionBackup.mediaList; + this._mediaDefault = optionBackup.mediaDefault; + this._currentMediaIndices = []; + return clone(isRecreate // this._optionBackup.baseOption, which is created at the first `setOption` + // called, and is merged into every new option by inner method `mergeToBackupOption` + // each time `setOption` called, can be only used in `isRecreate`, because + // its reliability is under suspicion. In other cases option merge is + // performed by `model.mergeOption`. + ? optionBackup.baseOption : this._newBaseOption); + }; + + OptionManager.prototype.getTimelineOption = function (ecModel) { + var option; + var timelineOptions = this._timelineOptions; + + if (timelineOptions.length) { + // getTimelineOption can only be called after ecModel inited, + // so we can get currentIndex from timelineModel. + var timelineModel = ecModel.getComponent('timeline'); + + if (timelineModel) { + option = clone( // FIXME:TS as TimelineModel or quivlant interface + timelineOptions[timelineModel.getCurrentIndex()]); + } + } + + return option; + }; + + OptionManager.prototype.getMediaOption = function (ecModel) { + var ecWidth = this._api.getWidth(); + + var ecHeight = this._api.getHeight(); + + var mediaList = this._mediaList; + var mediaDefault = this._mediaDefault; + var indices = []; + var result = []; // No media defined. + + if (!mediaList.length && !mediaDefault) { + return result; + } // Multi media may be applied, the latter defined media has higher priority. + + + for (var i = 0, len = mediaList.length; i < len; i++) { + if (applyMediaQuery(mediaList[i].query, ecWidth, ecHeight)) { + indices.push(i); + } + } // FIXME + // Whether mediaDefault should force users to provide? Otherwise + // the change by media query can not be recorvered. + + + if (!indices.length && mediaDefault) { + indices = [-1]; + } + + if (indices.length && !indicesEquals(indices, this._currentMediaIndices)) { + result = map(indices, function (index) { + return clone(index === -1 ? mediaDefault.option : mediaList[index].option); + }); + } // Otherwise return nothing. + + + this._currentMediaIndices = indices; + return result; + }; + + return OptionManager; + }(); + /** + * [RAW_OPTION_PATTERNS] + * (Note: "series: []" represents all other props in `ECUnitOption`) + * + * (1) No prop "baseOption" declared: + * Root option is used as "baseOption" (except prop "options" and "media"). + * ```js + * option = { + * series: [], + * timeline: {}, + * options: [], + * }; + * option = { + * series: [], + * media: {}, + * }; + * option = { + * series: [], + * timeline: {}, + * options: [], + * media: {}, + * } + * ``` + * + * (2) Prop "baseOption" declared: + * If "baseOption" declared, `ECUnitOption` props can only be declared + * inside "baseOption" except prop "timeline" (compat ec2). + * ```js + * option = { + * baseOption: { + * timeline: {}, + * series: [], + * }, + * options: [] + * }; + * option = { + * baseOption: { + * series: [], + * }, + * media: [] + * }; + * option = { + * baseOption: { + * timeline: {}, + * series: [], + * }, + * options: [] + * media: [] + * }; + * option = { + * // ec3 compat ec2: allow (only) `timeline` declared + * // outside baseOption. Keep this setting for compat. + * timeline: {}, + * baseOption: { + * series: [], + * }, + * options: [], + * media: [] + * }; + * ``` + */ + + + function parseRawOption( // `rawOption` May be modified + rawOption, optionPreprocessorFuncs, isNew) { + var mediaList = []; + var mediaDefault; + var baseOption; + var declaredBaseOption = rawOption.baseOption; // Compatible with ec2, [RAW_OPTION_PATTERNS] above. + + var timelineOnRoot = rawOption.timeline; + var timelineOptionsOnRoot = rawOption.options; + var mediaOnRoot = rawOption.media; + var hasMedia = !!rawOption.media; + var hasTimeline = !!(timelineOptionsOnRoot || timelineOnRoot || declaredBaseOption && declaredBaseOption.timeline); + + if (declaredBaseOption) { + baseOption = declaredBaseOption; // For merge option. + + if (!baseOption.timeline) { + baseOption.timeline = timelineOnRoot; + } + } // For convenience, enable to use the root option as the `baseOption`: + // `{ ...normalOptionProps, media: [{ ... }, { ... }] }` + else { + if (hasTimeline || hasMedia) { + rawOption.options = rawOption.media = null; + } + + baseOption = rawOption; + } + + if (hasMedia) { + if (isArray(mediaOnRoot)) { + each(mediaOnRoot, function (singleMedia) { + if ("development" !== 'production') { + // Real case of wrong config. + if (singleMedia && !singleMedia.option && isObject(singleMedia.query) && isObject(singleMedia.query.option)) { + error('Illegal media option. Must be like { media: [ { query: {}, option: {} } ] }'); + } + } + + if (singleMedia && singleMedia.option) { + if (singleMedia.query) { + mediaList.push(singleMedia); + } else if (!mediaDefault) { + // Use the first media default. + mediaDefault = singleMedia; + } + } + }); + } else { + if ("development" !== 'production') { + // Real case of wrong config. + error('Illegal media option. Must be an array. Like { media: [ {...}, {...} ] }'); + } + } + } + + doPreprocess(baseOption); + each(timelineOptionsOnRoot, function (option) { + return doPreprocess(option); + }); + each(mediaList, function (media) { + return doPreprocess(media.option); + }); + + function doPreprocess(option) { + each(optionPreprocessorFuncs, function (preProcess) { + preProcess(option, isNew); + }); + } + + return { + baseOption: baseOption, + timelineOptions: timelineOptionsOnRoot || [], + mediaDefault: mediaDefault, + mediaList: mediaList + }; + } + /** + * @see + * Support: width, height, aspectRatio + * Can use max or min as prefix. + */ + + + function applyMediaQuery(query, ecWidth, ecHeight) { + var realMap = { + width: ecWidth, + height: ecHeight, + aspectratio: ecWidth / ecHeight // lowser case for convenientce. + + }; + var applicatable = true; + each(query, function (value, attr) { + var matched = attr.match(QUERY_REG); + + if (!matched || !matched[1] || !matched[2]) { + return; + } + + var operator = matched[1]; + var realAttr = matched[2].toLowerCase(); + + if (!compare(realMap[realAttr], value, operator)) { + applicatable = false; + } + }); + return applicatable; + } + + function compare(real, expect, operator) { + if (operator === 'min') { + return real >= expect; + } else if (operator === 'max') { + return real <= expect; + } else { + // Equals + return real === expect; + } + } + + function indicesEquals(indices1, indices2) { + // indices is always order by asc and has only finite number. + return indices1.join(',') === indices2.join(','); + } + + var each$2 = each; + var isObject$1 = isObject; + var POSSIBLE_STYLES = ['areaStyle', 'lineStyle', 'nodeStyle', 'linkStyle', 'chordStyle', 'label', 'labelLine']; + + function compatEC2ItemStyle(opt) { + var itemStyleOpt = opt && opt.itemStyle; + + if (!itemStyleOpt) { + return; + } + + for (var i = 0, len = POSSIBLE_STYLES.length; i < len; i++) { + var styleName = POSSIBLE_STYLES[i]; + var normalItemStyleOpt = itemStyleOpt.normal; + var emphasisItemStyleOpt = itemStyleOpt.emphasis; + + if (normalItemStyleOpt && normalItemStyleOpt[styleName]) { + if ("development" !== 'production') { + deprecateReplaceLog("itemStyle.normal." + styleName, styleName); + } + + opt[styleName] = opt[styleName] || {}; + + if (!opt[styleName].normal) { + opt[styleName].normal = normalItemStyleOpt[styleName]; + } else { + merge(opt[styleName].normal, normalItemStyleOpt[styleName]); + } + + normalItemStyleOpt[styleName] = null; + } + + if (emphasisItemStyleOpt && emphasisItemStyleOpt[styleName]) { + if ("development" !== 'production') { + deprecateReplaceLog("itemStyle.emphasis." + styleName, "emphasis." + styleName); + } + + opt[styleName] = opt[styleName] || {}; + + if (!opt[styleName].emphasis) { + opt[styleName].emphasis = emphasisItemStyleOpt[styleName]; + } else { + merge(opt[styleName].emphasis, emphasisItemStyleOpt[styleName]); + } + + emphasisItemStyleOpt[styleName] = null; + } + } + } + + function convertNormalEmphasis(opt, optType, useExtend) { + if (opt && opt[optType] && (opt[optType].normal || opt[optType].emphasis)) { + var normalOpt = opt[optType].normal; + var emphasisOpt = opt[optType].emphasis; + + if (normalOpt) { + if ("development" !== 'production') { + // eslint-disable-next-line max-len + deprecateLog("'normal' hierarchy in " + optType + " has been removed since 4.0. All style properties are configured in " + optType + " directly now."); + } // Timeline controlStyle has other properties besides normal and emphasis + + + if (useExtend) { + opt[optType].normal = opt[optType].emphasis = null; + defaults(opt[optType], normalOpt); + } else { + opt[optType] = normalOpt; + } + } + + if (emphasisOpt) { + if ("development" !== 'production') { + deprecateLog(optType + ".emphasis has been changed to emphasis." + optType + " since 4.0"); + } + + opt.emphasis = opt.emphasis || {}; + opt.emphasis[optType] = emphasisOpt; // Also compat the case user mix the style and focus together in ec3 style + // for example: { itemStyle: { normal: {}, emphasis: {focus, shadowBlur} } } + + if (emphasisOpt.focus) { + opt.emphasis.focus = emphasisOpt.focus; + } + + if (emphasisOpt.blurScope) { + opt.emphasis.blurScope = emphasisOpt.blurScope; + } + } + } + } + + function removeEC3NormalStatus(opt) { + convertNormalEmphasis(opt, 'itemStyle'); + convertNormalEmphasis(opt, 'lineStyle'); + convertNormalEmphasis(opt, 'areaStyle'); + convertNormalEmphasis(opt, 'label'); + convertNormalEmphasis(opt, 'labelLine'); // treemap + + convertNormalEmphasis(opt, 'upperLabel'); // graph + + convertNormalEmphasis(opt, 'edgeLabel'); + } + + function compatTextStyle(opt, propName) { + // Check whether is not object (string\null\undefined ...) + var labelOptSingle = isObject$1(opt) && opt[propName]; + var textStyle = isObject$1(labelOptSingle) && labelOptSingle.textStyle; + + if (textStyle) { + if ("development" !== 'production') { + // eslint-disable-next-line max-len + deprecateLog("textStyle hierarchy in " + propName + " has been removed since 4.0. All textStyle properties are configured in " + propName + " directly now."); + } + + for (var i = 0, len = TEXT_STYLE_OPTIONS.length; i < len; i++) { + var textPropName = TEXT_STYLE_OPTIONS[i]; + + if (textStyle.hasOwnProperty(textPropName)) { + labelOptSingle[textPropName] = textStyle[textPropName]; + } + } + } + } + + function compatEC3CommonStyles(opt) { + if (opt) { + removeEC3NormalStatus(opt); + compatTextStyle(opt, 'label'); + opt.emphasis && compatTextStyle(opt.emphasis, 'label'); + } + } + + function processSeries(seriesOpt) { + if (!isObject$1(seriesOpt)) { + return; + } + + compatEC2ItemStyle(seriesOpt); + removeEC3NormalStatus(seriesOpt); + compatTextStyle(seriesOpt, 'label'); // treemap + + compatTextStyle(seriesOpt, 'upperLabel'); // graph + + compatTextStyle(seriesOpt, 'edgeLabel'); + + if (seriesOpt.emphasis) { + compatTextStyle(seriesOpt.emphasis, 'label'); // treemap + + compatTextStyle(seriesOpt.emphasis, 'upperLabel'); // graph + + compatTextStyle(seriesOpt.emphasis, 'edgeLabel'); + } + + var markPoint = seriesOpt.markPoint; + + if (markPoint) { + compatEC2ItemStyle(markPoint); + compatEC3CommonStyles(markPoint); + } + + var markLine = seriesOpt.markLine; + + if (markLine) { + compatEC2ItemStyle(markLine); + compatEC3CommonStyles(markLine); + } + + var markArea = seriesOpt.markArea; + + if (markArea) { + compatEC3CommonStyles(markArea); + } + + var data = seriesOpt.data; // Break with ec3: if `setOption` again, there may be no `type` in option, + // then the backward compat based on option type will not be performed. + + if (seriesOpt.type === 'graph') { + data = data || seriesOpt.nodes; + var edgeData = seriesOpt.links || seriesOpt.edges; + + if (edgeData && !isTypedArray(edgeData)) { + for (var i = 0; i < edgeData.length; i++) { + compatEC3CommonStyles(edgeData[i]); + } + } + + each(seriesOpt.categories, function (opt) { + removeEC3NormalStatus(opt); + }); + } + + if (data && !isTypedArray(data)) { + for (var i = 0; i < data.length; i++) { + compatEC3CommonStyles(data[i]); + } + } // mark point data + + + markPoint = seriesOpt.markPoint; + + if (markPoint && markPoint.data) { + var mpData = markPoint.data; + + for (var i = 0; i < mpData.length; i++) { + compatEC3CommonStyles(mpData[i]); + } + } // mark line data + + + markLine = seriesOpt.markLine; + + if (markLine && markLine.data) { + var mlData = markLine.data; + + for (var i = 0; i < mlData.length; i++) { + if (isArray(mlData[i])) { + compatEC3CommonStyles(mlData[i][0]); + compatEC3CommonStyles(mlData[i][1]); + } else { + compatEC3CommonStyles(mlData[i]); + } + } + } // Series + + + if (seriesOpt.type === 'gauge') { + compatTextStyle(seriesOpt, 'axisLabel'); + compatTextStyle(seriesOpt, 'title'); + compatTextStyle(seriesOpt, 'detail'); + } else if (seriesOpt.type === 'treemap') { + convertNormalEmphasis(seriesOpt.breadcrumb, 'itemStyle'); + each(seriesOpt.levels, function (opt) { + removeEC3NormalStatus(opt); + }); + } else if (seriesOpt.type === 'tree') { + removeEC3NormalStatus(seriesOpt.leaves); + } // sunburst starts from ec4, so it does not need to compat levels. + + } + + function toArr(o) { + return isArray(o) ? o : o ? [o] : []; + } + + function toObj(o) { + return (isArray(o) ? o[0] : o) || {}; + } + + function globalCompatStyle(option, isTheme) { + each$2(toArr(option.series), function (seriesOpt) { + isObject$1(seriesOpt) && processSeries(seriesOpt); + }); + var axes = ['xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'parallelAxis', 'radar']; + isTheme && axes.push('valueAxis', 'categoryAxis', 'logAxis', 'timeAxis'); + each$2(axes, function (axisName) { + each$2(toArr(option[axisName]), function (axisOpt) { + if (axisOpt) { + compatTextStyle(axisOpt, 'axisLabel'); + compatTextStyle(axisOpt.axisPointer, 'label'); + } + }); + }); + each$2(toArr(option.parallel), function (parallelOpt) { + var parallelAxisDefault = parallelOpt && parallelOpt.parallelAxisDefault; + compatTextStyle(parallelAxisDefault, 'axisLabel'); + compatTextStyle(parallelAxisDefault && parallelAxisDefault.axisPointer, 'label'); + }); + each$2(toArr(option.calendar), function (calendarOpt) { + convertNormalEmphasis(calendarOpt, 'itemStyle'); + compatTextStyle(calendarOpt, 'dayLabel'); + compatTextStyle(calendarOpt, 'monthLabel'); + compatTextStyle(calendarOpt, 'yearLabel'); + }); // radar.name.textStyle + + each$2(toArr(option.radar), function (radarOpt) { + compatTextStyle(radarOpt, 'name'); // Use axisName instead of name because component has name property + + if (radarOpt.name && radarOpt.axisName == null) { + radarOpt.axisName = radarOpt.name; + delete radarOpt.name; + + if ("development" !== 'production') { + deprecateLog('name property in radar component has been changed to axisName'); + } + } + + if (radarOpt.nameGap != null && radarOpt.axisNameGap == null) { + radarOpt.axisNameGap = radarOpt.nameGap; + delete radarOpt.nameGap; + + if ("development" !== 'production') { + deprecateLog('nameGap property in radar component has been changed to axisNameGap'); + } + } + + if ("development" !== 'production') { + each$2(radarOpt.indicator, function (indicatorOpt) { + if (indicatorOpt.text) { + deprecateReplaceLog('text', 'name', 'radar.indicator'); + } + }); + } + }); + each$2(toArr(option.geo), function (geoOpt) { + if (isObject$1(geoOpt)) { + compatEC3CommonStyles(geoOpt); + each$2(toArr(geoOpt.regions), function (regionObj) { + compatEC3CommonStyles(regionObj); + }); + } + }); + each$2(toArr(option.timeline), function (timelineOpt) { + compatEC3CommonStyles(timelineOpt); + convertNormalEmphasis(timelineOpt, 'label'); + convertNormalEmphasis(timelineOpt, 'itemStyle'); + convertNormalEmphasis(timelineOpt, 'controlStyle', true); + var data = timelineOpt.data; + isArray(data) && each(data, function (item) { + if (isObject(item)) { + convertNormalEmphasis(item, 'label'); + convertNormalEmphasis(item, 'itemStyle'); + } + }); + }); + each$2(toArr(option.toolbox), function (toolboxOpt) { + convertNormalEmphasis(toolboxOpt, 'iconStyle'); + each$2(toolboxOpt.feature, function (featureOpt) { + convertNormalEmphasis(featureOpt, 'iconStyle'); + }); + }); + compatTextStyle(toObj(option.axisPointer), 'label'); + compatTextStyle(toObj(option.tooltip).axisPointer, 'label'); // Clean logs + // storedLogs = {}; + } + + function get(opt, path) { + var pathArr = path.split(','); + var obj = opt; + + for (var i = 0; i < pathArr.length; i++) { + obj = obj && obj[pathArr[i]]; + + if (obj == null) { + break; + } + } + + return obj; + } + + function set$1(opt, path, val, overwrite) { + var pathArr = path.split(','); + var obj = opt; + var key; + var i = 0; + + for (; i < pathArr.length - 1; i++) { + key = pathArr[i]; + + if (obj[key] == null) { + obj[key] = {}; + } + + obj = obj[key]; + } + + if (overwrite || obj[pathArr[i]] == null) { + obj[pathArr[i]] = val; + } + } + + function compatLayoutProperties(option) { + option && each(LAYOUT_PROPERTIES, function (prop) { + if (prop[0] in option && !(prop[1] in option)) { + option[prop[1]] = option[prop[0]]; + } + }); + } + + var LAYOUT_PROPERTIES = [['x', 'left'], ['y', 'top'], ['x2', 'right'], ['y2', 'bottom']]; + var COMPATITABLE_COMPONENTS = ['grid', 'geo', 'parallel', 'legend', 'toolbox', 'title', 'visualMap', 'dataZoom', 'timeline']; + var BAR_ITEM_STYLE_MAP = [['borderRadius', 'barBorderRadius'], ['borderColor', 'barBorderColor'], ['borderWidth', 'barBorderWidth']]; + + function compatBarItemStyle(option) { + var itemStyle = option && option.itemStyle; + + if (itemStyle) { + for (var i = 0; i < BAR_ITEM_STYLE_MAP.length; i++) { + var oldName = BAR_ITEM_STYLE_MAP[i][1]; + var newName = BAR_ITEM_STYLE_MAP[i][0]; + + if (itemStyle[oldName] != null) { + itemStyle[newName] = itemStyle[oldName]; + + if ("development" !== 'production') { + deprecateReplaceLog(oldName, newName); + } + } + } + } + } + + function compatPieLabel(option) { + if (!option) { + return; + } + + if (option.alignTo === 'edge' && option.margin != null && option.edgeDistance == null) { + if ("development" !== 'production') { + deprecateReplaceLog('label.margin', 'label.edgeDistance', 'pie'); + } + + option.edgeDistance = option.margin; + } + } + + function compatSunburstState(option) { + if (!option) { + return; + } + + if (option.downplay && !option.blur) { + option.blur = option.downplay; + + if ("development" !== 'production') { + deprecateReplaceLog('downplay', 'blur', 'sunburst'); + } + } + } + + function compatGraphFocus(option) { + if (!option) { + return; + } + + if (option.focusNodeAdjacency != null) { + option.emphasis = option.emphasis || {}; + + if (option.emphasis.focus == null) { + if ("development" !== 'production') { + deprecateReplaceLog('focusNodeAdjacency', 'emphasis: { focus: \'adjacency\'}', 'graph/sankey'); + } + + option.emphasis.focus = 'adjacency'; + } + } + } + + function traverseTree(data, cb) { + if (data) { + for (var i = 0; i < data.length; i++) { + cb(data[i]); + data[i] && traverseTree(data[i].children, cb); + } + } + } + + function globalBackwardCompat(option, isTheme) { + globalCompatStyle(option, isTheme); // Make sure series array for model initialization. + + option.series = normalizeToArray(option.series); + each(option.series, function (seriesOpt) { + if (!isObject(seriesOpt)) { + return; + } + + var seriesType = seriesOpt.type; + + if (seriesType === 'line') { + if (seriesOpt.clipOverflow != null) { + seriesOpt.clip = seriesOpt.clipOverflow; + + if ("development" !== 'production') { + deprecateReplaceLog('clipOverflow', 'clip', 'line'); + } + } + } else if (seriesType === 'pie' || seriesType === 'gauge') { + if (seriesOpt.clockWise != null) { + seriesOpt.clockwise = seriesOpt.clockWise; + + if ("development" !== 'production') { + deprecateReplaceLog('clockWise', 'clockwise'); + } + } + + compatPieLabel(seriesOpt.label); + var data = seriesOpt.data; + + if (data && !isTypedArray(data)) { + for (var i = 0; i < data.length; i++) { + compatPieLabel(data[i]); + } + } + + if (seriesOpt.hoverOffset != null) { + seriesOpt.emphasis = seriesOpt.emphasis || {}; + + if (seriesOpt.emphasis.scaleSize = null) { + if ("development" !== 'production') { + deprecateReplaceLog('hoverOffset', 'emphasis.scaleSize'); + } + + seriesOpt.emphasis.scaleSize = seriesOpt.hoverOffset; + } + } + } else if (seriesType === 'gauge') { + var pointerColor = get(seriesOpt, 'pointer.color'); + pointerColor != null && set$1(seriesOpt, 'itemStyle.color', pointerColor); + } else if (seriesType === 'bar') { + compatBarItemStyle(seriesOpt); + compatBarItemStyle(seriesOpt.backgroundStyle); + compatBarItemStyle(seriesOpt.emphasis); + var data = seriesOpt.data; + + if (data && !isTypedArray(data)) { + for (var i = 0; i < data.length; i++) { + if (typeof data[i] === 'object') { + compatBarItemStyle(data[i]); + compatBarItemStyle(data[i] && data[i].emphasis); + } + } + } + } else if (seriesType === 'sunburst') { + var highlightPolicy = seriesOpt.highlightPolicy; + + if (highlightPolicy) { + seriesOpt.emphasis = seriesOpt.emphasis || {}; + + if (!seriesOpt.emphasis.focus) { + seriesOpt.emphasis.focus = highlightPolicy; + + if ("development" !== 'production') { + deprecateReplaceLog('highlightPolicy', 'emphasis.focus', 'sunburst'); + } + } + } + + compatSunburstState(seriesOpt); + traverseTree(seriesOpt.data, compatSunburstState); + } else if (seriesType === 'graph' || seriesType === 'sankey') { + compatGraphFocus(seriesOpt); // TODO nodes, edges? + } else if (seriesType === 'map') { + if (seriesOpt.mapType && !seriesOpt.map) { + if ("development" !== 'production') { + deprecateReplaceLog('mapType', 'map', 'map'); + } + + seriesOpt.map = seriesOpt.mapType; + } + + if (seriesOpt.mapLocation) { + if ("development" !== 'production') { + deprecateLog('`mapLocation` is not used anymore.'); + } + + defaults(seriesOpt, seriesOpt.mapLocation); + } + } + + if (seriesOpt.hoverAnimation != null) { + seriesOpt.emphasis = seriesOpt.emphasis || {}; + + if (seriesOpt.emphasis && seriesOpt.emphasis.scale == null) { + if ("development" !== 'production') { + deprecateReplaceLog('hoverAnimation', 'emphasis.scale'); + } + + seriesOpt.emphasis.scale = seriesOpt.hoverAnimation; + } + } + + compatLayoutProperties(seriesOpt); + }); // dataRange has changed to visualMap + + if (option.dataRange) { + option.visualMap = option.dataRange; + } + + each(COMPATITABLE_COMPONENTS, function (componentName) { + var options = option[componentName]; + + if (options) { + if (!isArray(options)) { + options = [options]; + } + + each(options, function (option) { + compatLayoutProperties(option); + }); + } + }); + } + + // data processing stage is blocked in stream. + // See + // (2) Only register once when import repeatly. + // Should be executed after series filtered and before stack calculation. + + function dataStack(ecModel) { + var stackInfoMap = createHashMap(); + ecModel.eachSeries(function (seriesModel) { + var stack = seriesModel.get('stack'); // Compatibal: when `stack` is set as '', do not stack. + + if (stack) { + var stackInfoList = stackInfoMap.get(stack) || stackInfoMap.set(stack, []); + var data = seriesModel.getData(); + var stackInfo = { + // Used for calculate axis extent automatically. + // TODO: Type getCalculationInfo return more specific type? + stackResultDimension: data.getCalculationInfo('stackResultDimension'), + stackedOverDimension: data.getCalculationInfo('stackedOverDimension'), + stackedDimension: data.getCalculationInfo('stackedDimension'), + stackedByDimension: data.getCalculationInfo('stackedByDimension'), + isStackedByIndex: data.getCalculationInfo('isStackedByIndex'), + data: data, + seriesModel: seriesModel + }; // If stacked on axis that do not support data stack. + + if (!stackInfo.stackedDimension || !(stackInfo.isStackedByIndex || stackInfo.stackedByDimension)) { + return; + } + + stackInfoList.length && data.setCalculationInfo('stackedOnSeries', stackInfoList[stackInfoList.length - 1].seriesModel); + stackInfoList.push(stackInfo); + } + }); + stackInfoMap.each(calculateStack); + } + + function calculateStack(stackInfoList) { + each(stackInfoList, function (targetStackInfo, idxInStack) { + var resultVal = []; + var resultNaN = [NaN, NaN]; + var dims = [targetStackInfo.stackResultDimension, targetStackInfo.stackedOverDimension]; + var targetData = targetStackInfo.data; + var isStackedByIndex = targetStackInfo.isStackedByIndex; // Should not write on raw data, because stack series model list changes + // depending on legend selection. + + targetData.modify(dims, function (v0, v1, dataIndex) { + var sum = targetData.get(targetStackInfo.stackedDimension, dataIndex); // Consider `connectNulls` of line area, if value is NaN, stackedOver + // should also be NaN, to draw a appropriate belt area. + + if (isNaN(sum)) { + return resultNaN; + } + + var byValue; + var stackedDataRawIndex; + + if (isStackedByIndex) { + stackedDataRawIndex = targetData.getRawIndex(dataIndex); + } else { + byValue = targetData.get(targetStackInfo.stackedByDimension, dataIndex); + } // If stackOver is NaN, chart view will render point on value start. + + + var stackedOver = NaN; + + for (var j = idxInStack - 1; j >= 0; j--) { + var stackInfo = stackInfoList[j]; // Has been optimized by inverted indices on `stackedByDimension`. + + if (!isStackedByIndex) { + stackedDataRawIndex = stackInfo.data.rawIndexOf(stackInfo.stackedByDimension, byValue); + } + + if (stackedDataRawIndex >= 0) { + var val = stackInfo.data.getByRawIndex(stackInfo.stackResultDimension, stackedDataRawIndex); // Considering positive stack, negative stack and empty data + + if (sum >= 0 && val > 0 || // Positive stack + sum <= 0 && val < 0 // Negative stack + ) { + // The sum should be as less as possible to be effected + // by floating arithmetic problem. A wrong result probably + // filtered incorrectly by axis min/max. + sum = addSafe(sum, val); + stackedOver = val; + break; + } + } + } + + resultVal[0] = sum; + resultVal[1] = stackedOver; + return resultVal; + }); + }); + } + + var SourceImpl = + /** @class */ + function () { + function SourceImpl(fields) { + this.data = fields.data || (fields.sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS ? {} : []); + this.sourceFormat = fields.sourceFormat || SOURCE_FORMAT_UNKNOWN; // Visit config + + this.seriesLayoutBy = fields.seriesLayoutBy || SERIES_LAYOUT_BY_COLUMN; + this.startIndex = fields.startIndex || 0; + this.dimensionsDetectedCount = fields.dimensionsDetectedCount; + this.metaRawOption = fields.metaRawOption; + var dimensionsDefine = this.dimensionsDefine = fields.dimensionsDefine; + + if (dimensionsDefine) { + for (var i = 0; i < dimensionsDefine.length; i++) { + var dim = dimensionsDefine[i]; + + if (dim.type == null) { + if (guessOrdinal(this, i) === BE_ORDINAL.Must) { + dim.type = 'ordinal'; + } + } + } + } + } + + return SourceImpl; + }(); + + function isSourceInstance(val) { + return val instanceof SourceImpl; + } + /** + * Create a source from option. + * NOTE: Created source is immutable. Don't change any properties in it. + */ + + function createSource(sourceData, thisMetaRawOption, // can be null. If not provided, auto detect it from `sourceData`. + sourceFormat) { + sourceFormat = sourceFormat || detectSourceFormat(sourceData); + var seriesLayoutBy = thisMetaRawOption.seriesLayoutBy; + var determined = determineSourceDimensions(sourceData, sourceFormat, seriesLayoutBy, thisMetaRawOption.sourceHeader, thisMetaRawOption.dimensions); + var source = new SourceImpl({ + data: sourceData, + sourceFormat: sourceFormat, + seriesLayoutBy: seriesLayoutBy, + dimensionsDefine: determined.dimensionsDefine, + startIndex: determined.startIndex, + dimensionsDetectedCount: determined.dimensionsDetectedCount, + metaRawOption: clone(thisMetaRawOption) + }); + return source; + } + /** + * Wrap original series data for some compatibility cases. + */ + + function createSourceFromSeriesDataOption(data) { + return new SourceImpl({ + data: data, + sourceFormat: isTypedArray(data) ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL + }); + } + /** + * Clone source but excludes source data. + */ + + function cloneSourceShallow(source) { + return new SourceImpl({ + data: source.data, + sourceFormat: source.sourceFormat, + seriesLayoutBy: source.seriesLayoutBy, + dimensionsDefine: clone(source.dimensionsDefine), + startIndex: source.startIndex, + dimensionsDetectedCount: source.dimensionsDetectedCount + }); + } + /** + * Note: An empty array will be detected as `SOURCE_FORMAT_ARRAY_ROWS`. + */ + + function detectSourceFormat(data) { + var sourceFormat = SOURCE_FORMAT_UNKNOWN; + + if (isTypedArray(data)) { + sourceFormat = SOURCE_FORMAT_TYPED_ARRAY; + } else if (isArray(data)) { + // FIXME Whether tolerate null in top level array? + if (data.length === 0) { + sourceFormat = SOURCE_FORMAT_ARRAY_ROWS; + } + + for (var i = 0, len = data.length; i < len; i++) { + var item = data[i]; + + if (item == null) { + continue; + } else if (isArray(item)) { + sourceFormat = SOURCE_FORMAT_ARRAY_ROWS; + break; + } else if (isObject(item)) { + sourceFormat = SOURCE_FORMAT_OBJECT_ROWS; + break; + } + } + } else if (isObject(data)) { + for (var key in data) { + if (hasOwn(data, key) && isArrayLike(data[key])) { + sourceFormat = SOURCE_FORMAT_KEYED_COLUMNS; + break; + } + } + } + + return sourceFormat; + } + /** + * Determine the source definitions from data standalone dimensions definitions + * are not specified. + */ + + function determineSourceDimensions(data, sourceFormat, seriesLayoutBy, sourceHeader, // standalone raw dimensions definition, like: + // { + // dimensions: ['aa', 'bb', { name: 'cc', type: 'time' }] + // } + // in `dataset` or `series` + dimensionsDefine) { + var dimensionsDetectedCount; + var startIndex; // PEDING: could data be null/undefined here? + // currently, if `dataset.source` not specified, error thrown. + // if `series.data` not specified, nothing rendered without error thrown. + // Should test these cases. + + if (!data) { + return { + dimensionsDefine: normalizeDimensionsOption(dimensionsDefine), + startIndex: startIndex, + dimensionsDetectedCount: dimensionsDetectedCount + }; + } + + if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) { + var dataArrayRows = data; // Rule: Most of the first line are string: it is header. + // Caution: consider a line with 5 string and 1 number, + // it still can not be sure it is a head, because the + // 5 string may be 5 values of category columns. + + if (sourceHeader === 'auto' || sourceHeader == null) { + arrayRowsTravelFirst(function (val) { + // '-' is regarded as null/undefined. + if (val != null && val !== '-') { + if (isString(val)) { + startIndex == null && (startIndex = 1); + } else { + startIndex = 0; + } + } // 10 is an experience number, avoid long loop. + + }, seriesLayoutBy, dataArrayRows, 10); + } else { + startIndex = isNumber(sourceHeader) ? sourceHeader : sourceHeader ? 1 : 0; + } + + if (!dimensionsDefine && startIndex === 1) { + dimensionsDefine = []; + arrayRowsTravelFirst(function (val, index) { + dimensionsDefine[index] = val != null ? val + '' : ''; + }, seriesLayoutBy, dataArrayRows, Infinity); + } + + dimensionsDetectedCount = dimensionsDefine ? dimensionsDefine.length : seriesLayoutBy === SERIES_LAYOUT_BY_ROW ? dataArrayRows.length : dataArrayRows[0] ? dataArrayRows[0].length : null; + } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) { + if (!dimensionsDefine) { + dimensionsDefine = objectRowsCollectDimensions(data); + } + } else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) { + if (!dimensionsDefine) { + dimensionsDefine = []; + each(data, function (colArr, key) { + dimensionsDefine.push(key); + }); + } + } else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) { + var value0 = getDataItemValue(data[0]); + dimensionsDetectedCount = isArray(value0) && value0.length || 1; + } else if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) { + if ("development" !== 'production') { + assert(!!dimensionsDefine, 'dimensions must be given if data is TypedArray.'); + } + } + + return { + startIndex: startIndex, + dimensionsDefine: normalizeDimensionsOption(dimensionsDefine), + dimensionsDetectedCount: dimensionsDetectedCount + }; + } + + function objectRowsCollectDimensions(data) { + var firstIndex = 0; + var obj; + + while (firstIndex < data.length && !(obj = data[firstIndex++])) {} // jshint ignore: line + + + if (obj) { + var dimensions_1 = []; + each(obj, function (value, key) { + dimensions_1.push(key); + }); + return dimensions_1; + } + } // Consider dimensions defined like ['A', 'price', 'B', 'price', 'C', 'price'], + // which is reasonable. But dimension name is duplicated. + // Returns undefined or an array contains only object without null/undefiend or string. + + + function normalizeDimensionsOption(dimensionsDefine) { + if (!dimensionsDefine) { + // The meaning of null/undefined is different from empty array. + return; + } + + var nameMap = createHashMap(); + return map(dimensionsDefine, function (rawItem, index) { + rawItem = isObject(rawItem) ? rawItem : { + name: rawItem + }; // Other fields will be discarded. + + var item = { + name: rawItem.name, + displayName: rawItem.displayName, + type: rawItem.type + }; // User can set null in dimensions. + // We dont auto specify name, othewise a given name may + // cause it be refered unexpectedly. + + if (item.name == null) { + return item; + } // Also consider number form like 2012. + + + item.name += ''; // User may also specify displayName. + // displayName will always exists except user not + // specified or dim name is not specified or detected. + // (A auto generated dim name will not be used as + // displayName). + + if (item.displayName == null) { + item.displayName = item.name; + } + + var exist = nameMap.get(item.name); + + if (!exist) { + nameMap.set(item.name, { + count: 1 + }); + } else { + item.name += '-' + exist.count++; + } + + return item; + }); + } + + function arrayRowsTravelFirst(cb, seriesLayoutBy, data, maxLoop) { + if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) { + for (var i = 0; i < data.length && i < maxLoop; i++) { + cb(data[i] ? data[i][0] : null, i); + } + } else { + var value0 = data[0] || []; + + for (var i = 0; i < value0.length && i < maxLoop; i++) { + cb(value0[i], i); + } + } + } + + function shouldRetrieveDataByName(source) { + var sourceFormat = source.sourceFormat; + return sourceFormat === SOURCE_FORMAT_OBJECT_ROWS || sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var _a, _b, _c; // TODO + var providerMethods; + var mountMethods; + /** + * If normal array used, mutable chunk size is supported. + * If typed array used, chunk size must be fixed. + */ + + var DefaultDataProvider = + /** @class */ + function () { + function DefaultDataProvider(sourceParam, dimSize) { + // let source: Source; + var source = !isSourceInstance(sourceParam) ? createSourceFromSeriesDataOption(sourceParam) : sourceParam; // declare source is Source; + + this._source = source; + var data = this._data = source.data; // Typed array. TODO IE10+? + + if (source.sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) { + if ("development" !== 'production') { + if (dimSize == null) { + throw new Error('Typed array data must specify dimension size'); + } + } + + this._offset = 0; + this._dimSize = dimSize; + this._data = data; + } + + mountMethods(this, data, source); + } + + DefaultDataProvider.prototype.getSource = function () { + return this._source; + }; + + DefaultDataProvider.prototype.count = function () { + return 0; + }; + + DefaultDataProvider.prototype.getItem = function (idx, out) { + return; + }; + + DefaultDataProvider.prototype.appendData = function (newData) {}; + + DefaultDataProvider.prototype.clean = function () {}; + + DefaultDataProvider.protoInitialize = function () { + // PENDING: To avoid potential incompat (e.g., prototype + // is visited somewhere), still init them on prototype. + var proto = DefaultDataProvider.prototype; + proto.pure = false; + proto.persistent = true; + }(); + + DefaultDataProvider.internalField = function () { + var _a; + + mountMethods = function (provider, data, source) { + var sourceFormat = source.sourceFormat; + var seriesLayoutBy = source.seriesLayoutBy; + var startIndex = source.startIndex; + var dimsDef = source.dimensionsDefine; + var methods = providerMethods[getMethodMapKey(sourceFormat, seriesLayoutBy)]; + + if ("development" !== 'production') { + assert(methods, 'Invalide sourceFormat: ' + sourceFormat); + } + + extend(provider, methods); + + if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) { + provider.getItem = getItemForTypedArray; + provider.count = countForTypedArray; + provider.fillStorage = fillStorageForTypedArray; + } else { + var rawItemGetter = getRawSourceItemGetter(sourceFormat, seriesLayoutBy); + provider.getItem = bind(rawItemGetter, null, data, startIndex, dimsDef); + var rawCounter = getRawSourceDataCounter(sourceFormat, seriesLayoutBy); + provider.count = bind(rawCounter, null, data, startIndex, dimsDef); + } + }; + + var getItemForTypedArray = function (idx, out) { + idx = idx - this._offset; + out = out || []; + var data = this._data; + var dimSize = this._dimSize; + var offset = dimSize * idx; + + for (var i = 0; i < dimSize; i++) { + out[i] = data[offset + i]; + } + + return out; + }; + + var fillStorageForTypedArray = function (start, end, storage, extent) { + var data = this._data; + var dimSize = this._dimSize; + + for (var dim = 0; dim < dimSize; dim++) { + var dimExtent = extent[dim]; + var min = dimExtent[0] == null ? Infinity : dimExtent[0]; + var max = dimExtent[1] == null ? -Infinity : dimExtent[1]; + var count = end - start; + var arr = storage[dim]; + + for (var i = 0; i < count; i++) { + // appendData with TypedArray will always do replace in provider. + var val = data[i * dimSize + dim]; + arr[start + i] = val; + val < min && (min = val); + val > max && (max = val); + } + + dimExtent[0] = min; + dimExtent[1] = max; + } + }; + + var countForTypedArray = function () { + return this._data ? this._data.length / this._dimSize : 0; + }; + + providerMethods = (_a = {}, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = { + pure: true, + appendData: appendDataSimply + }, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = { + pure: true, + appendData: function () { + throw new Error('Do not support appendData when set seriesLayoutBy: "row".'); + } + }, _a[SOURCE_FORMAT_OBJECT_ROWS] = { + pure: true, + appendData: appendDataSimply + }, _a[SOURCE_FORMAT_KEYED_COLUMNS] = { + pure: true, + appendData: function (newData) { + var data = this._data; + each(newData, function (newCol, key) { + var oldCol = data[key] || (data[key] = []); + + for (var i = 0; i < (newCol || []).length; i++) { + oldCol.push(newCol[i]); + } + }); + } + }, _a[SOURCE_FORMAT_ORIGINAL] = { + appendData: appendDataSimply + }, _a[SOURCE_FORMAT_TYPED_ARRAY] = { + persistent: false, + pure: true, + appendData: function (newData) { + if ("development" !== 'production') { + assert(isTypedArray(newData), 'Added data must be TypedArray if data in initialization is TypedArray'); + } + + this._data = newData; + }, + // Clean self if data is already used. + clean: function () { + // PENDING + this._offset += this.count(); + this._data = null; + } + }, _a); + + function appendDataSimply(newData) { + for (var i = 0; i < newData.length; i++) { + this._data.push(newData[i]); + } + } + }(); + + return DefaultDataProvider; + }(); + + var getItemSimply = function (rawData, startIndex, dimsDef, idx) { + return rawData[idx]; + }; + + var rawSourceItemGetterMap = (_a = {}, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = function (rawData, startIndex, dimsDef, idx) { + return rawData[idx + startIndex]; + }, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = function (rawData, startIndex, dimsDef, idx, out) { + idx += startIndex; + var item = out || []; + var data = rawData; + + for (var i = 0; i < data.length; i++) { + var row = data[i]; + item[i] = row ? row[idx] : null; + } + + return item; + }, _a[SOURCE_FORMAT_OBJECT_ROWS] = getItemSimply, _a[SOURCE_FORMAT_KEYED_COLUMNS] = function (rawData, startIndex, dimsDef, idx, out) { + var item = out || []; + + for (var i = 0; i < dimsDef.length; i++) { + var dimName = dimsDef[i].name; + + if ("development" !== 'production') { + if (dimName == null) { + throw new Error(); + } + } + + var col = rawData[dimName]; + item[i] = col ? col[idx] : null; + } + + return item; + }, _a[SOURCE_FORMAT_ORIGINAL] = getItemSimply, _a); + function getRawSourceItemGetter(sourceFormat, seriesLayoutBy) { + var method = rawSourceItemGetterMap[getMethodMapKey(sourceFormat, seriesLayoutBy)]; + + if ("development" !== 'production') { + assert(method, 'Do not support get item on "' + sourceFormat + '", "' + seriesLayoutBy + '".'); + } + + return method; + } + + var countSimply = function (rawData, startIndex, dimsDef) { + return rawData.length; + }; + + var rawSourceDataCounterMap = (_b = {}, _b[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = function (rawData, startIndex, dimsDef) { + return Math.max(0, rawData.length - startIndex); + }, _b[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = function (rawData, startIndex, dimsDef) { + var row = rawData[0]; + return row ? Math.max(0, row.length - startIndex) : 0; + }, _b[SOURCE_FORMAT_OBJECT_ROWS] = countSimply, _b[SOURCE_FORMAT_KEYED_COLUMNS] = function (rawData, startIndex, dimsDef) { + var dimName = dimsDef[0].name; + + if ("development" !== 'production') { + if (dimName == null) { + throw new Error(); + } + } + + var col = rawData[dimName]; + return col ? col.length : 0; + }, _b[SOURCE_FORMAT_ORIGINAL] = countSimply, _b); + function getRawSourceDataCounter(sourceFormat, seriesLayoutBy) { + var method = rawSourceDataCounterMap[getMethodMapKey(sourceFormat, seriesLayoutBy)]; + + if ("development" !== 'production') { + assert(method, 'Do not suppport count on "' + sourceFormat + '", "' + seriesLayoutBy + '".'); + } + + return method; + } + + var getRawValueSimply = function (dataItem, dimIndex, property) { + return dataItem[dimIndex]; + }; + + var rawSourceValueGetterMap = (_c = {}, _c[SOURCE_FORMAT_ARRAY_ROWS] = getRawValueSimply, _c[SOURCE_FORMAT_OBJECT_ROWS] = function (dataItem, dimIndex, property) { + return dataItem[property]; + }, _c[SOURCE_FORMAT_KEYED_COLUMNS] = getRawValueSimply, _c[SOURCE_FORMAT_ORIGINAL] = function (dataItem, dimIndex, property) { + // FIXME: In some case (markpoint in geo (geo-map.html)), + // dataItem is {coord: [...]} + var value = getDataItemValue(dataItem); + return !(value instanceof Array) ? value : value[dimIndex]; + }, _c[SOURCE_FORMAT_TYPED_ARRAY] = getRawValueSimply, _c); + function getRawSourceValueGetter(sourceFormat) { + var method = rawSourceValueGetterMap[sourceFormat]; + + if ("development" !== 'production') { + assert(method, 'Do not suppport get value on "' + sourceFormat + '".'); + } + + return method; + } + + function getMethodMapKey(sourceFormat, seriesLayoutBy) { + return sourceFormat === SOURCE_FORMAT_ARRAY_ROWS ? sourceFormat + '_' + seriesLayoutBy : sourceFormat; + } // ??? FIXME can these logic be more neat: getRawValue, getRawDataItem, + // Consider persistent. + // Caution: why use raw value to display on label or tooltip? + // A reason is to avoid format. For example time value we do not know + // how to format is expected. More over, if stack is used, calculated + // value may be 0.91000000001, which have brings trouble to display. + // TODO: consider how to treat null/undefined/NaN when display? + + + function retrieveRawValue(data, dataIndex, // If dimIndex is null/undefined, return OptionDataItem. + // Otherwise, return OptionDataValue. + dim) { + if (!data) { + return; + } // Consider data may be not persistent. + + + var dataItem = data.getRawDataItem(dataIndex); + + if (dataItem == null) { + return; + } + + var store = data.getStore(); + var sourceFormat = store.getSource().sourceFormat; + + if (dim != null) { + var dimIndex = data.getDimensionIndex(dim); + var property = store.getDimensionProperty(dimIndex); + return getRawSourceValueGetter(sourceFormat)(dataItem, dimIndex, property); + } else { + var result = dataItem; + + if (sourceFormat === SOURCE_FORMAT_ORIGINAL) { + result = getDataItemValue(dataItem); + } + + return result; + } + } + + var DIMENSION_LABEL_REG = /\{@(.+?)\}/g; + + var DataFormatMixin = + /** @class */ + function () { + function DataFormatMixin() {} + /** + * Get params for formatter + */ + + + DataFormatMixin.prototype.getDataParams = function (dataIndex, dataType) { + var data = this.getData(dataType); + var rawValue = this.getRawValue(dataIndex, dataType); + var rawDataIndex = data.getRawIndex(dataIndex); + var name = data.getName(dataIndex); + var itemOpt = data.getRawDataItem(dataIndex); + var style = data.getItemVisual(dataIndex, 'style'); + var color = style && style[data.getItemVisual(dataIndex, 'drawType') || 'fill']; + var borderColor = style && style.stroke; + var mainType = this.mainType; + var isSeries = mainType === 'series'; + var userOutput = data.userOutput && data.userOutput.get(); + return { + componentType: mainType, + componentSubType: this.subType, + componentIndex: this.componentIndex, + seriesType: isSeries ? this.subType : null, + seriesIndex: this.seriesIndex, + seriesId: isSeries ? this.id : null, + seriesName: isSeries ? this.name : null, + name: name, + dataIndex: rawDataIndex, + data: itemOpt, + dataType: dataType, + value: rawValue, + color: color, + borderColor: borderColor, + dimensionNames: userOutput ? userOutput.fullDimensions : null, + encode: userOutput ? userOutput.encode : null, + // Param name list for mapping `a`, `b`, `c`, `d`, `e` + $vars: ['seriesName', 'name', 'value'] + }; + }; + /** + * Format label + * @param dataIndex + * @param status 'normal' by default + * @param dataType + * @param labelDimIndex Only used in some chart that + * use formatter in different dimensions, like radar. + * @param formatter Formatter given outside. + * @return return null/undefined if no formatter + */ + + + DataFormatMixin.prototype.getFormattedLabel = function (dataIndex, status, dataType, labelDimIndex, formatter, extendParams) { + status = status || 'normal'; + var data = this.getData(dataType); + var params = this.getDataParams(dataIndex, dataType); + + if (extendParams) { + params.value = extendParams.interpolatedValue; + } + + if (labelDimIndex != null && isArray(params.value)) { + params.value = params.value[labelDimIndex]; + } + + if (!formatter) { + var itemModel = data.getItemModel(dataIndex); // @ts-ignore + + formatter = itemModel.get(status === 'normal' ? ['label', 'formatter'] : [status, 'label', 'formatter']); + } + + if (isFunction(formatter)) { + params.status = status; + params.dimensionIndex = labelDimIndex; + return formatter(params); + } else if (isString(formatter)) { + var str = formatTpl(formatter, params); // Support 'aaa{@[3]}bbb{@product}ccc'. + // Do not support '}' in dim name util have to. + + return str.replace(DIMENSION_LABEL_REG, function (origin, dimStr) { + var len = dimStr.length; + var dimLoose = dimStr; + + if (dimLoose.charAt(0) === '[' && dimLoose.charAt(len - 1) === ']') { + dimLoose = +dimLoose.slice(1, len - 1); // Also support: '[]' => 0 + + if ("development" !== 'production') { + if (isNaN(dimLoose)) { + error("Invalide label formatter: @" + dimStr + ", only support @[0], @[1], @[2], ..."); + } + } + } + + var val = retrieveRawValue(data, dataIndex, dimLoose); + + if (extendParams && isArray(extendParams.interpolatedValue)) { + var dimIndex = data.getDimensionIndex(dimLoose); + + if (dimIndex >= 0) { + val = extendParams.interpolatedValue[dimIndex]; + } + } + + return val != null ? val + '' : ''; + }); + } + }; + /** + * Get raw value in option + */ + + + DataFormatMixin.prototype.getRawValue = function (idx, dataType) { + return retrieveRawValue(this.getData(dataType), idx); + }; + /** + * Should be implemented. + * @param {number} dataIndex + * @param {boolean} [multipleSeries=false] + * @param {string} [dataType] + */ + + + DataFormatMixin.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + // Empty function + return; + }; + + return DataFormatMixin; + }(); + // but guess little chance has been used outside. Do we need to backward + // compat it? + // type TooltipFormatResultLegacyObject = { + // // `html` means the markup language text, either in 'html' or 'richText'. + // // The name `html` is not appropriate becuase in 'richText' it is not a HTML + // // string. But still support it for backward compat. + // html: string; + // markers: Dictionary; + // }; + + /** + * For backward compat, normalize the return from `formatTooltip`. + */ + + function normalizeTooltipFormatResult(result) { + var markupText; // let markers: Dictionary; + + var markupFragment; + + if (isObject(result)) { + if (result.type) { + markupFragment = result; + } else { + if ("development" !== 'production') { + console.warn('The return type of `formatTooltip` is not supported: ' + makePrintable(result)); + } + } // else { + // markupText = (result as TooltipFormatResultLegacyObject).html; + // markers = (result as TooltipFormatResultLegacyObject).markers; + // if (markersExisting) { + // markers = zrUtil.merge(markersExisting, markers); + // } + // } + + } else { + markupText = result; + } + + return { + text: markupText, + // markers: markers || markersExisting, + frag: markupFragment + }; + } + + /** + * @param {Object} define + * @return See the return of `createTask`. + */ + + function createTask(define) { + return new Task(define); + } + + var Task = + /** @class */ + function () { + function Task(define) { + define = define || {}; + this._reset = define.reset; + this._plan = define.plan; + this._count = define.count; + this._onDirty = define.onDirty; + this._dirty = true; + } + /** + * @param step Specified step. + * @param skip Skip customer perform call. + * @param modBy Sampling window size. + * @param modDataCount Sampling count. + * @return whether unfinished. + */ + + + Task.prototype.perform = function (performArgs) { + var upTask = this._upstream; + var skip = performArgs && performArgs.skip; // TODO some refactor. + // Pull data. Must pull data each time, because context.data + // may be updated by Series.setData. + + if (this._dirty && upTask) { + var context = this.context; + context.data = context.outputData = upTask.context.outputData; + } + + if (this.__pipeline) { + this.__pipeline.currentTask = this; + } + + var planResult; + + if (this._plan && !skip) { + planResult = this._plan(this.context); + } // Support sharding by mod, which changes the render sequence and makes the rendered graphic + // elements uniformed distributed when progress, especially when moving or zooming. + + + var lastModBy = normalizeModBy(this._modBy); + var lastModDataCount = this._modDataCount || 0; + var modBy = normalizeModBy(performArgs && performArgs.modBy); + var modDataCount = performArgs && performArgs.modDataCount || 0; + + if (lastModBy !== modBy || lastModDataCount !== modDataCount) { + planResult = 'reset'; + } + + function normalizeModBy(val) { + !(val >= 1) && (val = 1); // jshint ignore:line + + return val; + } + + var forceFirstProgress; + + if (this._dirty || planResult === 'reset') { + this._dirty = false; + forceFirstProgress = this._doReset(skip); + } + + this._modBy = modBy; + this._modDataCount = modDataCount; + var step = performArgs && performArgs.step; + + if (upTask) { + if ("development" !== 'production') { + assert(upTask._outputDueEnd != null); + } + + this._dueEnd = upTask._outputDueEnd; + } // DataTask or overallTask + else { + if ("development" !== 'production') { + assert(!this._progress || this._count); + } + + this._dueEnd = this._count ? this._count(this.context) : Infinity; + } // Note: Stubs, that its host overall task let it has progress, has progress. + // If no progress, pass index from upstream to downstream each time plan called. + + + if (this._progress) { + var start = this._dueIndex; + var end = Math.min(step != null ? this._dueIndex + step : Infinity, this._dueEnd); + + if (!skip && (forceFirstProgress || start < end)) { + var progress = this._progress; + + if (isArray(progress)) { + for (var i = 0; i < progress.length; i++) { + this._doProgress(progress[i], start, end, modBy, modDataCount); + } + } else { + this._doProgress(progress, start, end, modBy, modDataCount); + } + } + + this._dueIndex = end; // If no `outputDueEnd`, assume that output data and + // input data is the same, so use `dueIndex` as `outputDueEnd`. + + var outputDueEnd = this._settedOutputEnd != null ? this._settedOutputEnd : end; + + if ("development" !== 'production') { + // ??? Can not rollback. + assert(outputDueEnd >= this._outputDueEnd); + } + + this._outputDueEnd = outputDueEnd; + } else { + // (1) Some overall task has no progress. + // (2) Stubs, that its host overall task do not let it has progress, has no progress. + // This should always be performed so it can be passed to downstream. + this._dueIndex = this._outputDueEnd = this._settedOutputEnd != null ? this._settedOutputEnd : this._dueEnd; + } + + return this.unfinished(); + }; + + Task.prototype.dirty = function () { + this._dirty = true; + this._onDirty && this._onDirty(this.context); + }; + + Task.prototype._doProgress = function (progress, start, end, modBy, modDataCount) { + iterator.reset(start, end, modBy, modDataCount); + this._callingProgress = progress; + + this._callingProgress({ + start: start, + end: end, + count: end - start, + next: iterator.next + }, this.context); + }; + + Task.prototype._doReset = function (skip) { + this._dueIndex = this._outputDueEnd = this._dueEnd = 0; + this._settedOutputEnd = null; + var progress; + var forceFirstProgress; + + if (!skip && this._reset) { + progress = this._reset(this.context); + + if (progress && progress.progress) { + forceFirstProgress = progress.forceFirstProgress; + progress = progress.progress; + } // To simplify no progress checking, array must has item. + + + if (isArray(progress) && !progress.length) { + progress = null; + } + } + + this._progress = progress; + this._modBy = this._modDataCount = null; + var downstream = this._downstream; + downstream && downstream.dirty(); + return forceFirstProgress; + }; + + Task.prototype.unfinished = function () { + return this._progress && this._dueIndex < this._dueEnd; + }; + /** + * @param downTask The downstream task. + * @return The downstream task. + */ + + + Task.prototype.pipe = function (downTask) { + if ("development" !== 'production') { + assert(downTask && !downTask._disposed && downTask !== this); + } // If already downstream, do not dirty downTask. + + + if (this._downstream !== downTask || this._dirty) { + this._downstream = downTask; + downTask._upstream = this; + downTask.dirty(); + } + }; + + Task.prototype.dispose = function () { + if (this._disposed) { + return; + } + + this._upstream && (this._upstream._downstream = null); + this._downstream && (this._downstream._upstream = null); + this._dirty = false; + this._disposed = true; + }; + + Task.prototype.getUpstream = function () { + return this._upstream; + }; + + Task.prototype.getDownstream = function () { + return this._downstream; + }; + + Task.prototype.setOutputEnd = function (end) { + // This only happend in dataTask, dataZoom, map, currently. + // where dataZoom do not set end each time, but only set + // when reset. So we should record the setted end, in case + // that the stub of dataZoom perform again and earse the + // setted end by upstream. + this._outputDueEnd = this._settedOutputEnd = end; + }; + + return Task; + }(); + + var iterator = function () { + var end; + var current; + var modBy; + var modDataCount; + var winCount; + var it = { + reset: function (s, e, sStep, sCount) { + current = s; + end = e; + modBy = sStep; + modDataCount = sCount; + winCount = Math.ceil(modDataCount / modBy); + it.next = modBy > 1 && modDataCount > 0 ? modNext : sequentialNext; + } + }; + return it; + + function sequentialNext() { + return current < end ? current++ : null; + } + + function modNext() { + var dataIndex = current % winCount * modBy + Math.ceil(current / winCount); + var result = current >= end ? null : dataIndex < modDataCount ? dataIndex // If modDataCount is smaller than data.count() (consider `appendData` case), + // Use normal linear rendering mode. + : current; + current++; + return result; + } + }(); /////////////////////////////////////////////////////////// + // For stream debug (Should be commented out after used!) + // @usage: printTask(this, 'begin'); + // @usage: printTask(this, null, {someExtraProp}); + // @usage: Use `__idxInPipeline` as conditional breakpiont. + // + // window.printTask = function (task: any, prefix: string, extra: { [key: string]: unknown }): void { + // window.ecTaskUID == null && (window.ecTaskUID = 0); + // task.uidDebug == null && (task.uidDebug = `task_${window.ecTaskUID++}`); + // task.agent && task.agent.uidDebug == null && (task.agent.uidDebug = `task_${window.ecTaskUID++}`); + // let props = []; + // if (task.__pipeline) { + // let val = `${task.__idxInPipeline}/${task.__pipeline.tail.__idxInPipeline} ${task.agent ? '(stub)' : ''}`; + // props.push({text: '__idxInPipeline/total', value: val}); + // } else { + // let stubCount = 0; + // task.agentStubMap.each(() => stubCount++); + // props.push({text: 'idx', value: `overall (stubs: ${stubCount})`}); + // } + // props.push({text: 'uid', value: task.uidDebug}); + // if (task.__pipeline) { + // props.push({text: 'pipelineId', value: task.__pipeline.id}); + // task.agent && props.push( + // {text: 'stubFor', value: task.agent.uidDebug} + // ); + // } + // props.push( + // {text: 'dirty', value: task._dirty}, + // {text: 'dueIndex', value: task._dueIndex}, + // {text: 'dueEnd', value: task._dueEnd}, + // {text: 'outputDueEnd', value: task._outputDueEnd} + // ); + // if (extra) { + // Object.keys(extra).forEach(key => { + // props.push({text: key, value: extra[key]}); + // }); + // } + // let args = ['color: blue']; + // let msg = `%c[${prefix || 'T'}] %c` + props.map(item => ( + // args.push('color: green', 'color: red'), + // `${item.text}: %c${item.value}` + // )).join('%c, '); + // console.log.apply(console, [msg].concat(args)); + // // console.log(this); + // }; + // window.printPipeline = function (task: any, prefix: string) { + // const pipeline = task.__pipeline; + // let currTask = pipeline.head; + // while (currTask) { + // window.printTask(currTask, prefix); + // currTask = currTask._downstream; + // } + // }; + // window.showChain = function (chainHeadTask) { + // var chain = []; + // var task = chainHeadTask; + // while (task) { + // chain.push({ + // task: task, + // up: task._upstream, + // down: task._downstream, + // idxInPipeline: task.__idxInPipeline + // }); + // task = task._downstream; + // } + // return chain; + // }; + // window.findTaskInChain = function (task, chainHeadTask) { + // let chain = window.showChain(chainHeadTask); + // let result = []; + // for (let i = 0; i < chain.length; i++) { + // let chainItem = chain[i]; + // if (chainItem.task === task) { + // result.push(i); + // } + // } + // return result; + // }; + // window.printChainAEachInChainB = function (chainHeadTaskA, chainHeadTaskB) { + // let chainA = window.showChain(chainHeadTaskA); + // for (let i = 0; i < chainA.length; i++) { + // console.log('chainAIdx:', i, 'inChainB:', window.findTaskInChain(chainA[i].task, chainHeadTaskB)); + // } + // }; + + /** + * Convert raw the value in to inner value in List. + * + * [Performance sensitive] + * + * [Caution]: this is the key logic of user value parser. + * For backward compatibiliy, do not modify it until have to! + */ + + function parseDataValue(value, // For high performance, do not omit the second param. + opt) { + // Performance sensitive. + var dimType = opt && opt.type; + + if (dimType === 'ordinal') { + // If given value is a category string + return value; + } + + if (dimType === 'time' // spead up when using timestamp + && !isNumber(value) && value != null && value !== '-') { + value = +parseDate(value); + } // dimType defaults 'number'. + // If dimType is not ordinal and value is null or undefined or NaN or '-', + // parse to NaN. + // number-like string (like ' 123 ') can be converted to a number. + // where null/undefined or other string will be converted to NaN. + + + return value == null || value === '' ? NaN // If string (like '-'), using '+' parse to NaN + // If object, also parse to NaN + : +value; + } + var valueParserMap = createHashMap({ + 'number': function (val) { + // Do not use `numericToNumber` here. We have by defualt `numericToNumber`. + // Here the number parser can have loose rule: + // enable to cut suffix: "120px" => 120, "14%" => 14. + return parseFloat(val); + }, + 'time': function (val) { + // return timestamp. + return +parseDate(val); + }, + 'trim': function (val) { + return isString(val) ? trim(val) : val; + } + }); + function getRawValueParser(type) { + return valueParserMap.get(type); + } + var ORDER_COMPARISON_OP_MAP = { + lt: function (lval, rval) { + return lval < rval; + }, + lte: function (lval, rval) { + return lval <= rval; + }, + gt: function (lval, rval) { + return lval > rval; + }, + gte: function (lval, rval) { + return lval >= rval; + } + }; + + var FilterOrderComparator = + /** @class */ + function () { + function FilterOrderComparator(op, rval) { + if (!isNumber(rval)) { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = 'rvalue of "<", ">", "<=", ">=" can only be number in filter.'; + } + + throwError(errMsg); + } + + this._opFn = ORDER_COMPARISON_OP_MAP[op]; + this._rvalFloat = numericToNumber(rval); + } // Performance sensitive. + + + FilterOrderComparator.prototype.evaluate = function (lval) { + // Most cases is 'number', and typeof maybe 10 times faseter than parseFloat. + return isNumber(lval) ? this._opFn(lval, this._rvalFloat) : this._opFn(numericToNumber(lval), this._rvalFloat); + }; + + return FilterOrderComparator; + }(); + + var SortOrderComparator = + /** @class */ + function () { + /** + * @param order by defualt: 'asc' + * @param incomparable by defualt: Always on the tail. + * That is, if 'asc' => 'max', if 'desc' => 'min' + * See the definition of "incomparable" in [SORT_COMPARISON_RULE] + */ + function SortOrderComparator(order, incomparable) { + var isDesc = order === 'desc'; + this._resultLT = isDesc ? 1 : -1; + + if (incomparable == null) { + incomparable = isDesc ? 'min' : 'max'; + } + + this._incomparable = incomparable === 'min' ? -Infinity : Infinity; + } // See [SORT_COMPARISON_RULE]. + // Performance sensitive. + + + SortOrderComparator.prototype.evaluate = function (lval, rval) { + // Most cases is 'number', and typeof maybe 10 times faseter than parseFloat. + var lvalFloat = isNumber(lval) ? lval : numericToNumber(lval); + var rvalFloat = isNumber(rval) ? rval : numericToNumber(rval); + var lvalNotNumeric = isNaN(lvalFloat); + var rvalNotNumeric = isNaN(rvalFloat); + + if (lvalNotNumeric) { + lvalFloat = this._incomparable; + } + + if (rvalNotNumeric) { + rvalFloat = this._incomparable; + } + + if (lvalNotNumeric && rvalNotNumeric) { + var lvalIsStr = isString(lval); + var rvalIsStr = isString(rval); + + if (lvalIsStr) { + lvalFloat = rvalIsStr ? lval : 0; + } + + if (rvalIsStr) { + rvalFloat = lvalIsStr ? rval : 0; + } + } + + return lvalFloat < rvalFloat ? this._resultLT : lvalFloat > rvalFloat ? -this._resultLT : 0; + }; + + return SortOrderComparator; + }(); + + var FilterEqualityComparator = + /** @class */ + function () { + function FilterEqualityComparator(isEq, rval) { + this._rval = rval; + this._isEQ = isEq; + this._rvalTypeof = typeof rval; + this._rvalFloat = numericToNumber(rval); + } // Performance sensitive. + + + FilterEqualityComparator.prototype.evaluate = function (lval) { + var eqResult = lval === this._rval; + + if (!eqResult) { + var lvalTypeof = typeof lval; + + if (lvalTypeof !== this._rvalTypeof && (lvalTypeof === 'number' || this._rvalTypeof === 'number')) { + eqResult = numericToNumber(lval) === this._rvalFloat; + } + } + + return this._isEQ ? eqResult : !eqResult; + }; + + return FilterEqualityComparator; + }(); + /** + * [FILTER_COMPARISON_RULE] + * `lt`|`lte`|`gt`|`gte`: + * + rval must be a number. And lval will be converted to number (`numericToNumber`) to compare. + * `eq`: + * + If same type, compare with `===`. + * + If there is one number, convert to number (`numericToNumber`) to compare. + * + Else return `false`. + * `ne`: + * + Not `eq`. + * + * + * [SORT_COMPARISON_RULE] + * All the values are grouped into three categories: + * + "numeric" (number and numeric string) + * + "non-numeric-string" (string that excluding numeric string) + * + "others" + * "numeric" vs "numeric": values are ordered by number order. + * "non-numeric-string" vs "non-numeric-string": values are ordered by ES spec (#sec-abstract-relational-comparison). + * "others" vs "others": do not change order (always return 0). + * "numeric" vs "non-numeric-string": "non-numeric-string" is treated as "incomparable". + * "number" vs "others": "others" is treated as "incomparable". + * "non-numeric-string" vs "others": "others" is treated as "incomparable". + * "incomparable" will be seen as -Infinity or Infinity (depends on the settings). + * MEMO: + * non-numeric string sort make sence when need to put the items with the same tag together. + * But if we support string sort, we still need to avoid the misleading like `'2' > '12'`, + * So we treat "numeric-string" sorted by number order rather than string comparison. + * + * + * [CHECK_LIST_OF_THE_RULE_DESIGN] + * + Do not support string comparison until required. And also need to + * void the misleading of "2" > "12". + * + Should avoid the misleading case: + * `" 22 " gte "22"` is `true` but `" 22 " eq "22"` is `false`. + * + JS bad case should be avoided: null <= 0, [] <= 0, ' ' <= 0, ... + * + Only "numeric" can be converted to comparable number, otherwise converted to NaN. + * See `util/number.ts#numericToNumber`. + * + * @return If `op` is not `RelationalOperator`, return null; + */ + + + function createFilterComparator(op, rval) { + return op === 'eq' || op === 'ne' ? new FilterEqualityComparator(op === 'eq', rval) : hasOwn(ORDER_COMPARISON_OP_MAP, op) ? new FilterOrderComparator(op, rval) : null; + } + + /** + * TODO: disable writable. + * This structure will be exposed to users. + */ + + var ExternalSource = + /** @class */ + function () { + function ExternalSource() {} + + ExternalSource.prototype.getRawData = function () { + // Only built-in transform available. + throw new Error('not supported'); + }; + + ExternalSource.prototype.getRawDataItem = function (dataIndex) { + // Only built-in transform available. + throw new Error('not supported'); + }; + + ExternalSource.prototype.cloneRawData = function () { + return; + }; + /** + * @return If dimension not found, return null/undefined. + */ + + + ExternalSource.prototype.getDimensionInfo = function (dim) { + return; + }; + /** + * dimensions defined if and only if either: + * (a) dataset.dimensions are declared. + * (b) dataset data include dimensions definitions in data (detected or via specified `sourceHeader`). + * If dimensions are defined, `dimensionInfoAll` is corresponding to + * the defined dimensions. + * Otherwise, `dimensionInfoAll` is determined by data columns. + * @return Always return an array (even empty array). + */ + + + ExternalSource.prototype.cloneAllDimensionInfo = function () { + return; + }; + + ExternalSource.prototype.count = function () { + return; + }; + /** + * Only support by dimension index. + * No need to support by dimension name in transform function, + * becuase transform function is not case-specific, no need to use name literally. + */ + + + ExternalSource.prototype.retrieveValue = function (dataIndex, dimIndex) { + return; + }; + + ExternalSource.prototype.retrieveValueFromItem = function (dataItem, dimIndex) { + return; + }; + + ExternalSource.prototype.convertValue = function (rawVal, dimInfo) { + return parseDataValue(rawVal, dimInfo); + }; + + return ExternalSource; + }(); + + function createExternalSource(internalSource, externalTransform) { + var extSource = new ExternalSource(); + var data = internalSource.data; + var sourceFormat = extSource.sourceFormat = internalSource.sourceFormat; + var sourceHeaderCount = internalSource.startIndex; + var errMsg = ''; + + if (internalSource.seriesLayoutBy !== SERIES_LAYOUT_BY_COLUMN) { + // For the logic simplicity in transformer, only 'culumn' is + // supported in data transform. Otherwise, the `dimensionsDefine` + // might be detected by 'row', which probably confuses users. + if ("development" !== 'production') { + errMsg = '`seriesLayoutBy` of upstream dataset can only be "column" in data transform.'; + } + + throwError(errMsg); + } // [MEMO] + // Create a new dimensions structure for exposing. + // Do not expose all dimension info to users directly. + // Becuase the dimension is probably auto detected from data and not might reliable. + // Should not lead the transformers to think that is relialbe and return it. + // See [DIMENSION_INHERIT_RULE] in `sourceManager.ts`. + + + var dimensions = []; + var dimsByName = {}; + var dimsDef = internalSource.dimensionsDefine; + + if (dimsDef) { + each(dimsDef, function (dimDef, idx) { + var name = dimDef.name; + var dimDefExt = { + index: idx, + name: name, + displayName: dimDef.displayName + }; + dimensions.push(dimDefExt); // Users probably not sepcify dimension name. For simplicity, data transform + // do not generate dimension name. + + if (name != null) { + // Dimension name should not be duplicated. + // For simplicity, data transform forbid name duplication, do not generate + // new name like module `completeDimensions.ts` did, but just tell users. + var errMsg_1 = ''; + + if (hasOwn(dimsByName, name)) { + if ("development" !== 'production') { + errMsg_1 = 'dimension name "' + name + '" duplicated.'; + } + + throwError(errMsg_1); + } + + dimsByName[name] = dimDefExt; + } + }); + } // If dimension definitions are not defined and can not be detected. + // e.g., pure data `[[11, 22], ...]`. + else { + for (var i = 0; i < internalSource.dimensionsDetectedCount || 0; i++) { + // Do not generete name or anything others. The consequence process in + // `transform` or `series` probably have there own name generation strategry. + dimensions.push({ + index: i + }); + } + } // Implement public methods: + + + var rawItemGetter = getRawSourceItemGetter(sourceFormat, SERIES_LAYOUT_BY_COLUMN); + + if (externalTransform.__isBuiltIn) { + extSource.getRawDataItem = function (dataIndex) { + return rawItemGetter(data, sourceHeaderCount, dimensions, dataIndex); + }; + + extSource.getRawData = bind(getRawData, null, internalSource); + } + + extSource.cloneRawData = bind(cloneRawData, null, internalSource); + var rawCounter = getRawSourceDataCounter(sourceFormat, SERIES_LAYOUT_BY_COLUMN); + extSource.count = bind(rawCounter, null, data, sourceHeaderCount, dimensions); + var rawValueGetter = getRawSourceValueGetter(sourceFormat); + + extSource.retrieveValue = function (dataIndex, dimIndex) { + var rawItem = rawItemGetter(data, sourceHeaderCount, dimensions, dataIndex); + return retrieveValueFromItem(rawItem, dimIndex); + }; + + var retrieveValueFromItem = extSource.retrieveValueFromItem = function (dataItem, dimIndex) { + if (dataItem == null) { + return; + } + + var dimDef = dimensions[dimIndex]; // When `dimIndex` is `null`, `rawValueGetter` return the whole item. + + if (dimDef) { + return rawValueGetter(dataItem, dimIndex, dimDef.name); + } + }; + + extSource.getDimensionInfo = bind(getDimensionInfo, null, dimensions, dimsByName); + extSource.cloneAllDimensionInfo = bind(cloneAllDimensionInfo, null, dimensions); + return extSource; + } + + function getRawData(upstream) { + var sourceFormat = upstream.sourceFormat; + + if (!isSupportedSourceFormat(sourceFormat)) { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = '`getRawData` is not supported in source format ' + sourceFormat; + } + + throwError(errMsg); + } + + return upstream.data; + } + + function cloneRawData(upstream) { + var sourceFormat = upstream.sourceFormat; + var data = upstream.data; + + if (!isSupportedSourceFormat(sourceFormat)) { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = '`cloneRawData` is not supported in source format ' + sourceFormat; + } + + throwError(errMsg); + } + + if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) { + var result = []; + + for (var i = 0, len = data.length; i < len; i++) { + // Not strictly clone for performance + result.push(data[i].slice()); + } + + return result; + } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) { + var result = []; + + for (var i = 0, len = data.length; i < len; i++) { + // Not strictly clone for performance + result.push(extend({}, data[i])); + } + + return result; + } + } + + function getDimensionInfo(dimensions, dimsByName, dim) { + if (dim == null) { + return; + } // Keep the same logic as `List::getDimension` did. + + + if (isNumber(dim) // If being a number-like string but not being defined a dimension name. + || !isNaN(dim) && !hasOwn(dimsByName, dim)) { + return dimensions[dim]; + } else if (hasOwn(dimsByName, dim)) { + return dimsByName[dim]; + } + } + + function cloneAllDimensionInfo(dimensions) { + return clone(dimensions); + } + + var externalTransformMap = createHashMap(); + function registerExternalTransform(externalTransform) { + externalTransform = clone(externalTransform); + var type = externalTransform.type; + var errMsg = ''; + + if (!type) { + if ("development" !== 'production') { + errMsg = 'Must have a `type` when `registerTransform`.'; + } + + throwError(errMsg); + } + + var typeParsed = type.split(':'); + + if (typeParsed.length !== 2) { + if ("development" !== 'production') { + errMsg = 'Name must include namespace like "ns:regression".'; + } + + throwError(errMsg); + } // Namespace 'echarts:xxx' is official namespace, where the transforms should + // be called directly via 'xxx' rather than 'echarts:xxx'. + + + var isBuiltIn = false; + + if (typeParsed[0] === 'echarts') { + type = typeParsed[1]; + isBuiltIn = true; + } + + externalTransform.__isBuiltIn = isBuiltIn; + externalTransformMap.set(type, externalTransform); + } + function applyDataTransform(rawTransOption, sourceList, infoForPrint) { + var pipedTransOption = normalizeToArray(rawTransOption); + var pipeLen = pipedTransOption.length; + var errMsg = ''; + + if (!pipeLen) { + if ("development" !== 'production') { + errMsg = 'If `transform` declared, it should at least contain one transform.'; + } + + throwError(errMsg); + } + + for (var i = 0, len = pipeLen; i < len; i++) { + var transOption = pipedTransOption[i]; + sourceList = applySingleDataTransform(transOption, sourceList, infoForPrint, pipeLen === 1 ? null : i); // piped transform only support single input, except the fist one. + // piped transform only support single output, except the last one. + + if (i !== len - 1) { + sourceList.length = Math.max(sourceList.length, 1); + } + } + + return sourceList; + } + + function applySingleDataTransform(transOption, upSourceList, infoForPrint, // If `pipeIndex` is null/undefined, no piped transform. + pipeIndex) { + var errMsg = ''; + + if (!upSourceList.length) { + if ("development" !== 'production') { + errMsg = 'Must have at least one upstream dataset.'; + } + + throwError(errMsg); + } + + if (!isObject(transOption)) { + if ("development" !== 'production') { + errMsg = 'transform declaration must be an object rather than ' + typeof transOption + '.'; + } + + throwError(errMsg); + } + + var transType = transOption.type; + var externalTransform = externalTransformMap.get(transType); + + if (!externalTransform) { + if ("development" !== 'production') { + errMsg = 'Can not find transform on type "' + transType + '".'; + } + + throwError(errMsg); + } // Prepare source + + + var extUpSourceList = map(upSourceList, function (upSource) { + return createExternalSource(upSource, externalTransform); + }); + var resultList = normalizeToArray(externalTransform.transform({ + upstream: extUpSourceList[0], + upstreamList: extUpSourceList, + config: clone(transOption.config) + })); + + if ("development" !== 'production') { + if (transOption.print) { + var printStrArr = map(resultList, function (extSource) { + var pipeIndexStr = pipeIndex != null ? ' === pipe index: ' + pipeIndex : ''; + return ['=== dataset index: ' + infoForPrint.datasetIndex + pipeIndexStr + ' ===', '- transform result data:', makePrintable(extSource.data), '- transform result dimensions:', makePrintable(extSource.dimensions)].join('\n'); + }).join('\n'); + log(printStrArr); + } + } + + return map(resultList, function (result, resultIndex) { + var errMsg = ''; + + if (!isObject(result)) { + if ("development" !== 'production') { + errMsg = 'A transform should not return some empty results.'; + } + + throwError(errMsg); + } + + if (!result.data) { + if ("development" !== 'production') { + errMsg = 'Transform result data should be not be null or undefined'; + } + + throwError(errMsg); + } + + var sourceFormat = detectSourceFormat(result.data); + + if (!isSupportedSourceFormat(sourceFormat)) { + if ("development" !== 'production') { + errMsg = 'Transform result data should be array rows or object rows.'; + } + + throwError(errMsg); + } + + var resultMetaRawOption; + var firstUpSource = upSourceList[0]; + /** + * Intuitively, the end users known the content of the original `dataset.source`, + * calucating the transform result in mind. + * Suppose the original `dataset.source` is: + * ```js + * [ + * ['product', '2012', '2013', '2014', '2015'], + * ['AAA', 41.1, 30.4, 65.1, 53.3], + * ['BBB', 86.5, 92.1, 85.7, 83.1], + * ['CCC', 24.1, 67.2, 79.5, 86.4] + * ] + * ``` + * The dimension info have to be detected from the source data. + * Some of the transformers (like filter, sort) will follow the dimension info + * of upstream, while others use new dimensions (like aggregate). + * Transformer can output a field `dimensions` to define the its own output dimensions. + * We also allow transformers to ignore the output `dimensions` field, and + * inherit the upstream dimensions definition. It can reduce the burden of handling + * dimensions in transformers. + * + * See also [DIMENSION_INHERIT_RULE] in `sourceManager.ts`. + */ + + if (firstUpSource && resultIndex === 0 // If transformer returns `dimensions`, it means that the transformer has different + // dimensions definitions. We do not inherit anything from upstream. + && !result.dimensions) { + var startIndex = firstUpSource.startIndex; // We copy the header of upstream to the result becuase: + // (1) The returned data always does not contain header line and can not be used + // as dimension-detection. In this case we can not use "detected dimensions" of + // upstream directly, because it might be detected based on different `seriesLayoutBy`. + // (2) We should support that the series read the upstream source in `seriesLayoutBy: 'row'`. + // So the original detected header should be add to the result, otherwise they can not be read. + + if (startIndex) { + result.data = firstUpSource.data.slice(0, startIndex).concat(result.data); + } + + resultMetaRawOption = { + seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN, + sourceHeader: startIndex, + dimensions: firstUpSource.metaRawOption.dimensions + }; + } else { + resultMetaRawOption = { + seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN, + sourceHeader: 0, + dimensions: result.dimensions + }; + } + + return createSource(result.data, resultMetaRawOption, null); + }); + } + + function isSupportedSourceFormat(sourceFormat) { + return sourceFormat === SOURCE_FORMAT_ARRAY_ROWS || sourceFormat === SOURCE_FORMAT_OBJECT_ROWS; + } + + var UNDEFINED = 'undefined'; + /* global Float64Array, Int32Array, Uint32Array, Uint16Array */ + // Caution: MUST not use `new CtorUint32Array(arr, 0, len)`, because the Ctor of array is + // different from the Ctor of typed array. + + var CtorUint32Array = typeof Uint32Array === UNDEFINED ? Array : Uint32Array; + var CtorUint16Array = typeof Uint16Array === UNDEFINED ? Array : Uint16Array; + var CtorInt32Array = typeof Int32Array === UNDEFINED ? Array : Int32Array; + var CtorFloat64Array = typeof Float64Array === UNDEFINED ? Array : Float64Array; + /** + * Multi dimensional data store + */ + + var dataCtors = { + 'float': CtorFloat64Array, + 'int': CtorInt32Array, + // Ordinal data type can be string or int + 'ordinal': Array, + 'number': Array, + 'time': CtorFloat64Array + }; + var defaultDimValueGetters; + + function getIndicesCtor(rawCount) { + // The possible max value in this._indicies is always this._rawCount despite of filtering. + return rawCount > 65535 ? CtorUint32Array : CtorUint16Array; + } + + function getInitialExtent() { + return [Infinity, -Infinity]; + } + + function cloneChunk(originalChunk) { + var Ctor = originalChunk.constructor; // Only shallow clone is enough when Array. + + return Ctor === Array ? originalChunk.slice() : new Ctor(originalChunk); + } + + function prepareStore(store, dimIdx, dimType, end, append) { + var DataCtor = dataCtors[dimType || 'float']; + + if (append) { + var oldStore = store[dimIdx]; + var oldLen = oldStore && oldStore.length; + + if (!(oldLen === end)) { + var newStore = new DataCtor(end); // The cost of the copy is probably inconsiderable + // within the initial chunkSize. + + for (var j = 0; j < oldLen; j++) { + newStore[j] = oldStore[j]; + } + + store[dimIdx] = newStore; + } + } else { + store[dimIdx] = new DataCtor(end); + } + } + /** + * Basically, DataStore API keep immutable. + */ + + var DataStore = + /** @class */ + function () { + function DataStore() { + this._chunks = []; // It will not be calculated util needed. + + this._rawExtent = []; + this._extent = []; + this._count = 0; + this._rawCount = 0; + this._calcDimNameToIdx = createHashMap(); + } + /** + * Initialize from data + */ + + + DataStore.prototype.initData = function (provider, inputDimensions, dimValueGetter) { + if ("development" !== 'production') { + assert(isFunction(provider.getItem) && isFunction(provider.count), 'Inavlid data provider.'); + } + + this._provider = provider; // Clear + + this._chunks = []; + this._indices = null; + this.getRawIndex = this._getRawIdxIdentity; + var source = provider.getSource(); + var defaultGetter = this.defaultDimValueGetter = defaultDimValueGetters[source.sourceFormat]; // Default dim value getter + + this._dimValueGetter = dimValueGetter || defaultGetter; // Reset raw extent. + + this._rawExtent = []; + var willRetrieveDataByName = shouldRetrieveDataByName(source); + this._dimensions = map(inputDimensions, function (dim) { + if ("development" !== 'production') { + if (willRetrieveDataByName) { + assert(dim.property != null); + } + } + + return { + // Only pick these two props. Not leak other properties like orderMeta. + type: dim.type, + property: dim.property + }; + }); + + this._initDataFromProvider(0, provider.count()); + }; + + DataStore.prototype.getProvider = function () { + return this._provider; + }; + /** + * Caution: even when a `source` instance owned by a series, the created data store + * may still be shared by different sereis (the source hash does not use all `source` + * props, see `sourceManager`). In this case, the `source` props that are not used in + * hash (like `source.dimensionDefine`) probably only belongs to a certain series and + * thus should not be fetch here. + */ + + + DataStore.prototype.getSource = function () { + return this._provider.getSource(); + }; + /** + * @caution Only used in dataStack. + */ + + + DataStore.prototype.ensureCalculationDimension = function (dimName, type) { + var calcDimNameToIdx = this._calcDimNameToIdx; + var dimensions = this._dimensions; + var calcDimIdx = calcDimNameToIdx.get(dimName); + + if (calcDimIdx != null) { + if (dimensions[calcDimIdx].type === type) { + return calcDimIdx; + } + } else { + calcDimIdx = dimensions.length; + } + + dimensions[calcDimIdx] = { + type: type + }; + calcDimNameToIdx.set(dimName, calcDimIdx); + this._chunks[calcDimIdx] = new dataCtors[type || 'float'](this._rawCount); + this._rawExtent[calcDimIdx] = getInitialExtent(); + return calcDimIdx; + }; + + DataStore.prototype.collectOrdinalMeta = function (dimIdx, ordinalMeta) { + var chunk = this._chunks[dimIdx]; + var dim = this._dimensions[dimIdx]; + var rawExtents = this._rawExtent; + var offset = dim.ordinalOffset || 0; + var len = chunk.length; + + if (offset === 0) { + // We need to reset the rawExtent if collect is from start. + // Because this dimension may be guessed as number and calcuating a wrong extent. + rawExtents[dimIdx] = getInitialExtent(); + } + + var dimRawExtent = rawExtents[dimIdx]; // Parse from previous data offset. len may be changed after appendData + + for (var i = offset; i < len; i++) { + var val = chunk[i] = ordinalMeta.parseAndCollect(chunk[i]); + + if (!isNaN(val)) { + dimRawExtent[0] = Math.min(val, dimRawExtent[0]); + dimRawExtent[1] = Math.max(val, dimRawExtent[1]); + } + } + + dim.ordinalMeta = ordinalMeta; + dim.ordinalOffset = len; + dim.type = 'ordinal'; // Force to be ordinal + }; + + DataStore.prototype.getOrdinalMeta = function (dimIdx) { + var dimInfo = this._dimensions[dimIdx]; + var ordinalMeta = dimInfo.ordinalMeta; + return ordinalMeta; + }; + + DataStore.prototype.getDimensionProperty = function (dimIndex) { + var item = this._dimensions[dimIndex]; + return item && item.property; + }; + /** + * Caution: Can be only called on raw data (before `this._indices` created). + */ + + + DataStore.prototype.appendData = function (data) { + if ("development" !== 'production') { + assert(!this._indices, 'appendData can only be called on raw data.'); + } + + var provider = this._provider; + var start = this.count(); + provider.appendData(data); + var end = provider.count(); + + if (!provider.persistent) { + end += start; + } + + if (start < end) { + this._initDataFromProvider(start, end, true); + } + + return [start, end]; + }; + + DataStore.prototype.appendValues = function (values, minFillLen) { + var chunks = this._chunks; + var dimensions = this._dimensions; + var dimLen = dimensions.length; + var rawExtent = this._rawExtent; + var start = this.count(); + var end = start + Math.max(values.length, minFillLen || 0); + + for (var i = 0; i < dimLen; i++) { + var dim = dimensions[i]; + prepareStore(chunks, i, dim.type, end, true); + } + + var emptyDataItem = []; + + for (var idx = start; idx < end; idx++) { + var sourceIdx = idx - start; // Store the data by dimensions + + for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) { + var dim = dimensions[dimIdx]; + var val = defaultDimValueGetters.arrayRows.call(this, values[sourceIdx] || emptyDataItem, dim.property, sourceIdx, dimIdx); + chunks[dimIdx][idx] = val; + var dimRawExtent = rawExtent[dimIdx]; + val < dimRawExtent[0] && (dimRawExtent[0] = val); + val > dimRawExtent[1] && (dimRawExtent[1] = val); + } + } + + this._rawCount = this._count = end; + return { + start: start, + end: end + }; + }; + + DataStore.prototype._initDataFromProvider = function (start, end, append) { + var provider = this._provider; + var chunks = this._chunks; + var dimensions = this._dimensions; + var dimLen = dimensions.length; + var rawExtent = this._rawExtent; + var dimNames = map(dimensions, function (dim) { + return dim.property; + }); + + for (var i = 0; i < dimLen; i++) { + var dim = dimensions[i]; + + if (!rawExtent[i]) { + rawExtent[i] = getInitialExtent(); + } + + prepareStore(chunks, i, dim.type, end, append); + } + + if (provider.fillStorage) { + provider.fillStorage(start, end, chunks, rawExtent); + } else { + var dataItem = []; + + for (var idx = start; idx < end; idx++) { + // NOTICE: Try not to write things into dataItem + dataItem = provider.getItem(idx, dataItem); // Each data item is value + // [1, 2] + // 2 + // Bar chart, line chart which uses category axis + // only gives the 'y' value. 'x' value is the indices of category + // Use a tempValue to normalize the value to be a (x, y) value + // Store the data by dimensions + + for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) { + var dimStorage = chunks[dimIdx]; // PENDING NULL is empty or zero + + var val = this._dimValueGetter(dataItem, dimNames[dimIdx], idx, dimIdx); + + dimStorage[idx] = val; + var dimRawExtent = rawExtent[dimIdx]; + val < dimRawExtent[0] && (dimRawExtent[0] = val); + val > dimRawExtent[1] && (dimRawExtent[1] = val); + } + } + } + + if (!provider.persistent && provider.clean) { + // Clean unused data if data source is typed array. + provider.clean(); + } + + this._rawCount = this._count = end; // Reset data extent + + this._extent = []; + }; + + DataStore.prototype.count = function () { + return this._count; + }; + /** + * Get value. Return NaN if idx is out of range. + */ + + + DataStore.prototype.get = function (dim, idx) { + if (!(idx >= 0 && idx < this._count)) { + return NaN; + } + + var dimStore = this._chunks[dim]; + return dimStore ? dimStore[this.getRawIndex(idx)] : NaN; + }; + + DataStore.prototype.getValues = function (dimensions, idx) { + var values = []; + var dimArr = []; + + if (idx == null) { + idx = dimensions; // TODO get all from store? + + dimensions = []; // All dimensions + + for (var i = 0; i < this._dimensions.length; i++) { + dimArr.push(i); + } + } else { + dimArr = dimensions; + } + + for (var i = 0, len = dimArr.length; i < len; i++) { + values.push(this.get(dimArr[i], idx)); + } + + return values; + }; + /** + * @param dim concrete dim + */ + + + DataStore.prototype.getByRawIndex = function (dim, rawIdx) { + if (!(rawIdx >= 0 && rawIdx < this._rawCount)) { + return NaN; + } + + var dimStore = this._chunks[dim]; + return dimStore ? dimStore[rawIdx] : NaN; + }; + /** + * Get sum of data in one dimension + */ + + + DataStore.prototype.getSum = function (dim) { + var dimData = this._chunks[dim]; + var sum = 0; + + if (dimData) { + for (var i = 0, len = this.count(); i < len; i++) { + var value = this.get(dim, i); + + if (!isNaN(value)) { + sum += value; + } + } + } + + return sum; + }; + /** + * Get median of data in one dimension + */ + + + DataStore.prototype.getMedian = function (dim) { + var dimDataArray = []; // map all data of one dimension + + this.each([dim], function (val) { + if (!isNaN(val)) { + dimDataArray.push(val); + } + }); // TODO + // Use quick select? + + var sortedDimDataArray = dimDataArray.sort(function (a, b) { + return a - b; + }); + var len = this.count(); // calculate median + + return len === 0 ? 0 : len % 2 === 1 ? sortedDimDataArray[(len - 1) / 2] : (sortedDimDataArray[len / 2] + sortedDimDataArray[len / 2 - 1]) / 2; + }; + /** + * Retreive the index with given raw data index + */ + + + DataStore.prototype.indexOfRawIndex = function (rawIndex) { + if (rawIndex >= this._rawCount || rawIndex < 0) { + return -1; + } + + if (!this._indices) { + return rawIndex; + } // Indices are ascending + + + var indices = this._indices; // If rawIndex === dataIndex + + var rawDataIndex = indices[rawIndex]; + + if (rawDataIndex != null && rawDataIndex < this._count && rawDataIndex === rawIndex) { + return rawIndex; + } + + var left = 0; + var right = this._count - 1; + + while (left <= right) { + var mid = (left + right) / 2 | 0; + + if (indices[mid] < rawIndex) { + left = mid + 1; + } else if (indices[mid] > rawIndex) { + right = mid - 1; + } else { + return mid; + } + } + + return -1; + }; + /** + * Retreive the index of nearest value + * @param dim + * @param value + * @param [maxDistance=Infinity] + * @return If and only if multiple indices has + * the same value, they are put to the result. + */ + + + DataStore.prototype.indicesOfNearest = function (dim, value, maxDistance) { + var chunks = this._chunks; + var dimData = chunks[dim]; + var nearestIndices = []; + + if (!dimData) { + return nearestIndices; + } + + if (maxDistance == null) { + maxDistance = Infinity; + } + + var minDist = Infinity; + var minDiff = -1; + var nearestIndicesLen = 0; // Check the test case of `test/ut/spec/data/SeriesData.js`. + + for (var i = 0, len = this.count(); i < len; i++) { + var dataIndex = this.getRawIndex(i); + var diff = value - dimData[dataIndex]; + var dist = Math.abs(diff); + + if (dist <= maxDistance) { + // When the `value` is at the middle of `this.get(dim, i)` and `this.get(dim, i+1)`, + // we'd better not push both of them to `nearestIndices`, otherwise it is easy to + // get more than one item in `nearestIndices` (more specifically, in `tooltip`). + // So we chose the one that `diff >= 0` in this csae. + // But if `this.get(dim, i)` and `this.get(dim, j)` get the same value, both of them + // should be push to `nearestIndices`. + if (dist < minDist || dist === minDist && diff >= 0 && minDiff < 0) { + minDist = dist; + minDiff = diff; + nearestIndicesLen = 0; + } + + if (diff === minDiff) { + nearestIndices[nearestIndicesLen++] = i; + } + } + } + + nearestIndices.length = nearestIndicesLen; + return nearestIndices; + }; + + DataStore.prototype.getIndices = function () { + var newIndices; + var indices = this._indices; + + if (indices) { + var Ctor = indices.constructor; + var thisCount = this._count; // `new Array(a, b, c)` is different from `new Uint32Array(a, b, c)`. + + if (Ctor === Array) { + newIndices = new Ctor(thisCount); + + for (var i = 0; i < thisCount; i++) { + newIndices[i] = indices[i]; + } + } else { + newIndices = new Ctor(indices.buffer, 0, thisCount); + } + } else { + var Ctor = getIndicesCtor(this._rawCount); + newIndices = new Ctor(this.count()); + + for (var i = 0; i < newIndices.length; i++) { + newIndices[i] = i; + } + } + + return newIndices; + }; + /** + * Data filter. + */ + + + DataStore.prototype.filter = function (dims, cb) { + if (!this._count) { + return this; + } + + var newStore = this.clone(); + var count = newStore.count(); + var Ctor = getIndicesCtor(newStore._rawCount); + var newIndices = new Ctor(count); + var value = []; + var dimSize = dims.length; + var offset = 0; + var dim0 = dims[0]; + var chunks = newStore._chunks; + + for (var i = 0; i < count; i++) { + var keep = void 0; + var rawIdx = newStore.getRawIndex(i); // Simple optimization + + if (dimSize === 0) { + keep = cb(i); + } else if (dimSize === 1) { + var val = chunks[dim0][rawIdx]; + keep = cb(val, i); + } else { + var k = 0; + + for (; k < dimSize; k++) { + value[k] = chunks[dims[k]][rawIdx]; + } + + value[k] = i; + keep = cb.apply(null, value); + } + + if (keep) { + newIndices[offset++] = rawIdx; + } + } // Set indices after filtered. + + + if (offset < count) { + newStore._indices = newIndices; + } + + newStore._count = offset; // Reset data extent + + newStore._extent = []; + + newStore._updateGetRawIdx(); + + return newStore; + }; + /** + * Select data in range. (For optimization of filter) + * (Manually inline code, support 5 million data filtering in data zoom.) + */ + + + DataStore.prototype.selectRange = function (range) { + var newStore = this.clone(); + var len = newStore._count; + + if (!len) { + return this; + } + + var dims = keys(range); + var dimSize = dims.length; + + if (!dimSize) { + return this; + } + + var originalCount = newStore.count(); + var Ctor = getIndicesCtor(newStore._rawCount); + var newIndices = new Ctor(originalCount); + var offset = 0; + var dim0 = dims[0]; + var min = range[dim0][0]; + var max = range[dim0][1]; + var storeArr = newStore._chunks; + var quickFinished = false; + + if (!newStore._indices) { + // Extreme optimization for common case. About 2x faster in chrome. + var idx = 0; + + if (dimSize === 1) { + var dimStorage = storeArr[dims[0]]; + + for (var i = 0; i < len; i++) { + var val = dimStorage[i]; // NaN will not be filtered. Consider the case, in line chart, empty + // value indicates the line should be broken. But for the case like + // scatter plot, a data item with empty value will not be rendered, + // but the axis extent may be effected if some other dim of the data + // item has value. Fortunately it is not a significant negative effect. + + if (val >= min && val <= max || isNaN(val)) { + newIndices[offset++] = idx; + } + + idx++; + } + + quickFinished = true; + } else if (dimSize === 2) { + var dimStorage = storeArr[dims[0]]; + var dimStorage2 = storeArr[dims[1]]; + var min2 = range[dims[1]][0]; + var max2 = range[dims[1]][1]; + + for (var i = 0; i < len; i++) { + var val = dimStorage[i]; + var val2 = dimStorage2[i]; // Do not filter NaN, see comment above. + + if ((val >= min && val <= max || isNaN(val)) && (val2 >= min2 && val2 <= max2 || isNaN(val2))) { + newIndices[offset++] = idx; + } + + idx++; + } + + quickFinished = true; + } + } + + if (!quickFinished) { + if (dimSize === 1) { + for (var i = 0; i < originalCount; i++) { + var rawIndex = newStore.getRawIndex(i); + var val = storeArr[dims[0]][rawIndex]; // Do not filter NaN, see comment above. + + if (val >= min && val <= max || isNaN(val)) { + newIndices[offset++] = rawIndex; + } + } + } else { + for (var i = 0; i < originalCount; i++) { + var keep = true; + var rawIndex = newStore.getRawIndex(i); + + for (var k = 0; k < dimSize; k++) { + var dimk = dims[k]; + var val = storeArr[dimk][rawIndex]; // Do not filter NaN, see comment above. + + if (val < range[dimk][0] || val > range[dimk][1]) { + keep = false; + } + } + + if (keep) { + newIndices[offset++] = newStore.getRawIndex(i); + } + } + } + } // Set indices after filtered. + + + if (offset < originalCount) { + newStore._indices = newIndices; + } + + newStore._count = offset; // Reset data extent + + newStore._extent = []; + + newStore._updateGetRawIdx(); + + return newStore; + }; // /** + // * Data mapping to a plain array + // */ + // mapArray(dims: DimensionIndex[], cb: MapArrayCb): any[] { + // const result: any[] = []; + // this.each(dims, function () { + // result.push(cb && (cb as MapArrayCb).apply(null, arguments)); + // }); + // return result; + // } + + /** + * Data mapping to a new List with given dimensions + */ + + + DataStore.prototype.map = function (dims, cb) { + // TODO only clone picked chunks. + var target = this.clone(dims); + + this._updateDims(target, dims, cb); + + return target; + }; + /** + * @caution Danger!! Only used in dataStack. + */ + + + DataStore.prototype.modify = function (dims, cb) { + this._updateDims(this, dims, cb); + }; + + DataStore.prototype._updateDims = function (target, dims, cb) { + var targetChunks = target._chunks; + var tmpRetValue = []; + var dimSize = dims.length; + var dataCount = target.count(); + var values = []; + var rawExtent = target._rawExtent; + + for (var i = 0; i < dims.length; i++) { + rawExtent[dims[i]] = getInitialExtent(); + } + + for (var dataIndex = 0; dataIndex < dataCount; dataIndex++) { + var rawIndex = target.getRawIndex(dataIndex); + + for (var k = 0; k < dimSize; k++) { + values[k] = targetChunks[dims[k]][rawIndex]; + } + + values[dimSize] = dataIndex; + var retValue = cb && cb.apply(null, values); + + if (retValue != null) { + // a number or string (in oridinal dimension)? + if (typeof retValue !== 'object') { + tmpRetValue[0] = retValue; + retValue = tmpRetValue; + } + + for (var i = 0; i < retValue.length; i++) { + var dim = dims[i]; + var val = retValue[i]; + var rawExtentOnDim = rawExtent[dim]; + var dimStore = targetChunks[dim]; + + if (dimStore) { + dimStore[rawIndex] = val; + } + + if (val < rawExtentOnDim[0]) { + rawExtentOnDim[0] = val; + } + + if (val > rawExtentOnDim[1]) { + rawExtentOnDim[1] = val; + } + } + } + } + }; + /** + * Large data down sampling using largest-triangle-three-buckets + * @param {string} valueDimension + * @param {number} targetCount + */ + + + DataStore.prototype.lttbDownSample = function (valueDimension, rate) { + var target = this.clone([valueDimension], true); + var targetStorage = target._chunks; + var dimStore = targetStorage[valueDimension]; + var len = this.count(); + var sampledIndex = 0; + var frameSize = Math.floor(1 / rate); + var currentRawIndex = this.getRawIndex(0); + var maxArea; + var area; + var nextRawIndex; + var newIndices = new (getIndicesCtor(this._rawCount))(Math.min((Math.ceil(len / frameSize) + 2) * 2, len)); // First frame use the first data. + + newIndices[sampledIndex++] = currentRawIndex; + + for (var i = 1; i < len - 1; i += frameSize) { + var nextFrameStart = Math.min(i + frameSize, len - 1); + var nextFrameEnd = Math.min(i + frameSize * 2, len); + var avgX = (nextFrameEnd + nextFrameStart) / 2; + var avgY = 0; + + for (var idx = nextFrameStart; idx < nextFrameEnd; idx++) { + var rawIndex = this.getRawIndex(idx); + var y = dimStore[rawIndex]; + + if (isNaN(y)) { + continue; + } + + avgY += y; + } + + avgY /= nextFrameEnd - nextFrameStart; + var frameStart = i; + var frameEnd = Math.min(i + frameSize, len); + var pointAX = i - 1; + var pointAY = dimStore[currentRawIndex]; + maxArea = -1; + nextRawIndex = frameStart; + var firstNaNIndex = -1; + var countNaN = 0; // Find a point from current frame that construct a triangel with largest area with previous selected point + // And the average of next frame. + + for (var idx = frameStart; idx < frameEnd; idx++) { + var rawIndex = this.getRawIndex(idx); + var y = dimStore[rawIndex]; + + if (isNaN(y)) { + countNaN++; + + if (firstNaNIndex < 0) { + firstNaNIndex = rawIndex; + } + + continue; + } // Calculate triangle area over three buckets + + + area = Math.abs((pointAX - avgX) * (y - pointAY) - (pointAX - idx) * (avgY - pointAY)); + + if (area > maxArea) { + maxArea = area; + nextRawIndex = rawIndex; // Next a is this b + } + } + + if (countNaN > 0 && countNaN < frameEnd - frameStart) { + // Append first NaN point in every bucket. + // It is necessary to ensure the correct order of indices. + newIndices[sampledIndex++] = Math.min(firstNaNIndex, nextRawIndex); + nextRawIndex = Math.max(firstNaNIndex, nextRawIndex); + } + + newIndices[sampledIndex++] = nextRawIndex; + currentRawIndex = nextRawIndex; // This a is the next a (chosen b) + } // First frame use the last data. + + + newIndices[sampledIndex++] = this.getRawIndex(len - 1); + target._count = sampledIndex; + target._indices = newIndices; + target.getRawIndex = this._getRawIdx; + return target; + }; + /** + * Large data down sampling on given dimension + * @param sampleIndex Sample index for name and id + */ + + + DataStore.prototype.downSample = function (dimension, rate, sampleValue, sampleIndex) { + var target = this.clone([dimension], true); + var targetStorage = target._chunks; + var frameValues = []; + var frameSize = Math.floor(1 / rate); + var dimStore = targetStorage[dimension]; + var len = this.count(); + var rawExtentOnDim = target._rawExtent[dimension] = getInitialExtent(); + var newIndices = new (getIndicesCtor(this._rawCount))(Math.ceil(len / frameSize)); + var offset = 0; + + for (var i = 0; i < len; i += frameSize) { + // Last frame + if (frameSize > len - i) { + frameSize = len - i; + frameValues.length = frameSize; + } + + for (var k = 0; k < frameSize; k++) { + var dataIdx = this.getRawIndex(i + k); + frameValues[k] = dimStore[dataIdx]; + } + + var value = sampleValue(frameValues); + var sampleFrameIdx = this.getRawIndex(Math.min(i + sampleIndex(frameValues, value) || 0, len - 1)); // Only write value on the filtered data + + dimStore[sampleFrameIdx] = value; + + if (value < rawExtentOnDim[0]) { + rawExtentOnDim[0] = value; + } + + if (value > rawExtentOnDim[1]) { + rawExtentOnDim[1] = value; + } + + newIndices[offset++] = sampleFrameIdx; + } + + target._count = offset; + target._indices = newIndices; + + target._updateGetRawIdx(); + + return target; + }; + /** + * Data iteration + * @param ctx default this + * @example + * list.each('x', function (x, idx) {}); + * list.each(['x', 'y'], function (x, y, idx) {}); + * list.each(function (idx) {}) + */ + + + DataStore.prototype.each = function (dims, cb) { + if (!this._count) { + return; + } + + var dimSize = dims.length; + var chunks = this._chunks; + + for (var i = 0, len = this.count(); i < len; i++) { + var rawIdx = this.getRawIndex(i); // Simple optimization + + switch (dimSize) { + case 0: + cb(i); + break; + + case 1: + cb(chunks[dims[0]][rawIdx], i); + break; + + case 2: + cb(chunks[dims[0]][rawIdx], chunks[dims[1]][rawIdx], i); + break; + + default: + var k = 0; + var value = []; + + for (; k < dimSize; k++) { + value[k] = chunks[dims[k]][rawIdx]; + } // Index + + + value[k] = i; + cb.apply(null, value); + } + } + }; + /** + * Get extent of data in one dimension + */ + + + DataStore.prototype.getDataExtent = function (dim) { + // Make sure use concrete dim as cache name. + var dimData = this._chunks[dim]; + var initialExtent = getInitialExtent(); + + if (!dimData) { + return initialExtent; + } // Make more strict checkings to ensure hitting cache. + + + var currEnd = this.count(); // Consider the most cases when using data zoom, `getDataExtent` + // happened before filtering. We cache raw extent, which is not + // necessary to be cleared and recalculated when restore data. + + var useRaw = !this._indices; + var dimExtent; + + if (useRaw) { + return this._rawExtent[dim].slice(); + } + + dimExtent = this._extent[dim]; + + if (dimExtent) { + return dimExtent.slice(); + } + + dimExtent = initialExtent; + var min = dimExtent[0]; + var max = dimExtent[1]; + + for (var i = 0; i < currEnd; i++) { + var rawIdx = this.getRawIndex(i); + var value = dimData[rawIdx]; + value < min && (min = value); + value > max && (max = value); + } + + dimExtent = [min, max]; + this._extent[dim] = dimExtent; + return dimExtent; + }; + /** + * Get raw data item + */ + + + DataStore.prototype.getRawDataItem = function (idx) { + var rawIdx = this.getRawIndex(idx); + + if (!this._provider.persistent) { + var val = []; + var chunks = this._chunks; + + for (var i = 0; i < chunks.length; i++) { + val.push(chunks[i][rawIdx]); + } + + return val; + } else { + return this._provider.getItem(rawIdx); + } + }; + /** + * Clone shallow. + * + * @param clonedDims Determine which dims to clone. Will share the data if not specified. + */ + + + DataStore.prototype.clone = function (clonedDims, ignoreIndices) { + var target = new DataStore(); + var chunks = this._chunks; + var clonedDimsMap = clonedDims && reduce(clonedDims, function (obj, dimIdx) { + obj[dimIdx] = true; + return obj; + }, {}); + + if (clonedDimsMap) { + for (var i = 0; i < chunks.length; i++) { + // Not clone if dim is not picked. + target._chunks[i] = !clonedDimsMap[i] ? chunks[i] : cloneChunk(chunks[i]); + } + } else { + target._chunks = chunks; + } + + this._copyCommonProps(target); + + if (!ignoreIndices) { + target._indices = this._cloneIndices(); + } + + target._updateGetRawIdx(); + + return target; + }; + + DataStore.prototype._copyCommonProps = function (target) { + target._count = this._count; + target._rawCount = this._rawCount; + target._provider = this._provider; + target._dimensions = this._dimensions; + target._extent = clone(this._extent); + target._rawExtent = clone(this._rawExtent); + }; + + DataStore.prototype._cloneIndices = function () { + if (this._indices) { + var Ctor = this._indices.constructor; + var indices = void 0; + + if (Ctor === Array) { + var thisCount = this._indices.length; + indices = new Ctor(thisCount); + + for (var i = 0; i < thisCount; i++) { + indices[i] = this._indices[i]; + } + } else { + indices = new Ctor(this._indices); + } + + return indices; + } + + return null; + }; + + DataStore.prototype._getRawIdxIdentity = function (idx) { + return idx; + }; + + DataStore.prototype._getRawIdx = function (idx) { + if (idx < this._count && idx >= 0) { + return this._indices[idx]; + } + + return -1; + }; + + DataStore.prototype._updateGetRawIdx = function () { + this.getRawIndex = this._indices ? this._getRawIdx : this._getRawIdxIdentity; + }; + + DataStore.internalField = function () { + function getDimValueSimply(dataItem, property, dataIndex, dimIndex) { + return parseDataValue(dataItem[dimIndex], this._dimensions[dimIndex]); + } + + defaultDimValueGetters = { + arrayRows: getDimValueSimply, + objectRows: function (dataItem, property, dataIndex, dimIndex) { + return parseDataValue(dataItem[property], this._dimensions[dimIndex]); + }, + keyedColumns: getDimValueSimply, + original: function (dataItem, property, dataIndex, dimIndex) { + // Performance sensitive, do not use modelUtil.getDataItemValue. + // If dataItem is an plain object with no value field, the let `value` + // will be assigned with the object, but it will be tread correctly + // in the `convertValue`. + var value = dataItem && (dataItem.value == null ? dataItem : dataItem.value); + return parseDataValue(value instanceof Array ? value[dimIndex] // If value is a single number or something else not array. + : value, this._dimensions[dimIndex]); + }, + typedArray: function (dataItem, property, dataIndex, dimIndex) { + return dataItem[dimIndex]; + } + }; + }(); + + return DataStore; + }(); + + /** + * [REQUIREMENT_MEMO]: + * (0) `metaRawOption` means `dimensions`/`sourceHeader`/`seriesLayoutBy` in raw option. + * (1) Keep support the feature: `metaRawOption` can be specified both on `series` and + * `root-dataset`. Them on `series` has higher priority. + * (2) Do not support to set `metaRawOption` on a `non-root-dataset`, because it might + * confuse users: whether those props indicate how to visit the upstream source or visit + * the transform result source, and some transforms has nothing to do with these props, + * and some transforms might have multiple upstream. + * (3) Transforms should specify `metaRawOption` in each output, just like they can be + * declared in `root-dataset`. + * (4) At present only support visit source in `SERIES_LAYOUT_BY_COLUMN` in transforms. + * That is for reducing complexity in transfroms. + * PENDING: Whether to provide transposition transform? + * + * [IMPLEMENTAION_MEMO]: + * "sourceVisitConfig" are calculated from `metaRawOption` and `data`. + * They will not be calculated until `source` is about to be visited (to prevent from + * duplicate calcuation). `source` is visited only in series and input to transforms. + * + * [DIMENSION_INHERIT_RULE]: + * By default the dimensions are inherited from ancestors, unless a transform return + * a new dimensions definition. + * Consider the case: + * ```js + * dataset: [{ + * source: [ ['Product', 'Sales', 'Prise'], ['Cookies', 321, 44.21], ...] + * }, { + * transform: { type: 'filter', ... } + * }] + * dataset: [{ + * dimension: ['Product', 'Sales', 'Prise'], + * source: [ ['Cookies', 321, 44.21], ...] + * }, { + * transform: { type: 'filter', ... } + * }] + * ``` + * The two types of option should have the same behavior after transform. + * + * + * [SCENARIO]: + * (1) Provide source data directly: + * ```js + * series: { + * encode: {...}, + * dimensions: [...] + * seriesLayoutBy: 'row', + * data: [[...]] + * } + * ``` + * (2) Series refer to dataset. + * ```js + * series: [{ + * encode: {...} + * // Ignore datasetIndex means `datasetIndex: 0` + * // and the dimensions defination in dataset is used + * }, { + * encode: {...}, + * seriesLayoutBy: 'column', + * datasetIndex: 1 + * }] + * ``` + * (3) dataset transform + * ```js + * dataset: [{ + * source: [...] + * }, { + * source: [...] + * }, { + * // By default from 0. + * transform: { type: 'filter', config: {...} } + * }, { + * // Piped. + * transform: [ + * { type: 'filter', config: {...} }, + * { type: 'sort', config: {...} } + * ] + * }, { + * id: 'regressionData', + * fromDatasetIndex: 1, + * // Third-party transform + * transform: { type: 'ecStat:regression', config: {...} } + * }, { + * // retrieve the extra result. + * id: 'regressionFormula', + * fromDatasetId: 'regressionData', + * fromTransformResult: 1 + * }] + * ``` + */ + + var SourceManager = + /** @class */ + function () { + function SourceManager(sourceHost) { + // Cached source. Do not repeat calculating if not dirty. + this._sourceList = []; + this._storeList = []; // version sign of each upstream source manager. + + this._upstreamSignList = []; + this._versionSignBase = 0; + this._dirty = true; + this._sourceHost = sourceHost; + } + /** + * Mark dirty. + */ + + + SourceManager.prototype.dirty = function () { + this._setLocalSource([], []); + + this._storeList = []; + this._dirty = true; + }; + + SourceManager.prototype._setLocalSource = function (sourceList, upstreamSignList) { + this._sourceList = sourceList; + this._upstreamSignList = upstreamSignList; + this._versionSignBase++; + + if (this._versionSignBase > 9e10) { + this._versionSignBase = 0; + } + }; + /** + * For detecting whether the upstream source is dirty, so that + * the local cached source (in `_sourceList`) should be discarded. + */ + + + SourceManager.prototype._getVersionSign = function () { + return this._sourceHost.uid + '_' + this._versionSignBase; + }; + /** + * Always return a source instance. Otherwise throw error. + */ + + + SourceManager.prototype.prepareSource = function () { + // For the case that call `setOption` multiple time but no data changed, + // cache the result source to prevent from repeating transform. + if (this._isDirty()) { + this._createSource(); + + this._dirty = false; + } + }; + + SourceManager.prototype._createSource = function () { + this._setLocalSource([], []); + + var sourceHost = this._sourceHost; + + var upSourceMgrList = this._getUpstreamSourceManagers(); + + var hasUpstream = !!upSourceMgrList.length; + var resultSourceList; + var upstreamSignList; + + if (isSeries(sourceHost)) { + var seriesModel = sourceHost; + var data = void 0; + var sourceFormat = void 0; + var upSource = void 0; // Has upstream dataset + + if (hasUpstream) { + var upSourceMgr = upSourceMgrList[0]; + upSourceMgr.prepareSource(); + upSource = upSourceMgr.getSource(); + data = upSource.data; + sourceFormat = upSource.sourceFormat; + upstreamSignList = [upSourceMgr._getVersionSign()]; + } // Series data is from own. + else { + data = seriesModel.get('data', true); + sourceFormat = isTypedArray(data) ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL; + upstreamSignList = []; + } // See [REQUIREMENT_MEMO], merge settings on series and parent dataset if it is root. + + + var newMetaRawOption = this._getSourceMetaRawOption() || {}; + var upMetaRawOption = upSource && upSource.metaRawOption || {}; + var seriesLayoutBy = retrieve2(newMetaRawOption.seriesLayoutBy, upMetaRawOption.seriesLayoutBy) || null; + var sourceHeader = retrieve2(newMetaRawOption.sourceHeader, upMetaRawOption.sourceHeader); // Note here we should not use `upSource.dimensionsDefine`. Consider the case: + // `upSource.dimensionsDefine` is detected by `seriesLayoutBy: 'column'`, + // but series need `seriesLayoutBy: 'row'`. + + var dimensions = retrieve2(newMetaRawOption.dimensions, upMetaRawOption.dimensions); // We share source with dataset as much as possible + // to avoid extra memroy cost of high dimensional data. + + var needsCreateSource = seriesLayoutBy !== upMetaRawOption.seriesLayoutBy || !!sourceHeader !== !!upMetaRawOption.sourceHeader || dimensions; + resultSourceList = needsCreateSource ? [createSource(data, { + seriesLayoutBy: seriesLayoutBy, + sourceHeader: sourceHeader, + dimensions: dimensions + }, sourceFormat)] : []; + } else { + var datasetModel = sourceHost; // Has upstream dataset. + + if (hasUpstream) { + var result = this._applyTransform(upSourceMgrList); + + resultSourceList = result.sourceList; + upstreamSignList = result.upstreamSignList; + } // Is root dataset. + else { + var sourceData = datasetModel.get('source', true); + resultSourceList = [createSource(sourceData, this._getSourceMetaRawOption(), null)]; + upstreamSignList = []; + } + } + + if ("development" !== 'production') { + assert(resultSourceList && upstreamSignList); + } + + this._setLocalSource(resultSourceList, upstreamSignList); + }; + + SourceManager.prototype._applyTransform = function (upMgrList) { + var datasetModel = this._sourceHost; + var transformOption = datasetModel.get('transform', true); + var fromTransformResult = datasetModel.get('fromTransformResult', true); + + if ("development" !== 'production') { + assert(fromTransformResult != null || transformOption != null); + } + + if (fromTransformResult != null) { + var errMsg = ''; + + if (upMgrList.length !== 1) { + if ("development" !== 'production') { + errMsg = 'When using `fromTransformResult`, there should be only one upstream dataset'; + } + + doThrow(errMsg); + } + } + + var sourceList; + var upSourceList = []; + var upstreamSignList = []; + each(upMgrList, function (upMgr) { + upMgr.prepareSource(); + var upSource = upMgr.getSource(fromTransformResult || 0); + var errMsg = ''; + + if (fromTransformResult != null && !upSource) { + if ("development" !== 'production') { + errMsg = 'Can not retrieve result by `fromTransformResult`: ' + fromTransformResult; + } + + doThrow(errMsg); + } + + upSourceList.push(upSource); + upstreamSignList.push(upMgr._getVersionSign()); + }); + + if (transformOption) { + sourceList = applyDataTransform(transformOption, upSourceList, { + datasetIndex: datasetModel.componentIndex + }); + } else if (fromTransformResult != null) { + sourceList = [cloneSourceShallow(upSourceList[0])]; + } + + return { + sourceList: sourceList, + upstreamSignList: upstreamSignList + }; + }; + + SourceManager.prototype._isDirty = function () { + if (this._dirty) { + return true; + } // All sourceList is from the some upsteam. + + + var upSourceMgrList = this._getUpstreamSourceManagers(); + + for (var i = 0; i < upSourceMgrList.length; i++) { + var upSrcMgr = upSourceMgrList[i]; + + if ( // Consider the case that there is ancestor diry, call it recursively. + // The performance is probably not an issue because usually the chain is not long. + upSrcMgr._isDirty() || this._upstreamSignList[i] !== upSrcMgr._getVersionSign()) { + return true; + } + } + }; + /** + * @param sourceIndex By defualt 0, means "main source". + * Most cases there is only one source. + */ + + + SourceManager.prototype.getSource = function (sourceIndex) { + sourceIndex = sourceIndex || 0; + var source = this._sourceList[sourceIndex]; + + if (!source) { + // Series may share source instance with dataset. + var upSourceMgrList = this._getUpstreamSourceManagers(); + + return upSourceMgrList[0] && upSourceMgrList[0].getSource(sourceIndex); + } + + return source; + }; + /** + * + * Get a data store which can be shared across series. + * Only available for series. + * + * @param seriesDimRequest Dimensions that are generated in series. + * Should have been sorted by `storeDimIndex` asc. + */ + + + SourceManager.prototype.getSharedDataStore = function (seriesDimRequest) { + if ("development" !== 'production') { + assert(isSeries(this._sourceHost), 'Can only call getDataStore on series source manager.'); + } + + var schema = seriesDimRequest.makeStoreSchema(); + return this._innerGetDataStore(schema.dimensions, seriesDimRequest.source, schema.hash); + }; + + SourceManager.prototype._innerGetDataStore = function (storeDims, seriesSource, sourceReadKey) { + // TODO Can use other sourceIndex? + var sourceIndex = 0; + var storeList = this._storeList; + var cachedStoreMap = storeList[sourceIndex]; + + if (!cachedStoreMap) { + cachedStoreMap = storeList[sourceIndex] = {}; + } + + var cachedStore = cachedStoreMap[sourceReadKey]; + + if (!cachedStore) { + var upSourceMgr = this._getUpstreamSourceManagers()[0]; + + if (isSeries(this._sourceHost) && upSourceMgr) { + cachedStore = upSourceMgr._innerGetDataStore(storeDims, seriesSource, sourceReadKey); + } else { + cachedStore = new DataStore(); // Always create store from source of series. + + cachedStore.initData(new DefaultDataProvider(seriesSource, storeDims.length), storeDims); + } + + cachedStoreMap[sourceReadKey] = cachedStore; + } + + return cachedStore; + }; + /** + * PEDING: Is it fast enough? + * If no upstream, return empty array. + */ + + + SourceManager.prototype._getUpstreamSourceManagers = function () { + // Always get the relationship from the raw option. + // Do not cache the link of the dependency graph, so that + // no need to update them when change happen. + var sourceHost = this._sourceHost; + + if (isSeries(sourceHost)) { + var datasetModel = querySeriesUpstreamDatasetModel(sourceHost); + return !datasetModel ? [] : [datasetModel.getSourceManager()]; + } else { + return map(queryDatasetUpstreamDatasetModels(sourceHost), function (datasetModel) { + return datasetModel.getSourceManager(); + }); + } + }; + + SourceManager.prototype._getSourceMetaRawOption = function () { + var sourceHost = this._sourceHost; + var seriesLayoutBy; + var sourceHeader; + var dimensions; + + if (isSeries(sourceHost)) { + seriesLayoutBy = sourceHost.get('seriesLayoutBy', true); + sourceHeader = sourceHost.get('sourceHeader', true); + dimensions = sourceHost.get('dimensions', true); + } // See [REQUIREMENT_MEMO], `non-root-dataset` do not support them. + else if (!this._getUpstreamSourceManagers().length) { + var model = sourceHost; + seriesLayoutBy = model.get('seriesLayoutBy', true); + sourceHeader = model.get('sourceHeader', true); + dimensions = model.get('dimensions', true); + } + + return { + seriesLayoutBy: seriesLayoutBy, + sourceHeader: sourceHeader, + dimensions: dimensions + }; + }; + + return SourceManager; + }(); + // disable the transform merge, but do not disable transfrom clone from rawOption. + + function disableTransformOptionMerge(datasetModel) { + var transformOption = datasetModel.option.transform; + transformOption && setAsPrimitive(datasetModel.option.transform); + } + + function isSeries(sourceHost) { + // Avoid circular dependency with Series.ts + return sourceHost.mainType === 'series'; + } + + function doThrow(errMsg) { + throw new Error(errMsg); + } + + var TOOLTIP_LINE_HEIGHT_CSS = 'line-height:1'; // TODO: more textStyle option + + function getTooltipTextStyle(textStyle, renderMode) { + var nameFontColor = textStyle.color || '#6e7079'; + var nameFontSize = textStyle.fontSize || 12; + var nameFontWeight = textStyle.fontWeight || '400'; + var valueFontColor = textStyle.color || '#464646'; + var valueFontSize = textStyle.fontSize || 14; + var valueFontWeight = textStyle.fontWeight || '900'; + + if (renderMode === 'html') { + // `textStyle` is probably from user input, should be encoded to reduce security risk. + return { + // eslint-disable-next-line max-len + nameStyle: "font-size:" + encodeHTML(nameFontSize + '') + "px;color:" + encodeHTML(nameFontColor) + ";font-weight:" + encodeHTML(nameFontWeight + ''), + // eslint-disable-next-line max-len + valueStyle: "font-size:" + encodeHTML(valueFontSize + '') + "px;color:" + encodeHTML(valueFontColor) + ";font-weight:" + encodeHTML(valueFontWeight + '') + }; + } else { + return { + nameStyle: { + fontSize: nameFontSize, + fill: nameFontColor, + fontWeight: nameFontWeight + }, + valueStyle: { + fontSize: valueFontSize, + fill: valueFontColor, + fontWeight: valueFontWeight + } + }; + } + } // See `TooltipMarkupLayoutIntent['innerGapLevel']`. + // (value from UI design) + + + var HTML_GAPS = [0, 10, 20, 30]; + var RICH_TEXT_GAPS = ['', '\n', '\n\n', '\n\n\n']; // eslint-disable-next-line max-len + + function createTooltipMarkup(type, option) { + option.type = type; + return option; + } + + function isSectionFragment(frag) { + return frag.type === 'section'; + } + + function getBuilder(frag) { + return isSectionFragment(frag) ? buildSection : buildNameValue; + } + + function getBlockGapLevel(frag) { + if (isSectionFragment(frag)) { + var gapLevel_1 = 0; + var subBlockLen = frag.blocks.length; + var hasInnerGap_1 = subBlockLen > 1 || subBlockLen > 0 && !frag.noHeader; + each(frag.blocks, function (subBlock) { + var subGapLevel = getBlockGapLevel(subBlock); // If the some of the sub-blocks have some gaps (like 10px) inside, this block + // should use a larger gap (like 20px) to distinguish those sub-blocks. + + if (subGapLevel >= gapLevel_1) { + gapLevel_1 = subGapLevel + +(hasInnerGap_1 && ( // 0 always can not be readable gap level. + !subGapLevel // If no header, always keep the sub gap level. Otherwise + // look weird in case `multipleSeries`. + || isSectionFragment(subBlock) && !subBlock.noHeader)); + } + }); + return gapLevel_1; + } + + return 0; + } + + function buildSection(ctx, fragment, topMarginForOuterGap, toolTipTextStyle) { + var noHeader = fragment.noHeader; + var gaps = getGap(getBlockGapLevel(fragment)); + var subMarkupTextList = []; + var subBlocks = fragment.blocks || []; + assert(!subBlocks || isArray(subBlocks)); + subBlocks = subBlocks || []; + var orderMode = ctx.orderMode; + + if (fragment.sortBlocks && orderMode) { + subBlocks = subBlocks.slice(); + var orderMap = { + valueAsc: 'asc', + valueDesc: 'desc' + }; + + if (hasOwn(orderMap, orderMode)) { + var comparator_1 = new SortOrderComparator(orderMap[orderMode], null); + subBlocks.sort(function (a, b) { + return comparator_1.evaluate(a.sortParam, b.sortParam); + }); + } // FIXME 'seriesDesc' necessary? + else if (orderMode === 'seriesDesc') { + subBlocks.reverse(); + } + } + + each(subBlocks, function (subBlock, idx) { + var valueFormatter = fragment.valueFormatter; + var subMarkupText = getBuilder(subBlock)( // Inherit valueFormatter + valueFormatter ? extend(extend({}, ctx), { + valueFormatter: valueFormatter + }) : ctx, subBlock, idx > 0 ? gaps.html : 0, toolTipTextStyle); + subMarkupText != null && subMarkupTextList.push(subMarkupText); + }); + var subMarkupText = ctx.renderMode === 'richText' ? subMarkupTextList.join(gaps.richText) : wrapBlockHTML(subMarkupTextList.join(''), noHeader ? topMarginForOuterGap : gaps.html); + + if (noHeader) { + return subMarkupText; + } + + var displayableHeader = makeValueReadable(fragment.header, 'ordinal', ctx.useUTC); + var nameStyle = getTooltipTextStyle(toolTipTextStyle, ctx.renderMode).nameStyle; + + if (ctx.renderMode === 'richText') { + return wrapInlineNameRichText(ctx, displayableHeader, nameStyle) + gaps.richText + subMarkupText; + } else { + return wrapBlockHTML("
                                                                                          " + encodeHTML(displayableHeader) + '
                                                                                          ' + subMarkupText, topMarginForOuterGap); + } + } + + function buildNameValue(ctx, fragment, topMarginForOuterGap, toolTipTextStyle) { + var renderMode = ctx.renderMode; + var noName = fragment.noName; + var noValue = fragment.noValue; + var noMarker = !fragment.markerType; + var name = fragment.name; + var useUTC = ctx.useUTC; + + var valueFormatter = fragment.valueFormatter || ctx.valueFormatter || function (value) { + value = isArray(value) ? value : [value]; + return map(value, function (val, idx) { + return makeValueReadable(val, isArray(valueTypeOption) ? valueTypeOption[idx] : valueTypeOption, useUTC); + }); + }; + + if (noName && noValue) { + return; + } + + var markerStr = noMarker ? '' : ctx.markupStyleCreator.makeTooltipMarker(fragment.markerType, fragment.markerColor || '#333', renderMode); + var readableName = noName ? '' : makeValueReadable(name, 'ordinal', useUTC); + var valueTypeOption = fragment.valueType; + var readableValueList = noValue ? [] : valueFormatter(fragment.value); + var valueAlignRight = !noMarker || !noName; // It little weird if only value next to marker but far from marker. + + var valueCloseToMarker = !noMarker && noName; + + var _a = getTooltipTextStyle(toolTipTextStyle, renderMode), + nameStyle = _a.nameStyle, + valueStyle = _a.valueStyle; + + return renderMode === 'richText' ? (noMarker ? '' : markerStr) + (noName ? '' : wrapInlineNameRichText(ctx, readableName, nameStyle)) // Value has commas inside, so use ' ' as delimiter for multiple values. + + (noValue ? '' : wrapInlineValueRichText(ctx, readableValueList, valueAlignRight, valueCloseToMarker, valueStyle)) : wrapBlockHTML((noMarker ? '' : markerStr) + (noName ? '' : wrapInlineNameHTML(readableName, !noMarker, nameStyle)) + (noValue ? '' : wrapInlineValueHTML(readableValueList, valueAlignRight, valueCloseToMarker, valueStyle)), topMarginForOuterGap); + } + /** + * @return markupText. null/undefined means no content. + */ + + + function buildTooltipMarkup(fragment, markupStyleCreator, renderMode, orderMode, useUTC, toolTipTextStyle) { + if (!fragment) { + return; + } + + var builder = getBuilder(fragment); + var ctx = { + useUTC: useUTC, + renderMode: renderMode, + orderMode: orderMode, + markupStyleCreator: markupStyleCreator, + valueFormatter: fragment.valueFormatter + }; + return builder(ctx, fragment, 0, toolTipTextStyle); + } + + function getGap(gapLevel) { + return { + html: HTML_GAPS[gapLevel], + richText: RICH_TEXT_GAPS[gapLevel] + }; + } + + function wrapBlockHTML(encodedContent, topGap) { + var clearfix = '
                                                                                          '; + var marginCSS = "margin: " + topGap + "px 0 0"; + return "
                                                                                          " + encodedContent + clearfix + '
                                                                                          '; + } + + function wrapInlineNameHTML(name, leftHasMarker, style) { + var marginCss = leftHasMarker ? 'margin-left:2px' : ''; + return "" + encodeHTML(name) + ''; + } + + function wrapInlineValueHTML(valueList, alignRight, valueCloseToMarker, style) { + // Do not too close to marker, considering there are multiple values separated by spaces. + var paddingStr = valueCloseToMarker ? '10px' : '20px'; + var alignCSS = alignRight ? "float:right;margin-left:" + paddingStr : ''; + valueList = isArray(valueList) ? valueList : [valueList]; + return "" // Value has commas inside, so use ' ' as delimiter for multiple values. + + map(valueList, function (value) { + return encodeHTML(value); + }).join('  ') + ''; + } + + function wrapInlineNameRichText(ctx, name, style) { + return ctx.markupStyleCreator.wrapRichTextStyle(name, style); + } + + function wrapInlineValueRichText(ctx, values, alignRight, valueCloseToMarker, style) { + var styles = [style]; + var paddingLeft = valueCloseToMarker ? 10 : 20; + alignRight && styles.push({ + padding: [0, 0, 0, paddingLeft], + align: 'right' + }); // Value has commas inside, so use ' ' as delimiter for multiple values. + + return ctx.markupStyleCreator.wrapRichTextStyle(isArray(values) ? values.join(' ') : values, styles); + } + + function retrieveVisualColorForTooltipMarker(series, dataIndex) { + var style = series.getData().getItemVisual(dataIndex, 'style'); + var color = style[series.visualDrawType]; + return convertToColorString(color); + } + function getPaddingFromTooltipModel(model, renderMode) { + var padding = model.get('padding'); + return padding != null ? padding // We give slightly different to look pretty. + : renderMode === 'richText' ? [8, 10] : 10; + } + /** + * The major feature is generate styles for `renderMode: 'richText'`. + * But it also serves `renderMode: 'html'` to provide + * "renderMode-independent" API. + */ + + var TooltipMarkupStyleCreator = + /** @class */ + function () { + function TooltipMarkupStyleCreator() { + this.richTextStyles = {}; // Notice that "generate a style name" usuall happens repeatly when mouse moving and + // displaying a tooltip. So we put the `_nextStyleNameId` as a member of each creator + // rather than static shared by all creators (which will cause it increase to fast). + + this._nextStyleNameId = getRandomIdBase(); + } + + TooltipMarkupStyleCreator.prototype._generateStyleName = function () { + return '__EC_aUTo_' + this._nextStyleNameId++; + }; + + TooltipMarkupStyleCreator.prototype.makeTooltipMarker = function (markerType, colorStr, renderMode) { + var markerId = renderMode === 'richText' ? this._generateStyleName() : null; + var marker = getTooltipMarker({ + color: colorStr, + type: markerType, + renderMode: renderMode, + markerId: markerId + }); + + if (isString(marker)) { + return marker; + } else { + if ("development" !== 'production') { + assert(markerId); + } + + this.richTextStyles[markerId] = marker.style; + return marker.content; + } + }; + /** + * @usage + * ```ts + * const styledText = markupStyleCreator.wrapRichTextStyle([ + * // The styles will be auto merged. + * { + * fontSize: 12, + * color: 'blue' + * }, + * { + * padding: 20 + * } + * ]); + * ``` + */ + + + TooltipMarkupStyleCreator.prototype.wrapRichTextStyle = function (text, styles) { + var finalStl = {}; + + if (isArray(styles)) { + each(styles, function (stl) { + return extend(finalStl, stl); + }); + } else { + extend(finalStl, styles); + } + + var styleName = this._generateStyleName(); + + this.richTextStyles[styleName] = finalStl; + return "{" + styleName + "|" + text + "}"; + }; + + return TooltipMarkupStyleCreator; + }(); + + function defaultSeriesFormatTooltip(opt) { + var series = opt.series; + var dataIndex = opt.dataIndex; + var multipleSeries = opt.multipleSeries; + var data = series.getData(); + var tooltipDims = data.mapDimensionsAll('defaultedTooltip'); + var tooltipDimLen = tooltipDims.length; + var value = series.getRawValue(dataIndex); + var isValueArr = isArray(value); + var markerColor = retrieveVisualColorForTooltipMarker(series, dataIndex); // Complicated rule for pretty tooltip. + + var inlineValue; + var inlineValueType; + var subBlocks; + var sortParam; + + if (tooltipDimLen > 1 || isValueArr && !tooltipDimLen) { + var formatArrResult = formatTooltipArrayValue(value, series, dataIndex, tooltipDims, markerColor); + inlineValue = formatArrResult.inlineValues; + inlineValueType = formatArrResult.inlineValueTypes; + subBlocks = formatArrResult.blocks; // Only support tooltip sort by the first inline value. It's enough in most cases. + + sortParam = formatArrResult.inlineValues[0]; + } else if (tooltipDimLen) { + var dimInfo = data.getDimensionInfo(tooltipDims[0]); + sortParam = inlineValue = retrieveRawValue(data, dataIndex, tooltipDims[0]); + inlineValueType = dimInfo.type; + } else { + sortParam = inlineValue = isValueArr ? value[0] : value; + } // Do not show generated series name. It might not be readable. + + + var seriesNameSpecified = isNameSpecified(series); + var seriesName = seriesNameSpecified && series.name || ''; + var itemName = data.getName(dataIndex); + var inlineName = multipleSeries ? seriesName : itemName; + return createTooltipMarkup('section', { + header: seriesName, + // When series name not specified, do not show a header line with only '-'. + // This case alway happen in tooltip.trigger: 'item'. + noHeader: multipleSeries || !seriesNameSpecified, + sortParam: sortParam, + blocks: [createTooltipMarkup('nameValue', { + markerType: 'item', + markerColor: markerColor, + // Do not mix display seriesName and itemName in one tooltip, + // which might confuses users. + name: inlineName, + // name dimension might be auto assigned, where the name might + // be not readable. So we check trim here. + noName: !trim(inlineName), + value: inlineValue, + valueType: inlineValueType + })].concat(subBlocks || []) + }); + } + + function formatTooltipArrayValue(value, series, dataIndex, tooltipDims, colorStr) { + // check: category-no-encode-has-axis-data in dataset.html + var data = series.getData(); + var isValueMultipleLine = reduce(value, function (isValueMultipleLine, val, idx) { + var dimItem = data.getDimensionInfo(idx); + return isValueMultipleLine = isValueMultipleLine || dimItem && dimItem.tooltip !== false && dimItem.displayName != null; + }, false); + var inlineValues = []; + var inlineValueTypes = []; + var blocks = []; + tooltipDims.length ? each(tooltipDims, function (dim) { + setEachItem(retrieveRawValue(data, dataIndex, dim), dim); + }) // By default, all dims is used on tooltip. + : each(value, setEachItem); + + function setEachItem(val, dim) { + var dimInfo = data.getDimensionInfo(dim); // If `dimInfo.tooltip` is not set, show tooltip. + + if (!dimInfo || dimInfo.otherDims.tooltip === false) { + return; + } + + if (isValueMultipleLine) { + blocks.push(createTooltipMarkup('nameValue', { + markerType: 'subItem', + markerColor: colorStr, + name: dimInfo.displayName, + value: val, + valueType: dimInfo.type + })); + } else { + inlineValues.push(val); + inlineValueTypes.push(dimInfo.type); + } + } + + return { + inlineValues: inlineValues, + inlineValueTypes: inlineValueTypes, + blocks: blocks + }; + } + + var inner$1 = makeInner(); + + function getSelectionKey(data, dataIndex) { + return data.getName(dataIndex) || data.getId(dataIndex); + } + + var SERIES_UNIVERSAL_TRANSITION_PROP = '__universalTransitionEnabled'; + + var SeriesModel = + /** @class */ + function (_super) { + __extends(SeriesModel, _super); + + function SeriesModel() { + // [Caution]: Becuase this class or desecendants can be used as `XXX.extend(subProto)`, + // the class members must not be initialized in constructor or declaration place. + // Otherwise there is bad case: + // class A {xxx = 1;} + // enableClassExtend(A); + // class B extends A {} + // var C = B.extend({xxx: 5}); + // var c = new C(); + // console.log(c.xxx); // expect 5 but always 1. + var _this = _super !== null && _super.apply(this, arguments) || this; // --------------------------------------- + // Props about data selection + // --------------------------------------- + + + _this._selectedDataIndicesMap = {}; + return _this; + } + + SeriesModel.prototype.init = function (option, parentModel, ecModel) { + this.seriesIndex = this.componentIndex; + this.dataTask = createTask({ + count: dataTaskCount, + reset: dataTaskReset + }); + this.dataTask.context = { + model: this + }; + this.mergeDefaultAndTheme(option, ecModel); + var sourceManager = inner$1(this).sourceManager = new SourceManager(this); + sourceManager.prepareSource(); + var data = this.getInitialData(option, ecModel); + wrapData(data, this); + this.dataTask.context.data = data; + + if ("development" !== 'production') { + assert(data, 'getInitialData returned invalid data.'); + } + + inner$1(this).dataBeforeProcessed = data; // If we reverse the order (make data firstly, and then make + // dataBeforeProcessed by cloneShallow), cloneShallow will + // cause data.graph.data !== data when using + // module:echarts/data/Graph or module:echarts/data/Tree. + // See module:echarts/data/helper/linkSeriesData + // Theoretically, it is unreasonable to call `seriesModel.getData()` in the model + // init or merge stage, because the data can be restored. So we do not `restoreData` + // and `setData` here, which forbids calling `seriesModel.getData()` in this stage. + // Call `seriesModel.getRawData()` instead. + // this.restoreData(); + + autoSeriesName(this); + + this._initSelectedMapFromData(data); + }; + /** + * Util for merge default and theme to option + */ + + + SeriesModel.prototype.mergeDefaultAndTheme = function (option, ecModel) { + var layoutMode = fetchLayoutMode(this); + var inputPositionParams = layoutMode ? getLayoutParams(option) : {}; // Backward compat: using subType on theme. + // But if name duplicate between series subType + // (for example: parallel) add component mainType, + // add suffix 'Series'. + + var themeSubType = this.subType; + + if (ComponentModel.hasClass(themeSubType)) { + themeSubType += 'Series'; + } + + merge(option, ecModel.getTheme().get(this.subType)); + merge(option, this.getDefaultOption()); // Default label emphasis `show` + + defaultEmphasis(option, 'label', ['show']); + this.fillDataTextStyle(option.data); + + if (layoutMode) { + mergeLayoutParam(option, inputPositionParams, layoutMode); + } + }; + + SeriesModel.prototype.mergeOption = function (newSeriesOption, ecModel) { + // this.settingTask.dirty(); + newSeriesOption = merge(this.option, newSeriesOption, true); + this.fillDataTextStyle(newSeriesOption.data); + var layoutMode = fetchLayoutMode(this); + + if (layoutMode) { + mergeLayoutParam(this.option, newSeriesOption, layoutMode); + } + + var sourceManager = inner$1(this).sourceManager; + sourceManager.dirty(); + sourceManager.prepareSource(); + var data = this.getInitialData(newSeriesOption, ecModel); + wrapData(data, this); + this.dataTask.dirty(); + this.dataTask.context.data = data; + inner$1(this).dataBeforeProcessed = data; + autoSeriesName(this); + + this._initSelectedMapFromData(data); + }; + + SeriesModel.prototype.fillDataTextStyle = function (data) { + // Default data label emphasis `show` + // FIXME Tree structure data ? + // FIXME Performance ? + if (data && !isTypedArray(data)) { + var props = ['show']; + + for (var i = 0; i < data.length; i++) { + if (data[i] && data[i].label) { + defaultEmphasis(data[i], 'label', props); + } + } + } + }; + /** + * Init a data structure from data related option in series + * Must be overriden. + */ + + + SeriesModel.prototype.getInitialData = function (option, ecModel) { + return; + }; + /** + * Append data to list + */ + + + SeriesModel.prototype.appendData = function (params) { + // FIXME ??? + // (1) If data from dataset, forbidden append. + // (2) support append data of dataset. + var data = this.getRawData(); + data.appendData(params.data); + }; + /** + * Consider some method like `filter`, `map` need make new data, + * We should make sure that `seriesModel.getData()` get correct + * data in the stream procedure. So we fetch data from upstream + * each time `task.perform` called. + */ + + + SeriesModel.prototype.getData = function (dataType) { + var task = getCurrentTask(this); + + if (task) { + var data = task.context.data; + return dataType == null ? data : data.getLinkedData(dataType); + } else { + // When series is not alive (that may happen when click toolbox + // restore or setOption with not merge mode), series data may + // be still need to judge animation or something when graphic + // elements want to know whether fade out. + return inner$1(this).data; + } + }; + + SeriesModel.prototype.getAllData = function () { + var mainData = this.getData(); + return mainData && mainData.getLinkedDataAll ? mainData.getLinkedDataAll() : [{ + data: mainData + }]; + }; + + SeriesModel.prototype.setData = function (data) { + var task = getCurrentTask(this); + + if (task) { + var context = task.context; // Consider case: filter, data sample. + // FIXME:TS never used, so comment it + // if (context.data !== data && task.modifyOutputEnd) { + // task.setOutputEnd(data.count()); + // } + + context.outputData = data; // Caution: setData should update context.data, + // Because getData may be called multiply in a + // single stage and expect to get the data just + // set. (For example, AxisProxy, x y both call + // getData and setDate sequentially). + // So the context.data should be fetched from + // upstream each time when a stage starts to be + // performed. + + if (task !== this.dataTask) { + context.data = data; + } + } + + inner$1(this).data = data; + }; + + SeriesModel.prototype.getEncode = function () { + var encode = this.get('encode', true); + + if (encode) { + return createHashMap(encode); + } + }; + + SeriesModel.prototype.getSourceManager = function () { + return inner$1(this).sourceManager; + }; + + SeriesModel.prototype.getSource = function () { + return this.getSourceManager().getSource(); + }; + /** + * Get data before processed + */ + + + SeriesModel.prototype.getRawData = function () { + return inner$1(this).dataBeforeProcessed; + }; + + SeriesModel.prototype.getColorBy = function () { + var colorBy = this.get('colorBy'); + return colorBy || 'series'; + }; + + SeriesModel.prototype.isColorBySeries = function () { + return this.getColorBy() === 'series'; + }; + /** + * Get base axis if has coordinate system and has axis. + * By default use coordSys.getBaseAxis(); + * Can be overrided for some chart. + * @return {type} description + */ + + + SeriesModel.prototype.getBaseAxis = function () { + var coordSys = this.coordinateSystem; // @ts-ignore + + return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis(); + }; + /** + * Default tooltip formatter + * + * @param dataIndex + * @param multipleSeries + * @param dataType + * @param renderMode valid values: 'html'(by default) and 'richText'. + * 'html' is used for rendering tooltip in extra DOM form, and the result + * string is used as DOM HTML content. + * 'richText' is used for rendering tooltip in rich text form, for those where + * DOM operation is not supported. + * @return formatted tooltip with `html` and `markers` + * Notice: The override method can also return string + */ + + + SeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + return defaultSeriesFormatTooltip({ + series: this, + dataIndex: dataIndex, + multipleSeries: multipleSeries + }); + }; + + SeriesModel.prototype.isAnimationEnabled = function () { + var ecModel = this.ecModel; // Disable animation if using echarts in node but not give ssr flag. + // In ssr mode, renderToString will generate svg with css animation. + + if (env.node && !(ecModel && ecModel.ssr)) { + return false; + } + + var animationEnabled = this.getShallow('animation'); + + if (animationEnabled) { + if (this.getData().count() > this.getShallow('animationThreshold')) { + animationEnabled = false; + } + } + + return !!animationEnabled; + }; + + SeriesModel.prototype.restoreData = function () { + this.dataTask.dirty(); + }; + + SeriesModel.prototype.getColorFromPalette = function (name, scope, requestColorNum) { + var ecModel = this.ecModel; // PENDING + + var color = PaletteMixin.prototype.getColorFromPalette.call(this, name, scope, requestColorNum); + + if (!color) { + color = ecModel.getColorFromPalette(name, scope, requestColorNum); + } + + return color; + }; + /** + * Use `data.mapDimensionsAll(coordDim)` instead. + * @deprecated + */ + + + SeriesModel.prototype.coordDimToDataDim = function (coordDim) { + return this.getRawData().mapDimensionsAll(coordDim); + }; + /** + * Get progressive rendering count each step + */ + + + SeriesModel.prototype.getProgressive = function () { + return this.get('progressive'); + }; + /** + * Get progressive rendering count each step + */ + + + SeriesModel.prototype.getProgressiveThreshold = function () { + return this.get('progressiveThreshold'); + }; // PENGING If selectedMode is null ? + + + SeriesModel.prototype.select = function (innerDataIndices, dataType) { + this._innerSelect(this.getData(dataType), innerDataIndices); + }; + + SeriesModel.prototype.unselect = function (innerDataIndices, dataType) { + var selectedMap = this.option.selectedMap; + + if (!selectedMap) { + return; + } + + var selectedMode = this.option.selectedMode; + var data = this.getData(dataType); + + if (selectedMode === 'series' || selectedMap === 'all') { + this.option.selectedMap = {}; + this._selectedDataIndicesMap = {}; + return; + } + + for (var i = 0; i < innerDataIndices.length; i++) { + var dataIndex = innerDataIndices[i]; + var nameOrId = getSelectionKey(data, dataIndex); + selectedMap[nameOrId] = false; + this._selectedDataIndicesMap[nameOrId] = -1; + } + }; + + SeriesModel.prototype.toggleSelect = function (innerDataIndices, dataType) { + var tmpArr = []; + + for (var i = 0; i < innerDataIndices.length; i++) { + tmpArr[0] = innerDataIndices[i]; + this.isSelected(innerDataIndices[i], dataType) ? this.unselect(tmpArr, dataType) : this.select(tmpArr, dataType); + } + }; + + SeriesModel.prototype.getSelectedDataIndices = function () { + if (this.option.selectedMap === 'all') { + return [].slice.call(this.getData().getIndices()); + } + + var selectedDataIndicesMap = this._selectedDataIndicesMap; + var nameOrIds = keys(selectedDataIndicesMap); + var dataIndices = []; + + for (var i = 0; i < nameOrIds.length; i++) { + var dataIndex = selectedDataIndicesMap[nameOrIds[i]]; + + if (dataIndex >= 0) { + dataIndices.push(dataIndex); + } + } + + return dataIndices; + }; + + SeriesModel.prototype.isSelected = function (dataIndex, dataType) { + var selectedMap = this.option.selectedMap; + + if (!selectedMap) { + return false; + } + + var data = this.getData(dataType); + return (selectedMap === 'all' || selectedMap[getSelectionKey(data, dataIndex)]) && !data.getItemModel(dataIndex).get(['select', 'disabled']); + }; + + SeriesModel.prototype.isUniversalTransitionEnabled = function () { + if (this[SERIES_UNIVERSAL_TRANSITION_PROP]) { + return true; + } + + var universalTransitionOpt = this.option.universalTransition; // Quick reject + + if (!universalTransitionOpt) { + return false; + } + + if (universalTransitionOpt === true) { + return true; + } // Can be simply 'universalTransition: true' + + + return universalTransitionOpt && universalTransitionOpt.enabled; + }; + + SeriesModel.prototype._innerSelect = function (data, innerDataIndices) { + var _a, _b; + + var option = this.option; + var selectedMode = option.selectedMode; + var len = innerDataIndices.length; + + if (!selectedMode || !len) { + return; + } + + if (selectedMode === 'series') { + option.selectedMap = 'all'; + } else if (selectedMode === 'multiple') { + if (!isObject(option.selectedMap)) { + option.selectedMap = {}; + } + + var selectedMap = option.selectedMap; + + for (var i = 0; i < len; i++) { + var dataIndex = innerDataIndices[i]; // TODO diffrent types of data share same object. + + var nameOrId = getSelectionKey(data, dataIndex); + selectedMap[nameOrId] = true; + this._selectedDataIndicesMap[nameOrId] = data.getRawIndex(dataIndex); + } + } else if (selectedMode === 'single' || selectedMode === true) { + var lastDataIndex = innerDataIndices[len - 1]; + var nameOrId = getSelectionKey(data, lastDataIndex); + option.selectedMap = (_a = {}, _a[nameOrId] = true, _a); + this._selectedDataIndicesMap = (_b = {}, _b[nameOrId] = data.getRawIndex(lastDataIndex), _b); + } + }; + + SeriesModel.prototype._initSelectedMapFromData = function (data) { + // Ignore select info in data if selectedMap exists. + // NOTE It's only for legacy usage. edge data is not supported. + if (this.option.selectedMap) { + return; + } + + var dataIndices = []; + + if (data.hasItemOption) { + data.each(function (idx) { + var rawItem = data.getRawDataItem(idx); + + if (rawItem && rawItem.selected) { + dataIndices.push(idx); + } + }); + } + + if (dataIndices.length > 0) { + this._innerSelect(data, dataIndices); + } + }; // /** + // * @see {module:echarts/stream/Scheduler} + // */ + // abstract pipeTask: null + + + SeriesModel.registerClass = function (clz) { + return ComponentModel.registerClass(clz); + }; + + SeriesModel.protoInitialize = function () { + var proto = SeriesModel.prototype; + proto.type = 'series.__base__'; + proto.seriesIndex = 0; + proto.ignoreStyleOnData = false; + proto.hasSymbolVisual = false; + proto.defaultSymbol = 'circle'; // Make sure the values can be accessed! + + proto.visualStyleAccessPath = 'itemStyle'; + proto.visualDrawType = 'fill'; + }(); + + return SeriesModel; + }(ComponentModel); + + mixin(SeriesModel, DataFormatMixin); + mixin(SeriesModel, PaletteMixin); + mountExtend(SeriesModel, ComponentModel); + /** + * MUST be called after `prepareSource` called + * Here we need to make auto series, especially for auto legend. But we + * do not modify series.name in option to avoid side effects. + */ + + function autoSeriesName(seriesModel) { + // User specified name has higher priority, otherwise it may cause + // series can not be queried unexpectedly. + var name = seriesModel.name; + + if (!isNameSpecified(seriesModel)) { + seriesModel.name = getSeriesAutoName(seriesModel) || name; + } + } + + function getSeriesAutoName(seriesModel) { + var data = seriesModel.getRawData(); + var dataDims = data.mapDimensionsAll('seriesName'); + var nameArr = []; + each(dataDims, function (dataDim) { + var dimInfo = data.getDimensionInfo(dataDim); + dimInfo.displayName && nameArr.push(dimInfo.displayName); + }); + return nameArr.join(' '); + } + + function dataTaskCount(context) { + return context.model.getRawData().count(); + } + + function dataTaskReset(context) { + var seriesModel = context.model; + seriesModel.setData(seriesModel.getRawData().cloneShallow()); + return dataTaskProgress; + } + + function dataTaskProgress(param, context) { + // Avoid repead cloneShallow when data just created in reset. + if (context.outputData && param.end > context.outputData.count()) { + context.model.getRawData().cloneShallow(context.outputData); + } + } // TODO refactor + + + function wrapData(data, seriesModel) { + each(concatArray(data.CHANGABLE_METHODS, data.DOWNSAMPLE_METHODS), function (methodName) { + data.wrapMethod(methodName, curry(onDataChange, seriesModel)); + }); + } + + function onDataChange(seriesModel, newList) { + var task = getCurrentTask(seriesModel); + + if (task) { + // Consider case: filter, selectRange + task.setOutputEnd((newList || this).count()); + } + + return newList; + } + + function getCurrentTask(seriesModel) { + var scheduler = (seriesModel.ecModel || {}).scheduler; + var pipeline = scheduler && scheduler.getPipeline(seriesModel.uid); + + if (pipeline) { + // When pipline finished, the currrentTask keep the last + // task (renderTask). + var task = pipeline.currentTask; + + if (task) { + var agentStubMap = task.agentStubMap; + + if (agentStubMap) { + task = agentStubMap.get(seriesModel.uid); + } + } + + return task; + } + } + + var ComponentView = + /** @class */ + function () { + function ComponentView() { + this.group = new Group(); + this.uid = getUID('viewComponent'); + } + + ComponentView.prototype.init = function (ecModel, api) {}; + + ComponentView.prototype.render = function (model, ecModel, api, payload) {}; + + ComponentView.prototype.dispose = function (ecModel, api) {}; + + ComponentView.prototype.updateView = function (model, ecModel, api, payload) {// Do nothing; + }; + + ComponentView.prototype.updateLayout = function (model, ecModel, api, payload) {// Do nothing; + }; + + ComponentView.prototype.updateVisual = function (model, ecModel, api, payload) {// Do nothing; + }; + /** + * Hook for toggle blur target series. + * Can be used in marker for blur or leave blur the markers + */ + + + ComponentView.prototype.toggleBlurSeries = function (seriesModels, isBlur, ecModel) {// Do nothing; + }; + /** + * Traverse the new rendered elements. + * + * It will traverse the new added element in progressive rendering. + * And traverse all in normal rendering. + */ + + + ComponentView.prototype.eachRendered = function (cb) { + var group = this.group; + + if (group) { + group.traverse(cb); + } + }; + + return ComponentView; + }(); + enableClassExtend(ComponentView); + enableClassManagement(ComponentView); + + /** + * @return {string} If large mode changed, return string 'reset'; + */ + + function createRenderPlanner() { + var inner = makeInner(); + return function (seriesModel) { + var fields = inner(seriesModel); + var pipelineContext = seriesModel.pipelineContext; + var originalLarge = !!fields.large; + var originalProgressive = !!fields.progressiveRender; // FIXME: if the planner works on a filtered series, `pipelineContext` does not + // exists. See #11611 . Probably we need to modify this structure, see the comment + // on `performRawSeries` in `Schedular.js`. + + var large = fields.large = !!(pipelineContext && pipelineContext.large); + var progressive = fields.progressiveRender = !!(pipelineContext && pipelineContext.progressiveRender); + return !!(originalLarge !== large || originalProgressive !== progressive) && 'reset'; + }; + } + + var inner$2 = makeInner(); + var renderPlanner = createRenderPlanner(); + + var ChartView = + /** @class */ + function () { + function ChartView() { + this.group = new Group(); + this.uid = getUID('viewChart'); + this.renderTask = createTask({ + plan: renderTaskPlan, + reset: renderTaskReset + }); + this.renderTask.context = { + view: this + }; + } + + ChartView.prototype.init = function (ecModel, api) {}; + + ChartView.prototype.render = function (seriesModel, ecModel, api, payload) { + if ("development" !== 'production') { + throw new Error('render method must been implemented'); + } + }; + /** + * Highlight series or specified data item. + */ + + + ChartView.prototype.highlight = function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(payload && payload.dataType); + + if (!data) { + if ("development" !== 'production') { + error("Unknown dataType " + payload.dataType); + } + + return; + } + + toggleHighlight(data, payload, 'emphasis'); + }; + /** + * Downplay series or specified data item. + */ + + + ChartView.prototype.downplay = function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(payload && payload.dataType); + + if (!data) { + if ("development" !== 'production') { + error("Unknown dataType " + payload.dataType); + } + + return; + } + + toggleHighlight(data, payload, 'normal'); + }; + /** + * Remove self. + */ + + + ChartView.prototype.remove = function (ecModel, api) { + this.group.removeAll(); + }; + /** + * Dispose self. + */ + + + ChartView.prototype.dispose = function (ecModel, api) {}; + + ChartView.prototype.updateView = function (seriesModel, ecModel, api, payload) { + this.render(seriesModel, ecModel, api, payload); + }; // FIXME never used? + + + ChartView.prototype.updateLayout = function (seriesModel, ecModel, api, payload) { + this.render(seriesModel, ecModel, api, payload); + }; // FIXME never used? + + + ChartView.prototype.updateVisual = function (seriesModel, ecModel, api, payload) { + this.render(seriesModel, ecModel, api, payload); + }; + /** + * Traverse the new rendered elements. + * + * It will traverse the new added element in progressive rendering. + * And traverse all in normal rendering. + */ + + + ChartView.prototype.eachRendered = function (cb) { + traverseElements(this.group, cb); + }; + + ChartView.markUpdateMethod = function (payload, methodName) { + inner$2(payload).updateMethod = methodName; + }; + + ChartView.protoInitialize = function () { + var proto = ChartView.prototype; + proto.type = 'chart'; + }(); + + return ChartView; + }(); + /** + * Set state of single element + */ + + function elSetState(el, state, highlightDigit) { + if (el && isHighDownDispatcher(el)) { + (state === 'emphasis' ? enterEmphasis : leaveEmphasis)(el, highlightDigit); + } + } + + function toggleHighlight(data, payload, state) { + var dataIndex = queryDataIndex(data, payload); + var highlightDigit = payload && payload.highlightKey != null ? getHighlightDigit(payload.highlightKey) : null; + + if (dataIndex != null) { + each(normalizeToArray(dataIndex), function (dataIdx) { + elSetState(data.getItemGraphicEl(dataIdx), state, highlightDigit); + }); + } else { + data.eachItemGraphicEl(function (el) { + elSetState(el, state, highlightDigit); + }); + } + } + + enableClassExtend(ChartView, ['dispose']); + enableClassManagement(ChartView); + + function renderTaskPlan(context) { + return renderPlanner(context.model); + } + + function renderTaskReset(context) { + var seriesModel = context.model; + var ecModel = context.ecModel; + var api = context.api; + var payload = context.payload; // FIXME: remove updateView updateVisual + + var progressiveRender = seriesModel.pipelineContext.progressiveRender; + var view = context.view; + var updateMethod = payload && inner$2(payload).updateMethod; + var methodName = progressiveRender ? 'incrementalPrepareRender' : updateMethod && view[updateMethod] ? updateMethod // `appendData` is also supported when data amount + // is less than progressive threshold. + : 'render'; + + if (methodName !== 'render') { + view[methodName](seriesModel, ecModel, api, payload); + } + + return progressMethodMap[methodName]; + } + + var progressMethodMap = { + incrementalPrepareRender: { + progress: function (params, context) { + context.view.incrementalRender(params, context.model, context.ecModel, context.api, context.payload); + } + }, + render: { + // Put view.render in `progress` to support appendData. But in this case + // view.render should not be called in reset, otherwise it will be called + // twise. Use `forceFirstProgress` to make sure that view.render is called + // in any cases. + forceFirstProgress: true, + progress: function (params, context) { + context.view.render(context.model, context.ecModel, context.api, context.payload); + } + } + }; + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var ORIGIN_METHOD = '\0__throttleOriginMethod'; + var RATE = '\0__throttleRate'; + var THROTTLE_TYPE = '\0__throttleType'; + /** + * @public + * @param {(Function)} fn + * @param {number} [delay=0] Unit: ms. + * @param {boolean} [debounce=false] + * true: If call interval less than `delay`, only the last call works. + * false: If call interval less than `delay, call works on fixed rate. + * @return {(Function)} throttled fn. + */ + + function throttle(fn, delay, debounce) { + var currCall; + var lastCall = 0; + var lastExec = 0; + var timer = null; + var diff; + var scope; + var args; + var debounceNextCall; + delay = delay || 0; + + function exec() { + lastExec = new Date().getTime(); + timer = null; + fn.apply(scope, args || []); + } + + var cb = function () { + var cbArgs = []; + + for (var _i = 0; _i < arguments.length; _i++) { + cbArgs[_i] = arguments[_i]; + } + + currCall = new Date().getTime(); + scope = this; + args = cbArgs; + var thisDelay = debounceNextCall || delay; + var thisDebounce = debounceNextCall || debounce; + debounceNextCall = null; + diff = currCall - (thisDebounce ? lastCall : lastExec) - thisDelay; + clearTimeout(timer); // Here we should make sure that: the `exec` SHOULD NOT be called later + // than a new call of `cb`, that is, preserving the command order. Consider + // calculating "scale rate" when roaming as an example. When a call of `cb` + // happens, either the `exec` is called dierectly, or the call is delayed. + // But the delayed call should never be later than next call of `cb`. Under + // this assurance, we can simply update view state each time `dispatchAction` + // triggered by user roaming, but not need to add extra code to avoid the + // state being "rolled-back". + + if (thisDebounce) { + timer = setTimeout(exec, thisDelay); + } else { + if (diff >= 0) { + exec(); + } else { + timer = setTimeout(exec, -diff); + } + } + + lastCall = currCall; + }; + /** + * Clear throttle. + * @public + */ + + + cb.clear = function () { + if (timer) { + clearTimeout(timer); + timer = null; + } + }; + /** + * Enable debounce once. + */ + + + cb.debounceNextCall = function (debounceDelay) { + debounceNextCall = debounceDelay; + }; + + return cb; + } + /** + * Create throttle method or update throttle rate. + * + * @example + * ComponentView.prototype.render = function () { + * ... + * throttle.createOrUpdate( + * this, + * '_dispatchAction', + * this.model.get('throttle'), + * 'fixRate' + * ); + * }; + * ComponentView.prototype.remove = function () { + * throttle.clear(this, '_dispatchAction'); + * }; + * ComponentView.prototype.dispose = function () { + * throttle.clear(this, '_dispatchAction'); + * }; + * + */ + + function createOrUpdate(obj, fnAttr, rate, throttleType) { + var fn = obj[fnAttr]; + + if (!fn) { + return; + } + + var originFn = fn[ORIGIN_METHOD] || fn; + var lastThrottleType = fn[THROTTLE_TYPE]; + var lastRate = fn[RATE]; + + if (lastRate !== rate || lastThrottleType !== throttleType) { + if (rate == null || !throttleType) { + return obj[fnAttr] = originFn; + } + + fn = obj[fnAttr] = throttle(originFn, rate, throttleType === 'debounce'); + fn[ORIGIN_METHOD] = originFn; + fn[THROTTLE_TYPE] = throttleType; + fn[RATE] = rate; + } + + return fn; + } + /** + * Clear throttle. Example see throttle.createOrUpdate. + */ + + function clear(obj, fnAttr) { + var fn = obj[fnAttr]; + + if (fn && fn[ORIGIN_METHOD]) { + // Clear throttle + fn.clear && fn.clear(); + obj[fnAttr] = fn[ORIGIN_METHOD]; + } + } + + var inner$3 = makeInner(); + var defaultStyleMappers = { + itemStyle: makeStyleMapper(ITEM_STYLE_KEY_MAP, true), + lineStyle: makeStyleMapper(LINE_STYLE_KEY_MAP, true) + }; + var defaultColorKey = { + lineStyle: 'stroke', + itemStyle: 'fill' + }; + + function getStyleMapper(seriesModel, stylePath) { + var styleMapper = seriesModel.visualStyleMapper || defaultStyleMappers[stylePath]; + + if (!styleMapper) { + console.warn("Unkown style type '" + stylePath + "'."); + return defaultStyleMappers.itemStyle; + } + + return styleMapper; + } + + function getDefaultColorKey(seriesModel, stylePath) { + // return defaultColorKey[stylePath] || + var colorKey = seriesModel.visualDrawType || defaultColorKey[stylePath]; + + if (!colorKey) { + console.warn("Unkown style type '" + stylePath + "'."); + return 'fill'; + } + + return colorKey; + } + + var seriesStyleTask = { + createOnAllSeries: true, + performRawSeries: true, + reset: function (seriesModel, ecModel) { + var data = seriesModel.getData(); + var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; // Set in itemStyle + + var styleModel = seriesModel.getModel(stylePath); + var getStyle = getStyleMapper(seriesModel, stylePath); + var globalStyle = getStyle(styleModel); + var decalOption = styleModel.getShallow('decal'); + + if (decalOption) { + data.setVisual('decal', decalOption); + decalOption.dirty = true; + } // TODO + + + var colorKey = getDefaultColorKey(seriesModel, stylePath); + var color = globalStyle[colorKey]; // TODO style callback + + var colorCallback = isFunction(color) ? color : null; + var hasAutoColor = globalStyle.fill === 'auto' || globalStyle.stroke === 'auto'; // Get from color palette by default. + + if (!globalStyle[colorKey] || colorCallback || hasAutoColor) { + // Note: if some series has color specified (e.g., by itemStyle.color), we DO NOT + // make it effect palette. Bacause some scenarios users need to make some series + // transparent or as background, which should better not effect the palette. + var colorPalette = seriesModel.getColorFromPalette( // TODO series count changed. + seriesModel.name, null, ecModel.getSeriesCount()); + + if (!globalStyle[colorKey]) { + globalStyle[colorKey] = colorPalette; + data.setVisual('colorFromPalette', true); + } + + globalStyle.fill = globalStyle.fill === 'auto' || isFunction(globalStyle.fill) ? colorPalette : globalStyle.fill; + globalStyle.stroke = globalStyle.stroke === 'auto' || isFunction(globalStyle.stroke) ? colorPalette : globalStyle.stroke; + } + + data.setVisual('style', globalStyle); + data.setVisual('drawType', colorKey); // Only visible series has each data be visual encoded + + if (!ecModel.isSeriesFiltered(seriesModel) && colorCallback) { + data.setVisual('colorFromPalette', false); + return { + dataEach: function (data, idx) { + var dataParams = seriesModel.getDataParams(idx); + var itemStyle = extend({}, globalStyle); + itemStyle[colorKey] = colorCallback(dataParams); + data.setItemVisual(idx, 'style', itemStyle); + } + }; + } + } + }; + var sharedModel = new Model(); + var dataStyleTask = { + createOnAllSeries: true, + performRawSeries: true, + reset: function (seriesModel, ecModel) { + if (seriesModel.ignoreStyleOnData || ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var data = seriesModel.getData(); + var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; // Set in itemStyle + + var getStyle = getStyleMapper(seriesModel, stylePath); + var colorKey = data.getVisual('drawType'); + return { + dataEach: data.hasItemOption ? function (data, idx) { + // Not use getItemModel for performance considuration + var rawItem = data.getRawDataItem(idx); + + if (rawItem && rawItem[stylePath]) { + sharedModel.option = rawItem[stylePath]; + var style = getStyle(sharedModel); + var existsStyle = data.ensureUniqueItemVisual(idx, 'style'); + extend(existsStyle, style); + + if (sharedModel.option.decal) { + data.setItemVisual(idx, 'decal', sharedModel.option.decal); + sharedModel.option.decal.dirty = true; + } + + if (colorKey in style) { + data.setItemVisual(idx, 'colorFromPalette', false); + } + } + } : null + }; + } + }; // Pick color from palette for the data which has not been set with color yet. + // Note: do not support stream rendering. No such cases yet. + + var dataColorPaletteTask = { + performRawSeries: true, + overallReset: function (ecModel) { + // Each type of series use one scope. + // Pie and funnel are using diferrent scopes + var paletteScopeGroupByType = createHashMap(); + ecModel.eachSeries(function (seriesModel) { + var colorBy = seriesModel.getColorBy(); + + if (seriesModel.isColorBySeries()) { + return; + } + + var key = seriesModel.type + '-' + colorBy; + var colorScope = paletteScopeGroupByType.get(key); + + if (!colorScope) { + colorScope = {}; + paletteScopeGroupByType.set(key, colorScope); + } + + inner$3(seriesModel).scope = colorScope; + }); + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.isColorBySeries() || ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var dataAll = seriesModel.getRawData(); + var idxMap = {}; + var data = seriesModel.getData(); + var colorScope = inner$3(seriesModel).scope; + var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; + var colorKey = getDefaultColorKey(seriesModel, stylePath); + data.each(function (idx) { + var rawIdx = data.getRawIndex(idx); + idxMap[rawIdx] = idx; + }); // Iterate on data before filtered. To make sure color from palette can be + // Consistent when toggling legend. + + dataAll.each(function (rawIdx) { + var idx = idxMap[rawIdx]; + var fromPalette = data.getItemVisual(idx, 'colorFromPalette'); // Get color from palette for each data only when the color is inherited from series color, which is + // also picked from color palette. So following situation is not in the case: + // 1. series.itemStyle.color is set + // 2. color is encoded by visualMap + + if (fromPalette) { + var itemStyle = data.ensureUniqueItemVisual(idx, 'style'); + var name_1 = dataAll.getName(rawIdx) || rawIdx + ''; + var dataCount = dataAll.count(); + itemStyle[colorKey] = seriesModel.getColorFromPalette(name_1, colorScope, dataCount); + } + }); + }); + } + }; + + var PI$3 = Math.PI; + /** + * @param {module:echarts/ExtensionAPI} api + * @param {Object} [opts] + * @param {string} [opts.text] + * @param {string} [opts.color] + * @param {string} [opts.textColor] + * @return {module:zrender/Element} + */ + + function defaultLoading(api, opts) { + opts = opts || {}; + defaults(opts, { + text: 'loading', + textColor: '#000', + fontSize: 12, + fontWeight: 'normal', + fontStyle: 'normal', + fontFamily: 'sans-serif', + maskColor: 'rgba(255, 255, 255, 0.8)', + showSpinner: true, + color: '#5470c6', + spinnerRadius: 10, + lineWidth: 5, + zlevel: 0 + }); + var group = new Group(); + var mask = new Rect({ + style: { + fill: opts.maskColor + }, + zlevel: opts.zlevel, + z: 10000 + }); + group.add(mask); + var textContent = new ZRText({ + style: { + text: opts.text, + fill: opts.textColor, + fontSize: opts.fontSize, + fontWeight: opts.fontWeight, + fontStyle: opts.fontStyle, + fontFamily: opts.fontFamily + }, + zlevel: opts.zlevel, + z: 10001 + }); + var labelRect = new Rect({ + style: { + fill: 'none' + }, + textContent: textContent, + textConfig: { + position: 'right', + distance: 10 + }, + zlevel: opts.zlevel, + z: 10001 + }); + group.add(labelRect); + var arc; + + if (opts.showSpinner) { + arc = new Arc({ + shape: { + startAngle: -PI$3 / 2, + endAngle: -PI$3 / 2 + 0.1, + r: opts.spinnerRadius + }, + style: { + stroke: opts.color, + lineCap: 'round', + lineWidth: opts.lineWidth + }, + zlevel: opts.zlevel, + z: 10001 + }); + arc.animateShape(true).when(1000, { + endAngle: PI$3 * 3 / 2 + }).start('circularInOut'); + arc.animateShape(true).when(1000, { + startAngle: PI$3 * 3 / 2 + }).delay(300).start('circularInOut'); + group.add(arc); + } // Inject resize + + + group.resize = function () { + var textWidth = textContent.getBoundingRect().width; + var r = opts.showSpinner ? opts.spinnerRadius : 0; // cx = (containerWidth - arcDiameter - textDistance - textWidth) / 2 + // textDistance needs to be calculated when both animation and text exist + + var cx = (api.getWidth() - r * 2 - (opts.showSpinner && textWidth ? 10 : 0) - textWidth) / 2 - (opts.showSpinner && textWidth ? 0 : 5 + textWidth / 2) // only show the text + + (opts.showSpinner ? 0 : textWidth / 2) // only show the spinner + + (textWidth ? 0 : r); + var cy = api.getHeight() / 2; + opts.showSpinner && arc.setShape({ + cx: cx, + cy: cy + }); + labelRect.setShape({ + x: cx - r, + y: cy - r, + width: r * 2, + height: r * 2 + }); + mask.setShape({ + x: 0, + y: 0, + width: api.getWidth(), + height: api.getHeight() + }); + }; + + group.resize(); + return group; + } + + var Scheduler = + /** @class */ + function () { + function Scheduler(ecInstance, api, dataProcessorHandlers, visualHandlers) { + // key: handlerUID + this._stageTaskMap = createHashMap(); + this.ecInstance = ecInstance; + this.api = api; // Fix current processors in case that in some rear cases that + // processors might be registered after echarts instance created. + // Register processors incrementally for a echarts instance is + // not supported by this stream architecture. + + dataProcessorHandlers = this._dataProcessorHandlers = dataProcessorHandlers.slice(); + visualHandlers = this._visualHandlers = visualHandlers.slice(); + this._allHandlers = dataProcessorHandlers.concat(visualHandlers); + } + + Scheduler.prototype.restoreData = function (ecModel, payload) { + // TODO: Only restore needed series and components, but not all components. + // Currently `restoreData` of all of the series and component will be called. + // But some independent components like `title`, `legend`, `graphic`, `toolbox`, + // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`, + // and some components like coordinate system, axes, dataZoom, visualMap only + // need their target series refresh. + // (1) If we are implementing this feature some day, we should consider these cases: + // if a data processor depends on a component (e.g., dataZoomProcessor depends + // on the settings of `dataZoom`), it should be re-performed if the component + // is modified by `setOption`. + // (2) If a processor depends on sevral series, speicified by its `getTargetSeries`, + // it should be re-performed when the result array of `getTargetSeries` changed. + // We use `dependencies` to cover these issues. + // (3) How to update target series when coordinate system related components modified. + // TODO: simply the dirty mechanism? Check whether only the case here can set tasks dirty, + // and this case all of the tasks will be set as dirty. + ecModel.restoreData(payload); // Theoretically an overall task not only depends on each of its target series, but also + // depends on all of the series. + // The overall task is not in pipeline, and `ecModel.restoreData` only set pipeline tasks + // dirty. If `getTargetSeries` of an overall task returns nothing, we should also ensure + // that the overall task is set as dirty and to be performed, otherwise it probably cause + // state chaos. So we have to set dirty of all of the overall tasks manually, otherwise it + // probably cause state chaos (consider `dataZoomProcessor`). + + this._stageTaskMap.each(function (taskRecord) { + var overallTask = taskRecord.overallTask; + overallTask && overallTask.dirty(); + }); + }; // If seriesModel provided, incremental threshold is check by series data. + + + Scheduler.prototype.getPerformArgs = function (task, isBlock) { + // For overall task + if (!task.__pipeline) { + return; + } + + var pipeline = this._pipelineMap.get(task.__pipeline.id); + + var pCtx = pipeline.context; + var incremental = !isBlock && pipeline.progressiveEnabled && (!pCtx || pCtx.progressiveRender) && task.__idxInPipeline > pipeline.blockIndex; + var step = incremental ? pipeline.step : null; + var modDataCount = pCtx && pCtx.modDataCount; + var modBy = modDataCount != null ? Math.ceil(modDataCount / step) : null; + return { + step: step, + modBy: modBy, + modDataCount: modDataCount + }; + }; + + Scheduler.prototype.getPipeline = function (pipelineId) { + return this._pipelineMap.get(pipelineId); + }; + /** + * Current, progressive rendering starts from visual and layout. + * Always detect render mode in the same stage, avoiding that incorrect + * detection caused by data filtering. + * Caution: + * `updateStreamModes` use `seriesModel.getData()`. + */ + + + Scheduler.prototype.updateStreamModes = function (seriesModel, view) { + var pipeline = this._pipelineMap.get(seriesModel.uid); + + var data = seriesModel.getData(); + var dataLen = data.count(); // `progressiveRender` means that can render progressively in each + // animation frame. Note that some types of series do not provide + // `view.incrementalPrepareRender` but support `chart.appendData`. We + // use the term `incremental` but not `progressive` to describe the + // case that `chart.appendData`. + + var progressiveRender = pipeline.progressiveEnabled && view.incrementalPrepareRender && dataLen >= pipeline.threshold; + var large = seriesModel.get('large') && dataLen >= seriesModel.get('largeThreshold'); // TODO: modDataCount should not updated if `appendData`, otherwise cause whole repaint. + // see `test/candlestick-large3.html` + + var modDataCount = seriesModel.get('progressiveChunkMode') === 'mod' ? dataLen : null; + seriesModel.pipelineContext = pipeline.context = { + progressiveRender: progressiveRender, + modDataCount: modDataCount, + large: large + }; + }; + + Scheduler.prototype.restorePipelines = function (ecModel) { + var scheduler = this; + var pipelineMap = scheduler._pipelineMap = createHashMap(); + ecModel.eachSeries(function (seriesModel) { + var progressive = seriesModel.getProgressive(); + var pipelineId = seriesModel.uid; + pipelineMap.set(pipelineId, { + id: pipelineId, + head: null, + tail: null, + threshold: seriesModel.getProgressiveThreshold(), + progressiveEnabled: progressive && !(seriesModel.preventIncremental && seriesModel.preventIncremental()), + blockIndex: -1, + step: Math.round(progressive || 700), + count: 0 + }); + + scheduler._pipe(seriesModel, seriesModel.dataTask); + }); + }; + + Scheduler.prototype.prepareStageTasks = function () { + var stageTaskMap = this._stageTaskMap; + var ecModel = this.api.getModel(); + var api = this.api; + each(this._allHandlers, function (handler) { + var record = stageTaskMap.get(handler.uid) || stageTaskMap.set(handler.uid, {}); + var errMsg = ''; + + if ("development" !== 'production') { + // Currently do not need to support to sepecify them both. + errMsg = '"reset" and "overallReset" must not be both specified.'; + } + + assert(!(handler.reset && handler.overallReset), errMsg); + handler.reset && this._createSeriesStageTask(handler, record, ecModel, api); + handler.overallReset && this._createOverallStageTask(handler, record, ecModel, api); + }, this); + }; + + Scheduler.prototype.prepareView = function (view, model, ecModel, api) { + var renderTask = view.renderTask; + var context = renderTask.context; + context.model = model; + context.ecModel = ecModel; + context.api = api; + renderTask.__block = !view.incrementalPrepareRender; + + this._pipe(model, renderTask); + }; + + Scheduler.prototype.performDataProcessorTasks = function (ecModel, payload) { + // If we do not use `block` here, it should be considered when to update modes. + this._performStageTasks(this._dataProcessorHandlers, ecModel, payload, { + block: true + }); + }; + + Scheduler.prototype.performVisualTasks = function (ecModel, payload, opt) { + this._performStageTasks(this._visualHandlers, ecModel, payload, opt); + }; + + Scheduler.prototype._performStageTasks = function (stageHandlers, ecModel, payload, opt) { + opt = opt || {}; + var unfinished = false; + var scheduler = this; + each(stageHandlers, function (stageHandler, idx) { + if (opt.visualType && opt.visualType !== stageHandler.visualType) { + return; + } + + var stageHandlerRecord = scheduler._stageTaskMap.get(stageHandler.uid); + + var seriesTaskMap = stageHandlerRecord.seriesTaskMap; + var overallTask = stageHandlerRecord.overallTask; + + if (overallTask) { + var overallNeedDirty_1; + var agentStubMap = overallTask.agentStubMap; + agentStubMap.each(function (stub) { + if (needSetDirty(opt, stub)) { + stub.dirty(); + overallNeedDirty_1 = true; + } + }); + overallNeedDirty_1 && overallTask.dirty(); + scheduler.updatePayload(overallTask, payload); + var performArgs_1 = scheduler.getPerformArgs(overallTask, opt.block); // Execute stubs firstly, which may set the overall task dirty, + // then execute the overall task. And stub will call seriesModel.setData, + // which ensures that in the overallTask seriesModel.getData() will not + // return incorrect data. + + agentStubMap.each(function (stub) { + stub.perform(performArgs_1); + }); + + if (overallTask.perform(performArgs_1)) { + unfinished = true; + } + } else if (seriesTaskMap) { + seriesTaskMap.each(function (task, pipelineId) { + if (needSetDirty(opt, task)) { + task.dirty(); + } + + var performArgs = scheduler.getPerformArgs(task, opt.block); // FIXME + // if intending to decalare `performRawSeries` in handlers, only + // stream-independent (specifically, data item independent) operations can be + // performed. Because is a series is filtered, most of the tasks will not + // be performed. A stream-dependent operation probably cause wrong biz logic. + // Perhaps we should not provide a separate callback for this case instead + // of providing the config `performRawSeries`. The stream-dependent operaions + // and stream-independent operations should better not be mixed. + + performArgs.skip = !stageHandler.performRawSeries && ecModel.isSeriesFiltered(task.context.model); + scheduler.updatePayload(task, payload); + + if (task.perform(performArgs)) { + unfinished = true; + } + }); + } + }); + + function needSetDirty(opt, task) { + return opt.setDirty && (!opt.dirtyMap || opt.dirtyMap.get(task.__pipeline.id)); + } + + this.unfinished = unfinished || this.unfinished; + }; + + Scheduler.prototype.performSeriesTasks = function (ecModel) { + var unfinished; + ecModel.eachSeries(function (seriesModel) { + // Progress to the end for dataInit and dataRestore. + unfinished = seriesModel.dataTask.perform() || unfinished; + }); + this.unfinished = unfinished || this.unfinished; + }; + + Scheduler.prototype.plan = function () { + // Travel pipelines, check block. + this._pipelineMap.each(function (pipeline) { + var task = pipeline.tail; + + do { + if (task.__block) { + pipeline.blockIndex = task.__idxInPipeline; + break; + } + + task = task.getUpstream(); + } while (task); + }); + }; + + Scheduler.prototype.updatePayload = function (task, payload) { + payload !== 'remain' && (task.context.payload = payload); + }; + + Scheduler.prototype._createSeriesStageTask = function (stageHandler, stageHandlerRecord, ecModel, api) { + var scheduler = this; + var oldSeriesTaskMap = stageHandlerRecord.seriesTaskMap; // The count of stages are totally about only several dozen, so + // do not need to reuse the map. + + var newSeriesTaskMap = stageHandlerRecord.seriesTaskMap = createHashMap(); + var seriesType = stageHandler.seriesType; + var getTargetSeries = stageHandler.getTargetSeries; // If a stageHandler should cover all series, `createOnAllSeries` should be declared mandatorily, + // to avoid some typo or abuse. Otherwise if an extension do not specify a `seriesType`, + // it works but it may cause other irrelevant charts blocked. + + if (stageHandler.createOnAllSeries) { + ecModel.eachRawSeries(create); + } else if (seriesType) { + ecModel.eachRawSeriesByType(seriesType, create); + } else if (getTargetSeries) { + getTargetSeries(ecModel, api).each(create); + } + + function create(seriesModel) { + var pipelineId = seriesModel.uid; // Init tasks for each seriesModel only once. + // Reuse original task instance. + + var task = newSeriesTaskMap.set(pipelineId, oldSeriesTaskMap && oldSeriesTaskMap.get(pipelineId) || createTask({ + plan: seriesTaskPlan, + reset: seriesTaskReset, + count: seriesTaskCount + })); + task.context = { + model: seriesModel, + ecModel: ecModel, + api: api, + // PENDING: `useClearVisual` not used? + useClearVisual: stageHandler.isVisual && !stageHandler.isLayout, + plan: stageHandler.plan, + reset: stageHandler.reset, + scheduler: scheduler + }; + + scheduler._pipe(seriesModel, task); + } + }; + + Scheduler.prototype._createOverallStageTask = function (stageHandler, stageHandlerRecord, ecModel, api) { + var scheduler = this; + var overallTask = stageHandlerRecord.overallTask = stageHandlerRecord.overallTask // For overall task, the function only be called on reset stage. + || createTask({ + reset: overallTaskReset + }); + overallTask.context = { + ecModel: ecModel, + api: api, + overallReset: stageHandler.overallReset, + scheduler: scheduler + }; + var oldAgentStubMap = overallTask.agentStubMap; // The count of stages are totally about only several dozen, so + // do not need to reuse the map. + + var newAgentStubMap = overallTask.agentStubMap = createHashMap(); + var seriesType = stageHandler.seriesType; + var getTargetSeries = stageHandler.getTargetSeries; + var overallProgress = true; + var shouldOverallTaskDirty = false; // FIXME:TS never used, so comment it + // let modifyOutputEnd = stageHandler.modifyOutputEnd; + // An overall task with seriesType detected or has `getTargetSeries`, we add + // stub in each pipelines, it will set the overall task dirty when the pipeline + // progress. Moreover, to avoid call the overall task each frame (too frequent), + // we set the pipeline block. + + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = '"createOnAllSeries" do not supported for "overallReset", ' + 'becuase it will block all streams.'; + } + + assert(!stageHandler.createOnAllSeries, errMsg); + + if (seriesType) { + ecModel.eachRawSeriesByType(seriesType, createStub); + } else if (getTargetSeries) { + getTargetSeries(ecModel, api).each(createStub); + } // Otherwise, (usually it is legancy case), the overall task will only be + // executed when upstream dirty. Otherwise the progressive rendering of all + // pipelines will be disabled unexpectedly. But it still needs stubs to receive + // dirty info from upsteam. + else { + overallProgress = false; + each(ecModel.getSeries(), createStub); + } + + function createStub(seriesModel) { + var pipelineId = seriesModel.uid; + var stub = newAgentStubMap.set(pipelineId, oldAgentStubMap && oldAgentStubMap.get(pipelineId) || ( // When the result of `getTargetSeries` changed, the overallTask + // should be set as dirty and re-performed. + shouldOverallTaskDirty = true, createTask({ + reset: stubReset, + onDirty: stubOnDirty + }))); + stub.context = { + model: seriesModel, + overallProgress: overallProgress // FIXME:TS never used, so comment it + // modifyOutputEnd: modifyOutputEnd + + }; + stub.agent = overallTask; + stub.__block = overallProgress; + + scheduler._pipe(seriesModel, stub); + } + + if (shouldOverallTaskDirty) { + overallTask.dirty(); + } + }; + + Scheduler.prototype._pipe = function (seriesModel, task) { + var pipelineId = seriesModel.uid; + + var pipeline = this._pipelineMap.get(pipelineId); + + !pipeline.head && (pipeline.head = task); + pipeline.tail && pipeline.tail.pipe(task); + pipeline.tail = task; + task.__idxInPipeline = pipeline.count++; + task.__pipeline = pipeline; + }; + + Scheduler.wrapStageHandler = function (stageHandler, visualType) { + if (isFunction(stageHandler)) { + stageHandler = { + overallReset: stageHandler, + seriesType: detectSeriseType(stageHandler) + }; + } + + stageHandler.uid = getUID('stageHandler'); + visualType && (stageHandler.visualType = visualType); + return stageHandler; + }; + return Scheduler; + }(); + + function overallTaskReset(context) { + context.overallReset(context.ecModel, context.api, context.payload); + } + + function stubReset(context) { + return context.overallProgress && stubProgress; + } + + function stubProgress() { + this.agent.dirty(); + this.getDownstream().dirty(); + } + + function stubOnDirty() { + this.agent && this.agent.dirty(); + } + + function seriesTaskPlan(context) { + return context.plan ? context.plan(context.model, context.ecModel, context.api, context.payload) : null; + } + + function seriesTaskReset(context) { + if (context.useClearVisual) { + context.data.clearAllVisual(); + } + + var resetDefines = context.resetDefines = normalizeToArray(context.reset(context.model, context.ecModel, context.api, context.payload)); + return resetDefines.length > 1 ? map(resetDefines, function (v, idx) { + return makeSeriesTaskProgress(idx); + }) : singleSeriesTaskProgress; + } + + var singleSeriesTaskProgress = makeSeriesTaskProgress(0); + + function makeSeriesTaskProgress(resetDefineIdx) { + return function (params, context) { + var data = context.data; + var resetDefine = context.resetDefines[resetDefineIdx]; + + if (resetDefine && resetDefine.dataEach) { + for (var i = params.start; i < params.end; i++) { + resetDefine.dataEach(data, i); + } + } else if (resetDefine && resetDefine.progress) { + resetDefine.progress(params, data); + } + }; + } + + function seriesTaskCount(context) { + return context.data.count(); + } + /** + * Only some legacy stage handlers (usually in echarts extensions) are pure function. + * To ensure that they can work normally, they should work in block mode, that is, + * they should not be started util the previous tasks finished. So they cause the + * progressive rendering disabled. We try to detect the series type, to narrow down + * the block range to only the series type they concern, but not all series. + */ + + + function detectSeriseType(legacyFunc) { + seriesType = null; + + try { + // Assume there is no async when calling `eachSeriesByType`. + legacyFunc(ecModelMock, apiMock); + } catch (e) {} + + return seriesType; + } + + var ecModelMock = {}; + var apiMock = {}; + var seriesType; + mockMethods(ecModelMock, GlobalModel); + mockMethods(apiMock, ExtensionAPI); + + ecModelMock.eachSeriesByType = ecModelMock.eachRawSeriesByType = function (type) { + seriesType = type; + }; + + ecModelMock.eachComponent = function (cond) { + if (cond.mainType === 'series' && cond.subType) { + seriesType = cond.subType; + } + }; + + function mockMethods(target, Clz) { + /* eslint-disable */ + for (var name_1 in Clz.prototype) { + // Do not use hasOwnProperty + target[name_1] = noop; + } + /* eslint-enable */ + + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var colorAll = ['#37A2DA', '#32C5E9', '#67E0E3', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#E062AE', '#E690D1', '#e7bcf3', '#9d96f5', '#8378EA', '#96BFFF']; + var lightTheme = { + color: colorAll, + colorLayer: [['#37A2DA', '#ffd85c', '#fd7b5f'], ['#37A2DA', '#67E0E3', '#FFDB5C', '#ff9f7f', '#E062AE', '#9d96f5'], ['#37A2DA', '#32C5E9', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#e7bcf3', '#8378EA', '#96BFFF'], colorAll] + }; + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var contrastColor = '#B9B8CE'; + var backgroundColor = '#100C2A'; + + var axisCommon = function () { + return { + axisLine: { + lineStyle: { + color: contrastColor + } + }, + splitLine: { + lineStyle: { + color: '#484753' + } + }, + splitArea: { + areaStyle: { + color: ['rgba(255,255,255,0.02)', 'rgba(255,255,255,0.05)'] + } + }, + minorSplitLine: { + lineStyle: { + color: '#20203B' + } + } + }; + }; + + var colorPalette = ['#4992ff', '#7cffb2', '#fddd60', '#ff6e76', '#58d9f9', '#05c091', '#ff8a45', '#8d48e3', '#dd79ff']; + var theme = { + darkMode: true, + color: colorPalette, + backgroundColor: backgroundColor, + axisPointer: { + lineStyle: { + color: '#817f91' + }, + crossStyle: { + color: '#817f91' + }, + label: { + // TODO Contrast of label backgorundColor + color: '#fff' + } + }, + legend: { + textStyle: { + color: contrastColor + } + }, + textStyle: { + color: contrastColor + }, + title: { + textStyle: { + color: '#EEF1FA' + }, + subtextStyle: { + color: '#B9B8CE' + } + }, + toolbox: { + iconStyle: { + borderColor: contrastColor + } + }, + dataZoom: { + borderColor: '#71708A', + textStyle: { + color: contrastColor + }, + brushStyle: { + color: 'rgba(135,163,206,0.3)' + }, + handleStyle: { + color: '#353450', + borderColor: '#C5CBE3' + }, + moveHandleStyle: { + color: '#B0B6C3', + opacity: 0.3 + }, + fillerColor: 'rgba(135,163,206,0.2)', + emphasis: { + handleStyle: { + borderColor: '#91B7F2', + color: '#4D587D' + }, + moveHandleStyle: { + color: '#636D9A', + opacity: 0.7 + } + }, + dataBackground: { + lineStyle: { + color: '#71708A', + width: 1 + }, + areaStyle: { + color: '#71708A' + } + }, + selectedDataBackground: { + lineStyle: { + color: '#87A3CE' + }, + areaStyle: { + color: '#87A3CE' + } + } + }, + visualMap: { + textStyle: { + color: contrastColor + } + }, + timeline: { + lineStyle: { + color: contrastColor + }, + label: { + color: contrastColor + }, + controlStyle: { + color: contrastColor, + borderColor: contrastColor + } + }, + calendar: { + itemStyle: { + color: backgroundColor + }, + dayLabel: { + color: contrastColor + }, + monthLabel: { + color: contrastColor + }, + yearLabel: { + color: contrastColor + } + }, + timeAxis: axisCommon(), + logAxis: axisCommon(), + valueAxis: axisCommon(), + categoryAxis: axisCommon(), + line: { + symbol: 'circle' + }, + graph: { + color: colorPalette + }, + gauge: { + title: { + color: contrastColor + }, + axisLine: { + lineStyle: { + color: [[1, 'rgba(207,212,219,0.2)']] + } + }, + axisLabel: { + color: contrastColor + }, + detail: { + color: '#EEF1FA' + } + }, + candlestick: { + itemStyle: { + color: '#f64e56', + color0: '#54ea92', + borderColor: '#f64e56', + borderColor0: '#54ea92' // borderColor: '#ca2824', + // borderColor0: '#09a443' + + } + } + }; + theme.categoryAxis.splitLine.show = false; + + /** + * Usage of query: + * `chart.on('click', query, handler);` + * The `query` can be: + * + The component type query string, only `mainType` or `mainType.subType`, + * like: 'xAxis', 'series', 'xAxis.category' or 'series.line'. + * + The component query object, like: + * `{seriesIndex: 2}`, `{seriesName: 'xx'}`, `{seriesId: 'some'}`, + * `{xAxisIndex: 2}`, `{xAxisName: 'xx'}`, `{xAxisId: 'some'}`. + * + The data query object, like: + * `{dataIndex: 123}`, `{dataType: 'link'}`, `{name: 'some'}`. + * + The other query object (cmponent customized query), like: + * `{element: 'some'}` (only available in custom series). + * + * Caveat: If a prop in the `query` object is `null/undefined`, it is the + * same as there is no such prop in the `query` object. + */ + + var ECEventProcessor = + /** @class */ + function () { + function ECEventProcessor() {} + + ECEventProcessor.prototype.normalizeQuery = function (query) { + var cptQuery = {}; + var dataQuery = {}; + var otherQuery = {}; // `query` is `mainType` or `mainType.subType` of component. + + if (isString(query)) { + var condCptType = parseClassType(query); // `.main` and `.sub` may be ''. + + cptQuery.mainType = condCptType.main || null; + cptQuery.subType = condCptType.sub || null; + } // `query` is an object, convert to {mainType, index, name, id}. + else { + // `xxxIndex`, `xxxName`, `xxxId`, `name`, `dataIndex`, `dataType` is reserved, + // can not be used in `compomentModel.filterForExposedEvent`. + var suffixes_1 = ['Index', 'Name', 'Id']; + var dataKeys_1 = { + name: 1, + dataIndex: 1, + dataType: 1 + }; + each(query, function (val, key) { + var reserved = false; + + for (var i = 0; i < suffixes_1.length; i++) { + var propSuffix = suffixes_1[i]; + var suffixPos = key.lastIndexOf(propSuffix); + + if (suffixPos > 0 && suffixPos === key.length - propSuffix.length) { + var mainType = key.slice(0, suffixPos); // Consider `dataIndex`. + + if (mainType !== 'data') { + cptQuery.mainType = mainType; + cptQuery[propSuffix.toLowerCase()] = val; + reserved = true; + } + } + } + + if (dataKeys_1.hasOwnProperty(key)) { + dataQuery[key] = val; + reserved = true; + } + + if (!reserved) { + otherQuery[key] = val; + } + }); + } + + return { + cptQuery: cptQuery, + dataQuery: dataQuery, + otherQuery: otherQuery + }; + }; + + ECEventProcessor.prototype.filter = function (eventType, query) { + // They should be assigned before each trigger call. + var eventInfo = this.eventInfo; + + if (!eventInfo) { + return true; + } + + var targetEl = eventInfo.targetEl; + var packedEvent = eventInfo.packedEvent; + var model = eventInfo.model; + var view = eventInfo.view; // For event like 'globalout'. + + if (!model || !view) { + return true; + } + + var cptQuery = query.cptQuery; + var dataQuery = query.dataQuery; + return check(cptQuery, model, 'mainType') && check(cptQuery, model, 'subType') && check(cptQuery, model, 'index', 'componentIndex') && check(cptQuery, model, 'name') && check(cptQuery, model, 'id') && check(dataQuery, packedEvent, 'name') && check(dataQuery, packedEvent, 'dataIndex') && check(dataQuery, packedEvent, 'dataType') && (!view.filterForExposedEvent || view.filterForExposedEvent(eventType, query.otherQuery, targetEl, packedEvent)); + + function check(query, host, prop, propOnHost) { + return query[prop] == null || host[propOnHost || prop] === query[prop]; + } + }; + + ECEventProcessor.prototype.afterTrigger = function () { + // Make sure the eventInfo wont be used in next trigger. + this.eventInfo = null; + }; + + return ECEventProcessor; + }(); + + var SYMBOL_PROPS_WITH_CB = ['symbol', 'symbolSize', 'symbolRotate', 'symbolOffset']; + var SYMBOL_PROPS = SYMBOL_PROPS_WITH_CB.concat(['symbolKeepAspect']); // Encoding visual for all series include which is filtered for legend drawing + + var seriesSymbolTask = { + createOnAllSeries: true, + // For legend. + performRawSeries: true, + reset: function (seriesModel, ecModel) { + var data = seriesModel.getData(); + + if (seriesModel.legendIcon) { + data.setVisual('legendIcon', seriesModel.legendIcon); + } + + if (!seriesModel.hasSymbolVisual) { + return; + } + + var symbolOptions = {}; + var symbolOptionsCb = {}; + var hasCallback = false; + + for (var i = 0; i < SYMBOL_PROPS_WITH_CB.length; i++) { + var symbolPropName = SYMBOL_PROPS_WITH_CB[i]; + var val = seriesModel.get(symbolPropName); + + if (isFunction(val)) { + hasCallback = true; + symbolOptionsCb[symbolPropName] = val; + } else { + symbolOptions[symbolPropName] = val; + } + } + + symbolOptions.symbol = symbolOptions.symbol || seriesModel.defaultSymbol; + data.setVisual(extend({ + legendIcon: seriesModel.legendIcon || symbolOptions.symbol, + symbolKeepAspect: seriesModel.get('symbolKeepAspect') + }, symbolOptions)); // Only visible series has each data be visual encoded + + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var symbolPropsCb = keys(symbolOptionsCb); + + function dataEach(data, idx) { + var rawValue = seriesModel.getRawValue(idx); + var params = seriesModel.getDataParams(idx); + + for (var i = 0; i < symbolPropsCb.length; i++) { + var symbolPropName = symbolPropsCb[i]; + data.setItemVisual(idx, symbolPropName, symbolOptionsCb[symbolPropName](rawValue, params)); + } + } + + return { + dataEach: hasCallback ? dataEach : null + }; + } + }; + var dataSymbolTask = { + createOnAllSeries: true, + // For legend. + performRawSeries: true, + reset: function (seriesModel, ecModel) { + if (!seriesModel.hasSymbolVisual) { + return; + } // Only visible series has each data be visual encoded + + + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var data = seriesModel.getData(); + + function dataEach(data, idx) { + var itemModel = data.getItemModel(idx); + + for (var i = 0; i < SYMBOL_PROPS.length; i++) { + var symbolPropName = SYMBOL_PROPS[i]; + var val = itemModel.getShallow(symbolPropName, true); + + if (val != null) { + data.setItemVisual(idx, symbolPropName, val); + } + } + } + + return { + dataEach: data.hasItemOption ? dataEach : null + }; + } + }; + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function getItemVisualFromData(data, dataIndex, key) { + switch (key) { + case 'color': + var style = data.getItemVisual(dataIndex, 'style'); + return style[data.getVisual('drawType')]; + + case 'opacity': + return data.getItemVisual(dataIndex, 'style').opacity; + + case 'symbol': + case 'symbolSize': + case 'liftZ': + return data.getItemVisual(dataIndex, key); + + default: + if ("development" !== 'production') { + console.warn("Unknown visual type " + key); + } + + } + } + function getVisualFromData(data, key) { + switch (key) { + case 'color': + var style = data.getVisual('style'); + return style[data.getVisual('drawType')]; + + case 'opacity': + return data.getVisual('style').opacity; + + case 'symbol': + case 'symbolSize': + case 'liftZ': + return data.getVisual(key); + + default: + if ("development" !== 'production') { + console.warn("Unknown visual type " + key); + } + + } + } + function setItemVisualFromData(data, dataIndex, key, value) { + switch (key) { + case 'color': + // Make sure not sharing style object. + var style = data.ensureUniqueItemVisual(dataIndex, 'style'); + style[data.getVisual('drawType')] = value; // Mark the color has been changed, not from palette anymore + + data.setItemVisual(dataIndex, 'colorFromPalette', false); + break; + + case 'opacity': + data.ensureUniqueItemVisual(dataIndex, 'style').opacity = value; + break; + + case 'symbol': + case 'symbolSize': + case 'liftZ': + data.setItemVisual(dataIndex, key, value); + break; + + default: + if ("development" !== 'production') { + console.warn("Unknown visual type " + key); + } + + } + } + + // Inlucdes: pieSelect, pieUnSelect, pieToggleSelect, mapSelect, mapUnSelect, mapToggleSelect + + function createLegacyDataSelectAction(seriesType, ecRegisterAction) { + function getSeriesIndices(ecModel, payload) { + var seriesIndices = []; + ecModel.eachComponent({ + mainType: 'series', + subType: seriesType, + query: payload + }, function (seriesModel) { + seriesIndices.push(seriesModel.seriesIndex); + }); + return seriesIndices; + } + + each([[seriesType + 'ToggleSelect', 'toggleSelect'], [seriesType + 'Select', 'select'], [seriesType + 'UnSelect', 'unselect']], function (eventsMap) { + ecRegisterAction(eventsMap[0], function (payload, ecModel, api) { + payload = extend({}, payload); + + if ("development" !== 'production') { + deprecateReplaceLog(payload.type, eventsMap[1]); + } + + api.dispatchAction(extend(payload, { + type: eventsMap[1], + seriesIndex: getSeriesIndices(ecModel, payload) + })); + }); + }); + } + + function handleSeriesLegacySelectEvents(type, eventPostfix, ecIns, ecModel, payload) { + var legacyEventName = type + eventPostfix; + + if (!ecIns.isSilent(legacyEventName)) { + if ("development" !== 'production') { + deprecateLog("event " + legacyEventName + " is deprecated."); + } + + ecModel.eachComponent({ + mainType: 'series', + subType: 'pie' + }, function (seriesModel) { + var seriesIndex = seriesModel.seriesIndex; + var selectedMap = seriesModel.option.selectedMap; + var selected = payload.selected; + + for (var i = 0; i < selected.length; i++) { + if (selected[i].seriesIndex === seriesIndex) { + var data = seriesModel.getData(); + var dataIndex = queryDataIndex(data, payload.fromActionPayload); + ecIns.trigger(legacyEventName, { + type: legacyEventName, + seriesId: seriesModel.id, + name: isArray(dataIndex) ? data.getName(dataIndex[0]) : data.getName(dataIndex), + selected: isString(selectedMap) ? selectedMap : extend({}, selectedMap) + }); + } + } + }); + } + } + + function handleLegacySelectEvents(messageCenter, ecIns, api) { + messageCenter.on('selectchanged', function (params) { + var ecModel = api.getModel(); + + if (params.isFromClick) { + handleSeriesLegacySelectEvents('map', 'selectchanged', ecIns, ecModel, params); + handleSeriesLegacySelectEvents('pie', 'selectchanged', ecIns, ecModel, params); + } else if (params.fromAction === 'select') { + handleSeriesLegacySelectEvents('map', 'selected', ecIns, ecModel, params); + handleSeriesLegacySelectEvents('pie', 'selected', ecIns, ecModel, params); + } else if (params.fromAction === 'unselect') { + handleSeriesLegacySelectEvents('map', 'unselected', ecIns, ecModel, params); + handleSeriesLegacySelectEvents('pie', 'unselected', ecIns, ecModel, params); + } + }); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function findEventDispatcher(target, det, returnFirstMatch) { + var found; + + while (target) { + if (det(target)) { + found = target; + + if (returnFirstMatch) { + break; + } + } + + target = target.__hostTarget || target.parent; + } + + return found; + } + + var wmUniqueIndex = Math.round(Math.random() * 9); + var supportDefineProperty = typeof Object.defineProperty === 'function'; + var WeakMap = (function () { + function WeakMap() { + this._id = '__ec_inner_' + wmUniqueIndex++; + } + WeakMap.prototype.get = function (key) { + return this._guard(key)[this._id]; + }; + WeakMap.prototype.set = function (key, value) { + var target = this._guard(key); + if (supportDefineProperty) { + Object.defineProperty(target, this._id, { + value: value, + enumerable: false, + configurable: true + }); + } + else { + target[this._id] = value; + } + return this; + }; + WeakMap.prototype["delete"] = function (key) { + if (this.has(key)) { + delete this._guard(key)[this._id]; + return true; + } + return false; + }; + WeakMap.prototype.has = function (key) { + return !!this._guard(key)[this._id]; + }; + WeakMap.prototype._guard = function (key) { + if (key !== Object(key)) { + throw TypeError('Value of WeakMap is not a non-null object.'); + } + return key; + }; + return WeakMap; + }()); + + /** + * Triangle shape + * @inner + */ + + var Triangle = Path.extend({ + type: 'triangle', + shape: { + cx: 0, + cy: 0, + width: 0, + height: 0 + }, + buildPath: function (path, shape) { + var cx = shape.cx; + var cy = shape.cy; + var width = shape.width / 2; + var height = shape.height / 2; + path.moveTo(cx, cy - height); + path.lineTo(cx + width, cy + height); + path.lineTo(cx - width, cy + height); + path.closePath(); + } + }); + /** + * Diamond shape + * @inner + */ + + var Diamond = Path.extend({ + type: 'diamond', + shape: { + cx: 0, + cy: 0, + width: 0, + height: 0 + }, + buildPath: function (path, shape) { + var cx = shape.cx; + var cy = shape.cy; + var width = shape.width / 2; + var height = shape.height / 2; + path.moveTo(cx, cy - height); + path.lineTo(cx + width, cy); + path.lineTo(cx, cy + height); + path.lineTo(cx - width, cy); + path.closePath(); + } + }); + /** + * Pin shape + * @inner + */ + + var Pin = Path.extend({ + type: 'pin', + shape: { + // x, y on the cusp + x: 0, + y: 0, + width: 0, + height: 0 + }, + buildPath: function (path, shape) { + var x = shape.x; + var y = shape.y; + var w = shape.width / 5 * 3; // Height must be larger than width + + var h = Math.max(w, shape.height); + var r = w / 2; // Dist on y with tangent point and circle center + + var dy = r * r / (h - r); + var cy = y - h + r + dy; + var angle = Math.asin(dy / r); // Dist on x with tangent point and circle center + + var dx = Math.cos(angle) * r; + var tanX = Math.sin(angle); + var tanY = Math.cos(angle); + var cpLen = r * 0.6; + var cpLen2 = r * 0.7; + path.moveTo(x - dx, cy + dy); + path.arc(x, cy, r, Math.PI - angle, Math.PI * 2 + angle); + path.bezierCurveTo(x + dx - tanX * cpLen, cy + dy + tanY * cpLen, x, y - cpLen2, x, y); + path.bezierCurveTo(x, y - cpLen2, x - dx + tanX * cpLen, cy + dy + tanY * cpLen, x - dx, cy + dy); + path.closePath(); + } + }); + /** + * Arrow shape + * @inner + */ + + var Arrow = Path.extend({ + type: 'arrow', + shape: { + x: 0, + y: 0, + width: 0, + height: 0 + }, + buildPath: function (ctx, shape) { + var height = shape.height; + var width = shape.width; + var x = shape.x; + var y = shape.y; + var dx = width / 3 * 2; + ctx.moveTo(x, y); + ctx.lineTo(x + dx, y + height); + ctx.lineTo(x, y + height / 4 * 3); + ctx.lineTo(x - dx, y + height); + ctx.lineTo(x, y); + ctx.closePath(); + } + }); + /** + * Map of path contructors + */ + // TODO Use function to build symbol path. + + var symbolCtors = { + line: Line, + rect: Rect, + roundRect: Rect, + square: Rect, + circle: Circle, + diamond: Diamond, + pin: Pin, + arrow: Arrow, + triangle: Triangle + }; + var symbolShapeMakers = { + line: function (x, y, w, h, shape) { + shape.x1 = x; + shape.y1 = y + h / 2; + shape.x2 = x + w; + shape.y2 = y + h / 2; + }, + rect: function (x, y, w, h, shape) { + shape.x = x; + shape.y = y; + shape.width = w; + shape.height = h; + }, + roundRect: function (x, y, w, h, shape) { + shape.x = x; + shape.y = y; + shape.width = w; + shape.height = h; + shape.r = Math.min(w, h) / 4; + }, + square: function (x, y, w, h, shape) { + var size = Math.min(w, h); + shape.x = x; + shape.y = y; + shape.width = size; + shape.height = size; + }, + circle: function (x, y, w, h, shape) { + // Put circle in the center of square + shape.cx = x + w / 2; + shape.cy = y + h / 2; + shape.r = Math.min(w, h) / 2; + }, + diamond: function (x, y, w, h, shape) { + shape.cx = x + w / 2; + shape.cy = y + h / 2; + shape.width = w; + shape.height = h; + }, + pin: function (x, y, w, h, shape) { + shape.x = x + w / 2; + shape.y = y + h / 2; + shape.width = w; + shape.height = h; + }, + arrow: function (x, y, w, h, shape) { + shape.x = x + w / 2; + shape.y = y + h / 2; + shape.width = w; + shape.height = h; + }, + triangle: function (x, y, w, h, shape) { + shape.cx = x + w / 2; + shape.cy = y + h / 2; + shape.width = w; + shape.height = h; + } + }; + var symbolBuildProxies = {}; + each(symbolCtors, function (Ctor, name) { + symbolBuildProxies[name] = new Ctor(); + }); + var SymbolClz = Path.extend({ + type: 'symbol', + shape: { + symbolType: '', + x: 0, + y: 0, + width: 0, + height: 0 + }, + calculateTextPosition: function (out, config, rect) { + var res = calculateTextPosition(out, config, rect); + var shape = this.shape; + + if (shape && shape.symbolType === 'pin' && config.position === 'inside') { + res.y = rect.y + rect.height * 0.4; + } + + return res; + }, + buildPath: function (ctx, shape, inBundle) { + var symbolType = shape.symbolType; + + if (symbolType !== 'none') { + var proxySymbol = symbolBuildProxies[symbolType]; + + if (!proxySymbol) { + // Default rect + symbolType = 'rect'; + proxySymbol = symbolBuildProxies[symbolType]; + } + + symbolShapeMakers[symbolType](shape.x, shape.y, shape.width, shape.height, proxySymbol.shape); + proxySymbol.buildPath(ctx, proxySymbol.shape, inBundle); + } + } + }); // Provide setColor helper method to avoid determine if set the fill or stroke outside + + function symbolPathSetColor(color, innerColor) { + if (this.type !== 'image') { + var symbolStyle = this.style; + + if (this.__isEmptyBrush) { + symbolStyle.stroke = color; + symbolStyle.fill = innerColor || '#fff'; // TODO Same width with lineStyle in LineView + + symbolStyle.lineWidth = 2; + } else if (this.shape.symbolType === 'line') { + symbolStyle.stroke = color; + } else { + symbolStyle.fill = color; + } + + this.markRedraw(); + } + } + /** + * Create a symbol element with given symbol configuration: shape, x, y, width, height, color + */ + + + function createSymbol(symbolType, x, y, w, h, color, // whether to keep the ratio of w/h, + keepAspect) { + // TODO Support image object, DynamicImage. + var isEmpty = symbolType.indexOf('empty') === 0; + + if (isEmpty) { + symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6); + } + + var symbolPath; + + if (symbolType.indexOf('image://') === 0) { + symbolPath = makeImage(symbolType.slice(8), new BoundingRect(x, y, w, h), keepAspect ? 'center' : 'cover'); + } else if (symbolType.indexOf('path://') === 0) { + symbolPath = makePath(symbolType.slice(7), {}, new BoundingRect(x, y, w, h), keepAspect ? 'center' : 'cover'); + } else { + symbolPath = new SymbolClz({ + shape: { + symbolType: symbolType, + x: x, + y: y, + width: w, + height: h + } + }); + } + + symbolPath.__isEmptyBrush = isEmpty; // TODO Should deprecate setColor + + symbolPath.setColor = symbolPathSetColor; + + if (color) { + symbolPath.setColor(color); + } + + return symbolPath; + } + function normalizeSymbolSize(symbolSize) { + if (!isArray(symbolSize)) { + symbolSize = [+symbolSize, +symbolSize]; + } + + return [symbolSize[0] || 0, symbolSize[1] || 0]; + } + function normalizeSymbolOffset(symbolOffset, symbolSize) { + if (symbolOffset == null) { + return; + } + + if (!isArray(symbolOffset)) { + symbolOffset = [symbolOffset, symbolOffset]; + } + + return [parsePercent$1(symbolOffset[0], symbolSize[0]) || 0, parsePercent$1(retrieve2(symbolOffset[1], symbolOffset[0]), symbolSize[1]) || 0]; + } + + function createLinearGradient(ctx, obj, rect) { + var x = obj.x == null ? 0 : obj.x; + var x2 = obj.x2 == null ? 1 : obj.x2; + var y = obj.y == null ? 0 : obj.y; + var y2 = obj.y2 == null ? 0 : obj.y2; + if (!obj.global) { + x = x * rect.width + rect.x; + x2 = x2 * rect.width + rect.x; + y = y * rect.height + rect.y; + y2 = y2 * rect.height + rect.y; + } + x = isNaN(x) ? 0 : x; + x2 = isNaN(x2) ? 1 : x2; + y = isNaN(y) ? 0 : y; + y2 = isNaN(y2) ? 0 : y2; + var canvasGradient = ctx.createLinearGradient(x, y, x2, y2); + return canvasGradient; + } + function createRadialGradient(ctx, obj, rect) { + var width = rect.width; + var height = rect.height; + var min = Math.min(width, height); + var x = obj.x == null ? 0.5 : obj.x; + var y = obj.y == null ? 0.5 : obj.y; + var r = obj.r == null ? 0.5 : obj.r; + if (!obj.global) { + x = x * width + rect.x; + y = y * height + rect.y; + r = r * min; + } + var canvasGradient = ctx.createRadialGradient(x, y, 0, x, y, r); + return canvasGradient; + } + function getCanvasGradient(ctx, obj, rect) { + var canvasGradient = obj.type === 'radial' + ? createRadialGradient(ctx, obj, rect) + : createLinearGradient(ctx, obj, rect); + var colorStops = obj.colorStops; + for (var i = 0; i < colorStops.length; i++) { + canvasGradient.addColorStop(colorStops[i].offset, colorStops[i].color); + } + return canvasGradient; + } + function isClipPathChanged(clipPaths, prevClipPaths) { + if (clipPaths === prevClipPaths || (!clipPaths && !prevClipPaths)) { + return false; + } + if (!clipPaths || !prevClipPaths || (clipPaths.length !== prevClipPaths.length)) { + return true; + } + for (var i = 0; i < clipPaths.length; i++) { + if (clipPaths[i] !== prevClipPaths[i]) { + return true; + } + } + return false; + } + function parseInt10(val) { + return parseInt(val, 10); + } + function getSize(root, whIdx, opts) { + var wh = ['width', 'height'][whIdx]; + var cwh = ['clientWidth', 'clientHeight'][whIdx]; + var plt = ['paddingLeft', 'paddingTop'][whIdx]; + var prb = ['paddingRight', 'paddingBottom'][whIdx]; + if (opts[wh] != null && opts[wh] !== 'auto') { + return parseFloat(opts[wh]); + } + var stl = document.defaultView.getComputedStyle(root); + return ((root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh])) + - (parseInt10(stl[plt]) || 0) + - (parseInt10(stl[prb]) || 0)) | 0; + } + + function normalizeLineDash(lineType, lineWidth) { + if (!lineType || lineType === 'solid' || !(lineWidth > 0)) { + return null; + } + return lineType === 'dashed' + ? [4 * lineWidth, 2 * lineWidth] + : lineType === 'dotted' + ? [lineWidth] + : isNumber(lineType) + ? [lineType] : isArray(lineType) ? lineType : null; + } + function getLineDash(el) { + var style = el.style; + var lineDash = style.lineDash && style.lineWidth > 0 && normalizeLineDash(style.lineDash, style.lineWidth); + var lineDashOffset = style.lineDashOffset; + if (lineDash) { + var lineScale_1 = (style.strokeNoScale && el.getLineScale) ? el.getLineScale() : 1; + if (lineScale_1 && lineScale_1 !== 1) { + lineDash = map(lineDash, function (rawVal) { + return rawVal / lineScale_1; + }); + lineDashOffset /= lineScale_1; + } + } + return [lineDash, lineDashOffset]; + } + + var pathProxyForDraw = new PathProxy(true); + function styleHasStroke(style) { + var stroke = style.stroke; + return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0)); + } + function isValidStrokeFillStyle(strokeOrFill) { + return typeof strokeOrFill === 'string' && strokeOrFill !== 'none'; + } + function styleHasFill(style) { + var fill = style.fill; + return fill != null && fill !== 'none'; + } + function doFillPath(ctx, style) { + if (style.fillOpacity != null && style.fillOpacity !== 1) { + var originalGlobalAlpha = ctx.globalAlpha; + ctx.globalAlpha = style.fillOpacity * style.opacity; + ctx.fill(); + ctx.globalAlpha = originalGlobalAlpha; + } + else { + ctx.fill(); + } + } + function doStrokePath(ctx, style) { + if (style.strokeOpacity != null && style.strokeOpacity !== 1) { + var originalGlobalAlpha = ctx.globalAlpha; + ctx.globalAlpha = style.strokeOpacity * style.opacity; + ctx.stroke(); + ctx.globalAlpha = originalGlobalAlpha; + } + else { + ctx.stroke(); + } + } + function createCanvasPattern(ctx, pattern, el) { + var image = createOrUpdateImage(pattern.image, pattern.__image, el); + if (isImageReady(image)) { + var canvasPattern = ctx.createPattern(image, pattern.repeat || 'repeat'); + if (typeof DOMMatrix === 'function' + && canvasPattern + && canvasPattern.setTransform) { + var matrix = new DOMMatrix(); + matrix.translateSelf((pattern.x || 0), (pattern.y || 0)); + matrix.rotateSelf(0, 0, (pattern.rotation || 0) * RADIAN_TO_DEGREE); + matrix.scaleSelf((pattern.scaleX || 1), (pattern.scaleY || 1)); + canvasPattern.setTransform(matrix); + } + return canvasPattern; + } + } + function brushPath(ctx, el, style, inBatch) { + var _a; + var hasStroke = styleHasStroke(style); + var hasFill = styleHasFill(style); + var strokePercent = style.strokePercent; + var strokePart = strokePercent < 1; + var firstDraw = !el.path; + if ((!el.silent || strokePart) && firstDraw) { + el.createPathProxy(); + } + var path = el.path || pathProxyForDraw; + var dirtyFlag = el.__dirty; + if (!inBatch) { + var fill = style.fill; + var stroke = style.stroke; + var hasFillGradient = hasFill && !!fill.colorStops; + var hasStrokeGradient = hasStroke && !!stroke.colorStops; + var hasFillPattern = hasFill && !!fill.image; + var hasStrokePattern = hasStroke && !!stroke.image; + var fillGradient = void 0; + var strokeGradient = void 0; + var fillPattern = void 0; + var strokePattern = void 0; + var rect = void 0; + if (hasFillGradient || hasStrokeGradient) { + rect = el.getBoundingRect(); + } + if (hasFillGradient) { + fillGradient = dirtyFlag + ? getCanvasGradient(ctx, fill, rect) + : el.__canvasFillGradient; + el.__canvasFillGradient = fillGradient; + } + if (hasStrokeGradient) { + strokeGradient = dirtyFlag + ? getCanvasGradient(ctx, stroke, rect) + : el.__canvasStrokeGradient; + el.__canvasStrokeGradient = strokeGradient; + } + if (hasFillPattern) { + fillPattern = (dirtyFlag || !el.__canvasFillPattern) + ? createCanvasPattern(ctx, fill, el) + : el.__canvasFillPattern; + el.__canvasFillPattern = fillPattern; + } + if (hasStrokePattern) { + strokePattern = (dirtyFlag || !el.__canvasStrokePattern) + ? createCanvasPattern(ctx, stroke, el) + : el.__canvasStrokePattern; + el.__canvasStrokePattern = fillPattern; + } + if (hasFillGradient) { + ctx.fillStyle = fillGradient; + } + else if (hasFillPattern) { + if (fillPattern) { + ctx.fillStyle = fillPattern; + } + else { + hasFill = false; + } + } + if (hasStrokeGradient) { + ctx.strokeStyle = strokeGradient; + } + else if (hasStrokePattern) { + if (strokePattern) { + ctx.strokeStyle = strokePattern; + } + else { + hasStroke = false; + } + } + } + var scale = el.getGlobalScale(); + path.setScale(scale[0], scale[1], el.segmentIgnoreThreshold); + var lineDash; + var lineDashOffset; + if (ctx.setLineDash && style.lineDash) { + _a = getLineDash(el), lineDash = _a[0], lineDashOffset = _a[1]; + } + var needsRebuild = true; + if (firstDraw || (dirtyFlag & SHAPE_CHANGED_BIT)) { + path.setDPR(ctx.dpr); + if (strokePart) { + path.setContext(null); + } + else { + path.setContext(ctx); + needsRebuild = false; + } + path.reset(); + el.buildPath(path, el.shape, inBatch); + path.toStatic(); + el.pathUpdated(); + } + if (needsRebuild) { + path.rebuildPath(ctx, strokePart ? strokePercent : 1); + } + if (lineDash) { + ctx.setLineDash(lineDash); + ctx.lineDashOffset = lineDashOffset; + } + if (!inBatch) { + if (style.strokeFirst) { + if (hasStroke) { + doStrokePath(ctx, style); + } + if (hasFill) { + doFillPath(ctx, style); + } + } + else { + if (hasFill) { + doFillPath(ctx, style); + } + if (hasStroke) { + doStrokePath(ctx, style); + } + } + } + if (lineDash) { + ctx.setLineDash([]); + } + } + function brushImage(ctx, el, style) { + var image = el.__image = createOrUpdateImage(style.image, el.__image, el, el.onload); + if (!image || !isImageReady(image)) { + return; + } + var x = style.x || 0; + var y = style.y || 0; + var width = el.getWidth(); + var height = el.getHeight(); + var aspect = image.width / image.height; + if (width == null && height != null) { + width = height * aspect; + } + else if (height == null && width != null) { + height = width / aspect; + } + else if (width == null && height == null) { + width = image.width; + height = image.height; + } + if (style.sWidth && style.sHeight) { + var sx = style.sx || 0; + var sy = style.sy || 0; + ctx.drawImage(image, sx, sy, style.sWidth, style.sHeight, x, y, width, height); + } + else if (style.sx && style.sy) { + var sx = style.sx; + var sy = style.sy; + var sWidth = width - sx; + var sHeight = height - sy; + ctx.drawImage(image, sx, sy, sWidth, sHeight, x, y, width, height); + } + else { + ctx.drawImage(image, x, y, width, height); + } + } + function brushText(ctx, el, style) { + var _a; + var text = style.text; + text != null && (text += ''); + if (text) { + ctx.font = style.font || DEFAULT_FONT; + ctx.textAlign = style.textAlign; + ctx.textBaseline = style.textBaseline; + var lineDash = void 0; + var lineDashOffset = void 0; + if (ctx.setLineDash && style.lineDash) { + _a = getLineDash(el), lineDash = _a[0], lineDashOffset = _a[1]; + } + if (lineDash) { + ctx.setLineDash(lineDash); + ctx.lineDashOffset = lineDashOffset; + } + if (style.strokeFirst) { + if (styleHasStroke(style)) { + ctx.strokeText(text, style.x, style.y); + } + if (styleHasFill(style)) { + ctx.fillText(text, style.x, style.y); + } + } + else { + if (styleHasFill(style)) { + ctx.fillText(text, style.x, style.y); + } + if (styleHasStroke(style)) { + ctx.strokeText(text, style.x, style.y); + } + } + if (lineDash) { + ctx.setLineDash([]); + } + } + } + var SHADOW_NUMBER_PROPS = ['shadowBlur', 'shadowOffsetX', 'shadowOffsetY']; + var STROKE_PROPS = [ + ['lineCap', 'butt'], ['lineJoin', 'miter'], ['miterLimit', 10] + ]; + function bindCommonProps(ctx, style, prevStyle, forceSetAll, scope) { + var styleChanged = false; + if (!forceSetAll) { + prevStyle = prevStyle || {}; + if (style === prevStyle) { + return false; + } + } + if (forceSetAll || style.opacity !== prevStyle.opacity) { + flushPathDrawn(ctx, scope); + styleChanged = true; + var opacity = Math.max(Math.min(style.opacity, 1), 0); + ctx.globalAlpha = isNaN(opacity) ? DEFAULT_COMMON_STYLE.opacity : opacity; + } + if (forceSetAll || style.blend !== prevStyle.blend) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx.globalCompositeOperation = style.blend || DEFAULT_COMMON_STYLE.blend; + } + for (var i = 0; i < SHADOW_NUMBER_PROPS.length; i++) { + var propName = SHADOW_NUMBER_PROPS[i]; + if (forceSetAll || style[propName] !== prevStyle[propName]) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx[propName] = ctx.dpr * (style[propName] || 0); + } + } + if (forceSetAll || style.shadowColor !== prevStyle.shadowColor) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx.shadowColor = style.shadowColor || DEFAULT_COMMON_STYLE.shadowColor; + } + return styleChanged; + } + function bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetAll, scope) { + var style = getStyle(el, scope.inHover); + var prevStyle = forceSetAll + ? null + : (prevEl && getStyle(prevEl, scope.inHover) || {}); + if (style === prevStyle) { + return false; + } + var styleChanged = bindCommonProps(ctx, style, prevStyle, forceSetAll, scope); + if (forceSetAll || style.fill !== prevStyle.fill) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + isValidStrokeFillStyle(style.fill) && (ctx.fillStyle = style.fill); + } + if (forceSetAll || style.stroke !== prevStyle.stroke) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + isValidStrokeFillStyle(style.stroke) && (ctx.strokeStyle = style.stroke); + } + if (forceSetAll || style.opacity !== prevStyle.opacity) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx.globalAlpha = style.opacity == null ? 1 : style.opacity; + } + if (el.hasStroke()) { + var lineWidth = style.lineWidth; + var newLineWidth = lineWidth / ((style.strokeNoScale && el.getLineScale) ? el.getLineScale() : 1); + if (ctx.lineWidth !== newLineWidth) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx.lineWidth = newLineWidth; + } + } + for (var i = 0; i < STROKE_PROPS.length; i++) { + var prop = STROKE_PROPS[i]; + var propName = prop[0]; + if (forceSetAll || style[propName] !== prevStyle[propName]) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx[propName] = style[propName] || prop[1]; + } + } + return styleChanged; + } + function bindImageStyle(ctx, el, prevEl, forceSetAll, scope) { + return bindCommonProps(ctx, getStyle(el, scope.inHover), prevEl && getStyle(prevEl, scope.inHover), forceSetAll, scope); + } + function setContextTransform(ctx, el) { + var m = el.transform; + var dpr = ctx.dpr || 1; + if (m) { + ctx.setTransform(dpr * m[0], dpr * m[1], dpr * m[2], dpr * m[3], dpr * m[4], dpr * m[5]); + } + else { + ctx.setTransform(dpr, 0, 0, dpr, 0, 0); + } + } + function updateClipStatus(clipPaths, ctx, scope) { + var allClipped = false; + for (var i = 0; i < clipPaths.length; i++) { + var clipPath = clipPaths[i]; + allClipped = allClipped || clipPath.isZeroArea(); + setContextTransform(ctx, clipPath); + ctx.beginPath(); + clipPath.buildPath(ctx, clipPath.shape); + ctx.clip(); + } + scope.allClipped = allClipped; + } + function isTransformChanged(m0, m1) { + if (m0 && m1) { + return m0[0] !== m1[0] + || m0[1] !== m1[1] + || m0[2] !== m1[2] + || m0[3] !== m1[3] + || m0[4] !== m1[4] + || m0[5] !== m1[5]; + } + else if (!m0 && !m1) { + return false; + } + return true; + } + var DRAW_TYPE_PATH = 1; + var DRAW_TYPE_IMAGE = 2; + var DRAW_TYPE_TEXT = 3; + var DRAW_TYPE_INCREMENTAL = 4; + function canPathBatch(style) { + var hasFill = styleHasFill(style); + var hasStroke = styleHasStroke(style); + return !(style.lineDash + || !(+hasFill ^ +hasStroke) + || (hasFill && typeof style.fill !== 'string') + || (hasStroke && typeof style.stroke !== 'string') + || style.strokePercent < 1 + || style.strokeOpacity < 1 + || style.fillOpacity < 1); + } + function flushPathDrawn(ctx, scope) { + scope.batchFill && ctx.fill(); + scope.batchStroke && ctx.stroke(); + scope.batchFill = ''; + scope.batchStroke = ''; + } + function getStyle(el, inHover) { + return inHover ? (el.__hoverStyle || el.style) : el.style; + } + function brushSingle(ctx, el) { + brush(ctx, el, { inHover: false, viewWidth: 0, viewHeight: 0 }, true); + } + function brush(ctx, el, scope, isLast) { + var m = el.transform; + if (!el.shouldBePainted(scope.viewWidth, scope.viewHeight, false, false)) { + el.__dirty &= ~REDRAW_BIT; + el.__isRendered = false; + return; + } + var clipPaths = el.__clipPaths; + var prevElClipPaths = scope.prevElClipPaths; + var forceSetTransform = false; + var forceSetStyle = false; + if (!prevElClipPaths || isClipPathChanged(clipPaths, prevElClipPaths)) { + if (prevElClipPaths && prevElClipPaths.length) { + flushPathDrawn(ctx, scope); + ctx.restore(); + forceSetStyle = forceSetTransform = true; + scope.prevElClipPaths = null; + scope.allClipped = false; + scope.prevEl = null; + } + if (clipPaths && clipPaths.length) { + flushPathDrawn(ctx, scope); + ctx.save(); + updateClipStatus(clipPaths, ctx, scope); + forceSetTransform = true; + } + scope.prevElClipPaths = clipPaths; + } + if (scope.allClipped) { + el.__isRendered = false; + return; + } + el.beforeBrush && el.beforeBrush(); + el.innerBeforeBrush(); + var prevEl = scope.prevEl; + if (!prevEl) { + forceSetStyle = forceSetTransform = true; + } + var canBatchPath = el instanceof Path + && el.autoBatch + && canPathBatch(el.style); + if (forceSetTransform || isTransformChanged(m, prevEl.transform)) { + flushPathDrawn(ctx, scope); + setContextTransform(ctx, el); + } + else if (!canBatchPath) { + flushPathDrawn(ctx, scope); + } + var style = getStyle(el, scope.inHover); + if (el instanceof Path) { + if (scope.lastDrawType !== DRAW_TYPE_PATH) { + forceSetStyle = true; + scope.lastDrawType = DRAW_TYPE_PATH; + } + bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetStyle, scope); + if (!canBatchPath || (!scope.batchFill && !scope.batchStroke)) { + ctx.beginPath(); + } + brushPath(ctx, el, style, canBatchPath); + if (canBatchPath) { + scope.batchFill = style.fill || ''; + scope.batchStroke = style.stroke || ''; + } + } + else { + if (el instanceof TSpan) { + if (scope.lastDrawType !== DRAW_TYPE_TEXT) { + forceSetStyle = true; + scope.lastDrawType = DRAW_TYPE_TEXT; + } + bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetStyle, scope); + brushText(ctx, el, style); + } + else if (el instanceof ZRImage) { + if (scope.lastDrawType !== DRAW_TYPE_IMAGE) { + forceSetStyle = true; + scope.lastDrawType = DRAW_TYPE_IMAGE; + } + bindImageStyle(ctx, el, prevEl, forceSetStyle, scope); + brushImage(ctx, el, style); + } + else if (el.getTemporalDisplayables) { + if (scope.lastDrawType !== DRAW_TYPE_INCREMENTAL) { + forceSetStyle = true; + scope.lastDrawType = DRAW_TYPE_INCREMENTAL; + } + brushIncremental(ctx, el, scope); + } + } + if (canBatchPath && isLast) { + flushPathDrawn(ctx, scope); + } + el.innerAfterBrush(); + el.afterBrush && el.afterBrush(); + scope.prevEl = el; + el.__dirty = 0; + el.__isRendered = true; + } + function brushIncremental(ctx, el, scope) { + var displayables = el.getDisplayables(); + var temporalDisplayables = el.getTemporalDisplayables(); + ctx.save(); + var innerScope = { + prevElClipPaths: null, + prevEl: null, + allClipped: false, + viewWidth: scope.viewWidth, + viewHeight: scope.viewHeight, + inHover: scope.inHover + }; + var i; + var len; + for (i = el.getCursor(), len = displayables.length; i < len; i++) { + var displayable = displayables[i]; + displayable.beforeBrush && displayable.beforeBrush(); + displayable.innerBeforeBrush(); + brush(ctx, displayable, innerScope, i === len - 1); + displayable.innerAfterBrush(); + displayable.afterBrush && displayable.afterBrush(); + innerScope.prevEl = displayable; + } + for (var i_1 = 0, len_1 = temporalDisplayables.length; i_1 < len_1; i_1++) { + var displayable = temporalDisplayables[i_1]; + displayable.beforeBrush && displayable.beforeBrush(); + displayable.innerBeforeBrush(); + brush(ctx, displayable, innerScope, i_1 === len_1 - 1); + displayable.innerAfterBrush(); + displayable.afterBrush && displayable.afterBrush(); + innerScope.prevEl = displayable; + } + el.clearTemporalDisplayables(); + el.notClear = true; + ctx.restore(); + } + + var decalMap = new WeakMap(); + var decalCache = new LRU(100); + var decalKeys = ['symbol', 'symbolSize', 'symbolKeepAspect', 'color', 'backgroundColor', 'dashArrayX', 'dashArrayY', 'maxTileWidth', 'maxTileHeight']; + /** + * Create or update pattern image from decal options + * + * @param {InnerDecalObject | 'none'} decalObject decal options, 'none' if no decal + * @return {Pattern} pattern with generated image, null if no decal + */ + + function createOrUpdatePatternFromDecal(decalObject, api) { + if (decalObject === 'none') { + return null; + } + + var dpr = api.getDevicePixelRatio(); + var zr = api.getZr(); + var isSVG = zr.painter.type === 'svg'; + + if (decalObject.dirty) { + decalMap["delete"](decalObject); + } + + var oldPattern = decalMap.get(decalObject); + + if (oldPattern) { + return oldPattern; + } + + var decalOpt = defaults(decalObject, { + symbol: 'rect', + symbolSize: 1, + symbolKeepAspect: true, + color: 'rgba(0, 0, 0, 0.2)', + backgroundColor: null, + dashArrayX: 5, + dashArrayY: 5, + rotation: 0, + maxTileWidth: 512, + maxTileHeight: 512 + }); + + if (decalOpt.backgroundColor === 'none') { + decalOpt.backgroundColor = null; + } + + var pattern = { + repeat: 'repeat' + }; + setPatternnSource(pattern); + pattern.rotation = decalOpt.rotation; + pattern.scaleX = pattern.scaleY = isSVG ? 1 : 1 / dpr; + decalMap.set(decalObject, pattern); + decalObject.dirty = false; + return pattern; + + function setPatternnSource(pattern) { + var keys = [dpr]; + var isValidKey = true; + + for (var i = 0; i < decalKeys.length; ++i) { + var value = decalOpt[decalKeys[i]]; + + if (value != null && !isArray(value) && !isString(value) && !isNumber(value) && typeof value !== 'boolean') { + isValidKey = false; + break; + } + + keys.push(value); + } + + var cacheKey; + + if (isValidKey) { + cacheKey = keys.join(',') + (isSVG ? '-svg' : ''); + var cache = decalCache.get(cacheKey); + + if (cache) { + isSVG ? pattern.svgElement = cache : pattern.image = cache; + } + } + + var dashArrayX = normalizeDashArrayX(decalOpt.dashArrayX); + var dashArrayY = normalizeDashArrayY(decalOpt.dashArrayY); + var symbolArray = normalizeSymbolArray(decalOpt.symbol); + var lineBlockLengthsX = getLineBlockLengthX(dashArrayX); + var lineBlockLengthY = getLineBlockLengthY(dashArrayY); + var canvas = !isSVG && platformApi.createCanvas(); + var svgRoot = isSVG && { + tag: 'g', + attrs: {}, + key: 'dcl', + children: [] + }; + var pSize = getPatternSize(); + var ctx; + + if (canvas) { + canvas.width = pSize.width * dpr; + canvas.height = pSize.height * dpr; + ctx = canvas.getContext('2d'); + } + + brushDecal(); + + if (isValidKey) { + decalCache.put(cacheKey, canvas || svgRoot); + } + + pattern.image = canvas; + pattern.svgElement = svgRoot; + pattern.svgWidth = pSize.width; + pattern.svgHeight = pSize.height; + /** + * Get minumum length that can make a repeatable pattern. + * + * @return {Object} pattern width and height + */ + + function getPatternSize() { + /** + * For example, if dash is [[3, 2], [2, 1]] for X, it looks like + * |--- --- --- --- --- ... + * |-- -- -- -- -- -- -- -- ... + * |--- --- --- --- --- ... + * |-- -- -- -- -- -- -- -- ... + * So the minumum length of X is 15, + * which is the least common multiple of `3 + 2` and `2 + 1` + * |--- --- --- |--- --- ... + * |-- -- -- -- -- |-- -- -- ... + */ + var width = 1; + + for (var i = 0, xlen = lineBlockLengthsX.length; i < xlen; ++i) { + width = getLeastCommonMultiple(width, lineBlockLengthsX[i]); + } + + var symbolRepeats = 1; + + for (var i = 0, xlen = symbolArray.length; i < xlen; ++i) { + symbolRepeats = getLeastCommonMultiple(symbolRepeats, symbolArray[i].length); + } + + width *= symbolRepeats; + var height = lineBlockLengthY * lineBlockLengthsX.length * symbolArray.length; + + if ("development" !== 'production') { + var warn = function (attrName) { + /* eslint-disable-next-line */ + console.warn("Calculated decal size is greater than " + attrName + " due to decal option settings so " + attrName + " is used for the decal size. Please consider changing the decal option to make a smaller decal or set " + attrName + " to be larger to avoid incontinuity."); + }; + + if (width > decalOpt.maxTileWidth) { + warn('maxTileWidth'); + } + + if (height > decalOpt.maxTileHeight) { + warn('maxTileHeight'); + } + } + + return { + width: Math.max(1, Math.min(width, decalOpt.maxTileWidth)), + height: Math.max(1, Math.min(height, decalOpt.maxTileHeight)) + }; + } + + function brushDecal() { + if (ctx) { + ctx.clearRect(0, 0, canvas.width, canvas.height); + + if (decalOpt.backgroundColor) { + ctx.fillStyle = decalOpt.backgroundColor; + ctx.fillRect(0, 0, canvas.width, canvas.height); + } + } + + var ySum = 0; + + for (var i = 0; i < dashArrayY.length; ++i) { + ySum += dashArrayY[i]; + } + + if (ySum <= 0) { + // dashArrayY is 0, draw nothing + return; + } + + var y = -lineBlockLengthY; + var yId = 0; + var yIdTotal = 0; + var xId0 = 0; + + while (y < pSize.height) { + if (yId % 2 === 0) { + var symbolYId = yIdTotal / 2 % symbolArray.length; + var x = 0; + var xId1 = 0; + var xId1Total = 0; + + while (x < pSize.width * 2) { + var xSum = 0; + + for (var i = 0; i < dashArrayX[xId0].length; ++i) { + xSum += dashArrayX[xId0][i]; + } + + if (xSum <= 0) { + // Skip empty line + break; + } // E.g., [15, 5, 20, 5] draws only for 15 and 20 + + + if (xId1 % 2 === 0) { + var size = (1 - decalOpt.symbolSize) * 0.5; + var left = x + dashArrayX[xId0][xId1] * size; + var top_1 = y + dashArrayY[yId] * size; + var width = dashArrayX[xId0][xId1] * decalOpt.symbolSize; + var height = dashArrayY[yId] * decalOpt.symbolSize; + var symbolXId = xId1Total / 2 % symbolArray[symbolYId].length; + brushSymbol(left, top_1, width, height, symbolArray[symbolYId][symbolXId]); + } + + x += dashArrayX[xId0][xId1]; + ++xId1Total; + ++xId1; + + if (xId1 === dashArrayX[xId0].length) { + xId1 = 0; + } + } + + ++xId0; + + if (xId0 === dashArrayX.length) { + xId0 = 0; + } + } + + y += dashArrayY[yId]; + ++yIdTotal; + ++yId; + + if (yId === dashArrayY.length) { + yId = 0; + } + } + + function brushSymbol(x, y, width, height, symbolType) { + var scale = isSVG ? 1 : dpr; + var symbol = createSymbol(symbolType, x * scale, y * scale, width * scale, height * scale, decalOpt.color, decalOpt.symbolKeepAspect); + + if (isSVG) { + var symbolVNode = zr.painter.renderOneToVNode(symbol); + + if (symbolVNode) { + svgRoot.children.push(symbolVNode); + } + } else { + // Paint to canvas for all other renderers. + brushSingle(ctx, symbol); + } + } + } + } + } + /** + * Convert symbol array into normalized array + * + * @param {string | (string | string[])[]} symbol symbol input + * @return {string[][]} normolized symbol array + */ + + function normalizeSymbolArray(symbol) { + if (!symbol || symbol.length === 0) { + return [['rect']]; + } + + if (isString(symbol)) { + return [[symbol]]; + } + + var isAllString = true; + + for (var i = 0; i < symbol.length; ++i) { + if (!isString(symbol[i])) { + isAllString = false; + break; + } + } + + if (isAllString) { + return normalizeSymbolArray([symbol]); + } + + var result = []; + + for (var i = 0; i < symbol.length; ++i) { + if (isString(symbol[i])) { + result.push([symbol[i]]); + } else { + result.push(symbol[i]); + } + } + + return result; + } + /** + * Convert dash input into dashArray + * + * @param {DecalDashArrayX} dash dash input + * @return {number[][]} normolized dash array + */ + + + function normalizeDashArrayX(dash) { + if (!dash || dash.length === 0) { + return [[0, 0]]; + } + + if (isNumber(dash)) { + var dashValue = Math.ceil(dash); + return [[dashValue, dashValue]]; + } + /** + * [20, 5] should be normalized into [[20, 5]], + * while [20, [5, 10]] should be normalized into [[20, 20], [5, 10]] + */ + + + var isAllNumber = true; + + for (var i = 0; i < dash.length; ++i) { + if (!isNumber(dash[i])) { + isAllNumber = false; + break; + } + } + + if (isAllNumber) { + return normalizeDashArrayX([dash]); + } + + var result = []; + + for (var i = 0; i < dash.length; ++i) { + if (isNumber(dash[i])) { + var dashValue = Math.ceil(dash[i]); + result.push([dashValue, dashValue]); + } else { + var dashValue = map(dash[i], function (n) { + return Math.ceil(n); + }); + + if (dashValue.length % 2 === 1) { + // [4, 2, 1] means |---- - -- |---- - -- | + // so normalize it to be [4, 2, 1, 4, 2, 1] + result.push(dashValue.concat(dashValue)); + } else { + result.push(dashValue); + } + } + } + + return result; + } + /** + * Convert dash input into dashArray + * + * @param {DecalDashArrayY} dash dash input + * @return {number[]} normolized dash array + */ + + + function normalizeDashArrayY(dash) { + if (!dash || typeof dash === 'object' && dash.length === 0) { + return [0, 0]; + } + + if (isNumber(dash)) { + var dashValue_1 = Math.ceil(dash); + return [dashValue_1, dashValue_1]; + } + + var dashValue = map(dash, function (n) { + return Math.ceil(n); + }); + return dash.length % 2 ? dashValue.concat(dashValue) : dashValue; + } + /** + * Get block length of each line. A block is the length of dash line and space. + * For example, a line with [4, 1] has a dash line of 4 and a space of 1 after + * that, so the block length of this line is 5. + * + * @param {number[][]} dash dash arrary of X or Y + * @return {number[]} block length of each line + */ + + + function getLineBlockLengthX(dash) { + return map(dash, function (line) { + return getLineBlockLengthY(line); + }); + } + + function getLineBlockLengthY(dash) { + var blockLength = 0; + + for (var i = 0; i < dash.length; ++i) { + blockLength += dash[i]; + } + + if (dash.length % 2 === 1) { + // [4, 2, 1] means |---- - -- |---- - -- | + // So total length is (4 + 2 + 1) * 2 + return blockLength * 2; + } + + return blockLength; + } + + function decalVisual(ecModel, api) { + ecModel.eachRawSeries(function (seriesModel) { + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var data = seriesModel.getData(); + + if (data.hasItemVisual()) { + data.each(function (idx) { + var decal = data.getItemVisual(idx, 'decal'); + + if (decal) { + var itemStyle = data.ensureUniqueItemVisual(idx, 'style'); + itemStyle.decal = createOrUpdatePatternFromDecal(decal, api); + } + }); + } + + var decal = data.getVisual('decal'); + + if (decal) { + var style = data.getVisual('style'); + style.decal = createOrUpdatePatternFromDecal(decal, api); + } + }); + } + + var lifecycle = new Eventful(); + + // The implentations will be registered when installing the component. + // Avoid these code being bundled to the core module. + + var implsStore = {}; // TODO Type + + function registerImpl(name, impl) { + if ("development" !== 'production') { + if (implsStore[name]) { + error("Already has an implementation of " + name + "."); + } + } + + implsStore[name] = impl; + } + function getImpl(name) { + if ("development" !== 'production') { + if (!implsStore[name]) { + error("Implementation of " + name + " doesn't exists."); + } + } + + return implsStore[name]; + } + + var hasWindow = typeof window !== 'undefined'; + var version$1 = '5.3.2'; + var dependencies = { + zrender: '5.3.1' + }; + var TEST_FRAME_REMAIN_TIME = 1; + var PRIORITY_PROCESSOR_SERIES_FILTER = 800; // Some data processors depends on the stack result dimension (to calculate data extent). + // So data stack stage should be in front of data processing stage. + + var PRIORITY_PROCESSOR_DATASTACK = 900; // "Data filter" will block the stream, so it should be + // put at the begining of data processing. + + var PRIORITY_PROCESSOR_FILTER = 1000; + var PRIORITY_PROCESSOR_DEFAULT = 2000; + var PRIORITY_PROCESSOR_STATISTIC = 5000; + var PRIORITY_VISUAL_LAYOUT = 1000; + var PRIORITY_VISUAL_PROGRESSIVE_LAYOUT = 1100; + var PRIORITY_VISUAL_GLOBAL = 2000; + var PRIORITY_VISUAL_CHART = 3000; + var PRIORITY_VISUAL_COMPONENT = 4000; // Visual property in data. Greater than `PRIORITY_VISUAL_COMPONENT` to enable to + // overwrite the viusal result of component (like `visualMap`) + // using data item specific setting (like itemStyle.xxx on data item) + + var PRIORITY_VISUAL_CHART_DATA_CUSTOM = 4500; // Greater than `PRIORITY_VISUAL_CHART_DATA_CUSTOM` to enable to layout based on + // visual result like `symbolSize`. + + var PRIORITY_VISUAL_POST_CHART_LAYOUT = 4600; + var PRIORITY_VISUAL_BRUSH = 5000; + var PRIORITY_VISUAL_ARIA = 6000; + var PRIORITY_VISUAL_DECAL = 7000; + var PRIORITY = { + PROCESSOR: { + FILTER: PRIORITY_PROCESSOR_FILTER, + SERIES_FILTER: PRIORITY_PROCESSOR_SERIES_FILTER, + STATISTIC: PRIORITY_PROCESSOR_STATISTIC + }, + VISUAL: { + LAYOUT: PRIORITY_VISUAL_LAYOUT, + PROGRESSIVE_LAYOUT: PRIORITY_VISUAL_PROGRESSIVE_LAYOUT, + GLOBAL: PRIORITY_VISUAL_GLOBAL, + CHART: PRIORITY_VISUAL_CHART, + POST_CHART_LAYOUT: PRIORITY_VISUAL_POST_CHART_LAYOUT, + COMPONENT: PRIORITY_VISUAL_COMPONENT, + BRUSH: PRIORITY_VISUAL_BRUSH, + CHART_ITEM: PRIORITY_VISUAL_CHART_DATA_CUSTOM, + ARIA: PRIORITY_VISUAL_ARIA, + DECAL: PRIORITY_VISUAL_DECAL + } + }; // Main process have three entries: `setOption`, `dispatchAction` and `resize`, + // where they must not be invoked nestedly, except the only case: invoke + // dispatchAction with updateMethod "none" in main process. + // This flag is used to carry out this rule. + // All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]). + + var IN_MAIN_PROCESS_KEY = '__flagInMainProcess'; + var PENDING_UPDATE = '__pendingUpdate'; + var STATUS_NEEDS_UPDATE_KEY = '__needsUpdateStatus'; + var ACTION_REG = /^[a-zA-Z0-9_]+$/; + var CONNECT_STATUS_KEY = '__connectUpdateStatus'; + var CONNECT_STATUS_PENDING = 0; + var CONNECT_STATUS_UPDATING = 1; + var CONNECT_STATUS_UPDATED = 2; + + function createRegisterEventWithLowercaseECharts(method) { + return function () { + var args = []; + + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + + if (this.isDisposed()) { + disposedWarning(this.id); + return; + } + + return toLowercaseNameAndCallEventful(this, method, args); + }; + } + + function createRegisterEventWithLowercaseMessageCenter(method) { + return function () { + var args = []; + + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + + return toLowercaseNameAndCallEventful(this, method, args); + }; + } + + function toLowercaseNameAndCallEventful(host, method, args) { + // `args[0]` is event name. Event name is all lowercase. + args[0] = args[0] && args[0].toLowerCase(); + return Eventful.prototype[method].apply(host, args); + } + + var MessageCenter = + /** @class */ + function (_super) { + __extends(MessageCenter, _super); + + function MessageCenter() { + return _super !== null && _super.apply(this, arguments) || this; + } + + return MessageCenter; + }(Eventful); + + var messageCenterProto = MessageCenter.prototype; + messageCenterProto.on = createRegisterEventWithLowercaseMessageCenter('on'); + messageCenterProto.off = createRegisterEventWithLowercaseMessageCenter('off'); // --------------------------------------- + // Internal method names for class ECharts + // --------------------------------------- + + var prepare; + var prepareView; + var updateDirectly; + var updateMethods; + var doConvertPixel; + var updateStreamModes; + var doDispatchAction; + var flushPendingActions; + var triggerUpdatedEvent; + var bindRenderedEvent; + var bindMouseEvent; + var render; + var renderComponents; + var renderSeries; + var createExtensionAPI; + var enableConnect; + var markStatusToUpdate; + var applyChangedStates; + + var ECharts = + /** @class */ + function (_super) { + __extends(ECharts, _super); + + function ECharts(dom, // Theme name or themeOption. + theme, opts) { + var _this = _super.call(this, new ECEventProcessor()) || this; + + _this._chartsViews = []; + _this._chartsMap = {}; + _this._componentsViews = []; + _this._componentsMap = {}; // Can't dispatch action during rendering procedure + + _this._pendingActions = []; + opts = opts || {}; // Get theme by name + + if (isString(theme)) { + theme = themeStorage[theme]; + } + + _this._dom = dom; + var defaultRenderer = 'canvas'; + var defaultUseDirtyRect = false; + + if ("development" !== 'production') { + var root = + /* eslint-disable-next-line */ + hasWindow ? window : global; + defaultRenderer = root.__ECHARTS__DEFAULT__RENDERER__ || defaultRenderer; + var devUseDirtyRect = root.__ECHARTS__DEFAULT__USE_DIRTY_RECT__; + defaultUseDirtyRect = devUseDirtyRect == null ? defaultUseDirtyRect : devUseDirtyRect; + } + + var zr = _this._zr = init(dom, { + renderer: opts.renderer || defaultRenderer, + devicePixelRatio: opts.devicePixelRatio, + width: opts.width, + height: opts.height, + ssr: opts.ssr, + useDirtyRect: opts.useDirtyRect == null ? defaultUseDirtyRect : opts.useDirtyRect + }); + _this._ssr = opts.ssr; // Expect 60 fps. + + _this._throttledZrFlush = throttle(bind(zr.flush, zr), 17); + theme = clone(theme); + theme && globalBackwardCompat(theme, true); + _this._theme = theme; + _this._locale = createLocaleObject(opts.locale || SYSTEM_LANG); + _this._coordSysMgr = new CoordinateSystemManager(); + var api = _this._api = createExtensionAPI(_this); // Sort on demand + + function prioritySortFunc(a, b) { + return a.__prio - b.__prio; + } + + sort(visualFuncs, prioritySortFunc); + sort(dataProcessorFuncs, prioritySortFunc); + _this._scheduler = new Scheduler(_this, api, dataProcessorFuncs, visualFuncs); + _this._messageCenter = new MessageCenter(); // Init mouse events + + _this._initEvents(); // In case some people write `window.onresize = chart.resize` + + + _this.resize = bind(_this.resize, _this); + zr.animation.on('frame', _this._onframe, _this); + bindRenderedEvent(zr, _this); + bindMouseEvent(zr, _this); // ECharts instance can be used as value. + + setAsPrimitive(_this); + return _this; + } + + ECharts.prototype._onframe = function () { + if (this._disposed) { + return; + } + + applyChangedStates(this); + var scheduler = this._scheduler; // Lazy update + + if (this[PENDING_UPDATE]) { + var silent = this[PENDING_UPDATE].silent; + this[IN_MAIN_PROCESS_KEY] = true; + + try { + prepare(this); + updateMethods.update.call(this, null, this[PENDING_UPDATE].updateParams); + } catch (e) { + this[IN_MAIN_PROCESS_KEY] = false; + this[PENDING_UPDATE] = null; + throw e; + } // At present, in each frame, zrender performs: + // (1) animation step forward. + // (2) trigger('frame') (where this `_onframe` is called) + // (3) zrender flush (render). + // If we do nothing here, since we use `setToFinal: true`, the step (3) above + // will render the final state of the elements before the real animation started. + + + this._zr.flush(); + + this[IN_MAIN_PROCESS_KEY] = false; + this[PENDING_UPDATE] = null; + flushPendingActions.call(this, silent); + triggerUpdatedEvent.call(this, silent); + } // Avoid do both lazy update and progress in one frame. + else if (scheduler.unfinished) { + // Stream progress. + var remainTime = TEST_FRAME_REMAIN_TIME; + var ecModel = this._model; + var api = this._api; + scheduler.unfinished = false; + + do { + var startTime = +new Date(); + scheduler.performSeriesTasks(ecModel); // Currently dataProcessorFuncs do not check threshold. + + scheduler.performDataProcessorTasks(ecModel); + updateStreamModes(this, ecModel); // Do not update coordinate system here. Because that coord system update in + // each frame is not a good user experience. So we follow the rule that + // the extent of the coordinate system is determin in the first frame (the + // frame is executed immedietely after task reset. + // this._coordSysMgr.update(ecModel, api); + // console.log('--- ec frame visual ---', remainTime); + + scheduler.performVisualTasks(ecModel); + renderSeries(this, this._model, api, 'remain', {}); + remainTime -= +new Date() - startTime; + } while (remainTime > 0 && scheduler.unfinished); // Call flush explicitly for trigger finished event. + + + if (!scheduler.unfinished) { + this._zr.flush(); + } // Else, zr flushing be ensue within the same frame, + // because zr flushing is after onframe event. + + } + }; + + ECharts.prototype.getDom = function () { + return this._dom; + }; + + ECharts.prototype.getId = function () { + return this.id; + }; + + ECharts.prototype.getZr = function () { + return this._zr; + }; + + ECharts.prototype.isSSR = function () { + return this._ssr; + }; + /* eslint-disable-next-line */ + + + ECharts.prototype.setOption = function (option, notMerge, lazyUpdate) { + if (this[IN_MAIN_PROCESS_KEY]) { + if ("development" !== 'production') { + error('`setOption` should not be called during main process.'); + } + + return; + } + + if (this._disposed) { + disposedWarning(this.id); + return; + } + + var silent; + var replaceMerge; + var transitionOpt; + + if (isObject(notMerge)) { + lazyUpdate = notMerge.lazyUpdate; + silent = notMerge.silent; + replaceMerge = notMerge.replaceMerge; + transitionOpt = notMerge.transition; + notMerge = notMerge.notMerge; + } + + this[IN_MAIN_PROCESS_KEY] = true; + + if (!this._model || notMerge) { + var optionManager = new OptionManager(this._api); + var theme = this._theme; + var ecModel = this._model = new GlobalModel(); + ecModel.scheduler = this._scheduler; + ecModel.ssr = this._ssr; + ecModel.init(null, null, null, theme, this._locale, optionManager); + } + + this._model.setOption(option, { + replaceMerge: replaceMerge + }, optionPreprocessorFuncs); + + var updateParams = { + seriesTransition: transitionOpt, + optionChanged: true + }; + + if (lazyUpdate) { + this[PENDING_UPDATE] = { + silent: silent, + updateParams: updateParams + }; + this[IN_MAIN_PROCESS_KEY] = false; // `setOption(option, {lazyMode: true})` may be called when zrender has been slept. + // It should wake it up to make sure zrender start to render at the next frame. + + this.getZr().wakeUp(); + } else { + try { + prepare(this); + updateMethods.update.call(this, null, updateParams); + } catch (e) { + this[PENDING_UPDATE] = null; + this[IN_MAIN_PROCESS_KEY] = false; + throw e; + } // Ensure zr refresh sychronously, and then pixel in canvas can be + // fetched after `setOption`. + + + if (!this._ssr) { + // not use flush when using ssr mode. + this._zr.flush(); + } + + this[PENDING_UPDATE] = null; + this[IN_MAIN_PROCESS_KEY] = false; + flushPendingActions.call(this, silent); + triggerUpdatedEvent.call(this, silent); + } + }; + /** + * @deprecated + */ + + + ECharts.prototype.setTheme = function () { + deprecateLog('ECharts#setTheme() is DEPRECATED in ECharts 3.0'); + }; // We don't want developers to use getModel directly. + + + ECharts.prototype.getModel = function () { + return this._model; + }; + + ECharts.prototype.getOption = function () { + return this._model && this._model.getOption(); + }; + + ECharts.prototype.getWidth = function () { + return this._zr.getWidth(); + }; + + ECharts.prototype.getHeight = function () { + return this._zr.getHeight(); + }; + + ECharts.prototype.getDevicePixelRatio = function () { + return this._zr.painter.dpr + /* eslint-disable-next-line */ + || hasWindow && window.devicePixelRatio || 1; + }; + /** + * Get canvas which has all thing rendered + * @deprecated Use renderToCanvas instead. + */ + + + ECharts.prototype.getRenderedCanvas = function (opts) { + if ("development" !== 'production') { + deprecateReplaceLog('getRenderedCanvas', 'renderToCanvas'); + } + + return this.renderToCanvas(opts); + }; + + ECharts.prototype.renderToCanvas = function (opts) { + opts = opts || {}; + var painter = this._zr.painter; + + if ("development" !== 'production') { + if (painter.type !== 'canvas') { + throw new Error('renderToCanvas can only be used in the canvas renderer.'); + } + } + + return painter.getRenderedCanvas({ + backgroundColor: opts.backgroundColor || this._model.get('backgroundColor'), + pixelRatio: opts.pixelRatio || this.getDevicePixelRatio() + }); + }; + + ECharts.prototype.renderToSVGString = function (opts) { + opts = opts || {}; + var painter = this._zr.painter; + + if ("development" !== 'production') { + if (painter.type !== 'svg') { + throw new Error('renderToSVGString can only be used in the svg renderer.'); + } + } + + return painter.renderToString({ + useViewBox: opts.useViewBox + }); + }; + /** + * Get svg data url + */ + + + ECharts.prototype.getSvgDataURL = function () { + if (!env.svgSupported) { + return; + } + + var zr = this._zr; + var list = zr.storage.getDisplayList(); // Stop animations + + each(list, function (el) { + el.stopAnimation(null, true); + }); + return zr.painter.toDataURL(); + }; + + ECharts.prototype.getDataURL = function (opts) { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + opts = opts || {}; + var excludeComponents = opts.excludeComponents; + var ecModel = this._model; + var excludesComponentViews = []; + var self = this; + each(excludeComponents, function (componentType) { + ecModel.eachComponent({ + mainType: componentType + }, function (component) { + var view = self._componentsMap[component.__viewId]; + + if (!view.group.ignore) { + excludesComponentViews.push(view); + view.group.ignore = true; + } + }); + }); + var url = this._zr.painter.getType() === 'svg' ? this.getSvgDataURL() : this.renderToCanvas(opts).toDataURL('image/' + (opts && opts.type || 'png')); + each(excludesComponentViews, function (view) { + view.group.ignore = false; + }); + return url; + }; + + ECharts.prototype.getConnectedDataURL = function (opts) { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + var isSvg = opts.type === 'svg'; + var groupId = this.group; + var mathMin = Math.min; + var mathMax = Math.max; + var MAX_NUMBER = Infinity; + + if (connectedGroups[groupId]) { + var left_1 = MAX_NUMBER; + var top_1 = MAX_NUMBER; + var right_1 = -MAX_NUMBER; + var bottom_1 = -MAX_NUMBER; + var canvasList_1 = []; + var dpr_1 = opts && opts.pixelRatio || this.getDevicePixelRatio(); + each(instances$1, function (chart, id) { + if (chart.group === groupId) { + var canvas = isSvg ? chart.getZr().painter.getSvgDom().innerHTML : chart.renderToCanvas(clone(opts)); + var boundingRect = chart.getDom().getBoundingClientRect(); + left_1 = mathMin(boundingRect.left, left_1); + top_1 = mathMin(boundingRect.top, top_1); + right_1 = mathMax(boundingRect.right, right_1); + bottom_1 = mathMax(boundingRect.bottom, bottom_1); + canvasList_1.push({ + dom: canvas, + left: boundingRect.left, + top: boundingRect.top + }); + } + }); + left_1 *= dpr_1; + top_1 *= dpr_1; + right_1 *= dpr_1; + bottom_1 *= dpr_1; + var width = right_1 - left_1; + var height = bottom_1 - top_1; + var targetCanvas = platformApi.createCanvas(); + var zr_1 = init(targetCanvas, { + renderer: isSvg ? 'svg' : 'canvas' + }); + zr_1.resize({ + width: width, + height: height + }); + + if (isSvg) { + var content_1 = ''; + each(canvasList_1, function (item) { + var x = item.left - left_1; + var y = item.top - top_1; + content_1 += '' + item.dom + ''; + }); + zr_1.painter.getSvgRoot().innerHTML = content_1; + + if (opts.connectedBackgroundColor) { + zr_1.painter.setBackgroundColor(opts.connectedBackgroundColor); + } + + zr_1.refreshImmediately(); + return zr_1.painter.toDataURL(); + } else { + // Background between the charts + if (opts.connectedBackgroundColor) { + zr_1.add(new Rect({ + shape: { + x: 0, + y: 0, + width: width, + height: height + }, + style: { + fill: opts.connectedBackgroundColor + } + })); + } + + each(canvasList_1, function (item) { + var img = new ZRImage({ + style: { + x: item.left * dpr_1 - left_1, + y: item.top * dpr_1 - top_1, + image: item.dom + } + }); + zr_1.add(img); + }); + zr_1.refreshImmediately(); + return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png')); + } + } else { + return this.getDataURL(opts); + } + }; + + ECharts.prototype.convertToPixel = function (finder, value) { + return doConvertPixel(this, 'convertToPixel', finder, value); + }; + + ECharts.prototype.convertFromPixel = function (finder, value) { + return doConvertPixel(this, 'convertFromPixel', finder, value); + }; + /** + * Is the specified coordinate systems or components contain the given pixel point. + * @param {Array|number} value + * @return {boolean} result + */ + + + ECharts.prototype.containPixel = function (finder, value) { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + var ecModel = this._model; + var result; + var findResult = parseFinder(ecModel, finder); + each(findResult, function (models, key) { + key.indexOf('Models') >= 0 && each(models, function (model) { + var coordSys = model.coordinateSystem; + + if (coordSys && coordSys.containPoint) { + result = result || !!coordSys.containPoint(value); + } else if (key === 'seriesModels') { + var view = this._chartsMap[model.__viewId]; + + if (view && view.containPoint) { + result = result || view.containPoint(value, model); + } else { + if ("development" !== 'production') { + console.warn(key + ': ' + (view ? 'The found component do not support containPoint.' : 'No view mapping to the found component.')); + } + } + } else { + if ("development" !== 'production') { + console.warn(key + ': containPoint is not supported'); + } + } + }, this); + }, this); + return !!result; + }; + /** + * Get visual from series or data. + * @param finder + * If string, e.g., 'series', means {seriesIndex: 0}. + * If Object, could contain some of these properties below: + * { + * seriesIndex / seriesId / seriesName, + * dataIndex / dataIndexInside + * } + * If dataIndex is not specified, series visual will be fetched, + * but not data item visual. + * If all of seriesIndex, seriesId, seriesName are not specified, + * visual will be fetched from first series. + * @param visualType 'color', 'symbol', 'symbolSize' + */ + + + ECharts.prototype.getVisual = function (finder, visualType) { + var ecModel = this._model; + var parsedFinder = parseFinder(ecModel, finder, { + defaultMainType: 'series' + }); + var seriesModel = parsedFinder.seriesModel; + + if ("development" !== 'production') { + if (!seriesModel) { + console.warn('There is no specified seires model'); + } + } + + var data = seriesModel.getData(); + var dataIndexInside = parsedFinder.hasOwnProperty('dataIndexInside') ? parsedFinder.dataIndexInside : parsedFinder.hasOwnProperty('dataIndex') ? data.indexOfRawIndex(parsedFinder.dataIndex) : null; + return dataIndexInside != null ? getItemVisualFromData(data, dataIndexInside, visualType) : getVisualFromData(data, visualType); + }; + /** + * Get view of corresponding component model + */ + + + ECharts.prototype.getViewOfComponentModel = function (componentModel) { + return this._componentsMap[componentModel.__viewId]; + }; + /** + * Get view of corresponding series model + */ + + + ECharts.prototype.getViewOfSeriesModel = function (seriesModel) { + return this._chartsMap[seriesModel.__viewId]; + }; + + ECharts.prototype._initEvents = function () { + var _this = this; + + each(MOUSE_EVENT_NAMES, function (eveName) { + var handler = function (e) { + var ecModel = _this.getModel(); + + var el = e.target; + var params; + var isGlobalOut = eveName === 'globalout'; // no e.target when 'globalout'. + + if (isGlobalOut) { + params = {}; + } else { + el && findEventDispatcher(el, function (parent) { + var ecData = getECData(parent); + + if (ecData && ecData.dataIndex != null) { + var dataModel = ecData.dataModel || ecModel.getSeriesByIndex(ecData.seriesIndex); + params = dataModel && dataModel.getDataParams(ecData.dataIndex, ecData.dataType) || {}; + return true; + } // If element has custom eventData of components + else if (ecData.eventData) { + params = extend({}, ecData.eventData); + return true; + } + }, true); + } // Contract: if params prepared in mouse event, + // these properties must be specified: + // { + // componentType: string (component main type) + // componentIndex: number + // } + // Otherwise event query can not work. + + + if (params) { + var componentType = params.componentType; + var componentIndex = params.componentIndex; // Special handling for historic reason: when trigger by + // markLine/markPoint/markArea, the componentType is + // 'markLine'/'markPoint'/'markArea', but we should better + // enable them to be queried by seriesIndex, since their + // option is set in each series. + + if (componentType === 'markLine' || componentType === 'markPoint' || componentType === 'markArea') { + componentType = 'series'; + componentIndex = params.seriesIndex; + } + + var model = componentType && componentIndex != null && ecModel.getComponent(componentType, componentIndex); + var view = model && _this[model.mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId]; + + if ("development" !== 'production') { + // `event.componentType` and `event[componentTpype + 'Index']` must not + // be missed, otherwise there is no way to distinguish source component. + // See `dataFormat.getDataParams`. + if (!isGlobalOut && !(model && view)) { + console.warn('model or view can not be found by params'); + } + } + + params.event = e; + params.type = eveName; + _this._$eventProcessor.eventInfo = { + targetEl: el, + packedEvent: params, + model: model, + view: view + }; + + _this.trigger(eveName, params); + } + }; // Consider that some component (like tooltip, brush, ...) + // register zr event handler, but user event handler might + // do anything, such as call `setOption` or `dispatchAction`, + // which probably update any of the content and probably + // cause problem if it is called previous other inner handlers. + + + handler.zrEventfulCallAtLast = true; + + _this._zr.on(eveName, handler, _this); + }); + each(eventActionMap, function (actionType, eventType) { + _this._messageCenter.on(eventType, function (event) { + this.trigger(eventType, event); + }, _this); + }); // Extra events + // TODO register? + + each(['selectchanged'], function (eventType) { + _this._messageCenter.on(eventType, function (event) { + this.trigger(eventType, event); + }, _this); + }); + handleLegacySelectEvents(this._messageCenter, this, this._api); + }; + + ECharts.prototype.isDisposed = function () { + return this._disposed; + }; + + ECharts.prototype.clear = function () { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + this.setOption({ + series: [] + }, true); + }; + + ECharts.prototype.dispose = function () { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + this._disposed = true; + var dom = this.getDom(); + + if (dom) { + setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, ''); + } + + var chart = this; + var api = chart._api; + var ecModel = chart._model; + each(chart._componentsViews, function (component) { + component.dispose(ecModel, api); + }); + each(chart._chartsViews, function (chart) { + chart.dispose(ecModel, api); + }); // Dispose after all views disposed + + chart._zr.dispose(); // Set properties to null. + // To reduce the memory cost in case the top code still holds this instance unexpectedly. + + + chart._dom = chart._model = chart._chartsMap = chart._componentsMap = chart._chartsViews = chart._componentsViews = chart._scheduler = chart._api = chart._zr = chart._throttledZrFlush = chart._theme = chart._coordSysMgr = chart._messageCenter = null; + delete instances$1[chart.id]; + }; + /** + * Resize the chart + */ + + + ECharts.prototype.resize = function (opts) { + if (this[IN_MAIN_PROCESS_KEY]) { + if ("development" !== 'production') { + error('`resize` should not be called during main process.'); + } + + return; + } + + if (this._disposed) { + disposedWarning(this.id); + return; + } + + this._zr.resize(opts); + + var ecModel = this._model; // Resize loading effect + + this._loadingFX && this._loadingFX.resize(); + + if (!ecModel) { + return; + } + + var needPrepare = ecModel.resetOption('media'); + var silent = opts && opts.silent; // There is some real cases that: + // chart.setOption(option, { lazyUpdate: true }); + // chart.resize(); + + if (this[PENDING_UPDATE]) { + if (silent == null) { + silent = this[PENDING_UPDATE].silent; + } + + needPrepare = true; + this[PENDING_UPDATE] = null; + } + + this[IN_MAIN_PROCESS_KEY] = true; + + try { + needPrepare && prepare(this); + updateMethods.update.call(this, { + type: 'resize', + animation: extend({ + // Disable animation + duration: 0 + }, opts && opts.animation) + }); + } catch (e) { + this[IN_MAIN_PROCESS_KEY] = false; + throw e; + } + + this[IN_MAIN_PROCESS_KEY] = false; + flushPendingActions.call(this, silent); + triggerUpdatedEvent.call(this, silent); + }; + + ECharts.prototype.showLoading = function (name, cfg) { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + if (isObject(name)) { + cfg = name; + name = ''; + } + + name = name || 'default'; + this.hideLoading(); + + if (!loadingEffects[name]) { + if ("development" !== 'production') { + console.warn('Loading effects ' + name + ' not exists.'); + } + + return; + } + + var el = loadingEffects[name](this._api, cfg); + var zr = this._zr; + this._loadingFX = el; + zr.add(el); + }; + /** + * Hide loading effect + */ + + + ECharts.prototype.hideLoading = function () { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + this._loadingFX && this._zr.remove(this._loadingFX); + this._loadingFX = null; + }; + + ECharts.prototype.makeActionFromEvent = function (eventObj) { + var payload = extend({}, eventObj); + payload.type = eventActionMap[eventObj.type]; + return payload; + }; + /** + * @param opt If pass boolean, means opt.silent + * @param opt.silent Default `false`. Whether trigger events. + * @param opt.flush Default `undefined`. + * true: Flush immediately, and then pixel in canvas can be fetched + * immediately. Caution: it might affect performance. + * false: Not flush. + * undefined: Auto decide whether perform flush. + */ + + + ECharts.prototype.dispatchAction = function (payload, opt) { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + if (!isObject(opt)) { + opt = { + silent: !!opt + }; + } + + if (!actions[payload.type]) { + return; + } // Avoid dispatch action before setOption. Especially in `connect`. + + + if (!this._model) { + return; + } // May dispatchAction in rendering procedure + + + if (this[IN_MAIN_PROCESS_KEY]) { + this._pendingActions.push(payload); + + return; + } + + var silent = opt.silent; + doDispatchAction.call(this, payload, silent); + var flush = opt.flush; + + if (flush) { + this._zr.flush(); + } else if (flush !== false && env.browser.weChat) { + // In WeChat embeded browser, `requestAnimationFrame` and `setInterval` + // hang when sliding page (on touch event), which cause that zr does not + // refresh util user interaction finished, which is not expected. + // But `dispatchAction` may be called too frequently when pan on touch + // screen, which impacts performance if do not throttle them. + this._throttledZrFlush(); + } + + flushPendingActions.call(this, silent); + triggerUpdatedEvent.call(this, silent); + }; + + ECharts.prototype.updateLabelLayout = function () { + lifecycle.trigger('series:layoutlabels', this._model, this._api, { + // Not adding series labels. + // TODO + updatedSeries: [] + }); + }; + + ECharts.prototype.appendData = function (params) { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + var seriesIndex = params.seriesIndex; + var ecModel = this.getModel(); + var seriesModel = ecModel.getSeriesByIndex(seriesIndex); + + if ("development" !== 'production') { + assert(params.data && seriesModel); + } + + seriesModel.appendData(params); // Note: `appendData` does not support that update extent of coordinate + // system, util some scenario require that. In the expected usage of + // `appendData`, the initial extent of coordinate system should better + // be fixed by axis `min`/`max` setting or initial data, otherwise if + // the extent changed while `appendData`, the location of the painted + // graphic elements have to be changed, which make the usage of + // `appendData` meaningless. + + this._scheduler.unfinished = true; + this.getZr().wakeUp(); + }; // A work around for no `internal` modifier in ts yet but + // need to strictly hide private methods to JS users. + + + ECharts.internalField = function () { + prepare = function (ecIns) { + var scheduler = ecIns._scheduler; + scheduler.restorePipelines(ecIns._model); + scheduler.prepareStageTasks(); + prepareView(ecIns, true); + prepareView(ecIns, false); + scheduler.plan(); + }; + /** + * Prepare view instances of charts and components + */ + + + prepareView = function (ecIns, isComponent) { + var ecModel = ecIns._model; + var scheduler = ecIns._scheduler; + var viewList = isComponent ? ecIns._componentsViews : ecIns._chartsViews; + var viewMap = isComponent ? ecIns._componentsMap : ecIns._chartsMap; + var zr = ecIns._zr; + var api = ecIns._api; + + for (var i = 0; i < viewList.length; i++) { + viewList[i].__alive = false; + } + + isComponent ? ecModel.eachComponent(function (componentType, model) { + componentType !== 'series' && doPrepare(model); + }) : ecModel.eachSeries(doPrepare); + + function doPrepare(model) { + // By defaut view will be reused if possible for the case that `setOption` with "notMerge" + // mode and need to enable transition animation. (Usually, when they have the same id, or + // especially no id but have the same type & name & index. See the `model.id` generation + // rule in `makeIdAndName` and `viewId` generation rule here). + // But in `replaceMerge` mode, this feature should be able to disabled when it is clear that + // the new model has nothing to do with the old model. + var requireNewView = model.__requireNewView; // This command should not work twice. + + model.__requireNewView = false; // Consider: id same and type changed. + + var viewId = '_ec_' + model.id + '_' + model.type; + var view = !requireNewView && viewMap[viewId]; + + if (!view) { + var classType = parseClassType(model.type); + var Clazz = isComponent ? ComponentView.getClass(classType.main, classType.sub) : // FIXME:TS + // (ChartView as ChartViewConstructor).getClass('series', classType.sub) + // For backward compat, still support a chart type declared as only subType + // like "liquidfill", but recommend "series.liquidfill" + // But need a base class to make a type series. + ChartView.getClass(classType.sub); + + if ("development" !== 'production') { + assert(Clazz, classType.sub + ' does not exist.'); + } + + view = new Clazz(); + view.init(ecModel, api); + viewMap[viewId] = view; + viewList.push(view); + zr.add(view.group); + } + + model.__viewId = view.__id = viewId; + view.__alive = true; + view.__model = model; + view.group.__ecComponentInfo = { + mainType: model.mainType, + index: model.componentIndex + }; + !isComponent && scheduler.prepareView(view, model, ecModel, api); + } + + for (var i = 0; i < viewList.length;) { + var view = viewList[i]; + + if (!view.__alive) { + !isComponent && view.renderTask.dispose(); + zr.remove(view.group); + view.dispose(ecModel, api); + viewList.splice(i, 1); + + if (viewMap[view.__id] === view) { + delete viewMap[view.__id]; + } + + view.__id = view.group.__ecComponentInfo = null; + } else { + i++; + } + } + }; + + updateDirectly = function (ecIns, method, payload, mainType, subType) { + var ecModel = ecIns._model; + ecModel.setUpdatePayload(payload); // broadcast + + if (!mainType) { + // FIXME + // Chart will not be update directly here, except set dirty. + // But there is no such scenario now. + each([].concat(ecIns._componentsViews).concat(ecIns._chartsViews), callView); + return; + } + + var query = {}; + query[mainType + 'Id'] = payload[mainType + 'Id']; + query[mainType + 'Index'] = payload[mainType + 'Index']; + query[mainType + 'Name'] = payload[mainType + 'Name']; + var condition = { + mainType: mainType, + query: query + }; + subType && (condition.subType = subType); // subType may be '' by parseClassType; + + var excludeSeriesId = payload.excludeSeriesId; + var excludeSeriesIdMap; + + if (excludeSeriesId != null) { + excludeSeriesIdMap = createHashMap(); + each(normalizeToArray(excludeSeriesId), function (id) { + var modelId = convertOptionIdName(id, null); + + if (modelId != null) { + excludeSeriesIdMap.set(modelId, true); + } + }); + } // If dispatchAction before setOption, do nothing. + + + ecModel && ecModel.eachComponent(condition, function (model) { + var isExcluded = excludeSeriesIdMap && excludeSeriesIdMap.get(model.id) !== null; + + if (isExcluded) { + return; + } + + if (isHighDownPayload(payload)) { + if (model instanceof SeriesModel) { + if (payload.type === HIGHLIGHT_ACTION_TYPE && !payload.notBlur && !model.get(['emphasis', 'disabled'])) { + blurSeriesFromHighlightPayload(model, payload, ecIns._api); + } + } else { + var _a = findComponentHighDownDispatchers(model.mainType, model.componentIndex, payload.name, ecIns._api), + focusSelf = _a.focusSelf, + dispatchers = _a.dispatchers; + + if (payload.type === HIGHLIGHT_ACTION_TYPE && focusSelf && !payload.notBlur) { + blurComponent(model.mainType, model.componentIndex, ecIns._api); + } // PENDING: + // Whether to put this "enter emphasis" code in `ComponentView`, + // which will be the same as `ChartView` but might be not necessary + // and will be far from this logic. + + + if (dispatchers) { + each(dispatchers, function (dispatcher) { + payload.type === HIGHLIGHT_ACTION_TYPE ? enterEmphasis(dispatcher) : leaveEmphasis(dispatcher); + }); + } + } + } else if (isSelectChangePayload(payload)) { + // TODO geo + if (model instanceof SeriesModel) { + toggleSelectionFromPayload(model, payload, ecIns._api); + updateSeriesElementSelection(model); + markStatusToUpdate(ecIns); + } + } + }, ecIns); + ecModel && ecModel.eachComponent(condition, function (model) { + var isExcluded = excludeSeriesIdMap && excludeSeriesIdMap.get(model.id) !== null; + + if (isExcluded) { + return; + } + callView(ecIns[mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId]); + }, ecIns); + + function callView(view) { + view && view.__alive && view[method] && view[method](view.__model, ecModel, ecIns._api, payload); + } + }; + + updateMethods = { + prepareAndUpdate: function (payload) { + prepare(this); + updateMethods.update.call(this, payload, { + // Needs to mark option changed if newOption is given. + // It's from MagicType. + // TODO If use a separate flag optionChanged in payload? + optionChanged: payload.newOption != null + }); + }, + update: function (payload, updateParams) { + var ecModel = this._model; + var api = this._api; + var zr = this._zr; + var coordSysMgr = this._coordSysMgr; + var scheduler = this._scheduler; // update before setOption + + if (!ecModel) { + return; + } + + ecModel.setUpdatePayload(payload); + scheduler.restoreData(ecModel, payload); + scheduler.performSeriesTasks(ecModel); // TODO + // Save total ecModel here for undo/redo (after restoring data and before processing data). + // Undo (restoration of total ecModel) can be carried out in 'action' or outside API call. + // Create new coordinate system each update + // In LineView may save the old coordinate system and use it to get the orignal point + + coordSysMgr.create(ecModel, api); + scheduler.performDataProcessorTasks(ecModel, payload); // Current stream render is not supported in data process. So we can update + // stream modes after data processing, where the filtered data is used to + // deteming whether use progressive rendering. + + updateStreamModes(this, ecModel); // We update stream modes before coordinate system updated, then the modes info + // can be fetched when coord sys updating (consider the barGrid extent fix). But + // the drawback is the full coord info can not be fetched. Fortunately this full + // coord is not requied in stream mode updater currently. + + coordSysMgr.update(ecModel, api); + clearColorPalette(ecModel); + scheduler.performVisualTasks(ecModel, payload); + render(this, ecModel, api, payload, updateParams); // Set background + + var backgroundColor = ecModel.get('backgroundColor') || 'transparent'; + var darkMode = ecModel.get('darkMode'); + zr.setBackgroundColor(backgroundColor); // Force set dark mode. + + if (darkMode != null && darkMode !== 'auto') { + zr.setDarkMode(darkMode); + } + + lifecycle.trigger('afterupdate', ecModel, api); + }, + updateTransform: function (payload) { + var _this = this; + + var ecModel = this._model; + var api = this._api; // update before setOption + + if (!ecModel) { + return; + } + + ecModel.setUpdatePayload(payload); // ChartView.markUpdateMethod(payload, 'updateTransform'); + + var componentDirtyList = []; + ecModel.eachComponent(function (componentType, componentModel) { + if (componentType === 'series') { + return; + } + + var componentView = _this.getViewOfComponentModel(componentModel); + + if (componentView && componentView.__alive) { + if (componentView.updateTransform) { + var result = componentView.updateTransform(componentModel, ecModel, api, payload); + result && result.update && componentDirtyList.push(componentView); + } else { + componentDirtyList.push(componentView); + } + } + }); + var seriesDirtyMap = createHashMap(); + ecModel.eachSeries(function (seriesModel) { + var chartView = _this._chartsMap[seriesModel.__viewId]; + + if (chartView.updateTransform) { + var result = chartView.updateTransform(seriesModel, ecModel, api, payload); + result && result.update && seriesDirtyMap.set(seriesModel.uid, 1); + } else { + seriesDirtyMap.set(seriesModel.uid, 1); + } + }); + clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline. + // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true); + + this._scheduler.performVisualTasks(ecModel, payload, { + setDirty: true, + dirtyMap: seriesDirtyMap + }); // Currently, not call render of components. Geo render cost a lot. + // renderComponents(ecIns, ecModel, api, payload, componentDirtyList); + + + renderSeries(this, ecModel, api, payload, {}, seriesDirtyMap); + lifecycle.trigger('afterupdate', ecModel, api); + }, + updateView: function (payload) { + var ecModel = this._model; // update before setOption + + if (!ecModel) { + return; + } + + ecModel.setUpdatePayload(payload); + ChartView.markUpdateMethod(payload, 'updateView'); + clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline. + + this._scheduler.performVisualTasks(ecModel, payload, { + setDirty: true + }); + + render(this, ecModel, this._api, payload, {}); + lifecycle.trigger('afterupdate', ecModel, this._api); + }, + updateVisual: function (payload) { + // updateMethods.update.call(this, payload); + var _this = this; + + var ecModel = this._model; // update before setOption + + if (!ecModel) { + return; + } + + ecModel.setUpdatePayload(payload); // clear all visual + + ecModel.eachSeries(function (seriesModel) { + seriesModel.getData().clearAllVisual(); + }); // Perform visual + + ChartView.markUpdateMethod(payload, 'updateVisual'); + clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline. + + this._scheduler.performVisualTasks(ecModel, payload, { + visualType: 'visual', + setDirty: true + }); + + ecModel.eachComponent(function (componentType, componentModel) { + if (componentType !== 'series') { + var componentView = _this.getViewOfComponentModel(componentModel); + + componentView && componentView.__alive && componentView.updateVisual(componentModel, ecModel, _this._api, payload); + } + }); + ecModel.eachSeries(function (seriesModel) { + var chartView = _this._chartsMap[seriesModel.__viewId]; + chartView.updateVisual(seriesModel, ecModel, _this._api, payload); + }); + lifecycle.trigger('afterupdate', ecModel, this._api); + }, + updateLayout: function (payload) { + updateMethods.update.call(this, payload); + } + }; + + doConvertPixel = function (ecIns, methodName, finder, value) { + if (ecIns._disposed) { + disposedWarning(ecIns.id); + return; + } + + var ecModel = ecIns._model; + + var coordSysList = ecIns._coordSysMgr.getCoordinateSystems(); + + var result; + var parsedFinder = parseFinder(ecModel, finder); + + for (var i = 0; i < coordSysList.length; i++) { + var coordSys = coordSysList[i]; + + if (coordSys[methodName] && (result = coordSys[methodName](ecModel, parsedFinder, value)) != null) { + return result; + } + } + + if ("development" !== 'production') { + console.warn('No coordinate system that supports ' + methodName + ' found by the given finder.'); + } + }; + + updateStreamModes = function (ecIns, ecModel) { + var chartsMap = ecIns._chartsMap; + var scheduler = ecIns._scheduler; + ecModel.eachSeries(function (seriesModel) { + scheduler.updateStreamModes(seriesModel, chartsMap[seriesModel.__viewId]); + }); + }; + + doDispatchAction = function (payload, silent) { + var _this = this; + + var ecModel = this.getModel(); + var payloadType = payload.type; + var escapeConnect = payload.escapeConnect; + var actionWrap = actions[payloadType]; + var actionInfo = actionWrap.actionInfo; + var cptTypeTmp = (actionInfo.update || 'update').split(':'); + var updateMethod = cptTypeTmp.pop(); + var cptType = cptTypeTmp[0] != null && parseClassType(cptTypeTmp[0]); + this[IN_MAIN_PROCESS_KEY] = true; + var payloads = [payload]; + var batched = false; // Batch action + + if (payload.batch) { + batched = true; + payloads = map(payload.batch, function (item) { + item = defaults(extend({}, item), payload); + item.batch = null; + return item; + }); + } + + var eventObjBatch = []; + var eventObj; + var isSelectChange = isSelectChangePayload(payload); + var isHighDown = isHighDownPayload(payload); // Only leave blur once if there are multiple batches. + + if (isHighDown) { + allLeaveBlur(this._api); + } + + each(payloads, function (batchItem) { + // Action can specify the event by return it. + eventObj = actionWrap.action(batchItem, _this._model, _this._api); // Emit event outside + + eventObj = eventObj || extend({}, batchItem); // Convert type to eventType + + eventObj.type = actionInfo.event || eventObj.type; + eventObjBatch.push(eventObj); // light update does not perform data process, layout and visual. + + if (isHighDown) { + var _a = preParseFinder(payload), + queryOptionMap = _a.queryOptionMap, + mainTypeSpecified = _a.mainTypeSpecified; + + var componentMainType = mainTypeSpecified ? queryOptionMap.keys()[0] : 'series'; + updateDirectly(_this, updateMethod, batchItem, componentMainType); + markStatusToUpdate(_this); + } else if (isSelectChange) { + // At present `dispatchAction({ type: 'select', ... })` is not supported on components. + // geo still use 'geoselect'. + updateDirectly(_this, updateMethod, batchItem, 'series'); + markStatusToUpdate(_this); + } else if (cptType) { + updateDirectly(_this, updateMethod, batchItem, cptType.main, cptType.sub); + } + }); + + if (updateMethod !== 'none' && !isHighDown && !isSelectChange && !cptType) { + try { + // Still dirty + if (this[PENDING_UPDATE]) { + prepare(this); + updateMethods.update.call(this, payload); + this[PENDING_UPDATE] = null; + } else { + updateMethods[updateMethod].call(this, payload); + } + } catch (e) { + this[IN_MAIN_PROCESS_KEY] = false; + throw e; + } + } // Follow the rule of action batch + + + if (batched) { + eventObj = { + type: actionInfo.event || payloadType, + escapeConnect: escapeConnect, + batch: eventObjBatch + }; + } else { + eventObj = eventObjBatch[0]; + } + + this[IN_MAIN_PROCESS_KEY] = false; + + if (!silent) { + var messageCenter = this._messageCenter; + messageCenter.trigger(eventObj.type, eventObj); // Extra triggered 'selectchanged' event + + if (isSelectChange) { + var newObj = { + type: 'selectchanged', + escapeConnect: escapeConnect, + selected: getAllSelectedIndices(ecModel), + isFromClick: payload.isFromClick || false, + fromAction: payload.type, + fromActionPayload: payload + }; + messageCenter.trigger(newObj.type, newObj); + } + } + }; + + flushPendingActions = function (silent) { + var pendingActions = this._pendingActions; + + while (pendingActions.length) { + var payload = pendingActions.shift(); + doDispatchAction.call(this, payload, silent); + } + }; + + triggerUpdatedEvent = function (silent) { + !silent && this.trigger('updated'); + }; + /** + * Event `rendered` is triggered when zr + * rendered. It is useful for realtime + * snapshot (reflect animation). + * + * Event `finished` is triggered when: + * (1) zrender rendering finished. + * (2) initial animation finished. + * (3) progressive rendering finished. + * (4) no pending action. + * (5) no delayed setOption needs to be processed. + */ + + + bindRenderedEvent = function (zr, ecIns) { + zr.on('rendered', function (params) { + ecIns.trigger('rendered', params); // The `finished` event should not be triggered repeatly, + // so it should only be triggered when rendering indeed happend + // in zrender. (Consider the case that dipatchAction is keep + // triggering when mouse move). + + if ( // Although zr is dirty if initial animation is not finished + // and this checking is called on frame, we also check + // animation finished for robustness. + zr.animation.isFinished() && !ecIns[PENDING_UPDATE] && !ecIns._scheduler.unfinished && !ecIns._pendingActions.length) { + ecIns.trigger('finished'); + } + }); + }; + + bindMouseEvent = function (zr, ecIns) { + zr.on('mouseover', function (e) { + var el = e.target; + var dispatcher = findEventDispatcher(el, isHighDownDispatcher); + + if (dispatcher) { + handleGlobalMouseOverForHighDown(dispatcher, e, ecIns._api); + markStatusToUpdate(ecIns); + } + }).on('mouseout', function (e) { + var el = e.target; + var dispatcher = findEventDispatcher(el, isHighDownDispatcher); + + if (dispatcher) { + handleGlobalMouseOutForHighDown(dispatcher, e, ecIns._api); + markStatusToUpdate(ecIns); + } + }).on('click', function (e) { + var el = e.target; + var dispatcher = findEventDispatcher(el, function (target) { + return getECData(target).dataIndex != null; + }, true); + + if (dispatcher) { + var actionType = dispatcher.selected ? 'unselect' : 'select'; + var ecData = getECData(dispatcher); + + ecIns._api.dispatchAction({ + type: actionType, + dataType: ecData.dataType, + dataIndexInside: ecData.dataIndex, + seriesIndex: ecData.seriesIndex, + isFromClick: true + }); + } + }); + }; + + function clearColorPalette(ecModel) { + ecModel.clearColorPalette(); + ecModel.eachSeries(function (seriesModel) { + seriesModel.clearColorPalette(); + }); + } + + function allocateZlevels(ecModel) { + var componentZLevels = []; + var seriesZLevels = []; + var hasSeperateZLevel = false; + ecModel.eachComponent(function (componentType, componentModel) { + var zlevel = componentModel.get('zlevel') || 0; + var z = componentModel.get('z') || 0; + var zlevelKey = componentModel.getZLevelKey(); + hasSeperateZLevel = hasSeperateZLevel || !!zlevelKey; + (componentType === 'series' ? seriesZLevels : componentZLevels).push({ + zlevel: zlevel, + z: z, + idx: componentModel.componentIndex, + type: componentType, + key: zlevelKey + }); + }); + + if (hasSeperateZLevel) { + // Series after component + var zLevels = componentZLevels.concat(seriesZLevels); + var lastSeriesZLevel_1; + var lastSeriesKey_1; + sort(zLevels, function (a, b) { + if (a.zlevel === b.zlevel) { + return a.z - b.z; + } + + return a.zlevel - b.zlevel; + }); + each(zLevels, function (item) { + var componentModel = ecModel.getComponent(item.type, item.idx); + var zlevel = item.zlevel; + var key = item.key; + + if (lastSeriesZLevel_1 != null) { + zlevel = Math.max(lastSeriesZLevel_1, zlevel); + } + + if (key) { + if (zlevel === lastSeriesZLevel_1 && key !== lastSeriesKey_1) { + zlevel++; + } + + lastSeriesKey_1 = key; + } else if (lastSeriesKey_1) { + if (zlevel === lastSeriesZLevel_1) { + zlevel++; + } + + lastSeriesKey_1 = ''; + } + + lastSeriesZLevel_1 = zlevel; + componentModel.setZLevel(zlevel); + }); + } + } + + render = function (ecIns, ecModel, api, payload, updateParams) { + allocateZlevels(ecModel); + renderComponents(ecIns, ecModel, api, payload, updateParams); + each(ecIns._chartsViews, function (chart) { + chart.__alive = false; + }); + renderSeries(ecIns, ecModel, api, payload, updateParams); // Remove groups of unrendered charts + + each(ecIns._chartsViews, function (chart) { + if (!chart.__alive) { + chart.remove(ecModel, api); + } + }); + }; + + renderComponents = function (ecIns, ecModel, api, payload, updateParams, dirtyList) { + each(dirtyList || ecIns._componentsViews, function (componentView) { + var componentModel = componentView.__model; + clearStates(componentModel, componentView); + componentView.render(componentModel, ecModel, api, payload); + updateZ(componentModel, componentView); + updateStates(componentModel, componentView); + }); + }; + /** + * Render each chart and component + */ + + + renderSeries = function (ecIns, ecModel, api, payload, updateParams, dirtyMap) { + // Render all charts + var scheduler = ecIns._scheduler; + updateParams = extend(updateParams || {}, { + updatedSeries: ecModel.getSeries() + }); // TODO progressive? + + lifecycle.trigger('series:beforeupdate', ecModel, api, updateParams); + var unfinished = false; + ecModel.eachSeries(function (seriesModel) { + var chartView = ecIns._chartsMap[seriesModel.__viewId]; + chartView.__alive = true; + var renderTask = chartView.renderTask; + scheduler.updatePayload(renderTask, payload); // TODO states on marker. + + clearStates(seriesModel, chartView); + + if (dirtyMap && dirtyMap.get(seriesModel.uid)) { + renderTask.dirty(); + } + + if (renderTask.perform(scheduler.getPerformArgs(renderTask))) { + unfinished = true; + } + + chartView.group.silent = !!seriesModel.get('silent'); // Should not call markRedraw on group, because it will disable zrender + // increamental render (alway render from the __startIndex each frame) + // chartView.group.markRedraw(); + + updateBlend(seriesModel, chartView); + updateSeriesElementSelection(seriesModel); + }); + scheduler.unfinished = unfinished || scheduler.unfinished; + lifecycle.trigger('series:layoutlabels', ecModel, api, updateParams); // transition after label is layouted. + + lifecycle.trigger('series:transition', ecModel, api, updateParams); + ecModel.eachSeries(function (seriesModel) { + var chartView = ecIns._chartsMap[seriesModel.__viewId]; // Update Z after labels updated. Before applying states. + + updateZ(seriesModel, chartView); // NOTE: Update states after label is updated. + // label should be in normal status when layouting. + + updateStates(seriesModel, chartView); + }); // If use hover layer + + updateHoverLayerStatus(ecIns, ecModel); + lifecycle.trigger('series:afterupdate', ecModel, api, updateParams); + }; + + markStatusToUpdate = function (ecIns) { + ecIns[STATUS_NEEDS_UPDATE_KEY] = true; // Wake up zrender if it's sleep. Let it update states in the next frame. + + ecIns.getZr().wakeUp(); + }; + + applyChangedStates = function (ecIns) { + if (!ecIns[STATUS_NEEDS_UPDATE_KEY]) { + return; + } + + ecIns.getZr().storage.traverse(function (el) { + // Not applied on removed elements, it may still in fading. + if (isElementRemoved(el)) { + return; + } + + applyElementStates(el); + }); + ecIns[STATUS_NEEDS_UPDATE_KEY] = false; + }; + + function applyElementStates(el) { + var newStates = []; + var oldStates = el.currentStates; // Keep other states. + + for (var i = 0; i < oldStates.length; i++) { + var stateName = oldStates[i]; + + if (!(stateName === 'emphasis' || stateName === 'blur' || stateName === 'select')) { + newStates.push(stateName); + } + } // Only use states when it's exists. + + + if (el.selected && el.states.select) { + newStates.push('select'); + } + + if (el.hoverState === HOVER_STATE_EMPHASIS && el.states.emphasis) { + newStates.push('emphasis'); + } else if (el.hoverState === HOVER_STATE_BLUR && el.states.blur) { + newStates.push('blur'); + } + + el.useStates(newStates); + } + + function updateHoverLayerStatus(ecIns, ecModel) { + var zr = ecIns._zr; + var storage = zr.storage; + var elCount = 0; + storage.traverse(function (el) { + if (!el.isGroup) { + elCount++; + } + }); + + if (elCount > ecModel.get('hoverLayerThreshold') && !env.node && !env.worker) { + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.preventUsingHoverLayer) { + return; + } + + var chartView = ecIns._chartsMap[seriesModel.__viewId]; + + if (chartView.__alive) { + chartView.eachRendered(function (el) { + if (el.states.emphasis) { + el.states.emphasis.hoverLayer = true; + } + }); + } + }); + } + } + /** + * Update chart and blend. + */ + + function updateBlend(seriesModel, chartView) { + var blendMode = seriesModel.get('blendMode') || null; + chartView.eachRendered(function (el) { + // FIXME marker and other components + if (!el.isGroup) { + // DONT mark the element dirty. In case element is incremental and don't wan't to rerender. + el.style.blend = blendMode; + } + }); + } + + function updateZ(model, view) { + if (model.preventAutoZ) { + return; + } + + var z = model.get('z') || 0; + var zlevel = model.get('zlevel') || 0; // Set z and zlevel + + view.eachRendered(function (el) { + doUpdateZ(el, z, zlevel, -Infinity); // Don't traverse the children because it has been traversed in _updateZ. + + return true; + }); + } + + function doUpdateZ(el, z, zlevel, maxZ2) { + // Group may also have textContent + var label = el.getTextContent(); + var labelLine = el.getTextGuideLine(); + var isGroup = el.isGroup; + + if (isGroup) { + // set z & zlevel of children elements of Group + var children = el.childrenRef(); + + for (var i = 0; i < children.length; i++) { + maxZ2 = Math.max(doUpdateZ(children[i], z, zlevel, maxZ2), maxZ2); + } + } else { + // not Group + el.z = z; + el.zlevel = zlevel; + maxZ2 = Math.max(el.z2, maxZ2); + } // always set z and zlevel if label/labelLine exists + + + if (label) { + label.z = z; + label.zlevel = zlevel; // lift z2 of text content + // TODO if el.emphasis.z2 is spcefied, what about textContent. + + isFinite(maxZ2) && (label.z2 = maxZ2 + 2); + } + + if (labelLine) { + var textGuideLineConfig = el.textGuideLineConfig; + labelLine.z = z; + labelLine.zlevel = zlevel; + isFinite(maxZ2) && (labelLine.z2 = maxZ2 + (textGuideLineConfig && textGuideLineConfig.showAbove ? 1 : -1)); + } + + return maxZ2; + } // Clear states without animation. + // TODO States on component. + + + function clearStates(model, view) { + view.eachRendered(function (el) { + // Not applied on removed elements, it may still in fading. + if (isElementRemoved(el)) { + return; + } + + var textContent = el.getTextContent(); + var textGuide = el.getTextGuideLine(); + + if (el.stateTransition) { + el.stateTransition = null; + } + + if (textContent && textContent.stateTransition) { + textContent.stateTransition = null; + } + + if (textGuide && textGuide.stateTransition) { + textGuide.stateTransition = null; + } // TODO If el is incremental. + + + if (el.hasState()) { + el.prevStates = el.currentStates; + el.clearStates(); + } else if (el.prevStates) { + el.prevStates = null; + } + }); + } + + function updateStates(model, view) { + var stateAnimationModel = model.getModel('stateAnimation'); + var enableAnimation = model.isAnimationEnabled(); + var duration = stateAnimationModel.get('duration'); + var stateTransition = duration > 0 ? { + duration: duration, + delay: stateAnimationModel.get('delay'), + easing: stateAnimationModel.get('easing') // additive: stateAnimationModel.get('additive') + + } : null; + view.eachRendered(function (el) { + if (el.states && el.states.emphasis) { + // Not applied on removed elements, it may still in fading. + if (isElementRemoved(el)) { + return; + } + + if (el instanceof Path) { + savePathStates(el); + } // Only updated on changed element. In case element is incremental and don't wan't to rerender. + // TODO, a more proper way? + + + if (el.__dirty) { + var prevStates = el.prevStates; // Restore states without animation + + if (prevStates) { + el.useStates(prevStates); + } + } // Update state transition and enable animation again. + + + if (enableAnimation) { + el.stateTransition = stateTransition; + var textContent = el.getTextContent(); + var textGuide = el.getTextGuideLine(); // TODO Is it necessary to animate label? + + if (textContent) { + textContent.stateTransition = stateTransition; + } + + if (textGuide) { + textGuide.stateTransition = stateTransition; + } + } // The use higlighted and selected flag to toggle states. + + + if (el.__dirty) { + applyElementStates(el); + } + } + }); + } + + createExtensionAPI = function (ecIns) { + return new ( + /** @class */ + function (_super) { + __extends(class_1, _super); + + function class_1() { + return _super !== null && _super.apply(this, arguments) || this; + } + + class_1.prototype.getCoordinateSystems = function () { + return ecIns._coordSysMgr.getCoordinateSystems(); + }; + + class_1.prototype.getComponentByElement = function (el) { + while (el) { + var modelInfo = el.__ecComponentInfo; + + if (modelInfo != null) { + return ecIns._model.getComponent(modelInfo.mainType, modelInfo.index); + } + + el = el.parent; + } + }; + + class_1.prototype.enterEmphasis = function (el, highlightDigit) { + enterEmphasis(el, highlightDigit); + markStatusToUpdate(ecIns); + }; + + class_1.prototype.leaveEmphasis = function (el, highlightDigit) { + leaveEmphasis(el, highlightDigit); + markStatusToUpdate(ecIns); + }; + + class_1.prototype.enterBlur = function (el) { + enterBlur(el); + markStatusToUpdate(ecIns); + }; + + class_1.prototype.leaveBlur = function (el) { + leaveBlur(el); + markStatusToUpdate(ecIns); + }; + + class_1.prototype.enterSelect = function (el) { + enterSelect(el); + markStatusToUpdate(ecIns); + }; + + class_1.prototype.leaveSelect = function (el) { + leaveSelect(el); + markStatusToUpdate(ecIns); + }; + + class_1.prototype.getModel = function () { + return ecIns.getModel(); + }; + + class_1.prototype.getViewOfComponentModel = function (componentModel) { + return ecIns.getViewOfComponentModel(componentModel); + }; + + class_1.prototype.getViewOfSeriesModel = function (seriesModel) { + return ecIns.getViewOfSeriesModel(seriesModel); + }; + + return class_1; + }(ExtensionAPI))(ecIns); + }; + + enableConnect = function (chart) { + function updateConnectedChartsStatus(charts, status) { + for (var i = 0; i < charts.length; i++) { + var otherChart = charts[i]; + otherChart[CONNECT_STATUS_KEY] = status; + } + } + + each(eventActionMap, function (actionType, eventType) { + chart._messageCenter.on(eventType, function (event) { + if (connectedGroups[chart.group] && chart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_PENDING) { + if (event && event.escapeConnect) { + return; + } + + var action_1 = chart.makeActionFromEvent(event); + var otherCharts_1 = []; + each(instances$1, function (otherChart) { + if (otherChart !== chart && otherChart.group === chart.group) { + otherCharts_1.push(otherChart); + } + }); + updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_PENDING); + each(otherCharts_1, function (otherChart) { + if (otherChart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_UPDATING) { + otherChart.dispatchAction(action_1); + } + }); + updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_UPDATED); + } + }); + }); + }; + }(); + + return ECharts; + }(Eventful); + + var echartsProto = ECharts.prototype; + echartsProto.on = createRegisterEventWithLowercaseECharts('on'); + echartsProto.off = createRegisterEventWithLowercaseECharts('off'); + /** + * @deprecated + */ + // @ts-ignore + + echartsProto.one = function (eventName, cb, ctx) { + var self = this; + deprecateLog('ECharts#one is deprecated.'); + + function wrapped() { + var args2 = []; + + for (var _i = 0; _i < arguments.length; _i++) { + args2[_i] = arguments[_i]; + } + + cb && cb.apply && cb.apply(this, args2); // @ts-ignore + + self.off(eventName, wrapped); + } + + this.on.call(this, eventName, wrapped, ctx); + }; + + var MOUSE_EVENT_NAMES = ['click', 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'globalout', 'contextmenu']; + + function disposedWarning(id) { + if ("development" !== 'production') { + console.warn('Instance ' + id + ' has been disposed'); + } + } + + var actions = {}; + /** + * Map eventType to actionType + */ + + var eventActionMap = {}; + var dataProcessorFuncs = []; + var optionPreprocessorFuncs = []; + var visualFuncs = []; + var themeStorage = {}; + var loadingEffects = {}; + var instances$1 = {}; + var connectedGroups = {}; + var idBase = +new Date() - 0; + var groupIdBase = +new Date() - 0; + var DOM_ATTRIBUTE_KEY = '_echarts_instance_'; + /** + * @param opts.devicePixelRatio Use window.devicePixelRatio by default + * @param opts.renderer Can choose 'canvas' or 'svg' to render the chart. + * @param opts.width Use clientWidth of the input `dom` by default. + * Can be 'auto' (the same as null/undefined) + * @param opts.height Use clientHeight of the input `dom` by default. + * Can be 'auto' (the same as null/undefined) + * @param opts.locale Specify the locale. + * @param opts.useDirtyRect Enable dirty rectangle rendering or not. + */ + + function init$1(dom, theme, opts) { + var isClient = !(opts && opts.ssr); + + if (isClient) { + if ("development" !== 'production') { + if (!dom) { + throw new Error('Initialize failed: invalid dom.'); + } + } + + var existInstance = getInstanceByDom(dom); + + if (existInstance) { + if ("development" !== 'production') { + console.warn('There is a chart instance already initialized on the dom.'); + } + + return existInstance; + } + + if ("development" !== 'production') { + if (isDom(dom) && dom.nodeName.toUpperCase() !== 'CANVAS' && (!dom.clientWidth && (!opts || opts.width == null) || !dom.clientHeight && (!opts || opts.height == null))) { + console.warn('Can\'t get DOM width or height. Please check ' + 'dom.clientWidth and dom.clientHeight. They should not be 0.' + 'For example, you may need to call this in the callback ' + 'of window.onload.'); + } + } + } + + var chart = new ECharts(dom, theme, opts); + chart.id = 'ec_' + idBase++; + instances$1[chart.id] = chart; + isClient && setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id); + enableConnect(chart); + lifecycle.trigger('afterinit', chart); + return chart; + } + /** + * @usage + * (A) + * ```js + * let chart1 = echarts.init(dom1); + * let chart2 = echarts.init(dom2); + * chart1.group = 'xxx'; + * chart2.group = 'xxx'; + * echarts.connect('xxx'); + * ``` + * (B) + * ```js + * let chart1 = echarts.init(dom1); + * let chart2 = echarts.init(dom2); + * echarts.connect('xxx', [chart1, chart2]); + * ``` + */ + + function connect(groupId) { + // Is array of charts + if (isArray(groupId)) { + var charts = groupId; + groupId = null; // If any chart has group + + each(charts, function (chart) { + if (chart.group != null) { + groupId = chart.group; + } + }); + groupId = groupId || 'g_' + groupIdBase++; + each(charts, function (chart) { + chart.group = groupId; + }); + } + + connectedGroups[groupId] = true; + return groupId; + } + /** + * @deprecated + */ + + function disConnect(groupId) { + connectedGroups[groupId] = false; + } + /** + * Alias and backword compat + */ + + var disconnect = disConnect; + /** + * Dispose a chart instance + */ + + function dispose$1(chart) { + if (isString(chart)) { + chart = instances$1[chart]; + } else if (!(chart instanceof ECharts)) { + // Try to treat as dom + chart = getInstanceByDom(chart); + } + + if (chart instanceof ECharts && !chart.isDisposed()) { + chart.dispose(); + } + } + function getInstanceByDom(dom) { + return instances$1[getAttribute(dom, DOM_ATTRIBUTE_KEY)]; + } + function getInstanceById(key) { + return instances$1[key]; + } + /** + * Register theme + */ + + function registerTheme(name, theme) { + themeStorage[name] = theme; + } + /** + * Register option preprocessor + */ + + function registerPreprocessor(preprocessorFunc) { + if (indexOf(optionPreprocessorFuncs, preprocessorFunc) < 0) { + optionPreprocessorFuncs.push(preprocessorFunc); + } + } + function registerProcessor(priority, processor) { + normalizeRegister(dataProcessorFuncs, priority, processor, PRIORITY_PROCESSOR_DEFAULT); + } + /** + * Register postIniter + * @param {Function} postInitFunc + */ + + function registerPostInit(postInitFunc) { + registerUpdateLifecycle('afterinit', postInitFunc); + } + /** + * Register postUpdater + * @param {Function} postUpdateFunc + */ + + function registerPostUpdate(postUpdateFunc) { + registerUpdateLifecycle('afterupdate', postUpdateFunc); + } + function registerUpdateLifecycle(name, cb) { + lifecycle.on(name, cb); + } + function registerAction(actionInfo, eventName, action) { + if (isFunction(eventName)) { + action = eventName; + eventName = ''; + } + + var actionType = isObject(actionInfo) ? actionInfo.type : [actionInfo, actionInfo = { + event: eventName + }][0]; // Event name is all lowercase + + actionInfo.event = (actionInfo.event || actionType).toLowerCase(); + eventName = actionInfo.event; + + if (eventActionMap[eventName]) { + // Already registered. + return; + } // Validate action type and event name. + + + assert(ACTION_REG.test(actionType) && ACTION_REG.test(eventName)); + + if (!actions[actionType]) { + actions[actionType] = { + action: action, + actionInfo: actionInfo + }; + } + + eventActionMap[eventName] = actionType; + } + function registerCoordinateSystem(type, coordSysCreator) { + CoordinateSystemManager.register(type, coordSysCreator); + } + /** + * Get dimensions of specified coordinate system. + * @param {string} type + * @return {Array.} + */ + + function getCoordinateSystemDimensions(type) { + var coordSysCreator = CoordinateSystemManager.get(type); + + if (coordSysCreator) { + return coordSysCreator.getDimensionsInfo ? coordSysCreator.getDimensionsInfo() : coordSysCreator.dimensions.slice(); + } + } + + function registerLayout(priority, layoutTask) { + normalizeRegister(visualFuncs, priority, layoutTask, PRIORITY_VISUAL_LAYOUT, 'layout'); + } + + function registerVisual(priority, visualTask) { + normalizeRegister(visualFuncs, priority, visualTask, PRIORITY_VISUAL_CHART, 'visual'); + } + var registeredTasks = []; + + function normalizeRegister(targetList, priority, fn, defaultPriority, visualType) { + if (isFunction(priority) || isObject(priority)) { + fn = priority; + priority = defaultPriority; + } + + if ("development" !== 'production') { + if (isNaN(priority) || priority == null) { + throw new Error('Illegal priority'); + } // Check duplicate + + + each(targetList, function (wrap) { + assert(wrap.__raw !== fn); + }); + } // Already registered + + + if (indexOf(registeredTasks, fn) >= 0) { + return; + } + + registeredTasks.push(fn); + var stageHandler = Scheduler.wrapStageHandler(fn, visualType); + stageHandler.__prio = priority; + stageHandler.__raw = fn; + targetList.push(stageHandler); + } + + function registerLoading(name, loadingFx) { + loadingEffects[name] = loadingFx; + } + /** + * ZRender need a canvas context to do measureText. + * But in node environment canvas may be created by node-canvas. + * So we need to specify how to create a canvas instead of using document.createElement('canvas') + * + * + * @deprecated use setPlatformAPI({ createCanvas }) instead. + * + * @example + * let Canvas = require('canvas'); + * let echarts = require('echarts'); + * echarts.setCanvasCreator(function () { + * // Small size is enough. + * return new Canvas(32, 32); + * }); + */ + + function setCanvasCreator(creator) { + if ("development" !== 'production') { + deprecateLog('setCanvasCreator is deprecated. Use setPlatformAPI({ createCanvas }) instead.'); + } + + setPlatformAPI({ + createCanvas: creator + }); + } + /** + * The parameters and usage: see `geoSourceManager.registerMap`. + * Compatible with previous `echarts.registerMap`. + */ + + function registerMap(mapName, geoJson, specialAreas) { + var registerMap = getImpl('registerMap'); + registerMap && registerMap(mapName, geoJson, specialAreas); + } + function getMap(mapName) { + var getMap = getImpl('getMap'); + return getMap && getMap(mapName); + } + var registerTransform = registerExternalTransform; + /** + * Globa dispatchAction to a specified chart instance. + */ + // export function dispatchAction(payload: { chartId: string } & Payload, opt?: Parameters[1]) { + // if (!payload || !payload.chartId) { + // // Must have chartId to find chart + // return; + // } + // const chart = instances[payload.chartId]; + // if (chart) { + // chart.dispatchAction(payload, opt); + // } + // } + // Buitlin global visual + + registerVisual(PRIORITY_VISUAL_GLOBAL, seriesStyleTask); + registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataStyleTask); + registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataColorPaletteTask); + registerVisual(PRIORITY_VISUAL_GLOBAL, seriesSymbolTask); + registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataSymbolTask); + registerVisual(PRIORITY_VISUAL_DECAL, decalVisual); + registerPreprocessor(globalBackwardCompat); + registerProcessor(PRIORITY_PROCESSOR_DATASTACK, dataStack); + registerLoading('default', defaultLoading); // Default actions + + registerAction({ + type: HIGHLIGHT_ACTION_TYPE, + event: HIGHLIGHT_ACTION_TYPE, + update: HIGHLIGHT_ACTION_TYPE + }, noop); + registerAction({ + type: DOWNPLAY_ACTION_TYPE, + event: DOWNPLAY_ACTION_TYPE, + update: DOWNPLAY_ACTION_TYPE + }, noop); + registerAction({ + type: SELECT_ACTION_TYPE, + event: SELECT_ACTION_TYPE, + update: SELECT_ACTION_TYPE + }, noop); + registerAction({ + type: UNSELECT_ACTION_TYPE, + event: UNSELECT_ACTION_TYPE, + update: UNSELECT_ACTION_TYPE + }, noop); + registerAction({ + type: TOGGLE_SELECT_ACTION_TYPE, + event: TOGGLE_SELECT_ACTION_TYPE, + update: TOGGLE_SELECT_ACTION_TYPE + }, noop); // Default theme + + registerTheme('light', lightTheme); + registerTheme('dark', theme); // For backward compatibility, where the namespace `dataTool` will + // be mounted on `echarts` is the extension `dataTool` is imported. + + var dataTool = {}; + + var extensions = []; + var extensionRegisters = { + registerPreprocessor: registerPreprocessor, + registerProcessor: registerProcessor, + registerPostInit: registerPostInit, + registerPostUpdate: registerPostUpdate, + registerUpdateLifecycle: registerUpdateLifecycle, + registerAction: registerAction, + registerCoordinateSystem: registerCoordinateSystem, + registerLayout: registerLayout, + registerVisual: registerVisual, + registerTransform: registerTransform, + registerLoading: registerLoading, + registerMap: registerMap, + registerImpl: registerImpl, + PRIORITY: PRIORITY, + ComponentModel: ComponentModel, + ComponentView: ComponentView, + SeriesModel: SeriesModel, + ChartView: ChartView, + // TODO Use ComponentModel and SeriesModel instead of Constructor + registerComponentModel: function (ComponentModelClass) { + ComponentModel.registerClass(ComponentModelClass); + }, + registerComponentView: function (ComponentViewClass) { + ComponentView.registerClass(ComponentViewClass); + }, + registerSeriesModel: function (SeriesModelClass) { + SeriesModel.registerClass(SeriesModelClass); + }, + registerChartView: function (ChartViewClass) { + ChartView.registerClass(ChartViewClass); + }, + registerSubTypeDefaulter: function (componentType, defaulter) { + ComponentModel.registerSubTypeDefaulter(componentType, defaulter); + }, + registerPainter: function (painterType, PainterCtor) { + registerPainter(painterType, PainterCtor); + } + }; + function use(ext) { + if (isArray(ext)) { + // use([ChartLine, ChartBar]); + each(ext, function (singleExt) { + use(singleExt); + }); + return; + } + + if (indexOf(extensions, ext) >= 0) { + return; + } + + extensions.push(ext); + + if (isFunction(ext)) { + ext = { + install: ext + }; + } + + ext.install(extensionRegisters); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function dataIndexMapValueLength(valNumOrArrLengthMoreThan2) { + return valNumOrArrLengthMoreThan2 == null ? 0 : valNumOrArrLengthMoreThan2.length || 1; + } + + function defaultKeyGetter(item) { + return item; + } + + var DataDiffer = + /** @class */ + function () { + /** + * @param context Can be visited by this.context in callback. + */ + function DataDiffer(oldArr, newArr, oldKeyGetter, newKeyGetter, context, // By default: 'oneToOne'. + diffMode) { + this._old = oldArr; + this._new = newArr; + this._oldKeyGetter = oldKeyGetter || defaultKeyGetter; + this._newKeyGetter = newKeyGetter || defaultKeyGetter; // Visible in callback via `this.context`; + + this.context = context; + this._diffModeMultiple = diffMode === 'multiple'; + } + /** + * Callback function when add a data + */ + + + DataDiffer.prototype.add = function (func) { + this._add = func; + return this; + }; + /** + * Callback function when update a data + */ + + + DataDiffer.prototype.update = function (func) { + this._update = func; + return this; + }; + /** + * Callback function when update a data and only work in `cbMode: 'byKey'`. + */ + + + DataDiffer.prototype.updateManyToOne = function (func) { + this._updateManyToOne = func; + return this; + }; + /** + * Callback function when update a data and only work in `cbMode: 'byKey'`. + */ + + + DataDiffer.prototype.updateOneToMany = function (func) { + this._updateOneToMany = func; + return this; + }; + /** + * Callback function when update a data and only work in `cbMode: 'byKey'`. + */ + + + DataDiffer.prototype.updateManyToMany = function (func) { + this._updateManyToMany = func; + return this; + }; + /** + * Callback function when remove a data + */ + + + DataDiffer.prototype.remove = function (func) { + this._remove = func; + return this; + }; + + DataDiffer.prototype.execute = function () { + this[this._diffModeMultiple ? '_executeMultiple' : '_executeOneToOne'](); + }; + + DataDiffer.prototype._executeOneToOne = function () { + var oldArr = this._old; + var newArr = this._new; + var newDataIndexMap = {}; + var oldDataKeyArr = new Array(oldArr.length); + var newDataKeyArr = new Array(newArr.length); + + this._initIndexMap(oldArr, null, oldDataKeyArr, '_oldKeyGetter'); + + this._initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter'); + + for (var i = 0; i < oldArr.length; i++) { + var oldKey = oldDataKeyArr[i]; + var newIdxMapVal = newDataIndexMap[oldKey]; + var newIdxMapValLen = dataIndexMapValueLength(newIdxMapVal); // idx can never be empty array here. see 'set null' logic below. + + if (newIdxMapValLen > 1) { + // Consider there is duplicate key (for example, use dataItem.name as key). + // We should make sure every item in newArr and oldArr can be visited. + var newIdx = newIdxMapVal.shift(); + + if (newIdxMapVal.length === 1) { + newDataIndexMap[oldKey] = newIdxMapVal[0]; + } + + this._update && this._update(newIdx, i); + } else if (newIdxMapValLen === 1) { + newDataIndexMap[oldKey] = null; + this._update && this._update(newIdxMapVal, i); + } else { + this._remove && this._remove(i); + } + } + + this._performRestAdd(newDataKeyArr, newDataIndexMap); + }; + /** + * For example, consider the case: + * oldData: [o0, o1, o2, o3, o4, o5, o6, o7], + * newData: [n0, n1, n2, n3, n4, n5, n6, n7, n8], + * Where: + * o0, o1, n0 has key 'a' (many to one) + * o5, n4, n5, n6 has key 'b' (one to many) + * o2, n1 has key 'c' (one to one) + * n2, n3 has key 'd' (add) + * o3, o4 has key 'e' (remove) + * o6, o7, n7, n8 has key 'f' (many to many, treated as add and remove) + * Then: + * (The order of the following directives are not ensured.) + * this._updateManyToOne(n0, [o0, o1]); + * this._updateOneToMany([n4, n5, n6], o5); + * this._update(n1, o2); + * this._remove(o3); + * this._remove(o4); + * this._remove(o6); + * this._remove(o7); + * this._add(n2); + * this._add(n3); + * this._add(n7); + * this._add(n8); + */ + + + DataDiffer.prototype._executeMultiple = function () { + var oldArr = this._old; + var newArr = this._new; + var oldDataIndexMap = {}; + var newDataIndexMap = {}; + var oldDataKeyArr = []; + var newDataKeyArr = []; + + this._initIndexMap(oldArr, oldDataIndexMap, oldDataKeyArr, '_oldKeyGetter'); + + this._initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter'); + + for (var i = 0; i < oldDataKeyArr.length; i++) { + var oldKey = oldDataKeyArr[i]; + var oldIdxMapVal = oldDataIndexMap[oldKey]; + var newIdxMapVal = newDataIndexMap[oldKey]; + var oldIdxMapValLen = dataIndexMapValueLength(oldIdxMapVal); + var newIdxMapValLen = dataIndexMapValueLength(newIdxMapVal); + + if (oldIdxMapValLen > 1 && newIdxMapValLen === 1) { + this._updateManyToOne && this._updateManyToOne(newIdxMapVal, oldIdxMapVal); + newDataIndexMap[oldKey] = null; + } else if (oldIdxMapValLen === 1 && newIdxMapValLen > 1) { + this._updateOneToMany && this._updateOneToMany(newIdxMapVal, oldIdxMapVal); + newDataIndexMap[oldKey] = null; + } else if (oldIdxMapValLen === 1 && newIdxMapValLen === 1) { + this._update && this._update(newIdxMapVal, oldIdxMapVal); + newDataIndexMap[oldKey] = null; + } else if (oldIdxMapValLen > 1 && newIdxMapValLen > 1) { + this._updateManyToMany && this._updateManyToMany(newIdxMapVal, oldIdxMapVal); + newDataIndexMap[oldKey] = null; + } else if (oldIdxMapValLen > 1) { + for (var i_1 = 0; i_1 < oldIdxMapValLen; i_1++) { + this._remove && this._remove(oldIdxMapVal[i_1]); + } + } else { + this._remove && this._remove(oldIdxMapVal); + } + } + + this._performRestAdd(newDataKeyArr, newDataIndexMap); + }; + + DataDiffer.prototype._performRestAdd = function (newDataKeyArr, newDataIndexMap) { + for (var i = 0; i < newDataKeyArr.length; i++) { + var newKey = newDataKeyArr[i]; + var newIdxMapVal = newDataIndexMap[newKey]; + var idxMapValLen = dataIndexMapValueLength(newIdxMapVal); + + if (idxMapValLen > 1) { + for (var j = 0; j < idxMapValLen; j++) { + this._add && this._add(newIdxMapVal[j]); + } + } else if (idxMapValLen === 1) { + this._add && this._add(newIdxMapVal); + } // Support both `newDataKeyArr` are duplication removed or not removed. + + + newDataIndexMap[newKey] = null; + } + }; + + DataDiffer.prototype._initIndexMap = function (arr, // Can be null. + map, // In 'byKey', the output `keyArr` is duplication removed. + // In 'byIndex', the output `keyArr` is not duplication removed and + // its indices are accurately corresponding to `arr`. + keyArr, keyGetterName) { + var cbModeMultiple = this._diffModeMultiple; + + for (var i = 0; i < arr.length; i++) { + // Add prefix to avoid conflict with Object.prototype. + var key = '_ec_' + this[keyGetterName](arr[i], i); + + if (!cbModeMultiple) { + keyArr[i] = key; + } + + if (!map) { + continue; + } + + var idxMapVal = map[key]; + var idxMapValLen = dataIndexMapValueLength(idxMapVal); + + if (idxMapValLen === 0) { + // Simple optimize: in most cases, one index has one key, + // do not need array. + map[key] = i; + + if (cbModeMultiple) { + keyArr.push(key); + } + } else if (idxMapValLen === 1) { + map[key] = [idxMapVal, i]; + } else { + idxMapVal.push(i); + } + } + }; + + return DataDiffer; + }(); + + var DimensionUserOuput = + /** @class */ + function () { + function DimensionUserOuput(encode, dimRequest) { + this._encode = encode; + this._schema = dimRequest; + } + + DimensionUserOuput.prototype.get = function () { + return { + // Do not generate full dimension name until fist used. + fullDimensions: this._getFullDimensionNames(), + encode: this._encode + }; + }; + /** + * Get all data store dimension names. + * Theoretically a series data store is defined both by series and used dataset (if any). + * If some dimensions are omitted for performance reason in `this.dimensions`, + * the dimension name may not be auto-generated if user does not specify a dimension name. + * In this case, the dimension name is `null`/`undefined`. + */ + + + DimensionUserOuput.prototype._getFullDimensionNames = function () { + if (!this._cachedDimNames) { + this._cachedDimNames = this._schema ? this._schema.makeOutputDimensionNames() : []; + } + + return this._cachedDimNames; + }; + + return DimensionUserOuput; + }(); + function summarizeDimensions(data, schema) { + var summary = {}; + var encode = summary.encode = {}; + var notExtraCoordDimMap = createHashMap(); + var defaultedLabel = []; + var defaultedTooltip = []; + var userOutputEncode = {}; + each(data.dimensions, function (dimName) { + var dimItem = data.getDimensionInfo(dimName); + var coordDim = dimItem.coordDim; + + if (coordDim) { + if ("development" !== 'production') { + assert(VISUAL_DIMENSIONS.get(coordDim) == null); + } + + var coordDimIndex = dimItem.coordDimIndex; + getOrCreateEncodeArr(encode, coordDim)[coordDimIndex] = dimName; + + if (!dimItem.isExtraCoord) { + notExtraCoordDimMap.set(coordDim, 1); // Use the last coord dim (and label friendly) as default label, + // because when dataset is used, it is hard to guess which dimension + // can be value dimension. If both show x, y on label is not look good, + // and conventionally y axis is focused more. + + if (mayLabelDimType(dimItem.type)) { + defaultedLabel[0] = dimName; + } // User output encode do not contain generated coords. + // And it only has index. User can use index to retrieve value from the raw item array. + + + getOrCreateEncodeArr(userOutputEncode, coordDim)[coordDimIndex] = data.getDimensionIndex(dimItem.name); + } + + if (dimItem.defaultTooltip) { + defaultedTooltip.push(dimName); + } + } + + VISUAL_DIMENSIONS.each(function (v, otherDim) { + var encodeArr = getOrCreateEncodeArr(encode, otherDim); + var dimIndex = dimItem.otherDims[otherDim]; + + if (dimIndex != null && dimIndex !== false) { + encodeArr[dimIndex] = dimItem.name; + } + }); + }); + var dataDimsOnCoord = []; + var encodeFirstDimNotExtra = {}; + notExtraCoordDimMap.each(function (v, coordDim) { + var dimArr = encode[coordDim]; + encodeFirstDimNotExtra[coordDim] = dimArr[0]; // Not necessary to remove duplicate, because a data + // dim canot on more than one coordDim. + + dataDimsOnCoord = dataDimsOnCoord.concat(dimArr); + }); + summary.dataDimsOnCoord = dataDimsOnCoord; + summary.dataDimIndicesOnCoord = map(dataDimsOnCoord, function (dimName) { + return data.getDimensionInfo(dimName).storeDimIndex; + }); + summary.encodeFirstDimNotExtra = encodeFirstDimNotExtra; + var encodeLabel = encode.label; // FIXME `encode.label` is not recommanded, because formatter can not be set + // in this way. Use label.formatter instead. May be remove this approach someday. + + if (encodeLabel && encodeLabel.length) { + defaultedLabel = encodeLabel.slice(); + } + + var encodeTooltip = encode.tooltip; + + if (encodeTooltip && encodeTooltip.length) { + defaultedTooltip = encodeTooltip.slice(); + } else if (!defaultedTooltip.length) { + defaultedTooltip = defaultedLabel.slice(); + } + + encode.defaultedLabel = defaultedLabel; + encode.defaultedTooltip = defaultedTooltip; + summary.userOutput = new DimensionUserOuput(userOutputEncode, schema); + return summary; + } + + function getOrCreateEncodeArr(encode, dim) { + if (!encode.hasOwnProperty(dim)) { + encode[dim] = []; + } + + return encode[dim]; + } // FIXME:TS should be type `AxisType` + + + function getDimensionTypeByAxis(axisType) { + return axisType === 'category' ? 'ordinal' : axisType === 'time' ? 'time' : 'float'; + } + + function mayLabelDimType(dimType) { + // In most cases, ordinal and time do not suitable for label. + // Ordinal info can be displayed on axis. Time is too long. + return !(dimType === 'ordinal' || dimType === 'time'); + } // function findTheLastDimMayLabel(data) { + // // Get last value dim + // let dimensions = data.dimensions.slice(); + // let valueType; + // let valueDim; + // while (dimensions.length && ( + // valueDim = dimensions.pop(), + // valueType = data.getDimensionInfo(valueDim).type, + // valueType === 'ordinal' || valueType === 'time' + // )) {} // jshint ignore:line + // return valueDim; + // } + + var SeriesDimensionDefine = + /** @class */ + function () { + /** + * @param opt All of the fields will be shallow copied. + */ + function SeriesDimensionDefine(opt) { + /** + * The format of `otherDims` is: + * ```js + * { + * tooltip?: number + * label?: number + * itemName?: number + * seriesName?: number + * } + * ``` + * + * A `series.encode` can specified these fields: + * ```js + * encode: { + * // "3, 1, 5" is the index of data dimension. + * tooltip: [3, 1, 5], + * label: [0, 3], + * ... + * } + * ``` + * `otherDims` is the parse result of the `series.encode` above, like: + * ```js + * // Suppose the index of this data dimension is `3`. + * this.otherDims = { + * // `3` is at the index `0` of the `encode.tooltip` + * tooltip: 0, + * // `3` is at the index `1` of the `encode.label` + * label: 1 + * }; + * ``` + * + * This prop should never be `null`/`undefined` after initialized. + */ + this.otherDims = {}; + + if (opt != null) { + extend(this, opt); + } + } + + return SeriesDimensionDefine; + }(); + + var inner$4 = makeInner(); + var dimTypeShort = { + float: 'f', + int: 'i', + ordinal: 'o', + number: 'n', + time: 't' + }; + /** + * Represents the dimension requirement of a series. + * + * NOTICE: + * When there are too many dimensions in dataset and many series, only the used dimensions + * (i.e., used by coord sys and declared in `series.encode`) are add to `dimensionDefineList`. + * But users may query data by other unused dimension names. + * In this case, users can only query data if and only if they have defined dimension names + * via ec option, so we provide `getDimensionIndexFromSource`, which only query them from + * `source` dimensions. + */ + + var SeriesDataSchema = + /** @class */ + function () { + function SeriesDataSchema(opt) { + this.dimensions = opt.dimensions; + this._dimOmitted = opt.dimensionOmitted; + this.source = opt.source; + this._fullDimCount = opt.fullDimensionCount; + + this._updateDimOmitted(opt.dimensionOmitted); + } + + SeriesDataSchema.prototype.isDimensionOmitted = function () { + return this._dimOmitted; + }; + + SeriesDataSchema.prototype._updateDimOmitted = function (dimensionOmitted) { + this._dimOmitted = dimensionOmitted; + + if (!dimensionOmitted) { + return; + } + + if (!this._dimNameMap) { + this._dimNameMap = ensureSourceDimNameMap(this.source); + } + }; + /** + * @caution Can only be used when `dimensionOmitted: true`. + * + * Get index by user defined dimension name (i.e., not internal generate name). + * That is, get index from `dimensionsDefine`. + * If no `dimensionsDefine`, or no name get, return -1. + */ + + + SeriesDataSchema.prototype.getSourceDimensionIndex = function (dimName) { + return retrieve2(this._dimNameMap.get(dimName), -1); + }; + /** + * @caution Can only be used when `dimensionOmitted: true`. + * + * Notice: may return `null`/`undefined` if user not specify dimension names. + */ + + + SeriesDataSchema.prototype.getSourceDimension = function (dimIndex) { + var dimensionsDefine = this.source.dimensionsDefine; + + if (dimensionsDefine) { + return dimensionsDefine[dimIndex]; + } + }; + + SeriesDataSchema.prototype.makeStoreSchema = function () { + var dimCount = this._fullDimCount; + var willRetrieveDataByName = shouldRetrieveDataByName(this.source); + var makeHashStrict = !shouldOmitUnusedDimensions(dimCount); // If source don't have dimensions or series don't omit unsed dimensions. + // Generate from seriesDimList directly + + var dimHash = ''; + var dims = []; + + for (var fullDimIdx = 0, seriesDimIdx = 0; fullDimIdx < dimCount; fullDimIdx++) { + var property = void 0; + var type = void 0; + var ordinalMeta = void 0; + var seriesDimDef = this.dimensions[seriesDimIdx]; // The list has been sorted by `storeDimIndex` asc. + + if (seriesDimDef && seriesDimDef.storeDimIndex === fullDimIdx) { + property = willRetrieveDataByName ? seriesDimDef.name : null; + type = seriesDimDef.type; + ordinalMeta = seriesDimDef.ordinalMeta; + seriesDimIdx++; + } else { + var sourceDimDef = this.getSourceDimension(fullDimIdx); + + if (sourceDimDef) { + property = willRetrieveDataByName ? sourceDimDef.name : null; + type = sourceDimDef.type; + } + } + + dims.push({ + property: property, + type: type, + ordinalMeta: ordinalMeta + }); // If retrieving data by index, + // use to determine whether data can be shared. + // (Becuase in this case there might be no dimension name defined in dataset, but indices always exists). + // (indices are always 0, 1, 2, ..., so we can ignore them to shorten the hash). + // Otherwise if retrieving data by property name (like `data: [{aa: 123, bb: 765}, ...]`), + // use in hash. + + if (willRetrieveDataByName && property != null // For data stack, we have make sure each series has its own dim on this store. + // So we do not add property to hash to make sure they can share this store. + && (!seriesDimDef || !seriesDimDef.isCalculationCoord)) { + dimHash += makeHashStrict // Use escape character '`' in case that property name contains '$'. + ? property.replace(/\`/g, '`1').replace(/\$/g, '`2') // For better performance, when there are large dimensions, tolerant this defects that hardly meet. + : property; + } + + dimHash += '$'; + dimHash += dimTypeShort[type] || 'f'; + + if (ordinalMeta) { + dimHash += ordinalMeta.uid; + } + + dimHash += '$'; + } // Source from endpoint(usually series) will be read differently + // when seriesLayoutBy or startIndex(which is affected by sourceHeader) are different. + // So we use this three props as key. + + + var source = this.source; + var hash = [source.seriesLayoutBy, source.startIndex, dimHash].join('$$'); + return { + dimensions: dims, + hash: hash + }; + }; + + SeriesDataSchema.prototype.makeOutputDimensionNames = function () { + var result = []; + + for (var fullDimIdx = 0, seriesDimIdx = 0; fullDimIdx < this._fullDimCount; fullDimIdx++) { + var name_1 = void 0; + var seriesDimDef = this.dimensions[seriesDimIdx]; // The list has been sorted by `storeDimIndex` asc. + + if (seriesDimDef && seriesDimDef.storeDimIndex === fullDimIdx) { + if (!seriesDimDef.isCalculationCoord) { + name_1 = seriesDimDef.name; + } + + seriesDimIdx++; + } else { + var sourceDimDef = this.getSourceDimension(fullDimIdx); + + if (sourceDimDef) { + name_1 = sourceDimDef.name; + } + } + + result.push(name_1); + } + + return result; + }; + + SeriesDataSchema.prototype.appendCalculationDimension = function (dimDef) { + this.dimensions.push(dimDef); + dimDef.isCalculationCoord = true; + this._fullDimCount++; // If append dimension on a data store, consider the store + // might be shared by different series, series dimensions not + // really map to store dimensions. + + this._updateDimOmitted(true); + }; + + return SeriesDataSchema; + }(); + function isSeriesDataSchema(schema) { + return schema instanceof SeriesDataSchema; + } + function createDimNameMap(dimsDef) { + var dataDimNameMap = createHashMap(); + + for (var i = 0; i < (dimsDef || []).length; i++) { + var dimDefItemRaw = dimsDef[i]; + var userDimName = isObject(dimDefItemRaw) ? dimDefItemRaw.name : dimDefItemRaw; + + if (userDimName != null && dataDimNameMap.get(userDimName) == null) { + dataDimNameMap.set(userDimName, i); + } + } + + return dataDimNameMap; + } + function ensureSourceDimNameMap(source) { + var innerSource = inner$4(source); + return innerSource.dimNameMap || (innerSource.dimNameMap = createDimNameMap(source.dimensionsDefine)); + } + function shouldOmitUnusedDimensions(dimCount) { + return dimCount > 30; + } + + var isObject$2 = isObject; + var map$1 = map; + var CtorInt32Array$1 = typeof Int32Array === 'undefined' ? Array : Int32Array; // Use prefix to avoid index to be the same as otherIdList[idx], + // which will cause weird udpate animation. + + var ID_PREFIX = 'e\0\0'; + var INDEX_NOT_FOUND = -1; // type SeriesDimensionIndex = DimensionIndex; + + var TRANSFERABLE_PROPERTIES = ['hasItemOption', '_nameList', '_idList', '_invertedIndicesMap', '_dimSummary', 'userOutput', '_rawData', '_dimValueGetter', '_nameDimIdx', '_idDimIdx', '_nameRepeatCount']; + var CLONE_PROPERTIES = ['_approximateExtent']; // ----------------------------- + // Internal method declarations: + // ----------------------------- + + var prepareInvertedIndex; + var getId; + var getIdNameFromStore; + var normalizeDimensions; + var transferProperties; + var cloneListForMapAndSample; + var makeIdFromName; + + var SeriesData = + /** @class */ + function () { + /** + * @param dimensionsInput.dimensions + * For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...]. + * Dimensions should be concrete names like x, y, z, lng, lat, angle, radius + */ + function SeriesData(dimensionsInput, hostModel) { + this.type = 'list'; + this._dimOmitted = false; + this._nameList = []; + this._idList = []; // Models of data option is stored sparse for optimizing memory cost + // Never used yet (not used yet). + // private _optionModels: Model[] = []; + // Global visual properties after visual coding + + this._visual = {}; // Globel layout properties. + + this._layout = {}; // Item visual properties after visual coding + + this._itemVisuals = []; // Item layout properties after layout + + this._itemLayouts = []; // Graphic elemnents + + this._graphicEls = []; // key: dim, value: extent + + this._approximateExtent = {}; + this._calculationInfo = {}; // Having detected that there is data item is non primitive type + // (in type `OptionDataItemObject`). + // Like `data: [ { value: xx, itemStyle: {...} }, ...]` + // At present it only happen in `SOURCE_FORMAT_ORIGINAL`. + + this.hasItemOption = false; // Methods that create a new list based on this list should be listed here. + // Notice that those method should `RETURN` the new list. + + this.TRANSFERABLE_METHODS = ['cloneShallow', 'downSample', 'lttbDownSample', 'map']; // Methods that change indices of this list should be listed here. + + this.CHANGABLE_METHODS = ['filterSelf', 'selectRange']; + this.DOWNSAMPLE_METHODS = ['downSample', 'lttbDownSample']; + var dimensions; + var assignStoreDimIdx = false; + + if (isSeriesDataSchema(dimensionsInput)) { + dimensions = dimensionsInput.dimensions; + this._dimOmitted = dimensionsInput.isDimensionOmitted(); + this._schema = dimensionsInput; + } else { + assignStoreDimIdx = true; + dimensions = dimensionsInput; + } + + dimensions = dimensions || ['x', 'y']; + var dimensionInfos = {}; + var dimensionNames = []; + var invertedIndicesMap = {}; + var needsHasOwn = false; + var emptyObj = {}; + + for (var i = 0; i < dimensions.length; i++) { + // Use the original dimensions[i], where other flag props may exists. + var dimInfoInput = dimensions[i]; + var dimensionInfo = isString(dimInfoInput) ? new SeriesDimensionDefine({ + name: dimInfoInput + }) : !(dimInfoInput instanceof SeriesDimensionDefine) ? new SeriesDimensionDefine(dimInfoInput) : dimInfoInput; + var dimensionName = dimensionInfo.name; + dimensionInfo.type = dimensionInfo.type || 'float'; + + if (!dimensionInfo.coordDim) { + dimensionInfo.coordDim = dimensionName; + dimensionInfo.coordDimIndex = 0; + } + + var otherDims = dimensionInfo.otherDims = dimensionInfo.otherDims || {}; + dimensionNames.push(dimensionName); + dimensionInfos[dimensionName] = dimensionInfo; + + if (emptyObj[dimensionName] != null) { + needsHasOwn = true; + } + + if (dimensionInfo.createInvertedIndices) { + invertedIndicesMap[dimensionName] = []; + } + + if (otherDims.itemName === 0) { + this._nameDimIdx = i; + } + + if (otherDims.itemId === 0) { + this._idDimIdx = i; + } + + if ("development" !== 'production') { + assert(assignStoreDimIdx || dimensionInfo.storeDimIndex >= 0); + } + + if (assignStoreDimIdx) { + dimensionInfo.storeDimIndex = i; + } + } + + this.dimensions = dimensionNames; + this._dimInfos = dimensionInfos; + + this._initGetDimensionInfo(needsHasOwn); + + this.hostModel = hostModel; + this._invertedIndicesMap = invertedIndicesMap; + + if (this._dimOmitted) { + var dimIdxToName_1 = this._dimIdxToName = createHashMap(); + each(dimensionNames, function (dimName) { + dimIdxToName_1.set(dimensionInfos[dimName].storeDimIndex, dimName); + }); + } + } + /** + * + * Get concrete dimension name by dimension name or dimension index. + * If input a dimension name, do not validate whether the dimension name exits. + * + * @caution + * @param dim Must make sure the dimension is `SeriesDimensionLoose`. + * Because only those dimensions will have auto-generated dimension names if not + * have a user-specified name, and other dimensions will get a return of null/undefined. + * + * @notice Becuause of this reason, should better use `getDimensionIndex` instead, for examples: + * ```js + * const val = data.getStore().get(data.getDimensionIndex(dim), dataIdx); + * ``` + * + * @return Concrete dim name. + */ + + + SeriesData.prototype.getDimension = function (dim) { + var dimIdx = this._recognizeDimIndex(dim); + + if (dimIdx == null) { + return dim; + } + + dimIdx = dim; + + if (!this._dimOmitted) { + return this.dimensions[dimIdx]; + } // Retrieve from series dimension definition becuase it probably contains + // generated dimension name (like 'x', 'y'). + + + var dimName = this._dimIdxToName.get(dimIdx); + + if (dimName != null) { + return dimName; + } + + var sourceDimDef = this._schema.getSourceDimension(dimIdx); + + if (sourceDimDef) { + return sourceDimDef.name; + } + }; + /** + * Get dimension index in data store. Return -1 if not found. + * Can be used to index value from getRawValue. + */ + + + SeriesData.prototype.getDimensionIndex = function (dim) { + var dimIdx = this._recognizeDimIndex(dim); + + if (dimIdx != null) { + return dimIdx; + } + + if (dim == null) { + return -1; + } + + var dimInfo = this._getDimInfo(dim); + + return dimInfo ? dimInfo.storeDimIndex : this._dimOmitted ? this._schema.getSourceDimensionIndex(dim) : -1; + }; + /** + * The meanings of the input parameter `dim`: + * + * + If dim is a number (e.g., `1`), it means the index of the dimension. + * For example, `getDimension(0)` will return 'x' or 'lng' or 'radius'. + * + If dim is a number-like string (e.g., `"1"`): + * + If there is the same concrete dim name defined in `series.dimensions` or `dataset.dimensions`, + * it means that concrete name. + * + If not, it will be converted to a number, which means the index of the dimension. + * (why? because of the backward compatbility. We have been tolerating number-like string in + * dimension setting, although now it seems that it is not a good idea.) + * For example, `visualMap[i].dimension: "1"` is the same meaning as `visualMap[i].dimension: 1`, + * if no dimension name is defined as `"1"`. + * + If dim is a not-number-like string, it means the concrete dim name. + * For example, it can be be default name `"x"`, `"y"`, `"z"`, `"lng"`, `"lat"`, `"angle"`, `"radius"`, + * or customized in `dimensions` property of option like `"age"`. + * + * @return recogonized `DimensionIndex`. Otherwise return null/undefined (means that dim is `DimensionName`). + */ + + + SeriesData.prototype._recognizeDimIndex = function (dim) { + if (isNumber(dim) // If being a number-like string but not being defined as a dimension name. + || dim != null && !isNaN(dim) && !this._getDimInfo(dim) && (!this._dimOmitted || this._schema.getSourceDimensionIndex(dim) < 0)) { + return +dim; + } + }; + + SeriesData.prototype._getStoreDimIndex = function (dim) { + var dimIdx = this.getDimensionIndex(dim); + + if ("development" !== 'production') { + if (dimIdx == null) { + throw new Error('Unkown dimension ' + dim); + } + } + + return dimIdx; + }; + /** + * Get type and calculation info of particular dimension + * @param dim + * Dimension can be concrete names like x, y, z, lng, lat, angle, radius + * Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius' + */ + + + SeriesData.prototype.getDimensionInfo = function (dim) { + // Do not clone, because there may be categories in dimInfo. + return this._getDimInfo(this.getDimension(dim)); + }; + + SeriesData.prototype._initGetDimensionInfo = function (needsHasOwn) { + var dimensionInfos = this._dimInfos; + this._getDimInfo = needsHasOwn ? function (dimName) { + return dimensionInfos.hasOwnProperty(dimName) ? dimensionInfos[dimName] : undefined; + } : function (dimName) { + return dimensionInfos[dimName]; + }; + }; + /** + * concrete dimension name list on coord. + */ + + + SeriesData.prototype.getDimensionsOnCoord = function () { + return this._dimSummary.dataDimsOnCoord.slice(); + }; + + SeriesData.prototype.mapDimension = function (coordDim, idx) { + var dimensionsSummary = this._dimSummary; + + if (idx == null) { + return dimensionsSummary.encodeFirstDimNotExtra[coordDim]; + } + + var dims = dimensionsSummary.encode[coordDim]; + return dims ? dims[idx] : null; + }; + + SeriesData.prototype.mapDimensionsAll = function (coordDim) { + var dimensionsSummary = this._dimSummary; + var dims = dimensionsSummary.encode[coordDim]; + return (dims || []).slice(); + }; + + SeriesData.prototype.getStore = function () { + return this._store; + }; + /** + * Initialize from data + * @param data source or data or data store. + * @param nameList The name of a datum is used on data diff and + * default label/tooltip. + * A name can be specified in encode.itemName, + * or dataItem.name (only for series option data), + * or provided in nameList from outside. + */ + + + SeriesData.prototype.initData = function (data, nameList, dimValueGetter) { + var _this = this; + + var store; + + if (data instanceof DataStore) { + store = data; + } + + if (!store) { + var dimensions = this.dimensions; + var provider = isSourceInstance(data) || isArrayLike(data) ? new DefaultDataProvider(data, dimensions.length) : data; + store = new DataStore(); + var dimensionInfos = map$1(dimensions, function (dimName) { + return { + type: _this._dimInfos[dimName].type, + property: dimName + }; + }); + store.initData(provider, dimensionInfos, dimValueGetter); + } + + this._store = store; // Reset + + this._nameList = (nameList || []).slice(); + this._idList = []; + this._nameRepeatCount = {}; + + this._doInit(0, store.count()); // Cache summary info for fast visit. See "dimensionHelper". + // Needs to be initialized after store is prepared. + + + this._dimSummary = summarizeDimensions(this, this._schema); + this.userOutput = this._dimSummary.userOutput; + }; + /** + * Caution: Can be only called on raw data (before `this._indices` created). + */ + + + SeriesData.prototype.appendData = function (data) { + var range = this._store.appendData(data); + + this._doInit(range[0], range[1]); + }; + /** + * Caution: Can be only called on raw data (before `this._indices` created). + * This method does not modify `rawData` (`dataProvider`), but only + * add values to store. + * + * The final count will be increased by `Math.max(values.length, names.length)`. + * + * @param values That is the SourceType: 'arrayRows', like + * [ + * [12, 33, 44], + * [NaN, 43, 1], + * ['-', 'asdf', 0] + * ] + * Each item is exaclty cooresponding to a dimension. + */ + + + SeriesData.prototype.appendValues = function (values, names) { + var _a = this._store.appendValues(values, names.length), + start = _a.start, + end = _a.end; + + var shouldMakeIdFromName = this._shouldMakeIdFromName(); + + this._updateOrdinalMeta(); + + if (names) { + for (var idx = start; idx < end; idx++) { + var sourceIdx = idx - start; + this._nameList[idx] = names[sourceIdx]; + + if (shouldMakeIdFromName) { + makeIdFromName(this, idx); + } + } + } + }; + + SeriesData.prototype._updateOrdinalMeta = function () { + var store = this._store; + var dimensions = this.dimensions; + + for (var i = 0; i < dimensions.length; i++) { + var dimInfo = this._dimInfos[dimensions[i]]; + + if (dimInfo.ordinalMeta) { + store.collectOrdinalMeta(dimInfo.storeDimIndex, dimInfo.ordinalMeta); + } + } + }; + + SeriesData.prototype._shouldMakeIdFromName = function () { + var provider = this._store.getProvider(); + + return this._idDimIdx == null && provider.getSource().sourceFormat !== SOURCE_FORMAT_TYPED_ARRAY && !provider.fillStorage; + }; + + SeriesData.prototype._doInit = function (start, end) { + if (start >= end) { + return; + } + + var store = this._store; + var provider = store.getProvider(); + + this._updateOrdinalMeta(); + + var nameList = this._nameList; + var idList = this._idList; + var sourceFormat = provider.getSource().sourceFormat; + var isFormatOriginal = sourceFormat === SOURCE_FORMAT_ORIGINAL; // Each data item is value + // [1, 2] + // 2 + // Bar chart, line chart which uses category axis + // only gives the 'y' value. 'x' value is the indices of category + // Use a tempValue to normalize the value to be a (x, y) value + // If dataItem is {name: ...} or {id: ...}, it has highest priority. + // This kind of ids and names are always stored `_nameList` and `_idList`. + + if (isFormatOriginal && !provider.pure) { + var sharedDataItem = []; + + for (var idx = start; idx < end; idx++) { + // NOTICE: Try not to write things into dataItem + var dataItem = provider.getItem(idx, sharedDataItem); + + if (!this.hasItemOption && isDataItemOption(dataItem)) { + this.hasItemOption = true; + } + + if (dataItem) { + var itemName = dataItem.name; + + if (nameList[idx] == null && itemName != null) { + nameList[idx] = convertOptionIdName(itemName, null); + } + + var itemId = dataItem.id; + + if (idList[idx] == null && itemId != null) { + idList[idx] = convertOptionIdName(itemId, null); + } + } + } + } + + if (this._shouldMakeIdFromName()) { + for (var idx = start; idx < end; idx++) { + makeIdFromName(this, idx); + } + } + + prepareInvertedIndex(this); + }; + /** + * PENDING: In fact currently this function is only used to short-circuit + * the calling of `scale.unionExtentFromData` when data have been filtered by modules + * like "dataZoom". `scale.unionExtentFromData` is used to calculate data extent for series on + * an axis, but if a "axis related data filter module" is used, the extent of the axis have + * been fixed and no need to calling `scale.unionExtentFromData` actually. + * But if we add "custom data filter" in future, which is not "axis related", this method may + * be still needed. + * + * Optimize for the scenario that data is filtered by a given extent. + * Consider that if data amount is more than hundreds of thousand, + * extent calculation will cost more than 10ms and the cache will + * be erased because of the filtering. + */ + + + SeriesData.prototype.getApproximateExtent = function (dim) { + return this._approximateExtent[dim] || this._store.getDataExtent(this._getStoreDimIndex(dim)); + }; + /** + * Calculate extent on a filtered data might be time consuming. + * Approximate extent is only used for: calculte extent of filtered data outside. + */ + + + SeriesData.prototype.setApproximateExtent = function (extent, dim) { + dim = this.getDimension(dim); + this._approximateExtent[dim] = extent.slice(); + }; + + SeriesData.prototype.getCalculationInfo = function (key) { + return this._calculationInfo[key]; + }; + + SeriesData.prototype.setCalculationInfo = function (key, value) { + isObject$2(key) ? extend(this._calculationInfo, key) : this._calculationInfo[key] = value; + }; + /** + * @return Never be null/undefined. `number` will be converted to string. Becuase: + * In most cases, name is used in display, where returning a string is more convenient. + * In other cases, name is used in query (see `indexOfName`), where we can keep the + * rule that name `2` equals to name `'2'`. + */ + + + SeriesData.prototype.getName = function (idx) { + var rawIndex = this.getRawIndex(idx); + var name = this._nameList[rawIndex]; + + if (name == null && this._nameDimIdx != null) { + name = getIdNameFromStore(this, this._nameDimIdx, rawIndex); + } + + if (name == null) { + name = ''; + } + + return name; + }; + + SeriesData.prototype._getCategory = function (dimIdx, idx) { + var ordinal = this._store.get(dimIdx, idx); + + var ordinalMeta = this._store.getOrdinalMeta(dimIdx); + + if (ordinalMeta) { + return ordinalMeta.categories[ordinal]; + } + + return ordinal; + }; + /** + * @return Never null/undefined. `number` will be converted to string. Becuase: + * In all cases having encountered at present, id is used in making diff comparison, which + * are usually based on hash map. We can keep the rule that the internal id are always string + * (treat `2` is the same as `'2'`) to make the related logic simple. + */ + + + SeriesData.prototype.getId = function (idx) { + return getId(this, this.getRawIndex(idx)); + }; + + SeriesData.prototype.count = function () { + return this._store.count(); + }; + /** + * Get value. Return NaN if idx is out of range. + * + * @notice Should better to use `data.getStore().get(dimIndex, dataIdx)` instead. + */ + + + SeriesData.prototype.get = function (dim, idx) { + var store = this._store; + var dimInfo = this._dimInfos[dim]; + + if (dimInfo) { + return store.get(dimInfo.storeDimIndex, idx); + } + }; + /** + * @notice Should better to use `data.getStore().getByRawIndex(dimIndex, dataIdx)` instead. + */ + + + SeriesData.prototype.getByRawIndex = function (dim, rawIdx) { + var store = this._store; + var dimInfo = this._dimInfos[dim]; + + if (dimInfo) { + return store.getByRawIndex(dimInfo.storeDimIndex, rawIdx); + } + }; + + SeriesData.prototype.getIndices = function () { + return this._store.getIndices(); + }; + + SeriesData.prototype.getDataExtent = function (dim) { + return this._store.getDataExtent(this._getStoreDimIndex(dim)); + }; + + SeriesData.prototype.getSum = function (dim) { + return this._store.getSum(this._getStoreDimIndex(dim)); + }; + + SeriesData.prototype.getMedian = function (dim) { + return this._store.getMedian(this._getStoreDimIndex(dim)); + }; + + SeriesData.prototype.getValues = function (dimensions, idx) { + var _this = this; + + var store = this._store; + return isArray(dimensions) ? store.getValues(map$1(dimensions, function (dim) { + return _this._getStoreDimIndex(dim); + }), idx) : store.getValues(dimensions); + }; + /** + * If value is NaN. Inlcuding '-' + * Only check the coord dimensions. + */ + + + SeriesData.prototype.hasValue = function (idx) { + var dataDimIndicesOnCoord = this._dimSummary.dataDimIndicesOnCoord; + + for (var i = 0, len = dataDimIndicesOnCoord.length; i < len; i++) { + // Ordinal type originally can be string or number. + // But when an ordinal type is used on coord, it can + // not be string but only number. So we can also use isNaN. + if (isNaN(this._store.get(dataDimIndicesOnCoord[i], idx))) { + return false; + } + } + + return true; + }; + /** + * Retreive the index with given name + */ + + + SeriesData.prototype.indexOfName = function (name) { + for (var i = 0, len = this._store.count(); i < len; i++) { + if (this.getName(i) === name) { + return i; + } + } + + return -1; + }; + + SeriesData.prototype.getRawIndex = function (idx) { + return this._store.getRawIndex(idx); + }; + + SeriesData.prototype.indexOfRawIndex = function (rawIndex) { + return this._store.indexOfRawIndex(rawIndex); + }; + /** + * Only support the dimension which inverted index created. + * Do not support other cases until required. + * @param dim concrete dim + * @param value ordinal index + * @return rawIndex + */ + + + SeriesData.prototype.rawIndexOf = function (dim, value) { + var invertedIndices = dim && this._invertedIndicesMap[dim]; + + if ("development" !== 'production') { + if (!invertedIndices) { + throw new Error('Do not supported yet'); + } + } + + var rawIndex = invertedIndices[value]; + + if (rawIndex == null || isNaN(rawIndex)) { + return INDEX_NOT_FOUND; + } + + return rawIndex; + }; + /** + * Retreive the index of nearest value + * @param dim + * @param value + * @param [maxDistance=Infinity] + * @return If and only if multiple indices has + * the same value, they are put to the result. + */ + + + SeriesData.prototype.indicesOfNearest = function (dim, value, maxDistance) { + return this._store.indicesOfNearest(this._getStoreDimIndex(dim), value, maxDistance); + }; + + SeriesData.prototype.each = function (dims, cb, ctx) { + + if (isFunction(dims)) { + ctx = cb; + cb = dims; + dims = []; + } // ctxCompat just for compat echarts3 + + + var fCtx = ctx || this; + var dimIndices = map$1(normalizeDimensions(dims), this._getStoreDimIndex, this); + + this._store.each(dimIndices, fCtx ? bind(cb, fCtx) : cb); + }; + + SeriesData.prototype.filterSelf = function (dims, cb, ctx) { + + if (isFunction(dims)) { + ctx = cb; + cb = dims; + dims = []; + } // ctxCompat just for compat echarts3 + + + var fCtx = ctx || this; + var dimIndices = map$1(normalizeDimensions(dims), this._getStoreDimIndex, this); + this._store = this._store.filter(dimIndices, fCtx ? bind(cb, fCtx) : cb); + return this; + }; + /** + * Select data in range. (For optimization of filter) + * (Manually inline code, support 5 million data filtering in data zoom.) + */ + + + SeriesData.prototype.selectRange = function (range) { + + var _this = this; + + var innerRange = {}; + var dims = keys(range); + each(dims, function (dim) { + var dimIdx = _this._getStoreDimIndex(dim); + + innerRange[dimIdx] = range[dim]; + }); + this._store = this._store.selectRange(innerRange); + return this; + }; + /* eslint-enable max-len */ + + + SeriesData.prototype.mapArray = function (dims, cb, ctx) { + + if (isFunction(dims)) { + ctx = cb; + cb = dims; + dims = []; + } // ctxCompat just for compat echarts3 + + + ctx = ctx || this; + var result = []; + this.each(dims, function () { + result.push(cb && cb.apply(this, arguments)); + }, ctx); + return result; + }; + + SeriesData.prototype.map = function (dims, cb, ctx, ctxCompat) { + + var fCtx = ctx || ctxCompat || this; + var dimIndices = map$1(normalizeDimensions(dims), this._getStoreDimIndex, this); + var list = cloneListForMapAndSample(this); + list._store = this._store.map(dimIndices, fCtx ? bind(cb, fCtx) : cb); + return list; + }; + + SeriesData.prototype.modify = function (dims, cb, ctx, ctxCompat) { + var _this = this; // ctxCompat just for compat echarts3 + + + var fCtx = ctx || ctxCompat || this; + + if ("development" !== 'production') { + each(normalizeDimensions(dims), function (dim) { + var dimInfo = _this.getDimensionInfo(dim); + + if (!dimInfo.isCalculationCoord) { + console.error('Danger: only stack dimension can be modified'); + } + }); + } + + var dimIndices = map$1(normalizeDimensions(dims), this._getStoreDimIndex, this); // If do shallow clone here, if there are too many stacked series, + // it still cost lots of memory, becuase `_store.dimensions` are not shared. + // We should consider there probably be shallow clone happen in each sereis + // in consequent filter/map. + + this._store.modify(dimIndices, fCtx ? bind(cb, fCtx) : cb); + }; + /** + * Large data down sampling on given dimension + * @param sampleIndex Sample index for name and id + */ + + + SeriesData.prototype.downSample = function (dimension, rate, sampleValue, sampleIndex) { + var list = cloneListForMapAndSample(this); + list._store = this._store.downSample(this._getStoreDimIndex(dimension), rate, sampleValue, sampleIndex); + return list; + }; + /** + * Large data down sampling using largest-triangle-three-buckets + * @param {string} valueDimension + * @param {number} targetCount + */ + + + SeriesData.prototype.lttbDownSample = function (valueDimension, rate) { + var list = cloneListForMapAndSample(this); + list._store = this._store.lttbDownSample(this._getStoreDimIndex(valueDimension), rate); + return list; + }; + + SeriesData.prototype.getRawDataItem = function (idx) { + return this._store.getRawDataItem(idx); + }; + /** + * Get model of one data item. + */ + // TODO: Type of data item + + + SeriesData.prototype.getItemModel = function (idx) { + var hostModel = this.hostModel; + var dataItem = this.getRawDataItem(idx); + return new Model(dataItem, hostModel, hostModel && hostModel.ecModel); + }; + /** + * Create a data differ + */ + + + SeriesData.prototype.diff = function (otherList) { + var thisList = this; + return new DataDiffer(otherList ? otherList.getStore().getIndices() : [], this.getStore().getIndices(), function (idx) { + return getId(otherList, idx); + }, function (idx) { + return getId(thisList, idx); + }); + }; + /** + * Get visual property. + */ + + + SeriesData.prototype.getVisual = function (key) { + var visual = this._visual; + return visual && visual[key]; + }; + + SeriesData.prototype.setVisual = function (kvObj, val) { + this._visual = this._visual || {}; + + if (isObject$2(kvObj)) { + extend(this._visual, kvObj); + } else { + this._visual[kvObj] = val; + } + }; + /** + * Get visual property of single data item + */ + // eslint-disable-next-line + + + SeriesData.prototype.getItemVisual = function (idx, key) { + var itemVisual = this._itemVisuals[idx]; + var val = itemVisual && itemVisual[key]; + + if (val == null) { + // Use global visual property + return this.getVisual(key); + } + + return val; + }; + /** + * If exists visual property of single data item + */ + + + SeriesData.prototype.hasItemVisual = function () { + return this._itemVisuals.length > 0; + }; + /** + * Make sure itemVisual property is unique + */ + // TODO: use key to save visual to reduce memory. + + + SeriesData.prototype.ensureUniqueItemVisual = function (idx, key) { + var itemVisuals = this._itemVisuals; + var itemVisual = itemVisuals[idx]; + + if (!itemVisual) { + itemVisual = itemVisuals[idx] = {}; + } + + var val = itemVisual[key]; + + if (val == null) { + val = this.getVisual(key); // TODO Performance? + + if (isArray(val)) { + val = val.slice(); + } else if (isObject$2(val)) { + val = extend({}, val); + } + + itemVisual[key] = val; + } + + return val; + }; // eslint-disable-next-line + + + SeriesData.prototype.setItemVisual = function (idx, key, value) { + var itemVisual = this._itemVisuals[idx] || {}; + this._itemVisuals[idx] = itemVisual; + + if (isObject$2(key)) { + extend(itemVisual, key); + } else { + itemVisual[key] = value; + } + }; + /** + * Clear itemVisuals and list visual. + */ + + + SeriesData.prototype.clearAllVisual = function () { + this._visual = {}; + this._itemVisuals = []; + }; + + SeriesData.prototype.setLayout = function (key, val) { + isObject$2(key) ? extend(this._layout, key) : this._layout[key] = val; + }; + /** + * Get layout property. + */ + + + SeriesData.prototype.getLayout = function (key) { + return this._layout[key]; + }; + /** + * Get layout of single data item + */ + + + SeriesData.prototype.getItemLayout = function (idx) { + return this._itemLayouts[idx]; + }; + /** + * Set layout of single data item + */ + + + SeriesData.prototype.setItemLayout = function (idx, layout, merge) { + this._itemLayouts[idx] = merge ? extend(this._itemLayouts[idx] || {}, layout) : layout; + }; + /** + * Clear all layout of single data item + */ + + + SeriesData.prototype.clearItemLayouts = function () { + this._itemLayouts.length = 0; + }; + /** + * Set graphic element relative to data. It can be set as null + */ + + + SeriesData.prototype.setItemGraphicEl = function (idx, el) { + var seriesIndex = this.hostModel && this.hostModel.seriesIndex; + setCommonECData(seriesIndex, this.dataType, idx, el); + this._graphicEls[idx] = el; + }; + + SeriesData.prototype.getItemGraphicEl = function (idx) { + return this._graphicEls[idx]; + }; + + SeriesData.prototype.eachItemGraphicEl = function (cb, context) { + each(this._graphicEls, function (el, idx) { + if (el) { + cb && cb.call(context, el, idx); + } + }); + }; + /** + * Shallow clone a new list except visual and layout properties, and graph elements. + * New list only change the indices. + */ + + + SeriesData.prototype.cloneShallow = function (list) { + if (!list) { + list = new SeriesData(this._schema ? this._schema : map$1(this.dimensions, this._getDimInfo, this), this.hostModel); + } + + transferProperties(list, this); + list._store = this._store; + return list; + }; + /** + * Wrap some method to add more feature + */ + + + SeriesData.prototype.wrapMethod = function (methodName, injectFunction) { + var originalMethod = this[methodName]; + + if (!isFunction(originalMethod)) { + return; + } + + this.__wrappedMethods = this.__wrappedMethods || []; + + this.__wrappedMethods.push(methodName); + + this[methodName] = function () { + var res = originalMethod.apply(this, arguments); + return injectFunction.apply(this, [res].concat(slice(arguments))); + }; + }; // ---------------------------------------------------------- + // A work around for internal method visiting private member. + // ---------------------------------------------------------- + + + SeriesData.internalField = function () { + prepareInvertedIndex = function (data) { + var invertedIndicesMap = data._invertedIndicesMap; + each(invertedIndicesMap, function (invertedIndices, dim) { + var dimInfo = data._dimInfos[dim]; // Currently, only dimensions that has ordinalMeta can create inverted indices. + + var ordinalMeta = dimInfo.ordinalMeta; + var store = data._store; + + if (ordinalMeta) { + invertedIndices = invertedIndicesMap[dim] = new CtorInt32Array$1(ordinalMeta.categories.length); // The default value of TypedArray is 0. To avoid miss + // mapping to 0, we should set it as INDEX_NOT_FOUND. + + for (var i = 0; i < invertedIndices.length; i++) { + invertedIndices[i] = INDEX_NOT_FOUND; + } + + for (var i = 0; i < store.count(); i++) { + // Only support the case that all values are distinct. + invertedIndices[store.get(dimInfo.storeDimIndex, i)] = i; + } + } + }); + }; + + getIdNameFromStore = function (data, dimIdx, idx) { + return convertOptionIdName(data._getCategory(dimIdx, idx), null); + }; + /** + * @see the comment of `List['getId']`. + */ + + + getId = function (data, rawIndex) { + var id = data._idList[rawIndex]; + + if (id == null && data._idDimIdx != null) { + id = getIdNameFromStore(data, data._idDimIdx, rawIndex); + } + + if (id == null) { + id = ID_PREFIX + rawIndex; + } + + return id; + }; + + normalizeDimensions = function (dimensions) { + if (!isArray(dimensions)) { + dimensions = dimensions != null ? [dimensions] : []; + } + + return dimensions; + }; + /** + * Data in excludeDimensions is copied, otherwise transfered. + */ + + + cloneListForMapAndSample = function (original) { + var list = new SeriesData(original._schema ? original._schema : map$1(original.dimensions, original._getDimInfo, original), original.hostModel); // FIXME If needs stackedOn, value may already been stacked + + transferProperties(list, original); + return list; + }; + + transferProperties = function (target, source) { + each(TRANSFERABLE_PROPERTIES.concat(source.__wrappedMethods || []), function (propName) { + if (source.hasOwnProperty(propName)) { + target[propName] = source[propName]; + } + }); + target.__wrappedMethods = source.__wrappedMethods; + each(CLONE_PROPERTIES, function (propName) { + target[propName] = clone(source[propName]); + }); + target._calculationInfo = extend({}, source._calculationInfo); + }; + + makeIdFromName = function (data, idx) { + var nameList = data._nameList; + var idList = data._idList; + var nameDimIdx = data._nameDimIdx; + var idDimIdx = data._idDimIdx; + var name = nameList[idx]; + var id = idList[idx]; + + if (name == null && nameDimIdx != null) { + nameList[idx] = name = getIdNameFromStore(data, nameDimIdx, idx); + } + + if (id == null && idDimIdx != null) { + idList[idx] = id = getIdNameFromStore(data, idDimIdx, idx); + } + + if (id == null && name != null) { + var nameRepeatCount = data._nameRepeatCount; + var nmCnt = nameRepeatCount[name] = (nameRepeatCount[name] || 0) + 1; + id = name; + + if (nmCnt > 1) { + id += '__ec__' + nmCnt; + } + + idList[idx] = id; + } + }; + }(); + + return SeriesData; + }(); + + /** + * For outside usage compat (like echarts-gl are using it). + */ + + function createDimensions(source, opt) { + return prepareSeriesDataSchema(source, opt).dimensions; + } + /** + * This method builds the relationship between: + * + "what the coord sys or series requires (see `coordDimensions`)", + * + "what the user defines (in `encode` and `dimensions`, see `opt.dimensionsDefine` and `opt.encodeDefine`)" + * + "what the data source provids (see `source`)". + * + * Some guess strategy will be adapted if user does not define something. + * If no 'value' dimension specified, the first no-named dimension will be + * named as 'value'. + * + * @return The results are always sorted by `storeDimIndex` asc. + */ + + function prepareSeriesDataSchema( // TODO: TYPE completeDimensions type + source, opt) { + if (!isSourceInstance(source)) { + source = createSourceFromSeriesDataOption(source); + } + + opt = opt || {}; + var sysDims = opt.coordDimensions || []; + var dimsDef = opt.dimensionsDefine || source.dimensionsDefine || []; + var coordDimNameMap = createHashMap(); + var resultList = []; + var dimCount = getDimCount(source, sysDims, dimsDef, opt.dimensionsCount); // Try to ignore unsed dimensions if sharing a high dimension datastore + // 30 is an experience value. + + var omitUnusedDimensions = opt.canOmitUnusedDimensions && shouldOmitUnusedDimensions(dimCount); + var isUsingSourceDimensionsDef = dimsDef === source.dimensionsDefine; + var dataDimNameMap = isUsingSourceDimensionsDef ? ensureSourceDimNameMap(source) : createDimNameMap(dimsDef); + var encodeDef = opt.encodeDefine; + + if (!encodeDef && opt.encodeDefaulter) { + encodeDef = opt.encodeDefaulter(source, dimCount); + } + + var encodeDefMap = createHashMap(encodeDef); + var indicesMap = new CtorInt32Array(dimCount); + + for (var i = 0; i < indicesMap.length; i++) { + indicesMap[i] = -1; + } + + function getResultItem(dimIdx) { + var idx = indicesMap[dimIdx]; + + if (idx < 0) { + var dimDefItemRaw = dimsDef[dimIdx]; + var dimDefItem = isObject(dimDefItemRaw) ? dimDefItemRaw : { + name: dimDefItemRaw + }; + var resultItem = new SeriesDimensionDefine(); + var userDimName = dimDefItem.name; + + if (userDimName != null && dataDimNameMap.get(userDimName) != null) { + // Only if `series.dimensions` is defined in option + // displayName, will be set, and dimension will be diplayed vertically in + // tooltip by default. + resultItem.name = resultItem.displayName = userDimName; + } + + dimDefItem.type != null && (resultItem.type = dimDefItem.type); + dimDefItem.displayName != null && (resultItem.displayName = dimDefItem.displayName); + var newIdx = resultList.length; + indicesMap[dimIdx] = newIdx; + resultItem.storeDimIndex = dimIdx; + resultList.push(resultItem); + return resultItem; + } + + return resultList[idx]; + } + + if (!omitUnusedDimensions) { + for (var i = 0; i < dimCount; i++) { + getResultItem(i); + } + } // Set `coordDim` and `coordDimIndex` by `encodeDefMap` and normalize `encodeDefMap`. + + + encodeDefMap.each(function (dataDimsRaw, coordDim) { + var dataDims = normalizeToArray(dataDimsRaw).slice(); // Note: It is allowed that `dataDims.length` is `0`, e.g., options is + // `{encode: {x: -1, y: 1}}`. Should not filter anything in + // this case. + + if (dataDims.length === 1 && !isString(dataDims[0]) && dataDims[0] < 0) { + encodeDefMap.set(coordDim, false); + return; + } + + var validDataDims = encodeDefMap.set(coordDim, []); + each(dataDims, function (resultDimIdxOrName, idx) { + // The input resultDimIdx can be dim name or index. + var resultDimIdx = isString(resultDimIdxOrName) ? dataDimNameMap.get(resultDimIdxOrName) : resultDimIdxOrName; + + if (resultDimIdx != null && resultDimIdx < dimCount) { + validDataDims[idx] = resultDimIdx; + applyDim(getResultItem(resultDimIdx), coordDim, idx); + } + }); + }); // Apply templetes and default order from `sysDims`. + + var availDimIdx = 0; + each(sysDims, function (sysDimItemRaw) { + var coordDim; + var sysDimItemDimsDef; + var sysDimItemOtherDims; + var sysDimItem; + + if (isString(sysDimItemRaw)) { + coordDim = sysDimItemRaw; + sysDimItem = {}; + } else { + sysDimItem = sysDimItemRaw; + coordDim = sysDimItem.name; + var ordinalMeta = sysDimItem.ordinalMeta; + sysDimItem.ordinalMeta = null; + sysDimItem = extend({}, sysDimItem); + sysDimItem.ordinalMeta = ordinalMeta; // `coordDimIndex` should not be set directly. + + sysDimItemDimsDef = sysDimItem.dimsDef; + sysDimItemOtherDims = sysDimItem.otherDims; + sysDimItem.name = sysDimItem.coordDim = sysDimItem.coordDimIndex = sysDimItem.dimsDef = sysDimItem.otherDims = null; + } + + var dataDims = encodeDefMap.get(coordDim); // negative resultDimIdx means no need to mapping. + + if (dataDims === false) { + return; + } + + dataDims = normalizeToArray(dataDims); // dimensions provides default dim sequences. + + if (!dataDims.length) { + for (var i = 0; i < (sysDimItemDimsDef && sysDimItemDimsDef.length || 1); i++) { + while (availDimIdx < dimCount && getResultItem(availDimIdx).coordDim != null) { + availDimIdx++; + } + + availDimIdx < dimCount && dataDims.push(availDimIdx++); + } + } // Apply templates. + + + each(dataDims, function (resultDimIdx, coordDimIndex) { + var resultItem = getResultItem(resultDimIdx); // Coordinate system has a higher priority on dim type than source. + + if (isUsingSourceDimensionsDef && sysDimItem.type != null) { + resultItem.type = sysDimItem.type; + } + + applyDim(defaults(resultItem, sysDimItem), coordDim, coordDimIndex); + + if (resultItem.name == null && sysDimItemDimsDef) { + var sysDimItemDimsDefItem = sysDimItemDimsDef[coordDimIndex]; + !isObject(sysDimItemDimsDefItem) && (sysDimItemDimsDefItem = { + name: sysDimItemDimsDefItem + }); + resultItem.name = resultItem.displayName = sysDimItemDimsDefItem.name; + resultItem.defaultTooltip = sysDimItemDimsDefItem.defaultTooltip; + } // FIXME refactor, currently only used in case: {otherDims: {tooltip: false}} + + + sysDimItemOtherDims && defaults(resultItem.otherDims, sysDimItemOtherDims); + }); + }); + + function applyDim(resultItem, coordDim, coordDimIndex) { + if (VISUAL_DIMENSIONS.get(coordDim) != null) { + resultItem.otherDims[coordDim] = coordDimIndex; + } else { + resultItem.coordDim = coordDim; + resultItem.coordDimIndex = coordDimIndex; + coordDimNameMap.set(coordDim, true); + } + } // Make sure the first extra dim is 'value'. + + + var generateCoord = opt.generateCoord; + var generateCoordCount = opt.generateCoordCount; + var fromZero = generateCoordCount != null; + generateCoordCount = generateCoord ? generateCoordCount || 1 : 0; + var extra = generateCoord || 'value'; + + function ifNoNameFillWithCoordName(resultItem) { + if (resultItem.name == null) { + // Duplication will be removed in the next step. + resultItem.name = resultItem.coordDim; + } + } // Set dim `name` and other `coordDim` and other props. + + + if (!omitUnusedDimensions) { + for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) { + var resultItem = getResultItem(resultDimIdx); + var coordDim = resultItem.coordDim; + + if (coordDim == null) { + // TODO no need to generate coordDim for isExtraCoord? + resultItem.coordDim = genCoordDimName(extra, coordDimNameMap, fromZero); + resultItem.coordDimIndex = 0; // Series specified generateCoord is using out. + + if (!generateCoord || generateCoordCount <= 0) { + resultItem.isExtraCoord = true; + } + + generateCoordCount--; + } + + ifNoNameFillWithCoordName(resultItem); + + if (resultItem.type == null && (guessOrdinal(source, resultDimIdx) === BE_ORDINAL.Must // Consider the case: + // { + // dataset: {source: [ + // ['2001', 123], + // ['2002', 456], + // ... + // ['The others', 987], + // ]}, + // series: {type: 'pie'} + // } + // The first colum should better be treated as a "ordinal" although it + // might not able to be detected as an "ordinal" by `guessOrdinal`. + || resultItem.isExtraCoord && (resultItem.otherDims.itemName != null || resultItem.otherDims.seriesName != null))) { + resultItem.type = 'ordinal'; + } + } + } else { + each(resultList, function (resultItem) { + // PENDING: guessOrdinal or let user specify type: 'ordinal' manually? + ifNoNameFillWithCoordName(resultItem); + }); // Sort dimensions: there are some rule that use the last dim as label, + // and for some latter travel process easier. + + resultList.sort(function (item0, item1) { + return item0.storeDimIndex - item1.storeDimIndex; + }); + } + + removeDuplication(resultList); + return new SeriesDataSchema({ + source: source, + dimensions: resultList, + fullDimensionCount: dimCount, + dimensionOmitted: omitUnusedDimensions + }); + } + + function removeDuplication(result) { + var duplicationMap = createHashMap(); + + for (var i = 0; i < result.length; i++) { + var dim = result[i]; + var dimOriginalName = dim.name; + var count = duplicationMap.get(dimOriginalName) || 0; + + if (count > 0) { + // Starts from 0. + dim.name = dimOriginalName + (count - 1); + } + + count++; + duplicationMap.set(dimOriginalName, count); + } + } // ??? TODO + // Originally detect dimCount by data[0]. Should we + // optimize it to only by sysDims and dimensions and encode. + // So only necessary dims will be initialized. + // But + // (1) custom series should be considered. where other dims + // may be visited. + // (2) sometimes user need to calcualte bubble size or use visualMap + // on other dimensions besides coordSys needed. + // So, dims that is not used by system, should be shared in data store? + + + function getDimCount(source, sysDims, dimsDef, optDimCount) { + // Note that the result dimCount should not small than columns count + // of data, otherwise `dataDimNameMap` checking will be incorrect. + var dimCount = Math.max(source.dimensionsDetectedCount || 1, sysDims.length, dimsDef.length, optDimCount || 0); + each(sysDims, function (sysDimItem) { + var sysDimItemDimsDef; + + if (isObject(sysDimItem) && (sysDimItemDimsDef = sysDimItem.dimsDef)) { + dimCount = Math.max(dimCount, sysDimItemDimsDef.length); + } + }); + return dimCount; + } + + function genCoordDimName(name, map, fromZero) { + var mapData = map.data; + + if (fromZero || mapData.hasOwnProperty(name)) { + var i = 0; + + while (mapData.hasOwnProperty(name + i)) { + i++; + } + + name += i; + } + + map.set(name, true); + return name; + } + + /** + * @class + * For example: + * { + * coordSysName: 'cartesian2d', + * coordSysDims: ['x', 'y', ...], + * axisMap: HashMap({ + * x: xAxisModel, + * y: yAxisModel + * }), + * categoryAxisMap: HashMap({ + * x: xAxisModel, + * y: undefined + * }), + * // The index of the first category axis in `coordSysDims`. + * // `null/undefined` means no category axis exists. + * firstCategoryDimIndex: 1, + * // To replace user specified encode. + * } + */ + + var CoordSysInfo = + /** @class */ + function () { + function CoordSysInfo(coordSysName) { + this.coordSysDims = []; + this.axisMap = createHashMap(); + this.categoryAxisMap = createHashMap(); + this.coordSysName = coordSysName; + } + + return CoordSysInfo; + }(); + + function getCoordSysInfoBySeries(seriesModel) { + var coordSysName = seriesModel.get('coordinateSystem'); + var result = new CoordSysInfo(coordSysName); + var fetch = fetchers[coordSysName]; + + if (fetch) { + fetch(seriesModel, result, result.axisMap, result.categoryAxisMap); + return result; + } + } + var fetchers = { + cartesian2d: function (seriesModel, result, axisMap, categoryAxisMap) { + var xAxisModel = seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0]; + var yAxisModel = seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0]; + + if ("development" !== 'production') { + if (!xAxisModel) { + throw new Error('xAxis "' + retrieve(seriesModel.get('xAxisIndex'), seriesModel.get('xAxisId'), 0) + '" not found'); + } + + if (!yAxisModel) { + throw new Error('yAxis "' + retrieve(seriesModel.get('xAxisIndex'), seriesModel.get('yAxisId'), 0) + '" not found'); + } + } + + result.coordSysDims = ['x', 'y']; + axisMap.set('x', xAxisModel); + axisMap.set('y', yAxisModel); + + if (isCategory(xAxisModel)) { + categoryAxisMap.set('x', xAxisModel); + result.firstCategoryDimIndex = 0; + } + + if (isCategory(yAxisModel)) { + categoryAxisMap.set('y', yAxisModel); + result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1); + } + }, + singleAxis: function (seriesModel, result, axisMap, categoryAxisMap) { + var singleAxisModel = seriesModel.getReferringComponents('singleAxis', SINGLE_REFERRING).models[0]; + + if ("development" !== 'production') { + if (!singleAxisModel) { + throw new Error('singleAxis should be specified.'); + } + } + + result.coordSysDims = ['single']; + axisMap.set('single', singleAxisModel); + + if (isCategory(singleAxisModel)) { + categoryAxisMap.set('single', singleAxisModel); + result.firstCategoryDimIndex = 0; + } + }, + polar: function (seriesModel, result, axisMap, categoryAxisMap) { + var polarModel = seriesModel.getReferringComponents('polar', SINGLE_REFERRING).models[0]; + var radiusAxisModel = polarModel.findAxisModel('radiusAxis'); + var angleAxisModel = polarModel.findAxisModel('angleAxis'); + + if ("development" !== 'production') { + if (!angleAxisModel) { + throw new Error('angleAxis option not found'); + } + + if (!radiusAxisModel) { + throw new Error('radiusAxis option not found'); + } + } + + result.coordSysDims = ['radius', 'angle']; + axisMap.set('radius', radiusAxisModel); + axisMap.set('angle', angleAxisModel); + + if (isCategory(radiusAxisModel)) { + categoryAxisMap.set('radius', radiusAxisModel); + result.firstCategoryDimIndex = 0; + } + + if (isCategory(angleAxisModel)) { + categoryAxisMap.set('angle', angleAxisModel); + result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1); + } + }, + geo: function (seriesModel, result, axisMap, categoryAxisMap) { + result.coordSysDims = ['lng', 'lat']; + }, + parallel: function (seriesModel, result, axisMap, categoryAxisMap) { + var ecModel = seriesModel.ecModel; + var parallelModel = ecModel.getComponent('parallel', seriesModel.get('parallelIndex')); + var coordSysDims = result.coordSysDims = parallelModel.dimensions.slice(); + each(parallelModel.parallelAxisIndex, function (axisIndex, index) { + var axisModel = ecModel.getComponent('parallelAxis', axisIndex); + var axisDim = coordSysDims[index]; + axisMap.set(axisDim, axisModel); + + if (isCategory(axisModel)) { + categoryAxisMap.set(axisDim, axisModel); + + if (result.firstCategoryDimIndex == null) { + result.firstCategoryDimIndex = index; + } + } + }); + } + }; + + function isCategory(axisModel) { + return axisModel.get('type') === 'category'; + } + + /** + * Note that it is too complicated to support 3d stack by value + * (have to create two-dimension inverted index), so in 3d case + * we just support that stacked by index. + * + * @param seriesModel + * @param dimensionsInput The same as the input of . + * The input will be modified. + * @param opt + * @param opt.stackedCoordDimension Specify a coord dimension if needed. + * @param opt.byIndex=false + * @return calculationInfo + * { + * stackedDimension: string + * stackedByDimension: string + * isStackedByIndex: boolean + * stackedOverDimension: string + * stackResultDimension: string + * } + */ + + function enableDataStack(seriesModel, dimensionsInput, opt) { + opt = opt || {}; + var byIndex = opt.byIndex; + var stackedCoordDimension = opt.stackedCoordDimension; + var dimensionDefineList; + var schema; + var store; + + if (isLegacyDimensionsInput(dimensionsInput)) { + dimensionDefineList = dimensionsInput; + } else { + schema = dimensionsInput.schema; + dimensionDefineList = schema.dimensions; + store = dimensionsInput.store; + } // Compatibal: when `stack` is set as '', do not stack. + + + var mayStack = !!(seriesModel && seriesModel.get('stack')); + var stackedByDimInfo; + var stackedDimInfo; + var stackResultDimension; + var stackedOverDimension; + each(dimensionDefineList, function (dimensionInfo, index) { + if (isString(dimensionInfo)) { + dimensionDefineList[index] = dimensionInfo = { + name: dimensionInfo + }; + } + + if (mayStack && !dimensionInfo.isExtraCoord) { + // Find the first ordinal dimension as the stackedByDimInfo. + if (!byIndex && !stackedByDimInfo && dimensionInfo.ordinalMeta) { + stackedByDimInfo = dimensionInfo; + } // Find the first stackable dimension as the stackedDimInfo. + + + if (!stackedDimInfo && dimensionInfo.type !== 'ordinal' && dimensionInfo.type !== 'time' && (!stackedCoordDimension || stackedCoordDimension === dimensionInfo.coordDim)) { + stackedDimInfo = dimensionInfo; + } + } + }); + + if (stackedDimInfo && !byIndex && !stackedByDimInfo) { + // Compatible with previous design, value axis (time axis) only stack by index. + // It may make sense if the user provides elaborately constructed data. + byIndex = true; + } // Add stack dimension, they can be both calculated by coordinate system in `unionExtent`. + // That put stack logic in List is for using conveniently in echarts extensions, but it + // might not be a good way. + + + if (stackedDimInfo) { + // Use a weird name that not duplicated with other names. + // Also need to use seriesModel.id as postfix because different + // series may share same data store. The stack dimension needs to be distinguished. + stackResultDimension = '__\0ecstackresult_' + seriesModel.id; + stackedOverDimension = '__\0ecstackedover_' + seriesModel.id; // Create inverted index to fast query index by value. + + if (stackedByDimInfo) { + stackedByDimInfo.createInvertedIndices = true; + } + + var stackedDimCoordDim_1 = stackedDimInfo.coordDim; + var stackedDimType = stackedDimInfo.type; + var stackedDimCoordIndex_1 = 0; + each(dimensionDefineList, function (dimensionInfo) { + if (dimensionInfo.coordDim === stackedDimCoordDim_1) { + stackedDimCoordIndex_1++; + } + }); + var stackedOverDimensionDefine = { + name: stackResultDimension, + coordDim: stackedDimCoordDim_1, + coordDimIndex: stackedDimCoordIndex_1, + type: stackedDimType, + isExtraCoord: true, + isCalculationCoord: true, + storeDimIndex: dimensionDefineList.length + }; + var stackResultDimensionDefine = { + name: stackedOverDimension, + // This dimension contains stack base (generally, 0), so do not set it as + // `stackedDimCoordDim` to avoid extent calculation, consider log scale. + coordDim: stackedOverDimension, + coordDimIndex: stackedDimCoordIndex_1 + 1, + type: stackedDimType, + isExtraCoord: true, + isCalculationCoord: true, + storeDimIndex: dimensionDefineList.length + 1 + }; + + if (schema) { + if (store) { + stackedOverDimensionDefine.storeDimIndex = store.ensureCalculationDimension(stackedOverDimension, stackedDimType); + stackResultDimensionDefine.storeDimIndex = store.ensureCalculationDimension(stackResultDimension, stackedDimType); + } + + schema.appendCalculationDimension(stackedOverDimensionDefine); + schema.appendCalculationDimension(stackResultDimensionDefine); + } else { + dimensionDefineList.push(stackedOverDimensionDefine); + dimensionDefineList.push(stackResultDimensionDefine); + } + } + + return { + stackedDimension: stackedDimInfo && stackedDimInfo.name, + stackedByDimension: stackedByDimInfo && stackedByDimInfo.name, + isStackedByIndex: byIndex, + stackedOverDimension: stackedOverDimension, + stackResultDimension: stackResultDimension + }; + } + + function isLegacyDimensionsInput(dimensionsInput) { + return !isSeriesDataSchema(dimensionsInput.schema); + } + + function isDimensionStacked(data, stackedDim) { + // Each single series only maps to one pair of axis. So we do not need to + // check stackByDim, whatever stacked by a dimension or stacked by index. + return !!stackedDim && stackedDim === data.getCalculationInfo('stackedDimension'); + } + function getStackedDimension(data, targetDim) { + return isDimensionStacked(data, targetDim) ? data.getCalculationInfo('stackResultDimension') : targetDim; + } + + function getCoordSysDimDefs(seriesModel, coordSysInfo) { + var coordSysName = seriesModel.get('coordinateSystem'); + var registeredCoordSys = CoordinateSystemManager.get(coordSysName); + var coordSysDimDefs; + + if (coordSysInfo && coordSysInfo.coordSysDims) { + coordSysDimDefs = map(coordSysInfo.coordSysDims, function (dim) { + var dimInfo = { + name: dim + }; + var axisModel = coordSysInfo.axisMap.get(dim); + + if (axisModel) { + var axisType = axisModel.get('type'); + dimInfo.type = getDimensionTypeByAxis(axisType); + } + + return dimInfo; + }); + } + + if (!coordSysDimDefs) { + // Get dimensions from registered coordinate system + coordSysDimDefs = registeredCoordSys && (registeredCoordSys.getDimensionsInfo ? registeredCoordSys.getDimensionsInfo() : registeredCoordSys.dimensions.slice()) || ['x', 'y']; + } + + return coordSysDimDefs; + } + + function injectOrdinalMeta(dimInfoList, createInvertedIndices, coordSysInfo) { + var firstCategoryDimIndex; + var hasNameEncode; + coordSysInfo && each(dimInfoList, function (dimInfo, dimIndex) { + var coordDim = dimInfo.coordDim; + var categoryAxisModel = coordSysInfo.categoryAxisMap.get(coordDim); + + if (categoryAxisModel) { + if (firstCategoryDimIndex == null) { + firstCategoryDimIndex = dimIndex; + } + + dimInfo.ordinalMeta = categoryAxisModel.getOrdinalMeta(); + + if (createInvertedIndices) { + dimInfo.createInvertedIndices = true; + } + } + + if (dimInfo.otherDims.itemName != null) { + hasNameEncode = true; + } + }); + + if (!hasNameEncode && firstCategoryDimIndex != null) { + dimInfoList[firstCategoryDimIndex].otherDims.itemName = 0; + } + + return firstCategoryDimIndex; + } + /** + * Caution: there are side effects to `sourceManager` in this method. + * Should better only be called in `Series['getInitialData']`. + */ + + + function createSeriesData(sourceRaw, seriesModel, opt) { + opt = opt || {}; + var sourceManager = seriesModel.getSourceManager(); + var source; + var isOriginalSource = false; + + if (sourceRaw) { + isOriginalSource = true; + source = createSourceFromSeriesDataOption(sourceRaw); + } else { + source = sourceManager.getSource(); // Is series.data. not dataset. + + isOriginalSource = source.sourceFormat === SOURCE_FORMAT_ORIGINAL; + } + + var coordSysInfo = getCoordSysInfoBySeries(seriesModel); + var coordSysDimDefs = getCoordSysDimDefs(seriesModel, coordSysInfo); + var useEncodeDefaulter = opt.useEncodeDefaulter; + var encodeDefaulter = isFunction(useEncodeDefaulter) ? useEncodeDefaulter : useEncodeDefaulter ? curry(makeSeriesEncodeForAxisCoordSys, coordSysDimDefs, seriesModel) : null; + var createDimensionOptions = { + coordDimensions: coordSysDimDefs, + generateCoord: opt.generateCoord, + encodeDefine: seriesModel.getEncode(), + encodeDefaulter: encodeDefaulter, + canOmitUnusedDimensions: !isOriginalSource + }; + var schema = prepareSeriesDataSchema(source, createDimensionOptions); + var firstCategoryDimIndex = injectOrdinalMeta(schema.dimensions, opt.createInvertedIndices, coordSysInfo); + var store = !isOriginalSource ? sourceManager.getSharedDataStore(schema) : null; + var stackCalculationInfo = enableDataStack(seriesModel, { + schema: schema, + store: store + }); + var data = new SeriesData(schema, seriesModel); + data.setCalculationInfo(stackCalculationInfo); + var dimValueGetter = firstCategoryDimIndex != null && isNeedCompleteOrdinalData(source) ? function (itemOpt, dimName, dataIndex, dimIndex) { + // Use dataIndex as ordinal value in categoryAxis + return dimIndex === firstCategoryDimIndex ? dataIndex : this.defaultDimValueGetter(itemOpt, dimName, dataIndex, dimIndex); + } : null; + data.hasItemOption = false; + data.initData( // Try to reuse the data store in sourceManager if using dataset. + isOriginalSource ? source : store, null, dimValueGetter); + return data; + } + + function isNeedCompleteOrdinalData(source) { + if (source.sourceFormat === SOURCE_FORMAT_ORIGINAL) { + var sampleItem = firstDataNotNull(source.data || []); + return !isArray(getDataItemValue(sampleItem)); + } + } + + function firstDataNotNull(arr) { + var i = 0; + + while (i < arr.length && arr[i] == null) { + i++; + } + + return arr[i]; + } + + var Scale = + /** @class */ + function () { + function Scale(setting) { + this._setting = setting || {}; + this._extent = [Infinity, -Infinity]; + } + + Scale.prototype.getSetting = function (name) { + return this._setting[name]; + }; + /** + * Set extent from data + */ + + + Scale.prototype.unionExtent = function (other) { + var extent = this._extent; + other[0] < extent[0] && (extent[0] = other[0]); + other[1] > extent[1] && (extent[1] = other[1]); // not setExtent because in log axis it may transformed to power + // this.setExtent(extent[0], extent[1]); + }; + /** + * Set extent from data + */ + + + Scale.prototype.unionExtentFromData = function (data, dim) { + this.unionExtent(data.getApproximateExtent(dim)); + }; + /** + * Get extent + * + * Extent is always in increase order. + */ + + + Scale.prototype.getExtent = function () { + return this._extent.slice(); + }; + /** + * Set extent + */ + + + Scale.prototype.setExtent = function (start, end) { + var thisExtent = this._extent; + + if (!isNaN(start)) { + thisExtent[0] = start; + } + + if (!isNaN(end)) { + thisExtent[1] = end; + } + }; + /** + * If value is in extent range + */ + + + Scale.prototype.isInExtentRange = function (value) { + return this._extent[0] <= value && this._extent[1] >= value; + }; + /** + * When axis extent depends on data and no data exists, + * axis ticks should not be drawn, which is named 'blank'. + */ + + + Scale.prototype.isBlank = function () { + return this._isBlank; + }; + /** + * When axis extent depends on data and no data exists, + * axis ticks should not be drawn, which is named 'blank'. + */ + + + Scale.prototype.setBlank = function (isBlank) { + this._isBlank = isBlank; + }; + + return Scale; + }(); + + enableClassManagement(Scale); + + var uidBase = 0; + + var OrdinalMeta = + /** @class */ + function () { + function OrdinalMeta(opt) { + this.categories = opt.categories || []; + this._needCollect = opt.needCollect; + this._deduplication = opt.deduplication; + this.uid = ++uidBase; + } + + OrdinalMeta.createByAxisModel = function (axisModel) { + var option = axisModel.option; + var data = option.data; + var categories = data && map(data, getName); + return new OrdinalMeta({ + categories: categories, + needCollect: !categories, + // deduplication is default in axis. + deduplication: option.dedplication !== false + }); + }; + + OrdinalMeta.prototype.getOrdinal = function (category) { + // @ts-ignore + return this._getOrCreateMap().get(category); + }; + /** + * @return The ordinal. If not found, return NaN. + */ + + + OrdinalMeta.prototype.parseAndCollect = function (category) { + var index; + var needCollect = this._needCollect; // The value of category dim can be the index of the given category set. + // This feature is only supported when !needCollect, because we should + // consider a common case: a value is 2017, which is a number but is + // expected to be tread as a category. This case usually happen in dataset, + // where it happent to be no need of the index feature. + + if (!isString(category) && !needCollect) { + return category; + } // Optimize for the scenario: + // category is ['2012-01-01', '2012-01-02', ...], where the input + // data has been ensured not duplicate and is large data. + // Notice, if a dataset dimension provide categroies, usually echarts + // should remove duplication except user tell echarts dont do that + // (set axis.deduplication = false), because echarts do not know whether + // the values in the category dimension has duplication (consider the + // parallel-aqi example) + + + if (needCollect && !this._deduplication) { + index = this.categories.length; + this.categories[index] = category; + return index; + } + + var map = this._getOrCreateMap(); // @ts-ignore + + + index = map.get(category); + + if (index == null) { + if (needCollect) { + index = this.categories.length; + this.categories[index] = category; // @ts-ignore + + map.set(category, index); + } else { + index = NaN; + } + } + + return index; + }; // Consider big data, do not create map until needed. + + + OrdinalMeta.prototype._getOrCreateMap = function () { + return this._map || (this._map = createHashMap(this.categories)); + }; + + return OrdinalMeta; + }(); + + function getName(obj) { + if (isObject(obj) && obj.value != null) { + return obj.value; + } else { + return obj + ''; + } + } + + function isValueNice(val) { + var exp10 = Math.pow(10, quantityExponent(Math.abs(val))); + var f = Math.abs(val / exp10); + return f === 0 || f === 1 || f === 2 || f === 3 || f === 5; + } + function isIntervalOrLogScale(scale) { + return scale.type === 'interval' || scale.type === 'log'; + } + /** + * @param extent Both extent[0] and extent[1] should be valid number. + * Should be extent[0] < extent[1]. + * @param splitNumber splitNumber should be >= 1. + */ + + function intervalScaleNiceTicks(extent, splitNumber, minInterval, maxInterval) { + var result = {}; + var span = extent[1] - extent[0]; + var interval = result.interval = nice(span / splitNumber, true); + + if (minInterval != null && interval < minInterval) { + interval = result.interval = minInterval; + } + + if (maxInterval != null && interval > maxInterval) { + interval = result.interval = maxInterval; + } // Tow more digital for tick. + + + var precision = result.intervalPrecision = getIntervalPrecision(interval); // Niced extent inside original extent + + var niceTickExtent = result.niceTickExtent = [round(Math.ceil(extent[0] / interval) * interval, precision), round(Math.floor(extent[1] / interval) * interval, precision)]; + fixExtent(niceTickExtent, extent); + return result; + } + function increaseInterval(interval) { + var exp10 = Math.pow(10, quantityExponent(interval)); // Increase interval + + var f = interval / exp10; + + if (!f) { + f = 1; + } else if (f === 2) { + f = 3; + } else if (f === 3) { + f = 5; + } else { + // f is 1 or 5 + f *= 2; + } + + return round(f * exp10); + } + /** + * @return interval precision + */ + + function getIntervalPrecision(interval) { + // Tow more digital for tick. + return getPrecision(interval) + 2; + } + + function clamp(niceTickExtent, idx, extent) { + niceTickExtent[idx] = Math.max(Math.min(niceTickExtent[idx], extent[1]), extent[0]); + } // In some cases (e.g., splitNumber is 1), niceTickExtent may be out of extent. + + + function fixExtent(niceTickExtent, extent) { + !isFinite(niceTickExtent[0]) && (niceTickExtent[0] = extent[0]); + !isFinite(niceTickExtent[1]) && (niceTickExtent[1] = extent[1]); + clamp(niceTickExtent, 0, extent); + clamp(niceTickExtent, 1, extent); + + if (niceTickExtent[0] > niceTickExtent[1]) { + niceTickExtent[0] = niceTickExtent[1]; + } + } + function contain$1(val, extent) { + return val >= extent[0] && val <= extent[1]; + } + function normalize$1(val, extent) { + if (extent[1] === extent[0]) { + return 0.5; + } + + return (val - extent[0]) / (extent[1] - extent[0]); + } + function scale$2(val, extent) { + return val * (extent[1] - extent[0]) + extent[0]; + } + + var OrdinalScale = + /** @class */ + function (_super) { + __extends(OrdinalScale, _super); + + function OrdinalScale(setting) { + var _this = _super.call(this, setting) || this; + + _this.type = 'ordinal'; + + var ordinalMeta = _this.getSetting('ordinalMeta'); // Caution: Should not use instanceof, consider ec-extensions using + // import approach to get OrdinalMeta class. + + + if (!ordinalMeta) { + ordinalMeta = new OrdinalMeta({}); + } + + if (isArray(ordinalMeta)) { + ordinalMeta = new OrdinalMeta({ + categories: map(ordinalMeta, function (item) { + return isObject(item) ? item.value : item; + }) + }); + } + + _this._ordinalMeta = ordinalMeta; + _this._extent = _this.getSetting('extent') || [0, ordinalMeta.categories.length - 1]; + return _this; + } + + OrdinalScale.prototype.parse = function (val) { + // Caution: Math.round(null) will return `0` rather than `NaN` + if (val == null) { + return NaN; + } + + return isString(val) ? this._ordinalMeta.getOrdinal(val) // val might be float. + : Math.round(val); + }; + + OrdinalScale.prototype.contain = function (rank) { + rank = this.parse(rank); + return contain$1(rank, this._extent) && this._ordinalMeta.categories[rank] != null; + }; + /** + * Normalize given rank or name to linear [0, 1] + * @param val raw ordinal number. + * @return normalized value in [0, 1]. + */ + + + OrdinalScale.prototype.normalize = function (val) { + val = this._getTickNumber(this.parse(val)); + return normalize$1(val, this._extent); + }; + /** + * @param val normalized value in [0, 1]. + * @return raw ordinal number. + */ + + + OrdinalScale.prototype.scale = function (val) { + val = Math.round(scale$2(val, this._extent)); + return this.getRawOrdinalNumber(val); + }; + + OrdinalScale.prototype.getTicks = function () { + var ticks = []; + var extent = this._extent; + var rank = extent[0]; + + while (rank <= extent[1]) { + ticks.push({ + value: rank + }); + rank++; + } + + return ticks; + }; + + OrdinalScale.prototype.getMinorTicks = function (splitNumber) { + // Not support. + return; + }; + /** + * @see `Ordinal['_ordinalNumbersByTick']` + */ + + + OrdinalScale.prototype.setSortInfo = function (info) { + if (info == null) { + this._ordinalNumbersByTick = this._ticksByOrdinalNumber = null; + return; + } + + var infoOrdinalNumbers = info.ordinalNumbers; + var ordinalsByTick = this._ordinalNumbersByTick = []; + var ticksByOrdinal = this._ticksByOrdinalNumber = []; // Unnecessary support negative tick in `realtimeSort`. + + var tickNum = 0; + var allCategoryLen = this._ordinalMeta.categories.length; + + for (var len = Math.min(allCategoryLen, infoOrdinalNumbers.length); tickNum < len; ++tickNum) { + var ordinalNumber = infoOrdinalNumbers[tickNum]; + ordinalsByTick[tickNum] = ordinalNumber; + ticksByOrdinal[ordinalNumber] = tickNum; + } // Handle that `series.data` only covers part of the `axis.category.data`. + + + var unusedOrdinal = 0; + + for (; tickNum < allCategoryLen; ++tickNum) { + while (ticksByOrdinal[unusedOrdinal] != null) { + unusedOrdinal++; + } + ordinalsByTick.push(unusedOrdinal); + ticksByOrdinal[unusedOrdinal] = tickNum; + } + }; + + OrdinalScale.prototype._getTickNumber = function (ordinal) { + var ticksByOrdinalNumber = this._ticksByOrdinalNumber; // also support ordinal out of range of `ordinalMeta.categories.length`, + // where ordinal numbers are used as tick value directly. + + return ticksByOrdinalNumber && ordinal >= 0 && ordinal < ticksByOrdinalNumber.length ? ticksByOrdinalNumber[ordinal] : ordinal; + }; + /** + * @usage + * ```js + * const ordinalNumber = ordinalScale.getRawOrdinalNumber(tickVal); + * + * // case0 + * const rawOrdinalValue = axisModel.getCategories()[ordinalNumber]; + * // case1 + * const rawOrdinalValue = this._ordinalMeta.categories[ordinalNumber]; + * // case2 + * const coord = axis.dataToCoord(ordinalNumber); + * ``` + * + * @param {OrdinalNumber} tickNumber index of display + */ + + + OrdinalScale.prototype.getRawOrdinalNumber = function (tickNumber) { + var ordinalNumbersByTick = this._ordinalNumbersByTick; // tickNumber may be out of range, e.g., when axis max is larger than `ordinalMeta.categories.length`., + // where ordinal numbers are used as tick value directly. + + return ordinalNumbersByTick && tickNumber >= 0 && tickNumber < ordinalNumbersByTick.length ? ordinalNumbersByTick[tickNumber] : tickNumber; + }; + /** + * Get item on tick + */ + + + OrdinalScale.prototype.getLabel = function (tick) { + if (!this.isBlank()) { + var ordinalNumber = this.getRawOrdinalNumber(tick.value); + var cateogry = this._ordinalMeta.categories[ordinalNumber]; // Note that if no data, ordinalMeta.categories is an empty array. + // Return empty if it's not exist. + + return cateogry == null ? '' : cateogry + ''; + } + }; + + OrdinalScale.prototype.count = function () { + return this._extent[1] - this._extent[0] + 1; + }; + + OrdinalScale.prototype.unionExtentFromData = function (data, dim) { + this.unionExtent(data.getApproximateExtent(dim)); + }; + /** + * @override + * If value is in extent range + */ + + + OrdinalScale.prototype.isInExtentRange = function (value) { + value = this._getTickNumber(value); + return this._extent[0] <= value && this._extent[1] >= value; + }; + + OrdinalScale.prototype.getOrdinalMeta = function () { + return this._ordinalMeta; + }; + + OrdinalScale.prototype.calcNiceTicks = function () {}; + + OrdinalScale.prototype.calcNiceExtent = function () {}; + + OrdinalScale.type = 'ordinal'; + return OrdinalScale; + }(Scale); + + Scale.registerClass(OrdinalScale); + + var roundNumber = round; + + var IntervalScale = + /** @class */ + function (_super) { + __extends(IntervalScale, _super); + + function IntervalScale() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'interval'; // Step is calculated in adjustExtent. + + _this._interval = 0; + _this._intervalPrecision = 2; + return _this; + } + + IntervalScale.prototype.parse = function (val) { + return val; + }; + + IntervalScale.prototype.contain = function (val) { + return contain$1(val, this._extent); + }; + + IntervalScale.prototype.normalize = function (val) { + return normalize$1(val, this._extent); + }; + + IntervalScale.prototype.scale = function (val) { + return scale$2(val, this._extent); + }; + + IntervalScale.prototype.setExtent = function (start, end) { + var thisExtent = this._extent; // start,end may be a Number like '25',so... + + if (!isNaN(start)) { + thisExtent[0] = parseFloat(start); + } + + if (!isNaN(end)) { + thisExtent[1] = parseFloat(end); + } + }; + + IntervalScale.prototype.unionExtent = function (other) { + var extent = this._extent; + other[0] < extent[0] && (extent[0] = other[0]); + other[1] > extent[1] && (extent[1] = other[1]); // unionExtent may called by it's sub classes + + this.setExtent(extent[0], extent[1]); + }; + + IntervalScale.prototype.getInterval = function () { + return this._interval; + }; + + IntervalScale.prototype.setInterval = function (interval) { + this._interval = interval; // Dropped auto calculated niceExtent and use user setted extent + // We assume user wan't to set both interval, min, max to get a better result + + this._niceExtent = this._extent.slice(); + this._intervalPrecision = getIntervalPrecision(interval); + }; + /** + * @param expandToNicedExtent Whether expand the ticks to niced extent. + */ + + + IntervalScale.prototype.getTicks = function (expandToNicedExtent) { + var interval = this._interval; + var extent = this._extent; + var niceTickExtent = this._niceExtent; + var intervalPrecision = this._intervalPrecision; + var ticks = []; // If interval is 0, return []; + + if (!interval) { + return ticks; + } // Consider this case: using dataZoom toolbox, zoom and zoom. + + + var safeLimit = 10000; + + if (extent[0] < niceTickExtent[0]) { + if (expandToNicedExtent) { + ticks.push({ + value: roundNumber(niceTickExtent[0] - interval, intervalPrecision) + }); + } else { + ticks.push({ + value: extent[0] + }); + } + } + + var tick = niceTickExtent[0]; + + while (tick <= niceTickExtent[1]) { + ticks.push({ + value: tick + }); // Avoid rounding error + + tick = roundNumber(tick + interval, intervalPrecision); + + if (tick === ticks[ticks.length - 1].value) { + // Consider out of safe float point, e.g., + // -3711126.9907707 + 2e-10 === -3711126.9907707 + break; + } + + if (ticks.length > safeLimit) { + return []; + } + } // Consider this case: the last item of ticks is smaller + // than niceTickExtent[1] and niceTickExtent[1] === extent[1]. + + + var lastNiceTick = ticks.length ? ticks[ticks.length - 1].value : niceTickExtent[1]; + + if (extent[1] > lastNiceTick) { + if (expandToNicedExtent) { + ticks.push({ + value: roundNumber(lastNiceTick + interval, intervalPrecision) + }); + } else { + ticks.push({ + value: extent[1] + }); + } + } + + return ticks; + }; + + IntervalScale.prototype.getMinorTicks = function (splitNumber) { + var ticks = this.getTicks(true); + var minorTicks = []; + var extent = this.getExtent(); + + for (var i = 1; i < ticks.length; i++) { + var nextTick = ticks[i]; + var prevTick = ticks[i - 1]; + var count = 0; + var minorTicksGroup = []; + var interval = nextTick.value - prevTick.value; + var minorInterval = interval / splitNumber; + + while (count < splitNumber - 1) { + var minorTick = roundNumber(prevTick.value + (count + 1) * minorInterval); // For the first and last interval. The count may be less than splitNumber. + + if (minorTick > extent[0] && minorTick < extent[1]) { + minorTicksGroup.push(minorTick); + } + + count++; + } + + minorTicks.push(minorTicksGroup); + } + + return minorTicks; + }; + /** + * @param opt.precision If 'auto', use nice presision. + * @param opt.pad returns 1.50 but not 1.5 if precision is 2. + */ + + + IntervalScale.prototype.getLabel = function (data, opt) { + if (data == null) { + return ''; + } + + var precision = opt && opt.precision; + + if (precision == null) { + precision = getPrecision(data.value) || 0; + } else if (precision === 'auto') { + // Should be more precise then tick. + precision = this._intervalPrecision; + } // (1) If `precision` is set, 12.005 should be display as '12.00500'. + // (2) Use roundNumber (toFixed) to avoid scientific notation like '3.5e-7'. + + + var dataNum = roundNumber(data.value, precision, true); + return addCommas(dataNum); + }; + /** + * @param splitNumber By default `5`. + */ + + + IntervalScale.prototype.calcNiceTicks = function (splitNumber, minInterval, maxInterval) { + splitNumber = splitNumber || 5; + var extent = this._extent; + var span = extent[1] - extent[0]; + + if (!isFinite(span)) { + return; + } // User may set axis min 0 and data are all negative + // FIXME If it needs to reverse ? + + + if (span < 0) { + span = -span; + extent.reverse(); + } + + var result = intervalScaleNiceTicks(extent, splitNumber, minInterval, maxInterval); + this._intervalPrecision = result.intervalPrecision; + this._interval = result.interval; + this._niceExtent = result.niceTickExtent; + }; + + IntervalScale.prototype.calcNiceExtent = function (opt) { + var extent = this._extent; // If extent start and end are same, expand them + + if (extent[0] === extent[1]) { + if (extent[0] !== 0) { + // Expand extent + var expandSize = extent[0]; // In the fowllowing case + // Axis has been fixed max 100 + // Plus data are all 100 and axis extent are [100, 100]. + // Extend to the both side will cause expanded max is larger than fixed max. + // So only expand to the smaller side. + + if (!opt.fixMax) { + extent[1] += expandSize / 2; + extent[0] -= expandSize / 2; + } else { + extent[0] -= expandSize / 2; + } + } else { + extent[1] = 1; + } + } + + var span = extent[1] - extent[0]; // If there are no data and extent are [Infinity, -Infinity] + + if (!isFinite(span)) { + extent[0] = 0; + extent[1] = 1; + } + + this.calcNiceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval); // let extent = this._extent; + + var interval = this._interval; + + if (!opt.fixMin) { + extent[0] = roundNumber(Math.floor(extent[0] / interval) * interval); + } + + if (!opt.fixMax) { + extent[1] = roundNumber(Math.ceil(extent[1] / interval) * interval); + } + }; + + IntervalScale.prototype.setNiceExtent = function (min, max) { + this._niceExtent = [min, max]; + }; + + IntervalScale.type = 'interval'; + return IntervalScale; + }(Scale); + + Scale.registerClass(IntervalScale); + + /* global Float32Array */ + + var supportFloat32Array = typeof Float32Array !== 'undefined'; + var Float32ArrayCtor = !supportFloat32Array ? Array : Float32Array; + function createFloat32Array(arg) { + if (isArray(arg)) { + // Return self directly if don't support TypedArray. + return supportFloat32Array ? new Float32Array(arg) : arg; + } // Else is number + + + return new Float32ArrayCtor(arg); + } + + var STACK_PREFIX = '__ec_stack_'; + + function getSeriesStackId(seriesModel) { + return seriesModel.get('stack') || STACK_PREFIX + seriesModel.seriesIndex; + } + + function getAxisKey(axis) { + return axis.dim + axis.index; + } + /** + * @return {Object} {width, offset, offsetCenter} If axis.type is not 'category', return undefined. + */ + + + function getLayoutOnAxis(opt) { + var params = []; + var baseAxis = opt.axis; + var axisKey = 'axis0'; + + if (baseAxis.type !== 'category') { + return; + } + + var bandWidth = baseAxis.getBandWidth(); + + for (var i = 0; i < opt.count || 0; i++) { + params.push(defaults({ + bandWidth: bandWidth, + axisKey: axisKey, + stackId: STACK_PREFIX + i + }, opt)); + } + + var widthAndOffsets = doCalBarWidthAndOffset(params); + var result = []; + + for (var i = 0; i < opt.count; i++) { + var item = widthAndOffsets[axisKey][STACK_PREFIX + i]; + item.offsetCenter = item.offset + item.width / 2; + result.push(item); + } + + return result; + } + function prepareLayoutBarSeries(seriesType, ecModel) { + var seriesModels = []; + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + // Check series coordinate, do layout for cartesian2d only + if (isOnCartesian(seriesModel)) { + seriesModels.push(seriesModel); + } + }); + return seriesModels; + } + /** + * Map from (baseAxis.dim + '_' + baseAxis.index) to min gap of two adjacent + * values. + * This works for time axes, value axes, and log axes. + * For a single time axis, return value is in the form like + * {'x_0': [1000000]}. + * The value of 1000000 is in milliseconds. + */ + + function getValueAxesMinGaps(barSeries) { + /** + * Map from axis.index to values. + * For a single time axis, axisValues is in the form like + * {'x_0': [1495555200000, 1495641600000, 1495728000000]}. + * Items in axisValues[x], e.g. 1495555200000, are time values of all + * series. + */ + var axisValues = {}; + each(barSeries, function (seriesModel) { + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + + if (baseAxis.type !== 'time' && baseAxis.type !== 'value') { + return; + } + + var data = seriesModel.getData(); + var key = baseAxis.dim + '_' + baseAxis.index; + var dimIdx = data.getDimensionIndex(data.mapDimension(baseAxis.dim)); + var store = data.getStore(); + + for (var i = 0, cnt = store.count(); i < cnt; ++i) { + var value = store.get(dimIdx, i); + + if (!axisValues[key]) { + // No previous data for the axis + axisValues[key] = [value]; + } else { + // No value in previous series + axisValues[key].push(value); + } // Ignore duplicated time values in the same axis + + } + }); + var axisMinGaps = {}; + + for (var key in axisValues) { + if (axisValues.hasOwnProperty(key)) { + var valuesInAxis = axisValues[key]; + + if (valuesInAxis) { + // Sort axis values into ascending order to calculate gaps + valuesInAxis.sort(function (a, b) { + return a - b; + }); + var min = null; + + for (var j = 1; j < valuesInAxis.length; ++j) { + var delta = valuesInAxis[j] - valuesInAxis[j - 1]; + + if (delta > 0) { + // Ignore 0 delta because they are of the same axis value + min = min === null ? delta : Math.min(min, delta); + } + } // Set to null if only have one data + + + axisMinGaps[key] = min; + } + } + } + + return axisMinGaps; + } + + function makeColumnLayout(barSeries) { + var axisMinGaps = getValueAxesMinGaps(barSeries); + var seriesInfoList = []; + each(barSeries, function (seriesModel) { + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + var axisExtent = baseAxis.getExtent(); + var bandWidth; + + if (baseAxis.type === 'category') { + bandWidth = baseAxis.getBandWidth(); + } else if (baseAxis.type === 'value' || baseAxis.type === 'time') { + var key = baseAxis.dim + '_' + baseAxis.index; + var minGap = axisMinGaps[key]; + var extentSpan = Math.abs(axisExtent[1] - axisExtent[0]); + var scale = baseAxis.scale.getExtent(); + var scaleSpan = Math.abs(scale[1] - scale[0]); + bandWidth = minGap ? extentSpan / scaleSpan * minGap : extentSpan; // When there is only one data value + } else { + var data = seriesModel.getData(); + bandWidth = Math.abs(axisExtent[1] - axisExtent[0]) / data.count(); + } + + var barWidth = parsePercent$1(seriesModel.get('barWidth'), bandWidth); + var barMaxWidth = parsePercent$1(seriesModel.get('barMaxWidth'), bandWidth); + var barMinWidth = parsePercent$1( // barMinWidth by default is 0.5 / 1 in cartesian. Because in value axis, + // the auto-calculated bar width might be less than 0.5 / 1. + seriesModel.get('barMinWidth') || (isInLargeMode(seriesModel) ? 0.5 : 1), bandWidth); + var barGap = seriesModel.get('barGap'); + var barCategoryGap = seriesModel.get('barCategoryGap'); + seriesInfoList.push({ + bandWidth: bandWidth, + barWidth: barWidth, + barMaxWidth: barMaxWidth, + barMinWidth: barMinWidth, + barGap: barGap, + barCategoryGap: barCategoryGap, + axisKey: getAxisKey(baseAxis), + stackId: getSeriesStackId(seriesModel) + }); + }); + return doCalBarWidthAndOffset(seriesInfoList); + } + + function doCalBarWidthAndOffset(seriesInfoList) { + // Columns info on each category axis. Key is cartesian name + var columnsMap = {}; + each(seriesInfoList, function (seriesInfo, idx) { + var axisKey = seriesInfo.axisKey; + var bandWidth = seriesInfo.bandWidth; + var columnsOnAxis = columnsMap[axisKey] || { + bandWidth: bandWidth, + remainedWidth: bandWidth, + autoWidthCount: 0, + categoryGap: null, + gap: '20%', + stacks: {} + }; + var stacks = columnsOnAxis.stacks; + columnsMap[axisKey] = columnsOnAxis; + var stackId = seriesInfo.stackId; + + if (!stacks[stackId]) { + columnsOnAxis.autoWidthCount++; + } + + stacks[stackId] = stacks[stackId] || { + width: 0, + maxWidth: 0 + }; // Caution: In a single coordinate system, these barGrid attributes + // will be shared by series. Consider that they have default values, + // only the attributes set on the last series will work. + // Do not change this fact unless there will be a break change. + + var barWidth = seriesInfo.barWidth; + + if (barWidth && !stacks[stackId].width) { + // See #6312, do not restrict width. + stacks[stackId].width = barWidth; + barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth); + columnsOnAxis.remainedWidth -= barWidth; + } + + var barMaxWidth = seriesInfo.barMaxWidth; + barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth); + var barMinWidth = seriesInfo.barMinWidth; + barMinWidth && (stacks[stackId].minWidth = barMinWidth); + var barGap = seriesInfo.barGap; + barGap != null && (columnsOnAxis.gap = barGap); + var barCategoryGap = seriesInfo.barCategoryGap; + barCategoryGap != null && (columnsOnAxis.categoryGap = barCategoryGap); + }); + var result = {}; + each(columnsMap, function (columnsOnAxis, coordSysName) { + result[coordSysName] = {}; + var stacks = columnsOnAxis.stacks; + var bandWidth = columnsOnAxis.bandWidth; + var categoryGapPercent = columnsOnAxis.categoryGap; + + if (categoryGapPercent == null) { + var columnCount = keys(stacks).length; // More columns in one group + // the spaces between group is smaller. Or the column will be too thin. + + categoryGapPercent = Math.max(35 - columnCount * 4, 15) + '%'; + } + + var categoryGap = parsePercent$1(categoryGapPercent, bandWidth); + var barGapPercent = parsePercent$1(columnsOnAxis.gap, 1); + var remainedWidth = columnsOnAxis.remainedWidth; + var autoWidthCount = columnsOnAxis.autoWidthCount; + var autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); // Find if any auto calculated bar exceeded maxBarWidth + + each(stacks, function (column) { + var maxWidth = column.maxWidth; + var minWidth = column.minWidth; + + if (!column.width) { + var finalWidth = autoWidth; + + if (maxWidth && maxWidth < finalWidth) { + finalWidth = Math.min(maxWidth, remainedWidth); + } // `minWidth` has higher priority. `minWidth` decide that wheter the + // bar is able to be visible. So `minWidth` should not be restricted + // by `maxWidth` or `remainedWidth` (which is from `bandWidth`). In + // the extreme cases for `value` axis, bars are allowed to overlap + // with each other if `minWidth` specified. + + + if (minWidth && minWidth > finalWidth) { + finalWidth = minWidth; + } + + if (finalWidth !== autoWidth) { + column.width = finalWidth; + remainedWidth -= finalWidth + barGapPercent * finalWidth; + autoWidthCount--; + } + } else { + // `barMinWidth/barMaxWidth` has higher priority than `barWidth`, as + // CSS does. Becuase barWidth can be a percent value, where + // `barMaxWidth` can be used to restrict the final width. + var finalWidth = column.width; + + if (maxWidth) { + finalWidth = Math.min(finalWidth, maxWidth); + } // `minWidth` has higher priority, as described above + + + if (minWidth) { + finalWidth = Math.max(finalWidth, minWidth); + } + + column.width = finalWidth; + remainedWidth -= finalWidth + barGapPercent * finalWidth; + autoWidthCount--; + } + }); // Recalculate width again + + autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + var widthSum = 0; + var lastColumn; + each(stacks, function (column, idx) { + if (!column.width) { + column.width = autoWidth; + } + + lastColumn = column; + widthSum += column.width * (1 + barGapPercent); + }); + + if (lastColumn) { + widthSum -= lastColumn.width * barGapPercent; + } + + var offset = -widthSum / 2; + each(stacks, function (column, stackId) { + result[coordSysName][stackId] = result[coordSysName][stackId] || { + bandWidth: bandWidth, + offset: offset, + width: column.width + }; + offset += column.width * (1 + barGapPercent); + }); + }); + return result; + } + + function retrieveColumnLayout(barWidthAndOffset, axis, seriesModel) { + if (barWidthAndOffset && axis) { + var result = barWidthAndOffset[getAxisKey(axis)]; + + if (result != null && seriesModel != null) { + return result[getSeriesStackId(seriesModel)]; + } + + return result; + } + } + function layout(seriesType, ecModel) { + var seriesModels = prepareLayoutBarSeries(seriesType, ecModel); + var barWidthAndOffset = makeColumnLayout(seriesModels); + each(seriesModels, function (seriesModel) { + var data = seriesModel.getData(); + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + var stackId = getSeriesStackId(seriesModel); + var columnLayoutInfo = barWidthAndOffset[getAxisKey(baseAxis)][stackId]; + var columnOffset = columnLayoutInfo.offset; + var columnWidth = columnLayoutInfo.width; + data.setLayout({ + bandWidth: columnLayoutInfo.bandWidth, + offset: columnOffset, + size: columnWidth + }); + }); + } // TODO: Do not support stack in large mode yet. + + function createProgressiveLayout(seriesType) { + return { + seriesType: seriesType, + plan: createRenderPlanner(), + reset: function (seriesModel) { + if (!isOnCartesian(seriesModel)) { + return; + } + + var data = seriesModel.getData(); + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + var valueAxis = cartesian.getOtherAxis(baseAxis); + var valueDimIdx = data.getDimensionIndex(data.mapDimension(valueAxis.dim)); + var baseDimIdx = data.getDimensionIndex(data.mapDimension(baseAxis.dim)); + var drawBackground = seriesModel.get('showBackground', true); + var valueDim = data.mapDimension(valueAxis.dim); + var stackResultDim = data.getCalculationInfo('stackResultDimension'); + var stacked = isDimensionStacked(data, valueDim) && !!data.getCalculationInfo('stackedOnSeries'); + var isValueAxisH = valueAxis.isHorizontal(); + var valueAxisStart = getValueAxisStart(baseAxis, valueAxis); + var isLarge = isInLargeMode(seriesModel); + var barMinHeight = seriesModel.get('barMinHeight') || 0; + var stackedDimIdx = stackResultDim && data.getDimensionIndex(stackResultDim); // Layout info. + + var columnWidth = data.getLayout('size'); + var columnOffset = data.getLayout('offset'); + return { + progress: function (params, data) { + var count = params.count; + var largePoints = isLarge && createFloat32Array(count * 3); + var largeBackgroundPoints = isLarge && drawBackground && createFloat32Array(count * 3); + var largeDataIndices = isLarge && createFloat32Array(count); + var coordLayout = cartesian.master.getRect(); + var bgSize = isValueAxisH ? coordLayout.width : coordLayout.height; + var dataIndex; + var store = data.getStore(); + var idxOffset = 0; + + while ((dataIndex = params.next()) != null) { + var value = store.get(stacked ? stackedDimIdx : valueDimIdx, dataIndex); + var baseValue = store.get(baseDimIdx, dataIndex); + var baseCoord = valueAxisStart; + var startValue = void 0; // Because of the barMinHeight, we can not use the value in + // stackResultDimension directly. + + if (stacked) { + startValue = +value - store.get(valueDimIdx, dataIndex); + } + + var x = void 0; + var y = void 0; + var width = void 0; + var height = void 0; + + if (isValueAxisH) { + var coord = cartesian.dataToPoint([value, baseValue]); + + if (stacked) { + var startCoord = cartesian.dataToPoint([startValue, baseValue]); + baseCoord = startCoord[0]; + } + + x = baseCoord; + y = coord[1] + columnOffset; + width = coord[0] - baseCoord; + height = columnWidth; + + if (Math.abs(width) < barMinHeight) { + width = (width < 0 ? -1 : 1) * barMinHeight; + } + } else { + var coord = cartesian.dataToPoint([baseValue, value]); + + if (stacked) { + var startCoord = cartesian.dataToPoint([baseValue, startValue]); + baseCoord = startCoord[1]; + } + + x = coord[0] + columnOffset; + y = baseCoord; + width = columnWidth; + height = coord[1] - baseCoord; + + if (Math.abs(height) < barMinHeight) { + // Include zero to has a positive bar + height = (height <= 0 ? -1 : 1) * barMinHeight; + } + } + + if (!isLarge) { + data.setItemLayout(dataIndex, { + x: x, + y: y, + width: width, + height: height + }); + } else { + largePoints[idxOffset] = x; + largePoints[idxOffset + 1] = y; + largePoints[idxOffset + 2] = isValueAxisH ? width : height; + + if (largeBackgroundPoints) { + largeBackgroundPoints[idxOffset] = isValueAxisH ? coordLayout.x : x; + largeBackgroundPoints[idxOffset + 1] = isValueAxisH ? y : coordLayout.y; + largeBackgroundPoints[idxOffset + 2] = bgSize; + } + + largeDataIndices[dataIndex] = dataIndex; + } + + idxOffset += 3; + } + + if (isLarge) { + data.setLayout({ + largePoints: largePoints, + largeDataIndices: largeDataIndices, + largeBackgroundPoints: largeBackgroundPoints, + valueAxisHorizontal: isValueAxisH + }); + } + } + }; + } + }; + } + + function isOnCartesian(seriesModel) { + return seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'cartesian2d'; + } + + function isInLargeMode(seriesModel) { + return seriesModel.pipelineContext && seriesModel.pipelineContext.large; + } // See cases in `test/bar-start.html` and `#7412`, `#8747`. + + + function getValueAxisStart(baseAxis, valueAxis) { + return valueAxis.toGlobalCoord(valueAxis.dataToCoord(valueAxis.type === 'log' ? 1 : 0)); + } + + var bisect = function (a, x, lo, hi) { + while (lo < hi) { + var mid = lo + hi >>> 1; + + if (a[mid][1] < x) { + lo = mid + 1; + } else { + hi = mid; + } + } + + return lo; + }; + + var TimeScale = + /** @class */ + function (_super) { + __extends(TimeScale, _super); + + function TimeScale(settings) { + var _this = _super.call(this, settings) || this; + + _this.type = 'time'; + return _this; + } + /** + * Get label is mainly for other components like dataZoom, tooltip. + */ + + + TimeScale.prototype.getLabel = function (tick) { + var useUTC = this.getSetting('useUTC'); + return format(tick.value, fullLeveledFormatter[getDefaultFormatPrecisionOfInterval(getPrimaryTimeUnit(this._minLevelUnit))] || fullLeveledFormatter.second, useUTC, this.getSetting('locale')); + }; + + TimeScale.prototype.getFormattedLabel = function (tick, idx, labelFormatter) { + var isUTC = this.getSetting('useUTC'); + var lang = this.getSetting('locale'); + return leveledFormat(tick, idx, labelFormatter, lang, isUTC); + }; + /** + * @override + */ + + + TimeScale.prototype.getTicks = function () { + var interval = this._interval; + var extent = this._extent; + var ticks = []; // If interval is 0, return []; + + if (!interval) { + return ticks; + } + + ticks.push({ + value: extent[0], + level: 0 + }); + var useUTC = this.getSetting('useUTC'); + var innerTicks = getIntervalTicks(this._minLevelUnit, this._approxInterval, useUTC, extent); + ticks = ticks.concat(innerTicks); + ticks.push({ + value: extent[1], + level: 0 + }); + return ticks; + }; + + TimeScale.prototype.calcNiceExtent = function (opt) { + var extent = this._extent; // If extent start and end are same, expand them + + if (extent[0] === extent[1]) { + // Expand extent + extent[0] -= ONE_DAY; + extent[1] += ONE_DAY; + } // If there are no data and extent are [Infinity, -Infinity] + + + if (extent[1] === -Infinity && extent[0] === Infinity) { + var d = new Date(); + extent[1] = +new Date(d.getFullYear(), d.getMonth(), d.getDate()); + extent[0] = extent[1] - ONE_DAY; + } + + this.calcNiceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval); + }; + + TimeScale.prototype.calcNiceTicks = function (approxTickNum, minInterval, maxInterval) { + approxTickNum = approxTickNum || 10; + var extent = this._extent; + var span = extent[1] - extent[0]; + this._approxInterval = span / approxTickNum; + + if (minInterval != null && this._approxInterval < minInterval) { + this._approxInterval = minInterval; + } + + if (maxInterval != null && this._approxInterval > maxInterval) { + this._approxInterval = maxInterval; + } + + var scaleIntervalsLen = scaleIntervals.length; + var idx = Math.min(bisect(scaleIntervals, this._approxInterval, 0, scaleIntervalsLen), scaleIntervalsLen - 1); // Interval that can be used to calculate ticks + + this._interval = scaleIntervals[idx][1]; // Min level used when picking ticks from top down. + // We check one more level to avoid the ticks are to sparse in some case. + + this._minLevelUnit = scaleIntervals[Math.max(idx - 1, 0)][0]; + }; + + TimeScale.prototype.parse = function (val) { + // val might be float. + return isNumber(val) ? val : +parseDate(val); + }; + + TimeScale.prototype.contain = function (val) { + return contain$1(this.parse(val), this._extent); + }; + + TimeScale.prototype.normalize = function (val) { + return normalize$1(this.parse(val), this._extent); + }; + + TimeScale.prototype.scale = function (val) { + return scale$2(val, this._extent); + }; + + TimeScale.type = 'time'; + return TimeScale; + }(IntervalScale); + /** + * This implementation was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + */ + + + var scaleIntervals = [// Format interval + ['second', ONE_SECOND], ['minute', ONE_MINUTE], ['hour', ONE_HOUR], ['quarter-day', ONE_HOUR * 6], ['half-day', ONE_HOUR * 12], ['day', ONE_DAY * 1.2], ['half-week', ONE_DAY * 3.5], ['week', ONE_DAY * 7], ['month', ONE_DAY * 31], ['quarter', ONE_DAY * 95], ['half-year', ONE_YEAR / 2], ['year', ONE_YEAR] // 1Y + ]; + + function isUnitValueSame(unit, valueA, valueB, isUTC) { + var dateA = parseDate(valueA); + var dateB = parseDate(valueB); + + var isSame = function (unit) { + return getUnitValue(dateA, unit, isUTC) === getUnitValue(dateB, unit, isUTC); + }; + + var isSameYear = function () { + return isSame('year'); + }; // const isSameHalfYear = () => isSameYear() && isSame('half-year'); + // const isSameQuater = () => isSameYear() && isSame('quarter'); + + + var isSameMonth = function () { + return isSameYear() && isSame('month'); + }; + + var isSameDay = function () { + return isSameMonth() && isSame('day'); + }; // const isSameHalfDay = () => isSameDay() && isSame('half-day'); + + + var isSameHour = function () { + return isSameDay() && isSame('hour'); + }; + + var isSameMinute = function () { + return isSameHour() && isSame('minute'); + }; + + var isSameSecond = function () { + return isSameMinute() && isSame('second'); + }; + + var isSameMilliSecond = function () { + return isSameSecond() && isSame('millisecond'); + }; + + switch (unit) { + case 'year': + return isSameYear(); + + case 'month': + return isSameMonth(); + + case 'day': + return isSameDay(); + + case 'hour': + return isSameHour(); + + case 'minute': + return isSameMinute(); + + case 'second': + return isSameSecond(); + + case 'millisecond': + return isSameMilliSecond(); + } + } // const primaryUnitGetters = { + // year: fullYearGetterName(), + // month: monthGetterName(), + // day: dateGetterName(), + // hour: hoursGetterName(), + // minute: minutesGetterName(), + // second: secondsGetterName(), + // millisecond: millisecondsGetterName() + // }; + // const primaryUnitUTCGetters = { + // year: fullYearGetterName(true), + // month: monthGetterName(true), + // day: dateGetterName(true), + // hour: hoursGetterName(true), + // minute: minutesGetterName(true), + // second: secondsGetterName(true), + // millisecond: millisecondsGetterName(true) + // }; + // function moveTick(date: Date, unitName: TimeUnit, step: number, isUTC: boolean) { + // step = step || 1; + // switch (getPrimaryTimeUnit(unitName)) { + // case 'year': + // date[fullYearSetterName(isUTC)](date[fullYearGetterName(isUTC)]() + step); + // break; + // case 'month': + // date[monthSetterName(isUTC)](date[monthGetterName(isUTC)]() + step); + // break; + // case 'day': + // date[dateSetterName(isUTC)](date[dateGetterName(isUTC)]() + step); + // break; + // case 'hour': + // date[hoursSetterName(isUTC)](date[hoursGetterName(isUTC)]() + step); + // break; + // case 'minute': + // date[minutesSetterName(isUTC)](date[minutesGetterName(isUTC)]() + step); + // break; + // case 'second': + // date[secondsSetterName(isUTC)](date[secondsGetterName(isUTC)]() + step); + // break; + // case 'millisecond': + // date[millisecondsSetterName(isUTC)](date[millisecondsGetterName(isUTC)]() + step); + // break; + // } + // return date.getTime(); + // } + // const DATE_INTERVALS = [[8, 7.5], [4, 3.5], [2, 1.5]]; + // const MONTH_INTERVALS = [[6, 5.5], [3, 2.5], [2, 1.5]]; + // const MINUTES_SECONDS_INTERVALS = [[30, 30], [20, 20], [15, 15], [10, 10], [5, 5], [2, 2]]; + + + function getDateInterval(approxInterval, daysInMonth) { + approxInterval /= ONE_DAY; + return approxInterval > 16 ? 16 // Math.floor(daysInMonth / 2) + 1 // In this case we only want one tick betwen two month. + : approxInterval > 7.5 ? 7 // TODO week 7 or day 8? + : approxInterval > 3.5 ? 4 : approxInterval > 1.5 ? 2 : 1; + } + + function getMonthInterval(approxInterval) { + var APPROX_ONE_MONTH = 30 * ONE_DAY; + approxInterval /= APPROX_ONE_MONTH; + return approxInterval > 6 ? 6 : approxInterval > 3 ? 3 : approxInterval > 2 ? 2 : 1; + } + + function getHourInterval(approxInterval) { + approxInterval /= ONE_HOUR; + return approxInterval > 12 ? 12 : approxInterval > 6 ? 6 : approxInterval > 3.5 ? 4 : approxInterval > 2 ? 2 : 1; + } + + function getMinutesAndSecondsInterval(approxInterval, isMinutes) { + approxInterval /= isMinutes ? ONE_MINUTE : ONE_SECOND; + return approxInterval > 30 ? 30 : approxInterval > 20 ? 20 : approxInterval > 15 ? 15 : approxInterval > 10 ? 10 : approxInterval > 5 ? 5 : approxInterval > 2 ? 2 : 1; + } + + function getMillisecondsInterval(approxInterval) { + return nice(approxInterval, true); + } + + function getFirstTimestampOfUnit(date, unitName, isUTC) { + var outDate = new Date(date); + + switch (getPrimaryTimeUnit(unitName)) { + case 'year': + case 'month': + outDate[monthSetterName(isUTC)](0); + + case 'day': + outDate[dateSetterName(isUTC)](1); + + case 'hour': + outDate[hoursSetterName(isUTC)](0); + + case 'minute': + outDate[minutesSetterName(isUTC)](0); + + case 'second': + outDate[secondsSetterName(isUTC)](0); + outDate[millisecondsSetterName(isUTC)](0); + } + + return outDate.getTime(); + } + + function getIntervalTicks(bottomUnitName, approxInterval, isUTC, extent) { + var safeLimit = 10000; + var unitNames = timeUnits; + var iter = 0; + + function addTicksInSpan(interval, minTimestamp, maxTimestamp, getMethodName, setMethodName, isDate, out) { + var date = new Date(minTimestamp); + var dateTime = minTimestamp; + var d = date[getMethodName](); // if (isDate) { + // d -= 1; // Starts with 0; PENDING + // } + + while (dateTime < maxTimestamp && dateTime <= extent[1]) { + out.push({ + value: dateTime + }); + d += interval; + date[setMethodName](d); + dateTime = date.getTime(); + } // This extra tick is for calcuating ticks of next level. Will not been added to the final result + + + out.push({ + value: dateTime, + notAdd: true + }); + } + + function addLevelTicks(unitName, lastLevelTicks, levelTicks) { + var newAddedTicks = []; + var isFirstLevel = !lastLevelTicks.length; + + if (isUnitValueSame(getPrimaryTimeUnit(unitName), extent[0], extent[1], isUTC)) { + return; + } + + if (isFirstLevel) { + lastLevelTicks = [{ + // TODO Optimize. Not include so may ticks. + value: getFirstTimestampOfUnit(new Date(extent[0]), unitName, isUTC) + }, { + value: extent[1] + }]; + } + + for (var i = 0; i < lastLevelTicks.length - 1; i++) { + var startTick = lastLevelTicks[i].value; + var endTick = lastLevelTicks[i + 1].value; + + if (startTick === endTick) { + continue; + } + + var interval = void 0; + var getterName = void 0; + var setterName = void 0; + var isDate = false; + + switch (unitName) { + case 'year': + interval = Math.max(1, Math.round(approxInterval / ONE_DAY / 365)); + getterName = fullYearGetterName(isUTC); + setterName = fullYearSetterName(isUTC); + break; + + case 'half-year': + case 'quarter': + case 'month': + interval = getMonthInterval(approxInterval); + getterName = monthGetterName(isUTC); + setterName = monthSetterName(isUTC); + break; + + case 'week': // PENDING If week is added. Ignore day. + + case 'half-week': + case 'day': + interval = getDateInterval(approxInterval); // Use 32 days and let interval been 16 + + getterName = dateGetterName(isUTC); + setterName = dateSetterName(isUTC); + isDate = true; + break; + + case 'half-day': + case 'quarter-day': + case 'hour': + interval = getHourInterval(approxInterval); + getterName = hoursGetterName(isUTC); + setterName = hoursSetterName(isUTC); + break; + + case 'minute': + interval = getMinutesAndSecondsInterval(approxInterval, true); + getterName = minutesGetterName(isUTC); + setterName = minutesSetterName(isUTC); + break; + + case 'second': + interval = getMinutesAndSecondsInterval(approxInterval, false); + getterName = secondsGetterName(isUTC); + setterName = secondsSetterName(isUTC); + break; + + case 'millisecond': + interval = getMillisecondsInterval(approxInterval); + getterName = millisecondsGetterName(isUTC); + setterName = millisecondsSetterName(isUTC); + break; + } + + addTicksInSpan(interval, startTick, endTick, getterName, setterName, isDate, newAddedTicks); + + if (unitName === 'year' && levelTicks.length > 1 && i === 0) { + // Add nearest years to the left extent. + levelTicks.unshift({ + value: levelTicks[0].value - interval + }); + } + } + + for (var i = 0; i < newAddedTicks.length; i++) { + levelTicks.push(newAddedTicks[i]); + } // newAddedTicks.length && console.log(unitName, newAddedTicks); + + + return newAddedTicks; + } + + var levelsTicks = []; + var currentLevelTicks = []; + var tickCount = 0; + var lastLevelTickCount = 0; + + for (var i = 0; i < unitNames.length && iter++ < safeLimit; ++i) { + var primaryTimeUnit = getPrimaryTimeUnit(unitNames[i]); + + if (!isPrimaryTimeUnit(unitNames[i])) { + // TODO + continue; + } + + addLevelTicks(unitNames[i], levelsTicks[levelsTicks.length - 1] || [], currentLevelTicks); + var nextPrimaryTimeUnit = unitNames[i + 1] ? getPrimaryTimeUnit(unitNames[i + 1]) : null; + + if (primaryTimeUnit !== nextPrimaryTimeUnit) { + if (currentLevelTicks.length) { + lastLevelTickCount = tickCount; // Remove the duplicate so the tick count can be precisely. + + currentLevelTicks.sort(function (a, b) { + return a.value - b.value; + }); + var levelTicksRemoveDuplicated = []; + + for (var i_1 = 0; i_1 < currentLevelTicks.length; ++i_1) { + var tickValue = currentLevelTicks[i_1].value; + + if (i_1 === 0 || currentLevelTicks[i_1 - 1].value !== tickValue) { + levelTicksRemoveDuplicated.push(currentLevelTicks[i_1]); + + if (tickValue >= extent[0] && tickValue <= extent[1]) { + tickCount++; + } + } + } + + var targetTickNum = (extent[1] - extent[0]) / approxInterval; // Added too much in this level and not too less in last level + + if (tickCount > targetTickNum * 1.5 && lastLevelTickCount > targetTickNum / 1.5) { + break; + } // Only treat primary time unit as one level. + + + levelsTicks.push(levelTicksRemoveDuplicated); + + if (tickCount > targetTickNum || bottomUnitName === unitNames[i]) { + break; + } + } // Reset if next unitName is primary + + + currentLevelTicks = []; + } + } + + if ("development" !== 'production') { + if (iter >= safeLimit) { + warn('Exceed safe limit.'); + } + } + + var levelsTicksInExtent = filter(map(levelsTicks, function (levelTicks) { + return filter(levelTicks, function (tick) { + return tick.value >= extent[0] && tick.value <= extent[1] && !tick.notAdd; + }); + }), function (levelTicks) { + return levelTicks.length > 0; + }); + var ticks = []; + var maxLevel = levelsTicksInExtent.length - 1; + + for (var i = 0; i < levelsTicksInExtent.length; ++i) { + var levelTicks = levelsTicksInExtent[i]; + + for (var k = 0; k < levelTicks.length; ++k) { + ticks.push({ + value: levelTicks[k].value, + level: maxLevel - i + }); + } + } + + ticks.sort(function (a, b) { + return a.value - b.value; + }); // Remove duplicates + + var result = []; + + for (var i = 0; i < ticks.length; ++i) { + if (i === 0 || ticks[i].value !== ticks[i - 1].value) { + result.push(ticks[i]); + } + } + + return result; + } + + Scale.registerClass(TimeScale); + + var scaleProto = Scale.prototype; // FIXME:TS refactor: not good to call it directly with `this`? + + var intervalScaleProto = IntervalScale.prototype; + var roundingErrorFix = round; + var mathFloor = Math.floor; + var mathCeil = Math.ceil; + var mathPow$1 = Math.pow; + var mathLog = Math.log; + + var LogScale = + /** @class */ + function (_super) { + __extends(LogScale, _super); + + function LogScale() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'log'; + _this.base = 10; + _this._originalScale = new IntervalScale(); // FIXME:TS actually used by `IntervalScale` + + _this._interval = 0; + return _this; + } + /** + * @param Whether expand the ticks to niced extent. + */ + + + LogScale.prototype.getTicks = function (expandToNicedExtent) { + var originalScale = this._originalScale; + var extent = this._extent; + var originalExtent = originalScale.getExtent(); + var ticks = intervalScaleProto.getTicks.call(this, expandToNicedExtent); + return map(ticks, function (tick) { + var val = tick.value; + var powVal = round(mathPow$1(this.base, val)); // Fix #4158 + + powVal = val === extent[0] && this._fixMin ? fixRoundingError(powVal, originalExtent[0]) : powVal; + powVal = val === extent[1] && this._fixMax ? fixRoundingError(powVal, originalExtent[1]) : powVal; + return { + value: powVal + }; + }, this); + }; + + LogScale.prototype.setExtent = function (start, end) { + var base = this.base; + start = mathLog(start) / mathLog(base); + end = mathLog(end) / mathLog(base); + intervalScaleProto.setExtent.call(this, start, end); + }; + /** + * @return {number} end + */ + + + LogScale.prototype.getExtent = function () { + var base = this.base; + var extent = scaleProto.getExtent.call(this); + extent[0] = mathPow$1(base, extent[0]); + extent[1] = mathPow$1(base, extent[1]); // Fix #4158 + + var originalScale = this._originalScale; + var originalExtent = originalScale.getExtent(); + this._fixMin && (extent[0] = fixRoundingError(extent[0], originalExtent[0])); + this._fixMax && (extent[1] = fixRoundingError(extent[1], originalExtent[1])); + return extent; + }; + + LogScale.prototype.unionExtent = function (extent) { + this._originalScale.unionExtent(extent); + + var base = this.base; + extent[0] = mathLog(extent[0]) / mathLog(base); + extent[1] = mathLog(extent[1]) / mathLog(base); + scaleProto.unionExtent.call(this, extent); + }; + + LogScale.prototype.unionExtentFromData = function (data, dim) { + // TODO + // filter value that <= 0 + this.unionExtent(data.getApproximateExtent(dim)); + }; + /** + * Update interval and extent of intervals for nice ticks + * @param approxTickNum default 10 Given approx tick number + */ + + + LogScale.prototype.calcNiceTicks = function (approxTickNum) { + approxTickNum = approxTickNum || 10; + var extent = this._extent; + var span = extent[1] - extent[0]; + + if (span === Infinity || span <= 0) { + return; + } + + var interval = quantity(span); + var err = approxTickNum / span * interval; // Filter ticks to get closer to the desired count. + + if (err <= 0.5) { + interval *= 10; + } // Interval should be integer + + + while (!isNaN(interval) && Math.abs(interval) < 1 && Math.abs(interval) > 0) { + interval *= 10; + } + + var niceExtent = [round(mathCeil(extent[0] / interval) * interval), round(mathFloor(extent[1] / interval) * interval)]; + this._interval = interval; + this._niceExtent = niceExtent; + }; + + LogScale.prototype.calcNiceExtent = function (opt) { + intervalScaleProto.calcNiceExtent.call(this, opt); + this._fixMin = opt.fixMin; + this._fixMax = opt.fixMax; + }; + + LogScale.prototype.parse = function (val) { + return val; + }; + + LogScale.prototype.contain = function (val) { + val = mathLog(val) / mathLog(this.base); + return contain$1(val, this._extent); + }; + + LogScale.prototype.normalize = function (val) { + val = mathLog(val) / mathLog(this.base); + return normalize$1(val, this._extent); + }; + + LogScale.prototype.scale = function (val) { + val = scale$2(val, this._extent); + return mathPow$1(this.base, val); + }; + + LogScale.type = 'log'; + return LogScale; + }(Scale); + + var proto = LogScale.prototype; + proto.getMinorTicks = intervalScaleProto.getMinorTicks; + proto.getLabel = intervalScaleProto.getLabel; + + function fixRoundingError(val, originalVal) { + return roundingErrorFix(val, getPrecision(originalVal)); + } + + Scale.registerClass(LogScale); + + var ScaleRawExtentInfo = + /** @class */ + function () { + function ScaleRawExtentInfo(scale, model, // Usually: data extent from all series on this axis. + originalExtent) { + this._prepareParams(scale, model, originalExtent); + } + /** + * Parameters depending on ouside (like model, user callback) + * are prepared and fixed here. + */ + + + ScaleRawExtentInfo.prototype._prepareParams = function (scale, model, // Usually: data extent from all series on this axis. + dataExtent) { + if (dataExtent[1] < dataExtent[0]) { + dataExtent = [NaN, NaN]; + } + + this._dataMin = dataExtent[0]; + this._dataMax = dataExtent[1]; + var isOrdinal = this._isOrdinal = scale.type === 'ordinal'; + this._needCrossZero = scale.type === 'interval' && model.getNeedCrossZero && model.getNeedCrossZero(); + var modelMinRaw = this._modelMinRaw = model.get('min', true); + + if (isFunction(modelMinRaw)) { + // This callback alway provide users the full data extent (before data filtered). + this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw({ + min: dataExtent[0], + max: dataExtent[1] + })); + } else if (modelMinRaw !== 'dataMin') { + this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw); + } + + var modelMaxRaw = this._modelMaxRaw = model.get('max', true); + + if (isFunction(modelMaxRaw)) { + // This callback alway provide users the full data extent (before data filtered). + this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw({ + min: dataExtent[0], + max: dataExtent[1] + })); + } else if (modelMaxRaw !== 'dataMax') { + this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw); + } + + if (isOrdinal) { + // FIXME: there is a flaw here: if there is no "block" data processor like `dataZoom`, + // and progressive rendering is using, here the category result might just only contain + // the processed chunk rather than the entire result. + this._axisDataLen = model.getCategories().length; + } else { + var boundaryGap = model.get('boundaryGap'); + var boundaryGapArr = isArray(boundaryGap) ? boundaryGap : [boundaryGap || 0, boundaryGap || 0]; + + if (typeof boundaryGapArr[0] === 'boolean' || typeof boundaryGapArr[1] === 'boolean') { + if ("development" !== 'production') { + console.warn('Boolean type for boundaryGap is only ' + 'allowed for ordinal axis. Please use string in ' + 'percentage instead, e.g., "20%". Currently, ' + 'boundaryGap is set to be 0.'); + } + + this._boundaryGapInner = [0, 0]; + } else { + this._boundaryGapInner = [parsePercent(boundaryGapArr[0], 1), parsePercent(boundaryGapArr[1], 1)]; + } + } + }; + /** + * Calculate extent by prepared parameters. + * This method has no external dependency and can be called duplicatedly, + * getting the same result. + * If parameters changed, should call this method to recalcuate. + */ + + + ScaleRawExtentInfo.prototype.calculate = function () { + // Notice: When min/max is not set (that is, when there are null/undefined, + // which is the most common case), these cases should be ensured: + // (1) For 'ordinal', show all axis.data. + // (2) For others: + // + `boundaryGap` is applied (if min/max set, boundaryGap is + // disabled). + // + If `needCrossZero`, min/max should be zero, otherwise, min/max should + // be the result that originalExtent enlarged by boundaryGap. + // (3) If no data, it should be ensured that `scale.setBlank` is set. + var isOrdinal = this._isOrdinal; + var dataMin = this._dataMin; + var dataMax = this._dataMax; + var axisDataLen = this._axisDataLen; + var boundaryGapInner = this._boundaryGapInner; + var span = !isOrdinal ? dataMax - dataMin || Math.abs(dataMin) : null; // Currently if a `'value'` axis model min is specified as 'dataMin'/'dataMax', + // `boundaryGap` will not be used. It's the different from specifying as `null`/`undefined`. + + var min = this._modelMinRaw === 'dataMin' ? dataMin : this._modelMinNum; + var max = this._modelMaxRaw === 'dataMax' ? dataMax : this._modelMaxNum; // If `_modelMinNum`/`_modelMaxNum` is `null`/`undefined`, should not be fixed. + + var minFixed = min != null; + var maxFixed = max != null; + + if (min == null) { + min = isOrdinal ? axisDataLen ? 0 : NaN : dataMin - boundaryGapInner[0] * span; + } + + if (max == null) { + max = isOrdinal ? axisDataLen ? axisDataLen - 1 : NaN : dataMax + boundaryGapInner[1] * span; + } + + (min == null || !isFinite(min)) && (min = NaN); + (max == null || !isFinite(max)) && (max = NaN); + var isBlank = eqNaN(min) || eqNaN(max) || isOrdinal && !axisDataLen; // If data extent modified, need to recalculated to ensure cross zero. + + if (this._needCrossZero) { + // Axis is over zero and min is not set + if (min > 0 && max > 0 && !minFixed) { + min = 0; // minFixed = true; + } // Axis is under zero and max is not set + + + if (min < 0 && max < 0 && !maxFixed) { + max = 0; // maxFixed = true; + } // PENDING: + // When `needCrossZero` and all data is positive/negative, should it be ensured + // that the results processed by boundaryGap are positive/negative? + // If so, here `minFixed`/`maxFixed` need to be set. + + } + + var determinedMin = this._determinedMin; + var determinedMax = this._determinedMax; + + if (determinedMin != null) { + min = determinedMin; + minFixed = true; + } + + if (determinedMax != null) { + max = determinedMax; + maxFixed = true; + } // Ensure min/max be finite number or NaN here. (not to be null/undefined) + // `NaN` means min/max axis is blank. + + + return { + min: min, + max: max, + minFixed: minFixed, + maxFixed: maxFixed, + isBlank: isBlank + }; + }; + + ScaleRawExtentInfo.prototype.modifyDataMinMax = function (minMaxName, val) { + if ("development" !== 'production') { + assert(!this.frozen); + } + + this[DATA_MIN_MAX_ATTR[minMaxName]] = val; + }; + + ScaleRawExtentInfo.prototype.setDeterminedMinMax = function (minMaxName, val) { + var attr = DETERMINED_MIN_MAX_ATTR[minMaxName]; + + if ("development" !== 'production') { + assert(!this.frozen // Earse them usually means logic flaw. + && this[attr] == null); + } + + this[attr] = val; + }; + + ScaleRawExtentInfo.prototype.freeze = function () { + // @ts-ignore + this.frozen = true; + }; + + return ScaleRawExtentInfo; + }(); + var DETERMINED_MIN_MAX_ATTR = { + min: '_determinedMin', + max: '_determinedMax' + }; + var DATA_MIN_MAX_ATTR = { + min: '_dataMin', + max: '_dataMax' + }; + /** + * Get scale min max and related info only depends on model settings. + * This method can be called after coordinate system created. + * For example, in data processing stage. + * + * Scale extent info probably be required multiple times during a workflow. + * For example: + * (1) `dataZoom` depends it to get the axis extent in "100%" state. + * (2) `processor/extentCalculator` depends it to make sure whether axis extent is specified. + * (3) `coordSys.update` use it to finally decide the scale extent. + * But the callback of `min`/`max` should not be called multiple times. + * The code below should not be implemented repeatedly either. + * So we cache the result in the scale instance, which will be recreated at the begining + * of the workflow (because `scale` instance will be recreated each round of the workflow). + */ + + function ensureScaleRawExtentInfo(scale, model, // Usually: data extent from all series on this axis. + originalExtent) { + // Do not permit to recreate. + var rawExtentInfo = scale.rawExtentInfo; + + if (rawExtentInfo) { + return rawExtentInfo; + } + + rawExtentInfo = new ScaleRawExtentInfo(scale, model, originalExtent); // @ts-ignore + + scale.rawExtentInfo = rawExtentInfo; + return rawExtentInfo; + } + function parseAxisModelMinMax(scale, minMax) { + return minMax == null ? null : eqNaN(minMax) ? NaN : scale.parse(minMax); + } + + /** + * Get axis scale extent before niced. + * Item of returned array can only be number (including Infinity and NaN). + * + * Caution: + * Precondition of calling this method: + * The scale extent has been initialized using series data extent via + * `scale.setExtent` or `scale.unionExtentFromData`; + */ + + function getScaleExtent(scale, model) { + var scaleType = scale.type; + var rawExtentResult = ensureScaleRawExtentInfo(scale, model, scale.getExtent()).calculate(); + scale.setBlank(rawExtentResult.isBlank); + var min = rawExtentResult.min; + var max = rawExtentResult.max; // If bars are placed on a base axis of type time or interval account for axis boundary overflow and current axis + // is base axis + // FIXME + // (1) Consider support value axis, where below zero and axis `onZero` should be handled properly. + // (2) Refactor the logic with `barGrid`. Is it not need to `makeBarWidthAndOffsetInfo` twice with different extent? + // Should not depend on series type `bar`? + // (3) Fix that might overlap when using dataZoom. + // (4) Consider other chart types using `barGrid`? + // See #6728, #4862, `test/bar-overflow-time-plot.html` + + var ecModel = model.ecModel; + + if (ecModel && scaleType === 'time' + /*|| scaleType === 'interval' */ + ) { + var barSeriesModels = prepareLayoutBarSeries('bar', ecModel); + var isBaseAxisAndHasBarSeries_1 = false; + each(barSeriesModels, function (seriesModel) { + isBaseAxisAndHasBarSeries_1 = isBaseAxisAndHasBarSeries_1 || seriesModel.getBaseAxis() === model.axis; + }); + + if (isBaseAxisAndHasBarSeries_1) { + // Calculate placement of bars on axis. TODO should be decoupled + // with barLayout + var barWidthAndOffset = makeColumnLayout(barSeriesModels); // Adjust axis min and max to account for overflow + + var adjustedScale = adjustScaleForOverflow(min, max, model, barWidthAndOffset); + min = adjustedScale.min; + max = adjustedScale.max; + } + } + + return { + extent: [min, max], + // "fix" means "fixed", the value should not be + // changed in the subsequent steps. + fixMin: rawExtentResult.minFixed, + fixMax: rawExtentResult.maxFixed + }; + } + + function adjustScaleForOverflow(min, max, model, // Only support cartesian coord yet. + barWidthAndOffset) { + // Get Axis Length + var axisExtent = model.axis.getExtent(); + var axisLength = axisExtent[1] - axisExtent[0]; // Get bars on current base axis and calculate min and max overflow + + var barsOnCurrentAxis = retrieveColumnLayout(barWidthAndOffset, model.axis); + + if (barsOnCurrentAxis === undefined) { + return { + min: min, + max: max + }; + } + + var minOverflow = Infinity; + each(barsOnCurrentAxis, function (item) { + minOverflow = Math.min(item.offset, minOverflow); + }); + var maxOverflow = -Infinity; + each(barsOnCurrentAxis, function (item) { + maxOverflow = Math.max(item.offset + item.width, maxOverflow); + }); + minOverflow = Math.abs(minOverflow); + maxOverflow = Math.abs(maxOverflow); + var totalOverFlow = minOverflow + maxOverflow; // Calculate required buffer based on old range and overflow + + var oldRange = max - min; + var oldRangePercentOfNew = 1 - (minOverflow + maxOverflow) / axisLength; + var overflowBuffer = oldRange / oldRangePercentOfNew - oldRange; + max += overflowBuffer * (maxOverflow / totalOverFlow); + min -= overflowBuffer * (minOverflow / totalOverFlow); + return { + min: min, + max: max + }; + } // Precondition of calling this method: + // The scale extent has been initailized using series data extent via + // `scale.setExtent` or `scale.unionExtentFromData`; + + + function niceScaleExtent(scale, inModel) { + var model = inModel; + var extentInfo = getScaleExtent(scale, model); + var extent = extentInfo.extent; + var splitNumber = model.get('splitNumber'); + + if (scale instanceof LogScale) { + scale.base = model.get('logBase'); + } + + var scaleType = scale.type; + var interval = model.get('interval'); + var isIntervalOrTime = scaleType === 'interval' || scaleType === 'time'; + scale.setExtent(extent[0], extent[1]); + scale.calcNiceExtent({ + splitNumber: splitNumber, + fixMin: extentInfo.fixMin, + fixMax: extentInfo.fixMax, + minInterval: isIntervalOrTime ? model.get('minInterval') : null, + maxInterval: isIntervalOrTime ? model.get('maxInterval') : null + }); // If some one specified the min, max. And the default calculated interval + // is not good enough. He can specify the interval. It is often appeared + // in angle axis with angle 0 - 360. Interval calculated in interval scale is hard + // to be 60. + // FIXME + + if (interval != null) { + scale.setInterval && scale.setInterval(interval); + } + } + /** + * @param axisType Default retrieve from model.type + */ + + function createScaleByModel(model, axisType) { + axisType = axisType || model.get('type'); + + if (axisType) { + switch (axisType) { + // Buildin scale + case 'category': + return new OrdinalScale({ + ordinalMeta: model.getOrdinalMeta ? model.getOrdinalMeta() : model.getCategories(), + extent: [Infinity, -Infinity] + }); + + case 'time': + return new TimeScale({ + locale: model.ecModel.getLocaleModel(), + useUTC: model.ecModel.get('useUTC') + }); + + default: + // case 'value'/'interval', 'log', or others. + return new (Scale.getClass(axisType) || IntervalScale)(); + } + } + } + /** + * Check if the axis cross 0 + */ + + function ifAxisCrossZero(axis) { + var dataExtent = axis.scale.getExtent(); + var min = dataExtent[0]; + var max = dataExtent[1]; + return !(min > 0 && max > 0 || min < 0 && max < 0); + } + /** + * @param axis + * @return Label formatter function. + * param: {number} tickValue, + * param: {number} idx, the index in all ticks. + * If category axis, this param is not required. + * return: {string} label string. + */ + + function makeLabelFormatter(axis) { + var labelFormatter = axis.getLabelModel().get('formatter'); + var categoryTickStart = axis.type === 'category' ? axis.scale.getExtent()[0] : null; + + if (axis.scale.type === 'time') { + return function (tpl) { + return function (tick, idx) { + return axis.scale.getFormattedLabel(tick, idx, tpl); + }; + }(labelFormatter); + } else if (isString(labelFormatter)) { + return function (tpl) { + return function (tick) { + // For category axis, get raw value; for numeric axis, + // get formatted label like '1,333,444'. + var label = axis.scale.getLabel(tick); + var text = tpl.replace('{value}', label != null ? label : ''); + return text; + }; + }(labelFormatter); + } else if (isFunction(labelFormatter)) { + return function (cb) { + return function (tick, idx) { + // The original intention of `idx` is "the index of the tick in all ticks". + // But the previous implementation of category axis do not consider the + // `axisLabel.interval`, which cause that, for example, the `interval` is + // `1`, then the ticks "name5", "name7", "name9" are displayed, where the + // corresponding `idx` are `0`, `2`, `4`, but not `0`, `1`, `2`. So we keep + // the definition here for back compatibility. + if (categoryTickStart != null) { + idx = tick.value - categoryTickStart; + } + + return cb(getAxisRawValue(axis, tick), idx, tick.level != null ? { + level: tick.level + } : null); + }; + }(labelFormatter); + } else { + return function (tick) { + return axis.scale.getLabel(tick); + }; + } + } + function getAxisRawValue(axis, tick) { + // In category axis with data zoom, tick is not the original + // index of axis.data. So tick should not be exposed to user + // in category axis. + return axis.type === 'category' ? axis.scale.getLabel(tick) : tick.value; + } + /** + * @param axis + * @return Be null/undefined if no labels. + */ + + function estimateLabelUnionRect(axis) { + var axisModel = axis.model; + var scale = axis.scale; + + if (!axisModel.get(['axisLabel', 'show']) || scale.isBlank()) { + return; + } + + var realNumberScaleTicks; + var tickCount; + var categoryScaleExtent = scale.getExtent(); // Optimize for large category data, avoid call `getTicks()`. + + if (scale instanceof OrdinalScale) { + tickCount = scale.count(); + } else { + realNumberScaleTicks = scale.getTicks(); + tickCount = realNumberScaleTicks.length; + } + + var axisLabelModel = axis.getLabelModel(); + var labelFormatter = makeLabelFormatter(axis); + var rect; + var step = 1; // Simple optimization for large amount of labels + + if (tickCount > 40) { + step = Math.ceil(tickCount / 40); + } + + for (var i = 0; i < tickCount; i += step) { + var tick = realNumberScaleTicks ? realNumberScaleTicks[i] : { + value: categoryScaleExtent[0] + i + }; + var label = labelFormatter(tick, i); + var unrotatedSingleRect = axisLabelModel.getTextRect(label); + var singleRect = rotateTextRect(unrotatedSingleRect, axisLabelModel.get('rotate') || 0); + rect ? rect.union(singleRect) : rect = singleRect; + } + + return rect; + } + + function rotateTextRect(textRect, rotate) { + var rotateRadians = rotate * Math.PI / 180; + var beforeWidth = textRect.width; + var beforeHeight = textRect.height; + var afterWidth = beforeWidth * Math.abs(Math.cos(rotateRadians)) + Math.abs(beforeHeight * Math.sin(rotateRadians)); + var afterHeight = beforeWidth * Math.abs(Math.sin(rotateRadians)) + Math.abs(beforeHeight * Math.cos(rotateRadians)); + var rotatedRect = new BoundingRect(textRect.x, textRect.y, afterWidth, afterHeight); + return rotatedRect; + } + /** + * @param model axisLabelModel or axisTickModel + * @return {number|String} Can be null|'auto'|number|function + */ + + + function getOptionCategoryInterval(model) { + var interval = model.get('interval'); + return interval == null ? 'auto' : interval; + } + /** + * Set `categoryInterval` as 0 implicitly indicates that + * show all labels reguardless of overlap. + * @param {Object} axis axisModel.axis + */ + + function shouldShowAllLabels(axis) { + return axis.type === 'category' && getOptionCategoryInterval(axis.getLabelModel()) === 0; + } + function getDataDimensionsOnAxis(data, axisDim) { + // Remove duplicated dat dimensions caused by `getStackedDimension`. + var dataDimMap = {}; // Currently `mapDimensionsAll` will contain stack result dimension ('__\0ecstackresult'). + // PENDING: is it reasonable? Do we need to remove the original dim from "coord dim" since + // there has been stacked result dim? + + each(data.mapDimensionsAll(axisDim), function (dataDim) { + // For example, the extent of the original dimension + // is [0.1, 0.5], the extent of the `stackResultDimension` + // is [7, 9], the final extent should NOT include [0.1, 0.5], + // because there is no graphic corresponding to [0.1, 0.5]. + // See the case in `test/area-stack.html` `main1`, where area line + // stack needs `yAxis` not start from 0. + dataDimMap[getStackedDimension(data, dataDim)] = true; + }); + return keys(dataDimMap); + } + function unionAxisExtentFromData(dataExtent, data, axisDim) { + if (data) { + each(getDataDimensionsOnAxis(data, axisDim), function (dim) { + var seriesExtent = data.getApproximateExtent(dim); + seriesExtent[0] < dataExtent[0] && (dataExtent[0] = seriesExtent[0]); + seriesExtent[1] > dataExtent[1] && (dataExtent[1] = seriesExtent[1]); + }); + } + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + var AxisModelCommonMixin = + /** @class */ + function () { + function AxisModelCommonMixin() {} + + AxisModelCommonMixin.prototype.getNeedCrossZero = function () { + var option = this.option; + return !option.scale; + }; + /** + * Should be implemented by each axis model if necessary. + * @return coordinate system model + */ + + + AxisModelCommonMixin.prototype.getCoordSysModel = function () { + return; + }; + + return AxisModelCommonMixin; + }(); + + /** + * Create a muti dimension List structure from seriesModel. + */ + + function createList(seriesModel) { + return createSeriesData(null, seriesModel); + } // export function createGraph(seriesModel) { + var dataStack$1 = { + isDimensionStacked: isDimensionStacked, + enableDataStack: enableDataStack, + getStackedDimension: getStackedDimension + }; + /** + * Create scale + * @param {Array.} dataExtent + * @param {Object|module:echarts/Model} option If `optoin.type` + * is secified, it can only be `'value'` currently. + */ + + function createScale(dataExtent, option) { + var axisModel = option; + + if (!(option instanceof Model)) { + axisModel = new Model(option); // FIXME + // Currently AxisModelCommonMixin has nothing to do with the + // the requirements of `axisHelper.createScaleByModel`. For + // example the method `getCategories` and `getOrdinalMeta` + // are required for `'category'` axis, and ecModel are required + // for `'time'` axis. But occationally echarts-gl happened + // to only use `'value'` axis. + // zrUtil.mixin(axisModel, AxisModelCommonMixin); + } + + var scale = createScaleByModel(axisModel); + scale.setExtent(dataExtent[0], dataExtent[1]); + niceScaleExtent(scale, axisModel); + return scale; + } + /** + * Mixin common methods to axis model, + * + * Inlcude methods + * `getFormattedLabels() => Array.` + * `getCategories() => Array.` + * `getMin(origin: boolean) => number` + * `getMax(origin: boolean) => number` + * `getNeedCrossZero() => boolean` + */ + + function mixinAxisModelCommonMethods(Model) { + mixin(Model, AxisModelCommonMixin); + } + function createTextStyle$1(textStyleModel, opts) { + opts = opts || {}; + return createTextStyle(textStyleModel, null, null, opts.state !== 'normal'); + } + + var helper = /*#__PURE__*/Object.freeze({ + __proto__: null, + createList: createList, + getLayoutRect: getLayoutRect, + dataStack: dataStack$1, + createScale: createScale, + mixinAxisModelCommonMethods: mixinAxisModelCommonMethods, + getECData: getECData, + createTextStyle: createTextStyle$1, + createDimensions: createDimensions, + createSymbol: createSymbol, + enableHoverEmphasis: enableHoverEmphasis + }); + + var EPSILON$4 = 1e-8; + function isAroundEqual$1(a, b) { + return Math.abs(a - b) < EPSILON$4; + } + function contain$2(points, x, y) { + var w = 0; + var p = points[0]; + if (!p) { + return false; + } + for (var i = 1; i < points.length; i++) { + var p2 = points[i]; + w += windingLine(p[0], p[1], p2[0], p2[1], x, y); + p = p2; + } + var p0 = points[0]; + if (!isAroundEqual$1(p[0], p0[0]) || !isAroundEqual$1(p[1], p0[1])) { + w += windingLine(p[0], p[1], p0[0], p0[1], x, y); + } + return w !== 0; + } + + var TMP_TRANSFORM = []; + + function transformPoints(points, transform) { + for (var p = 0; p < points.length; p++) { + applyTransform(points[p], points[p], transform); + } + } + + function updateBBoxFromPoints(points, min$1, max$1, projection) { + for (var i = 0; i < points.length; i++) { + var p = points[i]; + + if (projection) { + // projection may return null point. + p = projection.project(p); + } + + if (p && isFinite(p[0]) && isFinite(p[1])) { + min(min$1, min$1, p); + max(max$1, max$1, p); + } + } + } + + function centroid(points) { + var signedArea = 0; + var cx = 0; + var cy = 0; + var len = points.length; + var x0 = points[len - 1][0]; + var y0 = points[len - 1][1]; // Polygon should been closed. + + for (var i = 0; i < len; i++) { + var x1 = points[i][0]; + var y1 = points[i][1]; + var a = x0 * y1 - x1 * y0; + signedArea += a; + cx += (x0 + x1) * a; + cy += (y0 + y1) * a; + x0 = x1; + y0 = y1; + } + + return signedArea ? [cx / signedArea / 3, cy / signedArea / 3, signedArea] : [points[0][0] || 0, points[0][1] || 0]; + } + + var Region = + /** @class */ + function () { + function Region(name) { + this.name = name; + } + + Region.prototype.setCenter = function (center) { + this._center = center; + }; + /** + * Get center point in data unit. That is, + * for GeoJSONRegion, the unit is lat/lng, + * for GeoSVGRegion, the unit is SVG local coord. + */ + + + Region.prototype.getCenter = function () { + var center = this._center; + + if (!center) { + // In most cases there are no need to calculate this center. + // So calculate only when called. + center = this._center = this.calcCenter(); + } + + return center; + }; + + return Region; + }(); + + var GeoJSONPolygonGeometry = + /** @class */ + function () { + function GeoJSONPolygonGeometry(exterior, interiors) { + this.type = 'polygon'; + this.exterior = exterior; + this.interiors = interiors; + } + + return GeoJSONPolygonGeometry; + }(); + + var GeoJSONLineStringGeometry = + /** @class */ + function () { + function GeoJSONLineStringGeometry(points) { + this.type = 'linestring'; + this.points = points; + } + + return GeoJSONLineStringGeometry; + }(); + + var GeoJSONRegion = + /** @class */ + function (_super) { + __extends(GeoJSONRegion, _super); + + function GeoJSONRegion(name, geometries, cp) { + var _this = _super.call(this, name) || this; + + _this.type = 'geoJSON'; + _this.geometries = geometries; + _this._center = cp && [cp[0], cp[1]]; + return _this; + } + + GeoJSONRegion.prototype.calcCenter = function () { + var geometries = this.geometries; + var largestGeo; + var largestGeoSize = 0; + + for (var i = 0; i < geometries.length; i++) { + var geo = geometries[i]; + var exterior = geo.exterior; // Simple trick to use points count instead of polygon area as region size. + // Ignore linestring + + var size = exterior && exterior.length; + + if (size > largestGeoSize) { + largestGeo = geo; + largestGeoSize = size; + } + } + + if (largestGeo) { + return centroid(largestGeo.exterior); + } // from bounding rect by default. + + + var rect = this.getBoundingRect(); + return [rect.x + rect.width / 2, rect.y + rect.height / 2]; + }; + + GeoJSONRegion.prototype.getBoundingRect = function (projection) { + var rect = this._rect; // Always recalculate if using projection. + + if (rect && !projection) { + return rect; + } + + var min = [Infinity, Infinity]; + var max = [-Infinity, -Infinity]; + var geometries = this.geometries; + each(geometries, function (geo) { + if (geo.type === 'polygon') { + // Doesn't consider hole + updateBBoxFromPoints(geo.exterior, min, max, projection); + } else { + each(geo.points, function (points) { + updateBBoxFromPoints(points, min, max, projection); + }); + } + }); // Normalie invalid bounding. + + if (!(isFinite(min[0]) && isFinite(min[1]) && isFinite(max[0]) && isFinite(max[1]))) { + min[0] = min[1] = max[0] = max[1] = 0; + } + + rect = new BoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]); + + if (!projection) { + this._rect = rect; + } + + return rect; + }; + + GeoJSONRegion.prototype.contain = function (coord) { + var rect = this.getBoundingRect(); + var geometries = this.geometries; + + if (!rect.contain(coord[0], coord[1])) { + return false; + } + + loopGeo: for (var i = 0, len = geometries.length; i < len; i++) { + var geo = geometries[i]; // Only support polygon. + + if (geo.type !== 'polygon') { + continue; + } + + var exterior = geo.exterior; + var interiors = geo.interiors; + + if (contain$2(exterior, coord[0], coord[1])) { + // Not in the region if point is in the hole. + for (var k = 0; k < (interiors ? interiors.length : 0); k++) { + if (contain$2(interiors[k], coord[0], coord[1])) { + continue loopGeo; + } + } + + return true; + } + } + + return false; + }; + /** + * Transform the raw coords to target bounding. + * @param x + * @param y + * @param width + * @param height + */ + + + GeoJSONRegion.prototype.transformTo = function (x, y, width, height) { + var rect = this.getBoundingRect(); + var aspect = rect.width / rect.height; + + if (!width) { + width = aspect * height; + } else if (!height) { + height = width / aspect; + } + + var target = new BoundingRect(x, y, width, height); + var transform = rect.calculateTransform(target); + var geometries = this.geometries; + + for (var i = 0; i < geometries.length; i++) { + var geo = geometries[i]; + + if (geo.type === 'polygon') { + transformPoints(geo.exterior, transform); + each(geo.interiors, function (interior) { + transformPoints(interior, transform); + }); + } else { + each(geo.points, function (points) { + transformPoints(points, transform); + }); + } + } + + rect = this._rect; + rect.copy(target); // Update center + + this._center = [rect.x + rect.width / 2, rect.y + rect.height / 2]; + }; + + GeoJSONRegion.prototype.cloneShallow = function (name) { + name == null && (name = this.name); + var newRegion = new GeoJSONRegion(name, this.geometries, this._center); + newRegion._rect = this._rect; + newRegion.transformTo = null; // Simply avoid to be called. + + return newRegion; + }; + + return GeoJSONRegion; + }(Region); + + var GeoSVGRegion = + /** @class */ + function (_super) { + __extends(GeoSVGRegion, _super); + + function GeoSVGRegion(name, elOnlyForCalculate) { + var _this = _super.call(this, name) || this; + + _this.type = 'geoSVG'; + _this._elOnlyForCalculate = elOnlyForCalculate; + return _this; + } + + GeoSVGRegion.prototype.calcCenter = function () { + var el = this._elOnlyForCalculate; + var rect = el.getBoundingRect(); + var center = [rect.x + rect.width / 2, rect.y + rect.height / 2]; + var mat = identity(TMP_TRANSFORM); + var target = el; + + while (target && !target.isGeoSVGGraphicRoot) { + mul$1(mat, target.getLocalTransform(), mat); + target = target.parent; + } + + invert(mat, mat); + applyTransform(center, center, mat); + return center; + }; + + return GeoSVGRegion; + }(Region); + + function decode(json) { + if (!json.UTF8Encoding) { + return json; + } + + var jsonCompressed = json; + var encodeScale = jsonCompressed.UTF8Scale; + + if (encodeScale == null) { + encodeScale = 1024; + } + + var features = jsonCompressed.features; + each(features, function (feature) { + var geometry = feature.geometry; + var encodeOffsets = geometry.encodeOffsets; + var coordinates = geometry.coordinates; // Geometry may be appeded manually in the script after json loaded. + // In this case this geometry is usually not encoded. + + if (!encodeOffsets) { + return; + } + + switch (geometry.type) { + case 'LineString': + geometry.coordinates = decodeRing(coordinates, encodeOffsets, encodeScale); + break; + + case 'Polygon': + decodeRings(coordinates, encodeOffsets, encodeScale); + break; + + case 'MultiLineString': + decodeRings(coordinates, encodeOffsets, encodeScale); + break; + + case 'MultiPolygon': + each(coordinates, function (rings, idx) { + return decodeRings(rings, encodeOffsets[idx], encodeScale); + }); + } + }); // Has been decoded + + jsonCompressed.UTF8Encoding = false; + return jsonCompressed; + } + + function decodeRings(rings, encodeOffsets, encodeScale) { + for (var c = 0; c < rings.length; c++) { + rings[c] = decodeRing(rings[c], encodeOffsets[c], encodeScale); + } + } + + function decodeRing(coordinate, encodeOffsets, encodeScale) { + var result = []; + var prevX = encodeOffsets[0]; + var prevY = encodeOffsets[1]; + + for (var i = 0; i < coordinate.length; i += 2) { + var x = coordinate.charCodeAt(i) - 64; + var y = coordinate.charCodeAt(i + 1) - 64; // ZigZag decoding + + x = x >> 1 ^ -(x & 1); + y = y >> 1 ^ -(y & 1); // Delta deocding + + x += prevX; + y += prevY; + prevX = x; + prevY = y; // Dequantize + + result.push([x / encodeScale, y / encodeScale]); + } + + return result; + } + + function parseGeoJSON(geoJson, nameProperty) { + geoJson = decode(geoJson); + return map(filter(geoJson.features, function (featureObj) { + // Output of mapshaper may have geometry null + return featureObj.geometry && featureObj.properties && featureObj.geometry.coordinates.length > 0; + }), function (featureObj) { + var properties = featureObj.properties; + var geo = featureObj.geometry; + var geometries = []; + + switch (geo.type) { + case 'Polygon': + var coordinates = geo.coordinates; // According to the GeoJSON specification. + // First must be exterior, and the rest are all interior(holes). + + geometries.push(new GeoJSONPolygonGeometry(coordinates[0], coordinates.slice(1))); + break; + + case 'MultiPolygon': + each(geo.coordinates, function (item) { + if (item[0]) { + geometries.push(new GeoJSONPolygonGeometry(item[0], item.slice(1))); + } + }); + break; + + case 'LineString': + geometries.push(new GeoJSONLineStringGeometry([geo.coordinates])); + break; + + case 'MultiLineString': + geometries.push(new GeoJSONLineStringGeometry(geo.coordinates)); + } + + var region = new GeoJSONRegion(properties[nameProperty || 'name'], geometries, properties.cp); + region.properties = properties; + return region; + }); + } + + var number = /*#__PURE__*/Object.freeze({ + __proto__: null, + linearMap: linearMap, + round: round, + asc: asc, + getPrecision: getPrecision, + getPrecisionSafe: getPrecisionSafe, + getPixelPrecision: getPixelPrecision, + getPercentWithPrecision: getPercentWithPrecision, + MAX_SAFE_INTEGER: MAX_SAFE_INTEGER, + remRadian: remRadian, + isRadianAroundZero: isRadianAroundZero, + parseDate: parseDate, + quantity: quantity, + quantityExponent: quantityExponent, + nice: nice, + quantile: quantile, + reformIntervals: reformIntervals, + isNumeric: isNumeric, + numericToNumber: numericToNumber + }); + + var time = /*#__PURE__*/Object.freeze({ + __proto__: null, + parse: parseDate, + format: format + }); + + var graphic$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + extendShape: extendShape, + extendPath: extendPath, + makePath: makePath, + makeImage: makeImage, + mergePath: mergePath$1, + resizePath: resizePath, + createIcon: createIcon, + updateProps: updateProps, + initProps: initProps, + getTransform: getTransform, + clipPointsByRect: clipPointsByRect, + clipRectByRect: clipRectByRect, + registerShape: registerShape, + getShapeClass: getShapeClass, + Group: Group, + Image: ZRImage, + Text: ZRText, + Circle: Circle, + Ellipse: Ellipse, + Sector: Sector, + Ring: Ring, + Polygon: Polygon, + Polyline: Polyline, + Rect: Rect, + Line: Line, + BezierCurve: BezierCurve, + Arc: Arc, + IncrementalDisplayable: IncrementalDisplayable, + CompoundPath: CompoundPath, + LinearGradient: LinearGradient, + RadialGradient: RadialGradient, + BoundingRect: BoundingRect + }); + + var format$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + addCommas: addCommas, + toCamelCase: toCamelCase, + normalizeCssArray: normalizeCssArray$1, + encodeHTML: encodeHTML, + formatTpl: formatTpl, + getTooltipMarker: getTooltipMarker, + formatTime: formatTime, + capitalFirst: capitalFirst, + truncateText: truncateText, + getTextRect: getTextRect + }); + + var util$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + map: map, + each: each, + indexOf: indexOf, + inherits: inherits, + reduce: reduce, + filter: filter, + bind: bind, + curry: curry, + isArray: isArray, + isString: isString, + isObject: isObject, + isFunction: isFunction, + extend: extend, + defaults: defaults, + clone: clone, + merge: merge + }); + + var inner$5 = makeInner(); + function createAxisLabels(axis) { + // Only ordinal scale support tick interval + return axis.type === 'category' ? makeCategoryLabels(axis) : makeRealNumberLabels(axis); + } + /** + * @param {module:echats/coord/Axis} axis + * @param {module:echarts/model/Model} tickModel For example, can be axisTick, splitLine, splitArea. + * @return {Object} { + * ticks: Array. + * tickCategoryInterval: number + * } + */ + + function createAxisTicks(axis, tickModel) { + // Only ordinal scale support tick interval + return axis.type === 'category' ? makeCategoryTicks(axis, tickModel) : { + ticks: map(axis.scale.getTicks(), function (tick) { + return tick.value; + }) + }; + } + + function makeCategoryLabels(axis) { + var labelModel = axis.getLabelModel(); + var result = makeCategoryLabelsActually(axis, labelModel); + return !labelModel.get('show') || axis.scale.isBlank() ? { + labels: [], + labelCategoryInterval: result.labelCategoryInterval + } : result; + } + + function makeCategoryLabelsActually(axis, labelModel) { + var labelsCache = getListCache(axis, 'labels'); + var optionLabelInterval = getOptionCategoryInterval(labelModel); + var result = listCacheGet(labelsCache, optionLabelInterval); + + if (result) { + return result; + } + + var labels; + var numericLabelInterval; + + if (isFunction(optionLabelInterval)) { + labels = makeLabelsByCustomizedCategoryInterval(axis, optionLabelInterval); + } else { + numericLabelInterval = optionLabelInterval === 'auto' ? makeAutoCategoryInterval(axis) : optionLabelInterval; + labels = makeLabelsByNumericCategoryInterval(axis, numericLabelInterval); + } // Cache to avoid calling interval function repeatly. + + + return listCacheSet(labelsCache, optionLabelInterval, { + labels: labels, + labelCategoryInterval: numericLabelInterval + }); + } + + function makeCategoryTicks(axis, tickModel) { + var ticksCache = getListCache(axis, 'ticks'); + var optionTickInterval = getOptionCategoryInterval(tickModel); + var result = listCacheGet(ticksCache, optionTickInterval); + + if (result) { + return result; + } + + var ticks; + var tickCategoryInterval; // Optimize for the case that large category data and no label displayed, + // we should not return all ticks. + + if (!tickModel.get('show') || axis.scale.isBlank()) { + ticks = []; + } + + if (isFunction(optionTickInterval)) { + ticks = makeLabelsByCustomizedCategoryInterval(axis, optionTickInterval, true); + } // Always use label interval by default despite label show. Consider this + // scenario, Use multiple grid with the xAxis sync, and only one xAxis shows + // labels. `splitLine` and `axisTick` should be consistent in this case. + else if (optionTickInterval === 'auto') { + var labelsResult = makeCategoryLabelsActually(axis, axis.getLabelModel()); + tickCategoryInterval = labelsResult.labelCategoryInterval; + ticks = map(labelsResult.labels, function (labelItem) { + return labelItem.tickValue; + }); + } else { + tickCategoryInterval = optionTickInterval; + ticks = makeLabelsByNumericCategoryInterval(axis, tickCategoryInterval, true); + } // Cache to avoid calling interval function repeatly. + + + return listCacheSet(ticksCache, optionTickInterval, { + ticks: ticks, + tickCategoryInterval: tickCategoryInterval + }); + } + + function makeRealNumberLabels(axis) { + var ticks = axis.scale.getTicks(); + var labelFormatter = makeLabelFormatter(axis); + return { + labels: map(ticks, function (tick, idx) { + return { + level: tick.level, + formattedLabel: labelFormatter(tick, idx), + rawLabel: axis.scale.getLabel(tick), + tickValue: tick.value + }; + }) + }; + } + + function getListCache(axis, prop) { + // Because key can be funciton, and cache size always be small, we use array cache. + return inner$5(axis)[prop] || (inner$5(axis)[prop] = []); + } + + function listCacheGet(cache, key) { + for (var i = 0; i < cache.length; i++) { + if (cache[i].key === key) { + return cache[i].value; + } + } + } + + function listCacheSet(cache, key, value) { + cache.push({ + key: key, + value: value + }); + return value; + } + + function makeAutoCategoryInterval(axis) { + var result = inner$5(axis).autoInterval; + return result != null ? result : inner$5(axis).autoInterval = axis.calculateCategoryInterval(); + } + /** + * Calculate interval for category axis ticks and labels. + * To get precise result, at least one of `getRotate` and `isHorizontal` + * should be implemented in axis. + */ + + + function calculateCategoryInterval(axis) { + var params = fetchAutoCategoryIntervalCalculationParams(axis); + var labelFormatter = makeLabelFormatter(axis); + var rotation = (params.axisRotate - params.labelRotate) / 180 * Math.PI; + var ordinalScale = axis.scale; + var ordinalExtent = ordinalScale.getExtent(); // Providing this method is for optimization: + // avoid generating a long array by `getTicks` + // in large category data case. + + var tickCount = ordinalScale.count(); + + if (ordinalExtent[1] - ordinalExtent[0] < 1) { + return 0; + } + + var step = 1; // Simple optimization. Empirical value: tick count should less than 40. + + if (tickCount > 40) { + step = Math.max(1, Math.floor(tickCount / 40)); + } + + var tickValue = ordinalExtent[0]; + var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue); + var unitW = Math.abs(unitSpan * Math.cos(rotation)); + var unitH = Math.abs(unitSpan * Math.sin(rotation)); + var maxW = 0; + var maxH = 0; // Caution: Performance sensitive for large category data. + // Consider dataZoom, we should make appropriate step to avoid O(n) loop. + + for (; tickValue <= ordinalExtent[1]; tickValue += step) { + var width = 0; + var height = 0; // Not precise, do not consider align and vertical align + // and each distance from axis line yet. + + var rect = getBoundingRect(labelFormatter({ + value: tickValue + }), params.font, 'center', 'top'); // Magic number + + width = rect.width * 1.3; + height = rect.height * 1.3; // Min size, void long loop. + + maxW = Math.max(maxW, width, 7); + maxH = Math.max(maxH, height, 7); + } + + var dw = maxW / unitW; + var dh = maxH / unitH; // 0/0 is NaN, 1/0 is Infinity. + + isNaN(dw) && (dw = Infinity); + isNaN(dh) && (dh = Infinity); + var interval = Math.max(0, Math.floor(Math.min(dw, dh))); + var cache = inner$5(axis.model); + var axisExtent = axis.getExtent(); + var lastAutoInterval = cache.lastAutoInterval; + var lastTickCount = cache.lastTickCount; // Use cache to keep interval stable while moving zoom window, + // otherwise the calculated interval might jitter when the zoom + // window size is close to the interval-changing size. + // For example, if all of the axis labels are `a, b, c, d, e, f, g`. + // The jitter will cause that sometimes the displayed labels are + // `a, d, g` (interval: 2) sometimes `a, c, e`(interval: 1). + + if (lastAutoInterval != null && lastTickCount != null && Math.abs(lastAutoInterval - interval) <= 1 && Math.abs(lastTickCount - tickCount) <= 1 // Always choose the bigger one, otherwise the critical + // point is not the same when zooming in or zooming out. + && lastAutoInterval > interval // If the axis change is caused by chart resize, the cache should not + // be used. Otherwise some hiden labels might not be shown again. + && cache.axisExtent0 === axisExtent[0] && cache.axisExtent1 === axisExtent[1]) { + interval = lastAutoInterval; + } // Only update cache if cache not used, otherwise the + // changing of interval is too insensitive. + else { + cache.lastTickCount = tickCount; + cache.lastAutoInterval = interval; + cache.axisExtent0 = axisExtent[0]; + cache.axisExtent1 = axisExtent[1]; + } + + return interval; + } + + function fetchAutoCategoryIntervalCalculationParams(axis) { + var labelModel = axis.getLabelModel(); + return { + axisRotate: axis.getRotate ? axis.getRotate() : axis.isHorizontal && !axis.isHorizontal() ? 90 : 0, + labelRotate: labelModel.get('rotate') || 0, + font: labelModel.getFont() + }; + } + + function makeLabelsByNumericCategoryInterval(axis, categoryInterval, onlyTick) { + var labelFormatter = makeLabelFormatter(axis); + var ordinalScale = axis.scale; + var ordinalExtent = ordinalScale.getExtent(); + var labelModel = axis.getLabelModel(); + var result = []; // TODO: axisType: ordinalTime, pick the tick from each month/day/year/... + + var step = Math.max((categoryInterval || 0) + 1, 1); + var startTick = ordinalExtent[0]; + var tickCount = ordinalScale.count(); // Calculate start tick based on zero if possible to keep label consistent + // while zooming and moving while interval > 0. Otherwise the selection + // of displayable ticks and symbols probably keep changing. + // 3 is empirical value. + + if (startTick !== 0 && step > 1 && tickCount / step > 2) { + startTick = Math.round(Math.ceil(startTick / step) * step); + } // (1) Only add min max label here but leave overlap checking + // to render stage, which also ensure the returned list + // suitable for splitLine and splitArea rendering. + // (2) Scales except category always contain min max label so + // do not need to perform this process. + + + var showAllLabel = shouldShowAllLabels(axis); + var includeMinLabel = labelModel.get('showMinLabel') || showAllLabel; + var includeMaxLabel = labelModel.get('showMaxLabel') || showAllLabel; + + if (includeMinLabel && startTick !== ordinalExtent[0]) { + addItem(ordinalExtent[0]); + } // Optimize: avoid generating large array by `ordinalScale.getTicks()`. + + + var tickValue = startTick; + + for (; tickValue <= ordinalExtent[1]; tickValue += step) { + addItem(tickValue); + } + + if (includeMaxLabel && tickValue - step !== ordinalExtent[1]) { + addItem(ordinalExtent[1]); + } + + function addItem(tickValue) { + var tickObj = { + value: tickValue + }; + result.push(onlyTick ? tickValue : { + formattedLabel: labelFormatter(tickObj), + rawLabel: ordinalScale.getLabel(tickObj), + tickValue: tickValue + }); + } + + return result; + } + + function makeLabelsByCustomizedCategoryInterval(axis, categoryInterval, onlyTick) { + var ordinalScale = axis.scale; + var labelFormatter = makeLabelFormatter(axis); + var result = []; + each(ordinalScale.getTicks(), function (tick) { + var rawLabel = ordinalScale.getLabel(tick); + var tickValue = tick.value; + + if (categoryInterval(tick.value, rawLabel)) { + result.push(onlyTick ? tickValue : { + formattedLabel: labelFormatter(tick), + rawLabel: rawLabel, + tickValue: tickValue + }); + } + }); + return result; + } + + var NORMALIZED_EXTENT = [0, 1]; + /** + * Base class of Axis. + */ + + var Axis = + /** @class */ + function () { + function Axis(dim, scale, extent) { + this.onBand = false; + this.inverse = false; + this.dim = dim; + this.scale = scale; + this._extent = extent || [0, 0]; + } + /** + * If axis extent contain given coord + */ + + + Axis.prototype.contain = function (coord) { + var extent = this._extent; + var min = Math.min(extent[0], extent[1]); + var max = Math.max(extent[0], extent[1]); + return coord >= min && coord <= max; + }; + /** + * If axis extent contain given data + */ + + + Axis.prototype.containData = function (data) { + return this.scale.contain(data); + }; + /** + * Get coord extent. + */ + + + Axis.prototype.getExtent = function () { + return this._extent.slice(); + }; + /** + * Get precision used for formatting + */ + + + Axis.prototype.getPixelPrecision = function (dataExtent) { + return getPixelPrecision(dataExtent || this.scale.getExtent(), this._extent); + }; + /** + * Set coord extent + */ + + + Axis.prototype.setExtent = function (start, end) { + var extent = this._extent; + extent[0] = start; + extent[1] = end; + }; + /** + * Convert data to coord. Data is the rank if it has an ordinal scale + */ + + + Axis.prototype.dataToCoord = function (data, clamp) { + var extent = this._extent; + var scale = this.scale; + data = scale.normalize(data); + + if (this.onBand && scale.type === 'ordinal') { + extent = extent.slice(); + fixExtentWithBands(extent, scale.count()); + } + + return linearMap(data, NORMALIZED_EXTENT, extent, clamp); + }; + /** + * Convert coord to data. Data is the rank if it has an ordinal scale + */ + + + Axis.prototype.coordToData = function (coord, clamp) { + var extent = this._extent; + var scale = this.scale; + + if (this.onBand && scale.type === 'ordinal') { + extent = extent.slice(); + fixExtentWithBands(extent, scale.count()); + } + + var t = linearMap(coord, extent, NORMALIZED_EXTENT, clamp); + return this.scale.scale(t); + }; + /** + * Convert pixel point to data in axis + */ + + + Axis.prototype.pointToData = function (point, clamp) { + // Should be implemented in derived class if necessary. + return; + }; + /** + * Different from `zrUtil.map(axis.getTicks(), axis.dataToCoord, axis)`, + * `axis.getTicksCoords` considers `onBand`, which is used by + * `boundaryGap:true` of category axis and splitLine and splitArea. + * @param opt.tickModel default: axis.model.getModel('axisTick') + * @param opt.clamp If `true`, the first and the last + * tick must be at the axis end points. Otherwise, clip ticks + * that outside the axis extent. + */ + + + Axis.prototype.getTicksCoords = function (opt) { + opt = opt || {}; + var tickModel = opt.tickModel || this.getTickModel(); + var result = createAxisTicks(this, tickModel); + var ticks = result.ticks; + var ticksCoords = map(ticks, function (tickVal) { + return { + coord: this.dataToCoord(this.scale.type === 'ordinal' ? this.scale.getRawOrdinalNumber(tickVal) : tickVal), + tickValue: tickVal + }; + }, this); + var alignWithLabel = tickModel.get('alignWithLabel'); + fixOnBandTicksCoords(this, ticksCoords, alignWithLabel, opt.clamp); + return ticksCoords; + }; + + Axis.prototype.getMinorTicksCoords = function () { + if (this.scale.type === 'ordinal') { + // Category axis doesn't support minor ticks + return []; + } + + var minorTickModel = this.model.getModel('minorTick'); + var splitNumber = minorTickModel.get('splitNumber'); // Protection. + + if (!(splitNumber > 0 && splitNumber < 100)) { + splitNumber = 5; + } + + var minorTicks = this.scale.getMinorTicks(splitNumber); + var minorTicksCoords = map(minorTicks, function (minorTicksGroup) { + return map(minorTicksGroup, function (minorTick) { + return { + coord: this.dataToCoord(minorTick), + tickValue: minorTick + }; + }, this); + }, this); + return minorTicksCoords; + }; + + Axis.prototype.getViewLabels = function () { + return createAxisLabels(this).labels; + }; + + Axis.prototype.getLabelModel = function () { + return this.model.getModel('axisLabel'); + }; + /** + * Notice here we only get the default tick model. For splitLine + * or splitArea, we should pass the splitLineModel or splitAreaModel + * manually when calling `getTicksCoords`. + * In GL, this method may be overrided to: + * `axisModel.getModel('axisTick', grid3DModel.getModel('axisTick'));` + */ + + + Axis.prototype.getTickModel = function () { + return this.model.getModel('axisTick'); + }; + /** + * Get width of band + */ + + + Axis.prototype.getBandWidth = function () { + var axisExtent = this._extent; + var dataExtent = this.scale.getExtent(); + var len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0); // Fix #2728, avoid NaN when only one data. + + len === 0 && (len = 1); + var size = Math.abs(axisExtent[1] - axisExtent[0]); + return Math.abs(size) / len; + }; + /** + * Only be called in category axis. + * Can be overrided, consider other axes like in 3D. + * @return Auto interval for cateogry axis tick and label + */ + + + Axis.prototype.calculateCategoryInterval = function () { + return calculateCategoryInterval(this); + }; + + return Axis; + }(); + + function fixExtentWithBands(extent, nTick) { + var size = extent[1] - extent[0]; + var len = nTick; + var margin = size / len / 2; + extent[0] += margin; + extent[1] -= margin; + } // If axis has labels [1, 2, 3, 4]. Bands on the axis are + // |---1---|---2---|---3---|---4---|. + // So the displayed ticks and splitLine/splitArea should between + // each data item, otherwise cause misleading (e.g., split tow bars + // of a single data item when there are two bar series). + // Also consider if tickCategoryInterval > 0 and onBand, ticks and + // splitLine/spliteArea should layout appropriately corresponding + // to displayed labels. (So we should not use `getBandWidth` in this + // case). + + + function fixOnBandTicksCoords(axis, ticksCoords, alignWithLabel, clamp) { + var ticksLen = ticksCoords.length; + + if (!axis.onBand || alignWithLabel || !ticksLen) { + return; + } + + var axisExtent = axis.getExtent(); + var last; + var diffSize; + + if (ticksLen === 1) { + ticksCoords[0].coord = axisExtent[0]; + last = ticksCoords[1] = { + coord: axisExtent[0] + }; + } else { + var crossLen = ticksCoords[ticksLen - 1].tickValue - ticksCoords[0].tickValue; + var shift_1 = (ticksCoords[ticksLen - 1].coord - ticksCoords[0].coord) / crossLen; + each(ticksCoords, function (ticksItem) { + ticksItem.coord -= shift_1 / 2; + }); + var dataExtent = axis.scale.getExtent(); + diffSize = 1 + dataExtent[1] - ticksCoords[ticksLen - 1].tickValue; + last = { + coord: ticksCoords[ticksLen - 1].coord + shift_1 * diffSize + }; + ticksCoords.push(last); + } + + var inverse = axisExtent[0] > axisExtent[1]; // Handling clamp. + + if (littleThan(ticksCoords[0].coord, axisExtent[0])) { + clamp ? ticksCoords[0].coord = axisExtent[0] : ticksCoords.shift(); + } + + if (clamp && littleThan(axisExtent[0], ticksCoords[0].coord)) { + ticksCoords.unshift({ + coord: axisExtent[0] + }); + } + + if (littleThan(axisExtent[1], last.coord)) { + clamp ? last.coord = axisExtent[1] : ticksCoords.pop(); + } + + if (clamp && littleThan(last.coord, axisExtent[1])) { + ticksCoords.push({ + coord: axisExtent[1] + }); + } + + function littleThan(a, b) { + // Avoid rounding error cause calculated tick coord different with extent. + // It may cause an extra unecessary tick added. + a = round(a); + b = round(b); + return inverse ? a > b : a < b; + } + } + + // Should use `ComponentModel.extend` or `class XXXX extend ComponentModel` to create class. + // Then use `registerComponentModel` in `install` parameter when `use` this extension. For example: + // class Bar3DModel extends ComponentModel {} + // export function install(registers) { regsiters.registerComponentModel(Bar3DModel); } + // echarts.use(install); + + function extendComponentModel(proto) { + var Model = ComponentModel.extend(proto); + ComponentModel.registerClass(Model); + return Model; + } + function extendComponentView(proto) { + var View = ComponentView.extend(proto); + ComponentView.registerClass(View); + return View; + } + function extendSeriesModel(proto) { + var Model = SeriesModel.extend(proto); + SeriesModel.registerClass(Model); + return Model; + } + function extendChartView(proto) { + var View = ChartView.extend(proto); + ChartView.registerClass(View); + return View; + } + + var PI2$6 = Math.PI * 2; + var CMD$3 = PathProxy.CMD; + var DEFAULT_SEARCH_SPACE = ['top', 'right', 'bottom', 'left']; + + function getCandidateAnchor(pos, distance, rect, outPt, outDir) { + var width = rect.width; + var height = rect.height; + + switch (pos) { + case 'top': + outPt.set(rect.x + width / 2, rect.y - distance); + outDir.set(0, -1); + break; + + case 'bottom': + outPt.set(rect.x + width / 2, rect.y + height + distance); + outDir.set(0, 1); + break; + + case 'left': + outPt.set(rect.x - distance, rect.y + height / 2); + outDir.set(-1, 0); + break; + + case 'right': + outPt.set(rect.x + width + distance, rect.y + height / 2); + outDir.set(1, 0); + break; + } + } + + function projectPointToArc(cx, cy, r, startAngle, endAngle, anticlockwise, x, y, out) { + x -= cx; + y -= cy; + var d = Math.sqrt(x * x + y * y); + x /= d; + y /= d; // Intersect point. + + var ox = x * r + cx; + var oy = y * r + cy; + + if (Math.abs(startAngle - endAngle) % PI2$6 < 1e-4) { + // Is a circle + out[0] = ox; + out[1] = oy; + return d - r; + } + + if (anticlockwise) { + var tmp = startAngle; + startAngle = normalizeRadian(endAngle); + endAngle = normalizeRadian(tmp); + } else { + startAngle = normalizeRadian(startAngle); + endAngle = normalizeRadian(endAngle); + } + + if (startAngle > endAngle) { + endAngle += PI2$6; + } + + var angle = Math.atan2(y, x); + + if (angle < 0) { + angle += PI2$6; + } + + if (angle >= startAngle && angle <= endAngle || angle + PI2$6 >= startAngle && angle + PI2$6 <= endAngle) { + // Project point is on the arc. + out[0] = ox; + out[1] = oy; + return d - r; + } + + var x1 = r * Math.cos(startAngle) + cx; + var y1 = r * Math.sin(startAngle) + cy; + var x2 = r * Math.cos(endAngle) + cx; + var y2 = r * Math.sin(endAngle) + cy; + var d1 = (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y); + var d2 = (x2 - x) * (x2 - x) + (y2 - y) * (y2 - y); + + if (d1 < d2) { + out[0] = x1; + out[1] = y1; + return Math.sqrt(d1); + } else { + out[0] = x2; + out[1] = y2; + return Math.sqrt(d2); + } + } + + function projectPointToLine(x1, y1, x2, y2, x, y, out, limitToEnds) { + var dx = x - x1; + var dy = y - y1; + var dx1 = x2 - x1; + var dy1 = y2 - y1; + var lineLen = Math.sqrt(dx1 * dx1 + dy1 * dy1); + dx1 /= lineLen; + dy1 /= lineLen; // dot product + + var projectedLen = dx * dx1 + dy * dy1; + var t = projectedLen / lineLen; + + if (limitToEnds) { + t = Math.min(Math.max(t, 0), 1); + } + + t *= lineLen; + var ox = out[0] = x1 + t * dx1; + var oy = out[1] = y1 + t * dy1; + return Math.sqrt((ox - x) * (ox - x) + (oy - y) * (oy - y)); + } + + function projectPointToRect(x1, y1, width, height, x, y, out) { + if (width < 0) { + x1 = x1 + width; + width = -width; + } + + if (height < 0) { + y1 = y1 + height; + height = -height; + } + + var x2 = x1 + width; + var y2 = y1 + height; + var ox = out[0] = Math.min(Math.max(x, x1), x2); + var oy = out[1] = Math.min(Math.max(y, y1), y2); + return Math.sqrt((ox - x) * (ox - x) + (oy - y) * (oy - y)); + } + + var tmpPt = []; + + function nearestPointOnRect(pt, rect, out) { + var dist = projectPointToRect(rect.x, rect.y, rect.width, rect.height, pt.x, pt.y, tmpPt); + out.set(tmpPt[0], tmpPt[1]); + return dist; + } + /** + * Calculate min distance corresponding point. + * This method won't evaluate if point is in the path. + */ + + + function nearestPointOnPath(pt, path, out) { + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + var x1; + var y1; + var minDist = Infinity; + var data = path.data; + var x = pt.x; + var y = pt.y; + + for (var i = 0; i < data.length;) { + var cmd = data[i++]; + + if (i === 1) { + xi = data[i]; + yi = data[i + 1]; + x0 = xi; + y0 = yi; + } + + var d = minDist; + + switch (cmd) { + case CMD$3.M: + // moveTo 命令重新创建一个新的 subpath, 并且更新新的起点 + // 在 closePath 的时候使用 + x0 = data[i++]; + y0 = data[i++]; + xi = x0; + yi = y0; + break; + + case CMD$3.L: + d = projectPointToLine(xi, yi, data[i], data[i + 1], x, y, tmpPt, true); + xi = data[i++]; + yi = data[i++]; + break; + + case CMD$3.C: + d = cubicProjectPoint(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], x, y, tmpPt); + xi = data[i++]; + yi = data[i++]; + break; + + case CMD$3.Q: + d = quadraticProjectPoint(xi, yi, data[i++], data[i++], data[i], data[i + 1], x, y, tmpPt); + xi = data[i++]; + yi = data[i++]; + break; + + case CMD$3.A: + // TODO Arc 判断的开销比较大 + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var theta = data[i++]; + var dTheta = data[i++]; // TODO Arc 旋转 + + i += 1; + var anticlockwise = !!(1 - data[i++]); + x1 = Math.cos(theta) * rx + cx; + y1 = Math.sin(theta) * ry + cy; // 不是直接使用 arc 命令 + + if (i <= 1) { + // 第一个命令起点还未定义 + x0 = x1; + y0 = y1; + } // zr 使用scale来模拟椭圆, 这里也对x做一定的缩放 + + + var _x = (x - cx) * ry / rx + cx; + + d = projectPointToArc(cx, cy, ry, theta, theta + dTheta, anticlockwise, _x, y, tmpPt); + xi = Math.cos(theta + dTheta) * rx + cx; + yi = Math.sin(theta + dTheta) * ry + cy; + break; + + case CMD$3.R: + x0 = xi = data[i++]; + y0 = yi = data[i++]; + var width = data[i++]; + var height = data[i++]; + d = projectPointToRect(x0, y0, width, height, x, y, tmpPt); + break; + + case CMD$3.Z: + d = projectPointToLine(xi, yi, x0, y0, x, y, tmpPt, true); + xi = x0; + yi = y0; + break; + } + + if (d < minDist) { + minDist = d; + out.set(tmpPt[0], tmpPt[1]); + } + } + + return minDist; + } // Temporal varible for intermediate usage. + + + var pt0 = new Point(); + var pt1 = new Point(); + var pt2 = new Point(); + var dir = new Point(); + var dir2 = new Point(); + /** + * Calculate a proper guide line based on the label position and graphic element definition + * @param label + * @param labelRect + * @param target + * @param targetRect + */ + + function updateLabelLinePoints(target, labelLineModel) { + if (!target) { + return; + } + + var labelLine = target.getTextGuideLine(); + var label = target.getTextContent(); // Needs to create text guide in each charts. + + if (!(label && labelLine)) { + return; + } + + var labelGuideConfig = target.textGuideLineConfig || {}; + var points = [[0, 0], [0, 0], [0, 0]]; + var searchSpace = labelGuideConfig.candidates || DEFAULT_SEARCH_SPACE; + var labelRect = label.getBoundingRect().clone(); + labelRect.applyTransform(label.getComputedTransform()); + var minDist = Infinity; + var anchorPoint = labelGuideConfig.anchor; + var targetTransform = target.getComputedTransform(); + var targetInversedTransform = targetTransform && invert([], targetTransform); + var len = labelLineModel.get('length2') || 0; + + if (anchorPoint) { + pt2.copy(anchorPoint); + } + + for (var i = 0; i < searchSpace.length; i++) { + var candidate = searchSpace[i]; + getCandidateAnchor(candidate, 0, labelRect, pt0, dir); + Point.scaleAndAdd(pt1, pt0, dir, len); // Transform to target coord space. + + pt1.transform(targetInversedTransform); // Note: getBoundingRect will ensure the `path` being created. + + var boundingRect = target.getBoundingRect(); + var dist = anchorPoint ? anchorPoint.distance(pt1) : target instanceof Path ? nearestPointOnPath(pt1, target.path, pt2) : nearestPointOnRect(pt1, boundingRect, pt2); // TODO pt2 is in the path + + if (dist < minDist) { + minDist = dist; // Transform back to global space. + + pt1.transform(targetTransform); + pt2.transform(targetTransform); + pt2.toArray(points[0]); + pt1.toArray(points[1]); + pt0.toArray(points[2]); + } + } + + limitTurnAngle(points, labelLineModel.get('minTurnAngle')); + labelLine.setShape({ + points: points + }); + } // Temporal variable for the limitTurnAngle function + + var tmpArr = []; + var tmpProjPoint = new Point(); + /** + * Reduce the line segment attached to the label to limit the turn angle between two segments. + * @param linePoints + * @param minTurnAngle Radian of minimum turn angle. 0 - 180 + */ + + function limitTurnAngle(linePoints, minTurnAngle) { + if (!(minTurnAngle <= 180 && minTurnAngle > 0)) { + return; + } + + minTurnAngle = minTurnAngle / 180 * Math.PI; // The line points can be + // /pt1----pt2 (label) + // / + // pt0/ + + pt0.fromArray(linePoints[0]); + pt1.fromArray(linePoints[1]); + pt2.fromArray(linePoints[2]); + Point.sub(dir, pt0, pt1); + Point.sub(dir2, pt2, pt1); + var len1 = dir.len(); + var len2 = dir2.len(); + + if (len1 < 1e-3 || len2 < 1e-3) { + return; + } + + dir.scale(1 / len1); + dir2.scale(1 / len2); + var angleCos = dir.dot(dir2); + var minTurnAngleCos = Math.cos(minTurnAngle); + + if (minTurnAngleCos < angleCos) { + // Smaller than minTurnAngle + // Calculate project point of pt0 on pt1-pt2 + var d = projectPointToLine(pt1.x, pt1.y, pt2.x, pt2.y, pt0.x, pt0.y, tmpArr, false); + tmpProjPoint.fromArray(tmpArr); // Calculate new projected length with limited minTurnAngle and get the new connect point + + tmpProjPoint.scaleAndAdd(dir2, d / Math.tan(Math.PI - minTurnAngle)); // Limit the new calculated connect point between pt1 and pt2. + + var t = pt2.x !== pt1.x ? (tmpProjPoint.x - pt1.x) / (pt2.x - pt1.x) : (tmpProjPoint.y - pt1.y) / (pt2.y - pt1.y); + + if (isNaN(t)) { + return; + } + + if (t < 0) { + Point.copy(tmpProjPoint, pt1); + } else if (t > 1) { + Point.copy(tmpProjPoint, pt2); + } + + tmpProjPoint.toArray(linePoints[1]); + } + } + /** + * Limit the angle of line and the surface + * @param maxSurfaceAngle Radian of minimum turn angle. 0 - 180. 0 is same direction to normal. 180 is opposite + */ + + function limitSurfaceAngle(linePoints, surfaceNormal, maxSurfaceAngle) { + if (!(maxSurfaceAngle <= 180 && maxSurfaceAngle > 0)) { + return; + } + + maxSurfaceAngle = maxSurfaceAngle / 180 * Math.PI; + pt0.fromArray(linePoints[0]); + pt1.fromArray(linePoints[1]); + pt2.fromArray(linePoints[2]); + Point.sub(dir, pt1, pt0); + Point.sub(dir2, pt2, pt1); + var len1 = dir.len(); + var len2 = dir2.len(); + + if (len1 < 1e-3 || len2 < 1e-3) { + return; + } + + dir.scale(1 / len1); + dir2.scale(1 / len2); + var angleCos = dir.dot(surfaceNormal); + var maxSurfaceAngleCos = Math.cos(maxSurfaceAngle); + + if (angleCos < maxSurfaceAngleCos) { + // Calculate project point of pt0 on pt1-pt2 + var d = projectPointToLine(pt1.x, pt1.y, pt2.x, pt2.y, pt0.x, pt0.y, tmpArr, false); + tmpProjPoint.fromArray(tmpArr); + var HALF_PI = Math.PI / 2; + var angle2 = Math.acos(dir2.dot(surfaceNormal)); + var newAngle = HALF_PI + angle2 - maxSurfaceAngle; + + if (newAngle >= HALF_PI) { + // parallel + Point.copy(tmpProjPoint, pt2); + } else { + // Calculate new projected length with limited minTurnAngle and get the new connect point + tmpProjPoint.scaleAndAdd(dir2, d / Math.tan(Math.PI / 2 - newAngle)); // Limit the new calculated connect point between pt1 and pt2. + + var t = pt2.x !== pt1.x ? (tmpProjPoint.x - pt1.x) / (pt2.x - pt1.x) : (tmpProjPoint.y - pt1.y) / (pt2.y - pt1.y); + + if (isNaN(t)) { + return; + } + + if (t < 0) { + Point.copy(tmpProjPoint, pt1); + } else if (t > 1) { + Point.copy(tmpProjPoint, pt2); + } + } + + tmpProjPoint.toArray(linePoints[1]); + } + } + + function setLabelLineState(labelLine, ignore, stateName, stateModel) { + var isNormal = stateName === 'normal'; + var stateObj = isNormal ? labelLine : labelLine.ensureState(stateName); // Make sure display. + + stateObj.ignore = ignore; // Set smooth + + var smooth = stateModel.get('smooth'); + + if (smooth && smooth === true) { + smooth = 0.3; + } + + stateObj.shape = stateObj.shape || {}; + + if (smooth > 0) { + stateObj.shape.smooth = smooth; + } + + var styleObj = stateModel.getModel('lineStyle').getLineStyle(); + isNormal ? labelLine.useStyle(styleObj) : stateObj.style = styleObj; + } + + function buildLabelLinePath(path, shape) { + var smooth = shape.smooth; + var points = shape.points; + + if (!points) { + return; + } + + path.moveTo(points[0][0], points[0][1]); + + if (smooth > 0 && points.length >= 3) { + var len1 = dist(points[0], points[1]); + var len2 = dist(points[1], points[2]); + + if (!len1 || !len2) { + path.lineTo(points[1][0], points[1][1]); + path.lineTo(points[2][0], points[2][1]); + return; + } + + var moveLen = Math.min(len1, len2) * smooth; + var midPoint0 = lerp([], points[1], points[0], moveLen / len1); + var midPoint2 = lerp([], points[1], points[2], moveLen / len2); + var midPoint1 = lerp([], midPoint0, midPoint2, 0.5); + path.bezierCurveTo(midPoint0[0], midPoint0[1], midPoint0[0], midPoint0[1], midPoint1[0], midPoint1[1]); + path.bezierCurveTo(midPoint2[0], midPoint2[1], midPoint2[0], midPoint2[1], points[2][0], points[2][1]); + } else { + for (var i = 1; i < points.length; i++) { + path.lineTo(points[i][0], points[i][1]); + } + } + } + /** + * Create a label line if necessary and set it's style. + */ + + + function setLabelLineStyle(targetEl, statesModels, defaultStyle) { + var labelLine = targetEl.getTextGuideLine(); + var label = targetEl.getTextContent(); + + if (!label) { + // Not show label line if there is no label. + if (labelLine) { + targetEl.removeTextGuideLine(); + } + + return; + } + + var normalModel = statesModels.normal; + var showNormal = normalModel.get('show'); + var labelIgnoreNormal = label.ignore; + + for (var i = 0; i < DISPLAY_STATES.length; i++) { + var stateName = DISPLAY_STATES[i]; + var stateModel = statesModels[stateName]; + var isNormal = stateName === 'normal'; + + if (stateModel) { + var stateShow = stateModel.get('show'); + var isLabelIgnored = isNormal ? labelIgnoreNormal : retrieve2(label.states[stateName] && label.states[stateName].ignore, labelIgnoreNormal); + + if (isLabelIgnored // Not show when label is not shown in this state. + || !retrieve2(stateShow, showNormal) // Use normal state by default if not set. + ) { + var stateObj = isNormal ? labelLine : labelLine && labelLine.states[stateName]; + + if (stateObj) { + stateObj.ignore = true; + } + + continue; + } // Create labelLine if not exists + + + if (!labelLine) { + labelLine = new Polyline(); + targetEl.setTextGuideLine(labelLine); // Reset state of normal because it's new created. + // NOTE: NORMAL should always been the first! + + if (!isNormal && (labelIgnoreNormal || !showNormal)) { + setLabelLineState(labelLine, true, 'normal', statesModels.normal); + } // Use same state proxy. + + + if (targetEl.stateProxy) { + labelLine.stateProxy = targetEl.stateProxy; + } + } + + setLabelLineState(labelLine, false, stateName, stateModel); + } + } + + if (labelLine) { + defaults(labelLine.style, defaultStyle); // Not fill. + + labelLine.style.fill = null; + var showAbove = normalModel.get('showAbove'); + var labelLineConfig = targetEl.textGuideLineConfig = targetEl.textGuideLineConfig || {}; + labelLineConfig.showAbove = showAbove || false; // Custom the buildPath. + + labelLine.buildPath = buildLabelLinePath; + } + } + function getLabelLineStatesModels(itemModel, labelLineName) { + labelLineName = labelLineName || 'labelLine'; + var statesModels = { + normal: itemModel.getModel(labelLineName) + }; + + for (var i = 0; i < SPECIAL_STATES.length; i++) { + var stateName = SPECIAL_STATES[i]; + statesModels[stateName] = itemModel.getModel([stateName, labelLineName]); + } + + return statesModels; + } + + function prepareLayoutList(input) { + var list = []; + + for (var i = 0; i < input.length; i++) { + var rawItem = input[i]; + + if (rawItem.defaultAttr.ignore) { + continue; + } + + var label = rawItem.label; + var transform = label.getComputedTransform(); // NOTE: Get bounding rect after getComputedTransform, or label may not been updated by the host el. + + var localRect = label.getBoundingRect(); + var isAxisAligned = !transform || transform[1] < 1e-5 && transform[2] < 1e-5; + var minMargin = label.style.margin || 0; + var globalRect = localRect.clone(); + globalRect.applyTransform(transform); + globalRect.x -= minMargin / 2; + globalRect.y -= minMargin / 2; + globalRect.width += minMargin; + globalRect.height += minMargin; + var obb = isAxisAligned ? new OrientedBoundingRect(localRect, transform) : null; + list.push({ + label: label, + labelLine: rawItem.labelLine, + rect: globalRect, + localRect: localRect, + obb: obb, + priority: rawItem.priority, + defaultAttr: rawItem.defaultAttr, + layoutOption: rawItem.computedLayoutOption, + axisAligned: isAxisAligned, + transform: transform + }); + } + + return list; + } + + function shiftLayout(list, xyDim, sizeDim, minBound, maxBound, balanceShift) { + var len = list.length; + + if (len < 2) { + return; + } + + list.sort(function (a, b) { + return a.rect[xyDim] - b.rect[xyDim]; + }); + var lastPos = 0; + var delta; + var adjusted = false; + var totalShifts = 0; + + for (var i = 0; i < len; i++) { + var item = list[i]; + var rect = item.rect; + delta = rect[xyDim] - lastPos; + + if (delta < 0) { + // shiftForward(i, len, -delta); + rect[xyDim] -= delta; + item.label[xyDim] -= delta; + adjusted = true; + } + + var shift = Math.max(-delta, 0); + totalShifts += shift; + lastPos = rect[xyDim] + rect[sizeDim]; + } + + if (totalShifts > 0 && balanceShift) { + // Shift back to make the distribution more equally. + shiftList(-totalShifts / len, 0, len); + } // TODO bleedMargin? + + + var first = list[0]; + var last = list[len - 1]; + var minGap; + var maxGap; + updateMinMaxGap(); // If ends exceed two bounds, squeeze at most 80%, then take the gap of two bounds. + + minGap < 0 && squeezeGaps(-minGap, 0.8); + maxGap < 0 && squeezeGaps(maxGap, 0.8); + updateMinMaxGap(); + takeBoundsGap(minGap, maxGap, 1); + takeBoundsGap(maxGap, minGap, -1); // Handle bailout when there is not enough space. + + updateMinMaxGap(); + + if (minGap < 0) { + squeezeWhenBailout(-minGap); + } + + if (maxGap < 0) { + squeezeWhenBailout(maxGap); + } + + function updateMinMaxGap() { + minGap = first.rect[xyDim] - minBound; + maxGap = maxBound - last.rect[xyDim] - last.rect[sizeDim]; + } + + function takeBoundsGap(gapThisBound, gapOtherBound, moveDir) { + if (gapThisBound < 0) { + // Move from other gap if can. + var moveFromMaxGap = Math.min(gapOtherBound, -gapThisBound); + + if (moveFromMaxGap > 0) { + shiftList(moveFromMaxGap * moveDir, 0, len); + var remained = moveFromMaxGap + gapThisBound; + + if (remained < 0) { + squeezeGaps(-remained * moveDir, 1); + } + } else { + squeezeGaps(-gapThisBound * moveDir, 1); + } + } + } + + function shiftList(delta, start, end) { + if (delta !== 0) { + adjusted = true; + } + + for (var i = start; i < end; i++) { + var item = list[i]; + var rect = item.rect; + rect[xyDim] += delta; + item.label[xyDim] += delta; + } + } // Squeeze gaps if the labels exceed margin. + + + function squeezeGaps(delta, maxSqeezePercent) { + var gaps = []; + var totalGaps = 0; + + for (var i = 1; i < len; i++) { + var prevItemRect = list[i - 1].rect; + var gap = Math.max(list[i].rect[xyDim] - prevItemRect[xyDim] - prevItemRect[sizeDim], 0); + gaps.push(gap); + totalGaps += gap; + } + + if (!totalGaps) { + return; + } + + var squeezePercent = Math.min(Math.abs(delta) / totalGaps, maxSqeezePercent); + + if (delta > 0) { + for (var i = 0; i < len - 1; i++) { + // Distribute the shift delta to all gaps. + var movement = gaps[i] * squeezePercent; // Forward + + shiftList(movement, 0, i + 1); + } + } else { + // Backward + for (var i = len - 1; i > 0; i--) { + // Distribute the shift delta to all gaps. + var movement = gaps[i - 1] * squeezePercent; + shiftList(-movement, i, len); + } + } + } + /** + * Squeeze to allow overlap if there is no more space available. + * Let other overlapping strategy like hideOverlap do the job instead of keep exceeding the bounds. + */ + + + function squeezeWhenBailout(delta) { + var dir = delta < 0 ? -1 : 1; + delta = Math.abs(delta); + var moveForEachLabel = Math.ceil(delta / (len - 1)); + + for (var i = 0; i < len - 1; i++) { + if (dir > 0) { + // Forward + shiftList(moveForEachLabel, 0, i + 1); + } else { + // Backward + shiftList(-moveForEachLabel, len - i - 1, len); + } + + delta -= moveForEachLabel; + + if (delta <= 0) { + return; + } + } + } + + return adjusted; + } + /** + * Adjust labels on x direction to avoid overlap. + */ + + + function shiftLayoutOnX(list, leftBound, rightBound, // If average the shifts on all labels and add them to 0 + // TODO: Not sure if should enable it. + // Pros: The angle of lines will distribute more equally + // Cons: In some layout. It may not what user wanted. like in pie. the label of last sector is usually changed unexpectedly. + balanceShift) { + return shiftLayout(list, 'x', 'width', leftBound, rightBound, balanceShift); + } + /** + * Adjust labels on y direction to avoid overlap. + */ + + function shiftLayoutOnY(list, topBound, bottomBound, // If average the shifts on all labels and add them to 0 + balanceShift) { + return shiftLayout(list, 'y', 'height', topBound, bottomBound, balanceShift); + } + function hideOverlap(labelList) { + var displayedLabels = []; // TODO, render overflow visible first, put in the displayedLabels. + + labelList.sort(function (a, b) { + return b.priority - a.priority; + }); + var globalRect = new BoundingRect(0, 0, 0, 0); + + function hideEl(el) { + if (!el.ignore) { + // Show on emphasis. + var emphasisState = el.ensureState('emphasis'); + + if (emphasisState.ignore == null) { + emphasisState.ignore = false; + } + } + + el.ignore = true; + } + + for (var i = 0; i < labelList.length; i++) { + var labelItem = labelList[i]; + var isAxisAligned = labelItem.axisAligned; + var localRect = labelItem.localRect; + var transform = labelItem.transform; + var label = labelItem.label; + var labelLine = labelItem.labelLine; + globalRect.copy(labelItem.rect); // Add a threshold because layout may be aligned precisely. + + globalRect.width -= 0.1; + globalRect.height -= 0.1; + globalRect.x += 0.05; + globalRect.y += 0.05; + var obb = labelItem.obb; + var overlapped = false; + + for (var j = 0; j < displayedLabels.length; j++) { + var existsTextCfg = displayedLabels[j]; // Fast rejection. + + if (!globalRect.intersect(existsTextCfg.rect)) { + continue; + } + + if (isAxisAligned && existsTextCfg.axisAligned) { + // Is overlapped + overlapped = true; + break; + } + + if (!existsTextCfg.obb) { + // If self is not axis aligned. But other is. + existsTextCfg.obb = new OrientedBoundingRect(existsTextCfg.localRect, existsTextCfg.transform); + } + + if (!obb) { + // If self is axis aligned. But other is not. + obb = new OrientedBoundingRect(localRect, transform); + } + + if (obb.intersect(existsTextCfg.obb)) { + overlapped = true; + break; + } + } // TODO Callback to determine if this overlap should be handled? + + + if (overlapped) { + hideEl(label); + labelLine && hideEl(labelLine); + } else { + label.attr('ignore', labelItem.defaultAttr.ignore); + labelLine && labelLine.attr('ignore', labelItem.defaultAttr.labelGuideIgnore); + displayedLabels.push(labelItem); + } + } + } + + function cloneArr(points) { + if (points) { + var newPoints = []; + + for (var i = 0; i < points.length; i++) { + newPoints.push(points[i].slice()); + } + + return newPoints; + } + } + + function prepareLayoutCallbackParams(labelItem, hostEl) { + var label = labelItem.label; + var labelLine = hostEl && hostEl.getTextGuideLine(); + return { + dataIndex: labelItem.dataIndex, + dataType: labelItem.dataType, + seriesIndex: labelItem.seriesModel.seriesIndex, + text: labelItem.label.style.text, + rect: labelItem.hostRect, + labelRect: labelItem.rect, + // x: labelAttr.x, + // y: labelAttr.y, + align: label.style.align, + verticalAlign: label.style.verticalAlign, + labelLinePoints: cloneArr(labelLine && labelLine.shape.points) + }; + } + + var LABEL_OPTION_TO_STYLE_KEYS = ['align', 'verticalAlign', 'width', 'height', 'fontSize']; + var dummyTransformable = new Transformable(); + var labelLayoutInnerStore = makeInner(); + var labelLineAnimationStore = makeInner(); + + function extendWithKeys(target, source, keys) { + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + + if (source[key] != null) { + target[key] = source[key]; + } + } + } + + var LABEL_LAYOUT_PROPS = ['x', 'y', 'rotation']; + + var LabelManager = + /** @class */ + function () { + function LabelManager() { + this._labelList = []; + this._chartViewList = []; + } + + LabelManager.prototype.clearLabels = function () { + this._labelList = []; + this._chartViewList = []; + }; + /** + * Add label to manager + */ + + + LabelManager.prototype._addLabel = function (dataIndex, dataType, seriesModel, label, layoutOption) { + var labelStyle = label.style; + var hostEl = label.__hostTarget; + var textConfig = hostEl.textConfig || {}; // TODO: If label is in other state. + + var labelTransform = label.getComputedTransform(); + var labelRect = label.getBoundingRect().plain(); + BoundingRect.applyTransform(labelRect, labelRect, labelTransform); + + if (labelTransform) { + dummyTransformable.setLocalTransform(labelTransform); + } else { + // Identity transform. + dummyTransformable.x = dummyTransformable.y = dummyTransformable.rotation = dummyTransformable.originX = dummyTransformable.originY = 0; + dummyTransformable.scaleX = dummyTransformable.scaleY = 1; + } + + var host = label.__hostTarget; + var hostRect; + + if (host) { + hostRect = host.getBoundingRect().plain(); + var transform = host.getComputedTransform(); + BoundingRect.applyTransform(hostRect, hostRect, transform); + } + + var labelGuide = hostRect && host.getTextGuideLine(); + + this._labelList.push({ + label: label, + labelLine: labelGuide, + seriesModel: seriesModel, + dataIndex: dataIndex, + dataType: dataType, + layoutOption: layoutOption, + computedLayoutOption: null, + rect: labelRect, + hostRect: hostRect, + // Label with lower priority will be hidden when overlapped + // Use rect size as default priority + priority: hostRect ? hostRect.width * hostRect.height : 0, + // Save default label attributes. + // For restore if developers want get back to default value in callback. + defaultAttr: { + ignore: label.ignore, + labelGuideIgnore: labelGuide && labelGuide.ignore, + x: dummyTransformable.x, + y: dummyTransformable.y, + scaleX: dummyTransformable.scaleX, + scaleY: dummyTransformable.scaleY, + rotation: dummyTransformable.rotation, + style: { + x: labelStyle.x, + y: labelStyle.y, + align: labelStyle.align, + verticalAlign: labelStyle.verticalAlign, + width: labelStyle.width, + height: labelStyle.height, + fontSize: labelStyle.fontSize + }, + cursor: label.cursor, + attachedPos: textConfig.position, + attachedRot: textConfig.rotation + } + }); + }; + + LabelManager.prototype.addLabelsOfSeries = function (chartView) { + var _this = this; + + this._chartViewList.push(chartView); + + var seriesModel = chartView.__model; + var layoutOption = seriesModel.get('labelLayout'); + /** + * Ignore layouting if it's not specified anything. + */ + + if (!(isFunction(layoutOption) || keys(layoutOption).length)) { + return; + } + + chartView.group.traverse(function (child) { + if (child.ignore) { + return true; // Stop traverse descendants. + } // Only support label being hosted on graphic elements. + + + var textEl = child.getTextContent(); + var ecData = getECData(child); // Can only attach the text on the element with dataIndex + + if (textEl && !textEl.disableLabelLayout) { + _this._addLabel(ecData.dataIndex, ecData.dataType, seriesModel, textEl, layoutOption); + } + }); + }; + + LabelManager.prototype.updateLayoutConfig = function (api) { + var width = api.getWidth(); + var height = api.getHeight(); + + function createDragHandler(el, labelLineModel) { + return function () { + updateLabelLinePoints(el, labelLineModel); + }; + } + + for (var i = 0; i < this._labelList.length; i++) { + var labelItem = this._labelList[i]; + var label = labelItem.label; + var hostEl = label.__hostTarget; + var defaultLabelAttr = labelItem.defaultAttr; + var layoutOption = void 0; // TODO A global layout option? + + if (isFunction(labelItem.layoutOption)) { + layoutOption = labelItem.layoutOption(prepareLayoutCallbackParams(labelItem, hostEl)); + } else { + layoutOption = labelItem.layoutOption; + } + + layoutOption = layoutOption || {}; + labelItem.computedLayoutOption = layoutOption; + var degreeToRadian = Math.PI / 180; // TODO hostEl should always exists. + // Or label should not have parent because the x, y is all in global space. + + if (hostEl) { + hostEl.setTextConfig({ + // Force to set local false. + local: false, + // Ignore position and rotation config on the host el if x or y is changed. + position: layoutOption.x != null || layoutOption.y != null ? null : defaultLabelAttr.attachedPos, + // Ignore rotation config on the host el if rotation is changed. + rotation: layoutOption.rotate != null ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.attachedRot, + offset: [layoutOption.dx || 0, layoutOption.dy || 0] + }); + } + + var needsUpdateLabelLine = false; + + if (layoutOption.x != null) { + // TODO width of chart view. + label.x = parsePercent$1(layoutOption.x, width); + label.setStyle('x', 0); // Ignore movement in style. TODO: origin. + + needsUpdateLabelLine = true; + } else { + label.x = defaultLabelAttr.x; + label.setStyle('x', defaultLabelAttr.style.x); + } + + if (layoutOption.y != null) { + // TODO height of chart view. + label.y = parsePercent$1(layoutOption.y, height); + label.setStyle('y', 0); // Ignore movement in style. + + needsUpdateLabelLine = true; + } else { + label.y = defaultLabelAttr.y; + label.setStyle('y', defaultLabelAttr.style.y); + } + + if (layoutOption.labelLinePoints) { + var guideLine = hostEl.getTextGuideLine(); + + if (guideLine) { + guideLine.setShape({ + points: layoutOption.labelLinePoints + }); // Not update + + needsUpdateLabelLine = false; + } + } + + var labelLayoutStore = labelLayoutInnerStore(label); + labelLayoutStore.needsUpdateLabelLine = needsUpdateLabelLine; + label.rotation = layoutOption.rotate != null ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.rotation; + label.scaleX = defaultLabelAttr.scaleX; + label.scaleY = defaultLabelAttr.scaleY; + + for (var k = 0; k < LABEL_OPTION_TO_STYLE_KEYS.length; k++) { + var key = LABEL_OPTION_TO_STYLE_KEYS[k]; + label.setStyle(key, layoutOption[key] != null ? layoutOption[key] : defaultLabelAttr.style[key]); + } + + if (layoutOption.draggable) { + label.draggable = true; + label.cursor = 'move'; + + if (hostEl) { + var hostModel = labelItem.seriesModel; + + if (labelItem.dataIndex != null) { + var data = labelItem.seriesModel.getData(labelItem.dataType); + hostModel = data.getItemModel(labelItem.dataIndex); + } + + label.on('drag', createDragHandler(hostEl, hostModel.getModel('labelLine'))); + } + } else { + // TODO Other drag functions? + label.off('drag'); + label.cursor = defaultLabelAttr.cursor; + } + } + }; + + LabelManager.prototype.layout = function (api) { + var width = api.getWidth(); + var height = api.getHeight(); + var labelList = prepareLayoutList(this._labelList); + var labelsNeedsAdjustOnX = filter(labelList, function (item) { + return item.layoutOption.moveOverlap === 'shiftX'; + }); + var labelsNeedsAdjustOnY = filter(labelList, function (item) { + return item.layoutOption.moveOverlap === 'shiftY'; + }); + shiftLayoutOnX(labelsNeedsAdjustOnX, 0, width); + shiftLayoutOnY(labelsNeedsAdjustOnY, 0, height); + var labelsNeedsHideOverlap = filter(labelList, function (item) { + return item.layoutOption.hideOverlap; + }); + hideOverlap(labelsNeedsHideOverlap); + }; + /** + * Process all labels. Not only labels with layoutOption. + */ + + + LabelManager.prototype.processLabelsOverall = function () { + var _this = this; + + each(this._chartViewList, function (chartView) { + var seriesModel = chartView.__model; + var ignoreLabelLineUpdate = chartView.ignoreLabelLineUpdate; + var animationEnabled = seriesModel.isAnimationEnabled(); + chartView.group.traverse(function (child) { + if (child.ignore && !child.forceLabelAnimation) { + return true; // Stop traverse descendants. + } + + var needsUpdateLabelLine = !ignoreLabelLineUpdate; + var label = child.getTextContent(); + + if (!needsUpdateLabelLine && label) { + needsUpdateLabelLine = labelLayoutInnerStore(label).needsUpdateLabelLine; + } + + if (needsUpdateLabelLine) { + _this._updateLabelLine(child, seriesModel); + } + + if (animationEnabled) { + _this._animateLabels(child, seriesModel); + } + }); + }); + }; + + LabelManager.prototype._updateLabelLine = function (el, seriesModel) { + // Only support label being hosted on graphic elements. + var textEl = el.getTextContent(); // Update label line style. + + var ecData = getECData(el); + var dataIndex = ecData.dataIndex; // Only support labelLine on the labels represent data. + + if (textEl && dataIndex != null) { + var data = seriesModel.getData(ecData.dataType); + var itemModel = data.getItemModel(dataIndex); + var defaultStyle = {}; + var visualStyle = data.getItemVisual(dataIndex, 'style'); + var visualType = data.getVisual('drawType'); // Default to be same with main color + + defaultStyle.stroke = visualStyle[visualType]; + var labelLineModel = itemModel.getModel('labelLine'); + setLabelLineStyle(el, getLabelLineStatesModels(itemModel), defaultStyle); + updateLabelLinePoints(el, labelLineModel); + } + }; + + LabelManager.prototype._animateLabels = function (el, seriesModel) { + var textEl = el.getTextContent(); + var guideLine = el.getTextGuideLine(); // Animate + + if (textEl // `forceLabelAnimation` has the highest priority + && (el.forceLabelAnimation || !textEl.ignore && !textEl.invisible && !el.disableLabelAnimation && !isElementRemoved(el))) { + var layoutStore = labelLayoutInnerStore(textEl); + var oldLayout = layoutStore.oldLayout; + var ecData = getECData(el); + var dataIndex = ecData.dataIndex; + var newProps = { + x: textEl.x, + y: textEl.y, + rotation: textEl.rotation + }; + var data = seriesModel.getData(ecData.dataType); + + if (!oldLayout) { + textEl.attr(newProps); // Disable fade in animation if value animation is enabled. + + if (!labelInner(textEl).valueAnimation) { + var oldOpacity = retrieve2(textEl.style.opacity, 1); // Fade in animation + + textEl.style.opacity = 0; + initProps(textEl, { + style: { + opacity: oldOpacity + } + }, seriesModel, dataIndex); + } + } else { + textEl.attr(oldLayout); // Make sure the animation from is in the right status. + + var prevStates = el.prevStates; + + if (prevStates) { + if (indexOf(prevStates, 'select') >= 0) { + textEl.attr(layoutStore.oldLayoutSelect); + } + + if (indexOf(prevStates, 'emphasis') >= 0) { + textEl.attr(layoutStore.oldLayoutEmphasis); + } + } + + updateProps(textEl, newProps, seriesModel, dataIndex); + } + + layoutStore.oldLayout = newProps; + + if (textEl.states.select) { + var layoutSelect = layoutStore.oldLayoutSelect = {}; + extendWithKeys(layoutSelect, newProps, LABEL_LAYOUT_PROPS); + extendWithKeys(layoutSelect, textEl.states.select, LABEL_LAYOUT_PROPS); + } + + if (textEl.states.emphasis) { + var layoutEmphasis = layoutStore.oldLayoutEmphasis = {}; + extendWithKeys(layoutEmphasis, newProps, LABEL_LAYOUT_PROPS); + extendWithKeys(layoutEmphasis, textEl.states.emphasis, LABEL_LAYOUT_PROPS); + } + + animateLabelValue(textEl, dataIndex, data, seriesModel, seriesModel); + } + + if (guideLine && !guideLine.ignore && !guideLine.invisible) { + var layoutStore = labelLineAnimationStore(guideLine); + var oldLayout = layoutStore.oldLayout; + var newLayout = { + points: guideLine.shape.points + }; + + if (!oldLayout) { + guideLine.setShape(newLayout); + guideLine.style.strokePercent = 0; + initProps(guideLine, { + style: { + strokePercent: 1 + } + }, seriesModel); + } else { + guideLine.attr({ + shape: oldLayout + }); + updateProps(guideLine, { + shape: newLayout + }, seriesModel); + } + + layoutStore.oldLayout = newLayout; + } + }; + + return LabelManager; + }(); + + var getLabelManager = makeInner(); + function installLabelLayout(registers) { + registers.registerUpdateLifecycle('series:beforeupdate', function (ecModel, api, params) { + // TODO api provide an namespace that can save stuff per instance + var labelManager = getLabelManager(api).labelManager; + + if (!labelManager) { + labelManager = getLabelManager(api).labelManager = new LabelManager(); + } + + labelManager.clearLabels(); + }); + registers.registerUpdateLifecycle('series:layoutlabels', function (ecModel, api, params) { + var labelManager = getLabelManager(api).labelManager; + params.updatedSeries.forEach(function (series) { + labelManager.addLabelsOfSeries(api.getViewOfSeriesModel(series)); + }); + labelManager.updateLayoutConfig(api); + labelManager.layout(api); + labelManager.processLabelsOverall(); + }); + } + + var mathSin$4 = Math.sin; + var mathCos$4 = Math.cos; + var PI$4 = Math.PI; + var PI2$7 = Math.PI * 2; + var degree = 180 / PI$4; + var SVGPathRebuilder = (function () { + function SVGPathRebuilder() { + } + SVGPathRebuilder.prototype.reset = function (precision) { + this._start = true; + this._d = []; + this._str = ''; + this._p = Math.pow(10, precision || 4); + }; + SVGPathRebuilder.prototype.moveTo = function (x, y) { + this._add('M', x, y); + }; + SVGPathRebuilder.prototype.lineTo = function (x, y) { + this._add('L', x, y); + }; + SVGPathRebuilder.prototype.bezierCurveTo = function (x, y, x2, y2, x3, y3) { + this._add('C', x, y, x2, y2, x3, y3); + }; + SVGPathRebuilder.prototype.quadraticCurveTo = function (x, y, x2, y2) { + this._add('Q', x, y, x2, y2); + }; + SVGPathRebuilder.prototype.arc = function (cx, cy, r, startAngle, endAngle, anticlockwise) { + this.ellipse(cx, cy, r, r, 0, startAngle, endAngle, anticlockwise); + }; + SVGPathRebuilder.prototype.ellipse = function (cx, cy, rx, ry, psi, startAngle, endAngle, anticlockwise) { + var dTheta = endAngle - startAngle; + var clockwise = !anticlockwise; + var dThetaPositive = Math.abs(dTheta); + var isCircle = isAroundZero$1(dThetaPositive - PI2$7) + || (clockwise ? dTheta >= PI2$7 : -dTheta >= PI2$7); + var unifiedTheta = dTheta > 0 ? dTheta % PI2$7 : (dTheta % PI2$7 + PI2$7); + var large = false; + if (isCircle) { + large = true; + } + else if (isAroundZero$1(dThetaPositive)) { + large = false; + } + else { + large = (unifiedTheta >= PI$4) === !!clockwise; + } + var x0 = cx + rx * mathCos$4(startAngle); + var y0 = cy + ry * mathSin$4(startAngle); + if (this._start) { + this._add('M', x0, y0); + } + var xRot = Math.round(psi * degree); + if (isCircle) { + var p = 1 / this._p; + var dTheta_1 = (clockwise ? 1 : -1) * (PI2$7 - p); + this._add('A', rx, ry, xRot, 1, +clockwise, cx + rx * mathCos$4(startAngle + dTheta_1), cy + ry * mathSin$4(startAngle + dTheta_1)); + if (p > 1e-2) { + this._add('A', rx, ry, xRot, 0, +clockwise, x0, y0); + } + } + else { + var x = cx + rx * mathCos$4(endAngle); + var y = cy + ry * mathSin$4(endAngle); + this._add('A', rx, ry, xRot, +large, +clockwise, x, y); + } + }; + SVGPathRebuilder.prototype.rect = function (x, y, w, h) { + this._add('M', x, y); + this._add('l', w, 0); + this._add('l', 0, h); + this._add('l', -w, 0); + this._add('Z'); + }; + SVGPathRebuilder.prototype.closePath = function () { + if (this._d.length > 0) { + this._add('Z'); + } + }; + SVGPathRebuilder.prototype._add = function (cmd, a, b, c, d, e, f, g, h) { + var vals = []; + var p = this._p; + for (var i = 1; i < arguments.length; i++) { + var val = arguments[i]; + if (isNaN(val)) { + this._invalid = true; + return; + } + vals.push(Math.round(val * p) / p); + } + this._d.push(cmd + vals.join(' ')); + this._start = cmd === 'Z'; + }; + SVGPathRebuilder.prototype.generateStr = function () { + this._str = this._invalid ? '' : this._d.join(''); + this._d = []; + }; + SVGPathRebuilder.prototype.getStr = function () { + return this._str; + }; + return SVGPathRebuilder; + }()); + + var NONE = 'none'; + var mathRound$1 = Math.round; + function pathHasFill(style) { + var fill = style.fill; + return fill != null && fill !== NONE; + } + function pathHasStroke(style) { + var stroke = style.stroke; + return stroke != null && stroke !== NONE; + } + var strokeProps = ['lineCap', 'miterLimit', 'lineJoin']; + var svgStrokeProps = map(strokeProps, function (prop) { return "stroke-" + prop.toLowerCase(); }); + function mapStyleToAttrs(updateAttr, style, el, forceUpdate) { + var opacity = style.opacity == null ? 1 : style.opacity; + if (el instanceof ZRImage) { + updateAttr('opacity', opacity); + return; + } + if (pathHasFill(style)) { + var fill = normalizeColor(style.fill); + updateAttr('fill', fill.color); + var fillOpacity = style.fillOpacity != null + ? style.fillOpacity * fill.opacity * opacity + : fill.opacity * opacity; + if (forceUpdate || fillOpacity < 1) { + updateAttr('fill-opacity', fillOpacity); + } + } + else { + updateAttr('fill', NONE); + } + if (pathHasStroke(style)) { + var stroke = normalizeColor(style.stroke); + updateAttr('stroke', stroke.color); + var strokeScale = style.strokeNoScale + ? el.getLineScale() + : 1; + var strokeWidth = (strokeScale ? (style.lineWidth || 0) / strokeScale : 0); + var strokeOpacity = style.strokeOpacity != null + ? style.strokeOpacity * stroke.opacity * opacity + : stroke.opacity * opacity; + var strokeFirst = style.strokeFirst; + if (forceUpdate || strokeWidth !== 1) { + updateAttr('stroke-width', strokeWidth); + } + if (forceUpdate || strokeFirst) { + updateAttr('paint-order', strokeFirst ? 'stroke' : 'fill'); + } + if (forceUpdate || strokeOpacity < 1) { + updateAttr('stroke-opacity', strokeOpacity); + } + if (style.lineDash) { + var _a = getLineDash(el), lineDash = _a[0], lineDashOffset = _a[1]; + if (lineDash) { + lineDashOffset = mathRound$1(lineDashOffset || 0); + updateAttr('stroke-dasharray', lineDash.join(',')); + if (lineDashOffset || forceUpdate) { + updateAttr('stroke-dashoffset', lineDashOffset); + } + } + } + else if (forceUpdate) { + updateAttr('stroke-dasharray', NONE); + } + for (var i = 0; i < strokeProps.length; i++) { + var propName = strokeProps[i]; + if (forceUpdate || style[propName] !== DEFAULT_PATH_STYLE[propName]) { + var val = style[propName] || DEFAULT_PATH_STYLE[propName]; + val && updateAttr(svgStrokeProps[i], val); + } + } + } + else if (forceUpdate) { + updateAttr('stroke', NONE); + } + } + + var SVGNS = 'http://www.w3.org/2000/svg'; + var XLINKNS = 'http://www.w3.org/1999/xlink'; + var XMLNS = 'http://www.w3.org/2000/xmlns/'; + var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace'; + function createElement(name) { + return document.createElementNS(SVGNS, name); + } + function createVNode(tag, key, attrs, children, text) { + return { + tag: tag, + attrs: attrs || {}, + children: children, + text: text, + key: key + }; + } + function createElementOpen(name, attrs) { + var attrsStr = []; + if (attrs) { + for (var key in attrs) { + var val = attrs[key]; + var part = key; + if (val === false) { + continue; + } + else if (val !== true && val != null) { + part += "=\"" + val + "\""; + } + attrsStr.push(part); + } + } + return "<" + name + " " + attrsStr.join(' ') + ">"; + } + function createElementClose(name) { + return ""; + } + function vNodeToString(el, opts) { + opts = opts || {}; + var S = opts.newline ? '\n' : ''; + function convertElToString(el) { + var children = el.children, tag = el.tag, attrs = el.attrs; + return createElementOpen(tag, attrs) + + (el.text || '') + + (children ? "" + S + map(children, function (child) { return convertElToString(child); }).join(S) + S : '') + + createElementClose(tag); + } + return convertElToString(el); + } + function getCssString(selectorNodes, animationNodes, opts) { + opts = opts || {}; + var S = opts.newline ? '\n' : ''; + var bracketBegin = " {" + S; + var bracketEnd = S + "}"; + var selectors = map(keys(selectorNodes), function (className) { + return className + bracketBegin + map(keys(selectorNodes[className]), function (attrName) { + return attrName + ":" + selectorNodes[className][attrName] + ";"; + }).join(S) + bracketEnd; + }).join(S); + var animations = map(keys(animationNodes), function (animationName) { + return "@keyframes " + animationName + bracketBegin + map(keys(animationNodes[animationName]), function (percent) { + return percent + bracketBegin + map(keys(animationNodes[animationName][percent]), function (attrName) { + var val = animationNodes[animationName][percent][attrName]; + if (attrName === 'd') { + val = "path(\"" + val + "\")"; + } + return attrName + ":" + val + ";"; + }).join(S) + bracketEnd; + }).join(S) + bracketEnd; + }).join(S); + if (!selectors && !animations) { + return ''; + } + return [''].join(S); + } + function createBrushScope(zrId) { + return { + zrId: zrId, + shadowCache: {}, + patternCache: {}, + gradientCache: {}, + clipPathCache: {}, + defs: {}, + cssNodes: {}, + cssAnims: {}, + cssClassIdx: 0, + cssAnimIdx: 0, + shadowIdx: 0, + gradientIdx: 0, + patternIdx: 0, + clipPathIdx: 0 + }; + } + function createSVGVNode(width, height, children, useViewBox) { + return createVNode('svg', 'root', { + 'width': width, + 'height': height, + 'xmlns': SVGNS, + 'xmlns:xlink': XLINKNS, + 'version': '1.1', + 'baseProfile': 'full', + 'viewBox': useViewBox ? "0 0 " + width + " " + height : false + }, children); + } + + var EASING_MAP = { + cubicIn: '0.32,0,0.67,0', + cubicOut: '0.33,1,0.68,1', + cubicInOut: '0.65,0,0.35,1', + quadraticIn: '0.11,0,0.5,0', + quadraticOut: '0.5,1,0.89,1', + quadraticInOut: '0.45,0,0.55,1', + quarticIn: '0.5,0,0.75,0', + quarticOut: '0.25,1,0.5,1', + quarticInOut: '0.76,0,0.24,1', + quinticIn: '0.64,0,0.78,0', + quinticOut: '0.22,1,0.36,1', + quinticInOut: '0.83,0,0.17,1', + sinusoidalIn: '0.12,0,0.39,0', + sinusoidalOut: '0.61,1,0.88,1', + sinusoidalInOut: '0.37,0,0.63,1', + exponentialIn: '0.7,0,0.84,0', + exponentialOut: '0.16,1,0.3,1', + exponentialInOut: '0.87,0,0.13,1', + circularIn: '0.55,0,1,0.45', + circularOut: '0,0.55,0.45,1', + circularInOut: '0.85,0,0.15,1' + }; + var transformOriginKey = 'transform-origin'; + function buildPathString(el, kfShape, path) { + var shape = extend({}, el.shape); + extend(shape, kfShape); + el.buildPath(path, shape); + var svgPathBuilder = new SVGPathRebuilder(); + svgPathBuilder.reset(getPathPrecision(el)); + path.rebuildPath(svgPathBuilder, 1); + svgPathBuilder.generateStr(); + return svgPathBuilder.getStr(); + } + function setTransformOrigin(target, transform) { + var originX = transform.originX, originY = transform.originY; + if (originX || originY) { + target[transformOriginKey] = originX + "px " + originY + "px"; + } + } + var ANIMATE_STYLE_MAP = { + fill: 'fill', + opacity: 'opacity', + lineWidth: 'stroke-width', + lineDashOffset: 'stroke-dashoffset' + }; + function addAnimation(cssAnim, scope) { + var animationName = scope.zrId + '-ani-' + scope.cssAnimIdx++; + scope.cssAnims[animationName] = cssAnim; + return animationName; + } + function createCompoundPathCSSAnimation(el, attrs, scope) { + var paths = el.shape.paths; + var composedAnim = {}; + var cssAnimationCfg; + var cssAnimationName; + each(paths, function (path) { + var subScope = createBrushScope(scope.zrId); + subScope.animation = true; + createCSSAnimation(path, {}, subScope, true); + var cssAnims = subScope.cssAnims; + var cssNodes = subScope.cssNodes; + var animNames = keys(cssAnims); + var len = animNames.length; + if (!len) { + return; + } + cssAnimationName = animNames[len - 1]; + var lastAnim = cssAnims[cssAnimationName]; + for (var percent in lastAnim) { + var kf = lastAnim[percent]; + composedAnim[percent] = composedAnim[percent] || { d: '' }; + composedAnim[percent].d += kf.d || ''; + } + for (var className in cssNodes) { + var val = cssNodes[className].animation; + if (val.indexOf(cssAnimationName) >= 0) { + cssAnimationCfg = val; + } + } + }); + if (!cssAnimationCfg) { + return; + } + attrs.d = false; + var animationName = addAnimation(composedAnim, scope); + return cssAnimationCfg.replace(cssAnimationName, animationName); + } + function getEasingFunc(easing) { + return isString(easing) + ? EASING_MAP[easing] + ? "cubic-bezier(" + EASING_MAP[easing] + ")" + : createCubicEasingFunc(easing) ? easing : '' + : ''; + } + function createCSSAnimation(el, attrs, scope, onlyShape) { + var animators = el.animators; + var len = animators.length; + var cssAnimations = []; + if (el instanceof CompoundPath) { + var animationCfg = createCompoundPathCSSAnimation(el, attrs, scope); + if (animationCfg) { + cssAnimations.push(animationCfg); + } + else if (!len) { + return; + } + } + else if (!len) { + return; + } + var groupAnimators = {}; + for (var i = 0; i < len; i++) { + var animator = animators[i]; + var cfgArr = [animator.getMaxTime() / 1000 + 's']; + var easing = getEasingFunc(animator.getClip().easing); + var delay = animator.getDelay(); + if (easing) { + cfgArr.push(easing); + } + else { + cfgArr.push('linear'); + } + if (delay) { + cfgArr.push(delay / 1000 + 's'); + } + if (animator.getLoop()) { + cfgArr.push('infinite'); + } + var cfg = cfgArr.join(' '); + groupAnimators[cfg] = groupAnimators[cfg] || [cfg, []]; + groupAnimators[cfg][1].push(animator); + } + function createSingleCSSAnimation(groupAnimator) { + var animators = groupAnimator[1]; + var len = animators.length; + var transformKfs = {}; + var shapeKfs = {}; + var finalKfs = {}; + var animationTimingFunctionAttrName = 'animation-timing-function'; + function saveAnimatorTrackToCssKfs(animator, cssKfs, toCssAttrName) { + var tracks = animator.getTracks(); + var maxTime = animator.getMaxTime(); + for (var k = 0; k < tracks.length; k++) { + var track = tracks[k]; + if (track.needsAnimate()) { + var kfs = track.keyframes; + var attrName = track.propName; + toCssAttrName && (attrName = toCssAttrName(attrName)); + if (attrName) { + for (var i = 0; i < kfs.length; i++) { + var kf = kfs[i]; + var percent = Math.round(kf.time / maxTime * 100) + '%'; + var kfEasing = getEasingFunc(kf.easing); + var rawValue = kf.rawValue; + if (isString(rawValue) || isNumber(rawValue)) { + cssKfs[percent] = cssKfs[percent] || {}; + cssKfs[percent][attrName] = kf.rawValue; + if (kfEasing) { + cssKfs[percent][animationTimingFunctionAttrName] = kfEasing; + } + } + } + } + } + } + } + for (var i = 0; i < len; i++) { + var animator = animators[i]; + var targetProp = animator.targetName; + if (!targetProp) { + !onlyShape && saveAnimatorTrackToCssKfs(animator, transformKfs); + } + else if (targetProp === 'shape') { + saveAnimatorTrackToCssKfs(animator, shapeKfs); + } + } + for (var percent in transformKfs) { + var transform = {}; + copyTransform(transform, el); + extend(transform, transformKfs[percent]); + var str = getSRTTransformString(transform); + var timingFunction = transformKfs[percent][animationTimingFunctionAttrName]; + finalKfs[percent] = str ? { + transform: str + } : {}; + setTransformOrigin(finalKfs[percent], transform); + if (timingFunction) { + finalKfs[percent][animationTimingFunctionAttrName] = timingFunction; + } + } + var path; + var canAnimateShape = true; + for (var percent in shapeKfs) { + finalKfs[percent] = finalKfs[percent] || {}; + var isFirst = !path; + var timingFunction = shapeKfs[percent][animationTimingFunctionAttrName]; + if (isFirst) { + path = new PathProxy(); + } + var len_1 = path.len(); + path.reset(); + finalKfs[percent].d = buildPathString(el, shapeKfs[percent], path); + var newLen = path.len(); + if (!isFirst && len_1 !== newLen) { + canAnimateShape = false; + break; + } + if (timingFunction) { + finalKfs[percent][animationTimingFunctionAttrName] = timingFunction; + } + } + if (!canAnimateShape) { + for (var percent in finalKfs) { + delete finalKfs[percent].d; + } + } + if (!onlyShape) { + for (var i = 0; i < len; i++) { + var animator = animators[i]; + var targetProp = animator.targetName; + if (targetProp === 'style') { + saveAnimatorTrackToCssKfs(animator, finalKfs, function (propName) { return ANIMATE_STYLE_MAP[propName]; }); + } + } + } + var percents = keys(finalKfs); + var allTransformOriginSame = true; + var transformOrigin; + for (var i = 1; i < percents.length; i++) { + var p0 = percents[i - 1]; + var p1 = percents[i]; + if (finalKfs[p0][transformOriginKey] !== finalKfs[p1][transformOriginKey]) { + allTransformOriginSame = false; + break; + } + transformOrigin = finalKfs[p0][transformOriginKey]; + } + if (allTransformOriginSame && transformOrigin) { + for (var percent in finalKfs) { + if (finalKfs[percent][transformOriginKey]) { + delete finalKfs[percent][transformOriginKey]; + } + } + attrs[transformOriginKey] = transformOrigin; + } + if (filter(percents, function (percent) { return keys(finalKfs[percent]).length > 0; }).length) { + var animationName = addAnimation(finalKfs, scope); + return animationName + " " + groupAnimator[0] + " both"; + } + } + for (var key in groupAnimators) { + var animationCfg = createSingleCSSAnimation(groupAnimators[key]); + if (animationCfg) { + cssAnimations.push(animationCfg); + } + } + if (cssAnimations.length) { + var className = scope.zrId + '-cls-' + scope.cssClassIdx++; + scope.cssNodes['.' + className] = { + animation: cssAnimations.join(',') + }; + attrs["class"] = className; + } + } + + var round$2 = Math.round; + function isImageLike$1(val) { + return val && isString(val.src); + } + function isCanvasLike(val) { + return val && isFunction(val.toDataURL); + } + function setStyleAttrs(attrs, style, el, scope) { + mapStyleToAttrs(function (key, val) { + var isFillStroke = key === 'fill' || key === 'stroke'; + if (isFillStroke && isGradient(val)) { + setGradient(style, attrs, key, scope); + } + else if (isFillStroke && isPattern(val)) { + setPattern(el, attrs, key, scope); + } + else { + attrs[key] = val; + } + }, style, el, false); + setShadow(el, attrs, scope); + } + function noRotateScale(m) { + return isAroundZero$1(m[0] - 1) + && isAroundZero$1(m[1]) + && isAroundZero$1(m[2]) + && isAroundZero$1(m[3] - 1); + } + function noTranslate(m) { + return isAroundZero$1(m[4]) && isAroundZero$1(m[5]); + } + function setTransform(attrs, m, compress) { + if (m && !(noTranslate(m) && noRotateScale(m))) { + var mul = compress ? 10 : 1e4; + attrs.transform = noRotateScale(m) + ? "translate(" + round$2(m[4] * mul) / mul + " " + round$2(m[5] * mul) / mul + ")" : getMatrixStr(m); + } + } + function convertPolyShape(shape, attrs, mul) { + var points = shape.points; + var strArr = []; + for (var i = 0; i < points.length; i++) { + strArr.push(round$2(points[i][0] * mul) / mul); + strArr.push(round$2(points[i][1] * mul) / mul); + } + attrs.points = strArr.join(' '); + } + function validatePolyShape(shape) { + return !shape.smooth; + } + function createAttrsConvert(desc) { + var normalizedDesc = map(desc, function (item) { + return (typeof item === 'string' ? [item, item] : item); + }); + return function (shape, attrs, mul) { + for (var i = 0; i < normalizedDesc.length; i++) { + var item = normalizedDesc[i]; + var val = shape[item[0]]; + if (val != null) { + attrs[item[1]] = round$2(val * mul) / mul; + } + } + }; + } + var buitinShapesDef = { + circle: [createAttrsConvert(['cx', 'cy', 'r'])], + polyline: [convertPolyShape, validatePolyShape], + polygon: [convertPolyShape, validatePolyShape] + }; + function hasShapeAnimation(el) { + var animators = el.animators; + for (var i = 0; i < animators.length; i++) { + if (animators[i].targetName === 'shape') { + return true; + } + } + return false; + } + function brushSVGPath(el, scope) { + var style = el.style; + var shape = el.shape; + var builtinShpDef = buitinShapesDef[el.type]; + var attrs = {}; + var needsAnimate = scope.animation; + var svgElType = 'path'; + var strokePercent = el.style.strokePercent; + var precision = (scope.compress && getPathPrecision(el)) || 4; + if (builtinShpDef + && !scope.willUpdate + && !(builtinShpDef[1] && !builtinShpDef[1](shape)) + && !(needsAnimate && hasShapeAnimation(el)) + && !(strokePercent < 1)) { + svgElType = el.type; + var mul = Math.pow(10, precision); + builtinShpDef[0](shape, attrs, mul); + } + else { + if (!el.path) { + el.createPathProxy(); + } + var path = el.path; + if (el.shapeChanged()) { + path.beginPath(); + el.buildPath(path, el.shape); + el.pathUpdated(); + } + var pathVersion = path.getVersion(); + var elExt = el; + var svgPathBuilder = elExt.__svgPathBuilder; + if (elExt.__svgPathVersion !== pathVersion + || !svgPathBuilder + || strokePercent !== elExt.__svgPathStrokePercent) { + if (!svgPathBuilder) { + svgPathBuilder = elExt.__svgPathBuilder = new SVGPathRebuilder(); + } + svgPathBuilder.reset(precision); + path.rebuildPath(svgPathBuilder, strokePercent); + svgPathBuilder.generateStr(); + elExt.__svgPathVersion = pathVersion; + elExt.__svgPathStrokePercent = strokePercent; + } + attrs.d = svgPathBuilder.getStr(); + } + setTransform(attrs, el.transform); + setStyleAttrs(attrs, style, el, scope); + scope.animation && createCSSAnimation(el, attrs, scope); + return createVNode(svgElType, el.id + '', attrs); + } + function brushSVGImage(el, scope) { + var style = el.style; + var image = style.image; + if (image && !isString(image)) { + if (isImageLike$1(image)) { + image = image.src; + } + else if (isCanvasLike(image)) { + image = image.toDataURL(); + } + } + if (!image) { + return; + } + var x = style.x || 0; + var y = style.y || 0; + var dw = style.width; + var dh = style.height; + var attrs = { + href: image, + width: dw, + height: dh + }; + if (x) { + attrs.x = x; + } + if (y) { + attrs.y = y; + } + setTransform(attrs, el.transform); + setStyleAttrs(attrs, style, el, scope); + scope.animation && createCSSAnimation(el, attrs, scope); + return createVNode('image', el.id + '', attrs); + } + function brushSVGTSpan(el, scope) { + var style = el.style; + var text = style.text; + text != null && (text += ''); + if (!text || isNaN(style.x) || isNaN(style.y)) { + return; + } + var font = style.font || DEFAULT_FONT; + var x = style.x || 0; + var y = adjustTextY(style.y || 0, getLineHeight(font), style.textBaseline); + var textAlign = TEXT_ALIGN_TO_ANCHOR[style.textAlign] + || style.textAlign; + var attrs = { + 'dominant-baseline': 'central', + 'text-anchor': textAlign + }; + if (hasSeparateFont(style)) { + var separatedFontStr = ''; + var fontStyle = style.fontStyle; + var fontSize = parseFontSize(style.fontSize); + if (!parseFloat(fontSize)) { + return; + } + var fontFamily = style.fontFamily || DEFAULT_FONT_FAMILY; + var fontWeight = style.fontWeight; + separatedFontStr += "font-size:" + fontSize + ";font-family:" + fontFamily + ";"; + if (fontStyle && fontStyle !== 'normal') { + separatedFontStr += "font-style:" + fontStyle + ";"; + } + if (fontWeight && fontWeight !== 'normal') { + separatedFontStr += "font-weight:" + fontWeight + ";"; + } + attrs.style = separatedFontStr; + } + else { + attrs.style = "font: " + font; + } + if (text.match(/\s/)) { + attrs['xml:space'] = 'preserve'; + } + if (x) { + attrs.x = x; + } + if (y) { + attrs.y = y; + } + setTransform(attrs, el.transform); + setStyleAttrs(attrs, style, el, scope); + scope.animation && createCSSAnimation(el, attrs, scope); + return createVNode('text', el.id + '', attrs, undefined, text); + } + function brush$1(el, scope) { + if (el instanceof Path) { + return brushSVGPath(el, scope); + } + else if (el instanceof ZRImage) { + return brushSVGImage(el, scope); + } + else if (el instanceof TSpan) { + return brushSVGTSpan(el, scope); + } + } + function setShadow(el, attrs, scope) { + var style = el.style; + if (hasShadow(style)) { + var shadowKey = getShadowKey(el); + var shadowCache = scope.shadowCache; + var shadowId = shadowCache[shadowKey]; + if (!shadowId) { + var globalScale = el.getGlobalScale(); + var scaleX = globalScale[0]; + var scaleY = globalScale[1]; + if (!scaleX || !scaleY) { + return; + } + var offsetX = style.shadowOffsetX || 0; + var offsetY = style.shadowOffsetY || 0; + var blur_1 = style.shadowBlur; + var _a = normalizeColor(style.shadowColor), opacity = _a.opacity, color = _a.color; + var stdDx = blur_1 / 2 / scaleX; + var stdDy = blur_1 / 2 / scaleY; + var stdDeviation = stdDx + ' ' + stdDy; + shadowId = scope.zrId + '-s' + scope.shadowIdx++; + scope.defs[shadowId] = createVNode('filter', shadowId, { + 'id': shadowId, + 'x': '-100%', + 'y': '-100%', + 'width': '300%', + 'height': '300%' + }, [ + createVNode('feDropShadow', '', { + 'dx': offsetX / scaleX, + 'dy': offsetY / scaleY, + 'stdDeviation': stdDeviation, + 'flood-color': color, + 'flood-opacity': opacity + }) + ]); + shadowCache[shadowKey] = shadowId; + } + attrs.filter = getIdURL(shadowId); + } + } + function setGradient(style, attrs, target, scope) { + var val = style[target]; + var gradientTag; + var gradientAttrs = { + 'gradientUnits': val.global + ? 'userSpaceOnUse' + : 'objectBoundingBox' + }; + if (isLinearGradient(val)) { + gradientTag = 'linearGradient'; + gradientAttrs.x1 = val.x; + gradientAttrs.y1 = val.y; + gradientAttrs.x2 = val.x2; + gradientAttrs.y2 = val.y2; + } + else if (isRadialGradient(val)) { + gradientTag = 'radialGradient'; + gradientAttrs.cx = retrieve2(val.x, 0.5); + gradientAttrs.cy = retrieve2(val.y, 0.5); + gradientAttrs.r = retrieve2(val.r, 0.5); + } + else { + if ("development" !== 'production') { + logError('Illegal gradient type.'); + } + return; + } + var colors = val.colorStops; + var colorStops = []; + for (var i = 0, len = colors.length; i < len; ++i) { + var offset = round4(colors[i].offset) * 100 + '%'; + var stopColor = colors[i].color; + var _a = normalizeColor(stopColor), color = _a.color, opacity = _a.opacity; + var stopsAttrs = { + 'offset': offset + }; + stopsAttrs['stop-color'] = color; + if (opacity < 1) { + stopsAttrs['stop-opacity'] = opacity; + } + colorStops.push(createVNode('stop', i + '', stopsAttrs)); + } + var gradientVNode = createVNode(gradientTag, '', gradientAttrs, colorStops); + var gradientKey = vNodeToString(gradientVNode); + var gradientCache = scope.gradientCache; + var gradientId = gradientCache[gradientKey]; + if (!gradientId) { + gradientId = scope.zrId + '-g' + scope.gradientIdx++; + gradientCache[gradientKey] = gradientId; + gradientAttrs.id = gradientId; + scope.defs[gradientId] = createVNode(gradientTag, gradientId, gradientAttrs, colorStops); + } + attrs[target] = getIdURL(gradientId); + } + function setPattern(el, attrs, target, scope) { + var val = el.style[target]; + var patternAttrs = { + 'patternUnits': 'userSpaceOnUse' + }; + var child; + if (isImagePattern(val)) { + var imageWidth_1 = val.imageWidth; + var imageHeight_1 = val.imageHeight; + var imageSrc = void 0; + var patternImage = val.image; + if (isString(patternImage)) { + imageSrc = patternImage; + } + else if (isImageLike$1(patternImage)) { + imageSrc = patternImage.src; + } + else if (isCanvasLike(patternImage)) { + imageSrc = patternImage.toDataURL(); + } + if (typeof Image === 'undefined') { + var errMsg = 'Image width/height must been given explictly in svg-ssr renderer.'; + assert(imageWidth_1, errMsg); + assert(imageHeight_1, errMsg); + } + else if (imageWidth_1 == null || imageHeight_1 == null) { + var setSizeToVNode_1 = function (vNode, img) { + if (vNode) { + var svgEl = vNode.elm; + var width = (vNode.attrs.width = imageWidth_1 || img.width); + var height = (vNode.attrs.height = imageHeight_1 || img.height); + if (svgEl) { + svgEl.setAttribute('width', width); + svgEl.setAttribute('height', height); + } + } + }; + var createdImage = createOrUpdateImage(imageSrc, null, el, function (img) { + setSizeToVNode_1(patternVNode, img); + setSizeToVNode_1(child, img); + }); + if (createdImage && createdImage.width && createdImage.height) { + imageWidth_1 = imageWidth_1 || createdImage.width; + imageHeight_1 = imageHeight_1 || createdImage.height; + } + } + child = createVNode('image', 'img', { + href: imageSrc, + width: imageWidth_1, + height: imageHeight_1 + }); + patternAttrs.width = imageWidth_1; + patternAttrs.height = imageHeight_1; + } + else if (val.svgElement) { + child = clone(val.svgElement); + patternAttrs.width = val.svgWidth; + patternAttrs.height = val.svgHeight; + } + if (!child) { + return; + } + patternAttrs.patternTransform = getSRTTransformString(val); + var patternVNode = createVNode('pattern', '', patternAttrs, [child]); + var patternKey = vNodeToString(patternVNode); + var patternCache = scope.patternCache; + var patternId = patternCache[patternKey]; + if (!patternId) { + patternId = scope.zrId + '-p' + scope.patternIdx++; + patternCache[patternKey] = patternId; + patternAttrs.id = patternId; + patternVNode = scope.defs[patternId] = createVNode('pattern', patternId, patternAttrs, [child]); + } + attrs[target] = getIdURL(patternId); + } + function setClipPath(clipPath, attrs, scope) { + var clipPathCache = scope.clipPathCache, defs = scope.defs; + var clipPathId = clipPathCache[clipPath.id]; + if (!clipPathId) { + clipPathId = scope.zrId + '-c' + scope.clipPathIdx++; + var clipPathAttrs = { + id: clipPathId + }; + clipPathCache[clipPath.id] = clipPathId; + defs[clipPathId] = createVNode('clipPath', clipPathId, clipPathAttrs, [brushSVGPath(clipPath, scope)]); + } + attrs['clip-path'] = getIdURL(clipPathId); + } + + function createTextNode(text) { + return document.createTextNode(text); + } + function insertBefore(parentNode, newNode, referenceNode) { + parentNode.insertBefore(newNode, referenceNode); + } + function removeChild(node, child) { + node.removeChild(child); + } + function appendChild(node, child) { + node.appendChild(child); + } + function parentNode(node) { + return node.parentNode; + } + function nextSibling(node) { + return node.nextSibling; + } + function setTextContent(node, text) { + node.textContent = text; + } + + var colonChar = 58; + var xChar = 120; + var emptyNode = createVNode('', ''); + function isUndef(s) { + return s === undefined; + } + function isDef(s) { + return s !== undefined; + } + function createKeyToOldIdx(children, beginIdx, endIdx) { + var map = {}; + for (var i = beginIdx; i <= endIdx; ++i) { + var key = children[i].key; + if (key !== undefined) { + if ("development" !== 'production') { + if (map[key] != null) { + console.error("Duplicate key " + key); + } + } + map[key] = i; + } + } + return map; + } + function sameVnode(vnode1, vnode2) { + var isSameKey = vnode1.key === vnode2.key; + var isSameTag = vnode1.tag === vnode2.tag; + return isSameTag && isSameKey; + } + function createElm(vnode) { + var i; + var children = vnode.children; + var tag = vnode.tag; + if (isDef(tag)) { + var elm = (vnode.elm = createElement(tag)); + updateAttrs(emptyNode, vnode); + if (isArray(children)) { + for (i = 0; i < children.length; ++i) { + var ch = children[i]; + if (ch != null) { + appendChild(elm, createElm(ch)); + } + } + } + else if (isDef(vnode.text) && !isObject(vnode.text)) { + appendChild(elm, createTextNode(vnode.text)); + } + } + else { + vnode.elm = createTextNode(vnode.text); + } + return vnode.elm; + } + function addVnodes(parentElm, before, vnodes, startIdx, endIdx) { + for (; startIdx <= endIdx; ++startIdx) { + var ch = vnodes[startIdx]; + if (ch != null) { + insertBefore(parentElm, createElm(ch), before); + } + } + } + function removeVnodes(parentElm, vnodes, startIdx, endIdx) { + for (; startIdx <= endIdx; ++startIdx) { + var ch = vnodes[startIdx]; + if (ch != null) { + if (isDef(ch.tag)) { + var parent_1 = parentNode(ch.elm); + removeChild(parent_1, ch.elm); + } + else { + removeChild(parentElm, ch.elm); + } + } + } + } + function updateAttrs(oldVnode, vnode) { + var key; + var elm = vnode.elm; + var oldAttrs = oldVnode && oldVnode.attrs || {}; + var attrs = vnode.attrs || {}; + if (oldAttrs === attrs) { + return; + } + for (key in attrs) { + var cur = attrs[key]; + var old = oldAttrs[key]; + if (old !== cur) { + if (cur === true) { + elm.setAttribute(key, ''); + } + else if (cur === false) { + elm.removeAttribute(key); + } + else { + if (key.charCodeAt(0) !== xChar) { + elm.setAttribute(key, cur); + } + else if (key === 'xmlns:xlink' || key === 'xmlns') { + elm.setAttributeNS(XMLNS, key, cur); + } + else if (key.charCodeAt(3) === colonChar) { + elm.setAttributeNS(XML_NAMESPACE, key, cur); + } + else if (key.charCodeAt(5) === colonChar) { + elm.setAttributeNS(XLINKNS, key, cur); + } + else { + elm.setAttribute(key, cur); + } + } + } + } + for (key in oldAttrs) { + if (!(key in attrs)) { + elm.removeAttribute(key); + } + } + } + function updateChildren(parentElm, oldCh, newCh) { + var oldStartIdx = 0; + var newStartIdx = 0; + var oldEndIdx = oldCh.length - 1; + var oldStartVnode = oldCh[0]; + var oldEndVnode = oldCh[oldEndIdx]; + var newEndIdx = newCh.length - 1; + var newStartVnode = newCh[0]; + var newEndVnode = newCh[newEndIdx]; + var oldKeyToIdx; + var idxInOld; + var elmToMove; + var before; + while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { + if (oldStartVnode == null) { + oldStartVnode = oldCh[++oldStartIdx]; + } + else if (oldEndVnode == null) { + oldEndVnode = oldCh[--oldEndIdx]; + } + else if (newStartVnode == null) { + newStartVnode = newCh[++newStartIdx]; + } + else if (newEndVnode == null) { + newEndVnode = newCh[--newEndIdx]; + } + else if (sameVnode(oldStartVnode, newStartVnode)) { + patchVnode(oldStartVnode, newStartVnode); + oldStartVnode = oldCh[++oldStartIdx]; + newStartVnode = newCh[++newStartIdx]; + } + else if (sameVnode(oldEndVnode, newEndVnode)) { + patchVnode(oldEndVnode, newEndVnode); + oldEndVnode = oldCh[--oldEndIdx]; + newEndVnode = newCh[--newEndIdx]; + } + else if (sameVnode(oldStartVnode, newEndVnode)) { + patchVnode(oldStartVnode, newEndVnode); + insertBefore(parentElm, oldStartVnode.elm, nextSibling(oldEndVnode.elm)); + oldStartVnode = oldCh[++oldStartIdx]; + newEndVnode = newCh[--newEndIdx]; + } + else if (sameVnode(oldEndVnode, newStartVnode)) { + patchVnode(oldEndVnode, newStartVnode); + insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm); + oldEndVnode = oldCh[--oldEndIdx]; + newStartVnode = newCh[++newStartIdx]; + } + else { + if (isUndef(oldKeyToIdx)) { + oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); + } + idxInOld = oldKeyToIdx[newStartVnode.key]; + if (isUndef(idxInOld)) { + insertBefore(parentElm, createElm(newStartVnode), oldStartVnode.elm); + } + else { + elmToMove = oldCh[idxInOld]; + if (elmToMove.tag !== newStartVnode.tag) { + insertBefore(parentElm, createElm(newStartVnode), oldStartVnode.elm); + } + else { + patchVnode(elmToMove, newStartVnode); + oldCh[idxInOld] = undefined; + insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm); + } + } + newStartVnode = newCh[++newStartIdx]; + } + } + if (oldStartIdx <= oldEndIdx || newStartIdx <= newEndIdx) { + if (oldStartIdx > oldEndIdx) { + before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm; + addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx); + } + else { + removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx); + } + } + } + function patchVnode(oldVnode, vnode) { + var elm = (vnode.elm = oldVnode.elm); + var oldCh = oldVnode.children; + var ch = vnode.children; + if (oldVnode === vnode) { + return; + } + updateAttrs(oldVnode, vnode); + if (isUndef(vnode.text)) { + if (isDef(oldCh) && isDef(ch)) { + if (oldCh !== ch) { + updateChildren(elm, oldCh, ch); + } + } + else if (isDef(ch)) { + if (isDef(oldVnode.text)) { + setTextContent(elm, ''); + } + addVnodes(elm, null, ch, 0, ch.length - 1); + } + else if (isDef(oldCh)) { + removeVnodes(elm, oldCh, 0, oldCh.length - 1); + } + else if (isDef(oldVnode.text)) { + setTextContent(elm, ''); + } + } + else if (oldVnode.text !== vnode.text) { + if (isDef(oldCh)) { + removeVnodes(elm, oldCh, 0, oldCh.length - 1); + } + setTextContent(elm, vnode.text); + } + } + function patch(oldVnode, vnode) { + if (sameVnode(oldVnode, vnode)) { + patchVnode(oldVnode, vnode); + } + else { + var elm = oldVnode.elm; + var parent_2 = parentNode(elm); + createElm(vnode); + if (parent_2 !== null) { + insertBefore(parent_2, vnode.elm, nextSibling(elm)); + removeVnodes(parent_2, [oldVnode], 0, 0); + } + } + return vnode; + } + + var svgId = 0; + var SVGPainter = (function () { + function SVGPainter(root, storage, opts) { + this.type = 'svg'; + this.refreshHover = createMethodNotSupport('refreshHover'); + this.configLayer = createMethodNotSupport('configLayer'); + this.storage = storage; + this._opts = opts = extend({}, opts); + this.root = root; + this._id = 'zr' + svgId++; + this._oldVNode = createSVGVNode(opts.width, opts.height); + if (root && !opts.ssr) { + var viewport = this._viewport = document.createElement('div'); + viewport.style.cssText = 'position:relative;overflow:hidden'; + var svgDom = this._svgDom = this._oldVNode.elm = createElement('svg'); + updateAttrs(null, this._oldVNode); + viewport.appendChild(svgDom); + root.appendChild(viewport); + } + this.resize(opts.width, opts.height); + } + SVGPainter.prototype.getType = function () { + return this.type; + }; + SVGPainter.prototype.getViewportRoot = function () { + return this._viewport; + }; + SVGPainter.prototype.getViewportRootOffset = function () { + var viewportRoot = this.getViewportRoot(); + if (viewportRoot) { + return { + offsetLeft: viewportRoot.offsetLeft || 0, + offsetTop: viewportRoot.offsetTop || 0 + }; + } + }; + SVGPainter.prototype.getSvgDom = function () { + return this._svgDom; + }; + SVGPainter.prototype.refresh = function () { + if (this.root) { + var vnode = this.renderToVNode({ + willUpdate: true + }); + vnode.attrs.style = 'position:absolute;left:0;top:0;user-select:none'; + patch(this._oldVNode, vnode); + this._oldVNode = vnode; + } + }; + SVGPainter.prototype.renderOneToVNode = function (el) { + return brush$1(el, createBrushScope(this._id)); + }; + SVGPainter.prototype.renderToVNode = function (opts) { + opts = opts || {}; + var list = this.storage.getDisplayList(true); + var bgColor = this._backgroundColor; + var width = this._width; + var height = this._height; + var scope = createBrushScope(this._id); + scope.animation = opts.animation; + scope.willUpdate = opts.willUpdate; + scope.compress = opts.compress; + var children = []; + if (bgColor && bgColor !== 'none') { + var _a = normalizeColor(bgColor), color = _a.color, opacity = _a.opacity; + this._bgVNode = createVNode('rect', 'bg', { + width: width, + height: height, + x: '0', + y: '0', + id: '0', + fill: color, + 'fill-opacity': opacity + }); + children.push(this._bgVNode); + } + else { + this._bgVNode = null; + } + var mainVNode = !opts.compress + ? (this._mainVNode = createVNode('g', 'main', {}, [])) : null; + this._paintList(list, scope, mainVNode ? mainVNode.children : children); + mainVNode && children.push(mainVNode); + var defs = map(keys(scope.defs), function (id) { return scope.defs[id]; }); + if (defs.length) { + children.push(createVNode('defs', 'defs', {}, defs)); + } + if (opts.animation) { + var animationCssStr = getCssString(scope.cssNodes, scope.cssAnims, { newline: true }); + if (animationCssStr) { + var styleNode = createVNode('style', 'stl', {}, [], animationCssStr); + children.push(styleNode); + } + } + return createSVGVNode(width, height, children, opts.useViewBox); + }; + SVGPainter.prototype.renderToString = function (opts) { + opts = opts || {}; + return vNodeToString(this.renderToVNode({ + animation: retrieve2(opts.cssAnimation, true), + willUpdate: false, + compress: true, + useViewBox: retrieve2(opts.useViewBox, true) + }), { newline: true }); + }; + SVGPainter.prototype.setBackgroundColor = function (backgroundColor) { + this._backgroundColor = backgroundColor; + var bgVNode = this._bgVNode; + if (bgVNode && bgVNode.elm) { + var _a = normalizeColor(backgroundColor), color = _a.color, opacity = _a.opacity; + bgVNode.elm.setAttribute('fill', color); + if (opacity < 1) { + bgVNode.elm.setAttribute('fill-opacity', opacity); + } + } + }; + SVGPainter.prototype.getSvgRoot = function () { + return this._mainVNode && this._mainVNode.elm; + }; + SVGPainter.prototype._paintList = function (list, scope, out) { + var listLen = list.length; + var clipPathsGroupsStack = []; + var clipPathsGroupsStackDepth = 0; + var currentClipPathGroup; + var prevClipPaths; + var clipGroupNodeIdx = 0; + for (var i = 0; i < listLen; i++) { + var displayable = list[i]; + if (!displayable.invisible) { + var clipPaths = displayable.__clipPaths; + var len = clipPaths && clipPaths.length || 0; + var prevLen = prevClipPaths && prevClipPaths.length || 0; + var lca = void 0; + for (lca = Math.max(len - 1, prevLen - 1); lca >= 0; lca--) { + if (clipPaths && prevClipPaths + && clipPaths[lca] === prevClipPaths[lca]) { + break; + } + } + for (var i_1 = prevLen - 1; i_1 > lca; i_1--) { + clipPathsGroupsStackDepth--; + currentClipPathGroup = clipPathsGroupsStack[clipPathsGroupsStackDepth - 1]; + } + for (var i_2 = lca + 1; i_2 < len; i_2++) { + var groupAttrs = {}; + setClipPath(clipPaths[i_2], groupAttrs, scope); + var g = createVNode('g', 'clip-g-' + clipGroupNodeIdx++, groupAttrs, []); + (currentClipPathGroup ? currentClipPathGroup.children : out).push(g); + clipPathsGroupsStack[clipPathsGroupsStackDepth++] = g; + currentClipPathGroup = g; + } + prevClipPaths = clipPaths; + var ret = brush$1(displayable, scope); + if (ret) { + (currentClipPathGroup ? currentClipPathGroup.children : out).push(ret); + } + } + } + }; + SVGPainter.prototype.resize = function (width, height) { + var opts = this._opts; + var root = this.root; + var viewport = this._viewport; + width != null && (opts.width = width); + height != null && (opts.height = height); + if (root && viewport) { + viewport.style.display = 'none'; + width = getSize(root, 0, opts); + height = getSize(root, 1, opts); + viewport.style.display = ''; + } + if (this._width !== width || this._height !== height) { + this._width = width; + this._height = height; + if (viewport) { + var viewportStyle = viewport.style; + viewportStyle.width = width + 'px'; + viewportStyle.height = height + 'px'; + } + var svgDom = this._svgDom; + if (svgDom) { + svgDom.setAttribute('width', width); + svgDom.setAttribute('height', height); + } + } + }; + SVGPainter.prototype.getWidth = function () { + return this._width; + }; + SVGPainter.prototype.getHeight = function () { + return this._height; + }; + SVGPainter.prototype.dispose = function () { + if (this.root) { + this.root.innerHTML = ''; + } + this._svgDom = + this._viewport = + this.storage = + this._oldVNode = + this._bgVNode = + this._mainVNode = null; + }; + SVGPainter.prototype.clear = function () { + if (this._svgDom) { + this._svgDom.innerHTML = null; + } + this._oldVNode = null; + }; + SVGPainter.prototype.toDataURL = function (base64) { + var str = encodeURIComponent(this.renderToString()); + var prefix = 'data:image/svg+xml;'; + if (base64) { + str = encodeBase64(str); + return str && prefix + 'base64,' + str; + } + return prefix + 'charset=UTF-8,' + str; + }; + return SVGPainter; + }()); + function createMethodNotSupport(method) { + return function () { + if ("development" !== 'production') { + logError('In SVG mode painter not support method "' + method + '"'); + } + }; + } + + function install(registers) { + registers.registerPainter('svg', SVGPainter); + } + + function createDom(id, painter, dpr) { + var newDom = platformApi.createCanvas(); + var width = painter.getWidth(); + var height = painter.getHeight(); + var newDomStyle = newDom.style; + if (newDomStyle) { + newDomStyle.position = 'absolute'; + newDomStyle.left = '0'; + newDomStyle.top = '0'; + newDomStyle.width = width + 'px'; + newDomStyle.height = height + 'px'; + newDom.setAttribute('data-zr-dom-id', id); + } + newDom.width = width * dpr; + newDom.height = height * dpr; + return newDom; + } + var Layer = (function (_super) { + __extends(Layer, _super); + function Layer(id, painter, dpr) { + var _this = _super.call(this) || this; + _this.motionBlur = false; + _this.lastFrameAlpha = 0.7; + _this.dpr = 1; + _this.virtual = false; + _this.config = {}; + _this.incremental = false; + _this.zlevel = 0; + _this.maxRepaintRectCount = 5; + _this.__dirty = true; + _this.__firstTimePaint = true; + _this.__used = false; + _this.__drawIndex = 0; + _this.__startIndex = 0; + _this.__endIndex = 0; + _this.__prevStartIndex = null; + _this.__prevEndIndex = null; + var dom; + dpr = dpr || devicePixelRatio; + if (typeof id === 'string') { + dom = createDom(id, painter, dpr); + } + else if (isObject(id)) { + dom = id; + id = dom.id; + } + _this.id = id; + _this.dom = dom; + var domStyle = dom.style; + if (domStyle) { + disableUserSelect(dom); + dom.onselectstart = function () { return false; }; + domStyle.padding = '0'; + domStyle.margin = '0'; + domStyle.borderWidth = '0'; + } + _this.painter = painter; + _this.dpr = dpr; + return _this; + } + Layer.prototype.getElementCount = function () { + return this.__endIndex - this.__startIndex; + }; + Layer.prototype.afterBrush = function () { + this.__prevStartIndex = this.__startIndex; + this.__prevEndIndex = this.__endIndex; + }; + Layer.prototype.initContext = function () { + this.ctx = this.dom.getContext('2d'); + this.ctx.dpr = this.dpr; + }; + Layer.prototype.setUnpainted = function () { + this.__firstTimePaint = true; + }; + Layer.prototype.createBackBuffer = function () { + var dpr = this.dpr; + this.domBack = createDom('back-' + this.id, this.painter, dpr); + this.ctxBack = this.domBack.getContext('2d'); + if (dpr !== 1) { + this.ctxBack.scale(dpr, dpr); + } + }; + Layer.prototype.createRepaintRects = function (displayList, prevList, viewWidth, viewHeight) { + if (this.__firstTimePaint) { + this.__firstTimePaint = false; + return null; + } + var mergedRepaintRects = []; + var maxRepaintRectCount = this.maxRepaintRectCount; + var full = false; + var pendingRect = new BoundingRect(0, 0, 0, 0); + function addRectToMergePool(rect) { + if (!rect.isFinite() || rect.isZero()) { + return; + } + if (mergedRepaintRects.length === 0) { + var boundingRect = new BoundingRect(0, 0, 0, 0); + boundingRect.copy(rect); + mergedRepaintRects.push(boundingRect); + } + else { + var isMerged = false; + var minDeltaArea = Infinity; + var bestRectToMergeIdx = 0; + for (var i = 0; i < mergedRepaintRects.length; ++i) { + var mergedRect = mergedRepaintRects[i]; + if (mergedRect.intersect(rect)) { + var pendingRect_1 = new BoundingRect(0, 0, 0, 0); + pendingRect_1.copy(mergedRect); + pendingRect_1.union(rect); + mergedRepaintRects[i] = pendingRect_1; + isMerged = true; + break; + } + else if (full) { + pendingRect.copy(rect); + pendingRect.union(mergedRect); + var aArea = rect.width * rect.height; + var bArea = mergedRect.width * mergedRect.height; + var pendingArea = pendingRect.width * pendingRect.height; + var deltaArea = pendingArea - aArea - bArea; + if (deltaArea < minDeltaArea) { + minDeltaArea = deltaArea; + bestRectToMergeIdx = i; + } + } + } + if (full) { + mergedRepaintRects[bestRectToMergeIdx].union(rect); + isMerged = true; + } + if (!isMerged) { + var boundingRect = new BoundingRect(0, 0, 0, 0); + boundingRect.copy(rect); + mergedRepaintRects.push(boundingRect); + } + if (!full) { + full = mergedRepaintRects.length >= maxRepaintRectCount; + } + } + } + for (var i = this.__startIndex; i < this.__endIndex; ++i) { + var el = displayList[i]; + if (el) { + var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true); + var prevRect = el.__isRendered && ((el.__dirty & REDRAW_BIT) || !shouldPaint) + ? el.getPrevPaintRect() + : null; + if (prevRect) { + addRectToMergePool(prevRect); + } + var curRect = shouldPaint && ((el.__dirty & REDRAW_BIT) || !el.__isRendered) + ? el.getPaintRect() + : null; + if (curRect) { + addRectToMergePool(curRect); + } + } + } + for (var i = this.__prevStartIndex; i < this.__prevEndIndex; ++i) { + var el = prevList[i]; + var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true); + if (el && (!shouldPaint || !el.__zr) && el.__isRendered) { + var prevRect = el.getPrevPaintRect(); + if (prevRect) { + addRectToMergePool(prevRect); + } + } + } + var hasIntersections; + do { + hasIntersections = false; + for (var i = 0; i < mergedRepaintRects.length;) { + if (mergedRepaintRects[i].isZero()) { + mergedRepaintRects.splice(i, 1); + continue; + } + for (var j = i + 1; j < mergedRepaintRects.length;) { + if (mergedRepaintRects[i].intersect(mergedRepaintRects[j])) { + hasIntersections = true; + mergedRepaintRects[i].union(mergedRepaintRects[j]); + mergedRepaintRects.splice(j, 1); + } + else { + j++; + } + } + i++; + } + } while (hasIntersections); + this._paintRects = mergedRepaintRects; + return mergedRepaintRects; + }; + Layer.prototype.debugGetPaintRects = function () { + return (this._paintRects || []).slice(); + }; + Layer.prototype.resize = function (width, height) { + var dpr = this.dpr; + var dom = this.dom; + var domStyle = dom.style; + var domBack = this.domBack; + if (domStyle) { + domStyle.width = width + 'px'; + domStyle.height = height + 'px'; + } + dom.width = width * dpr; + dom.height = height * dpr; + if (domBack) { + domBack.width = width * dpr; + domBack.height = height * dpr; + if (dpr !== 1) { + this.ctxBack.scale(dpr, dpr); + } + } + }; + Layer.prototype.clear = function (clearAll, clearColor, repaintRects) { + var dom = this.dom; + var ctx = this.ctx; + var width = dom.width; + var height = dom.height; + clearColor = clearColor || this.clearColor; + var haveMotionBLur = this.motionBlur && !clearAll; + var lastFrameAlpha = this.lastFrameAlpha; + var dpr = this.dpr; + var self = this; + if (haveMotionBLur) { + if (!this.domBack) { + this.createBackBuffer(); + } + this.ctxBack.globalCompositeOperation = 'copy'; + this.ctxBack.drawImage(dom, 0, 0, width / dpr, height / dpr); + } + var domBack = this.domBack; + function doClear(x, y, width, height) { + ctx.clearRect(x, y, width, height); + if (clearColor && clearColor !== 'transparent') { + var clearColorGradientOrPattern = void 0; + if (isGradientObject(clearColor)) { + clearColorGradientOrPattern = clearColor.__canvasGradient + || getCanvasGradient(ctx, clearColor, { + x: 0, + y: 0, + width: width, + height: height + }); + clearColor.__canvasGradient = clearColorGradientOrPattern; + } + else if (isImagePatternObject(clearColor)) { + clearColorGradientOrPattern = createCanvasPattern(ctx, clearColor, { + dirty: function () { + self.setUnpainted(); + self.__painter.refresh(); + } + }); + } + ctx.save(); + ctx.fillStyle = clearColorGradientOrPattern || clearColor; + ctx.fillRect(x, y, width, height); + ctx.restore(); + } + if (haveMotionBLur) { + ctx.save(); + ctx.globalAlpha = lastFrameAlpha; + ctx.drawImage(domBack, x, y, width, height); + ctx.restore(); + } + } + if (!repaintRects || haveMotionBLur) { + doClear(0, 0, width, height); + } + else if (repaintRects.length) { + each(repaintRects, function (rect) { + doClear(rect.x * dpr, rect.y * dpr, rect.width * dpr, rect.height * dpr); + }); + } + }; + return Layer; + }(Eventful)); + + var HOVER_LAYER_ZLEVEL = 1e5; + var CANVAS_ZLEVEL = 314159; + var EL_AFTER_INCREMENTAL_INC = 0.01; + var INCREMENTAL_INC = 0.001; + function isLayerValid(layer) { + if (!layer) { + return false; + } + if (layer.__builtin__) { + return true; + } + if (typeof (layer.resize) !== 'function' + || typeof (layer.refresh) !== 'function') { + return false; + } + return true; + } + function createRoot(width, height) { + var domRoot = document.createElement('div'); + domRoot.style.cssText = [ + 'position:relative', + 'width:' + width + 'px', + 'height:' + height + 'px', + 'padding:0', + 'margin:0', + 'border-width:0' + ].join(';') + ';'; + return domRoot; + } + var CanvasPainter = (function () { + function CanvasPainter(root, storage, opts, id) { + this.type = 'canvas'; + this._zlevelList = []; + this._prevDisplayList = []; + this._layers = {}; + this._layerConfig = {}; + this._needsManuallyCompositing = false; + this.type = 'canvas'; + var singleCanvas = !root.nodeName + || root.nodeName.toUpperCase() === 'CANVAS'; + this._opts = opts = extend({}, opts || {}); + this.dpr = opts.devicePixelRatio || devicePixelRatio; + this._singleCanvas = singleCanvas; + this.root = root; + var rootStyle = root.style; + if (rootStyle) { + disableUserSelect(root); + root.innerHTML = ''; + } + this.storage = storage; + var zlevelList = this._zlevelList; + this._prevDisplayList = []; + var layers = this._layers; + if (!singleCanvas) { + this._width = getSize(root, 0, opts); + this._height = getSize(root, 1, opts); + var domRoot = this._domRoot = createRoot(this._width, this._height); + root.appendChild(domRoot); + } + else { + var rootCanvas = root; + var width = rootCanvas.width; + var height = rootCanvas.height; + if (opts.width != null) { + width = opts.width; + } + if (opts.height != null) { + height = opts.height; + } + this.dpr = opts.devicePixelRatio || 1; + rootCanvas.width = width * this.dpr; + rootCanvas.height = height * this.dpr; + this._width = width; + this._height = height; + var mainLayer = new Layer(rootCanvas, this, this.dpr); + mainLayer.__builtin__ = true; + mainLayer.initContext(); + layers[CANVAS_ZLEVEL] = mainLayer; + mainLayer.zlevel = CANVAS_ZLEVEL; + zlevelList.push(CANVAS_ZLEVEL); + this._domRoot = root; + } + } + CanvasPainter.prototype.getType = function () { + return 'canvas'; + }; + CanvasPainter.prototype.isSingleCanvas = function () { + return this._singleCanvas; + }; + CanvasPainter.prototype.getViewportRoot = function () { + return this._domRoot; + }; + CanvasPainter.prototype.getViewportRootOffset = function () { + var viewportRoot = this.getViewportRoot(); + if (viewportRoot) { + return { + offsetLeft: viewportRoot.offsetLeft || 0, + offsetTop: viewportRoot.offsetTop || 0 + }; + } + }; + CanvasPainter.prototype.refresh = function (paintAll) { + var list = this.storage.getDisplayList(true); + var prevList = this._prevDisplayList; + var zlevelList = this._zlevelList; + this._redrawId = Math.random(); + this._paintList(list, prevList, paintAll, this._redrawId); + for (var i = 0; i < zlevelList.length; i++) { + var z = zlevelList[i]; + var layer = this._layers[z]; + if (!layer.__builtin__ && layer.refresh) { + var clearColor = i === 0 ? this._backgroundColor : null; + layer.refresh(clearColor); + } + } + if (this._opts.useDirtyRect) { + this._prevDisplayList = list.slice(); + } + return this; + }; + CanvasPainter.prototype.refreshHover = function () { + this._paintHoverList(this.storage.getDisplayList(false)); + }; + CanvasPainter.prototype._paintHoverList = function (list) { + var len = list.length; + var hoverLayer = this._hoverlayer; + hoverLayer && hoverLayer.clear(); + if (!len) { + return; + } + var scope = { + inHover: true, + viewWidth: this._width, + viewHeight: this._height + }; + var ctx; + for (var i = 0; i < len; i++) { + var el = list[i]; + if (el.__inHover) { + if (!hoverLayer) { + hoverLayer = this._hoverlayer = this.getLayer(HOVER_LAYER_ZLEVEL); + } + if (!ctx) { + ctx = hoverLayer.ctx; + ctx.save(); + } + brush(ctx, el, scope, i === len - 1); + } + } + if (ctx) { + ctx.restore(); + } + }; + CanvasPainter.prototype.getHoverLayer = function () { + return this.getLayer(HOVER_LAYER_ZLEVEL); + }; + CanvasPainter.prototype.paintOne = function (ctx, el) { + brushSingle(ctx, el); + }; + CanvasPainter.prototype._paintList = function (list, prevList, paintAll, redrawId) { + if (this._redrawId !== redrawId) { + return; + } + paintAll = paintAll || false; + this._updateLayerStatus(list); + var _a = this._doPaintList(list, prevList, paintAll), finished = _a.finished, needsRefreshHover = _a.needsRefreshHover; + if (this._needsManuallyCompositing) { + this._compositeManually(); + } + if (needsRefreshHover) { + this._paintHoverList(list); + } + if (!finished) { + var self_1 = this; + requestAnimationFrame$1(function () { + self_1._paintList(list, prevList, paintAll, redrawId); + }); + } + else { + this.eachLayer(function (layer) { + layer.afterBrush && layer.afterBrush(); + }); + } + }; + CanvasPainter.prototype._compositeManually = function () { + var ctx = this.getLayer(CANVAS_ZLEVEL).ctx; + var width = this._domRoot.width; + var height = this._domRoot.height; + ctx.clearRect(0, 0, width, height); + this.eachBuiltinLayer(function (layer) { + if (layer.virtual) { + ctx.drawImage(layer.dom, 0, 0, width, height); + } + }); + }; + CanvasPainter.prototype._doPaintList = function (list, prevList, paintAll) { + var _this = this; + var layerList = []; + var useDirtyRect = this._opts.useDirtyRect; + for (var zi = 0; zi < this._zlevelList.length; zi++) { + var zlevel = this._zlevelList[zi]; + var layer = this._layers[zlevel]; + if (layer.__builtin__ + && layer !== this._hoverlayer + && (layer.__dirty || paintAll)) { + layerList.push(layer); + } + } + var finished = true; + var needsRefreshHover = false; + var _loop_1 = function (k) { + var layer = layerList[k]; + var ctx = layer.ctx; + var repaintRects = useDirtyRect + && layer.createRepaintRects(list, prevList, this_1._width, this_1._height); + var start = paintAll ? layer.__startIndex : layer.__drawIndex; + var useTimer = !paintAll && layer.incremental && Date.now; + var startTime = useTimer && Date.now(); + var clearColor = layer.zlevel === this_1._zlevelList[0] + ? this_1._backgroundColor : null; + if (layer.__startIndex === layer.__endIndex) { + layer.clear(false, clearColor, repaintRects); + } + else if (start === layer.__startIndex) { + var firstEl = list[start]; + if (!firstEl.incremental || !firstEl.notClear || paintAll) { + layer.clear(false, clearColor, repaintRects); + } + } + if (start === -1) { + console.error('For some unknown reason. drawIndex is -1'); + start = layer.__startIndex; + } + var i; + var repaint = function (repaintRect) { + var scope = { + inHover: false, + allClipped: false, + prevEl: null, + viewWidth: _this._width, + viewHeight: _this._height + }; + for (i = start; i < layer.__endIndex; i++) { + var el = list[i]; + if (el.__inHover) { + needsRefreshHover = true; + } + _this._doPaintEl(el, layer, useDirtyRect, repaintRect, scope, i === layer.__endIndex - 1); + if (useTimer) { + var dTime = Date.now() - startTime; + if (dTime > 15) { + break; + } + } + } + if (scope.prevElClipPaths) { + ctx.restore(); + } + }; + if (repaintRects) { + if (repaintRects.length === 0) { + i = layer.__endIndex; + } + else { + var dpr = this_1.dpr; + for (var r = 0; r < repaintRects.length; ++r) { + var rect = repaintRects[r]; + ctx.save(); + ctx.beginPath(); + ctx.rect(rect.x * dpr, rect.y * dpr, rect.width * dpr, rect.height * dpr); + ctx.clip(); + repaint(rect); + ctx.restore(); + } + } + } + else { + ctx.save(); + repaint(); + ctx.restore(); + } + layer.__drawIndex = i; + if (layer.__drawIndex < layer.__endIndex) { + finished = false; + } + }; + var this_1 = this; + for (var k = 0; k < layerList.length; k++) { + _loop_1(k); + } + if (env.wxa) { + each(this._layers, function (layer) { + if (layer && layer.ctx && layer.ctx.draw) { + layer.ctx.draw(); + } + }); + } + return { + finished: finished, + needsRefreshHover: needsRefreshHover + }; + }; + CanvasPainter.prototype._doPaintEl = function (el, currentLayer, useDirtyRect, repaintRect, scope, isLast) { + var ctx = currentLayer.ctx; + if (useDirtyRect) { + var paintRect = el.getPaintRect(); + if (!repaintRect || paintRect && paintRect.intersect(repaintRect)) { + brush(ctx, el, scope, isLast); + el.setPrevPaintRect(paintRect); + } + } + else { + brush(ctx, el, scope, isLast); + } + }; + CanvasPainter.prototype.getLayer = function (zlevel, virtual) { + if (this._singleCanvas && !this._needsManuallyCompositing) { + zlevel = CANVAS_ZLEVEL; + } + var layer = this._layers[zlevel]; + if (!layer) { + layer = new Layer('zr_' + zlevel, this, this.dpr); + layer.zlevel = zlevel; + layer.__builtin__ = true; + if (this._layerConfig[zlevel]) { + merge(layer, this._layerConfig[zlevel], true); + } + else if (this._layerConfig[zlevel - EL_AFTER_INCREMENTAL_INC]) { + merge(layer, this._layerConfig[zlevel - EL_AFTER_INCREMENTAL_INC], true); + } + if (virtual) { + layer.virtual = virtual; + } + this.insertLayer(zlevel, layer); + layer.initContext(); + } + return layer; + }; + CanvasPainter.prototype.insertLayer = function (zlevel, layer) { + var layersMap = this._layers; + var zlevelList = this._zlevelList; + var len = zlevelList.length; + var domRoot = this._domRoot; + var prevLayer = null; + var i = -1; + if (layersMap[zlevel]) { + if ("development" !== 'production') { + logError('ZLevel ' + zlevel + ' has been used already'); + } + return; + } + if (!isLayerValid(layer)) { + if ("development" !== 'production') { + logError('Layer of zlevel ' + zlevel + ' is not valid'); + } + return; + } + if (len > 0 && zlevel > zlevelList[0]) { + for (i = 0; i < len - 1; i++) { + if (zlevelList[i] < zlevel + && zlevelList[i + 1] > zlevel) { + break; + } + } + prevLayer = layersMap[zlevelList[i]]; + } + zlevelList.splice(i + 1, 0, zlevel); + layersMap[zlevel] = layer; + if (!layer.virtual) { + if (prevLayer) { + var prevDom = prevLayer.dom; + if (prevDom.nextSibling) { + domRoot.insertBefore(layer.dom, prevDom.nextSibling); + } + else { + domRoot.appendChild(layer.dom); + } + } + else { + if (domRoot.firstChild) { + domRoot.insertBefore(layer.dom, domRoot.firstChild); + } + else { + domRoot.appendChild(layer.dom); + } + } + } + layer.__painter = this; + }; + CanvasPainter.prototype.eachLayer = function (cb, context) { + var zlevelList = this._zlevelList; + for (var i = 0; i < zlevelList.length; i++) { + var z = zlevelList[i]; + cb.call(context, this._layers[z], z); + } + }; + CanvasPainter.prototype.eachBuiltinLayer = function (cb, context) { + var zlevelList = this._zlevelList; + for (var i = 0; i < zlevelList.length; i++) { + var z = zlevelList[i]; + var layer = this._layers[z]; + if (layer.__builtin__) { + cb.call(context, layer, z); + } + } + }; + CanvasPainter.prototype.eachOtherLayer = function (cb, context) { + var zlevelList = this._zlevelList; + for (var i = 0; i < zlevelList.length; i++) { + var z = zlevelList[i]; + var layer = this._layers[z]; + if (!layer.__builtin__) { + cb.call(context, layer, z); + } + } + }; + CanvasPainter.prototype.getLayers = function () { + return this._layers; + }; + CanvasPainter.prototype._updateLayerStatus = function (list) { + this.eachBuiltinLayer(function (layer, z) { + layer.__dirty = layer.__used = false; + }); + function updatePrevLayer(idx) { + if (prevLayer) { + if (prevLayer.__endIndex !== idx) { + prevLayer.__dirty = true; + } + prevLayer.__endIndex = idx; + } + } + if (this._singleCanvas) { + for (var i_1 = 1; i_1 < list.length; i_1++) { + var el = list[i_1]; + if (el.zlevel !== list[i_1 - 1].zlevel || el.incremental) { + this._needsManuallyCompositing = true; + break; + } + } + } + var prevLayer = null; + var incrementalLayerCount = 0; + var prevZlevel; + var i; + for (i = 0; i < list.length; i++) { + var el = list[i]; + var zlevel = el.zlevel; + var layer = void 0; + if (prevZlevel !== zlevel) { + prevZlevel = zlevel; + incrementalLayerCount = 0; + } + if (el.incremental) { + layer = this.getLayer(zlevel + INCREMENTAL_INC, this._needsManuallyCompositing); + layer.incremental = true; + incrementalLayerCount = 1; + } + else { + layer = this.getLayer(zlevel + (incrementalLayerCount > 0 ? EL_AFTER_INCREMENTAL_INC : 0), this._needsManuallyCompositing); + } + if (!layer.__builtin__) { + logError('ZLevel ' + zlevel + ' has been used by unkown layer ' + layer.id); + } + if (layer !== prevLayer) { + layer.__used = true; + if (layer.__startIndex !== i) { + layer.__dirty = true; + } + layer.__startIndex = i; + if (!layer.incremental) { + layer.__drawIndex = i; + } + else { + layer.__drawIndex = -1; + } + updatePrevLayer(i); + prevLayer = layer; + } + if ((el.__dirty & REDRAW_BIT) && !el.__inHover) { + layer.__dirty = true; + if (layer.incremental && layer.__drawIndex < 0) { + layer.__drawIndex = i; + } + } + } + updatePrevLayer(i); + this.eachBuiltinLayer(function (layer, z) { + if (!layer.__used && layer.getElementCount() > 0) { + layer.__dirty = true; + layer.__startIndex = layer.__endIndex = layer.__drawIndex = 0; + } + if (layer.__dirty && layer.__drawIndex < 0) { + layer.__drawIndex = layer.__startIndex; + } + }); + }; + CanvasPainter.prototype.clear = function () { + this.eachBuiltinLayer(this._clearLayer); + return this; + }; + CanvasPainter.prototype._clearLayer = function (layer) { + layer.clear(); + }; + CanvasPainter.prototype.setBackgroundColor = function (backgroundColor) { + this._backgroundColor = backgroundColor; + each(this._layers, function (layer) { + layer.setUnpainted(); + }); + }; + CanvasPainter.prototype.configLayer = function (zlevel, config) { + if (config) { + var layerConfig = this._layerConfig; + if (!layerConfig[zlevel]) { + layerConfig[zlevel] = config; + } + else { + merge(layerConfig[zlevel], config, true); + } + for (var i = 0; i < this._zlevelList.length; i++) { + var _zlevel = this._zlevelList[i]; + if (_zlevel === zlevel || _zlevel === zlevel + EL_AFTER_INCREMENTAL_INC) { + var layer = this._layers[_zlevel]; + merge(layer, layerConfig[zlevel], true); + } + } + } + }; + CanvasPainter.prototype.delLayer = function (zlevel) { + var layers = this._layers; + var zlevelList = this._zlevelList; + var layer = layers[zlevel]; + if (!layer) { + return; + } + layer.dom.parentNode.removeChild(layer.dom); + delete layers[zlevel]; + zlevelList.splice(indexOf(zlevelList, zlevel), 1); + }; + CanvasPainter.prototype.resize = function (width, height) { + if (!this._domRoot.style) { + if (width == null || height == null) { + return; + } + this._width = width; + this._height = height; + this.getLayer(CANVAS_ZLEVEL).resize(width, height); + } + else { + var domRoot = this._domRoot; + domRoot.style.display = 'none'; + var opts = this._opts; + var root = this.root; + width != null && (opts.width = width); + height != null && (opts.height = height); + width = getSize(root, 0, opts); + height = getSize(root, 1, opts); + domRoot.style.display = ''; + if (this._width !== width || height !== this._height) { + domRoot.style.width = width + 'px'; + domRoot.style.height = height + 'px'; + for (var id in this._layers) { + if (this._layers.hasOwnProperty(id)) { + this._layers[id].resize(width, height); + } + } + this.refresh(true); + } + this._width = width; + this._height = height; + } + return this; + }; + CanvasPainter.prototype.clearLayer = function (zlevel) { + var layer = this._layers[zlevel]; + if (layer) { + layer.clear(); + } + }; + CanvasPainter.prototype.dispose = function () { + this.root.innerHTML = ''; + this.root = + this.storage = + this._domRoot = + this._layers = null; + }; + CanvasPainter.prototype.getRenderedCanvas = function (opts) { + opts = opts || {}; + if (this._singleCanvas && !this._compositeManually) { + return this._layers[CANVAS_ZLEVEL].dom; + } + var imageLayer = new Layer('image', this, opts.pixelRatio || this.dpr); + imageLayer.initContext(); + imageLayer.clear(false, opts.backgroundColor || this._backgroundColor); + var ctx = imageLayer.ctx; + if (opts.pixelRatio <= this.dpr) { + this.refresh(); + var width_1 = imageLayer.dom.width; + var height_1 = imageLayer.dom.height; + this.eachLayer(function (layer) { + if (layer.__builtin__) { + ctx.drawImage(layer.dom, 0, 0, width_1, height_1); + } + else if (layer.renderToCanvas) { + ctx.save(); + layer.renderToCanvas(ctx); + ctx.restore(); + } + }); + } + else { + var scope = { + inHover: false, + viewWidth: this._width, + viewHeight: this._height + }; + var displayList = this.storage.getDisplayList(true); + for (var i = 0, len = displayList.length; i < len; i++) { + var el = displayList[i]; + brush(ctx, el, scope, i === len - 1); + } + } + return imageLayer.dom; + }; + CanvasPainter.prototype.getWidth = function () { + return this._width; + }; + CanvasPainter.prototype.getHeight = function () { + return this._height; + }; + return CanvasPainter; + }()); + + function install$1(registers) { + registers.registerPainter('canvas', CanvasPainter); + } + + var LineSeriesModel = + /** @class */ + function (_super) { + __extends(LineSeriesModel, _super); + + function LineSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = LineSeriesModel.type; + _this.hasSymbolVisual = true; + return _this; + } + + LineSeriesModel.prototype.getInitialData = function (option) { + if ("development" !== 'production') { + var coordSys = option.coordinateSystem; + + if (coordSys !== 'polar' && coordSys !== 'cartesian2d') { + throw new Error('Line not support coordinateSystem besides cartesian and polar'); + } + } + + return createSeriesData(null, this, { + useEncodeDefaulter: true + }); + }; + + LineSeriesModel.prototype.getLegendIcon = function (opt) { + var group = new Group(); + var line = createSymbol('line', 0, opt.itemHeight / 2, opt.itemWidth, 0, opt.lineStyle.stroke, false); + group.add(line); + line.setStyle(opt.lineStyle); + var visualType = this.getData().getVisual('symbol'); + var visualRotate = this.getData().getVisual('symbolRotate'); + var symbolType = visualType === 'none' ? 'circle' : visualType; // Symbol size is 80% when there is a line + + var size = opt.itemHeight * 0.8; + var symbol = createSymbol(symbolType, (opt.itemWidth - size) / 2, (opt.itemHeight - size) / 2, size, size, opt.itemStyle.fill); + group.add(symbol); + symbol.setStyle(opt.itemStyle); + var symbolRotate = opt.iconRotate === 'inherit' ? visualRotate : opt.iconRotate || 0; + symbol.rotation = symbolRotate * Math.PI / 180; + symbol.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]); + + if (symbolType.indexOf('empty') > -1) { + symbol.style.stroke = symbol.style.fill; + symbol.style.fill = '#fff'; + symbol.style.lineWidth = 2; + } + + return group; + }; + + LineSeriesModel.type = 'series.line'; + LineSeriesModel.dependencies = ['grid', 'polar']; + LineSeriesModel.defaultOption = { + // zlevel: 0, + z: 3, + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + clip: true, + label: { + position: 'top' + }, + // itemStyle: { + // }, + endLabel: { + show: false, + valueAnimation: true, + distance: 8 + }, + lineStyle: { + width: 2, + type: 'solid' + }, + emphasis: { + scale: true + }, + // areaStyle: { + // origin of areaStyle. Valid values: + // `'auto'/null/undefined`: from axisLine to data + // `'start'`: from min to data + // `'end'`: from data to max + // origin: 'auto' + // }, + // false, 'start', 'end', 'middle' + step: false, + // Disabled if step is true + smooth: false, + smoothMonotone: null, + symbol: 'emptyCircle', + symbolSize: 4, + symbolRotate: null, + showSymbol: true, + // `false`: follow the label interval strategy. + // `true`: show all symbols. + // `'auto'`: If possible, show all symbols, otherwise + // follow the label interval strategy. + showAllSymbol: 'auto', + // Whether to connect break point. + connectNulls: false, + // Sampling for large data. Can be: 'average', 'max', 'min', 'sum', 'lttb'. + sampling: 'none', + animationEasing: 'linear', + // Disable progressive + progressive: 0, + hoverLayerThreshold: Infinity, + universalTransition: { + divideShape: 'clone' + }, + triggerLineEvent: false + }; + return LineSeriesModel; + }(SeriesModel); + + /** + * @return label string. Not null/undefined + */ + + function getDefaultLabel(data, dataIndex) { + var labelDims = data.mapDimensionsAll('defaultedLabel'); + var len = labelDims.length; // Simple optimization (in lots of cases, label dims length is 1) + + if (len === 1) { + var rawVal = retrieveRawValue(data, dataIndex, labelDims[0]); + return rawVal != null ? rawVal + '' : null; + } else if (len) { + var vals = []; + + for (var i = 0; i < labelDims.length; i++) { + vals.push(retrieveRawValue(data, dataIndex, labelDims[i])); + } + + return vals.join(' '); + } + } + function getDefaultInterpolatedLabel(data, interpolatedValue) { + var labelDims = data.mapDimensionsAll('defaultedLabel'); + + if (!isArray(interpolatedValue)) { + return interpolatedValue + ''; + } + + var vals = []; + + for (var i = 0; i < labelDims.length; i++) { + var dimIndex = data.getDimensionIndex(labelDims[i]); + + if (dimIndex >= 0) { + vals.push(interpolatedValue[dimIndex]); + } + } + + return vals.join(' '); + } + + var Symbol = + /** @class */ + function (_super) { + __extends(Symbol, _super); + + function Symbol(data, idx, seriesScope, opts) { + var _this = _super.call(this) || this; + + _this.updateData(data, idx, seriesScope, opts); + + return _this; + } + + Symbol.prototype._createSymbol = function (symbolType, data, idx, symbolSize, keepAspect) { + // Remove paths created before + this.removeAll(); // let symbolPath = createSymbol( + // symbolType, -0.5, -0.5, 1, 1, color + // ); + // If width/height are set too small (e.g., set to 1) on ios10 + // and macOS Sierra, a circle stroke become a rect, no matter what + // the scale is set. So we set width/height as 2. See #4150. + + var symbolPath = createSymbol(symbolType, -1, -1, 2, 2, null, keepAspect); + symbolPath.attr({ + z2: 100, + culling: true, + scaleX: symbolSize[0] / 2, + scaleY: symbolSize[1] / 2 + }); // Rewrite drift method + + symbolPath.drift = driftSymbol; + this._symbolType = symbolType; + this.add(symbolPath); + }; + /** + * Stop animation + * @param {boolean} toLastFrame + */ + + + Symbol.prototype.stopSymbolAnimation = function (toLastFrame) { + this.childAt(0).stopAnimation(null, toLastFrame); + }; + + Symbol.prototype.getSymbolType = function () { + return this._symbolType; + }; + /** + * FIXME: + * Caution: This method breaks the encapsulation of this module, + * but it indeed brings convenience. So do not use the method + * unless you detailedly know all the implements of `Symbol`, + * especially animation. + * + * Get symbol path element. + */ + + + Symbol.prototype.getSymbolPath = function () { + return this.childAt(0); + }; + /** + * Highlight symbol + */ + + + Symbol.prototype.highlight = function () { + enterEmphasis(this.childAt(0)); + }; + /** + * Downplay symbol + */ + + + Symbol.prototype.downplay = function () { + leaveEmphasis(this.childAt(0)); + }; + /** + * @param {number} zlevel + * @param {number} z + */ + + + Symbol.prototype.setZ = function (zlevel, z) { + var symbolPath = this.childAt(0); + symbolPath.zlevel = zlevel; + symbolPath.z = z; + }; + + Symbol.prototype.setDraggable = function (draggable) { + var symbolPath = this.childAt(0); + symbolPath.draggable = draggable; + symbolPath.cursor = draggable ? 'move' : symbolPath.cursor; + }; + /** + * Update symbol properties + */ + + + Symbol.prototype.updateData = function (data, idx, seriesScope, opts) { + this.silent = false; + var symbolType = data.getItemVisual(idx, 'symbol') || 'circle'; + var seriesModel = data.hostModel; + var symbolSize = Symbol.getSymbolSize(data, idx); + var isInit = symbolType !== this._symbolType; + var disableAnimation = opts && opts.disableAnimation; + + if (isInit) { + var keepAspect = data.getItemVisual(idx, 'symbolKeepAspect'); + + this._createSymbol(symbolType, data, idx, symbolSize, keepAspect); + } else { + var symbolPath = this.childAt(0); + symbolPath.silent = false; + var target = { + scaleX: symbolSize[0] / 2, + scaleY: symbolSize[1] / 2 + }; + disableAnimation ? symbolPath.attr(target) : updateProps(symbolPath, target, seriesModel, idx); + saveOldStyle(symbolPath); + } + + this._updateCommon(data, idx, symbolSize, seriesScope, opts); + + if (isInit) { + var symbolPath = this.childAt(0); + + if (!disableAnimation) { + var target = { + scaleX: this._sizeX, + scaleY: this._sizeY, + style: { + // Always fadeIn. Because it has fadeOut animation when symbol is removed.. + opacity: symbolPath.style.opacity + } + }; + symbolPath.scaleX = symbolPath.scaleY = 0; + symbolPath.style.opacity = 0; + initProps(symbolPath, target, seriesModel, idx); + } + } + + if (disableAnimation) { + // Must stop leave transition manually if don't call initProps or updateProps. + this.childAt(0).stopAnimation('leave'); + } + }; + + Symbol.prototype._updateCommon = function (data, idx, symbolSize, seriesScope, opts) { + var symbolPath = this.childAt(0); + var seriesModel = data.hostModel; + var emphasisItemStyle; + var blurItemStyle; + var selectItemStyle; + var focus; + var blurScope; + var emphasisDisabled; + var labelStatesModels; + var hoverScale; + var cursorStyle; + + if (seriesScope) { + emphasisItemStyle = seriesScope.emphasisItemStyle; + blurItemStyle = seriesScope.blurItemStyle; + selectItemStyle = seriesScope.selectItemStyle; + focus = seriesScope.focus; + blurScope = seriesScope.blurScope; + labelStatesModels = seriesScope.labelStatesModels; + hoverScale = seriesScope.hoverScale; + cursorStyle = seriesScope.cursorStyle; + emphasisDisabled = seriesScope.emphasisDisabled; + } + + if (!seriesScope || data.hasItemOption) { + var itemModel = seriesScope && seriesScope.itemModel ? seriesScope.itemModel : data.getItemModel(idx); + var emphasisModel = itemModel.getModel('emphasis'); + emphasisItemStyle = emphasisModel.getModel('itemStyle').getItemStyle(); + selectItemStyle = itemModel.getModel(['select', 'itemStyle']).getItemStyle(); + blurItemStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle(); + focus = emphasisModel.get('focus'); + blurScope = emphasisModel.get('blurScope'); + emphasisDisabled = emphasisModel.get('disabled'); + labelStatesModels = getLabelStatesModels(itemModel); + hoverScale = emphasisModel.getShallow('scale'); + cursorStyle = itemModel.getShallow('cursor'); + } + + var symbolRotate = data.getItemVisual(idx, 'symbolRotate'); + symbolPath.attr('rotation', (symbolRotate || 0) * Math.PI / 180 || 0); + var symbolOffset = normalizeSymbolOffset(data.getItemVisual(idx, 'symbolOffset'), symbolSize); + + if (symbolOffset) { + symbolPath.x = symbolOffset[0]; + symbolPath.y = symbolOffset[1]; + } + + cursorStyle && symbolPath.attr('cursor', cursorStyle); + var symbolStyle = data.getItemVisual(idx, 'style'); + var visualColor = symbolStyle.fill; + + if (symbolPath instanceof ZRImage) { + var pathStyle = symbolPath.style; + symbolPath.useStyle(extend({ + // TODO other properties like x, y ? + image: pathStyle.image, + x: pathStyle.x, + y: pathStyle.y, + width: pathStyle.width, + height: pathStyle.height + }, symbolStyle)); + } else { + if (symbolPath.__isEmptyBrush) { + // fill and stroke will be swapped if it's empty. + // So we cloned a new style to avoid it affecting the original style in visual storage. + // TODO Better implementation. No empty logic! + symbolPath.useStyle(extend({}, symbolStyle)); + } else { + symbolPath.useStyle(symbolStyle); + } // Disable decal because symbol scale will been applied on the decal. + + + symbolPath.style.decal = null; + symbolPath.setColor(visualColor, opts && opts.symbolInnerColor); + symbolPath.style.strokeNoScale = true; + } + + var liftZ = data.getItemVisual(idx, 'liftZ'); + var z2Origin = this._z2; + + if (liftZ != null) { + if (z2Origin == null) { + this._z2 = symbolPath.z2; + symbolPath.z2 += liftZ; + } + } else if (z2Origin != null) { + symbolPath.z2 = z2Origin; + this._z2 = null; + } + + var useNameLabel = opts && opts.useNameLabel; + setLabelStyle(symbolPath, labelStatesModels, { + labelFetcher: seriesModel, + labelDataIndex: idx, + defaultText: getLabelDefaultText, + inheritColor: visualColor, + defaultOpacity: symbolStyle.opacity + }); // Do not execute util needed. + + function getLabelDefaultText(idx) { + return useNameLabel ? data.getName(idx) : getDefaultLabel(data, idx); + } + + this._sizeX = symbolSize[0] / 2; + this._sizeY = symbolSize[1] / 2; + var emphasisState = symbolPath.ensureState('emphasis'); + emphasisState.style = emphasisItemStyle; + symbolPath.ensureState('select').style = selectItemStyle; + symbolPath.ensureState('blur').style = blurItemStyle; + + if (hoverScale) { + var scaleRatio = Math.max(isNumber(hoverScale) ? hoverScale : 1.1, 3 / this._sizeY); + emphasisState.scaleX = this._sizeX * scaleRatio; + emphasisState.scaleY = this._sizeY * scaleRatio; + } + + this.setSymbolScale(1); + toggleHoverEmphasis(this, focus, blurScope, emphasisDisabled); + }; + + Symbol.prototype.setSymbolScale = function (scale) { + this.scaleX = this.scaleY = scale; + }; + + Symbol.prototype.fadeOut = function (cb, seriesModel, opt) { + var symbolPath = this.childAt(0); + var dataIndex = getECData(this).dataIndex; + var animationOpt = opt && opt.animation; // Avoid mistaken hover when fading out + + this.silent = symbolPath.silent = true; // Not show text when animating + + if (opt && opt.fadeLabel) { + var textContent = symbolPath.getTextContent(); + + if (textContent) { + removeElement(textContent, { + style: { + opacity: 0 + } + }, seriesModel, { + dataIndex: dataIndex, + removeOpt: animationOpt, + cb: function () { + symbolPath.removeTextContent(); + } + }); + } + } else { + symbolPath.removeTextContent(); + } + + removeElement(symbolPath, { + style: { + opacity: 0 + }, + scaleX: 0, + scaleY: 0 + }, seriesModel, { + dataIndex: dataIndex, + cb: cb, + removeOpt: animationOpt + }); + }; + + Symbol.getSymbolSize = function (data, idx) { + return normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize')); + }; + + return Symbol; + }(Group); + + function driftSymbol(dx, dy) { + this.parent.drift(dx, dy); + } + + function symbolNeedsDraw(data, point, idx, opt) { + return point && !isNaN(point[0]) && !isNaN(point[1]) && !(opt.isIgnore && opt.isIgnore(idx)) // We do not set clipShape on group, because it will cut part of + // the symbol element shape. We use the same clip shape here as + // the line clip. + && !(opt.clipShape && !opt.clipShape.contain(point[0], point[1])) && data.getItemVisual(idx, 'symbol') !== 'none'; + } + + function normalizeUpdateOpt(opt) { + if (opt != null && !isObject(opt)) { + opt = { + isIgnore: opt + }; + } + + return opt || {}; + } + + function makeSeriesScope(data) { + var seriesModel = data.hostModel; + var emphasisModel = seriesModel.getModel('emphasis'); + return { + emphasisItemStyle: emphasisModel.getModel('itemStyle').getItemStyle(), + blurItemStyle: seriesModel.getModel(['blur', 'itemStyle']).getItemStyle(), + selectItemStyle: seriesModel.getModel(['select', 'itemStyle']).getItemStyle(), + focus: emphasisModel.get('focus'), + blurScope: emphasisModel.get('blurScope'), + emphasisDisabled: emphasisModel.get('disabled'), + hoverScale: emphasisModel.get('scale'), + labelStatesModels: getLabelStatesModels(seriesModel), + cursorStyle: seriesModel.get('cursor') + }; + } + + var SymbolDraw = + /** @class */ + function () { + function SymbolDraw(SymbolCtor) { + this.group = new Group(); + this._SymbolCtor = SymbolCtor || Symbol; + } + /** + * Update symbols draw by new data + */ + + + SymbolDraw.prototype.updateData = function (data, opt) { + // Remove progressive els. + this._progressiveEls = null; + opt = normalizeUpdateOpt(opt); + var group = this.group; + var seriesModel = data.hostModel; + var oldData = this._data; + var SymbolCtor = this._SymbolCtor; + var disableAnimation = opt.disableAnimation; + var seriesScope = makeSeriesScope(data); + var symbolUpdateOpt = { + disableAnimation: disableAnimation + }; + + var getSymbolPoint = opt.getSymbolPoint || function (idx) { + return data.getItemLayout(idx); + }; // There is no oldLineData only when first rendering or switching from + // stream mode to normal mode, where previous elements should be removed. + + + if (!oldData) { + group.removeAll(); + } + + data.diff(oldData).add(function (newIdx) { + var point = getSymbolPoint(newIdx); + + if (symbolNeedsDraw(data, point, newIdx, opt)) { + var symbolEl = new SymbolCtor(data, newIdx, seriesScope, symbolUpdateOpt); + symbolEl.setPosition(point); + data.setItemGraphicEl(newIdx, symbolEl); + group.add(symbolEl); + } + }).update(function (newIdx, oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); + var point = getSymbolPoint(newIdx); + + if (!symbolNeedsDraw(data, point, newIdx, opt)) { + group.remove(symbolEl); + return; + } + + var newSymbolType = data.getItemVisual(newIdx, 'symbol') || 'circle'; + var oldSymbolType = symbolEl && symbolEl.getSymbolType && symbolEl.getSymbolType(); + + if (!symbolEl // Create a new if symbol type changed. + || oldSymbolType && oldSymbolType !== newSymbolType) { + group.remove(symbolEl); + symbolEl = new SymbolCtor(data, newIdx, seriesScope, symbolUpdateOpt); + symbolEl.setPosition(point); + } else { + symbolEl.updateData(data, newIdx, seriesScope, symbolUpdateOpt); + var target = { + x: point[0], + y: point[1] + }; + disableAnimation ? symbolEl.attr(target) : updateProps(symbolEl, target, seriesModel); + } // Add back + + + group.add(symbolEl); + data.setItemGraphicEl(newIdx, symbolEl); + }).remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && el.fadeOut(function () { + group.remove(el); + }, seriesModel); + }).execute(); + this._getSymbolPoint = getSymbolPoint; + this._data = data; + }; + + SymbolDraw.prototype.updateLayout = function () { + var _this = this; + + var data = this._data; + + if (data) { + // Not use animation + data.eachItemGraphicEl(function (el, idx) { + var point = _this._getSymbolPoint(idx); + + el.setPosition(point); + el.markRedraw(); + }); + } + }; + + SymbolDraw.prototype.incrementalPrepareUpdate = function (data) { + this._seriesScope = makeSeriesScope(data); + this._data = null; + this.group.removeAll(); + }; + /** + * Update symbols draw by new data + */ + + SymbolDraw.prototype.incrementalUpdate = function (taskParams, data, opt) { + // Clear + this._progressiveEls = []; + opt = normalizeUpdateOpt(opt); + + function updateIncrementalAndHover(el) { + if (!el.isGroup) { + el.incremental = true; + el.ensureState('emphasis').hoverLayer = true; + } + } + + for (var idx = taskParams.start; idx < taskParams.end; idx++) { + var point = data.getItemLayout(idx); + + if (symbolNeedsDraw(data, point, idx, opt)) { + var el = new this._SymbolCtor(data, idx, this._seriesScope); + el.traverse(updateIncrementalAndHover); + el.setPosition(point); + this.group.add(el); + data.setItemGraphicEl(idx, el); + + this._progressiveEls.push(el); + } + } + }; + + SymbolDraw.prototype.eachRendered = function (cb) { + traverseElements(this._progressiveEls || this.group, cb); + }; + + SymbolDraw.prototype.remove = function (enableAnimation) { + var group = this.group; + var data = this._data; // Incremental model do not have this._data. + + if (data && enableAnimation) { + data.eachItemGraphicEl(function (el) { + el.fadeOut(function () { + group.remove(el); + }, data.hostModel); + }); + } else { + group.removeAll(); + } + }; + return SymbolDraw; + }(); + + function prepareDataCoordInfo(coordSys, data, valueOrigin) { + var baseAxis = coordSys.getBaseAxis(); + var valueAxis = coordSys.getOtherAxis(baseAxis); + var valueStart = getValueStart(valueAxis, valueOrigin); + var baseAxisDim = baseAxis.dim; + var valueAxisDim = valueAxis.dim; + var valueDim = data.mapDimension(valueAxisDim); + var baseDim = data.mapDimension(baseAxisDim); + var baseDataOffset = valueAxisDim === 'x' || valueAxisDim === 'radius' ? 1 : 0; + var dims = map(coordSys.dimensions, function (coordDim) { + return data.mapDimension(coordDim); + }); + var stacked = false; + var stackResultDim = data.getCalculationInfo('stackResultDimension'); + + if (isDimensionStacked(data, dims[0] + /*, dims[1]*/ + )) { + // jshint ignore:line + stacked = true; + dims[0] = stackResultDim; + } + + if (isDimensionStacked(data, dims[1] + /*, dims[0]*/ + )) { + // jshint ignore:line + stacked = true; + dims[1] = stackResultDim; + } + + return { + dataDimsForPoint: dims, + valueStart: valueStart, + valueAxisDim: valueAxisDim, + baseAxisDim: baseAxisDim, + stacked: !!stacked, + valueDim: valueDim, + baseDim: baseDim, + baseDataOffset: baseDataOffset, + stackedOverDimension: data.getCalculationInfo('stackedOverDimension') + }; + } + + function getValueStart(valueAxis, valueOrigin) { + var valueStart = 0; + var extent = valueAxis.scale.getExtent(); + + if (valueOrigin === 'start') { + valueStart = extent[0]; + } else if (valueOrigin === 'end') { + valueStart = extent[1]; + } // If origin is specified as a number, use it as + // valueStart directly + else if (isNumber(valueOrigin) && !isNaN(valueOrigin)) { + valueStart = valueOrigin; + } // auto + else { + // Both positive + if (extent[0] > 0) { + valueStart = extent[0]; + } // Both negative + else if (extent[1] < 0) { + valueStart = extent[1]; + } // If is one positive, and one negative, onZero shall be true + + } + + return valueStart; + } + + function getStackedOnPoint(dataCoordInfo, coordSys, data, idx) { + var value = NaN; + + if (dataCoordInfo.stacked) { + value = data.get(data.getCalculationInfo('stackedOverDimension'), idx); + } + + if (isNaN(value)) { + value = dataCoordInfo.valueStart; + } + + var baseDataOffset = dataCoordInfo.baseDataOffset; + var stackedData = []; + stackedData[baseDataOffset] = data.get(dataCoordInfo.baseDim, idx); + stackedData[1 - baseDataOffset] = value; + return coordSys.dataToPoint(stackedData); + } + + function diffData(oldData, newData) { + var diffResult = []; + newData.diff(oldData).add(function (idx) { + diffResult.push({ + cmd: '+', + idx: idx + }); + }).update(function (newIdx, oldIdx) { + diffResult.push({ + cmd: '=', + idx: oldIdx, + idx1: newIdx + }); + }).remove(function (idx) { + diffResult.push({ + cmd: '-', + idx: idx + }); + }).execute(); + return diffResult; + } + + function lineAnimationDiff(oldData, newData, oldStackedOnPoints, newStackedOnPoints, oldCoordSys, newCoordSys, oldValueOrigin, newValueOrigin) { + var diff = diffData(oldData, newData); // let newIdList = newData.mapArray(newData.getId); + // let oldIdList = oldData.mapArray(oldData.getId); + // convertToIntId(newIdList, oldIdList); + // // FIXME One data ? + // diff = arrayDiff(oldIdList, newIdList); + + var currPoints = []; + var nextPoints = []; // Points for stacking base line + + var currStackedPoints = []; + var nextStackedPoints = []; + var status = []; + var sortedIndices = []; + var rawIndices = []; + var newDataOldCoordInfo = prepareDataCoordInfo(oldCoordSys, newData, oldValueOrigin); // const oldDataNewCoordInfo = prepareDataCoordInfo(newCoordSys, oldData, newValueOrigin); + + var oldPoints = oldData.getLayout('points') || []; + var newPoints = newData.getLayout('points') || []; + + for (var i = 0; i < diff.length; i++) { + var diffItem = diff[i]; + var pointAdded = true; + var oldIdx2 = void 0; + var newIdx2 = void 0; // FIXME, animation is not so perfect when dataZoom window moves fast + // Which is in case remvoing or add more than one data in the tail or head + + switch (diffItem.cmd) { + case '=': + oldIdx2 = diffItem.idx * 2; + newIdx2 = diffItem.idx1 * 2; + var currentX = oldPoints[oldIdx2]; + var currentY = oldPoints[oldIdx2 + 1]; + var nextX = newPoints[newIdx2]; + var nextY = newPoints[newIdx2 + 1]; // If previous data is NaN, use next point directly + + if (isNaN(currentX) || isNaN(currentY)) { + currentX = nextX; + currentY = nextY; + } + + currPoints.push(currentX, currentY); + nextPoints.push(nextX, nextY); + currStackedPoints.push(oldStackedOnPoints[oldIdx2], oldStackedOnPoints[oldIdx2 + 1]); + nextStackedPoints.push(newStackedOnPoints[newIdx2], newStackedOnPoints[newIdx2 + 1]); + rawIndices.push(newData.getRawIndex(diffItem.idx1)); + break; + + case '+': + var newIdx = diffItem.idx; + var newDataDimsForPoint = newDataOldCoordInfo.dataDimsForPoint; + var oldPt = oldCoordSys.dataToPoint([newData.get(newDataDimsForPoint[0], newIdx), newData.get(newDataDimsForPoint[1], newIdx)]); + newIdx2 = newIdx * 2; + currPoints.push(oldPt[0], oldPt[1]); + nextPoints.push(newPoints[newIdx2], newPoints[newIdx2 + 1]); + var stackedOnPoint = getStackedOnPoint(newDataOldCoordInfo, oldCoordSys, newData, newIdx); + currStackedPoints.push(stackedOnPoint[0], stackedOnPoint[1]); + nextStackedPoints.push(newStackedOnPoints[newIdx2], newStackedOnPoints[newIdx2 + 1]); + rawIndices.push(newData.getRawIndex(newIdx)); + break; + + case '-': + pointAdded = false; + } // Original indices + + + if (pointAdded) { + status.push(diffItem); + sortedIndices.push(sortedIndices.length); + } + } // Diff result may be crossed if all items are changed + // Sort by data index + + + sortedIndices.sort(function (a, b) { + return rawIndices[a] - rawIndices[b]; + }); + var len = currPoints.length; + var sortedCurrPoints = createFloat32Array(len); + var sortedNextPoints = createFloat32Array(len); + var sortedCurrStackedPoints = createFloat32Array(len); + var sortedNextStackedPoints = createFloat32Array(len); + var sortedStatus = []; + + for (var i = 0; i < sortedIndices.length; i++) { + var idx = sortedIndices[i]; + var i2 = i * 2; + var idx2 = idx * 2; + sortedCurrPoints[i2] = currPoints[idx2]; + sortedCurrPoints[i2 + 1] = currPoints[idx2 + 1]; + sortedNextPoints[i2] = nextPoints[idx2]; + sortedNextPoints[i2 + 1] = nextPoints[idx2 + 1]; + sortedCurrStackedPoints[i2] = currStackedPoints[idx2]; + sortedCurrStackedPoints[i2 + 1] = currStackedPoints[idx2 + 1]; + sortedNextStackedPoints[i2] = nextStackedPoints[idx2]; + sortedNextStackedPoints[i2 + 1] = nextStackedPoints[idx2 + 1]; + sortedStatus[i] = status[idx]; + } + + return { + current: sortedCurrPoints, + next: sortedNextPoints, + stackedOnCurrent: sortedCurrStackedPoints, + stackedOnNext: sortedNextStackedPoints, + status: sortedStatus + }; + } + + var mathMin$5 = Math.min; + var mathMax$5 = Math.max; + + function isPointNull(x, y) { + return isNaN(x) || isNaN(y); + } + /** + * Draw smoothed line in non-monotone, in may cause undesired curve in extreme + * situations. This should be used when points are non-monotone neither in x or + * y dimension. + */ + + + function drawSegment(ctx, points, start, segLen, allLen, dir, smooth, smoothMonotone, connectNulls) { + var prevX; + var prevY; + var cpx0; + var cpy0; + var cpx1; + var cpy1; + var idx = start; + var k = 0; + + for (; k < segLen; k++) { + var x = points[idx * 2]; + var y = points[idx * 2 + 1]; + + if (idx >= allLen || idx < 0) { + break; + } + + if (isPointNull(x, y)) { + if (connectNulls) { + idx += dir; + continue; + } + + break; + } + + if (idx === start) { + ctx[dir > 0 ? 'moveTo' : 'lineTo'](x, y); + cpx0 = x; + cpy0 = y; + } else { + var dx = x - prevX; + var dy = y - prevY; // Ignore tiny segment. + + if (dx * dx + dy * dy < 0.5) { + idx += dir; + continue; + } + + if (smooth > 0) { + var nextIdx = idx + dir; + var nextX = points[nextIdx * 2]; + var nextY = points[nextIdx * 2 + 1]; // Ignore duplicate point + + while (nextX === x && nextY === y && k < segLen) { + k++; + nextIdx += dir; + idx += dir; + nextX = points[nextIdx * 2]; + nextY = points[nextIdx * 2 + 1]; + x = points[idx * 2]; + y = points[idx * 2 + 1]; + dx = x - prevX; + dy = y - prevY; + } + + var tmpK = k + 1; + + if (connectNulls) { + // Find next point not null + while (isPointNull(nextX, nextY) && tmpK < segLen) { + tmpK++; + nextIdx += dir; + nextX = points[nextIdx * 2]; + nextY = points[nextIdx * 2 + 1]; + } + } + + var ratioNextSeg = 0.5; + var vx = 0; + var vy = 0; + var nextCpx0 = void 0; + var nextCpy0 = void 0; // Is last point + + if (tmpK >= segLen || isPointNull(nextX, nextY)) { + cpx1 = x; + cpy1 = y; + } else { + vx = nextX - prevX; + vy = nextY - prevY; + var dx0 = x - prevX; + var dx1 = nextX - x; + var dy0 = y - prevY; + var dy1 = nextY - y; + var lenPrevSeg = void 0; + var lenNextSeg = void 0; + + if (smoothMonotone === 'x') { + lenPrevSeg = Math.abs(dx0); + lenNextSeg = Math.abs(dx1); + var dir_1 = vx > 0 ? 1 : -1; + cpx1 = x - dir_1 * lenPrevSeg * smooth; + cpy1 = y; + nextCpx0 = x + dir_1 * lenNextSeg * smooth; + nextCpy0 = y; + } else if (smoothMonotone === 'y') { + lenPrevSeg = Math.abs(dy0); + lenNextSeg = Math.abs(dy1); + var dir_2 = vy > 0 ? 1 : -1; + cpx1 = x; + cpy1 = y - dir_2 * lenPrevSeg * smooth; + nextCpx0 = x; + nextCpy0 = y + dir_2 * lenNextSeg * smooth; + } else { + lenPrevSeg = Math.sqrt(dx0 * dx0 + dy0 * dy0); + lenNextSeg = Math.sqrt(dx1 * dx1 + dy1 * dy1); // Use ratio of seg length + + ratioNextSeg = lenNextSeg / (lenNextSeg + lenPrevSeg); + cpx1 = x - vx * smooth * (1 - ratioNextSeg); + cpy1 = y - vy * smooth * (1 - ratioNextSeg); // cp0 of next segment + + nextCpx0 = x + vx * smooth * ratioNextSeg; + nextCpy0 = y + vy * smooth * ratioNextSeg; // Smooth constraint between point and next point. + // Avoid exceeding extreme after smoothing. + + nextCpx0 = mathMin$5(nextCpx0, mathMax$5(nextX, x)); + nextCpy0 = mathMin$5(nextCpy0, mathMax$5(nextY, y)); + nextCpx0 = mathMax$5(nextCpx0, mathMin$5(nextX, x)); + nextCpy0 = mathMax$5(nextCpy0, mathMin$5(nextY, y)); // Reclaculate cp1 based on the adjusted cp0 of next seg. + + vx = nextCpx0 - x; + vy = nextCpy0 - y; + cpx1 = x - vx * lenPrevSeg / lenNextSeg; + cpy1 = y - vy * lenPrevSeg / lenNextSeg; // Smooth constraint between point and prev point. + // Avoid exceeding extreme after smoothing. + + cpx1 = mathMin$5(cpx1, mathMax$5(prevX, x)); + cpy1 = mathMin$5(cpy1, mathMax$5(prevY, y)); + cpx1 = mathMax$5(cpx1, mathMin$5(prevX, x)); + cpy1 = mathMax$5(cpy1, mathMin$5(prevY, y)); // Adjust next cp0 again. + + vx = x - cpx1; + vy = y - cpy1; + nextCpx0 = x + vx * lenNextSeg / lenPrevSeg; + nextCpy0 = y + vy * lenNextSeg / lenPrevSeg; + } + } + + ctx.bezierCurveTo(cpx0, cpy0, cpx1, cpy1, x, y); + cpx0 = nextCpx0; + cpy0 = nextCpy0; + } else { + ctx.lineTo(x, y); + } + } + + prevX = x; + prevY = y; + idx += dir; + } + + return k; + } + + var ECPolylineShape = + /** @class */ + function () { + function ECPolylineShape() { + this.smooth = 0; + this.smoothConstraint = true; + } + + return ECPolylineShape; + }(); + + var ECPolyline = + /** @class */ + function (_super) { + __extends(ECPolyline, _super); + + function ECPolyline(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'ec-polyline'; + return _this; + } + + ECPolyline.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + + ECPolyline.prototype.getDefaultShape = function () { + return new ECPolylineShape(); + }; + + ECPolyline.prototype.buildPath = function (ctx, shape) { + var points = shape.points; + var i = 0; + var len = points.length / 2; // const result = getBoundingBox(points, shape.smoothConstraint); + + if (shape.connectNulls) { + // Must remove first and last null values avoid draw error in polygon + for (; len > 0; len--) { + if (!isPointNull(points[len * 2 - 2], points[len * 2 - 1])) { + break; + } + } + + for (; i < len; i++) { + if (!isPointNull(points[i * 2], points[i * 2 + 1])) { + break; + } + } + } + + while (i < len) { + i += drawSegment(ctx, points, i, len, len, 1, shape.smooth, shape.smoothMonotone, shape.connectNulls) + 1; + } + }; + + ECPolyline.prototype.getPointOn = function (xOrY, dim) { + if (!this.path) { + this.createPathProxy(); + this.buildPath(this.path, this.shape); + } + + var path = this.path; + var data = path.data; + var CMD = PathProxy.CMD; + var x0; + var y0; + var isDimX = dim === 'x'; + var roots = []; + + for (var i = 0; i < data.length;) { + var cmd = data[i++]; + var x = void 0; + var y = void 0; + var x2 = void 0; + var y2 = void 0; + var x3 = void 0; + var y3 = void 0; + var t = void 0; + + switch (cmd) { + case CMD.M: + x0 = data[i++]; + y0 = data[i++]; + break; + + case CMD.L: + x = data[i++]; + y = data[i++]; + t = isDimX ? (xOrY - x0) / (x - x0) : (xOrY - y0) / (y - y0); + + if (t <= 1 && t >= 0) { + var val = isDimX ? (y - y0) * t + y0 : (x - x0) * t + x0; + return isDimX ? [xOrY, val] : [val, xOrY]; + } + + x0 = x; + y0 = y; + break; + + case CMD.C: + x = data[i++]; + y = data[i++]; + x2 = data[i++]; + y2 = data[i++]; + x3 = data[i++]; + y3 = data[i++]; + var nRoot = isDimX ? cubicRootAt(x0, x, x2, x3, xOrY, roots) : cubicRootAt(y0, y, y2, y3, xOrY, roots); + + if (nRoot > 0) { + for (var i_1 = 0; i_1 < nRoot; i_1++) { + var t_1 = roots[i_1]; + + if (t_1 <= 1 && t_1 >= 0) { + var val = isDimX ? cubicAt(y0, y, y2, y3, t_1) : cubicAt(x0, x, x2, x3, t_1); + return isDimX ? [xOrY, val] : [val, xOrY]; + } + } + } + + x0 = x3; + y0 = y3; + break; + } + } + }; + + return ECPolyline; + }(Path); + + var ECPolygonShape = + /** @class */ + function (_super) { + __extends(ECPolygonShape, _super); + + function ECPolygonShape() { + return _super !== null && _super.apply(this, arguments) || this; + } + + return ECPolygonShape; + }(ECPolylineShape); + + var ECPolygon = + /** @class */ + function (_super) { + __extends(ECPolygon, _super); + + function ECPolygon(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'ec-polygon'; + return _this; + } + + ECPolygon.prototype.getDefaultShape = function () { + return new ECPolygonShape(); + }; + + ECPolygon.prototype.buildPath = function (ctx, shape) { + var points = shape.points; + var stackedOnPoints = shape.stackedOnPoints; + var i = 0; + var len = points.length / 2; + var smoothMonotone = shape.smoothMonotone; + + if (shape.connectNulls) { + // Must remove first and last null values avoid draw error in polygon + for (; len > 0; len--) { + if (!isPointNull(points[len * 2 - 2], points[len * 2 - 1])) { + break; + } + } + + for (; i < len; i++) { + if (!isPointNull(points[i * 2], points[i * 2 + 1])) { + break; + } + } + } + + while (i < len) { + var k = drawSegment(ctx, points, i, len, len, 1, shape.smooth, smoothMonotone, shape.connectNulls); + drawSegment(ctx, stackedOnPoints, i + k - 1, k, len, -1, shape.stackedOnSmooth, smoothMonotone, shape.connectNulls); + i += k + 1; + ctx.closePath(); + } + }; + + return ECPolygon; + }(Path); + + function createGridClipPath(cartesian, hasAnimation, seriesModel, done, during) { + var rect = cartesian.getArea(); + var x = rect.x; + var y = rect.y; + var width = rect.width; + var height = rect.height; + var lineWidth = seriesModel.get(['lineStyle', 'width']) || 2; // Expand the clip path a bit to avoid the border is clipped and looks thinner + + x -= lineWidth / 2; + y -= lineWidth / 2; + width += lineWidth; + height += lineWidth; // fix: https://github.com/apache/incubator-echarts/issues/11369 + + x = Math.floor(x); + width = Math.round(width); + var clipPath = new Rect({ + shape: { + x: x, + y: y, + width: width, + height: height + } + }); + + if (hasAnimation) { + var baseAxis = cartesian.getBaseAxis(); + var isHorizontal = baseAxis.isHorizontal(); + var isAxisInversed = baseAxis.inverse; + + if (isHorizontal) { + if (isAxisInversed) { + clipPath.shape.x += width; + } + + clipPath.shape.width = 0; + } else { + if (!isAxisInversed) { + clipPath.shape.y += height; + } + + clipPath.shape.height = 0; + } + + var duringCb = isFunction(during) ? function (percent) { + during(percent, clipPath); + } : null; + initProps(clipPath, { + shape: { + width: width, + height: height, + x: x, + y: y + } + }, seriesModel, null, done, duringCb); + } + + return clipPath; + } + + function createPolarClipPath(polar, hasAnimation, seriesModel) { + var sectorArea = polar.getArea(); // Avoid float number rounding error for symbol on the edge of axis extent. + + var r0 = round(sectorArea.r0, 1); + var r = round(sectorArea.r, 1); + var clipPath = new Sector({ + shape: { + cx: round(polar.cx, 1), + cy: round(polar.cy, 1), + r0: r0, + r: r, + startAngle: sectorArea.startAngle, + endAngle: sectorArea.endAngle, + clockwise: sectorArea.clockwise + } + }); + + if (hasAnimation) { + var isRadial = polar.getBaseAxis().dim === 'angle'; + + if (isRadial) { + clipPath.shape.endAngle = sectorArea.startAngle; + } else { + clipPath.shape.r = r0; + } + + initProps(clipPath, { + shape: { + endAngle: sectorArea.endAngle, + r: r + } + }, seriesModel); + } + + return clipPath; + } + + function createClipPath(coordSys, hasAnimation, seriesModel, done, during) { + if (!coordSys) { + return null; + } else if (coordSys.type === 'polar') { + return createPolarClipPath(coordSys, hasAnimation, seriesModel); + } else if (coordSys.type === 'cartesian2d') { + return createGridClipPath(coordSys, hasAnimation, seriesModel, done, during); + } + + return null; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function isCoordinateSystemType(coordSys, type) { + return coordSys.type === type; + } + + function isPointsSame(points1, points2) { + if (points1.length !== points2.length) { + return; + } + + for (var i = 0; i < points1.length; i++) { + if (points1[i] !== points2[i]) { + return; + } + } + + return true; + } + + function bboxFromPoints(points) { + var minX = Infinity; + var minY = Infinity; + var maxX = -Infinity; + var maxY = -Infinity; + + for (var i = 0; i < points.length;) { + var x = points[i++]; + var y = points[i++]; + + if (!isNaN(x)) { + minX = Math.min(x, minX); + maxX = Math.max(x, maxX); + } + + if (!isNaN(y)) { + minY = Math.min(y, minY); + maxY = Math.max(y, maxY); + } + } + + return [[minX, minY], [maxX, maxY]]; + } + + function getBoundingDiff(points1, points2) { + var _a = bboxFromPoints(points1), + min1 = _a[0], + max1 = _a[1]; + + var _b = bboxFromPoints(points2), + min2 = _b[0], + max2 = _b[1]; // Get a max value from each corner of two boundings. + + + return Math.max(Math.abs(min1[0] - min2[0]), Math.abs(min1[1] - min2[1]), Math.abs(max1[0] - max2[0]), Math.abs(max1[1] - max2[1])); + } + + function getSmooth(smooth) { + return isNumber(smooth) ? smooth : smooth ? 0.5 : 0; + } + + function getStackedOnPoints(coordSys, data, dataCoordInfo) { + if (!dataCoordInfo.valueDim) { + return []; + } + + var len = data.count(); + var points = createFloat32Array(len * 2); + + for (var idx = 0; idx < len; idx++) { + var pt = getStackedOnPoint(dataCoordInfo, coordSys, data, idx); + points[idx * 2] = pt[0]; + points[idx * 2 + 1] = pt[1]; + } + + return points; + } + + function turnPointsIntoStep(points, coordSys, stepTurnAt, connectNulls) { + var baseAxis = coordSys.getBaseAxis(); + var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1; + var stepPoints = []; + var i = 0; + var stepPt = []; + var pt = []; + var nextPt = []; + var filteredPoints = []; + + if (connectNulls) { + for (i = 0; i < points.length; i += 2) { + if (!isNaN(points[i]) && !isNaN(points[i + 1])) { + filteredPoints.push(points[i], points[i + 1]); + } + } + + points = filteredPoints; + } + + for (i = 0; i < points.length - 2; i += 2) { + nextPt[0] = points[i + 2]; + nextPt[1] = points[i + 3]; + pt[0] = points[i]; + pt[1] = points[i + 1]; + stepPoints.push(pt[0], pt[1]); + + switch (stepTurnAt) { + case 'end': + stepPt[baseIndex] = nextPt[baseIndex]; + stepPt[1 - baseIndex] = pt[1 - baseIndex]; + stepPoints.push(stepPt[0], stepPt[1]); + break; + + case 'middle': + var middle = (pt[baseIndex] + nextPt[baseIndex]) / 2; + var stepPt2 = []; + stepPt[baseIndex] = stepPt2[baseIndex] = middle; + stepPt[1 - baseIndex] = pt[1 - baseIndex]; + stepPt2[1 - baseIndex] = nextPt[1 - baseIndex]; + stepPoints.push(stepPt[0], stepPt[1]); + stepPoints.push(stepPt2[0], stepPt2[1]); + break; + + default: + // default is start + stepPt[baseIndex] = pt[baseIndex]; + stepPt[1 - baseIndex] = nextPt[1 - baseIndex]; + stepPoints.push(stepPt[0], stepPt[1]); + } + } // Last points + + + stepPoints.push(points[i++], points[i++]); + return stepPoints; + } + /** + * Clip color stops to edge. Avoid creating too large gradients. + * Which may lead to blurry when GPU acceleration is enabled. See #15680 + * + * The stops has been sorted from small to large. + */ + + + function clipColorStops(colorStops, maxSize) { + var newColorStops = []; + var len = colorStops.length; // coord will always < 0 in prevOutOfRangeColorStop. + + var prevOutOfRangeColorStop; + var prevInRangeColorStop; + + function lerpStop(stop0, stop1, clippedCoord) { + var coord0 = stop0.coord; + var p = (clippedCoord - coord0) / (stop1.coord - coord0); + var color = lerp$1(p, [stop0.color, stop1.color]); + return { + coord: clippedCoord, + color: color + }; + } + + for (var i = 0; i < len; i++) { + var stop_1 = colorStops[i]; + var coord = stop_1.coord; + + if (coord < 0) { + prevOutOfRangeColorStop = stop_1; + } else if (coord > maxSize) { + if (prevInRangeColorStop) { + newColorStops.push(lerpStop(prevInRangeColorStop, stop_1, maxSize)); + } else if (prevOutOfRangeColorStop) { + // If there are two stops and coord range is between these two stops + newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop_1, 0), lerpStop(prevOutOfRangeColorStop, stop_1, maxSize)); + } // All following stop will be out of range. So just ignore them. + + + break; + } else { + if (prevOutOfRangeColorStop) { + newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop_1, 0)); // Reset + + prevOutOfRangeColorStop = null; + } + + newColorStops.push(stop_1); + prevInRangeColorStop = stop_1; + } + } + + return newColorStops; + } + + function getVisualGradient(data, coordSys, api) { + var visualMetaList = data.getVisual('visualMeta'); + + if (!visualMetaList || !visualMetaList.length || !data.count()) { + // When data.count() is 0, gradient range can not be calculated. + return; + } + + if (coordSys.type !== 'cartesian2d') { + if ("development" !== 'production') { + console.warn('Visual map on line style is only supported on cartesian2d.'); + } + + return; + } + + var coordDim; + var visualMeta; + + for (var i = visualMetaList.length - 1; i >= 0; i--) { + var dimInfo = data.getDimensionInfo(visualMetaList[i].dimension); + coordDim = dimInfo && dimInfo.coordDim; // Can only be x or y + + if (coordDim === 'x' || coordDim === 'y') { + visualMeta = visualMetaList[i]; + break; + } + } + + if (!visualMeta) { + if ("development" !== 'production') { + console.warn('Visual map on line style only support x or y dimension.'); + } + + return; + } // If the area to be rendered is bigger than area defined by LinearGradient, + // the canvas spec prescribes that the color of the first stop and the last + // stop should be used. But if two stops are added at offset 0, in effect + // browsers use the color of the second stop to render area outside + // LinearGradient. So we can only infinitesimally extend area defined in + // LinearGradient to render `outerColors`. + + + var axis = coordSys.getAxis(coordDim); // dataToCoord mapping may not be linear, but must be monotonic. + + var colorStops = map(visualMeta.stops, function (stop) { + // offset will be calculated later. + return { + coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)), + color: stop.color + }; + }); + var stopLen = colorStops.length; + var outerColors = visualMeta.outerColors.slice(); + + if (stopLen && colorStops[0].coord > colorStops[stopLen - 1].coord) { + colorStops.reverse(); + outerColors.reverse(); + } + + var colorStopsInRange = clipColorStops(colorStops, coordDim === 'x' ? api.getWidth() : api.getHeight()); + var inRangeStopLen = colorStopsInRange.length; + + if (!inRangeStopLen && stopLen) { + // All stops are out of range. All will be the same color. + return colorStops[0].coord < 0 ? outerColors[1] ? outerColors[1] : colorStops[stopLen - 1].color : outerColors[0] ? outerColors[0] : colorStops[0].color; + } + + var tinyExtent = 10; // Arbitrary value: 10px + + var minCoord = colorStopsInRange[0].coord - tinyExtent; + var maxCoord = colorStopsInRange[inRangeStopLen - 1].coord + tinyExtent; + var coordSpan = maxCoord - minCoord; + + if (coordSpan < 1e-3) { + return 'transparent'; + } + + each(colorStopsInRange, function (stop) { + stop.offset = (stop.coord - minCoord) / coordSpan; + }); + colorStopsInRange.push({ + // NOTE: inRangeStopLen may still be 0 if stoplen is zero. + offset: inRangeStopLen ? colorStopsInRange[inRangeStopLen - 1].offset : 0.5, + color: outerColors[1] || 'transparent' + }); + colorStopsInRange.unshift({ + offset: inRangeStopLen ? colorStopsInRange[0].offset : 0.5, + color: outerColors[0] || 'transparent' + }); + var gradient = new LinearGradient(0, 0, 0, 0, colorStopsInRange, true); + gradient[coordDim] = minCoord; + gradient[coordDim + '2'] = maxCoord; + return gradient; + } + + function getIsIgnoreFunc(seriesModel, data, coordSys) { + var showAllSymbol = seriesModel.get('showAllSymbol'); + var isAuto = showAllSymbol === 'auto'; + + if (showAllSymbol && !isAuto) { + return; + } + + var categoryAxis = coordSys.getAxesByScale('ordinal')[0]; + + if (!categoryAxis) { + return; + } // Note that category label interval strategy might bring some weird effect + // in some scenario: users may wonder why some of the symbols are not + // displayed. So we show all symbols as possible as we can. + + + if (isAuto // Simplify the logic, do not determine label overlap here. + && canShowAllSymbolForCategory(categoryAxis, data)) { + return; + } // Otherwise follow the label interval strategy on category axis. + + + var categoryDataDim = data.mapDimension(categoryAxis.dim); + var labelMap = {}; + each(categoryAxis.getViewLabels(), function (labelItem) { + var ordinalNumber = categoryAxis.scale.getRawOrdinalNumber(labelItem.tickValue); + labelMap[ordinalNumber] = 1; + }); + return function (dataIndex) { + return !labelMap.hasOwnProperty(data.get(categoryDataDim, dataIndex)); + }; + } + + function canShowAllSymbolForCategory(categoryAxis, data) { + // In mose cases, line is monotonous on category axis, and the label size + // is close with each other. So we check the symbol size and some of the + // label size alone with the category axis to estimate whether all symbol + // can be shown without overlap. + var axisExtent = categoryAxis.getExtent(); + var availSize = Math.abs(axisExtent[1] - axisExtent[0]) / categoryAxis.scale.count(); + isNaN(availSize) && (availSize = 0); // 0/0 is NaN. + // Sampling some points, max 5. + + var dataLen = data.count(); + var step = Math.max(1, Math.round(dataLen / 5)); + + for (var dataIndex = 0; dataIndex < dataLen; dataIndex += step) { + if (Symbol.getSymbolSize(data, dataIndex // Only for cartesian, where `isHorizontal` exists. + )[categoryAxis.isHorizontal() ? 1 : 0] // Empirical number + * 1.5 > availSize) { + return false; + } + } + + return true; + } + + function isPointNull$1(x, y) { + return isNaN(x) || isNaN(y); + } + + function getLastIndexNotNull(points) { + var len = points.length / 2; + + for (; len > 0; len--) { + if (!isPointNull$1(points[len * 2 - 2], points[len * 2 - 1])) { + break; + } + } + + return len - 1; + } + + function getPointAtIndex(points, idx) { + return [points[idx * 2], points[idx * 2 + 1]]; + } + + function getIndexRange(points, xOrY, dim) { + var len = points.length / 2; + var dimIdx = dim === 'x' ? 0 : 1; + var a; + var b; + var prevIndex = 0; + var nextIndex = -1; + + for (var i = 0; i < len; i++) { + b = points[i * 2 + dimIdx]; + + if (isNaN(b) || isNaN(points[i * 2 + 1 - dimIdx])) { + continue; + } + + if (i === 0) { + a = b; + continue; + } + + if (a <= xOrY && b >= xOrY || a >= xOrY && b <= xOrY) { + nextIndex = i; + break; + } + + prevIndex = i; + a = b; + } + + return { + range: [prevIndex, nextIndex], + t: (xOrY - a) / (b - a) + }; + } + + function anyStateShowEndLabel(seriesModel) { + if (seriesModel.get(['endLabel', 'show'])) { + return true; + } + + for (var i = 0; i < SPECIAL_STATES.length; i++) { + if (seriesModel.get([SPECIAL_STATES[i], 'endLabel', 'show'])) { + return true; + } + } + + return false; + } + + function createLineClipPath(lineView, coordSys, hasAnimation, seriesModel) { + if (isCoordinateSystemType(coordSys, 'cartesian2d')) { + var endLabelModel_1 = seriesModel.getModel('endLabel'); + var valueAnimation_1 = endLabelModel_1.get('valueAnimation'); + var data_1 = seriesModel.getData(); + var labelAnimationRecord_1 = { + lastFrameIndex: 0 + }; + var during = anyStateShowEndLabel(seriesModel) ? function (percent, clipRect) { + lineView._endLabelOnDuring(percent, clipRect, data_1, labelAnimationRecord_1, valueAnimation_1, endLabelModel_1, coordSys); + } : null; + var isHorizontal = coordSys.getBaseAxis().isHorizontal(); + var clipPath = createGridClipPath(coordSys, hasAnimation, seriesModel, function () { + var endLabel = lineView._endLabel; + + if (endLabel && hasAnimation) { + if (labelAnimationRecord_1.originalX != null) { + endLabel.attr({ + x: labelAnimationRecord_1.originalX, + y: labelAnimationRecord_1.originalY + }); + } + } + }, during); // Expand clip shape to avoid clipping when line value exceeds axis + + if (!seriesModel.get('clip', true)) { + var rectShape = clipPath.shape; + var expandSize = Math.max(rectShape.width, rectShape.height); + + if (isHorizontal) { + rectShape.y -= expandSize; + rectShape.height += expandSize * 2; + } else { + rectShape.x -= expandSize; + rectShape.width += expandSize * 2; + } + } // Set to the final frame. To make sure label layout is right. + + + if (during) { + during(1, clipPath); + } + + return clipPath; + } else { + if ("development" !== 'production') { + if (seriesModel.get(['endLabel', 'show'])) { + console.warn('endLabel is not supported for lines in polar systems.'); + } + } + + return createPolarClipPath(coordSys, hasAnimation, seriesModel); + } + } + + function getEndLabelStateSpecified(endLabelModel, coordSys) { + var baseAxis = coordSys.getBaseAxis(); + var isHorizontal = baseAxis.isHorizontal(); + var isBaseInversed = baseAxis.inverse; + var align = isHorizontal ? isBaseInversed ? 'right' : 'left' : 'center'; + var verticalAlign = isHorizontal ? 'middle' : isBaseInversed ? 'top' : 'bottom'; + return { + normal: { + align: endLabelModel.get('align') || align, + verticalAlign: endLabelModel.get('verticalAlign') || verticalAlign + } + }; + } + + var LineView = + /** @class */ + function (_super) { + __extends(LineView, _super); + + function LineView() { + return _super !== null && _super.apply(this, arguments) || this; + } + + LineView.prototype.init = function () { + var lineGroup = new Group(); + var symbolDraw = new SymbolDraw(); + this.group.add(symbolDraw.group); + this._symbolDraw = symbolDraw; + this._lineGroup = lineGroup; + }; + + LineView.prototype.render = function (seriesModel, ecModel, api) { + var _this = this; + + var coordSys = seriesModel.coordinateSystem; + var group = this.group; + var data = seriesModel.getData(); + var lineStyleModel = seriesModel.getModel('lineStyle'); + var areaStyleModel = seriesModel.getModel('areaStyle'); + var points = data.getLayout('points') || []; + var isCoordSysPolar = coordSys.type === 'polar'; + var prevCoordSys = this._coordSys; + var symbolDraw = this._symbolDraw; + var polyline = this._polyline; + var polygon = this._polygon; + var lineGroup = this._lineGroup; + var hasAnimation = seriesModel.get('animation'); + var isAreaChart = !areaStyleModel.isEmpty(); + var valueOrigin = areaStyleModel.get('origin'); + var dataCoordInfo = prepareDataCoordInfo(coordSys, data, valueOrigin); + var stackedOnPoints = isAreaChart && getStackedOnPoints(coordSys, data, dataCoordInfo); + var showSymbol = seriesModel.get('showSymbol'); + var connectNulls = seriesModel.get('connectNulls'); + var isIgnoreFunc = showSymbol && !isCoordSysPolar && getIsIgnoreFunc(seriesModel, data, coordSys); // Remove temporary symbols + + var oldData = this._data; + oldData && oldData.eachItemGraphicEl(function (el, idx) { + if (el.__temp) { + group.remove(el); + oldData.setItemGraphicEl(idx, null); + } + }); // Remove previous created symbols if showSymbol changed to false + + if (!showSymbol) { + symbolDraw.remove(); + } + + group.add(lineGroup); // FIXME step not support polar + + var step = !isCoordSysPolar ? seriesModel.get('step') : false; + var clipShapeForSymbol; + + if (coordSys && coordSys.getArea && seriesModel.get('clip', true)) { + clipShapeForSymbol = coordSys.getArea(); // Avoid float number rounding error for symbol on the edge of axis extent. + // See #7913 and `test/dataZoom-clip.html`. + + if (clipShapeForSymbol.width != null) { + clipShapeForSymbol.x -= 0.1; + clipShapeForSymbol.y -= 0.1; + clipShapeForSymbol.width += 0.2; + clipShapeForSymbol.height += 0.2; + } else if (clipShapeForSymbol.r0) { + clipShapeForSymbol.r0 -= 0.5; + clipShapeForSymbol.r += 0.5; + } + } + + this._clipShapeForSymbol = clipShapeForSymbol; + var visualColor = getVisualGradient(data, coordSys, api) || data.getVisual('style')[data.getVisual('drawType')]; // Initialization animation or coordinate system changed + + if (!(polyline && prevCoordSys.type === coordSys.type && step === this._step)) { + showSymbol && symbolDraw.updateData(data, { + isIgnore: isIgnoreFunc, + clipShape: clipShapeForSymbol, + disableAnimation: true, + getSymbolPoint: function (idx) { + return [points[idx * 2], points[idx * 2 + 1]]; + } + }); + hasAnimation && this._initSymbolLabelAnimation(data, coordSys, clipShapeForSymbol); + + if (step) { + // TODO If stacked series is not step + points = turnPointsIntoStep(points, coordSys, step, connectNulls); + + if (stackedOnPoints) { + stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step, connectNulls); + } + } + + polyline = this._newPolyline(points); + + if (isAreaChart) { + polygon = this._newPolygon(points, stackedOnPoints); + } // NOTE: Must update _endLabel before setClipPath. + + + if (!isCoordSysPolar) { + this._initOrUpdateEndLabel(seriesModel, coordSys, convertToColorString(visualColor)); + } + + lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel)); + } else { + if (isAreaChart && !polygon) { + // If areaStyle is added + polygon = this._newPolygon(points, stackedOnPoints); + } else if (polygon && !isAreaChart) { + // If areaStyle is removed + lineGroup.remove(polygon); + polygon = this._polygon = null; + } // NOTE: Must update _endLabel before setClipPath. + + + if (!isCoordSysPolar) { + this._initOrUpdateEndLabel(seriesModel, coordSys, convertToColorString(visualColor)); + } // Update clipPath + + + var oldClipPath = lineGroup.getClipPath(); + + if (oldClipPath) { + var newClipPath = createLineClipPath(this, coordSys, false, seriesModel); + initProps(oldClipPath, { + shape: newClipPath.shape + }, seriesModel); + } else { + lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel)); + } // Always update, or it is wrong in the case turning on legend + // because points are not changed + + + showSymbol && symbolDraw.updateData(data, { + isIgnore: isIgnoreFunc, + clipShape: clipShapeForSymbol, + disableAnimation: true, + getSymbolPoint: function (idx) { + return [points[idx * 2], points[idx * 2 + 1]]; + } + }); // In the case data zoom triggerred refreshing frequently + // Data may not change if line has a category axis. So it should animate nothing + + if (!isPointsSame(this._stackedOnPoints, stackedOnPoints) || !isPointsSame(this._points, points)) { + if (hasAnimation) { + this._doUpdateAnimation(data, stackedOnPoints, coordSys, api, step, valueOrigin, connectNulls); + } else { + // Not do it in update with animation + if (step) { + // TODO If stacked series is not step + points = turnPointsIntoStep(points, coordSys, step, connectNulls); + + if (stackedOnPoints) { + stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step, connectNulls); + } + } + + polyline.setShape({ + points: points + }); + polygon && polygon.setShape({ + points: points, + stackedOnPoints: stackedOnPoints + }); + } + } + } + + var emphasisModel = seriesModel.getModel('emphasis'); + var focus = emphasisModel.get('focus'); + var blurScope = emphasisModel.get('blurScope'); + var emphasisDisabled = emphasisModel.get('disabled'); + polyline.useStyle(defaults( // Use color in lineStyle first + lineStyleModel.getLineStyle(), { + fill: 'none', + stroke: visualColor, + lineJoin: 'bevel' + })); + setStatesStylesFromModel(polyline, seriesModel, 'lineStyle'); + + if (polyline.style.lineWidth > 0 && seriesModel.get(['emphasis', 'lineStyle', 'width']) === 'bolder') { + var emphasisLineStyle = polyline.getState('emphasis').style; + emphasisLineStyle.lineWidth = +polyline.style.lineWidth + 1; + } // Needs seriesIndex for focus + + + getECData(polyline).seriesIndex = seriesModel.seriesIndex; + toggleHoverEmphasis(polyline, focus, blurScope, emphasisDisabled); + var smooth = getSmooth(seriesModel.get('smooth')); + var smoothMonotone = seriesModel.get('smoothMonotone'); + polyline.setShape({ + smooth: smooth, + smoothMonotone: smoothMonotone, + connectNulls: connectNulls + }); + + if (polygon) { + var stackedOnSeries = data.getCalculationInfo('stackedOnSeries'); + var stackedOnSmooth = 0; + polygon.useStyle(defaults(areaStyleModel.getAreaStyle(), { + fill: visualColor, + opacity: 0.7, + lineJoin: 'bevel', + decal: data.getVisual('style').decal + })); + + if (stackedOnSeries) { + stackedOnSmooth = getSmooth(stackedOnSeries.get('smooth')); + } + + polygon.setShape({ + smooth: smooth, + stackedOnSmooth: stackedOnSmooth, + smoothMonotone: smoothMonotone, + connectNulls: connectNulls + }); + setStatesStylesFromModel(polygon, seriesModel, 'areaStyle'); // Needs seriesIndex for focus + + getECData(polygon).seriesIndex = seriesModel.seriesIndex; + toggleHoverEmphasis(polygon, focus, blurScope, emphasisDisabled); + } + + var changePolyState = function (toState) { + _this._changePolyState(toState); + }; + + data.eachItemGraphicEl(function (el) { + // Switch polyline / polygon state if element changed its state. + el && (el.onHoverStateChange = changePolyState); + }); + this._polyline.onHoverStateChange = changePolyState; + this._data = data; // Save the coordinate system for transition animation when data changed + + this._coordSys = coordSys; + this._stackedOnPoints = stackedOnPoints; + this._points = points; + this._step = step; + this._valueOrigin = valueOrigin; + + if (seriesModel.get('triggerLineEvent')) { + this.packEventData(seriesModel, polyline); + polygon && this.packEventData(seriesModel, polygon); + } + }; + + LineView.prototype.packEventData = function (seriesModel, el) { + getECData(el).eventData = { + componentType: 'series', + componentSubType: 'line', + componentIndex: seriesModel.componentIndex, + seriesIndex: seriesModel.seriesIndex, + seriesName: seriesModel.name, + seriesType: 'line' + }; + }; + + LineView.prototype.highlight = function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + var dataIndex = queryDataIndex(data, payload); + + this._changePolyState('emphasis'); + + if (!(dataIndex instanceof Array) && dataIndex != null && dataIndex >= 0) { + var points = data.getLayout('points'); + var symbol = data.getItemGraphicEl(dataIndex); + + if (!symbol) { + // Create a temporary symbol if it is not exists + var x = points[dataIndex * 2]; + var y = points[dataIndex * 2 + 1]; + + if (isNaN(x) || isNaN(y)) { + // Null data + return; + } // fix #11360: should't draw symbol outside clipShapeForSymbol + + + if (this._clipShapeForSymbol && !this._clipShapeForSymbol.contain(x, y)) { + return; + } + + var zlevel = seriesModel.get('zlevel'); + var z = seriesModel.get('z'); + symbol = new Symbol(data, dataIndex); + symbol.x = x; + symbol.y = y; + symbol.setZ(zlevel, z); // ensure label text of the temporary symbol is in front of line and area polygon + + var symbolLabel = symbol.getSymbolPath().getTextContent(); + + if (symbolLabel) { + symbolLabel.zlevel = zlevel; + symbolLabel.z = z; + symbolLabel.z2 = this._polyline.z2 + 1; + } + + symbol.__temp = true; + data.setItemGraphicEl(dataIndex, symbol); // Stop scale animation + + symbol.stopSymbolAnimation(true); + this.group.add(symbol); + } + + symbol.highlight(); + } else { + // Highlight whole series + ChartView.prototype.highlight.call(this, seriesModel, ecModel, api, payload); + } + }; + + LineView.prototype.downplay = function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + var dataIndex = queryDataIndex(data, payload); + + this._changePolyState('normal'); + + if (dataIndex != null && dataIndex >= 0) { + var symbol = data.getItemGraphicEl(dataIndex); + + if (symbol) { + if (symbol.__temp) { + data.setItemGraphicEl(dataIndex, null); + this.group.remove(symbol); + } else { + symbol.downplay(); + } + } + } else { + // FIXME + // can not downplay completely. + // Downplay whole series + ChartView.prototype.downplay.call(this, seriesModel, ecModel, api, payload); + } + }; + + LineView.prototype._changePolyState = function (toState) { + var polygon = this._polygon; + setStatesFlag(this._polyline, toState); + polygon && setStatesFlag(polygon, toState); + }; + + LineView.prototype._newPolyline = function (points) { + var polyline = this._polyline; // Remove previous created polyline + + if (polyline) { + this._lineGroup.remove(polyline); + } + + polyline = new ECPolyline({ + shape: { + points: points + }, + segmentIgnoreThreshold: 2, + z2: 10 + }); + + this._lineGroup.add(polyline); + + this._polyline = polyline; + return polyline; + }; + + LineView.prototype._newPolygon = function (points, stackedOnPoints) { + var polygon = this._polygon; // Remove previous created polygon + + if (polygon) { + this._lineGroup.remove(polygon); + } + + polygon = new ECPolygon({ + shape: { + points: points, + stackedOnPoints: stackedOnPoints + }, + segmentIgnoreThreshold: 2 + }); + + this._lineGroup.add(polygon); + + this._polygon = polygon; + return polygon; + }; + + LineView.prototype._initSymbolLabelAnimation = function (data, coordSys, clipShape) { + var isHorizontalOrRadial; + var isCoordSysPolar; + var baseAxis = coordSys.getBaseAxis(); + var isAxisInverse = baseAxis.inverse; + + if (coordSys.type === 'cartesian2d') { + isHorizontalOrRadial = baseAxis.isHorizontal(); + isCoordSysPolar = false; + } else if (coordSys.type === 'polar') { + isHorizontalOrRadial = baseAxis.dim === 'angle'; + isCoordSysPolar = true; + } + + var seriesModel = data.hostModel; + var seriesDuration = seriesModel.get('animationDuration'); + + if (isFunction(seriesDuration)) { + seriesDuration = seriesDuration(null); + } + + var seriesDalay = seriesModel.get('animationDelay') || 0; + var seriesDalayValue = isFunction(seriesDalay) ? seriesDalay(null) : seriesDalay; + data.eachItemGraphicEl(function (symbol, idx) { + var el = symbol; + + if (el) { + var point = [symbol.x, symbol.y]; + var start = void 0; + var end = void 0; + var current = void 0; + + if (clipShape) { + if (isCoordSysPolar) { + var polarClip = clipShape; + var coord = coordSys.pointToCoord(point); + + if (isHorizontalOrRadial) { + start = polarClip.startAngle; + end = polarClip.endAngle; + current = -coord[1] / 180 * Math.PI; + } else { + start = polarClip.r0; + end = polarClip.r; + current = coord[0]; + } + } else { + var gridClip = clipShape; + + if (isHorizontalOrRadial) { + start = gridClip.x; + end = gridClip.x + gridClip.width; + current = symbol.x; + } else { + start = gridClip.y + gridClip.height; + end = gridClip.y; + current = symbol.y; + } + } + } + + var ratio = end === start ? 0 : (current - start) / (end - start); + + if (isAxisInverse) { + ratio = 1 - ratio; + } + + var delay = isFunction(seriesDalay) ? seriesDalay(idx) : seriesDuration * ratio + seriesDalayValue; + var symbolPath = el.getSymbolPath(); + var text = symbolPath.getTextContent(); + el.attr({ + scaleX: 0, + scaleY: 0 + }); + el.animateTo({ + scaleX: 1, + scaleY: 1 + }, { + duration: 200, + setToFinal: true, + delay: delay + }); + + if (text) { + text.animateFrom({ + style: { + opacity: 0 + } + }, { + duration: 300, + delay: delay + }); + } + + symbolPath.disableLabelAnimation = true; + } + }); + }; + + LineView.prototype._initOrUpdateEndLabel = function (seriesModel, coordSys, inheritColor) { + var endLabelModel = seriesModel.getModel('endLabel'); + + if (anyStateShowEndLabel(seriesModel)) { + var data_2 = seriesModel.getData(); + var polyline = this._polyline; // series may be filtered. + + var points = data_2.getLayout('points'); + + if (!points) { + polyline.removeTextContent(); + this._endLabel = null; + return; + } + + var endLabel = this._endLabel; + + if (!endLabel) { + endLabel = this._endLabel = new ZRText({ + z2: 200 // should be higher than item symbol + + }); + endLabel.ignoreClip = true; + polyline.setTextContent(this._endLabel); + polyline.disableLabelAnimation = true; + } // Find last non-NaN data to display data + + + var dataIndex = getLastIndexNotNull(points); + + if (dataIndex >= 0) { + setLabelStyle(polyline, getLabelStatesModels(seriesModel, 'endLabel'), { + inheritColor: inheritColor, + labelFetcher: seriesModel, + labelDataIndex: dataIndex, + defaultText: function (dataIndex, opt, interpolatedValue) { + return interpolatedValue != null ? getDefaultInterpolatedLabel(data_2, interpolatedValue) : getDefaultLabel(data_2, dataIndex); + }, + enableTextSetter: true + }, getEndLabelStateSpecified(endLabelModel, coordSys)); + polyline.textConfig.position = null; + } + } else if (this._endLabel) { + this._polyline.removeTextContent(); + + this._endLabel = null; + } + }; + + LineView.prototype._endLabelOnDuring = function (percent, clipRect, data, animationRecord, valueAnimation, endLabelModel, coordSys) { + var endLabel = this._endLabel; + var polyline = this._polyline; + + if (endLabel) { + // NOTE: Don't remove percent < 1. percent === 1 means the first frame during render. + // The label is not prepared at this time. + if (percent < 1 && animationRecord.originalX == null) { + animationRecord.originalX = endLabel.x; + animationRecord.originalY = endLabel.y; + } + + var points = data.getLayout('points'); + var seriesModel = data.hostModel; + var connectNulls = seriesModel.get('connectNulls'); + var precision = endLabelModel.get('precision'); + var distance = endLabelModel.get('distance') || 0; + var baseAxis = coordSys.getBaseAxis(); + var isHorizontal = baseAxis.isHorizontal(); + var isBaseInversed = baseAxis.inverse; + var clipShape = clipRect.shape; + var xOrY = isBaseInversed ? isHorizontal ? clipShape.x : clipShape.y + clipShape.height : isHorizontal ? clipShape.x + clipShape.width : clipShape.y; + var distanceX = (isHorizontal ? distance : 0) * (isBaseInversed ? -1 : 1); + var distanceY = (isHorizontal ? 0 : -distance) * (isBaseInversed ? -1 : 1); + var dim = isHorizontal ? 'x' : 'y'; + var dataIndexRange = getIndexRange(points, xOrY, dim); + var indices = dataIndexRange.range; + var diff = indices[1] - indices[0]; + var value = void 0; + + if (diff >= 1) { + // diff > 1 && connectNulls, which is on the null data. + if (diff > 1 && !connectNulls) { + var pt = getPointAtIndex(points, indices[0]); + endLabel.attr({ + x: pt[0] + distanceX, + y: pt[1] + distanceY + }); + valueAnimation && (value = seriesModel.getRawValue(indices[0])); + } else { + var pt = polyline.getPointOn(xOrY, dim); + pt && endLabel.attr({ + x: pt[0] + distanceX, + y: pt[1] + distanceY + }); + var startValue = seriesModel.getRawValue(indices[0]); + var endValue = seriesModel.getRawValue(indices[1]); + valueAnimation && (value = interpolateRawValues(data, precision, startValue, endValue, dataIndexRange.t)); + } + + animationRecord.lastFrameIndex = indices[0]; + } else { + // If diff <= 0, which is the range is not found(Include NaN) + // Choose the first point or last point. + var idx = percent === 1 || animationRecord.lastFrameIndex > 0 ? indices[0] : 0; + var pt = getPointAtIndex(points, idx); + valueAnimation && (value = seriesModel.getRawValue(idx)); + endLabel.attr({ + x: pt[0] + distanceX, + y: pt[1] + distanceY + }); + } + + if (valueAnimation) { + labelInner(endLabel).setLabelText(value); + } + } + }; + /** + * @private + */ + // FIXME Two value axis + + + LineView.prototype._doUpdateAnimation = function (data, stackedOnPoints, coordSys, api, step, valueOrigin, connectNulls) { + var polyline = this._polyline; + var polygon = this._polygon; + var seriesModel = data.hostModel; + var diff = lineAnimationDiff(this._data, data, this._stackedOnPoints, stackedOnPoints, this._coordSys, coordSys, this._valueOrigin); + var current = diff.current; + var stackedOnCurrent = diff.stackedOnCurrent; + var next = diff.next; + var stackedOnNext = diff.stackedOnNext; + + if (step) { + // TODO If stacked series is not step + current = turnPointsIntoStep(diff.current, coordSys, step, connectNulls); + stackedOnCurrent = turnPointsIntoStep(diff.stackedOnCurrent, coordSys, step, connectNulls); + next = turnPointsIntoStep(diff.next, coordSys, step, connectNulls); + stackedOnNext = turnPointsIntoStep(diff.stackedOnNext, coordSys, step, connectNulls); + } // Don't apply animation if diff is large. + // For better result and avoid memory explosion problems like + // https://github.com/apache/incubator-echarts/issues/12229 + + + if (getBoundingDiff(current, next) > 3000 || polygon && getBoundingDiff(stackedOnCurrent, stackedOnNext) > 3000) { + polyline.stopAnimation(); + polyline.setShape({ + points: next + }); + + if (polygon) { + polygon.stopAnimation(); + polygon.setShape({ + points: next, + stackedOnPoints: stackedOnNext + }); + } + + return; + } + + polyline.shape.__points = diff.current; + polyline.shape.points = current; + var target = { + shape: { + points: next + } + }; // Also animate the original points. + // If points reference is changed when turning into step line. + + if (diff.current !== current) { + target.shape.__points = diff.next; + } // Stop previous animation. + + + polyline.stopAnimation(); + updateProps(polyline, target, seriesModel); + + if (polygon) { + polygon.setShape({ + // Reuse the points with polyline. + points: current, + stackedOnPoints: stackedOnCurrent + }); + polygon.stopAnimation(); + updateProps(polygon, { + shape: { + stackedOnPoints: stackedOnNext + } + }, seriesModel); // If use attr directly in updateProps. + + if (polyline.shape.points !== polygon.shape.points) { + polygon.shape.points = polyline.shape.points; + } + } + + var updatedDataInfo = []; + var diffStatus = diff.status; + + for (var i = 0; i < diffStatus.length; i++) { + var cmd = diffStatus[i].cmd; + + if (cmd === '=') { + var el = data.getItemGraphicEl(diffStatus[i].idx1); + + if (el) { + updatedDataInfo.push({ + el: el, + ptIdx: i // Index of points + + }); + } + } + } + + if (polyline.animators && polyline.animators.length) { + polyline.animators[0].during(function () { + polygon && polygon.dirtyShape(); + var points = polyline.shape.__points; + + for (var i = 0; i < updatedDataInfo.length; i++) { + var el = updatedDataInfo[i].el; + var offset = updatedDataInfo[i].ptIdx * 2; + el.x = points[offset]; + el.y = points[offset + 1]; + el.markRedraw(); + } + }); + } + }; + + LineView.prototype.remove = function (ecModel) { + var group = this.group; + var oldData = this._data; + + this._lineGroup.removeAll(); + + this._symbolDraw.remove(true); // Remove temporary created elements when highlighting + + + oldData && oldData.eachItemGraphicEl(function (el, idx) { + if (el.__temp) { + group.remove(el); + oldData.setItemGraphicEl(idx, null); + } + }); + this._polyline = this._polygon = this._coordSys = this._points = this._stackedOnPoints = this._endLabel = this._data = null; + }; + + LineView.type = 'line'; + return LineView; + }(ChartView); + + function pointsLayout(seriesType, forceStoreInTypedArray) { + return { + seriesType: seriesType, + plan: createRenderPlanner(), + reset: function (seriesModel) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + var pipelineContext = seriesModel.pipelineContext; + var useTypedArray = forceStoreInTypedArray || pipelineContext.large; + + if (!coordSys) { + return; + } + + var dims = map(coordSys.dimensions, function (dim) { + return data.mapDimension(dim); + }).slice(0, 2); + var dimLen = dims.length; + var stackResultDim = data.getCalculationInfo('stackResultDimension'); + + if (isDimensionStacked(data, dims[0])) { + dims[0] = stackResultDim; + } + + if (isDimensionStacked(data, dims[1])) { + dims[1] = stackResultDim; + } + + var store = data.getStore(); + var dimIdx0 = data.getDimensionIndex(dims[0]); + var dimIdx1 = data.getDimensionIndex(dims[1]); + return dimLen && { + progress: function (params, data) { + var segCount = params.end - params.start; + var points = useTypedArray && createFloat32Array(segCount * dimLen); + var tmpIn = []; + var tmpOut = []; + + for (var i = params.start, offset = 0; i < params.end; i++) { + var point = void 0; + + if (dimLen === 1) { + var x = store.get(dimIdx0, i); // NOTE: Make sure the second parameter is null to use default strategy. + + point = coordSys.dataToPoint(x, null, tmpOut); + } else { + tmpIn[0] = store.get(dimIdx0, i); + tmpIn[1] = store.get(dimIdx1, i); // Let coordinate system to handle the NaN data. + + point = coordSys.dataToPoint(tmpIn, null, tmpOut); + } + + if (useTypedArray) { + points[offset++] = point[0]; + points[offset++] = point[1]; + } else { + data.setItemLayout(i, point.slice()); + } + } + + useTypedArray && data.setLayout('points', points); + } + }; + } + }; + } + + var samplers = { + average: function (frame) { + var sum = 0; + var count = 0; + + for (var i = 0; i < frame.length; i++) { + if (!isNaN(frame[i])) { + sum += frame[i]; + count++; + } + } // Return NaN if count is 0 + + + return count === 0 ? NaN : sum / count; + }, + sum: function (frame) { + var sum = 0; + + for (var i = 0; i < frame.length; i++) { + // Ignore NaN + sum += frame[i] || 0; + } + + return sum; + }, + max: function (frame) { + var max = -Infinity; + + for (var i = 0; i < frame.length; i++) { + frame[i] > max && (max = frame[i]); + } // NaN will cause illegal axis extent. + + + return isFinite(max) ? max : NaN; + }, + min: function (frame) { + var min = Infinity; + + for (var i = 0; i < frame.length; i++) { + frame[i] < min && (min = frame[i]); + } // NaN will cause illegal axis extent. + + + return isFinite(min) ? min : NaN; + }, + // TODO + // Median + nearest: function (frame) { + return frame[0]; + } + }; + + var indexSampler = function (frame) { + return Math.round(frame.length / 2); + }; + + function dataSample(seriesType) { + return { + seriesType: seriesType, + // FIXME:TS never used, so comment it + // modifyOutputEnd: true, + reset: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var sampling = seriesModel.get('sampling'); + var coordSys = seriesModel.coordinateSystem; + var count = data.count(); // Only cartesian2d support down sampling. Disable it when there is few data. + + if (count > 10 && coordSys.type === 'cartesian2d' && sampling) { + var baseAxis = coordSys.getBaseAxis(); + var valueAxis = coordSys.getOtherAxis(baseAxis); + var extent = baseAxis.getExtent(); + var dpr = api.getDevicePixelRatio(); // Coordinste system has been resized + + var size = Math.abs(extent[1] - extent[0]) * (dpr || 1); + var rate = Math.round(count / size); + + if (isFinite(rate) && rate > 1) { + if (sampling === 'lttb') { + seriesModel.setData(data.lttbDownSample(data.mapDimension(valueAxis.dim), 1 / rate)); + } + + var sampler = void 0; + + if (isString(sampling)) { + sampler = samplers[sampling]; + } else if (isFunction(sampling)) { + sampler = sampling; + } + + if (sampler) { + // Only support sample the first dim mapped from value axis. + seriesModel.setData(data.downSample(data.mapDimension(valueAxis.dim), 1 / rate, sampler, indexSampler)); + } + } + } + } + }; + } + + function install$2(registers) { + registers.registerChartView(LineView); + registers.registerSeriesModel(LineSeriesModel); + registers.registerLayout(pointsLayout('line', true)); + registers.registerVisual({ + seriesType: 'line', + reset: function (seriesModel) { + var data = seriesModel.getData(); // Visual coding for legend + + var lineStyle = seriesModel.getModel('lineStyle').getLineStyle(); + + if (lineStyle && !lineStyle.stroke) { + // Fill in visual should be palette color if + // has color callback + lineStyle.stroke = data.getVisual('style').fill; + } + + data.setVisual('legendLineStyle', lineStyle); + } + }); // Down sample after filter + + registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, dataSample('line')); + } + + var BaseBarSeriesModel = + /** @class */ + function (_super) { + __extends(BaseBarSeriesModel, _super); + + function BaseBarSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = BaseBarSeriesModel.type; + return _this; + } + + BaseBarSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createSeriesData(null, this, { + useEncodeDefaulter: true + }); + }; + + BaseBarSeriesModel.prototype.getMarkerPosition = function (value) { + var coordSys = this.coordinateSystem; + + if (coordSys && coordSys.clampData) { + // PENDING if clamp ? + var pt = coordSys.dataToPoint(coordSys.clampData(value)); + var data = this.getData(); + var offset = data.getLayout('offset'); + var size = data.getLayout('size'); + var offsetIndex = coordSys.getBaseAxis().isHorizontal() ? 0 : 1; + pt[offsetIndex] += offset + size / 2; + return pt; + } + + return [NaN, NaN]; + }; + + BaseBarSeriesModel.type = 'series.__base_bar__'; + BaseBarSeriesModel.defaultOption = { + // zlevel: 0, + z: 2, + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + // stack: null + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + barMinHeight: 0, + barMinAngle: 0, + // cursor: null, + large: false, + largeThreshold: 400, + progressive: 3e3, + progressiveChunkMode: 'mod' + }; + return BaseBarSeriesModel; + }(SeriesModel); + + SeriesModel.registerClass(BaseBarSeriesModel); + + var BarSeriesModel = + /** @class */ + function (_super) { + __extends(BarSeriesModel, _super); + + function BarSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = BarSeriesModel.type; + return _this; + } + + BarSeriesModel.prototype.getInitialData = function () { + return createSeriesData(null, this, { + useEncodeDefaulter: true, + createInvertedIndices: !!this.get('realtimeSort', true) || null + }); + }; + /** + * @override + */ + + + BarSeriesModel.prototype.getProgressive = function () { + // Do not support progressive in normal mode. + return this.get('large') ? this.get('progressive') : false; + }; + /** + * @override + */ + + + BarSeriesModel.prototype.getProgressiveThreshold = function () { + // Do not support progressive in normal mode. + var progressiveThreshold = this.get('progressiveThreshold'); + var largeThreshold = this.get('largeThreshold'); + + if (largeThreshold > progressiveThreshold) { + progressiveThreshold = largeThreshold; + } + + return progressiveThreshold; + }; + + BarSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) { + return selectors.rect(data.getItemLayout(dataIndex)); + }; + + BarSeriesModel.type = 'series.bar'; + BarSeriesModel.dependencies = ['grid', 'polar']; + BarSeriesModel.defaultOption = inheritDefaultOption(BaseBarSeriesModel.defaultOption, { + // If clipped + // Only available on cartesian2d + clip: true, + roundCap: false, + showBackground: false, + backgroundStyle: { + color: 'rgba(180, 180, 180, 0.2)', + borderColor: null, + borderWidth: 0, + borderType: 'solid', + borderRadius: 0, + shadowBlur: 0, + shadowColor: null, + shadowOffsetX: 0, + shadowOffsetY: 0, + opacity: 1 + }, + select: { + itemStyle: { + borderColor: '#212121' + } + }, + realtimeSort: false + }); + return BarSeriesModel; + }(BaseBarSeriesModel); + + /** + * Sausage: similar to sector, but have half circle on both sides + */ + + var SausageShape = + /** @class */ + function () { + function SausageShape() { + this.cx = 0; + this.cy = 0; + this.r0 = 0; + this.r = 0; + this.startAngle = 0; + this.endAngle = Math.PI * 2; + this.clockwise = true; + } + + return SausageShape; + }(); + + var SausagePath = + /** @class */ + function (_super) { + __extends(SausagePath, _super); + + function SausagePath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'sausage'; + return _this; + } + + SausagePath.prototype.getDefaultShape = function () { + return new SausageShape(); + }; + + SausagePath.prototype.buildPath = function (ctx, shape) { + var cx = shape.cx; + var cy = shape.cy; + var r0 = Math.max(shape.r0 || 0, 0); + var r = Math.max(shape.r, 0); + var dr = (r - r0) * 0.5; + var rCenter = r0 + dr; + var startAngle = shape.startAngle; + var endAngle = shape.endAngle; + var clockwise = shape.clockwise; + var PI2 = Math.PI * 2; + var lessThanCircle = clockwise ? endAngle - startAngle < PI2 : startAngle - endAngle < PI2; + + if (!lessThanCircle) { + // Normalize angles + startAngle = endAngle - (clockwise ? PI2 : -PI2); + } + + var unitStartX = Math.cos(startAngle); + var unitStartY = Math.sin(startAngle); + var unitEndX = Math.cos(endAngle); + var unitEndY = Math.sin(endAngle); + + if (lessThanCircle) { + ctx.moveTo(unitStartX * r0 + cx, unitStartY * r0 + cy); + ctx.arc(unitStartX * rCenter + cx, unitStartY * rCenter + cy, dr, -Math.PI + startAngle, startAngle, !clockwise); + } else { + ctx.moveTo(unitStartX * r + cx, unitStartY * r + cy); + } + + ctx.arc(cx, cy, r, startAngle, endAngle, !clockwise); + ctx.arc(unitEndX * rCenter + cx, unitEndY * rCenter + cy, dr, endAngle - Math.PI * 2, endAngle - Math.PI, !clockwise); + + if (r0 !== 0) { + ctx.arc(cx, cy, r0, endAngle, startAngle, clockwise); + } // ctx.closePath(); + + }; + + return SausagePath; + }(Path); + + function createSectorCalculateTextPosition(positionMapping, opts) { + opts = opts || {}; + var isRoundCap = opts.isRoundCap; + return function (out, opts, boundingRect) { + var textPosition = opts.position; + + if (!textPosition || textPosition instanceof Array) { + return calculateTextPosition(out, opts, boundingRect); + } + + var mappedSectorPosition = positionMapping(textPosition); + var distance = opts.distance != null ? opts.distance : 5; + var sector = this.shape; + var cx = sector.cx; + var cy = sector.cy; + var r = sector.r; + var r0 = sector.r0; + var middleR = (r + r0) / 2; + var startAngle = sector.startAngle; + var endAngle = sector.endAngle; + var middleAngle = (startAngle + endAngle) / 2; + var extraDist = isRoundCap ? Math.abs(r - r0) / 2 : 0; + var mathCos = Math.cos; + var mathSin = Math.sin; // base position: top-left + + var x = cx + r * mathCos(startAngle); + var y = cy + r * mathSin(startAngle); + var textAlign = 'left'; + var textVerticalAlign = 'top'; + + switch (mappedSectorPosition) { + case 'startArc': + x = cx + (r0 - distance) * mathCos(middleAngle); + y = cy + (r0 - distance) * mathSin(middleAngle); + textAlign = 'center'; + textVerticalAlign = 'top'; + break; + + case 'insideStartArc': + x = cx + (r0 + distance) * mathCos(middleAngle); + y = cy + (r0 + distance) * mathSin(middleAngle); + textAlign = 'center'; + textVerticalAlign = 'bottom'; + break; + + case 'startAngle': + x = cx + middleR * mathCos(startAngle) + adjustAngleDistanceX(startAngle, distance + extraDist, false); + y = cy + middleR * mathSin(startAngle) + adjustAngleDistanceY(startAngle, distance + extraDist, false); + textAlign = 'right'; + textVerticalAlign = 'middle'; + break; + + case 'insideStartAngle': + x = cx + middleR * mathCos(startAngle) + adjustAngleDistanceX(startAngle, -distance + extraDist, false); + y = cy + middleR * mathSin(startAngle) + adjustAngleDistanceY(startAngle, -distance + extraDist, false); + textAlign = 'left'; + textVerticalAlign = 'middle'; + break; + + case 'middle': + x = cx + middleR * mathCos(middleAngle); + y = cy + middleR * mathSin(middleAngle); + textAlign = 'center'; + textVerticalAlign = 'middle'; + break; + + case 'endArc': + x = cx + (r + distance) * mathCos(middleAngle); + y = cy + (r + distance) * mathSin(middleAngle); + textAlign = 'center'; + textVerticalAlign = 'bottom'; + break; + + case 'insideEndArc': + x = cx + (r - distance) * mathCos(middleAngle); + y = cy + (r - distance) * mathSin(middleAngle); + textAlign = 'center'; + textVerticalAlign = 'top'; + break; + + case 'endAngle': + x = cx + middleR * mathCos(endAngle) + adjustAngleDistanceX(endAngle, distance + extraDist, true); + y = cy + middleR * mathSin(endAngle) + adjustAngleDistanceY(endAngle, distance + extraDist, true); + textAlign = 'left'; + textVerticalAlign = 'middle'; + break; + + case 'insideEndAngle': + x = cx + middleR * mathCos(endAngle) + adjustAngleDistanceX(endAngle, -distance + extraDist, true); + y = cy + middleR * mathSin(endAngle) + adjustAngleDistanceY(endAngle, -distance + extraDist, true); + textAlign = 'right'; + textVerticalAlign = 'middle'; + break; + + default: + return calculateTextPosition(out, opts, boundingRect); + } + + out = out || {}; + out.x = x; + out.y = y; + out.align = textAlign; + out.verticalAlign = textVerticalAlign; + return out; + }; + } + function setSectorTextRotation(sector, textPosition, positionMapping, rotateType) { + if (isNumber(rotateType)) { + // user-set rotation + sector.setTextConfig({ + rotation: rotateType + }); + return; + } else if (isArray(textPosition)) { + // user-set position, use 0 as auto rotation + sector.setTextConfig({ + rotation: 0 + }); + return; + } + + var shape = sector.shape; + var startAngle = shape.clockwise ? shape.startAngle : shape.endAngle; + var endAngle = shape.clockwise ? shape.endAngle : shape.startAngle; + var middleAngle = (startAngle + endAngle) / 2; + var anchorAngle; + var mappedSectorPosition = positionMapping(textPosition); + + switch (mappedSectorPosition) { + case 'startArc': + case 'insideStartArc': + case 'middle': + case 'insideEndArc': + case 'endArc': + anchorAngle = middleAngle; + break; + + case 'startAngle': + case 'insideStartAngle': + anchorAngle = startAngle; + break; + + case 'endAngle': + case 'insideEndAngle': + anchorAngle = endAngle; + break; + + default: + sector.setTextConfig({ + rotation: 0 + }); + return; + } + + var rotate = Math.PI * 1.5 - anchorAngle; + /** + * TODO: labels with rotate > Math.PI / 2 should be rotate another + * half round flipped to increase readability. However, only middle + * position supports this for now, because in other positions, the + * anchor point is not at the center of the text, so the positions + * after rotating is not as expected. + */ + + if (mappedSectorPosition === 'middle' && rotate > Math.PI / 2 && rotate < Math.PI * 1.5) { + rotate -= Math.PI; + } + + sector.setTextConfig({ + rotation: rotate + }); + } + + function adjustAngleDistanceX(angle, distance, isEnd) { + return distance * Math.sin(angle) * (isEnd ? -1 : 1); + } + + function adjustAngleDistanceY(angle, distance, isEnd) { + return distance * Math.cos(angle) * (isEnd ? 1 : -1); + } + + var mathMax$6 = Math.max; + var mathMin$6 = Math.min; + + function getClipArea(coord, data) { + var coordSysClipArea = coord.getArea && coord.getArea(); + + if (isCoordinateSystemType(coord, 'cartesian2d')) { + var baseAxis = coord.getBaseAxis(); // When boundaryGap is false or using time axis. bar may exceed the grid. + // We should not clip this part. + // See test/bar2.html + + if (baseAxis.type !== 'category' || !baseAxis.onBand) { + var expandWidth = data.getLayout('bandWidth'); + + if (baseAxis.isHorizontal()) { + coordSysClipArea.x -= expandWidth; + coordSysClipArea.width += expandWidth * 2; + } else { + coordSysClipArea.y -= expandWidth; + coordSysClipArea.height += expandWidth * 2; + } + } + } + + return coordSysClipArea; + } + + var BarView = + /** @class */ + function (_super) { + __extends(BarView, _super); + + function BarView() { + var _this = _super.call(this) || this; + + _this.type = BarView.type; + _this._isFirstFrame = true; + return _this; + } + + BarView.prototype.render = function (seriesModel, ecModel, api, payload) { + this._model = seriesModel; + + this._removeOnRenderedListener(api); + + this._updateDrawMode(seriesModel); + + var coordinateSystemType = seriesModel.get('coordinateSystem'); + + if (coordinateSystemType === 'cartesian2d' || coordinateSystemType === 'polar') { + // Clear previously rendered progressive elements. + this._progressiveEls = null; + this._isLargeDraw ? this._renderLarge(seriesModel, ecModel, api) : this._renderNormal(seriesModel, ecModel, api, payload); + } else if ("development" !== 'production') { + warn('Only cartesian2d and polar supported for bar.'); + } + }; + + BarView.prototype.incrementalPrepareRender = function (seriesModel) { + this._clear(); + + this._updateDrawMode(seriesModel); // incremental also need to clip, otherwise might be overlow. + // But must not set clip in each frame, otherwise all of the children will be marked redraw. + + + this._updateLargeClip(seriesModel); + }; + + BarView.prototype.incrementalRender = function (params, seriesModel) { + // Reset + this._progressiveEls = []; // Do not support progressive in normal mode. + + this._incrementalRenderLarge(params, seriesModel); + }; + + BarView.prototype.eachRendered = function (cb) { + traverseElements(this._progressiveEls || this.group, cb); + }; + + BarView.prototype._updateDrawMode = function (seriesModel) { + var isLargeDraw = seriesModel.pipelineContext.large; + + if (this._isLargeDraw == null || isLargeDraw !== this._isLargeDraw) { + this._isLargeDraw = isLargeDraw; + + this._clear(); + } + }; + + BarView.prototype._renderNormal = function (seriesModel, ecModel, api, payload) { + var group = this.group; + var data = seriesModel.getData(); + var oldData = this._data; + var coord = seriesModel.coordinateSystem; + var baseAxis = coord.getBaseAxis(); + var isHorizontalOrRadial; + + if (coord.type === 'cartesian2d') { + isHorizontalOrRadial = baseAxis.isHorizontal(); + } else if (coord.type === 'polar') { + isHorizontalOrRadial = baseAxis.dim === 'angle'; + } + + var animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null; + var realtimeSortCfg = shouldRealtimeSort(seriesModel, coord); + + if (realtimeSortCfg) { + this._enableRealtimeSort(realtimeSortCfg, data, api); + } + + var needsClip = seriesModel.get('clip', true) || realtimeSortCfg; + var coordSysClipArea = getClipArea(coord, data); // If there is clipPath created in large mode. Remove it. + + group.removeClipPath(); // We don't use clipPath in normal mode because we needs a perfect animation + // And don't want the label are clipped. + + var roundCap = seriesModel.get('roundCap', true); + var drawBackground = seriesModel.get('showBackground', true); + var backgroundModel = seriesModel.getModel('backgroundStyle'); + var barBorderRadius = backgroundModel.get('borderRadius') || 0; + var bgEls = []; + var oldBgEls = this._backgroundEls; + var isInitSort = payload && payload.isInitSort; + var isChangeOrder = payload && payload.type === 'changeAxisOrder'; + + function createBackground(dataIndex) { + var bgLayout = getLayout[coord.type](data, dataIndex); + var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout); + bgEl.useStyle(backgroundModel.getItemStyle()); // Only cartesian2d support borderRadius. + + if (coord.type === 'cartesian2d') { + bgEl.setShape('r', barBorderRadius); + } + + bgEls[dataIndex] = bgEl; + return bgEl; + } + data.diff(oldData).add(function (dataIndex) { + var itemModel = data.getItemModel(dataIndex); + var layout = getLayout[coord.type](data, dataIndex, itemModel); + + if (drawBackground) { + createBackground(dataIndex); + } // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy". + + + if (!data.hasValue(dataIndex) || !isValidLayout[coord.type](layout)) { + return; + } + + var isClipped = false; + + if (needsClip) { + // Clip will modify the layout params. + // And return a boolean to determine if the shape are fully clipped. + isClipped = clip[coord.type](coordSysClipArea, layout); + } + + var el = elementCreator[coord.type](seriesModel, data, dataIndex, layout, isHorizontalOrRadial, animationModel, baseAxis.model, false, roundCap); + + if (realtimeSortCfg) { + /** + * Force label animation because even if the element is + * ignored because it's clipped, it may not be clipped after + * changing order. Then, if not using forceLabelAnimation, + * the label animation was never started, in which case, + * the label will be the final value and doesn't have label + * animation. + */ + el.forceLabelAnimation = true; + } + + updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar'); + + if (isInitSort) { + el.attr({ + shape: layout + }); + } else if (realtimeSortCfg) { + updateRealtimeAnimation(realtimeSortCfg, animationModel, el, layout, dataIndex, isHorizontalOrRadial, false, false); + } else { + initProps(el, { + shape: layout + }, seriesModel, dataIndex); + } + + data.setItemGraphicEl(dataIndex, el); + group.add(el); + el.ignore = isClipped; + }).update(function (newIndex, oldIndex) { + var itemModel = data.getItemModel(newIndex); + var layout = getLayout[coord.type](data, newIndex, itemModel); + + if (drawBackground) { + var bgEl = void 0; + + if (oldBgEls.length === 0) { + bgEl = createBackground(oldIndex); + } else { + bgEl = oldBgEls[oldIndex]; + bgEl.useStyle(backgroundModel.getItemStyle()); // Only cartesian2d support borderRadius. + + if (coord.type === 'cartesian2d') { + bgEl.setShape('r', barBorderRadius); + } + + bgEls[newIndex] = bgEl; + } + + var bgLayout = getLayout[coord.type](data, newIndex); + var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord); + updateProps(bgEl, { + shape: shape + }, animationModel, newIndex); + } + + var el = oldData.getItemGraphicEl(oldIndex); + + if (!data.hasValue(newIndex) || !isValidLayout[coord.type](layout)) { + group.remove(el); + return; + } + + var isClipped = false; + + if (needsClip) { + isClipped = clip[coord.type](coordSysClipArea, layout); + + if (isClipped) { + group.remove(el); + } + } + + if (!el) { + el = elementCreator[coord.type](seriesModel, data, newIndex, layout, isHorizontalOrRadial, animationModel, baseAxis.model, !!el, roundCap); + } else { + saveOldStyle(el); + } + + if (realtimeSortCfg) { + el.forceLabelAnimation = true; + } + + if (isChangeOrder) { + var textEl = el.getTextContent(); + + if (textEl) { + var labelInnerStore = labelInner(textEl); + + if (labelInnerStore.prevValue != null) { + /** + * Set preValue to be value so that no new label + * should be started, otherwise, it will take a full + * `animationDurationUpdate` time to finish the + * animation, which is not expected. + */ + labelInnerStore.prevValue = labelInnerStore.value; + } + } + } // Not change anything if only order changed. + // Especially not change label. + else { + updateStyle(el, data, newIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar'); + } + + if (isInitSort) { + el.attr({ + shape: layout + }); + } else if (realtimeSortCfg) { + updateRealtimeAnimation(realtimeSortCfg, animationModel, el, layout, newIndex, isHorizontalOrRadial, true, isChangeOrder); + } else { + updateProps(el, { + shape: layout + }, seriesModel, newIndex, null); + } + + data.setItemGraphicEl(newIndex, el); + el.ignore = isClipped; + group.add(el); + }).remove(function (dataIndex) { + var el = oldData.getItemGraphicEl(dataIndex); + el && removeElementWithFadeOut(el, seriesModel, dataIndex); + }).execute(); + var bgGroup = this._backgroundGroup || (this._backgroundGroup = new Group()); + bgGroup.removeAll(); + + for (var i = 0; i < bgEls.length; ++i) { + bgGroup.add(bgEls[i]); + } + + group.add(bgGroup); + this._backgroundEls = bgEls; + this._data = data; + }; + + BarView.prototype._renderLarge = function (seriesModel, ecModel, api) { + this._clear(); + + createLarge(seriesModel, this.group); + + this._updateLargeClip(seriesModel); + }; + + BarView.prototype._incrementalRenderLarge = function (params, seriesModel) { + this._removeBackground(); + + createLarge(seriesModel, this.group, this._progressiveEls, true); + }; + + BarView.prototype._updateLargeClip = function (seriesModel) { + // Use clipPath in large mode. + var clipPath = seriesModel.get('clip', true) && createClipPath(seriesModel.coordinateSystem, false, seriesModel); + var group = this.group; + + if (clipPath) { + group.setClipPath(clipPath); + } else { + group.removeClipPath(); + } + }; + + BarView.prototype._enableRealtimeSort = function (realtimeSortCfg, data, api) { + var _this = this; // If no data in the first frame, wait for data to initSort + + + if (!data.count()) { + return; + } + + var baseAxis = realtimeSortCfg.baseAxis; + + if (this._isFirstFrame) { + this._dispatchInitSort(data, realtimeSortCfg, api); + + this._isFirstFrame = false; + } else { + var orderMapping_1 = function (idx) { + var el = data.getItemGraphicEl(idx); + var shape = el && el.shape; + return shape && // The result should be consistent with the initial sort by data value. + // Do not support the case that both positive and negative exist. + Math.abs(baseAxis.isHorizontal() ? shape.height : shape.width) // If data is NaN, shape.xxx may be NaN, so use || 0 here in case + || 0; + }; + + this._onRendered = function () { + _this._updateSortWithinSameData(data, orderMapping_1, baseAxis, api); + }; + + api.getZr().on('rendered', this._onRendered); + } + }; + + BarView.prototype._dataSort = function (data, baseAxis, orderMapping) { + var info = []; + data.each(data.mapDimension(baseAxis.dim), function (ordinalNumber, dataIdx) { + var mappedValue = orderMapping(dataIdx); + mappedValue = mappedValue == null ? NaN : mappedValue; + info.push({ + dataIndex: dataIdx, + mappedValue: mappedValue, + ordinalNumber: ordinalNumber + }); + }); + info.sort(function (a, b) { + // If NaN, it will be treated as min val. + return b.mappedValue - a.mappedValue; + }); + return { + ordinalNumbers: map(info, function (item) { + return item.ordinalNumber; + }) + }; + }; + + BarView.prototype._isOrderChangedWithinSameData = function (data, orderMapping, baseAxis) { + var scale = baseAxis.scale; + var ordinalDataDim = data.mapDimension(baseAxis.dim); + var lastValue = Number.MAX_VALUE; + + for (var tickNum = 0, len = scale.getOrdinalMeta().categories.length; tickNum < len; ++tickNum) { + var rawIdx = data.rawIndexOf(ordinalDataDim, scale.getRawOrdinalNumber(tickNum)); + var value = rawIdx < 0 // If some tick have no bar, the tick will be treated as min. + ? Number.MIN_VALUE // PENDING: if dataZoom on baseAxis exits, is it a performance issue? + : orderMapping(data.indexOfRawIndex(rawIdx)); + + if (value > lastValue) { + return true; + } + + lastValue = value; + } + + return false; + }; + /* + * Consider the case when A and B changed order, whose representing + * bars are both out of sight, we don't wish to trigger reorder action + * as long as the order in the view doesn't change. + */ + + + BarView.prototype._isOrderDifferentInView = function (orderInfo, baseAxis) { + var scale = baseAxis.scale; + var extent = scale.getExtent(); + var tickNum = Math.max(0, extent[0]); + var tickMax = Math.min(extent[1], scale.getOrdinalMeta().categories.length - 1); + + for (; tickNum <= tickMax; ++tickNum) { + if (orderInfo.ordinalNumbers[tickNum] !== scale.getRawOrdinalNumber(tickNum)) { + return true; + } + } + }; + + BarView.prototype._updateSortWithinSameData = function (data, orderMapping, baseAxis, api) { + if (!this._isOrderChangedWithinSameData(data, orderMapping, baseAxis)) { + return; + } + + var sortInfo = this._dataSort(data, baseAxis, orderMapping); + + if (this._isOrderDifferentInView(sortInfo, baseAxis)) { + this._removeOnRenderedListener(api); + + api.dispatchAction({ + type: 'changeAxisOrder', + componentType: baseAxis.dim + 'Axis', + axisId: baseAxis.index, + sortInfo: sortInfo + }); + } + }; + + BarView.prototype._dispatchInitSort = function (data, realtimeSortCfg, api) { + var baseAxis = realtimeSortCfg.baseAxis; + + var sortResult = this._dataSort(data, baseAxis, function (dataIdx) { + return data.get(data.mapDimension(realtimeSortCfg.otherAxis.dim), dataIdx); + }); + + api.dispatchAction({ + type: 'changeAxisOrder', + componentType: baseAxis.dim + 'Axis', + isInitSort: true, + axisId: baseAxis.index, + sortInfo: sortResult + }); + }; + + BarView.prototype.remove = function (ecModel, api) { + this._clear(this._model); + + this._removeOnRenderedListener(api); + }; + + BarView.prototype.dispose = function (ecModel, api) { + this._removeOnRenderedListener(api); + }; + + BarView.prototype._removeOnRenderedListener = function (api) { + if (this._onRendered) { + api.getZr().off('rendered', this._onRendered); + this._onRendered = null; + } + }; + + BarView.prototype._clear = function (model) { + var group = this.group; + var data = this._data; + + if (model && model.isAnimationEnabled() && data && !this._isLargeDraw) { + this._removeBackground(); + + this._backgroundEls = []; + data.eachItemGraphicEl(function (el) { + removeElementWithFadeOut(el, model, getECData(el).dataIndex); + }); + } else { + group.removeAll(); + } + + this._data = null; + this._isFirstFrame = true; + }; + + BarView.prototype._removeBackground = function () { + this.group.remove(this._backgroundGroup); + this._backgroundGroup = null; + }; + + BarView.type = 'bar'; + return BarView; + }(ChartView); + + var clip = { + cartesian2d: function (coordSysBoundingRect, layout) { + var signWidth = layout.width < 0 ? -1 : 1; + var signHeight = layout.height < 0 ? -1 : 1; // Needs positive width and height + + if (signWidth < 0) { + layout.x += layout.width; + layout.width = -layout.width; + } + + if (signHeight < 0) { + layout.y += layout.height; + layout.height = -layout.height; + } + + var coordSysX2 = coordSysBoundingRect.x + coordSysBoundingRect.width; + var coordSysY2 = coordSysBoundingRect.y + coordSysBoundingRect.height; + var x = mathMax$6(layout.x, coordSysBoundingRect.x); + var x2 = mathMin$6(layout.x + layout.width, coordSysX2); + var y = mathMax$6(layout.y, coordSysBoundingRect.y); + var y2 = mathMin$6(layout.y + layout.height, coordSysY2); + var xClipped = x2 < x; + var yClipped = y2 < y; // When xClipped or yClipped, the element will be marked as `ignore`. + // But we should also place the element at the edge of the coord sys bounding rect. + // Beause if data changed and the bar show again, its transition animaiton + // will begin at this place. + + layout.x = xClipped && x > coordSysX2 ? x2 : x; + layout.y = yClipped && y > coordSysY2 ? y2 : y; + layout.width = xClipped ? 0 : x2 - x; + layout.height = yClipped ? 0 : y2 - y; // Reverse back + + if (signWidth < 0) { + layout.x += layout.width; + layout.width = -layout.width; + } + + if (signHeight < 0) { + layout.y += layout.height; + layout.height = -layout.height; + } + + return xClipped || yClipped; + }, + polar: function (coordSysClipArea, layout) { + var signR = layout.r0 <= layout.r ? 1 : -1; // Make sure r is larger than r0 + + if (signR < 0) { + var tmp = layout.r; + layout.r = layout.r0; + layout.r0 = tmp; + } + + var r = mathMin$6(layout.r, coordSysClipArea.r); + var r0 = mathMax$6(layout.r0, coordSysClipArea.r0); + layout.r = r; + layout.r0 = r0; + var clipped = r - r0 < 0; // Reverse back + + if (signR < 0) { + var tmp = layout.r; + layout.r = layout.r0; + layout.r0 = tmp; + } + + return clipped; + } + }; + var elementCreator = { + cartesian2d: function (seriesModel, data, newIndex, layout, isHorizontal, animationModel, axisModel, isUpdate, roundCap) { + var rect = new Rect({ + shape: extend({}, layout), + z2: 1 + }); + rect.__dataIndex = newIndex; + rect.name = 'item'; + + if (animationModel) { + var rectShape = rect.shape; + var animateProperty = isHorizontal ? 'height' : 'width'; + rectShape[animateProperty] = 0; + } + + return rect; + }, + polar: function (seriesModel, data, newIndex, layout, isRadial, animationModel, axisModel, isUpdate, roundCap) { + var ShapeClass = !isRadial && roundCap ? SausagePath : Sector; + var sector = new ShapeClass({ + shape: layout, + z2: 1 + }); + sector.name = 'item'; + var positionMap = createPolarPositionMapping(isRadial); + sector.calculateTextPosition = createSectorCalculateTextPosition(positionMap, { + isRoundCap: ShapeClass === SausagePath + }); // Animation + + if (animationModel) { + var sectorShape = sector.shape; + var animateProperty = isRadial ? 'r' : 'endAngle'; + var animateTarget = {}; + sectorShape[animateProperty] = isRadial ? 0 : layout.startAngle; + animateTarget[animateProperty] = layout[animateProperty]; + (isUpdate ? updateProps : initProps)(sector, { + shape: animateTarget // __value: typeof dataValue === 'string' ? parseInt(dataValue, 10) : dataValue + + }, animationModel); + } + + return sector; + } + }; + + function shouldRealtimeSort(seriesModel, coordSys) { + var realtimeSortOption = seriesModel.get('realtimeSort', true); + var baseAxis = coordSys.getBaseAxis(); + + if ("development" !== 'production') { + if (realtimeSortOption) { + if (baseAxis.type !== 'category') { + warn('`realtimeSort` will not work because this bar series is not based on a category axis.'); + } + + if (coordSys.type !== 'cartesian2d') { + warn('`realtimeSort` will not work because this bar series is not on cartesian2d.'); + } + } + } + + if (realtimeSortOption && baseAxis.type === 'category' && coordSys.type === 'cartesian2d') { + return { + baseAxis: baseAxis, + otherAxis: coordSys.getOtherAxis(baseAxis) + }; + } + } + + function updateRealtimeAnimation(realtimeSortCfg, seriesAnimationModel, el, layout, newIndex, isHorizontal, isUpdate, isChangeOrder) { + var seriesTarget; + var axisTarget; + + if (isHorizontal) { + axisTarget = { + x: layout.x, + width: layout.width + }; + seriesTarget = { + y: layout.y, + height: layout.height + }; + } else { + axisTarget = { + y: layout.y, + height: layout.height + }; + seriesTarget = { + x: layout.x, + width: layout.width + }; + } + + if (!isChangeOrder) { + // Keep the original growth animation if only axis order changed. + // Not start a new animation. + (isUpdate ? updateProps : initProps)(el, { + shape: seriesTarget + }, seriesAnimationModel, newIndex, null); + } + + var axisAnimationModel = seriesAnimationModel ? realtimeSortCfg.baseAxis.model : null; + (isUpdate ? updateProps : initProps)(el, { + shape: axisTarget + }, axisAnimationModel, newIndex); + } + + function checkPropertiesNotValid(obj, props) { + for (var i = 0; i < props.length; i++) { + if (!isFinite(obj[props[i]])) { + return true; + } + } + + return false; + } + + var rectPropties = ['x', 'y', 'width', 'height']; + var polarPropties = ['cx', 'cy', 'r', 'startAngle', 'endAngle']; + var isValidLayout = { + cartesian2d: function (layout) { + return !checkPropertiesNotValid(layout, rectPropties); + }, + polar: function (layout) { + return !checkPropertiesNotValid(layout, polarPropties); + } + }; + var getLayout = { + // itemModel is only used to get borderWidth, which is not needed + // when calculating bar background layout. + cartesian2d: function (data, dataIndex, itemModel) { + var layout = data.getItemLayout(dataIndex); + var fixedLineWidth = itemModel ? getLineWidth(itemModel, layout) : 0; // fix layout with lineWidth + + var signX = layout.width > 0 ? 1 : -1; + var signY = layout.height > 0 ? 1 : -1; + return { + x: layout.x + signX * fixedLineWidth / 2, + y: layout.y + signY * fixedLineWidth / 2, + width: layout.width - signX * fixedLineWidth, + height: layout.height - signY * fixedLineWidth + }; + }, + polar: function (data, dataIndex, itemModel) { + var layout = data.getItemLayout(dataIndex); + return { + cx: layout.cx, + cy: layout.cy, + r0: layout.r0, + r: layout.r, + startAngle: layout.startAngle, + endAngle: layout.endAngle, + clockwise: layout.clockwise + }; + } + }; + + function isZeroOnPolar(layout) { + return layout.startAngle != null && layout.endAngle != null && layout.startAngle === layout.endAngle; + } + + function createPolarPositionMapping(isRadial) { + return function (isRadial) { + var arcOrAngle = isRadial ? 'Arc' : 'Angle'; + return function (position) { + switch (position) { + case 'start': + case 'insideStart': + case 'end': + case 'insideEnd': + return position + arcOrAngle; + + default: + return position; + } + }; + }(isRadial); + } + + function updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, isPolar) { + var style = data.getItemVisual(dataIndex, 'style'); + + if (!isPolar) { + el.setShape('r', itemModel.get(['itemStyle', 'borderRadius']) || 0); + } + + el.useStyle(style); + var cursorStyle = itemModel.getShallow('cursor'); + cursorStyle && el.attr('cursor', cursorStyle); + var labelPositionOutside = isPolar ? isHorizontalOrRadial ? layout.r >= layout.r0 ? 'endArc' : 'startArc' : layout.endAngle >= layout.startAngle ? 'endAngle' : 'startAngle' : isHorizontalOrRadial ? layout.height >= 0 ? 'bottom' : 'top' : layout.width >= 0 ? 'right' : 'left'; + var labelStatesModels = getLabelStatesModels(itemModel); + setLabelStyle(el, labelStatesModels, { + labelFetcher: seriesModel, + labelDataIndex: dataIndex, + defaultText: getDefaultLabel(seriesModel.getData(), dataIndex), + inheritColor: style.fill, + defaultOpacity: style.opacity, + defaultOutsidePosition: labelPositionOutside + }); + var label = el.getTextContent(); + + if (isPolar && label) { + var position = itemModel.get(['label', 'position']); + el.textConfig.inside = position === 'middle' ? true : null; + setSectorTextRotation(el, position === 'outside' ? labelPositionOutside : position, createPolarPositionMapping(isHorizontalOrRadial), itemModel.get(['label', 'rotate'])); + } + + setLabelValueAnimation(label, labelStatesModels, seriesModel.getRawValue(dataIndex), function (value) { + return getDefaultInterpolatedLabel(data, value); + }); + var emphasisModel = itemModel.getModel(['emphasis']); + toggleHoverEmphasis(el, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled')); + setStatesStylesFromModel(el, itemModel); + + if (isZeroOnPolar(layout)) { + el.style.fill = 'none'; + el.style.stroke = 'none'; + each(el.states, function (state) { + if (state.style) { + state.style.fill = state.style.stroke = 'none'; + } + }); + } + } // In case width or height are too small. + + + function getLineWidth(itemModel, rawLayout) { + // Has no border. + var borderColor = itemModel.get(['itemStyle', 'borderColor']); + + if (!borderColor || borderColor === 'none') { + return 0; + } + + var lineWidth = itemModel.get(['itemStyle', 'borderWidth']) || 0; // width or height may be NaN for empty data + + var width = isNaN(rawLayout.width) ? Number.MAX_VALUE : Math.abs(rawLayout.width); + var height = isNaN(rawLayout.height) ? Number.MAX_VALUE : Math.abs(rawLayout.height); + return Math.min(lineWidth, width, height); + } + + var LagePathShape = + /** @class */ + function () { + function LagePathShape() {} + + return LagePathShape; + }(); + + var LargePath = + /** @class */ + function (_super) { + __extends(LargePath, _super); + + function LargePath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'largeBar'; + return _this; + } + + LargePath.prototype.getDefaultShape = function () { + return new LagePathShape(); + }; + + LargePath.prototype.buildPath = function (ctx, shape) { + // Drawing lines is more efficient than drawing + // a whole line or drawing rects. + var points = shape.points; + var baseDimIdx = this.baseDimIdx; + var valueDimIdx = 1 - this.baseDimIdx; + var startPoint = []; + var size = []; + var barWidth = this.barWidth; + + for (var i = 0; i < points.length; i += 3) { + size[baseDimIdx] = barWidth; + size[valueDimIdx] = points[i + 2]; + startPoint[baseDimIdx] = points[i + baseDimIdx]; + startPoint[valueDimIdx] = points[i + valueDimIdx]; + ctx.rect(startPoint[0], startPoint[1], size[0], size[1]); + } + }; + + return LargePath; + }(Path); + + function createLarge(seriesModel, group, progressiveEls, incremental) { + // TODO support polar + var data = seriesModel.getData(); + var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0; + var largeDataIndices = data.getLayout('largeDataIndices'); + var barWidth = data.getLayout('size'); + var backgroundModel = seriesModel.getModel('backgroundStyle'); + var bgPoints = data.getLayout('largeBackgroundPoints'); + + if (bgPoints) { + var bgEl = new LargePath({ + shape: { + points: bgPoints + }, + incremental: !!incremental, + silent: true, + z2: 0 + }); + bgEl.baseDimIdx = baseDimIdx; + bgEl.largeDataIndices = largeDataIndices; + bgEl.barWidth = barWidth; + bgEl.useStyle(backgroundModel.getItemStyle()); + group.add(bgEl); + progressiveEls && progressiveEls.push(bgEl); + } + + var el = new LargePath({ + shape: { + points: data.getLayout('largePoints') + }, + incremental: !!incremental, + z2: 1 + }); + el.baseDimIdx = baseDimIdx; + el.largeDataIndices = largeDataIndices; + el.barWidth = barWidth; + group.add(el); + el.useStyle(data.getVisual('style')); // Enable tooltip and user mouse/touch event handlers. + + getECData(el).seriesIndex = seriesModel.seriesIndex; + + if (!seriesModel.get('silent')) { + el.on('mousedown', largePathUpdateDataIndex); + el.on('mousemove', largePathUpdateDataIndex); + } + + progressiveEls && progressiveEls.push(el); + } // Use throttle to avoid frequently traverse to find dataIndex. + + + var largePathUpdateDataIndex = throttle(function (event) { + var largePath = this; + var dataIndex = largePathFindDataIndex(largePath, event.offsetX, event.offsetY); + getECData(largePath).dataIndex = dataIndex >= 0 ? dataIndex : null; + }, 30, false); + + function largePathFindDataIndex(largePath, x, y) { + var baseDimIdx = largePath.baseDimIdx; + var valueDimIdx = 1 - baseDimIdx; + var points = largePath.shape.points; + var largeDataIndices = largePath.largeDataIndices; + var startPoint = []; + var size = []; + var barWidth = largePath.barWidth; + + for (var i = 0, len = points.length / 3; i < len; i++) { + var ii = i * 3; + size[baseDimIdx] = barWidth; + size[valueDimIdx] = points[ii + 2]; + startPoint[baseDimIdx] = points[ii + baseDimIdx]; + startPoint[valueDimIdx] = points[ii + valueDimIdx]; + + if (size[valueDimIdx] < 0) { + startPoint[valueDimIdx] += size[valueDimIdx]; + size[valueDimIdx] = -size[valueDimIdx]; + } + + if (x >= startPoint[0] && x <= startPoint[0] + size[0] && y >= startPoint[1] && y <= startPoint[1] + size[1]) { + return largeDataIndices[i]; + } + } + + return -1; + } + + function createBackgroundShape(isHorizontalOrRadial, layout, coord) { + if (isCoordinateSystemType(coord, 'cartesian2d')) { + var rectShape = layout; + var coordLayout = coord.getArea(); + return { + x: isHorizontalOrRadial ? rectShape.x : coordLayout.x, + y: isHorizontalOrRadial ? coordLayout.y : rectShape.y, + width: isHorizontalOrRadial ? rectShape.width : coordLayout.width, + height: isHorizontalOrRadial ? coordLayout.height : rectShape.height + }; + } else { + var coordLayout = coord.getArea(); + var sectorShape = layout; + return { + cx: coordLayout.cx, + cy: coordLayout.cy, + r0: isHorizontalOrRadial ? coordLayout.r0 : sectorShape.r0, + r: isHorizontalOrRadial ? coordLayout.r : sectorShape.r, + startAngle: isHorizontalOrRadial ? sectorShape.startAngle : 0, + endAngle: isHorizontalOrRadial ? sectorShape.endAngle : Math.PI * 2 + }; + } + } + + function createBackgroundEl(coord, isHorizontalOrRadial, layout) { + var ElementClz = coord.type === 'polar' ? Sector : Rect; + return new ElementClz({ + shape: createBackgroundShape(isHorizontalOrRadial, layout, coord), + silent: true, + z2: 0 + }); + } + + function install$3(registers) { + registers.registerChartView(BarView); + registers.registerSeriesModel(BarSeriesModel); + registers.registerLayout(registers.PRIORITY.VISUAL.LAYOUT, curry(layout, 'bar')); // Do layout after other overall layout, which can preapre some informations. + + registers.registerLayout(registers.PRIORITY.VISUAL.PROGRESSIVE_LAYOUT, createProgressiveLayout('bar')); // Down sample after filter + + registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, dataSample('bar')); + /** + * @payload + * @property {string} [componentType=series] + * @property {number} [dx] + * @property {number} [dy] + * @property {number} [zoom] + * @property {number} [originX] + * @property {number} [originY] + */ + + registers.registerAction({ + type: 'changeAxisOrder', + event: 'changeAxisOrder', + update: 'update' + }, function (payload, ecModel) { + var componentType = payload.componentType || 'series'; + ecModel.eachComponent({ + mainType: componentType, + query: payload + }, function (componentModel) { + if (payload.sortInfo) { + componentModel.axis.setCategorySortInfo(payload.sortInfo); + } + }); + }); + } + + var PI2$8 = Math.PI * 2; + var RADIAN = Math.PI / 180; + + function getViewRect(seriesModel, api) { + return getLayoutRect(seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + } + + function getBasicPieLayout(seriesModel, api) { + var viewRect = getViewRect(seriesModel, api); + var center = seriesModel.get('center'); + var radius = seriesModel.get('radius'); + + if (!isArray(radius)) { + radius = [0, radius]; + } + + if (!isArray(center)) { + center = [center, center]; + } + + var width = parsePercent$1(viewRect.width, api.getWidth()); + var height = parsePercent$1(viewRect.height, api.getHeight()); + var size = Math.min(width, height); + var cx = parsePercent$1(center[0], width) + viewRect.x; + var cy = parsePercent$1(center[1], height) + viewRect.y; + var r0 = parsePercent$1(radius[0], size / 2); + var r = parsePercent$1(radius[1], size / 2); + return { + cx: cx, + cy: cy, + r0: r0, + r: r + }; + } + function pieLayout(seriesType, ecModel, api) { + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + var data = seriesModel.getData(); + var valueDim = data.mapDimension('value'); + var viewRect = getViewRect(seriesModel, api); + + var _a = getBasicPieLayout(seriesModel, api), + cx = _a.cx, + cy = _a.cy, + r = _a.r, + r0 = _a.r0; + + var startAngle = -seriesModel.get('startAngle') * RADIAN; + var minAngle = seriesModel.get('minAngle') * RADIAN; + var validDataCount = 0; + data.each(valueDim, function (value) { + !isNaN(value) && validDataCount++; + }); + var sum = data.getSum(valueDim); // Sum may be 0 + + var unitRadian = Math.PI / (sum || validDataCount) * 2; + var clockwise = seriesModel.get('clockwise'); + var roseType = seriesModel.get('roseType'); + var stillShowZeroSum = seriesModel.get('stillShowZeroSum'); // [0...max] + + var extent = data.getDataExtent(valueDim); + extent[0] = 0; // In the case some sector angle is smaller than minAngle + + var restAngle = PI2$8; + var valueSumLargerThanMinAngle = 0; + var currentAngle = startAngle; + var dir = clockwise ? 1 : -1; + data.setLayout({ + viewRect: viewRect, + r: r + }); + data.each(valueDim, function (value, idx) { + var angle; + + if (isNaN(value)) { + data.setItemLayout(idx, { + angle: NaN, + startAngle: NaN, + endAngle: NaN, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: r0, + r: roseType ? NaN : r + }); + return; + } // FIXME 兼容 2.0 但是 roseType 是 area 的时候才是这样? + + + if (roseType !== 'area') { + angle = sum === 0 && stillShowZeroSum ? unitRadian : value * unitRadian; + } else { + angle = PI2$8 / validDataCount; + } + + if (angle < minAngle) { + angle = minAngle; + restAngle -= minAngle; + } else { + valueSumLargerThanMinAngle += value; + } + + var endAngle = currentAngle + dir * angle; + data.setItemLayout(idx, { + angle: angle, + startAngle: currentAngle, + endAngle: endAngle, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: r0, + r: roseType ? linearMap(value, extent, [r0, r]) : r + }); + currentAngle = endAngle; + }); // Some sector is constrained by minAngle + // Rest sectors needs recalculate angle + + if (restAngle < PI2$8 && validDataCount) { + // Average the angle if rest angle is not enough after all angles is + // Constrained by minAngle + if (restAngle <= 1e-3) { + var angle_1 = PI2$8 / validDataCount; + data.each(valueDim, function (value, idx) { + if (!isNaN(value)) { + var layout_1 = data.getItemLayout(idx); + layout_1.angle = angle_1; + layout_1.startAngle = startAngle + dir * idx * angle_1; + layout_1.endAngle = startAngle + dir * (idx + 1) * angle_1; + } + }); + } else { + unitRadian = restAngle / valueSumLargerThanMinAngle; + currentAngle = startAngle; + data.each(valueDim, function (value, idx) { + if (!isNaN(value)) { + var layout_2 = data.getItemLayout(idx); + var angle = layout_2.angle === minAngle ? minAngle : value * unitRadian; + layout_2.startAngle = currentAngle; + layout_2.endAngle = currentAngle + dir * angle; + currentAngle += dir * angle; + } + }); + } + } + }); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function dataFilter(seriesType) { + return { + seriesType: seriesType, + reset: function (seriesModel, ecModel) { + var legendModels = ecModel.findComponents({ + mainType: 'legend' + }); + + if (!legendModels || !legendModels.length) { + return; + } + + var data = seriesModel.getData(); + data.filterSelf(function (idx) { + var name = data.getName(idx); // If in any legend component the status is not selected. + + for (var i = 0; i < legendModels.length; i++) { + // @ts-ignore FIXME: LegendModel + if (!legendModels[i].isSelected(name)) { + return false; + } + } + + return true; + }); + } + }; + } + + var RADIAN$1 = Math.PI / 180; + + function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight, viewLeft, viewTop, farthestX) { + if (list.length < 2) { + return; + } + + function recalculateXOnSemiToAlignOnEllipseCurve(semi) { + var rB = semi.rB; + var rB2 = rB * rB; + + for (var i = 0; i < semi.list.length; i++) { + var item = semi.list[i]; + var dy = Math.abs(item.label.y - cy); // horizontal r is always same with original r because x is not changed. + + var rA = r + item.len; + var rA2 = rA * rA; // Use ellipse implicit function to calculate x + + var dx = Math.sqrt((1 - Math.abs(dy * dy / rB2)) * rA2); + var newX = cx + (dx + item.len2) * dir; + var deltaX = newX - item.label.x; + var newTargetWidth = item.targetTextWidth - deltaX * dir; // text x is changed, so need to recalculate width. + + constrainTextWidth(item, newTargetWidth, true); + item.label.x = newX; + } + } // Adjust X based on the shifted y. Make tight labels aligned on an ellipse curve. + + + function recalculateX(items) { + // Extremes of + var topSemi = { + list: [], + maxY: 0 + }; + var bottomSemi = { + list: [], + maxY: 0 + }; + + for (var i = 0; i < items.length; i++) { + if (items[i].labelAlignTo !== 'none') { + continue; + } + + var item = items[i]; + var semi = item.label.y > cy ? bottomSemi : topSemi; + var dy = Math.abs(item.label.y - cy); + + if (dy >= semi.maxY) { + var dx = item.label.x - cx - item.len2 * dir; // horizontal r is always same with original r because x is not changed. + + var rA = r + item.len; // Canculate rB based on the topest / bottemest label. + + var rB = Math.abs(dx) < rA ? Math.sqrt(dy * dy / (1 - dx * dx / rA / rA)) : rA; + semi.rB = rB; + semi.maxY = dy; + } + + semi.list.push(item); + } + + recalculateXOnSemiToAlignOnEllipseCurve(topSemi); + recalculateXOnSemiToAlignOnEllipseCurve(bottomSemi); + } + + var len = list.length; + + for (var i = 0; i < len; i++) { + if (list[i].position === 'outer' && list[i].labelAlignTo === 'labelLine') { + var dx = list[i].label.x - farthestX; + list[i].linePoints[1][0] += dx; + list[i].label.x = farthestX; + } + } + + if (shiftLayoutOnY(list, viewTop, viewTop + viewHeight)) { + recalculateX(list); + } + } + + function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop) { + var leftList = []; + var rightList = []; + var leftmostX = Number.MAX_VALUE; + var rightmostX = -Number.MAX_VALUE; + + for (var i = 0; i < labelLayoutList.length; i++) { + var label = labelLayoutList[i].label; + + if (isPositionCenter(labelLayoutList[i])) { + continue; + } + + if (label.x < cx) { + leftmostX = Math.min(leftmostX, label.x); + leftList.push(labelLayoutList[i]); + } else { + rightmostX = Math.max(rightmostX, label.x); + rightList.push(labelLayoutList[i]); + } + } + + for (var i = 0; i < labelLayoutList.length; i++) { + var layout = labelLayoutList[i]; + + if (!isPositionCenter(layout) && layout.linePoints) { + if (layout.labelStyleWidth != null) { + continue; + } + + var label = layout.label; + var linePoints = layout.linePoints; + var targetTextWidth = void 0; + + if (layout.labelAlignTo === 'edge') { + if (label.x < cx) { + targetTextWidth = linePoints[2][0] - layout.labelDistance - viewLeft - layout.edgeDistance; + } else { + targetTextWidth = viewLeft + viewWidth - layout.edgeDistance - linePoints[2][0] - layout.labelDistance; + } + } else if (layout.labelAlignTo === 'labelLine') { + if (label.x < cx) { + targetTextWidth = leftmostX - viewLeft - layout.bleedMargin; + } else { + targetTextWidth = viewLeft + viewWidth - rightmostX - layout.bleedMargin; + } + } else { + if (label.x < cx) { + targetTextWidth = label.x - viewLeft - layout.bleedMargin; + } else { + targetTextWidth = viewLeft + viewWidth - label.x - layout.bleedMargin; + } + } + + layout.targetTextWidth = targetTextWidth; + constrainTextWidth(layout, targetTextWidth); + } + } + + adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight, viewLeft, viewTop, rightmostX); + adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight, viewLeft, viewTop, leftmostX); + + for (var i = 0; i < labelLayoutList.length; i++) { + var layout = labelLayoutList[i]; + + if (!isPositionCenter(layout) && layout.linePoints) { + var label = layout.label; + var linePoints = layout.linePoints; + var isAlignToEdge = layout.labelAlignTo === 'edge'; + var padding = label.style.padding; + var paddingH = padding ? padding[1] + padding[3] : 0; // textRect.width already contains paddingH if bgColor is set + + var extraPaddingH = label.style.backgroundColor ? 0 : paddingH; + var realTextWidth = layout.rect.width + extraPaddingH; + var dist = linePoints[1][0] - linePoints[2][0]; + + if (isAlignToEdge) { + if (label.x < cx) { + linePoints[2][0] = viewLeft + layout.edgeDistance + realTextWidth + layout.labelDistance; + } else { + linePoints[2][0] = viewLeft + viewWidth - layout.edgeDistance - realTextWidth - layout.labelDistance; + } + } else { + if (label.x < cx) { + linePoints[2][0] = label.x + layout.labelDistance; + } else { + linePoints[2][0] = label.x - layout.labelDistance; + } + + linePoints[1][0] = linePoints[2][0] + dist; + } + + linePoints[1][1] = linePoints[2][1] = label.y; + } + } + } + /** + * Set max width of each label, and then wrap each label to the max width. + * + * @param layout label layout + * @param availableWidth max width for the label to display + * @param forceRecalculate recaculate the text layout even if the current width + * is smaller than `availableWidth`. This is useful when the text was previously + * wrapped by calling `constrainTextWidth` but now `availableWidth` changed, in + * which case, previous wrapping should be redo. + */ + + + function constrainTextWidth(layout, availableWidth, forceRecalculate) { + if (forceRecalculate === void 0) { + forceRecalculate = false; + } + + if (layout.labelStyleWidth != null) { + // User-defined style.width has the highest priority. + return; + } + + var label = layout.label; + var style = label.style; + var textRect = layout.rect; + var bgColor = style.backgroundColor; + var padding = style.padding; + var paddingH = padding ? padding[1] + padding[3] : 0; + var overflow = style.overflow; // textRect.width already contains paddingH if bgColor is set + + var oldOuterWidth = textRect.width + (bgColor ? 0 : paddingH); + + if (availableWidth < oldOuterWidth || forceRecalculate) { + var oldHeight = textRect.height; + + if (overflow && overflow.match('break')) { + // Temporarily set background to be null to calculate + // the bounding box without backgroud. + label.setStyle('backgroundColor', null); // Set constraining width + + label.setStyle('width', availableWidth - paddingH); // This is the real bounding box of the text without padding + + var innerRect = label.getBoundingRect(); + label.setStyle('width', Math.ceil(innerRect.width)); + label.setStyle('backgroundColor', bgColor); + } else { + var availableInnerWidth = availableWidth - paddingH; + var newWidth = availableWidth < oldOuterWidth // Current text is too wide, use `availableWidth` as max width. + ? availableInnerWidth : // Current available width is enough, but the text may have + // already been wrapped with a smaller available width. + forceRecalculate ? availableInnerWidth > layout.unconstrainedWidth // Current available is larger than text width, + // so don't constrain width (otherwise it may have + // empty space in the background). + ? null // Current available is smaller than text width, so + // use the current available width as constraining + // width. + : availableInnerWidth : // Current available width is enough, so no need to + // constrain. + null; + label.setStyle('width', newWidth); + } + + var newRect = label.getBoundingRect(); + textRect.width = newRect.width; + var margin = (label.style.margin || 0) + 2.1; + textRect.height = newRect.height + margin; + textRect.y -= (textRect.height - oldHeight) / 2; + } + } + + function isPositionCenter(sectorShape) { + // Not change x for center label + return sectorShape.position === 'center'; + } + + function pieLabelLayout(seriesModel) { + var data = seriesModel.getData(); + var labelLayoutList = []; + var cx; + var cy; + var hasLabelRotate = false; + var minShowLabelRadian = (seriesModel.get('minShowLabelAngle') || 0) * RADIAN$1; + var viewRect = data.getLayout('viewRect'); + var r = data.getLayout('r'); + var viewWidth = viewRect.width; + var viewLeft = viewRect.x; + var viewTop = viewRect.y; + var viewHeight = viewRect.height; + + function setNotShow(el) { + el.ignore = true; + } + + function isLabelShown(label) { + if (!label.ignore) { + return true; + } + + for (var key in label.states) { + if (label.states[key].ignore === false) { + return true; + } + } + + return false; + } + + data.each(function (idx) { + var sector = data.getItemGraphicEl(idx); + var sectorShape = sector.shape; + var label = sector.getTextContent(); + var labelLine = sector.getTextGuideLine(); + var itemModel = data.getItemModel(idx); + var labelModel = itemModel.getModel('label'); // Use position in normal or emphasis + + var labelPosition = labelModel.get('position') || itemModel.get(['emphasis', 'label', 'position']); + var labelDistance = labelModel.get('distanceToLabelLine'); + var labelAlignTo = labelModel.get('alignTo'); + var edgeDistance = parsePercent$1(labelModel.get('edgeDistance'), viewWidth); + var bleedMargin = labelModel.get('bleedMargin'); + var labelLineModel = itemModel.getModel('labelLine'); + var labelLineLen = labelLineModel.get('length'); + labelLineLen = parsePercent$1(labelLineLen, viewWidth); + var labelLineLen2 = labelLineModel.get('length2'); + labelLineLen2 = parsePercent$1(labelLineLen2, viewWidth); + + if (Math.abs(sectorShape.endAngle - sectorShape.startAngle) < minShowLabelRadian) { + each(label.states, setNotShow); + label.ignore = true; + return; + } + + if (!isLabelShown(label)) { + return; + } + + var midAngle = (sectorShape.startAngle + sectorShape.endAngle) / 2; + var nx = Math.cos(midAngle); + var ny = Math.sin(midAngle); + var textX; + var textY; + var linePoints; + var textAlign; + cx = sectorShape.cx; + cy = sectorShape.cy; + var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner'; + + if (labelPosition === 'center') { + textX = sectorShape.cx; + textY = sectorShape.cy; + textAlign = 'center'; + } else { + var x1 = (isLabelInside ? (sectorShape.r + sectorShape.r0) / 2 * nx : sectorShape.r * nx) + cx; + var y1 = (isLabelInside ? (sectorShape.r + sectorShape.r0) / 2 * ny : sectorShape.r * ny) + cy; + textX = x1 + nx * 3; + textY = y1 + ny * 3; + + if (!isLabelInside) { + // For roseType + var x2 = x1 + nx * (labelLineLen + r - sectorShape.r); + var y2 = y1 + ny * (labelLineLen + r - sectorShape.r); + var x3 = x2 + (nx < 0 ? -1 : 1) * labelLineLen2; + var y3 = y2; + + if (labelAlignTo === 'edge') { + // Adjust textX because text align of edge is opposite + textX = nx < 0 ? viewLeft + edgeDistance : viewLeft + viewWidth - edgeDistance; + } else { + textX = x3 + (nx < 0 ? -labelDistance : labelDistance); + } + + textY = y3; + linePoints = [[x1, y1], [x2, y2], [x3, y3]]; + } + + textAlign = isLabelInside ? 'center' : labelAlignTo === 'edge' ? nx > 0 ? 'right' : 'left' : nx > 0 ? 'left' : 'right'; + } + + var PI = Math.PI; + var labelRotate = 0; + var rotate = labelModel.get('rotate'); + + if (isNumber(rotate)) { + labelRotate = rotate * (PI / 180); + } else if (labelPosition === 'center') { + labelRotate = 0; + } else if (rotate === 'radial' || rotate === true) { + var radialAngle = nx < 0 ? -midAngle + PI : -midAngle; + labelRotate = radialAngle; + } else if (rotate === 'tangential' && labelPosition !== 'outside' && labelPosition !== 'outer') { + var rad = Math.atan2(nx, ny); + + if (rad < 0) { + rad = PI * 2 + rad; + } + + var isDown = ny > 0; + + if (isDown) { + rad = PI + rad; + } + + labelRotate = rad - PI; + } + + hasLabelRotate = !!labelRotate; + label.x = textX; + label.y = textY; + label.rotation = labelRotate; + label.setStyle({ + verticalAlign: 'middle' + }); // Not sectorShape the inside label + + if (!isLabelInside) { + var textRect = label.getBoundingRect().clone(); + textRect.applyTransform(label.getComputedTransform()); // Text has a default 1px stroke. Exclude this. + + var margin = (label.style.margin || 0) + 2.1; + textRect.y -= margin / 2; + textRect.height += margin; + labelLayoutList.push({ + label: label, + labelLine: labelLine, + position: labelPosition, + len: labelLineLen, + len2: labelLineLen2, + minTurnAngle: labelLineModel.get('minTurnAngle'), + maxSurfaceAngle: labelLineModel.get('maxSurfaceAngle'), + surfaceNormal: new Point(nx, ny), + linePoints: linePoints, + textAlign: textAlign, + labelDistance: labelDistance, + labelAlignTo: labelAlignTo, + edgeDistance: edgeDistance, + bleedMargin: bleedMargin, + rect: textRect, + unconstrainedWidth: textRect.width, + labelStyleWidth: label.style.width + }); + } else { + label.setStyle({ + align: textAlign + }); + var selectState = label.states.select; + + if (selectState) { + selectState.x += label.x; + selectState.y += label.y; + } + } + + sector.setTextConfig({ + inside: isLabelInside + }); + }); + + if (!hasLabelRotate && seriesModel.get('avoidLabelOverlap')) { + avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop); + } + + for (var i = 0; i < labelLayoutList.length; i++) { + var layout = labelLayoutList[i]; + var label = layout.label; + var labelLine = layout.labelLine; + var notShowLabel = isNaN(label.x) || isNaN(label.y); + + if (label) { + label.setStyle({ + align: layout.textAlign + }); + + if (notShowLabel) { + each(label.states, setNotShow); + label.ignore = true; + } + + var selectState = label.states.select; + + if (selectState) { + selectState.x += label.x; + selectState.y += label.y; + } + } + + if (labelLine) { + var linePoints = layout.linePoints; + + if (notShowLabel || !linePoints) { + each(labelLine.states, setNotShow); + labelLine.ignore = true; + } else { + limitTurnAngle(linePoints, layout.minTurnAngle); + limitSurfaceAngle(linePoints, layout.surfaceNormal, layout.maxSurfaceAngle); + labelLine.setShape({ + points: linePoints + }); // Set the anchor to the midpoint of sector + + label.__hostTarget.textGuideLineConfig = { + anchor: new Point(linePoints[0][0], linePoints[0][1]) + }; + } + } + } + } + + function getSectorCornerRadius(model, shape, zeroIfNull) { + var cornerRadius = model.get('borderRadius'); + + if (cornerRadius == null) { + return zeroIfNull ? { + cornerRadius: 0 + } : null; + } + + if (!isArray(cornerRadius)) { + cornerRadius = [cornerRadius, cornerRadius, cornerRadius, cornerRadius]; + } + + var dr = Math.abs(shape.r || 0 - shape.r0 || 0); + return { + cornerRadius: map(cornerRadius, function (cr) { + return parsePercent(cr, dr); + }) + }; + } + + /** + * Piece of pie including Sector, Label, LabelLine + */ + + var PiePiece = + /** @class */ + function (_super) { + __extends(PiePiece, _super); + + function PiePiece(data, idx, startAngle) { + var _this = _super.call(this) || this; + + _this.z2 = 2; + var text = new ZRText(); + + _this.setTextContent(text); + + _this.updateData(data, idx, startAngle, true); + + return _this; + } + + PiePiece.prototype.updateData = function (data, idx, startAngle, firstCreate) { + var sector = this; + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var emphasisModel = itemModel.getModel('emphasis'); + var layout = data.getItemLayout(idx); // cornerRadius & innerCornerRadius doesn't exist in the item layout. Use `0` if null value is specified. + // see `setItemLayout` in `pieLayout.ts`. + + var sectorShape = extend(getSectorCornerRadius(itemModel.getModel('itemStyle'), layout, true), layout); // Ignore NaN data. + + if (isNaN(sectorShape.startAngle)) { + // Use NaN shape to avoid drawing shape. + sector.setShape(sectorShape); + return; + } + + if (firstCreate) { + sector.setShape(sectorShape); + var animationType = seriesModel.getShallow('animationType'); + + if (seriesModel.ecModel.ssr) { + // Use scale animation in SSR mode(opacity?) + // Because CSS SVG animation doesn't support very customized shape animation. + initProps(sector, { + scaleX: 0, + scaleY: 0 + }, seriesModel, { + dataIndex: idx, + isFrom: true + }); + sector.originX = sectorShape.cx; + sector.originY = sectorShape.cy; + } else if (animationType === 'scale') { + sector.shape.r = layout.r0; + initProps(sector, { + shape: { + r: layout.r + } + }, seriesModel, idx); + } // Expansion + else { + if (startAngle != null) { + sector.setShape({ + startAngle: startAngle, + endAngle: startAngle + }); + initProps(sector, { + shape: { + startAngle: layout.startAngle, + endAngle: layout.endAngle + } + }, seriesModel, idx); + } else { + sector.shape.endAngle = layout.startAngle; + updateProps(sector, { + shape: { + endAngle: layout.endAngle + } + }, seriesModel, idx); + } + } + } else { + saveOldStyle(sector); // Transition animation from the old shape + + updateProps(sector, { + shape: sectorShape + }, seriesModel, idx); + } + + sector.useStyle(data.getItemVisual(idx, 'style')); + setStatesStylesFromModel(sector, itemModel); + var midAngle = (layout.startAngle + layout.endAngle) / 2; + var offset = seriesModel.get('selectedOffset'); + var dx = Math.cos(midAngle) * offset; + var dy = Math.sin(midAngle) * offset; + var cursorStyle = itemModel.getShallow('cursor'); + cursorStyle && sector.attr('cursor', cursorStyle); + + this._updateLabel(seriesModel, data, idx); + + sector.ensureState('emphasis').shape = extend({ + r: layout.r + (emphasisModel.get('scale') ? emphasisModel.get('scaleSize') || 0 : 0) + }, getSectorCornerRadius(emphasisModel.getModel('itemStyle'), layout)); + extend(sector.ensureState('select'), { + x: dx, + y: dy, + shape: getSectorCornerRadius(itemModel.getModel(['select', 'itemStyle']), layout) + }); + extend(sector.ensureState('blur'), { + shape: getSectorCornerRadius(itemModel.getModel(['blur', 'itemStyle']), layout) + }); + var labelLine = sector.getTextGuideLine(); + var labelText = sector.getTextContent(); + labelLine && extend(labelLine.ensureState('select'), { + x: dx, + y: dy + }); // TODO: needs dx, dy in zrender? + + extend(labelText.ensureState('select'), { + x: dx, + y: dy + }); + toggleHoverEmphasis(this, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled')); + }; + + PiePiece.prototype._updateLabel = function (seriesModel, data, idx) { + var sector = this; + var itemModel = data.getItemModel(idx); + var labelLineModel = itemModel.getModel('labelLine'); + var style = data.getItemVisual(idx, 'style'); + var visualColor = style && style.fill; + var visualOpacity = style && style.opacity; + setLabelStyle(sector, getLabelStatesModels(itemModel), { + labelFetcher: data.hostModel, + labelDataIndex: idx, + inheritColor: visualColor, + defaultOpacity: visualOpacity, + defaultText: seriesModel.getFormattedLabel(idx, 'normal') || data.getName(idx) + }); + var labelText = sector.getTextContent(); // Set textConfig on sector. + + sector.setTextConfig({ + // reset position, rotation + position: null, + rotation: null + }); // Make sure update style on labelText after setLabelStyle. + // Because setLabelStyle will replace a new style on it. + + labelText.attr({ + z2: 10 + }); + var labelPosition = seriesModel.get(['label', 'position']); + + if (labelPosition !== 'outside' && labelPosition !== 'outer') { + sector.removeTextGuideLine(); + } else { + var polyline = this.getTextGuideLine(); + + if (!polyline) { + polyline = new Polyline(); + this.setTextGuideLine(polyline); + } // Default use item visual color + + + setLabelLineStyle(this, getLabelLineStatesModels(itemModel), { + stroke: visualColor, + opacity: retrieve3(labelLineModel.get(['lineStyle', 'opacity']), visualOpacity, 1) + }); + } + }; + + return PiePiece; + }(Sector); // Pie view + + + var PieView = + /** @class */ + function (_super) { + __extends(PieView, _super); + + function PieView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.ignoreLabelLineUpdate = true; + return _this; + } + + PieView.prototype.render = function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + var oldData = this._data; + var group = this.group; + var startAngle; // First render + + if (!oldData && data.count() > 0) { + var shape = data.getItemLayout(0); + + for (var s = 1; isNaN(shape && shape.startAngle) && s < data.count(); ++s) { + shape = data.getItemLayout(s); + } + + if (shape) { + startAngle = shape.startAngle; + } + } // remove empty-circle if it exists + + + if (this._emptyCircleSector) { + group.remove(this._emptyCircleSector); + } // when all data are filtered, show lightgray empty circle + + + if (data.count() === 0 && seriesModel.get('showEmptyCircle')) { + var sector = new Sector({ + shape: getBasicPieLayout(seriesModel, api) + }); + sector.useStyle(seriesModel.getModel('emptyCircleStyle').getItemStyle()); + this._emptyCircleSector = sector; + group.add(sector); + } + + data.diff(oldData).add(function (idx) { + var piePiece = new PiePiece(data, idx, startAngle); + data.setItemGraphicEl(idx, piePiece); + group.add(piePiece); + }).update(function (newIdx, oldIdx) { + var piePiece = oldData.getItemGraphicEl(oldIdx); + piePiece.updateData(data, newIdx, startAngle); + piePiece.off('click'); + group.add(piePiece); + data.setItemGraphicEl(newIdx, piePiece); + }).remove(function (idx) { + var piePiece = oldData.getItemGraphicEl(idx); + removeElementWithFadeOut(piePiece, seriesModel, idx); + }).execute(); + pieLabelLayout(seriesModel); // Always use initial animation. + + if (seriesModel.get('animationTypeUpdate') !== 'expansion') { + this._data = data; + } + }; + + PieView.prototype.dispose = function () {}; + + PieView.prototype.containPoint = function (point, seriesModel) { + var data = seriesModel.getData(); + var itemLayout = data.getItemLayout(0); + + if (itemLayout) { + var dx = point[0] - itemLayout.cx; + var dy = point[1] - itemLayout.cy; + var radius = Math.sqrt(dx * dx + dy * dy); + return radius <= itemLayout.r && radius >= itemLayout.r0; + } + }; + + PieView.type = 'pie'; + return PieView; + }(ChartView); + + /** + * [Usage]: + * (1) + * createListSimply(seriesModel, ['value']); + * (2) + * createListSimply(seriesModel, { + * coordDimensions: ['value'], + * dimensionsCount: 5 + * }); + */ + + function createSeriesDataSimply(seriesModel, opt, nameList) { + opt = isArray(opt) && { + coordDimensions: opt + } || extend({ + encodeDefine: seriesModel.getEncode() + }, opt); + var source = seriesModel.getSource(); + var dimensions = prepareSeriesDataSchema(source, opt).dimensions; + var list = new SeriesData(dimensions, seriesModel); + list.initData(source, nameList); + return list; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + /** + * LegendVisualProvider is an bridge that pick encoded color from data and + * provide to the legend component. + */ + var LegendVisualProvider = + /** @class */ + function () { + function LegendVisualProvider( // Function to get data after filtered. It stores all the encoding info + getDataWithEncodedVisual, // Function to get raw data before filtered. + getRawData) { + this._getDataWithEncodedVisual = getDataWithEncodedVisual; + this._getRawData = getRawData; + } + + LegendVisualProvider.prototype.getAllNames = function () { + var rawData = this._getRawData(); // We find the name from the raw data. In case it's filtered by the legend component. + // Normally, the name can be found in rawData, but can't be found in filtered data will display as gray. + + + return rawData.mapArray(rawData.getName); + }; + + LegendVisualProvider.prototype.containName = function (name) { + var rawData = this._getRawData(); + + return rawData.indexOfName(name) >= 0; + }; + + LegendVisualProvider.prototype.indexOfName = function (name) { + // Only get data when necessary. + // Because LegendVisualProvider constructor may be new in the stage that data is not prepared yet. + // Invoking Series#getData immediately will throw an error. + var dataWithEncodedVisual = this._getDataWithEncodedVisual(); + + return dataWithEncodedVisual.indexOfName(name); + }; + + LegendVisualProvider.prototype.getItemVisual = function (dataIndex, key) { + // Get encoded visual properties from final filtered data. + var dataWithEncodedVisual = this._getDataWithEncodedVisual(); + + return dataWithEncodedVisual.getItemVisual(dataIndex, key); + }; + + return LegendVisualProvider; + }(); + + var PieSeriesModel = + /** @class */ + function (_super) { + __extends(PieSeriesModel, _super); + + function PieSeriesModel() { + return _super !== null && _super.apply(this, arguments) || this; + } + /** + * @overwrite + */ + + + PieSeriesModel.prototype.init = function (option) { + _super.prototype.init.apply(this, arguments); // Enable legend selection for each data item + // Use a function instead of direct access because data reference may changed + + + this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this)); + + this._defaultLabelLine(option); + }; + /** + * @overwrite + */ + + + PieSeriesModel.prototype.mergeOption = function () { + _super.prototype.mergeOption.apply(this, arguments); + }; + /** + * @overwrite + */ + + + PieSeriesModel.prototype.getInitialData = function () { + return createSeriesDataSimply(this, { + coordDimensions: ['value'], + encodeDefaulter: curry(makeSeriesEncodeForNameBased, this) + }); + }; + /** + * @overwrite + */ + + + PieSeriesModel.prototype.getDataParams = function (dataIndex) { + var data = this.getData(); + + var params = _super.prototype.getDataParams.call(this, dataIndex); // FIXME toFixed? + + + var valueList = []; + data.each(data.mapDimension('value'), function (value) { + valueList.push(value); + }); + params.percent = getPercentWithPrecision(valueList, dataIndex, data.hostModel.get('percentPrecision')); + params.$vars.push('percent'); + return params; + }; + + PieSeriesModel.prototype._defaultLabelLine = function (option) { + // Extend labelLine emphasis + defaultEmphasis(option, 'labelLine', ['show']); + var labelLineNormalOpt = option.labelLine; + var labelLineEmphasisOpt = option.emphasis.labelLine; // Not show label line if `label.normal.show = false` + + labelLineNormalOpt.show = labelLineNormalOpt.show && option.label.show; + labelLineEmphasisOpt.show = labelLineEmphasisOpt.show && option.emphasis.label.show; + }; + + PieSeriesModel.type = 'series.pie'; + PieSeriesModel.defaultOption = { + // zlevel: 0, + z: 2, + legendHoverLink: true, + colorBy: 'data', + // 默认全局居中 + center: ['50%', '50%'], + radius: [0, '75%'], + // 默认顺时针 + clockwise: true, + startAngle: 90, + // 最小角度改为0 + minAngle: 0, + // If the angle of a sector less than `minShowLabelAngle`, + // the label will not be displayed. + minShowLabelAngle: 0, + // 选中时扇区偏移量 + selectedOffset: 10, + // 选择模式,默认关闭,可选single,multiple + // selectedMode: false, + // 南丁格尔玫瑰图模式,'radius'(半径) | 'area'(面积) + // roseType: null, + percentPrecision: 2, + // If still show when all data zero. + stillShowZeroSum: true, + // cursor: null, + left: 0, + top: 0, + right: 0, + bottom: 0, + width: null, + height: null, + label: { + // color: 'inherit', + // If rotate around circle + rotate: 0, + show: true, + overflow: 'truncate', + // 'outer', 'inside', 'center' + position: 'outer', + // 'none', 'labelLine', 'edge'. Works only when position is 'outer' + alignTo: 'none', + // Closest distance between label and chart edge. + // Works only position is 'outer' and alignTo is 'edge'. + edgeDistance: '25%', + // Works only position is 'outer' and alignTo is not 'edge'. + bleedMargin: 10, + // Distance between text and label line. + distanceToLabelLine: 5 // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调 + // 默认使用全局文本样式,详见TEXTSTYLE + // distance: 当position为inner时有效,为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数 + + }, + // Enabled when label.normal.position is 'outer' + labelLine: { + show: true, + // 引导线两段中的第一段长度 + length: 15, + // 引导线两段中的第二段长度 + length2: 15, + smooth: false, + minTurnAngle: 90, + maxSurfaceAngle: 90, + lineStyle: { + // color: 各异, + width: 1, + type: 'solid' + } + }, + itemStyle: { + borderWidth: 1, + borderJoin: 'round' + }, + showEmptyCircle: true, + emptyCircleStyle: { + color: 'lightgray', + opacity: 1 + }, + labelLayout: { + // Hide the overlapped label. + hideOverlap: true + }, + emphasis: { + scale: true, + scaleSize: 5 + }, + // If use strategy to avoid label overlapping + avoidLabelOverlap: true, + // Animation type. Valid values: expansion, scale + animationType: 'expansion', + animationDuration: 1000, + // Animation type when update. Valid values: transition, expansion + animationTypeUpdate: 'transition', + animationEasingUpdate: 'cubicInOut', + animationDurationUpdate: 500, + animationEasing: 'cubicInOut' + }; + return PieSeriesModel; + }(SeriesModel); + + function negativeDataFilter(seriesType) { + return { + seriesType: seriesType, + reset: function (seriesModel, ecModel) { + var data = seriesModel.getData(); + data.filterSelf(function (idx) { + // handle negative value condition + var valueDim = data.mapDimension('value'); + var curValue = data.get(valueDim, idx); + + if (isNumber(curValue) && !isNaN(curValue) && curValue < 0) { + return false; + } + + return true; + }); + } + }; + } + + function install$4(registers) { + registers.registerChartView(PieView); + registers.registerSeriesModel(PieSeriesModel); + createLegacyDataSelectAction('pie', registers.registerAction); + registers.registerLayout(curry(pieLayout, 'pie')); + registers.registerProcessor(dataFilter('pie')); + registers.registerProcessor(negativeDataFilter('pie')); + } + + var ScatterSeriesModel = + /** @class */ + function (_super) { + __extends(ScatterSeriesModel, _super); + + function ScatterSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ScatterSeriesModel.type; + _this.hasSymbolVisual = true; + return _this; + } + + ScatterSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createSeriesData(null, this, { + useEncodeDefaulter: true + }); + }; + + ScatterSeriesModel.prototype.getProgressive = function () { + var progressive = this.option.progressive; + + if (progressive == null) { + // PENDING + return this.option.large ? 5e3 : this.get('progressive'); + } + + return progressive; + }; + + ScatterSeriesModel.prototype.getProgressiveThreshold = function () { + var progressiveThreshold = this.option.progressiveThreshold; + + if (progressiveThreshold == null) { + // PENDING + return this.option.large ? 1e4 : this.get('progressiveThreshold'); + } + + return progressiveThreshold; + }; + + ScatterSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) { + return selectors.point(data.getItemLayout(dataIndex)); + }; + + ScatterSeriesModel.prototype.getZLevelKey = function () { + // Each progressive series has individual key. + return this.getData().count() > this.getProgressiveThreshold() ? this.id : ''; + }; + + ScatterSeriesModel.type = 'series.scatter'; + ScatterSeriesModel.dependencies = ['grid', 'polar', 'geo', 'singleAxis', 'calendar']; + ScatterSeriesModel.defaultOption = { + coordinateSystem: 'cartesian2d', + // zlevel: 0, + z: 2, + legendHoverLink: true, + symbolSize: 10, + // symbolRotate: null, // 图形旋转控制 + large: false, + // Available when large is true + largeThreshold: 2000, + // cursor: null, + itemStyle: { + opacity: 0.8 // color: 各异 + + }, + emphasis: { + scale: true + }, + // If clip the overflow graphics + // Works on cartesian / polar series + clip: true, + select: { + itemStyle: { + borderColor: '#212121' + } + }, + universalTransition: { + divideShape: 'clone' + } // progressive: null + + }; + return ScatterSeriesModel; + }(SeriesModel); + + var BOOST_SIZE_THRESHOLD = 4; + + var LargeSymbolPathShape = + /** @class */ + function () { + function LargeSymbolPathShape() {} + + return LargeSymbolPathShape; + }(); + + var LargeSymbolPath = + /** @class */ + function (_super) { + __extends(LargeSymbolPath, _super); + + function LargeSymbolPath(opts) { + var _this = _super.call(this, opts) || this; + + _this._off = 0; + _this.hoverDataIdx = -1; + return _this; + } + + LargeSymbolPath.prototype.getDefaultShape = function () { + return new LargeSymbolPathShape(); + }; + + LargeSymbolPath.prototype.reset = function () { + this.notClear = false; + this._off = 0; + }; + + LargeSymbolPath.prototype.buildPath = function (path, shape) { + var points = shape.points; + var size = shape.size; + var symbolProxy = this.symbolProxy; + var symbolProxyShape = symbolProxy.shape; + var ctx = path.getContext ? path.getContext() : path; + var canBoost = ctx && size[0] < BOOST_SIZE_THRESHOLD; + var softClipShape = this.softClipShape; + var i; // Do draw in afterBrush. + + if (canBoost) { + this._ctx = ctx; + return; + } + + this._ctx = null; + + for (i = this._off; i < points.length;) { + var x = points[i++]; + var y = points[i++]; + + if (isNaN(x) || isNaN(y)) { + continue; + } + + if (softClipShape && !softClipShape.contain(x, y)) { + continue; + } + + symbolProxyShape.x = x - size[0] / 2; + symbolProxyShape.y = y - size[1] / 2; + symbolProxyShape.width = size[0]; + symbolProxyShape.height = size[1]; + symbolProxy.buildPath(path, symbolProxyShape, true); + } + + if (this.incremental) { + this._off = i; + this.notClear = true; + } + }; + + LargeSymbolPath.prototype.afterBrush = function () { + var shape = this.shape; + var points = shape.points; + var size = shape.size; + var ctx = this._ctx; + var softClipShape = this.softClipShape; + var i; + + if (!ctx) { + return; + } // PENDING If style or other canvas status changed? + + + for (i = this._off; i < points.length;) { + var x = points[i++]; + var y = points[i++]; + + if (isNaN(x) || isNaN(y)) { + continue; + } + + if (softClipShape && !softClipShape.contain(x, y)) { + continue; + } // fillRect is faster than building a rect path and draw. + // And it support light globalCompositeOperation. + + + ctx.fillRect(x - size[0] / 2, y - size[1] / 2, size[0], size[1]); + } + + if (this.incremental) { + this._off = i; + this.notClear = true; + } + }; + + LargeSymbolPath.prototype.findDataIndex = function (x, y) { + // TODO ??? + // Consider transform + var shape = this.shape; + var points = shape.points; + var size = shape.size; + var w = Math.max(size[0], 4); + var h = Math.max(size[1], 4); // Not consider transform + // Treat each element as a rect + // top down traverse + + for (var idx = points.length / 2 - 1; idx >= 0; idx--) { + var i = idx * 2; + var x0 = points[i] - w / 2; + var y0 = points[i + 1] - h / 2; + + if (x >= x0 && y >= y0 && x <= x0 + w && y <= y0 + h) { + return idx; + } + } + + return -1; + }; + + LargeSymbolPath.prototype.contain = function (x, y) { + var localPos = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + x = localPos[0]; + y = localPos[1]; + + if (rect.contain(x, y)) { + // Cache found data index. + var dataIdx = this.hoverDataIdx = this.findDataIndex(x, y); + return dataIdx >= 0; + } + + this.hoverDataIdx = -1; + return false; + }; + + LargeSymbolPath.prototype.getBoundingRect = function () { + // Ignore stroke for large symbol draw. + var rect = this._rect; + + if (!rect) { + var shape = this.shape; + var points = shape.points; + var size = shape.size; + var w = size[0]; + var h = size[1]; + var minX = Infinity; + var minY = Infinity; + var maxX = -Infinity; + var maxY = -Infinity; + + for (var i = 0; i < points.length;) { + var x = points[i++]; + var y = points[i++]; + minX = Math.min(x, minX); + maxX = Math.max(x, maxX); + minY = Math.min(y, minY); + maxY = Math.max(y, maxY); + } + + rect = this._rect = new BoundingRect(minX - w / 2, minY - h / 2, maxX - minX + w, maxY - minY + h); + } + + return rect; + }; + + return LargeSymbolPath; + }(Path); + + var LargeSymbolDraw = + /** @class */ + function () { + function LargeSymbolDraw() { + this.group = new Group(); + } + /** + * Update symbols draw by new data + */ + + + LargeSymbolDraw.prototype.updateData = function (data, opt) { + this._clear(); + + var symbolEl = this._create(); + + symbolEl.setShape({ + points: data.getLayout('points') + }); + + this._setCommon(symbolEl, data, opt); + }; + + LargeSymbolDraw.prototype.updateLayout = function (data) { + var points = data.getLayout('points'); + this.group.eachChild(function (child) { + if (child.startIndex != null) { + var len = (child.endIndex - child.startIndex) * 2; + var byteOffset = child.startIndex * 4 * 2; + points = new Float32Array(points.buffer, byteOffset, len); + } + + child.setShape('points', points); // Reset draw cursor. + + child.reset(); + }); + }; + + LargeSymbolDraw.prototype.incrementalPrepareUpdate = function (data) { + this._clear(); + }; + + LargeSymbolDraw.prototype.incrementalUpdate = function (taskParams, data, opt) { + var lastAdded = this._newAdded[0]; + var points = data.getLayout('points'); + var oldPoints = lastAdded && lastAdded.shape.points; // Merging the exists. Each element has 1e4 points. + // Consider the performance balance between too much elements and too much points in one shape(may affect hover optimization) + + if (oldPoints && oldPoints.length < 2e4) { + var oldLen = oldPoints.length; + var newPoints = new Float32Array(oldLen + points.length); // Concat two array + + newPoints.set(oldPoints); + newPoints.set(points, oldLen); // Update endIndex + + lastAdded.endIndex = taskParams.end; + lastAdded.setShape({ + points: newPoints + }); + } else { + // Clear + this._newAdded = []; + + var symbolEl = this._create(); + + symbolEl.startIndex = taskParams.start; + symbolEl.endIndex = taskParams.end; + symbolEl.incremental = true; + symbolEl.setShape({ + points: points + }); + + this._setCommon(symbolEl, data, opt); + } + }; + + LargeSymbolDraw.prototype.eachRendered = function (cb) { + this._newAdded[0] && cb(this._newAdded[0]); + }; + + LargeSymbolDraw.prototype._create = function () { + var symbolEl = new LargeSymbolPath({ + cursor: 'default' + }); + this.group.add(symbolEl); + + this._newAdded.push(symbolEl); + + return symbolEl; + }; + + LargeSymbolDraw.prototype._setCommon = function (symbolEl, data, opt) { + var hostModel = data.hostModel; + opt = opt || {}; + var size = data.getVisual('symbolSize'); + symbolEl.setShape('size', size instanceof Array ? size : [size, size]); + symbolEl.softClipShape = opt.clipShape || null; // Create symbolProxy to build path for each data + + symbolEl.symbolProxy = createSymbol(data.getVisual('symbol'), 0, 0, 0, 0); // Use symbolProxy setColor method + + symbolEl.setColor = symbolEl.symbolProxy.setColor; + var extrudeShadow = symbolEl.shape.size[0] < BOOST_SIZE_THRESHOLD; + symbolEl.useStyle( // Draw shadow when doing fillRect is extremely slow. + hostModel.getModel('itemStyle').getItemStyle(extrudeShadow ? ['color', 'shadowBlur', 'shadowColor'] : ['color'])); + var globalStyle = data.getVisual('style'); + var visualColor = globalStyle && globalStyle.fill; + + if (visualColor) { + symbolEl.setColor(visualColor); + } + + var ecData = getECData(symbolEl); // Enable tooltip + // PENDING May have performance issue when path is extremely large + + ecData.seriesIndex = hostModel.seriesIndex; + symbolEl.on('mousemove', function (e) { + ecData.dataIndex = null; + var dataIndex = symbolEl.hoverDataIdx; + + if (dataIndex >= 0) { + // Provide dataIndex for tooltip + ecData.dataIndex = dataIndex + (symbolEl.startIndex || 0); + } + }); + }; + + LargeSymbolDraw.prototype.remove = function () { + this._clear(); + }; + + LargeSymbolDraw.prototype._clear = function () { + this._newAdded = []; + this.group.removeAll(); + }; + + return LargeSymbolDraw; + }(); + + var ScatterView = + /** @class */ + function (_super) { + __extends(ScatterView, _super); + + function ScatterView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ScatterView.type; + return _this; + } + + ScatterView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var symbolDraw = this._updateSymbolDraw(data, seriesModel); + + symbolDraw.updateData(data, { + // TODO + // If this parameter should be a shape or a bounding volume + // shape will be more general. + // But bounding volume like bounding rect will be much faster in the contain calculation + clipShape: this._getClipShape(seriesModel) + }); + this._finished = true; + }; + + ScatterView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var symbolDraw = this._updateSymbolDraw(data, seriesModel); + + symbolDraw.incrementalPrepareUpdate(data); + this._finished = false; + }; + + ScatterView.prototype.incrementalRender = function (taskParams, seriesModel, ecModel) { + this._symbolDraw.incrementalUpdate(taskParams, seriesModel.getData(), { + clipShape: this._getClipShape(seriesModel) + }); + + this._finished = taskParams.end === seriesModel.getData().count(); + }; + + ScatterView.prototype.updateTransform = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); // Must mark group dirty and make sure the incremental layer will be cleared + // PENDING + + this.group.dirty(); + + if (!this._finished || data.count() > 1e4) { + return { + update: true + }; + } else { + var res = pointsLayout('').reset(seriesModel, ecModel, api); + + if (res.progress) { + res.progress({ + start: 0, + end: data.count(), + count: data.count() + }, data); + } + + this._symbolDraw.updateLayout(data); + } + }; + + ScatterView.prototype.eachRendered = function (cb) { + this._symbolDraw && this._symbolDraw.eachRendered(cb); + }; + + ScatterView.prototype._getClipShape = function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var clipArea = coordSys && coordSys.getArea && coordSys.getArea(); + return seriesModel.get('clip', true) ? clipArea : null; + }; + + ScatterView.prototype._updateSymbolDraw = function (data, seriesModel) { + var symbolDraw = this._symbolDraw; + var pipelineContext = seriesModel.pipelineContext; + var isLargeDraw = pipelineContext.large; + + if (!symbolDraw || isLargeDraw !== this._isLargeDraw) { + symbolDraw && symbolDraw.remove(); + symbolDraw = this._symbolDraw = isLargeDraw ? new LargeSymbolDraw() : new SymbolDraw(); + this._isLargeDraw = isLargeDraw; + this.group.removeAll(); + } + + this.group.add(symbolDraw.group); + return symbolDraw; + }; + + ScatterView.prototype.remove = function (ecModel, api) { + this._symbolDraw && this._symbolDraw.remove(true); + this._symbolDraw = null; + }; + + ScatterView.prototype.dispose = function () {}; + + ScatterView.type = 'scatter'; + return ScatterView; + }(ChartView); + + var GridModel = + /** @class */ + function (_super) { + __extends(GridModel, _super); + + function GridModel() { + return _super !== null && _super.apply(this, arguments) || this; + } + + GridModel.type = 'grid'; + GridModel.dependencies = ['xAxis', 'yAxis']; + GridModel.layoutMode = 'box'; + GridModel.defaultOption = { + show: false, + // zlevel: 0, + z: 0, + left: '10%', + top: 60, + right: '10%', + bottom: 70, + // If grid size contain label + containLabel: false, + // width: {totalWidth} - left - right, + // height: {totalHeight} - top - bottom, + backgroundColor: 'rgba(0,0,0,0)', + borderWidth: 1, + borderColor: '#ccc' + }; + return GridModel; + }(ComponentModel); + + var CartesianAxisModel = + /** @class */ + function (_super) { + __extends(CartesianAxisModel, _super); + + function CartesianAxisModel() { + return _super !== null && _super.apply(this, arguments) || this; + } + + CartesianAxisModel.prototype.getCoordSysModel = function () { + return this.getReferringComponents('grid', SINGLE_REFERRING).models[0]; + }; + + CartesianAxisModel.type = 'cartesian2dAxis'; + return CartesianAxisModel; + }(ComponentModel); + mixin(CartesianAxisModel, AxisModelCommonMixin); + + var defaultOption = { + show: true, + // zlevel: 0, + z: 0, + // Inverse the axis. + inverse: false, + // Axis name displayed. + name: '', + // 'start' | 'middle' | 'end' + nameLocation: 'end', + // By degree. By default auto rotate by nameLocation. + nameRotate: null, + nameTruncate: { + maxWidth: null, + ellipsis: '...', + placeholder: '.' + }, + // Use global text style by default. + nameTextStyle: {}, + // The gap between axisName and axisLine. + nameGap: 15, + // Default `false` to support tooltip. + silent: false, + // Default `false` to avoid legacy user event listener fail. + triggerEvent: false, + tooltip: { + show: false + }, + axisPointer: {}, + axisLine: { + show: true, + onZero: true, + onZeroAxisIndex: null, + lineStyle: { + color: '#6E7079', + width: 1, + type: 'solid' + }, + // The arrow at both ends the the axis. + symbol: ['none', 'none'], + symbolSize: [10, 15] + }, + axisTick: { + show: true, + // Whether axisTick is inside the grid or outside the grid. + inside: false, + // The length of axisTick. + length: 5, + lineStyle: { + width: 1 + } + }, + axisLabel: { + show: true, + // Whether axisLabel is inside the grid or outside the grid. + inside: false, + rotate: 0, + // true | false | null/undefined (auto) + showMinLabel: null, + // true | false | null/undefined (auto) + showMaxLabel: null, + margin: 8, + // formatter: null, + fontSize: 12 + }, + splitLine: { + show: true, + lineStyle: { + color: ['#E0E6F1'], + width: 1, + type: 'solid' + } + }, + splitArea: { + show: false, + areaStyle: { + color: ['rgba(250,250,250,0.2)', 'rgba(210,219,238,0.2)'] + } + } + }; + var categoryAxis = merge({ + // The gap at both ends of the axis. For categoryAxis, boolean. + boundaryGap: true, + // Set false to faster category collection. + deduplication: null, + // splitArea: { + // show: false + // }, + splitLine: { + show: false + }, + axisTick: { + // If tick is align with label when boundaryGap is true + alignWithLabel: false, + interval: 'auto' + }, + axisLabel: { + interval: 'auto' + } + }, defaultOption); + var valueAxis = merge({ + boundaryGap: [0, 0], + axisLine: { + // Not shown when other axis is categoryAxis in cartesian + show: 'auto' + }, + axisTick: { + // Not shown when other axis is categoryAxis in cartesian + show: 'auto' + }, + // TODO + // min/max: [30, datamin, 60] or [20, datamin] or [datamin, 60] + splitNumber: 5, + minorTick: { + // Minor tick, not available for cateogry axis. + show: false, + // Split number of minor ticks. The value should be in range of (0, 100) + splitNumber: 5, + // Lenght of minor tick + length: 3, + // Line style + lineStyle: {// Default to be same with axisTick + } + }, + minorSplitLine: { + show: false, + lineStyle: { + color: '#F4F7FD', + width: 1 + } + } + }, defaultOption); + var timeAxis = merge({ + splitNumber: 6, + axisLabel: { + // To eliminate labels that are not nice + showMinLabel: false, + showMaxLabel: false, + rich: { + primary: { + fontWeight: 'bold' + } + } + }, + splitLine: { + show: false + } + }, valueAxis); + var logAxis = defaults({ + logBase: 10 + }, valueAxis); + var axisDefault = { + category: categoryAxis, + value: valueAxis, + time: timeAxis, + log: logAxis + }; + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var AXIS_TYPES = { + value: 1, + category: 1, + time: 1, + log: 1 + }; + + /** + * Generate sub axis model class + * @param axisName 'x' 'y' 'radius' 'angle' 'parallel' ... + */ + + function axisModelCreator(registers, axisName, BaseAxisModelClass, extraDefaultOption) { + each(AXIS_TYPES, function (v, axisType) { + var defaultOption = merge(merge({}, axisDefault[axisType], true), extraDefaultOption, true); + + var AxisModel = + /** @class */ + function (_super) { + __extends(AxisModel, _super); + + function AxisModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = axisName + 'Axis.' + axisType; + return _this; + } + + AxisModel.prototype.mergeDefaultAndTheme = function (option, ecModel) { + var layoutMode = fetchLayoutMode(this); + var inputPositionParams = layoutMode ? getLayoutParams(option) : {}; + var themeModel = ecModel.getTheme(); + merge(option, themeModel.get(axisType + 'Axis')); + merge(option, this.getDefaultOption()); + option.type = getAxisType(option); + + if (layoutMode) { + mergeLayoutParam(option, inputPositionParams, layoutMode); + } + }; + + AxisModel.prototype.optionUpdated = function () { + var thisOption = this.option; + + if (thisOption.type === 'category') { + this.__ordinalMeta = OrdinalMeta.createByAxisModel(this); + } + }; + /** + * Should not be called before all of 'getInitailData' finished. + * Because categories are collected during initializing data. + */ + + + AxisModel.prototype.getCategories = function (rawData) { + var option = this.option; // FIXME + // warning if called before all of 'getInitailData' finished. + + if (option.type === 'category') { + if (rawData) { + return option.data; + } + + return this.__ordinalMeta.categories; + } + }; + + AxisModel.prototype.getOrdinalMeta = function () { + return this.__ordinalMeta; + }; + + AxisModel.type = axisName + 'Axis.' + axisType; + AxisModel.defaultOption = defaultOption; + return AxisModel; + }(BaseAxisModelClass); + + registers.registerComponentModel(AxisModel); + }); + registers.registerSubTypeDefaulter(axisName + 'Axis', getAxisType); + } + + function getAxisType(option) { + // Default axis with data is category axis + return option.type || (option.data ? 'category' : 'value'); + } + + var Cartesian = + /** @class */ + function () { + function Cartesian(name) { + this.type = 'cartesian'; + this._dimList = []; + this._axes = {}; + this.name = name || ''; + } + + Cartesian.prototype.getAxis = function (dim) { + return this._axes[dim]; + }; + + Cartesian.prototype.getAxes = function () { + return map(this._dimList, function (dim) { + return this._axes[dim]; + }, this); + }; + + Cartesian.prototype.getAxesByScale = function (scaleType) { + scaleType = scaleType.toLowerCase(); + return filter(this.getAxes(), function (axis) { + return axis.scale.type === scaleType; + }); + }; + + Cartesian.prototype.addAxis = function (axis) { + var dim = axis.dim; + this._axes[dim] = axis; + + this._dimList.push(dim); + }; + + return Cartesian; + }(); + + var cartesian2DDimensions = ['x', 'y']; + + function canCalculateAffineTransform(scale) { + return scale.type === 'interval' || scale.type === 'time'; + } + + var Cartesian2D = + /** @class */ + function (_super) { + __extends(Cartesian2D, _super); + + function Cartesian2D() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'cartesian2d'; + _this.dimensions = cartesian2DDimensions; + return _this; + } + /** + * Calculate an affine transform matrix if two axes are time or value. + * It's mainly for accelartion on the large time series data. + */ + + + Cartesian2D.prototype.calcAffineTransform = function () { + this._transform = this._invTransform = null; + var xAxisScale = this.getAxis('x').scale; + var yAxisScale = this.getAxis('y').scale; + + if (!canCalculateAffineTransform(xAxisScale) || !canCalculateAffineTransform(yAxisScale)) { + return; + } + + var xScaleExtent = xAxisScale.getExtent(); + var yScaleExtent = yAxisScale.getExtent(); + var start = this.dataToPoint([xScaleExtent[0], yScaleExtent[0]]); + var end = this.dataToPoint([xScaleExtent[1], yScaleExtent[1]]); + var xScaleSpan = xScaleExtent[1] - xScaleExtent[0]; + var yScaleSpan = yScaleExtent[1] - yScaleExtent[0]; + + if (!xScaleSpan || !yScaleSpan) { + return; + } // Accelerate data to point calculation on the special large time series data. + + + var scaleX = (end[0] - start[0]) / xScaleSpan; + var scaleY = (end[1] - start[1]) / yScaleSpan; + var translateX = start[0] - xScaleExtent[0] * scaleX; + var translateY = start[1] - yScaleExtent[0] * scaleY; + var m = this._transform = [scaleX, 0, 0, scaleY, translateX, translateY]; + this._invTransform = invert([], m); + }; + /** + * Base axis will be used on stacking. + */ + + + Cartesian2D.prototype.getBaseAxis = function () { + return this.getAxesByScale('ordinal')[0] || this.getAxesByScale('time')[0] || this.getAxis('x'); + }; + + Cartesian2D.prototype.containPoint = function (point) { + var axisX = this.getAxis('x'); + var axisY = this.getAxis('y'); + return axisX.contain(axisX.toLocalCoord(point[0])) && axisY.contain(axisY.toLocalCoord(point[1])); + }; + + Cartesian2D.prototype.containData = function (data) { + return this.getAxis('x').containData(data[0]) && this.getAxis('y').containData(data[1]); + }; + + Cartesian2D.prototype.dataToPoint = function (data, clamp, out) { + out = out || []; + var xVal = data[0]; + var yVal = data[1]; // Fast path + + if (this._transform // It's supported that if data is like `[Inifity, 123]`, where only Y pixel calculated. + && xVal != null && isFinite(xVal) && yVal != null && isFinite(yVal)) { + return applyTransform(out, data, this._transform); + } + + var xAxis = this.getAxis('x'); + var yAxis = this.getAxis('y'); + out[0] = xAxis.toGlobalCoord(xAxis.dataToCoord(xVal, clamp)); + out[1] = yAxis.toGlobalCoord(yAxis.dataToCoord(yVal, clamp)); + return out; + }; + + Cartesian2D.prototype.clampData = function (data, out) { + var xScale = this.getAxis('x').scale; + var yScale = this.getAxis('y').scale; + var xAxisExtent = xScale.getExtent(); + var yAxisExtent = yScale.getExtent(); + var x = xScale.parse(data[0]); + var y = yScale.parse(data[1]); + out = out || []; + out[0] = Math.min(Math.max(Math.min(xAxisExtent[0], xAxisExtent[1]), x), Math.max(xAxisExtent[0], xAxisExtent[1])); + out[1] = Math.min(Math.max(Math.min(yAxisExtent[0], yAxisExtent[1]), y), Math.max(yAxisExtent[0], yAxisExtent[1])); + return out; + }; + + Cartesian2D.prototype.pointToData = function (point, clamp) { + var out = []; + + if (this._invTransform) { + return applyTransform(out, point, this._invTransform); + } + + var xAxis = this.getAxis('x'); + var yAxis = this.getAxis('y'); + out[0] = xAxis.coordToData(xAxis.toLocalCoord(point[0]), clamp); + out[1] = yAxis.coordToData(yAxis.toLocalCoord(point[1]), clamp); + return out; + }; + + Cartesian2D.prototype.getOtherAxis = function (axis) { + return this.getAxis(axis.dim === 'x' ? 'y' : 'x'); + }; + /** + * Get rect area of cartesian. + * Area will have a contain function to determine if a point is in the coordinate system. + */ + + + Cartesian2D.prototype.getArea = function () { + var xExtent = this.getAxis('x').getGlobalExtent(); + var yExtent = this.getAxis('y').getGlobalExtent(); + var x = Math.min(xExtent[0], xExtent[1]); + var y = Math.min(yExtent[0], yExtent[1]); + var width = Math.max(xExtent[0], xExtent[1]) - x; + var height = Math.max(yExtent[0], yExtent[1]) - y; + return new BoundingRect(x, y, width, height); + }; + + return Cartesian2D; + }(Cartesian); + + var Axis2D = + /** @class */ + function (_super) { + __extends(Axis2D, _super); + + function Axis2D(dim, scale, coordExtent, axisType, position) { + var _this = _super.call(this, dim, scale, coordExtent) || this; + /** + * Index of axis, can be used as key + * Injected outside. + */ + + + _this.index = 0; + _this.type = axisType || 'value'; + _this.position = position || 'bottom'; + return _this; + } + + Axis2D.prototype.isHorizontal = function () { + var position = this.position; + return position === 'top' || position === 'bottom'; + }; + /** + * Each item cooresponds to this.getExtent(), which + * means globalExtent[0] may greater than globalExtent[1], + * unless `asc` is input. + * + * @param {boolean} [asc] + * @return {Array.} + */ + + + Axis2D.prototype.getGlobalExtent = function (asc) { + var ret = this.getExtent(); + ret[0] = this.toGlobalCoord(ret[0]); + ret[1] = this.toGlobalCoord(ret[1]); + asc && ret[0] > ret[1] && ret.reverse(); + return ret; + }; + + Axis2D.prototype.pointToData = function (point, clamp) { + return this.coordToData(this.toLocalCoord(point[this.dim === 'x' ? 0 : 1]), clamp); + }; + /** + * Set ordinalSortInfo + * @param info new OrdinalSortInfo + */ + + + Axis2D.prototype.setCategorySortInfo = function (info) { + if (this.type !== 'category') { + return false; + } + + this.model.option.categorySortInfo = info; + this.scale.setSortInfo(info); + }; + + return Axis2D; + }(Axis); + + /** + * Can only be called after coordinate system creation stage. + * (Can be called before coordinate system update stage). + */ + + function layout$1(gridModel, axisModel, opt) { + opt = opt || {}; + var grid = gridModel.coordinateSystem; + var axis = axisModel.axis; + var layout = {}; + var otherAxisOnZeroOf = axis.getAxesOnZeroOf()[0]; + var rawAxisPosition = axis.position; + var axisPosition = otherAxisOnZeroOf ? 'onZero' : rawAxisPosition; + var axisDim = axis.dim; + var rect = grid.getRect(); + var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height]; + var idx = { + left: 0, + right: 1, + top: 0, + bottom: 1, + onZero: 2 + }; + var axisOffset = axisModel.get('offset') || 0; + var posBound = axisDim === 'x' ? [rectBound[2] - axisOffset, rectBound[3] + axisOffset] : [rectBound[0] - axisOffset, rectBound[1] + axisOffset]; + + if (otherAxisOnZeroOf) { + var onZeroCoord = otherAxisOnZeroOf.toGlobalCoord(otherAxisOnZeroOf.dataToCoord(0)); + posBound[idx.onZero] = Math.max(Math.min(onZeroCoord, posBound[1]), posBound[0]); + } // Axis position + + + layout.position = [axisDim === 'y' ? posBound[idx[axisPosition]] : rectBound[0], axisDim === 'x' ? posBound[idx[axisPosition]] : rectBound[3]]; // Axis rotation + + layout.rotation = Math.PI / 2 * (axisDim === 'x' ? 0 : 1); // Tick and label direction, x y is axisDim + + var dirMap = { + top: -1, + bottom: 1, + left: -1, + right: 1 + }; + layout.labelDirection = layout.tickDirection = layout.nameDirection = dirMap[rawAxisPosition]; + layout.labelOffset = otherAxisOnZeroOf ? posBound[idx[rawAxisPosition]] - posBound[idx.onZero] : 0; + + if (axisModel.get(['axisTick', 'inside'])) { + layout.tickDirection = -layout.tickDirection; + } + + if (retrieve(opt.labelInside, axisModel.get(['axisLabel', 'inside']))) { + layout.labelDirection = -layout.labelDirection; + } // Special label rotation + + + var labelRotate = axisModel.get(['axisLabel', 'rotate']); + layout.labelRotate = axisPosition === 'top' ? -labelRotate : labelRotate; // Over splitLine and splitArea + + layout.z2 = 1; + return layout; + } + function isCartesian2DSeries(seriesModel) { + return seriesModel.get('coordinateSystem') === 'cartesian2d'; + } + function findAxisModels(seriesModel) { + var axisModelMap = { + xAxisModel: null, + yAxisModel: null + }; + each(axisModelMap, function (v, key) { + var axisType = key.replace(/Model$/, ''); + var axisModel = seriesModel.getReferringComponents(axisType, SINGLE_REFERRING).models[0]; + + if ("development" !== 'production') { + if (!axisModel) { + throw new Error(axisType + ' "' + retrieve3(seriesModel.get(axisType + 'Index'), seriesModel.get(axisType + 'Id'), 0) + '" not found'); + } + } + + axisModelMap[key] = axisModel; + }); + return axisModelMap; + } + + var mathLog$1 = Math.log; + function alignScaleTicks(scale, axisModel, alignToScale) { + var intervalScaleProto = IntervalScale.prototype; // NOTE: There is a precondition for log scale here: + // In log scale we store _interval and _extent of exponent value. + // So if we use the method of InternalScale to set/get these data. + // It process the exponent value, which is linear and what we want here. + + var alignToTicks = intervalScaleProto.getTicks.call(alignToScale); + var alignToNicedTicks = intervalScaleProto.getTicks.call(alignToScale, true); + var alignToSplitNumber = alignToTicks.length - 1; + var alignToInterval = intervalScaleProto.getInterval.call(alignToScale); + var scaleExtent = getScaleExtent(scale, axisModel); + var rawExtent = scaleExtent.extent; + var isMinFixed = scaleExtent.fixMin; + var isMaxFixed = scaleExtent.fixMax; + + if (scale.type === 'log') { + var logBase = mathLog$1(scale.base); + rawExtent = [mathLog$1(rawExtent[0]) / logBase, mathLog$1(rawExtent[1]) / logBase]; + } + + scale.setExtent(rawExtent[0], rawExtent[1]); + scale.calcNiceExtent({ + splitNumber: alignToSplitNumber, + fixMin: isMinFixed, + fixMax: isMaxFixed + }); + var extent = intervalScaleProto.getExtent.call(scale); // Need to update the rawExtent. + // Because value in rawExtent may be not parsed. e.g. 'dataMin', 'dataMax' + + if (isMinFixed) { + rawExtent[0] = extent[0]; + } + + if (isMaxFixed) { + rawExtent[1] = extent[1]; + } + + var interval = intervalScaleProto.getInterval.call(scale); + var min = rawExtent[0]; + var max = rawExtent[1]; + + if (isMinFixed && isMaxFixed) { + // User set min, max, divide to get new interval + interval = (max - min) / alignToSplitNumber; + } else if (isMinFixed) { + max = rawExtent[0] + interval * alignToSplitNumber; // User set min, expand extent on the other side + + while (max < rawExtent[1] && isFinite(max) && isFinite(rawExtent[1])) { + interval = increaseInterval(interval); + max = rawExtent[0] + interval * alignToSplitNumber; + } + } else if (isMaxFixed) { + // User set max, expand extent on the other side + min = rawExtent[1] - interval * alignToSplitNumber; + + while (min > rawExtent[0] && isFinite(min) && isFinite(rawExtent[0])) { + interval = increaseInterval(interval); + min = rawExtent[1] - interval * alignToSplitNumber; + } + } else { + var nicedSplitNumber = scale.getTicks().length - 1; + + if (nicedSplitNumber > alignToSplitNumber) { + interval = increaseInterval(interval); + } + + var range = interval * alignToSplitNumber; + max = Math.ceil(rawExtent[1] / interval) * interval; + min = round(max - range); // Not change the result that crossing zero. + + if (min < 0 && rawExtent[0] >= 0) { + min = 0; + max = round(range); + } else if (max > 0 && rawExtent[1] <= 0) { + max = 0; + min = -round(range); + } + } // Adjust min, max based on the extent of alignTo. When min or max is set in alignTo scale + + + var t0 = (alignToTicks[0].value - alignToNicedTicks[0].value) / alignToInterval; + var t1 = (alignToTicks[alignToSplitNumber].value - alignToNicedTicks[alignToSplitNumber].value) / alignToInterval; // NOTE: Must in setExtent -> setInterval -> setNiceExtent order. + + intervalScaleProto.setExtent.call(scale, min + interval * t0, max + interval * t1); + intervalScaleProto.setInterval.call(scale, interval); + + if (t0 || t1) { + intervalScaleProto.setNiceExtent.call(scale, min + interval, max - interval); + } + + if ("development" !== 'production') { + var ticks = intervalScaleProto.getTicks.call(scale); + + if (ticks[1] && (!isValueNice(interval) || getPrecisionSafe(ticks[1].value) > getPrecisionSafe(interval))) { + warn( // eslint-disable-next-line + "The ticks may be not readable when set min: " + axisModel.get('min') + ", max: " + axisModel.get('max') + " and alignTicks: true"); + } + } + } + + var Grid = + /** @class */ + function () { + function Grid(gridModel, ecModel, api) { + // FIXME:TS where used (different from registered type 'cartesian2d')? + this.type = 'grid'; + this._coordsMap = {}; + this._coordsList = []; + this._axesMap = {}; + this._axesList = []; + this.axisPointerEnabled = true; + this.dimensions = cartesian2DDimensions; + + this._initCartesian(gridModel, ecModel, api); + + this.model = gridModel; + } + + Grid.prototype.getRect = function () { + return this._rect; + }; + + Grid.prototype.update = function (ecModel, api) { + var axesMap = this._axesMap; + + this._updateScale(ecModel, this.model); + + function updateAxisTicks(axes) { + var alignTo; // Axis is added in order of axisIndex. + + var axesIndices = keys(axes); + var len = axesIndices.length; + + if (!len) { + return; + } + + var axisNeedsAlign = []; // Process once and calculate the ticks for those don't use alignTicks. + + for (var i = len - 1; i >= 0; i--) { + var idx = +axesIndices[i]; // Convert to number. + + var axis = axes[idx]; + var model = axis.model; + var scale = axis.scale; + + if ( // Only value and log axis without interval support alignTicks. + isIntervalOrLogScale(scale) && model.get('alignTicks') && model.get('interval') == null) { + axisNeedsAlign.push(axis); + } else { + niceScaleExtent(scale, model); + + if (isIntervalOrLogScale(scale)) { + // Can only align to interval or log axis. + alignTo = axis; + } + } + } + // PENDING. Should we find the axis that both set interval, min, max and align to this one? + + if (axisNeedsAlign.length) { + if (!alignTo) { + alignTo = axisNeedsAlign.pop(); + niceScaleExtent(alignTo.scale, alignTo.model); + } + + each(axisNeedsAlign, function (axis) { + alignScaleTicks(axis.scale, axis.model, alignTo.scale); + }); + } + } + + updateAxisTicks(axesMap.x); + updateAxisTicks(axesMap.y); // Key: axisDim_axisIndex, value: boolean, whether onZero target. + + var onZeroRecords = {}; + each(axesMap.x, function (xAxis) { + fixAxisOnZero(axesMap, 'y', xAxis, onZeroRecords); + }); + each(axesMap.y, function (yAxis) { + fixAxisOnZero(axesMap, 'x', yAxis, onZeroRecords); + }); // Resize again if containLabel is enabled + // FIXME It may cause getting wrong grid size in data processing stage + + this.resize(this.model, api); + }; + /** + * Resize the grid + */ + + + Grid.prototype.resize = function (gridModel, api, ignoreContainLabel) { + var boxLayoutParams = gridModel.getBoxLayoutParams(); + var isContainLabel = !ignoreContainLabel && gridModel.get('containLabel'); + var gridRect = getLayoutRect(boxLayoutParams, { + width: api.getWidth(), + height: api.getHeight() + }); + this._rect = gridRect; + var axesList = this._axesList; + adjustAxes(); // Minus label size + + if (isContainLabel) { + each(axesList, function (axis) { + if (!axis.model.get(['axisLabel', 'inside'])) { + var labelUnionRect = estimateLabelUnionRect(axis); + + if (labelUnionRect) { + var dim = axis.isHorizontal() ? 'height' : 'width'; + var margin = axis.model.get(['axisLabel', 'margin']); + gridRect[dim] -= labelUnionRect[dim] + margin; + + if (axis.position === 'top') { + gridRect.y += labelUnionRect.height + margin; + } else if (axis.position === 'left') { + gridRect.x += labelUnionRect.width + margin; + } + } + } + }); + adjustAxes(); + } + + each(this._coordsList, function (coord) { + // Calculate affine matrix to accelerate the data to point transform. + // If all the axes scales are time or value. + coord.calcAffineTransform(); + }); + + function adjustAxes() { + each(axesList, function (axis) { + var isHorizontal = axis.isHorizontal(); + var extent = isHorizontal ? [0, gridRect.width] : [0, gridRect.height]; + var idx = axis.inverse ? 1 : 0; + axis.setExtent(extent[idx], extent[1 - idx]); + updateAxisTransform(axis, isHorizontal ? gridRect.x : gridRect.y); + }); + } + }; + + Grid.prototype.getAxis = function (dim, axisIndex) { + var axesMapOnDim = this._axesMap[dim]; + + if (axesMapOnDim != null) { + return axesMapOnDim[axisIndex || 0]; + } + }; + + Grid.prototype.getAxes = function () { + return this._axesList.slice(); + }; + + Grid.prototype.getCartesian = function (xAxisIndex, yAxisIndex) { + if (xAxisIndex != null && yAxisIndex != null) { + var key = 'x' + xAxisIndex + 'y' + yAxisIndex; + return this._coordsMap[key]; + } + + if (isObject(xAxisIndex)) { + yAxisIndex = xAxisIndex.yAxisIndex; + xAxisIndex = xAxisIndex.xAxisIndex; + } + + for (var i = 0, coordList = this._coordsList; i < coordList.length; i++) { + if (coordList[i].getAxis('x').index === xAxisIndex || coordList[i].getAxis('y').index === yAxisIndex) { + return coordList[i]; + } + } + }; + + Grid.prototype.getCartesians = function () { + return this._coordsList.slice(); + }; + /** + * @implements + */ + + + Grid.prototype.convertToPixel = function (ecModel, finder, value) { + var target = this._findConvertTarget(finder); + + return target.cartesian ? target.cartesian.dataToPoint(value) : target.axis ? target.axis.toGlobalCoord(target.axis.dataToCoord(value)) : null; + }; + /** + * @implements + */ + + + Grid.prototype.convertFromPixel = function (ecModel, finder, value) { + var target = this._findConvertTarget(finder); + + return target.cartesian ? target.cartesian.pointToData(value) : target.axis ? target.axis.coordToData(target.axis.toLocalCoord(value)) : null; + }; + + Grid.prototype._findConvertTarget = function (finder) { + var seriesModel = finder.seriesModel; + var xAxisModel = finder.xAxisModel || seriesModel && seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0]; + var yAxisModel = finder.yAxisModel || seriesModel && seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0]; + var gridModel = finder.gridModel; + var coordsList = this._coordsList; + var cartesian; + var axis; + + if (seriesModel) { + cartesian = seriesModel.coordinateSystem; + indexOf(coordsList, cartesian) < 0 && (cartesian = null); + } else if (xAxisModel && yAxisModel) { + cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); + } else if (xAxisModel) { + axis = this.getAxis('x', xAxisModel.componentIndex); + } else if (yAxisModel) { + axis = this.getAxis('y', yAxisModel.componentIndex); + } // Lowest priority. + else if (gridModel) { + var grid = gridModel.coordinateSystem; + + if (grid === this) { + cartesian = this._coordsList[0]; + } + } + + return { + cartesian: cartesian, + axis: axis + }; + }; + /** + * @implements + */ + + + Grid.prototype.containPoint = function (point) { + var coord = this._coordsList[0]; + + if (coord) { + return coord.containPoint(point); + } + }; + /** + * Initialize cartesian coordinate systems + */ + + + Grid.prototype._initCartesian = function (gridModel, ecModel, api) { + var _this = this; + + var grid = this; + var axisPositionUsed = { + left: false, + right: false, + top: false, + bottom: false + }; + var axesMap = { + x: {}, + y: {} + }; + var axesCount = { + x: 0, + y: 0 + }; /// Create axis + + ecModel.eachComponent('xAxis', createAxisCreator('x'), this); + ecModel.eachComponent('yAxis', createAxisCreator('y'), this); + + if (!axesCount.x || !axesCount.y) { + // Roll back when there no either x or y axis + this._axesMap = {}; + this._axesList = []; + return; + } + + this._axesMap = axesMap; /// Create cartesian2d + + each(axesMap.x, function (xAxis, xAxisIndex) { + each(axesMap.y, function (yAxis, yAxisIndex) { + var key = 'x' + xAxisIndex + 'y' + yAxisIndex; + var cartesian = new Cartesian2D(key); + cartesian.master = _this; + cartesian.model = gridModel; + _this._coordsMap[key] = cartesian; + + _this._coordsList.push(cartesian); + + cartesian.addAxis(xAxis); + cartesian.addAxis(yAxis); + }); + }); + + function createAxisCreator(dimName) { + return function (axisModel, idx) { + if (!isAxisUsedInTheGrid(axisModel, gridModel)) { + return; + } + + var axisPosition = axisModel.get('position'); + + if (dimName === 'x') { + // Fix position + if (axisPosition !== 'top' && axisPosition !== 'bottom') { + // Default bottom of X + axisPosition = axisPositionUsed.bottom ? 'top' : 'bottom'; + } + } else { + // Fix position + if (axisPosition !== 'left' && axisPosition !== 'right') { + // Default left of Y + axisPosition = axisPositionUsed.left ? 'right' : 'left'; + } + } + + axisPositionUsed[axisPosition] = true; + var axis = new Axis2D(dimName, createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisPosition); + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); // Inject axis into axisModel + + axisModel.axis = axis; // Inject axisModel into axis + + axis.model = axisModel; // Inject grid info axis + + axis.grid = grid; // Index of axis, can be used as key + + axis.index = idx; + + grid._axesList.push(axis); + + axesMap[dimName][idx] = axis; + axesCount[dimName]++; + }; + } + }; + /** + * Update cartesian properties from series. + */ + + + Grid.prototype._updateScale = function (ecModel, gridModel) { + // Reset scale + each(this._axesList, function (axis) { + axis.scale.setExtent(Infinity, -Infinity); + + if (axis.type === 'category') { + var categorySortInfo = axis.model.get('categorySortInfo'); + axis.scale.setSortInfo(categorySortInfo); + } + }); + ecModel.eachSeries(function (seriesModel) { + if (isCartesian2DSeries(seriesModel)) { + var axesModelMap = findAxisModels(seriesModel); + var xAxisModel = axesModelMap.xAxisModel; + var yAxisModel = axesModelMap.yAxisModel; + + if (!isAxisUsedInTheGrid(xAxisModel, gridModel) || !isAxisUsedInTheGrid(yAxisModel, gridModel)) { + return; + } + + var cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); + var data = seriesModel.getData(); + var xAxis = cartesian.getAxis('x'); + var yAxis = cartesian.getAxis('y'); + unionExtent(data, xAxis); + unionExtent(data, yAxis); + } + }, this); + + function unionExtent(data, axis) { + each(getDataDimensionsOnAxis(data, axis.dim), function (dim) { + axis.scale.unionExtentFromData(data, dim); + }); + } + }; + /** + * @param dim 'x' or 'y' or 'auto' or null/undefined + */ + + + Grid.prototype.getTooltipAxes = function (dim) { + var baseAxes = []; + var otherAxes = []; + each(this.getCartesians(), function (cartesian) { + var baseAxis = dim != null && dim !== 'auto' ? cartesian.getAxis(dim) : cartesian.getBaseAxis(); + var otherAxis = cartesian.getOtherAxis(baseAxis); + indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis); + indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis); + }); + return { + baseAxes: baseAxes, + otherAxes: otherAxes + }; + }; + + Grid.create = function (ecModel, api) { + var grids = []; + ecModel.eachComponent('grid', function (gridModel, idx) { + var grid = new Grid(gridModel, ecModel, api); + grid.name = 'grid_' + idx; // dataSampling requires axis extent, so resize + // should be performed in create stage. + + grid.resize(gridModel, api, true); + gridModel.coordinateSystem = grid; + grids.push(grid); + }); // Inject the coordinateSystems into seriesModel + + ecModel.eachSeries(function (seriesModel) { + if (!isCartesian2DSeries(seriesModel)) { + return; + } + + var axesModelMap = findAxisModels(seriesModel); + var xAxisModel = axesModelMap.xAxisModel; + var yAxisModel = axesModelMap.yAxisModel; + var gridModel = xAxisModel.getCoordSysModel(); + + if ("development" !== 'production') { + if (!gridModel) { + throw new Error('Grid "' + retrieve3(xAxisModel.get('gridIndex'), xAxisModel.get('gridId'), 0) + '" not found'); + } + + if (xAxisModel.getCoordSysModel() !== yAxisModel.getCoordSysModel()) { + throw new Error('xAxis and yAxis must use the same grid'); + } + } + + var grid = gridModel.coordinateSystem; + seriesModel.coordinateSystem = grid.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); + }); + return grids; + }; // For deciding which dimensions to use when creating list data + + + Grid.dimensions = cartesian2DDimensions; + return Grid; + }(); + /** + * Check if the axis is used in the specified grid. + */ + + + function isAxisUsedInTheGrid(axisModel, gridModel) { + return axisModel.getCoordSysModel() === gridModel; + } + + function fixAxisOnZero(axesMap, otherAxisDim, axis, // Key: see `getOnZeroRecordKey` + onZeroRecords) { + axis.getAxesOnZeroOf = function () { + // TODO: onZero of multiple axes. + return otherAxisOnZeroOf ? [otherAxisOnZeroOf] : []; + }; // onZero can not be enabled in these two situations: + // 1. When any other axis is a category axis. + // 2. When no axis is cross 0 point. + + + var otherAxes = axesMap[otherAxisDim]; + var otherAxisOnZeroOf; + var axisModel = axis.model; + var onZero = axisModel.get(['axisLine', 'onZero']); + var onZeroAxisIndex = axisModel.get(['axisLine', 'onZeroAxisIndex']); + + if (!onZero) { + return; + } // If target axis is specified. + + + if (onZeroAxisIndex != null) { + if (canOnZeroToAxis(otherAxes[onZeroAxisIndex])) { + otherAxisOnZeroOf = otherAxes[onZeroAxisIndex]; + } + } else { + // Find the first available other axis. + for (var idx in otherAxes) { + if (otherAxes.hasOwnProperty(idx) && canOnZeroToAxis(otherAxes[idx]) // Consider that two Y axes on one value axis, + // if both onZero, the two Y axes overlap. + && !onZeroRecords[getOnZeroRecordKey(otherAxes[idx])]) { + otherAxisOnZeroOf = otherAxes[idx]; + break; + } + } + } + + if (otherAxisOnZeroOf) { + onZeroRecords[getOnZeroRecordKey(otherAxisOnZeroOf)] = true; + } + + function getOnZeroRecordKey(axis) { + return axis.dim + '_' + axis.index; + } + } + + function canOnZeroToAxis(axis) { + return axis && axis.type !== 'category' && axis.type !== 'time' && ifAxisCrossZero(axis); + } + + function updateAxisTransform(axis, coordBase) { + var axisExtent = axis.getExtent(); + var axisExtentSum = axisExtent[0] + axisExtent[1]; // Fast transform + + axis.toGlobalCoord = axis.dim === 'x' ? function (coord) { + return coord + coordBase; + } : function (coord) { + return axisExtentSum - coord + coordBase; + }; + axis.toLocalCoord = axis.dim === 'x' ? function (coord) { + return coord - coordBase; + } : function (coord) { + return axisExtentSum - coord + coordBase; + }; + } + + var PI$5 = Math.PI; + /** + * A final axis is translated and rotated from a "standard axis". + * So opt.position and opt.rotation is required. + * + * A standard axis is and axis from [0, 0] to [0, axisExtent[1]], + * for example: (0, 0) ------------> (0, 50) + * + * nameDirection or tickDirection or labelDirection is 1 means tick + * or label is below the standard axis, whereas is -1 means above + * the standard axis. labelOffset means offset between label and axis, + * which is useful when 'onZero', where axisLabel is in the grid and + * label in outside grid. + * + * Tips: like always, + * positive rotation represents anticlockwise, and negative rotation + * represents clockwise. + * The direction of position coordinate is the same as the direction + * of screen coordinate. + * + * Do not need to consider axis 'inverse', which is auto processed by + * axis extent. + */ + + var AxisBuilder = + /** @class */ + function () { + function AxisBuilder(axisModel, opt) { + this.group = new Group(); + this.opt = opt; + this.axisModel = axisModel; // Default value + + defaults(opt, { + labelOffset: 0, + nameDirection: 1, + tickDirection: 1, + labelDirection: 1, + silent: true, + handleAutoShown: function () { + return true; + } + }); // FIXME Not use a seperate text group? + + var transformGroup = new Group({ + x: opt.position[0], + y: opt.position[1], + rotation: opt.rotation + }); // this.group.add(transformGroup); + // this._transformGroup = transformGroup; + + transformGroup.updateTransform(); + this._transformGroup = transformGroup; + } + + AxisBuilder.prototype.hasBuilder = function (name) { + return !!builders[name]; + }; + + AxisBuilder.prototype.add = function (name) { + builders[name](this.opt, this.axisModel, this.group, this._transformGroup); + }; + + AxisBuilder.prototype.getGroup = function () { + return this.group; + }; + + AxisBuilder.innerTextLayout = function (axisRotation, textRotation, direction) { + var rotationDiff = remRadian(textRotation - axisRotation); + var textAlign; + var textVerticalAlign; + + if (isRadianAroundZero(rotationDiff)) { + // Label is parallel with axis line. + textVerticalAlign = direction > 0 ? 'top' : 'bottom'; + textAlign = 'center'; + } else if (isRadianAroundZero(rotationDiff - PI$5)) { + // Label is inverse parallel with axis line. + textVerticalAlign = direction > 0 ? 'bottom' : 'top'; + textAlign = 'center'; + } else { + textVerticalAlign = 'middle'; + + if (rotationDiff > 0 && rotationDiff < PI$5) { + textAlign = direction > 0 ? 'right' : 'left'; + } else { + textAlign = direction > 0 ? 'left' : 'right'; + } + } + + return { + rotation: rotationDiff, + textAlign: textAlign, + textVerticalAlign: textVerticalAlign + }; + }; + + AxisBuilder.makeAxisEventDataBase = function (axisModel) { + var eventData = { + componentType: axisModel.mainType, + componentIndex: axisModel.componentIndex + }; + eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex; + return eventData; + }; + + AxisBuilder.isLabelSilent = function (axisModel) { + var tooltipOpt = axisModel.get('tooltip'); + return axisModel.get('silent') // Consider mouse cursor, add these restrictions. + || !(axisModel.get('triggerEvent') || tooltipOpt && tooltipOpt.show); + }; + + return AxisBuilder; + }(); + var builders = { + axisLine: function (opt, axisModel, group, transformGroup) { + var shown = axisModel.get(['axisLine', 'show']); + + if (shown === 'auto' && opt.handleAutoShown) { + shown = opt.handleAutoShown('axisLine'); + } + + if (!shown) { + return; + } + + var extent = axisModel.axis.getExtent(); + var matrix = transformGroup.transform; + var pt1 = [extent[0], 0]; + var pt2 = [extent[1], 0]; + + if (matrix) { + applyTransform(pt1, pt1, matrix); + applyTransform(pt2, pt2, matrix); + } + + var lineStyle = extend({ + lineCap: 'round' + }, axisModel.getModel(['axisLine', 'lineStyle']).getLineStyle()); + var line = new Line({ + // Id for animation + subPixelOptimize: true, + shape: { + x1: pt1[0], + y1: pt1[1], + x2: pt2[0], + y2: pt2[1] + }, + style: lineStyle, + strokeContainThreshold: opt.strokeContainThreshold || 5, + silent: true, + z2: 1 + }); + line.anid = 'line'; + group.add(line); + var arrows = axisModel.get(['axisLine', 'symbol']); + + if (arrows != null) { + var arrowSize = axisModel.get(['axisLine', 'symbolSize']); + + if (isString(arrows)) { + // Use the same arrow for start and end point + arrows = [arrows, arrows]; + } + + if (isString(arrowSize) || isNumber(arrowSize)) { + // Use the same size for width and height + arrowSize = [arrowSize, arrowSize]; + } + + var arrowOffset = normalizeSymbolOffset(axisModel.get(['axisLine', 'symbolOffset']) || 0, arrowSize); + var symbolWidth_1 = arrowSize[0]; + var symbolHeight_1 = arrowSize[1]; + each([{ + rotate: opt.rotation + Math.PI / 2, + offset: arrowOffset[0], + r: 0 + }, { + rotate: opt.rotation - Math.PI / 2, + offset: arrowOffset[1], + r: Math.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0]) + (pt1[1] - pt2[1]) * (pt1[1] - pt2[1])) + }], function (point, index) { + if (arrows[index] !== 'none' && arrows[index] != null) { + var symbol = createSymbol(arrows[index], -symbolWidth_1 / 2, -symbolHeight_1 / 2, symbolWidth_1, symbolHeight_1, lineStyle.stroke, true); // Calculate arrow position with offset + + var r = point.r + point.offset; + symbol.attr({ + rotation: point.rotate, + x: pt1[0] + r * Math.cos(opt.rotation), + y: pt1[1] - r * Math.sin(opt.rotation), + silent: true, + z2: 11 + }); + group.add(symbol); + } + }); + } + }, + axisTickLabel: function (opt, axisModel, group, transformGroup) { + var ticksEls = buildAxisMajorTicks(group, transformGroup, axisModel, opt); + var labelEls = buildAxisLabel(group, transformGroup, axisModel, opt); + fixMinMaxLabelShow(axisModel, labelEls, ticksEls); + buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection); // This bit fixes the label overlap issue for the time chart. + // See https://github.com/apache/echarts/issues/14266 for more. + + if (axisModel.get(['axisLabel', 'hideOverlap'])) { + var labelList = prepareLayoutList(map(labelEls, function (label) { + return { + label: label, + priority: label.z2, + defaultAttr: { + ignore: label.ignore + } + }; + })); + hideOverlap(labelList); + } + }, + axisName: function (opt, axisModel, group, transformGroup) { + var name = retrieve(opt.axisName, axisModel.get('name')); + + if (!name) { + return; + } + + var nameLocation = axisModel.get('nameLocation'); + var nameDirection = opt.nameDirection; + var textStyleModel = axisModel.getModel('nameTextStyle'); + var gap = axisModel.get('nameGap') || 0; + var extent = axisModel.axis.getExtent(); + var gapSignal = extent[0] > extent[1] ? -1 : 1; + var pos = [nameLocation === 'start' ? extent[0] - gapSignal * gap : nameLocation === 'end' ? extent[1] + gapSignal * gap : (extent[0] + extent[1]) / 2, // Reuse labelOffset. + isNameLocationCenter(nameLocation) ? opt.labelOffset + nameDirection * gap : 0]; + var labelLayout; + var nameRotation = axisModel.get('nameRotate'); + + if (nameRotation != null) { + nameRotation = nameRotation * PI$5 / 180; // To radian. + } + + var axisNameAvailableWidth; + + if (isNameLocationCenter(nameLocation)) { + labelLayout = AxisBuilder.innerTextLayout(opt.rotation, nameRotation != null ? nameRotation : opt.rotation, // Adapt to axis. + nameDirection); + } else { + labelLayout = endTextLayout(opt.rotation, nameLocation, nameRotation || 0, extent); + axisNameAvailableWidth = opt.axisNameAvailableWidth; + + if (axisNameAvailableWidth != null) { + axisNameAvailableWidth = Math.abs(axisNameAvailableWidth / Math.sin(labelLayout.rotation)); + !isFinite(axisNameAvailableWidth) && (axisNameAvailableWidth = null); + } + } + + var textFont = textStyleModel.getFont(); + var truncateOpt = axisModel.get('nameTruncate', true) || {}; + var ellipsis = truncateOpt.ellipsis; + var maxWidth = retrieve(opt.nameTruncateMaxWidth, truncateOpt.maxWidth, axisNameAvailableWidth); + var textEl = new ZRText({ + x: pos[0], + y: pos[1], + rotation: labelLayout.rotation, + silent: AxisBuilder.isLabelSilent(axisModel), + style: createTextStyle(textStyleModel, { + text: name, + font: textFont, + overflow: 'truncate', + width: maxWidth, + ellipsis: ellipsis, + fill: textStyleModel.getTextColor() || axisModel.get(['axisLine', 'lineStyle', 'color']), + align: textStyleModel.get('align') || labelLayout.textAlign, + verticalAlign: textStyleModel.get('verticalAlign') || labelLayout.textVerticalAlign + }), + z2: 1 + }); + setTooltipConfig({ + el: textEl, + componentModel: axisModel, + itemName: name + }); + textEl.__fullText = name; // Id for animation + + textEl.anid = 'name'; + + if (axisModel.get('triggerEvent')) { + var eventData = AxisBuilder.makeAxisEventDataBase(axisModel); + eventData.targetType = 'axisName'; + eventData.name = name; + getECData(textEl).eventData = eventData; + } // FIXME + + + transformGroup.add(textEl); + textEl.updateTransform(); + group.add(textEl); + textEl.decomposeTransform(); + } + }; + + function endTextLayout(rotation, textPosition, textRotate, extent) { + var rotationDiff = remRadian(textRotate - rotation); + var textAlign; + var textVerticalAlign; + var inverse = extent[0] > extent[1]; + var onLeft = textPosition === 'start' && !inverse || textPosition !== 'start' && inverse; + + if (isRadianAroundZero(rotationDiff - PI$5 / 2)) { + textVerticalAlign = onLeft ? 'bottom' : 'top'; + textAlign = 'center'; + } else if (isRadianAroundZero(rotationDiff - PI$5 * 1.5)) { + textVerticalAlign = onLeft ? 'top' : 'bottom'; + textAlign = 'center'; + } else { + textVerticalAlign = 'middle'; + + if (rotationDiff < PI$5 * 1.5 && rotationDiff > PI$5 / 2) { + textAlign = onLeft ? 'left' : 'right'; + } else { + textAlign = onLeft ? 'right' : 'left'; + } + } + + return { + rotation: rotationDiff, + textAlign: textAlign, + textVerticalAlign: textVerticalAlign + }; + } + + function fixMinMaxLabelShow(axisModel, labelEls, tickEls) { + if (shouldShowAllLabels(axisModel.axis)) { + return; + } // If min or max are user set, we need to check + // If the tick on min(max) are overlap on their neighbour tick + // If they are overlapped, we need to hide the min(max) tick label + + + var showMinLabel = axisModel.get(['axisLabel', 'showMinLabel']); + var showMaxLabel = axisModel.get(['axisLabel', 'showMaxLabel']); // FIXME + // Have not consider onBand yet, where tick els is more than label els. + + labelEls = labelEls || []; + tickEls = tickEls || []; + var firstLabel = labelEls[0]; + var nextLabel = labelEls[1]; + var lastLabel = labelEls[labelEls.length - 1]; + var prevLabel = labelEls[labelEls.length - 2]; + var firstTick = tickEls[0]; + var nextTick = tickEls[1]; + var lastTick = tickEls[tickEls.length - 1]; + var prevTick = tickEls[tickEls.length - 2]; + + if (showMinLabel === false) { + ignoreEl(firstLabel); + ignoreEl(firstTick); + } else if (isTwoLabelOverlapped(firstLabel, nextLabel)) { + if (showMinLabel) { + ignoreEl(nextLabel); + ignoreEl(nextTick); + } else { + ignoreEl(firstLabel); + ignoreEl(firstTick); + } + } + + if (showMaxLabel === false) { + ignoreEl(lastLabel); + ignoreEl(lastTick); + } else if (isTwoLabelOverlapped(prevLabel, lastLabel)) { + if (showMaxLabel) { + ignoreEl(prevLabel); + ignoreEl(prevTick); + } else { + ignoreEl(lastLabel); + ignoreEl(lastTick); + } + } + } + + function ignoreEl(el) { + el && (el.ignore = true); + } + + function isTwoLabelOverlapped(current, next) { + // current and next has the same rotation. + var firstRect = current && current.getBoundingRect().clone(); + var nextRect = next && next.getBoundingRect().clone(); + + if (!firstRect || !nextRect) { + return; + } // When checking intersect of two rotated labels, we use mRotationBack + // to avoid that boundingRect is enlarge when using `boundingRect.applyTransform`. + + + var mRotationBack = identity([]); + rotate(mRotationBack, mRotationBack, -current.rotation); + firstRect.applyTransform(mul$1([], mRotationBack, current.getLocalTransform())); + nextRect.applyTransform(mul$1([], mRotationBack, next.getLocalTransform())); + return firstRect.intersect(nextRect); + } + + function isNameLocationCenter(nameLocation) { + return nameLocation === 'middle' || nameLocation === 'center'; + } + + function createTicks(ticksCoords, tickTransform, tickEndCoord, tickLineStyle, anidPrefix) { + var tickEls = []; + var pt1 = []; + var pt2 = []; + + for (var i = 0; i < ticksCoords.length; i++) { + var tickCoord = ticksCoords[i].coord; + pt1[0] = tickCoord; + pt1[1] = 0; + pt2[0] = tickCoord; + pt2[1] = tickEndCoord; + + if (tickTransform) { + applyTransform(pt1, pt1, tickTransform); + applyTransform(pt2, pt2, tickTransform); + } // Tick line, Not use group transform to have better line draw + + + var tickEl = new Line({ + subPixelOptimize: true, + shape: { + x1: pt1[0], + y1: pt1[1], + x2: pt2[0], + y2: pt2[1] + }, + style: tickLineStyle, + z2: 2, + autoBatch: true, + silent: true + }); + tickEl.anid = anidPrefix + '_' + ticksCoords[i].tickValue; + tickEls.push(tickEl); + } + + return tickEls; + } + + function buildAxisMajorTicks(group, transformGroup, axisModel, opt) { + var axis = axisModel.axis; + var tickModel = axisModel.getModel('axisTick'); + var shown = tickModel.get('show'); + + if (shown === 'auto' && opt.handleAutoShown) { + shown = opt.handleAutoShown('axisTick'); + } + + if (!shown || axis.scale.isBlank()) { + return; + } + + var lineStyleModel = tickModel.getModel('lineStyle'); + var tickEndCoord = opt.tickDirection * tickModel.get('length'); + var ticksCoords = axis.getTicksCoords(); + var ticksEls = createTicks(ticksCoords, transformGroup.transform, tickEndCoord, defaults(lineStyleModel.getLineStyle(), { + stroke: axisModel.get(['axisLine', 'lineStyle', 'color']) + }), 'ticks'); + + for (var i = 0; i < ticksEls.length; i++) { + group.add(ticksEls[i]); + } + + return ticksEls; + } + + function buildAxisMinorTicks(group, transformGroup, axisModel, tickDirection) { + var axis = axisModel.axis; + var minorTickModel = axisModel.getModel('minorTick'); + + if (!minorTickModel.get('show') || axis.scale.isBlank()) { + return; + } + + var minorTicksCoords = axis.getMinorTicksCoords(); + + if (!minorTicksCoords.length) { + return; + } + + var lineStyleModel = minorTickModel.getModel('lineStyle'); + var tickEndCoord = tickDirection * minorTickModel.get('length'); + var minorTickLineStyle = defaults(lineStyleModel.getLineStyle(), defaults(axisModel.getModel('axisTick').getLineStyle(), { + stroke: axisModel.get(['axisLine', 'lineStyle', 'color']) + })); + + for (var i = 0; i < minorTicksCoords.length; i++) { + var minorTicksEls = createTicks(minorTicksCoords[i], transformGroup.transform, tickEndCoord, minorTickLineStyle, 'minorticks_' + i); + + for (var k = 0; k < minorTicksEls.length; k++) { + group.add(minorTicksEls[k]); + } + } + } + + function buildAxisLabel(group, transformGroup, axisModel, opt) { + var axis = axisModel.axis; + var show = retrieve(opt.axisLabelShow, axisModel.get(['axisLabel', 'show'])); + + if (!show || axis.scale.isBlank()) { + return; + } + + var labelModel = axisModel.getModel('axisLabel'); + var labelMargin = labelModel.get('margin'); + var labels = axis.getViewLabels(); // Special label rotate. + + var labelRotation = (retrieve(opt.labelRotate, labelModel.get('rotate')) || 0) * PI$5 / 180; + var labelLayout = AxisBuilder.innerTextLayout(opt.rotation, labelRotation, opt.labelDirection); + var rawCategoryData = axisModel.getCategories && axisModel.getCategories(true); + var labelEls = []; + var silent = AxisBuilder.isLabelSilent(axisModel); + var triggerEvent = axisModel.get('triggerEvent'); + each(labels, function (labelItem, index) { + var tickValue = axis.scale.type === 'ordinal' ? axis.scale.getRawOrdinalNumber(labelItem.tickValue) : labelItem.tickValue; + var formattedLabel = labelItem.formattedLabel; + var rawLabel = labelItem.rawLabel; + var itemLabelModel = labelModel; + + if (rawCategoryData && rawCategoryData[tickValue]) { + var rawCategoryItem = rawCategoryData[tickValue]; + + if (isObject(rawCategoryItem) && rawCategoryItem.textStyle) { + itemLabelModel = new Model(rawCategoryItem.textStyle, labelModel, axisModel.ecModel); + } + } + + var textColor = itemLabelModel.getTextColor() || axisModel.get(['axisLine', 'lineStyle', 'color']); + var tickCoord = axis.dataToCoord(tickValue); + var textEl = new ZRText({ + x: tickCoord, + y: opt.labelOffset + opt.labelDirection * labelMargin, + rotation: labelLayout.rotation, + silent: silent, + z2: 10 + (labelItem.level || 0), + style: createTextStyle(itemLabelModel, { + text: formattedLabel, + align: itemLabelModel.getShallow('align', true) || labelLayout.textAlign, + verticalAlign: itemLabelModel.getShallow('verticalAlign', true) || itemLabelModel.getShallow('baseline', true) || labelLayout.textVerticalAlign, + fill: isFunction(textColor) ? textColor( // (1) In category axis with data zoom, tick is not the original + // index of axis.data. So tick should not be exposed to user + // in category axis. + // (2) Compatible with previous version, which always use formatted label as + // input. But in interval scale the formatted label is like '223,445', which + // maked user repalce ','. So we modify it to return original val but remain + // it as 'string' to avoid error in replacing. + axis.type === 'category' ? rawLabel : axis.type === 'value' ? tickValue + '' : tickValue, index) : textColor + }) + }); + textEl.anid = 'label_' + tickValue; // Pack data for mouse event + + if (triggerEvent) { + var eventData = AxisBuilder.makeAxisEventDataBase(axisModel); + eventData.targetType = 'axisLabel'; + eventData.value = rawLabel; + eventData.tickIndex = index; + + if (axis.type === 'category') { + eventData.dataIndex = tickValue; + } + + getECData(textEl).eventData = eventData; + } // FIXME + + + transformGroup.add(textEl); + textEl.updateTransform(); + labelEls.push(textEl); + group.add(textEl); + textEl.decomposeTransform(); + }); + return labelEls; + } + + // allAxesInfo should be updated when setOption performed. + + function collect(ecModel, api) { + var result = { + /** + * key: makeKey(axis.model) + * value: { + * axis, + * coordSys, + * axisPointerModel, + * triggerTooltip, + * involveSeries, + * snap, + * seriesModels, + * seriesDataCount + * } + */ + axesInfo: {}, + seriesInvolved: false, + + /** + * key: makeKey(coordSys.model) + * value: Object: key makeKey(axis.model), value: axisInfo + */ + coordSysAxesInfo: {}, + coordSysMap: {} + }; + collectAxesInfo(result, ecModel, api); // Check seriesInvolved for performance, in case too many series in some chart. + + result.seriesInvolved && collectSeriesInfo(result, ecModel); + return result; + } + + function collectAxesInfo(result, ecModel, api) { + var globalTooltipModel = ecModel.getComponent('tooltip'); + var globalAxisPointerModel = ecModel.getComponent('axisPointer'); // links can only be set on global. + + var linksOption = globalAxisPointerModel.get('link', true) || []; + var linkGroups = []; // Collect axes info. + + each(api.getCoordinateSystems(), function (coordSys) { + // Some coordinate system do not support axes, like geo. + if (!coordSys.axisPointerEnabled) { + return; + } + + var coordSysKey = makeKey(coordSys.model); + var axesInfoInCoordSys = result.coordSysAxesInfo[coordSysKey] = {}; + result.coordSysMap[coordSysKey] = coordSys; // Set tooltip (like 'cross') is a convienent way to show axisPointer + // for user. So we enable seting tooltip on coordSys model. + + var coordSysModel = coordSys.model; + var baseTooltipModel = coordSysModel.getModel('tooltip', globalTooltipModel); + each(coordSys.getAxes(), curry(saveTooltipAxisInfo, false, null)); // If axis tooltip used, choose tooltip axis for each coordSys. + // Notice this case: coordSys is `grid` but not `cartesian2D` here. + + if (coordSys.getTooltipAxes && globalTooltipModel // If tooltip.showContent is set as false, tooltip will not + // show but axisPointer will show as normal. + && baseTooltipModel.get('show')) { + // Compatible with previous logic. But series.tooltip.trigger: 'axis' + // or series.data[n].tooltip.trigger: 'axis' are not support any more. + var triggerAxis = baseTooltipModel.get('trigger') === 'axis'; + var cross = baseTooltipModel.get(['axisPointer', 'type']) === 'cross'; + var tooltipAxes = coordSys.getTooltipAxes(baseTooltipModel.get(['axisPointer', 'axis'])); + + if (triggerAxis || cross) { + each(tooltipAxes.baseAxes, curry(saveTooltipAxisInfo, cross ? 'cross' : true, triggerAxis)); + } + + if (cross) { + each(tooltipAxes.otherAxes, curry(saveTooltipAxisInfo, 'cross', false)); + } + } // fromTooltip: true | false | 'cross' + // triggerTooltip: true | false | null + + + function saveTooltipAxisInfo(fromTooltip, triggerTooltip, axis) { + var axisPointerModel = axis.model.getModel('axisPointer', globalAxisPointerModel); + var axisPointerShow = axisPointerModel.get('show'); + + if (!axisPointerShow || axisPointerShow === 'auto' && !fromTooltip && !isHandleTrigger(axisPointerModel)) { + return; + } + + if (triggerTooltip == null) { + triggerTooltip = axisPointerModel.get('triggerTooltip'); + } + + axisPointerModel = fromTooltip ? makeAxisPointerModel(axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip) : axisPointerModel; + var snap = axisPointerModel.get('snap'); + var axisKey = makeKey(axis.model); + var involveSeries = triggerTooltip || snap || axis.type === 'category'; // If result.axesInfo[key] exist, override it (tooltip has higher priority). + + var axisInfo = result.axesInfo[axisKey] = { + key: axisKey, + axis: axis, + coordSys: coordSys, + axisPointerModel: axisPointerModel, + triggerTooltip: triggerTooltip, + involveSeries: involveSeries, + snap: snap, + useHandle: isHandleTrigger(axisPointerModel), + seriesModels: [], + linkGroup: null + }; + axesInfoInCoordSys[axisKey] = axisInfo; + result.seriesInvolved = result.seriesInvolved || involveSeries; + var groupIndex = getLinkGroupIndex(linksOption, axis); + + if (groupIndex != null) { + var linkGroup = linkGroups[groupIndex] || (linkGroups[groupIndex] = { + axesInfo: {} + }); + linkGroup.axesInfo[axisKey] = axisInfo; + linkGroup.mapper = linksOption[groupIndex].mapper; + axisInfo.linkGroup = linkGroup; + } + } + }); + } + + function makeAxisPointerModel(axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip) { + var tooltipAxisPointerModel = baseTooltipModel.getModel('axisPointer'); + var fields = ['type', 'snap', 'lineStyle', 'shadowStyle', 'label', 'animation', 'animationDurationUpdate', 'animationEasingUpdate', 'z']; + var volatileOption = {}; + each(fields, function (field) { + volatileOption[field] = clone(tooltipAxisPointerModel.get(field)); + }); // category axis do not auto snap, otherwise some tick that do not + // has value can not be hovered. value/time/log axis default snap if + // triggered from tooltip and trigger tooltip. + + volatileOption.snap = axis.type !== 'category' && !!triggerTooltip; // Compatibel with previous behavior, tooltip axis do not show label by default. + // Only these properties can be overrided from tooltip to axisPointer. + + if (tooltipAxisPointerModel.get('type') === 'cross') { + volatileOption.type = 'line'; + } + + var labelOption = volatileOption.label || (volatileOption.label = {}); // Follow the convention, do not show label when triggered by tooltip by default. + + labelOption.show == null && (labelOption.show = false); + + if (fromTooltip === 'cross') { + // When 'cross', both axes show labels. + var tooltipAxisPointerLabelShow = tooltipAxisPointerModel.get(['label', 'show']); + labelOption.show = tooltipAxisPointerLabelShow != null ? tooltipAxisPointerLabelShow : true; // If triggerTooltip, this is a base axis, which should better not use cross style + // (cross style is dashed by default) + + if (!triggerTooltip) { + var crossStyle = volatileOption.lineStyle = tooltipAxisPointerModel.get('crossStyle'); + crossStyle && defaults(labelOption, crossStyle.textStyle); + } + } + + return axis.model.getModel('axisPointer', new Model(volatileOption, globalAxisPointerModel, ecModel)); + } + + function collectSeriesInfo(result, ecModel) { + // Prepare data for axis trigger + ecModel.eachSeries(function (seriesModel) { + // Notice this case: this coordSys is `cartesian2D` but not `grid`. + var coordSys = seriesModel.coordinateSystem; + var seriesTooltipTrigger = seriesModel.get(['tooltip', 'trigger'], true); + var seriesTooltipShow = seriesModel.get(['tooltip', 'show'], true); + + if (!coordSys || seriesTooltipTrigger === 'none' || seriesTooltipTrigger === false || seriesTooltipTrigger === 'item' || seriesTooltipShow === false || seriesModel.get(['axisPointer', 'show'], true) === false) { + return; + } + + each(result.coordSysAxesInfo[makeKey(coordSys.model)], function (axisInfo) { + var axis = axisInfo.axis; + + if (coordSys.getAxis(axis.dim) === axis) { + axisInfo.seriesModels.push(seriesModel); + axisInfo.seriesDataCount == null && (axisInfo.seriesDataCount = 0); + axisInfo.seriesDataCount += seriesModel.getData().count(); + } + }); + }); + } + /** + * For example: + * { + * axisPointer: { + * links: [{ + * xAxisIndex: [2, 4], + * yAxisIndex: 'all' + * }, { + * xAxisId: ['a5', 'a7'], + * xAxisName: 'xxx' + * }] + * } + * } + */ + + + function getLinkGroupIndex(linksOption, axis) { + var axisModel = axis.model; + var dim = axis.dim; + + for (var i = 0; i < linksOption.length; i++) { + var linkOption = linksOption[i] || {}; + + if (checkPropInLink(linkOption[dim + 'AxisId'], axisModel.id) || checkPropInLink(linkOption[dim + 'AxisIndex'], axisModel.componentIndex) || checkPropInLink(linkOption[dim + 'AxisName'], axisModel.name)) { + return i; + } + } + } + + function checkPropInLink(linkPropValue, axisPropValue) { + return linkPropValue === 'all' || isArray(linkPropValue) && indexOf(linkPropValue, axisPropValue) >= 0 || linkPropValue === axisPropValue; + } + + function fixValue(axisModel) { + var axisInfo = getAxisInfo(axisModel); + + if (!axisInfo) { + return; + } + + var axisPointerModel = axisInfo.axisPointerModel; + var scale = axisInfo.axis.scale; + var option = axisPointerModel.option; + var status = axisPointerModel.get('status'); + var value = axisPointerModel.get('value'); // Parse init value for category and time axis. + + if (value != null) { + value = scale.parse(value); + } + + var useHandle = isHandleTrigger(axisPointerModel); // If `handle` used, `axisPointer` will always be displayed, so value + // and status should be initialized. + + if (status == null) { + option.status = useHandle ? 'show' : 'hide'; + } + + var extent = scale.getExtent().slice(); + extent[0] > extent[1] && extent.reverse(); + + if ( // Pick a value on axis when initializing. + value == null // If both `handle` and `dataZoom` are used, value may be out of axis extent, + // where we should re-pick a value to keep `handle` displaying normally. + || value > extent[1]) { + // Make handle displayed on the end of the axis when init, which looks better. + value = extent[1]; + } + + if (value < extent[0]) { + value = extent[0]; + } + + option.value = value; + + if (useHandle) { + option.status = axisInfo.axis.scale.isBlank() ? 'hide' : 'show'; + } + } + function getAxisInfo(axisModel) { + var coordSysAxesInfo = (axisModel.ecModel.getComponent('axisPointer') || {}).coordSysAxesInfo; + return coordSysAxesInfo && coordSysAxesInfo.axesInfo[makeKey(axisModel)]; + } + function getAxisPointerModel(axisModel) { + var axisInfo = getAxisInfo(axisModel); + return axisInfo && axisInfo.axisPointerModel; + } + + function isHandleTrigger(axisPointerModel) { + return !!axisPointerModel.get(['handle', 'show']); + } + /** + * @param {module:echarts/model/Model} model + * @return {string} unique key + */ + + + function makeKey(model) { + return model.type + '||' + model.id; + } + + var axisPointerClazz = {}; + /** + * Base class of AxisView. + */ + + var AxisView = + /** @class */ + function (_super) { + __extends(AxisView, _super); + + function AxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = AxisView.type; + return _this; + } + /** + * @override + */ + + + AxisView.prototype.render = function (axisModel, ecModel, api, payload) { + // FIXME + // This process should proformed after coordinate systems updated + // (axis scale updated), and should be performed each time update. + // So put it here temporarily, although it is not appropriate to + // put a model-writing procedure in `view`. + this.axisPointerClass && fixValue(axisModel); + + _super.prototype.render.apply(this, arguments); + + this._doUpdateAxisPointerClass(axisModel, api, true); + }; + /** + * Action handler. + */ + + + AxisView.prototype.updateAxisPointer = function (axisModel, ecModel, api, payload) { + this._doUpdateAxisPointerClass(axisModel, api, false); + }; + /** + * @override + */ + + + AxisView.prototype.remove = function (ecModel, api) { + var axisPointer = this._axisPointer; + axisPointer && axisPointer.remove(api); + }; + /** + * @override + */ + + + AxisView.prototype.dispose = function (ecModel, api) { + this._disposeAxisPointer(api); + + _super.prototype.dispose.apply(this, arguments); + }; + + AxisView.prototype._doUpdateAxisPointerClass = function (axisModel, api, forceRender) { + var Clazz = AxisView.getAxisPointerClass(this.axisPointerClass); + + if (!Clazz) { + return; + } + + var axisPointerModel = getAxisPointerModel(axisModel); + axisPointerModel ? (this._axisPointer || (this._axisPointer = new Clazz())).render(axisModel, axisPointerModel, api, forceRender) : this._disposeAxisPointer(api); + }; + + AxisView.prototype._disposeAxisPointer = function (api) { + this._axisPointer && this._axisPointer.dispose(api); + this._axisPointer = null; + }; + + AxisView.registerAxisPointerClass = function (type, clazz) { + if ("development" !== 'production') { + if (axisPointerClazz[type]) { + throw new Error('axisPointer ' + type + ' exists'); + } + } + + axisPointerClazz[type] = clazz; + }; + + AxisView.getAxisPointerClass = function (type) { + return type && axisPointerClazz[type]; + }; + AxisView.type = 'axis'; + return AxisView; + }(ComponentView); + + var inner$6 = makeInner(); + function rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel) { + var axis = axisModel.axis; + + if (axis.scale.isBlank()) { + return; + } // TODO: TYPE + + + var splitAreaModel = axisModel.getModel('splitArea'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var areaColors = areaStyleModel.get('color'); + var gridRect = gridModel.coordinateSystem.getRect(); + var ticksCoords = axis.getTicksCoords({ + tickModel: splitAreaModel, + clamp: true + }); + + if (!ticksCoords.length) { + return; + } // For Making appropriate splitArea animation, the color and anid + // should be corresponding to previous one if possible. + + + var areaColorsLen = areaColors.length; + var lastSplitAreaColors = inner$6(axisView).splitAreaColors; + var newSplitAreaColors = createHashMap(); + var colorIndex = 0; + + if (lastSplitAreaColors) { + for (var i = 0; i < ticksCoords.length; i++) { + var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue); + + if (cIndex != null) { + colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen; + break; + } + } + } + + var prev = axis.toGlobalCoord(ticksCoords[0].coord); + var areaStyle = areaStyleModel.getAreaStyle(); + areaColors = isArray(areaColors) ? areaColors : [areaColors]; + + for (var i = 1; i < ticksCoords.length; i++) { + var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord); + var x = void 0; + var y = void 0; + var width = void 0; + var height = void 0; + + if (axis.isHorizontal()) { + x = prev; + y = gridRect.y; + width = tickCoord - x; + height = gridRect.height; + prev = x + width; + } else { + x = gridRect.x; + y = prev; + width = gridRect.width; + height = tickCoord - y; + prev = y + height; + } + + var tickValue = ticksCoords[i - 1].tickValue; + tickValue != null && newSplitAreaColors.set(tickValue, colorIndex); + axisGroup.add(new Rect({ + anid: tickValue != null ? 'area_' + tickValue : null, + shape: { + x: x, + y: y, + width: width, + height: height + }, + style: defaults({ + fill: areaColors[colorIndex] + }, areaStyle), + autoBatch: true, + silent: true + })); + colorIndex = (colorIndex + 1) % areaColorsLen; + } + + inner$6(axisView).splitAreaColors = newSplitAreaColors; + } + function rectCoordAxisHandleRemove(axisView) { + inner$6(axisView).splitAreaColors = null; + } + + var axisBuilderAttrs = ['axisLine', 'axisTickLabel', 'axisName']; + var selfBuilderAttrs = ['splitArea', 'splitLine', 'minorSplitLine']; + + var CartesianAxisView = + /** @class */ + function (_super) { + __extends(CartesianAxisView, _super); + + function CartesianAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CartesianAxisView.type; + _this.axisPointerClass = 'CartesianAxisPointer'; + return _this; + } + /** + * @override + */ + + + CartesianAxisView.prototype.render = function (axisModel, ecModel, api, payload) { + this.group.removeAll(); + var oldAxisGroup = this._axisGroup; + this._axisGroup = new Group(); + this.group.add(this._axisGroup); + + if (!axisModel.get('show')) { + return; + } + + var gridModel = axisModel.getCoordSysModel(); + var layout = layout$1(gridModel, axisModel); + var axisBuilder = new AxisBuilder(axisModel, extend({ + handleAutoShown: function (elementType) { + var cartesians = gridModel.coordinateSystem.getCartesians(); + + for (var i = 0; i < cartesians.length; i++) { + if (isIntervalOrLogScale(cartesians[i].getOtherAxis(axisModel.axis).scale)) { + // Still show axis tick or axisLine if other axis is value / log + return true; + } + } // Not show axisTick or axisLine if other axis is category / time + + + return false; + } + }, layout)); + each(axisBuilderAttrs, axisBuilder.add, axisBuilder); + + this._axisGroup.add(axisBuilder.getGroup()); + + each(selfBuilderAttrs, function (name) { + if (axisModel.get([name, 'show'])) { + axisElementBuilders[name](this, this._axisGroup, axisModel, gridModel); + } + }, this); // THIS is a special case for bar racing chart. + // Update the axis label from the natural initial layout to + // sorted layout should has no animation. + + var isInitialSortFromBarRacing = payload && payload.type === 'changeAxisOrder' && payload.isInitSort; + + if (!isInitialSortFromBarRacing) { + groupTransition(oldAxisGroup, this._axisGroup, axisModel); + } + + _super.prototype.render.call(this, axisModel, ecModel, api, payload); + }; + + CartesianAxisView.prototype.remove = function () { + rectCoordAxisHandleRemove(this); + }; + + CartesianAxisView.type = 'cartesianAxis'; + return CartesianAxisView; + }(AxisView); + + var axisElementBuilders = { + splitLine: function (axisView, axisGroup, axisModel, gridModel) { + var axis = axisModel.axis; + + if (axis.scale.isBlank()) { + return; + } + + var splitLineModel = axisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + lineColors = isArray(lineColors) ? lineColors : [lineColors]; + var gridRect = gridModel.coordinateSystem.getRect(); + var isHorizontal = axis.isHorizontal(); + var lineCount = 0; + var ticksCoords = axis.getTicksCoords({ + tickModel: splitLineModel + }); + var p1 = []; + var p2 = []; + var lineStyle = lineStyleModel.getLineStyle(); + + for (var i = 0; i < ticksCoords.length; i++) { + var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord); + + if (isHorizontal) { + p1[0] = tickCoord; + p1[1] = gridRect.y; + p2[0] = tickCoord; + p2[1] = gridRect.y + gridRect.height; + } else { + p1[0] = gridRect.x; + p1[1] = tickCoord; + p2[0] = gridRect.x + gridRect.width; + p2[1] = tickCoord; + } + + var colorIndex = lineCount++ % lineColors.length; + var tickValue = ticksCoords[i].tickValue; + axisGroup.add(new Line({ + anid: tickValue != null ? 'line_' + ticksCoords[i].tickValue : null, + subPixelOptimize: true, + autoBatch: true, + shape: { + x1: p1[0], + y1: p1[1], + x2: p2[0], + y2: p2[1] + }, + style: defaults({ + stroke: lineColors[colorIndex] + }, lineStyle), + silent: true + })); + } + }, + minorSplitLine: function (axisView, axisGroup, axisModel, gridModel) { + var axis = axisModel.axis; + var minorSplitLineModel = axisModel.getModel('minorSplitLine'); + var lineStyleModel = minorSplitLineModel.getModel('lineStyle'); + var gridRect = gridModel.coordinateSystem.getRect(); + var isHorizontal = axis.isHorizontal(); + var minorTicksCoords = axis.getMinorTicksCoords(); + + if (!minorTicksCoords.length) { + return; + } + + var p1 = []; + var p2 = []; + var lineStyle = lineStyleModel.getLineStyle(); + + for (var i = 0; i < minorTicksCoords.length; i++) { + for (var k = 0; k < minorTicksCoords[i].length; k++) { + var tickCoord = axis.toGlobalCoord(minorTicksCoords[i][k].coord); + + if (isHorizontal) { + p1[0] = tickCoord; + p1[1] = gridRect.y; + p2[0] = tickCoord; + p2[1] = gridRect.y + gridRect.height; + } else { + p1[0] = gridRect.x; + p1[1] = tickCoord; + p2[0] = gridRect.x + gridRect.width; + p2[1] = tickCoord; + } + + axisGroup.add(new Line({ + anid: 'minor_line_' + minorTicksCoords[i][k].tickValue, + subPixelOptimize: true, + autoBatch: true, + shape: { + x1: p1[0], + y1: p1[1], + x2: p2[0], + y2: p2[1] + }, + style: lineStyle, + silent: true + })); + } + } + }, + splitArea: function (axisView, axisGroup, axisModel, gridModel) { + rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel); + } + }; + + var CartesianXAxisView = + /** @class */ + function (_super) { + __extends(CartesianXAxisView, _super); + + function CartesianXAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CartesianXAxisView.type; + return _this; + } + + CartesianXAxisView.type = 'xAxis'; + return CartesianXAxisView; + }(CartesianAxisView); + + var CartesianYAxisView = + /** @class */ + function (_super) { + __extends(CartesianYAxisView, _super); + + function CartesianYAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CartesianXAxisView.type; + return _this; + } + + CartesianYAxisView.type = 'yAxis'; + return CartesianYAxisView; + }(CartesianAxisView); + + var GridView = + /** @class */ + function (_super) { + __extends(GridView, _super); + + function GridView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'grid'; + return _this; + } + + GridView.prototype.render = function (gridModel, ecModel) { + this.group.removeAll(); + + if (gridModel.get('show')) { + this.group.add(new Rect({ + shape: gridModel.coordinateSystem.getRect(), + style: defaults({ + fill: gridModel.get('backgroundColor') + }, gridModel.getItemStyle()), + silent: true, + z2: -1 + })); + } + }; + + GridView.type = 'grid'; + return GridView; + }(ComponentView); + + var extraOption = { + // gridIndex: 0, + // gridId: '', + offset: 0 + }; + function install$5(registers) { + registers.registerComponentView(GridView); + registers.registerComponentModel(GridModel); + registers.registerCoordinateSystem('cartesian2d', Grid); + axisModelCreator(registers, 'x', CartesianAxisModel, extraOption); + axisModelCreator(registers, 'y', CartesianAxisModel, extraOption); + registers.registerComponentView(CartesianXAxisView); + registers.registerComponentView(CartesianYAxisView); + registers.registerPreprocessor(function (option) { + // Only create grid when need + if (option.xAxis && option.yAxis && !option.grid) { + option.grid = {}; + } + }); + } + + function install$6(registers) { + // In case developer forget to include grid component + use(install$5); + registers.registerSeriesModel(ScatterSeriesModel); + registers.registerChartView(ScatterView); + registers.registerLayout(pointsLayout('scatter')); + } + + function radarLayout(ecModel) { + ecModel.eachSeriesByType('radar', function (seriesModel) { + var data = seriesModel.getData(); + var points = []; + var coordSys = seriesModel.coordinateSystem; + + if (!coordSys) { + return; + } + + var axes = coordSys.getIndicatorAxes(); + each(axes, function (axis, axisIndex) { + data.each(data.mapDimension(axes[axisIndex].dim), function (val, dataIndex) { + points[dataIndex] = points[dataIndex] || []; + var point = coordSys.dataToPoint(val, axisIndex); + points[dataIndex][axisIndex] = isValidPoint(point) ? point : getValueMissingPoint(coordSys); + }); + }); // Close polygon + + data.each(function (idx) { + // TODO + // Is it appropriate to connect to the next data when some data is missing? + // Or, should trade it like `connectNull` in line chart? + var firstPoint = find(points[idx], function (point) { + return isValidPoint(point); + }) || getValueMissingPoint(coordSys); // Copy the first actual point to the end of the array + + points[idx].push(firstPoint.slice()); + data.setItemLayout(idx, points[idx]); + }); + }); + } + + function isValidPoint(point) { + return !isNaN(point[0]) && !isNaN(point[1]); + } + + function getValueMissingPoint(coordSys) { + // It is error-prone to input [NaN, NaN] into polygon, polygon. + // (probably cause problem when refreshing or animating) + return [coordSys.cx, coordSys.cy]; + } + + function radarBackwardCompat(option) { + var polarOptArr = option.polar; + + if (polarOptArr) { + if (!isArray(polarOptArr)) { + polarOptArr = [polarOptArr]; + } + + var polarNotRadar_1 = []; + each(polarOptArr, function (polarOpt, idx) { + if (polarOpt.indicator) { + if (polarOpt.type && !polarOpt.shape) { + polarOpt.shape = polarOpt.type; + } + + option.radar = option.radar || []; + + if (!isArray(option.radar)) { + option.radar = [option.radar]; + } + + option.radar.push(polarOpt); + } else { + polarNotRadar_1.push(polarOpt); + } + }); + option.polar = polarNotRadar_1; + } + + each(option.series, function (seriesOpt) { + if (seriesOpt && seriesOpt.type === 'radar' && seriesOpt.polarIndex) { + seriesOpt.radarIndex = seriesOpt.polarIndex; + } + }); + } + + var RadarView = + /** @class */ + function (_super) { + __extends(RadarView, _super); + + function RadarView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = RadarView.type; + return _this; + } + + RadarView.prototype.render = function (seriesModel, ecModel, api) { + var polar = seriesModel.coordinateSystem; + var group = this.group; + var data = seriesModel.getData(); + var oldData = this._data; + + function createSymbol$1(data, idx) { + var symbolType = data.getItemVisual(idx, 'symbol') || 'circle'; + + if (symbolType === 'none') { + return; + } + + var symbolSize = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize')); + var symbolPath = createSymbol(symbolType, -1, -1, 2, 2); + var symbolRotate = data.getItemVisual(idx, 'symbolRotate') || 0; + symbolPath.attr({ + style: { + strokeNoScale: true + }, + z2: 100, + scaleX: symbolSize[0] / 2, + scaleY: symbolSize[1] / 2, + rotation: symbolRotate * Math.PI / 180 || 0 + }); + return symbolPath; + } + + function updateSymbols(oldPoints, newPoints, symbolGroup, data, idx, isInit) { + // Simply rerender all + symbolGroup.removeAll(); + + for (var i = 0; i < newPoints.length - 1; i++) { + var symbolPath = createSymbol$1(data, idx); + + if (symbolPath) { + symbolPath.__dimIdx = i; + + if (oldPoints[i]) { + symbolPath.setPosition(oldPoints[i]); + graphic[isInit ? 'initProps' : 'updateProps'](symbolPath, { + x: newPoints[i][0], + y: newPoints[i][1] + }, seriesModel, idx); + } else { + symbolPath.setPosition(newPoints[i]); + } + + symbolGroup.add(symbolPath); + } + } + } + + function getInitialPoints(points) { + return map(points, function (pt) { + return [polar.cx, polar.cy]; + }); + } + + data.diff(oldData).add(function (idx) { + var points = data.getItemLayout(idx); + + if (!points) { + return; + } + + var polygon = new Polygon(); + var polyline = new Polyline(); + var target = { + shape: { + points: points + } + }; + polygon.shape.points = getInitialPoints(points); + polyline.shape.points = getInitialPoints(points); + initProps(polygon, target, seriesModel, idx); + initProps(polyline, target, seriesModel, idx); + var itemGroup = new Group(); + var symbolGroup = new Group(); + itemGroup.add(polyline); + itemGroup.add(polygon); + itemGroup.add(symbolGroup); + updateSymbols(polyline.shape.points, points, symbolGroup, data, idx, true); + data.setItemGraphicEl(idx, itemGroup); + }).update(function (newIdx, oldIdx) { + var itemGroup = oldData.getItemGraphicEl(oldIdx); + var polyline = itemGroup.childAt(0); + var polygon = itemGroup.childAt(1); + var symbolGroup = itemGroup.childAt(2); + var target = { + shape: { + points: data.getItemLayout(newIdx) + } + }; + + if (!target.shape.points) { + return; + } + + updateSymbols(polyline.shape.points, target.shape.points, symbolGroup, data, newIdx, false); + saveOldStyle(polygon); + saveOldStyle(polyline); + updateProps(polyline, target, seriesModel); + updateProps(polygon, target, seriesModel); + data.setItemGraphicEl(newIdx, itemGroup); + }).remove(function (idx) { + group.remove(oldData.getItemGraphicEl(idx)); + }).execute(); + data.eachItemGraphicEl(function (itemGroup, idx) { + var itemModel = data.getItemModel(idx); + var polyline = itemGroup.childAt(0); + var polygon = itemGroup.childAt(1); + var symbolGroup = itemGroup.childAt(2); // Radar uses the visual encoded from itemStyle. + + var itemStyle = data.getItemVisual(idx, 'style'); + var color = itemStyle.fill; + group.add(itemGroup); + polyline.useStyle(defaults(itemModel.getModel('lineStyle').getLineStyle(), { + fill: 'none', + stroke: color + })); + setStatesStylesFromModel(polyline, itemModel, 'lineStyle'); + setStatesStylesFromModel(polygon, itemModel, 'areaStyle'); + var areaStyleModel = itemModel.getModel('areaStyle'); + var polygonIgnore = areaStyleModel.isEmpty() && areaStyleModel.parentModel.isEmpty(); + polygon.ignore = polygonIgnore; + each(['emphasis', 'select', 'blur'], function (stateName) { + var stateModel = itemModel.getModel([stateName, 'areaStyle']); + var stateIgnore = stateModel.isEmpty() && stateModel.parentModel.isEmpty(); // Won't be ignore if normal state is not ignore. + + polygon.ensureState(stateName).ignore = stateIgnore && polygonIgnore; + }); + polygon.useStyle(defaults(areaStyleModel.getAreaStyle(), { + fill: color, + opacity: 0.7, + decal: itemStyle.decal + })); + var emphasisModel = itemModel.getModel('emphasis'); + var itemHoverStyle = emphasisModel.getModel('itemStyle').getItemStyle(); + symbolGroup.eachChild(function (symbolPath) { + if (symbolPath instanceof ZRImage) { + var pathStyle = symbolPath.style; + symbolPath.useStyle(extend({ + // TODO other properties like x, y ? + image: pathStyle.image, + x: pathStyle.x, + y: pathStyle.y, + width: pathStyle.width, + height: pathStyle.height + }, itemStyle)); + } else { + symbolPath.useStyle(itemStyle); + symbolPath.setColor(color); + symbolPath.style.strokeNoScale = true; + } + + var pathEmphasisState = symbolPath.ensureState('emphasis'); + pathEmphasisState.style = clone(itemHoverStyle); + var defaultText = data.getStore().get(data.getDimensionIndex(symbolPath.__dimIdx), idx); + (defaultText == null || isNaN(defaultText)) && (defaultText = ''); + setLabelStyle(symbolPath, getLabelStatesModels(itemModel), { + labelFetcher: data.hostModel, + labelDataIndex: idx, + labelDimIndex: symbolPath.__dimIdx, + defaultText: defaultText, + inheritColor: color, + defaultOpacity: itemStyle.opacity + }); + }); + toggleHoverEmphasis(itemGroup, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled')); + }); + this._data = data; + }; + + RadarView.prototype.remove = function () { + this.group.removeAll(); + this._data = null; + }; + + RadarView.type = 'radar'; + return RadarView; + }(ChartView); + + var RadarSeriesModel = + /** @class */ + function (_super) { + __extends(RadarSeriesModel, _super); + + function RadarSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = RadarSeriesModel.type; + _this.hasSymbolVisual = true; + return _this; + } // Overwrite + + + RadarSeriesModel.prototype.init = function (option) { + _super.prototype.init.apply(this, arguments); // Enable legend selection for each data item + // Use a function instead of direct access because data reference may changed + + + this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this)); + }; + + RadarSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createSeriesDataSimply(this, { + generateCoord: 'indicator_', + generateCoordCount: Infinity + }); + }; + + RadarSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var data = this.getData(); + var coordSys = this.coordinateSystem; + var indicatorAxes = coordSys.getIndicatorAxes(); + var name = this.getData().getName(dataIndex); + var nameToDisplay = name === '' ? this.name : name; + var markerColor = retrieveVisualColorForTooltipMarker(this, dataIndex); + return createTooltipMarkup('section', { + header: nameToDisplay, + sortBlocks: true, + blocks: map(indicatorAxes, function (axis) { + var val = data.get(data.mapDimension(axis.dim), dataIndex); + return createTooltipMarkup('nameValue', { + markerType: 'subItem', + markerColor: markerColor, + name: axis.name, + value: val, + sortParam: val + }); + }) + }); + }; + + RadarSeriesModel.prototype.getTooltipPosition = function (dataIndex) { + if (dataIndex != null) { + var data_1 = this.getData(); + var coordSys = this.coordinateSystem; + var values = data_1.getValues(map(coordSys.dimensions, function (dim) { + return data_1.mapDimension(dim); + }), dataIndex); + + for (var i = 0, len = values.length; i < len; i++) { + if (!isNaN(values[i])) { + var indicatorAxes = coordSys.getIndicatorAxes(); + return coordSys.coordToPoint(indicatorAxes[i].dataToCoord(values[i]), i); + } + } + } + }; + + RadarSeriesModel.type = 'series.radar'; + RadarSeriesModel.dependencies = ['radar']; + RadarSeriesModel.defaultOption = { + // zlevel: 0, + z: 2, + colorBy: 'data', + coordinateSystem: 'radar', + legendHoverLink: true, + radarIndex: 0, + lineStyle: { + width: 2, + type: 'solid', + join: 'round' + }, + label: { + position: 'top' + }, + // areaStyle: { + // }, + // itemStyle: {} + symbolSize: 8 // symbolRotate: null + + }; + return RadarSeriesModel; + }(SeriesModel); + + var valueAxisDefault = axisDefault.value; + + function defaultsShow(opt, show) { + return defaults({ + show: show + }, opt); + } + + var RadarModel = + /** @class */ + function (_super) { + __extends(RadarModel, _super); + + function RadarModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = RadarModel.type; + return _this; + } + + RadarModel.prototype.optionUpdated = function () { + var boundaryGap = this.get('boundaryGap'); + var splitNumber = this.get('splitNumber'); + var scale = this.get('scale'); + var axisLine = this.get('axisLine'); + var axisTick = this.get('axisTick'); // let axisType = this.get('axisType'); + + var axisLabel = this.get('axisLabel'); + var nameTextStyle = this.get('axisName'); + var showName = this.get(['axisName', 'show']); + var nameFormatter = this.get(['axisName', 'formatter']); + var nameGap = this.get('axisNameGap'); + var triggerEvent = this.get('triggerEvent'); + var indicatorModels = map(this.get('indicator') || [], function (indicatorOpt) { + // PENDING + if (indicatorOpt.max != null && indicatorOpt.max > 0 && !indicatorOpt.min) { + indicatorOpt.min = 0; + } else if (indicatorOpt.min != null && indicatorOpt.min < 0 && !indicatorOpt.max) { + indicatorOpt.max = 0; + } + + var iNameTextStyle = nameTextStyle; + + if (indicatorOpt.color != null) { + iNameTextStyle = defaults({ + color: indicatorOpt.color + }, nameTextStyle); + } // Use same configuration + + + var innerIndicatorOpt = merge(clone(indicatorOpt), { + boundaryGap: boundaryGap, + splitNumber: splitNumber, + scale: scale, + axisLine: axisLine, + axisTick: axisTick, + // axisType: axisType, + axisLabel: axisLabel, + // Compatible with 2 and use text + name: indicatorOpt.text, + showName: showName, + nameLocation: 'end', + nameGap: nameGap, + // min: 0, + nameTextStyle: iNameTextStyle, + triggerEvent: triggerEvent + }, false); + + if (!showName) { + innerIndicatorOpt.name = ''; + } + + if (isString(nameFormatter)) { + var indName = innerIndicatorOpt.name; + innerIndicatorOpt.name = nameFormatter.replace('{value}', indName != null ? indName : ''); + } else if (isFunction(nameFormatter)) { + innerIndicatorOpt.name = nameFormatter(innerIndicatorOpt.name, innerIndicatorOpt); + } + + var model = new Model(innerIndicatorOpt, null, this.ecModel); + mixin(model, AxisModelCommonMixin.prototype); // For triggerEvent. + + model.mainType = 'radar'; + model.componentIndex = this.componentIndex; + return model; + }, this); + this._indicatorModels = indicatorModels; + }; + + RadarModel.prototype.getIndicatorModels = function () { + return this._indicatorModels; + }; + + RadarModel.type = 'radar'; + RadarModel.defaultOption = { + // zlevel: 0, + z: 0, + center: ['50%', '50%'], + radius: '75%', + startAngle: 90, + axisName: { + show: true // formatter: null + // textStyle: {} + + }, + boundaryGap: [0, 0], + splitNumber: 5, + axisNameGap: 15, + scale: false, + // Polygon or circle + shape: 'polygon', + axisLine: merge({ + lineStyle: { + color: '#bbb' + } + }, valueAxisDefault.axisLine), + axisLabel: defaultsShow(valueAxisDefault.axisLabel, false), + axisTick: defaultsShow(valueAxisDefault.axisTick, false), + // axisType: 'value', + splitLine: defaultsShow(valueAxisDefault.splitLine, true), + splitArea: defaultsShow(valueAxisDefault.splitArea, true), + // {text, min, max} + indicator: [] + }; + return RadarModel; + }(ComponentModel); + + var axisBuilderAttrs$1 = ['axisLine', 'axisTickLabel', 'axisName']; + + var RadarView$1 = + /** @class */ + function (_super) { + __extends(RadarView, _super); + + function RadarView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = RadarView.type; + return _this; + } + + RadarView.prototype.render = function (radarModel, ecModel, api) { + var group = this.group; + group.removeAll(); + + this._buildAxes(radarModel); + + this._buildSplitLineAndArea(radarModel); + }; + + RadarView.prototype._buildAxes = function (radarModel) { + var radar = radarModel.coordinateSystem; + var indicatorAxes = radar.getIndicatorAxes(); + var axisBuilders = map(indicatorAxes, function (indicatorAxis) { + var axisName = indicatorAxis.model.get('showName') ? indicatorAxis.name : ''; // hide name + + var axisBuilder = new AxisBuilder(indicatorAxis.model, { + axisName: axisName, + position: [radar.cx, radar.cy], + rotation: indicatorAxis.angle, + labelDirection: -1, + tickDirection: -1, + nameDirection: 1 + }); + return axisBuilder; + }); + each(axisBuilders, function (axisBuilder) { + each(axisBuilderAttrs$1, axisBuilder.add, axisBuilder); + this.group.add(axisBuilder.getGroup()); + }, this); + }; + + RadarView.prototype._buildSplitLineAndArea = function (radarModel) { + var radar = radarModel.coordinateSystem; + var indicatorAxes = radar.getIndicatorAxes(); + + if (!indicatorAxes.length) { + return; + } + + var shape = radarModel.get('shape'); + var splitLineModel = radarModel.getModel('splitLine'); + var splitAreaModel = radarModel.getModel('splitArea'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var showSplitLine = splitLineModel.get('show'); + var showSplitArea = splitAreaModel.get('show'); + var splitLineColors = lineStyleModel.get('color'); + var splitAreaColors = areaStyleModel.get('color'); + var splitLineColorsArr = isArray(splitLineColors) ? splitLineColors : [splitLineColors]; + var splitAreaColorsArr = isArray(splitAreaColors) ? splitAreaColors : [splitAreaColors]; + var splitLines = []; + var splitAreas = []; + + function getColorIndex(areaOrLine, areaOrLineColorList, idx) { + var colorIndex = idx % areaOrLineColorList.length; + areaOrLine[colorIndex] = areaOrLine[colorIndex] || []; + return colorIndex; + } + + if (shape === 'circle') { + var ticksRadius = indicatorAxes[0].getTicksCoords(); + var cx = radar.cx; + var cy = radar.cy; + + for (var i = 0; i < ticksRadius.length; i++) { + if (showSplitLine) { + var colorIndex = getColorIndex(splitLines, splitLineColorsArr, i); + splitLines[colorIndex].push(new Circle({ + shape: { + cx: cx, + cy: cy, + r: ticksRadius[i].coord + } + })); + } + + if (showSplitArea && i < ticksRadius.length - 1) { + var colorIndex = getColorIndex(splitAreas, splitAreaColorsArr, i); + splitAreas[colorIndex].push(new Ring({ + shape: { + cx: cx, + cy: cy, + r0: ticksRadius[i].coord, + r: ticksRadius[i + 1].coord + } + })); + } + } + } // Polyyon + else { + var realSplitNumber_1; + var axesTicksPoints = map(indicatorAxes, function (indicatorAxis, idx) { + var ticksCoords = indicatorAxis.getTicksCoords(); + realSplitNumber_1 = realSplitNumber_1 == null ? ticksCoords.length - 1 : Math.min(ticksCoords.length - 1, realSplitNumber_1); + return map(ticksCoords, function (tickCoord) { + return radar.coordToPoint(tickCoord.coord, idx); + }); + }); + var prevPoints = []; + + for (var i = 0; i <= realSplitNumber_1; i++) { + var points = []; + + for (var j = 0; j < indicatorAxes.length; j++) { + points.push(axesTicksPoints[j][i]); + } // Close + + + if (points[0]) { + points.push(points[0].slice()); + } else { + if ("development" !== 'production') { + console.error('Can\'t draw value axis ' + i); + } + } + + if (showSplitLine) { + var colorIndex = getColorIndex(splitLines, splitLineColorsArr, i); + splitLines[colorIndex].push(new Polyline({ + shape: { + points: points + } + })); + } + + if (showSplitArea && prevPoints) { + var colorIndex = getColorIndex(splitAreas, splitAreaColorsArr, i - 1); + splitAreas[colorIndex].push(new Polygon({ + shape: { + points: points.concat(prevPoints) + } + })); + } + + prevPoints = points.slice().reverse(); + } + } + + var lineStyle = lineStyleModel.getLineStyle(); + var areaStyle = areaStyleModel.getAreaStyle(); // Add splitArea before splitLine + + each(splitAreas, function (splitAreas, idx) { + this.group.add(mergePath$1(splitAreas, { + style: defaults({ + stroke: 'none', + fill: splitAreaColorsArr[idx % splitAreaColorsArr.length] + }, areaStyle), + silent: true + })); + }, this); + each(splitLines, function (splitLines, idx) { + this.group.add(mergePath$1(splitLines, { + style: defaults({ + fill: 'none', + stroke: splitLineColorsArr[idx % splitLineColorsArr.length] + }, lineStyle), + silent: true + })); + }, this); + }; + + RadarView.type = 'radar'; + return RadarView; + }(ComponentView); + + var IndicatorAxis = + /** @class */ + function (_super) { + __extends(IndicatorAxis, _super); + + function IndicatorAxis(dim, scale, radiusExtent) { + var _this = _super.call(this, dim, scale, radiusExtent) || this; + + _this.type = 'value'; + _this.angle = 0; + _this.name = ''; + return _this; + } + + return IndicatorAxis; + }(Axis); + + var Radar = + /** @class */ + function () { + function Radar(radarModel, ecModel, api) { + /** + * + * Radar dimensions + */ + this.dimensions = []; + this._model = radarModel; + this._indicatorAxes = map(radarModel.getIndicatorModels(), function (indicatorModel, idx) { + var dim = 'indicator_' + idx; + var indicatorAxis = new IndicatorAxis(dim, new IntervalScale() // (indicatorModel.get('axisType') === 'log') ? new LogScale() : new IntervalScale() + ); + indicatorAxis.name = indicatorModel.get('name'); // Inject model and axis + + indicatorAxis.model = indicatorModel; + indicatorModel.axis = indicatorAxis; + this.dimensions.push(dim); + return indicatorAxis; + }, this); + this.resize(radarModel, api); + } + + Radar.prototype.getIndicatorAxes = function () { + return this._indicatorAxes; + }; + + Radar.prototype.dataToPoint = function (value, indicatorIndex) { + var indicatorAxis = this._indicatorAxes[indicatorIndex]; + return this.coordToPoint(indicatorAxis.dataToCoord(value), indicatorIndex); + }; // TODO: API should be coordToPoint([coord, indicatorIndex]) + + + Radar.prototype.coordToPoint = function (coord, indicatorIndex) { + var indicatorAxis = this._indicatorAxes[indicatorIndex]; + var angle = indicatorAxis.angle; + var x = this.cx + coord * Math.cos(angle); + var y = this.cy - coord * Math.sin(angle); + return [x, y]; + }; + + Radar.prototype.pointToData = function (pt) { + var dx = pt[0] - this.cx; + var dy = pt[1] - this.cy; + var radius = Math.sqrt(dx * dx + dy * dy); + dx /= radius; + dy /= radius; + var radian = Math.atan2(-dy, dx); // Find the closest angle + // FIXME index can calculated directly + + var minRadianDiff = Infinity; + var closestAxis; + var closestAxisIdx = -1; + + for (var i = 0; i < this._indicatorAxes.length; i++) { + var indicatorAxis = this._indicatorAxes[i]; + var diff = Math.abs(radian - indicatorAxis.angle); + + if (diff < minRadianDiff) { + closestAxis = indicatorAxis; + closestAxisIdx = i; + minRadianDiff = diff; + } + } + + return [closestAxisIdx, +(closestAxis && closestAxis.coordToData(radius))]; + }; + + Radar.prototype.resize = function (radarModel, api) { + var center = radarModel.get('center'); + var viewWidth = api.getWidth(); + var viewHeight = api.getHeight(); + var viewSize = Math.min(viewWidth, viewHeight) / 2; + this.cx = parsePercent$1(center[0], viewWidth); + this.cy = parsePercent$1(center[1], viewHeight); + this.startAngle = radarModel.get('startAngle') * Math.PI / 180; // radius may be single value like `20`, `'80%'`, or array like `[10, '80%']` + + var radius = radarModel.get('radius'); + + if (isString(radius) || isNumber(radius)) { + radius = [0, radius]; + } + + this.r0 = parsePercent$1(radius[0], viewSize); + this.r = parsePercent$1(radius[1], viewSize); + each(this._indicatorAxes, function (indicatorAxis, idx) { + indicatorAxis.setExtent(this.r0, this.r); + var angle = this.startAngle + idx * Math.PI * 2 / this._indicatorAxes.length; // Normalize to [-PI, PI] + + angle = Math.atan2(Math.sin(angle), Math.cos(angle)); + indicatorAxis.angle = angle; + }, this); + }; + + Radar.prototype.update = function (ecModel, api) { + var indicatorAxes = this._indicatorAxes; + var radarModel = this._model; + each(indicatorAxes, function (indicatorAxis) { + indicatorAxis.scale.setExtent(Infinity, -Infinity); + }); + ecModel.eachSeriesByType('radar', function (radarSeries, idx) { + if (radarSeries.get('coordinateSystem') !== 'radar' // @ts-ignore + || ecModel.getComponent('radar', radarSeries.get('radarIndex')) !== radarModel) { + return; + } + + var data = radarSeries.getData(); + each(indicatorAxes, function (indicatorAxis) { + indicatorAxis.scale.unionExtentFromData(data, data.mapDimension(indicatorAxis.dim)); + }); + }, this); + var splitNumber = radarModel.get('splitNumber'); + var dummyScale = new IntervalScale(); + dummyScale.setExtent(0, splitNumber); + dummyScale.setInterval(1); // Force all the axis fixing the maxSplitNumber. + + each(indicatorAxes, function (indicatorAxis, idx) { + alignScaleTicks(indicatorAxis.scale, indicatorAxis.model, dummyScale); + }); + }; + + Radar.prototype.convertToPixel = function (ecModel, finder, value) { + console.warn('Not implemented.'); + return null; + }; + + Radar.prototype.convertFromPixel = function (ecModel, finder, pixel) { + console.warn('Not implemented.'); + return null; + }; + + Radar.prototype.containPoint = function (point) { + console.warn('Not implemented.'); + return false; + }; + + Radar.create = function (ecModel, api) { + var radarList = []; + ecModel.eachComponent('radar', function (radarModel) { + var radar = new Radar(radarModel, ecModel, api); + radarList.push(radar); + radarModel.coordinateSystem = radar; + }); + ecModel.eachSeriesByType('radar', function (radarSeries) { + if (radarSeries.get('coordinateSystem') === 'radar') { + // Inject coordinate system + // @ts-ignore + radarSeries.coordinateSystem = radarList[radarSeries.get('radarIndex') || 0]; + } + }); + return radarList; + }; + /** + * Radar dimensions is based on the data + */ + + + Radar.dimensions = []; + return Radar; + }(); + + function install$7(registers) { + registers.registerCoordinateSystem('radar', Radar); + registers.registerComponentModel(RadarModel); + registers.registerComponentView(RadarView$1); + registers.registerVisual({ + seriesType: 'radar', + reset: function (seriesModel) { + var data = seriesModel.getData(); // itemVisual symbol is for selected data + + data.each(function (idx) { + data.setItemVisual(idx, 'legendIcon', 'roundRect'); + }); // visual is for unselected data + + data.setVisual('legendIcon', 'roundRect'); + } + }); + } + + function install$8(registers) { + use(install$7); + registers.registerChartView(RadarView); + registers.registerSeriesModel(RadarSeriesModel); + registers.registerLayout(radarLayout); + registers.registerProcessor(dataFilter('radar')); + registers.registerPreprocessor(radarBackwardCompat); + } + + var ATTR = '\0_ec_interaction_mutex'; + function take(zr, resourceKey, userKey) { + var store = getStore(zr); + store[resourceKey] = userKey; + } + function release(zr, resourceKey, userKey) { + var store = getStore(zr); + var uKey = store[resourceKey]; + + if (uKey === userKey) { + store[resourceKey] = null; + } + } + function isTaken(zr, resourceKey) { + return !!getStore(zr)[resourceKey]; + } + + function getStore(zr) { + return zr[ATTR] || (zr[ATTR] = {}); + } + /** + * payload: { + * type: 'takeGlobalCursor', + * key: 'dataZoomSelect', or 'brush', or ..., + * If no userKey, release global cursor. + * } + */ + // TODO: SELF REGISTERED. + + + registerAction({ + type: 'takeGlobalCursor', + event: 'globalCursorTaken', + update: 'update' + }, noop); + + var RoamController = + /** @class */ + function (_super) { + __extends(RoamController, _super); + + function RoamController(zr) { + var _this = _super.call(this) || this; + + _this._zr = zr; // Avoid two roamController bind the same handler + + var mousedownHandler = bind(_this._mousedownHandler, _this); + var mousemoveHandler = bind(_this._mousemoveHandler, _this); + var mouseupHandler = bind(_this._mouseupHandler, _this); + var mousewheelHandler = bind(_this._mousewheelHandler, _this); + var pinchHandler = bind(_this._pinchHandler, _this); + /** + * Notice: only enable needed types. For example, if 'zoom' + * is not needed, 'zoom' should not be enabled, otherwise + * default mousewheel behaviour (scroll page) will be disabled. + */ + + _this.enable = function (controlType, opt) { + // Disable previous first + this.disable(); + this._opt = defaults(clone(opt) || {}, { + zoomOnMouseWheel: true, + moveOnMouseMove: true, + // By default, wheel do not trigger move. + moveOnMouseWheel: false, + preventDefaultMouseMove: true + }); + + if (controlType == null) { + controlType = true; + } + + if (controlType === true || controlType === 'move' || controlType === 'pan') { + zr.on('mousedown', mousedownHandler); + zr.on('mousemove', mousemoveHandler); + zr.on('mouseup', mouseupHandler); + } + + if (controlType === true || controlType === 'scale' || controlType === 'zoom') { + zr.on('mousewheel', mousewheelHandler); + zr.on('pinch', pinchHandler); + } + }; + + _this.disable = function () { + zr.off('mousedown', mousedownHandler); + zr.off('mousemove', mousemoveHandler); + zr.off('mouseup', mouseupHandler); + zr.off('mousewheel', mousewheelHandler); + zr.off('pinch', pinchHandler); + }; + + return _this; + } + + RoamController.prototype.isDragging = function () { + return this._dragging; + }; + + RoamController.prototype.isPinching = function () { + return this._pinching; + }; + + RoamController.prototype.setPointerChecker = function (pointerChecker) { + this.pointerChecker = pointerChecker; + }; + + RoamController.prototype.dispose = function () { + this.disable(); + }; + + RoamController.prototype._mousedownHandler = function (e) { + if (isMiddleOrRightButtonOnMouseUpDown(e) || e.target && e.target.draggable) { + return; + } + + var x = e.offsetX; + var y = e.offsetY; // Only check on mosedown, but not mousemove. + // Mouse can be out of target when mouse moving. + + if (this.pointerChecker && this.pointerChecker(e, x, y)) { + this._x = x; + this._y = y; + this._dragging = true; + } + }; + + RoamController.prototype._mousemoveHandler = function (e) { + if (!this._dragging || !isAvailableBehavior('moveOnMouseMove', e, this._opt) || e.gestureEvent === 'pinch' || isTaken(this._zr, 'globalPan')) { + return; + } + + var x = e.offsetX; + var y = e.offsetY; + var oldX = this._x; + var oldY = this._y; + var dx = x - oldX; + var dy = y - oldY; + this._x = x; + this._y = y; + this._opt.preventDefaultMouseMove && stop(e.event); + trigger(this, 'pan', 'moveOnMouseMove', e, { + dx: dx, + dy: dy, + oldX: oldX, + oldY: oldY, + newX: x, + newY: y, + isAvailableBehavior: null + }); + }; + + RoamController.prototype._mouseupHandler = function (e) { + if (!isMiddleOrRightButtonOnMouseUpDown(e)) { + this._dragging = false; + } + }; + + RoamController.prototype._mousewheelHandler = function (e) { + var shouldZoom = isAvailableBehavior('zoomOnMouseWheel', e, this._opt); + var shouldMove = isAvailableBehavior('moveOnMouseWheel', e, this._opt); + var wheelDelta = e.wheelDelta; + var absWheelDeltaDelta = Math.abs(wheelDelta); + var originX = e.offsetX; + var originY = e.offsetY; // wheelDelta maybe -0 in chrome mac. + + if (wheelDelta === 0 || !shouldZoom && !shouldMove) { + return; + } // If both `shouldZoom` and `shouldMove` is true, trigger + // their event both, and the final behavior is determined + // by event listener themselves. + + + if (shouldZoom) { + // Convenience: + // Mac and VM Windows on Mac: scroll up: zoom out. + // Windows: scroll up: zoom in. + // FIXME: Should do more test in different environment. + // wheelDelta is too complicated in difference nvironment + // (https://developer.mozilla.org/en-US/docs/Web/Events/mousewheel), + // although it has been normallized by zrender. + // wheelDelta of mouse wheel is bigger than touch pad. + var factor = absWheelDeltaDelta > 3 ? 1.4 : absWheelDeltaDelta > 1 ? 1.2 : 1.1; + var scale = wheelDelta > 0 ? factor : 1 / factor; + checkPointerAndTrigger(this, 'zoom', 'zoomOnMouseWheel', e, { + scale: scale, + originX: originX, + originY: originY, + isAvailableBehavior: null + }); + } + + if (shouldMove) { + // FIXME: Should do more test in different environment. + var absDelta = Math.abs(wheelDelta); // wheelDelta of mouse wheel is bigger than touch pad. + + var scrollDelta = (wheelDelta > 0 ? 1 : -1) * (absDelta > 3 ? 0.4 : absDelta > 1 ? 0.15 : 0.05); + checkPointerAndTrigger(this, 'scrollMove', 'moveOnMouseWheel', e, { + scrollDelta: scrollDelta, + originX: originX, + originY: originY, + isAvailableBehavior: null + }); + } + }; + + RoamController.prototype._pinchHandler = function (e) { + if (isTaken(this._zr, 'globalPan')) { + return; + } + + var scale = e.pinchScale > 1 ? 1.1 : 1 / 1.1; + checkPointerAndTrigger(this, 'zoom', null, e, { + scale: scale, + originX: e.pinchX, + originY: e.pinchY, + isAvailableBehavior: null + }); + }; + + return RoamController; + }(Eventful); + + function checkPointerAndTrigger(controller, eventName, behaviorToCheck, e, contollerEvent) { + if (controller.pointerChecker && controller.pointerChecker(e, contollerEvent.originX, contollerEvent.originY)) { + // When mouse is out of roamController rect, + // default befavoius should not be be disabled, otherwise + // page sliding is disabled, contrary to expectation. + stop(e.event); + trigger(controller, eventName, behaviorToCheck, e, contollerEvent); + } + } + + function trigger(controller, eventName, behaviorToCheck, e, contollerEvent) { + // Also provide behavior checker for event listener, for some case that + // multiple components share one listener. + contollerEvent.isAvailableBehavior = bind(isAvailableBehavior, null, behaviorToCheck, e); // TODO should not have type issue. + + controller.trigger(eventName, contollerEvent); + } // settings: { + // zoomOnMouseWheel + // moveOnMouseMove + // moveOnMouseWheel + // } + // The value can be: true / false / 'shift' / 'ctrl' / 'alt'. + + + function isAvailableBehavior(behaviorToCheck, e, settings) { + var setting = settings[behaviorToCheck]; + return !behaviorToCheck || setting && (!isString(setting) || e.event[setting + 'Key']); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + /** + * For geo and graph. + */ + function updateViewOnPan(controllerHost, dx, dy) { + var target = controllerHost.target; + target.x += dx; + target.y += dy; + target.dirty(); + } + /** + * For geo and graph. + */ + + function updateViewOnZoom(controllerHost, zoomDelta, zoomX, zoomY) { + var target = controllerHost.target; + var zoomLimit = controllerHost.zoomLimit; + var newZoom = controllerHost.zoom = controllerHost.zoom || 1; + newZoom *= zoomDelta; + + if (zoomLimit) { + var zoomMin = zoomLimit.min || 0; + var zoomMax = zoomLimit.max || Infinity; + newZoom = Math.max(Math.min(zoomMax, newZoom), zoomMin); + } + + var zoomScale = newZoom / controllerHost.zoom; + controllerHost.zoom = newZoom; // Keep the mouse center when scaling + + target.x -= (zoomX - target.x) * (zoomScale - 1); + target.y -= (zoomY - target.y) * (zoomScale - 1); + target.scaleX *= zoomScale; + target.scaleY *= zoomScale; + target.dirty(); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var IRRELEVANT_EXCLUDES = { + 'axisPointer': 1, + 'tooltip': 1, + 'brush': 1 + }; + /** + * Avoid that: mouse click on a elements that is over geo or graph, + * but roam is triggered. + */ + + function onIrrelevantElement(e, api, targetCoordSysModel) { + var model = api.getComponentByElement(e.topTarget); // If model is axisModel, it works only if it is injected with coordinateSystem. + + var coordSys = model && model.coordinateSystem; + return model && model !== targetCoordSysModel && !IRRELEVANT_EXCLUDES.hasOwnProperty(model.mainType) && coordSys && coordSys.model !== targetCoordSysModel; + } + + function parseXML(svg) { + if (isString(svg)) { + var parser = new DOMParser(); + svg = parser.parseFromString(svg, 'text/xml'); + } + var svgNode = svg; + if (svgNode.nodeType === 9) { + svgNode = svgNode.firstChild; + } + while (svgNode.nodeName.toLowerCase() !== 'svg' || svgNode.nodeType !== 1) { + svgNode = svgNode.nextSibling; + } + return svgNode; + } + + var nodeParsers; + var INHERITABLE_STYLE_ATTRIBUTES_MAP = { + 'fill': 'fill', + 'stroke': 'stroke', + 'stroke-width': 'lineWidth', + 'opacity': 'opacity', + 'fill-opacity': 'fillOpacity', + 'stroke-opacity': 'strokeOpacity', + 'stroke-dasharray': 'lineDash', + 'stroke-dashoffset': 'lineDashOffset', + 'stroke-linecap': 'lineCap', + 'stroke-linejoin': 'lineJoin', + 'stroke-miterlimit': 'miterLimit', + 'font-family': 'fontFamily', + 'font-size': 'fontSize', + 'font-style': 'fontStyle', + 'font-weight': 'fontWeight', + 'text-anchor': 'textAlign', + 'visibility': 'visibility', + 'display': 'display' + }; + var INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS = keys(INHERITABLE_STYLE_ATTRIBUTES_MAP); + var SELF_STYLE_ATTRIBUTES_MAP = { + 'alignment-baseline': 'textBaseline', + 'stop-color': 'stopColor' + }; + var SELF_STYLE_ATTRIBUTES_MAP_KEYS = keys(SELF_STYLE_ATTRIBUTES_MAP); + var SVGParser = (function () { + function SVGParser() { + this._defs = {}; + this._root = null; + } + SVGParser.prototype.parse = function (xml, opt) { + opt = opt || {}; + var svg = parseXML(xml); + if ("development" !== 'production') { + if (!svg) { + throw new Error('Illegal svg'); + } + } + this._defsUsePending = []; + var root = new Group(); + this._root = root; + var named = []; + var viewBox = svg.getAttribute('viewBox') || ''; + var width = parseFloat((svg.getAttribute('width') || opt.width)); + var height = parseFloat((svg.getAttribute('height') || opt.height)); + isNaN(width) && (width = null); + isNaN(height) && (height = null); + parseAttributes(svg, root, null, true, false); + var child = svg.firstChild; + while (child) { + this._parseNode(child, root, named, null, false, false); + child = child.nextSibling; + } + applyDefs(this._defs, this._defsUsePending); + this._defsUsePending = []; + var viewBoxRect; + var viewBoxTransform; + if (viewBox) { + var viewBoxArr = splitNumberSequence(viewBox); + if (viewBoxArr.length >= 4) { + viewBoxRect = { + x: parseFloat((viewBoxArr[0] || 0)), + y: parseFloat((viewBoxArr[1] || 0)), + width: parseFloat(viewBoxArr[2]), + height: parseFloat(viewBoxArr[3]) + }; + } + } + if (viewBoxRect && width != null && height != null) { + viewBoxTransform = makeViewBoxTransform(viewBoxRect, { x: 0, y: 0, width: width, height: height }); + if (!opt.ignoreViewBox) { + var elRoot = root; + root = new Group(); + root.add(elRoot); + elRoot.scaleX = elRoot.scaleY = viewBoxTransform.scale; + elRoot.x = viewBoxTransform.x; + elRoot.y = viewBoxTransform.y; + } + } + if (!opt.ignoreRootClip && width != null && height != null) { + root.setClipPath(new Rect({ + shape: { x: 0, y: 0, width: width, height: height } + })); + } + return { + root: root, + width: width, + height: height, + viewBoxRect: viewBoxRect, + viewBoxTransform: viewBoxTransform, + named: named + }; + }; + SVGParser.prototype._parseNode = function (xmlNode, parentGroup, named, namedFrom, isInDefs, isInText) { + var nodeName = xmlNode.nodeName.toLowerCase(); + var el; + var namedFromForSub = namedFrom; + if (nodeName === 'defs') { + isInDefs = true; + } + if (nodeName === 'text') { + isInText = true; + } + if (nodeName === 'defs' || nodeName === 'switch') { + el = parentGroup; + } + else { + if (!isInDefs) { + var parser_1 = nodeParsers[nodeName]; + if (parser_1 && hasOwn(nodeParsers, nodeName)) { + el = parser_1.call(this, xmlNode, parentGroup); + var nameAttr = xmlNode.getAttribute('name'); + if (nameAttr) { + var newNamed = { + name: nameAttr, + namedFrom: null, + svgNodeTagLower: nodeName, + el: el + }; + named.push(newNamed); + if (nodeName === 'g') { + namedFromForSub = newNamed; + } + } + else if (namedFrom) { + named.push({ + name: namedFrom.name, + namedFrom: namedFrom, + svgNodeTagLower: nodeName, + el: el + }); + } + parentGroup.add(el); + } + } + var parser = paintServerParsers[nodeName]; + if (parser && hasOwn(paintServerParsers, nodeName)) { + var def = parser.call(this, xmlNode); + var id = xmlNode.getAttribute('id'); + if (id) { + this._defs[id] = def; + } + } + } + if (el && el.isGroup) { + var child = xmlNode.firstChild; + while (child) { + if (child.nodeType === 1) { + this._parseNode(child, el, named, namedFromForSub, isInDefs, isInText); + } + else if (child.nodeType === 3 && isInText) { + this._parseText(child, el); + } + child = child.nextSibling; + } + } + }; + SVGParser.prototype._parseText = function (xmlNode, parentGroup) { + var text = new TSpan({ + style: { + text: xmlNode.textContent + }, + silent: true, + x: this._textX || 0, + y: this._textY || 0 + }); + inheritStyle(parentGroup, text); + parseAttributes(xmlNode, text, this._defsUsePending, false, false); + applyTextAlignment(text, parentGroup); + var textStyle = text.style; + var fontSize = textStyle.fontSize; + if (fontSize && fontSize < 9) { + textStyle.fontSize = 9; + text.scaleX *= fontSize / 9; + text.scaleY *= fontSize / 9; + } + var font = (textStyle.fontSize || textStyle.fontFamily) && [ + textStyle.fontStyle, + textStyle.fontWeight, + (textStyle.fontSize || 12) + 'px', + textStyle.fontFamily || 'sans-serif' + ].join(' '); + textStyle.font = font; + var rect = text.getBoundingRect(); + this._textX += rect.width; + parentGroup.add(text); + return text; + }; + SVGParser.internalField = (function () { + nodeParsers = { + 'g': function (xmlNode, parentGroup) { + var g = new Group(); + inheritStyle(parentGroup, g); + parseAttributes(xmlNode, g, this._defsUsePending, false, false); + return g; + }, + 'rect': function (xmlNode, parentGroup) { + var rect = new Rect(); + inheritStyle(parentGroup, rect); + parseAttributes(xmlNode, rect, this._defsUsePending, false, false); + rect.setShape({ + x: parseFloat(xmlNode.getAttribute('x') || '0'), + y: parseFloat(xmlNode.getAttribute('y') || '0'), + width: parseFloat(xmlNode.getAttribute('width') || '0'), + height: parseFloat(xmlNode.getAttribute('height') || '0') + }); + rect.silent = true; + return rect; + }, + 'circle': function (xmlNode, parentGroup) { + var circle = new Circle(); + inheritStyle(parentGroup, circle); + parseAttributes(xmlNode, circle, this._defsUsePending, false, false); + circle.setShape({ + cx: parseFloat(xmlNode.getAttribute('cx') || '0'), + cy: parseFloat(xmlNode.getAttribute('cy') || '0'), + r: parseFloat(xmlNode.getAttribute('r') || '0') + }); + circle.silent = true; + return circle; + }, + 'line': function (xmlNode, parentGroup) { + var line = new Line(); + inheritStyle(parentGroup, line); + parseAttributes(xmlNode, line, this._defsUsePending, false, false); + line.setShape({ + x1: parseFloat(xmlNode.getAttribute('x1') || '0'), + y1: parseFloat(xmlNode.getAttribute('y1') || '0'), + x2: parseFloat(xmlNode.getAttribute('x2') || '0'), + y2: parseFloat(xmlNode.getAttribute('y2') || '0') + }); + line.silent = true; + return line; + }, + 'ellipse': function (xmlNode, parentGroup) { + var ellipse = new Ellipse(); + inheritStyle(parentGroup, ellipse); + parseAttributes(xmlNode, ellipse, this._defsUsePending, false, false); + ellipse.setShape({ + cx: parseFloat(xmlNode.getAttribute('cx') || '0'), + cy: parseFloat(xmlNode.getAttribute('cy') || '0'), + rx: parseFloat(xmlNode.getAttribute('rx') || '0'), + ry: parseFloat(xmlNode.getAttribute('ry') || '0') + }); + ellipse.silent = true; + return ellipse; + }, + 'polygon': function (xmlNode, parentGroup) { + var pointsStr = xmlNode.getAttribute('points'); + var pointsArr; + if (pointsStr) { + pointsArr = parsePoints(pointsStr); + } + var polygon = new Polygon({ + shape: { + points: pointsArr || [] + }, + silent: true + }); + inheritStyle(parentGroup, polygon); + parseAttributes(xmlNode, polygon, this._defsUsePending, false, false); + return polygon; + }, + 'polyline': function (xmlNode, parentGroup) { + var pointsStr = xmlNode.getAttribute('points'); + var pointsArr; + if (pointsStr) { + pointsArr = parsePoints(pointsStr); + } + var polyline = new Polyline({ + shape: { + points: pointsArr || [] + }, + silent: true + }); + inheritStyle(parentGroup, polyline); + parseAttributes(xmlNode, polyline, this._defsUsePending, false, false); + return polyline; + }, + 'image': function (xmlNode, parentGroup) { + var img = new ZRImage(); + inheritStyle(parentGroup, img); + parseAttributes(xmlNode, img, this._defsUsePending, false, false); + img.setStyle({ + image: xmlNode.getAttribute('xlink:href') || xmlNode.getAttribute('href'), + x: +xmlNode.getAttribute('x'), + y: +xmlNode.getAttribute('y'), + width: +xmlNode.getAttribute('width'), + height: +xmlNode.getAttribute('height') + }); + img.silent = true; + return img; + }, + 'text': function (xmlNode, parentGroup) { + var x = xmlNode.getAttribute('x') || '0'; + var y = xmlNode.getAttribute('y') || '0'; + var dx = xmlNode.getAttribute('dx') || '0'; + var dy = xmlNode.getAttribute('dy') || '0'; + this._textX = parseFloat(x) + parseFloat(dx); + this._textY = parseFloat(y) + parseFloat(dy); + var g = new Group(); + inheritStyle(parentGroup, g); + parseAttributes(xmlNode, g, this._defsUsePending, false, true); + return g; + }, + 'tspan': function (xmlNode, parentGroup) { + var x = xmlNode.getAttribute('x'); + var y = xmlNode.getAttribute('y'); + if (x != null) { + this._textX = parseFloat(x); + } + if (y != null) { + this._textY = parseFloat(y); + } + var dx = xmlNode.getAttribute('dx') || '0'; + var dy = xmlNode.getAttribute('dy') || '0'; + var g = new Group(); + inheritStyle(parentGroup, g); + parseAttributes(xmlNode, g, this._defsUsePending, false, true); + this._textX += parseFloat(dx); + this._textY += parseFloat(dy); + return g; + }, + 'path': function (xmlNode, parentGroup) { + var d = xmlNode.getAttribute('d') || ''; + var path = createFromString(d); + inheritStyle(parentGroup, path); + parseAttributes(xmlNode, path, this._defsUsePending, false, false); + path.silent = true; + return path; + } + }; + })(); + return SVGParser; + }()); + var paintServerParsers = { + 'lineargradient': function (xmlNode) { + var x1 = parseInt(xmlNode.getAttribute('x1') || '0', 10); + var y1 = parseInt(xmlNode.getAttribute('y1') || '0', 10); + var x2 = parseInt(xmlNode.getAttribute('x2') || '10', 10); + var y2 = parseInt(xmlNode.getAttribute('y2') || '0', 10); + var gradient = new LinearGradient(x1, y1, x2, y2); + parsePaintServerUnit(xmlNode, gradient); + parseGradientColorStops(xmlNode, gradient); + return gradient; + }, + 'radialgradient': function (xmlNode) { + var cx = parseInt(xmlNode.getAttribute('cx') || '0', 10); + var cy = parseInt(xmlNode.getAttribute('cy') || '0', 10); + var r = parseInt(xmlNode.getAttribute('r') || '0', 10); + var gradient = new RadialGradient(cx, cy, r); + parsePaintServerUnit(xmlNode, gradient); + parseGradientColorStops(xmlNode, gradient); + return gradient; + } + }; + function parsePaintServerUnit(xmlNode, gradient) { + var gradientUnits = xmlNode.getAttribute('gradientUnits'); + if (gradientUnits === 'userSpaceOnUse') { + gradient.global = true; + } + } + function parseGradientColorStops(xmlNode, gradient) { + var stop = xmlNode.firstChild; + while (stop) { + if (stop.nodeType === 1 + && stop.nodeName.toLocaleLowerCase() === 'stop') { + var offsetStr = stop.getAttribute('offset'); + var offset = void 0; + if (offsetStr && offsetStr.indexOf('%') > 0) { + offset = parseInt(offsetStr, 10) / 100; + } + else if (offsetStr) { + offset = parseFloat(offsetStr); + } + else { + offset = 0; + } + var styleVals = {}; + parseInlineStyle(stop, styleVals, styleVals); + var stopColor = styleVals.stopColor + || stop.getAttribute('stop-color') + || '#000000'; + gradient.colorStops.push({ + offset: offset, + color: stopColor + }); + } + stop = stop.nextSibling; + } + } + function inheritStyle(parent, child) { + if (parent && parent.__inheritedStyle) { + if (!child.__inheritedStyle) { + child.__inheritedStyle = {}; + } + defaults(child.__inheritedStyle, parent.__inheritedStyle); + } + } + function parsePoints(pointsString) { + var list = splitNumberSequence(pointsString); + var points = []; + for (var i = 0; i < list.length; i += 2) { + var x = parseFloat(list[i]); + var y = parseFloat(list[i + 1]); + points.push([x, y]); + } + return points; + } + function parseAttributes(xmlNode, el, defsUsePending, onlyInlineStyle, isTextGroup) { + var disp = el; + var inheritedStyle = disp.__inheritedStyle = disp.__inheritedStyle || {}; + var selfStyle = {}; + if (xmlNode.nodeType === 1) { + parseTransformAttribute(xmlNode, el); + parseInlineStyle(xmlNode, inheritedStyle, selfStyle); + if (!onlyInlineStyle) { + parseAttributeStyle(xmlNode, inheritedStyle, selfStyle); + } + } + disp.style = disp.style || {}; + if (inheritedStyle.fill != null) { + disp.style.fill = getFillStrokeStyle(disp, 'fill', inheritedStyle.fill, defsUsePending); + } + if (inheritedStyle.stroke != null) { + disp.style.stroke = getFillStrokeStyle(disp, 'stroke', inheritedStyle.stroke, defsUsePending); + } + each([ + 'lineWidth', 'opacity', 'fillOpacity', 'strokeOpacity', 'miterLimit', 'fontSize' + ], function (propName) { + if (inheritedStyle[propName] != null) { + disp.style[propName] = parseFloat(inheritedStyle[propName]); + } + }); + each([ + 'lineDashOffset', 'lineCap', 'lineJoin', 'fontWeight', 'fontFamily', 'fontStyle', 'textAlign' + ], function (propName) { + if (inheritedStyle[propName] != null) { + disp.style[propName] = inheritedStyle[propName]; + } + }); + if (isTextGroup) { + disp.__selfStyle = selfStyle; + } + if (inheritedStyle.lineDash) { + disp.style.lineDash = map(splitNumberSequence(inheritedStyle.lineDash), function (str) { + return parseFloat(str); + }); + } + if (inheritedStyle.visibility === 'hidden' || inheritedStyle.visibility === 'collapse') { + disp.invisible = true; + } + if (inheritedStyle.display === 'none') { + disp.ignore = true; + } + } + function applyTextAlignment(text, parentGroup) { + var parentSelfStyle = parentGroup.__selfStyle; + if (parentSelfStyle) { + var textBaseline = parentSelfStyle.textBaseline; + var zrTextBaseline = textBaseline; + if (!textBaseline || textBaseline === 'auto') { + zrTextBaseline = 'alphabetic'; + } + else if (textBaseline === 'baseline') { + zrTextBaseline = 'alphabetic'; + } + else if (textBaseline === 'before-edge' || textBaseline === 'text-before-edge') { + zrTextBaseline = 'top'; + } + else if (textBaseline === 'after-edge' || textBaseline === 'text-after-edge') { + zrTextBaseline = 'bottom'; + } + else if (textBaseline === 'central' || textBaseline === 'mathematical') { + zrTextBaseline = 'middle'; + } + text.style.textBaseline = zrTextBaseline; + } + var parentInheritedStyle = parentGroup.__inheritedStyle; + if (parentInheritedStyle) { + var textAlign = parentInheritedStyle.textAlign; + var zrTextAlign = textAlign; + if (textAlign) { + if (textAlign === 'middle') { + zrTextAlign = 'center'; + } + text.style.textAlign = zrTextAlign; + } + } + } + var urlRegex = /^url\(\s*#(.*?)\)/; + function getFillStrokeStyle(el, method, str, defsUsePending) { + var urlMatch = str && str.match(urlRegex); + if (urlMatch) { + var url = trim(urlMatch[1]); + defsUsePending.push([el, method, url]); + return; + } + if (str === 'none') { + str = null; + } + return str; + } + function applyDefs(defs, defsUsePending) { + for (var i = 0; i < defsUsePending.length; i++) { + var item = defsUsePending[i]; + item[0].style[item[1]] = defs[item[2]]; + } + } + var numberReg$1 = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g; + function splitNumberSequence(rawStr) { + return rawStr.match(numberReg$1) || []; + } + var transformRegex = /(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.eE,]*)\)/g; + var DEGREE_TO_ANGLE = Math.PI / 180; + function parseTransformAttribute(xmlNode, node) { + var transform = xmlNode.getAttribute('transform'); + if (transform) { + transform = transform.replace(/,/g, ' '); + var transformOps_1 = []; + var mt = null; + transform.replace(transformRegex, function (str, type, value) { + transformOps_1.push(type, value); + return ''; + }); + for (var i = transformOps_1.length - 1; i > 0; i -= 2) { + var value = transformOps_1[i]; + var type = transformOps_1[i - 1]; + var valueArr = splitNumberSequence(value); + mt = mt || create$1(); + switch (type) { + case 'translate': + translate(mt, mt, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || '0')]); + break; + case 'scale': + scale$1(mt, mt, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || valueArr[0])]); + break; + case 'rotate': + rotate(mt, mt, -parseFloat(valueArr[0]) * DEGREE_TO_ANGLE); + break; + case 'skewX': + var sx = Math.tan(parseFloat(valueArr[0]) * DEGREE_TO_ANGLE); + mul$1(mt, [1, 0, sx, 1, 0, 0], mt); + break; + case 'skewY': + var sy = Math.tan(parseFloat(valueArr[0]) * DEGREE_TO_ANGLE); + mul$1(mt, [1, sy, 0, 1, 0, 0], mt); + break; + case 'matrix': + mt[0] = parseFloat(valueArr[0]); + mt[1] = parseFloat(valueArr[1]); + mt[2] = parseFloat(valueArr[2]); + mt[3] = parseFloat(valueArr[3]); + mt[4] = parseFloat(valueArr[4]); + mt[5] = parseFloat(valueArr[5]); + break; + } + } + node.setLocalTransform(mt); + } + } + var styleRegex = /([^\s:;]+)\s*:\s*([^:;]+)/g; + function parseInlineStyle(xmlNode, inheritableStyleResult, selfStyleResult) { + var style = xmlNode.getAttribute('style'); + if (!style) { + return; + } + styleRegex.lastIndex = 0; + var styleRegResult; + while ((styleRegResult = styleRegex.exec(style)) != null) { + var svgStlAttr = styleRegResult[1]; + var zrInheritableStlAttr = hasOwn(INHERITABLE_STYLE_ATTRIBUTES_MAP, svgStlAttr) + ? INHERITABLE_STYLE_ATTRIBUTES_MAP[svgStlAttr] + : null; + if (zrInheritableStlAttr) { + inheritableStyleResult[zrInheritableStlAttr] = styleRegResult[2]; + } + var zrSelfStlAttr = hasOwn(SELF_STYLE_ATTRIBUTES_MAP, svgStlAttr) + ? SELF_STYLE_ATTRIBUTES_MAP[svgStlAttr] + : null; + if (zrSelfStlAttr) { + selfStyleResult[zrSelfStlAttr] = styleRegResult[2]; + } + } + } + function parseAttributeStyle(xmlNode, inheritableStyleResult, selfStyleResult) { + for (var i = 0; i < INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS.length; i++) { + var svgAttrName = INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS[i]; + var attrValue = xmlNode.getAttribute(svgAttrName); + if (attrValue != null) { + inheritableStyleResult[INHERITABLE_STYLE_ATTRIBUTES_MAP[svgAttrName]] = attrValue; + } + } + for (var i = 0; i < SELF_STYLE_ATTRIBUTES_MAP_KEYS.length; i++) { + var svgAttrName = SELF_STYLE_ATTRIBUTES_MAP_KEYS[i]; + var attrValue = xmlNode.getAttribute(svgAttrName); + if (attrValue != null) { + selfStyleResult[SELF_STYLE_ATTRIBUTES_MAP[svgAttrName]] = attrValue; + } + } + } + function makeViewBoxTransform(viewBoxRect, boundingRect) { + var scaleX = boundingRect.width / viewBoxRect.width; + var scaleY = boundingRect.height / viewBoxRect.height; + var scale = Math.min(scaleX, scaleY); + return { + scale: scale, + x: -(viewBoxRect.x + viewBoxRect.width / 2) * scale + (boundingRect.x + boundingRect.width / 2), + y: -(viewBoxRect.y + viewBoxRect.height / 2) * scale + (boundingRect.y + boundingRect.height / 2) + }; + } + function parseSVG(xml, opt) { + var parser = new SVGParser(); + return parser.parse(xml, opt); + } + + /** + * "region available" means that: enable users to set attribute `name="xxx"` on those tags + * to make it be a region. + * 1. region styles and its label styles can be defined in echarts opton: + * ```js + * geo: { + * regions: [{ + * name: 'xxx', + * itemStyle: { ... }, + * label: { ... } + * }, { + * ... + * }, + * ...] + * }; + * ``` + * 2. name can be duplicated in different SVG tag. All of the tags with the same name share + * a region option. For exampel if there are two representing two lung lobes. They have + * no common parents but both of them need to display label "lung" inside. + */ + + var REGION_AVAILABLE_SVG_TAG_MAP = createHashMap(['rect', 'circle', 'line', 'ellipse', 'polygon', 'polyline', 'path', // are also enabled becuase some SVG might paint text itself, + // but still need to trigger events or tooltip. + 'text', 'tspan', // is also enabled because this case: if multiple tags share one name + // and need label displayed, every tags will display the name, which is not + // expected. So we can put them into a . Thereby only one label + // displayed and located based on the bounding rect of the . + 'g']); + + var GeoSVGResource = + /** @class */ + function () { + function GeoSVGResource(mapName, svg) { + this.type = 'geoSVG'; // All used graphics. key: hostKey, value: root + + this._usedGraphicMap = createHashMap(); // All unused graphics. + + this._freedGraphics = []; + this._mapName = mapName; // Only perform parse to XML object here, which might be time + // consiming for large SVG. + // Although convert XML to zrender element is also time consiming, + // if we do it here, the clone of zrender elements has to be + // required. So we do it once for each geo instance, util real + // performance issues call for optimizing it. + + this._parsedXML = parseXML(svg); + } + + GeoSVGResource.prototype.load = function () + /* nameMap: NameMap */ + { + // In the "load" stage, graphic need to be built to + // get boundingRect for geo coordinate system. + var firstGraphic = this._firstGraphic; // Create the return data structure only when first graphic created. + // Because they will be used in geo coordinate system update stage, + // and `regions` will be mounted at `geo` coordinate system, + // in which there is no "view" info, so that it should better not to + // make references to graphic elements. + + if (!firstGraphic) { + firstGraphic = this._firstGraphic = this._buildGraphic(this._parsedXML); + + this._freedGraphics.push(firstGraphic); + + this._boundingRect = this._firstGraphic.boundingRect.clone(); // PENDING: `nameMap` will not be supported until some real requirement come. + // if (nameMap) { + // named = applyNameMap(named, nameMap); + // } + + var _a = createRegions(firstGraphic.named), + regions = _a.regions, + regionsMap = _a.regionsMap; + + this._regions = regions; + this._regionsMap = regionsMap; + } + + return { + boundingRect: this._boundingRect, + regions: this._regions, + regionsMap: this._regionsMap + }; + }; + + GeoSVGResource.prototype._buildGraphic = function (svgXML) { + var result; + var rootFromParse; + + try { + result = svgXML && parseSVG(svgXML, { + ignoreViewBox: true, + ignoreRootClip: true + }) || {}; + rootFromParse = result.root; + assert(rootFromParse != null); + } catch (e) { + throw new Error('Invalid svg format\n' + e.message); + } // Note: we keep the covenant that the root has no transform. So always add an extra root. + + + var root = new Group(); + root.add(rootFromParse); + root.isGeoSVGGraphicRoot = true; // [THE_RULE_OF_VIEWPORT_AND_VIEWBOX] + // + // Consider: `` + // - the `width/height` we call it `svgWidth/svgHeight` for short. + // - `(0, 0, svgWidth, svgHeight)` defines the viewport of the SVG, or say, + // "viewport boundingRect", or `boundingRect` for short. + // - `viewBox` defines the transform from the real content ot the viewport. + // `viewBox` has the same unit as the content of SVG. + // If `viewBox` exists, a transform is defined, so the unit of `svgWidth/svgHeight` become + // different from the content of SVG. Otherwise, they are the same. + // + // If both `svgWidth/svgHeight/viewBox` are specified in a SVG file, the transform rule will be: + // 0. `boundingRect` is `(0, 0, svgWidth, svgHeight)`. Set it to Geo['_rect'] (View['_rect']). + // 1. Make a transform from `viewBox` to `boundingRect`. + // Note: only suport `preserveAspectRatio 'xMidYMid'` here. That is, this transform will preserve + // the aspect ratio. + // 2. Make a transform from boundingRect to Geo['_viewRect'] (View['_viewRect']) + // (`Geo`/`View` will do this job). + // Note: this transform might not preserve aspect radio, which depending on how users specify + // viewRect in echarts option (e.g., `geo.left/top/width/height` will not preserve aspect ratio, + // but `geo.layoutCenter/layoutSize` will preserve aspect ratio). + // + // If `svgWidth/svgHeight` not specified, we use `viewBox` as the `boundingRect` to make the SVG + // layout look good. + // + // If neither `svgWidth/svgHeight` nor `viewBox` are not specified, we calculate the boundingRect + // of the SVG content and use them to make SVG layout look good. + + var svgWidth = result.width; + var svgHeight = result.height; + var viewBoxRect = result.viewBoxRect; + var boundingRect = this._boundingRect; + + if (!boundingRect) { + var bRectX = void 0; + var bRectY = void 0; + var bRectWidth = void 0; + var bRectHeight = void 0; + + if (svgWidth != null) { + bRectX = 0; + bRectWidth = svgWidth; + } else if (viewBoxRect) { + bRectX = viewBoxRect.x; + bRectWidth = viewBoxRect.width; + } + + if (svgHeight != null) { + bRectY = 0; + bRectHeight = svgHeight; + } else if (viewBoxRect) { + bRectY = viewBoxRect.y; + bRectHeight = viewBoxRect.height; + } // If both viewBox and svgWidth/svgHeight not specified, + // we have to determine how to layout those element to make them look good. + + + if (bRectX == null || bRectY == null) { + var calculatedBoundingRect = rootFromParse.getBoundingRect(); + + if (bRectX == null) { + bRectX = calculatedBoundingRect.x; + bRectWidth = calculatedBoundingRect.width; + } + + if (bRectY == null) { + bRectY = calculatedBoundingRect.y; + bRectHeight = calculatedBoundingRect.height; + } + } + + boundingRect = this._boundingRect = new BoundingRect(bRectX, bRectY, bRectWidth, bRectHeight); + } + + if (viewBoxRect) { + var viewBoxTransform = makeViewBoxTransform(viewBoxRect, boundingRect); // Only support `preserveAspectRatio 'xMidYMid'` + + rootFromParse.scaleX = rootFromParse.scaleY = viewBoxTransform.scale; + rootFromParse.x = viewBoxTransform.x; + rootFromParse.y = viewBoxTransform.y; + } // SVG needs to clip based on `viewBox`. And some SVG files really rely on this feature. + // They do not strictly confine all of the content inside a display rect, but deliberately + // use a `viewBox` to define a displayable rect. + // PENDING: + // The drawback of the `setClipPath` here is: the region label (genereted by echarts) near the + // edge might also be clipped, because region labels are put as `textContent` of the SVG path. + + + root.setClipPath(new Rect({ + shape: boundingRect.plain() + })); + var named = []; + each(result.named, function (namedItem) { + if (REGION_AVAILABLE_SVG_TAG_MAP.get(namedItem.svgNodeTagLower) != null) { + named.push(namedItem); + setSilent(namedItem.el); + } + }); + return { + root: root, + boundingRect: boundingRect, + named: named + }; + }; + /** + * Consider: + * (1) One graphic element can not be shared by different `geoView` running simultaneously. + * Notice, also need to consider multiple echarts instances share a `mapRecord`. + * (2) Converting SVG to graphic elements is time consuming. + * (3) In the current architecture, `load` should be called frequently to get boundingRect, + * and it is called without view info. + * So we maintain graphic elements in this module, and enables `view` to use/return these + * graphics from/to the pool with it's uid. + */ + + + GeoSVGResource.prototype.useGraphic = function (hostKey + /*, nameMap: NameMap */ + ) { + var usedRootMap = this._usedGraphicMap; + var svgGraphic = usedRootMap.get(hostKey); + + if (svgGraphic) { + return svgGraphic; + } + + svgGraphic = this._freedGraphics.pop() // use the first boundingRect to avoid duplicated boundingRect calculation. + || this._buildGraphic(this._parsedXML); + usedRootMap.set(hostKey, svgGraphic); // PENDING: `nameMap` will not be supported until some real requirement come. + // `nameMap` can only be obtained from echarts option. + // The original `named` must not be modified. + // if (nameMap) { + // svgGraphic = extend({}, svgGraphic); + // svgGraphic.named = applyNameMap(svgGraphic.named, nameMap); + // } + + return svgGraphic; + }; + + GeoSVGResource.prototype.freeGraphic = function (hostKey) { + var usedRootMap = this._usedGraphicMap; + var svgGraphic = usedRootMap.get(hostKey); + + if (svgGraphic) { + usedRootMap.removeKey(hostKey); + + this._freedGraphics.push(svgGraphic); + } + }; + + return GeoSVGResource; + }(); + + function setSilent(el) { + // Only named element has silent: false, other elements should + // act as background and has no user interaction. + el.silent = false; // text|tspan will be converted to group. + + if (el.isGroup) { + el.traverse(function (child) { + child.silent = false; + }); + } + } + + function createRegions(named) { + var regions = []; + var regionsMap = createHashMap(); // Create resions only for the first graphic. + + each(named, function (namedItem) { + // Region has feature to calculate center for tooltip or other features. + // If there is a , the center should be the center of the + // bounding rect of the g. + if (namedItem.namedFrom != null) { + return; + } + + var region = new GeoSVGRegion(namedItem.name, namedItem.el); // PENDING: if `nameMap` supported, this region can not be mounted on + // `this`, but can only be created each time `load()` called. + + regions.push(region); // PENDING: if multiple tag named with the same name, only one will be + // found by `_regionsMap`. `_regionsMap` is used to find a coordinate + // by name. We use `region.getCenter()` as the coordinate. + + regionsMap.set(namedItem.name, region); + }); + return { + regions: regions, + regionsMap: regionsMap + }; + } // PENDING: `nameMap` will not be supported until some real requirement come. + // /** + // * Use the alias in geoNameMap. + // * The input `named` must not be modified. + // */ + // function applyNameMap( + // named: GeoSVGGraphicRecord['named'], + // nameMap: NameMap + // ): GeoSVGGraphicRecord['named'] { + // const result = [] as GeoSVGGraphicRecord['named']; + // for (let i = 0; i < named.length; i++) { + // let regionGraphic = named[i]; + // const name = regionGraphic.name; + // if (nameMap && nameMap.hasOwnProperty(name)) { + // regionGraphic = extend({}, regionGraphic); + // regionGraphic.name = name; + // } + // result.push(regionGraphic); + // } + // return result; + // } + + var geoCoord = [126, 25]; + var nanhaiName = '南海诸岛'; + var points$1 = [[[0, 3.5], [7, 11.2], [15, 11.9], [30, 7], [42, 0.7], [52, 0.7], [56, 7.7], [59, 0.7], [64, 0.7], [64, 0], [5, 0], [0, 3.5]], [[13, 16.1], [19, 14.7], [16, 21.7], [11, 23.1], [13, 16.1]], [[12, 32.2], [14, 38.5], [15, 38.5], [13, 32.2], [12, 32.2]], [[16, 47.6], [12, 53.2], [13, 53.2], [18, 47.6], [16, 47.6]], [[6, 64.4], [8, 70], [9, 70], [8, 64.4], [6, 64.4]], [[23, 82.6], [29, 79.8], [30, 79.8], [25, 82.6], [23, 82.6]], [[37, 70.7], [43, 62.3], [44, 62.3], [39, 70.7], [37, 70.7]], [[48, 51.1], [51, 45.5], [53, 45.5], [50, 51.1], [48, 51.1]], [[51, 35], [51, 28.7], [53, 28.7], [53, 35], [51, 35]], [[52, 22.4], [55, 17.5], [56, 17.5], [53, 22.4], [52, 22.4]], [[58, 12.6], [62, 7], [63, 7], [60, 12.6], [58, 12.6]], [[0, 3.5], [0, 93.1], [64, 93.1], [64, 0], [63, 0], [63, 92.4], [1, 92.4], [1, 3.5], [0, 3.5]]]; + + for (var i = 0; i < points$1.length; i++) { + for (var k = 0; k < points$1[i].length; k++) { + points$1[i][k][0] /= 10.5; + points$1[i][k][1] /= -10.5 / 0.75; + points$1[i][k][0] += geoCoord[0]; + points$1[i][k][1] += geoCoord[1]; + } + } + + function fixNanhai(mapType, regions) { + if (mapType === 'china') { + for (var i = 0; i < regions.length; i++) { + // Already exists. + if (regions[i].name === nanhaiName) { + return; + } + } + + regions.push(new GeoJSONRegion(nanhaiName, map(points$1, function (exterior) { + return { + type: 'polygon', + exterior: exterior + }; + }), geoCoord)); + } + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var coordsOffsetMap = { + '南海诸岛': [32, 80], + // 全国 + '广东': [0, -10], + '香港': [10, 5], + '澳门': [-10, 10], + //'北京': [-10, 0], + '天津': [5, 5] + }; + function fixTextCoords(mapType, region) { + if (mapType === 'china') { + var coordFix = coordsOffsetMap[region.name]; + + if (coordFix) { + var cp = region.getCenter(); + cp[0] += coordFix[0] / 10.5; + cp[1] += -coordFix[1] / (10.5 / 0.75); + region.setCenter(cp); + } + } + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // Fix for 钓鱼岛 + // let Region = require('../Region'); + // let zrUtil = require('zrender/lib/core/util'); + // let geoCoord = [126, 25]; + var points$2 = [[[123.45165252685547, 25.73527164402261], [123.49731445312499, 25.73527164402261], [123.49731445312499, 25.750734064600884], [123.45165252685547, 25.750734064600884], [123.45165252685547, 25.73527164402261]]]; + function fixDiaoyuIsland(mapType, region) { + if (mapType === 'china' && region.name === '台湾') { + region.geometries.push({ + type: 'polygon', + exterior: points$2[0] + }); + } + } + + var DEFAULT_NAME_PROPERTY = 'name'; + + var GeoJSONResource = + /** @class */ + function () { + function GeoJSONResource(mapName, geoJSON, specialAreas) { + this.type = 'geoJSON'; + this._parsedMap = createHashMap(); + this._mapName = mapName; + this._specialAreas = specialAreas; // PENDING: delay the parse to the first usage to rapid up the FMP? + + this._geoJSON = parseInput(geoJSON); + } + /** + * @param nameMap can be null/undefined + * @param nameProperty can be null/undefined + */ + + + GeoJSONResource.prototype.load = function (nameMap, nameProperty) { + nameProperty = nameProperty || DEFAULT_NAME_PROPERTY; + + var parsed = this._parsedMap.get(nameProperty); + + if (!parsed) { + var rawRegions = this._parseToRegions(nameProperty); + + parsed = this._parsedMap.set(nameProperty, { + regions: rawRegions, + boundingRect: calculateBoundingRect(rawRegions) + }); + } + + var regionsMap = createHashMap(); + var finalRegions = []; + each(parsed.regions, function (region) { + var regionName = region.name; // Try use the alias in geoNameMap + + if (nameMap && hasOwn(nameMap, regionName)) { + region = region.cloneShallow(regionName = nameMap[regionName]); + } + + finalRegions.push(region); + regionsMap.set(regionName, region); + }); + return { + regions: finalRegions, + boundingRect: parsed.boundingRect || new BoundingRect(0, 0, 0, 0), + regionsMap: regionsMap + }; + }; + + GeoJSONResource.prototype._parseToRegions = function (nameProperty) { + var mapName = this._mapName; + var geoJSON = this._geoJSON; + var rawRegions; // https://jsperf.com/try-catch-performance-overhead + + try { + rawRegions = geoJSON ? parseGeoJSON(geoJSON, nameProperty) : []; + } catch (e) { + throw new Error('Invalid geoJson format\n' + e.message); + } + + fixNanhai(mapName, rawRegions); + each(rawRegions, function (region) { + var regionName = region.name; + fixTextCoords(mapName, region); + fixDiaoyuIsland(mapName, region); // Some area like Alaska in USA map needs to be tansformed + // to look better + + var specialArea = this._specialAreas && this._specialAreas[regionName]; + + if (specialArea) { + region.transformTo(specialArea.left, specialArea.top, specialArea.width, specialArea.height); + } + }, this); + return rawRegions; + }; + /** + * Only for exporting to users. + * **MUST NOT** used internally. + */ + + + GeoJSONResource.prototype.getMapForUser = function () { + return { + // For backward compatibility, use geoJson + // PENDING: it has been returning them without clone. + // do we need to avoid outsite modification? + geoJson: this._geoJSON, + geoJSON: this._geoJSON, + specialAreas: this._specialAreas + }; + }; + + return GeoJSONResource; + }(); + + function calculateBoundingRect(regions) { + var rect; + + for (var i = 0; i < regions.length; i++) { + var regionRect = regions[i].getBoundingRect(); + rect = rect || regionRect.clone(); + rect.union(regionRect); + } + + return rect; + } + + function parseInput(source) { + return !isString(source) ? source : typeof JSON !== 'undefined' && JSON.parse ? JSON.parse(source) : new Function('return (' + source + ');')(); + } + + var storage = createHashMap(); + var geoSourceManager = { + /** + * Compatible with previous `echarts.registerMap`. + * + * @usage + * ```js + * + * echarts.registerMap('USA', geoJson, specialAreas); + * + * echarts.registerMap('USA', { + * geoJson: geoJson, + * specialAreas: {...} + * }); + * echarts.registerMap('USA', { + * geoJSON: geoJson, + * specialAreas: {...} + * }); + * + * echarts.registerMap('airport', { + * svg: svg + * } + * ``` + * + * Note: + * Do not support that register multiple geoJSON or SVG + * one map name. Because different geoJSON and SVG have + * different unit. It's not easy to make sure how those + * units are mapping/normalize. + * If intending to use multiple geoJSON or SVG, we can + * use multiple geo coordinate system. + */ + registerMap: function (mapName, rawDef, rawSpecialAreas) { + if (rawDef.svg) { + var resource = new GeoSVGResource(mapName, rawDef.svg); + storage.set(mapName, resource); + } else { + // Recommend: + // echarts.registerMap('eu', { geoJSON: xxx, specialAreas: xxx }); + // Backward compatibility: + // echarts.registerMap('eu', geoJSON, specialAreas); + // echarts.registerMap('eu', { geoJson: xxx, specialAreas: xxx }); + var geoJSON = rawDef.geoJson || rawDef.geoJSON; + + if (geoJSON && !rawDef.features) { + rawSpecialAreas = rawDef.specialAreas; + } else { + geoJSON = rawDef; + } + + var resource = new GeoJSONResource(mapName, geoJSON, rawSpecialAreas); + storage.set(mapName, resource); + } + }, + getGeoResource: function (mapName) { + return storage.get(mapName); + }, + + /** + * Only for exporting to users. + * **MUST NOT** used internally. + */ + getMapForUser: function (mapName) { + var resource = storage.get(mapName); // Do not support return SVG until some real requirement come. + + return resource && resource.type === 'geoJSON' && resource.getMapForUser(); + }, + load: function (mapName, nameMap, nameProperty) { + var resource = storage.get(mapName); + + if (!resource) { + if ("development" !== 'production') { + console.error('Map ' + mapName + ' not exists. The GeoJSON of the map must be provided.'); + } + + return; + } + + return resource.load(nameMap, nameProperty); + } + }; + + /** + * Only these tags enable use `itemStyle` if they are named in SVG. + * Other tags like might not suitable for `itemStyle`. + * They will not be considered to be styled until some requirements come. + */ + + var OPTION_STYLE_ENABLED_TAGS = ['rect', 'circle', 'line', 'ellipse', 'polygon', 'polyline', 'path']; + var OPTION_STYLE_ENABLED_TAG_MAP = createHashMap(OPTION_STYLE_ENABLED_TAGS); + var STATE_TRIGGER_TAG_MAP = createHashMap(OPTION_STYLE_ENABLED_TAGS.concat(['g'])); + var LABEL_HOST_MAP = createHashMap(OPTION_STYLE_ENABLED_TAGS.concat(['g'])); + var mapLabelRaw = makeInner(); + + function getFixedItemStyle(model) { + var itemStyle = model.getItemStyle(); + var areaColor = model.get('areaColor'); // If user want the color not to be changed when hover, + // they should both set areaColor and color to be null. + + if (areaColor != null) { + itemStyle.fill = areaColor; + } + + return itemStyle; + } // Only stroke can be used for line. + // Using fill in style if stroke not exits. + // TODO Not sure yet. Perhaps a separate `lineStyle`? + + + function fixLineStyle(styleHost) { + var style = styleHost.style; + + if (style) { + style.stroke = style.stroke || style.fill; + style.fill = null; + } + } + + var MapDraw = + /** @class */ + function () { + function MapDraw(api) { + var group = new Group(); + this.uid = getUID('ec_map_draw'); + this._controller = new RoamController(api.getZr()); + this._controllerHost = { + target: group + }; + this.group = group; + group.add(this._regionsGroup = new Group()); + group.add(this._svgGroup = new Group()); + } + + MapDraw.prototype.draw = function (mapOrGeoModel, ecModel, api, fromView, payload) { + var isGeo = mapOrGeoModel.mainType === 'geo'; // Map series has data. GEO model that controlled by map series + // will be assigned with map data. Other GEO model has no data. + + var data = mapOrGeoModel.getData && mapOrGeoModel.getData(); + isGeo && ecModel.eachComponent({ + mainType: 'series', + subType: 'map' + }, function (mapSeries) { + if (!data && mapSeries.getHostGeoModel() === mapOrGeoModel) { + data = mapSeries.getData(); + } + }); + var geo = mapOrGeoModel.coordinateSystem; + var regionsGroup = this._regionsGroup; + var group = this.group; + var transformInfo = geo.getTransformInfo(); + var transformInfoRaw = transformInfo.raw; + var transformInfoRoam = transformInfo.roam; // No animation when first draw or in action + + var isFirstDraw = !regionsGroup.childAt(0) || payload; + + if (isFirstDraw) { + group.x = transformInfoRoam.x; + group.y = transformInfoRoam.y; + group.scaleX = transformInfoRoam.scaleX; + group.scaleY = transformInfoRoam.scaleY; + group.dirty(); + } else { + updateProps(group, transformInfoRoam, mapOrGeoModel); + } + + var isVisualEncodedByVisualMap = data && data.getVisual('visualMeta') && data.getVisual('visualMeta').length > 0; + var viewBuildCtx = { + api: api, + geo: geo, + mapOrGeoModel: mapOrGeoModel, + data: data, + isVisualEncodedByVisualMap: isVisualEncodedByVisualMap, + isGeo: isGeo, + transformInfoRaw: transformInfoRaw + }; + + if (geo.resourceType === 'geoJSON') { + this._buildGeoJSON(viewBuildCtx); + } else if (geo.resourceType === 'geoSVG') { + this._buildSVG(viewBuildCtx); + } + + this._updateController(mapOrGeoModel, ecModel, api); + + this._updateMapSelectHandler(mapOrGeoModel, regionsGroup, api, fromView); + }; + + MapDraw.prototype._buildGeoJSON = function (viewBuildCtx) { + var regionsGroupByName = this._regionsGroupByName = createHashMap(); + var regionsInfoByName = createHashMap(); + var regionsGroup = this._regionsGroup; + var transformInfoRaw = viewBuildCtx.transformInfoRaw; + var mapOrGeoModel = viewBuildCtx.mapOrGeoModel; + var data = viewBuildCtx.data; + var projection = viewBuildCtx.geo.projection; + var projectionStream = projection && projection.stream; + + function transformPoint(point, project) { + if (project) { + // projection may return null point. + point = project(point); + } + + return point && [point[0] * transformInfoRaw.scaleX + transformInfoRaw.x, point[1] * transformInfoRaw.scaleY + transformInfoRaw.y]; + } + + function transformPolygonPoints(inPoints) { + var outPoints = []; // If projectionStream is provided. Use it instead of single point project. + + var project = !projectionStream && projection && projection.project; + + for (var i = 0; i < inPoints.length; ++i) { + var newPt = transformPoint(inPoints[i], project); + newPt && outPoints.push(newPt); + } + + return outPoints; + } + + function getPolyShape(points) { + return { + shape: { + points: transformPolygonPoints(points) + } + }; + } + + regionsGroup.removeAll(); // Only when the resource is GeoJSON, there is `geo.regions`. + + each(viewBuildCtx.geo.regions, function (region) { + var regionName = region.name; // Consider in GeoJson properties.name may be duplicated, for example, + // there is multiple region named "United Kindom" or "France" (so many + // colonies). And it is not appropriate to merge them in geo, which + // will make them share the same label and bring trouble in label + // location calculation. + + var regionGroup = regionsGroupByName.get(regionName); + + var _a = regionsInfoByName.get(regionName) || {}, + dataIdx = _a.dataIdx, + regionModel = _a.regionModel; + + if (!regionGroup) { + regionGroup = regionsGroupByName.set(regionName, new Group()); + regionsGroup.add(regionGroup); + dataIdx = data ? data.indexOfName(regionName) : null; + regionModel = viewBuildCtx.isGeo ? mapOrGeoModel.getRegionModel(regionName) : data ? data.getItemModel(dataIdx) : null; + regionsInfoByName.set(regionName, { + dataIdx: dataIdx, + regionModel: regionModel + }); + } + + var polygonSubpaths = []; + var polylineSubpaths = []; + each(region.geometries, function (geometry) { + // Polygon and MultiPolygon + if (geometry.type === 'polygon') { + var polys = [geometry.exterior].concat(geometry.interiors || []); + + if (projectionStream) { + polys = projectPolys(polys, projectionStream); + } + + each(polys, function (poly) { + polygonSubpaths.push(new Polygon(getPolyShape(poly))); + }); + } // LineString and MultiLineString + else { + var points = geometry.points; + + if (projectionStream) { + points = projectPolys(points, projectionStream, true); + } + + each(points, function (points) { + polylineSubpaths.push(new Polyline(getPolyShape(points))); + }); + } + }); + var centerPt = transformPoint(region.getCenter(), projection && projection.project); + + function createCompoundPath(subpaths, isLine) { + if (!subpaths.length) { + return; + } + + var compoundPath = new CompoundPath({ + culling: true, + segmentIgnoreThreshold: 1, + shape: { + paths: subpaths + } + }); + regionGroup.add(compoundPath); + applyOptionStyleForRegion(viewBuildCtx, compoundPath, dataIdx, regionModel); + resetLabelForRegion(viewBuildCtx, compoundPath, regionName, regionModel, mapOrGeoModel, dataIdx, centerPt); + + if (isLine) { + fixLineStyle(compoundPath); + each(compoundPath.states, fixLineStyle); + } + } + + createCompoundPath(polygonSubpaths); + createCompoundPath(polylineSubpaths, true); + }); // Ensure children have been added to `regionGroup` before calling them. + + regionsGroupByName.each(function (regionGroup, regionName) { + var _a = regionsInfoByName.get(regionName), + dataIdx = _a.dataIdx, + regionModel = _a.regionModel; + + resetEventTriggerForRegion(viewBuildCtx, regionGroup, regionName, regionModel, mapOrGeoModel, dataIdx); + resetTooltipForRegion(viewBuildCtx, regionGroup, regionName, regionModel, mapOrGeoModel); + resetStateTriggerForRegion(viewBuildCtx, regionGroup, regionName, regionModel, mapOrGeoModel); + }, this); + }; + + MapDraw.prototype._buildSVG = function (viewBuildCtx) { + var mapName = viewBuildCtx.geo.map; + var transformInfoRaw = viewBuildCtx.transformInfoRaw; + this._svgGroup.x = transformInfoRaw.x; + this._svgGroup.y = transformInfoRaw.y; + this._svgGroup.scaleX = transformInfoRaw.scaleX; + this._svgGroup.scaleY = transformInfoRaw.scaleY; + + if (this._svgResourceChanged(mapName)) { + this._freeSVG(); + + this._useSVG(mapName); + } + + var svgDispatcherMap = this._svgDispatcherMap = createHashMap(); + var focusSelf = false; + each(this._svgGraphicRecord.named, function (namedItem) { + // Note that we also allow different elements have the same name. + // For example, a glyph of a city and the label of the city have + // the same name and their tooltip info can be defined in a single + // region option. + var regionName = namedItem.name; + var mapOrGeoModel = viewBuildCtx.mapOrGeoModel; + var data = viewBuildCtx.data; + var svgNodeTagLower = namedItem.svgNodeTagLower; + var el = namedItem.el; + var dataIdx = data ? data.indexOfName(regionName) : null; + var regionModel = mapOrGeoModel.getRegionModel(regionName); + + if (OPTION_STYLE_ENABLED_TAG_MAP.get(svgNodeTagLower) != null && el instanceof Displayable) { + applyOptionStyleForRegion(viewBuildCtx, el, dataIdx, regionModel); + } + + if (el instanceof Displayable) { + el.culling = true; + } // We do not know how the SVG like so we'd better not to change z2. + // Otherwise it might bring some unexpected result. For example, + // an area hovered that make some inner city can not be clicked. + + + el.z2EmphasisLift = 0; // If self named: + + if (!namedItem.namedFrom) { + // label should batter to be displayed based on the center of + // if it is named rather than displayed on each child. + if (LABEL_HOST_MAP.get(svgNodeTagLower) != null) { + resetLabelForRegion(viewBuildCtx, el, regionName, regionModel, mapOrGeoModel, dataIdx, null); + } + + resetEventTriggerForRegion(viewBuildCtx, el, regionName, regionModel, mapOrGeoModel, dataIdx); + resetTooltipForRegion(viewBuildCtx, el, regionName, regionModel, mapOrGeoModel); + + if (STATE_TRIGGER_TAG_MAP.get(svgNodeTagLower) != null) { + var focus_1 = resetStateTriggerForRegion(viewBuildCtx, el, regionName, regionModel, mapOrGeoModel); + + if (focus_1 === 'self') { + focusSelf = true; + } + + var els = svgDispatcherMap.get(regionName) || svgDispatcherMap.set(regionName, []); + els.push(el); + } + } + }, this); + + this._enableBlurEntireSVG(focusSelf, viewBuildCtx); + }; + + MapDraw.prototype._enableBlurEntireSVG = function (focusSelf, viewBuildCtx) { + // It's a little complicated to support blurring the entire geoSVG in series-map. + // So do not suport it until some requirements come. + // At present, in series-map, only regions can be blurred. + if (focusSelf && viewBuildCtx.isGeo) { + var blurStyle = viewBuildCtx.mapOrGeoModel.getModel(['blur', 'itemStyle']).getItemStyle(); // Only suport `opacity` here. Because not sure that other props are suitable for + // all of the elements generated by SVG (especially for Text/TSpan/Image/... ). + + var opacity_1 = blurStyle.opacity; + + this._svgGraphicRecord.root.traverse(function (el) { + if (!el.isGroup) { + // PENDING: clear those settings to SVG elements when `_freeSVG`. + // (Currently it happen not to be needed.) + setDefaultStateProxy(el); + var style = el.ensureState('blur').style || {}; // Do not overwrite the region style that already set from region option. + + if (style.opacity == null && opacity_1 != null) { + style.opacity = opacity_1; + } // If `ensureState('blur').style = {}`, there will be default opacity. + // Enable `stateTransition` (animation). + + + el.ensureState('emphasis'); + } + }); + } + }; + + MapDraw.prototype.remove = function () { + this._regionsGroup.removeAll(); + + this._regionsGroupByName = null; + + this._svgGroup.removeAll(); + + this._freeSVG(); + + this._controller.dispose(); + + this._controllerHost = null; + }; + + MapDraw.prototype.findHighDownDispatchers = function (name, geoModel) { + if (name == null) { + return []; + } + + var geo = geoModel.coordinateSystem; + + if (geo.resourceType === 'geoJSON') { + var regionsGroupByName = this._regionsGroupByName; + + if (regionsGroupByName) { + var regionGroup = regionsGroupByName.get(name); + return regionGroup ? [regionGroup] : []; + } + } else if (geo.resourceType === 'geoSVG') { + return this._svgDispatcherMap && this._svgDispatcherMap.get(name) || []; + } + }; + + MapDraw.prototype._svgResourceChanged = function (mapName) { + return this._svgMapName !== mapName; + }; + + MapDraw.prototype._useSVG = function (mapName) { + var resource = geoSourceManager.getGeoResource(mapName); + + if (resource && resource.type === 'geoSVG') { + var svgGraphic = resource.useGraphic(this.uid); + + this._svgGroup.add(svgGraphic.root); + + this._svgGraphicRecord = svgGraphic; + this._svgMapName = mapName; + } + }; + + MapDraw.prototype._freeSVG = function () { + var mapName = this._svgMapName; + + if (mapName == null) { + return; + } + + var resource = geoSourceManager.getGeoResource(mapName); + + if (resource && resource.type === 'geoSVG') { + resource.freeGraphic(this.uid); + } + + this._svgGraphicRecord = null; + this._svgDispatcherMap = null; + + this._svgGroup.removeAll(); + + this._svgMapName = null; + }; + + MapDraw.prototype._updateController = function (mapOrGeoModel, ecModel, api) { + var geo = mapOrGeoModel.coordinateSystem; + var controller = this._controller; + var controllerHost = this._controllerHost; // @ts-ignore FIXME:TS + + controllerHost.zoomLimit = mapOrGeoModel.get('scaleLimit'); + controllerHost.zoom = geo.getZoom(); // roamType is will be set default true if it is null + // @ts-ignore FIXME:TS + + controller.enable(mapOrGeoModel.get('roam') || false); + var mainType = mapOrGeoModel.mainType; + + function makeActionBase() { + var action = { + type: 'geoRoam', + componentType: mainType + }; + action[mainType + 'Id'] = mapOrGeoModel.id; + return action; + } + + controller.off('pan').on('pan', function (e) { + this._mouseDownFlag = false; + updateViewOnPan(controllerHost, e.dx, e.dy); + api.dispatchAction(extend(makeActionBase(), { + dx: e.dx, + dy: e.dy, + animation: { + duration: 0 + } + })); + }, this); + controller.off('zoom').on('zoom', function (e) { + this._mouseDownFlag = false; + updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY); + api.dispatchAction(extend(makeActionBase(), { + zoom: e.scale, + originX: e.originX, + originY: e.originY, + animation: { + duration: 0 + } + })); + }, this); + controller.setPointerChecker(function (e, x, y) { + return geo.containPoint([x, y]) && !onIrrelevantElement(e, api, mapOrGeoModel); + }); + }; + /** + * FIXME: this is a temporarily workaround. + * When `geoRoam` the elements need to be reset in `MapView['render']`, because the props like + * `ignore` might have been modified by `LabelManager`, and `LabelManager#addLabelsOfSeries` + * will subsequently cache `defaultAttr` like `ignore`. If do not do this reset, the modified + * props will have no chance to be restored. + * Note: this reset should be after `clearStates` in `renderSeries` becuase `useStates` in + * `renderSeries` will cache the modified `ignore` to `el._normalState`. + * TODO: + * Use clone/immutable in `LabelManager`? + */ + + + MapDraw.prototype.resetForLabelLayout = function () { + this.group.traverse(function (el) { + var label = el.getTextContent(); + + if (label) { + label.ignore = mapLabelRaw(label).ignore; + } + }); + }; + + MapDraw.prototype._updateMapSelectHandler = function (mapOrGeoModel, regionsGroup, api, fromView) { + var mapDraw = this; + regionsGroup.off('mousedown'); + regionsGroup.off('click'); // @ts-ignore FIXME:TS resolve type conflict + + if (mapOrGeoModel.get('selectedMode')) { + regionsGroup.on('mousedown', function () { + mapDraw._mouseDownFlag = true; + }); + regionsGroup.on('click', function (e) { + if (!mapDraw._mouseDownFlag) { + return; + } + + mapDraw._mouseDownFlag = false; + }); + } + }; + + return MapDraw; + }(); + + function applyOptionStyleForRegion(viewBuildCtx, el, dataIndex, regionModel) { + // All of the path are using `itemStyle`, becuase + // (1) Some SVG also use fill on polyline (The different between + // polyline and polygon is "open" or "close" but not fill or not). + // (2) For the common props like opacity, if some use itemStyle + // and some use `lineStyle`, it might confuse users. + // (3) Most SVG use , where can not detect wether draw a "line" + // or a filled shape, so use `itemStyle` for . + var normalStyleModel = regionModel.getModel('itemStyle'); + var emphasisStyleModel = regionModel.getModel(['emphasis', 'itemStyle']); + var blurStyleModel = regionModel.getModel(['blur', 'itemStyle']); + var selectStyleModel = regionModel.getModel(['select', 'itemStyle']); // NOTE: DONT use 'style' in visual when drawing map. + // This component is used for drawing underlying map for both geo component and map series. + + var normalStyle = getFixedItemStyle(normalStyleModel); + var emphasisStyle = getFixedItemStyle(emphasisStyleModel); + var selectStyle = getFixedItemStyle(selectStyleModel); + var blurStyle = getFixedItemStyle(blurStyleModel); // Update the itemStyle if has data visual + + var data = viewBuildCtx.data; + + if (data) { + // Only visual color of each item will be used. It can be encoded by visualMap + // But visual color of series is used in symbol drawing + // Visual color for each series is for the symbol draw + var style = data.getItemVisual(dataIndex, 'style'); + var decal = data.getItemVisual(dataIndex, 'decal'); + + if (viewBuildCtx.isVisualEncodedByVisualMap && style.fill) { + normalStyle.fill = style.fill; + } + + if (decal) { + normalStyle.decal = createOrUpdatePatternFromDecal(decal, viewBuildCtx.api); + } + } // SVG text, tspan and image can be named but not supporeted + // to be styled by region option yet. + + + el.setStyle(normalStyle); + el.style.strokeNoScale = true; + el.ensureState('emphasis').style = emphasisStyle; + el.ensureState('select').style = selectStyle; + el.ensureState('blur').style = blurStyle; // Enable blur + + setDefaultStateProxy(el); + } + + function resetLabelForRegion(viewBuildCtx, el, regionName, regionModel, mapOrGeoModel, // Exist only if `viewBuildCtx.data` exists. + dataIdx, // If labelXY not provided, use `textConfig.position: 'inside'` + labelXY) { + var data = viewBuildCtx.data; + var isGeo = viewBuildCtx.isGeo; + var isDataNaN = data && isNaN(data.get(data.mapDimension('value'), dataIdx)); + var itemLayout = data && data.getItemLayout(dataIdx); // In the following cases label will be drawn + // 1. In map series and data value is NaN + // 2. In geo component + // 3. Region has no series legendIcon, which will be add a showLabel flag in mapSymbolLayout + + if (isGeo || isDataNaN || itemLayout && itemLayout.showLabel) { + var query = !isGeo ? dataIdx : regionName; + var labelFetcher = void 0; // Consider dataIdx not found. + + if (!data || dataIdx >= 0) { + labelFetcher = mapOrGeoModel; + } + + var specifiedTextOpt = labelXY ? { + normal: { + align: 'center', + verticalAlign: 'middle' + } + } : null; // Caveat: must be called after `setDefaultStateProxy(el);` called. + // because textContent will be assign with `el.stateProxy` inside. + + setLabelStyle(el, getLabelStatesModels(regionModel), { + labelFetcher: labelFetcher, + labelDataIndex: query, + defaultText: regionName + }, specifiedTextOpt); + var textEl = el.getTextContent(); + + if (textEl) { + mapLabelRaw(textEl).ignore = textEl.ignore; + + if (el.textConfig && labelXY) { + // Compute a relative offset based on the el bounding rect. + var rect = el.getBoundingRect().clone(); // Need to make sure the percent position base on the same rect in normal and + // emphasis state. Otherwise if using boundingRect of el, but the emphasis state + // has borderWidth (even 0.5px), the text position will be changed obviously + // if the position is very big like ['1234%', '1345%']. + + el.textConfig.layoutRect = rect; + el.textConfig.position = [(labelXY[0] - rect.x) / rect.width * 100 + '%', (labelXY[1] - rect.y) / rect.height * 100 + '%']; + } + } // PENDING: + // If labelLayout is enabled (test/label-layout.html), el.dataIndex should be specified. + // But el.dataIndex is also used to determine whether user event should be triggered, + // where el.seriesIndex or el.dataModel must be specified. At present for a single el + // there is not case that "only label layout enabled but user event disabled", so here + // we depends `resetEventTriggerForRegion` to do the job of setting `el.dataIndex`. + + + el.disableLabelAnimation = true; + } else { + el.removeTextContent(); + el.removeTextConfig(); + el.disableLabelAnimation = null; + } + } + + function resetEventTriggerForRegion(viewBuildCtx, eventTrigger, regionName, regionModel, mapOrGeoModel, // Exist only if `viewBuildCtx.data` exists. + dataIdx) { + // setItemGraphicEl, setHoverStyle after all polygons and labels + // are added to the rigionGroup + if (viewBuildCtx.data) { + // FIXME: when series-map use a SVG map, and there are duplicated name specified + // on different SVG elements, after `data.setItemGraphicEl(...)`: + // (1) all of them will be mounted with `dataIndex`, `seriesIndex`, so that tooltip + // can be triggered only mouse hover. That's correct. + // (2) only the last element will be kept in `data`, so that if trigger tooltip + // by `dispatchAction`, only the last one can be found and triggered. That might be + // not correct. We will fix it in future if anyone demanding that. + viewBuildCtx.data.setItemGraphicEl(dataIdx, eventTrigger); + } // series-map will not trigger "geoselectchange" no matter it is + // based on a declared geo component. Becuause series-map will + // trigger "selectchange". If it trigger both the two events, + // If users call `chart.dispatchAction({type: 'toggleSelect'})`, + // it not easy to also fire event "geoselectchanged". + else { + // Package custom mouse event for geo component + getECData(eventTrigger).eventData = { + componentType: 'geo', + componentIndex: mapOrGeoModel.componentIndex, + geoIndex: mapOrGeoModel.componentIndex, + name: regionName, + region: regionModel && regionModel.option || {} + }; + } + } + + function resetTooltipForRegion(viewBuildCtx, el, regionName, regionModel, mapOrGeoModel) { + if (!viewBuildCtx.data) { + setTooltipConfig({ + el: el, + componentModel: mapOrGeoModel, + itemName: regionName, + // @ts-ignore FIXME:TS fix the "compatible with each other"? + itemTooltipOption: regionModel.get('tooltip') + }); + } + } + + function resetStateTriggerForRegion(viewBuildCtx, el, regionName, regionModel, mapOrGeoModel) { + // @ts-ignore FIXME:TS fix the "compatible with each other"? + el.highDownSilentOnTouch = !!mapOrGeoModel.get('selectedMode'); // @ts-ignore FIXME:TS fix the "compatible with each other"? + + var emphasisModel = regionModel.getModel('emphasis'); + var focus = emphasisModel.get('focus'); + toggleHoverEmphasis(el, focus, emphasisModel.get('blurScope'), emphasisModel.get('disabled')); + + if (viewBuildCtx.isGeo) { + enableComponentHighDownFeatures(el, mapOrGeoModel, regionName); + } + + return focus; + } + + function projectPolys(rings, // Polygons include exterior and interiors. Or polylines. + createStream, isLine) { + var polygons = []; + var curPoly; + + function startPolygon() { + curPoly = []; + } + + function endPolygon() { + if (curPoly.length) { + polygons.push(curPoly); + curPoly = []; + } + } + + var stream = createStream({ + polygonStart: startPolygon, + polygonEnd: endPolygon, + lineStart: startPolygon, + lineEnd: endPolygon, + point: function (x, y) { + // May have NaN values from stream. + if (isFinite(x) && isFinite(y)) { + curPoly.push([x, y]); + } + }, + sphere: function () {} + }); + !isLine && stream.polygonStart(); + each(rings, function (ring) { + stream.lineStart(); + + for (var i = 0; i < ring.length; i++) { + stream.point(ring[i][0], ring[i][1]); + } + + stream.lineEnd(); + }); + !isLine && stream.polygonEnd(); + return polygons; + } + // @ts-ignore FIXME:TS fix the "compatible with each other"? + + var MapView = + /** @class */ + function (_super) { + __extends(MapView, _super); + + function MapView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MapView.type; + return _this; + } + + MapView.prototype.render = function (mapModel, ecModel, api, payload) { + // Not render if it is an toggleSelect action from self + if (payload && payload.type === 'mapToggleSelect' && payload.from === this.uid) { + return; + } + + var group = this.group; + group.removeAll(); + + if (mapModel.getHostGeoModel()) { + return; + } + + if (this._mapDraw && payload && payload.type === 'geoRoam') { + this._mapDraw.resetForLabelLayout(); + } // Not update map if it is an roam action from self + + + if (!(payload && payload.type === 'geoRoam' && payload.componentType === 'series' && payload.seriesId === mapModel.id)) { + if (mapModel.needsDrawMap) { + var mapDraw = this._mapDraw || new MapDraw(api); + group.add(mapDraw.group); + mapDraw.draw(mapModel, ecModel, api, this, payload); + this._mapDraw = mapDraw; + } else { + // Remove drawed map + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + } + } else { + var mapDraw = this._mapDraw; + mapDraw && group.add(mapDraw.group); + } + + mapModel.get('showLegendSymbol') && ecModel.getComponent('legend') && this._renderSymbols(mapModel, ecModel, api); + }; + + MapView.prototype.remove = function () { + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + this.group.removeAll(); + }; + + MapView.prototype.dispose = function () { + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + }; + + MapView.prototype._renderSymbols = function (mapModel, ecModel, api) { + var originalData = mapModel.originalData; + var group = this.group; + originalData.each(originalData.mapDimension('value'), function (value, originalDataIndex) { + if (isNaN(value)) { + return; + } + + var layout = originalData.getItemLayout(originalDataIndex); + + if (!layout || !layout.point) { + // Not exists in map + return; + } + + var point = layout.point; + var offset = layout.offset; + var circle = new Circle({ + style: { + // Because the special of map draw. + // Which needs statistic of multiple series and draw on one map. + // And each series also need a symbol with legend color + // + // Layout and visual are put one the different data + // TODO + fill: mapModel.getData().getVisual('style').fill + }, + shape: { + cx: point[0] + offset * 9, + cy: point[1], + r: 3 + }, + silent: true, + // Do not overlap the first series, on which labels are displayed. + z2: 8 + (!offset ? Z2_EMPHASIS_LIFT + 1 : 0) + }); // Only the series that has the first value on the same region is in charge of rendering the label. + // But consider the case: + // series: [ + // {id: 'X', type: 'map', map: 'm', {data: [{name: 'A', value: 11}, {name: 'B', {value: 22}]}, + // {id: 'Y', type: 'map', map: 'm', {data: [{name: 'A', value: 21}, {name: 'C', {value: 33}]} + // ] + // The offset `0` of item `A` is at series `X`, but of item `C` is at series `Y`. + // For backward compatibility, we follow the rule that render label `A` by the + // settings on series `X` but render label `C` by the settings on series `Y`. + + if (!offset) { + var fullData = mapModel.mainSeries.getData(); + var name_1 = originalData.getName(originalDataIndex); + var fullIndex_1 = fullData.indexOfName(name_1); + var itemModel = originalData.getItemModel(originalDataIndex); + var labelModel = itemModel.getModel('label'); + var regionGroup = fullData.getItemGraphicEl(fullIndex_1); // `getFormattedLabel` needs to use `getData` inside. Here + // `mapModel.getData()` is shallow cloned from `mainSeries.getData()`. + // FIXME + // If this is not the `mainSeries`, the item model (like label formatter) + // set on original data item will never get. But it has been working + // like that from the begining, and this scenario is rarely encountered. + // So it won't be fixed until have to. + + setLabelStyle(circle, getLabelStatesModels(itemModel), { + labelFetcher: { + getFormattedLabel: function (idx, state) { + return mapModel.getFormattedLabel(fullIndex_1, state); + } + }, + defaultText: name_1 + }); + circle.disableLabelAnimation = true; + + if (!labelModel.get('position')) { + circle.setTextConfig({ + position: 'bottom' + }); + } + + regionGroup.onHoverStateChange = function (toState) { + setStatesFlag(circle, toState); + }; + } + + group.add(circle); + }); + }; + + MapView.type = 'map'; + return MapView; + }(ChartView); + + var MapSeries = + /** @class */ + function (_super) { + __extends(MapSeries, _super); + + function MapSeries() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MapSeries.type; // Only first map series of same mapType will drawMap. + + _this.needsDrawMap = false; // Group of all map series with same mapType + + _this.seriesGroup = []; + + _this.getTooltipPosition = function (dataIndex) { + if (dataIndex != null) { + var name_1 = this.getData().getName(dataIndex); + var geo = this.coordinateSystem; + var region = geo.getRegion(name_1); + return region && geo.dataToPoint(region.getCenter()); + } + }; + + return _this; + } + + MapSeries.prototype.getInitialData = function (option) { + var data = createSeriesDataSimply(this, { + coordDimensions: ['value'], + encodeDefaulter: curry(makeSeriesEncodeForNameBased, this) + }); + var dataNameMap = createHashMap(); + var toAppendNames = []; + + for (var i = 0, len = data.count(); i < len; i++) { + var name_2 = data.getName(i); + dataNameMap.set(name_2, true); + } + + var geoSource = geoSourceManager.load(this.getMapType(), this.option.nameMap, this.option.nameProperty); + each(geoSource.regions, function (region) { + var name = region.name; + + if (!dataNameMap.get(name)) { + toAppendNames.push(name); + } + }); // Complete data with missing regions. The consequent processes (like visual + // map and render) can not be performed without a "full data". For example, + // find `dataIndex` by name. + + data.appendValues([], toAppendNames); + return data; + }; + /** + * If no host geo model, return null, which means using a + * inner exclusive geo model. + */ + + + MapSeries.prototype.getHostGeoModel = function () { + var geoIndex = this.option.geoIndex; + return geoIndex != null ? this.ecModel.getComponent('geo', geoIndex) : null; + }; + + MapSeries.prototype.getMapType = function () { + return (this.getHostGeoModel() || this).option.map; + }; // _fillOption(option, mapName) { + // Shallow clone + // option = zrUtil.extend({}, option); + // option.data = geoCreator.getFilledRegions(option.data, mapName, option.nameMap); + // return option; + // } + + + MapSeries.prototype.getRawValue = function (dataIndex) { + // Use value stored in data instead because it is calculated from multiple series + // FIXME Provide all value of multiple series ? + var data = this.getData(); + return data.get(data.mapDimension('value'), dataIndex); + }; + /** + * Get model of region + */ + + + MapSeries.prototype.getRegionModel = function (regionName) { + var data = this.getData(); + return data.getItemModel(data.indexOfName(regionName)); + }; + /** + * Map tooltip formatter + */ + + + MapSeries.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + // FIXME orignalData and data is a bit confusing + var data = this.getData(); + var value = this.getRawValue(dataIndex); + var name = data.getName(dataIndex); + var seriesGroup = this.seriesGroup; + var seriesNames = []; + + for (var i = 0; i < seriesGroup.length; i++) { + var otherIndex = seriesGroup[i].originalData.indexOfName(name); + var valueDim = data.mapDimension('value'); + + if (!isNaN(seriesGroup[i].originalData.get(valueDim, otherIndex))) { + seriesNames.push(seriesGroup[i].name); + } + } + + return createTooltipMarkup('section', { + header: seriesNames.join(', '), + noHeader: !seriesNames.length, + blocks: [createTooltipMarkup('nameValue', { + name: name, + value: value + })] + }); + }; + + MapSeries.prototype.setZoom = function (zoom) { + this.option.zoom = zoom; + }; + + MapSeries.prototype.setCenter = function (center) { + this.option.center = center; + }; + + MapSeries.prototype.getLegendIcon = function (opt) { + var iconType = opt.icon || 'roundRect'; + var icon = createSymbol(iconType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill); + icon.setStyle(opt.itemStyle); // Map do not use itemStyle.borderWidth as border width + + icon.style.stroke = 'none'; // No rotation because no series visual symbol for map + + if (iconType.indexOf('empty') > -1) { + icon.style.stroke = icon.style.fill; + icon.style.fill = '#fff'; + icon.style.lineWidth = 2; + } + + return icon; + }; + + MapSeries.type = 'series.map'; + MapSeries.dependencies = ['geo']; + MapSeries.layoutMode = 'box'; + MapSeries.defaultOption = { + // 一级层叠 + // zlevel: 0, + // 二级层叠 + z: 2, + coordinateSystem: 'geo', + // map should be explicitly specified since ec3. + map: '', + // If `geoIndex` is not specified, a exclusive geo will be + // created. Otherwise use the specified geo component, and + // `map` and `mapType` are ignored. + // geoIndex: 0, + // 'center' | 'left' | 'right' | 'x%' | {number} + left: 'center', + // 'center' | 'top' | 'bottom' | 'x%' | {number} + top: 'center', + // right + // bottom + // width: + // height + // Aspect is width / height. Inited to be geoJson bbox aspect + // This parameter is used for scale this aspect + // Default value: + // for geoSVG source: 1, + // for geoJSON source: 0.75. + aspectScale: null, + ///// Layout with center and size + // If you wan't to put map in a fixed size box with right aspect ratio + // This two properties may more conveninet + // layoutCenter: [50%, 50%] + // layoutSize: 100 + showLegendSymbol: true, + // Define left-top, right-bottom coords to control view + // For example, [ [180, 90], [-180, -90] ], + // higher priority than center and zoom + boundingCoords: null, + // Default on center of map + center: null, + zoom: 1, + scaleLimit: null, + selectedMode: true, + label: { + show: false, + color: '#000' + }, + // scaleLimit: null, + itemStyle: { + borderWidth: 0.5, + borderColor: '#444', + areaColor: '#eee' + }, + emphasis: { + label: { + show: true, + color: 'rgb(100,0,0)' + }, + itemStyle: { + areaColor: 'rgba(255,215,0,0.8)' + } + }, + select: { + label: { + show: true, + color: 'rgb(100,0,0)' + }, + itemStyle: { + color: 'rgba(255,215,0,0.8)' + } + }, + nameProperty: 'name' + }; + return MapSeries; + }(SeriesModel); + + function dataStatistics(datas, statisticType) { + var dataNameMap = {}; + each(datas, function (data) { + data.each(data.mapDimension('value'), function (value, idx) { + // Add prefix to avoid conflict with Object.prototype. + var mapKey = 'ec-' + data.getName(idx); + dataNameMap[mapKey] = dataNameMap[mapKey] || []; + + if (!isNaN(value)) { + dataNameMap[mapKey].push(value); + } + }); + }); + return datas[0].map(datas[0].mapDimension('value'), function (value, idx) { + var mapKey = 'ec-' + datas[0].getName(idx); + var sum = 0; + var min = Infinity; + var max = -Infinity; + var len = dataNameMap[mapKey].length; + + for (var i = 0; i < len; i++) { + min = Math.min(min, dataNameMap[mapKey][i]); + max = Math.max(max, dataNameMap[mapKey][i]); + sum += dataNameMap[mapKey][i]; + } + + var result; + + if (statisticType === 'min') { + result = min; + } else if (statisticType === 'max') { + result = max; + } else if (statisticType === 'average') { + result = sum / len; + } else { + result = sum; + } + + return len === 0 ? NaN : result; + }); + } + + function mapDataStatistic(ecModel) { + var seriesGroups = {}; + ecModel.eachSeriesByType('map', function (seriesModel) { + var hostGeoModel = seriesModel.getHostGeoModel(); + var key = hostGeoModel ? 'o' + hostGeoModel.id : 'i' + seriesModel.getMapType(); + (seriesGroups[key] = seriesGroups[key] || []).push(seriesModel); + }); + each(seriesGroups, function (seriesList, key) { + var data = dataStatistics(map(seriesList, function (seriesModel) { + return seriesModel.getData(); + }), seriesList[0].get('mapValueCalculation')); + + for (var i = 0; i < seriesList.length; i++) { + seriesList[i].originalData = seriesList[i].getData(); + } // FIXME Put where? + + + for (var i = 0; i < seriesList.length; i++) { + seriesList[i].seriesGroup = seriesList; + seriesList[i].needsDrawMap = i === 0 && !seriesList[i].getHostGeoModel(); + seriesList[i].setData(data.cloneShallow()); + seriesList[i].mainSeries = seriesList[0]; + } + }); + } + + function mapSymbolLayout(ecModel) { + var processedMapType = {}; + ecModel.eachSeriesByType('map', function (mapSeries) { + var mapType = mapSeries.getMapType(); + + if (mapSeries.getHostGeoModel() || processedMapType[mapType]) { + return; + } + + var mapSymbolOffsets = {}; + each(mapSeries.seriesGroup, function (subMapSeries) { + var geo = subMapSeries.coordinateSystem; + var data = subMapSeries.originalData; + + if (subMapSeries.get('showLegendSymbol') && ecModel.getComponent('legend')) { + data.each(data.mapDimension('value'), function (value, idx) { + var name = data.getName(idx); + var region = geo.getRegion(name); // If input series.data is [11, 22, '-'/null/undefined, 44], + // it will be filled with NaN: [11, 22, NaN, 44] and NaN will + // not be drawn. So here must validate if value is NaN. + + if (!region || isNaN(value)) { + return; + } + + var offset = mapSymbolOffsets[name] || 0; + var point = geo.dataToPoint(region.getCenter()); + mapSymbolOffsets[name] = offset + 1; + data.setItemLayout(idx, { + point: point, + offset: offset + }); + }); + } + }); // Show label of those region not has legendIcon (which is offset 0) + + var data = mapSeries.getData(); + data.each(function (idx) { + var name = data.getName(idx); + var layout = data.getItemLayout(idx) || {}; + layout.showLabel = !mapSymbolOffsets[name]; + data.setItemLayout(idx, layout); + }); + processedMapType[mapType] = true; + }); + } + + var v2ApplyTransform = applyTransform; + + var View = + /** @class */ + function (_super) { + __extends(View, _super); + + function View(name) { + var _this = _super.call(this) || this; + + _this.type = 'view'; + _this.dimensions = ['x', 'y']; + /** + * Represents the transform brought by roam/zoom. + * If `View['_viewRect']` applies roam transform, + * we can get the final displayed rect. + */ + + _this._roamTransformable = new Transformable(); + /** + * Represents the transform from `View['_rect']` to `View['_viewRect']`. + */ + + _this._rawTransformable = new Transformable(); + _this.name = name; + return _this; + } + + View.prototype.setBoundingRect = function (x, y, width, height) { + this._rect = new BoundingRect(x, y, width, height); + return this._rect; + }; + /** + * @return {module:zrender/core/BoundingRect} + */ + + + View.prototype.getBoundingRect = function () { + return this._rect; + }; + + View.prototype.setViewRect = function (x, y, width, height) { + this._transformTo(x, y, width, height); + + this._viewRect = new BoundingRect(x, y, width, height); + }; + /** + * Transformed to particular position and size + */ + + + View.prototype._transformTo = function (x, y, width, height) { + var rect = this.getBoundingRect(); + var rawTransform = this._rawTransformable; + rawTransform.transform = rect.calculateTransform(new BoundingRect(x, y, width, height)); + var rawParent = rawTransform.parent; + rawTransform.parent = null; + rawTransform.decomposeTransform(); + rawTransform.parent = rawParent; + + this._updateTransform(); + }; + /** + * Set center of view + */ + + + View.prototype.setCenter = function (centerCoord) { + if (!centerCoord) { + return; + } + + this._center = centerCoord; + + this._updateCenterAndZoom(); + }; + + View.prototype.setZoom = function (zoom) { + zoom = zoom || 1; + var zoomLimit = this.zoomLimit; + + if (zoomLimit) { + if (zoomLimit.max != null) { + zoom = Math.min(zoomLimit.max, zoom); + } + + if (zoomLimit.min != null) { + zoom = Math.max(zoomLimit.min, zoom); + } + } + + this._zoom = zoom; + + this._updateCenterAndZoom(); + }; + /** + * Get default center without roam + */ + + + View.prototype.getDefaultCenter = function () { + // Rect before any transform + var rawRect = this.getBoundingRect(); + var cx = rawRect.x + rawRect.width / 2; + var cy = rawRect.y + rawRect.height / 2; + return [cx, cy]; + }; + + View.prototype.getCenter = function () { + return this._center || this.getDefaultCenter(); + }; + + View.prototype.getZoom = function () { + return this._zoom || 1; + }; + + View.prototype.getRoamTransform = function () { + return this._roamTransformable.getLocalTransform(); + }; + /** + * Remove roam + */ + + + View.prototype._updateCenterAndZoom = function () { + // Must update after view transform updated + var rawTransformMatrix = this._rawTransformable.getLocalTransform(); + + var roamTransform = this._roamTransformable; + var defaultCenter = this.getDefaultCenter(); + var center = this.getCenter(); + var zoom = this.getZoom(); + center = applyTransform([], center, rawTransformMatrix); + defaultCenter = applyTransform([], defaultCenter, rawTransformMatrix); + roamTransform.originX = center[0]; + roamTransform.originY = center[1]; + roamTransform.x = defaultCenter[0] - center[0]; + roamTransform.y = defaultCenter[1] - center[1]; + roamTransform.scaleX = roamTransform.scaleY = zoom; + + this._updateTransform(); + }; + /** + * Update transform props on `this` based on the current + * `this._roamTransformable` and `this._rawTransformable`. + */ + + + View.prototype._updateTransform = function () { + var roamTransformable = this._roamTransformable; + var rawTransformable = this._rawTransformable; + rawTransformable.parent = roamTransformable; + roamTransformable.updateTransform(); + rawTransformable.updateTransform(); + copy$1(this.transform || (this.transform = []), rawTransformable.transform || create$1()); + this._rawTransform = rawTransformable.getLocalTransform(); + this.invTransform = this.invTransform || []; + invert(this.invTransform, this.transform); + this.decomposeTransform(); + }; + + View.prototype.getTransformInfo = function () { + var rawTransformable = this._rawTransformable; + var roamTransformable = this._roamTransformable; // Becuase roamTransformabel has `originX/originY` modified, + // but the caller of `getTransformInfo` can not handle `originX/originY`, + // so need to recalcualte them. + + var dummyTransformable = new Transformable(); + dummyTransformable.transform = roamTransformable.transform; + dummyTransformable.decomposeTransform(); + return { + roam: { + x: dummyTransformable.x, + y: dummyTransformable.y, + scaleX: dummyTransformable.scaleX, + scaleY: dummyTransformable.scaleY + }, + raw: { + x: rawTransformable.x, + y: rawTransformable.y, + scaleX: rawTransformable.scaleX, + scaleY: rawTransformable.scaleY + } + }; + }; + + View.prototype.getViewRect = function () { + return this._viewRect; + }; + /** + * Get view rect after roam transform + */ + + + View.prototype.getViewRectAfterRoam = function () { + var rect = this.getBoundingRect().clone(); + rect.applyTransform(this.transform); + return rect; + }; + /** + * Convert a single (lon, lat) data item to (x, y) point. + */ + + + View.prototype.dataToPoint = function (data, noRoam, out) { + var transform = noRoam ? this._rawTransform : this.transform; + out = out || []; + return transform ? v2ApplyTransform(out, data, transform) : copy(out, data); + }; + /** + * Convert a (x, y) point to (lon, lat) data + */ + + + View.prototype.pointToData = function (point) { + var invTransform = this.invTransform; + return invTransform ? v2ApplyTransform([], point, invTransform) : [point[0], point[1]]; + }; + + View.prototype.convertToPixel = function (ecModel, finder, value) { + var coordSys = getCoordSys(finder); + return coordSys === this ? coordSys.dataToPoint(value) : null; + }; + + View.prototype.convertFromPixel = function (ecModel, finder, pixel) { + var coordSys = getCoordSys(finder); + return coordSys === this ? coordSys.pointToData(pixel) : null; + }; + /** + * @implements + */ + + + View.prototype.containPoint = function (point) { + return this.getViewRectAfterRoam().contain(point[0], point[1]); + }; + + View.dimensions = ['x', 'y']; + return View; + }(Transformable); + + function getCoordSys(finder) { + var seriesModel = finder.seriesModel; + return seriesModel ? seriesModel.coordinateSystem : null; // e.g., graph. + } + + var GEO_DEFAULT_PARAMS = { + 'geoJSON': { + aspectScale: 0.75, + invertLongitute: true + }, + 'geoSVG': { + aspectScale: 1, + invertLongitute: false + } + }; + var geo2DDimensions = ['lng', 'lat']; + + var Geo = + /** @class */ + function (_super) { + __extends(Geo, _super); + + function Geo(name, map, opt) { + var _this = _super.call(this, name) || this; + + _this.dimensions = geo2DDimensions; + _this.type = 'geo'; // Only store specified name coord via `addGeoCoord`. + + _this._nameCoordMap = createHashMap(); + _this.map = map; + var projection = opt.projection; + var source = geoSourceManager.load(map, opt.nameMap, opt.nameProperty); + var resource = geoSourceManager.getGeoResource(map); + var resourceType = _this.resourceType = resource ? resource.type : null; + var regions = _this.regions = source.regions; + var defaultParams = GEO_DEFAULT_PARAMS[resource.type]; + _this._regionsMap = source.regionsMap; + _this.regions = source.regions; + + if ("development" !== 'production' && projection) { + // Do some check + if (resourceType === 'geoSVG') { + if ("development" !== 'production') { + warn("Map " + map + " with SVG source can't use projection. Only GeoJSON source supports projection."); + } + + projection = null; + } + + if (!(projection.project && projection.unproject)) { + if ("development" !== 'production') { + warn('project and unproject must be both provided in the projeciton.'); + } + + projection = null; + } + } + + _this.projection = projection; + var boundingRect; + + if (projection) { + // Can't reuse the raw bounding rect + for (var i = 0; i < regions.length; i++) { + var regionRect = regions[i].getBoundingRect(projection); + boundingRect = boundingRect || regionRect.clone(); + boundingRect.union(regionRect); + } + } else { + boundingRect = source.boundingRect; + } + + _this.setBoundingRect(boundingRect.x, boundingRect.y, boundingRect.width, boundingRect.height); // aspectScale and invertLongitute actually is the parameters default raw projection. + // So we ignore them if projection is given. + // Ignore default aspect scale if projection exits. + + + _this.aspectScale = projection ? 1 : retrieve2(opt.aspectScale, defaultParams.aspectScale); // Not invert longitute if projection exits. + + _this._invertLongitute = projection ? false : defaultParams.invertLongitute; + return _this; + } + + Geo.prototype._transformTo = function (x, y, width, height) { + var rect = this.getBoundingRect(); + var invertLongitute = this._invertLongitute; + rect = rect.clone(); + + if (invertLongitute) { + // Longitute is inverted + rect.y = -rect.y - rect.height; + } + + var rawTransformable = this._rawTransformable; + rawTransformable.transform = rect.calculateTransform(new BoundingRect(x, y, width, height)); + var rawParent = rawTransformable.parent; + rawTransformable.parent = null; + rawTransformable.decomposeTransform(); + rawTransformable.parent = rawParent; + + if (invertLongitute) { + rawTransformable.scaleY = -rawTransformable.scaleY; + } + + this._updateTransform(); + }; + + Geo.prototype.getRegion = function (name) { + return this._regionsMap.get(name); + }; + + Geo.prototype.getRegionByCoord = function (coord) { + var regions = this.regions; + + for (var i = 0; i < regions.length; i++) { + var region = regions[i]; + + if (region.type === 'geoJSON' && region.contain(coord)) { + return regions[i]; + } + } + }; + /** + * Add geoCoord for indexing by name + */ + + + Geo.prototype.addGeoCoord = function (name, geoCoord) { + this._nameCoordMap.set(name, geoCoord); + }; + /** + * Get geoCoord by name + */ + + + Geo.prototype.getGeoCoord = function (name) { + var region = this._regionsMap.get(name); // calcualte center only on demand. + + + return this._nameCoordMap.get(name) || region && region.getCenter(); + }; + + Geo.prototype.dataToPoint = function (data, noRoam, out) { + if (isString(data)) { + // Map area name to geoCoord + data = this.getGeoCoord(data); + } + + if (data) { + var projection = this.projection; + + if (projection) { + // projection may return null point. + data = projection.project(data); + } + + return data && this.projectedToPoint(data); + } + }; + + Geo.prototype.pointToData = function (point) { + var projection = this.projection; + + if (projection) { + // projection may return null point. + point = projection.unproject(point); + } + + return point && this.pointToProjected(point); + }; + /** + * Point to projected data. Same with pointToData when projection is used. + */ + + + Geo.prototype.pointToProjected = function (point) { + return _super.prototype.pointToData.call(this, point); + }; + + Geo.prototype.projectedToPoint = function (projected, noRoam, out) { + return _super.prototype.dataToPoint.call(this, projected, noRoam, out); + }; + + Geo.prototype.convertToPixel = function (ecModel, finder, value) { + var coordSys = getCoordSys$1(finder); + return coordSys === this ? coordSys.dataToPoint(value) : null; + }; + + Geo.prototype.convertFromPixel = function (ecModel, finder, pixel) { + var coordSys = getCoordSys$1(finder); + return coordSys === this ? coordSys.pointToData(pixel) : null; + }; + + return Geo; + }(View); + mixin(Geo, View); + + function getCoordSys$1(finder) { + var geoModel = finder.geoModel; + var seriesModel = finder.seriesModel; + return geoModel ? geoModel.coordinateSystem : seriesModel ? seriesModel.coordinateSystem // For map series. + || (seriesModel.getReferringComponents('geo', SINGLE_REFERRING).models[0] || {}).coordinateSystem : null; + } + + /** + * Resize method bound to the geo + */ + + function resizeGeo(geoModel, api) { + var boundingCoords = geoModel.get('boundingCoords'); + + if (boundingCoords != null) { + var leftTop_1 = boundingCoords[0]; + var rightBottom_1 = boundingCoords[1]; + + if (!(isFinite(leftTop_1[0]) && isFinite(leftTop_1[1]) && isFinite(rightBottom_1[0]) && isFinite(rightBottom_1[1]))) { + if ("development" !== 'production') { + console.error('Invalid boundingCoords'); + } + } else { + // Sample around the lng/lat rect and use projection to calculate actual bounding rect. + var projection_1 = this.projection; + + if (projection_1) { + var xMin = leftTop_1[0]; + var yMin = leftTop_1[1]; + var xMax = rightBottom_1[0]; + var yMax = rightBottom_1[1]; + leftTop_1 = [Infinity, Infinity]; + rightBottom_1 = [-Infinity, -Infinity]; // TODO better way? + + var sampleLine = function (x0, y0, x1, y1) { + var dx = x1 - x0; + var dy = y1 - y0; + + for (var i = 0; i <= 100; i++) { + var p = i / 100; + var pt = projection_1.project([x0 + dx * p, y0 + dy * p]); + min(leftTop_1, leftTop_1, pt); + max(rightBottom_1, rightBottom_1, pt); + } + }; // Top + + + sampleLine(xMin, yMin, xMax, yMin); // Right + + sampleLine(xMax, yMin, xMax, yMax); // Bottom + + sampleLine(xMax, yMax, xMin, yMax); // Left + + sampleLine(xMin, yMax, xMax, yMin); + } + + this.setBoundingRect(leftTop_1[0], leftTop_1[1], rightBottom_1[0] - leftTop_1[0], rightBottom_1[1] - leftTop_1[1]); + } + } + + var rect = this.getBoundingRect(); + var centerOption = geoModel.get('layoutCenter'); + var sizeOption = geoModel.get('layoutSize'); + var viewWidth = api.getWidth(); + var viewHeight = api.getHeight(); + var aspect = rect.width / rect.height * this.aspectScale; + var useCenterAndSize = false; + var center; + var size; + + if (centerOption && sizeOption) { + center = [parsePercent$1(centerOption[0], viewWidth), parsePercent$1(centerOption[1], viewHeight)]; + size = parsePercent$1(sizeOption, Math.min(viewWidth, viewHeight)); + + if (!isNaN(center[0]) && !isNaN(center[1]) && !isNaN(size)) { + useCenterAndSize = true; + } else { + if ("development" !== 'production') { + console.warn('Given layoutCenter or layoutSize data are invalid. Use left/top/width/height instead.'); + } + } + } + + var viewRect; + + if (useCenterAndSize) { + viewRect = {}; + + if (aspect > 1) { + // Width is same with size + viewRect.width = size; + viewRect.height = size / aspect; + } else { + viewRect.height = size; + viewRect.width = size * aspect; + } + + viewRect.y = center[1] - viewRect.height / 2; + viewRect.x = center[0] - viewRect.width / 2; + } else { + // Use left/top/width/height + var boxLayoutOption = geoModel.getBoxLayoutParams(); + boxLayoutOption.aspect = aspect; + viewRect = getLayoutRect(boxLayoutOption, { + width: viewWidth, + height: viewHeight + }); + } + + this.setViewRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height); + this.setCenter(geoModel.get('center')); + this.setZoom(geoModel.get('zoom')); + } // Back compat for ECharts2, where the coord map is set on map series: + // {type: 'map', geoCoord: {'cityA': [116.46,39.92], 'cityA': [119.12,24.61]}}, + + + function setGeoCoords(geo, model) { + each(model.get('geoCoord'), function (geoCoord, name) { + geo.addGeoCoord(name, geoCoord); + }); + } + + var GeoCreator = + /** @class */ + function () { + function GeoCreator() { + // For deciding which dimensions to use when creating list data + this.dimensions = geo2DDimensions; + } + + GeoCreator.prototype.create = function (ecModel, api) { + var geoList = []; + + function getCommonGeoProperties(model) { + return { + nameProperty: model.get('nameProperty'), + aspectScale: model.get('aspectScale'), + projection: model.get('projection') + }; + } // FIXME Create each time may be slow + + + ecModel.eachComponent('geo', function (geoModel, idx) { + var mapName = geoModel.get('map'); + var geo = new Geo(mapName + idx, mapName, extend({ + nameMap: geoModel.get('nameMap') + }, getCommonGeoProperties(geoModel))); + geo.zoomLimit = geoModel.get('scaleLimit'); + geoList.push(geo); // setGeoCoords(geo, geoModel); + + geoModel.coordinateSystem = geo; + geo.model = geoModel; // Inject resize method + + geo.resize = resizeGeo; + geo.resize(geoModel, api); + }); + ecModel.eachSeries(function (seriesModel) { + var coordSys = seriesModel.get('coordinateSystem'); + + if (coordSys === 'geo') { + var geoIndex = seriesModel.get('geoIndex') || 0; + seriesModel.coordinateSystem = geoList[geoIndex]; + } + }); // If has map series + + var mapModelGroupBySeries = {}; + ecModel.eachSeriesByType('map', function (seriesModel) { + if (!seriesModel.getHostGeoModel()) { + var mapType = seriesModel.getMapType(); + mapModelGroupBySeries[mapType] = mapModelGroupBySeries[mapType] || []; + mapModelGroupBySeries[mapType].push(seriesModel); + } + }); + each(mapModelGroupBySeries, function (mapSeries, mapType) { + var nameMapList = map(mapSeries, function (singleMapSeries) { + return singleMapSeries.get('nameMap'); + }); + var geo = new Geo(mapType, mapType, extend({ + nameMap: mergeAll(nameMapList) + }, getCommonGeoProperties(mapSeries[0]))); + geo.zoomLimit = retrieve.apply(null, map(mapSeries, function (singleMapSeries) { + return singleMapSeries.get('scaleLimit'); + })); + geoList.push(geo); // Inject resize method + + geo.resize = resizeGeo; + geo.resize(mapSeries[0], api); + each(mapSeries, function (singleMapSeries) { + singleMapSeries.coordinateSystem = geo; + setGeoCoords(geo, singleMapSeries); + }); + }); + return geoList; + }; + /** + * Fill given regions array + */ + + + GeoCreator.prototype.getFilledRegions = function (originRegionArr, mapName, nameMap, nameProperty) { + // Not use the original + var regionsArr = (originRegionArr || []).slice(); + var dataNameMap = createHashMap(); + + for (var i = 0; i < regionsArr.length; i++) { + dataNameMap.set(regionsArr[i].name, regionsArr[i]); + } + + var source = geoSourceManager.load(mapName, nameMap, nameProperty); + each(source.regions, function (region) { + var name = region.name; + !dataNameMap.get(name) && regionsArr.push({ + name: name + }); + }); + return regionsArr; + }; + + return GeoCreator; + }(); + + var geoCreator = new GeoCreator(); + + var GeoModel = + /** @class */ + function (_super) { + __extends(GeoModel, _super); + + function GeoModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GeoModel.type; + return _this; + } + + GeoModel.prototype.init = function (option, parentModel, ecModel) { + var source = geoSourceManager.getGeoResource(option.map); + + if (source && source.type === 'geoJSON') { + var itemStyle = option.itemStyle = option.itemStyle || {}; + + if (!('color' in itemStyle)) { + itemStyle.color = '#eee'; + } + } + + this.mergeDefaultAndTheme(option, ecModel); // Default label emphasis `show` + + defaultEmphasis(option, 'label', ['show']); + }; + + GeoModel.prototype.optionUpdated = function () { + var _this = this; + + var option = this.option; + option.regions = geoCreator.getFilledRegions(option.regions, option.map, option.nameMap, option.nameProperty); + var selectedMap = {}; + this._optionModelMap = reduce(option.regions || [], function (optionModelMap, regionOpt) { + var regionName = regionOpt.name; + + if (regionName) { + optionModelMap.set(regionName, new Model(regionOpt, _this, _this.ecModel)); + + if (regionOpt.selected) { + selectedMap[regionName] = true; + } + } + + return optionModelMap; + }, createHashMap()); + + if (!option.selectedMap) { + option.selectedMap = selectedMap; + } + }; + /** + * Get model of region. + */ + + + GeoModel.prototype.getRegionModel = function (name) { + return this._optionModelMap.get(name) || new Model(null, this, this.ecModel); + }; + /** + * Format label + * @param name Region name + */ + + + GeoModel.prototype.getFormattedLabel = function (name, status) { + var regionModel = this.getRegionModel(name); + var formatter = status === 'normal' ? regionModel.get(['label', 'formatter']) : regionModel.get(['emphasis', 'label', 'formatter']); + var params = { + name: name + }; + + if (isFunction(formatter)) { + params.status = status; + return formatter(params); + } else if (isString(formatter)) { + return formatter.replace('{a}', name != null ? name : ''); + } + }; + + GeoModel.prototype.setZoom = function (zoom) { + this.option.zoom = zoom; + }; + + GeoModel.prototype.setCenter = function (center) { + this.option.center = center; + }; // PENGING If selectedMode is null ? + + + GeoModel.prototype.select = function (name) { + var option = this.option; + var selectedMode = option.selectedMode; + + if (!selectedMode) { + return; + } + + if (selectedMode !== 'multiple') { + option.selectedMap = null; + } + + var selectedMap = option.selectedMap || (option.selectedMap = {}); + selectedMap[name] = true; + }; + + GeoModel.prototype.unSelect = function (name) { + var selectedMap = this.option.selectedMap; + + if (selectedMap) { + selectedMap[name] = false; + } + }; + + GeoModel.prototype.toggleSelected = function (name) { + this[this.isSelected(name) ? 'unSelect' : 'select'](name); + }; + + GeoModel.prototype.isSelected = function (name) { + var selectedMap = this.option.selectedMap; + return !!(selectedMap && selectedMap[name]); + }; + + GeoModel.type = 'geo'; + GeoModel.layoutMode = 'box'; + GeoModel.defaultOption = { + // zlevel: 0, + z: 0, + show: true, + left: 'center', + top: 'center', + // Default value: + // for geoSVG source: 1, + // for geoJSON source: 0.75. + aspectScale: null, + ///// Layout with center and size + // If you wan't to put map in a fixed size box with right aspect ratio + // This two properties may more conveninet + // layoutCenter: [50%, 50%] + // layoutSize: 100 + silent: false, + // Map type + map: '', + // Define left-top, right-bottom coords to control view + // For example, [ [180, 90], [-180, -90] ] + boundingCoords: null, + // Default on center of map + center: null, + zoom: 1, + scaleLimit: null, + // selectedMode: false + label: { + show: false, + color: '#000' + }, + itemStyle: { + borderWidth: 0.5, + borderColor: '#444' // Default color: + // + geoJSON: #eee + // + geoSVG: null (use SVG original `fill`) + // color: '#eee' + + }, + emphasis: { + label: { + show: true, + color: 'rgb(100,0,0)' + }, + itemStyle: { + color: 'rgba(255,215,0,0.8)' + } + }, + select: { + label: { + show: true, + color: 'rgb(100,0,0)' + }, + itemStyle: { + color: 'rgba(255,215,0,0.8)' + } + }, + regions: [] // tooltip: { + // show: false + // } + + }; + return GeoModel; + }(ComponentModel); + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function getCenterCoord(view, point) { + // Use projected coord as center because it's linear. + return view.pointToProjected ? view.pointToProjected(point) : view.pointToData(point); + } + + function updateCenterAndZoom(view, payload, zoomLimit) { + var previousZoom = view.getZoom(); + var center = view.getCenter(); + var zoom = payload.zoom; + var point = view.projectedToPoint ? view.projectedToPoint(center) : view.dataToPoint(center); + + if (payload.dx != null && payload.dy != null) { + point[0] -= payload.dx; + point[1] -= payload.dy; + view.setCenter(getCenterCoord(view, point)); + } + + if (zoom != null) { + if (zoomLimit) { + var zoomMin = zoomLimit.min || 0; + var zoomMax = zoomLimit.max || Infinity; + zoom = Math.max(Math.min(previousZoom * zoom, zoomMax), zoomMin) / previousZoom; + } // Zoom on given point(originX, originY) + + + view.scaleX *= zoom; + view.scaleY *= zoom; + var fixX = (payload.originX - view.x) * (zoom - 1); + var fixY = (payload.originY - view.y) * (zoom - 1); + view.x -= fixX; + view.y -= fixY; + view.updateTransform(); // Get the new center + + view.setCenter(getCenterCoord(view, point)); + view.setZoom(zoom * previousZoom); + } + + return { + center: view.getCenter(), + zoom: view.getZoom() + }; + } + + var GeoView = + /** @class */ + function (_super) { + __extends(GeoView, _super); + + function GeoView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GeoView.type; + _this.focusBlurEnabled = true; + return _this; + } + + GeoView.prototype.init = function (ecModel, api) { + this._api = api; + }; + + GeoView.prototype.render = function (geoModel, ecModel, api, payload) { + this._model = geoModel; + + if (!geoModel.get('show')) { + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + return; + } + + if (!this._mapDraw) { + this._mapDraw = new MapDraw(api); + } + + var mapDraw = this._mapDraw; + mapDraw.draw(geoModel, ecModel, api, this, payload); + mapDraw.group.on('click', this._handleRegionClick, this); + mapDraw.group.silent = geoModel.get('silent'); + this.group.add(mapDraw.group); + this.updateSelectStatus(geoModel, ecModel, api); + }; + + GeoView.prototype._handleRegionClick = function (e) { + var eventData; + findEventDispatcher(e.target, function (current) { + return (eventData = getECData(current).eventData) != null; + }, true); + + if (eventData) { + this._api.dispatchAction({ + type: 'geoToggleSelect', + geoId: this._model.id, + name: eventData.name + }); + } + }; + + GeoView.prototype.updateSelectStatus = function (model, ecModel, api) { + var _this = this; + + this._mapDraw.group.traverse(function (node) { + var eventData = getECData(node).eventData; + + if (eventData) { + _this._model.isSelected(eventData.name) ? api.enterSelect(node) : api.leaveSelect(node); // No need to traverse children. + + return true; + } + }); + }; + + GeoView.prototype.findHighDownDispatchers = function (name) { + return this._mapDraw && this._mapDraw.findHighDownDispatchers(name, this._model); + }; + + GeoView.prototype.dispose = function () { + this._mapDraw && this._mapDraw.remove(); + }; + + GeoView.type = 'geo'; + return GeoView; + }(ComponentView); + + function registerMap$1(mapName, geoJson, specialAreas) { + geoSourceManager.registerMap(mapName, geoJson, specialAreas); + } + + function install$9(registers) { + registers.registerCoordinateSystem('geo', geoCreator); + registers.registerComponentModel(GeoModel); + registers.registerComponentView(GeoView); + registers.registerImpl('registerMap', registerMap$1); + registers.registerImpl('getMap', function (mapName) { + return geoSourceManager.getMapForUser(mapName); + }); + + function makeAction(method, actionInfo) { + actionInfo.update = 'geo:updateSelectStatus'; + registers.registerAction(actionInfo, function (payload, ecModel) { + var selected = {}; + var allSelected = []; + ecModel.eachComponent({ + mainType: 'geo', + query: payload + }, function (geoModel) { + geoModel[method](payload.name); + var geo = geoModel.coordinateSystem; + each(geo.regions, function (region) { + selected[region.name] = geoModel.isSelected(region.name) || false; + }); // Notice: there might be duplicated name in different regions. + + var names = []; + each(selected, function (v, name) { + selected[name] && names.push(name); + }); + allSelected.push({ + geoIndex: geoModel.componentIndex, + // Use singular, the same naming convention as the event `selectchanged`. + name: names + }); + }); + return { + selected: selected, + allSelected: allSelected, + name: payload.name + }; + }); + } + + makeAction('toggleSelected', { + type: 'geoToggleSelect', + event: 'geoselectchanged' + }); + makeAction('select', { + type: 'geoSelect', + event: 'geoselected' + }); + makeAction('unSelect', { + type: 'geoUnSelect', + event: 'geounselected' + }); + /** + * @payload + * @property {string} [componentType=series] + * @property {number} [dx] + * @property {number} [dy] + * @property {number} [zoom] + * @property {number} [originX] + * @property {number} [originY] + */ + + registers.registerAction({ + type: 'geoRoam', + event: 'geoRoam', + update: 'updateTransform' + }, function (payload, ecModel) { + var componentType = payload.componentType || 'series'; + ecModel.eachComponent({ + mainType: componentType, + query: payload + }, function (componentModel) { + var geo = componentModel.coordinateSystem; + + if (geo.type !== 'geo') { + return; + } + + var res = updateCenterAndZoom(geo, payload, componentModel.get('scaleLimit')); + componentModel.setCenter && componentModel.setCenter(res.center); + componentModel.setZoom && componentModel.setZoom(res.zoom); // All map series with same `map` use the same geo coordinate system + // So the center and zoom must be in sync. Include the series not selected by legend + + if (componentType === 'series') { + each(componentModel.seriesGroup, function (seriesModel) { + seriesModel.setCenter(res.center); + seriesModel.setZoom(res.zoom); + }); + } + }); + }); + } + + function install$a(registers) { + use(install$9); + registers.registerChartView(MapView); + registers.registerSeriesModel(MapSeries); + registers.registerLayout(mapSymbolLayout); + registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, mapDataStatistic); + createLegacyDataSelectAction('map', registers.registerAction); + } + + /** + * Initialize all computational message for following algorithm. + */ + + function init$2(inRoot) { + var root = inRoot; + root.hierNode = { + defaultAncestor: null, + ancestor: root, + prelim: 0, + modifier: 0, + change: 0, + shift: 0, + i: 0, + thread: null + }; + var nodes = [root]; + var node; + var children; + + while (node = nodes.pop()) { + // jshint ignore:line + children = node.children; + + if (node.isExpand && children.length) { + var n = children.length; + + for (var i = n - 1; i >= 0; i--) { + var child = children[i]; + child.hierNode = { + defaultAncestor: null, + ancestor: child, + prelim: 0, + modifier: 0, + change: 0, + shift: 0, + i: i, + thread: null + }; + nodes.push(child); + } + } + } + } + /** + * The implementation of this function was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + * + * Computes a preliminary x coordinate for node. Before that, this function is + * applied recursively to the children of node, as well as the function + * apportion(). After spacing out the children by calling executeShifts(), the + * node is placed to the midpoint of its outermost children. + */ + + function firstWalk(node, separation) { + var children = node.isExpand ? node.children : []; + var siblings = node.parentNode.children; + var subtreeW = node.hierNode.i ? siblings[node.hierNode.i - 1] : null; + + if (children.length) { + executeShifts(node); + var midPoint = (children[0].hierNode.prelim + children[children.length - 1].hierNode.prelim) / 2; + + if (subtreeW) { + node.hierNode.prelim = subtreeW.hierNode.prelim + separation(node, subtreeW); + node.hierNode.modifier = node.hierNode.prelim - midPoint; + } else { + node.hierNode.prelim = midPoint; + } + } else if (subtreeW) { + node.hierNode.prelim = subtreeW.hierNode.prelim + separation(node, subtreeW); + } + + node.parentNode.hierNode.defaultAncestor = apportion(node, subtreeW, node.parentNode.hierNode.defaultAncestor || siblings[0], separation); + } + /** + * The implementation of this function was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + * + * Computes all real x-coordinates by summing up the modifiers recursively. + */ + + function secondWalk(node) { + var nodeX = node.hierNode.prelim + node.parentNode.hierNode.modifier; + node.setLayout({ + x: nodeX + }, true); + node.hierNode.modifier += node.parentNode.hierNode.modifier; + } + function separation(cb) { + return arguments.length ? cb : defaultSeparation; + } + /** + * Transform the common coordinate to radial coordinate. + */ + + function radialCoordinate(rad, r) { + rad -= Math.PI / 2; + return { + x: r * Math.cos(rad), + y: r * Math.sin(rad) + }; + } + /** + * Get the layout position of the whole view. + */ + + function getViewRect$1(seriesModel, api) { + return getLayoutRect(seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + } + /** + * All other shifts, applied to the smaller subtrees between w- and w+, are + * performed by this function. + * + * The implementation of this function was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + */ + + function executeShifts(node) { + var children = node.children; + var n = children.length; + var shift = 0; + var change = 0; + + while (--n >= 0) { + var child = children[n]; + child.hierNode.prelim += shift; + child.hierNode.modifier += shift; + change += child.hierNode.change; + shift += child.hierNode.shift + change; + } + } + /** + * The implementation of this function was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + * + * The core of the algorithm. Here, a new subtree is combined with the + * previous subtrees. Threads are used to traverse the inside and outside + * contours of the left and right subtree up to the highest common level. + * Whenever two nodes of the inside contours conflict, we compute the left + * one of the greatest uncommon ancestors using the function nextAncestor() + * and call moveSubtree() to shift the subtree and prepare the shifts of + * smaller subtrees. Finally, we add a new thread (if necessary). + */ + + + function apportion(subtreeV, subtreeW, ancestor, separation) { + if (subtreeW) { + var nodeOutRight = subtreeV; + var nodeInRight = subtreeV; + var nodeOutLeft = nodeInRight.parentNode.children[0]; + var nodeInLeft = subtreeW; + var sumOutRight = nodeOutRight.hierNode.modifier; + var sumInRight = nodeInRight.hierNode.modifier; + var sumOutLeft = nodeOutLeft.hierNode.modifier; + var sumInLeft = nodeInLeft.hierNode.modifier; + + while (nodeInLeft = nextRight(nodeInLeft), nodeInRight = nextLeft(nodeInRight), nodeInLeft && nodeInRight) { + nodeOutRight = nextRight(nodeOutRight); + nodeOutLeft = nextLeft(nodeOutLeft); + nodeOutRight.hierNode.ancestor = subtreeV; + var shift = nodeInLeft.hierNode.prelim + sumInLeft - nodeInRight.hierNode.prelim - sumInRight + separation(nodeInLeft, nodeInRight); + + if (shift > 0) { + moveSubtree(nextAncestor(nodeInLeft, subtreeV, ancestor), subtreeV, shift); + sumInRight += shift; + sumOutRight += shift; + } + + sumInLeft += nodeInLeft.hierNode.modifier; + sumInRight += nodeInRight.hierNode.modifier; + sumOutRight += nodeOutRight.hierNode.modifier; + sumOutLeft += nodeOutLeft.hierNode.modifier; + } + + if (nodeInLeft && !nextRight(nodeOutRight)) { + nodeOutRight.hierNode.thread = nodeInLeft; + nodeOutRight.hierNode.modifier += sumInLeft - sumOutRight; + } + + if (nodeInRight && !nextLeft(nodeOutLeft)) { + nodeOutLeft.hierNode.thread = nodeInRight; + nodeOutLeft.hierNode.modifier += sumInRight - sumOutLeft; + ancestor = subtreeV; + } + } + + return ancestor; + } + /** + * This function is used to traverse the right contour of a subtree. + * It returns the rightmost child of node or the thread of node. The function + * returns null if and only if node is on the highest depth of its subtree. + */ + + + function nextRight(node) { + var children = node.children; + return children.length && node.isExpand ? children[children.length - 1] : node.hierNode.thread; + } + /** + * This function is used to traverse the left contour of a subtree (or a subforest). + * It returns the leftmost child of node or the thread of node. The function + * returns null if and only if node is on the highest depth of its subtree. + */ + + + function nextLeft(node) { + var children = node.children; + return children.length && node.isExpand ? children[0] : node.hierNode.thread; + } + /** + * If nodeInLeft’s ancestor is a sibling of node, returns nodeInLeft’s ancestor. + * Otherwise, returns the specified ancestor. + */ + + + function nextAncestor(nodeInLeft, node, ancestor) { + return nodeInLeft.hierNode.ancestor.parentNode === node.parentNode ? nodeInLeft.hierNode.ancestor : ancestor; + } + /** + * The implementation of this function was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + * + * Shifts the current subtree rooted at wr. + * This is done by increasing prelim(w+) and modifier(w+) by shift. + */ + + + function moveSubtree(wl, wr, shift) { + var change = shift / (wr.hierNode.i - wl.hierNode.i); + wr.hierNode.change -= change; + wr.hierNode.shift += shift; + wr.hierNode.modifier += shift; + wr.hierNode.prelim += shift; + wl.hierNode.change += change; + } + /** + * The implementation of this function was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + */ + + + function defaultSeparation(node1, node2) { + return node1.parentNode === node2.parentNode ? 1 : 2; + } + + var TreeEdgeShape = + /** @class */ + function () { + function TreeEdgeShape() { + this.parentPoint = []; + this.childPoints = []; + } + + return TreeEdgeShape; + }(); + + var TreePath = + /** @class */ + function (_super) { + __extends(TreePath, _super); + + function TreePath(opts) { + return _super.call(this, opts) || this; + } + + TreePath.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + + TreePath.prototype.getDefaultShape = function () { + return new TreeEdgeShape(); + }; + + TreePath.prototype.buildPath = function (ctx, shape) { + var childPoints = shape.childPoints; + var childLen = childPoints.length; + var parentPoint = shape.parentPoint; + var firstChildPos = childPoints[0]; + var lastChildPos = childPoints[childLen - 1]; + + if (childLen === 1) { + ctx.moveTo(parentPoint[0], parentPoint[1]); + ctx.lineTo(firstChildPos[0], firstChildPos[1]); + return; + } + + var orient = shape.orient; + var forkDim = orient === 'TB' || orient === 'BT' ? 0 : 1; + var otherDim = 1 - forkDim; + var forkPosition = parsePercent$1(shape.forkPosition, 1); + var tmpPoint = []; + tmpPoint[forkDim] = parentPoint[forkDim]; + tmpPoint[otherDim] = parentPoint[otherDim] + (lastChildPos[otherDim] - parentPoint[otherDim]) * forkPosition; + ctx.moveTo(parentPoint[0], parentPoint[1]); + ctx.lineTo(tmpPoint[0], tmpPoint[1]); + ctx.moveTo(firstChildPos[0], firstChildPos[1]); + tmpPoint[forkDim] = firstChildPos[forkDim]; + ctx.lineTo(tmpPoint[0], tmpPoint[1]); + tmpPoint[forkDim] = lastChildPos[forkDim]; + ctx.lineTo(tmpPoint[0], tmpPoint[1]); + ctx.lineTo(lastChildPos[0], lastChildPos[1]); + + for (var i = 1; i < childLen - 1; i++) { + var point = childPoints[i]; + ctx.moveTo(point[0], point[1]); + tmpPoint[forkDim] = point[forkDim]; + ctx.lineTo(tmpPoint[0], tmpPoint[1]); + } + }; + + return TreePath; + }(Path); + + var TreeView = + /** @class */ + function (_super) { + __extends(TreeView, _super); + + function TreeView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TreeView.type; + _this._mainGroup = new Group(); + return _this; + } + + TreeView.prototype.init = function (ecModel, api) { + this._controller = new RoamController(api.getZr()); + this._controllerHost = { + target: this.group + }; + this.group.add(this._mainGroup); + }; + + TreeView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var layoutInfo = seriesModel.layoutInfo; + var group = this._mainGroup; + var layout = seriesModel.get('layout'); + + if (layout === 'radial') { + group.x = layoutInfo.x + layoutInfo.width / 2; + group.y = layoutInfo.y + layoutInfo.height / 2; + } else { + group.x = layoutInfo.x; + group.y = layoutInfo.y; + } + + this._updateViewCoordSys(seriesModel); + + this._updateController(seriesModel, ecModel, api); + + var oldData = this._data; + data.diff(oldData).add(function (newIdx) { + if (symbolNeedsDraw$1(data, newIdx)) { + // Create node and edge + updateNode(data, newIdx, null, group, seriesModel); + } + }).update(function (newIdx, oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); + + if (!symbolNeedsDraw$1(data, newIdx)) { + symbolEl && removeNode(oldData, oldIdx, symbolEl, group, seriesModel); + return; + } // Update node and edge + + + updateNode(data, newIdx, symbolEl, group, seriesModel); + }).remove(function (oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); // When remove a collapsed node of subtree, since the collapsed + // node haven't been initialized with a symbol element, + // you can't found it's symbol element through index. + // so if we want to remove the symbol element we should insure + // that the symbol element is not null. + + if (symbolEl) { + removeNode(oldData, oldIdx, symbolEl, group, seriesModel); + } + }).execute(); + this._nodeScaleRatio = seriesModel.get('nodeScaleRatio'); + + this._updateNodeAndLinkScale(seriesModel); + + if (seriesModel.get('expandAndCollapse') === true) { + data.eachItemGraphicEl(function (el, dataIndex) { + el.off('click').on('click', function () { + api.dispatchAction({ + type: 'treeExpandAndCollapse', + seriesId: seriesModel.id, + dataIndex: dataIndex + }); + }); + }); + } + + this._data = data; + }; + + TreeView.prototype._updateViewCoordSys = function (seriesModel) { + var data = seriesModel.getData(); + var points = []; + data.each(function (idx) { + var layout = data.getItemLayout(idx); + + if (layout && !isNaN(layout.x) && !isNaN(layout.y)) { + points.push([+layout.x, +layout.y]); + } + }); + var min = []; + var max = []; + fromPoints(points, min, max); // If don't Store min max when collapse the root node after roam, + // the root node will disappear. + + var oldMin = this._min; + var oldMax = this._max; // If width or height is 0 + + if (max[0] - min[0] === 0) { + min[0] = oldMin ? oldMin[0] : min[0] - 1; + max[0] = oldMax ? oldMax[0] : max[0] + 1; + } + + if (max[1] - min[1] === 0) { + min[1] = oldMin ? oldMin[1] : min[1] - 1; + max[1] = oldMax ? oldMax[1] : max[1] + 1; + } + + var viewCoordSys = seriesModel.coordinateSystem = new View(); + viewCoordSys.zoomLimit = seriesModel.get('scaleLimit'); + viewCoordSys.setBoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]); + viewCoordSys.setCenter(seriesModel.get('center')); + viewCoordSys.setZoom(seriesModel.get('zoom')); // Here we use viewCoordSys just for computing the 'position' and 'scale' of the group + + this.group.attr({ + x: viewCoordSys.x, + y: viewCoordSys.y, + scaleX: viewCoordSys.scaleX, + scaleY: viewCoordSys.scaleY + }); + this._min = min; + this._max = max; + }; + + TreeView.prototype._updateController = function (seriesModel, ecModel, api) { + var _this = this; + + var controller = this._controller; + var controllerHost = this._controllerHost; + var group = this.group; + controller.setPointerChecker(function (e, x, y) { + var rect = group.getBoundingRect(); + rect.applyTransform(group.transform); + return rect.contain(x, y) && !onIrrelevantElement(e, api, seriesModel); + }); + controller.enable(seriesModel.get('roam')); + controllerHost.zoomLimit = seriesModel.get('scaleLimit'); + controllerHost.zoom = seriesModel.coordinateSystem.getZoom(); + controller.off('pan').off('zoom').on('pan', function (e) { + updateViewOnPan(controllerHost, e.dx, e.dy); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'treeRoam', + dx: e.dx, + dy: e.dy + }); + }).on('zoom', function (e) { + updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'treeRoam', + zoom: e.scale, + originX: e.originX, + originY: e.originY + }); + + _this._updateNodeAndLinkScale(seriesModel); // Only update label layout on zoom + + + api.updateLabelLayout(); + }); + }; + + TreeView.prototype._updateNodeAndLinkScale = function (seriesModel) { + var data = seriesModel.getData(); + + var nodeScale = this._getNodeGlobalScale(seriesModel); + + data.eachItemGraphicEl(function (el, idx) { + el.setSymbolScale(nodeScale); + }); + }; + + TreeView.prototype._getNodeGlobalScale = function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys.type !== 'view') { + return 1; + } + + var nodeScaleRatio = this._nodeScaleRatio; + var groupZoom = coordSys.scaleX || 1; // Scale node when zoom changes + + var roamZoom = coordSys.getZoom(); + var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1; + return nodeScale / groupZoom; + }; + + TreeView.prototype.dispose = function () { + this._controller && this._controller.dispose(); + this._controllerHost = null; + }; + + TreeView.prototype.remove = function () { + this._mainGroup.removeAll(); + + this._data = null; + }; + + TreeView.type = 'tree'; + return TreeView; + }(ChartView); + + function symbolNeedsDraw$1(data, dataIndex) { + var layout = data.getItemLayout(dataIndex); + return layout && !isNaN(layout.x) && !isNaN(layout.y); + } + + function updateNode(data, dataIndex, symbolEl, group, seriesModel) { + var isInit = !symbolEl; + var node = data.tree.getNodeByDataIndex(dataIndex); + var itemModel = node.getModel(); + var visualColor = node.getVisual('style').fill; + var symbolInnerColor = node.isExpand === false && node.children.length !== 0 ? visualColor : '#fff'; + var virtualRoot = data.tree.root; + var source = node.parentNode === virtualRoot ? node : node.parentNode || node; + var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex); + var sourceLayout = source.getLayout(); + var sourceOldLayout = sourceSymbolEl ? { + x: sourceSymbolEl.__oldX, + y: sourceSymbolEl.__oldY, + rawX: sourceSymbolEl.__radialOldRawX, + rawY: sourceSymbolEl.__radialOldRawY + } : sourceLayout; + var targetLayout = node.getLayout(); + + if (isInit) { + symbolEl = new Symbol(data, dataIndex, null, { + symbolInnerColor: symbolInnerColor, + useNameLabel: true + }); + symbolEl.x = sourceOldLayout.x; + symbolEl.y = sourceOldLayout.y; + } else { + symbolEl.updateData(data, dataIndex, null, { + symbolInnerColor: symbolInnerColor, + useNameLabel: true + }); + } + + symbolEl.__radialOldRawX = symbolEl.__radialRawX; + symbolEl.__radialOldRawY = symbolEl.__radialRawY; + symbolEl.__radialRawX = targetLayout.rawX; + symbolEl.__radialRawY = targetLayout.rawY; + group.add(symbolEl); + data.setItemGraphicEl(dataIndex, symbolEl); + symbolEl.__oldX = symbolEl.x; + symbolEl.__oldY = symbolEl.y; + updateProps(symbolEl, { + x: targetLayout.x, + y: targetLayout.y + }, seriesModel); + var symbolPath = symbolEl.getSymbolPath(); + + if (seriesModel.get('layout') === 'radial') { + var realRoot = virtualRoot.children[0]; + var rootLayout = realRoot.getLayout(); + var length_1 = realRoot.children.length; + var rad = void 0; + var isLeft = void 0; + + if (targetLayout.x === rootLayout.x && node.isExpand === true) { + var center = { + x: (realRoot.children[0].getLayout().x + realRoot.children[length_1 - 1].getLayout().x) / 2, + y: (realRoot.children[0].getLayout().y + realRoot.children[length_1 - 1].getLayout().y) / 2 + }; + rad = Math.atan2(center.y - rootLayout.y, center.x - rootLayout.x); + + if (rad < 0) { + rad = Math.PI * 2 + rad; + } + + isLeft = center.x < rootLayout.x; + + if (isLeft) { + rad = rad - Math.PI; + } + } else { + rad = Math.atan2(targetLayout.y - rootLayout.y, targetLayout.x - rootLayout.x); + + if (rad < 0) { + rad = Math.PI * 2 + rad; + } + + if (node.children.length === 0 || node.children.length !== 0 && node.isExpand === false) { + isLeft = targetLayout.x < rootLayout.x; + + if (isLeft) { + rad = rad - Math.PI; + } + } else { + isLeft = targetLayout.x > rootLayout.x; + + if (!isLeft) { + rad = rad - Math.PI; + } + } + } + + var textPosition = isLeft ? 'left' : 'right'; + var normalLabelModel = itemModel.getModel('label'); + var rotate = normalLabelModel.get('rotate'); + var labelRotateRadian = rotate * (Math.PI / 180); + var textContent = symbolPath.getTextContent(); + + if (textContent) { + symbolPath.setTextConfig({ + position: normalLabelModel.get('position') || textPosition, + rotation: rotate == null ? -rad : labelRotateRadian, + origin: 'center' + }); + textContent.setStyle('verticalAlign', 'middle'); + } + } // Handle status + + + var focus = itemModel.get(['emphasis', 'focus']); + var focusDataIndices = focus === 'ancestor' ? node.getAncestorsIndices() : focus === 'descendant' ? node.getDescendantIndices() : null; + + if (focusDataIndices) { + // Modify the focus to data indices. + getECData(symbolEl).focus = focusDataIndices; + } + + drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sourceLayout, targetLayout, group); + + if (symbolEl.__edge) { + symbolEl.onHoverStateChange = function (toState) { + if (toState !== 'blur') { + // NOTE: Ensure the parent elements will been blurred firstly. + // According to the return of getAncestorsIndices and getDescendantIndices + // TODO: A bit tricky. + var parentEl = node.parentNode && data.getItemGraphicEl(node.parentNode.dataIndex); + + if (!(parentEl && parentEl.hoverState === HOVER_STATE_BLUR)) { + setStatesFlag(symbolEl.__edge, toState); + } + } + }; + } + } + + function drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sourceLayout, targetLayout, group) { + var itemModel = node.getModel(); + var edgeShape = seriesModel.get('edgeShape'); + var layout = seriesModel.get('layout'); + var orient = seriesModel.getOrient(); + var curvature = seriesModel.get(['lineStyle', 'curveness']); + var edgeForkPosition = seriesModel.get('edgeForkPosition'); + var lineStyle = itemModel.getModel('lineStyle').getLineStyle(); + var edge = symbolEl.__edge; + + if (edgeShape === 'curve') { + if (node.parentNode && node.parentNode !== virtualRoot) { + if (!edge) { + edge = symbolEl.__edge = new BezierCurve({ + shape: getEdgeShape(layout, orient, curvature, sourceOldLayout, sourceOldLayout) + }); + } + + updateProps(edge, { + shape: getEdgeShape(layout, orient, curvature, sourceLayout, targetLayout) + }, seriesModel); + } + } else if (edgeShape === 'polyline') { + if (layout === 'orthogonal') { + if (node !== virtualRoot && node.children && node.children.length !== 0 && node.isExpand === true) { + var children = node.children; + var childPoints = []; + + for (var i = 0; i < children.length; i++) { + var childLayout = children[i].getLayout(); + childPoints.push([childLayout.x, childLayout.y]); + } + + if (!edge) { + edge = symbolEl.__edge = new TreePath({ + shape: { + parentPoint: [targetLayout.x, targetLayout.y], + childPoints: [[targetLayout.x, targetLayout.y]], + orient: orient, + forkPosition: edgeForkPosition + } + }); + } + + updateProps(edge, { + shape: { + parentPoint: [targetLayout.x, targetLayout.y], + childPoints: childPoints + } + }, seriesModel); + } + } else { + if ("development" !== 'production') { + throw new Error('The polyline edgeShape can only be used in orthogonal layout'); + } + } + } + + if (edge) { + edge.useStyle(defaults({ + strokeNoScale: true, + fill: null + }, lineStyle)); + setStatesStylesFromModel(edge, itemModel, 'lineStyle'); + setDefaultStateProxy(edge); + group.add(edge); + } + } + + function removeNodeEdge(node, data, group, seriesModel, removeAnimationOpt) { + var virtualRoot = data.tree.root; + + var _a = getSourceNode(virtualRoot, node), + source = _a.source, + sourceLayout = _a.sourceLayout; + + var symbolEl = data.getItemGraphicEl(node.dataIndex); + + if (!symbolEl) { + return; + } + + var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex); + var sourceEdge = sourceSymbolEl.__edge; // 1. when expand the sub tree, delete the children node should delete the edge of + // the source at the same time. because the polyline edge shape is only owned by the source. + // 2.when the node is the only children of the source, delete the node should delete the edge of + // the source at the same time. the same reason as above. + + var edge = symbolEl.__edge || (source.isExpand === false || source.children.length === 1 ? sourceEdge : undefined); + var edgeShape = seriesModel.get('edgeShape'); + var layoutOpt = seriesModel.get('layout'); + var orient = seriesModel.get('orient'); + var curvature = seriesModel.get(['lineStyle', 'curveness']); + + if (edge) { + if (edgeShape === 'curve') { + removeElement(edge, { + shape: getEdgeShape(layoutOpt, orient, curvature, sourceLayout, sourceLayout), + style: { + opacity: 0 + } + }, seriesModel, { + cb: function () { + group.remove(edge); + }, + removeOpt: removeAnimationOpt + }); + } else if (edgeShape === 'polyline' && seriesModel.get('layout') === 'orthogonal') { + removeElement(edge, { + shape: { + parentPoint: [sourceLayout.x, sourceLayout.y], + childPoints: [[sourceLayout.x, sourceLayout.y]] + }, + style: { + opacity: 0 + } + }, seriesModel, { + cb: function () { + group.remove(edge); + }, + removeOpt: removeAnimationOpt + }); + } + } + } + + function getSourceNode(virtualRoot, node) { + var source = node.parentNode === virtualRoot ? node : node.parentNode || node; + var sourceLayout; + + while (sourceLayout = source.getLayout(), sourceLayout == null) { + source = source.parentNode === virtualRoot ? source : source.parentNode || source; + } + + return { + source: source, + sourceLayout: sourceLayout + }; + } + + function removeNode(data, dataIndex, symbolEl, group, seriesModel) { + var node = data.tree.getNodeByDataIndex(dataIndex); + var virtualRoot = data.tree.root; + var sourceLayout = getSourceNode(virtualRoot, node).sourceLayout; // Use same duration and easing with update to have more consistent animation. + + var removeAnimationOpt = { + duration: seriesModel.get('animationDurationUpdate'), + easing: seriesModel.get('animationEasingUpdate') + }; + removeElement(symbolEl, { + x: sourceLayout.x + 1, + y: sourceLayout.y + 1 + }, seriesModel, { + cb: function () { + group.remove(symbolEl); + data.setItemGraphicEl(dataIndex, null); + }, + removeOpt: removeAnimationOpt + }); + symbolEl.fadeOut(null, data.hostModel, { + fadeLabel: true, + animation: removeAnimationOpt + }); // remove edge as parent node + + node.children.forEach(function (childNode) { + removeNodeEdge(childNode, data, group, seriesModel, removeAnimationOpt); + }); // remove edge as child node + + removeNodeEdge(node, data, group, seriesModel, removeAnimationOpt); + } + + function getEdgeShape(layoutOpt, orient, curvature, sourceLayout, targetLayout) { + var cpx1; + var cpy1; + var cpx2; + var cpy2; + var x1; + var x2; + var y1; + var y2; + + if (layoutOpt === 'radial') { + x1 = sourceLayout.rawX; + y1 = sourceLayout.rawY; + x2 = targetLayout.rawX; + y2 = targetLayout.rawY; + var radialCoor1 = radialCoordinate(x1, y1); + var radialCoor2 = radialCoordinate(x1, y1 + (y2 - y1) * curvature); + var radialCoor3 = radialCoordinate(x2, y2 + (y1 - y2) * curvature); + var radialCoor4 = radialCoordinate(x2, y2); + return { + x1: radialCoor1.x || 0, + y1: radialCoor1.y || 0, + x2: radialCoor4.x || 0, + y2: radialCoor4.y || 0, + cpx1: radialCoor2.x || 0, + cpy1: radialCoor2.y || 0, + cpx2: radialCoor3.x || 0, + cpy2: radialCoor3.y || 0 + }; + } else { + x1 = sourceLayout.x; + y1 = sourceLayout.y; + x2 = targetLayout.x; + y2 = targetLayout.y; + + if (orient === 'LR' || orient === 'RL') { + cpx1 = x1 + (x2 - x1) * curvature; + cpy1 = y1; + cpx2 = x2 + (x1 - x2) * curvature; + cpy2 = y2; + } + + if (orient === 'TB' || orient === 'BT') { + cpx1 = x1; + cpy1 = y1 + (y2 - y1) * curvature; + cpx2 = x2; + cpy2 = y2 + (y1 - y2) * curvature; + } + } + + return { + x1: x1, + y1: y1, + x2: x2, + y2: y2, + cpx1: cpx1, + cpy1: cpy1, + cpx2: cpx2, + cpy2: cpy2 + }; + } + + var inner$7 = makeInner(); + + function linkSeriesData(opt) { + var mainData = opt.mainData; + var datas = opt.datas; + + if (!datas) { + datas = { + main: mainData + }; + opt.datasAttr = { + main: 'data' + }; + } + + opt.datas = opt.mainData = null; + linkAll(mainData, datas, opt); // Porxy data original methods. + + each(datas, function (data) { + each(mainData.TRANSFERABLE_METHODS, function (methodName) { + data.wrapMethod(methodName, curry(transferInjection, opt)); + }); + }); // Beyond transfer, additional features should be added to `cloneShallow`. + + mainData.wrapMethod('cloneShallow', curry(cloneShallowInjection, opt)); // Only mainData trigger change, because struct.update may trigger + // another changable methods, which may bring about dead lock. + + each(mainData.CHANGABLE_METHODS, function (methodName) { + mainData.wrapMethod(methodName, curry(changeInjection, opt)); + }); // Make sure datas contains mainData. + + assert(datas[mainData.dataType] === mainData); + } + + function transferInjection(opt, res) { + if (isMainData(this)) { + // Transfer datas to new main data. + var datas = extend({}, inner$7(this).datas); + datas[this.dataType] = res; + linkAll(res, datas, opt); + } else { + // Modify the reference in main data to point newData. + linkSingle(res, this.dataType, inner$7(this).mainData, opt); + } + + return res; + } + + function changeInjection(opt, res) { + opt.struct && opt.struct.update(); + return res; + } + + function cloneShallowInjection(opt, res) { + // cloneShallow, which brings about some fragilities, may be inappropriate + // to be exposed as an API. So for implementation simplicity we can make + // the restriction that cloneShallow of not-mainData should not be invoked + // outside, but only be invoked here. + each(inner$7(res).datas, function (data, dataType) { + data !== res && linkSingle(data.cloneShallow(), dataType, res, opt); + }); + return res; + } + /** + * Supplement method to List. + * + * @public + * @param [dataType] If not specified, return mainData. + */ + + + function getLinkedData(dataType) { + var mainData = inner$7(this).mainData; + return dataType == null || mainData == null ? mainData : inner$7(mainData).datas[dataType]; + } + /** + * Get list of all linked data + */ + + + function getLinkedDataAll() { + var mainData = inner$7(this).mainData; + return mainData == null ? [{ + data: mainData + }] : map(keys(inner$7(mainData).datas), function (type) { + return { + type: type, + data: inner$7(mainData).datas[type] + }; + }); + } + + function isMainData(data) { + return inner$7(data).mainData === data; + } + + function linkAll(mainData, datas, opt) { + inner$7(mainData).datas = {}; + each(datas, function (data, dataType) { + linkSingle(data, dataType, mainData, opt); + }); + } + + function linkSingle(data, dataType, mainData, opt) { + inner$7(mainData).datas[dataType] = data; + inner$7(data).mainData = mainData; + data.dataType = dataType; + + if (opt.struct) { + data[opt.structAttr] = opt.struct; + opt.struct[opt.datasAttr[dataType]] = data; + } // Supplement method. + + + data.getLinkedData = getLinkedData; + data.getLinkedDataAll = getLinkedDataAll; + } + + var TreeNode = + /** @class */ + function () { + function TreeNode(name, hostTree) { + this.depth = 0; + this.height = 0; + /** + * Reference to list item. + * Do not persistent dataIndex outside, + * besause it may be changed by list. + * If dataIndex -1, + * this node is logical deleted (filtered) in list. + */ + + this.dataIndex = -1; + this.children = []; + this.viewChildren = []; + this.isExpand = false; + this.name = name || ''; + this.hostTree = hostTree; + } + /** + * The node is removed. + */ + + + TreeNode.prototype.isRemoved = function () { + return this.dataIndex < 0; + }; + + TreeNode.prototype.eachNode = function (options, cb, context) { + if (isFunction(options)) { + context = cb; + cb = options; + options = null; + } + + options = options || {}; + + if (isString(options)) { + options = { + order: options + }; + } + + var order = options.order || 'preorder'; + var children = this[options.attr || 'children']; + var suppressVisitSub; + order === 'preorder' && (suppressVisitSub = cb.call(context, this)); + + for (var i = 0; !suppressVisitSub && i < children.length; i++) { + children[i].eachNode(options, cb, context); + } + + order === 'postorder' && cb.call(context, this); + }; + /** + * Update depth and height of this subtree. + */ + + + TreeNode.prototype.updateDepthAndHeight = function (depth) { + var height = 0; + this.depth = depth; + + for (var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + child.updateDepthAndHeight(depth + 1); + + if (child.height > height) { + height = child.height; + } + } + + this.height = height + 1; + }; + + TreeNode.prototype.getNodeById = function (id) { + if (this.getId() === id) { + return this; + } + + for (var i = 0, children = this.children, len = children.length; i < len; i++) { + var res = children[i].getNodeById(id); + + if (res) { + return res; + } + } + }; + + TreeNode.prototype.contains = function (node) { + if (node === this) { + return true; + } + + for (var i = 0, children = this.children, len = children.length; i < len; i++) { + var res = children[i].contains(node); + + if (res) { + return res; + } + } + }; + /** + * @param includeSelf Default false. + * @return order: [root, child, grandchild, ...] + */ + + + TreeNode.prototype.getAncestors = function (includeSelf) { + var ancestors = []; + var node = includeSelf ? this : this.parentNode; + + while (node) { + ancestors.push(node); + node = node.parentNode; + } + + ancestors.reverse(); + return ancestors; + }; + + TreeNode.prototype.getAncestorsIndices = function () { + var indices = []; + var currNode = this; + + while (currNode) { + indices.push(currNode.dataIndex); + currNode = currNode.parentNode; + } + + indices.reverse(); + return indices; + }; + + TreeNode.prototype.getDescendantIndices = function () { + var indices = []; + this.eachNode(function (childNode) { + indices.push(childNode.dataIndex); + }); + return indices; + }; + + TreeNode.prototype.getValue = function (dimension) { + var data = this.hostTree.data; + return data.getStore().get(data.getDimensionIndex(dimension || 'value'), this.dataIndex); + }; + + TreeNode.prototype.setLayout = function (layout, merge) { + this.dataIndex >= 0 && this.hostTree.data.setItemLayout(this.dataIndex, layout, merge); + }; + /** + * @return {Object} layout + */ + + + TreeNode.prototype.getLayout = function () { + return this.hostTree.data.getItemLayout(this.dataIndex); + }; // @depcrecated + // getModel(path: S): Model + // eslint-disable-next-line @typescript-eslint/no-unused-vars + + + TreeNode.prototype.getModel = function (path) { + if (this.dataIndex < 0) { + return; + } + + var hostTree = this.hostTree; + var itemModel = hostTree.data.getItemModel(this.dataIndex); + return itemModel.getModel(path); + }; // TODO: TYPE More specific model + + + TreeNode.prototype.getLevelModel = function () { + return (this.hostTree.levelModels || [])[this.depth]; + }; + + TreeNode.prototype.setVisual = function (key, value) { + this.dataIndex >= 0 && this.hostTree.data.setItemVisual(this.dataIndex, key, value); + }; + /** + * Get item visual + * FIXME: make return type better + */ + + + TreeNode.prototype.getVisual = function (key) { + return this.hostTree.data.getItemVisual(this.dataIndex, key); + }; + + TreeNode.prototype.getRawIndex = function () { + return this.hostTree.data.getRawIndex(this.dataIndex); + }; + + TreeNode.prototype.getId = function () { + return this.hostTree.data.getId(this.dataIndex); + }; + /** + * index in parent's children + */ + + + TreeNode.prototype.getChildIndex = function () { + if (this.parentNode) { + var children = this.parentNode.children; + + for (var i = 0; i < children.length; ++i) { + if (children[i] === this) { + return i; + } + } + + return -1; + } + + return -1; + }; + /** + * if this is an ancestor of another node + * + * @param node another node + * @return if is ancestor + */ + + + TreeNode.prototype.isAncestorOf = function (node) { + var parent = node.parentNode; + + while (parent) { + if (parent === this) { + return true; + } + + parent = parent.parentNode; + } + + return false; + }; + /** + * if this is an descendant of another node + * + * @param node another node + * @return if is descendant + */ + + + TreeNode.prototype.isDescendantOf = function (node) { + return node !== this && node.isAncestorOf(this); + }; + + return TreeNode; + }(); + + var Tree = + /** @class */ + function () { + function Tree(hostModel) { + this.type = 'tree'; + this._nodes = []; + this.hostModel = hostModel; + } + + Tree.prototype.eachNode = function (options, cb, context) { + this.root.eachNode(options, cb, context); + }; + + Tree.prototype.getNodeByDataIndex = function (dataIndex) { + var rawIndex = this.data.getRawIndex(dataIndex); + return this._nodes[rawIndex]; + }; + + Tree.prototype.getNodeById = function (name) { + return this.root.getNodeById(name); + }; + /** + * Update item available by list, + * when list has been performed options like 'filterSelf' or 'map'. + */ + + + Tree.prototype.update = function () { + var data = this.data; + var nodes = this._nodes; + + for (var i = 0, len = nodes.length; i < len; i++) { + nodes[i].dataIndex = -1; + } + + for (var i = 0, len = data.count(); i < len; i++) { + nodes[data.getRawIndex(i)].dataIndex = i; + } + }; + /** + * Clear all layouts + */ + + + Tree.prototype.clearLayouts = function () { + this.data.clearItemLayouts(); + }; + /** + * data node format: + * { + * name: ... + * value: ... + * children: [ + * { + * name: ... + * value: ... + * children: ... + * }, + * ... + * ] + * } + */ + + + Tree.createTree = function (dataRoot, hostModel, beforeLink) { + var tree = new Tree(hostModel); + var listData = []; + var dimMax = 1; + buildHierarchy(dataRoot); + + function buildHierarchy(dataNode, parentNode) { + var value = dataNode.value; + dimMax = Math.max(dimMax, isArray(value) ? value.length : 1); + listData.push(dataNode); + var node = new TreeNode(convertOptionIdName(dataNode.name, ''), tree); + parentNode ? addChild(node, parentNode) : tree.root = node; + + tree._nodes.push(node); + + var children = dataNode.children; + + if (children) { + for (var i = 0; i < children.length; i++) { + buildHierarchy(children[i], node); + } + } + } + + tree.root.updateDepthAndHeight(0); + var dimensions = prepareSeriesDataSchema(listData, { + coordDimensions: ['value'], + dimensionsCount: dimMax + }).dimensions; + var list = new SeriesData(dimensions, hostModel); + list.initData(listData); + beforeLink && beforeLink(list); + linkSeriesData({ + mainData: list, + struct: tree, + structAttr: 'tree' + }); + tree.update(); + return tree; + }; + + return Tree; + }(); + /** + * It is needed to consider the mess of 'list', 'hostModel' when creating a TreeNote, + * so this function is not ready and not necessary to be public. + */ + + + function addChild(child, node) { + var children = node.children; + + if (child.parentNode === node) { + return; + } + + children.push(child); + child.parentNode = node; + } + + function retrieveTargetInfo(payload, validPayloadTypes, seriesModel) { + if (payload && indexOf(validPayloadTypes, payload.type) >= 0) { + var root = seriesModel.getData().tree.root; + var targetNode = payload.targetNode; + + if (isString(targetNode)) { + targetNode = root.getNodeById(targetNode); + } + + if (targetNode && root.contains(targetNode)) { + return { + node: targetNode + }; + } + + var targetNodeId = payload.targetNodeId; + + if (targetNodeId != null && (targetNode = root.getNodeById(targetNodeId))) { + return { + node: targetNode + }; + } + } + } // Not includes the given node at the last item. + + function getPathToRoot(node) { + var path = []; + + while (node) { + node = node.parentNode; + node && path.push(node); + } + + return path.reverse(); + } + function aboveViewRoot(viewRoot, node) { + var viewPath = getPathToRoot(viewRoot); + return indexOf(viewPath, node) >= 0; + } // From root to the input node (the input node will be included). + + function wrapTreePathInfo(node, seriesModel) { + var treePathInfo = []; + + while (node) { + var nodeDataIndex = node.dataIndex; + treePathInfo.push({ + name: node.name, + dataIndex: nodeDataIndex, + value: seriesModel.getRawValue(nodeDataIndex) + }); + node = node.parentNode; + } + + treePathInfo.reverse(); + return treePathInfo; + } + + var TreeSeriesModel = + /** @class */ + function (_super) { + __extends(TreeSeriesModel, _super); + + function TreeSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.hasSymbolVisual = true; // Do it self. + + _this.ignoreStyleOnData = true; + return _this; + } + /** + * Init a tree data structure from data in option series + */ + + + TreeSeriesModel.prototype.getInitialData = function (option) { + //create an virtual root + var root = { + name: option.name, + children: option.data + }; + var leaves = option.leaves || {}; + var leavesModel = new Model(leaves, this, this.ecModel); + var tree = Tree.createTree(root, this, beforeLink); + + function beforeLink(nodeData) { + nodeData.wrapMethod('getItemModel', function (model, idx) { + var node = tree.getNodeByDataIndex(idx); + + if (!(node && node.children.length && node.isExpand)) { + model.parentModel = leavesModel; + } + + return model; + }); + } + + var treeDepth = 0; + tree.eachNode('preorder', function (node) { + if (node.depth > treeDepth) { + treeDepth = node.depth; + } + }); + var expandAndCollapse = option.expandAndCollapse; + var expandTreeDepth = expandAndCollapse && option.initialTreeDepth >= 0 ? option.initialTreeDepth : treeDepth; + tree.root.eachNode('preorder', function (node) { + var item = node.hostTree.data.getRawDataItem(node.dataIndex); // Add item.collapsed != null, because users can collapse node original in the series.data. + + node.isExpand = item && item.collapsed != null ? !item.collapsed : node.depth <= expandTreeDepth; + }); + return tree.data; + }; + /** + * Make the configuration 'orient' backward compatibly, with 'horizontal = LR', 'vertical = TB'. + * @returns {string} orient + */ + + + TreeSeriesModel.prototype.getOrient = function () { + var orient = this.get('orient'); + + if (orient === 'horizontal') { + orient = 'LR'; + } else if (orient === 'vertical') { + orient = 'TB'; + } + + return orient; + }; + + TreeSeriesModel.prototype.setZoom = function (zoom) { + this.option.zoom = zoom; + }; + + TreeSeriesModel.prototype.setCenter = function (center) { + this.option.center = center; + }; + + TreeSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var tree = this.getData().tree; + var realRoot = tree.root.children[0]; + var node = tree.getNodeByDataIndex(dataIndex); + var value = node.getValue(); + var name = node.name; + + while (node && node !== realRoot) { + name = node.parentNode.name + '.' + name; + node = node.parentNode; + } + + return createTooltipMarkup('nameValue', { + name: name, + value: value, + noValue: isNaN(value) || value == null + }); + }; // Add tree path to tooltip param + + + TreeSeriesModel.prototype.getDataParams = function (dataIndex) { + var params = _super.prototype.getDataParams.apply(this, arguments); + + var node = this.getData().tree.getNodeByDataIndex(dataIndex); + params.treeAncestors = wrapTreePathInfo(node, this); + params.collapsed = !node.isExpand; + return params; + }; + + TreeSeriesModel.type = 'series.tree'; // can support the position parameters 'left', 'top','right','bottom', 'width', + // 'height' in the setOption() with 'merge' mode normal. + + TreeSeriesModel.layoutMode = 'box'; + TreeSeriesModel.defaultOption = { + // zlevel: 0, + z: 2, + coordinateSystem: 'view', + // the position of the whole view + left: '12%', + top: '12%', + right: '12%', + bottom: '12%', + // the layout of the tree, two value can be selected, 'orthogonal' or 'radial' + layout: 'orthogonal', + // value can be 'polyline' + edgeShape: 'curve', + edgeForkPosition: '50%', + // true | false | 'move' | 'scale', see module:component/helper/RoamController. + roam: false, + // Symbol size scale ratio in roam + nodeScaleRatio: 0.4, + // Default on center of graph + center: null, + zoom: 1, + orient: 'LR', + symbol: 'emptyCircle', + symbolSize: 7, + expandAndCollapse: true, + initialTreeDepth: 2, + lineStyle: { + color: '#ccc', + width: 1.5, + curveness: 0.5 + }, + itemStyle: { + color: 'lightsteelblue', + // borderColor: '#c23531', + borderWidth: 1.5 + }, + label: { + show: true + }, + animationEasing: 'linear', + animationDuration: 700, + animationDurationUpdate: 500 + }; + return TreeSeriesModel; + }(SeriesModel); + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + /** + * Traverse the tree from bottom to top and do something + */ + function eachAfter(root, callback, separation) { + var nodes = [root]; + var next = []; + var node; + + while (node = nodes.pop()) { + // jshint ignore:line + next.push(node); + + if (node.isExpand) { + var children = node.children; + + if (children.length) { + for (var i = 0; i < children.length; i++) { + nodes.push(children[i]); + } + } + } + } + + while (node = next.pop()) { + // jshint ignore:line + callback(node, separation); + } + } + /** + * Traverse the tree from top to bottom and do something + */ + + + function eachBefore(root, callback) { + var nodes = [root]; + var node; + + while (node = nodes.pop()) { + // jshint ignore:line + callback(node); + + if (node.isExpand) { + var children = node.children; + + if (children.length) { + for (var i = children.length - 1; i >= 0; i--) { + nodes.push(children[i]); + } + } + } + } + } + + function treeLayout(ecModel, api) { + ecModel.eachSeriesByType('tree', function (seriesModel) { + commonLayout(seriesModel, api); + }); + } + + function commonLayout(seriesModel, api) { + var layoutInfo = getViewRect$1(seriesModel, api); + seriesModel.layoutInfo = layoutInfo; + var layout = seriesModel.get('layout'); + var width = 0; + var height = 0; + var separation$1 = null; + + if (layout === 'radial') { + width = 2 * Math.PI; + height = Math.min(layoutInfo.height, layoutInfo.width) / 2; + separation$1 = separation(function (node1, node2) { + return (node1.parentNode === node2.parentNode ? 1 : 2) / node1.depth; + }); + } else { + width = layoutInfo.width; + height = layoutInfo.height; + separation$1 = separation(); + } + + var virtualRoot = seriesModel.getData().tree.root; + var realRoot = virtualRoot.children[0]; + + if (realRoot) { + init$2(virtualRoot); + eachAfter(realRoot, firstWalk, separation$1); + virtualRoot.hierNode.modifier = -realRoot.hierNode.prelim; + eachBefore(realRoot, secondWalk); + var left_1 = realRoot; + var right_1 = realRoot; + var bottom_1 = realRoot; + eachBefore(realRoot, function (node) { + var x = node.getLayout().x; + + if (x < left_1.getLayout().x) { + left_1 = node; + } + + if (x > right_1.getLayout().x) { + right_1 = node; + } + + if (node.depth > bottom_1.depth) { + bottom_1 = node; + } + }); + var delta = left_1 === right_1 ? 1 : separation$1(left_1, right_1) / 2; + var tx_1 = delta - left_1.getLayout().x; + var kx_1 = 0; + var ky_1 = 0; + var coorX_1 = 0; + var coorY_1 = 0; + + if (layout === 'radial') { + kx_1 = width / (right_1.getLayout().x + delta + tx_1); // here we use (node.depth - 1), bucause the real root's depth is 1 + + ky_1 = height / (bottom_1.depth - 1 || 1); + eachBefore(realRoot, function (node) { + coorX_1 = (node.getLayout().x + tx_1) * kx_1; + coorY_1 = (node.depth - 1) * ky_1; + var finalCoor = radialCoordinate(coorX_1, coorY_1); + node.setLayout({ + x: finalCoor.x, + y: finalCoor.y, + rawX: coorX_1, + rawY: coorY_1 + }, true); + }); + } else { + var orient_1 = seriesModel.getOrient(); + + if (orient_1 === 'RL' || orient_1 === 'LR') { + ky_1 = height / (right_1.getLayout().x + delta + tx_1); + kx_1 = width / (bottom_1.depth - 1 || 1); + eachBefore(realRoot, function (node) { + coorY_1 = (node.getLayout().x + tx_1) * ky_1; + coorX_1 = orient_1 === 'LR' ? (node.depth - 1) * kx_1 : width - (node.depth - 1) * kx_1; + node.setLayout({ + x: coorX_1, + y: coorY_1 + }, true); + }); + } else if (orient_1 === 'TB' || orient_1 === 'BT') { + kx_1 = width / (right_1.getLayout().x + delta + tx_1); + ky_1 = height / (bottom_1.depth - 1 || 1); + eachBefore(realRoot, function (node) { + coorX_1 = (node.getLayout().x + tx_1) * kx_1; + coorY_1 = orient_1 === 'TB' ? (node.depth - 1) * ky_1 : height - (node.depth - 1) * ky_1; + node.setLayout({ + x: coorX_1, + y: coorY_1 + }, true); + }); + } + } + } + } + + function treeVisual(ecModel) { + ecModel.eachSeriesByType('tree', function (seriesModel) { + var data = seriesModel.getData(); + var tree = data.tree; + tree.eachNode(function (node) { + var model = node.getModel(); // TODO Optimize + + var style = model.getModel('itemStyle').getItemStyle(); + var existsStyle = data.ensureUniqueItemVisual(node.dataIndex, 'style'); + extend(existsStyle, style); + }); + }); + } + + function installTreeAction(registers) { + registers.registerAction({ + type: 'treeExpandAndCollapse', + event: 'treeExpandAndCollapse', + update: 'update' + }, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', + subType: 'tree', + query: payload + }, function (seriesModel) { + var dataIndex = payload.dataIndex; + var tree = seriesModel.getData().tree; + var node = tree.getNodeByDataIndex(dataIndex); + node.isExpand = !node.isExpand; + }); + }); + registers.registerAction({ + type: 'treeRoam', + event: 'treeRoam', + // Here we set 'none' instead of 'update', because roam action + // just need to update the transform matrix without having to recalculate + // the layout. So don't need to go through the whole update process, such + // as 'dataPrcocess', 'coordSystemUpdate', 'layout' and so on. + update: 'none' + }, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', + subType: 'tree', + query: payload + }, function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var res = updateCenterAndZoom(coordSys, payload); + seriesModel.setCenter && seriesModel.setCenter(res.center); + seriesModel.setZoom && seriesModel.setZoom(res.zoom); + }); + }); + } + + function install$b(registers) { + registers.registerChartView(TreeView); + registers.registerSeriesModel(TreeSeriesModel); + registers.registerLayout(treeLayout); + registers.registerVisual(treeVisual); + installTreeAction(registers); + } + + var actionTypes = ['treemapZoomToNode', 'treemapRender', 'treemapMove']; + function installTreemapAction(registers) { + for (var i = 0; i < actionTypes.length; i++) { + registers.registerAction({ + type: actionTypes[i], + update: 'updateView' + }, noop); + } + + registers.registerAction({ + type: 'treemapRootToNode', + update: 'updateView' + }, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', + subType: 'treemap', + query: payload + }, handleRootToNode); + + function handleRootToNode(model, index) { + var types = ['treemapZoomToNode', 'treemapRootToNode']; + var targetInfo = retrieveTargetInfo(payload, types, model); + + if (targetInfo) { + var originViewRoot = model.getViewRoot(); + + if (originViewRoot) { + payload.direction = aboveViewRoot(originViewRoot, targetInfo.node) ? 'rollUp' : 'drillDown'; + } + + model.resetViewRoot(targetInfo.node); + } + } + }); + } + + function enableAriaDecalForTree(seriesModel) { + var data = seriesModel.getData(); + var tree = data.tree; + var decalPaletteScope = {}; + tree.eachNode(function (node) { + // Use decal of level 1 node + var current = node; + + while (current && current.depth > 1) { + current = current.parentNode; + } + + var decal = getDecalFromPalette(seriesModel.ecModel, current.name || current.dataIndex + '', decalPaletteScope); + node.setVisual('decal', decal); + }); + } + + var TreemapSeriesModel = + /** @class */ + function (_super) { + __extends(TreemapSeriesModel, _super); + + function TreemapSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TreemapSeriesModel.type; + _this.preventUsingHoverLayer = true; + return _this; + } + /** + * @override + */ + + + TreemapSeriesModel.prototype.getInitialData = function (option, ecModel) { + // Create a virtual root. + var root = { + name: option.name, + children: option.data + }; + completeTreeValue(root); + var levels = option.levels || []; // Used in "visual priority" in `treemapVisual.js`. + // This way is a little tricky, must satisfy the precondition: + // 1. There is no `treeNode.getModel('itemStyle.xxx')` used. + // 2. The `Model.prototype.getModel()` will not use any clone-like way. + + var designatedVisualItemStyle = this.designatedVisualItemStyle = {}; + var designatedVisualModel = new Model({ + itemStyle: designatedVisualItemStyle + }, this, ecModel); + levels = option.levels = setDefault(levels, ecModel); + var levelModels = map(levels || [], function (levelDefine) { + return new Model(levelDefine, designatedVisualModel, ecModel); + }, this); // Make sure always a new tree is created when setOption, + // in TreemapView, we check whether oldTree === newTree + // to choose mappings approach among old shapes and new shapes. + + var tree = Tree.createTree(root, this, beforeLink); + + function beforeLink(nodeData) { + nodeData.wrapMethod('getItemModel', function (model, idx) { + var node = tree.getNodeByDataIndex(idx); + var levelModel = node ? levelModels[node.depth] : null; // If no levelModel, we also need `designatedVisualModel`. + + model.parentModel = levelModel || designatedVisualModel; + return model; + }); + } + + return tree.data; + }; + + TreemapSeriesModel.prototype.optionUpdated = function () { + this.resetViewRoot(); + }; + /** + * @override + * @param {number} dataIndex + * @param {boolean} [mutipleSeries=false] + */ + + + TreemapSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var data = this.getData(); + var value = this.getRawValue(dataIndex); + var name = data.getName(dataIndex); + return createTooltipMarkup('nameValue', { + name: name, + value: value + }); + }; + /** + * Add tree path to tooltip param + * + * @override + * @param {number} dataIndex + * @return {Object} + */ + + + TreemapSeriesModel.prototype.getDataParams = function (dataIndex) { + var params = _super.prototype.getDataParams.apply(this, arguments); + + var node = this.getData().tree.getNodeByDataIndex(dataIndex); + params.treeAncestors = wrapTreePathInfo(node, this); // compatitable the previous code. + + params.treePathInfo = params.treeAncestors; + return params; + }; + /** + * @public + * @param {Object} layoutInfo { + * x: containerGroup x + * y: containerGroup y + * width: containerGroup width + * height: containerGroup height + * } + */ + + + TreemapSeriesModel.prototype.setLayoutInfo = function (layoutInfo) { + /** + * @readOnly + * @type {Object} + */ + this.layoutInfo = this.layoutInfo || {}; + extend(this.layoutInfo, layoutInfo); + }; + /** + * @param {string} id + * @return {number} index + */ + + + TreemapSeriesModel.prototype.mapIdToIndex = function (id) { + // A feature is implemented: + // index is monotone increasing with the sequence of + // input id at the first time. + // This feature can make sure that each data item and its + // mapped color have the same index between data list and + // color list at the beginning, which is useful for user + // to adjust data-color mapping. + + /** + * @private + * @type {Object} + */ + var idIndexMap = this._idIndexMap; + + if (!idIndexMap) { + idIndexMap = this._idIndexMap = createHashMap(); + /** + * @private + * @type {number} + */ + + this._idIndexMapCount = 0; + } + + var index = idIndexMap.get(id); + + if (index == null) { + idIndexMap.set(id, index = this._idIndexMapCount++); + } + + return index; + }; + + TreemapSeriesModel.prototype.getViewRoot = function () { + return this._viewRoot; + }; + + TreemapSeriesModel.prototype.resetViewRoot = function (viewRoot) { + viewRoot ? this._viewRoot = viewRoot : viewRoot = this._viewRoot; + var root = this.getRawData().tree.root; + + if (!viewRoot || viewRoot !== root && !root.contains(viewRoot)) { + this._viewRoot = root; + } + }; + + TreemapSeriesModel.prototype.enableAriaDecal = function () { + enableAriaDecalForTree(this); + }; + + TreemapSeriesModel.type = 'series.treemap'; + TreemapSeriesModel.layoutMode = 'box'; + TreemapSeriesModel.defaultOption = { + // Disable progressive rendering + progressive: 0, + // size: ['80%', '80%'], // deprecated, compatible with ec2. + left: 'center', + top: 'middle', + width: '80%', + height: '80%', + sort: true, + clipWindow: 'origin', + squareRatio: 0.5 * (1 + Math.sqrt(5)), + leafDepth: null, + drillDownIcon: '▶', + // to align specialized icon. ▷▶❒❐▼✚ + zoomToNodeRatio: 0.32 * 0.32, + roam: true, + nodeClick: 'zoomToNode', + animation: true, + animationDurationUpdate: 900, + animationEasing: 'quinticInOut', + breadcrumb: { + show: true, + height: 22, + left: 'center', + top: 'bottom', + // right + // bottom + emptyItemWidth: 25, + itemStyle: { + color: 'rgba(0,0,0,0.7)', + textStyle: { + color: '#fff' + } + } + }, + label: { + show: true, + // Do not use textDistance, for ellipsis rect just the same as treemap node rect. + distance: 0, + padding: 5, + position: 'inside', + // formatter: null, + color: '#fff', + overflow: 'truncate' // align + // verticalAlign + + }, + upperLabel: { + show: false, + position: [0, '50%'], + height: 20, + // formatter: null, + // color: '#fff', + overflow: 'truncate', + // align: null, + verticalAlign: 'middle' + }, + itemStyle: { + color: null, + colorAlpha: null, + colorSaturation: null, + borderWidth: 0, + gapWidth: 0, + borderColor: '#fff', + borderColorSaturation: null // If specified, borderColor will be ineffective, and the + // border color is evaluated by color of current node and + // borderColorSaturation. + + }, + emphasis: { + upperLabel: { + show: true, + position: [0, '50%'], + overflow: 'truncate', + verticalAlign: 'middle' + } + }, + visualDimension: 0, + visualMin: null, + visualMax: null, + color: [], + // level[n].color (if necessary). + // + Specify color list of each level. level[0].color would be global + // color list if not specified. (see method `setDefault`). + // + But set as a empty array to forbid fetch color from global palette + // when using nodeModel.get('color'), otherwise nodes on deep level + // will always has color palette set and are not able to inherit color + // from parent node. + // + TreemapSeries.color can not be set as 'none', otherwise effect + // legend color fetching (see seriesColor.js). + colorAlpha: null, + colorSaturation: null, + colorMappingBy: 'index', + visibleMin: 10, + // be rendered. Only works when sort is 'asc' or 'desc'. + childrenVisibleMin: null, + // grandchildren will not show. + // Why grandchildren? If not grandchildren but children, + // some siblings show children and some not, + // the appearance may be mess and not consistent, + levels: [] // Each item: { + // visibleMin, itemStyle, visualDimension, label + // } + // data: { + // value: [], + // children: [], + // link: 'http://xxx.xxx.xxx', + // target: 'blank' or 'self' + // } + + }; + return TreemapSeriesModel; + }(SeriesModel); + /** + * @param {Object} dataNode + */ + + + function completeTreeValue(dataNode) { + // Postorder travel tree. + // If value of none-leaf node is not set, + // calculate it by suming up the value of all children. + var sum = 0; + each(dataNode.children, function (child) { + completeTreeValue(child); + var childValue = child.value; + isArray(childValue) && (childValue = childValue[0]); + sum += childValue; + }); + var thisValue = dataNode.value; + + if (isArray(thisValue)) { + thisValue = thisValue[0]; + } + + if (thisValue == null || isNaN(thisValue)) { + thisValue = sum; + } // Value should not less than 0. + + + if (thisValue < 0) { + thisValue = 0; + } + + isArray(dataNode.value) ? dataNode.value[0] = thisValue : dataNode.value = thisValue; + } + /** + * set default to level configuration + */ + + + function setDefault(levels, ecModel) { + var globalColorList = normalizeToArray(ecModel.get('color')); + var globalDecalList = normalizeToArray(ecModel.get(['aria', 'decal', 'decals'])); + + if (!globalColorList) { + return; + } + + levels = levels || []; + var hasColorDefine; + var hasDecalDefine; + each(levels, function (levelDefine) { + var model = new Model(levelDefine); + var modelColor = model.get('color'); + var modelDecal = model.get('decal'); + + if (model.get(['itemStyle', 'color']) || modelColor && modelColor !== 'none') { + hasColorDefine = true; + } + + if (model.get(['itemStyle', 'decal']) || modelDecal && modelDecal !== 'none') { + hasDecalDefine = true; + } + }); + var level0 = levels[0] || (levels[0] = {}); + + if (!hasColorDefine) { + level0.color = globalColorList.slice(); + } + + if (!hasDecalDefine && globalDecalList) { + level0.decal = globalDecalList.slice(); + } + + return levels; + } + + var TEXT_PADDING = 8; + var ITEM_GAP = 8; + var ARRAY_LENGTH = 5; + + var Breadcrumb = + /** @class */ + function () { + function Breadcrumb(containerGroup) { + this.group = new Group(); + containerGroup.add(this.group); + } + + Breadcrumb.prototype.render = function (seriesModel, api, targetNode, onSelect) { + var model = seriesModel.getModel('breadcrumb'); + var thisGroup = this.group; + thisGroup.removeAll(); + + if (!model.get('show') || !targetNode) { + return; + } + + var normalStyleModel = model.getModel('itemStyle'); // let emphasisStyleModel = model.getModel('emphasis.itemStyle'); + + var textStyleModel = normalStyleModel.getModel('textStyle'); + var layoutParam = { + pos: { + left: model.get('left'), + right: model.get('right'), + top: model.get('top'), + bottom: model.get('bottom') + }, + box: { + width: api.getWidth(), + height: api.getHeight() + }, + emptyItemWidth: model.get('emptyItemWidth'), + totalWidth: 0, + renderList: [] + }; + + this._prepare(targetNode, layoutParam, textStyleModel); + + this._renderContent(seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect); + + positionElement(thisGroup, layoutParam.pos, layoutParam.box); + }; + /** + * Prepare render list and total width + * @private + */ + + + Breadcrumb.prototype._prepare = function (targetNode, layoutParam, textStyleModel) { + for (var node = targetNode; node; node = node.parentNode) { + var text = convertOptionIdName(node.getModel().get('name'), ''); + var textRect = textStyleModel.getTextRect(text); + var itemWidth = Math.max(textRect.width + TEXT_PADDING * 2, layoutParam.emptyItemWidth); + layoutParam.totalWidth += itemWidth + ITEM_GAP; + layoutParam.renderList.push({ + node: node, + text: text, + width: itemWidth + }); + } + }; + /** + * @private + */ + + + Breadcrumb.prototype._renderContent = function (seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect) { + // Start rendering. + var lastX = 0; + var emptyItemWidth = layoutParam.emptyItemWidth; + var height = seriesModel.get(['breadcrumb', 'height']); + var availableSize = getAvailableSize(layoutParam.pos, layoutParam.box); + var totalWidth = layoutParam.totalWidth; + var renderList = layoutParam.renderList; + + for (var i = renderList.length - 1; i >= 0; i--) { + var item = renderList[i]; + var itemNode = item.node; + var itemWidth = item.width; + var text = item.text; // Hdie text and shorten width if necessary. + + if (totalWidth > availableSize.width) { + totalWidth -= itemWidth - emptyItemWidth; + itemWidth = emptyItemWidth; + text = null; + } + + var el = new Polygon({ + shape: { + points: makeItemPoints(lastX, 0, itemWidth, height, i === renderList.length - 1, i === 0) + }, + style: defaults(normalStyleModel.getItemStyle(), { + lineJoin: 'bevel' + }), + textContent: new ZRText({ + style: { + text: text, + fill: textStyleModel.getTextColor(), + font: textStyleModel.getFont() + } + }), + textConfig: { + position: 'inside' + }, + z2: Z2_EMPHASIS_LIFT * 1e4, + onclick: curry(onSelect, itemNode) + }); + el.disableLabelAnimation = true; + this.group.add(el); + packEventData(el, seriesModel, itemNode); + lastX += itemWidth + ITEM_GAP; + } + }; + + Breadcrumb.prototype.remove = function () { + this.group.removeAll(); + }; + + return Breadcrumb; + }(); + + function makeItemPoints(x, y, itemWidth, itemHeight, head, tail) { + var points = [[head ? x : x - ARRAY_LENGTH, y], [x + itemWidth, y], [x + itemWidth, y + itemHeight], [head ? x : x - ARRAY_LENGTH, y + itemHeight]]; + !tail && points.splice(2, 0, [x + itemWidth + ARRAY_LENGTH, y + itemHeight / 2]); + !head && points.push([x, y + itemHeight / 2]); + return points; + } // Package custom mouse event. + + + function packEventData(el, seriesModel, itemNode) { + getECData(el).eventData = { + componentType: 'series', + componentSubType: 'treemap', + componentIndex: seriesModel.componentIndex, + seriesIndex: seriesModel.seriesIndex, + seriesName: seriesModel.name, + seriesType: 'treemap', + selfType: 'breadcrumb', + nodeData: { + dataIndex: itemNode && itemNode.dataIndex, + name: itemNode && itemNode.name + }, + treePathInfo: itemNode && wrapTreePathInfo(itemNode, seriesModel) + }; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + /** + * Animate multiple elements with a single done-callback. + * + * @example + * animation + * .createWrap() + * .add(el1, {x: 10, y: 10}) + * .add(el2, {shape: {width: 500}, style: {fill: 'red'}}, 400) + * .done(function () { // done }) + * .start('cubicOut'); + */ + var AnimationWrap = + /** @class */ + function () { + function AnimationWrap() { + this._storage = []; + this._elExistsMap = {}; + } + /** + * Caution: a el can only be added once, otherwise 'done' + * might not be called. This method checks this (by el.id), + * suppresses adding and returns false when existing el found. + * + * @return Whether adding succeeded. + */ + + + AnimationWrap.prototype.add = function (el, target, duration, delay, easing) { + if (this._elExistsMap[el.id]) { + return false; + } + + this._elExistsMap[el.id] = true; + + this._storage.push({ + el: el, + target: target, + duration: duration, + delay: delay, + easing: easing + }); + + return true; + }; + /** + * Only execute when animation done/aborted. + */ + + + AnimationWrap.prototype.finished = function (callback) { + this._finishedCallback = callback; + return this; + }; + /** + * Will stop exist animation firstly. + */ + + + AnimationWrap.prototype.start = function () { + var _this = this; + + var count = this._storage.length; + + var checkTerminate = function () { + count--; + + if (count <= 0) { + // Guard. + _this._storage.length = 0; + _this._elExistsMap = {}; + _this._finishedCallback && _this._finishedCallback(); + } + }; + + for (var i = 0, len = this._storage.length; i < len; i++) { + var item = this._storage[i]; + item.el.animateTo(item.target, { + duration: item.duration, + delay: item.delay, + easing: item.easing, + setToFinal: true, + done: checkTerminate, + aborted: checkTerminate + }); + } + + return this; + }; + + return AnimationWrap; + }(); + + function createWrap() { + return new AnimationWrap(); + } + + var Group$1 = Group; + var Rect$1 = Rect; + var DRAG_THRESHOLD = 3; + var PATH_LABEL_NOAMAL = 'label'; + var PATH_UPPERLABEL_NORMAL = 'upperLabel'; // Should larger than emphasis states lift z + + var Z2_BASE = Z2_EMPHASIS_LIFT * 10; // Should bigger than every z2. + + var Z2_BG = Z2_EMPHASIS_LIFT * 2; + var Z2_CONTENT = Z2_EMPHASIS_LIFT * 3; + var getStateItemStyle = makeStyleMapper([['fill', 'color'], // `borderColor` and `borderWidth` has been occupied, + // so use `stroke` to indicate the stroke of the rect. + ['stroke', 'strokeColor'], ['lineWidth', 'strokeWidth'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor'] // Option decal is in `DecalObject` but style.decal is in `PatternObject`. + // So do not transfer decal directly. + ]); + + var getItemStyleNormal = function (model) { + // Normal style props should include emphasis style props. + var itemStyle = getStateItemStyle(model); // Clear styles set by emphasis. + + itemStyle.stroke = itemStyle.fill = itemStyle.lineWidth = null; + return itemStyle; + }; + + var inner$8 = makeInner(); + + var TreemapView = + /** @class */ + function (_super) { + __extends(TreemapView, _super); + + function TreemapView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TreemapView.type; + _this._state = 'ready'; + _this._storage = createStorage(); + return _this; + } + /** + * @override + */ + + + TreemapView.prototype.render = function (seriesModel, ecModel, api, payload) { + var models = ecModel.findComponents({ + mainType: 'series', + subType: 'treemap', + query: payload + }); + + if (indexOf(models, seriesModel) < 0) { + return; + } + + this.seriesModel = seriesModel; + this.api = api; + this.ecModel = ecModel; + var types = ['treemapZoomToNode', 'treemapRootToNode']; + var targetInfo = retrieveTargetInfo(payload, types, seriesModel); + var payloadType = payload && payload.type; + var layoutInfo = seriesModel.layoutInfo; + var isInit = !this._oldTree; + var thisStorage = this._storage; // Mark new root when action is treemapRootToNode. + + var reRoot = payloadType === 'treemapRootToNode' && targetInfo && thisStorage ? { + rootNodeGroup: thisStorage.nodeGroup[targetInfo.node.getRawIndex()], + direction: payload.direction + } : null; + + var containerGroup = this._giveContainerGroup(layoutInfo); + + var hasAnimation = seriesModel.get('animation'); + + var renderResult = this._doRender(containerGroup, seriesModel, reRoot); + + hasAnimation && !isInit && (!payloadType || payloadType === 'treemapZoomToNode' || payloadType === 'treemapRootToNode') ? this._doAnimation(containerGroup, renderResult, seriesModel, reRoot) : renderResult.renderFinally(); + + this._resetController(api); + + this._renderBreadcrumb(seriesModel, api, targetInfo); + }; + + TreemapView.prototype._giveContainerGroup = function (layoutInfo) { + var containerGroup = this._containerGroup; + + if (!containerGroup) { + // FIXME + // 加一层containerGroup是为了clip,但是现在clip功能并没有实现。 + containerGroup = this._containerGroup = new Group$1(); + + this._initEvents(containerGroup); + + this.group.add(containerGroup); + } + + containerGroup.x = layoutInfo.x; + containerGroup.y = layoutInfo.y; + return containerGroup; + }; + + TreemapView.prototype._doRender = function (containerGroup, seriesModel, reRoot) { + var thisTree = seriesModel.getData().tree; + var oldTree = this._oldTree; // Clear last shape records. + + var lastsForAnimation = createStorage(); + var thisStorage = createStorage(); + var oldStorage = this._storage; + var willInvisibleEls = []; + + function doRenderNode(thisNode, oldNode, parentGroup, depth) { + return renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimation, willInvisibleEls, thisNode, oldNode, parentGroup, depth); + } // Notice: when thisTree and oldTree are the same tree (see list.cloneShallow), + // the oldTree is actually losted, so we can not find all of the old graphic + // elements from tree. So we use this stragegy: make element storage, move + // from old storage to new storage, clear old storage. + + + dualTravel(thisTree.root ? [thisTree.root] : [], oldTree && oldTree.root ? [oldTree.root] : [], containerGroup, thisTree === oldTree || !oldTree, 0); // Process all removing. + + var willDeleteEls = clearStorage(oldStorage); + this._oldTree = thisTree; + this._storage = thisStorage; + return { + lastsForAnimation: lastsForAnimation, + willDeleteEls: willDeleteEls, + renderFinally: renderFinally + }; + + function dualTravel(thisViewChildren, oldViewChildren, parentGroup, sameTree, depth) { + // When 'render' is triggered by action, + // 'this' and 'old' may be the same tree, + // we use rawIndex in that case. + if (sameTree) { + oldViewChildren = thisViewChildren; + each(thisViewChildren, function (child, index) { + !child.isRemoved() && processNode(index, index); + }); + } // Diff hierarchically (diff only in each subtree, but not whole). + // because, consistency of view is important. + else { + new DataDiffer(oldViewChildren, thisViewChildren, getKey, getKey).add(processNode).update(processNode).remove(curry(processNode, null)).execute(); + } + + function getKey(node) { + // Identify by name or raw index. + return node.getId(); + } + + function processNode(newIndex, oldIndex) { + var thisNode = newIndex != null ? thisViewChildren[newIndex] : null; + var oldNode = oldIndex != null ? oldViewChildren[oldIndex] : null; + var group = doRenderNode(thisNode, oldNode, parentGroup, depth); + group && dualTravel(thisNode && thisNode.viewChildren || [], oldNode && oldNode.viewChildren || [], group, sameTree, depth + 1); + } + } + + function clearStorage(storage) { + var willDeleteEls = createStorage(); + storage && each(storage, function (store, storageName) { + var delEls = willDeleteEls[storageName]; + each(store, function (el) { + el && (delEls.push(el), inner$8(el).willDelete = true); + }); + }); + return willDeleteEls; + } + + function renderFinally() { + each(willDeleteEls, function (els) { + each(els, function (el) { + el.parent && el.parent.remove(el); + }); + }); + each(willInvisibleEls, function (el) { + el.invisible = true; // Setting invisible is for optimizing, so no need to set dirty, + // just mark as invisible. + + el.dirty(); + }); + } + }; + + TreemapView.prototype._doAnimation = function (containerGroup, renderResult, seriesModel, reRoot) { + var durationOption = seriesModel.get('animationDurationUpdate'); + var easingOption = seriesModel.get('animationEasing'); // TODO: do not support function until necessary. + + var duration = (isFunction(durationOption) ? 0 : durationOption) || 0; + var easing = (isFunction(easingOption) ? null : easingOption) || 'cubicOut'; + var animationWrap = createWrap(); // Make delete animations. + + each(renderResult.willDeleteEls, function (store, storageName) { + each(store, function (el, rawIndex) { + if (el.invisible) { + return; + } + + var parent = el.parent; // Always has parent, and parent is nodeGroup. + + var target; + var innerStore = inner$8(parent); + + if (reRoot && reRoot.direction === 'drillDown') { + target = parent === reRoot.rootNodeGroup // This is the content element of view root. + // Only `content` will enter this branch, because + // `background` and `nodeGroup` will not be deleted. + ? { + shape: { + x: 0, + y: 0, + width: innerStore.nodeWidth, + height: innerStore.nodeHeight + }, + style: { + opacity: 0 + } + } // Others. + : { + style: { + opacity: 0 + } + }; + } else { + var targetX = 0; + var targetY = 0; + + if (!innerStore.willDelete) { + // Let node animate to right-bottom corner, cooperating with fadeout, + // which is appropriate for user understanding. + // Divided by 2 for reRoot rolling up effect. + targetX = innerStore.nodeWidth / 2; + targetY = innerStore.nodeHeight / 2; + } + + target = storageName === 'nodeGroup' ? { + x: targetX, + y: targetY, + style: { + opacity: 0 + } + } : { + shape: { + x: targetX, + y: targetY, + width: 0, + height: 0 + }, + style: { + opacity: 0 + } + }; + } // TODO: do not support delay until necessary. + + + target && animationWrap.add(el, target, duration, 0, easing); + }); + }); // Make other animations + + each(this._storage, function (store, storageName) { + each(store, function (el, rawIndex) { + var last = renderResult.lastsForAnimation[storageName][rawIndex]; + var target = {}; + + if (!last) { + return; + } + + if (el instanceof Group) { + if (last.oldX != null) { + target.x = el.x; + target.y = el.y; + el.x = last.oldX; + el.y = last.oldY; + } + } else { + if (last.oldShape) { + target.shape = extend({}, el.shape); + el.setShape(last.oldShape); + } + + if (last.fadein) { + el.setStyle('opacity', 0); + target.style = { + opacity: 1 + }; + } // When animation is stopped for succedent animation starting, + // el.style.opacity might not be 1 + else if (el.style.opacity !== 1) { + target.style = { + opacity: 1 + }; + } + } + + animationWrap.add(el, target, duration, 0, easing); + }); + }, this); + this._state = 'animating'; + animationWrap.finished(bind(function () { + this._state = 'ready'; + renderResult.renderFinally(); + }, this)).start(); + }; + + TreemapView.prototype._resetController = function (api) { + var controller = this._controller; // Init controller. + + if (!controller) { + controller = this._controller = new RoamController(api.getZr()); + controller.enable(this.seriesModel.get('roam')); + controller.on('pan', bind(this._onPan, this)); + controller.on('zoom', bind(this._onZoom, this)); + } + + var rect = new BoundingRect(0, 0, api.getWidth(), api.getHeight()); + controller.setPointerChecker(function (e, x, y) { + return rect.contain(x, y); + }); + }; + + TreemapView.prototype._clearController = function () { + var controller = this._controller; + + if (controller) { + controller.dispose(); + controller = null; + } + }; + + TreemapView.prototype._onPan = function (e) { + if (this._state !== 'animating' && (Math.abs(e.dx) > DRAG_THRESHOLD || Math.abs(e.dy) > DRAG_THRESHOLD)) { + // These param must not be cached. + var root = this.seriesModel.getData().tree.root; + + if (!root) { + return; + } + + var rootLayout = root.getLayout(); + + if (!rootLayout) { + return; + } + + this.api.dispatchAction({ + type: 'treemapMove', + from: this.uid, + seriesId: this.seriesModel.id, + rootRect: { + x: rootLayout.x + e.dx, + y: rootLayout.y + e.dy, + width: rootLayout.width, + height: rootLayout.height + } + }); + } + }; + + TreemapView.prototype._onZoom = function (e) { + var mouseX = e.originX; + var mouseY = e.originY; + + if (this._state !== 'animating') { + // These param must not be cached. + var root = this.seriesModel.getData().tree.root; + + if (!root) { + return; + } + + var rootLayout = root.getLayout(); + + if (!rootLayout) { + return; + } + + var rect = new BoundingRect(rootLayout.x, rootLayout.y, rootLayout.width, rootLayout.height); + var layoutInfo = this.seriesModel.layoutInfo; // Transform mouse coord from global to containerGroup. + + mouseX -= layoutInfo.x; + mouseY -= layoutInfo.y; // Scale root bounding rect. + + var m = create$1(); + translate(m, m, [-mouseX, -mouseY]); + scale$1(m, m, [e.scale, e.scale]); + translate(m, m, [mouseX, mouseY]); + rect.applyTransform(m); + this.api.dispatchAction({ + type: 'treemapRender', + from: this.uid, + seriesId: this.seriesModel.id, + rootRect: { + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + } + }); + } + }; + + TreemapView.prototype._initEvents = function (containerGroup) { + var _this = this; + + containerGroup.on('click', function (e) { + if (_this._state !== 'ready') { + return; + } + + var nodeClick = _this.seriesModel.get('nodeClick', true); + + if (!nodeClick) { + return; + } + + var targetInfo = _this.findTarget(e.offsetX, e.offsetY); + + if (!targetInfo) { + return; + } + + var node = targetInfo.node; + + if (node.getLayout().isLeafRoot) { + _this._rootToNode(targetInfo); + } else { + if (nodeClick === 'zoomToNode') { + _this._zoomToNode(targetInfo); + } else if (nodeClick === 'link') { + var itemModel = node.hostTree.data.getItemModel(node.dataIndex); + var link = itemModel.get('link', true); + var linkTarget = itemModel.get('target', true) || 'blank'; + link && windowOpen(link, linkTarget); + } + } + }, this); + }; + + TreemapView.prototype._renderBreadcrumb = function (seriesModel, api, targetInfo) { + var _this = this; + + if (!targetInfo) { + targetInfo = seriesModel.get('leafDepth', true) != null ? { + node: seriesModel.getViewRoot() + } // FIXME + // better way? + // Find breadcrumb tail on center of containerGroup. + : this.findTarget(api.getWidth() / 2, api.getHeight() / 2); + + if (!targetInfo) { + targetInfo = { + node: seriesModel.getData().tree.root + }; + } + } + + (this._breadcrumb || (this._breadcrumb = new Breadcrumb(this.group))).render(seriesModel, api, targetInfo.node, function (node) { + if (_this._state !== 'animating') { + aboveViewRoot(seriesModel.getViewRoot(), node) ? _this._rootToNode({ + node: node + }) : _this._zoomToNode({ + node: node + }); + } + }); + }; + /** + * @override + */ + + + TreemapView.prototype.remove = function () { + this._clearController(); + + this._containerGroup && this._containerGroup.removeAll(); + this._storage = createStorage(); + this._state = 'ready'; + this._breadcrumb && this._breadcrumb.remove(); + }; + + TreemapView.prototype.dispose = function () { + this._clearController(); + }; + + TreemapView.prototype._zoomToNode = function (targetInfo) { + this.api.dispatchAction({ + type: 'treemapZoomToNode', + from: this.uid, + seriesId: this.seriesModel.id, + targetNode: targetInfo.node + }); + }; + + TreemapView.prototype._rootToNode = function (targetInfo) { + this.api.dispatchAction({ + type: 'treemapRootToNode', + from: this.uid, + seriesId: this.seriesModel.id, + targetNode: targetInfo.node + }); + }; + /** + * @public + * @param {number} x Global coord x. + * @param {number} y Global coord y. + * @return {Object} info If not found, return undefined; + * @return {number} info.node Target node. + * @return {number} info.offsetX x refer to target node. + * @return {number} info.offsetY y refer to target node. + */ + + + TreemapView.prototype.findTarget = function (x, y) { + var targetInfo; + var viewRoot = this.seriesModel.getViewRoot(); + viewRoot.eachNode({ + attr: 'viewChildren', + order: 'preorder' + }, function (node) { + var bgEl = this._storage.background[node.getRawIndex()]; // If invisible, there might be no element. + + + if (bgEl) { + var point = bgEl.transformCoordToLocal(x, y); + var shape = bgEl.shape; // For performance consideration, dont use 'getBoundingRect'. + + if (shape.x <= point[0] && point[0] <= shape.x + shape.width && shape.y <= point[1] && point[1] <= shape.y + shape.height) { + targetInfo = { + node: node, + offsetX: point[0], + offsetY: point[1] + }; + } else { + return false; // Suppress visit subtree. + } + } + }, this); + return targetInfo; + }; + + TreemapView.type = 'treemap'; + return TreemapView; + }(ChartView); + /** + * @inner + */ + + + function createStorage() { + return { + nodeGroup: [], + background: [], + content: [] + }; + } + /** + * @inner + * @return Return undefined means do not travel further. + */ + + + function renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimation, willInvisibleEls, thisNode, oldNode, parentGroup, depth) { + // Whether under viewRoot. + if (!thisNode) { + // Deleting nodes will be performed finally. This method just find + // element from old storage, or create new element, set them to new + // storage, and set styles. + return; + } // ------------------------------------------------------------------- + // Start of closure variables available in "Procedures in renderNode". + + + var thisLayout = thisNode.getLayout(); + var data = seriesModel.getData(); + var nodeModel = thisNode.getModel(); // Only for enabling highlight/downplay. Clear firstly. + // Because some node will not be rendered. + + data.setItemGraphicEl(thisNode.dataIndex, null); + + if (!thisLayout || !thisLayout.isInView) { + return; + } + + var thisWidth = thisLayout.width; + var thisHeight = thisLayout.height; + var borderWidth = thisLayout.borderWidth; + var thisInvisible = thisLayout.invisible; + var thisRawIndex = thisNode.getRawIndex(); + var oldRawIndex = oldNode && oldNode.getRawIndex(); + var thisViewChildren = thisNode.viewChildren; + var upperHeight = thisLayout.upperHeight; + var isParent = thisViewChildren && thisViewChildren.length; + var itemStyleNormalModel = nodeModel.getModel('itemStyle'); + var itemStyleEmphasisModel = nodeModel.getModel(['emphasis', 'itemStyle']); + var itemStyleBlurModel = nodeModel.getModel(['blur', 'itemStyle']); + var itemStyleSelectModel = nodeModel.getModel(['select', 'itemStyle']); + var borderRadius = itemStyleNormalModel.get('borderRadius') || 0; // End of closure ariables available in "Procedures in renderNode". + // ----------------------------------------------------------------- + // Node group + + var group = giveGraphic('nodeGroup', Group$1); + + if (!group) { + return; + } + + parentGroup.add(group); // x,y are not set when el is above view root. + + group.x = thisLayout.x || 0; + group.y = thisLayout.y || 0; + group.markRedraw(); + inner$8(group).nodeWidth = thisWidth; + inner$8(group).nodeHeight = thisHeight; + + if (thisLayout.isAboveViewRoot) { + return group; + } // Background + + + var bg = giveGraphic('background', Rect$1, depth, Z2_BG); + bg && renderBackground(group, bg, isParent && thisLayout.upperLabelHeight); + var emphasisModel = nodeModel.getModel('emphasis'); + var focus = emphasisModel.get('focus'); + var blurScope = emphasisModel.get('blurScope'); + var isDisabled = emphasisModel.get('disabled'); + var focusOrIndices = focus === 'ancestor' ? thisNode.getAncestorsIndices() : focus === 'descendant' ? thisNode.getDescendantIndices() : focus; // No children, render content. + + if (isParent) { + // Because of the implementation about "traverse" in graphic hover style, we + // can not set hover listener on the "group" of non-leaf node. Otherwise the + // hover event from the descendents will be listenered. + if (isHighDownDispatcher(group)) { + setAsHighDownDispatcher(group, false); + } + + if (bg) { + setAsHighDownDispatcher(bg, !isDisabled); // Only for enabling highlight/downplay. + + data.setItemGraphicEl(thisNode.dataIndex, bg); + enableHoverFocus(bg, focusOrIndices, blurScope); + } + } else { + var content = giveGraphic('content', Rect$1, depth, Z2_CONTENT); + content && renderContent(group, content); + bg.disableMorphing = true; + + if (bg && isHighDownDispatcher(bg)) { + setAsHighDownDispatcher(bg, false); + } + + setAsHighDownDispatcher(group, !isDisabled); // Only for enabling highlight/downplay. + + data.setItemGraphicEl(thisNode.dataIndex, group); + enableHoverFocus(group, focusOrIndices, blurScope); + } + + return group; // ---------------------------- + // | Procedures in renderNode | + // ---------------------------- + + function renderBackground(group, bg, useUpperLabel) { + var ecData = getECData(bg); // For tooltip. + + ecData.dataIndex = thisNode.dataIndex; + ecData.seriesIndex = seriesModel.seriesIndex; + bg.setShape({ + x: 0, + y: 0, + width: thisWidth, + height: thisHeight, + r: borderRadius + }); + + if (thisInvisible) { + // If invisible, do not set visual, otherwise the element will + // change immediately before animation. We think it is OK to + // remain its origin color when moving out of the view window. + processInvisible(bg); + } else { + bg.invisible = false; + var style = thisNode.getVisual('style'); + var visualBorderColor = style.stroke; + var normalStyle = getItemStyleNormal(itemStyleNormalModel); + normalStyle.fill = visualBorderColor; + var emphasisStyle = getStateItemStyle(itemStyleEmphasisModel); + emphasisStyle.fill = itemStyleEmphasisModel.get('borderColor'); + var blurStyle = getStateItemStyle(itemStyleBlurModel); + blurStyle.fill = itemStyleBlurModel.get('borderColor'); + var selectStyle = getStateItemStyle(itemStyleSelectModel); + selectStyle.fill = itemStyleSelectModel.get('borderColor'); + + if (useUpperLabel) { + var upperLabelWidth = thisWidth - 2 * borderWidth; + prepareText( // PENDING: convert ZRColor to ColorString for text. + bg, visualBorderColor, style.opacity, { + x: borderWidth, + y: 0, + width: upperLabelWidth, + height: upperHeight + }); + } // For old bg. + else { + bg.removeTextContent(); + } + + bg.setStyle(normalStyle); + bg.ensureState('emphasis').style = emphasisStyle; + bg.ensureState('blur').style = blurStyle; + bg.ensureState('select').style = selectStyle; + setDefaultStateProxy(bg); + } + + group.add(bg); + } + + function renderContent(group, content) { + var ecData = getECData(content); // For tooltip. + + ecData.dataIndex = thisNode.dataIndex; + ecData.seriesIndex = seriesModel.seriesIndex; + var contentWidth = Math.max(thisWidth - 2 * borderWidth, 0); + var contentHeight = Math.max(thisHeight - 2 * borderWidth, 0); + content.culling = true; + content.setShape({ + x: borderWidth, + y: borderWidth, + width: contentWidth, + height: contentHeight, + r: borderRadius + }); + + if (thisInvisible) { + // If invisible, do not set visual, otherwise the element will + // change immediately before animation. We think it is OK to + // remain its origin color when moving out of the view window. + processInvisible(content); + } else { + content.invisible = false; + var nodeStyle = thisNode.getVisual('style'); + var visualColor = nodeStyle.fill; + var normalStyle = getItemStyleNormal(itemStyleNormalModel); + normalStyle.fill = visualColor; + normalStyle.decal = nodeStyle.decal; + var emphasisStyle = getStateItemStyle(itemStyleEmphasisModel); + var blurStyle = getStateItemStyle(itemStyleBlurModel); + var selectStyle = getStateItemStyle(itemStyleSelectModel); // PENDING: convert ZRColor to ColorString for text. + + prepareText(content, visualColor, nodeStyle.opacity, null); + content.setStyle(normalStyle); + content.ensureState('emphasis').style = emphasisStyle; + content.ensureState('blur').style = blurStyle; + content.ensureState('select').style = selectStyle; + setDefaultStateProxy(content); + } + + group.add(content); + } + + function processInvisible(element) { + // Delay invisible setting utill animation finished, + // avoid element vanish suddenly before animation. + !element.invisible && willInvisibleEls.push(element); + } + + function prepareText(rectEl, visualColor, visualOpacity, // Can be null/undefined + upperLabelRect) { + var normalLabelModel = nodeModel.getModel(upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL); + var defaultText = convertOptionIdName(nodeModel.get('name'), null); + var isShow = normalLabelModel.getShallow('show'); + setLabelStyle(rectEl, getLabelStatesModels(nodeModel, upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL), { + defaultText: isShow ? defaultText : null, + inheritColor: visualColor, + defaultOpacity: visualOpacity, + labelFetcher: seriesModel, + labelDataIndex: thisNode.dataIndex + }); + var textEl = rectEl.getTextContent(); + + if (!textEl) { + return; + } + + var textStyle = textEl.style; + var textPadding = normalizeCssArray(textStyle.padding || 0); + + if (upperLabelRect) { + rectEl.setTextConfig({ + layoutRect: upperLabelRect + }); + textEl.disableLabelLayout = true; + } + + textEl.beforeUpdate = function () { + var width = Math.max((upperLabelRect ? upperLabelRect.width : rectEl.shape.width) - textPadding[1] - textPadding[3], 0); + var height = Math.max((upperLabelRect ? upperLabelRect.height : rectEl.shape.height) - textPadding[0] - textPadding[2], 0); + + if (textStyle.width !== width || textStyle.height !== height) { + textEl.setStyle({ + width: width, + height: height + }); + } + }; + + textStyle.truncateMinChar = 2; + textStyle.lineOverflow = 'truncate'; + addDrillDownIcon(textStyle, upperLabelRect, thisLayout); + var textEmphasisState = textEl.getState('emphasis'); + addDrillDownIcon(textEmphasisState ? textEmphasisState.style : null, upperLabelRect, thisLayout); + } + + function addDrillDownIcon(style, upperLabelRect, thisLayout) { + var text = style ? style.text : null; + + if (!upperLabelRect && thisLayout.isLeafRoot && text != null) { + var iconChar = seriesModel.get('drillDownIcon', true); + style.text = iconChar ? iconChar + ' ' + text : text; + } + } + + function giveGraphic(storageName, Ctor, depth, z) { + var element = oldRawIndex != null && oldStorage[storageName][oldRawIndex]; + var lasts = lastsForAnimation[storageName]; + + if (element) { + // Remove from oldStorage + oldStorage[storageName][oldRawIndex] = null; + prepareAnimationWhenHasOld(lasts, element); + } // If invisible and no old element, do not create new element (for optimizing). + else if (!thisInvisible) { + element = new Ctor(); + + if (element instanceof Displayable) { + element.z2 = calculateZ2(depth, z); + } + + prepareAnimationWhenNoOld(lasts, element); + } // Set to thisStorage + + + return thisStorage[storageName][thisRawIndex] = element; + } + + function prepareAnimationWhenHasOld(lasts, element) { + var lastCfg = lasts[thisRawIndex] = {}; + + if (element instanceof Group$1) { + lastCfg.oldX = element.x; + lastCfg.oldY = element.y; + } else { + lastCfg.oldShape = extend({}, element.shape); + } + } // If a element is new, we need to find the animation start point carefully, + // otherwise it will looks strange when 'zoomToNode'. + + + function prepareAnimationWhenNoOld(lasts, element) { + var lastCfg = lasts[thisRawIndex] = {}; + var parentNode = thisNode.parentNode; + var isGroup = element instanceof Group; + + if (parentNode && (!reRoot || reRoot.direction === 'drillDown')) { + var parentOldX = 0; + var parentOldY = 0; // New nodes appear from right-bottom corner in 'zoomToNode' animation. + // For convenience, get old bounding rect from background. + + var parentOldBg = lastsForAnimation.background[parentNode.getRawIndex()]; + + if (!reRoot && parentOldBg && parentOldBg.oldShape) { + parentOldX = parentOldBg.oldShape.width; + parentOldY = parentOldBg.oldShape.height; + } // When no parent old shape found, its parent is new too, + // so we can just use {x:0, y:0}. + + + if (isGroup) { + lastCfg.oldX = 0; + lastCfg.oldY = parentOldY; + } else { + lastCfg.oldShape = { + x: parentOldX, + y: parentOldY, + width: 0, + height: 0 + }; + } + } // Fade in, user can be aware that these nodes are new. + + + lastCfg.fadein = !isGroup; + } + } // We can not set all backgroud with the same z, Because the behaviour of + // drill down and roll up differ background creation sequence from tree + // hierarchy sequence, which cause that lowser background element overlap + // upper ones. So we calculate z based on depth. + // Moreover, we try to shrink down z interval to [0, 1] to avoid that + // treemap with large z overlaps other components. + + + function calculateZ2(depth, z2InLevel) { + return depth * Z2_BASE + z2InLevel; + } + + var each$3 = each; + var isObject$3 = isObject; + var CATEGORY_DEFAULT_VISUAL_INDEX = -1; + + var VisualMapping = + /** @class */ + function () { + function VisualMapping(option) { + var mappingMethod = option.mappingMethod; + var visualType = option.type; + var thisOption = this.option = clone(option); + this.type = visualType; + this.mappingMethod = mappingMethod; + this._normalizeData = normalizers[mappingMethod]; + var visualHandler = VisualMapping.visualHandlers[visualType]; + this.applyVisual = visualHandler.applyVisual; + this.getColorMapper = visualHandler.getColorMapper; + this._normalizedToVisual = visualHandler._normalizedToVisual[mappingMethod]; + + if (mappingMethod === 'piecewise') { + normalizeVisualRange(thisOption); + preprocessForPiecewise(thisOption); + } else if (mappingMethod === 'category') { + thisOption.categories ? preprocessForSpecifiedCategory(thisOption) // categories is ordinal when thisOption.categories not specified, + // which need no more preprocess except normalize visual. + : normalizeVisualRange(thisOption, true); + } else { + // mappingMethod === 'linear' or 'fixed' + assert(mappingMethod !== 'linear' || thisOption.dataExtent); + normalizeVisualRange(thisOption); + } + } + + VisualMapping.prototype.mapValueToVisual = function (value) { + var normalized = this._normalizeData(value); + + return this._normalizedToVisual(normalized, value); + }; + + VisualMapping.prototype.getNormalizer = function () { + return bind(this._normalizeData, this); + }; + /** + * List available visual types. + * + * @public + * @return {Array.} + */ + + + VisualMapping.listVisualTypes = function () { + return keys(VisualMapping.visualHandlers); + }; // /** + // * @public + // */ + // static addVisualHandler(name, handler) { + // visualHandlers[name] = handler; + // } + + /** + * @public + */ + + + VisualMapping.isValidType = function (visualType) { + return VisualMapping.visualHandlers.hasOwnProperty(visualType); + }; + /** + * Convinent method. + * Visual can be Object or Array or primary type. + */ + + + VisualMapping.eachVisual = function (visual, callback, context) { + if (isObject(visual)) { + each(visual, callback, context); + } else { + callback.call(context, visual); + } + }; + + VisualMapping.mapVisual = function (visual, callback, context) { + var isPrimary; + var newVisual = isArray(visual) ? [] : isObject(visual) ? {} : (isPrimary = true, null); + VisualMapping.eachVisual(visual, function (v, key) { + var newVal = callback.call(context, v, key); + isPrimary ? newVisual = newVal : newVisual[key] = newVal; + }); + return newVisual; + }; + /** + * Retrieve visual properties from given object. + */ + + + VisualMapping.retrieveVisuals = function (obj) { + var ret = {}; + var hasVisual; + obj && each$3(VisualMapping.visualHandlers, function (h, visualType) { + if (obj.hasOwnProperty(visualType)) { + ret[visualType] = obj[visualType]; + hasVisual = true; + } + }); + return hasVisual ? ret : null; + }; + /** + * Give order to visual types, considering colorSaturation, colorAlpha depends on color. + * + * @public + * @param {(Object|Array)} visualTypes If Object, like: {color: ..., colorSaturation: ...} + * IF Array, like: ['color', 'symbol', 'colorSaturation'] + * @return {Array.} Sorted visual types. + */ + + + VisualMapping.prepareVisualTypes = function (visualTypes) { + if (isArray(visualTypes)) { + visualTypes = visualTypes.slice(); + } else if (isObject$3(visualTypes)) { + var types_1 = []; + each$3(visualTypes, function (item, type) { + types_1.push(type); + }); + visualTypes = types_1; + } else { + return []; + } + + visualTypes.sort(function (type1, type2) { + // color should be front of colorSaturation, colorAlpha, ... + // symbol and symbolSize do not matter. + return type2 === 'color' && type1 !== 'color' && type1.indexOf('color') === 0 ? 1 : -1; + }); + return visualTypes; + }; + /** + * 'color', 'colorSaturation', 'colorAlpha', ... are depends on 'color'. + * Other visuals are only depends on themself. + */ + + + VisualMapping.dependsOn = function (visualType1, visualType2) { + return visualType2 === 'color' ? !!(visualType1 && visualType1.indexOf(visualType2) === 0) : visualType1 === visualType2; + }; + /** + * @param value + * @param pieceList [{value: ..., interval: [min, max]}, ...] + * Always from small to big. + * @param findClosestWhenOutside Default to be false + * @return index + */ + + + VisualMapping.findPieceIndex = function (value, pieceList, findClosestWhenOutside) { + var possibleI; + var abs = Infinity; // value has the higher priority. + + for (var i = 0, len = pieceList.length; i < len; i++) { + var pieceValue = pieceList[i].value; + + if (pieceValue != null) { + if (pieceValue === value // FIXME + // It is supposed to compare value according to value type of dimension, + // but currently value type can exactly be string or number. + // Compromise for numeric-like string (like '12'), especially + // in the case that visualMap.categories is ['22', '33']. + || isString(pieceValue) && pieceValue === value + '') { + return i; + } + + findClosestWhenOutside && updatePossible(pieceValue, i); + } + } + + for (var i = 0, len = pieceList.length; i < len; i++) { + var piece = pieceList[i]; + var interval = piece.interval; + var close_1 = piece.close; + + if (interval) { + if (interval[0] === -Infinity) { + if (littleThan(close_1[1], value, interval[1])) { + return i; + } + } else if (interval[1] === Infinity) { + if (littleThan(close_1[0], interval[0], value)) { + return i; + } + } else if (littleThan(close_1[0], interval[0], value) && littleThan(close_1[1], value, interval[1])) { + return i; + } + + findClosestWhenOutside && updatePossible(interval[0], i); + findClosestWhenOutside && updatePossible(interval[1], i); + } + } + + if (findClosestWhenOutside) { + return value === Infinity ? pieceList.length - 1 : value === -Infinity ? 0 : possibleI; + } + + function updatePossible(val, index) { + var newAbs = Math.abs(val - value); + + if (newAbs < abs) { + abs = newAbs; + possibleI = index; + } + } + }; + + VisualMapping.visualHandlers = { + color: { + applyVisual: makeApplyVisual('color'), + getColorMapper: function () { + var thisOption = this.option; + return bind(thisOption.mappingMethod === 'category' ? function (value, isNormalized) { + !isNormalized && (value = this._normalizeData(value)); + return doMapCategory.call(this, value); + } : function (value, isNormalized, out) { + // If output rgb array + // which will be much faster and useful in pixel manipulation + var returnRGBArray = !!out; + !isNormalized && (value = this._normalizeData(value)); + out = fastLerp(value, thisOption.parsedVisual, out); + return returnRGBArray ? out : stringify(out, 'rgba'); + }, this); + }, + _normalizedToVisual: { + linear: function (normalized) { + return stringify(fastLerp(normalized, this.option.parsedVisual), 'rgba'); + }, + category: doMapCategory, + piecewise: function (normalized, value) { + var result = getSpecifiedVisual.call(this, value); + + if (result == null) { + result = stringify(fastLerp(normalized, this.option.parsedVisual), 'rgba'); + } + + return result; + }, + fixed: doMapFixed + } + }, + colorHue: makePartialColorVisualHandler(function (color$1, value) { + return modifyHSL(color$1, value); + }), + colorSaturation: makePartialColorVisualHandler(function (color$1, value) { + return modifyHSL(color$1, null, value); + }), + colorLightness: makePartialColorVisualHandler(function (color$1, value) { + return modifyHSL(color$1, null, null, value); + }), + colorAlpha: makePartialColorVisualHandler(function (color$1, value) { + return modifyAlpha(color$1, value); + }), + decal: { + applyVisual: makeApplyVisual('decal'), + _normalizedToVisual: { + linear: null, + category: doMapCategory, + piecewise: null, + fixed: null + } + }, + opacity: { + applyVisual: makeApplyVisual('opacity'), + _normalizedToVisual: createNormalizedToNumericVisual([0, 1]) + }, + liftZ: { + applyVisual: makeApplyVisual('liftZ'), + _normalizedToVisual: { + linear: doMapFixed, + category: doMapFixed, + piecewise: doMapFixed, + fixed: doMapFixed + } + }, + symbol: { + applyVisual: function (value, getter, setter) { + var symbolCfg = this.mapValueToVisual(value); + setter('symbol', symbolCfg); + }, + _normalizedToVisual: { + linear: doMapToArray, + category: doMapCategory, + piecewise: function (normalized, value) { + var result = getSpecifiedVisual.call(this, value); + + if (result == null) { + result = doMapToArray.call(this, normalized); + } + + return result; + }, + fixed: doMapFixed + } + }, + symbolSize: { + applyVisual: makeApplyVisual('symbolSize'), + _normalizedToVisual: createNormalizedToNumericVisual([0, 1]) + } + }; + return VisualMapping; + }(); + + function preprocessForPiecewise(thisOption) { + var pieceList = thisOption.pieceList; + thisOption.hasSpecialVisual = false; + each(pieceList, function (piece, index) { + piece.originIndex = index; // piece.visual is "result visual value" but not + // a visual range, so it does not need to be normalized. + + if (piece.visual != null) { + thisOption.hasSpecialVisual = true; + } + }); + } + + function preprocessForSpecifiedCategory(thisOption) { + // Hash categories. + var categories = thisOption.categories; + var categoryMap = thisOption.categoryMap = {}; + var visual = thisOption.visual; + each$3(categories, function (cate, index) { + categoryMap[cate] = index; + }); // Process visual map input. + + if (!isArray(visual)) { + var visualArr_1 = []; + + if (isObject(visual)) { + each$3(visual, function (v, cate) { + var index = categoryMap[cate]; + visualArr_1[index != null ? index : CATEGORY_DEFAULT_VISUAL_INDEX] = v; + }); + } else { + // Is primary type, represents default visual. + visualArr_1[CATEGORY_DEFAULT_VISUAL_INDEX] = visual; + } + + visual = setVisualToOption(thisOption, visualArr_1); + } // Remove categories that has no visual, + // then we can mapping them to CATEGORY_DEFAULT_VISUAL_INDEX. + + + for (var i = categories.length - 1; i >= 0; i--) { + if (visual[i] == null) { + delete categoryMap[categories[i]]; + categories.pop(); + } + } + } + + function normalizeVisualRange(thisOption, isCategory) { + var visual = thisOption.visual; + var visualArr = []; + + if (isObject(visual)) { + each$3(visual, function (v) { + visualArr.push(v); + }); + } else if (visual != null) { + visualArr.push(visual); + } + + var doNotNeedPair = { + color: 1, + symbol: 1 + }; + + if (!isCategory && visualArr.length === 1 && !doNotNeedPair.hasOwnProperty(thisOption.type)) { + // Do not care visualArr.length === 0, which is illegal. + visualArr[1] = visualArr[0]; + } + + setVisualToOption(thisOption, visualArr); + } + + function makePartialColorVisualHandler(applyValue) { + return { + applyVisual: function (value, getter, setter) { + // Only used in HSL + var colorChannel = this.mapValueToVisual(value); // Must not be array value + + setter('color', applyValue(getter('color'), colorChannel)); + }, + _normalizedToVisual: createNormalizedToNumericVisual([0, 1]) + }; + } + + function doMapToArray(normalized) { + var visual = this.option.visual; + return visual[Math.round(linearMap(normalized, [0, 1], [0, visual.length - 1], true))] || {}; // TODO {}? + } + + function makeApplyVisual(visualType) { + return function (value, getter, setter) { + setter(visualType, this.mapValueToVisual(value)); + }; + } + + function doMapCategory(normalized) { + var visual = this.option.visual; + return visual[this.option.loop && normalized !== CATEGORY_DEFAULT_VISUAL_INDEX ? normalized % visual.length : normalized]; + } + + function doMapFixed() { + // visual will be convert to array. + return this.option.visual[0]; + } + /** + * Create mapped to numeric visual + */ + + + function createNormalizedToNumericVisual(sourceExtent) { + return { + linear: function (normalized) { + return linearMap(normalized, sourceExtent, this.option.visual, true); + }, + category: doMapCategory, + piecewise: function (normalized, value) { + var result = getSpecifiedVisual.call(this, value); + + if (result == null) { + result = linearMap(normalized, sourceExtent, this.option.visual, true); + } + + return result; + }, + fixed: doMapFixed + }; + } + + function getSpecifiedVisual(value) { + var thisOption = this.option; + var pieceList = thisOption.pieceList; + + if (thisOption.hasSpecialVisual) { + var pieceIndex = VisualMapping.findPieceIndex(value, pieceList); + var piece = pieceList[pieceIndex]; + + if (piece && piece.visual) { + return piece.visual[this.type]; + } + } + } + + function setVisualToOption(thisOption, visualArr) { + thisOption.visual = visualArr; + + if (thisOption.type === 'color') { + thisOption.parsedVisual = map(visualArr, function (item) { + var color$1 = parse(item); + + if (!color$1 && "development" !== 'production') { + warn("'" + item + "' is an illegal color, fallback to '#000000'", true); + } + + return color$1 || [0, 0, 0, 1]; + }); + } + + return visualArr; + } + /** + * Normalizers by mapping methods. + */ + + + var normalizers = { + linear: function (value) { + return linearMap(value, this.option.dataExtent, [0, 1], true); + }, + piecewise: function (value) { + var pieceList = this.option.pieceList; + var pieceIndex = VisualMapping.findPieceIndex(value, pieceList, true); + + if (pieceIndex != null) { + return linearMap(pieceIndex, [0, pieceList.length - 1], [0, 1], true); + } + }, + category: function (value) { + var index = this.option.categories ? this.option.categoryMap[value] : value; // ordinal value + + return index == null ? CATEGORY_DEFAULT_VISUAL_INDEX : index; + }, + fixed: noop + }; + + function littleThan(close, a, b) { + return close ? a <= b : a < b; + } + + var ITEM_STYLE_NORMAL = 'itemStyle'; + var inner$9 = makeInner(); + var treemapVisual = { + seriesType: 'treemap', + reset: function (seriesModel) { + var tree = seriesModel.getData().tree; + var root = tree.root; + + if (root.isRemoved()) { + return; + } + + travelTree(root, // Visual should calculate from tree root but not view root. + {}, seriesModel.getViewRoot().getAncestors(), seriesModel); + } + }; + + function travelTree(node, designatedVisual, viewRootAncestors, seriesModel) { + var nodeModel = node.getModel(); + var nodeLayout = node.getLayout(); + var data = node.hostTree.data; // Optimize + + if (!nodeLayout || nodeLayout.invisible || !nodeLayout.isInView) { + return; + } + + var nodeItemStyleModel = nodeModel.getModel(ITEM_STYLE_NORMAL); + var visuals = buildVisuals(nodeItemStyleModel, designatedVisual, seriesModel); + var existsStyle = data.ensureUniqueItemVisual(node.dataIndex, 'style'); // calculate border color + + var borderColor = nodeItemStyleModel.get('borderColor'); + var borderColorSaturation = nodeItemStyleModel.get('borderColorSaturation'); + var thisNodeColor; + + if (borderColorSaturation != null) { + // For performance, do not always execute 'calculateColor'. + thisNodeColor = calculateColor(visuals); + borderColor = calculateBorderColor(borderColorSaturation, thisNodeColor); + } + + existsStyle.stroke = borderColor; + var viewChildren = node.viewChildren; + + if (!viewChildren || !viewChildren.length) { + thisNodeColor = calculateColor(visuals); // Apply visual to this node. + + existsStyle.fill = thisNodeColor; + } else { + var mapping_1 = buildVisualMapping(node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren); // Designate visual to children. + + each(viewChildren, function (child, index) { + // If higher than viewRoot, only ancestors of viewRoot is needed to visit. + if (child.depth >= viewRootAncestors.length || child === viewRootAncestors[child.depth]) { + var childVisual = mapVisual(nodeModel, visuals, child, index, mapping_1, seriesModel); + travelTree(child, childVisual, viewRootAncestors, seriesModel); + } + }); + } + } + + function buildVisuals(nodeItemStyleModel, designatedVisual, seriesModel) { + var visuals = extend({}, designatedVisual); + var designatedVisualItemStyle = seriesModel.designatedVisualItemStyle; + each(['color', 'colorAlpha', 'colorSaturation'], function (visualName) { + // Priority: thisNode > thisLevel > parentNodeDesignated > seriesModel + designatedVisualItemStyle[visualName] = designatedVisual[visualName]; + var val = nodeItemStyleModel.get(visualName); + designatedVisualItemStyle[visualName] = null; + val != null && (visuals[visualName] = val); + }); + return visuals; + } + + function calculateColor(visuals) { + var color = getValueVisualDefine(visuals, 'color'); + + if (color) { + var colorAlpha = getValueVisualDefine(visuals, 'colorAlpha'); + var colorSaturation = getValueVisualDefine(visuals, 'colorSaturation'); + + if (colorSaturation) { + color = modifyHSL(color, null, null, colorSaturation); + } + + if (colorAlpha) { + color = modifyAlpha(color, colorAlpha); + } + + return color; + } + } + + function calculateBorderColor(borderColorSaturation, thisNodeColor) { + return thisNodeColor != null // Can only be string + ? modifyHSL(thisNodeColor, null, null, borderColorSaturation) : null; + } + + function getValueVisualDefine(visuals, name) { + var value = visuals[name]; + + if (value != null && value !== 'none') { + return value; + } + } + + function buildVisualMapping(node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren) { + if (!viewChildren || !viewChildren.length) { + return; + } + + var rangeVisual = getRangeVisual(nodeModel, 'color') || visuals.color != null && visuals.color !== 'none' && (getRangeVisual(nodeModel, 'colorAlpha') || getRangeVisual(nodeModel, 'colorSaturation')); + + if (!rangeVisual) { + return; + } + + var visualMin = nodeModel.get('visualMin'); + var visualMax = nodeModel.get('visualMax'); + var dataExtent = nodeLayout.dataExtent.slice(); + visualMin != null && visualMin < dataExtent[0] && (dataExtent[0] = visualMin); + visualMax != null && visualMax > dataExtent[1] && (dataExtent[1] = visualMax); + var colorMappingBy = nodeModel.get('colorMappingBy'); + var opt = { + type: rangeVisual.name, + dataExtent: dataExtent, + visual: rangeVisual.range + }; + + if (opt.type === 'color' && (colorMappingBy === 'index' || colorMappingBy === 'id')) { + opt.mappingMethod = 'category'; + opt.loop = true; // categories is ordinal, so do not set opt.categories. + } else { + opt.mappingMethod = 'linear'; + } + + var mapping = new VisualMapping(opt); + inner$9(mapping).drColorMappingBy = colorMappingBy; + return mapping; + } // Notice: If we dont have the attribute 'colorRange', but only use + // attribute 'color' to represent both concepts of 'colorRange' and 'color', + // (It means 'colorRange' when 'color' is Array, means 'color' when not array), + // this problem will be encountered: + // If a level-1 node dont have children, and its siblings has children, + // and colorRange is set on level-1, then the node can not be colored. + // So we separate 'colorRange' and 'color' to different attributes. + + + function getRangeVisual(nodeModel, name) { + // 'colorRange', 'colorARange', 'colorSRange'. + // If not exsits on this node, fetch from levels and series. + var range = nodeModel.get(name); + return isArray(range) && range.length ? { + name: name, + range: range + } : null; + } + + function mapVisual(nodeModel, visuals, child, index, mapping, seriesModel) { + var childVisuals = extend({}, visuals); + + if (mapping) { + // Only support color, colorAlpha, colorSaturation. + var mappingType = mapping.type; + var colorMappingBy = mappingType === 'color' && inner$9(mapping).drColorMappingBy; + var value = colorMappingBy === 'index' ? index : colorMappingBy === 'id' ? seriesModel.mapIdToIndex(child.getId()) : child.getValue(nodeModel.get('visualDimension')); + childVisuals[mappingType] = mapping.mapValueToVisual(value); + } + + return childVisuals; + } + + var mathMax$7 = Math.max; + var mathMin$7 = Math.min; + var retrieveValue = retrieve; + var each$4 = each; + var PATH_BORDER_WIDTH = ['itemStyle', 'borderWidth']; + var PATH_GAP_WIDTH = ['itemStyle', 'gapWidth']; + var PATH_UPPER_LABEL_SHOW = ['upperLabel', 'show']; + var PATH_UPPER_LABEL_HEIGHT = ['upperLabel', 'height']; + /** + * @public + */ + + var treemapLayout = { + seriesType: 'treemap', + reset: function (seriesModel, ecModel, api, payload) { + // Layout result in each node: + // {x, y, width, height, area, borderWidth} + var ecWidth = api.getWidth(); + var ecHeight = api.getHeight(); + var seriesOption = seriesModel.option; + var layoutInfo = getLayoutRect(seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + var size = seriesOption.size || []; // Compatible with ec2. + + var containerWidth = parsePercent$1(retrieveValue(layoutInfo.width, size[0]), ecWidth); + var containerHeight = parsePercent$1(retrieveValue(layoutInfo.height, size[1]), ecHeight); // Fetch payload info. + + var payloadType = payload && payload.type; + var types = ['treemapZoomToNode', 'treemapRootToNode']; + var targetInfo = retrieveTargetInfo(payload, types, seriesModel); + var rootRect = payloadType === 'treemapRender' || payloadType === 'treemapMove' ? payload.rootRect : null; + var viewRoot = seriesModel.getViewRoot(); + var viewAbovePath = getPathToRoot(viewRoot); + + if (payloadType !== 'treemapMove') { + var rootSize = payloadType === 'treemapZoomToNode' ? estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) : rootRect ? [rootRect.width, rootRect.height] : [containerWidth, containerHeight]; + var sort_1 = seriesOption.sort; + + if (sort_1 && sort_1 !== 'asc' && sort_1 !== 'desc') { + // Default to be desc order. + sort_1 = 'desc'; + } + + var options = { + squareRatio: seriesOption.squareRatio, + sort: sort_1, + leafDepth: seriesOption.leafDepth + }; // layout should be cleared because using updateView but not update. + + viewRoot.hostTree.clearLayouts(); // TODO + // optimize: if out of view clip, do not layout. + // But take care that if do not render node out of view clip, + // how to calculate start po + + var viewRootLayout_1 = { + x: 0, + y: 0, + width: rootSize[0], + height: rootSize[1], + area: rootSize[0] * rootSize[1] + }; + viewRoot.setLayout(viewRootLayout_1); + squarify(viewRoot, options, false, 0); // Supplement layout. + + viewRootLayout_1 = viewRoot.getLayout(); + each$4(viewAbovePath, function (node, index) { + var childValue = (viewAbovePath[index + 1] || viewRoot).getValue(); + node.setLayout(extend({ + dataExtent: [childValue, childValue], + borderWidth: 0, + upperHeight: 0 + }, viewRootLayout_1)); + }); + } + + var treeRoot = seriesModel.getData().tree.root; + treeRoot.setLayout(calculateRootPosition(layoutInfo, rootRect, targetInfo), true); + seriesModel.setLayoutInfo(layoutInfo); // FIXME + // 现在没有clip功能,暂时取ec高宽。 + + prunning(treeRoot, // Transform to base element coordinate system. + new BoundingRect(-layoutInfo.x, -layoutInfo.y, ecWidth, ecHeight), viewAbovePath, viewRoot, 0); + } + }; + /** + * Layout treemap with squarify algorithm. + * The original presentation of this algorithm + * was made by Mark Bruls, Kees Huizing, and Jarke J. van Wijk + * . + * The implementation of this algorithm was originally copied from "d3.js" + * + * with some modifications made for this program. + * See the license statement at the head of this file. + * + * @protected + * @param {module:echarts/data/Tree~TreeNode} node + * @param {Object} options + * @param {string} options.sort 'asc' or 'desc' + * @param {number} options.squareRatio + * @param {boolean} hideChildren + * @param {number} depth + */ + + function squarify(node, options, hideChildren, depth) { + var width; + var height; + + if (node.isRemoved()) { + return; + } + + var thisLayout = node.getLayout(); + width = thisLayout.width; + height = thisLayout.height; // Considering border and gap + + var nodeModel = node.getModel(); + var borderWidth = nodeModel.get(PATH_BORDER_WIDTH); + var halfGapWidth = nodeModel.get(PATH_GAP_WIDTH) / 2; + var upperLabelHeight = getUpperLabelHeight(nodeModel); + var upperHeight = Math.max(borderWidth, upperLabelHeight); + var layoutOffset = borderWidth - halfGapWidth; + var layoutOffsetUpper = upperHeight - halfGapWidth; + node.setLayout({ + borderWidth: borderWidth, + upperHeight: upperHeight, + upperLabelHeight: upperLabelHeight + }, true); + width = mathMax$7(width - 2 * layoutOffset, 0); + height = mathMax$7(height - layoutOffset - layoutOffsetUpper, 0); + var totalArea = width * height; + var viewChildren = initChildren(node, nodeModel, totalArea, options, hideChildren, depth); + + if (!viewChildren.length) { + return; + } + + var rect = { + x: layoutOffset, + y: layoutOffsetUpper, + width: width, + height: height + }; + var rowFixedLength = mathMin$7(width, height); + var best = Infinity; // the best row score so far + + var row = []; + row.area = 0; + + for (var i = 0, len = viewChildren.length; i < len;) { + var child = viewChildren[i]; + row.push(child); + row.area += child.getLayout().area; + var score = worst(row, rowFixedLength, options.squareRatio); // continue with this orientation + + if (score <= best) { + i++; + best = score; + } // abort, and try a different orientation + else { + row.area -= row.pop().getLayout().area; + position(row, rowFixedLength, rect, halfGapWidth, false); + rowFixedLength = mathMin$7(rect.width, rect.height); + row.length = row.area = 0; + best = Infinity; + } + } + + if (row.length) { + position(row, rowFixedLength, rect, halfGapWidth, true); + } + + if (!hideChildren) { + var childrenVisibleMin = nodeModel.get('childrenVisibleMin'); + + if (childrenVisibleMin != null && totalArea < childrenVisibleMin) { + hideChildren = true; + } + } + + for (var i = 0, len = viewChildren.length; i < len; i++) { + squarify(viewChildren[i], options, hideChildren, depth + 1); + } + } + /** + * Set area to each child, and calculate data extent for visual coding. + */ + + + function initChildren(node, nodeModel, totalArea, options, hideChildren, depth) { + var viewChildren = node.children || []; + var orderBy = options.sort; + orderBy !== 'asc' && orderBy !== 'desc' && (orderBy = null); + var overLeafDepth = options.leafDepth != null && options.leafDepth <= depth; // leafDepth has higher priority. + + if (hideChildren && !overLeafDepth) { + return node.viewChildren = []; + } // Sort children, order by desc. + + + viewChildren = filter(viewChildren, function (child) { + return !child.isRemoved(); + }); + sort$1(viewChildren, orderBy); + var info = statistic(nodeModel, viewChildren, orderBy); + + if (info.sum === 0) { + return node.viewChildren = []; + } + + info.sum = filterByThreshold(nodeModel, totalArea, info.sum, orderBy, viewChildren); + + if (info.sum === 0) { + return node.viewChildren = []; + } // Set area to each child. + + + for (var i = 0, len = viewChildren.length; i < len; i++) { + var area = viewChildren[i].getValue() / info.sum * totalArea; // Do not use setLayout({...}, true), because it is needed to clear last layout. + + viewChildren[i].setLayout({ + area: area + }); + } + + if (overLeafDepth) { + viewChildren.length && node.setLayout({ + isLeafRoot: true + }, true); + viewChildren.length = 0; + } + + node.viewChildren = viewChildren; + node.setLayout({ + dataExtent: info.dataExtent + }, true); + return viewChildren; + } + /** + * Consider 'visibleMin'. Modify viewChildren and get new sum. + */ + + + function filterByThreshold(nodeModel, totalArea, sum, orderBy, orderedChildren) { + // visibleMin is not supported yet when no option.sort. + if (!orderBy) { + return sum; + } + + var visibleMin = nodeModel.get('visibleMin'); + var len = orderedChildren.length; + var deletePoint = len; // Always travel from little value to big value. + + for (var i = len - 1; i >= 0; i--) { + var value = orderedChildren[orderBy === 'asc' ? len - i - 1 : i].getValue(); + + if (value / sum * totalArea < visibleMin) { + deletePoint = i; + sum -= value; + } + } + + orderBy === 'asc' ? orderedChildren.splice(0, len - deletePoint) : orderedChildren.splice(deletePoint, len - deletePoint); + return sum; + } + /** + * Sort + */ + + + function sort$1(viewChildren, orderBy) { + if (orderBy) { + viewChildren.sort(function (a, b) { + var diff = orderBy === 'asc' ? a.getValue() - b.getValue() : b.getValue() - a.getValue(); + return diff === 0 ? orderBy === 'asc' ? a.dataIndex - b.dataIndex : b.dataIndex - a.dataIndex : diff; + }); + } + + return viewChildren; + } + /** + * Statistic + */ + + + function statistic(nodeModel, children, orderBy) { + // Calculate sum. + var sum = 0; + + for (var i = 0, len = children.length; i < len; i++) { + sum += children[i].getValue(); + } // Statistic data extent for latter visual coding. + // Notice: data extent should be calculate based on raw children + // but not filtered view children, otherwise visual mapping will not + // be stable when zoom (where children is filtered by visibleMin). + + + var dimension = nodeModel.get('visualDimension'); + var dataExtent; // The same as area dimension. + + if (!children || !children.length) { + dataExtent = [NaN, NaN]; + } else if (dimension === 'value' && orderBy) { + dataExtent = [children[children.length - 1].getValue(), children[0].getValue()]; + orderBy === 'asc' && dataExtent.reverse(); + } // Other dimension. + else { + dataExtent = [Infinity, -Infinity]; + each$4(children, function (child) { + var value = child.getValue(dimension); + value < dataExtent[0] && (dataExtent[0] = value); + value > dataExtent[1] && (dataExtent[1] = value); + }); + } + + return { + sum: sum, + dataExtent: dataExtent + }; + } + /** + * Computes the score for the specified row, + * as the worst aspect ratio. + */ + + + function worst(row, rowFixedLength, ratio) { + var areaMax = 0; + var areaMin = Infinity; + + for (var i = 0, area = void 0, len = row.length; i < len; i++) { + area = row[i].getLayout().area; + + if (area) { + area < areaMin && (areaMin = area); + area > areaMax && (areaMax = area); + } + } + + var squareArea = row.area * row.area; + var f = rowFixedLength * rowFixedLength * ratio; + return squareArea ? mathMax$7(f * areaMax / squareArea, squareArea / (f * areaMin)) : Infinity; + } + /** + * Positions the specified row of nodes. Modifies `rect`. + */ + + + function position(row, rowFixedLength, rect, halfGapWidth, flush) { + // When rowFixedLength === rect.width, + // it is horizontal subdivision, + // rowFixedLength is the width of the subdivision, + // rowOtherLength is the height of the subdivision, + // and nodes will be positioned from left to right. + // wh[idx0WhenH] means: when horizontal, + // wh[idx0WhenH] => wh[0] => 'width'. + // xy[idx1WhenH] => xy[1] => 'y'. + var idx0WhenH = rowFixedLength === rect.width ? 0 : 1; + var idx1WhenH = 1 - idx0WhenH; + var xy = ['x', 'y']; + var wh = ['width', 'height']; + var last = rect[xy[idx0WhenH]]; + var rowOtherLength = rowFixedLength ? row.area / rowFixedLength : 0; + + if (flush || rowOtherLength > rect[wh[idx1WhenH]]) { + rowOtherLength = rect[wh[idx1WhenH]]; // over+underflow + } + + for (var i = 0, rowLen = row.length; i < rowLen; i++) { + var node = row[i]; + var nodeLayout = {}; + var step = rowOtherLength ? node.getLayout().area / rowOtherLength : 0; + var wh1 = nodeLayout[wh[idx1WhenH]] = mathMax$7(rowOtherLength - 2 * halfGapWidth, 0); // We use Math.max/min to avoid negative width/height when considering gap width. + + var remain = rect[xy[idx0WhenH]] + rect[wh[idx0WhenH]] - last; + var modWH = i === rowLen - 1 || remain < step ? remain : step; + var wh0 = nodeLayout[wh[idx0WhenH]] = mathMax$7(modWH - 2 * halfGapWidth, 0); + nodeLayout[xy[idx1WhenH]] = rect[xy[idx1WhenH]] + mathMin$7(halfGapWidth, wh1 / 2); + nodeLayout[xy[idx0WhenH]] = last + mathMin$7(halfGapWidth, wh0 / 2); + last += modWH; + node.setLayout(nodeLayout, true); + } + + rect[xy[idx1WhenH]] += rowOtherLength; + rect[wh[idx1WhenH]] -= rowOtherLength; + } // Return [containerWidth, containerHeight] as default. + + + function estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) { + // If targetInfo.node exists, we zoom to the node, + // so estimate whold width and heigth by target node. + var currNode = (targetInfo || {}).node; + var defaultSize = [containerWidth, containerHeight]; + + if (!currNode || currNode === viewRoot) { + return defaultSize; + } + + var parent; + var viewArea = containerWidth * containerHeight; + var area = viewArea * seriesModel.option.zoomToNodeRatio; + + while (parent = currNode.parentNode) { + // jshint ignore:line + var sum = 0; + var siblings = parent.children; + + for (var i = 0, len = siblings.length; i < len; i++) { + sum += siblings[i].getValue(); + } + + var currNodeValue = currNode.getValue(); + + if (currNodeValue === 0) { + return defaultSize; + } + + area *= sum / currNodeValue; // Considering border, suppose aspect ratio is 1. + + var parentModel = parent.getModel(); + var borderWidth = parentModel.get(PATH_BORDER_WIDTH); + var upperHeight = Math.max(borderWidth, getUpperLabelHeight(parentModel)); + area += 4 * borderWidth * borderWidth + (3 * borderWidth + upperHeight) * Math.pow(area, 0.5); + area > MAX_SAFE_INTEGER && (area = MAX_SAFE_INTEGER); + currNode = parent; + } + + area < viewArea && (area = viewArea); + var scale = Math.pow(area / viewArea, 0.5); + return [containerWidth * scale, containerHeight * scale]; + } // Root postion base on coord of containerGroup + + + function calculateRootPosition(layoutInfo, rootRect, targetInfo) { + if (rootRect) { + return { + x: rootRect.x, + y: rootRect.y + }; + } + + var defaultPosition = { + x: 0, + y: 0 + }; + + if (!targetInfo) { + return defaultPosition; + } // If targetInfo is fetched by 'retrieveTargetInfo', + // old tree and new tree are the same tree, + // so the node still exists and we can visit it. + + + var targetNode = targetInfo.node; + var layout = targetNode.getLayout(); + + if (!layout) { + return defaultPosition; + } // Transform coord from local to container. + + + var targetCenter = [layout.width / 2, layout.height / 2]; + var node = targetNode; + + while (node) { + var nodeLayout = node.getLayout(); + targetCenter[0] += nodeLayout.x; + targetCenter[1] += nodeLayout.y; + node = node.parentNode; + } + + return { + x: layoutInfo.width / 2 - targetCenter[0], + y: layoutInfo.height / 2 - targetCenter[1] + }; + } // Mark nodes visible for prunning when visual coding and rendering. + // Prunning depends on layout and root position, so we have to do it after layout. + + + function prunning(node, clipRect, viewAbovePath, viewRoot, depth) { + var nodeLayout = node.getLayout(); + var nodeInViewAbovePath = viewAbovePath[depth]; + var isAboveViewRoot = nodeInViewAbovePath && nodeInViewAbovePath === node; + + if (nodeInViewAbovePath && !isAboveViewRoot || depth === viewAbovePath.length && node !== viewRoot) { + return; + } + + node.setLayout({ + // isInView means: viewRoot sub tree + viewAbovePath + isInView: true, + // invisible only means: outside view clip so that the node can not + // see but still layout for animation preparation but not render. + invisible: !isAboveViewRoot && !clipRect.intersect(nodeLayout), + isAboveViewRoot: isAboveViewRoot + }, true); // Transform to child coordinate. + + var childClipRect = new BoundingRect(clipRect.x - nodeLayout.x, clipRect.y - nodeLayout.y, clipRect.width, clipRect.height); + each$4(node.viewChildren || [], function (child) { + prunning(child, childClipRect, viewAbovePath, viewRoot, depth + 1); + }); + } + + function getUpperLabelHeight(model) { + return model.get(PATH_UPPER_LABEL_SHOW) ? model.get(PATH_UPPER_LABEL_HEIGHT) : 0; + } + + function install$c(registers) { + registers.registerSeriesModel(TreemapSeriesModel); + registers.registerChartView(TreemapView); + registers.registerVisual(treemapVisual); + registers.registerLayout(treemapLayout); + installTreemapAction(registers); + } + + function categoryFilter(ecModel) { + var legendModels = ecModel.findComponents({ + mainType: 'legend' + }); + + if (!legendModels || !legendModels.length) { + return; + } + + ecModel.eachSeriesByType('graph', function (graphSeries) { + var categoriesData = graphSeries.getCategoriesData(); + var graph = graphSeries.getGraph(); + var data = graph.data; + var categoryNames = categoriesData.mapArray(categoriesData.getName); + data.filterSelf(function (idx) { + var model = data.getItemModel(idx); + var category = model.getShallow('category'); + + if (category != null) { + if (isNumber(category)) { + category = categoryNames[category]; + } // If in any legend component the status is not selected. + + + for (var i = 0; i < legendModels.length; i++) { + if (!legendModels[i].isSelected(category)) { + return false; + } + } + } + + return true; + }); + }); + } + + function categoryVisual(ecModel) { + var paletteScope = {}; + ecModel.eachSeriesByType('graph', function (seriesModel) { + var categoriesData = seriesModel.getCategoriesData(); + var data = seriesModel.getData(); + var categoryNameIdxMap = {}; + categoriesData.each(function (idx) { + var name = categoriesData.getName(idx); // Add prefix to avoid conflict with Object.prototype. + + categoryNameIdxMap['ec-' + name] = idx; + var itemModel = categoriesData.getItemModel(idx); + var style = itemModel.getModel('itemStyle').getItemStyle(); + + if (!style.fill) { + // Get color from palette. + style.fill = seriesModel.getColorFromPalette(name, paletteScope); + } + + categoriesData.setItemVisual(idx, 'style', style); + var symbolVisualList = ['symbol', 'symbolSize', 'symbolKeepAspect']; + + for (var i = 0; i < symbolVisualList.length; i++) { + var symbolVisual = itemModel.getShallow(symbolVisualList[i], true); + + if (symbolVisual != null) { + categoriesData.setItemVisual(idx, symbolVisualList[i], symbolVisual); + } + } + }); // Assign category color to visual + + if (categoriesData.count()) { + data.each(function (idx) { + var model = data.getItemModel(idx); + var categoryIdx = model.getShallow('category'); + + if (categoryIdx != null) { + if (isString(categoryIdx)) { + categoryIdx = categoryNameIdxMap['ec-' + categoryIdx]; + } + + var categoryStyle = categoriesData.getItemVisual(categoryIdx, 'style'); + var style = data.ensureUniqueItemVisual(idx, 'style'); + extend(style, categoryStyle); + var visualList = ['symbol', 'symbolSize', 'symbolKeepAspect']; + + for (var i = 0; i < visualList.length; i++) { + data.setItemVisual(idx, visualList[i], categoriesData.getItemVisual(categoryIdx, visualList[i])); + } + } + }); + } + }); + } + + function normalize$2(a) { + if (!(a instanceof Array)) { + a = [a, a]; + } + + return a; + } + + function graphEdgeVisual(ecModel) { + ecModel.eachSeriesByType('graph', function (seriesModel) { + var graph = seriesModel.getGraph(); + var edgeData = seriesModel.getEdgeData(); + var symbolType = normalize$2(seriesModel.get('edgeSymbol')); + var symbolSize = normalize$2(seriesModel.get('edgeSymbolSize')); // const colorQuery = ['lineStyle', 'color'] as const; + // const opacityQuery = ['lineStyle', 'opacity'] as const; + + edgeData.setVisual('fromSymbol', symbolType && symbolType[0]); + edgeData.setVisual('toSymbol', symbolType && symbolType[1]); + edgeData.setVisual('fromSymbolSize', symbolSize && symbolSize[0]); + edgeData.setVisual('toSymbolSize', symbolSize && symbolSize[1]); + edgeData.setVisual('style', seriesModel.getModel('lineStyle').getLineStyle()); + edgeData.each(function (idx) { + var itemModel = edgeData.getItemModel(idx); + var edge = graph.getEdgeByIndex(idx); + var symbolType = normalize$2(itemModel.getShallow('symbol', true)); + var symbolSize = normalize$2(itemModel.getShallow('symbolSize', true)); // Edge visual must after node visual + + var style = itemModel.getModel('lineStyle').getLineStyle(); + var existsStyle = edgeData.ensureUniqueItemVisual(idx, 'style'); + extend(existsStyle, style); + + switch (existsStyle.stroke) { + case 'source': + { + var nodeStyle = edge.node1.getVisual('style'); + existsStyle.stroke = nodeStyle && nodeStyle.fill; + break; + } + + case 'target': + { + var nodeStyle = edge.node2.getVisual('style'); + existsStyle.stroke = nodeStyle && nodeStyle.fill; + break; + } + } + + symbolType[0] && edge.setVisual('fromSymbol', symbolType[0]); + symbolType[1] && edge.setVisual('toSymbol', symbolType[1]); + symbolSize[0] && edge.setVisual('fromSymbolSize', symbolSize[0]); + symbolSize[1] && edge.setVisual('toSymbolSize', symbolSize[1]); + }); + }); + } + + var KEY_DELIMITER = '-->'; + /** + * params handler + * @param {module:echarts/model/SeriesModel} seriesModel + * @returns {*} + */ + + var getAutoCurvenessParams = function (seriesModel) { + return seriesModel.get('autoCurveness') || null; + }; + /** + * Generate a list of edge curvatures, 20 is the default + * @param {module:echarts/model/SeriesModel} seriesModel + * @param {number} appendLength + * @return 20 => [0, -0.2, 0.2, -0.4, 0.4, -0.6, 0.6, -0.8, 0.8, -1, 1, -1.2, 1.2, -1.4, 1.4, -1.6, 1.6, -1.8, 1.8, -2] + */ + + + var createCurveness = function (seriesModel, appendLength) { + var autoCurvenessParmas = getAutoCurvenessParams(seriesModel); + var length = 20; + var curvenessList = []; // handler the function set + + if (isNumber(autoCurvenessParmas)) { + length = autoCurvenessParmas; + } else if (isArray(autoCurvenessParmas)) { + seriesModel.__curvenessList = autoCurvenessParmas; + return; + } // append length + + + if (appendLength > length) { + length = appendLength; + } // make sure the length is even + + + var len = length % 2 ? length + 2 : length + 3; + curvenessList = []; + + for (var i = 0; i < len; i++) { + curvenessList.push((i % 2 ? i + 1 : i) / 10 * (i % 2 ? -1 : 1)); + } + + seriesModel.__curvenessList = curvenessList; + }; + /** + * Create different cache key data in the positive and negative directions, in order to set the curvature later + * @param {number|string|module:echarts/data/Graph.Node} n1 + * @param {number|string|module:echarts/data/Graph.Node} n2 + * @param {module:echarts/model/SeriesModel} seriesModel + * @returns {string} key + */ + + + var getKeyOfEdges = function (n1, n2, seriesModel) { + var source = [n1.id, n1.dataIndex].join('.'); + var target = [n2.id, n2.dataIndex].join('.'); + return [seriesModel.uid, source, target].join(KEY_DELIMITER); + }; + /** + * get opposite key + * @param {string} key + * @returns {string} + */ + + + var getOppositeKey = function (key) { + var keys = key.split(KEY_DELIMITER); + return [keys[0], keys[2], keys[1]].join(KEY_DELIMITER); + }; + /** + * get edgeMap with key + * @param edge + * @param {module:echarts/model/SeriesModel} seriesModel + */ + + + var getEdgeFromMap = function (edge, seriesModel) { + var key = getKeyOfEdges(edge.node1, edge.node2, seriesModel); + return seriesModel.__edgeMap[key]; + }; + /** + * calculate all cases total length + * @param edge + * @param seriesModel + * @returns {number} + */ + + + var getTotalLengthBetweenNodes = function (edge, seriesModel) { + var len = getEdgeMapLengthWithKey(getKeyOfEdges(edge.node1, edge.node2, seriesModel), seriesModel); + var lenV = getEdgeMapLengthWithKey(getKeyOfEdges(edge.node2, edge.node1, seriesModel), seriesModel); + return len + lenV; + }; + /** + * + * @param key + */ + + + var getEdgeMapLengthWithKey = function (key, seriesModel) { + var edgeMap = seriesModel.__edgeMap; + return edgeMap[key] ? edgeMap[key].length : 0; + }; + /** + * Count the number of edges between the same two points, used to obtain the curvature table and the parity of the edge + * @see /graph/GraphSeries.js@getInitialData + * @param {module:echarts/model/SeriesModel} seriesModel + */ + + + function initCurvenessList(seriesModel) { + if (!getAutoCurvenessParams(seriesModel)) { + return; + } + + seriesModel.__curvenessList = []; + seriesModel.__edgeMap = {}; // calc the array of curveness List + + createCurveness(seriesModel); + } + /** + * set edgeMap with key + * @param {number|string|module:echarts/data/Graph.Node} n1 + * @param {number|string|module:echarts/data/Graph.Node} n2 + * @param {module:echarts/model/SeriesModel} seriesModel + * @param {number} index + */ + + function createEdgeMapForCurveness(n1, n2, seriesModel, index) { + if (!getAutoCurvenessParams(seriesModel)) { + return; + } + + var key = getKeyOfEdges(n1, n2, seriesModel); + var edgeMap = seriesModel.__edgeMap; + var oppositeEdges = edgeMap[getOppositeKey(key)]; // set direction + + if (edgeMap[key] && !oppositeEdges) { + edgeMap[key].isForward = true; + } else if (oppositeEdges && edgeMap[key]) { + oppositeEdges.isForward = true; + edgeMap[key].isForward = false; + } + + edgeMap[key] = edgeMap[key] || []; + edgeMap[key].push(index); + } + /** + * get curvature for edge + * @param edge + * @param {module:echarts/model/SeriesModel} seriesModel + * @param index + */ + + function getCurvenessForEdge(edge, seriesModel, index, needReverse) { + var autoCurvenessParams = getAutoCurvenessParams(seriesModel); + var isArrayParam = isArray(autoCurvenessParams); + + if (!autoCurvenessParams) { + return null; + } + + var edgeArray = getEdgeFromMap(edge, seriesModel); + + if (!edgeArray) { + return null; + } + + var edgeIndex = -1; + + for (var i = 0; i < edgeArray.length; i++) { + if (edgeArray[i] === index) { + edgeIndex = i; + break; + } + } // if totalLen is Longer createCurveness + + + var totalLen = getTotalLengthBetweenNodes(edge, seriesModel); + createCurveness(seriesModel, totalLen); + edge.lineStyle = edge.lineStyle || {}; // if is opposite edge, must set curvenss to opposite number + + var curKey = getKeyOfEdges(edge.node1, edge.node2, seriesModel); + var curvenessList = seriesModel.__curvenessList; // if pass array no need parity + + var parityCorrection = isArrayParam ? 0 : totalLen % 2 ? 0 : 1; + + if (!edgeArray.isForward) { + // the opposite edge show outside + var oppositeKey = getOppositeKey(curKey); + var len = getEdgeMapLengthWithKey(oppositeKey, seriesModel); + var resValue = curvenessList[edgeIndex + len + parityCorrection]; // isNeedReverse, simple, force type need reverse the curveness in the junction of the forword and the opposite + + if (needReverse) { + // set as array may make the parity handle with the len of opposite + if (isArrayParam) { + if (autoCurvenessParams && autoCurvenessParams[0] === 0) { + return (len + parityCorrection) % 2 ? resValue : -resValue; + } else { + return ((len % 2 ? 0 : 1) + parityCorrection) % 2 ? resValue : -resValue; + } + } else { + return (len + parityCorrection) % 2 ? resValue : -resValue; + } + } else { + return curvenessList[edgeIndex + len + parityCorrection]; + } + } else { + return curvenessList[parityCorrection + edgeIndex]; + } + } + + function simpleLayout(seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && coordSys.type !== 'view') { + return; + } + + var graph = seriesModel.getGraph(); + graph.eachNode(function (node) { + var model = node.getModel(); + node.setLayout([+model.get('x'), +model.get('y')]); + }); + simpleLayoutEdge(graph, seriesModel); + } + function simpleLayoutEdge(graph, seriesModel) { + graph.eachEdge(function (edge, index) { + var curveness = retrieve3(edge.getModel().get(['lineStyle', 'curveness']), -getCurvenessForEdge(edge, seriesModel, index, true), 0); + var p1 = clone$1(edge.node1.getLayout()); + var p2 = clone$1(edge.node2.getLayout()); + var points = [p1, p2]; + + if (+curveness) { + points.push([(p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * curveness, (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * curveness]); + } + + edge.setLayout(points); + }); + } + + function graphSimpleLayout(ecModel, api) { + ecModel.eachSeriesByType('graph', function (seriesModel) { + var layout = seriesModel.get('layout'); + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && coordSys.type !== 'view') { + var data_1 = seriesModel.getData(); + var dimensions_1 = []; + each(coordSys.dimensions, function (coordDim) { + dimensions_1 = dimensions_1.concat(data_1.mapDimensionsAll(coordDim)); + }); + + for (var dataIndex = 0; dataIndex < data_1.count(); dataIndex++) { + var value = []; + var hasValue = false; + + for (var i = 0; i < dimensions_1.length; i++) { + var val = data_1.get(dimensions_1[i], dataIndex); + + if (!isNaN(val)) { + hasValue = true; + } + + value.push(val); + } + + if (hasValue) { + data_1.setItemLayout(dataIndex, coordSys.dataToPoint(value)); + } else { + // Also {Array.}, not undefined to avoid if...else... statement + data_1.setItemLayout(dataIndex, [NaN, NaN]); + } + } + + simpleLayoutEdge(data_1.graph, seriesModel); + } else if (!layout || layout === 'none') { + simpleLayout(seriesModel); + } + }); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function getNodeGlobalScale(seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys.type !== 'view') { + return 1; + } + + var nodeScaleRatio = seriesModel.option.nodeScaleRatio; + var groupZoom = coordSys.scaleX; // Scale node when zoom changes + + var roamZoom = coordSys.getZoom(); + var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1; + return nodeScale / groupZoom; + } + function getSymbolSize(node) { + var symbolSize = node.getVisual('symbolSize'); + + if (symbolSize instanceof Array) { + symbolSize = (symbolSize[0] + symbolSize[1]) / 2; + } + + return +symbolSize; + } + + var PI$6 = Math.PI; + var _symbolRadiansHalf = []; + /** + * `basedOn` can be: + * 'value': + * This layout is not accurate and have same bad case. For example, + * if the min value is very smaller than the max value, the nodes + * with the min value probably overlap even though there is enough + * space to layout them. So we only use this approach in the as the + * init layout of the force layout. + * FIXME + * Probably we do not need this method any more but use + * `basedOn: 'symbolSize'` in force layout if + * delay its init operations to GraphView. + * 'symbolSize': + * This approach work only if all of the symbol size calculated. + * That is, the progressive rendering is not applied to graph. + * FIXME + * If progressive rendering is applied to graph some day, + * probably we have to use `basedOn: 'value'`. + */ + + function circularLayout(seriesModel, basedOn) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && coordSys.type !== 'view') { + return; + } + + var rect = coordSys.getBoundingRect(); + var nodeData = seriesModel.getData(); + var graph = nodeData.graph; + var cx = rect.width / 2 + rect.x; + var cy = rect.height / 2 + rect.y; + var r = Math.min(rect.width, rect.height) / 2; + var count = nodeData.count(); + nodeData.setLayout({ + cx: cx, + cy: cy + }); + + if (!count) { + return; + } + + _layoutNodesBasedOn[basedOn](seriesModel, graph, nodeData, r, cx, cy, count); + + graph.eachEdge(function (edge, index) { + var curveness = retrieve3(edge.getModel().get(['lineStyle', 'curveness']), getCurvenessForEdge(edge, seriesModel, index), 0); + var p1 = clone$1(edge.node1.getLayout()); + var p2 = clone$1(edge.node2.getLayout()); + var cp1; + var x12 = (p1[0] + p2[0]) / 2; + var y12 = (p1[1] + p2[1]) / 2; + + if (+curveness) { + curveness *= 3; + cp1 = [cx * curveness + x12 * (1 - curveness), cy * curveness + y12 * (1 - curveness)]; + } + + edge.setLayout([p1, p2, cp1]); + }); + } + var _layoutNodesBasedOn = { + value: function (seriesModel, graph, nodeData, r, cx, cy, count) { + var angle = 0; + var sum = nodeData.getSum('value'); + var unitAngle = Math.PI * 2 / (sum || count); + graph.eachNode(function (node) { + var value = node.getValue('value'); + var radianHalf = unitAngle * (sum ? value : 1) / 2; + angle += radianHalf; + node.setLayout([r * Math.cos(angle) + cx, r * Math.sin(angle) + cy]); + angle += radianHalf; + }); + }, + symbolSize: function (seriesModel, graph, nodeData, r, cx, cy, count) { + var sumRadian = 0; + _symbolRadiansHalf.length = count; + var nodeScale = getNodeGlobalScale(seriesModel); + graph.eachNode(function (node) { + var symbolSize = getSymbolSize(node); // Normally this case will not happen, but we still add + // some the defensive code (2px is an arbitrary value). + + isNaN(symbolSize) && (symbolSize = 2); + symbolSize < 0 && (symbolSize = 0); + symbolSize *= nodeScale; + var symbolRadianHalf = Math.asin(symbolSize / 2 / r); // when `symbolSize / 2` is bigger than `r`. + + isNaN(symbolRadianHalf) && (symbolRadianHalf = PI$6 / 2); + _symbolRadiansHalf[node.dataIndex] = symbolRadianHalf; + sumRadian += symbolRadianHalf * 2; + }); + var halfRemainRadian = (2 * PI$6 - sumRadian) / count / 2; + var angle = 0; + graph.eachNode(function (node) { + var radianHalf = halfRemainRadian + _symbolRadiansHalf[node.dataIndex]; + angle += radianHalf; + node.setLayout([r * Math.cos(angle) + cx, r * Math.sin(angle) + cy]); + angle += radianHalf; + }); + } + }; + + function graphCircularLayout(ecModel) { + ecModel.eachSeriesByType('graph', function (seriesModel) { + if (seriesModel.get('layout') === 'circular') { + circularLayout(seriesModel, 'symbolSize'); + } + }); + } + + var scaleAndAdd$1 = scaleAndAdd; // function adjacentNode(n, e) { + // return e.n1 === n ? e.n2 : e.n1; + // } + + function forceLayout(inNodes, inEdges, opts) { + var nodes = inNodes; + var edges = inEdges; + var rect = opts.rect; + var width = rect.width; + var height = rect.height; + var center = [rect.x + width / 2, rect.y + height / 2]; // let scale = opts.scale || 1; + + var gravity = opts.gravity == null ? 0.1 : opts.gravity; // for (let i = 0; i < edges.length; i++) { + // let e = edges[i]; + // let n1 = e.n1; + // let n2 = e.n2; + // n1.edges = n1.edges || []; + // n2.edges = n2.edges || []; + // n1.edges.push(e); + // n2.edges.push(e); + // } + // Init position + + for (var i = 0; i < nodes.length; i++) { + var n = nodes[i]; + + if (!n.p) { + n.p = create(width * (Math.random() - 0.5) + center[0], height * (Math.random() - 0.5) + center[1]); + } + + n.pp = clone$1(n.p); + n.edges = null; + } // Formula in 'Graph Drawing by Force-directed Placement' + // let k = scale * Math.sqrt(width * height / nodes.length); + // let k2 = k * k; + + + var initialFriction = opts.friction == null ? 0.6 : opts.friction; + var friction = initialFriction; + var beforeStepCallback; + var afterStepCallback; + return { + warmUp: function () { + friction = initialFriction * 0.8; + }, + setFixed: function (idx) { + nodes[idx].fixed = true; + }, + setUnfixed: function (idx) { + nodes[idx].fixed = false; + }, + + /** + * Before step hook + */ + beforeStep: function (cb) { + beforeStepCallback = cb; + }, + + /** + * After step hook + */ + afterStep: function (cb) { + afterStepCallback = cb; + }, + + /** + * Some formulas were originally copied from "d3.js" + * https://github.com/d3/d3/blob/b516d77fb8566b576088e73410437494717ada26/src/layout/force.js + * with some modifications made for this project. + * See the license statement at the head of this file. + */ + step: function (cb) { + beforeStepCallback && beforeStepCallback(nodes, edges); + var v12 = []; + var nLen = nodes.length; + + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + + if (e.ignoreForceLayout) { + continue; + } + + var n1 = e.n1; + var n2 = e.n2; + sub(v12, n2.p, n1.p); + var d = len(v12) - e.d; + var w = n2.w / (n1.w + n2.w); + + if (isNaN(w)) { + w = 0; + } + + normalize(v12, v12); + !n1.fixed && scaleAndAdd$1(n1.p, n1.p, v12, w * d * friction); + !n2.fixed && scaleAndAdd$1(n2.p, n2.p, v12, -(1 - w) * d * friction); + } // Gravity + + + for (var i = 0; i < nLen; i++) { + var n = nodes[i]; + + if (!n.fixed) { + sub(v12, center, n.p); // let d = vec2.len(v12); + // vec2.scale(v12, v12, 1 / d); + // let gravityFactor = gravity; + + scaleAndAdd$1(n.p, n.p, v12, gravity * friction); + } + } // Repulsive + // PENDING + + + for (var i = 0; i < nLen; i++) { + var n1 = nodes[i]; + + for (var j = i + 1; j < nLen; j++) { + var n2 = nodes[j]; + sub(v12, n2.p, n1.p); + var d = len(v12); + + if (d === 0) { + // Random repulse + set(v12, Math.random() - 0.5, Math.random() - 0.5); + d = 1; + } + + var repFact = (n1.rep + n2.rep) / d / d; + !n1.fixed && scaleAndAdd$1(n1.pp, n1.pp, v12, repFact); + !n2.fixed && scaleAndAdd$1(n2.pp, n2.pp, v12, -repFact); + } + } + + var v = []; + + for (var i = 0; i < nLen; i++) { + var n = nodes[i]; + + if (!n.fixed) { + sub(v, n.p, n.pp); + scaleAndAdd$1(n.p, n.p, v, friction); + copy(n.pp, n.p); + } + } + + friction = friction * 0.992; + var finished = friction < 0.01; + afterStepCallback && afterStepCallback(nodes, edges, finished); + cb && cb(finished); + } + }; + } + + function graphForceLayout(ecModel) { + ecModel.eachSeriesByType('graph', function (graphSeries) { + var coordSys = graphSeries.coordinateSystem; + + if (coordSys && coordSys.type !== 'view') { + return; + } + + if (graphSeries.get('layout') === 'force') { + var preservedPoints_1 = graphSeries.preservedPoints || {}; + var graph_1 = graphSeries.getGraph(); + var nodeData_1 = graph_1.data; + var edgeData = graph_1.edgeData; + var forceModel = graphSeries.getModel('force'); + var initLayout = forceModel.get('initLayout'); + + if (graphSeries.preservedPoints) { + nodeData_1.each(function (idx) { + var id = nodeData_1.getId(idx); + nodeData_1.setItemLayout(idx, preservedPoints_1[id] || [NaN, NaN]); + }); + } else if (!initLayout || initLayout === 'none') { + simpleLayout(graphSeries); + } else if (initLayout === 'circular') { + circularLayout(graphSeries, 'value'); + } + + var nodeDataExtent_1 = nodeData_1.getDataExtent('value'); + var edgeDataExtent_1 = edgeData.getDataExtent('value'); // let edgeDataExtent = edgeData.getDataExtent('value'); + + var repulsion = forceModel.get('repulsion'); + var edgeLength = forceModel.get('edgeLength'); + var repulsionArr_1 = isArray(repulsion) ? repulsion : [repulsion, repulsion]; + var edgeLengthArr_1 = isArray(edgeLength) ? edgeLength : [edgeLength, edgeLength]; // Larger value has smaller length + + edgeLengthArr_1 = [edgeLengthArr_1[1], edgeLengthArr_1[0]]; + var nodes_1 = nodeData_1.mapArray('value', function (value, idx) { + var point = nodeData_1.getItemLayout(idx); + var rep = linearMap(value, nodeDataExtent_1, repulsionArr_1); + + if (isNaN(rep)) { + rep = (repulsionArr_1[0] + repulsionArr_1[1]) / 2; + } + + return { + w: rep, + rep: rep, + fixed: nodeData_1.getItemModel(idx).get('fixed'), + p: !point || isNaN(point[0]) || isNaN(point[1]) ? null : point + }; + }); + var edges = edgeData.mapArray('value', function (value, idx) { + var edge = graph_1.getEdgeByIndex(idx); + var d = linearMap(value, edgeDataExtent_1, edgeLengthArr_1); + + if (isNaN(d)) { + d = (edgeLengthArr_1[0] + edgeLengthArr_1[1]) / 2; + } + + var edgeModel = edge.getModel(); + var curveness = retrieve3(edge.getModel().get(['lineStyle', 'curveness']), -getCurvenessForEdge(edge, graphSeries, idx, true), 0); + return { + n1: nodes_1[edge.node1.dataIndex], + n2: nodes_1[edge.node2.dataIndex], + d: d, + curveness: curveness, + ignoreForceLayout: edgeModel.get('ignoreForceLayout') + }; + }); // let coordSys = graphSeries.coordinateSystem; + + var rect = coordSys.getBoundingRect(); + var forceInstance = forceLayout(nodes_1, edges, { + rect: rect, + gravity: forceModel.get('gravity'), + friction: forceModel.get('friction') + }); + forceInstance.beforeStep(function (nodes, edges) { + for (var i = 0, l = nodes.length; i < l; i++) { + if (nodes[i].fixed) { + // Write back to layout instance + copy(nodes[i].p, graph_1.getNodeByIndex(i).getLayout()); + } + } + }); + forceInstance.afterStep(function (nodes, edges, stopped) { + for (var i = 0, l = nodes.length; i < l; i++) { + if (!nodes[i].fixed) { + graph_1.getNodeByIndex(i).setLayout(nodes[i].p); + } + + preservedPoints_1[nodeData_1.getId(i)] = nodes[i].p; + } + + for (var i = 0, l = edges.length; i < l; i++) { + var e = edges[i]; + var edge = graph_1.getEdgeByIndex(i); + var p1 = e.n1.p; + var p2 = e.n2.p; + var points = edge.getLayout(); + points = points ? points.slice() : []; + points[0] = points[0] || []; + points[1] = points[1] || []; + copy(points[0], p1); + copy(points[1], p2); + + if (+e.curveness) { + points[2] = [(p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * e.curveness, (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * e.curveness]; + } + + edge.setLayout(points); + } + }); + graphSeries.forceLayout = forceInstance; + graphSeries.preservedPoints = preservedPoints_1; // Step to get the layout + + forceInstance.step(); + } else { + // Remove prev injected forceLayout instance + graphSeries.forceLayout = null; + } + }); + } + + function getViewRect$2(seriesModel, api, aspect) { + var option = extend(seriesModel.getBoxLayoutParams(), { + aspect: aspect + }); + return getLayoutRect(option, { + width: api.getWidth(), + height: api.getHeight() + }); + } + + function createViewCoordSys(ecModel, api) { + var viewList = []; + ecModel.eachSeriesByType('graph', function (seriesModel) { + var coordSysType = seriesModel.get('coordinateSystem'); + + if (!coordSysType || coordSysType === 'view') { + var data_1 = seriesModel.getData(); + var positions = data_1.mapArray(function (idx) { + var itemModel = data_1.getItemModel(idx); + return [+itemModel.get('x'), +itemModel.get('y')]; + }); + var min = []; + var max = []; + fromPoints(positions, min, max); // If width or height is 0 + + if (max[0] - min[0] === 0) { + max[0] += 1; + min[0] -= 1; + } + + if (max[1] - min[1] === 0) { + max[1] += 1; + min[1] -= 1; + } + + var aspect = (max[0] - min[0]) / (max[1] - min[1]); // FIXME If get view rect after data processed? + + var viewRect = getViewRect$2(seriesModel, api, aspect); // Position may be NaN, use view rect instead + + if (isNaN(aspect)) { + min = [viewRect.x, viewRect.y]; + max = [viewRect.x + viewRect.width, viewRect.y + viewRect.height]; + } + + var bbWidth = max[0] - min[0]; + var bbHeight = max[1] - min[1]; + var viewWidth = viewRect.width; + var viewHeight = viewRect.height; + var viewCoordSys = seriesModel.coordinateSystem = new View(); + viewCoordSys.zoomLimit = seriesModel.get('scaleLimit'); + viewCoordSys.setBoundingRect(min[0], min[1], bbWidth, bbHeight); + viewCoordSys.setViewRect(viewRect.x, viewRect.y, viewWidth, viewHeight); // Update roam info + + viewCoordSys.setCenter(seriesModel.get('center')); + viewCoordSys.setZoom(seriesModel.get('zoom')); + viewList.push(viewCoordSys); + } + }); + return viewList; + } + + var straightLineProto = Line.prototype; + var bezierCurveProto = BezierCurve.prototype; + + var StraightLineShape = + /** @class */ + function () { + function StraightLineShape() { + // Start point + this.x1 = 0; + this.y1 = 0; // End point + + this.x2 = 0; + this.y2 = 0; + this.percent = 1; + } + + return StraightLineShape; + }(); + + var CurveShape = + /** @class */ + function (_super) { + __extends(CurveShape, _super); + + function CurveShape() { + return _super !== null && _super.apply(this, arguments) || this; + } + + return CurveShape; + }(StraightLineShape); + + function isStraightLine(shape) { + return isNaN(+shape.cpx1) || isNaN(+shape.cpy1); + } + + var ECLinePath = + /** @class */ + function (_super) { + __extends(ECLinePath, _super); + + function ECLinePath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'ec-line'; + return _this; + } + + ECLinePath.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + + ECLinePath.prototype.getDefaultShape = function () { + return new StraightLineShape(); + }; + + ECLinePath.prototype.buildPath = function (ctx, shape) { + if (isStraightLine(shape)) { + straightLineProto.buildPath.call(this, ctx, shape); + } else { + bezierCurveProto.buildPath.call(this, ctx, shape); + } + }; + + ECLinePath.prototype.pointAt = function (t) { + if (isStraightLine(this.shape)) { + return straightLineProto.pointAt.call(this, t); + } else { + return bezierCurveProto.pointAt.call(this, t); + } + }; + + ECLinePath.prototype.tangentAt = function (t) { + var shape = this.shape; + var p = isStraightLine(shape) ? [shape.x2 - shape.x1, shape.y2 - shape.y1] : bezierCurveProto.tangentAt.call(this, t); + return normalize(p, p); + }; + + return ECLinePath; + }(Path); + + var SYMBOL_CATEGORIES = ['fromSymbol', 'toSymbol']; + + function makeSymbolTypeKey(symbolCategory) { + return '_' + symbolCategory + 'Type'; + } + /** + * @inner + */ + + + function createSymbol$1(name, lineData, idx) { + var symbolType = lineData.getItemVisual(idx, name); + + if (!symbolType || symbolType === 'none') { + return; + } + + var symbolSize = lineData.getItemVisual(idx, name + 'Size'); + var symbolRotate = lineData.getItemVisual(idx, name + 'Rotate'); + var symbolOffset = lineData.getItemVisual(idx, name + 'Offset'); + var symbolKeepAspect = lineData.getItemVisual(idx, name + 'KeepAspect'); + var symbolSizeArr = normalizeSymbolSize(symbolSize); + var symbolOffsetArr = normalizeSymbolOffset(symbolOffset || 0, symbolSizeArr); + var symbolPath = createSymbol(symbolType, -symbolSizeArr[0] / 2 + symbolOffsetArr[0], -symbolSizeArr[1] / 2 + symbolOffsetArr[1], symbolSizeArr[0], symbolSizeArr[1], null, symbolKeepAspect); + symbolPath.__specifiedRotation = symbolRotate == null || isNaN(symbolRotate) ? void 0 : +symbolRotate * Math.PI / 180 || 0; + symbolPath.name = name; + return symbolPath; + } + + function createLine(points) { + var line = new ECLinePath({ + name: 'line', + subPixelOptimize: true + }); + setLinePoints(line.shape, points); + return line; + } + + function setLinePoints(targetShape, points) { + targetShape.x1 = points[0][0]; + targetShape.y1 = points[0][1]; + targetShape.x2 = points[1][0]; + targetShape.y2 = points[1][1]; + targetShape.percent = 1; + var cp1 = points[2]; + + if (cp1) { + targetShape.cpx1 = cp1[0]; + targetShape.cpy1 = cp1[1]; + } else { + targetShape.cpx1 = NaN; + targetShape.cpy1 = NaN; + } + } + + var Line$1 = + /** @class */ + function (_super) { + __extends(Line, _super); + + function Line(lineData, idx, seriesScope) { + var _this = _super.call(this) || this; + + _this._createLine(lineData, idx, seriesScope); + + return _this; + } + + Line.prototype._createLine = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + var linePoints = lineData.getItemLayout(idx); + var line = createLine(linePoints); + line.shape.percent = 0; + initProps(line, { + shape: { + percent: 1 + } + }, seriesModel, idx); + this.add(line); + each(SYMBOL_CATEGORIES, function (symbolCategory) { + var symbol = createSymbol$1(symbolCategory, lineData, idx); // symbols must added after line to make sure + // it will be updated after line#update. + // Or symbol position and rotation update in line#beforeUpdate will be one frame slow + + this.add(symbol); + this[makeSymbolTypeKey(symbolCategory)] = lineData.getItemVisual(idx, symbolCategory); + }, this); + + this._updateCommonStl(lineData, idx, seriesScope); + }; // TODO More strict on the List type in parameters? + + + Line.prototype.updateData = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + var line = this.childOfName('line'); + var linePoints = lineData.getItemLayout(idx); + var target = { + shape: {} + }; + setLinePoints(target.shape, linePoints); + updateProps(line, target, seriesModel, idx); + each(SYMBOL_CATEGORIES, function (symbolCategory) { + var symbolType = lineData.getItemVisual(idx, symbolCategory); + var key = makeSymbolTypeKey(symbolCategory); // Symbol changed + + if (this[key] !== symbolType) { + this.remove(this.childOfName(symbolCategory)); + var symbol = createSymbol$1(symbolCategory, lineData, idx); + this.add(symbol); + } + + this[key] = symbolType; + }, this); + + this._updateCommonStl(lineData, idx, seriesScope); + }; + + Line.prototype.getLinePath = function () { + return this.childAt(0); + }; + + Line.prototype._updateCommonStl = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + var line = this.childOfName('line'); + var emphasisLineStyle = seriesScope && seriesScope.emphasisLineStyle; + var blurLineStyle = seriesScope && seriesScope.blurLineStyle; + var selectLineStyle = seriesScope && seriesScope.selectLineStyle; + var labelStatesModels = seriesScope && seriesScope.labelStatesModels; + var emphasisDisabled = seriesScope && seriesScope.emphasisDisabled; + var focus = seriesScope && seriesScope.focus; + var blurScope = seriesScope && seriesScope.blurScope; // Optimization for large dataset + + if (!seriesScope || lineData.hasItemOption) { + var itemModel = lineData.getItemModel(idx); + var emphasisModel = itemModel.getModel('emphasis'); + emphasisLineStyle = emphasisModel.getModel('lineStyle').getLineStyle(); + blurLineStyle = itemModel.getModel(['blur', 'lineStyle']).getLineStyle(); + selectLineStyle = itemModel.getModel(['select', 'lineStyle']).getLineStyle(); + emphasisDisabled = emphasisModel.get('disabled'); + focus = emphasisModel.get('focus'); + blurScope = emphasisModel.get('blurScope'); + labelStatesModels = getLabelStatesModels(itemModel); + } + + var lineStyle = lineData.getItemVisual(idx, 'style'); + var visualColor = lineStyle.stroke; + line.useStyle(lineStyle); + line.style.fill = null; + line.style.strokeNoScale = true; + line.ensureState('emphasis').style = emphasisLineStyle; + line.ensureState('blur').style = blurLineStyle; + line.ensureState('select').style = selectLineStyle; // Update symbol + + each(SYMBOL_CATEGORIES, function (symbolCategory) { + var symbol = this.childOfName(symbolCategory); + + if (symbol) { + // Share opacity and color with line. + symbol.setColor(visualColor); + symbol.style.opacity = lineStyle.opacity; + + for (var i = 0; i < SPECIAL_STATES.length; i++) { + var stateName = SPECIAL_STATES[i]; + var lineState = line.getState(stateName); + + if (lineState) { + var lineStateStyle = lineState.style || {}; + var state = symbol.ensureState(stateName); + var stateStyle = state.style || (state.style = {}); + + if (lineStateStyle.stroke != null) { + stateStyle[symbol.__isEmptyBrush ? 'stroke' : 'fill'] = lineStateStyle.stroke; + } + + if (lineStateStyle.opacity != null) { + stateStyle.opacity = lineStateStyle.opacity; + } + } + } + + symbol.markRedraw(); + } + }, this); + var rawVal = seriesModel.getRawValue(idx); + setLabelStyle(this, labelStatesModels, { + labelDataIndex: idx, + labelFetcher: { + getFormattedLabel: function (dataIndex, stateName) { + return seriesModel.getFormattedLabel(dataIndex, stateName, lineData.dataType); + } + }, + inheritColor: visualColor || '#000', + defaultOpacity: lineStyle.opacity, + defaultText: (rawVal == null ? lineData.getName(idx) : isFinite(rawVal) ? round(rawVal) : rawVal) + '' + }); + var label = this.getTextContent(); // Always set `textStyle` even if `normalStyle.text` is null, because default + // values have to be set on `normalStyle`. + + if (label) { + var labelNormalModel = labelStatesModels.normal; + label.__align = label.style.align; + label.__verticalAlign = label.style.verticalAlign; // 'start', 'middle', 'end' + + label.__position = labelNormalModel.get('position') || 'middle'; + var distance = labelNormalModel.get('distance'); + + if (!isArray(distance)) { + distance = [distance, distance]; + } + + label.__labelDistance = distance; + } + + this.setTextConfig({ + position: null, + local: true, + inside: false // Can't be inside for stroke element. + + }); + toggleHoverEmphasis(this, focus, blurScope, emphasisDisabled); + }; + + Line.prototype.highlight = function () { + enterEmphasis(this); + }; + + Line.prototype.downplay = function () { + leaveEmphasis(this); + }; + + Line.prototype.updateLayout = function (lineData, idx) { + this.setLinePoints(lineData.getItemLayout(idx)); + }; + + Line.prototype.setLinePoints = function (points) { + var linePath = this.childOfName('line'); + setLinePoints(linePath.shape, points); + linePath.dirty(); + }; + + Line.prototype.beforeUpdate = function () { + var lineGroup = this; + var symbolFrom = lineGroup.childOfName('fromSymbol'); + var symbolTo = lineGroup.childOfName('toSymbol'); + var label = lineGroup.getTextContent(); // Quick reject + + if (!symbolFrom && !symbolTo && (!label || label.ignore)) { + return; + } + + var invScale = 1; + var parentNode = this.parent; + + while (parentNode) { + if (parentNode.scaleX) { + invScale /= parentNode.scaleX; + } + + parentNode = parentNode.parent; + } + + var line = lineGroup.childOfName('line'); // If line not changed + // FIXME Parent scale changed + + if (!this.__dirty && !line.__dirty) { + return; + } + + var percent = line.shape.percent; + var fromPos = line.pointAt(0); + var toPos = line.pointAt(percent); + var d = sub([], toPos, fromPos); + normalize(d, d); + + function setSymbolRotation(symbol, percent) { + // Fix #12388 + // when symbol is set to be 'arrow' in markLine, + // symbolRotate value will be ignored, and compulsively use tangent angle. + // rotate by default if symbol rotation is not specified + var specifiedRotation = symbol.__specifiedRotation; + + if (specifiedRotation == null) { + var tangent = line.tangentAt(percent); + symbol.attr('rotation', (percent === 1 ? -1 : 1) * Math.PI / 2 - Math.atan2(tangent[1], tangent[0])); + } else { + symbol.attr('rotation', specifiedRotation); + } + } + + if (symbolFrom) { + symbolFrom.setPosition(fromPos); + setSymbolRotation(symbolFrom, 0); + symbolFrom.scaleX = symbolFrom.scaleY = invScale * percent; + symbolFrom.markRedraw(); + } + + if (symbolTo) { + symbolTo.setPosition(toPos); + setSymbolRotation(symbolTo, 1); + symbolTo.scaleX = symbolTo.scaleY = invScale * percent; + symbolTo.markRedraw(); + } + + if (label && !label.ignore) { + label.x = label.y = 0; + label.originX = label.originY = 0; + var textAlign = void 0; + var textVerticalAlign = void 0; + var distance = label.__labelDistance; + var distanceX = distance[0] * invScale; + var distanceY = distance[1] * invScale; + var halfPercent = percent / 2; + var tangent = line.tangentAt(halfPercent); + var n = [tangent[1], -tangent[0]]; + var cp = line.pointAt(halfPercent); + + if (n[1] > 0) { + n[0] = -n[0]; + n[1] = -n[1]; + } + + var dir = tangent[0] < 0 ? -1 : 1; + + if (label.__position !== 'start' && label.__position !== 'end') { + var rotation = -Math.atan2(tangent[1], tangent[0]); + + if (toPos[0] < fromPos[0]) { + rotation = Math.PI + rotation; + } + + label.rotation = rotation; + } + + var dy = void 0; + + switch (label.__position) { + case 'insideStartTop': + case 'insideMiddleTop': + case 'insideEndTop': + case 'middle': + dy = -distanceY; + textVerticalAlign = 'bottom'; + break; + + case 'insideStartBottom': + case 'insideMiddleBottom': + case 'insideEndBottom': + dy = distanceY; + textVerticalAlign = 'top'; + break; + + default: + dy = 0; + textVerticalAlign = 'middle'; + } + + switch (label.__position) { + case 'end': + label.x = d[0] * distanceX + toPos[0]; + label.y = d[1] * distanceY + toPos[1]; + textAlign = d[0] > 0.8 ? 'left' : d[0] < -0.8 ? 'right' : 'center'; + textVerticalAlign = d[1] > 0.8 ? 'top' : d[1] < -0.8 ? 'bottom' : 'middle'; + break; + + case 'start': + label.x = -d[0] * distanceX + fromPos[0]; + label.y = -d[1] * distanceY + fromPos[1]; + textAlign = d[0] > 0.8 ? 'right' : d[0] < -0.8 ? 'left' : 'center'; + textVerticalAlign = d[1] > 0.8 ? 'bottom' : d[1] < -0.8 ? 'top' : 'middle'; + break; + + case 'insideStartTop': + case 'insideStart': + case 'insideStartBottom': + label.x = distanceX * dir + fromPos[0]; + label.y = fromPos[1] + dy; + textAlign = tangent[0] < 0 ? 'right' : 'left'; + label.originX = -distanceX * dir; + label.originY = -dy; + break; + + case 'insideMiddleTop': + case 'insideMiddle': + case 'insideMiddleBottom': + case 'middle': + label.x = cp[0]; + label.y = cp[1] + dy; + textAlign = 'center'; + label.originY = -dy; + break; + + case 'insideEndTop': + case 'insideEnd': + case 'insideEndBottom': + label.x = -distanceX * dir + toPos[0]; + label.y = toPos[1] + dy; + textAlign = tangent[0] >= 0 ? 'right' : 'left'; + label.originX = distanceX * dir; + label.originY = -dy; + break; + } + + label.scaleX = label.scaleY = invScale; + label.setStyle({ + // Use the user specified text align and baseline first + verticalAlign: label.__verticalAlign || textVerticalAlign, + align: label.__align || textAlign + }); + } + }; + + return Line; + }(Group); + + var LineDraw = + /** @class */ + function () { + function LineDraw(LineCtor) { + this.group = new Group(); + this._LineCtor = LineCtor || Line$1; + } + + LineDraw.prototype.updateData = function (lineData) { + var _this = this; // Remove progressive els. + + + this._progressiveEls = null; + var lineDraw = this; + var group = lineDraw.group; + var oldLineData = lineDraw._lineData; + lineDraw._lineData = lineData; // There is no oldLineData only when first rendering or switching from + // stream mode to normal mode, where previous elements should be removed. + + if (!oldLineData) { + group.removeAll(); + } + + var seriesScope = makeSeriesScope$1(lineData); + lineData.diff(oldLineData).add(function (idx) { + _this._doAdd(lineData, idx, seriesScope); + }).update(function (newIdx, oldIdx) { + _this._doUpdate(oldLineData, lineData, oldIdx, newIdx, seriesScope); + }).remove(function (idx) { + group.remove(oldLineData.getItemGraphicEl(idx)); + }).execute(); + }; + + LineDraw.prototype.updateLayout = function () { + var lineData = this._lineData; // Do not support update layout in incremental mode. + + if (!lineData) { + return; + } + + lineData.eachItemGraphicEl(function (el, idx) { + el.updateLayout(lineData, idx); + }, this); + }; + + LineDraw.prototype.incrementalPrepareUpdate = function (lineData) { + this._seriesScope = makeSeriesScope$1(lineData); + this._lineData = null; + this.group.removeAll(); + }; + + LineDraw.prototype.incrementalUpdate = function (taskParams, lineData) { + this._progressiveEls = []; + + function updateIncrementalAndHover(el) { + if (!el.isGroup && !isEffectObject(el)) { + el.incremental = true; + el.ensureState('emphasis').hoverLayer = true; + } + } + + for (var idx = taskParams.start; idx < taskParams.end; idx++) { + var itemLayout = lineData.getItemLayout(idx); + + if (lineNeedsDraw(itemLayout)) { + var el = new this._LineCtor(lineData, idx, this._seriesScope); + el.traverse(updateIncrementalAndHover); + this.group.add(el); + lineData.setItemGraphicEl(idx, el); + + this._progressiveEls.push(el); + } + } + }; + + LineDraw.prototype.remove = function () { + this.group.removeAll(); + }; + + LineDraw.prototype.eachRendered = function (cb) { + traverseElements(this._progressiveEls || this.group, cb); + }; + + LineDraw.prototype._doAdd = function (lineData, idx, seriesScope) { + var itemLayout = lineData.getItemLayout(idx); + + if (!lineNeedsDraw(itemLayout)) { + return; + } + + var el = new this._LineCtor(lineData, idx, seriesScope); + lineData.setItemGraphicEl(idx, el); + this.group.add(el); + }; + + LineDraw.prototype._doUpdate = function (oldLineData, newLineData, oldIdx, newIdx, seriesScope) { + var itemEl = oldLineData.getItemGraphicEl(oldIdx); + + if (!lineNeedsDraw(newLineData.getItemLayout(newIdx))) { + this.group.remove(itemEl); + return; + } + + if (!itemEl) { + itemEl = new this._LineCtor(newLineData, newIdx, seriesScope); + } else { + itemEl.updateData(newLineData, newIdx, seriesScope); + } + + newLineData.setItemGraphicEl(newIdx, itemEl); + this.group.add(itemEl); + }; + + return LineDraw; + }(); + + function isEffectObject(el) { + return el.animators && el.animators.length > 0; + } + + function makeSeriesScope$1(lineData) { + var hostModel = lineData.hostModel; + var emphasisModel = hostModel.getModel('emphasis'); + return { + lineStyle: hostModel.getModel('lineStyle').getLineStyle(), + emphasisLineStyle: emphasisModel.getModel(['lineStyle']).getLineStyle(), + blurLineStyle: hostModel.getModel(['blur', 'lineStyle']).getLineStyle(), + selectLineStyle: hostModel.getModel(['select', 'lineStyle']).getLineStyle(), + emphasisDisabled: emphasisModel.get('disabled'), + blurScope: emphasisModel.get('blurScope'), + focus: emphasisModel.get('focus'), + labelStatesModels: getLabelStatesModels(hostModel) + }; + } + + function isPointNaN(pt) { + return isNaN(pt[0]) || isNaN(pt[1]); + } + + function lineNeedsDraw(pts) { + return pts && !isPointNaN(pts[0]) && !isPointNaN(pts[1]); + } + + var v1 = []; + var v2 = []; + var v3 = []; + var quadraticAt$1 = quadraticAt; + var v2DistSquare = distSquare; + var mathAbs$2 = Math.abs; + + function intersectCurveCircle(curvePoints, center, radius) { + var p0 = curvePoints[0]; + var p1 = curvePoints[1]; + var p2 = curvePoints[2]; + var d = Infinity; + var t; + var radiusSquare = radius * radius; + var interval = 0.1; + + for (var _t = 0.1; _t <= 0.9; _t += 0.1) { + v1[0] = quadraticAt$1(p0[0], p1[0], p2[0], _t); + v1[1] = quadraticAt$1(p0[1], p1[1], p2[1], _t); + var diff = mathAbs$2(v2DistSquare(v1, center) - radiusSquare); + + if (diff < d) { + d = diff; + t = _t; + } + } // Assume the segment is monotone,Find root through Bisection method + // At most 32 iteration + + + for (var i = 0; i < 32; i++) { + // let prev = t - interval; + var next = t + interval; // v1[0] = quadraticAt(p0[0], p1[0], p2[0], prev); + // v1[1] = quadraticAt(p0[1], p1[1], p2[1], prev); + + v2[0] = quadraticAt$1(p0[0], p1[0], p2[0], t); + v2[1] = quadraticAt$1(p0[1], p1[1], p2[1], t); + v3[0] = quadraticAt$1(p0[0], p1[0], p2[0], next); + v3[1] = quadraticAt$1(p0[1], p1[1], p2[1], next); + var diff = v2DistSquare(v2, center) - radiusSquare; + + if (mathAbs$2(diff) < 1e-2) { + break; + } // let prevDiff = v2DistSquare(v1, center) - radiusSquare; + + + var nextDiff = v2DistSquare(v3, center) - radiusSquare; + interval /= 2; + + if (diff < 0) { + if (nextDiff >= 0) { + t = t + interval; + } else { + t = t - interval; + } + } else { + if (nextDiff >= 0) { + t = t - interval; + } else { + t = t + interval; + } + } + } + + return t; + } // Adjust edge to avoid + + + function adjustEdge(graph, scale) { + var tmp0 = []; + var quadraticSubdivide$1 = quadraticSubdivide; + var pts = [[], [], []]; + var pts2 = [[], []]; + var v = []; + scale /= 2; + graph.eachEdge(function (edge, idx) { + var linePoints = edge.getLayout(); + var fromSymbol = edge.getVisual('fromSymbol'); + var toSymbol = edge.getVisual('toSymbol'); + + if (!linePoints.__original) { + linePoints.__original = [clone$1(linePoints[0]), clone$1(linePoints[1])]; + + if (linePoints[2]) { + linePoints.__original.push(clone$1(linePoints[2])); + } + } + + var originalPoints = linePoints.__original; // Quadratic curve + + if (linePoints[2] != null) { + copy(pts[0], originalPoints[0]); + copy(pts[1], originalPoints[2]); + copy(pts[2], originalPoints[1]); + + if (fromSymbol && fromSymbol !== 'none') { + var symbolSize = getSymbolSize(edge.node1); + var t = intersectCurveCircle(pts, originalPoints[0], symbolSize * scale); // Subdivide and get the second + + quadraticSubdivide$1(pts[0][0], pts[1][0], pts[2][0], t, tmp0); + pts[0][0] = tmp0[3]; + pts[1][0] = tmp0[4]; + quadraticSubdivide$1(pts[0][1], pts[1][1], pts[2][1], t, tmp0); + pts[0][1] = tmp0[3]; + pts[1][1] = tmp0[4]; + } + + if (toSymbol && toSymbol !== 'none') { + var symbolSize = getSymbolSize(edge.node2); + var t = intersectCurveCircle(pts, originalPoints[1], symbolSize * scale); // Subdivide and get the first + + quadraticSubdivide$1(pts[0][0], pts[1][0], pts[2][0], t, tmp0); + pts[1][0] = tmp0[1]; + pts[2][0] = tmp0[2]; + quadraticSubdivide$1(pts[0][1], pts[1][1], pts[2][1], t, tmp0); + pts[1][1] = tmp0[1]; + pts[2][1] = tmp0[2]; + } // Copy back to layout + + + copy(linePoints[0], pts[0]); + copy(linePoints[1], pts[2]); + copy(linePoints[2], pts[1]); + } // Line + else { + copy(pts2[0], originalPoints[0]); + copy(pts2[1], originalPoints[1]); + sub(v, pts2[1], pts2[0]); + normalize(v, v); + + if (fromSymbol && fromSymbol !== 'none') { + var symbolSize = getSymbolSize(edge.node1); + scaleAndAdd(pts2[0], pts2[0], v, symbolSize * scale); + } + + if (toSymbol && toSymbol !== 'none') { + var symbolSize = getSymbolSize(edge.node2); + scaleAndAdd(pts2[1], pts2[1], v, -symbolSize * scale); + } + + copy(linePoints[0], pts2[0]); + copy(linePoints[1], pts2[1]); + } + }); + } + + function isViewCoordSys(coordSys) { + return coordSys.type === 'view'; + } + + var GraphView = + /** @class */ + function (_super) { + __extends(GraphView, _super); + + function GraphView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GraphView.type; + return _this; + } + + GraphView.prototype.init = function (ecModel, api) { + var symbolDraw = new SymbolDraw(); + var lineDraw = new LineDraw(); + var group = this.group; + this._controller = new RoamController(api.getZr()); + this._controllerHost = { + target: group + }; + group.add(symbolDraw.group); + group.add(lineDraw.group); + this._symbolDraw = symbolDraw; + this._lineDraw = lineDraw; + this._firstRender = true; + }; + + GraphView.prototype.render = function (seriesModel, ecModel, api) { + var _this = this; + + var coordSys = seriesModel.coordinateSystem; + this._model = seriesModel; + var symbolDraw = this._symbolDraw; + var lineDraw = this._lineDraw; + var group = this.group; + + if (isViewCoordSys(coordSys)) { + var groupNewProp = { + x: coordSys.x, + y: coordSys.y, + scaleX: coordSys.scaleX, + scaleY: coordSys.scaleY + }; + + if (this._firstRender) { + group.attr(groupNewProp); + } else { + updateProps(group, groupNewProp, seriesModel); + } + } // Fix edge contact point with node + + + adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel)); + var data = seriesModel.getData(); + symbolDraw.updateData(data); + var edgeData = seriesModel.getEdgeData(); // TODO: TYPE + + lineDraw.updateData(edgeData); + + this._updateNodeAndLinkScale(); + + this._updateController(seriesModel, ecModel, api); + + clearTimeout(this._layoutTimeout); + var forceLayout = seriesModel.forceLayout; + var layoutAnimation = seriesModel.get(['force', 'layoutAnimation']); + + if (forceLayout) { + this._startForceLayoutIteration(forceLayout, layoutAnimation); + } + + data.graph.eachNode(function (node) { + var idx = node.dataIndex; + var el = node.getGraphicEl(); + var itemModel = node.getModel(); + + if (!el) { + return; + } // Update draggable + + + el.off('drag').off('dragend'); + var draggable = itemModel.get('draggable'); + + if (draggable) { + el.on('drag', function () { + if (forceLayout) { + forceLayout.warmUp(); + !_this._layouting && _this._startForceLayoutIteration(forceLayout, layoutAnimation); + forceLayout.setFixed(idx); // Write position back to layout + + data.setItemLayout(idx, [el.x, el.y]); + } + }).on('dragend', function () { + if (forceLayout) { + forceLayout.setUnfixed(idx); + } + }); + } + + el.setDraggable(draggable && !!forceLayout); + var focus = itemModel.get(['emphasis', 'focus']); + + if (focus === 'adjacency') { + getECData(el).focus = node.getAdjacentDataIndices(); + } + }); + data.graph.eachEdge(function (edge) { + var el = edge.getGraphicEl(); + var focus = edge.getModel().get(['emphasis', 'focus']); + + if (!el) { + return; + } + + if (focus === 'adjacency') { + getECData(el).focus = { + edge: [edge.dataIndex], + node: [edge.node1.dataIndex, edge.node2.dataIndex] + }; + } + }); + var circularRotateLabel = seriesModel.get('layout') === 'circular' && seriesModel.get(['circular', 'rotateLabel']); + var cx = data.getLayout('cx'); + var cy = data.getLayout('cy'); + data.eachItemGraphicEl(function (el, idx) { + var itemModel = data.getItemModel(idx); + var labelRotate = itemModel.get(['label', 'rotate']) || 0; + var symbolPath = el.getSymbolPath(); + + if (circularRotateLabel) { + var pos = data.getItemLayout(idx); + var rad = Math.atan2(pos[1] - cy, pos[0] - cx); + + if (rad < 0) { + rad = Math.PI * 2 + rad; + } + + var isLeft = pos[0] < cx; + + if (isLeft) { + rad = rad - Math.PI; + } + + var textPosition = isLeft ? 'left' : 'right'; + symbolPath.setTextConfig({ + rotation: -rad, + position: textPosition, + origin: 'center' + }); + var emphasisState = symbolPath.ensureState('emphasis'); + extend(emphasisState.textConfig || (emphasisState.textConfig = {}), { + position: textPosition + }); + } else { + symbolPath.setTextConfig({ + rotation: labelRotate *= Math.PI / 180 + }); + } + }); + this._firstRender = false; + }; + + GraphView.prototype.dispose = function () { + this._controller && this._controller.dispose(); + this._controllerHost = null; + }; + + GraphView.prototype._startForceLayoutIteration = function (forceLayout, layoutAnimation) { + var self = this; + + (function step() { + forceLayout.step(function (stopped) { + self.updateLayout(self._model); + (self._layouting = !stopped) && (layoutAnimation ? self._layoutTimeout = setTimeout(step, 16) : step()); + }); + })(); + }; + + GraphView.prototype._updateController = function (seriesModel, ecModel, api) { + var _this = this; + + var controller = this._controller; + var controllerHost = this._controllerHost; + var group = this.group; + controller.setPointerChecker(function (e, x, y) { + var rect = group.getBoundingRect(); + rect.applyTransform(group.transform); + return rect.contain(x, y) && !onIrrelevantElement(e, api, seriesModel); + }); + + if (!isViewCoordSys(seriesModel.coordinateSystem)) { + controller.disable(); + return; + } + + controller.enable(seriesModel.get('roam')); + controllerHost.zoomLimit = seriesModel.get('scaleLimit'); + controllerHost.zoom = seriesModel.coordinateSystem.getZoom(); + controller.off('pan').off('zoom').on('pan', function (e) { + updateViewOnPan(controllerHost, e.dx, e.dy); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'graphRoam', + dx: e.dx, + dy: e.dy + }); + }).on('zoom', function (e) { + updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'graphRoam', + zoom: e.scale, + originX: e.originX, + originY: e.originY + }); + + _this._updateNodeAndLinkScale(); + + adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel)); + + _this._lineDraw.updateLayout(); // Only update label layout on zoom + + + api.updateLabelLayout(); + }); + }; + + GraphView.prototype._updateNodeAndLinkScale = function () { + var seriesModel = this._model; + var data = seriesModel.getData(); + var nodeScale = getNodeGlobalScale(seriesModel); + data.eachItemGraphicEl(function (el, idx) { + el && el.setSymbolScale(nodeScale); + }); + }; + + GraphView.prototype.updateLayout = function (seriesModel) { + adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel)); + + this._symbolDraw.updateLayout(); + + this._lineDraw.updateLayout(); + }; + + GraphView.prototype.remove = function (ecModel, api) { + this._symbolDraw && this._symbolDraw.remove(); + this._lineDraw && this._lineDraw.remove(); + }; + + GraphView.type = 'graph'; + return GraphView; + }(ChartView); + + function generateNodeKey(id) { + return '_EC_' + id; + } + + var Graph = + /** @class */ + function () { + function Graph(directed) { + this.type = 'graph'; + this.nodes = []; + this.edges = []; + this._nodesMap = {}; + /** + * @type {Object.} + * @private + */ + + this._edgesMap = {}; + this._directed = directed || false; + } + /** + * If is directed graph + */ + + + Graph.prototype.isDirected = function () { + return this._directed; + }; + /** + * Add a new node + */ + + Graph.prototype.addNode = function (id, dataIndex) { + id = id == null ? '' + dataIndex : '' + id; + var nodesMap = this._nodesMap; + + if (nodesMap[generateNodeKey(id)]) { + if ("development" !== 'production') { + console.error('Graph nodes have duplicate name or id'); + } + + return; + } + + var node = new GraphNode(id, dataIndex); + node.hostGraph = this; + this.nodes.push(node); + nodesMap[generateNodeKey(id)] = node; + return node; + }; + /** + * Get node by data index + */ + + Graph.prototype.getNodeByIndex = function (dataIndex) { + var rawIdx = this.data.getRawIndex(dataIndex); + return this.nodes[rawIdx]; + }; + /** + * Get node by id + */ + + Graph.prototype.getNodeById = function (id) { + return this._nodesMap[generateNodeKey(id)]; + }; + /** + * Add a new edge + */ + + Graph.prototype.addEdge = function (n1, n2, dataIndex) { + var nodesMap = this._nodesMap; + var edgesMap = this._edgesMap; // PNEDING + + if (isNumber(n1)) { + n1 = this.nodes[n1]; + } + + if (isNumber(n2)) { + n2 = this.nodes[n2]; + } + + if (!(n1 instanceof GraphNode)) { + n1 = nodesMap[generateNodeKey(n1)]; + } + + if (!(n2 instanceof GraphNode)) { + n2 = nodesMap[generateNodeKey(n2)]; + } + + if (!n1 || !n2) { + return; + } + + var key = n1.id + '-' + n2.id; + var edge = new GraphEdge(n1, n2, dataIndex); + edge.hostGraph = this; + + if (this._directed) { + n1.outEdges.push(edge); + n2.inEdges.push(edge); + } + + n1.edges.push(edge); + + if (n1 !== n2) { + n2.edges.push(edge); + } + + this.edges.push(edge); + edgesMap[key] = edge; + return edge; + }; + /** + * Get edge by data index + */ + + Graph.prototype.getEdgeByIndex = function (dataIndex) { + var rawIdx = this.edgeData.getRawIndex(dataIndex); + return this.edges[rawIdx]; + }; + /** + * Get edge by two linked nodes + */ + + Graph.prototype.getEdge = function (n1, n2) { + if (n1 instanceof GraphNode) { + n1 = n1.id; + } + + if (n2 instanceof GraphNode) { + n2 = n2.id; + } + + var edgesMap = this._edgesMap; + + if (this._directed) { + return edgesMap[n1 + '-' + n2]; + } else { + return edgesMap[n1 + '-' + n2] || edgesMap[n2 + '-' + n1]; + } + }; + /** + * Iterate all nodes + */ + + Graph.prototype.eachNode = function (cb, context) { + var nodes = this.nodes; + var len = nodes.length; + + for (var i = 0; i < len; i++) { + if (nodes[i].dataIndex >= 0) { + cb.call(context, nodes[i], i); + } + } + }; + /** + * Iterate all edges + */ + + Graph.prototype.eachEdge = function (cb, context) { + var edges = this.edges; + var len = edges.length; + + for (var i = 0; i < len; i++) { + if (edges[i].dataIndex >= 0 && edges[i].node1.dataIndex >= 0 && edges[i].node2.dataIndex >= 0) { + cb.call(context, edges[i], i); + } + } + }; + /** + * Breadth first traverse + * Return true to stop traversing + */ + + Graph.prototype.breadthFirstTraverse = function (cb, startNode, direction, context) { + if (!(startNode instanceof GraphNode)) { + startNode = this._nodesMap[generateNodeKey(startNode)]; + } + + if (!startNode) { + return; + } + + var edgeType = direction === 'out' ? 'outEdges' : direction === 'in' ? 'inEdges' : 'edges'; + + for (var i = 0; i < this.nodes.length; i++) { + this.nodes[i].__visited = false; + } + + if (cb.call(context, startNode, null)) { + return; + } + + var queue = [startNode]; + + while (queue.length) { + var currentNode = queue.shift(); + var edges = currentNode[edgeType]; + + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + var otherNode = e.node1 === currentNode ? e.node2 : e.node1; + + if (!otherNode.__visited) { + if (cb.call(context, otherNode, currentNode)) { + // Stop traversing + return; + } + + queue.push(otherNode); + otherNode.__visited = true; + } + } + } + }; + // depthFirstTraverse( + // cb, startNode, direction, context + // ) { + // }; + // Filter update + + Graph.prototype.update = function () { + var data = this.data; + var edgeData = this.edgeData; + var nodes = this.nodes; + var edges = this.edges; + + for (var i = 0, len = nodes.length; i < len; i++) { + nodes[i].dataIndex = -1; + } + + for (var i = 0, len = data.count(); i < len; i++) { + nodes[data.getRawIndex(i)].dataIndex = i; + } + + edgeData.filterSelf(function (idx) { + var edge = edges[edgeData.getRawIndex(idx)]; + return edge.node1.dataIndex >= 0 && edge.node2.dataIndex >= 0; + }); // Update edge + + for (var i = 0, len = edges.length; i < len; i++) { + edges[i].dataIndex = -1; + } + + for (var i = 0, len = edgeData.count(); i < len; i++) { + edges[edgeData.getRawIndex(i)].dataIndex = i; + } + }; + /** + * @return {module:echarts/data/Graph} + */ + + Graph.prototype.clone = function () { + var graph = new Graph(this._directed); + var nodes = this.nodes; + var edges = this.edges; + + for (var i = 0; i < nodes.length; i++) { + graph.addNode(nodes[i].id, nodes[i].dataIndex); + } + + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + graph.addEdge(e.node1.id, e.node2.id, e.dataIndex); + } + + return graph; + }; + return Graph; + }(); + + var GraphNode = + /** @class */ + function () { + function GraphNode(id, dataIndex) { + this.inEdges = []; + this.outEdges = []; + this.edges = []; + this.dataIndex = -1; + this.id = id == null ? '' : id; + this.dataIndex = dataIndex == null ? -1 : dataIndex; + } + /** + * @return {number} + */ + + + GraphNode.prototype.degree = function () { + return this.edges.length; + }; + /** + * @return {number} + */ + + + GraphNode.prototype.inDegree = function () { + return this.inEdges.length; + }; + /** + * @return {number} + */ + + + GraphNode.prototype.outDegree = function () { + return this.outEdges.length; + }; + + GraphNode.prototype.getModel = function (path) { + if (this.dataIndex < 0) { + return; + } + + var graph = this.hostGraph; + var itemModel = graph.data.getItemModel(this.dataIndex); + return itemModel.getModel(path); + }; + + GraphNode.prototype.getAdjacentDataIndices = function () { + var dataIndices = { + edge: [], + node: [] + }; + + for (var i = 0; i < this.edges.length; i++) { + var adjacentEdge = this.edges[i]; + + if (adjacentEdge.dataIndex < 0) { + continue; + } + + dataIndices.edge.push(adjacentEdge.dataIndex); + dataIndices.node.push(adjacentEdge.node1.dataIndex, adjacentEdge.node2.dataIndex); + } + + return dataIndices; + }; + + return GraphNode; + }(); + + var GraphEdge = + /** @class */ + function () { + function GraphEdge(n1, n2, dataIndex) { + this.dataIndex = -1; + this.node1 = n1; + this.node2 = n2; + this.dataIndex = dataIndex == null ? -1 : dataIndex; + } // eslint-disable-next-line @typescript-eslint/no-unused-vars + + + GraphEdge.prototype.getModel = function (path) { + if (this.dataIndex < 0) { + return; + } + + var graph = this.hostGraph; + var itemModel = graph.edgeData.getItemModel(this.dataIndex); + return itemModel.getModel(path); + }; + + GraphEdge.prototype.getAdjacentDataIndices = function () { + return { + edge: [this.dataIndex], + node: [this.node1.dataIndex, this.node2.dataIndex] + }; + }; + + return GraphEdge; + }(); + + function createGraphDataProxyMixin(hostName, dataName) { + return { + /** + * @param Default 'value'. can be 'a', 'b', 'c', 'd', 'e'. + */ + getValue: function (dimension) { + var data = this[hostName][dataName]; + return data.getStore().get(data.getDimensionIndex(dimension || 'value'), this.dataIndex); + }, + // TODO: TYPE stricter type. + setVisual: function (key, value) { + this.dataIndex >= 0 && this[hostName][dataName].setItemVisual(this.dataIndex, key, value); + }, + getVisual: function (key) { + return this[hostName][dataName].getItemVisual(this.dataIndex, key); + }, + setLayout: function (layout, merge) { + this.dataIndex >= 0 && this[hostName][dataName].setItemLayout(this.dataIndex, layout, merge); + }, + getLayout: function () { + return this[hostName][dataName].getItemLayout(this.dataIndex); + }, + getGraphicEl: function () { + return this[hostName][dataName].getItemGraphicEl(this.dataIndex); + }, + getRawIndex: function () { + return this[hostName][dataName].getRawIndex(this.dataIndex); + } + }; + } + mixin(GraphNode, createGraphDataProxyMixin('hostGraph', 'data')); + mixin(GraphEdge, createGraphDataProxyMixin('hostGraph', 'edgeData')); + + function createGraphFromNodeEdge(nodes, edges, seriesModel, directed, beforeLink) { + // ??? TODO + // support dataset? + var graph = new Graph(directed); + + for (var i = 0; i < nodes.length; i++) { + graph.addNode(retrieve( // Id, name, dataIndex + nodes[i].id, nodes[i].name, i), i); + } + + var linkNameList = []; + var validEdges = []; + var linkCount = 0; + + for (var i = 0; i < edges.length; i++) { + var link = edges[i]; + var source = link.source; + var target = link.target; // addEdge may fail when source or target not exists + + if (graph.addEdge(source, target, linkCount)) { + validEdges.push(link); + linkNameList.push(retrieve(convertOptionIdName(link.id, null), source + ' > ' + target)); + linkCount++; + } + } + + var coordSys = seriesModel.get('coordinateSystem'); + var nodeData; + + if (coordSys === 'cartesian2d' || coordSys === 'polar') { + nodeData = createSeriesData(nodes, seriesModel); + } else { + var coordSysCtor = CoordinateSystemManager.get(coordSys); + var coordDimensions = coordSysCtor ? coordSysCtor.dimensions || [] : []; // FIXME: Some geo do not need `value` dimenson, whereas `calendar` needs + // `value` dimension, but graph need `value` dimension. It's better to + // uniform this behavior. + + if (indexOf(coordDimensions, 'value') < 0) { + coordDimensions.concat(['value']); + } + + var dimensions = prepareSeriesDataSchema(nodes, { + coordDimensions: coordDimensions, + encodeDefine: seriesModel.getEncode() + }).dimensions; + nodeData = new SeriesData(dimensions, seriesModel); + nodeData.initData(nodes); + } + + var edgeData = new SeriesData(['value'], seriesModel); + edgeData.initData(validEdges, linkNameList); + beforeLink && beforeLink(nodeData, edgeData); + linkSeriesData({ + mainData: nodeData, + struct: graph, + structAttr: 'graph', + datas: { + node: nodeData, + edge: edgeData + }, + datasAttr: { + node: 'data', + edge: 'edgeData' + } + }); // Update dataIndex of nodes and edges because invalid edge may be removed + + graph.update(); + return graph; + } + + var GraphSeriesModel = + /** @class */ + function (_super) { + __extends(GraphSeriesModel, _super); + + function GraphSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GraphSeriesModel.type; + _this.hasSymbolVisual = true; + return _this; + } + + GraphSeriesModel.prototype.init = function (option) { + _super.prototype.init.apply(this, arguments); + + var self = this; + + function getCategoriesData() { + return self._categoriesData; + } // Provide data for legend select + + + this.legendVisualProvider = new LegendVisualProvider(getCategoriesData, getCategoriesData); + this.fillDataTextStyle(option.edges || option.links); + + this._updateCategoriesData(); + }; + + GraphSeriesModel.prototype.mergeOption = function (option) { + _super.prototype.mergeOption.apply(this, arguments); + + this.fillDataTextStyle(option.edges || option.links); + + this._updateCategoriesData(); + }; + + GraphSeriesModel.prototype.mergeDefaultAndTheme = function (option) { + _super.prototype.mergeDefaultAndTheme.apply(this, arguments); + + defaultEmphasis(option, 'edgeLabel', ['show']); + }; + + GraphSeriesModel.prototype.getInitialData = function (option, ecModel) { + var edges = option.edges || option.links || []; + var nodes = option.data || option.nodes || []; + var self = this; + + if (nodes && edges) { + // auto curveness + initCurvenessList(this); + var graph = createGraphFromNodeEdge(nodes, edges, this, true, beforeLink); + each(graph.edges, function (edge) { + createEdgeMapForCurveness(edge.node1, edge.node2, this, edge.dataIndex); + }, this); + return graph.data; + } + + function beforeLink(nodeData, edgeData) { + // Overwrite nodeData.getItemModel to + nodeData.wrapMethod('getItemModel', function (model) { + var categoriesModels = self._categoriesModels; + var categoryIdx = model.getShallow('category'); + var categoryModel = categoriesModels[categoryIdx]; + + if (categoryModel) { + categoryModel.parentModel = model.parentModel; + model.parentModel = categoryModel; + } + + return model; + }); // TODO Inherit resolveParentPath by default in Model#getModel? + + var oldGetModel = Model.prototype.getModel; + + function newGetModel(path, parentModel) { + var model = oldGetModel.call(this, path, parentModel); + model.resolveParentPath = resolveParentPath; + return model; + } + + edgeData.wrapMethod('getItemModel', function (model) { + model.resolveParentPath = resolveParentPath; + model.getModel = newGetModel; + return model; + }); + + function resolveParentPath(pathArr) { + if (pathArr && (pathArr[0] === 'label' || pathArr[1] === 'label')) { + var newPathArr = pathArr.slice(); + + if (pathArr[0] === 'label') { + newPathArr[0] = 'edgeLabel'; + } else if (pathArr[1] === 'label') { + newPathArr[1] = 'edgeLabel'; + } + + return newPathArr; + } + + return pathArr; + } + } + }; + + GraphSeriesModel.prototype.getGraph = function () { + return this.getData().graph; + }; + + GraphSeriesModel.prototype.getEdgeData = function () { + return this.getGraph().edgeData; + }; + + GraphSeriesModel.prototype.getCategoriesData = function () { + return this._categoriesData; + }; + + GraphSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + if (dataType === 'edge') { + var nodeData = this.getData(); + var params = this.getDataParams(dataIndex, dataType); + var edge = nodeData.graph.getEdgeByIndex(dataIndex); + var sourceName = nodeData.getName(edge.node1.dataIndex); + var targetName = nodeData.getName(edge.node2.dataIndex); + var nameArr = []; + sourceName != null && nameArr.push(sourceName); + targetName != null && nameArr.push(targetName); + return createTooltipMarkup('nameValue', { + name: nameArr.join(' > '), + value: params.value, + noValue: params.value == null + }); + } // dataType === 'node' or empty + + + var nodeMarkup = defaultSeriesFormatTooltip({ + series: this, + dataIndex: dataIndex, + multipleSeries: multipleSeries + }); + return nodeMarkup; + }; + + GraphSeriesModel.prototype._updateCategoriesData = function () { + var categories = map(this.option.categories || [], function (category) { + // Data must has value + return category.value != null ? category : extend({ + value: 0 + }, category); + }); + var categoriesData = new SeriesData(['value'], this); + categoriesData.initData(categories); + this._categoriesData = categoriesData; + this._categoriesModels = categoriesData.mapArray(function (idx) { + return categoriesData.getItemModel(idx); + }); + }; + + GraphSeriesModel.prototype.setZoom = function (zoom) { + this.option.zoom = zoom; + }; + + GraphSeriesModel.prototype.setCenter = function (center) { + this.option.center = center; + }; + + GraphSeriesModel.prototype.isAnimationEnabled = function () { + return _super.prototype.isAnimationEnabled.call(this) // Not enable animation when do force layout + && !(this.get('layout') === 'force' && this.get(['force', 'layoutAnimation'])); + }; + + GraphSeriesModel.type = 'series.graph'; + GraphSeriesModel.dependencies = ['grid', 'polar', 'geo', 'singleAxis', 'calendar']; + GraphSeriesModel.defaultOption = { + // zlevel: 0, + z: 2, + coordinateSystem: 'view', + // Default option for all coordinate systems + // xAxisIndex: 0, + // yAxisIndex: 0, + // polarIndex: 0, + // geoIndex: 0, + legendHoverLink: true, + layout: null, + // Configuration of circular layout + circular: { + rotateLabel: false + }, + // Configuration of force directed layout + force: { + initLayout: null, + // Node repulsion. Can be an array to represent range. + repulsion: [0, 50], + gravity: 0.1, + // Initial friction + friction: 0.6, + // Edge length. Can be an array to represent range. + edgeLength: 30, + layoutAnimation: true + }, + left: 'center', + top: 'center', + // right: null, + // bottom: null, + // width: '80%', + // height: '80%', + symbol: 'circle', + symbolSize: 10, + edgeSymbol: ['none', 'none'], + edgeSymbolSize: 10, + edgeLabel: { + position: 'middle', + distance: 5 + }, + draggable: false, + roam: false, + // Default on center of graph + center: null, + zoom: 1, + // Symbol size scale ratio in roam + nodeScaleRatio: 0.6, + // cursor: null, + // categories: [], + // data: [] + // Or + // nodes: [] + // + // links: [] + // Or + // edges: [] + label: { + show: false, + formatter: '{b}' + }, + itemStyle: {}, + lineStyle: { + color: '#aaa', + width: 1, + opacity: 0.5 + }, + emphasis: { + scale: true, + label: { + show: true + } + }, + select: { + itemStyle: { + borderColor: '#212121' + } + } + }; + return GraphSeriesModel; + }(SeriesModel); + + var actionInfo = { + type: 'graphRoam', + event: 'graphRoam', + update: 'none' + }; + function install$d(registers) { + registers.registerChartView(GraphView); + registers.registerSeriesModel(GraphSeriesModel); + registers.registerProcessor(categoryFilter); + registers.registerVisual(categoryVisual); + registers.registerVisual(graphEdgeVisual); + registers.registerLayout(graphSimpleLayout); + registers.registerLayout(registers.PRIORITY.VISUAL.POST_CHART_LAYOUT, graphCircularLayout); + registers.registerLayout(graphForceLayout); + registers.registerCoordinateSystem('graphView', { + dimensions: View.dimensions, + create: createViewCoordSys + }); // Register legacy focus actions + + registers.registerAction({ + type: 'focusNodeAdjacency', + event: 'focusNodeAdjacency', + update: 'series:focusNodeAdjacency' + }, noop); + registers.registerAction({ + type: 'unfocusNodeAdjacency', + event: 'unfocusNodeAdjacency', + update: 'series:unfocusNodeAdjacency' + }, noop); // Register roam action. + + registers.registerAction(actionInfo, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', + query: payload + }, function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var res = updateCenterAndZoom(coordSys, payload); + seriesModel.setCenter && seriesModel.setCenter(res.center); + seriesModel.setZoom && seriesModel.setZoom(res.zoom); + }); + }); + } + + var PointerShape = + /** @class */ + function () { + function PointerShape() { + this.angle = 0; + this.width = 10; + this.r = 10; + this.x = 0; + this.y = 0; + } + + return PointerShape; + }(); + + var PointerPath = + /** @class */ + function (_super) { + __extends(PointerPath, _super); + + function PointerPath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'pointer'; + return _this; + } + + PointerPath.prototype.getDefaultShape = function () { + return new PointerShape(); + }; + + PointerPath.prototype.buildPath = function (ctx, shape) { + var mathCos = Math.cos; + var mathSin = Math.sin; + var r = shape.r; + var width = shape.width; + var angle = shape.angle; + var x = shape.x - mathCos(angle) * width * (width >= r / 3 ? 1 : 2); + var y = shape.y - mathSin(angle) * width * (width >= r / 3 ? 1 : 2); + angle = shape.angle - Math.PI / 2; + ctx.moveTo(x, y); + ctx.lineTo(shape.x + mathCos(angle) * width, shape.y + mathSin(angle) * width); + ctx.lineTo(shape.x + mathCos(shape.angle) * r, shape.y + mathSin(shape.angle) * r); + ctx.lineTo(shape.x - mathCos(angle) * width, shape.y - mathSin(angle) * width); + ctx.lineTo(x, y); + }; + + return PointerPath; + }(Path); + + function parsePosition(seriesModel, api) { + var center = seriesModel.get('center'); + var width = api.getWidth(); + var height = api.getHeight(); + var size = Math.min(width, height); + var cx = parsePercent$1(center[0], api.getWidth()); + var cy = parsePercent$1(center[1], api.getHeight()); + var r = parsePercent$1(seriesModel.get('radius'), size / 2); + return { + cx: cx, + cy: cy, + r: r + }; + } + + function formatLabel(value, labelFormatter) { + var label = value == null ? '' : value + ''; + + if (labelFormatter) { + if (isString(labelFormatter)) { + label = labelFormatter.replace('{value}', label); + } else if (isFunction(labelFormatter)) { + label = labelFormatter(value); + } + } + + return label; + } + + var GaugeView = + /** @class */ + function (_super) { + __extends(GaugeView, _super); + + function GaugeView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GaugeView.type; + return _this; + } + + GaugeView.prototype.render = function (seriesModel, ecModel, api) { + this.group.removeAll(); + var colorList = seriesModel.get(['axisLine', 'lineStyle', 'color']); + var posInfo = parsePosition(seriesModel, api); + + this._renderMain(seriesModel, ecModel, api, colorList, posInfo); + + this._data = seriesModel.getData(); + }; + + GaugeView.prototype.dispose = function () {}; + + GaugeView.prototype._renderMain = function (seriesModel, ecModel, api, colorList, posInfo) { + var group = this.group; + var clockwise = seriesModel.get('clockwise'); + var startAngle = -seriesModel.get('startAngle') / 180 * Math.PI; + var endAngle = -seriesModel.get('endAngle') / 180 * Math.PI; + var axisLineModel = seriesModel.getModel('axisLine'); + var roundCap = axisLineModel.get('roundCap'); + var MainPath = roundCap ? SausagePath : Sector; + var showAxis = axisLineModel.get('show'); + var lineStyleModel = axisLineModel.getModel('lineStyle'); + var axisLineWidth = lineStyleModel.get('width'); + var angles = [startAngle, endAngle]; + normalizeArcAngles(angles, !clockwise); + startAngle = angles[0]; + endAngle = angles[1]; + var angleRangeSpan = endAngle - startAngle; + var prevEndAngle = startAngle; + + for (var i = 0; showAxis && i < colorList.length; i++) { + // Clamp + var percent = Math.min(Math.max(colorList[i][0], 0), 1); + endAngle = startAngle + angleRangeSpan * percent; + var sector = new MainPath({ + shape: { + startAngle: prevEndAngle, + endAngle: endAngle, + cx: posInfo.cx, + cy: posInfo.cy, + clockwise: clockwise, + r0: posInfo.r - axisLineWidth, + r: posInfo.r + }, + silent: true + }); + sector.setStyle({ + fill: colorList[i][1] + }); + sector.setStyle(lineStyleModel.getLineStyle( // Because we use sector to simulate arc + // so the properties for stroking are useless + ['color', 'width'])); + group.add(sector); + prevEndAngle = endAngle; + } + + var getColor = function (percent) { + // Less than 0 + if (percent <= 0) { + return colorList[0][1]; + } + + var i; + + for (i = 0; i < colorList.length; i++) { + if (colorList[i][0] >= percent && (i === 0 ? 0 : colorList[i - 1][0]) < percent) { + return colorList[i][1]; + } + } // More than 1 + + + return colorList[i - 1][1]; + }; + + this._renderTicks(seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise, axisLineWidth); + + this._renderTitleAndDetail(seriesModel, ecModel, api, getColor, posInfo); + + this._renderAnchor(seriesModel, posInfo); + + this._renderPointer(seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise, axisLineWidth); + }; + + GaugeView.prototype._renderTicks = function (seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise, axisLineWidth) { + var group = this.group; + var cx = posInfo.cx; + var cy = posInfo.cy; + var r = posInfo.r; + var minVal = +seriesModel.get('min'); + var maxVal = +seriesModel.get('max'); + var splitLineModel = seriesModel.getModel('splitLine'); + var tickModel = seriesModel.getModel('axisTick'); + var labelModel = seriesModel.getModel('axisLabel'); + var splitNumber = seriesModel.get('splitNumber'); + var subSplitNumber = tickModel.get('splitNumber'); + var splitLineLen = parsePercent$1(splitLineModel.get('length'), r); + var tickLen = parsePercent$1(tickModel.get('length'), r); + var angle = startAngle; + var step = (endAngle - startAngle) / splitNumber; + var subStep = step / subSplitNumber; + var splitLineStyle = splitLineModel.getModel('lineStyle').getLineStyle(); + var tickLineStyle = tickModel.getModel('lineStyle').getLineStyle(); + var splitLineDistance = splitLineModel.get('distance'); + var unitX; + var unitY; + + for (var i = 0; i <= splitNumber; i++) { + unitX = Math.cos(angle); + unitY = Math.sin(angle); // Split line + + if (splitLineModel.get('show')) { + var distance = splitLineDistance ? splitLineDistance + axisLineWidth : axisLineWidth; + var splitLine = new Line({ + shape: { + x1: unitX * (r - distance) + cx, + y1: unitY * (r - distance) + cy, + x2: unitX * (r - splitLineLen - distance) + cx, + y2: unitY * (r - splitLineLen - distance) + cy + }, + style: splitLineStyle, + silent: true + }); + + if (splitLineStyle.stroke === 'auto') { + splitLine.setStyle({ + stroke: getColor(i / splitNumber) + }); + } + + group.add(splitLine); + } // Label + + + if (labelModel.get('show')) { + var distance = labelModel.get('distance') + splitLineDistance; + var label = formatLabel(round(i / splitNumber * (maxVal - minVal) + minVal), labelModel.get('formatter')); + var autoColor = getColor(i / splitNumber); + group.add(new ZRText({ + style: createTextStyle(labelModel, { + text: label, + x: unitX * (r - splitLineLen - distance) + cx, + y: unitY * (r - splitLineLen - distance) + cy, + verticalAlign: unitY < -0.8 ? 'top' : unitY > 0.8 ? 'bottom' : 'middle', + align: unitX < -0.4 ? 'left' : unitX > 0.4 ? 'right' : 'center' + }, { + inheritColor: autoColor + }), + silent: true + })); + } // Axis tick + + + if (tickModel.get('show') && i !== splitNumber) { + var distance = tickModel.get('distance'); + distance = distance ? distance + axisLineWidth : axisLineWidth; + + for (var j = 0; j <= subSplitNumber; j++) { + unitX = Math.cos(angle); + unitY = Math.sin(angle); + var tickLine = new Line({ + shape: { + x1: unitX * (r - distance) + cx, + y1: unitY * (r - distance) + cy, + x2: unitX * (r - tickLen - distance) + cx, + y2: unitY * (r - tickLen - distance) + cy + }, + silent: true, + style: tickLineStyle + }); + + if (tickLineStyle.stroke === 'auto') { + tickLine.setStyle({ + stroke: getColor((i + j / subSplitNumber) / splitNumber) + }); + } + + group.add(tickLine); + angle += subStep; + } + + angle -= subStep; + } else { + angle += step; + } + } + }; + + GaugeView.prototype._renderPointer = function (seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise, axisLineWidth) { + var group = this.group; + var oldData = this._data; + var oldProgressData = this._progressEls; + var progressList = []; + var showPointer = seriesModel.get(['pointer', 'show']); + var progressModel = seriesModel.getModel('progress'); + var showProgress = progressModel.get('show'); + var data = seriesModel.getData(); + var valueDim = data.mapDimension('value'); + var minVal = +seriesModel.get('min'); + var maxVal = +seriesModel.get('max'); + var valueExtent = [minVal, maxVal]; + var angleExtent = [startAngle, endAngle]; + + function createPointer(idx, angle) { + var itemModel = data.getItemModel(idx); + var pointerModel = itemModel.getModel('pointer'); + var pointerWidth = parsePercent$1(pointerModel.get('width'), posInfo.r); + var pointerLength = parsePercent$1(pointerModel.get('length'), posInfo.r); + var pointerStr = seriesModel.get(['pointer', 'icon']); + var pointerOffset = pointerModel.get('offsetCenter'); + var pointerOffsetX = parsePercent$1(pointerOffset[0], posInfo.r); + var pointerOffsetY = parsePercent$1(pointerOffset[1], posInfo.r); + var pointerKeepAspect = pointerModel.get('keepAspect'); + var pointer; // not exist icon type will be set 'rect' + + if (pointerStr) { + pointer = createSymbol(pointerStr, pointerOffsetX - pointerWidth / 2, pointerOffsetY - pointerLength, pointerWidth, pointerLength, null, pointerKeepAspect); + } else { + pointer = new PointerPath({ + shape: { + angle: -Math.PI / 2, + width: pointerWidth, + r: pointerLength, + x: pointerOffsetX, + y: pointerOffsetY + } + }); + } + + pointer.rotation = -(angle + Math.PI / 2); + pointer.x = posInfo.cx; + pointer.y = posInfo.cy; + return pointer; + } + + function createProgress(idx, endAngle) { + var roundCap = progressModel.get('roundCap'); + var ProgressPath = roundCap ? SausagePath : Sector; + var isOverlap = progressModel.get('overlap'); + var progressWidth = isOverlap ? progressModel.get('width') : axisLineWidth / data.count(); + var r0 = isOverlap ? posInfo.r - progressWidth : posInfo.r - (idx + 1) * progressWidth; + var r = isOverlap ? posInfo.r : posInfo.r - idx * progressWidth; + var progress = new ProgressPath({ + shape: { + startAngle: startAngle, + endAngle: endAngle, + cx: posInfo.cx, + cy: posInfo.cy, + clockwise: clockwise, + r0: r0, + r: r + } + }); + isOverlap && (progress.z2 = maxVal - data.get(valueDim, idx) % maxVal); + return progress; + } + + if (showProgress || showPointer) { + data.diff(oldData).add(function (idx) { + var val = data.get(valueDim, idx); + + if (showPointer) { + var pointer = createPointer(idx, startAngle); // TODO hide pointer on NaN value? + + initProps(pointer, { + rotation: -((isNaN(+val) ? angleExtent[0] : linearMap(val, valueExtent, angleExtent, true)) + Math.PI / 2) + }, seriesModel); + group.add(pointer); + data.setItemGraphicEl(idx, pointer); + } + + if (showProgress) { + var progress = createProgress(idx, startAngle); + var isClip = progressModel.get('clip'); + initProps(progress, { + shape: { + endAngle: linearMap(val, valueExtent, angleExtent, isClip) + } + }, seriesModel); + group.add(progress); // Add data index and series index for indexing the data by element + // Useful in tooltip + + setCommonECData(seriesModel.seriesIndex, data.dataType, idx, progress); + progressList[idx] = progress; + } + }).update(function (newIdx, oldIdx) { + var val = data.get(valueDim, newIdx); + + if (showPointer) { + var previousPointer = oldData.getItemGraphicEl(oldIdx); + var previousRotate = previousPointer ? previousPointer.rotation : startAngle; + var pointer = createPointer(newIdx, previousRotate); + pointer.rotation = previousRotate; + updateProps(pointer, { + rotation: -((isNaN(+val) ? angleExtent[0] : linearMap(val, valueExtent, angleExtent, true)) + Math.PI / 2) + }, seriesModel); + group.add(pointer); + data.setItemGraphicEl(newIdx, pointer); + } + + if (showProgress) { + var previousProgress = oldProgressData[oldIdx]; + var previousEndAngle = previousProgress ? previousProgress.shape.endAngle : startAngle; + var progress = createProgress(newIdx, previousEndAngle); + var isClip = progressModel.get('clip'); + updateProps(progress, { + shape: { + endAngle: linearMap(val, valueExtent, angleExtent, isClip) + } + }, seriesModel); + group.add(progress); // Add data index and series index for indexing the data by element + // Useful in tooltip + + setCommonECData(seriesModel.seriesIndex, data.dataType, newIdx, progress); + progressList[newIdx] = progress; + } + }).execute(); + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var emphasisModel = itemModel.getModel('emphasis'); + var focus = emphasisModel.get('focus'); + var blurScope = emphasisModel.get('blurScope'); + var emphasisDisabled = emphasisModel.get('disabled'); + + if (showPointer) { + var pointer = data.getItemGraphicEl(idx); + var symbolStyle = data.getItemVisual(idx, 'style'); + var visualColor = symbolStyle.fill; + + if (pointer instanceof ZRImage) { + var pathStyle = pointer.style; + pointer.useStyle(extend({ + image: pathStyle.image, + x: pathStyle.x, + y: pathStyle.y, + width: pathStyle.width, + height: pathStyle.height + }, symbolStyle)); + } else { + pointer.useStyle(symbolStyle); + pointer.type !== 'pointer' && pointer.setColor(visualColor); + } + + pointer.setStyle(itemModel.getModel(['pointer', 'itemStyle']).getItemStyle()); + + if (pointer.style.fill === 'auto') { + pointer.setStyle('fill', getColor(linearMap(data.get(valueDim, idx), valueExtent, [0, 1], true))); + } + + pointer.z2EmphasisLift = 0; + setStatesStylesFromModel(pointer, itemModel); + toggleHoverEmphasis(pointer, focus, blurScope, emphasisDisabled); + } + + if (showProgress) { + var progress = progressList[idx]; + progress.useStyle(data.getItemVisual(idx, 'style')); + progress.setStyle(itemModel.getModel(['progress', 'itemStyle']).getItemStyle()); + progress.z2EmphasisLift = 0; + setStatesStylesFromModel(progress, itemModel); + toggleHoverEmphasis(progress, focus, blurScope, emphasisDisabled); + } + }); + this._progressEls = progressList; + } + }; + + GaugeView.prototype._renderAnchor = function (seriesModel, posInfo) { + var anchorModel = seriesModel.getModel('anchor'); + var showAnchor = anchorModel.get('show'); + + if (showAnchor) { + var anchorSize = anchorModel.get('size'); + var anchorType = anchorModel.get('icon'); + var offsetCenter = anchorModel.get('offsetCenter'); + var anchorKeepAspect = anchorModel.get('keepAspect'); + var anchor = createSymbol(anchorType, posInfo.cx - anchorSize / 2 + parsePercent$1(offsetCenter[0], posInfo.r), posInfo.cy - anchorSize / 2 + parsePercent$1(offsetCenter[1], posInfo.r), anchorSize, anchorSize, null, anchorKeepAspect); + anchor.z2 = anchorModel.get('showAbove') ? 1 : 0; + anchor.setStyle(anchorModel.getModel('itemStyle').getItemStyle()); + this.group.add(anchor); + } + }; + + GaugeView.prototype._renderTitleAndDetail = function (seriesModel, ecModel, api, getColor, posInfo) { + var _this = this; + + var data = seriesModel.getData(); + var valueDim = data.mapDimension('value'); + var minVal = +seriesModel.get('min'); + var maxVal = +seriesModel.get('max'); + var contentGroup = new Group(); + var newTitleEls = []; + var newDetailEls = []; + var hasAnimation = seriesModel.isAnimationEnabled(); + var showPointerAbove = seriesModel.get(['pointer', 'showAbove']); + data.diff(this._data).add(function (idx) { + newTitleEls[idx] = new ZRText({ + silent: true + }); + newDetailEls[idx] = new ZRText({ + silent: true + }); + }).update(function (idx, oldIdx) { + newTitleEls[idx] = _this._titleEls[oldIdx]; + newDetailEls[idx] = _this._detailEls[oldIdx]; + }).execute(); + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var value = data.get(valueDim, idx); + var itemGroup = new Group(); + var autoColor = getColor(linearMap(value, [minVal, maxVal], [0, 1], true)); + var itemTitleModel = itemModel.getModel('title'); + + if (itemTitleModel.get('show')) { + var titleOffsetCenter = itemTitleModel.get('offsetCenter'); + var titleX = posInfo.cx + parsePercent$1(titleOffsetCenter[0], posInfo.r); + var titleY = posInfo.cy + parsePercent$1(titleOffsetCenter[1], posInfo.r); + var labelEl = newTitleEls[idx]; + labelEl.attr({ + z2: showPointerAbove ? 0 : 2, + style: createTextStyle(itemTitleModel, { + x: titleX, + y: titleY, + text: data.getName(idx), + align: 'center', + verticalAlign: 'middle' + }, { + inheritColor: autoColor + }) + }); + itemGroup.add(labelEl); + } + + var itemDetailModel = itemModel.getModel('detail'); + + if (itemDetailModel.get('show')) { + var detailOffsetCenter = itemDetailModel.get('offsetCenter'); + var detailX = posInfo.cx + parsePercent$1(detailOffsetCenter[0], posInfo.r); + var detailY = posInfo.cy + parsePercent$1(detailOffsetCenter[1], posInfo.r); + var width = parsePercent$1(itemDetailModel.get('width'), posInfo.r); + var height = parsePercent$1(itemDetailModel.get('height'), posInfo.r); + var detailColor = seriesModel.get(['progress', 'show']) ? data.getItemVisual(idx, 'style').fill : autoColor; + var labelEl = newDetailEls[idx]; + var formatter_1 = itemDetailModel.get('formatter'); + labelEl.attr({ + z2: showPointerAbove ? 0 : 2, + style: createTextStyle(itemDetailModel, { + x: detailX, + y: detailY, + text: formatLabel(value, formatter_1), + width: isNaN(width) ? null : width, + height: isNaN(height) ? null : height, + align: 'center', + verticalAlign: 'middle' + }, { + inheritColor: detailColor + }) + }); + setLabelValueAnimation(labelEl, { + normal: itemDetailModel + }, value, function (value) { + return formatLabel(value, formatter_1); + }); + hasAnimation && animateLabelValue(labelEl, idx, data, seriesModel, { + getFormattedLabel: function (labelDataIndex, status, dataType, labelDimIndex, fmt, extendParams) { + return formatLabel(extendParams ? extendParams.interpolatedValue : value, formatter_1); + } + }); + itemGroup.add(labelEl); + } + + contentGroup.add(itemGroup); + }); + this.group.add(contentGroup); + this._titleEls = newTitleEls; + this._detailEls = newDetailEls; + }; + + GaugeView.type = 'gauge'; + return GaugeView; + }(ChartView); + + var GaugeSeriesModel = + /** @class */ + function (_super) { + __extends(GaugeSeriesModel, _super); + + function GaugeSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GaugeSeriesModel.type; + _this.visualStyleAccessPath = 'itemStyle'; + return _this; + } + + GaugeSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createSeriesDataSimply(this, ['value']); + }; + + GaugeSeriesModel.type = 'series.gauge'; + GaugeSeriesModel.defaultOption = { + // zlevel: 0, + z: 2, + colorBy: 'data', + // 默认全局居中 + center: ['50%', '50%'], + legendHoverLink: true, + radius: '75%', + startAngle: 225, + endAngle: -45, + clockwise: true, + // 最小值 + min: 0, + // 最大值 + max: 100, + // 分割段数,默认为10 + splitNumber: 10, + // 坐标轴线 + axisLine: { + // 默认显示,属性show控制显示与否 + show: true, + roundCap: false, + lineStyle: { + color: [[1, '#E6EBF8']], + width: 10 + } + }, + // 坐标轴线 + progress: { + // 默认显示,属性show控制显示与否 + show: false, + overlap: true, + width: 10, + roundCap: false, + clip: true + }, + // 分隔线 + splitLine: { + // 默认显示,属性show控制显示与否 + show: true, + // 属性length控制线长 + length: 10, + distance: 10, + // 属性lineStyle(详见lineStyle)控制线条样式 + lineStyle: { + color: '#63677A', + width: 3, + type: 'solid' + } + }, + // 坐标轴小标记 + axisTick: { + // 属性show控制显示与否,默认不显示 + show: true, + // 每份split细分多少段 + splitNumber: 5, + // 属性length控制线长 + length: 6, + distance: 10, + // 属性lineStyle控制线条样式 + lineStyle: { + color: '#63677A', + width: 1, + type: 'solid' + } + }, + axisLabel: { + show: true, + distance: 15, + // formatter: null, + color: '#464646', + fontSize: 12 + }, + pointer: { + icon: null, + offsetCenter: [0, 0], + show: true, + showAbove: true, + length: '60%', + width: 6, + keepAspect: false + }, + anchor: { + show: false, + showAbove: false, + size: 6, + icon: 'circle', + offsetCenter: [0, 0], + keepAspect: false, + itemStyle: { + color: '#fff', + borderWidth: 0, + borderColor: '#5470c6' + } + }, + title: { + show: true, + // x, y,单位px + offsetCenter: [0, '20%'], + // 其余属性默认使用全局文本样式,详见TEXTSTYLE + color: '#464646', + fontSize: 16, + valueAnimation: false + }, + detail: { + show: true, + backgroundColor: 'rgba(0,0,0,0)', + borderWidth: 0, + borderColor: '#ccc', + width: 100, + height: null, + padding: [5, 10], + // x, y,单位px + offsetCenter: [0, '40%'], + // formatter: null, + // 其余属性默认使用全局文本样式,详见TEXTSTYLE + color: '#464646', + fontSize: 30, + fontWeight: 'bold', + lineHeight: 30, + valueAnimation: false + } + }; + return GaugeSeriesModel; + }(SeriesModel); + + function install$e(registers) { + registers.registerChartView(GaugeView); + registers.registerSeriesModel(GaugeSeriesModel); + } + + var opacityAccessPath = ['itemStyle', 'opacity']; + /** + * Piece of pie including Sector, Label, LabelLine + */ + + var FunnelPiece = + /** @class */ + function (_super) { + __extends(FunnelPiece, _super); + + function FunnelPiece(data, idx) { + var _this = _super.call(this) || this; + + var polygon = _this; + var labelLine = new Polyline(); + var text = new ZRText(); + polygon.setTextContent(text); + + _this.setTextGuideLine(labelLine); + + _this.updateData(data, idx, true); + + return _this; + } + + FunnelPiece.prototype.updateData = function (data, idx, firstCreate) { + var polygon = this; + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var layout = data.getItemLayout(idx); + var emphasisModel = itemModel.getModel('emphasis'); + var opacity = itemModel.get(opacityAccessPath); + opacity = opacity == null ? 1 : opacity; + + if (!firstCreate) { + saveOldStyle(polygon); + } // Update common style + + + polygon.useStyle(data.getItemVisual(idx, 'style')); + polygon.style.lineJoin = 'round'; + + if (firstCreate) { + polygon.setShape({ + points: layout.points + }); + polygon.style.opacity = 0; + initProps(polygon, { + style: { + opacity: opacity + } + }, seriesModel, idx); + } else { + updateProps(polygon, { + style: { + opacity: opacity + }, + shape: { + points: layout.points + } + }, seriesModel, idx); + } + + setStatesStylesFromModel(polygon, itemModel); + + this._updateLabel(data, idx); + + toggleHoverEmphasis(this, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled')); + }; + + FunnelPiece.prototype._updateLabel = function (data, idx) { + var polygon = this; + var labelLine = this.getTextGuideLine(); + var labelText = polygon.getTextContent(); + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var layout = data.getItemLayout(idx); + var labelLayout = layout.label; + var style = data.getItemVisual(idx, 'style'); + var visualColor = style.fill; + setLabelStyle( // position will not be used in setLabelStyle + labelText, getLabelStatesModels(itemModel), { + labelFetcher: data.hostModel, + labelDataIndex: idx, + defaultOpacity: style.opacity, + defaultText: data.getName(idx) + }, { + normal: { + align: labelLayout.textAlign, + verticalAlign: labelLayout.verticalAlign + } + }); + polygon.setTextConfig({ + local: true, + inside: !!labelLayout.inside, + insideStroke: visualColor, + // insideFill: 'auto', + outsideFill: visualColor + }); + var linePoints = labelLayout.linePoints; + labelLine.setShape({ + points: linePoints + }); + polygon.textGuideLineConfig = { + anchor: linePoints ? new Point(linePoints[0][0], linePoints[0][1]) : null + }; // Make sure update style on labelText after setLabelStyle. + // Because setLabelStyle will replace a new style on it. + + updateProps(labelText, { + style: { + x: labelLayout.x, + y: labelLayout.y + } + }, seriesModel, idx); + labelText.attr({ + rotation: labelLayout.rotation, + originX: labelLayout.x, + originY: labelLayout.y, + z2: 10 + }); + setLabelLineStyle(polygon, getLabelLineStatesModels(itemModel), { + // Default use item visual color + stroke: visualColor + }); + }; + + return FunnelPiece; + }(Polygon); + + var FunnelView = + /** @class */ + function (_super) { + __extends(FunnelView, _super); + + function FunnelView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = FunnelView.type; + _this.ignoreLabelLineUpdate = true; + return _this; + } + + FunnelView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var oldData = this._data; + var group = this.group; + data.diff(oldData).add(function (idx) { + var funnelPiece = new FunnelPiece(data, idx); + data.setItemGraphicEl(idx, funnelPiece); + group.add(funnelPiece); + }).update(function (newIdx, oldIdx) { + var piece = oldData.getItemGraphicEl(oldIdx); + piece.updateData(data, newIdx); + group.add(piece); + data.setItemGraphicEl(newIdx, piece); + }).remove(function (idx) { + var piece = oldData.getItemGraphicEl(idx); + removeElementWithFadeOut(piece, seriesModel, idx); + }).execute(); + this._data = data; + }; + + FunnelView.prototype.remove = function () { + this.group.removeAll(); + this._data = null; + }; + + FunnelView.prototype.dispose = function () {}; + + FunnelView.type = 'funnel'; + return FunnelView; + }(ChartView); + + var FunnelSeriesModel = + /** @class */ + function (_super) { + __extends(FunnelSeriesModel, _super); + + function FunnelSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = FunnelSeriesModel.type; + return _this; + } + + FunnelSeriesModel.prototype.init = function (option) { + _super.prototype.init.apply(this, arguments); // Enable legend selection for each data item + // Use a function instead of direct access because data reference may changed + + + this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this)); // Extend labelLine emphasis + + this._defaultLabelLine(option); + }; + + FunnelSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createSeriesDataSimply(this, { + coordDimensions: ['value'], + encodeDefaulter: curry(makeSeriesEncodeForNameBased, this) + }); + }; + + FunnelSeriesModel.prototype._defaultLabelLine = function (option) { + // Extend labelLine emphasis + defaultEmphasis(option, 'labelLine', ['show']); + var labelLineNormalOpt = option.labelLine; + var labelLineEmphasisOpt = option.emphasis.labelLine; // Not show label line if `label.normal.show = false` + + labelLineNormalOpt.show = labelLineNormalOpt.show && option.label.show; + labelLineEmphasisOpt.show = labelLineEmphasisOpt.show && option.emphasis.label.show; + }; // Overwrite + + + FunnelSeriesModel.prototype.getDataParams = function (dataIndex) { + var data = this.getData(); + + var params = _super.prototype.getDataParams.call(this, dataIndex); + + var valueDim = data.mapDimension('value'); + var sum = data.getSum(valueDim); // Percent is 0 if sum is 0 + + params.percent = !sum ? 0 : +(data.get(valueDim, dataIndex) / sum * 100).toFixed(2); + params.$vars.push('percent'); + return params; + }; + + FunnelSeriesModel.type = 'series.funnel'; + FunnelSeriesModel.defaultOption = { + // zlevel: 0, // 一级层叠 + z: 2, + legendHoverLink: true, + colorBy: 'data', + left: 80, + top: 60, + right: 80, + bottom: 60, + // width: {totalWidth} - left - right, + // height: {totalHeight} - top - bottom, + // 默认取数据最小最大值 + // min: 0, + // max: 100, + minSize: '0%', + maxSize: '100%', + sort: 'descending', + orient: 'vertical', + gap: 0, + funnelAlign: 'center', + label: { + show: true, + position: 'outer' // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调 + + }, + labelLine: { + show: true, + length: 20, + lineStyle: { + // color: 各异, + width: 1 + } + }, + itemStyle: { + // color: 各异, + borderColor: '#fff', + borderWidth: 1 + }, + emphasis: { + label: { + show: true + } + }, + select: { + itemStyle: { + borderColor: '#212121' + } + } + }; + return FunnelSeriesModel; + }(SeriesModel); + + function getViewRect$3(seriesModel, api) { + return getLayoutRect(seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + } + + function getSortedIndices(data, sort) { + var valueDim = data.mapDimension('value'); + var valueArr = data.mapArray(valueDim, function (val) { + return val; + }); + var indices = []; + var isAscending = sort === 'ascending'; + + for (var i = 0, len = data.count(); i < len; i++) { + indices[i] = i; + } // Add custom sortable function & none sortable opetion by "options.sort" + + + if (isFunction(sort)) { + indices.sort(sort); + } else if (sort !== 'none') { + indices.sort(function (a, b) { + return isAscending ? valueArr[a] - valueArr[b] : valueArr[b] - valueArr[a]; + }); + } + + return indices; + } + + function labelLayout(data) { + var seriesModel = data.hostModel; + var orient = seriesModel.get('orient'); + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var labelModel = itemModel.getModel('label'); + var labelPosition = labelModel.get('position'); + var labelLineModel = itemModel.getModel('labelLine'); + var layout = data.getItemLayout(idx); + var points = layout.points; + var isLabelInside = labelPosition === 'inner' || labelPosition === 'inside' || labelPosition === 'center' || labelPosition === 'insideLeft' || labelPosition === 'insideRight'; + var textAlign; + var textX; + var textY; + var linePoints; + + if (isLabelInside) { + if (labelPosition === 'insideLeft') { + textX = (points[0][0] + points[3][0]) / 2 + 5; + textY = (points[0][1] + points[3][1]) / 2; + textAlign = 'left'; + } else if (labelPosition === 'insideRight') { + textX = (points[1][0] + points[2][0]) / 2 - 5; + textY = (points[1][1] + points[2][1]) / 2; + textAlign = 'right'; + } else { + textX = (points[0][0] + points[1][0] + points[2][0] + points[3][0]) / 4; + textY = (points[0][1] + points[1][1] + points[2][1] + points[3][1]) / 4; + textAlign = 'center'; + } + + linePoints = [[textX, textY], [textX, textY]]; + } else { + var x1 = void 0; + var y1 = void 0; + var x2 = void 0; + var y2 = void 0; + var labelLineLen = labelLineModel.get('length'); + + if ("development" !== 'production') { + if (orient === 'vertical' && ['top', 'bottom'].indexOf(labelPosition) > -1) { + labelPosition = 'left'; + console.warn('Position error: Funnel chart on vertical orient dose not support top and bottom.'); + } + + if (orient === 'horizontal' && ['left', 'right'].indexOf(labelPosition) > -1) { + labelPosition = 'bottom'; + console.warn('Position error: Funnel chart on horizontal orient dose not support left and right.'); + } + } + + if (labelPosition === 'left') { + // Left side + x1 = (points[3][0] + points[0][0]) / 2; + y1 = (points[3][1] + points[0][1]) / 2; + x2 = x1 - labelLineLen; + textX = x2 - 5; + textAlign = 'right'; + } else if (labelPosition === 'right') { + // Right side + x1 = (points[1][0] + points[2][0]) / 2; + y1 = (points[1][1] + points[2][1]) / 2; + x2 = x1 + labelLineLen; + textX = x2 + 5; + textAlign = 'left'; + } else if (labelPosition === 'top') { + // Top side + x1 = (points[3][0] + points[0][0]) / 2; + y1 = (points[3][1] + points[0][1]) / 2; + y2 = y1 - labelLineLen; + textY = y2 - 5; + textAlign = 'center'; + } else if (labelPosition === 'bottom') { + // Bottom side + x1 = (points[1][0] + points[2][0]) / 2; + y1 = (points[1][1] + points[2][1]) / 2; + y2 = y1 + labelLineLen; + textY = y2 + 5; + textAlign = 'center'; + } else if (labelPosition === 'rightTop') { + // RightTop side + x1 = orient === 'horizontal' ? points[3][0] : points[1][0]; + y1 = orient === 'horizontal' ? points[3][1] : points[1][1]; + + if (orient === 'horizontal') { + y2 = y1 - labelLineLen; + textY = y2 - 5; + textAlign = 'center'; + } else { + x2 = x1 + labelLineLen; + textX = x2 + 5; + textAlign = 'top'; + } + } else if (labelPosition === 'rightBottom') { + // RightBottom side + x1 = points[2][0]; + y1 = points[2][1]; + + if (orient === 'horizontal') { + y2 = y1 + labelLineLen; + textY = y2 + 5; + textAlign = 'center'; + } else { + x2 = x1 + labelLineLen; + textX = x2 + 5; + textAlign = 'bottom'; + } + } else if (labelPosition === 'leftTop') { + // LeftTop side + x1 = points[0][0]; + y1 = orient === 'horizontal' ? points[0][1] : points[1][1]; + + if (orient === 'horizontal') { + y2 = y1 - labelLineLen; + textY = y2 - 5; + textAlign = 'center'; + } else { + x2 = x1 - labelLineLen; + textX = x2 - 5; + textAlign = 'right'; + } + } else if (labelPosition === 'leftBottom') { + // LeftBottom side + x1 = orient === 'horizontal' ? points[1][0] : points[3][0]; + y1 = orient === 'horizontal' ? points[1][1] : points[2][1]; + + if (orient === 'horizontal') { + y2 = y1 + labelLineLen; + textY = y2 + 5; + textAlign = 'center'; + } else { + x2 = x1 - labelLineLen; + textX = x2 - 5; + textAlign = 'right'; + } + } else { + // Right side or Bottom side + x1 = (points[1][0] + points[2][0]) / 2; + y1 = (points[1][1] + points[2][1]) / 2; + + if (orient === 'horizontal') { + y2 = y1 + labelLineLen; + textY = y2 + 5; + textAlign = 'center'; + } else { + x2 = x1 + labelLineLen; + textX = x2 + 5; + textAlign = 'left'; + } + } + + if (orient === 'horizontal') { + x2 = x1; + textX = x2; + } else { + y2 = y1; + textY = y2; + } + + linePoints = [[x1, y1], [x2, y2]]; + } + + layout.label = { + linePoints: linePoints, + x: textX, + y: textY, + verticalAlign: 'middle', + textAlign: textAlign, + inside: isLabelInside + }; + }); + } + + function funnelLayout(ecModel, api) { + ecModel.eachSeriesByType('funnel', function (seriesModel) { + var data = seriesModel.getData(); + var valueDim = data.mapDimension('value'); + var sort = seriesModel.get('sort'); + var viewRect = getViewRect$3(seriesModel, api); + var orient = seriesModel.get('orient'); + var viewWidth = viewRect.width; + var viewHeight = viewRect.height; + var indices = getSortedIndices(data, sort); + var x = viewRect.x; + var y = viewRect.y; + var sizeExtent = orient === 'horizontal' ? [parsePercent$1(seriesModel.get('minSize'), viewHeight), parsePercent$1(seriesModel.get('maxSize'), viewHeight)] : [parsePercent$1(seriesModel.get('minSize'), viewWidth), parsePercent$1(seriesModel.get('maxSize'), viewWidth)]; + var dataExtent = data.getDataExtent(valueDim); + var min = seriesModel.get('min'); + var max = seriesModel.get('max'); + + if (min == null) { + min = Math.min(dataExtent[0], 0); + } + + if (max == null) { + max = dataExtent[1]; + } + + var funnelAlign = seriesModel.get('funnelAlign'); + var gap = seriesModel.get('gap'); + var viewSize = orient === 'horizontal' ? viewWidth : viewHeight; + var itemSize = (viewSize - gap * (data.count() - 1)) / data.count(); + + var getLinePoints = function (idx, offset) { + // End point index is data.count() and we assign it 0 + if (orient === 'horizontal') { + var val_1 = data.get(valueDim, idx) || 0; + var itemHeight = linearMap(val_1, [min, max], sizeExtent, true); + var y0 = void 0; + + switch (funnelAlign) { + case 'top': + y0 = y; + break; + + case 'center': + y0 = y + (viewHeight - itemHeight) / 2; + break; + + case 'bottom': + y0 = y + (viewHeight - itemHeight); + break; + } + + return [[offset, y0], [offset, y0 + itemHeight]]; + } + + var val = data.get(valueDim, idx) || 0; + var itemWidth = linearMap(val, [min, max], sizeExtent, true); + var x0; + + switch (funnelAlign) { + case 'left': + x0 = x; + break; + + case 'center': + x0 = x + (viewWidth - itemWidth) / 2; + break; + + case 'right': + x0 = x + viewWidth - itemWidth; + break; + } + + return [[x0, offset], [x0 + itemWidth, offset]]; + }; + + if (sort === 'ascending') { + // From bottom to top + itemSize = -itemSize; + gap = -gap; + + if (orient === 'horizontal') { + x += viewWidth; + } else { + y += viewHeight; + } + + indices = indices.reverse(); + } + + for (var i = 0; i < indices.length; i++) { + var idx = indices[i]; + var nextIdx = indices[i + 1]; + var itemModel = data.getItemModel(idx); + + if (orient === 'horizontal') { + var width = itemModel.get(['itemStyle', 'width']); + + if (width == null) { + width = itemSize; + } else { + width = parsePercent$1(width, viewWidth); + + if (sort === 'ascending') { + width = -width; + } + } + + var start = getLinePoints(idx, x); + var end = getLinePoints(nextIdx, x + width); + x += width + gap; + data.setItemLayout(idx, { + points: start.concat(end.slice().reverse()) + }); + } else { + var height = itemModel.get(['itemStyle', 'height']); + + if (height == null) { + height = itemSize; + } else { + height = parsePercent$1(height, viewHeight); + + if (sort === 'ascending') { + height = -height; + } + } + + var start = getLinePoints(idx, y); + var end = getLinePoints(nextIdx, y + height); + y += height + gap; + data.setItemLayout(idx, { + points: start.concat(end.slice().reverse()) + }); + } + } + + labelLayout(data); + }); + } + + function install$f(registers) { + registers.registerChartView(FunnelView); + registers.registerSeriesModel(FunnelSeriesModel); + registers.registerLayout(funnelLayout); + registers.registerProcessor(dataFilter('funnel')); + } + + var DEFAULT_SMOOTH = 0.3; + + var ParallelView = + /** @class */ + function (_super) { + __extends(ParallelView, _super); + + function ParallelView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ParallelView.type; + _this._dataGroup = new Group(); + _this._initialized = false; + return _this; + } + + ParallelView.prototype.init = function () { + this.group.add(this._dataGroup); + }; + /** + * @override + */ + + + ParallelView.prototype.render = function (seriesModel, ecModel, api, payload) { + // Clear previously rendered progressive elements. + this._progressiveEls = null; + var dataGroup = this._dataGroup; + var data = seriesModel.getData(); + var oldData = this._data; + var coordSys = seriesModel.coordinateSystem; + var dimensions = coordSys.dimensions; + var seriesScope = makeSeriesScope$2(seriesModel); + data.diff(oldData).add(add).update(update).remove(remove).execute(); + + function add(newDataIndex) { + var line = addEl(data, dataGroup, newDataIndex, dimensions, coordSys); + updateElCommon(line, data, newDataIndex, seriesScope); + } + + function update(newDataIndex, oldDataIndex) { + var line = oldData.getItemGraphicEl(oldDataIndex); + var points = createLinePoints(data, newDataIndex, dimensions, coordSys); + data.setItemGraphicEl(newDataIndex, line); + updateProps(line, { + shape: { + points: points + } + }, seriesModel, newDataIndex); + saveOldStyle(line); + updateElCommon(line, data, newDataIndex, seriesScope); + } + + function remove(oldDataIndex) { + var line = oldData.getItemGraphicEl(oldDataIndex); + dataGroup.remove(line); + } // First create + + + if (!this._initialized) { + this._initialized = true; + var clipPath = createGridClipShape(coordSys, seriesModel, function () { + // Callback will be invoked immediately if there is no animation + setTimeout(function () { + dataGroup.removeClipPath(); + }); + }); + dataGroup.setClipPath(clipPath); + } + + this._data = data; + }; + + ParallelView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) { + this._initialized = true; + this._data = null; + + this._dataGroup.removeAll(); + }; + + ParallelView.prototype.incrementalRender = function (taskParams, seriesModel, ecModel) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + var dimensions = coordSys.dimensions; + var seriesScope = makeSeriesScope$2(seriesModel); + var progressiveEls = this._progressiveEls = []; + + for (var dataIndex = taskParams.start; dataIndex < taskParams.end; dataIndex++) { + var line = addEl(data, this._dataGroup, dataIndex, dimensions, coordSys); + line.incremental = true; + updateElCommon(line, data, dataIndex, seriesScope); + progressiveEls.push(line); + } + }; + + ParallelView.prototype.remove = function () { + this._dataGroup && this._dataGroup.removeAll(); + this._data = null; + }; + + ParallelView.type = 'parallel'; + return ParallelView; + }(ChartView); + + function createGridClipShape(coordSys, seriesModel, cb) { + var parallelModel = coordSys.model; + var rect = coordSys.getRect(); + var rectEl = new Rect({ + shape: { + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + } + }); + var dim = parallelModel.get('layout') === 'horizontal' ? 'width' : 'height'; + rectEl.setShape(dim, 0); + initProps(rectEl, { + shape: { + width: rect.width, + height: rect.height + } + }, seriesModel, cb); + return rectEl; + } + + function createLinePoints(data, dataIndex, dimensions, coordSys) { + var points = []; + + for (var i = 0; i < dimensions.length; i++) { + var dimName = dimensions[i]; + var value = data.get(data.mapDimension(dimName), dataIndex); + + if (!isEmptyValue(value, coordSys.getAxis(dimName).type)) { + points.push(coordSys.dataToPoint(value, dimName)); + } + } + + return points; + } + + function addEl(data, dataGroup, dataIndex, dimensions, coordSys) { + var points = createLinePoints(data, dataIndex, dimensions, coordSys); + var line = new Polyline({ + shape: { + points: points + }, + // silent: true, + z2: 10 + }); + dataGroup.add(line); + data.setItemGraphicEl(dataIndex, line); + return line; + } + + function makeSeriesScope$2(seriesModel) { + var smooth = seriesModel.get('smooth', true); + smooth === true && (smooth = DEFAULT_SMOOTH); + smooth = numericToNumber(smooth); + eqNaN(smooth) && (smooth = 0); + return { + smooth: smooth + }; + } + + function updateElCommon(el, data, dataIndex, seriesScope) { + el.useStyle(data.getItemVisual(dataIndex, 'style')); + el.style.fill = null; + el.setShape('smooth', seriesScope.smooth); + var itemModel = data.getItemModel(dataIndex); + var emphasisModel = itemModel.getModel('emphasis'); + setStatesStylesFromModel(el, itemModel, 'lineStyle'); + toggleHoverEmphasis(el, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled')); + } // function simpleDiff(oldData, newData, dimensions) { + // let oldLen; + // if (!oldData + // || !oldData.__plProgressive + // || (oldLen = oldData.count()) !== newData.count() + // ) { + // return true; + // } + // let dimLen = dimensions.length; + // for (let i = 0; i < oldLen; i++) { + // for (let j = 0; j < dimLen; j++) { + // if (oldData.get(dimensions[j], i) !== newData.get(dimensions[j], i)) { + // return true; + // } + // } + // } + // return false; + // } + // FIXME put in common util? + + + function isEmptyValue(val, axisType) { + return axisType === 'category' ? val == null : val == null || isNaN(val); // axisType === 'value' + } + + var ParallelSeriesModel = + /** @class */ + function (_super) { + __extends(ParallelSeriesModel, _super); + + function ParallelSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ParallelSeriesModel.type; + _this.visualStyleAccessPath = 'lineStyle'; + _this.visualDrawType = 'stroke'; + return _this; + } + + ParallelSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createSeriesData(null, this, { + useEncodeDefaulter: bind(makeDefaultEncode, null, this) + }); + }; + /** + * User can get data raw indices on 'axisAreaSelected' event received. + * + * @return Raw indices + */ + + + ParallelSeriesModel.prototype.getRawIndicesByActiveState = function (activeState) { + var coordSys = this.coordinateSystem; + var data = this.getData(); + var indices = []; + coordSys.eachActiveState(data, function (theActiveState, dataIndex) { + if (activeState === theActiveState) { + indices.push(data.getRawIndex(dataIndex)); + } + }); + return indices; + }; + + ParallelSeriesModel.type = 'series.parallel'; + ParallelSeriesModel.dependencies = ['parallel']; + ParallelSeriesModel.defaultOption = { + // zlevel: 0, + z: 2, + coordinateSystem: 'parallel', + parallelIndex: 0, + label: { + show: false + }, + inactiveOpacity: 0.05, + activeOpacity: 1, + lineStyle: { + width: 1, + opacity: 0.45, + type: 'solid' + }, + emphasis: { + label: { + show: false + } + }, + progressive: 500, + smooth: false, + animationEasing: 'linear' + }; + return ParallelSeriesModel; + }(SeriesModel); + + function makeDefaultEncode(seriesModel) { + // The mapping of parallelAxis dimension to data dimension can + // be specified in parallelAxis.option.dim. For example, if + // parallelAxis.option.dim is 'dim3', it mapping to the third + // dimension of data. But `data.encode` has higher priority. + // Moreover, parallelModel.dimension should not be regarded as data + // dimensions. Consider dimensions = ['dim4', 'dim2', 'dim6']; + var parallelModel = seriesModel.ecModel.getComponent('parallel', seriesModel.get('parallelIndex')); + + if (!parallelModel) { + return; + } + + var encodeDefine = {}; + each(parallelModel.dimensions, function (axisDim) { + var dataDimIndex = convertDimNameToNumber(axisDim); + encodeDefine[axisDim] = dataDimIndex; + }); + return encodeDefine; + } + + function convertDimNameToNumber(dimName) { + return +dimName.replace('dim', ''); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var opacityAccessPath$1 = ['lineStyle', 'opacity']; + var parallelVisual = { + seriesType: 'parallel', + reset: function (seriesModel, ecModel) { + var coordSys = seriesModel.coordinateSystem; + var opacityMap = { + normal: seriesModel.get(['lineStyle', 'opacity']), + active: seriesModel.get('activeOpacity'), + inactive: seriesModel.get('inactiveOpacity') + }; + return { + progress: function (params, data) { + coordSys.eachActiveState(data, function (activeState, dataIndex) { + var opacity = opacityMap[activeState]; + + if (activeState === 'normal' && data.hasItemOption) { + var itemOpacity = data.getItemModel(dataIndex).get(opacityAccessPath$1, true); + itemOpacity != null && (opacity = itemOpacity); + } + + var existsStyle = data.ensureUniqueItemVisual(dataIndex, 'style'); + existsStyle.opacity = opacity; + }, params.start, params.end); + } + }; + } + }; + + function parallelPreprocessor(option) { + createParallelIfNeeded(option); + mergeAxisOptionFromParallel(option); + } + /** + * Create a parallel coordinate if not exists. + * @inner + */ + + function createParallelIfNeeded(option) { + if (option.parallel) { + return; + } + + var hasParallelSeries = false; + each(option.series, function (seriesOpt) { + if (seriesOpt && seriesOpt.type === 'parallel') { + hasParallelSeries = true; + } + }); + + if (hasParallelSeries) { + option.parallel = [{}]; + } + } + /** + * Merge aixs definition from parallel option (if exists) to axis option. + * @inner + */ + + + function mergeAxisOptionFromParallel(option) { + var axes = normalizeToArray(option.parallelAxis); + each(axes, function (axisOption) { + if (!isObject(axisOption)) { + return; + } + + var parallelIndex = axisOption.parallelIndex || 0; + var parallelOption = normalizeToArray(option.parallel)[parallelIndex]; + + if (parallelOption && parallelOption.parallelAxisDefault) { + merge(axisOption, parallelOption.parallelAxisDefault, false); + } + }); + } + + var CLICK_THRESHOLD = 5; // > 4 + + var ParallelView$1 = + /** @class */ + function (_super) { + __extends(ParallelView, _super); + + function ParallelView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ParallelView.type; + return _this; + } + + ParallelView.prototype.render = function (parallelModel, ecModel, api) { + this._model = parallelModel; + this._api = api; + + if (!this._handlers) { + this._handlers = {}; + each(handlers, function (handler, eventName) { + api.getZr().on(eventName, this._handlers[eventName] = bind(handler, this)); + }, this); + } + + createOrUpdate(this, '_throttledDispatchExpand', parallelModel.get('axisExpandRate'), 'fixRate'); + }; + + ParallelView.prototype.dispose = function (ecModel, api) { + clear(this, '_throttledDispatchExpand'); + each(this._handlers, function (handler, eventName) { + api.getZr().off(eventName, handler); + }); + this._handlers = null; + }; + /** + * @internal + * @param {Object} [opt] If null, cancle the last action triggering for debounce. + */ + + + ParallelView.prototype._throttledDispatchExpand = function (opt) { + this._dispatchExpand(opt); + }; + /** + * @internal + */ + + + ParallelView.prototype._dispatchExpand = function (opt) { + opt && this._api.dispatchAction(extend({ + type: 'parallelAxisExpand' + }, opt)); + }; + + ParallelView.type = 'parallel'; + return ParallelView; + }(ComponentView); + + var handlers = { + mousedown: function (e) { + if (checkTrigger(this, 'click')) { + this._mouseDownPoint = [e.offsetX, e.offsetY]; + } + }, + mouseup: function (e) { + var mouseDownPoint = this._mouseDownPoint; + + if (checkTrigger(this, 'click') && mouseDownPoint) { + var point = [e.offsetX, e.offsetY]; + var dist = Math.pow(mouseDownPoint[0] - point[0], 2) + Math.pow(mouseDownPoint[1] - point[1], 2); + + if (dist > CLICK_THRESHOLD) { + return; + } + + var result = this._model.coordinateSystem.getSlidedAxisExpandWindow([e.offsetX, e.offsetY]); + + result.behavior !== 'none' && this._dispatchExpand({ + axisExpandWindow: result.axisExpandWindow + }); + } + + this._mouseDownPoint = null; + }, + mousemove: function (e) { + // Should do nothing when brushing. + if (this._mouseDownPoint || !checkTrigger(this, 'mousemove')) { + return; + } + + var model = this._model; + var result = model.coordinateSystem.getSlidedAxisExpandWindow([e.offsetX, e.offsetY]); + var behavior = result.behavior; + behavior === 'jump' && this._throttledDispatchExpand.debounceNextCall(model.get('axisExpandDebounce')); + + this._throttledDispatchExpand(behavior === 'none' ? null // Cancle the last trigger, in case that mouse slide out of the area quickly. + : { + axisExpandWindow: result.axisExpandWindow, + // Jumping uses animation, and sliding suppresses animation. + animation: behavior === 'jump' ? null : { + duration: 0 // Disable animation. + + } + }); + } + }; + + function checkTrigger(view, triggerOn) { + var model = view._model; + return model.get('axisExpandable') && model.get('axisExpandTriggerOn') === triggerOn; + } + + var ParallelModel = + /** @class */ + function (_super) { + __extends(ParallelModel, _super); + + function ParallelModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ParallelModel.type; + return _this; + } + + ParallelModel.prototype.init = function () { + _super.prototype.init.apply(this, arguments); + + this.mergeOption({}); + }; + + ParallelModel.prototype.mergeOption = function (newOption) { + var thisOption = this.option; + newOption && merge(thisOption, newOption, true); + + this._initDimensions(); + }; + /** + * Whether series or axis is in this coordinate system. + */ + + + ParallelModel.prototype.contains = function (model, ecModel) { + var parallelIndex = model.get('parallelIndex'); + return parallelIndex != null && ecModel.getComponent('parallel', parallelIndex) === this; + }; + + ParallelModel.prototype.setAxisExpand = function (opt) { + each(['axisExpandable', 'axisExpandCenter', 'axisExpandCount', 'axisExpandWidth', 'axisExpandWindow'], function (name) { + if (opt.hasOwnProperty(name)) { + // @ts-ignore FIXME: why "never" inferred in this.option[name]? + this.option[name] = opt[name]; + } + }, this); + }; + + ParallelModel.prototype._initDimensions = function () { + var dimensions = this.dimensions = []; + var parallelAxisIndex = this.parallelAxisIndex = []; + var axisModels = filter(this.ecModel.queryComponents({ + mainType: 'parallelAxis' + }), function (axisModel) { + // Can not use this.contains here, because + // initialization has not been completed yet. + return (axisModel.get('parallelIndex') || 0) === this.componentIndex; + }, this); + each(axisModels, function (axisModel) { + dimensions.push('dim' + axisModel.get('dim')); + parallelAxisIndex.push(axisModel.componentIndex); + }); + }; + + ParallelModel.type = 'parallel'; + ParallelModel.dependencies = ['parallelAxis']; + ParallelModel.layoutMode = 'box'; + ParallelModel.defaultOption = { + // zlevel: 0, + z: 0, + left: 80, + top: 60, + right: 80, + bottom: 60, + // width: {totalWidth} - left - right, + // height: {totalHeight} - top - bottom, + layout: 'horizontal', + // FIXME + // naming? + axisExpandable: false, + axisExpandCenter: null, + axisExpandCount: 0, + axisExpandWidth: 50, + axisExpandRate: 17, + axisExpandDebounce: 50, + // [out, in, jumpTarget]. In percentage. If use [null, 0.05], null means full. + // Do not doc to user until necessary. + axisExpandSlideTriggerArea: [-0.15, 0.05, 0.4], + axisExpandTriggerOn: 'click', + parallelAxisDefault: null + }; + return ParallelModel; + }(ComponentModel); + + var ParallelAxis = + /** @class */ + function (_super) { + __extends(ParallelAxis, _super); + + function ParallelAxis(dim, scale, coordExtent, axisType, axisIndex) { + var _this = _super.call(this, dim, scale, coordExtent) || this; + + _this.type = axisType || 'value'; + _this.axisIndex = axisIndex; + return _this; + } + + ParallelAxis.prototype.isHorizontal = function () { + return this.coordinateSystem.getModel().get('layout') !== 'horizontal'; + }; + + return ParallelAxis; + }(Axis); + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + /** + * Calculate slider move result. + * Usage: + * (1) If both handle0 and handle1 are needed to be moved, set minSpan the same as + * maxSpan and the same as `Math.abs(handleEnd[1] - handleEnds[0])`. + * (2) If handle0 is forbidden to cross handle1, set minSpan as `0`. + * + * @param delta Move length. + * @param handleEnds handleEnds[0] can be bigger then handleEnds[1]. + * handleEnds will be modified in this method. + * @param extent handleEnds is restricted by extent. + * extent[0] should less or equals than extent[1]. + * @param handleIndex Can be 'all', means that both move the two handleEnds. + * @param minSpan The range of dataZoom can not be smaller than that. + * If not set, handle0 and cross handle1. If set as a non-negative + * number (including `0`), handles will push each other when reaching + * the minSpan. + * @param maxSpan The range of dataZoom can not be larger than that. + * @return The input handleEnds. + */ + function sliderMove(delta, handleEnds, extent, handleIndex, minSpan, maxSpan) { + delta = delta || 0; + var extentSpan = extent[1] - extent[0]; // Notice maxSpan and minSpan can be null/undefined. + + if (minSpan != null) { + minSpan = restrict(minSpan, [0, extentSpan]); + } + + if (maxSpan != null) { + maxSpan = Math.max(maxSpan, minSpan != null ? minSpan : 0); + } + + if (handleIndex === 'all') { + var handleSpan = Math.abs(handleEnds[1] - handleEnds[0]); + handleSpan = restrict(handleSpan, [0, extentSpan]); + minSpan = maxSpan = restrict(handleSpan, [minSpan, maxSpan]); + handleIndex = 0; + } + + handleEnds[0] = restrict(handleEnds[0], extent); + handleEnds[1] = restrict(handleEnds[1], extent); + var originalDistSign = getSpanSign(handleEnds, handleIndex); + handleEnds[handleIndex] += delta; // Restrict in extent. + + var extentMinSpan = minSpan || 0; + var realExtent = extent.slice(); + originalDistSign.sign < 0 ? realExtent[0] += extentMinSpan : realExtent[1] -= extentMinSpan; + handleEnds[handleIndex] = restrict(handleEnds[handleIndex], realExtent); // Expand span. + + var currDistSign; + currDistSign = getSpanSign(handleEnds, handleIndex); + + if (minSpan != null && (currDistSign.sign !== originalDistSign.sign || currDistSign.span < minSpan)) { + // If minSpan exists, 'cross' is forbidden. + handleEnds[1 - handleIndex] = handleEnds[handleIndex] + originalDistSign.sign * minSpan; + } // Shrink span. + + + currDistSign = getSpanSign(handleEnds, handleIndex); + + if (maxSpan != null && currDistSign.span > maxSpan) { + handleEnds[1 - handleIndex] = handleEnds[handleIndex] + currDistSign.sign * maxSpan; + } + + return handleEnds; + } + + function getSpanSign(handleEnds, handleIndex) { + var dist = handleEnds[handleIndex] - handleEnds[1 - handleIndex]; // If `handleEnds[0] === handleEnds[1]`, always believe that handleEnd[0] + // is at left of handleEnds[1] for non-cross case. + + return { + span: Math.abs(dist), + sign: dist > 0 ? -1 : dist < 0 ? 1 : handleIndex ? -1 : 1 + }; + } + + function restrict(value, extend) { + return Math.min(extend[1] != null ? extend[1] : Infinity, Math.max(extend[0] != null ? extend[0] : -Infinity, value)); + } + + var each$5 = each; + var mathMin$8 = Math.min; + var mathMax$8 = Math.max; + var mathFloor$1 = Math.floor; + var mathCeil$1 = Math.ceil; + var round$3 = round; + var PI$7 = Math.PI; + + var Parallel = + /** @class */ + function () { + function Parallel(parallelModel, ecModel, api) { + this.type = 'parallel'; + /** + * key: dimension + */ + + this._axesMap = createHashMap(); + /** + * key: dimension + * value: {position: [], rotation, } + */ + + this._axesLayout = {}; + this.dimensions = parallelModel.dimensions; + this._model = parallelModel; + + this._init(parallelModel, ecModel, api); + } + + Parallel.prototype._init = function (parallelModel, ecModel, api) { + var dimensions = parallelModel.dimensions; + var parallelAxisIndex = parallelModel.parallelAxisIndex; + each$5(dimensions, function (dim, idx) { + var axisIndex = parallelAxisIndex[idx]; + var axisModel = ecModel.getComponent('parallelAxis', axisIndex); + + var axis = this._axesMap.set(dim, new ParallelAxis(dim, createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisIndex)); + + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); // Injection + + axisModel.axis = axis; + axis.model = axisModel; + axis.coordinateSystem = axisModel.coordinateSystem = this; + }, this); + }; + /** + * Update axis scale after data processed + */ + + + Parallel.prototype.update = function (ecModel, api) { + this._updateAxesFromSeries(this._model, ecModel); + }; + + Parallel.prototype.containPoint = function (point) { + var layoutInfo = this._makeLayoutInfo(); + + var axisBase = layoutInfo.axisBase; + var layoutBase = layoutInfo.layoutBase; + var pixelDimIndex = layoutInfo.pixelDimIndex; + var pAxis = point[1 - pixelDimIndex]; + var pLayout = point[pixelDimIndex]; + return pAxis >= axisBase && pAxis <= axisBase + layoutInfo.axisLength && pLayout >= layoutBase && pLayout <= layoutBase + layoutInfo.layoutLength; + }; + + Parallel.prototype.getModel = function () { + return this._model; + }; + /** + * Update properties from series + */ + + + Parallel.prototype._updateAxesFromSeries = function (parallelModel, ecModel) { + ecModel.eachSeries(function (seriesModel) { + if (!parallelModel.contains(seriesModel, ecModel)) { + return; + } + + var data = seriesModel.getData(); + each$5(this.dimensions, function (dim) { + var axis = this._axesMap.get(dim); + + axis.scale.unionExtentFromData(data, data.mapDimension(dim)); + niceScaleExtent(axis.scale, axis.model); + }, this); + }, this); + }; + /** + * Resize the parallel coordinate system. + */ + + + Parallel.prototype.resize = function (parallelModel, api) { + this._rect = getLayoutRect(parallelModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + + this._layoutAxes(); + }; + + Parallel.prototype.getRect = function () { + return this._rect; + }; + + Parallel.prototype._makeLayoutInfo = function () { + var parallelModel = this._model; + var rect = this._rect; + var xy = ['x', 'y']; + var wh = ['width', 'height']; + var layout = parallelModel.get('layout'); + var pixelDimIndex = layout === 'horizontal' ? 0 : 1; + var layoutLength = rect[wh[pixelDimIndex]]; + var layoutExtent = [0, layoutLength]; + var axisCount = this.dimensions.length; + var axisExpandWidth = restrict$1(parallelModel.get('axisExpandWidth'), layoutExtent); + var axisExpandCount = restrict$1(parallelModel.get('axisExpandCount') || 0, [0, axisCount]); + var axisExpandable = parallelModel.get('axisExpandable') && axisCount > 3 && axisCount > axisExpandCount && axisExpandCount > 1 && axisExpandWidth > 0 && layoutLength > 0; // `axisExpandWindow` is According to the coordinates of [0, axisExpandLength], + // for sake of consider the case that axisCollapseWidth is 0 (when screen is narrow), + // where collapsed axes should be overlapped. + + var axisExpandWindow = parallelModel.get('axisExpandWindow'); + var winSize; + + if (!axisExpandWindow) { + winSize = restrict$1(axisExpandWidth * (axisExpandCount - 1), layoutExtent); + var axisExpandCenter = parallelModel.get('axisExpandCenter') || mathFloor$1(axisCount / 2); + axisExpandWindow = [axisExpandWidth * axisExpandCenter - winSize / 2]; + axisExpandWindow[1] = axisExpandWindow[0] + winSize; + } else { + winSize = restrict$1(axisExpandWindow[1] - axisExpandWindow[0], layoutExtent); + axisExpandWindow[1] = axisExpandWindow[0] + winSize; + } + + var axisCollapseWidth = (layoutLength - winSize) / (axisCount - axisExpandCount); // Avoid axisCollapseWidth is too small. + + axisCollapseWidth < 3 && (axisCollapseWidth = 0); // Find the first and last indices > ewin[0] and < ewin[1]. + + var winInnerIndices = [mathFloor$1(round$3(axisExpandWindow[0] / axisExpandWidth, 1)) + 1, mathCeil$1(round$3(axisExpandWindow[1] / axisExpandWidth, 1)) - 1]; // Pos in ec coordinates. + + var axisExpandWindow0Pos = axisCollapseWidth / axisExpandWidth * axisExpandWindow[0]; + return { + layout: layout, + pixelDimIndex: pixelDimIndex, + layoutBase: rect[xy[pixelDimIndex]], + layoutLength: layoutLength, + axisBase: rect[xy[1 - pixelDimIndex]], + axisLength: rect[wh[1 - pixelDimIndex]], + axisExpandable: axisExpandable, + axisExpandWidth: axisExpandWidth, + axisCollapseWidth: axisCollapseWidth, + axisExpandWindow: axisExpandWindow, + axisCount: axisCount, + winInnerIndices: winInnerIndices, + axisExpandWindow0Pos: axisExpandWindow0Pos + }; + }; + + Parallel.prototype._layoutAxes = function () { + var rect = this._rect; + var axes = this._axesMap; + var dimensions = this.dimensions; + + var layoutInfo = this._makeLayoutInfo(); + + var layout = layoutInfo.layout; + axes.each(function (axis) { + var axisExtent = [0, layoutInfo.axisLength]; + var idx = axis.inverse ? 1 : 0; + axis.setExtent(axisExtent[idx], axisExtent[1 - idx]); + }); + each$5(dimensions, function (dim, idx) { + var posInfo = (layoutInfo.axisExpandable ? layoutAxisWithExpand : layoutAxisWithoutExpand)(idx, layoutInfo); + var positionTable = { + horizontal: { + x: posInfo.position, + y: layoutInfo.axisLength + }, + vertical: { + x: 0, + y: posInfo.position + } + }; + var rotationTable = { + horizontal: PI$7 / 2, + vertical: 0 + }; + var position = [positionTable[layout].x + rect.x, positionTable[layout].y + rect.y]; + var rotation = rotationTable[layout]; + var transform = create$1(); + rotate(transform, transform, rotation); + translate(transform, transform, position); // TODO + // tick layout info + // TODO + // update dimensions info based on axis order. + + this._axesLayout[dim] = { + position: position, + rotation: rotation, + transform: transform, + axisNameAvailableWidth: posInfo.axisNameAvailableWidth, + axisLabelShow: posInfo.axisLabelShow, + nameTruncateMaxWidth: posInfo.nameTruncateMaxWidth, + tickDirection: 1, + labelDirection: 1 + }; + }, this); + }; + /** + * Get axis by dim. + */ + + + Parallel.prototype.getAxis = function (dim) { + return this._axesMap.get(dim); + }; + /** + * Convert a dim value of a single item of series data to Point. + */ + + + Parallel.prototype.dataToPoint = function (value, dim) { + return this.axisCoordToPoint(this._axesMap.get(dim).dataToCoord(value), dim); + }; + /** + * Travel data for one time, get activeState of each data item. + * @param start the start dataIndex that travel from. + * @param end the next dataIndex of the last dataIndex will be travel. + */ + + + Parallel.prototype.eachActiveState = function (data, callback, start, end) { + start == null && (start = 0); + end == null && (end = data.count()); + var axesMap = this._axesMap; + var dimensions = this.dimensions; + var dataDimensions = []; + var axisModels = []; + each(dimensions, function (axisDim) { + dataDimensions.push(data.mapDimension(axisDim)); + axisModels.push(axesMap.get(axisDim).model); + }); + var hasActiveSet = this.hasAxisBrushed(); + + for (var dataIndex = start; dataIndex < end; dataIndex++) { + var activeState = void 0; + + if (!hasActiveSet) { + activeState = 'normal'; + } else { + activeState = 'active'; + var values = data.getValues(dataDimensions, dataIndex); + + for (var j = 0, lenj = dimensions.length; j < lenj; j++) { + var state = axisModels[j].getActiveState(values[j]); + + if (state === 'inactive') { + activeState = 'inactive'; + break; + } + } + } + + callback(activeState, dataIndex); + } + }; + /** + * Whether has any activeSet. + */ + + + Parallel.prototype.hasAxisBrushed = function () { + var dimensions = this.dimensions; + var axesMap = this._axesMap; + var hasActiveSet = false; + + for (var j = 0, lenj = dimensions.length; j < lenj; j++) { + if (axesMap.get(dimensions[j]).model.getActiveState() !== 'normal') { + hasActiveSet = true; + } + } + + return hasActiveSet; + }; + /** + * Convert coords of each axis to Point. + * Return point. For example: [10, 20] + */ + + + Parallel.prototype.axisCoordToPoint = function (coord, dim) { + var axisLayout = this._axesLayout[dim]; + return applyTransform$1([coord, 0], axisLayout.transform); + }; + /** + * Get axis layout. + */ + + + Parallel.prototype.getAxisLayout = function (dim) { + return clone(this._axesLayout[dim]); + }; + /** + * @return {Object} {axisExpandWindow, delta, behavior: 'jump' | 'slide' | 'none'}. + */ + + + Parallel.prototype.getSlidedAxisExpandWindow = function (point) { + var layoutInfo = this._makeLayoutInfo(); + + var pixelDimIndex = layoutInfo.pixelDimIndex; + var axisExpandWindow = layoutInfo.axisExpandWindow.slice(); + var winSize = axisExpandWindow[1] - axisExpandWindow[0]; + var extent = [0, layoutInfo.axisExpandWidth * (layoutInfo.axisCount - 1)]; // Out of the area of coordinate system. + + if (!this.containPoint(point)) { + return { + behavior: 'none', + axisExpandWindow: axisExpandWindow + }; + } // Conver the point from global to expand coordinates. + + + var pointCoord = point[pixelDimIndex] - layoutInfo.layoutBase - layoutInfo.axisExpandWindow0Pos; // For dragging operation convenience, the window should not be + // slided when mouse is the center area of the window. + + var delta; + var behavior = 'slide'; + var axisCollapseWidth = layoutInfo.axisCollapseWidth; + + var triggerArea = this._model.get('axisExpandSlideTriggerArea'); // But consider touch device, jump is necessary. + + + var useJump = triggerArea[0] != null; + + if (axisCollapseWidth) { + if (useJump && axisCollapseWidth && pointCoord < winSize * triggerArea[0]) { + behavior = 'jump'; + delta = pointCoord - winSize * triggerArea[2]; + } else if (useJump && axisCollapseWidth && pointCoord > winSize * (1 - triggerArea[0])) { + behavior = 'jump'; + delta = pointCoord - winSize * (1 - triggerArea[2]); + } else { + (delta = pointCoord - winSize * triggerArea[1]) >= 0 && (delta = pointCoord - winSize * (1 - triggerArea[1])) <= 0 && (delta = 0); + } + + delta *= layoutInfo.axisExpandWidth / axisCollapseWidth; + delta ? sliderMove(delta, axisExpandWindow, extent, 'all') // Avoid nonsense triger on mousemove. + : behavior = 'none'; + } // When screen is too narrow, make it visible and slidable, although it is hard to interact. + else { + var winSize2 = axisExpandWindow[1] - axisExpandWindow[0]; + var pos = extent[1] * pointCoord / winSize2; + axisExpandWindow = [mathMax$8(0, pos - winSize2 / 2)]; + axisExpandWindow[1] = mathMin$8(extent[1], axisExpandWindow[0] + winSize2); + axisExpandWindow[0] = axisExpandWindow[1] - winSize2; + } + + return { + axisExpandWindow: axisExpandWindow, + behavior: behavior + }; + }; + + return Parallel; + }(); + + function restrict$1(len, extent) { + return mathMin$8(mathMax$8(len, extent[0]), extent[1]); + } + + function layoutAxisWithoutExpand(axisIndex, layoutInfo) { + var step = layoutInfo.layoutLength / (layoutInfo.axisCount - 1); + return { + position: step * axisIndex, + axisNameAvailableWidth: step, + axisLabelShow: true + }; + } + + function layoutAxisWithExpand(axisIndex, layoutInfo) { + var layoutLength = layoutInfo.layoutLength; + var axisExpandWidth = layoutInfo.axisExpandWidth; + var axisCount = layoutInfo.axisCount; + var axisCollapseWidth = layoutInfo.axisCollapseWidth; + var winInnerIndices = layoutInfo.winInnerIndices; + var position; + var axisNameAvailableWidth = axisCollapseWidth; + var axisLabelShow = false; + var nameTruncateMaxWidth; + + if (axisIndex < winInnerIndices[0]) { + position = axisIndex * axisCollapseWidth; + nameTruncateMaxWidth = axisCollapseWidth; + } else if (axisIndex <= winInnerIndices[1]) { + position = layoutInfo.axisExpandWindow0Pos + axisIndex * axisExpandWidth - layoutInfo.axisExpandWindow[0]; + axisNameAvailableWidth = axisExpandWidth; + axisLabelShow = true; + } else { + position = layoutLength - (axisCount - 1 - axisIndex) * axisCollapseWidth; + nameTruncateMaxWidth = axisCollapseWidth; + } + + return { + position: position, + axisNameAvailableWidth: axisNameAvailableWidth, + axisLabelShow: axisLabelShow, + nameTruncateMaxWidth: nameTruncateMaxWidth + }; + } + + function createParallelCoordSys(ecModel, api) { + var coordSysList = []; + ecModel.eachComponent('parallel', function (parallelModel, idx) { + var coordSys = new Parallel(parallelModel, ecModel, api); + coordSys.name = 'parallel_' + idx; + coordSys.resize(parallelModel, api); + parallelModel.coordinateSystem = coordSys; + coordSys.model = parallelModel; + coordSysList.push(coordSys); + }); // Inject the coordinateSystems into seriesModel + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'parallel') { + var parallelModel = seriesModel.getReferringComponents('parallel', SINGLE_REFERRING).models[0]; + seriesModel.coordinateSystem = parallelModel.coordinateSystem; + } + }); + return coordSysList; + } + + var parallelCoordSysCreator = { + create: createParallelCoordSys + }; + + var ParallelAxisModel = + /** @class */ + function (_super) { + __extends(ParallelAxisModel, _super); + + function ParallelAxisModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ParallelAxisModel.type; + /** + * @readOnly + */ + + _this.activeIntervals = []; + return _this; + } + + ParallelAxisModel.prototype.getAreaSelectStyle = function () { + return makeStyleMapper([['fill', 'color'], ['lineWidth', 'borderWidth'], ['stroke', 'borderColor'], ['width', 'width'], ['opacity', 'opacity'] // Option decal is in `DecalObject` but style.decal is in `PatternObject`. + // So do not transfer decal directly. + ])(this.getModel('areaSelectStyle')); + }; + /** + * The code of this feature is put on AxisModel but not ParallelAxis, + * because axisModel can be alive after echarts updating but instance of + * ParallelAxis having been disposed. this._activeInterval should be kept + * when action dispatched (i.e. legend click). + * + * @param intervals `interval.length === 0` means set all active. + */ + + + ParallelAxisModel.prototype.setActiveIntervals = function (intervals) { + var activeIntervals = this.activeIntervals = clone(intervals); // Normalize + + if (activeIntervals) { + for (var i = activeIntervals.length - 1; i >= 0; i--) { + asc(activeIntervals[i]); + } + } + }; + /** + * @param value When only attempting detect whether 'no activeIntervals set', + * `value` is not needed to be input. + */ + + + ParallelAxisModel.prototype.getActiveState = function (value) { + var activeIntervals = this.activeIntervals; + + if (!activeIntervals.length) { + return 'normal'; + } + + if (value == null || isNaN(+value)) { + return 'inactive'; + } // Simple optimization + + + if (activeIntervals.length === 1) { + var interval = activeIntervals[0]; + + if (interval[0] <= value && value <= interval[1]) { + return 'active'; + } + } else { + for (var i = 0, len = activeIntervals.length; i < len; i++) { + if (activeIntervals[i][0] <= value && value <= activeIntervals[i][1]) { + return 'active'; + } + } + } + + return 'inactive'; + }; + + return ParallelAxisModel; + }(ComponentModel); + + mixin(ParallelAxisModel, AxisModelCommonMixin); + + var BRUSH_PANEL_GLOBAL = true; + var mathMin$9 = Math.min; + var mathMax$9 = Math.max; + var mathPow$2 = Math.pow; + var COVER_Z = 10000; + var UNSELECT_THRESHOLD = 6; + var MIN_RESIZE_LINE_WIDTH = 6; + var MUTEX_RESOURCE_KEY = 'globalPan'; + var DIRECTION_MAP = { + w: [0, 0], + e: [0, 1], + n: [1, 0], + s: [1, 1] + }; + var CURSOR_MAP = { + w: 'ew', + e: 'ew', + n: 'ns', + s: 'ns', + ne: 'nesw', + sw: 'nesw', + nw: 'nwse', + se: 'nwse' + }; + var DEFAULT_BRUSH_OPT = { + brushStyle: { + lineWidth: 2, + stroke: 'rgba(210,219,238,0.3)', + fill: '#D2DBEE' + }, + transformable: true, + brushMode: 'single', + removeOnClick: false + }; + var baseUID = 0; + /** + * params: + * areas: Array., coord relates to container group, + * If no container specified, to global. + * opt { + * isEnd: boolean, + * removeOnClick: boolean + * } + */ + + var BrushController = + /** @class */ + function (_super) { + __extends(BrushController, _super); + + function BrushController(zr) { + var _this = _super.call(this) || this; + /** + * @internal + */ + + + _this._track = []; + /** + * @internal + */ + + _this._covers = []; + _this._handlers = {}; + + if ("development" !== 'production') { + assert(zr); + } + + _this._zr = zr; + _this.group = new Group(); + _this._uid = 'brushController_' + baseUID++; + each(pointerHandlers, function (handler, eventName) { + this._handlers[eventName] = bind(handler, this); + }, _this); + return _this; + } + /** + * If set to `false`, select disabled. + */ + + + BrushController.prototype.enableBrush = function (brushOption) { + if ("development" !== 'production') { + assert(this._mounted); + } + + this._brushType && this._doDisableBrush(); + brushOption.brushType && this._doEnableBrush(brushOption); + return this; + }; + + BrushController.prototype._doEnableBrush = function (brushOption) { + var zr = this._zr; // Consider roam, which takes globalPan too. + + if (!this._enableGlobalPan) { + take(zr, MUTEX_RESOURCE_KEY, this._uid); + } + + each(this._handlers, function (handler, eventName) { + zr.on(eventName, handler); + }); + this._brushType = brushOption.brushType; + this._brushOption = merge(clone(DEFAULT_BRUSH_OPT), brushOption, true); + }; + + BrushController.prototype._doDisableBrush = function () { + var zr = this._zr; + release(zr, MUTEX_RESOURCE_KEY, this._uid); + each(this._handlers, function (handler, eventName) { + zr.off(eventName, handler); + }); + this._brushType = this._brushOption = null; + }; + /** + * @param panelOpts If not pass, it is global brush. + */ + + + BrushController.prototype.setPanels = function (panelOpts) { + if (panelOpts && panelOpts.length) { + var panels_1 = this._panels = {}; + each(panelOpts, function (panelOpts) { + panels_1[panelOpts.panelId] = clone(panelOpts); + }); + } else { + this._panels = null; + } + + return this; + }; + + BrushController.prototype.mount = function (opt) { + opt = opt || {}; + + if ("development" !== 'production') { + this._mounted = true; // should be at first. + } + + this._enableGlobalPan = opt.enableGlobalPan; + var thisGroup = this.group; + + this._zr.add(thisGroup); + + thisGroup.attr({ + x: opt.x || 0, + y: opt.y || 0, + rotation: opt.rotation || 0, + scaleX: opt.scaleX || 1, + scaleY: opt.scaleY || 1 + }); + this._transform = thisGroup.getLocalTransform(); + return this; + }; // eachCover(cb, context): void { + // each(this._covers, cb, context); + // } + + /** + * Update covers. + * @param coverConfigList + * If coverConfigList is null/undefined, all covers removed. + */ + + + BrushController.prototype.updateCovers = function (coverConfigList) { + if ("development" !== 'production') { + assert(this._mounted); + } + + coverConfigList = map(coverConfigList, function (coverConfig) { + return merge(clone(DEFAULT_BRUSH_OPT), coverConfig, true); + }); + var tmpIdPrefix = '\0-brush-index-'; + var oldCovers = this._covers; + var newCovers = this._covers = []; + var controller = this; + var creatingCover = this._creatingCover; + new DataDiffer(oldCovers, coverConfigList, oldGetKey, getKey).add(addOrUpdate).update(addOrUpdate).remove(remove).execute(); + return this; + + function getKey(brushOption, index) { + return (brushOption.id != null ? brushOption.id : tmpIdPrefix + index) + '-' + brushOption.brushType; + } + + function oldGetKey(cover, index) { + return getKey(cover.__brushOption, index); + } + + function addOrUpdate(newIndex, oldIndex) { + var newBrushInternal = coverConfigList[newIndex]; // Consider setOption in event listener of brushSelect, + // where updating cover when creating should be forbiden. + + if (oldIndex != null && oldCovers[oldIndex] === creatingCover) { + newCovers[newIndex] = oldCovers[oldIndex]; + } else { + var cover = newCovers[newIndex] = oldIndex != null ? (oldCovers[oldIndex].__brushOption = newBrushInternal, oldCovers[oldIndex]) : endCreating(controller, createCover(controller, newBrushInternal)); + updateCoverAfterCreation(controller, cover); + } + } + + function remove(oldIndex) { + if (oldCovers[oldIndex] !== creatingCover) { + controller.group.remove(oldCovers[oldIndex]); + } + } + }; + + BrushController.prototype.unmount = function () { + if ("development" !== 'production') { + if (!this._mounted) { + return; + } + } + + this.enableBrush(false); // container may 'removeAll' outside. + + clearCovers(this); + + this._zr.remove(this.group); + + if ("development" !== 'production') { + this._mounted = false; // should be at last. + } + + return this; + }; + + BrushController.prototype.dispose = function () { + this.unmount(); + this.off(); + }; + + return BrushController; + }(Eventful); + + function createCover(controller, brushOption) { + var cover = coverRenderers[brushOption.brushType].createCover(controller, brushOption); + cover.__brushOption = brushOption; + updateZ(cover, brushOption); + controller.group.add(cover); + return cover; + } + + function endCreating(controller, creatingCover) { + var coverRenderer = getCoverRenderer(creatingCover); + + if (coverRenderer.endCreating) { + coverRenderer.endCreating(controller, creatingCover); + updateZ(creatingCover, creatingCover.__brushOption); + } + + return creatingCover; + } + + function updateCoverShape(controller, cover) { + var brushOption = cover.__brushOption; + getCoverRenderer(cover).updateCoverShape(controller, cover, brushOption.range, brushOption); + } + + function updateZ(cover, brushOption) { + var z = brushOption.z; + z == null && (z = COVER_Z); + cover.traverse(function (el) { + el.z = z; + el.z2 = z; // Consider in given container. + }); + } + + function updateCoverAfterCreation(controller, cover) { + getCoverRenderer(cover).updateCommon(controller, cover); + updateCoverShape(controller, cover); + } + + function getCoverRenderer(cover) { + return coverRenderers[cover.__brushOption.brushType]; + } // return target panel or `true` (means global panel) + + + function getPanelByPoint(controller, e, localCursorPoint) { + var panels = controller._panels; + + if (!panels) { + return BRUSH_PANEL_GLOBAL; // Global panel + } + + var panel; + var transform = controller._transform; + each(panels, function (pn) { + pn.isTargetByCursor(e, localCursorPoint, transform) && (panel = pn); + }); + return panel; + } // Return a panel or true + + + function getPanelByCover(controller, cover) { + var panels = controller._panels; + + if (!panels) { + return BRUSH_PANEL_GLOBAL; // Global panel + } + + var panelId = cover.__brushOption.panelId; // User may give cover without coord sys info, + // which is then treated as global panel. + + return panelId != null ? panels[panelId] : BRUSH_PANEL_GLOBAL; + } + + function clearCovers(controller) { + var covers = controller._covers; + var originalLength = covers.length; + each(covers, function (cover) { + controller.group.remove(cover); + }, controller); + covers.length = 0; + return !!originalLength; + } + + function trigger$1(controller, opt) { + var areas = map(controller._covers, function (cover) { + var brushOption = cover.__brushOption; + var range = clone(brushOption.range); + return { + brushType: brushOption.brushType, + panelId: brushOption.panelId, + range: range + }; + }); + controller.trigger('brush', { + areas: areas, + isEnd: !!opt.isEnd, + removeOnClick: !!opt.removeOnClick + }); + } + + function shouldShowCover(controller) { + var track = controller._track; + + if (!track.length) { + return false; + } + + var p2 = track[track.length - 1]; + var p1 = track[0]; + var dx = p2[0] - p1[0]; + var dy = p2[1] - p1[1]; + var dist = mathPow$2(dx * dx + dy * dy, 0.5); + return dist > UNSELECT_THRESHOLD; + } + + function getTrackEnds(track) { + var tail = track.length - 1; + tail < 0 && (tail = 0); + return [track[0], track[tail]]; + } + + function createBaseRectCover(rectRangeConverter, controller, brushOption, edgeNameSequences) { + var cover = new Group(); + cover.add(new Rect({ + name: 'main', + style: makeStyle(brushOption), + silent: true, + draggable: true, + cursor: 'move', + drift: curry(driftRect, rectRangeConverter, controller, cover, ['n', 's', 'w', 'e']), + ondragend: curry(trigger$1, controller, { + isEnd: true + }) + })); + each(edgeNameSequences, function (nameSequence) { + cover.add(new Rect({ + name: nameSequence.join(''), + style: { + opacity: 0 + }, + draggable: true, + silent: true, + invisible: true, + drift: curry(driftRect, rectRangeConverter, controller, cover, nameSequence), + ondragend: curry(trigger$1, controller, { + isEnd: true + }) + })); + }); + return cover; + } + + function updateBaseRect(controller, cover, localRange, brushOption) { + var lineWidth = brushOption.brushStyle.lineWidth || 0; + var handleSize = mathMax$9(lineWidth, MIN_RESIZE_LINE_WIDTH); + var x = localRange[0][0]; + var y = localRange[1][0]; + var xa = x - lineWidth / 2; + var ya = y - lineWidth / 2; + var x2 = localRange[0][1]; + var y2 = localRange[1][1]; + var x2a = x2 - handleSize + lineWidth / 2; + var y2a = y2 - handleSize + lineWidth / 2; + var width = x2 - x; + var height = y2 - y; + var widtha = width + lineWidth; + var heighta = height + lineWidth; + updateRectShape(controller, cover, 'main', x, y, width, height); + + if (brushOption.transformable) { + updateRectShape(controller, cover, 'w', xa, ya, handleSize, heighta); + updateRectShape(controller, cover, 'e', x2a, ya, handleSize, heighta); + updateRectShape(controller, cover, 'n', xa, ya, widtha, handleSize); + updateRectShape(controller, cover, 's', xa, y2a, widtha, handleSize); + updateRectShape(controller, cover, 'nw', xa, ya, handleSize, handleSize); + updateRectShape(controller, cover, 'ne', x2a, ya, handleSize, handleSize); + updateRectShape(controller, cover, 'sw', xa, y2a, handleSize, handleSize); + updateRectShape(controller, cover, 'se', x2a, y2a, handleSize, handleSize); + } + } + + function updateCommon(controller, cover) { + var brushOption = cover.__brushOption; + var transformable = brushOption.transformable; + var mainEl = cover.childAt(0); + mainEl.useStyle(makeStyle(brushOption)); + mainEl.attr({ + silent: !transformable, + cursor: transformable ? 'move' : 'default' + }); + each([['w'], ['e'], ['n'], ['s'], ['s', 'e'], ['s', 'w'], ['n', 'e'], ['n', 'w']], function (nameSequence) { + var el = cover.childOfName(nameSequence.join('')); + var globalDir = nameSequence.length === 1 ? getGlobalDirection1(controller, nameSequence[0]) : getGlobalDirection2(controller, nameSequence); + el && el.attr({ + silent: !transformable, + invisible: !transformable, + cursor: transformable ? CURSOR_MAP[globalDir] + '-resize' : null + }); + }); + } + + function updateRectShape(controller, cover, name, x, y, w, h) { + var el = cover.childOfName(name); + el && el.setShape(pointsToRect(clipByPanel(controller, cover, [[x, y], [x + w, y + h]]))); + } + + function makeStyle(brushOption) { + return defaults({ + strokeNoScale: true + }, brushOption.brushStyle); + } + + function formatRectRange(x, y, x2, y2) { + var min = [mathMin$9(x, x2), mathMin$9(y, y2)]; + var max = [mathMax$9(x, x2), mathMax$9(y, y2)]; + return [[min[0], max[0]], [min[1], max[1]] // y range + ]; + } + + function getTransform$1(controller) { + return getTransform(controller.group); + } + + function getGlobalDirection1(controller, localDirName) { + var map = { + w: 'left', + e: 'right', + n: 'top', + s: 'bottom' + }; + var inverseMap = { + left: 'w', + right: 'e', + top: 'n', + bottom: 's' + }; + var dir = transformDirection(map[localDirName], getTransform$1(controller)); + return inverseMap[dir]; + } + + function getGlobalDirection2(controller, localDirNameSeq) { + var globalDir = [getGlobalDirection1(controller, localDirNameSeq[0]), getGlobalDirection1(controller, localDirNameSeq[1])]; + (globalDir[0] === 'e' || globalDir[0] === 'w') && globalDir.reverse(); + return globalDir.join(''); + } + + function driftRect(rectRangeConverter, controller, cover, dirNameSequence, dx, dy) { + var brushOption = cover.__brushOption; + var rectRange = rectRangeConverter.toRectRange(brushOption.range); + var localDelta = toLocalDelta(controller, dx, dy); + each(dirNameSequence, function (dirName) { + var ind = DIRECTION_MAP[dirName]; + rectRange[ind[0]][ind[1]] += localDelta[ind[0]]; + }); + brushOption.range = rectRangeConverter.fromRectRange(formatRectRange(rectRange[0][0], rectRange[1][0], rectRange[0][1], rectRange[1][1])); + updateCoverAfterCreation(controller, cover); + trigger$1(controller, { + isEnd: false + }); + } + + function driftPolygon(controller, cover, dx, dy) { + var range = cover.__brushOption.range; + var localDelta = toLocalDelta(controller, dx, dy); + each(range, function (point) { + point[0] += localDelta[0]; + point[1] += localDelta[1]; + }); + updateCoverAfterCreation(controller, cover); + trigger$1(controller, { + isEnd: false + }); + } + + function toLocalDelta(controller, dx, dy) { + var thisGroup = controller.group; + var localD = thisGroup.transformCoordToLocal(dx, dy); + var localZero = thisGroup.transformCoordToLocal(0, 0); + return [localD[0] - localZero[0], localD[1] - localZero[1]]; + } + + function clipByPanel(controller, cover, data) { + var panel = getPanelByCover(controller, cover); + return panel && panel !== BRUSH_PANEL_GLOBAL ? panel.clipPath(data, controller._transform) : clone(data); + } + + function pointsToRect(points) { + var xmin = mathMin$9(points[0][0], points[1][0]); + var ymin = mathMin$9(points[0][1], points[1][1]); + var xmax = mathMax$9(points[0][0], points[1][0]); + var ymax = mathMax$9(points[0][1], points[1][1]); + return { + x: xmin, + y: ymin, + width: xmax - xmin, + height: ymax - ymin + }; + } + + function resetCursor(controller, e, localCursorPoint) { + if ( // Check active + !controller._brushType // resetCursor should be always called when mouse is in zr area, + // but not called when mouse is out of zr area to avoid bad influence + // if `mousemove`, `mouseup` are triggered from `document` event. + || isOutsideZrArea(controller, e.offsetX, e.offsetY)) { + return; + } + + var zr = controller._zr; + var covers = controller._covers; + var currPanel = getPanelByPoint(controller, e, localCursorPoint); // Check whether in covers. + + if (!controller._dragging) { + for (var i = 0; i < covers.length; i++) { + var brushOption = covers[i].__brushOption; + + if (currPanel && (currPanel === BRUSH_PANEL_GLOBAL || brushOption.panelId === currPanel.panelId) && coverRenderers[brushOption.brushType].contain(covers[i], localCursorPoint[0], localCursorPoint[1])) { + // Use cursor style set on cover. + return; + } + } + } + + currPanel && zr.setCursorStyle('crosshair'); + } + + function preventDefault(e) { + var rawE = e.event; + rawE.preventDefault && rawE.preventDefault(); + } + + function mainShapeContain(cover, x, y) { + return cover.childOfName('main').contain(x, y); + } + + function updateCoverByMouse(controller, e, localCursorPoint, isEnd) { + var creatingCover = controller._creatingCover; + var panel = controller._creatingPanel; + var thisBrushOption = controller._brushOption; + var eventParams; + + controller._track.push(localCursorPoint.slice()); + + if (shouldShowCover(controller) || creatingCover) { + if (panel && !creatingCover) { + thisBrushOption.brushMode === 'single' && clearCovers(controller); + var brushOption = clone(thisBrushOption); + brushOption.brushType = determineBrushType(brushOption.brushType, panel); + brushOption.panelId = panel === BRUSH_PANEL_GLOBAL ? null : panel.panelId; + creatingCover = controller._creatingCover = createCover(controller, brushOption); + + controller._covers.push(creatingCover); + } + + if (creatingCover) { + var coverRenderer = coverRenderers[determineBrushType(controller._brushType, panel)]; + var coverBrushOption = creatingCover.__brushOption; + coverBrushOption.range = coverRenderer.getCreatingRange(clipByPanel(controller, creatingCover, controller._track)); + + if (isEnd) { + endCreating(controller, creatingCover); + coverRenderer.updateCommon(controller, creatingCover); + } + + updateCoverShape(controller, creatingCover); + eventParams = { + isEnd: isEnd + }; + } + } else if (isEnd && thisBrushOption.brushMode === 'single' && thisBrushOption.removeOnClick) { + // Help user to remove covers easily, only by a tiny drag, in 'single' mode. + // But a single click do not clear covers, because user may have casual + // clicks (for example, click on other component and do not expect covers + // disappear). + // Only some cover removed, trigger action, but not every click trigger action. + if (getPanelByPoint(controller, e, localCursorPoint) && clearCovers(controller)) { + eventParams = { + isEnd: isEnd, + removeOnClick: true + }; + } + } + + return eventParams; + } + + function determineBrushType(brushType, panel) { + if (brushType === 'auto') { + if ("development" !== 'production') { + assert(panel && panel.defaultBrushType, 'MUST have defaultBrushType when brushType is "atuo"'); + } + + return panel.defaultBrushType; + } + + return brushType; + } + + var pointerHandlers = { + mousedown: function (e) { + if (this._dragging) { + // In case some browser do not support globalOut, + // and release mouse out side the browser. + handleDragEnd(this, e); + } else if (!e.target || !e.target.draggable) { + preventDefault(e); + var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY); + this._creatingCover = null; + var panel = this._creatingPanel = getPanelByPoint(this, e, localCursorPoint); + + if (panel) { + this._dragging = true; + this._track = [localCursorPoint.slice()]; + } + } + }, + mousemove: function (e) { + var x = e.offsetX; + var y = e.offsetY; + var localCursorPoint = this.group.transformCoordToLocal(x, y); + resetCursor(this, e, localCursorPoint); + + if (this._dragging) { + preventDefault(e); + var eventParams = updateCoverByMouse(this, e, localCursorPoint, false); + eventParams && trigger$1(this, eventParams); + } + }, + mouseup: function (e) { + handleDragEnd(this, e); + } + }; + + function handleDragEnd(controller, e) { + if (controller._dragging) { + preventDefault(e); + var x = e.offsetX; + var y = e.offsetY; + var localCursorPoint = controller.group.transformCoordToLocal(x, y); + var eventParams = updateCoverByMouse(controller, e, localCursorPoint, true); + controller._dragging = false; + controller._track = []; + controller._creatingCover = null; // trigger event shoule be at final, after procedure will be nested. + + eventParams && trigger$1(controller, eventParams); + } + } + + function isOutsideZrArea(controller, x, y) { + var zr = controller._zr; + return x < 0 || x > zr.getWidth() || y < 0 || y > zr.getHeight(); + } + /** + * key: brushType + */ + + + var coverRenderers = { + lineX: getLineRenderer(0), + lineY: getLineRenderer(1), + rect: { + createCover: function (controller, brushOption) { + function returnInput(range) { + return range; + } + + return createBaseRectCover({ + toRectRange: returnInput, + fromRectRange: returnInput + }, controller, brushOption, [['w'], ['e'], ['n'], ['s'], ['s', 'e'], ['s', 'w'], ['n', 'e'], ['n', 'w']]); + }, + getCreatingRange: function (localTrack) { + var ends = getTrackEnds(localTrack); + return formatRectRange(ends[1][0], ends[1][1], ends[0][0], ends[0][1]); + }, + updateCoverShape: function (controller, cover, localRange, brushOption) { + updateBaseRect(controller, cover, localRange, brushOption); + }, + updateCommon: updateCommon, + contain: mainShapeContain + }, + polygon: { + createCover: function (controller, brushOption) { + var cover = new Group(); // Do not use graphic.Polygon because graphic.Polyline do not close the + // border of the shape when drawing, which is a better experience for user. + + cover.add(new Polyline({ + name: 'main', + style: makeStyle(brushOption), + silent: true + })); + return cover; + }, + getCreatingRange: function (localTrack) { + return localTrack; + }, + endCreating: function (controller, cover) { + cover.remove(cover.childAt(0)); // Use graphic.Polygon close the shape. + + cover.add(new Polygon({ + name: 'main', + draggable: true, + drift: curry(driftPolygon, controller, cover), + ondragend: curry(trigger$1, controller, { + isEnd: true + }) + })); + }, + updateCoverShape: function (controller, cover, localRange, brushOption) { + cover.childAt(0).setShape({ + points: clipByPanel(controller, cover, localRange) + }); + }, + updateCommon: updateCommon, + contain: mainShapeContain + } + }; + + function getLineRenderer(xyIndex) { + return { + createCover: function (controller, brushOption) { + return createBaseRectCover({ + toRectRange: function (range) { + var rectRange = [range, [0, 100]]; + xyIndex && rectRange.reverse(); + return rectRange; + }, + fromRectRange: function (rectRange) { + return rectRange[xyIndex]; + } + }, controller, brushOption, [[['w'], ['e']], [['n'], ['s']]][xyIndex]); + }, + getCreatingRange: function (localTrack) { + var ends = getTrackEnds(localTrack); + var min = mathMin$9(ends[0][xyIndex], ends[1][xyIndex]); + var max = mathMax$9(ends[0][xyIndex], ends[1][xyIndex]); + return [min, max]; + }, + updateCoverShape: function (controller, cover, localRange, brushOption) { + var otherExtent; // If brushWidth not specified, fit the panel. + + var panel = getPanelByCover(controller, cover); + + if (panel !== BRUSH_PANEL_GLOBAL && panel.getLinearBrushOtherExtent) { + otherExtent = panel.getLinearBrushOtherExtent(xyIndex); + } else { + var zr = controller._zr; + otherExtent = [0, [zr.getWidth(), zr.getHeight()][1 - xyIndex]]; + } + + var rectRange = [localRange, otherExtent]; + xyIndex && rectRange.reverse(); + updateBaseRect(controller, cover, rectRange, brushOption); + }, + updateCommon: updateCommon, + contain: mainShapeContain + }; + } + + function makeRectPanelClipPath(rect) { + rect = normalizeRect(rect); + return function (localPoints) { + return clipPointsByRect(localPoints, rect); + }; + } + function makeLinearBrushOtherExtent(rect, specifiedXYIndex) { + rect = normalizeRect(rect); + return function (xyIndex) { + var idx = specifiedXYIndex != null ? specifiedXYIndex : xyIndex; + var brushWidth = idx ? rect.width : rect.height; + var base = idx ? rect.x : rect.y; + return [base, base + (brushWidth || 0)]; + }; + } + function makeRectIsTargetByCursor(rect, api, targetModel) { + var boundingRect = normalizeRect(rect); + return function (e, localCursorPoint) { + return boundingRect.contain(localCursorPoint[0], localCursorPoint[1]) && !onIrrelevantElement(e, api, targetModel); + }; + } // Consider width/height is negative. + + function normalizeRect(rect) { + return BoundingRect.create(rect); + } + + var elementList = ['axisLine', 'axisTickLabel', 'axisName']; + + var ParallelAxisView = + /** @class */ + function (_super) { + __extends(ParallelAxisView, _super); + + function ParallelAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ParallelAxisView.type; + return _this; + } + + ParallelAxisView.prototype.init = function (ecModel, api) { + _super.prototype.init.apply(this, arguments); + + (this._brushController = new BrushController(api.getZr())).on('brush', bind(this._onBrush, this)); + }; + + ParallelAxisView.prototype.render = function (axisModel, ecModel, api, payload) { + if (fromAxisAreaSelect(axisModel, ecModel, payload)) { + return; + } + + this.axisModel = axisModel; + this.api = api; + this.group.removeAll(); + var oldAxisGroup = this._axisGroup; + this._axisGroup = new Group(); + this.group.add(this._axisGroup); + + if (!axisModel.get('show')) { + return; + } + + var coordSysModel = getCoordSysModel(axisModel, ecModel); + var coordSys = coordSysModel.coordinateSystem; + var areaSelectStyle = axisModel.getAreaSelectStyle(); + var areaWidth = areaSelectStyle.width; + var dim = axisModel.axis.dim; + var axisLayout = coordSys.getAxisLayout(dim); + var builderOpt = extend({ + strokeContainThreshold: areaWidth + }, axisLayout); + var axisBuilder = new AxisBuilder(axisModel, builderOpt); + each(elementList, axisBuilder.add, axisBuilder); + + this._axisGroup.add(axisBuilder.getGroup()); + + this._refreshBrushController(builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api); + + groupTransition(oldAxisGroup, this._axisGroup, axisModel); + }; // /** + // * @override + // */ + // updateVisual(axisModel, ecModel, api, payload) { + // this._brushController && this._brushController + // .updateCovers(getCoverInfoList(axisModel)); + // } + + + ParallelAxisView.prototype._refreshBrushController = function (builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api) { + // After filtering, axis may change, select area needs to be update. + var extent = axisModel.axis.getExtent(); + var extentLen = extent[1] - extent[0]; + var extra = Math.min(30, Math.abs(extentLen) * 0.1); // Arbitrary value. + // width/height might be negative, which will be + // normalized in BoundingRect. + + var rect = BoundingRect.create({ + x: extent[0], + y: -areaWidth / 2, + width: extentLen, + height: areaWidth + }); + rect.x -= extra; + rect.width += 2 * extra; + + this._brushController.mount({ + enableGlobalPan: true, + rotation: builderOpt.rotation, + x: builderOpt.position[0], + y: builderOpt.position[1] + }).setPanels([{ + panelId: 'pl', + clipPath: makeRectPanelClipPath(rect), + isTargetByCursor: makeRectIsTargetByCursor(rect, api, coordSysModel), + getLinearBrushOtherExtent: makeLinearBrushOtherExtent(rect, 0) + }]).enableBrush({ + brushType: 'lineX', + brushStyle: areaSelectStyle, + removeOnClick: true + }).updateCovers(getCoverInfoList(axisModel)); + }; + + ParallelAxisView.prototype._onBrush = function (eventParam) { + var coverInfoList = eventParam.areas; // Do not cache these object, because the mey be changed. + + var axisModel = this.axisModel; + var axis = axisModel.axis; + var intervals = map(coverInfoList, function (coverInfo) { + return [axis.coordToData(coverInfo.range[0], true), axis.coordToData(coverInfo.range[1], true)]; + }); // If realtime is true, action is not dispatched on drag end, because + // the drag end emits the same params with the last drag move event, + // and may have some delay when using touch pad. + + if (!axisModel.option.realtime === eventParam.isEnd || eventParam.removeOnClick) { + // jshint ignore:line + this.api.dispatchAction({ + type: 'axisAreaSelect', + parallelAxisId: axisModel.id, + intervals: intervals + }); + } + }; + + ParallelAxisView.prototype.dispose = function () { + this._brushController.dispose(); + }; + + ParallelAxisView.type = 'parallelAxis'; + return ParallelAxisView; + }(ComponentView); + + function fromAxisAreaSelect(axisModel, ecModel, payload) { + return payload && payload.type === 'axisAreaSelect' && ecModel.findComponents({ + mainType: 'parallelAxis', + query: payload + })[0] === axisModel; + } + + function getCoverInfoList(axisModel) { + var axis = axisModel.axis; + return map(axisModel.activeIntervals, function (interval) { + return { + brushType: 'lineX', + panelId: 'pl', + range: [axis.dataToCoord(interval[0], true), axis.dataToCoord(interval[1], true)] + }; + }); + } + + function getCoordSysModel(axisModel, ecModel) { + return ecModel.getComponent('parallel', axisModel.get('parallelIndex')); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var actionInfo$1 = { + type: 'axisAreaSelect', + event: 'axisAreaSelected' // update: 'updateVisual' + + }; + function installParallelActions(registers) { + registers.registerAction(actionInfo$1, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'parallelAxis', + query: payload + }, function (parallelAxisModel) { + parallelAxisModel.axis.model.setActiveIntervals(payload.intervals); + }); + }); + /** + * @payload + */ + + registers.registerAction('parallelAxisExpand', function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'parallel', + query: payload + }, function (parallelModel) { + parallelModel.setAxisExpand(payload); + }); + }); + } + + var defaultAxisOption = { + type: 'value', + areaSelectStyle: { + width: 20, + borderWidth: 1, + borderColor: 'rgba(160,197,232)', + color: 'rgba(160,197,232)', + opacity: 0.3 + }, + realtime: true, + z: 10 + }; + function install$g(registers) { + registers.registerComponentView(ParallelView$1); + registers.registerComponentModel(ParallelModel); + registers.registerCoordinateSystem('parallel', parallelCoordSysCreator); + registers.registerPreprocessor(parallelPreprocessor); + registers.registerComponentModel(ParallelAxisModel); + registers.registerComponentView(ParallelAxisView); + axisModelCreator(registers, 'parallel', ParallelAxisModel, defaultAxisOption); + installParallelActions(registers); + } + + function install$h(registers) { + use(install$g); + registers.registerChartView(ParallelView); + registers.registerSeriesModel(ParallelSeriesModel); + registers.registerVisual(registers.PRIORITY.VISUAL.BRUSH, parallelVisual); + } + + var SankeyPathShape = + /** @class */ + function () { + function SankeyPathShape() { + this.x1 = 0; + this.y1 = 0; + this.x2 = 0; + this.y2 = 0; + this.cpx1 = 0; + this.cpy1 = 0; + this.cpx2 = 0; + this.cpy2 = 0; + this.extent = 0; + } + + return SankeyPathShape; + }(); + + var SankeyPath = + /** @class */ + function (_super) { + __extends(SankeyPath, _super); + + function SankeyPath(opts) { + return _super.call(this, opts) || this; + } + + SankeyPath.prototype.getDefaultShape = function () { + return new SankeyPathShape(); + }; + + SankeyPath.prototype.buildPath = function (ctx, shape) { + var extent = shape.extent; + ctx.moveTo(shape.x1, shape.y1); + ctx.bezierCurveTo(shape.cpx1, shape.cpy1, shape.cpx2, shape.cpy2, shape.x2, shape.y2); + + if (shape.orient === 'vertical') { + ctx.lineTo(shape.x2 + extent, shape.y2); + ctx.bezierCurveTo(shape.cpx2 + extent, shape.cpy2, shape.cpx1 + extent, shape.cpy1, shape.x1 + extent, shape.y1); + } else { + ctx.lineTo(shape.x2, shape.y2 + extent); + ctx.bezierCurveTo(shape.cpx2, shape.cpy2 + extent, shape.cpx1, shape.cpy1 + extent, shape.x1, shape.y1 + extent); + } + + ctx.closePath(); + }; + + SankeyPath.prototype.highlight = function () { + enterEmphasis(this); + }; + + SankeyPath.prototype.downplay = function () { + leaveEmphasis(this); + }; + + return SankeyPath; + }(Path); + + var SankeyView = + /** @class */ + function (_super) { + __extends(SankeyView, _super); + + function SankeyView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SankeyView.type; + _this._focusAdjacencyDisabled = false; + return _this; + } + + SankeyView.prototype.render = function (seriesModel, ecModel, api) { + var sankeyView = this; + var graph = seriesModel.getGraph(); + var group = this.group; + var layoutInfo = seriesModel.layoutInfo; // view width + + var width = layoutInfo.width; // view height + + var height = layoutInfo.height; + var nodeData = seriesModel.getData(); + var edgeData = seriesModel.getData('edge'); + var orient = seriesModel.get('orient'); + this._model = seriesModel; + group.removeAll(); + group.x = layoutInfo.x; + group.y = layoutInfo.y; // generate a bezire Curve for each edge + + graph.eachEdge(function (edge) { + var curve = new SankeyPath(); + var ecData = getECData(curve); + ecData.dataIndex = edge.dataIndex; + ecData.seriesIndex = seriesModel.seriesIndex; + ecData.dataType = 'edge'; + var edgeModel = edge.getModel(); + var lineStyleModel = edgeModel.getModel('lineStyle'); + var curvature = lineStyleModel.get('curveness'); + var n1Layout = edge.node1.getLayout(); + var node1Model = edge.node1.getModel(); + var dragX1 = node1Model.get('localX'); + var dragY1 = node1Model.get('localY'); + var n2Layout = edge.node2.getLayout(); + var node2Model = edge.node2.getModel(); + var dragX2 = node2Model.get('localX'); + var dragY2 = node2Model.get('localY'); + var edgeLayout = edge.getLayout(); + var x1; + var y1; + var x2; + var y2; + var cpx1; + var cpy1; + var cpx2; + var cpy2; + curve.shape.extent = Math.max(1, edgeLayout.dy); + curve.shape.orient = orient; + + if (orient === 'vertical') { + x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + edgeLayout.sy; + y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + n1Layout.dy; + x2 = (dragX2 != null ? dragX2 * width : n2Layout.x) + edgeLayout.ty; + y2 = dragY2 != null ? dragY2 * height : n2Layout.y; + cpx1 = x1; + cpy1 = y1 * (1 - curvature) + y2 * curvature; + cpx2 = x2; + cpy2 = y1 * curvature + y2 * (1 - curvature); + } else { + x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + n1Layout.dx; + y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + edgeLayout.sy; + x2 = dragX2 != null ? dragX2 * width : n2Layout.x; + y2 = (dragY2 != null ? dragY2 * height : n2Layout.y) + edgeLayout.ty; + cpx1 = x1 * (1 - curvature) + x2 * curvature; + cpy1 = y1; + cpx2 = x1 * curvature + x2 * (1 - curvature); + cpy2 = y2; + } + + curve.setShape({ + x1: x1, + y1: y1, + x2: x2, + y2: y2, + cpx1: cpx1, + cpy1: cpy1, + cpx2: cpx2, + cpy2: cpy2 + }); + curve.useStyle(lineStyleModel.getItemStyle()); // Special color, use source node color or target node color + + switch (curve.style.fill) { + case 'source': + curve.style.fill = edge.node1.getVisual('color'); + curve.style.decal = edge.node1.getVisual('style').decal; + break; + + case 'target': + curve.style.fill = edge.node2.getVisual('color'); + curve.style.decal = edge.node2.getVisual('style').decal; + break; + + case 'gradient': + var sourceColor = edge.node1.getVisual('color'); + var targetColor = edge.node2.getVisual('color'); + + if (isString(sourceColor) && isString(targetColor)) { + curve.style.fill = new LinearGradient(0, 0, +(orient === 'horizontal'), +(orient === 'vertical'), [{ + color: sourceColor, + offset: 0 + }, { + color: targetColor, + offset: 1 + }]); + } + + } + + var emphasisModel = edgeModel.getModel('emphasis'); + setStatesStylesFromModel(curve, edgeModel, 'lineStyle', function (model) { + return model.getItemStyle(); + }); + group.add(curve); + edgeData.setItemGraphicEl(edge.dataIndex, curve); + var focus = emphasisModel.get('focus'); + toggleHoverEmphasis(curve, focus === 'adjacency' ? edge.getAdjacentDataIndices() : focus, emphasisModel.get('blurScope'), emphasisModel.get('disabled')); + getECData(curve).dataType = 'edge'; + }); // Generate a rect for each node + + graph.eachNode(function (node) { + var layout = node.getLayout(); + var itemModel = node.getModel(); + var dragX = itemModel.get('localX'); + var dragY = itemModel.get('localY'); + var emphasisModel = itemModel.getModel('emphasis'); + var rect = new Rect({ + shape: { + x: dragX != null ? dragX * width : layout.x, + y: dragY != null ? dragY * height : layout.y, + width: layout.dx, + height: layout.dy + }, + style: itemModel.getModel('itemStyle').getItemStyle(), + z2: 10 + }); + setLabelStyle(rect, getLabelStatesModels(itemModel), { + labelFetcher: seriesModel, + labelDataIndex: node.dataIndex, + defaultText: node.id + }); + rect.disableLabelAnimation = true; + rect.setStyle('fill', node.getVisual('color')); + rect.setStyle('decal', node.getVisual('style').decal); + setStatesStylesFromModel(rect, itemModel); + group.add(rect); + nodeData.setItemGraphicEl(node.dataIndex, rect); + getECData(rect).dataType = 'node'; + var focus = emphasisModel.get('focus'); + toggleHoverEmphasis(rect, focus === 'adjacency' ? node.getAdjacentDataIndices() : focus, emphasisModel.get('blurScope'), emphasisModel.get('disabled')); + }); + nodeData.eachItemGraphicEl(function (el, dataIndex) { + var itemModel = nodeData.getItemModel(dataIndex); + + if (itemModel.get('draggable')) { + el.drift = function (dx, dy) { + sankeyView._focusAdjacencyDisabled = true; + this.shape.x += dx; + this.shape.y += dy; + this.dirty(); + api.dispatchAction({ + type: 'dragNode', + seriesId: seriesModel.id, + dataIndex: nodeData.getRawIndex(dataIndex), + localX: this.shape.x / width, + localY: this.shape.y / height + }); + }; + + el.ondragend = function () { + sankeyView._focusAdjacencyDisabled = false; + }; + + el.draggable = true; + el.cursor = 'move'; + } + }); + + if (!this._data && seriesModel.isAnimationEnabled()) { + group.setClipPath(createGridClipShape$1(group.getBoundingRect(), seriesModel, function () { + group.removeClipPath(); + })); + } + + this._data = seriesModel.getData(); + }; + + SankeyView.prototype.dispose = function () {}; + + SankeyView.type = 'sankey'; + return SankeyView; + }(ChartView); // Add animation to the view + + + function createGridClipShape$1(rect, seriesModel, cb) { + var rectEl = new Rect({ + shape: { + x: rect.x - 10, + y: rect.y - 10, + width: 0, + height: rect.height + 20 + } + }); + initProps(rectEl, { + shape: { + width: rect.width + 20 + } + }, seriesModel, cb); + return rectEl; + } + + var SankeySeriesModel = + /** @class */ + function (_super) { + __extends(SankeySeriesModel, _super); + + function SankeySeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SankeySeriesModel.type; + return _this; + } + /** + * Init a graph data structure from data in option series + */ + + + SankeySeriesModel.prototype.getInitialData = function (option, ecModel) { + var links = option.edges || option.links; + var nodes = option.data || option.nodes; + var levels = option.levels; + this.levelModels = []; + var levelModels = this.levelModels; + + for (var i = 0; i < levels.length; i++) { + if (levels[i].depth != null && levels[i].depth >= 0) { + levelModels[levels[i].depth] = new Model(levels[i], this, ecModel); + } else { + if ("development" !== 'production') { + throw new Error('levels[i].depth is mandatory and should be natural number'); + } + } + } + + if (nodes && links) { + var graph = createGraphFromNodeEdge(nodes, links, this, true, beforeLink); + return graph.data; + } + + function beforeLink(nodeData, edgeData) { + nodeData.wrapMethod('getItemModel', function (model, idx) { + var seriesModel = model.parentModel; + var layout = seriesModel.getData().getItemLayout(idx); + + if (layout) { + var nodeDepth = layout.depth; + var levelModel = seriesModel.levelModels[nodeDepth]; + + if (levelModel) { + model.parentModel = levelModel; + } + } + + return model; + }); + edgeData.wrapMethod('getItemModel', function (model, idx) { + var seriesModel = model.parentModel; + var edge = seriesModel.getGraph().getEdgeByIndex(idx); + var layout = edge.node1.getLayout(); + + if (layout) { + var depth = layout.depth; + var levelModel = seriesModel.levelModels[depth]; + + if (levelModel) { + model.parentModel = levelModel; + } + } + + return model; + }); + } + }; + + SankeySeriesModel.prototype.setNodePosition = function (dataIndex, localPosition) { + var nodes = this.option.data || this.option.nodes; + var dataItem = nodes[dataIndex]; + dataItem.localX = localPosition[0]; + dataItem.localY = localPosition[1]; + }; + /** + * Return the graphic data structure + * + * @return graphic data structure + */ + + + SankeySeriesModel.prototype.getGraph = function () { + return this.getData().graph; + }; + /** + * Get edge data of graphic data structure + * + * @return data structure of list + */ + + + SankeySeriesModel.prototype.getEdgeData = function () { + return this.getGraph().edgeData; + }; + + SankeySeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + function noValue(val) { + return isNaN(val) || val == null; + } // dataType === 'node' or empty do not show tooltip by default + + + if (dataType === 'edge') { + var params = this.getDataParams(dataIndex, dataType); + var rawDataOpt = params.data; + var edgeValue = params.value; + var edgeName = rawDataOpt.source + ' -- ' + rawDataOpt.target; + return createTooltipMarkup('nameValue', { + name: edgeName, + value: edgeValue, + noValue: noValue(edgeValue) + }); + } // dataType === 'node' + else { + var node = this.getGraph().getNodeByIndex(dataIndex); + var value = node.getLayout().value; + var name_1 = this.getDataParams(dataIndex, dataType).data.name; + return createTooltipMarkup('nameValue', { + name: name_1 != null ? name_1 + '' : null, + value: value, + noValue: noValue(value) + }); + } + }; + + SankeySeriesModel.prototype.optionUpdated = function () {}; // Override Series.getDataParams() + + + SankeySeriesModel.prototype.getDataParams = function (dataIndex, dataType) { + var params = _super.prototype.getDataParams.call(this, dataIndex, dataType); + + if (params.value == null && dataType === 'node') { + var node = this.getGraph().getNodeByIndex(dataIndex); + var nodeValue = node.getLayout().value; + params.value = nodeValue; + } + + return params; + }; + + SankeySeriesModel.type = 'series.sankey'; + SankeySeriesModel.defaultOption = { + // zlevel: 0, + z: 2, + coordinateSystem: 'view', + left: '5%', + top: '5%', + right: '20%', + bottom: '5%', + orient: 'horizontal', + nodeWidth: 20, + nodeGap: 8, + draggable: true, + layoutIterations: 32, + label: { + show: true, + position: 'right', + fontSize: 12 + }, + levels: [], + nodeAlign: 'justify', + lineStyle: { + color: '#314656', + opacity: 0.2, + curveness: 0.5 + }, + emphasis: { + label: { + show: true + }, + lineStyle: { + opacity: 0.5 + } + }, + select: { + itemStyle: { + borderColor: '#212121' + } + }, + animationEasing: 'linear', + animationDuration: 1000 + }; + return SankeySeriesModel; + }(SeriesModel); + + function sankeyLayout(ecModel, api) { + ecModel.eachSeriesByType('sankey', function (seriesModel) { + var nodeWidth = seriesModel.get('nodeWidth'); + var nodeGap = seriesModel.get('nodeGap'); + var layoutInfo = getViewRect$4(seriesModel, api); + seriesModel.layoutInfo = layoutInfo; + var width = layoutInfo.width; + var height = layoutInfo.height; + var graph = seriesModel.getGraph(); + var nodes = graph.nodes; + var edges = graph.edges; + computeNodeValues(nodes); + var filteredNodes = filter(nodes, function (node) { + return node.getLayout().value === 0; + }); + var iterations = filteredNodes.length !== 0 ? 0 : seriesModel.get('layoutIterations'); + var orient = seriesModel.get('orient'); + var nodeAlign = seriesModel.get('nodeAlign'); + layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign); + }); + } + /** + * Get the layout position of the whole view + */ + + function getViewRect$4(seriesModel, api) { + return getLayoutRect(seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + } + + function layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign) { + computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient, nodeAlign); + computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient); + computeEdgeDepths(nodes, orient); + } + /** + * Compute the value of each node by summing the associated edge's value + */ + + + function computeNodeValues(nodes) { + each(nodes, function (node) { + var value1 = sum(node.outEdges, getEdgeValue); + var value2 = sum(node.inEdges, getEdgeValue); + var nodeRawValue = node.getValue() || 0; + var value = Math.max(value1, value2, nodeRawValue); + node.setLayout({ + value: value + }, true); + }); + } + /** + * Compute the x-position for each node. + * + * Here we use Kahn algorithm to detect cycle when we traverse + * the node to computer the initial x position. + */ + + + function computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient, nodeAlign) { + // Used to mark whether the edge is deleted. if it is deleted, + // the value is 0, otherwise it is 1. + var remainEdges = []; // Storage each node's indegree. + + var indegreeArr = []; //Used to storage the node with indegree is equal to 0. + + var zeroIndegrees = []; + var nextTargetNode = []; + var x = 0; // let kx = 0; + + for (var i = 0; i < edges.length; i++) { + remainEdges[i] = 1; + } + + for (var i = 0; i < nodes.length; i++) { + indegreeArr[i] = nodes[i].inEdges.length; + + if (indegreeArr[i] === 0) { + zeroIndegrees.push(nodes[i]); + } + } + + var maxNodeDepth = -1; // Traversing nodes using topological sorting to calculate the + // horizontal(if orient === 'horizontal') or vertical(if orient === 'vertical') + // position of the nodes. + + while (zeroIndegrees.length) { + for (var idx = 0; idx < zeroIndegrees.length; idx++) { + var node = zeroIndegrees[idx]; + var item = node.hostGraph.data.getRawDataItem(node.dataIndex); + var isItemDepth = item.depth != null && item.depth >= 0; + + if (isItemDepth && item.depth > maxNodeDepth) { + maxNodeDepth = item.depth; + } + + node.setLayout({ + depth: isItemDepth ? item.depth : x + }, true); + orient === 'vertical' ? node.setLayout({ + dy: nodeWidth + }, true) : node.setLayout({ + dx: nodeWidth + }, true); + + for (var edgeIdx = 0; edgeIdx < node.outEdges.length; edgeIdx++) { + var edge = node.outEdges[edgeIdx]; + var indexEdge = edges.indexOf(edge); + remainEdges[indexEdge] = 0; + var targetNode = edge.node2; + var nodeIndex = nodes.indexOf(targetNode); + + if (--indegreeArr[nodeIndex] === 0 && nextTargetNode.indexOf(targetNode) < 0) { + nextTargetNode.push(targetNode); + } + } + } + + ++x; + zeroIndegrees = nextTargetNode; + nextTargetNode = []; + } + + for (var i = 0; i < remainEdges.length; i++) { + if (remainEdges[i] === 1) { + throw new Error('Sankey is a DAG, the original data has cycle!'); + } + } + + var maxDepth = maxNodeDepth > x - 1 ? maxNodeDepth : x - 1; + + if (nodeAlign && nodeAlign !== 'left') { + adjustNodeWithNodeAlign(nodes, nodeAlign, orient, maxDepth); + } + + var kx = orient === 'vertical' ? (height - nodeWidth) / maxDepth : (width - nodeWidth) / maxDepth; + scaleNodeBreadths(nodes, kx, orient); + } + + function isNodeDepth(node) { + var item = node.hostGraph.data.getRawDataItem(node.dataIndex); + return item.depth != null && item.depth >= 0; + } + + function adjustNodeWithNodeAlign(nodes, nodeAlign, orient, maxDepth) { + if (nodeAlign === 'right') { + var nextSourceNode = []; + var remainNodes = nodes; + var nodeHeight = 0; + + while (remainNodes.length) { + for (var i = 0; i < remainNodes.length; i++) { + var node = remainNodes[i]; + node.setLayout({ + skNodeHeight: nodeHeight + }, true); + + for (var j = 0; j < node.inEdges.length; j++) { + var edge = node.inEdges[j]; + + if (nextSourceNode.indexOf(edge.node1) < 0) { + nextSourceNode.push(edge.node1); + } + } + } + + remainNodes = nextSourceNode; + nextSourceNode = []; + ++nodeHeight; + } + + each(nodes, function (node) { + if (!isNodeDepth(node)) { + node.setLayout({ + depth: Math.max(0, maxDepth - node.getLayout().skNodeHeight) + }, true); + } + }); + } else if (nodeAlign === 'justify') { + moveSinksRight(nodes, maxDepth); + } + } + /** + * All the node without outEgdes are assigned maximum x-position and + * be aligned in the last column. + * + * @param nodes. node of sankey view. + * @param maxDepth. use to assign to node without outEdges as x-position. + */ + + + function moveSinksRight(nodes, maxDepth) { + each(nodes, function (node) { + if (!isNodeDepth(node) && !node.outEdges.length) { + node.setLayout({ + depth: maxDepth + }, true); + } + }); + } + /** + * Scale node x-position to the width + * + * @param nodes node of sankey view + * @param kx multiple used to scale nodes + */ + + + function scaleNodeBreadths(nodes, kx, orient) { + each(nodes, function (node) { + var nodeDepth = node.getLayout().depth * kx; + orient === 'vertical' ? node.setLayout({ + y: nodeDepth + }, true) : node.setLayout({ + x: nodeDepth + }, true); + }); + } + /** + * Using Gauss-Seidel iterations method to compute the node depth(y-position) + * + * @param nodes node of sankey view + * @param edges edge of sankey view + * @param height the whole height of the area to draw the view + * @param nodeGap the vertical distance between two nodes + * in the same column. + * @param iterations the number of iterations for the algorithm + */ + + + function computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient) { + var nodesByBreadth = prepareNodesByBreadth(nodes, orient); + initializeNodeDepth(nodesByBreadth, edges, height, width, nodeGap, orient); + resolveCollisions(nodesByBreadth, nodeGap, height, width, orient); + + for (var alpha = 1; iterations > 0; iterations--) { + // 0.99 is a experience parameter, ensure that each iterations of + // changes as small as possible. + alpha *= 0.99; + relaxRightToLeft(nodesByBreadth, alpha, orient); + resolveCollisions(nodesByBreadth, nodeGap, height, width, orient); + relaxLeftToRight(nodesByBreadth, alpha, orient); + resolveCollisions(nodesByBreadth, nodeGap, height, width, orient); + } + } + + function prepareNodesByBreadth(nodes, orient) { + var nodesByBreadth = []; + var keyAttr = orient === 'vertical' ? 'y' : 'x'; + var groupResult = groupData(nodes, function (node) { + return node.getLayout()[keyAttr]; + }); + groupResult.keys.sort(function (a, b) { + return a - b; + }); + each(groupResult.keys, function (key) { + nodesByBreadth.push(groupResult.buckets.get(key)); + }); + return nodesByBreadth; + } + /** + * Compute the original y-position for each node + */ + + + function initializeNodeDepth(nodesByBreadth, edges, height, width, nodeGap, orient) { + var minKy = Infinity; + each(nodesByBreadth, function (nodes) { + var n = nodes.length; + var sum = 0; + each(nodes, function (node) { + sum += node.getLayout().value; + }); + var ky = orient === 'vertical' ? (width - (n - 1) * nodeGap) / sum : (height - (n - 1) * nodeGap) / sum; + + if (ky < minKy) { + minKy = ky; + } + }); + each(nodesByBreadth, function (nodes) { + each(nodes, function (node, i) { + var nodeDy = node.getLayout().value * minKy; + + if (orient === 'vertical') { + node.setLayout({ + x: i + }, true); + node.setLayout({ + dx: nodeDy + }, true); + } else { + node.setLayout({ + y: i + }, true); + node.setLayout({ + dy: nodeDy + }, true); + } + }); + }); + each(edges, function (edge) { + var edgeDy = +edge.getValue() * minKy; + edge.setLayout({ + dy: edgeDy + }, true); + }); + } + /** + * Resolve the collision of initialized depth (y-position) + */ + + + function resolveCollisions(nodesByBreadth, nodeGap, height, width, orient) { + var keyAttr = orient === 'vertical' ? 'x' : 'y'; + each(nodesByBreadth, function (nodes) { + nodes.sort(function (a, b) { + return a.getLayout()[keyAttr] - b.getLayout()[keyAttr]; + }); + var nodeX; + var node; + var dy; + var y0 = 0; + var n = nodes.length; + var nodeDyAttr = orient === 'vertical' ? 'dx' : 'dy'; + + for (var i = 0; i < n; i++) { + node = nodes[i]; + dy = y0 - node.getLayout()[keyAttr]; + + if (dy > 0) { + nodeX = node.getLayout()[keyAttr] + dy; + orient === 'vertical' ? node.setLayout({ + x: nodeX + }, true) : node.setLayout({ + y: nodeX + }, true); + } + + y0 = node.getLayout()[keyAttr] + node.getLayout()[nodeDyAttr] + nodeGap; + } + + var viewWidth = orient === 'vertical' ? width : height; // If the bottommost node goes outside the bounds, push it back up + + dy = y0 - nodeGap - viewWidth; + + if (dy > 0) { + nodeX = node.getLayout()[keyAttr] - dy; + orient === 'vertical' ? node.setLayout({ + x: nodeX + }, true) : node.setLayout({ + y: nodeX + }, true); + y0 = nodeX; + + for (var i = n - 2; i >= 0; --i) { + node = nodes[i]; + dy = node.getLayout()[keyAttr] + node.getLayout()[nodeDyAttr] + nodeGap - y0; + + if (dy > 0) { + nodeX = node.getLayout()[keyAttr] - dy; + orient === 'vertical' ? node.setLayout({ + x: nodeX + }, true) : node.setLayout({ + y: nodeX + }, true); + } + + y0 = node.getLayout()[keyAttr]; + } + } + }); + } + /** + * Change the y-position of the nodes, except most the right side nodes + * @param nodesByBreadth + * @param alpha parameter used to adjust the nodes y-position + */ + + + function relaxRightToLeft(nodesByBreadth, alpha, orient) { + each(nodesByBreadth.slice().reverse(), function (nodes) { + each(nodes, function (node) { + if (node.outEdges.length) { + var y = sum(node.outEdges, weightedTarget, orient) / sum(node.outEdges, getEdgeValue); + + if (isNaN(y)) { + var len = node.outEdges.length; + y = len ? sum(node.outEdges, centerTarget, orient) / len : 0; + } + + if (orient === 'vertical') { + var nodeX = node.getLayout().x + (y - center$1(node, orient)) * alpha; + node.setLayout({ + x: nodeX + }, true); + } else { + var nodeY = node.getLayout().y + (y - center$1(node, orient)) * alpha; + node.setLayout({ + y: nodeY + }, true); + } + } + }); + }); + } + + function weightedTarget(edge, orient) { + return center$1(edge.node2, orient) * edge.getValue(); + } + + function centerTarget(edge, orient) { + return center$1(edge.node2, orient); + } + + function weightedSource(edge, orient) { + return center$1(edge.node1, orient) * edge.getValue(); + } + + function centerSource(edge, orient) { + return center$1(edge.node1, orient); + } + + function center$1(node, orient) { + return orient === 'vertical' ? node.getLayout().x + node.getLayout().dx / 2 : node.getLayout().y + node.getLayout().dy / 2; + } + + function getEdgeValue(edge) { + return edge.getValue(); + } + + function sum(array, cb, orient) { + var sum = 0; + var len = array.length; + var i = -1; + + while (++i < len) { + var value = +cb(array[i], orient); + + if (!isNaN(value)) { + sum += value; + } + } + + return sum; + } + /** + * Change the y-position of the nodes, except most the left side nodes + */ + + + function relaxLeftToRight(nodesByBreadth, alpha, orient) { + each(nodesByBreadth, function (nodes) { + each(nodes, function (node) { + if (node.inEdges.length) { + var y = sum(node.inEdges, weightedSource, orient) / sum(node.inEdges, getEdgeValue); + + if (isNaN(y)) { + var len = node.inEdges.length; + y = len ? sum(node.inEdges, centerSource, orient) / len : 0; + } + + if (orient === 'vertical') { + var nodeX = node.getLayout().x + (y - center$1(node, orient)) * alpha; + node.setLayout({ + x: nodeX + }, true); + } else { + var nodeY = node.getLayout().y + (y - center$1(node, orient)) * alpha; + node.setLayout({ + y: nodeY + }, true); + } + } + }); + }); + } + /** + * Compute the depth(y-position) of each edge + */ + + + function computeEdgeDepths(nodes, orient) { + var keyAttr = orient === 'vertical' ? 'x' : 'y'; + each(nodes, function (node) { + node.outEdges.sort(function (a, b) { + return a.node2.getLayout()[keyAttr] - b.node2.getLayout()[keyAttr]; + }); + node.inEdges.sort(function (a, b) { + return a.node1.getLayout()[keyAttr] - b.node1.getLayout()[keyAttr]; + }); + }); + each(nodes, function (node) { + var sy = 0; + var ty = 0; + each(node.outEdges, function (edge) { + edge.setLayout({ + sy: sy + }, true); + sy += edge.getLayout().dy; + }); + each(node.inEdges, function (edge) { + edge.setLayout({ + ty: ty + }, true); + ty += edge.getLayout().dy; + }); + }); + } + + function sankeyVisual(ecModel) { + ecModel.eachSeriesByType('sankey', function (seriesModel) { + var graph = seriesModel.getGraph(); + var nodes = graph.nodes; + + if (nodes.length) { + var minValue_1 = Infinity; + var maxValue_1 = -Infinity; + each(nodes, function (node) { + var nodeValue = node.getLayout().value; + + if (nodeValue < minValue_1) { + minValue_1 = nodeValue; + } + + if (nodeValue > maxValue_1) { + maxValue_1 = nodeValue; + } + }); + each(nodes, function (node) { + var mapping = new VisualMapping({ + type: 'color', + mappingMethod: 'linear', + dataExtent: [minValue_1, maxValue_1], + visual: seriesModel.get('color') + }); + var mapValueToColor = mapping.mapValueToVisual(node.getLayout().value); + var customColor = node.getModel().get(['itemStyle', 'color']); + + if (customColor != null) { + node.setVisual('color', customColor); + node.setVisual('style', { + fill: customColor + }); + } else { + node.setVisual('color', mapValueToColor); + node.setVisual('style', { + fill: mapValueToColor + }); + } + }); + } + }); + } + + function install$i(registers) { + registers.registerChartView(SankeyView); + registers.registerSeriesModel(SankeySeriesModel); + registers.registerLayout(sankeyLayout); + registers.registerVisual(sankeyVisual); + registers.registerAction({ + type: 'dragNode', + event: 'dragnode', + // here can only use 'update' now, other value is not support in echarts. + update: 'update' + }, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', + subType: 'sankey', + query: payload + }, function (seriesModel) { + seriesModel.setNodePosition(payload.dataIndex, [payload.localX, payload.localY]); + }); + }); + } + + var WhiskerBoxCommonMixin = + /** @class */ + function () { + function WhiskerBoxCommonMixin() {} + /** + * @override + */ + + + WhiskerBoxCommonMixin.prototype.getInitialData = function (option, ecModel) { + // When both types of xAxis and yAxis are 'value', layout is + // needed to be specified by user. Otherwise, layout can be + // judged by which axis is category. + var ordinalMeta; + var xAxisModel = ecModel.getComponent('xAxis', this.get('xAxisIndex')); + var yAxisModel = ecModel.getComponent('yAxis', this.get('yAxisIndex')); + var xAxisType = xAxisModel.get('type'); + var yAxisType = yAxisModel.get('type'); + var addOrdinal; // FIXME + // Consider time axis. + + if (xAxisType === 'category') { + option.layout = 'horizontal'; + ordinalMeta = xAxisModel.getOrdinalMeta(); + addOrdinal = true; + } else if (yAxisType === 'category') { + option.layout = 'vertical'; + ordinalMeta = yAxisModel.getOrdinalMeta(); + addOrdinal = true; + } else { + option.layout = option.layout || 'horizontal'; + } + + var coordDims = ['x', 'y']; + var baseAxisDimIndex = option.layout === 'horizontal' ? 0 : 1; + var baseAxisDim = this._baseAxisDim = coordDims[baseAxisDimIndex]; + var otherAxisDim = coordDims[1 - baseAxisDimIndex]; + var axisModels = [xAxisModel, yAxisModel]; + var baseAxisType = axisModels[baseAxisDimIndex].get('type'); + var otherAxisType = axisModels[1 - baseAxisDimIndex].get('type'); + var data = option.data; // Clone a new data for next setOption({}) usage. + // Avoid modifying current data will affect further update. + + if (data && addOrdinal) { + var newOptionData_1 = []; + each(data, function (item, index) { + var newItem; + + if (isArray(item)) { + newItem = item.slice(); // Modify current using data. + + item.unshift(index); + } else if (isArray(item.value)) { + newItem = extend({}, item); + newItem.value = newItem.value.slice(); // Modify current using data. + + item.value.unshift(index); + } else { + newItem = item; + } + + newOptionData_1.push(newItem); + }); + option.data = newOptionData_1; + } + + var defaultValueDimensions = this.defaultValueDimensions; + var coordDimensions = [{ + name: baseAxisDim, + type: getDimensionTypeByAxis(baseAxisType), + ordinalMeta: ordinalMeta, + otherDims: { + tooltip: false, + itemName: 0 + }, + dimsDef: ['base'] + }, { + name: otherAxisDim, + type: getDimensionTypeByAxis(otherAxisType), + dimsDef: defaultValueDimensions.slice() + }]; + return createSeriesDataSimply(this, { + coordDimensions: coordDimensions, + dimensionsCount: defaultValueDimensions.length + 1, + encodeDefaulter: curry(makeSeriesEncodeForAxisCoordSys, coordDimensions, this) + }); + }; + /** + * If horizontal, base axis is x, otherwise y. + * @override + */ + + + WhiskerBoxCommonMixin.prototype.getBaseAxis = function () { + var dim = this._baseAxisDim; + return this.ecModel.getComponent(dim + 'Axis', this.get(dim + 'AxisIndex')).axis; + }; + + return WhiskerBoxCommonMixin; + }(); + + var BoxplotSeriesModel = + /** @class */ + function (_super) { + __extends(BoxplotSeriesModel, _super); + + function BoxplotSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = BoxplotSeriesModel.type; // TODO + // box width represents group size, so dimension should have 'size'. + + /** + * @see + * The meanings of 'min' and 'max' depend on user, + * and echarts do not need to know it. + * @readOnly + */ + + _this.defaultValueDimensions = [{ + name: 'min', + defaultTooltip: true + }, { + name: 'Q1', + defaultTooltip: true + }, { + name: 'median', + defaultTooltip: true + }, { + name: 'Q3', + defaultTooltip: true + }, { + name: 'max', + defaultTooltip: true + }]; + _this.visualDrawType = 'stroke'; + return _this; + } + + BoxplotSeriesModel.type = 'series.boxplot'; + BoxplotSeriesModel.dependencies = ['xAxis', 'yAxis', 'grid']; + BoxplotSeriesModel.defaultOption = { + // zlevel: 0, + z: 2, + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + layout: null, + boxWidth: [7, 50], + itemStyle: { + color: '#fff', + borderWidth: 1 + }, + emphasis: { + scale: true, + itemStyle: { + borderWidth: 2, + shadowBlur: 5, + shadowOffsetX: 1, + shadowOffsetY: 1, + shadowColor: 'rgba(0,0,0,0.2)' + } + }, + animationDuration: 800 + }; + return BoxplotSeriesModel; + }(SeriesModel); + + mixin(BoxplotSeriesModel, WhiskerBoxCommonMixin, true); + + var BoxplotView = + /** @class */ + function (_super) { + __extends(BoxplotView, _super); + + function BoxplotView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = BoxplotView.type; + return _this; + } + + BoxplotView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var group = this.group; + var oldData = this._data; // There is no old data only when first rendering or switching from + // stream mode to normal mode, where previous elements should be removed. + + if (!this._data) { + group.removeAll(); + } + + var constDim = seriesModel.get('layout') === 'horizontal' ? 1 : 0; + data.diff(oldData).add(function (newIdx) { + if (data.hasValue(newIdx)) { + var itemLayout = data.getItemLayout(newIdx); + var symbolEl = createNormalBox(itemLayout, data, newIdx, constDim, true); + data.setItemGraphicEl(newIdx, symbolEl); + group.add(symbolEl); + } + }).update(function (newIdx, oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); // Empty data + + if (!data.hasValue(newIdx)) { + group.remove(symbolEl); + return; + } + + var itemLayout = data.getItemLayout(newIdx); + + if (!symbolEl) { + symbolEl = createNormalBox(itemLayout, data, newIdx, constDim); + } else { + saveOldStyle(symbolEl); + updateNormalBoxData(itemLayout, symbolEl, data, newIdx); + } + + group.add(symbolEl); + data.setItemGraphicEl(newIdx, symbolEl); + }).remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && group.remove(el); + }).execute(); + this._data = data; + }; + + BoxplotView.prototype.remove = function (ecModel) { + var group = this.group; + var data = this._data; + this._data = null; + data && data.eachItemGraphicEl(function (el) { + el && group.remove(el); + }); + }; + + BoxplotView.type = 'boxplot'; + return BoxplotView; + }(ChartView); + + var BoxPathShape = + /** @class */ + function () { + function BoxPathShape() {} + + return BoxPathShape; + }(); + + var BoxPath = + /** @class */ + function (_super) { + __extends(BoxPath, _super); + + function BoxPath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'boxplotBoxPath'; + return _this; + } + + BoxPath.prototype.getDefaultShape = function () { + return new BoxPathShape(); + }; + + BoxPath.prototype.buildPath = function (ctx, shape) { + var ends = shape.points; + var i = 0; + ctx.moveTo(ends[i][0], ends[i][1]); + i++; + + for (; i < 4; i++) { + ctx.lineTo(ends[i][0], ends[i][1]); + } + + ctx.closePath(); + + for (; i < ends.length; i++) { + ctx.moveTo(ends[i][0], ends[i][1]); + i++; + ctx.lineTo(ends[i][0], ends[i][1]); + } + }; + + return BoxPath; + }(Path); + + function createNormalBox(itemLayout, data, dataIndex, constDim, isInit) { + var ends = itemLayout.ends; + var el = new BoxPath({ + shape: { + points: isInit ? transInit(ends, constDim, itemLayout) : ends + } + }); + updateNormalBoxData(itemLayout, el, data, dataIndex, isInit); + return el; + } + + function updateNormalBoxData(itemLayout, el, data, dataIndex, isInit) { + var seriesModel = data.hostModel; + var updateMethod = graphic[isInit ? 'initProps' : 'updateProps']; + updateMethod(el, { + shape: { + points: itemLayout.ends + } + }, seriesModel, dataIndex); + el.useStyle(data.getItemVisual(dataIndex, 'style')); + el.style.strokeNoScale = true; + el.z2 = 100; + var itemModel = data.getItemModel(dataIndex); + var emphasisModel = itemModel.getModel('emphasis'); + setStatesStylesFromModel(el, itemModel); + toggleHoverEmphasis(el, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled')); + } + + function transInit(points, dim, itemLayout) { + return map(points, function (point) { + point = point.slice(); + point[dim] = itemLayout.initBaseline; + return point; + }); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function boxplotVisual(ecModel, api) {} + + var each$6 = each; + function boxplotLayout(ecModel) { + var groupResult = groupSeriesByAxis(ecModel); + each$6(groupResult, function (groupItem) { + var seriesModels = groupItem.seriesModels; + + if (!seriesModels.length) { + return; + } + + calculateBase(groupItem); + each$6(seriesModels, function (seriesModel, idx) { + layoutSingleSeries(seriesModel, groupItem.boxOffsetList[idx], groupItem.boxWidthList[idx]); + }); + }); + } + /** + * Group series by axis. + */ + + function groupSeriesByAxis(ecModel) { + var result = []; + var axisList = []; + ecModel.eachSeriesByType('boxplot', function (seriesModel) { + var baseAxis = seriesModel.getBaseAxis(); + var idx = indexOf(axisList, baseAxis); + + if (idx < 0) { + idx = axisList.length; + axisList[idx] = baseAxis; + result[idx] = { + axis: baseAxis, + seriesModels: [] + }; + } + + result[idx].seriesModels.push(seriesModel); + }); + return result; + } + /** + * Calculate offset and box width for each series. + */ + + + function calculateBase(groupItem) { + var baseAxis = groupItem.axis; + var seriesModels = groupItem.seriesModels; + var seriesCount = seriesModels.length; + var boxWidthList = groupItem.boxWidthList = []; + var boxOffsetList = groupItem.boxOffsetList = []; + var boundList = []; + var bandWidth; + + if (baseAxis.type === 'category') { + bandWidth = baseAxis.getBandWidth(); + } else { + var maxDataCount_1 = 0; + each$6(seriesModels, function (seriesModel) { + maxDataCount_1 = Math.max(maxDataCount_1, seriesModel.getData().count()); + }); + var extent = baseAxis.getExtent(); + bandWidth = Math.abs(extent[1] - extent[0]) / maxDataCount_1; + } + + each$6(seriesModels, function (seriesModel) { + var boxWidthBound = seriesModel.get('boxWidth'); + + if (!isArray(boxWidthBound)) { + boxWidthBound = [boxWidthBound, boxWidthBound]; + } + + boundList.push([parsePercent$1(boxWidthBound[0], bandWidth) || 0, parsePercent$1(boxWidthBound[1], bandWidth) || 0]); + }); + var availableWidth = bandWidth * 0.8 - 2; + var boxGap = availableWidth / seriesCount * 0.3; + var boxWidth = (availableWidth - boxGap * (seriesCount - 1)) / seriesCount; + var base = boxWidth / 2 - availableWidth / 2; + each$6(seriesModels, function (seriesModel, idx) { + boxOffsetList.push(base); + base += boxGap + boxWidth; + boxWidthList.push(Math.min(Math.max(boxWidth, boundList[idx][0]), boundList[idx][1])); + }); + } + /** + * Calculate points location for each series. + */ + + + function layoutSingleSeries(seriesModel, offset, boxWidth) { + var coordSys = seriesModel.coordinateSystem; + var data = seriesModel.getData(); + var halfWidth = boxWidth / 2; + var cDimIdx = seriesModel.get('layout') === 'horizontal' ? 0 : 1; + var vDimIdx = 1 - cDimIdx; + var coordDims = ['x', 'y']; + var cDim = data.mapDimension(coordDims[cDimIdx]); + var vDims = data.mapDimensionsAll(coordDims[vDimIdx]); + + if (cDim == null || vDims.length < 5) { + return; + } + + for (var dataIndex = 0; dataIndex < data.count(); dataIndex++) { + var axisDimVal = data.get(cDim, dataIndex); + var median = getPoint(axisDimVal, vDims[2], dataIndex); + var end1 = getPoint(axisDimVal, vDims[0], dataIndex); + var end2 = getPoint(axisDimVal, vDims[1], dataIndex); + var end4 = getPoint(axisDimVal, vDims[3], dataIndex); + var end5 = getPoint(axisDimVal, vDims[4], dataIndex); + var ends = []; + addBodyEnd(ends, end2, false); + addBodyEnd(ends, end4, true); + ends.push(end1, end2, end5, end4); + layEndLine(ends, end1); + layEndLine(ends, end5); + layEndLine(ends, median); + data.setItemLayout(dataIndex, { + initBaseline: median[vDimIdx], + ends: ends + }); + } + + function getPoint(axisDimVal, dim, dataIndex) { + var val = data.get(dim, dataIndex); + var p = []; + p[cDimIdx] = axisDimVal; + p[vDimIdx] = val; + var point; + + if (isNaN(axisDimVal) || isNaN(val)) { + point = [NaN, NaN]; + } else { + point = coordSys.dataToPoint(p); + point[cDimIdx] += offset; + } + + return point; + } + + function addBodyEnd(ends, point, start) { + var point1 = point.slice(); + var point2 = point.slice(); + point1[cDimIdx] += halfWidth; + point2[cDimIdx] -= halfWidth; + start ? ends.push(point1, point2) : ends.push(point2, point1); + } + + function layEndLine(ends, endCenter) { + var from = endCenter.slice(); + var to = endCenter.slice(); + from[cDimIdx] -= halfWidth; + to[cDimIdx] += halfWidth; + ends.push(from, to); + } + } + + /** + * See: + * + * + * + * Helper method for preparing data. + * + * @param rawData like + * [ + * [12,232,443], (raw data set for the first box) + * [3843,5545,1232], (raw data set for the second box) + * ... + * ] + * @param opt.boundIQR=1.5 Data less than min bound is outlier. + * default 1.5, means Q1 - 1.5 * (Q3 - Q1). + * If 'none'/0 passed, min bound will not be used. + */ + + function prepareBoxplotData(rawData, opt) { + opt = opt || {}; + var boxData = []; + var outliers = []; + var boundIQR = opt.boundIQR; + var useExtreme = boundIQR === 'none' || boundIQR === 0; + + for (var i = 0; i < rawData.length; i++) { + var ascList = asc(rawData[i].slice()); + var Q1 = quantile(ascList, 0.25); + var Q2 = quantile(ascList, 0.5); + var Q3 = quantile(ascList, 0.75); + var min = ascList[0]; + var max = ascList[ascList.length - 1]; + var bound = (boundIQR == null ? 1.5 : boundIQR) * (Q3 - Q1); + var low = useExtreme ? min : Math.max(min, Q1 - bound); + var high = useExtreme ? max : Math.min(max, Q3 + bound); + var itemNameFormatter = opt.itemNameFormatter; + var itemName = isFunction(itemNameFormatter) ? itemNameFormatter({ + value: i + }) : isString(itemNameFormatter) ? itemNameFormatter.replace('{value}', i + '') : i + ''; + boxData.push([itemName, low, Q1, Q2, Q3, high]); + + for (var j = 0; j < ascList.length; j++) { + var dataItem = ascList[j]; + + if (dataItem < low || dataItem > high) { + var outlier = [itemName, dataItem]; + outliers.push(outlier); + } + } + } + + return { + boxData: boxData, + outliers: outliers + }; + } + + var boxplotTransform = { + type: 'echarts:boxplot', + transform: function transform(params) { + var upstream = params.upstream; + + if (upstream.sourceFormat !== SOURCE_FORMAT_ARRAY_ROWS) { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = makePrintable('source data is not applicable for this boxplot transform. Expect number[][].'); + } + + throwError(errMsg); + } + + var result = prepareBoxplotData(upstream.getRawData(), params.config); + return [{ + dimensions: ['ItemName', 'Low', 'Q1', 'Q2', 'Q3', 'High'], + data: result.boxData + }, { + data: result.outliers + }]; + } + }; + + function install$j(registers) { + registers.registerSeriesModel(BoxplotSeriesModel); + registers.registerChartView(BoxplotView); + registers.registerVisual(boxplotVisual); + registers.registerLayout(boxplotLayout); + registers.registerTransform(boxplotTransform); + } + + var SKIP_PROPS = ['color', 'borderColor']; + + var CandlestickView = + /** @class */ + function (_super) { + __extends(CandlestickView, _super); + + function CandlestickView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CandlestickView.type; + return _this; + } + + CandlestickView.prototype.render = function (seriesModel, ecModel, api) { + // If there is clipPath created in large mode. Remove it. + this.group.removeClipPath(); // Clear previously rendered progressive elements. + + this._progressiveEls = null; + + this._updateDrawMode(seriesModel); + + this._isLargeDraw ? this._renderLarge(seriesModel) : this._renderNormal(seriesModel); + }; + + CandlestickView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) { + this._clear(); + + this._updateDrawMode(seriesModel); + }; + + CandlestickView.prototype.incrementalRender = function (params, seriesModel, ecModel, api) { + this._progressiveEls = []; + this._isLargeDraw ? this._incrementalRenderLarge(params, seriesModel) : this._incrementalRenderNormal(params, seriesModel); + }; + + CandlestickView.prototype.eachRendered = function (cb) { + traverseElements(this._progressiveEls || this.group, cb); + }; + + CandlestickView.prototype._updateDrawMode = function (seriesModel) { + var isLargeDraw = seriesModel.pipelineContext.large; + + if (this._isLargeDraw == null || isLargeDraw !== this._isLargeDraw) { + this._isLargeDraw = isLargeDraw; + + this._clear(); + } + }; + + CandlestickView.prototype._renderNormal = function (seriesModel) { + var data = seriesModel.getData(); + var oldData = this._data; + var group = this.group; + var isSimpleBox = data.getLayout('isSimpleBox'); + var needsClip = seriesModel.get('clip', true); + var coord = seriesModel.coordinateSystem; + var clipArea = coord.getArea && coord.getArea(); // There is no old data only when first rendering or switching from + // stream mode to normal mode, where previous elements should be removed. + + if (!this._data) { + group.removeAll(); + } + + data.diff(oldData).add(function (newIdx) { + if (data.hasValue(newIdx)) { + var itemLayout = data.getItemLayout(newIdx); + + if (needsClip && isNormalBoxClipped(clipArea, itemLayout)) { + return; + } + + var el = createNormalBox$1(itemLayout, newIdx, true); + initProps(el, { + shape: { + points: itemLayout.ends + } + }, seriesModel, newIdx); + setBoxCommon(el, data, newIdx, isSimpleBox); + group.add(el); + data.setItemGraphicEl(newIdx, el); + } + }).update(function (newIdx, oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); // Empty data + + if (!data.hasValue(newIdx)) { + group.remove(el); + return; + } + + var itemLayout = data.getItemLayout(newIdx); + + if (needsClip && isNormalBoxClipped(clipArea, itemLayout)) { + group.remove(el); + return; + } + + if (!el) { + el = createNormalBox$1(itemLayout); + } else { + updateProps(el, { + shape: { + points: itemLayout.ends + } + }, seriesModel, newIdx); + saveOldStyle(el); + } + + setBoxCommon(el, data, newIdx, isSimpleBox); + group.add(el); + data.setItemGraphicEl(newIdx, el); + }).remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && group.remove(el); + }).execute(); + this._data = data; + }; + + CandlestickView.prototype._renderLarge = function (seriesModel) { + this._clear(); + + createLarge$1(seriesModel, this.group); + var clipPath = seriesModel.get('clip', true) ? createClipPath(seriesModel.coordinateSystem, false, seriesModel) : null; + + if (clipPath) { + this.group.setClipPath(clipPath); + } else { + this.group.removeClipPath(); + } + }; + + CandlestickView.prototype._incrementalRenderNormal = function (params, seriesModel) { + var data = seriesModel.getData(); + var isSimpleBox = data.getLayout('isSimpleBox'); + var dataIndex; + + while ((dataIndex = params.next()) != null) { + var itemLayout = data.getItemLayout(dataIndex); + var el = createNormalBox$1(itemLayout); + setBoxCommon(el, data, dataIndex, isSimpleBox); + el.incremental = true; + this.group.add(el); + + this._progressiveEls.push(el); + } + }; + + CandlestickView.prototype._incrementalRenderLarge = function (params, seriesModel) { + createLarge$1(seriesModel, this.group, this._progressiveEls, true); + }; + + CandlestickView.prototype.remove = function (ecModel) { + this._clear(); + }; + + CandlestickView.prototype._clear = function () { + this.group.removeAll(); + this._data = null; + }; + + CandlestickView.type = 'candlestick'; + return CandlestickView; + }(ChartView); + + var NormalBoxPathShape = + /** @class */ + function () { + function NormalBoxPathShape() {} + + return NormalBoxPathShape; + }(); + + var NormalBoxPath = + /** @class */ + function (_super) { + __extends(NormalBoxPath, _super); + + function NormalBoxPath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'normalCandlestickBox'; + return _this; + } + + NormalBoxPath.prototype.getDefaultShape = function () { + return new NormalBoxPathShape(); + }; + + NormalBoxPath.prototype.buildPath = function (ctx, shape) { + var ends = shape.points; + + if (this.__simpleBox) { + ctx.moveTo(ends[4][0], ends[4][1]); + ctx.lineTo(ends[6][0], ends[6][1]); + } else { + ctx.moveTo(ends[0][0], ends[0][1]); + ctx.lineTo(ends[1][0], ends[1][1]); + ctx.lineTo(ends[2][0], ends[2][1]); + ctx.lineTo(ends[3][0], ends[3][1]); + ctx.closePath(); + ctx.moveTo(ends[4][0], ends[4][1]); + ctx.lineTo(ends[5][0], ends[5][1]); + ctx.moveTo(ends[6][0], ends[6][1]); + ctx.lineTo(ends[7][0], ends[7][1]); + } + }; + + return NormalBoxPath; + }(Path); + + function createNormalBox$1(itemLayout, dataIndex, isInit) { + var ends = itemLayout.ends; + return new NormalBoxPath({ + shape: { + points: isInit ? transInit$1(ends, itemLayout) : ends + }, + z2: 100 + }); + } + + function isNormalBoxClipped(clipArea, itemLayout) { + var clipped = true; + + for (var i = 0; i < itemLayout.ends.length; i++) { + // If any point are in the region. + if (clipArea.contain(itemLayout.ends[i][0], itemLayout.ends[i][1])) { + clipped = false; + break; + } + } + + return clipped; + } + + function setBoxCommon(el, data, dataIndex, isSimpleBox) { + var itemModel = data.getItemModel(dataIndex); + el.useStyle(data.getItemVisual(dataIndex, 'style')); + el.style.strokeNoScale = true; + el.__simpleBox = isSimpleBox; + setStatesStylesFromModel(el, itemModel); + } + + function transInit$1(points, itemLayout) { + return map(points, function (point) { + point = point.slice(); + point[1] = itemLayout.initBaseline; + return point; + }); + } + + var LargeBoxPathShape = + /** @class */ + function () { + function LargeBoxPathShape() {} + + return LargeBoxPathShape; + }(); + + var LargeBoxPath = + /** @class */ + function (_super) { + __extends(LargeBoxPath, _super); + + function LargeBoxPath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'largeCandlestickBox'; + return _this; + } + + LargeBoxPath.prototype.getDefaultShape = function () { + return new LargeBoxPathShape(); + }; + + LargeBoxPath.prototype.buildPath = function (ctx, shape) { + // Drawing lines is more efficient than drawing + // a whole line or drawing rects. + var points = shape.points; + + for (var i = 0; i < points.length;) { + if (this.__sign === points[i++]) { + var x = points[i++]; + ctx.moveTo(x, points[i++]); + ctx.lineTo(x, points[i++]); + } else { + i += 3; + } + } + }; + + return LargeBoxPath; + }(Path); + + function createLarge$1(seriesModel, group, progressiveEls, incremental) { + var data = seriesModel.getData(); + var largePoints = data.getLayout('largePoints'); + var elP = new LargeBoxPath({ + shape: { + points: largePoints + }, + __sign: 1 + }); + group.add(elP); + var elN = new LargeBoxPath({ + shape: { + points: largePoints + }, + __sign: -1 + }); + group.add(elN); + setLargeStyle(1, elP, seriesModel); + setLargeStyle(-1, elN, seriesModel); + + if (incremental) { + elP.incremental = true; + elN.incremental = true; + } + + if (progressiveEls) { + progressiveEls.push(elP, elN); + } + } + + function setLargeStyle(sign, el, seriesModel, data) { + // TODO put in visual? + var borderColor = seriesModel.get(['itemStyle', sign > 0 ? 'borderColor' : 'borderColor0']) || seriesModel.get(['itemStyle', sign > 0 ? 'color' : 'color0']); // Color must be excluded. + // Because symbol provide setColor individually to set fill and stroke + + var itemStyle = seriesModel.getModel('itemStyle').getItemStyle(SKIP_PROPS); + el.useStyle(itemStyle); + el.style.fill = null; + el.style.stroke = borderColor; + } + + var CandlestickSeriesModel = + /** @class */ + function (_super) { + __extends(CandlestickSeriesModel, _super); + + function CandlestickSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CandlestickSeriesModel.type; + _this.defaultValueDimensions = [{ + name: 'open', + defaultTooltip: true + }, { + name: 'close', + defaultTooltip: true + }, { + name: 'lowest', + defaultTooltip: true + }, { + name: 'highest', + defaultTooltip: true + }]; + return _this; + } + /** + * Get dimension for shadow in dataZoom + * @return dimension name + */ + + + CandlestickSeriesModel.prototype.getShadowDim = function () { + return 'open'; + }; + + CandlestickSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) { + var itemLayout = data.getItemLayout(dataIndex); + return itemLayout && selectors.rect(itemLayout.brushRect); + }; + + CandlestickSeriesModel.type = 'series.candlestick'; + CandlestickSeriesModel.dependencies = ['xAxis', 'yAxis', 'grid']; + CandlestickSeriesModel.defaultOption = { + // zlevel: 0, + z: 2, + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + // xAxisIndex: 0, + // yAxisIndex: 0, + layout: null, + clip: true, + itemStyle: { + color: '#eb5454', + color0: '#47b262', + borderColor: '#eb5454', + borderColor0: '#47b262', + // borderColor: '#d24040', + // borderColor0: '#398f4f', + borderWidth: 1 + }, + emphasis: { + scale: true, + itemStyle: { + borderWidth: 2 + } + }, + barMaxWidth: null, + barMinWidth: null, + barWidth: null, + large: true, + largeThreshold: 600, + progressive: 3e3, + progressiveThreshold: 1e4, + progressiveChunkMode: 'mod', + animationEasing: 'linear', + animationDuration: 300 + }; + return CandlestickSeriesModel; + }(SeriesModel); + + mixin(CandlestickSeriesModel, WhiskerBoxCommonMixin, true); + + function candlestickPreprocessor(option) { + if (!option || !isArray(option.series)) { + return; + } // Translate 'k' to 'candlestick'. + + + each(option.series, function (seriesItem) { + if (isObject(seriesItem) && seriesItem.type === 'k') { + seriesItem.type = 'candlestick'; + } + }); + } + + var positiveBorderColorQuery = ['itemStyle', 'borderColor']; + var negativeBorderColorQuery = ['itemStyle', 'borderColor0']; + var positiveColorQuery = ['itemStyle', 'color']; + var negativeColorQuery = ['itemStyle', 'color0']; + var candlestickVisual = { + seriesType: 'candlestick', + plan: createRenderPlanner(), + // For legend. + performRawSeries: true, + reset: function (seriesModel, ecModel) { + function getColor(sign, model) { + return model.get(sign > 0 ? positiveColorQuery : negativeColorQuery); + } + + function getBorderColor(sign, model) { + return model.get(sign > 0 ? positiveBorderColorQuery : negativeBorderColorQuery); + } // Only visible series has each data be visual encoded + + + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var isLargeRender = seriesModel.pipelineContext.large; + return !isLargeRender && { + progress: function (params, data) { + var dataIndex; + + while ((dataIndex = params.next()) != null) { + var itemModel = data.getItemModel(dataIndex); + var sign = data.getItemLayout(dataIndex).sign; + var style = itemModel.getItemStyle(); + style.fill = getColor(sign, itemModel); + style.stroke = getBorderColor(sign, itemModel) || style.fill; + var existsStyle = data.ensureUniqueItemVisual(dataIndex, 'style'); + extend(existsStyle, style); + } + } + }; + } + }; + + var candlestickLayout = { + seriesType: 'candlestick', + plan: createRenderPlanner(), + reset: function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var data = seriesModel.getData(); + var candleWidth = calculateCandleWidth(seriesModel, data); + var cDimIdx = 0; + var vDimIdx = 1; + var coordDims = ['x', 'y']; + var cDimI = data.getDimensionIndex(data.mapDimension(coordDims[cDimIdx])); + var vDimsI = map(data.mapDimensionsAll(coordDims[vDimIdx]), data.getDimensionIndex, data); + var openDimI = vDimsI[0]; + var closeDimI = vDimsI[1]; + var lowestDimI = vDimsI[2]; + var highestDimI = vDimsI[3]; + data.setLayout({ + candleWidth: candleWidth, + // The value is experimented visually. + isSimpleBox: candleWidth <= 1.3 + }); + + if (cDimI < 0 || vDimsI.length < 4) { + return; + } + + return { + progress: seriesModel.pipelineContext.large ? largeProgress : normalProgress + }; + + function normalProgress(params, data) { + var dataIndex; + var store = data.getStore(); + + while ((dataIndex = params.next()) != null) { + var axisDimVal = store.get(cDimI, dataIndex); + var openVal = store.get(openDimI, dataIndex); + var closeVal = store.get(closeDimI, dataIndex); + var lowestVal = store.get(lowestDimI, dataIndex); + var highestVal = store.get(highestDimI, dataIndex); + var ocLow = Math.min(openVal, closeVal); + var ocHigh = Math.max(openVal, closeVal); + var ocLowPoint = getPoint(ocLow, axisDimVal); + var ocHighPoint = getPoint(ocHigh, axisDimVal); + var lowestPoint = getPoint(lowestVal, axisDimVal); + var highestPoint = getPoint(highestVal, axisDimVal); + var ends = []; + addBodyEnd(ends, ocHighPoint, 0); + addBodyEnd(ends, ocLowPoint, 1); + ends.push(subPixelOptimizePoint(highestPoint), subPixelOptimizePoint(ocHighPoint), subPixelOptimizePoint(lowestPoint), subPixelOptimizePoint(ocLowPoint)); + data.setItemLayout(dataIndex, { + sign: getSign(store, dataIndex, openVal, closeVal, closeDimI), + initBaseline: openVal > closeVal ? ocHighPoint[vDimIdx] : ocLowPoint[vDimIdx], + ends: ends, + brushRect: makeBrushRect(lowestVal, highestVal, axisDimVal) + }); + } + + function getPoint(val, axisDimVal) { + var p = []; + p[cDimIdx] = axisDimVal; + p[vDimIdx] = val; + return isNaN(axisDimVal) || isNaN(val) ? [NaN, NaN] : coordSys.dataToPoint(p); + } + + function addBodyEnd(ends, point, start) { + var point1 = point.slice(); + var point2 = point.slice(); + point1[cDimIdx] = subPixelOptimize$1(point1[cDimIdx] + candleWidth / 2, 1, false); + point2[cDimIdx] = subPixelOptimize$1(point2[cDimIdx] - candleWidth / 2, 1, true); + start ? ends.push(point1, point2) : ends.push(point2, point1); + } + + function makeBrushRect(lowestVal, highestVal, axisDimVal) { + var pmin = getPoint(lowestVal, axisDimVal); + var pmax = getPoint(highestVal, axisDimVal); + pmin[cDimIdx] -= candleWidth / 2; + pmax[cDimIdx] -= candleWidth / 2; + return { + x: pmin[0], + y: pmin[1], + width: candleWidth , + height: pmax[1] - pmin[1] + }; + } + + function subPixelOptimizePoint(point) { + point[cDimIdx] = subPixelOptimize$1(point[cDimIdx], 1); + return point; + } + } + + function largeProgress(params, data) { + // Structure: [sign, x, yhigh, ylow, sign, x, yhigh, ylow, ...] + var points = createFloat32Array(params.count * 4); + var offset = 0; + var point; + var tmpIn = []; + var tmpOut = []; + var dataIndex; + var store = data.getStore(); + + while ((dataIndex = params.next()) != null) { + var axisDimVal = store.get(cDimI, dataIndex); + var openVal = store.get(openDimI, dataIndex); + var closeVal = store.get(closeDimI, dataIndex); + var lowestVal = store.get(lowestDimI, dataIndex); + var highestVal = store.get(highestDimI, dataIndex); + + if (isNaN(axisDimVal) || isNaN(lowestVal) || isNaN(highestVal)) { + points[offset++] = NaN; + offset += 3; + continue; + } + + points[offset++] = getSign(store, dataIndex, openVal, closeVal, closeDimI); + tmpIn[cDimIdx] = axisDimVal; + tmpIn[vDimIdx] = lowestVal; + point = coordSys.dataToPoint(tmpIn, null, tmpOut); + points[offset++] = point ? point[0] : NaN; + points[offset++] = point ? point[1] : NaN; + tmpIn[vDimIdx] = highestVal; + point = coordSys.dataToPoint(tmpIn, null, tmpOut); + points[offset++] = point ? point[1] : NaN; + } + + data.setLayout('largePoints', points); + } + } + }; + + function getSign(store, dataIndex, openVal, closeVal, closeDimI) { + var sign; + + if (openVal > closeVal) { + sign = -1; + } else if (openVal < closeVal) { + sign = 1; + } else { + sign = dataIndex > 0 // If close === open, compare with close of last record + ? store.get(closeDimI, dataIndex - 1) <= closeVal ? 1 : -1 : // No record of previous, set to be positive + 1; + } + + return sign; + } + + function calculateCandleWidth(seriesModel, data) { + var baseAxis = seriesModel.getBaseAxis(); + var extent; + var bandWidth = baseAxis.type === 'category' ? baseAxis.getBandWidth() : (extent = baseAxis.getExtent(), Math.abs(extent[1] - extent[0]) / data.count()); + var barMaxWidth = parsePercent$1(retrieve2(seriesModel.get('barMaxWidth'), bandWidth), bandWidth); + var barMinWidth = parsePercent$1(retrieve2(seriesModel.get('barMinWidth'), 1), bandWidth); + var barWidth = seriesModel.get('barWidth'); + return barWidth != null ? parsePercent$1(barWidth, bandWidth) // Put max outer to ensure bar visible in spite of overlap. + : Math.max(Math.min(bandWidth / 2, barMaxWidth), barMinWidth); + } + + function install$k(registers) { + registers.registerChartView(CandlestickView); + registers.registerSeriesModel(CandlestickSeriesModel); + registers.registerPreprocessor(candlestickPreprocessor); + registers.registerVisual(candlestickVisual); + registers.registerLayout(candlestickLayout); + } + + function updateRipplePath(rippleGroup, effectCfg) { + var color = effectCfg.rippleEffectColor || effectCfg.color; + rippleGroup.eachChild(function (ripplePath) { + ripplePath.attr({ + z: effectCfg.z, + zlevel: effectCfg.zlevel, + style: { + stroke: effectCfg.brushType === 'stroke' ? color : null, + fill: effectCfg.brushType === 'fill' ? color : null + } + }); + }); + } + + var EffectSymbol = + /** @class */ + function (_super) { + __extends(EffectSymbol, _super); + + function EffectSymbol(data, idx) { + var _this = _super.call(this) || this; + + var symbol = new Symbol(data, idx); + var rippleGroup = new Group(); + + _this.add(symbol); + + _this.add(rippleGroup); + + _this.updateData(data, idx); + + return _this; + } + + EffectSymbol.prototype.stopEffectAnimation = function () { + this.childAt(1).removeAll(); + }; + + EffectSymbol.prototype.startEffectAnimation = function (effectCfg) { + var symbolType = effectCfg.symbolType; + var color = effectCfg.color; + var rippleNumber = effectCfg.rippleNumber; + var rippleGroup = this.childAt(1); + + for (var i = 0; i < rippleNumber; i++) { + // If width/height are set too small (e.g., set to 1) on ios10 + // and macOS Sierra, a circle stroke become a rect, no matter what + // the scale is set. So we set width/height as 2. See #4136. + var ripplePath = createSymbol(symbolType, -1, -1, 2, 2, color); + ripplePath.attr({ + style: { + strokeNoScale: true + }, + z2: 99, + silent: true, + scaleX: 0.5, + scaleY: 0.5 + }); + var delay = -i / rippleNumber * effectCfg.period + effectCfg.effectOffset; + ripplePath.animate('', true).when(effectCfg.period, { + scaleX: effectCfg.rippleScale / 2, + scaleY: effectCfg.rippleScale / 2 + }).delay(delay).start(); + ripplePath.animateStyle(true).when(effectCfg.period, { + opacity: 0 + }).delay(delay).start(); + rippleGroup.add(ripplePath); + } + + updateRipplePath(rippleGroup, effectCfg); + }; + /** + * Update effect symbol + */ + + + EffectSymbol.prototype.updateEffectAnimation = function (effectCfg) { + var oldEffectCfg = this._effectCfg; + var rippleGroup = this.childAt(1); // Must reinitialize effect if following configuration changed + + var DIFFICULT_PROPS = ['symbolType', 'period', 'rippleScale', 'rippleNumber']; + + for (var i = 0; i < DIFFICULT_PROPS.length; i++) { + var propName = DIFFICULT_PROPS[i]; + + if (oldEffectCfg[propName] !== effectCfg[propName]) { + this.stopEffectAnimation(); + this.startEffectAnimation(effectCfg); + return; + } + } + + updateRipplePath(rippleGroup, effectCfg); + }; + /** + * Highlight symbol + */ + + + EffectSymbol.prototype.highlight = function () { + enterEmphasis(this); + }; + /** + * Downplay symbol + */ + + + EffectSymbol.prototype.downplay = function () { + leaveEmphasis(this); + }; + + EffectSymbol.prototype.getSymbolType = function () { + var symbol = this.childAt(0); + return symbol && symbol.getSymbolType(); + }; + /** + * Update symbol properties + */ + + + EffectSymbol.prototype.updateData = function (data, idx) { + var _this = this; + + var seriesModel = data.hostModel; + this.childAt(0).updateData(data, idx); + var rippleGroup = this.childAt(1); + var itemModel = data.getItemModel(idx); + var symbolType = data.getItemVisual(idx, 'symbol'); + var symbolSize = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize')); + var symbolStyle = data.getItemVisual(idx, 'style'); + var color = symbolStyle && symbolStyle.fill; + var emphasisModel = itemModel.getModel('emphasis'); + rippleGroup.setScale(symbolSize); + rippleGroup.traverse(function (ripplePath) { + ripplePath.setStyle('fill', color); + }); + var symbolOffset = normalizeSymbolOffset(data.getItemVisual(idx, 'symbolOffset'), symbolSize); + + if (symbolOffset) { + rippleGroup.x = symbolOffset[0]; + rippleGroup.y = symbolOffset[1]; + } + + var symbolRotate = data.getItemVisual(idx, 'symbolRotate'); + rippleGroup.rotation = (symbolRotate || 0) * Math.PI / 180 || 0; + var effectCfg = {}; + effectCfg.showEffectOn = seriesModel.get('showEffectOn'); + effectCfg.rippleScale = itemModel.get(['rippleEffect', 'scale']); + effectCfg.brushType = itemModel.get(['rippleEffect', 'brushType']); + effectCfg.period = itemModel.get(['rippleEffect', 'period']) * 1000; + effectCfg.effectOffset = idx / data.count(); + effectCfg.z = seriesModel.getShallow('z') || 0; + effectCfg.zlevel = seriesModel.getShallow('zlevel') || 0; + effectCfg.symbolType = symbolType; + effectCfg.color = color; + effectCfg.rippleEffectColor = itemModel.get(['rippleEffect', 'color']); + effectCfg.rippleNumber = itemModel.get(['rippleEffect', 'number']); + + if (effectCfg.showEffectOn === 'render') { + this._effectCfg ? this.updateEffectAnimation(effectCfg) : this.startEffectAnimation(effectCfg); + this._effectCfg = effectCfg; + } else { + // Not keep old effect config + this._effectCfg = null; + this.stopEffectAnimation(); + + this.onHoverStateChange = function (toState) { + if (toState === 'emphasis') { + if (effectCfg.showEffectOn !== 'render') { + _this.startEffectAnimation(effectCfg); + } + } else if (toState === 'normal') { + if (effectCfg.showEffectOn !== 'render') { + _this.stopEffectAnimation(); + } + } + }; + } + + this._effectCfg = effectCfg; + toggleHoverEmphasis(this, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled')); + }; + + EffectSymbol.prototype.fadeOut = function (cb) { + cb && cb(); + }; + return EffectSymbol; + }(Group); + + var EffectScatterView = + /** @class */ + function (_super) { + __extends(EffectScatterView, _super); + + function EffectScatterView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = EffectScatterView.type; + return _this; + } + + EffectScatterView.prototype.init = function () { + this._symbolDraw = new SymbolDraw(EffectSymbol); + }; + + EffectScatterView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var effectSymbolDraw = this._symbolDraw; + effectSymbolDraw.updateData(data, { + clipShape: this._getClipShape(seriesModel) + }); + this.group.add(effectSymbolDraw.group); + }; + + EffectScatterView.prototype._getClipShape = function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var clipArea = coordSys && coordSys.getArea && coordSys.getArea(); + return seriesModel.get('clip', true) ? clipArea : null; + }; + + EffectScatterView.prototype.updateTransform = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + this.group.dirty(); + var res = pointsLayout('').reset(seriesModel, ecModel, api); + + if (res.progress) { + res.progress({ + start: 0, + end: data.count(), + count: data.count() + }, data); + } + + this._symbolDraw.updateLayout(); + }; + + EffectScatterView.prototype._updateGroupTransform = function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && coordSys.getRoamTransform) { + this.group.transform = clone$2(coordSys.getRoamTransform()); + this.group.decomposeTransform(); + } + }; + + EffectScatterView.prototype.remove = function (ecModel, api) { + this._symbolDraw && this._symbolDraw.remove(true); + }; + + EffectScatterView.type = 'effectScatter'; + return EffectScatterView; + }(ChartView); + + var EffectScatterSeriesModel = + /** @class */ + function (_super) { + __extends(EffectScatterSeriesModel, _super); + + function EffectScatterSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = EffectScatterSeriesModel.type; + _this.hasSymbolVisual = true; + return _this; + } + + EffectScatterSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createSeriesData(null, this, { + useEncodeDefaulter: true + }); + }; + + EffectScatterSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) { + return selectors.point(data.getItemLayout(dataIndex)); + }; + + EffectScatterSeriesModel.type = 'series.effectScatter'; + EffectScatterSeriesModel.dependencies = ['grid', 'polar']; + EffectScatterSeriesModel.defaultOption = { + coordinateSystem: 'cartesian2d', + // zlevel: 0, + z: 2, + legendHoverLink: true, + effectType: 'ripple', + progressive: 0, + // When to show the effect, option: 'render'|'emphasis' + showEffectOn: 'render', + clip: true, + // Ripple effect config + rippleEffect: { + period: 4, + // Scale of ripple + scale: 2.5, + // Brush type can be fill or stroke + brushType: 'fill', + // Ripple number + number: 3 + }, + universalTransition: { + divideShape: 'clone' + }, + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + // Polar coordinate system + // polarIndex: 0, + // Geo coordinate system + // geoIndex: 0, + // symbol: null, // 图形类型 + symbolSize: 10 // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2 + // symbolRotate: null, // 图形旋转控制 + // itemStyle: { + // opacity: 1 + // } + + }; + return EffectScatterSeriesModel; + }(SeriesModel); + + function install$l(registers) { + registers.registerChartView(EffectScatterView); + registers.registerSeriesModel(EffectScatterSeriesModel); + registers.registerLayout(pointsLayout('effectScatter')); + } + + var EffectLine = + /** @class */ + function (_super) { + __extends(EffectLine, _super); + + function EffectLine(lineData, idx, seriesScope) { + var _this = _super.call(this) || this; + + _this.add(_this.createLine(lineData, idx, seriesScope)); + + _this._updateEffectSymbol(lineData, idx); + + return _this; + } + + EffectLine.prototype.createLine = function (lineData, idx, seriesScope) { + return new Line$1(lineData, idx, seriesScope); + }; + + EffectLine.prototype._updateEffectSymbol = function (lineData, idx) { + var itemModel = lineData.getItemModel(idx); + var effectModel = itemModel.getModel('effect'); + var size = effectModel.get('symbolSize'); + var symbolType = effectModel.get('symbol'); + + if (!isArray(size)) { + size = [size, size]; + } + + var lineStyle = lineData.getItemVisual(idx, 'style'); + var color = effectModel.get('color') || lineStyle && lineStyle.stroke; + var symbol = this.childAt(1); + + if (this._symbolType !== symbolType) { + // Remove previous + this.remove(symbol); + symbol = createSymbol(symbolType, -0.5, -0.5, 1, 1, color); + symbol.z2 = 100; + symbol.culling = true; + this.add(symbol); + } // Symbol may be removed if loop is false + + + if (!symbol) { + return; + } // Shadow color is same with color in default + + + symbol.setStyle('shadowColor', color); + symbol.setStyle(effectModel.getItemStyle(['color'])); + symbol.scaleX = size[0]; + symbol.scaleY = size[1]; + symbol.setColor(color); + this._symbolType = symbolType; + this._symbolScale = size; + + this._updateEffectAnimation(lineData, effectModel, idx); + }; + + EffectLine.prototype._updateEffectAnimation = function (lineData, effectModel, idx) { + var symbol = this.childAt(1); + + if (!symbol) { + return; + } + + var points = lineData.getItemLayout(idx); + var period = effectModel.get('period') * 1000; + var loop = effectModel.get('loop'); + var constantSpeed = effectModel.get('constantSpeed'); + var delayExpr = retrieve(effectModel.get('delay'), function (idx) { + return idx / lineData.count() * period / 3; + }); // Ignore when updating + + symbol.ignore = true; + + this._updateAnimationPoints(symbol, points); + + if (constantSpeed > 0) { + period = this._getLineLength(symbol) / constantSpeed * 1000; + } + + if (period !== this._period || loop !== this._loop) { + symbol.stopAnimation(); + var delayNum = void 0; + + if (isFunction(delayExpr)) { + delayNum = delayExpr(idx); + } else { + delayNum = delayExpr; + } + + if (symbol.__t > 0) { + delayNum = -period * symbol.__t; + } + + this._animateSymbol(symbol, period, delayNum, loop); + } + + this._period = period; + this._loop = loop; + }; + + EffectLine.prototype._animateSymbol = function (symbol, period, delayNum, loop) { + if (period > 0) { + symbol.__t = 0; + var self_1 = this; + var animator = symbol.animate('', loop).when(period, { + __t: 1 + }).delay(delayNum).during(function () { + self_1._updateSymbolPosition(symbol); + }); + + if (!loop) { + animator.done(function () { + self_1.remove(symbol); + }); + } + + animator.start(); + } + }; + + EffectLine.prototype._getLineLength = function (symbol) { + // Not so accurate + return dist(symbol.__p1, symbol.__cp1) + dist(symbol.__cp1, symbol.__p2); + }; + + EffectLine.prototype._updateAnimationPoints = function (symbol, points) { + symbol.__p1 = points[0]; + symbol.__p2 = points[1]; + symbol.__cp1 = points[2] || [(points[0][0] + points[1][0]) / 2, (points[0][1] + points[1][1]) / 2]; + }; + + EffectLine.prototype.updateData = function (lineData, idx, seriesScope) { + this.childAt(0).updateData(lineData, idx, seriesScope); + + this._updateEffectSymbol(lineData, idx); + }; + + EffectLine.prototype._updateSymbolPosition = function (symbol) { + var p1 = symbol.__p1; + var p2 = symbol.__p2; + var cp1 = symbol.__cp1; + var t = symbol.__t; + var pos = [symbol.x, symbol.y]; + var lastPos = pos.slice(); + var quadraticAt$1 = quadraticAt; + var quadraticDerivativeAt$1 = quadraticDerivativeAt; + pos[0] = quadraticAt$1(p1[0], cp1[0], p2[0], t); + pos[1] = quadraticAt$1(p1[1], cp1[1], p2[1], t); // Tangent + + var tx = quadraticDerivativeAt$1(p1[0], cp1[0], p2[0], t); + var ty = quadraticDerivativeAt$1(p1[1], cp1[1], p2[1], t); + symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2; // enable continuity trail for 'line', 'rect', 'roundRect' symbolType + + if (this._symbolType === 'line' || this._symbolType === 'rect' || this._symbolType === 'roundRect') { + if (symbol.__lastT !== undefined && symbol.__lastT < symbol.__t) { + symbol.scaleY = dist(lastPos, pos) * 1.05; // make sure the last segment render within endPoint + + if (t === 1) { + pos[0] = lastPos[0] + (pos[0] - lastPos[0]) / 2; + pos[1] = lastPos[1] + (pos[1] - lastPos[1]) / 2; + } + } else if (symbol.__lastT === 1) { + // After first loop, symbol.__t does NOT start with 0, so connect p1 to pos directly. + symbol.scaleY = 2 * dist(p1, pos); + } else { + symbol.scaleY = this._symbolScale[1]; + } + } + + symbol.__lastT = symbol.__t; + symbol.ignore = false; + symbol.x = pos[0]; + symbol.y = pos[1]; + }; + + EffectLine.prototype.updateLayout = function (lineData, idx) { + this.childAt(0).updateLayout(lineData, idx); + var effectModel = lineData.getItemModel(idx).getModel('effect'); + + this._updateEffectAnimation(lineData, effectModel, idx); + }; + + return EffectLine; + }(Group); + + var Polyline$1 = + /** @class */ + function (_super) { + __extends(Polyline$1, _super); + + function Polyline$1(lineData, idx, seriesScope) { + var _this = _super.call(this) || this; + + _this._createPolyline(lineData, idx, seriesScope); + + return _this; + } + + Polyline$1.prototype._createPolyline = function (lineData, idx, seriesScope) { + // let seriesModel = lineData.hostModel; + var points = lineData.getItemLayout(idx); + var line = new Polyline({ + shape: { + points: points + } + }); + this.add(line); + + this._updateCommonStl(lineData, idx, seriesScope); + }; + + Polyline$1.prototype.updateData = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + var line = this.childAt(0); + var target = { + shape: { + points: lineData.getItemLayout(idx) + } + }; + updateProps(line, target, seriesModel, idx); + + this._updateCommonStl(lineData, idx, seriesScope); + }; + + Polyline$1.prototype._updateCommonStl = function (lineData, idx, seriesScope) { + var line = this.childAt(0); + var itemModel = lineData.getItemModel(idx); + var emphasisLineStyle = seriesScope && seriesScope.emphasisLineStyle; + var focus = seriesScope && seriesScope.focus; + var blurScope = seriesScope && seriesScope.blurScope; + var emphasisDisabled = seriesScope && seriesScope.emphasisDisabled; + + if (!seriesScope || lineData.hasItemOption) { + var emphasisModel = itemModel.getModel('emphasis'); + emphasisLineStyle = emphasisModel.getModel('lineStyle').getLineStyle(); + emphasisDisabled = emphasisModel.get('disabled'); + focus = emphasisModel.get('focus'); + blurScope = emphasisModel.get('blurScope'); + } + + line.useStyle(lineData.getItemVisual(idx, 'style')); + line.style.fill = null; + line.style.strokeNoScale = true; + var lineEmphasisState = line.ensureState('emphasis'); + lineEmphasisState.style = emphasisLineStyle; + toggleHoverEmphasis(this, focus, blurScope, emphasisDisabled); + }; + + Polyline$1.prototype.updateLayout = function (lineData, idx) { + var polyline = this.childAt(0); + polyline.setShape('points', lineData.getItemLayout(idx)); + }; + return Polyline$1; + }(Group); + + var EffectPolyline = + /** @class */ + function (_super) { + __extends(EffectPolyline, _super); + + function EffectPolyline() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this._lastFrame = 0; + _this._lastFramePercent = 0; + return _this; + } // Override + + + EffectPolyline.prototype.createLine = function (lineData, idx, seriesScope) { + return new Polyline$1(lineData, idx, seriesScope); + }; + + EffectPolyline.prototype._updateAnimationPoints = function (symbol, points) { + this._points = points; + var accLenArr = [0]; + var len = 0; + + for (var i = 1; i < points.length; i++) { + var p1 = points[i - 1]; + var p2 = points[i]; + len += dist(p1, p2); + accLenArr.push(len); + } + + if (len === 0) { + this._length = 0; + return; + } + + for (var i = 0; i < accLenArr.length; i++) { + accLenArr[i] /= len; + } + + this._offsets = accLenArr; + this._length = len; + }; + + EffectPolyline.prototype._getLineLength = function () { + return this._length; + }; + + EffectPolyline.prototype._updateSymbolPosition = function (symbol) { + var t = symbol.__t; + var points = this._points; + var offsets = this._offsets; + var len = points.length; + + if (!offsets) { + // Has length 0 + return; + } + + var lastFrame = this._lastFrame; + var frame; + + if (t < this._lastFramePercent) { + // Start from the next frame + // PENDING start from lastFrame ? + var start = Math.min(lastFrame + 1, len - 1); + + for (frame = start; frame >= 0; frame--) { + if (offsets[frame] <= t) { + break; + } + } // PENDING really need to do this ? + + + frame = Math.min(frame, len - 2); + } else { + for (frame = lastFrame; frame < len; frame++) { + if (offsets[frame] > t) { + break; + } + } + + frame = Math.min(frame - 1, len - 2); + } + + var p = (t - offsets[frame]) / (offsets[frame + 1] - offsets[frame]); + var p0 = points[frame]; + var p1 = points[frame + 1]; + symbol.x = p0[0] * (1 - p) + p * p1[0]; + symbol.y = p0[1] * (1 - p) + p * p1[1]; + var tx = p1[0] - p0[0]; + var ty = p1[1] - p0[1]; + symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2; + this._lastFrame = frame; + this._lastFramePercent = t; + symbol.ignore = false; + }; + return EffectPolyline; + }(EffectLine); + + var LargeLinesPathShape = + /** @class */ + function () { + function LargeLinesPathShape() { + this.polyline = false; + this.curveness = 0; + this.segs = []; + } + + return LargeLinesPathShape; + }(); + + var LargeLinesPath = + /** @class */ + function (_super) { + __extends(LargeLinesPath, _super); + + function LargeLinesPath(opts) { + var _this = _super.call(this, opts) || this; + + _this._off = 0; + _this.hoverDataIdx = -1; + return _this; + } + + LargeLinesPath.prototype.reset = function () { + this.notClear = false; + this._off = 0; + }; + + LargeLinesPath.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + + LargeLinesPath.prototype.getDefaultShape = function () { + return new LargeLinesPathShape(); + }; + + LargeLinesPath.prototype.buildPath = function (ctx, shape) { + var segs = shape.segs; + var curveness = shape.curveness; + var i; + + if (shape.polyline) { + for (i = this._off; i < segs.length;) { + var count = segs[i++]; + + if (count > 0) { + ctx.moveTo(segs[i++], segs[i++]); + + for (var k = 1; k < count; k++) { + ctx.lineTo(segs[i++], segs[i++]); + } + } + } + } else { + for (i = this._off; i < segs.length;) { + var x0 = segs[i++]; + var y0 = segs[i++]; + var x1 = segs[i++]; + var y1 = segs[i++]; + ctx.moveTo(x0, y0); + + if (curveness > 0) { + var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness; + var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness; + ctx.quadraticCurveTo(x2, y2, x1, y1); + } else { + ctx.lineTo(x1, y1); + } + } + } + + if (this.incremental) { + this._off = i; + this.notClear = true; + } + }; + + LargeLinesPath.prototype.findDataIndex = function (x, y) { + var shape = this.shape; + var segs = shape.segs; + var curveness = shape.curveness; + var lineWidth = this.style.lineWidth; + + if (shape.polyline) { + var dataIndex = 0; + + for (var i = 0; i < segs.length;) { + var count = segs[i++]; + + if (count > 0) { + var x0 = segs[i++]; + var y0 = segs[i++]; + + for (var k = 1; k < count; k++) { + var x1 = segs[i++]; + var y1 = segs[i++]; + + if (containStroke(x0, y0, x1, y1, lineWidth, x, y)) { + return dataIndex; + } + } + } + + dataIndex++; + } + } else { + var dataIndex = 0; + + for (var i = 0; i < segs.length;) { + var x0 = segs[i++]; + var y0 = segs[i++]; + var x1 = segs[i++]; + var y1 = segs[i++]; + + if (curveness > 0) { + var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness; + var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness; + + if (containStroke$2(x0, y0, x2, y2, x1, y1, lineWidth, x, y)) { + return dataIndex; + } + } else { + if (containStroke(x0, y0, x1, y1, lineWidth, x, y)) { + return dataIndex; + } + } + + dataIndex++; + } + } + + return -1; + }; + + LargeLinesPath.prototype.contain = function (x, y) { + var localPos = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + x = localPos[0]; + y = localPos[1]; + + if (rect.contain(x, y)) { + // Cache found data index. + var dataIdx = this.hoverDataIdx = this.findDataIndex(x, y); + return dataIdx >= 0; + } + + this.hoverDataIdx = -1; + return false; + }; + + LargeLinesPath.prototype.getBoundingRect = function () { + // Ignore stroke for large symbol draw. + var rect = this._rect; + + if (!rect) { + var shape = this.shape; + var points = shape.segs; + var minX = Infinity; + var minY = Infinity; + var maxX = -Infinity; + var maxY = -Infinity; + + for (var i = 0; i < points.length;) { + var x = points[i++]; + var y = points[i++]; + minX = Math.min(x, minX); + maxX = Math.max(x, maxX); + minY = Math.min(y, minY); + maxY = Math.max(y, maxY); + } + + rect = this._rect = new BoundingRect(minX, minY, maxX, maxY); + } + + return rect; + }; + + return LargeLinesPath; + }(Path); + + var LargeLineDraw = + /** @class */ + function () { + function LargeLineDraw() { + this.group = new Group(); + } + /** + * Update symbols draw by new data + */ + + + LargeLineDraw.prototype.updateData = function (data) { + this._clear(); + + var lineEl = this._create(); + + lineEl.setShape({ + segs: data.getLayout('linesPoints') + }); + + this._setCommon(lineEl, data); + }; + /** + * @override + */ + + LargeLineDraw.prototype.incrementalPrepareUpdate = function (data) { + this.group.removeAll(); + + this._clear(); + }; + /** + * @override + */ + + LargeLineDraw.prototype.incrementalUpdate = function (taskParams, data) { + var lastAdded = this._newAdded[0]; + var linePoints = data.getLayout('linesPoints'); + var oldSegs = lastAdded && lastAdded.shape.segs; // Merging the exists. Each element has 1e4 points. + // Consider the performance balance between too much elements and too much points in one shape(may affect hover optimization) + + if (oldSegs && oldSegs.length < 2e4) { + var oldLen = oldSegs.length; + var newSegs = new Float32Array(oldLen + linePoints.length); // Concat two array + + newSegs.set(oldSegs); + newSegs.set(linePoints, oldLen); + lastAdded.setShape({ + segs: newSegs + }); + } else { + // Clear + this._newAdded = []; + + var lineEl = this._create(); + + lineEl.incremental = true; + lineEl.setShape({ + segs: linePoints + }); + + this._setCommon(lineEl, data); + + lineEl.__startIndex = taskParams.start; + } + }; + /** + * @override + */ + + + LargeLineDraw.prototype.remove = function () { + this._clear(); + }; + + LargeLineDraw.prototype.eachRendered = function (cb) { + this._newAdded[0] && cb(this._newAdded[0]); + }; + + LargeLineDraw.prototype._create = function () { + var lineEl = new LargeLinesPath({ + cursor: 'default' + }); + + this._newAdded.push(lineEl); + + this.group.add(lineEl); + return lineEl; + }; + + LargeLineDraw.prototype._setCommon = function (lineEl, data, isIncremental) { + var hostModel = data.hostModel; + lineEl.setShape({ + polyline: hostModel.get('polyline'), + curveness: hostModel.get(['lineStyle', 'curveness']) + }); + lineEl.useStyle(hostModel.getModel('lineStyle').getLineStyle()); + lineEl.style.strokeNoScale = true; + var style = data.getVisual('style'); + + if (style && style.stroke) { + lineEl.setStyle('stroke', style.stroke); + } + + lineEl.setStyle('fill', null); + var ecData = getECData(lineEl); // Enable tooltip + // PENDING May have performance issue when path is extremely large + + ecData.seriesIndex = hostModel.seriesIndex; + lineEl.on('mousemove', function (e) { + ecData.dataIndex = null; + var dataIndex = lineEl.hoverDataIdx; + + if (dataIndex > 0) { + // Provide dataIndex for tooltip + ecData.dataIndex = dataIndex + lineEl.__startIndex; + } + }); + }; + + LargeLineDraw.prototype._clear = function () { + this._newAdded = []; + this.group.removeAll(); + }; + return LargeLineDraw; + }(); + + var linesLayout = { + seriesType: 'lines', + plan: createRenderPlanner(), + reset: function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (!coordSys) { + if ("development" !== 'production') { + error('The lines series must have a coordinate system.'); + } + + return; + } + + var isPolyline = seriesModel.get('polyline'); + var isLarge = seriesModel.pipelineContext.large; + return { + progress: function (params, lineData) { + var lineCoords = []; + + if (isLarge) { + var points = void 0; + var segCount = params.end - params.start; + + if (isPolyline) { + var totalCoordsCount = 0; + + for (var i = params.start; i < params.end; i++) { + totalCoordsCount += seriesModel.getLineCoordsCount(i); + } + + points = new Float32Array(segCount + totalCoordsCount * 2); + } else { + points = new Float32Array(segCount * 4); + } + + var offset = 0; + var pt = []; + + for (var i = params.start; i < params.end; i++) { + var len = seriesModel.getLineCoords(i, lineCoords); + + if (isPolyline) { + points[offset++] = len; + } + + for (var k = 0; k < len; k++) { + pt = coordSys.dataToPoint(lineCoords[k], false, pt); + points[offset++] = pt[0]; + points[offset++] = pt[1]; + } + } + + lineData.setLayout('linesPoints', points); + } else { + for (var i = params.start; i < params.end; i++) { + var itemModel = lineData.getItemModel(i); + var len = seriesModel.getLineCoords(i, lineCoords); + var pts = []; + + if (isPolyline) { + for (var j = 0; j < len; j++) { + pts.push(coordSys.dataToPoint(lineCoords[j])); + } + } else { + pts[0] = coordSys.dataToPoint(lineCoords[0]); + pts[1] = coordSys.dataToPoint(lineCoords[1]); + var curveness = itemModel.get(['lineStyle', 'curveness']); + + if (+curveness) { + pts[2] = [(pts[0][0] + pts[1][0]) / 2 - (pts[0][1] - pts[1][1]) * curveness, (pts[0][1] + pts[1][1]) / 2 - (pts[1][0] - pts[0][0]) * curveness]; + } + } + + lineData.setItemLayout(i, pts); + } + } + } + }; + } + }; + + var LinesView = + /** @class */ + function (_super) { + __extends(LinesView, _super); + + function LinesView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = LinesView.type; + return _this; + } + + LinesView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var lineDraw = this._updateLineDraw(data, seriesModel); + + var zlevel = seriesModel.get('zlevel'); + var trailLength = seriesModel.get(['effect', 'trailLength']); + var zr = api.getZr(); // Avoid the drag cause ghost shadow + // FIXME Better way ? + // SVG doesn't support + + var isSvg = zr.painter.getType() === 'svg'; + + if (!isSvg) { + zr.painter.getLayer(zlevel).clear(true); + } // Config layer with motion blur + + + if (this._lastZlevel != null && !isSvg) { + zr.configLayer(this._lastZlevel, { + motionBlur: false + }); + } + + if (this._showEffect(seriesModel) && trailLength > 0) { + if (!isSvg) { + zr.configLayer(zlevel, { + motionBlur: true, + lastFrameAlpha: Math.max(Math.min(trailLength / 10 + 0.9, 1), 0) + }); + } else if ("development" !== 'production') { + console.warn('SVG render mode doesn\'t support lines with trail effect'); + } + } + + lineDraw.updateData(data); + var clipPath = seriesModel.get('clip', true) && createClipPath(seriesModel.coordinateSystem, false, seriesModel); + + if (clipPath) { + this.group.setClipPath(clipPath); + } else { + this.group.removeClipPath(); + } + + this._lastZlevel = zlevel; + this._finished = true; + }; + + LinesView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var lineDraw = this._updateLineDraw(data, seriesModel); + + lineDraw.incrementalPrepareUpdate(data); + + this._clearLayer(api); + + this._finished = false; + }; + + LinesView.prototype.incrementalRender = function (taskParams, seriesModel, ecModel) { + this._lineDraw.incrementalUpdate(taskParams, seriesModel.getData()); + + this._finished = taskParams.end === seriesModel.getData().count(); + }; + + LinesView.prototype.eachRendered = function (cb) { + this._lineDraw && this._lineDraw.eachRendered(cb); + }; + + LinesView.prototype.updateTransform = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var pipelineContext = seriesModel.pipelineContext; + + if (!this._finished || pipelineContext.large || pipelineContext.progressiveRender) { + // TODO Don't have to do update in large mode. Only do it when there are millions of data. + return { + update: true + }; + } else { + // TODO Use same logic with ScatterView. + // Manually update layout + var res = linesLayout.reset(seriesModel, ecModel, api); + + if (res.progress) { + res.progress({ + start: 0, + end: data.count(), + count: data.count() + }, data); + } // Not in large mode + + + this._lineDraw.updateLayout(); + + this._clearLayer(api); + } + }; + + LinesView.prototype._updateLineDraw = function (data, seriesModel) { + var lineDraw = this._lineDraw; + + var hasEffect = this._showEffect(seriesModel); + + var isPolyline = !!seriesModel.get('polyline'); + var pipelineContext = seriesModel.pipelineContext; + var isLargeDraw = pipelineContext.large; + + if ("development" !== 'production') { + if (hasEffect && isLargeDraw) { + console.warn('Large lines not support effect'); + } + } + + if (!lineDraw || hasEffect !== this._hasEffet || isPolyline !== this._isPolyline || isLargeDraw !== this._isLargeDraw) { + if (lineDraw) { + lineDraw.remove(); + } + + lineDraw = this._lineDraw = isLargeDraw ? new LargeLineDraw() : new LineDraw(isPolyline ? hasEffect ? EffectPolyline : Polyline$1 : hasEffect ? EffectLine : Line$1); + this._hasEffet = hasEffect; + this._isPolyline = isPolyline; + this._isLargeDraw = isLargeDraw; + } + + this.group.add(lineDraw.group); + return lineDraw; + }; + + LinesView.prototype._showEffect = function (seriesModel) { + return !!seriesModel.get(['effect', 'show']); + }; + + LinesView.prototype._clearLayer = function (api) { + // Not use motion when dragging or zooming + var zr = api.getZr(); + var isSvg = zr.painter.getType() === 'svg'; + + if (!isSvg && this._lastZlevel != null) { + zr.painter.getLayer(this._lastZlevel).clear(true); + } + }; + + LinesView.prototype.remove = function (ecModel, api) { + this._lineDraw && this._lineDraw.remove(); + this._lineDraw = null; // Clear motion when lineDraw is removed + + this._clearLayer(api); + }; + + LinesView.prototype.dispose = function (ecModel, api) { + this.remove(ecModel, api); + }; + + LinesView.type = 'lines'; + return LinesView; + }(ChartView); + + var Uint32Arr = typeof Uint32Array === 'undefined' ? Array : Uint32Array; + var Float64Arr = typeof Float64Array === 'undefined' ? Array : Float64Array; + + function compatEc2(seriesOpt) { + var data = seriesOpt.data; + + if (data && data[0] && data[0][0] && data[0][0].coord) { + if ("development" !== 'production') { + console.warn('Lines data configuration has been changed to' + ' { coords:[[1,2],[2,3]] }'); + } + + seriesOpt.data = map(data, function (itemOpt) { + var coords = [itemOpt[0].coord, itemOpt[1].coord]; + var target = { + coords: coords + }; + + if (itemOpt[0].name) { + target.fromName = itemOpt[0].name; + } + + if (itemOpt[1].name) { + target.toName = itemOpt[1].name; + } + + return mergeAll([target, itemOpt[0], itemOpt[1]]); + }); + } + } + + var LinesSeriesModel = + /** @class */ + function (_super) { + __extends(LinesSeriesModel, _super); + + function LinesSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = LinesSeriesModel.type; + _this.visualStyleAccessPath = 'lineStyle'; + _this.visualDrawType = 'stroke'; + return _this; + } + + LinesSeriesModel.prototype.init = function (option) { + // The input data may be null/undefined. + option.data = option.data || []; // Not using preprocessor because mergeOption may not have series.type + + compatEc2(option); + + var result = this._processFlatCoordsArray(option.data); + + this._flatCoords = result.flatCoords; + this._flatCoordsOffset = result.flatCoordsOffset; + + if (result.flatCoords) { + option.data = new Float32Array(result.count); + } + + _super.prototype.init.apply(this, arguments); + }; + + LinesSeriesModel.prototype.mergeOption = function (option) { + compatEc2(option); + + if (option.data) { + // Only update when have option data to merge. + var result = this._processFlatCoordsArray(option.data); + + this._flatCoords = result.flatCoords; + this._flatCoordsOffset = result.flatCoordsOffset; + + if (result.flatCoords) { + option.data = new Float32Array(result.count); + } + } + + _super.prototype.mergeOption.apply(this, arguments); + }; + + LinesSeriesModel.prototype.appendData = function (params) { + var result = this._processFlatCoordsArray(params.data); + + if (result.flatCoords) { + if (!this._flatCoords) { + this._flatCoords = result.flatCoords; + this._flatCoordsOffset = result.flatCoordsOffset; + } else { + this._flatCoords = concatArray(this._flatCoords, result.flatCoords); + this._flatCoordsOffset = concatArray(this._flatCoordsOffset, result.flatCoordsOffset); + } + + params.data = new Float32Array(result.count); + } + + this.getRawData().appendData(params.data); + }; + + LinesSeriesModel.prototype._getCoordsFromItemModel = function (idx) { + var itemModel = this.getData().getItemModel(idx); + var coords = itemModel.option instanceof Array ? itemModel.option : itemModel.getShallow('coords'); + + if ("development" !== 'production') { + if (!(coords instanceof Array && coords.length > 0 && coords[0] instanceof Array)) { + throw new Error('Invalid coords ' + JSON.stringify(coords) + '. Lines must have 2d coords array in data item.'); + } + } + + return coords; + }; + + LinesSeriesModel.prototype.getLineCoordsCount = function (idx) { + if (this._flatCoordsOffset) { + return this._flatCoordsOffset[idx * 2 + 1]; + } else { + return this._getCoordsFromItemModel(idx).length; + } + }; + + LinesSeriesModel.prototype.getLineCoords = function (idx, out) { + if (this._flatCoordsOffset) { + var offset = this._flatCoordsOffset[idx * 2]; + var len = this._flatCoordsOffset[idx * 2 + 1]; + + for (var i = 0; i < len; i++) { + out[i] = out[i] || []; + out[i][0] = this._flatCoords[offset + i * 2]; + out[i][1] = this._flatCoords[offset + i * 2 + 1]; + } + + return len; + } else { + var coords = this._getCoordsFromItemModel(idx); + + for (var i = 0; i < coords.length; i++) { + out[i] = out[i] || []; + out[i][0] = coords[i][0]; + out[i][1] = coords[i][1]; + } + + return coords.length; + } + }; + + LinesSeriesModel.prototype._processFlatCoordsArray = function (data) { + var startOffset = 0; + + if (this._flatCoords) { + startOffset = this._flatCoords.length; + } // Stored as a typed array. In format + // Points Count(2) | x | y | x | y | Points Count(3) | x | y | x | y | x | y | + + + if (isNumber(data[0])) { + var len = data.length; // Store offset and len of each segment + + var coordsOffsetAndLenStorage = new Uint32Arr(len); + var coordsStorage = new Float64Arr(len); + var coordsCursor = 0; + var offsetCursor = 0; + var dataCount = 0; + + for (var i = 0; i < len;) { + dataCount++; + var count = data[i++]; // Offset + + coordsOffsetAndLenStorage[offsetCursor++] = coordsCursor + startOffset; // Len + + coordsOffsetAndLenStorage[offsetCursor++] = count; + + for (var k = 0; k < count; k++) { + var x = data[i++]; + var y = data[i++]; + coordsStorage[coordsCursor++] = x; + coordsStorage[coordsCursor++] = y; + + if (i > len) { + if ("development" !== 'production') { + throw new Error('Invalid data format.'); + } + } + } + } + + return { + flatCoordsOffset: new Uint32Array(coordsOffsetAndLenStorage.buffer, 0, offsetCursor), + flatCoords: coordsStorage, + count: dataCount + }; + } + + return { + flatCoordsOffset: null, + flatCoords: null, + count: data.length + }; + }; + + LinesSeriesModel.prototype.getInitialData = function (option, ecModel) { + if ("development" !== 'production') { + var CoordSys = CoordinateSystemManager.get(option.coordinateSystem); + + if (!CoordSys) { + throw new Error('Unkown coordinate system ' + option.coordinateSystem); + } + } + + var lineData = new SeriesData(['value'], this); + lineData.hasItemOption = false; + lineData.initData(option.data, [], function (dataItem, dimName, dataIndex, dimIndex) { + // dataItem is simply coords + if (dataItem instanceof Array) { + return NaN; + } else { + lineData.hasItemOption = true; + var value = dataItem.value; + + if (value != null) { + return value instanceof Array ? value[dimIndex] : value; + } + } + }); + return lineData; + }; + + LinesSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var data = this.getData(); + var itemModel = data.getItemModel(dataIndex); + var name = itemModel.get('name'); + + if (name) { + return name; + } + + var fromName = itemModel.get('fromName'); + var toName = itemModel.get('toName'); + var nameArr = []; + fromName != null && nameArr.push(fromName); + toName != null && nameArr.push(toName); + return createTooltipMarkup('nameValue', { + name: nameArr.join(' > ') + }); + }; + + LinesSeriesModel.prototype.preventIncremental = function () { + return !!this.get(['effect', 'show']); + }; + + LinesSeriesModel.prototype.getProgressive = function () { + var progressive = this.option.progressive; + + if (progressive == null) { + return this.option.large ? 1e4 : this.get('progressive'); + } + + return progressive; + }; + + LinesSeriesModel.prototype.getProgressiveThreshold = function () { + var progressiveThreshold = this.option.progressiveThreshold; + + if (progressiveThreshold == null) { + return this.option.large ? 2e4 : this.get('progressiveThreshold'); + } + + return progressiveThreshold; + }; + + LinesSeriesModel.prototype.getZLevelKey = function () { + var effectModel = this.getModel('effect'); + var trailLength = effectModel.get('trailLength'); + return this.getData().count() > this.getProgressiveThreshold() // Each progressive series has individual key. + ? this.id : effectModel.get('show') && trailLength > 0 ? trailLength + '' : ''; + }; + + LinesSeriesModel.type = 'series.lines'; + LinesSeriesModel.dependencies = ['grid', 'polar', 'geo', 'calendar']; + LinesSeriesModel.defaultOption = { + coordinateSystem: 'geo', + // zlevel: 0, + z: 2, + legendHoverLink: true, + // Cartesian coordinate system + xAxisIndex: 0, + yAxisIndex: 0, + symbol: ['none', 'none'], + symbolSize: [10, 10], + // Geo coordinate system + geoIndex: 0, + effect: { + show: false, + period: 4, + constantSpeed: 0, + symbol: 'circle', + symbolSize: 3, + loop: true, + trailLength: 0.2 + }, + large: false, + // Available when large is true + largeThreshold: 2000, + polyline: false, + clip: true, + label: { + show: false, + position: 'end' // distance: 5, + // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调 + + }, + lineStyle: { + opacity: 0.5 + } + }; + return LinesSeriesModel; + }(SeriesModel); + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function normalize$3(a) { + if (!(a instanceof Array)) { + a = [a, a]; + } + + return a; + } + + var linesVisual = { + seriesType: 'lines', + reset: function (seriesModel) { + var symbolType = normalize$3(seriesModel.get('symbol')); + var symbolSize = normalize$3(seriesModel.get('symbolSize')); + var data = seriesModel.getData(); + data.setVisual('fromSymbol', symbolType && symbolType[0]); + data.setVisual('toSymbol', symbolType && symbolType[1]); + data.setVisual('fromSymbolSize', symbolSize && symbolSize[0]); + data.setVisual('toSymbolSize', symbolSize && symbolSize[1]); + + function dataEach(data, idx) { + var itemModel = data.getItemModel(idx); + var symbolType = normalize$3(itemModel.getShallow('symbol', true)); + var symbolSize = normalize$3(itemModel.getShallow('symbolSize', true)); + symbolType[0] && data.setItemVisual(idx, 'fromSymbol', symbolType[0]); + symbolType[1] && data.setItemVisual(idx, 'toSymbol', symbolType[1]); + symbolSize[0] && data.setItemVisual(idx, 'fromSymbolSize', symbolSize[0]); + symbolSize[1] && data.setItemVisual(idx, 'toSymbolSize', symbolSize[1]); + } + + return { + dataEach: data.hasItemOption ? dataEach : null + }; + } + }; + + function install$m(registers) { + registers.registerChartView(LinesView); + registers.registerSeriesModel(LinesSeriesModel); + registers.registerLayout(linesLayout); + registers.registerVisual(linesVisual); + } + + var GRADIENT_LEVELS = 256; + + var HeatmapLayer = + /** @class */ + function () { + function HeatmapLayer() { + this.blurSize = 30; + this.pointSize = 20; + this.maxOpacity = 1; + this.minOpacity = 0; + this._gradientPixels = { + inRange: null, + outOfRange: null + }; + var canvas = platformApi.createCanvas(); + this.canvas = canvas; + } + /** + * Renders Heatmap and returns the rendered canvas + * @param data array of data, each has x, y, value + * @param width canvas width + * @param height canvas height + */ + + + HeatmapLayer.prototype.update = function (data, width, height, normalize, colorFunc, isInRange) { + var brush = this._getBrush(); + + var gradientInRange = this._getGradient(colorFunc, 'inRange'); + + var gradientOutOfRange = this._getGradient(colorFunc, 'outOfRange'); + + var r = this.pointSize + this.blurSize; + var canvas = this.canvas; + var ctx = canvas.getContext('2d'); + var len = data.length; + canvas.width = width; + canvas.height = height; + + for (var i = 0; i < len; ++i) { + var p = data[i]; + var x = p[0]; + var y = p[1]; + var value = p[2]; // calculate alpha using value + + var alpha = normalize(value); // draw with the circle brush with alpha + + ctx.globalAlpha = alpha; + ctx.drawImage(brush, x - r, y - r); + } + + if (!canvas.width || !canvas.height) { + // Avoid "Uncaught DOMException: Failed to execute 'getImageData' on + // 'CanvasRenderingContext2D': The source height is 0." + return canvas; + } // colorize the canvas using alpha value and set with gradient + + + var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + var pixels = imageData.data; + var offset = 0; + var pixelLen = pixels.length; + var minOpacity = this.minOpacity; + var maxOpacity = this.maxOpacity; + var diffOpacity = maxOpacity - minOpacity; + + while (offset < pixelLen) { + var alpha = pixels[offset + 3] / 256; + var gradientOffset = Math.floor(alpha * (GRADIENT_LEVELS - 1)) * 4; // Simple optimize to ignore the empty data + + if (alpha > 0) { + var gradient = isInRange(alpha) ? gradientInRange : gradientOutOfRange; // Any alpha > 0 will be mapped to [minOpacity, maxOpacity] + + alpha > 0 && (alpha = alpha * diffOpacity + minOpacity); + pixels[offset++] = gradient[gradientOffset]; + pixels[offset++] = gradient[gradientOffset + 1]; + pixels[offset++] = gradient[gradientOffset + 2]; + pixels[offset++] = gradient[gradientOffset + 3] * alpha * 256; + } else { + offset += 4; + } + } + + ctx.putImageData(imageData, 0, 0); + return canvas; + }; + /** + * get canvas of a black circle brush used for canvas to draw later + */ + + + HeatmapLayer.prototype._getBrush = function () { + var brushCanvas = this._brushCanvas || (this._brushCanvas = platformApi.createCanvas()); // set brush size + + var r = this.pointSize + this.blurSize; + var d = r * 2; + brushCanvas.width = d; + brushCanvas.height = d; + var ctx = brushCanvas.getContext('2d'); + ctx.clearRect(0, 0, d, d); // in order to render shadow without the distinct circle, + // draw the distinct circle in an invisible place, + // and use shadowOffset to draw shadow in the center of the canvas + + ctx.shadowOffsetX = d; + ctx.shadowBlur = this.blurSize; // draw the shadow in black, and use alpha and shadow blur to generate + // color in color map + + ctx.shadowColor = '#000'; // draw circle in the left to the canvas + + ctx.beginPath(); + ctx.arc(-r, r, this.pointSize, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fill(); + return brushCanvas; + }; + /** + * get gradient color map + * @private + */ + + + HeatmapLayer.prototype._getGradient = function (colorFunc, state) { + var gradientPixels = this._gradientPixels; + var pixelsSingleState = gradientPixels[state] || (gradientPixels[state] = new Uint8ClampedArray(256 * 4)); + var color = [0, 0, 0, 0]; + var off = 0; + + for (var i = 0; i < 256; i++) { + colorFunc[state](i / 255, true, color); + pixelsSingleState[off++] = color[0]; + pixelsSingleState[off++] = color[1]; + pixelsSingleState[off++] = color[2]; + pixelsSingleState[off++] = color[3]; + } + + return pixelsSingleState; + }; + + return HeatmapLayer; + }(); + + function getIsInPiecewiseRange(dataExtent, pieceList, selected) { + var dataSpan = dataExtent[1] - dataExtent[0]; + pieceList = map(pieceList, function (piece) { + return { + interval: [(piece.interval[0] - dataExtent[0]) / dataSpan, (piece.interval[1] - dataExtent[0]) / dataSpan] + }; + }); + var len = pieceList.length; + var lastIndex = 0; + return function (val) { + var i; // Try to find in the location of the last found + + for (i = lastIndex; i < len; i++) { + var interval = pieceList[i].interval; + + if (interval[0] <= val && val <= interval[1]) { + lastIndex = i; + break; + } + } + + if (i === len) { + // Not found, back interation + for (i = lastIndex - 1; i >= 0; i--) { + var interval = pieceList[i].interval; + + if (interval[0] <= val && val <= interval[1]) { + lastIndex = i; + break; + } + } + } + + return i >= 0 && i < len && selected[i]; + }; + } + + function getIsInContinuousRange(dataExtent, range) { + var dataSpan = dataExtent[1] - dataExtent[0]; + range = [(range[0] - dataExtent[0]) / dataSpan, (range[1] - dataExtent[0]) / dataSpan]; + return function (val) { + return val >= range[0] && val <= range[1]; + }; + } + + function isGeoCoordSys(coordSys) { + var dimensions = coordSys.dimensions; // Not use coorSys.type === 'geo' because coordSys maybe extended + + return dimensions[0] === 'lng' && dimensions[1] === 'lat'; + } + + var HeatmapView = + /** @class */ + function (_super) { + __extends(HeatmapView, _super); + + function HeatmapView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = HeatmapView.type; + return _this; + } + + HeatmapView.prototype.render = function (seriesModel, ecModel, api) { + var visualMapOfThisSeries; + ecModel.eachComponent('visualMap', function (visualMap) { + visualMap.eachTargetSeries(function (targetSeries) { + if (targetSeries === seriesModel) { + visualMapOfThisSeries = visualMap; + } + }); + }); + + if ("development" !== 'production') { + if (!visualMapOfThisSeries) { + throw new Error('Heatmap must use with visualMap'); + } + } // Clear previously rendered progressive elements. + + + this._progressiveEls = null; + this.group.removeAll(); + var coordSys = seriesModel.coordinateSystem; + + if (coordSys.type === 'cartesian2d' || coordSys.type === 'calendar') { + this._renderOnCartesianAndCalendar(seriesModel, api, 0, seriesModel.getData().count()); + } else if (isGeoCoordSys(coordSys)) { + this._renderOnGeo(coordSys, seriesModel, visualMapOfThisSeries, api); + } + }; + + HeatmapView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) { + this.group.removeAll(); + }; + + HeatmapView.prototype.incrementalRender = function (params, seriesModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys) { + // geo does not support incremental rendering? + if (isGeoCoordSys(coordSys)) { + this.render(seriesModel, ecModel, api); + } else { + this._progressiveEls = []; + + this._renderOnCartesianAndCalendar(seriesModel, api, params.start, params.end, true); + } + } + }; + + HeatmapView.prototype.eachRendered = function (cb) { + traverseElements(this._progressiveEls || this.group, cb); + }; + + HeatmapView.prototype._renderOnCartesianAndCalendar = function (seriesModel, api, start, end, incremental) { + var coordSys = seriesModel.coordinateSystem; + var isCartesian2d = isCoordinateSystemType(coordSys, 'cartesian2d'); + var width; + var height; + var xAxisExtent; + var yAxisExtent; + + if (isCartesian2d) { + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + + if ("development" !== 'production') { + if (!(xAxis.type === 'category' && yAxis.type === 'category')) { + throw new Error('Heatmap on cartesian must have two category axes'); + } + + if (!(xAxis.onBand && yAxis.onBand)) { + throw new Error('Heatmap on cartesian must have two axes with boundaryGap true'); + } + } // add 0.5px to avoid the gaps + + + width = xAxis.getBandWidth() + .5; + height = yAxis.getBandWidth() + .5; + xAxisExtent = xAxis.scale.getExtent(); + yAxisExtent = yAxis.scale.getExtent(); + } + + var group = this.group; + var data = seriesModel.getData(); + var emphasisStyle = seriesModel.getModel(['emphasis', 'itemStyle']).getItemStyle(); + var blurStyle = seriesModel.getModel(['blur', 'itemStyle']).getItemStyle(); + var selectStyle = seriesModel.getModel(['select', 'itemStyle']).getItemStyle(); + var borderRadius = seriesModel.get(['itemStyle', 'borderRadius']); + var labelStatesModels = getLabelStatesModels(seriesModel); + var emphasisModel = seriesModel.getModel('emphasis'); + var focus = emphasisModel.get('focus'); + var blurScope = emphasisModel.get('blurScope'); + var emphasisDisabled = emphasisModel.get('disabled'); + var dataDims = isCartesian2d ? [data.mapDimension('x'), data.mapDimension('y'), data.mapDimension('value')] : [data.mapDimension('time'), data.mapDimension('value')]; + + for (var idx = start; idx < end; idx++) { + var rect = void 0; + var style = data.getItemVisual(idx, 'style'); + + if (isCartesian2d) { + var dataDimX = data.get(dataDims[0], idx); + var dataDimY = data.get(dataDims[1], idx); // Ignore empty data and out of extent data + + if (isNaN(data.get(dataDims[2], idx)) || dataDimX < xAxisExtent[0] || dataDimX > xAxisExtent[1] || dataDimY < yAxisExtent[0] || dataDimY > yAxisExtent[1]) { + continue; + } + + var point = coordSys.dataToPoint([dataDimX, dataDimY]); + rect = new Rect({ + shape: { + x: point[0] - width / 2, + y: point[1] - height / 2, + width: width, + height: height + }, + style: style + }); + } else { + // Ignore empty data + if (isNaN(data.get(dataDims[1], idx))) { + continue; + } + + rect = new Rect({ + z2: 1, + shape: coordSys.dataToRect([data.get(dataDims[0], idx)]).contentShape, + style: style + }); + } // Optimization for large datset + + + if (data.hasItemOption) { + var itemModel = data.getItemModel(idx); + var emphasisModel_1 = itemModel.getModel('emphasis'); + emphasisStyle = emphasisModel_1.getModel('itemStyle').getItemStyle(); + blurStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle(); + selectStyle = itemModel.getModel(['select', 'itemStyle']).getItemStyle(); // Each item value struct in the data would be firstly + // { + // itemStyle: { borderRadius: [30, 30] }, + // value: [2022, 02, 22] + // } + + borderRadius = itemModel.get(['itemStyle', 'borderRadius']); + focus = emphasisModel_1.get('focus'); + blurScope = emphasisModel_1.get('blurScope'); + emphasisDisabled = emphasisModel_1.get('disabled'); + labelStatesModels = getLabelStatesModels(itemModel); + } + + rect.shape.r = borderRadius; + var rawValue = seriesModel.getRawValue(idx); + var defaultText = '-'; + + if (rawValue && rawValue[2] != null) { + defaultText = rawValue[2] + ''; + } + + setLabelStyle(rect, labelStatesModels, { + labelFetcher: seriesModel, + labelDataIndex: idx, + defaultOpacity: style.opacity, + defaultText: defaultText + }); + rect.ensureState('emphasis').style = emphasisStyle; + rect.ensureState('blur').style = blurStyle; + rect.ensureState('select').style = selectStyle; + toggleHoverEmphasis(rect, focus, blurScope, emphasisDisabled); + rect.incremental = incremental; // PENDING + + if (incremental) { + // Rect must use hover layer if it's incremental. + rect.states.emphasis.hoverLayer = true; + } + + group.add(rect); + data.setItemGraphicEl(idx, rect); + + if (this._progressiveEls) { + this._progressiveEls.push(rect); + } + } + }; + + HeatmapView.prototype._renderOnGeo = function (geo, seriesModel, visualMapModel, api) { + var inRangeVisuals = visualMapModel.targetVisuals.inRange; + var outOfRangeVisuals = visualMapModel.targetVisuals.outOfRange; // if (!visualMapping) { + // throw new Error('Data range must have color visuals'); + // } + + var data = seriesModel.getData(); + var hmLayer = this._hmLayer || this._hmLayer || new HeatmapLayer(); + hmLayer.blurSize = seriesModel.get('blurSize'); + hmLayer.pointSize = seriesModel.get('pointSize'); + hmLayer.minOpacity = seriesModel.get('minOpacity'); + hmLayer.maxOpacity = seriesModel.get('maxOpacity'); + var rect = geo.getViewRect().clone(); + var roamTransform = geo.getRoamTransform(); + rect.applyTransform(roamTransform); // Clamp on viewport + + var x = Math.max(rect.x, 0); + var y = Math.max(rect.y, 0); + var x2 = Math.min(rect.width + rect.x, api.getWidth()); + var y2 = Math.min(rect.height + rect.y, api.getHeight()); + var width = x2 - x; + var height = y2 - y; + var dims = [data.mapDimension('lng'), data.mapDimension('lat'), data.mapDimension('value')]; + var points = data.mapArray(dims, function (lng, lat, value) { + var pt = geo.dataToPoint([lng, lat]); + pt[0] -= x; + pt[1] -= y; + pt.push(value); + return pt; + }); + var dataExtent = visualMapModel.getExtent(); + var isInRange = visualMapModel.type === 'visualMap.continuous' ? getIsInContinuousRange(dataExtent, visualMapModel.option.range) : getIsInPiecewiseRange(dataExtent, visualMapModel.getPieceList(), visualMapModel.option.selected); + hmLayer.update(points, width, height, inRangeVisuals.color.getNormalizer(), { + inRange: inRangeVisuals.color.getColorMapper(), + outOfRange: outOfRangeVisuals.color.getColorMapper() + }, isInRange); + var img = new ZRImage({ + style: { + width: width, + height: height, + x: x, + y: y, + image: hmLayer.canvas + }, + silent: true + }); + this.group.add(img); + }; + + HeatmapView.type = 'heatmap'; + return HeatmapView; + }(ChartView); + + var HeatmapSeriesModel = + /** @class */ + function (_super) { + __extends(HeatmapSeriesModel, _super); + + function HeatmapSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = HeatmapSeriesModel.type; + return _this; + } + + HeatmapSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createSeriesData(null, this, { + generateCoord: 'value' + }); + }; + + HeatmapSeriesModel.prototype.preventIncremental = function () { + var coordSysCreator = CoordinateSystemManager.get(this.get('coordinateSystem')); + + if (coordSysCreator && coordSysCreator.dimensions) { + return coordSysCreator.dimensions[0] === 'lng' && coordSysCreator.dimensions[1] === 'lat'; + } + }; + + HeatmapSeriesModel.type = 'series.heatmap'; + HeatmapSeriesModel.dependencies = ['grid', 'geo', 'calendar']; + HeatmapSeriesModel.defaultOption = { + coordinateSystem: 'cartesian2d', + // zlevel: 0, + z: 2, + // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + // Geo coordinate system + geoIndex: 0, + blurSize: 30, + pointSize: 20, + maxOpacity: 1, + minOpacity: 0, + select: { + itemStyle: { + borderColor: '#212121' + } + } + }; + return HeatmapSeriesModel; + }(SeriesModel); + + function install$n(registers) { + registers.registerChartView(HeatmapView); + registers.registerSeriesModel(HeatmapSeriesModel); + } + + var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'borderWidth']; // index: +isHorizontal + + var LAYOUT_ATTRS = [{ + xy: 'x', + wh: 'width', + index: 0, + posDesc: ['left', 'right'] + }, { + xy: 'y', + wh: 'height', + index: 1, + posDesc: ['top', 'bottom'] + }]; + var pathForLineWidth = new Circle(); + + var PictorialBarView = + /** @class */ + function (_super) { + __extends(PictorialBarView, _super); + + function PictorialBarView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = PictorialBarView.type; + return _this; + } + + PictorialBarView.prototype.render = function (seriesModel, ecModel, api) { + var group = this.group; + var data = seriesModel.getData(); + var oldData = this._data; + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + var isHorizontal = baseAxis.isHorizontal(); + var coordSysRect = cartesian.master.getRect(); + var opt = { + ecSize: { + width: api.getWidth(), + height: api.getHeight() + }, + seriesModel: seriesModel, + coordSys: cartesian, + coordSysExtent: [[coordSysRect.x, coordSysRect.x + coordSysRect.width], [coordSysRect.y, coordSysRect.y + coordSysRect.height]], + isHorizontal: isHorizontal, + valueDim: LAYOUT_ATTRS[+isHorizontal], + categoryDim: LAYOUT_ATTRS[1 - +isHorizontal] + }; + data.diff(oldData).add(function (dataIndex) { + if (!data.hasValue(dataIndex)) { + return; + } + + var itemModel = getItemModel(data, dataIndex); + var symbolMeta = getSymbolMeta(data, dataIndex, itemModel, opt); + var bar = createBar(data, opt, symbolMeta); + data.setItemGraphicEl(dataIndex, bar); + group.add(bar); + updateCommon$1(bar, opt, symbolMeta); + }).update(function (newIndex, oldIndex) { + var bar = oldData.getItemGraphicEl(oldIndex); + + if (!data.hasValue(newIndex)) { + group.remove(bar); + return; + } + + var itemModel = getItemModel(data, newIndex); + var symbolMeta = getSymbolMeta(data, newIndex, itemModel, opt); + var pictorialShapeStr = getShapeStr(data, symbolMeta); + + if (bar && pictorialShapeStr !== bar.__pictorialShapeStr) { + group.remove(bar); + data.setItemGraphicEl(newIndex, null); + bar = null; + } + + if (bar) { + updateBar(bar, opt, symbolMeta); + } else { + bar = createBar(data, opt, symbolMeta, true); + } + + data.setItemGraphicEl(newIndex, bar); + bar.__pictorialSymbolMeta = symbolMeta; // Add back + + group.add(bar); + updateCommon$1(bar, opt, symbolMeta); + }).remove(function (dataIndex) { + var bar = oldData.getItemGraphicEl(dataIndex); + bar && removeBar(oldData, dataIndex, bar.__pictorialSymbolMeta.animationModel, bar); + }).execute(); + this._data = data; + return this.group; + }; + + PictorialBarView.prototype.remove = function (ecModel, api) { + var group = this.group; + var data = this._data; + + if (ecModel.get('animation')) { + if (data) { + data.eachItemGraphicEl(function (bar) { + removeBar(data, getECData(bar).dataIndex, ecModel, bar); + }); + } + } else { + group.removeAll(); + } + }; + + PictorialBarView.type = 'pictorialBar'; + return PictorialBarView; + }(ChartView); // Set or calculate default value about symbol, and calculate layout info. + + + function getSymbolMeta(data, dataIndex, itemModel, opt) { + var layout = data.getItemLayout(dataIndex); + var symbolRepeat = itemModel.get('symbolRepeat'); + var symbolClip = itemModel.get('symbolClip'); + var symbolPosition = itemModel.get('symbolPosition') || 'start'; + var symbolRotate = itemModel.get('symbolRotate'); + var rotation = (symbolRotate || 0) * Math.PI / 180 || 0; + var symbolPatternSize = itemModel.get('symbolPatternSize') || 2; + var isAnimationEnabled = itemModel.isAnimationEnabled(); + var symbolMeta = { + dataIndex: dataIndex, + layout: layout, + itemModel: itemModel, + symbolType: data.getItemVisual(dataIndex, 'symbol') || 'circle', + style: data.getItemVisual(dataIndex, 'style'), + symbolClip: symbolClip, + symbolRepeat: symbolRepeat, + symbolRepeatDirection: itemModel.get('symbolRepeatDirection'), + symbolPatternSize: symbolPatternSize, + rotation: rotation, + animationModel: isAnimationEnabled ? itemModel : null, + hoverScale: isAnimationEnabled && itemModel.get(['emphasis', 'scale']), + z2: itemModel.getShallow('z', true) || 0 + }; + prepareBarLength(itemModel, symbolRepeat, layout, opt, symbolMeta); + prepareSymbolSize(data, dataIndex, layout, symbolRepeat, symbolClip, symbolMeta.boundingLength, symbolMeta.pxSign, symbolPatternSize, opt, symbolMeta); + prepareLineWidth(itemModel, symbolMeta.symbolScale, rotation, opt, symbolMeta); + var symbolSize = symbolMeta.symbolSize; + var symbolOffset = normalizeSymbolOffset(itemModel.get('symbolOffset'), symbolSize); + prepareLayoutInfo(itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset, symbolPosition, symbolMeta.valueLineWidth, symbolMeta.boundingLength, symbolMeta.repeatCutLength, opt, symbolMeta); + return symbolMeta; + } // bar length can be negative. + + + function prepareBarLength(itemModel, symbolRepeat, layout, opt, outputSymbolMeta) { + var valueDim = opt.valueDim; + var symbolBoundingData = itemModel.get('symbolBoundingData'); + var valueAxis = opt.coordSys.getOtherAxis(opt.coordSys.getBaseAxis()); + var zeroPx = valueAxis.toGlobalCoord(valueAxis.dataToCoord(0)); + var pxSignIdx = 1 - +(layout[valueDim.wh] <= 0); + var boundingLength; + + if (isArray(symbolBoundingData)) { + var symbolBoundingExtent = [convertToCoordOnAxis(valueAxis, symbolBoundingData[0]) - zeroPx, convertToCoordOnAxis(valueAxis, symbolBoundingData[1]) - zeroPx]; + symbolBoundingExtent[1] < symbolBoundingExtent[0] && symbolBoundingExtent.reverse(); + boundingLength = symbolBoundingExtent[pxSignIdx]; + } else if (symbolBoundingData != null) { + boundingLength = convertToCoordOnAxis(valueAxis, symbolBoundingData) - zeroPx; + } else if (symbolRepeat) { + boundingLength = opt.coordSysExtent[valueDim.index][pxSignIdx] - zeroPx; + } else { + boundingLength = layout[valueDim.wh]; + } + + outputSymbolMeta.boundingLength = boundingLength; + + if (symbolRepeat) { + outputSymbolMeta.repeatCutLength = layout[valueDim.wh]; + } // if 'pxSign' means sign of pixel, it can't be zero, or symbolScale will be zero + // and when borderWidth be settled, the actual linewidth will be NaN + + + outputSymbolMeta.pxSign = boundingLength > 0 ? 1 : -1; + } + + function convertToCoordOnAxis(axis, value) { + return axis.toGlobalCoord(axis.dataToCoord(axis.scale.parse(value))); + } // Support ['100%', '100%'] + + + function prepareSymbolSize(data, dataIndex, layout, symbolRepeat, symbolClip, boundingLength, pxSign, symbolPatternSize, opt, outputSymbolMeta) { + var valueDim = opt.valueDim; + var categoryDim = opt.categoryDim; + var categorySize = Math.abs(layout[categoryDim.wh]); + var symbolSize = data.getItemVisual(dataIndex, 'symbolSize'); + var parsedSymbolSize; + + if (isArray(symbolSize)) { + parsedSymbolSize = symbolSize.slice(); + } else { + if (symbolSize == null) { + // will parse to number below + parsedSymbolSize = ['100%', '100%']; + } else { + parsedSymbolSize = [symbolSize, symbolSize]; + } + } // Note: percentage symbolSize (like '100%') do not consider lineWidth, because it is + // to complicated to calculate real percent value if considering scaled lineWidth. + // So the actual size will bigger than layout size if lineWidth is bigger than zero, + // which can be tolerated in pictorial chart. + + + parsedSymbolSize[categoryDim.index] = parsePercent$1(parsedSymbolSize[categoryDim.index], categorySize); + parsedSymbolSize[valueDim.index] = parsePercent$1(parsedSymbolSize[valueDim.index], symbolRepeat ? categorySize : Math.abs(boundingLength)); + outputSymbolMeta.symbolSize = parsedSymbolSize; // If x or y is less than zero, show reversed shape. + + var symbolScale = outputSymbolMeta.symbolScale = [parsedSymbolSize[0] / symbolPatternSize, parsedSymbolSize[1] / symbolPatternSize]; // Follow convention, 'right' and 'top' is the normal scale. + + symbolScale[valueDim.index] *= (opt.isHorizontal ? -1 : 1) * pxSign; + } + + function prepareLineWidth(itemModel, symbolScale, rotation, opt, outputSymbolMeta) { + // In symbols are drawn with scale, so do not need to care about the case that width + // or height are too small. But symbol use strokeNoScale, where acture lineWidth should + // be calculated. + var valueLineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0; + + if (valueLineWidth) { + pathForLineWidth.attr({ + scaleX: symbolScale[0], + scaleY: symbolScale[1], + rotation: rotation + }); + pathForLineWidth.updateTransform(); + valueLineWidth /= pathForLineWidth.getLineScale(); + valueLineWidth *= symbolScale[opt.valueDim.index]; + } + + outputSymbolMeta.valueLineWidth = valueLineWidth || 0; + } + + function prepareLayoutInfo(itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset, symbolPosition, valueLineWidth, boundingLength, repeatCutLength, opt, outputSymbolMeta) { + var categoryDim = opt.categoryDim; + var valueDim = opt.valueDim; + var pxSign = outputSymbolMeta.pxSign; + var unitLength = Math.max(symbolSize[valueDim.index] + valueLineWidth, 0); + var pathLen = unitLength; // Note: rotation will not effect the layout of symbols, because user may + // want symbols to rotate on its center, which should not be translated + // when rotating. + + if (symbolRepeat) { + var absBoundingLength = Math.abs(boundingLength); + var symbolMargin = retrieve(itemModel.get('symbolMargin'), '15%') + ''; + var hasEndGap = false; + + if (symbolMargin.lastIndexOf('!') === symbolMargin.length - 1) { + hasEndGap = true; + symbolMargin = symbolMargin.slice(0, symbolMargin.length - 1); + } + + var symbolMarginNumeric = parsePercent$1(symbolMargin, symbolSize[valueDim.index]); + var uLenWithMargin = Math.max(unitLength + symbolMarginNumeric * 2, 0); // When symbol margin is less than 0, margin at both ends will be subtracted + // to ensure that all of the symbols will not be overflow the given area. + + var endFix = hasEndGap ? 0 : symbolMarginNumeric * 2; // Both final repeatTimes and final symbolMarginNumeric area calculated based on + // boundingLength. + + var repeatSpecified = isNumeric(symbolRepeat); + var repeatTimes = repeatSpecified ? symbolRepeat : toIntTimes((absBoundingLength + endFix) / uLenWithMargin); // Adjust calculate margin, to ensure each symbol is displayed + // entirely in the given layout area. + + var mDiff = absBoundingLength - repeatTimes * unitLength; + symbolMarginNumeric = mDiff / 2 / (hasEndGap ? repeatTimes : Math.max(repeatTimes - 1, 1)); + uLenWithMargin = unitLength + symbolMarginNumeric * 2; + endFix = hasEndGap ? 0 : symbolMarginNumeric * 2; // Update repeatTimes when not all symbol will be shown. + + if (!repeatSpecified && symbolRepeat !== 'fixed') { + repeatTimes = repeatCutLength ? toIntTimes((Math.abs(repeatCutLength) + endFix) / uLenWithMargin) : 0; + } + + pathLen = repeatTimes * uLenWithMargin - endFix; + outputSymbolMeta.repeatTimes = repeatTimes; + outputSymbolMeta.symbolMargin = symbolMarginNumeric; + } + + var sizeFix = pxSign * (pathLen / 2); + var pathPosition = outputSymbolMeta.pathPosition = []; + pathPosition[categoryDim.index] = layout[categoryDim.wh] / 2; + pathPosition[valueDim.index] = symbolPosition === 'start' ? sizeFix : symbolPosition === 'end' ? boundingLength - sizeFix : boundingLength / 2; // 'center' + + if (symbolOffset) { + pathPosition[0] += symbolOffset[0]; + pathPosition[1] += symbolOffset[1]; + } + + var bundlePosition = outputSymbolMeta.bundlePosition = []; + bundlePosition[categoryDim.index] = layout[categoryDim.xy]; + bundlePosition[valueDim.index] = layout[valueDim.xy]; + var barRectShape = outputSymbolMeta.barRectShape = extend({}, layout); + barRectShape[valueDim.wh] = pxSign * Math.max(Math.abs(layout[valueDim.wh]), Math.abs(pathPosition[valueDim.index] + sizeFix)); + barRectShape[categoryDim.wh] = layout[categoryDim.wh]; + var clipShape = outputSymbolMeta.clipShape = {}; // Consider that symbol may be overflow layout rect. + + clipShape[categoryDim.xy] = -layout[categoryDim.xy]; + clipShape[categoryDim.wh] = opt.ecSize[categoryDim.wh]; + clipShape[valueDim.xy] = 0; + clipShape[valueDim.wh] = layout[valueDim.wh]; + } + + function createPath(symbolMeta) { + var symbolPatternSize = symbolMeta.symbolPatternSize; + var path = createSymbol( // Consider texture img, make a big size. + symbolMeta.symbolType, -symbolPatternSize / 2, -symbolPatternSize / 2, symbolPatternSize, symbolPatternSize); + path.attr({ + culling: true + }); + path.type !== 'image' && path.setStyle({ + strokeNoScale: true + }); + return path; + } + + function createOrUpdateRepeatSymbols(bar, opt, symbolMeta, isUpdate) { + var bundle = bar.__pictorialBundle; + var symbolSize = symbolMeta.symbolSize; + var valueLineWidth = symbolMeta.valueLineWidth; + var pathPosition = symbolMeta.pathPosition; + var valueDim = opt.valueDim; + var repeatTimes = symbolMeta.repeatTimes || 0; + var index = 0; + var unit = symbolSize[opt.valueDim.index] + valueLineWidth + symbolMeta.symbolMargin * 2; + eachPath(bar, function (path) { + path.__pictorialAnimationIndex = index; + path.__pictorialRepeatTimes = repeatTimes; + + if (index < repeatTimes) { + updateAttr(path, null, makeTarget(index), symbolMeta, isUpdate); + } else { + updateAttr(path, null, { + scaleX: 0, + scaleY: 0 + }, symbolMeta, isUpdate, function () { + bundle.remove(path); + }); + } // updateHoverAnimation(path, symbolMeta); + + + index++; + }); + + for (; index < repeatTimes; index++) { + var path = createPath(symbolMeta); + path.__pictorialAnimationIndex = index; + path.__pictorialRepeatTimes = repeatTimes; + bundle.add(path); + var target = makeTarget(index); + updateAttr(path, { + x: target.x, + y: target.y, + scaleX: 0, + scaleY: 0 + }, { + scaleX: target.scaleX, + scaleY: target.scaleY, + rotation: target.rotation + }, symbolMeta, isUpdate); + } + + function makeTarget(index) { + var position = pathPosition.slice(); // (start && pxSign > 0) || (end && pxSign < 0): i = repeatTimes - index + // Otherwise: i = index; + + var pxSign = symbolMeta.pxSign; + var i = index; + + if (symbolMeta.symbolRepeatDirection === 'start' ? pxSign > 0 : pxSign < 0) { + i = repeatTimes - 1 - index; + } + + position[valueDim.index] = unit * (i - repeatTimes / 2 + 0.5) + pathPosition[valueDim.index]; + return { + x: position[0], + y: position[1], + scaleX: symbolMeta.symbolScale[0], + scaleY: symbolMeta.symbolScale[1], + rotation: symbolMeta.rotation + }; + } + } + + function createOrUpdateSingleSymbol(bar, opt, symbolMeta, isUpdate) { + var bundle = bar.__pictorialBundle; + var mainPath = bar.__pictorialMainPath; + + if (!mainPath) { + mainPath = bar.__pictorialMainPath = createPath(symbolMeta); + bundle.add(mainPath); + updateAttr(mainPath, { + x: symbolMeta.pathPosition[0], + y: symbolMeta.pathPosition[1], + scaleX: 0, + scaleY: 0, + rotation: symbolMeta.rotation + }, { + scaleX: symbolMeta.symbolScale[0], + scaleY: symbolMeta.symbolScale[1] + }, symbolMeta, isUpdate); + } else { + updateAttr(mainPath, null, { + x: symbolMeta.pathPosition[0], + y: symbolMeta.pathPosition[1], + scaleX: symbolMeta.symbolScale[0], + scaleY: symbolMeta.symbolScale[1], + rotation: symbolMeta.rotation + }, symbolMeta, isUpdate); + } + } // bar rect is used for label. + + + function createOrUpdateBarRect(bar, symbolMeta, isUpdate) { + var rectShape = extend({}, symbolMeta.barRectShape); + var barRect = bar.__pictorialBarRect; + + if (!barRect) { + barRect = bar.__pictorialBarRect = new Rect({ + z2: 2, + shape: rectShape, + silent: true, + style: { + stroke: 'transparent', + fill: 'transparent', + lineWidth: 0 + } + }); + barRect.disableMorphing = true; + bar.add(barRect); + } else { + updateAttr(barRect, null, { + shape: rectShape + }, symbolMeta, isUpdate); + } + } + + function createOrUpdateClip(bar, opt, symbolMeta, isUpdate) { + // If not clip, symbol will be remove and rebuilt. + if (symbolMeta.symbolClip) { + var clipPath = bar.__pictorialClipPath; + var clipShape = extend({}, symbolMeta.clipShape); + var valueDim = opt.valueDim; + var animationModel = symbolMeta.animationModel; + var dataIndex = symbolMeta.dataIndex; + + if (clipPath) { + updateProps(clipPath, { + shape: clipShape + }, animationModel, dataIndex); + } else { + clipShape[valueDim.wh] = 0; + clipPath = new Rect({ + shape: clipShape + }); + + bar.__pictorialBundle.setClipPath(clipPath); + + bar.__pictorialClipPath = clipPath; + var target = {}; + target[valueDim.wh] = symbolMeta.clipShape[valueDim.wh]; + graphic[isUpdate ? 'updateProps' : 'initProps'](clipPath, { + shape: target + }, animationModel, dataIndex); + } + } + } + + function getItemModel(data, dataIndex) { + var itemModel = data.getItemModel(dataIndex); + itemModel.getAnimationDelayParams = getAnimationDelayParams; + itemModel.isAnimationEnabled = isAnimationEnabled; + return itemModel; + } + + function getAnimationDelayParams(path) { + // The order is the same as the z-order, see `symbolRepeatDiretion`. + return { + index: path.__pictorialAnimationIndex, + count: path.__pictorialRepeatTimes + }; + } + + function isAnimationEnabled() { + // `animation` prop can be set on itemModel in pictorial bar chart. + return this.parentModel.isAnimationEnabled() && !!this.getShallow('animation'); + } + + function createBar(data, opt, symbolMeta, isUpdate) { + // bar is the main element for each data. + var bar = new Group(); // bundle is used for location and clip. + + var bundle = new Group(); + bar.add(bundle); + bar.__pictorialBundle = bundle; + bundle.x = symbolMeta.bundlePosition[0]; + bundle.y = symbolMeta.bundlePosition[1]; + + if (symbolMeta.symbolRepeat) { + createOrUpdateRepeatSymbols(bar, opt, symbolMeta); + } else { + createOrUpdateSingleSymbol(bar, opt, symbolMeta); + } + + createOrUpdateBarRect(bar, symbolMeta, isUpdate); + createOrUpdateClip(bar, opt, symbolMeta, isUpdate); + bar.__pictorialShapeStr = getShapeStr(data, symbolMeta); + bar.__pictorialSymbolMeta = symbolMeta; + return bar; + } + + function updateBar(bar, opt, symbolMeta) { + var animationModel = symbolMeta.animationModel; + var dataIndex = symbolMeta.dataIndex; + var bundle = bar.__pictorialBundle; + updateProps(bundle, { + x: symbolMeta.bundlePosition[0], + y: symbolMeta.bundlePosition[1] + }, animationModel, dataIndex); + + if (symbolMeta.symbolRepeat) { + createOrUpdateRepeatSymbols(bar, opt, symbolMeta, true); + } else { + createOrUpdateSingleSymbol(bar, opt, symbolMeta, true); + } + + createOrUpdateBarRect(bar, symbolMeta, true); + createOrUpdateClip(bar, opt, symbolMeta, true); + } + + function removeBar(data, dataIndex, animationModel, bar) { + // Not show text when animating + var labelRect = bar.__pictorialBarRect; + labelRect && labelRect.removeTextContent(); + var pathes = []; + eachPath(bar, function (path) { + pathes.push(path); + }); + bar.__pictorialMainPath && pathes.push(bar.__pictorialMainPath); // I do not find proper remove animation for clip yet. + + bar.__pictorialClipPath && (animationModel = null); + each(pathes, function (path) { + removeElement(path, { + scaleX: 0, + scaleY: 0 + }, animationModel, dataIndex, function () { + bar.parent && bar.parent.remove(bar); + }); + }); + data.setItemGraphicEl(dataIndex, null); + } + + function getShapeStr(data, symbolMeta) { + return [data.getItemVisual(symbolMeta.dataIndex, 'symbol') || 'none', !!symbolMeta.symbolRepeat, !!symbolMeta.symbolClip].join(':'); + } + + function eachPath(bar, cb, context) { + // Do not use Group#eachChild, because it do not support remove. + each(bar.__pictorialBundle.children(), function (el) { + el !== bar.__pictorialBarRect && cb.call(context, el); + }); + } + + function updateAttr(el, immediateAttrs, animationAttrs, symbolMeta, isUpdate, cb) { + immediateAttrs && el.attr(immediateAttrs); // when symbolCip used, only clip path has init animation, otherwise it would be weird effect. + + if (symbolMeta.symbolClip && !isUpdate) { + animationAttrs && el.attr(animationAttrs); + } else { + animationAttrs && graphic[isUpdate ? 'updateProps' : 'initProps'](el, animationAttrs, symbolMeta.animationModel, symbolMeta.dataIndex, cb); + } + } + + function updateCommon$1(bar, opt, symbolMeta) { + var dataIndex = symbolMeta.dataIndex; + var itemModel = symbolMeta.itemModel; // Color must be excluded. + // Because symbol provide setColor individually to set fill and stroke + + var emphasisModel = itemModel.getModel('emphasis'); + var emphasisStyle = emphasisModel.getModel('itemStyle').getItemStyle(); + var blurStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle(); + var selectStyle = itemModel.getModel(['select', 'itemStyle']).getItemStyle(); + var cursorStyle = itemModel.getShallow('cursor'); + var focus = emphasisModel.get('focus'); + var blurScope = emphasisModel.get('blurScope'); + var hoverScale = emphasisModel.get('scale'); + eachPath(bar, function (path) { + if (path instanceof ZRImage) { + var pathStyle = path.style; + path.useStyle(extend({ + // TODO other properties like dx, dy ? + image: pathStyle.image, + x: pathStyle.x, + y: pathStyle.y, + width: pathStyle.width, + height: pathStyle.height + }, symbolMeta.style)); + } else { + path.useStyle(symbolMeta.style); + } + + var emphasisState = path.ensureState('emphasis'); + emphasisState.style = emphasisStyle; + + if (hoverScale) { + // NOTE: Must after scale is set after updateAttr + emphasisState.scaleX = path.scaleX * 1.1; + emphasisState.scaleY = path.scaleY * 1.1; + } + + path.ensureState('blur').style = blurStyle; + path.ensureState('select').style = selectStyle; + cursorStyle && (path.cursor = cursorStyle); + path.z2 = symbolMeta.z2; + }); + var barPositionOutside = opt.valueDim.posDesc[+(symbolMeta.boundingLength > 0)]; + var barRect = bar.__pictorialBarRect; + setLabelStyle(barRect, getLabelStatesModels(itemModel), { + labelFetcher: opt.seriesModel, + labelDataIndex: dataIndex, + defaultText: getDefaultLabel(opt.seriesModel.getData(), dataIndex), + inheritColor: symbolMeta.style.fill, + defaultOpacity: symbolMeta.style.opacity, + defaultOutsidePosition: barPositionOutside + }); + toggleHoverEmphasis(bar, focus, blurScope, emphasisModel.get('disabled')); + } + + function toIntTimes(times) { + var roundedTimes = Math.round(times); // Escapse accurate error + + return Math.abs(times - roundedTimes) < 1e-4 ? roundedTimes : Math.ceil(times); + } + + var PictorialBarSeriesModel = + /** @class */ + function (_super) { + __extends(PictorialBarSeriesModel, _super); + + function PictorialBarSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = PictorialBarSeriesModel.type; + _this.hasSymbolVisual = true; + _this.defaultSymbol = 'roundRect'; + return _this; + } + + PictorialBarSeriesModel.prototype.getInitialData = function (option) { + // Disable stack. + option.stack = null; + return _super.prototype.getInitialData.apply(this, arguments); + }; + + PictorialBarSeriesModel.type = 'series.pictorialBar'; + PictorialBarSeriesModel.dependencies = ['grid']; + PictorialBarSeriesModel.defaultOption = inheritDefaultOption(BaseBarSeriesModel.defaultOption, { + symbol: 'circle', + symbolSize: null, + symbolRotate: null, + symbolPosition: null, + symbolOffset: null, + symbolMargin: null, + symbolRepeat: false, + symbolRepeatDirection: 'end', + symbolClip: false, + symbolBoundingData: null, + symbolPatternSize: 400, + barGap: '-100%', + // z can be set in data item, which is z2 actually. + // Disable progressive + progressive: 0, + emphasis: { + // By default pictorialBar do not hover scale. Hover scale is not suitable + // for the case that both has foreground and background. + scale: false + }, + select: { + itemStyle: { + borderColor: '#212121' + } + } + }); + return PictorialBarSeriesModel; + }(BaseBarSeriesModel); + + function install$o(registers) { + registers.registerChartView(PictorialBarView); + registers.registerSeriesModel(PictorialBarSeriesModel); + registers.registerLayout(registers.PRIORITY.VISUAL.LAYOUT, curry(layout, 'pictorialBar')); // Do layout after other overall layout, which can preapre some informations. + + registers.registerLayout(registers.PRIORITY.VISUAL.PROGRESSIVE_LAYOUT, createProgressiveLayout('pictorialBar')); + } + + var ThemeRiverView = + /** @class */ + function (_super) { + __extends(ThemeRiverView, _super); + + function ThemeRiverView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ThemeRiverView.type; + _this._layers = []; + return _this; + } + + ThemeRiverView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var self = this; + var group = this.group; + var layersSeries = seriesModel.getLayerSeries(); + var layoutInfo = data.getLayout('layoutInfo'); + var rect = layoutInfo.rect; + var boundaryGap = layoutInfo.boundaryGap; + group.x = 0; + group.y = rect.y + boundaryGap[0]; + + function keyGetter(item) { + return item.name; + } + + var dataDiffer = new DataDiffer(this._layersSeries || [], layersSeries, keyGetter, keyGetter); + var newLayersGroups = []; + dataDiffer.add(bind(process, this, 'add')).update(bind(process, this, 'update')).remove(bind(process, this, 'remove')).execute(); + + function process(status, idx, oldIdx) { + var oldLayersGroups = self._layers; + + if (status === 'remove') { + group.remove(oldLayersGroups[idx]); + return; + } + + var points0 = []; + var points1 = []; + var style; + var indices = layersSeries[idx].indices; + var j = 0; + + for (; j < indices.length; j++) { + var layout = data.getItemLayout(indices[j]); + var x = layout.x; + var y0 = layout.y0; + var y = layout.y; + points0.push(x, y0); + points1.push(x, y0 + y); + style = data.getItemVisual(indices[j], 'style'); + } + + var polygon; + var textLayout = data.getItemLayout(indices[0]); + var labelModel = seriesModel.getModel('label'); + var margin = labelModel.get('margin'); + var emphasisModel = seriesModel.getModel('emphasis'); + + if (status === 'add') { + var layerGroup = newLayersGroups[idx] = new Group(); + polygon = new ECPolygon({ + shape: { + points: points0, + stackedOnPoints: points1, + smooth: 0.4, + stackedOnSmooth: 0.4, + smoothConstraint: false + }, + z2: 0 + }); + layerGroup.add(polygon); + group.add(layerGroup); + + if (seriesModel.isAnimationEnabled()) { + polygon.setClipPath(createGridClipShape$2(polygon.getBoundingRect(), seriesModel, function () { + polygon.removeClipPath(); + })); + } + } else { + var layerGroup = oldLayersGroups[oldIdx]; + polygon = layerGroup.childAt(0); + group.add(layerGroup); + newLayersGroups[idx] = layerGroup; + updateProps(polygon, { + shape: { + points: points0, + stackedOnPoints: points1 + } + }, seriesModel); + saveOldStyle(polygon); + } + + setLabelStyle(polygon, getLabelStatesModels(seriesModel), { + labelDataIndex: indices[j - 1], + defaultText: data.getName(indices[j - 1]), + inheritColor: style.fill + }, { + normal: { + verticalAlign: 'middle' // align: 'right' + + } + }); + polygon.setTextConfig({ + position: null, + local: true + }); + var labelEl = polygon.getTextContent(); // TODO More label position options. + + if (labelEl) { + labelEl.x = textLayout.x - margin; + labelEl.y = textLayout.y0 + textLayout.y / 2; + } + + polygon.useStyle(style); + data.setItemGraphicEl(idx, polygon); + setStatesStylesFromModel(polygon, seriesModel); + toggleHoverEmphasis(polygon, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled')); + } + + this._layersSeries = layersSeries; + this._layers = newLayersGroups; + }; + + ThemeRiverView.type = 'themeRiver'; + return ThemeRiverView; + }(ChartView); + + function createGridClipShape$2(rect, seriesModel, cb) { + var rectEl = new Rect({ + shape: { + x: rect.x - 10, + y: rect.y - 10, + width: 0, + height: rect.height + 20 + } + }); + initProps(rectEl, { + shape: { + x: rect.x - 50, + width: rect.width + 100, + height: rect.height + 20 + } + }, seriesModel, cb); + return rectEl; + } + + var DATA_NAME_INDEX = 2; + + var ThemeRiverSeriesModel = + /** @class */ + function (_super) { + __extends(ThemeRiverSeriesModel, _super); + + function ThemeRiverSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ThemeRiverSeriesModel.type; + return _this; + } + /** + * @override + */ + + + ThemeRiverSeriesModel.prototype.init = function (option) { + // eslint-disable-next-line + _super.prototype.init.apply(this, arguments); // Put this function here is for the sake of consistency of code style. + // Enable legend selection for each data item + // Use a function instead of direct access because data reference may changed + + + this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this)); + }; + /** + * If there is no value of a certain point in the time for some event,set it value to 0. + * + * @param {Array} data initial data in the option + * @return {Array} + */ + + + ThemeRiverSeriesModel.prototype.fixData = function (data) { + var rawDataLength = data.length; + /** + * Make sure every layer data get the same keys. + * The value index tells which layer has visited. + * { + * 2014/01/01: -1 + * } + */ + + var timeValueKeys = {}; // grouped data by name + + var groupResult = groupData(data, function (item) { + if (!timeValueKeys.hasOwnProperty(item[0] + '')) { + timeValueKeys[item[0] + ''] = -1; + } + + return item[2]; + }); + var layerData = []; + groupResult.buckets.each(function (items, key) { + layerData.push({ + name: key, + dataList: items + }); + }); + var layerNum = layerData.length; + + for (var k = 0; k < layerNum; ++k) { + var name_1 = layerData[k].name; + + for (var j = 0; j < layerData[k].dataList.length; ++j) { + var timeValue = layerData[k].dataList[j][0] + ''; + timeValueKeys[timeValue] = k; + } + + for (var timeValue in timeValueKeys) { + if (timeValueKeys.hasOwnProperty(timeValue) && timeValueKeys[timeValue] !== k) { + timeValueKeys[timeValue] = k; + data[rawDataLength] = [timeValue, 0, name_1]; + rawDataLength++; + } + } + } + + return data; + }; + /** + * @override + * @param option the initial option that user gived + * @param ecModel the model object for themeRiver option + */ + + + ThemeRiverSeriesModel.prototype.getInitialData = function (option, ecModel) { + var singleAxisModel = this.getReferringComponents('singleAxis', SINGLE_REFERRING).models[0]; + var axisType = singleAxisModel.get('type'); // filter the data item with the value of label is undefined + + var filterData = filter(option.data, function (dataItem) { + return dataItem[2] !== undefined; + }); // ??? TODO design a stage to transfer data for themeRiver and lines? + + var data = this.fixData(filterData || []); + var nameList = []; + var nameMap = this.nameMap = createHashMap(); + var count = 0; + + for (var i = 0; i < data.length; ++i) { + nameList.push(data[i][DATA_NAME_INDEX]); + + if (!nameMap.get(data[i][DATA_NAME_INDEX])) { + nameMap.set(data[i][DATA_NAME_INDEX], count); + count++; + } + } + + var dimensions = prepareSeriesDataSchema(data, { + coordDimensions: ['single'], + dimensionsDefine: [{ + name: 'time', + type: getDimensionTypeByAxis(axisType) + }, { + name: 'value', + type: 'float' + }, { + name: 'name', + type: 'ordinal' + }], + encodeDefine: { + single: 0, + value: 1, + itemName: 2 + } + }).dimensions; + var list = new SeriesData(dimensions, this); + list.initData(data); + return list; + }; + /** + * The raw data is divided into multiple layers and each layer + * has same name. + */ + + + ThemeRiverSeriesModel.prototype.getLayerSeries = function () { + var data = this.getData(); + var lenCount = data.count(); + var indexArr = []; + + for (var i = 0; i < lenCount; ++i) { + indexArr[i] = i; + } + + var timeDim = data.mapDimension('single'); // data group by name + + var groupResult = groupData(indexArr, function (index) { + return data.get('name', index); + }); + var layerSeries = []; + groupResult.buckets.each(function (items, key) { + items.sort(function (index1, index2) { + return data.get(timeDim, index1) - data.get(timeDim, index2); + }); + layerSeries.push({ + name: key, + indices: items + }); + }); + return layerSeries; + }; + /** + * Get data indices for show tooltip content + */ + + + ThemeRiverSeriesModel.prototype.getAxisTooltipData = function (dim, value, baseAxis) { + if (!isArray(dim)) { + dim = dim ? [dim] : []; + } + + var data = this.getData(); + var layerSeries = this.getLayerSeries(); + var indices = []; + var layerNum = layerSeries.length; + var nestestValue; + + for (var i = 0; i < layerNum; ++i) { + var minDist = Number.MAX_VALUE; + var nearestIdx = -1; + var pointNum = layerSeries[i].indices.length; + + for (var j = 0; j < pointNum; ++j) { + var theValue = data.get(dim[0], layerSeries[i].indices[j]); + var dist = Math.abs(theValue - value); + + if (dist <= minDist) { + nestestValue = theValue; + minDist = dist; + nearestIdx = layerSeries[i].indices[j]; + } + } + + indices.push(nearestIdx); + } + + return { + dataIndices: indices, + nestestValue: nestestValue + }; + }; + + ThemeRiverSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var data = this.getData(); + var name = data.getName(dataIndex); + var value = data.get(data.mapDimension('value'), dataIndex); + return createTooltipMarkup('nameValue', { + name: name, + value: value + }); + }; + + ThemeRiverSeriesModel.type = 'series.themeRiver'; + ThemeRiverSeriesModel.dependencies = ['singleAxis']; + ThemeRiverSeriesModel.defaultOption = { + // zlevel: 0, + z: 2, + colorBy: 'data', + coordinateSystem: 'singleAxis', + // gap in axis's orthogonal orientation + boundaryGap: ['10%', '10%'], + // legendHoverLink: true, + singleAxisIndex: 0, + animationEasing: 'linear', + label: { + margin: 4, + show: true, + position: 'left', + fontSize: 11 + }, + emphasis: { + label: { + show: true + } + } + }; + return ThemeRiverSeriesModel; + }(SeriesModel); + + function themeRiverLayout(ecModel, api) { + ecModel.eachSeriesByType('themeRiver', function (seriesModel) { + var data = seriesModel.getData(); + var single = seriesModel.coordinateSystem; + var layoutInfo = {}; // use the axis boundingRect for view + + var rect = single.getRect(); + layoutInfo.rect = rect; + var boundaryGap = seriesModel.get('boundaryGap'); + var axis = single.getAxis(); + layoutInfo.boundaryGap = boundaryGap; + + if (axis.orient === 'horizontal') { + boundaryGap[0] = parsePercent$1(boundaryGap[0], rect.height); + boundaryGap[1] = parsePercent$1(boundaryGap[1], rect.height); + var height = rect.height - boundaryGap[0] - boundaryGap[1]; + doThemeRiverLayout(data, seriesModel, height); + } else { + boundaryGap[0] = parsePercent$1(boundaryGap[0], rect.width); + boundaryGap[1] = parsePercent$1(boundaryGap[1], rect.width); + var width = rect.width - boundaryGap[0] - boundaryGap[1]; + doThemeRiverLayout(data, seriesModel, width); + } + + data.setLayout('layoutInfo', layoutInfo); + }); + } + /** + * The layout information about themeriver + * + * @param data data in the series + * @param seriesModel the model object of themeRiver series + * @param height value used to compute every series height + */ + + function doThemeRiverLayout(data, seriesModel, height) { + if (!data.count()) { + return; + } + + var coordSys = seriesModel.coordinateSystem; // the data in each layer are organized into a series. + + var layerSeries = seriesModel.getLayerSeries(); // the points in each layer. + + var timeDim = data.mapDimension('single'); + var valueDim = data.mapDimension('value'); + var layerPoints = map(layerSeries, function (singleLayer) { + return map(singleLayer.indices, function (idx) { + var pt = coordSys.dataToPoint(data.get(timeDim, idx)); + pt[1] = data.get(valueDim, idx); + return pt; + }); + }); + var base = computeBaseline(layerPoints); + var baseLine = base.y0; + var ky = height / base.max; // set layout information for each item. + + var n = layerSeries.length; + var m = layerSeries[0].indices.length; + var baseY0; + + for (var j = 0; j < m; ++j) { + baseY0 = baseLine[j] * ky; + data.setItemLayout(layerSeries[0].indices[j], { + layerIndex: 0, + x: layerPoints[0][j][0], + y0: baseY0, + y: layerPoints[0][j][1] * ky + }); + + for (var i = 1; i < n; ++i) { + baseY0 += layerPoints[i - 1][j][1] * ky; + data.setItemLayout(layerSeries[i].indices[j], { + layerIndex: i, + x: layerPoints[i][j][0], + y0: baseY0, + y: layerPoints[i][j][1] * ky + }); + } + } + } + /** + * Compute the baseLine of the rawdata + * Inspired by Lee Byron's paper Stacked Graphs - Geometry & Aesthetics + * + * @param data the points in each layer + */ + + + function computeBaseline(data) { + var layerNum = data.length; + var pointNum = data[0].length; + var sums = []; + var y0 = []; + var max = 0; + + for (var i = 0; i < pointNum; ++i) { + var temp = 0; + + for (var j = 0; j < layerNum; ++j) { + temp += data[j][i][1]; + } + + if (temp > max) { + max = temp; + } + + sums.push(temp); + } + + for (var k = 0; k < pointNum; ++k) { + y0[k] = (max - sums[k]) / 2; + } + + max = 0; + + for (var l = 0; l < pointNum; ++l) { + var sum = sums[l] + y0[l]; + + if (sum > max) { + max = sum; + } + } + + return { + y0: y0, + max: max + }; + } + + function install$p(registers) { + registers.registerChartView(ThemeRiverView); + registers.registerSeriesModel(ThemeRiverSeriesModel); + registers.registerLayout(themeRiverLayout); + registers.registerProcessor(dataFilter('themeRiver')); + } + + var DEFAULT_SECTOR_Z = 2; + var DEFAULT_TEXT_Z = 4; + /** + * Sunburstce of Sunburst including Sector, Label, LabelLine + */ + + var SunburstPiece = + /** @class */ + function (_super) { + __extends(SunburstPiece, _super); + + function SunburstPiece(node, seriesModel, ecModel, api) { + var _this = _super.call(this) || this; + + _this.z2 = DEFAULT_SECTOR_Z; + _this.textConfig = { + inside: true + }; + getECData(_this).seriesIndex = seriesModel.seriesIndex; + var text = new ZRText({ + z2: DEFAULT_TEXT_Z, + silent: node.getModel().get(['label', 'silent']) + }); + + _this.setTextContent(text); + + _this.updateData(true, node, seriesModel, ecModel, api); + + return _this; + } + + SunburstPiece.prototype.updateData = function (firstCreate, node, // state: 'emphasis' | 'normal' | 'highlight' | 'downplay', + seriesModel, ecModel, api) { + this.node = node; + node.piece = this; + seriesModel = seriesModel || this._seriesModel; + ecModel = ecModel || this._ecModel; + var sector = this; + getECData(sector).dataIndex = node.dataIndex; + var itemModel = node.getModel(); + var emphasisModel = itemModel.getModel('emphasis'); + var layout = node.getLayout(); + var sectorShape = extend({}, layout); + sectorShape.label = null; + var normalStyle = node.getVisual('style'); + normalStyle.lineJoin = 'bevel'; + var decal = node.getVisual('decal'); + + if (decal) { + normalStyle.decal = createOrUpdatePatternFromDecal(decal, api); + } + + var cornerRadius = getSectorCornerRadius(itemModel.getModel('itemStyle'), sectorShape, true); + extend(sectorShape, cornerRadius); + each(SPECIAL_STATES, function (stateName) { + var state = sector.ensureState(stateName); + var itemStyleModel = itemModel.getModel([stateName, 'itemStyle']); + state.style = itemStyleModel.getItemStyle(); // border radius + + var cornerRadius = getSectorCornerRadius(itemStyleModel, sectorShape); + + if (cornerRadius) { + state.shape = cornerRadius; + } + }); + + if (firstCreate) { + sector.setShape(sectorShape); + sector.shape.r = layout.r0; + updateProps(sector, { + shape: { + r: layout.r + } + }, seriesModel, node.dataIndex); + } else { + // Disable animation for gradient since no interpolation method + // is supported for gradient + updateProps(sector, { + shape: sectorShape + }, seriesModel); + saveOldStyle(sector); + } + + sector.useStyle(normalStyle); + + this._updateLabel(seriesModel); + + var cursorStyle = itemModel.getShallow('cursor'); + cursorStyle && sector.attr('cursor', cursorStyle); + this._seriesModel = seriesModel || this._seriesModel; + this._ecModel = ecModel || this._ecModel; + var focus = emphasisModel.get('focus'); + var focusOrIndices = focus === 'ancestor' ? node.getAncestorsIndices() : focus === 'descendant' ? node.getDescendantIndices() : focus; + toggleHoverEmphasis(this, focusOrIndices, emphasisModel.get('blurScope'), emphasisModel.get('disabled')); + }; + + SunburstPiece.prototype._updateLabel = function (seriesModel) { + var _this = this; + + var itemModel = this.node.getModel(); + var normalLabelModel = itemModel.getModel('label'); + var layout = this.node.getLayout(); + var angle = layout.endAngle - layout.startAngle; + var midAngle = (layout.startAngle + layout.endAngle) / 2; + var dx = Math.cos(midAngle); + var dy = Math.sin(midAngle); + var sector = this; + var label = sector.getTextContent(); + var dataIndex = this.node.dataIndex; + var labelMinAngle = normalLabelModel.get('minAngle') / 180 * Math.PI; + var isNormalShown = normalLabelModel.get('show') && !(labelMinAngle != null && Math.abs(angle) < labelMinAngle); + label.ignore = !isNormalShown; // TODO use setLabelStyle + + each(DISPLAY_STATES, function (stateName) { + var labelStateModel = stateName === 'normal' ? itemModel.getModel('label') : itemModel.getModel([stateName, 'label']); + var isNormal = stateName === 'normal'; + var state = isNormal ? label : label.ensureState(stateName); + var text = seriesModel.getFormattedLabel(dataIndex, stateName); + + if (isNormal) { + text = text || _this.node.name; + } + + state.style = createTextStyle(labelStateModel, {}, null, stateName !== 'normal', true); + + if (text) { + state.style.text = text; + } // Not displaying text when angle is too small + + + var isShown = labelStateModel.get('show'); + + if (isShown != null && !isNormal) { + state.ignore = !isShown; + } + + var labelPosition = getLabelAttr(labelStateModel, 'position'); + var sectorState = isNormal ? sector : sector.states[stateName]; + var labelColor = sectorState.style.fill; + sectorState.textConfig = { + outsideFill: labelStateModel.get('color') === 'inherit' ? labelColor : null, + inside: labelPosition !== 'outside' + }; + var r; + var labelPadding = getLabelAttr(labelStateModel, 'distance') || 0; + var textAlign = getLabelAttr(labelStateModel, 'align'); + + if (labelPosition === 'outside') { + r = layout.r + labelPadding; + textAlign = midAngle > Math.PI / 2 ? 'right' : 'left'; + } else { + if (!textAlign || textAlign === 'center') { + // Put label in the center if it's a circle + if (angle === 2 * Math.PI && layout.r0 === 0) { + r = 0; + } else { + r = (layout.r + layout.r0) / 2; + } + + textAlign = 'center'; + } else if (textAlign === 'left') { + r = layout.r0 + labelPadding; + + if (midAngle > Math.PI / 2) { + textAlign = 'right'; + } + } else if (textAlign === 'right') { + r = layout.r - labelPadding; + + if (midAngle > Math.PI / 2) { + textAlign = 'left'; + } + } + } + + state.style.align = textAlign; + state.style.verticalAlign = getLabelAttr(labelStateModel, 'verticalAlign') || 'middle'; + state.x = r * dx + layout.cx; + state.y = r * dy + layout.cy; + var rotateType = getLabelAttr(labelStateModel, 'rotate'); + var rotate = 0; + + if (rotateType === 'radial') { + rotate = -midAngle; + + if (rotate < -Math.PI / 2) { + rotate += Math.PI; + } + } else if (rotateType === 'tangential') { + rotate = Math.PI / 2 - midAngle; + + if (rotate > Math.PI / 2) { + rotate -= Math.PI; + } else if (rotate < -Math.PI / 2) { + rotate += Math.PI; + } + } else if (isNumber(rotateType)) { + rotate = rotateType * Math.PI / 180; + } + + state.rotation = rotate; + }); + + function getLabelAttr(model, name) { + var stateAttr = model.get(name); + + if (stateAttr == null) { + return normalLabelModel.get(name); + } + + return stateAttr; + } + + label.dirtyStyle(); + }; + + return SunburstPiece; + }(Sector); + + var ROOT_TO_NODE_ACTION = 'sunburstRootToNode'; + var HIGHLIGHT_ACTION = 'sunburstHighlight'; + var UNHIGHLIGHT_ACTION = 'sunburstUnhighlight'; + function installSunburstAction(registers) { + registers.registerAction({ + type: ROOT_TO_NODE_ACTION, + update: 'updateView' + }, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', + subType: 'sunburst', + query: payload + }, handleRootToNode); + + function handleRootToNode(model, index) { + var targetInfo = retrieveTargetInfo(payload, [ROOT_TO_NODE_ACTION], model); + + if (targetInfo) { + var originViewRoot = model.getViewRoot(); + + if (originViewRoot) { + payload.direction = aboveViewRoot(originViewRoot, targetInfo.node) ? 'rollUp' : 'drillDown'; + } + + model.resetViewRoot(targetInfo.node); + } + } + }); + registers.registerAction({ + type: HIGHLIGHT_ACTION, + update: 'none' + }, function (payload, ecModel, api) { + // Clone + payload = extend({}, payload); + ecModel.eachComponent({ + mainType: 'series', + subType: 'sunburst', + query: payload + }, handleHighlight); + + function handleHighlight(model) { + var targetInfo = retrieveTargetInfo(payload, [HIGHLIGHT_ACTION], model); + + if (targetInfo) { + payload.dataIndex = targetInfo.node.dataIndex; + } + } + + if ("development" !== 'production') { + deprecateReplaceLog('highlight', 'sunburstHighlight'); + } // Fast forward action + + + api.dispatchAction(extend(payload, { + type: 'highlight' + })); + }); + registers.registerAction({ + type: UNHIGHLIGHT_ACTION, + update: 'updateView' + }, function (payload, ecModel, api) { + payload = extend({}, payload); + + if ("development" !== 'production') { + deprecateReplaceLog('downplay', 'sunburstUnhighlight'); + } + + api.dispatchAction(extend(payload, { + type: 'downplay' + })); + }); + } + + var SunburstView = + /** @class */ + function (_super) { + __extends(SunburstView, _super); + + function SunburstView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SunburstView.type; + return _this; + } + + SunburstView.prototype.render = function (seriesModel, ecModel, api, // @ts-ignore + payload) { + var self = this; + this.seriesModel = seriesModel; + this.api = api; + this.ecModel = ecModel; + var data = seriesModel.getData(); + var virtualRoot = data.tree.root; + var newRoot = seriesModel.getViewRoot(); + var group = this.group; + var renderLabelForZeroData = seriesModel.get('renderLabelForZeroData'); + var newChildren = []; + newRoot.eachNode(function (node) { + newChildren.push(node); + }); + var oldChildren = this._oldChildren || []; + dualTravel(newChildren, oldChildren); + renderRollUp(virtualRoot, newRoot); + + this._initEvents(); + + this._oldChildren = newChildren; + + function dualTravel(newChildren, oldChildren) { + if (newChildren.length === 0 && oldChildren.length === 0) { + return; + } + + new DataDiffer(oldChildren, newChildren, getKey, getKey).add(processNode).update(processNode).remove(curry(processNode, null)).execute(); + + function getKey(node) { + return node.getId(); + } + + function processNode(newIdx, oldIdx) { + var newNode = newIdx == null ? null : newChildren[newIdx]; + var oldNode = oldIdx == null ? null : oldChildren[oldIdx]; + doRenderNode(newNode, oldNode); + } + } + + function doRenderNode(newNode, oldNode) { + if (!renderLabelForZeroData && newNode && !newNode.getValue()) { + // Not render data with value 0 + newNode = null; + } + + if (newNode !== virtualRoot && oldNode !== virtualRoot) { + if (oldNode && oldNode.piece) { + if (newNode) { + // Update + oldNode.piece.updateData(false, newNode, seriesModel, ecModel, api); // For tooltip + + data.setItemGraphicEl(newNode.dataIndex, oldNode.piece); + } else { + // Remove + removeNode(oldNode); + } + } else if (newNode) { + // Add + var piece = new SunburstPiece(newNode, seriesModel, ecModel, api); + group.add(piece); // For tooltip + + data.setItemGraphicEl(newNode.dataIndex, piece); + } + } + } + + function removeNode(node) { + if (!node) { + return; + } + + if (node.piece) { + group.remove(node.piece); + node.piece = null; + } + } + + function renderRollUp(virtualRoot, viewRoot) { + if (viewRoot.depth > 0) { + // Render + if (self.virtualPiece) { + // Update + self.virtualPiece.updateData(false, virtualRoot, seriesModel, ecModel, api); + } else { + // Add + self.virtualPiece = new SunburstPiece(virtualRoot, seriesModel, ecModel, api); + group.add(self.virtualPiece); + } // TODO event scope + + + viewRoot.piece.off('click'); + self.virtualPiece.on('click', function (e) { + self._rootToNode(viewRoot.parentNode); + }); + } else if (self.virtualPiece) { + // Remove + group.remove(self.virtualPiece); + self.virtualPiece = null; + } + } + }; + /** + * @private + */ + + + SunburstView.prototype._initEvents = function () { + var _this = this; + + this.group.off('click'); + this.group.on('click', function (e) { + var targetFound = false; + + var viewRoot = _this.seriesModel.getViewRoot(); + + viewRoot.eachNode(function (node) { + if (!targetFound && node.piece && node.piece === e.target) { + var nodeClick = node.getModel().get('nodeClick'); + + if (nodeClick === 'rootToNode') { + _this._rootToNode(node); + } else if (nodeClick === 'link') { + var itemModel = node.getModel(); + var link = itemModel.get('link'); + + if (link) { + var linkTarget = itemModel.get('target', true) || '_blank'; + windowOpen(link, linkTarget); + } + } + + targetFound = true; + } + }); + }); + }; + /** + * @private + */ + + + SunburstView.prototype._rootToNode = function (node) { + if (node !== this.seriesModel.getViewRoot()) { + this.api.dispatchAction({ + type: ROOT_TO_NODE_ACTION, + from: this.uid, + seriesId: this.seriesModel.id, + targetNode: node + }); + } + }; + /** + * @implement + */ + + + SunburstView.prototype.containPoint = function (point, seriesModel) { + var treeRoot = seriesModel.getData(); + var itemLayout = treeRoot.getItemLayout(0); + + if (itemLayout) { + var dx = point[0] - itemLayout.cx; + var dy = point[1] - itemLayout.cy; + var radius = Math.sqrt(dx * dx + dy * dy); + return radius <= itemLayout.r && radius >= itemLayout.r0; + } + }; + + SunburstView.type = 'sunburst'; + return SunburstView; + }(ChartView); + + var SunburstSeriesModel = + /** @class */ + function (_super) { + __extends(SunburstSeriesModel, _super); + + function SunburstSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SunburstSeriesModel.type; + _this.ignoreStyleOnData = true; + return _this; + } + + SunburstSeriesModel.prototype.getInitialData = function (option, ecModel) { + // Create a virtual root. + var root = { + name: option.name, + children: option.data + }; + completeTreeValue$1(root); + var levelModels = this._levelModels = map(option.levels || [], function (levelDefine) { + return new Model(levelDefine, this, ecModel); + }, this); // Make sure always a new tree is created when setOption, + // in TreemapView, we check whether oldTree === newTree + // to choose mappings approach among old shapes and new shapes. + + var tree = Tree.createTree(root, this, beforeLink); + + function beforeLink(nodeData) { + nodeData.wrapMethod('getItemModel', function (model, idx) { + var node = tree.getNodeByDataIndex(idx); + var levelModel = levelModels[node.depth]; + levelModel && (model.parentModel = levelModel); + return model; + }); + } + + return tree.data; + }; + + SunburstSeriesModel.prototype.optionUpdated = function () { + this.resetViewRoot(); + }; + /* + * @override + */ + + + SunburstSeriesModel.prototype.getDataParams = function (dataIndex) { + var params = _super.prototype.getDataParams.apply(this, arguments); + + var node = this.getData().tree.getNodeByDataIndex(dataIndex); + params.treePathInfo = wrapTreePathInfo(node, this); + return params; + }; + + SunburstSeriesModel.prototype.getLevelModel = function (node) { + return this._levelModels && this._levelModels[node.depth]; + }; + + SunburstSeriesModel.prototype.getViewRoot = function () { + return this._viewRoot; + }; + + SunburstSeriesModel.prototype.resetViewRoot = function (viewRoot) { + viewRoot ? this._viewRoot = viewRoot : viewRoot = this._viewRoot; + var root = this.getRawData().tree.root; + + if (!viewRoot || viewRoot !== root && !root.contains(viewRoot)) { + this._viewRoot = root; + } + }; + + SunburstSeriesModel.prototype.enableAriaDecal = function () { + enableAriaDecalForTree(this); + }; + + SunburstSeriesModel.type = 'series.sunburst'; + SunburstSeriesModel.defaultOption = { + // zlevel: 0, + z: 2, + // 默认全局居中 + center: ['50%', '50%'], + radius: [0, '75%'], + // 默认顺时针 + clockwise: true, + startAngle: 90, + // 最小角度改为0 + minAngle: 0, + // If still show when all data zero. + stillShowZeroSum: true, + // 'rootToNode', 'link', or false + nodeClick: 'rootToNode', + renderLabelForZeroData: false, + label: { + // could be: 'radial', 'tangential', or 'none' + rotate: 'radial', + show: true, + opacity: 1, + // 'left' is for inner side of inside, and 'right' is for outter + // side for inside + align: 'center', + position: 'inside', + distance: 5, + silent: true + }, + itemStyle: { + borderWidth: 1, + borderColor: 'white', + borderType: 'solid', + shadowBlur: 0, + shadowColor: 'rgba(0, 0, 0, 0.2)', + shadowOffsetX: 0, + shadowOffsetY: 0, + opacity: 1 + }, + emphasis: { + focus: 'descendant' + }, + blur: { + itemStyle: { + opacity: 0.2 + }, + label: { + opacity: 0.1 + } + }, + // Animation type canbe expansion, scale + animationType: 'expansion', + animationDuration: 1000, + animationDurationUpdate: 500, + data: [], + + /** + * Sort order. + * + * Valid values: 'desc', 'asc', null, or callback function. + * 'desc' and 'asc' for descend and ascendant order; + * null for not sorting; + * example of callback function: + * function(nodeA, nodeB) { + * return nodeA.getValue() - nodeB.getValue(); + * } + */ + sort: 'desc' + }; + return SunburstSeriesModel; + }(SeriesModel); + + function completeTreeValue$1(dataNode) { + // Postorder travel tree. + // If value of none-leaf node is not set, + // calculate it by suming up the value of all children. + var sum = 0; + each(dataNode.children, function (child) { + completeTreeValue$1(child); + var childValue = child.value; // TODO First value of array must be a number + + isArray(childValue) && (childValue = childValue[0]); + sum += childValue; + }); + var thisValue = dataNode.value; + + if (isArray(thisValue)) { + thisValue = thisValue[0]; + } + + if (thisValue == null || isNaN(thisValue)) { + thisValue = sum; + } // Value should not less than 0. + + + if (thisValue < 0) { + thisValue = 0; + } + + isArray(dataNode.value) ? dataNode.value[0] = thisValue : dataNode.value = thisValue; + } + + var RADIAN$2 = Math.PI / 180; + function sunburstLayout(seriesType, ecModel, api) { + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + var center = seriesModel.get('center'); + var radius = seriesModel.get('radius'); + + if (!isArray(radius)) { + radius = [0, radius]; + } + + if (!isArray(center)) { + center = [center, center]; + } + + var width = api.getWidth(); + var height = api.getHeight(); + var size = Math.min(width, height); + var cx = parsePercent$1(center[0], width); + var cy = parsePercent$1(center[1], height); + var r0 = parsePercent$1(radius[0], size / 2); + var r = parsePercent$1(radius[1], size / 2); + var startAngle = -seriesModel.get('startAngle') * RADIAN$2; + var minAngle = seriesModel.get('minAngle') * RADIAN$2; + var virtualRoot = seriesModel.getData().tree.root; + var treeRoot = seriesModel.getViewRoot(); + var rootDepth = treeRoot.depth; + var sort = seriesModel.get('sort'); + + if (sort != null) { + initChildren$1(treeRoot, sort); + } + + var validDataCount = 0; + each(treeRoot.children, function (child) { + !isNaN(child.getValue()) && validDataCount++; + }); + var sum = treeRoot.getValue(); // Sum may be 0 + + var unitRadian = Math.PI / (sum || validDataCount) * 2; + var renderRollupNode = treeRoot.depth > 0; + var levels = treeRoot.height - (renderRollupNode ? -1 : 1); + var rPerLevel = (r - r0) / (levels || 1); + var clockwise = seriesModel.get('clockwise'); + var stillShowZeroSum = seriesModel.get('stillShowZeroSum'); // In the case some sector angle is smaller than minAngle + // let restAngle = PI2; + // let valueSumLargerThanMinAngle = 0; + + var dir = clockwise ? 1 : -1; + /** + * Render a tree + * @return increased angle + */ + + var renderNode = function (node, startAngle) { + if (!node) { + return; + } + + var endAngle = startAngle; // Render self + + if (node !== virtualRoot) { + // Tree node is virtual, so it doesn't need to be drawn + var value = node.getValue(); + var angle = sum === 0 && stillShowZeroSum ? unitRadian : value * unitRadian; + + if (angle < minAngle) { + angle = minAngle; // restAngle -= minAngle; + } // else { + // valueSumLargerThanMinAngle += value; + // } + + + endAngle = startAngle + dir * angle; + var depth = node.depth - rootDepth - (renderRollupNode ? -1 : 1); + var rStart = r0 + rPerLevel * depth; + var rEnd = r0 + rPerLevel * (depth + 1); + var levelModel = seriesModel.getLevelModel(node); + + if (levelModel) { + var r0_1 = levelModel.get('r0', true); + var r_1 = levelModel.get('r', true); + var radius_1 = levelModel.get('radius', true); + + if (radius_1 != null) { + r0_1 = radius_1[0]; + r_1 = radius_1[1]; + } + + r0_1 != null && (rStart = parsePercent$1(r0_1, size / 2)); + r_1 != null && (rEnd = parsePercent$1(r_1, size / 2)); + } + + node.setLayout({ + angle: angle, + startAngle: startAngle, + endAngle: endAngle, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: rStart, + r: rEnd + }); + } // Render children + + + if (node.children && node.children.length) { + // currentAngle = startAngle; + var siblingAngle_1 = 0; + each(node.children, function (node) { + siblingAngle_1 += renderNode(node, startAngle + siblingAngle_1); + }); + } + + return endAngle - startAngle; + }; // Virtual root node for roll up + + + if (renderRollupNode) { + var rStart = r0; + var rEnd = r0 + rPerLevel; + var angle = Math.PI * 2; + virtualRoot.setLayout({ + angle: angle, + startAngle: startAngle, + endAngle: startAngle + angle, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: rStart, + r: rEnd + }); + } + + renderNode(treeRoot, startAngle); + }); + } + /** + * Init node children by order and update visual + */ + + function initChildren$1(node, sortOrder) { + var children = node.children || []; + node.children = sort$2(children, sortOrder); // Init children recursively + + if (children.length) { + each(node.children, function (child) { + initChildren$1(child, sortOrder); + }); + } + } + /** + * Sort children nodes + * + * @param {TreeNode[]} children children of node to be sorted + * @param {string | function | null} sort sort method + * See SunburstSeries.js for details. + */ + + + function sort$2(children, sortOrder) { + if (isFunction(sortOrder)) { + var sortTargets = map(children, function (child, idx) { + var value = child.getValue(); + return { + params: { + depth: child.depth, + height: child.height, + dataIndex: child.dataIndex, + getValue: function () { + return value; + } + }, + index: idx + }; + }); + sortTargets.sort(function (a, b) { + return sortOrder(a.params, b.params); + }); + return map(sortTargets, function (target) { + return children[target.index]; + }); + } else { + var isAsc_1 = sortOrder === 'asc'; + return children.sort(function (a, b) { + var diff = (a.getValue() - b.getValue()) * (isAsc_1 ? 1 : -1); + return diff === 0 ? (a.dataIndex - b.dataIndex) * (isAsc_1 ? -1 : 1) : diff; + }); + } + } + + function sunburstVisual(ecModel) { + var paletteScope = {}; // Default color strategy + + function pickColor(node, seriesModel, treeHeight) { + // Choose color from palette based on the first level. + var current = node; + + while (current && current.depth > 1) { + current = current.parentNode; + } + + var color = seriesModel.getColorFromPalette(current.name || current.dataIndex + '', paletteScope); + + if (node.depth > 1 && isString(color)) { + // Lighter on the deeper level. + color = lift(color, (node.depth - 1) / (treeHeight - 1) * 0.5); + } + + return color; + } + + ecModel.eachSeriesByType('sunburst', function (seriesModel) { + var data = seriesModel.getData(); + var tree = data.tree; + tree.eachNode(function (node) { + var model = node.getModel(); + var style = model.getModel('itemStyle').getItemStyle(); + + if (!style.fill) { + style.fill = pickColor(node, seriesModel, tree.root.height); + } + + var existsStyle = data.ensureUniqueItemVisual(node.dataIndex, 'style'); + extend(existsStyle, style); + }); + }); + } + + function install$q(registers) { + registers.registerChartView(SunburstView); + registers.registerSeriesModel(SunburstSeriesModel); + registers.registerLayout(curry(sunburstLayout, 'sunburst')); + registers.registerProcessor(curry(dataFilter, 'sunburst')); + registers.registerVisual(sunburstVisual); + installSunburstAction(registers); + } + + // `visual('color') visual('borderColor')` is supported. + + var STYLE_VISUAL_TYPE = { + color: 'fill', + borderColor: 'stroke' + }; + var NON_STYLE_VISUAL_PROPS = { + symbol: 1, + symbolSize: 1, + symbolKeepAspect: 1, + legendIcon: 1, + visualMeta: 1, + liftZ: 1, + decal: 1 + }; + var customInnerStore = makeInner(); + + var CustomSeriesModel = + /** @class */ + function (_super) { + __extends(CustomSeriesModel, _super); + + function CustomSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CustomSeriesModel.type; + return _this; + } + + CustomSeriesModel.prototype.optionUpdated = function () { + this.currentZLevel = this.get('zlevel', true); + this.currentZ = this.get('z', true); + }; + + CustomSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createSeriesData(null, this); + }; + + CustomSeriesModel.prototype.getDataParams = function (dataIndex, dataType, el) { + var params = _super.prototype.getDataParams.call(this, dataIndex, dataType); + + el && (params.info = customInnerStore(el).info); + return params; + }; + + CustomSeriesModel.type = 'series.custom'; + CustomSeriesModel.dependencies = ['grid', 'polar', 'geo', 'singleAxis', 'calendar']; + CustomSeriesModel.defaultOption = { + coordinateSystem: 'cartesian2d', + // zlevel: 0, + z: 2, + legendHoverLink: true, + // Custom series will not clip by default. + // Some case will use custom series to draw label + // For example https://echarts.apache.org/examples/en/editor.html?c=custom-gantt-flight + clip: false // Cartesian coordinate system + // xAxisIndex: 0, + // yAxisIndex: 0, + // Polar coordinate system + // polarIndex: 0, + // Geo coordinate system + // geoIndex: 0, + + }; + return CustomSeriesModel; + }(SeriesModel); + + function dataToCoordSize(dataSize, dataItem) { + // dataItem is necessary in log axis. + dataItem = dataItem || [0, 0]; + return map(['x', 'y'], function (dim, dimIdx) { + var axis = this.getAxis(dim); + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + return axis.type === 'category' ? axis.getBandWidth() : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize)); + }, this); + } + + function cartesianPrepareCustom(coordSys) { + var rect = coordSys.master.getRect(); + return { + coordSys: { + // The name exposed to user is always 'cartesian2d' but not 'grid'. + type: 'cartesian2d', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + api: { + coord: function (data) { + // do not provide "out" param + return coordSys.dataToPoint(data); + }, + size: bind(dataToCoordSize, coordSys) + } + }; + } + + function dataToCoordSize$1(dataSize, dataItem) { + dataItem = dataItem || [0, 0]; + return map([0, 1], function (dimIdx) { + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + var p1 = []; + var p2 = []; + p1[dimIdx] = val - halfSize; + p2[dimIdx] = val + halfSize; + p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx]; + return Math.abs(this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]); + }, this); + } + + function geoPrepareCustom(coordSys) { + var rect = coordSys.getBoundingRect(); + return { + coordSys: { + type: 'geo', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height, + zoom: coordSys.getZoom() + }, + api: { + coord: function (data) { + // do not provide "out" and noRoam param, + // Compatible with this usage: + // echarts.util.map(item.points, api.coord) + return coordSys.dataToPoint(data); + }, + size: bind(dataToCoordSize$1, coordSys) + } + }; + } + + function dataToCoordSize$2(dataSize, dataItem) { + // dataItem is necessary in log axis. + var axis = this.getAxis(); + var val = dataItem instanceof Array ? dataItem[0] : dataItem; + var halfSize = (dataSize instanceof Array ? dataSize[0] : dataSize) / 2; + return axis.type === 'category' ? axis.getBandWidth() : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize)); + } + + function singlePrepareCustom(coordSys) { + var rect = coordSys.getRect(); + return { + coordSys: { + type: 'singleAxis', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + api: { + coord: function (val) { + // do not provide "out" param + return coordSys.dataToPoint(val); + }, + size: bind(dataToCoordSize$2, coordSys) + } + }; + } + + function dataToCoordSize$3(dataSize, dataItem) { + // dataItem is necessary in log axis. + dataItem = dataItem || [0, 0]; + return map(['Radius', 'Angle'], function (dim, dimIdx) { + var getterName = 'get' + dim + 'Axis'; // TODO: TYPE Check Angle Axis + + var axis = this[getterName](); + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + var result = axis.type === 'category' ? axis.getBandWidth() : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize)); + + if (dim === 'Angle') { + result = result * Math.PI / 180; + } + + return result; + }, this); + } + + function polarPrepareCustom(coordSys) { + var radiusAxis = coordSys.getRadiusAxis(); + var angleAxis = coordSys.getAngleAxis(); + var radius = radiusAxis.getExtent(); + radius[0] > radius[1] && radius.reverse(); + return { + coordSys: { + type: 'polar', + cx: coordSys.cx, + cy: coordSys.cy, + r: radius[1], + r0: radius[0] + }, + api: { + coord: function (data) { + var radius = radiusAxis.dataToRadius(data[0]); + var angle = angleAxis.dataToAngle(data[1]); + var coord = coordSys.coordToPoint([radius, angle]); + coord.push(radius, angle * Math.PI / 180); + return coord; + }, + size: bind(dataToCoordSize$3, coordSys) + } + }; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function calendarPrepareCustom(coordSys) { + var rect = coordSys.getRect(); + var rangeInfo = coordSys.getRangeInfo(); + return { + coordSys: { + type: 'calendar', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height, + cellWidth: coordSys.getCellWidth(), + cellHeight: coordSys.getCellHeight(), + rangeInfo: { + start: rangeInfo.start, + end: rangeInfo.end, + weeks: rangeInfo.weeks, + dayCount: rangeInfo.allDay + } + }, + api: { + coord: function (data, clamp) { + return coordSys.dataToPoint(data, clamp); + } + } + }; + } + + var deprecatedLogs = {}; + /** + * Whether need to call `convertEC4CompatibleStyle`. + */ + + function isEC4CompatibleStyle(style, elType, hasOwnTextContentOption, hasOwnTextConfig) { + // Since echarts5, `RectText` is separated from its host element and style.text + // does not exist any more. The compat work brings some extra burden on performance. + // So we provide: + // `legacy: true` force make compat. + // `legacy: false`, force do not compat. + // `legacy` not set: auto detect wheter legacy. + // But in this case we do not compat (difficult to detect and rare case): + // Becuse custom series and graphic component support "merge", users may firstly + // only set `textStrokeWidth` style or secondly only set `text`. + return style && (style.legacy || style.legacy !== false && !hasOwnTextContentOption && !hasOwnTextConfig && elType !== 'tspan' // Difficult to detect whether legacy for a "text" el. + && (elType === 'text' || hasOwn(style, 'text'))); + } + /** + * `EC4CompatibleStyle` is style that might be in echarts4 format or echarts5 format. + * @param hostStyle The properties might be modified. + * @return If be text el, `textContentStyle` and `textConfig` will not be retured. + * Otherwise a `textContentStyle` and `textConfig` will be created, whose props area + * retried from the `hostStyle`. + */ + + function convertFromEC4CompatibleStyle(hostStyle, elType, isNormal) { + var srcStyle = hostStyle; + var textConfig; + var textContent; + var textContentStyle; + + if (elType === 'text') { + textContentStyle = srcStyle; + } else { + textContentStyle = {}; + hasOwn(srcStyle, 'text') && (textContentStyle.text = srcStyle.text); + hasOwn(srcStyle, 'rich') && (textContentStyle.rich = srcStyle.rich); + hasOwn(srcStyle, 'textFill') && (textContentStyle.fill = srcStyle.textFill); + hasOwn(srcStyle, 'textStroke') && (textContentStyle.stroke = srcStyle.textStroke); + hasOwn(srcStyle, 'fontFamily') && (textContentStyle.fontFamily = srcStyle.fontFamily); + hasOwn(srcStyle, 'fontSize') && (textContentStyle.fontSize = srcStyle.fontSize); + hasOwn(srcStyle, 'fontStyle') && (textContentStyle.fontStyle = srcStyle.fontStyle); + hasOwn(srcStyle, 'fontWeight') && (textContentStyle.fontWeight = srcStyle.fontWeight); + textContent = { + type: 'text', + style: textContentStyle, + // ec4 do not support rectText trigger. + // And when text postion is different in normal and emphasis + // => hover text trigger emphasis; + // => text position changed, leave mouse pointer immediately; + // That might cause state incorrect. + silent: true + }; + textConfig = {}; + var hasOwnPos = hasOwn(srcStyle, 'textPosition'); + + if (isNormal) { + textConfig.position = hasOwnPos ? srcStyle.textPosition : 'inside'; + } else { + hasOwnPos && (textConfig.position = srcStyle.textPosition); + } + + hasOwn(srcStyle, 'textPosition') && (textConfig.position = srcStyle.textPosition); + hasOwn(srcStyle, 'textOffset') && (textConfig.offset = srcStyle.textOffset); + hasOwn(srcStyle, 'textRotation') && (textConfig.rotation = srcStyle.textRotation); + hasOwn(srcStyle, 'textDistance') && (textConfig.distance = srcStyle.textDistance); + } + + convertEC4CompatibleRichItem(textContentStyle, hostStyle); + each(textContentStyle.rich, function (richItem) { + convertEC4CompatibleRichItem(richItem, richItem); + }); + return { + textConfig: textConfig, + textContent: textContent + }; + } + /** + * The result will be set to `out`. + */ + + function convertEC4CompatibleRichItem(out, richItem) { + if (!richItem) { + return; + } // (1) For simplicity, make textXXX properties (deprecated since ec5) has + // higher priority. For example, consider in ec4 `borderColor: 5, textBorderColor: 10` + // on a rect means `borderColor: 4` on the rect and `borderColor: 10` on an attached + // richText in ec5. + // (2) `out === richItem` if and only if `out` is text el or rich item. + // So we can overwite existing props in `out` since textXXX has higher priority. + + + richItem.font = richItem.textFont || richItem.font; + hasOwn(richItem, 'textStrokeWidth') && (out.lineWidth = richItem.textStrokeWidth); + hasOwn(richItem, 'textAlign') && (out.align = richItem.textAlign); + hasOwn(richItem, 'textVerticalAlign') && (out.verticalAlign = richItem.textVerticalAlign); + hasOwn(richItem, 'textLineHeight') && (out.lineHeight = richItem.textLineHeight); + hasOwn(richItem, 'textWidth') && (out.width = richItem.textWidth); + hasOwn(richItem, 'textHeight') && (out.height = richItem.textHeight); + hasOwn(richItem, 'textBackgroundColor') && (out.backgroundColor = richItem.textBackgroundColor); + hasOwn(richItem, 'textPadding') && (out.padding = richItem.textPadding); + hasOwn(richItem, 'textBorderColor') && (out.borderColor = richItem.textBorderColor); + hasOwn(richItem, 'textBorderWidth') && (out.borderWidth = richItem.textBorderWidth); + hasOwn(richItem, 'textBorderRadius') && (out.borderRadius = richItem.textBorderRadius); + hasOwn(richItem, 'textBoxShadowColor') && (out.shadowColor = richItem.textBoxShadowColor); + hasOwn(richItem, 'textBoxShadowBlur') && (out.shadowBlur = richItem.textBoxShadowBlur); + hasOwn(richItem, 'textBoxShadowOffsetX') && (out.shadowOffsetX = richItem.textBoxShadowOffsetX); + hasOwn(richItem, 'textBoxShadowOffsetY') && (out.shadowOffsetY = richItem.textBoxShadowOffsetY); + } + /** + * Convert to pure echarts4 format style. + * `itemStyle` will be modified, added with ec4 style properties from + * `textStyle` and `textConfig`. + * + * [Caveat]: For simplicity, `insideRollback` in ec4 does not compat, where + * `styleEmphasis: {textFill: 'red'}` will remove the normal auto added stroke. + */ + + + function convertToEC4StyleForCustomSerise(itemStl, txStl, txCfg) { + var out = itemStl; // See `custom.ts`, a trick to set extra `textPosition` firstly. + + out.textPosition = out.textPosition || txCfg.position || 'inside'; + txCfg.offset != null && (out.textOffset = txCfg.offset); + txCfg.rotation != null && (out.textRotation = txCfg.rotation); + txCfg.distance != null && (out.textDistance = txCfg.distance); + var isInside = out.textPosition.indexOf('inside') >= 0; + var hostFill = itemStl.fill || '#000'; + convertToEC4RichItem(out, txStl); + var textFillNotSet = out.textFill == null; + + if (isInside) { + if (textFillNotSet) { + out.textFill = txCfg.insideFill || '#fff'; + !out.textStroke && txCfg.insideStroke && (out.textStroke = txCfg.insideStroke); + !out.textStroke && (out.textStroke = hostFill); + out.textStrokeWidth == null && (out.textStrokeWidth = 2); + } + } else { + if (textFillNotSet) { + out.textFill = itemStl.fill || txCfg.outsideFill || '#000'; + } + + !out.textStroke && txCfg.outsideStroke && (out.textStroke = txCfg.outsideStroke); + } + + out.text = txStl.text; + out.rich = txStl.rich; + each(txStl.rich, function (richItem) { + convertToEC4RichItem(richItem, richItem); + }); + return out; + } + + function convertToEC4RichItem(out, richItem) { + if (!richItem) { + return; + } + + hasOwn(richItem, 'fill') && (out.textFill = richItem.fill); + hasOwn(richItem, 'stroke') && (out.textStroke = richItem.fill); + hasOwn(richItem, 'lineWidth') && (out.textStrokeWidth = richItem.lineWidth); + hasOwn(richItem, 'font') && (out.font = richItem.font); + hasOwn(richItem, 'fontStyle') && (out.fontStyle = richItem.fontStyle); + hasOwn(richItem, 'fontWeight') && (out.fontWeight = richItem.fontWeight); + hasOwn(richItem, 'fontSize') && (out.fontSize = richItem.fontSize); + hasOwn(richItem, 'fontFamily') && (out.fontFamily = richItem.fontFamily); + hasOwn(richItem, 'align') && (out.textAlign = richItem.align); + hasOwn(richItem, 'verticalAlign') && (out.textVerticalAlign = richItem.verticalAlign); + hasOwn(richItem, 'lineHeight') && (out.textLineHeight = richItem.lineHeight); + hasOwn(richItem, 'width') && (out.textWidth = richItem.width); + hasOwn(richItem, 'height') && (out.textHeight = richItem.height); + hasOwn(richItem, 'backgroundColor') && (out.textBackgroundColor = richItem.backgroundColor); + hasOwn(richItem, 'padding') && (out.textPadding = richItem.padding); + hasOwn(richItem, 'borderColor') && (out.textBorderColor = richItem.borderColor); + hasOwn(richItem, 'borderWidth') && (out.textBorderWidth = richItem.borderWidth); + hasOwn(richItem, 'borderRadius') && (out.textBorderRadius = richItem.borderRadius); + hasOwn(richItem, 'shadowColor') && (out.textBoxShadowColor = richItem.shadowColor); + hasOwn(richItem, 'shadowBlur') && (out.textBoxShadowBlur = richItem.shadowBlur); + hasOwn(richItem, 'shadowOffsetX') && (out.textBoxShadowOffsetX = richItem.shadowOffsetX); + hasOwn(richItem, 'shadowOffsetY') && (out.textBoxShadowOffsetY = richItem.shadowOffsetY); + hasOwn(richItem, 'textShadowColor') && (out.textShadowColor = richItem.textShadowColor); + hasOwn(richItem, 'textShadowBlur') && (out.textShadowBlur = richItem.textShadowBlur); + hasOwn(richItem, 'textShadowOffsetX') && (out.textShadowOffsetX = richItem.textShadowOffsetX); + hasOwn(richItem, 'textShadowOffsetY') && (out.textShadowOffsetY = richItem.textShadowOffsetY); + } + + function warnDeprecated(deprecated, insteadApproach) { + if ("development" !== 'production') { + var key = deprecated + '^_^' + insteadApproach; + + if (!deprecatedLogs[key]) { + console.warn("[ECharts] DEPRECATED: \"" + deprecated + "\" has been deprecated. " + insteadApproach); + deprecatedLogs[key] = true; + } + } + } + + var LEGACY_TRANSFORM_PROPS_MAP = { + position: ['x', 'y'], + scale: ['scaleX', 'scaleY'], + origin: ['originX', 'originY'] + }; + var LEGACY_TRANSFORM_PROPS = keys(LEGACY_TRANSFORM_PROPS_MAP); + var TRANSFORM_PROPS_MAP = reduce(TRANSFORMABLE_PROPS, function (obj, key) { + obj[key] = 1; + return obj; + }, {}); + var transformPropNamesStr = TRANSFORMABLE_PROPS.join(', '); // '' means root + + var ELEMENT_ANIMATABLE_PROPS = ['', 'style', 'shape', 'extra']; + var transitionInnerStore = makeInner(); + + function getElementAnimationConfig(animationType, el, elOption, parentModel, dataIndex) { + var animationProp = animationType + "Animation"; + var config = getAnimationConfig(animationType, parentModel, dataIndex) || {}; + var userDuring = transitionInnerStore(el).userDuring; // Only set when duration is > 0 and it's need to be animated. + + if (config.duration > 0) { + // For simplicity, if during not specified, the previous during will not work any more. + config.during = userDuring ? bind(duringCall, { + el: el, + userDuring: userDuring + }) : null; + config.setToFinal = true; + config.scope = animationType; + } + + extend(config, elOption[animationProp]); + return config; + } + + function applyUpdateTransition(el, elOption, animatableModel, opts) { + opts = opts || {}; + var dataIndex = opts.dataIndex, + isInit = opts.isInit, + clearStyle = opts.clearStyle; + var hasAnimation = animatableModel.isAnimationEnabled(); // Save the meta info for further morphing. Like apply on the sub morphing elements. + + var store = transitionInnerStore(el); + var styleOpt = elOption.style; + store.userDuring = elOption.during; + var transFromProps = {}; + var propsToSet = {}; + prepareTransformAllPropsFinal(el, elOption, propsToSet); + prepareShapeOrExtraAllPropsFinal('shape', elOption, propsToSet); + prepareShapeOrExtraAllPropsFinal('extra', elOption, propsToSet); + + if (!isInit && hasAnimation) { + prepareTransformTransitionFrom(el, elOption, transFromProps); + prepareShapeOrExtraTransitionFrom('shape', el, elOption, transFromProps); + prepareShapeOrExtraTransitionFrom('extra', el, elOption, transFromProps); + prepareStyleTransitionFrom(el, elOption, styleOpt, transFromProps); + } + + propsToSet.style = styleOpt; + applyPropsDirectly(el, propsToSet, clearStyle); + applyMiscProps(el, elOption); + + if (hasAnimation) { + if (isInit) { + var enterFromProps_1 = {}; + each(ELEMENT_ANIMATABLE_PROPS, function (propName) { + var prop = propName ? elOption[propName] : elOption; + + if (prop && prop.enterFrom) { + if (propName) { + enterFromProps_1[propName] = enterFromProps_1[propName] || {}; + } + + extend(propName ? enterFromProps_1[propName] : enterFromProps_1, prop.enterFrom); + } + }); + var config = getElementAnimationConfig('enter', el, elOption, animatableModel, dataIndex); + + if (config.duration > 0) { + el.animateFrom(enterFromProps_1, config); + } + } else { + applyPropsTransition(el, elOption, dataIndex || 0, animatableModel, transFromProps); + } + } // Store leave to be used in leave transition. + + + updateLeaveTo(el, elOption); + styleOpt ? el.dirty() : el.markRedraw(); + } + function updateLeaveTo(el, elOption) { + // Try merge to previous set leaveTo + var leaveToProps = transitionInnerStore(el).leaveToProps; + + for (var i = 0; i < ELEMENT_ANIMATABLE_PROPS.length; i++) { + var propName = ELEMENT_ANIMATABLE_PROPS[i]; + var prop = propName ? elOption[propName] : elOption; + + if (prop && prop.leaveTo) { + if (!leaveToProps) { + leaveToProps = transitionInnerStore(el).leaveToProps = {}; + } + + if (propName) { + leaveToProps[propName] = leaveToProps[propName] || {}; + } + + extend(propName ? leaveToProps[propName] : leaveToProps, prop.leaveTo); + } + } + } + function applyLeaveTransition(el, elOption, animatableModel, onRemove) { + if (el) { + var parent_1 = el.parent; + var leaveToProps = transitionInnerStore(el).leaveToProps; + + if (leaveToProps) { + // TODO TODO use leave after leaveAnimation in series is introduced + // TODO Data index? + var config = getElementAnimationConfig('update', el, elOption, animatableModel, 0); + + config.done = function () { + parent_1.remove(el); + onRemove && onRemove(); + }; + + el.animateTo(leaveToProps, config); + } else { + parent_1.remove(el); + onRemove && onRemove(); + } + } + } + function isTransitionAll(transition) { + return transition === 'all'; + } + + function applyPropsDirectly(el, // Can be null/undefined + allPropsFinal, clearStyle) { + var styleOpt = allPropsFinal.style; + + if (!el.isGroup && styleOpt) { + if (clearStyle) { + el.useStyle({}); // When style object changed, how to trade the existing animation? + // It is probably complicated and not needed to cover all the cases. + // But still need consider the case: + // (1) When using init animation on `style.opacity`, and before the animation + // ended users triggers an update by mousewhel. At that time the init + // animation should better be continued rather than terminated. + // So after `useStyle` called, we should change the animation target manually + // to continue the effect of the init animation. + // (2) PENDING: If the previous animation targeted at a `val1`, and currently we need + // to update the value to `val2` and no animation declared, should be terminate + // the previous animation or just modify the target of the animation? + // Therotically That will happen not only on `style` but also on `shape` and + // `transfrom` props. But we haven't handle this case at present yet. + // (3) PENDING: Is it proper to visit `animators` and `targetName`? + + var animators = el.animators; + + for (var i = 0; i < animators.length; i++) { + var animator = animators[i]; // targetName is the "topKey". + + if (animator.targetName === 'style') { + animator.changeTarget(el.style); + } + } + } + + el.setStyle(styleOpt); + } + + if (allPropsFinal) { + // Not set style here. + allPropsFinal.style = null; // Set el to the final state firstly. + + allPropsFinal && el.attr(allPropsFinal); + allPropsFinal.style = styleOpt; + } + } + + function applyPropsTransition(el, elOption, dataIndex, model, // Can be null/undefined + transFromProps) { + if (transFromProps) { + var config = getElementAnimationConfig('update', el, elOption, model, dataIndex); + + if (config.duration > 0) { + el.animateFrom(transFromProps, config); + } + } + } + + function applyMiscProps(el, elOption) { + // Merge by default. + hasOwn(elOption, 'silent') && (el.silent = elOption.silent); + hasOwn(elOption, 'ignore') && (el.ignore = elOption.ignore); + + if (el instanceof Displayable) { + hasOwn(elOption, 'invisible') && (el.invisible = elOption.invisible); + } + + if (el instanceof Path) { + hasOwn(elOption, 'autoBatch') && (el.autoBatch = elOption.autoBatch); + } + } // Use it to avoid it be exposed to user. + + + var tmpDuringScope = {}; + var transitionDuringAPI = { + // Usually other props do not need to be changed in animation during. + setTransform: function (key, val) { + if ("development" !== 'production') { + assert(hasOwn(TRANSFORM_PROPS_MAP, key), 'Only ' + transformPropNamesStr + ' available in `setTransform`.'); + } + + tmpDuringScope.el[key] = val; + return this; + }, + getTransform: function (key) { + if ("development" !== 'production') { + assert(hasOwn(TRANSFORM_PROPS_MAP, key), 'Only ' + transformPropNamesStr + ' available in `getTransform`.'); + } + + return tmpDuringScope.el[key]; + }, + setShape: function (key, val) { + if ("development" !== 'production') { + assertNotReserved(key); + } + + var el = tmpDuringScope.el; + var shape = el.shape || (el.shape = {}); + shape[key] = val; + el.dirtyShape && el.dirtyShape(); + return this; + }, + getShape: function (key) { + if ("development" !== 'production') { + assertNotReserved(key); + } + + var shape = tmpDuringScope.el.shape; + + if (shape) { + return shape[key]; + } + }, + setStyle: function (key, val) { + if ("development" !== 'production') { + assertNotReserved(key); + } + + var el = tmpDuringScope.el; + var style = el.style; + + if (style) { + if ("development" !== 'production') { + if (eqNaN(val)) { + warn('style.' + key + ' must not be assigned with NaN.'); + } + } + + style[key] = val; + el.dirtyStyle && el.dirtyStyle(); + } + + return this; + }, + getStyle: function (key) { + if ("development" !== 'production') { + assertNotReserved(key); + } + + var style = tmpDuringScope.el.style; + + if (style) { + return style[key]; + } + }, + setExtra: function (key, val) { + if ("development" !== 'production') { + assertNotReserved(key); + } + + var extra = tmpDuringScope.el.extra || (tmpDuringScope.el.extra = {}); + extra[key] = val; + return this; + }, + getExtra: function (key) { + if ("development" !== 'production') { + assertNotReserved(key); + } + + var extra = tmpDuringScope.el.extra; + + if (extra) { + return extra[key]; + } + } + }; + + function assertNotReserved(key) { + if ("development" !== 'production') { + if (key === 'transition' || key === 'enterFrom' || key === 'leaveTo') { + throw new Error('key must not be "' + key + '"'); + } + } + } + + function duringCall() { + // Do not provide "percent" until some requirements come. + // Because consider thies case: + // enterFrom: {x: 100, y: 30}, transition: 'x'. + // And enter duration is different from update duration. + // Thus it might be confused about the meaning of "percent" in during callback. + var scope = this; + var el = scope.el; + + if (!el) { + return; + } // If el is remove from zr by reason like legend, during still need to called, + // becuase el will be added back to zr and the prop value should not be incorrect. + + + var latestUserDuring = transitionInnerStore(el).userDuring; + var scopeUserDuring = scope.userDuring; // Ensured a during is only called once in each animation frame. + // If a during is called multiple times in one frame, maybe some users' calulation logic + // might be wrong (not sure whether this usage exists). + // The case of a during might be called twice can be: by default there is a animator for + // 'x', 'y' when init. Before the init animation finished, call `setOption` to start + // another animators for 'style'/'shape'/'extra'. + + if (latestUserDuring !== scopeUserDuring) { + // release + scope.el = scope.userDuring = null; + return; + } + + tmpDuringScope.el = el; // Give no `this` to user in "during" calling. + + scopeUserDuring(transitionDuringAPI); // FIXME: if in future meet the case that some prop will be both modified in `during` and `state`, + // consider the issue that the prop might be incorrect when return to "normal" state. + } + + function prepareShapeOrExtraTransitionFrom(mainAttr, fromEl, elOption, transFromProps) { + var attrOpt = elOption[mainAttr]; + + if (!attrOpt) { + return; + } + + var elPropsInAttr = fromEl[mainAttr]; + var transFromPropsInAttr; + + if (elPropsInAttr) { + var transition = elOption.transition; + var attrTransition = attrOpt.transition; + + if (attrTransition) { + !transFromPropsInAttr && (transFromPropsInAttr = transFromProps[mainAttr] = {}); + + if (isTransitionAll(attrTransition)) { + extend(transFromPropsInAttr, elPropsInAttr); + } else { + var transitionKeys = normalizeToArray(attrTransition); + + for (var i = 0; i < transitionKeys.length; i++) { + var key = transitionKeys[i]; + var elVal = elPropsInAttr[key]; + transFromPropsInAttr[key] = elVal; + } + } + } else if (isTransitionAll(transition) || indexOf(transition, mainAttr) >= 0) { + !transFromPropsInAttr && (transFromPropsInAttr = transFromProps[mainAttr] = {}); + var elPropsInAttrKeys = keys(elPropsInAttr); + + for (var i = 0; i < elPropsInAttrKeys.length; i++) { + var key = elPropsInAttrKeys[i]; + var elVal = elPropsInAttr[key]; + + if (isNonStyleTransitionEnabled(attrOpt[key], elVal)) { + transFromPropsInAttr[key] = elVal; + } + } + } + } + } + + function prepareShapeOrExtraAllPropsFinal(mainAttr, elOption, allProps) { + var attrOpt = elOption[mainAttr]; + + if (!attrOpt) { + return; + } + + var allPropsInAttr = allProps[mainAttr] = {}; + var keysInAttr = keys(attrOpt); + + for (var i = 0; i < keysInAttr.length; i++) { + var key = keysInAttr[i]; // To avoid share one object with different element, and + // to avoid user modify the object inexpectedly, have to clone. + + allPropsInAttr[key] = cloneValue(attrOpt[key]); + } + } + + function prepareTransformTransitionFrom(el, elOption, transFromProps) { + var transition = elOption.transition; + var transitionKeys = isTransitionAll(transition) ? TRANSFORMABLE_PROPS : normalizeToArray(transition || []); + + for (var i = 0; i < transitionKeys.length; i++) { + var key = transitionKeys[i]; + + if (key === 'style' || key === 'shape' || key === 'extra') { + continue; + } + + var elVal = el[key]; + + if ("development" !== 'production') { + checkTransformPropRefer(key, 'el.transition'); + } // Do not clone, animator will perform that clone. + + + transFromProps[key] = elVal; + } + } + + function prepareTransformAllPropsFinal(el, elOption, allProps) { + for (var i = 0; i < LEGACY_TRANSFORM_PROPS.length; i++) { + var legacyName = LEGACY_TRANSFORM_PROPS[i]; + var xyName = LEGACY_TRANSFORM_PROPS_MAP[legacyName]; + var legacyArr = elOption[legacyName]; + + if (legacyArr) { + allProps[xyName[0]] = legacyArr[0]; + allProps[xyName[1]] = legacyArr[1]; + } + } + + for (var i = 0; i < TRANSFORMABLE_PROPS.length; i++) { + var key = TRANSFORMABLE_PROPS[i]; + + if (elOption[key] != null) { + allProps[key] = elOption[key]; + } + } + } + + function prepareStyleTransitionFrom(fromEl, elOption, styleOpt, transFromProps) { + if (!styleOpt) { + return; + } + + var fromElStyle = fromEl.style; + var transFromStyleProps; + + if (fromElStyle) { + var styleTransition = styleOpt.transition; + var elTransition = elOption.transition; + + if (styleTransition && !isTransitionAll(styleTransition)) { + var transitionKeys = normalizeToArray(styleTransition); + !transFromStyleProps && (transFromStyleProps = transFromProps.style = {}); + + for (var i = 0; i < transitionKeys.length; i++) { + var key = transitionKeys[i]; + var elVal = fromElStyle[key]; // Do not clone, see `checkNonStyleTansitionRefer`. + + transFromStyleProps[key] = elVal; + } + } else if (fromEl.getAnimationStyleProps && (isTransitionAll(elTransition) || isTransitionAll(styleTransition) || indexOf(elTransition, 'style') >= 0)) { + var animationProps = fromEl.getAnimationStyleProps(); + var animationStyleProps = animationProps ? animationProps.style : null; + + if (animationStyleProps) { + !transFromStyleProps && (transFromStyleProps = transFromProps.style = {}); + var styleKeys = keys(styleOpt); + + for (var i = 0; i < styleKeys.length; i++) { + var key = styleKeys[i]; + + if (animationStyleProps[key]) { + var elVal = fromElStyle[key]; + transFromStyleProps[key] = elVal; + } + } + } + } + } + } + + function isNonStyleTransitionEnabled(optVal, elVal) { + // The same as `checkNonStyleTansitionRefer`. + return !isArrayLike(optVal) ? optVal != null && isFinite(optVal) : optVal !== elVal; + } + + var checkTransformPropRefer; + + if ("development" !== 'production') { + checkTransformPropRefer = function (key, usedIn) { + if (!hasOwn(TRANSFORM_PROPS_MAP, key)) { + warn('Prop `' + key + '` is not a permitted in `' + usedIn + '`. ' + 'Only `' + keys(TRANSFORM_PROPS_MAP).join('`, `') + '` are permitted.'); + } + }; + } + + var getStateToRestore = makeInner(); + var KEYFRAME_EXCLUDE_KEYS = ['percent', 'easing', 'shape', 'style', 'extra']; + /** + * Stop previous keyframe animation and restore the attributes. + * Avoid new keyframe animation starts with wrong internal state when the percent: 0 is not set. + */ + + function stopPreviousKeyframeAnimationAndRestore(el) { + // Stop previous keyframe animation. + el.stopAnimation('keyframe'); // Restore + + el.attr(getStateToRestore(el)); + } + function applyKeyframeAnimation(el, animationOpts, animatableModel) { + if (!animatableModel.isAnimationEnabled() || !animationOpts) { + return; + } + + if (isArray(animationOpts)) { + each(animationOpts, function (singleAnimationOpts) { + applyKeyframeAnimation(el, singleAnimationOpts, animatableModel); + }); + return; + } + + var keyframes = animationOpts.keyframes; + var duration = animationOpts.duration; + + if (animatableModel && duration == null) { + // Default to use duration of config. + // NOTE: animation config from payload will be ignored because they are mainly for transitions. + var config = getAnimationConfig('enter', animatableModel, 0); + duration = config && config.duration; + } + + if (!keyframes || !duration) { + return; + } + + var stateToRestore = getStateToRestore(el); + each(ELEMENT_ANIMATABLE_PROPS, function (targetPropName) { + if (targetPropName && !el[targetPropName]) { + return; + } + + var animator; + var endFrameIsSet = false; // Sort keyframes by percent. + + keyframes.sort(function (a, b) { + return a.percent - b.percent; + }); + each(keyframes, function (kf) { + // Stop current animation. + var animators = el.animators; + var kfValues = targetPropName ? kf[targetPropName] : kf; + + if ("development" !== 'production') { + if (kf.percent >= 1) { + endFrameIsSet = true; + } + } + + if (!kfValues) { + return; + } + + var propKeys = keys(kfValues); + + if (!targetPropName) { + // PENDING performance? + propKeys = filter(propKeys, function (key) { + return indexOf(KEYFRAME_EXCLUDE_KEYS, key) < 0; + }); + } + + if (!propKeys.length) { + return; + } + + if (!animator) { + animator = el.animate(targetPropName, animationOpts.loop, true); + animator.scope = 'keyframe'; + } + + for (var i = 0; i < animators.length; i++) { + // Stop all other animation that is not keyframe. + if (animators[i] !== animator && animators[i].targetName === animator.targetName) { + animators[i].stopTracks(propKeys); + } + } + + targetPropName && (stateToRestore[targetPropName] = stateToRestore[targetPropName] || {}); + var savedTarget = targetPropName ? stateToRestore[targetPropName] : stateToRestore; + each(propKeys, function (key) { + // Save original value. + savedTarget[key] = ((targetPropName ? el[targetPropName] : el) || {})[key]; + }); + animator.whenWithKeys(duration * kf.percent, kfValues, propKeys, kf.easing); + }); + + if (!animator) { + return; + } + + if ("development" !== 'production') { + if (!endFrameIsSet) { + warn('End frame with percent: 1 is missing in the keyframeAnimation.', true); + } + } + + animator.delay(animationOpts.delay || 0).duration(duration).start(animationOpts.easing); + }); + } + + var EMPHASIS = 'emphasis'; + var NORMAL = 'normal'; + var BLUR = 'blur'; + var SELECT = 'select'; + var STATES = [NORMAL, EMPHASIS, BLUR, SELECT]; + var PATH_ITEM_STYLE = { + normal: ['itemStyle'], + emphasis: [EMPHASIS, 'itemStyle'], + blur: [BLUR, 'itemStyle'], + select: [SELECT, 'itemStyle'] + }; + var PATH_LABEL = { + normal: ['label'], + emphasis: [EMPHASIS, 'label'], + blur: [BLUR, 'label'], + select: [SELECT, 'label'] + }; + var DEFAULT_TRANSITION = ['x', 'y']; // Use prefix to avoid index to be the same as el.name, + // which will cause weird update animation. + + var GROUP_DIFF_PREFIX = 'e\0\0'; + var attachedTxInfoTmp = { + normal: {}, + emphasis: {}, + blur: {}, + select: {} + }; + /** + * To reduce total package size of each coordinate systems, the modules `prepareCustom` + * of each coordinate systems are not required by each coordinate systems directly, but + * required by the module `custom`. + * + * prepareInfoForCustomSeries {Function}: optional + * @return {Object} {coordSys: {...}, api: { + * coord: function (data, clamp) {}, // return point in global. + * size: function (dataSize, dataItem) {} // return size of each axis in coordSys. + * }} + */ + + var prepareCustoms = { + cartesian2d: cartesianPrepareCustom, + geo: geoPrepareCustom, + singleAxis: singlePrepareCustom, + polar: polarPrepareCustom, + calendar: calendarPrepareCustom + }; + + function isPath$1(el) { + return el instanceof Path; + } + + function isDisplayable(el) { + return el instanceof Displayable; + } + + function copyElement(sourceEl, targetEl) { + targetEl.copyTransform(sourceEl); + + if (isDisplayable(targetEl) && isDisplayable(sourceEl)) { + targetEl.setStyle(sourceEl.style); + targetEl.z = sourceEl.z; + targetEl.z2 = sourceEl.z2; + targetEl.zlevel = sourceEl.zlevel; + targetEl.invisible = sourceEl.invisible; + targetEl.ignore = sourceEl.ignore; + + if (isPath$1(targetEl) && isPath$1(sourceEl)) { + targetEl.setShape(sourceEl.shape); + } + } + } + + var CustomChartView = + /** @class */ + function (_super) { + __extends(CustomChartView, _super); + + function CustomChartView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CustomChartView.type; + return _this; + } + + CustomChartView.prototype.render = function (customSeries, ecModel, api, payload) { + // Clear previously rendered progressive elements. + this._progressiveEls = null; + var oldData = this._data; + var data = customSeries.getData(); + var group = this.group; + var renderItem = makeRenderItem(customSeries, data, ecModel, api); + + if (!oldData) { + // Previous render is incremental render or first render. + // Needs remove the incremental rendered elements. + group.removeAll(); + } + + data.diff(oldData).add(function (newIdx) { + createOrUpdateItem(api, null, newIdx, renderItem(newIdx, payload), customSeries, group, data); + }).remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + applyLeaveTransition(el, customInnerStore(el).option, customSeries); + }).update(function (newIdx, oldIdx) { + var oldEl = oldData.getItemGraphicEl(oldIdx); + createOrUpdateItem(api, oldEl, newIdx, renderItem(newIdx, payload), customSeries, group, data); + }).execute(); // Do clipping + + var clipPath = customSeries.get('clip', true) ? createClipPath(customSeries.coordinateSystem, false, customSeries) : null; + + if (clipPath) { + group.setClipPath(clipPath); + } else { + group.removeClipPath(); + } + + this._data = data; + }; + + CustomChartView.prototype.incrementalPrepareRender = function (customSeries, ecModel, api) { + this.group.removeAll(); + this._data = null; + }; + + CustomChartView.prototype.incrementalRender = function (params, customSeries, ecModel, api, payload) { + var data = customSeries.getData(); + var renderItem = makeRenderItem(customSeries, data, ecModel, api); + var progressiveEls = this._progressiveEls = []; + + function setIncrementalAndHoverLayer(el) { + if (!el.isGroup) { + el.incremental = true; + el.ensureState('emphasis').hoverLayer = true; + } + } + + for (var idx = params.start; idx < params.end; idx++) { + var el = createOrUpdateItem(null, null, idx, renderItem(idx, payload), customSeries, this.group, data); + + if (el) { + el.traverse(setIncrementalAndHoverLayer); + progressiveEls.push(el); + } + } + }; + + CustomChartView.prototype.eachRendered = function (cb) { + traverseElements(this._progressiveEls || this.group, cb); + }; + + CustomChartView.prototype.filterForExposedEvent = function (eventType, query, targetEl, packedEvent) { + var elementName = query.element; + + if (elementName == null || targetEl.name === elementName) { + return true; + } // Enable to give a name on a group made by `renderItem`, and listen + // events that triggerd by its descendents. + + + while ((targetEl = targetEl.__hostTarget || targetEl.parent) && targetEl !== this.group) { + if (targetEl.name === elementName) { + return true; + } + } + + return false; + }; + + CustomChartView.type = 'custom'; + return CustomChartView; + }(ChartView); + + function createEl(elOption) { + var graphicType = elOption.type; + var el; // Those graphic elements are not shapes. They should not be + // overwritten by users, so do them first. + + if (graphicType === 'path') { + var shape = elOption.shape; // Using pathRect brings convenience to users sacle svg path. + + var pathRect = shape.width != null && shape.height != null ? { + x: shape.x || 0, + y: shape.y || 0, + width: shape.width, + height: shape.height + } : null; + var pathData = getPathData(shape); // Path is also used for icon, so layout 'center' by default. + + el = makePath(pathData, null, pathRect, shape.layout || 'center'); + customInnerStore(el).customPathData = pathData; + } else if (graphicType === 'image') { + el = new ZRImage({}); + customInnerStore(el).customImagePath = elOption.style.image; + } else if (graphicType === 'text') { + el = new ZRText({}); // customInnerStore(el).customText = (elOption.style as TextStyleProps).text; + } else if (graphicType === 'group') { + el = new Group(); + } else if (graphicType === 'compoundPath') { + throw new Error('"compoundPath" is not supported yet.'); + } else { + var Clz = getShapeClass(graphicType); + + if (!Clz) { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = 'graphic type "' + graphicType + '" can not be found.'; + } + + throwError(errMsg); + } + + el = new Clz(); + } + + customInnerStore(el).customGraphicType = graphicType; + el.name = elOption.name; // Compat ec4: the default z2 lift is 1. If changing the number, + // some cases probably be broken: hierarchy layout along z, like circle packing, + // where emphasis only intending to modify color/border rather than lift z2. + + el.z2EmphasisLift = 1; + el.z2SelectLift = 1; + return el; + } + + function updateElNormal( // Can be null/undefined + api, el, dataIndex, elOption, attachedTxInfo, seriesModel, isInit) { + // Stop and restore before update any other attributes. + stopPreviousKeyframeAnimationAndRestore(el); + var txCfgOpt = attachedTxInfo && attachedTxInfo.normal.cfg; + + if (txCfgOpt) { + // PENDING: whether use user object directly rather than clone? + // TODO:5.0 textConfig transition animation? + el.setTextConfig(txCfgOpt); + } // Default transition ['x', 'y'] + + + if (elOption && elOption.transition == null) { + elOption.transition = DEFAULT_TRANSITION; + } // Do some normalization on style. + + + var styleOpt = elOption && elOption.style; + + if (styleOpt) { + if (el.type === 'text') { + var textOptionStyle = styleOpt; // Compatible with ec4: if `textFill` or `textStroke` exists use them. + + hasOwn(textOptionStyle, 'textFill') && (textOptionStyle.fill = textOptionStyle.textFill); + hasOwn(textOptionStyle, 'textStroke') && (textOptionStyle.stroke = textOptionStyle.textStroke); + } + + var decalPattern = void 0; + var decalObj = isPath$1(el) ? styleOpt.decal : null; + + if (api && decalObj) { + decalObj.dirty = true; + decalPattern = createOrUpdatePatternFromDecal(decalObj, api); + } // Always overwrite in case user specify this prop. + + + styleOpt.__decalPattern = decalPattern; + } + + if (isDisplayable(el)) { + if (styleOpt) { + var decalPattern = styleOpt.__decalPattern; + + if (decalPattern) { + styleOpt.decal = decalPattern; + } + } + } + + applyUpdateTransition(el, elOption, seriesModel, { + dataIndex: dataIndex, + isInit: isInit, + clearStyle: true + }); + applyKeyframeAnimation(el, elOption.keyframeAnimation, seriesModel); + } + + function updateElOnState(state, el, elStateOpt, styleOpt, attachedTxInfo) { + var elDisplayable = el.isGroup ? null : el; + var txCfgOpt = attachedTxInfo && attachedTxInfo[state].cfg; // PENDING:5.0 support customize scale change and transition animation? + + if (elDisplayable) { + // By default support auto lift color when hover whether `emphasis` specified. + var stateObj = elDisplayable.ensureState(state); + + if (styleOpt === false) { + var existingEmphasisState = elDisplayable.getState(state); + + if (existingEmphasisState) { + existingEmphasisState.style = null; + } + } else { + // style is needed to enable defaut emphasis. + stateObj.style = styleOpt || null; + } // If `elOption.styleEmphasis` or `elOption.emphasis.style` is `false`, + // remove hover style. + // If `elOption.textConfig` or `elOption.emphasis.textConfig` is null/undefined, it does not + // make sense. So for simplicity, we do not ditinguish `hasOwnProperty` and null/undefined. + + + if (txCfgOpt) { + stateObj.textConfig = txCfgOpt; + } + + setDefaultStateProxy(elDisplayable); + } + } + + function updateZ$1(el, elOption, seriesModel) { + // Group not support textContent and not support z yet. + if (el.isGroup) { + return; + } + + var elDisplayable = el; + var currentZ = seriesModel.currentZ; + var currentZLevel = seriesModel.currentZLevel; // Always erase. + + elDisplayable.z = currentZ; + elDisplayable.zlevel = currentZLevel; // z2 must not be null/undefined, otherwise sort error may occur. + + var optZ2 = elOption.z2; + optZ2 != null && (elDisplayable.z2 = optZ2 || 0); + + for (var i = 0; i < STATES.length; i++) { + updateZForEachState(elDisplayable, elOption, STATES[i]); + } + } + + function updateZForEachState(elDisplayable, elOption, state) { + var isNormal = state === NORMAL; + var elStateOpt = isNormal ? elOption : retrieveStateOption(elOption, state); + var optZ2 = elStateOpt ? elStateOpt.z2 : null; + var stateObj; + + if (optZ2 != null) { + // Do not `ensureState` until required. + stateObj = isNormal ? elDisplayable : elDisplayable.ensureState(state); + stateObj.z2 = optZ2 || 0; + } + } + + function makeRenderItem(customSeries, data, ecModel, api) { + var renderItem = customSeries.get('renderItem'); + var coordSys = customSeries.coordinateSystem; + var prepareResult = {}; + + if (coordSys) { + if ("development" !== 'production') { + assert(renderItem, 'series.render is required.'); + assert(coordSys.prepareCustoms || prepareCustoms[coordSys.type], 'This coordSys does not support custom series.'); + } // `coordSys.prepareCustoms` is used for external coord sys like bmap. + + + prepareResult = coordSys.prepareCustoms ? coordSys.prepareCustoms(coordSys) : prepareCustoms[coordSys.type](coordSys); + } + + var userAPI = defaults({ + getWidth: api.getWidth, + getHeight: api.getHeight, + getZr: api.getZr, + getDevicePixelRatio: api.getDevicePixelRatio, + value: value, + style: style, + ordinalRawValue: ordinalRawValue, + styleEmphasis: styleEmphasis, + visual: visual, + barLayout: barLayout, + currentSeriesIndices: currentSeriesIndices, + font: font + }, prepareResult.api || {}); + var userParams = { + // The life cycle of context: current round of rendering. + // The global life cycle is probably not necessary, because + // user can store global status by themselves. + context: {}, + seriesId: customSeries.id, + seriesName: customSeries.name, + seriesIndex: customSeries.seriesIndex, + coordSys: prepareResult.coordSys, + dataInsideLength: data.count(), + encode: wrapEncodeDef(customSeries.getData()) + }; // If someday intending to refactor them to a class, should consider do not + // break change: currently these attribute member are encapsulated in a closure + // so that do not need to force user to call these method with a scope. + // Do not support call `api` asynchronously without dataIndexInside input. + + var currDataIndexInside; + var currItemModel; + var currItemStyleModels = {}; + var currLabelModels = {}; + var seriesItemStyleModels = {}; + var seriesLabelModels = {}; + + for (var i = 0; i < STATES.length; i++) { + var stateName = STATES[i]; + seriesItemStyleModels[stateName] = customSeries.getModel(PATH_ITEM_STYLE[stateName]); + seriesLabelModels[stateName] = customSeries.getModel(PATH_LABEL[stateName]); + } + + function getItemModel(dataIndexInside) { + return dataIndexInside === currDataIndexInside ? currItemModel || (currItemModel = data.getItemModel(dataIndexInside)) : data.getItemModel(dataIndexInside); + } + + function getItemStyleModel(dataIndexInside, state) { + return !data.hasItemOption ? seriesItemStyleModels[state] : dataIndexInside === currDataIndexInside ? currItemStyleModels[state] || (currItemStyleModels[state] = getItemModel(dataIndexInside).getModel(PATH_ITEM_STYLE[state])) : getItemModel(dataIndexInside).getModel(PATH_ITEM_STYLE[state]); + } + + function getLabelModel(dataIndexInside, state) { + return !data.hasItemOption ? seriesLabelModels[state] : dataIndexInside === currDataIndexInside ? currLabelModels[state] || (currLabelModels[state] = getItemModel(dataIndexInside).getModel(PATH_LABEL[state])) : getItemModel(dataIndexInside).getModel(PATH_LABEL[state]); + } + + return function (dataIndexInside, payload) { + currDataIndexInside = dataIndexInside; + currItemModel = null; + currItemStyleModels = {}; + currLabelModels = {}; + return renderItem && renderItem(defaults({ + dataIndexInside: dataIndexInside, + dataIndex: data.getRawIndex(dataIndexInside), + // Can be used for optimization when zoom or roam. + actionType: payload ? payload.type : null + }, userParams), userAPI); + }; + /** + * @public + * @param dim by default 0. + * @param dataIndexInside by default `currDataIndexInside`. + */ + + function value(dim, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + return data.getStore().get(data.getDimensionIndex(dim || 0), dataIndexInside); + } + /** + * @public + * @param dim by default 0. + * @param dataIndexInside by default `currDataIndexInside`. + */ + + + function ordinalRawValue(dim, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + dim = dim || 0; + var dimInfo = data.getDimensionInfo(dim); + + if (!dimInfo) { + var dimIndex = data.getDimensionIndex(dim); + return dimIndex >= 0 ? data.getStore().get(dimIndex, dataIndexInside) : undefined; + } + + var val = data.get(dimInfo.name, dataIndexInside); + var ordinalMeta = dimInfo && dimInfo.ordinalMeta; + return ordinalMeta ? ordinalMeta.categories[val] : val; + } + /** + * @deprecated The orgininal intention of `api.style` is enable to set itemStyle + * like other series. But it not necessary and not easy to give a strict definition + * of what it return. And since echarts5 it needs to be make compat work. So + * deprecates it since echarts5. + * + * By default, `visual` is applied to style (to support visualMap). + * `visual.color` is applied at `fill`. If user want apply visual.color on `stroke`, + * it can be implemented as: + * `api.style({stroke: api.visual('color'), fill: null})`; + * + * [Compat]: since ec5, RectText has been separated from its hosts el. + * so `api.style()` will only return the style from `itemStyle` but not handle `label` + * any more. But `series.label` config is never published in doc. + * We still compat it in `api.style()`. But not encourage to use it and will still not + * to pulish it to doc. + * @public + * @param dataIndexInside by default `currDataIndexInside`. + */ + + + function style(userProps, dataIndexInside) { + if ("development" !== 'production') { + warnDeprecated('api.style', 'Please write literal style directly instead.'); + } + + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + var style = data.getItemVisual(dataIndexInside, 'style'); + var visualColor = style && style.fill; + var opacity = style && style.opacity; + var itemStyle = getItemStyleModel(dataIndexInside, NORMAL).getItemStyle(); + visualColor != null && (itemStyle.fill = visualColor); + opacity != null && (itemStyle.opacity = opacity); + var opt = { + inheritColor: isString(visualColor) ? visualColor : '#000' + }; + var labelModel = getLabelModel(dataIndexInside, NORMAL); // Now that the feture of "auto adjust text fill/stroke" has been migrated to zrender + // since ec5, we should set `isAttached` as `false` here and make compat in + // `convertToEC4StyleForCustomSerise`. + + var textStyle = createTextStyle(labelModel, null, opt, false, true); + textStyle.text = labelModel.getShallow('show') ? retrieve2(customSeries.getFormattedLabel(dataIndexInside, NORMAL), getDefaultLabel(data, dataIndexInside)) : null; + var textConfig = createTextConfig(labelModel, opt, false); + preFetchFromExtra(userProps, itemStyle); + itemStyle = convertToEC4StyleForCustomSerise(itemStyle, textStyle, textConfig); + userProps && applyUserPropsAfter(itemStyle, userProps); + itemStyle.legacy = true; + return itemStyle; + } + /** + * @deprecated The reason see `api.style()` + * @public + * @param dataIndexInside by default `currDataIndexInside`. + */ + + + function styleEmphasis(userProps, dataIndexInside) { + if ("development" !== 'production') { + warnDeprecated('api.styleEmphasis', 'Please write literal style directly instead.'); + } + + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + var itemStyle = getItemStyleModel(dataIndexInside, EMPHASIS).getItemStyle(); + var labelModel = getLabelModel(dataIndexInside, EMPHASIS); + var textStyle = createTextStyle(labelModel, null, null, true, true); + textStyle.text = labelModel.getShallow('show') ? retrieve3(customSeries.getFormattedLabel(dataIndexInside, EMPHASIS), customSeries.getFormattedLabel(dataIndexInside, NORMAL), getDefaultLabel(data, dataIndexInside)) : null; + var textConfig = createTextConfig(labelModel, null, true); + preFetchFromExtra(userProps, itemStyle); + itemStyle = convertToEC4StyleForCustomSerise(itemStyle, textStyle, textConfig); + userProps && applyUserPropsAfter(itemStyle, userProps); + itemStyle.legacy = true; + return itemStyle; + } + + function applyUserPropsAfter(itemStyle, extra) { + for (var key in extra) { + if (hasOwn(extra, key)) { + itemStyle[key] = extra[key]; + } + } + } + + function preFetchFromExtra(extra, itemStyle) { + // A trick to retrieve those props firstly, which are used to + // apply auto inside fill/stroke in `convertToEC4StyleForCustomSerise`. + // (It's not reasonable but only for a degree of compat) + if (extra) { + extra.textFill && (itemStyle.textFill = extra.textFill); + extra.textPosition && (itemStyle.textPosition = extra.textPosition); + } + } + /** + * @public + * @param dataIndexInside by default `currDataIndexInside`. + */ + + + function visual(visualType, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + + if (hasOwn(STYLE_VISUAL_TYPE, visualType)) { + var style_1 = data.getItemVisual(dataIndexInside, 'style'); + return style_1 ? style_1[STYLE_VISUAL_TYPE[visualType]] : null; + } // Only support these visuals. Other visual might be inner tricky + // for performance (like `style`), do not expose to users. + + + if (hasOwn(NON_STYLE_VISUAL_PROPS, visualType)) { + return data.getItemVisual(dataIndexInside, visualType); + } + } + /** + * @public + * @return If not support, return undefined. + */ + + + function barLayout(opt) { + if (coordSys.type === 'cartesian2d') { + var baseAxis = coordSys.getBaseAxis(); + return getLayoutOnAxis(defaults({ + axis: baseAxis + }, opt)); + } + } + /** + * @public + */ + + + function currentSeriesIndices() { + return ecModel.getCurrentSeriesIndices(); + } + /** + * @public + * @return font string + */ + + + function font(opt) { + return getFont(opt, ecModel); + } + } + + function wrapEncodeDef(data) { + var encodeDef = {}; + each(data.dimensions, function (dimName) { + var dimInfo = data.getDimensionInfo(dimName); + + if (!dimInfo.isExtraCoord) { + var coordDim = dimInfo.coordDim; + var dataDims = encodeDef[coordDim] = encodeDef[coordDim] || []; + dataDims[dimInfo.coordDimIndex] = data.getDimensionIndex(dimName); + } + }); + return encodeDef; + } + + function createOrUpdateItem(api, existsEl, dataIndex, elOption, seriesModel, group, data) { + // [Rule] + // If `renderItem` returns `null`/`undefined`/`false`, remove the previous el if existing. + // (It seems that violate the "merge" principle, but most of users probably intuitively + // regard "return;" as "show nothing element whatever", so make a exception to meet the + // most cases.) + // The rule or "merge" see [STRATEGY_MERGE]. + // If `elOption` is `null`/`undefined`/`false` (when `renderItem` returns nothing). + if (!elOption) { + group.remove(existsEl); + return; + } + + var el = doCreateOrUpdateEl(api, existsEl, dataIndex, elOption, seriesModel, group); + el && data.setItemGraphicEl(dataIndex, el); + el && toggleHoverEmphasis(el, elOption.focus, elOption.blurScope, elOption.emphasisDisabled); + return el; + } + + function doCreateOrUpdateEl(api, existsEl, dataIndex, elOption, seriesModel, group) { + if ("development" !== 'production') { + assert(elOption, 'should not have an null/undefined element setting'); + } + + var toBeReplacedIdx = -1; + var oldEl = existsEl; + + if (existsEl && doesElNeedRecreate(existsEl, elOption, seriesModel) // || ( + // // PENDING: even in one-to-one mapping case, if el is marked as morph, + // // do not sure whether the el will be mapped to another el with different + // // hierarchy in Group tree. So always recreate el rather than reuse the el. + // morphHelper && morphHelper.isOneToOneFrom(el) + // ) + ) { + // Should keep at the original index, otherwise "merge by index" will be incorrect. + toBeReplacedIdx = indexOf(group.childrenRef(), existsEl); + existsEl = null; + } + + var isInit = !existsEl; + var el = existsEl; + + if (!el) { + el = createEl(elOption); + + if (oldEl) { + copyElement(oldEl, el); + } + } else { + // FIMXE:NEXT unified clearState? + // If in some case the performance issue arised, consider + // do not clearState but update cached normal state directly. + el.clearStates(); + } // Need to set morph: false explictly to disable automatically morphing. + + + if (elOption.morph === false) { + el.disableMorphing = true; + } else if (el.disableMorphing) { + el.disableMorphing = false; + } + + attachedTxInfoTmp.normal.cfg = attachedTxInfoTmp.normal.conOpt = attachedTxInfoTmp.emphasis.cfg = attachedTxInfoTmp.emphasis.conOpt = attachedTxInfoTmp.blur.cfg = attachedTxInfoTmp.blur.conOpt = attachedTxInfoTmp.select.cfg = attachedTxInfoTmp.select.conOpt = null; + attachedTxInfoTmp.isLegacy = false; + doCreateOrUpdateAttachedTx(el, dataIndex, elOption, seriesModel, isInit, attachedTxInfoTmp); + doCreateOrUpdateClipPath(el, dataIndex, elOption, seriesModel, isInit); + updateElNormal(api, el, dataIndex, elOption, attachedTxInfoTmp, seriesModel, isInit); // `elOption.info` enables user to mount some info on + // elements and use them in event handlers. + // Update them only when user specified, otherwise, remain. + + hasOwn(elOption, 'info') && (customInnerStore(el).info = elOption.info); + + for (var i = 0; i < STATES.length; i++) { + var stateName = STATES[i]; + + if (stateName !== NORMAL) { + var otherStateOpt = retrieveStateOption(elOption, stateName); + var otherStyleOpt = retrieveStyleOptionOnState(elOption, otherStateOpt, stateName); + updateElOnState(stateName, el, otherStateOpt, otherStyleOpt, attachedTxInfoTmp); + } + } + + updateZ$1(el, elOption, seriesModel); + + if (elOption.type === 'group') { + mergeChildren(api, el, dataIndex, elOption, seriesModel); + } + + if (toBeReplacedIdx >= 0) { + group.replaceAt(el, toBeReplacedIdx); + } else { + group.add(el); + } + + return el; + } // `el` must not be null/undefined. + + + function doesElNeedRecreate(el, elOption, seriesModel) { + var elInner = customInnerStore(el); + var elOptionType = elOption.type; + var elOptionShape = elOption.shape; + var elOptionStyle = elOption.style; + return (// Always create new if universal transition is enabled. + // Because we do transition after render. It needs to know what old element is. Replacement will loose it. + seriesModel.isUniversalTransitionEnabled() // If `elOptionType` is `null`, follow the merge principle. + || elOptionType != null && elOptionType !== elInner.customGraphicType || elOptionType === 'path' && hasOwnPathData(elOptionShape) && getPathData(elOptionShape) !== elInner.customPathData || elOptionType === 'image' && hasOwn(elOptionStyle, 'image') && elOptionStyle.image !== elInner.customImagePath // // FIXME test and remove this restriction? + // || (elOptionType === 'text' + // && hasOwn(elOptionStyle, 'text') + // && (elOptionStyle as TextStyleProps).text !== elInner.customText + // ) + + ); + } + + function doCreateOrUpdateClipPath(el, dataIndex, elOption, seriesModel, isInit) { + // Based on the "merge" principle, if no clipPath provided, + // do nothing. The exists clip will be totally removed only if + // `el.clipPath` is `false`. Otherwise it will be merged/replaced. + var clipPathOpt = elOption.clipPath; + + if (clipPathOpt === false) { + if (el && el.getClipPath()) { + el.removeClipPath(); + } + } else if (clipPathOpt) { + var clipPath = el.getClipPath(); + + if (clipPath && doesElNeedRecreate(clipPath, clipPathOpt, seriesModel)) { + clipPath = null; + } + + if (!clipPath) { + clipPath = createEl(clipPathOpt); + + if ("development" !== 'production') { + assert(isPath$1(clipPath), 'Only any type of `path` can be used in `clipPath`, rather than ' + clipPath.type + '.'); + } + + el.setClipPath(clipPath); + } + + updateElNormal(null, clipPath, dataIndex, clipPathOpt, null, seriesModel, isInit); + } // If not define `clipPath` in option, do nothing unnecessary. + + } + + function doCreateOrUpdateAttachedTx(el, dataIndex, elOption, seriesModel, isInit, attachedTxInfo) { + // group do not support textContent temporarily untill necessary. + if (el.isGroup) { + return; + } // Normal must be called before emphasis, for `isLegacy` detection. + + + processTxInfo(elOption, null, attachedTxInfo); + processTxInfo(elOption, EMPHASIS, attachedTxInfo); // If `elOption.textConfig` or `elOption.textContent` is null/undefined, it does not make sence. + // So for simplicity, if "elOption hasOwnProperty of them but be null/undefined", we do not + // trade them as set to null to el. + // Especially: + // `elOption.textContent: false` means remove textContent. + // `elOption.textContent.emphasis.style: false` means remove the style from emphasis state. + + var txConOptNormal = attachedTxInfo.normal.conOpt; + var txConOptEmphasis = attachedTxInfo.emphasis.conOpt; + var txConOptBlur = attachedTxInfo.blur.conOpt; + var txConOptSelect = attachedTxInfo.select.conOpt; + + if (txConOptNormal != null || txConOptEmphasis != null || txConOptSelect != null || txConOptBlur != null) { + var textContent = el.getTextContent(); + + if (txConOptNormal === false) { + textContent && el.removeTextContent(); + } else { + txConOptNormal = attachedTxInfo.normal.conOpt = txConOptNormal || { + type: 'text' + }; + + if (!textContent) { + textContent = createEl(txConOptNormal); + el.setTextContent(textContent); + } else { + // If in some case the performance issue arised, consider + // do not clearState but update cached normal state directly. + textContent.clearStates(); + } + + updateElNormal(null, textContent, dataIndex, txConOptNormal, null, seriesModel, isInit); + var txConStlOptNormal = txConOptNormal && txConOptNormal.style; + + for (var i = 0; i < STATES.length; i++) { + var stateName = STATES[i]; + + if (stateName !== NORMAL) { + var txConOptOtherState = attachedTxInfo[stateName].conOpt; + updateElOnState(stateName, textContent, txConOptOtherState, retrieveStyleOptionOnState(txConOptNormal, txConOptOtherState, stateName), null); + } + } + + txConStlOptNormal ? textContent.dirty() : textContent.markRedraw(); + } + } + } + + function processTxInfo(elOption, state, attachedTxInfo) { + var stateOpt = !state ? elOption : retrieveStateOption(elOption, state); + var styleOpt = !state ? elOption.style : retrieveStyleOptionOnState(elOption, stateOpt, EMPHASIS); + var elType = elOption.type; + var txCfg = stateOpt ? stateOpt.textConfig : null; + var txConOptNormal = elOption.textContent; + var txConOpt = !txConOptNormal ? null : !state ? txConOptNormal : retrieveStateOption(txConOptNormal, state); + + if (styleOpt && ( // Because emphasis style has little info to detect legacy, + // if normal is legacy, emphasis is trade as legacy. + attachedTxInfo.isLegacy || isEC4CompatibleStyle(styleOpt, elType, !!txCfg, !!txConOpt))) { + attachedTxInfo.isLegacy = true; + var convertResult = convertFromEC4CompatibleStyle(styleOpt, elType, !state); // Explicitly specified `textConfig` and `textContent` has higher priority than + // the ones generated by legacy style. Otherwise if users use them and `api.style` + // at the same time, they not both work and hardly to known why. + + if (!txCfg && convertResult.textConfig) { + txCfg = convertResult.textConfig; + } + + if (!txConOpt && convertResult.textContent) { + txConOpt = convertResult.textContent; + } + } + + if (!state && txConOpt) { + var txConOptNormal_1 = txConOpt; // `textContent: {type: 'text'}`, the "type" is easy to be missing. So we tolerate it. + + !txConOptNormal_1.type && (txConOptNormal_1.type = 'text'); + + if ("development" !== 'production') { + // Do not tolerate incorret type for forward compat. + assert(txConOptNormal_1.type === 'text', 'textContent.type must be "text"'); + } + } + + var info = !state ? attachedTxInfo.normal : attachedTxInfo[state]; + info.cfg = txCfg; + info.conOpt = txConOpt; + } + + function retrieveStateOption(elOption, state) { + return !state ? elOption : elOption ? elOption[state] : null; + } + + function retrieveStyleOptionOnState(stateOptionNormal, stateOption, state) { + var style = stateOption && stateOption.style; + + if (style == null && state === EMPHASIS && stateOptionNormal) { + style = stateOptionNormal.styleEmphasis; + } + + return style; + } // Usage: + // (1) By default, `elOption.$mergeChildren` is `'byIndex'`, which indicates that + // the existing children will not be removed, and enables the feature that + // update some of the props of some of the children simply by construct + // the returned children of `renderItem` like: + // `var children = group.children = []; children[3] = {opacity: 0.5};` + // (2) If `elOption.$mergeChildren` is `'byName'`, add/update/remove children + // by child.name. But that might be lower performance. + // (3) If `elOption.$mergeChildren` is `false`, the existing children will be + // replaced totally. + // (4) If `!elOption.children`, following the "merge" principle, nothing will happen. + // + // For implementation simpleness, do not provide a direct way to remove sinlge + // child (otherwise the total indicies of the children array have to be modified). + // User can remove a single child by set its `ignore` as `true`. + + + function mergeChildren(api, el, dataIndex, elOption, seriesModel) { + var newChildren = elOption.children; + var newLen = newChildren ? newChildren.length : 0; + var mergeChildren = elOption.$mergeChildren; // `diffChildrenByName` has been deprecated. + + var byName = mergeChildren === 'byName' || elOption.diffChildrenByName; + var notMerge = mergeChildren === false; // For better performance on roam update, only enter if necessary. + + if (!newLen && !byName && !notMerge) { + return; + } + + if (byName) { + diffGroupChildren({ + api: api, + oldChildren: el.children() || [], + newChildren: newChildren || [], + dataIndex: dataIndex, + seriesModel: seriesModel, + group: el + }); + return; + } + + notMerge && el.removeAll(); // Mapping children of a group simply by index, which + // might be better performance. + + var index = 0; + + for (; index < newLen; index++) { + newChildren[index] && doCreateOrUpdateEl(api, el.childAt(index), dataIndex, newChildren[index], seriesModel, el); + } + + for (var i = el.childCount() - 1; i >= index; i--) { + // Do not supprot leave elements that are not mentioned in the latest + // `renderItem` return. Otherwise users may not have a clear and simple + // concept that how to contorl all of the elements. + var child = el.childAt(i); + applyLeaveTransition(child, customInnerStore(el).option, seriesModel); + } + } + + function diffGroupChildren(context) { + new DataDiffer(context.oldChildren, context.newChildren, getKey, getKey, context).add(processAddUpdate).update(processAddUpdate).remove(processRemove).execute(); + } + + function getKey(item, idx) { + var name = item && item.name; + return name != null ? name : GROUP_DIFF_PREFIX + idx; + } + + function processAddUpdate(newIndex, oldIndex) { + var context = this.context; + var childOption = newIndex != null ? context.newChildren[newIndex] : null; + var child = oldIndex != null ? context.oldChildren[oldIndex] : null; + doCreateOrUpdateEl(context.api, child, context.dataIndex, childOption, context.seriesModel, context.group); + } + + function processRemove(oldIndex) { + var context = this.context; + var child = context.oldChildren[oldIndex]; + applyLeaveTransition(child, customInnerStore(child).option, context.seriesModel); + } + /** + * @return SVG Path data. + */ + + + function getPathData(shape) { + // "d" follows the SVG convention. + return shape && (shape.pathData || shape.d); + } + + function hasOwnPathData(shape) { + return shape && (hasOwn(shape, 'pathData') || hasOwn(shape, 'd')); + } + + function install$r(registers) { + registers.registerChartView(CustomChartView); + registers.registerSeriesModel(CustomSeriesModel); + } + + var inner$a = makeInner(); + var clone$3 = clone; + var bind$1 = bind; + /** + * Base axis pointer class in 2D. + */ + + var BaseAxisPointer = + /** @class */ + function () { + function BaseAxisPointer() { + this._dragging = false; + /** + * In px, arbitrary value. Do not set too small, + * no animation is ok for most cases. + */ + + this.animationThreshold = 15; + } + /** + * @implement + */ + + + BaseAxisPointer.prototype.render = function (axisModel, axisPointerModel, api, forceRender) { + var value = axisPointerModel.get('value'); + var status = axisPointerModel.get('status'); // Bind them to `this`, not in closure, otherwise they will not + // be replaced when user calling setOption in not merge mode. + + this._axisModel = axisModel; + this._axisPointerModel = axisPointerModel; + this._api = api; // Optimize: `render` will be called repeatly during mouse move. + // So it is power consuming if performing `render` each time, + // especially on mobile device. + + if (!forceRender && this._lastValue === value && this._lastStatus === status) { + return; + } + + this._lastValue = value; + this._lastStatus = status; + var group = this._group; + var handle = this._handle; + + if (!status || status === 'hide') { + // Do not clear here, for animation better. + group && group.hide(); + handle && handle.hide(); + return; + } + + group && group.show(); + handle && handle.show(); // Otherwise status is 'show' + + var elOption = {}; + this.makeElOption(elOption, value, axisModel, axisPointerModel, api); // Enable change axis pointer type. + + var graphicKey = elOption.graphicKey; + + if (graphicKey !== this._lastGraphicKey) { + this.clear(api); + } + + this._lastGraphicKey = graphicKey; + var moveAnimation = this._moveAnimation = this.determineAnimation(axisModel, axisPointerModel); + + if (!group) { + group = this._group = new Group(); + this.createPointerEl(group, elOption, axisModel, axisPointerModel); + this.createLabelEl(group, elOption, axisModel, axisPointerModel); + api.getZr().add(group); + } else { + var doUpdateProps = curry(updateProps$1, axisPointerModel, moveAnimation); + this.updatePointerEl(group, elOption, doUpdateProps); + this.updateLabelEl(group, elOption, doUpdateProps, axisPointerModel); + } + + updateMandatoryProps(group, axisPointerModel, true); + + this._renderHandle(value); + }; + /** + * @implement + */ + + + BaseAxisPointer.prototype.remove = function (api) { + this.clear(api); + }; + /** + * @implement + */ + + + BaseAxisPointer.prototype.dispose = function (api) { + this.clear(api); + }; + /** + * @protected + */ + + + BaseAxisPointer.prototype.determineAnimation = function (axisModel, axisPointerModel) { + var animation = axisPointerModel.get('animation'); + var axis = axisModel.axis; + var isCategoryAxis = axis.type === 'category'; + var useSnap = axisPointerModel.get('snap'); // Value axis without snap always do not snap. + + if (!useSnap && !isCategoryAxis) { + return false; + } + + if (animation === 'auto' || animation == null) { + var animationThreshold = this.animationThreshold; + + if (isCategoryAxis && axis.getBandWidth() > animationThreshold) { + return true; + } // It is important to auto animation when snap used. Consider if there is + // a dataZoom, animation will be disabled when too many points exist, while + // it will be enabled for better visual effect when little points exist. + + + if (useSnap) { + var seriesDataCount = getAxisInfo(axisModel).seriesDataCount; + var axisExtent = axis.getExtent(); // Approximate band width + + return Math.abs(axisExtent[0] - axisExtent[1]) / seriesDataCount > animationThreshold; + } + + return false; + } + + return animation === true; + }; + /** + * add {pointer, label, graphicKey} to elOption + * @protected + */ + + + BaseAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) {// Shoule be implemenented by sub-class. + }; + /** + * @protected + */ + + + BaseAxisPointer.prototype.createPointerEl = function (group, elOption, axisModel, axisPointerModel) { + var pointerOption = elOption.pointer; + + if (pointerOption) { + var pointerEl = inner$a(group).pointerEl = new graphic[pointerOption.type](clone$3(elOption.pointer)); + group.add(pointerEl); + } + }; + /** + * @protected + */ + + + BaseAxisPointer.prototype.createLabelEl = function (group, elOption, axisModel, axisPointerModel) { + if (elOption.label) { + var labelEl = inner$a(group).labelEl = new ZRText(clone$3(elOption.label)); + group.add(labelEl); + updateLabelShowHide(labelEl, axisPointerModel); + } + }; + /** + * @protected + */ + + + BaseAxisPointer.prototype.updatePointerEl = function (group, elOption, updateProps) { + var pointerEl = inner$a(group).pointerEl; + + if (pointerEl && elOption.pointer) { + pointerEl.setStyle(elOption.pointer.style); + updateProps(pointerEl, { + shape: elOption.pointer.shape + }); + } + }; + /** + * @protected + */ + + + BaseAxisPointer.prototype.updateLabelEl = function (group, elOption, updateProps, axisPointerModel) { + var labelEl = inner$a(group).labelEl; + + if (labelEl) { + labelEl.setStyle(elOption.label.style); + updateProps(labelEl, { + // Consider text length change in vertical axis, animation should + // be used on shape, otherwise the effect will be weird. + // TODOTODO + // shape: elOption.label.shape, + x: elOption.label.x, + y: elOption.label.y + }); + updateLabelShowHide(labelEl, axisPointerModel); + } + }; + /** + * @private + */ + + + BaseAxisPointer.prototype._renderHandle = function (value) { + if (this._dragging || !this.updateHandleTransform) { + return; + } + + var axisPointerModel = this._axisPointerModel; + + var zr = this._api.getZr(); + + var handle = this._handle; + var handleModel = axisPointerModel.getModel('handle'); + var status = axisPointerModel.get('status'); + + if (!handleModel.get('show') || !status || status === 'hide') { + handle && zr.remove(handle); + this._handle = null; + return; + } + + var isInit; + + if (!this._handle) { + isInit = true; + handle = this._handle = createIcon(handleModel.get('icon'), { + cursor: 'move', + draggable: true, + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + stop(e.event); + }, + onmousedown: bind$1(this._onHandleDragMove, this, 0, 0), + drift: bind$1(this._onHandleDragMove, this), + ondragend: bind$1(this._onHandleDragEnd, this) + }); + zr.add(handle); + } + + updateMandatoryProps(handle, axisPointerModel, false); // update style + + handle.setStyle(handleModel.getItemStyle(null, ['color', 'borderColor', 'borderWidth', 'opacity', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'])); // update position + + var handleSize = handleModel.get('size'); + + if (!isArray(handleSize)) { + handleSize = [handleSize, handleSize]; + } + + handle.scaleX = handleSize[0] / 2; + handle.scaleY = handleSize[1] / 2; + createOrUpdate(this, '_doDispatchAxisPointer', handleModel.get('throttle') || 0, 'fixRate'); + + this._moveHandleToValue(value, isInit); + }; + + BaseAxisPointer.prototype._moveHandleToValue = function (value, isInit) { + updateProps$1(this._axisPointerModel, !isInit && this._moveAnimation, this._handle, getHandleTransProps(this.getHandleTransform(value, this._axisModel, this._axisPointerModel))); + }; + + BaseAxisPointer.prototype._onHandleDragMove = function (dx, dy) { + var handle = this._handle; + + if (!handle) { + return; + } + + this._dragging = true; // Persistent for throttle. + + var trans = this.updateHandleTransform(getHandleTransProps(handle), [dx, dy], this._axisModel, this._axisPointerModel); + this._payloadInfo = trans; + handle.stopAnimation(); + handle.attr(getHandleTransProps(trans)); + inner$a(handle).lastProp = null; + + this._doDispatchAxisPointer(); + }; + /** + * Throttled method. + */ + + + BaseAxisPointer.prototype._doDispatchAxisPointer = function () { + var handle = this._handle; + + if (!handle) { + return; + } + + var payloadInfo = this._payloadInfo; + var axisModel = this._axisModel; + + this._api.dispatchAction({ + type: 'updateAxisPointer', + x: payloadInfo.cursorPoint[0], + y: payloadInfo.cursorPoint[1], + tooltipOption: payloadInfo.tooltipOption, + axesInfo: [{ + axisDim: axisModel.axis.dim, + axisIndex: axisModel.componentIndex + }] + }); + }; + + BaseAxisPointer.prototype._onHandleDragEnd = function () { + this._dragging = false; + var handle = this._handle; + + if (!handle) { + return; + } + + var value = this._axisPointerModel.get('value'); // Consider snap or categroy axis, handle may be not consistent with + // axisPointer. So move handle to align the exact value position when + // drag ended. + + + this._moveHandleToValue(value); // For the effect: tooltip will be shown when finger holding on handle + // button, and will be hidden after finger left handle button. + + + this._api.dispatchAction({ + type: 'hideTip' + }); + }; + /** + * @private + */ + + + BaseAxisPointer.prototype.clear = function (api) { + this._lastValue = null; + this._lastStatus = null; + var zr = api.getZr(); + var group = this._group; + var handle = this._handle; + + if (zr && group) { + this._lastGraphicKey = null; + group && zr.remove(group); + handle && zr.remove(handle); + this._group = null; + this._handle = null; + this._payloadInfo = null; + } + + clear(this, '_doDispatchAxisPointer'); + }; + /** + * @protected + */ + + + BaseAxisPointer.prototype.doClear = function () {// Implemented by sub-class if necessary. + }; + + BaseAxisPointer.prototype.buildLabel = function (xy, wh, xDimIndex) { + xDimIndex = xDimIndex || 0; + return { + x: xy[xDimIndex], + y: xy[1 - xDimIndex], + width: wh[xDimIndex], + height: wh[1 - xDimIndex] + }; + }; + + return BaseAxisPointer; + }(); + + function updateProps$1(animationModel, moveAnimation, el, props) { + // Animation optimize. + if (!propsEqual(inner$a(el).lastProp, props)) { + inner$a(el).lastProp = props; + moveAnimation ? updateProps(el, props, animationModel) : (el.stopAnimation(), el.attr(props)); + } + } + + function propsEqual(lastProps, newProps) { + if (isObject(lastProps) && isObject(newProps)) { + var equals_1 = true; + each(newProps, function (item, key) { + equals_1 = equals_1 && propsEqual(lastProps[key], item); + }); + return !!equals_1; + } else { + return lastProps === newProps; + } + } + + function updateLabelShowHide(labelEl, axisPointerModel) { + labelEl[axisPointerModel.get(['label', 'show']) ? 'show' : 'hide'](); + } + + function getHandleTransProps(trans) { + return { + x: trans.x || 0, + y: trans.y || 0, + rotation: trans.rotation || 0 + }; + } + + function updateMandatoryProps(group, axisPointerModel, silent) { + var z = axisPointerModel.get('z'); + var zlevel = axisPointerModel.get('zlevel'); + group && group.traverse(function (el) { + if (el.type !== 'group') { + z != null && (el.z = z); + zlevel != null && (el.zlevel = zlevel); + el.silent = silent; + } + }); + } + + function buildElStyle(axisPointerModel) { + var axisPointerType = axisPointerModel.get('type'); + var styleModel = axisPointerModel.getModel(axisPointerType + 'Style'); + var style; + + if (axisPointerType === 'line') { + style = styleModel.getLineStyle(); + style.fill = null; + } else if (axisPointerType === 'shadow') { + style = styleModel.getAreaStyle(); + style.stroke = null; + } + + return style; + } + /** + * @param {Function} labelPos {align, verticalAlign, position} + */ + + function buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos) { + var value = axisPointerModel.get('value'); + var text = getValueLabel(value, axisModel.axis, axisModel.ecModel, axisPointerModel.get('seriesDataIndices'), { + precision: axisPointerModel.get(['label', 'precision']), + formatter: axisPointerModel.get(['label', 'formatter']) + }); + var labelModel = axisPointerModel.getModel('label'); + var paddings = normalizeCssArray$1(labelModel.get('padding') || 0); + var font = labelModel.getFont(); + var textRect = getBoundingRect(text, font); + var position = labelPos.position; + var width = textRect.width + paddings[1] + paddings[3]; + var height = textRect.height + paddings[0] + paddings[2]; // Adjust by align. + + var align = labelPos.align; + align === 'right' && (position[0] -= width); + align === 'center' && (position[0] -= width / 2); + var verticalAlign = labelPos.verticalAlign; + verticalAlign === 'bottom' && (position[1] -= height); + verticalAlign === 'middle' && (position[1] -= height / 2); // Not overflow ec container + + confineInContainer(position, width, height, api); + var bgColor = labelModel.get('backgroundColor'); + + if (!bgColor || bgColor === 'auto') { + bgColor = axisModel.get(['axisLine', 'lineStyle', 'color']); + } + + elOption.label = { + // shape: {x: 0, y: 0, width: width, height: height, r: labelModel.get('borderRadius')}, + x: position[0], + y: position[1], + style: createTextStyle(labelModel, { + text: text, + font: font, + fill: labelModel.getTextColor(), + padding: paddings, + backgroundColor: bgColor + }), + // Lable should be over axisPointer. + z2: 10 + }; + } // Do not overflow ec container + + function confineInContainer(position, width, height, api) { + var viewWidth = api.getWidth(); + var viewHeight = api.getHeight(); + position[0] = Math.min(position[0] + width, viewWidth) - width; + position[1] = Math.min(position[1] + height, viewHeight) - height; + position[0] = Math.max(position[0], 0); + position[1] = Math.max(position[1], 0); + } + + function getValueLabel(value, axis, ecModel, seriesDataIndices, opt) { + value = axis.scale.parse(value); + var text = axis.scale.getLabel({ + value: value + }, { + // If `precision` is set, width can be fixed (like '12.00500'), which + // helps to debounce when when moving label. + precision: opt.precision + }); + var formatter = opt.formatter; + + if (formatter) { + var params_1 = { + value: getAxisRawValue(axis, { + value: value + }), + axisDimension: axis.dim, + axisIndex: axis.index, + seriesData: [] + }; + each(seriesDataIndices, function (idxItem) { + var series = ecModel.getSeriesByIndex(idxItem.seriesIndex); + var dataIndex = idxItem.dataIndexInside; + var dataParams = series && series.getDataParams(dataIndex); + dataParams && params_1.seriesData.push(dataParams); + }); + + if (isString(formatter)) { + text = formatter.replace('{value}', text); + } else if (isFunction(formatter)) { + text = formatter(params_1); + } + } + + return text; + } + function getTransformedPosition(axis, value, layoutInfo) { + var transform = create$1(); + rotate(transform, transform, layoutInfo.rotation); + translate(transform, transform, layoutInfo.position); + return applyTransform$1([axis.dataToCoord(value), (layoutInfo.labelOffset || 0) + (layoutInfo.labelDirection || 1) * (layoutInfo.labelMargin || 0)], transform); + } + function buildCartesianSingleLabelElOption(value, elOption, layoutInfo, axisModel, axisPointerModel, api) { + // @ts-ignore + var textLayout = AxisBuilder.innerTextLayout(layoutInfo.rotation, 0, layoutInfo.labelDirection); + layoutInfo.labelMargin = axisPointerModel.get(['label', 'margin']); + buildLabelElOption(elOption, axisModel, axisPointerModel, api, { + position: getTransformedPosition(axisModel.axis, value, layoutInfo), + align: textLayout.textAlign, + verticalAlign: textLayout.textVerticalAlign + }); + } + function makeLineShape(p1, p2, xDimIndex) { + xDimIndex = xDimIndex || 0; + return { + x1: p1[xDimIndex], + y1: p1[1 - xDimIndex], + x2: p2[xDimIndex], + y2: p2[1 - xDimIndex] + }; + } + function makeRectShape(xy, wh, xDimIndex) { + xDimIndex = xDimIndex || 0; + return { + x: xy[xDimIndex], + y: xy[1 - xDimIndex], + width: wh[xDimIndex], + height: wh[1 - xDimIndex] + }; + } + function makeSectorShape(cx, cy, r0, r, startAngle, endAngle) { + return { + cx: cx, + cy: cy, + r0: r0, + r: r, + startAngle: startAngle, + endAngle: endAngle, + clockwise: true + }; + } + + var CartesianAxisPointer = + /** @class */ + function (_super) { + __extends(CartesianAxisPointer, _super); + + function CartesianAxisPointer() { + return _super !== null && _super.apply(this, arguments) || this; + } + /** + * @override + */ + + + CartesianAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) { + var axis = axisModel.axis; + var grid = axis.grid; + var axisPointerType = axisPointerModel.get('type'); + var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent(); + var pixelValue = axis.toGlobalCoord(axis.dataToCoord(value, true)); + + if (axisPointerType && axisPointerType !== 'none') { + var elStyle = buildElStyle(axisPointerModel); + var pointerOption = pointerShapeBuilder[axisPointerType](axis, pixelValue, otherExtent); + pointerOption.style = elStyle; + elOption.graphicKey = pointerOption.type; + elOption.pointer = pointerOption; + } + + var layoutInfo = layout$1(grid.model, axisModel); + buildCartesianSingleLabelElOption( // @ts-ignore + value, elOption, layoutInfo, axisModel, axisPointerModel, api); + }; + /** + * @override + */ + + + CartesianAxisPointer.prototype.getHandleTransform = function (value, axisModel, axisPointerModel) { + var layoutInfo = layout$1(axisModel.axis.grid.model, axisModel, { + labelInside: false + }); // @ts-ignore + + layoutInfo.labelMargin = axisPointerModel.get(['handle', 'margin']); + var pos = getTransformedPosition(axisModel.axis, value, layoutInfo); + return { + x: pos[0], + y: pos[1], + rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0) + }; + }; + /** + * @override + */ + + + CartesianAxisPointer.prototype.updateHandleTransform = function (transform, delta, axisModel, axisPointerModel) { + var axis = axisModel.axis; + var grid = axis.grid; + var axisExtent = axis.getGlobalExtent(true); + var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent(); + var dimIndex = axis.dim === 'x' ? 0 : 1; + var currPosition = [transform.x, transform.y]; + currPosition[dimIndex] += delta[dimIndex]; + currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]); + currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]); + var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2; + var cursorPoint = [cursorOtherValue, cursorOtherValue]; + cursorPoint[dimIndex] = currPosition[dimIndex]; // Make tooltip do not overlap axisPointer and in the middle of the grid. + + var tooltipOptions = [{ + verticalAlign: 'middle' + }, { + align: 'center' + }]; + return { + x: currPosition[0], + y: currPosition[1], + rotation: transform.rotation, + cursorPoint: cursorPoint, + tooltipOption: tooltipOptions[dimIndex] + }; + }; + + return CartesianAxisPointer; + }(BaseAxisPointer); + + function getCartesian(grid, axis) { + var opt = {}; + opt[axis.dim + 'AxisIndex'] = axis.index; + return grid.getCartesian(opt); + } + + var pointerShapeBuilder = { + line: function (axis, pixelValue, otherExtent) { + var targetShape = makeLineShape([pixelValue, otherExtent[0]], [pixelValue, otherExtent[1]], getAxisDimIndex(axis)); + return { + type: 'Line', + subPixelOptimize: true, + shape: targetShape + }; + }, + shadow: function (axis, pixelValue, otherExtent) { + var bandWidth = Math.max(1, axis.getBandWidth()); + var span = otherExtent[1] - otherExtent[0]; + return { + type: 'Rect', + shape: makeRectShape([pixelValue - bandWidth / 2, otherExtent[0]], [bandWidth, span], getAxisDimIndex(axis)) + }; + } + }; + + function getAxisDimIndex(axis) { + return axis.dim === 'x' ? 0 : 1; + } + + var AxisPointerModel = + /** @class */ + function (_super) { + __extends(AxisPointerModel, _super); + + function AxisPointerModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = AxisPointerModel.type; + return _this; + } + + AxisPointerModel.type = 'axisPointer'; + AxisPointerModel.defaultOption = { + // 'auto' means that show when triggered by tooltip or handle. + show: 'auto', + // zlevel: 0, + z: 50, + type: 'line', + // axispointer triggered by tootip determine snap automatically, + // see `modelHelper`. + snap: false, + triggerTooltip: true, + value: null, + status: null, + link: [], + // Do not set 'auto' here, otherwise global animation: false + // will not effect at this axispointer. + animation: null, + animationDurationUpdate: 200, + lineStyle: { + color: '#B9BEC9', + width: 1, + type: 'dashed' + }, + shadowStyle: { + color: 'rgba(210,219,238,0.2)' + }, + label: { + show: true, + formatter: null, + precision: 'auto', + margin: 3, + color: '#fff', + padding: [5, 7, 5, 7], + backgroundColor: 'auto', + borderColor: null, + borderWidth: 0, + borderRadius: 3 + }, + handle: { + show: false, + // eslint-disable-next-line + icon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z', + size: 45, + // handle margin is from symbol center to axis, which is stable when circular move. + margin: 50, + // color: '#1b8bbd' + // color: '#2f4554' + color: '#333', + shadowBlur: 3, + shadowColor: '#aaa', + shadowOffsetX: 0, + shadowOffsetY: 2, + // For mobile performance + throttle: 40 + } + }; + return AxisPointerModel; + }(ComponentModel); + + var inner$b = makeInner(); + var each$7 = each; + /** + * @param {string} key + * @param {module:echarts/ExtensionAPI} api + * @param {Function} handler + * param: {string} currTrigger + * param: {Array.} point + */ + + function register(key, api, handler) { + if (env.node) { + return; + } + + var zr = api.getZr(); + inner$b(zr).records || (inner$b(zr).records = {}); + initGlobalListeners(zr, api); + var record = inner$b(zr).records[key] || (inner$b(zr).records[key] = {}); + record.handler = handler; + } + + function initGlobalListeners(zr, api) { + if (inner$b(zr).initialized) { + return; + } + + inner$b(zr).initialized = true; + useHandler('click', curry(doEnter, 'click')); + useHandler('mousemove', curry(doEnter, 'mousemove')); // useHandler('mouseout', onLeave); + + useHandler('globalout', onLeave); + + function useHandler(eventType, cb) { + zr.on(eventType, function (e) { + var dis = makeDispatchAction(api); + each$7(inner$b(zr).records, function (record) { + record && cb(record, e, dis.dispatchAction); + }); + dispatchTooltipFinally(dis.pendings, api); + }); + } + } + + function dispatchTooltipFinally(pendings, api) { + var showLen = pendings.showTip.length; + var hideLen = pendings.hideTip.length; + var actuallyPayload; + + if (showLen) { + actuallyPayload = pendings.showTip[showLen - 1]; + } else if (hideLen) { + actuallyPayload = pendings.hideTip[hideLen - 1]; + } + + if (actuallyPayload) { + actuallyPayload.dispatchAction = null; + api.dispatchAction(actuallyPayload); + } + } + + function onLeave(record, e, dispatchAction) { + record.handler('leave', null, dispatchAction); + } + + function doEnter(currTrigger, record, e, dispatchAction) { + record.handler(currTrigger, e, dispatchAction); + } + + function makeDispatchAction(api) { + var pendings = { + showTip: [], + hideTip: [] + }; // FIXME + // better approach? + // 'showTip' and 'hideTip' can be triggered by axisPointer and tooltip, + // which may be conflict, (axisPointer call showTip but tooltip call hideTip); + // So we have to add "final stage" to merge those dispatched actions. + + var dispatchAction = function (payload) { + var pendingList = pendings[payload.type]; + + if (pendingList) { + pendingList.push(payload); + } else { + payload.dispatchAction = dispatchAction; + api.dispatchAction(payload); + } + }; + + return { + dispatchAction: dispatchAction, + pendings: pendings + }; + } + + function unregister(key, api) { + if (env.node) { + return; + } + + var zr = api.getZr(); + var record = (inner$b(zr).records || {})[key]; + + if (record) { + inner$b(zr).records[key] = null; + } + } + + var AxisPointerView = + /** @class */ + function (_super) { + __extends(AxisPointerView, _super); + + function AxisPointerView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = AxisPointerView.type; + return _this; + } + + AxisPointerView.prototype.render = function (globalAxisPointerModel, ecModel, api) { + var globalTooltipModel = ecModel.getComponent('tooltip'); + var triggerOn = globalAxisPointerModel.get('triggerOn') || globalTooltipModel && globalTooltipModel.get('triggerOn') || 'mousemove|click'; // Register global listener in AxisPointerView to enable + // AxisPointerView to be independent to Tooltip. + + register('axisPointer', api, function (currTrigger, e, dispatchAction) { + // If 'none', it is not controlled by mouse totally. + if (triggerOn !== 'none' && (currTrigger === 'leave' || triggerOn.indexOf(currTrigger) >= 0)) { + dispatchAction({ + type: 'updateAxisPointer', + currTrigger: currTrigger, + x: e && e.offsetX, + y: e && e.offsetY + }); + } + }); + }; + + AxisPointerView.prototype.remove = function (ecModel, api) { + unregister('axisPointer', api); + }; + + AxisPointerView.prototype.dispose = function (ecModel, api) { + unregister('axisPointer', api); + }; + + AxisPointerView.type = 'axisPointer'; + return AxisPointerView; + }(ComponentView); + + /** + * @param finder contains {seriesIndex, dataIndex, dataIndexInside} + * @param ecModel + * @return {point: [x, y], el: ...} point Will not be null. + */ + + function findPointFromSeries(finder, ecModel) { + var point = []; + var seriesIndex = finder.seriesIndex; + var seriesModel; + + if (seriesIndex == null || !(seriesModel = ecModel.getSeriesByIndex(seriesIndex))) { + return { + point: [] + }; + } + + var data = seriesModel.getData(); + var dataIndex = queryDataIndex(data, finder); + + if (dataIndex == null || dataIndex < 0 || isArray(dataIndex)) { + return { + point: [] + }; + } + + var el = data.getItemGraphicEl(dataIndex); + var coordSys = seriesModel.coordinateSystem; + + if (seriesModel.getTooltipPosition) { + point = seriesModel.getTooltipPosition(dataIndex) || []; + } else if (coordSys && coordSys.dataToPoint) { + if (finder.isStacked) { + var baseAxis = coordSys.getBaseAxis(); + var valueAxis = coordSys.getOtherAxis(baseAxis); + var valueAxisDim = valueAxis.dim; + var baseAxisDim = baseAxis.dim; + var baseDataOffset = valueAxisDim === 'x' || valueAxisDim === 'radius' ? 1 : 0; + var baseDim = data.mapDimension(baseAxisDim); + var stackedData = []; + stackedData[baseDataOffset] = data.get(baseDim, dataIndex); + stackedData[1 - baseDataOffset] = data.get(data.getCalculationInfo('stackResultDimension'), dataIndex); + point = coordSys.dataToPoint(stackedData) || []; + } else { + point = coordSys.dataToPoint(data.getValues(map(coordSys.dimensions, function (dim) { + return data.mapDimension(dim); + }), dataIndex)) || []; + } + } else if (el) { + // Use graphic bounding rect + var rect = el.getBoundingRect().clone(); + rect.applyTransform(el.transform); + point = [rect.x + rect.width / 2, rect.y + rect.height / 2]; + } + + return { + point: point, + el: el + }; + } + + var inner$c = makeInner(); + /** + * Basic logic: check all axis, if they do not demand show/highlight, + * then hide/downplay them. + * + * @return content of event obj for echarts.connect. + */ + + function axisTrigger(payload, ecModel, api) { + var currTrigger = payload.currTrigger; + var point = [payload.x, payload.y]; + var finder = payload; + var dispatchAction = payload.dispatchAction || bind(api.dispatchAction, api); + var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo; // Pending + // See #6121. But we are not able to reproduce it yet. + + if (!coordSysAxesInfo) { + return; + } + + if (illegalPoint(point)) { + // Used in the default behavior of `connection`: use the sample seriesIndex + // and dataIndex. And also used in the tooltipView trigger. + point = findPointFromSeries({ + seriesIndex: finder.seriesIndex, + // Do not use dataIndexInside from other ec instance. + // FIXME: auto detect it? + dataIndex: finder.dataIndex + }, ecModel).point; + } + + var isIllegalPoint = illegalPoint(point); // Axis and value can be specified when calling dispatchAction({type: 'updateAxisPointer'}). + // Notice: In this case, it is difficult to get the `point` (which is necessary to show + // tooltip, so if point is not given, we just use the point found by sample seriesIndex + // and dataIndex. + + var inputAxesInfo = finder.axesInfo; + var axesInfo = coordSysAxesInfo.axesInfo; + var shouldHide = currTrigger === 'leave' || illegalPoint(point); + var outputPayload = {}; + var showValueMap = {}; + var dataByCoordSys = { + list: [], + map: {} + }; + var updaters = { + showPointer: curry(showPointer, showValueMap), + showTooltip: curry(showTooltip, dataByCoordSys) + }; // Process for triggered axes. + + each(coordSysAxesInfo.coordSysMap, function (coordSys, coordSysKey) { + // If a point given, it must be contained by the coordinate system. + var coordSysContainsPoint = isIllegalPoint || coordSys.containPoint(point); + each(coordSysAxesInfo.coordSysAxesInfo[coordSysKey], function (axisInfo, key) { + var axis = axisInfo.axis; + var inputAxisInfo = findInputAxisInfo(inputAxesInfo, axisInfo); // If no inputAxesInfo, no axis is restricted. + + if (!shouldHide && coordSysContainsPoint && (!inputAxesInfo || inputAxisInfo)) { + var val = inputAxisInfo && inputAxisInfo.value; + + if (val == null && !isIllegalPoint) { + val = axis.pointToData(point); + } + + val != null && processOnAxis(axisInfo, val, updaters, false, outputPayload); + } + }); + }); // Process for linked axes. + + var linkTriggers = {}; + each(axesInfo, function (tarAxisInfo, tarKey) { + var linkGroup = tarAxisInfo.linkGroup; // If axis has been triggered in the previous stage, it should not be triggered by link. + + if (linkGroup && !showValueMap[tarKey]) { + each(linkGroup.axesInfo, function (srcAxisInfo, srcKey) { + var srcValItem = showValueMap[srcKey]; // If srcValItem exist, source axis is triggered, so link to target axis. + + if (srcAxisInfo !== tarAxisInfo && srcValItem) { + var val = srcValItem.value; + linkGroup.mapper && (val = tarAxisInfo.axis.scale.parse(linkGroup.mapper(val, makeMapperParam(srcAxisInfo), makeMapperParam(tarAxisInfo)))); + linkTriggers[tarAxisInfo.key] = val; + } + }); + } + }); + each(linkTriggers, function (val, tarKey) { + processOnAxis(axesInfo[tarKey], val, updaters, true, outputPayload); + }); + updateModelActually(showValueMap, axesInfo, outputPayload); + dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction); + dispatchHighDownActually(axesInfo, dispatchAction, api); + return outputPayload; + } + + function processOnAxis(axisInfo, newValue, updaters, noSnap, outputFinder) { + var axis = axisInfo.axis; + + if (axis.scale.isBlank() || !axis.containData(newValue)) { + return; + } + + if (!axisInfo.involveSeries) { + updaters.showPointer(axisInfo, newValue); + return; + } // Heavy calculation. So put it after axis.containData checking. + + + var payloadInfo = buildPayloadsBySeries(newValue, axisInfo); + var payloadBatch = payloadInfo.payloadBatch; + var snapToValue = payloadInfo.snapToValue; // Fill content of event obj for echarts.connect. + // By default use the first involved series data as a sample to connect. + + if (payloadBatch[0] && outputFinder.seriesIndex == null) { + extend(outputFinder, payloadBatch[0]); + } // If no linkSource input, this process is for collecting link + // target, where snap should not be accepted. + + + if (!noSnap && axisInfo.snap) { + if (axis.containData(snapToValue) && snapToValue != null) { + newValue = snapToValue; + } + } + + updaters.showPointer(axisInfo, newValue, payloadBatch); // Tooltip should always be snapToValue, otherwise there will be + // incorrect "axis value ~ series value" mapping displayed in tooltip. + + updaters.showTooltip(axisInfo, payloadInfo, snapToValue); + } + + function buildPayloadsBySeries(value, axisInfo) { + var axis = axisInfo.axis; + var dim = axis.dim; + var snapToValue = value; + var payloadBatch = []; + var minDist = Number.MAX_VALUE; + var minDiff = -1; + each(axisInfo.seriesModels, function (series, idx) { + var dataDim = series.getData().mapDimensionsAll(dim); + var seriesNestestValue; + var dataIndices; + + if (series.getAxisTooltipData) { + var result = series.getAxisTooltipData(dataDim, value, axis); + dataIndices = result.dataIndices; + seriesNestestValue = result.nestestValue; + } else { + dataIndices = series.getData().indicesOfNearest(dataDim[0], value, // Add a threshold to avoid find the wrong dataIndex + // when data length is not same. + // false, + axis.type === 'category' ? 0.5 : null); + + if (!dataIndices.length) { + return; + } + + seriesNestestValue = series.getData().get(dataDim[0], dataIndices[0]); + } + + if (seriesNestestValue == null || !isFinite(seriesNestestValue)) { + return; + } + + var diff = value - seriesNestestValue; + var dist = Math.abs(diff); // Consider category case + + if (dist <= minDist) { + if (dist < minDist || diff >= 0 && minDiff < 0) { + minDist = dist; + minDiff = diff; + snapToValue = seriesNestestValue; + payloadBatch.length = 0; + } + + each(dataIndices, function (dataIndex) { + payloadBatch.push({ + seriesIndex: series.seriesIndex, + dataIndexInside: dataIndex, + dataIndex: series.getData().getRawIndex(dataIndex) + }); + }); + } + }); + return { + payloadBatch: payloadBatch, + snapToValue: snapToValue + }; + } + + function showPointer(showValueMap, axisInfo, value, payloadBatch) { + showValueMap[axisInfo.key] = { + value: value, + payloadBatch: payloadBatch + }; + } + + function showTooltip(dataByCoordSys, axisInfo, payloadInfo, value) { + var payloadBatch = payloadInfo.payloadBatch; + var axis = axisInfo.axis; + var axisModel = axis.model; + var axisPointerModel = axisInfo.axisPointerModel; // If no data, do not create anything in dataByCoordSys, + // whose length will be used to judge whether dispatch action. + + if (!axisInfo.triggerTooltip || !payloadBatch.length) { + return; + } + + var coordSysModel = axisInfo.coordSys.model; + var coordSysKey = makeKey(coordSysModel); + var coordSysItem = dataByCoordSys.map[coordSysKey]; + + if (!coordSysItem) { + coordSysItem = dataByCoordSys.map[coordSysKey] = { + coordSysId: coordSysModel.id, + coordSysIndex: coordSysModel.componentIndex, + coordSysType: coordSysModel.type, + coordSysMainType: coordSysModel.mainType, + dataByAxis: [] + }; + dataByCoordSys.list.push(coordSysItem); + } + + coordSysItem.dataByAxis.push({ + axisDim: axis.dim, + axisIndex: axisModel.componentIndex, + axisType: axisModel.type, + axisId: axisModel.id, + value: value, + // Caustion: viewHelper.getValueLabel is actually on "view stage", which + // depends that all models have been updated. So it should not be performed + // here. Considering axisPointerModel used here is volatile, which is hard + // to be retrieve in TooltipView, we prepare parameters here. + valueLabelOpt: { + precision: axisPointerModel.get(['label', 'precision']), + formatter: axisPointerModel.get(['label', 'formatter']) + }, + seriesDataIndices: payloadBatch.slice() + }); + } + + function updateModelActually(showValueMap, axesInfo, outputPayload) { + var outputAxesInfo = outputPayload.axesInfo = []; // Basic logic: If no 'show' required, 'hide' this axisPointer. + + each(axesInfo, function (axisInfo, key) { + var option = axisInfo.axisPointerModel.option; + var valItem = showValueMap[key]; + + if (valItem) { + !axisInfo.useHandle && (option.status = 'show'); + option.value = valItem.value; // For label formatter param and highlight. + + option.seriesDataIndices = (valItem.payloadBatch || []).slice(); + } // When always show (e.g., handle used), remain + // original value and status. + else { + // If hide, value still need to be set, consider + // click legend to toggle axis blank. + !axisInfo.useHandle && (option.status = 'hide'); + } // If status is 'hide', should be no info in payload. + + + option.status === 'show' && outputAxesInfo.push({ + axisDim: axisInfo.axis.dim, + axisIndex: axisInfo.axis.model.componentIndex, + value: option.value + }); + }); + } + + function dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction) { + // Basic logic: If no showTip required, hideTip will be dispatched. + if (illegalPoint(point) || !dataByCoordSys.list.length) { + dispatchAction({ + type: 'hideTip' + }); + return; + } // In most case only one axis (or event one series is used). It is + // convinient to fetch payload.seriesIndex and payload.dataIndex + // dirtectly. So put the first seriesIndex and dataIndex of the first + // axis on the payload. + + + var sampleItem = ((dataByCoordSys.list[0].dataByAxis[0] || {}).seriesDataIndices || [])[0] || {}; + dispatchAction({ + type: 'showTip', + escapeConnect: true, + x: point[0], + y: point[1], + tooltipOption: payload.tooltipOption, + position: payload.position, + dataIndexInside: sampleItem.dataIndexInside, + dataIndex: sampleItem.dataIndex, + seriesIndex: sampleItem.seriesIndex, + dataByCoordSys: dataByCoordSys.list + }); + } + + function dispatchHighDownActually(axesInfo, dispatchAction, api) { + // FIXME + // highlight status modification shoule be a stage of main process? + // (Consider confilct (e.g., legend and axisPointer) and setOption) + var zr = api.getZr(); + var highDownKey = 'axisPointerLastHighlights'; + var lastHighlights = inner$c(zr)[highDownKey] || {}; + var newHighlights = inner$c(zr)[highDownKey] = {}; // Update highlight/downplay status according to axisPointer model. + // Build hash map and remove duplicate incidentally. + + each(axesInfo, function (axisInfo, key) { + var option = axisInfo.axisPointerModel.option; + option.status === 'show' && each(option.seriesDataIndices, function (batchItem) { + var key = batchItem.seriesIndex + ' | ' + batchItem.dataIndex; + newHighlights[key] = batchItem; + }); + }); // Diff. + + var toHighlight = []; + var toDownplay = []; + each(lastHighlights, function (batchItem, key) { + !newHighlights[key] && toDownplay.push(batchItem); + }); + each(newHighlights, function (batchItem, key) { + !lastHighlights[key] && toHighlight.push(batchItem); + }); + toDownplay.length && api.dispatchAction({ + type: 'downplay', + escapeConnect: true, + // Not blur others when highlight in axisPointer. + notBlur: true, + batch: toDownplay + }); + toHighlight.length && api.dispatchAction({ + type: 'highlight', + escapeConnect: true, + // Not blur others when highlight in axisPointer. + notBlur: true, + batch: toHighlight + }); + } + + function findInputAxisInfo(inputAxesInfo, axisInfo) { + for (var i = 0; i < (inputAxesInfo || []).length; i++) { + var inputAxisInfo = inputAxesInfo[i]; + + if (axisInfo.axis.dim === inputAxisInfo.axisDim && axisInfo.axis.model.componentIndex === inputAxisInfo.axisIndex) { + return inputAxisInfo; + } + } + } + + function makeMapperParam(axisInfo) { + var axisModel = axisInfo.axis.model; + var item = {}; + var dim = item.axisDim = axisInfo.axis.dim; + item.axisIndex = item[dim + 'AxisIndex'] = axisModel.componentIndex; + item.axisName = item[dim + 'AxisName'] = axisModel.name; + item.axisId = item[dim + 'AxisId'] = axisModel.id; + return item; + } + + function illegalPoint(point) { + return !point || point[0] == null || isNaN(point[0]) || point[1] == null || isNaN(point[1]); + } + + function install$s(registers) { + // CartesianAxisPointer is not supposed to be required here. But consider + // echarts.simple.js and online build tooltip, which only require gridSimple, + // CartesianAxisPointer should be able to required somewhere. + AxisView.registerAxisPointerClass('CartesianAxisPointer', CartesianAxisPointer); + registers.registerComponentModel(AxisPointerModel); + registers.registerComponentView(AxisPointerView); + registers.registerPreprocessor(function (option) { + // Always has a global axisPointerModel for default setting. + if (option) { + (!option.axisPointer || option.axisPointer.length === 0) && (option.axisPointer = {}); + var link = option.axisPointer.link; // Normalize to array to avoid object mergin. But if link + // is not set, remain null/undefined, otherwise it will + // override existent link setting. + + if (link && !isArray(link)) { + option.axisPointer.link = [link]; + } + } + }); // This process should proformed after coordinate systems created + // and series data processed. So put it on statistic processing stage. + + registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, function (ecModel, api) { + // Build axisPointerModel, mergin tooltip.axisPointer model for each axis. + // allAxesInfo should be updated when setOption performed. + ecModel.getComponent('axisPointer').coordSysAxesInfo = collect(ecModel, api); + }); // Broadcast to all views. + + registers.registerAction({ + type: 'updateAxisPointer', + event: 'updateAxisPointer', + update: ':updateAxisPointer' + }, axisTrigger); + } + + function install$t(registers) { + use(install$5); + use(install$s); + } + + var PolarAxisPointer = + /** @class */ + function (_super) { + __extends(PolarAxisPointer, _super); + + function PolarAxisPointer() { + return _super !== null && _super.apply(this, arguments) || this; + } + /** + * @override + */ + + + PolarAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) { + var axis = axisModel.axis; + + if (axis.dim === 'angle') { + this.animationThreshold = Math.PI / 18; + } + + var polar = axis.polar; + var otherAxis = polar.getOtherAxis(axis); + var otherExtent = otherAxis.getExtent(); + var coordValue = axis.dataToCoord(value); + var axisPointerType = axisPointerModel.get('type'); + + if (axisPointerType && axisPointerType !== 'none') { + var elStyle = buildElStyle(axisPointerModel); + var pointerOption = pointerShapeBuilder$1[axisPointerType](axis, polar, coordValue, otherExtent); + pointerOption.style = elStyle; + elOption.graphicKey = pointerOption.type; + elOption.pointer = pointerOption; + } + + var labelMargin = axisPointerModel.get(['label', 'margin']); + var labelPos = getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin); + buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos); + }; + + return PolarAxisPointer; + }(BaseAxisPointer); + + function getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin) { + var axis = axisModel.axis; + var coord = axis.dataToCoord(value); + var axisAngle = polar.getAngleAxis().getExtent()[0]; + axisAngle = axisAngle / 180 * Math.PI; + var radiusExtent = polar.getRadiusAxis().getExtent(); + var position; + var align; + var verticalAlign; + + if (axis.dim === 'radius') { + var transform = create$1(); + rotate(transform, transform, axisAngle); + translate(transform, transform, [polar.cx, polar.cy]); + position = applyTransform$1([coord, -labelMargin], transform); + var labelRotation = axisModel.getModel('axisLabel').get('rotate') || 0; // @ts-ignore + + var labelLayout = AxisBuilder.innerTextLayout(axisAngle, labelRotation * Math.PI / 180, -1); + align = labelLayout.textAlign; + verticalAlign = labelLayout.textVerticalAlign; + } else { + // angle axis + var r = radiusExtent[1]; + position = polar.coordToPoint([r + labelMargin, coord]); + var cx = polar.cx; + var cy = polar.cy; + align = Math.abs(position[0] - cx) / r < 0.3 ? 'center' : position[0] > cx ? 'left' : 'right'; + verticalAlign = Math.abs(position[1] - cy) / r < 0.3 ? 'middle' : position[1] > cy ? 'top' : 'bottom'; + } + + return { + position: position, + align: align, + verticalAlign: verticalAlign + }; + } + + var pointerShapeBuilder$1 = { + line: function (axis, polar, coordValue, otherExtent) { + return axis.dim === 'angle' ? { + type: 'Line', + shape: makeLineShape(polar.coordToPoint([otherExtent[0], coordValue]), polar.coordToPoint([otherExtent[1], coordValue])) + } : { + type: 'Circle', + shape: { + cx: polar.cx, + cy: polar.cy, + r: coordValue + } + }; + }, + shadow: function (axis, polar, coordValue, otherExtent) { + var bandWidth = Math.max(1, axis.getBandWidth()); + var radian = Math.PI / 180; + return axis.dim === 'angle' ? { + type: 'Sector', + shape: makeSectorShape(polar.cx, polar.cy, otherExtent[0], otherExtent[1], // In ECharts y is negative if angle is positive + (-coordValue - bandWidth / 2) * radian, (-coordValue + bandWidth / 2) * radian) + } : { + type: 'Sector', + shape: makeSectorShape(polar.cx, polar.cy, coordValue - bandWidth / 2, coordValue + bandWidth / 2, 0, Math.PI * 2) + }; + } + }; + + var PolarModel = + /** @class */ + function (_super) { + __extends(PolarModel, _super); + + function PolarModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = PolarModel.type; + return _this; + } + + PolarModel.prototype.findAxisModel = function (axisType) { + var foundAxisModel; + var ecModel = this.ecModel; + ecModel.eachComponent(axisType, function (axisModel) { + if (axisModel.getCoordSysModel() === this) { + foundAxisModel = axisModel; + } + }, this); + return foundAxisModel; + }; + + PolarModel.type = 'polar'; + PolarModel.dependencies = ['radiusAxis', 'angleAxis']; + PolarModel.defaultOption = { + // zlevel: 0, + z: 0, + center: ['50%', '50%'], + radius: '80%' + }; + return PolarModel; + }(ComponentModel); + + var PolarAxisModel = + /** @class */ + function (_super) { + __extends(PolarAxisModel, _super); + + function PolarAxisModel() { + return _super !== null && _super.apply(this, arguments) || this; + } + + PolarAxisModel.prototype.getCoordSysModel = function () { + return this.getReferringComponents('polar', SINGLE_REFERRING).models[0]; + }; + + PolarAxisModel.type = 'polarAxis'; + return PolarAxisModel; + }(ComponentModel); + + mixin(PolarAxisModel, AxisModelCommonMixin); + + var AngleAxisModel = + /** @class */ + function (_super) { + __extends(AngleAxisModel, _super); + + function AngleAxisModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = AngleAxisModel.type; + return _this; + } + + AngleAxisModel.type = 'angleAxis'; + return AngleAxisModel; + }(PolarAxisModel); + + var RadiusAxisModel = + /** @class */ + function (_super) { + __extends(RadiusAxisModel, _super); + + function RadiusAxisModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = RadiusAxisModel.type; + return _this; + } + + RadiusAxisModel.type = 'radiusAxis'; + return RadiusAxisModel; + }(PolarAxisModel); + + var RadiusAxis = + /** @class */ + function (_super) { + __extends(RadiusAxis, _super); + + function RadiusAxis(scale, radiusExtent) { + return _super.call(this, 'radius', scale, radiusExtent) || this; + } + + RadiusAxis.prototype.pointToData = function (point, clamp) { + return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1]; + }; + + return RadiusAxis; + }(Axis); + + RadiusAxis.prototype.dataToRadius = Axis.prototype.dataToCoord; + RadiusAxis.prototype.radiusToData = Axis.prototype.coordToData; + + var inner$d = makeInner(); + + var AngleAxis = + /** @class */ + function (_super) { + __extends(AngleAxis, _super); + + function AngleAxis(scale, angleExtent) { + return _super.call(this, 'angle', scale, angleExtent || [0, 360]) || this; + } + + AngleAxis.prototype.pointToData = function (point, clamp) { + return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1]; + }; + /** + * Only be called in category axis. + * Angle axis uses text height to decide interval + * + * @override + * @return {number} Auto interval for cateogry axis tick and label + */ + + + AngleAxis.prototype.calculateCategoryInterval = function () { + var axis = this; + var labelModel = axis.getLabelModel(); + var ordinalScale = axis.scale; + var ordinalExtent = ordinalScale.getExtent(); // Providing this method is for optimization: + // avoid generating a long array by `getTicks` + // in large category data case. + + var tickCount = ordinalScale.count(); + + if (ordinalExtent[1] - ordinalExtent[0] < 1) { + return 0; + } + + var tickValue = ordinalExtent[0]; + var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue); + var unitH = Math.abs(unitSpan); // Not precise, just use height as text width + // and each distance from axis line yet. + + var rect = getBoundingRect(tickValue == null ? '' : tickValue + '', labelModel.getFont(), 'center', 'top'); + var maxH = Math.max(rect.height, 7); + var dh = maxH / unitH; // 0/0 is NaN, 1/0 is Infinity. + + isNaN(dh) && (dh = Infinity); + var interval = Math.max(0, Math.floor(dh)); + var cache = inner$d(axis.model); + var lastAutoInterval = cache.lastAutoInterval; + var lastTickCount = cache.lastTickCount; // Use cache to keep interval stable while moving zoom window, + // otherwise the calculated interval might jitter when the zoom + // window size is close to the interval-changing size. + + if (lastAutoInterval != null && lastTickCount != null && Math.abs(lastAutoInterval - interval) <= 1 && Math.abs(lastTickCount - tickCount) <= 1 // Always choose the bigger one, otherwise the critical + // point is not the same when zooming in or zooming out. + && lastAutoInterval > interval) { + interval = lastAutoInterval; + } // Only update cache if cache not used, otherwise the + // changing of interval is too insensitive. + else { + cache.lastTickCount = tickCount; + cache.lastAutoInterval = interval; + } + + return interval; + }; + + return AngleAxis; + }(Axis); + + AngleAxis.prototype.dataToAngle = Axis.prototype.dataToCoord; + AngleAxis.prototype.angleToData = Axis.prototype.coordToData; + + var polarDimensions = ['radius', 'angle']; + + var Polar = + /** @class */ + function () { + function Polar(name) { + this.dimensions = polarDimensions; + this.type = 'polar'; + /** + * x of polar center + */ + + this.cx = 0; + /** + * y of polar center + */ + + this.cy = 0; + this._radiusAxis = new RadiusAxis(); + this._angleAxis = new AngleAxis(); + this.axisPointerEnabled = true; + this.name = name || ''; + this._radiusAxis.polar = this._angleAxis.polar = this; + } + /** + * If contain coord + */ + + + Polar.prototype.containPoint = function (point) { + var coord = this.pointToCoord(point); + return this._radiusAxis.contain(coord[0]) && this._angleAxis.contain(coord[1]); + }; + /** + * If contain data + */ + + + Polar.prototype.containData = function (data) { + return this._radiusAxis.containData(data[0]) && this._angleAxis.containData(data[1]); + }; + + Polar.prototype.getAxis = function (dim) { + var key = '_' + dim + 'Axis'; + return this[key]; + }; + + Polar.prototype.getAxes = function () { + return [this._radiusAxis, this._angleAxis]; + }; + /** + * Get axes by type of scale + */ + + + Polar.prototype.getAxesByScale = function (scaleType) { + var axes = []; + var angleAxis = this._angleAxis; + var radiusAxis = this._radiusAxis; + angleAxis.scale.type === scaleType && axes.push(angleAxis); + radiusAxis.scale.type === scaleType && axes.push(radiusAxis); + return axes; + }; + + Polar.prototype.getAngleAxis = function () { + return this._angleAxis; + }; + + Polar.prototype.getRadiusAxis = function () { + return this._radiusAxis; + }; + + Polar.prototype.getOtherAxis = function (axis) { + var angleAxis = this._angleAxis; + return axis === angleAxis ? this._radiusAxis : angleAxis; + }; + /** + * Base axis will be used on stacking. + * + */ + + + Polar.prototype.getBaseAxis = function () { + return this.getAxesByScale('ordinal')[0] || this.getAxesByScale('time')[0] || this.getAngleAxis(); + }; + + Polar.prototype.getTooltipAxes = function (dim) { + var baseAxis = dim != null && dim !== 'auto' ? this.getAxis(dim) : this.getBaseAxis(); + return { + baseAxes: [baseAxis], + otherAxes: [this.getOtherAxis(baseAxis)] + }; + }; + /** + * Convert a single data item to (x, y) point. + * Parameter data is an array which the first element is radius and the second is angle + */ + + + Polar.prototype.dataToPoint = function (data, clamp) { + return this.coordToPoint([this._radiusAxis.dataToRadius(data[0], clamp), this._angleAxis.dataToAngle(data[1], clamp)]); + }; + /** + * Convert a (x, y) point to data + */ + + + Polar.prototype.pointToData = function (point, clamp) { + var coord = this.pointToCoord(point); + return [this._radiusAxis.radiusToData(coord[0], clamp), this._angleAxis.angleToData(coord[1], clamp)]; + }; + /** + * Convert a (x, y) point to (radius, angle) coord + */ + + + Polar.prototype.pointToCoord = function (point) { + var dx = point[0] - this.cx; + var dy = point[1] - this.cy; + var angleAxis = this.getAngleAxis(); + var extent = angleAxis.getExtent(); + var minAngle = Math.min(extent[0], extent[1]); + var maxAngle = Math.max(extent[0], extent[1]); // Fix fixed extent in polarCreator + // FIXME + + angleAxis.inverse ? minAngle = maxAngle - 360 : maxAngle = minAngle + 360; + var radius = Math.sqrt(dx * dx + dy * dy); + dx /= radius; + dy /= radius; + var radian = Math.atan2(-dy, dx) / Math.PI * 180; // move to angleExtent + + var dir = radian < minAngle ? 1 : -1; + + while (radian < minAngle || radian > maxAngle) { + radian += dir * 360; + } + + return [radius, radian]; + }; + /** + * Convert a (radius, angle) coord to (x, y) point + */ + + + Polar.prototype.coordToPoint = function (coord) { + var radius = coord[0]; + var radian = coord[1] / 180 * Math.PI; + var x = Math.cos(radian) * radius + this.cx; // Inverse the y + + var y = -Math.sin(radian) * radius + this.cy; + return [x, y]; + }; + /** + * Get ring area of cartesian. + * Area will have a contain function to determine if a point is in the coordinate system. + */ + + + Polar.prototype.getArea = function () { + var angleAxis = this.getAngleAxis(); + var radiusAxis = this.getRadiusAxis(); + var radiusExtent = radiusAxis.getExtent().slice(); + radiusExtent[0] > radiusExtent[1] && radiusExtent.reverse(); + var angleExtent = angleAxis.getExtent(); + var RADIAN = Math.PI / 180; + return { + cx: this.cx, + cy: this.cy, + r0: radiusExtent[0], + r: radiusExtent[1], + startAngle: -angleExtent[0] * RADIAN, + endAngle: -angleExtent[1] * RADIAN, + clockwise: angleAxis.inverse, + contain: function (x, y) { + // It's a ring shape. + // Start angle and end angle don't matter + var dx = x - this.cx; + var dy = y - this.cy; // minus a tiny value 1e-4 to avoid being clipped unexpectedly + + var d2 = dx * dx + dy * dy - 1e-4; + var r = this.r; + var r0 = this.r0; + return d2 <= r * r && d2 >= r0 * r0; + } + }; + }; + + Polar.prototype.convertToPixel = function (ecModel, finder, value) { + var coordSys = getCoordSys$2(finder); + return coordSys === this ? this.dataToPoint(value) : null; + }; + + Polar.prototype.convertFromPixel = function (ecModel, finder, pixel) { + var coordSys = getCoordSys$2(finder); + return coordSys === this ? this.pointToData(pixel) : null; + }; + + return Polar; + }(); + + function getCoordSys$2(finder) { + var seriesModel = finder.seriesModel; + var polarModel = finder.polarModel; + return polarModel && polarModel.coordinateSystem || seriesModel && seriesModel.coordinateSystem; + } + + /** + * Resize method bound to the polar + */ + + function resizePolar(polar, polarModel, api) { + var center = polarModel.get('center'); + var width = api.getWidth(); + var height = api.getHeight(); + polar.cx = parsePercent$1(center[0], width); + polar.cy = parsePercent$1(center[1], height); + var radiusAxis = polar.getRadiusAxis(); + var size = Math.min(width, height) / 2; + var radius = polarModel.get('radius'); + + if (radius == null) { + radius = [0, '100%']; + } else if (!isArray(radius)) { + // r0 = 0 + radius = [0, radius]; + } + + var parsedRadius = [parsePercent$1(radius[0], size), parsePercent$1(radius[1], size)]; + radiusAxis.inverse ? radiusAxis.setExtent(parsedRadius[1], parsedRadius[0]) : radiusAxis.setExtent(parsedRadius[0], parsedRadius[1]); + } + /** + * Update polar + */ + + + function updatePolarScale(ecModel, api) { + var polar = this; + var angleAxis = polar.getAngleAxis(); + var radiusAxis = polar.getRadiusAxis(); // Reset scale + + angleAxis.scale.setExtent(Infinity, -Infinity); + radiusAxis.scale.setExtent(Infinity, -Infinity); + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.coordinateSystem === polar) { + var data_1 = seriesModel.getData(); + each(getDataDimensionsOnAxis(data_1, 'radius'), function (dim) { + radiusAxis.scale.unionExtentFromData(data_1, dim); + }); + each(getDataDimensionsOnAxis(data_1, 'angle'), function (dim) { + angleAxis.scale.unionExtentFromData(data_1, dim); + }); + } + }); + niceScaleExtent(angleAxis.scale, angleAxis.model); + niceScaleExtent(radiusAxis.scale, radiusAxis.model); // Fix extent of category angle axis + + if (angleAxis.type === 'category' && !angleAxis.onBand) { + var extent = angleAxis.getExtent(); + var diff = 360 / angleAxis.scale.count(); + angleAxis.inverse ? extent[1] += diff : extent[1] -= diff; + angleAxis.setExtent(extent[0], extent[1]); + } + } + + function isAngleAxisModel(axisModel) { + return axisModel.mainType === 'angleAxis'; + } + /** + * Set common axis properties + */ + + + function setAxis(axis, axisModel) { + axis.type = axisModel.get('type'); + axis.scale = createScaleByModel(axisModel); + axis.onBand = axisModel.get('boundaryGap') && axis.type === 'category'; + axis.inverse = axisModel.get('inverse'); + + if (isAngleAxisModel(axisModel)) { + axis.inverse = axis.inverse !== axisModel.get('clockwise'); + var startAngle = axisModel.get('startAngle'); + axis.setExtent(startAngle, startAngle + (axis.inverse ? -360 : 360)); + } // Inject axis instance + + + axisModel.axis = axis; + axis.model = axisModel; + } + + var polarCreator = { + dimensions: polarDimensions, + create: function (ecModel, api) { + var polarList = []; + ecModel.eachComponent('polar', function (polarModel, idx) { + var polar = new Polar(idx + ''); // Inject resize and update method + + polar.update = updatePolarScale; + var radiusAxis = polar.getRadiusAxis(); + var angleAxis = polar.getAngleAxis(); + var radiusAxisModel = polarModel.findAxisModel('radiusAxis'); + var angleAxisModel = polarModel.findAxisModel('angleAxis'); + setAxis(radiusAxis, radiusAxisModel); + setAxis(angleAxis, angleAxisModel); + resizePolar(polar, polarModel, api); + polarList.push(polar); + polarModel.coordinateSystem = polar; + polar.model = polarModel; + }); // Inject coordinateSystem to series + + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'polar') { + var polarModel = seriesModel.getReferringComponents('polar', SINGLE_REFERRING).models[0]; + + if ("development" !== 'production') { + if (!polarModel) { + throw new Error('Polar "' + retrieve(seriesModel.get('polarIndex'), seriesModel.get('polarId'), 0) + '" not found'); + } + } + + seriesModel.coordinateSystem = polarModel.coordinateSystem; + } + }); + return polarList; + } + }; + + var elementList$1 = ['axisLine', 'axisLabel', 'axisTick', 'minorTick', 'splitLine', 'minorSplitLine', 'splitArea']; + + function getAxisLineShape(polar, rExtent, angle) { + rExtent[1] > rExtent[0] && (rExtent = rExtent.slice().reverse()); + var start = polar.coordToPoint([rExtent[0], angle]); + var end = polar.coordToPoint([rExtent[1], angle]); + return { + x1: start[0], + y1: start[1], + x2: end[0], + y2: end[1] + }; + } + + function getRadiusIdx(polar) { + var radiusAxis = polar.getRadiusAxis(); + return radiusAxis.inverse ? 0 : 1; + } // Remove the last tick which will overlap the first tick + + + function fixAngleOverlap(list) { + var firstItem = list[0]; + var lastItem = list[list.length - 1]; + + if (firstItem && lastItem && Math.abs(Math.abs(firstItem.coord - lastItem.coord) - 360) < 1e-4) { + list.pop(); + } + } + + var AngleAxisView = + /** @class */ + function (_super) { + __extends(AngleAxisView, _super); + + function AngleAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = AngleAxisView.type; + _this.axisPointerClass = 'PolarAxisPointer'; + return _this; + } + + AngleAxisView.prototype.render = function (angleAxisModel, ecModel) { + this.group.removeAll(); + + if (!angleAxisModel.get('show')) { + return; + } + + var angleAxis = angleAxisModel.axis; + var polar = angleAxis.polar; + var radiusExtent = polar.getRadiusAxis().getExtent(); + var ticksAngles = angleAxis.getTicksCoords(); + var minorTickAngles = angleAxis.getMinorTicksCoords(); + var labels = map(angleAxis.getViewLabels(), function (labelItem) { + labelItem = clone(labelItem); + var scale = angleAxis.scale; + var tickValue = scale.type === 'ordinal' ? scale.getRawOrdinalNumber(labelItem.tickValue) : labelItem.tickValue; + labelItem.coord = angleAxis.dataToCoord(tickValue); + return labelItem; + }); + fixAngleOverlap(labels); + fixAngleOverlap(ticksAngles); + each(elementList$1, function (name) { + if (angleAxisModel.get([name, 'show']) && (!angleAxis.scale.isBlank() || name === 'axisLine')) { + angelAxisElementsBuilders[name](this.group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent, labels); + } + }, this); + }; + + AngleAxisView.type = 'angleAxis'; + return AngleAxisView; + }(AxisView); + + var angelAxisElementsBuilders = { + axisLine: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) { + var lineStyleModel = angleAxisModel.getModel(['axisLine', 'lineStyle']); // extent id of the axis radius (r0 and r) + + var rId = getRadiusIdx(polar); + var r0Id = rId ? 0 : 1; + var shape; + + if (radiusExtent[r0Id] === 0) { + shape = new Circle({ + shape: { + cx: polar.cx, + cy: polar.cy, + r: radiusExtent[rId] + }, + style: lineStyleModel.getLineStyle(), + z2: 1, + silent: true + }); + } else { + shape = new Ring({ + shape: { + cx: polar.cx, + cy: polar.cy, + r: radiusExtent[rId], + r0: radiusExtent[r0Id] + }, + style: lineStyleModel.getLineStyle(), + z2: 1, + silent: true + }); + } + + shape.style.fill = null; + group.add(shape); + }, + axisTick: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) { + var tickModel = angleAxisModel.getModel('axisTick'); + var tickLen = (tickModel.get('inside') ? -1 : 1) * tickModel.get('length'); + var radius = radiusExtent[getRadiusIdx(polar)]; + var lines = map(ticksAngles, function (tickAngleItem) { + return new Line({ + shape: getAxisLineShape(polar, [radius, radius + tickLen], tickAngleItem.coord) + }); + }); + group.add(mergePath$1(lines, { + style: defaults(tickModel.getModel('lineStyle').getLineStyle(), { + stroke: angleAxisModel.get(['axisLine', 'lineStyle', 'color']) + }) + })); + }, + minorTick: function (group, angleAxisModel, polar, tickAngles, minorTickAngles, radiusExtent) { + if (!minorTickAngles.length) { + return; + } + + var tickModel = angleAxisModel.getModel('axisTick'); + var minorTickModel = angleAxisModel.getModel('minorTick'); + var tickLen = (tickModel.get('inside') ? -1 : 1) * minorTickModel.get('length'); + var radius = radiusExtent[getRadiusIdx(polar)]; + var lines = []; + + for (var i = 0; i < minorTickAngles.length; i++) { + for (var k = 0; k < minorTickAngles[i].length; k++) { + lines.push(new Line({ + shape: getAxisLineShape(polar, [radius, radius + tickLen], minorTickAngles[i][k].coord) + })); + } + } + + group.add(mergePath$1(lines, { + style: defaults(minorTickModel.getModel('lineStyle').getLineStyle(), defaults(tickModel.getLineStyle(), { + stroke: angleAxisModel.get(['axisLine', 'lineStyle', 'color']) + })) + })); + }, + axisLabel: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent, labels) { + var rawCategoryData = angleAxisModel.getCategories(true); + var commonLabelModel = angleAxisModel.getModel('axisLabel'); + var labelMargin = commonLabelModel.get('margin'); + var triggerEvent = angleAxisModel.get('triggerEvent'); // Use length of ticksAngles because it may remove the last tick to avoid overlapping + + each(labels, function (labelItem, idx) { + var labelModel = commonLabelModel; + var tickValue = labelItem.tickValue; + var r = radiusExtent[getRadiusIdx(polar)]; + var p = polar.coordToPoint([r + labelMargin, labelItem.coord]); + var cx = polar.cx; + var cy = polar.cy; + var labelTextAlign = Math.abs(p[0] - cx) / r < 0.3 ? 'center' : p[0] > cx ? 'left' : 'right'; + var labelTextVerticalAlign = Math.abs(p[1] - cy) / r < 0.3 ? 'middle' : p[1] > cy ? 'top' : 'bottom'; + + if (rawCategoryData && rawCategoryData[tickValue]) { + var rawCategoryItem = rawCategoryData[tickValue]; + + if (isObject(rawCategoryItem) && rawCategoryItem.textStyle) { + labelModel = new Model(rawCategoryItem.textStyle, commonLabelModel, commonLabelModel.ecModel); + } + } + + var textEl = new ZRText({ + silent: AxisBuilder.isLabelSilent(angleAxisModel), + style: createTextStyle(labelModel, { + x: p[0], + y: p[1], + fill: labelModel.getTextColor() || angleAxisModel.get(['axisLine', 'lineStyle', 'color']), + text: labelItem.formattedLabel, + align: labelTextAlign, + verticalAlign: labelTextVerticalAlign + }) + }); + group.add(textEl); // Pack data for mouse event + + if (triggerEvent) { + var eventData = AxisBuilder.makeAxisEventDataBase(angleAxisModel); + eventData.targetType = 'axisLabel'; + eventData.value = labelItem.rawLabel; + getECData(textEl).eventData = eventData; + } + }, this); + }, + splitLine: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) { + var splitLineModel = angleAxisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + var lineCount = 0; + lineColors = lineColors instanceof Array ? lineColors : [lineColors]; + var splitLines = []; + + for (var i = 0; i < ticksAngles.length; i++) { + var colorIndex = lineCount++ % lineColors.length; + splitLines[colorIndex] = splitLines[colorIndex] || []; + splitLines[colorIndex].push(new Line({ + shape: getAxisLineShape(polar, radiusExtent, ticksAngles[i].coord) + })); + } // Simple optimization + // Batching the lines if color are the same + + + for (var i = 0; i < splitLines.length; i++) { + group.add(mergePath$1(splitLines[i], { + style: defaults({ + stroke: lineColors[i % lineColors.length] + }, lineStyleModel.getLineStyle()), + silent: true, + z: angleAxisModel.get('z') + })); + } + }, + minorSplitLine: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) { + if (!minorTickAngles.length) { + return; + } + + var minorSplitLineModel = angleAxisModel.getModel('minorSplitLine'); + var lineStyleModel = minorSplitLineModel.getModel('lineStyle'); + var lines = []; + + for (var i = 0; i < minorTickAngles.length; i++) { + for (var k = 0; k < minorTickAngles[i].length; k++) { + lines.push(new Line({ + shape: getAxisLineShape(polar, radiusExtent, minorTickAngles[i][k].coord) + })); + } + } + + group.add(mergePath$1(lines, { + style: lineStyleModel.getLineStyle(), + silent: true, + z: angleAxisModel.get('z') + })); + }, + splitArea: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) { + if (!ticksAngles.length) { + return; + } + + var splitAreaModel = angleAxisModel.getModel('splitArea'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var areaColors = areaStyleModel.get('color'); + var lineCount = 0; + areaColors = areaColors instanceof Array ? areaColors : [areaColors]; + var splitAreas = []; + var RADIAN = Math.PI / 180; + var prevAngle = -ticksAngles[0].coord * RADIAN; + var r0 = Math.min(radiusExtent[0], radiusExtent[1]); + var r1 = Math.max(radiusExtent[0], radiusExtent[1]); + var clockwise = angleAxisModel.get('clockwise'); + + for (var i = 1, len = ticksAngles.length; i <= len; i++) { + var coord = i === len ? ticksAngles[0].coord : ticksAngles[i].coord; + var colorIndex = lineCount++ % areaColors.length; + splitAreas[colorIndex] = splitAreas[colorIndex] || []; + splitAreas[colorIndex].push(new Sector({ + shape: { + cx: polar.cx, + cy: polar.cy, + r0: r0, + r: r1, + startAngle: prevAngle, + endAngle: -coord * RADIAN, + clockwise: clockwise + }, + silent: true + })); + prevAngle = -coord * RADIAN; + } // Simple optimization + // Batching the lines if color are the same + + + for (var i = 0; i < splitAreas.length; i++) { + group.add(mergePath$1(splitAreas[i], { + style: defaults({ + fill: areaColors[i % areaColors.length] + }, areaStyleModel.getAreaStyle()), + silent: true + })); + } + } + }; + + var axisBuilderAttrs$2 = ['axisLine', 'axisTickLabel', 'axisName']; + var selfBuilderAttrs$1 = ['splitLine', 'splitArea', 'minorSplitLine']; + + var RadiusAxisView = + /** @class */ + function (_super) { + __extends(RadiusAxisView, _super); + + function RadiusAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = RadiusAxisView.type; + _this.axisPointerClass = 'PolarAxisPointer'; + return _this; + } + + RadiusAxisView.prototype.render = function (radiusAxisModel, ecModel) { + this.group.removeAll(); + + if (!radiusAxisModel.get('show')) { + return; + } + + var oldAxisGroup = this._axisGroup; + var newAxisGroup = this._axisGroup = new Group(); + this.group.add(newAxisGroup); + var radiusAxis = radiusAxisModel.axis; + var polar = radiusAxis.polar; + var angleAxis = polar.getAngleAxis(); + var ticksCoords = radiusAxis.getTicksCoords(); + var minorTicksCoords = radiusAxis.getMinorTicksCoords(); + var axisAngle = angleAxis.getExtent()[0]; + var radiusExtent = radiusAxis.getExtent(); + var layout = layoutAxis(polar, radiusAxisModel, axisAngle); + var axisBuilder = new AxisBuilder(radiusAxisModel, layout); + each(axisBuilderAttrs$2, axisBuilder.add, axisBuilder); + newAxisGroup.add(axisBuilder.getGroup()); + groupTransition(oldAxisGroup, newAxisGroup, radiusAxisModel); + each(selfBuilderAttrs$1, function (name) { + if (radiusAxisModel.get([name, 'show']) && !radiusAxis.scale.isBlank()) { + axisElementBuilders$1[name](this.group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords, minorTicksCoords); + } + }, this); + }; + + RadiusAxisView.type = 'radiusAxis'; + return RadiusAxisView; + }(AxisView); + + var axisElementBuilders$1 = { + splitLine: function (group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) { + var splitLineModel = radiusAxisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + var lineCount = 0; + lineColors = lineColors instanceof Array ? lineColors : [lineColors]; + var splitLines = []; + + for (var i = 0; i < ticksCoords.length; i++) { + var colorIndex = lineCount++ % lineColors.length; + splitLines[colorIndex] = splitLines[colorIndex] || []; + splitLines[colorIndex].push(new Circle({ + shape: { + cx: polar.cx, + cy: polar.cy, + // ensure circle radius >= 0 + r: Math.max(ticksCoords[i].coord, 0) + } + })); + } // Simple optimization + // Batching the lines if color are the same + + + for (var i = 0; i < splitLines.length; i++) { + group.add(mergePath$1(splitLines[i], { + style: defaults({ + stroke: lineColors[i % lineColors.length], + fill: null + }, lineStyleModel.getLineStyle()), + silent: true + })); + } + }, + minorSplitLine: function (group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords, minorTicksCoords) { + if (!minorTicksCoords.length) { + return; + } + + var minorSplitLineModel = radiusAxisModel.getModel('minorSplitLine'); + var lineStyleModel = minorSplitLineModel.getModel('lineStyle'); + var lines = []; + + for (var i = 0; i < minorTicksCoords.length; i++) { + for (var k = 0; k < minorTicksCoords[i].length; k++) { + lines.push(new Circle({ + shape: { + cx: polar.cx, + cy: polar.cy, + r: minorTicksCoords[i][k].coord + } + })); + } + } + + group.add(mergePath$1(lines, { + style: defaults({ + fill: null + }, lineStyleModel.getLineStyle()), + silent: true + })); + }, + splitArea: function (group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) { + if (!ticksCoords.length) { + return; + } + + var splitAreaModel = radiusAxisModel.getModel('splitArea'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var areaColors = areaStyleModel.get('color'); + var lineCount = 0; + areaColors = areaColors instanceof Array ? areaColors : [areaColors]; + var splitAreas = []; + var prevRadius = ticksCoords[0].coord; + + for (var i = 1; i < ticksCoords.length; i++) { + var colorIndex = lineCount++ % areaColors.length; + splitAreas[colorIndex] = splitAreas[colorIndex] || []; + splitAreas[colorIndex].push(new Sector({ + shape: { + cx: polar.cx, + cy: polar.cy, + r0: prevRadius, + r: ticksCoords[i].coord, + startAngle: 0, + endAngle: Math.PI * 2 + }, + silent: true + })); + prevRadius = ticksCoords[i].coord; + } // Simple optimization + // Batching the lines if color are the same + + + for (var i = 0; i < splitAreas.length; i++) { + group.add(mergePath$1(splitAreas[i], { + style: defaults({ + fill: areaColors[i % areaColors.length] + }, areaStyleModel.getAreaStyle()), + silent: true + })); + } + } + }; + /** + * @inner + */ + + function layoutAxis(polar, radiusAxisModel, axisAngle) { + return { + position: [polar.cx, polar.cy], + rotation: axisAngle / 180 * Math.PI, + labelDirection: -1, + tickDirection: -1, + nameDirection: 1, + labelRotate: radiusAxisModel.getModel('axisLabel').get('rotate'), + // Over splitLine and splitArea + z2: 1 + }; + } + + function getSeriesStackId$1(seriesModel) { + return seriesModel.get('stack') || '__ec_stack_' + seriesModel.seriesIndex; + } + + function getAxisKey$1(polar, axis) { + return axis.dim + polar.model.componentIndex; + } + + function barLayoutPolar(seriesType, ecModel, api) { + var lastStackCoords = {}; + var barWidthAndOffset = calRadialBar(filter(ecModel.getSeriesByType(seriesType), function (seriesModel) { + return !ecModel.isSeriesFiltered(seriesModel) && seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'polar'; + })); + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + // Check series coordinate, do layout for polar only + if (seriesModel.coordinateSystem.type !== 'polar') { + return; + } + + var data = seriesModel.getData(); + var polar = seriesModel.coordinateSystem; + var baseAxis = polar.getBaseAxis(); + var axisKey = getAxisKey$1(polar, baseAxis); + var stackId = getSeriesStackId$1(seriesModel); + var columnLayoutInfo = barWidthAndOffset[axisKey][stackId]; + var columnOffset = columnLayoutInfo.offset; + var columnWidth = columnLayoutInfo.width; + var valueAxis = polar.getOtherAxis(baseAxis); + var cx = seriesModel.coordinateSystem.cx; + var cy = seriesModel.coordinateSystem.cy; + var barMinHeight = seriesModel.get('barMinHeight') || 0; + var barMinAngle = seriesModel.get('barMinAngle') || 0; + lastStackCoords[stackId] = lastStackCoords[stackId] || []; + var valueDim = data.mapDimension(valueAxis.dim); + var baseDim = data.mapDimension(baseAxis.dim); + var stacked = isDimensionStacked(data, valueDim + /*, baseDim*/ + ); + var clampLayout = baseAxis.dim !== 'radius' || !seriesModel.get('roundCap', true); + var valueAxisStart = valueAxis.dataToCoord(0); + + for (var idx = 0, len = data.count(); idx < len; idx++) { + var value = data.get(valueDim, idx); + var baseValue = data.get(baseDim, idx); + var sign = value >= 0 ? 'p' : 'n'; + var baseCoord = valueAxisStart; // Because of the barMinHeight, we can not use the value in + // stackResultDimension directly. + // Only ordinal axis can be stacked. + + if (stacked) { + if (!lastStackCoords[stackId][baseValue]) { + lastStackCoords[stackId][baseValue] = { + p: valueAxisStart, + n: valueAxisStart // Negative stack + + }; + } // Should also consider #4243 + + + baseCoord = lastStackCoords[stackId][baseValue][sign]; + } + + var r0 = void 0; + var r = void 0; + var startAngle = void 0; + var endAngle = void 0; // radial sector + + if (valueAxis.dim === 'radius') { + var radiusSpan = valueAxis.dataToCoord(value) - valueAxisStart; + var angle = baseAxis.dataToCoord(baseValue); + + if (Math.abs(radiusSpan) < barMinHeight) { + radiusSpan = (radiusSpan < 0 ? -1 : 1) * barMinHeight; + } + + r0 = baseCoord; + r = baseCoord + radiusSpan; + startAngle = angle - columnOffset; + endAngle = startAngle - columnWidth; + stacked && (lastStackCoords[stackId][baseValue][sign] = r); + } // tangential sector + else { + var angleSpan = valueAxis.dataToCoord(value, clampLayout) - valueAxisStart; + var radius = baseAxis.dataToCoord(baseValue); + + if (Math.abs(angleSpan) < barMinAngle) { + angleSpan = (angleSpan < 0 ? -1 : 1) * barMinAngle; + } + + r0 = radius + columnOffset; + r = r0 + columnWidth; + startAngle = baseCoord; + endAngle = baseCoord + angleSpan; // if the previous stack is at the end of the ring, + // add a round to differentiate it from origin + // let extent = angleAxis.getExtent(); + // let stackCoord = angle; + // if (stackCoord === extent[0] && value > 0) { + // stackCoord = extent[1]; + // } + // else if (stackCoord === extent[1] && value < 0) { + // stackCoord = extent[0]; + // } + + stacked && (lastStackCoords[stackId][baseValue][sign] = endAngle); + } + + data.setItemLayout(idx, { + cx: cx, + cy: cy, + r0: r0, + r: r, + // Consider that positive angle is anti-clockwise, + // while positive radian of sector is clockwise + startAngle: -startAngle * Math.PI / 180, + endAngle: -endAngle * Math.PI / 180, + + /** + * Keep the same logic with bar in catesion: use end value to + * control direction. Notice that if clockwise is true (by + * default), the sector will always draw clockwisely, no matter + * whether endAngle is greater or less than startAngle. + */ + clockwise: startAngle >= endAngle + }); + } + }); + } + /** + * Calculate bar width and offset for radial bar charts + */ + + + function calRadialBar(barSeries) { + // Columns info on each category axis. Key is polar name + var columnsMap = {}; + each(barSeries, function (seriesModel, idx) { + var data = seriesModel.getData(); + var polar = seriesModel.coordinateSystem; + var baseAxis = polar.getBaseAxis(); + var axisKey = getAxisKey$1(polar, baseAxis); + var axisExtent = baseAxis.getExtent(); + var bandWidth = baseAxis.type === 'category' ? baseAxis.getBandWidth() : Math.abs(axisExtent[1] - axisExtent[0]) / data.count(); + var columnsOnAxis = columnsMap[axisKey] || { + bandWidth: bandWidth, + remainedWidth: bandWidth, + autoWidthCount: 0, + categoryGap: '20%', + gap: '30%', + stacks: {} + }; + var stacks = columnsOnAxis.stacks; + columnsMap[axisKey] = columnsOnAxis; + var stackId = getSeriesStackId$1(seriesModel); + + if (!stacks[stackId]) { + columnsOnAxis.autoWidthCount++; + } + + stacks[stackId] = stacks[stackId] || { + width: 0, + maxWidth: 0 + }; + var barWidth = parsePercent$1(seriesModel.get('barWidth'), bandWidth); + var barMaxWidth = parsePercent$1(seriesModel.get('barMaxWidth'), bandWidth); + var barGap = seriesModel.get('barGap'); + var barCategoryGap = seriesModel.get('barCategoryGap'); + + if (barWidth && !stacks[stackId].width) { + barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth); + stacks[stackId].width = barWidth; + columnsOnAxis.remainedWidth -= barWidth; + } + + barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth); + barGap != null && (columnsOnAxis.gap = barGap); + barCategoryGap != null && (columnsOnAxis.categoryGap = barCategoryGap); + }); + var result = {}; + each(columnsMap, function (columnsOnAxis, coordSysName) { + result[coordSysName] = {}; + var stacks = columnsOnAxis.stacks; + var bandWidth = columnsOnAxis.bandWidth; + var categoryGap = parsePercent$1(columnsOnAxis.categoryGap, bandWidth); + var barGapPercent = parsePercent$1(columnsOnAxis.gap, 1); + var remainedWidth = columnsOnAxis.remainedWidth; + var autoWidthCount = columnsOnAxis.autoWidthCount; + var autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); // Find if any auto calculated bar exceeded maxBarWidth + + each(stacks, function (column, stack) { + var maxWidth = column.maxWidth; + + if (maxWidth && maxWidth < autoWidth) { + maxWidth = Math.min(maxWidth, remainedWidth); + + if (column.width) { + maxWidth = Math.min(maxWidth, column.width); + } + + remainedWidth -= maxWidth; + column.width = maxWidth; + autoWidthCount--; + } + }); // Recalculate width again + + autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + var widthSum = 0; + var lastColumn; + each(stacks, function (column, idx) { + if (!column.width) { + column.width = autoWidth; + } + + lastColumn = column; + widthSum += column.width * (1 + barGapPercent); + }); + + if (lastColumn) { + widthSum -= lastColumn.width * barGapPercent; + } + + var offset = -widthSum / 2; + each(stacks, function (column, stackId) { + result[coordSysName][stackId] = result[coordSysName][stackId] || { + offset: offset, + width: column.width + }; + offset += column.width * (1 + barGapPercent); + }); + }); + return result; + } + + var angleAxisExtraOption = { + startAngle: 90, + clockwise: true, + splitNumber: 12, + axisLabel: { + rotate: 0 + } + }; + var radiusAxisExtraOption = { + splitNumber: 5 + }; + + var PolarView = + /** @class */ + function (_super) { + __extends(PolarView, _super); + + function PolarView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = PolarView.type; + return _this; + } + + PolarView.type = 'polar'; + return PolarView; + }(ComponentView); + + function install$u(registers) { + use(install$s); + AxisView.registerAxisPointerClass('PolarAxisPointer', PolarAxisPointer); + registers.registerCoordinateSystem('polar', polarCreator); + registers.registerComponentModel(PolarModel); + registers.registerComponentView(PolarView); // Model and view for angleAxis and radiusAxis + + axisModelCreator(registers, 'angle', AngleAxisModel, angleAxisExtraOption); + axisModelCreator(registers, 'radius', RadiusAxisModel, radiusAxisExtraOption); + registers.registerComponentView(AngleAxisView); + registers.registerComponentView(RadiusAxisView); + registers.registerLayout(curry(barLayoutPolar, 'bar')); + } + + function layout$2(axisModel, opt) { + opt = opt || {}; + var single = axisModel.coordinateSystem; + var axis = axisModel.axis; + var layout = {}; + var axisPosition = axis.position; + var orient = axis.orient; + var rect = single.getRect(); + var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height]; + var positionMap = { + horizontal: { + top: rectBound[2], + bottom: rectBound[3] + }, + vertical: { + left: rectBound[0], + right: rectBound[1] + } + }; + layout.position = [orient === 'vertical' ? positionMap.vertical[axisPosition] : rectBound[0], orient === 'horizontal' ? positionMap.horizontal[axisPosition] : rectBound[3]]; + var r = { + horizontal: 0, + vertical: 1 + }; + layout.rotation = Math.PI / 2 * r[orient]; + var directionMap = { + top: -1, + bottom: 1, + right: 1, + left: -1 + }; + layout.labelDirection = layout.tickDirection = layout.nameDirection = directionMap[axisPosition]; + + if (axisModel.get(['axisTick', 'inside'])) { + layout.tickDirection = -layout.tickDirection; + } + + if (retrieve(opt.labelInside, axisModel.get(['axisLabel', 'inside']))) { + layout.labelDirection = -layout.labelDirection; + } + + var labelRotation = opt.rotate; + labelRotation == null && (labelRotation = axisModel.get(['axisLabel', 'rotate'])); + layout.labelRotation = axisPosition === 'top' ? -labelRotation : labelRotation; + layout.z2 = 1; + return layout; + } + + var axisBuilderAttrs$3 = ['axisLine', 'axisTickLabel', 'axisName']; + var selfBuilderAttrs$2 = ['splitArea', 'splitLine']; + + var SingleAxisView = + /** @class */ + function (_super) { + __extends(SingleAxisView, _super); + + function SingleAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SingleAxisView.type; + _this.axisPointerClass = 'SingleAxisPointer'; + return _this; + } + + SingleAxisView.prototype.render = function (axisModel, ecModel, api, payload) { + var group = this.group; + group.removeAll(); + var oldAxisGroup = this._axisGroup; + this._axisGroup = new Group(); + var layout = layout$2(axisModel); + var axisBuilder = new AxisBuilder(axisModel, layout); + each(axisBuilderAttrs$3, axisBuilder.add, axisBuilder); + group.add(this._axisGroup); + group.add(axisBuilder.getGroup()); + each(selfBuilderAttrs$2, function (name) { + if (axisModel.get([name, 'show'])) { + axisElementBuilders$2[name](this, this.group, this._axisGroup, axisModel); + } + }, this); + groupTransition(oldAxisGroup, this._axisGroup, axisModel); + + _super.prototype.render.call(this, axisModel, ecModel, api, payload); + }; + + SingleAxisView.prototype.remove = function () { + rectCoordAxisHandleRemove(this); + }; + + SingleAxisView.type = 'singleAxis'; + return SingleAxisView; + }(AxisView); + + var axisElementBuilders$2 = { + splitLine: function (axisView, group, axisGroup, axisModel) { + var axis = axisModel.axis; + + if (axis.scale.isBlank()) { + return; + } + + var splitLineModel = axisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + lineColors = lineColors instanceof Array ? lineColors : [lineColors]; + var gridRect = axisModel.coordinateSystem.getRect(); + var isHorizontal = axis.isHorizontal(); + var splitLines = []; + var lineCount = 0; + var ticksCoords = axis.getTicksCoords({ + tickModel: splitLineModel + }); + var p1 = []; + var p2 = []; + + for (var i = 0; i < ticksCoords.length; ++i) { + var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord); + + if (isHorizontal) { + p1[0] = tickCoord; + p1[1] = gridRect.y; + p2[0] = tickCoord; + p2[1] = gridRect.y + gridRect.height; + } else { + p1[0] = gridRect.x; + p1[1] = tickCoord; + p2[0] = gridRect.x + gridRect.width; + p2[1] = tickCoord; + } + + var colorIndex = lineCount++ % lineColors.length; + splitLines[colorIndex] = splitLines[colorIndex] || []; + splitLines[colorIndex].push(new Line({ + subPixelOptimize: true, + shape: { + x1: p1[0], + y1: p1[1], + x2: p2[0], + y2: p2[1] + }, + silent: true + })); + } + + var lineStyle = lineStyleModel.getLineStyle(['color']); + + for (var i = 0; i < splitLines.length; ++i) { + group.add(mergePath$1(splitLines[i], { + style: defaults({ + stroke: lineColors[i % lineColors.length] + }, lineStyle), + silent: true + })); + } + }, + splitArea: function (axisView, group, axisGroup, axisModel) { + rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, axisModel); + } + }; + + var SingleAxisModel = + /** @class */ + function (_super) { + __extends(SingleAxisModel, _super); + + function SingleAxisModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SingleAxisModel.type; + return _this; + } + + SingleAxisModel.prototype.getCoordSysModel = function () { + return this; + }; + + SingleAxisModel.type = 'singleAxis'; + SingleAxisModel.layoutMode = 'box'; + SingleAxisModel.defaultOption = { + left: '5%', + top: '5%', + right: '5%', + bottom: '5%', + type: 'value', + position: 'bottom', + orient: 'horizontal', + axisLine: { + show: true, + lineStyle: { + width: 1, + type: 'solid' + } + }, + // Single coordinate system and single axis is the, + // which is used as the parent tooltip model. + // same model, so we set default tooltip show as true. + tooltip: { + show: true + }, + axisTick: { + show: true, + length: 6, + lineStyle: { + width: 1 + } + }, + axisLabel: { + show: true, + interval: 'auto' + }, + splitLine: { + show: true, + lineStyle: { + type: 'dashed', + opacity: 0.2 + } + } + }; + return SingleAxisModel; + }(ComponentModel); + + mixin(SingleAxisModel, AxisModelCommonMixin.prototype); + + var SingleAxis = + /** @class */ + function (_super) { + __extends(SingleAxis, _super); + + function SingleAxis(dim, scale, coordExtent, axisType, position) { + var _this = _super.call(this, dim, scale, coordExtent) || this; + + _this.type = axisType || 'value'; + _this.position = position || 'bottom'; + return _this; + } + /** + * Judge the orient of the axis. + */ + + + SingleAxis.prototype.isHorizontal = function () { + var position = this.position; + return position === 'top' || position === 'bottom'; + }; + + SingleAxis.prototype.pointToData = function (point, clamp) { + return this.coordinateSystem.pointToData(point)[0]; + }; + + return SingleAxis; + }(Axis); + + var singleDimensions = ['single']; + /** + * Create a single coordinates system. + */ + + var Single = + /** @class */ + function () { + function Single(axisModel, ecModel, api) { + this.type = 'single'; + this.dimension = 'single'; + /** + * Add it just for draw tooltip. + */ + + this.dimensions = singleDimensions; + this.axisPointerEnabled = true; + this.model = axisModel; + + this._init(axisModel, ecModel, api); + } + /** + * Initialize single coordinate system. + */ + + + Single.prototype._init = function (axisModel, ecModel, api) { + var dim = this.dimension; + var axis = new SingleAxis(dim, createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisModel.get('position')); + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); + axis.orient = axisModel.get('orient'); + axisModel.axis = axis; + axis.model = axisModel; + axis.coordinateSystem = this; + this._axis = axis; + }; + /** + * Update axis scale after data processed + */ + + + Single.prototype.update = function (ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.coordinateSystem === this) { + var data_1 = seriesModel.getData(); + each(data_1.mapDimensionsAll(this.dimension), function (dim) { + this._axis.scale.unionExtentFromData(data_1, dim); + }, this); + niceScaleExtent(this._axis.scale, this._axis.model); + } + }, this); + }; + /** + * Resize the single coordinate system. + */ + + + Single.prototype.resize = function (axisModel, api) { + this._rect = getLayoutRect({ + left: axisModel.get('left'), + top: axisModel.get('top'), + right: axisModel.get('right'), + bottom: axisModel.get('bottom'), + width: axisModel.get('width'), + height: axisModel.get('height') + }, { + width: api.getWidth(), + height: api.getHeight() + }); + + this._adjustAxis(); + }; + + Single.prototype.getRect = function () { + return this._rect; + }; + + Single.prototype._adjustAxis = function () { + var rect = this._rect; + var axis = this._axis; + var isHorizontal = axis.isHorizontal(); + var extent = isHorizontal ? [0, rect.width] : [0, rect.height]; + var idx = axis.reverse ? 1 : 0; + axis.setExtent(extent[idx], extent[1 - idx]); + + this._updateAxisTransform(axis, isHorizontal ? rect.x : rect.y); + }; + + Single.prototype._updateAxisTransform = function (axis, coordBase) { + var axisExtent = axis.getExtent(); + var extentSum = axisExtent[0] + axisExtent[1]; + var isHorizontal = axis.isHorizontal(); + axis.toGlobalCoord = isHorizontal ? function (coord) { + return coord + coordBase; + } : function (coord) { + return extentSum - coord + coordBase; + }; + axis.toLocalCoord = isHorizontal ? function (coord) { + return coord - coordBase; + } : function (coord) { + return extentSum - coord + coordBase; + }; + }; + /** + * Get axis. + */ + + + Single.prototype.getAxis = function () { + return this._axis; + }; + /** + * Get axis, add it just for draw tooltip. + */ + + + Single.prototype.getBaseAxis = function () { + return this._axis; + }; + + Single.prototype.getAxes = function () { + return [this._axis]; + }; + + Single.prototype.getTooltipAxes = function () { + return { + baseAxes: [this.getAxis()], + // Empty otherAxes + otherAxes: [] + }; + }; + /** + * If contain point. + */ + + + Single.prototype.containPoint = function (point) { + var rect = this.getRect(); + var axis = this.getAxis(); + var orient = axis.orient; + + if (orient === 'horizontal') { + return axis.contain(axis.toLocalCoord(point[0])) && point[1] >= rect.y && point[1] <= rect.y + rect.height; + } else { + return axis.contain(axis.toLocalCoord(point[1])) && point[0] >= rect.y && point[0] <= rect.y + rect.height; + } + }; + + Single.prototype.pointToData = function (point) { + var axis = this.getAxis(); + return [axis.coordToData(axis.toLocalCoord(point[axis.orient === 'horizontal' ? 0 : 1]))]; + }; + /** + * Convert the series data to concrete point. + * Can be [val] | val + */ + + + Single.prototype.dataToPoint = function (val) { + var axis = this.getAxis(); + var rect = this.getRect(); + var pt = []; + var idx = axis.orient === 'horizontal' ? 0 : 1; + + if (val instanceof Array) { + val = val[0]; + } + + pt[idx] = axis.toGlobalCoord(axis.dataToCoord(+val)); + pt[1 - idx] = idx === 0 ? rect.y + rect.height / 2 : rect.x + rect.width / 2; + return pt; + }; + + Single.prototype.convertToPixel = function (ecModel, finder, value) { + var coordSys = getCoordSys$3(finder); + return coordSys === this ? this.dataToPoint(value) : null; + }; + + Single.prototype.convertFromPixel = function (ecModel, finder, pixel) { + var coordSys = getCoordSys$3(finder); + return coordSys === this ? this.pointToData(pixel) : null; + }; + + return Single; + }(); + + function getCoordSys$3(finder) { + var seriesModel = finder.seriesModel; + var singleModel = finder.singleAxisModel; + return singleModel && singleModel.coordinateSystem || seriesModel && seriesModel.coordinateSystem; + } + + /** + * Create single coordinate system and inject it into seriesModel. + */ + + function create$2(ecModel, api) { + var singles = []; + ecModel.eachComponent('singleAxis', function (axisModel, idx) { + var single = new Single(axisModel, ecModel, api); + single.name = 'single_' + idx; + single.resize(axisModel, api); + axisModel.coordinateSystem = single; + singles.push(single); + }); + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'singleAxis') { + var singleAxisModel = seriesModel.getReferringComponents('singleAxis', SINGLE_REFERRING).models[0]; + seriesModel.coordinateSystem = singleAxisModel && singleAxisModel.coordinateSystem; + } + }); + return singles; + } + + var singleCreator = { + create: create$2, + dimensions: singleDimensions + }; + + var XY = ['x', 'y']; + var WH = ['width', 'height']; + + var SingleAxisPointer = + /** @class */ + function (_super) { + __extends(SingleAxisPointer, _super); + + function SingleAxisPointer() { + return _super !== null && _super.apply(this, arguments) || this; + } + /** + * @override + */ + + + SingleAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) { + var axis = axisModel.axis; + var coordSys = axis.coordinateSystem; + var otherExtent = getGlobalExtent(coordSys, 1 - getPointDimIndex(axis)); + var pixelValue = coordSys.dataToPoint(value)[0]; + var axisPointerType = axisPointerModel.get('type'); + + if (axisPointerType && axisPointerType !== 'none') { + var elStyle = buildElStyle(axisPointerModel); + var pointerOption = pointerShapeBuilder$2[axisPointerType](axis, pixelValue, otherExtent); + pointerOption.style = elStyle; + elOption.graphicKey = pointerOption.type; + elOption.pointer = pointerOption; + } + + var layoutInfo = layout$2(axisModel); + buildCartesianSingleLabelElOption( // @ts-ignore + value, elOption, layoutInfo, axisModel, axisPointerModel, api); + }; + /** + * @override + */ + + + SingleAxisPointer.prototype.getHandleTransform = function (value, axisModel, axisPointerModel) { + var layoutInfo = layout$2(axisModel, { + labelInside: false + }); // @ts-ignore + + layoutInfo.labelMargin = axisPointerModel.get(['handle', 'margin']); + var position = getTransformedPosition(axisModel.axis, value, layoutInfo); + return { + x: position[0], + y: position[1], + rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0) + }; + }; + /** + * @override + */ + + + SingleAxisPointer.prototype.updateHandleTransform = function (transform, delta, axisModel, axisPointerModel) { + var axis = axisModel.axis; + var coordSys = axis.coordinateSystem; + var dimIndex = getPointDimIndex(axis); + var axisExtent = getGlobalExtent(coordSys, dimIndex); + var currPosition = [transform.x, transform.y]; + currPosition[dimIndex] += delta[dimIndex]; + currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]); + currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]); + var otherExtent = getGlobalExtent(coordSys, 1 - dimIndex); + var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2; + var cursorPoint = [cursorOtherValue, cursorOtherValue]; + cursorPoint[dimIndex] = currPosition[dimIndex]; + return { + x: currPosition[0], + y: currPosition[1], + rotation: transform.rotation, + cursorPoint: cursorPoint, + tooltipOption: { + verticalAlign: 'middle' + } + }; + }; + + return SingleAxisPointer; + }(BaseAxisPointer); + + var pointerShapeBuilder$2 = { + line: function (axis, pixelValue, otherExtent) { + var targetShape = makeLineShape([pixelValue, otherExtent[0]], [pixelValue, otherExtent[1]], getPointDimIndex(axis)); + return { + type: 'Line', + subPixelOptimize: true, + shape: targetShape + }; + }, + shadow: function (axis, pixelValue, otherExtent) { + var bandWidth = axis.getBandWidth(); + var span = otherExtent[1] - otherExtent[0]; + return { + type: 'Rect', + shape: makeRectShape([pixelValue - bandWidth / 2, otherExtent[0]], [bandWidth, span], getPointDimIndex(axis)) + }; + } + }; + + function getPointDimIndex(axis) { + return axis.isHorizontal() ? 0 : 1; + } + + function getGlobalExtent(coordSys, dimIndex) { + var rect = coordSys.getRect(); + return [rect[XY[dimIndex]], rect[XY[dimIndex]] + rect[WH[dimIndex]]]; + } + + var SingleView = + /** @class */ + function (_super) { + __extends(SingleView, _super); + + function SingleView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SingleView.type; + return _this; + } + + SingleView.type = 'single'; + return SingleView; + }(ComponentView); + + function install$v(registers) { + use(install$s); + AxisView.registerAxisPointerClass('SingleAxisPointer', SingleAxisPointer); + registers.registerComponentView(SingleView); // Axis + + registers.registerComponentView(SingleAxisView); + registers.registerComponentModel(SingleAxisModel); + axisModelCreator(registers, 'single', SingleAxisModel, SingleAxisModel.defaultOption); + registers.registerCoordinateSystem('single', singleCreator); + } + + var CalendarModel = + /** @class */ + function (_super) { + __extends(CalendarModel, _super); + + function CalendarModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CalendarModel.type; + return _this; + } + /** + * @override + */ + + + CalendarModel.prototype.init = function (option, parentModel, ecModel) { + var inputPositionParams = getLayoutParams(option); + + _super.prototype.init.apply(this, arguments); + + mergeAndNormalizeLayoutParams(option, inputPositionParams); + }; + /** + * @override + */ + + + CalendarModel.prototype.mergeOption = function (option) { + _super.prototype.mergeOption.apply(this, arguments); + + mergeAndNormalizeLayoutParams(this.option, option); + }; + + CalendarModel.prototype.getCellSize = function () { + // Has been normalized + return this.option.cellSize; + }; + + CalendarModel.type = 'calendar'; + CalendarModel.defaultOption = { + // zlevel: 0, + z: 2, + left: 80, + top: 60, + cellSize: 20, + // horizontal vertical + orient: 'horizontal', + // month separate line style + splitLine: { + show: true, + lineStyle: { + color: '#000', + width: 1, + type: 'solid' + } + }, + // rect style temporarily unused emphasis + itemStyle: { + color: '#fff', + borderWidth: 1, + borderColor: '#ccc' + }, + // week text style + dayLabel: { + show: true, + firstDay: 0, + // start end + position: 'start', + margin: '50%', + color: '#000' + }, + // month text style + monthLabel: { + show: true, + // start end + position: 'start', + margin: 5, + // center or left + align: 'center', + formatter: null, + color: '#000' + }, + // year text style + yearLabel: { + show: true, + // top bottom left right + position: null, + margin: 30, + formatter: null, + color: '#ccc', + fontFamily: 'sans-serif', + fontWeight: 'bolder', + fontSize: 20 + } + }; + return CalendarModel; + }(ComponentModel); + + function mergeAndNormalizeLayoutParams(target, raw) { + // Normalize cellSize + var cellSize = target.cellSize; + var cellSizeArr; + + if (!isArray(cellSize)) { + cellSizeArr = target.cellSize = [cellSize, cellSize]; + } else { + cellSizeArr = cellSize; + } + + if (cellSizeArr.length === 1) { + cellSizeArr[1] = cellSizeArr[0]; + } + + var ignoreSize = map([0, 1], function (hvIdx) { + // If user have set `width` or both `left` and `right`, cellSizeArr + // will be automatically set to 'auto', otherwise the default + // setting of cellSizeArr will make `width` setting not work. + if (sizeCalculable(raw, hvIdx)) { + cellSizeArr[hvIdx] = 'auto'; + } + + return cellSizeArr[hvIdx] != null && cellSizeArr[hvIdx] !== 'auto'; + }); + mergeLayoutParam(target, raw, { + type: 'box', + ignoreSize: ignoreSize + }); + } + + var CalendarView = + /** @class */ + function (_super) { + __extends(CalendarView, _super); + + function CalendarView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CalendarView.type; + return _this; + } + + CalendarView.prototype.render = function (calendarModel, ecModel, api) { + var group = this.group; + group.removeAll(); + var coordSys = calendarModel.coordinateSystem; // range info + + var rangeData = coordSys.getRangeInfo(); + var orient = coordSys.getOrient(); // locale + + var localeModel = ecModel.getLocaleModel(); + + this._renderDayRect(calendarModel, rangeData, group); // _renderLines must be called prior to following function + + + this._renderLines(calendarModel, rangeData, orient, group); + + this._renderYearText(calendarModel, rangeData, orient, group); + + this._renderMonthText(calendarModel, localeModel, orient, group); + + this._renderWeekText(calendarModel, localeModel, rangeData, orient, group); + }; // render day rect + + + CalendarView.prototype._renderDayRect = function (calendarModel, rangeData, group) { + var coordSys = calendarModel.coordinateSystem; + var itemRectStyleModel = calendarModel.getModel('itemStyle').getItemStyle(); + var sw = coordSys.getCellWidth(); + var sh = coordSys.getCellHeight(); + + for (var i = rangeData.start.time; i <= rangeData.end.time; i = coordSys.getNextNDay(i, 1).time) { + var point = coordSys.dataToRect([i], false).tl; // every rect + + var rect = new Rect({ + shape: { + x: point[0], + y: point[1], + width: sw, + height: sh + }, + cursor: 'default', + style: itemRectStyleModel + }); + group.add(rect); + } + }; // render separate line + + + CalendarView.prototype._renderLines = function (calendarModel, rangeData, orient, group) { + var self = this; + var coordSys = calendarModel.coordinateSystem; + var lineStyleModel = calendarModel.getModel(['splitLine', 'lineStyle']).getLineStyle(); + var show = calendarModel.get(['splitLine', 'show']); + var lineWidth = lineStyleModel.lineWidth; + this._tlpoints = []; + this._blpoints = []; + this._firstDayOfMonth = []; + this._firstDayPoints = []; + var firstDay = rangeData.start; + + for (var i = 0; firstDay.time <= rangeData.end.time; i++) { + addPoints(firstDay.formatedDate); + + if (i === 0) { + firstDay = coordSys.getDateInfo(rangeData.start.y + '-' + rangeData.start.m); + } + + var date = firstDay.date; + date.setMonth(date.getMonth() + 1); + firstDay = coordSys.getDateInfo(date); + } + + addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate); + + function addPoints(date) { + self._firstDayOfMonth.push(coordSys.getDateInfo(date)); + + self._firstDayPoints.push(coordSys.dataToRect([date], false).tl); + + var points = self._getLinePointsOfOneWeek(calendarModel, date, orient); + + self._tlpoints.push(points[0]); + + self._blpoints.push(points[points.length - 1]); + + show && self._drawSplitline(points, lineStyleModel, group); + } // render top/left line + + + show && this._drawSplitline(self._getEdgesPoints(self._tlpoints, lineWidth, orient), lineStyleModel, group); // render bottom/right line + + show && this._drawSplitline(self._getEdgesPoints(self._blpoints, lineWidth, orient), lineStyleModel, group); + }; // get points at both ends + + + CalendarView.prototype._getEdgesPoints = function (points, lineWidth, orient) { + var rs = [points[0].slice(), points[points.length - 1].slice()]; + var idx = orient === 'horizontal' ? 0 : 1; // both ends of the line are extend half lineWidth + + rs[0][idx] = rs[0][idx] - lineWidth / 2; + rs[1][idx] = rs[1][idx] + lineWidth / 2; + return rs; + }; // render split line + + + CalendarView.prototype._drawSplitline = function (points, lineStyle, group) { + var poyline = new Polyline({ + z2: 20, + shape: { + points: points + }, + style: lineStyle + }); + group.add(poyline); + }; // render month line of one week points + + + CalendarView.prototype._getLinePointsOfOneWeek = function (calendarModel, date, orient) { + var coordSys = calendarModel.coordinateSystem; + var parsedDate = coordSys.getDateInfo(date); + var points = []; + + for (var i = 0; i < 7; i++) { + var tmpD = coordSys.getNextNDay(parsedDate.time, i); + var point = coordSys.dataToRect([tmpD.time], false); + points[2 * tmpD.day] = point.tl; + points[2 * tmpD.day + 1] = point[orient === 'horizontal' ? 'bl' : 'tr']; + } + + return points; + }; + + CalendarView.prototype._formatterLabel = function (formatter, params) { + if (isString(formatter) && formatter) { + return formatTplSimple(formatter, params); + } + + if (isFunction(formatter)) { + return formatter(params); + } + + return params.nameMap; + }; + + CalendarView.prototype._yearTextPositionControl = function (textEl, point, orient, position, margin) { + var x = point[0]; + var y = point[1]; + var aligns = ['center', 'bottom']; + + if (position === 'bottom') { + y += margin; + aligns = ['center', 'top']; + } else if (position === 'left') { + x -= margin; + } else if (position === 'right') { + x += margin; + aligns = ['center', 'top']; + } else { + // top + y -= margin; + } + + var rotate = 0; + + if (position === 'left' || position === 'right') { + rotate = Math.PI / 2; + } + + return { + rotation: rotate, + x: x, + y: y, + style: { + align: aligns[0], + verticalAlign: aligns[1] + } + }; + }; // render year + + + CalendarView.prototype._renderYearText = function (calendarModel, rangeData, orient, group) { + var yearLabel = calendarModel.getModel('yearLabel'); + + if (!yearLabel.get('show')) { + return; + } + + var margin = yearLabel.get('margin'); + var pos = yearLabel.get('position'); + + if (!pos) { + pos = orient !== 'horizontal' ? 'top' : 'left'; + } + + var points = [this._tlpoints[this._tlpoints.length - 1], this._blpoints[0]]; + var xc = (points[0][0] + points[1][0]) / 2; + var yc = (points[0][1] + points[1][1]) / 2; + var idx = orient === 'horizontal' ? 0 : 1; + var posPoints = { + top: [xc, points[idx][1]], + bottom: [xc, points[1 - idx][1]], + left: [points[1 - idx][0], yc], + right: [points[idx][0], yc] + }; + var name = rangeData.start.y; + + if (+rangeData.end.y > +rangeData.start.y) { + name = name + '-' + rangeData.end.y; + } + + var formatter = yearLabel.get('formatter'); + var params = { + start: rangeData.start.y, + end: rangeData.end.y, + nameMap: name + }; + + var content = this._formatterLabel(formatter, params); + + var yearText = new ZRText({ + z2: 30, + style: createTextStyle(yearLabel, { + text: content + }) + }); + yearText.attr(this._yearTextPositionControl(yearText, posPoints[pos], orient, pos, margin)); + group.add(yearText); + }; + + CalendarView.prototype._monthTextPositionControl = function (point, isCenter, orient, position, margin) { + var align = 'left'; + var vAlign = 'top'; + var x = point[0]; + var y = point[1]; + + if (orient === 'horizontal') { + y = y + margin; + + if (isCenter) { + align = 'center'; + } + + if (position === 'start') { + vAlign = 'bottom'; + } + } else { + x = x + margin; + + if (isCenter) { + vAlign = 'middle'; + } + + if (position === 'start') { + align = 'right'; + } + } + + return { + x: x, + y: y, + align: align, + verticalAlign: vAlign + }; + }; // render month and year text + + + CalendarView.prototype._renderMonthText = function (calendarModel, localeModel, orient, group) { + var monthLabel = calendarModel.getModel('monthLabel'); + + if (!monthLabel.get('show')) { + return; + } + + var nameMap = monthLabel.get('nameMap'); + var margin = monthLabel.get('margin'); + var pos = monthLabel.get('position'); + var align = monthLabel.get('align'); + var termPoints = [this._tlpoints, this._blpoints]; + + if (!nameMap || isString(nameMap)) { + if (nameMap) { + // case-sensitive + localeModel = getLocaleModel(nameMap) || localeModel; + } // PENDING + // for ZH locale, original form is `一月` but current form is `1月` + + + nameMap = localeModel.get(['time', 'monthAbbr']) || []; + } + + var idx = pos === 'start' ? 0 : 1; + var axis = orient === 'horizontal' ? 0 : 1; + margin = pos === 'start' ? -margin : margin; + var isCenter = align === 'center'; + + for (var i = 0; i < termPoints[idx].length - 1; i++) { + var tmp = termPoints[idx][i].slice(); + var firstDay = this._firstDayOfMonth[i]; + + if (isCenter) { + var firstDayPoints = this._firstDayPoints[i]; + tmp[axis] = (firstDayPoints[axis] + termPoints[0][i + 1][axis]) / 2; + } + + var formatter = monthLabel.get('formatter'); + var name_1 = nameMap[+firstDay.m - 1]; + var params = { + yyyy: firstDay.y, + yy: (firstDay.y + '').slice(2), + MM: firstDay.m, + M: +firstDay.m, + nameMap: name_1 + }; + + var content = this._formatterLabel(formatter, params); + + var monthText = new ZRText({ + z2: 30, + style: extend(createTextStyle(monthLabel, { + text: content + }), this._monthTextPositionControl(tmp, isCenter, orient, pos, margin)) + }); + group.add(monthText); + } + }; + + CalendarView.prototype._weekTextPositionControl = function (point, orient, position, margin, cellSize) { + var align = 'center'; + var vAlign = 'middle'; + var x = point[0]; + var y = point[1]; + var isStart = position === 'start'; + + if (orient === 'horizontal') { + x = x + margin + (isStart ? 1 : -1) * cellSize[0] / 2; + align = isStart ? 'right' : 'left'; + } else { + y = y + margin + (isStart ? 1 : -1) * cellSize[1] / 2; + vAlign = isStart ? 'bottom' : 'top'; + } + + return { + x: x, + y: y, + align: align, + verticalAlign: vAlign + }; + }; // render weeks + + + CalendarView.prototype._renderWeekText = function (calendarModel, localeModel, rangeData, orient, group) { + var dayLabel = calendarModel.getModel('dayLabel'); + + if (!dayLabel.get('show')) { + return; + } + + var coordSys = calendarModel.coordinateSystem; + var pos = dayLabel.get('position'); + var nameMap = dayLabel.get('nameMap'); + var margin = dayLabel.get('margin'); + var firstDayOfWeek = coordSys.getFirstDayOfWeek(); + + if (!nameMap || isString(nameMap)) { + if (nameMap) { + // case-sensitive + localeModel = getLocaleModel(nameMap) || localeModel; + } // Use the first letter of `dayOfWeekAbbr` if `dayOfWeekShort` doesn't exist in the locale file + + + var dayOfWeekShort = localeModel.get(['time', 'dayOfWeekShort']); + nameMap = dayOfWeekShort || map(localeModel.get(['time', 'dayOfWeekAbbr']), function (val) { + return val[0]; + }); + } + + var start = coordSys.getNextNDay(rangeData.end.time, 7 - rangeData.lweek).time; + var cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()]; + margin = parsePercent$1(margin, Math.min(cellSize[1], cellSize[0])); + + if (pos === 'start') { + start = coordSys.getNextNDay(rangeData.start.time, -(7 + rangeData.fweek)).time; + margin = -margin; + } + + for (var i = 0; i < 7; i++) { + var tmpD = coordSys.getNextNDay(start, i); + var point = coordSys.dataToRect([tmpD.time], false).center; + var day = i; + day = Math.abs((i + firstDayOfWeek) % 7); + var weekText = new ZRText({ + z2: 30, + style: extend(createTextStyle(dayLabel, { + text: nameMap[day] + }), this._weekTextPositionControl(point, orient, pos, margin, cellSize)) + }); + group.add(weekText); + } + }; + + CalendarView.type = 'calendar'; + return CalendarView; + }(ComponentView); + + var PROXIMATE_ONE_DAY = 86400000; + + var Calendar = + /** @class */ + function () { + function Calendar(calendarModel, ecModel, api) { + this.type = 'calendar'; + this.dimensions = Calendar.dimensions; // Required in createListFromData + + this.getDimensionsInfo = Calendar.getDimensionsInfo; + this._model = calendarModel; + } + + Calendar.getDimensionsInfo = function () { + return [{ + name: 'time', + type: 'time' + }, 'value']; + }; + + Calendar.prototype.getRangeInfo = function () { + return this._rangeInfo; + }; + + Calendar.prototype.getModel = function () { + return this._model; + }; + + Calendar.prototype.getRect = function () { + return this._rect; + }; + + Calendar.prototype.getCellWidth = function () { + return this._sw; + }; + + Calendar.prototype.getCellHeight = function () { + return this._sh; + }; + + Calendar.prototype.getOrient = function () { + return this._orient; + }; + /** + * getFirstDayOfWeek + * + * @example + * 0 : start at Sunday + * 1 : start at Monday + * + * @return {number} + */ + + + Calendar.prototype.getFirstDayOfWeek = function () { + return this._firstDayOfWeek; + }; + /** + * get date info + * } + */ + + + Calendar.prototype.getDateInfo = function (date) { + date = parseDate(date); + var y = date.getFullYear(); + var m = date.getMonth() + 1; + var mStr = m < 10 ? '0' + m : '' + m; + var d = date.getDate(); + var dStr = d < 10 ? '0' + d : '' + d; + var day = date.getDay(); + day = Math.abs((day + 7 - this.getFirstDayOfWeek()) % 7); + return { + y: y + '', + m: mStr, + d: dStr, + day: day, + time: date.getTime(), + formatedDate: y + '-' + mStr + '-' + dStr, + date: date + }; + }; + + Calendar.prototype.getNextNDay = function (date, n) { + n = n || 0; + + if (n === 0) { + return this.getDateInfo(date); + } + + date = new Date(this.getDateInfo(date).time); + date.setDate(date.getDate() + n); + return this.getDateInfo(date); + }; + + Calendar.prototype.update = function (ecModel, api) { + this._firstDayOfWeek = +this._model.getModel('dayLabel').get('firstDay'); + this._orient = this._model.get('orient'); + this._lineWidth = this._model.getModel('itemStyle').getItemStyle().lineWidth || 0; + this._rangeInfo = this._getRangeInfo(this._initRangeOption()); + var weeks = this._rangeInfo.weeks || 1; + var whNames = ['width', 'height']; + + var cellSize = this._model.getCellSize().slice(); + + var layoutParams = this._model.getBoxLayoutParams(); + + var cellNumbers = this._orient === 'horizontal' ? [weeks, 7] : [7, weeks]; + each([0, 1], function (idx) { + if (cellSizeSpecified(cellSize, idx)) { + layoutParams[whNames[idx]] = cellSize[idx] * cellNumbers[idx]; + } + }); + var whGlobal = { + width: api.getWidth(), + height: api.getHeight() + }; + var calendarRect = this._rect = getLayoutRect(layoutParams, whGlobal); + each([0, 1], function (idx) { + if (!cellSizeSpecified(cellSize, idx)) { + cellSize[idx] = calendarRect[whNames[idx]] / cellNumbers[idx]; + } + }); + + function cellSizeSpecified(cellSize, idx) { + return cellSize[idx] != null && cellSize[idx] !== 'auto'; + } // Has been calculated out number. + + + this._sw = cellSize[0]; + this._sh = cellSize[1]; + }; + /** + * Convert a time data(time, value) item to (x, y) point. + */ + // TODO Clamp of calendar is not same with cartesian coordinate systems. + // It will return NaN if data exceeds. + + + Calendar.prototype.dataToPoint = function (data, clamp) { + isArray(data) && (data = data[0]); + clamp == null && (clamp = true); + var dayInfo = this.getDateInfo(data); + var range = this._rangeInfo; + var date = dayInfo.formatedDate; // if not in range return [NaN, NaN] + + if (clamp && !(dayInfo.time >= range.start.time && dayInfo.time < range.end.time + PROXIMATE_ONE_DAY)) { + return [NaN, NaN]; + } + + var week = dayInfo.day; + + var nthWeek = this._getRangeInfo([range.start.time, date]).nthWeek; + + if (this._orient === 'vertical') { + return [this._rect.x + week * this._sw + this._sw / 2, this._rect.y + nthWeek * this._sh + this._sh / 2]; + } + + return [this._rect.x + nthWeek * this._sw + this._sw / 2, this._rect.y + week * this._sh + this._sh / 2]; + }; + /** + * Convert a (x, y) point to time data + */ + + + Calendar.prototype.pointToData = function (point) { + var date = this.pointToDate(point); + return date && date.time; + }; + /** + * Convert a time date item to (x, y) four point. + */ + + + Calendar.prototype.dataToRect = function (data, clamp) { + var point = this.dataToPoint(data, clamp); + return { + contentShape: { + x: point[0] - (this._sw - this._lineWidth) / 2, + y: point[1] - (this._sh - this._lineWidth) / 2, + width: this._sw - this._lineWidth, + height: this._sh - this._lineWidth + }, + center: point, + tl: [point[0] - this._sw / 2, point[1] - this._sh / 2], + tr: [point[0] + this._sw / 2, point[1] - this._sh / 2], + br: [point[0] + this._sw / 2, point[1] + this._sh / 2], + bl: [point[0] - this._sw / 2, point[1] + this._sh / 2] + }; + }; + /** + * Convert a (x, y) point to time date + * + * @param {Array} point point + * @return {Object} date + */ + + + Calendar.prototype.pointToDate = function (point) { + var nthX = Math.floor((point[0] - this._rect.x) / this._sw) + 1; + var nthY = Math.floor((point[1] - this._rect.y) / this._sh) + 1; + var range = this._rangeInfo.range; + + if (this._orient === 'vertical') { + return this._getDateByWeeksAndDay(nthY, nthX - 1, range); + } + + return this._getDateByWeeksAndDay(nthX, nthY - 1, range); + }; + + Calendar.prototype.convertToPixel = function (ecModel, finder, value) { + var coordSys = getCoordSys$4(finder); + return coordSys === this ? coordSys.dataToPoint(value) : null; + }; + + Calendar.prototype.convertFromPixel = function (ecModel, finder, pixel) { + var coordSys = getCoordSys$4(finder); + return coordSys === this ? coordSys.pointToData(pixel) : null; + }; + + Calendar.prototype.containPoint = function (point) { + console.warn('Not implemented.'); + return false; + }; + /** + * initRange + * Normalize to an [start, end] array + */ + + + Calendar.prototype._initRangeOption = function () { + var range = this._model.get('range'); + + var normalizedRange; // Convert [1990] to 1990 + + if (isArray(range) && range.length === 1) { + range = range[0]; + } + + if (!isArray(range)) { + var rangeStr = range.toString(); // One year. + + if (/^\d{4}$/.test(rangeStr)) { + normalizedRange = [rangeStr + '-01-01', rangeStr + '-12-31']; + } // One month + + + if (/^\d{4}[\/|-]\d{1,2}$/.test(rangeStr)) { + var start = this.getDateInfo(rangeStr); + var firstDay = start.date; + firstDay.setMonth(firstDay.getMonth() + 1); + var end = this.getNextNDay(firstDay, -1); + normalizedRange = [start.formatedDate, end.formatedDate]; + } // One day + + + if (/^\d{4}[\/|-]\d{1,2}[\/|-]\d{1,2}$/.test(rangeStr)) { + normalizedRange = [rangeStr, rangeStr]; + } + } else { + normalizedRange = range; + } + + if (!normalizedRange) { + if ("development" !== 'production') { + logError('Invalid date range.'); + } // Not handling it. + + + return range; + } + + var tmp = this._getRangeInfo(normalizedRange); + + if (tmp.start.time > tmp.end.time) { + normalizedRange.reverse(); + } + + return normalizedRange; + }; + /** + * range info + * + * @private + * @param {Array} range range ['2017-01-01', '2017-07-08'] + * If range[0] > range[1], they will not be reversed. + * @return {Object} obj + */ + + + Calendar.prototype._getRangeInfo = function (range) { + var parsedRange = [this.getDateInfo(range[0]), this.getDateInfo(range[1])]; + var reversed; + + if (parsedRange[0].time > parsedRange[1].time) { + reversed = true; + parsedRange.reverse(); + } + + var allDay = Math.floor(parsedRange[1].time / PROXIMATE_ONE_DAY) - Math.floor(parsedRange[0].time / PROXIMATE_ONE_DAY) + 1; // Consider case1 (#11677 #10430): + // Set the system timezone as "UK", set the range to `['2016-07-01', '2016-12-31']` + // Consider case2: + // Firstly set system timezone as "Time Zone: America/Toronto", + // ``` + // let first = new Date(1478412000000 - 3600 * 1000 * 2.5); + // let second = new Date(1478412000000); + // let allDays = Math.floor(second / ONE_DAY) - Math.floor(first / ONE_DAY) + 1; + // ``` + // will get wrong result because of DST. So we should fix it. + + var date = new Date(parsedRange[0].time); + var startDateNum = date.getDate(); + var endDateNum = parsedRange[1].date.getDate(); + date.setDate(startDateNum + allDay - 1); // The bias can not over a month, so just compare date. + + var dateNum = date.getDate(); + + if (dateNum !== endDateNum) { + var sign = date.getTime() - parsedRange[1].time > 0 ? 1 : -1; + + while ((dateNum = date.getDate()) !== endDateNum && (date.getTime() - parsedRange[1].time) * sign > 0) { + allDay -= sign; + date.setDate(dateNum - sign); + } + } + + var weeks = Math.floor((allDay + parsedRange[0].day + 6) / 7); + var nthWeek = reversed ? -weeks + 1 : weeks - 1; + reversed && parsedRange.reverse(); + return { + range: [parsedRange[0].formatedDate, parsedRange[1].formatedDate], + start: parsedRange[0], + end: parsedRange[1], + allDay: allDay, + weeks: weeks, + // From 0. + nthWeek: nthWeek, + fweek: parsedRange[0].day, + lweek: parsedRange[1].day + }; + }; + /** + * get date by nthWeeks and week day in range + * + * @private + * @param {number} nthWeek the week + * @param {number} day the week day + * @param {Array} range [d1, d2] + * @return {Object} + */ + + + Calendar.prototype._getDateByWeeksAndDay = function (nthWeek, day, range) { + var rangeInfo = this._getRangeInfo(range); + + if (nthWeek > rangeInfo.weeks || nthWeek === 0 && day < rangeInfo.fweek || nthWeek === rangeInfo.weeks && day > rangeInfo.lweek) { + return null; + } + + var nthDay = (nthWeek - 1) * 7 - rangeInfo.fweek + day; + var date = new Date(rangeInfo.start.time); + date.setDate(+rangeInfo.start.d + nthDay); + return this.getDateInfo(date); + }; + + Calendar.create = function (ecModel, api) { + var calendarList = []; + ecModel.eachComponent('calendar', function (calendarModel) { + var calendar = new Calendar(calendarModel, ecModel, api); + calendarList.push(calendar); + calendarModel.coordinateSystem = calendar; + }); + ecModel.eachSeries(function (calendarSeries) { + if (calendarSeries.get('coordinateSystem') === 'calendar') { + // Inject coordinate system + calendarSeries.coordinateSystem = calendarList[calendarSeries.get('calendarIndex') || 0]; + } + }); + return calendarList; + }; + + Calendar.dimensions = ['time', 'value']; + return Calendar; + }(); + + function getCoordSys$4(finder) { + var calendarModel = finder.calendarModel; + var seriesModel = finder.seriesModel; + var coordSys = calendarModel ? calendarModel.coordinateSystem : seriesModel ? seriesModel.coordinateSystem : null; + return coordSys; + } + + function install$w(registers) { + registers.registerComponentModel(CalendarModel); + registers.registerComponentView(CalendarView); + registers.registerCoordinateSystem('calendar', Calendar); + } + + function setKeyInfoToNewElOption(resultItem, newElOption) { + var existElOption = resultItem.existing; // Set id and type after id assigned. + + newElOption.id = resultItem.keyInfo.id; + !newElOption.type && existElOption && (newElOption.type = existElOption.type); // Set parent id if not specified + + if (newElOption.parentId == null) { + var newElParentOption = newElOption.parentOption; + + if (newElParentOption) { + newElOption.parentId = newElParentOption.id; + } else if (existElOption) { + newElOption.parentId = existElOption.parentId; + } + } // Clear + + + newElOption.parentOption = null; + } + + function isSetLoc(obj, props) { + var isSet; + each(props, function (prop) { + obj[prop] != null && obj[prop] !== 'auto' && (isSet = true); + }); + return isSet; + } + + function mergeNewElOptionToExist(existList, index, newElOption) { + // Update existing options, for `getOption` feature. + var newElOptCopy = extend({}, newElOption); + var existElOption = existList[index]; + var $action = newElOption.$action || 'merge'; + + if ($action === 'merge') { + if (existElOption) { + if ("development" !== 'production') { + var newType = newElOption.type; + assert(!newType || existElOption.type === newType, 'Please set $action: "replace" to change `type`'); + } // We can ensure that newElOptCopy and existElOption are not + // the same object, so `merge` will not change newElOptCopy. + + + merge(existElOption, newElOptCopy, true); // Rigid body, use ignoreSize. + + mergeLayoutParam(existElOption, newElOptCopy, { + ignoreSize: true + }); // Will be used in render. + + copyLayoutParams(newElOption, existElOption); // Copy transition info to new option so it can be used in the transition. + // DO IT AFTER merge + + copyTransitionInfo(newElOption, existElOption); + copyTransitionInfo(newElOption, existElOption, 'shape'); + copyTransitionInfo(newElOption, existElOption, 'style'); + copyTransitionInfo(newElOption, existElOption, 'extra'); // Copy clipPath + + newElOption.clipPath = existElOption.clipPath; + } else { + existList[index] = newElOptCopy; + } + } else if ($action === 'replace') { + existList[index] = newElOptCopy; + } else if ($action === 'remove') { + // null will be cleaned later. + existElOption && (existList[index] = null); + } + } + + var TRANSITION_PROPS_TO_COPY = ['transition', 'enterFrom', 'leaveTo']; + var ROOT_TRANSITION_PROPS_TO_COPY = TRANSITION_PROPS_TO_COPY.concat(['enterAnimation', 'updateAnimation', 'leaveAnimation']); + + function copyTransitionInfo(target, source, targetProp) { + if (targetProp) { + if (!target[targetProp] && source[targetProp]) { + // TODO avoid creating this empty object when there is no transition configuration. + target[targetProp] = {}; + } + + target = target[targetProp]; + source = source[targetProp]; + } + + if (!target || !source) { + return; + } + + var props = targetProp ? TRANSITION_PROPS_TO_COPY : ROOT_TRANSITION_PROPS_TO_COPY; + + for (var i = 0; i < props.length; i++) { + var prop = props[i]; + + if (target[prop] == null && source[prop] != null) { + target[prop] = source[prop]; + } + } + } + + function setLayoutInfoToExist(existItem, newElOption) { + if (!existItem) { + return; + } + + existItem.hv = newElOption.hv = [// Rigid body, dont care `width`. + isSetLoc(newElOption, ['left', 'right']), // Rigid body, dont care `height`. + isSetLoc(newElOption, ['top', 'bottom'])]; // Give default group size. Otherwise layout error may occur. + + if (existItem.type === 'group') { + var existingGroupOpt = existItem; + var newGroupOpt = newElOption; + existingGroupOpt.width == null && (existingGroupOpt.width = newGroupOpt.width = 0); + existingGroupOpt.height == null && (existingGroupOpt.height = newGroupOpt.height = 0); + } + } + + var GraphicComponentModel = + /** @class */ + function (_super) { + __extends(GraphicComponentModel, _super); + + function GraphicComponentModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GraphicComponentModel.type; + _this.preventAutoZ = true; + return _this; + } + + GraphicComponentModel.prototype.mergeOption = function (option, ecModel) { + // Prevent default merge to elements + var elements = this.option.elements; + this.option.elements = null; + + _super.prototype.mergeOption.call(this, option, ecModel); + + this.option.elements = elements; + }; + + GraphicComponentModel.prototype.optionUpdated = function (newOption, isInit) { + var thisOption = this.option; + var newList = (isInit ? thisOption : newOption).elements; + var existList = thisOption.elements = isInit ? [] : thisOption.elements; + var flattenedList = []; + + this._flatten(newList, flattenedList, null); + + var mappingResult = mappingToExists(existList, flattenedList, 'normalMerge'); // Clear elOptionsToUpdate + + var elOptionsToUpdate = this._elOptionsToUpdate = []; + each(mappingResult, function (resultItem, index) { + var newElOption = resultItem.newOption; + + if ("development" !== 'production') { + assert(isObject(newElOption) || resultItem.existing, 'Empty graphic option definition'); + } + + if (!newElOption) { + return; + } + + elOptionsToUpdate.push(newElOption); + setKeyInfoToNewElOption(resultItem, newElOption); + mergeNewElOptionToExist(existList, index, newElOption); + setLayoutInfoToExist(existList[index], newElOption); + }, this); // Clean + + thisOption.elements = filter(existList, function (item) { + // $action should be volatile, otherwise option gotten from + // `getOption` will contain unexpected $action. + item && delete item.$action; + return item != null; + }); + }; + /** + * Convert + * [{ + * type: 'group', + * id: 'xx', + * children: [{type: 'circle'}, {type: 'polygon'}] + * }] + * to + * [ + * {type: 'group', id: 'xx'}, + * {type: 'circle', parentId: 'xx'}, + * {type: 'polygon', parentId: 'xx'} + * ] + */ + + + GraphicComponentModel.prototype._flatten = function (optionList, result, parentOption) { + each(optionList, function (option) { + if (!option) { + return; + } + + if (parentOption) { + option.parentOption = parentOption; + } + + result.push(option); + var children = option.children; + + if (option.type === 'group' && children) { + this._flatten(children, result, option); + } // Deleting for JSON output, and for not affecting group creation. + + + delete option.children; + }, this); + }; // FIXME + // Pass to view using payload? setOption has a payload? + + + GraphicComponentModel.prototype.useElOptionsToUpdate = function () { + var els = this._elOptionsToUpdate; // Clear to avoid render duplicately when zooming. + + this._elOptionsToUpdate = null; + return els; + }; + + GraphicComponentModel.type = 'graphic'; + GraphicComponentModel.defaultOption = { + elements: [] // parentId: null + + }; + return GraphicComponentModel; + }(ComponentModel); + + var nonShapeGraphicElements = { + // Reserved but not supported in graphic component. + path: null, + compoundPath: null, + // Supported in graphic component. + group: Group, + image: ZRImage, + text: ZRText + }; + var inner$e = makeInner(); // ------------------------ + // View + // ------------------------ + + var GraphicComponentView = + /** @class */ + function (_super) { + __extends(GraphicComponentView, _super); + + function GraphicComponentView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GraphicComponentView.type; + return _this; + } + + GraphicComponentView.prototype.init = function () { + this._elMap = createHashMap(); + }; + + GraphicComponentView.prototype.render = function (graphicModel, ecModel, api) { + // Having leveraged between use cases and algorithm complexity, a very + // simple layout mechanism is used: + // The size(width/height) can be determined by itself or its parent (not + // implemented yet), but can not by its children. (Top-down travel) + // The location(x/y) can be determined by the bounding rect of itself + // (can including its descendants or not) and the size of its parent. + // (Bottom-up travel) + // When `chart.clear()` or `chart.setOption({...}, true)` with the same id, + // view will be reused. + if (graphicModel !== this._lastGraphicModel) { + this._clear(); + } + + this._lastGraphicModel = graphicModel; + + this._updateElements(graphicModel); + + this._relocate(graphicModel, api); + }; + /** + * Update graphic elements. + */ + + + GraphicComponentView.prototype._updateElements = function (graphicModel) { + var elOptionsToUpdate = graphicModel.useElOptionsToUpdate(); + + if (!elOptionsToUpdate) { + return; + } + + var elMap = this._elMap; + var rootGroup = this.group; + var globalZ = graphicModel.get('z'); + var globalZLevel = graphicModel.get('zlevel'); // Top-down tranverse to assign graphic settings to each elements. + + each(elOptionsToUpdate, function (elOption) { + var id = convertOptionIdName(elOption.id, null); + var elExisting = id != null ? elMap.get(id) : null; + var parentId = convertOptionIdName(elOption.parentId, null); + var targetElParent = parentId != null ? elMap.get(parentId) : rootGroup; + var elType = elOption.type; + var elOptionStyle = elOption.style; + + if (elType === 'text' && elOptionStyle) { + // In top/bottom mode, textVerticalAlign should not be used, which cause + // inaccurately locating. + if (elOption.hv && elOption.hv[1]) { + elOptionStyle.textVerticalAlign = elOptionStyle.textBaseline = elOptionStyle.verticalAlign = elOptionStyle.align = null; + } + } + + var textContentOption = elOption.textContent; + var textConfig = elOption.textConfig; + + if (elOptionStyle && isEC4CompatibleStyle(elOptionStyle, elType, !!textConfig, !!textContentOption)) { + var convertResult = convertFromEC4CompatibleStyle(elOptionStyle, elType, true); + + if (!textConfig && convertResult.textConfig) { + textConfig = elOption.textConfig = convertResult.textConfig; + } + + if (!textContentOption && convertResult.textContent) { + textContentOption = convertResult.textContent; + } + } // Remove unnecessary props to avoid potential problems. + + + var elOptionCleaned = getCleanedElOption(elOption); // For simple, do not support parent change, otherwise reorder is needed. + + if ("development" !== 'production') { + elExisting && assert(targetElParent === elExisting.parent, 'Changing parent is not supported.'); + } + + var $action = elOption.$action || 'merge'; + var isMerge = $action === 'merge'; + var isReplace = $action === 'replace'; + + if (isMerge) { + var isInit = !elExisting; + var el_1 = elExisting; + + if (isInit) { + el_1 = createEl$1(id, targetElParent, elOption.type, elMap); + } else { + el_1 && (inner$e(el_1).isNew = false); // Stop and restore before update any other attributes. + + stopPreviousKeyframeAnimationAndRestore(el_1); + } + + if (el_1) { + applyUpdateTransition(el_1, elOptionCleaned, graphicModel, { + isInit: isInit + }); + updateCommonAttrs(el_1, elOption, globalZ, globalZLevel); + } + } else if (isReplace) { + removeEl(elExisting, elOption, elMap, graphicModel); + var el_2 = createEl$1(id, targetElParent, elOption.type, elMap); + + if (el_2) { + applyUpdateTransition(el_2, elOptionCleaned, graphicModel, { + isInit: true + }); + updateCommonAttrs(el_2, elOption, globalZ, globalZLevel); + } + } else if ($action === 'remove') { + updateLeaveTo(elExisting, elOption); + removeEl(elExisting, elOption, elMap, graphicModel); + } + + var el = elMap.get(id); + + if (el && textContentOption) { + if (isMerge) { + var textContentExisting = el.getTextContent(); + textContentExisting ? textContentExisting.attr(textContentOption) : el.setTextContent(new ZRText(textContentOption)); + } else if (isReplace) { + el.setTextContent(new ZRText(textContentOption)); + } + } + + if (el) { + var clipPathOption = elOption.clipPath; + + if (clipPathOption) { + var clipPathType = clipPathOption.type; + var clipPath = void 0; + var isInit = false; + + if (isMerge) { + var oldClipPath = el.getClipPath(); + isInit = !oldClipPath || inner$e(oldClipPath).type !== clipPathType; + clipPath = isInit ? newEl(clipPathType) : oldClipPath; + } else if (isReplace) { + isInit = true; + clipPath = newEl(clipPathType); + } + + el.setClipPath(clipPath); + applyUpdateTransition(clipPath, clipPathOption, graphicModel, { + isInit: isInit + }); + applyKeyframeAnimation(clipPath, clipPathOption.keyframeAnimation, graphicModel); + } + + var elInner = inner$e(el); + el.setTextConfig(textConfig); + elInner.option = elOption; + setEventData(el, graphicModel, elOption); + setTooltipConfig({ + el: el, + componentModel: graphicModel, + itemName: el.name, + itemTooltipOption: elOption.tooltip + }); + applyKeyframeAnimation(el, elOption.keyframeAnimation, graphicModel); + } + }); + }; + /** + * Locate graphic elements. + */ + + + GraphicComponentView.prototype._relocate = function (graphicModel, api) { + var elOptions = graphicModel.option.elements; + var rootGroup = this.group; + var elMap = this._elMap; + var apiWidth = api.getWidth(); + var apiHeight = api.getHeight(); + var xy = ['x', 'y']; // Top-down to calculate percentage width/height of group + + for (var i = 0; i < elOptions.length; i++) { + var elOption = elOptions[i]; + var id = convertOptionIdName(elOption.id, null); + var el = id != null ? elMap.get(id) : null; + + if (!el || !el.isGroup) { + continue; + } + + var parentEl = el.parent; + var isParentRoot = parentEl === rootGroup; // Like 'position:absolut' in css, default 0. + + var elInner = inner$e(el); + var parentElInner = inner$e(parentEl); + elInner.width = parsePercent$1(elInner.option.width, isParentRoot ? apiWidth : parentElInner.width) || 0; + elInner.height = parsePercent$1(elInner.option.height, isParentRoot ? apiHeight : parentElInner.height) || 0; + } // Bottom-up tranvese all elements (consider ec resize) to locate elements. + + + for (var i = elOptions.length - 1; i >= 0; i--) { + var elOption = elOptions[i]; + var id = convertOptionIdName(elOption.id, null); + var el = id != null ? elMap.get(id) : null; + + if (!el) { + continue; + } + + var parentEl = el.parent; + var parentElInner = inner$e(parentEl); + var containerInfo = parentEl === rootGroup ? { + width: apiWidth, + height: apiHeight + } : { + width: parentElInner.width, + height: parentElInner.height + }; // PENDING + // Currently, when `bounding: 'all'`, the union bounding rect of the group + // does not include the rect of [0, 0, group.width, group.height], which + // is probably weird for users. Should we make a break change for it? + + var layoutPos = {}; + var layouted = positionElement(el, elOption, containerInfo, null, { + hv: elOption.hv, + boundingMode: elOption.bounding + }, layoutPos); + + if (!inner$e(el).isNew && layouted) { + var transition = elOption.transition; + var animatePos = {}; + + for (var k = 0; k < xy.length; k++) { + var key = xy[k]; + var val = layoutPos[key]; + + if (transition && (isTransitionAll(transition) || indexOf(transition, key) >= 0)) { + animatePos[key] = val; + } else { + el[key] = val; + } + } + + updateProps(el, animatePos, graphicModel, 0); + } else { + el.attr(layoutPos); + } + } + }; + /** + * Clear all elements. + */ + + + GraphicComponentView.prototype._clear = function () { + var _this = this; + + var elMap = this._elMap; + elMap.each(function (el) { + removeEl(el, inner$e(el).option, elMap, _this._lastGraphicModel); + }); + this._elMap = createHashMap(); + }; + + GraphicComponentView.prototype.dispose = function () { + this._clear(); + }; + + GraphicComponentView.type = 'graphic'; + return GraphicComponentView; + }(ComponentView); + + function newEl(graphicType) { + if ("development" !== 'production') { + assert(graphicType, 'graphic type MUST be set'); + } + + var Clz = hasOwn(nonShapeGraphicElements, graphicType) // Those graphic elements are not shapes. They should not be + // overwritten by users, so do them first. + ? nonShapeGraphicElements[graphicType] : getShapeClass(graphicType); + + if ("development" !== 'production') { + assert(Clz, "graphic type " + graphicType + " can not be found"); + } + + var el = new Clz({}); + inner$e(el).type = graphicType; + return el; + } + + function createEl$1(id, targetElParent, graphicType, elMap) { + var el = newEl(graphicType); + targetElParent.add(el); + elMap.set(id, el); + inner$e(el).id = id; + inner$e(el).isNew = true; + return el; + } + + function removeEl(elExisting, elOption, elMap, graphicModel) { + var existElParent = elExisting && elExisting.parent; + + if (existElParent) { + elExisting.type === 'group' && elExisting.traverse(function (el) { + removeEl(el, elOption, elMap, graphicModel); + }); + applyLeaveTransition(elExisting, elOption, graphicModel); + elMap.removeKey(inner$e(elExisting).id); + } + } + + function updateCommonAttrs(el, elOption, defaultZ, defaultZlevel) { + if (!el.isGroup) { + var elDisplayable = el; + elDisplayable.cursor = retrieve2(elOption.cursor, Displayable.prototype.cursor); // We should not support configure z and zlevel in the element level. + // But seems we didn't limit it previously. So here still use it to avoid breaking. + + elDisplayable.z = retrieve2(elOption.z, defaultZ || 0); + elDisplayable.zlevel = retrieve2(elOption.zlevel, defaultZlevel || 0); // z2 must not be null/undefined, otherwise sort error may occur. + + var optZ2 = elOption.z2; + optZ2 != null && (elDisplayable.z2 = optZ2 || 0); + } + + each(keys(elOption), function (key) { + var val = elOption[key]; // Assign event handlers. + // PENDING: should enumerate all event names or use pattern matching? + + if (key.indexOf('on') === 0 && isFunction(val)) { + el[key] = val; + } + }); + el.draggable = elOption.draggable; // Other attributes + + elOption.name != null && (el.name = elOption.name); + elOption.id != null && (el.id = elOption.id); + } // Remove unnecessary props to avoid potential problems. + + + function getCleanedElOption(elOption) { + elOption = extend({}, elOption); + each(['id', 'parentId', '$action', 'hv', 'bounding', 'textContent', 'clipPath'].concat(LOCATION_PARAMS), function (name) { + delete elOption[name]; + }); + return elOption; + } + + function setEventData(el, graphicModel, elOption) { + var eventData = getECData(el).eventData; // Simple optimize for large amount of elements that no need event. + + if (!el.silent && !el.ignore && !eventData) { + eventData = getECData(el).eventData = { + componentType: 'graphic', + componentIndex: graphicModel.componentIndex, + name: el.name + }; + } // `elOption.info` enables user to mount some info on + // elements and use them in event handlers. + + + if (eventData) { + eventData.info = elOption.info; + } + } + + function install$x(registers) { + registers.registerComponentModel(GraphicComponentModel); + registers.registerComponentView(GraphicComponentView); + registers.registerPreprocessor(function (option) { + var graphicOption = option.graphic; // Convert + // {graphic: [{left: 10, type: 'circle'}, ...]} + // or + // {graphic: {left: 10, type: 'circle'}} + // to + // {graphic: [{elements: [{left: 10, type: 'circle'}, ...]}]} + + if (isArray(graphicOption)) { + if (!graphicOption[0] || !graphicOption[0].elements) { + option.graphic = [{ + elements: graphicOption + }]; + } else { + // Only one graphic instance can be instantiated. (We dont + // want that too many views are created in echarts._viewMap) + option.graphic = [option.graphic[0]]; + } + } else if (graphicOption && !graphicOption.elements) { + option.graphic = [{ + elements: [graphicOption] + }]; + } + }); + } + + var DATA_ZOOM_AXIS_DIMENSIONS = ['x', 'y', 'radius', 'angle', 'single']; // Supported coords. + // FIXME: polar has been broken (but rarely used). + + var SERIES_COORDS = ['cartesian2d', 'polar', 'singleAxis']; + function isCoordSupported(seriesModel) { + var coordType = seriesModel.get('coordinateSystem'); + return indexOf(SERIES_COORDS, coordType) >= 0; + } + function getAxisMainType(axisDim) { + if ("development" !== 'production') { + assert(axisDim); + } + + return axisDim + 'Axis'; + } + /** + * If two dataZoomModels has the same axis controlled, we say that they are 'linked'. + * This function finds all linked dataZoomModels start from the given payload. + */ + + function findEffectedDataZooms(ecModel, payload) { + // Key: `DataZoomAxisDimension` + var axisRecords = createHashMap(); + var effectedModels = []; // Key: uid of dataZoomModel + + var effectedModelMap = createHashMap(); // Find the dataZooms specified by payload. + + ecModel.eachComponent({ + mainType: 'dataZoom', + query: payload + }, function (dataZoomModel) { + if (!effectedModelMap.get(dataZoomModel.uid)) { + addToEffected(dataZoomModel); + } + }); // Start from the given dataZoomModels, travel the graph to find + // all of the linked dataZoom models. + + var foundNewLink; + + do { + foundNewLink = false; + ecModel.eachComponent('dataZoom', processSingle); + } while (foundNewLink); + + function processSingle(dataZoomModel) { + if (!effectedModelMap.get(dataZoomModel.uid) && isLinked(dataZoomModel)) { + addToEffected(dataZoomModel); + foundNewLink = true; + } + } + + function addToEffected(dataZoom) { + effectedModelMap.set(dataZoom.uid, true); + effectedModels.push(dataZoom); + markAxisControlled(dataZoom); + } + + function isLinked(dataZoomModel) { + var isLink = false; + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + var axisIdxArr = axisRecords.get(axisDim); + + if (axisIdxArr && axisIdxArr[axisIndex]) { + isLink = true; + } + }); + return isLink; + } + + function markAxisControlled(dataZoomModel) { + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + (axisRecords.get(axisDim) || axisRecords.set(axisDim, []))[axisIndex] = true; + }); + } + + return effectedModels; + } + /** + * Find the first target coordinate system. + * Available after model built. + * + * @return Like { + * grid: [ + * {model: coord0, axisModels: [axis1, axis3], coordIndex: 1}, + * {model: coord1, axisModels: [axis0, axis2], coordIndex: 0}, + * ... + * ], // cartesians must not be null/undefined. + * polar: [ + * {model: coord0, axisModels: [axis4], coordIndex: 0}, + * ... + * ], // polars must not be null/undefined. + * singleAxis: [ + * {model: coord0, axisModels: [], coordIndex: 0} + * ] + * } + */ + + function collectReferCoordSysModelInfo(dataZoomModel) { + var ecModel = dataZoomModel.ecModel; + var coordSysInfoWrap = { + infoList: [], + infoMap: createHashMap() + }; + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + var axisModel = ecModel.getComponent(getAxisMainType(axisDim), axisIndex); + + if (!axisModel) { + return; + } + + var coordSysModel = axisModel.getCoordSysModel(); + + if (!coordSysModel) { + return; + } + + var coordSysUid = coordSysModel.uid; + var coordSysInfo = coordSysInfoWrap.infoMap.get(coordSysUid); + + if (!coordSysInfo) { + coordSysInfo = { + model: coordSysModel, + axisModels: [] + }; + coordSysInfoWrap.infoList.push(coordSysInfo); + coordSysInfoWrap.infoMap.set(coordSysUid, coordSysInfo); + } + + coordSysInfo.axisModels.push(axisModel); + }); + return coordSysInfoWrap; + } + + var DataZoomAxisInfo = + /** @class */ + function () { + function DataZoomAxisInfo() { + this.indexList = []; + this.indexMap = []; + } + + DataZoomAxisInfo.prototype.add = function (axisCmptIdx) { + // Remove duplication. + if (!this.indexMap[axisCmptIdx]) { + this.indexList.push(axisCmptIdx); + this.indexMap[axisCmptIdx] = true; + } + }; + + return DataZoomAxisInfo; + }(); + + var DataZoomModel = + /** @class */ + function (_super) { + __extends(DataZoomModel, _super); + + function DataZoomModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = DataZoomModel.type; + _this._autoThrottle = true; + _this._noTarget = true; + /** + * It is `[rangeModeForMin, rangeModeForMax]`. + * The optional values for `rangeMode`: + * + `'value'` mode: the axis extent will always be determined by + * `dataZoom.startValue` and `dataZoom.endValue`, despite + * how data like and how `axis.min` and `axis.max` are. + * + `'percent'` mode: `100` represents 100% of the `[dMin, dMax]`, + * where `dMin` is `axis.min` if `axis.min` specified, otherwise `data.extent[0]`, + * and `dMax` is `axis.max` if `axis.max` specified, otherwise `data.extent[1]`. + * Axis extent will be determined by the result of the percent of `[dMin, dMax]`. + * + * For example, when users are using dynamic data (update data periodically via `setOption`), + * if in `'value`' mode, the window will be kept in a fixed value range despite how + * data are appended, while if in `'percent'` mode, whe window range will be changed alone with + * the appended data (suppose `axis.min` and `axis.max` are not specified). + */ + + _this._rangePropMode = ['percent', 'percent']; + return _this; + } + + DataZoomModel.prototype.init = function (option, parentModel, ecModel) { + var inputRawOption = retrieveRawOption(option); + /** + * Suppose a "main process" start at the point that model prepared (that is, + * model initialized or merged or method called in `action`). + * We should keep the `main process` idempotent, that is, given a set of values + * on `option`, we get the same result. + * + * But sometimes, values on `option` will be updated for providing users + * a "final calculated value" (`dataZoomProcessor` will do that). Those value + * should not be the base/input of the `main process`. + * + * So in that case we should save and keep the input of the `main process` + * separately, called `settledOption`. + * + * For example, consider the case: + * (Step_1) brush zoom the grid by `toolbox.dataZoom`, + * where the original input `option.startValue`, `option.endValue` are earsed by + * calculated value. + * (Step)2) click the legend to hide and show a series, + * where the new range is calculated by the earsed `startValue` and `endValue`, + * which brings incorrect result. + */ + + this.settledOption = inputRawOption; + this.mergeDefaultAndTheme(option, ecModel); + + this._doInit(inputRawOption); + }; + + DataZoomModel.prototype.mergeOption = function (newOption) { + var inputRawOption = retrieveRawOption(newOption); //FIX #2591 + + merge(this.option, newOption, true); + merge(this.settledOption, inputRawOption, true); + + this._doInit(inputRawOption); + }; + + DataZoomModel.prototype._doInit = function (inputRawOption) { + var thisOption = this.option; + + this._setDefaultThrottle(inputRawOption); + + this._updateRangeUse(inputRawOption); + + var settledOption = this.settledOption; + each([['start', 'startValue'], ['end', 'endValue']], function (names, index) { + // start/end has higher priority over startValue/endValue if they + // both set, but we should make chart.setOption({endValue: 1000}) + // effective, rather than chart.setOption({endValue: 1000, end: null}). + if (this._rangePropMode[index] === 'value') { + thisOption[names[0]] = settledOption[names[0]] = null; + } // Otherwise do nothing and use the merge result. + + }, this); + + this._resetTarget(); + }; + + DataZoomModel.prototype._resetTarget = function () { + var optionOrient = this.get('orient', true); + var targetAxisIndexMap = this._targetAxisInfoMap = createHashMap(); + + var hasAxisSpecified = this._fillSpecifiedTargetAxis(targetAxisIndexMap); + + if (hasAxisSpecified) { + this._orient = optionOrient || this._makeAutoOrientByTargetAxis(); + } else { + this._orient = optionOrient || 'horizontal'; + + this._fillAutoTargetAxisByOrient(targetAxisIndexMap, this._orient); + } + + this._noTarget = true; + targetAxisIndexMap.each(function (axisInfo) { + if (axisInfo.indexList.length) { + this._noTarget = false; + } + }, this); + }; + + DataZoomModel.prototype._fillSpecifiedTargetAxis = function (targetAxisIndexMap) { + var hasAxisSpecified = false; + each(DATA_ZOOM_AXIS_DIMENSIONS, function (axisDim) { + var refering = this.getReferringComponents(getAxisMainType(axisDim), MULTIPLE_REFERRING); // When user set axisIndex as a empty array, we think that user specify axisIndex + // but do not want use auto mode. Because empty array may be encountered when + // some error occured. + + if (!refering.specified) { + return; + } + + hasAxisSpecified = true; + var axisInfo = new DataZoomAxisInfo(); + each(refering.models, function (axisModel) { + axisInfo.add(axisModel.componentIndex); + }); + targetAxisIndexMap.set(axisDim, axisInfo); + }, this); + return hasAxisSpecified; + }; + + DataZoomModel.prototype._fillAutoTargetAxisByOrient = function (targetAxisIndexMap, orient) { + var ecModel = this.ecModel; + var needAuto = true; // Find axis that parallel to dataZoom as default. + + if (needAuto) { + var axisDim = orient === 'vertical' ? 'y' : 'x'; + var axisModels = ecModel.findComponents({ + mainType: axisDim + 'Axis' + }); + setParallelAxis(axisModels, axisDim); + } // Find axis that parallel to dataZoom as default. + + + if (needAuto) { + var axisModels = ecModel.findComponents({ + mainType: 'singleAxis', + filter: function (axisModel) { + return axisModel.get('orient', true) === orient; + } + }); + setParallelAxis(axisModels, 'single'); + } + + function setParallelAxis(axisModels, axisDim) { + // At least use the first parallel axis as the target axis. + var axisModel = axisModels[0]; + + if (!axisModel) { + return; + } + + var axisInfo = new DataZoomAxisInfo(); + axisInfo.add(axisModel.componentIndex); + targetAxisIndexMap.set(axisDim, axisInfo); + needAuto = false; // Find parallel axes in the same grid. + + if (axisDim === 'x' || axisDim === 'y') { + var gridModel_1 = axisModel.getReferringComponents('grid', SINGLE_REFERRING).models[0]; + gridModel_1 && each(axisModels, function (axModel) { + if (axisModel.componentIndex !== axModel.componentIndex && gridModel_1 === axModel.getReferringComponents('grid', SINGLE_REFERRING).models[0]) { + axisInfo.add(axModel.componentIndex); + } + }); + } + } + + if (needAuto) { + // If no parallel axis, find the first category axis as default. (Also consider polar). + each(DATA_ZOOM_AXIS_DIMENSIONS, function (axisDim) { + if (!needAuto) { + return; + } + + var axisModels = ecModel.findComponents({ + mainType: getAxisMainType(axisDim), + filter: function (axisModel) { + return axisModel.get('type', true) === 'category'; + } + }); + + if (axisModels[0]) { + var axisInfo = new DataZoomAxisInfo(); + axisInfo.add(axisModels[0].componentIndex); + targetAxisIndexMap.set(axisDim, axisInfo); + needAuto = false; + } + }, this); + } + }; + + DataZoomModel.prototype._makeAutoOrientByTargetAxis = function () { + var dim; // Find the first axis + + this.eachTargetAxis(function (axisDim) { + !dim && (dim = axisDim); + }, this); + return dim === 'y' ? 'vertical' : 'horizontal'; + }; + + DataZoomModel.prototype._setDefaultThrottle = function (inputRawOption) { + // When first time user set throttle, auto throttle ends. + if (inputRawOption.hasOwnProperty('throttle')) { + this._autoThrottle = false; + } + + if (this._autoThrottle) { + var globalOption = this.ecModel.option; + this.option.throttle = globalOption.animation && globalOption.animationDurationUpdate > 0 ? 100 : 20; + } + }; + + DataZoomModel.prototype._updateRangeUse = function (inputRawOption) { + var rangePropMode = this._rangePropMode; + var rangeModeInOption = this.get('rangeMode'); + each([['start', 'startValue'], ['end', 'endValue']], function (names, index) { + var percentSpecified = inputRawOption[names[0]] != null; + var valueSpecified = inputRawOption[names[1]] != null; + + if (percentSpecified && !valueSpecified) { + rangePropMode[index] = 'percent'; + } else if (!percentSpecified && valueSpecified) { + rangePropMode[index] = 'value'; + } else if (rangeModeInOption) { + rangePropMode[index] = rangeModeInOption[index]; + } else if (percentSpecified) { + // percentSpecified && valueSpecified + rangePropMode[index] = 'percent'; + } // else remain its original setting. + + }); + }; + + DataZoomModel.prototype.noTarget = function () { + return this._noTarget; + }; + + DataZoomModel.prototype.getFirstTargetAxisModel = function () { + var firstAxisModel; + this.eachTargetAxis(function (axisDim, axisIndex) { + if (firstAxisModel == null) { + firstAxisModel = this.ecModel.getComponent(getAxisMainType(axisDim), axisIndex); + } + }, this); + return firstAxisModel; + }; + /** + * @param {Function} callback param: axisModel, dimNames, axisIndex, dataZoomModel, ecModel + */ + + + DataZoomModel.prototype.eachTargetAxis = function (callback, context) { + this._targetAxisInfoMap.each(function (axisInfo, axisDim) { + each(axisInfo.indexList, function (axisIndex) { + callback.call(context, axisDim, axisIndex); + }); + }); + }; + /** + * @return If not found, return null/undefined. + */ + + + DataZoomModel.prototype.getAxisProxy = function (axisDim, axisIndex) { + var axisModel = this.getAxisModel(axisDim, axisIndex); + + if (axisModel) { + return axisModel.__dzAxisProxy; + } + }; + /** + * @return If not found, return null/undefined. + */ + + + DataZoomModel.prototype.getAxisModel = function (axisDim, axisIndex) { + if ("development" !== 'production') { + assert(axisDim && axisIndex != null); + } + + var axisInfo = this._targetAxisInfoMap.get(axisDim); + + if (axisInfo && axisInfo.indexMap[axisIndex]) { + return this.ecModel.getComponent(getAxisMainType(axisDim), axisIndex); + } + }; + /** + * If not specified, set to undefined. + */ + + + DataZoomModel.prototype.setRawRange = function (opt) { + var thisOption = this.option; + var settledOption = this.settledOption; + each([['start', 'startValue'], ['end', 'endValue']], function (names) { + // Consider the pair : + // If one has value and the other one is `null/undefined`, we both set them + // to `settledOption`. This strategy enables the feature to clear the original + // value in `settledOption` to `null/undefined`. + // But if both of them are `null/undefined`, we do not set them to `settledOption` + // and keep `settledOption` with the original value. This strategy enables users to + // only set but not set when calling + // `dispatchAction`. + // The pair is treated in the same way. + if (opt[names[0]] != null || opt[names[1]] != null) { + thisOption[names[0]] = settledOption[names[0]] = opt[names[0]]; + thisOption[names[1]] = settledOption[names[1]] = opt[names[1]]; + } + }, this); + + this._updateRangeUse(opt); + }; + + DataZoomModel.prototype.setCalculatedRange = function (opt) { + var option = this.option; + each(['start', 'startValue', 'end', 'endValue'], function (name) { + option[name] = opt[name]; + }); + }; + + DataZoomModel.prototype.getPercentRange = function () { + var axisProxy = this.findRepresentativeAxisProxy(); + + if (axisProxy) { + return axisProxy.getDataPercentWindow(); + } + }; + /** + * For example, chart.getModel().getComponent('dataZoom').getValueRange('y', 0); + * + * @return [startValue, endValue] value can only be '-' or finite number. + */ + + + DataZoomModel.prototype.getValueRange = function (axisDim, axisIndex) { + if (axisDim == null && axisIndex == null) { + var axisProxy = this.findRepresentativeAxisProxy(); + + if (axisProxy) { + return axisProxy.getDataValueWindow(); + } + } else { + return this.getAxisProxy(axisDim, axisIndex).getDataValueWindow(); + } + }; + /** + * @param axisModel If axisModel given, find axisProxy + * corresponding to the axisModel + */ + + + DataZoomModel.prototype.findRepresentativeAxisProxy = function (axisModel) { + if (axisModel) { + return axisModel.__dzAxisProxy; + } // Find the first hosted axisProxy + + + var firstProxy; + + var axisDimList = this._targetAxisInfoMap.keys(); + + for (var i = 0; i < axisDimList.length; i++) { + var axisDim = axisDimList[i]; + + var axisInfo = this._targetAxisInfoMap.get(axisDim); + + for (var j = 0; j < axisInfo.indexList.length; j++) { + var proxy = this.getAxisProxy(axisDim, axisInfo.indexList[j]); + + if (proxy.hostedBy(this)) { + return proxy; + } + + if (!firstProxy) { + firstProxy = proxy; + } + } + } // If no hosted proxy found, still need to return a proxy. + // This case always happens in toolbox dataZoom, where axes are all hosted by + // other dataZooms. + + + return firstProxy; + }; + + DataZoomModel.prototype.getRangePropMode = function () { + return this._rangePropMode.slice(); + }; + + DataZoomModel.prototype.getOrient = function () { + if ("development" !== 'production') { + // Should not be called before initialized. + assert(this._orient); + } + + return this._orient; + }; + + DataZoomModel.type = 'dataZoom'; + DataZoomModel.dependencies = ['xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'series', 'toolbox']; + DataZoomModel.defaultOption = { + // zlevel: 0, + z: 4, + filterMode: 'filter', + start: 0, + end: 100 + }; + return DataZoomModel; + }(ComponentModel); + /** + * Retrieve the those raw params from option, which will be cached separately. + * becasue they will be overwritten by normalized/calculated values in the main + * process. + */ + + + function retrieveRawOption(option) { + var ret = {}; + each(['start', 'end', 'startValue', 'endValue', 'throttle'], function (name) { + option.hasOwnProperty(name) && (ret[name] = option[name]); + }); + return ret; + } + + var SelectDataZoomModel = + /** @class */ + function (_super) { + __extends(SelectDataZoomModel, _super); + + function SelectDataZoomModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SelectDataZoomModel.type; + return _this; + } + + SelectDataZoomModel.type = 'dataZoom.select'; + return SelectDataZoomModel; + }(DataZoomModel); + + var DataZoomView = + /** @class */ + function (_super) { + __extends(DataZoomView, _super); + + function DataZoomView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = DataZoomView.type; + return _this; + } + + DataZoomView.prototype.render = function (dataZoomModel, ecModel, api, payload) { + this.dataZoomModel = dataZoomModel; + this.ecModel = ecModel; + this.api = api; + }; + + DataZoomView.type = 'dataZoom'; + return DataZoomView; + }(ComponentView); + + var SelectDataZoomView = + /** @class */ + function (_super) { + __extends(SelectDataZoomView, _super); + + function SelectDataZoomView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SelectDataZoomView.type; + return _this; + } + + SelectDataZoomView.type = 'dataZoom.select'; + return SelectDataZoomView; + }(DataZoomView); + + var each$8 = each; + var asc$1 = asc; + /** + * Operate single axis. + * One axis can only operated by one axis operator. + * Different dataZoomModels may be defined to operate the same axis. + * (i.e. 'inside' data zoom and 'slider' data zoom components) + * So dataZoomModels share one axisProxy in that case. + */ + + var AxisProxy = + /** @class */ + function () { + function AxisProxy(dimName, axisIndex, dataZoomModel, ecModel) { + this._dimName = dimName; + this._axisIndex = axisIndex; + this.ecModel = ecModel; + this._dataZoomModel = dataZoomModel; // /** + // * @readOnly + // * @private + // */ + // this.hasSeriesStacked; + } + /** + * Whether the axisProxy is hosted by dataZoomModel. + */ + + + AxisProxy.prototype.hostedBy = function (dataZoomModel) { + return this._dataZoomModel === dataZoomModel; + }; + /** + * @return Value can only be NaN or finite value. + */ + + + AxisProxy.prototype.getDataValueWindow = function () { + return this._valueWindow.slice(); + }; + /** + * @return {Array.} + */ + + + AxisProxy.prototype.getDataPercentWindow = function () { + return this._percentWindow.slice(); + }; + + AxisProxy.prototype.getTargetSeriesModels = function () { + var seriesModels = []; + this.ecModel.eachSeries(function (seriesModel) { + if (isCoordSupported(seriesModel)) { + var axisMainType = getAxisMainType(this._dimName); + var axisModel = seriesModel.getReferringComponents(axisMainType, SINGLE_REFERRING).models[0]; + + if (axisModel && this._axisIndex === axisModel.componentIndex) { + seriesModels.push(seriesModel); + } + } + }, this); + return seriesModels; + }; + + AxisProxy.prototype.getAxisModel = function () { + return this.ecModel.getComponent(this._dimName + 'Axis', this._axisIndex); + }; + + AxisProxy.prototype.getMinMaxSpan = function () { + return clone(this._minMaxSpan); + }; + /** + * Only calculate by given range and this._dataExtent, do not change anything. + */ + + + AxisProxy.prototype.calculateDataWindow = function (opt) { + var dataExtent = this._dataExtent; + var axisModel = this.getAxisModel(); + var scale = axisModel.axis.scale; + + var rangePropMode = this._dataZoomModel.getRangePropMode(); + + var percentExtent = [0, 100]; + var percentWindow = []; + var valueWindow = []; + var hasPropModeValue; + each$8(['start', 'end'], function (prop, idx) { + var boundPercent = opt[prop]; + var boundValue = opt[prop + 'Value']; // Notice: dataZoom is based either on `percentProp` ('start', 'end') or + // on `valueProp` ('startValue', 'endValue'). (They are based on the data extent + // but not min/max of axis, which will be calculated by data window then). + // The former one is suitable for cases that a dataZoom component controls multiple + // axes with different unit or extent, and the latter one is suitable for accurate + // zoom by pixel (e.g., in dataZoomSelect). + // we use `getRangePropMode()` to mark which prop is used. `rangePropMode` is updated + // only when setOption or dispatchAction, otherwise it remains its original value. + // (Why not only record `percentProp` and always map to `valueProp`? Because + // the map `valueProp` -> `percentProp` -> `valueProp` probably not the original + // `valueProp`. consider two axes constrolled by one dataZoom. They have different + // data extent. All of values that are overflow the `dataExtent` will be calculated + // to percent '100%'). + + if (rangePropMode[idx] === 'percent') { + boundPercent == null && (boundPercent = percentExtent[idx]); // Use scale.parse to math round for category or time axis. + + boundValue = scale.parse(linearMap(boundPercent, percentExtent, dataExtent)); + } else { + hasPropModeValue = true; + boundValue = boundValue == null ? dataExtent[idx] : scale.parse(boundValue); // Calculating `percent` from `value` may be not accurate, because + // This calculation can not be inversed, because all of values that + // are overflow the `dataExtent` will be calculated to percent '100%' + + boundPercent = linearMap(boundValue, dataExtent, percentExtent); + } // valueWindow[idx] = round(boundValue); + // percentWindow[idx] = round(boundPercent); + + + valueWindow[idx] = boundValue; + percentWindow[idx] = boundPercent; + }); + asc$1(valueWindow); + asc$1(percentWindow); // The windows from user calling of `dispatchAction` might be out of the extent, + // or do not obey the `min/maxSpan`, `min/maxValueSpan`. But we dont restrict window + // by `zoomLock` here, because we see `zoomLock` just as a interaction constraint, + // where API is able to initialize/modify the window size even though `zoomLock` + // specified. + + var spans = this._minMaxSpan; + hasPropModeValue ? restrictSet(valueWindow, percentWindow, dataExtent, percentExtent, false) : restrictSet(percentWindow, valueWindow, percentExtent, dataExtent, true); + + function restrictSet(fromWindow, toWindow, fromExtent, toExtent, toValue) { + var suffix = toValue ? 'Span' : 'ValueSpan'; + sliderMove(0, fromWindow, fromExtent, 'all', spans['min' + suffix], spans['max' + suffix]); + + for (var i = 0; i < 2; i++) { + toWindow[i] = linearMap(fromWindow[i], fromExtent, toExtent, true); + toValue && (toWindow[i] = scale.parse(toWindow[i])); + } + } + + return { + valueWindow: valueWindow, + percentWindow: percentWindow + }; + }; + /** + * Notice: reset should not be called before series.restoreData() called, + * so it is recommanded to be called in "process stage" but not "model init + * stage". + */ + + + AxisProxy.prototype.reset = function (dataZoomModel) { + if (dataZoomModel !== this._dataZoomModel) { + return; + } + + var targetSeries = this.getTargetSeriesModels(); // Culculate data window and data extent, and record them. + + this._dataExtent = calculateDataExtent(this, this._dimName, targetSeries); // `calculateDataWindow` uses min/maxSpan. + + this._updateMinMaxSpan(); + + var dataWindow = this.calculateDataWindow(dataZoomModel.settledOption); + this._valueWindow = dataWindow.valueWindow; + this._percentWindow = dataWindow.percentWindow; // Update axis setting then. + + this._setAxisModel(); + }; + + AxisProxy.prototype.filterData = function (dataZoomModel, api) { + if (dataZoomModel !== this._dataZoomModel) { + return; + } + + var axisDim = this._dimName; + var seriesModels = this.getTargetSeriesModels(); + var filterMode = dataZoomModel.get('filterMode'); + var valueWindow = this._valueWindow; + + if (filterMode === 'none') { + return; + } // FIXME + // Toolbox may has dataZoom injected. And if there are stacked bar chart + // with NaN data, NaN will be filtered and stack will be wrong. + // So we need to force the mode to be set empty. + // In fect, it is not a big deal that do not support filterMode-'filter' + // when using toolbox#dataZoom, utill tooltip#dataZoom support "single axis + // selection" some day, which might need "adapt to data extent on the + // otherAxis", which is disabled by filterMode-'empty'. + // But currently, stack has been fixed to based on value but not index, + // so this is not an issue any more. + // let otherAxisModel = this.getOtherAxisModel(); + // if (dataZoomModel.get('$fromToolbox') + // && otherAxisModel + // && otherAxisModel.hasSeriesStacked + // ) { + // filterMode = 'empty'; + // } + // TODO + // filterMode 'weakFilter' and 'empty' is not optimized for huge data yet. + + + each$8(seriesModels, function (seriesModel) { + var seriesData = seriesModel.getData(); + var dataDims = seriesData.mapDimensionsAll(axisDim); + + if (!dataDims.length) { + return; + } + + if (filterMode === 'weakFilter') { + var store_1 = seriesData.getStore(); + var dataDimIndices_1 = map(dataDims, function (dim) { + return seriesData.getDimensionIndex(dim); + }, seriesData); + seriesData.filterSelf(function (dataIndex) { + var leftOut; + var rightOut; + var hasValue; + + for (var i = 0; i < dataDims.length; i++) { + var value = store_1.get(dataDimIndices_1[i], dataIndex); + var thisHasValue = !isNaN(value); + var thisLeftOut = value < valueWindow[0]; + var thisRightOut = value > valueWindow[1]; + + if (thisHasValue && !thisLeftOut && !thisRightOut) { + return true; + } + + thisHasValue && (hasValue = true); + thisLeftOut && (leftOut = true); + thisRightOut && (rightOut = true); + } // If both left out and right out, do not filter. + + + return hasValue && leftOut && rightOut; + }); + } else { + each$8(dataDims, function (dim) { + if (filterMode === 'empty') { + seriesModel.setData(seriesData = seriesData.map(dim, function (value) { + return !isInWindow(value) ? NaN : value; + })); + } else { + var range = {}; + range[dim] = valueWindow; // console.time('select'); + + seriesData.selectRange(range); // console.timeEnd('select'); + } + }); + } + + each$8(dataDims, function (dim) { + seriesData.setApproximateExtent(valueWindow, dim); + }); + }); + + function isInWindow(value) { + return value >= valueWindow[0] && value <= valueWindow[1]; + } + }; + + AxisProxy.prototype._updateMinMaxSpan = function () { + var minMaxSpan = this._minMaxSpan = {}; + var dataZoomModel = this._dataZoomModel; + var dataExtent = this._dataExtent; + each$8(['min', 'max'], function (minMax) { + var percentSpan = dataZoomModel.get(minMax + 'Span'); + var valueSpan = dataZoomModel.get(minMax + 'ValueSpan'); + valueSpan != null && (valueSpan = this.getAxisModel().axis.scale.parse(valueSpan)); // minValueSpan and maxValueSpan has higher priority than minSpan and maxSpan + + if (valueSpan != null) { + percentSpan = linearMap(dataExtent[0] + valueSpan, dataExtent, [0, 100], true); + } else if (percentSpan != null) { + valueSpan = linearMap(percentSpan, [0, 100], dataExtent, true) - dataExtent[0]; + } + + minMaxSpan[minMax + 'Span'] = percentSpan; + minMaxSpan[minMax + 'ValueSpan'] = valueSpan; + }, this); + }; + + AxisProxy.prototype._setAxisModel = function () { + var axisModel = this.getAxisModel(); + var percentWindow = this._percentWindow; + var valueWindow = this._valueWindow; + + if (!percentWindow) { + return; + } // [0, 500]: arbitrary value, guess axis extent. + + + var precision = getPixelPrecision(valueWindow, [0, 500]); + precision = Math.min(precision, 20); // For value axis, if min/max/scale are not set, we just use the extent obtained + // by series data, which may be a little different from the extent calculated by + // `axisHelper.getScaleExtent`. But the different just affects the experience a + // little when zooming. So it will not be fixed until some users require it strongly. + + var rawExtentInfo = axisModel.axis.scale.rawExtentInfo; + + if (percentWindow[0] !== 0) { + rawExtentInfo.setDeterminedMinMax('min', +valueWindow[0].toFixed(precision)); + } + + if (percentWindow[1] !== 100) { + rawExtentInfo.setDeterminedMinMax('max', +valueWindow[1].toFixed(precision)); + } + + rawExtentInfo.freeze(); + }; + + return AxisProxy; + }(); + + function calculateDataExtent(axisProxy, axisDim, seriesModels) { + var dataExtent = [Infinity, -Infinity]; + each$8(seriesModels, function (seriesModel) { + unionAxisExtentFromData(dataExtent, seriesModel.getData(), axisDim); + }); // It is important to get "consistent" extent when more then one axes is + // controlled by a `dataZoom`, otherwise those axes will not be synchronized + // when zooming. But it is difficult to know what is "consistent", considering + // axes have different type or even different meanings (For example, two + // time axes are used to compare data of the same date in different years). + // So basically dataZoom just obtains extent by series.data (in category axis + // extent can be obtained from axis.data). + // Nevertheless, user can set min/max/scale on axes to make extent of axes + // consistent. + + var axisModel = axisProxy.getAxisModel(); + var rawExtentResult = ensureScaleRawExtentInfo(axisModel.axis.scale, axisModel, dataExtent).calculate(); + return [rawExtentResult.min, rawExtentResult.max]; + } + + var dataZoomProcessor = { + // `dataZoomProcessor` will only be performed in needed series. Consider if + // there is a line series and a pie series, it is better not to update the + // line series if only pie series is needed to be updated. + getTargetSeries: function (ecModel) { + function eachAxisModel(cb) { + ecModel.eachComponent('dataZoom', function (dataZoomModel) { + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + var axisModel = ecModel.getComponent(getAxisMainType(axisDim), axisIndex); + cb(axisDim, axisIndex, axisModel, dataZoomModel); + }); + }); + } // FIXME: it brings side-effect to `getTargetSeries`. + // Prepare axis proxies. + + + eachAxisModel(function (axisDim, axisIndex, axisModel, dataZoomModel) { + // dispose all last axis proxy, in case that some axis are deleted. + axisModel.__dzAxisProxy = null; + }); + var proxyList = []; + eachAxisModel(function (axisDim, axisIndex, axisModel, dataZoomModel) { + // Different dataZooms may constrol the same axis. In that case, + // an axisProxy serves both of them. + if (!axisModel.__dzAxisProxy) { + // Use the first dataZoomModel as the main model of axisProxy. + axisModel.__dzAxisProxy = new AxisProxy(axisDim, axisIndex, dataZoomModel, ecModel); + proxyList.push(axisModel.__dzAxisProxy); + } + }); + var seriesModelMap = createHashMap(); + each(proxyList, function (axisProxy) { + each(axisProxy.getTargetSeriesModels(), function (seriesModel) { + seriesModelMap.set(seriesModel.uid, seriesModel); + }); + }); + return seriesModelMap; + }, + // Consider appendData, where filter should be performed. Because data process is + // in block mode currently, it is not need to worry about that the overallProgress + // execute every frame. + overallReset: function (ecModel, api) { + ecModel.eachComponent('dataZoom', function (dataZoomModel) { + // We calculate window and reset axis here but not in model + // init stage and not after action dispatch handler, because + // reset should be called after seriesData.restoreData. + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + dataZoomModel.getAxisProxy(axisDim, axisIndex).reset(dataZoomModel); + }); // Caution: data zoom filtering is order sensitive when using + // percent range and no min/max/scale set on axis. + // For example, we have dataZoom definition: + // [ + // {xAxisIndex: 0, start: 30, end: 70}, + // {yAxisIndex: 0, start: 20, end: 80} + // ] + // In this case, [20, 80] of y-dataZoom should be based on data + // that have filtered by x-dataZoom using range of [30, 70], + // but should not be based on full raw data. Thus sliding + // x-dataZoom will change both ranges of xAxis and yAxis, + // while sliding y-dataZoom will only change the range of yAxis. + // So we should filter x-axis after reset x-axis immediately, + // and then reset y-axis and filter y-axis. + + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + dataZoomModel.getAxisProxy(axisDim, axisIndex).filterData(dataZoomModel, api); + }); + }); + ecModel.eachComponent('dataZoom', function (dataZoomModel) { + // Fullfill all of the range props so that user + // is able to get them from chart.getOption(). + var axisProxy = dataZoomModel.findRepresentativeAxisProxy(); + + if (axisProxy) { + var percentRange = axisProxy.getDataPercentWindow(); + var valueRange = axisProxy.getDataValueWindow(); + dataZoomModel.setCalculatedRange({ + start: percentRange[0], + end: percentRange[1], + startValue: valueRange[0], + endValue: valueRange[1] + }); + } + }); + } + }; + + function installDataZoomAction(registers) { + registers.registerAction('dataZoom', function (payload, ecModel) { + var effectedModels = findEffectedDataZooms(ecModel, payload); + each(effectedModels, function (dataZoomModel) { + dataZoomModel.setRawRange({ + start: payload.start, + end: payload.end, + startValue: payload.startValue, + endValue: payload.endValue + }); + }); + }); + } + + var installed = false; + function installCommon(registers) { + if (installed) { + return; + } + + installed = true; + registers.registerProcessor(registers.PRIORITY.PROCESSOR.FILTER, dataZoomProcessor); + installDataZoomAction(registers); + registers.registerSubTypeDefaulter('dataZoom', function () { + // Default 'slider' when no type specified. + return 'slider'; + }); + } + + function install$y(registers) { + registers.registerComponentModel(SelectDataZoomModel); + registers.registerComponentView(SelectDataZoomView); + installCommon(registers); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var ToolboxFeature = + /** @class */ + function () { + function ToolboxFeature() {} + + return ToolboxFeature; + }(); + var features = {}; + function registerFeature(name, ctor) { + features[name] = ctor; + } + function getFeature(name) { + return features[name]; + } + + var ToolboxModel = + /** @class */ + function (_super) { + __extends(ToolboxModel, _super); + + function ToolboxModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ToolboxModel.type; + return _this; + } + + ToolboxModel.prototype.optionUpdated = function () { + _super.prototype.optionUpdated.apply(this, arguments); + + var ecModel = this.ecModel; + each(this.option.feature, function (featureOpt, featureName) { + var Feature = getFeature(featureName); + + if (Feature) { + if (Feature.getDefaultOption) { + Feature.defaultOption = Feature.getDefaultOption(ecModel); + } + + merge(featureOpt, Feature.defaultOption); + } + }); + }; + + ToolboxModel.type = 'toolbox'; + ToolboxModel.layoutMode = { + type: 'box', + ignoreSize: true + }; + ToolboxModel.defaultOption = { + show: true, + z: 6, + // zlevel: 0, + orient: 'horizontal', + left: 'right', + top: 'top', + // right + // bottom + backgroundColor: 'transparent', + borderColor: '#ccc', + borderRadius: 0, + borderWidth: 0, + padding: 5, + itemSize: 15, + itemGap: 8, + showTitle: true, + iconStyle: { + borderColor: '#666', + color: 'none' + }, + emphasis: { + iconStyle: { + borderColor: '#3E98C5' + } + }, + // textStyle: {}, + // feature + tooltip: { + show: false, + position: 'bottom' + } + }; + return ToolboxModel; + }(ComponentModel); + + /** + * Layout list like component. + * It will box layout each items in group of component and then position the whole group in the viewport + * @param {module:zrender/group/Group} group + * @param {module:echarts/model/Component} componentModel + * @param {module:echarts/ExtensionAPI} + */ + + function layout$3(group, componentModel, api) { + var boxLayoutParams = componentModel.getBoxLayoutParams(); + var padding = componentModel.get('padding'); + var viewportSize = { + width: api.getWidth(), + height: api.getHeight() + }; + var rect = getLayoutRect(boxLayoutParams, viewportSize, padding); + box(componentModel.get('orient'), group, componentModel.get('itemGap'), rect.width, rect.height); + positionElement(group, boxLayoutParams, viewportSize, padding); + } + function makeBackground(rect, componentModel) { + var padding = normalizeCssArray$1(componentModel.get('padding')); + var style = componentModel.getItemStyle(['color', 'opacity']); + style.fill = componentModel.get('backgroundColor'); + rect = new Rect({ + shape: { + x: rect.x - padding[3], + y: rect.y - padding[0], + width: rect.width + padding[1] + padding[3], + height: rect.height + padding[0] + padding[2], + r: componentModel.get('borderRadius') + }, + style: style, + silent: true, + z2: -1 + }); // FIXME + // `subPixelOptimizeRect` may bring some gap between edge of viewpart + // and background rect when setting like `left: 0`, `top: 0`. + // graphic.subPixelOptimizeRect(rect); + + return rect; + } + + var ToolboxView = + /** @class */ + function (_super) { + __extends(ToolboxView, _super); + + function ToolboxView() { + return _super !== null && _super.apply(this, arguments) || this; + } + + ToolboxView.prototype.render = function (toolboxModel, ecModel, api, payload) { + var group = this.group; + group.removeAll(); + + if (!toolboxModel.get('show')) { + return; + } + + var itemSize = +toolboxModel.get('itemSize'); + var isVertical = toolboxModel.get('orient') === 'vertical'; + var featureOpts = toolboxModel.get('feature') || {}; + var features = this._features || (this._features = {}); + var featureNames = []; + each(featureOpts, function (opt, name) { + featureNames.push(name); + }); + new DataDiffer(this._featureNames || [], featureNames).add(processFeature).update(processFeature).remove(curry(processFeature, null)).execute(); // Keep for diff. + + this._featureNames = featureNames; + + function processFeature(newIndex, oldIndex) { + var featureName = featureNames[newIndex]; + var oldName = featureNames[oldIndex]; + var featureOpt = featureOpts[featureName]; + var featureModel = new Model(featureOpt, toolboxModel, toolboxModel.ecModel); + var feature; // FIX#11236, merge feature title from MagicType newOption. TODO: consider seriesIndex ? + + if (payload && payload.newTitle != null && payload.featureName === featureName) { + featureOpt.title = payload.newTitle; + } + + if (featureName && !oldName) { + // Create + if (isUserFeatureName(featureName)) { + feature = { + onclick: featureModel.option.onclick, + featureName: featureName + }; + } else { + var Feature = getFeature(featureName); + + if (!Feature) { + return; + } + + feature = new Feature(); + } + + features[featureName] = feature; + } else { + feature = features[oldName]; // If feature does not exsit. + + if (!feature) { + return; + } + } + + feature.uid = getUID('toolbox-feature'); + feature.model = featureModel; + feature.ecModel = ecModel; + feature.api = api; + var isToolboxFeature = feature instanceof ToolboxFeature; + + if (!featureName && oldName) { + isToolboxFeature && feature.dispose && feature.dispose(ecModel, api); + return; + } + + if (!featureModel.get('show') || isToolboxFeature && feature.unusable) { + isToolboxFeature && feature.remove && feature.remove(ecModel, api); + return; + } + + createIconPaths(featureModel, feature, featureName); + + featureModel.setIconStatus = function (iconName, status) { + var option = this.option; + var iconPaths = this.iconPaths; + option.iconStatus = option.iconStatus || {}; + option.iconStatus[iconName] = status; + + if (iconPaths[iconName]) { + (status === 'emphasis' ? enterEmphasis : leaveEmphasis)(iconPaths[iconName]); + } + }; + + if (feature instanceof ToolboxFeature) { + if (feature.render) { + feature.render(featureModel, ecModel, api, payload); + } + } + } + + function createIconPaths(featureModel, feature, featureName) { + var iconStyleModel = featureModel.getModel('iconStyle'); + var iconStyleEmphasisModel = featureModel.getModel(['emphasis', 'iconStyle']); // If one feature has mutiple icon. they are orginaized as + // { + // icon: { + // foo: '', + // bar: '' + // }, + // title: { + // foo: '', + // bar: '' + // } + // } + + var icons = feature instanceof ToolboxFeature && feature.getIcons ? feature.getIcons() : featureModel.get('icon'); + var titles = featureModel.get('title') || {}; + var iconsMap; + var titlesMap; + + if (isString(icons)) { + iconsMap = {}; + iconsMap[featureName] = icons; + } else { + iconsMap = icons; + } + + if (isString(titles)) { + titlesMap = {}; + titlesMap[featureName] = titles; + } else { + titlesMap = titles; + } + + var iconPaths = featureModel.iconPaths = {}; + each(iconsMap, function (iconStr, iconName) { + var path = createIcon(iconStr, {}, { + x: -itemSize / 2, + y: -itemSize / 2, + width: itemSize, + height: itemSize + }); // TODO handling image + + path.setStyle(iconStyleModel.getItemStyle()); + var pathEmphasisState = path.ensureState('emphasis'); + pathEmphasisState.style = iconStyleEmphasisModel.getItemStyle(); // Text position calculation + + var textContent = new ZRText({ + style: { + text: titlesMap[iconName], + align: iconStyleEmphasisModel.get('textAlign'), + borderRadius: iconStyleEmphasisModel.get('textBorderRadius'), + padding: iconStyleEmphasisModel.get('textPadding'), + fill: null + }, + ignore: true + }); + path.setTextContent(textContent); + setTooltipConfig({ + el: path, + componentModel: toolboxModel, + itemName: iconName, + formatterParamsExtra: { + title: titlesMap[iconName] + } + }); + path.__title = titlesMap[iconName]; + path.on('mouseover', function () { + // Should not reuse above hoverStyle, which might be modified. + var hoverStyle = iconStyleEmphasisModel.getItemStyle(); + var defaultTextPosition = isVertical ? toolboxModel.get('right') == null && toolboxModel.get('left') !== 'right' ? 'right' : 'left' : toolboxModel.get('bottom') == null && toolboxModel.get('top') !== 'bottom' ? 'bottom' : 'top'; + textContent.setStyle({ + fill: iconStyleEmphasisModel.get('textFill') || hoverStyle.fill || hoverStyle.stroke || '#000', + backgroundColor: iconStyleEmphasisModel.get('textBackgroundColor') + }); + path.setTextConfig({ + position: iconStyleEmphasisModel.get('textPosition') || defaultTextPosition + }); + textContent.ignore = !toolboxModel.get('showTitle'); // Use enterEmphasis and leaveEmphasis provide by ec. + // There are flags managed by the echarts. + + api.enterEmphasis(this); + }).on('mouseout', function () { + if (featureModel.get(['iconStatus', iconName]) !== 'emphasis') { + api.leaveEmphasis(this); + } + + textContent.hide(); + }); + (featureModel.get(['iconStatus', iconName]) === 'emphasis' ? enterEmphasis : leaveEmphasis)(path); + group.add(path); + path.on('click', bind(feature.onclick, feature, ecModel, api, iconName)); + iconPaths[iconName] = path; + }); + } + + layout$3(group, toolboxModel, api); // Render background after group is layout + // FIXME + + group.add(makeBackground(group.getBoundingRect(), toolboxModel)); // Adjust icon title positions to avoid them out of screen + + isVertical || group.eachChild(function (icon) { + var titleText = icon.__title; // const hoverStyle = icon.hoverStyle; + // TODO simplify code? + + var emphasisState = icon.ensureState('emphasis'); + var emphasisTextConfig = emphasisState.textConfig || (emphasisState.textConfig = {}); + var textContent = icon.getTextContent(); + var emphasisTextState = textContent && textContent.ensureState('emphasis'); // May be background element + + if (emphasisTextState && !isFunction(emphasisTextState) && titleText) { + var emphasisTextStyle = emphasisTextState.style || (emphasisTextState.style = {}); + var rect = getBoundingRect(titleText, ZRText.makeFont(emphasisTextStyle)); + var offsetX = icon.x + group.x; + var offsetY = icon.y + group.y + itemSize; + var needPutOnTop = false; + + if (offsetY + rect.height > api.getHeight()) { + emphasisTextConfig.position = 'top'; + needPutOnTop = true; + } + + var topOffset = needPutOnTop ? -5 - rect.height : itemSize + 10; + + if (offsetX + rect.width / 2 > api.getWidth()) { + emphasisTextConfig.position = ['100%', topOffset]; + emphasisTextStyle.align = 'right'; + } else if (offsetX - rect.width / 2 < 0) { + emphasisTextConfig.position = [0, topOffset]; + emphasisTextStyle.align = 'left'; + } + } + }); + }; + + ToolboxView.prototype.updateView = function (toolboxModel, ecModel, api, payload) { + each(this._features, function (feature) { + feature instanceof ToolboxFeature && feature.updateView && feature.updateView(feature.model, ecModel, api, payload); + }); + }; // updateLayout(toolboxModel, ecModel, api, payload) { + // zrUtil.each(this._features, function (feature) { + // feature.updateLayout && feature.updateLayout(feature.model, ecModel, api, payload); + // }); + // }, + + + ToolboxView.prototype.remove = function (ecModel, api) { + each(this._features, function (feature) { + feature instanceof ToolboxFeature && feature.remove && feature.remove(ecModel, api); + }); + this.group.removeAll(); + }; + + ToolboxView.prototype.dispose = function (ecModel, api) { + each(this._features, function (feature) { + feature instanceof ToolboxFeature && feature.dispose && feature.dispose(ecModel, api); + }); + }; + + ToolboxView.type = 'toolbox'; + return ToolboxView; + }(ComponentView); + + function isUserFeatureName(featureName) { + return featureName.indexOf('my') === 0; + } + + /* global window, document */ + + var SaveAsImage = + /** @class */ + function (_super) { + __extends(SaveAsImage, _super); + + function SaveAsImage() { + return _super !== null && _super.apply(this, arguments) || this; + } + + SaveAsImage.prototype.onclick = function (ecModel, api) { + var model = this.model; + var title = model.get('name') || ecModel.get('title.0.text') || 'echarts'; + var isSvg = api.getZr().painter.getType() === 'svg'; + var type = isSvg ? 'svg' : model.get('type', true) || 'png'; + var url = api.getConnectedDataURL({ + type: type, + backgroundColor: model.get('backgroundColor', true) || ecModel.get('backgroundColor') || '#fff', + connectedBackgroundColor: model.get('connectedBackgroundColor'), + excludeComponents: model.get('excludeComponents'), + pixelRatio: model.get('pixelRatio') + }); + var browser = env.browser; // Chrome, Firefox, New Edge + + if (isFunction(MouseEvent) && (browser.newEdge || !browser.ie && !browser.edge)) { + var $a = document.createElement('a'); + $a.download = title + '.' + type; + $a.target = '_blank'; + $a.href = url; + var evt = new MouseEvent('click', { + // some micro front-end framework, window maybe is a Proxy + view: document.defaultView, + bubbles: true, + cancelable: false + }); + $a.dispatchEvent(evt); + } // IE or old Edge + else { + // @ts-ignore + if (window.navigator.msSaveOrOpenBlob || isSvg) { + var parts = url.split(','); // data:[][;charset=][;base64], + + var base64Encoded = parts[0].indexOf('base64') > -1; + var bstr = isSvg // should decode the svg data uri first + ? decodeURIComponent(parts[1]) : parts[1]; // only `atob` when the data uri is encoded with base64 + // otherwise, like `svg` data uri exported by zrender, + // there will be an error, for it's not encoded with base64. + // (just a url-encoded string through `encodeURIComponent`) + + base64Encoded && (bstr = window.atob(bstr)); + var filename = title + '.' + type; // @ts-ignore + + if (window.navigator.msSaveOrOpenBlob) { + var n = bstr.length; + var u8arr = new Uint8Array(n); + + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + + var blob = new Blob([u8arr]); // @ts-ignore + + window.navigator.msSaveOrOpenBlob(blob, filename); + } else { + var frame = document.createElement('iframe'); + document.body.appendChild(frame); + var cw = frame.contentWindow; + var doc = cw.document; + doc.open('image/svg+xml', 'replace'); + doc.write(bstr); + doc.close(); + cw.focus(); + doc.execCommand('SaveAs', true, filename); + document.body.removeChild(frame); + } + } else { + var lang = model.get('lang'); + var html = '' + '' + '' + ''; + var tab = window.open(); + tab.document.write(html); + tab.document.title = title; + } + } + }; + + SaveAsImage.getDefaultOption = function (ecModel) { + var defaultOption = { + show: true, + icon: 'M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0', + title: ecModel.getLocaleModel().get(['toolbox', 'saveAsImage', 'title']), + type: 'png', + // Default use option.backgroundColor + // backgroundColor: '#fff', + connectedBackgroundColor: '#fff', + name: '', + excludeComponents: ['toolbox'], + // use current pixel ratio of device by default + // pixelRatio: 1, + lang: ecModel.getLocaleModel().get(['toolbox', 'saveAsImage', 'lang']) + }; + return defaultOption; + }; + + return SaveAsImage; + }(ToolboxFeature); + + var INNER_STACK_KEYWORD = '__ec_magicType_stack__'; + var radioTypes = [['line', 'bar'], ['stack']]; + + var MagicType = + /** @class */ + function (_super) { + __extends(MagicType, _super); + + function MagicType() { + return _super !== null && _super.apply(this, arguments) || this; + } + + MagicType.prototype.getIcons = function () { + var model = this.model; + var availableIcons = model.get('icon'); + var icons = {}; + each(model.get('type'), function (type) { + if (availableIcons[type]) { + icons[type] = availableIcons[type]; + } + }); + return icons; + }; + + MagicType.getDefaultOption = function (ecModel) { + var defaultOption = { + show: true, + type: [], + // Icon group + icon: { + line: 'M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4', + bar: 'M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7', + // eslint-disable-next-line + stack: 'M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z' // jshint ignore:line + + }, + // `line`, `bar`, `stack`, `tiled` + title: ecModel.getLocaleModel().get(['toolbox', 'magicType', 'title']), + option: {}, + seriesIndex: {} + }; + return defaultOption; + }; + + MagicType.prototype.onclick = function (ecModel, api, type) { + var model = this.model; + var seriesIndex = model.get(['seriesIndex', type]); // Not supported magicType + + if (!seriesOptGenreator[type]) { + return; + } + + var newOption = { + series: [] + }; + + var generateNewSeriesTypes = function (seriesModel) { + var seriesType = seriesModel.subType; + var seriesId = seriesModel.id; + var newSeriesOpt = seriesOptGenreator[type](seriesType, seriesId, seriesModel, model); + + if (newSeriesOpt) { + // PENDING If merge original option? + defaults(newSeriesOpt, seriesModel.option); + newOption.series.push(newSeriesOpt); + } // Modify boundaryGap + + + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && coordSys.type === 'cartesian2d' && (type === 'line' || type === 'bar')) { + var categoryAxis = coordSys.getAxesByScale('ordinal')[0]; + + if (categoryAxis) { + var axisDim = categoryAxis.dim; + var axisType = axisDim + 'Axis'; + var axisModel = seriesModel.getReferringComponents(axisType, SINGLE_REFERRING).models[0]; + var axisIndex = axisModel.componentIndex; + newOption[axisType] = newOption[axisType] || []; + + for (var i = 0; i <= axisIndex; i++) { + newOption[axisType][axisIndex] = newOption[axisType][axisIndex] || {}; + } + + newOption[axisType][axisIndex].boundaryGap = type === 'bar'; + } + } + }; + + each(radioTypes, function (radio) { + if (indexOf(radio, type) >= 0) { + each(radio, function (item) { + model.setIconStatus(item, 'normal'); + }); + } + }); + model.setIconStatus(type, 'emphasis'); + ecModel.eachComponent({ + mainType: 'series', + query: seriesIndex == null ? null : { + seriesIndex: seriesIndex + } + }, generateNewSeriesTypes); + var newTitle; + var currentType = type; // Change title of stack + + if (type === 'stack') { + // use titles in model instead of ecModel + // as stack and tiled appears in pair, just flip them + // no need of checking stack state + newTitle = merge({ + stack: model.option.title.tiled, + tiled: model.option.title.stack + }, model.option.title); + + if (model.get(['iconStatus', type]) !== 'emphasis') { + currentType = 'tiled'; + } + } + + api.dispatchAction({ + type: 'changeMagicType', + currentType: currentType, + newOption: newOption, + newTitle: newTitle, + featureName: 'magicType' + }); + }; + + return MagicType; + }(ToolboxFeature); + + var seriesOptGenreator = { + 'line': function (seriesType, seriesId, seriesModel, model) { + if (seriesType === 'bar') { + return merge({ + id: seriesId, + type: 'line', + // Preserve data related option + data: seriesModel.get('data'), + stack: seriesModel.get('stack'), + markPoint: seriesModel.get('markPoint'), + markLine: seriesModel.get('markLine') + }, model.get(['option', 'line']) || {}, true); + } + }, + 'bar': function (seriesType, seriesId, seriesModel, model) { + if (seriesType === 'line') { + return merge({ + id: seriesId, + type: 'bar', + // Preserve data related option + data: seriesModel.get('data'), + stack: seriesModel.get('stack'), + markPoint: seriesModel.get('markPoint'), + markLine: seriesModel.get('markLine') + }, model.get(['option', 'bar']) || {}, true); + } + }, + 'stack': function (seriesType, seriesId, seriesModel, model) { + var isStack = seriesModel.get('stack') === INNER_STACK_KEYWORD; + + if (seriesType === 'line' || seriesType === 'bar') { + model.setIconStatus('stack', isStack ? 'normal' : 'emphasis'); + return merge({ + id: seriesId, + stack: isStack ? '' : INNER_STACK_KEYWORD + }, model.get(['option', 'stack']) || {}, true); + } + } + }; // TODO: SELF REGISTERED. + + registerAction({ + type: 'changeMagicType', + event: 'magicTypeChanged', + update: 'prepareAndUpdate' + }, function (payload, ecModel) { + ecModel.mergeOption(payload.newOption); + }); + + /* global document */ + + var BLOCK_SPLITER = new Array(60).join('-'); + var ITEM_SPLITER = '\t'; + /** + * Group series into two types + * 1. on category axis, like line, bar + * 2. others, like scatter, pie + */ + + function groupSeries(ecModel) { + var seriesGroupByCategoryAxis = {}; + var otherSeries = []; + var meta = []; + ecModel.eachRawSeries(function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && (coordSys.type === 'cartesian2d' || coordSys.type === 'polar')) { + // TODO: TYPE Consider polar? Include polar may increase unecessary bundle size. + var baseAxis = coordSys.getBaseAxis(); + + if (baseAxis.type === 'category') { + var key = baseAxis.dim + '_' + baseAxis.index; + + if (!seriesGroupByCategoryAxis[key]) { + seriesGroupByCategoryAxis[key] = { + categoryAxis: baseAxis, + valueAxis: coordSys.getOtherAxis(baseAxis), + series: [] + }; + meta.push({ + axisDim: baseAxis.dim, + axisIndex: baseAxis.index + }); + } + + seriesGroupByCategoryAxis[key].series.push(seriesModel); + } else { + otherSeries.push(seriesModel); + } + } else { + otherSeries.push(seriesModel); + } + }); + return { + seriesGroupByCategoryAxis: seriesGroupByCategoryAxis, + other: otherSeries, + meta: meta + }; + } + /** + * Assemble content of series on cateogory axis + * @inner + */ + + + function assembleSeriesWithCategoryAxis(groups) { + var tables = []; + each(groups, function (group, key) { + var categoryAxis = group.categoryAxis; + var valueAxis = group.valueAxis; + var valueAxisDim = valueAxis.dim; + var headers = [' '].concat(map(group.series, function (series) { + return series.name; + })); // @ts-ignore TODO Polar + + var columns = [categoryAxis.model.getCategories()]; + each(group.series, function (series) { + var rawData = series.getRawData(); + columns.push(series.getRawData().mapArray(rawData.mapDimension(valueAxisDim), function (val) { + return val; + })); + }); // Assemble table content + + var lines = [headers.join(ITEM_SPLITER)]; + + for (var i = 0; i < columns[0].length; i++) { + var items = []; + + for (var j = 0; j < columns.length; j++) { + items.push(columns[j][i]); + } + + lines.push(items.join(ITEM_SPLITER)); + } + + tables.push(lines.join('\n')); + }); + return tables.join('\n\n' + BLOCK_SPLITER + '\n\n'); + } + /** + * Assemble content of other series + */ + + + function assembleOtherSeries(series) { + return map(series, function (series) { + var data = series.getRawData(); + var lines = [series.name]; + var vals = []; + data.each(data.dimensions, function () { + var argLen = arguments.length; + var dataIndex = arguments[argLen - 1]; + var name = data.getName(dataIndex); + + for (var i = 0; i < argLen - 1; i++) { + vals[i] = arguments[i]; + } + + lines.push((name ? name + ITEM_SPLITER : '') + vals.join(ITEM_SPLITER)); + }); + return lines.join('\n'); + }).join('\n\n' + BLOCK_SPLITER + '\n\n'); + } + + function getContentFromModel(ecModel) { + var result = groupSeries(ecModel); + return { + value: filter([assembleSeriesWithCategoryAxis(result.seriesGroupByCategoryAxis), assembleOtherSeries(result.other)], function (str) { + return !!str.replace(/[\n\t\s]/g, ''); + }).join('\n\n' + BLOCK_SPLITER + '\n\n'), + meta: result.meta + }; + } + + function trim$1(str) { + return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + } + /** + * If a block is tsv format + */ + + + function isTSVFormat(block) { + // Simple method to find out if a block is tsv format + var firstLine = block.slice(0, block.indexOf('\n')); + + if (firstLine.indexOf(ITEM_SPLITER) >= 0) { + return true; + } + } + + var itemSplitRegex = new RegExp('[' + ITEM_SPLITER + ']+', 'g'); + /** + * @param {string} tsv + * @return {Object} + */ + + function parseTSVContents(tsv) { + var tsvLines = tsv.split(/\n+/g); + var headers = trim$1(tsvLines.shift()).split(itemSplitRegex); + var categories = []; + var series = map(headers, function (header) { + return { + name: header, + data: [] + }; + }); + + for (var i = 0; i < tsvLines.length; i++) { + var items = trim$1(tsvLines[i]).split(itemSplitRegex); + categories.push(items.shift()); + + for (var j = 0; j < items.length; j++) { + series[j] && (series[j].data[i] = items[j]); + } + } + + return { + series: series, + categories: categories + }; + } + + function parseListContents(str) { + var lines = str.split(/\n+/g); + var seriesName = trim$1(lines.shift()); + var data = []; + + for (var i = 0; i < lines.length; i++) { + // if line is empty, ignore it. + // there is a case that a user forgot to delete `\n`. + var line = trim$1(lines[i]); + + if (!line) { + continue; + } + + var items = line.split(itemSplitRegex); + var name_1 = ''; + var value = void 0; + var hasName = false; + + if (isNaN(items[0])) { + // First item is name + hasName = true; + name_1 = items[0]; + items = items.slice(1); + data[i] = { + name: name_1, + value: [] + }; + value = data[i].value; + } else { + value = data[i] = []; + } + + for (var j = 0; j < items.length; j++) { + value.push(+items[j]); + } + + if (value.length === 1) { + hasName ? data[i].value = value[0] : data[i] = value[0]; + } + } + + return { + name: seriesName, + data: data + }; + } + + function parseContents(str, blockMetaList) { + var blocks = str.split(new RegExp('\n*' + BLOCK_SPLITER + '\n*', 'g')); + var newOption = { + series: [] + }; + each(blocks, function (block, idx) { + if (isTSVFormat(block)) { + var result = parseTSVContents(block); + var blockMeta = blockMetaList[idx]; + var axisKey = blockMeta.axisDim + 'Axis'; + + if (blockMeta) { + newOption[axisKey] = newOption[axisKey] || []; + newOption[axisKey][blockMeta.axisIndex] = { + data: result.categories + }; + newOption.series = newOption.series.concat(result.series); + } + } else { + var result = parseListContents(block); + newOption.series.push(result); + } + }); + return newOption; + } + + var DataView = + /** @class */ + function (_super) { + __extends(DataView, _super); + + function DataView() { + return _super !== null && _super.apply(this, arguments) || this; + } + + DataView.prototype.onclick = function (ecModel, api) { + // FIXME: better way? + setTimeout(function () { + api.dispatchAction({ + type: 'hideTip' + }); + }); + var container = api.getDom(); + var model = this.model; + + if (this._dom) { + container.removeChild(this._dom); + } + + var root = document.createElement('div'); // use padding to avoid 5px whitespace + + root.style.cssText = 'position:absolute;top:0;bottom:0;left:0;right:0;padding:5px'; + root.style.backgroundColor = model.get('backgroundColor') || '#fff'; // Create elements + + var header = document.createElement('h4'); + var lang = model.get('lang') || []; + header.innerHTML = lang[0] || model.get('title'); + header.style.cssText = 'margin:10px 20px'; + header.style.color = model.get('textColor'); + var viewMain = document.createElement('div'); + var textarea = document.createElement('textarea'); + viewMain.style.cssText = 'overflow:auto'; + var optionToContent = model.get('optionToContent'); + var contentToOption = model.get('contentToOption'); + var result = getContentFromModel(ecModel); + + if (isFunction(optionToContent)) { + var htmlOrDom = optionToContent(api.getOption()); + + if (isString(htmlOrDom)) { + viewMain.innerHTML = htmlOrDom; + } else if (isDom(htmlOrDom)) { + viewMain.appendChild(htmlOrDom); + } + } else { + // Use default textarea + textarea.readOnly = model.get('readOnly'); + var style = textarea.style; // eslint-disable-next-line max-len + + style.cssText = 'display:block;width:100%;height:100%;font-family:monospace;font-size:14px;line-height:1.6rem;resize:none;box-sizing:border-box;outline:none'; + style.color = model.get('textColor'); + style.borderColor = model.get('textareaBorderColor'); + style.backgroundColor = model.get('textareaColor'); + textarea.value = result.value; + viewMain.appendChild(textarea); + } + + var blockMetaList = result.meta; + var buttonContainer = document.createElement('div'); + buttonContainer.style.cssText = 'position:absolute;bottom:5px;left:0;right:0'; // eslint-disable-next-line max-len + + var buttonStyle = 'float:right;margin-right:20px;border:none;cursor:pointer;padding:2px 5px;font-size:12px;border-radius:3px'; + var closeButton = document.createElement('div'); + var refreshButton = document.createElement('div'); + buttonStyle += ';background-color:' + model.get('buttonColor'); + buttonStyle += ';color:' + model.get('buttonTextColor'); + var self = this; + + function close() { + container.removeChild(root); + self._dom = null; + } + + addEventListener(closeButton, 'click', close); + addEventListener(refreshButton, 'click', function () { + if (contentToOption == null && optionToContent != null || contentToOption != null && optionToContent == null) { + if ("development" !== 'production') { + // eslint-disable-next-line + warn('It seems you have just provided one of `contentToOption` and `optionToContent` functions but missed the other one. Data change is ignored.'); + } + + close(); + return; + } + + var newOption; + + try { + if (isFunction(contentToOption)) { + newOption = contentToOption(viewMain, api.getOption()); + } else { + newOption = parseContents(textarea.value, blockMetaList); + } + } catch (e) { + close(); + throw new Error('Data view format error ' + e); + } + + if (newOption) { + api.dispatchAction({ + type: 'changeDataView', + newOption: newOption + }); + } + + close(); + }); + closeButton.innerHTML = lang[1]; + refreshButton.innerHTML = lang[2]; + refreshButton.style.cssText = closeButton.style.cssText = buttonStyle; + !model.get('readOnly') && buttonContainer.appendChild(refreshButton); + buttonContainer.appendChild(closeButton); + root.appendChild(header); + root.appendChild(viewMain); + root.appendChild(buttonContainer); + viewMain.style.height = container.clientHeight - 80 + 'px'; + container.appendChild(root); + this._dom = root; + }; + + DataView.prototype.remove = function (ecModel, api) { + this._dom && api.getDom().removeChild(this._dom); + }; + + DataView.prototype.dispose = function (ecModel, api) { + this.remove(ecModel, api); + }; + + DataView.getDefaultOption = function (ecModel) { + var defaultOption = { + show: true, + readOnly: false, + optionToContent: null, + contentToOption: null, + // eslint-disable-next-line + icon: 'M17.5,17.3H33 M17.5,17.3H33 M45.4,29.5h-28 M11.5,2v56H51V14.8L38.4,2H11.5z M38.4,2.2v12.7H51 M45.4,41.7h-28', + title: ecModel.getLocaleModel().get(['toolbox', 'dataView', 'title']), + lang: ecModel.getLocaleModel().get(['toolbox', 'dataView', 'lang']), + backgroundColor: '#fff', + textColor: '#000', + textareaColor: '#fff', + textareaBorderColor: '#333', + buttonColor: '#c23531', + buttonTextColor: '#fff' + }; + return defaultOption; + }; + + return DataView; + }(ToolboxFeature); + /** + * @inner + */ + + + function tryMergeDataOption(newData, originalData) { + return map(newData, function (newVal, idx) { + var original = originalData && originalData[idx]; + + if (isObject(original) && !isArray(original)) { + var newValIsObject = isObject(newVal) && !isArray(newVal); + + if (!newValIsObject) { + newVal = { + value: newVal + }; + } // original data has name but new data has no name + + + var shouldDeleteName = original.name != null && newVal.name == null; // Original data has option + + newVal = defaults(newVal, original); + shouldDeleteName && delete newVal.name; + return newVal; + } else { + return newVal; + } + }); + } // TODO: SELF REGISTERED. + + + registerAction({ + type: 'changeDataView', + event: 'dataViewChanged', + update: 'prepareAndUpdate' + }, function (payload, ecModel) { + var newSeriesOptList = []; + each(payload.newOption.series, function (seriesOpt) { + var seriesModel = ecModel.getSeriesByName(seriesOpt.name)[0]; + + if (!seriesModel) { + // New created series + // Geuss the series type + newSeriesOptList.push(extend({ + // Default is scatter + type: 'scatter' + }, seriesOpt)); + } else { + var originalData = seriesModel.get('data'); + newSeriesOptList.push({ + name: seriesOpt.name, + data: tryMergeDataOption(seriesOpt.data, originalData) + }); + } + }); + ecModel.mergeOption(defaults({ + series: newSeriesOptList + }, payload.newOption)); + }); + + var each$9 = each; + var inner$f = makeInner(); + /** + * @param ecModel + * @param newSnapshot key is dataZoomId + */ + + function push(ecModel, newSnapshot) { + var storedSnapshots = getStoreSnapshots(ecModel); // If previous dataZoom can not be found, + // complete an range with current range. + + each$9(newSnapshot, function (batchItem, dataZoomId) { + var i = storedSnapshots.length - 1; + + for (; i >= 0; i--) { + var snapshot = storedSnapshots[i]; + + if (snapshot[dataZoomId]) { + break; + } + } + + if (i < 0) { + // No origin range set, create one by current range. + var dataZoomModel = ecModel.queryComponents({ + mainType: 'dataZoom', + subType: 'select', + id: dataZoomId + })[0]; + + if (dataZoomModel) { + var percentRange = dataZoomModel.getPercentRange(); + storedSnapshots[0][dataZoomId] = { + dataZoomId: dataZoomId, + start: percentRange[0], + end: percentRange[1] + }; + } + } + }); + storedSnapshots.push(newSnapshot); + } + function pop(ecModel) { + var storedSnapshots = getStoreSnapshots(ecModel); + var head = storedSnapshots[storedSnapshots.length - 1]; + storedSnapshots.length > 1 && storedSnapshots.pop(); // Find top for all dataZoom. + + var snapshot = {}; + each$9(head, function (batchItem, dataZoomId) { + for (var i = storedSnapshots.length - 1; i >= 0; i--) { + batchItem = storedSnapshots[i][dataZoomId]; + + if (batchItem) { + snapshot[dataZoomId] = batchItem; + break; + } + } + }); + return snapshot; + } + function clear$1(ecModel) { + inner$f(ecModel).snapshots = null; + } + function count(ecModel) { + return getStoreSnapshots(ecModel).length; + } + /** + * History length of each dataZoom may be different. + * this._history[0] is used to store origin range. + */ + + function getStoreSnapshots(ecModel) { + var store = inner$f(ecModel); + + if (!store.snapshots) { + store.snapshots = [{}]; + } + + return store.snapshots; + } + + var RestoreOption = + /** @class */ + function (_super) { + __extends(RestoreOption, _super); + + function RestoreOption() { + return _super !== null && _super.apply(this, arguments) || this; + } + + RestoreOption.prototype.onclick = function (ecModel, api) { + clear$1(ecModel); + api.dispatchAction({ + type: 'restore', + from: this.uid + }); + }; + + RestoreOption.getDefaultOption = function (ecModel) { + var defaultOption = { + show: true, + // eslint-disable-next-line + icon: 'M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5', + title: ecModel.getLocaleModel().get(['toolbox', 'restore', 'title']) + }; + return defaultOption; + }; + + return RestoreOption; + }(ToolboxFeature); // TODO: SELF REGISTERED. + + + registerAction({ + type: 'restore', + event: 'restore', + update: 'prepareAndUpdate' + }, function (payload, ecModel) { + ecModel.resetOption('recreate'); + }); + + // how to genarialize to more coordinate systems. + + var INCLUDE_FINDER_MAIN_TYPES = ['grid', 'xAxis', 'yAxis', 'geo', 'graph', 'polar', 'radiusAxis', 'angleAxis', 'bmap']; + + var BrushTargetManager = + /** @class */ + function () { + /** + * @param finder contains Index/Id/Name of xAxis/yAxis/geo/grid + * Each can be {number|Array.}. like: {xAxisIndex: [3, 4]} + * @param opt.include include coordinate system types. + */ + function BrushTargetManager(finder, ecModel, opt) { + var _this = this; + + this._targetInfoList = []; + var foundCpts = parseFinder$1(ecModel, finder); + each(targetInfoBuilders, function (builder, type) { + if (!opt || !opt.include || indexOf(opt.include, type) >= 0) { + builder(foundCpts, _this._targetInfoList); + } + }); + } + + BrushTargetManager.prototype.setOutputRanges = function (areas, ecModel) { + this.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) { + (area.coordRanges || (area.coordRanges = [])).push(coordRange); // area.coordRange is the first of area.coordRanges + + if (!area.coordRange) { + area.coordRange = coordRange; // In 'category' axis, coord to pixel is not reversible, so we can not + // rebuild range by coordRange accrately, which may bring trouble when + // brushing only one item. So we use __rangeOffset to rebuilding range + // by coordRange. And this it only used in brush component so it is no + // need to be adapted to coordRanges. + + var result = coordConvert[area.brushType](0, coordSys, coordRange); + area.__rangeOffset = { + offset: diffProcessor[area.brushType](result.values, area.range, [1, 1]), + xyMinMax: result.xyMinMax + }; + } + }); + return areas; + }; + + BrushTargetManager.prototype.matchOutputRanges = function (areas, ecModel, cb) { + each(areas, function (area) { + var targetInfo = this.findTargetInfo(area, ecModel); + + if (targetInfo && targetInfo !== true) { + each(targetInfo.coordSyses, function (coordSys) { + var result = coordConvert[area.brushType](1, coordSys, area.range, true); + cb(area, result.values, coordSys, ecModel); + }); + } + }, this); + }; + /** + * the `areas` is `BrushModel.areas`. + * Called in layout stage. + * convert `area.coordRange` to global range and set panelId to `area.range`. + */ + + + BrushTargetManager.prototype.setInputRanges = function (areas, ecModel) { + each(areas, function (area) { + var targetInfo = this.findTargetInfo(area, ecModel); + + if ("development" !== 'production') { + assert(!targetInfo || targetInfo === true || area.coordRange, 'coordRange must be specified when coord index specified.'); + assert(!targetInfo || targetInfo !== true || area.range, 'range must be specified in global brush.'); + } + + area.range = area.range || []; // convert coordRange to global range and set panelId. + + if (targetInfo && targetInfo !== true) { + area.panelId = targetInfo.panelId; // (1) area.range shoule always be calculate from coordRange but does + // not keep its original value, for the sake of the dataZoom scenario, + // where area.coordRange remains unchanged but area.range may be changed. + // (2) Only support converting one coordRange to pixel range in brush + // component. So do not consider `coordRanges`. + // (3) About __rangeOffset, see comment above. + + var result = coordConvert[area.brushType](0, targetInfo.coordSys, area.coordRange); + var rangeOffset = area.__rangeOffset; + area.range = rangeOffset ? diffProcessor[area.brushType](result.values, rangeOffset.offset, getScales(result.xyMinMax, rangeOffset.xyMinMax)) : result.values; + } + }, this); + }; + + BrushTargetManager.prototype.makePanelOpts = function (api, getDefaultBrushType) { + return map(this._targetInfoList, function (targetInfo) { + var rect = targetInfo.getPanelRect(); + return { + panelId: targetInfo.panelId, + defaultBrushType: getDefaultBrushType ? getDefaultBrushType(targetInfo) : null, + clipPath: makeRectPanelClipPath(rect), + isTargetByCursor: makeRectIsTargetByCursor(rect, api, targetInfo.coordSysModel), + getLinearBrushOtherExtent: makeLinearBrushOtherExtent(rect) + }; + }); + }; + + BrushTargetManager.prototype.controlSeries = function (area, seriesModel, ecModel) { + // Check whether area is bound in coord, and series do not belong to that coord. + // If do not do this check, some brush (like lineX) will controll all axes. + var targetInfo = this.findTargetInfo(area, ecModel); + return targetInfo === true || targetInfo && indexOf(targetInfo.coordSyses, seriesModel.coordinateSystem) >= 0; + }; + /** + * If return Object, a coord found. + * If reutrn true, global found. + * Otherwise nothing found. + */ + + + BrushTargetManager.prototype.findTargetInfo = function (area, ecModel) { + var targetInfoList = this._targetInfoList; + var foundCpts = parseFinder$1(ecModel, area); + + for (var i = 0; i < targetInfoList.length; i++) { + var targetInfo = targetInfoList[i]; + var areaPanelId = area.panelId; + + if (areaPanelId) { + if (targetInfo.panelId === areaPanelId) { + return targetInfo; + } + } else { + for (var j = 0; j < targetInfoMatchers.length; j++) { + if (targetInfoMatchers[j](foundCpts, targetInfo)) { + return targetInfo; + } + } + } + } + + return true; + }; + + return BrushTargetManager; + }(); + + function formatMinMax(minMax) { + minMax[0] > minMax[1] && minMax.reverse(); + return minMax; + } + + function parseFinder$1(ecModel, finder) { + return parseFinder(ecModel, finder, { + includeMainTypes: INCLUDE_FINDER_MAIN_TYPES + }); + } + + var targetInfoBuilders = { + grid: function (foundCpts, targetInfoList) { + var xAxisModels = foundCpts.xAxisModels; + var yAxisModels = foundCpts.yAxisModels; + var gridModels = foundCpts.gridModels; // Remove duplicated. + + var gridModelMap = createHashMap(); + var xAxesHas = {}; + var yAxesHas = {}; + + if (!xAxisModels && !yAxisModels && !gridModels) { + return; + } + + each(xAxisModels, function (axisModel) { + var gridModel = axisModel.axis.grid.model; + gridModelMap.set(gridModel.id, gridModel); + xAxesHas[gridModel.id] = true; + }); + each(yAxisModels, function (axisModel) { + var gridModel = axisModel.axis.grid.model; + gridModelMap.set(gridModel.id, gridModel); + yAxesHas[gridModel.id] = true; + }); + each(gridModels, function (gridModel) { + gridModelMap.set(gridModel.id, gridModel); + xAxesHas[gridModel.id] = true; + yAxesHas[gridModel.id] = true; + }); + gridModelMap.each(function (gridModel) { + var grid = gridModel.coordinateSystem; + var cartesians = []; + each(grid.getCartesians(), function (cartesian, index) { + if (indexOf(xAxisModels, cartesian.getAxis('x').model) >= 0 || indexOf(yAxisModels, cartesian.getAxis('y').model) >= 0) { + cartesians.push(cartesian); + } + }); + targetInfoList.push({ + panelId: 'grid--' + gridModel.id, + gridModel: gridModel, + coordSysModel: gridModel, + // Use the first one as the representitive coordSys. + coordSys: cartesians[0], + coordSyses: cartesians, + getPanelRect: panelRectBuilders.grid, + xAxisDeclared: xAxesHas[gridModel.id], + yAxisDeclared: yAxesHas[gridModel.id] + }); + }); + }, + geo: function (foundCpts, targetInfoList) { + each(foundCpts.geoModels, function (geoModel) { + var coordSys = geoModel.coordinateSystem; + targetInfoList.push({ + panelId: 'geo--' + geoModel.id, + geoModel: geoModel, + coordSysModel: geoModel, + coordSys: coordSys, + coordSyses: [coordSys], + getPanelRect: panelRectBuilders.geo + }); + }); + } + }; + var targetInfoMatchers = [// grid + function (foundCpts, targetInfo) { + var xAxisModel = foundCpts.xAxisModel; + var yAxisModel = foundCpts.yAxisModel; + var gridModel = foundCpts.gridModel; + !gridModel && xAxisModel && (gridModel = xAxisModel.axis.grid.model); + !gridModel && yAxisModel && (gridModel = yAxisModel.axis.grid.model); + return gridModel && gridModel === targetInfo.gridModel; + }, // geo + function (foundCpts, targetInfo) { + var geoModel = foundCpts.geoModel; + return geoModel && geoModel === targetInfo.geoModel; + }]; + var panelRectBuilders = { + grid: function () { + // grid is not Transformable. + return this.coordSys.master.getRect().clone(); + }, + geo: function () { + var coordSys = this.coordSys; + var rect = coordSys.getBoundingRect().clone(); // geo roam and zoom transform + + rect.applyTransform(getTransform(coordSys)); + return rect; + } + }; + var coordConvert = { + lineX: curry(axisConvert, 0), + lineY: curry(axisConvert, 1), + rect: function (to, coordSys, rangeOrCoordRange, clamp) { + var xminymin = to ? coordSys.pointToData([rangeOrCoordRange[0][0], rangeOrCoordRange[1][0]], clamp) : coordSys.dataToPoint([rangeOrCoordRange[0][0], rangeOrCoordRange[1][0]], clamp); + var xmaxymax = to ? coordSys.pointToData([rangeOrCoordRange[0][1], rangeOrCoordRange[1][1]], clamp) : coordSys.dataToPoint([rangeOrCoordRange[0][1], rangeOrCoordRange[1][1]], clamp); + var values = [formatMinMax([xminymin[0], xmaxymax[0]]), formatMinMax([xminymin[1], xmaxymax[1]])]; + return { + values: values, + xyMinMax: values + }; + }, + polygon: function (to, coordSys, rangeOrCoordRange, clamp) { + var xyMinMax = [[Infinity, -Infinity], [Infinity, -Infinity]]; + var values = map(rangeOrCoordRange, function (item) { + var p = to ? coordSys.pointToData(item, clamp) : coordSys.dataToPoint(item, clamp); + xyMinMax[0][0] = Math.min(xyMinMax[0][0], p[0]); + xyMinMax[1][0] = Math.min(xyMinMax[1][0], p[1]); + xyMinMax[0][1] = Math.max(xyMinMax[0][1], p[0]); + xyMinMax[1][1] = Math.max(xyMinMax[1][1], p[1]); + return p; + }); + return { + values: values, + xyMinMax: xyMinMax + }; + } + }; + + function axisConvert(axisNameIndex, to, coordSys, rangeOrCoordRange) { + if ("development" !== 'production') { + assert(coordSys.type === 'cartesian2d', 'lineX/lineY brush is available only in cartesian2d.'); + } + + var axis = coordSys.getAxis(['x', 'y'][axisNameIndex]); + var values = formatMinMax(map([0, 1], function (i) { + return to ? axis.coordToData(axis.toLocalCoord(rangeOrCoordRange[i]), true) : axis.toGlobalCoord(axis.dataToCoord(rangeOrCoordRange[i])); + })); + var xyMinMax = []; + xyMinMax[axisNameIndex] = values; + xyMinMax[1 - axisNameIndex] = [NaN, NaN]; + return { + values: values, + xyMinMax: xyMinMax + }; + } + + var diffProcessor = { + lineX: curry(axisDiffProcessor, 0), + lineY: curry(axisDiffProcessor, 1), + rect: function (values, refer, scales) { + return [[values[0][0] - scales[0] * refer[0][0], values[0][1] - scales[0] * refer[0][1]], [values[1][0] - scales[1] * refer[1][0], values[1][1] - scales[1] * refer[1][1]]]; + }, + polygon: function (values, refer, scales) { + return map(values, function (item, idx) { + return [item[0] - scales[0] * refer[idx][0], item[1] - scales[1] * refer[idx][1]]; + }); + } + }; + + function axisDiffProcessor(axisNameIndex, values, refer, scales) { + return [values[0] - scales[axisNameIndex] * refer[0], values[1] - scales[axisNameIndex] * refer[1]]; + } // We have to process scale caused by dataZoom manually, + // although it might be not accurate. + // Return [0~1, 0~1] + + + function getScales(xyMinMaxCurr, xyMinMaxOrigin) { + var sizeCurr = getSize$1(xyMinMaxCurr); + var sizeOrigin = getSize$1(xyMinMaxOrigin); + var scales = [sizeCurr[0] / sizeOrigin[0], sizeCurr[1] / sizeOrigin[1]]; + isNaN(scales[0]) && (scales[0] = 1); + isNaN(scales[1]) && (scales[1] = 1); + return scales; + } + + function getSize$1(xyMinMax) { + return xyMinMax ? [xyMinMax[0][1] - xyMinMax[0][0], xyMinMax[1][1] - xyMinMax[1][0]] : [NaN, NaN]; + } + + var each$a = each; + var DATA_ZOOM_ID_BASE = makeInternalComponentId('toolbox-dataZoom_'); + + var DataZoomFeature = + /** @class */ + function (_super) { + __extends(DataZoomFeature, _super); + + function DataZoomFeature() { + return _super !== null && _super.apply(this, arguments) || this; + } + + DataZoomFeature.prototype.render = function (featureModel, ecModel, api, payload) { + if (!this._brushController) { + this._brushController = new BrushController(api.getZr()); + + this._brushController.on('brush', bind(this._onBrush, this)).mount(); + } + + updateZoomBtnStatus(featureModel, ecModel, this, payload, api); + updateBackBtnStatus(featureModel, ecModel); + }; + + DataZoomFeature.prototype.onclick = function (ecModel, api, type) { + handlers$1[type].call(this); + }; + + DataZoomFeature.prototype.remove = function (ecModel, api) { + this._brushController && this._brushController.unmount(); + }; + + DataZoomFeature.prototype.dispose = function (ecModel, api) { + this._brushController && this._brushController.dispose(); + }; + + DataZoomFeature.prototype._onBrush = function (eventParam) { + var areas = eventParam.areas; + + if (!eventParam.isEnd || !areas.length) { + return; + } + + var snapshot = {}; + var ecModel = this.ecModel; + + this._brushController.updateCovers([]); // remove cover + + + var brushTargetManager = new BrushTargetManager(makeAxisFinder(this.model), ecModel, { + include: ['grid'] + }); + brushTargetManager.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) { + if (coordSys.type !== 'cartesian2d') { + return; + } + + var brushType = area.brushType; + + if (brushType === 'rect') { + setBatch('x', coordSys, coordRange[0]); + setBatch('y', coordSys, coordRange[1]); + } else { + setBatch({ + lineX: 'x', + lineY: 'y' + }[brushType], coordSys, coordRange); + } + }); + push(ecModel, snapshot); + + this._dispatchZoomAction(snapshot); + + function setBatch(dimName, coordSys, minMax) { + var axis = coordSys.getAxis(dimName); + var axisModel = axis.model; + var dataZoomModel = findDataZoom(dimName, axisModel, ecModel); // Restrict range. + + var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy(axisModel).getMinMaxSpan(); + + if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) { + minMax = sliderMove(0, minMax.slice(), axis.scale.getExtent(), 0, minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan); + } + + dataZoomModel && (snapshot[dataZoomModel.id] = { + dataZoomId: dataZoomModel.id, + startValue: minMax[0], + endValue: minMax[1] + }); + } + + function findDataZoom(dimName, axisModel, ecModel) { + var found; + ecModel.eachComponent({ + mainType: 'dataZoom', + subType: 'select' + }, function (dzModel) { + var has = dzModel.getAxisModel(dimName, axisModel.componentIndex); + has && (found = dzModel); + }); + return found; + } + }; + + DataZoomFeature.prototype._dispatchZoomAction = function (snapshot) { + var batch = []; // Convert from hash map to array. + + each$a(snapshot, function (batchItem, dataZoomId) { + batch.push(clone(batchItem)); + }); + batch.length && this.api.dispatchAction({ + type: 'dataZoom', + from: this.uid, + batch: batch + }); + }; + + DataZoomFeature.getDefaultOption = function (ecModel) { + var defaultOption = { + show: true, + filterMode: 'filter', + // Icon group + icon: { + zoom: 'M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1', + back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26' + }, + // `zoom`, `back` + title: ecModel.getLocaleModel().get(['toolbox', 'dataZoom', 'title']), + brushStyle: { + borderWidth: 0, + color: 'rgba(210,219,238,0.2)' + } + }; + return defaultOption; + }; + + return DataZoomFeature; + }(ToolboxFeature); + + var handlers$1 = { + zoom: function () { + var nextActive = !this._isZoomActive; + this.api.dispatchAction({ + type: 'takeGlobalCursor', + key: 'dataZoomSelect', + dataZoomSelectActive: nextActive + }); + }, + back: function () { + this._dispatchZoomAction(pop(this.ecModel)); + } + }; + + function makeAxisFinder(dzFeatureModel) { + var setting = { + xAxisIndex: dzFeatureModel.get('xAxisIndex', true), + yAxisIndex: dzFeatureModel.get('yAxisIndex', true), + xAxisId: dzFeatureModel.get('xAxisId', true), + yAxisId: dzFeatureModel.get('yAxisId', true) + }; // If both `xAxisIndex` `xAxisId` not set, it means 'all'. + // If both `yAxisIndex` `yAxisId` not set, it means 'all'. + // Some old cases set like this below to close yAxis control but leave xAxis control: + // `{ feature: { dataZoom: { yAxisIndex: false } }`. + + if (setting.xAxisIndex == null && setting.xAxisId == null) { + setting.xAxisIndex = 'all'; + } + + if (setting.yAxisIndex == null && setting.yAxisId == null) { + setting.yAxisIndex = 'all'; + } + + return setting; + } + + function updateBackBtnStatus(featureModel, ecModel) { + featureModel.setIconStatus('back', count(ecModel) > 1 ? 'emphasis' : 'normal'); + } + + function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) { + var zoomActive = view._isZoomActive; + + if (payload && payload.type === 'takeGlobalCursor') { + zoomActive = payload.key === 'dataZoomSelect' ? payload.dataZoomSelectActive : false; + } + + view._isZoomActive = zoomActive; + featureModel.setIconStatus('zoom', zoomActive ? 'emphasis' : 'normal'); + var brushTargetManager = new BrushTargetManager(makeAxisFinder(featureModel), ecModel, { + include: ['grid'] + }); + var panels = brushTargetManager.makePanelOpts(api, function (targetInfo) { + return targetInfo.xAxisDeclared && !targetInfo.yAxisDeclared ? 'lineX' : !targetInfo.xAxisDeclared && targetInfo.yAxisDeclared ? 'lineY' : 'rect'; + }); + + view._brushController.setPanels(panels).enableBrush(zoomActive && panels.length ? { + brushType: 'auto', + brushStyle: featureModel.getModel('brushStyle').getItemStyle() + } : false); + } + + registerInternalOptionCreator('dataZoom', function (ecModel) { + var toolboxModel = ecModel.getComponent('toolbox', 0); + var featureDataZoomPath = ['feature', 'dataZoom']; + + if (!toolboxModel || toolboxModel.get(featureDataZoomPath) == null) { + return; + } + + var dzFeatureModel = toolboxModel.getModel(featureDataZoomPath); + var dzOptions = []; + var finder = makeAxisFinder(dzFeatureModel); + var finderResult = parseFinder(ecModel, finder); + each$a(finderResult.xAxisModels, function (axisModel) { + return buildInternalOptions(axisModel, 'xAxis', 'xAxisIndex'); + }); + each$a(finderResult.yAxisModels, function (axisModel) { + return buildInternalOptions(axisModel, 'yAxis', 'yAxisIndex'); + }); + + function buildInternalOptions(axisModel, axisMainType, axisIndexPropName) { + var axisIndex = axisModel.componentIndex; + var newOpt = { + type: 'select', + $fromToolbox: true, + // Default to be filter + filterMode: dzFeatureModel.get('filterMode', true) || 'filter', + // Id for merge mapping. + id: DATA_ZOOM_ID_BASE + axisMainType + axisIndex + }; + newOpt[axisIndexPropName] = axisIndex; + dzOptions.push(newOpt); + } + + return dzOptions; + }); + + function install$z(registers) { + registers.registerComponentModel(ToolboxModel); + registers.registerComponentView(ToolboxView); + registerFeature('saveAsImage', SaveAsImage); + registerFeature('magicType', MagicType); + registerFeature('dataView', DataView); + registerFeature('dataZoom', DataZoomFeature); + registerFeature('restore', RestoreOption); + use(install$y); + } + + var TooltipModel = + /** @class */ + function (_super) { + __extends(TooltipModel, _super); + + function TooltipModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TooltipModel.type; + return _this; + } + + TooltipModel.type = 'tooltip'; + TooltipModel.dependencies = ['axisPointer']; + TooltipModel.defaultOption = { + // zlevel: 0, + z: 60, + show: true, + // tooltip main content + showContent: true, + // 'trigger' only works on coordinate system. + // 'item' | 'axis' | 'none' + trigger: 'item', + // 'click' | 'mousemove' | 'none' + triggerOn: 'mousemove|click', + alwaysShowContent: false, + displayMode: 'single', + renderMode: 'auto', + // whether restraint content inside viewRect. + // If renderMode: 'richText', default true. + // If renderMode: 'html', defaut false (for backward compat). + confine: null, + showDelay: 0, + hideDelay: 100, + // Animation transition time, unit is second + transitionDuration: 0.4, + enterable: false, + backgroundColor: '#fff', + // box shadow + shadowBlur: 10, + shadowColor: 'rgba(0, 0, 0, .2)', + shadowOffsetX: 1, + shadowOffsetY: 2, + // tooltip border radius, unit is px, default is 4 + borderRadius: 4, + // tooltip border width, unit is px, default is 0 (no border) + borderWidth: 1, + // Tooltip inside padding, default is 5 for all direction + // Array is allowed to set up, right, bottom, left, same with css + // The default value: See `tooltip/tooltipMarkup.ts#getPaddingFromTooltipModel`. + padding: null, + // Extra css text + extraCssText: '', + // axis indicator, trigger by axis + axisPointer: { + // default is line + // legal values: 'line' | 'shadow' | 'cross' + type: 'line', + // Valid when type is line, appoint tooltip line locate on which line. Optional + // legal values: 'x' | 'y' | 'angle' | 'radius' | 'auto' + // default is 'auto', chose the axis which type is category. + // for multiply y axis, cartesian coord chose x axis, polar chose angle axis + axis: 'auto', + animation: 'auto', + animationDurationUpdate: 200, + animationEasingUpdate: 'exponentialOut', + crossStyle: { + color: '#999', + width: 1, + type: 'dashed', + // TODO formatter + textStyle: {} + } // lineStyle and shadowStyle should not be specified here, + // otherwise it will always override those styles on option.axisPointer. + + }, + textStyle: { + color: '#666', + fontSize: 14 + } + }; + return TooltipModel; + }(ComponentModel); + + /* global document */ + + function shouldTooltipConfine(tooltipModel) { + var confineOption = tooltipModel.get('confine'); + return confineOption != null ? !!confineOption // In richText mode, the outside part can not be visible. + : tooltipModel.get('renderMode') === 'richText'; + } + + function testStyle(styleProps) { + if (!env.domSupported) { + return; + } + + var style = document.documentElement.style; + + for (var i = 0, len = styleProps.length; i < len; i++) { + if (styleProps[i] in style) { + return styleProps[i]; + } + } + } + + var TRANSFORM_VENDOR = testStyle(['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']); + var TRANSITION_VENDOR = testStyle(['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']); + function toCSSVendorPrefix(styleVendor, styleProp) { + if (!styleVendor) { + return styleProp; + } + + styleProp = toCamelCase(styleProp, true); + var idx = styleVendor.indexOf(styleProp); + styleVendor = idx === -1 ? styleProp : "-" + styleVendor.slice(0, idx) + "-" + styleProp; + return styleVendor.toLowerCase(); + } + function getComputedStyle(el, style) { + var stl = el.currentStyle || document.defaultView && document.defaultView.getComputedStyle(el); + return stl ? style ? stl[style] : stl : null; + } + + /* global document, window */ + + var CSS_TRANSITION_VENDOR = toCSSVendorPrefix(TRANSITION_VENDOR, 'transition'); + var CSS_TRANSFORM_VENDOR = toCSSVendorPrefix(TRANSFORM_VENDOR, 'transform'); // eslint-disable-next-line + + var gCssText = "position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;" + (env.transform3dSupported ? 'will-change:transform;' : ''); + + function mirrorPos(pos) { + pos = pos === 'left' ? 'right' : pos === 'right' ? 'left' : pos === 'top' ? 'bottom' : 'top'; + return pos; + } + + function assembleArrow(tooltipModel, borderColor, arrowPosition) { + if (!isString(arrowPosition) || arrowPosition === 'inside') { + return ''; + } + + var backgroundColor = tooltipModel.get('backgroundColor'); + var borderWidth = tooltipModel.get('borderWidth'); + borderColor = convertToColorString(borderColor); + var arrowPos = mirrorPos(arrowPosition); + var arrowSize = Math.max(Math.round(borderWidth) * 1.5, 6); + var positionStyle = ''; + var transformStyle = CSS_TRANSFORM_VENDOR + ':'; + var rotateDeg; + + if (indexOf(['left', 'right'], arrowPos) > -1) { + positionStyle += 'top:50%'; + transformStyle += "translateY(-50%) rotate(" + (rotateDeg = arrowPos === 'left' ? -225 : -45) + "deg)"; + } else { + positionStyle += 'left:50%'; + transformStyle += "translateX(-50%) rotate(" + (rotateDeg = arrowPos === 'top' ? 225 : 45) + "deg)"; + } + + var rotateRadian = rotateDeg * Math.PI / 180; + var arrowWH = arrowSize + borderWidth; + var rotatedWH = arrowWH * Math.abs(Math.cos(rotateRadian)) + arrowWH * Math.abs(Math.sin(rotateRadian)); + var arrowOffset = Math.round(((rotatedWH - Math.SQRT2 * borderWidth) / 2 + Math.SQRT2 * borderWidth - (rotatedWH - arrowWH) / 2) * 100) / 100; + positionStyle += ";" + arrowPos + ":-" + arrowOffset + "px"; + var borderStyle = borderColor + " solid " + borderWidth + "px;"; + var styleCss = ["position:absolute;width:" + arrowSize + "px;height:" + arrowSize + "px;", positionStyle + ";" + transformStyle + ";", "border-bottom:" + borderStyle, "border-right:" + borderStyle, "background-color:" + backgroundColor + ";"]; + return "
                                                                                          "; + } + + function assembleTransition(duration, onlyFade) { + var transitionCurve = 'cubic-bezier(0.23,1,0.32,1)'; + var transitionOption = " " + duration / 2 + "s " + transitionCurve; + var transitionText = "opacity" + transitionOption + ",visibility" + transitionOption; + + if (!onlyFade) { + transitionOption = " " + duration + "s " + transitionCurve; + transitionText += env.transformSupported ? "," + CSS_TRANSFORM_VENDOR + transitionOption : ",left" + transitionOption + ",top" + transitionOption; + } + + return CSS_TRANSITION_VENDOR + ':' + transitionText; + } + + function assembleTransform(x, y, toString) { + // If using float on style, the final width of the dom might + // keep changing slightly while mouse move. So `toFixed(0)` them. + var x0 = x.toFixed(0) + 'px'; + var y0 = y.toFixed(0) + 'px'; // not support transform, use `left` and `top` instead. + + if (!env.transformSupported) { + return toString ? "top:" + y0 + ";left:" + x0 + ";" : [['top', y0], ['left', x0]]; + } // support transform + + + var is3d = env.transform3dSupported; + var translate = "translate" + (is3d ? '3d' : '') + "(" + x0 + "," + y0 + (is3d ? ',0' : '') + ")"; + return toString ? 'top:0;left:0;' + CSS_TRANSFORM_VENDOR + ':' + translate + ';' : [['top', 0], ['left', 0], [TRANSFORM_VENDOR, translate]]; + } + /** + * @param {Object} textStyle + * @return {string} + * @inner + */ + + + function assembleFont(textStyleModel) { + var cssText = []; + var fontSize = textStyleModel.get('fontSize'); + var color = textStyleModel.getTextColor(); + color && cssText.push('color:' + color); + cssText.push('font:' + textStyleModel.getFont()); + fontSize // @ts-ignore, leave it to the tooltip refactor. + && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px'); + var shadowColor = textStyleModel.get('textShadowColor'); + var shadowBlur = textStyleModel.get('textShadowBlur') || 0; + var shadowOffsetX = textStyleModel.get('textShadowOffsetX') || 0; + var shadowOffsetY = textStyleModel.get('textShadowOffsetY') || 0; + shadowColor && shadowBlur && cssText.push('text-shadow:' + shadowOffsetX + 'px ' + shadowOffsetY + 'px ' + shadowBlur + 'px ' + shadowColor); + each(['decoration', 'align'], function (name) { + var val = textStyleModel.get(name); + val && cssText.push('text-' + name + ':' + val); + }); + return cssText.join(';'); + } + + function assembleCssText(tooltipModel, enableTransition, onlyFade) { + var cssText = []; + var transitionDuration = tooltipModel.get('transitionDuration'); + var backgroundColor = tooltipModel.get('backgroundColor'); + var shadowBlur = tooltipModel.get('shadowBlur'); + var shadowColor = tooltipModel.get('shadowColor'); + var shadowOffsetX = tooltipModel.get('shadowOffsetX'); + var shadowOffsetY = tooltipModel.get('shadowOffsetY'); + var textStyleModel = tooltipModel.getModel('textStyle'); + var padding = getPaddingFromTooltipModel(tooltipModel, 'html'); + var boxShadow = shadowOffsetX + "px " + shadowOffsetY + "px " + shadowBlur + "px " + shadowColor; + cssText.push('box-shadow:' + boxShadow); // Animation transition. Do not animate when transitionDuration is 0. + + enableTransition && transitionDuration && cssText.push(assembleTransition(transitionDuration, onlyFade)); + + if (backgroundColor) { + cssText.push('background-color:' + backgroundColor); + } // Border style + + + each(['width', 'color', 'radius'], function (name) { + var borderName = 'border-' + name; + var camelCase = toCamelCase(borderName); + var val = tooltipModel.get(camelCase); + val != null && cssText.push(borderName + ':' + val + (name === 'color' ? '' : 'px')); + }); // Text style + + cssText.push(assembleFont(textStyleModel)); // Padding + + if (padding != null) { + cssText.push('padding:' + normalizeCssArray$1(padding).join('px ') + 'px'); + } + + return cssText.join(';') + ';'; + } // If not able to make, do not modify the input `out`. + + + function makeStyleCoord(out, zr, appendToBody, zrX, zrY) { + var zrPainter = zr && zr.painter; + + if (appendToBody) { + var zrViewportRoot = zrPainter && zrPainter.getViewportRoot(); + + if (zrViewportRoot) { + // Some APPs might use scale on body, so we support CSS transform here. + transformLocalCoord(out, zrViewportRoot, document.body, zrX, zrY); + } + } else { + out[0] = zrX; + out[1] = zrY; // xy should be based on canvas root. But tooltipContent is + // the sibling of canvas root. So padding of ec container + // should be considered here. + + var viewportRootOffset = zrPainter && zrPainter.getViewportRootOffset(); + + if (viewportRootOffset) { + out[0] += viewportRootOffset.offsetLeft; + out[1] += viewportRootOffset.offsetTop; + } + } + + out[2] = out[0] / zr.getWidth(); + out[3] = out[1] / zr.getHeight(); + } + + var TooltipHTMLContent = + /** @class */ + function () { + function TooltipHTMLContent(container, api, opt) { + this._show = false; + this._styleCoord = [0, 0, 0, 0]; + this._enterable = true; + this._firstShow = true; + this._longHide = true; + + if (env.wxa) { + return null; + } + + var el = document.createElement('div'); // TODO: TYPE + + el.domBelongToZr = true; + this.el = el; + var zr = this._zr = api.getZr(); + var appendToBody = this._appendToBody = opt && opt.appendToBody; + makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2); + + if (appendToBody) { + document.body.appendChild(el); + } else { + container.appendChild(el); + } + + this._container = container; // FIXME + // Is it needed to trigger zr event manually if + // the browser do not support `pointer-events: none`. + + var self = this; + + el.onmouseenter = function () { + // clear the timeout in hideLater and keep showing tooltip + if (self._enterable) { + clearTimeout(self._hideTimeout); + self._show = true; + } + + self._inContent = true; + }; + + el.onmousemove = function (e) { + e = e || window.event; + + if (!self._enterable) { + // `pointer-events: none` is set to tooltip content div + // if `enterable` is set as `false`, and `el.onmousemove` + // can not be triggered. But in browser that do not + // support `pointer-events`, we need to do this: + // Try trigger zrender event to avoid mouse + // in and out shape too frequently + var handler = zr.handler; + var zrViewportRoot = zr.painter.getViewportRoot(); + normalizeEvent(zrViewportRoot, e, true); + handler.dispatch('mousemove', e); + } + }; + + el.onmouseleave = function () { + // set `_inContent` to `false` before `hideLater` + self._inContent = false; + + if (self._enterable) { + if (self._show) { + self.hideLater(self._hideDelay); + } + } + }; + } + /** + * Update when tooltip is rendered + */ + + + TooltipHTMLContent.prototype.update = function (tooltipModel) { + // FIXME + // Move this logic to ec main? + var container = this._container; + var position = getComputedStyle(container, 'position'); + var domStyle = container.style; + + if (domStyle.position !== 'absolute' && position !== 'absolute') { + domStyle.position = 'relative'; + } // move tooltip if chart resized + + + var alwaysShowContent = tooltipModel.get('alwaysShowContent'); + alwaysShowContent && this._moveIfResized(); // update className + + this.el.className = tooltipModel.get('className') || ''; // Hide the tooltip + // PENDING + // this.hide(); + }; + + TooltipHTMLContent.prototype.show = function (tooltipModel, nearPointColor) { + clearTimeout(this._hideTimeout); + clearTimeout(this._longHideTimeout); + var el = this.el; + var style = el.style; + var styleCoord = this._styleCoord; + + if (!el.innerHTML) { + style.display = 'none'; + } else { + style.cssText = gCssText + assembleCssText(tooltipModel, !this._firstShow, this._longHide) // initial transform + + assembleTransform(styleCoord[0], styleCoord[1], true) + ("border-color:" + convertToColorString(nearPointColor) + ";") + (tooltipModel.get('extraCssText') || '') // If mouse occasionally move over the tooltip, a mouseout event will be + // triggered by canvas, and cause some unexpectable result like dragging + // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve + // it. Although it is not supported by IE8~IE10, fortunately it is a rare + // scenario. + + (";pointer-events:" + (this._enterable ? 'auto' : 'none')); + } + + this._show = true; + this._firstShow = false; + this._longHide = false; + }; + + TooltipHTMLContent.prototype.setContent = function (content, markers, tooltipModel, borderColor, arrowPosition) { + var el = this.el; + + if (content == null) { + el.innerHTML = ''; + return; + } + + var arrow = ''; + + if (isString(arrowPosition) && tooltipModel.get('trigger') === 'item' && !shouldTooltipConfine(tooltipModel)) { + arrow = assembleArrow(tooltipModel, borderColor, arrowPosition); + } + + if (isString(content)) { + el.innerHTML = content + arrow; + } else if (content) { + // Clear previous + el.innerHTML = ''; + + if (!isArray(content)) { + content = [content]; + } + + for (var i = 0; i < content.length; i++) { + if (isDom(content[i]) && content[i].parentNode !== el) { + el.appendChild(content[i]); + } + } // no arrow if empty + + + if (arrow && el.childNodes.length) { + // no need to create a new parent element, but it's not supported by IE 10 and older. + // const arrowEl = document.createRange().createContextualFragment(arrow); + var arrowEl = document.createElement('div'); + arrowEl.innerHTML = arrow; + el.appendChild(arrowEl); + } + } + }; + + TooltipHTMLContent.prototype.setEnterable = function (enterable) { + this._enterable = enterable; + }; + + TooltipHTMLContent.prototype.getSize = function () { + var el = this.el; + return [el.offsetWidth, el.offsetHeight]; + }; + + TooltipHTMLContent.prototype.moveTo = function (zrX, zrY) { + var styleCoord = this._styleCoord; + makeStyleCoord(styleCoord, this._zr, this._appendToBody, zrX, zrY); + + if (styleCoord[0] != null && styleCoord[1] != null) { + var style_1 = this.el.style; + var transforms = assembleTransform(styleCoord[0], styleCoord[1]); + each(transforms, function (transform) { + style_1[transform[0]] = transform[1]; + }); + } + }; + /** + * when `alwaysShowContent` is true, + * move the tooltip after chart resized + */ + + + TooltipHTMLContent.prototype._moveIfResized = function () { + // The ratio of left to width + var ratioX = this._styleCoord[2]; // The ratio of top to height + + var ratioY = this._styleCoord[3]; + this.moveTo(ratioX * this._zr.getWidth(), ratioY * this._zr.getHeight()); + }; + + TooltipHTMLContent.prototype.hide = function () { + var _this = this; + + var style = this.el.style; + style.visibility = 'hidden'; + style.opacity = '0'; + env.transform3dSupported && (style.willChange = ''); + this._show = false; + this._longHideTimeout = setTimeout(function () { + return _this._longHide = true; + }, 500); + }; + + TooltipHTMLContent.prototype.hideLater = function (time) { + if (this._show && !(this._inContent && this._enterable)) { + if (time) { + this._hideDelay = time; // Set show false to avoid invoke hideLater multiple times + + this._show = false; + this._hideTimeout = setTimeout(bind(this.hide, this), time); + } else { + this.hide(); + } + } + }; + + TooltipHTMLContent.prototype.isShow = function () { + return this._show; + }; + + TooltipHTMLContent.prototype.dispose = function () { + this.el.parentNode.removeChild(this.el); + }; + + return TooltipHTMLContent; + }(); + + var TooltipRichContent = + /** @class */ + function () { + function TooltipRichContent(api) { + this._show = false; + this._styleCoord = [0, 0, 0, 0]; + this._enterable = true; + this._zr = api.getZr(); + makeStyleCoord$1(this._styleCoord, this._zr, api.getWidth() / 2, api.getHeight() / 2); + } + /** + * Update when tooltip is rendered + */ + + + TooltipRichContent.prototype.update = function (tooltipModel) { + var alwaysShowContent = tooltipModel.get('alwaysShowContent'); + alwaysShowContent && this._moveIfResized(); + }; + + TooltipRichContent.prototype.show = function () { + if (this._hideTimeout) { + clearTimeout(this._hideTimeout); + } + + this.el.show(); + this._show = true; + }; + /** + * Set tooltip content + */ + + + TooltipRichContent.prototype.setContent = function (content, markupStyleCreator, tooltipModel, borderColor, arrowPosition) { + var _this = this; + + if (isObject(content)) { + throwError("development" !== 'production' ? 'Passing DOM nodes as content is not supported in richText tooltip!' : ''); + } + + if (this.el) { + this._zr.remove(this.el); + } + + var textStyleModel = tooltipModel.getModel('textStyle'); + this.el = new ZRText({ + style: { + rich: markupStyleCreator.richTextStyles, + text: content, + lineHeight: 22, + borderWidth: 1, + borderColor: borderColor, + textShadowColor: textStyleModel.get('textShadowColor'), + fill: tooltipModel.get(['textStyle', 'color']), + padding: getPaddingFromTooltipModel(tooltipModel, 'richText'), + verticalAlign: 'top', + align: 'left' + }, + z: tooltipModel.get('z') + }); + each(['backgroundColor', 'borderRadius', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'], function (propName) { + _this.el.style[propName] = tooltipModel.get(propName); + }); + each(['textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY'], function (propName) { + _this.el.style[propName] = textStyleModel.get(propName) || 0; + }); + + this._zr.add(this.el); + + var self = this; + this.el.on('mouseover', function () { + // clear the timeout in hideLater and keep showing tooltip + if (self._enterable) { + clearTimeout(self._hideTimeout); + self._show = true; + } + + self._inContent = true; + }); + this.el.on('mouseout', function () { + if (self._enterable) { + if (self._show) { + self.hideLater(self._hideDelay); + } + } + + self._inContent = false; + }); + }; + + TooltipRichContent.prototype.setEnterable = function (enterable) { + this._enterable = enterable; + }; + + TooltipRichContent.prototype.getSize = function () { + var el = this.el; + var bounding = this.el.getBoundingRect(); // bounding rect does not include shadow. For renderMode richText, + // if overflow, it will be cut. So calculate them accurately. + + var shadowOuterSize = calcShadowOuterSize(el.style); + return [bounding.width + shadowOuterSize.left + shadowOuterSize.right, bounding.height + shadowOuterSize.top + shadowOuterSize.bottom]; + }; + + TooltipRichContent.prototype.moveTo = function (x, y) { + var el = this.el; + + if (el) { + var styleCoord = this._styleCoord; + makeStyleCoord$1(styleCoord, this._zr, x, y); + x = styleCoord[0]; + y = styleCoord[1]; + var style = el.style; + var borderWidth = mathMaxWith0(style.borderWidth || 0); + var shadowOuterSize = calcShadowOuterSize(style); // rich text x, y do not include border. + + el.x = x + borderWidth + shadowOuterSize.left; + el.y = y + borderWidth + shadowOuterSize.top; + el.markRedraw(); + } + }; + /** + * when `alwaysShowContent` is true, + * move the tooltip after chart resized + */ + + + TooltipRichContent.prototype._moveIfResized = function () { + // The ratio of left to width + var ratioX = this._styleCoord[2]; // The ratio of top to height + + var ratioY = this._styleCoord[3]; + this.moveTo(ratioX * this._zr.getWidth(), ratioY * this._zr.getHeight()); + }; + + TooltipRichContent.prototype.hide = function () { + if (this.el) { + this.el.hide(); + } + + this._show = false; + }; + + TooltipRichContent.prototype.hideLater = function (time) { + if (this._show && !(this._inContent && this._enterable)) { + if (time) { + this._hideDelay = time; // Set show false to avoid invoke hideLater multiple times + + this._show = false; + this._hideTimeout = setTimeout(bind(this.hide, this), time); + } else { + this.hide(); + } + } + }; + + TooltipRichContent.prototype.isShow = function () { + return this._show; + }; + + TooltipRichContent.prototype.dispose = function () { + this._zr.remove(this.el); + }; + + return TooltipRichContent; + }(); + + function mathMaxWith0(val) { + return Math.max(0, val); + } + + function calcShadowOuterSize(style) { + var shadowBlur = mathMaxWith0(style.shadowBlur || 0); + var shadowOffsetX = mathMaxWith0(style.shadowOffsetX || 0); + var shadowOffsetY = mathMaxWith0(style.shadowOffsetY || 0); + return { + left: mathMaxWith0(shadowBlur - shadowOffsetX), + right: mathMaxWith0(shadowBlur + shadowOffsetX), + top: mathMaxWith0(shadowBlur - shadowOffsetY), + bottom: mathMaxWith0(shadowBlur + shadowOffsetY) + }; + } + + function makeStyleCoord$1(out, zr, zrX, zrY) { + out[0] = zrX; + out[1] = zrY; + out[2] = out[0] / zr.getWidth(); + out[3] = out[1] / zr.getHeight(); + } + + var proxyRect = new Rect({ + shape: { + x: -1, + y: -1, + width: 2, + height: 2 + } + }); + + var TooltipView = + /** @class */ + function (_super) { + __extends(TooltipView, _super); + + function TooltipView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TooltipView.type; + return _this; + } + + TooltipView.prototype.init = function (ecModel, api) { + if (env.node || !api.getDom()) { + return; + } + + var tooltipModel = ecModel.getComponent('tooltip'); + var renderMode = this._renderMode = getTooltipRenderMode(tooltipModel.get('renderMode')); + this._tooltipContent = renderMode === 'richText' ? new TooltipRichContent(api) : new TooltipHTMLContent(api.getDom(), api, { + appendToBody: tooltipModel.get('appendToBody', true) + }); + }; + + TooltipView.prototype.render = function (tooltipModel, ecModel, api) { + if (env.node || !api.getDom()) { + return; + } // Reset + + + this.group.removeAll(); + this._tooltipModel = tooltipModel; + this._ecModel = ecModel; + this._api = api; + /** + * @private + * @type {boolean} + */ + + this._alwaysShowContent = tooltipModel.get('alwaysShowContent'); + var tooltipContent = this._tooltipContent; + tooltipContent.update(tooltipModel); + tooltipContent.setEnterable(tooltipModel.get('enterable')); + + this._initGlobalListener(); + + this._keepShow(); // PENDING + // `mousemove` event will be triggered very frequently when the mouse moves fast, + // which causes that the `updatePosition` function was also called frequently. + // In Chrome with devtools open and Firefox, tooltip looks laggy and shakes. See #14695 #16101 + // To avoid frequent triggering, + // consider throttling it in 50ms when transition is enabled + + + if (this._renderMode !== 'richText' && tooltipModel.get('transitionDuration')) { + createOrUpdate(this, '_updatePosition', 50, 'fixRate'); + } else { + clear(this, '_updatePosition'); + } + }; + + TooltipView.prototype._initGlobalListener = function () { + var tooltipModel = this._tooltipModel; + var triggerOn = tooltipModel.get('triggerOn'); + register('itemTooltip', this._api, bind(function (currTrigger, e, dispatchAction) { + // If 'none', it is not controlled by mouse totally. + if (triggerOn !== 'none') { + if (triggerOn.indexOf(currTrigger) >= 0) { + this._tryShow(e, dispatchAction); + } else if (currTrigger === 'leave') { + this._hide(dispatchAction); + } + } + }, this)); + }; + + TooltipView.prototype._keepShow = function () { + var tooltipModel = this._tooltipModel; + var ecModel = this._ecModel; + var api = this._api; // Try to keep the tooltip show when refreshing + + if (this._lastX != null && this._lastY != null // When user is willing to control tooltip totally using API, + // self.manuallyShowTip({x, y}) might cause tooltip hide, + // which is not expected. + && tooltipModel.get('triggerOn') !== 'none') { + var self_1 = this; + clearTimeout(this._refreshUpdateTimeout); + this._refreshUpdateTimeout = setTimeout(function () { + // Show tip next tick after other charts are rendered + // In case highlight action has wrong result + // FIXME + !api.isDisposed() && self_1.manuallyShowTip(tooltipModel, ecModel, api, { + x: self_1._lastX, + y: self_1._lastY, + dataByCoordSys: self_1._lastDataByCoordSys + }); + }); + } + }; + /** + * Show tip manually by + * dispatchAction({ + * type: 'showTip', + * x: 10, + * y: 10 + * }); + * Or + * dispatchAction({ + * type: 'showTip', + * seriesIndex: 0, + * dataIndex or dataIndexInside or name + * }); + * + * TODO Batch + */ + + + TooltipView.prototype.manuallyShowTip = function (tooltipModel, ecModel, api, payload) { + if (payload.from === this.uid || env.node || !api.getDom()) { + return; + } + + var dispatchAction = makeDispatchAction$1(payload, api); // Reset ticket + + this._ticket = ''; // When triggered from axisPointer. + + var dataByCoordSys = payload.dataByCoordSys; + var cmptRef = findComponentReference(payload, ecModel, api); + + if (cmptRef) { + var rect = cmptRef.el.getBoundingRect().clone(); + rect.applyTransform(cmptRef.el.transform); + + this._tryShow({ + offsetX: rect.x + rect.width / 2, + offsetY: rect.y + rect.height / 2, + target: cmptRef.el, + position: payload.position, + // When manully trigger, the mouse is not on the el, so we'd better to + // position tooltip on the bottom of the el and display arrow is possible. + positionDefault: 'bottom' + }, dispatchAction); + } else if (payload.tooltip && payload.x != null && payload.y != null) { + var el = proxyRect; + el.x = payload.x; + el.y = payload.y; + el.update(); + getECData(el).tooltipConfig = { + name: null, + option: payload.tooltip + }; // Manually show tooltip while view is not using zrender elements. + + this._tryShow({ + offsetX: payload.x, + offsetY: payload.y, + target: el + }, dispatchAction); + } else if (dataByCoordSys) { + this._tryShow({ + offsetX: payload.x, + offsetY: payload.y, + position: payload.position, + dataByCoordSys: dataByCoordSys, + tooltipOption: payload.tooltipOption + }, dispatchAction); + } else if (payload.seriesIndex != null) { + if (this._manuallyAxisShowTip(tooltipModel, ecModel, api, payload)) { + return; + } + + var pointInfo = findPointFromSeries(payload, ecModel); + var cx = pointInfo.point[0]; + var cy = pointInfo.point[1]; + + if (cx != null && cy != null) { + this._tryShow({ + offsetX: cx, + offsetY: cy, + target: pointInfo.el, + position: payload.position, + // When manully trigger, the mouse is not on the el, so we'd better to + // position tooltip on the bottom of the el and display arrow is possible. + positionDefault: 'bottom' + }, dispatchAction); + } + } else if (payload.x != null && payload.y != null) { + // FIXME + // should wrap dispatchAction like `axisPointer/globalListener` ? + api.dispatchAction({ + type: 'updateAxisPointer', + x: payload.x, + y: payload.y + }); + + this._tryShow({ + offsetX: payload.x, + offsetY: payload.y, + position: payload.position, + target: api.getZr().findHover(payload.x, payload.y).target + }, dispatchAction); + } + }; + + TooltipView.prototype.manuallyHideTip = function (tooltipModel, ecModel, api, payload) { + var tooltipContent = this._tooltipContent; + + if (!this._alwaysShowContent && this._tooltipModel) { + tooltipContent.hideLater(this._tooltipModel.get('hideDelay')); + } + + this._lastX = this._lastY = this._lastDataByCoordSys = null; + + if (payload.from !== this.uid) { + this._hide(makeDispatchAction$1(payload, api)); + } + }; // Be compatible with previous design, that is, when tooltip.type is 'axis' and + // dispatchAction 'showTip' with seriesIndex and dataIndex will trigger axis pointer + // and tooltip. + + + TooltipView.prototype._manuallyAxisShowTip = function (tooltipModel, ecModel, api, payload) { + var seriesIndex = payload.seriesIndex; + var dataIndex = payload.dataIndex; // @ts-ignore + + var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo; + + if (seriesIndex == null || dataIndex == null || coordSysAxesInfo == null) { + return; + } + + var seriesModel = ecModel.getSeriesByIndex(seriesIndex); + + if (!seriesModel) { + return; + } + + var data = seriesModel.getData(); + var tooltipCascadedModel = buildTooltipModel([data.getItemModel(dataIndex), seriesModel, (seriesModel.coordinateSystem || {}).model], this._tooltipModel); + + if (tooltipCascadedModel.get('trigger') !== 'axis') { + return; + } + + api.dispatchAction({ + type: 'updateAxisPointer', + seriesIndex: seriesIndex, + dataIndex: dataIndex, + position: payload.position + }); + return true; + }; + + TooltipView.prototype._tryShow = function (e, dispatchAction) { + var el = e.target; + var tooltipModel = this._tooltipModel; + + if (!tooltipModel) { + return; + } // Save mouse x, mouse y. So we can try to keep showing the tip if chart is refreshed + + + this._lastX = e.offsetX; + this._lastY = e.offsetY; + var dataByCoordSys = e.dataByCoordSys; + + if (dataByCoordSys && dataByCoordSys.length) { + this._showAxisTooltip(dataByCoordSys, e); + } else if (el) { + this._lastDataByCoordSys = null; + var seriesDispatcher_1; + var cmptDispatcher_1; + findEventDispatcher(el, function (target) { + // Always show item tooltip if mouse is on the element with dataIndex + if (getECData(target).dataIndex != null) { + seriesDispatcher_1 = target; + return true; + } // Tooltip provided directly. Like legend. + + + if (getECData(target).tooltipConfig != null) { + cmptDispatcher_1 = target; + return true; + } + }, true); + + if (seriesDispatcher_1) { + this._showSeriesItemTooltip(e, seriesDispatcher_1, dispatchAction); + } else if (cmptDispatcher_1) { + this._showComponentItemTooltip(e, cmptDispatcher_1, dispatchAction); + } else { + this._hide(dispatchAction); + } + } else { + this._lastDataByCoordSys = null; + + this._hide(dispatchAction); + } + }; + + TooltipView.prototype._showOrMove = function (tooltipModel, cb) { + // showDelay is used in this case: tooltip.enterable is set + // as true. User intent to move mouse into tooltip and click + // something. `showDelay` makes it easier to enter the content + // but tooltip do not move immediately. + var delay = tooltipModel.get('showDelay'); + cb = bind(cb, this); + clearTimeout(this._showTimout); + delay > 0 ? this._showTimout = setTimeout(cb, delay) : cb(); + }; + + TooltipView.prototype._showAxisTooltip = function (dataByCoordSys, e) { + var ecModel = this._ecModel; + var globalTooltipModel = this._tooltipModel; + var point = [e.offsetX, e.offsetY]; + var singleTooltipModel = buildTooltipModel([e.tooltipOption], globalTooltipModel); + var renderMode = this._renderMode; + var cbParamsList = []; + var articleMarkup = createTooltipMarkup('section', { + blocks: [], + noHeader: true + }); // Only for legacy: `Serise['formatTooltip']` returns a string. + + var markupTextArrLegacy = []; + var markupStyleCreator = new TooltipMarkupStyleCreator(); + each(dataByCoordSys, function (itemCoordSys) { + each(itemCoordSys.dataByAxis, function (axisItem) { + var axisModel = ecModel.getComponent(axisItem.axisDim + 'Axis', axisItem.axisIndex); + var axisValue = axisItem.value; + + if (!axisModel || axisValue == null) { + return; + } + + var axisValueLabel = getValueLabel(axisValue, axisModel.axis, ecModel, axisItem.seriesDataIndices, axisItem.valueLabelOpt); + var axisSectionMarkup = createTooltipMarkup('section', { + header: axisValueLabel, + noHeader: !trim(axisValueLabel), + sortBlocks: true, + blocks: [] + }); + articleMarkup.blocks.push(axisSectionMarkup); + each(axisItem.seriesDataIndices, function (idxItem) { + var series = ecModel.getSeriesByIndex(idxItem.seriesIndex); + var dataIndex = idxItem.dataIndexInside; + var cbParams = series.getDataParams(dataIndex); // Can't find data. + + if (cbParams.dataIndex < 0) { + return; + } + + cbParams.axisDim = axisItem.axisDim; + cbParams.axisIndex = axisItem.axisIndex; + cbParams.axisType = axisItem.axisType; + cbParams.axisId = axisItem.axisId; + cbParams.axisValue = getAxisRawValue(axisModel.axis, { + value: axisValue + }); + cbParams.axisValueLabel = axisValueLabel; // Pre-create marker style for makers. Users can assemble richText + // text in `formatter` callback and use those markers style. + + cbParams.marker = markupStyleCreator.makeTooltipMarker('item', convertToColorString(cbParams.color), renderMode); + var seriesTooltipResult = normalizeTooltipFormatResult(series.formatTooltip(dataIndex, true, null)); + var frag = seriesTooltipResult.frag; + + if (frag) { + var valueFormatter = buildTooltipModel([series], globalTooltipModel).get('valueFormatter'); + axisSectionMarkup.blocks.push(valueFormatter ? extend({ + valueFormatter: valueFormatter + }, frag) : frag); + } + + if (seriesTooltipResult.text) { + markupTextArrLegacy.push(seriesTooltipResult.text); + } + + cbParamsList.push(cbParams); + }); + }); + }); // In most cases, the second axis is displays upper on the first one. + // So we reverse it to look better. + + articleMarkup.blocks.reverse(); + markupTextArrLegacy.reverse(); + var positionExpr = e.position; + var orderMode = singleTooltipModel.get('order'); + var builtMarkupText = buildTooltipMarkup(articleMarkup, markupStyleCreator, renderMode, orderMode, ecModel.get('useUTC'), singleTooltipModel.get('textStyle')); + builtMarkupText && markupTextArrLegacy.unshift(builtMarkupText); + var blockBreak = renderMode === 'richText' ? '\n\n' : '
                                                                                          '; + var allMarkupText = markupTextArrLegacy.join(blockBreak); + + this._showOrMove(singleTooltipModel, function () { + if (this._updateContentNotChangedOnAxis(dataByCoordSys, cbParamsList)) { + this._updatePosition(singleTooltipModel, positionExpr, point[0], point[1], this._tooltipContent, cbParamsList); + } else { + this._showTooltipContent(singleTooltipModel, allMarkupText, cbParamsList, Math.random() + '', point[0], point[1], positionExpr, null, markupStyleCreator); + } + }); // Do not trigger events here, because this branch only be entered + // from dispatchAction. + + }; + + TooltipView.prototype._showSeriesItemTooltip = function (e, dispatcher, dispatchAction) { + var ecModel = this._ecModel; + var ecData = getECData(dispatcher); // Use dataModel in element if possible + // Used when mouseover on a element like markPoint or edge + // In which case, the data is not main data in series. + + var seriesIndex = ecData.seriesIndex; + var seriesModel = ecModel.getSeriesByIndex(seriesIndex); // For example, graph link. + + var dataModel = ecData.dataModel || seriesModel; + var dataIndex = ecData.dataIndex; + var dataType = ecData.dataType; + var data = dataModel.getData(dataType); + var renderMode = this._renderMode; + var positionDefault = e.positionDefault; + var tooltipModel = buildTooltipModel([data.getItemModel(dataIndex), dataModel, seriesModel && (seriesModel.coordinateSystem || {}).model], this._tooltipModel, positionDefault ? { + position: positionDefault + } : null); + var tooltipTrigger = tooltipModel.get('trigger'); + + if (tooltipTrigger != null && tooltipTrigger !== 'item') { + return; + } + + var params = dataModel.getDataParams(dataIndex, dataType); + var markupStyleCreator = new TooltipMarkupStyleCreator(); // Pre-create marker style for makers. Users can assemble richText + // text in `formatter` callback and use those markers style. + + params.marker = markupStyleCreator.makeTooltipMarker('item', convertToColorString(params.color), renderMode); + var seriesTooltipResult = normalizeTooltipFormatResult(dataModel.formatTooltip(dataIndex, false, dataType)); + var orderMode = tooltipModel.get('order'); + var valueFormatter = tooltipModel.get('valueFormatter'); + var frag = seriesTooltipResult.frag; + var markupText = frag ? buildTooltipMarkup(valueFormatter ? extend({ + valueFormatter: valueFormatter + }, frag) : frag, markupStyleCreator, renderMode, orderMode, ecModel.get('useUTC'), tooltipModel.get('textStyle')) : seriesTooltipResult.text; + var asyncTicket = 'item_' + dataModel.name + '_' + dataIndex; + + this._showOrMove(tooltipModel, function () { + this._showTooltipContent(tooltipModel, markupText, params, asyncTicket, e.offsetX, e.offsetY, e.position, e.target, markupStyleCreator); + }); // FIXME + // duplicated showtip if manuallyShowTip is called from dispatchAction. + + + dispatchAction({ + type: 'showTip', + dataIndexInside: dataIndex, + dataIndex: data.getRawIndex(dataIndex), + seriesIndex: seriesIndex, + from: this.uid + }); + }; + + TooltipView.prototype._showComponentItemTooltip = function (e, el, dispatchAction) { + var ecData = getECData(el); + var tooltipConfig = ecData.tooltipConfig; + var tooltipOpt = tooltipConfig.option || {}; + + if (isString(tooltipOpt)) { + var content = tooltipOpt; + tooltipOpt = { + content: content, + // Fixed formatter + formatter: content + }; + } + + var tooltipModelCascade = [tooltipOpt]; + + var cmpt = this._ecModel.getComponent(ecData.componentMainType, ecData.componentIndex); + + if (cmpt) { + tooltipModelCascade.push(cmpt); + } // In most cases, component tooltip formatter has different params with series tooltip formatter, + // so that they can not share the same formatter. Since the global tooltip formatter is used for series + // by convension, we do not use it as the default formatter for component. + + + tooltipModelCascade.push({ + formatter: tooltipOpt.content + }); + var positionDefault = e.positionDefault; + var subTooltipModel = buildTooltipModel(tooltipModelCascade, this._tooltipModel, positionDefault ? { + position: positionDefault + } : null); + var defaultHtml = subTooltipModel.get('content'); + var asyncTicket = Math.random() + ''; // PENDING: this case do not support richText style yet. + + var markupStyleCreator = new TooltipMarkupStyleCreator(); // Do not check whether `trigger` is 'none' here, because `trigger` + // only works on coordinate system. In fact, we have not found case + // that requires setting `trigger` nothing on component yet. + + this._showOrMove(subTooltipModel, function () { + // Use formatterParams from element defined in component + // Avoid users modify it. + var formatterParams = clone(subTooltipModel.get('formatterParams') || {}); + + this._showTooltipContent(subTooltipModel, defaultHtml, formatterParams, asyncTicket, e.offsetX, e.offsetY, e.position, el, markupStyleCreator); + }); // If not dispatch showTip, tip may be hide triggered by axis. + + + dispatchAction({ + type: 'showTip', + from: this.uid + }); + }; + + TooltipView.prototype._showTooltipContent = function ( // Use Model insteadof TooltipModel because this model may be from series or other options. + // Instead of top level tooltip. + tooltipModel, defaultHtml, params, asyncTicket, x, y, positionExpr, el, markupStyleCreator) { + // Reset ticket + this._ticket = ''; + + if (!tooltipModel.get('showContent') || !tooltipModel.get('show')) { + return; + } + + var tooltipContent = this._tooltipContent; + tooltipContent.setEnterable(tooltipModel.get('enterable')); + var formatter = tooltipModel.get('formatter'); + positionExpr = positionExpr || tooltipModel.get('position'); + var html = defaultHtml; + + var nearPoint = this._getNearestPoint([x, y], params, tooltipModel.get('trigger'), tooltipModel.get('borderColor')); + + var nearPointColor = nearPoint.color; + + if (formatter) { + if (isString(formatter)) { + var useUTC = tooltipModel.ecModel.get('useUTC'); + var params0 = isArray(params) ? params[0] : params; + var isTimeAxis = params0 && params0.axisType && params0.axisType.indexOf('time') >= 0; + html = formatter; + + if (isTimeAxis) { + html = format(params0.axisValue, html, useUTC); + } + + html = formatTpl(html, params, true); + } else if (isFunction(formatter)) { + var callback = bind(function (cbTicket, html) { + if (cbTicket === this._ticket) { + tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPointColor, positionExpr); + + this._updatePosition(tooltipModel, positionExpr, x, y, tooltipContent, params, el); + } + }, this); + this._ticket = asyncTicket; + html = formatter(params, asyncTicket, callback); + } else { + html = formatter; + } + } + + tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPointColor, positionExpr); + tooltipContent.show(tooltipModel, nearPointColor); + + this._updatePosition(tooltipModel, positionExpr, x, y, tooltipContent, params, el); + }; + + TooltipView.prototype._getNearestPoint = function (point, tooltipDataParams, trigger, borderColor) { + if (trigger === 'axis' || isArray(tooltipDataParams)) { + return { + color: borderColor || (this._renderMode === 'html' ? '#fff' : 'none') + }; + } + + if (!isArray(tooltipDataParams)) { + return { + color: borderColor || tooltipDataParams.color || tooltipDataParams.borderColor + }; + } + }; + + TooltipView.prototype._updatePosition = function (tooltipModel, positionExpr, x, // Mouse x + y, // Mouse y + content, params, el) { + var viewWidth = this._api.getWidth(); + + var viewHeight = this._api.getHeight(); + + positionExpr = positionExpr || tooltipModel.get('position'); + var contentSize = content.getSize(); + var align = tooltipModel.get('align'); + var vAlign = tooltipModel.get('verticalAlign'); + var rect = el && el.getBoundingRect().clone(); + el && rect.applyTransform(el.transform); + + if (isFunction(positionExpr)) { + // Callback of position can be an array or a string specify the position + positionExpr = positionExpr([x, y], params, content.el, rect, { + viewSize: [viewWidth, viewHeight], + contentSize: contentSize.slice() + }); + } + + if (isArray(positionExpr)) { + x = parsePercent$1(positionExpr[0], viewWidth); + y = parsePercent$1(positionExpr[1], viewHeight); + } else if (isObject(positionExpr)) { + var boxLayoutPosition = positionExpr; + boxLayoutPosition.width = contentSize[0]; + boxLayoutPosition.height = contentSize[1]; + var layoutRect = getLayoutRect(boxLayoutPosition, { + width: viewWidth, + height: viewHeight + }); + x = layoutRect.x; + y = layoutRect.y; + align = null; // When positionExpr is left/top/right/bottom, + // align and verticalAlign will not work. + + vAlign = null; + } // Specify tooltip position by string 'top' 'bottom' 'left' 'right' around graphic element + else if (isString(positionExpr) && el) { + var pos = calcTooltipPosition(positionExpr, rect, contentSize, tooltipModel.get('borderWidth')); + x = pos[0]; + y = pos[1]; + } else { + var pos = refixTooltipPosition(x, y, content, viewWidth, viewHeight, align ? null : 20, vAlign ? null : 20); + x = pos[0]; + y = pos[1]; + } + + align && (x -= isCenterAlign(align) ? contentSize[0] / 2 : align === 'right' ? contentSize[0] : 0); + vAlign && (y -= isCenterAlign(vAlign) ? contentSize[1] / 2 : vAlign === 'bottom' ? contentSize[1] : 0); + + if (shouldTooltipConfine(tooltipModel)) { + var pos = confineTooltipPosition(x, y, content, viewWidth, viewHeight); + x = pos[0]; + y = pos[1]; + } + + content.moveTo(x, y); + }; // FIXME + // Should we remove this but leave this to user? + + + TooltipView.prototype._updateContentNotChangedOnAxis = function (dataByCoordSys, cbParamsList) { + var lastCoordSys = this._lastDataByCoordSys; + var lastCbParamsList = this._cbParamsList; + var contentNotChanged = !!lastCoordSys && lastCoordSys.length === dataByCoordSys.length; + contentNotChanged && each(lastCoordSys, function (lastItemCoordSys, indexCoordSys) { + var lastDataByAxis = lastItemCoordSys.dataByAxis || []; + var thisItemCoordSys = dataByCoordSys[indexCoordSys] || {}; + var thisDataByAxis = thisItemCoordSys.dataByAxis || []; + contentNotChanged = contentNotChanged && lastDataByAxis.length === thisDataByAxis.length; + contentNotChanged && each(lastDataByAxis, function (lastItem, indexAxis) { + var thisItem = thisDataByAxis[indexAxis] || {}; + var lastIndices = lastItem.seriesDataIndices || []; + var newIndices = thisItem.seriesDataIndices || []; + contentNotChanged = contentNotChanged && lastItem.value === thisItem.value && lastItem.axisType === thisItem.axisType && lastItem.axisId === thisItem.axisId && lastIndices.length === newIndices.length; + contentNotChanged && each(lastIndices, function (lastIdxItem, j) { + var newIdxItem = newIndices[j]; + contentNotChanged = contentNotChanged && lastIdxItem.seriesIndex === newIdxItem.seriesIndex && lastIdxItem.dataIndex === newIdxItem.dataIndex; + }); // check is cbParams data value changed + + lastCbParamsList && each(lastItem.seriesDataIndices, function (idxItem) { + var seriesIdx = idxItem.seriesIndex; + var cbParams = cbParamsList[seriesIdx]; + var lastCbParams = lastCbParamsList[seriesIdx]; + + if (cbParams && lastCbParams && lastCbParams.data !== cbParams.data) { + contentNotChanged = false; + } + }); + }); + }); + this._lastDataByCoordSys = dataByCoordSys; + this._cbParamsList = cbParamsList; + return !!contentNotChanged; + }; + + TooltipView.prototype._hide = function (dispatchAction) { + // Do not directly hideLater here, because this behavior may be prevented + // in dispatchAction when showTip is dispatched. + // FIXME + // duplicated hideTip if manuallyHideTip is called from dispatchAction. + this._lastDataByCoordSys = null; + dispatchAction({ + type: 'hideTip', + from: this.uid + }); + }; + + TooltipView.prototype.dispose = function (ecModel, api) { + if (env.node || !api.getDom()) { + return; + } + + clear(this, '_updatePosition'); + + this._tooltipContent.dispose(); + + unregister('itemTooltip', api); + }; + + TooltipView.type = 'tooltip'; + return TooltipView; + }(ComponentView); + /** + * From top to bottom. (the last one should be globalTooltipModel); + */ + + + function buildTooltipModel(modelCascade, globalTooltipModel, defaultTooltipOption) { + // Last is always tooltip model. + var ecModel = globalTooltipModel.ecModel; + var resultModel; + + if (defaultTooltipOption) { + resultModel = new Model(defaultTooltipOption, ecModel, ecModel); + resultModel = new Model(globalTooltipModel.option, resultModel, ecModel); + } else { + resultModel = globalTooltipModel; + } + + for (var i = modelCascade.length - 1; i >= 0; i--) { + var tooltipOpt = modelCascade[i]; + + if (tooltipOpt) { + if (tooltipOpt instanceof Model) { + tooltipOpt = tooltipOpt.get('tooltip', true); + } // In each data item tooltip can be simply write: + // { + // value: 10, + // tooltip: 'Something you need to know' + // } + + + if (isString(tooltipOpt)) { + tooltipOpt = { + formatter: tooltipOpt + }; + } + + if (tooltipOpt) { + resultModel = new Model(tooltipOpt, resultModel, ecModel); + } + } + } + + return resultModel; + } + + function makeDispatchAction$1(payload, api) { + return payload.dispatchAction || bind(api.dispatchAction, api); + } + + function refixTooltipPosition(x, y, content, viewWidth, viewHeight, gapH, gapV) { + var size = content.getSize(); + var width = size[0]; + var height = size[1]; + + if (gapH != null) { + // Add extra 2 pixels for this case: + // At present the "values" in defaut tooltip are using CSS `float: right`. + // When the right edge of the tooltip box is on the right side of the + // viewport, the `float` layout might push the "values" to the second line. + if (x + width + gapH + 2 > viewWidth) { + x -= width + gapH; + } else { + x += gapH; + } + } + + if (gapV != null) { + if (y + height + gapV > viewHeight) { + y -= height + gapV; + } else { + y += gapV; + } + } + + return [x, y]; + } + + function confineTooltipPosition(x, y, content, viewWidth, viewHeight) { + var size = content.getSize(); + var width = size[0]; + var height = size[1]; + x = Math.min(x + width, viewWidth) - width; + y = Math.min(y + height, viewHeight) - height; + x = Math.max(x, 0); + y = Math.max(y, 0); + return [x, y]; + } + + function calcTooltipPosition(position, rect, contentSize, borderWidth) { + var domWidth = contentSize[0]; + var domHeight = contentSize[1]; + var offset = Math.ceil(Math.SQRT2 * borderWidth) + 8; + var x = 0; + var y = 0; + var rectWidth = rect.width; + var rectHeight = rect.height; + + switch (position) { + case 'inside': + x = rect.x + rectWidth / 2 - domWidth / 2; + y = rect.y + rectHeight / 2 - domHeight / 2; + break; + + case 'top': + x = rect.x + rectWidth / 2 - domWidth / 2; + y = rect.y - domHeight - offset; + break; + + case 'bottom': + x = rect.x + rectWidth / 2 - domWidth / 2; + y = rect.y + rectHeight + offset; + break; + + case 'left': + x = rect.x - domWidth - offset; + y = rect.y + rectHeight / 2 - domHeight / 2; + break; + + case 'right': + x = rect.x + rectWidth + offset; + y = rect.y + rectHeight / 2 - domHeight / 2; + } + + return [x, y]; + } + + function isCenterAlign(align) { + return align === 'center' || align === 'middle'; + } + /** + * Find target component by payload like: + * ```js + * { legendId: 'some_id', name: 'xxx' } + * { toolboxIndex: 1, name: 'xxx' } + * { geoName: 'some_name', name: 'xxx' } + * ``` + * PENDING: at present only + * + * If not found, return null/undefined. + */ + + + function findComponentReference(payload, ecModel, api) { + var queryOptionMap = preParseFinder(payload).queryOptionMap; + var componentMainType = queryOptionMap.keys()[0]; + + if (!componentMainType || componentMainType === 'series') { + return; + } + + var queryResult = queryReferringComponents(ecModel, componentMainType, queryOptionMap.get(componentMainType), { + useDefault: false, + enableAll: false, + enableNone: false + }); + var model = queryResult.models[0]; + + if (!model) { + return; + } + + var view = api.getViewOfComponentModel(model); + var el; + view.group.traverse(function (subEl) { + var tooltipConfig = getECData(subEl).tooltipConfig; + + if (tooltipConfig && tooltipConfig.name === payload.name) { + el = subEl; + return true; // stop + } + }); + + if (el) { + return { + componentMainType: componentMainType, + componentIndex: model.componentIndex, + el: el + }; + } + } + + function install$A(registers) { + use(install$s); + registers.registerComponentModel(TooltipModel); + registers.registerComponentView(TooltipView); + /** + * @action + * @property {string} type + * @property {number} seriesIndex + * @property {number} dataIndex + * @property {number} [x] + * @property {number} [y] + */ + + registers.registerAction({ + type: 'showTip', + event: 'showTip', + update: 'tooltip:manuallyShowTip' + }, noop); + registers.registerAction({ + type: 'hideTip', + event: 'hideTip', + update: 'tooltip:manuallyHideTip' + }, noop); + } + + var DEFAULT_TOOLBOX_BTNS = ['rect', 'polygon', 'keep', 'clear']; + function brushPreprocessor(option, isNew) { + var brushComponents = normalizeToArray(option ? option.brush : []); + + if (!brushComponents.length) { + return; + } + + var brushComponentSpecifiedBtns = []; + each(brushComponents, function (brushOpt) { + var tbs = brushOpt.hasOwnProperty('toolbox') ? brushOpt.toolbox : []; + + if (tbs instanceof Array) { + brushComponentSpecifiedBtns = brushComponentSpecifiedBtns.concat(tbs); + } + }); + var toolbox = option && option.toolbox; + + if (isArray(toolbox)) { + toolbox = toolbox[0]; + } + + if (!toolbox) { + toolbox = { + feature: {} + }; + option.toolbox = [toolbox]; + } + + var toolboxFeature = toolbox.feature || (toolbox.feature = {}); + var toolboxBrush = toolboxFeature.brush || (toolboxFeature.brush = {}); + var brushTypes = toolboxBrush.type || (toolboxBrush.type = []); + brushTypes.push.apply(brushTypes, brushComponentSpecifiedBtns); + removeDuplicate(brushTypes); + + if (isNew && !brushTypes.length) { + brushTypes.push.apply(brushTypes, DEFAULT_TOOLBOX_BTNS); + } + } + + function removeDuplicate(arr) { + var map = {}; + each(arr, function (val) { + map[val] = 1; + }); + arr.length = 0; + each(map, function (flag, val) { + arr.push(val); + }); + } + + var each$b = each; + + function hasKeys(obj) { + if (obj) { + for (var name_1 in obj) { + if (obj.hasOwnProperty(name_1)) { + return true; + } + } + } + } + + function createVisualMappings(option, stateList, supplementVisualOption) { + var visualMappings = {}; + each$b(stateList, function (state) { + var mappings = visualMappings[state] = createMappings(); + each$b(option[state], function (visualData, visualType) { + if (!VisualMapping.isValidType(visualType)) { + return; + } + + var mappingOption = { + type: visualType, + visual: visualData + }; + supplementVisualOption && supplementVisualOption(mappingOption, state); + mappings[visualType] = new VisualMapping(mappingOption); // Prepare a alpha for opacity, for some case that opacity + // is not supported, such as rendering using gradient color. + + if (visualType === 'opacity') { + mappingOption = clone(mappingOption); + mappingOption.type = 'colorAlpha'; + mappings.__hidden.__alphaForOpacity = new VisualMapping(mappingOption); + } + }); + }); + return visualMappings; + + function createMappings() { + var Creater = function () {}; // Make sure hidden fields will not be visited by + // object iteration (with hasOwnProperty checking). + + + Creater.prototype.__hidden = Creater.prototype; + var obj = new Creater(); + return obj; + } + } + function replaceVisualOption(thisOption, newOption, keys) { + // Visual attributes merge is not supported, otherwise it + // brings overcomplicated merge logic. See #2853. So if + // newOption has anyone of these keys, all of these keys + // will be reset. Otherwise, all keys remain. + var has; + each(keys, function (key) { + if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) { + has = true; + } + }); + has && each(keys, function (key) { + if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) { + thisOption[key] = clone(newOption[key]); + } else { + delete thisOption[key]; + } + }); + } + /** + * @param stateList + * @param visualMappings + * @param list + * @param getValueState param: valueOrIndex, return: state. + * @param scope Scope for getValueState + * @param dimension Concrete dimension, if used. + */ + // ???! handle brush? + + function applyVisual(stateList, visualMappings, data, getValueState, scope, dimension) { + var visualTypesMap = {}; + each(stateList, function (state) { + var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]); + visualTypesMap[state] = visualTypes; + }); + var dataIndex; + + function getVisual(key) { + return getItemVisualFromData(data, dataIndex, key); + } + + function setVisual(key, value) { + setItemVisualFromData(data, dataIndex, key, value); + } + + if (dimension == null) { + data.each(eachItem); + } else { + data.each([dimension], eachItem); + } + + function eachItem(valueOrIndex, index) { + dataIndex = dimension == null ? valueOrIndex // First argument is index + : index; + var rawDataItem = data.getRawDataItem(dataIndex); // Consider performance + // @ts-ignore + + if (rawDataItem && rawDataItem.visualMap === false) { + return; + } + + var valueState = getValueState.call(scope, valueOrIndex); + var mappings = visualMappings[valueState]; + var visualTypes = visualTypesMap[valueState]; + + for (var i = 0, len = visualTypes.length; i < len; i++) { + var type = visualTypes[i]; + mappings[type] && mappings[type].applyVisual(valueOrIndex, getVisual, setVisual); + } + } + } + /** + * @param data + * @param stateList + * @param visualMappings > + * @param getValueState param: valueOrIndex, return: state. + * @param dim dimension or dimension index. + */ + + function incrementalApplyVisual(stateList, visualMappings, getValueState, dim) { + var visualTypesMap = {}; + each(stateList, function (state) { + var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]); + visualTypesMap[state] = visualTypes; + }); + return { + progress: function progress(params, data) { + var dimIndex; + + if (dim != null) { + dimIndex = data.getDimensionIndex(dim); + } + + function getVisual(key) { + return getItemVisualFromData(data, dataIndex, key); + } + + function setVisual(key, value) { + setItemVisualFromData(data, dataIndex, key, value); + } + + var dataIndex; + var store = data.getStore(); + + while ((dataIndex = params.next()) != null) { + var rawDataItem = data.getRawDataItem(dataIndex); // Consider performance + // @ts-ignore + + if (rawDataItem && rawDataItem.visualMap === false) { + continue; + } + + var value = dim != null ? store.get(dimIndex, dataIndex) : dataIndex; + var valueState = getValueState(value); + var mappings = visualMappings[valueState]; + var visualTypes = visualTypesMap[valueState]; + + for (var i = 0, len = visualTypes.length; i < len; i++) { + var type = visualTypes[i]; + mappings[type] && mappings[type].applyVisual(value, getVisual, setVisual); + } + } + } + }; + } + + function makeBrushCommonSelectorForSeries(area) { + var brushType = area.brushType; // Do not use function binding or curry for performance. + + var selectors = { + point: function (itemLayout) { + return selector[brushType].point(itemLayout, selectors, area); + }, + rect: function (itemLayout) { + return selector[brushType].rect(itemLayout, selectors, area); + } + }; + return selectors; + } + var selector = { + lineX: getLineSelectors(0), + lineY: getLineSelectors(1), + rect: { + point: function (itemLayout, selectors, area) { + return itemLayout && area.boundingRect.contain(itemLayout[0], itemLayout[1]); + }, + rect: function (itemLayout, selectors, area) { + return itemLayout && area.boundingRect.intersect(itemLayout); + } + }, + polygon: { + point: function (itemLayout, selectors, area) { + return itemLayout && area.boundingRect.contain(itemLayout[0], itemLayout[1]) && contain$2(area.range, itemLayout[0], itemLayout[1]); + }, + rect: function (itemLayout, selectors, area) { + var points = area.range; + + if (!itemLayout || points.length <= 1) { + return false; + } + + var x = itemLayout.x; + var y = itemLayout.y; + var width = itemLayout.width; + var height = itemLayout.height; + var p = points[0]; + + if (contain$2(points, x, y) || contain$2(points, x + width, y) || contain$2(points, x, y + height) || contain$2(points, x + width, y + height) || BoundingRect.create(itemLayout).contain(p[0], p[1]) || linePolygonIntersect(x, y, x + width, y, points) || linePolygonIntersect(x, y, x, y + height, points) || linePolygonIntersect(x + width, y, x + width, y + height, points) || linePolygonIntersect(x, y + height, x + width, y + height, points)) { + return true; + } + } + } + }; + + function getLineSelectors(xyIndex) { + var xy = ['x', 'y']; + var wh = ['width', 'height']; + return { + point: function (itemLayout, selectors, area) { + if (itemLayout) { + var range = area.range; + var p = itemLayout[xyIndex]; + return inLineRange(p, range); + } + }, + rect: function (itemLayout, selectors, area) { + if (itemLayout) { + var range = area.range; + var layoutRange = [itemLayout[xy[xyIndex]], itemLayout[xy[xyIndex]] + itemLayout[wh[xyIndex]]]; + layoutRange[1] < layoutRange[0] && layoutRange.reverse(); + return inLineRange(layoutRange[0], range) || inLineRange(layoutRange[1], range) || inLineRange(range[0], layoutRange) || inLineRange(range[1], layoutRange); + } + } + }; + } + + function inLineRange(p, range) { + return range[0] <= p && p <= range[1]; + } + + var STATE_LIST = ['inBrush', 'outOfBrush']; + var DISPATCH_METHOD = '__ecBrushSelect'; + var DISPATCH_FLAG = '__ecInBrushSelectEvent'; + function layoutCovers(ecModel) { + ecModel.eachComponent({ + mainType: 'brush' + }, function (brushModel) { + var brushTargetManager = brushModel.brushTargetManager = new BrushTargetManager(brushModel.option, ecModel); + brushTargetManager.setInputRanges(brushModel.areas, ecModel); + }); + } + /** + * Register the visual encoding if this modules required. + */ + + function brushVisual(ecModel, api, payload) { + var brushSelected = []; + var throttleType; + var throttleDelay; + ecModel.eachComponent({ + mainType: 'brush' + }, function (brushModel) { + payload && payload.type === 'takeGlobalCursor' && brushModel.setBrushOption(payload.key === 'brush' ? payload.brushOption : { + brushType: false + }); + }); + layoutCovers(ecModel); + ecModel.eachComponent({ + mainType: 'brush' + }, function (brushModel, brushIndex) { + var thisBrushSelected = { + brushId: brushModel.id, + brushIndex: brushIndex, + brushName: brushModel.name, + areas: clone(brushModel.areas), + selected: [] + }; // Every brush component exists in event params, convenient + // for user to find by index. + + brushSelected.push(thisBrushSelected); + var brushOption = brushModel.option; + var brushLink = brushOption.brushLink; + var linkedSeriesMap = []; + var selectedDataIndexForLink = []; + var rangeInfoBySeries = []; + var hasBrushExists = false; + + if (!brushIndex) { + // Only the first throttle setting works. + throttleType = brushOption.throttleType; + throttleDelay = brushOption.throttleDelay; + } // Add boundingRect and selectors to range. + + + var areas = map(brushModel.areas, function (area) { + var builder = boundingRectBuilders[area.brushType]; + var selectableArea = defaults({ + boundingRect: builder ? builder(area) : void 0 + }, area); + selectableArea.selectors = makeBrushCommonSelectorForSeries(selectableArea); + return selectableArea; + }); + var visualMappings = createVisualMappings(brushModel.option, STATE_LIST, function (mappingOption) { + mappingOption.mappingMethod = 'fixed'; + }); + isArray(brushLink) && each(brushLink, function (seriesIndex) { + linkedSeriesMap[seriesIndex] = 1; + }); + + function linkOthers(seriesIndex) { + return brushLink === 'all' || !!linkedSeriesMap[seriesIndex]; + } // If no supported brush or no brush on the series, + // all visuals should be in original state. + + + function brushed(rangeInfoList) { + return !!rangeInfoList.length; + } + /** + * Logic for each series: (If the logic has to be modified one day, do it carefully!) + * + * ( brushed ┬ && ┬hasBrushExist ┬ && linkOthers ) => StepA: ┬record, ┬ StepB: ┬visualByRecord. + * !brushed┘ ├hasBrushExist ┤ └nothing,┘ ├visualByRecord. + * └!hasBrushExist┘ └nothing. + * ( !brushed && ┬hasBrushExist ┬ && linkOthers ) => StepA: nothing, StepB: ┬visualByRecord. + * └!hasBrushExist┘ └nothing. + * ( brushed ┬ && !linkOthers ) => StepA: nothing, StepB: ┬visualByCheck. + * !brushed┘ └nothing. + * ( !brushed && !linkOthers ) => StepA: nothing, StepB: nothing. + */ + // Step A + + + ecModel.eachSeries(function (seriesModel, seriesIndex) { + var rangeInfoList = rangeInfoBySeries[seriesIndex] = []; + seriesModel.subType === 'parallel' ? stepAParallel(seriesModel, seriesIndex) : stepAOthers(seriesModel, seriesIndex, rangeInfoList); + }); + + function stepAParallel(seriesModel, seriesIndex) { + var coordSys = seriesModel.coordinateSystem; + hasBrushExists = hasBrushExists || coordSys.hasAxisBrushed(); + linkOthers(seriesIndex) && coordSys.eachActiveState(seriesModel.getData(), function (activeState, dataIndex) { + activeState === 'active' && (selectedDataIndexForLink[dataIndex] = 1); + }); + } + + function stepAOthers(seriesModel, seriesIndex, rangeInfoList) { + if (!seriesModel.brushSelector || brushModelNotControll(brushModel, seriesIndex)) { + return; + } + + each(areas, function (area) { + if (brushModel.brushTargetManager.controlSeries(area, seriesModel, ecModel)) { + rangeInfoList.push(area); + } + + hasBrushExists = hasBrushExists || brushed(rangeInfoList); + }); + + if (linkOthers(seriesIndex) && brushed(rangeInfoList)) { + var data_1 = seriesModel.getData(); + data_1.each(function (dataIndex) { + if (checkInRange(seriesModel, rangeInfoList, data_1, dataIndex)) { + selectedDataIndexForLink[dataIndex] = 1; + } + }); + } + } // Step B + + + ecModel.eachSeries(function (seriesModel, seriesIndex) { + var seriesBrushSelected = { + seriesId: seriesModel.id, + seriesIndex: seriesIndex, + seriesName: seriesModel.name, + dataIndex: [] + }; // Every series exists in event params, convenient + // for user to find series by seriesIndex. + + thisBrushSelected.selected.push(seriesBrushSelected); + var rangeInfoList = rangeInfoBySeries[seriesIndex]; + var data = seriesModel.getData(); + var getValueState = linkOthers(seriesIndex) ? function (dataIndex) { + return selectedDataIndexForLink[dataIndex] ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') : 'outOfBrush'; + } : function (dataIndex) { + return checkInRange(seriesModel, rangeInfoList, data, dataIndex) ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') : 'outOfBrush'; + }; // If no supported brush or no brush, all visuals are in original state. + + (linkOthers(seriesIndex) ? hasBrushExists : brushed(rangeInfoList)) && applyVisual(STATE_LIST, visualMappings, data, getValueState); + }); + }); + dispatchAction(api, throttleType, throttleDelay, brushSelected, payload); + } + + function dispatchAction(api, throttleType, throttleDelay, brushSelected, payload) { + // This event will not be triggered when `setOpion`, otherwise dead lock may + // triggered when do `setOption` in event listener, which we do not find + // satisfactory way to solve yet. Some considered resolutions: + // (a) Diff with prevoius selected data ant only trigger event when changed. + // But store previous data and diff precisely (i.e., not only by dataIndex, but + // also detect value changes in selected data) might bring complexity or fragility. + // (b) Use spectial param like `silent` to suppress event triggering. + // But such kind of volatile param may be weird in `setOption`. + if (!payload) { + return; + } + + var zr = api.getZr(); + + if (zr[DISPATCH_FLAG]) { + return; + } + + if (!zr[DISPATCH_METHOD]) { + zr[DISPATCH_METHOD] = doDispatch; + } + + var fn = createOrUpdate(zr, DISPATCH_METHOD, throttleDelay, throttleType); + fn(api, brushSelected); + } + + function doDispatch(api, brushSelected) { + if (!api.isDisposed()) { + var zr = api.getZr(); + zr[DISPATCH_FLAG] = true; + api.dispatchAction({ + type: 'brushSelect', + batch: brushSelected + }); + zr[DISPATCH_FLAG] = false; + } + } + + function checkInRange(seriesModel, rangeInfoList, data, dataIndex) { + for (var i = 0, len = rangeInfoList.length; i < len; i++) { + var area = rangeInfoList[i]; + + if (seriesModel.brushSelector(dataIndex, data, area.selectors, area)) { + return true; + } + } + } + + function brushModelNotControll(brushModel, seriesIndex) { + var seriesIndices = brushModel.option.seriesIndex; + return seriesIndices != null && seriesIndices !== 'all' && (isArray(seriesIndices) ? indexOf(seriesIndices, seriesIndex) < 0 : seriesIndex !== seriesIndices); + } + + var boundingRectBuilders = { + rect: function (area) { + return getBoundingRectFromMinMax(area.range); + }, + polygon: function (area) { + var minMax; + var range = area.range; + + for (var i = 0, len = range.length; i < len; i++) { + minMax = minMax || [[Infinity, -Infinity], [Infinity, -Infinity]]; + var rg = range[i]; + rg[0] < minMax[0][0] && (minMax[0][0] = rg[0]); + rg[0] > minMax[0][1] && (minMax[0][1] = rg[0]); + rg[1] < minMax[1][0] && (minMax[1][0] = rg[1]); + rg[1] > minMax[1][1] && (minMax[1][1] = rg[1]); + } + + return minMax && getBoundingRectFromMinMax(minMax); + } + }; + + function getBoundingRectFromMinMax(minMax) { + return new BoundingRect(minMax[0][0], minMax[1][0], minMax[0][1] - minMax[0][0], minMax[1][1] - minMax[1][0]); + } + + var BrushView = + /** @class */ + function (_super) { + __extends(BrushView, _super); + + function BrushView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = BrushView.type; + return _this; + } + + BrushView.prototype.init = function (ecModel, api) { + this.ecModel = ecModel; + this.api = api; + this.model; + (this._brushController = new BrushController(api.getZr())).on('brush', bind(this._onBrush, this)).mount(); + }; + + BrushView.prototype.render = function (brushModel, ecModel, api, payload) { + this.model = brushModel; + + this._updateController(brushModel, ecModel, api, payload); + }; + + BrushView.prototype.updateTransform = function (brushModel, ecModel, api, payload) { + // PENDING: `updateTransform` is a little tricky, whose layout need + // to be calculate mandatorily and other stages will not be performed. + // Take care the correctness of the logic. See #11754 . + layoutCovers(ecModel); + + this._updateController(brushModel, ecModel, api, payload); + }; + + BrushView.prototype.updateVisual = function (brushModel, ecModel, api, payload) { + this.updateTransform(brushModel, ecModel, api, payload); + }; + + BrushView.prototype.updateView = function (brushModel, ecModel, api, payload) { + this._updateController(brushModel, ecModel, api, payload); + }; + + BrushView.prototype._updateController = function (brushModel, ecModel, api, payload) { + // Do not update controller when drawing. + (!payload || payload.$from !== brushModel.id) && this._brushController.setPanels(brushModel.brushTargetManager.makePanelOpts(api)).enableBrush(brushModel.brushOption).updateCovers(brushModel.areas.slice()); + }; // updateLayout: updateController, + // updateVisual: updateController, + + + BrushView.prototype.dispose = function () { + this._brushController.dispose(); + }; + + BrushView.prototype._onBrush = function (eventParam) { + var modelId = this.model.id; + var areas = this.model.brushTargetManager.setOutputRanges(eventParam.areas, this.ecModel); // Action is not dispatched on drag end, because the drag end + // emits the same params with the last drag move event, and + // may have some delay when using touch pad, which makes + // animation not smooth (when using debounce). + + (!eventParam.isEnd || eventParam.removeOnClick) && this.api.dispatchAction({ + type: 'brush', + brushId: modelId, + areas: clone(areas), + $from: modelId + }); + eventParam.isEnd && this.api.dispatchAction({ + type: 'brushEnd', + brushId: modelId, + areas: clone(areas), + $from: modelId + }); + }; + + BrushView.type = 'brush'; + return BrushView; + }(ComponentView); + + var DEFAULT_OUT_OF_BRUSH_COLOR = '#ddd'; + + var BrushModel = + /** @class */ + function (_super) { + __extends(BrushModel, _super); + + function BrushModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = BrushModel.type; + /** + * @readOnly + */ + + _this.areas = []; + /** + * Current brush painting area settings. + * @readOnly + */ + + _this.brushOption = {}; + return _this; + } + + BrushModel.prototype.optionUpdated = function (newOption, isInit) { + var thisOption = this.option; + !isInit && replaceVisualOption(thisOption, newOption, ['inBrush', 'outOfBrush']); + var inBrush = thisOption.inBrush = thisOption.inBrush || {}; // Always give default visual, consider setOption at the second time. + + thisOption.outOfBrush = thisOption.outOfBrush || { + color: DEFAULT_OUT_OF_BRUSH_COLOR + }; + + if (!inBrush.hasOwnProperty('liftZ')) { + // Bigger than the highlight z lift, otherwise it will + // be effected by the highlight z when brush. + inBrush.liftZ = 5; + } + }; + /** + * If `areas` is null/undefined, range state remain. + */ + + + BrushModel.prototype.setAreas = function (areas) { + if ("development" !== 'production') { + assert(isArray(areas)); + each(areas, function (area) { + assert(area.brushType, 'Illegal areas'); + }); + } // If areas is null/undefined, range state remain. + // This helps user to dispatchAction({type: 'brush'}) with no areas + // set but just want to get the current brush select info from a `brush` event. + + + if (!areas) { + return; + } + + this.areas = map(areas, function (area) { + return generateBrushOption(this.option, area); + }, this); + }; + /** + * Set the current painting brush option. + */ + + + BrushModel.prototype.setBrushOption = function (brushOption) { + this.brushOption = generateBrushOption(this.option, brushOption); + this.brushType = this.brushOption.brushType; + }; + + BrushModel.type = 'brush'; + BrushModel.dependencies = ['geo', 'grid', 'xAxis', 'yAxis', 'parallel', 'series']; + BrushModel.defaultOption = { + seriesIndex: 'all', + brushType: 'rect', + brushMode: 'single', + transformable: true, + brushStyle: { + borderWidth: 1, + color: 'rgba(210,219,238,0.3)', + borderColor: '#D2DBEE' + }, + throttleType: 'fixRate', + throttleDelay: 0, + removeOnClick: true, + z: 10000 + }; + return BrushModel; + }(ComponentModel); + + function generateBrushOption(option, brushOption) { + return merge({ + brushType: option.brushType, + brushMode: option.brushMode, + transformable: option.transformable, + brushStyle: new Model(option.brushStyle).getItemStyle(), + removeOnClick: option.removeOnClick, + z: option.z + }, brushOption, true); + } + + var ICON_TYPES = ['rect', 'polygon', 'lineX', 'lineY', 'keep', 'clear']; + + var BrushFeature = + /** @class */ + function (_super) { + __extends(BrushFeature, _super); + + function BrushFeature() { + return _super !== null && _super.apply(this, arguments) || this; + } + + BrushFeature.prototype.render = function (featureModel, ecModel, api) { + var brushType; + var brushMode; + var isBrushed; + ecModel.eachComponent({ + mainType: 'brush' + }, function (brushModel) { + brushType = brushModel.brushType; + brushMode = brushModel.brushOption.brushMode || 'single'; + isBrushed = isBrushed || !!brushModel.areas.length; + }); + this._brushType = brushType; + this._brushMode = brushMode; + each(featureModel.get('type', true), function (type) { + featureModel.setIconStatus(type, (type === 'keep' ? brushMode === 'multiple' : type === 'clear' ? isBrushed : type === brushType) ? 'emphasis' : 'normal'); + }); + }; + + BrushFeature.prototype.updateView = function (featureModel, ecModel, api) { + this.render(featureModel, ecModel, api); + }; + + BrushFeature.prototype.getIcons = function () { + var model = this.model; + var availableIcons = model.get('icon', true); + var icons = {}; + each(model.get('type', true), function (type) { + if (availableIcons[type]) { + icons[type] = availableIcons[type]; + } + }); + return icons; + }; + + BrushFeature.prototype.onclick = function (ecModel, api, type) { + var brushType = this._brushType; + var brushMode = this._brushMode; + + if (type === 'clear') { + // Trigger parallel action firstly + api.dispatchAction({ + type: 'axisAreaSelect', + intervals: [] + }); + api.dispatchAction({ + type: 'brush', + command: 'clear', + // Clear all areas of all brush components. + areas: [] + }); + } else { + api.dispatchAction({ + type: 'takeGlobalCursor', + key: 'brush', + brushOption: { + brushType: type === 'keep' ? brushType : brushType === type ? false : type, + brushMode: type === 'keep' ? brushMode === 'multiple' ? 'single' : 'multiple' : brushMode + } + }); + } + }; + + BrushFeature.getDefaultOption = function (ecModel) { + var defaultOption = { + show: true, + type: ICON_TYPES.slice(), + icon: { + /* eslint-disable */ + rect: 'M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13', + polygon: 'M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2', + lineX: 'M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4', + lineY: 'M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4', + keep: 'M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z', + clear: 'M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2' // jshint ignore:line + + /* eslint-enable */ + + }, + // `rect`, `polygon`, `lineX`, `lineY`, `keep`, `clear` + title: ecModel.getLocaleModel().get(['toolbox', 'brush', 'title']) + }; + return defaultOption; + }; + + return BrushFeature; + }(ToolboxFeature); + + function install$B(registers) { + registers.registerComponentView(BrushView); + registers.registerComponentModel(BrushModel); + registers.registerPreprocessor(brushPreprocessor); + registers.registerVisual(registers.PRIORITY.VISUAL.BRUSH, brushVisual); + registers.registerAction({ + type: 'brush', + event: 'brush', + update: 'updateVisual' + }, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'brush', + query: payload + }, function (brushModel) { + brushModel.setAreas(payload.areas); + }); + }); + /** + * payload: { + * brushComponents: [ + * { + * brushId, + * brushIndex, + * brushName, + * series: [ + * { + * seriesId, + * seriesIndex, + * seriesName, + * rawIndices: [21, 34, ...] + * }, + * ... + * ] + * }, + * ... + * ] + * } + */ + + registers.registerAction({ + type: 'brushSelect', + event: 'brushSelected', + update: 'none' + }, noop); + registers.registerAction({ + type: 'brushEnd', + event: 'brushEnd', + update: 'none' + }, noop); + registerFeature('brush', BrushFeature); + } + + var TitleModel = + /** @class */ + function (_super) { + __extends(TitleModel, _super); + + function TitleModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TitleModel.type; + _this.layoutMode = { + type: 'box', + ignoreSize: true + }; + return _this; + } + + TitleModel.type = 'title'; + TitleModel.defaultOption = { + // zlevel: 0, + z: 6, + show: true, + text: '', + target: 'blank', + subtext: '', + subtarget: 'blank', + left: 0, + top: 0, + backgroundColor: 'rgba(0,0,0,0)', + borderColor: '#ccc', + borderWidth: 0, + padding: 5, + itemGap: 10, + textStyle: { + fontSize: 18, + fontWeight: 'bold', + color: '#464646' + }, + subtextStyle: { + fontSize: 12, + color: '#6E7079' + } + }; + return TitleModel; + }(ComponentModel); // View + + + var TitleView = + /** @class */ + function (_super) { + __extends(TitleView, _super); + + function TitleView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TitleView.type; + return _this; + } + + TitleView.prototype.render = function (titleModel, ecModel, api) { + this.group.removeAll(); + + if (!titleModel.get('show')) { + return; + } + + var group = this.group; + var textStyleModel = titleModel.getModel('textStyle'); + var subtextStyleModel = titleModel.getModel('subtextStyle'); + var textAlign = titleModel.get('textAlign'); + var textVerticalAlign = retrieve2(titleModel.get('textBaseline'), titleModel.get('textVerticalAlign')); + var textEl = new ZRText({ + style: createTextStyle(textStyleModel, { + text: titleModel.get('text'), + fill: textStyleModel.getTextColor() + }, { + disableBox: true + }), + z2: 10 + }); + var textRect = textEl.getBoundingRect(); + var subText = titleModel.get('subtext'); + var subTextEl = new ZRText({ + style: createTextStyle(subtextStyleModel, { + text: subText, + fill: subtextStyleModel.getTextColor(), + y: textRect.height + titleModel.get('itemGap'), + verticalAlign: 'top' + }, { + disableBox: true + }), + z2: 10 + }); + var link = titleModel.get('link'); + var sublink = titleModel.get('sublink'); + var triggerEvent = titleModel.get('triggerEvent', true); + textEl.silent = !link && !triggerEvent; + subTextEl.silent = !sublink && !triggerEvent; + + if (link) { + textEl.on('click', function () { + windowOpen(link, '_' + titleModel.get('target')); + }); + } + + if (sublink) { + subTextEl.on('click', function () { + windowOpen(sublink, '_' + titleModel.get('subtarget')); + }); + } + + getECData(textEl).eventData = getECData(subTextEl).eventData = triggerEvent ? { + componentType: 'title', + componentIndex: titleModel.componentIndex + } : null; + group.add(textEl); + subText && group.add(subTextEl); // If no subText, but add subTextEl, there will be an empty line. + + var groupRect = group.getBoundingRect(); + var layoutOption = titleModel.getBoxLayoutParams(); + layoutOption.width = groupRect.width; + layoutOption.height = groupRect.height; + var layoutRect = getLayoutRect(layoutOption, { + width: api.getWidth(), + height: api.getHeight() + }, titleModel.get('padding')); // Adjust text align based on position + + if (!textAlign) { + // Align left if title is on the left. center and right is same + textAlign = titleModel.get('left') || titleModel.get('right'); // @ts-ignore + + if (textAlign === 'middle') { + textAlign = 'center'; + } // Adjust layout by text align + + + if (textAlign === 'right') { + layoutRect.x += layoutRect.width; + } else if (textAlign === 'center') { + layoutRect.x += layoutRect.width / 2; + } + } + + if (!textVerticalAlign) { + textVerticalAlign = titleModel.get('top') || titleModel.get('bottom'); // @ts-ignore + + if (textVerticalAlign === 'center') { + textVerticalAlign = 'middle'; + } + + if (textVerticalAlign === 'bottom') { + layoutRect.y += layoutRect.height; + } else if (textVerticalAlign === 'middle') { + layoutRect.y += layoutRect.height / 2; + } + + textVerticalAlign = textVerticalAlign || 'top'; + } + + group.x = layoutRect.x; + group.y = layoutRect.y; + group.markRedraw(); + var alignStyle = { + align: textAlign, + verticalAlign: textVerticalAlign + }; + textEl.setStyle(alignStyle); + subTextEl.setStyle(alignStyle); // Render background + // Get groupRect again because textAlign has been changed + + groupRect = group.getBoundingRect(); + var padding = layoutRect.margin; + var style = titleModel.getItemStyle(['color', 'opacity']); + style.fill = titleModel.get('backgroundColor'); + var rect = new Rect({ + shape: { + x: groupRect.x - padding[3], + y: groupRect.y - padding[0], + width: groupRect.width + padding[1] + padding[3], + height: groupRect.height + padding[0] + padding[2], + r: titleModel.get('borderRadius') + }, + style: style, + subPixelOptimize: true, + silent: true + }); + group.add(rect); + }; + + TitleView.type = 'title'; + return TitleView; + }(ComponentView); + + function install$C(registers) { + registers.registerComponentModel(TitleModel); + registers.registerComponentView(TitleView); + } + + var TimelineModel = + /** @class */ + function (_super) { + __extends(TimelineModel, _super); + + function TimelineModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TimelineModel.type; + _this.layoutMode = 'box'; + return _this; + } + /** + * @override + */ + + + TimelineModel.prototype.init = function (option, parentModel, ecModel) { + this.mergeDefaultAndTheme(option, ecModel); + + this._initData(); + }; + /** + * @override + */ + + + TimelineModel.prototype.mergeOption = function (option) { + _super.prototype.mergeOption.apply(this, arguments); + + this._initData(); + }; + + TimelineModel.prototype.setCurrentIndex = function (currentIndex) { + if (currentIndex == null) { + currentIndex = this.option.currentIndex; + } + + var count = this._data.count(); + + if (this.option.loop) { + currentIndex = (currentIndex % count + count) % count; + } else { + currentIndex >= count && (currentIndex = count - 1); + currentIndex < 0 && (currentIndex = 0); + } + + this.option.currentIndex = currentIndex; + }; + /** + * @return {number} currentIndex + */ + + + TimelineModel.prototype.getCurrentIndex = function () { + return this.option.currentIndex; + }; + /** + * @return {boolean} + */ + + + TimelineModel.prototype.isIndexMax = function () { + return this.getCurrentIndex() >= this._data.count() - 1; + }; + /** + * @param {boolean} state true: play, false: stop + */ + + + TimelineModel.prototype.setPlayState = function (state) { + this.option.autoPlay = !!state; + }; + /** + * @return {boolean} true: play, false: stop + */ + + + TimelineModel.prototype.getPlayState = function () { + return !!this.option.autoPlay; + }; + /** + * @private + */ + + + TimelineModel.prototype._initData = function () { + var thisOption = this.option; + var dataArr = thisOption.data || []; + var axisType = thisOption.axisType; + var names = this._names = []; + var processedDataArr; + + if (axisType === 'category') { + processedDataArr = []; + each(dataArr, function (item, index) { + var value = convertOptionIdName(getDataItemValue(item), ''); + var newItem; + + if (isObject(item)) { + newItem = clone(item); + newItem.value = index; + } else { + newItem = index; + } + + processedDataArr.push(newItem); + names.push(value); + }); + } else { + processedDataArr = dataArr; + } + + var dimType = { + category: 'ordinal', + time: 'time', + value: 'number' + }[axisType] || 'number'; + var data = this._data = new SeriesData([{ + name: 'value', + type: dimType + }], this); + data.initData(processedDataArr, names); + }; + + TimelineModel.prototype.getData = function () { + return this._data; + }; + /** + * @public + * @return {Array.} categoreis + */ + + + TimelineModel.prototype.getCategories = function () { + if (this.get('axisType') === 'category') { + return this._names.slice(); + } + }; + + TimelineModel.type = 'timeline'; + /** + * @protected + */ + + TimelineModel.defaultOption = { + // zlevel: 0, // 一级层叠 + z: 4, + show: true, + axisType: 'time', + realtime: true, + left: '20%', + top: null, + right: '20%', + bottom: 0, + width: null, + height: 40, + padding: 5, + controlPosition: 'left', + autoPlay: false, + rewind: false, + loop: true, + playInterval: 2000, + currentIndex: 0, + itemStyle: {}, + label: { + color: '#000' + }, + data: [] + }; + return TimelineModel; + }(ComponentModel); + + var SliderTimelineModel = + /** @class */ + function (_super) { + __extends(SliderTimelineModel, _super); + + function SliderTimelineModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SliderTimelineModel.type; + return _this; + } + + SliderTimelineModel.type = 'timeline.slider'; + /** + * @protected + */ + + SliderTimelineModel.defaultOption = inheritDefaultOption(TimelineModel.defaultOption, { + backgroundColor: 'rgba(0,0,0,0)', + borderColor: '#ccc', + borderWidth: 0, + orient: 'horizontal', + inverse: false, + tooltip: { + trigger: 'item' // data item may also have tootip attr. + + }, + symbol: 'circle', + symbolSize: 12, + lineStyle: { + show: true, + width: 2, + color: '#DAE1F5' + }, + label: { + position: 'auto', + // When using number, label position is not + // restricted by viewRect. + // positive: right/bottom, negative: left/top + show: true, + interval: 'auto', + rotate: 0, + // formatter: null, + // 其余属性默认使用全局文本样式,详见TEXTSTYLE + color: '#A4B1D7' + }, + itemStyle: { + color: '#A4B1D7', + borderWidth: 1 + }, + checkpointStyle: { + symbol: 'circle', + symbolSize: 15, + color: '#316bf3', + borderColor: '#fff', + borderWidth: 2, + shadowBlur: 2, + shadowOffsetX: 1, + shadowOffsetY: 1, + shadowColor: 'rgba(0, 0, 0, 0.3)', + // borderColor: 'rgba(194,53,49, 0.5)', + animation: true, + animationDuration: 300, + animationEasing: 'quinticInOut' + }, + controlStyle: { + show: true, + showPlayBtn: true, + showPrevBtn: true, + showNextBtn: true, + itemSize: 24, + itemGap: 12, + position: 'left', + playIcon: 'path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z', + stopIcon: 'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z', + // eslint-disable-next-line max-len + nextIcon: 'M2,18.5A1.52,1.52,0,0,1,.92,18a1.49,1.49,0,0,1,0-2.12L7.81,9.36,1,3.11A1.5,1.5,0,1,1,3,.89l8,7.34a1.48,1.48,0,0,1,.49,1.09,1.51,1.51,0,0,1-.46,1.1L3,18.08A1.5,1.5,0,0,1,2,18.5Z', + // eslint-disable-next-line max-len + prevIcon: 'M10,.5A1.52,1.52,0,0,1,11.08,1a1.49,1.49,0,0,1,0,2.12L4.19,9.64,11,15.89a1.5,1.5,0,1,1-2,2.22L1,10.77A1.48,1.48,0,0,1,.5,9.68,1.51,1.51,0,0,1,1,8.58L9,.92A1.5,1.5,0,0,1,10,.5Z', + prevBtnSize: 18, + nextBtnSize: 18, + color: '#A4B1D7', + borderColor: '#A4B1D7', + borderWidth: 1 + }, + emphasis: { + label: { + show: true, + // 其余属性默认使用全局文本样式,详见TEXTSTYLE + color: '#6f778d' + }, + itemStyle: { + color: '#316BF3' + }, + controlStyle: { + color: '#316BF3', + borderColor: '#316BF3', + borderWidth: 2 + } + }, + progress: { + lineStyle: { + color: '#316BF3' + }, + itemStyle: { + color: '#316BF3' + }, + label: { + color: '#6f778d' + } + }, + data: [] + }); + return SliderTimelineModel; + }(TimelineModel); + + mixin(SliderTimelineModel, DataFormatMixin.prototype); + + var TimelineView = + /** @class */ + function (_super) { + __extends(TimelineView, _super); + + function TimelineView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TimelineView.type; + return _this; + } + + TimelineView.type = 'timeline'; + return TimelineView; + }(ComponentView); + + /** + * Extend axis 2d + */ + + var TimelineAxis = + /** @class */ + function (_super) { + __extends(TimelineAxis, _super); + + function TimelineAxis(dim, scale, coordExtent, axisType) { + var _this = _super.call(this, dim, scale, coordExtent) || this; + + _this.type = axisType || 'value'; + return _this; + } + /** + * @override + */ + + + TimelineAxis.prototype.getLabelModel = function () { + // Force override + return this.model.getModel('label'); + }; + /** + * @override + */ + + + TimelineAxis.prototype.isHorizontal = function () { + return this.model.get('orient') === 'horizontal'; + }; + + return TimelineAxis; + }(Axis); + + var PI$8 = Math.PI; + var labelDataIndexStore = makeInner(); + + var SliderTimelineView = + /** @class */ + function (_super) { + __extends(SliderTimelineView, _super); + + function SliderTimelineView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SliderTimelineView.type; + return _this; + } + + SliderTimelineView.prototype.init = function (ecModel, api) { + this.api = api; + }; + /** + * @override + */ + + + SliderTimelineView.prototype.render = function (timelineModel, ecModel, api) { + this.model = timelineModel; + this.api = api; + this.ecModel = ecModel; + this.group.removeAll(); + + if (timelineModel.get('show', true)) { + var layoutInfo_1 = this._layout(timelineModel, api); + + var mainGroup_1 = this._createGroup('_mainGroup'); + + var labelGroup = this._createGroup('_labelGroup'); + + var axis_1 = this._axis = this._createAxis(layoutInfo_1, timelineModel); + + timelineModel.formatTooltip = function (dataIndex) { + var name = axis_1.scale.getLabel({ + value: dataIndex + }); + return createTooltipMarkup('nameValue', { + noName: true, + value: name + }); + }; + + each(['AxisLine', 'AxisTick', 'Control', 'CurrentPointer'], function (name) { + this['_render' + name](layoutInfo_1, mainGroup_1, axis_1, timelineModel); + }, this); + + this._renderAxisLabel(layoutInfo_1, labelGroup, axis_1, timelineModel); + + this._position(layoutInfo_1, timelineModel); + } + + this._doPlayStop(); + + this._updateTicksStatus(); + }; + /** + * @override + */ + + + SliderTimelineView.prototype.remove = function () { + this._clearTimer(); + + this.group.removeAll(); + }; + /** + * @override + */ + + + SliderTimelineView.prototype.dispose = function () { + this._clearTimer(); + }; + + SliderTimelineView.prototype._layout = function (timelineModel, api) { + var labelPosOpt = timelineModel.get(['label', 'position']); + var orient = timelineModel.get('orient'); + var viewRect = getViewRect$5(timelineModel, api); + var parsedLabelPos; // Auto label offset. + + if (labelPosOpt == null || labelPosOpt === 'auto') { + parsedLabelPos = orient === 'horizontal' ? viewRect.y + viewRect.height / 2 < api.getHeight() / 2 ? '-' : '+' : viewRect.x + viewRect.width / 2 < api.getWidth() / 2 ? '+' : '-'; + } else if (isString(labelPosOpt)) { + parsedLabelPos = { + horizontal: { + top: '-', + bottom: '+' + }, + vertical: { + left: '-', + right: '+' + } + }[orient][labelPosOpt]; + } else { + // is number + parsedLabelPos = labelPosOpt; + } + + var labelAlignMap = { + horizontal: 'center', + vertical: parsedLabelPos >= 0 || parsedLabelPos === '+' ? 'left' : 'right' + }; + var labelBaselineMap = { + horizontal: parsedLabelPos >= 0 || parsedLabelPos === '+' ? 'top' : 'bottom', + vertical: 'middle' + }; + var rotationMap = { + horizontal: 0, + vertical: PI$8 / 2 + }; // Position + + var mainLength = orient === 'vertical' ? viewRect.height : viewRect.width; + var controlModel = timelineModel.getModel('controlStyle'); + var showControl = controlModel.get('show', true); + var controlSize = showControl ? controlModel.get('itemSize') : 0; + var controlGap = showControl ? controlModel.get('itemGap') : 0; + var sizePlusGap = controlSize + controlGap; // Special label rotate. + + var labelRotation = timelineModel.get(['label', 'rotate']) || 0; + labelRotation = labelRotation * PI$8 / 180; // To radian. + + var playPosition; + var prevBtnPosition; + var nextBtnPosition; + var controlPosition = controlModel.get('position', true); + var showPlayBtn = showControl && controlModel.get('showPlayBtn', true); + var showPrevBtn = showControl && controlModel.get('showPrevBtn', true); + var showNextBtn = showControl && controlModel.get('showNextBtn', true); + var xLeft = 0; + var xRight = mainLength; // position[0] means left, position[1] means middle. + + if (controlPosition === 'left' || controlPosition === 'bottom') { + showPlayBtn && (playPosition = [0, 0], xLeft += sizePlusGap); + showPrevBtn && (prevBtnPosition = [xLeft, 0], xLeft += sizePlusGap); + showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap); + } else { + // 'top' 'right' + showPlayBtn && (playPosition = [xRight - controlSize, 0], xRight -= sizePlusGap); + showPrevBtn && (prevBtnPosition = [0, 0], xLeft += sizePlusGap); + showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap); + } + + var axisExtent = [xLeft, xRight]; + + if (timelineModel.get('inverse')) { + axisExtent.reverse(); + } + + return { + viewRect: viewRect, + mainLength: mainLength, + orient: orient, + rotation: rotationMap[orient], + labelRotation: labelRotation, + labelPosOpt: parsedLabelPos, + labelAlign: timelineModel.get(['label', 'align']) || labelAlignMap[orient], + labelBaseline: timelineModel.get(['label', 'verticalAlign']) || timelineModel.get(['label', 'baseline']) || labelBaselineMap[orient], + // Based on mainGroup. + playPosition: playPosition, + prevBtnPosition: prevBtnPosition, + nextBtnPosition: nextBtnPosition, + axisExtent: axisExtent, + controlSize: controlSize, + controlGap: controlGap + }; + }; + + SliderTimelineView.prototype._position = function (layoutInfo, timelineModel) { + // Position is be called finally, because bounding rect is needed for + // adapt content to fill viewRect (auto adapt offset). + // Timeline may be not all in the viewRect when 'offset' is specified + // as a number, because it is more appropriate that label aligns at + // 'offset' but not the other edge defined by viewRect. + var mainGroup = this._mainGroup; + var labelGroup = this._labelGroup; + var viewRect = layoutInfo.viewRect; + + if (layoutInfo.orient === 'vertical') { + // transform to horizontal, inverse rotate by left-top point. + var m = create$1(); + var rotateOriginX = viewRect.x; + var rotateOriginY = viewRect.y + viewRect.height; + translate(m, m, [-rotateOriginX, -rotateOriginY]); + rotate(m, m, -PI$8 / 2); + translate(m, m, [rotateOriginX, rotateOriginY]); + viewRect = viewRect.clone(); + viewRect.applyTransform(m); + } + + var viewBound = getBound(viewRect); + var mainBound = getBound(mainGroup.getBoundingRect()); + var labelBound = getBound(labelGroup.getBoundingRect()); + var mainPosition = [mainGroup.x, mainGroup.y]; + var labelsPosition = [labelGroup.x, labelGroup.y]; + labelsPosition[0] = mainPosition[0] = viewBound[0][0]; + var labelPosOpt = layoutInfo.labelPosOpt; + + if (labelPosOpt == null || isString(labelPosOpt)) { + // '+' or '-' + var mainBoundIdx = labelPosOpt === '+' ? 0 : 1; + toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx); + toBound(labelsPosition, labelBound, viewBound, 1, 1 - mainBoundIdx); + } else { + var mainBoundIdx = labelPosOpt >= 0 ? 0 : 1; + toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx); + labelsPosition[1] = mainPosition[1] + labelPosOpt; + } + + mainGroup.setPosition(mainPosition); + labelGroup.setPosition(labelsPosition); + mainGroup.rotation = labelGroup.rotation = layoutInfo.rotation; + setOrigin(mainGroup); + setOrigin(labelGroup); + + function setOrigin(targetGroup) { + targetGroup.originX = viewBound[0][0] - targetGroup.x; + targetGroup.originY = viewBound[1][0] - targetGroup.y; + } + + function getBound(rect) { + // [[xmin, xmax], [ymin, ymax]] + return [[rect.x, rect.x + rect.width], [rect.y, rect.y + rect.height]]; + } + + function toBound(fromPos, from, to, dimIdx, boundIdx) { + fromPos[dimIdx] += to[dimIdx][boundIdx] - from[dimIdx][boundIdx]; + } + }; + + SliderTimelineView.prototype._createAxis = function (layoutInfo, timelineModel) { + var data = timelineModel.getData(); + var axisType = timelineModel.get('axisType'); + var scale = createScaleByModel$1(timelineModel, axisType); // Customize scale. The `tickValue` is `dataIndex`. + + scale.getTicks = function () { + return data.mapArray(['value'], function (value) { + return { + value: value + }; + }); + }; + + var dataExtent = data.getDataExtent('value'); + scale.setExtent(dataExtent[0], dataExtent[1]); + scale.calcNiceTicks(); + var axis = new TimelineAxis('value', scale, layoutInfo.axisExtent, axisType); + axis.model = timelineModel; + return axis; + }; + + SliderTimelineView.prototype._createGroup = function (key) { + var newGroup = this[key] = new Group(); + this.group.add(newGroup); + return newGroup; + }; + + SliderTimelineView.prototype._renderAxisLine = function (layoutInfo, group, axis, timelineModel) { + var axisExtent = axis.getExtent(); + + if (!timelineModel.get(['lineStyle', 'show'])) { + return; + } + + var line = new Line({ + shape: { + x1: axisExtent[0], + y1: 0, + x2: axisExtent[1], + y2: 0 + }, + style: extend({ + lineCap: 'round' + }, timelineModel.getModel('lineStyle').getLineStyle()), + silent: true, + z2: 1 + }); + group.add(line); + var progressLine = this._progressLine = new Line({ + shape: { + x1: axisExtent[0], + x2: this._currentPointer ? this._currentPointer.x : axisExtent[0], + y1: 0, + y2: 0 + }, + style: defaults({ + lineCap: 'round', + lineWidth: line.style.lineWidth + }, timelineModel.getModel(['progress', 'lineStyle']).getLineStyle()), + silent: true, + z2: 1 + }); + group.add(progressLine); + }; + + SliderTimelineView.prototype._renderAxisTick = function (layoutInfo, group, axis, timelineModel) { + var _this = this; + + var data = timelineModel.getData(); // Show all ticks, despite ignoring strategy. + + var ticks = axis.scale.getTicks(); + this._tickSymbols = []; // The value is dataIndex, see the costomized scale. + + each(ticks, function (tick) { + var tickCoord = axis.dataToCoord(tick.value); + var itemModel = data.getItemModel(tick.value); + var itemStyleModel = itemModel.getModel('itemStyle'); + var hoverStyleModel = itemModel.getModel(['emphasis', 'itemStyle']); + var progressStyleModel = itemModel.getModel(['progress', 'itemStyle']); + var symbolOpt = { + x: tickCoord, + y: 0, + onclick: bind(_this._changeTimeline, _this, tick.value) + }; + var el = giveSymbol(itemModel, itemStyleModel, group, symbolOpt); + el.ensureState('emphasis').style = hoverStyleModel.getItemStyle(); + el.ensureState('progress').style = progressStyleModel.getItemStyle(); + enableHoverEmphasis(el); + var ecData = getECData(el); + + if (itemModel.get('tooltip')) { + ecData.dataIndex = tick.value; + ecData.dataModel = timelineModel; + } else { + ecData.dataIndex = ecData.dataModel = null; + } + + _this._tickSymbols.push(el); + }); + }; + + SliderTimelineView.prototype._renderAxisLabel = function (layoutInfo, group, axis, timelineModel) { + var _this = this; + + var labelModel = axis.getLabelModel(); + + if (!labelModel.get('show')) { + return; + } + + var data = timelineModel.getData(); + var labels = axis.getViewLabels(); + this._tickLabels = []; + each(labels, function (labelItem) { + // The tickValue is dataIndex, see the costomized scale. + var dataIndex = labelItem.tickValue; + var itemModel = data.getItemModel(dataIndex); + var normalLabelModel = itemModel.getModel('label'); + var hoverLabelModel = itemModel.getModel(['emphasis', 'label']); + var progressLabelModel = itemModel.getModel(['progress', 'label']); + var tickCoord = axis.dataToCoord(labelItem.tickValue); + var textEl = new ZRText({ + x: tickCoord, + y: 0, + rotation: layoutInfo.labelRotation - layoutInfo.rotation, + onclick: bind(_this._changeTimeline, _this, dataIndex), + silent: false, + style: createTextStyle(normalLabelModel, { + text: labelItem.formattedLabel, + align: layoutInfo.labelAlign, + verticalAlign: layoutInfo.labelBaseline + }) + }); + textEl.ensureState('emphasis').style = createTextStyle(hoverLabelModel); + textEl.ensureState('progress').style = createTextStyle(progressLabelModel); + group.add(textEl); + enableHoverEmphasis(textEl); + labelDataIndexStore(textEl).dataIndex = dataIndex; + + _this._tickLabels.push(textEl); + }); + }; + + SliderTimelineView.prototype._renderControl = function (layoutInfo, group, axis, timelineModel) { + var controlSize = layoutInfo.controlSize; + var rotation = layoutInfo.rotation; + var itemStyle = timelineModel.getModel('controlStyle').getItemStyle(); + var hoverStyle = timelineModel.getModel(['emphasis', 'controlStyle']).getItemStyle(); + var playState = timelineModel.getPlayState(); + var inverse = timelineModel.get('inverse', true); + makeBtn(layoutInfo.nextBtnPosition, 'next', bind(this._changeTimeline, this, inverse ? '-' : '+')); + makeBtn(layoutInfo.prevBtnPosition, 'prev', bind(this._changeTimeline, this, inverse ? '+' : '-')); + makeBtn(layoutInfo.playPosition, playState ? 'stop' : 'play', bind(this._handlePlayClick, this, !playState), true); + + function makeBtn(position, iconName, onclick, willRotate) { + if (!position) { + return; + } + + var iconSize = parsePercent(retrieve2(timelineModel.get(['controlStyle', iconName + 'BtnSize']), controlSize), controlSize); + var rect = [0, -iconSize / 2, iconSize, iconSize]; + var btn = makeControlIcon(timelineModel, iconName + 'Icon', rect, { + x: position[0], + y: position[1], + originX: controlSize / 2, + originY: 0, + rotation: willRotate ? -rotation : 0, + rectHover: true, + style: itemStyle, + onclick: onclick + }); + btn.ensureState('emphasis').style = hoverStyle; + group.add(btn); + enableHoverEmphasis(btn); + } + }; + + SliderTimelineView.prototype._renderCurrentPointer = function (layoutInfo, group, axis, timelineModel) { + var data = timelineModel.getData(); + var currentIndex = timelineModel.getCurrentIndex(); + var pointerModel = data.getItemModel(currentIndex).getModel('checkpointStyle'); + var me = this; + var callback = { + onCreate: function (pointer) { + pointer.draggable = true; + pointer.drift = bind(me._handlePointerDrag, me); + pointer.ondragend = bind(me._handlePointerDragend, me); + pointerMoveTo(pointer, me._progressLine, currentIndex, axis, timelineModel, true); + }, + onUpdate: function (pointer) { + pointerMoveTo(pointer, me._progressLine, currentIndex, axis, timelineModel); + } + }; // Reuse when exists, for animation and drag. + + this._currentPointer = giveSymbol(pointerModel, pointerModel, this._mainGroup, {}, this._currentPointer, callback); + }; + + SliderTimelineView.prototype._handlePlayClick = function (nextState) { + this._clearTimer(); + + this.api.dispatchAction({ + type: 'timelinePlayChange', + playState: nextState, + from: this.uid + }); + }; + + SliderTimelineView.prototype._handlePointerDrag = function (dx, dy, e) { + this._clearTimer(); + + this._pointerChangeTimeline([e.offsetX, e.offsetY]); + }; + + SliderTimelineView.prototype._handlePointerDragend = function (e) { + this._pointerChangeTimeline([e.offsetX, e.offsetY], true); + }; + + SliderTimelineView.prototype._pointerChangeTimeline = function (mousePos, trigger) { + var toCoord = this._toAxisCoord(mousePos)[0]; + + var axis = this._axis; + var axisExtent = asc(axis.getExtent().slice()); + toCoord > axisExtent[1] && (toCoord = axisExtent[1]); + toCoord < axisExtent[0] && (toCoord = axisExtent[0]); + this._currentPointer.x = toCoord; + + this._currentPointer.markRedraw(); + + this._progressLine.shape.x2 = toCoord; + + this._progressLine.dirty(); + + var targetDataIndex = this._findNearestTick(toCoord); + + var timelineModel = this.model; + + if (trigger || targetDataIndex !== timelineModel.getCurrentIndex() && timelineModel.get('realtime')) { + this._changeTimeline(targetDataIndex); + } + }; + + SliderTimelineView.prototype._doPlayStop = function () { + var _this = this; + + this._clearTimer(); + + if (this.model.getPlayState()) { + this._timer = setTimeout(function () { + // Do not cache + var timelineModel = _this.model; + + _this._changeTimeline(timelineModel.getCurrentIndex() + (timelineModel.get('rewind', true) ? -1 : 1)); + }, this.model.get('playInterval')); + } + }; + + SliderTimelineView.prototype._toAxisCoord = function (vertex) { + var trans = this._mainGroup.getLocalTransform(); + + return applyTransform$1(vertex, trans, true); + }; + + SliderTimelineView.prototype._findNearestTick = function (axisCoord) { + var data = this.model.getData(); + var dist = Infinity; + var targetDataIndex; + var axis = this._axis; + data.each(['value'], function (value, dataIndex) { + var coord = axis.dataToCoord(value); + var d = Math.abs(coord - axisCoord); + + if (d < dist) { + dist = d; + targetDataIndex = dataIndex; + } + }); + return targetDataIndex; + }; + + SliderTimelineView.prototype._clearTimer = function () { + if (this._timer) { + clearTimeout(this._timer); + this._timer = null; + } + }; + + SliderTimelineView.prototype._changeTimeline = function (nextIndex) { + var currentIndex = this.model.getCurrentIndex(); + + if (nextIndex === '+') { + nextIndex = currentIndex + 1; + } else if (nextIndex === '-') { + nextIndex = currentIndex - 1; + } + + this.api.dispatchAction({ + type: 'timelineChange', + currentIndex: nextIndex, + from: this.uid + }); + }; + + SliderTimelineView.prototype._updateTicksStatus = function () { + var currentIndex = this.model.getCurrentIndex(); + var tickSymbols = this._tickSymbols; + var tickLabels = this._tickLabels; + + if (tickSymbols) { + for (var i = 0; i < tickSymbols.length; i++) { + tickSymbols && tickSymbols[i] && tickSymbols[i].toggleState('progress', i < currentIndex); + } + } + + if (tickLabels) { + for (var i = 0; i < tickLabels.length; i++) { + tickLabels && tickLabels[i] && tickLabels[i].toggleState('progress', labelDataIndexStore(tickLabels[i]).dataIndex <= currentIndex); + } + } + }; + + SliderTimelineView.type = 'timeline.slider'; + return SliderTimelineView; + }(TimelineView); + + function createScaleByModel$1(model, axisType) { + axisType = axisType || model.get('type'); + + if (axisType) { + switch (axisType) { + // Buildin scale + case 'category': + return new OrdinalScale({ + ordinalMeta: model.getCategories(), + extent: [Infinity, -Infinity] + }); + + case 'time': + return new TimeScale({ + locale: model.ecModel.getLocaleModel(), + useUTC: model.ecModel.get('useUTC') + }); + + default: + // default to be value + return new IntervalScale(); + } + } + } + + function getViewRect$5(model, api) { + return getLayoutRect(model.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }, model.get('padding')); + } + + function makeControlIcon(timelineModel, objPath, rect, opts) { + var style = opts.style; + var icon = createIcon(timelineModel.get(['controlStyle', objPath]), opts || {}, new BoundingRect(rect[0], rect[1], rect[2], rect[3])); // TODO createIcon won't use style in opt. + + if (style) { + icon.setStyle(style); + } + + return icon; + } + /** + * Create symbol or update symbol + * opt: basic position and event handlers + */ + + + function giveSymbol(hostModel, itemStyleModel, group, opt, symbol, callback) { + var color = itemStyleModel.get('color'); + + if (!symbol) { + var symbolType = hostModel.get('symbol'); + symbol = createSymbol(symbolType, -1, -1, 2, 2, color); + symbol.setStyle('strokeNoScale', true); + group.add(symbol); + callback && callback.onCreate(symbol); + } else { + symbol.setColor(color); + group.add(symbol); // Group may be new, also need to add. + + callback && callback.onUpdate(symbol); + } // Style + + + var itemStyle = itemStyleModel.getItemStyle(['color']); + symbol.setStyle(itemStyle); // Transform and events. + + opt = merge({ + rectHover: true, + z2: 100 + }, opt, true); + var symbolSize = normalizeSymbolSize(hostModel.get('symbolSize')); + opt.scaleX = symbolSize[0] / 2; + opt.scaleY = symbolSize[1] / 2; + var symbolOffset = normalizeSymbolOffset(hostModel.get('symbolOffset'), symbolSize); + + if (symbolOffset) { + opt.x = (opt.x || 0) + symbolOffset[0]; + opt.y = (opt.y || 0) + symbolOffset[1]; + } + + var symbolRotate = hostModel.get('symbolRotate'); + opt.rotation = (symbolRotate || 0) * Math.PI / 180 || 0; + symbol.attr(opt); // FIXME + // (1) When symbol.style.strokeNoScale is true and updateTransform is not performed, + // getBoundingRect will return wrong result. + // (This is supposed to be resolved in zrender, but it is a little difficult to + // leverage performance and auto updateTransform) + // (2) All of ancesters of symbol do not scale, so we can just updateTransform symbol. + + symbol.updateTransform(); + return symbol; + } + + function pointerMoveTo(pointer, progressLine, dataIndex, axis, timelineModel, noAnimation) { + if (pointer.dragging) { + return; + } + + var pointerModel = timelineModel.getModel('checkpointStyle'); + var toCoord = axis.dataToCoord(timelineModel.getData().get('value', dataIndex)); + + if (noAnimation || !pointerModel.get('animation', true)) { + pointer.attr({ + x: toCoord, + y: 0 + }); + progressLine && progressLine.attr({ + shape: { + x2: toCoord + } + }); + } else { + var animationCfg = { + duration: pointerModel.get('animationDuration', true), + easing: pointerModel.get('animationEasing', true) + }; + pointer.stopAnimation(null, true); + pointer.animateTo({ + x: toCoord, + y: 0 + }, animationCfg); + progressLine && progressLine.animateTo({ + shape: { + x2: toCoord + } + }, animationCfg); + } + } + + function installTimelineAction(registers) { + registers.registerAction({ + type: 'timelineChange', + event: 'timelineChanged', + update: 'prepareAndUpdate' + }, function (payload, ecModel, api) { + var timelineModel = ecModel.getComponent('timeline'); + + if (timelineModel && payload.currentIndex != null) { + timelineModel.setCurrentIndex(payload.currentIndex); + + if (!timelineModel.get('loop', true) && timelineModel.isIndexMax() && timelineModel.getPlayState()) { + timelineModel.setPlayState(false); // The timeline has played to the end, trigger event + + api.dispatchAction({ + type: 'timelinePlayChange', + playState: false, + from: payload.from + }); + } + } // Set normalized currentIndex to payload. + + + ecModel.resetOption('timeline', { + replaceMerge: timelineModel.get('replaceMerge', true) + }); + return defaults({ + currentIndex: timelineModel.option.currentIndex + }, payload); + }); + registers.registerAction({ + type: 'timelinePlayChange', + event: 'timelinePlayChanged', + update: 'update' + }, function (payload, ecModel) { + var timelineModel = ecModel.getComponent('timeline'); + + if (timelineModel && payload.playState != null) { + timelineModel.setPlayState(payload.playState); + } + }); + } + + function timelinePreprocessor(option) { + var timelineOpt = option && option.timeline; + + if (!isArray(timelineOpt)) { + timelineOpt = timelineOpt ? [timelineOpt] : []; + } + + each(timelineOpt, function (opt) { + if (!opt) { + return; + } + + compatibleEC2(opt); + }); + } + + function compatibleEC2(opt) { + var type = opt.type; + var ec2Types = { + 'number': 'value', + 'time': 'time' + }; // Compatible with ec2 + + if (ec2Types[type]) { + opt.axisType = ec2Types[type]; + delete opt.type; + } + + transferItem(opt); + + if (has(opt, 'controlPosition')) { + var controlStyle = opt.controlStyle || (opt.controlStyle = {}); + + if (!has(controlStyle, 'position')) { + controlStyle.position = opt.controlPosition; + } + + if (controlStyle.position === 'none' && !has(controlStyle, 'show')) { + controlStyle.show = false; + delete controlStyle.position; + } + + delete opt.controlPosition; + } + + each(opt.data || [], function (dataItem) { + if (isObject(dataItem) && !isArray(dataItem)) { + if (!has(dataItem, 'value') && has(dataItem, 'name')) { + // In ec2, using name as value. + dataItem.value = dataItem.name; + } + + transferItem(dataItem); + } + }); + } + + function transferItem(opt) { + var itemStyle = opt.itemStyle || (opt.itemStyle = {}); + var itemStyleEmphasis = itemStyle.emphasis || (itemStyle.emphasis = {}); // Transfer label out + + var label = opt.label || opt.label || {}; + var labelNormal = label.normal || (label.normal = {}); + var excludeLabelAttr = { + normal: 1, + emphasis: 1 + }; + each(label, function (value, name) { + if (!excludeLabelAttr[name] && !has(labelNormal, name)) { + labelNormal[name] = value; + } + }); + + if (itemStyleEmphasis.label && !has(label, 'emphasis')) { + label.emphasis = itemStyleEmphasis.label; + delete itemStyleEmphasis.label; + } + } + + function has(obj, attr) { + return obj.hasOwnProperty(attr); + } + + function install$D(registers) { + registers.registerComponentModel(SliderTimelineModel); + registers.registerComponentView(SliderTimelineView); + registers.registerSubTypeDefaulter('timeline', function () { + // Only slider now. + return 'slider'; + }); + installTimelineAction(registers); + registers.registerPreprocessor(timelinePreprocessor); + } + + function checkMarkerInSeries(seriesOpts, markerType) { + if (!seriesOpts) { + return false; + } + + var seriesOptArr = isArray(seriesOpts) ? seriesOpts : [seriesOpts]; + + for (var idx = 0; idx < seriesOptArr.length; idx++) { + if (seriesOptArr[idx] && seriesOptArr[idx][markerType]) { + return true; + } + } + + return false; + } + + function fillLabel(opt) { + defaultEmphasis(opt, 'label', ['show']); + } // { [componentType]: MarkerModel } + + + var inner$g = makeInner(); + + var MarkerModel = + /** @class */ + function (_super) { + __extends(MarkerModel, _super); + + function MarkerModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkerModel.type; + /** + * If marker model is created by self from series + */ + + _this.createdBySelf = false; + return _this; + } + /** + * @overrite + */ + + + MarkerModel.prototype.init = function (option, parentModel, ecModel) { + if ("development" !== 'production') { + if (this.type === 'marker') { + throw new Error('Marker component is abstract component. Use markLine, markPoint, markArea instead.'); + } + } + + this.mergeDefaultAndTheme(option, ecModel); + + this._mergeOption(option, ecModel, false, true); + }; + + MarkerModel.prototype.isAnimationEnabled = function () { + if (env.node) { + return false; + } + + var hostSeries = this.__hostSeries; + return this.getShallow('animation') && hostSeries && hostSeries.isAnimationEnabled(); + }; + /** + * @overrite + */ + + + MarkerModel.prototype.mergeOption = function (newOpt, ecModel) { + this._mergeOption(newOpt, ecModel, false, false); + }; + + MarkerModel.prototype._mergeOption = function (newOpt, ecModel, createdBySelf, isInit) { + var componentType = this.mainType; + + if (!createdBySelf) { + ecModel.eachSeries(function (seriesModel) { + // mainType can be markPoint, markLine, markArea + var markerOpt = seriesModel.get(this.mainType, true); + var markerModel = inner$g(seriesModel)[componentType]; + + if (!markerOpt || !markerOpt.data) { + inner$g(seriesModel)[componentType] = null; + return; + } + + if (!markerModel) { + if (isInit) { + // Default label emphasis `position` and `show` + fillLabel(markerOpt); + } + + each(markerOpt.data, function (item) { + // FIXME Overwrite fillLabel method ? + if (item instanceof Array) { + fillLabel(item[0]); + fillLabel(item[1]); + } else { + fillLabel(item); + } + }); + markerModel = this.createMarkerModelFromSeries(markerOpt, this, ecModel); // markerModel = new ImplementedMarkerModel( + // markerOpt, this, ecModel + // ); + + extend(markerModel, { + mainType: this.mainType, + // Use the same series index and name + seriesIndex: seriesModel.seriesIndex, + name: seriesModel.name, + createdBySelf: true + }); + markerModel.__hostSeries = seriesModel; + } else { + markerModel._mergeOption(markerOpt, ecModel, true); + } + + inner$g(seriesModel)[componentType] = markerModel; + }, this); + } + }; + + MarkerModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var data = this.getData(); + var value = this.getRawValue(dataIndex); + var itemName = data.getName(dataIndex); + return createTooltipMarkup('section', { + header: this.name, + blocks: [createTooltipMarkup('nameValue', { + name: itemName, + value: value, + noName: !itemName, + noValue: value == null + })] + }); + }; + + MarkerModel.prototype.getData = function () { + return this._data; + }; + + MarkerModel.prototype.setData = function (data) { + this._data = data; + }; + + MarkerModel.getMarkerModelFromSeries = function (seriesModel, // Support three types of markers. Strict check. + componentType) { + return inner$g(seriesModel)[componentType]; + }; + + MarkerModel.type = 'marker'; + MarkerModel.dependencies = ['series', 'grid', 'polar', 'geo']; + return MarkerModel; + }(ComponentModel); + + mixin(MarkerModel, DataFormatMixin.prototype); + + var MarkPointModel = + /** @class */ + function (_super) { + __extends(MarkPointModel, _super); + + function MarkPointModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkPointModel.type; + return _this; + } + + MarkPointModel.prototype.createMarkerModelFromSeries = function (markerOpt, masterMarkerModel, ecModel) { + return new MarkPointModel(markerOpt, masterMarkerModel, ecModel); + }; + + MarkPointModel.type = 'markPoint'; + MarkPointModel.defaultOption = { + // zlevel: 0, + z: 5, + symbol: 'pin', + symbolSize: 50, + //symbolRotate: 0, + //symbolOffset: [0, 0] + tooltip: { + trigger: 'item' + }, + label: { + show: true, + position: 'inside' + }, + itemStyle: { + borderWidth: 2 + }, + emphasis: { + label: { + show: true + } + } + }; + return MarkPointModel; + }(MarkerModel); + + function hasXOrY(item) { + return !(isNaN(parseFloat(item.x)) && isNaN(parseFloat(item.y))); + } + + function hasXAndY(item) { + return !isNaN(parseFloat(item.x)) && !isNaN(parseFloat(item.y)); + } + + function markerTypeCalculatorWithExtent(markerType, data, otherDataDim, targetDataDim, otherCoordIndex, targetCoordIndex) { + var coordArr = []; + var stacked = isDimensionStacked(data, targetDataDim + /*, otherDataDim*/ + ); + var calcDataDim = stacked ? data.getCalculationInfo('stackResultDimension') : targetDataDim; + var value = numCalculate(data, calcDataDim, markerType); + var dataIndex = data.indicesOfNearest(calcDataDim, value)[0]; + coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex); + coordArr[targetCoordIndex] = data.get(calcDataDim, dataIndex); + var coordArrValue = data.get(targetDataDim, dataIndex); // Make it simple, do not visit all stacked value to count precision. + + var precision = getPrecision(data.get(targetDataDim, dataIndex)); + precision = Math.min(precision, 20); + + if (precision >= 0) { + coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision); + } + + return [coordArr, coordArrValue]; + } // TODO Specified percent + + + var markerTypeCalculator = { + min: curry(markerTypeCalculatorWithExtent, 'min'), + max: curry(markerTypeCalculatorWithExtent, 'max'), + average: curry(markerTypeCalculatorWithExtent, 'average'), + median: curry(markerTypeCalculatorWithExtent, 'median') + }; + /** + * Transform markPoint data item to format used in List by do the following + * 1. Calculate statistic like `max`, `min`, `average` + * 2. Convert `item.xAxis`, `item.yAxis` to `item.coord` array + */ + + function dataTransform(seriesModel, item) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; // 1. If not specify the position with pixel directly + // 2. If `coord` is not a data array. Which uses `xAxis`, + // `yAxis` to specify the coord on each dimension + // parseFloat first because item.x and item.y can be percent string like '20%' + + if (item && !hasXAndY(item) && !isArray(item.coord) && coordSys) { + var dims = coordSys.dimensions; + var axisInfo = getAxisInfo$1(item, data, coordSys, seriesModel); // Clone the option + // Transform the properties xAxis, yAxis, radiusAxis, angleAxis, geoCoord to value + + item = clone(item); + + if (item.type && markerTypeCalculator[item.type] && axisInfo.baseAxis && axisInfo.valueAxis) { + var otherCoordIndex = indexOf(dims, axisInfo.baseAxis.dim); + var targetCoordIndex = indexOf(dims, axisInfo.valueAxis.dim); + var coordInfo = markerTypeCalculator[item.type](data, axisInfo.baseDataDim, axisInfo.valueDataDim, otherCoordIndex, targetCoordIndex); + item.coord = coordInfo[0]; // Force to use the value of calculated value. + // let item use the value without stack. + + item.value = coordInfo[1]; + } else { + // FIXME Only has one of xAxis and yAxis. + var coord = [item.xAxis != null ? item.xAxis : item.radiusAxis, item.yAxis != null ? item.yAxis : item.angleAxis]; // Each coord support max, min, average + + for (var i = 0; i < 2; i++) { + if (markerTypeCalculator[coord[i]]) { + coord[i] = numCalculate(data, data.mapDimension(dims[i]), coord[i]); + } + } + + item.coord = coord; + } + } + + return item; + } + function getAxisInfo$1(item, data, coordSys, seriesModel) { + var ret = {}; + + if (item.valueIndex != null || item.valueDim != null) { + ret.valueDataDim = item.valueIndex != null ? data.getDimension(item.valueIndex) : item.valueDim; + ret.valueAxis = coordSys.getAxis(dataDimToCoordDim(seriesModel, ret.valueDataDim)); + ret.baseAxis = coordSys.getOtherAxis(ret.valueAxis); + ret.baseDataDim = data.mapDimension(ret.baseAxis.dim); + } else { + ret.baseAxis = seriesModel.getBaseAxis(); + ret.valueAxis = coordSys.getOtherAxis(ret.baseAxis); + ret.baseDataDim = data.mapDimension(ret.baseAxis.dim); + ret.valueDataDim = data.mapDimension(ret.valueAxis.dim); + } + + return ret; + } + + function dataDimToCoordDim(seriesModel, dataDim) { + var dimItem = seriesModel.getData().getDimensionInfo(dataDim); + return dimItem && dimItem.coordDim; + } + /** + * Filter data which is out of coordinateSystem range + * [dataFilter description] + */ + + + function dataFilter$1( // Currently only polar and cartesian has containData. + coordSys, item) { + // Alwalys return true if there is no coordSys + return coordSys && coordSys.containData && item.coord && !hasXOrY(item) ? coordSys.containData(item.coord) : true; + } + function createMarkerDimValueGetter(inCoordSys, dims) { + return inCoordSys ? function (item, dimName, dataIndex, dimIndex) { + var rawVal = dimIndex < 2 // x, y, radius, angle + ? item.coord && item.coord[dimIndex] : item.value; + return parseDataValue(rawVal, dims[dimIndex]); + } : function (item, dimName, dataIndex, dimIndex) { + return parseDataValue(item.value, dims[dimIndex]); + }; + } + function numCalculate(data, valueDataDim, type) { + if (type === 'average') { + var sum_1 = 0; + var count_1 = 0; + data.each(valueDataDim, function (val, idx) { + if (!isNaN(val)) { + sum_1 += val; + count_1++; + } + }); + return sum_1 / count_1; + } else if (type === 'median') { + return data.getMedian(valueDataDim); + } else { + // max & min + return data.getDataExtent(valueDataDim)[type === 'max' ? 1 : 0]; + } + } + + var inner$h = makeInner(); + + var MarkerView = + /** @class */ + function (_super) { + __extends(MarkerView, _super); + + function MarkerView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkerView.type; + return _this; + } + + MarkerView.prototype.init = function () { + this.markerGroupMap = createHashMap(); + }; + + MarkerView.prototype.render = function (markerModel, ecModel, api) { + var _this = this; + + var markerGroupMap = this.markerGroupMap; + markerGroupMap.each(function (item) { + inner$h(item).keep = false; + }); + ecModel.eachSeries(function (seriesModel) { + var markerModel = MarkerModel.getMarkerModelFromSeries(seriesModel, _this.type); + markerModel && _this.renderSeries(seriesModel, markerModel, ecModel, api); + }); + markerGroupMap.each(function (item) { + !inner$h(item).keep && _this.group.remove(item.group); + }); + }; + + MarkerView.prototype.markKeep = function (drawGroup) { + inner$h(drawGroup).keep = true; + }; + + MarkerView.prototype.toggleBlurSeries = function (seriesModelList, isBlur) { + var _this = this; + + each(seriesModelList, function (seriesModel) { + var markerModel = MarkerModel.getMarkerModelFromSeries(seriesModel, _this.type); + + if (markerModel) { + var data = markerModel.getData(); + data.eachItemGraphicEl(function (el) { + if (el) { + isBlur ? enterBlur(el) : leaveBlur(el); + } + }); + } + }); + }; + + MarkerView.type = 'marker'; + return MarkerView; + }(ComponentView); + + function updateMarkerLayout(mpData, seriesModel, api) { + var coordSys = seriesModel.coordinateSystem; + mpData.each(function (idx) { + var itemModel = mpData.getItemModel(idx); + var point; + var xPx = parsePercent$1(itemModel.get('x'), api.getWidth()); + var yPx = parsePercent$1(itemModel.get('y'), api.getHeight()); + + if (!isNaN(xPx) && !isNaN(yPx)) { + point = [xPx, yPx]; + } // Chart like bar may have there own marker positioning logic + else if (seriesModel.getMarkerPosition) { + // Use the getMarkerPoisition + point = seriesModel.getMarkerPosition(mpData.getValues(mpData.dimensions, idx)); + } else if (coordSys) { + var x = mpData.get(coordSys.dimensions[0], idx); + var y = mpData.get(coordSys.dimensions[1], idx); + point = coordSys.dataToPoint([x, y]); + } // Use x, y if has any + + + if (!isNaN(xPx)) { + point[0] = xPx; + } + + if (!isNaN(yPx)) { + point[1] = yPx; + } + + mpData.setItemLayout(idx, point); + }); + } + + var MarkPointView = + /** @class */ + function (_super) { + __extends(MarkPointView, _super); + + function MarkPointView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkPointView.type; + return _this; + } + + MarkPointView.prototype.updateTransform = function (markPointModel, ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + var mpModel = MarkerModel.getMarkerModelFromSeries(seriesModel, 'markPoint'); + + if (mpModel) { + updateMarkerLayout(mpModel.getData(), seriesModel, api); + this.markerGroupMap.get(seriesModel.id).updateLayout(); + } + }, this); + }; + + MarkPointView.prototype.renderSeries = function (seriesModel, mpModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var seriesId = seriesModel.id; + var seriesData = seriesModel.getData(); + var symbolDrawMap = this.markerGroupMap; + var symbolDraw = symbolDrawMap.get(seriesId) || symbolDrawMap.set(seriesId, new SymbolDraw()); + var mpData = createData(coordSys, seriesModel, mpModel); // FIXME + + mpModel.setData(mpData); + updateMarkerLayout(mpModel.getData(), seriesModel, api); + mpData.each(function (idx) { + var itemModel = mpData.getItemModel(idx); + var symbol = itemModel.getShallow('symbol'); + var symbolSize = itemModel.getShallow('symbolSize'); + var symbolRotate = itemModel.getShallow('symbolRotate'); + var symbolOffset = itemModel.getShallow('symbolOffset'); + var symbolKeepAspect = itemModel.getShallow('symbolKeepAspect'); // TODO: refactor needed: single data item should not support callback function + + if (isFunction(symbol) || isFunction(symbolSize) || isFunction(symbolRotate) || isFunction(symbolOffset)) { + var rawIdx = mpModel.getRawValue(idx); + var dataParams = mpModel.getDataParams(idx); + + if (isFunction(symbol)) { + symbol = symbol(rawIdx, dataParams); + } + + if (isFunction(symbolSize)) { + // FIXME 这里不兼容 ECharts 2.x,2.x 貌似参数是整个数据? + symbolSize = symbolSize(rawIdx, dataParams); + } + + if (isFunction(symbolRotate)) { + symbolRotate = symbolRotate(rawIdx, dataParams); + } + + if (isFunction(symbolOffset)) { + symbolOffset = symbolOffset(rawIdx, dataParams); + } + } + + var style = itemModel.getModel('itemStyle').getItemStyle(); + var color = getVisualFromData(seriesData, 'color'); + + if (!style.fill) { + style.fill = color; + } + + mpData.setItemVisual(idx, { + symbol: symbol, + symbolSize: symbolSize, + symbolRotate: symbolRotate, + symbolOffset: symbolOffset, + symbolKeepAspect: symbolKeepAspect, + style: style + }); + }); // TODO Text are wrong + + symbolDraw.updateData(mpData); + this.group.add(symbolDraw.group); // Set host model for tooltip + // FIXME + + mpData.eachItemGraphicEl(function (el) { + el.traverse(function (child) { + getECData(child).dataModel = mpModel; + }); + }); + this.markKeep(symbolDraw); + symbolDraw.group.silent = mpModel.get('silent') || seriesModel.get('silent'); + }; + + MarkPointView.type = 'markPoint'; + return MarkPointView; + }(MarkerView); + + function createData(coordSys, seriesModel, mpModel) { + var coordDimsInfos; + + if (coordSys) { + coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) { + var info = seriesModel.getData().getDimensionInfo(seriesModel.getData().mapDimension(coordDim)) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys + + return extend(extend({}, info), { + name: coordDim, + // DON'T use ordinalMeta to parse and collect ordinal. + ordinalMeta: null + }); + }); + } else { + coordDimsInfos = [{ + name: 'value', + type: 'float' + }]; + } + + var mpData = new SeriesData(coordDimsInfos, mpModel); + var dataOpt = map(mpModel.get('data'), curry(dataTransform, seriesModel)); + + if (coordSys) { + dataOpt = filter(dataOpt, curry(dataFilter$1, coordSys)); + } + + var dimValueGetter = createMarkerDimValueGetter(!!coordSys, coordDimsInfos); + mpData.initData(dataOpt, null, dimValueGetter); + return mpData; + } + + function install$E(registers) { + registers.registerComponentModel(MarkPointModel); + registers.registerComponentView(MarkPointView); + registers.registerPreprocessor(function (opt) { + if (checkMarkerInSeries(opt.series, 'markPoint')) { + // Make sure markPoint component is enabled + opt.markPoint = opt.markPoint || {}; + } + }); + } + + var MarkLineModel = + /** @class */ + function (_super) { + __extends(MarkLineModel, _super); + + function MarkLineModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkLineModel.type; + return _this; + } + + MarkLineModel.prototype.createMarkerModelFromSeries = function (markerOpt, masterMarkerModel, ecModel) { + return new MarkLineModel(markerOpt, masterMarkerModel, ecModel); + }; + + MarkLineModel.type = 'markLine'; + MarkLineModel.defaultOption = { + // zlevel: 0, + z: 5, + symbol: ['circle', 'arrow'], + symbolSize: [8, 16], + //symbolRotate: 0, + symbolOffset: 0, + precision: 2, + tooltip: { + trigger: 'item' + }, + label: { + show: true, + position: 'end', + distance: 5 + }, + lineStyle: { + type: 'dashed' + }, + emphasis: { + label: { + show: true + }, + lineStyle: { + width: 3 + } + }, + animationEasing: 'linear' + }; + return MarkLineModel; + }(MarkerModel); + + var inner$i = makeInner(); + + var markLineTransform = function (seriesModel, coordSys, mlModel, item) { + var data = seriesModel.getData(); + var itemArray; + + if (!isArray(item)) { + // Special type markLine like 'min', 'max', 'average', 'median' + var mlType = item.type; + + if (mlType === 'min' || mlType === 'max' || mlType === 'average' || mlType === 'median' // In case + // data: [{ + // yAxis: 10 + // }] + || item.xAxis != null || item.yAxis != null) { + var valueAxis = void 0; + var value = void 0; + + if (item.yAxis != null || item.xAxis != null) { + valueAxis = coordSys.getAxis(item.yAxis != null ? 'y' : 'x'); + value = retrieve(item.yAxis, item.xAxis); + } else { + var axisInfo = getAxisInfo$1(item, data, coordSys, seriesModel); + valueAxis = axisInfo.valueAxis; + var valueDataDim = getStackedDimension(data, axisInfo.valueDataDim); + value = numCalculate(data, valueDataDim, mlType); + } + + var valueIndex = valueAxis.dim === 'x' ? 0 : 1; + var baseIndex = 1 - valueIndex; // Normized to 2d data with start and end point + + var mlFrom = clone(item); + var mlTo = { + coord: [] + }; + mlFrom.type = null; + mlFrom.coord = []; + mlFrom.coord[baseIndex] = -Infinity; + mlTo.coord[baseIndex] = Infinity; + var precision = mlModel.get('precision'); + + if (precision >= 0 && isNumber(value)) { + value = +value.toFixed(Math.min(precision, 20)); + } + + mlFrom.coord[valueIndex] = mlTo.coord[valueIndex] = value; + itemArray = [mlFrom, mlTo, { + type: mlType, + valueIndex: item.valueIndex, + // Force to use the value of calculated value. + value: value + }]; + } else { + // Invalid data + if ("development" !== 'production') { + logError('Invalid markLine data.'); + } + + itemArray = []; + } + } else { + itemArray = item; + } + + var normalizedItem = [dataTransform(seriesModel, itemArray[0]), dataTransform(seriesModel, itemArray[1]), extend({}, itemArray[2])]; // Avoid line data type is extended by from(to) data type + + normalizedItem[2].type = normalizedItem[2].type || null; // Merge from option and to option into line option + + merge(normalizedItem[2], normalizedItem[0]); + merge(normalizedItem[2], normalizedItem[1]); + return normalizedItem; + }; + + function isInifinity(val) { + return !isNaN(val) && !isFinite(val); + } // If a markLine has one dim + + + function ifMarkLineHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) { + var otherDimIndex = 1 - dimIndex; + var dimName = coordSys.dimensions[dimIndex]; + return isInifinity(fromCoord[otherDimIndex]) && isInifinity(toCoord[otherDimIndex]) && fromCoord[dimIndex] === toCoord[dimIndex] && coordSys.getAxis(dimName).containData(fromCoord[dimIndex]); + } + + function markLineFilter(coordSys, item) { + if (coordSys.type === 'cartesian2d') { + var fromCoord = item[0].coord; + var toCoord = item[1].coord; // In case + // { + // markLine: { + // data: [{ yAxis: 2 }] + // } + // } + + if (fromCoord && toCoord && (ifMarkLineHasOnlyDim(1, fromCoord, toCoord, coordSys) || ifMarkLineHasOnlyDim(0, fromCoord, toCoord, coordSys))) { + return true; + } + } + + return dataFilter$1(coordSys, item[0]) && dataFilter$1(coordSys, item[1]); + } + + function updateSingleMarkerEndLayout(data, idx, isFrom, seriesModel, api) { + var coordSys = seriesModel.coordinateSystem; + var itemModel = data.getItemModel(idx); + var point; + var xPx = parsePercent$1(itemModel.get('x'), api.getWidth()); + var yPx = parsePercent$1(itemModel.get('y'), api.getHeight()); + + if (!isNaN(xPx) && !isNaN(yPx)) { + point = [xPx, yPx]; + } else { + // Chart like bar may have there own marker positioning logic + if (seriesModel.getMarkerPosition) { + // Use the getMarkerPoisition + point = seriesModel.getMarkerPosition(data.getValues(data.dimensions, idx)); + } else { + var dims = coordSys.dimensions; + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + point = coordSys.dataToPoint([x, y]); + } // Expand line to the edge of grid if value on one axis is Inifnity + // In case + // markLine: { + // data: [{ + // yAxis: 2 + // // or + // type: 'average' + // }] + // } + + + if (isCoordinateSystemType(coordSys, 'cartesian2d')) { + // TODO: TYPE ts@4.1 may still infer it as Axis instead of Axis2D. Not sure if it's a bug + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + var dims = coordSys.dimensions; + + if (isInifinity(data.get(dims[0], idx))) { + point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[isFrom ? 0 : 1]); + } else if (isInifinity(data.get(dims[1], idx))) { + point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[isFrom ? 0 : 1]); + } + } // Use x, y if has any + + + if (!isNaN(xPx)) { + point[0] = xPx; + } + + if (!isNaN(yPx)) { + point[1] = yPx; + } + } + + data.setItemLayout(idx, point); + } + + var MarkLineView = + /** @class */ + function (_super) { + __extends(MarkLineView, _super); + + function MarkLineView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkLineView.type; + return _this; + } + + MarkLineView.prototype.updateTransform = function (markLineModel, ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + var mlModel = MarkerModel.getMarkerModelFromSeries(seriesModel, 'markLine'); + + if (mlModel) { + var mlData_1 = mlModel.getData(); + var fromData_1 = inner$i(mlModel).from; + var toData_1 = inner$i(mlModel).to; // Update visual and layout of from symbol and to symbol + + fromData_1.each(function (idx) { + updateSingleMarkerEndLayout(fromData_1, idx, true, seriesModel, api); + updateSingleMarkerEndLayout(toData_1, idx, false, seriesModel, api); + }); // Update layout of line + + mlData_1.each(function (idx) { + mlData_1.setItemLayout(idx, [fromData_1.getItemLayout(idx), toData_1.getItemLayout(idx)]); + }); + this.markerGroupMap.get(seriesModel.id).updateLayout(); + } + }, this); + }; + + MarkLineView.prototype.renderSeries = function (seriesModel, mlModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var seriesId = seriesModel.id; + var seriesData = seriesModel.getData(); + var lineDrawMap = this.markerGroupMap; + var lineDraw = lineDrawMap.get(seriesId) || lineDrawMap.set(seriesId, new LineDraw()); + this.group.add(lineDraw.group); + var mlData = createList$1(coordSys, seriesModel, mlModel); + var fromData = mlData.from; + var toData = mlData.to; + var lineData = mlData.line; + inner$i(mlModel).from = fromData; + inner$i(mlModel).to = toData; // Line data for tooltip and formatter + + mlModel.setData(lineData); // TODO + // Functionally, `symbolSize` & `symbolOffset` can also be 2D array now. + // But the related logic and type definition are not finished yet. + // Finish it if required + + var symbolType = mlModel.get('symbol'); + var symbolSize = mlModel.get('symbolSize'); + var symbolRotate = mlModel.get('symbolRotate'); + var symbolOffset = mlModel.get('symbolOffset'); // TODO: support callback function like markPoint + + if (!isArray(symbolType)) { + symbolType = [symbolType, symbolType]; + } + + if (!isArray(symbolSize)) { + symbolSize = [symbolSize, symbolSize]; + } + + if (!isArray(symbolRotate)) { + symbolRotate = [symbolRotate, symbolRotate]; + } + + if (!isArray(symbolOffset)) { + symbolOffset = [symbolOffset, symbolOffset]; + } // Update visual and layout of from symbol and to symbol + + + mlData.from.each(function (idx) { + updateDataVisualAndLayout(fromData, idx, true); + updateDataVisualAndLayout(toData, idx, false); + }); // Update visual and layout of line + + lineData.each(function (idx) { + var lineStyle = lineData.getItemModel(idx).getModel('lineStyle').getLineStyle(); // lineData.setItemVisual(idx, { + // color: lineColor || fromData.getItemVisual(idx, 'color') + // }); + + lineData.setItemLayout(idx, [fromData.getItemLayout(idx), toData.getItemLayout(idx)]); + + if (lineStyle.stroke == null) { + lineStyle.stroke = fromData.getItemVisual(idx, 'style').fill; + } + + lineData.setItemVisual(idx, { + fromSymbolKeepAspect: fromData.getItemVisual(idx, 'symbolKeepAspect'), + fromSymbolOffset: fromData.getItemVisual(idx, 'symbolOffset'), + fromSymbolRotate: fromData.getItemVisual(idx, 'symbolRotate'), + fromSymbolSize: fromData.getItemVisual(idx, 'symbolSize'), + fromSymbol: fromData.getItemVisual(idx, 'symbol'), + toSymbolKeepAspect: toData.getItemVisual(idx, 'symbolKeepAspect'), + toSymbolOffset: toData.getItemVisual(idx, 'symbolOffset'), + toSymbolRotate: toData.getItemVisual(idx, 'symbolRotate'), + toSymbolSize: toData.getItemVisual(idx, 'symbolSize'), + toSymbol: toData.getItemVisual(idx, 'symbol'), + style: lineStyle + }); + }); + lineDraw.updateData(lineData); // Set host model for tooltip + // FIXME + + mlData.line.eachItemGraphicEl(function (el, idx) { + el.traverse(function (child) { + getECData(child).dataModel = mlModel; + }); + }); + + function updateDataVisualAndLayout(data, idx, isFrom) { + var itemModel = data.getItemModel(idx); + updateSingleMarkerEndLayout(data, idx, isFrom, seriesModel, api); + var style = itemModel.getModel('itemStyle').getItemStyle(); + + if (style.fill == null) { + style.fill = getVisualFromData(seriesData, 'color'); + } + + data.setItemVisual(idx, { + symbolKeepAspect: itemModel.get('symbolKeepAspect'), + // `0` should be considered as a valid value, so use `retrieve2` instead of `||` + symbolOffset: retrieve2(itemModel.get('symbolOffset', true), symbolOffset[isFrom ? 0 : 1]), + symbolRotate: retrieve2(itemModel.get('symbolRotate', true), symbolRotate[isFrom ? 0 : 1]), + // TODO: when 2d array is supported, it should ignore parent + symbolSize: retrieve2(itemModel.get('symbolSize'), symbolSize[isFrom ? 0 : 1]), + symbol: retrieve2(itemModel.get('symbol', true), symbolType[isFrom ? 0 : 1]), + style: style + }); + } + + this.markKeep(lineDraw); + lineDraw.group.silent = mlModel.get('silent') || seriesModel.get('silent'); + }; + + MarkLineView.type = 'markLine'; + return MarkLineView; + }(MarkerView); + + function createList$1(coordSys, seriesModel, mlModel) { + var coordDimsInfos; + + if (coordSys) { + coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) { + var info = seriesModel.getData().getDimensionInfo(seriesModel.getData().mapDimension(coordDim)) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys + + return extend(extend({}, info), { + name: coordDim, + // DON'T use ordinalMeta to parse and collect ordinal. + ordinalMeta: null + }); + }); + } else { + coordDimsInfos = [{ + name: 'value', + type: 'float' + }]; + } + + var fromData = new SeriesData(coordDimsInfos, mlModel); + var toData = new SeriesData(coordDimsInfos, mlModel); // No dimensions + + var lineData = new SeriesData([], mlModel); + var optData = map(mlModel.get('data'), curry(markLineTransform, seriesModel, coordSys, mlModel)); + + if (coordSys) { + optData = filter(optData, curry(markLineFilter, coordSys)); + } + + var dimValueGetter = createMarkerDimValueGetter(!!coordSys, coordDimsInfos); + fromData.initData(map(optData, function (item) { + return item[0]; + }), null, dimValueGetter); + toData.initData(map(optData, function (item) { + return item[1]; + }), null, dimValueGetter); + lineData.initData(map(optData, function (item) { + return item[2]; + })); + lineData.hasItemOption = true; + return { + from: fromData, + to: toData, + line: lineData + }; + } + + function install$F(registers) { + registers.registerComponentModel(MarkLineModel); + registers.registerComponentView(MarkLineView); + registers.registerPreprocessor(function (opt) { + if (checkMarkerInSeries(opt.series, 'markLine')) { + // Make sure markLine component is enabled + opt.markLine = opt.markLine || {}; + } + }); + } + + var MarkAreaModel = + /** @class */ + function (_super) { + __extends(MarkAreaModel, _super); + + function MarkAreaModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkAreaModel.type; + return _this; + } + + MarkAreaModel.prototype.createMarkerModelFromSeries = function (markerOpt, masterMarkerModel, ecModel) { + return new MarkAreaModel(markerOpt, masterMarkerModel, ecModel); + }; + + MarkAreaModel.type = 'markArea'; + MarkAreaModel.defaultOption = { + // zlevel: 0, + // PENDING + z: 1, + tooltip: { + trigger: 'item' + }, + // markArea should fixed on the coordinate system + animation: false, + label: { + show: true, + position: 'top' + }, + itemStyle: { + // color and borderColor default to use color from series + // color: 'auto' + // borderColor: 'auto' + borderWidth: 0 + }, + emphasis: { + label: { + show: true, + position: 'top' + } + } + }; + return MarkAreaModel; + }(MarkerModel); + + var inner$j = makeInner(); + + var markAreaTransform = function (seriesModel, coordSys, maModel, item) { + var lt = dataTransform(seriesModel, item[0]); + var rb = dataTransform(seriesModel, item[1]); // FIXME make sure lt is less than rb + + var ltCoord = lt.coord; + var rbCoord = rb.coord; + ltCoord[0] = retrieve(ltCoord[0], -Infinity); + ltCoord[1] = retrieve(ltCoord[1], -Infinity); + rbCoord[0] = retrieve(rbCoord[0], Infinity); + rbCoord[1] = retrieve(rbCoord[1], Infinity); // Merge option into one + + var result = mergeAll([{}, lt, rb]); + result.coord = [lt.coord, rb.coord]; + result.x0 = lt.x; + result.y0 = lt.y; + result.x1 = rb.x; + result.y1 = rb.y; + return result; + }; + + function isInifinity$1(val) { + return !isNaN(val) && !isFinite(val); + } // If a markArea has one dim + + + function ifMarkAreaHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) { + var otherDimIndex = 1 - dimIndex; + return isInifinity$1(fromCoord[otherDimIndex]) && isInifinity$1(toCoord[otherDimIndex]); + } + + function markAreaFilter(coordSys, item) { + var fromCoord = item.coord[0]; + var toCoord = item.coord[1]; + + if (isCoordinateSystemType(coordSys, 'cartesian2d')) { + // In case + // { + // markArea: { + // data: [{ yAxis: 2 }] + // } + // } + if (fromCoord && toCoord && (ifMarkAreaHasOnlyDim(1, fromCoord, toCoord) || ifMarkAreaHasOnlyDim(0, fromCoord, toCoord))) { + return true; + } + } + + return dataFilter$1(coordSys, { + coord: fromCoord, + x: item.x0, + y: item.y0 + }) || dataFilter$1(coordSys, { + coord: toCoord, + x: item.x1, + y: item.y1 + }); + } // dims can be ['x0', 'y0'], ['x1', 'y1'], ['x0', 'y1'], ['x1', 'y0'] + + + function getSingleMarkerEndPoint(data, idx, dims, seriesModel, api) { + var coordSys = seriesModel.coordinateSystem; + var itemModel = data.getItemModel(idx); + var point; + var xPx = parsePercent$1(itemModel.get(dims[0]), api.getWidth()); + var yPx = parsePercent$1(itemModel.get(dims[1]), api.getHeight()); + + if (!isNaN(xPx) && !isNaN(yPx)) { + point = [xPx, yPx]; + } else { + // Chart like bar may have there own marker positioning logic + if (seriesModel.getMarkerPosition) { + // Use the getMarkerPoisition + point = seriesModel.getMarkerPosition(data.getValues(dims, idx)); + } else { + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + var pt = [x, y]; + coordSys.clampData && coordSys.clampData(pt, pt); + point = coordSys.dataToPoint(pt, true); + } + + if (isCoordinateSystemType(coordSys, 'cartesian2d')) { + // TODO: TYPE ts@4.1 may still infer it as Axis instead of Axis2D. Not sure if it's a bug + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + + if (isInifinity$1(x)) { + point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[dims[0] === 'x0' ? 0 : 1]); + } else if (isInifinity$1(y)) { + point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[dims[1] === 'y0' ? 0 : 1]); + } + } // Use x, y if has any + + + if (!isNaN(xPx)) { + point[0] = xPx; + } + + if (!isNaN(yPx)) { + point[1] = yPx; + } + } + + return point; + } + + var dimPermutations = [['x0', 'y0'], ['x1', 'y0'], ['x1', 'y1'], ['x0', 'y1']]; + + var MarkAreaView = + /** @class */ + function (_super) { + __extends(MarkAreaView, _super); + + function MarkAreaView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkAreaView.type; + return _this; + } + + MarkAreaView.prototype.updateTransform = function (markAreaModel, ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + var maModel = MarkerModel.getMarkerModelFromSeries(seriesModel, 'markArea'); + + if (maModel) { + var areaData_1 = maModel.getData(); + areaData_1.each(function (idx) { + var points = map(dimPermutations, function (dim) { + return getSingleMarkerEndPoint(areaData_1, idx, dim, seriesModel, api); + }); // Layout + + areaData_1.setItemLayout(idx, points); + var el = areaData_1.getItemGraphicEl(idx); + el.setShape('points', points); + }); + } + }, this); + }; + + MarkAreaView.prototype.renderSeries = function (seriesModel, maModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var seriesId = seriesModel.id; + var seriesData = seriesModel.getData(); + var areaGroupMap = this.markerGroupMap; + var polygonGroup = areaGroupMap.get(seriesId) || areaGroupMap.set(seriesId, { + group: new Group() + }); + this.group.add(polygonGroup.group); + this.markKeep(polygonGroup); + var areaData = createList$2(coordSys, seriesModel, maModel); // Line data for tooltip and formatter + + maModel.setData(areaData); // Update visual and layout of line + + areaData.each(function (idx) { + // Layout + var points = map(dimPermutations, function (dim) { + return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api); + }); + var xAxisScale = coordSys.getAxis('x').scale; + var yAxisScale = coordSys.getAxis('y').scale; + var xAxisExtent = xAxisScale.getExtent(); + var yAxisExtent = yAxisScale.getExtent(); + var xPointExtent = [xAxisScale.parse(areaData.get('x0', idx)), xAxisScale.parse(areaData.get('x1', idx))]; + var yPointExtent = [yAxisScale.parse(areaData.get('y0', idx)), yAxisScale.parse(areaData.get('y1', idx))]; + asc(xPointExtent); + asc(yPointExtent); + var overlapped = !(xAxisExtent[0] > xPointExtent[1] || xAxisExtent[1] < xPointExtent[0] || yAxisExtent[0] > yPointExtent[1] || yAxisExtent[1] < yPointExtent[0]); // If none of the area is inside coordSys, allClipped is set to be true + // in layout so that label will not be displayed. See #12591 + + var allClipped = !overlapped; + areaData.setItemLayout(idx, { + points: points, + allClipped: allClipped + }); + var style = areaData.getItemModel(idx).getModel('itemStyle').getItemStyle(); + var color$1 = getVisualFromData(seriesData, 'color'); + + if (!style.fill) { + style.fill = color$1; + + if (isString(style.fill)) { + style.fill = modifyAlpha(style.fill, 0.4); + } + } + + if (!style.stroke) { + style.stroke = color$1; + } // Visual + + + areaData.setItemVisual(idx, 'style', style); + }); + areaData.diff(inner$j(polygonGroup).data).add(function (idx) { + var layout = areaData.getItemLayout(idx); + + if (!layout.allClipped) { + var polygon = new Polygon({ + shape: { + points: layout.points + } + }); + areaData.setItemGraphicEl(idx, polygon); + polygonGroup.group.add(polygon); + } + }).update(function (newIdx, oldIdx) { + var polygon = inner$j(polygonGroup).data.getItemGraphicEl(oldIdx); + var layout = areaData.getItemLayout(newIdx); + + if (!layout.allClipped) { + if (polygon) { + updateProps(polygon, { + shape: { + points: layout.points + } + }, maModel, newIdx); + } else { + polygon = new Polygon({ + shape: { + points: layout.points + } + }); + } + + areaData.setItemGraphicEl(newIdx, polygon); + polygonGroup.group.add(polygon); + } else if (polygon) { + polygonGroup.group.remove(polygon); + } + }).remove(function (idx) { + var polygon = inner$j(polygonGroup).data.getItemGraphicEl(idx); + polygonGroup.group.remove(polygon); + }).execute(); + areaData.eachItemGraphicEl(function (polygon, idx) { + var itemModel = areaData.getItemModel(idx); + var style = areaData.getItemVisual(idx, 'style'); + polygon.useStyle(areaData.getItemVisual(idx, 'style')); + setLabelStyle(polygon, getLabelStatesModels(itemModel), { + labelFetcher: maModel, + labelDataIndex: idx, + defaultText: areaData.getName(idx) || '', + inheritColor: isString(style.fill) ? modifyAlpha(style.fill, 1) : '#000' + }); + setStatesStylesFromModel(polygon, itemModel); + toggleHoverEmphasis(polygon, null, null, itemModel.get(['emphasis', 'disabled'])); + getECData(polygon).dataModel = maModel; + }); + inner$j(polygonGroup).data = areaData; + polygonGroup.group.silent = maModel.get('silent') || seriesModel.get('silent'); + }; + + MarkAreaView.type = 'markArea'; + return MarkAreaView; + }(MarkerView); + + function createList$2(coordSys, seriesModel, maModel) { + var areaData; + var dataDims; + var dims = ['x0', 'y0', 'x1', 'y1']; + + if (coordSys) { + var coordDimsInfos_1 = map(coordSys && coordSys.dimensions, function (coordDim) { + var data = seriesModel.getData(); + var info = data.getDimensionInfo(data.mapDimension(coordDim)) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys + + return extend(extend({}, info), { + name: coordDim, + // DON'T use ordinalMeta to parse and collect ordinal. + ordinalMeta: null + }); + }); + dataDims = map(dims, function (dim, idx) { + return { + name: dim, + type: coordDimsInfos_1[idx % 2].type + }; + }); + areaData = new SeriesData(dataDims, maModel); + } else { + dataDims = [{ + name: 'value', + type: 'float' + }]; + areaData = new SeriesData(dataDims, maModel); + } + + var optData = map(maModel.get('data'), curry(markAreaTransform, seriesModel, coordSys, maModel)); + + if (coordSys) { + optData = filter(optData, curry(markAreaFilter, coordSys)); + } + + var dimValueGetter = coordSys ? function (item, dimName, dataIndex, dimIndex) { + // TODO should convert to ParsedValue? + var rawVal = item.coord[Math.floor(dimIndex / 2)][dimIndex % 2]; + return parseDataValue(rawVal, dataDims[dimIndex]); + } : function (item, dimName, dataIndex, dimIndex) { + return parseDataValue(item.value, dataDims[dimIndex]); + }; + areaData.initData(optData, null, dimValueGetter); + areaData.hasItemOption = true; + return areaData; + } + + function install$G(registers) { + registers.registerComponentModel(MarkAreaModel); + registers.registerComponentView(MarkAreaView); + registers.registerPreprocessor(function (opt) { + if (checkMarkerInSeries(opt.series, 'markArea')) { + // Make sure markArea component is enabled + opt.markArea = opt.markArea || {}; + } + }); + } + + var getDefaultSelectorOptions = function (ecModel, type) { + if (type === 'all') { + return { + type: 'all', + title: ecModel.getLocaleModel().get(['legend', 'selector', 'all']) + }; + } else if (type === 'inverse') { + return { + type: 'inverse', + title: ecModel.getLocaleModel().get(['legend', 'selector', 'inverse']) + }; + } + }; + + var LegendModel = + /** @class */ + function (_super) { + __extends(LegendModel, _super); + + function LegendModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = LegendModel.type; + _this.layoutMode = { + type: 'box', + // legend.width/height are maxWidth/maxHeight actually, + // whereas realy width/height is calculated by its content. + // (Setting {left: 10, right: 10} does not make sense). + // So consider the case: + // `setOption({legend: {left: 10});` + // then `setOption({legend: {right: 10});` + // The previous `left` should be cleared by setting `ignoreSize`. + ignoreSize: true + }; + return _this; + } + + LegendModel.prototype.init = function (option, parentModel, ecModel) { + this.mergeDefaultAndTheme(option, ecModel); + option.selected = option.selected || {}; + + this._updateSelector(option); + }; + + LegendModel.prototype.mergeOption = function (option, ecModel) { + _super.prototype.mergeOption.call(this, option, ecModel); + + this._updateSelector(option); + }; + + LegendModel.prototype._updateSelector = function (option) { + var selector = option.selector; + var ecModel = this.ecModel; + + if (selector === true) { + selector = option.selector = ['all', 'inverse']; + } + + if (isArray(selector)) { + each(selector, function (item, index) { + isString(item) && (item = { + type: item + }); + selector[index] = merge(item, getDefaultSelectorOptions(ecModel, item.type)); + }); + } + }; + + LegendModel.prototype.optionUpdated = function () { + this._updateData(this.ecModel); + + var legendData = this._data; // If selectedMode is single, try to select one + + if (legendData[0] && this.get('selectedMode') === 'single') { + var hasSelected = false; // If has any selected in option.selected + + for (var i = 0; i < legendData.length; i++) { + var name_1 = legendData[i].get('name'); + + if (this.isSelected(name_1)) { + // Force to unselect others + this.select(name_1); + hasSelected = true; + break; + } + } // Try select the first if selectedMode is single + + + !hasSelected && this.select(legendData[0].get('name')); + } + }; + + LegendModel.prototype._updateData = function (ecModel) { + var potentialData = []; + var availableNames = []; + ecModel.eachRawSeries(function (seriesModel) { + var seriesName = seriesModel.name; + availableNames.push(seriesName); + var isPotential; + + if (seriesModel.legendVisualProvider) { + var provider = seriesModel.legendVisualProvider; + var names = provider.getAllNames(); + + if (!ecModel.isSeriesFiltered(seriesModel)) { + availableNames = availableNames.concat(names); + } + + if (names.length) { + potentialData = potentialData.concat(names); + } else { + isPotential = true; + } + } else { + isPotential = true; + } + + if (isPotential && isNameSpecified(seriesModel)) { + potentialData.push(seriesModel.name); + } + }); + /** + * @type {Array.} + * @private + */ + + this._availableNames = availableNames; // If legend.data not specified in option, use availableNames as data, + // which is convinient for user preparing option. + + var rawData = this.get('data') || potentialData; + var legendData = map(rawData, function (dataItem) { + // Can be string or number + if (isString(dataItem) || isNumber(dataItem)) { + dataItem = { + name: dataItem + }; + } + + return new Model(dataItem, this, this.ecModel); + }, this); + /** + * @type {Array.} + * @private + */ + + this._data = legendData; + }; + + LegendModel.prototype.getData = function () { + return this._data; + }; + + LegendModel.prototype.select = function (name) { + var selected = this.option.selected; + var selectedMode = this.get('selectedMode'); + + if (selectedMode === 'single') { + var data = this._data; + each(data, function (dataItem) { + selected[dataItem.get('name')] = false; + }); + } + + selected[name] = true; + }; + + LegendModel.prototype.unSelect = function (name) { + if (this.get('selectedMode') !== 'single') { + this.option.selected[name] = false; + } + }; + + LegendModel.prototype.toggleSelected = function (name) { + var selected = this.option.selected; // Default is true + + if (!selected.hasOwnProperty(name)) { + selected[name] = true; + } + + this[selected[name] ? 'unSelect' : 'select'](name); + }; + + LegendModel.prototype.allSelect = function () { + var data = this._data; + var selected = this.option.selected; + each(data, function (dataItem) { + selected[dataItem.get('name', true)] = true; + }); + }; + + LegendModel.prototype.inverseSelect = function () { + var data = this._data; + var selected = this.option.selected; + each(data, function (dataItem) { + var name = dataItem.get('name', true); // Initially, default value is true + + if (!selected.hasOwnProperty(name)) { + selected[name] = true; + } + + selected[name] = !selected[name]; + }); + }; + + LegendModel.prototype.isSelected = function (name) { + var selected = this.option.selected; + return !(selected.hasOwnProperty(name) && !selected[name]) && indexOf(this._availableNames, name) >= 0; + }; + + LegendModel.prototype.getOrient = function () { + return this.get('orient') === 'vertical' ? { + index: 1, + name: 'vertical' + } : { + index: 0, + name: 'horizontal' + }; + }; + + LegendModel.type = 'legend.plain'; + LegendModel.dependencies = ['series']; + LegendModel.defaultOption = { + // zlevel: 0, + z: 4, + show: true, + orient: 'horizontal', + left: 'center', + // right: 'center', + top: 0, + // bottom: null, + align: 'auto', + backgroundColor: 'rgba(0,0,0,0)', + borderColor: '#ccc', + borderRadius: 0, + borderWidth: 0, + padding: 5, + itemGap: 10, + itemWidth: 25, + itemHeight: 14, + symbolRotate: 'inherit', + symbolKeepAspect: true, + inactiveColor: '#ccc', + inactiveBorderColor: '#ccc', + inactiveBorderWidth: 'auto', + itemStyle: { + color: 'inherit', + opacity: 'inherit', + borderColor: 'inherit', + borderWidth: 'auto', + borderCap: 'inherit', + borderJoin: 'inherit', + borderDashOffset: 'inherit', + borderMiterLimit: 'inherit' + }, + lineStyle: { + width: 'auto', + color: 'inherit', + inactiveColor: '#ccc', + inactiveWidth: 2, + opacity: 'inherit', + type: 'inherit', + cap: 'inherit', + join: 'inherit', + dashOffset: 'inherit', + miterLimit: 'inherit' + }, + textStyle: { + color: '#333' + }, + selectedMode: true, + selector: false, + selectorLabel: { + show: true, + borderRadius: 10, + padding: [3, 5, 3, 5], + fontSize: 12, + fontFamily: 'sans-serif', + color: '#666', + borderWidth: 1, + borderColor: '#666' + }, + emphasis: { + selectorLabel: { + show: true, + color: '#eee', + backgroundColor: '#666' + } + }, + selectorPosition: 'auto', + selectorItemGap: 7, + selectorButtonGap: 10, + tooltip: { + show: false + } + }; + return LegendModel; + }(ComponentModel); + + var curry$1 = curry; + var each$c = each; + var Group$2 = Group; + + var LegendView = + /** @class */ + function (_super) { + __extends(LegendView, _super); + + function LegendView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = LegendView.type; + _this.newlineDisabled = false; + return _this; + } + + LegendView.prototype.init = function () { + this.group.add(this._contentGroup = new Group$2()); + this.group.add(this._selectorGroup = new Group$2()); + this._isFirstRender = true; + }; + /** + * @protected + */ + + + LegendView.prototype.getContentGroup = function () { + return this._contentGroup; + }; + /** + * @protected + */ + + + LegendView.prototype.getSelectorGroup = function () { + return this._selectorGroup; + }; + /** + * @override + */ + + + LegendView.prototype.render = function (legendModel, ecModel, api) { + var isFirstRender = this._isFirstRender; + this._isFirstRender = false; + this.resetInner(); + + if (!legendModel.get('show', true)) { + return; + } + + var itemAlign = legendModel.get('align'); + var orient = legendModel.get('orient'); + + if (!itemAlign || itemAlign === 'auto') { + itemAlign = legendModel.get('left') === 'right' && orient === 'vertical' ? 'right' : 'left'; + } // selector has been normalized to an array in model + + + var selector = legendModel.get('selector', true); + var selectorPosition = legendModel.get('selectorPosition', true); + + if (selector && (!selectorPosition || selectorPosition === 'auto')) { + selectorPosition = orient === 'horizontal' ? 'end' : 'start'; + } + + this.renderInner(itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition); // Perform layout. + + var positionInfo = legendModel.getBoxLayoutParams(); + var viewportSize = { + width: api.getWidth(), + height: api.getHeight() + }; + var padding = legendModel.get('padding'); + var maxSize = getLayoutRect(positionInfo, viewportSize, padding); + var mainRect = this.layoutInner(legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition); // Place mainGroup, based on the calculated `mainRect`. + + var layoutRect = getLayoutRect(defaults({ + width: mainRect.width, + height: mainRect.height + }, positionInfo), viewportSize, padding); + this.group.x = layoutRect.x - mainRect.x; + this.group.y = layoutRect.y - mainRect.y; + this.group.markRedraw(); // Render background after group is layout. + + this.group.add(this._backgroundEl = makeBackground(mainRect, legendModel)); + }; + + LegendView.prototype.resetInner = function () { + this.getContentGroup().removeAll(); + this._backgroundEl && this.group.remove(this._backgroundEl); + this.getSelectorGroup().removeAll(); + }; + + LegendView.prototype.renderInner = function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) { + var contentGroup = this.getContentGroup(); + var legendDrawnMap = createHashMap(); + var selectMode = legendModel.get('selectedMode'); + var excludeSeriesId = []; + ecModel.eachRawSeries(function (seriesModel) { + !seriesModel.get('legendHoverLink') && excludeSeriesId.push(seriesModel.id); + }); + each$c(legendModel.getData(), function (legendItemModel, dataIndex) { + var name = legendItemModel.get('name'); // Use empty string or \n as a newline string + + if (!this.newlineDisabled && (name === '' || name === '\n')) { + var g = new Group$2(); // @ts-ignore + + g.newline = true; + contentGroup.add(g); + return; + } // Representitive series. + + + var seriesModel = ecModel.getSeriesByName(name)[0]; + + if (legendDrawnMap.get(name)) { + // Have been drawed + return; + } // Legend to control series. + + + if (seriesModel) { + var data = seriesModel.getData(); + var lineVisualStyle = data.getVisual('legendLineStyle') || {}; + var legendIcon = data.getVisual('legendIcon'); + /** + * `data.getVisual('style')` may be the color from the register + * in series. For example, for line series, + */ + + var style = data.getVisual('style'); + + var itemGroup = this._createItem(seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, lineVisualStyle, style, legendIcon, selectMode); + + itemGroup.on('click', curry$1(dispatchSelectAction, name, null, api, excludeSeriesId)).on('mouseover', curry$1(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId)).on('mouseout', curry$1(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId)); + legendDrawnMap.set(name, true); + } else { + // Legend to control data. In pie and funnel. + ecModel.eachRawSeries(function (seriesModel) { + // In case multiple series has same data name + if (legendDrawnMap.get(name)) { + return; + } + + if (seriesModel.legendVisualProvider) { + var provider = seriesModel.legendVisualProvider; + + if (!provider.containName(name)) { + return; + } + + var idx = provider.indexOfName(name); + var style = provider.getItemVisual(idx, 'style'); + var legendIcon = provider.getItemVisual(idx, 'legendIcon'); + var colorArr = parse(style.fill); // Color may be set to transparent in visualMap when data is out of range. + // Do not show nothing. + + if (colorArr && colorArr[3] === 0) { + colorArr[3] = 0.2; // TODO color is set to 0, 0, 0, 0. Should show correct RGBA + + style = extend(extend({}, style), { + fill: stringify(colorArr, 'rgba') + }); + } + + var itemGroup = this._createItem(seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, {}, style, legendIcon, selectMode); // FIXME: consider different series has items with the same name. + + + itemGroup.on('click', curry$1(dispatchSelectAction, null, name, api, excludeSeriesId)) // Should not specify the series name, consider legend controls + // more than one pie series. + .on('mouseover', curry$1(dispatchHighlightAction, null, name, api, excludeSeriesId)).on('mouseout', curry$1(dispatchDownplayAction, null, name, api, excludeSeriesId)); + legendDrawnMap.set(name, true); + } + }, this); + } + + if ("development" !== 'production') { + if (!legendDrawnMap.get(name)) { + console.warn(name + ' series not exists. Legend data should be same with series name or data name.'); + } + } + }, this); + + if (selector) { + this._createSelector(selector, legendModel, api, orient, selectorPosition); + } + }; + + LegendView.prototype._createSelector = function (selector, legendModel, api, orient, selectorPosition) { + var selectorGroup = this.getSelectorGroup(); + each$c(selector, function createSelectorButton(selectorItem) { + var type = selectorItem.type; + var labelText = new ZRText({ + style: { + x: 0, + y: 0, + align: 'center', + verticalAlign: 'middle' + }, + onclick: function () { + api.dispatchAction({ + type: type === 'all' ? 'legendAllSelect' : 'legendInverseSelect' + }); + } + }); + selectorGroup.add(labelText); + var labelModel = legendModel.getModel('selectorLabel'); + var emphasisLabelModel = legendModel.getModel(['emphasis', 'selectorLabel']); + setLabelStyle(labelText, { + normal: labelModel, + emphasis: emphasisLabelModel + }, { + defaultText: selectorItem.title + }); + enableHoverEmphasis(labelText); + }); + }; + + LegendView.prototype._createItem = function (seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, lineVisualStyle, itemVisualStyle, legendIcon, selectMode) { + var drawType = seriesModel.visualDrawType; + var itemWidth = legendModel.get('itemWidth'); + var itemHeight = legendModel.get('itemHeight'); + var isSelected = legendModel.isSelected(name); + var iconRotate = legendItemModel.get('symbolRotate'); + var symbolKeepAspect = legendItemModel.get('symbolKeepAspect'); + var legendIconType = legendItemModel.get('icon'); + legendIcon = legendIconType || legendIcon || 'roundRect'; + var style = getLegendStyle(legendIcon, legendItemModel, lineVisualStyle, itemVisualStyle, drawType, isSelected); + var itemGroup = new Group$2(); + var textStyleModel = legendItemModel.getModel('textStyle'); + + if (isFunction(seriesModel.getLegendIcon) && (!legendIconType || legendIconType === 'inherit')) { + // Series has specific way to define legend icon + itemGroup.add(seriesModel.getLegendIcon({ + itemWidth: itemWidth, + itemHeight: itemHeight, + icon: legendIcon, + iconRotate: iconRotate, + itemStyle: style.itemStyle, + lineStyle: style.lineStyle, + symbolKeepAspect: symbolKeepAspect + })); + } else { + // Use default legend icon policy for most series + var rotate = legendIconType === 'inherit' && seriesModel.getData().getVisual('symbol') ? iconRotate === 'inherit' ? seriesModel.getData().getVisual('symbolRotate') : iconRotate : 0; // No rotation for no icon + + itemGroup.add(getDefaultLegendIcon({ + itemWidth: itemWidth, + itemHeight: itemHeight, + icon: legendIcon, + iconRotate: rotate, + itemStyle: style.itemStyle, + lineStyle: style.lineStyle, + symbolKeepAspect: symbolKeepAspect + })); + } + + var textX = itemAlign === 'left' ? itemWidth + 5 : -5; + var textAlign = itemAlign; + var formatter = legendModel.get('formatter'); + var content = name; + + if (isString(formatter) && formatter) { + content = formatter.replace('{name}', name != null ? name : ''); + } else if (isFunction(formatter)) { + content = formatter(name); + } + + var inactiveColor = legendItemModel.get('inactiveColor'); + itemGroup.add(new ZRText({ + style: createTextStyle(textStyleModel, { + text: content, + x: textX, + y: itemHeight / 2, + fill: isSelected ? textStyleModel.getTextColor() : inactiveColor, + align: textAlign, + verticalAlign: 'middle' + }) + })); // Add a invisible rect to increase the area of mouse hover + + var hitRect = new Rect({ + shape: itemGroup.getBoundingRect(), + invisible: true + }); + var tooltipModel = legendItemModel.getModel('tooltip'); + + if (tooltipModel.get('show')) { + setTooltipConfig({ + el: hitRect, + componentModel: legendModel, + itemName: name, + itemTooltipOption: tooltipModel.option + }); + } + + itemGroup.add(hitRect); + itemGroup.eachChild(function (child) { + child.silent = true; + }); + hitRect.silent = !selectMode; + this.getContentGroup().add(itemGroup); + enableHoverEmphasis(itemGroup); // @ts-ignore + + itemGroup.__legendDataIndex = dataIndex; + return itemGroup; + }; + + LegendView.prototype.layoutInner = function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) { + var contentGroup = this.getContentGroup(); + var selectorGroup = this.getSelectorGroup(); // Place items in contentGroup. + + box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), maxSize.width, maxSize.height); + var contentRect = contentGroup.getBoundingRect(); + var contentPos = [-contentRect.x, -contentRect.y]; + selectorGroup.markRedraw(); + contentGroup.markRedraw(); + + if (selector) { + // Place buttons in selectorGroup + box( // Buttons in selectorGroup always layout horizontally + 'horizontal', selectorGroup, legendModel.get('selectorItemGap', true)); + var selectorRect = selectorGroup.getBoundingRect(); + var selectorPos = [-selectorRect.x, -selectorRect.y]; + var selectorButtonGap = legendModel.get('selectorButtonGap', true); + var orientIdx = legendModel.getOrient().index; + var wh = orientIdx === 0 ? 'width' : 'height'; + var hw = orientIdx === 0 ? 'height' : 'width'; + var yx = orientIdx === 0 ? 'y' : 'x'; + + if (selectorPosition === 'end') { + selectorPos[orientIdx] += contentRect[wh] + selectorButtonGap; + } else { + contentPos[orientIdx] += selectorRect[wh] + selectorButtonGap; + } //Always align selector to content as 'middle' + + + selectorPos[1 - orientIdx] += contentRect[hw] / 2 - selectorRect[hw] / 2; + selectorGroup.x = selectorPos[0]; + selectorGroup.y = selectorPos[1]; + contentGroup.x = contentPos[0]; + contentGroup.y = contentPos[1]; + var mainRect = { + x: 0, + y: 0 + }; + mainRect[wh] = contentRect[wh] + selectorButtonGap + selectorRect[wh]; + mainRect[hw] = Math.max(contentRect[hw], selectorRect[hw]); + mainRect[yx] = Math.min(0, selectorRect[yx] + selectorPos[1 - orientIdx]); + return mainRect; + } else { + contentGroup.x = contentPos[0]; + contentGroup.y = contentPos[1]; + return this.group.getBoundingRect(); + } + }; + /** + * @protected + */ + + + LegendView.prototype.remove = function () { + this.getContentGroup().removeAll(); + this._isFirstRender = true; + }; + + LegendView.type = 'legend.plain'; + return LegendView; + }(ComponentView); + + function getLegendStyle(iconType, legendModel, lineVisualStyle, itemVisualStyle, drawType, isSelected) { + /** + * Use series style if is inherit; + * elsewise, use legend style + */ + function handleCommonProps(style, visualStyle) { + // If lineStyle.width is 'auto', it is set to be 2 if series has border + if (style.lineWidth === 'auto') { + style.lineWidth = visualStyle.lineWidth > 0 ? 2 : 0; + } + + each$c(style, function (propVal, propName) { + style[propName] === 'inherit' && (style[propName] = visualStyle[propName]); + }); + } // itemStyle + + + var legendItemModel = legendModel.getModel('itemStyle'); + var itemStyle = legendItemModel.getItemStyle(); + var iconBrushType = iconType.lastIndexOf('empty', 0) === 0 ? 'fill' : 'stroke'; + itemStyle.decal = itemVisualStyle.decal; + + if (itemStyle.fill === 'inherit') { + /** + * Series with visualDrawType as 'stroke' should have + * series stroke as legend fill + */ + itemStyle.fill = itemVisualStyle[drawType]; + } + + if (itemStyle.stroke === 'inherit') { + /** + * icon type with "emptyXXX" should use fill color + * in visual style + */ + itemStyle.stroke = itemVisualStyle[iconBrushType]; + } + + if (itemStyle.opacity === 'inherit') { + /** + * Use lineStyle.opacity if drawType is stroke + */ + itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity; + } + + handleCommonProps(itemStyle, itemVisualStyle); // lineStyle + + var legendLineModel = legendModel.getModel('lineStyle'); + var lineStyle = legendLineModel.getLineStyle(); + handleCommonProps(lineStyle, lineVisualStyle); // Fix auto color to real color + + itemStyle.fill === 'auto' && (itemStyle.fill = itemVisualStyle.fill); + itemStyle.stroke === 'auto' && (itemStyle.stroke = itemVisualStyle.fill); + lineStyle.stroke === 'auto' && (lineStyle.stroke = itemVisualStyle.fill); + + if (!isSelected) { + var borderWidth = legendModel.get('inactiveBorderWidth'); + /** + * Since stroke is set to be inactiveBorderColor, it may occur that + * there is no border in series but border in legend, so we need to + * use border only when series has border if is set to be auto + */ + + var visualHasBorder = itemStyle[iconBrushType]; + itemStyle.lineWidth = borderWidth === 'auto' ? itemVisualStyle.lineWidth > 0 && visualHasBorder ? 2 : 0 : itemStyle.lineWidth; + itemStyle.fill = legendModel.get('inactiveColor'); + itemStyle.stroke = legendModel.get('inactiveBorderColor'); + lineStyle.stroke = legendLineModel.get('inactiveColor'); + lineStyle.lineWidth = legendLineModel.get('inactiveWidth'); + } + + return { + itemStyle: itemStyle, + lineStyle: lineStyle + }; + } + + function getDefaultLegendIcon(opt) { + var symboType = opt.icon || 'roundRect'; + var icon = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill, opt.symbolKeepAspect); + icon.setStyle(opt.itemStyle); + icon.rotation = (opt.iconRotate || 0) * Math.PI / 180; + icon.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]); + + if (symboType.indexOf('empty') > -1) { + icon.style.stroke = icon.style.fill; + icon.style.fill = '#fff'; + icon.style.lineWidth = 2; + } + + return icon; + } + + function dispatchSelectAction(seriesName, dataName, api, excludeSeriesId) { + // downplay before unselect + dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId); + api.dispatchAction({ + type: 'legendToggleSelect', + name: seriesName != null ? seriesName : dataName + }); // highlight after select + // TODO higlight immediately may cause animation loss. + + dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId); + } + + function isUseHoverLayer(api) { + var list = api.getZr().storage.getDisplayList(); + var emphasisState; + var i = 0; + var len = list.length; + + while (i < len && !(emphasisState = list[i].states.emphasis)) { + i++; + } + + return emphasisState && emphasisState.hoverLayer; + } + + function dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId) { + // If element hover will move to a hoverLayer. + if (!isUseHoverLayer(api)) { + api.dispatchAction({ + type: 'highlight', + seriesName: seriesName, + name: dataName, + excludeSeriesId: excludeSeriesId + }); + } + } + + function dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId) { + // If element hover will move to a hoverLayer. + if (!isUseHoverLayer(api)) { + api.dispatchAction({ + type: 'downplay', + seriesName: seriesName, + name: dataName, + excludeSeriesId: excludeSeriesId + }); + } + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function legendFilter(ecModel) { + var legendModels = ecModel.findComponents({ + mainType: 'legend' + }); + + if (legendModels && legendModels.length) { + ecModel.filterSeries(function (series) { + // If in any legend component the status is not selected. + // Because in legend series is assumed selected when it is not in the legend data. + for (var i = 0; i < legendModels.length; i++) { + if (!legendModels[i].isSelected(series.name)) { + return false; + } + } + + return true; + }); + } + } + + function legendSelectActionHandler(methodName, payload, ecModel) { + var selectedMap = {}; + var isToggleSelect = methodName === 'toggleSelected'; + var isSelected; // Update all legend components + + ecModel.eachComponent('legend', function (legendModel) { + if (isToggleSelect && isSelected != null) { + // Force other legend has same selected status + // Or the first is toggled to true and other are toggled to false + // In the case one legend has some item unSelected in option. And if other legend + // doesn't has the item, they will assume it is selected. + legendModel[isSelected ? 'select' : 'unSelect'](payload.name); + } else if (methodName === 'allSelect' || methodName === 'inverseSelect') { + legendModel[methodName](); + } else { + legendModel[methodName](payload.name); + isSelected = legendModel.isSelected(payload.name); + } + + var legendData = legendModel.getData(); + each(legendData, function (model) { + var name = model.get('name'); // Wrap element + + if (name === '\n' || name === '') { + return; + } + + var isItemSelected = legendModel.isSelected(name); + + if (selectedMap.hasOwnProperty(name)) { + // Unselected if any legend is unselected + selectedMap[name] = selectedMap[name] && isItemSelected; + } else { + selectedMap[name] = isItemSelected; + } + }); + }); // Return the event explicitly + + return methodName === 'allSelect' || methodName === 'inverseSelect' ? { + selected: selectedMap + } : { + name: payload.name, + selected: selectedMap + }; + } + + function installLegendAction(registers) { + /** + * @event legendToggleSelect + * @type {Object} + * @property {string} type 'legendToggleSelect' + * @property {string} [from] + * @property {string} name Series name or data item name + */ + registers.registerAction('legendToggleSelect', 'legendselectchanged', curry(legendSelectActionHandler, 'toggleSelected')); + registers.registerAction('legendAllSelect', 'legendselectall', curry(legendSelectActionHandler, 'allSelect')); + registers.registerAction('legendInverseSelect', 'legendinverseselect', curry(legendSelectActionHandler, 'inverseSelect')); + /** + * @event legendSelect + * @type {Object} + * @property {string} type 'legendSelect' + * @property {string} name Series name or data item name + */ + + registers.registerAction('legendSelect', 'legendselected', curry(legendSelectActionHandler, 'select')); + /** + * @event legendUnSelect + * @type {Object} + * @property {string} type 'legendUnSelect' + * @property {string} name Series name or data item name + */ + + registers.registerAction('legendUnSelect', 'legendunselected', curry(legendSelectActionHandler, 'unSelect')); + } + + function install$H(registers) { + registers.registerComponentModel(LegendModel); + registers.registerComponentView(LegendView); + registers.registerProcessor(registers.PRIORITY.PROCESSOR.SERIES_FILTER, legendFilter); + registers.registerSubTypeDefaulter('legend', function () { + return 'plain'; + }); + installLegendAction(registers); + } + + var ScrollableLegendModel = + /** @class */ + function (_super) { + __extends(ScrollableLegendModel, _super); + + function ScrollableLegendModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ScrollableLegendModel.type; + return _this; + } + /** + * @param {number} scrollDataIndex + */ + + + ScrollableLegendModel.prototype.setScrollDataIndex = function (scrollDataIndex) { + this.option.scrollDataIndex = scrollDataIndex; + }; + + ScrollableLegendModel.prototype.init = function (option, parentModel, ecModel) { + var inputPositionParams = getLayoutParams(option); + + _super.prototype.init.call(this, option, parentModel, ecModel); + + mergeAndNormalizeLayoutParams$1(this, option, inputPositionParams); + }; + /** + * @override + */ + + + ScrollableLegendModel.prototype.mergeOption = function (option, ecModel) { + _super.prototype.mergeOption.call(this, option, ecModel); + + mergeAndNormalizeLayoutParams$1(this, this.option, option); + }; + + ScrollableLegendModel.type = 'legend.scroll'; + ScrollableLegendModel.defaultOption = inheritDefaultOption(LegendModel.defaultOption, { + scrollDataIndex: 0, + pageButtonItemGap: 5, + pageButtonGap: null, + pageButtonPosition: 'end', + pageFormatter: '{current}/{total}', + pageIcons: { + horizontal: ['M0,0L12,-10L12,10z', 'M0,0L-12,-10L-12,10z'], + vertical: ['M0,0L20,0L10,-20z', 'M0,0L20,0L10,20z'] + }, + pageIconColor: '#2f4554', + pageIconInactiveColor: '#aaa', + pageIconSize: 15, + pageTextStyle: { + color: '#333' + }, + animationDurationUpdate: 800 + }); + return ScrollableLegendModel; + }(LegendModel); + + function mergeAndNormalizeLayoutParams$1(legendModel, target, raw) { + var orient = legendModel.getOrient(); + var ignoreSize = [1, 1]; + ignoreSize[orient.index] = 0; + mergeLayoutParam(target, raw, { + type: 'box', + ignoreSize: !!ignoreSize + }); + } + + var Group$3 = Group; + var WH$1 = ['width', 'height']; + var XY$1 = ['x', 'y']; + + var ScrollableLegendView = + /** @class */ + function (_super) { + __extends(ScrollableLegendView, _super); + + function ScrollableLegendView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ScrollableLegendView.type; + _this.newlineDisabled = true; + _this._currentIndex = 0; + return _this; + } + + ScrollableLegendView.prototype.init = function () { + _super.prototype.init.call(this); + + this.group.add(this._containerGroup = new Group$3()); + + this._containerGroup.add(this.getContentGroup()); + + this.group.add(this._controllerGroup = new Group$3()); + }; + /** + * @override + */ + + + ScrollableLegendView.prototype.resetInner = function () { + _super.prototype.resetInner.call(this); + + this._controllerGroup.removeAll(); + + this._containerGroup.removeClipPath(); + + this._containerGroup.__rectSize = null; + }; + /** + * @override + */ + + + ScrollableLegendView.prototype.renderInner = function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) { + var self = this; // Render content items. + + _super.prototype.renderInner.call(this, itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition); + + var controllerGroup = this._controllerGroup; // FIXME: support be 'auto' adapt to size number text length, + // e.g., '3/12345' should not overlap with the control arrow button. + + var pageIconSize = legendModel.get('pageIconSize', true); + var pageIconSizeArr = isArray(pageIconSize) ? pageIconSize : [pageIconSize, pageIconSize]; + createPageButton('pagePrev', 0); + var pageTextStyleModel = legendModel.getModel('pageTextStyle'); + controllerGroup.add(new ZRText({ + name: 'pageText', + style: { + // Placeholder to calculate a proper layout. + text: 'xx/xx', + fill: pageTextStyleModel.getTextColor(), + font: pageTextStyleModel.getFont(), + verticalAlign: 'middle', + align: 'center' + }, + silent: true + })); + createPageButton('pageNext', 1); + + function createPageButton(name, iconIdx) { + var pageDataIndexName = name + 'DataIndex'; + var icon = createIcon(legendModel.get('pageIcons', true)[legendModel.getOrient().name][iconIdx], { + // Buttons will be created in each render, so we do not need + // to worry about avoiding using legendModel kept in scope. + onclick: bind(self._pageGo, self, pageDataIndexName, legendModel, api) + }, { + x: -pageIconSizeArr[0] / 2, + y: -pageIconSizeArr[1] / 2, + width: pageIconSizeArr[0], + height: pageIconSizeArr[1] + }); + icon.name = name; + controllerGroup.add(icon); + } + }; + /** + * @override + */ + + + ScrollableLegendView.prototype.layoutInner = function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) { + var selectorGroup = this.getSelectorGroup(); + var orientIdx = legendModel.getOrient().index; + var wh = WH$1[orientIdx]; + var xy = XY$1[orientIdx]; + var hw = WH$1[1 - orientIdx]; + var yx = XY$1[1 - orientIdx]; + selector && box( // Buttons in selectorGroup always layout horizontally + 'horizontal', selectorGroup, legendModel.get('selectorItemGap', true)); + var selectorButtonGap = legendModel.get('selectorButtonGap', true); + var selectorRect = selectorGroup.getBoundingRect(); + var selectorPos = [-selectorRect.x, -selectorRect.y]; + var processMaxSize = clone(maxSize); + selector && (processMaxSize[wh] = maxSize[wh] - selectorRect[wh] - selectorButtonGap); + + var mainRect = this._layoutContentAndController(legendModel, isFirstRender, processMaxSize, orientIdx, wh, hw, yx, xy); + + if (selector) { + if (selectorPosition === 'end') { + selectorPos[orientIdx] += mainRect[wh] + selectorButtonGap; + } else { + var offset = selectorRect[wh] + selectorButtonGap; + selectorPos[orientIdx] -= offset; + mainRect[xy] -= offset; + } + + mainRect[wh] += selectorRect[wh] + selectorButtonGap; + selectorPos[1 - orientIdx] += mainRect[yx] + mainRect[hw] / 2 - selectorRect[hw] / 2; + mainRect[hw] = Math.max(mainRect[hw], selectorRect[hw]); + mainRect[yx] = Math.min(mainRect[yx], selectorRect[yx] + selectorPos[1 - orientIdx]); + selectorGroup.x = selectorPos[0]; + selectorGroup.y = selectorPos[1]; + selectorGroup.markRedraw(); + } + + return mainRect; + }; + + ScrollableLegendView.prototype._layoutContentAndController = function (legendModel, isFirstRender, maxSize, orientIdx, wh, hw, yx, xy) { + var contentGroup = this.getContentGroup(); + var containerGroup = this._containerGroup; + var controllerGroup = this._controllerGroup; // Place items in contentGroup. + + box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), !orientIdx ? null : maxSize.width, orientIdx ? null : maxSize.height); + box( // Buttons in controller are layout always horizontally. + 'horizontal', controllerGroup, legendModel.get('pageButtonItemGap', true)); + var contentRect = contentGroup.getBoundingRect(); + var controllerRect = controllerGroup.getBoundingRect(); + var showController = this._showController = contentRect[wh] > maxSize[wh]; // In case that the inner elements of contentGroup layout do not based on [0, 0] + + var contentPos = [-contentRect.x, -contentRect.y]; // Remain contentPos when scroll animation perfroming. + // If first rendering, `contentGroup.position` is [0, 0], which + // does not make sense and may cause unexepcted animation if adopted. + + if (!isFirstRender) { + contentPos[orientIdx] = contentGroup[xy]; + } // Layout container group based on 0. + + + var containerPos = [0, 0]; + var controllerPos = [-controllerRect.x, -controllerRect.y]; + var pageButtonGap = retrieve2(legendModel.get('pageButtonGap', true), legendModel.get('itemGap', true)); // Place containerGroup and controllerGroup and contentGroup. + + if (showController) { + var pageButtonPosition = legendModel.get('pageButtonPosition', true); // controller is on the right / bottom. + + if (pageButtonPosition === 'end') { + controllerPos[orientIdx] += maxSize[wh] - controllerRect[wh]; + } // controller is on the left / top. + else { + containerPos[orientIdx] += controllerRect[wh] + pageButtonGap; + } + } // Always align controller to content as 'middle'. + + + controllerPos[1 - orientIdx] += contentRect[hw] / 2 - controllerRect[hw] / 2; + contentGroup.setPosition(contentPos); + containerGroup.setPosition(containerPos); + controllerGroup.setPosition(controllerPos); // Calculate `mainRect` and set `clipPath`. + // mainRect should not be calculated by `this.group.getBoundingRect()` + // for sake of the overflow. + + var mainRect = { + x: 0, + y: 0 + }; // Consider content may be overflow (should be clipped). + + mainRect[wh] = showController ? maxSize[wh] : contentRect[wh]; + mainRect[hw] = Math.max(contentRect[hw], controllerRect[hw]); // `containerRect[yx] + containerPos[1 - orientIdx]` is 0. + + mainRect[yx] = Math.min(0, controllerRect[yx] + controllerPos[1 - orientIdx]); + containerGroup.__rectSize = maxSize[wh]; + + if (showController) { + var clipShape = { + x: 0, + y: 0 + }; + clipShape[wh] = Math.max(maxSize[wh] - controllerRect[wh] - pageButtonGap, 0); + clipShape[hw] = mainRect[hw]; + containerGroup.setClipPath(new Rect({ + shape: clipShape + })); // Consider content may be larger than container, container rect + // can not be obtained from `containerGroup.getBoundingRect()`. + + containerGroup.__rectSize = clipShape[wh]; + } else { + // Do not remove or ignore controller. Keep them set as placeholders. + controllerGroup.eachChild(function (child) { + child.attr({ + invisible: true, + silent: true + }); + }); + } // Content translate animation. + + + var pageInfo = this._getPageInfo(legendModel); + + pageInfo.pageIndex != null && updateProps(contentGroup, { + x: pageInfo.contentPosition[0], + y: pageInfo.contentPosition[1] + }, // When switch from "show controller" to "not show controller", view should be + // updated immediately without animation, otherwise causes weird effect. + showController ? legendModel : null); + + this._updatePageInfoView(legendModel, pageInfo); + + return mainRect; + }; + + ScrollableLegendView.prototype._pageGo = function (to, legendModel, api) { + var scrollDataIndex = this._getPageInfo(legendModel)[to]; + + scrollDataIndex != null && api.dispatchAction({ + type: 'legendScroll', + scrollDataIndex: scrollDataIndex, + legendId: legendModel.id + }); + }; + + ScrollableLegendView.prototype._updatePageInfoView = function (legendModel, pageInfo) { + var controllerGroup = this._controllerGroup; + each(['pagePrev', 'pageNext'], function (name) { + var key = name + 'DataIndex'; + var canJump = pageInfo[key] != null; + var icon = controllerGroup.childOfName(name); + + if (icon) { + icon.setStyle('fill', canJump ? legendModel.get('pageIconColor', true) : legendModel.get('pageIconInactiveColor', true)); + icon.cursor = canJump ? 'pointer' : 'default'; + } + }); + var pageText = controllerGroup.childOfName('pageText'); + var pageFormatter = legendModel.get('pageFormatter'); + var pageIndex = pageInfo.pageIndex; + var current = pageIndex != null ? pageIndex + 1 : 0; + var total = pageInfo.pageCount; + pageText && pageFormatter && pageText.setStyle('text', isString(pageFormatter) ? pageFormatter.replace('{current}', current == null ? '' : current + '').replace('{total}', total == null ? '' : total + '') : pageFormatter({ + current: current, + total: total + })); + }; + /** + * contentPosition: Array., null when data item not found. + * pageIndex: number, null when data item not found. + * pageCount: number, always be a number, can be 0. + * pagePrevDataIndex: number, null when no previous page. + * pageNextDataIndex: number, null when no next page. + * } + */ + + + ScrollableLegendView.prototype._getPageInfo = function (legendModel) { + var scrollDataIndex = legendModel.get('scrollDataIndex', true); + var contentGroup = this.getContentGroup(); + var containerRectSize = this._containerGroup.__rectSize; + var orientIdx = legendModel.getOrient().index; + var wh = WH$1[orientIdx]; + var xy = XY$1[orientIdx]; + + var targetItemIndex = this._findTargetItemIndex(scrollDataIndex); + + var children = contentGroup.children(); + var targetItem = children[targetItemIndex]; + var itemCount = children.length; + var pCount = !itemCount ? 0 : 1; + var result = { + contentPosition: [contentGroup.x, contentGroup.y], + pageCount: pCount, + pageIndex: pCount - 1, + pagePrevDataIndex: null, + pageNextDataIndex: null + }; + + if (!targetItem) { + return result; + } + + var targetItemInfo = getItemInfo(targetItem); + result.contentPosition[orientIdx] = -targetItemInfo.s; // Strategy: + // (1) Always align based on the left/top most item. + // (2) It is user-friendly that the last item shown in the + // current window is shown at the begining of next window. + // Otherwise if half of the last item is cut by the window, + // it will have no chance to display entirely. + // (3) Consider that item size probably be different, we + // have calculate pageIndex by size rather than item index, + // and we can not get page index directly by division. + // (4) The window is to narrow to contain more than + // one item, we should make sure that the page can be fliped. + + for (var i = targetItemIndex + 1, winStartItemInfo = targetItemInfo, winEndItemInfo = targetItemInfo, currItemInfo = null; i <= itemCount; ++i) { + currItemInfo = getItemInfo(children[i]); + + if ( // Half of the last item is out of the window. + !currItemInfo && winEndItemInfo.e > winStartItemInfo.s + containerRectSize || // If the current item does not intersect with the window, the new page + // can be started at the current item or the last item. + currItemInfo && !intersect(currItemInfo, winStartItemInfo.s)) { + if (winEndItemInfo.i > winStartItemInfo.i) { + winStartItemInfo = winEndItemInfo; + } else { + // e.g., when page size is smaller than item size. + winStartItemInfo = currItemInfo; + } + + if (winStartItemInfo) { + if (result.pageNextDataIndex == null) { + result.pageNextDataIndex = winStartItemInfo.i; + } + + ++result.pageCount; + } + } + + winEndItemInfo = currItemInfo; + } + + for (var i = targetItemIndex - 1, winStartItemInfo = targetItemInfo, winEndItemInfo = targetItemInfo, currItemInfo = null; i >= -1; --i) { + currItemInfo = getItemInfo(children[i]); + + if ( // If the the end item does not intersect with the window started + // from the current item, a page can be settled. + (!currItemInfo || !intersect(winEndItemInfo, currItemInfo.s)) && // e.g., when page size is smaller than item size. + winStartItemInfo.i < winEndItemInfo.i) { + winEndItemInfo = winStartItemInfo; + + if (result.pagePrevDataIndex == null) { + result.pagePrevDataIndex = winStartItemInfo.i; + } + + ++result.pageCount; + ++result.pageIndex; + } + + winStartItemInfo = currItemInfo; + } + + return result; + + function getItemInfo(el) { + if (el) { + var itemRect = el.getBoundingRect(); + var start = itemRect[xy] + el[xy]; + return { + s: start, + e: start + itemRect[wh], + i: el.__legendDataIndex + }; + } + } + + function intersect(itemInfo, winStart) { + return itemInfo.e >= winStart && itemInfo.s <= winStart + containerRectSize; + } + }; + + ScrollableLegendView.prototype._findTargetItemIndex = function (targetDataIndex) { + if (!this._showController) { + return 0; + } + + var index; + var contentGroup = this.getContentGroup(); + var defaultIndex; + contentGroup.eachChild(function (child, idx) { + var legendDataIdx = child.__legendDataIndex; // FIXME + // If the given targetDataIndex (from model) is illegal, + // we use defaultIndex. But the index on the legend model and + // action payload is still illegal. That case will not be + // changed until some scenario requires. + + if (defaultIndex == null && legendDataIdx != null) { + defaultIndex = idx; + } + + if (legendDataIdx === targetDataIndex) { + index = idx; + } + }); + return index != null ? index : defaultIndex; + }; + + ScrollableLegendView.type = 'legend.scroll'; + return ScrollableLegendView; + }(LegendView); + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function installScrollableLegendAction(registers) { + /** + * @event legendScroll + * @type {Object} + * @property {string} type 'legendScroll' + * @property {string} scrollDataIndex + */ + registers.registerAction('legendScroll', 'legendscroll', function (payload, ecModel) { + var scrollDataIndex = payload.scrollDataIndex; + scrollDataIndex != null && ecModel.eachComponent({ + mainType: 'legend', + subType: 'scroll', + query: payload + }, function (legendModel) { + legendModel.setScrollDataIndex(scrollDataIndex); + }); + }); + } + + function install$I(registers) { + use(install$H); + registers.registerComponentModel(ScrollableLegendModel); + registers.registerComponentView(ScrollableLegendView); + installScrollableLegendAction(registers); + } + + function install$J(registers) { + use(install$H); + use(install$I); + } + + var InsideZoomModel = + /** @class */ + function (_super) { + __extends(InsideZoomModel, _super); + + function InsideZoomModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = InsideZoomModel.type; + return _this; + } + + InsideZoomModel.type = 'dataZoom.inside'; + InsideZoomModel.defaultOption = inheritDefaultOption(DataZoomModel.defaultOption, { + disabled: false, + zoomLock: false, + zoomOnMouseWheel: true, + moveOnMouseMove: true, + moveOnMouseWheel: false, + preventDefaultMouseMove: true + }); + return InsideZoomModel; + }(DataZoomModel); + + var inner$k = makeInner(); + function setViewInfoToCoordSysRecord(api, dataZoomModel, getRange) { + inner$k(api).coordSysRecordMap.each(function (coordSysRecord) { + var dzInfo = coordSysRecord.dataZoomInfoMap.get(dataZoomModel.uid); + + if (dzInfo) { + dzInfo.getRange = getRange; + } + }); + } + function disposeCoordSysRecordIfNeeded(api, dataZoomModel) { + var coordSysRecordMap = inner$k(api).coordSysRecordMap; + var coordSysKeyArr = coordSysRecordMap.keys(); + + for (var i = 0; i < coordSysKeyArr.length; i++) { + var coordSysKey = coordSysKeyArr[i]; + var coordSysRecord = coordSysRecordMap.get(coordSysKey); + var dataZoomInfoMap = coordSysRecord.dataZoomInfoMap; + + if (dataZoomInfoMap) { + var dzUid = dataZoomModel.uid; + var dzInfo = dataZoomInfoMap.get(dzUid); + + if (dzInfo) { + dataZoomInfoMap.removeKey(dzUid); + + if (!dataZoomInfoMap.keys().length) { + disposeCoordSysRecord(coordSysRecordMap, coordSysRecord); + } + } + } + } + } + + function disposeCoordSysRecord(coordSysRecordMap, coordSysRecord) { + if (coordSysRecord) { + coordSysRecordMap.removeKey(coordSysRecord.model.uid); + var controller = coordSysRecord.controller; + controller && controller.dispose(); + } + } + + function createCoordSysRecord(api, coordSysModel) { + // These init props will never change after record created. + var coordSysRecord = { + model: coordSysModel, + containsPoint: curry(containsPoint, coordSysModel), + dispatchAction: curry(dispatchAction$1, api), + dataZoomInfoMap: null, + controller: null + }; // Must not do anything depends on coordSysRecord outside the event handler here, + // because coordSysRecord not completed yet. + + var controller = coordSysRecord.controller = new RoamController(api.getZr()); + each(['pan', 'zoom', 'scrollMove'], function (eventName) { + controller.on(eventName, function (event) { + var batch = []; + coordSysRecord.dataZoomInfoMap.each(function (dzInfo) { + // Check whether the behaviors (zoomOnMouseWheel, moveOnMouseMove, + // moveOnMouseWheel, ...) enabled. + if (!event.isAvailableBehavior(dzInfo.model.option)) { + return; + } + + var method = (dzInfo.getRange || {})[eventName]; + var range = method && method(dzInfo.dzReferCoordSysInfo, coordSysRecord.model.mainType, coordSysRecord.controller, event); + !dzInfo.model.get('disabled', true) && range && batch.push({ + dataZoomId: dzInfo.model.id, + start: range[0], + end: range[1] + }); + }); + batch.length && coordSysRecord.dispatchAction(batch); + }); + }); + return coordSysRecord; + } + /** + * This action will be throttled. + */ + + + function dispatchAction$1(api, batch) { + if (!api.isDisposed()) { + api.dispatchAction({ + type: 'dataZoom', + animation: { + easing: 'cubicOut', + duration: 100 + }, + batch: batch + }); + } + } + + function containsPoint(coordSysModel, e, x, y) { + return coordSysModel.coordinateSystem.containPoint([x, y]); + } + /** + * Merge roamController settings when multiple dataZooms share one roamController. + */ + + + function mergeControllerParams(dataZoomInfoMap) { + var controlType; // DO NOT use reserved word (true, false, undefined) as key literally. Even if encapsulated + // as string, it is probably revert to reserved word by compress tool. See #7411. + + var prefix = 'type_'; + var typePriority = { + 'type_true': 2, + 'type_move': 1, + 'type_false': 0, + 'type_undefined': -1 + }; + var preventDefaultMouseMove = true; + dataZoomInfoMap.each(function (dataZoomInfo) { + var dataZoomModel = dataZoomInfo.model; + var oneType = dataZoomModel.get('disabled', true) ? false : dataZoomModel.get('zoomLock', true) ? 'move' : true; + + if (typePriority[prefix + oneType] > typePriority[prefix + controlType]) { + controlType = oneType; + } // Prevent default move event by default. If one false, do not prevent. Otherwise + // users may be confused why it does not work when multiple insideZooms exist. + + + preventDefaultMouseMove = preventDefaultMouseMove && dataZoomModel.get('preventDefaultMouseMove', true); + }); + return { + controlType: controlType, + opt: { + // RoamController will enable all of these functionalities, + // and the final behavior is determined by its event listener + // provided by each inside zoom. + zoomOnMouseWheel: true, + moveOnMouseMove: true, + moveOnMouseWheel: true, + preventDefaultMouseMove: !!preventDefaultMouseMove + } + }; + } + + function installDataZoomRoamProcessor(registers) { + registers.registerProcessor(registers.PRIORITY.PROCESSOR.FILTER, function (ecModel, api) { + var apiInner = inner$k(api); + var coordSysRecordMap = apiInner.coordSysRecordMap || (apiInner.coordSysRecordMap = createHashMap()); + coordSysRecordMap.each(function (coordSysRecord) { + // `coordSysRecordMap` always exists (becuase it hold the `roam controller`, which should + // better not re-create each time), but clear `dataZoomInfoMap` each round of the workflow. + coordSysRecord.dataZoomInfoMap = null; + }); + ecModel.eachComponent({ + mainType: 'dataZoom', + subType: 'inside' + }, function (dataZoomModel) { + var dzReferCoordSysWrap = collectReferCoordSysModelInfo(dataZoomModel); + each(dzReferCoordSysWrap.infoList, function (dzCoordSysInfo) { + var coordSysUid = dzCoordSysInfo.model.uid; + var coordSysRecord = coordSysRecordMap.get(coordSysUid) || coordSysRecordMap.set(coordSysUid, createCoordSysRecord(api, dzCoordSysInfo.model)); + var dataZoomInfoMap = coordSysRecord.dataZoomInfoMap || (coordSysRecord.dataZoomInfoMap = createHashMap()); // Notice these props might be changed each time for a single dataZoomModel. + + dataZoomInfoMap.set(dataZoomModel.uid, { + dzReferCoordSysInfo: dzCoordSysInfo, + model: dataZoomModel, + getRange: null + }); + }); + }); // (1) Merge dataZoom settings for each coord sys and set to the roam controller. + // (2) Clear coord sys if not refered by any dataZoom. + + coordSysRecordMap.each(function (coordSysRecord) { + var controller = coordSysRecord.controller; + var firstDzInfo; + var dataZoomInfoMap = coordSysRecord.dataZoomInfoMap; + + if (dataZoomInfoMap) { + var firstDzKey = dataZoomInfoMap.keys()[0]; + + if (firstDzKey != null) { + firstDzInfo = dataZoomInfoMap.get(firstDzKey); + } + } + + if (!firstDzInfo) { + disposeCoordSysRecord(coordSysRecordMap, coordSysRecord); + return; + } + + var controllerParams = mergeControllerParams(dataZoomInfoMap); + controller.enable(controllerParams.controlType, controllerParams.opt); + controller.setPointerChecker(coordSysRecord.containsPoint); + createOrUpdate(coordSysRecord, 'dispatchAction', firstDzInfo.model.get('throttle', true), 'fixRate'); + }); + }); + } + + var InsideZoomView = + /** @class */ + function (_super) { + __extends(InsideZoomView, _super); + + function InsideZoomView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'dataZoom.inside'; + return _this; + } + + InsideZoomView.prototype.render = function (dataZoomModel, ecModel, api) { + _super.prototype.render.apply(this, arguments); + + if (dataZoomModel.noTarget()) { + this._clear(); + + return; + } // Hence the `throttle` util ensures to preserve command order, + // here simply updating range all the time will not cause missing + // any of the the roam change. + + + this.range = dataZoomModel.getPercentRange(); // Reset controllers. + + setViewInfoToCoordSysRecord(api, dataZoomModel, { + pan: bind(getRangeHandlers.pan, this), + zoom: bind(getRangeHandlers.zoom, this), + scrollMove: bind(getRangeHandlers.scrollMove, this) + }); + }; + + InsideZoomView.prototype.dispose = function () { + this._clear(); + + _super.prototype.dispose.apply(this, arguments); + }; + + InsideZoomView.prototype._clear = function () { + disposeCoordSysRecordIfNeeded(this.api, this.dataZoomModel); + this.range = null; + }; + + InsideZoomView.type = 'dataZoom.inside'; + return InsideZoomView; + }(DataZoomView); + + var getRangeHandlers = { + zoom: function (coordSysInfo, coordSysMainType, controller, e) { + var lastRange = this.range; + var range = lastRange.slice(); // Calculate transform by the first axis. + + var axisModel = coordSysInfo.axisModels[0]; + + if (!axisModel) { + return; + } + + var directionInfo = getDirectionInfo[coordSysMainType](null, [e.originX, e.originY], axisModel, controller, coordSysInfo); + var percentPoint = (directionInfo.signal > 0 ? directionInfo.pixelStart + directionInfo.pixelLength - directionInfo.pixel : directionInfo.pixel - directionInfo.pixelStart) / directionInfo.pixelLength * (range[1] - range[0]) + range[0]; + var scale = Math.max(1 / e.scale, 0); + range[0] = (range[0] - percentPoint) * scale + percentPoint; + range[1] = (range[1] - percentPoint) * scale + percentPoint; // Restrict range. + + var minMaxSpan = this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); + sliderMove(0, range, [0, 100], 0, minMaxSpan.minSpan, minMaxSpan.maxSpan); + this.range = range; + + if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) { + return range; + } + }, + pan: makeMover(function (range, axisModel, coordSysInfo, coordSysMainType, controller, e) { + var directionInfo = getDirectionInfo[coordSysMainType]([e.oldX, e.oldY], [e.newX, e.newY], axisModel, controller, coordSysInfo); + return directionInfo.signal * (range[1] - range[0]) * directionInfo.pixel / directionInfo.pixelLength; + }), + scrollMove: makeMover(function (range, axisModel, coordSysInfo, coordSysMainType, controller, e) { + var directionInfo = getDirectionInfo[coordSysMainType]([0, 0], [e.scrollDelta, e.scrollDelta], axisModel, controller, coordSysInfo); + return directionInfo.signal * (range[1] - range[0]) * e.scrollDelta; + }) + }; + + function makeMover(getPercentDelta) { + return function (coordSysInfo, coordSysMainType, controller, e) { + var lastRange = this.range; + var range = lastRange.slice(); // Calculate transform by the first axis. + + var axisModel = coordSysInfo.axisModels[0]; + + if (!axisModel) { + return; + } + + var percentDelta = getPercentDelta(range, axisModel, coordSysInfo, coordSysMainType, controller, e); + sliderMove(percentDelta, range, [0, 100], 'all'); + this.range = range; + + if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) { + return range; + } + }; + } + + var getDirectionInfo = { + grid: function (oldPoint, newPoint, axisModel, controller, coordSysInfo) { + var axis = axisModel.axis; + var ret = {}; + var rect = coordSysInfo.model.coordinateSystem.getRect(); + oldPoint = oldPoint || [0, 0]; + + if (axis.dim === 'x') { + ret.pixel = newPoint[0] - oldPoint[0]; + ret.pixelLength = rect.width; + ret.pixelStart = rect.x; + ret.signal = axis.inverse ? 1 : -1; + } else { + // axis.dim === 'y' + ret.pixel = newPoint[1] - oldPoint[1]; + ret.pixelLength = rect.height; + ret.pixelStart = rect.y; + ret.signal = axis.inverse ? -1 : 1; + } + + return ret; + }, + polar: function (oldPoint, newPoint, axisModel, controller, coordSysInfo) { + var axis = axisModel.axis; + var ret = {}; + var polar = coordSysInfo.model.coordinateSystem; + var radiusExtent = polar.getRadiusAxis().getExtent(); + var angleExtent = polar.getAngleAxis().getExtent(); + oldPoint = oldPoint ? polar.pointToCoord(oldPoint) : [0, 0]; + newPoint = polar.pointToCoord(newPoint); + + if (axisModel.mainType === 'radiusAxis') { + ret.pixel = newPoint[0] - oldPoint[0]; // ret.pixelLength = Math.abs(radiusExtent[1] - radiusExtent[0]); + // ret.pixelStart = Math.min(radiusExtent[0], radiusExtent[1]); + + ret.pixelLength = radiusExtent[1] - radiusExtent[0]; + ret.pixelStart = radiusExtent[0]; + ret.signal = axis.inverse ? 1 : -1; + } else { + // 'angleAxis' + ret.pixel = newPoint[1] - oldPoint[1]; // ret.pixelLength = Math.abs(angleExtent[1] - angleExtent[0]); + // ret.pixelStart = Math.min(angleExtent[0], angleExtent[1]); + + ret.pixelLength = angleExtent[1] - angleExtent[0]; + ret.pixelStart = angleExtent[0]; + ret.signal = axis.inverse ? -1 : 1; + } + + return ret; + }, + singleAxis: function (oldPoint, newPoint, axisModel, controller, coordSysInfo) { + var axis = axisModel.axis; + var rect = coordSysInfo.model.coordinateSystem.getRect(); + var ret = {}; + oldPoint = oldPoint || [0, 0]; + + if (axis.orient === 'horizontal') { + ret.pixel = newPoint[0] - oldPoint[0]; + ret.pixelLength = rect.width; + ret.pixelStart = rect.x; + ret.signal = axis.inverse ? 1 : -1; + } else { + // 'vertical' + ret.pixel = newPoint[1] - oldPoint[1]; + ret.pixelLength = rect.height; + ret.pixelStart = rect.y; + ret.signal = axis.inverse ? -1 : 1; + } + + return ret; + } + }; + + function install$K(registers) { + installCommon(registers); + registers.registerComponentModel(InsideZoomModel); + registers.registerComponentView(InsideZoomView); + installDataZoomRoamProcessor(registers); + } + + var SliderZoomModel = + /** @class */ + function (_super) { + __extends(SliderZoomModel, _super); + + function SliderZoomModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SliderZoomModel.type; + return _this; + } + + SliderZoomModel.type = 'dataZoom.slider'; + SliderZoomModel.layoutMode = 'box'; + SliderZoomModel.defaultOption = inheritDefaultOption(DataZoomModel.defaultOption, { + show: true, + // deault value can only be drived in view stage. + right: 'ph', + top: 'ph', + width: 'ph', + height: 'ph', + left: null, + bottom: null, + borderColor: '#d2dbee', + borderRadius: 3, + backgroundColor: 'rgba(47,69,84,0)', + // dataBackgroundColor: '#ddd', + dataBackground: { + lineStyle: { + color: '#d2dbee', + width: 0.5 + }, + areaStyle: { + color: '#d2dbee', + opacity: 0.2 + } + }, + selectedDataBackground: { + lineStyle: { + color: '#8fb0f7', + width: 0.5 + }, + areaStyle: { + color: '#8fb0f7', + opacity: 0.2 + } + }, + // Color of selected window. + fillerColor: 'rgba(135,175,274,0.2)', + handleIcon: 'path://M-9.35,34.56V42m0-40V9.5m-2,0h4a2,2,0,0,1,2,2v21a2,2,0,0,1-2,2h-4a2,2,0,0,1-2-2v-21A2,2,0,0,1-11.35,9.5Z', + // Percent of the slider height + handleSize: '100%', + handleStyle: { + color: '#fff', + borderColor: '#ACB8D1' + }, + moveHandleSize: 7, + moveHandleIcon: 'path://M-320.9-50L-320.9-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-348-41-339-50-320.9-50z M-212.3-50L-212.3-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-239.4-41-230.4-50-212.3-50z M-103.7-50L-103.7-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-130.9-41-121.8-50-103.7-50z', + moveHandleStyle: { + color: '#D2DBEE', + opacity: 0.7 + }, + showDetail: true, + showDataShadow: 'auto', + realtime: true, + zoomLock: false, + textStyle: { + color: '#6E7079' + }, + brushSelect: true, + brushStyle: { + color: 'rgba(135,175,274,0.15)' + }, + emphasis: { + handleStyle: { + borderColor: '#8FB0F7' + }, + moveHandleStyle: { + color: '#8FB0F7' + } + } + }); + return SliderZoomModel; + }(DataZoomModel); + + var Rect$2 = Rect; // Constants + + var DEFAULT_LOCATION_EDGE_GAP = 7; + var DEFAULT_FRAME_BORDER_WIDTH = 1; + var DEFAULT_FILLER_SIZE = 30; + var DEFAULT_MOVE_HANDLE_SIZE = 7; + var HORIZONTAL = 'horizontal'; + var VERTICAL = 'vertical'; + var LABEL_GAP = 5; + var SHOW_DATA_SHADOW_SERIES_TYPE = ['line', 'bar', 'candlestick', 'scatter']; + var REALTIME_ANIMATION_CONFIG = { + easing: 'cubicOut', + duration: 100, + delay: 0 + }; + + var SliderZoomView = + /** @class */ + function (_super) { + __extends(SliderZoomView, _super); + + function SliderZoomView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SliderZoomView.type; + _this._displayables = {}; + return _this; + } + + SliderZoomView.prototype.init = function (ecModel, api) { + this.api = api; // A unique handler for each dataZoom component + + this._onBrush = bind(this._onBrush, this); + this._onBrushEnd = bind(this._onBrushEnd, this); + }; + + SliderZoomView.prototype.render = function (dataZoomModel, ecModel, api, payload) { + _super.prototype.render.apply(this, arguments); + + createOrUpdate(this, '_dispatchZoomAction', dataZoomModel.get('throttle'), 'fixRate'); + this._orient = dataZoomModel.getOrient(); + + if (dataZoomModel.get('show') === false) { + this.group.removeAll(); + return; + } + + if (dataZoomModel.noTarget()) { + this._clear(); + + this.group.removeAll(); + return; + } // Notice: this._resetInterval() should not be executed when payload.type + // is 'dataZoom', origin this._range should be maintained, otherwise 'pan' + // or 'zoom' info will be missed because of 'throttle' of this.dispatchAction, + + + if (!payload || payload.type !== 'dataZoom' || payload.from !== this.uid) { + this._buildView(); + } + + this._updateView(); + }; + + SliderZoomView.prototype.dispose = function () { + this._clear(); + + _super.prototype.dispose.apply(this, arguments); + }; + + SliderZoomView.prototype._clear = function () { + clear(this, '_dispatchZoomAction'); + var zr = this.api.getZr(); + zr.off('mousemove', this._onBrush); + zr.off('mouseup', this._onBrushEnd); + }; + + SliderZoomView.prototype._buildView = function () { + var thisGroup = this.group; + thisGroup.removeAll(); + this._brushing = false; + this._displayables.brushRect = null; + + this._resetLocation(); + + this._resetInterval(); + + var barGroup = this._displayables.sliderGroup = new Group(); + + this._renderBackground(); + + this._renderHandle(); + + this._renderDataShadow(); + + thisGroup.add(barGroup); + + this._positionGroup(); + }; + + SliderZoomView.prototype._resetLocation = function () { + var dataZoomModel = this.dataZoomModel; + var api = this.api; + var showMoveHandle = dataZoomModel.get('brushSelect'); + var moveHandleSize = showMoveHandle ? DEFAULT_MOVE_HANDLE_SIZE : 0; // If some of x/y/width/height are not specified, + // auto-adapt according to target grid. + + var coordRect = this._findCoordRect(); + + var ecSize = { + width: api.getWidth(), + height: api.getHeight() + }; // Default align by coordinate system rect. + + var positionInfo = this._orient === HORIZONTAL ? { + // Why using 'right', because right should be used in vertical, + // and it is better to be consistent for dealing with position param merge. + right: ecSize.width - coordRect.x - coordRect.width, + top: ecSize.height - DEFAULT_FILLER_SIZE - DEFAULT_LOCATION_EDGE_GAP - moveHandleSize, + width: coordRect.width, + height: DEFAULT_FILLER_SIZE + } : { + right: DEFAULT_LOCATION_EDGE_GAP, + top: coordRect.y, + width: DEFAULT_FILLER_SIZE, + height: coordRect.height + }; // Do not write back to option and replace value 'ph', because + // the 'ph' value should be recalculated when resize. + + var layoutParams = getLayoutParams(dataZoomModel.option); // Replace the placeholder value. + + each(['right', 'top', 'width', 'height'], function (name) { + if (layoutParams[name] === 'ph') { + layoutParams[name] = positionInfo[name]; + } + }); + var layoutRect = getLayoutRect(layoutParams, ecSize); + this._location = { + x: layoutRect.x, + y: layoutRect.y + }; + this._size = [layoutRect.width, layoutRect.height]; + this._orient === VERTICAL && this._size.reverse(); + }; + + SliderZoomView.prototype._positionGroup = function () { + var thisGroup = this.group; + var location = this._location; + var orient = this._orient; // Just use the first axis to determine mapping. + + var targetAxisModel = this.dataZoomModel.getFirstTargetAxisModel(); + var inverse = targetAxisModel && targetAxisModel.get('inverse'); + var sliderGroup = this._displayables.sliderGroup; + var otherAxisInverse = (this._dataShadowInfo || {}).otherAxisInverse; // Transform barGroup. + + sliderGroup.attr(orient === HORIZONTAL && !inverse ? { + scaleY: otherAxisInverse ? 1 : -1, + scaleX: 1 + } : orient === HORIZONTAL && inverse ? { + scaleY: otherAxisInverse ? 1 : -1, + scaleX: -1 + } : orient === VERTICAL && !inverse ? { + scaleY: otherAxisInverse ? -1 : 1, + scaleX: 1, + rotation: Math.PI / 2 + } // Dont use Math.PI, considering shadow direction. + : { + scaleY: otherAxisInverse ? -1 : 1, + scaleX: -1, + rotation: Math.PI / 2 + }); // Position barGroup + + var rect = thisGroup.getBoundingRect([sliderGroup]); + thisGroup.x = location.x - rect.x; + thisGroup.y = location.y - rect.y; + thisGroup.markRedraw(); + }; + + SliderZoomView.prototype._getViewExtent = function () { + return [0, this._size[0]]; + }; + + SliderZoomView.prototype._renderBackground = function () { + var dataZoomModel = this.dataZoomModel; + var size = this._size; + var barGroup = this._displayables.sliderGroup; + var brushSelect = dataZoomModel.get('brushSelect'); + barGroup.add(new Rect$2({ + silent: true, + shape: { + x: 0, + y: 0, + width: size[0], + height: size[1] + }, + style: { + fill: dataZoomModel.get('backgroundColor') + }, + z2: -40 + })); // Click panel, over shadow, below handles. + + var clickPanel = new Rect$2({ + shape: { + x: 0, + y: 0, + width: size[0], + height: size[1] + }, + style: { + fill: 'transparent' + }, + z2: 0, + onclick: bind(this._onClickPanel, this) + }); + var zr = this.api.getZr(); + + if (brushSelect) { + clickPanel.on('mousedown', this._onBrushStart, this); + clickPanel.cursor = 'crosshair'; + zr.on('mousemove', this._onBrush); + zr.on('mouseup', this._onBrushEnd); + } else { + zr.off('mousemove', this._onBrush); + zr.off('mouseup', this._onBrushEnd); + } + + barGroup.add(clickPanel); + }; + + SliderZoomView.prototype._renderDataShadow = function () { + var info = this._dataShadowInfo = this._prepareDataShadowInfo(); + + this._displayables.dataShadowSegs = []; + + if (!info) { + return; + } + + var size = this._size; + var oldSize = this._shadowSize || []; + var seriesModel = info.series; + var data = seriesModel.getRawData(); + var otherDim = seriesModel.getShadowDim ? seriesModel.getShadowDim() // @see candlestick + : info.otherDim; + + if (otherDim == null) { + return; + } + + var polygonPts = this._shadowPolygonPts; + var polylinePts = this._shadowPolylinePts; // Not re-render if data doesn't change. + + if (data !== this._shadowData || otherDim !== this._shadowDim || size[0] !== oldSize[0] || size[1] !== oldSize[1]) { + var otherDataExtent_1 = data.getDataExtent(otherDim); // Nice extent. + + var otherOffset = (otherDataExtent_1[1] - otherDataExtent_1[0]) * 0.3; + otherDataExtent_1 = [otherDataExtent_1[0] - otherOffset, otherDataExtent_1[1] + otherOffset]; + var otherShadowExtent_1 = [0, size[1]]; + var thisShadowExtent = [0, size[0]]; + var areaPoints_1 = [[size[0], 0], [0, 0]]; + var linePoints_1 = []; + var step_1 = thisShadowExtent[1] / (data.count() - 1); + var thisCoord_1 = 0; // Optimize for large data shadow + + var stride_1 = Math.round(data.count() / size[0]); + var lastIsEmpty_1; + data.each([otherDim], function (value, index) { + if (stride_1 > 0 && index % stride_1) { + thisCoord_1 += step_1; + return; + } // FIXME + // Should consider axis.min/axis.max when drawing dataShadow. + // FIXME + // 应该使用统一的空判断?还是在list里进行空判断? + + + var isEmpty = value == null || isNaN(value) || value === ''; // See #4235. + + var otherCoord = isEmpty ? 0 : linearMap(value, otherDataExtent_1, otherShadowExtent_1, true); // Attempt to draw data shadow precisely when there are empty value. + + if (isEmpty && !lastIsEmpty_1 && index) { + areaPoints_1.push([areaPoints_1[areaPoints_1.length - 1][0], 0]); + linePoints_1.push([linePoints_1[linePoints_1.length - 1][0], 0]); + } else if (!isEmpty && lastIsEmpty_1) { + areaPoints_1.push([thisCoord_1, 0]); + linePoints_1.push([thisCoord_1, 0]); + } + + areaPoints_1.push([thisCoord_1, otherCoord]); + linePoints_1.push([thisCoord_1, otherCoord]); + thisCoord_1 += step_1; + lastIsEmpty_1 = isEmpty; + }); + polygonPts = this._shadowPolygonPts = areaPoints_1; + polylinePts = this._shadowPolylinePts = linePoints_1; + } + + this._shadowData = data; + this._shadowDim = otherDim; + this._shadowSize = [size[0], size[1]]; + var dataZoomModel = this.dataZoomModel; + + function createDataShadowGroup(isSelectedArea) { + var model = dataZoomModel.getModel(isSelectedArea ? 'selectedDataBackground' : 'dataBackground'); + var group = new Group(); + var polygon = new Polygon({ + shape: { + points: polygonPts + }, + segmentIgnoreThreshold: 1, + style: model.getModel('areaStyle').getAreaStyle(), + silent: true, + z2: -20 + }); + var polyline = new Polyline({ + shape: { + points: polylinePts + }, + segmentIgnoreThreshold: 1, + style: model.getModel('lineStyle').getLineStyle(), + silent: true, + z2: -19 + }); + group.add(polygon); + group.add(polyline); + return group; + } // let dataBackgroundModel = dataZoomModel.getModel('dataBackground'); + + + for (var i = 0; i < 3; i++) { + var group = createDataShadowGroup(i === 1); + + this._displayables.sliderGroup.add(group); + + this._displayables.dataShadowSegs.push(group); + } + }; + + SliderZoomView.prototype._prepareDataShadowInfo = function () { + var dataZoomModel = this.dataZoomModel; + var showDataShadow = dataZoomModel.get('showDataShadow'); + + if (showDataShadow === false) { + return; + } // Find a representative series. + + + var result; + var ecModel = this.ecModel; + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + var seriesModels = dataZoomModel.getAxisProxy(axisDim, axisIndex).getTargetSeriesModels(); + each(seriesModels, function (seriesModel) { + if (result) { + return; + } + + if (showDataShadow !== true && indexOf(SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type')) < 0) { + return; + } + + var thisAxis = ecModel.getComponent(getAxisMainType(axisDim), axisIndex).axis; + var otherDim = getOtherDim(axisDim); + var otherAxisInverse; + var coordSys = seriesModel.coordinateSystem; + + if (otherDim != null && coordSys.getOtherAxis) { + otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse; + } + + otherDim = seriesModel.getData().mapDimension(otherDim); + result = { + thisAxis: thisAxis, + series: seriesModel, + thisDim: axisDim, + otherDim: otherDim, + otherAxisInverse: otherAxisInverse + }; + }, this); + }, this); + return result; + }; + + SliderZoomView.prototype._renderHandle = function () { + var thisGroup = this.group; + var displayables = this._displayables; + var handles = displayables.handles = [null, null]; + var handleLabels = displayables.handleLabels = [null, null]; + var sliderGroup = this._displayables.sliderGroup; + var size = this._size; + var dataZoomModel = this.dataZoomModel; + var api = this.api; + var borderRadius = dataZoomModel.get('borderRadius') || 0; + var brushSelect = dataZoomModel.get('brushSelect'); + var filler = displayables.filler = new Rect$2({ + silent: brushSelect, + style: { + fill: dataZoomModel.get('fillerColor') + }, + textConfig: { + position: 'inside' + } + }); + sliderGroup.add(filler); // Frame border. + + sliderGroup.add(new Rect$2({ + silent: true, + subPixelOptimize: true, + shape: { + x: 0, + y: 0, + width: size[0], + height: size[1], + r: borderRadius + }, + style: { + stroke: dataZoomModel.get('dataBackgroundColor') // deprecated option + || dataZoomModel.get('borderColor'), + lineWidth: DEFAULT_FRAME_BORDER_WIDTH, + fill: 'rgba(0,0,0,0)' + } + })); // Left and right handle to resize + + each([0, 1], function (handleIndex) { + var iconStr = dataZoomModel.get('handleIcon'); + + if (!symbolBuildProxies[iconStr] && iconStr.indexOf('path://') < 0 && iconStr.indexOf('image://') < 0) { + // Compatitable with the old icon parsers. Which can use a path string without path:// + iconStr = 'path://' + iconStr; + + if ("development" !== 'production') { + deprecateLog('handleIcon now needs \'path://\' prefix when using a path string'); + } + } + + var path = createSymbol(iconStr, -1, 0, 2, 2, null, true); + path.attr({ + cursor: getCursor(this._orient), + draggable: true, + drift: bind(this._onDragMove, this, handleIndex), + ondragend: bind(this._onDragEnd, this), + onmouseover: bind(this._showDataInfo, this, true), + onmouseout: bind(this._showDataInfo, this, false), + z2: 5 + }); + var bRect = path.getBoundingRect(); + var handleSize = dataZoomModel.get('handleSize'); + this._handleHeight = parsePercent$1(handleSize, this._size[1]); + this._handleWidth = bRect.width / bRect.height * this._handleHeight; + path.setStyle(dataZoomModel.getModel('handleStyle').getItemStyle()); + path.style.strokeNoScale = true; + path.rectHover = true; + path.ensureState('emphasis').style = dataZoomModel.getModel(['emphasis', 'handleStyle']).getItemStyle(); + enableHoverEmphasis(path); + var handleColor = dataZoomModel.get('handleColor'); // deprecated option + // Compatitable with previous version + + if (handleColor != null) { + path.style.fill = handleColor; + } + + sliderGroup.add(handles[handleIndex] = path); + var textStyleModel = dataZoomModel.getModel('textStyle'); + thisGroup.add(handleLabels[handleIndex] = new ZRText({ + silent: true, + invisible: true, + style: createTextStyle(textStyleModel, { + x: 0, + y: 0, + text: '', + verticalAlign: 'middle', + align: 'center', + fill: textStyleModel.getTextColor(), + font: textStyleModel.getFont() + }), + z2: 10 + })); + }, this); // Handle to move. Only visible when brushSelect is set true. + + var actualMoveZone = filler; + + if (brushSelect) { + var moveHandleHeight = parsePercent$1(dataZoomModel.get('moveHandleSize'), size[1]); + var moveHandle_1 = displayables.moveHandle = new Rect({ + style: dataZoomModel.getModel('moveHandleStyle').getItemStyle(), + silent: true, + shape: { + r: [0, 0, 2, 2], + y: size[1] - 0.5, + height: moveHandleHeight + } + }); + var iconSize = moveHandleHeight * 0.8; + var moveHandleIcon = displayables.moveHandleIcon = createSymbol(dataZoomModel.get('moveHandleIcon'), -iconSize / 2, -iconSize / 2, iconSize, iconSize, '#fff', true); + moveHandleIcon.silent = true; + moveHandleIcon.y = size[1] + moveHandleHeight / 2 - 0.5; + moveHandle_1.ensureState('emphasis').style = dataZoomModel.getModel(['emphasis', 'moveHandleStyle']).getItemStyle(); + var moveZoneExpandSize = Math.min(size[1] / 2, Math.max(moveHandleHeight, 10)); + actualMoveZone = displayables.moveZone = new Rect({ + invisible: true, + shape: { + y: size[1] - moveZoneExpandSize, + height: moveHandleHeight + moveZoneExpandSize + } + }); + actualMoveZone.on('mouseover', function () { + api.enterEmphasis(moveHandle_1); + }).on('mouseout', function () { + api.leaveEmphasis(moveHandle_1); + }); + sliderGroup.add(moveHandle_1); + sliderGroup.add(moveHandleIcon); + sliderGroup.add(actualMoveZone); + } + + actualMoveZone.attr({ + draggable: true, + cursor: getCursor(this._orient), + drift: bind(this._onDragMove, this, 'all'), + ondragstart: bind(this._showDataInfo, this, true), + ondragend: bind(this._onDragEnd, this), + onmouseover: bind(this._showDataInfo, this, true), + onmouseout: bind(this._showDataInfo, this, false) + }); + }; + + SliderZoomView.prototype._resetInterval = function () { + var range = this._range = this.dataZoomModel.getPercentRange(); + + var viewExtent = this._getViewExtent(); + + this._handleEnds = [linearMap(range[0], [0, 100], viewExtent, true), linearMap(range[1], [0, 100], viewExtent, true)]; + }; + + SliderZoomView.prototype._updateInterval = function (handleIndex, delta) { + var dataZoomModel = this.dataZoomModel; + var handleEnds = this._handleEnds; + + var viewExtend = this._getViewExtent(); + + var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); + var percentExtent = [0, 100]; + sliderMove(delta, handleEnds, viewExtend, dataZoomModel.get('zoomLock') ? 'all' : handleIndex, minMaxSpan.minSpan != null ? linearMap(minMaxSpan.minSpan, percentExtent, viewExtend, true) : null, minMaxSpan.maxSpan != null ? linearMap(minMaxSpan.maxSpan, percentExtent, viewExtend, true) : null); + var lastRange = this._range; + var range = this._range = asc([linearMap(handleEnds[0], viewExtend, percentExtent, true), linearMap(handleEnds[1], viewExtend, percentExtent, true)]); + return !lastRange || lastRange[0] !== range[0] || lastRange[1] !== range[1]; + }; + + SliderZoomView.prototype._updateView = function (nonRealtime) { + var displaybles = this._displayables; + var handleEnds = this._handleEnds; + var handleInterval = asc(handleEnds.slice()); + var size = this._size; + each([0, 1], function (handleIndex) { + // Handles + var handle = displaybles.handles[handleIndex]; + var handleHeight = this._handleHeight; + handle.attr({ + scaleX: handleHeight / 2, + scaleY: handleHeight / 2, + // This is a trick, by adding an extra tiny offset to let the default handle's end point align to the drag window. + // NOTE: It may affect some custom shapes a bit. But we prefer to have better result by default. + x: handleEnds[handleIndex] + (handleIndex ? -1 : 1), + y: size[1] / 2 - handleHeight / 2 + }); + }, this); // Filler + + displaybles.filler.setShape({ + x: handleInterval[0], + y: 0, + width: handleInterval[1] - handleInterval[0], + height: size[1] + }); + var viewExtent = { + x: handleInterval[0], + width: handleInterval[1] - handleInterval[0] + }; // Move handle + + if (displaybles.moveHandle) { + displaybles.moveHandle.setShape(viewExtent); + displaybles.moveZone.setShape(viewExtent); // Force update path on the invisible object + + displaybles.moveZone.getBoundingRect(); + displaybles.moveHandleIcon && displaybles.moveHandleIcon.attr('x', viewExtent.x + viewExtent.width / 2); + } // update clip path of shadow. + + + var dataShadowSegs = displaybles.dataShadowSegs; + var segIntervals = [0, handleInterval[0], handleInterval[1], size[0]]; + + for (var i = 0; i < dataShadowSegs.length; i++) { + var segGroup = dataShadowSegs[i]; + var clipPath = segGroup.getClipPath(); + + if (!clipPath) { + clipPath = new Rect(); + segGroup.setClipPath(clipPath); + } + + clipPath.setShape({ + x: segIntervals[i], + y: 0, + width: segIntervals[i + 1] - segIntervals[i], + height: size[1] + }); + } + + this._updateDataInfo(nonRealtime); + }; + + SliderZoomView.prototype._updateDataInfo = function (nonRealtime) { + var dataZoomModel = this.dataZoomModel; + var displaybles = this._displayables; + var handleLabels = displaybles.handleLabels; + var orient = this._orient; + var labelTexts = ['', '']; // FIXME + // date型,支持formatter,autoformatter(ec2 date.getAutoFormatter) + + if (dataZoomModel.get('showDetail')) { + var axisProxy = dataZoomModel.findRepresentativeAxisProxy(); + + if (axisProxy) { + var axis = axisProxy.getAxisModel().axis; + var range = this._range; + var dataInterval = nonRealtime // See #4434, data and axis are not processed and reset yet in non-realtime mode. + ? axisProxy.calculateDataWindow({ + start: range[0], + end: range[1] + }).valueWindow : axisProxy.getDataValueWindow(); + labelTexts = [this._formatLabel(dataInterval[0], axis), this._formatLabel(dataInterval[1], axis)]; + } + } + + var orderedHandleEnds = asc(this._handleEnds.slice()); + setLabel.call(this, 0); + setLabel.call(this, 1); + + function setLabel(handleIndex) { + // Label + // Text should not transform by barGroup. + // Ignore handlers transform + var barTransform = getTransform(displaybles.handles[handleIndex].parent, this.group); + var direction = transformDirection(handleIndex === 0 ? 'right' : 'left', barTransform); + var offset = this._handleWidth / 2 + LABEL_GAP; + var textPoint = applyTransform$1([orderedHandleEnds[handleIndex] + (handleIndex === 0 ? -offset : offset), this._size[1] / 2], barTransform); + handleLabels[handleIndex].setStyle({ + x: textPoint[0], + y: textPoint[1], + verticalAlign: orient === HORIZONTAL ? 'middle' : direction, + align: orient === HORIZONTAL ? direction : 'center', + text: labelTexts[handleIndex] + }); + } + }; + + SliderZoomView.prototype._formatLabel = function (value, axis) { + var dataZoomModel = this.dataZoomModel; + var labelFormatter = dataZoomModel.get('labelFormatter'); + var labelPrecision = dataZoomModel.get('labelPrecision'); + + if (labelPrecision == null || labelPrecision === 'auto') { + labelPrecision = axis.getPixelPrecision(); + } + + var valueStr = value == null || isNaN(value) ? '' // FIXME Glue code + : axis.type === 'category' || axis.type === 'time' ? axis.scale.getLabel({ + value: Math.round(value) + }) // param of toFixed should less then 20. + : value.toFixed(Math.min(labelPrecision, 20)); + return isFunction(labelFormatter) ? labelFormatter(value, valueStr) : isString(labelFormatter) ? labelFormatter.replace('{value}', valueStr) : valueStr; + }; + /** + * @param showOrHide true: show, false: hide + */ + + + SliderZoomView.prototype._showDataInfo = function (showOrHide) { + // Always show when drgging. + showOrHide = this._dragging || showOrHide; + var displayables = this._displayables; + var handleLabels = displayables.handleLabels; + handleLabels[0].attr('invisible', !showOrHide); + handleLabels[1].attr('invisible', !showOrHide); // Highlight move handle + + displayables.moveHandle && this.api[showOrHide ? 'enterEmphasis' : 'leaveEmphasis'](displayables.moveHandle, 1); + }; + + SliderZoomView.prototype._onDragMove = function (handleIndex, dx, dy, event) { + this._dragging = true; // For mobile device, prevent screen slider on the button. + + stop(event.event); // Transform dx, dy to bar coordination. + + var barTransform = this._displayables.sliderGroup.getLocalTransform(); + + var vertex = applyTransform$1([dx, dy], barTransform, true); + + var changed = this._updateInterval(handleIndex, vertex[0]); + + var realtime = this.dataZoomModel.get('realtime'); + + this._updateView(!realtime); // Avoid dispatch dataZoom repeatly but range not changed, + // which cause bad visual effect when progressive enabled. + + + changed && realtime && this._dispatchZoomAction(true); + }; + + SliderZoomView.prototype._onDragEnd = function () { + this._dragging = false; + + this._showDataInfo(false); // While in realtime mode and stream mode, dispatch action when + // drag end will cause the whole view rerender, which is unnecessary. + + + var realtime = this.dataZoomModel.get('realtime'); + !realtime && this._dispatchZoomAction(false); + }; + + SliderZoomView.prototype._onClickPanel = function (e) { + var size = this._size; + + var localPoint = this._displayables.sliderGroup.transformCoordToLocal(e.offsetX, e.offsetY); + + if (localPoint[0] < 0 || localPoint[0] > size[0] || localPoint[1] < 0 || localPoint[1] > size[1]) { + return; + } + + var handleEnds = this._handleEnds; + var center = (handleEnds[0] + handleEnds[1]) / 2; + + var changed = this._updateInterval('all', localPoint[0] - center); + + this._updateView(); + + changed && this._dispatchZoomAction(false); + }; + + SliderZoomView.prototype._onBrushStart = function (e) { + var x = e.offsetX; + var y = e.offsetY; + this._brushStart = new Point(x, y); + this._brushing = true; + this._brushStartTime = +new Date(); // this._updateBrushRect(x, y); + }; + + SliderZoomView.prototype._onBrushEnd = function (e) { + if (!this._brushing) { + return; + } + + var brushRect = this._displayables.brushRect; + this._brushing = false; + + if (!brushRect) { + return; + } + + brushRect.attr('ignore', true); + var brushShape = brushRect.shape; + var brushEndTime = +new Date(); // console.log(brushEndTime - this._brushStartTime); + + if (brushEndTime - this._brushStartTime < 200 && Math.abs(brushShape.width) < 5) { + // Will treat it as a click + return; + } + + var viewExtend = this._getViewExtent(); + + var percentExtent = [0, 100]; + this._range = asc([linearMap(brushShape.x, viewExtend, percentExtent, true), linearMap(brushShape.x + brushShape.width, viewExtend, percentExtent, true)]); + this._handleEnds = [brushShape.x, brushShape.x + brushShape.width]; + + this._updateView(); + + this._dispatchZoomAction(false); + }; + + SliderZoomView.prototype._onBrush = function (e) { + if (this._brushing) { + // For mobile device, prevent screen slider on the button. + stop(e.event); + + this._updateBrushRect(e.offsetX, e.offsetY); + } + }; + + SliderZoomView.prototype._updateBrushRect = function (mouseX, mouseY) { + var displayables = this._displayables; + var dataZoomModel = this.dataZoomModel; + var brushRect = displayables.brushRect; + + if (!brushRect) { + brushRect = displayables.brushRect = new Rect$2({ + silent: true, + style: dataZoomModel.getModel('brushStyle').getItemStyle() + }); + displayables.sliderGroup.add(brushRect); + } + + brushRect.attr('ignore', false); + var brushStart = this._brushStart; + var sliderGroup = this._displayables.sliderGroup; + var endPoint = sliderGroup.transformCoordToLocal(mouseX, mouseY); + var startPoint = sliderGroup.transformCoordToLocal(brushStart.x, brushStart.y); + var size = this._size; + endPoint[0] = Math.max(Math.min(size[0], endPoint[0]), 0); + brushRect.setShape({ + x: startPoint[0], + y: 0, + width: endPoint[0] - startPoint[0], + height: size[1] + }); + }; + /** + * This action will be throttled. + */ + + + SliderZoomView.prototype._dispatchZoomAction = function (realtime) { + var range = this._range; + this.api.dispatchAction({ + type: 'dataZoom', + from: this.uid, + dataZoomId: this.dataZoomModel.id, + animation: realtime ? REALTIME_ANIMATION_CONFIG : null, + start: range[0], + end: range[1] + }); + }; + + SliderZoomView.prototype._findCoordRect = function () { + // Find the grid coresponding to the first axis referred by dataZoom. + var rect; + var coordSysInfoList = collectReferCoordSysModelInfo(this.dataZoomModel).infoList; + + if (!rect && coordSysInfoList.length) { + var coordSys = coordSysInfoList[0].model.coordinateSystem; + rect = coordSys.getRect && coordSys.getRect(); + } + + if (!rect) { + var width = this.api.getWidth(); + var height = this.api.getHeight(); + rect = { + x: width * 0.2, + y: height * 0.2, + width: width * 0.6, + height: height * 0.6 + }; + } + + return rect; + }; + + SliderZoomView.type = 'dataZoom.slider'; + return SliderZoomView; + }(DataZoomView); + + function getOtherDim(thisDim) { + // FIXME + // 这个逻辑和getOtherAxis里一致,但是写在这里是否不好 + var map = { + x: 'y', + y: 'x', + radius: 'angle', + angle: 'radius' + }; + return map[thisDim]; + } + + function getCursor(orient) { + return orient === 'vertical' ? 'ns-resize' : 'ew-resize'; + } + + function install$L(registers) { + registers.registerComponentModel(SliderZoomModel); + registers.registerComponentView(SliderZoomView); + installCommon(registers); + } + + function install$M(registers) { + use(install$K); + use(install$L); // Do not install './dataZoomSelect', + // since it only work for toolbox dataZoom. + } + + var visualDefault = { + /** + * @public + */ + get: function (visualType, key, isCategory) { + var value = clone((defaultOption$1[visualType] || {})[key]); + return isCategory ? isArray(value) ? value[value.length - 1] : value : value; + } + }; + var defaultOption$1 = { + color: { + active: ['#006edd', '#e0ffff'], + inactive: ['rgba(0,0,0,0)'] + }, + colorHue: { + active: [0, 360], + inactive: [0, 0] + }, + colorSaturation: { + active: [0.3, 1], + inactive: [0, 0] + }, + colorLightness: { + active: [0.9, 0.5], + inactive: [0, 0] + }, + colorAlpha: { + active: [0.3, 1], + inactive: [0, 0] + }, + opacity: { + active: [0.3, 1], + inactive: [0, 0] + }, + symbol: { + active: ['circle', 'roundRect', 'diamond'], + inactive: ['none'] + }, + symbolSize: { + active: [10, 50], + inactive: [0, 0] + } + }; + + var mapVisual$1 = VisualMapping.mapVisual; + var eachVisual = VisualMapping.eachVisual; + var isArray$1 = isArray; + var each$d = each; + var asc$2 = asc; + var linearMap$1 = linearMap; + + var VisualMapModel = + /** @class */ + function (_super) { + __extends(VisualMapModel, _super); + + function VisualMapModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = VisualMapModel.type; + _this.stateList = ['inRange', 'outOfRange']; + _this.replacableOptionKeys = ['inRange', 'outOfRange', 'target', 'controller', 'color']; + _this.layoutMode = { + type: 'box', + ignoreSize: true + }; + /** + * [lowerBound, upperBound] + */ + + _this.dataBound = [-Infinity, Infinity]; + _this.targetVisuals = {}; + _this.controllerVisuals = {}; + return _this; + } + + VisualMapModel.prototype.init = function (option, parentModel, ecModel) { + this.mergeDefaultAndTheme(option, ecModel); + }; + /** + * @protected + */ + + + VisualMapModel.prototype.optionUpdated = function (newOption, isInit) { + var thisOption = this.option; + !isInit && replaceVisualOption(thisOption, newOption, this.replacableOptionKeys); + this.textStyleModel = this.getModel('textStyle'); + this.resetItemSize(); + this.completeVisualOption(); + }; + /** + * @protected + */ + + + VisualMapModel.prototype.resetVisual = function (supplementVisualOption) { + var stateList = this.stateList; + supplementVisualOption = bind(supplementVisualOption, this); + this.controllerVisuals = createVisualMappings(this.option.controller, stateList, supplementVisualOption); + this.targetVisuals = createVisualMappings(this.option.target, stateList, supplementVisualOption); + }; + /** + * @public + */ + + + VisualMapModel.prototype.getItemSymbol = function () { + return null; + }; + /** + * @protected + * @return {Array.} An array of series indices. + */ + + + VisualMapModel.prototype.getTargetSeriesIndices = function () { + var optionSeriesIndex = this.option.seriesIndex; + var seriesIndices = []; + + if (optionSeriesIndex == null || optionSeriesIndex === 'all') { + this.ecModel.eachSeries(function (seriesModel, index) { + seriesIndices.push(index); + }); + } else { + seriesIndices = normalizeToArray(optionSeriesIndex); + } + + return seriesIndices; + }; + /** + * @public + */ + + + VisualMapModel.prototype.eachTargetSeries = function (callback, context) { + each(this.getTargetSeriesIndices(), function (seriesIndex) { + var seriesModel = this.ecModel.getSeriesByIndex(seriesIndex); + + if (seriesModel) { + callback.call(context, seriesModel); + } + }, this); + }; + /** + * @pubilc + */ + + + VisualMapModel.prototype.isTargetSeries = function (seriesModel) { + var is = false; + this.eachTargetSeries(function (model) { + model === seriesModel && (is = true); + }); + return is; + }; + /** + * @example + * this.formatValueText(someVal); // format single numeric value to text. + * this.formatValueText(someVal, true); // format single category value to text. + * this.formatValueText([min, max]); // format numeric min-max to text. + * this.formatValueText([this.dataBound[0], max]); // using data lower bound. + * this.formatValueText([min, this.dataBound[1]]); // using data upper bound. + * + * @param value Real value, or this.dataBound[0 or 1]. + * @param isCategory Only available when value is number. + * @param edgeSymbols Open-close symbol when value is interval. + * @protected + */ + + + VisualMapModel.prototype.formatValueText = function (value, isCategory, edgeSymbols) { + var option = this.option; + var precision = option.precision; + var dataBound = this.dataBound; + var formatter = option.formatter; + var isMinMax; + edgeSymbols = edgeSymbols || ['<', '>']; + + if (isArray(value)) { + value = value.slice(); + isMinMax = true; + } + + var textValue = isCategory ? value // Value is string when isCategory + : isMinMax ? [toFixed(value[0]), toFixed(value[1])] : toFixed(value); + + if (isString(formatter)) { + return formatter.replace('{value}', isMinMax ? textValue[0] : textValue).replace('{value2}', isMinMax ? textValue[1] : textValue); + } else if (isFunction(formatter)) { + return isMinMax ? formatter(value[0], value[1]) : formatter(value); + } + + if (isMinMax) { + if (value[0] === dataBound[0]) { + return edgeSymbols[0] + ' ' + textValue[1]; + } else if (value[1] === dataBound[1]) { + return edgeSymbols[1] + ' ' + textValue[0]; + } else { + return textValue[0] + ' - ' + textValue[1]; + } + } else { + // Format single value (includes category case). + return textValue; + } + + function toFixed(val) { + return val === dataBound[0] ? 'min' : val === dataBound[1] ? 'max' : (+val).toFixed(Math.min(precision, 20)); + } + }; + /** + * @protected + */ + + + VisualMapModel.prototype.resetExtent = function () { + var thisOption = this.option; // Can not calculate data extent by data here. + // Because series and data may be modified in processing stage. + // So we do not support the feature "auto min/max". + + var extent = asc$2([thisOption.min, thisOption.max]); + this._dataExtent = extent; + }; + /** + * PENDING: + * delete this method if no outer usage. + * + * Return Concrete dimention. If return null/undefined, no dimension used. + */ + // getDataDimension(data: SeriesData) { + // const optDim = this.option.dimension; + // if (optDim != null) { + // return data.getDimension(optDim); + // } + // const dimNames = data.dimensions; + // for (let i = dimNames.length - 1; i >= 0; i--) { + // const dimName = dimNames[i]; + // const dimInfo = data.getDimensionInfo(dimName); + // if (!dimInfo.isCalculationCoord) { + // return dimName; + // } + // } + // } + + + VisualMapModel.prototype.getDataDimensionIndex = function (data) { + var optDim = this.option.dimension; + + if (optDim != null) { + return data.getDimensionIndex(optDim); + } + + var dimNames = data.dimensions; + + for (var i = dimNames.length - 1; i >= 0; i--) { + var dimName = dimNames[i]; + var dimInfo = data.getDimensionInfo(dimName); + + if (!dimInfo.isCalculationCoord) { + return dimInfo.storeDimIndex; + } + } + }; + + VisualMapModel.prototype.getExtent = function () { + return this._dataExtent.slice(); + }; + + VisualMapModel.prototype.completeVisualOption = function () { + var ecModel = this.ecModel; + var thisOption = this.option; + var base = { + inRange: thisOption.inRange, + outOfRange: thisOption.outOfRange + }; + var target = thisOption.target || (thisOption.target = {}); + var controller = thisOption.controller || (thisOption.controller = {}); + merge(target, base); // Do not override + + merge(controller, base); // Do not override + + var isCategory = this.isCategory(); + completeSingle.call(this, target); + completeSingle.call(this, controller); + completeInactive.call(this, target, 'inRange', 'outOfRange'); // completeInactive.call(this, target, 'outOfRange', 'inRange'); + + completeController.call(this, controller); + + function completeSingle(base) { + // Compatible with ec2 dataRange.color. + // The mapping order of dataRange.color is: [high value, ..., low value] + // whereas inRange.color and outOfRange.color is [low value, ..., high value] + // Notice: ec2 has no inverse. + if (isArray$1(thisOption.color) // If there has been inRange: {symbol: ...}, adding color is a mistake. + // So adding color only when no inRange defined. + && !base.inRange) { + base.inRange = { + color: thisOption.color.slice().reverse() + }; + } // Compatible with previous logic, always give a defautl color, otherwise + // simple config with no inRange and outOfRange will not work. + // Originally we use visualMap.color as the default color, but setOption at + // the second time the default color will be erased. So we change to use + // constant DEFAULT_COLOR. + // If user do not want the default color, set inRange: {color: null}. + + + base.inRange = base.inRange || { + color: ecModel.get('gradientColor') + }; + } + + function completeInactive(base, stateExist, stateAbsent) { + var optExist = base[stateExist]; + var optAbsent = base[stateAbsent]; + + if (optExist && !optAbsent) { + optAbsent = base[stateAbsent] = {}; + each$d(optExist, function (visualData, visualType) { + if (!VisualMapping.isValidType(visualType)) { + return; + } + + var defa = visualDefault.get(visualType, 'inactive', isCategory); + + if (defa != null) { + optAbsent[visualType] = defa; // Compatibable with ec2: + // Only inactive color to rgba(0,0,0,0) can not + // make label transparent, so use opacity also. + + if (visualType === 'color' && !optAbsent.hasOwnProperty('opacity') && !optAbsent.hasOwnProperty('colorAlpha')) { + optAbsent.opacity = [0, 0]; + } + } + }); + } + } + + function completeController(controller) { + var symbolExists = (controller.inRange || {}).symbol || (controller.outOfRange || {}).symbol; + var symbolSizeExists = (controller.inRange || {}).symbolSize || (controller.outOfRange || {}).symbolSize; + var inactiveColor = this.get('inactiveColor'); + var itemSymbol = this.getItemSymbol(); + var defaultSymbol = itemSymbol || 'roundRect'; + each$d(this.stateList, function (state) { + var itemSize = this.itemSize; + var visuals = controller[state]; // Set inactive color for controller if no other color + // attr (like colorAlpha) specified. + + if (!visuals) { + visuals = controller[state] = { + color: isCategory ? inactiveColor : [inactiveColor] + }; + } // Consistent symbol and symbolSize if not specified. + + + if (visuals.symbol == null) { + visuals.symbol = symbolExists && clone(symbolExists) || (isCategory ? defaultSymbol : [defaultSymbol]); + } + + if (visuals.symbolSize == null) { + visuals.symbolSize = symbolSizeExists && clone(symbolSizeExists) || (isCategory ? itemSize[0] : [itemSize[0], itemSize[0]]); + } // Filter none + + + visuals.symbol = mapVisual$1(visuals.symbol, function (symbol) { + return symbol === 'none' ? defaultSymbol : symbol; + }); // Normalize symbolSize + + var symbolSize = visuals.symbolSize; + + if (symbolSize != null) { + var max_1 = -Infinity; // symbolSize can be object when categories defined. + + eachVisual(symbolSize, function (value) { + value > max_1 && (max_1 = value); + }); + visuals.symbolSize = mapVisual$1(symbolSize, function (value) { + return linearMap$1(value, [0, max_1], [0, itemSize[0]], true); + }); + } + }, this); + } + }; + + VisualMapModel.prototype.resetItemSize = function () { + this.itemSize = [parseFloat(this.get('itemWidth')), parseFloat(this.get('itemHeight'))]; + }; + + VisualMapModel.prototype.isCategory = function () { + return !!this.option.categories; + }; + /** + * @public + * @abstract + */ + + + VisualMapModel.prototype.setSelected = function (selected) {}; + + VisualMapModel.prototype.getSelected = function () { + return null; + }; + /** + * @public + * @abstract + */ + + + VisualMapModel.prototype.getValueState = function (value) { + return null; + }; + /** + * FIXME + * Do not publish to thirt-part-dev temporarily + * util the interface is stable. (Should it return + * a function but not visual meta?) + * + * @pubilc + * @abstract + * @param getColorVisual + * params: value, valueState + * return: color + * @return {Object} visualMeta + * should includes {stops, outerColors} + * outerColor means [colorBeyondMinValue, colorBeyondMaxValue] + */ + + + VisualMapModel.prototype.getVisualMeta = function (getColorVisual) { + return null; + }; + + VisualMapModel.type = 'visualMap'; + VisualMapModel.dependencies = ['series']; + VisualMapModel.defaultOption = { + show: true, + // zlevel: 0, + z: 4, + seriesIndex: 'all', + min: 0, + max: 200, + left: 0, + right: null, + top: null, + bottom: 0, + itemWidth: null, + itemHeight: null, + inverse: false, + orient: 'vertical', + backgroundColor: 'rgba(0,0,0,0)', + borderColor: '#ccc', + contentColor: '#5793f3', + inactiveColor: '#aaa', + borderWidth: 0, + padding: 5, + // 接受数组分别设定上右下左边距,同css + textGap: 10, + precision: 0, + textStyle: { + color: '#333' // 值域文字颜色 + + } + }; + return VisualMapModel; + }(ComponentModel); + + var DEFAULT_BAR_BOUND = [20, 140]; + + var ContinuousModel = + /** @class */ + function (_super) { + __extends(ContinuousModel, _super); + + function ContinuousModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ContinuousModel.type; + return _this; + } + /** + * @override + */ + + + ContinuousModel.prototype.optionUpdated = function (newOption, isInit) { + _super.prototype.optionUpdated.apply(this, arguments); + + this.resetExtent(); + this.resetVisual(function (mappingOption) { + mappingOption.mappingMethod = 'linear'; + mappingOption.dataExtent = this.getExtent(); + }); + + this._resetRange(); + }; + /** + * @protected + * @override + */ + + + ContinuousModel.prototype.resetItemSize = function () { + _super.prototype.resetItemSize.apply(this, arguments); + + var itemSize = this.itemSize; + (itemSize[0] == null || isNaN(itemSize[0])) && (itemSize[0] = DEFAULT_BAR_BOUND[0]); + (itemSize[1] == null || isNaN(itemSize[1])) && (itemSize[1] = DEFAULT_BAR_BOUND[1]); + }; + /** + * @private + */ + + + ContinuousModel.prototype._resetRange = function () { + var dataExtent = this.getExtent(); + var range = this.option.range; + + if (!range || range.auto) { + // `range` should always be array (so we dont use other + // value like 'auto') for user-friend. (consider getOption). + dataExtent.auto = 1; + this.option.range = dataExtent; + } else if (isArray(range)) { + if (range[0] > range[1]) { + range.reverse(); + } + + range[0] = Math.max(range[0], dataExtent[0]); + range[1] = Math.min(range[1], dataExtent[1]); + } + }; + /** + * @protected + * @override + */ + + + ContinuousModel.prototype.completeVisualOption = function () { + _super.prototype.completeVisualOption.apply(this, arguments); + + each(this.stateList, function (state) { + var symbolSize = this.option.controller[state].symbolSize; + + if (symbolSize && symbolSize[0] !== symbolSize[1]) { + symbolSize[0] = symbolSize[1] / 3; // For good looking. + } + }, this); + }; + /** + * @override + */ + + + ContinuousModel.prototype.setSelected = function (selected) { + this.option.range = selected.slice(); + + this._resetRange(); + }; + /** + * @public + */ + + + ContinuousModel.prototype.getSelected = function () { + var dataExtent = this.getExtent(); + var dataInterval = asc((this.get('range') || []).slice()); // Clamp + + dataInterval[0] > dataExtent[1] && (dataInterval[0] = dataExtent[1]); + dataInterval[1] > dataExtent[1] && (dataInterval[1] = dataExtent[1]); + dataInterval[0] < dataExtent[0] && (dataInterval[0] = dataExtent[0]); + dataInterval[1] < dataExtent[0] && (dataInterval[1] = dataExtent[0]); + return dataInterval; + }; + /** + * @override + */ + + + ContinuousModel.prototype.getValueState = function (value) { + var range = this.option.range; + var dataExtent = this.getExtent(); // When range[0] === dataExtent[0], any value larger than dataExtent[0] maps to 'inRange'. + // range[1] is processed likewise. + + return (range[0] <= dataExtent[0] || range[0] <= value) && (range[1] >= dataExtent[1] || value <= range[1]) ? 'inRange' : 'outOfRange'; + }; + + ContinuousModel.prototype.findTargetDataIndices = function (range) { + var result = []; + this.eachTargetSeries(function (seriesModel) { + var dataIndices = []; + var data = seriesModel.getData(); + data.each(this.getDataDimensionIndex(data), function (value, dataIndex) { + range[0] <= value && value <= range[1] && dataIndices.push(dataIndex); + }, this); + result.push({ + seriesId: seriesModel.id, + dataIndex: dataIndices + }); + }, this); + return result; + }; + /** + * @implement + */ + + + ContinuousModel.prototype.getVisualMeta = function (getColorVisual) { + var oVals = getColorStopValues(this, 'outOfRange', this.getExtent()); + var iVals = getColorStopValues(this, 'inRange', this.option.range.slice()); + var stops = []; + + function setStop(value, valueState) { + stops.push({ + value: value, + color: getColorVisual(value, valueState) + }); + } // Format to: outOfRange -- inRange -- outOfRange. + + + var iIdx = 0; + var oIdx = 0; + var iLen = iVals.length; + var oLen = oVals.length; + + for (; oIdx < oLen && (!iVals.length || oVals[oIdx] <= iVals[0]); oIdx++) { + // If oVal[oIdx] === iVals[iIdx], oVal[oIdx] should be ignored. + if (oVals[oIdx] < iVals[iIdx]) { + setStop(oVals[oIdx], 'outOfRange'); + } + } + + for (var first = 1; iIdx < iLen; iIdx++, first = 0) { + // If range is full, value beyond min, max will be clamped. + // make a singularity + first && stops.length && setStop(iVals[iIdx], 'outOfRange'); + setStop(iVals[iIdx], 'inRange'); + } + + for (var first = 1; oIdx < oLen; oIdx++) { + if (!iVals.length || iVals[iVals.length - 1] < oVals[oIdx]) { + // make a singularity + if (first) { + stops.length && setStop(stops[stops.length - 1].value, 'outOfRange'); + first = 0; + } + + setStop(oVals[oIdx], 'outOfRange'); + } + } + + var stopsLen = stops.length; + return { + stops: stops, + outerColors: [stopsLen ? stops[0].color : 'transparent', stopsLen ? stops[stopsLen - 1].color : 'transparent'] + }; + }; + + ContinuousModel.type = 'visualMap.continuous'; + ContinuousModel.defaultOption = inheritDefaultOption(VisualMapModel.defaultOption, { + align: 'auto', + calculable: false, + hoverLink: true, + realtime: true, + handleIcon: 'path://M-11.39,9.77h0a3.5,3.5,0,0,1-3.5,3.5h-22a3.5,3.5,0,0,1-3.5-3.5h0a3.5,3.5,0,0,1,3.5-3.5h22A3.5,3.5,0,0,1-11.39,9.77Z', + handleSize: '120%', + handleStyle: { + borderColor: '#fff', + borderWidth: 1 + }, + indicatorIcon: 'circle', + indicatorSize: '50%', + indicatorStyle: { + borderColor: '#fff', + borderWidth: 2, + shadowBlur: 2, + shadowOffsetX: 1, + shadowOffsetY: 1, + shadowColor: 'rgba(0,0,0,0.2)' + } // emphasis: { + // handleStyle: { + // shadowBlur: 3, + // shadowOffsetX: 1, + // shadowOffsetY: 1, + // shadowColor: 'rgba(0,0,0,0.2)' + // } + // } + + }); + return ContinuousModel; + }(VisualMapModel); + + function getColorStopValues(visualMapModel, valueState, dataExtent) { + if (dataExtent[0] === dataExtent[1]) { + return dataExtent.slice(); + } // When using colorHue mapping, it is not linear color any more. + // Moreover, canvas gradient seems not to be accurate linear. + // FIXME + // Should be arbitrary value 100? or based on pixel size? + + + var count = 200; + var step = (dataExtent[1] - dataExtent[0]) / count; + var value = dataExtent[0]; + var stopValues = []; + + for (var i = 0; i <= count && value < dataExtent[1]; i++) { + stopValues.push(value); + value += step; + } + + stopValues.push(dataExtent[1]); + return stopValues; + } + + var VisualMapView = + /** @class */ + function (_super) { + __extends(VisualMapView, _super); + + function VisualMapView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = VisualMapView.type; + _this.autoPositionValues = { + left: 1, + right: 1, + top: 1, + bottom: 1 + }; + return _this; + } + + VisualMapView.prototype.init = function (ecModel, api) { + this.ecModel = ecModel; + this.api = api; + }; + /** + * @protected + */ + + + VisualMapView.prototype.render = function (visualMapModel, ecModel, api, payload // TODO: TYPE + ) { + this.visualMapModel = visualMapModel; + + if (visualMapModel.get('show') === false) { + this.group.removeAll(); + return; + } + + this.doRender(visualMapModel, ecModel, api, payload); + }; + /** + * @protected + */ + + + VisualMapView.prototype.renderBackground = function (group) { + var visualMapModel = this.visualMapModel; + var padding = normalizeCssArray$1(visualMapModel.get('padding') || 0); + var rect = group.getBoundingRect(); + group.add(new Rect({ + z2: -1, + silent: true, + shape: { + x: rect.x - padding[3], + y: rect.y - padding[0], + width: rect.width + padding[3] + padding[1], + height: rect.height + padding[0] + padding[2] + }, + style: { + fill: visualMapModel.get('backgroundColor'), + stroke: visualMapModel.get('borderColor'), + lineWidth: visualMapModel.get('borderWidth') + } + })); + }; + /** + * @protected + * @param targetValue can be Infinity or -Infinity + * @param visualCluster Only can be 'color' 'opacity' 'symbol' 'symbolSize' + * @param opts + * @param opts.forceState Specify state, instead of using getValueState method. + * @param opts.convertOpacityToAlpha For color gradient in controller widget. + * @return {*} Visual value. + */ + + + VisualMapView.prototype.getControllerVisual = function (targetValue, visualCluster, opts) { + opts = opts || {}; + var forceState = opts.forceState; + var visualMapModel = this.visualMapModel; + var visualObj = {}; // Default values. + + if (visualCluster === 'color') { + var defaultColor = visualMapModel.get('contentColor'); + visualObj.color = defaultColor; + } + + function getter(key) { + return visualObj[key]; + } + + function setter(key, value) { + visualObj[key] = value; + } + + var mappings = visualMapModel.controllerVisuals[forceState || visualMapModel.getValueState(targetValue)]; + var visualTypes = VisualMapping.prepareVisualTypes(mappings); + each(visualTypes, function (type) { + var visualMapping = mappings[type]; + + if (opts.convertOpacityToAlpha && type === 'opacity') { + type = 'colorAlpha'; + visualMapping = mappings.__alphaForOpacity; + } + + if (VisualMapping.dependsOn(type, visualCluster)) { + visualMapping && visualMapping.applyVisual(targetValue, getter, setter); + } + }); + return visualObj[visualCluster]; + }; + + VisualMapView.prototype.positionGroup = function (group) { + var model = this.visualMapModel; + var api = this.api; + positionElement(group, model.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + }; + + VisualMapView.prototype.doRender = function (visualMapModel, ecModel, api, payload) {}; + + VisualMapView.type = 'visualMap'; + return VisualMapView; + }(ComponentView); + + var paramsSet = [['left', 'right', 'width'], ['top', 'bottom', 'height']]; + /** + * @param visualMapModel + * @param api + * @param itemSize always [short, long] + * @return {string} 'left' or 'right' or 'top' or 'bottom' + */ + + function getItemAlign(visualMapModel, api, itemSize) { + var modelOption = visualMapModel.option; + var itemAlign = modelOption.align; + + if (itemAlign != null && itemAlign !== 'auto') { + return itemAlign; + } // Auto decision align. + + + var ecSize = { + width: api.getWidth(), + height: api.getHeight() + }; + var realIndex = modelOption.orient === 'horizontal' ? 1 : 0; + var reals = paramsSet[realIndex]; + var fakeValue = [0, null, 10]; + var layoutInput = {}; + + for (var i = 0; i < 3; i++) { + layoutInput[paramsSet[1 - realIndex][i]] = fakeValue[i]; + layoutInput[reals[i]] = i === 2 ? itemSize[0] : modelOption[reals[i]]; + } + + var rParam = [['x', 'width', 3], ['y', 'height', 0]][realIndex]; + var rect = getLayoutRect(layoutInput, ecSize, modelOption.padding); + return reals[(rect.margin[rParam[2]] || 0) + rect[rParam[0]] + rect[rParam[1]] * 0.5 < ecSize[rParam[1]] * 0.5 ? 0 : 1]; + } + /** + * Prepare dataIndex for outside usage, where dataIndex means rawIndex, and + * dataIndexInside means filtered index. + */ + // TODO: TYPE more specified payload types. + + function makeHighDownBatch(batch, visualMapModel) { + each(batch || [], function (batchItem) { + if (batchItem.dataIndex != null) { + batchItem.dataIndexInside = batchItem.dataIndex; + batchItem.dataIndex = null; + } + + batchItem.highlightKey = 'visualMap' + (visualMapModel ? visualMapModel.componentIndex : ''); + }); + return batch; + } + + var linearMap$2 = linearMap; + var each$e = each; + var mathMin$a = Math.min; + var mathMax$a = Math.max; // Arbitrary value + + var HOVER_LINK_SIZE = 12; + var HOVER_LINK_OUT = 6; // Notice: + // Any "interval" should be by the order of [low, high]. + // "handle0" (handleIndex === 0) maps to + // low data value: this._dataInterval[0] and has low coord. + // "handle1" (handleIndex === 1) maps to + // high data value: this._dataInterval[1] and has high coord. + // The logic of transform is implemented in this._createBarGroup. + + var ContinuousView = + /** @class */ + function (_super) { + __extends(ContinuousView, _super); + + function ContinuousView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ContinuousView.type; + _this._shapes = {}; + _this._dataInterval = []; + _this._handleEnds = []; + _this._hoverLinkDataIndices = []; + return _this; + } + + ContinuousView.prototype.doRender = function (visualMapModel, ecModel, api, payload) { + this._api = api; + + if (!payload || payload.type !== 'selectDataRange' || payload.from !== this.uid) { + this._buildView(); + } + }; + + ContinuousView.prototype._buildView = function () { + this.group.removeAll(); + var visualMapModel = this.visualMapModel; + var thisGroup = this.group; + this._orient = visualMapModel.get('orient'); + this._useHandle = visualMapModel.get('calculable'); + + this._resetInterval(); + + this._renderBar(thisGroup); + + var dataRangeText = visualMapModel.get('text'); + + this._renderEndsText(thisGroup, dataRangeText, 0); + + this._renderEndsText(thisGroup, dataRangeText, 1); // Do this for background size calculation. + + + this._updateView(true); // After updating view, inner shapes is built completely, + // and then background can be rendered. + + + this.renderBackground(thisGroup); // Real update view + + this._updateView(); + + this._enableHoverLinkToSeries(); + + this._enableHoverLinkFromSeries(); + + this.positionGroup(thisGroup); + }; + + ContinuousView.prototype._renderEndsText = function (group, dataRangeText, endsIndex) { + if (!dataRangeText) { + return; + } // Compatible with ec2, text[0] map to high value, text[1] map low value. + + + var text = dataRangeText[1 - endsIndex]; + text = text != null ? text + '' : ''; + var visualMapModel = this.visualMapModel; + var textGap = visualMapModel.get('textGap'); + var itemSize = visualMapModel.itemSize; + var barGroup = this._shapes.mainGroup; + + var position = this._applyTransform([itemSize[0] / 2, endsIndex === 0 ? -textGap : itemSize[1] + textGap], barGroup); + + var align = this._applyTransform(endsIndex === 0 ? 'bottom' : 'top', barGroup); + + var orient = this._orient; + var textStyleModel = this.visualMapModel.textStyleModel; + this.group.add(new ZRText({ + style: createTextStyle(textStyleModel, { + x: position[0], + y: position[1], + verticalAlign: orient === 'horizontal' ? 'middle' : align, + align: orient === 'horizontal' ? align : 'center', + text: text + }) + })); + }; + + ContinuousView.prototype._renderBar = function (targetGroup) { + var visualMapModel = this.visualMapModel; + var shapes = this._shapes; + var itemSize = visualMapModel.itemSize; + var orient = this._orient; + var useHandle = this._useHandle; + var itemAlign = getItemAlign(visualMapModel, this.api, itemSize); + + var mainGroup = shapes.mainGroup = this._createBarGroup(itemAlign); + + var gradientBarGroup = new Group(); + mainGroup.add(gradientBarGroup); // Bar + + gradientBarGroup.add(shapes.outOfRange = createPolygon()); + gradientBarGroup.add(shapes.inRange = createPolygon(null, useHandle ? getCursor$1(this._orient) : null, bind(this._dragHandle, this, 'all', false), bind(this._dragHandle, this, 'all', true))); // A border radius clip. + + gradientBarGroup.setClipPath(new Rect({ + shape: { + x: 0, + y: 0, + width: itemSize[0], + height: itemSize[1], + r: 3 + } + })); + var textRect = visualMapModel.textStyleModel.getTextRect('国'); + var textSize = mathMax$a(textRect.width, textRect.height); // Handle + + if (useHandle) { + shapes.handleThumbs = []; + shapes.handleLabels = []; + shapes.handleLabelPoints = []; + + this._createHandle(visualMapModel, mainGroup, 0, itemSize, textSize, orient); + + this._createHandle(visualMapModel, mainGroup, 1, itemSize, textSize, orient); + } + + this._createIndicator(visualMapModel, mainGroup, itemSize, textSize, orient); + + targetGroup.add(mainGroup); + }; + + ContinuousView.prototype._createHandle = function (visualMapModel, mainGroup, handleIndex, itemSize, textSize, orient) { + var onDrift = bind(this._dragHandle, this, handleIndex, false); + var onDragEnd = bind(this._dragHandle, this, handleIndex, true); + var handleSize = parsePercent(visualMapModel.get('handleSize'), itemSize[0]); + var handleThumb = createSymbol(visualMapModel.get('handleIcon'), -handleSize / 2, -handleSize / 2, handleSize, handleSize, null, true); + var cursor = getCursor$1(this._orient); + handleThumb.attr({ + cursor: cursor, + draggable: true, + drift: onDrift, + ondragend: onDragEnd, + onmousemove: function (e) { + stop(e.event); + } + }); + handleThumb.x = itemSize[0] / 2; + handleThumb.useStyle(visualMapModel.getModel('handleStyle').getItemStyle()); + handleThumb.setStyle({ + strokeNoScale: true, + strokeFirst: true + }); + handleThumb.style.lineWidth *= 2; + handleThumb.ensureState('emphasis').style = visualMapModel.getModel(['emphasis', 'handleStyle']).getItemStyle(); + setAsHighDownDispatcher(handleThumb, true); + mainGroup.add(handleThumb); // Text is always horizontal layout but should not be effected by + // transform (orient/inverse). So label is built separately but not + // use zrender/graphic/helper/RectText, and is located based on view + // group (according to handleLabelPoint) but not barGroup. + + var textStyleModel = this.visualMapModel.textStyleModel; + var handleLabel = new ZRText({ + cursor: cursor, + draggable: true, + drift: onDrift, + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + stop(e.event); + }, + ondragend: onDragEnd, + style: createTextStyle(textStyleModel, { + x: 0, + y: 0, + text: '' + }) + }); + handleLabel.ensureState('blur').style = { + opacity: 0.1 + }; + handleLabel.stateTransition = { + duration: 200 + }; + this.group.add(handleLabel); + var handleLabelPoint = [handleSize, 0]; + var shapes = this._shapes; + shapes.handleThumbs[handleIndex] = handleThumb; + shapes.handleLabelPoints[handleIndex] = handleLabelPoint; + shapes.handleLabels[handleIndex] = handleLabel; + }; + + ContinuousView.prototype._createIndicator = function (visualMapModel, mainGroup, itemSize, textSize, orient) { + var scale = parsePercent(visualMapModel.get('indicatorSize'), itemSize[0]); + var indicator = createSymbol(visualMapModel.get('indicatorIcon'), -scale / 2, -scale / 2, scale, scale, null, true); + indicator.attr({ + cursor: 'move', + invisible: true, + silent: true, + x: itemSize[0] / 2 + }); + var indicatorStyle = visualMapModel.getModel('indicatorStyle').getItemStyle(); + + if (indicator instanceof ZRImage) { + var pathStyle = indicator.style; + indicator.useStyle(extend({ + // TODO other properties like x, y ? + image: pathStyle.image, + x: pathStyle.x, + y: pathStyle.y, + width: pathStyle.width, + height: pathStyle.height + }, indicatorStyle)); + } else { + indicator.useStyle(indicatorStyle); + } + + mainGroup.add(indicator); + var textStyleModel = this.visualMapModel.textStyleModel; + var indicatorLabel = new ZRText({ + silent: true, + invisible: true, + style: createTextStyle(textStyleModel, { + x: 0, + y: 0, + text: '' + }) + }); + this.group.add(indicatorLabel); + var indicatorLabelPoint = [(orient === 'horizontal' ? textSize / 2 : HOVER_LINK_OUT) + itemSize[0] / 2, 0]; + var shapes = this._shapes; + shapes.indicator = indicator; + shapes.indicatorLabel = indicatorLabel; + shapes.indicatorLabelPoint = indicatorLabelPoint; + this._firstShowIndicator = true; + }; + + ContinuousView.prototype._dragHandle = function (handleIndex, isEnd, // dx is event from ondragend if isEnd is true. It's not used + dx, dy) { + if (!this._useHandle) { + return; + } + + this._dragging = !isEnd; + + if (!isEnd) { + // Transform dx, dy to bar coordination. + var vertex = this._applyTransform([dx, dy], this._shapes.mainGroup, true); + + this._updateInterval(handleIndex, vertex[1]); + + this._hideIndicator(); // Considering realtime, update view should be executed + // before dispatch action. + + + this._updateView(); + } // dragEnd do not dispatch action when realtime. + + + if (isEnd === !this.visualMapModel.get('realtime')) { + // jshint ignore:line + this.api.dispatchAction({ + type: 'selectDataRange', + from: this.uid, + visualMapId: this.visualMapModel.id, + selected: this._dataInterval.slice() + }); + } + + if (isEnd) { + !this._hovering && this._clearHoverLinkToSeries(); + } else if (useHoverLinkOnHandle(this.visualMapModel)) { + this._doHoverLinkToSeries(this._handleEnds[handleIndex], false); + } + }; + + ContinuousView.prototype._resetInterval = function () { + var visualMapModel = this.visualMapModel; + var dataInterval = this._dataInterval = visualMapModel.getSelected(); + var dataExtent = visualMapModel.getExtent(); + var sizeExtent = [0, visualMapModel.itemSize[1]]; + this._handleEnds = [linearMap$2(dataInterval[0], dataExtent, sizeExtent, true), linearMap$2(dataInterval[1], dataExtent, sizeExtent, true)]; + }; + /** + * @private + * @param {(number|string)} handleIndex 0 or 1 or 'all' + * @param {number} dx + * @param {number} dy + */ + + + ContinuousView.prototype._updateInterval = function (handleIndex, delta) { + delta = delta || 0; + var visualMapModel = this.visualMapModel; + var handleEnds = this._handleEnds; + var sizeExtent = [0, visualMapModel.itemSize[1]]; + sliderMove(delta, handleEnds, sizeExtent, handleIndex, // cross is forbiden + 0); + var dataExtent = visualMapModel.getExtent(); // Update data interval. + + this._dataInterval = [linearMap$2(handleEnds[0], sizeExtent, dataExtent, true), linearMap$2(handleEnds[1], sizeExtent, dataExtent, true)]; + }; + + ContinuousView.prototype._updateView = function (forSketch) { + var visualMapModel = this.visualMapModel; + var dataExtent = visualMapModel.getExtent(); + var shapes = this._shapes; + var outOfRangeHandleEnds = [0, visualMapModel.itemSize[1]]; + var inRangeHandleEnds = forSketch ? outOfRangeHandleEnds : this._handleEnds; + + var visualInRange = this._createBarVisual(this._dataInterval, dataExtent, inRangeHandleEnds, 'inRange'); + + var visualOutOfRange = this._createBarVisual(dataExtent, dataExtent, outOfRangeHandleEnds, 'outOfRange'); + + shapes.inRange.setStyle({ + fill: visualInRange.barColor // opacity: visualInRange.opacity + + }).setShape('points', visualInRange.barPoints); + shapes.outOfRange.setStyle({ + fill: visualOutOfRange.barColor // opacity: visualOutOfRange.opacity + + }).setShape('points', visualOutOfRange.barPoints); + + this._updateHandle(inRangeHandleEnds, visualInRange); + }; + + ContinuousView.prototype._createBarVisual = function (dataInterval, dataExtent, handleEnds, forceState) { + var opts = { + forceState: forceState, + convertOpacityToAlpha: true + }; + + var colorStops = this._makeColorGradient(dataInterval, opts); + + var symbolSizes = [this.getControllerVisual(dataInterval[0], 'symbolSize', opts), this.getControllerVisual(dataInterval[1], 'symbolSize', opts)]; + + var barPoints = this._createBarPoints(handleEnds, symbolSizes); + + return { + barColor: new LinearGradient(0, 0, 0, 1, colorStops), + barPoints: barPoints, + handlesColor: [colorStops[0].color, colorStops[colorStops.length - 1].color] + }; + }; + + ContinuousView.prototype._makeColorGradient = function (dataInterval, opts) { + // Considering colorHue, which is not linear, so we have to sample + // to calculate gradient color stops, but not only caculate head + // and tail. + var sampleNumber = 100; // Arbitrary value. + + var colorStops = []; + var step = (dataInterval[1] - dataInterval[0]) / sampleNumber; + colorStops.push({ + color: this.getControllerVisual(dataInterval[0], 'color', opts), + offset: 0 + }); + + for (var i = 1; i < sampleNumber; i++) { + var currValue = dataInterval[0] + step * i; + + if (currValue > dataInterval[1]) { + break; + } + + colorStops.push({ + color: this.getControllerVisual(currValue, 'color', opts), + offset: i / sampleNumber + }); + } + + colorStops.push({ + color: this.getControllerVisual(dataInterval[1], 'color', opts), + offset: 1 + }); + return colorStops; + }; + + ContinuousView.prototype._createBarPoints = function (handleEnds, symbolSizes) { + var itemSize = this.visualMapModel.itemSize; + return [[itemSize[0] - symbolSizes[0], handleEnds[0]], [itemSize[0], handleEnds[0]], [itemSize[0], handleEnds[1]], [itemSize[0] - symbolSizes[1], handleEnds[1]]]; + }; + + ContinuousView.prototype._createBarGroup = function (itemAlign) { + var orient = this._orient; + var inverse = this.visualMapModel.get('inverse'); + return new Group(orient === 'horizontal' && !inverse ? { + scaleX: itemAlign === 'bottom' ? 1 : -1, + rotation: Math.PI / 2 + } : orient === 'horizontal' && inverse ? { + scaleX: itemAlign === 'bottom' ? -1 : 1, + rotation: -Math.PI / 2 + } : orient === 'vertical' && !inverse ? { + scaleX: itemAlign === 'left' ? 1 : -1, + scaleY: -1 + } : { + scaleX: itemAlign === 'left' ? 1 : -1 + }); + }; + + ContinuousView.prototype._updateHandle = function (handleEnds, visualInRange) { + if (!this._useHandle) { + return; + } + + var shapes = this._shapes; + var visualMapModel = this.visualMapModel; + var handleThumbs = shapes.handleThumbs; + var handleLabels = shapes.handleLabels; + var itemSize = visualMapModel.itemSize; + var dataExtent = visualMapModel.getExtent(); + each$e([0, 1], function (handleIndex) { + var handleThumb = handleThumbs[handleIndex]; + handleThumb.setStyle('fill', visualInRange.handlesColor[handleIndex]); + handleThumb.y = handleEnds[handleIndex]; + var val = linearMap$2(handleEnds[handleIndex], [0, itemSize[1]], dataExtent, true); + var symbolSize = this.getControllerVisual(val, 'symbolSize'); + handleThumb.scaleX = handleThumb.scaleY = symbolSize / itemSize[0]; + handleThumb.x = itemSize[0] - symbolSize / 2; // Update handle label position. + + var textPoint = applyTransform$1(shapes.handleLabelPoints[handleIndex], getTransform(handleThumb, this.group)); + handleLabels[handleIndex].setStyle({ + x: textPoint[0], + y: textPoint[1], + text: visualMapModel.formatValueText(this._dataInterval[handleIndex]), + verticalAlign: 'middle', + align: this._orient === 'vertical' ? this._applyTransform('left', shapes.mainGroup) : 'center' + }); + }, this); + }; + + ContinuousView.prototype._showIndicator = function (cursorValue, textValue, rangeSymbol, halfHoverLinkSize) { + var visualMapModel = this.visualMapModel; + var dataExtent = visualMapModel.getExtent(); + var itemSize = visualMapModel.itemSize; + var sizeExtent = [0, itemSize[1]]; + var shapes = this._shapes; + var indicator = shapes.indicator; + + if (!indicator) { + return; + } + + indicator.attr('invisible', false); + var opts = { + convertOpacityToAlpha: true + }; + var color = this.getControllerVisual(cursorValue, 'color', opts); + var symbolSize = this.getControllerVisual(cursorValue, 'symbolSize'); + var y = linearMap$2(cursorValue, dataExtent, sizeExtent, true); + var x = itemSize[0] - symbolSize / 2; + var oldIndicatorPos = { + x: indicator.x, + y: indicator.y + }; // Update handle label position. + + indicator.y = y; + indicator.x = x; + var textPoint = applyTransform$1(shapes.indicatorLabelPoint, getTransform(indicator, this.group)); + var indicatorLabel = shapes.indicatorLabel; + indicatorLabel.attr('invisible', false); + + var align = this._applyTransform('left', shapes.mainGroup); + + var orient = this._orient; + var isHorizontal = orient === 'horizontal'; + indicatorLabel.setStyle({ + text: (rangeSymbol ? rangeSymbol : '') + visualMapModel.formatValueText(textValue), + verticalAlign: isHorizontal ? align : 'middle', + align: isHorizontal ? 'center' : align + }); + var indicatorNewProps = { + x: x, + y: y, + style: { + fill: color + } + }; + var labelNewProps = { + style: { + x: textPoint[0], + y: textPoint[1] + } + }; + + if (visualMapModel.ecModel.isAnimationEnabled() && !this._firstShowIndicator) { + var animationCfg = { + duration: 100, + easing: 'cubicInOut', + additive: true + }; + indicator.x = oldIndicatorPos.x; + indicator.y = oldIndicatorPos.y; + indicator.animateTo(indicatorNewProps, animationCfg); + indicatorLabel.animateTo(labelNewProps, animationCfg); + } else { + indicator.attr(indicatorNewProps); + indicatorLabel.attr(labelNewProps); + } + + this._firstShowIndicator = false; + var handleLabels = this._shapes.handleLabels; + + if (handleLabels) { + for (var i = 0; i < handleLabels.length; i++) { + // Fade out handle labels. + // NOTE: Must use api enter/leave on emphasis/blur/select state. Or the global states manager will change it. + this._api.enterBlur(handleLabels[i]); + } + } + }; + + ContinuousView.prototype._enableHoverLinkToSeries = function () { + var self = this; + + this._shapes.mainGroup.on('mousemove', function (e) { + self._hovering = true; + + if (!self._dragging) { + var itemSize = self.visualMapModel.itemSize; + + var pos = self._applyTransform([e.offsetX, e.offsetY], self._shapes.mainGroup, true, true); // For hover link show when hover handle, which might be + // below or upper than sizeExtent. + + + pos[1] = mathMin$a(mathMax$a(0, pos[1]), itemSize[1]); + + self._doHoverLinkToSeries(pos[1], 0 <= pos[0] && pos[0] <= itemSize[0]); + } + }).on('mouseout', function () { + // When mouse is out of handle, hoverLink still need + // to be displayed when realtime is set as false. + self._hovering = false; + !self._dragging && self._clearHoverLinkToSeries(); + }); + }; + + ContinuousView.prototype._enableHoverLinkFromSeries = function () { + var zr = this.api.getZr(); + + if (this.visualMapModel.option.hoverLink) { + zr.on('mouseover', this._hoverLinkFromSeriesMouseOver, this); + zr.on('mouseout', this._hideIndicator, this); + } else { + this._clearHoverLinkFromSeries(); + } + }; + + ContinuousView.prototype._doHoverLinkToSeries = function (cursorPos, hoverOnBar) { + var visualMapModel = this.visualMapModel; + var itemSize = visualMapModel.itemSize; + + if (!visualMapModel.option.hoverLink) { + return; + } + + var sizeExtent = [0, itemSize[1]]; + var dataExtent = visualMapModel.getExtent(); // For hover link show when hover handle, which might be below or upper than sizeExtent. + + cursorPos = mathMin$a(mathMax$a(sizeExtent[0], cursorPos), sizeExtent[1]); + var halfHoverLinkSize = getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent); + var hoverRange = [cursorPos - halfHoverLinkSize, cursorPos + halfHoverLinkSize]; + var cursorValue = linearMap$2(cursorPos, sizeExtent, dataExtent, true); + var valueRange = [linearMap$2(hoverRange[0], sizeExtent, dataExtent, true), linearMap$2(hoverRange[1], sizeExtent, dataExtent, true)]; // Consider data range is out of visualMap range, see test/visualMap-continuous.html, + // where china and india has very large population. + + hoverRange[0] < sizeExtent[0] && (valueRange[0] = -Infinity); + hoverRange[1] > sizeExtent[1] && (valueRange[1] = Infinity); // Do not show indicator when mouse is over handle, + // otherwise labels overlap, especially when dragging. + + if (hoverOnBar) { + if (valueRange[0] === -Infinity) { + this._showIndicator(cursorValue, valueRange[1], '< ', halfHoverLinkSize); + } else if (valueRange[1] === Infinity) { + this._showIndicator(cursorValue, valueRange[0], '> ', halfHoverLinkSize); + } else { + this._showIndicator(cursorValue, cursorValue, '≈ ', halfHoverLinkSize); + } + } // When realtime is set as false, handles, which are in barGroup, + // also trigger hoverLink, which help user to realize where they + // focus on when dragging. (see test/heatmap-large.html) + // When realtime is set as true, highlight will not show when hover + // handle, because the label on handle, which displays a exact value + // but not range, might mislead users. + + + var oldBatch = this._hoverLinkDataIndices; + var newBatch = []; + + if (hoverOnBar || useHoverLinkOnHandle(visualMapModel)) { + newBatch = this._hoverLinkDataIndices = visualMapModel.findTargetDataIndices(valueRange); + } + + var resultBatches = compressBatches(oldBatch, newBatch); + + this._dispatchHighDown('downplay', makeHighDownBatch(resultBatches[0], visualMapModel)); + + this._dispatchHighDown('highlight', makeHighDownBatch(resultBatches[1], visualMapModel)); + }; + + ContinuousView.prototype._hoverLinkFromSeriesMouseOver = function (e) { + var el = e.target; + var visualMapModel = this.visualMapModel; + + if (!el || getECData(el).dataIndex == null) { + return; + } + + var ecData = getECData(el); + var dataModel = this.ecModel.getSeriesByIndex(ecData.seriesIndex); + + if (!visualMapModel.isTargetSeries(dataModel)) { + return; + } + + var data = dataModel.getData(ecData.dataType); + var value = data.getStore().get(visualMapModel.getDataDimensionIndex(data), ecData.dataIndex); + + if (!isNaN(value)) { + this._showIndicator(value, value); + } + }; + + ContinuousView.prototype._hideIndicator = function () { + var shapes = this._shapes; + shapes.indicator && shapes.indicator.attr('invisible', true); + shapes.indicatorLabel && shapes.indicatorLabel.attr('invisible', true); + var handleLabels = this._shapes.handleLabels; + + if (handleLabels) { + for (var i = 0; i < handleLabels.length; i++) { + // Fade out handle labels. + // NOTE: Must use api enter/leave on emphasis/blur/select state. Or the global states manager will change it. + this._api.leaveBlur(handleLabels[i]); + } + } + }; + + ContinuousView.prototype._clearHoverLinkToSeries = function () { + this._hideIndicator(); + + var indices = this._hoverLinkDataIndices; + + this._dispatchHighDown('downplay', makeHighDownBatch(indices, this.visualMapModel)); + + indices.length = 0; + }; + + ContinuousView.prototype._clearHoverLinkFromSeries = function () { + this._hideIndicator(); + + var zr = this.api.getZr(); + zr.off('mouseover', this._hoverLinkFromSeriesMouseOver); + zr.off('mouseout', this._hideIndicator); + }; + + ContinuousView.prototype._applyTransform = function (vertex, element, inverse, global) { + var transform = getTransform(element, global ? null : this.group); + return isArray(vertex) ? applyTransform$1(vertex, transform, inverse) : transformDirection(vertex, transform, inverse); + }; // TODO: TYPE more specified payload types. + + + ContinuousView.prototype._dispatchHighDown = function (type, batch) { + batch && batch.length && this.api.dispatchAction({ + type: type, + batch: batch + }); + }; + /** + * @override + */ + + + ContinuousView.prototype.dispose = function () { + this._clearHoverLinkFromSeries(); + + this._clearHoverLinkToSeries(); + }; + /** + * @override + */ + + + ContinuousView.prototype.remove = function () { + this._clearHoverLinkFromSeries(); + + this._clearHoverLinkToSeries(); + }; + + ContinuousView.type = 'visualMap.continuous'; + return ContinuousView; + }(VisualMapView); + + function createPolygon(points, cursor, onDrift, onDragEnd) { + return new Polygon({ + shape: { + points: points + }, + draggable: !!onDrift, + cursor: cursor, + drift: onDrift, + onmousemove: function (e) { + // Fot mobile devicem, prevent screen slider on the button. + stop(e.event); + }, + ondragend: onDragEnd + }); + } + + function getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent) { + var halfHoverLinkSize = HOVER_LINK_SIZE / 2; + var hoverLinkDataSize = visualMapModel.get('hoverLinkDataSize'); + + if (hoverLinkDataSize) { + halfHoverLinkSize = linearMap$2(hoverLinkDataSize, dataExtent, sizeExtent, true) / 2; + } + + return halfHoverLinkSize; + } + + function useHoverLinkOnHandle(visualMapModel) { + var hoverLinkOnHandle = visualMapModel.get('hoverLinkOnHandle'); + return !!(hoverLinkOnHandle == null ? visualMapModel.get('realtime') : hoverLinkOnHandle); + } + + function getCursor$1(orient) { + return orient === 'vertical' ? 'ns-resize' : 'ew-resize'; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var visualMapActionInfo = { + type: 'selectDataRange', + event: 'dataRangeSelected', + // FIXME use updateView appears wrong + update: 'update' + }; + var visualMapActionHander = function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'visualMap', + query: payload + }, function (model) { + model.setSelected(payload.selected); + }); + }; + + var visualMapEncodingHandlers = [{ + createOnAllSeries: true, + reset: function (seriesModel, ecModel) { + var resetDefines = []; + ecModel.eachComponent('visualMap', function (visualMapModel) { + var pipelineContext = seriesModel.pipelineContext; + + if (!visualMapModel.isTargetSeries(seriesModel) || pipelineContext && pipelineContext.large) { + return; + } + + resetDefines.push(incrementalApplyVisual(visualMapModel.stateList, visualMapModel.targetVisuals, bind(visualMapModel.getValueState, visualMapModel), visualMapModel.getDataDimensionIndex(seriesModel.getData()))); + }); + return resetDefines; + } + }, // Only support color. + { + createOnAllSeries: true, + reset: function (seriesModel, ecModel) { + var data = seriesModel.getData(); + var visualMetaList = []; + ecModel.eachComponent('visualMap', function (visualMapModel) { + if (visualMapModel.isTargetSeries(seriesModel)) { + var visualMeta = visualMapModel.getVisualMeta(bind(getColorVisual, null, seriesModel, visualMapModel)) || { + stops: [], + outerColors: [] + }; + var dimIdx = visualMapModel.getDataDimensionIndex(data); + + if (dimIdx >= 0) { + // visualMeta.dimension should be dimension index, but not concrete dimension. + visualMeta.dimension = dimIdx; + visualMetaList.push(visualMeta); + } + } + }); // console.log(JSON.stringify(visualMetaList.map(a => a.stops))); + + seriesModel.getData().setVisual('visualMeta', visualMetaList); + } + }]; // FIXME + // performance and export for heatmap? + // value can be Infinity or -Infinity + + function getColorVisual(seriesModel, visualMapModel, value, valueState) { + var mappings = visualMapModel.targetVisuals[valueState]; + var visualTypes = VisualMapping.prepareVisualTypes(mappings); + var resultVisual = { + color: getVisualFromData(seriesModel.getData(), 'color') // default color. + + }; + + for (var i = 0, len = visualTypes.length; i < len; i++) { + var type = visualTypes[i]; + var mapping = mappings[type === 'opacity' ? '__alphaForOpacity' : type]; + mapping && mapping.applyVisual(value, getVisual, setVisual); + } + + return resultVisual.color; + + function getVisual(key) { + return resultVisual[key]; + } + + function setVisual(key, value) { + resultVisual[key] = value; + } + } + + var each$f = each; + function visualMapPreprocessor(option) { + var visualMap = option && option.visualMap; + + if (!isArray(visualMap)) { + visualMap = visualMap ? [visualMap] : []; + } + + each$f(visualMap, function (opt) { + if (!opt) { + return; + } // rename splitList to pieces + + + if (has$1(opt, 'splitList') && !has$1(opt, 'pieces')) { + opt.pieces = opt.splitList; + delete opt.splitList; + } + + var pieces = opt.pieces; + + if (pieces && isArray(pieces)) { + each$f(pieces, function (piece) { + if (isObject(piece)) { + if (has$1(piece, 'start') && !has$1(piece, 'min')) { + piece.min = piece.start; + } + + if (has$1(piece, 'end') && !has$1(piece, 'max')) { + piece.max = piece.end; + } + } + }); + } + }); + } + + function has$1(obj, name) { + return obj && obj.hasOwnProperty && obj.hasOwnProperty(name); + } + + var installed$1 = false; + function installCommon$1(registers) { + if (installed$1) { + return; + } + + installed$1 = true; + registers.registerSubTypeDefaulter('visualMap', function (option) { + // Compatible with ec2, when splitNumber === 0, continuous visualMap will be used. + return !option.categories && (!(option.pieces ? option.pieces.length > 0 : option.splitNumber > 0) || option.calculable) ? 'continuous' : 'piecewise'; + }); + registers.registerAction(visualMapActionInfo, visualMapActionHander); + each(visualMapEncodingHandlers, function (handler) { + registers.registerVisual(registers.PRIORITY.VISUAL.COMPONENT, handler); + }); + registers.registerPreprocessor(visualMapPreprocessor); + } + + function install$N(registers) { + registers.registerComponentModel(ContinuousModel); + registers.registerComponentView(ContinuousView); + installCommon$1(registers); + } + + var PiecewiseModel = + /** @class */ + function (_super) { + __extends(PiecewiseModel, _super); + + function PiecewiseModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = PiecewiseModel.type; + /** + * The order is always [low, ..., high]. + * [{text: string, interval: Array.}, ...] + */ + + _this._pieceList = []; + return _this; + } + + PiecewiseModel.prototype.optionUpdated = function (newOption, isInit) { + _super.prototype.optionUpdated.apply(this, arguments); + + this.resetExtent(); + + var mode = this._mode = this._determineMode(); + + this._pieceList = []; + + resetMethods[this._mode].call(this, this._pieceList); + + this._resetSelected(newOption, isInit); + + var categories = this.option.categories; + this.resetVisual(function (mappingOption, state) { + if (mode === 'categories') { + mappingOption.mappingMethod = 'category'; + mappingOption.categories = clone(categories); + } else { + mappingOption.dataExtent = this.getExtent(); + mappingOption.mappingMethod = 'piecewise'; + mappingOption.pieceList = map(this._pieceList, function (piece) { + piece = clone(piece); + + if (state !== 'inRange') { + // FIXME + // outOfRange do not support special visual in pieces. + piece.visual = null; + } + + return piece; + }); + } + }); + }; + /** + * @protected + * @override + */ + + + PiecewiseModel.prototype.completeVisualOption = function () { + // Consider this case: + // visualMap: { + // pieces: [{symbol: 'circle', lt: 0}, {symbol: 'rect', gte: 0}] + // } + // where no inRange/outOfRange set but only pieces. So we should make + // default inRange/outOfRange for this case, otherwise visuals that only + // appear in `pieces` will not be taken into account in visual encoding. + var option = this.option; + var visualTypesInPieces = {}; + var visualTypes = VisualMapping.listVisualTypes(); + var isCategory = this.isCategory(); + each(option.pieces, function (piece) { + each(visualTypes, function (visualType) { + if (piece.hasOwnProperty(visualType)) { + visualTypesInPieces[visualType] = 1; + } + }); + }); + each(visualTypesInPieces, function (v, visualType) { + var exists = false; + each(this.stateList, function (state) { + exists = exists || has(option, state, visualType) || has(option.target, state, visualType); + }, this); + !exists && each(this.stateList, function (state) { + (option[state] || (option[state] = {}))[visualType] = visualDefault.get(visualType, state === 'inRange' ? 'active' : 'inactive', isCategory); + }); + }, this); + + function has(obj, state, visualType) { + return obj && obj[state] && obj[state].hasOwnProperty(visualType); + } + + _super.prototype.completeVisualOption.apply(this, arguments); + }; + + PiecewiseModel.prototype._resetSelected = function (newOption, isInit) { + var thisOption = this.option; + var pieceList = this._pieceList; // Selected do not merge but all override. + + var selected = (isInit ? thisOption : newOption).selected || {}; + thisOption.selected = selected; // Consider 'not specified' means true. + + each(pieceList, function (piece, index) { + var key = this.getSelectedMapKey(piece); + + if (!selected.hasOwnProperty(key)) { + selected[key] = true; + } + }, this); + + if (thisOption.selectedMode === 'single') { + // Ensure there is only one selected. + var hasSel_1 = false; + each(pieceList, function (piece, index) { + var key = this.getSelectedMapKey(piece); + + if (selected[key]) { + hasSel_1 ? selected[key] = false : hasSel_1 = true; + } + }, this); + } // thisOption.selectedMode === 'multiple', default: all selected. + + }; + /** + * @public + */ + + + PiecewiseModel.prototype.getItemSymbol = function () { + return this.get('itemSymbol'); + }; + /** + * @public + */ + + + PiecewiseModel.prototype.getSelectedMapKey = function (piece) { + return this._mode === 'categories' ? piece.value + '' : piece.index + ''; + }; + /** + * @public + */ + + + PiecewiseModel.prototype.getPieceList = function () { + return this._pieceList; + }; + /** + * @return {string} + */ + + + PiecewiseModel.prototype._determineMode = function () { + var option = this.option; + return option.pieces && option.pieces.length > 0 ? 'pieces' : this.option.categories ? 'categories' : 'splitNumber'; + }; + /** + * @override + */ + + + PiecewiseModel.prototype.setSelected = function (selected) { + this.option.selected = clone(selected); + }; + /** + * @override + */ + + + PiecewiseModel.prototype.getValueState = function (value) { + var index = VisualMapping.findPieceIndex(value, this._pieceList); + return index != null ? this.option.selected[this.getSelectedMapKey(this._pieceList[index])] ? 'inRange' : 'outOfRange' : 'outOfRange'; + }; + /** + * @public + * @param pieceIndex piece index in visualMapModel.getPieceList() + */ + + + PiecewiseModel.prototype.findTargetDataIndices = function (pieceIndex) { + var result = []; + var pieceList = this._pieceList; + this.eachTargetSeries(function (seriesModel) { + var dataIndices = []; + var data = seriesModel.getData(); + data.each(this.getDataDimensionIndex(data), function (value, dataIndex) { + // Should always base on model pieceList, because it is order sensitive. + var pIdx = VisualMapping.findPieceIndex(value, pieceList); + pIdx === pieceIndex && dataIndices.push(dataIndex); + }, this); + result.push({ + seriesId: seriesModel.id, + dataIndex: dataIndices + }); + }, this); + return result; + }; + /** + * @private + * @param piece piece.value or piece.interval is required. + * @return Can be Infinity or -Infinity + */ + + + PiecewiseModel.prototype.getRepresentValue = function (piece) { + var representValue; + + if (this.isCategory()) { + representValue = piece.value; + } else { + if (piece.value != null) { + representValue = piece.value; + } else { + var pieceInterval = piece.interval || []; + representValue = pieceInterval[0] === -Infinity && pieceInterval[1] === Infinity ? 0 : (pieceInterval[0] + pieceInterval[1]) / 2; + } + } + + return representValue; + }; + + PiecewiseModel.prototype.getVisualMeta = function (getColorVisual) { + // Do not support category. (category axis is ordinal, numerical) + if (this.isCategory()) { + return; + } + + var stops = []; + var outerColors = ['', '']; + var visualMapModel = this; + + function setStop(interval, valueState) { + var representValue = visualMapModel.getRepresentValue({ + interval: interval + }); // Not category + + if (!valueState) { + valueState = visualMapModel.getValueState(representValue); + } + + var color = getColorVisual(representValue, valueState); + + if (interval[0] === -Infinity) { + outerColors[0] = color; + } else if (interval[1] === Infinity) { + outerColors[1] = color; + } else { + stops.push({ + value: interval[0], + color: color + }, { + value: interval[1], + color: color + }); + } + } // Suplement + + + var pieceList = this._pieceList.slice(); + + if (!pieceList.length) { + pieceList.push({ + interval: [-Infinity, Infinity] + }); + } else { + var edge = pieceList[0].interval[0]; + edge !== -Infinity && pieceList.unshift({ + interval: [-Infinity, edge] + }); + edge = pieceList[pieceList.length - 1].interval[1]; + edge !== Infinity && pieceList.push({ + interval: [edge, Infinity] + }); + } + + var curr = -Infinity; + each(pieceList, function (piece) { + var interval = piece.interval; + + if (interval) { + // Fulfill gap. + interval[0] > curr && setStop([curr, interval[0]], 'outOfRange'); + setStop(interval.slice()); + curr = interval[1]; + } + }, this); + return { + stops: stops, + outerColors: outerColors + }; + }; + + PiecewiseModel.type = 'visualMap.piecewise'; + PiecewiseModel.defaultOption = inheritDefaultOption(VisualMapModel.defaultOption, { + selected: null, + minOpen: false, + maxOpen: false, + align: 'auto', + itemWidth: 20, + itemHeight: 14, + itemSymbol: 'roundRect', + pieces: null, + categories: null, + splitNumber: 5, + selectedMode: 'multiple', + itemGap: 10, + hoverLink: true // Enable hover highlight. + + }); + return PiecewiseModel; + }(VisualMapModel); + /** + * Key is this._mode + * @type {Object} + * @this {module:echarts/component/viusalMap/PiecewiseMode} + */ + + var resetMethods = { + splitNumber: function (outPieceList) { + var thisOption = this.option; + var precision = Math.min(thisOption.precision, 20); + var dataExtent = this.getExtent(); + var splitNumber = thisOption.splitNumber; + splitNumber = Math.max(parseInt(splitNumber, 10), 1); + thisOption.splitNumber = splitNumber; + var splitStep = (dataExtent[1] - dataExtent[0]) / splitNumber; // Precision auto-adaption + + while (+splitStep.toFixed(precision) !== splitStep && precision < 5) { + precision++; + } + + thisOption.precision = precision; + splitStep = +splitStep.toFixed(precision); + + if (thisOption.minOpen) { + outPieceList.push({ + interval: [-Infinity, dataExtent[0]], + close: [0, 0] + }); + } + + for (var index = 0, curr = dataExtent[0]; index < splitNumber; curr += splitStep, index++) { + var max = index === splitNumber - 1 ? dataExtent[1] : curr + splitStep; + outPieceList.push({ + interval: [curr, max], + close: [1, 1] + }); + } + + if (thisOption.maxOpen) { + outPieceList.push({ + interval: [dataExtent[1], Infinity], + close: [0, 0] + }); + } + + reformIntervals(outPieceList); + each(outPieceList, function (piece, index) { + piece.index = index; + piece.text = this.formatValueText(piece.interval); + }, this); + }, + categories: function (outPieceList) { + var thisOption = this.option; + each(thisOption.categories, function (cate) { + // FIXME category模式也使用pieceList,但在visualMapping中不是使用pieceList。 + // 是否改一致。 + outPieceList.push({ + text: this.formatValueText(cate, true), + value: cate + }); + }, this); // See "Order Rule". + + normalizeReverse(thisOption, outPieceList); + }, + pieces: function (outPieceList) { + var thisOption = this.option; + each(thisOption.pieces, function (pieceListItem, index) { + if (!isObject(pieceListItem)) { + pieceListItem = { + value: pieceListItem + }; + } + + var item = { + text: '', + index: index + }; + + if (pieceListItem.label != null) { + item.text = pieceListItem.label; + } + + if (pieceListItem.hasOwnProperty('value')) { + var value = item.value = pieceListItem.value; + item.interval = [value, value]; + item.close = [1, 1]; + } else { + // `min` `max` is legacy option. + // `lt` `gt` `lte` `gte` is recommanded. + var interval = item.interval = []; + var close_1 = item.close = [0, 0]; + var closeList = [1, 0, 1]; + var infinityList = [-Infinity, Infinity]; + var useMinMax = []; + + for (var lg = 0; lg < 2; lg++) { + var names = [['gte', 'gt', 'min'], ['lte', 'lt', 'max']][lg]; + + for (var i = 0; i < 3 && interval[lg] == null; i++) { + interval[lg] = pieceListItem[names[i]]; + close_1[lg] = closeList[i]; + useMinMax[lg] = i === 2; + } + + interval[lg] == null && (interval[lg] = infinityList[lg]); + } + + useMinMax[0] && interval[1] === Infinity && (close_1[0] = 0); + useMinMax[1] && interval[0] === -Infinity && (close_1[1] = 0); + + if ("development" !== 'production') { + if (interval[0] > interval[1]) { + console.warn('Piece ' + index + 'is illegal: ' + interval + ' lower bound should not greater then uppper bound.'); + } + } + + if (interval[0] === interval[1] && close_1[0] && close_1[1]) { + // Consider: [{min: 5, max: 5, visual: {...}}, {min: 0, max: 5}], + // we use value to lift the priority when min === max + item.value = interval[0]; + } + } + + item.visual = VisualMapping.retrieveVisuals(pieceListItem); + outPieceList.push(item); + }, this); // See "Order Rule". + + normalizeReverse(thisOption, outPieceList); // Only pieces + + reformIntervals(outPieceList); + each(outPieceList, function (piece) { + var close = piece.close; + var edgeSymbols = [['<', '≤'][close[1]], ['>', '≥'][close[0]]]; + piece.text = piece.text || this.formatValueText(piece.value != null ? piece.value : piece.interval, false, edgeSymbols); + }, this); + } + }; + + function normalizeReverse(thisOption, pieceList) { + var inverse = thisOption.inverse; + + if (thisOption.orient === 'vertical' ? !inverse : inverse) { + pieceList.reverse(); + } + } + + var PiecewiseVisualMapView = + /** @class */ + function (_super) { + __extends(PiecewiseVisualMapView, _super); + + function PiecewiseVisualMapView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = PiecewiseVisualMapView.type; + return _this; + } + + PiecewiseVisualMapView.prototype.doRender = function () { + var thisGroup = this.group; + thisGroup.removeAll(); + var visualMapModel = this.visualMapModel; + var textGap = visualMapModel.get('textGap'); + var textStyleModel = visualMapModel.textStyleModel; + var textFont = textStyleModel.getFont(); + var textFill = textStyleModel.getTextColor(); + + var itemAlign = this._getItemAlign(); + + var itemSize = visualMapModel.itemSize; + + var viewData = this._getViewData(); + + var endsText = viewData.endsText; + var showLabel = retrieve(visualMapModel.get('showLabel', true), !endsText); + endsText && this._renderEndsText(thisGroup, endsText[0], itemSize, showLabel, itemAlign); + each(viewData.viewPieceList, function (item) { + var piece = item.piece; + var itemGroup = new Group(); + itemGroup.onclick = bind(this._onItemClick, this, piece); + + this._enableHoverLink(itemGroup, item.indexInModelPieceList); // TODO Category + + + var representValue = visualMapModel.getRepresentValue(piece); + + this._createItemSymbol(itemGroup, representValue, [0, 0, itemSize[0], itemSize[1]]); + + if (showLabel) { + var visualState = this.visualMapModel.getValueState(representValue); + itemGroup.add(new ZRText({ + style: { + x: itemAlign === 'right' ? -textGap : itemSize[0] + textGap, + y: itemSize[1] / 2, + text: piece.text, + verticalAlign: 'middle', + align: itemAlign, + font: textFont, + fill: textFill, + opacity: visualState === 'outOfRange' ? 0.5 : 1 + } + })); + } + + thisGroup.add(itemGroup); + }, this); + endsText && this._renderEndsText(thisGroup, endsText[1], itemSize, showLabel, itemAlign); + box(visualMapModel.get('orient'), thisGroup, visualMapModel.get('itemGap')); + this.renderBackground(thisGroup); + this.positionGroup(thisGroup); + }; + + PiecewiseVisualMapView.prototype._enableHoverLink = function (itemGroup, pieceIndex) { + var _this = this; + + itemGroup.on('mouseover', function () { + return onHoverLink('highlight'); + }).on('mouseout', function () { + return onHoverLink('downplay'); + }); + + var onHoverLink = function (method) { + var visualMapModel = _this.visualMapModel; // TODO: TYPE More detailed action types + + visualMapModel.option.hoverLink && _this.api.dispatchAction({ + type: method, + batch: makeHighDownBatch(visualMapModel.findTargetDataIndices(pieceIndex), visualMapModel) + }); + }; + }; + + PiecewiseVisualMapView.prototype._getItemAlign = function () { + var visualMapModel = this.visualMapModel; + var modelOption = visualMapModel.option; + + if (modelOption.orient === 'vertical') { + return getItemAlign(visualMapModel, this.api, visualMapModel.itemSize); + } else { + // horizontal, most case left unless specifying right. + var align = modelOption.align; + + if (!align || align === 'auto') { + align = 'left'; + } + + return align; + } + }; + + PiecewiseVisualMapView.prototype._renderEndsText = function (group, text, itemSize, showLabel, itemAlign) { + if (!text) { + return; + } + + var itemGroup = new Group(); + var textStyleModel = this.visualMapModel.textStyleModel; + itemGroup.add(new ZRText({ + style: createTextStyle(textStyleModel, { + x: showLabel ? itemAlign === 'right' ? itemSize[0] : 0 : itemSize[0] / 2, + y: itemSize[1] / 2, + verticalAlign: 'middle', + align: showLabel ? itemAlign : 'center', + text: text + }) + })); + group.add(itemGroup); + }; + /** + * @private + * @return {Object} {peiceList, endsText} The order is the same as screen pixel order. + */ + + + PiecewiseVisualMapView.prototype._getViewData = function () { + var visualMapModel = this.visualMapModel; + var viewPieceList = map(visualMapModel.getPieceList(), function (piece, index) { + return { + piece: piece, + indexInModelPieceList: index + }; + }); + var endsText = visualMapModel.get('text'); // Consider orient and inverse. + + var orient = visualMapModel.get('orient'); + var inverse = visualMapModel.get('inverse'); // Order of model pieceList is always [low, ..., high] + + if (orient === 'horizontal' ? inverse : !inverse) { + viewPieceList.reverse(); + } // Origin order of endsText is [high, low] + else if (endsText) { + endsText = endsText.slice().reverse(); + } + + return { + viewPieceList: viewPieceList, + endsText: endsText + }; + }; + + PiecewiseVisualMapView.prototype._createItemSymbol = function (group, representValue, shapeParam) { + group.add(createSymbol( // symbol will be string + this.getControllerVisual(representValue, 'symbol'), shapeParam[0], shapeParam[1], shapeParam[2], shapeParam[3], // color will be string + this.getControllerVisual(representValue, 'color'))); + }; + + PiecewiseVisualMapView.prototype._onItemClick = function (piece) { + var visualMapModel = this.visualMapModel; + var option = visualMapModel.option; + var selected = clone(option.selected); + var newKey = visualMapModel.getSelectedMapKey(piece); + + if (option.selectedMode === 'single') { + selected[newKey] = true; + each(selected, function (o, key) { + selected[key] = key === newKey; + }); + } else { + selected[newKey] = !selected[newKey]; + } + + this.api.dispatchAction({ + type: 'selectDataRange', + from: this.uid, + visualMapId: this.visualMapModel.id, + selected: selected + }); + }; + + PiecewiseVisualMapView.type = 'visualMap.piecewise'; + return PiecewiseVisualMapView; + }(VisualMapView); + + function install$O(registers) { + registers.registerComponentModel(PiecewiseModel); + registers.registerComponentView(PiecewiseVisualMapView); + installCommon$1(registers); + } + + function install$P(registers) { + use(install$N); + use(install$O); // Do not install './dataZoomSelect', + // since it only work for toolbox dataZoom. + } + + var DEFAULT_OPTION = { + label: { + enabled: true + }, + decal: { + show: false + } + }; + var inner$l = makeInner(); + var decalPaletteScope = {}; + function ariaVisual(ecModel, api) { + var ariaModel = ecModel.getModel('aria'); // See "area enabled" detection code in `GlobalModel.ts`. + + if (!ariaModel.get('enabled')) { + return; + } + + var defaultOption = clone(DEFAULT_OPTION); + merge(defaultOption.label, ecModel.getLocaleModel().get('aria'), false); + merge(ariaModel.option, defaultOption, false); + setDecal(); + setLabel(); + + function setDecal() { + var decalModel = ariaModel.getModel('decal'); + var useDecal = decalModel.get('show'); + + if (useDecal) { + // Each type of series use one scope. + // Pie and funnel are using diferrent scopes + var paletteScopeGroupByType_1 = createHashMap(); + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.isColorBySeries()) { + return; + } + + var decalScope = paletteScopeGroupByType_1.get(seriesModel.type); + + if (!decalScope) { + decalScope = {}; + paletteScopeGroupByType_1.set(seriesModel.type, decalScope); + } + + inner$l(seriesModel).scope = decalScope; + }); + ecModel.eachRawSeries(function (seriesModel) { + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + if (isFunction(seriesModel.enableAriaDecal)) { + // Let series define how to use decal palette on data + seriesModel.enableAriaDecal(); + return; + } + + var data = seriesModel.getData(); + + if (!seriesModel.isColorBySeries()) { + var dataAll_1 = seriesModel.getRawData(); + var idxMap_1 = {}; + var decalScope_1 = inner$l(seriesModel).scope; + data.each(function (idx) { + var rawIdx = data.getRawIndex(idx); + idxMap_1[rawIdx] = idx; + }); + var dataCount_1 = dataAll_1.count(); + dataAll_1.each(function (rawIdx) { + var idx = idxMap_1[rawIdx]; + var name = dataAll_1.getName(rawIdx) || rawIdx + ''; + var paletteDecal = getDecalFromPalette(seriesModel.ecModel, name, decalScope_1, dataCount_1); + var specifiedDecal = data.getItemVisual(idx, 'decal'); + data.setItemVisual(idx, 'decal', mergeDecal(specifiedDecal, paletteDecal)); + }); + } else { + var paletteDecal = getDecalFromPalette(seriesModel.ecModel, seriesModel.name, decalPaletteScope, ecModel.getSeriesCount()); + var specifiedDecal = data.getVisual('decal'); + data.setVisual('decal', mergeDecal(specifiedDecal, paletteDecal)); + } + + function mergeDecal(specifiedDecal, paletteDecal) { + // Merge decal from palette to decal from itemStyle. + // User do not need to specify all of the decal props. + var resultDecal = specifiedDecal ? extend(extend({}, paletteDecal), specifiedDecal) : paletteDecal; + resultDecal.dirty = true; + return resultDecal; + } + }); + } + } + + function setLabel() { + var labelLocale = ecModel.getLocaleModel().get('aria'); + var labelModel = ariaModel.getModel('label'); + labelModel.option = defaults(labelModel.option, labelLocale); + + if (!labelModel.get('enabled')) { + return; + } + + var dom = api.getZr().dom; + + if (labelModel.get('description')) { + dom.setAttribute('aria-label', labelModel.get('description')); + return; + } + + var seriesCnt = ecModel.getSeriesCount(); + var maxDataCnt = labelModel.get(['data', 'maxCount']) || 10; + var maxSeriesCnt = labelModel.get(['series', 'maxCount']) || 10; + var displaySeriesCnt = Math.min(seriesCnt, maxSeriesCnt); + var ariaLabel; + + if (seriesCnt < 1) { + // No series, no aria label + return; + } else { + var title = getTitle(); + + if (title) { + var withTitle = labelModel.get(['general', 'withTitle']); + ariaLabel = replace(withTitle, { + title: title + }); + } else { + ariaLabel = labelModel.get(['general', 'withoutTitle']); + } + + var seriesLabels_1 = []; + var prefix = seriesCnt > 1 ? labelModel.get(['series', 'multiple', 'prefix']) : labelModel.get(['series', 'single', 'prefix']); + ariaLabel += replace(prefix, { + seriesCount: seriesCnt + }); + ecModel.eachSeries(function (seriesModel, idx) { + if (idx < displaySeriesCnt) { + var seriesLabel = void 0; + var seriesName = seriesModel.get('name'); + var withName = seriesName ? 'withName' : 'withoutName'; + seriesLabel = seriesCnt > 1 ? labelModel.get(['series', 'multiple', withName]) : labelModel.get(['series', 'single', withName]); + seriesLabel = replace(seriesLabel, { + seriesId: seriesModel.seriesIndex, + seriesName: seriesModel.get('name'), + seriesType: getSeriesTypeName(seriesModel.subType) + }); + var data = seriesModel.getData(); + + if (data.count() > maxDataCnt) { + // Show part of data + var partialLabel = labelModel.get(['data', 'partialData']); + seriesLabel += replace(partialLabel, { + displayCnt: maxDataCnt + }); + } else { + seriesLabel += labelModel.get(['data', 'allData']); + } + + var middleSeparator_1 = labelModel.get(['data', 'separator', 'middle']); + var endSeparator_1 = labelModel.get(['data', 'separator', 'end']); + var dataLabels = []; + + for (var i = 0; i < data.count(); i++) { + if (i < maxDataCnt) { + var name_1 = data.getName(i); + var value = data.getValues(i); + var dataLabel = labelModel.get(['data', name_1 ? 'withName' : 'withoutName']); + dataLabels.push(replace(dataLabel, { + name: name_1, + value: value.join(middleSeparator_1) + })); + } + } + + seriesLabel += dataLabels.join(middleSeparator_1) + endSeparator_1; + seriesLabels_1.push(seriesLabel); + } + }); + var separatorModel = labelModel.getModel(['series', 'multiple', 'separator']); + var middleSeparator = separatorModel.get('middle'); + var endSeparator = separatorModel.get('end'); + ariaLabel += seriesLabels_1.join(middleSeparator) + endSeparator; + dom.setAttribute('aria-label', ariaLabel); + } + } + + function replace(str, keyValues) { + if (!isString(str)) { + return str; + } + + var result = str; + each(keyValues, function (value, key) { + result = result.replace(new RegExp('\\{\\s*' + key + '\\s*\\}', 'g'), value); + }); + return result; + } + + function getTitle() { + var title = ecModel.get('title'); + + if (title && title.length) { + title = title[0]; + } + + return title && title.text; + } + + function getSeriesTypeName(type) { + return ecModel.getLocaleModel().get(['series', 'typeNames'])[type] || '自定义图'; + } + } + + function ariaPreprocessor(option) { + if (!option || !option.aria) { + return; + } + + var aria = option.aria; // aria.show is deprecated and should use aria.enabled instead + + if (aria.show != null) { + aria.enabled = aria.show; + } + + aria.label = aria.label || {}; // move description, general, series, data to be under aria.label + + each(['description', 'general', 'series', 'data'], function (name) { + if (aria[name] != null) { + aria.label[name] = aria[name]; + } + }); + } + + function install$Q(registers) { + registers.registerPreprocessor(ariaPreprocessor); + registers.registerVisual(registers.PRIORITY.VISUAL.ARIA, ariaVisual); + } + + var RELATIONAL_EXPRESSION_OP_ALIAS_MAP = { + value: 'eq', + // PENDING: not good for literal semantic? + '<': 'lt', + '<=': 'lte', + '>': 'gt', + '>=': 'gte', + '=': 'eq', + '!=': 'ne', + '<>': 'ne' // Might mileading for sake of the different between '==' and '===', + // So dont support them. + // '==': 'eq', + // '===': 'seq', + // '!==': 'sne' + // PENDING: Whether support some common alias "ge", "le", "neq"? + // ge: 'gte', + // le: 'lte', + // neq: 'ne', + + }; // type RelationalExpressionOpEvaluate = (tarVal: unknown, condVal: unknown) => boolean; + + var RegExpEvaluator = + /** @class */ + function () { + function RegExpEvaluator(rVal) { + // Support condVal: RegExp | string + var condValue = this._condVal = isString(rVal) ? new RegExp(rVal) : isRegExp(rVal) ? rVal : null; + + if (condValue == null) { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = makePrintable('Illegal regexp', rVal, 'in'); + } + + throwError(errMsg); + } + } + + RegExpEvaluator.prototype.evaluate = function (lVal) { + var type = typeof lVal; + return isString(type) ? this._condVal.test(lVal) : isNumber(type) ? this._condVal.test(lVal + '') : false; + }; + + return RegExpEvaluator; + }(); + + var ConstConditionInternal = + /** @class */ + function () { + function ConstConditionInternal() {} + + ConstConditionInternal.prototype.evaluate = function () { + return this.value; + }; + + return ConstConditionInternal; + }(); + + var AndConditionInternal = + /** @class */ + function () { + function AndConditionInternal() {} + + AndConditionInternal.prototype.evaluate = function () { + var children = this.children; + + for (var i = 0; i < children.length; i++) { + if (!children[i].evaluate()) { + return false; + } + } + + return true; + }; + + return AndConditionInternal; + }(); + + var OrConditionInternal = + /** @class */ + function () { + function OrConditionInternal() {} + + OrConditionInternal.prototype.evaluate = function () { + var children = this.children; + + for (var i = 0; i < children.length; i++) { + if (children[i].evaluate()) { + return true; + } + } + + return false; + }; + + return OrConditionInternal; + }(); + + var NotConditionInternal = + /** @class */ + function () { + function NotConditionInternal() {} + + NotConditionInternal.prototype.evaluate = function () { + return !this.child.evaluate(); + }; + + return NotConditionInternal; + }(); + + var RelationalConditionInternal = + /** @class */ + function () { + function RelationalConditionInternal() {} + + RelationalConditionInternal.prototype.evaluate = function () { + var needParse = !!this.valueParser; // Call getValue with no `this`. + + var getValue = this.getValue; + var tarValRaw = getValue(this.valueGetterParam); + var tarValParsed = needParse ? this.valueParser(tarValRaw) : null; // Relational cond follow "and" logic internally. + + for (var i = 0; i < this.subCondList.length; i++) { + if (!this.subCondList[i].evaluate(needParse ? tarValParsed : tarValRaw)) { + return false; + } + } + + return true; + }; + + return RelationalConditionInternal; + }(); + + function parseOption(exprOption, getters) { + if (exprOption === true || exprOption === false) { + var cond = new ConstConditionInternal(); + cond.value = exprOption; + return cond; + } + + var errMsg = ''; + + if (!isObjectNotArray(exprOption)) { + if ("development" !== 'production') { + errMsg = makePrintable('Illegal config. Expect a plain object but actually', exprOption); + } + + throwError(errMsg); + } + + if (exprOption.and) { + return parseAndOrOption('and', exprOption, getters); + } else if (exprOption.or) { + return parseAndOrOption('or', exprOption, getters); + } else if (exprOption.not) { + return parseNotOption(exprOption, getters); + } + + return parseRelationalOption(exprOption, getters); + } + + function parseAndOrOption(op, exprOption, getters) { + var subOptionArr = exprOption[op]; + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = makePrintable('"and"/"or" condition should only be `' + op + ': [...]` and must not be empty array.', 'Illegal condition:', exprOption); + } + + if (!isArray(subOptionArr)) { + throwError(errMsg); + } + + if (!subOptionArr.length) { + throwError(errMsg); + } + + var cond = op === 'and' ? new AndConditionInternal() : new OrConditionInternal(); + cond.children = map(subOptionArr, function (subOption) { + return parseOption(subOption, getters); + }); + + if (!cond.children.length) { + throwError(errMsg); + } + + return cond; + } + + function parseNotOption(exprOption, getters) { + var subOption = exprOption.not; + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = makePrintable('"not" condition should only be `not: {}`.', 'Illegal condition:', exprOption); + } + + if (!isObjectNotArray(subOption)) { + throwError(errMsg); + } + + var cond = new NotConditionInternal(); + cond.child = parseOption(subOption, getters); + + if (!cond.child) { + throwError(errMsg); + } + + return cond; + } + + function parseRelationalOption(exprOption, getters) { + var errMsg = ''; + var valueGetterParam = getters.prepareGetValue(exprOption); + var subCondList = []; + var exprKeys = keys(exprOption); + var parserName = exprOption.parser; + var valueParser = parserName ? getRawValueParser(parserName) : null; + + for (var i = 0; i < exprKeys.length; i++) { + var keyRaw = exprKeys[i]; + + if (keyRaw === 'parser' || getters.valueGetterAttrMap.get(keyRaw)) { + continue; + } + + var op = hasOwn(RELATIONAL_EXPRESSION_OP_ALIAS_MAP, keyRaw) ? RELATIONAL_EXPRESSION_OP_ALIAS_MAP[keyRaw] : keyRaw; + var condValueRaw = exprOption[keyRaw]; + var condValueParsed = valueParser ? valueParser(condValueRaw) : condValueRaw; + var evaluator = createFilterComparator(op, condValueParsed) || op === 'reg' && new RegExpEvaluator(condValueParsed); + + if (!evaluator) { + if ("development" !== 'production') { + errMsg = makePrintable('Illegal relational operation: "' + keyRaw + '" in condition:', exprOption); + } + + throwError(errMsg); + } + + subCondList.push(evaluator); + } + + if (!subCondList.length) { + if ("development" !== 'production') { + errMsg = makePrintable('Relational condition must have at least one operator.', 'Illegal condition:', exprOption); + } // No relational operator always disabled in case of dangers result. + + + throwError(errMsg); + } + + var cond = new RelationalConditionInternal(); + cond.valueGetterParam = valueGetterParam; + cond.valueParser = valueParser; + cond.getValue = getters.getValue; + cond.subCondList = subCondList; + return cond; + } + + function isObjectNotArray(val) { + return isObject(val) && !isArrayLike(val); + } + + var ConditionalExpressionParsed = + /** @class */ + function () { + function ConditionalExpressionParsed(exprOption, getters) { + this._cond = parseOption(exprOption, getters); + } + + ConditionalExpressionParsed.prototype.evaluate = function () { + return this._cond.evaluate(); + }; + + return ConditionalExpressionParsed; + }(); + function parseConditionalExpression(exprOption, getters) { + return new ConditionalExpressionParsed(exprOption, getters); + } + + var filterTransform = { + type: 'echarts:filter', + // PEDING: enhance to filter by index rather than create new data + transform: function (params) { + // [Caveat] Fail-Fast: + // Do not return the whole dataset unless user config indicate it explicitly. + // For example, if no condition specified by mistake, return an empty result + // is better than return the entire raw soruce for user to find the mistake. + var upstream = params.upstream; + var rawItem; + var condition = parseConditionalExpression(params.config, { + valueGetterAttrMap: createHashMap({ + dimension: true + }), + prepareGetValue: function (exprOption) { + var errMsg = ''; + var dimLoose = exprOption.dimension; + + if (!hasOwn(exprOption, 'dimension')) { + if ("development" !== 'production') { + errMsg = makePrintable('Relation condition must has prop "dimension" specified.', 'Illegal condition:', exprOption); + } + + throwError(errMsg); + } + + var dimInfo = upstream.getDimensionInfo(dimLoose); + + if (!dimInfo) { + if ("development" !== 'production') { + errMsg = makePrintable('Can not find dimension info via: ' + dimLoose + '.\n', 'Existing dimensions: ', upstream.cloneAllDimensionInfo(), '.\n', 'Illegal condition:', exprOption, '.\n'); + } + + throwError(errMsg); + } + + return { + dimIdx: dimInfo.index + }; + }, + getValue: function (param) { + return upstream.retrieveValueFromItem(rawItem, param.dimIdx); + } + }); + var resultData = []; + + for (var i = 0, len = upstream.count(); i < len; i++) { + rawItem = upstream.getRawDataItem(i); + + if (condition.evaluate()) { + resultData.push(rawItem); + } + } + + return { + data: resultData + }; + } + }; + + var sampleLog = ''; + + if ("development" !== 'production') { + sampleLog = ['Valid config is like:', '{ dimension: "age", order: "asc" }', 'or [{ dimension: "age", order: "asc"], { dimension: "date", order: "desc" }]'].join(' '); + } + + var sortTransform = { + type: 'echarts:sort', + transform: function (params) { + var upstream = params.upstream; + var config = params.config; + var errMsg = ''; // Normalize + // const orderExprList: OrderExpression[] = isArray(config[0]) + // ? config as OrderExpression[] + // : [config as OrderExpression]; + + var orderExprList = normalizeToArray(config); + + if (!orderExprList.length) { + if ("development" !== 'production') { + errMsg = 'Empty `config` in sort transform.'; + } + + throwError(errMsg); + } + + var orderDefList = []; + each(orderExprList, function (orderExpr) { + var dimLoose = orderExpr.dimension; + var order = orderExpr.order; + var parserName = orderExpr.parser; + var incomparable = orderExpr.incomparable; + + if (dimLoose == null) { + if ("development" !== 'production') { + errMsg = 'Sort transform config must has "dimension" specified.' + sampleLog; + } + + throwError(errMsg); + } + + if (order !== 'asc' && order !== 'desc') { + if ("development" !== 'production') { + errMsg = 'Sort transform config must has "order" specified.' + sampleLog; + } + + throwError(errMsg); + } + + if (incomparable && incomparable !== 'min' && incomparable !== 'max') { + var errMsg_1 = ''; + + if ("development" !== 'production') { + errMsg_1 = 'incomparable must be "min" or "max" rather than "' + incomparable + '".'; + } + + throwError(errMsg_1); + } + + if (order !== 'asc' && order !== 'desc') { + var errMsg_2 = ''; + + if ("development" !== 'production') { + errMsg_2 = 'order must be "asc" or "desc" rather than "' + order + '".'; + } + + throwError(errMsg_2); + } + + var dimInfo = upstream.getDimensionInfo(dimLoose); + + if (!dimInfo) { + if ("development" !== 'production') { + errMsg = makePrintable('Can not find dimension info via: ' + dimLoose + '.\n', 'Existing dimensions: ', upstream.cloneAllDimensionInfo(), '.\n', 'Illegal config:', orderExpr, '.\n'); + } + + throwError(errMsg); + } + + var parser = parserName ? getRawValueParser(parserName) : null; + + if (parserName && !parser) { + if ("development" !== 'production') { + errMsg = makePrintable('Invalid parser name ' + parserName + '.\n', 'Illegal config:', orderExpr, '.\n'); + } + + throwError(errMsg); + } + + orderDefList.push({ + dimIdx: dimInfo.index, + parser: parser, + comparator: new SortOrderComparator(order, incomparable) + }); + }); // TODO: support it? + + var sourceFormat = upstream.sourceFormat; + + if (sourceFormat !== SOURCE_FORMAT_ARRAY_ROWS && sourceFormat !== SOURCE_FORMAT_OBJECT_ROWS) { + if ("development" !== 'production') { + errMsg = 'sourceFormat "' + sourceFormat + '" is not supported yet'; + } + + throwError(errMsg); + } // Other upstream format are all array. + + + var resultData = []; + + for (var i = 0, len = upstream.count(); i < len; i++) { + resultData.push(upstream.getRawDataItem(i)); + } + + resultData.sort(function (item0, item1) { + for (var i = 0; i < orderDefList.length; i++) { + var orderDef = orderDefList[i]; + var val0 = upstream.retrieveValueFromItem(item0, orderDef.dimIdx); + var val1 = upstream.retrieveValueFromItem(item1, orderDef.dimIdx); + + if (orderDef.parser) { + val0 = orderDef.parser(val0); + val1 = orderDef.parser(val1); + } + + var result = orderDef.comparator.evaluate(val0, val1); + + if (result !== 0) { + return result; + } + } + + return 0; + }); + return { + data: resultData + }; + } + }; + + function install$R(registers) { + registers.registerTransform(filterTransform); + registers.registerTransform(sortTransform); + } + + var DatasetModel = + /** @class */ + function (_super) { + __extends(DatasetModel, _super); + + function DatasetModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'dataset'; + return _this; + } + + DatasetModel.prototype.init = function (option, parentModel, ecModel) { + _super.prototype.init.call(this, option, parentModel, ecModel); + + this._sourceManager = new SourceManager(this); + disableTransformOptionMerge(this); + }; + + DatasetModel.prototype.mergeOption = function (newOption, ecModel) { + _super.prototype.mergeOption.call(this, newOption, ecModel); + + disableTransformOptionMerge(this); + }; + + DatasetModel.prototype.optionUpdated = function () { + this._sourceManager.dirty(); + }; + + DatasetModel.prototype.getSourceManager = function () { + return this._sourceManager; + }; + + DatasetModel.type = 'dataset'; + DatasetModel.defaultOption = { + seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN + }; + return DatasetModel; + }(ComponentModel); + + var DatasetView = + /** @class */ + function (_super) { + __extends(DatasetView, _super); + + function DatasetView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'dataset'; + return _this; + } + + DatasetView.type = 'dataset'; + return DatasetView; + }(ComponentView); + + function install$S(registers) { + registers.registerComponentModel(DatasetModel); + registers.registerComponentView(DatasetView); + } + + var CMD$4 = PathProxy.CMD; + function aroundEqual(a, b) { + return Math.abs(a - b) < 1e-5; + } + function pathToBezierCurves(path) { + var data = path.data; + var len = path.len(); + var bezierArrayGroups = []; + var currentSubpath; + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + function createNewSubpath(x, y) { + if (currentSubpath && currentSubpath.length > 2) { + bezierArrayGroups.push(currentSubpath); + } + currentSubpath = [x, y]; + } + function addLine(x0, y0, x1, y1) { + if (!(aroundEqual(x0, x1) && aroundEqual(y0, y1))) { + currentSubpath.push(x0, y0, x1, y1, x1, y1); + } + } + function addArc(startAngle, endAngle, cx, cy, rx, ry) { + var delta = Math.abs(endAngle - startAngle); + var len = Math.tan(delta / 4) * 4 / 3; + var dir = endAngle < startAngle ? -1 : 1; + var c1 = Math.cos(startAngle); + var s1 = Math.sin(startAngle); + var c2 = Math.cos(endAngle); + var s2 = Math.sin(endAngle); + var x1 = c1 * rx + cx; + var y1 = s1 * ry + cy; + var x4 = c2 * rx + cx; + var y4 = s2 * ry + cy; + var hx = rx * len * dir; + var hy = ry * len * dir; + currentSubpath.push(x1 - hx * s1, y1 + hy * c1, x4 + hx * s2, y4 - hy * c2, x4, y4); + } + var x1; + var y1; + var x2; + var y2; + for (var i = 0; i < len;) { + var cmd = data[i++]; + var isFirst = i === 1; + if (isFirst) { + xi = data[i]; + yi = data[i + 1]; + x0 = xi; + y0 = yi; + if (cmd === CMD$4.L || cmd === CMD$4.C || cmd === CMD$4.Q) { + currentSubpath = [x0, y0]; + } + } + switch (cmd) { + case CMD$4.M: + xi = x0 = data[i++]; + yi = y0 = data[i++]; + createNewSubpath(x0, y0); + break; + case CMD$4.L: + x1 = data[i++]; + y1 = data[i++]; + addLine(xi, yi, x1, y1); + xi = x1; + yi = y1; + break; + case CMD$4.C: + currentSubpath.push(data[i++], data[i++], data[i++], data[i++], xi = data[i++], yi = data[i++]); + break; + case CMD$4.Q: + x1 = data[i++]; + y1 = data[i++]; + x2 = data[i++]; + y2 = data[i++]; + currentSubpath.push(xi + 2 / 3 * (x1 - xi), yi + 2 / 3 * (y1 - yi), x2 + 2 / 3 * (x1 - x2), y2 + 2 / 3 * (y1 - y2), x2, y2); + xi = x2; + yi = y2; + break; + case CMD$4.A: + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var startAngle = data[i++]; + var endAngle = data[i++] + startAngle; + i += 1; + var anticlockwise = !data[i++]; + x1 = Math.cos(startAngle) * rx + cx; + y1 = Math.sin(startAngle) * ry + cy; + if (isFirst) { + x0 = x1; + y0 = y1; + createNewSubpath(x0, y0); + } + else { + addLine(xi, yi, x1, y1); + } + xi = Math.cos(endAngle) * rx + cx; + yi = Math.sin(endAngle) * ry + cy; + var step = (anticlockwise ? -1 : 1) * Math.PI / 2; + for (var angle = startAngle; anticlockwise ? angle > endAngle : angle < endAngle; angle += step) { + var nextAngle = anticlockwise ? Math.max(angle + step, endAngle) + : Math.min(angle + step, endAngle); + addArc(angle, nextAngle, cx, cy, rx, ry); + } + break; + case CMD$4.R: + x0 = xi = data[i++]; + y0 = yi = data[i++]; + x1 = x0 + data[i++]; + y1 = y0 + data[i++]; + createNewSubpath(x1, y0); + addLine(x1, y0, x1, y1); + addLine(x1, y1, x0, y1); + addLine(x0, y1, x0, y0); + addLine(x0, y0, x1, y0); + break; + case CMD$4.Z: + currentSubpath && addLine(xi, yi, x0, y0); + xi = x0; + yi = y0; + break; + } + } + if (currentSubpath && currentSubpath.length > 2) { + bezierArrayGroups.push(currentSubpath); + } + return bezierArrayGroups; + } + function adpativeBezier(x0, y0, x1, y1, x2, y2, x3, y3, out, scale) { + if (aroundEqual(x0, x1) && aroundEqual(y0, y1) && aroundEqual(x2, x3) && aroundEqual(y2, y3)) { + out.push(x3, y3); + return; + } + var PIXEL_DISTANCE = 2 / scale; + var PIXEL_DISTANCE_SQR = PIXEL_DISTANCE * PIXEL_DISTANCE; + var dx = x3 - x0; + var dy = y3 - y0; + var d = Math.sqrt(dx * dx + dy * dy); + dx /= d; + dy /= d; + var dx1 = x1 - x0; + var dy1 = y1 - y0; + var dx2 = x2 - x3; + var dy2 = y2 - y3; + var cp1LenSqr = dx1 * dx1 + dy1 * dy1; + var cp2LenSqr = dx2 * dx2 + dy2 * dy2; + if (cp1LenSqr < PIXEL_DISTANCE_SQR && cp2LenSqr < PIXEL_DISTANCE_SQR) { + out.push(x3, y3); + return; + } + var projLen1 = dx * dx1 + dy * dy1; + var projLen2 = -dx * dx2 - dy * dy2; + var d1Sqr = cp1LenSqr - projLen1 * projLen1; + var d2Sqr = cp2LenSqr - projLen2 * projLen2; + if (d1Sqr < PIXEL_DISTANCE_SQR && projLen1 >= 0 + && d2Sqr < PIXEL_DISTANCE_SQR && projLen2 >= 0) { + out.push(x3, y3); + return; + } + var tmpSegX = []; + var tmpSegY = []; + cubicSubdivide(x0, x1, x2, x3, 0.5, tmpSegX); + cubicSubdivide(y0, y1, y2, y3, 0.5, tmpSegY); + adpativeBezier(tmpSegX[0], tmpSegY[0], tmpSegX[1], tmpSegY[1], tmpSegX[2], tmpSegY[2], tmpSegX[3], tmpSegY[3], out, scale); + adpativeBezier(tmpSegX[4], tmpSegY[4], tmpSegX[5], tmpSegY[5], tmpSegX[6], tmpSegY[6], tmpSegX[7], tmpSegY[7], out, scale); + } + function pathToPolygons(path, scale) { + var bezierArrayGroups = pathToBezierCurves(path); + var polygons = []; + scale = scale || 1; + for (var i = 0; i < bezierArrayGroups.length; i++) { + var beziers = bezierArrayGroups[i]; + var polygon = []; + var x0 = beziers[0]; + var y0 = beziers[1]; + polygon.push(x0, y0); + for (var k = 2; k < beziers.length;) { + var x1 = beziers[k++]; + var y1 = beziers[k++]; + var x2 = beziers[k++]; + var y2 = beziers[k++]; + var x3 = beziers[k++]; + var y3 = beziers[k++]; + adpativeBezier(x0, y0, x1, y1, x2, y2, x3, y3, polygon, scale); + x0 = x3; + y0 = y3; + } + polygons.push(polygon); + } + return polygons; + } + + function getDividingGrids(dimSize, rowDim, count) { + var rowSize = dimSize[rowDim]; + var columnSize = dimSize[1 - rowDim]; + var ratio = Math.abs(rowSize / columnSize); + var rowCount = Math.ceil(Math.sqrt(ratio * count)); + var columnCount = Math.floor(count / rowCount); + if (columnCount === 0) { + columnCount = 1; + rowCount = count; + } + var grids = []; + for (var i = 0; i < rowCount; i++) { + grids.push(columnCount); + } + var currentCount = rowCount * columnCount; + var remained = count - currentCount; + if (remained > 0) { + for (var i = 0; i < remained; i++) { + grids[i % rowCount] += 1; + } + } + return grids; + } + function divideSector(sectorShape, count, outShapes) { + var r0 = sectorShape.r0; + var r = sectorShape.r; + var startAngle = sectorShape.startAngle; + var endAngle = sectorShape.endAngle; + var angle = Math.abs(endAngle - startAngle); + var arcLen = angle * r; + var deltaR = r - r0; + var isAngleRow = arcLen > Math.abs(deltaR); + var grids = getDividingGrids([arcLen, deltaR], isAngleRow ? 0 : 1, count); + var rowSize = (isAngleRow ? angle : deltaR) / grids.length; + for (var row = 0; row < grids.length; row++) { + var columnSize = (isAngleRow ? deltaR : angle) / grids[row]; + for (var column = 0; column < grids[row]; column++) { + var newShape = {}; + if (isAngleRow) { + newShape.startAngle = startAngle + rowSize * row; + newShape.endAngle = startAngle + rowSize * (row + 1); + newShape.r0 = r0 + columnSize * column; + newShape.r = r0 + columnSize * (column + 1); + } + else { + newShape.startAngle = startAngle + columnSize * column; + newShape.endAngle = startAngle + columnSize * (column + 1); + newShape.r0 = r0 + rowSize * row; + newShape.r = r0 + rowSize * (row + 1); + } + newShape.clockwise = sectorShape.clockwise; + newShape.cx = sectorShape.cx; + newShape.cy = sectorShape.cy; + outShapes.push(newShape); + } + } + } + function divideRect(rectShape, count, outShapes) { + var width = rectShape.width; + var height = rectShape.height; + var isHorizontalRow = width > height; + var grids = getDividingGrids([width, height], isHorizontalRow ? 0 : 1, count); + var rowSizeDim = isHorizontalRow ? 'width' : 'height'; + var columnSizeDim = isHorizontalRow ? 'height' : 'width'; + var rowDim = isHorizontalRow ? 'x' : 'y'; + var columnDim = isHorizontalRow ? 'y' : 'x'; + var rowSize = rectShape[rowSizeDim] / grids.length; + for (var row = 0; row < grids.length; row++) { + var columnSize = rectShape[columnSizeDim] / grids[row]; + for (var column = 0; column < grids[row]; column++) { + var newShape = {}; + newShape[rowDim] = row * rowSize; + newShape[columnDim] = column * columnSize; + newShape[rowSizeDim] = rowSize; + newShape[columnSizeDim] = columnSize; + newShape.x += rectShape.x; + newShape.y += rectShape.y; + outShapes.push(newShape); + } + } + } + function crossProduct2d$1(x1, y1, x2, y2) { + return x1 * y2 - x2 * y1; + } + function lineLineIntersect$1(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) { + var mx = a2x - a1x; + var my = a2y - a1y; + var nx = b2x - b1x; + var ny = b2y - b1y; + var nmCrossProduct = crossProduct2d$1(nx, ny, mx, my); + if (Math.abs(nmCrossProduct) < 1e-6) { + return null; + } + var b1a1x = a1x - b1x; + var b1a1y = a1y - b1y; + var p = crossProduct2d$1(b1a1x, b1a1y, nx, ny) / nmCrossProduct; + if (p < 0 || p > 1) { + return null; + } + return new Point(p * mx + a1x, p * my + a1y); + } + function projPtOnLine(pt, lineA, lineB) { + var dir = new Point(); + Point.sub(dir, lineB, lineA); + dir.normalize(); + var dir2 = new Point(); + Point.sub(dir2, pt, lineA); + var len = dir2.dot(dir); + return len; + } + function addToPoly(poly, pt) { + var last = poly[poly.length - 1]; + if (last && last[0] === pt[0] && last[1] === pt[1]) { + return; + } + poly.push(pt); + } + function splitPolygonByLine(points, lineA, lineB) { + var len = points.length; + var intersections = []; + for (var i = 0; i < len; i++) { + var p0 = points[i]; + var p1 = points[(i + 1) % len]; + var intersectionPt = lineLineIntersect$1(p0[0], p0[1], p1[0], p1[1], lineA.x, lineA.y, lineB.x, lineB.y); + if (intersectionPt) { + intersections.push({ + projPt: projPtOnLine(intersectionPt, lineA, lineB), + pt: intersectionPt, + idx: i + }); + } + } + if (intersections.length < 2) { + return [{ points: points }, { points: points }]; + } + intersections.sort(function (a, b) { + return a.projPt - b.projPt; + }); + var splitPt0 = intersections[0]; + var splitPt1 = intersections[intersections.length - 1]; + if (splitPt1.idx < splitPt0.idx) { + var tmp = splitPt0; + splitPt0 = splitPt1; + splitPt1 = tmp; + } + var splitPt0Arr = [splitPt0.pt.x, splitPt0.pt.y]; + var splitPt1Arr = [splitPt1.pt.x, splitPt1.pt.y]; + var newPolyA = [splitPt0Arr]; + var newPolyB = [splitPt1Arr]; + for (var i = splitPt0.idx + 1; i <= splitPt1.idx; i++) { + addToPoly(newPolyA, points[i].slice()); + } + addToPoly(newPolyA, splitPt1Arr); + addToPoly(newPolyA, splitPt0Arr); + for (var i = splitPt1.idx + 1; i <= splitPt0.idx + len; i++) { + addToPoly(newPolyB, points[i % len].slice()); + } + addToPoly(newPolyB, splitPt0Arr); + addToPoly(newPolyB, splitPt1Arr); + return [{ + points: newPolyA + }, { + points: newPolyB + }]; + } + function binaryDividePolygon(polygonShape) { + var points = polygonShape.points; + var min = []; + var max = []; + fromPoints(points, min, max); + var boundingRect = new BoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]); + var width = boundingRect.width; + var height = boundingRect.height; + var x = boundingRect.x; + var y = boundingRect.y; + var pt0 = new Point(); + var pt1 = new Point(); + if (width > height) { + pt0.x = pt1.x = x + width / 2; + pt0.y = y; + pt1.y = y + height; + } + else { + pt0.y = pt1.y = y + height / 2; + pt0.x = x; + pt1.x = x + width; + } + return splitPolygonByLine(points, pt0, pt1); + } + function binaryDivideRecursive(divider, shape, count, out) { + if (count === 1) { + out.push(shape); + } + else { + var mid = Math.floor(count / 2); + var sub = divider(shape); + binaryDivideRecursive(divider, sub[0], mid, out); + binaryDivideRecursive(divider, sub[1], count - mid, out); + } + return out; + } + function clone$4(path, count) { + var paths = []; + for (var i = 0; i < count; i++) { + paths.push(clonePath(path)); + } + return paths; + } + function copyPathProps(source, target) { + target.setStyle(source.style); + target.z = source.z; + target.z2 = source.z2; + target.zlevel = source.zlevel; + } + function polygonConvert(points) { + var out = []; + for (var i = 0; i < points.length;) { + out.push([points[i++], points[i++]]); + } + return out; + } + function split(path, count) { + var outShapes = []; + var shape = path.shape; + var OutShapeCtor; + switch (path.type) { + case 'rect': + divideRect(shape, count, outShapes); + OutShapeCtor = Rect; + break; + case 'sector': + divideSector(shape, count, outShapes); + OutShapeCtor = Sector; + break; + case 'circle': + divideSector({ + r0: 0, r: shape.r, startAngle: 0, endAngle: Math.PI * 2, + cx: shape.cx, cy: shape.cy + }, count, outShapes); + OutShapeCtor = Sector; + break; + default: + var m = path.getComputedTransform(); + var scale = m ? Math.sqrt(Math.max(m[0] * m[0] + m[1] * m[1], m[2] * m[2] + m[3] * m[3])) : 1; + var polygons = map(pathToPolygons(path.getUpdatedPathProxy(), scale), function (poly) { return polygonConvert(poly); }); + var polygonCount = polygons.length; + if (polygonCount === 0) { + binaryDivideRecursive(binaryDividePolygon, { + points: polygons[0] + }, count, outShapes); + } + else if (polygonCount === count) { + for (var i = 0; i < polygonCount; i++) { + outShapes.push({ + points: polygons[i] + }); + } + } + else { + var totalArea_1 = 0; + var items = map(polygons, function (poly) { + var min = []; + var max = []; + fromPoints(poly, min, max); + var area = (max[1] - min[1]) * (max[0] - min[0]); + totalArea_1 += area; + return { poly: poly, area: area }; + }); + items.sort(function (a, b) { return b.area - a.area; }); + var left = count; + for (var i = 0; i < polygonCount; i++) { + var item = items[i]; + if (left <= 0) { + break; + } + var selfCount = i === polygonCount - 1 + ? left + : Math.ceil(item.area / totalArea_1 * count); + if (selfCount < 0) { + continue; + } + binaryDivideRecursive(binaryDividePolygon, { + points: item.poly + }, selfCount, outShapes); + left -= selfCount; + } + } + OutShapeCtor = Polygon; + break; + } + if (!OutShapeCtor) { + return clone$4(path, count); + } + var out = []; + for (var i = 0; i < outShapes.length; i++) { + var subPath = new OutShapeCtor(); + subPath.setShape(outShapes[i]); + copyPathProps(path, subPath); + out.push(subPath); + } + return out; + } + + function alignSubpath(subpath1, subpath2) { + var len1 = subpath1.length; + var len2 = subpath2.length; + if (len1 === len2) { + return [subpath1, subpath2]; + } + var tmpSegX = []; + var tmpSegY = []; + var shorterPath = len1 < len2 ? subpath1 : subpath2; + var shorterLen = Math.min(len1, len2); + var diff = Math.abs(len2 - len1) / 6; + var shorterBezierCount = (shorterLen - 2) / 6; + var eachCurveSubDivCount = Math.ceil(diff / shorterBezierCount) + 1; + var newSubpath = [shorterPath[0], shorterPath[1]]; + var remained = diff; + for (var i = 2; i < shorterLen;) { + var x0 = shorterPath[i - 2]; + var y0 = shorterPath[i - 1]; + var x1 = shorterPath[i++]; + var y1 = shorterPath[i++]; + var x2 = shorterPath[i++]; + var y2 = shorterPath[i++]; + var x3 = shorterPath[i++]; + var y3 = shorterPath[i++]; + if (remained <= 0) { + newSubpath.push(x1, y1, x2, y2, x3, y3); + continue; + } + var actualSubDivCount = Math.min(remained, eachCurveSubDivCount - 1) + 1; + for (var k = 1; k <= actualSubDivCount; k++) { + var p = k / actualSubDivCount; + cubicSubdivide(x0, x1, x2, x3, p, tmpSegX); + cubicSubdivide(y0, y1, y2, y3, p, tmpSegY); + x0 = tmpSegX[3]; + y0 = tmpSegY[3]; + newSubpath.push(tmpSegX[1], tmpSegY[1], tmpSegX[2], tmpSegY[2], x0, y0); + x1 = tmpSegX[5]; + y1 = tmpSegY[5]; + x2 = tmpSegX[6]; + y2 = tmpSegY[6]; + } + remained -= actualSubDivCount - 1; + } + return shorterPath === subpath1 ? [newSubpath, subpath2] : [subpath1, newSubpath]; + } + function createSubpath(lastSubpathSubpath, otherSubpath) { + var len = lastSubpathSubpath.length; + var lastX = lastSubpathSubpath[len - 2]; + var lastY = lastSubpathSubpath[len - 1]; + var newSubpath = []; + for (var i = 0; i < otherSubpath.length;) { + newSubpath[i++] = lastX; + newSubpath[i++] = lastY; + } + return newSubpath; + } + function alignBezierCurves(array1, array2) { + var _a; + var lastSubpath1; + var lastSubpath2; + var newArray1 = []; + var newArray2 = []; + for (var i = 0; i < Math.max(array1.length, array2.length); i++) { + var subpath1 = array1[i]; + var subpath2 = array2[i]; + var newSubpath1 = void 0; + var newSubpath2 = void 0; + if (!subpath1) { + newSubpath1 = createSubpath(lastSubpath1 || subpath2, subpath2); + newSubpath2 = subpath2; + } + else if (!subpath2) { + newSubpath2 = createSubpath(lastSubpath2 || subpath1, subpath1); + newSubpath1 = subpath1; + } + else { + _a = alignSubpath(subpath1, subpath2), newSubpath1 = _a[0], newSubpath2 = _a[1]; + lastSubpath1 = newSubpath1; + lastSubpath2 = newSubpath2; + } + newArray1.push(newSubpath1); + newArray2.push(newSubpath2); + } + return [newArray1, newArray2]; + } + function centroid$1(array) { + var signedArea = 0; + var cx = 0; + var cy = 0; + var len = array.length; + for (var i = 0, j = len - 2; i < len; j = i, i += 2) { + var x0 = array[j]; + var y0 = array[j + 1]; + var x1 = array[i]; + var y1 = array[i + 1]; + var a = x0 * y1 - x1 * y0; + signedArea += a; + cx += (x0 + x1) * a; + cy += (y0 + y1) * a; + } + if (signedArea === 0) { + return [array[0] || 0, array[1] || 0]; + } + return [cx / signedArea / 3, cy / signedArea / 3, signedArea]; + } + function findBestRingOffset(fromSubBeziers, toSubBeziers, fromCp, toCp) { + var bezierCount = (fromSubBeziers.length - 2) / 6; + var bestScore = Infinity; + var bestOffset = 0; + var len = fromSubBeziers.length; + var len2 = len - 2; + for (var offset = 0; offset < bezierCount; offset++) { + var cursorOffset = offset * 6; + var score = 0; + for (var k = 0; k < len; k += 2) { + var idx = k === 0 ? cursorOffset : ((cursorOffset + k - 2) % len2 + 2); + var x0 = fromSubBeziers[idx] - fromCp[0]; + var y0 = fromSubBeziers[idx + 1] - fromCp[1]; + var x1 = toSubBeziers[k] - toCp[0]; + var y1 = toSubBeziers[k + 1] - toCp[1]; + var dx = x1 - x0; + var dy = y1 - y0; + score += dx * dx + dy * dy; + } + if (score < bestScore) { + bestScore = score; + bestOffset = offset; + } + } + return bestOffset; + } + function reverse(array) { + var newArr = []; + var len = array.length; + for (var i = 0; i < len; i += 2) { + newArr[i] = array[len - i - 2]; + newArr[i + 1] = array[len - i - 1]; + } + return newArr; + } + function findBestMorphingRotation(fromArr, toArr, searchAngleIteration, searchAngleRange) { + var result = []; + var fromNeedsReverse; + for (var i = 0; i < fromArr.length; i++) { + var fromSubpathBezier = fromArr[i]; + var toSubpathBezier = toArr[i]; + var fromCp = centroid$1(fromSubpathBezier); + var toCp = centroid$1(toSubpathBezier); + if (fromNeedsReverse == null) { + fromNeedsReverse = fromCp[2] < 0 !== toCp[2] < 0; + } + var newFromSubpathBezier = []; + var newToSubpathBezier = []; + var bestAngle = 0; + var bestScore = Infinity; + var tmpArr = []; + var len = fromSubpathBezier.length; + if (fromNeedsReverse) { + fromSubpathBezier = reverse(fromSubpathBezier); + } + var offset = findBestRingOffset(fromSubpathBezier, toSubpathBezier, fromCp, toCp) * 6; + var len2 = len - 2; + for (var k = 0; k < len2; k += 2) { + var idx = (offset + k) % len2 + 2; + newFromSubpathBezier[k + 2] = fromSubpathBezier[idx] - fromCp[0]; + newFromSubpathBezier[k + 3] = fromSubpathBezier[idx + 1] - fromCp[1]; + } + newFromSubpathBezier[0] = fromSubpathBezier[offset] - fromCp[0]; + newFromSubpathBezier[1] = fromSubpathBezier[offset + 1] - fromCp[1]; + if (searchAngleIteration > 0) { + var step = searchAngleRange / searchAngleIteration; + for (var angle = -searchAngleRange / 2; angle <= searchAngleRange / 2; angle += step) { + var sa = Math.sin(angle); + var ca = Math.cos(angle); + var score = 0; + for (var k = 0; k < fromSubpathBezier.length; k += 2) { + var x0 = newFromSubpathBezier[k]; + var y0 = newFromSubpathBezier[k + 1]; + var x1 = toSubpathBezier[k] - toCp[0]; + var y1 = toSubpathBezier[k + 1] - toCp[1]; + var newX1 = x1 * ca - y1 * sa; + var newY1 = x1 * sa + y1 * ca; + tmpArr[k] = newX1; + tmpArr[k + 1] = newY1; + var dx = newX1 - x0; + var dy = newY1 - y0; + score += dx * dx + dy * dy; + } + if (score < bestScore) { + bestScore = score; + bestAngle = angle; + for (var m = 0; m < tmpArr.length; m++) { + newToSubpathBezier[m] = tmpArr[m]; + } + } + } + } + else { + for (var i_1 = 0; i_1 < len; i_1 += 2) { + newToSubpathBezier[i_1] = toSubpathBezier[i_1] - toCp[0]; + newToSubpathBezier[i_1 + 1] = toSubpathBezier[i_1 + 1] - toCp[1]; + } + } + result.push({ + from: newFromSubpathBezier, + to: newToSubpathBezier, + fromCp: fromCp, + toCp: toCp, + rotation: -bestAngle + }); + } + return result; + } + function isCombineMorphing(path) { + return path.__isCombineMorphing; + } + var SAVED_METHOD_PREFIX = '__mOriginal_'; + function saveAndModifyMethod(obj, methodName, modifiers) { + var savedMethodName = SAVED_METHOD_PREFIX + methodName; + var originalMethod = obj[savedMethodName] || obj[methodName]; + if (!obj[savedMethodName]) { + obj[savedMethodName] = obj[methodName]; + } + var replace = modifiers.replace; + var after = modifiers.after; + var before = modifiers.before; + obj[methodName] = function () { + var args = arguments; + var res; + before && before.apply(this, args); + if (replace) { + res = replace.apply(this, args); + } + else { + res = originalMethod.apply(this, args); + } + after && after.apply(this, args); + return res; + }; + } + function restoreMethod(obj, methodName) { + var savedMethodName = SAVED_METHOD_PREFIX + methodName; + if (obj[savedMethodName]) { + obj[methodName] = obj[savedMethodName]; + obj[savedMethodName] = null; + } + } + function applyTransformOnBeziers(bezierCurves, mm) { + for (var i = 0; i < bezierCurves.length; i++) { + var subBeziers = bezierCurves[i]; + for (var k = 0; k < subBeziers.length;) { + var x = subBeziers[k]; + var y = subBeziers[k + 1]; + subBeziers[k++] = mm[0] * x + mm[2] * y + mm[4]; + subBeziers[k++] = mm[1] * x + mm[3] * y + mm[5]; + } + } + } + function prepareMorphPath(fromPath, toPath) { + var fromPathProxy = fromPath.getUpdatedPathProxy(); + var toPathProxy = toPath.getUpdatedPathProxy(); + var _a = alignBezierCurves(pathToBezierCurves(fromPathProxy), pathToBezierCurves(toPathProxy)), fromBezierCurves = _a[0], toBezierCurves = _a[1]; + var fromPathTransform = fromPath.getComputedTransform(); + var toPathTransform = toPath.getComputedTransform(); + function updateIdentityTransform() { + this.transform = null; + } + fromPathTransform && applyTransformOnBeziers(fromBezierCurves, fromPathTransform); + toPathTransform && applyTransformOnBeziers(toBezierCurves, toPathTransform); + saveAndModifyMethod(toPath, 'updateTransform', { replace: updateIdentityTransform }); + toPath.transform = null; + var morphingData = findBestMorphingRotation(fromBezierCurves, toBezierCurves, 10, Math.PI); + var tmpArr = []; + saveAndModifyMethod(toPath, 'buildPath', { replace: function (path) { + var t = toPath.__morphT; + var onet = 1 - t; + var newCp = []; + for (var i = 0; i < morphingData.length; i++) { + var item = morphingData[i]; + var from = item.from; + var to = item.to; + var angle = item.rotation * t; + var fromCp = item.fromCp; + var toCp = item.toCp; + var sa = Math.sin(angle); + var ca = Math.cos(angle); + lerp(newCp, fromCp, toCp, t); + for (var m = 0; m < from.length; m += 2) { + var x0_1 = from[m]; + var y0_1 = from[m + 1]; + var x1 = to[m]; + var y1 = to[m + 1]; + var x = x0_1 * onet + x1 * t; + var y = y0_1 * onet + y1 * t; + tmpArr[m] = (x * ca - y * sa) + newCp[0]; + tmpArr[m + 1] = (x * sa + y * ca) + newCp[1]; + } + var x0 = tmpArr[0]; + var y0 = tmpArr[1]; + path.moveTo(x0, y0); + for (var m = 2; m < from.length;) { + var x1 = tmpArr[m++]; + var y1 = tmpArr[m++]; + var x2 = tmpArr[m++]; + var y2 = tmpArr[m++]; + var x3 = tmpArr[m++]; + var y3 = tmpArr[m++]; + if (x0 === x1 && y0 === y1 && x2 === x3 && y2 === y3) { + path.lineTo(x3, y3); + } + else { + path.bezierCurveTo(x1, y1, x2, y2, x3, y3); + } + x0 = x3; + y0 = y3; + } + } + } }); + } + function morphPath(fromPath, toPath, animationOpts) { + if (!fromPath || !toPath) { + return toPath; + } + var oldDone = animationOpts.done; + var oldDuring = animationOpts.during; + prepareMorphPath(fromPath, toPath); + toPath.__morphT = 0; + function restoreToPath() { + restoreMethod(toPath, 'buildPath'); + restoreMethod(toPath, 'updateTransform'); + toPath.__morphT = -1; + toPath.createPathProxy(); + toPath.dirtyShape(); + } + toPath.animateTo({ + __morphT: 1 + }, defaults({ + during: function (p) { + toPath.dirtyShape(); + oldDuring && oldDuring(p); + }, + done: function () { + restoreToPath(); + oldDone && oldDone(); + } + }, animationOpts)); + return toPath; + } + function hilbert(x, y, minX, minY, maxX, maxY) { + var bits = 16; + x = (maxX === minX) ? 0 : Math.round(32767 * (x - minX) / (maxX - minX)); + y = (maxY === minY) ? 0 : Math.round(32767 * (y - minY) / (maxY - minY)); + var d = 0; + var tmp; + for (var s = (1 << bits) / 2; s > 0; s /= 2) { + var rx = 0; + var ry = 0; + if ((x & s) > 0) { + rx = 1; + } + if ((y & s) > 0) { + ry = 1; + } + d += s * s * ((3 * rx) ^ ry); + if (ry === 0) { + if (rx === 1) { + x = s - 1 - x; + y = s - 1 - y; + } + tmp = x; + x = y; + y = tmp; + } + } + return d; + } + function sortPaths(pathList) { + var xMin = Infinity; + var yMin = Infinity; + var xMax = -Infinity; + var yMax = -Infinity; + var cps = map(pathList, function (path) { + var rect = path.getBoundingRect(); + var m = path.getComputedTransform(); + var x = rect.x + rect.width / 2 + (m ? m[4] : 0); + var y = rect.y + rect.height / 2 + (m ? m[5] : 0); + xMin = Math.min(x, xMin); + yMin = Math.min(y, yMin); + xMax = Math.max(x, xMax); + yMax = Math.max(y, yMax); + return [x, y]; + }); + var items = map(cps, function (cp, idx) { + return { + cp: cp, + z: hilbert(cp[0], cp[1], xMin, yMin, xMax, yMax), + path: pathList[idx] + }; + }); + return items.sort(function (a, b) { return a.z - b.z; }).map(function (item) { return item.path; }); + } + function defaultDividePath(param) { + return split(param.path, param.count); + } + function createEmptyReturn() { + return { + fromIndividuals: [], + toIndividuals: [], + count: 0 + }; + } + function combineMorph(fromList, toPath, animationOpts) { + var fromPathList = []; + function addFromPath(fromList) { + for (var i = 0; i < fromList.length; i++) { + var from = fromList[i]; + if (isCombineMorphing(from)) { + addFromPath(from.childrenRef()); + } + else if (from instanceof Path) { + fromPathList.push(from); + } + } + } + addFromPath(fromList); + var separateCount = fromPathList.length; + if (!separateCount) { + return createEmptyReturn(); + } + var dividePath = animationOpts.dividePath || defaultDividePath; + var toSubPathList = dividePath({ + path: toPath, count: separateCount + }); + if (toSubPathList.length !== separateCount) { + console.error('Invalid morphing: unmatched splitted path'); + return createEmptyReturn(); + } + fromPathList = sortPaths(fromPathList); + toSubPathList = sortPaths(toSubPathList); + var oldDone = animationOpts.done; + var oldDuring = animationOpts.during; + var individualDelay = animationOpts.individualDelay; + var identityTransform = new Transformable(); + for (var i = 0; i < separateCount; i++) { + var from = fromPathList[i]; + var to = toSubPathList[i]; + to.parent = toPath; + to.copyTransform(identityTransform); + if (!individualDelay) { + prepareMorphPath(from, to); + } + } + toPath.__isCombineMorphing = true; + toPath.childrenRef = function () { + return toSubPathList; + }; + function addToSubPathListToZr(zr) { + for (var i = 0; i < toSubPathList.length; i++) { + toSubPathList[i].addSelfToZr(zr); + } + } + saveAndModifyMethod(toPath, 'addSelfToZr', { + after: function (zr) { + addToSubPathListToZr(zr); + } + }); + saveAndModifyMethod(toPath, 'removeSelfFromZr', { + after: function (zr) { + for (var i = 0; i < toSubPathList.length; i++) { + toSubPathList[i].removeSelfFromZr(zr); + } + } + }); + function restoreToPath() { + toPath.__isCombineMorphing = false; + toPath.__morphT = -1; + toPath.childrenRef = null; + restoreMethod(toPath, 'addSelfToZr'); + restoreMethod(toPath, 'removeSelfFromZr'); + } + var toLen = toSubPathList.length; + if (individualDelay) { + var animating_1 = toLen; + var eachDone = function () { + animating_1--; + if (animating_1 === 0) { + restoreToPath(); + oldDone && oldDone(); + } + }; + for (var i = 0; i < toLen; i++) { + var indivdualAnimationOpts = individualDelay ? defaults({ + delay: (animationOpts.delay || 0) + individualDelay(i, toLen, fromPathList[i], toSubPathList[i]), + done: eachDone + }, animationOpts) : animationOpts; + morphPath(fromPathList[i], toSubPathList[i], indivdualAnimationOpts); + } + } + else { + toPath.__morphT = 0; + toPath.animateTo({ + __morphT: 1 + }, defaults({ + during: function (p) { + for (var i = 0; i < toLen; i++) { + var child = toSubPathList[i]; + child.__morphT = toPath.__morphT; + child.dirtyShape(); + } + oldDuring && oldDuring(p); + }, + done: function () { + restoreToPath(); + for (var i = 0; i < fromList.length; i++) { + restoreMethod(fromList[i], 'updateTransform'); + } + oldDone && oldDone(); + } + }, animationOpts)); + } + if (toPath.__zr) { + addToSubPathListToZr(toPath.__zr); + } + return { + fromIndividuals: fromPathList, + toIndividuals: toSubPathList, + count: toLen + }; + } + function separateMorph(fromPath, toPathList, animationOpts) { + var toLen = toPathList.length; + var fromPathList = []; + var dividePath = animationOpts.dividePath || defaultDividePath; + function addFromPath(fromList) { + for (var i = 0; i < fromList.length; i++) { + var from = fromList[i]; + if (isCombineMorphing(from)) { + addFromPath(from.childrenRef()); + } + else if (from instanceof Path) { + fromPathList.push(from); + } + } + } + if (isCombineMorphing(fromPath)) { + addFromPath(fromPath.childrenRef()); + var fromLen = fromPathList.length; + if (fromLen < toLen) { + var k = 0; + for (var i = fromLen; i < toLen; i++) { + fromPathList.push(clonePath(fromPathList[k++ % fromLen])); + } + } + fromPathList.length = toLen; + } + else { + fromPathList = dividePath({ path: fromPath, count: toLen }); + var fromPathTransform = fromPath.getComputedTransform(); + for (var i = 0; i < fromPathList.length; i++) { + fromPathList[i].setLocalTransform(fromPathTransform); + } + if (fromPathList.length !== toLen) { + console.error('Invalid morphing: unmatched splitted path'); + return createEmptyReturn(); + } + } + fromPathList = sortPaths(fromPathList); + toPathList = sortPaths(toPathList); + var individualDelay = animationOpts.individualDelay; + for (var i = 0; i < toLen; i++) { + var indivdualAnimationOpts = individualDelay ? defaults({ + delay: (animationOpts.delay || 0) + individualDelay(i, toLen, fromPathList[i], toPathList[i]) + }, animationOpts) : animationOpts; + morphPath(fromPathList[i], toPathList[i], indivdualAnimationOpts); + } + return { + fromIndividuals: fromPathList, + toIndividuals: toPathList, + count: toPathList.length + }; + } + + function isMultiple(elements) { + return isArray(elements[0]); + } + + function prepareMorphBatches(one, many) { + var batches = []; + var batchCount = one.length; + + for (var i = 0; i < batchCount; i++) { + batches.push({ + one: one[i], + many: [] + }); + } + + for (var i = 0; i < many.length; i++) { + var len = many[i].length; + var k = void 0; + + for (k = 0; k < len; k++) { + batches[k % batchCount].many.push(many[i][k]); + } + } + + var off = 0; // If one has more paths than each one of many. average them. + + for (var i = batchCount - 1; i >= 0; i--) { + if (!batches[i].many.length) { + var moveFrom = batches[off].many; + + if (moveFrom.length <= 1) { + // Not enough + // Start from the first one. + if (off) { + off = 0; + } else { + return batches; + } + } + + var len = moveFrom.length; + var mid = Math.ceil(len / 2); + batches[i].many = moveFrom.slice(mid, len); + batches[off].many = moveFrom.slice(0, mid); + off++; + } + } + + return batches; + } + + var pathDividers = { + clone: function (params) { + var ret = []; // Fitting the alpha + + var approxOpacity = 1 - Math.pow(1 - params.path.style.opacity, 1 / params.count); + + for (var i = 0; i < params.count; i++) { + var cloned = clonePath(params.path); + cloned.setStyle('opacity', approxOpacity); + ret.push(cloned); + } + + return ret; + }, + // Use the default divider + split: null + }; + function applyMorphAnimation(from, to, divideShape, seriesModel, dataIndex, animateOtherProps) { + if (!from.length || !to.length) { + return; + } + + var updateAnimationCfg = getAnimationConfig('update', seriesModel, dataIndex); + + if (!(updateAnimationCfg && updateAnimationCfg.duration > 0)) { + return; + } + + var animationDelay = seriesModel.getModel('universalTransition').get('delay'); + var animationCfg = Object.assign({ + // Need to setToFinal so the further calculation based on the style can be correct. + // Like emphasis color. + setToFinal: true + }, updateAnimationCfg); + var many; + var one; + + if (isMultiple(from)) { + // manyToOne + many = from; + one = to; + } + + if (isMultiple(to)) { + // oneToMany + many = to; + one = from; + } + + function morphOneBatch(batch, fromIsMany, animateIndex, animateCount, forceManyOne) { + var batchMany = batch.many; + var batchOne = batch.one; + + if (batchMany.length === 1 && !forceManyOne) { + // Is one to one + var batchFrom = fromIsMany ? batchMany[0] : batchOne; + var batchTo = fromIsMany ? batchOne : batchMany[0]; + + if (isCombineMorphing(batchFrom)) { + // Keep doing combine animation. + morphOneBatch({ + many: [batchFrom], + one: batchTo + }, true, animateIndex, animateCount, true); + } else { + var individualAnimationCfg = animationDelay ? defaults({ + delay: animationDelay(animateIndex, animateCount) + }, animationCfg) : animationCfg; + morphPath(batchFrom, batchTo, individualAnimationCfg); + animateOtherProps(batchFrom, batchTo, batchFrom, batchTo, individualAnimationCfg); + } + } else { + var separateAnimationCfg = defaults({ + dividePath: pathDividers[divideShape], + individualDelay: animationDelay && function (idx, count, fromPath, toPath) { + return animationDelay(idx + animateIndex, animateCount); + } + }, animationCfg); + + var _a = fromIsMany ? combineMorph(batchMany, batchOne, separateAnimationCfg) : separateMorph(batchOne, batchMany, separateAnimationCfg), + fromIndividuals = _a.fromIndividuals, + toIndividuals = _a.toIndividuals; + + var count = fromIndividuals.length; + + for (var k = 0; k < count; k++) { + var individualAnimationCfg = animationDelay ? defaults({ + delay: animationDelay(k, count) + }, animationCfg) : animationCfg; + animateOtherProps(fromIndividuals[k], toIndividuals[k], fromIsMany ? batchMany[k] : batch.one, fromIsMany ? batch.one : batchMany[k], individualAnimationCfg); + } + } + } + + var fromIsMany = many ? many === from // Is one to one. If the path number not match. also needs do merge and separate morphing. + : from.length > to.length; + var morphBatches = many ? prepareMorphBatches(one, many) : prepareMorphBatches(fromIsMany ? to : from, [fromIsMany ? from : to]); + var animateCount = 0; + + for (var i = 0; i < morphBatches.length; i++) { + animateCount += morphBatches[i].many.length; + } + + var animateIndex = 0; + + for (var i = 0; i < morphBatches.length; i++) { + morphOneBatch(morphBatches[i], fromIsMany, animateIndex, animateCount); + animateIndex += morphBatches[i].many.length; + } + } + function getPathList(elements) { + if (!elements) { + return []; + } + + if (isArray(elements)) { + var pathList_1 = []; + + for (var i = 0; i < elements.length; i++) { + pathList_1.push(getPathList(elements[i])); + } + + return pathList_1; + } + + var pathList = []; + elements.traverse(function (el) { + if (el instanceof Path && !el.disableMorphing && !el.invisible && !el.ignore) { + pathList.push(el); + } + }); + return pathList; + } + + var DATA_COUNT_THRESHOLD = 1e4; + var getUniversalTransitionGlobalStore = makeInner(); + + function getGroupIdDimension(data) { + var dimensions = data.dimensions; + + for (var i = 0; i < dimensions.length; i++) { + var dimInfo = data.getDimensionInfo(dimensions[i]); + + if (dimInfo && dimInfo.otherDims.itemGroupId === 0) { + return dimensions[i]; + } + } + } + + function flattenDataDiffItems(list) { + var items = []; + each(list, function (seriesInfo) { + var data = seriesInfo.data; + + if (data.count() > DATA_COUNT_THRESHOLD) { + if ("development" !== 'production') { + warn('Universal transition is disabled on large data > 10k.'); + } + + return; + } + + var indices = data.getIndices(); + var groupDim = getGroupIdDimension(data); + + for (var dataIndex = 0; dataIndex < indices.length; dataIndex++) { + items.push({ + data: data, + dim: seriesInfo.dim || groupDim, + divide: seriesInfo.divide, + dataIndex: dataIndex + }); + } + }); + return items; + } + + function fadeInElement(newEl, newSeries, newIndex) { + newEl.traverse(function (el) { + if (el instanceof Path) { + // TODO use fade in animation for target element. + initProps(el, { + style: { + opacity: 0 + } + }, newSeries, { + dataIndex: newIndex, + isFrom: true + }); + } + }); + } + + function removeEl$1(el) { + if (el.parent) { + // Bake parent transform to element. + // So it can still have proper transform to transition after it's removed. + var computedTransform = el.getComputedTransform(); + el.setLocalTransform(computedTransform); + el.parent.remove(el); + } + } + + function stopAnimation(el) { + el.stopAnimation(); + + if (el.isGroup) { + el.traverse(function (child) { + child.stopAnimation(); + }); + } + } + + function animateElementStyles(el, dataIndex, seriesModel) { + var animationConfig = getAnimationConfig('update', seriesModel, dataIndex); + animationConfig && el.traverse(function (child) { + if (child instanceof Displayable) { + var oldStyle = getOldStyle(child); + + if (oldStyle) { + child.animateFrom({ + style: oldStyle + }, animationConfig); + } + } + }); + } + + function isAllIdSame(oldDiffItems, newDiffItems) { + var len = oldDiffItems.length; + + if (len !== newDiffItems.length) { + return false; + } + + for (var i = 0; i < len; i++) { + var oldItem = oldDiffItems[i]; + var newItem = newDiffItems[i]; + + if (oldItem.data.getId(oldItem.dataIndex) !== newItem.data.getId(newItem.dataIndex)) { + return false; + } + } + + return true; + } + + function transitionBetween(oldList, newList, api) { + var oldDiffItems = flattenDataDiffItems(oldList); + var newDiffItems = flattenDataDiffItems(newList); + + function updateMorphingPathProps(from, to, rawFrom, rawTo, animationCfg) { + if (rawFrom || from) { + to.animateFrom({ + style: rawFrom && rawFrom !== from ? // dividingMethod like clone may override the style(opacity) + // So extend it to raw style. + extend(extend({}, rawFrom.style), from.style) : from.style + }, animationCfg); + } + } + + function findKeyDim(items) { + for (var i = 0; i < items.length; i++) { + if (items[i].dim) { + return items[i].dim; + } + } + } + + var oldKeyDim = findKeyDim(oldDiffItems); + var newKeyDim = findKeyDim(newDiffItems); + var hasMorphAnimation = false; + + function createKeyGetter(isOld, onlyGetId) { + return function (diffItem) { + var data = diffItem.data; + var dataIndex = diffItem.dataIndex; // TODO if specified dim + + if (onlyGetId) { + return data.getId(dataIndex); + } // Use group id as transition key by default. + // So we can achieve multiple to multiple animation like drilldown / up naturally. + // If group id not exits. Use id instead. If so, only one to one transition will be applied. + + + var dataGroupId = data.hostModel && data.hostModel.get('dataGroupId'); // If specified key dimension(itemGroupId by default). Use this same dimension from other data. + // PENDING: If only use key dimension of newData. + + var keyDim = isOld ? oldKeyDim || newKeyDim : newKeyDim || oldKeyDim; + var dimInfo = keyDim && data.getDimensionInfo(keyDim); + var dimOrdinalMeta = dimInfo && dimInfo.ordinalMeta; + + if (dimInfo) { + // Get from encode.itemGroupId. + var key = data.get(dimInfo.name, dataIndex); + + if (dimOrdinalMeta) { + return dimOrdinalMeta.categories[key] || key + ''; + } + + return key + ''; + } // Get groupId from raw item. { groupId: '' } + + + var itemVal = data.getRawDataItem(dataIndex); + + if (itemVal && itemVal.groupId) { + return itemVal.groupId + ''; + } + + return dataGroupId || data.getId(dataIndex); + }; + } // Use id if it's very likely to be an one to one animation + // It's more robust than groupId + // TODO Check if key dimension is specified. + + + var useId = isAllIdSame(oldDiffItems, newDiffItems); + var isElementStillInChart = {}; + + if (!useId) { + // We may have different diff strategy with basicTransition if we use other dimension as key. + // If so, we can't simply check if oldEl is same with newEl. We need a map to check if oldEl is still being used in the new chart. + // We can't use the elements that already being morphed. Let it keep it's original basic transition. + for (var i = 0; i < newDiffItems.length; i++) { + var newItem = newDiffItems[i]; + var el = newItem.data.getItemGraphicEl(newItem.dataIndex); + + if (el) { + isElementStillInChart[el.id] = true; + } + } + } + + function updateOneToOne(newIndex, oldIndex) { + var oldItem = oldDiffItems[oldIndex]; + var newItem = newDiffItems[newIndex]; + var newSeries = newItem.data.hostModel; // TODO Mark this elements is morphed and don't morph them anymore + + var oldEl = oldItem.data.getItemGraphicEl(oldItem.dataIndex); + var newEl = newItem.data.getItemGraphicEl(newItem.dataIndex); // Can't handle same elements. + + if (oldEl === newEl) { + newEl && animateElementStyles(newEl, newItem.dataIndex, newSeries); + return; + } + + if ( // We can't use the elements that already being morphed + oldEl && isElementStillInChart[oldEl.id]) { + return; + } + + if (newEl) { + // TODO: If keep animating the group in case + // some of the elements don't want to be morphed. + // TODO Label? + stopAnimation(newEl); + + if (oldEl) { + stopAnimation(oldEl); // If old element is doing leaving animation. stop it and remove it immediately. + + removeEl$1(oldEl); + hasMorphAnimation = true; + applyMorphAnimation(getPathList(oldEl), getPathList(newEl), newItem.divide, newSeries, newIndex, updateMorphingPathProps); + } else { + fadeInElement(newEl, newSeries, newIndex); + } + } // else keep oldEl leaving animation. + + } + + new DataDiffer(oldDiffItems, newDiffItems, createKeyGetter(true, useId), createKeyGetter(false, useId), null, 'multiple').update(updateOneToOne).updateManyToOne(function (newIndex, oldIndices) { + var newItem = newDiffItems[newIndex]; + var newData = newItem.data; + var newSeries = newData.hostModel; + var newEl = newData.getItemGraphicEl(newItem.dataIndex); + var oldElsList = filter(map(oldIndices, function (idx) { + return oldDiffItems[idx].data.getItemGraphicEl(oldDiffItems[idx].dataIndex); + }), function (oldEl) { + return oldEl && oldEl !== newEl && !isElementStillInChart[oldEl.id]; + }); + + if (newEl) { + stopAnimation(newEl); + + if (oldElsList.length) { + // If old element is doing leaving animation. stop it and remove it immediately. + each(oldElsList, function (oldEl) { + stopAnimation(oldEl); + removeEl$1(oldEl); + }); + hasMorphAnimation = true; + applyMorphAnimation(getPathList(oldElsList), getPathList(newEl), newItem.divide, newSeries, newIndex, updateMorphingPathProps); + } else { + fadeInElement(newEl, newSeries, newItem.dataIndex); + } + } // else keep oldEl leaving animation. + + }).updateOneToMany(function (newIndices, oldIndex) { + var oldItem = oldDiffItems[oldIndex]; + var oldEl = oldItem.data.getItemGraphicEl(oldItem.dataIndex); // We can't use the elements that already being morphed + + if (oldEl && isElementStillInChart[oldEl.id]) { + return; + } + + var newElsList = filter(map(newIndices, function (idx) { + return newDiffItems[idx].data.getItemGraphicEl(newDiffItems[idx].dataIndex); + }), function (el) { + return el && el !== oldEl; + }); + var newSeris = newDiffItems[newIndices[0]].data.hostModel; + + if (newElsList.length) { + each(newElsList, function (newEl) { + return stopAnimation(newEl); + }); + + if (oldEl) { + stopAnimation(oldEl); // If old element is doing leaving animation. stop it and remove it immediately. + + removeEl$1(oldEl); + hasMorphAnimation = true; + applyMorphAnimation(getPathList(oldEl), getPathList(newElsList), oldItem.divide, // Use divide on old. + newSeris, newIndices[0], updateMorphingPathProps); + } else { + each(newElsList, function (newEl) { + return fadeInElement(newEl, newSeris, newIndices[0]); + }); + } + } // else keep oldEl leaving animation. + + }).updateManyToMany(function (newIndices, oldIndices) { + // If two data are same and both have groupId. + // Normally they should be diff by id. + new DataDiffer(oldIndices, newIndices, function (rawIdx) { + return oldDiffItems[rawIdx].data.getId(oldDiffItems[rawIdx].dataIndex); + }, function (rawIdx) { + return newDiffItems[rawIdx].data.getId(newDiffItems[rawIdx].dataIndex); + }).update(function (newIndex, oldIndex) { + // Use the original index + updateOneToOne(newIndices[newIndex], oldIndices[oldIndex]); + }).execute(); + }).execute(); + + if (hasMorphAnimation) { + each(newList, function (_a) { + var data = _a.data; + var seriesModel = data.hostModel; + var view = seriesModel && api.getViewOfSeriesModel(seriesModel); + var animationCfg = getAnimationConfig('update', seriesModel, 0); // use 0 index. + + if (view && seriesModel.isAnimationEnabled() && animationCfg && animationCfg.duration > 0) { + view.group.traverse(function (el) { + if (el instanceof Path && !el.animators.length) { + // We can't accept there still exists element that has no animation + // if universalTransition is enabled + el.animateFrom({ + style: { + opacity: 0 + } + }, animationCfg); + } + }); + } + }); + } + } + + function getSeriesTransitionKey(series) { + var seriesKey = series.getModel('universalTransition').get('seriesKey'); + + if (!seriesKey) { + // Use series id by default. + return series.id; + } + + return seriesKey; + } + + function convertArraySeriesKeyToString(seriesKey) { + if (isArray(seriesKey)) { + // Order independent. + return seriesKey.sort().join(','); + } + + return seriesKey; + } + + function getDivideShapeFromData(data) { + if (data.hostModel) { + return data.hostModel.getModel('universalTransition').get('divideShape'); + } + } + + function findTransitionSeriesBatches(globalStore, params) { + var updateBatches = createHashMap(); + var oldDataMap = createHashMap(); // Map that only store key in array seriesKey. + // Which is used to query the old data when transition from one to multiple series. + + var oldDataMapForSplit = createHashMap(); + each(globalStore.oldSeries, function (series, idx) { + var oldData = globalStore.oldData[idx]; + var transitionKey = getSeriesTransitionKey(series); + var transitionKeyStr = convertArraySeriesKeyToString(transitionKey); + oldDataMap.set(transitionKeyStr, oldData); + + if (isArray(transitionKey)) { + // Same key can't in different array seriesKey. + each(transitionKey, function (key) { + oldDataMapForSplit.set(key, { + data: oldData, + key: transitionKeyStr + }); + }); + } + }); + + function checkTransitionSeriesKeyDuplicated(transitionKeyStr) { + if (updateBatches.get(transitionKeyStr)) { + warn("Duplicated seriesKey in universalTransition " + transitionKeyStr); + } + } + + each(params.updatedSeries, function (series) { + if (series.isUniversalTransitionEnabled() && series.isAnimationEnabled()) { + var newData = series.getData(); + var transitionKey = getSeriesTransitionKey(series); + var transitionKeyStr = convertArraySeriesKeyToString(transitionKey); // Only transition between series with same id. + + var oldData = oldDataMap.get(transitionKeyStr); // string transition key is the best match. + + if (oldData) { + if ("development" !== 'production') { + checkTransitionSeriesKeyDuplicated(transitionKeyStr); + } // TODO check if data is same? + + + updateBatches.set(transitionKeyStr, { + oldSeries: [{ + divide: getDivideShapeFromData(oldData), + data: oldData + }], + newSeries: [{ + divide: getDivideShapeFromData(newData), + data: newData + }] + }); + } else { + // Transition from multiple series. + if (isArray(transitionKey)) { + if ("development" !== 'production') { + checkTransitionSeriesKeyDuplicated(transitionKeyStr); + } + + var oldSeries_1 = []; + each(transitionKey, function (key) { + var oldData = oldDataMap.get(key); + + if (oldData) { + oldSeries_1.push({ + divide: getDivideShapeFromData(oldData), + data: oldData + }); + } + }); + + if (oldSeries_1.length) { + updateBatches.set(transitionKeyStr, { + oldSeries: oldSeries_1, + newSeries: [{ + data: newData, + divide: getDivideShapeFromData(newData) + }] + }); + } + } else { + // Try transition to multiple series. + var oldData_1 = oldDataMapForSplit.get(transitionKey); + + if (oldData_1) { + var batch = updateBatches.get(oldData_1.key); + + if (!batch) { + batch = { + oldSeries: [{ + data: oldData_1.data, + divide: getDivideShapeFromData(oldData_1.data) + }], + newSeries: [] + }; + updateBatches.set(oldData_1.key, batch); + } + + batch.newSeries.push({ + data: newData, + divide: getDivideShapeFromData(newData) + }); + } + } + } + } + }); + return updateBatches; + } + + function querySeries(series, finder) { + for (var i = 0; i < series.length; i++) { + var found = finder.seriesIndex != null && finder.seriesIndex === series[i].seriesIndex || finder.seriesId != null && finder.seriesId === series[i].id; + + if (found) { + return i; + } + } + } + + function transitionSeriesFromOpt(transitionOpt, globalStore, params, api) { + var from = []; + var to = []; + each(normalizeToArray(transitionOpt.from), function (finder) { + var idx = querySeries(globalStore.oldSeries, finder); + + if (idx >= 0) { + from.push({ + data: globalStore.oldData[idx], + // TODO can specify divideShape in transition. + divide: getDivideShapeFromData(globalStore.oldData[idx]), + dim: finder.dimension + }); + } + }); + each(normalizeToArray(transitionOpt.to), function (finder) { + var idx = querySeries(params.updatedSeries, finder); + + if (idx >= 0) { + var data = params.updatedSeries[idx].getData(); + to.push({ + data: data, + divide: getDivideShapeFromData(data), + dim: finder.dimension + }); + } + }); + + if (from.length > 0 && to.length > 0) { + transitionBetween(from, to, api); + } + } + + function installUniversalTransition(registers) { + registers.registerUpdateLifecycle('series:beforeupdate', function (ecMOdel, api, params) { + each(normalizeToArray(params.seriesTransition), function (transOpt) { + each(normalizeToArray(transOpt.to), function (finder) { + var series = params.updatedSeries; + + for (var i = 0; i < series.length; i++) { + if (finder.seriesIndex != null && finder.seriesIndex === series[i].seriesIndex || finder.seriesId != null && finder.seriesId === series[i].id) { + series[i][SERIES_UNIVERSAL_TRANSITION_PROP] = true; + } + } + }); + }); + }); + registers.registerUpdateLifecycle('series:transition', function (ecModel, api, params) { + // TODO api provide an namespace that can save stuff per instance + var globalStore = getUniversalTransitionGlobalStore(api); // TODO multiple to multiple series. + + if (globalStore.oldSeries && params.updatedSeries && params.optionChanged) { + // Use give transition config if its' give; + var transitionOpt = params.seriesTransition; + + if (transitionOpt) { + each(normalizeToArray(transitionOpt), function (opt) { + transitionSeriesFromOpt(opt, globalStore, params, api); + }); + } else { + // Else guess from series based on transition series key. + var updateBatches_1 = findTransitionSeriesBatches(globalStore, params); + each(updateBatches_1.keys(), function (key) { + var batch = updateBatches_1.get(key); + transitionBetween(batch.oldSeries, batch.newSeries, api); + }); + } // Reset + + + each(params.updatedSeries, function (series) { + // Reset; + if (series[SERIES_UNIVERSAL_TRANSITION_PROP]) { + series[SERIES_UNIVERSAL_TRANSITION_PROP] = false; + } + }); + } // Save all series of current update. Not only the updated one. + + + var allSeries = ecModel.getSeries(); + var savedSeries = globalStore.oldSeries = []; + var savedData = globalStore.oldData = []; + + for (var i = 0; i < allSeries.length; i++) { + var data = allSeries[i].getData(); // Only save the data that can have transition. + // Avoid large data costing too much extra memory + + if (data.count() < DATA_COUNT_THRESHOLD) { + savedSeries.push(allSeries[i]); + savedData.push(data); + } + } + }); + } + + // Render engines + // ----------------- + // Render via Canvas. + // echarts.init(dom, null, { renderer: 'canvas' }) + + use([install$1]); // Render via SVG. + // echarts.init(dom, null, { renderer: 'svg' }) + + use([install]); // ---------------- + // Charts (series) + // ---------------- + // All of the series types, for example: + // chart.setOption({ + // series: [{ + // type: 'line' // or 'bar', 'pie', ... + // }] + // }); + + use([install$2, install$3, install$4, install$6, install$8, install$a, install$b, install$c, install$d, install$e, install$f, install$h, install$i, install$j, install$k, install$l, install$m, install$n, install$o, install$p, install$q, install$r]); // ------------------- + // Coordinate systems + // ------------------- + // All of the axis modules have been included in the + // coordinate system module below, do not need to + // make extra import. + // `cartesian` coordinate system. For some historical + // reasons, it is named as grid, for example: + // chart.setOption({ + // grid: {...}, + // xAxis: {...}, + // yAxis: {...}, + // series: [{...}] + // }); + + use(install$t); // `polar` coordinate system, for example: + // chart.setOption({ + // polar: {...}, + // radiusAxis: {...}, + // angleAxis: {...}, + // series: [{ + // coordinateSystem: 'polar' + // }] + // }); + + use(install$u); // `geo` coordinate system, for example: + // chart.setOption({ + // geo: {...}, + // series: [{ + // coordinateSystem: 'geo' + // }] + // }); + + use(install$9); // `singleAxis` coordinate system (notice, it is a coordinate system + // with only one axis, work for chart like theme river), for example: + // chart.setOption({ + // singleAxis: {...} + // series: [{type: 'themeRiver', ...}] + // }); + + use(install$v); // `parallel` coordinate system, only work for parallel series, for example: + // chart.setOption({ + // parallel: {...}, + // parallelAxis: [{...}, ...], + // series: [{ + // type: 'parallel' + // }] + // }); + + use(install$g); // `calendar` coordinate system. for example, + // chart.setOptionp({ + // calendar: {...}, + // series: [{ + // coordinateSystem: 'calendar' + // }] + // ); + + use(install$w); // ------------------ + // Other components + // ------------------ + // `graphic` component, for example: + // chart.setOption({ + // graphic: {...} + // }); + + use(install$x); // `toolbox` component, for example: + // chart.setOption({ + // toolbox: {...} + // }); + + use(install$z); // `tooltip` component, for example: + // chart.setOption({ + // tooltip: {...} + // }); + + use(install$A); // `axisPointer` component, for example: + // chart.setOption({ + // tooltip: {axisPointer: {...}, ...} + // }); + // Or + // chart.setOption({ + // axisPointer: {...} + // }); + + use(install$s); // `brush` component, for example: + // chart.setOption({ + // brush: {...} + // }); + // Or + // chart.setOption({ + // tooltip: {feature: {brush: {...}} + // }) + + use(install$B); // `title` component, for example: + // chart.setOption({ + // title: {...} + // }); + + use(install$C); // `timeline` component, for example: + // chart.setOption({ + // timeline: {...} + // }); + + use(install$D); // `markPoint` component, for example: + // chart.setOption({ + // series: [{markPoint: {...}}] + // }); + + use(install$E); // `markLine` component, for example: + // chart.setOption({ + // series: [{markLine: {...}}] + // }); + + use(install$F); // `markArea` component, for example: + // chart.setOption({ + // series: [{markArea: {...}}] + // }); + + use(install$G); // `legend` component not scrollable. for example: + // chart.setOption({ + // legend: {...} + // }); + + use(install$J); // `dataZoom` component including both `dataZoomInside` and `dataZoomSlider`. + + use(install$M); // `dataZoom` component providing drag, pinch, wheel behaviors + // inside coodinate system, for example: + // chart.setOption({ + // dataZoom: {type: 'inside'} + // }); + + use(install$K); // `dataZoom` component providing a slider bar, for example: + // chart.setOption({ + // dataZoom: {type: 'slider'} + // }); + + use(install$L); // `visualMap` component including both `visualMapContinuous` and `visualMapPiecewise`. + + use(install$P); // `visualMap` component providing continuous bar, for example: + // chart.setOption({ + // visualMap: {type: 'continuous'} + // }); + + use(install$N); // `visualMap` component providing pieces bar, for example: + // chart.setOption({ + // visualMap: {type: 'piecewise'} + // }); + + use(install$O); // `aria` component providing aria, for example: + // chart.setOption({ + // aria: {...} + // }); + + use(install$Q); // dataset transform + // chart.setOption({ + // dataset: { + // transform: [] + // } + // }); + + use(install$R); + use(install$S); // universal transition + // chart.setOption({ + // series: { + // universalTransition: { enabled: true } + // } + // }) + + use(installUniversalTransition); // label layout + // chart.setOption({ + // series: { + // labelLayout: { hideOverlap: true } + // } + // }) + + use(installLabelLayout); + + exports.Axis = Axis; + exports.ChartView = ChartView; + exports.ComponentModel = ComponentModel; + exports.ComponentView = ComponentView; + exports.List = SeriesData; + exports.Model = Model; + exports.PRIORITY = PRIORITY; + exports.SeriesModel = SeriesModel; + exports.color = color; + exports.connect = connect; + exports.dataTool = dataTool; + exports.dependencies = dependencies; + exports.disConnect = disConnect; + exports.disconnect = disconnect; + exports.dispose = dispose$1; + exports.env = env; + exports.extendChartView = extendChartView; + exports.extendComponentModel = extendComponentModel; + exports.extendComponentView = extendComponentView; + exports.extendSeriesModel = extendSeriesModel; + exports.format = format$1; + exports.getCoordinateSystemDimensions = getCoordinateSystemDimensions; + exports.getInstanceByDom = getInstanceByDom; + exports.getInstanceById = getInstanceById; + exports.getMap = getMap; + exports.graphic = graphic$1; + exports.helper = helper; + exports.init = init$1; + exports.innerDrawElementOnCanvas = brushSingle; + exports.matrix = matrix; + exports.number = number; + exports.parseGeoJSON = parseGeoJSON; + exports.parseGeoJson = parseGeoJSON; + exports.registerAction = registerAction; + exports.registerCoordinateSystem = registerCoordinateSystem; + exports.registerLayout = registerLayout; + exports.registerLoading = registerLoading; + exports.registerLocale = registerLocale; + exports.registerMap = registerMap; + exports.registerPostInit = registerPostInit; + exports.registerPostUpdate = registerPostUpdate; + exports.registerPreprocessor = registerPreprocessor; + exports.registerProcessor = registerProcessor; + exports.registerTheme = registerTheme; + exports.registerTransform = registerTransform; + exports.registerUpdateLifecycle = registerUpdateLifecycle; + exports.registerVisual = registerVisual; + exports.setCanvasCreator = setCanvasCreator; + exports.setPlatformAPI = setPlatformAPI; + exports.throttle = throttle; + exports.time = time; + exports.use = use; + exports.util = util$1; + exports.vector = vector; + exports.version = version$1; + exports.zrUtil = util; + exports.zrender = zrender; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +layui.define('echartsTheme', function(exports) { + echarts.registerTheme('walden', layui.echartsTheme); + exports('echarts', echarts); +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/echartsTheme.js b/demo/webman/backend/plugin/admin/public/component/pear/module/echartsTheme.js new file mode 100644 index 0000000000000000000000000000000000000000..2cf0bfae7297a04c7f5f612e9597fbc64fc78fdc --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/echartsTheme.js @@ -0,0 +1,450 @@ +layui.define(function(exports) { + exports('echartsTheme', + { + "color": [ + "#3fb1e3", + "#6be6c1", + "#626c91", + "#a0a7e6", + "#c4ebad", + "#96dee8" + ], + "backgroundColor": "rgba(252,252,252,0)", + "textStyle": {}, + "title": { + "textStyle": { + "color": "#666666" + }, + "subtextStyle": { + "color": "#999999" + } + }, + "line": { + "itemStyle": { + "borderWidth": "3" + }, + "lineStyle": { + "width": "4" + }, + "symbolSize": "10", + "symbol": "emptyCircle", + "smooth": true + }, + "radar": { + "itemStyle": { + "borderWidth": "3" + }, + "lineStyle": { + "width": "4" + }, + "symbolSize": "10", + "symbol": "emptyCircle", + "smooth": true + }, + "bar": { + "itemStyle": { + "barBorderWidth": 0, + "barBorderColor": "#ccc" + }, + "emphasis": { + "itemStyle": { + "barBorderWidth": 0, + "barBorderColor": "#ccc" + } + } + }, + "pie": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "scatter": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "boxplot": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + + }, + "emphasis": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "parallel": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "sankey": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "funnel": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "gauge": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "candlestick": { + "itemStyle": { + "color": "#e6a0d2", + "color0": "transparent", + "borderColor": "#e6a0d2", + "borderColor0": "#3fb1e3", + "borderWidth": "2" + } + }, + "graph": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "lineStyle": { + "width": "1", + "color": "#cccccc" + }, + "symbolSize": "10", + "symbol": "emptyCircle", + "smooth": true, + "color": [ + "#3fb1e3", + "#6be6c1", + "#626c91", + "#a0a7e6", + "#c4ebad", + "#96dee8" + ], + "label": { + "color": "#ffffff" + } + }, + "map": { + "itemStyle": { + "areaColor": "#eeeeee", + "borderColor": "#aaaaaa", + "borderWidth": 0.5 + }, + "label": { + "color": "#ffffff" + }, + "emphasis": { + "itemStyle": { + "areaColor": "rgba(63,177,227,0.25)", + "borderColor": "#3fb1e3", + "borderWidth": 1 + }, + "label":{ + "color": "rgb(63,177,227)" + } + } + }, + "geo": { + "itemStyle": { + "areaColor": "#eeeeee", + "borderColor": "#aaaaaa", + "borderWidth": 0.5 + }, + "label": { + "color": "#ffffff" + }, + "emphasis": { + "itemStyle": { + "areaColor": "rgba(63,177,227,0.25)", + "borderColor": "#3fb1e3", + "borderWidth": 1 + }, + "label":{ + "color": "rgb(63,177,227)" + } + } + }, + "categoryAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisTick": { + "show": false, + "lineStyle": { + "color": "#333" + } + }, + "axisLabel": { + "show": true, + + "color": "#999999" + + }, + "splitLine": { + "show": true, + "lineStyle": { + "color": [ + "#eeeeee" + ] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": [ + "rgba(250,250,250,0.05)", + "rgba(200,200,200,0.02)" + ] + } + } + }, + "valueAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisTick": { + "show": false, + "lineStyle": { + "color": "#333" + } + }, + "axisLabel": { + "show": true, + "color": "#999999" + + }, + "splitLine": { + "show": true, + "lineStyle": { + "color": [ + "#eeeeee" + ] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": [ + "rgba(250,250,250,0.05)", + "rgba(200,200,200,0.02)" + ] + } + } + }, + "logAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisTick": { + "show": false, + "lineStyle": { + "color": "#333" + } + }, + "axisLabel": { + "show": true, + "color": "#999999" + + }, + "splitLine": { + "show": true, + "lineStyle": { + "color": [ + "#eeeeee" + ] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": [ + "rgba(250,250,250,0.05)", + "rgba(200,200,200,0.02)" + ] + } + } + }, + "timeAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisTick": { + "show": false, + "lineStyle": { + "color": "#333" + } + }, + "axisLabel": { + "show": true, + + "color": "#999999" + + }, + "splitLine": { + "show": true, + "lineStyle": { + "color": [ + "#eeeeee" + ] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": [ + "rgba(250,250,250,0.05)", + "rgba(200,200,200,0.02)" + ] + } + } + }, + "toolbox": { + "iconStyle": { + "borderColor": "#999999" + }, + "emphasis": { + "iconStyle": { + "borderColor": "#666666" + } + } + }, + "legend": { + "textStyle": { + "color": "#999999" + } + }, + "tooltip": { + "axisPointer": { + "lineStyle": { + "color": "#cccccc", + "width": 1 + }, + "crossStyle": { + "color": "#cccccc", + "width": 1 + } + } + }, + "timeline": { + "lineStyle": { + "color": "#626c91", + "width": 1 + }, + "itemStyle": { + "color": "#626c91", + "borderWidth": 1 + + }, + "controlStyle": { + "color": "#626c91", + "borderColor": "#626c91", + "borderWidth": 0.5 + }, + "checkpointStyle": { + "color": "#3fb1e3", + "borderColor": "rgba(63,177,227,0.15)" + }, + "label": { + "color": "#626c91" + }, + "emphasis": { + "itemStyle": { + "color": "#626c91" + }, + "controlStyle":{ + "color": "#626c91", + "borderColor": "#626c91", + "borderWidth": 0.5 + }, + "label":{ + "color": "#626c91" + } + } + }, + "visualMap": { + "color": [ + "#2a99c9", + "#afe8ff" + ] + }, + "dataZoom": { + "backgroundColor": "rgba(255,255,255,0)", + "dataBackgroundColor": "rgba(222,222,222,1)", + "fillerColor": "rgba(114,230,212,0.25)", + "handleColor": "#cccccc", + "handleSize": "100%", + "textStyle": { + "color": "#999999" + } + }, + "markPoint": { + "label": { + "color": "#ffffff" + }, + "emphasis": { + "label": { + "color": "#ffffff" + } + } + } + }); +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/encrypt.js b/demo/webman/backend/plugin/admin/public/component/pear/module/encrypt.js new file mode 100644 index 0000000000000000000000000000000000000000..9594f1a0f1da95d0a13f19d9b332856d711be1cf --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/encrypt.js @@ -0,0 +1,1775 @@ +/** + layui hash extend +**/ + +layui.define(function (exports) { + /** + * jshashes - https://github.com/h2non/jshashes + * Released under the "New BSD" license + * + * Algorithms specification: + * + * MD5 - http://www.ietf.org/rfc/rfc1321.txt + * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html + * SHA1 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + * HMAC - http://www.ietf.org/rfc/rfc2104.txt + */ + var pearHash; + + function utf8Encode(str) { + var x, y, output = '', + i = -1, + l; + + if (str && str.length) { + l = str.length; + while ((i += 1) < l) { + /* Decode utf-16 surrogate pairs */ + x = str.charCodeAt(i); + y = i + 1 < l ? str.charCodeAt(i + 1) : 0; + if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) { + x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); + i += 1; + } + /* Encode output as utf-8 */ + if (x <= 0x7F) { + output += String.fromCharCode(x); + } else if (x <= 0x7FF) { + output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F), + 0x80 | (x & 0x3F)); + } else if (x <= 0xFFFF) { + output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), + 0x80 | ((x >>> 6) & 0x3F), + 0x80 | (x & 0x3F)); + } else if (x <= 0x1FFFFF) { + output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), + 0x80 | ((x >>> 12) & 0x3F), + 0x80 | ((x >>> 6) & 0x3F), + 0x80 | (x & 0x3F)); + } + } + } + return output; + } + + function utf8Decode(str) { + var i, ac, c1, c2, c3, arr = [], + l; + i = ac = c1 = c2 = c3 = 0; + + if (str && str.length) { + l = str.length; + str += ''; + + while (i < l) { + c1 = str.charCodeAt(i); + ac += 1; + if (c1 < 128) { + arr[ac] = String.fromCharCode(c1); + i += 1; + } else if (c1 > 191 && c1 < 224) { + c2 = str.charCodeAt(i + 1); + arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63)); + i += 2; + } else { + c2 = str.charCodeAt(i + 1); + c3 = str.charCodeAt(i + 2); + arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + } + return arr.join(''); + } + + /** + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ + + function safe_add(x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF), + msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); + } + + /** + * Bitwise rotate a 32-bit number to the left. + */ + + function bit_rol(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)); + } + + /** + * Convert a raw string to a hex string + */ + + function rstr2hex(input, hexcase) { + var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef', + output = '', + x, i = 0, + l = input.length; + for (; i < l; i += 1) { + x = input.charCodeAt(i); + output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F); + } + return output; + } + + /** + * Encode a string as utf-16 + */ + + function str2rstr_utf16le(input) { + var i, l = input.length, + output = ''; + for (i = 0; i < l; i += 1) { + output += String.fromCharCode(input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF); + } + return output; + } + + function str2rstr_utf16be(input) { + var i, l = input.length, + output = ''; + for (i = 0; i < l; i += 1) { + output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF); + } + return output; + } + + /** + * Convert an array of big-endian words to a string + */ + + function binb2rstr(input) { + var i, l = input.length * 32, + output = ''; + for (i = 0; i < l; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF); + } + return output; + } + + /** + * Convert an array of little-endian words to a string + */ + + function binl2rstr(input) { + var i, l = input.length * 32, + output = ''; + for (i = 0; i < l; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); + } + return output; + } + + /** + * Convert a raw string to an array of little-endian words + * Characters >255 have their high-byte silently ignored. + */ + + function rstr2binl(input) { + var i, l = input.length * 8, + output = Array(input.length >> 2), + lo = output.length; + for (i = 0; i < lo; i += 1) { + output[i] = 0; + } + for (i = 0; i < l; i += 8) { + output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32); + } + return output; + } + + /** + * Convert a raw string to an array of big-endian words + * Characters >255 have their high-byte silently ignored. + */ + + function rstr2binb(input) { + var i, l = input.length * 8, + output = Array(input.length >> 2), + lo = output.length; + for (i = 0; i < lo; i += 1) { + output[i] = 0; + } + for (i = 0; i < l; i += 8) { + output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32); + } + return output; + } + + /** + * Convert a raw string to an arbitrary string encoding + */ + + function rstr2any(input, encoding) { + var divisor = encoding.length, + remainders = Array(), + i, q, x, ld, quotient, dividend, output, full_length; + + /* Convert to an array of 16-bit big-endian values, forming the dividend */ + dividend = Array(Math.ceil(input.length / 2)); + ld = dividend.length; + for (i = 0; i < ld; i += 1) { + dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); + } + + /** + * Repeatedly perform a long division. The binary array forms the dividend, + * the length of the encoding is the divisor. Once computed, the quotient + * forms the dividend for the next step. We stop when the dividend is zerHashes. + * All remainders are stored for later use. + */ + while (dividend.length > 0) { + quotient = Array(); + x = 0; + for (i = 0; i < dividend.length; i += 1) { + x = (x << 16) + dividend[i]; + q = Math.floor(x / divisor); + x -= q * divisor; + if (quotient.length > 0 || q > 0) { + quotient[quotient.length] = q; + } + } + remainders[remainders.length] = x; + dividend = quotient; + } + + /* Convert the remainders to the output string */ + output = ''; + for (i = remainders.length - 1; i >= 0; i--) { + output += encoding.charAt(remainders[i]); + } + + /* Append leading zero equivalents */ + full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2))); + for (i = output.length; i < full_length; i += 1) { + output = encoding[0] + output; + } + return output; + } + + /** + * Convert a raw string to a base-64 string + */ + + function rstr2b64(input, b64pad) { + var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', + output = '', + len = input.length, + i, j, triplet; + b64pad = b64pad || '='; + for (i = 0; i < len; i += 3) { + triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0); + for (j = 0; j < 4; j += 1) { + if (i * 8 + j * 6 > input.length * 8) { + output += b64pad; + } else { + output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F); + } + } + } + return output; + } + + pearHash = { + /** + * @property {String} version + * @readonly + */ + VERSION: '1.0.6', + /** + * @member Hashes + * @class Base64 + * @constructor + */ + Base64: function () { + // private properties + var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', + pad = '=', // default pad according with the RFC standard + url = false, // URL encoding support @todo + utf8 = true; // by default enable UTF-8 support encoding + + // public method for encoding + this.encode = function (input) { + var i, j, triplet, + output = '', + len = input.length; + + pad = pad || '='; + input = (utf8) ? utf8Encode(input) : input; + + for (i = 0; i < len; i += 3) { + triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0); + for (j = 0; j < 4; j += 1) { + if (i * 8 + j * 6 > len * 8) { + output += pad; + } else { + output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F); + } + } + } + return output; + }; + + // public method for decoding + this.decode = function (input) { + // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + var i, o1, o2, o3, h1, h2, h3, h4, bits, ac, + dec = '', + arr = []; + if (!input) { + return input; + } + + i = ac = 0; + input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '=' + //input += ''; + + do { // unpack four hexets into three octets using index points in b64 + h1 = tab.indexOf(input.charAt(i += 1)); + h2 = tab.indexOf(input.charAt(i += 1)); + h3 = tab.indexOf(input.charAt(i += 1)); + h4 = tab.indexOf(input.charAt(i += 1)); + + bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; + + o1 = bits >> 16 & 0xff; + o2 = bits >> 8 & 0xff; + o3 = bits & 0xff; + ac += 1; + + if (h3 === 64) { + arr[ac] = String.fromCharCode(o1); + } else if (h4 === 64) { + arr[ac] = String.fromCharCode(o1, o2); + } else { + arr[ac] = String.fromCharCode(o1, o2, o3); + } + } while (i < input.length); + + dec = arr.join(''); + dec = (utf8) ? utf8Decode(dec) : dec; + + return dec; + }; + + // set custom pad string + this.setPad = function (str) { + pad = str || pad; + return this; + }; + // set custom tab string characters + this.setTab = function (str) { + tab = str || tab; + return this; + }; + this.setUTF8 = function (bool) { + if (typeof bool === 'boolean') { + utf8 = bool; + } + return this; + }; + }, + + /** + * CRC-32 calculation + * @member Hashes + * @method CRC32 + * @static + * @param {String} str Input String + * @return {String} + */ + CRC32: function (str) { + var crc = 0, + x = 0, + y = 0, + table, i, iTop; + str = utf8Encode(str); + + table = [ + '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ', + '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ', + '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ', + '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ', + 'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ', + '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ', + 'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ', + '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ', + 'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ', + '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ', + 'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ', + '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ', + 'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ', + '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ', + '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ', + '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ', + '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ', + 'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ', + '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ', + 'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ', + '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ', + 'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ', + '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ', + 'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ', + '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ', + 'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D' + ].join(''); + + crc = crc ^ (-1); + for (i = 0, iTop = str.length; i < iTop; i += 1) { + y = (crc ^ str.charCodeAt(i)) & 0xFF; + x = '0x' + table.substr(y * 9, 8); + crc = (crc >>> 8) ^ x; + } + // always return a positive number (that's what >>> 0 does) + return (crc ^ (-1)) >>> 0; + }, + /** + * @member Hashes + * @class MD5 + * @constructor + * @param {Object} [config] + * + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See for more infHashes. + */ + MD5: function (options) { + /** + * Private config properties. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase} + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase + b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding + + // privileged (public) methods + this.hex = function (s) { + return rstr2hex(rstr(s, utf8), hexcase); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s, utf8), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d), hexcase); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * Enable/disable uppercase hexadecimal returned string + * @param {Boolean} + * @return {Object} this + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * Defines a base64 pad string + * @param {String} Pad + * @return {Object} this + */ + this.setPad = function (a) { + b64pad = a || b64pad; + return this; + }; + /** + * Defines a base64 pad string + * @param {Boolean} + * @return {Object} [this] + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + // private methods + + /** + * Calculate the MD5 of a raw string + */ + + function rstr(s) { + s = (utf8) ? utf8Encode(s) : s; + return binl2rstr(binl(rstr2binl(s), s.length * 8)); + } + + /** + * Calculate the HMAC-MD5, of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + var bkey, ipad, opad, hash, i; + + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + bkey = rstr2binl(key); + if (bkey.length > 16) { + bkey = binl(bkey, key.length * 8); + } + + ipad = Array(16), opad = Array(16); + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8); + return binl2rstr(binl(opad.concat(hash), 512 + 128)); + } + + /** + * Calculate the MD5 of an array of little-endian words, and a bit length. + */ + + function binl(x, len) { + var i, olda, oldb, oldc, oldd, + a = 1732584193, + b = -271733879, + c = -1732584194, + d = 271733878; + + /* append padding */ + x[len >> 5] |= 0x80 << ((len) % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + for (i = 0; i < x.length; i += 16) { + olda = a; + oldb = b; + oldc = c; + oldd = d; + + a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936); + d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); + d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); + d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); + b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); + d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); + d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); + c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); + d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); + c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); + d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); + c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); + d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); + c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); + d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); + d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); + d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); + d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844); + d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); + d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); + d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); + d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + } + return Array(a, b, c, d); + } + + /** + * These functions implement the four basic operations the algorithm uses. + */ + + function md5_cmn(q, a, b, x, s, t) { + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); + } + + function md5_ff(a, b, c, d, x, s, t) { + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); + } + + function md5_gg(a, b, c, d, x, s, t) { + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); + } + + function md5_hh(a, b, c, d, x, s, t) { + return md5_cmn(b ^ c ^ d, a, b, x, s, t); + } + + function md5_ii(a, b, c, d, x, s, t) { + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); + } + }, + /** + * @member Hashes + * @class Hashes.SHA1 + * @param {Object} [config] + * @constructor + * + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1 + * Version 2.2 Copyright Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See http://pajhome.org.uk/crypt/md5 for details. + */ + SHA1: function (options) { + /** + * Private config properties. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase} + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase + b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding + + // public methods + this.hex = function (s) { + return rstr2hex(rstr(s, utf8), hexcase); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s, utf8), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s, utf8), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d)); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + * @public + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * @description Enable/disable uppercase hexadecimal returned string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {string} Pad + * @return {Object} this + * @public + */ + this.setPad = function (a) { + b64pad = a || b64pad; + return this; + }; + /** + * @description Defines a base64 pad string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + // private methods + + /** + * Calculate the SHA-512 of a raw string + */ + + function rstr(s) { + s = (utf8) ? utf8Encode(s) : s; + return binb2rstr(binb(rstr2binb(s), s.length * 8)); + } + + /** + * Calculate the HMAC-SHA1 of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + var bkey, ipad, opad, i, hash; + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + bkey = rstr2binb(key); + + if (bkey.length > 16) { + bkey = binb(bkey, key.length * 8); + } + ipad = Array(16), opad = Array(16); + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8); + return binb2rstr(binb(opad.concat(hash), 512 + 160)); + } + + /** + * Calculate the SHA-1 of an array of big-endian words, and a bit length + */ + + function binb(x, len) { + var i, j, t, olda, oldb, oldc, oldd, olde, + w = Array(80), + a = 1732584193, + b = -271733879, + c = -1732584194, + d = 271733878, + e = -1009589776; + + /* append padding */ + x[len >> 5] |= 0x80 << (24 - len % 32); + x[((len + 64 >> 9) << 4) + 15] = len; + + for (i = 0; i < x.length; i += 16) { + olda = a; + oldb = b; + oldc = c; + oldd = d; + olde = e; + + for (j = 0; j < 80; j += 1) { + if (j < 16) { + w[j] = x[i + j]; + } else { + w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); + } + t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), + safe_add(safe_add(e, w[j]), sha1_kt(j))); + e = d; + d = c; + c = bit_rol(b, 30); + b = a; + a = t; + } + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + e = safe_add(e, olde); + } + return Array(a, b, c, d, e); + } + + /** + * Perform the appropriate triplet combination function for the current + * iteration + */ + + function sha1_ft(t, b, c, d) { + if (t < 20) { + return (b & c) | ((~b) & d); + } + if (t < 40) { + return b ^ c ^ d; + } + if (t < 60) { + return (b & c) | (b & d) | (c & d); + } + return b ^ c ^ d; + } + + /** + * Determine the appropriate additive constant for the current iteration + */ + + function sha1_kt(t) { + return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : + (t < 60) ? -1894007588 : -899497514; + } + }, + /** + * @class Hashes.SHA256 + * @param {config} + * + * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2 + * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See http://pajhome.org.uk/crypt/md5 for details. + * Also http://anmar.eu.org/projects/jssha2/ + */ + SHA256: function (options) { + /** + * Private properties configuration variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * @see this.setUpperCase() method + * @see this.setPad() method + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase */ + b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', + /* base-64 pad character. Default '=' for strict RFC compliance */ + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, + /* enable/disable utf8 encoding */ + sha256_K; + + /* privileged (public) methods */ + this.hex = function (s) { + return rstr2hex(rstr(s, utf8)); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s, utf8), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s, utf8), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d)); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + * @public + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * Enable/disable uppercase hexadecimal returned string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {string} Pad + * @return {Object} this + * @public + */ + this.setPad = function (a) { + b64pad = a || b64pad; + return this; + }; + /** + * Defines a base64 pad string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + // private methods + + /** + * Calculate the SHA-512 of a raw string + */ + + function rstr(s, utf8) { + s = (utf8) ? utf8Encode(s) : s; + return binb2rstr(binb(rstr2binb(s), s.length * 8)); + } + + /** + * Calculate the HMAC-sha256 of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + var hash, i = 0, + bkey = rstr2binb(key), + ipad = Array(16), + opad = Array(16); + + if (bkey.length > 16) { + bkey = binb(bkey, key.length * 8); + } + + for (; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8); + return binb2rstr(binb(opad.concat(hash), 512 + 256)); + } + + /* + * Main sha256 function, with its support functions + */ + + function sha256_S(X, n) { + return (X >>> n) | (X << (32 - n)); + } + + function sha256_R(X, n) { + return (X >>> n); + } + + function sha256_Ch(x, y, z) { + return ((x & y) ^ ((~x) & z)); + } + + function sha256_Maj(x, y, z) { + return ((x & y) ^ (x & z) ^ (y & z)); + } + + function sha256_Sigma0256(x) { + return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22)); + } + + function sha256_Sigma1256(x) { + return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25)); + } + + function sha256_Gamma0256(x) { + return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3)); + } + + function sha256_Gamma1256(x) { + return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10)); + } + + function sha256_Sigma0512(x) { + return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39)); + } + + function sha256_Sigma1512(x) { + return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41)); + } + + function sha256_Gamma0512(x) { + return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7)); + } + + function sha256_Gamma1512(x) { + return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6)); + } + + sha256_K = [ + 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, + 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522, + 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585, + 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, + 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, + 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, + 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998 + ]; + + function binb(m, l) { + var HASH = [1779033703, -1150833019, 1013904242, -1521486534, + 1359893119, -1694144372, 528734635, 1541459225 + ]; + var W = new Array(64); + var a, b, c, d, e, f, g, h; + var i, j, T1, T2; + + /* append padding */ + m[l >> 5] |= 0x80 << (24 - l % 32); + m[((l + 64 >> 9) << 4) + 15] = l; + + for (i = 0; i < m.length; i += 16) { + a = HASH[0]; + b = HASH[1]; + c = HASH[2]; + d = HASH[3]; + e = HASH[4]; + f = HASH[5]; + g = HASH[6]; + h = HASH[7]; + + for (j = 0; j < 64; j += 1) { + if (j < 16) { + W[j] = m[j + i]; + } else { + W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]), + sha256_Gamma0256(W[j - 15])), W[j - 16]); + } + + T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)), + sha256_K[j]), W[j]); + T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c)); + h = g; + g = f; + f = e; + e = safe_add(d, T1); + d = c; + c = b; + b = a; + a = safe_add(T1, T2); + } + + HASH[0] = safe_add(a, HASH[0]); + HASH[1] = safe_add(b, HASH[1]); + HASH[2] = safe_add(c, HASH[2]); + HASH[3] = safe_add(d, HASH[3]); + HASH[4] = safe_add(e, HASH[4]); + HASH[5] = safe_add(f, HASH[5]); + HASH[6] = safe_add(g, HASH[6]); + HASH[7] = safe_add(h, HASH[7]); + } + return HASH; + } + + }, + + /** + * @class Hashes.SHA512 + * @param {config} + * + * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2 + * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See http://pajhome.org.uk/crypt/md5 for details. + */ + SHA512: function (options) { + /** + * Private properties configuration variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * @see this.setUpperCase() method + * @see this.setPad() method + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, + /* hexadecimal output case format. false - lowercase; true - uppercase */ + b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', + /* base-64 pad character. Default '=' for strict RFC compliance */ + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, + /* enable/disable utf8 encoding */ + sha512_k; + + /* privileged (public) methods */ + this.hex = function (s) { + return rstr2hex(rstr(s)); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d)); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + * @public + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * @description Enable/disable uppercase hexadecimal returned string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {string} Pad + * @return {Object} this + * @public + */ + this.setPad = function (a) { + b64pad = a || b64pad; + return this; + }; + /** + * @description Defines a base64 pad string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + /* private methods */ + + /** + * Calculate the SHA-512 of a raw string + */ + + function rstr(s) { + s = (utf8) ? utf8Encode(s) : s; + return binb2rstr(binb(rstr2binb(s), s.length * 8)); + } + /* + * Calculate the HMAC-SHA-512 of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + + var hash, i = 0, + bkey = rstr2binb(key), + ipad = Array(32), + opad = Array(32); + + if (bkey.length > 32) { + bkey = binb(bkey, key.length * 8); + } + + for (; i < 32; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8); + return binb2rstr(binb(opad.concat(hash), 1024 + 512)); + } + + /** + * Calculate the SHA-512 of an array of big-endian dwords, and a bit length + */ + + function binb(x, len) { + var j, i, l, + W = new Array(80), + hash = new Array(16), + //Initial hash values + H = [ + new int64(0x6a09e667, -205731576), + new int64(-1150833019, -2067093701), + new int64(0x3c6ef372, -23791573), + new int64(-1521486534, 0x5f1d36f1), + new int64(0x510e527f, -1377402159), + new int64(-1694144372, 0x2b3e6c1f), + new int64(0x1f83d9ab, -79577749), + new int64(0x5be0cd19, 0x137e2179) + ], + T1 = new int64(0, 0), + T2 = new int64(0, 0), + a = new int64(0, 0), + b = new int64(0, 0), + c = new int64(0, 0), + d = new int64(0, 0), + e = new int64(0, 0), + f = new int64(0, 0), + g = new int64(0, 0), + h = new int64(0, 0), + //Temporary variables not specified by the document + s0 = new int64(0, 0), + s1 = new int64(0, 0), + Ch = new int64(0, 0), + Maj = new int64(0, 0), + r1 = new int64(0, 0), + r2 = new int64(0, 0), + r3 = new int64(0, 0); + + if (sha512_k === undefined) { + //SHA512 constants + sha512_k = [ + new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd), + new int64(-1245643825, -330482897), new int64(-373957723, -2121671748), + new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031), + new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736), + new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe), + new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302), + new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1), + new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428), + new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3), + new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65), + new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483), + new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459), + new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210), + new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340), + new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395), + new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70), + new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926), + new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473), + new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8), + new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b), + new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023), + new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30), + new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910), + new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8), + new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53), + new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016), + new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893), + new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397), + new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60), + new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec), + new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047), + new int64(-1090935817, -1295615723), new int64(-965641998, -479046869), + new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207), + new int64(-354779690, -840897762), new int64(-176337025, -294727304), + new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026), + new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b), + new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493), + new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620), + new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430), + new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817) + ]; + } + + for (i = 0; i < 80; i += 1) { + W[i] = new int64(0, 0); + } + + // append padding to the source string. The format is described in the FIPS. + x[len >> 5] |= 0x80 << (24 - (len & 0x1f)); + x[((len + 128 >> 10) << 5) + 31] = len; + l = x.length; + for (i = 0; i < l; i += 32) { //32 dwords is the block size + int64copy(a, H[0]); + int64copy(b, H[1]); + int64copy(c, H[2]); + int64copy(d, H[3]); + int64copy(e, H[4]); + int64copy(f, H[5]); + int64copy(g, H[6]); + int64copy(h, H[7]); + + for (j = 0; j < 16; j += 1) { + W[j].h = x[i + 2 * j]; + W[j].l = x[i + 2 * j + 1]; + } + + for (j = 16; j < 80; j += 1) { + //sigma1 + int64rrot(r1, W[j - 2], 19); + int64revrrot(r2, W[j - 2], 29); + int64shr(r3, W[j - 2], 6); + s1.l = r1.l ^ r2.l ^ r3.l; + s1.h = r1.h ^ r2.h ^ r3.h; + //sigma0 + int64rrot(r1, W[j - 15], 1); + int64rrot(r2, W[j - 15], 8); + int64shr(r3, W[j - 15], 7); + s0.l = r1.l ^ r2.l ^ r3.l; + s0.h = r1.h ^ r2.h ^ r3.h; + + int64add4(W[j], s1, W[j - 7], s0, W[j - 16]); + } + + for (j = 0; j < 80; j += 1) { + //Ch + Ch.l = (e.l & f.l) ^ (~e.l & g.l); + Ch.h = (e.h & f.h) ^ (~e.h & g.h); + + //Sigma1 + int64rrot(r1, e, 14); + int64rrot(r2, e, 18); + int64revrrot(r3, e, 9); + s1.l = r1.l ^ r2.l ^ r3.l; + s1.h = r1.h ^ r2.h ^ r3.h; + + //Sigma0 + int64rrot(r1, a, 28); + int64revrrot(r2, a, 2); + int64revrrot(r3, a, 7); + s0.l = r1.l ^ r2.l ^ r3.l; + s0.h = r1.h ^ r2.h ^ r3.h; + + //Maj + Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l); + Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h); + + int64add5(T1, h, s1, Ch, sha512_k[j], W[j]); + int64add(T2, s0, Maj); + + int64copy(h, g); + int64copy(g, f); + int64copy(f, e); + int64add(e, d, T1); + int64copy(d, c); + int64copy(c, b); + int64copy(b, a); + int64add(a, T1, T2); + } + int64add(H[0], H[0], a); + int64add(H[1], H[1], b); + int64add(H[2], H[2], c); + int64add(H[3], H[3], d); + int64add(H[4], H[4], e); + int64add(H[5], H[5], f); + int64add(H[6], H[6], g); + int64add(H[7], H[7], h); + } + + //represent the hash as an array of 32-bit dwords + for (i = 0; i < 8; i += 1) { + hash[2 * i] = H[i].h; + hash[2 * i + 1] = H[i].l; + } + return hash; + } + + //A constructor for 64-bit numbers + + function int64(h, l) { + this.h = h; + this.l = l; + //this.toString = int64toString; + } + + //Copies src into dst, assuming both are 64-bit numbers + + function int64copy(dst, src) { + dst.h = src.h; + dst.l = src.l; + } + + //Right-rotates a 64-bit number by shift + //Won't handle cases of shift>=32 + //The function revrrot() is for that + + function int64rrot(dst, x, shift) { + dst.l = (x.l >>> shift) | (x.h << (32 - shift)); + dst.h = (x.h >>> shift) | (x.l << (32 - shift)); + } + + //Reverses the dwords of the source and then rotates right by shift. + //This is equivalent to rotation by 32+shift + + function int64revrrot(dst, x, shift) { + dst.l = (x.h >>> shift) | (x.l << (32 - shift)); + dst.h = (x.l >>> shift) | (x.h << (32 - shift)); + } + + //Bitwise-shifts right a 64-bit number by shift + //Won't handle shift>=32, but it's never needed in SHA512 + + function int64shr(dst, x, shift) { + dst.l = (x.l >>> shift) | (x.h << (32 - shift)); + dst.h = (x.h >>> shift); + } + + //Adds two 64-bit numbers + //Like the original implementation, does not rely on 32-bit operations + + function int64add(dst, x, y) { + var w0 = (x.l & 0xffff) + (y.l & 0xffff); + var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16); + var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16); + var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16); + dst.l = (w0 & 0xffff) | (w1 << 16); + dst.h = (w2 & 0xffff) | (w3 << 16); + } + + //Same, except with 4 addends. Works faster than adding them one by one. + + function int64add4(dst, a, b, c, d) { + var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff); + var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16); + var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16); + var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16); + dst.l = (w0 & 0xffff) | (w1 << 16); + dst.h = (w2 & 0xffff) | (w3 << 16); + } + + //Same, except with 5 addends + + function int64add5(dst, a, b, c, d, e) { + var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff), + w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16), + w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16), + w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16); + dst.l = (w0 & 0xffff) | (w1 << 16); + dst.h = (w2 & 0xffff) | (w3 << 16); + } + }, + /** + * @class Hashes.RMD160 + * @constructor + * @param {Object} [config] + * + * A JavaScript implementation of the RIPEMD-160 Algorithm + * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See http://pajhome.org.uk/crypt/md5 for details. + * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/ + */ + RMD160: function (options) { + /** + * Private properties configuration variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * @see this.setUpperCase() method + * @see this.setPad() method + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, + /* hexadecimal output case format. false - lowercase; true - uppercase */ + b64pad = (options && typeof options.pad === 'string') ? options.pa : '=', + /* base-64 pad character. Default '=' for strict RFC compliance */ + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, + /* enable/disable utf8 encoding */ + rmd160_r1 = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 + ], + rmd160_r2 = [ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 + ], + rmd160_s1 = [ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 + ], + rmd160_s2 = [ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 + ]; + + /* privileged (public) methods */ + this.hex = function (s) { + return rstr2hex(rstr(s, utf8)); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s, utf8), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s, utf8), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d)); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + * @public + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * @description Enable/disable uppercase hexadecimal returned string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {string} Pad + * @return {Object} this + * @public + */ + this.setPad = function (a) { + if (typeof a !== 'undefined') { + b64pad = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + /* private methods */ + + /** + * Calculate the rmd160 of a raw string + */ + + function rstr(s) { + s = (utf8) ? utf8Encode(s) : s; + return binl2rstr(binl(rstr2binl(s), s.length * 8)); + } + + /** + * Calculate the HMAC-rmd160 of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + var i, hash, + bkey = rstr2binl(key), + ipad = Array(16), + opad = Array(16); + + if (bkey.length > 16) { + bkey = binl(bkey, key.length * 8); + } + + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8); + return binl2rstr(binl(opad.concat(hash), 512 + 160)); + } + + /** + * Convert an array of little-endian words to a string + */ + + function binl2rstr(input) { + var i, output = '', + l = input.length * 32; + for (i = 0; i < l; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); + } + return output; + } + + /** + * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length. + */ + + function binl(x, len) { + var T, j, i, l, + h0 = 0x67452301, + h1 = 0xefcdab89, + h2 = 0x98badcfe, + h3 = 0x10325476, + h4 = 0xc3d2e1f0, + A1, B1, C1, D1, E1, + A2, B2, C2, D2, E2; + + /* append padding */ + x[len >> 5] |= 0x80 << (len % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + l = x.length; + + for (i = 0; i < l; i += 16) { + A1 = A2 = h0; + B1 = B2 = h1; + C1 = C2 = h2; + D1 = D2 = h3; + E1 = E2 = h4; + for (j = 0; j <= 79; j += 1) { + T = safe_add(A1, rmd160_f(j, B1, C1, D1)); + T = safe_add(T, x[i + rmd160_r1[j]]); + T = safe_add(T, rmd160_K1(j)); + T = safe_add(bit_rol(T, rmd160_s1[j]), E1); + A1 = E1; + E1 = D1; + D1 = bit_rol(C1, 10); + C1 = B1; + B1 = T; + T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2)); + T = safe_add(T, x[i + rmd160_r2[j]]); + T = safe_add(T, rmd160_K2(j)); + T = safe_add(bit_rol(T, rmd160_s2[j]), E2); + A2 = E2; + E2 = D2; + D2 = bit_rol(C2, 10); + C2 = B2; + B2 = T; + } + + T = safe_add(h1, safe_add(C1, D2)); + h1 = safe_add(h2, safe_add(D1, E2)); + h2 = safe_add(h3, safe_add(E1, A2)); + h3 = safe_add(h4, safe_add(A1, B2)); + h4 = safe_add(h0, safe_add(B1, C2)); + h0 = T; + } + return [h0, h1, h2, h3, h4]; + } + + // specific algorithm methods + + function rmd160_f(j, x, y, z) { + return (0 <= j && j <= 15) ? (x ^ y ^ z) : + (16 <= j && j <= 31) ? (x & y) | (~x & z) : + (32 <= j && j <= 47) ? (x | ~y) ^ z : + (48 <= j && j <= 63) ? (x & z) | (y & ~z) : + (64 <= j && j <= 79) ? x ^ (y | ~z) : + 'rmd160_f: j out of range'; + } + + function rmd160_K1(j) { + return (0 <= j && j <= 15) ? 0x00000000 : + (16 <= j && j <= 31) ? 0x5a827999 : + (32 <= j && j <= 47) ? 0x6ed9eba1 : + (48 <= j && j <= 63) ? 0x8f1bbcdc : + (64 <= j && j <= 79) ? 0xa953fd4e : + 'rmd160_K1: j out of range'; + } + + function rmd160_K2(j) { + return (0 <= j && j <= 15) ? 0x50a28be6 : + (16 <= j && j <= 31) ? 0x5c4dd124 : + (32 <= j && j <= 47) ? 0x6d703ef3 : + (48 <= j && j <= 63) ? 0x7a6d76e9 : + (64 <= j && j <= 79) ? 0x00000000 : + 'rmd160_K2: j out of range'; + } + } + }; + + // new MD5 instance + var MD5 = new pearHash.MD5 + // new SHA1 instance + var SHA1 = new pearHash.SHA1 + // new SHA256 instance + var SHA256 = new pearHash.SHA256 + // new SHA512 instace + var SHA512 = new pearHash.SHA512 + // new RIPEMD-160 instace + var RMD160 = new pearHash.RMD160 + var Base64 = new pearHash.Base64 + + pearHash.md5 = function (str) { + return MD5.hex(str); + } + pearHash.sha1 = function (str) { + return SHA1.hex(str); + } + pearHash.sha256 = function (str) { + return SHA256.hex(str); + } + pearHash.sha512 = function (str) { + return SHA512.hex(str); + } + pearHash.crc32 = pearHash.CRC32; + pearHash.rmd160 = function (str) { + return RMD160.hex(str); + } + pearHash.Base64Encode = function (str) { + return Base64.encode(str); + } + pearHash.Base64Decode = function (str) { + return Base64.decode(str); + } + exports('encrypt', pearHash); +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/frame.js b/demo/webman/backend/plugin/admin/public/component/pear/module/frame.js new file mode 100644 index 0000000000000000000000000000000000000000..3f5af1919553d98d3f82868e41149e837b91f7a5 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/frame.js @@ -0,0 +1,67 @@ +layui.define(['jquery', 'element'], function (exports) { + "use strict"; + + var $ = layui.jquery; + + var pearFrame = function (opt) { + this.option = opt; + }; + + pearFrame.prototype.render = function (opt) { + var option = { + elem: opt.elem, + url: opt.url, + title: opt.title, + width: opt.width, + height: opt.height, + done: opt.done ? opt.done : function () { console.log("菜单渲染成功"); } + } + createFrameHTML(option); + $("#" + option.elem).width(option.width); + $("#" + option.elem).height(option.height); + return new pearFrame(option); + } + + pearFrame.prototype.changePage = function (url, loading) { + var $frameLoad = $("#" + this.option.elem).find(".pear-frame-loading"); + var $frame = $("#" + this.option.elem + " iframe"); + $frame.attr("src", url); + frameLoading($frame, $frameLoad, loading); + } + + pearFrame.prototype.changePageByElement = function (elem, url, title, loading) { + var $frameLoad = $("#" + elem).find(".pear-frame-loading"); + var $frame = $("#" + elem + " iframe"); + $frame.attr("src", url); + $("#" + elem + " .title").html(title); + frameLoading($frame, $frameLoad, loading); + } + + pearFrame.prototype.refresh = function (loading) { + var $frameLoad = $("#" + this.option.elem).find(".pear-frame-loading"); + var $frame = $("#" + this.option.elem).find("iframe"); + $frame.attr("src", $frame.attr("src")); + frameLoading($frame, $frameLoad, loading); + } + + function createFrameHTML(option) { + var iframe = ""; + var loading = '
                                                                                          ' + + '
                                                                                          ' + + '' + + '
                                                                                          ' + + '
                                                                                          '; + $("#" + option.elem).html("
                                                                                          " + iframe + loading + "
                                                                                          "); + } + + function frameLoading(iframeEl, loadingEl, isLoading) { + if (isLoading) { + loadingEl.css({ display: 'block' }); + $(iframeEl).on('load', function () { + loadingEl.fadeOut(1000); + }) + } + } + + exports('frame', new pearFrame()); +}); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/fullscreen.js b/demo/webman/backend/plugin/admin/public/component/pear/module/fullscreen.js new file mode 100644 index 0000000000000000000000000000000000000000..a0f3b4dd49b26a13546c64f1861efb3c2ff42c04 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/fullscreen.js @@ -0,0 +1,54 @@ +layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'menu', 'frame', 'theme', 'convert'], + function(exports) { + "use strict"; + var $ = layui.jquery; + var defer = $.Deferred(); + var fullScreen = new function() { + this.func = null; + this.onFullchange = function(func){ + this.func = func; + var evts = ['fullscreenchange','webkitfullscreenchange','mozfullscreenchange','MSFullscreenChange']; + for(var i=0;i'; + } else { + oriIcon += ORIGINAL_ELEM_VALUE; + } + oriIcon += ''; + + var selectHtml = + '
                                                                                          ' + + '
                                                                                          ' + + '
                                                                                          ' + + '' + + oriIcon + + '' + + '' + + '
                                                                                          ' + + '
                                                                                          ' + + '
                                                                                          ' + + '123' + + '
                                                                                          '; + $(elem).after(selectHtml); + return a; + }, + /** + * 展开/折叠下拉框 + */ + toggleSelect: function() { + var item = '#' + TITLE_ID + ' .layui-iconpicker-item,#' + TITLE_ID + + ' .layui-iconpicker-item .layui-edge'; + a.event('click', item, function(e) { + var $icon = $('#' + ICON_BODY); + if ($icon.hasClass(selected)) { + $icon.removeClass(selected).addClass(unselect); + } else { + // 隐藏其他picker + $('.layui-form-select').removeClass(selected); + // 显示当前picker + $icon.addClass(selected).removeClass(unselect); + } + e.stopPropagation(); + }); + return a; + }, + /** + * 绘制主体部分 + */ + createBody: function() { + // 获取数据 + var searchHtml = ''; + + if (search) { + searchHtml = ''; + } + + // 组合dom + var bodyHtml = '
                                                                                          ' + + searchHtml + + '
                                                                                          ' + + '
                                                                                          '; + $('#' + ICON_BODY).find('.layui-anim').eq(0).html(bodyHtml); + a.search().createList().check().page(); + + return a; + }, + /** + * 绘制图标列表 + * @param text 模糊查询关键字 + * @returns {string} + */ + createList: function(text) { + var d = data, + l = d.length, + pageHtml = '', + listHtml = $( + '
                                                                                          ') //'
                                                                                          '; + + // 计算分页数据 + var _limit = limit, // 每页显示数量 + _pages = l % _limit === 0 ? l / _limit : parseInt(l / _limit + 1), // 总计多少页 + _id = PAGE_ID; + + // 图标列表 + var icons = []; + + for (var i = 0; i < l; i++) { + var obj = d[i]; + + // 判断是否模糊查询 + if (text && obj.indexOf(text) === -1) { + continue; + } + + // 是否自定义格子宽度 + var style = ''; + if (cellWidth !== null) { + style += ' style="width:' + cellWidth + '"'; + } + + // 每个图标dom + var icon = '
                                                                                          '; + if (isFontClass) { + icon += ''; + } else { + icon += '' + obj.replace('amp;', '') + ''; + } + icon += '
                                                                                          '; + + icons.push(icon); + } + + // 查询出图标后再分页 + l = icons.length; + _pages = l % _limit === 0 ? l / _limit : parseInt(l / _limit + 1); + for (var i = 0; i < _pages; i++) { + // 按limit分块 + var lm = $( + '
                                                                                          '); + + for (var j = i * _limit; j < (i + 1) * _limit && j < l; j++) { + lm.append(icons[j]); + } + + listHtml.append(lm); + } + + // 无数据 + if (l === 0) { + listHtml.append('

                                                                                          无数据

                                                                                          '); + } + + // 判断是否分页 + if (page) { + $('#' + PICKER_BODY).addClass('layui-iconpicker-body-page'); + pageHtml = '
                                                                                          ' + + '
                                                                                          ' + + '1/' + + '' + _pages + '' + + ' (' + l + ')' + + '
                                                                                          ' + + '
                                                                                          ' + + ' ' + + ' ' + + '
                                                                                          ' + + '
                                                                                          '; + } + + + $('#' + ICON_BODY).find('.layui-anim').find('.' + LIST_BOX).html('').append( + listHtml).append(pageHtml); + return a; + }, + // 阻止Layui的一些默认事件 + preventEvent: function() { + var item = '#' + ICON_BODY + ' .layui-anim'; + a.event('click', item, function(e) { + e.stopPropagation(); + }); + return a; + }, + // 分页 + page: function() { + var icon = '#' + PAGE_ID + ' .layui-iconpicker-page-operate .layui-icon'; + + $(icon).unbind('click'); + a.event('click', icon, function(e) { + var elem = e.currentTarget, + total = parseInt($('#' + PAGE_ID + '-pages').html()), + isPrev = $(elem).attr('prev') !== undefined, + // 按钮上标的页码 + index = parseInt($(elem).attr('data-index')), + $cur = $('#' + PAGE_ID + '-current'), + // 点击时正在显示的页码 + current = parseInt($cur.html()); + + // 分页数据 + if (isPrev && current > 1) { + current = current - 1; + $(icon + '[prev]').attr('data-index', current); + } else if (!isPrev && current < total) { + current = current + 1; + $(icon + '[next]').attr('data-index', current); + } + $cur.html(current); + + // 图标数据 + $('#' + ICON_BODY + ' .layui-iconpicker-icon-limit').hide(); + $('#layui-iconpicker-icon-limit-' + tmp + current).show(); + e.stopPropagation(); + }); + return a; + }, + /** + * 搜索 + */ + search: function() { + var item = '#' + PICKER_BODY + ' .layui-iconpicker-search .layui-input'; + a.event('input propertychange', item, function(e) { + var elem = e.target, + t = $(elem).val(); + a.createList(t); + }); + return a; + }, + /** + * 点击选中图标 + */ + check: function() { + var item = '#' + PICKER_BODY + ' .layui-iconpicker-icon-item'; + a.event('click', item, function(e) { + var el = $(e.currentTarget).find('.layui-icon'), + icon = ''; + if (isFontClass) { + var clsArr = el.attr('class').split(/[\s\n]/), + cls = clsArr[1], + icon = cls; + $('#' + TITLE_ID).find('.layui-iconpicker-item .layui-icon').html( + '').attr('class', clsArr.join(' ')); + } else { + var cls = el.html(), + icon = cls; + $('#' + TITLE_ID).find('.layui-iconpicker-item .layui-icon').html( + icon); + } + + $('#' + ICON_BODY).removeClass(selected).addClass(unselect); + $(elem).val(icon).attr('value', icon); + // 回调 + if (click) { + click({ + icon: icon + }); + } + + }); + return a; + }, + // 监听原始input数值改变 + inputListen: function() { + var el = $(elem); + a.event('change', elem, function() { + var value = el.val(); + }) + // el.change(function(){ + + // }); + return a; + }, + event: function(evt, el, fn) { + $(BODY).on(evt, el, fn); + } + }; + + var common = { + /** + * 加载样式表 + */ + loadCss: function() { + var css = + '.layui-iconpicker {max-width: 280px;}.layui-iconpicker .layui-anim{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box;}.layui-iconpicker-item{border:1px solid #e6e6e6;width:90px;height:38px;border-radius:4px;cursor:pointer;position:relative;}.layui-iconpicker-icon{border-right:1px solid #e6e6e6;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;width:60px;height:100%;float:left;text-align:center;background:#fff;transition:all .3s;}.layui-iconpicker-icon i{line-height:38px;font-size:18px;}.layui-iconpicker-item > .layui-edge{left:70px;}.layui-iconpicker-item:hover{border-color:#D2D2D2!important;}.layui-iconpicker-item:hover .layui-iconpicker-icon{border-color:#D2D2D2!important;}.layui-iconpicker.layui-form-selected .layui-anim{display:block;}.layui-iconpicker-body{padding:6px;}.layui-iconpicker .layui-iconpicker-list{background-color:#fff;border:1px solid #ccc;border-radius:4px;}.layui-iconpicker .layui-iconpicker-icon-item{display:inline-block;width:21.1%;line-height:36px;text-align:center;cursor:pointer;vertical-align:top;height:36px;margin:4px;border:1px solid #ddd;border-radius:2px;transition:300ms;}.layui-iconpicker .layui-iconpicker-icon-item i.layui-icon{font-size:17px;}.layui-iconpicker .layui-iconpicker-icon-item:hover{background-color:#eee;border-color:#ccc;-webkit-box-shadow:0 0 2px #aaa,0 0 2px #fff inset;-moz-box-shadow:0 0 2px #aaa,0 0 2px #fff inset;box-shadow:0 0 2px #aaa,0 0 2px #fff inset;text-shadow:0 0 1px #fff;}.layui-iconpicker-search{position:relative;margin:0 0 6px 0;border:1px solid #e6e6e6;border-radius:2px;transition:300ms;}.layui-iconpicker-search:hover{border-color:#D2D2D2!important;}.layui-iconpicker-search .layui-input{cursor:text;display:inline-block;width:86%;border:none;padding-right:0;margin-top:1px;}.layui-iconpicker-search .layui-icon{position:absolute;top:11px;right:4%;}.layui-iconpicker-tips{text-align:center;padding:8px 0;cursor:not-allowed;}.layui-iconpicker-page{margin-top:6px;margin-bottom:-6px;font-size:12px;padding:0 2px;}.layui-iconpicker-page-count{display:inline-block;}.layui-iconpicker-page-operate{display:inline-block;float:right;cursor:default;}.layui-iconpicker-page-operate .layui-icon{font-size:12px;cursor:pointer;}.layui-iconpicker-body-page .layui-iconpicker-icon-limit{display:none;}.layui-iconpicker-body-page .layui-iconpicker-icon-limit:first-child{display:block;}'; + var $style = $('head').find('style[iconpicker]'); + if ($style.length === 0) { + $('head').append(''); + } + }, + /** + * 获取数据 + */ + getData: { + fontClass: function() { + var arr = ["layui-icon-rate-half", "layui-icon-rate", "layui-icon-rate-solid", + "layui-icon-cellphone", "layui-icon-vercode", "layui-icon-login-wechat", + "layui-icon-login-qq", "layui-icon-login-weibo", "layui-icon-password", + "layui-icon-username", "layui-icon-refresh-3", "layui-icon-auz", + "layui-icon-spread-left", "layui-icon-shrink-right", + "layui-icon-snowflake", "layui-icon-tips", "layui-icon-note", + "layui-icon-home", "layui-icon-senior", "layui-icon-refresh", + "layui-icon-refresh-1", "layui-icon-flag", "layui-icon-theme", + "layui-icon-notice", "layui-icon-website", "layui-icon-console", + "layui-icon-face-surprised", "layui-icon-set", "layui-icon-template-1", + "layui-icon-app", "layui-icon-template", "layui-icon-praise", + "layui-icon-tread", "layui-icon-male", "layui-icon-female", + "layui-icon-camera", "layui-icon-camera-fill", "layui-icon-more", + "layui-icon-more-vertical", "layui-icon-rmb", "layui-icon-dollar", + "layui-icon-diamond", "layui-icon-fire", "layui-icon-return", + "layui-icon-location", "layui-icon-read", "layui-icon-survey", + "layui-icon-face-smile", "layui-icon-face-cry", + "layui-icon-cart-simple", "layui-icon-cart", "layui-icon-next", + "layui-icon-prev", "layui-icon-upload-drag", "layui-icon-upload", + "layui-icon-download-circle", "layui-icon-component", + "layui-icon-file-b", "layui-icon-user", "layui-icon-find-fill", + "layui-icon-loading", "layui-icon-loading-1", "layui-icon-add-1", + "layui-icon-play", "layui-icon-pause", "layui-icon-headset", + "layui-icon-video", "layui-icon-voice", "layui-icon-speaker", + "layui-icon-fonts-del", "layui-icon-fonts-code", + "layui-icon-fonts-html", "layui-icon-fonts-strong", "layui-icon-unlink", + "layui-icon-picture", "layui-icon-link", "layui-icon-face-smile-b", + "layui-icon-align-left", "layui-icon-align-right", + "layui-icon-align-center", "layui-icon-fonts-u", "layui-icon-fonts-i", + "layui-icon-tabs", "layui-icon-radio", "layui-icon-circle", + "layui-icon-edit", "layui-icon-share", "layui-icon-delete", + "layui-icon-form", "layui-icon-cellphone-fine", "layui-icon-dialogue", + "layui-icon-fonts-clear", "layui-icon-layer", "layui-icon-date", + "layui-icon-water", "layui-icon-code-circle", "layui-icon-carousel", + "layui-icon-prev-circle", "layui-icon-layouts", "layui-icon-util", + "layui-icon-templeate-1", "layui-icon-upload-circle", "layui-icon-tree", + "layui-icon-table", "layui-icon-chart", "layui-icon-chart-screen", + "layui-icon-engine", "layui-icon-triangle-d", "layui-icon-triangle-r", + "layui-icon-file", "layui-icon-set-sm", "layui-icon-add-circle", + "layui-icon-404", "layui-icon-about", "layui-icon-up", + "layui-icon-down", "layui-icon-left", "layui-icon-right", + "layui-icon-circle-dot", "layui-icon-search", "layui-icon-set-fill", + "layui-icon-group", "layui-icon-friends", "layui-icon-reply-fill", + "layui-icon-menu-fill", "layui-icon-log", "layui-icon-picture-fine", + "layui-icon-face-smile-fine", "layui-icon-list", "layui-icon-release", + "layui-icon-ok", "layui-icon-help", "layui-icon-chat", "layui-icon-top", + "layui-icon-star", "layui-icon-star-fill", "layui-icon-close-fill", + "layui-icon-close", "layui-icon-ok-circle", "layui-icon-add-circle-fine" + ]; + return arr; + }, + unicode: function() { + return ["&#xe6c9;", "&#xe67b;", "&#xe67a;", "&#xe678;", + "&#xe679;", "&#xe677;", "&#xe676;", "&#xe675;", + "&#xe673;", "&#xe66f;", "&#xe9aa;", "&#xe672;", + "&#xe66b;", "&#xe668;", "&#xe6b1;", "&#xe702;", + "&#xe66e;", "&#xe68e;", "&#xe674;", "&#xe669;", + "&#xe666;", "&#xe66c;", "&#xe66a;", "&#xe667;", + "&#xe7ae;", "&#xe665;", "&#xe664;", "&#xe716;", + "&#xe656;", "&#xe653;", "&#xe663;", "&#xe6c6;", + "&#xe6c5;", "&#xe662;", "&#xe661;", "&#xe660;", + "&#xe65d;", "&#xe65f;", "&#xe671;", "&#xe65e;", + "&#xe659;", "&#xe735;", "&#xe756;", "&#xe65c;", + "&#xe715;", "&#xe705;", "&#xe6b2;", "&#xe6af;", + "&#xe69c;", "&#xe698;", "&#xe657;", "&#xe65b;", + "&#xe65a;", "&#xe681;", "&#xe67c;", "&#xe601;", + "&#xe857;", "&#xe655;", "&#xe770;", "&#xe670;", + "&#xe63d;", "&#xe63e;", "&#xe654;", "&#xe652;", + "&#xe651;", "&#xe6fc;", "&#xe6ed;", "&#xe688;", + "&#xe645;", "&#xe64f;", "&#xe64e;", "&#xe64b;", + "&#xe62b;", "&#xe64d;", "&#xe64a;", "&#xe64c;", + "&#xe650;", "&#xe649;", "&#xe648;", "&#xe647;", + "&#xe646;", "&#xe644;", "&#xe62a;", "&#xe643;", + "&#xe63f;", "&#xe642;", "&#xe641;", "&#xe640;", + "&#xe63c;", "&#xe63b;", "&#xe63a;", "&#xe639;", + "&#xe638;", "&#xe637;", "&#xe636;", "&#xe635;", + "&#xe634;", "&#xe633;", "&#xe632;", "&#xe631;", + "&#xe630;", "&#xe62f;", "&#xe62e;", "&#xe62d;", + "&#xe62c;", "&#xe629;", "&#xe628;", "&#xe625;", + "&#xe623;", "&#xe621;", "&#xe620;", "&#xe61f;", + "&#xe61c;", "&#xe60b;", "&#xe619;", "&#xe61a;", + "&#xe603;", "&#xe602;", "&#xe617;", "&#xe615;", + "&#xe614;", "&#xe613;", "&#xe612;", "&#xe611;", + "&#xe60f;", "&#xe60e;", "&#xe60d;", "&#xe60c;", + "&#xe60a;", "&#xe609;", "&#xe605;", "&#xe607;", + "&#xe606;", "&#xe604;", "&#xe600;", "&#xe658;", + "&#x1007;", "&#x1006;", "&#x1005;", "&#xe608;" + ]; + } + } + }; + + a.init(); + return new IconPicker(); + }; + + /** + * 选中图标 + * @param filter lay-filter + * @param iconName 图标名称,自动识别fontClass/unicode + */ + IconPicker.prototype.checkIcon = function(filter, iconName) { + var el = $('*[lay-filter=' + filter + ']'), + p = el.next().find('.layui-iconpicker-item .layui-icon'), + c = iconName; + + if (c.indexOf('#xe') > 0) { + p.html(c); + } else { + p.html('').attr('class', 'layui-icon ' + c); + } + el.attr('value', c).val(c); + }; + + var iconPicker = new IconPicker(); + exports(_MOD, iconPicker); +}); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/loading.js b/demo/webman/backend/plugin/admin/public/component/pear/module/loading.js new file mode 100644 index 0000000000000000000000000000000000000000..447bd38f8199880901c334ffea87a1b7d04ebdb6 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/loading.js @@ -0,0 +1,2091 @@ +layui.define(['table', 'jquery', 'element'], function (exports) { + "use strict"; + + var MOD_NAME = 'loading', + $ = layui.jquery, + element = layui.element; + var pearOper = new function () { + this.blockRemove = function(dom,time){ + Notiflix.Block.Remove(dom, time); + } + this.block = function(option){ + if(option.type==1){ + Notiflix.Block.Standard( + option.elem + ,option.msg); + } + else if(option.type==2){ + Notiflix.Block.Hourglass( + option.elem + ,option.msg); + } + else if(option.type==3){ + Notiflix.Block.Circle( + option.elem + ,option.msg); + } + else if(option.type==4){ + Notiflix.Block.Arrows( + option.elem + ,option.msg); + } + else if(option.type==5){ + Notiflix.Block.Dots( + option.elem + ,option.msg); + } + else if(option.type==6){ + Notiflix.Block.Pulse( + option.elem + ,option.msg); + } + } + this.report = function(option){ + if(option.type=="success"){ + Notiflix.Report.Success( + option.title, + option.message,'确认'); + }else if(option.type=="failure"){ + Notiflix.Report.Failure( + option.title, + option.message,'确认'); + }else if(option.type=="warning"){ + Notiflix.Report.Warning( + option.title, + option.message,'确认'); + }else if(option.type=="info"){ + Notiflix.Report.Info( + option.title, + option.message,'确认'); + } + } + + this.notice = function(option){ + Notiflix.Notify.Init({ + position:option.position?"right-top":option.position, + }); + if(option.type=="success"){ + + Notiflix.Notify.Success(option.title); + }else if(option.type=="failure"){ + + Notiflix.Notify.Failure(option.title); + }else if(option.type=="warning"){ + + Notiflix.Notify.Warning(option.title); + }else if(option.type=="info"){ + + Notiflix.Notify.Info(option.title); + } + } + + this.confirm = function(option){ + Notiflix.Confirm.Show( + option.title, + option.message, + '确认', + '取消', + option.success, + option.cancle + ); + } + + this.drawer = function(position,dom,distance){ + var _right = new mSlider({ + dom: dom, + direction: position, + distance:distance + }); + _right.open(); + } + + this.loadRemove = function(time){ + Notiflix.Loading.Remove(time); + } + + this.Load = function(type,message){ + if(type==1){ + Notiflix.Loading.Standard(message); + }else if(type==2){ + Notiflix.Loading.Hourglass(message); + }else if(type==3){ + Notiflix.Loading.Circle(message); + }else if(type==4){ + Notiflix.Loading.Dots(message); + }else if(type==5){ + Notiflix.Loading.Pulse(message); + } + } + + this.msg = function(option){ + if(option.type=="success"){ + + layer.msg(option.title,{icon:1,time:option.time},option.callback); + + }else if(option.type=="failure"){ + + layer.msg(option.title,{icon:2,time:option.time},option.callback); + + }else if(option.type=="warning"){ + + layer.msg(option.title,{icon:3,time:option.time},option.callback); + + }else if(option.type=="info"){ + + layer.msg(option.title,{icon:4,time:option.time},option.callback); + } + } + }; + + // Notiflix: Notify Default Settings on + var notifySettings = { + wrapID: 'NotiflixNotifyWrap', // can not customizable + width: '280px', + position: 'right-top', // 'right-top' - 'right-bottom' - 'left-top' - 'left-bottom' + distance: '10px', + opacity: 1, + borderRadius: '5px', + rtl: false, + timeout: 3000, + messageMaxLength: 110, + backOverlay: false, + backOverlayColor: 'rgba(0,0,0,0.5)', + plainText: true, + showOnlyTheLastOne: false, + clickToClose: false, + + ID: 'NotiflixNotify', + className: 'notiflix-notify', + zindex: 4001, + useGoogleFont: true, + fontFamily: 'Quicksand', + fontSize: '13px', + cssAnimation: true, + cssAnimationDuration: 400, + cssAnimationStyle: 'fade', // 'fade' - 'zoom' - 'from-right' - 'from-top' - 'from-bottom' - 'from-left' + closeButton: false, + useIcon: true, + useFontAwesome: false, + fontAwesomeIconStyle: 'basic', // 'basic' - 'shadow' + fontAwesomeIconSize: '34px', + + success: { + background: '#32c682', + textColor: '#fff', + childClassName: 'success', + notiflixIconColor: 'rgba(0,0,0,0.2)', + fontAwesomeClassName: 'fas fa-check-circle', + fontAwesomeIconColor: 'rgba(0,0,0,0.2)', + }, + + failure: { + background: '#ff5549', + textColor: '#fff', + childClassName: 'failure', + notiflixIconColor: 'rgba(0,0,0,0.2)', + fontAwesomeClassName: 'fas fa-times-circle', + fontAwesomeIconColor: 'rgba(0,0,0,0.2)', + }, + + warning: { + background: '#eebf31', + textColor: '#fff', + childClassName: 'warning', + notiflixIconColor: 'rgba(0,0,0,0.2)', + fontAwesomeClassName: 'fas fa-exclamation-circle', + fontAwesomeIconColor: 'rgba(0,0,0,0.2)', + }, + + info: { + background: '#26c0d3', + textColor: '#fff', + childClassName: 'info', + notiflixIconColor: 'rgba(0,0,0,0.2)', + fontAwesomeClassName: 'fas fa-info-circle', + fontAwesomeIconColor: 'rgba(0,0,0,0.2)', + }, + }; + // Notiflix: Notify Default Settings off + + // Notiflix: Report Default Settings on + var reportSettings = { + ID: 'NotiflixReportWrap', // can not customizable + className: 'notiflix-report', + width: '320px', + backgroundColor: '#f8f8f8', + borderRadius: '25px', + rtl: false, + zindex: 4002, + backOverlay: true, + backOverlayColor: 'rgba(0, 0, 0, 0.5)', + useGoogleFont: true, + fontFamily: 'Quicksand', + svgSize: '110px', + plainText: true, + titleFontSize: '16px', + titleMaxLength: 34, + messageFontSize: '13px', + messageMaxLength: 400, + buttonFontSize: '14px', + buttonMaxLength: 34, + cssAnimation: true, + cssAnimationDuration: 360, + cssAnimationStyle: 'fade', // 'fade' - 'zoom' + + success: { + svgColor: '#32c682', + titleColor: '#1e1e1e', + messageColor: '#242424', + buttonBackground: '#32c682', + buttonColor: '#fff', + }, + + failure: { + svgColor: '#ff5549', + titleColor: '#1e1e1e', + messageColor: '#242424', + buttonBackground: '#ff5549', + buttonColor: '#fff', + }, + + warning: { + svgColor: '#eebf31', + titleColor: '#1e1e1e', + messageColor: '#242424', + buttonBackground: '#eebf31', + buttonColor: '#fff', + }, + + info: { + svgColor: '#26c0d3', + titleColor: '#1e1e1e', + messageColor: '#242424', + buttonBackground: '#26c0d3', + buttonColor: '#fff', + }, + }; + // Notiflix: Report Default Settings off + + // Notiflix: Confirm Default Settings on + var confirmSettings = { + ID: 'NotiflixConfirmWrap', // can not customizable + className: 'notiflix-confirm', + width: '300px', + zindex: 4003, + position: 'center', // 'center' - 'center-top' - 'right-top' - 'right-bottom' - 'left-top' - 'left-bottom' + distance: '10px', + backgroundColor: '#f8f8f8', + borderRadius: '25px', + backOverlay: true, + backOverlayColor: 'rgba(0,0,0,0.5)', + rtl: false, + useGoogleFont: true, + fontFamily: 'Quicksand', + cssAnimation: true, + cssAnimationStyle: 'fade', // 'zoom' - 'fade' + cssAnimationDuration: 300, + plainText: true, + + titleColor: '#32c682', + titleFontSize: '16px', + titleMaxLength: 34, + + messageColor: '#1e1e1e', + messageFontSize: '14px', + messageMaxLength: 110, + + buttonsFontSize: '15px', + buttonsMaxLength: 34, + okButtonColor: '#f8f8f8', + okButtonBackground: '#32c682', + cancelButtonColor: '#f8f8f8', + cancelButtonBackground: '#a9a9a9', + }; + // Notiflix: Confirm Default Settings off + + // Notiflix: Loading Default Settings on + var loadingSettings = { + ID: 'NotiflixLoadingWrap', // can not customizable + className: 'notiflix-loading', + zindex: 4000, + backgroundColor: 'rgba(0,0,0,0.8)', + rtl: false, + useGoogleFont: true, + fontFamily: 'Quicksand', + cssAnimation: true, + cssAnimationDuration: 400, + clickToClose: false, + customSvgUrl: null, + svgSize: '80px', + svgColor: '#32c682', + messageID: 'NotiflixLoadingMessage', + messageFontSize: '15px', + messageMaxLength: 34, + messageColor: '#dcdcdc', + }; + // Notiflix: Loading Default Settings off + + // Notiflix: Block Default Settings on + var blockSettings = { + ID: 'NotiflixBlockWrap', // can not customizable + querySelectorLimit: 200, + className: 'notiflix-block', + position: 'absolute', + zindex: 1000, + backgroundColor: 'rgba(255,255,255,0.9)', + rtl: false, + useGoogleFont: true, + fontFamily: 'Quicksand', + cssAnimation: true, + cssAnimationDuration: 300, + svgSize: '45px', + svgColor: '#383838', + messageFontSize: '14px', + messageMaxLength: 34, + messageColor: '#383838', + }; + // Notiflix: Block Default Settings off + + // Notiflix: Extend on + var extendNotiflix = function () { + // variables + var extended = {}; + var deep = false; + var i = 0; + // check if a deep merge + if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') { + deep = arguments[0]; + i++; + } + // merge the object into the extended object + var merge = function (obj) { + for (var prop in obj) { + if (Object.prototype.hasOwnProperty.call(obj, prop)) { + // if property is an object, merge properties + if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') { + extended[prop] = extendNotiflix(extended[prop], obj[prop]); + } else { + extended[prop] = obj[prop]; + } + } + } + }; + // loop through each object and conduct a merge + for (; i < arguments.length; i++) { + merge(arguments[i]); + } + return extended; + }; + // Notiflix: Extend off + + // Notiflix: Plaintext on + var notiflixPlaintext = function (html) { + var htmlPool = document.createElement('div'); + htmlPool.innerHTML = html; + return htmlPool.textContent || htmlPool.innerText || ''; + }; + // Notiflix: Plaintext off + + // Notiflix: GoogleFont on + var notiflixGoogleFont = function (use, family) { + if (!document.getElementById('NotiflixQuicksand') && use && (family && typeof family === 'string' && family.toLowerCase() === 'quicksand')) { + // google fonts dns prefetch on + var dns = ''; + var dnsRange = document.createRange(); + dnsRange.selectNode(document.head); + var dnsFragment = dnsRange.createContextualFragment(dns); + document.head.appendChild(dnsFragment); + // google fonts dns prefetch off + + // google fonts style on + var font = ''; + var fontRange = document.createRange(); + fontRange.selectNode(document.head); + var fontFragment = fontRange.createContextualFragment(font); + document.head.appendChild(fontFragment); + // google fonts style off + } + }; + // Notiflix: GoogleFont off + + // Notiflix: Console Error on + var notiflixConsoleError = function (title, message) { + return console.error('%c ' + title + ' ', 'padding:2px;border-radius:20px;color:#fff;background:#ff5549', '\n' + message + '\nVisit documentation page to learn more: https://www.notiflix.com/documentation'); + }; + // Notiflix: Console Error off + + // Notiflix: Console Log on + var notiflixConsoleLog = function (title, message) { + return console.log('%c ' + title + ' ', 'padding:2px;border-radius:20px;color:#fff;background:#26c0d3', '\n' + message + '\nVisit documentation page to learn more: https://www.notiflix.com/documentation'); + }; + // Notiflix: Console Log off + + // Notiflix: Main on + var newNotifySettings; + var newReportSettings; + var newConfirmSettings; + var newLoadingSettings; + var newBlockSettings; + var Notiflix = { + // Notify on + Notify: { + + // Init + Init: function (userNotifyOpt) { + // extend options + newNotifySettings = extendNotiflix(true, notifySettings, userNotifyOpt); + // use GoogleFonts if "Quicksand" + notiflixGoogleFont(newNotifySettings.useGoogleFont, newNotifySettings.fontFamily); + }, + + // Merge First Init + Merge: function (userNotifyExtend) { + // if initialized already + if (newNotifySettings) { + newNotifySettings = extendNotiflix(true, newNotifySettings, userNotifyExtend); + } + // initialize first + else { + notiflixConsoleError('Notiflix Error', 'You have to initialize the Notify module before call Merge function.'); + return false; + } + }, + + // Display Notification: Success + Success: function (message, callback) { + // if not initialized pretend like init + if (!newNotifySettings) { + Notiflix.Notify.Init({}); + } + var theType = newNotifySettings.success; + NotiflixNotify(message, callback, theType, 'Success'); + }, + + // Display Notification: Failure + Failure: function (message, callback) { + // if not initialized pretend like init + if (!newNotifySettings) { + Notiflix.Notify.Init({}); + } + var theType = newNotifySettings.failure; + NotiflixNotify(message, callback, theType, 'Failure'); + }, + + // Display Notification: Warning + Warning: function (message, callback) { + // if not initialized pretend like init + if (!newNotifySettings) { + Notiflix.Notify.Init({}); + } + var theType = newNotifySettings.warning; + NotiflixNotify(message, callback, theType, 'Warning'); + }, + + // Display Notification: Info + Info: function (message, callback) { + // if not initialized pretend like init + if (!newNotifySettings) { + Notiflix.Notify.Init({}); + } + var theType = newNotifySettings.info; + NotiflixNotify(message, callback, theType, 'Info'); + }, + }, + // Notify off + + // Report on + Report: { + + // Init + Init: function (userReportOpt) { + // extend options + newReportSettings = extendNotiflix(true, reportSettings, userReportOpt); + // use GoogleFonts if "Quicksand" + notiflixGoogleFont(newReportSettings.useGoogleFont, newReportSettings.fontFamily); + }, + + // Merge First Init + Merge: function (userReportExtend) { + // if initialized already + if (newReportSettings) { + newReportSettings = extendNotiflix(true, newReportSettings, userReportExtend); + } + // initialize first + else { + notiflixConsoleError('Notiflix Error', 'You have to initialize the Report module before call Merge function.'); + return false; + } + }, + + // Display Report: Success + Success: function (title, message, buttonText, buttonCallback) { + // if not initialized pretend like init + if (!newReportSettings) { + Notiflix.Report.Init({}); + } + var theType = newReportSettings.success; + NotiflixReport(title, message, buttonText, buttonCallback, theType, 'Success'); + }, + + // Display Report: Failure + Failure: function (title, message, buttonText, buttonCallback) { + // if not initialized pretend like init + if (!newReportSettings) { + Notiflix.Report.Init({}); + } + var theType = newReportSettings.failure; + NotiflixReport(title, message, buttonText, buttonCallback, theType, 'Failure'); + }, + + // Display Report: Warning + Warning: function (title, message, buttonText, buttonCallback) { + // if not initialized pretend like init + if (!newReportSettings) { + Notiflix.Report.Init({}); + } + var theType = newReportSettings.warning; + NotiflixReport(title, message, buttonText, buttonCallback, theType, 'Warning'); + }, + + // Display Report: Info + Info: function (title, message, buttonText, buttonCallback) { + // if not initialized pretend like init + if (!newReportSettings) { + Notiflix.Report.Init({}); + } + var theType = newReportSettings.info; + NotiflixReport(title, message, buttonText, buttonCallback, theType, 'Info'); + }, + }, + // Report off + + // Confirm on + Confirm: { + + // Init + Init: function (userConfirmOpt) { + // extend options + newConfirmSettings = extendNotiflix(true, confirmSettings, userConfirmOpt); + // use GoogleFonts if "Quicksand" + notiflixGoogleFont(newConfirmSettings.useGoogleFont, newConfirmSettings.fontFamily); + }, + + // Merge First Init + Merge: function (userConfirmExtend) { + // if initialized already + if (newConfirmSettings) { + newConfirmSettings = extendNotiflix(true, newConfirmSettings, userConfirmExtend); + } + // initialize first + else { + notiflixConsoleError('Notiflix Error', 'You have to initialize the Confirm module before call Merge function.'); + return false; + } + }, + + // Display Confirm: Show + Show: function (title, message, okText, cancelText, okCallback, cancelCallback) { + if (!title) { title = 'Notiflix Confirm'; } + if (!message) { message = 'Do you agree with me?'; } + if (!okText) { okText = 'Yes'; } + if (!cancelText) { cancelText = 'No'; } + if (!okCallback) { okCallback = undefined; } + if (!cancelCallback) { cancelCallback = undefined; } + NotiflixConfirm(title, message, okText, cancelText, okCallback, cancelCallback); + }, + }, + // Confirm off + + // Loading on + Loading: { + + // Init + Init: function (userLoadingOpt) { + // extend options + newLoadingSettings = extendNotiflix(true, loadingSettings, userLoadingOpt); + // use GoogleFonts if "Quicksand" + notiflixGoogleFont(newLoadingSettings.useGoogleFont, newLoadingSettings.fontFamily); + }, + + // Merge First Init + Merge: function (userLoadingExtend) { + // if initialized already + if (newLoadingSettings) { + newLoadingSettings = extendNotiflix(true, newLoadingSettings, userLoadingExtend); + } + // initialize first + else { + notiflixConsoleError('Notiflix Error', 'You have to initialize the Loading module before call Merge function.'); + return false; + } + }, + + // Display Loading: Standard + Standard: function (message) { + NotiflixLoading(message, 'standard', true, 0); // true => display || 0 => delay + }, + + // Display Loading: Hourglass + Hourglass: function (message) { + NotiflixLoading(message, 'hourglass', true, 0); // true => display || 0 => delay + }, + + // Display Loading: Circle + Circle: function (message) { + NotiflixLoading(message, 'circle', true, 0); // true => display || 0 => delay + }, + + // Display Loading: Arrows + Arrows: function (message) { + NotiflixLoading(message, 'arrows', true, 0); // true => display || 0 => delay + }, + + // Display Loading: Dots + Dots: function (message) { + NotiflixLoading(message, 'dots', true, 0); // true => display || 0 => delay + }, + + // Display Loading: Pulse + Pulse: function (message) { + NotiflixLoading(message, 'pulse', true, 0); // true => display || 0 => delay + }, + + // Display Loading: Custom + Custom: function (message) { + NotiflixLoading(message, 'custom', true, 0); // true => display || 0 => delay + }, + + // Display Loading: Notiflix + Notiflix: function (message) { + NotiflixLoading(message, 'notiflix', true, 0); // true => display || 0 => delay + }, + + // Remove Loading + Remove: function (theDelay) { + if (!theDelay) { theDelay = 0; } + NotiflixLoading(false, false, false, theDelay); // false = Remove + }, + + // Change The Message + Change: function (newMessage) { + NotiflixLoadingChange(newMessage); + }, + }, + // Loading off + + // Block on + Block: { + + // Initialize + Init: function (userBlockOpt) { + // extend options + newBlockSettings = extendNotiflix(true, blockSettings, userBlockOpt); + // use GoogleFonts if "Quicksand" + notiflixGoogleFont(newBlockSettings.useGoogleFont, newBlockSettings.fontFamily); + }, + + // Merge First Initialize + Merge: function (userBlockExtend) { + // if initialized already + if (newBlockSettings) { + newBlockSettings = extendNotiflix(true, newBlockSettings, userBlockExtend); + } + // initialize first + else { + notiflixConsoleError('Notiflix Error', 'You have to initialize the "Notiflix.Block" module before call Merge function.'); + return false; + } + }, + + // Display Block: Standard + Standard: function (selector, message) { + var block = true; + var theIcon = 'standard'; + NotiflixBlockUnblockElement(block, selector, theIcon, message); + }, + + // Display Block: Hourglass + Hourglass: function (selector, message) { + var block = true; + var theIcon = 'hourglass'; + NotiflixBlockUnblockElement(block, selector, theIcon, message); + }, + + // Display Block: Circle + Circle: function (selector, message) { + var block = true; + var theIcon = 'circle'; + NotiflixBlockUnblockElement(block, selector, theIcon, message); + }, + + // Display Block: Arrows + Arrows: function (selector, message) { + var block = true; + var theIcon = 'arrows'; + NotiflixBlockUnblockElement(block, selector, theIcon, message); + }, + + // Display Block: Dots + Dots: function (selector, message) { + var block = true; + var theIcon = 'dots'; + NotiflixBlockUnblockElement(block, selector, theIcon, message); + }, + + // Display Block: Pulse + Pulse: function (selector, message) { + var block = true; + var theIcon = 'pulse'; + NotiflixBlockUnblockElement(block, selector, theIcon, message); + }, + + // Remove Block + Remove: function (selector, delay) { + var block = false; + var theIcon = null; + var message = null; + NotiflixBlockUnblockElement(block, selector, theIcon, message, delay); + }, + }, + // Block off + }; + // Notiflix: Main off + + + // Notiflix: Notify Single on + var notiflixNotifyCount = 0; + var NotiflixNotify = function (message, callback, theType, staticType) { + if (arguments && arguments.length === 4) { + + // notify counter on + notiflixNotifyCount++; + // notify counter off + + // if no message on + if (!message) { + message = 'Notiflix ' + staticType; + } + // if no message off + + // if plainText true = HTML tags not allowed on + if (newNotifySettings.plainText) { + message = notiflixPlaintext(message); // message plain text + } + // if plainText true = HTML tags not allowed off + + // if plainText false but the message length more than messageMaxLength = HTML tags error on + if (!newNotifySettings.plainText && message.length > newNotifySettings.messageMaxLength) { + Notiflix.Notify.Merge({ closeButton: true, plainText: false, }); + message = 'HTML Tags Error: Your content length is more than "messageMaxLength" option.'; // message html error + } + // if plainText false but the message length more than messageMaxLength = HTML tags error off + + // message max length substring on + if (message.length > newNotifySettings.messageMaxLength) { + message = message.substring(0, newNotifySettings.messageMaxLength) + '...'; + } + // message max length substring off + + // font awesome icon style on + if (newNotifySettings.fontAwesomeIconStyle === 'shadow') { + theType.fontAwesomeIconColor = theType.background; + } + // font awesome icon style off + + // if cssAnimaion false -> duration on + if (!newNotifySettings.cssAnimation) { + newNotifySettings.cssAnimationDuration = 0; + } + // if cssAnimaion false -> duration off + + // notify wrap on + var docBody = document.body; + var ntflxNotifyWrap = document.createElement('div'); + ntflxNotifyWrap.id = notifySettings.wrapID; + ntflxNotifyWrap.style.width = newNotifySettings.width; + ntflxNotifyWrap.style.zIndex = newNotifySettings.zindex; + ntflxNotifyWrap.style.opacity = newNotifySettings.opacity; + + // wrap position on + if (newNotifySettings.position === 'right-bottom') { + ntflxNotifyWrap.style.right = newNotifySettings.distance; + ntflxNotifyWrap.style.bottom = newNotifySettings.distance; + ntflxNotifyWrap.style.top = 'auto'; + ntflxNotifyWrap.style.left = 'auto'; + } else if (newNotifySettings.position === 'left-top') { + ntflxNotifyWrap.style.left = newNotifySettings.distance; + ntflxNotifyWrap.style.top = newNotifySettings.distance; + ntflxNotifyWrap.style.right = 'auto'; + ntflxNotifyWrap.style.bottom = 'auto'; + } else if (newNotifySettings.position === 'left-bottom') { + ntflxNotifyWrap.style.left = newNotifySettings.distance; + ntflxNotifyWrap.style.bottom = newNotifySettings.distance; + ntflxNotifyWrap.style.top = 'auto'; + ntflxNotifyWrap.style.right = 'auto'; + } else { // 'right-top' or else + ntflxNotifyWrap.style.right = newNotifySettings.distance; + ntflxNotifyWrap.style.top = newNotifySettings.distance; + ntflxNotifyWrap.style.left = 'auto'; + ntflxNotifyWrap.style.bottom = 'auto'; + } + // wrap position off + + // if background overlay true on + var notifyOverlay; + if (newNotifySettings.backOverlay) { + notifyOverlay = document.createElement('div'); + notifyOverlay.id = newNotifySettings.ID + 'Overlay'; + notifyOverlay.style.width = '100%'; + notifyOverlay.style.height = '100%'; + notifyOverlay.style.position = 'fixed'; + notifyOverlay.style.zIndex = newNotifySettings.zindex; + notifyOverlay.style.left = 0; + notifyOverlay.style.top = 0; + notifyOverlay.style.right = 0; + notifyOverlay.style.bottom = 0; + notifyOverlay.style.background = newNotifySettings.backOverlayColor; + notifyOverlay.className = (newNotifySettings.cssAnimation ? 'with-animation' : ''); + notifyOverlay.style.animationDuration = (newNotifySettings.cssAnimation) ? newNotifySettings.cssAnimationDuration + 'ms' : ''; + if (!document.getElementById(notifyOverlay.id)) { + docBody.appendChild(notifyOverlay); + } + } + // if background overlay true off + + if (!document.getElementById(ntflxNotifyWrap.id)) { + docBody.appendChild(ntflxNotifyWrap); + } + // notify wrap off + + // notify content on + var ntflxNotify = document.createElement('div'); + ntflxNotify.id = newNotifySettings.ID + '-' + notiflixNotifyCount; + ntflxNotify.className = newNotifySettings.className + ' ' + theType.childClassName + ' ' + (newNotifySettings.cssAnimation ? 'with-animation' : '') + ' ' + (newNotifySettings.useIcon ? 'with-icon' : '') + ' nx-' + newNotifySettings.cssAnimationStyle + ' ' + (newNotifySettings.closeButton && !callback ? 'with-close-button' : '') + ' ' + (callback && typeof callback === 'function' ? 'with-callback' : '') + ' ' + (newNotifySettings.clickToClose ? 'click-to-close' : ''); + ntflxNotify.style.fontSize = newNotifySettings.fontSize; + ntflxNotify.style.color = theType.textColor; + ntflxNotify.style.background = theType.background; + ntflxNotify.style.borderRadius = newNotifySettings.borderRadius; + + // rtl on + if (newNotifySettings.rtl) { + ntflxNotify.setAttribute('dir', 'rtl'); + ntflxNotify.classList.add('rtl-on'); + } + // rtl off + + // font-family on + ntflxNotify.style.fontFamily = '"' + newNotifySettings.fontFamily + '"' + ', sans-serif'; + // font-family off + + // use css animation on + if (newNotifySettings.cssAnimation) { + ntflxNotify.style.animationDuration = newNotifySettings.cssAnimationDuration + 'ms'; + } + // use css animation off + + // close button element on + var closeButtonHTML = ''; + if (newNotifySettings.closeButton && !callback) { + closeButtonHTML = ''; + } + // close buttpon element off + + // use icon on + if (newNotifySettings.useIcon) { + // use font awesome + if (newNotifySettings.useFontAwesome) { + ntflxNotify.innerHTML = '' + message + '' + (newNotifySettings.closeButton ? closeButtonHTML : ''); + } + // use notiflix icon + else { + var svgIcon; + if (staticType === 'Success') { // success + svgIcon = ''; + } else if (staticType === 'Failure') { // failure + svgIcon = ''; + } else if (staticType === 'Warning') { // warning + svgIcon = ''; + } else if (staticType === 'Info') { // info + svgIcon = ''; + } else { + svgIcon = ''; + } + ntflxNotify.innerHTML = svgIcon + '' + message + '' + (newNotifySettings.closeButton ? closeButtonHTML : ''); + } + } + // without icon + else { + ntflxNotify.innerHTML = '' + message + '' + (newNotifySettings.closeButton ? closeButtonHTML : ''); + } + // use icon off + // notify content off + + // notify append or prepend on + if (newNotifySettings.position === 'left-bottom' || newNotifySettings.position === 'right-bottom') { // the new one will be first + var notifyWrap = document.getElementById(ntflxNotifyWrap.id); + notifyWrap.insertBefore(ntflxNotify, notifyWrap.firstChild); + } else { + document.getElementById(ntflxNotifyWrap.id).appendChild(ntflxNotify); + } + + if (newNotifySettings.useIcon) { // if useIcon, dynamically vertical align the contents + var messageIcon = document.getElementById(ntflxNotify.id).querySelectorAll('.nmi')[0]; + var messageIconH = 40; + // if font awesome + if (newNotifySettings.useFontAwesome) { + messageIconH = Math.round(parseInt(messageIcon.offsetHeight)); + } + // if notiflix SVG + else { + var SvgBBox = messageIcon.getBBox(); + messageIconH = Math.round(parseInt(SvgBBox.width)); + } + var messageText = document.getElementById(ntflxNotify.id).querySelectorAll('span')[0]; + var messageTextH = Math.round(messageText.offsetHeight); + if (messageTextH <= messageIconH) { + messageText.style.paddingTop = (messageIconH - messageTextH) / 2 + 'px'; + messageText.style.paddingBottom = (messageIconH - messageTextH) / 2 + 'px'; + } + } + // notify append or prepend off + + // remove by timeout or click on + if (document.getElementById(ntflxNotify.id)) { + // set elements on + var removeDiv = document.getElementById(ntflxNotify.id); + var removeWrap = document.getElementById(ntflxNotifyWrap.id); + var removeOverlay; + if (newNotifySettings.backOverlay) { + removeOverlay = document.getElementById(notifyOverlay.id); + } + // set elements on + + // timeout vars on + var timeoutHide; + var timeoutRemove; + // timeout vars off + + // hide notify elm and hide overlay on + var hideNotifyElementsAndOverlay = function () { + removeDiv.classList.add('remove'); + if (newNotifySettings.backOverlay && removeWrap.childElementCount <= 0) { + removeOverlay.classList.add('remove'); + } + clearTimeout(timeoutHide); + }; + // hide notify elm and hide overlay off + + // remove notify elm and wrapper on + var removeNotifyElmentsAndWrapper = function () { + var notifyExist = document.getElementById(ntflxNotify.id); + if (notifyExist && removeDiv.parentNode !== null) { + removeDiv.parentNode.removeChild(removeDiv); + } + if (removeWrap.childElementCount <= 0 && removeWrap.parentNode !== null) { // if childs count === 0 remove wrap + removeWrap.parentNode.removeChild(removeWrap); + if (newNotifySettings.backOverlay && removeOverlay.parentNode !== null) { + removeOverlay.parentNode.removeChild(removeOverlay); + } + } + clearTimeout(timeoutRemove); + }; + // remove notify elm and wrapper off + + // if close button and callback undefined on + if (newNotifySettings.closeButton && !callback) { + var closeButtonElm = document.getElementById(ntflxNotify.id).querySelectorAll('span.notify-close-button')[0]; + closeButtonElm.addEventListener('click', function () { + hideNotifyElementsAndOverlay(); + var clickToCloseTimeout = setTimeout(function () { + removeNotifyElmentsAndWrapper(); + clearTimeout(clickToCloseTimeout); + }, newNotifySettings.cssAnimationDuration); + }); + } + // if close button and callback undefined off + + // if callback or click to close on + if ((callback && typeof callback === 'function') || newNotifySettings.clickToClose) { + removeDiv.addEventListener('click', function (e) { + if (callback && typeof callback === 'function') { + callback(); + } + hideNotifyElementsAndOverlay(); + var callbackTimeout = setTimeout(function () { + removeNotifyElmentsAndWrapper(); + clearTimeout(callbackTimeout); + }, newNotifySettings.cssAnimationDuration); + }); + } + // if callback or click to close off + + // else auto remove on + if (!newNotifySettings.closeButton && !callback) { + timeoutHide = setTimeout(function () { + hideNotifyElementsAndOverlay(); + }, newNotifySettings.timeout); + timeoutRemove = setTimeout(function () { + removeNotifyElmentsAndWrapper(); + }, newNotifySettings.timeout + newNotifySettings.cssAnimationDuration); + } + // else auto remove off + } + // remove by timeout or click off + + // notify - show only the last one on + if (newNotifySettings.showOnlyTheLastOne && notiflixNotifyCount > 0) { + var allNotifyElmNotTheLastOne = document.querySelectorAll('[id^=' + newNotifySettings.ID + '-]:not([id=' + newNotifySettings.ID + '-' + notiflixNotifyCount + '])'); + for (var i = 0; i < allNotifyElmNotTheLastOne.length; i++) { + var eachNotifyElmNotLastOne = allNotifyElmNotTheLastOne[i]; + if (eachNotifyElmNotLastOne.parentNode !== null) { + eachNotifyElmNotLastOne.parentNode.removeChild(eachNotifyElmNotLastOne); + } + } + } + // notify - show only the last one off + + } else { + notiflixConsoleError('Notiflix Error', 'Where is the arguments?'); + } + }; + // Notiflix: Notify Single off + + + // Notiflix: Report Single on + var NotiflixReport = function (title, message, buttonText, buttonCallback, theType, staticType) { + + // check the arguments on + if (!title) { title = 'Notiflix ' + staticType; } + if (!message) { + if (staticType === 'Success') { + message = '"Do not try to become a person of success but try to become a person of value."

                                                                                          - Albert Einstein'; + } + else if (staticType === 'Failure') { + message = '"Failure is simply the opportunity to begin again, this time more intelligently."

                                                                                          - Henry Ford'; + } + else if (staticType === 'Warning') { + message = '"The peoples who want to live comfortably without producing and fatigue; they are doomed to lose their dignity, then liberty, and then independence and destiny."

                                                                                          - Mustafa Kemal Ataturk'; + } + else if (staticType === 'Info') { + message = '"Knowledge rests not upon truth alone, but upon error also."

                                                                                          - Carl Gustav Jung'; + } + } + if (!buttonText) { buttonText = 'Okay'; } + if (!buttonCallback) { buttonCallback = undefined; } + // check the arguments off + + // if plainText true = HTML tags not allowed on + if (newReportSettings.plainText) { + title = notiflixPlaintext(title); + message = notiflixPlaintext(message); + buttonText = notiflixPlaintext(buttonText); + } + // if plainText true = HTML tags not allowed off + + // if plainText false but the contents length more than *MaxLength = HTML tags error on + if (!newReportSettings.plainText) { + if (title.length > newReportSettings.titleMaxLength) { + title = 'HTML Tags Error'; // title html error + message = 'Your Title content length is more than "titleMaxLength" option.'; // message html error + buttonText = 'Okay'; // button html error + } + if (message.length > newReportSettings.messageMaxLength) { + title = 'HTML Tags Error'; // title html error + message = 'Your Message content length is more than "messageMaxLength" option.'; // message html error + buttonText = 'Okay'; // button html error + } + if (buttonText.length > newReportSettings.buttonMaxLength) { + title = 'HTML Tags Error'; // title html error + message = 'Your Button content length is more than "buttonMaxLength" option.'; // message html error + buttonText = 'Okay'; // button html error + } + } + // if plainText false but the contents length more than *MaxLength = HTML tags error off + + // max length on + if (title.length > newReportSettings.titleMaxLength) { + title = title.substring(0, newReportSettings.titleMaxLength) + '...'; + } + if (message.length > newReportSettings.messageMaxLength) { + message = message.substring(0, newReportSettings.messageMaxLength) + '...'; + } + if (buttonText.length > newReportSettings.buttonMaxLength) { + buttonText = buttonText.substring(0, newReportSettings.buttonMaxLength) + '...'; + } + // max length off + + // if cssAnimaion false -> duration on + if (!newReportSettings.cssAnimation) { + newReportSettings.cssAnimationDuration = 0; + } + // if cssAnimaion false -> duration off + + // report wrap on + var docBody = document.body; + var ntflxReportWrap = document.createElement('div'); + ntflxReportWrap.id = reportSettings.ID; + ntflxReportWrap.className = newReportSettings.className; + ntflxReportWrap.style.width = newReportSettings.width; + ntflxReportWrap.style.zIndex = newReportSettings.zindex; + ntflxReportWrap.style.borderRadius = newReportSettings.borderRadius; + ntflxReportWrap.style.fontFamily = '"' + newReportSettings.fontFamily + '"' + ', sans-serif'; + + // rtl on + if (newReportSettings.rtl) { + ntflxReportWrap.setAttribute('dir', 'rtl'); + ntflxReportWrap.classList.add('rtl-on'); + } + // rtl off + + // overlay on + var reportOverlay = ''; + if (newReportSettings.backOverlay) { + reportOverlay = '
                                                                                          '; + } + // overlay off + + // svg icon on + var svgIcon = ''; + if (staticType === 'Success') { + svgIcon = notiflixReportSvgSuccess(newReportSettings.svgSize, theType.svgColor); + } else if (staticType === 'Failure') { + svgIcon = notiflixReportSvgFailure(newReportSettings.svgSize, theType.svgColor); + } else if (staticType === 'Warning') { + svgIcon = notiflixReportSvgWarning(newReportSettings.svgSize, theType.svgColor); + } else if (staticType === 'Info') { + svgIcon = notiflixReportSvgInfo(newReportSettings.svgSize, theType.svgColor); + } + // svg icon off + + ntflxReportWrap.innerHTML = reportOverlay + '
                                                                                          ' + + '
                                                                                          ' + svgIcon + '
                                                                                          ' + + '
                                                                                          ' + title + '
                                                                                          ' + + '

                                                                                          ' + message + '

                                                                                          ' + + '' + buttonText + '' + + '
                                                                                          '; + + // if there is no report element + if (!document.getElementById(ntflxReportWrap.id)) { + // append + docBody.appendChild(ntflxReportWrap); + + // vertical align on + var windowH = Math.round(window.innerHeight); + var reportH = Math.round(document.getElementById(ntflxReportWrap.id).offsetHeight); + ntflxReportWrap.style.top = (windowH - reportH) / 2 + 'px'; + // vertical align off + + // callback on + var getReportWrap = document.getElementById(ntflxReportWrap.id); + var reportButton = document.getElementById('NXReportButton'); + reportButton.addEventListener('click', function () { + // if callback on + if (buttonCallback && typeof buttonCallback === 'function') { + buttonCallback(); + } + // if callback off + + // remove element on + getReportWrap.classList.add('remove'); + var timeout = setTimeout(function () { + if (getReportWrap.parentNode !== null) { + getReportWrap.parentNode.removeChild(getReportWrap); + } + clearTimeout(timeout); + }, newReportSettings.cssAnimationDuration); + // remove element off + }); + // callback off + + } + // report wrap off + + }; + // Notiflix: Report Single off + + + // Notiflix: Confirm Single on + var NotiflixConfirm = function (title, message, okButtonText, cancelButtonText, okButtonCallback, cancelButtonCallback) { + // if not initialized pretend like init + if (!newConfirmSettings) { + Notiflix.Confirm.Init({}); + } + + // if plainText true => HTML tags not allowed on + if (newConfirmSettings.plainText) { + title = notiflixPlaintext(title); + message = notiflixPlaintext(message); + okButtonText = notiflixPlaintext(okButtonText); + cancelButtonText = notiflixPlaintext(cancelButtonText); + } + // if plainText true => HTML tags not allowed off + + // if plainText false but the contents length more than *MaxLength = HTML tags error on + if (!newConfirmSettings.plainText) { + if (title.length > newConfirmSettings.titleMaxLength) { + title = 'HTML Tags Error'; // title html error + message = 'Your Title content length is more than "titleMaxLength" option.'; // message html error + okButtonText = 'Okay'; // button html error + cancelButtonText = '...'; // button html error + } + if (message.length > newConfirmSettings.messageMaxLength) { + title = 'HTML Tags Error'; // title html error + message = 'Your Message content length is more than "messageMaxLength" option.'; // message html error + okButtonText = 'Okay'; // button html error + cancelButtonText = '...'; // button html error + } + if ((okButtonText.length || cancelButtonText.length) > newConfirmSettings.buttonsMaxLength) { + title = 'HTML Tags Error'; // title html error + message = 'Your Buttons contents length is more than "buttonsMaxLength" option.'; // message html error + okButtonText = 'Okay'; // button html error + cancelButtonText = '...'; // button html error + } + } + // if plainText false but the contents length more than *MaxLength = HTML tags error off + + // max length on + if (title.length > newConfirmSettings.titleMaxLength) { + title = title.substring(0, newConfirmSettings.titleMaxLength) + '...'; + } + if (message.length > newConfirmSettings.messageMaxLength) { + message = message.substring(0, newConfirmSettings.messageMaxLength) + '...'; + } + if (okButtonText.length > newConfirmSettings.buttonsMaxLength) { + okButtonText = okButtonText.substring(0, newConfirmSettings.buttonsMaxLength) + '...'; + } + if (cancelButtonText.length > newConfirmSettings.buttonsMaxLength) { + cancelButtonText = cancelButtonText.substring(0, newConfirmSettings.buttonsMaxLength) + '...'; + } + // max length off + + // if cssAnimaion false -> duration on + if (!newConfirmSettings.cssAnimation) { + newConfirmSettings.cssAnimationDuration = 0; + } + // if cssAnimaion false -> duration off + + // confirm wrap on + var docBody = document.body; + var ntflxConfirmWrap = document.createElement('div'); + ntflxConfirmWrap.id = confirmSettings.ID; + ntflxConfirmWrap.className = newConfirmSettings.className + (newConfirmSettings.cssAnimation ? ' with-animation nx-' + newConfirmSettings.cssAnimationStyle : ''); + ntflxConfirmWrap.style.width = newConfirmSettings.width; + ntflxConfirmWrap.style.zIndex = newConfirmSettings.zindex; + + // rtl on + if (newConfirmSettings.rtl) { + ntflxConfirmWrap.setAttribute('dir', 'rtl'); + ntflxConfirmWrap.classList.add('rtl-on'); + } + // rtl off + + // font-family on + ntflxConfirmWrap.style.fontFamily = '"' + newConfirmSettings.fontFamily + '"' + ', sans-serif'; + // font-family off + + // if background overlay true on + var confirmOverlay = ''; + if (newConfirmSettings.backOverlay) { + confirmOverlay = '
                                                                                          '; + } + // if background overlay true off + + // if have a callback => add cancel button on + var cancelButtonHTML = ''; + if (okButtonCallback) { + cancelButtonHTML = '' + cancelButtonText + ''; + } + // if have a callback => add cancel button off + + ntflxConfirmWrap.innerHTML = confirmOverlay + + '
                                                                                          ' + + '
                                                                                          ' + + '
                                                                                          ' + title + '
                                                                                          ' + + '

                                                                                          ' + message + '

                                                                                          ' + + '
                                                                                          ' + + '
                                                                                          ' + + '' + okButtonText + '' + + cancelButtonHTML + + '
                                                                                          ' + + '
                                                                                          '; + // confirm wrap off + + // if there is no confirm box on + if (!document.getElementById(ntflxConfirmWrap.id)) { + docBody.appendChild(ntflxConfirmWrap); + + // position on + if (newConfirmSettings.position === 'center') { // if center-center + var windowH = Math.round(window.innerHeight); + var confirmH = Math.round(document.getElementById(ntflxConfirmWrap.id).offsetHeight); + ntflxConfirmWrap.style.top = (windowH - confirmH) / 2 + 'px'; + ntflxConfirmWrap.style.left = newConfirmSettings.distance; + ntflxConfirmWrap.style.right = newConfirmSettings.distance; + ntflxConfirmWrap.style.bottom = 'auto'; + ntflxConfirmWrap.style.margin = 'auto'; + } else if (newConfirmSettings.position === 'right-top') { // if right-top + ntflxConfirmWrap.style.right = newConfirmSettings.distance; + ntflxConfirmWrap.style.top = newConfirmSettings.distance; + ntflxConfirmWrap.style.bottom = 'auto'; + ntflxConfirmWrap.style.left = 'auto'; + ntflxConfirmWrap.style.margin = 'auto'; + } else if (newConfirmSettings.position === 'right-bottom') { // if right-bottom + ntflxConfirmWrap.style.right = newConfirmSettings.distance; + ntflxConfirmWrap.style.bottom = newConfirmSettings.distance; + ntflxConfirmWrap.style.top = 'auto'; + ntflxConfirmWrap.style.left = 'auto'; + ntflxConfirmWrap.style.margin = 'auto'; + } else if (newConfirmSettings.position === 'left-top') { // if left-top + ntflxConfirmWrap.style.left = newConfirmSettings.distance; + ntflxConfirmWrap.style.top = newConfirmSettings.distance; + ntflxConfirmWrap.style.right = 'auto'; + ntflxConfirmWrap.style.bottom = 'auto'; + ntflxConfirmWrap.style.margin = 'auto'; + } else if (newConfirmSettings.position === 'left-bottom') { // if left-bottom + ntflxConfirmWrap.style.left = newConfirmSettings.distance; + ntflxConfirmWrap.style.bottom = newConfirmSettings.distance; + ntflxConfirmWrap.style.top = 'auto'; + ntflxConfirmWrap.style.right = 'auto'; + ntflxConfirmWrap.style.margin = 'auto'; + } else { // if center-top + ntflxConfirmWrap.style.top = newConfirmSettings.distance; + ntflxConfirmWrap.style.left = 0; + ntflxConfirmWrap.style.right = 0; + ntflxConfirmWrap.style.bottom = 'auto'; + ntflxConfirmWrap.style.margin = 'auto'; + } + // position off + + // buttons listener on + var confirmCloseWrap = document.getElementById(ntflxConfirmWrap.id); + var okButton = document.getElementById('NXConfirmButtonOk'); + + // ok button listener on + okButton.addEventListener('click', function () { + // if ok callback && if ok callback is a function + if (okButtonCallback && typeof okButtonCallback === 'function') { + okButtonCallback(); + } + confirmCloseWrap.classList.add('remove'); + + var timeout = setTimeout(function () { + if (confirmCloseWrap.parentNode !== null) { + confirmCloseWrap.parentNode.removeChild(confirmCloseWrap); + clearTimeout(timeout); + } + }, newConfirmSettings.cssAnimationDuration); + }); + // ok button listener off + + // if ok callback && if ok callback a function => add Cancel Button listener on + if (okButtonCallback && typeof okButtonCallback === 'function') { + // cancel button listener on + var cancelButton = document.getElementById('NXConfirmButtonCancel'); + cancelButton.addEventListener('click', function () { + // if cancel callback && if cancel callback a function + if (cancelButtonCallback && typeof cancelButtonCallback === 'function') { + cancelButtonCallback(); + } + confirmCloseWrap.classList.add('remove'); + + var timeout = setTimeout(function () { + if (confirmCloseWrap.parentNode !== null) { + confirmCloseWrap.parentNode.removeChild(confirmCloseWrap); + clearTimeout(timeout); + } + }, newConfirmSettings.cssAnimationDuration); + }); + // cancel button listener off + } + // if ok callback && if ok callback a function => add Cancel Button listener off + // buttons listener off + } + // if there is no confirm box off + }; + // Notiflix: Confirm Single off + + + // Notiflix: Loading Single on + var NotiflixLoading = function (message, iconType, display, theDelay) { + // if not initialized pretend like init + if (!newLoadingSettings) { + Notiflix.Loading.Init({}); + } + // check the message + if (!message) { + message = ''; + } + // show loading + if (display) { + + // if message settings on + if (message.toString().length > newLoadingSettings.messageMaxLength) { + message = notiflixPlaintext(message).toString().substring(0, newLoadingSettings.messageMaxLength) + '...'; + } else { + message = notiflixPlaintext(message).toString(); + } + var intSvgSize = parseInt(newLoadingSettings.svgSize); + var messageHTML = ''; + if (message.length > 0) { + var messagePosTop = Math.round(intSvgSize - (intSvgSize / 4)).toString() + 'px'; + var messageHeight = (parseInt(newLoadingSettings.messageFontSize) * 1.4).toString() + 'px'; + messageHTML = '

                                                                                          ' + message + '

                                                                                          '; + } + // if message settings off + + // if cssAnimaion false -> duration on + if (!newLoadingSettings.cssAnimation) { + newLoadingSettings.cssAnimationDuration = 0; + } + // if cssAnimaion false -> duration off + + // svgIcon on + var svgIcon = ''; + if (iconType === 'standard') { + svgIcon = notiflixIndicatorSvgStandard(newLoadingSettings.svgSize, newLoadingSettings.svgColor); + } else if (iconType === 'hourglass') { + svgIcon = notiflixIndicatorSvgHourglass(newLoadingSettings.svgSize, newLoadingSettings.svgColor); + } else if (iconType === 'circle') { + svgIcon = notiflixIndicatorSvgCircle(newLoadingSettings.svgSize, newLoadingSettings.svgColor); + } else if (iconType === 'arrows') { + svgIcon = notiflixIndicatorSvgArrows(newLoadingSettings.svgSize, newLoadingSettings.svgColor); + } else if (iconType === 'dots') { + svgIcon = notiflixIndicatorSvgDots(newLoadingSettings.svgSize, newLoadingSettings.svgColor); + } else if (iconType === 'pulse') { + svgIcon = notiflixIndicatorSvgPulse(newLoadingSettings.svgSize, newLoadingSettings.svgColor); + } else if (iconType === 'custom' && newLoadingSettings.customSvgUrl !== null) { + svgIcon = 'Notiflix'; + } else if (iconType === 'custom' && newLoadingSettings.customSvgUrl == null) { + notiflixConsoleError('Notiflix Error', 'You have to set a static SVG url to "customSvgUrl" option to use Loading Custom.'); + return false; + } else if (iconType === 'notiflix') { + svgIcon = notiflixIndicatorSvgNotiflix(newLoadingSettings.svgSize, '#f8f8f8', '#32c682'); + } + var svgPosTop = 0; + if (message.length > 0) { + svgPosTop = '-' + Math.round(intSvgSize - (intSvgSize / 4)).toString() + 'px'; + } + var svgIconHTML = '
                                                                                          ' + svgIcon + '
                                                                                          '; + // svgIcon off + + // loading wrap on + var docBody = document.body; + var ntflxLoadingWrap = document.createElement('div'); + ntflxLoadingWrap.id = loadingSettings.ID; + ntflxLoadingWrap.className = newLoadingSettings.className + (newLoadingSettings.cssAnimation ? ' with-animation' : '') + (newLoadingSettings.clickToClose ? ' click-to-close' : ''); + ntflxLoadingWrap.style.zIndex = newLoadingSettings.zindex; + ntflxLoadingWrap.style.background = newLoadingSettings.backgroundColor; + ntflxLoadingWrap.style.animationDuration = newLoadingSettings.cssAnimationDuration + 'ms'; + ntflxLoadingWrap.style.fontFamily = '"' + newLoadingSettings.fontFamily + '"' + ', sans-serif'; + + // rtl on + if (newLoadingSettings.rtl) { + ntflxLoadingWrap.setAttribute('dir', 'rtl'); + ntflxLoadingWrap.classList.add('rtl-on'); + } + // rtl off + + // append on + ntflxLoadingWrap.innerHTML = svgIconHTML + messageHTML; + + // if there is no loading element + if (!document.getElementById(ntflxLoadingWrap.id)) { + // append + docBody.appendChild(ntflxLoadingWrap); + + // if click to close + if (newLoadingSettings.clickToClose) { + var loadingWrapElm = document.getElementById(ntflxLoadingWrap.id); + loadingWrapElm.addEventListener('click', function () { + ntflxLoadingWrap.classList.add('remove'); + var timeout = setTimeout(function () { + if (ntflxLoadingWrap.parentNode !== null) { + ntflxLoadingWrap.parentNode.removeChild(ntflxLoadingWrap); + clearTimeout(timeout); + } + }, newLoadingSettings.cssAnimationDuration); + }); + } + } + // append off + + } + // remove loading + else { + // if there is a loading element + if (document.getElementById(loadingSettings.ID)) { + var loadingElm = document.getElementById(loadingSettings.ID); + var timeout = setTimeout(function () { + loadingElm.classList.add('remove'); + var timeout2 = setTimeout(function () { + if (loadingElm.parentNode !== null) { + loadingElm.parentNode.removeChild(loadingElm); + clearTimeout(timeout2); + } + }, newLoadingSettings.cssAnimationDuration); + clearTimeout(timeout); + }, theDelay); + } + } + }; + // Notiflix: Loading Single off + + // Notiflix: Loading Change Message on + var NotiflixLoadingChange = function (newMessage) { + // check the new message + if (!newMessage) { + newMessage = ''; + } + // if has any loading + if (document.getElementById(loadingSettings.ID)) { + // if there is a new message + if (newMessage.length > 0) { + // max length on + if (newMessage.length > newLoadingSettings.messageMaxLength) { + newMessage = notiflixPlaintext(newMessage).toString().substring(0, newLoadingSettings.messageMaxLength) + '...'; + } else { + newMessage = notiflixPlaintext(newMessage).toString(); + } + // max length off + + // there is a message element + var oldMessageElm = document.getElementById(loadingSettings.ID).getElementsByTagName('p')[0]; + if (oldMessageElm) { + oldMessageElm.innerHTML = newMessage; // change the message + } + // there is no message element + else { + // create a new message element on + var newMessageHTML = document.createElement('p'); + newMessageHTML.id = newLoadingSettings.messageID; + newMessageHTML.className = 'loading-message new'; + newMessageHTML.style.color = newLoadingSettings.messageColor; + newMessageHTML.style.fontSize = newLoadingSettings.messageFontSize; + var intSvgSize = parseInt(newLoadingSettings.svgSize); + var messagePosTop = Math.round(intSvgSize - (intSvgSize / 4)).toString() + 'px'; + newMessageHTML.style.top = messagePosTop; + var messageHeight = (parseInt(newLoadingSettings.messageFontSize) * 1.4).toString() + 'px'; + newMessageHTML.style.height = messageHeight; + newMessageHTML.innerHTML = newMessage; + var messageWrap = document.getElementById(loadingSettings.ID); + messageWrap.appendChild(newMessageHTML); + // create a new message element off + + // vertical align svg on + var svgDivElm = document.getElementById(loadingSettings.ID).getElementsByTagName('div')[0]; + var svgNewPosTop = '-' + Math.round(intSvgSize - (intSvgSize / 4)).toString() + 'px'; + svgDivElm.style.top = svgNewPosTop; + // vertical align svg off + } + } + // if no message + else { + notiflixConsoleError('Notiflix Error', 'Where is the new message?'); + } + } + }; + // Notiflix: Loading Change Message off + + + // Notiflix: Block or Unblock Element on + var notiflixBlockElementCounter = 0; + var NotiflixBlockUnblockElement = function (block, selector, iconType, message, theDelay) { + + // check typeof selector on + if (typeof selector !== 'string') { + notiflixConsoleError('Notiflix Error', 'The selector must be a String.'); + return false; + } + // check typeof selector off + + // check the delay on + if (typeof theDelay !== 'number') { + theDelay = 0; + } + // check the delay off + + // check the selector on + var getSelector = document.querySelectorAll(selector); + if (getSelector.length > 0) { + + // if not initialized pretend like init on + if (!newBlockSettings) { + Notiflix.Block.Init({}); + } + // if not initialized pretend like init off + + // check the message on + if (!message || (message && typeof message !== 'string')) { + message = undefined; + } + // check the message off + + } else { + notiflixConsoleError('Notiflix Error', 'You called the "Notiflix.Block..." function with "' + selector + '" selector, but there is no such element(s) on the document.'); + return false; + } + // check the selector off + + // if cssAnimaion false => duration on + if (!newBlockSettings.cssAnimation) { + newBlockSettings.cssAnimationDuration = 0; + } + // if cssAnimaion false => duration off + + // check the class name on + var blockClassName = 'notiflix-block'; + if (newBlockSettings.className && typeof newBlockSettings.className === 'string') { + blockClassName = newBlockSettings.className.trim(); + } + // check the class name off + + // check query limit on + var getQueryLimit = (typeof newBlockSettings.querySelectorLimit === 'number' ? newBlockSettings.querySelectorLimit : 200); + var checkQueryLimit = (getSelector.length >= getQueryLimit ? getQueryLimit : getSelector.length); + // check query limit off + + // block + if (block) { + + // add element(s) and style on + for (var i = 0; i < checkQueryLimit; i++) { + var eachSelector = getSelector[i]; + + // check block element exist on + var eachBlockElement = eachSelector.querySelectorAll('[id^=' + blockSettings.ID + ']'); + if (eachBlockElement.length < 1) { + + // check the icon on + var icon = ''; + if (iconType) { + if (iconType === 'hourglass') { + icon = notiflixIndicatorSvgHourglass(newBlockSettings.svgSize, newBlockSettings.svgColor); + } else if (iconType === 'circle') { + icon = notiflixIndicatorSvgCircle(newBlockSettings.svgSize, newBlockSettings.svgColor); + } else if (iconType === 'arrows') { + icon = notiflixIndicatorSvgArrows(newBlockSettings.svgSize, newBlockSettings.svgColor); + } else if (iconType === 'dots') { + icon = notiflixIndicatorSvgDots(newBlockSettings.svgSize, newBlockSettings.svgColor); + } else if (iconType === 'pulse') { + icon = notiflixIndicatorSvgPulse(newBlockSettings.svgSize, newBlockSettings.svgColor); + } else { + icon = notiflixIndicatorSvgStandard(newBlockSettings.svgSize, newBlockSettings.svgColor); + } + } + var intSvgSize = parseInt(newBlockSettings.svgSize); + var posRatio = Math.round(intSvgSize - (intSvgSize / 5)).toString() + 'px'; + var svgPosTop = (message && message.length > 0 ? '-' + posRatio : 0); + var iconElement = '' + icon + ''; + // check the icon off + + // check the message on + var messageElement = ''; + var messageHeight = 0; + if (message) { + if (message.length > newBlockSettings.messageMaxLength) { + message = notiflixPlaintext(message).toString().substring(0, newBlockSettings.messageMaxLength) + '...'; + } else { + message = notiflixPlaintext(message).toString(); + } + messageHeight = Math.round(parseInt(newBlockSettings.messageFontSize) * 1.4).toString() + 'px'; + messageElement = '' + message + ''; + } + // check the message off + + // block element on + notiflixBlockElementCounter++; + var notiflixBlockWrap = document.createElement('div'); + notiflixBlockWrap.id = blockSettings.ID + '-' + notiflixBlockElementCounter; + notiflixBlockWrap.className = blockClassName + '-wrap' + (newBlockSettings.cssAnimation ? ' with-animation' : ''); + notiflixBlockWrap.style.position = newBlockSettings.position; + notiflixBlockWrap.style.zIndex = newBlockSettings.zindex; + notiflixBlockWrap.style.background = newBlockSettings.backgroundColor; + notiflixBlockWrap.style.animationDuration = newBlockSettings.cssAnimationDuration + 'ms'; + notiflixBlockWrap.style.fontFamily = '"' + newBlockSettings.fontFamily + '"' + ', sans-serif'; + // block element off + + // block element rtl on + if (newBlockSettings.rtl) { + notiflixBlockWrap.setAttribute('dir', 'rtl'); + notiflixBlockWrap.classList.add('rtl-on'); + } + // block element rtl off + + // block element data on + notiflixBlockWrap.innerHTML = iconElement + messageElement; + // block element data off + + // append block element on + var eachSelectorPos = getComputedStyle(eachSelector).getPropertyValue('position'); + eachSelectorPos = eachSelectorPos && typeof eachSelectorPos === 'string' ? eachSelectorPos.toLowerCase() : 'relative'; + + // selector internal style on + var eachSelectorIdOrClass = ''; + if (eachSelector.getAttribute('id')) { + eachSelectorIdOrClass = '#' + eachSelector.getAttribute('id'); + } else if (eachSelector.classList[0]) { + eachSelectorIdOrClass = '.' + eachSelector.classList[0]; + } + + var positions = ['absolute', 'relative', 'fixed', 'sticky']; + if (positions.indexOf(eachSelectorPos) <= -1) { + var minHeight = Math.round((parseInt(messageHeight) + intSvgSize) * 1.5).toString() + 'px'; + var style = ''; + var styleRange = document.createRange(); + styleRange.selectNode(document.head); + var styleFragment = styleRange.createContextualFragment(style); + document.head.appendChild(styleFragment); + eachSelector.classList.add(blockClassName + '-position'); + } + // selector internal style off + + // append + eachSelector.appendChild(notiflixBlockWrap); + // append block element off + } + // check block element exist off + } + // add element(s) and style off + } + // unblock/remove + else { + + // Step 3 => Remove each block element on + var removeBlockElements = function (eachOne) { + var timeout = setTimeout(function () { + // remove element + eachOne.remove(); + + // remove this selector internal style + var eachOneId = eachOne.getAttribute('id'); + var eachOneStyle = document.getElementById('Style-' + eachOneId); + if (eachOneStyle) { + eachOneStyle.remove(); + } + + // clear timeout + clearTimeout(timeout); + }, newBlockSettings.cssAnimationDuration); + } + // Step 3 => Remove each block element off + + // Step 2A => Remove each block element on + var removeClassBlockElements = function (eachBlockElement) { + // if elements exist + if (eachBlockElement && eachBlockElement.length > 0) { + for (var i = 0; i < eachBlockElement.length; i++) { + var eachOne = eachBlockElement[i]; + if (eachOne) { + // add remove class + eachOne.classList.add('remove'); + // remove block elements + removeBlockElements(eachOne); + } + } + } + // not exist + else { + notiflixConsoleLog('Notiflix Info', '"Notiflix.Block.Remove();" function called with "' + selector + '" selector, but this selector does not have a "Notiflix.Block..." element to remove.'); + } + } + // Step 2A => Remove each block element on + + // Step 2B => Remove each selector class name on + var removeEachSelectorClassName = function (eachSelector) { + var timeout = setTimeout(function () { + // remove class name + var positionClass = blockClassName + '-position'; + eachSelector.classList.remove(positionClass); + + // clear timeout + clearTimeout(timeout); + }, newBlockSettings.cssAnimationDuration + 300); + } + // Step 2B => Remove each selector class name off + + // Step 1 => Remove selector class name on + var selectorTimeout = setTimeout(function () { + for (var i = 0; i < checkQueryLimit; i++) { + var eachSelector = getSelector[i]; + + // remove each selector class name + removeEachSelectorClassName(eachSelector); + + // remove each block element + eachBlockElement = eachSelector.querySelectorAll('[id^=' + blockSettings.ID + ']'); + removeClassBlockElements(eachBlockElement); + } + // clear timeout + clearTimeout(selectorTimeout); + }, theDelay); + // Step 1 => Remove selector class name off + } + }; + // Notiflix: Block or Unblock Element off + + + // Notiflix: Report SVG Success on + var notiflixReportSvgSuccess = function (width, color) { + if (!width) { width = '110px'; } + if (!color) { color = '#32c682'; } + var reportSvgSuccess = ''; + return reportSvgSuccess; + }; + // Notiflix: Report SVG Success off + + // Notiflix: Report SVG Failure on + var notiflixReportSvgFailure = function (width, color) { + if (!width) { width = '110px'; } + if (!color) { color = '#ff5549'; } + var reportSvgFailure = ''; + return reportSvgFailure; + }; + // Notiflix: Report SVG Failure off + + // Notiflix: Report SVG Warning on + var notiflixReportSvgWarning = function (width, color) { + if (!width) { width = '110px'; } + if (!color) { color = '#eebf31'; } + var reportSvgWarning = ''; + return reportSvgWarning; + }; + // Notiflix: Report SVG Warning off + + // Notiflix: Report SVG Info on + var notiflixReportSvgInfo = function (width, color) { + if (!width) { width = '110px'; } + if (!color) { color = '#26c0d3'; } + var reportSvgInfo = ''; + return reportSvgInfo; + }; + // Notiflix: Report SVG Info off + + + // Notiflix: Indicator SVG standard on + var notiflixIndicatorSvgStandard = function (width, color) { + if (!width) { width = '60px'; } + if (!color) { color = '#32c682'; } + var standard = ''; + return standard; + }; + // Notiflix: Indicator SVG standard off + + // Notiflix: Indicator SVG hourglass on + var notiflixIndicatorSvgHourglass = function (width, color) { + if (!width) { width = '60px'; } + if (!color) { color = '#32c682'; } + var hourglass = ' '; + return hourglass; + }; + // Notiflix: Indicator SVG hourglass off + + // Notiflix: Indicator SVG circle on + var notiflixIndicatorSvgCircle = function (width, color) { + if (!width) { width = '60px'; } + if (!color) { color = '#32c682'; } + var circle = ''; + return circle; + }; + // Notiflix: Indicator SVG circle off + + // Notiflix: Indicator SVG arrows on + var notiflixIndicatorSvgArrows = function (width, color) { + if (!width) { width = '60px'; } + if (!color) { color = '#32c682'; } + var arrows = ''; + return arrows; + }; + // Notiflix: Indicator SVG arrows off + + // Notiflix: Indicator SVG dots on + var notiflixIndicatorSvgDots = function (width, color) { + if (!width) { width = '60px'; } + if (!color) { color = '#32c682'; } + var dots = ' '; + return dots; + }; + // Notiflix: Indicator SVG dots off + + // Notiflix: Indicator SVG pulse on + var notiflixIndicatorSvgPulse = function (width, color) { + if (!width) { width = '60px'; } + if (!color) { color = '#32c682'; } + var pulse = ''; + return pulse; + }; + // Notiflix: Indicator SVG pulse off + + // Notiflix: Indicator SVG notiflix on + var notiflixIndicatorSvgNotiflix = function (width, white, green) { + if (!width) { width = '60px'; } + if (!white) { white = '#f8f8f8'; } + if (!green) { green = '#32c682'; } + var notiflixIcon = ''; + return notiflixIcon; + }; + // Notiflix: Indicator SVG notiflix off + + + /* + * 侧边滑出弹层插件 mSlider.js + * DH (https://denghao.me) + * 2018-07 + */ + // (function(b, c) { + // function a(d) { + // this.opts = { + // "direction": d.direction || "left", + // "distance": d.distance || "60%", + // "dom": this.Q(d.dom), + // "time": d.time || "", + // "maskClose": (d.maskClose + "").toString() !== "false" ? true : false, + // "callback": d.callback || "" + // }; + // this.rnd = this.rnd(); + // this.dom = this.opts.dom[0]; + // this.wrap = ""; + // this.inner = ""; + // this.mask = ""; + // this.init() + // } + // a.prototype = { + // Q: function(d) { + // return document.querySelectorAll(d) + // }, + // isMobile: function() { + // return navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i) ? true : false + // }, + // addEvent: function(f, e, d) { + // if (f.attachEvent) { + // f.attachEvent("on" + e, d) + // } else { + // f.addEventListener(e, d, false) + // } + // }, + // rnd: function() { + // return Math.random().toString(36).substr(2, 6) + // }, + // init: function() { + // var g = this; + // if (!g.dom) { + // console.log("未正确绑定弹窗容器"); + // return + // } + // var d = document.createElement("div"); + // var e = document.createElement("div"); + // var f = document.createElement("div"); + // d.setAttribute("class", "mSlider-main ms-" + g.rnd); + // e.setAttribute("class", "mSlider-inner"); + // f.setAttribute("class", "mSlider-mask"); + // g.Q("body")[0].appendChild(d); + // g.Q(".ms-" + g.rnd)[0].appendChild(e); + // g.Q(".ms-" + g.rnd)[0].appendChild(f); + // g.wrap = g.Q(".ms-" + g.rnd)[0]; + // g.inner = g.Q(".ms-" + g.rnd + " .mSlider-inner")[0]; + // g.mask = g.Q(".ms-" + g.rnd + " .mSlider-mask")[0]; + // g.inner.appendChild(g.dom); + // switch (g.opts.direction) { + // case "top": + // g.top = "0"; + // g.left = "0"; + // g.width = "100%"; + // g.height = g.opts.distance; + // g.translate = "0,-100%,0"; + // break; + // case "bottom": + // g.bottom = "0"; + // g.left = "0"; + // g.width = "100%"; + // g.height = g.opts.distance; + // g.translate = "0,100%,0"; + // break; + // case "right": + // g.top = "0"; + // g.right = "0"; + // g.width = g.opts.distance; + // g.height = document.documentElement.clientHeight + "px"; + // g.translate = "100%,0,0"; + // break; + // default: + // g.top = "0"; + // g.left = "0"; + // g.width = g.opts.distance; + // g.height = document.documentElement.clientHeight + "px"; + // g.translate = "-100%,0,0" + // } + // g.wrap.style.display = "none"; + // g.wrap.style.position = "fixed"; + // g.wrap.style.top = "0"; + // g.wrap.style.left = "0"; + // g.wrap.style.width = "100%"; + // g.wrap.style.height = "100%"; + // g.wrap.style.zIndex = 99; + // g.inner.style.position = "absolute"; + // g.inner.style.top = g.top; + // g.inner.style.bottom = g.bottom; + // g.inner.style.left = g.left; + // g.inner.style.right = g.right; + // g.inner.style.width = g.width; + // g.inner.style.height = g.height; + // g.inner.style.backgroundColor = "#fff"; + // g.inner.style.transform = "translate3d(" + g.translate + ")"; + // g.inner.style.webkitTransition = "all .2s ease-out"; + // g.inner.style.transition = "all .2s ease-out"; + // g.inner.style.zIndex = 100; + // g.mask.style.width = "100%"; + // g.mask.style.height = "100%"; + // g.mask.style.opacity = "0"; + // g.mask.style.backgroundColor = "black"; + // g.mask.style.zIndex = "98"; + // g.mask.style.webkitTransition = "all .2s ease-out"; + // g.mask.style.transition = "all .2s ease-out"; + // g.mask.style.webkitBackfaceVisibility = "hidden"; + // g.events() + // }, + // open: function() { + // var d = this; + // d.wrap.style.display = "block"; + + // setTimeout(function() { + // d.inner.style.transform = "translate3d(0,0,0)"; + // d.inner.style.webkitTransform = "translate3d(0,0,0)"; + // d.mask.style.opacity = 0.5 + // }, 30); + // if (d.opts.time) { + // d.timer = setTimeout(function() { + // d.close() + // }, d.opts.time) + // } + // }, + // close: function() { + // var d = this; + // d.timer && clearTimeout(d.timer); + // d.inner.style.webkitTransform = "translate3d(" + d.translate + ")"; + // d.inner.style.transform = "translate3d(" + d.translate + ")"; + // d.mask.style.opacity = 0; + // setTimeout(function() { + // d.wrap.style.display = "none"; + // d.timer = null; + // d.opts.callback && d.opts.callback() + // }, 300) + // }, + // events: function() { + // var d = this; + // d.addEvent(d.mask, "touchmove", function(f) { + // f.preventDefault() + // }); + // d.addEvent(d.mask, (d.isMobile() ? "touchend" : "click"), function(f) { + // if (d.opts.maskClose) { + // d.close() + // } + // }) + // } + // }; + // b.mSlider = a + // })(window); + + exports(MOD_NAME,pearOper); +}) + diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/menu.js b/demo/webman/backend/plugin/admin/public/component/pear/module/menu.js new file mode 100644 index 0000000000000000000000000000000000000000..eb5d7d964996606ea60a158d5f212405cddbec60 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/menu.js @@ -0,0 +1,571 @@ +layui.define(['table', 'jquery', 'element'], function (exports) { + "use strict"; + + var MOD_NAME = 'menu', + $ = layui.jquery, + element = layui.element; + + var pearMenu = function (opt) { + this.option = opt; + }; + + pearMenu.prototype.render = function (opt) { + + var option = { + elem: opt.elem, + async: opt.async, + parseData: opt.parseData, + url: opt.url, + method: opt.method ? opt.method : "GET", + defaultOpen: opt.defaultOpen, + defaultSelect: opt.defaultSelect, + control: opt.control, + controlWidth: opt.controlWidth ? opt.controlWidth : "auto", + defaultMenu: opt.defaultMenu, + accordion: opt.accordion, + height: opt.height, + theme: opt.theme, + data: opt.data ? opt.data : [], + change: opt.change ? opt.change : function () { }, + done: opt.done ? opt.done : function () { } + } + var tempDone = option.done; + option.done = function(){ + if (option.control) { + rationalizeHeaderControlWidthAuto(option); + } + tempDone(); + } + + if (option.async) { + if (option.method === "GET") { + getData(option.url).then(function (data) { + option.data = data.data; //变更 + renderMenu(option); + }); + } else { + postData(option.url).then(function (data) { + option.data = data.data; //变更 + renderMenu(option); + }); + } + } else { + // 延时返回,和 javascript 执行时序关联 + window.setTimeout(function () { renderMenu(option); }, 500); + } + + // 处理高度 + $("#" + opt.elem).height(option.height) + + setTimeout(function () { + $("#" + opt.control + " .control").on("mousewheel DOMMouseScroll", function (event) { + + var delta = (event.originalEvent.wheelDelta && (event.originalEvent.wheelDelta > 0 ? 1 : -1)) || // chrome & ie + (event.originalEvent.detail && (event.originalEvent.detail > 0 ? -1 : 1)); // firefox + + if (delta > 0) { + for (var num = 1; num < 20; num++) { + setTimeout(function () { + if ($("#" + opt.control + " .control ul").css('left').replace("px", "") < 0) { + $("#" + opt.control + " .control ul").css("left", "+=2px"); + } + }, 10) + } + } else if (delta < 0) { + if (((Number)($("#" + opt.control + " .control ul").css("left").replace("px", "")) + ($("#" + opt.control + " .control ul").width() - $("#" + opt.control + " .control").width())) > 0) { + for (var num = 1; num < 20; num++) { + setTimeout(function () { + $("#" + opt.control + " .control ul").css("left", "-=2px"); + }, 10) + } + } + } + }); + }, 1000) + + return new pearMenu(option); + } + + pearMenu.prototype.click = function (clickEvent) { + var _this = this; + $("body").on("click", "#" + _this.option.elem + " .site-demo-active", function () { + var dom = $(this); + var data = { + menuId: dom.attr("menu-id"), + menuTitle: dom.attr("menu-title"), + menuPath: dom.attr("menu-title"), + menuIcon: dom.attr("menu-icon"), + menuUrl: dom.attr("menu-url"), + openType: dom.attr("open-type") + }; + var doms = hash(dom); + if (doms != null) { + if (doms.text() != '') { + data['menuPath'] = doms.find("span").text() + " / " + data['menuPath']; + } + } + if (doms != null) { + var domss = hash(doms); + if (domss != null) { + if (domss.text() != '') { + data['menuPath'] = domss.find("span").text() + " / " + data['menuPath']; + } + } + } + if (domss != null) { + var domsss = hash(domss); + if (domsss != null) { + if (domsss.text() != '') { + data['menuPath'] = domsss.find("span").text() + " / " + data['menuPath']; + } + } + } + if ($("#" + _this.option.elem).is(".pear-nav-mini")) { + if (_this.option.accordion) { + activeMenus = $(this).parent().parent().parent().children("a"); + } else { + activeMenus.push($(this).parent().parent().parent().children("a")); + } + } + clickEvent(dom, data); + }) + } + + function hash(dom) { + var d = dom.parent().parent().prev(); + if (d.prop("tagName") === "UL") { + return null; + } + return d; + } + + pearMenu.prototype.skin = function (skin) { + var menu = $(".pear-nav-tree[lay-filter='" + this.option.elem + "']").parent(); + menu.removeClass("dark-theme"); + menu.removeClass("light-theme"); + menu.addClass(skin); + } + + pearMenu.prototype.selectItem = function (pearId) { + if (this.option.control != false) { + $("#" + this.option.elem + " a[menu-id='" + pearId + "']").parents(".layui-side-scroll ").find("ul").css({ + display: "none" + }); + $("#" + this.option.elem + " a[menu-id='" + pearId + "']").parents(".layui-side-scroll ").find(".layui-this").removeClass( + "layui-this"); + $("#" + this.option.elem + " a[menu-id='" + pearId + "']").parents("ul").css({ + display: "block" + }); + var controlId = $("#" + this.option.elem + " a[menu-id='" + pearId + "']").parents("ul").attr("pear-id"); + if (controlId != undefined) { + $("#" + this.option.control).find(".layui-this").removeClass("layui-this"); + $("#" + this.option.control).find("[pear-id='" + controlId + "']").addClass("layui-this"); + } + } + + $("#" + this.option.elem + " a[menu-id='" + pearId + "']").parents(".pear-nav-tree").find(".layui-this").removeClass( + "layui-this"); + if (!$("#" + this.option.elem).is(".pear-nav-mini")) { + var openEle = null; + var openEleHeight = 0; + $($("#" + this.option.elem + " a[menu-id='" + pearId + "']").parents('.layui-nav-child').get().reverse()).each(function () { + if (!$(this).parent().is('.layui-nav-itemed')) { + if (openEleHeight == 0) { + openEle = $(this); + } else { + $(this).parent().addClass('layui-nav-itemed'); + $(this).css({ + height: 'auto', + }); + } + openEleHeight += $(this).children("dd").length * 48; + } + }); + if (this.option.accordion) { + if (openEleHeight > 0) { + var currentDom = openEle.parent().siblings('.layui-nav-itemed').children(".layui-nav-child"); + currentDom.animate({ + height: "0px" + }, 240, function () { + currentDom.css({ + height: "auto" + }); + $(this).parent().removeClass("layui-nav-itemed"); + $(this).find('.layui-nav-itemed').removeClass("layui-nav-itemed"); + }); + } + } + if (openEleHeight > 0) { + openEle.parent().addClass("layui-nav-itemed"); + openEle.height(0); + openEle.animate({ + height: openEleHeight + "px" + }, 240, function () { + $(this).css({ height: 'auto' }); + }); + } + } + $("#" + this.option.elem + " a[menu-id='" + pearId + "']").parent().addClass("layui-this"); + } + + var activeMenus; + pearMenu.prototype.collapse = function (time) { + var elem = this.option.elem; + var config = this.option; + if ($("#" + this.option.elem).is(".pear-nav-mini")) { + $.each(activeMenus, function (i, item) { + $("#" + elem + " a[menu-id='" + $(this).attr("menu-id") + "']").parent().addClass("layui-nav-itemed"); + }) + $("#" + this.option.elem).removeClass("pear-nav-mini"); + $("#" + this.option.elem).animate({ + width: "220px" + }, 180); + isHoverMenu(false, config); + var that = this; + $("#" + this.option.elem) + .promise() + .done(function () { + if (that.option.control) { + rationalizeHeaderControlWidth(that.option); + } + }) + } else { + activeMenus = $("#" + this.option.elem).find(".layui-nav-itemed>a"); + $("#" + this.option.elem).find(".layui-nav-itemed").removeClass("layui-nav-itemed"); + $("#" + this.option.elem).addClass("pear-nav-mini"); + $("#" + this.option.elem).animate({ + width: "60px" + }, 400); + var that = this; + $("#" + this.option.elem) + .promise() + .done(function () { + isHoverMenu(true, config); + if (that.option.control) { + rationalizeHeaderControlWidth(that.option); + } + }) + } + } + + function getData(url) { + var defer = $.Deferred(); + var symbol = url.indexOf('?') !== -1 ? '&' : '?'; + $.get(url + symbol + "fresh=" + Math.random(), function (result) { + defer.resolve(result) + }); + return defer.promise(); + } + + function postData(url) { + var defer = $.Deferred(); + var symbol = url.indexOf('?') !== -1 ? '&' : '?'; + $.post(url + symbol + "fresh=" + Math.random(), function (result) { + defer.resolve(result) + }, "json"); + return defer.promise(); + } + + function renderMenu(option) { + if (option.parseData != false) { + option.parseData(option.data); + } + if (option.data.length > 0) { + if (option.control != false) { + createMenuAndControl(option); + } else { + createMenu(option); + } + } + element.init(); + downShow(option); + option.done(); + } + + function createMenu(option) { + var menuHtml = '
                                                                                            ' + $.each(option.data, function (i, item) { + var content = '
                                                                                          • '; + if (i == option.defaultOpen) { + content = '
                                                                                          • '; + } + var href = "javascript:;"; + var target = ""; + var className = "site-demo-active" + if (item.openType == "_blank" && item.type == 1) { + href = item.href; + target = "target='_blank'"; + className = ""; + } + if (item.type == 0) { + // 创 建 目 录 结 构 + content += '' + item.title + + ''; + } else if (item.type == 1) { + content += '' + item.title + ''; + } + // 调 用 递 归 方 法 加 载 无 限 层 级 的 子 菜 单 + content += loadchild(item); + // 结 束 一 个 根 菜 单 项 + content += '
                                                                                          • '; + menuHtml += content; + }); + // 结 束 菜 单 结 构 的 初 始 化 + menuHtml += "
                                                                                          "; + // 将 菜 单 拼 接 到 初 始 化 容 器 中 + $("#" + option.elem).html(menuHtml); + } + + function createMenuAndControl(option) { + var control = '
                                                                                            '; + var controlPe = '
                                                                                              '; + // 声 明 头 部 + var menu = '
                                                                                              ' + // 开 启 同 步 操 作 + var index = 0; + var controlItemPe = '
                                                                                              '; + $.each(option.data, function (i, item) { + var menuItem = ''; + var controlItem = ''; + if (i === option.defaultMenu) { + controlItem = '
                                                                                            • ' + item.title + '
                                                                                            • '; + menuItem = '
                                                                                                '; + + controlPe += '
                                                                                              • ' + item.title + ''; + + controlItemPe += '
                                                                                                ' + item.title + '
                                                                                                '; + } else { + + controlItem = '
                                                                                              • ' + item.title + '
                                                                                              • '; + + menuItem = ''; + control += controlItem; + }) + controlItemPe += "
                                                                                            " + controlPe += controlItemPe; + $("#" + option.control).html(control + "
                                                                                          "); + $("#" + option.control).append(controlPe); + $("#" + option.elem).html(menu); + $("#" + option.control + " .pear-nav-control").on("click", "[pear-id]", function () { + $("#" + option.elem).find(".pear-nav-tree").css({ + display: 'none' + }); + $("#" + option.elem).find(".pear-nav-tree[pear-id='" + $(this).attr("pear-id") + "']").css({ + display: 'block' + }); + $("#" + option.control).find(".pe-title").html($(this).attr("pear-title")); + $("#" + option.control).find("") + option.change($(this).attr("pear-id"), $(this).attr("pear-title"), $(this).attr("pear-href")) + }) + } + + /** 加载子菜单 (递归)*/ + function loadchild(obj) { + // 判 单 是 否 是 菜 单, 如 果 是 菜 单 直 接 返 回 + if (obj.type == 1) { + return ""; + } + // 创 建 子 菜 单 结 构 + var content = '
                                                                                          '; + // 如 果 嵌 套 不 等 于 空 + if (obj.children != null && obj.children.length > 0) { + // 遍 历 子 项 目 + $.each(obj.children, function (i, note) { + // 创 建 子 项 结 构 + content += '
                                                                                          '; + var href = "javascript:;"; + var target = ""; + var className = "site-demo-active"; + if (note.openType == "_blank" && note.type == 1) { + href = note.href; + target = "target='_blank'"; + className = ""; + } + // 判 断 子 项 类 型 + if (note.type == 0) { + // 创 建 目 录 结 构 + content += '' + note.title + ''; + } else if (note.type == 1) { + // 创 建 菜 单 结 构 + content += '' + note.title + ''; + } + // 加 载 子 项 目 录 + content += loadchild(note); + // 结 束 当 前 子 菜 单 + content += '
                                                                                          '; + }); + // 封 装 + } else { + content += '
                                                                                          目录为空
                                                                                          '; + } + content += '
                                                                                          '; + return content; + } + + function downShow(option) { + $("body #" + option.elem).on("click", "a[menu-type='0']", function () { + if (!$("#" + option.elem).is(".pear-nav-mini")) { + var superEle = $(this).parent(); + var ele = $(this).next('.layui-nav-child'); + var heights = ele.children("dd").length * 48; + + if ($(this).parent().is(".layui-nav-itemed")) { + if (option.accordion) { + var currentDom = $(this).parent().siblings('.layui-nav-itemed').children('.layui-nav-child'); + currentDom.animate({ + height: '0px' + }, 240, function () { + currentDom.css({ + height: "auto", + }); + $(this).parent().removeClass("layui-nav-itemed"); + $(this).find('.layui-nav-itemed').removeClass("layui-nav-itemed"); + }); + } + ele.height(0); + ele.animate({ + height: heights + "px" + }, 240, function () { + ele.css({ + height: "auto" + }); + }); + } else { + $(this).parent().addClass("layui-nav-itemed"); + ele.animate({ + height: "0px" + }, 240, function () { + ele.css({ + height: "auto" + }); + $(this).parent().removeClass("layui-nav-itemed"); + }); + } + } + }) + } + + /** 二 级 悬 浮 菜 单*/ + function isHoverMenu(b, option) { + if (b) { + var navItem = "#" + option.elem + ".pear-nav-mini .layui-nav-item"; + var navChildDl = navItem + " .layui-nav-child>dl"; + var navChildDd = navItem + " .layui-nav-child>dd"; + + $(navItem + "," + navChildDd).mouseenter(function () { + var _this = $(this); + _this.siblings().find(".layui-nav-child") + .removeClass("layui-nav-hover").css({ + left: 0, + top: 0 + }); + _this.children(".layui-nav-child").addClass("layui-nav-hover"); + var height = $(window).height(); + var topLength = _this.offset().top; + var thisHeight = _this.children(".layui-nav-child").height(); + if ((thisHeight + topLength) > height) { + topLength = height - thisHeight - 10; + } + var left = _this.offset().left + 60; + if (!_this.hasClass("layui-nav-item")) { + left = _this.offset().left + _this.width(); + } + _this.children(".layui-nav-child").offset({ + top: topLength, + left: left + }); + }); + + $(navItem + "," + navChildDl).mouseleave(function () { + var _this = $(this); + _this.closest('.layui-nav-item') + .find(".layui-nav-child") + .removeClass("layui-nav-hover") + .css({ + left: 0, + top: 0 + }); + }); + + } else { + $("#" + option.elem + " .layui-nav-item").off('mouseenter').unbind('mouseleave'); + $("#" + option.elem + " dd").off('mouseenter').unbind('mouseleave'); + } + } + + function rationalizeHeaderControlWidth(option) { + var $headerControl = $("#" + option.control); + var $nextEl = $headerControl.next(); + var rationalizeWidth; + if ($nextEl.length) { + rationalizeWidth = $nextEl.position().left - $headerControl.position().left; + } else { + rationalizeWidth = $headerControl.parent().innerWidth() - $headerControl.position().left; + } + + if (option.controlWidth && rationalizeWidth >= option.controlWidth) { + rationalizeWidth = option.controlWidth; + } + $("#" + option.control + " .control").css({ "width": rationalizeWidth, "transition": "width .15s" }); + } + + function rationalizeHeaderControlWidthAuto(option){ + $(window).on('resize', function () { + rationalizeHeaderControlWidth(option); + }) + + $(document).ready(function () { + rationalizeHeaderControlWidth(option); + }); + } + + exports(MOD_NAME, new pearMenu()); +}) diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/message.js b/demo/webman/backend/plugin/admin/public/component/pear/module/message.js new file mode 100644 index 0000000000000000000000000000000000000000..48374cb4131a72da40c225207977d13000c37e8c --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/message.js @@ -0,0 +1,132 @@ +layui.define(['table', 'jquery', 'element'], function (exports) { + "use strict"; + + var MOD_NAME = 'message', + $ = layui.jquery, + element = layui.element; + + var message = function (opt) { + this.option = opt; + }; + + message.prototype.render = function (opt) { + //默认配置值 + var option = { + elem: opt.elem, + url: opt.url ? opt.url : false, + height: opt.height, + data: opt.data + } + if (option.url != false) { + option.data = getData(option.url); + var notice = createHtml(option); + $(option.elem).html(notice); + var targetNode = document.querySelector(option.elem + ' .pear-notice') + var mutationObserver = new MutationObserver(function (mutationsList, observer) { + if (getComputedStyle(targetNode).display !== 'none') { + var rect = targetNode.getBoundingClientRect(); + //是否超出右侧屏幕 + if (rect.right > $(window).width()) { + var elemRight = document.querySelector(option.elem).getBoundingClientRect().right; + var offsetRight = 20; + targetNode.style.right = elemRight - $(window).width() + offsetRight + 'px'; + targetNode.style.left = 'unset'; + } + } + }); + mutationObserver.observe(targetNode, { + attributes: true, + childList: false, + subtree: false, + attributeOldValue: false, + attributeFilter: ['class'] + }); + } + setTimeout(function () { + element.init(); + $(opt.elem + " li").click(function (e) { + $(this).siblings().removeClass('pear-this'); + $(this).addClass('pear-this'); + }) + }, 300); + return new message(option); + } + + message.prototype.click = function (callback) { + $("*[notice-id]").click(function (event) { + event.preventDefault(); + var id = $(this).attr("notice-id"); + var title = $(this).attr("notice-title"); + var context = $(this).attr("notice-context"); + var form = $(this).attr("notice-form"); + callback(id, title, context, form); + }) + } + + /** 刷 新 消 息 */ + message.prototype.reload = function () { + + } + + /** 同 步 请 求 获 取 数 据 */ + function getData(url) { + $.ajaxSettings.async = false; + var data = null; + $.get(url, function (result) { + data = result; + }); + $.ajaxSettings.async = true; + return data; + } + + function createHtml(option) { + + var count = 0; + var noticeTitle = '
                                                                                            '; + var noticeContent = '
                                                                                            '; + + + // 根据 data 便利数据 + $.each(option.data, function (i, item) { + + if (i === 0) { + noticeTitle += '
                                                                                          • ' + item.title + '
                                                                                          • '; + noticeContent += '
                                                                                            '; + } else { + noticeTitle += '
                                                                                          • ' + item.title + '
                                                                                          • '; + noticeContent += '
                                                                                            '; + } + + $.each(item.children, function (i, note) { + noticeContent += '
                                                                                            ' ; + + if (note.avatar) + noticeContent +=''; + + noticeContent +='
                                                                                            ' + note.title + '
                                                                                            ' + + '
                                                                                            ' + note.time + '
                                                                                            ' + + '
                                                                                            '; + }) + + // 空内容 + if(item.children.length==0){ + noticeContent +='

                                                                                            暂无数据

                                                                                            '; + } + noticeContent += '
                                                                                            '; + }) + + var notice = '
                                                                                          • ' + + '
                                                                                          • ' + + '
                                                                                            '; + + noticeTitle += '
                                                                                          '; + noticeContent += '
                                                                                          '; + notice += noticeTitle; + notice += noticeContent; + notice += '
                                                                                          '; + return notice; + } + + exports(MOD_NAME, new message()); +}) diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/notice.js b/demo/webman/backend/plugin/admin/public/component/pear/module/notice.js new file mode 100644 index 0000000000000000000000000000000000000000..4ea67ec8b3e784abd5b28d103042bd3499bdaf2d --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/notice.js @@ -0,0 +1,489 @@ + +(function(define) { + define(['jquery'], function($) { + return (function() { + var $container; + var listener; + var toastId = 0; + var toastType = { + error: 'error', + info: 'info', + success: 'success', + warning: 'warning' + }; + + var cssStyle = $( + '' + ); + $("body").append(cssStyle); + + var toastr = { + clear: clear, + remove: remove, + error: error, + getContainer: getContainer, + info: info, + options: {}, + subscribe: subscribe, + success: success, + version: '2.1.4', + warning: warning + }; + + var previousToast; + + return toastr; + + function error(message, title, optionsOverride) { + return notify({ + type: toastType.error, + iconClass: getOptions().iconClasses.error, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function getContainer(options, create) { + if (!options) { + options = getOptions(); + } + $container = $('#' + options.containerId); + if ($container.length) { + return $container; + } + if (create) { + $container = createContainer(options); + } + return $container; + } + + function info(message, title, optionsOverride) { + return notify({ + type: toastType.info, + iconClass: getOptions().iconClasses.info, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function subscribe(callback) { + listener = callback; + } + + function success(message, title, optionsOverride) { + return notify({ + type: toastType.success, + iconClass: getOptions().iconClasses.success, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function warning(message, title, optionsOverride) { + return notify({ + type: toastType.warning, + iconClass: getOptions().iconClasses.warning, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function clear($toastElement, clearOptions) { + var options = getOptions(); + if (!$container) { + getContainer(options); + } + if (!clearToast($toastElement, options, clearOptions)) { + clearContainer(options); + } + } + + function remove($toastElement) { + var options = getOptions(); + if (!$container) { + getContainer(options); + } + if ($toastElement && $(':focus', $toastElement).length === 0) { + removeToast($toastElement); + return; + } + if ($container.children().length) { + $container.remove(); + } + } + + // internal functions + + function clearContainer(options) { + var toastsToClear = $container.children(); + for (var i = toastsToClear.length - 1; i >= 0; i--) { + clearToast($(toastsToClear[i]), options); + } + } + + function clearToast($toastElement, options, clearOptions) { + var force = clearOptions && clearOptions.force ? clearOptions.force : false; + if ($toastElement && (force || $(':focus', $toastElement).length === 0)) { + $toastElement[options.hideMethod]({ + duration: options.hideDuration, + easing: options.hideEasing, + complete: function() { + removeToast($toastElement); + } + }); + return true; + } + return false; + } + + function createContainer(options) { + $container = $('
                                                                                          ') + .attr('id', options.containerId) + .addClass(options.positionClass); + + $container.appendTo($(options.target)); + return $container; + } + + function getDefaults() { + return { + tapToDismiss: true, + toastClass: 'toast', + containerId: 'toast-container', + debug: false, + + showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery + showDuration: 300, + showEasing: 'swing', //swing and linear are built into jQuery + onShown: undefined, + hideMethod: 'fadeOut', + hideDuration: 1000, + hideEasing: 'swing', + onHidden: undefined, + closeMethod: false, + closeDuration: false, + closeEasing: false, + closeOnHover: true, + + extendedTimeOut: 1000, + iconClasses: { + error: 'toast-error', + info: 'toast-info', + success: 'toast-success', + warning: 'toast-warning' + }, + iconClass: 'toast-info', + positionClass: 'toast-top-right', + timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky + titleClass: 'toast-title', + messageClass: 'toast-message', + escapeHtml: false, + target: 'body', + closeHtml: '', + closeClass: 'toast-close-button', + newestOnTop: true, + preventDuplicates: false, + progressBar: false, + progressClass: 'toast-progress', + rtl: false + }; + } + + function publish(args) { + if (!listener) { + return; + } + listener(args); + } + + function notify(map) { + var options = getOptions(); + var iconClass = map.iconClass || options.iconClass; + + if (typeof(map.optionsOverride) !== 'undefined') { + options = $.extend(options, map.optionsOverride); + iconClass = map.optionsOverride.iconClass || iconClass; + } + + if (shouldExit(options, map)) { + return; + } + + toastId++; + + $container = getContainer(options, true); + + var intervalId = null; + var $toastElement = $('
                                                                                          '); + var $titleElement = $('
                                                                                          '); + var $messageElement = $('
                                                                                          '); + var $progressElement = $('
                                                                                          '); + var $closeElement = $(options.closeHtml); + var progressBar = { + intervalId: null, + hideEta: null, + maxHideTime: null + }; + var response = { + toastId: toastId, + state: 'visible', + startTime: new Date(), + options: options, + map: map + }; + + personalizeToast(); + + displayToast(); + + handleEvents(); + + publish(response); + + if (options.debug && console) { + console.log(response); + } + + return $toastElement; + + function escapeHtml(source) { + if (source == null) { + source = ''; + } + + return source + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); + } + + function personalizeToast() { + setIcon(); + setTitle(); + setMessage(); + setCloseButton(); + setProgressBar(); + setRTL(); + setSequence(); + setAria(); + } + + function setAria() { + var ariaValue = ''; + switch (map.iconClass) { + case 'toast-success': + case 'toast-info': + ariaValue = 'polite'; + break; + default: + ariaValue = 'assertive'; + } + $toastElement.attr('aria-live', ariaValue); + } + + function handleEvents() { + if (options.closeOnHover) { + $toastElement.hover(stickAround, delayedHideToast); + } + + if (!options.onclick && options.tapToDismiss) { + $toastElement.click(hideToast); + } + + if (options.closeButton && $closeElement) { + $closeElement.click(function(event) { + if (event.stopPropagation) { + event.stopPropagation(); + } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) { + event.cancelBubble = true; + } + + if (options.onCloseClick) { + options.onCloseClick(event); + } + + hideToast(true); + }); + } + + if (options.onclick) { + $toastElement.click(function(event) { + options.onclick(event); + hideToast(); + }); + } + } + + function displayToast() { + $toastElement.hide(); + + $toastElement[options.showMethod]({ + duration: options.showDuration, + easing: options.showEasing, + complete: options.onShown + }); + + if (options.timeOut > 0) { + intervalId = setTimeout(hideToast, options.timeOut); + progressBar.maxHideTime = parseFloat(options.timeOut); + progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; + if (options.progressBar) { + progressBar.intervalId = setInterval(updateProgress, 10); + } + } + } + + function setIcon() { + if (map.iconClass) { + $toastElement.addClass(options.toastClass).addClass(iconClass); + } + } + + function setSequence() { + if (options.newestOnTop) { + $container.prepend($toastElement); + } else { + $container.append($toastElement); + } + } + + function setTitle() { + if (map.title) { + var suffix = map.title; + if (options.escapeHtml) { + suffix = escapeHtml(map.title); + } + $titleElement.append(suffix).addClass(options.titleClass); + $toastElement.append($titleElement); + } + } + + function setMessage() { + if (map.message) { + var suffix = map.message; + if (options.escapeHtml) { + suffix = escapeHtml(map.message); + } + $messageElement.append(suffix).addClass(options.messageClass); + $toastElement.append($messageElement); + } + } + + function setCloseButton() { + if (options.closeButton) { + $closeElement.addClass(options.closeClass).attr('role', 'button'); + $toastElement.prepend($closeElement); + } + } + + function setProgressBar() { + if (options.progressBar) { + $progressElement.addClass(options.progressClass); + $toastElement.prepend($progressElement); + } + } + + function setRTL() { + if (options.rtl) { + $toastElement.addClass('rtl'); + } + } + + function shouldExit(options, map) { + if (options.preventDuplicates) { + if (map.message === previousToast) { + return true; + } else { + previousToast = map.message; + } + } + return false; + } + + function hideToast(override) { + var method = override && options.closeMethod !== false ? options.closeMethod : options.hideMethod; + var duration = override && options.closeDuration !== false ? + options.closeDuration : options.hideDuration; + var easing = override && options.closeEasing !== false ? options.closeEasing : options.hideEasing; + if ($(':focus', $toastElement).length && !override) { + return; + } + clearTimeout(progressBar.intervalId); + return $toastElement[method]({ + duration: duration, + easing: easing, + complete: function() { + removeToast($toastElement); + clearTimeout(intervalId); + if (options.onHidden && response.state !== 'hidden') { + options.onHidden(); + } + response.state = 'hidden'; + response.endTime = new Date(); + publish(response); + } + }); + } + + function delayedHideToast() { + if (options.timeOut > 0 || options.extendedTimeOut > 0) { + intervalId = setTimeout(hideToast, options.extendedTimeOut); + progressBar.maxHideTime = parseFloat(options.extendedTimeOut); + progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; + } + } + + function stickAround() { + clearTimeout(intervalId); + progressBar.hideEta = 0; + $toastElement.stop(true, true)[options.showMethod]({ + duration: options.showDuration, + easing: options.showEasing + }); + } + + function updateProgress() { + var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100; + $progressElement.width(percentage + '%'); + } + } + + function getOptions() { + return $.extend({}, getDefaults(), toastr.options); + } + + function removeToast($toastElement) { + if (!$container) { + $container = getContainer(); + } + if ($toastElement.is(':visible')) { + return; + } + $toastElement.remove(); + $toastElement = null; + if ($container.children().length === 0) { + $container.remove(); + previousToast = undefined; + } + } + + })(); + }); +}(typeof define === 'function' && define.amd ? define : function(deps, factory) { + if (typeof module !== 'undefined' && module.exports) { //Node + module.exports = factory(require('jquery')); + } else if (window.layui && layui.define) { + layui.define('jquery', function(exports) { //layui加载 + exports('toastr', factory(layui.jquery)); + exports('notice', factory(layui.jquery)); + }); + } else { + window.toastr = factory(window.jQuery); + } +})); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/nprogress.js b/demo/webman/backend/plugin/admin/public/component/pear/module/nprogress.js new file mode 100644 index 0000000000000000000000000000000000000000..882039a763a3087e66f7bf2e9945fd84fc524e92 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/nprogress.js @@ -0,0 +1,503 @@ +/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress + * @license MIT */ + +;(function(root, factory) { + + if (typeof define === 'function' && define.amd) { + define(factory); + } else if (typeof exports === 'object') { + module.exports = factory(); + } else { + root.NProgress = factory(); + } + +})(this, function() { + var NProgress = {}; + + NProgress.version = '0.2.0'; + + var Settings = NProgress.settings = { + minimum: 0.08, + easing: 'linear', + positionUsing: '', + speed: 200, + trickle: true, + trickleSpeed: 200, + showSpinner: true, + barSelector: '[role="bar"]', + spinnerSelector: '[role="spinner"]', + parent: 'body', + template: '
                                                                                          ' + }; + + /** + * Updates configuration. + * + * NProgress.configure({ + * minimum: 0.1 + * }); + */ + NProgress.configure = function(options) { + var key, value; + for (key in options) { + value = options[key]; + if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value; + } + + return this; + }; + + /** + * Last number. + */ + + NProgress.status = null; + + /** + * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`. + * + * NProgress.set(0.4); + * NProgress.set(1.0); + */ + + NProgress.set = function(n) { + var started = NProgress.isStarted(); + + n = clamp(n, Settings.minimum, 1); + NProgress.status = (n === 1 ? null : n); + + var progress = NProgress.render(!started), + bar = progress.querySelector(Settings.barSelector), + speed = Settings.speed, + ease = Settings.easing; + + progress.offsetWidth; /* Repaint */ + + queue(function(next) { + // Set positionUsing if it hasn't already been set + if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS(); + + // Add transition + css(bar, barPositionCSS(n, speed, ease)); + + if (n === 1) { + // Fade out + css(progress, { + transition: 'none', + opacity: 1 + }); + progress.offsetWidth; /* Repaint */ + + setTimeout(function() { + css(progress, { + transition: 'all ' + speed + 'ms linear', + opacity: 0 + }); + setTimeout(function() { + NProgress.remove(); + next(); + }, speed); + }, speed); + } else { + setTimeout(next, speed); + } + }); + + return this; + }; + + NProgress.isStarted = function() { + return typeof NProgress.status === 'number'; + }; + + /** + * Shows the progress bar. + * This is the same as setting the status to 0%, except that it doesn't go backwards. + * + * NProgress.start(); + * + */ + NProgress.start = function() { + if (!NProgress.status) NProgress.set(0); + + var work = function() { + setTimeout(function() { + if (!NProgress.status) return; + NProgress.trickle(); + work(); + }, Settings.trickleSpeed); + }; + + if (Settings.trickle) work(); + + return this; + }; + + /** + * Hides the progress bar. + * This is the *sort of* the same as setting the status to 100%, with the + * difference being `done()` makes some placebo effect of some realistic motion. + * + * NProgress.done(); + * + * If `true` is passed, it will show the progress bar even if its hidden. + * + * NProgress.done(true); + */ + + NProgress.done = function(force) { + if (!force && !NProgress.status) return this; + + return NProgress.inc(0.3 + 0.5 * Math.random()).set(1); + }; + + /** + * Increments by a random amount. + */ + + NProgress.inc = function(amount) { + var n = NProgress.status; + + if (!n) { + return NProgress.start(); + } else if(n > 1) { + return; + } else { + if (typeof amount !== 'number') { + if (n >= 0 && n < 0.2) { amount = 0.1; } + else if (n >= 0.2 && n < 0.5) { amount = 0.04; } + else if (n >= 0.5 && n < 0.8) { amount = 0.02; } + else if (n >= 0.8 && n < 0.99) { amount = 0.005; } + else { amount = 0; } + } + + n = clamp(n + amount, 0, 0.994); + return NProgress.set(n); + } + }; + + NProgress.trickle = function() { + return NProgress.inc(); + }; + + /** + * Waits for all supplied jQuery promises and + * increases the progress as the promises resolve. + * + * @param $promise jQUery Promise + */ + (function() { + var initial = 0, current = 0; + + NProgress.promise = function($promise) { + if (!$promise || $promise.state() === "resolved") { + return this; + } + + if (current === 0) { + NProgress.start(); + } + + initial++; + current++; + + $promise.always(function() { + current--; + if (current === 0) { + initial = 0; + NProgress.done(); + } else { + NProgress.set((initial - current) / initial); + } + }); + + return this; + }; + + })(); + + /** + * (Internal) renders the progress bar markup based on the `template` + * setting. + */ + + NProgress.render = function(fromStart) { + if (NProgress.isRendered()) return document.getElementById('nprogress'); + + addClass(document.documentElement, 'nprogress-busy'); + + var progress = document.createElement('div'); + progress.id = 'nprogress'; + progress.innerHTML = Settings.template; + + + + var bar = progress.querySelector(Settings.barSelector), + perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0), + parent = isDOM(Settings.parent) + ? Settings.parent + : document.querySelector(Settings.parent), + spinner + + css(bar, { + transition: 'all 0 linear', + transform: 'translate3d(' + perc + '%,0,0)' + }); + + if (!Settings.showSpinner) { + spinner = progress.querySelector(Settings.spinnerSelector); + spinner && removeElement(spinner); + } + + if (parent != document.body) { + addClass(parent, 'nprogress-custom-parent'); + } + + parent.appendChild(progress); + return progress; + }; + + /** + * Removes the element. Opposite of render(). + */ + + NProgress.remove = function() { + removeClass(document.documentElement, 'nprogress-busy'); + var parent = isDOM(Settings.parent) + ? Settings.parent + : document.querySelector(Settings.parent) + removeClass(parent, 'nprogress-custom-parent') + var progress = document.getElementById('nprogress'); + progress && removeElement(progress); + }; + + /** + * Checks if the progress bar is rendered. + */ + + NProgress.isRendered = function() { + return !!document.getElementById('nprogress'); + }; + + /** + * Determine which positioning CSS rule to use. + */ + + NProgress.getPositioningCSS = function() { + // Sniff on document.body.style + var bodyStyle = document.body.style; + + // Sniff prefixes + var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' : + ('MozTransform' in bodyStyle) ? 'Moz' : + ('msTransform' in bodyStyle) ? 'ms' : + ('OTransform' in bodyStyle) ? 'O' : ''; + + if (vendorPrefix + 'Perspective' in bodyStyle) { + // Modern browsers with 3D support, e.g. Webkit, IE10 + return 'translate3d'; + } else if (vendorPrefix + 'Transform' in bodyStyle) { + // Browsers without 3D support, e.g. IE9 + return 'translate'; + } else { + // Browsers without translate() support, e.g. IE7-8 + return 'margin'; + } + }; + + /** + * Helpers + */ + + function isDOM (obj) { + if (typeof HTMLElement === 'object') { + return obj instanceof HTMLElement + } + return ( + obj && + typeof obj === 'object' && + obj.nodeType === 1 && + typeof obj.nodeName === 'string' + ) + } + + function clamp(n, min, max) { + if (n < min) return min; + if (n > max) return max; + return n; + } + + /** + * (Internal) converts a percentage (`0..1`) to a bar translateX + * percentage (`-100%..0%`). + */ + + function toBarPerc(n) { + return (-1 + n) * 100; + } + + + /** + * (Internal) returns the correct CSS for changing the bar's + * position given an n percentage, and speed and ease from Settings + */ + + function barPositionCSS(n, speed, ease) { + var barCSS; + + if (Settings.positionUsing === 'translate3d') { + barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' }; + } else if (Settings.positionUsing === 'translate') { + barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' }; + } else { + barCSS = { 'margin-left': toBarPerc(n)+'%' }; + } + + barCSS.transition = 'all '+speed+'ms '+ease; + + return barCSS; + } + + /** + * (Internal) Queues a function to be executed. + */ + + var queue = (function() { + var pending = []; + + function next() { + var fn = pending.shift(); + if (fn) { + fn(next); + } + } + + return function(fn) { + pending.push(fn); + if (pending.length == 1) next(); + }; + })(); + + /** + * (Internal) Applies css properties to an element, similar to the jQuery + * css method. + * + * While this helper does assist with vendor prefixed property names, it + * does not perform any manipulation of values prior to setting styles. + */ + + var css = (function() { + var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ], + cssProps = {}; + + function camelCase(string) { + return string.replace(/^-ms-/, 'ms-').replace(/-([\da-z])/gi, function(match, letter) { + return letter.toUpperCase(); + }); + } + + function getVendorProp(name) { + var style = document.body.style; + if (name in style) return name; + + var i = cssPrefixes.length, + capName = name.charAt(0).toUpperCase() + name.slice(1), + vendorName; + while (i--) { + vendorName = cssPrefixes[i] + capName; + if (vendorName in style) return vendorName; + } + + return name; + } + + function getStyleProp(name) { + name = camelCase(name); + return cssProps[name] || (cssProps[name] = getVendorProp(name)); + } + + function applyCss(element, prop, value) { + prop = getStyleProp(prop); + element.style[prop] = value; + } + + return function(element, properties) { + var args = arguments, + prop, + value; + + if (args.length == 2) { + for (prop in properties) { + value = properties[prop]; + if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value); + } + } else { + applyCss(element, args[1], args[2]); + } + } + })(); + + /** + * (Internal) Determines if an element or space separated list of class names contains a class name. + */ + + function hasClass(element, name) { + var list = typeof element == 'string' ? element : classList(element); + return list.indexOf(' ' + name + ' ') >= 0; + } + + /** + * (Internal) Adds a class to an element. + */ + + function addClass(element, name) { + var oldList = classList(element), + newList = oldList + name; + + if (hasClass(oldList, name)) return; + + // Trim the opening space. + element.className = newList.substring(1); + } + + /** + * (Internal) Removes a class from an element. + */ + + function removeClass(element, name) { + var oldList = classList(element), + newList; + + if (!hasClass(element, name)) return; + + // Replace the class name. + newList = oldList.replace(' ' + name + ' ', ' '); + + // Trim the opening and closing spaces. + element.className = newList.substring(1, newList.length - 1); + } + + /** + * (Internal) Gets a space separated list of the class names on the element. + * The list is wrapped with a single space on each end to facilitate finding + * matches within the list. + */ + + function classList(element) { + return (' ' + (element && element.className || '') + ' ').replace(/\s+/gi, ' '); + } + + /** + * (Internal) Removes an element from the DOM. + */ + + function removeElement(element) { + element && element.parentNode && element.parentNode.removeChild(element); + } + + return NProgress; +}); + +layui.define([], function(exports) { + exports('nprogress', NProgress); +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/popover/popover.js b/demo/webman/backend/plugin/admin/public/component/pear/module/popover/popover.js new file mode 100644 index 0000000000000000000000000000000000000000..7f2e9bd7dfd019eb88f5933890c2aab33a637d29 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/popover/popover.js @@ -0,0 +1,1219 @@ +/* + * webui popover plugin - v1.2.17 + * A lightWeight popover plugin with jquery ,enchance the popover plugin of bootstrap with some awesome new features. It works well with bootstrap ,but bootstrap is not necessary! + * https://github.com/sandywalker/webui-popover + * + * Made by Sandy Duan + * Under MIT License + */ + +layui.define(['jquery', 'element'], function(exports) { + var $=layui.$; + // Create the defaults once + var pluginName = 'webuiPopover'; + var pluginClass = 'webui-popover'; + var pluginType = 'webui.popover'; + var defaults = { + placement: 'auto', + container: null, + width: 'auto', + height: 'auto', + trigger: 'click', //hover,click,sticky,manual + style: '', + opacity:null, + selector: false, // jQuery selector, if a selector is provided, popover objects will be delegated to the specified. + delay: { + show: null, + hide: 300 + }, + async: { + type: 'GET', + before: null, //function(that, xhr, settings){} + success: null, //function(that, xhr){} + error: null //function(that, xhr, data){} + }, + cache: true, + multi: false, + arrow: true, + title: '', + content: '', + closeable: false, + padding: true, + url: '', + type: 'html', + direction: '', // ltr,rtl + animation: null, + template: '
                                                                                          ' + + '
                                                                                          ' + + '
                                                                                          ' + + '' + + '

                                                                                          ' + + '

                                                                                           

                                                                                          ' + + '
                                                                                          ' + + '
                                                                                          ', + backdrop: false, + dismissible: true, + onShow: null, + onHide: null, + abortXHR: true, + autoHide: false, + offsetTop: 0, + offsetLeft: 0, + iframeOptions: { + frameborder: '0', + allowtransparency: 'true', + id: '', + name: '', + scrolling: '', + onload: '', + height: '', + width: '' + }, + hideEmpty: false + }; + + var rtlClass = pluginClass + '-rtl'; + var _srcElements = []; + var backdrop = $('
                                                                                          '); + var _globalIdSeed = 0; + var _isBodyEventHandled = false; + var _offsetOut = -2000; // the value offset out of the screen + var $document = $(document); + + var toNumber = function (numeric, fallback) { + return isNaN(numeric) ? (fallback || 0) : Number(numeric); + }; + + var getPopFromElement = function ($element) { + return $element.data('plugin_' + pluginName); + }; + + var hideAllPop = function () { + var pop = null; + for (var i = 0; i < _srcElements.length; i++) { + pop = getPopFromElement(_srcElements[i]); + if (pop) { + pop.hide(true); + } + } + $document.trigger('hiddenAll.' + pluginType); + }; + + var hideOtherPops = function (currentPop) { + var pop = null; + for (var i = 0; i < _srcElements.length; i++) { + pop = getPopFromElement(_srcElements[i]); + if (pop && pop.id !== currentPop.id) { + pop.hide(true); + } + } + $document.trigger('hiddenAll.' + pluginType); + }; + + var isMobile = ('ontouchstart' in document.documentElement) && (/Mobi/.test(navigator.userAgent)); + + var pointerEventToXY = function (e) { + var out = { + x: 0, + y: 0 + }; + if (e.type === 'touchstart' || e.type === 'touchmove' || e.type === 'touchend' || e.type === 'touchcancel') { + var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; + out.x = touch.pageX; + out.y = touch.pageY; + } else if (e.type === 'mousedown' || e.type === 'mouseup' || e.type === 'click') { + out.x = e.pageX; + out.y = e.pageY; + } + return out; + }; + + + // The actual plugin constructor + function WebuiPopover(element, options) { + this.$element = $(element); + if (options) { + if ($.type(options.delay) === 'string' || $.type(options.delay) === 'number') { + options.delay = { + show: options.delay, + hide: options.delay + }; // bc break fix + } + } + this.options = $.extend({}, defaults, options); + this._defaults = defaults; + this._name = pluginName; + this._targetclick = false; + this.init(); + _srcElements.push(this.$element); + return this; + + } + + WebuiPopover.prototype = { + //init webui popover + init: function () { + if (this.$element[0] instanceof document.constructor && !this.options.selector) { + throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!'); + } + + if (this.getTrigger() !== 'manual') { + //init the event handlers + if (isMobile) { + this.$element.off('touchend', this.options.selector).on('touchend', this.options.selector, $.proxy(this.toggle, this)); + } else if (this.getTrigger() === 'click') { + this.$element.off('click', this.options.selector).on('click', this.options.selector, $.proxy(this.toggle, this)); + } else if (this.getTrigger() === 'hover') { + this.$element + .off('mouseenter mouseleave click', this.options.selector) + .on('mouseenter', this.options.selector, $.proxy(this.mouseenterHandler, this)) + .on('mouseleave', this.options.selector, $.proxy(this.mouseleaveHandler, this)); + } + } + this._poped = false; + this._inited = true; + this._opened = false; + this._idSeed = _globalIdSeed; + this.id = pluginName + this._idSeed; + // normalize container + this.options.container = $(this.options.container || document.body).first(); + + if (this.options.backdrop) { + backdrop.appendTo(this.options.container).hide(); + } + _globalIdSeed++; + if (this.getTrigger() === 'sticky') { + this.show(); + } + + if (this.options.selector) { + this._options = $.extend({}, this.options, { + selector: '' + }); + } + + }, + /* api methods and actions */ + destroy: function () { + var index = -1; + + for (var i = 0; i < _srcElements.length; i++) { + if (_srcElements[i] === this.$element) { + index = i; + break; + } + } + + _srcElements.splice(index, 1); + + + this.hide(); + this.$element.data('plugin_' + pluginName, null); + if (this.getTrigger() === 'click') { + this.$element.off('click'); + } else if (this.getTrigger() === 'hover') { + this.$element.off('mouseenter mouseleave'); + } + if (this.$target) { + this.$target.remove(); + } + }, + getDelegateOptions: function () { + var options = {}; + + this._options && $.each(this._options, function (key, value) { + if (defaults[key] !== value) { + options[key] = value; + } + }); + return options; + }, + /* + param: force boolean value, if value is true then force hide the popover + param: event dom event, + */ + hide: function (force, event) { + + if (!force && this.getTrigger() === 'sticky') { + return; + } + if (!this._opened) { + return; + } + if (event) { + event.preventDefault(); + event.stopPropagation(); + } + + if (this.xhr && this.options.abortXHR === true) { + this.xhr.abort(); + this.xhr = null; + } + + + var e = $.Event('hide.' + pluginType); + this.$element.trigger(e, [this.$target]); + if (this.$target) { + this.$target.removeClass('in').addClass(this.getHideAnimation()); + var that = this; + setTimeout(function () { + that.$target.hide(); + if (!that.getCache()) { + that.$target.remove(); + //that.getTriggerElement.removeAttr('data-target'); + } + }, that.getHideDelay()); + } + if (this.options.backdrop) { + backdrop.hide(); + } + this._opened = false; + this.$element.trigger('hidden.' + pluginType, [this.$target]); + + if (this.options.onHide) { + this.options.onHide(this.$target); + } + + }, + resetAutoHide: function () { + var that = this; + var autoHide = that.getAutoHide(); + if (autoHide) { + if (that.autoHideHandler) { + clearTimeout(that.autoHideHandler); + } + that.autoHideHandler = setTimeout(function () { + that.hide(); + }, autoHide); + } + }, + delegate: function (eventTarget) { + var self = $(eventTarget).data('plugin_' + pluginName); + if (!self) { + self = new WebuiPopover(eventTarget, this.getDelegateOptions()); + $(eventTarget).data('plugin_' + pluginName, self); + } + return self; + }, + toggle: function (e) { + var self = this; + if (e) { + e.preventDefault(); + e.stopPropagation(); + if (this.options.selector) { + self = this.delegate(e.currentTarget); + } + } + self[self.getTarget().hasClass('in') ? 'hide' : 'show'](); + }, + hideAll: function () { + hideAllPop(); + }, + hideOthers: function () { + hideOtherPops(this); + }, + /*core method ,show popover */ + show: function () { + if (this._opened) { + return; + } + //removeAllTargets(); + var + $target = this.getTarget().removeClass().addClass(pluginClass).addClass(this._customTargetClass); + if (!this.options.multi) { + this.hideOthers(); + } + + // use cache by default, if not cache setted , reInit the contents + if (!this.getCache() || !this._poped || this.content === '') { + this.content = ''; + this.setTitle(this.getTitle()); + if (!this.options.closeable) { + $target.find('.close').off('click').remove(); + } + if (!this.isAsync()) { + this.setContent(this.getContent()); + } else { + this.setContentASync(this.options.content); + } + + if (this.canEmptyHide() && this.content === '') { + return; + } + $target.show(); + } + + this.displayContent(); + + if (this.options.onShow) { + this.options.onShow($target); + } + + this.bindBodyEvents(); + if (this.options.backdrop) { + backdrop.show(); + } + this._opened = true; + this.resetAutoHide(); + }, + displayContent: function () { + var + //element postion + elementPos = this.getElementPosition(), + //target postion + $target = this.getTarget().removeClass().addClass(pluginClass).addClass(this._customTargetClass), + //target content + $targetContent = this.getContentElement(), + //target Width + targetWidth = $target[0].offsetWidth, + //target Height + targetHeight = $target[0].offsetHeight, + //placement + placement = 'bottom', + e = $.Event('show.' + pluginType); + + if (this.canEmptyHide()) { + + var content = $targetContent.children().html(); + if (content !== null && content.trim().length === 0) { + return; + } + } + + //if (this.hasContent()){ + this.$element.trigger(e, [$target]); + //} + // support width as data attribute + var optWidth = this.$element.data('width') || this.options.width; + if (optWidth === '') { + optWidth = this._defaults.width; + } + + if (optWidth !== 'auto') { + $target.width(optWidth); + } + + // support height as data attribute + var optHeight = this.$element.data('height') || this.options.height; + if (optHeight === '') { + optHeight = this._defaults.height; + } + + if (optHeight !== 'auto') { + $targetContent.height(optHeight); + } + + if (this.options.style) { + this.$target.addClass(pluginClass + '-' + this.options.style); + } + + //check rtl + if (this.options.direction === 'rtl' && !$targetContent.hasClass(rtlClass)) { + $targetContent.addClass(rtlClass); + } + + //init the popover and insert into the document body + if (!this.options.arrow) { + $target.find('.webui-arrow').remove(); + } + $target.detach().css({ + top: _offsetOut, + left: _offsetOut, + display: 'block', + opacity:this.options.opacity || 1 + }); + + if (this.getAnimation()) { + $target.addClass(this.getAnimation()); + } + $target.appendTo(this.options.container); + + + placement = this.getPlacement(elementPos); + + //This line is just for compatible with knockout custom binding + this.$element.trigger('added.' + pluginType); + + this.initTargetEvents(); + + if (!this.options.padding) { + if (this.options.height !== 'auto') { + $targetContent.css('height', $targetContent.outerHeight()); + } + this.$target.addClass('webui-no-padding'); + } + + // add maxHeight and maxWidth support by limodou@gmail.com 2016/10/1 + if (this.options.maxHeight) { + $targetContent.css('maxHeight', this.options.maxHeight); + } + + if (this.options.maxWidth) { + $targetContent.css('maxWidth', this.options.maxWidth); + } + // end + + targetWidth = $target[0].offsetWidth; + targetHeight = $target[0].offsetHeight; + + var postionInfo = this.getTargetPositin(elementPos, placement, targetWidth, targetHeight); + + this.$target.css(postionInfo.position).addClass(placement).addClass('in'); + + if (this.options.type === 'iframe') { + var $iframe = $target.find('iframe'); + var iframeWidth = $target.width(); + var iframeHeight = $iframe.parent().height(); + + if (this.options.iframeOptions.width !== '' && this.options.iframeOptions.width !== 'auto') { + iframeWidth = this.options.iframeOptions.width; + } + + if (this.options.iframeOptions.height !== '' && this.options.iframeOptions.height !== 'auto') { + iframeHeight = this.options.iframeOptions.height; + } + + $iframe.width(iframeWidth).height(iframeHeight); + } + + if (!this.options.arrow) { + this.$target.css({ + 'margin': 0 + }); + } + if (this.options.arrow) { + var $arrow = this.$target.find('.webui-arrow'); + $arrow.removeAttr('style'); + + //prevent arrow change by content size + if (placement === 'left' || placement === 'right') { + $arrow.css({ + top: this.$target.height() / 2 + }); + } else if (placement === 'top' || placement === 'bottom') { + $arrow.css({ + left: this.$target.width() / 2 + }); + } + + if (postionInfo.arrowOffset) { + //hide the arrow if offset is negative + if (postionInfo.arrowOffset.left === -1 || postionInfo.arrowOffset.top === -1) { + $arrow.hide(); + } else { + $arrow.css(postionInfo.arrowOffset); + } + } + + } + this._poped = true; + this.$element.trigger('shown.' + pluginType, [this.$target]); + }, + + isTargetLoaded: function () { + return this.getTarget().find('i.glyphicon-refresh').length === 0; + }, + + /*getter setters */ + getTriggerElement: function () { + return this.$element; + }, + getTarget: function () { + if (!this.$target) { + var id = pluginName + this._idSeed; + this.$target = $(this.options.template) + .attr('id', id); + this._customTargetClass = this.$target.attr('class') !== pluginClass ? this.$target.attr('class') : null; + this.getTriggerElement().attr('data-target', id); + } + if (!this.$target.data('trigger-element')) { + this.$target.data('trigger-element', this.getTriggerElement()); + } + return this.$target; + }, + removeTarget: function () { + this.$target.remove(); + this.$target = null; + this.$contentElement = null; + }, + getTitleElement: function () { + return this.getTarget().find('.' + pluginClass + '-title'); + }, + getContentElement: function () { + if (!this.$contentElement) { + this.$contentElement = this.getTarget().find('.' + pluginClass + '-content'); + } + return this.$contentElement; + }, + getTitle: function () { + return this.$element.attr('data-title') || this.options.title || this.$element.attr('title'); + }, + getUrl: function () { + return this.$element.attr('data-url') || this.options.url; + }, + getAutoHide: function () { + return this.$element.attr('data-auto-hide') || this.options.autoHide; + }, + getOffsetTop: function () { + return toNumber(this.$element.attr('data-offset-top')) || this.options.offsetTop; + }, + getOffsetLeft: function () { + return toNumber(this.$element.attr('data-offset-left')) || this.options.offsetLeft; + }, + getCache: function () { + var dataAttr = this.$element.attr('data-cache'); + if (typeof (dataAttr) !== 'undefined') { + switch (dataAttr.toLowerCase()) { + case 'true': + case 'yes': + case '1': + return true; + case 'false': + case 'no': + case '0': + return false; + } + } + return this.options.cache; + }, + getTrigger: function () { + return this.$element.attr('data-trigger') || this.options.trigger; + }, + getDelayShow: function () { + var dataAttr = this.$element.attr('data-delay-show'); + if (typeof (dataAttr) !== 'undefined') { + return dataAttr; + } + return this.options.delay.show === 0 ? 0 : this.options.delay.show || 100; + }, + getHideDelay: function () { + var dataAttr = this.$element.attr('data-delay-hide'); + if (typeof (dataAttr) !== 'undefined') { + return dataAttr; + } + return this.options.delay.hide === 0 ? 0 : this.options.delay.hide || 100; + }, + getAnimation: function () { + var dataAttr = this.$element.attr('data-animation'); + return dataAttr || this.options.animation; + }, + getHideAnimation: function () { + var ani = this.getAnimation(); + return ani ? ani + '-out' : 'out'; + }, + setTitle: function (title) { + var $titleEl = this.getTitleElement(); + if (title) { + //check rtl + if (this.options.direction === 'rtl' && !$titleEl.hasClass(rtlClass)) { + $titleEl.addClass(rtlClass); + } + $titleEl.html(title); + } else { + $titleEl.remove(); + } + }, + hasContent: function () { + return this.getContent(); + }, + canEmptyHide: function () { + return this.options.hideEmpty && this.options.type === 'html'; + }, + getIframe: function () { + var $iframe = $('').attr('src', this.getUrl()); + var self = this; + $.each(this._defaults.iframeOptions, function (opt) { + if (typeof self.options.iframeOptions[opt] !== 'undefined') { + $iframe.attr(opt, self.options.iframeOptions[opt]); + } + }); + + return $iframe; + }, + getContent: function () { + if (this.getUrl()) { + switch (this.options.type) { + case 'iframe': + this.content = this.getIframe(); + break; + case 'html': + try { + this.content = $(this.getUrl()); + if (!this.content.is(':visible')) { + this.content.show(); + } + } catch (error) { + throw new Error('Unable to get popover content. Invalid selector specified.'); + } + break; + } + } else if (!this.content) { + var content = ''; + if ($.isFunction(this.options.content)) { + content = this.options.content.apply(this.$element[0], [this]); + } else { + content = this.options.content; + } + this.content = this.$element.attr('data-content') || content; + if (!this.content) { + var $next = this.$element.next(); + + if ($next && $next.hasClass(pluginClass + '-content')) { + this.content = $next; + } + } + } + return this.content; + }, + setContent: function (content) { + var $target = this.getTarget(); + var $ct = this.getContentElement(); + if (typeof content === 'string') { + $ct.html(content); + } else if (content instanceof $) { + $ct.html(''); + //Don't want to clone too many times. + if (!this.options.cache) { + content.clone(true, true).removeClass(pluginClass + '-content').appendTo($ct); + } else { + content.removeClass(pluginClass + '-content').appendTo($ct); + } + } + this.$target = $target; + }, + isAsync: function () { + return this.options.type === 'async'; + }, + setContentASync: function (content) { + var that = this; + if (this.xhr) { + return; + } + this.xhr = $.ajax({ + url: this.getUrl(), + type: this.options.async.type, + cache: this.getCache(), + beforeSend: function (xhr, settings) { + if (that.options.async.before) { + that.options.async.before(that, xhr, settings); + } + }, + success: function (data) { + that.bindBodyEvents(); + if (content && $.isFunction(content)) { + that.content = content.apply(that.$element[0], [data]); + } else { + that.content = data; + } + that.setContent(that.content); + var $targetContent = that.getContentElement(); + $targetContent.removeAttr('style'); + that.displayContent(); + if (that.options.async.success) { + that.options.async.success(that, data); + } + }, + complete: function () { + that.xhr = null; + }, + error: function (xhr, data) { + if (that.options.async.error) { + that.options.async.error(that, xhr, data); + } + } + }); + }, + + bindBodyEvents: function () { + if (_isBodyEventHandled) { + return; + } + if (this.options.dismissible && this.getTrigger() === 'click') { + if (isMobile) { + $document.off('touchstart.webui-popover').on('touchstart.webui-popover', $.proxy(this.bodyTouchStartHandler, this)); + } else { + $document.off('keyup.webui-popover').on('keyup.webui-popover', $.proxy(this.escapeHandler, this)); + $document.off('click.webui-popover').on('click.webui-popover', $.proxy(this.bodyClickHandler, this)); + } + } else if (this.getTrigger() === 'hover') { + $document.off('touchend.webui-popover') + .on('touchend.webui-popover', $.proxy(this.bodyClickHandler, this)); + } + }, + + /* event handlers */ + mouseenterHandler: function (e) { + var self = this; + + if (e && this.options.selector) { + self = this.delegate(e.currentTarget); + } + + if (self._timeout) { + clearTimeout(self._timeout); + } + self._enterTimeout = setTimeout(function () { + if (!self.getTarget().is(':visible')) { + self.show(); + } + }, this.getDelayShow()); + }, + mouseleaveHandler: function () { + var self = this; + clearTimeout(self._enterTimeout); + //key point, set the _timeout then use clearTimeout when mouse leave + self._timeout = setTimeout(function () { + self.hide(); + }, this.getHideDelay()); + }, + escapeHandler: function (e) { + if (e.keyCode === 27) { + this.hideAll(); + } + }, + bodyTouchStartHandler: function (e) { + var self = this; + var $eventEl = $(e.currentTarget); + $eventEl.on('touchend', function (e) { + self.bodyClickHandler(e); + $eventEl.off('touchend'); + }); + $eventEl.on('touchmove', function () { + $eventEl.off('touchend'); + }); + }, + bodyClickHandler: function (e) { + _isBodyEventHandled = true; + var canHide = true; + for (var i = 0; i < _srcElements.length; i++) { + var pop = getPopFromElement(_srcElements[i]); + if (pop && pop._opened) { + var offset = pop.getTarget().offset(); + var popX1 = offset.left; + var popY1 = offset.top; + var popX2 = offset.left + pop.getTarget().width(); + var popY2 = offset.top + pop.getTarget().height(); + var pt = pointerEventToXY(e); + var inPop = pt.x >= popX1 && pt.x <= popX2 && pt.y >= popY1 && pt.y <= popY2; + if (inPop) { + canHide = false; + break; + } + } + } + if (canHide) { + hideAllPop(); + } + }, + + /* + targetClickHandler: function() { + this._targetclick = true; + }, + */ + + //reset and init the target events; + initTargetEvents: function () { + if (this.getTrigger() === 'hover') { + this.$target + .off('mouseenter mouseleave') + .on('mouseenter', $.proxy(this.mouseenterHandler, this)) + .on('mouseleave', $.proxy(this.mouseleaveHandler, this)); + } + this.$target.find('.close').off('click').on('click', $.proxy(this.hide, this, true)); + //this.$target.off('click.webui-popover').on('click.webui-popover', $.proxy(this.targetClickHandler, this)); + }, + /* utils methods */ + //caculate placement of the popover + getPlacement: function (pos) { + var + placement, + container = this.options.container, + clientWidth = container.innerWidth(), + clientHeight = container.innerHeight(), + scrollTop = container.scrollTop(), + scrollLeft = container.scrollLeft(), + pageX = Math.max(0, pos.left - scrollLeft), + pageY = Math.max(0, pos.top - scrollTop); + //arrowSize = 20; + + //if placement equals auto,caculate the placement by element information; + if (typeof (this.options.placement) === 'function') { + placement = this.options.placement.call(this, this.getTarget()[0], this.$element[0]); + } else { + placement = this.$element.data('placement') || this.options.placement; + } + + var isH = placement === 'horizontal'; + var isV = placement === 'vertical'; + var detect = placement === 'auto' || isH || isV; + + if (detect) { + if (pageX < clientWidth / 3) { + if (pageY < clientHeight / 3) { + placement = isH ? 'right-bottom' : 'bottom-right'; + } else if (pageY < clientHeight * 2 / 3) { + if (isV) { + placement = pageY <= clientHeight / 2 ? 'bottom-right' : 'top-right'; + } else { + placement = 'right'; + } + } else { + placement = isH ? 'right-top' : 'top-right'; + } + //placement= pageY>targetHeight+arrowSize?'top-right':'bottom-right'; + } else if (pageX < clientWidth * 2 / 3) { + if (pageY < clientHeight / 3) { + if (isH) { + placement = pageX <= clientWidth / 2 ? 'right-bottom' : 'left-bottom'; + } else { + placement = 'bottom'; + } + } else if (pageY < clientHeight * 2 / 3) { + if (isH) { + placement = pageX <= clientWidth / 2 ? 'right' : 'left'; + } else { + placement = pageY <= clientHeight / 2 ? 'bottom' : 'top'; + } + } else { + if (isH) { + placement = pageX <= clientWidth / 2 ? 'right-top' : 'left-top'; + } else { + placement = 'top'; + } + } + } else { + //placement = pageY>targetHeight+arrowSize?'top-left':'bottom-left'; + if (pageY < clientHeight / 3) { + placement = isH ? 'left-bottom' : 'bottom-left'; + } else if (pageY < clientHeight * 2 / 3) { + if (isV) { + placement = pageY <= clientHeight / 2 ? 'bottom-left' : 'top-left'; + } else { + placement = 'left'; + } + } else { + placement = isH ? 'left-top' : 'top-left'; + } + } + } else if (placement === 'auto-top') { + if (pageX < clientWidth / 3) { + placement = 'top-right'; + } else if (pageX < clientWidth * 2 / 3) { + placement = 'top'; + } else { + placement = 'top-left'; + } + } else if (placement === 'auto-bottom') { + if (pageX < clientWidth / 3) { + placement = 'bottom-right'; + } else if (pageX < clientWidth * 2 / 3) { + placement = 'bottom'; + } else { + placement = 'bottom-left'; + } + } else if (placement === 'auto-left') { + if (pageY < clientHeight / 3) { + placement = 'left-top'; + } else if (pageY < clientHeight * 2 / 3) { + placement = 'left'; + } else { + placement = 'left-bottom'; + } + } else if (placement === 'auto-right') { + if (pageY < clientHeight / 3) { + placement = 'right-bottom'; + } else if (pageY < clientHeight * 2 / 3) { + placement = 'right'; + } else { + placement = 'right-top'; + } + } + return placement; + }, + getElementPosition: function () { + // If the container is the body or normal conatiner, just use $element.offset() + var elRect = this.$element[0].getBoundingClientRect(); + var container = this.options.container; + var cssPos = container.css('position'); + + if (container.is(document.body) || cssPos === 'static') { + return $.extend({}, this.$element.offset(), { + width: this.$element[0].offsetWidth || elRect.width, + height: this.$element[0].offsetHeight || elRect.height + }); + // Else fixed container need recalculate the position + } else if (cssPos === 'fixed') { + var containerRect = container[0].getBoundingClientRect(); + return { + top: elRect.top - containerRect.top + container.scrollTop(), + left: elRect.left - containerRect.left + container.scrollLeft(), + width: elRect.width, + height: elRect.height + }; + } else if (cssPos === 'relative') { + return { + top: this.$element.offset().top - container.offset().top, + left: this.$element.offset().left - container.offset().left, + width: this.$element[0].offsetWidth || elRect.width, + height: this.$element[0].offsetHeight || elRect.height + }; + } + }, + + getTargetPositin: function (elementPos, placement, targetWidth, targetHeight) { + var pos = elementPos, + container = this.options.container, + //clientWidth = container.innerWidth(), + //clientHeight = container.innerHeight(), + elementW = this.$element.outerWidth(), + elementH = this.$element.outerHeight(), + scrollTop = document.documentElement.scrollTop + container.scrollTop(), + scrollLeft = document.documentElement.scrollLeft + container.scrollLeft(), + position = {}, + arrowOffset = null, + arrowSize = this.options.arrow ? 20 : 0, + padding = 10, + fixedW = elementW < arrowSize + padding ? arrowSize : 0, + fixedH = elementH < arrowSize + padding ? arrowSize : 0, + refix = 0, + pageH = document.documentElement.clientHeight + scrollTop, + pageW = document.documentElement.clientWidth + scrollLeft; + + var validLeft = pos.left + pos.width / 2 - fixedW > 0; + var validRight = pos.left + pos.width / 2 + fixedW < pageW; + var validTop = pos.top + pos.height / 2 - fixedH > 0; + var validBottom = pos.top + pos.height / 2 + fixedH < pageH; + + + switch (placement) { + case 'bottom': + position = { + top: pos.top + pos.height, + left: pos.left + pos.width / 2 - targetWidth / 2 + }; + break; + case 'top': + position = { + top: pos.top - targetHeight, + left: pos.left + pos.width / 2 - targetWidth / 2 + }; + break; + case 'left': + position = { + top: pos.top + pos.height / 2 - targetHeight / 2, + left: pos.left - targetWidth + }; + break; + case 'right': + position = { + top: pos.top + pos.height / 2 - targetHeight / 2, + left: pos.left + pos.width + }; + break; + case 'top-right': + position = { + top: pos.top - targetHeight, + left: validLeft ? pos.left - fixedW : padding + }; + arrowOffset = { + left: validLeft ? Math.min(elementW, targetWidth) / 2 + fixedW : _offsetOut + }; + break; + case 'top-left': + refix = validRight ? fixedW : -padding; + position = { + top: pos.top - targetHeight, + left: pos.left - targetWidth + pos.width + refix + }; + arrowOffset = { + left: validRight ? targetWidth - Math.min(elementW, targetWidth) / 2 - fixedW : _offsetOut + }; + break; + case 'bottom-right': + position = { + top: pos.top + pos.height, + left: validLeft ? pos.left - fixedW : padding + }; + arrowOffset = { + left: validLeft ? Math.min(elementW, targetWidth) / 2 + fixedW : _offsetOut + }; + break; + case 'bottom-left': + refix = validRight ? fixedW : -padding; + position = { + top: pos.top + pos.height, + left: pos.left - targetWidth + pos.width + refix + }; + arrowOffset = { + left: validRight ? targetWidth - Math.min(elementW, targetWidth) / 2 - fixedW : _offsetOut + }; + break; + case 'right-top': + refix = validBottom ? fixedH : -padding; + position = { + top: pos.top - targetHeight + pos.height + refix, + left: pos.left + pos.width + }; + arrowOffset = { + top: validBottom ? targetHeight - Math.min(elementH, targetHeight) / 2 - fixedH : _offsetOut + }; + break; + case 'right-bottom': + position = { + top: validTop ? pos.top - fixedH : padding, + left: pos.left + pos.width + }; + arrowOffset = { + top: validTop ? Math.min(elementH, targetHeight) / 2 + fixedH : _offsetOut + }; + break; + case 'left-top': + refix = validBottom ? fixedH : -padding; + position = { + top: pos.top - targetHeight + pos.height + refix, + left: pos.left - targetWidth + }; + arrowOffset = { + top: validBottom ? targetHeight - Math.min(elementH, targetHeight) / 2 - fixedH : _offsetOut + }; + break; + case 'left-bottom': + position = { + top: validTop ? pos.top - fixedH : padding, + left: pos.left - targetWidth + }; + arrowOffset = { + top: validTop ? Math.min(elementH, targetHeight) / 2 + fixedH : _offsetOut + }; + break; + + } + position.top += this.getOffsetTop(); + position.left += this.getOffsetLeft(); + + return { + position: position, + arrowOffset: arrowOffset + }; + } + }; + $.fn[pluginName] = function (options, noInit) { + var results = []; + var $result = this.each(function () { + + var webuiPopover = $.data(this, 'plugin_' + pluginName); + if (!webuiPopover) { + if (!options) { + webuiPopover = new WebuiPopover(this, null); + } else if (typeof options === 'string') { + if (options !== 'destroy') { + if (!noInit) { + webuiPopover = new WebuiPopover(this, null); + results.push(webuiPopover[options]()); + } + } + } else if (typeof options === 'object') { + webuiPopover = new WebuiPopover(this, options); + } + $.data(this, 'plugin_' + pluginName, webuiPopover); + } else { + if (options === 'destroy') { + webuiPopover.destroy(); + } else if (typeof options === 'string') { + results.push(webuiPopover[options]()); + } + } + }); + return (results.length) ? results : $result; + }; + + //Global object exposes to window. + var webuiPopovers = (function () { + var _hideAll = function () { + hideAllPop(); + }; + var _create = function (selector, options) { + options = options || {}; + $(selector).webuiPopover(options); + }; + var _isCreated = function (selector) { + var created = true; + $(selector).each(function (i, item) { + created = created && $(item).data('plugin_' + pluginName) !== undefined; + }); + return created; + }; + var _show = function (selector, options) { + if (options) { + $(selector).webuiPopover(options).webuiPopover('show'); + } else { + $(selector).webuiPopover('show'); + } + }; + var _hide = function (selector) { + $(selector).webuiPopover('hide'); + }; + + var _setDefaultOptions = function (options) { + defaults = $.extend({}, defaults, options); + }; + + var _updateContent = function (selector, content) { + var pop = $(selector).data('plugin_' + pluginName); + if (pop) { + var cache = pop.getCache(); + pop.options.cache = false; + pop.options.content = content; + if (pop._opened) { + pop._opened = false; + pop.show(); + } else { + if (pop.isAsync()) { + pop.setContentASync(content); + } else { + pop.setContent(content); + } + } + pop.options.cache = cache; + } + }; + + var _updateContentAsync = function (selector, url) { + var pop = $(selector).data('plugin_' + pluginName); + if (pop) { + var cache = pop.getCache(); + var type = pop.options.type; + pop.options.cache = false; + pop.options.url = url; + + if (pop._opened) { + pop._opened = false; + pop.show(); + } else { + pop.options.type = 'async'; + pop.setContentASync(pop.content); + } + pop.options.cache = cache; + pop.options.type = type; + } + }; + + return { + show: _show, + hide: _hide, + create: _create, + isCreated: _isCreated, + hideAll: _hideAll, + updateContent: _updateContent, + updateContentAsync: _updateContentAsync, + setDefaultOptions: _setDefaultOptions + }; + })(); + window.WebuiPopovers = webuiPopovers; + exports("popover",WebuiPopovers); +}) + + + + diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/popup.js b/demo/webman/backend/plugin/admin/public/component/pear/module/popup.js new file mode 100644 index 0000000000000000000000000000000000000000..376edaf61159aeccf3ed66233226a6071b289bba --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/popup.js @@ -0,0 +1,49 @@ +layui.define(['layer', 'jquery', 'element'], function(exports) { + "use strict"; + + var MOD_NAME = 'popup', + $ = layui.jquery, + layer = layui.layer, + element = layui.element; + + var popup = new function() { + + this.success = function(msg) { + layer.msg(msg, { + icon: 1, + time: 1000 + }) + }, + this.failure = function(msg) { + layer.msg(msg, { + icon: 2, + time: 1000 + }) + }, + this.warning = function(msg) { + layer.msg(msg, { + icon: 3, + time: 1000 + }) + }, + this.success = function(msg, callback) { + layer.msg(msg, { + icon: 1, + time: 1000 + }, callback); + }, + this.failure = function(msg, callback) { + layer.msg(msg, { + icon: 2, + time: 3000 + }, callback); + }, + this.warming = function(msg, callback) { + layer.msg(msg, { + icon: 3, + time: 2000 + }, callback); + } + }; + exports(MOD_NAME, popup); +}) diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/select.js b/demo/webman/backend/plugin/admin/public/component/pear/module/select.js new file mode 100644 index 0000000000000000000000000000000000000000..3b095f72cdfea386ca6adcf4ae1ac7c1b14128c2 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/select.js @@ -0,0 +1,1740 @@ +/** + * name: formSelects + * 基于Layui Select多选 + * version: 4.0.0.0910 + * http://sun.faysunshine.com/layui/formSelects-v4/dist/formSelects-v4.js + */ +(function(layui, window, factory) { + if(typeof exports === 'object') { // 支持 CommonJS + module.exports = factory(); + } else if(typeof define === 'function' && define.amd) { // 支持 AMD + define(factory); + } else if(window.layui && layui.define) { //layui加载 + layui.define(['jquery'], function(exports) { + exports('select', factory()); + }); + } else { + window.formSelects = factory(); + } +})(typeof layui == 'undefined' ? null : layui, window, function() { + let v = '4.0.0.0910', + NAME = 'xm-select', + PNAME = 'xm-select-parent', + INPUT = 'xm-select-input', + TDIV = 'xm-select--suffix', + THIS = 'xm-select-this', + LABEL = 'xm-select-label', + SEARCH = 'xm-select-search', + SEARCH_TYPE = 'xm-select-search-type', + SHOW_COUNT = 'xm-select-show-count', + CREATE = 'xm-select-create', + CREATE_LONG = 'xm-select-create-long', + MAX = 'xm-select-max', + SKIN = 'xm-select-skin', + DIRECTION = "xm-select-direction", + HEIGHT = 'xm-select-height', + DISABLED = 'xm-dis-disabled', + DIS = 'xm-select-dis', + TEMP = 'xm-select-temp', + RADIO = 'xm-select-radio', + LINKAGE= 'xm-select-linkage', + DL = 'xm-select-dl', + DD_HIDE = 'xm-select-hide', + HIDE_INPUT = 'xm-hide-input', + SANJIAO = 'xm-select-sj', + ICON_CLOSE = 'xm-icon-close', + FORM_TITLE = 'xm-select-title', + FORM_SELECT = 'xm-form-select', + FORM_SELECTED = 'xm-form-selected', + FORM_NONE = 'xm-select-none', + FORM_EMPTY = 'xm-select-empty', + FORM_INPUT = 'xm-input', + FORM_DL_INPUT = 'xm-dl-input', + FORM_SELECT_TIPS = 'xm-select-tips', + CHECKBOX_YES = 'xm-iconfont', + FORM_TEAM_PID = 'XM_PID_VALUE', + CZ = 'xm-cz', + CZ_GROUP = 'xm-cz-group', + TIPS = '请选择', + data = {}, + events = { + on: {}, + endOn: {}, + filter: {}, + maxTips: {}, + opened: {}, + closed: {} + }, + ajax = { + type: 'get', + header: { + + }, + first: true, + data: {}, + searchUrl: '', + searchName: 'keyword', + searchVal: null, + keyName: 'name', + keyVal: 'value', + keySel: 'selected', + keyDis: 'disabled', + keyChildren: 'children', + dataType: '', + delay: 500, + beforeSuccess: null, + success: null, + error: null, + beforeSearch: null, + response: { + statusCode: 0, + statusName: 'code', + msgName: 'msg', + dataName: 'data' + }, + tree: { + nextClick: function(id, item, callback){ + callback([]); + }, + folderChoose: true, + lazy: true + } + }, + quickBtns = [ + {icon: 'xm-iconfont icon-quanxuan', name: '全选', click: function(id, cm){ + cm.selectAll(id, true, true); + }}, + {icon: 'xm-iconfont icon-qingkong', name: '清空', click: function(id, cm){ + cm.removeAll(id, true, true); + }}, + {icon: 'xm-iconfont icon-fanxuan', name: '反选', click: function(id, cm){ + cm.reverse(id, true, true); + }}, + {icon: 'xm-iconfont icon-pifu', name: '换肤', click: function(id, cm){ + cm.skin(id); + }} + ], + $ = window.$ || (window.layui && window.layui.jquery), + $win = $(window), + ajaxs = {}, + fsConfig = {}, + fsConfigs = {}, + FormSelects = function(options) { + this.config = { + name: null, //xm-select="xxx" + max: null, + maxTips: (id, vals, val, max) => { + let ipt = $(`[xid="${this.config.name}"]`).prev().find(`.${NAME}`); + if(ipt.parents('.layui-form-item[pane]').length) { + ipt = ipt.parents('.layui-form-item[pane]'); + } + ipt.attr('style', 'border-color: red !important'); + setTimeout(() => { + ipt.removeAttr('style'); + }, 300); + }, + init: null, //初始化的选择值, + on: null, //select值发生变化 + opened: null, + closed: null, + filter: (id, inputVal, val, isDisabled) => { + return val.name.indexOf(inputVal) == -1; + }, + clearid: -1, + direction: 'auto', + height: null, + isEmpty: false, + btns: [quickBtns[0], quickBtns[1], quickBtns[2]], + searchType: 0, + create: (id, name) => { + return Date.now(); + }, + template: (id, item) => { + return item.name; + }, + showCount: 0, + isCreate: false, + placeholder: TIPS, + clearInput: false, + }; + this.select = null; + this.values = []; + $.extend(this.config, options, { + searchUrl: options.isSearch ? options.searchUrl : null, + placeholder: options.optionsFirst ? ( + options.optionsFirst.value ? TIPS : (options.optionsFirst.innerHTML || TIPS) + ) : TIPS, + btns: options.radio ? [quickBtns[1]] : [quickBtns[0], quickBtns[1], quickBtns[2]], + }, fsConfigs[options.name] || fsConfig); + if(isNaN(this.config.showCount) || this.config.showCount <= 0) { + this.config.showCount = 19921012; + } + }; + + //一些简单的处理方法 + let Common = function(){ + this.appender(); + this.on(); + this.onreset(); + }; + + Common.prototype.appender = function(){//针对IE做的一些拓展 + //拓展Array map方法 + if(!Array.prototype.map){Array.prototype.map=function(i,h){var b,a,c,e=Object(this),f=e.length>>>0;if(h){b=h}a=new Array(f);c=0;while(c>>0;if(typeof g!=="function"){throw new TypeError(g+" is not a function")}if(arguments.length>1){d=b}c=0;while(c>>0;if(typeof b!=="function"){throw new TypeError()}var e=[];var d=arguments[1];for(var c=0;c { + let othis = $(select), + id = othis.attr(NAME), + hasLayuiRender = othis.next(`.layui-form-select`), + hasRender = othis.next(`.${PNAME}`), + options = { + name: id, + disabled: select.disabled, + max: othis.attr(MAX) - 0, + isSearch: othis.attr(SEARCH) != undefined, + searchUrl: othis.attr(SEARCH), + isCreate: othis.attr(CREATE) != undefined, + radio: othis.attr(RADIO) != undefined, + skin: othis.attr(SKIN), + direction: othis.attr(DIRECTION), + optionsFirst: select.options[0], + height: othis.attr(HEIGHT), + formname: othis.attr('name') || othis.attr('_name'), + layverify: othis.attr('lay-verify') || othis.attr('_lay-verify'), + layverType: othis.attr('lay-verType'), + searchType: othis.attr(SEARCH_TYPE) == 'dl' ? 1 : 0, + showCount: othis.attr(SHOW_COUNT) - 0, + }, + value = othis.find('option[selected]').toArray().map((option) => {//获取已选中的数据 + return { + name: option.innerHTML, + value: option.value, + } + }), + fs = new FormSelects(options); + + fs.values = value; + + if(fs.config.init) { + fs.values = fs.config.init.map(item => { + if(typeof item == 'object') { + return item; + } + return { + name: othis.find(`option[value="${item}"]`).text(), + value: item + } + }).filter(item => { + return item.name; + }); + fs.config.init = fs.values.concat([]); + }else{ + fs.config.init = value.concat([]); + } + + !fs.values && (fs.values = []); + + data[id] = fs; + + //先取消layui对select的渲染 + hasLayuiRender[0] && hasLayuiRender.remove(); + hasRender[0] && hasRender.remove(); + + //构造渲染div + let dinfo = this.renderSelect(id, fs.config.placeholder, select); + let heightStyle = !fs.config.height || fs.config.height == 'auto' ? '' : `xm-hg style="height: 34px;"`; + let inputHtml = [ + `
                                                                                          `, + ``, + `
                                                                                          ` + ]; + let reElem = + $(`
                                                                                          + +
                                                                                          +
                                                                                          + ${inputHtml.join('')} + +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          ${dinfo}
                                                                                          +
                                                                                          `); + + var $parent = $(`
                                                                                          `); + $parent.append(reElem) + othis.after($parent); + othis.attr('lay-ignore', ''); + othis.removeAttr('name') && othis.attr('_name', fs.config.formname); + othis.removeAttr('lay-verify') && othis.attr('_lay-verify', fs.config.layverify); + + //如果可搜索, 加上事件 + if(fs.config.isSearch){ + ajaxs[id] = $.extend({}, ajax, {searchUrl: fs.config.searchUrl}, ajaxs[id]); + $(document).on('input', `div.${PNAME}[FS_ID="${id}"] .${INPUT}`, (e) => { + this.search(id, e, fs.config.searchUrl); + }); + if(fs.config.searchUrl){//触发第一次请求事件 + this.triggerSearch(reElem, true); + } + }else{//隐藏第二个dl + reElem.find(`dl dd.${FORM_DL_INPUT}`).css('display', 'none'); + } + }); + } + + Common.prototype.search = function(id, e, searchUrl, call){ + let input; + if(call){ + input = call; + }else{ + input = e.target; + let keyCode = e.keyCode; + if(keyCode === 9 || keyCode === 13 || keyCode === 37 || keyCode === 38 || keyCode === 39 || keyCode === 40) { + return false; + } + } + let inputValue = $.trim(input.value); + //过滤一下tips + this.changePlaceHolder($(input)); + + let ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax; + searchUrl = ajaxConfig.searchUrl || searchUrl; + let fs = data[id], + isCreate = fs.config.isCreate, + reElem = $(`dl[xid="${id}"]`).parents(`.${FORM_SELECT}`); + //如果开启了远程搜索 + if(searchUrl){ + if(ajaxConfig.searchVal){ + inputValue = ajaxConfig.searchVal; + ajaxConfig.searchVal = ''; + } + if(!ajaxConfig.beforeSearch || (ajaxConfig.beforeSearch && ajaxConfig.beforeSearch instanceof Function && ajaxConfig.beforeSearch(id, searchUrl, inputValue))){ + let delay = ajaxConfig.delay; + if(ajaxConfig.first){ + ajaxConfig.first = false; + delay = 10; + } + clearTimeout(fs.clearid); + fs.clearid = setTimeout(() => { + reElem.find(`dl > *:not(.${FORM_SELECT_TIPS})`).remove(); + reElem.find(`dd.${FORM_NONE}`).addClass(FORM_EMPTY).text('请求中'); + this.ajax(id, searchUrl, inputValue, false, null, true); + }, delay); + } + }else{ + reElem.find(`dl .${DD_HIDE}`).removeClass(DD_HIDE); + //遍历选项, 选择可以显示的值 + reElem.find(`dl dd:not(.${FORM_SELECT_TIPS})`).each((idx, item) => { + let _item = $(item); + let searchFun = events.filter[id] || data[id].config.filter; + if(searchFun && searchFun(id, inputValue, this.getItem(id, _item), _item.hasClass(DISABLED)) == true){ + _item.addClass(DD_HIDE); + } + }); + //控制分组名称 + reElem.find('dl dt').each((index, item) => { + if(!$(item).nextUntil('dt', `:not(.${DD_HIDE})`).length) { + $(item).addClass(DD_HIDE); + } + }); + //动态创建 + this.create(id, isCreate, inputValue); + let shows = reElem.find(`dl dd:not(.${FORM_SELECT_TIPS}):not(.${DD_HIDE})`); + if(!shows.length){ + reElem.find(`dd.${FORM_NONE}`).addClass(FORM_EMPTY).text('无匹配项'); + }else{ + reElem.find(`dd.${FORM_NONE}`).removeClass(FORM_EMPTY); + } + } + } + + Common.prototype.isArray = function(obj){ + return Object.prototype.toString.call(obj) == "[object Array]"; + } + + Common.prototype.triggerSearch = function(div, isCall){ + (div ? [div] : $(`.${FORM_SELECT}`).toArray()).forEach((reElem, index) => { + reElem = $(reElem); + let id = reElem.find('dl').attr('xid') + if((id && data[id] && data[id].config.isEmpty) || isCall){ + this.search(id, null, null, data[id].config.searchType == 0 ? reElem.find(`.${LABEL} .${INPUT}`) : reElem.find(`dl .${FORM_DL_INPUT} .${INPUT}`)); + } + }); + } + + Common.prototype.clearInput = function(id){ + let div = $(`.${PNAME}[fs_id="${id}"]`); + let input = data[id].config.searchType == 0 ? div.find(`.${LABEL} .${INPUT}`) : div.find(`dl .${FORM_DL_INPUT} .${INPUT}`); + input.val(''); + } + + Common.prototype.ajax = function(id, searchUrl, inputValue, isLinkage, linkageWidth, isSearch, successCallback, isReplace){ + let reElem = $(`.${PNAME} dl[xid="${id}"]`).parents(`.${FORM_SELECT}`); + if(!reElem[0] || !searchUrl){ + return ; + } + let ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax; + let ajaxData = $.extend(true, {}, ajaxConfig.data); + ajaxData[ajaxConfig.searchName] = inputValue; + //是否需要对ajax添加随机时间 + //ajaxData['_'] = Date.now(); + $.ajax({ + type: ajaxConfig.type, + headers: ajaxConfig.header, + url: searchUrl, + data: ajaxConfig.dataType == 'json' ? JSON.stringify(ajaxData) : ajaxData, + success: (res) => { + if(typeof res == 'string'){ + res = JSON.parse(res); + } + ajaxConfig.beforeSuccess && ajaxConfig.beforeSuccess instanceof Function && (res = ajaxConfig.beforeSuccess(id, searchUrl, inputValue, res)); + if(this.isArray(res)){ + let newRes = {}; + newRes[ajaxConfig.response.statusName] = ajaxConfig.response.statusCode; + newRes[ajaxConfig.response.msgName] = ""; + newRes[ajaxConfig.response.dataName] = res; + res = newRes; + } + if(res[ajaxConfig.response.statusName] != ajaxConfig.response.statusCode) { + reElem.find(`dd.${FORM_NONE}`).addClass(FORM_EMPTY).text(res[ajaxConfig.response.msgName]); + }else{ + reElem.find(`dd.${FORM_NONE}`).removeClass(FORM_EMPTY); + this.renderData(id, res[ajaxConfig.response.dataName], isLinkage, linkageWidth, isSearch, isReplace); + data[id].config.isEmpty = res[ajaxConfig.response.dataName].length == 0; + } + successCallback && successCallback(id); + ajaxConfig.success && ajaxConfig.success instanceof Function && ajaxConfig.success(id, searchUrl, inputValue, res); + }, + error: (err) => { + reElem.find(`dd[lay-value]:not(.${FORM_SELECT_TIPS})`).remove(); + reElem.find(`dd.${FORM_NONE}`).addClass(FORM_EMPTY).text('服务异常'); + ajaxConfig.error && ajaxConfig.error instanceof Function && ajaxConfig.error(id, searchUrl, inputValue, err); + } + }); + } + + Common.prototype.renderData = function(id, dataArr, linkage, linkageWidth, isSearch, isReplace){ + if(linkage){//渲染多级联动 + this.renderLinkage(id, dataArr, linkageWidth); + return; + } + if(isReplace){ + this.renderReplace(id, dataArr); + return; + } + + let reElem = $(`.${PNAME} dl[xid="${id}"]`).parents(`.${FORM_SELECT}`); + let ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax; + let pcInput = reElem.find(`.${TDIV} input`); + + dataArr = this.exchangeData(id, dataArr); + let values = []; + reElem.find('dl').html(this.renderSelect(id, pcInput.attr('placeholder') || pcInput.attr('back'), dataArr.map((item) => { + let itemVal = $.extend({}, item, { + innerHTML: item[ajaxConfig.keyName], + value: item[ajaxConfig.keyVal], + sel: item[ajaxConfig.keySel], + disabled: item[ajaxConfig.keyDis], + type: item.type, + name: item[ajaxConfig.keyName] + }); + if(itemVal.sel){ + values.push(itemVal); + } + return itemVal; + }))); + + let label = reElem.find(`.${LABEL}`); + let dl = reElem.find('dl[xid]'); + if(isSearch){//如果是远程搜索, 这里需要判重 + let oldVal = data[id].values; + oldVal.forEach((item, index) => { + dl.find(`dd[lay-value="${item.value}"]`).addClass(THIS); + }); + values.forEach((item, index) => { + if(this.indexOf(oldVal, item) == -1){ + this.addLabel(id, label, item); + dl.find(`dd[lay-value="${item.value}"]`).addClass(THIS); + oldVal.push(item); + } + }); + }else{ + values.forEach((item, index) => { + this.addLabel(id, label, item); + dl.find(`dd[lay-value="${item.value}"]`).addClass(THIS); + }); + data[id].values = values; + } + this.commonHandler(id, label); + } + + Common.prototype.renderLinkage = function(id, dataArr, linkageWidth){ + let result = [], + index = 0, + temp = {"0": dataArr}, + ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax; + db[id] = {}; + do{ + let group = result[index ++] = [], + _temp = temp; + temp = {}; + $.each(_temp, (pid, arr) => { + $.each(arr, (idx, item) => { + let val = { + pid: pid, + name: item[ajaxConfig.keyName], + value: item[ajaxConfig.keyVal], + }; + db[id][val.value] = $.extend(item, val); + group.push(val); + let children = item[ajaxConfig.keyChildren]; + if(children && children.length){ + temp[val.value] = children; + } + }); + }); + }while(Object.getOwnPropertyNames(temp).length); + + let reElem = $(`.${PNAME} dl[xid="${id}"]`).parents(`.${FORM_SELECT}`); + let html = ['
                                                                                          ']; + + $.each(result, (idx, arr) => { + let groupDiv = [`
                                                                                          `]; + $.each(arr, (idx2, item) => { + let span = `
                                                                                        • ${item.name}
                                                                                        • `; + groupDiv.push(span); + }); + groupDiv.push(`
                                                                                          `); + html = html.concat(groupDiv); + }); + html.push('
                                                                                          '); + html.push('
                                                                                          '); + reElem.find('dl').html(html.join('')); + reElem.find(`.${INPUT}`).css('display', 'none');//联动暂时不支持搜索 + } + + Common.prototype.renderReplace = function(id, dataArr){ + let dl = $(`.${PNAME} dl[xid="${id}"]`); + let ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax; + + dataArr = this.exchangeData(id, dataArr); + db[id] = dataArr; + + let html = dataArr.map((item) => { + let itemVal = $.extend({}, item, { + innerHTML: item[ajaxConfig.keyName], + value: item[ajaxConfig.keyVal], + sel: item[ajaxConfig.keySel], + disabled: item[ajaxConfig.keyDis], + type: item.type, + name: item[ajaxConfig.keyName] + }); + return this.createDD(id, itemVal); + }).join(''); + + dl.find(`dd:not(.${FORM_SELECT_TIPS}),dt:not([style])`).remove(); + dl.find(`dt[style]`).after($(html)); + } + + Common.prototype.exchangeData = function(id, arr){//这里处理树形结构 + let ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax; + let childrenName = ajaxConfig['keyChildren']; + let disabledName = ajaxConfig['keyDis']; + db[id] = {}; + let result = this.getChildrenList(arr, childrenName, disabledName, [], false); + return result; + } + + Common.prototype.getChildrenList = function(arr, childrenName, disabledName, pid, disabled){ + let result = [], offset = 0; + for(let a = 0; a < arr.length; a ++){ + let item = arr[a]; + if(item.type && item.type == 'optgroup'){ + result.push(item); + continue; + }else{ + offset ++; + } + let parentIds = pid.concat([]); + parentIds.push(`${offset - 1}_E`); + item[FORM_TEAM_PID] = JSON.stringify(parentIds); + item[disabledName] = item[disabledName] || disabled; + result.push(item); + let child = item[childrenName]; + if(child && common.isArray(child) && child.length){ + item['XM_TREE_FOLDER'] = true; + let pidArr = parentIds.concat([]); + let childResult = this.getChildrenList(child, childrenName, disabledName, pidArr, item[disabledName]); + result = result.concat(childResult); + } + } + return result; + } + + Common.prototype.create = function(id, isCreate, inputValue){ + if(isCreate && inputValue){ + let fs = data[id], + dl = $(`[xid="${id}"]`), + tips= dl.find(`dd.${FORM_SELECT_TIPS}.${FORM_DL_INPUT}`), + tdd = null, + temp = dl.find(`dd.${TEMP}`); + dl.find(`dd:not(.${FORM_SELECT_TIPS}):not(.${TEMP})`).each((index, item) => { + if(inputValue == $(item).find('span').attr('name')){ + tdd = item; + } + }); + if(!tdd){//如果不存在, 则创建 + let val = fs.config.create(id, inputValue); + if(temp[0]){ + temp.attr('lay-value', val); + temp.find('span').text(inputValue); + temp.find('span').attr("name", inputValue); + temp.removeClass(DD_HIDE); + }else{ + tips.after($(this.createDD(id, { + name: inputValue, + innerHTML: inputValue, + value: val + }, `${TEMP} ${CREATE_LONG}`))); + } + } + }else{ + $(`[xid=${id}] dd.${TEMP}`).remove(); + } + } + + Common.prototype.createDD = function(id, item, clz){ + let ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax; + let name = $.trim(item.innerHTML); + db[id][item.value] = $(item).is('option') ? (item = function(){ + let resultItem = {}; + resultItem[ajaxConfig.keyName] = name; + resultItem[ajaxConfig.keyVal] = item.value; + resultItem[ajaxConfig.keyDis] = item.disabled; + return resultItem; + }()) : item; + let template = data[id].config.template(id, item); + let pid = item[FORM_TEAM_PID]; + pid ? (pid = JSON.parse(pid)) : (pid = [-1]); + let attr = pid[0] == -1 ? '' : `tree-id="${pid.join('-')}" tree-folder="${!!item['XM_TREE_FOLDER']}"`; + return `
                                                                                          +
                                                                                          + + ${template} +
                                                                                          +
                                                                                          `; + } + + Common.prototype.createQuickBtn = function(obj, right){ + return `
                                                                                          ${obj.name}
                                                                                          ` + } + + Common.prototype.renderBtns = function(id, show, right){ + let quickBtn = []; + let dl = $(`dl[xid="${id}"]`); + quickBtn.push(`
                                                                                          `); + $.each(data[id].config.btns, (index, item) => { + quickBtn.push(this.createQuickBtn(item, right)); + }); + quickBtn.push(`
                                                                                          `); + quickBtn.push(this.createQuickBtn({icon: 'xm-iconfont icon-caidan', name: ''})); + return quickBtn.join(''); + } + + Common.prototype.renderSelect = function(id, tips, select){ + db[id] = {}; + let arr = []; + if(data[id].config.btns.length){ + setTimeout(() => { + let dl = $(`dl[xid="${id}"]`); + dl.parents(`.${FORM_SELECT}`).attr(SEARCH_TYPE, data[id].config.searchType); + dl.find(`.${CZ_GROUP}`).css('max-width', `${dl.prev().width() - 54}px`); + }, 10) + arr.push([ + `
                                                                                          `, + this.renderBtns(id, null, '30px'), + `
                                                                                          `, + `
                                                                                          `, + ``, + ``, + `
                                                                                          ` + ].join('')); + }else{ + arr.push(`
                                                                                          ${tips}
                                                                                          `); + } + if(this.isArray(select)){ + $(select).each((index, item) => { + if(item){ + if(item.type && item.type === 'optgroup') { + arr.push(`
                                                                                          ${item.name}
                                                                                          `); + } else { + arr.push(this.createDD(id, item)); + } + } + }); + }else{ + $(select).find('*').each((index, item) => { + if(item.tagName.toLowerCase() == 'option' && index == 0 && !item.value){ + return ; + } + if(item.tagName.toLowerCase() === 'optgroup') { + arr.push(`
                                                                                          ${item.label}
                                                                                          `); + } else { + arr.push(this.createDD(id, item)); + } + }); + } + arr.push('
                                                                                          '); + arr.push(`
                                                                                          没有选项
                                                                                          `); + return arr.join(''); + } + + Common.prototype.on = function(){//事件绑定 + this.one(); + + $(document).on('click', (e) => { + if(!$(e.target).parents(`.${FORM_TITLE}`)[0]){//清空input中的值 + $(`.${PNAME} dl .${DD_HIDE}`).removeClass(DD_HIDE); + $(`.${PNAME} dl dd.${FORM_EMPTY}`).removeClass(FORM_EMPTY); + $(`.${PNAME} dl dd.${TEMP}`).remove(); + $.each(data, (key, fs) => { + this.clearInput(key); + if(!fs.values.length){ + this.changePlaceHolder($(`div[FS_ID="${key}"] .${LABEL}`)); + } + }); + } + $(`.${PNAME} .${FORM_SELECTED}`).each((index, item) => { + this.changeShow($(item).find(`.${FORM_TITLE}`), false); + }) ; + }); + } + + Common.prototype.calcLabelLeft = function(label, w, call){ + let pos = this.getPosition(label[0]); + pos.y = pos.x + label[0].clientWidth; + let left = label[0].offsetLeft; + if(!label.find('span').length){ + left = 0; + }else if(call){//校正归位 + let span = label.find('span:last'); + span.css('display') == 'none' ? (span = span.prev()[0]) : (span = span[0]); + let spos = this.getPosition(span); + spos.y = spos.x + span.clientWidth; + + if(spos.y > pos.y){ + left = left - (spos.y - pos.y) - 5; + }else{ + left = 0; + } + }else{ + if(w < 0){ + let span = label.find(':last'); + span.css('display') == 'none' ? (span = span.prev()[0]) : (span = span[0]); + let spos = this.getPosition(span); + spos.y = spos.x + span.clientWidth; + if(spos.y > pos.y){ + left -= 10; + } + }else{ + if(left < 0){ + left += 10; + } + if(left > 0){ + left = 0; + } + } + } + label.css('left', left + 'px'); + } + + Common.prototype.one = function(target){//一次性事件绑定 + $(target ? target : document).off('click', `.${FORM_TITLE}`).on('click', `.${FORM_TITLE}`, (e) => { + let othis = $(e.target), + title = othis.is(FORM_TITLE) ? othis : othis.parents(`.${FORM_TITLE}`), + dl = title.next(), + id = dl.attr('xid'); + + //清空非本select的input val + $(`dl[xid]`).not(dl).each((index, item) => { + this.clearInput($(item).attr('xid')); + }); + $(`dl[xid]`).not(dl).find(`dd.${DD_HIDE}`).removeClass(DD_HIDE); + + //如果是disabled select + if(title.hasClass(DIS)){ + return false; + } + //如果点击的是右边的三角或者只读的input + if(othis.is(`.${SANJIAO}`) || othis.is(`.${INPUT}[readonly]`)){ + this.changeShow(title, !title.parents(`.${FORM_SELECT}`).hasClass(FORM_SELECTED)); + return false; + } + //如果点击的是input的右边, focus一下 + if(title.find(`.${INPUT}:not(readonly)`)[0]){ + let input = title.find(`.${INPUT}`), + epos = {x: e.pageX, y: e.pageY}, + pos = this.getPosition(title[0]), + width = title.width(); + while(epos.x > pos.x){ + if($(document.elementFromPoint(epos.x, epos.y)).is(input)){ + input.focus(); + this.changeShow(title, true); + return false; + } + epos.x -= 50; + } + } + + //如果点击的是可搜索的input + if(othis.is(`.${INPUT}`)){ + this.changeShow(title, true); + return false; + } + //如果点击的是x按钮 + if(othis.is(`i[fsw="${NAME}"]`)){ + let val = this.getItem(id, othis), + dd = dl.find(`dd[lay-value='${val.value}']`); + if(dd.hasClass(DISABLED)){//如果是disabled状态, 不可选, 不可删 + return false; + } + this.handlerLabel(id, dd, false, val); + return false; + } + + this.changeShow(title, !title.parents(`.${FORM_SELECT}`).hasClass(FORM_SELECTED)); + return false; + }); + $(target ? target : document).off('click', `dl.${DL}`).on('click', `dl.${DL}`, (e) => { + let othis = $(e.target); + if(othis.is(`.${LINKAGE}`) || othis.parents(`.${LINKAGE}`)[0]){//linkage的处理 + othis = othis.is('li') ? othis : othis.parents('li[xm-value]'); + let group = othis.parents('.xm-select-linkage-group'), + id = othis.parents('dl').attr('xid'); + if(!id){ + return false; + } + //激活li + group.find('.xm-select-active').removeClass('xm-select-active'); + othis.addClass('xm-select-active'); + //激活下一个group, 激活前显示对应数据 + group.nextAll('.xm-select-linkage-group').addClass('xm-select-linkage-hide'); + let nextGroup = group.next('.xm-select-linkage-group'); + nextGroup.find('li').addClass('xm-select-linkage-hide'); + nextGroup.find(`li[pid="${othis.attr('xm-value')}"]`).removeClass('xm-select-linkage-hide'); + //如果没有下一个group, 或没有对应的值 + if(!nextGroup[0] || nextGroup.find(`li:not(.xm-select-linkage-hide)`).length == 0){ + let vals = [], + index = 0, + isAdd = !othis.hasClass('xm-select-this'); + if(data[id].config.radio){ + othis.parents('.xm-select-linkage').find('.xm-select-this').removeClass('xm-select-this'); + } + do{ + vals[index ++] = { + name: othis.find('span').text(), + value: othis.attr('xm-value') + } + othis = othis.parents('.xm-select-linkage-group').prev().find(`li[xm-value="${othis.attr('pid')}"]`); + }while(othis.length); + vals.reverse(); + let val = { + name: vals.map((item) => { + return item.name; + }).join('/'), + value: vals.map((item) => { + return item.value; + }).join('/'), + } + this.handlerLabel(id, null, isAdd, val); + }else{ + nextGroup.removeClass('xm-select-linkage-hide'); + } + return false; + } + + if(othis.is('dl')){ + return false; + } + + if(othis.is('dt')){ + othis.nextUntil(`dt`).each((index, item) => { + item = $(item); + if(item.hasClass(DISABLED) || item.hasClass(THIS)){ + + }else{ + item.find('i:not(.icon-expand)').click(); + } + }); + return false; + } + let dd = othis.is('dd') ? othis : othis.parents('dd'); + let id = dd.parent('dl').attr('xid'); + + if(dd.hasClass(DISABLED)){//被禁用选项的处理 + return false; + } + + //菜单功效 + if(othis.is('i.icon-caidan')){ + let opens = [], closes = []; + othis.parents('dl').find('dd[tree-folder="true"]').each((index, item) => { + $(item).attr('xm-tree-hidn') == undefined ? opens.push(item) : closes.push(item); + }); + let arr = closes.length ? closes : opens; + arr.forEach(item => item.click()); + return false; + } + //树状结构的选择 + let treeId = dd.attr('tree-id'); + if(treeId){ + //忽略右边的图标 + if(othis.is('i:not(.icon-expand)')){ + this.handlerLabel(id, dd, !dd.hasClass(THIS)); + return false; + } + let ajaxConfig = ajaxs[id] || ajax; + let treeConfig = ajaxConfig.tree; + let childrens = dd.nextAll(`dd[tree-id^="${treeId}"]`); + if(childrens && childrens.length){ + let len = childrens[0].clientHeight; + len ? ( + this.addTreeHeight(dd, len), + len = 0 + ) : ( + len = dd.attr('xm-tree-hidn') || 36, + dd.removeAttr('xm-tree-hidn'), + dd.find('>i').remove(), + (childrens = childrens.filter((index, item) => $(item).attr('tree-id').split('-').length - 1 == treeId.split('-').length)) + ); + childrens.animate({ + height: len + }, 150) + return false; + }else{ + if(treeConfig.nextClick && treeConfig.nextClick instanceof Function){ + treeConfig.nextClick(id, this.getItem(id, dd), (res) => { + if(!res || !res.length){ + this.handlerLabel(id, dd, !dd.hasClass(THIS)); + }else{ + dd.attr('tree-folder', 'true'); + let ddChilds = []; + res.forEach((item, idx) => { + item.innerHTML = item[ajaxConfig.keyName]; + item[FORM_TEAM_PID] = JSON.stringify(treeId.split('-').concat([idx])); + ddChilds.push(this.createDD(id, item)); + db[id][item[ajaxConfig.keyVal]] = item; + }); + dd.after(ddChilds.join('')); + } + }); + return false; + } + } + } + + if(dd.hasClass(FORM_SELECT_TIPS)){//tips的处理 + let btn = othis.is(`.${CZ}`) ? othis : othis.parents(`.${CZ}`); + if(!btn[0]){ + return false; + } + let method = btn.attr('method'); + let obj = data[id].config.btns.filter(bean => bean.name == method)[0]; + obj && obj.click && obj.click instanceof Function && obj.click(id, this); + return false; + } + this.handlerLabel(id, dd, !dd.hasClass(THIS)); + return false; + }); + } + + Common.prototype.addTreeHeight = function(dd, len){ + let treeId = dd.attr('tree-id'); + let childrens = dd.nextAll(`dd[tree-id^="${treeId}"]`); + if(childrens.length){ + dd.append(''); + dd.attr('xm-tree-hidn', len); + childrens.each((index, item) => { + let that = $(item); + this.addTreeHeight(that, len); + }) + } + } + + let db = {}; + Common.prototype.getItem = function(id, value){ + if(value instanceof $){ + if(value.is(`i[fsw="${NAME}"]`)){ + let span = value.parent(); + return db[id][value] || { + name: span.find('font').text(), + value: span.attr('value') + } + } + let val = value.attr('lay-value'); + return !db[id][val] ? (db[id][val] = { + name: value.find('span[name]').attr('name'), + value: val + }) : db[id][val]; + }else if(typeof(value) == 'string' && value.indexOf('/') != -1){ + return db[id][value] || { + name: this.valToName(id, value), + value: value + } + } + return db[id][value]; + } + + Common.prototype.linkageAdd = function(id, val){ + let dl = $(`dl[xid="${id}"]`); + dl.find('.xm-select-active').removeClass('xm-select-active'); + let vs = val.value.split('/'); + let pid, li, index = 0; + let lis = []; + do{ + pid = vs[index]; + li = dl.find(`.xm-select-linkage-group${index + 1} li[xm-value="${pid}"]`); + li[0] && lis.push(li); + index ++; + }while(li.length && pid != undefined); + if(lis.length == vs.length){ + $.each(lis, (idx, item) => { + item.addClass('xm-select-this'); + }); + } + } + + Common.prototype.linkageDel = function(id, val){ + let dl = $(`dl[xid="${id}"]`); + let vs = val.value.split('/'); + let pid, li, index = vs.length - 1; + do{ + pid = vs[index]; + li = dl.find(`.xm-select-linkage-group${index + 1} li[xm-value="${pid}"]`); + if(!li.parent().next().find(`li[pid=${pid}].xm-select-this`).length){ + li.removeClass('xm-select-this'); + } + index --; + }while(li.length && pid != undefined); + } + + Common.prototype.valToName = function(id, val){ + let dl = $(`dl[xid="${id}"]`); + let vs = (val + "").split('/'); + if(!vs.length){ + return null; + } + let names = []; + $.each(vs, (idx, item) => { + let name = dl.find(`.xm-select-linkage-group${idx + 1} li[xm-value="${item}"] span`).text(); + names.push(name); + }); + return names.length == vs.length ? names.join('/') : null; + } + + Common.prototype.commonHandler = function(key, label){ + if(!label || !label[0]){ + return ; + } + this.checkHideSpan(key, label); + //计算input的提示语 + this.changePlaceHolder(label); + //计算高度 + this.retop(label.parents(`.${FORM_SELECT}`)); + this.calcLabelLeft(label, 0, true); + //表单默认值 + this.setHidnVal(key, label); + //title值 + label.parents(`.${FORM_TITLE} .${NAME}`).attr('title', data[key].values.map((val) => { + return val.name; + }).join(',')); + } + + Common.prototype.initVal = function(id){ + let target = {}; + if(id){ + target[id] = data[id]; + }else{ + target = data; + } + $.each(target, (key, val) => { + let values = val.values, + div = $(`dl[xid="${key}"]`).parent(), + label = div.find(`.${LABEL}`), + dl = div.find('dl'); + dl.find(`dd.${THIS}`).removeClass(THIS); + + let _vals = values.concat([]); + _vals.concat([]).forEach((item, index) => { + this.addLabel(key, label, item); + dl.find(`dd[lay-value="${item.value}"]`).addClass(THIS); + }); + if(val.config.radio){ + _vals.length && values.push(_vals[_vals.length - 1]); + } + this.commonHandler(key, label); + }); + } + + Common.prototype.setHidnVal = function(key, label) { + if(!label || !label[0]) { + return; + } + label.parents(`.${PNAME}`).find(`.${HIDE_INPUT}`).val(data[key].values.map((val) => { + return val.value; + }).join(',')); + } + + Common.prototype.handlerLabel = function(id, dd, isAdd, oval, notOn){ + let div = $(`[xid="${id}"]`).prev().find(`.${LABEL}`), + val = dd && this.getItem(id, dd), + vals = data[id].values, + on = data[id].config.on || events.on[id], + endOn = data[id].config.endOn || events.endOn[id]; + if(oval){ + val = oval; + } + let fs = data[id]; + if(isAdd && fs.config.max && fs.values.length >= fs.config.max){ + let maxTipsFun = events.maxTips[id] || data[id].config.maxTips; + maxTipsFun && maxTipsFun(id, vals.concat([]), val, fs.config.max); + return ; + } + if(!notOn){ + if(on && on instanceof Function && on(id, vals.concat([]), val, isAdd, dd && dd.hasClass(DISABLED)) == false) { + return ; + } + } + let dl = $(`dl[xid="${id}"]`); + isAdd ? ( + (dd && dd[0] ? ( + dd.addClass(THIS), + dd.removeClass(TEMP) + ) : ( + dl.find('.xm-select-linkage')[0] && this.linkageAdd(id, val) + )), + this.addLabel(id, div, val), + vals.push(val) + ) : ( + (dd && dd[0] ? ( + dd.removeClass(THIS) + ) : ( + dl.find('.xm-select-linkage')[0] && this.linkageDel(id, val) + )), + this.delLabel(id, div, val), + this.remove(vals, val) + ); + if(!div[0]) return ; + //单选选完后直接关闭选择域 + if(fs.config.radio){ + this.changeShow(div, false); + } + //移除表单验证的红色边框 + div.parents(`.${FORM_TITLE}`).prev().removeClass('layui-form-danger'); + + //清空搜索值 + fs.config.clearInput && this.clearInput(id); + + this.commonHandler(id, div); + + !notOn && endOn && endOn instanceof Function && endOn(id, vals.concat([]), val, isAdd, dd && dd.hasClass(DISABLED)); + } + + Common.prototype.addLabel = function(id, div, val){ + if(!val) return ; + let tips = `fsw="${NAME}"`; + let [$label, $close] = [ + $(`${val.name}`), + $(``) + ]; + $label.append($close); + //如果是radio模式 + let fs = data[id]; + if(fs.config.radio){ + fs.values.length = 0; + $(`dl[xid="${id}"]`).find(`dd.${THIS}:not([lay-value="${val.value}"])`).removeClass(THIS); + div.find('span').remove(); + } + //如果是固定高度 + div.find('input').css('width', '50px'); + div.find('input').before($label); + } + + Common.prototype.delLabel = function(id, div, val){ + if(!val) return ; + div.find(`span[value="${val.value}"]:first`).remove(); + } + + Common.prototype.checkHideSpan = function(id, div){ + let parentHeight = div.parents(`.${NAME}`)[0].offsetHeight + 5; + div.find('span.xm-span-hide').removeClass('xm-span-hide'); + div.find('span[style]').remove(); + + let count = data[id].config.showCount; + div.find('span').each((index, item) => { + if(index >= count){ + $(item).addClass('xm-span-hide'); + } + }); + + let prefix = div.find(`span:eq(${count})`); + prefix[0] && prefix.before($(` + ${div.find('span').length - count}`)) + } + + Common.prototype.retop = function(div){//计算dl显示的位置 + let dl = div.find('dl'), + top = div.offset().top + div.outerHeight() + 5 - $win.scrollTop(), + dlHeight = dl.outerHeight(); + let up = div.hasClass('layui-form-selectup') || dl.css('top').indexOf('-') != -1 || (top + dlHeight > $win.height() && top >= dlHeight); + div = div.find(`.${NAME}`); + + let fs = data[dl.attr('xid')]; + let base = dl.parents('.layui-form-pane')[0] && dl.prev()[0].clientHeight > 38 ? 14 : 10; + if((fs && fs.config.direction == 'up') || up){ + up = true; + if((fs && fs.config.direction == 'down')){ + up = false; + } + } + let reHeight = div[0].offsetTop + div.height() + base; + if(up) { + dl.css({ + top: 'auto', + bottom: reHeight + 3 + 'px', + }); + } else { + dl.css({ + top: reHeight + 'px', + bottom: 'auto' + }); + } + } + + Common.prototype.changeShow = function(children, isShow){//显示于隐藏 + $('.layui-form-selected').removeClass('layui-form-selected'); + let top = children.parents(`.${FORM_SELECT}`), + realShow = top.hasClass(FORM_SELECTED), + id = top.find('dl').attr('xid'); + $(`.${PNAME} .${FORM_SELECT}`).not(top).removeClass(FORM_SELECTED); + if(isShow){ + this.retop(top); + top.addClass(FORM_SELECTED); + top.find(`.${INPUT}`).focus(); + if(!top.find(`dl dd[lay-value]:not(.${FORM_SELECT_TIPS})`).length){ + top.find(`dl .${FORM_NONE}`).addClass(FORM_EMPTY); + } + }else{ + top.removeClass(FORM_SELECTED); + this.clearInput(id); + top.find(`dl .${FORM_EMPTY}`).removeClass(FORM_EMPTY); + top.find(`dl dd.${DD_HIDE}`).removeClass(DD_HIDE); + top.find(`dl dd.${TEMP}`).remove(); + //计算ajax数据是否为空, 然后重新请求数据 + if(id && data[id] && data[id].config.isEmpty){ + this.triggerSearch(top); + } + this.changePlaceHolder(top.find(`.${LABEL}`)); + } + if(isShow != realShow){ + let openFun = data[id].config.opened || events.opened[id]; + isShow && openFun && openFun instanceof Function && openFun(id); + let closeFun = data[id].config.closed || events.closed[id]; + !isShow && closeFun && closeFun instanceof Function && closeFun(id); + } + } + + Common.prototype.changePlaceHolder = function(div){//显示于隐藏提示语 + //调整pane模式下的高度 + let title = div.parents(`.${FORM_TITLE}`); + title[0] || (title = div.parents(`dl`).prev()); + if(!title[0]){ + return ; + } + + let id = div.parents(`.${PNAME}`).find(`dl[xid]`).attr('xid'); + if(data[id] && data[id].config.height){//既然固定高度了, 那就看着办吧 + + }else{ + let height = title.find(`.${NAME}`)[0].clientHeight; + title.css('height' , (height > 36 ? height + 4 : height) + 'px'); + //如果是layui pane模式, 处理label的高度 + let label = title.parents(`.${PNAME}`).parent().prev(); + if(label.is('.layui-form-label') && title.parents('.layui-form-pane')[0]){ + height = height > 36 ? height + 4 : height; + title.css('height' , height + 'px'); + label.css({ + height: height + 2 + 'px', + lineHeight: (height - 18) + 'px' + }) + } + } + + let input = title.find(`.${TDIV} input`), + isShow = !div.find('span:last')[0] && !title.find(`.${INPUT}`).val(); + if(isShow){ + let ph = input.attr('back'); + input.removeAttr('back'); + input.attr('placeholder', ph); + }else{ + let ph = input.attr('placeholder'); + input.removeAttr('placeholder'); + input.attr('back', ph) + } + } + + Common.prototype.indexOf = function(arr, val){ + for(let i = 0; i < arr.length; i++) { + if(arr[i].value == val || arr[i].value == (val ? val.value : val) || arr[i] == val || JSON.stringify(arr[i]) == JSON.stringify(val)) { + return i; + } + } + return -1; + } + + Common.prototype.remove = function(arr, val){ + let idx = this.indexOf(arr, val ? val.value : val); + if(idx > -1) { + arr.splice(idx, 1); + return true; + } + return false; + } + + Common.prototype.selectAll = function(id, isOn, skipDis){ + let dl = $(`[xid="${id}"]`); + if(!dl[0]){ + return ; + } + if(dl.find('.xm-select-linkage')[0]){ + return ; + } + dl.find(`dd[lay-value]:not(.${FORM_SELECT_TIPS}):not(.${THIS})${skipDis ? ':not(.'+DISABLED+')' :''}`).each((index, item) => { + item = $(item); + let val = this.getItem(id, item); + this.handlerLabel(id, dl.find(`dd[lay-value="${val.value}"]`), true, val, !isOn); + }); + } + + Common.prototype.removeAll = function(id, isOn, skipDis){ + let dl = $(`[xid="${id}"]`); + if(!dl[0]){ + return ; + } + if(dl.find('.xm-select-linkage')[0]){//针对多级联动的处理 + data[id].values.concat([]).forEach((item, idx) => { + let vs = item.value.split('/'); + let pid, li, index = 0; + do{ + pid = vs[index ++]; + li = dl.find(`.xm-select-linkage-group${index}:not(.xm-select-linkage-hide) li[xm-value="${pid}"]`); + li.click(); + }while(li.length && pid != undefined); + }); + return ; + } + data[id].values.concat([]).forEach((item, index) => { + if(skipDis && dl.find(`dd[lay-value="${item.value}"]`).hasClass(DISABLED)){ + + }else{ + this.handlerLabel(id, dl.find(`dd[lay-value="${item.value}"]`), false, item, !isOn); + } + }); + } + + Common.prototype.reverse = function(id, isOn, skipDis){ + let dl = $(`[xid="${id}"]`); + if(!dl[0]){ + return ; + } + if(dl.find('.xm-select-linkage')[0]){ + return ; + } + dl.find(`dd[lay-value]:not(.${FORM_SELECT_TIPS})${skipDis ? ':not(.'+DISABLED+')' :''}`).each((index, item) => { + item = $(item); + let val = this.getItem(id, item); + this.handlerLabel(id, dl.find(`dd[lay-value="${val.value}"]`), !item.hasClass(THIS), val, !isOn); + }); + } + + Common.prototype.skin = function(id){ + let skins = ['default' ,'primary', 'normal', 'warm', 'danger']; + let skin = skins[Math.floor(Math.random() * skins.length)]; + $(`dl[xid="${id}"]`).parents(`.${PNAME}`).find(`.${FORM_SELECT}`).attr('xm-select-skin', skin); + this.check(id) && this.commonHandler(id, $(`dl[xid="${id}"]`).parents(`.${PNAME}`).find(`.${LABEL}`)); + } + + Common.prototype.getPosition = function(e){ + let x = 0, y = 0; + while (e != null) { + x += e.offsetLeft; + y += e.offsetTop; + e = e.offsetParent; + } + return { x: x, y: y }; + }; + + Common.prototype.onreset = function(){//监听reset按钮, 然后重置多选 + $(document).on('click', '[type=reset]', (e) => { + $(e.target).parents('form').find(`.${PNAME} dl[xid]`).each((index, item) => { + let id = item.getAttribute('xid'), + dl = $(item), + dd, + temp = {}; + common.removeAll(id); + data[id].config.init.forEach((val, idx) => { + if(val && (!temp[val] || data[id].config.repeat) && (dd = dl.find(`dd[lay-value="${val.value}"]`))[0]){ + common.handlerLabel(id, dd, true); + temp[val] = 1; + } + }); + }) + }); + } + + Common.prototype.bindEvent = function(name, id, fun){ + if(id && id instanceof Function){ + fun = id; + id = null; + } + if(fun && fun instanceof Function){ + if(!id){ + $.each(data, (id, val) => { + data[id] ? (data[id].config[name] = fun) : (events[name][id] = fun) + }) + }else{ + data[id] ? (data[id].config[name] = fun, delete events[name][id]) : (events[name][id] = fun) + } + } + } + + Common.prototype.check = function(id, notAutoRender){ + if($(`dl[xid="${id}"]`).length) { + return true; + }else if($(`select[xm-select="${id}"]`).length){ + if(!notAutoRender){ + this.render(id, $(`select[xm-select="${id}"]`)); + return true; + } + }else{ + delete data[id]; + return false; + } + } + + Common.prototype.render = function(id, select){ + common.init(select); + common.one($(`dl[xid="${id}"]`).parents(`.${PNAME}`)); + common.initVal(id); + } + + Common.prototype.log = function(obj){ + console.log(obj); + } + + let Select4 = function(){ + this.v = v; + this.render(); + }; + let common = new Common(); + + Select4.prototype.value = function(id, type, isAppend){ + if(typeof id != 'string'){ + return []; + } + let fs = data[id]; + if(!common.check(id)){ + return []; + } + if(typeof type == 'string' || type == undefined){ + let arr = fs.values.concat([]) || []; + if(type == 'val') { + return arr.map((val) => { + return val.value; + }); + } + if(type == 'valStr') { + return arr.map((val) => { + return val.value; + }).join(','); + } + if(type == 'name') { + return arr.map((val) => { + return val.name; + }); + } + if(type == 'nameStr') { + return arr.map((val) => { + return val.name; + }).join(','); + } + return arr; + } + if(common.isArray(type)) { + let dl = $(`[xid="${id}"]`), + temp = {}, + dd, + isAdd = true; + if(isAppend == false){//删除传入的数组 + isAdd = false; + }else if(isAppend == true){//追加模式 + isAdd = true; + }else{//删除原有的数据 + common.removeAll(id); + } + if(isAdd){ + fs.values.forEach((val, index) => { + temp[val.value] = 1; + }); + } + type.forEach((val, index) => { + if(val && (!temp[val] || fs.config.repeat)){ + if((dd = dl.find(`dd[lay-value="${val}"]`))[0]){ + common.handlerLabel(id, dd, isAdd, null, true); + temp[val] = 1; + }else{ + let name = common.valToName(id, val); + if(name){ + common.handlerLabel(id, dd, isAdd, common.getItem(id, val), true); + temp[val] = 1; + } + } + } + }); + } + } + + Select4.prototype.on = function(id, fun, isEnd) { + common.bindEvent(isEnd ? 'endOn' : 'on', id, fun); + return this; + } + + Select4.prototype.filter = function(id, fun){ + common.bindEvent('filter', id, fun); + return this; + } + + Select4.prototype.maxTips = function(id, fun){ + common.bindEvent('maxTips', id, fun); + return this; + } + + Select4.prototype.opened = function(id, fun){ + common.bindEvent('opened', id, fun); + return this; + } + + Select4.prototype.closed = function(id, fun){ + common.bindEvent('closed', id, fun); + return this; + } + + Select4.prototype.config = function(id, config, isJson){ + if(id && typeof id == 'object'){ + isJson = config == true; + config = id; + id = null; + } + if(config && typeof config== 'object'){ + if(isJson){ + config.header || (config.header = {}); + config.header['Content-Type'] = 'application/json; charset=UTF-8'; + config.dataType = 'json'; + } + id ? ( + ajaxs[id] = $.extend(true, {}, ajaxs[id] || ajax, config), !common.check(id) && this.render(id), + data[id] && config.direction && (data[id].config.direction = config.direction), + data[id] && config.clearInput && (data[id].config.clearInput = true), + config.searchUrl && data[id] && common.triggerSearch($(`.${PNAME} dl[xid="${id}"]`).parents(`.${FORM_SELECT}`), true) + ) : ( + $.extend(true, ajax, config), + $.each(ajaxs, (key, item) => { + $.extend(true, item, config) + }) + ); + } + return this; + } + + Select4.prototype.render = function(id, options){ + if(id && typeof id == 'object'){ + options = id; + id = null; + } + let config = options ? { + init: options.init, + disabled: options.disabled, + max: options.max, + isSearch: options.isSearch, + searchUrl: options.searchUrl, + isCreate: options.isCreate, + radio: options.radio, + skin: options.skin, + direction: options.direction, + height: options.height, + formname: options.formname, + layverify: options.layverify, + layverType: options.layverType, + showCount: options.showCount, + placeholder: options.placeholder, + create: options.create, + filter: options.filter, + maxTips: options.maxTips, + on: options.on, + on: options.on, + opened: options.opened, + closed: options.closed, + template: options.template, + clearInput: options.clearInput, + } : {}; + + options && options.searchType != undefined && (config.searchType = options.searchType == 'dl' ? 1 : 0); + + if(id){ + fsConfigs[id] = {}; + $.extend(fsConfigs[id], data[id] ? data[id].config : {}, config); + }else{ + $.extend(fsConfig, config); + } + + ($(`select[${NAME}="${id}"]`)[0] ? $(`select[${NAME}="${id}"]`) : $(`select[${NAME}]`)).each((index, select) => { + let sid = select.getAttribute(NAME); + common.render(sid, select); + setTimeout(() => common.setHidnVal(sid, $(`select[xm-select="${sid}"] + div.${PNAME} .${LABEL}`)), 10); + }); + return this; + } + + Select4.prototype.disabled = function(id){ + let target = {}; + id ? (common.check(id) && (target[id] = data[id])) : (target = data); + + $.each(target, (key, val) => { + $(`dl[xid="${key}"]`).prev().addClass(DIS); + }); + return this; + } + + Select4.prototype.undisabled = function(id){ + let target = {}; + id ? (common.check(id) && (target[id] = data[id])) : (target = data); + + $.each(target, (key, val) => { + $(`dl[xid="${key}"]`).prev().removeClass(DIS); + }); + return this; + } + + Select4.prototype.data = function(id, type, config){ + if(!id || !type || !config){ + common.log(`id: ${id} param error !!!`) + return this; + } + if(!common.check(id)){ + common.log(`id: ${id} not render !!!`) + return this; + } + this.value(id, []); + this.config(id, config); + if(type == 'local'){ + common.renderData(id, config.arr, config.linkage == true, config.linkageWidth ? config.linkageWidth : '100'); + }else if(type == 'server'){ + common.ajax(id, config.url, config.keyword, config.linkage == true, config.linkageWidth ? config.linkageWidth : '100'); + } + return this; + } + + Select4.prototype.btns = function(id, btns, config){ + if(id && common.isArray(id)){ + btns = id; + id = null; + } + if(!btns || !common.isArray(btns)) { + return this; + }; + let target = {}; + id ? (common.check(id) && (target[id] = data[id])) : (target = data); + + btns = btns.map((obj) => { + if(typeof obj == 'string'){ + if(obj == 'select'){ + return quickBtns[0]; + } + if(obj == 'remove'){ + return quickBtns[1]; + } + if(obj == 'reverse'){ + return quickBtns[2]; + } + if(obj == 'skin'){ + return quickBtns[3]; + } + } + return obj; + }); + + $.each(target, (key, val) => { + val.config.btns = btns; + let dd = $(`dl[xid="${key}"]`).find(`.${FORM_SELECT_TIPS}:first`); + if(btns.length){ + let show = config && config.show && (config.show == 'name' || config.show == 'icon') ? config.show : ''; + let html = common.renderBtns(key, show, config && config.space ? config.space : '30px'); + dd.html(html); + }else{ + let pcInput = dd.parents(`.${FORM_SELECT}`).find(`.${TDIV} input`); + let html = pcInput.attr('placeholder') || pcInput.attr('back'); + dd.html(html); + dd.removeAttr('style'); + } + }); + + return this; + } + + Select4.prototype.search = function(id, val){ + if(id && common.check(id)){ + ajaxs[id] = $.extend(true, {}, ajaxs[id] || ajax, { + first: true, + searchVal: val + }); + common.triggerSearch($(`dl[xid="${id}"]`).parents(`.${FORM_SELECT}`), true); + } + return this; + } + + Select4.prototype.replace = function(id, type, config){ + if(!id || !type || !config){ + common.log(`id: ${id} param error !!!`) + return this; + } + if(!common.check(id, true)){ + common.log(`id: ${id} not render !!!`) + return this; + } + let oldVals = this.value(id, 'val'); + this.value(id, []); + this.config(id, config); + if(type == 'local'){ + common.renderData(id, config.arr, config.linkage == true, config.linkageWidth ? config.linkageWidth : '100', false, true); + this.value(id, oldVals, true); + }else if(type == 'server'){ + common.ajax(id, config.url, config.keyword, config.linkage == true, config.linkageWidth ? config.linkageWidth : '100', false, (id) => { + this.value(id, oldVals, true); + }, true); + } + } + + return new Select4(); +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/step.js b/demo/webman/backend/plugin/admin/public/component/pear/module/step.js new file mode 100644 index 0000000000000000000000000000000000000000..4c96d1788571c5c08b70386186365849bf54ce87 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/step.js @@ -0,0 +1,80 @@ +layui.define(['layer', 'carousel'], function (exports) { + var $ = layui.jquery; + var layer = layui.layer; + var carousel = layui.carousel; + + var renderDom = function (elem, stepItems, postion) { + var stepDiv = '
                                                                                          '; + for (var i = 0; i < stepItems.length; i++) { + stepDiv += '
                                                                                          '; + if (i < (stepItems.length - 1)) { + if (i < postion) { + stepDiv += '
                                                                                          '; + } else { + stepDiv += '
                                                                                          '; + } + } + var number = stepItems[i].number; + if (!number) { + number = i + 1; + } + if (i == postion) { + stepDiv += '
                                                                                          ' + number + '
                                                                                          '; + } else if (i < postion) { + stepDiv += '
                                                                                          '; + } else { + stepDiv += '
                                                                                          ' + number + '
                                                                                          '; + } + var title = stepItems[i].title; + var desc = stepItems[i].desc; + var time = stepItems[i].time; + if (title || desc || time) { + stepDiv += '
                                                                                          '; + if (title) { + stepDiv += '
                                                                                          ' + title + '
                                                                                          '; + } + if (desc) { + stepDiv += '
                                                                                          ' + desc + '
                                                                                          '; + } + if (time) { + stepDiv += '
                                                                                          ' + time + '
                                                                                          '; + } + stepDiv += '
                                                                                          '; + } + stepDiv += '
                                                                                          '; + } + stepDiv += '
                                                                                          '; + $(elem).prepend(stepDiv); + var bfb = 100 / stepItems.length; + $('.step-item').css('width', bfb + '%'); + }; + + var pearStep = { + render: function (param) { + param.indicator = 'none'; // 不显示指示器 + param.arrow = 'always'; // 始终显示箭头 + param.autoplay = false; // 关闭自动播放 + if (!param.stepWidth) { + param.stepWidth = '400px'; + } + carousel.render(param); + var stepItems = param.stepItems; + renderDom(param.elem, stepItems, 0); + $('.lay-step').css('width', param.stepWidth); + carousel.on('change(' + param.filter + ')', function (obj) { + $(param.elem).find('.lay-step').remove(); + renderDom(param.elem, stepItems, obj.index); + $('.lay-step').css('width', param.stepWidth); + }); + $(param.elem).find('.layui-carousel-arrow').css('display', 'none'); + $(param.elem).css('background-color', 'transparent'); + }, + next: function (elem) { + $(elem).find('.layui-carousel-arrow[lay-type=add]').trigger('click'); + }, + pre: function (elem) { + $(elem).find('.layui-carousel-arrow[lay-type=sub]').trigger('click'); + } + }; + exports('step', pearStep); +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tab.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tab.js new file mode 100644 index 0000000000000000000000000000000000000000..4284f45d668e4951af17b1f9d385fc7df84d27cd --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tab.js @@ -0,0 +1,663 @@ +layui.define(['jquery', 'element'], function(exports) { + "use strict"; + + var MOD_NAME = 'tab', + $ = layui.jquery, + element = layui.element; + + var pearTab = function(opt) { + this.option = opt; + }; + + var tabData = new Array(); + var tabDataCurrent = 0; + var contextTabDOM; + + pearTab.prototype.render = function(opt) { + + var option = { + elem: opt.elem, + data: opt.data, + tool: opt.tool, + roll: opt.roll, + index: opt.index, + width: opt.width, + height: opt.height, + tabMax: opt.tabMax, + session: opt.session ? opt.session : false, + preload: opt.preload ? opt.preload : false, + closeEvent: opt.closeEvent, + success: opt.success ? opt.success : function(id) {} + } + + if (option.session) { + if (sessionStorage.getItem(option.elem + "-pear-tab-data") != null) { + tabData = JSON.parse(sessionStorage.getItem(option.elem + "-pear-tab-data")); + option.data = JSON.parse(sessionStorage.getItem(option.elem + "-pear-tab-data")); + tabDataCurrent = sessionStorage.getItem(option.elem + "-pear-tab-data-current"); + tabData.forEach(function(item, index) { + if (item.id == tabDataCurrent) { + option.index = index; + } + }) + } else { + tabData = opt.data; + } + } + + var lastIndex; + var tab = createTab(option); + $("#" + option.elem).html(tab); + $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-prev").click(function() { + rollPage("left", option); + }) + $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-next").click(function() { + rollPage("right", option); + }) + element.init(); + toolEvent(option); + $("#" + option.elem).width(opt.width); + $("#" + option.elem).height(opt.height); + $("#" + option.elem).css({ + position: "relative" + }); + closeEvent(option); + + option.success(sessionStorage.getItem(option.elem + "-pear-tab-data-current")); + + $("body .layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title").on("contextmenu", "li", + function(e) { + // 获取当前元素位置 + var top = e.clientY; + var left = e.clientX; + var menuWidth = 100; + var currentId = $(this).attr("lay-id"); + var menu = "
                                                                                          • 关闭当前
                                                                                          • 关闭其他
                                                                                          • 关闭所有
                                                                                          "; + + contextTabDOM = $(this); + var isOutsideBounds = (left + menuWidth) > $(window).width(); + if (isOutsideBounds) { + left = $(window).width() - menuWidth; + } + // 初始化 + layer.open({ + type: 1, + title: false, + shade: false, + skin: 'pear-tab-menu', + closeBtn: false, + area: [menuWidth + 'px', '108px'], + fixed: true, + anim: false, + isOutAnim: false, + offset: [top, left], + content: menu, //iframe的url, + success: function(layero, index) { + layer.close(lastIndex); + lastIndex = index; + menuEvent(option, index); + var timer; + $(layero).on('mouseout', function() { + timer = setTimeout(function() { + layer.close(index); + }, 30) + }); + + $(layero).on('mouseover', function() { + clearTimeout(timer); + }); + + // 清除 item 右击 + $(layero).on('contextmenu', function() { + return false; + }) + + } + }); + return false; + }) + + mousewheelAndTouchmoveHandler(option) + return new pearTab(option); + } + + pearTab.prototype.click = function(callback) { + var elem = this.option.elem; + var option = this.option; + element.on('tab(' + this.option.elem + ')', function(data) { + var id = $("#" + elem + " .layui-tab-title .layui-this").attr("lay-id"); + sessionStorage.setItem(option.elem + "-pear-tab-data-current", id); + if (!option.preload) { + var $iframe = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-content").find( + "iframe[id='" + id + "']"); + var iframeUrl = $iframe.attr("src"); + if (!iframeUrl || iframeUrl === "about:blank") { + // 获取 url 并重载 + tabData.forEach(function(item, index) { + if (item.id === id) { + iframeUrl = item.url; + } + }) + tabIframeLoading(elem); + $iframe.attr("src", iframeUrl); + } + } + callback(id); + }); + } + + pearTab.prototype.positionTab = function() { + var $tabTitle = $('.layui-tab[lay-filter=' + this.option.elem + '] .layui-tab-title'); + var autoLeft = 0; + $tabTitle.children("li").each(function() { + if ($(this).hasClass('layui-this')) { + return false; + } else { + autoLeft += $(this).outerWidth(); + } + }); + $tabTitle.animate({ + scrollLeft: autoLeft - $tabTitle.width() / 3 + }, 200); + } + + pearTab.prototype.clear = function() { + sessionStorage.removeItem(this.option.elem + "-pear-tab-data"); + sessionStorage.removeItem(this.option.elem + "-pear-tab-data-current"); + } + + pearTab.prototype.addTab = function(opt) { + var title = ''; + if (opt.close) { + title += '' + opt.title + + 'ဆ'; + } else { + title += '' + opt.title + + 'ဆ'; + } + element.tabAdd(this.option.elem, { + title: title, + content: '', + id: opt.id + }); + if (time != false && time != 0) { + tabIframeLoading(elem, opt.id); + } + tabData.push(opt); + sessionStorage.setItem(elem + "-pear-tab-data", JSON.stringify(tabData)); + } else { + var isData = false; + $.each($(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title li[lay-id]"), function() { + if ($(this).attr("lay-id") == opt.id) { + isData = true; + } + }) + + if (isData == false) { + element.tabAdd(elem, { + title: title, + content: '', + id: opt.id + }); + if (time != false && time != 0) { + tabIframeLoading(this.option.elem, opt.id); + } + tabData.push(opt); + sessionStorage.setItem(elem + "-pear-tab-data", JSON.stringify(tabData)); + + } + } + sessionStorage.setItem(elem + "-pear-tab-data-current", opt.id); + element.tabChange(elem, opt.id); + } + + /** 添 加 唯 一 选 项 卡 */ + pearTab.prototype.addTabOnly = function(opt, time) { + var title = ''; + if (opt.close) { + title += '' + opt.title + + 'ဆ'; + } else { + title += '' + opt.title + + 'ဆ'; + } + if ($(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title li[lay-id]").length <= + 0) { + element.tabAdd(this.option.elem, { + title: title, + content: '', + id: opt.id + }); + if (time != false && time != 0) { + tabIframeLoading(this.option.elem, opt.id); + } + tabData.push(opt); + sessionStorage.setItem(this.option.elem + "-pear-tab-data", JSON.stringify(tabData)); + sessionStorage.setItem(this.option.elem + "-pear-tab-data-current", opt.id); + } else { + var isData = false; + $.each($(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title li[lay-id]"), + function() { + if ($(this).attr("lay-id") == opt.id) { + isData = true; + } + }) + if (isData == false) { + + if (this.option.tabMax != false) { + if ($(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title li[lay-id]") + .length >= this.option.tabMax) { + layer.msg("最多打开" + this.option.tabMax + "个标签页", { + icon: 2, + time: 1000, + shift: 6 + }); + return false; + } + } + + element.tabAdd(this.option.elem, { + title: title, + content: '', + id: opt.id + }); + if (time != false && time != 0) { + tabIframeLoading(this.option.elem, opt.id); + } + tabData.push(opt); + sessionStorage.setItem(this.option.elem + "-pear-tab-data", JSON.stringify(tabData)); + sessionStorage.setItem(this.option.elem + "-pear-tab-data-current", opt.id); + } + } + element.tabChange(this.option.elem, opt.id); + sessionStorage.setItem(this.option.elem + "-pear-tab-data-current", opt.id); + } + + // 刷 新 指 定 的 选 项 卡 + pearTab.prototype.refresh = function(time) { + // 刷 新 指 定 的 选 项 卡 + var $iframe = $(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-content .layui-show") + .find("iframe"); + if (time != false && time != 0) { + tabIframeLoading(this.option.elem); + } + $iframe.attr("src", $iframe.attr("src")); + } + + function tabIframeLoading(elem, id) { + var load = '
                                                                                          ' + + '
                                                                                          ' + + '' + + '
                                                                                          ' + + '
                                                                                          ' + var $iframe = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-content .layui-show").find("iframe"); + if (id) { + $iframe = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-content").find("iframe[id='" + id + + "']"); + } + $iframe.parent().append(load); + var pearLoad = $("#" + elem).find("#pear-tab-loading" + index); + pearLoad.css({ + display: "block" + }); + index++; + $iframe.on("load", function() { + pearLoad.fadeOut(1000, function() { + pearLoad.remove(); + }); + }) + } + + function tabDelete(elem, id, callback, option) { + //根据 elem id 来删除指定的 layui title li + var tabTitle = $(".layui-tab[lay-filter='" + elem + "']").find(".layui-tab-title"); + + // 删除指定 id 的 title + var removeTab = tabTitle.find("li[lay-id='" + id + "']"); + var nextNode = removeTab.next("li"); + if (!removeTab.hasClass("layui-this")) { + removeTab.remove(); + var tabContent = $(".layui-tab[lay-filter='" + elem + "']").find("iframe[id='" + id + "']") + .parent(); + tabContent.remove(); + + tabData = JSON.parse(sessionStorage.getItem(elem + "-pear-tab-data")); + tabDataCurrent = sessionStorage.getItem(elem + "-pear-tab-data-current"); + tabData = tabData.filter(function(item) { + return item.id != id; + }) + sessionStorage.setItem(elem + "-pear-tab-data", JSON.stringify(tabData)); + return false; + } + + var currId; + if (nextNode.length) { + nextNode.addClass("layui-this"); + currId = nextNode.attr("lay-id"); + $("#" + elem + " [id='" + currId + "']").parent().addClass("layui-show"); + } else { + var prevNode = removeTab.prev("li"); + prevNode.addClass("layui-this"); + currId = prevNode.attr("lay-id"); + $("#" + elem + " [id='" + currId + "']").parent().addClass("layui-show"); + } + callback(currId); + tabData = JSON.parse(sessionStorage.getItem(elem + "-pear-tab-data")); + tabDataCurrent = sessionStorage.getItem(elem + "-pear-tab-data-current"); + tabData = tabData.filter(function(item) { + return item.id != id; + }) + sessionStorage.setItem(elem + "-pear-tab-data", JSON.stringify(tabData)); + sessionStorage.setItem(elem + "-pear-tab-data-current", currId); + + removeTab.remove(); + // 删除 content + var tabContent = $(".layui-tab[lay-filter='" + elem + "']").find("iframe[id='" + id + "']").parent(); + // 删除 + tabContent.remove(); + } + + function createTab(option) { + + var type = ""; + var types = option.type + " "; + if (option.roll == true) { + type = "layui-tab-roll"; + } + if (option.tool != false) { + type = "layui-tab-tool"; + } + if (option.roll == true && option.tool != false) { + type = "layui-tab-rollTool"; + } + var tab = '
                                                                                          '; + var title = '
                                                                                            '; + var content = '
                                                                                            '; + var control = + '
                                                                                            • '; + + // 处 理 选 项 卡 头 部 + var index = 0; + $.each(option.data, function(i, item) { + var TitleItem = ''; + if (option.index == index) { + TitleItem += '
                                                                                            • '; + } else { + TitleItem += '
                                                                                            • '; + } + + if (item.close) { + // 当 前 选 项 卡 可 以 关 闭 + TitleItem += '' + item.title + ''; + } else { + // 当 前 选 项 卡 不 允 许 关 闭 + TitleItem += '' + item.title + ''; + } + TitleItem += 'ဆ
                                                                                            • '; + title += TitleItem; + if (option.index == index) { + + // 处 理 显 示 内 容 + content += '
                                                                                              ' + } else { + if (!option.preload) { + item.url = "about:blank"; + } + // 处 理 显 示 内 容 + content += '
                                                                                              ' + } + index++; + }); + + title += '
                                                                                            '; + content += '
                                                                                          • '; + control += '
                                                                                            关 闭 当 前
                                                                                            ' + control += '
                                                                                            关 闭 其 他
                                                                                            ' + control += '
                                                                                            关 闭 全 部
                                                                                            ' + control += '
                                                                                          '; + + tab += title; + tab += control; + tab += content; + tab += '
                                                                                          '; + tab += '' + return tab; + } + + function rollPage(d, option) { + var $tabTitle = $('#' + option.elem + ' .layui-tab-title'); + var left = $tabTitle.scrollLeft(); + if ('left' === d) { + $tabTitle.animate({ + scrollLeft: left - 450 + }, 200); + } else { + $tabTitle.animate({ + scrollLeft: left + 450 + }, 200); + } + } + + function closeEvent(option) { + $(".layui-tab[lay-filter='" + option.elem + "']").on("click", ".layui-tab-close", function() { + var layid = $(this).parent().attr("lay-id"); + tabDelete(option.elem, layid, option.closeEvent, option); + }) + } + + function menuEvent(option, index) { + + $("#" + option.elem + "closeThis").click(function() { + var currentTab = contextTabDOM; + + if (currentTab.find("span").is(".able-close")) { + var currentId = currentTab.attr("lay-id"); + tabDelete(option.elem, currentId, option.closeEvent, option); + } else { + layer.msg("当前页面不允许关闭", { + icon: 3, + time: 800 + }) + } + layer.close(index); + }) + + $("#" + option.elem + "closeOther").click(function() { + var currentId = contextTabDOM.attr("lay-id"); + var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li"); + $.each(tabtitle, function(i) { + if ($(this).attr("lay-id") != currentId) { + if ($(this).find("span").is(".able-close")) { + tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, + option); + } + } + }) + layer.close(index); + }) + + $("#" + option.elem + "closeAll").click(function() { + var currentId = contextTabDOM.attr("lay-id"); + var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li"); + $.each(tabtitle, function(i) { + if ($(this).find("span").is(".able-close")) { + tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, option); + } + }) + layer.close(index); + }) + } + + function toolEvent(option) { + $("body .layui-tab[lay-filter='" + option.elem + "']").on("click", "#closeThis", function() { + var currentTab = $(".layui-tab[lay-filter='" + option.elem + + "'] .layui-tab-title .layui-this"); + if (currentTab.find("span").is(".able-close")) { + var currentId = currentTab.attr("lay-id"); + tabDelete(option.elem, currentId, option.closeEvent, option); + } else { + layer.msg("当前页面不允许关闭", { + icon: 3, + time: 800 + }) + } + }) + + $("body .layui-tab[lay-filter='" + option.elem + "']").on("click", "#closeOther", function() { + var currentId = $(".layui-tab[lay-filter='" + option.elem + + "'] .layui-tab-title .layui-this").attr("lay-id"); + var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li"); + $.each(tabtitle, function(i) { + if ($(this).attr("lay-id") != currentId) { + if ($(this).find("span").is(".able-close")) { + tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, + option); + } + } + }) + }) + + $("body .layui-tab[lay-filter='" + option.elem + "']").on("click", "#closeAll", function() { + var currentId = $(".layui-tab[lay-filter='" + option.elem + + "'] .layui-tab-title .layui-this").attr("lay-id"); + var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li"); + $.each(tabtitle, function(i) { + if ($(this).find("span").is(".able-close")) { + tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, option); + } + }) + }) + } + + function mousewheelAndTouchmoveHandler(option) { + var $bodyTab = $("body .layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title") + var $tabTitle = $('#' + option.elem + ' .layui-tab-title'); + var mouseScrollStep = 100 + // 鼠标滚轮 + $bodyTab.on("mousewheel DOMMouseScroll", function(e) { + e.originalEvent.preventDefault() + var delta = (e.originalEvent.wheelDelta && (e.originalEvent.wheelDelta > 0 ? "top" : + "down")) || // chrome & ie + (e.originalEvent.detail && (e.originalEvent.detail > 0 ? "down" : "top")); // firefox + var scrollLeft = $tabTitle.scrollLeft(); + + if (delta === "top") { + scrollLeft -= mouseScrollStep + } else if (delta === "down") { + scrollLeft += mouseScrollStep + } + $tabTitle.scrollLeft(scrollLeft) + }); + + // 触摸移动 + var touchX = 0; + $bodyTab.on("touchstart", function(e) { + var touch = e.originalEvent.targetTouches[0]; + touchX = touch.pageX + }) + $bodyTab.on("touchmove", function(e) { + var event = e.originalEvent; + if (event.targetTouches.length > 1) return; + event.preventDefault(); + var touch = event.targetTouches[0]; + var distanceX = touchX - touch.pageX + var scrollLeft = $tabTitle.scrollLeft(); + touchX = touch.pageX + $tabTitle.scrollLeft(scrollLeft += distanceX) + }); + } + + exports(MOD_NAME, new pearTab()); +}) diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tag.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tag.js new file mode 100644 index 0000000000000000000000000000000000000000..b7222ce296ba1ee1f2fe61f303cbd2545b412401 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tag.js @@ -0,0 +1,159 @@ +layui.define('jquery', function(exports){ + "use strict"; + + var $ = layui.$ + ,MOD_NAME = 'tag', + TAG_CLASS = '.tag', + BUTTON_NEW_TAG ='button-new-tag', + INPUT_NEW_TAG ='input-new-tag', + TAG_ITEM ='tag-item', + CLOSE = 'tag-close', + DEFAULT_SKIN ='layui-btn layui-btn-primary layui-btn-sm' + ,tag = function(){ + this.config = { + skin: DEFAULT_SKIN, + tagText:'+ New Tag' + }; + this.configs = {} + }; + + //全局设置 + tag.prototype.set = function(options){ + var that = this; + $.extend(true, that.config, options); + tag.render(); + return that; + }; + + //表单事件监听 + tag.prototype.on = function(events, callback){ + return layui.onevent.call(this, MOD_NAME, events, callback); + }; + + //外部Tag新增 + tag.prototype.add = function(filter, options){ + var tagElem = $(TAG_CLASS + '[lay-filter='+ filter +']') + call.add(null, tagElem, options); + call.tagAuto(filter); + return this; + }; + + //外部Tag删除 + tag.prototype.delete = function(filter, layid){ + var tagElem = $(TAG_CLASS + '[lay-filter='+ filter +']') + ,tagItemElem = tagElem.find('>.' + TAG_ITEM + '[lay-id="'+ layid +'"]'); + call.delete(null, tagItemElem); + return this; + }; + + //基础事件体 + var call = { + //Tag点击 + tagClick: function(e, index, tagItemElem, options){ + options = options || {}; + var othis = tagItemElem || $(this) + ,index = index || othis.index(othis) + ,parents = othis.parents(TAG_CLASS).eq(0) + ,filter = parents.attr('lay-filter'); + layui.event.call(this, MOD_NAME, 'click('+ filter +')', { + elem: parents + ,index: index + }); + } + //Tag新增事件 + ,add: function(e, tagElem, options){ + var filter = tagElem.attr('lay-filter'), + buttonNewTag = tagElem.children('.' + BUTTON_NEW_TAG), + index = buttonNewTag.index() + ,newTag = ''; + var result = layui.event.call(this, MOD_NAME, 'add('+ filter +')', { + elem: tagElem + ,index: index + ,othis: newTag + }) + if(result === false) return; + buttonNewTag[0] ? buttonNewTag.before(newTag) : tagElem.append(newTag); + } + //Tag输入事件 + ,input: function(e, othis){ + var buttonNewTag = othis || $(this) + ,parents = buttonNewTag.parents(TAG_CLASS).eq(0) + ,filter = parents.attr('lay-filter') + var options = tag.configs[filter] = $.extend({}, tag.config, tag.configs[filter] || {}, options); + //标签输入框 + var inpatNewTag = $('
                                                                                          '); + inpatNewTag.addClass(options.skin); + buttonNewTag.after(inpatNewTag).remove(); + inpatNewTag.children('.layui-input').on('blur', function () { + if(this.value){ + var options = { + text: this.value + } + call.add(null, parents, options); + } + inpatNewTag.remove(); + call.tagAuto(filter); + }).focus(); + } + //Tag删除 + ,delete: function(e, othis){ + var tagItem = othis || $(this).parent(), index = tagItem.index() + ,parents = tagItem.parents(TAG_CLASS).eq(0) + ,filter = parents.attr('lay-filter'); + + var result = layui.event.call(this, MOD_NAME, 'delete('+ filter +')', { + elem: parents + ,index: index + }) + if(result === false) return; + tagItem.remove() + } + //Tag 自适应 + ,tagAuto: function(filter){ + filter = filter || ''; + var options = filter ? tag.configs[filter] || tag.config : tag.config; + var elemFilter = function(){ + return filter ? ('[lay-filter="' + filter +'"]') : ''; + }(); + $(TAG_CLASS + elemFilter).each(function(){ + var othis = $(this),tagItem = othis.children('.' + TAG_ITEM), buttonNewTag = othis.children('.' + BUTTON_NEW_TAG); + tagItem.removeClass(DEFAULT_SKIN).addClass(options.skin); + //允许关闭 + if(othis.attr('lay-allowClose') && tagItem.length){ + tagItem.each(function(){ + var li = $(this); + if(!li.find('.'+CLOSE)[0]){ + var close = $('ဆ'); + close.on('click', call.delete); + li.append(close); + } + }); + } + //允许新增标签 + if(othis.attr('lay-newTag') && buttonNewTag.length === 0){ + buttonNewTag = $(''); + buttonNewTag.on('click', call.input); + othis.append(buttonNewTag); + } + buttonNewTag.html(options.tagText); + buttonNewTag.removeClass(DEFAULT_SKIN).addClass(options.skin); + }); + } + }; + + tag.prototype.init = function(filter, options){ + if(filter){ + tag.configs[filter] = $.extend({}, tag.config, tag.configs[filter] || {}, options); + } + return call.tagAuto.call(this, filter); + }; + + tag.prototype.render = tag.prototype.init; + + var tag = new tag(), dom = $(document); + tag.render(); + + dom.on('click', '.' + TAG_ITEM, call.tagClick); //tag 单击事件 + exports(MOD_NAME, tag); +}); + diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/theme.js b/demo/webman/backend/plugin/admin/public/component/pear/module/theme.js new file mode 100644 index 0000000000000000000000000000000000000000..c7b3abfd96bd6be08afdd278d976151552b2f74a --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/theme.js @@ -0,0 +1,110 @@ +layui.define(["jquery","layer"], function (exports) { + var MOD_NAME = 'theme', + $ = layui.jquery; + + var theme = {}; + theme.autoHead = false; + + theme.changeTheme = function (target, autoHead) { + this.autoHead = autoHead; + var color = localStorage.getItem("theme-color-color"); + var second = localStorage.getItem("theme-color-second"); + this.colorSet(color, second); + if (target.frames.length == 0) return; + for (var i = 0; i < target.frames.length; i++) { + try { + if(target.frames[i].layui == undefined) continue; + target.frames[i].layui.theme.changeTheme(target.frames[i], autoHead); + } + catch (error) { + console.log(error); + } + } + } + + theme.colorSet = function(color, second) { + var style = ''; + style += '.light-theme .pear-nav-tree .layui-this a:hover,.light-theme .pear-nav-tree .layui-this,.light-theme .pear-nav-tree .layui-this a,.pear-nav-tree .layui-this a,.pear-nav-tree .layui-this{background-color: ' +color + '!important;}'; + style += '.pear-admin .layui-logo .title{color:' + color + '!important;}'; + style += '.pear-frame-title .dot,.pear-tab .layui-this .pear-tab-active{background-color: ' + color +'!important;}'; + style += '.bottom-nav li a:hover{background-color:' + color + '!important;}'; + style += '.pear-btn-primary {border: 1px solid ' + color + '!important;}'; + style += '.pear-admin .layui-header .layui-nav .layui-nav-bar{background-color: ' + color + '!important;}' + style += '.ball-loader>span,.signal-loader>span {background-color: ' + color + '!important;}'; + style += '.layui-header .layui-nav-child .layui-this a{background-color:' + color +'!important;color:white!important;}'; + style += '#preloader{background-color:' + color + '!important;}'; + style += '.pearone-color .color-content li.layui-this:after, .pearone-color .color-content li:hover:after {border: ' +color + ' 3px solid!important;}'; + style += '.layui-nav .layui-nav-child dd.layui-this a, .layui-nav-child dd.layui-this{background-color:' + color + ';color:white;}'; + style += '.pear-social-entrance {background-color:' + color + '!important}'; + style += '.pear-admin .pe-collapse {background-color:' + color + '!important}'; + style += '.layui-fixbar li {background-color:' + color + '!important}'; + style += '.pear-btn-primary {background-color:' + color + '!important}'; + style += '.layui-input:focus,.layui-textarea:focus {border-color: ' + color + '!important;box-shadow: 0 0 0 3px ' + second + ' !important;}' + style += '.layui-form-checkbox[lay-skin=primary]:hover span {background-color: initial;}' + style += '.layui-form-checked[lay-skin=primary] i {border-color: ' + color + '!important;background-color: ' + color + ';}' + style += '.layui-form-checked,.layui-form-checked:hover {border-color: ' + color + '!important;}' + style += '.layui-form-checked span,.layui-form-checked:hover span {background-color: ' + color + ';}' + style += '.layui-form-checked i,.layui-form-checked:hover i {color: ' + color + ';}' + style += '.layui-form-onswitch { border-color: ' + color + '; background-color: ' + color + ';}' + style += '.layui-form-radio>i:hover, .layui-form-radioed>i {color: ' + color + ';}' + style += '.layui-laypage .layui-laypage-curr .layui-laypage-em{background-color:'+ color +'!important}' + style += '.layui-tab-brief>.layui-tab-more li.layui-this:after, .layui-tab-brief>.layui-tab-title .layui-this:after{border-bottom: 3px solid '+color+'!important}' + style += '.layui-tab-brief>.layui-tab-title .layui-this{color:'+color+'!important}' + style += '.layui-progress-bar{background-color:'+color+'}'; + style += '.layui-elem-quote{border-left: 5px solid '+ color +'}'; + style += '.layui-timeline-axis{color:' + color + '}'; + style += '.layui-laydate .layui-this, .layui-laydate .layui-this div{background-color:'+color+'!important}';//变更 + style += 'xm-select .xm-label .xm-label-block{background-color:'+color+'!important}';//变更 + style += 'xm-select{border-color:#EEE !important}';//变更 + style += 'xm-select .xm-body .xm-option.selected .xm-option-icon{border-color:'+color+'!important;color:'+color+'!important;}';//变更 + style += 'xm-select .xm-body .xm-option .xm-option-icon{border-color:'+color+'!important;}';//变更 + style += 'xm-select > .xm-body .xm-option.selected.hide-icon{background-color:'+color+'!important;}';//变更 + style += 'xm-select > .xm-body .xm-toolbar .toolbar-tag:hover{color:'+color+'!important;}';//变更 + style += '.layui-layer-dialog .layui-layer-content .layui-icon-ok{color:'+color+'!important;}';//变更 + style += '.layui-layer-dialog .layui-layer-content .layui-icon-ok{color:'+color+'!important;}';//变更 + style += 'a{color:'+color+';opacity:.8}';//变更 + style += 'a:hover{color:'+color+';opacity:1}';//变更 + style += '.pear-this,.pear-text{color:' + color + '!important}'; + style += '.pear-back{background-color:'+ color +'!important}'; + style += '.pear-collapsed-pe{background-color:'+color+'!important}' + style += '.layui-form-select dl dd.layui-this{color:'+color+'!important;}' + style += '.tag-item-normal{background:'+color+'!important}'; + style += '.step-item-head.step-item-head-active{background-color:'+color+'}' + style += '.step-item-head{border: 3px solid '+color+';}' + style += '.step-item-tail i{background-color:'+color+'}' + style += '.step-item-head{color:' + color + '}' + style += 'div[xm-select-skin=normal] .xm-select-title div.xm-select-label>span i {background-color:'+color+'!important}' + style += 'div[xm-select-skin=normal] .xm-select-title div.xm-select-label>span{border: 1px solid '+color+'!important;background-color:'+color+'!important}' + style += 'div[xm-select-skin=normal] dl dd:not(.xm-dis-disabled) i{border-color:'+color+'!important}' + style += 'div[xm-select-skin=normal] dl dd.xm-select-this:not(.xm-dis-disabled) i{color:'+color+'!important}' + style += 'div[xm-select-skin=normal].xm-form-selected .xm-select, div[xm-select-skin=normal].xm-form-selected .xm-select:hover{border-color:'+color+'!important}' + style += '.layui-layer-btn a:first-child{border-color:'+color+';background-color:'+color+'!important}'; + style += '.layui-form-checkbox[lay-skin=primary]:hover i{border-color:'+color+'!important}' + style += '.pear-tab-menu .item:hover{background-color:'+color+'!important}' + style += '.layui-form-danger:focus {border-color:#FF5722 !important}' + style += '.pear-admin .user .layui-this a:hover{color:white!important}' + style += '.pear-admin .user a:hover{color:'+color+'!important}' + style += '.pear-notice .layui-this{color:'+color+'!important}' + style += '.layui-form-radio:hover *, .layui-form-radioed, .layui-form-radioed>i{color:' + color + ' !important}'; + style += '.pear-btn:hover {color: '+color+';background-color: ' + second + ';}' + style += '.pear-btn-primary[plain] {color: '+ color +' !important;background: ' + second + ' !important;}' + style += '.pear-btn-primary[plain]:hover {background-color: ' + color + '!important}' + style += '.light-theme .pear-nav-tree .layui-this a:hover,.light-theme .pear-nav-tree .layui-this,.light-theme .pear-nav-tree .layui-this a {background-color:'+second+'!important;color:'+color+'!important;}' + style += '.light-theme .pear-nav-tree .layui-this{ border-right: 3px solid '+color+'!important}' + style += '.loader:after {background:'+color+'}' + if(this.autoHead === true || this.autoHead === "true"){ + style += '.pear-admin.banner-layout .layui-header .layui-logo,.pear-admin .layui-header{border:none;background-color:' + color + '!important;}.pear-admin.banner-layout .layui-header .layui-logo .title,.pear-admin .layui-header .layui-nav .layui-nav-item>a{color:whitesmoke!important;}'; + style += '.pear-admin.banner-layout .layui-header{ box-shadow: 2px 0 6px rgb(0 21 41 / 35%) }' + style += '.pear-admin .layui-header .layui-layout-control .layui-this *,.pear-admin.banner-layout .layui-header .layui-layout-control .layui-this *{ background-color: rgba(0,0,0,.1)!important;}' + } + style += '.menu-search-list li:hover,.menu-search-list li.this{background-color:'+ color +'}' + var colorPane = $("#pear-admin-color"); + if(colorPane.length>0){ + colorPane.html(style); + }else{ + $("head").append("") + } + } + + exports(MOD_NAME, theme); +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce.js new file mode 100644 index 0000000000000000000000000000000000000000..edf993cd72c6173965b5c879c44821c443408e81 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce.js @@ -0,0 +1,219 @@ +layui.define(['jquery'],function (exports) { + var $ = layui.$ + + var modFile = layui.cache.modules['tinymce']; + + var modPath = modFile.substr(0, modFile.lastIndexOf('.')) + + var setter = layui.setter || {} + + var response = setter.response || {} + + var plugin_filename = 'tinymce.min.js'//插件路径,不包含base_url部分 + + var settings = { + base_url: modPath + , relative_urls: false + , remove_script_host: true + , images_upload_url: ''//图片上传接口,可在option传入,也可在这里修改,option的值优先 + , language: 'zh_CN'//语言,可在option传入,也可在这里修改,option的值优先 + , response: {//后台返回数据格式设置 + statusName: response.statusName || 'code'//返回状态字段 + , msgName: response.msgName || 'msg'//返回消息字段 + , dataName: response.dataName || 'data'//返回的数据 + , statusCode: response.statusCode || { + ok: 0//数据正常 + } + } + , success: function (res, succFun, failFun) {//图片上传完成回调 根据自己需要修改 + if (res[this.response.statusName] == this.response.statusCode.ok) { + succFun(res[this.response.dataName]["url"]); + } else { + failFun(res[this.response.msgName]["url"]); + } + } + }; + + // ---------------- 以下代码无需修改 ---------------- + + var t = {}; + + //初始化 + t.render = function (options,callback) { + + initTinymce(); + + var option = initOptions(options,callback) + + ,edit = t.get(option.elem); + + if (edit) { + edit.destroy(); + } + + tinymce.init(option); + + return t.get(option.elem); + }; + + t.init = t.render + + // 获取ID对应的编辑器对象 + t.get = function (elem) { + + initTinymce(); + + if (elem && /^#|\./.test(elem)) { + var id = elem.substr(1); + var edit = tinymce.editors[id]; + return edit + } else { + return false; + } + } + + //重载 + t.reload = function (elem, option, callback) { + + var options = {} + + if(typeof elem == 'string'){ + option.elem = elem + options = $.extend({}, option) + } else if (typeof elem == 'object' && typeof elem.elem == 'string'){ + options = $.extend({}, elem) + callback = option + } + + var optionCache = layui.sessionData('layui-tinymce')[options.elem] + + delete optionCache.init_instance_callback + + $.extend(optionCache,options) + + return t.render(optionCache,callback) + } + + function initOptions(option,callback) { + + var admin = layui.admin || {} + + var form = option.form || {} + + var file_field = form.name || 'edit' //文件字段名 + + var form_data = form.data || {} //其他表单数据 {key:value, ...} + + option.suffix= isset(option.suffix) ? option.suffix : (plugin_filename.indexOf('.min')>-1 ? '.min' : '') + + option.base_url = isset(option.base_url) ? option.base_url : settings.base_url + + option.relative_urls = isset(option.relative_urls) ? option.relative_urls : settings.relative_urls + + option.remove_script_host = isset(option.remove_script_host) ? option.remove_script_host : settings.remove_script_host + + option.language = isset(option.language) ? option.language : settings.language + + option.selector = isset(option.selector) ? option.selector : option.elem + + option.quickbars_selection_toolbar = isset(option.quickbars_selection_toolbar) ? option.quickbars_selection_toolbar : 'cut copy | bold italic underline strikethrough ' + + option.plugins = isset(option.plugins) ? option.plugins : 'code kityformula-editor quickbars print preview searchreplace autolink fullscreen image link media codesample table charmap hr advlist lists wordcount imagetools indent2em'; + + option.toolbar = isset(option.toolbar) ? option.toolbar : 'code undo redo | kityformula-editor forecolor backcolor bold italic underline strikethrough | indent2em alignleft aligncenter alignright alignjustify outdent indent | link bullist numlist image table codesample | formatselect fontselect fontsizeselect'; + + option.resize = isset(option.resize) ? option.resize : false; + + option.elementpath = isset(option.elementpath) ? option.elementpath : false; + + option.branding = isset(option.branding) ? option.branding : false; + + option.contextmenu_never_use_native = isset(option.contextmenu_never_use_native) ? option.contextmenu_never_use_native : true; + + option.menubar = isset(option.menubar) ? option.menubar : 'file edit insert format table'; + + option.menu = isset(option.menu) ? option.menu : { + file: {title: '文件', items: 'newdocument | print preview fullscreen | wordcount'}, + edit: {title: '编辑', items: 'undo redo | cut copy paste pastetext selectall | searchreplace'}, + format: { + title: '格式', + items: 'bold italic underline strikethrough superscript subscript | formats | forecolor backcolor | removeformat' + }, + table: {title: '表格', items: 'inserttable tableprops deletetable | cell row column'}, + }; + + option.init_instance_callback =isset(option.init_instance_callback) ? option.init_instance_callback : function(inst) { + if(typeof callback == 'function') callback(option,inst) + }; + + option.images_upload_url = isset(option.images_upload_url) ? option.images_upload_url : settings.images_upload_url; + + option.images_upload_handler = isset(option.images_upload_handler) ? option.images_upload_handler : function(blobInfo, succFun, failFun) { + if(isEmpty(option.images_upload_url)){ + failFun("上传接口未配置"); + return console.error('images_upload_url未配置'); + } + var formData = new FormData(); + formData.append(file_field, blobInfo.blob()); + if(typeof form_data == 'object'){ + for(var key in form_data){ + formData.append(key, form_data[key]); + } + } + var ajaxOpt = { + url: option.images_upload_url, + dataType: 'json', + type: 'POST', + data: formData, + processData: false, + contentType: false, + success: function (res) { + settings.success(res, succFun, failFun) + }, + error: function (res) { + failFun("网络错误:" + res.status); + } + }; + if (typeof admin.req == 'function') { + admin.req(ajaxOpt); + } else { + $.ajax(ajaxOpt); + } + } + + layui.sessionData('layui-tinymce',{ + key:option.selector, + value:option + }) + return option + } + + function initTinymce() { + if (typeof tinymce == 'undefined') { + $.ajax({//获取插件 + url: settings.base_url + '/' + plugin_filename, + dataType: 'script', + cache: true, + async: false, + }); + } + } + + function isset(value) { + return typeof value !== 'undefined' && value !== null + } + + function isEmpty(value) { + if(typeof value === 'undefined' || value === null|| value === ''){ + return true + } else if (value instanceof Array && value.length === 0){ + return true + } else if (typeof value === 'object' && Object.keys(value).length === 0){ + return true + } + return false + } + + exports('tinymce', t); + +}); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/icons/default/icons.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/icons/default/icons.js new file mode 100644 index 0000000000000000000000000000000000000000..d31c90729dd5f8f653d00f8f772e14fcf94f1634 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/icons/default/icons.js @@ -0,0 +1,172 @@ +tinymce.IconManager.add('default', { + icons: { + 'accessibility-check': '', + 'action-next': '', + 'action-prev': '', + 'align-center': '', + 'align-justify': '', + 'align-left': '', + 'align-none': '', + 'align-right': '', + 'arrow-left': '', + 'arrow-right': '', + 'bold': '', + 'bookmark': '', + 'border-width': '', + 'brightness': '', + 'browse': '', + 'cancel': '', + 'change-case': '', + 'character-count': '', + 'checklist-rtl': '', + 'checklist': '', + 'checkmark': '', + 'chevron-down': '', + 'chevron-left': '', + 'chevron-right': '', + 'chevron-up': '', + 'close': '', + 'code-sample': '', + 'color-levels': '', + 'color-picker': '', + 'color-swatch-remove-color': '', + 'color-swatch': '', + 'comment-add': '', + 'comment': '', + 'contrast': '', + 'copy': '', + 'crop': '', + 'cut-column': '', + 'cut-row': '', + 'cut': '', + 'document-properties': '', + 'drag': '', + 'duplicate-column': '', + 'duplicate-row': '', + 'duplicate': '', + 'edit-block': '', + 'edit-image': '', + 'embed-page': '', + 'embed': '', + 'emoji': '', + 'export': '', + 'fill': '', + 'flip-horizontally': '', + 'flip-vertically': '', + 'format-painter': '', + 'format': '', + 'fullscreen': '', + 'gallery': '', + 'gamma': '', + 'help': '', + 'highlight-bg-color': '', + 'home': '', + 'horizontal-rule': '', + 'image-options': '', + 'image': '', + 'indent': '', + 'info': '', + 'insert-character': '', + 'insert-time': '', + 'invert': '', + 'italic': '', + 'line-height': '', + 'line': '', + 'link': '', + 'list-bull-circle': '', + 'list-bull-default': '', + 'list-bull-square': '', + 'list-num-default-rtl': '', + 'list-num-default': '', + 'list-num-lower-alpha-rtl': '', + 'list-num-lower-alpha': '', + 'list-num-lower-greek-rtl': '', + 'list-num-lower-greek': '', + 'list-num-lower-roman-rtl': '', + 'list-num-lower-roman': '', + 'list-num-upper-alpha-rtl': '', + 'list-num-upper-alpha': '', + 'list-num-upper-roman-rtl': '', + 'list-num-upper-roman': '', + 'lock': '', + 'ltr': '', + 'more-drawer': '', + 'new-document': '', + 'new-tab': '', + 'non-breaking': '', + 'notice': '', + 'ordered-list-rtl': '', + 'ordered-list': '', + 'orientation': '', + 'outdent': '', + 'page-break': '', + 'paragraph': '', + 'paste-column-after': '', + 'paste-column-before': '', + 'paste-row-after': '', + 'paste-row-before': '', + 'paste-text': '', + 'paste': '', + 'permanent-pen': '', + 'plus': '', + 'preferences': '', + 'preview': '', + 'print': '', + 'quote': '', + 'redo': '', + 'reload': '', + 'remove-formatting': '', + 'remove': '', + 'resize-handle': '', + 'resize': '', + 'restore-draft': '', + 'rotate-left': '', + 'rotate-right': '', + 'rtl': '', + 'save': '', + 'search': '', + 'select-all': '', + 'selected': '', + 'settings': '', + 'sharpen': '', + 'sourcecode': '', + 'spell-check': '', + 'strike-through': '', + 'subscript': '', + 'superscript': '', + 'table-cell-properties': '', + 'table-cell-select-all': '', + 'table-cell-select-inner': '', + 'table-delete-column': '', + 'table-delete-row': '', + 'table-delete-table': '', + 'table-insert-column-after': '', + 'table-insert-column-before': '', + 'table-insert-row-above': '', + 'table-insert-row-after': '', + 'table-left-header': '', + 'table-merge-cells': '', + 'table-row-properties': '', + 'table-split-cells': '', + 'table-top-header': '', + 'table': '', + 'template': '', + 'temporary-placeholder': '', + 'text-color': '', + 'toc': '', + 'translate': '', + 'underline': '', + 'undo': '', + 'unlink': '', + 'unlock': '', + 'unordered-list': '', + 'unselected': '', + 'upload': '', + 'user': '', + 'visualblocks': '', + 'visualchars': '', + 'warning': '', + 'zoom-in': '', + 'zoom-out': '', + } +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/icons/default/icons.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/icons/default/icons.min.js new file mode 100644 index 0000000000000000000000000000000000000000..086f297d3278cfd6ef86b01297022f883ff80dd5 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/icons/default/icons.min.js @@ -0,0 +1 @@ +tinymce.IconManager.add("default",{icons:{"accessibility-check":'',"action-next":'',"action-prev":'',"align-center":'',"align-justify":'',"align-left":'',"align-none":'',"align-right":'',"arrow-left":'',"arrow-right":'',bold:'',bookmark:'',"border-width":'',brightness:'',browse:'',cancel:'',"change-case":'',"character-count":'',"checklist-rtl":'',checklist:'',checkmark:'',"chevron-down":'',"chevron-left":'',"chevron-right":'',"chevron-up":'',close:'',"code-sample":'',"color-levels":'',"color-picker":'',"color-swatch-remove-color":'',"color-swatch":'',"comment-add":'',comment:'',contrast:'',copy:'',crop:'',"cut-column":'',"cut-row":'',cut:'',"document-properties":'',drag:'',"duplicate-column":'',"duplicate-row":'',duplicate:'',"edit-block":'',"edit-image":'',"embed-page":'',embed:'',emoji:'',"export":'',fill:'',"flip-horizontally":'',"flip-vertically":'',"format-painter":'',format:'',fullscreen:'',gallery:'',gamma:'',help:'',"highlight-bg-color":'',home:'',"horizontal-rule":'',"image-options":'',image:'',indent:'',info:'',"insert-character":'',"insert-time":'',invert:'',italic:'',"line-height":'',line:'',link:'',"list-bull-circle":'',"list-bull-default":'',"list-bull-square":'',"list-num-default-rtl":'',"list-num-default":'',"list-num-lower-alpha-rtl":'',"list-num-lower-alpha":'',"list-num-lower-greek-rtl":'',"list-num-lower-greek":'',"list-num-lower-roman-rtl":'',"list-num-lower-roman":'',"list-num-upper-alpha-rtl":'',"list-num-upper-alpha":'',"list-num-upper-roman-rtl":'',"list-num-upper-roman":'',lock:'',ltr:'',"more-drawer":'',"new-document":'',"new-tab":'',"non-breaking":'',notice:'',"ordered-list-rtl":'',"ordered-list":'',orientation:'',outdent:'',"page-break":'',paragraph:'',"paste-column-after":'',"paste-column-before":'',"paste-row-after":'',"paste-row-before":'',"paste-text":'',paste:'',"permanent-pen":'',plus:'',preferences:'',preview:'',print:'',quote:'',redo:'',reload:'',"remove-formatting":'',remove:'',"resize-handle":'',resize:'',"restore-draft":'',"rotate-left":'',"rotate-right":'',rtl:'',save:'',search:'',"select-all":'',selected:'',settings:'',sharpen:'',sourcecode:'',"spell-check":'',"strike-through":'',subscript:'',superscript:'',"table-cell-properties":'',"table-cell-select-all":'',"table-cell-select-inner":'',"table-delete-column":'',"table-delete-row":'',"table-delete-table":'',"table-insert-column-after":'',"table-insert-column-before":'',"table-insert-row-above":'',"table-insert-row-after":'',"table-left-header":'',"table-merge-cells":'',"table-row-properties":'',"table-split-cells":'',"table-top-header":'',table:'',template:'',"temporary-placeholder":'',"text-color":'',toc:'',translate:'',underline:'',undo:'',unlink:'',unlock:'',"unordered-list":'',unselected:'',upload:'',user:'',visualblocks:'',visualchars:'',warning:'',"zoom-in":'',"zoom-out":''}}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/langs/readme.md b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/langs/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..a52bf03f9a3ae977eaca0d3f4c406199cc15b023 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/langs/readme.md @@ -0,0 +1,3 @@ +This is where language files should be placed. + +Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/langs/zh_CN.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/langs/zh_CN.js new file mode 100644 index 0000000000000000000000000000000000000000..89b106c296961d5b77563073977757a8bfefeba0 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/langs/zh_CN.js @@ -0,0 +1,419 @@ +tinymce.addI18n('zh_CN',{ +"Redo": "\u91cd\u505a", +"Undo": "\u64a4\u9500", +"Cut": "\u526a\u5207", +"Copy": "\u590d\u5236", +"Paste": "\u7c98\u8d34", +"Select all": "\u5168\u9009", +"New document": "\u65b0\u6587\u4ef6", +"Ok": "\u786e\u5b9a", +"Cancel": "\u53d6\u6d88", +"Visual aids": "\u7f51\u683c\u7ebf", +"Bold": "\u7c97\u4f53", +"Italic": "\u659c\u4f53", +"Underline": "\u4e0b\u5212\u7ebf", +"Strikethrough": "\u5220\u9664\u7ebf", +"Superscript": "\u4e0a\u6807", +"Subscript": "\u4e0b\u6807", +"Clear formatting": "\u6e05\u9664\u683c\u5f0f", +"Align left": "\u5de6\u8fb9\u5bf9\u9f50", +"Align center": "\u4e2d\u95f4\u5bf9\u9f50", +"Align right": "\u53f3\u8fb9\u5bf9\u9f50", +"Justify": "\u4e24\u7aef\u5bf9\u9f50", +"Bullet list": "\u9879\u76ee\u7b26\u53f7", +"Numbered list": "\u7f16\u53f7\u5217\u8868", +"Decrease indent": "\u51cf\u5c11\u7f29\u8fdb", +"Increase indent": "\u589e\u52a0\u7f29\u8fdb", +"Close": "\u5173\u95ed", +"Formats": "\u683c\u5f0f", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u4f60\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u6253\u5f00\u526a\u8d34\u677f\uff0c\u8bf7\u4f7f\u7528Ctrl+X\/C\/V\u7b49\u5feb\u6377\u952e\u3002", +"Headers": "\u6807\u9898", +"Header 1": "\u6807\u98981", +"Header 2": "\u6807\u98982", +"Header 3": "\u6807\u98983", +"Header 4": "\u6807\u98984", +"Header 5": "\u6807\u98985", +"Header 6": "\u6807\u98986", +"Headings": "\u6807\u9898", +"Heading 1": "\u6807\u98981", +"Heading 2": "\u6807\u98982", +"Heading 3": "\u6807\u98983", +"Heading 4": "\u6807\u98984", +"Heading 5": "\u6807\u98985", +"Heading 6": "\u6807\u98986", +"Preformatted": "\u9884\u5148\u683c\u5f0f\u5316\u7684", +"Div": "Div", +"Pre": "Pre", +"Code": "\u4ee3\u7801", +"Paragraph": "\u6bb5\u843d", +"Blockquote": "\u5f15\u6587\u533a\u5757", +"Inline": "\u6587\u672c", +"Blocks": "\u57fa\u5757", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u7c98\u8d34\u6a21\u5f0f\uff0c\u518d\u6b21\u70b9\u51fb\u53ef\u4ee5\u56de\u5230\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002", +"Fonts": "\u5b57\u4f53", +"Font Sizes": "\u5b57\u53f7", +"Class": "\u7c7b\u578b", +"Browse for an image": "\u6d4f\u89c8\u56fe\u50cf", +"OR": "\u6216", +"Drop an image here": "\u62d6\u653e\u4e00\u5f20\u56fe\u50cf\u81f3\u6b64", +"Upload": "\u4e0a\u4f20", +"Block": "\u5757", +"Align": "\u5bf9\u9f50", +"Default": "\u9ed8\u8ba4", +"Circle": "\u7a7a\u5fc3\u5706", +"Disc": "\u5b9e\u5fc3\u5706", +"Square": "\u65b9\u5757", +"Lower Alpha": "\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd", +"Lower Greek": "\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd", +"Lower Roman": "\u5c0f\u5199\u7f57\u9a6c\u5b57\u6bcd", +"Upper Alpha": "\u5927\u5199\u82f1\u6587\u5b57\u6bcd", +"Upper Roman": "\u5927\u5199\u7f57\u9a6c\u5b57\u6bcd", +"Anchor...": "\u951a\u70b9...", +"Name": "\u540d\u79f0", +"Id": "\u6807\u8bc6\u7b26", +"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\u6807\u8bc6\u7b26\u5e94\u8be5\u4ee5\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u8ddf\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002", +"You have unsaved changes are you sure you want to navigate away?": "\u4f60\u8fd8\u6709\u6587\u6863\u5c1a\u672a\u4fdd\u5b58\uff0c\u786e\u5b9a\u8981\u79bb\u5f00\uff1f", +"Restore last draft": "\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f", +"Special character...": "\u7279\u6b8a\u5b57\u7b26...", +"Source code": "\u6e90\u4ee3\u7801", +"Insert\/Edit code sample": "\u63d2\u5165\/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b", +"Language": "\u8bed\u8a00", +"Code sample...": "\u793a\u4f8b\u4ee3\u7801...", +"Color Picker": "\u9009\u8272\u5668", +"R": "R", +"G": "G", +"B": "B", +"Left to right": "\u4ece\u5de6\u5230\u53f3", +"Right to left": "\u4ece\u53f3\u5230\u5de6", +"Emoticons...": "\u8868\u60c5\u7b26\u53f7...", +"Metadata and Document Properties": "\u5143\u6570\u636e\u548c\u6587\u6863\u5c5e\u6027", +"Title": "\u6807\u9898", +"Keywords": "\u5173\u952e\u8bcd", +"Description": "\u63cf\u8ff0", +"Robots": "\u673a\u5668\u4eba", +"Author": "\u4f5c\u8005", +"Encoding": "\u7f16\u7801", +"Fullscreen": "\u5168\u5c4f", +"Action": "\u64cd\u4f5c", +"Shortcut": "\u5feb\u6377\u952e", +"Help": "\u5e2e\u52a9", +"Address": "\u5730\u5740", +"Focus to menubar": "\u79fb\u52a8\u7126\u70b9\u5230\u83dc\u5355\u680f", +"Focus to toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u5de5\u5177\u680f", +"Focus to element path": "\u79fb\u52a8\u7126\u70b9\u5230\u5143\u7d20\u8def\u5f84", +"Focus to contextual toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u4e0a\u4e0b\u6587\u83dc\u5355", +"Insert link (if link plugin activated)": "\u63d2\u5165\u94fe\u63a5 (\u5982\u679c\u94fe\u63a5\u63d2\u4ef6\u5df2\u6fc0\u6d3b)", +"Save (if save plugin activated)": "\u4fdd\u5b58(\u5982\u679c\u4fdd\u5b58\u63d2\u4ef6\u5df2\u6fc0\u6d3b)", +"Find (if searchreplace plugin activated)": "\u67e5\u627e(\u5982\u679c\u67e5\u627e\u66ff\u6362\u63d2\u4ef6\u5df2\u6fc0\u6d3b)", +"Plugins installed ({0}):": "\u5df2\u5b89\u88c5\u63d2\u4ef6 ({0}):", +"Premium plugins:": "\u4f18\u79c0\u63d2\u4ef6\uff1a", +"Learn more...": "\u4e86\u89e3\u66f4\u591a...", +"You are using {0}": "\u4f60\u6b63\u5728\u4f7f\u7528 {0}", +"Plugins": "\u63d2\u4ef6", +"Handy Shortcuts": "\u5feb\u6377\u952e", +"Horizontal line": "\u6c34\u5e73\u5206\u5272\u7ebf", +"Insert\/edit image": "\u63d2\u5165\/\u7f16\u8f91\u56fe\u7247", +"Image description": "\u56fe\u7247\u63cf\u8ff0", +"Source": "\u5730\u5740", +"Dimensions": "\u5927\u5c0f", +"Constrain proportions": "\u4fdd\u6301\u7eb5\u6a2a\u6bd4", +"General": "\u666e\u901a", +"Advanced": "\u9ad8\u7ea7", +"Style": "\u6837\u5f0f", +"Vertical space": "\u5782\u76f4\u8fb9\u8ddd", +"Horizontal space": "\u6c34\u5e73\u8fb9\u8ddd", +"Border": "\u8fb9\u6846", +"Insert image": "\u63d2\u5165\u56fe\u7247", +"Image...": "\u56fe\u7247...", +"Image list": "\u56fe\u7247\u5217\u8868", +"Rotate counterclockwise": "\u9006\u65f6\u9488\u65cb\u8f6c", +"Rotate clockwise": "\u987a\u65f6\u9488\u65cb\u8f6c", +"Flip vertically": "\u5782\u76f4\u7ffb\u8f6c", +"Flip horizontally": "\u6c34\u5e73\u7ffb\u8f6c", +"Edit image": "\u7f16\u8f91\u56fe\u7247", +"Image options": "\u56fe\u7247\u9009\u9879", +"Zoom in": "\u653e\u5927", +"Zoom out": "\u7f29\u5c0f", +"Crop": "\u88c1\u526a", +"Resize": "\u8c03\u6574\u5927\u5c0f", +"Orientation": "\u65b9\u5411", +"Brightness": "\u4eae\u5ea6", +"Sharpen": "\u9510\u5316", +"Contrast": "\u5bf9\u6bd4\u5ea6", +"Color levels": "\u989c\u8272\u5c42\u6b21", +"Gamma": "\u4f3d\u9a6c\u503c", +"Invert": "\u53cd\u8f6c", +"Apply": "\u5e94\u7528", +"Back": "\u540e\u9000", +"Insert date\/time": "\u63d2\u5165\u65e5\u671f\/\u65f6\u95f4", +"Date\/time": "\u65e5\u671f\/\u65f6\u95f4", +"Insert\/Edit Link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5", +"Insert\/edit link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5", +"Text to display": "\u663e\u793a\u6587\u5b57", +"Url": "\u5730\u5740", +"Open link in...": "\u94fe\u63a5\u6253\u5f00\u4f4d\u7f6e...", +"Current window": "\u5f53\u524d\u7a97\u53e3", +"None": "\u65e0", +"New window": "\u5728\u65b0\u7a97\u53e3\u6253\u5f00", +"Remove link": "\u5220\u9664\u94fe\u63a5", +"Anchors": "\u951a\u70b9", +"Link...": "\u94fe\u63a5...", +"Paste or type a link": "\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u4e3a\u90ae\u4ef6\u5730\u5740\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7f00\u5417\uff1f", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u5c5e\u4e8e\u5916\u90e8\u94fe\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp:\/\/:\u524d\u7f00\u5417\uff1f", +"Link list": "\u94fe\u63a5\u5217\u8868", +"Insert video": "\u63d2\u5165\u89c6\u9891", +"Insert\/edit video": "\u63d2\u5165\/\u7f16\u8f91\u89c6\u9891", +"Insert\/edit media": "\u63d2\u5165\/\u7f16\u8f91\u5a92\u4f53", +"Alternative source": "\u955c\u50cf", +"Alternative source URL": "\u66ff\u4ee3\u6765\u6e90\u7f51\u5740", +"Media poster (Image URL)": "\u5c01\u9762(\u56fe\u7247\u5730\u5740)", +"Paste your embed code below:": "\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:", +"Embed": "\u5185\u5d4c", +"Media...": "\u591a\u5a92\u4f53...", +"Nonbreaking space": "\u4e0d\u95f4\u65ad\u7a7a\u683c", +"Page break": "\u5206\u9875\u7b26", +"Paste as text": "\u7c98\u8d34\u4e3a\u6587\u672c", +"Preview": "\u9884\u89c8", +"Print...": "\u6253\u5370...", +"Save": "\u4fdd\u5b58", +"Find": "\u67e5\u627e", +"Replace with": "\u66ff\u6362\u4e3a", +"Replace": "\u66ff\u6362", +"Replace all": "\u5168\u90e8\u66ff\u6362", +"Previous": "\u4e0a\u4e00\u4e2a", +"Next": "\u4e0b\u4e00\u4e2a", +"Find and replace...": "\u67e5\u627e\u5e76\u66ff\u6362...", +"Could not find the specified string.": "\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9.", +"Match case": "\u533a\u5206\u5927\u5c0f\u5199", +"Find whole words only": "\u5168\u5b57\u5339\u914d", +"Spell check": "\u62fc\u5199\u68c0\u67e5", +"Ignore": "\u5ffd\u7565", +"Ignore all": "\u5168\u90e8\u5ffd\u7565", +"Finish": "\u5b8c\u6210", +"Add to Dictionary": "\u6dfb\u52a0\u5230\u5b57\u5178", +"Insert table": "\u63d2\u5165\u8868\u683c", +"Table properties": "\u8868\u683c\u5c5e\u6027", +"Delete table": "\u5220\u9664\u8868\u683c", +"Cell": "\u5355\u5143\u683c", +"Row": "\u884c", +"Column": "\u5217", +"Cell properties": "\u5355\u5143\u683c\u5c5e\u6027", +"Merge cells": "\u5408\u5e76\u5355\u5143\u683c", +"Split cell": "\u62c6\u5206\u5355\u5143\u683c", +"Insert row before": "\u5728\u4e0a\u65b9\u63d2\u5165", +"Insert row after": "\u5728\u4e0b\u65b9\u63d2\u5165", +"Delete row": "\u5220\u9664\u884c", +"Row properties": "\u884c\u5c5e\u6027", +"Cut row": "\u526a\u5207\u884c", +"Copy row": "\u590d\u5236\u884c", +"Paste row before": "\u7c98\u8d34\u5230\u4e0a\u65b9", +"Paste row after": "\u7c98\u8d34\u5230\u4e0b\u65b9", +"Insert column before": "\u5728\u5de6\u4fa7\u63d2\u5165", +"Insert column after": "\u5728\u53f3\u4fa7\u63d2\u5165", +"Delete column": "\u5220\u9664\u5217", +"Cols": "\u5217", +"Rows": "\u884c", +"Width": "\u5bbd", +"Height": "\u9ad8", +"Cell spacing": "\u5355\u5143\u683c\u5916\u95f4\u8ddd", +"Cell padding": "\u5355\u5143\u683c\u5185\u8fb9\u8ddd", +"Show caption": "\u663e\u793a\u6807\u9898", +"Left": "\u5de6\u5bf9\u9f50", +"Center": "\u5c45\u4e2d", +"Right": "\u53f3\u5bf9\u9f50", +"Cell type": "\u5355\u5143\u683c\u7c7b\u578b", +"Scope": "\u8303\u56f4", +"Alignment": "\u5bf9\u9f50\u65b9\u5f0f", +"H Align": "\u6c34\u5e73\u5bf9\u9f50", +"V Align": "\u5782\u76f4\u5bf9\u9f50", +"Top": "\u9876\u90e8\u5bf9\u9f50", +"Middle": "\u5782\u76f4\u5c45\u4e2d", +"Bottom": "\u5e95\u90e8\u5bf9\u9f50", +"Header cell": "\u8868\u5934\u5355\u5143\u683c", +"Row group": "\u884c\u7ec4", +"Column group": "\u5217\u7ec4", +"Row type": "\u884c\u7c7b\u578b", +"Header": "\u8868\u5934", +"Body": "\u8868\u4f53", +"Footer": "\u8868\u5c3e", +"Border color": "\u8fb9\u6846\u989c\u8272", +"Insert template...": "\u63d2\u5165\u6a21\u677f...", +"Templates": "\u6a21\u677f", +"Template": "\u6a21\u677f", +"Text color": "\u6587\u5b57\u989c\u8272", +"Background color": "\u80cc\u666f\u8272", +"Custom...": "\u81ea\u5b9a\u4e49...", +"Custom color": "\u81ea\u5b9a\u4e49\u989c\u8272", +"No color": "\u65e0", +"Remove color": "\u79fb\u9664\u989c\u8272", +"Table of Contents": "\u5185\u5bb9\u5217\u8868", +"Show blocks": "\u663e\u793a\u533a\u5757\u8fb9\u6846", +"Show invisible characters": "\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26", +"Word count": "\u5b57\u6570", +"Count": "\u8ba1\u6570", +"Document": "\u6587\u6863", +"Selection": "\u9009\u62e9", +"Words": "\u5355\u8bcd", +"Words: {0}": "\u5b57\u6570\uff1a{0}", +"{0} words": "{0} \u5b57", +"File": "\u6587\u4ef6", +"Edit": "\u7f16\u8f91", +"Insert": "\u63d2\u5165", +"View": "\u89c6\u56fe", +"Format": "\u683c\u5f0f", +"Table": "\u8868\u683c", +"Tools": "\u5de5\u5177", +"Powered by {0}": "\u7531{0}\u9a71\u52a8", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u5728\u7f16\u8f91\u533a\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9", +"Image title": "\u56fe\u7247\u6807\u9898", +"Border width": "\u8fb9\u6846\u5bbd\u5ea6", +"Border style": "\u8fb9\u6846\u6837\u5f0f", +"Error": "\u9519\u8bef", +"Warn": "\u8b66\u544a", +"Valid": "\u6709\u6548", +"To open the popup, press Shift+Enter": "\u6309Shitf+Enter\u952e\u6253\u5f00\u5bf9\u8bdd\u6846", +"Rich Text Area. Press ALT-0 for help.": "\u7f16\u8f91\u533a\u3002\u6309Alt+0\u952e\u6253\u5f00\u5e2e\u52a9\u3002", +"System Font": "\u7cfb\u7edf\u5b57\u4f53", +"Failed to upload image: {0}": "\u56fe\u7247\u4e0a\u4f20\u5931\u8d25: {0}", +"Failed to load plugin: {0} from url {1}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25: {0} \u6765\u81ea\u94fe\u63a5 {1}", +"Failed to load plugin url: {0}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25 \u94fe\u63a5: {0}", +"Failed to initialize plugin: {0}": "\u63d2\u4ef6\u521d\u59cb\u5316\u5931\u8d25: {0}", +"example": "\u793a\u4f8b", +"Search": "\u641c\u7d22", +"All": "\u5168\u90e8", +"Currency": "\u8d27\u5e01", +"Text": "\u6587\u5b57", +"Quotations": "\u5f15\u7528", +"Mathematical": "\u6570\u5b66", +"Extended Latin": "\u62c9\u4e01\u8bed\u6269\u5145", +"Symbols": "\u7b26\u53f7", +"Arrows": "\u7bad\u5934", +"User Defined": "\u81ea\u5b9a\u4e49", +"dollar sign": "\u7f8e\u5143\u7b26\u53f7", +"currency sign": "\u8d27\u5e01\u7b26\u53f7", +"euro-currency sign": "\u6b27\u5143\u7b26\u53f7", +"colon sign": "\u5192\u53f7", +"cruzeiro sign": "\u514b\u9c81\u8d5b\u7f57\u5e01\u7b26\u53f7", +"french franc sign": "\u6cd5\u90ce\u7b26\u53f7", +"lira sign": "\u91cc\u62c9\u7b26\u53f7", +"mill sign": "\u5bc6\u5c14\u7b26\u53f7", +"naira sign": "\u5948\u62c9\u7b26\u53f7", +"peseta sign": "\u6bd4\u585e\u5854\u7b26\u53f7", +"rupee sign": "\u5362\u6bd4\u7b26\u53f7", +"won sign": "\u97e9\u5143\u7b26\u53f7", +"new sheqel sign": "\u65b0\u8c22\u514b\u5c14\u7b26\u53f7", +"dong sign": "\u8d8a\u5357\u76fe\u7b26\u53f7", +"kip sign": "\u8001\u631d\u57fa\u666e\u7b26\u53f7", +"tugrik sign": "\u56fe\u683c\u91cc\u514b\u7b26\u53f7", +"drachma sign": "\u5fb7\u62c9\u514b\u9a6c\u7b26\u53f7", +"german penny symbol": "\u5fb7\u56fd\u4fbf\u58eb\u7b26\u53f7", +"peso sign": "\u6bd4\u7d22\u7b26\u53f7", +"guarani sign": "\u74dc\u62c9\u5c3c\u7b26\u53f7", +"austral sign": "\u6fb3\u5143\u7b26\u53f7", +"hryvnia sign": "\u683c\u91cc\u592b\u5c3c\u4e9a\u7b26\u53f7", +"cedi sign": "\u585e\u5730\u7b26\u53f7", +"livre tournois sign": "\u91cc\u5f17\u5f17\u5c14\u7b26\u53f7", +"spesmilo sign": "spesmilo\u7b26\u53f7", +"tenge sign": "\u575a\u6208\u7b26\u53f7", +"indian rupee sign": "\u5370\u5ea6\u5362\u6bd4", +"turkish lira sign": "\u571f\u8033\u5176\u91cc\u62c9", +"nordic mark sign": "\u5317\u6b27\u9a6c\u514b", +"manat sign": "\u9a6c\u7eb3\u7279\u7b26\u53f7", +"ruble sign": "\u5362\u5e03\u7b26\u53f7", +"yen character": "\u65e5\u5143\u5b57\u6837", +"yuan character": "\u4eba\u6c11\u5e01\u5143\u5b57\u6837", +"yuan character, in hong kong and taiwan": "\u5143\u5b57\u6837\uff08\u6e2f\u53f0\u5730\u533a\uff09", +"yen\/yuan character variant one": "\u5143\u5b57\u6837\uff08\u5927\u5199\uff09", +"Loading emoticons...": "\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7...", +"Could not load emoticons": "\u4e0d\u80fd\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7", +"People": "\u4eba\u7c7b", +"Animals and Nature": "\u52a8\u7269\u548c\u81ea\u7136", +"Food and Drink": "\u98df\u7269\u548c\u996e\u54c1", +"Activity": "\u6d3b\u52a8", +"Travel and Places": "\u65c5\u6e38\u548c\u5730\u70b9", +"Objects": "\u7269\u4ef6", +"Flags": "\u65d7\u5e1c", +"Characters": "\u5b57\u7b26", +"Characters (no spaces)": "\u5b57\u7b26(\u65e0\u7a7a\u683c)", +"{0} characters": "{0} \u4e2a\u5b57\u7b26", +"Error: Form submit field collision.": "\u9519\u8bef: \u8868\u5355\u63d0\u4ea4\u5b57\u6bb5\u51b2\u7a81\u3002", +"Error: No form element found.": "\u9519\u8bef: \u6ca1\u6709\u8868\u5355\u63a7\u4ef6\u3002", +"Update": "\u66f4\u65b0", +"Color swatch": "\u989c\u8272\u6837\u672c", +"Turquoise": "\u9752\u7eff\u8272", +"Green": "\u7eff\u8272", +"Blue": "\u84dd\u8272", +"Purple": "\u7d2b\u8272", +"Navy Blue": "\u6d77\u519b\u84dd", +"Dark Turquoise": "\u6df1\u84dd\u7eff\u8272", +"Dark Green": "\u6df1\u7eff\u8272", +"Medium Blue": "\u4e2d\u84dd\u8272", +"Medium Purple": "\u4e2d\u7d2b\u8272", +"Midnight Blue": "\u6df1\u84dd\u8272", +"Yellow": "\u9ec4\u8272", +"Orange": "\u6a59\u8272", +"Red": "\u7ea2\u8272", +"Light Gray": "\u6d45\u7070\u8272", +"Gray": "\u7070\u8272", +"Dark Yellow": "\u6697\u9ec4\u8272", +"Dark Orange": "\u6df1\u6a59\u8272", +"Dark Red": "\u6df1\u7ea2\u8272", +"Medium Gray": "\u4e2d\u7070\u8272", +"Dark Gray": "\u6df1\u7070\u8272", +"Light Green": "\u6d45\u7eff\u8272", +"Light Yellow": "\u6d45\u9ec4\u8272", +"Light Red": "\u6d45\u7ea2\u8272", +"Light Purple": "\u6d45\u7d2b\u8272", +"Light Blue": "\u6d45\u84dd\u8272", +"Dark Purple": "\u6df1\u7d2b\u8272", +"Dark Blue": "\u6df1\u84dd\u8272", +"Black": "\u9ed1\u8272", +"White": "\u767d\u8272", +"Switch to or from fullscreen mode": "\u5207\u6362\u5168\u5c4f\u6a21\u5f0f", +"Open help dialog": "\u6253\u5f00\u5e2e\u52a9\u5bf9\u8bdd\u6846", +"history": "\u5386\u53f2", +"styles": "\u6837\u5f0f", +"formatting": "\u683c\u5f0f\u5316", +"alignment": "\u5bf9\u9f50", +"indentation": "\u7f29\u8fdb", +"permanent pen": "\u8bb0\u53f7\u7b14", +"comments": "\u5907\u6ce8", +"Format Painter": "\u683c\u5f0f\u5237", +"Insert\/edit iframe": "\u63d2\u5165\/\u7f16\u8f91\u6846\u67b6", +"Capitalization": "\u5927\u5199", +"lowercase": "\u5c0f\u5199", +"UPPERCASE": "\u5927\u5199", +"Title Case": "\u9996\u5b57\u6bcd\u5927\u5199", +"Permanent Pen Properties": "\u6c38\u4e45\u7b14\u5c5e\u6027", +"Permanent pen properties...": "\u6c38\u4e45\u7b14\u5c5e\u6027...", +"Font": "\u5b57\u4f53", +"Size": "\u5b57\u53f7", +"More...": "\u66f4\u591a...", +"Spellcheck Language": "\u62fc\u5199\u68c0\u67e5\u8bed\u8a00", +"Select...": "\u9009\u62e9...", +"Preferences": "\u9996\u9009\u9879", +"Yes": "\u662f", +"No": "\u5426", +"Keyboard Navigation": "\u952e\u76d8\u6307\u5f15", +"Version": "\u7248\u672c", +"Anchor": "\u951a\u70b9", +"Special character": "\u7279\u6b8a\u7b26\u53f7", +"Code sample": "\u4ee3\u7801\u793a\u4f8b", +"Color": "\u989c\u8272", +"Emoticons": "\u8868\u60c5", +"Document properties": "\u6587\u6863\u5c5e\u6027", +"Image": "\u56fe\u7247", +"Insert link": "\u63d2\u5165\u94fe\u63a5", +"Target": "\u6253\u5f00\u65b9\u5f0f", +"Link": "\u94fe\u63a5", +"Poster": "\u5c01\u9762", +"Media": "\u5a92\u4f53", +"Print": "\u6253\u5370", +"Prev": "\u4e0a\u4e00\u4e2a", +"Find and replace": "\u67e5\u627e\u548c\u66ff\u6362", +"Whole words": "\u5168\u5b57\u5339\u914d", +"Spellcheck": "\u62fc\u5199\u68c0\u67e5", +"Caption": "\u6807\u9898", +"Insert template": "\u63d2\u5165\u6a21\u677f" +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/advlist/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/advlist/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..0dd07b0660256bb5730d03a6dadcb61b93320626 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/advlist/plugin.js @@ -0,0 +1,278 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var applyListFormat = function (editor, listName, styleValue) { + var cmd = listName === 'UL' ? 'InsertUnorderedList' : 'InsertOrderedList'; + editor.execCommand(cmd, false, styleValue === false ? null : { 'list-style-type': styleValue }); + }; + + var register = function (editor) { + editor.addCommand('ApplyUnorderedListStyle', function (ui, value) { + applyListFormat(editor, 'UL', value['list-style-type']); + }); + editor.addCommand('ApplyOrderedListStyle', function (ui, value) { + applyListFormat(editor, 'OL', value['list-style-type']); + }); + }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var getNumberStyles = function (editor) { + var styles = editor.getParam('advlist_number_styles', 'default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman'); + return styles ? styles.split(/[ ,]/) : []; + }; + var getBulletStyles = function (editor) { + var styles = editor.getParam('advlist_bullet_styles', 'default,circle,square'); + return styles ? styles.split(/[ ,]/) : []; + }; + + var noop = function () { + }; + var constant = function (value) { + return function () { + return value; + }; + }; + var never = constant(false); + var always = constant(true); + + var none = function () { + return NONE; + }; + var NONE = function () { + var eq = function (o) { + return o.isNone(); + }; + var call = function (thunk) { + return thunk(); + }; + var id = function (n) { + return n; + }; + var me = { + fold: function (n, _s) { + return n(); + }, + is: never, + isSome: never, + isNone: always, + getOr: id, + getOrThunk: call, + getOrDie: function (msg) { + throw new Error(msg || 'error: getOrDie called on none.'); + }, + getOrNull: constant(null), + getOrUndefined: constant(undefined), + or: id, + orThunk: call, + map: none, + each: noop, + bind: none, + exists: never, + forall: always, + filter: none, + equals: eq, + equals_: eq, + toArray: function () { + return []; + }, + toString: constant('none()') + }; + return me; + }(); + var some = function (a) { + var constant_a = constant(a); + var self = function () { + return me; + }; + var bind = function (f) { + return f(a); + }; + var me = { + fold: function (n, s) { + return s(a); + }, + is: function (v) { + return a === v; + }, + isSome: always, + isNone: never, + getOr: constant_a, + getOrThunk: constant_a, + getOrDie: constant_a, + getOrNull: constant_a, + getOrUndefined: constant_a, + or: self, + orThunk: self, + map: function (f) { + return some(f(a)); + }, + each: function (f) { + f(a); + }, + bind: bind, + exists: bind, + forall: bind, + filter: function (f) { + return f(a) ? me : NONE; + }, + toArray: function () { + return [a]; + }, + toString: function () { + return 'some(' + a + ')'; + }, + equals: function (o) { + return o.is(a); + }, + equals_: function (o, elementEq) { + return o.fold(never, function (b) { + return elementEq(a, b); + }); + } + }; + return me; + }; + var from = function (value) { + return value === null || value === undefined ? NONE : some(value); + }; + var Optional = { + some: some, + none: none, + from: from + }; + + var isChildOfBody = function (editor, elm) { + return editor.$.contains(editor.getBody(), elm); + }; + var isTableCellNode = function (node) { + return node && /^(TH|TD)$/.test(node.nodeName); + }; + var isListNode = function (editor) { + return function (node) { + return node && /^(OL|UL|DL)$/.test(node.nodeName) && isChildOfBody(editor, node); + }; + }; + var getSelectedStyleType = function (editor) { + var listElm = editor.dom.getParent(editor.selection.getNode(), 'ol,ul'); + var style = editor.dom.getStyle(listElm, 'listStyleType'); + return Optional.from(style); + }; + + var findIndex = function (list, predicate) { + for (var index = 0; index < list.length; index++) { + var element = list[index]; + if (predicate(element)) { + return index; + } + } + return -1; + }; + var styleValueToText = function (styleValue) { + return styleValue.replace(/\-/g, ' ').replace(/\b\w/g, function (chr) { + return chr.toUpperCase(); + }); + }; + var isWithinList = function (editor, e, nodeName) { + var tableCellIndex = findIndex(e.parents, isTableCellNode); + var parents = tableCellIndex !== -1 ? e.parents.slice(0, tableCellIndex) : e.parents; + var lists = global$1.grep(parents, isListNode(editor)); + return lists.length > 0 && lists[0].nodeName === nodeName; + }; + var addSplitButton = function (editor, id, tooltip, cmd, nodeName, styles) { + editor.ui.registry.addSplitButton(id, { + tooltip: tooltip, + icon: nodeName === 'OL' ? 'ordered-list' : 'unordered-list', + presets: 'listpreview', + columns: 3, + fetch: function (callback) { + var items = global$1.map(styles, function (styleValue) { + var iconStyle = nodeName === 'OL' ? 'num' : 'bull'; + var iconName = styleValue === 'disc' || styleValue === 'decimal' ? 'default' : styleValue; + var itemValue = styleValue === 'default' ? '' : styleValue; + var displayText = styleValueToText(styleValue); + return { + type: 'choiceitem', + value: itemValue, + icon: 'list-' + iconStyle + '-' + iconName, + text: displayText + }; + }); + callback(items); + }, + onAction: function () { + return editor.execCommand(cmd); + }, + onItemAction: function (_splitButtonApi, value) { + applyListFormat(editor, nodeName, value); + }, + select: function (value) { + var listStyleType = getSelectedStyleType(editor); + return listStyleType.map(function (listStyle) { + return value === listStyle; + }).getOr(false); + }, + onSetup: function (api) { + var nodeChangeHandler = function (e) { + api.setActive(isWithinList(editor, e, nodeName)); + }; + editor.on('NodeChange', nodeChangeHandler); + return function () { + return editor.off('NodeChange', nodeChangeHandler); + }; + } + }); + }; + var addButton = function (editor, id, tooltip, cmd, nodeName, _styles) { + editor.ui.registry.addToggleButton(id, { + active: false, + tooltip: tooltip, + icon: nodeName === 'OL' ? 'ordered-list' : 'unordered-list', + onSetup: function (api) { + var nodeChangeHandler = function (e) { + api.setActive(isWithinList(editor, e, nodeName)); + }; + editor.on('NodeChange', nodeChangeHandler); + return function () { + return editor.off('NodeChange', nodeChangeHandler); + }; + }, + onAction: function () { + return editor.execCommand(cmd); + } + }); + }; + var addControl = function (editor, id, tooltip, cmd, nodeName, styles) { + if (styles.length > 1) { + addSplitButton(editor, id, tooltip, cmd, nodeName, styles); + } else { + addButton(editor, id, tooltip, cmd, nodeName); + } + }; + var register$1 = function (editor) { + addControl(editor, 'numlist', 'Numbered list', 'InsertOrderedList', 'OL', getNumberStyles(editor)); + addControl(editor, 'bullist', 'Bullet list', 'InsertUnorderedList', 'UL', getBulletStyles(editor)); + }; + + function Plugin () { + global.add('advlist', function (editor) { + if (editor.hasPlugin('lists')) { + register$1(editor); + register(editor); + } + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/advlist/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/advlist/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..dfa80d9ae746cd6af06417ab91da6d6876ca9dc1 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/advlist/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var n,e,t,r=tinymce.util.Tools.resolve("tinymce.PluginManager"),u=function(n,e,t){var r="UL"===e?"InsertUnorderedList":"InsertOrderedList";n.execCommand(r,!1,!1===t?null:{"list-style-type":t})},l=tinymce.util.Tools.resolve("tinymce.util.Tools"),i=function(n){return function(){return n}},c=i(!1),s=i(!0),o=function(){return a},a=(n=function(n){return n.isNone()},{fold:function(n,e){return n()},is:c,isSome:c,isNone:s,getOr:t=function(n){return n},getOrThunk:e=function(n){return n()},getOrDie:function(n){throw new Error(n||"error: getOrDie called on none.")},getOrNull:i(null),getOrUndefined:i(undefined),or:t,orThunk:e,map:o,each:function(){},bind:o,exists:c,forall:s,filter:o,equals:n,equals_:n,toArray:function(){return[]},toString:i("none()")}),f=function(t){var n=i(t),e=function(){return o},r=function(n){return n(t)},o={fold:function(n,e){return e(t)},is:function(n){return t===n},isSome:s,isNone:c,getOr:n,getOrThunk:n,getOrDie:n,getOrNull:n,getOrUndefined:n,or:e,orThunk:e,map:function(n){return f(n(t))},each:function(n){n(t)},bind:r,exists:r,forall:r,filter:function(n){return n(t)?o:a},toArray:function(){return[t]},toString:function(){return"some("+t+")"},equals:function(n){return n.is(t)},equals_:function(n,e){return n.fold(c,function(n){return e(t,n)})}};return o},d=function(n){return null===n||n===undefined?a:f(n)},g=function(n){return n&&/^(TH|TD)$/.test(n.nodeName)},m=function(r){return function(n){return n&&/^(OL|UL|DL)$/.test(n.nodeName)&&(t=n,(e=r).$.contains(e.getBody(),t));var e,t}},p=function(n,e,t){var r=function(n,e){for(var t=0;t len) { + index = len; + } + } + return index; + }; + var setStart = function (rng, container, offset) { + if (container.nodeType !== 1 || container.hasChildNodes()) { + rng.setStart(container, scopeIndex(container, offset)); + } else { + rng.setStartBefore(container); + } + }; + var setEnd = function (rng, container, offset) { + if (container.nodeType !== 1 || container.hasChildNodes()) { + rng.setEnd(container, scopeIndex(container, offset)); + } else { + rng.setEndAfter(container); + } + }; + var parseCurrentLine = function (editor, endOffset, delimiter) { + var end, endContainer, bookmark, text, prev, len, rngText; + var autoLinkPattern = getAutoLinkPattern(editor); + var defaultLinkTarget = getDefaultLinkTarget(editor); + if (editor.selection.getNode().tagName === 'A') { + return; + } + var rng = editor.selection.getRng().cloneRange(); + if (rng.startOffset < 5) { + prev = rng.endContainer.previousSibling; + if (!prev) { + if (!rng.endContainer.firstChild || !rng.endContainer.firstChild.nextSibling) { + return; + } + prev = rng.endContainer.firstChild.nextSibling; + } + len = prev.length; + setStart(rng, prev, len); + setEnd(rng, prev, len); + if (rng.endOffset < 5) { + return; + } + end = rng.endOffset; + endContainer = prev; + } else { + endContainer = rng.endContainer; + if (endContainer.nodeType !== 3 && endContainer.firstChild) { + while (endContainer.nodeType !== 3 && endContainer.firstChild) { + endContainer = endContainer.firstChild; + } + if (endContainer.nodeType === 3) { + setStart(rng, endContainer, 0); + setEnd(rng, endContainer, endContainer.nodeValue.length); + } + } + if (rng.endOffset === 1) { + end = 2; + } else { + end = rng.endOffset - 1 - endOffset; + } + } + var start = end; + do { + setStart(rng, endContainer, end >= 2 ? end - 2 : 0); + setEnd(rng, endContainer, end >= 1 ? end - 1 : 0); + end -= 1; + rngText = rng.toString(); + } while (rngText !== ' ' && rngText !== '' && rngText.charCodeAt(0) !== 160 && end - 2 >= 0 && rngText !== delimiter); + if (rangeEqualsDelimiterOrSpace(rng.toString(), delimiter)) { + setStart(rng, endContainer, end); + setEnd(rng, endContainer, start); + end += 1; + } else if (rng.startOffset === 0) { + setStart(rng, endContainer, 0); + setEnd(rng, endContainer, start); + } else { + setStart(rng, endContainer, end); + setEnd(rng, endContainer, start); + } + text = rng.toString(); + if (text.charAt(text.length - 1) === '.') { + setEnd(rng, endContainer, start - 1); + } + text = rng.toString().trim(); + var matches = text.match(autoLinkPattern); + var protocol = getDefaultLinkProtocol(editor); + if (matches) { + if (matches[1] === 'www.') { + matches[1] = protocol + '://www.'; + } else if (/@$/.test(matches[1]) && !/^mailto:/.test(matches[1])) { + matches[1] = 'mailto:' + matches[1]; + } + bookmark = editor.selection.getBookmark(); + editor.selection.setRng(rng); + editor.execCommand('createlink', false, matches[1] + matches[2]); + if (defaultLinkTarget !== false) { + editor.dom.setAttrib(editor.selection.getNode(), 'target', defaultLinkTarget); + } + editor.selection.moveToBookmark(bookmark); + editor.nodeChanged(); + } + }; + var setup = function (editor) { + var autoUrlDetectState; + editor.on('keydown', function (e) { + if (e.keyCode === 13) { + return handleEnter(editor); + } + }); + if (global$1.browser.isIE()) { + editor.on('focus', function () { + if (!autoUrlDetectState) { + autoUrlDetectState = true; + try { + editor.execCommand('AutoUrlDetect', false, true); + } catch (ex) { + } + } + }); + return; + } + editor.on('keypress', function (e) { + if (e.keyCode === 41) { + return handleEclipse(editor); + } + }); + editor.on('keyup', function (e) { + if (e.keyCode === 32) { + return handleSpacebar(editor); + } + }); + }; + + function Plugin () { + global.add('autolink', function (editor) { + setup(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/autolink/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/autolink/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..244005414ba8a9b59c7c5462e04a8c580cf31427 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/autolink/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),o=tinymce.util.Tools.resolve("tinymce.Env"),i=function(e,t){var n;return t<0&&(t=0),3!==e.nodeType||(n=e.data.length) getAutoResizeMinHeight(editor)) { + resizeHeight = contentHeight + chromeHeight; + } + var maxHeight = getAutoResizeMaxHeight(editor); + if (maxHeight && resizeHeight > maxHeight) { + resizeHeight = maxHeight; + toggleScrolling(editor, true); + } else { + toggleScrolling(editor, false); + } + if (resizeHeight !== oldSize.get()) { + var deltaSize = resizeHeight - oldSize.get(); + dom.setStyle(editor.getContainer(), 'height', resizeHeight + 'px'); + oldSize.set(resizeHeight); + fireResizeEditor(editor); + if (global$1.browser.isSafari() && global$1.mac) { + var win = editor.getWin(); + win.scrollTo(win.pageXOffset, win.pageYOffset); + } + if (editor.hasFocus()) { + editor.selection.scrollIntoView(editor.selection.getNode()); + } + if (global$1.webkit && deltaSize < 0) { + resize(editor, oldSize); + } + } + }; + var setup = function (editor, oldSize) { + editor.on('init', function () { + var overflowPadding = getAutoResizeOverflowPadding(editor); + var dom = editor.dom; + dom.setStyles(editor.getDoc().documentElement, { height: 'auto' }); + dom.setStyles(editor.getBody(), { + 'paddingLeft': overflowPadding, + 'paddingRight': overflowPadding, + 'min-height': 0 + }); + }); + editor.on('NodeChange SetContent keyup FullscreenStateChanged ResizeContent', function () { + resize(editor, oldSize); + }); + if (shouldAutoResizeOnInit(editor)) { + editor.on('init', function () { + wait(editor, oldSize, 20, 100, function () { + wait(editor, oldSize, 5, 1000); + }); + }); + } + }; + + var register = function (editor, oldSize) { + editor.addCommand('mceAutoResize', function () { + resize(editor, oldSize); + }); + }; + + function Plugin () { + global.add('autoresize', function (editor) { + if (!editor.settings.hasOwnProperty('resize')) { + editor.settings.resize = false; + } + if (!editor.inline) { + var oldSize = Cell(0); + register(editor, oldSize); + setup(editor, oldSize); + } + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/autoresize/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/autoresize/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..01cb7d5383df5816d4c610fb679ceaeadd16d04e --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/autoresize/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),h=tinymce.util.Tools.resolve("tinymce.Env"),r=tinymce.util.Tools.resolve("tinymce.util.Delay"),y=function(e){return e.getParam("min_height",e.getElement().offsetHeight,"number")},a=function(e,t,n,i,o){r.setEditorTimeout(e,function(){b(e,t),n--?a(e,t,n,i,o):o&&o()},i)},p=function(e,t){var n=e.getBody();n&&(n.style.overflowY=t?"":"hidden",t||(n.scrollTop=0))},v=function(e,t,n,i){var o=parseInt(e.getStyle(t,n,i),10);return isNaN(o)?0:o},b=function(e,t){var n,i,o,r,s,a,g,u,l,c,m,f=e.dom,d=e.getDoc();d&&((n=e).plugins.fullscreen&&n.plugins.fullscreen.isFullscreen()?p(e,!0):(i=d.documentElement,o=e.getParam("autoresize_bottom_margin",50,"number"),r=y(e),s=v(f,i,"margin-top",!0),a=v(f,i,"margin-bottom",!0),(g=i.offsetHeight+s+a+o)<0&&(g=0),g+(u=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight)>y(e)&&(r=g+u),(l=e.getParam("max_height",0,"number"))&&l getAutoSaveRetention(editor)) { + removeDraft(editor, false); + return false; + } + return true; + }; + var removeDraft = function (editor, fire) { + var prefix = getAutoSavePrefix(editor); + global$2.removeItem(prefix + 'draft'); + global$2.removeItem(prefix + 'time'); + if (fire !== false) { + fireRemoveDraft(editor); + } + }; + var storeDraft = function (editor) { + var prefix = getAutoSavePrefix(editor); + if (!isEmpty(editor) && editor.isDirty()) { + global$2.setItem(prefix + 'draft', editor.getContent({ + format: 'raw', + no_events: true + })); + global$2.setItem(prefix + 'time', new Date().getTime().toString()); + fireStoreDraft(editor); + } + }; + var restoreDraft = function (editor) { + var prefix = getAutoSavePrefix(editor); + if (hasDraft(editor)) { + editor.setContent(global$2.getItem(prefix + 'draft'), { format: 'raw' }); + fireRestoreDraft(editor); + } + }; + var startStoreDraft = function (editor) { + var interval = getAutoSaveInterval(editor); + global$1.setEditorInterval(editor, function () { + storeDraft(editor); + }, interval); + }; + var restoreLastDraft = function (editor) { + editor.undoManager.transact(function () { + restoreDraft(editor); + removeDraft(editor); + }); + editor.focus(); + }; + + var get = function (editor) { + return { + hasDraft: function () { + return hasDraft(editor); + }, + storeDraft: function () { + return storeDraft(editor); + }, + restoreDraft: function () { + return restoreDraft(editor); + }, + removeDraft: function (fire) { + return removeDraft(editor, fire); + }, + isEmpty: function (html) { + return isEmpty(editor, html); + } + }; + }; + + var global$4 = tinymce.util.Tools.resolve('tinymce.EditorManager'); + + var setup = function (editor) { + editor.editorManager.on('BeforeUnload', function (e) { + var msg; + global$3.each(global$4.get(), function (editor) { + if (editor.plugins.autosave) { + editor.plugins.autosave.storeDraft(); + } + if (!msg && editor.isDirty() && shouldAskBeforeUnload(editor)) { + msg = editor.translate('You have unsaved changes are you sure you want to navigate away?'); + } + }); + if (msg) { + e.preventDefault(); + e.returnValue = msg; + } + }); + }; + + var makeSetupHandler = function (editor) { + return function (api) { + api.setDisabled(!hasDraft(editor)); + var editorEventCallback = function () { + return api.setDisabled(!hasDraft(editor)); + }; + editor.on('StoreDraft RestoreDraft RemoveDraft', editorEventCallback); + return function () { + return editor.off('StoreDraft RestoreDraft RemoveDraft', editorEventCallback); + }; + }; + }; + var register = function (editor) { + startStoreDraft(editor); + editor.ui.registry.addButton('restoredraft', { + tooltip: 'Restore last draft', + icon: 'restore-draft', + onAction: function () { + restoreLastDraft(editor); + }, + onSetup: makeSetupHandler(editor) + }); + editor.ui.registry.addMenuItem('restoredraft', { + text: 'Restore last draft', + icon: 'restore-draft', + onAction: function () { + restoreLastDraft(editor); + }, + onSetup: makeSetupHandler(editor) + }); + }; + + function Plugin () { + global.add('autosave', function (editor) { + setup(editor); + register(editor); + editor.on('init', function () { + if (shouldRestoreWhenEmpty(editor) && editor.dom.isEmpty(editor.getBody())) { + restoreDraft(editor); + } + }); + return get(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/autosave/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/autosave/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..cd2529400b592035216299e9f052832fb5a5a510 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/autosave/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var e,t=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=(e=undefined,function(t){return e===t}),r=tinymce.util.Tools.resolve("tinymce.util.Delay"),n=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),o=tinymce.util.Tools.resolve("tinymce.util.Tools"),i=function(t,e){var r=t||e,n=/^(\d+)([ms]?)$/.exec(""+r);return(n[2]?{s:1e3,m:6e4}[n[2]]:1)*parseInt(r,10)},u=function(t){var e=document.location;return t.getParam("autosave_prefix","tinymce-autosave-{path}{query}{hash}-{id}-").replace(/{path}/g,e.pathname).replace(/{query}/g,e.search).replace(/{hash}/g,e.hash).replace(/{id}/g,t.id)},s=function(t,e){if(a(e))return t.dom.isEmpty(t.getBody());var r=o.trim(e);if(""===r)return!0;var n=(new DOMParser).parseFromString(r,"text/html");return t.dom.isEmpty(n)},f=function(t){var e=parseInt(n.getItem(u(t)+"time"),10)||0;return!((new Date).getTime()-e>i(t.getParam("autosave_retention"),"20m"))||(c(t,!1),!1)},c=function(t,e){var r=u(t);n.removeItem(r+"draft"),n.removeItem(r+"time"),!1!==e&&t.fire("RemoveDraft")},m=function(t){var e=u(t);!s(t)&&t.isDirty()&&(n.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),n.setItem(e+"time",(new Date).getTime().toString()),t.fire("StoreDraft"))},l=function(t){var e=u(t);f(t)&&(t.setContent(n.getItem(e+"draft"),{format:"raw"}),t.fire("RestoreDraft"))},v=function(t){var e=i(t.getParam("autosave_interval"),"30s");r.setEditorInterval(t,function(){m(t)},e)},d=function(t){t.undoManager.transact(function(){l(t),c(t)}),t.focus()},g=tinymce.util.Tools.resolve("tinymce.EditorManager"),y=function(r){return function(t){t.setDisabled(!f(r));var e=function(){return t.setDisabled(!f(r))};return r.on("StoreDraft RestoreDraft RemoveDraft",e),function(){return r.off("StoreDraft RestoreDraft RemoveDraft",e)}}};t.add("autosave",function(t){var e,r;return t.editorManager.on("BeforeUnload",function(t){var e;o.each(g.get(),function(t){t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&t.getParam("autosave_ask_before_unload",!0)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))}),e&&(t.preventDefault(),t.returnValue=e)}),v(e=t),e.ui.registry.addButton("restoredraft",{tooltip:"Restore last draft",icon:"restore-draft",onAction:function(){d(e)},onSetup:y(e)}),e.ui.registry.addMenuItem("restoredraft",{text:"Restore last draft",icon:"restore-draft",onAction:function(){d(e)},onSetup:y(e)}),t.on("init",function(){t.getParam("autosave_restore_when_empty",!1)&&t.dom.isEmpty(t.getBody())&&l(t)}),r=t,{hasDraft:function(){return f(r)},storeDraft:function(){return m(r)},restoreDraft:function(){return l(r)},removeDraft:function(t){return c(r,t)},isEmpty:function(t){return s(r,t)}}})}(); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/bbcode/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/bbcode/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..5b7ac22397ac5f8615dd700ba86b5c155bdb0f41 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/bbcode/plugin.js @@ -0,0 +1,99 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var html2bbcode = function (s) { + s = global$1.trim(s); + var rep = function (re, str) { + s = s.replace(re, str); + }; + rep(/(.*?)<\/a>/gi, '[url=$1]$2[/url]'); + rep(/(.*?)<\/font>/gi, '[code][color=$1]$2[/color][/code]'); + rep(/(.*?)<\/font>/gi, '[quote][color=$1]$2[/color][/quote]'); + rep(/(.*?)<\/font>/gi, '[code][color=$1]$2[/color][/code]'); + rep(/(.*?)<\/font>/gi, '[quote][color=$1]$2[/color][/quote]'); + rep(/(.*?)<\/span>/gi, '[color=$1]$2[/color]'); + rep(/(.*?)<\/font>/gi, '[color=$1]$2[/color]'); + rep(/(.*?)<\/span>/gi, '[size=$1]$2[/size]'); + rep(/(.*?)<\/font>/gi, '$1'); + rep(//gi, '[img]$1[/img]'); + rep(/(.*?)<\/span>/gi, '[code]$1[/code]'); + rep(/(.*?)<\/span>/gi, '[quote]$1[/quote]'); + rep(/(.*?)<\/strong>/gi, '[code][b]$1[/b][/code]'); + rep(/(.*?)<\/strong>/gi, '[quote][b]$1[/b][/quote]'); + rep(/(.*?)<\/em>/gi, '[code][i]$1[/i][/code]'); + rep(/(.*?)<\/em>/gi, '[quote][i]$1[/i][/quote]'); + rep(/(.*?)<\/u>/gi, '[code][u]$1[/u][/code]'); + rep(/(.*?)<\/u>/gi, '[quote][u]$1[/u][/quote]'); + rep(/<\/(strong|b)>/gi, '[/b]'); + rep(/<(strong|b)>/gi, '[b]'); + rep(/<\/(em|i)>/gi, '[/i]'); + rep(/<(em|i)>/gi, '[i]'); + rep(/<\/u>/gi, '[/u]'); + rep(/(.*?)<\/span>/gi, '[u]$1[/u]'); + rep(//gi, '[u]'); + rep(/]*>/gi, '[quote]'); + rep(/<\/blockquote>/gi, '[/quote]'); + rep(/
                                                                                          /gi, '\n'); + rep(//gi, '\n'); + rep(/
                                                                                          /gi, '\n'); + rep(/

                                                                                          /gi, ''); + rep(/<\/p>/gi, '\n'); + rep(/ |\u00a0/gi, ' '); + rep(/"/gi, '"'); + rep(/</gi, '<'); + rep(/>/gi, '>'); + rep(/&/gi, '&'); + return s; + }; + var bbcode2html = function (s) { + s = global$1.trim(s); + var rep = function (re, str) { + s = s.replace(re, str); + }; + rep(/\n/gi, '
                                                                                          '); + rep(/\[b\]/gi, ''); + rep(/\[\/b\]/gi, ''); + rep(/\[i\]/gi, ''); + rep(/\[\/i\]/gi, ''); + rep(/\[u\]/gi, ''); + rep(/\[\/u\]/gi, ''); + rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi, '$2'); + rep(/\[url\](.*?)\[\/url\]/gi, '$1'); + rep(/\[img\](.*?)\[\/img\]/gi, ''); + rep(/\[color=(.*?)\](.*?)\[\/color\]/gi, '$2'); + rep(/\[code\](.*?)\[\/code\]/gi, '$1 '); + rep(/\[quote.*?\](.*?)\[\/quote\]/gi, '$1 '); + return s; + }; + + function Plugin () { + global.add('bbcode', function (editor) { + editor.on('BeforeSetContent', function (e) { + e.content = bbcode2html(e.content); + }); + editor.on('PostProcess', function (e) { + if (e.set) { + e.content = bbcode2html(e.content); + } + if (e.get) { + e.content = html2bbcode(e.content); + } + }); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/bbcode/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/bbcode/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..a0471d465ff1b12ba3a734c34188ef09596ef37e --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/bbcode/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var o=tinymce.util.Tools.resolve("tinymce.PluginManager"),e=tinymce.util.Tools.resolve("tinymce.util.Tools"),t=function(t){t=e.trim(t);var o=function(o,e){t=t.replace(o,e)};return o(/\n/gi,"
                                                                                          "),o(/\[b\]/gi,""),o(/\[\/b\]/gi,""),o(/\[i\]/gi,""),o(/\[\/i\]/gi,""),o(/\[u\]/gi,""),o(/\[\/u\]/gi,""),o(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'$2'),o(/\[url\](.*?)\[\/url\]/gi,'$1'),o(/\[img\](.*?)\[\/img\]/gi,''),o(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2'),o(/\[code\](.*?)\[\/code\]/gi,'$1 '),o(/\[quote.*?\](.*?)\[\/quote\]/gi,'$1 '),t};o.add("bbcode",function(o){o.on("BeforeSetContent",function(o){o.content=t(o.content)}),o.on("PostProcess",function(o){o.set&&(o.content=t(o.content)),o.get&&(o.content=function(t){t=e.trim(t);var o=function(o,e){t=t.replace(o,e)};return o(/(.*?)<\/a>/gi,"[url=$1]$2[/url]"),o(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),o(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),o(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),o(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),o(/(.*?)<\/span>/gi,"[color=$1]$2[/color]"),o(/(.*?)<\/font>/gi,"[color=$1]$2[/color]"),o(/(.*?)<\/span>/gi,"[size=$1]$2[/size]"),o(/(.*?)<\/font>/gi,"$1"),o(//gi,"[img]$1[/img]"),o(/(.*?)<\/span>/gi,"[code]$1[/code]"),o(/(.*?)<\/span>/gi,"[quote]$1[/quote]"),o(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),o(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),o(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),o(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),o(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),o(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),o(/<\/(strong|b)>/gi,"[/b]"),o(/<(strong|b)>/gi,"[b]"),o(/<\/(em|i)>/gi,"[/i]"),o(/<(em|i)>/gi,"[i]"),o(/<\/u>/gi,"[/u]"),o(/(.*?)<\/span>/gi,"[u]$1[/u]"),o(//gi,"[u]"),o(/]*>/gi,"[quote]"),o(/<\/blockquote>/gi,"[/quote]"),o(/
                                                                                          /gi,"\n"),o(//gi,"\n"),o(/
                                                                                          /gi,"\n"),o(/

                                                                                          /gi,""),o(/<\/p>/gi,"\n"),o(/ |\u00a0/gi," "),o(/"/gi,'"'),o(/</gi,"<"),o(/>/gi,">"),o(/&/gi,"&"),t}(o.content))})})}(); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/charmap/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/charmap/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..cceb2ec18ffbed225037c6beb3bdaff16cd74b6c --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/charmap/plugin.js @@ -0,0 +1,1706 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var fireInsertCustomChar = function (editor, chr) { + return editor.fire('insertCustomChar', { chr: chr }); + }; + + var insertChar = function (editor, chr) { + var evtChr = fireInsertCustomChar(editor, chr).chr; + editor.execCommand('mceInsertContent', false, evtChr); + }; + + var noop = function () { + }; + var constant = function (value) { + return function () { + return value; + }; + }; + var never = constant(false); + var always = constant(true); + + var none = function () { + return NONE; + }; + var NONE = function () { + var eq = function (o) { + return o.isNone(); + }; + var call = function (thunk) { + return thunk(); + }; + var id = function (n) { + return n; + }; + var me = { + fold: function (n, _s) { + return n(); + }, + is: never, + isSome: never, + isNone: always, + getOr: id, + getOrThunk: call, + getOrDie: function (msg) { + throw new Error(msg || 'error: getOrDie called on none.'); + }, + getOrNull: constant(null), + getOrUndefined: constant(undefined), + or: id, + orThunk: call, + map: none, + each: noop, + bind: none, + exists: never, + forall: always, + filter: none, + equals: eq, + equals_: eq, + toArray: function () { + return []; + }, + toString: constant('none()') + }; + return me; + }(); + var some = function (a) { + var constant_a = constant(a); + var self = function () { + return me; + }; + var bind = function (f) { + return f(a); + }; + var me = { + fold: function (n, s) { + return s(a); + }, + is: function (v) { + return a === v; + }, + isSome: always, + isNone: never, + getOr: constant_a, + getOrThunk: constant_a, + getOrDie: constant_a, + getOrNull: constant_a, + getOrUndefined: constant_a, + or: self, + orThunk: self, + map: function (f) { + return some(f(a)); + }, + each: function (f) { + f(a); + }, + bind: bind, + exists: bind, + forall: bind, + filter: function (f) { + return f(a) ? me : NONE; + }, + toArray: function () { + return [a]; + }, + toString: function () { + return 'some(' + a + ')'; + }, + equals: function (o) { + return o.is(a); + }, + equals_: function (o, elementEq) { + return o.fold(never, function (b) { + return elementEq(a, b); + }); + } + }; + return me; + }; + var from = function (value) { + return value === null || value === undefined ? NONE : some(value); + }; + var Optional = { + some: some, + none: none, + from: from + }; + + var typeOf = function (x) { + var t = typeof x; + if (x === null) { + return 'null'; + } else if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { + return 'array'; + } else if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { + return 'string'; + } else { + return t; + } + }; + var isType = function (type) { + return function (value) { + return typeOf(value) === type; + }; + }; + var isArray = isType('array'); + + var nativePush = Array.prototype.push; + var map = function (xs, f) { + var len = xs.length; + var r = new Array(len); + for (var i = 0; i < len; i++) { + var x = xs[i]; + r[i] = f(x, i); + } + return r; + }; + var each = function (xs, f) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + f(x, i); + } + }; + var findUntil = function (xs, pred, until) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i)) { + return Optional.some(x); + } else if (until(x, i)) { + break; + } + } + return Optional.none(); + }; + var find = function (xs, pred) { + return findUntil(xs, pred, never); + }; + var flatten = function (xs) { + var r = []; + for (var i = 0, len = xs.length; i < len; ++i) { + if (!isArray(xs[i])) { + throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs); + } + nativePush.apply(r, xs[i]); + } + return r; + }; + var bind = function (xs, f) { + return flatten(map(xs, f)); + }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var getCharMap = function (editor) { + return editor.getParam('charmap'); + }; + var getCharMapAppend = function (editor) { + return editor.getParam('charmap_append'); + }; + + var isArray$1 = global$1.isArray; + var UserDefined = 'User Defined'; + var getDefaultCharMap = function () { + return [ + { + name: 'Currency', + characters: [ + [ + 36, + 'dollar sign' + ], + [ + 162, + 'cent sign' + ], + [ + 8364, + 'euro sign' + ], + [ + 163, + 'pound sign' + ], + [ + 165, + 'yen sign' + ], + [ + 164, + 'currency sign' + ], + [ + 8352, + 'euro-currency sign' + ], + [ + 8353, + 'colon sign' + ], + [ + 8354, + 'cruzeiro sign' + ], + [ + 8355, + 'french franc sign' + ], + [ + 8356, + 'lira sign' + ], + [ + 8357, + 'mill sign' + ], + [ + 8358, + 'naira sign' + ], + [ + 8359, + 'peseta sign' + ], + [ + 8360, + 'rupee sign' + ], + [ + 8361, + 'won sign' + ], + [ + 8362, + 'new sheqel sign' + ], + [ + 8363, + 'dong sign' + ], + [ + 8365, + 'kip sign' + ], + [ + 8366, + 'tugrik sign' + ], + [ + 8367, + 'drachma sign' + ], + [ + 8368, + 'german penny symbol' + ], + [ + 8369, + 'peso sign' + ], + [ + 8370, + 'guarani sign' + ], + [ + 8371, + 'austral sign' + ], + [ + 8372, + 'hryvnia sign' + ], + [ + 8373, + 'cedi sign' + ], + [ + 8374, + 'livre tournois sign' + ], + [ + 8375, + 'spesmilo sign' + ], + [ + 8376, + 'tenge sign' + ], + [ + 8377, + 'indian rupee sign' + ], + [ + 8378, + 'turkish lira sign' + ], + [ + 8379, + 'nordic mark sign' + ], + [ + 8380, + 'manat sign' + ], + [ + 8381, + 'ruble sign' + ], + [ + 20870, + 'yen character' + ], + [ + 20803, + 'yuan character' + ], + [ + 22291, + 'yuan character, in hong kong and taiwan' + ], + [ + 22278, + 'yen/yuan character variant one' + ] + ] + }, + { + name: 'Text', + characters: [ + [ + 169, + 'copyright sign' + ], + [ + 174, + 'registered sign' + ], + [ + 8482, + 'trade mark sign' + ], + [ + 8240, + 'per mille sign' + ], + [ + 181, + 'micro sign' + ], + [ + 183, + 'middle dot' + ], + [ + 8226, + 'bullet' + ], + [ + 8230, + 'three dot leader' + ], + [ + 8242, + 'minutes / feet' + ], + [ + 8243, + 'seconds / inches' + ], + [ + 167, + 'section sign' + ], + [ + 182, + 'paragraph sign' + ], + [ + 223, + 'sharp s / ess-zed' + ] + ] + }, + { + name: 'Quotations', + characters: [ + [ + 8249, + 'single left-pointing angle quotation mark' + ], + [ + 8250, + 'single right-pointing angle quotation mark' + ], + [ + 171, + 'left pointing guillemet' + ], + [ + 187, + 'right pointing guillemet' + ], + [ + 8216, + 'left single quotation mark' + ], + [ + 8217, + 'right single quotation mark' + ], + [ + 8220, + 'left double quotation mark' + ], + [ + 8221, + 'right double quotation mark' + ], + [ + 8218, + 'single low-9 quotation mark' + ], + [ + 8222, + 'double low-9 quotation mark' + ], + [ + 60, + 'less-than sign' + ], + [ + 62, + 'greater-than sign' + ], + [ + 8804, + 'less-than or equal to' + ], + [ + 8805, + 'greater-than or equal to' + ], + [ + 8211, + 'en dash' + ], + [ + 8212, + 'em dash' + ], + [ + 175, + 'macron' + ], + [ + 8254, + 'overline' + ], + [ + 164, + 'currency sign' + ], + [ + 166, + 'broken bar' + ], + [ + 168, + 'diaeresis' + ], + [ + 161, + 'inverted exclamation mark' + ], + [ + 191, + 'turned question mark' + ], + [ + 710, + 'circumflex accent' + ], + [ + 732, + 'small tilde' + ], + [ + 176, + 'degree sign' + ], + [ + 8722, + 'minus sign' + ], + [ + 177, + 'plus-minus sign' + ], + [ + 247, + 'division sign' + ], + [ + 8260, + 'fraction slash' + ], + [ + 215, + 'multiplication sign' + ], + [ + 185, + 'superscript one' + ], + [ + 178, + 'superscript two' + ], + [ + 179, + 'superscript three' + ], + [ + 188, + 'fraction one quarter' + ], + [ + 189, + 'fraction one half' + ], + [ + 190, + 'fraction three quarters' + ] + ] + }, + { + name: 'Mathematical', + characters: [ + [ + 402, + 'function / florin' + ], + [ + 8747, + 'integral' + ], + [ + 8721, + 'n-ary sumation' + ], + [ + 8734, + 'infinity' + ], + [ + 8730, + 'square root' + ], + [ + 8764, + 'similar to' + ], + [ + 8773, + 'approximately equal to' + ], + [ + 8776, + 'almost equal to' + ], + [ + 8800, + 'not equal to' + ], + [ + 8801, + 'identical to' + ], + [ + 8712, + 'element of' + ], + [ + 8713, + 'not an element of' + ], + [ + 8715, + 'contains as member' + ], + [ + 8719, + 'n-ary product' + ], + [ + 8743, + 'logical and' + ], + [ + 8744, + 'logical or' + ], + [ + 172, + 'not sign' + ], + [ + 8745, + 'intersection' + ], + [ + 8746, + 'union' + ], + [ + 8706, + 'partial differential' + ], + [ + 8704, + 'for all' + ], + [ + 8707, + 'there exists' + ], + [ + 8709, + 'diameter' + ], + [ + 8711, + 'backward difference' + ], + [ + 8727, + 'asterisk operator' + ], + [ + 8733, + 'proportional to' + ], + [ + 8736, + 'angle' + ] + ] + }, + { + name: 'Extended Latin', + characters: [ + [ + 192, + 'A - grave' + ], + [ + 193, + 'A - acute' + ], + [ + 194, + 'A - circumflex' + ], + [ + 195, + 'A - tilde' + ], + [ + 196, + 'A - diaeresis' + ], + [ + 197, + 'A - ring above' + ], + [ + 256, + 'A - macron' + ], + [ + 198, + 'ligature AE' + ], + [ + 199, + 'C - cedilla' + ], + [ + 200, + 'E - grave' + ], + [ + 201, + 'E - acute' + ], + [ + 202, + 'E - circumflex' + ], + [ + 203, + 'E - diaeresis' + ], + [ + 274, + 'E - macron' + ], + [ + 204, + 'I - grave' + ], + [ + 205, + 'I - acute' + ], + [ + 206, + 'I - circumflex' + ], + [ + 207, + 'I - diaeresis' + ], + [ + 298, + 'I - macron' + ], + [ + 208, + 'ETH' + ], + [ + 209, + 'N - tilde' + ], + [ + 210, + 'O - grave' + ], + [ + 211, + 'O - acute' + ], + [ + 212, + 'O - circumflex' + ], + [ + 213, + 'O - tilde' + ], + [ + 214, + 'O - diaeresis' + ], + [ + 216, + 'O - slash' + ], + [ + 332, + 'O - macron' + ], + [ + 338, + 'ligature OE' + ], + [ + 352, + 'S - caron' + ], + [ + 217, + 'U - grave' + ], + [ + 218, + 'U - acute' + ], + [ + 219, + 'U - circumflex' + ], + [ + 220, + 'U - diaeresis' + ], + [ + 362, + 'U - macron' + ], + [ + 221, + 'Y - acute' + ], + [ + 376, + 'Y - diaeresis' + ], + [ + 562, + 'Y - macron' + ], + [ + 222, + 'THORN' + ], + [ + 224, + 'a - grave' + ], + [ + 225, + 'a - acute' + ], + [ + 226, + 'a - circumflex' + ], + [ + 227, + 'a - tilde' + ], + [ + 228, + 'a - diaeresis' + ], + [ + 229, + 'a - ring above' + ], + [ + 257, + 'a - macron' + ], + [ + 230, + 'ligature ae' + ], + [ + 231, + 'c - cedilla' + ], + [ + 232, + 'e - grave' + ], + [ + 233, + 'e - acute' + ], + [ + 234, + 'e - circumflex' + ], + [ + 235, + 'e - diaeresis' + ], + [ + 275, + 'e - macron' + ], + [ + 236, + 'i - grave' + ], + [ + 237, + 'i - acute' + ], + [ + 238, + 'i - circumflex' + ], + [ + 239, + 'i - diaeresis' + ], + [ + 299, + 'i - macron' + ], + [ + 240, + 'eth' + ], + [ + 241, + 'n - tilde' + ], + [ + 242, + 'o - grave' + ], + [ + 243, + 'o - acute' + ], + [ + 244, + 'o - circumflex' + ], + [ + 245, + 'o - tilde' + ], + [ + 246, + 'o - diaeresis' + ], + [ + 248, + 'o slash' + ], + [ + 333, + 'o macron' + ], + [ + 339, + 'ligature oe' + ], + [ + 353, + 's - caron' + ], + [ + 249, + 'u - grave' + ], + [ + 250, + 'u - acute' + ], + [ + 251, + 'u - circumflex' + ], + [ + 252, + 'u - diaeresis' + ], + [ + 363, + 'u - macron' + ], + [ + 253, + 'y - acute' + ], + [ + 254, + 'thorn' + ], + [ + 255, + 'y - diaeresis' + ], + [ + 563, + 'y - macron' + ], + [ + 913, + 'Alpha' + ], + [ + 914, + 'Beta' + ], + [ + 915, + 'Gamma' + ], + [ + 916, + 'Delta' + ], + [ + 917, + 'Epsilon' + ], + [ + 918, + 'Zeta' + ], + [ + 919, + 'Eta' + ], + [ + 920, + 'Theta' + ], + [ + 921, + 'Iota' + ], + [ + 922, + 'Kappa' + ], + [ + 923, + 'Lambda' + ], + [ + 924, + 'Mu' + ], + [ + 925, + 'Nu' + ], + [ + 926, + 'Xi' + ], + [ + 927, + 'Omicron' + ], + [ + 928, + 'Pi' + ], + [ + 929, + 'Rho' + ], + [ + 931, + 'Sigma' + ], + [ + 932, + 'Tau' + ], + [ + 933, + 'Upsilon' + ], + [ + 934, + 'Phi' + ], + [ + 935, + 'Chi' + ], + [ + 936, + 'Psi' + ], + [ + 937, + 'Omega' + ], + [ + 945, + 'alpha' + ], + [ + 946, + 'beta' + ], + [ + 947, + 'gamma' + ], + [ + 948, + 'delta' + ], + [ + 949, + 'epsilon' + ], + [ + 950, + 'zeta' + ], + [ + 951, + 'eta' + ], + [ + 952, + 'theta' + ], + [ + 953, + 'iota' + ], + [ + 954, + 'kappa' + ], + [ + 955, + 'lambda' + ], + [ + 956, + 'mu' + ], + [ + 957, + 'nu' + ], + [ + 958, + 'xi' + ], + [ + 959, + 'omicron' + ], + [ + 960, + 'pi' + ], + [ + 961, + 'rho' + ], + [ + 962, + 'final sigma' + ], + [ + 963, + 'sigma' + ], + [ + 964, + 'tau' + ], + [ + 965, + 'upsilon' + ], + [ + 966, + 'phi' + ], + [ + 967, + 'chi' + ], + [ + 968, + 'psi' + ], + [ + 969, + 'omega' + ] + ] + }, + { + name: 'Symbols', + characters: [ + [ + 8501, + 'alef symbol' + ], + [ + 982, + 'pi symbol' + ], + [ + 8476, + 'real part symbol' + ], + [ + 978, + 'upsilon - hook symbol' + ], + [ + 8472, + 'Weierstrass p' + ], + [ + 8465, + 'imaginary part' + ] + ] + }, + { + name: 'Arrows', + characters: [ + [ + 8592, + 'leftwards arrow' + ], + [ + 8593, + 'upwards arrow' + ], + [ + 8594, + 'rightwards arrow' + ], + [ + 8595, + 'downwards arrow' + ], + [ + 8596, + 'left right arrow' + ], + [ + 8629, + 'carriage return' + ], + [ + 8656, + 'leftwards double arrow' + ], + [ + 8657, + 'upwards double arrow' + ], + [ + 8658, + 'rightwards double arrow' + ], + [ + 8659, + 'downwards double arrow' + ], + [ + 8660, + 'left right double arrow' + ], + [ + 8756, + 'therefore' + ], + [ + 8834, + 'subset of' + ], + [ + 8835, + 'superset of' + ], + [ + 8836, + 'not a subset of' + ], + [ + 8838, + 'subset of or equal to' + ], + [ + 8839, + 'superset of or equal to' + ], + [ + 8853, + 'circled plus' + ], + [ + 8855, + 'circled times' + ], + [ + 8869, + 'perpendicular' + ], + [ + 8901, + 'dot operator' + ], + [ + 8968, + 'left ceiling' + ], + [ + 8969, + 'right ceiling' + ], + [ + 8970, + 'left floor' + ], + [ + 8971, + 'right floor' + ], + [ + 9001, + 'left-pointing angle bracket' + ], + [ + 9002, + 'right-pointing angle bracket' + ], + [ + 9674, + 'lozenge' + ], + [ + 9824, + 'black spade suit' + ], + [ + 9827, + 'black club suit' + ], + [ + 9829, + 'black heart suit' + ], + [ + 9830, + 'black diamond suit' + ], + [ + 8194, + 'en space' + ], + [ + 8195, + 'em space' + ], + [ + 8201, + 'thin space' + ], + [ + 8204, + 'zero width non-joiner' + ], + [ + 8205, + 'zero width joiner' + ], + [ + 8206, + 'left-to-right mark' + ], + [ + 8207, + 'right-to-left mark' + ] + ] + } + ]; + }; + var charmapFilter = function (charmap) { + return global$1.grep(charmap, function (item) { + return isArray$1(item) && item.length === 2; + }); + }; + var getCharsFromSetting = function (settingValue) { + if (isArray$1(settingValue)) { + return [].concat(charmapFilter(settingValue)); + } + if (typeof settingValue === 'function') { + return settingValue(); + } + return []; + }; + var extendCharMap = function (editor, charmap) { + var userCharMap = getCharMap(editor); + if (userCharMap) { + charmap = [{ + name: UserDefined, + characters: getCharsFromSetting(userCharMap) + }]; + } + var userCharMapAppend = getCharMapAppend(editor); + if (userCharMapAppend) { + var userDefinedGroup = global$1.grep(charmap, function (cg) { + return cg.name === UserDefined; + }); + if (userDefinedGroup.length) { + userDefinedGroup[0].characters = [].concat(userDefinedGroup[0].characters).concat(getCharsFromSetting(userCharMapAppend)); + return charmap; + } + return [].concat(charmap).concat({ + name: UserDefined, + characters: getCharsFromSetting(userCharMapAppend) + }); + } + return charmap; + }; + var getCharMap$1 = function (editor) { + var groups = extendCharMap(editor, getDefaultCharMap()); + return groups.length > 1 ? [{ + name: 'All', + characters: bind(groups, function (g) { + return g.characters; + }) + }].concat(groups) : groups; + }; + + var get = function (editor) { + var getCharMap = function () { + return getCharMap$1(editor); + }; + var insertChar$1 = function (chr) { + insertChar(editor, chr); + }; + return { + getCharMap: getCharMap, + insertChar: insertChar$1 + }; + }; + + var Cell = function (initial) { + var value = initial; + var get = function () { + return value; + }; + var set = function (v) { + value = v; + }; + return { + get: get, + set: set + }; + }; + + var last = function (fn, rate) { + var timer = null; + var cancel = function () { + if (timer !== null) { + clearTimeout(timer); + timer = null; + } + }; + var throttle = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + if (timer !== null) { + clearTimeout(timer); + } + timer = setTimeout(function () { + fn.apply(null, args); + timer = null; + }, rate); + }; + return { + cancel: cancel, + throttle: throttle + }; + }; + + var nativeFromCodePoint = String.fromCodePoint; + var contains = function (str, substr) { + return str.indexOf(substr) !== -1; + }; + var fromCodePoint = function () { + var codePoints = []; + for (var _i = 0; _i < arguments.length; _i++) { + codePoints[_i] = arguments[_i]; + } + if (nativeFromCodePoint) { + return nativeFromCodePoint.apply(void 0, codePoints); + } else { + var codeUnits = []; + var codeLen = 0; + var result = ''; + for (var index = 0, len = codePoints.length; index !== len; ++index) { + var codePoint = +codePoints[index]; + if (!(codePoint < 1114111 && codePoint >>> 0 === codePoint)) { + throw RangeError('Invalid code point: ' + codePoint); + } + if (codePoint <= 65535) { + codeLen = codeUnits.push(codePoint); + } else { + codePoint -= 65536; + codeLen = codeUnits.push((codePoint >> 10) + 55296, codePoint % 1024 + 56320); + } + if (codeLen >= 16383) { + result += String.fromCharCode.apply(null, codeUnits); + codeUnits.length = 0; + } + } + return result + String.fromCharCode.apply(null, codeUnits); + } + }; + + var charMatches = function (charCode, name, lowerCasePattern) { + if (contains(fromCodePoint(charCode).toLowerCase(), lowerCasePattern)) { + return true; + } else { + return contains(name.toLowerCase(), lowerCasePattern) || contains(name.toLowerCase().replace(/\s+/g, ''), lowerCasePattern); + } + }; + var scan = function (group, pattern) { + var matches = []; + var lowerCasePattern = pattern.toLowerCase(); + each(group.characters, function (g) { + if (charMatches(g[0], g[1], lowerCasePattern)) { + matches.push(g); + } + }); + return map(matches, function (m) { + return { + text: m[1], + value: fromCodePoint(m[0]), + icon: fromCodePoint(m[0]) + }; + }); + }; + + var patternName = 'pattern'; + var open = function (editor, charMap) { + var makeGroupItems = function () { + return [ + { + label: 'Search', + type: 'input', + name: patternName + }, + { + type: 'collection', + name: 'results' + } + ]; + }; + var makeTabs = function () { + return map(charMap, function (charGroup) { + return { + title: charGroup.name, + name: charGroup.name, + items: makeGroupItems() + }; + }); + }; + var makePanel = function () { + return { + type: 'panel', + items: makeGroupItems() + }; + }; + var makeTabPanel = function () { + return { + type: 'tabpanel', + tabs: makeTabs() + }; + }; + var currentTab = charMap.length === 1 ? Cell(UserDefined) : Cell('All'); + var scanAndSet = function (dialogApi, pattern) { + find(charMap, function (group) { + return group.name === currentTab.get(); + }).each(function (f) { + var items = scan(f, pattern); + dialogApi.setData({ results: items }); + }); + }; + var SEARCH_DELAY = 40; + var updateFilter = last(function (dialogApi) { + var pattern = dialogApi.getData().pattern; + scanAndSet(dialogApi, pattern); + }, SEARCH_DELAY); + var body = charMap.length === 1 ? makePanel() : makeTabPanel(); + var initialData = { + pattern: '', + results: scan(charMap[0], '') + }; + var bridgeSpec = { + title: 'Special Character', + size: 'normal', + body: body, + buttons: [{ + type: 'cancel', + name: 'close', + text: 'Close', + primary: true + }], + initialData: initialData, + onAction: function (api, details) { + if (details.name === 'results') { + insertChar(editor, details.value); + api.close(); + } + }, + onTabChange: function (dialogApi, details) { + currentTab.set(details.newTabName); + updateFilter.throttle(dialogApi); + }, + onChange: function (dialogApi, changeData) { + if (changeData.name === patternName) { + updateFilter.throttle(dialogApi); + } + } + }; + var dialogApi = editor.windowManager.open(bridgeSpec); + dialogApi.focus(patternName); + }; + + var register = function (editor, charMap) { + editor.addCommand('mceShowCharmap', function () { + open(editor, charMap); + }); + }; + + var global$2 = tinymce.util.Tools.resolve('tinymce.util.Promise'); + + var init = function (editor, all) { + editor.ui.registry.addAutocompleter('charmap', { + ch: ':', + columns: 'auto', + minChars: 2, + fetch: function (pattern, _maxResults) { + return new global$2(function (resolve, _reject) { + resolve(scan(all, pattern)); + }); + }, + onAction: function (autocompleteApi, rng, value) { + editor.selection.setRng(rng); + editor.insertContent(value); + autocompleteApi.hide(); + } + }); + }; + + var register$1 = function (editor) { + editor.ui.registry.addButton('charmap', { + icon: 'insert-character', + tooltip: 'Special character', + onAction: function () { + return editor.execCommand('mceShowCharmap'); + } + }); + editor.ui.registry.addMenuItem('charmap', { + icon: 'insert-character', + text: 'Special character...', + onAction: function () { + return editor.execCommand('mceShowCharmap'); + } + }); + }; + + function Plugin () { + global.add('charmap', function (editor) { + var charMap = getCharMap$1(editor); + register(editor, charMap); + register$1(editor); + init(editor, charMap[0]); + return get(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/charmap/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/charmap/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..3df46f29907ce0e27f7ceebe958fdc96932ce665 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/charmap/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var e,n,r,t,a=tinymce.util.Tools.resolve("tinymce.PluginManager"),s=function(e,n){var r,t=(r=n,e.fire("insertCustomChar",{chr:r}).chr);e.execCommand("mceInsertContent",!1,t)},i=function(e){return function(){return e}},o=i(!1),c=i(!0),u=function(){return l},l=(e=function(e){return e.isNone()},{fold:function(e,n){return e()},is:o,isSome:o,isNone:c,getOr:r=function(e){return e},getOrThunk:n=function(e){return e()},getOrDie:function(e){throw new Error(e||"error: getOrDie called on none.")},getOrNull:i(null),getOrUndefined:i(undefined),or:r,orThunk:n,map:u,each:function(){},bind:u,exists:o,forall:c,filter:u,equals:e,equals_:e,toArray:function(){return[]},toString:i("none()")}),g=function(r){var e=i(r),n=function(){return a},t=function(e){return e(r)},a={fold:function(e,n){return n(r)},is:function(e){return r===e},isSome:c,isNone:o,getOr:e,getOrThunk:e,getOrDie:e,getOrNull:e,getOrUndefined:e,or:n,orThunk:n,map:function(e){return g(e(r))},each:function(e){e(r)},bind:t,exists:t,forall:t,filter:function(e){return e(r)?a:l},toArray:function(){return[r]},toString:function(){return"some("+r+")"},equals:function(e){return e.is(r)},equals_:function(e,n){return e.fold(o,function(e){return n(r,e)})}};return a},m={some:g,none:u,from:function(e){return null===e||e===undefined?l:g(e)}},f=(t="array",function(e){return r=typeof(n=e),(null===n?"null":"object"==r&&(Array.prototype.isPrototypeOf(n)||n.constructor&&"Array"===n.constructor.name)?"array":"object"==r&&(String.prototype.isPrototypeOf(n)||n.constructor&&"String"===n.constructor.name)?"string":r)===t;var n,r}),h=Array.prototype.push,p=function(e,n){for(var r=e.length,t=new Array(r),a=0;a>>0===o))throw RangeError("Invalid code point: "+o);16383<=(o<=65535?r.push(o):(o-=65536,r.push(55296+(o>>10),o%1024+56320)))&&(t+=String.fromCharCode.apply(null,r),r.length=0)}return t+String.fromCharCode.apply(null,r)},S=function(e,n){var a=[],i=n.toLowerCase();return function(e,n){for(var r=0,t=e.length;r= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none(); + }; + var head = function (xs) { + return get(xs, 0); + }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils'); + + function isCodeSample(elm) { + return elm && elm.nodeName === 'PRE' && elm.className.indexOf('language-') !== -1; + } + function trimArg(predicateFn) { + return function (arg1, arg2) { + return predicateFn(arg2); + }; + } + + var Global = typeof window !== 'undefined' ? window : Function('return this;')(); + + var exports$1 = {}, module = { exports: exports$1 }, global$2 = {}; + (function (define, exports, module, require) { + var oldprism = window.Prism; + window.Prism = { manual: true }; + (function (f) { + if (typeof exports === 'object' && typeof module !== 'undefined') { + module.exports = f(); + } else if (typeof define === 'function' && define.amd) { + define([], f); + } else { + var g; + if (typeof window !== 'undefined') { + g = window; + } else if (typeof global$2 !== 'undefined') { + g = global$2; + } else if (typeof self !== 'undefined') { + g = self; + } else { + g = this; + } + g.EphoxContactWrapper = f(); + } + }(function () { + return function () { + function r(e, n, t) { + function o(i, f) { + if (!n[i]) { + if (!e[i]) { + var c = 'function' == typeof require && require; + if (!f && c) + return c(i, !0); + if (u) + return u(i, !0); + var a = new Error('Cannot find module \'' + i + '\''); + throw a.code = 'MODULE_NOT_FOUND', a; + } + var p = n[i] = { exports: {} }; + e[i][0].call(p.exports, function (r) { + var n = e[i][1][r]; + return o(n || r); + }, p, p.exports, r, e, n, t); + } + return n[i].exports; + } + for (var u = 'function' == typeof require && require, i = 0; i < t.length; i++) + o(t[i]); + return o; + } + return r; + }()({ + 1: [ + function (require, module, exports) { + Prism.languages.c = Prism.languages.extend('clike', { + 'comment': { + pattern: /\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/, + greedy: true + }, + 'class-name': { + pattern: /(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+/, + lookbehind: true + }, + 'keyword': /\b(?:__attribute__|_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/, + 'function': /[a-z_]\w*(?=\s*\()/i, + 'operator': />>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/, + 'number': /(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i + }); + Prism.languages.insertBefore('c', 'string', { + 'macro': { + pattern: /(^\s*)#\s*[a-z]+(?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im, + lookbehind: true, + greedy: true, + alias: 'property', + inside: { + 'string': [ + { + pattern: /^(#\s*include\s*)<[^>]+>/, + lookbehind: true + }, + Prism.languages.c['string'] + ], + 'comment': Prism.languages.c['comment'], + 'directive': { + pattern: /^(#\s*)[a-z]+/, + lookbehind: true, + alias: 'keyword' + }, + 'directive-hash': /^#/, + 'punctuation': /##|\\(?=[\r\n])/, + 'expression': { + pattern: /\S[\s\S]*/, + inside: Prism.languages.c + } + } + }, + 'constant': /\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/ + }); + delete Prism.languages.c['boolean']; + }, + {} + ], + 2: [ + function (require, module, exports) { + Prism.languages.clike = { + 'comment': [ + { + pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/, + lookbehind: true + }, + { + pattern: /(^|[^\\:])\/\/.*/, + lookbehind: true, + greedy: true + } + ], + 'string': { + pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, + greedy: true + }, + 'class-name': { + pattern: /(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i, + lookbehind: true, + inside: { 'punctuation': /[.\\]/ } + }, + 'keyword': /\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/, + 'boolean': /\b(?:true|false)\b/, + 'function': /\w+(?=\()/, + 'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i, + 'operator': /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/, + 'punctuation': /[{}[\];(),.:]/ + }; + }, + {} + ], + 3: [ + function (require, module, exports) { + (function (global) { + (function () { + var _self = typeof window !== 'undefined' ? window : typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope ? self : {}; + var Prism = function (_self) { + var lang = /\blang(?:uage)?-([\w-]+)\b/i; + var uniqueId = 0; + var _ = { + manual: _self.Prism && _self.Prism.manual, + disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler, + util: { + encode: function encode(tokens) { + if (tokens instanceof Token) { + return new Token(tokens.type, encode(tokens.content), tokens.alias); + } else if (Array.isArray(tokens)) { + return tokens.map(encode); + } else { + return tokens.replace(/&/g, '&').replace(/' + env.content + ''; + }; + function matchGrammar(text, tokenList, grammar, startNode, startPos, rematch) { + for (var token in grammar) { + if (!grammar.hasOwnProperty(token) || !grammar[token]) { + continue; + } + var patterns = grammar[token]; + patterns = Array.isArray(patterns) ? patterns : [patterns]; + for (var j = 0; j < patterns.length; ++j) { + if (rematch && rematch.cause == token + ',' + j) { + return; + } + var patternObj = patterns[j], inside = patternObj.inside, lookbehind = !!patternObj.lookbehind, greedy = !!patternObj.greedy, lookbehindLength = 0, alias = patternObj.alias; + if (greedy && !patternObj.pattern.global) { + var flags = patternObj.pattern.toString().match(/[imsuy]*$/)[0]; + patternObj.pattern = RegExp(patternObj.pattern.source, flags + 'g'); + } + var pattern = patternObj.pattern || patternObj; + for (var currentNode = startNode.next, pos = startPos; currentNode !== tokenList.tail; pos += currentNode.value.length, currentNode = currentNode.next) { + if (rematch && pos >= rematch.reach) { + break; + } + var str = currentNode.value; + if (tokenList.length > text.length) { + return; + } + if (str instanceof Token) { + continue; + } + var removeCount = 1; + if (greedy && currentNode != tokenList.tail.prev) { + pattern.lastIndex = pos; + var match = pattern.exec(text); + if (!match) { + break; + } + var from = match.index + (lookbehind && match[1] ? match[1].length : 0); + var to = match.index + match[0].length; + var p = pos; + p += currentNode.value.length; + while (from >= p) { + currentNode = currentNode.next; + p += currentNode.value.length; + } + p -= currentNode.value.length; + pos = p; + if (currentNode.value instanceof Token) { + continue; + } + for (var k = currentNode; k !== tokenList.tail && (p < to || typeof k.value === 'string'); k = k.next) { + removeCount++; + p += k.value.length; + } + removeCount--; + str = text.slice(pos, p); + match.index -= pos; + } else { + pattern.lastIndex = 0; + var match = pattern.exec(str); + } + if (!match) { + continue; + } + if (lookbehind) { + lookbehindLength = match[1] ? match[1].length : 0; + } + var from = match.index + lookbehindLength, matchStr = match[0].slice(lookbehindLength), to = from + matchStr.length, before = str.slice(0, from), after = str.slice(to); + var reach = pos + str.length; + if (rematch && reach > rematch.reach) { + rematch.reach = reach; + } + var removeFrom = currentNode.prev; + if (before) { + removeFrom = addAfter(tokenList, removeFrom, before); + pos += before.length; + } + removeRange(tokenList, removeFrom, removeCount); + var wrapped = new Token(token, inside ? _.tokenize(matchStr, inside) : matchStr, alias, matchStr); + currentNode = addAfter(tokenList, removeFrom, wrapped); + if (after) { + addAfter(tokenList, currentNode, after); + } + if (removeCount > 1) { + matchGrammar(text, tokenList, grammar, currentNode.prev, pos, { + cause: token + ',' + j, + reach: reach + }); + } + } + } + } + } + function LinkedList() { + var head = { + value: null, + prev: null, + next: null + }; + var tail = { + value: null, + prev: head, + next: null + }; + head.next = tail; + this.head = head; + this.tail = tail; + this.length = 0; + } + function addAfter(list, node, value) { + var next = node.next; + var newNode = { + value: value, + prev: node, + next: next + }; + node.next = newNode; + next.prev = newNode; + list.length++; + return newNode; + } + function removeRange(list, node, count) { + var next = node.next; + for (var i = 0; i < count && next !== list.tail; i++) { + next = next.next; + } + node.next = next; + next.prev = node; + list.length -= i; + } + function toArray(list) { + var array = []; + var node = list.head.next; + while (node !== list.tail) { + array.push(node.value); + node = node.next; + } + return array; + } + if (!_self.document) { + if (!_self.addEventListener) { + return _; + } + if (!_.disableWorkerMessageHandler) { + _self.addEventListener('message', function (evt) { + var message = JSON.parse(evt.data), lang = message.language, code = message.code, immediateClose = message.immediateClose; + _self.postMessage(_.highlight(code, _.languages[lang], lang)); + if (immediateClose) { + _self.close(); + } + }, false); + } + return _; + } + var script = _.util.currentScript(); + if (script) { + _.filename = script.src; + if (script.hasAttribute('data-manual')) { + _.manual = true; + } + } + function highlightAutomaticallyCallback() { + if (!_.manual) { + _.highlightAll(); + } + } + if (!_.manual) { + var readyState = document.readyState; + if (readyState === 'loading' || readyState === 'interactive' && script && script.defer) { + document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback); + } else { + if (window.requestAnimationFrame) { + window.requestAnimationFrame(highlightAutomaticallyCallback); + } else { + window.setTimeout(highlightAutomaticallyCallback, 16); + } + } + } + return _; + }(_self); + if (typeof module !== 'undefined' && module.exports) { + module.exports = Prism; + } + if (typeof global !== 'undefined') { + global.Prism = Prism; + } + }.call(this)); + }.call(this, typeof global$2 !== 'undefined' ? global$2 : typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : {})); + }, + {} + ], + 4: [ + function (require, module, exports) { + (function (Prism) { + var keyword = /\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/; + Prism.languages.cpp = Prism.languages.extend('c', { + 'class-name': [ + { + pattern: RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g, function () { + return keyword.source; + })), + lookbehind: true + }, + /\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/, + /\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i, + /\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/ + ], + 'keyword': keyword, + 'number': { + pattern: /(?:\b0b[01']+|\b0x(?:[\da-f']+\.?[\da-f']*|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+\.?[\d']*|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]*/i, + greedy: true + }, + 'operator': />>=?|<<=?|->|([-+&|:])\1|[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/, + 'boolean': /\b(?:true|false)\b/ + }); + Prism.languages.insertBefore('cpp', 'string', { + 'raw-string': { + pattern: /R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/, + alias: 'string', + greedy: true + } + }); + Prism.languages.insertBefore('cpp', 'class-name', { + 'base-clause': { + pattern: /(\b(?:class|struct)\s+\w+\s*:\s*)(?:[^;{}"'])+?(?=\s*[;{])/, + lookbehind: true, + greedy: true, + inside: Prism.languages.extend('cpp', {}) + } + }); + Prism.languages.insertBefore('inside', 'operator', { 'class-name': /\b[a-z_]\w*\b(?!\s*::)/i }, Prism.languages.cpp['base-clause']); + }(Prism)); + }, + {} + ], + 5: [ + function (require, module, exports) { + (function (Prism) { + function replace(pattern, replacements) { + return pattern.replace(/<<(\d+)>>/g, function (m, index) { + return '(?:' + replacements[+index] + ')'; + }); + } + function re(pattern, replacements, flags) { + return RegExp(replace(pattern, replacements), flags || ''); + } + function nested(pattern, depthLog2) { + for (var i = 0; i < depthLog2; i++) { + pattern = pattern.replace(/<>/g, function () { + return '(?:' + pattern + ')'; + }); + } + return pattern.replace(/<>/g, '[^\\s\\S]'); + } + var keywordKinds = { + type: 'bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void', + typeDeclaration: 'class enum interface struct', + contextual: 'add alias and ascending async await by descending from get global group into join let nameof not notnull on or orderby partial remove select set unmanaged value when where where', + other: 'abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield' + }; + function keywordsToPattern(words) { + return '\\b(?:' + words.trim().replace(/ /g, '|') + ')\\b'; + } + var typeDeclarationKeywords = keywordsToPattern(keywordKinds.typeDeclaration); + var keywords = RegExp(keywordsToPattern(keywordKinds.type + ' ' + keywordKinds.typeDeclaration + ' ' + keywordKinds.contextual + ' ' + keywordKinds.other)); + var nonTypeKeywords = keywordsToPattern(keywordKinds.typeDeclaration + ' ' + keywordKinds.contextual + ' ' + keywordKinds.other); + var nonContextualKeywords = keywordsToPattern(keywordKinds.type + ' ' + keywordKinds.typeDeclaration + ' ' + keywordKinds.other); + var generic = nested(/<(?:[^<>;=+\-*/%&|^]|<>)*>/.source, 2); + var nestedRound = nested(/\((?:[^()]|<>)*\)/.source, 2); + var name = /@?\b[A-Za-z_]\w*\b/.source; + var genericName = replace(/<<0>>(?:\s*<<1>>)?/.source, [ + name, + generic + ]); + var identifier = replace(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source, [ + nonTypeKeywords, + genericName + ]); + var array = /\[\s*(?:,\s*)*\]/.source; + var typeExpressionWithoutTuple = replace(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source, [ + identifier, + array + ]); + var tupleElement = replace(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source, [ + generic, + nestedRound, + array + ]); + var tuple = replace(/\(<<0>>+(?:,<<0>>+)+\)/.source, [tupleElement]); + var typeExpression = replace(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source, [ + tuple, + identifier, + array + ]); + var typeInside = { + 'keyword': keywords, + 'punctuation': /[<>()?,.:[\]]/ + }; + var character = /'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source; + var regularString = /"(?:\\.|[^\\"\r\n])*"/.source; + var verbatimString = /@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source; + Prism.languages.csharp = Prism.languages.extend('clike', { + 'string': [ + { + pattern: re(/(^|[^$\\])<<0>>/.source, [verbatimString]), + lookbehind: true, + greedy: true + }, + { + pattern: re(/(^|[^@$\\])<<0>>/.source, [regularString]), + lookbehind: true, + greedy: true + }, + { + pattern: RegExp(character), + greedy: true, + alias: 'character' + } + ], + 'class-name': [ + { + pattern: re(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source, [identifier]), + lookbehind: true, + inside: typeInside + }, + { + pattern: re(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source, [ + name, + typeExpression + ]), + lookbehind: true, + inside: typeInside + }, + { + pattern: re(/(\busing\s+)<<0>>(?=\s*=)/.source, [name]), + lookbehind: true + }, + { + pattern: re(/(\b<<0>>\s+)<<1>>/.source, [ + typeDeclarationKeywords, + genericName + ]), + lookbehind: true, + inside: typeInside + }, + { + pattern: re(/(\bcatch\s*\(\s*)<<0>>/.source, [identifier]), + lookbehind: true, + inside: typeInside + }, + { + pattern: re(/(\bwhere\s+)<<0>>/.source, [name]), + lookbehind: true + }, + { + pattern: re(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source, [typeExpressionWithoutTuple]), + lookbehind: true, + inside: typeInside + }, + { + pattern: re(/\b<<0>>(?=\s+(?!<<1>>)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source, [ + typeExpression, + nonContextualKeywords, + name + ]), + inside: typeInside + } + ], + 'keyword': keywords, + 'number': /(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:ul|lu|[dflmu])?\b/i, + 'operator': />>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/, + 'punctuation': /\?\.?|::|[{}[\];(),.:]/ + }); + Prism.languages.insertBefore('csharp', 'number', { + 'range': { + pattern: /\.\./, + alias: 'operator' + } + }); + Prism.languages.insertBefore('csharp', 'punctuation', { + 'named-parameter': { + pattern: re(/([(,]\s*)<<0>>(?=\s*:)/.source, [name]), + lookbehind: true, + alias: 'punctuation' + } + }); + Prism.languages.insertBefore('csharp', 'class-name', { + 'namespace': { + pattern: re(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source, [name]), + lookbehind: true, + inside: { 'punctuation': /\./ } + }, + 'type-expression': { + pattern: re(/(\b(?:default|typeof|sizeof)\s*\(\s*)(?:[^()\s]|\s(?!\s*\))|<<0>>)*(?=\s*\))/.source, [nestedRound]), + lookbehind: true, + alias: 'class-name', + inside: typeInside + }, + 'return-type': { + pattern: re(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source, [ + typeExpression, + identifier + ]), + inside: typeInside, + alias: 'class-name' + }, + 'constructor-invocation': { + pattern: re(/(\bnew\s+)<<0>>(?=\s*[[({])/.source, [typeExpression]), + lookbehind: true, + inside: typeInside, + alias: 'class-name' + }, + 'generic-method': { + pattern: re(/<<0>>\s*<<1>>(?=\s*\()/.source, [ + name, + generic + ]), + inside: { + 'function': re(/^<<0>>/.source, [name]), + 'generic': { + pattern: RegExp(generic), + alias: 'class-name', + inside: typeInside + } + } + }, + 'type-list': { + pattern: re(/\b((?:<<0>>\s+<<1>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>)(?:\s*,\s*(?:<<3>>|<<4>>))*(?=\s*(?:where|[{;]|=>|$))/.source, [ + typeDeclarationKeywords, + genericName, + name, + typeExpression, + keywords.source + ]), + lookbehind: true, + inside: { + 'keyword': keywords, + 'class-name': { + pattern: RegExp(typeExpression), + greedy: true, + inside: typeInside + }, + 'punctuation': /,/ + } + }, + 'preprocessor': { + pattern: /(^\s*)#.*/m, + lookbehind: true, + alias: 'property', + inside: { + 'directive': { + pattern: /(\s*#)\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/, + lookbehind: true, + alias: 'keyword' + } + } + } + }); + var regularStringOrCharacter = regularString + '|' + character; + var regularStringCharacterOrComment = replace(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source, [regularStringOrCharacter]); + var roundExpression = nested(replace(/[^"'/()]|<<0>>|\(<>*\)/.source, [regularStringCharacterOrComment]), 2); + var attrTarget = /\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source; + var attr = replace(/<<0>>(?:\s*\(<<1>>*\))?/.source, [ + identifier, + roundExpression + ]); + Prism.languages.insertBefore('csharp', 'class-name', { + 'attribute': { + pattern: re(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source, [ + attrTarget, + attr + ]), + lookbehind: true, + greedy: true, + inside: { + 'target': { + pattern: re(/^<<0>>(?=\s*:)/.source, [attrTarget]), + alias: 'keyword' + }, + 'attribute-arguments': { + pattern: re(/\(<<0>>*\)/.source, [roundExpression]), + inside: Prism.languages.csharp + }, + 'class-name': { + pattern: RegExp(identifier), + inside: { 'punctuation': /\./ } + }, + 'punctuation': /[:,]/ + } + } + }); + var formatString = /:[^}\r\n]+/.source; + var mInterpolationRound = nested(replace(/[^"'/()]|<<0>>|\(<>*\)/.source, [regularStringCharacterOrComment]), 2); + var mInterpolation = replace(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source, [ + mInterpolationRound, + formatString + ]); + var sInterpolationRound = nested(replace(/[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<>*\)/.source, [regularStringOrCharacter]), 2); + var sInterpolation = replace(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source, [ + sInterpolationRound, + formatString + ]); + function createInterpolationInside(interpolation, interpolationRound) { + return { + 'interpolation': { + pattern: re(/((?:^|[^{])(?:\{\{)*)<<0>>/.source, [interpolation]), + lookbehind: true, + inside: { + 'format-string': { + pattern: re(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source, [ + interpolationRound, + formatString + ]), + lookbehind: true, + inside: { 'punctuation': /^:/ } + }, + 'punctuation': /^\{|\}$/, + 'expression': { + pattern: /[\s\S]+/, + alias: 'language-csharp', + inside: Prism.languages.csharp + } + } + }, + 'string': /[\s\S]+/ + }; + } + Prism.languages.insertBefore('csharp', 'string', { + 'interpolation-string': [ + { + pattern: re(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source, [mInterpolation]), + lookbehind: true, + greedy: true, + inside: createInterpolationInside(mInterpolation, mInterpolationRound) + }, + { + pattern: re(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source, [sInterpolation]), + lookbehind: true, + greedy: true, + inside: createInterpolationInside(sInterpolation, sInterpolationRound) + } + ] + }); + }(Prism)); + Prism.languages.dotnet = Prism.languages.cs = Prism.languages.csharp; + }, + {} + ], + 6: [ + function (require, module, exports) { + (function (Prism) { + var string = /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/; + Prism.languages.css = { + 'comment': /\/\*[\s\S]*?\*\//, + 'atrule': { + pattern: /@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/, + inside: { + 'rule': /^@[\w-]+/, + 'selector-function-argument': { + pattern: /(\bselector\s*\((?!\s*\))\s*)(?:[^()]|\((?:[^()]|\([^()]*\))*\))+?(?=\s*\))/, + lookbehind: true, + alias: 'selector' + }, + 'keyword': { + pattern: /(^|[^\w-])(?:and|not|only|or)(?![\w-])/, + lookbehind: true + } + } + }, + 'url': { + pattern: RegExp('\\burl\\((?:' + string.source + '|' + /(?:[^\\\r\n()"']|\\[\s\S])*/.source + ')\\)', 'i'), + greedy: true, + inside: { + 'function': /^url/i, + 'punctuation': /^\(|\)$/, + 'string': { + pattern: RegExp('^' + string.source + '$'), + alias: 'url' + } + } + }, + 'selector': RegExp('[^{}\\s](?:[^{};"\']|' + string.source + ')*?(?=\\s*\\{)'), + 'string': { + pattern: string, + greedy: true + }, + 'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i, + 'important': /!important\b/i, + 'function': /[-a-z0-9]+(?=\()/i, + 'punctuation': /[(){};:,]/ + }; + Prism.languages.css['atrule'].inside.rest = Prism.languages.css; + var markup = Prism.languages.markup; + if (markup) { + markup.tag.addInlined('style', 'css'); + Prism.languages.insertBefore('inside', 'attr-value', { + 'style-attr': { + pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i, + inside: { + 'attr-name': { + pattern: /^\s*style/i, + inside: markup.tag.inside + }, + 'punctuation': /^\s*=\s*['"]|['"]\s*$/, + 'attr-value': { + pattern: /.+/i, + inside: Prism.languages.css + } + }, + alias: 'language-css' + } + }, markup.tag); + } + }(Prism)); + }, + {} + ], + 7: [ + function (require, module, exports) { + (function (Prism) { + var keywords = /\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|null|open|opens|package|private|protected|provides|public|record|requires|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/; + var className = /\b[A-Z](?:\w*[a-z]\w*)?\b/; + Prism.languages.java = Prism.languages.extend('clike', { + 'class-name': [ + className, + /\b[A-Z]\w*(?=\s+\w+\s*[;,=())])/ + ], + 'keyword': keywords, + 'function': [ + Prism.languages.clike.function, + { + pattern: /(\:\:)[a-z_]\w*/, + lookbehind: true + } + ], + 'number': /\b0b[01][01_]*L?\b|\b0x[\da-f_]*\.?[\da-f_p+-]+\b|(?:\b\d[\d_]*\.?[\d_]*|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i, + 'operator': { + pattern: /(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m, + lookbehind: true + } + }); + Prism.languages.insertBefore('java', 'string', { + 'triple-quoted-string': { + pattern: /"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/, + greedy: true, + alias: 'string' + } + }); + Prism.languages.insertBefore('java', 'class-name', { + 'annotation': { + alias: 'punctuation', + pattern: /(^|[^.])@\w+/, + lookbehind: true + }, + 'namespace': { + pattern: RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(//g, function () { + return keywords.source; + })), + lookbehind: true, + inside: { 'punctuation': /\./ } + }, + 'generics': { + pattern: /<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/, + inside: { + 'class-name': className, + 'keyword': keywords, + 'punctuation': /[<>(),.:]/, + 'operator': /[?&|]/ + } + } + }); + }(Prism)); + }, + {} + ], + 8: [ + function (require, module, exports) { + Prism.languages.javascript = Prism.languages.extend('clike', { + 'class-name': [ + Prism.languages.clike['class-name'], + { + pattern: /(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/, + lookbehind: true + } + ], + 'keyword': [ + { + pattern: /((?:^|})\s*)(?:catch|finally)\b/, + lookbehind: true + }, + { + pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|(?:get|set)(?=\s*[\[$\w\xA0-\uFFFF])|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/, + lookbehind: true + } + ], + 'number': /\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/, + 'function': /#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/, + 'operator': /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/ + }); + Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/; + Prism.languages.insertBefore('javascript', 'keyword', { + 'regex': { + pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/, + lookbehind: true, + greedy: true, + inside: { + 'regex-source': { + pattern: /^(\/)[\s\S]+(?=\/[a-z]*$)/, + lookbehind: true, + alias: 'language-regex', + inside: Prism.languages.regex + }, + 'regex-flags': /[a-z]+$/, + 'regex-delimiter': /^\/|\/$/ + } + }, + 'function-variable': { + pattern: /#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/, + alias: 'function' + }, + 'parameter': [ + { + pattern: /(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/, + lookbehind: true, + inside: Prism.languages.javascript + }, + { + pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i, + inside: Prism.languages.javascript + }, + { + pattern: /(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/, + lookbehind: true, + inside: Prism.languages.javascript + }, + { + pattern: /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/, + lookbehind: true, + inside: Prism.languages.javascript + } + ], + 'constant': /\b[A-Z](?:[A-Z_]|\dx?)*\b/ + }); + Prism.languages.insertBefore('javascript', 'string', { + 'template-string': { + pattern: /`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/, + greedy: true, + inside: { + 'template-punctuation': { + pattern: /^`|`$/, + alias: 'string' + }, + 'interpolation': { + pattern: /((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/, + lookbehind: true, + inside: { + 'interpolation-punctuation': { + pattern: /^\${|}$/, + alias: 'punctuation' + }, + rest: Prism.languages.javascript + } + }, + 'string': /[\s\S]+/ + } + } + }); + if (Prism.languages.markup) { + Prism.languages.markup.tag.addInlined('script', 'javascript'); + } + Prism.languages.js = Prism.languages.javascript; + }, + {} + ], + 9: [ + function (require, module, exports) { + (function (Prism) { + function getPlaceholder(language, index) { + return '___' + language.toUpperCase() + index + '___'; + } + Object.defineProperties(Prism.languages['markup-templating'] = {}, { + buildPlaceholders: { + value: function (env, language, placeholderPattern, replaceFilter) { + if (env.language !== language) { + return; + } + var tokenStack = env.tokenStack = []; + env.code = env.code.replace(placeholderPattern, function (match) { + if (typeof replaceFilter === 'function' && !replaceFilter(match)) { + return match; + } + var i = tokenStack.length; + var placeholder; + while (env.code.indexOf(placeholder = getPlaceholder(language, i)) !== -1) + ++i; + tokenStack[i] = match; + return placeholder; + }); + env.grammar = Prism.languages.markup; + } + }, + tokenizePlaceholders: { + value: function (env, language) { + if (env.language !== language || !env.tokenStack) { + return; + } + env.grammar = Prism.languages[language]; + var j = 0; + var keys = Object.keys(env.tokenStack); + function walkTokens(tokens) { + for (var i = 0; i < tokens.length; i++) { + if (j >= keys.length) { + break; + } + var token = tokens[i]; + if (typeof token === 'string' || token.content && typeof token.content === 'string') { + var k = keys[j]; + var t = env.tokenStack[k]; + var s = typeof token === 'string' ? token : token.content; + var placeholder = getPlaceholder(language, k); + var index = s.indexOf(placeholder); + if (index > -1) { + ++j; + var before = s.substring(0, index); + var middle = new Prism.Token(language, Prism.tokenize(t, env.grammar), 'language-' + language, t); + var after = s.substring(index + placeholder.length); + var replacement = []; + if (before) { + replacement.push.apply(replacement, walkTokens([before])); + } + replacement.push(middle); + if (after) { + replacement.push.apply(replacement, walkTokens([after])); + } + if (typeof token === 'string') { + tokens.splice.apply(tokens, [ + i, + 1 + ].concat(replacement)); + } else { + token.content = replacement; + } + } + } else if (token.content) { + walkTokens(token.content); + } + } + return tokens; + } + walkTokens(env.tokens); + } + } + }); + }(Prism)); + }, + {} + ], + 10: [ + function (require, module, exports) { + Prism.languages.markup = { + 'comment': //, + 'prolog': /<\?[\s\S]+?\?>/, + 'doctype': { + pattern: /"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i, + greedy: true, + inside: { + 'internal-subset': { + pattern: /(\[)[\s\S]+(?=\]>$)/, + lookbehind: true, + greedy: true, + inside: null + }, + 'string': { + pattern: /"[^"]*"|'[^']*'/, + greedy: true + }, + 'punctuation': /^$|[[\]]/, + 'doctype-tag': /^DOCTYPE/, + 'name': /[^\s<>'"]+/ + } + }, + 'cdata': //i, + 'tag': { + pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/, + greedy: true, + inside: { + 'tag': { + pattern: /^<\/?[^\s>\/]+/, + inside: { + 'punctuation': /^<\/?/, + 'namespace': /^[^\s>\/:]+:/ + } + }, + 'attr-value': { + pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/, + inside: { + 'punctuation': [ + { + pattern: /^=/, + alias: 'attr-equals' + }, + /"|'/ + ] + } + }, + 'punctuation': /\/?>/, + 'attr-name': { + pattern: /[^\s>\/]+/, + inside: { 'namespace': /^[^\s>\/:]+:/ } + } + } + }, + 'entity': [ + { + pattern: /&[\da-z]{1,8};/i, + alias: 'named-entity' + }, + /&#x?[\da-f]{1,8};/i + ] + }; + Prism.languages.markup['tag'].inside['attr-value'].inside['entity'] = Prism.languages.markup['entity']; + Prism.languages.markup['doctype'].inside['internal-subset'].inside = Prism.languages.markup; + Prism.hooks.add('wrap', function (env) { + if (env.type === 'entity') { + env.attributes['title'] = env.content.replace(/&/, '&'); + } + }); + Object.defineProperty(Prism.languages.markup.tag, 'addInlined', { + value: function addInlined(tagName, lang) { + var includedCdataInside = {}; + includedCdataInside['language-' + lang] = { + pattern: /(^$)/i, + lookbehind: true, + inside: Prism.languages[lang] + }; + includedCdataInside['cdata'] = /^$/i; + var inside = { + 'included-cdata': { + pattern: //i, + inside: includedCdataInside + } + }; + inside['language-' + lang] = { + pattern: /[\s\S]+/, + inside: Prism.languages[lang] + }; + var def = {}; + def[tagName] = { + pattern: RegExp(/(<__[\s\S]*?>)(?:))*\]\]>|(?!)/.source.replace(/__/g, function () { + return tagName; + }), 'i'), + lookbehind: true, + greedy: true, + inside: inside + }; + Prism.languages.insertBefore('markup', 'cdata', def); + } + }); + Prism.languages.html = Prism.languages.markup; + Prism.languages.mathml = Prism.languages.markup; + Prism.languages.svg = Prism.languages.markup; + Prism.languages.xml = Prism.languages.extend('markup', {}); + Prism.languages.ssml = Prism.languages.xml; + Prism.languages.atom = Prism.languages.xml; + Prism.languages.rss = Prism.languages.xml; + }, + {} + ], + 11: [ + function (require, module, exports) { + (function (Prism) { + Prism.languages.php = Prism.languages.extend('clike', { + 'keyword': /\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|new|or|parent|print|private|protected|public|require|require_once|return|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i, + 'boolean': { + pattern: /\b(?:false|true)\b/i, + alias: 'constant' + }, + 'constant': [ + /\b[A-Z_][A-Z0-9_]*\b/, + /\b(?:null)\b/i + ], + 'comment': { + pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/, + lookbehind: true + } + }); + Prism.languages.insertBefore('php', 'string', { + 'shell-comment': { + pattern: /(^|[^\\])#.*/, + lookbehind: true, + alias: 'comment' + } + }); + Prism.languages.insertBefore('php', 'comment', { + 'delimiter': { + pattern: /\?>$|^<\?(?:php(?=\s)|=)?/i, + alias: 'important' + } + }); + Prism.languages.insertBefore('php', 'keyword', { + 'variable': /\$+(?:\w+\b|(?={))/i, + 'package': { + pattern: /(\\|namespace\s+|use\s+)[\w\\]+/, + lookbehind: true, + inside: { punctuation: /\\/ } + } + }); + Prism.languages.insertBefore('php', 'operator', { + 'property': { + pattern: /(->)[\w]+/, + lookbehind: true + } + }); + var string_interpolation = { + pattern: /{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)*)/, + lookbehind: true, + inside: Prism.languages.php + }; + Prism.languages.insertBefore('php', 'string', { + 'nowdoc-string': { + pattern: /<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/, + greedy: true, + alias: 'string', + inside: { + 'delimiter': { + pattern: /^<<<'[^']+'|[a-z_]\w*;$/i, + alias: 'symbol', + inside: { 'punctuation': /^<<<'?|[';]$/ } + } + } + }, + 'heredoc-string': { + pattern: /<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i, + greedy: true, + alias: 'string', + inside: { + 'delimiter': { + pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i, + alias: 'symbol', + inside: { 'punctuation': /^<<<"?|[";]$/ } + }, + 'interpolation': string_interpolation + } + }, + 'single-quoted-string': { + pattern: /'(?:\\[\s\S]|[^\\'])*'/, + greedy: true, + alias: 'string' + }, + 'double-quoted-string': { + pattern: /"(?:\\[\s\S]|[^\\"])*"/, + greedy: true, + alias: 'string', + inside: { 'interpolation': string_interpolation } + } + }); + delete Prism.languages.php['string']; + Prism.hooks.add('before-tokenize', function (env) { + if (!/<\?/.test(env.code)) { + return; + } + var phpPattern = /<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#)(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|\/\*[\s\S]*?(?:\*\/|$))*?(?:\?>|$)/ig; + Prism.languages['markup-templating'].buildPlaceholders(env, 'php', phpPattern); + }); + Prism.hooks.add('after-tokenize', function (env) { + Prism.languages['markup-templating'].tokenizePlaceholders(env, 'php'); + }); + }(Prism)); + }, + {} + ], + 12: [ + function (require, module, exports) { + Prism.languages.python = { + 'comment': { + pattern: /(^|[^\\])#.*/, + lookbehind: true + }, + 'string-interpolation': { + pattern: /(?:f|rf|fr)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i, + greedy: true, + inside: { + 'interpolation': { + pattern: /((?:^|[^{])(?:{{)*){(?!{)(?:[^{}]|{(?!{)(?:[^{}]|{(?!{)(?:[^{}])+})+})+}/, + lookbehind: true, + inside: { + 'format-spec': { + pattern: /(:)[^:(){}]+(?=}$)/, + lookbehind: true + }, + 'conversion-option': { + pattern: /![sra](?=[:}]$)/, + alias: 'punctuation' + }, + rest: null + } + }, + 'string': /[\s\S]+/ + } + }, + 'triple-quoted-string': { + pattern: /(?:[rub]|rb|br)?("""|''')[\s\S]*?\1/i, + greedy: true, + alias: 'string' + }, + 'string': { + pattern: /(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i, + greedy: true + }, + 'function': { + pattern: /((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g, + lookbehind: true + }, + 'class-name': { + pattern: /(\bclass\s+)\w+/i, + lookbehind: true + }, + 'decorator': { + pattern: /(^\s*)@\w+(?:\.\w+)*/im, + lookbehind: true, + alias: [ + 'annotation', + 'punctuation' + ], + inside: { 'punctuation': /\./ } + }, + 'keyword': /\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/, + 'builtin': /\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/, + 'boolean': /\b(?:True|False|None)\b/, + 'number': /(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i, + 'operator': /[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/, + 'punctuation': /[{}[\];(),.:]/ + }; + Prism.languages.python['string-interpolation'].inside['interpolation'].inside.rest = Prism.languages.python; + Prism.languages.py = Prism.languages.python; + }, + {} + ], + 13: [ + function (require, module, exports) { + (function (Prism) { + Prism.languages.ruby = Prism.languages.extend('clike', { + 'comment': [ + /#.*/, + { + pattern: /^=begin\s[\s\S]*?^=end/m, + greedy: true + } + ], + 'class-name': { + pattern: /(\b(?:class)\s+|\bcatch\s+\()[\w.\\]+/i, + lookbehind: true, + inside: { 'punctuation': /[.\\]/ } + }, + 'keyword': /\b(?:alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|protected|private|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/ + }); + var interpolation = { + pattern: /#\{[^}]+\}/, + inside: { + 'delimiter': { + pattern: /^#\{|\}$/, + alias: 'tag' + }, + rest: Prism.languages.ruby + } + }; + delete Prism.languages.ruby.function; + Prism.languages.insertBefore('ruby', 'keyword', { + 'regex': [ + { + pattern: RegExp(/%r/.source + '(?:' + [ + /([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1[gim]{0,3}/.source, + /\((?:[^()\\]|\\[\s\S])*\)[gim]{0,3}/.source, + /\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}[gim]{0,3}/.source, + /\[(?:[^\[\]\\]|\\[\s\S])*\][gim]{0,3}/.source, + /<(?:[^<>\\]|\\[\s\S])*>[gim]{0,3}/.source + ].join('|') + ')'), + greedy: true, + inside: { 'interpolation': interpolation } + }, + { + pattern: /(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[gim]{0,3}(?=\s*(?:$|[\r\n,.;})]))/, + lookbehind: true, + greedy: true + } + ], + 'variable': /[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/, + 'symbol': { + pattern: /(^|[^:]):[a-zA-Z_]\w*(?:[?!]|\b)/, + lookbehind: true + }, + 'method-definition': { + pattern: /(\bdef\s+)[\w.]+/, + lookbehind: true, + inside: { + 'function': /\w+$/, + rest: Prism.languages.ruby + } + } + }); + Prism.languages.insertBefore('ruby', 'number', { + 'builtin': /\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|Fixnum|Float|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\b/, + 'constant': /\b[A-Z]\w*(?:[?!]|\b)/ + }); + Prism.languages.ruby.string = [ + { + pattern: RegExp(/%[qQiIwWxs]?/.source + '(?:' + [ + /([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source, + /\((?:[^()\\]|\\[\s\S])*\)/.source, + /\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}/.source, + /\[(?:[^\[\]\\]|\\[\s\S])*\]/.source, + /<(?:[^<>\\]|\\[\s\S])*>/.source + ].join('|') + ')'), + greedy: true, + inside: { 'interpolation': interpolation } + }, + { + pattern: /("|')(?:#\{[^}]+\}|\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, + greedy: true, + inside: { 'interpolation': interpolation } + } + ]; + Prism.languages.rb = Prism.languages.ruby; + }(Prism)); + }, + {} + ], + 14: [ + function (require, module, exports) { + var Prism = require('prismjs/components/prism-core'); + require('prismjs/components/prism-clike'); + require('prismjs/components/prism-markup-templating'); + require('prismjs/components/prism-c'); + require('prismjs/components/prism-cpp'); + require('prismjs/components/prism-csharp'); + require('prismjs/components/prism-css'); + require('prismjs/components/prism-java'); + require('prismjs/components/prism-javascript'); + require('prismjs/components/prism-markup'); + require('prismjs/components/prism-php'); + require('prismjs/components/prism-python'); + require('prismjs/components/prism-ruby'); + module.exports = { boltExport: Prism }; + }, + { + 'prismjs/components/prism-c': 1, + 'prismjs/components/prism-clike': 2, + 'prismjs/components/prism-core': 3, + 'prismjs/components/prism-cpp': 4, + 'prismjs/components/prism-csharp': 5, + 'prismjs/components/prism-css': 6, + 'prismjs/components/prism-java': 7, + 'prismjs/components/prism-javascript': 8, + 'prismjs/components/prism-markup': 10, + 'prismjs/components/prism-markup-templating': 9, + 'prismjs/components/prism-php': 11, + 'prismjs/components/prism-python': 12, + 'prismjs/components/prism-ruby': 13 + } + ] + }, {}, [14])(14); + })); + var prism = window.Prism; + window.Prism = oldprism; + return prism; + }(undefined, exports$1, module, undefined)); + var Prism$1 = module.exports.boltExport; + + var getLanguages = function (editor) { + return editor.getParam('codesample_languages'); + }; + var useGlobalPrismJS = function (editor) { + return editor.getParam('codesample_global_prismjs', false, 'boolean'); + }; + + var get$1 = function (editor) { + return Global.Prism && useGlobalPrismJS(editor) ? Global.Prism : Prism$1; + }; + + var getSelectedCodeSample = function (editor) { + var node = editor.selection ? editor.selection.getNode() : null; + if (isCodeSample(node)) { + return Optional.some(node); + } + return Optional.none(); + }; + var insertCodeSample = function (editor, language, code) { + editor.undoManager.transact(function () { + var node = getSelectedCodeSample(editor); + code = global$1.DOM.encode(code); + return node.fold(function () { + editor.insertContent('

                                                                                          ' + code + '
                                                                                          '); + editor.selection.select(editor.$('#__new').removeAttr('id')[0]); + }, function (n) { + editor.dom.setAttrib(n, 'class', 'language-' + language); + n.innerHTML = code; + get$1(editor).highlightElement(n); + editor.selection.select(n); + }); + }); + }; + var getCurrentCode = function (editor) { + var node = getSelectedCodeSample(editor); + return node.fold(function () { + return ''; + }, function (n) { + return n.textContent; + }); + }; + + var getLanguages$1 = function (editor) { + var defaultLanguages = [ + { + text: 'HTML/XML', + value: 'markup' + }, + { + text: 'JavaScript', + value: 'javascript' + }, + { + text: 'CSS', + value: 'css' + }, + { + text: 'PHP', + value: 'php' + }, + { + text: 'Ruby', + value: 'ruby' + }, + { + text: 'Python', + value: 'python' + }, + { + text: 'Java', + value: 'java' + }, + { + text: 'C', + value: 'c' + }, + { + text: 'C#', + value: 'csharp' + }, + { + text: 'C++', + value: 'cpp' + } + ]; + var customLanguages = getLanguages(editor); + return customLanguages ? customLanguages : defaultLanguages; + }; + var getCurrentLanguage = function (editor, fallback) { + var node = getSelectedCodeSample(editor); + return node.fold(function () { + return fallback; + }, function (n) { + var matches = n.className.match(/language-(\w+)/); + return matches ? matches[1] : fallback; + }); + }; + + var open = function (editor) { + var languages = getLanguages$1(editor); + var defaultLanguage = head(languages).fold(function () { + return ''; + }, function (l) { + return l.value; + }); + var currentLanguage = getCurrentLanguage(editor, defaultLanguage); + var currentCode = getCurrentCode(editor); + editor.windowManager.open({ + title: 'Insert/Edit Code Sample', + size: 'large', + body: { + type: 'panel', + items: [ + { + type: 'selectbox', + name: 'language', + label: 'Language', + items: languages + }, + { + type: 'textarea', + name: 'code', + label: 'Code view' + } + ] + }, + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true + } + ], + initialData: { + language: currentLanguage, + code: currentCode + }, + onSubmit: function (api) { + var data = api.getData(); + insertCodeSample(editor, data.language, data.code); + api.close(); + } + }); + }; + + var register = function (editor) { + editor.addCommand('codesample', function () { + var node = editor.selection.getNode(); + if (editor.selection.isCollapsed() || isCodeSample(node)) { + open(editor); + } else { + editor.formatter.toggle('code'); + } + }); + }; + + var setup = function (editor) { + var $ = editor.$; + editor.on('PreProcess', function (e) { + $('pre[contenteditable=false]', e.node).filter(trimArg(isCodeSample)).each(function (idx, elm) { + var $elm = $(elm), code = elm.textContent; + $elm.attr('class', $.trim($elm.attr('class'))); + $elm.removeAttr('contentEditable'); + $elm.empty().append($('').each(function () { + this.textContent = code; + })); + }); + }); + editor.on('SetContent', function () { + var unprocessedCodeSamples = $('pre').filter(trimArg(isCodeSample)).filter(function (idx, elm) { + return elm.contentEditable !== 'false'; + }); + if (unprocessedCodeSamples.length) { + editor.undoManager.transact(function () { + unprocessedCodeSamples.each(function (idx, elm) { + $(elm).find('br').each(function (idx, elm) { + elm.parentNode.replaceChild(editor.getDoc().createTextNode('\n'), elm); + }); + elm.contentEditable = 'false'; + elm.innerHTML = editor.dom.encode(elm.textContent); + get$1(editor).highlightElement(elm); + elm.className = $.trim(elm.className); + }); + }); + } + }); + }; + + var isCodeSampleSelection = function (editor) { + var node = editor.selection.getStart(); + return editor.dom.is(node, 'pre[class*="language-"]'); + }; + var register$1 = function (editor) { + editor.ui.registry.addToggleButton('codesample', { + icon: 'code-sample', + tooltip: 'Insert/edit code sample', + onAction: function () { + return open(editor); + }, + onSetup: function (api) { + var nodeChangeHandler = function () { + api.setActive(isCodeSampleSelection(editor)); + }; + editor.on('NodeChange', nodeChangeHandler); + return function () { + return editor.off('NodeChange', nodeChangeHandler); + }; + } + }); + editor.ui.registry.addMenuItem('codesample', { + text: 'Code sample...', + icon: 'code-sample', + onAction: function () { + return open(editor); + } + }); + }; + + function Plugin () { + global.add('codesample', function (editor) { + setup(editor); + register$1(editor); + register(editor); + editor.on('dblclick', function (ev) { + if (isCodeSample(ev.target)) { + open(editor); + } + }); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/codesample/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/codesample/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..53f78f8a74bbee469a2368a0f07afc4c94ffc996 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/codesample/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var e,n,t,r=tinymce.util.Tools.resolve("tinymce.PluginManager"),s=function(e){return function(){return e}},i=s(!1),o=s(!0),a=function(){return l},l=(e=function(e){return e.isNone()},{fold:function(e,n){return e()},is:i,isSome:i,isNone:o,getOr:t=function(e){return e},getOrThunk:n=function(e){return e()},getOrDie:function(e){throw new Error(e||"error: getOrDie called on none.")},getOrNull:s(null),getOrUndefined:s(undefined),or:t,orThunk:n,map:a,each:function(){},bind:a,exists:i,forall:o,filter:a,equals:e,equals_:e,toArray:function(){return[]},toString:s("none()")}),u=function(t){var e=s(t),n=function(){return a},r=function(e){return e(t)},a={fold:function(e,n){return n(t)},is:function(e){return t===e},isSome:o,isNone:i,getOr:e,getOrThunk:e,getOrDie:e,getOrNull:e,getOrUndefined:e,or:n,orThunk:n,map:function(e){return u(e(t))},each:function(e){e(t)},bind:r,exists:r,forall:r,filter:function(e){return e(t)?a:l},toArray:function(){return[t]},toString:function(){return"some("+t+")"},equals:function(e){return e.is(t)},equals_:function(e,n){return e.fold(i,function(e){return n(t,e)})}};return a},c={some:u,none:a,from:function(e){return null===e||e===undefined?l:u(e)}},p=function(e){return n=e,(t=0)<=t&&t>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/,number:/(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Prism.languages.c.string],comment:Prism.languages.c.comment,directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:Prism.languages.c}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c["boolean"]},{}],2:[function(e,n,t){Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(?:true|false)\b/,"function":/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}},{}],3:[function(e,t,n){(function(n){(function(){var e=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,O={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function a(e){return e instanceof N?new N(e.type,a(e.content),e.alias):Array.isArray(e)?e.map(a):e.replace(/&/g,"&").replace(/=s.reach);y+=b.value.length,b=b.next){var v=b.value;if(n.length>e.length)return;if(!(v instanceof N)){var w,k,x,_,P,F,A=1;if(g&&b!=n.tail.prev){h.lastIndex=y;var S=h.exec(e);if(!S)break;var $=S.index+(d&&S[1]?S[1].length:0),j=S.index+S[0].length,E=y;for(E+=b.value.length;E<=$;)b=b.next,E+=b.value.length;if(E-=b.value.length,y=E,b.value instanceof N)continue;for(var z=b;z!==n.tail&&(Es.reach&&(s.reach=_),P=b.prev,k&&(P=B(n,P,k),y+=k.length),T(n,P,A),F=new N(i,p?O.tokenize(w,p):w,f,w),b=B(n,P,F),x&&B(n,b,x),1"+r.content+""},!u.document)return u.addEventListener&&(O.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(O.highlight(r,O.languages[t],t)),a&&u.close()},!1)),O;var e,t=O.util.currentScript();function r(){O.manual||O.highlightAll()}return t&&(O.filename=t.src,t.hasAttribute("data-manual")&&(O.manual=!0)),O.manual||("loading"===(e=document.readyState)||"interactive"===e&&t&&t.defer?document.addEventListener("DOMContentLoaded",r):window.requestAnimationFrame?window.requestAnimationFrame(r):window.setTimeout(r,16)),O}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{});void 0!==t&&t.exports&&(t.exports=e),void 0!==n&&(n.Prism=e)}).call(this)}).call(this,void 0!==y?y:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],4:[function(e,n,t){var r,a;r=Prism,a=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,r.languages.cpp=r.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,function(){return a.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:a,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+\.?[\da-f']*|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+\.?[\d']*|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]*/i,greedy:!0},operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,"boolean":/\b(?:true|false)\b/}),r.languages.insertBefore("cpp","string",{"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),r.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)(?:[^;{}"'])+?(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:r.languages.extend("cpp",{})}}),r.languages.insertBefore("inside","operator",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},r.languages.cpp["base-clause"])},{}],5:[function(e,n,t){!function(t){function r(e,t){return e.replace(/<<(\d+)>>/g,function(e,n){return"(?:"+t[+n]+")"})}function a(e,n,t){return RegExp(r(e,n),t||"")}function e(e,n){for(var t=0;t>/g,function(){return"(?:"+e+")"});return e.replace(/<>/g,"[^\\s\\S]")}var n="bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",s="class enum interface struct",i="add alias and ascending async await by descending from get global group into join let nameof not notnull on or orderby partial remove select set unmanaged value when where where",o="abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield";function l(e){return"\\b(?:"+e.trim().replace(/ /g,"|")+")\\b"}var u=l(s),c=RegExp(l(n+" "+s+" "+i+" "+o)),p=l(s+" "+i+" "+o),d=l(n+" "+s+" "+o),g=e(/<(?:[^<>;=+\-*/%&|^]|<>)*>/.source,2),m=e(/\((?:[^()]|<>)*\)/.source,2),f=/@?\b[A-Za-z_]\w*\b/.source,h=r(/<<0>>(?:\s*<<1>>)?/.source,[f,g]),b=r(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source,[p,h]),y=/\[\s*(?:,\s*)*\]/.source,v=r(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source,[b,y]),w=r(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source,[g,m,y]),k=r(/\(<<0>>+(?:,<<0>>+)+\)/.source,[w]),x=r(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source,[k,b,y]),_={keyword:c,punctuation:/[<>()?,.:[\]]/},P=/'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source,F=/"(?:\\.|[^\\"\r\n])*"/.source,A=/@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source;t.languages.csharp=t.languages.extend("clike",{string:[{pattern:a(/(^|[^$\\])<<0>>/.source,[A]),lookbehind:!0,greedy:!0},{pattern:a(/(^|[^@$\\])<<0>>/.source,[F]),lookbehind:!0,greedy:!0},{pattern:RegExp(P),greedy:!0,alias:"character"}],"class-name":[{pattern:a(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source,[b]),lookbehind:!0,inside:_},{pattern:a(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source,[f,x]),lookbehind:!0,inside:_},{pattern:a(/(\busing\s+)<<0>>(?=\s*=)/.source,[f]),lookbehind:!0},{pattern:a(/(\b<<0>>\s+)<<1>>/.source,[u,h]),lookbehind:!0,inside:_},{pattern:a(/(\bcatch\s*\(\s*)<<0>>/.source,[b]),lookbehind:!0,inside:_},{pattern:a(/(\bwhere\s+)<<0>>/.source,[f]),lookbehind:!0},{pattern:a(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source,[v]),lookbehind:!0,inside:_},{pattern:a(/\b<<0>>(?=\s+(?!<<1>>)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source,[x,d,f]),inside:_}],keyword:c,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:ul|lu|[dflmu])?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),t.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),t.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:a(/([(,]\s*)<<0>>(?=\s*:)/.source,[f]),lookbehind:!0,alias:"punctuation"}}),t.languages.insertBefore("csharp","class-name",{namespace:{pattern:a(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source,[f]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:a(/(\b(?:default|typeof|sizeof)\s*\(\s*)(?:[^()\s]|\s(?!\s*\))|<<0>>)*(?=\s*\))/.source,[m]),lookbehind:!0,alias:"class-name",inside:_},"return-type":{pattern:a(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source,[x,b]),inside:_,alias:"class-name"},"constructor-invocation":{pattern:a(/(\bnew\s+)<<0>>(?=\s*[[({])/.source,[x]),lookbehind:!0,inside:_,alias:"class-name"},"generic-method":{pattern:a(/<<0>>\s*<<1>>(?=\s*\()/.source,[f,g]),inside:{"function":a(/^<<0>>/.source,[f]),generic:{pattern:RegExp(g),alias:"class-name",inside:_}}},"type-list":{pattern:a(/\b((?:<<0>>\s+<<1>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>)(?:\s*,\s*(?:<<3>>|<<4>>))*(?=\s*(?:where|[{;]|=>|$))/.source,[u,h,f,x,c.source]),lookbehind:!0,inside:{keyword:c,"class-name":{pattern:RegExp(x),greedy:!0,inside:_},punctuation:/,/}},preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(\s*#)\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var S=F+"|"+P,$=r(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source,[S]),j=e(r(/[^"'/()]|<<0>>|\(<>*\)/.source,[$]),2),E=/\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source,z=r(/<<0>>(?:\s*\(<<1>>*\))?/.source,[b,j]);t.languages.insertBefore("csharp","class-name",{attribute:{pattern:a(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source,[E,z]),lookbehind:!0,greedy:!0,inside:{target:{pattern:a(/^<<0>>(?=\s*:)/.source,[E]),alias:"keyword"},"attribute-arguments":{pattern:a(/\(<<0>>*\)/.source,[j]),inside:t.languages.csharp},"class-name":{pattern:RegExp(b),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var C=/:[^}\r\n]+/.source,O=e(r(/[^"'/()]|<<0>>|\(<>*\)/.source,[$]),2),N=r(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[O,C]),B=e(r(/[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<>*\)/.source,[S]),2),T=r(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[B,C]);function D(e,n){return{interpolation:{pattern:a(/((?:^|[^{])(?:\{\{)*)<<0>>/.source,[e]),lookbehind:!0,inside:{"format-string":{pattern:a(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source,[n,C]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:t.languages.csharp}}},string:/[\s\S]+/}}t.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:a(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source,[N]),lookbehind:!0,greedy:!0,inside:D(N,O)},{pattern:a(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source,[T]),lookbehind:!0,greedy:!0,inside:D(T,B)}]})}(Prism),Prism.languages.dotnet=Prism.languages.cs=Prism.languages.csharp},{}],6:[function(e,n,t){!function(e){var n=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\((?!\s*\))\s*)(?:[^()]|\((?:[^()]|\([^()]*\))*\))+?(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+n.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{"function":/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+n.source+"$"),alias:"url"}}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+n.source+")*?(?=\\s*\\{)"),string:{pattern:n,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var t=e.languages.markup;t&&(t.tag.addInlined("style","css"),e.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:t.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:e.languages.css}},alias:"language-css"}},t.tag))}(Prism)},{}],7:[function(e,n,t){var r,a,s;r=Prism,a=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|null|open|opens|package|private|protected|provides|public|record|requires|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,s=/\b[A-Z](?:\w*[a-z]\w*)?\b/,r.languages.java=r.languages.extend("clike",{"class-name":[s,/\b[A-Z]\w*(?=\s+\w+\s*[;,=())])/],keyword:a,"function":[r.languages.clike["function"],{pattern:/(\:\:)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x[\da-f_]*\.?[\da-f_p+-]+\b|(?:\b\d[\d_]*\.?[\d_]*|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),r.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"}}),r.languages.insertBefore("java","class-name",{annotation:{alias:"punctuation",pattern:/(^|[^.])@\w+/,lookbehind:!0},namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(//g,function(){return a.source})),lookbehind:!0,inside:{punctuation:/\./}},generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":s,keyword:a,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})},{}],8:[function(e,n,t){Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|(?:get|set)(?=\s*[\[$\w\xA0-\uFFFF])|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,"function":/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-flags":/[a-z]+$/,"regex-delimiter":/^\/|\/$/}},"function-variable":{pattern:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.js=Prism.languages.javascript},{}],9:[function(e,n,t){function b(e,n){return"___"+e.toUpperCase()+n+"___"}var y;y=Prism,Object.defineProperties(y.languages["markup-templating"]={},{buildPlaceholders:{value:function(r,a,e,s){var i;r.language===a&&(i=r.tokenStack=[],r.code=r.code.replace(e,function(e){if("function"==typeof s&&!s(e))return e;for(var n,t=i.length;-1!==r.code.indexOf(n=b(a,t));)++t;return i[t]=e,n}),r.grammar=y.languages.markup)}},tokenizePlaceholders:{value:function(d,g){var m,f;d.language===g&&d.tokenStack&&(d.grammar=y.languages[g],m=0,f=Object.keys(d.tokenStack),function h(e){for(var n=0;n=f.length);n++){var t,r,a,s,i,o,l,u,c,p=e[n];"string"==typeof p||p.content&&"string"==typeof p.content?(t=f[m],r=d.tokenStack[t],a="string"==typeof p?p:p.content,s=b(g,t),-1<(i=a.indexOf(s))&&(++m,o=a.substring(0,i),l=new y.Token(g,y.tokenize(r,d.grammar),"language-"+g,r),u=a.substring(i+s.length),c=[],o&&c.push.apply(c,h([o])),c.push(l),u&&c.push.apply(c,h([u])),"string"==typeof p?e.splice.apply(e,[n,1].concat(c)):p.content=c)):p.content&&h(p.content)}return e}(d.tokens))}}})},{}],10:[function(e,n,t){Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/,name:/[^\s<>'"]+/}},cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(e,n){var t={};t["language-"+n]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[n]},t.cdata=/^$/i;var r={"included-cdata":{pattern://i,inside:t}};r["language-"+n]={pattern:/[\s\S]+/,inside:Prism.languages[n]};var a={};a[e]={pattern:RegExp(/(<__[\s\S]*?>)(?:))*\]\]>|(?!)/.source.replace(/__/g,function(){return e}),"i"),lookbehind:!0,greedy:!0,inside:r},Prism.languages.insertBefore("markup","cdata",a)}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml},{}],11:[function(e,n,t){!function(n){n.languages.php=n.languages.extend("clike",{keyword:/\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|new|or|parent|print|private|protected|public|require|require_once|return|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,"boolean":{pattern:/\b(?:false|true)\b/i,alias:"constant"},constant:[/\b[A-Z_][A-Z0-9_]*\b/,/\b(?:null)\b/i],comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0}}),n.languages.insertBefore("php","string",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),n.languages.insertBefore("php","comment",{delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"}}),n.languages.insertBefore("php","keyword",{variable:/\$+(?:\w+\b|(?={))/i,"package":{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),n.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}});var e={pattern:/{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)*)/,lookbehind:!0,inside:n.languages.php};n.languages.insertBefore("php","string",{"nowdoc-string":{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},"heredoc-string":{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:e}},"single-quoted-string":{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0,alias:"string"},"double-quoted-string":{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,alias:"string",inside:{interpolation:e}}}),delete n.languages.php.string,n.hooks.add("before-tokenize",function(e){/<\?/.test(e.code)&&n.languages["markup-templating"].buildPlaceholders(e,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#)(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|\/\*[\s\S]*?(?:\*\/|$))*?(?:\?>|$)/gi)}),n.hooks.add("after-tokenize",function(e){n.languages["markup-templating"].tokenizePlaceholders(e,"php")})}(Prism)},{}],12:[function(e,n,t){Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},"string-interpolation":{pattern:/(?:f|rf|fr)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:{{)*){(?!{)(?:[^{}]|{(?!{)(?:[^{}]|{(?!{)(?:[^{}])+})+})+}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|rb|br)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},"function":{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^\s*)@\w+(?:\.\w+)*/im,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,"boolean":/\b(?:True|False|None)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python},{}],13:[function(e,n,t){!function(e){e.languages.ruby=e.languages.extend("clike",{comment:[/#.*/,{pattern:/^=begin\s[\s\S]*?^=end/m,greedy:!0}],"class-name":{pattern:/(\b(?:class)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|protected|private|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/});var n={pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"tag"},rest:e.languages.ruby}};delete e.languages.ruby["function"],e.languages.insertBefore("ruby","keyword",{regex:[{pattern:RegExp(/%r/.source+"(?:"+[/([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1[gim]{0,3}/.source,/\((?:[^()\\]|\\[\s\S])*\)[gim]{0,3}/.source,/\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}[gim]{0,3}/.source,/\[(?:[^\[\]\\]|\\[\s\S])*\][gim]{0,3}/.source,/<(?:[^<>\\]|\\[\s\S])*>[gim]{0,3}/.source].join("|")+")"),greedy:!0,inside:{interpolation:n}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[gim]{0,3}(?=\s*(?:$|[\r\n,.;})]))/,lookbehind:!0,greedy:!0}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:{pattern:/(^|[^:]):[a-zA-Z_]\w*(?:[?!]|\b)/,lookbehind:!0},"method-definition":{pattern:/(\bdef\s+)[\w.]+/,lookbehind:!0,inside:{"function":/\w+$/,rest:e.languages.ruby}}}),e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|Fixnum|Float|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\b/,constant:/\b[A-Z]\w*(?:[?!]|\b)/}),e.languages.ruby.string=[{pattern:RegExp(/%[qQiIwWxs]?/.source+"(?:"+[/([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/\((?:[^()\\]|\\[\s\S])*\)/.source,/\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}/.source,/\[(?:[^\[\]\\]|\\[\s\S])*\]/.source,/<(?:[^<>\\]|\\[\s\S])*>/.source].join("|")+")"),greedy:!0,inside:{interpolation:n}},{pattern:/("|')(?:#\{[^}]+\}|\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{interpolation:n}}],e.languages.rb=e.languages.ruby}(Prism)},{}],14:[function(e,n,t){var r=e("prismjs/components/prism-core");e("prismjs/components/prism-clike"),e("prismjs/components/prism-markup-templating"),e("prismjs/components/prism-c"),e("prismjs/components/prism-cpp"),e("prismjs/components/prism-csharp"),e("prismjs/components/prism-css"),e("prismjs/components/prism-java"),e("prismjs/components/prism-javascript"),e("prismjs/components/prism-markup"),e("prismjs/components/prism-php"),e("prismjs/components/prism-python"),e("prismjs/components/prism-ruby"),n.exports={boltExport:r}},{"prismjs/components/prism-c":1,"prismjs/components/prism-clike":2,"prismjs/components/prism-core":3,"prismjs/components/prism-cpp":4,"prismjs/components/prism-csharp":5,"prismjs/components/prism-css":6,"prismjs/components/prism-java":7,"prismjs/components/prism-javascript":8,"prismjs/components/prism-markup":10,"prismjs/components/prism-markup-templating":9,"prismjs/components/prism-php":11,"prismjs/components/prism-python":12,"prismjs/components/prism-ruby":13}]},{},[14])(14)});var a=window.Prism;window.Prism=e}(undefined,h,b,undefined);var v=b.exports.boltExport,w=function(e){return f.Prism&&e.getParam("codesample_global_prismjs",!1,"boolean")?f.Prism:v},k=function(e){var n=e.selection?e.selection.getNode():null;return g(n)?c.some(n):c.none()},x=function(s){var t,e=s.getParam("codesample_languages")||[{text:"HTML/XML",value:"markup"},{text:"JavaScript",value:"javascript"},{text:"CSS",value:"css"},{text:"PHP",value:"php"},{text:"Ruby",value:"ruby"},{text:"Python",value:"python"},{text:"Java",value:"java"},{text:"C",value:"c"},{text:"C#",value:"csharp"},{text:"C++",value:"cpp"}],n=p(e).fold(function(){return""},function(e){return e.value}),r=(t=n,k(s).fold(function(){return t},function(e){var n=e.className.match(/language-(\w+)/);return n?n[1]:t})),a=k(s).fold(function(){return""},function(e){return e.textContent});s.windowManager.open({title:"Insert/Edit Code Sample",size:"large",body:{type:"panel",items:[{type:"selectbox",name:"language",label:"Language",items:e},{type:"textarea",name:"code",label:"Code view"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{language:r,code:a},onSubmit:function(e){var n,t,r,a=e.getData();n=s,t=a.language,r=a.code,n.undoManager.transact(function(){var e=k(n);return r=d.DOM.encode(r),e.fold(function(){n.insertContent('
                                                                                          '+r+"
                                                                                          "),n.selection.select(n.$("#__new").removeAttr("id")[0])},function(e){n.dom.setAttrib(e,"class","language-"+t),e.innerHTML=r,w(n).highlightElement(e),n.selection.select(e)})}),e.close()}})},_=function(r){r.ui.registry.addToggleButton("codesample",{icon:"code-sample",tooltip:"Insert/edit code sample",onAction:function(){return x(r)},onSetup:function(t){var e=function(){var e,n;t.setActive((n=(e=r).selection.getStart(),e.dom.is(n,'pre[class*="language-"]')))};return r.on("NodeChange",e),function(){return r.off("NodeChange",e)}}}),r.ui.registry.addMenuItem("codesample",{text:"Code sample...",icon:"code-sample",onAction:function(){return x(r)}})};r.add("codesample",function(n){var t,a,r;a=(t=n).$,t.on("PreProcess",function(e){a("pre[contenteditable=false]",e.node).filter(m(g)).each(function(e,n){var t=a(n),r=n.textContent;t.attr("class",a.trim(t.attr("class"))),t.removeAttr("contentEditable"),t.empty().append(a("").each(function(){this.textContent=r}))})}),t.on("SetContent",function(){var e=a("pre").filter(m(g)).filter(function(e,n){return"false"!==n.contentEditable});e.length&&t.undoManager.transact(function(){e.each(function(e,n){a(n).find("br").each(function(e,n){n.parentNode.replaceChild(t.getDoc().createTextNode("\n"),n)}),n.contentEditable="false",n.innerHTML=t.dom.encode(n.textContent),w(t).highlightElement(n),n.className=a.trim(n.className)})})}),_(n),(r=n).addCommand("codesample",function(){var e=r.selection.getNode();r.selection.isCollapsed()||g(e)?x(r):r.formatter.toggle("code")}),n.on("dblclick",function(e){g(e.target)&&x(n)})})}(); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/colorpicker/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/colorpicker/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..c8cbff2df8ab4e69d74252cdaef9588b3b8c72a5 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/colorpicker/plugin.js @@ -0,0 +1,22 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + function Plugin () { + global.add('colorpicker', function () { + console.warn('Color picker plugin is now built in to the core editor, please remove it from your editor configuration'); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/colorpicker/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/colorpicker/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..67519fb5e5e07e579d047bfd429d6ecbe1ea7915 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/colorpicker/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("colorpicker",function(){console.warn("Color picker plugin is now built in to the core editor, please remove it from your editor configuration")})}(); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/contextmenu/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/contextmenu/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..084e28762898ed8de1184330eb56f07a736e51ee --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/contextmenu/plugin.js @@ -0,0 +1,22 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + function Plugin () { + global.add('contextmenu', function () { + console.warn('Context menu plugin is now built in to the core editor, please remove it from your editor configuration'); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/contextmenu/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/contextmenu/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..3fe1c73463d94fee54a3c9980fa2a9462c3ec972 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/contextmenu/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("contextmenu",function(){console.warn("Context menu plugin is now built in to the core editor, please remove it from your editor configuration")})}(); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/directionality/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/directionality/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..fc9e6eb56a1d23043d43a8dc4fd30c66befd481c --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/directionality/plugin.js @@ -0,0 +1,314 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var setDir = function (editor, dir) { + var dom = editor.dom; + var curDir; + var blocks = editor.selection.getSelectedBlocks(); + if (blocks.length) { + curDir = dom.getAttrib(blocks[0], 'dir'); + global$1.each(blocks, function (block) { + if (!dom.getParent(block.parentNode, '*[dir="' + dir + '"]', dom.getRoot())) { + dom.setAttrib(block, 'dir', curDir !== dir ? dir : null); + } + }); + editor.nodeChanged(); + } + }; + + var register = function (editor) { + editor.addCommand('mceDirectionLTR', function () { + setDir(editor, 'ltr'); + }); + editor.addCommand('mceDirectionRTL', function () { + setDir(editor, 'rtl'); + }); + }; + + var noop = function () { + }; + var compose1 = function (fbc, fab) { + return function (a) { + return fbc(fab(a)); + }; + }; + var constant = function (value) { + return function () { + return value; + }; + }; + var never = constant(false); + var always = constant(true); + + var none = function () { + return NONE; + }; + var NONE = function () { + var eq = function (o) { + return o.isNone(); + }; + var call = function (thunk) { + return thunk(); + }; + var id = function (n) { + return n; + }; + var me = { + fold: function (n, _s) { + return n(); + }, + is: never, + isSome: never, + isNone: always, + getOr: id, + getOrThunk: call, + getOrDie: function (msg) { + throw new Error(msg || 'error: getOrDie called on none.'); + }, + getOrNull: constant(null), + getOrUndefined: constant(undefined), + or: id, + orThunk: call, + map: none, + each: noop, + bind: none, + exists: never, + forall: always, + filter: none, + equals: eq, + equals_: eq, + toArray: function () { + return []; + }, + toString: constant('none()') + }; + return me; + }(); + var some = function (a) { + var constant_a = constant(a); + var self = function () { + return me; + }; + var bind = function (f) { + return f(a); + }; + var me = { + fold: function (n, s) { + return s(a); + }, + is: function (v) { + return a === v; + }, + isSome: always, + isNone: never, + getOr: constant_a, + getOrThunk: constant_a, + getOrDie: constant_a, + getOrNull: constant_a, + getOrUndefined: constant_a, + or: self, + orThunk: self, + map: function (f) { + return some(f(a)); + }, + each: function (f) { + f(a); + }, + bind: bind, + exists: bind, + forall: bind, + filter: function (f) { + return f(a) ? me : NONE; + }, + toArray: function () { + return [a]; + }, + toString: function () { + return 'some(' + a + ')'; + }, + equals: function (o) { + return o.is(a); + }, + equals_: function (o, elementEq) { + return o.fold(never, function (b) { + return elementEq(a, b); + }); + } + }; + return me; + }; + var from = function (value) { + return value === null || value === undefined ? NONE : some(value); + }; + var Optional = { + some: some, + none: none, + from: from + }; + + var isSimpleType = function (type) { + return function (value) { + return typeof value === type; + }; + }; + var isFunction = isSimpleType('function'); + + var isSupported = function (dom) { + return dom.style !== undefined && isFunction(dom.style.getPropertyValue); + }; + + var fromHtml = function (html, scope) { + var doc = scope || document; + var div = doc.createElement('div'); + div.innerHTML = html; + if (!div.hasChildNodes() || div.childNodes.length > 1) { + console.error('HTML does not have a single root node', html); + throw new Error('HTML must have a single root node'); + } + return fromDom(div.childNodes[0]); + }; + var fromTag = function (tag, scope) { + var doc = scope || document; + var node = doc.createElement(tag); + return fromDom(node); + }; + var fromText = function (text, scope) { + var doc = scope || document; + var node = doc.createTextNode(text); + return fromDom(node); + }; + var fromDom = function (node) { + if (node === null || node === undefined) { + throw new Error('Node cannot be null or undefined'); + } + return { dom: node }; + }; + var fromPoint = function (docElm, x, y) { + return Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom); + }; + var SugarElement = { + fromHtml: fromHtml, + fromTag: fromTag, + fromText: fromText, + fromDom: fromDom, + fromPoint: fromPoint + }; + + var Global = typeof window !== 'undefined' ? window : Function('return this;')(); + + var DOCUMENT = 9; + var DOCUMENT_FRAGMENT = 11; + var TEXT = 3; + + var type = function (element) { + return element.dom.nodeType; + }; + var isType = function (t) { + return function (element) { + return type(element) === t; + }; + }; + var isText = isType(TEXT); + var isDocument = isType(DOCUMENT); + var isDocumentFragment = isType(DOCUMENT_FRAGMENT); + + var owner = function (element) { + return SugarElement.fromDom(element.dom.ownerDocument); + }; + var documentOrOwner = function (dos) { + return isDocument(dos) ? dos : owner(dos); + }; + + var isShadowRoot = function (dos) { + return isDocumentFragment(dos); + }; + var supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode); + var getRootNode = supported ? function (e) { + return SugarElement.fromDom(e.dom.getRootNode()); + } : documentOrOwner; + var getShadowRoot = function (e) { + var r = getRootNode(e); + return isShadowRoot(r) ? Optional.some(r) : Optional.none(); + }; + var getShadowHost = function (e) { + return SugarElement.fromDom(e.dom.host); + }; + + var inBody = function (element) { + var dom = isText(element) ? element.dom.parentNode : element.dom; + if (dom === undefined || dom === null || dom.ownerDocument === null) { + return false; + } + var doc = dom.ownerDocument; + return getShadowRoot(SugarElement.fromDom(dom)).fold(function () { + return doc.body.contains(dom); + }, compose1(inBody, getShadowHost)); + }; + + var get = function (element, property) { + var dom = element.dom; + var styles = window.getComputedStyle(dom); + var r = styles.getPropertyValue(property); + return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r; + }; + var getUnsafeProperty = function (dom, property) { + return isSupported(dom) ? dom.style.getPropertyValue(property) : ''; + }; + + var getDirection = function (element) { + return get(element, 'direction') === 'rtl' ? 'rtl' : 'ltr'; + }; + + var getNodeChangeHandler = function (editor, dir) { + return function (api) { + var nodeChangeHandler = function (e) { + var element = SugarElement.fromDom(e.element); + api.setActive(getDirection(element) === dir); + }; + editor.on('NodeChange', nodeChangeHandler); + return function () { + return editor.off('NodeChange', nodeChangeHandler); + }; + }; + }; + var register$1 = function (editor) { + editor.ui.registry.addToggleButton('ltr', { + tooltip: 'Left to right', + icon: 'ltr', + onAction: function () { + return editor.execCommand('mceDirectionLTR'); + }, + onSetup: getNodeChangeHandler(editor, 'ltr') + }); + editor.ui.registry.addToggleButton('rtl', { + tooltip: 'Right to left', + icon: 'rtl', + onAction: function () { + return editor.execCommand('mceDirectionRTL'); + }, + onSetup: getNodeChangeHandler(editor, 'rtl') + }); + }; + + function Plugin () { + global.add('directionality', function (editor) { + register(editor); + register$1(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/directionality/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/directionality/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..e20ec96ef42b10a36acd69ec52819701ef728b7b --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/directionality/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var n,t,e,o,r=tinymce.util.Tools.resolve("tinymce.PluginManager"),u=tinymce.util.Tools.resolve("tinymce.util.Tools"),i=function(n,t){var e,o=n.dom,r=n.selection.getSelectedBlocks();r.length&&(e=o.getAttrib(r[0],"dir"),u.each(r,function(n){o.getParent(n.parentNode,'*[dir="'+t+'"]',o.getRoot())||o.setAttrib(n,"dir",e!==t?t:null)}),n.nodeChanged())},c=function(n){return function(){return n}},f=c(!1),d=c(!0),l=function(){return m},m=(n=function(n){return n.isNone()},{fold:function(n,t){return n()},is:f,isSome:f,isNone:d,getOr:e=function(n){return n},getOrThunk:t=function(n){return n()},getOrDie:function(n){throw new Error(n||"error: getOrDie called on none.")},getOrNull:c(null),getOrUndefined:c(undefined),or:e,orThunk:t,map:l,each:function(){},bind:l,exists:f,forall:d,filter:l,equals:n,equals_:n,toArray:function(){return[]},toString:c("none()")}),a=function(e){var n=c(e),t=function(){return r},o=function(n){return n(e)},r={fold:function(n,t){return t(e)},is:function(n){return e===n},isSome:d,isNone:f,getOr:n,getOrThunk:n,getOrDie:n,getOrNull:n,getOrUndefined:n,or:t,orThunk:t,map:function(n){return a(n(e))},each:function(n){n(e)},bind:o,exists:o,forall:o,filter:function(n){return n(e)?r:m},toArray:function(){return[e]},toString:function(){return"some("+e+")"},equals:function(n){return n.is(e)},equals_:function(n,t){return n.fold(f,function(n){return t(e,n)})}};return r},s={some:a,none:l,from:function(n){return null===n||n===undefined?m:a(n)}},g=(o="function",function(n){return typeof n===o}),h=function(n){if(null===n||n===undefined)throw new Error("Node cannot be null or undefined");return{dom:n}},y={fromHtml:function(n,t){var e=(t||document).createElement("div");if(e.innerHTML=n,!e.hasChildNodes()||1', + fitzpatrick_scale: false, + category: "symbols" + }, + 1234: { + keywords: [ "numbers", "blue-square" ], + "char": '\ud83d\udd22', + fitzpatrick_scale: false, + category: "symbols" + }, + grinning: { + keywords: [ "face", "smile", "happy", "joy", ":D", "grin" ], + "char": '\ud83d\ude00', + fitzpatrick_scale: false, + category: "people" + }, + grimacing: { + keywords: [ "face", "grimace", "teeth" ], + "char": '\ud83d\ude2c', + fitzpatrick_scale: false, + category: "people" + }, + grin: { + keywords: [ "face", "happy", "smile", "joy", "kawaii" ], + "char": '\ud83d\ude01', + fitzpatrick_scale: false, + category: "people" + }, + joy: { + keywords: [ "face", "cry", "tears", "weep", "happy", "happytears", "haha" ], + "char": '\ud83d\ude02', + fitzpatrick_scale: false, + category: "people" + }, + rofl: { + keywords: [ "face", "rolling", "floor", "laughing", "lol", "haha" ], + "char": '\ud83e\udd23', + fitzpatrick_scale: false, + category: "people" + }, + partying: { + keywords: [ "face", "celebration", "woohoo" ], + "char": '\ud83e\udd73', + fitzpatrick_scale: false, + category: "people" + }, + smiley: { + keywords: [ "face", "happy", "joy", "haha", ":D", ":)", "smile", "funny" ], + "char": '\ud83d\ude03', + fitzpatrick_scale: false, + category: "people" + }, + smile: { + keywords: [ "face", "happy", "joy", "funny", "haha", "laugh", "like", ":D", ":)" ], + "char": '\ud83d\ude04', + fitzpatrick_scale: false, + category: "people" + }, + sweat_smile: { + keywords: [ "face", "hot", "happy", "laugh", "sweat", "smile", "relief" ], + "char": '\ud83d\ude05', + fitzpatrick_scale: false, + category: "people" + }, + laughing: { + keywords: [ "happy", "joy", "lol", "satisfied", "haha", "face", "glad", "XD", "laugh" ], + "char": '\ud83d\ude06', + fitzpatrick_scale: false, + category: "people" + }, + innocent: { + keywords: [ "face", "angel", "heaven", "halo" ], + "char": '\ud83d\ude07', + fitzpatrick_scale: false, + category: "people" + }, + wink: { + keywords: [ "face", "happy", "mischievous", "secret", ";)", "smile", "eye" ], + "char": '\ud83d\ude09', + fitzpatrick_scale: false, + category: "people" + }, + blush: { + keywords: [ "face", "smile", "happy", "flushed", "crush", "embarrassed", "shy", "joy" ], + "char": '\ud83d\ude0a', + fitzpatrick_scale: false, + category: "people" + }, + slightly_smiling_face: { + keywords: [ "face", "smile" ], + "char": '\ud83d\ude42', + fitzpatrick_scale: false, + category: "people" + }, + upside_down_face: { + keywords: [ "face", "flipped", "silly", "smile" ], + "char": '\ud83d\ude43', + fitzpatrick_scale: false, + category: "people" + }, + relaxed: { + keywords: [ "face", "blush", "massage", "happiness" ], + "char": '\u263a\ufe0f', + fitzpatrick_scale: false, + category: "people" + }, + yum: { + keywords: [ "happy", "joy", "tongue", "smile", "face", "silly", "yummy", "nom", "delicious", "savouring" ], + "char": '\ud83d\ude0b', + fitzpatrick_scale: false, + category: "people" + }, + relieved: { + keywords: [ "face", "relaxed", "phew", "massage", "happiness" ], + "char": '\ud83d\ude0c', + fitzpatrick_scale: false, + category: "people" + }, + heart_eyes: { + keywords: [ "face", "love", "like", "affection", "valentines", "infatuation", "crush", "heart" ], + "char": '\ud83d\ude0d', + fitzpatrick_scale: false, + category: "people" + }, + smiling_face_with_three_hearts: { + keywords: [ "face", "love", "like", "affection", "valentines", "infatuation", "crush", "hearts", "adore" ], + "char": '\ud83e\udd70', + fitzpatrick_scale: false, + category: "people" + }, + kissing_heart: { + keywords: [ "face", "love", "like", "affection", "valentines", "infatuation", "kiss" ], + "char": '\ud83d\ude18', + fitzpatrick_scale: false, + category: "people" + }, + kissing: { + keywords: [ "love", "like", "face", "3", "valentines", "infatuation", "kiss" ], + "char": '\ud83d\ude17', + fitzpatrick_scale: false, + category: "people" + }, + kissing_smiling_eyes: { + keywords: [ "face", "affection", "valentines", "infatuation", "kiss" ], + "char": '\ud83d\ude19', + fitzpatrick_scale: false, + category: "people" + }, + kissing_closed_eyes: { + keywords: [ "face", "love", "like", "affection", "valentines", "infatuation", "kiss" ], + "char": '\ud83d\ude1a', + fitzpatrick_scale: false, + category: "people" + }, + stuck_out_tongue_winking_eye: { + keywords: [ "face", "prank", "childish", "playful", "mischievous", "smile", "wink", "tongue" ], + "char": '\ud83d\ude1c', + fitzpatrick_scale: false, + category: "people" + }, + zany: { + keywords: [ "face", "goofy", "crazy" ], + "char": '\ud83e\udd2a', + fitzpatrick_scale: false, + category: "people" + }, + raised_eyebrow: { + keywords: [ "face", "distrust", "scepticism", "disapproval", "disbelief", "surprise" ], + "char": '\ud83e\udd28', + fitzpatrick_scale: false, + category: "people" + }, + monocle: { + keywords: [ "face", "stuffy", "wealthy" ], + "char": '\ud83e\uddd0', + fitzpatrick_scale: false, + category: "people" + }, + stuck_out_tongue_closed_eyes: { + keywords: [ "face", "prank", "playful", "mischievous", "smile", "tongue" ], + "char": '\ud83d\ude1d', + fitzpatrick_scale: false, + category: "people" + }, + stuck_out_tongue: { + keywords: [ "face", "prank", "childish", "playful", "mischievous", "smile", "tongue" ], + "char": '\ud83d\ude1b', + fitzpatrick_scale: false, + category: "people" + }, + money_mouth_face: { + keywords: [ "face", "rich", "dollar", "money" ], + "char": '\ud83e\udd11', + fitzpatrick_scale: false, + category: "people" + }, + nerd_face: { + keywords: [ "face", "nerdy", "geek", "dork" ], + "char": '\ud83e\udd13', + fitzpatrick_scale: false, + category: "people" + }, + sunglasses: { + keywords: [ "face", "cool", "smile", "summer", "beach", "sunglass" ], + "char": '\ud83d\ude0e', + fitzpatrick_scale: false, + category: "people" + }, + star_struck: { + keywords: [ "face", "smile", "starry", "eyes", "grinning" ], + "char": '\ud83e\udd29', + fitzpatrick_scale: false, + category: "people" + }, + clown_face: { + keywords: [ "face" ], + "char": '\ud83e\udd21', + fitzpatrick_scale: false, + category: "people" + }, + cowboy_hat_face: { + keywords: [ "face", "cowgirl", "hat" ], + "char": '\ud83e\udd20', + fitzpatrick_scale: false, + category: "people" + }, + hugs: { + keywords: [ "face", "smile", "hug" ], + "char": '\ud83e\udd17', + fitzpatrick_scale: false, + category: "people" + }, + smirk: { + keywords: [ "face", "smile", "mean", "prank", "smug", "sarcasm" ], + "char": '\ud83d\ude0f', + fitzpatrick_scale: false, + category: "people" + }, + no_mouth: { + keywords: [ "face", "hellokitty" ], + "char": '\ud83d\ude36', + fitzpatrick_scale: false, + category: "people" + }, + neutral_face: { + keywords: [ "indifference", "meh", ":|", "neutral" ], + "char": '\ud83d\ude10', + fitzpatrick_scale: false, + category: "people" + }, + expressionless: { + keywords: [ "face", "indifferent", "-_-", "meh", "deadpan" ], + "char": '\ud83d\ude11', + fitzpatrick_scale: false, + category: "people" + }, + unamused: { + keywords: [ "indifference", "bored", "straight face", "serious", "sarcasm", "unimpressed", "skeptical", "dubious", "side_eye" ], + "char": '\ud83d\ude12', + fitzpatrick_scale: false, + category: "people" + }, + roll_eyes: { + keywords: [ "face", "eyeroll", "frustrated" ], + "char": '\ud83d\ude44', + fitzpatrick_scale: false, + category: "people" + }, + thinking: { + keywords: [ "face", "hmmm", "think", "consider" ], + "char": '\ud83e\udd14', + fitzpatrick_scale: false, + category: "people" + }, + lying_face: { + keywords: [ "face", "lie", "pinocchio" ], + "char": '\ud83e\udd25', + fitzpatrick_scale: false, + category: "people" + }, + hand_over_mouth: { + keywords: [ "face", "whoops", "shock", "surprise" ], + "char": '\ud83e\udd2d', + fitzpatrick_scale: false, + category: "people" + }, + shushing: { + keywords: [ "face", "quiet", "shhh" ], + "char": '\ud83e\udd2b', + fitzpatrick_scale: false, + category: "people" + }, + symbols_over_mouth: { + keywords: [ "face", "swearing", "cursing", "cussing", "profanity", "expletive" ], + "char": '\ud83e\udd2c', + fitzpatrick_scale: false, + category: "people" + }, + exploding_head: { + keywords: [ "face", "shocked", "mind", "blown" ], + "char": '\ud83e\udd2f', + fitzpatrick_scale: false, + category: "people" + }, + flushed: { + keywords: [ "face", "blush", "shy", "flattered" ], + "char": '\ud83d\ude33', + fitzpatrick_scale: false, + category: "people" + }, + disappointed: { + keywords: [ "face", "sad", "upset", "depressed", ":(" ], + "char": '\ud83d\ude1e', + fitzpatrick_scale: false, + category: "people" + }, + worried: { + keywords: [ "face", "concern", "nervous", ":(" ], + "char": '\ud83d\ude1f', + fitzpatrick_scale: false, + category: "people" + }, + angry: { + keywords: [ "mad", "face", "annoyed", "frustrated" ], + "char": '\ud83d\ude20', + fitzpatrick_scale: false, + category: "people" + }, + rage: { + keywords: [ "angry", "mad", "hate", "despise" ], + "char": '\ud83d\ude21', + fitzpatrick_scale: false, + category: "people" + }, + pensive: { + keywords: [ "face", "sad", "depressed", "upset" ], + "char": '\ud83d\ude14', + fitzpatrick_scale: false, + category: "people" + }, + confused: { + keywords: [ "face", "indifference", "huh", "weird", "hmmm", ":/" ], + "char": '\ud83d\ude15', + fitzpatrick_scale: false, + category: "people" + }, + slightly_frowning_face: { + keywords: [ "face", "frowning", "disappointed", "sad", "upset" ], + "char": '\ud83d\ude41', + fitzpatrick_scale: false, + category: "people" + }, + frowning_face: { + keywords: [ "face", "sad", "upset", "frown" ], + "char": '\u2639', + fitzpatrick_scale: false, + category: "people" + }, + persevere: { + keywords: [ "face", "sick", "no", "upset", "oops" ], + "char": '\ud83d\ude23', + fitzpatrick_scale: false, + category: "people" + }, + confounded: { + keywords: [ "face", "confused", "sick", "unwell", "oops", ":S" ], + "char": '\ud83d\ude16', + fitzpatrick_scale: false, + category: "people" + }, + tired_face: { + keywords: [ "sick", "whine", "upset", "frustrated" ], + "char": '\ud83d\ude2b', + fitzpatrick_scale: false, + category: "people" + }, + weary: { + keywords: [ "face", "tired", "sleepy", "sad", "frustrated", "upset" ], + "char": '\ud83d\ude29', + fitzpatrick_scale: false, + category: "people" + }, + pleading: { + keywords: [ "face", "begging", "mercy" ], + "char": '\ud83e\udd7a', + fitzpatrick_scale: false, + category: "people" + }, + triumph: { + keywords: [ "face", "gas", "phew", "proud", "pride" ], + "char": '\ud83d\ude24', + fitzpatrick_scale: false, + category: "people" + }, + open_mouth: { + keywords: [ "face", "surprise", "impressed", "wow", "whoa", ":O" ], + "char": '\ud83d\ude2e', + fitzpatrick_scale: false, + category: "people" + }, + scream: { + keywords: [ "face", "munch", "scared", "omg" ], + "char": '\ud83d\ude31', + fitzpatrick_scale: false, + category: "people" + }, + fearful: { + keywords: [ "face", "scared", "terrified", "nervous", "oops", "huh" ], + "char": '\ud83d\ude28', + fitzpatrick_scale: false, + category: "people" + }, + cold_sweat: { + keywords: [ "face", "nervous", "sweat" ], + "char": '\ud83d\ude30', + fitzpatrick_scale: false, + category: "people" + }, + hushed: { + keywords: [ "face", "woo", "shh" ], + "char": '\ud83d\ude2f', + fitzpatrick_scale: false, + category: "people" + }, + frowning: { + keywords: [ "face", "aw", "what" ], + "char": '\ud83d\ude26', + fitzpatrick_scale: false, + category: "people" + }, + anguished: { + keywords: [ "face", "stunned", "nervous" ], + "char": '\ud83d\ude27', + fitzpatrick_scale: false, + category: "people" + }, + cry: { + keywords: [ "face", "tears", "sad", "depressed", "upset", ":'(" ], + "char": '\ud83d\ude22', + fitzpatrick_scale: false, + category: "people" + }, + disappointed_relieved: { + keywords: [ "face", "phew", "sweat", "nervous" ], + "char": '\ud83d\ude25', + fitzpatrick_scale: false, + category: "people" + }, + drooling_face: { + keywords: [ "face" ], + "char": '\ud83e\udd24', + fitzpatrick_scale: false, + category: "people" + }, + sleepy: { + keywords: [ "face", "tired", "rest", "nap" ], + "char": '\ud83d\ude2a', + fitzpatrick_scale: false, + category: "people" + }, + sweat: { + keywords: [ "face", "hot", "sad", "tired", "exercise" ], + "char": '\ud83d\ude13', + fitzpatrick_scale: false, + category: "people" + }, + hot: { + keywords: [ "face", "feverish", "heat", "red", "sweating" ], + "char": '\ud83e\udd75', + fitzpatrick_scale: false, + category: "people" + }, + cold: { + keywords: [ "face", "blue", "freezing", "frozen", "frostbite", "icicles" ], + "char": '\ud83e\udd76', + fitzpatrick_scale: false, + category: "people" + }, + sob: { + keywords: [ "face", "cry", "tears", "sad", "upset", "depressed" ], + "char": '\ud83d\ude2d', + fitzpatrick_scale: false, + category: "people" + }, + dizzy_face: { + keywords: [ "spent", "unconscious", "xox", "dizzy" ], + "char": '\ud83d\ude35', + fitzpatrick_scale: false, + category: "people" + }, + astonished: { + keywords: [ "face", "xox", "surprised", "poisoned" ], + "char": '\ud83d\ude32', + fitzpatrick_scale: false, + category: "people" + }, + zipper_mouth_face: { + keywords: [ "face", "sealed", "zipper", "secret" ], + "char": '\ud83e\udd10', + fitzpatrick_scale: false, + category: "people" + }, + nauseated_face: { + keywords: [ "face", "vomit", "gross", "green", "sick", "throw up", "ill" ], + "char": '\ud83e\udd22', + fitzpatrick_scale: false, + category: "people" + }, + sneezing_face: { + keywords: [ "face", "gesundheit", "sneeze", "sick", "allergy" ], + "char": '\ud83e\udd27', + fitzpatrick_scale: false, + category: "people" + }, + vomiting: { + keywords: [ "face", "sick" ], + "char": '\ud83e\udd2e', + fitzpatrick_scale: false, + category: "people" + }, + mask: { + keywords: [ "face", "sick", "ill", "disease" ], + "char": '\ud83d\ude37', + fitzpatrick_scale: false, + category: "people" + }, + face_with_thermometer: { + keywords: [ "sick", "temperature", "thermometer", "cold", "fever" ], + "char": '\ud83e\udd12', + fitzpatrick_scale: false, + category: "people" + }, + face_with_head_bandage: { + keywords: [ "injured", "clumsy", "bandage", "hurt" ], + "char": '\ud83e\udd15', + fitzpatrick_scale: false, + category: "people" + }, + woozy: { + keywords: [ "face", "dizzy", "intoxicated", "tipsy", "wavy" ], + "char": '\ud83e\udd74', + fitzpatrick_scale: false, + category: "people" + }, + sleeping: { + keywords: [ "face", "tired", "sleepy", "night", "zzz" ], + "char": '\ud83d\ude34', + fitzpatrick_scale: false, + category: "people" + }, + zzz: { + keywords: [ "sleepy", "tired", "dream" ], + "char": '\ud83d\udca4', + fitzpatrick_scale: false, + category: "people" + }, + poop: { + keywords: [ "hankey", "shitface", "fail", "turd", "shit" ], + "char": '\ud83d\udca9', + fitzpatrick_scale: false, + category: "people" + }, + smiling_imp: { + keywords: [ "devil", "horns" ], + "char": '\ud83d\ude08', + fitzpatrick_scale: false, + category: "people" + }, + imp: { + keywords: [ "devil", "angry", "horns" ], + "char": '\ud83d\udc7f', + fitzpatrick_scale: false, + category: "people" + }, + japanese_ogre: { + keywords: [ "monster", "red", "mask", "halloween", "scary", "creepy", "devil", "demon", "japanese", "ogre" ], + "char": '\ud83d\udc79', + fitzpatrick_scale: false, + category: "people" + }, + japanese_goblin: { + keywords: [ "red", "evil", "mask", "monster", "scary", "creepy", "japanese", "goblin" ], + "char": '\ud83d\udc7a', + fitzpatrick_scale: false, + category: "people" + }, + skull: { + keywords: [ "dead", "skeleton", "creepy", "death" ], + "char": '\ud83d\udc80', + fitzpatrick_scale: false, + category: "people" + }, + ghost: { + keywords: [ "halloween", "spooky", "scary" ], + "char": '\ud83d\udc7b', + fitzpatrick_scale: false, + category: "people" + }, + alien: { + keywords: [ "UFO", "paul", "weird", "outer_space" ], + "char": '\ud83d\udc7d', + fitzpatrick_scale: false, + category: "people" + }, + robot: { + keywords: [ "computer", "machine", "bot" ], + "char": '\ud83e\udd16', + fitzpatrick_scale: false, + category: "people" + }, + smiley_cat: { + keywords: [ "animal", "cats", "happy", "smile" ], + "char": '\ud83d\ude3a', + fitzpatrick_scale: false, + category: "people" + }, + smile_cat: { + keywords: [ "animal", "cats", "smile" ], + "char": '\ud83d\ude38', + fitzpatrick_scale: false, + category: "people" + }, + joy_cat: { + keywords: [ "animal", "cats", "haha", "happy", "tears" ], + "char": '\ud83d\ude39', + fitzpatrick_scale: false, + category: "people" + }, + heart_eyes_cat: { + keywords: [ "animal", "love", "like", "affection", "cats", "valentines", "heart" ], + "char": '\ud83d\ude3b', + fitzpatrick_scale: false, + category: "people" + }, + smirk_cat: { + keywords: [ "animal", "cats", "smirk" ], + "char": '\ud83d\ude3c', + fitzpatrick_scale: false, + category: "people" + }, + kissing_cat: { + keywords: [ "animal", "cats", "kiss" ], + "char": '\ud83d\ude3d', + fitzpatrick_scale: false, + category: "people" + }, + scream_cat: { + keywords: [ "animal", "cats", "munch", "scared", "scream" ], + "char": '\ud83d\ude40', + fitzpatrick_scale: false, + category: "people" + }, + crying_cat_face: { + keywords: [ "animal", "tears", "weep", "sad", "cats", "upset", "cry" ], + "char": '\ud83d\ude3f', + fitzpatrick_scale: false, + category: "people" + }, + pouting_cat: { + keywords: [ "animal", "cats" ], + "char": '\ud83d\ude3e', + fitzpatrick_scale: false, + category: "people" + }, + palms_up: { + keywords: [ "hands", "gesture", "cupped", "prayer" ], + "char": '\ud83e\udd32', + fitzpatrick_scale: true, + category: "people" + }, + raised_hands: { + keywords: [ "gesture", "hooray", "yea", "celebration", "hands" ], + "char": '\ud83d\ude4c', + fitzpatrick_scale: true, + category: "people" + }, + clap: { + keywords: [ "hands", "praise", "applause", "congrats", "yay" ], + "char": '\ud83d\udc4f', + fitzpatrick_scale: true, + category: "people" + }, + wave: { + keywords: [ "hands", "gesture", "goodbye", "solong", "farewell", "hello", "hi", "palm" ], + "char": '\ud83d\udc4b', + fitzpatrick_scale: true, + category: "people" + }, + call_me_hand: { + keywords: [ "hands", "gesture" ], + "char": '\ud83e\udd19', + fitzpatrick_scale: true, + category: "people" + }, + "+1": { + keywords: [ "thumbsup", "yes", "awesome", "good", "agree", "accept", "cool", "hand", "like" ], + "char": '\ud83d\udc4d', + fitzpatrick_scale: true, + category: "people" + }, + "-1": { + keywords: [ "thumbsdown", "no", "dislike", "hand" ], + "char": '\ud83d\udc4e', + fitzpatrick_scale: true, + category: "people" + }, + facepunch: { + keywords: [ "angry", "violence", "fist", "hit", "attack", "hand" ], + "char": '\ud83d\udc4a', + fitzpatrick_scale: true, + category: "people" + }, + fist: { + keywords: [ "fingers", "hand", "grasp" ], + "char": '\u270a', + fitzpatrick_scale: true, + category: "people" + }, + fist_left: { + keywords: [ "hand", "fistbump" ], + "char": '\ud83e\udd1b', + fitzpatrick_scale: true, + category: "people" + }, + fist_right: { + keywords: [ "hand", "fistbump" ], + "char": '\ud83e\udd1c', + fitzpatrick_scale: true, + category: "people" + }, + v: { + keywords: [ "fingers", "ohyeah", "hand", "peace", "victory", "two" ], + "char": '\u270c', + fitzpatrick_scale: true, + category: "people" + }, + ok_hand: { + keywords: [ "fingers", "limbs", "perfect", "ok", "okay" ], + "char": '\ud83d\udc4c', + fitzpatrick_scale: true, + category: "people" + }, + raised_hand: { + keywords: [ "fingers", "stop", "highfive", "palm", "ban" ], + "char": '\u270b', + fitzpatrick_scale: true, + category: "people" + }, + raised_back_of_hand: { + keywords: [ "fingers", "raised", "backhand" ], + "char": '\ud83e\udd1a', + fitzpatrick_scale: true, + category: "people" + }, + open_hands: { + keywords: [ "fingers", "butterfly", "hands", "open" ], + "char": '\ud83d\udc50', + fitzpatrick_scale: true, + category: "people" + }, + muscle: { + keywords: [ "arm", "flex", "hand", "summer", "strong", "biceps" ], + "char": '\ud83d\udcaa', + fitzpatrick_scale: true, + category: "people" + }, + pray: { + keywords: [ "please", "hope", "wish", "namaste", "highfive" ], + "char": '\ud83d\ude4f', + fitzpatrick_scale: true, + category: "people" + }, + foot: { + keywords: [ "kick", "stomp" ], + "char": '\ud83e\uddb6', + fitzpatrick_scale: true, + category: "people" + }, + leg: { + keywords: [ "kick", "limb" ], + "char": '\ud83e\uddb5', + fitzpatrick_scale: true, + category: "people" + }, + handshake: { + keywords: [ "agreement", "shake" ], + "char": '\ud83e\udd1d', + fitzpatrick_scale: false, + category: "people" + }, + point_up: { + keywords: [ "hand", "fingers", "direction", "up" ], + "char": '\u261d', + fitzpatrick_scale: true, + category: "people" + }, + point_up_2: { + keywords: [ "fingers", "hand", "direction", "up" ], + "char": '\ud83d\udc46', + fitzpatrick_scale: true, + category: "people" + }, + point_down: { + keywords: [ "fingers", "hand", "direction", "down" ], + "char": '\ud83d\udc47', + fitzpatrick_scale: true, + category: "people" + }, + point_left: { + keywords: [ "direction", "fingers", "hand", "left" ], + "char": '\ud83d\udc48', + fitzpatrick_scale: true, + category: "people" + }, + point_right: { + keywords: [ "fingers", "hand", "direction", "right" ], + "char": '\ud83d\udc49', + fitzpatrick_scale: true, + category: "people" + }, + fu: { + keywords: [ "hand", "fingers", "rude", "middle", "flipping" ], + "char": '\ud83d\udd95', + fitzpatrick_scale: true, + category: "people" + }, + raised_hand_with_fingers_splayed: { + keywords: [ "hand", "fingers", "palm" ], + "char": '\ud83d\udd90', + fitzpatrick_scale: true, + category: "people" + }, + love_you: { + keywords: [ "hand", "fingers", "gesture" ], + "char": '\ud83e\udd1f', + fitzpatrick_scale: true, + category: "people" + }, + metal: { + keywords: [ "hand", "fingers", "evil_eye", "sign_of_horns", "rock_on" ], + "char": '\ud83e\udd18', + fitzpatrick_scale: true, + category: "people" + }, + crossed_fingers: { + keywords: [ "good", "lucky" ], + "char": '\ud83e\udd1e', + fitzpatrick_scale: true, + category: "people" + }, + vulcan_salute: { + keywords: [ "hand", "fingers", "spock", "star trek" ], + "char": '\ud83d\udd96', + fitzpatrick_scale: true, + category: "people" + }, + writing_hand: { + keywords: [ "lower_left_ballpoint_pen", "stationery", "write", "compose" ], + "char": '\u270d', + fitzpatrick_scale: true, + category: "people" + }, + selfie: { + keywords: [ "camera", "phone" ], + "char": '\ud83e\udd33', + fitzpatrick_scale: true, + category: "people" + }, + nail_care: { + keywords: [ "beauty", "manicure", "finger", "fashion", "nail" ], + "char": '\ud83d\udc85', + fitzpatrick_scale: true, + category: "people" + }, + lips: { + keywords: [ "mouth", "kiss" ], + "char": '\ud83d\udc44', + fitzpatrick_scale: false, + category: "people" + }, + tooth: { + keywords: [ "teeth", "dentist" ], + "char": '\ud83e\uddb7', + fitzpatrick_scale: false, + category: "people" + }, + tongue: { + keywords: [ "mouth", "playful" ], + "char": '\ud83d\udc45', + fitzpatrick_scale: false, + category: "people" + }, + ear: { + keywords: [ "face", "hear", "sound", "listen" ], + "char": '\ud83d\udc42', + fitzpatrick_scale: true, + category: "people" + }, + nose: { + keywords: [ "smell", "sniff" ], + "char": '\ud83d\udc43', + fitzpatrick_scale: true, + category: "people" + }, + eye: { + keywords: [ "face", "look", "see", "watch", "stare" ], + "char": '\ud83d\udc41', + fitzpatrick_scale: false, + category: "people" + }, + eyes: { + keywords: [ "look", "watch", "stalk", "peek", "see" ], + "char": '\ud83d\udc40', + fitzpatrick_scale: false, + category: "people" + }, + brain: { + keywords: [ "smart", "intelligent" ], + "char": '\ud83e\udde0', + fitzpatrick_scale: false, + category: "people" + }, + bust_in_silhouette: { + keywords: [ "user", "person", "human" ], + "char": '\ud83d\udc64', + fitzpatrick_scale: false, + category: "people" + }, + busts_in_silhouette: { + keywords: [ "user", "person", "human", "group", "team" ], + "char": '\ud83d\udc65', + fitzpatrick_scale: false, + category: "people" + }, + speaking_head: { + keywords: [ "user", "person", "human", "sing", "say", "talk" ], + "char": '\ud83d\udde3', + fitzpatrick_scale: false, + category: "people" + }, + baby: { + keywords: [ "child", "boy", "girl", "toddler" ], + "char": '\ud83d\udc76', + fitzpatrick_scale: true, + category: "people" + }, + child: { + keywords: [ "gender-neutral", "young" ], + "char": '\ud83e\uddd2', + fitzpatrick_scale: true, + category: "people" + }, + boy: { + keywords: [ "man", "male", "guy", "teenager" ], + "char": '\ud83d\udc66', + fitzpatrick_scale: true, + category: "people" + }, + girl: { + keywords: [ "female", "woman", "teenager" ], + "char": '\ud83d\udc67', + fitzpatrick_scale: true, + category: "people" + }, + adult: { + keywords: [ "gender-neutral", "person" ], + "char": '\ud83e\uddd1', + fitzpatrick_scale: true, + category: "people" + }, + man: { + keywords: [ "mustache", "father", "dad", "guy", "classy", "sir", "moustache" ], + "char": '\ud83d\udc68', + fitzpatrick_scale: true, + category: "people" + }, + woman: { + keywords: [ "female", "girls", "lady" ], + "char": '\ud83d\udc69', + fitzpatrick_scale: true, + category: "people" + }, + blonde_woman: { + keywords: [ "woman", "female", "girl", "blonde", "person" ], + "char": '\ud83d\udc71\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + blonde_man: { + keywords: [ "man", "male", "boy", "blonde", "guy", "person" ], + "char": '\ud83d\udc71', + fitzpatrick_scale: true, + category: "people" + }, + bearded_person: { + keywords: [ "person", "bewhiskered" ], + "char": '\ud83e\uddd4', + fitzpatrick_scale: true, + category: "people" + }, + older_adult: { + keywords: [ "human", "elder", "senior", "gender-neutral" ], + "char": '\ud83e\uddd3', + fitzpatrick_scale: true, + category: "people" + }, + older_man: { + keywords: [ "human", "male", "men", "old", "elder", "senior" ], + "char": '\ud83d\udc74', + fitzpatrick_scale: true, + category: "people" + }, + older_woman: { + keywords: [ "human", "female", "women", "lady", "old", "elder", "senior" ], + "char": '\ud83d\udc75', + fitzpatrick_scale: true, + category: "people" + }, + man_with_gua_pi_mao: { + keywords: [ "male", "boy", "chinese" ], + "char": '\ud83d\udc72', + fitzpatrick_scale: true, + category: "people" + }, + woman_with_headscarf: { + keywords: [ "female", "hijab", "mantilla", "tichel" ], + "char": '\ud83e\uddd5', + fitzpatrick_scale: true, + category: "people" + }, + woman_with_turban: { + keywords: [ "female", "indian", "hinduism", "arabs", "woman" ], + "char": '\ud83d\udc73\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + man_with_turban: { + keywords: [ "male", "indian", "hinduism", "arabs" ], + "char": '\ud83d\udc73', + fitzpatrick_scale: true, + category: "people" + }, + policewoman: { + keywords: [ "woman", "police", "law", "legal", "enforcement", "arrest", "911", "female" ], + "char": '\ud83d\udc6e\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + policeman: { + keywords: [ "man", "police", "law", "legal", "enforcement", "arrest", "911" ], + "char": '\ud83d\udc6e', + fitzpatrick_scale: true, + category: "people" + }, + construction_worker_woman: { + keywords: [ "female", "human", "wip", "build", "construction", "worker", "labor", "woman" ], + "char": '\ud83d\udc77\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + construction_worker_man: { + keywords: [ "male", "human", "wip", "guy", "build", "construction", "worker", "labor" ], + "char": '\ud83d\udc77', + fitzpatrick_scale: true, + category: "people" + }, + guardswoman: { + keywords: [ "uk", "gb", "british", "female", "royal", "woman" ], + "char": '\ud83d\udc82\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + guardsman: { + keywords: [ "uk", "gb", "british", "male", "guy", "royal" ], + "char": '\ud83d\udc82', + fitzpatrick_scale: true, + category: "people" + }, + female_detective: { + keywords: [ "human", "spy", "detective", "female", "woman" ], + "char": '\ud83d\udd75\ufe0f\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + male_detective: { + keywords: [ "human", "spy", "detective" ], + "char": '\ud83d\udd75', + fitzpatrick_scale: true, + category: "people" + }, + woman_health_worker: { + keywords: [ "doctor", "nurse", "therapist", "healthcare", "woman", "human" ], + "char": '\ud83d\udc69\u200d\u2695\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + man_health_worker: { + keywords: [ "doctor", "nurse", "therapist", "healthcare", "man", "human" ], + "char": '\ud83d\udc68\u200d\u2695\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + woman_farmer: { + keywords: [ "rancher", "gardener", "woman", "human" ], + "char": '\ud83d\udc69\u200d\ud83c\udf3e', + fitzpatrick_scale: true, + category: "people" + }, + man_farmer: { + keywords: [ "rancher", "gardener", "man", "human" ], + "char": '\ud83d\udc68\u200d\ud83c\udf3e', + fitzpatrick_scale: true, + category: "people" + }, + woman_cook: { + keywords: [ "chef", "woman", "human" ], + "char": '\ud83d\udc69\u200d\ud83c\udf73', + fitzpatrick_scale: true, + category: "people" + }, + man_cook: { + keywords: [ "chef", "man", "human" ], + "char": '\ud83d\udc68\u200d\ud83c\udf73', + fitzpatrick_scale: true, + category: "people" + }, + woman_student: { + keywords: [ "graduate", "woman", "human" ], + "char": '\ud83d\udc69\u200d\ud83c\udf93', + fitzpatrick_scale: true, + category: "people" + }, + man_student: { + keywords: [ "graduate", "man", "human" ], + "char": '\ud83d\udc68\u200d\ud83c\udf93', + fitzpatrick_scale: true, + category: "people" + }, + woman_singer: { + keywords: [ "rockstar", "entertainer", "woman", "human" ], + "char": '\ud83d\udc69\u200d\ud83c\udfa4', + fitzpatrick_scale: true, + category: "people" + }, + man_singer: { + keywords: [ "rockstar", "entertainer", "man", "human" ], + "char": '\ud83d\udc68\u200d\ud83c\udfa4', + fitzpatrick_scale: true, + category: "people" + }, + woman_teacher: { + keywords: [ "instructor", "professor", "woman", "human" ], + "char": '\ud83d\udc69\u200d\ud83c\udfeb', + fitzpatrick_scale: true, + category: "people" + }, + man_teacher: { + keywords: [ "instructor", "professor", "man", "human" ], + "char": '\ud83d\udc68\u200d\ud83c\udfeb', + fitzpatrick_scale: true, + category: "people" + }, + woman_factory_worker: { + keywords: [ "assembly", "industrial", "woman", "human" ], + "char": '\ud83d\udc69\u200d\ud83c\udfed', + fitzpatrick_scale: true, + category: "people" + }, + man_factory_worker: { + keywords: [ "assembly", "industrial", "man", "human" ], + "char": '\ud83d\udc68\u200d\ud83c\udfed', + fitzpatrick_scale: true, + category: "people" + }, + woman_technologist: { + keywords: [ "coder", "developer", "engineer", "programmer", "software", "woman", "human", "laptop", "computer" ], + "char": '\ud83d\udc69\u200d\ud83d\udcbb', + fitzpatrick_scale: true, + category: "people" + }, + man_technologist: { + keywords: [ "coder", "developer", "engineer", "programmer", "software", "man", "human", "laptop", "computer" ], + "char": '\ud83d\udc68\u200d\ud83d\udcbb', + fitzpatrick_scale: true, + category: "people" + }, + woman_office_worker: { + keywords: [ "business", "manager", "woman", "human" ], + "char": '\ud83d\udc69\u200d\ud83d\udcbc', + fitzpatrick_scale: true, + category: "people" + }, + man_office_worker: { + keywords: [ "business", "manager", "man", "human" ], + "char": '\ud83d\udc68\u200d\ud83d\udcbc', + fitzpatrick_scale: true, + category: "people" + }, + woman_mechanic: { + keywords: [ "plumber", "woman", "human", "wrench" ], + "char": '\ud83d\udc69\u200d\ud83d\udd27', + fitzpatrick_scale: true, + category: "people" + }, + man_mechanic: { + keywords: [ "plumber", "man", "human", "wrench" ], + "char": '\ud83d\udc68\u200d\ud83d\udd27', + fitzpatrick_scale: true, + category: "people" + }, + woman_scientist: { + keywords: [ "biologist", "chemist", "engineer", "physicist", "woman", "human" ], + "char": '\ud83d\udc69\u200d\ud83d\udd2c', + fitzpatrick_scale: true, + category: "people" + }, + man_scientist: { + keywords: [ "biologist", "chemist", "engineer", "physicist", "man", "human" ], + "char": '\ud83d\udc68\u200d\ud83d\udd2c', + fitzpatrick_scale: true, + category: "people" + }, + woman_artist: { + keywords: [ "painter", "woman", "human" ], + "char": '\ud83d\udc69\u200d\ud83c\udfa8', + fitzpatrick_scale: true, + category: "people" + }, + man_artist: { + keywords: [ "painter", "man", "human" ], + "char": '\ud83d\udc68\u200d\ud83c\udfa8', + fitzpatrick_scale: true, + category: "people" + }, + woman_firefighter: { + keywords: [ "fireman", "woman", "human" ], + "char": '\ud83d\udc69\u200d\ud83d\ude92', + fitzpatrick_scale: true, + category: "people" + }, + man_firefighter: { + keywords: [ "fireman", "man", "human" ], + "char": '\ud83d\udc68\u200d\ud83d\ude92', + fitzpatrick_scale: true, + category: "people" + }, + woman_pilot: { + keywords: [ "aviator", "plane", "woman", "human" ], + "char": '\ud83d\udc69\u200d\u2708\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + man_pilot: { + keywords: [ "aviator", "plane", "man", "human" ], + "char": '\ud83d\udc68\u200d\u2708\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + woman_astronaut: { + keywords: [ "space", "rocket", "woman", "human" ], + "char": '\ud83d\udc69\u200d\ud83d\ude80', + fitzpatrick_scale: true, + category: "people" + }, + man_astronaut: { + keywords: [ "space", "rocket", "man", "human" ], + "char": '\ud83d\udc68\u200d\ud83d\ude80', + fitzpatrick_scale: true, + category: "people" + }, + woman_judge: { + keywords: [ "justice", "court", "woman", "human" ], + "char": '\ud83d\udc69\u200d\u2696\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + man_judge: { + keywords: [ "justice", "court", "man", "human" ], + "char": '\ud83d\udc68\u200d\u2696\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + woman_superhero: { + keywords: [ "woman", "female", "good", "heroine", "superpowers" ], + "char": '\ud83e\uddb8\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + man_superhero: { + keywords: [ "man", "male", "good", "hero", "superpowers" ], + "char": '\ud83e\uddb8\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + woman_supervillain: { + keywords: [ "woman", "female", "evil", "bad", "criminal", "heroine", "superpowers" ], + "char": '\ud83e\uddb9\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + man_supervillain: { + keywords: [ "man", "male", "evil", "bad", "criminal", "hero", "superpowers" ], + "char": '\ud83e\uddb9\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + mrs_claus: { + keywords: [ "woman", "female", "xmas", "mother christmas" ], + "char": '\ud83e\udd36', + fitzpatrick_scale: true, + category: "people" + }, + santa: { + keywords: [ "festival", "man", "male", "xmas", "father christmas" ], + "char": '\ud83c\udf85', + fitzpatrick_scale: true, + category: "people" + }, + sorceress: { + keywords: [ "woman", "female", "mage", "witch" ], + "char": '\ud83e\uddd9\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + wizard: { + keywords: [ "man", "male", "mage", "sorcerer" ], + "char": '\ud83e\uddd9\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + woman_elf: { + keywords: [ "woman", "female" ], + "char": '\ud83e\udddd\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + man_elf: { + keywords: [ "man", "male" ], + "char": '\ud83e\udddd\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + woman_vampire: { + keywords: [ "woman", "female" ], + "char": '\ud83e\udddb\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + man_vampire: { + keywords: [ "man", "male", "dracula" ], + "char": '\ud83e\udddb\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + woman_zombie: { + keywords: [ "woman", "female", "undead", "walking dead" ], + "char": '\ud83e\udddf\u200d\u2640\ufe0f', + fitzpatrick_scale: false, + category: "people" + }, + man_zombie: { + keywords: [ "man", "male", "dracula", "undead", "walking dead" ], + "char": '\ud83e\udddf\u200d\u2642\ufe0f', + fitzpatrick_scale: false, + category: "people" + }, + woman_genie: { + keywords: [ "woman", "female" ], + "char": '\ud83e\uddde\u200d\u2640\ufe0f', + fitzpatrick_scale: false, + category: "people" + }, + man_genie: { + keywords: [ "man", "male" ], + "char": '\ud83e\uddde\u200d\u2642\ufe0f', + fitzpatrick_scale: false, + category: "people" + }, + mermaid: { + keywords: [ "woman", "female", "merwoman", "ariel" ], + "char": '\ud83e\udddc\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + merman: { + keywords: [ "man", "male", "triton" ], + "char": '\ud83e\udddc\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + woman_fairy: { + keywords: [ "woman", "female" ], + "char": '\ud83e\uddda\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + man_fairy: { + keywords: [ "man", "male" ], + "char": '\ud83e\uddda\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + angel: { + keywords: [ "heaven", "wings", "halo" ], + "char": '\ud83d\udc7c', + fitzpatrick_scale: true, + category: "people" + }, + pregnant_woman: { + keywords: [ "baby" ], + "char": '\ud83e\udd30', + fitzpatrick_scale: true, + category: "people" + }, + breastfeeding: { + keywords: [ "nursing", "baby" ], + "char": '\ud83e\udd31', + fitzpatrick_scale: true, + category: "people" + }, + princess: { + keywords: [ "girl", "woman", "female", "blond", "crown", "royal", "queen" ], + "char": '\ud83d\udc78', + fitzpatrick_scale: true, + category: "people" + }, + prince: { + keywords: [ "boy", "man", "male", "crown", "royal", "king" ], + "char": '\ud83e\udd34', + fitzpatrick_scale: true, + category: "people" + }, + bride_with_veil: { + keywords: [ "couple", "marriage", "wedding", "woman", "bride" ], + "char": '\ud83d\udc70', + fitzpatrick_scale: true, + category: "people" + }, + man_in_tuxedo: { + keywords: [ "couple", "marriage", "wedding", "groom" ], + "char": '\ud83e\udd35', + fitzpatrick_scale: true, + category: "people" + }, + running_woman: { + keywords: [ "woman", "walking", "exercise", "race", "running", "female" ], + "char": '\ud83c\udfc3\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + running_man: { + keywords: [ "man", "walking", "exercise", "race", "running" ], + "char": '\ud83c\udfc3', + fitzpatrick_scale: true, + category: "people" + }, + walking_woman: { + keywords: [ "human", "feet", "steps", "woman", "female" ], + "char": '\ud83d\udeb6\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + walking_man: { + keywords: [ "human", "feet", "steps" ], + "char": '\ud83d\udeb6', + fitzpatrick_scale: true, + category: "people" + }, + dancer: { + keywords: [ "female", "girl", "woman", "fun" ], + "char": '\ud83d\udc83', + fitzpatrick_scale: true, + category: "people" + }, + man_dancing: { + keywords: [ "male", "boy", "fun", "dancer" ], + "char": '\ud83d\udd7a', + fitzpatrick_scale: true, + category: "people" + }, + dancing_women: { + keywords: [ "female", "bunny", "women", "girls" ], + "char": '\ud83d\udc6f', + fitzpatrick_scale: false, + category: "people" + }, + dancing_men: { + keywords: [ "male", "bunny", "men", "boys" ], + "char": '\ud83d\udc6f\u200d\u2642\ufe0f', + fitzpatrick_scale: false, + category: "people" + }, + couple: { + keywords: [ "pair", "people", "human", "love", "date", "dating", "like", "affection", "valentines", "marriage" ], + "char": '\ud83d\udc6b', + fitzpatrick_scale: false, + category: "people" + }, + two_men_holding_hands: { + keywords: [ "pair", "couple", "love", "like", "bromance", "friendship", "people", "human" ], + "char": '\ud83d\udc6c', + fitzpatrick_scale: false, + category: "people" + }, + two_women_holding_hands: { + keywords: [ "pair", "friendship", "couple", "love", "like", "female", "people", "human" ], + "char": '\ud83d\udc6d', + fitzpatrick_scale: false, + category: "people" + }, + bowing_woman: { + keywords: [ "woman", "female", "girl" ], + "char": '\ud83d\ude47\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + bowing_man: { + keywords: [ "man", "male", "boy" ], + "char": '\ud83d\ude47', + fitzpatrick_scale: true, + category: "people" + }, + man_facepalming: { + keywords: [ "man", "male", "boy", "disbelief" ], + "char": '\ud83e\udd26\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + woman_facepalming: { + keywords: [ "woman", "female", "girl", "disbelief" ], + "char": '\ud83e\udd26\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + woman_shrugging: { + keywords: [ "woman", "female", "girl", "confused", "indifferent", "doubt" ], + "char": '\ud83e\udd37', + fitzpatrick_scale: true, + category: "people" + }, + man_shrugging: { + keywords: [ "man", "male", "boy", "confused", "indifferent", "doubt" ], + "char": '\ud83e\udd37\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + tipping_hand_woman: { + keywords: [ "female", "girl", "woman", "human", "information" ], + "char": '\ud83d\udc81', + fitzpatrick_scale: true, + category: "people" + }, + tipping_hand_man: { + keywords: [ "male", "boy", "man", "human", "information" ], + "char": '\ud83d\udc81\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + no_good_woman: { + keywords: [ "female", "girl", "woman", "nope" ], + "char": '\ud83d\ude45', + fitzpatrick_scale: true, + category: "people" + }, + no_good_man: { + keywords: [ "male", "boy", "man", "nope" ], + "char": '\ud83d\ude45\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + ok_woman: { + keywords: [ "women", "girl", "female", "pink", "human", "woman" ], + "char": '\ud83d\ude46', + fitzpatrick_scale: true, + category: "people" + }, + ok_man: { + keywords: [ "men", "boy", "male", "blue", "human", "man" ], + "char": '\ud83d\ude46\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + raising_hand_woman: { + keywords: [ "female", "girl", "woman" ], + "char": '\ud83d\ude4b', + fitzpatrick_scale: true, + category: "people" + }, + raising_hand_man: { + keywords: [ "male", "boy", "man" ], + "char": '\ud83d\ude4b\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + pouting_woman: { + keywords: [ "female", "girl", "woman" ], + "char": '\ud83d\ude4e', + fitzpatrick_scale: true, + category: "people" + }, + pouting_man: { + keywords: [ "male", "boy", "man" ], + "char": '\ud83d\ude4e\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + frowning_woman: { + keywords: [ "female", "girl", "woman", "sad", "depressed", "discouraged", "unhappy" ], + "char": '\ud83d\ude4d', + fitzpatrick_scale: true, + category: "people" + }, + frowning_man: { + keywords: [ "male", "boy", "man", "sad", "depressed", "discouraged", "unhappy" ], + "char": '\ud83d\ude4d\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + haircut_woman: { + keywords: [ "female", "girl", "woman" ], + "char": '\ud83d\udc87', + fitzpatrick_scale: true, + category: "people" + }, + haircut_man: { + keywords: [ "male", "boy", "man" ], + "char": '\ud83d\udc87\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + massage_woman: { + keywords: [ "female", "girl", "woman", "head" ], + "char": '\ud83d\udc86', + fitzpatrick_scale: true, + category: "people" + }, + massage_man: { + keywords: [ "male", "boy", "man", "head" ], + "char": '\ud83d\udc86\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + woman_in_steamy_room: { + keywords: [ "female", "woman", "spa", "steamroom", "sauna" ], + "char": '\ud83e\uddd6\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + man_in_steamy_room: { + keywords: [ "male", "man", "spa", "steamroom", "sauna" ], + "char": '\ud83e\uddd6\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "people" + }, + couple_with_heart_woman_man: { + keywords: [ "pair", "love", "like", "affection", "human", "dating", "valentines", "marriage" ], + "char": '\ud83d\udc91', + fitzpatrick_scale: false, + category: "people" + }, + couple_with_heart_woman_woman: { + keywords: [ "pair", "love", "like", "affection", "human", "dating", "valentines", "marriage" ], + "char": '\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc69', + fitzpatrick_scale: false, + category: "people" + }, + couple_with_heart_man_man: { + keywords: [ "pair", "love", "like", "affection", "human", "dating", "valentines", "marriage" ], + "char": '\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68', + fitzpatrick_scale: false, + category: "people" + }, + couplekiss_man_woman: { + keywords: [ "pair", "valentines", "love", "like", "dating", "marriage" ], + "char": '\ud83d\udc8f', + fitzpatrick_scale: false, + category: "people" + }, + couplekiss_woman_woman: { + keywords: [ "pair", "valentines", "love", "like", "dating", "marriage" ], + "char": '\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69', + fitzpatrick_scale: false, + category: "people" + }, + couplekiss_man_man: { + keywords: [ "pair", "valentines", "love", "like", "dating", "marriage" ], + "char": '\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68', + fitzpatrick_scale: false, + category: "people" + }, + family_man_woman_boy: { + keywords: [ "home", "parents", "child", "mom", "dad", "father", "mother", "people", "human" ], + "char": '\ud83d\udc6a', + fitzpatrick_scale: false, + category: "people" + }, + family_man_woman_girl: { + keywords: [ "home", "parents", "people", "human", "child" ], + "char": '\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67', + fitzpatrick_scale: false, + category: "people" + }, + family_man_woman_girl_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_man_woman_boy_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_man_woman_girl_girl: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67', + fitzpatrick_scale: false, + category: "people" + }, + family_woman_woman_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_woman_woman_girl: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67', + fitzpatrick_scale: false, + category: "people" + }, + family_woman_woman_girl_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_woman_woman_boy_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_woman_woman_girl_girl: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67', + fitzpatrick_scale: false, + category: "people" + }, + family_man_man_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_man_man_girl: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67', + fitzpatrick_scale: false, + category: "people" + }, + family_man_man_girl_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_man_man_boy_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_man_man_girl_girl: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": '\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67', + fitzpatrick_scale: false, + category: "people" + }, + family_woman_boy: { + keywords: [ "home", "parent", "people", "human", "child" ], + "char": '\ud83d\udc69\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_woman_girl: { + keywords: [ "home", "parent", "people", "human", "child" ], + "char": '\ud83d\udc69\u200d\ud83d\udc67', + fitzpatrick_scale: false, + category: "people" + }, + family_woman_girl_boy: { + keywords: [ "home", "parent", "people", "human", "children" ], + "char": '\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_woman_boy_boy: { + keywords: [ "home", "parent", "people", "human", "children" ], + "char": '\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_woman_girl_girl: { + keywords: [ "home", "parent", "people", "human", "children" ], + "char": '\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67', + fitzpatrick_scale: false, + category: "people" + }, + family_man_boy: { + keywords: [ "home", "parent", "people", "human", "child" ], + "char": '\ud83d\udc68\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_man_girl: { + keywords: [ "home", "parent", "people", "human", "child" ], + "char": '\ud83d\udc68\u200d\ud83d\udc67', + fitzpatrick_scale: false, + category: "people" + }, + family_man_girl_boy: { + keywords: [ "home", "parent", "people", "human", "children" ], + "char": '\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_man_boy_boy: { + keywords: [ "home", "parent", "people", "human", "children" ], + "char": '\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66', + fitzpatrick_scale: false, + category: "people" + }, + family_man_girl_girl: { + keywords: [ "home", "parent", "people", "human", "children" ], + "char": '\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67', + fitzpatrick_scale: false, + category: "people" + }, + yarn: { + keywords: [ "ball", "crochet", "knit" ], + "char": '\ud83e\uddf6', + fitzpatrick_scale: false, + category: "people" + }, + thread: { + keywords: [ "needle", "sewing", "spool", "string" ], + "char": '\ud83e\uddf5', + fitzpatrick_scale: false, + category: "people" + }, + coat: { + keywords: [ "jacket" ], + "char": '\ud83e\udde5', + fitzpatrick_scale: false, + category: "people" + }, + labcoat: { + keywords: [ "doctor", "experiment", "scientist", "chemist" ], + "char": '\ud83e\udd7c', + fitzpatrick_scale: false, + category: "people" + }, + womans_clothes: { + keywords: [ "fashion", "shopping_bags", "female" ], + "char": '\ud83d\udc5a', + fitzpatrick_scale: false, + category: "people" + }, + tshirt: { + keywords: [ "fashion", "cloth", "casual", "shirt", "tee" ], + "char": '\ud83d\udc55', + fitzpatrick_scale: false, + category: "people" + }, + jeans: { + keywords: [ "fashion", "shopping" ], + "char": '\ud83d\udc56', + fitzpatrick_scale: false, + category: "people" + }, + necktie: { + keywords: [ "shirt", "suitup", "formal", "fashion", "cloth", "business" ], + "char": '\ud83d\udc54', + fitzpatrick_scale: false, + category: "people" + }, + dress: { + keywords: [ "clothes", "fashion", "shopping" ], + "char": '\ud83d\udc57', + fitzpatrick_scale: false, + category: "people" + }, + bikini: { + keywords: [ "swimming", "female", "woman", "girl", "fashion", "beach", "summer" ], + "char": '\ud83d\udc59', + fitzpatrick_scale: false, + category: "people" + }, + kimono: { + keywords: [ "dress", "fashion", "women", "female", "japanese" ], + "char": '\ud83d\udc58', + fitzpatrick_scale: false, + category: "people" + }, + lipstick: { + keywords: [ "female", "girl", "fashion", "woman" ], + "char": '\ud83d\udc84', + fitzpatrick_scale: false, + category: "people" + }, + kiss: { + keywords: [ "face", "lips", "love", "like", "affection", "valentines" ], + "char": '\ud83d\udc8b', + fitzpatrick_scale: false, + category: "people" + }, + footprints: { + keywords: [ "feet", "tracking", "walking", "beach" ], + "char": '\ud83d\udc63', + fitzpatrick_scale: false, + category: "people" + }, + flat_shoe: { + keywords: [ "ballet", "slip-on", "slipper" ], + "char": '\ud83e\udd7f', + fitzpatrick_scale: false, + category: "people" + }, + high_heel: { + keywords: [ "fashion", "shoes", "female", "pumps", "stiletto" ], + "char": '\ud83d\udc60', + fitzpatrick_scale: false, + category: "people" + }, + sandal: { + keywords: [ "shoes", "fashion", "flip flops" ], + "char": '\ud83d\udc61', + fitzpatrick_scale: false, + category: "people" + }, + boot: { + keywords: [ "shoes", "fashion" ], + "char": '\ud83d\udc62', + fitzpatrick_scale: false, + category: "people" + }, + mans_shoe: { + keywords: [ "fashion", "male" ], + "char": '\ud83d\udc5e', + fitzpatrick_scale: false, + category: "people" + }, + athletic_shoe: { + keywords: [ "shoes", "sports", "sneakers" ], + "char": '\ud83d\udc5f', + fitzpatrick_scale: false, + category: "people" + }, + hiking_boot: { + keywords: [ "backpacking", "camping", "hiking" ], + "char": '\ud83e\udd7e', + fitzpatrick_scale: false, + category: "people" + }, + socks: { + keywords: [ "stockings", "clothes" ], + "char": '\ud83e\udde6', + fitzpatrick_scale: false, + category: "people" + }, + gloves: { + keywords: [ "hands", "winter", "clothes" ], + "char": '\ud83e\udde4', + fitzpatrick_scale: false, + category: "people" + }, + scarf: { + keywords: [ "neck", "winter", "clothes" ], + "char": '\ud83e\udde3', + fitzpatrick_scale: false, + category: "people" + }, + womans_hat: { + keywords: [ "fashion", "accessories", "female", "lady", "spring" ], + "char": '\ud83d\udc52', + fitzpatrick_scale: false, + category: "people" + }, + tophat: { + keywords: [ "magic", "gentleman", "classy", "circus" ], + "char": '\ud83c\udfa9', + fitzpatrick_scale: false, + category: "people" + }, + billed_hat: { + keywords: [ "cap", "baseball" ], + "char": '\ud83e\udde2', + fitzpatrick_scale: false, + category: "people" + }, + rescue_worker_helmet: { + keywords: [ "construction", "build" ], + "char": '\u26d1', + fitzpatrick_scale: false, + category: "people" + }, + mortar_board: { + keywords: [ "school", "college", "degree", "university", "graduation", "cap", "hat", "legal", "learn", "education" ], + "char": '\ud83c\udf93', + fitzpatrick_scale: false, + category: "people" + }, + crown: { + keywords: [ "king", "kod", "leader", "royalty", "lord" ], + "char": '\ud83d\udc51', + fitzpatrick_scale: false, + category: "people" + }, + school_satchel: { + keywords: [ "student", "education", "bag", "backpack" ], + "char": '\ud83c\udf92', + fitzpatrick_scale: false, + category: "people" + }, + luggage: { + keywords: [ "packing", "travel" ], + "char": '\ud83e\uddf3', + fitzpatrick_scale: false, + category: "people" + }, + pouch: { + keywords: [ "bag", "accessories", "shopping" ], + "char": '\ud83d\udc5d', + fitzpatrick_scale: false, + category: "people" + }, + purse: { + keywords: [ "fashion", "accessories", "money", "sales", "shopping" ], + "char": '\ud83d\udc5b', + fitzpatrick_scale: false, + category: "people" + }, + handbag: { + keywords: [ "fashion", "accessory", "accessories", "shopping" ], + "char": '\ud83d\udc5c', + fitzpatrick_scale: false, + category: "people" + }, + briefcase: { + keywords: [ "business", "documents", "work", "law", "legal", "job", "career" ], + "char": '\ud83d\udcbc', + fitzpatrick_scale: false, + category: "people" + }, + eyeglasses: { + keywords: [ "fashion", "accessories", "eyesight", "nerdy", "dork", "geek" ], + "char": '\ud83d\udc53', + fitzpatrick_scale: false, + category: "people" + }, + dark_sunglasses: { + keywords: [ "face", "cool", "accessories" ], + "char": '\ud83d\udd76', + fitzpatrick_scale: false, + category: "people" + }, + goggles: { + keywords: [ "eyes", "protection", "safety" ], + "char": '\ud83e\udd7d', + fitzpatrick_scale: false, + category: "people" + }, + ring: { + keywords: [ "wedding", "propose", "marriage", "valentines", "diamond", "fashion", "jewelry", "gem", "engagement" ], + "char": '\ud83d\udc8d', + fitzpatrick_scale: false, + category: "people" + }, + closed_umbrella: { + keywords: [ "weather", "rain", "drizzle" ], + "char": '\ud83c\udf02', + fitzpatrick_scale: false, + category: "people" + }, + dog: { + keywords: [ "animal", "friend", "nature", "woof", "puppy", "pet", "faithful" ], + "char": '\ud83d\udc36', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cat: { + keywords: [ "animal", "meow", "nature", "pet", "kitten" ], + "char": '\ud83d\udc31', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + mouse: { + keywords: [ "animal", "nature", "cheese_wedge", "rodent" ], + "char": '\ud83d\udc2d', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hamster: { + keywords: [ "animal", "nature" ], + "char": '\ud83d\udc39', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + rabbit: { + keywords: [ "animal", "nature", "pet", "spring", "magic", "bunny" ], + "char": '\ud83d\udc30', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + fox_face: { + keywords: [ "animal", "nature", "face" ], + "char": '\ud83e\udd8a', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + bear: { + keywords: [ "animal", "nature", "wild" ], + "char": '\ud83d\udc3b', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + panda_face: { + keywords: [ "animal", "nature", "panda" ], + "char": '\ud83d\udc3c', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + koala: { + keywords: [ "animal", "nature" ], + "char": '\ud83d\udc28', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + tiger: { + keywords: [ "animal", "cat", "danger", "wild", "nature", "roar" ], + "char": '\ud83d\udc2f', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + lion: { + keywords: [ "animal", "nature" ], + "char": '\ud83e\udd81', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cow: { + keywords: [ "beef", "ox", "animal", "nature", "moo", "milk" ], + "char": '\ud83d\udc2e', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + pig: { + keywords: [ "animal", "oink", "nature" ], + "char": '\ud83d\udc37', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + pig_nose: { + keywords: [ "animal", "oink" ], + "char": '\ud83d\udc3d', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + frog: { + keywords: [ "animal", "nature", "croak", "toad" ], + "char": '\ud83d\udc38', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + squid: { + keywords: [ "animal", "nature", "ocean", "sea" ], + "char": '\ud83e\udd91', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + octopus: { + keywords: [ "animal", "creature", "ocean", "sea", "nature", "beach" ], + "char": '\ud83d\udc19', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + shrimp: { + keywords: [ "animal", "ocean", "nature", "seafood" ], + "char": '\ud83e\udd90', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + monkey_face: { + keywords: [ "animal", "nature", "circus" ], + "char": '\ud83d\udc35', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + gorilla: { + keywords: [ "animal", "nature", "circus" ], + "char": '\ud83e\udd8d', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + see_no_evil: { + keywords: [ "monkey", "animal", "nature", "haha" ], + "char": '\ud83d\ude48', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hear_no_evil: { + keywords: [ "animal", "monkey", "nature" ], + "char": '\ud83d\ude49', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + speak_no_evil: { + keywords: [ "monkey", "animal", "nature", "omg" ], + "char": '\ud83d\ude4a', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + monkey: { + keywords: [ "animal", "nature", "banana", "circus" ], + "char": '\ud83d\udc12', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + chicken: { + keywords: [ "animal", "cluck", "nature", "bird" ], + "char": '\ud83d\udc14', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + penguin: { + keywords: [ "animal", "nature" ], + "char": '\ud83d\udc27', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + bird: { + keywords: [ "animal", "nature", "fly", "tweet", "spring" ], + "char": '\ud83d\udc26', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + baby_chick: { + keywords: [ "animal", "chicken", "bird" ], + "char": '\ud83d\udc24', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hatching_chick: { + keywords: [ "animal", "chicken", "egg", "born", "baby", "bird" ], + "char": '\ud83d\udc23', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hatched_chick: { + keywords: [ "animal", "chicken", "baby", "bird" ], + "char": '\ud83d\udc25', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + duck: { + keywords: [ "animal", "nature", "bird", "mallard" ], + "char": '\ud83e\udd86', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + eagle: { + keywords: [ "animal", "nature", "bird" ], + "char": '\ud83e\udd85', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + owl: { + keywords: [ "animal", "nature", "bird", "hoot" ], + "char": '\ud83e\udd89', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + bat: { + keywords: [ "animal", "nature", "blind", "vampire" ], + "char": '\ud83e\udd87', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + wolf: { + keywords: [ "animal", "nature", "wild" ], + "char": '\ud83d\udc3a', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + boar: { + keywords: [ "animal", "nature" ], + "char": '\ud83d\udc17', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + horse: { + keywords: [ "animal", "brown", "nature" ], + "char": '\ud83d\udc34', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + unicorn: { + keywords: [ "animal", "nature", "mystical" ], + "char": '\ud83e\udd84', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + honeybee: { + keywords: [ "animal", "insect", "nature", "bug", "spring", "honey" ], + "char": '\ud83d\udc1d', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + bug: { + keywords: [ "animal", "insect", "nature", "worm" ], + "char": '\ud83d\udc1b', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + butterfly: { + keywords: [ "animal", "insect", "nature", "caterpillar" ], + "char": '\ud83e\udd8b', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + snail: { + keywords: [ "slow", "animal", "shell" ], + "char": '\ud83d\udc0c', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + beetle: { + keywords: [ "animal", "insect", "nature", "ladybug" ], + "char": '\ud83d\udc1e', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + ant: { + keywords: [ "animal", "insect", "nature", "bug" ], + "char": '\ud83d\udc1c', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + grasshopper: { + keywords: [ "animal", "cricket", "chirp" ], + "char": '\ud83e\udd97', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + spider: { + keywords: [ "animal", "arachnid" ], + "char": '\ud83d\udd77', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + scorpion: { + keywords: [ "animal", "arachnid" ], + "char": '\ud83e\udd82', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + crab: { + keywords: [ "animal", "crustacean" ], + "char": '\ud83e\udd80', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + snake: { + keywords: [ "animal", "evil", "nature", "hiss", "python" ], + "char": '\ud83d\udc0d', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + lizard: { + keywords: [ "animal", "nature", "reptile" ], + "char": '\ud83e\udd8e', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + "t-rex": { + keywords: [ "animal", "nature", "dinosaur", "tyrannosaurus", "extinct" ], + "char": '\ud83e\udd96', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sauropod: { + keywords: [ "animal", "nature", "dinosaur", "brachiosaurus", "brontosaurus", "diplodocus", "extinct" ], + "char": '\ud83e\udd95', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + turtle: { + keywords: [ "animal", "slow", "nature", "tortoise" ], + "char": '\ud83d\udc22', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + tropical_fish: { + keywords: [ "animal", "swim", "ocean", "beach", "nemo" ], + "char": '\ud83d\udc20', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + fish: { + keywords: [ "animal", "food", "nature" ], + "char": '\ud83d\udc1f', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + blowfish: { + keywords: [ "animal", "nature", "food", "sea", "ocean" ], + "char": '\ud83d\udc21', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dolphin: { + keywords: [ "animal", "nature", "fish", "sea", "ocean", "flipper", "fins", "beach" ], + "char": '\ud83d\udc2c', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + shark: { + keywords: [ "animal", "nature", "fish", "sea", "ocean", "jaws", "fins", "beach" ], + "char": '\ud83e\udd88', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + whale: { + keywords: [ "animal", "nature", "sea", "ocean" ], + "char": '\ud83d\udc33', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + whale2: { + keywords: [ "animal", "nature", "sea", "ocean" ], + "char": '\ud83d\udc0b', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + crocodile: { + keywords: [ "animal", "nature", "reptile", "lizard", "alligator" ], + "char": '\ud83d\udc0a', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + leopard: { + keywords: [ "animal", "nature" ], + "char": '\ud83d\udc06', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + zebra: { + keywords: [ "animal", "nature", "stripes", "safari" ], + "char": '\ud83e\udd93', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + tiger2: { + keywords: [ "animal", "nature", "roar" ], + "char": '\ud83d\udc05', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + water_buffalo: { + keywords: [ "animal", "nature", "ox", "cow" ], + "char": '\ud83d\udc03', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + ox: { + keywords: [ "animal", "cow", "beef" ], + "char": '\ud83d\udc02', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cow2: { + keywords: [ "beef", "ox", "animal", "nature", "moo", "milk" ], + "char": '\ud83d\udc04', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + deer: { + keywords: [ "animal", "nature", "horns", "venison" ], + "char": '\ud83e\udd8c', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dromedary_camel: { + keywords: [ "animal", "hot", "desert", "hump" ], + "char": '\ud83d\udc2a', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + camel: { + keywords: [ "animal", "nature", "hot", "desert", "hump" ], + "char": '\ud83d\udc2b', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + giraffe: { + keywords: [ "animal", "nature", "spots", "safari" ], + "char": '\ud83e\udd92', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + elephant: { + keywords: [ "animal", "nature", "nose", "th", "circus" ], + "char": '\ud83d\udc18', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + rhinoceros: { + keywords: [ "animal", "nature", "horn" ], + "char": '\ud83e\udd8f', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + goat: { + keywords: [ "animal", "nature" ], + "char": '\ud83d\udc10', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + ram: { + keywords: [ "animal", "sheep", "nature" ], + "char": '\ud83d\udc0f', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sheep: { + keywords: [ "animal", "nature", "wool", "shipit" ], + "char": '\ud83d\udc11', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + racehorse: { + keywords: [ "animal", "gamble", "luck" ], + "char": '\ud83d\udc0e', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + pig2: { + keywords: [ "animal", "nature" ], + "char": '\ud83d\udc16', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + rat: { + keywords: [ "animal", "mouse", "rodent" ], + "char": '\ud83d\udc00', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + mouse2: { + keywords: [ "animal", "nature", "rodent" ], + "char": '\ud83d\udc01', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + rooster: { + keywords: [ "animal", "nature", "chicken" ], + "char": '\ud83d\udc13', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + turkey: { + keywords: [ "animal", "bird" ], + "char": '\ud83e\udd83', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dove: { + keywords: [ "animal", "bird" ], + "char": '\ud83d\udd4a', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dog2: { + keywords: [ "animal", "nature", "friend", "doge", "pet", "faithful" ], + "char": '\ud83d\udc15', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + poodle: { + keywords: [ "dog", "animal", "101", "nature", "pet" ], + "char": '\ud83d\udc29', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cat2: { + keywords: [ "animal", "meow", "pet", "cats" ], + "char": '\ud83d\udc08', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + rabbit2: { + keywords: [ "animal", "nature", "pet", "magic", "spring" ], + "char": '\ud83d\udc07', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + chipmunk: { + keywords: [ "animal", "nature", "rodent", "squirrel" ], + "char": '\ud83d\udc3f', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hedgehog: { + keywords: [ "animal", "nature", "spiny" ], + "char": '\ud83e\udd94', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + raccoon: { + keywords: [ "animal", "nature" ], + "char": '\ud83e\udd9d', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + llama: { + keywords: [ "animal", "nature", "alpaca" ], + "char": '\ud83e\udd99', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hippopotamus: { + keywords: [ "animal", "nature" ], + "char": '\ud83e\udd9b', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + kangaroo: { + keywords: [ "animal", "nature", "australia", "joey", "hop", "marsupial" ], + "char": '\ud83e\udd98', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + badger: { + keywords: [ "animal", "nature", "honey" ], + "char": '\ud83e\udda1', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + swan: { + keywords: [ "animal", "nature", "bird" ], + "char": '\ud83e\udda2', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + peacock: { + keywords: [ "animal", "nature", "peahen", "bird" ], + "char": '\ud83e\udd9a', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + parrot: { + keywords: [ "animal", "nature", "bird", "pirate", "talk" ], + "char": '\ud83e\udd9c', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + lobster: { + keywords: [ "animal", "nature", "bisque", "claws", "seafood" ], + "char": '\ud83e\udd9e', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + mosquito: { + keywords: [ "animal", "nature", "insect", "malaria" ], + "char": '\ud83e\udd9f', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + paw_prints: { + keywords: [ "animal", "tracking", "footprints", "dog", "cat", "pet", "feet" ], + "char": '\ud83d\udc3e', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dragon: { + keywords: [ "animal", "myth", "nature", "chinese", "green" ], + "char": '\ud83d\udc09', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dragon_face: { + keywords: [ "animal", "myth", "nature", "chinese", "green" ], + "char": '\ud83d\udc32', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cactus: { + keywords: [ "vegetable", "plant", "nature" ], + "char": '\ud83c\udf35', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + christmas_tree: { + keywords: [ "festival", "vacation", "december", "xmas", "celebration" ], + "char": '\ud83c\udf84', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + evergreen_tree: { + keywords: [ "plant", "nature" ], + "char": '\ud83c\udf32', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + deciduous_tree: { + keywords: [ "plant", "nature" ], + "char": '\ud83c\udf33', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + palm_tree: { + keywords: [ "plant", "vegetable", "nature", "summer", "beach", "mojito", "tropical" ], + "char": '\ud83c\udf34', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + seedling: { + keywords: [ "plant", "nature", "grass", "lawn", "spring" ], + "char": '\ud83c\udf31', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + herb: { + keywords: [ "vegetable", "plant", "medicine", "weed", "grass", "lawn" ], + "char": '\ud83c\udf3f', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + shamrock: { + keywords: [ "vegetable", "plant", "nature", "irish", "clover" ], + "char": '\u2618', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + four_leaf_clover: { + keywords: [ "vegetable", "plant", "nature", "lucky", "irish" ], + "char": '\ud83c\udf40', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + bamboo: { + keywords: [ "plant", "nature", "vegetable", "panda", "pine_decoration" ], + "char": '\ud83c\udf8d', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + tanabata_tree: { + keywords: [ "plant", "nature", "branch", "summer" ], + "char": '\ud83c\udf8b', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + leaves: { + keywords: [ "nature", "plant", "tree", "vegetable", "grass", "lawn", "spring" ], + "char": '\ud83c\udf43', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + fallen_leaf: { + keywords: [ "nature", "plant", "vegetable", "leaves" ], + "char": '\ud83c\udf42', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + maple_leaf: { + keywords: [ "nature", "plant", "vegetable", "ca", "fall" ], + "char": '\ud83c\udf41', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + ear_of_rice: { + keywords: [ "nature", "plant" ], + "char": '\ud83c\udf3e', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hibiscus: { + keywords: [ "plant", "vegetable", "flowers", "beach" ], + "char": '\ud83c\udf3a', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sunflower: { + keywords: [ "nature", "plant", "fall" ], + "char": '\ud83c\udf3b', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + rose: { + keywords: [ "flowers", "valentines", "love", "spring" ], + "char": '\ud83c\udf39', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + wilted_flower: { + keywords: [ "plant", "nature", "flower" ], + "char": '\ud83e\udd40', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + tulip: { + keywords: [ "flowers", "plant", "nature", "summer", "spring" ], + "char": '\ud83c\udf37', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + blossom: { + keywords: [ "nature", "flowers", "yellow" ], + "char": '\ud83c\udf3c', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cherry_blossom: { + keywords: [ "nature", "plant", "spring", "flower" ], + "char": '\ud83c\udf38', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + bouquet: { + keywords: [ "flowers", "nature", "spring" ], + "char": '\ud83d\udc90', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + mushroom: { + keywords: [ "plant", "vegetable" ], + "char": '\ud83c\udf44', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + chestnut: { + keywords: [ "food", "squirrel" ], + "char": '\ud83c\udf30', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + jack_o_lantern: { + keywords: [ "halloween", "light", "pumpkin", "creepy", "fall" ], + "char": '\ud83c\udf83', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + shell: { + keywords: [ "nature", "sea", "beach" ], + "char": '\ud83d\udc1a', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + spider_web: { + keywords: [ "animal", "insect", "arachnid", "silk" ], + "char": '\ud83d\udd78', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + earth_americas: { + keywords: [ "globe", "world", "USA", "international" ], + "char": '\ud83c\udf0e', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + earth_africa: { + keywords: [ "globe", "world", "international" ], + "char": '\ud83c\udf0d', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + earth_asia: { + keywords: [ "globe", "world", "east", "international" ], + "char": '\ud83c\udf0f', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + full_moon: { + keywords: [ "nature", "yellow", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": '\ud83c\udf15', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + waning_gibbous_moon: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep", "waxing_gibbous_moon" ], + "char": '\ud83c\udf16', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + last_quarter_moon: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": '\ud83c\udf17', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + waning_crescent_moon: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": '\ud83c\udf18', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + new_moon: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": '\ud83c\udf11', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + waxing_crescent_moon: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": '\ud83c\udf12', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + first_quarter_moon: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": '\ud83c\udf13', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + waxing_gibbous_moon: { + keywords: [ "nature", "night", "sky", "gray", "twilight", "planet", "space", "evening", "sleep" ], + "char": '\ud83c\udf14', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + new_moon_with_face: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": '\ud83c\udf1a', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + full_moon_with_face: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": '\ud83c\udf1d', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + first_quarter_moon_with_face: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": '\ud83c\udf1b', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + last_quarter_moon_with_face: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": '\ud83c\udf1c', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sun_with_face: { + keywords: [ "nature", "morning", "sky" ], + "char": '\ud83c\udf1e', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + crescent_moon: { + keywords: [ "night", "sleep", "sky", "evening", "magic" ], + "char": '\ud83c\udf19', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + star: { + keywords: [ "night", "yellow" ], + "char": '\u2b50', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + star2: { + keywords: [ "night", "sparkle", "awesome", "good", "magic" ], + "char": '\ud83c\udf1f', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dizzy: { + keywords: [ "star", "sparkle", "shoot", "magic" ], + "char": '\ud83d\udcab', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sparkles: { + keywords: [ "stars", "shine", "shiny", "cool", "awesome", "good", "magic" ], + "char": '\u2728', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + comet: { + keywords: [ "space" ], + "char": '\u2604', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sunny: { + keywords: [ "weather", "nature", "brightness", "summer", "beach", "spring" ], + "char": '\u2600\ufe0f', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sun_behind_small_cloud: { + keywords: [ "weather" ], + "char": '\ud83c\udf24', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + partly_sunny: { + keywords: [ "weather", "nature", "cloudy", "morning", "fall", "spring" ], + "char": '\u26c5', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sun_behind_large_cloud: { + keywords: [ "weather" ], + "char": '\ud83c\udf25', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sun_behind_rain_cloud: { + keywords: [ "weather" ], + "char": '\ud83c\udf26', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cloud: { + keywords: [ "weather", "sky" ], + "char": '\u2601\ufe0f', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cloud_with_rain: { + keywords: [ "weather" ], + "char": '\ud83c\udf27', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cloud_with_lightning_and_rain: { + keywords: [ "weather", "lightning" ], + "char": '\u26c8', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cloud_with_lightning: { + keywords: [ "weather", "thunder" ], + "char": '\ud83c\udf29', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + zap: { + keywords: [ "thunder", "weather", "lightning bolt", "fast" ], + "char": '\u26a1', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + fire: { + keywords: [ "hot", "cook", "flame" ], + "char": '\ud83d\udd25', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + boom: { + keywords: [ "bomb", "explode", "explosion", "collision", "blown" ], + "char": '\ud83d\udca5', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + snowflake: { + keywords: [ "winter", "season", "cold", "weather", "christmas", "xmas" ], + "char": '\u2744\ufe0f', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cloud_with_snow: { + keywords: [ "weather" ], + "char": '\ud83c\udf28', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + snowman: { + keywords: [ "winter", "season", "cold", "weather", "christmas", "xmas", "frozen", "without_snow" ], + "char": '\u26c4', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + snowman_with_snow: { + keywords: [ "winter", "season", "cold", "weather", "christmas", "xmas", "frozen" ], + "char": '\u2603', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + wind_face: { + keywords: [ "gust", "air" ], + "char": '\ud83c\udf2c', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dash: { + keywords: [ "wind", "air", "fast", "shoo", "fart", "smoke", "puff" ], + "char": '\ud83d\udca8', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + tornado: { + keywords: [ "weather", "cyclone", "twister" ], + "char": '\ud83c\udf2a', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + fog: { + keywords: [ "weather" ], + "char": '\ud83c\udf2b', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + open_umbrella: { + keywords: [ "weather", "spring" ], + "char": '\u2602', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + umbrella: { + keywords: [ "rainy", "weather", "spring" ], + "char": '\u2614', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + droplet: { + keywords: [ "water", "drip", "faucet", "spring" ], + "char": '\ud83d\udca7', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sweat_drops: { + keywords: [ "water", "drip", "oops" ], + "char": '\ud83d\udca6', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + ocean: { + keywords: [ "sea", "water", "wave", "nature", "tsunami", "disaster" ], + "char": '\ud83c\udf0a', + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + green_apple: { + keywords: [ "fruit", "nature" ], + "char": '\ud83c\udf4f', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + apple: { + keywords: [ "fruit", "mac", "school" ], + "char": '\ud83c\udf4e', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + pear: { + keywords: [ "fruit", "nature", "food" ], + "char": '\ud83c\udf50', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + tangerine: { + keywords: [ "food", "fruit", "nature", "orange" ], + "char": '\ud83c\udf4a', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + lemon: { + keywords: [ "fruit", "nature" ], + "char": '\ud83c\udf4b', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + banana: { + keywords: [ "fruit", "food", "monkey" ], + "char": '\ud83c\udf4c', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + watermelon: { + keywords: [ "fruit", "food", "picnic", "summer" ], + "char": '\ud83c\udf49', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + grapes: { + keywords: [ "fruit", "food", "wine" ], + "char": '\ud83c\udf47', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + strawberry: { + keywords: [ "fruit", "food", "nature" ], + "char": '\ud83c\udf53', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + melon: { + keywords: [ "fruit", "nature", "food" ], + "char": '\ud83c\udf48', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cherries: { + keywords: [ "food", "fruit" ], + "char": '\ud83c\udf52', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + peach: { + keywords: [ "fruit", "nature", "food" ], + "char": '\ud83c\udf51', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + pineapple: { + keywords: [ "fruit", "nature", "food" ], + "char": '\ud83c\udf4d', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + coconut: { + keywords: [ "fruit", "nature", "food", "palm" ], + "char": '\ud83e\udd65', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + kiwi_fruit: { + keywords: [ "fruit", "food" ], + "char": '\ud83e\udd5d', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + mango: { + keywords: [ "fruit", "food", "tropical" ], + "char": '\ud83e\udd6d', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + avocado: { + keywords: [ "fruit", "food" ], + "char": '\ud83e\udd51', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + broccoli: { + keywords: [ "fruit", "food", "vegetable" ], + "char": '\ud83e\udd66', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + tomato: { + keywords: [ "fruit", "vegetable", "nature", "food" ], + "char": '\ud83c\udf45', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + eggplant: { + keywords: [ "vegetable", "nature", "food", "aubergine" ], + "char": '\ud83c\udf46', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cucumber: { + keywords: [ "fruit", "food", "pickle" ], + "char": '\ud83e\udd52', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + carrot: { + keywords: [ "vegetable", "food", "orange" ], + "char": '\ud83e\udd55', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + hot_pepper: { + keywords: [ "food", "spicy", "chilli", "chili" ], + "char": '\ud83c\udf36', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + potato: { + keywords: [ "food", "tuber", "vegatable", "starch" ], + "char": '\ud83e\udd54', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + corn: { + keywords: [ "food", "vegetable", "plant" ], + "char": '\ud83c\udf3d', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + leafy_greens: { + keywords: [ "food", "vegetable", "plant", "bok choy", "cabbage", "kale", "lettuce" ], + "char": '\ud83e\udd6c', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + sweet_potato: { + keywords: [ "food", "nature" ], + "char": '\ud83c\udf60', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + peanuts: { + keywords: [ "food", "nut" ], + "char": '\ud83e\udd5c', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + honey_pot: { + keywords: [ "bees", "sweet", "kitchen" ], + "char": '\ud83c\udf6f', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + croissant: { + keywords: [ "food", "bread", "french" ], + "char": '\ud83e\udd50', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + bread: { + keywords: [ "food", "wheat", "breakfast", "toast" ], + "char": '\ud83c\udf5e', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + baguette_bread: { + keywords: [ "food", "bread", "french" ], + "char": '\ud83e\udd56', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + bagel: { + keywords: [ "food", "bread", "bakery", "schmear" ], + "char": '\ud83e\udd6f', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + pretzel: { + keywords: [ "food", "bread", "twisted" ], + "char": '\ud83e\udd68', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cheese: { + keywords: [ "food", "chadder" ], + "char": '\ud83e\uddc0', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + egg: { + keywords: [ "food", "chicken", "breakfast" ], + "char": '\ud83e\udd5a', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + bacon: { + keywords: [ "food", "breakfast", "pork", "pig", "meat" ], + "char": '\ud83e\udd53', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + steak: { + keywords: [ "food", "cow", "meat", "cut", "chop", "lambchop", "porkchop" ], + "char": '\ud83e\udd69', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + pancakes: { + keywords: [ "food", "breakfast", "flapjacks", "hotcakes" ], + "char": '\ud83e\udd5e', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + poultry_leg: { + keywords: [ "food", "meat", "drumstick", "bird", "chicken", "turkey" ], + "char": '\ud83c\udf57', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + meat_on_bone: { + keywords: [ "good", "food", "drumstick" ], + "char": '\ud83c\udf56', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + bone: { + keywords: [ "skeleton" ], + "char": '\ud83e\uddb4', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + fried_shrimp: { + keywords: [ "food", "animal", "appetizer", "summer" ], + "char": '\ud83c\udf64', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + fried_egg: { + keywords: [ "food", "breakfast", "kitchen", "egg" ], + "char": '\ud83c\udf73', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + hamburger: { + keywords: [ "meat", "fast food", "beef", "cheeseburger", "mcdonalds", "burger king" ], + "char": '\ud83c\udf54', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + fries: { + keywords: [ "chips", "snack", "fast food" ], + "char": '\ud83c\udf5f', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + stuffed_flatbread: { + keywords: [ "food", "flatbread", "stuffed", "gyro" ], + "char": '\ud83e\udd59', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + hotdog: { + keywords: [ "food", "frankfurter" ], + "char": '\ud83c\udf2d', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + pizza: { + keywords: [ "food", "party" ], + "char": '\ud83c\udf55', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + sandwich: { + keywords: [ "food", "lunch", "bread" ], + "char": '\ud83e\udd6a', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + canned_food: { + keywords: [ "food", "soup" ], + "char": '\ud83e\udd6b', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + spaghetti: { + keywords: [ "food", "italian", "noodle" ], + "char": '\ud83c\udf5d', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + taco: { + keywords: [ "food", "mexican" ], + "char": '\ud83c\udf2e', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + burrito: { + keywords: [ "food", "mexican" ], + "char": '\ud83c\udf2f', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + green_salad: { + keywords: [ "food", "healthy", "lettuce" ], + "char": '\ud83e\udd57', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + shallow_pan_of_food: { + keywords: [ "food", "cooking", "casserole", "paella" ], + "char": '\ud83e\udd58', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + ramen: { + keywords: [ "food", "japanese", "noodle", "chopsticks" ], + "char": '\ud83c\udf5c', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + stew: { + keywords: [ "food", "meat", "soup" ], + "char": '\ud83c\udf72', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + fish_cake: { + keywords: [ "food", "japan", "sea", "beach", "narutomaki", "pink", "swirl", "kamaboko", "surimi", "ramen" ], + "char": '\ud83c\udf65', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + fortune_cookie: { + keywords: [ "food", "prophecy" ], + "char": '\ud83e\udd60', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + sushi: { + keywords: [ "food", "fish", "japanese", "rice" ], + "char": '\ud83c\udf63', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + bento: { + keywords: [ "food", "japanese", "box" ], + "char": '\ud83c\udf71', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + curry: { + keywords: [ "food", "spicy", "hot", "indian" ], + "char": '\ud83c\udf5b', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + rice_ball: { + keywords: [ "food", "japanese" ], + "char": '\ud83c\udf59', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + rice: { + keywords: [ "food", "china", "asian" ], + "char": '\ud83c\udf5a', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + rice_cracker: { + keywords: [ "food", "japanese" ], + "char": '\ud83c\udf58', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + oden: { + keywords: [ "food", "japanese" ], + "char": '\ud83c\udf62', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + dango: { + keywords: [ "food", "dessert", "sweet", "japanese", "barbecue", "meat" ], + "char": '\ud83c\udf61', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + shaved_ice: { + keywords: [ "hot", "dessert", "summer" ], + "char": '\ud83c\udf67', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + ice_cream: { + keywords: [ "food", "hot", "dessert" ], + "char": '\ud83c\udf68', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + icecream: { + keywords: [ "food", "hot", "dessert", "summer" ], + "char": '\ud83c\udf66', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + pie: { + keywords: [ "food", "dessert", "pastry" ], + "char": '\ud83e\udd67', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cake: { + keywords: [ "food", "dessert" ], + "char": '\ud83c\udf70', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cupcake: { + keywords: [ "food", "dessert", "bakery", "sweet" ], + "char": '\ud83e\uddc1', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + moon_cake: { + keywords: [ "food", "autumn" ], + "char": '\ud83e\udd6e', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + birthday: { + keywords: [ "food", "dessert", "cake" ], + "char": '\ud83c\udf82', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + custard: { + keywords: [ "dessert", "food" ], + "char": '\ud83c\udf6e', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + candy: { + keywords: [ "snack", "dessert", "sweet", "lolly" ], + "char": '\ud83c\udf6c', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + lollipop: { + keywords: [ "food", "snack", "candy", "sweet" ], + "char": '\ud83c\udf6d', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + chocolate_bar: { + keywords: [ "food", "snack", "dessert", "sweet" ], + "char": '\ud83c\udf6b', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + popcorn: { + keywords: [ "food", "movie theater", "films", "snack" ], + "char": '\ud83c\udf7f', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + dumpling: { + keywords: [ "food", "empanada", "pierogi", "potsticker" ], + "char": '\ud83e\udd5f', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + doughnut: { + keywords: [ "food", "dessert", "snack", "sweet", "donut" ], + "char": '\ud83c\udf69', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cookie: { + keywords: [ "food", "snack", "oreo", "chocolate", "sweet", "dessert" ], + "char": '\ud83c\udf6a', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + milk_glass: { + keywords: [ "beverage", "drink", "cow" ], + "char": '\ud83e\udd5b', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + beer: { + keywords: [ "relax", "beverage", "drink", "drunk", "party", "pub", "summer", "alcohol", "booze" ], + "char": '\ud83c\udf7a', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + beers: { + keywords: [ "relax", "beverage", "drink", "drunk", "party", "pub", "summer", "alcohol", "booze" ], + "char": '\ud83c\udf7b', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + clinking_glasses: { + keywords: [ "beverage", "drink", "party", "alcohol", "celebrate", "cheers", "wine", "champagne", "toast" ], + "char": '\ud83e\udd42', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + wine_glass: { + keywords: [ "drink", "beverage", "drunk", "alcohol", "booze" ], + "char": '\ud83c\udf77', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + tumbler_glass: { + keywords: [ "drink", "beverage", "drunk", "alcohol", "liquor", "booze", "bourbon", "scotch", "whisky", "glass", "shot" ], + "char": '\ud83e\udd43', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cocktail: { + keywords: [ "drink", "drunk", "alcohol", "beverage", "booze", "mojito" ], + "char": '\ud83c\udf78', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + tropical_drink: { + keywords: [ "beverage", "cocktail", "summer", "beach", "alcohol", "booze", "mojito" ], + "char": '\ud83c\udf79', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + champagne: { + keywords: [ "drink", "wine", "bottle", "celebration" ], + "char": '\ud83c\udf7e', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + sake: { + keywords: [ "wine", "drink", "drunk", "beverage", "japanese", "alcohol", "booze" ], + "char": '\ud83c\udf76', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + tea: { + keywords: [ "drink", "bowl", "breakfast", "green", "british" ], + "char": '\ud83c\udf75', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cup_with_straw: { + keywords: [ "drink", "soda" ], + "char": '\ud83e\udd64', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + coffee: { + keywords: [ "beverage", "caffeine", "latte", "espresso" ], + "char": '\u2615', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + baby_bottle: { + keywords: [ "food", "container", "milk" ], + "char": '\ud83c\udf7c', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + salt: { + keywords: [ "condiment", "shaker" ], + "char": '\ud83e\uddc2', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + spoon: { + keywords: [ "cutlery", "kitchen", "tableware" ], + "char": '\ud83e\udd44', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + fork_and_knife: { + keywords: [ "cutlery", "kitchen" ], + "char": '\ud83c\udf74', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + plate_with_cutlery: { + keywords: [ "food", "eat", "meal", "lunch", "dinner", "restaurant" ], + "char": '\ud83c\udf7d', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + bowl_with_spoon: { + keywords: [ "food", "breakfast", "cereal", "oatmeal", "porridge" ], + "char": '\ud83e\udd63', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + takeout_box: { + keywords: [ "food", "leftovers" ], + "char": '\ud83e\udd61', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + chopsticks: { + keywords: [ "food" ], + "char": '\ud83e\udd62', + fitzpatrick_scale: false, + category: "food_and_drink" + }, + soccer: { + keywords: [ "sports", "football" ], + "char": '\u26bd', + fitzpatrick_scale: false, + category: "activity" + }, + basketball: { + keywords: [ "sports", "balls", "NBA" ], + "char": '\ud83c\udfc0', + fitzpatrick_scale: false, + category: "activity" + }, + football: { + keywords: [ "sports", "balls", "NFL" ], + "char": '\ud83c\udfc8', + fitzpatrick_scale: false, + category: "activity" + }, + baseball: { + keywords: [ "sports", "balls" ], + "char": '\u26be', + fitzpatrick_scale: false, + category: "activity" + }, + softball: { + keywords: [ "sports", "balls" ], + "char": '\ud83e\udd4e', + fitzpatrick_scale: false, + category: "activity" + }, + tennis: { + keywords: [ "sports", "balls", "green" ], + "char": '\ud83c\udfbe', + fitzpatrick_scale: false, + category: "activity" + }, + volleyball: { + keywords: [ "sports", "balls" ], + "char": '\ud83c\udfd0', + fitzpatrick_scale: false, + category: "activity" + }, + rugby_football: { + keywords: [ "sports", "team" ], + "char": '\ud83c\udfc9', + fitzpatrick_scale: false, + category: "activity" + }, + flying_disc: { + keywords: [ "sports", "frisbee", "ultimate" ], + "char": '\ud83e\udd4f', + fitzpatrick_scale: false, + category: "activity" + }, + "8ball": { + keywords: [ "pool", "hobby", "game", "luck", "magic" ], + "char": '\ud83c\udfb1', + fitzpatrick_scale: false, + category: "activity" + }, + golf: { + keywords: [ "sports", "business", "flag", "hole", "summer" ], + "char": '\u26f3', + fitzpatrick_scale: false, + category: "activity" + }, + golfing_woman: { + keywords: [ "sports", "business", "woman", "female" ], + "char": '\ud83c\udfcc\ufe0f\u200d\u2640\ufe0f', + fitzpatrick_scale: false, + category: "activity" + }, + golfing_man: { + keywords: [ "sports", "business" ], + "char": '\ud83c\udfcc', + fitzpatrick_scale: true, + category: "activity" + }, + ping_pong: { + keywords: [ "sports", "pingpong" ], + "char": '\ud83c\udfd3', + fitzpatrick_scale: false, + category: "activity" + }, + badminton: { + keywords: [ "sports" ], + "char": '\ud83c\udff8', + fitzpatrick_scale: false, + category: "activity" + }, + goal_net: { + keywords: [ "sports" ], + "char": '\ud83e\udd45', + fitzpatrick_scale: false, + category: "activity" + }, + ice_hockey: { + keywords: [ "sports" ], + "char": '\ud83c\udfd2', + fitzpatrick_scale: false, + category: "activity" + }, + field_hockey: { + keywords: [ "sports" ], + "char": '\ud83c\udfd1', + fitzpatrick_scale: false, + category: "activity" + }, + lacrosse: { + keywords: [ "sports", "ball", "stick" ], + "char": '\ud83e\udd4d', + fitzpatrick_scale: false, + category: "activity" + }, + cricket: { + keywords: [ "sports" ], + "char": '\ud83c\udfcf', + fitzpatrick_scale: false, + category: "activity" + }, + ski: { + keywords: [ "sports", "winter", "cold", "snow" ], + "char": '\ud83c\udfbf', + fitzpatrick_scale: false, + category: "activity" + }, + skier: { + keywords: [ "sports", "winter", "snow" ], + "char": '\u26f7', + fitzpatrick_scale: false, + category: "activity" + }, + snowboarder: { + keywords: [ "sports", "winter" ], + "char": '\ud83c\udfc2', + fitzpatrick_scale: true, + category: "activity" + }, + person_fencing: { + keywords: [ "sports", "fencing", "sword" ], + "char": '\ud83e\udd3a', + fitzpatrick_scale: false, + category: "activity" + }, + women_wrestling: { + keywords: [ "sports", "wrestlers" ], + "char": '\ud83e\udd3c\u200d\u2640\ufe0f', + fitzpatrick_scale: false, + category: "activity" + }, + men_wrestling: { + keywords: [ "sports", "wrestlers" ], + "char": '\ud83e\udd3c\u200d\u2642\ufe0f', + fitzpatrick_scale: false, + category: "activity" + }, + woman_cartwheeling: { + keywords: [ "gymnastics" ], + "char": '\ud83e\udd38\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + man_cartwheeling: { + keywords: [ "gymnastics" ], + "char": '\ud83e\udd38\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + woman_playing_handball: { + keywords: [ "sports" ], + "char": '\ud83e\udd3e\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + man_playing_handball: { + keywords: [ "sports" ], + "char": '\ud83e\udd3e\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + ice_skate: { + keywords: [ "sports" ], + "char": '\u26f8', + fitzpatrick_scale: false, + category: "activity" + }, + curling_stone: { + keywords: [ "sports" ], + "char": '\ud83e\udd4c', + fitzpatrick_scale: false, + category: "activity" + }, + skateboard: { + keywords: [ "board" ], + "char": '\ud83d\udef9', + fitzpatrick_scale: false, + category: "activity" + }, + sled: { + keywords: [ "sleigh", "luge", "toboggan" ], + "char": '\ud83d\udef7', + fitzpatrick_scale: false, + category: "activity" + }, + bow_and_arrow: { + keywords: [ "sports" ], + "char": '\ud83c\udff9', + fitzpatrick_scale: false, + category: "activity" + }, + fishing_pole_and_fish: { + keywords: [ "food", "hobby", "summer" ], + "char": '\ud83c\udfa3', + fitzpatrick_scale: false, + category: "activity" + }, + boxing_glove: { + keywords: [ "sports", "fighting" ], + "char": '\ud83e\udd4a', + fitzpatrick_scale: false, + category: "activity" + }, + martial_arts_uniform: { + keywords: [ "judo", "karate", "taekwondo" ], + "char": '\ud83e\udd4b', + fitzpatrick_scale: false, + category: "activity" + }, + rowing_woman: { + keywords: [ "sports", "hobby", "water", "ship", "woman", "female" ], + "char": '\ud83d\udea3\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + rowing_man: { + keywords: [ "sports", "hobby", "water", "ship" ], + "char": '\ud83d\udea3', + fitzpatrick_scale: true, + category: "activity" + }, + climbing_woman: { + keywords: [ "sports", "hobby", "woman", "female", "rock" ], + "char": '\ud83e\uddd7\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + climbing_man: { + keywords: [ "sports", "hobby", "man", "male", "rock" ], + "char": '\ud83e\uddd7\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + swimming_woman: { + keywords: [ "sports", "exercise", "human", "athlete", "water", "summer", "woman", "female" ], + "char": '\ud83c\udfca\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + swimming_man: { + keywords: [ "sports", "exercise", "human", "athlete", "water", "summer" ], + "char": '\ud83c\udfca', + fitzpatrick_scale: true, + category: "activity" + }, + woman_playing_water_polo: { + keywords: [ "sports", "pool" ], + "char": '\ud83e\udd3d\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + man_playing_water_polo: { + keywords: [ "sports", "pool" ], + "char": '\ud83e\udd3d\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + woman_in_lotus_position: { + keywords: [ "woman", "female", "meditation", "yoga", "serenity", "zen", "mindfulness" ], + "char": '\ud83e\uddd8\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + man_in_lotus_position: { + keywords: [ "man", "male", "meditation", "yoga", "serenity", "zen", "mindfulness" ], + "char": '\ud83e\uddd8\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + surfing_woman: { + keywords: [ "sports", "ocean", "sea", "summer", "beach", "woman", "female" ], + "char": '\ud83c\udfc4\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + surfing_man: { + keywords: [ "sports", "ocean", "sea", "summer", "beach" ], + "char": '\ud83c\udfc4', + fitzpatrick_scale: true, + category: "activity" + }, + bath: { + keywords: [ "clean", "shower", "bathroom" ], + "char": '\ud83d\udec0', + fitzpatrick_scale: true, + category: "activity" + }, + basketball_woman: { + keywords: [ "sports", "human", "woman", "female" ], + "char": '\u26f9\ufe0f\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + basketball_man: { + keywords: [ "sports", "human" ], + "char": '\u26f9', + fitzpatrick_scale: true, + category: "activity" + }, + weight_lifting_woman: { + keywords: [ "sports", "training", "exercise", "woman", "female" ], + "char": '\ud83c\udfcb\ufe0f\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + weight_lifting_man: { + keywords: [ "sports", "training", "exercise" ], + "char": '\ud83c\udfcb', + fitzpatrick_scale: true, + category: "activity" + }, + biking_woman: { + keywords: [ "sports", "bike", "exercise", "hipster", "woman", "female" ], + "char": '\ud83d\udeb4\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + biking_man: { + keywords: [ "sports", "bike", "exercise", "hipster" ], + "char": '\ud83d\udeb4', + fitzpatrick_scale: true, + category: "activity" + }, + mountain_biking_woman: { + keywords: [ "transportation", "sports", "human", "race", "bike", "woman", "female" ], + "char": '\ud83d\udeb5\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + mountain_biking_man: { + keywords: [ "transportation", "sports", "human", "race", "bike" ], + "char": '\ud83d\udeb5', + fitzpatrick_scale: true, + category: "activity" + }, + horse_racing: { + keywords: [ "animal", "betting", "competition", "gambling", "luck" ], + "char": '\ud83c\udfc7', + fitzpatrick_scale: true, + category: "activity" + }, + business_suit_levitating: { + keywords: [ "suit", "business", "levitate", "hover", "jump" ], + "char": '\ud83d\udd74', + fitzpatrick_scale: true, + category: "activity" + }, + trophy: { + keywords: [ "win", "award", "contest", "place", "ftw", "ceremony" ], + "char": '\ud83c\udfc6', + fitzpatrick_scale: false, + category: "activity" + }, + running_shirt_with_sash: { + keywords: [ "play", "pageant" ], + "char": '\ud83c\udfbd', + fitzpatrick_scale: false, + category: "activity" + }, + medal_sports: { + keywords: [ "award", "winning" ], + "char": '\ud83c\udfc5', + fitzpatrick_scale: false, + category: "activity" + }, + medal_military: { + keywords: [ "award", "winning", "army" ], + "char": '\ud83c\udf96', + fitzpatrick_scale: false, + category: "activity" + }, + "1st_place_medal": { + keywords: [ "award", "winning", "first" ], + "char": '\ud83e\udd47', + fitzpatrick_scale: false, + category: "activity" + }, + "2nd_place_medal": { + keywords: [ "award", "second" ], + "char": '\ud83e\udd48', + fitzpatrick_scale: false, + category: "activity" + }, + "3rd_place_medal": { + keywords: [ "award", "third" ], + "char": '\ud83e\udd49', + fitzpatrick_scale: false, + category: "activity" + }, + reminder_ribbon: { + keywords: [ "sports", "cause", "support", "awareness" ], + "char": '\ud83c\udf97', + fitzpatrick_scale: false, + category: "activity" + }, + rosette: { + keywords: [ "flower", "decoration", "military" ], + "char": '\ud83c\udff5', + fitzpatrick_scale: false, + category: "activity" + }, + ticket: { + keywords: [ "event", "concert", "pass" ], + "char": '\ud83c\udfab', + fitzpatrick_scale: false, + category: "activity" + }, + tickets: { + keywords: [ "sports", "concert", "entrance" ], + "char": '\ud83c\udf9f', + fitzpatrick_scale: false, + category: "activity" + }, + performing_arts: { + keywords: [ "acting", "theater", "drama" ], + "char": '\ud83c\udfad', + fitzpatrick_scale: false, + category: "activity" + }, + art: { + keywords: [ "design", "paint", "draw", "colors" ], + "char": '\ud83c\udfa8', + fitzpatrick_scale: false, + category: "activity" + }, + circus_tent: { + keywords: [ "festival", "carnival", "party" ], + "char": '\ud83c\udfaa', + fitzpatrick_scale: false, + category: "activity" + }, + woman_juggling: { + keywords: [ "juggle", "balance", "skill", "multitask" ], + "char": '\ud83e\udd39\u200d\u2640\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + man_juggling: { + keywords: [ "juggle", "balance", "skill", "multitask" ], + "char": '\ud83e\udd39\u200d\u2642\ufe0f', + fitzpatrick_scale: true, + category: "activity" + }, + microphone: { + keywords: [ "sound", "music", "PA", "sing", "talkshow" ], + "char": '\ud83c\udfa4', + fitzpatrick_scale: false, + category: "activity" + }, + headphones: { + keywords: [ "music", "score", "gadgets" ], + "char": '\ud83c\udfa7', + fitzpatrick_scale: false, + category: "activity" + }, + musical_score: { + keywords: [ "treble", "clef", "compose" ], + "char": '\ud83c\udfbc', + fitzpatrick_scale: false, + category: "activity" + }, + musical_keyboard: { + keywords: [ "piano", "instrument", "compose" ], + "char": '\ud83c\udfb9', + fitzpatrick_scale: false, + category: "activity" + }, + drum: { + keywords: [ "music", "instrument", "drumsticks", "snare" ], + "char": '\ud83e\udd41', + fitzpatrick_scale: false, + category: "activity" + }, + saxophone: { + keywords: [ "music", "instrument", "jazz", "blues" ], + "char": '\ud83c\udfb7', + fitzpatrick_scale: false, + category: "activity" + }, + trumpet: { + keywords: [ "music", "brass" ], + "char": '\ud83c\udfba', + fitzpatrick_scale: false, + category: "activity" + }, + guitar: { + keywords: [ "music", "instrument" ], + "char": '\ud83c\udfb8', + fitzpatrick_scale: false, + category: "activity" + }, + violin: { + keywords: [ "music", "instrument", "orchestra", "symphony" ], + "char": '\ud83c\udfbb', + fitzpatrick_scale: false, + category: "activity" + }, + clapper: { + keywords: [ "movie", "film", "record" ], + "char": '\ud83c\udfac', + fitzpatrick_scale: false, + category: "activity" + }, + video_game: { + keywords: [ "play", "console", "PS4", "controller" ], + "char": '\ud83c\udfae', + fitzpatrick_scale: false, + category: "activity" + }, + space_invader: { + keywords: [ "game", "arcade", "play" ], + "char": '\ud83d\udc7e', + fitzpatrick_scale: false, + category: "activity" + }, + dart: { + keywords: [ "game", "play", "bar", "target", "bullseye" ], + "char": '\ud83c\udfaf', + fitzpatrick_scale: false, + category: "activity" + }, + game_die: { + keywords: [ "dice", "random", "tabletop", "play", "luck" ], + "char": '\ud83c\udfb2', + fitzpatrick_scale: false, + category: "activity" + }, + chess_pawn: { + keywords: [ "expendable" ], + "char": "\u265f", + fitzpatrick_scale: false, + category: "activity" + }, + slot_machine: { + keywords: [ "bet", "gamble", "vegas", "fruit machine", "luck", "casino" ], + "char": '\ud83c\udfb0', + fitzpatrick_scale: false, + category: "activity" + }, + jigsaw: { + keywords: [ "interlocking", "puzzle", "piece" ], + "char": '\ud83e\udde9', + fitzpatrick_scale: false, + category: "activity" + }, + bowling: { + keywords: [ "sports", "fun", "play" ], + "char": '\ud83c\udfb3', + fitzpatrick_scale: false, + category: "activity" + }, + red_car: { + keywords: [ "red", "transportation", "vehicle" ], + "char": '\ud83d\ude97', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + taxi: { + keywords: [ "uber", "vehicle", "cars", "transportation" ], + "char": '\ud83d\ude95', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + blue_car: { + keywords: [ "transportation", "vehicle" ], + "char": '\ud83d\ude99', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + bus: { + keywords: [ "car", "vehicle", "transportation" ], + "char": '\ud83d\ude8c', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + trolleybus: { + keywords: [ "bart", "transportation", "vehicle" ], + "char": '\ud83d\ude8e', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + racing_car: { + keywords: [ "sports", "race", "fast", "formula", "f1" ], + "char": '\ud83c\udfce', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + police_car: { + keywords: [ "vehicle", "cars", "transportation", "law", "legal", "enforcement" ], + "char": '\ud83d\ude93', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + ambulance: { + keywords: [ "health", "911", "hospital" ], + "char": '\ud83d\ude91', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + fire_engine: { + keywords: [ "transportation", "cars", "vehicle" ], + "char": '\ud83d\ude92', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + minibus: { + keywords: [ "vehicle", "car", "transportation" ], + "char": '\ud83d\ude90', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + truck: { + keywords: [ "cars", "transportation" ], + "char": '\ud83d\ude9a', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + articulated_lorry: { + keywords: [ "vehicle", "cars", "transportation", "express" ], + "char": '\ud83d\ude9b', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + tractor: { + keywords: [ "vehicle", "car", "farming", "agriculture" ], + "char": '\ud83d\ude9c', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + kick_scooter: { + keywords: [ "vehicle", "kick", "razor" ], + "char": '\ud83d\udef4', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + motorcycle: { + keywords: [ "race", "sports", "fast" ], + "char": '\ud83c\udfcd', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + bike: { + keywords: [ "sports", "bicycle", "exercise", "hipster" ], + "char": '\ud83d\udeb2', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + motor_scooter: { + keywords: [ "vehicle", "vespa", "sasha" ], + "char": '\ud83d\udef5', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + rotating_light: { + keywords: [ "police", "ambulance", "911", "emergency", "alert", "error", "pinged", "law", "legal" ], + "char": '\ud83d\udea8', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + oncoming_police_car: { + keywords: [ "vehicle", "law", "legal", "enforcement", "911" ], + "char": '\ud83d\ude94', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + oncoming_bus: { + keywords: [ "vehicle", "transportation" ], + "char": '\ud83d\ude8d', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + oncoming_automobile: { + keywords: [ "car", "vehicle", "transportation" ], + "char": '\ud83d\ude98', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + oncoming_taxi: { + keywords: [ "vehicle", "cars", "uber" ], + "char": '\ud83d\ude96', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + aerial_tramway: { + keywords: [ "transportation", "vehicle", "ski" ], + "char": '\ud83d\udea1', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + mountain_cableway: { + keywords: [ "transportation", "vehicle", "ski" ], + "char": '\ud83d\udea0', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + suspension_railway: { + keywords: [ "vehicle", "transportation" ], + "char": '\ud83d\ude9f', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + railway_car: { + keywords: [ "transportation", "vehicle" ], + "char": '\ud83d\ude83', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + train: { + keywords: [ "transportation", "vehicle", "carriage", "public", "travel" ], + "char": '\ud83d\ude8b', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + monorail: { + keywords: [ "transportation", "vehicle" ], + "char": '\ud83d\ude9d', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + bullettrain_side: { + keywords: [ "transportation", "vehicle" ], + "char": '\ud83d\ude84', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + bullettrain_front: { + keywords: [ "transportation", "vehicle", "speed", "fast", "public", "travel" ], + "char": '\ud83d\ude85', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + light_rail: { + keywords: [ "transportation", "vehicle" ], + "char": '\ud83d\ude88', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + mountain_railway: { + keywords: [ "transportation", "vehicle" ], + "char": '\ud83d\ude9e', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + steam_locomotive: { + keywords: [ "transportation", "vehicle", "train" ], + "char": '\ud83d\ude82', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + train2: { + keywords: [ "transportation", "vehicle" ], + "char": '\ud83d\ude86', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + metro: { + keywords: [ "transportation", "blue-square", "mrt", "underground", "tube" ], + "char": '\ud83d\ude87', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + tram: { + keywords: [ "transportation", "vehicle" ], + "char": '\ud83d\ude8a', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + station: { + keywords: [ "transportation", "vehicle", "public" ], + "char": '\ud83d\ude89', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + flying_saucer: { + keywords: [ "transportation", "vehicle", "ufo" ], + "char": '\ud83d\udef8', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + helicopter: { + keywords: [ "transportation", "vehicle", "fly" ], + "char": '\ud83d\ude81', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + small_airplane: { + keywords: [ "flight", "transportation", "fly", "vehicle" ], + "char": '\ud83d\udee9', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + airplane: { + keywords: [ "vehicle", "transportation", "flight", "fly" ], + "char": '\u2708\ufe0f', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + flight_departure: { + keywords: [ "airport", "flight", "landing" ], + "char": '\ud83d\udeeb', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + flight_arrival: { + keywords: [ "airport", "flight", "boarding" ], + "char": '\ud83d\udeec', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + sailboat: { + keywords: [ "ship", "summer", "transportation", "water", "sailing" ], + "char": '\u26f5', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + motor_boat: { + keywords: [ "ship" ], + "char": '\ud83d\udee5', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + speedboat: { + keywords: [ "ship", "transportation", "vehicle", "summer" ], + "char": '\ud83d\udea4', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + ferry: { + keywords: [ "boat", "ship", "yacht" ], + "char": '\u26f4', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + passenger_ship: { + keywords: [ "yacht", "cruise", "ferry" ], + "char": '\ud83d\udef3', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + rocket: { + keywords: [ "launch", "ship", "staffmode", "NASA", "outer space", "outer_space", "fly" ], + "char": '\ud83d\ude80', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + artificial_satellite: { + keywords: [ "communication", "gps", "orbit", "spaceflight", "NASA", "ISS" ], + "char": '\ud83d\udef0', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + seat: { + keywords: [ "sit", "airplane", "transport", "bus", "flight", "fly" ], + "char": '\ud83d\udcba', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + canoe: { + keywords: [ "boat", "paddle", "water", "ship" ], + "char": '\ud83d\udef6', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + anchor: { + keywords: [ "ship", "ferry", "sea", "boat" ], + "char": '\u2693', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + construction: { + keywords: [ "wip", "progress", "caution", "warning" ], + "char": '\ud83d\udea7', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + fuelpump: { + keywords: [ "gas station", "petroleum" ], + "char": '\u26fd', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + busstop: { + keywords: [ "transportation", "wait" ], + "char": '\ud83d\ude8f', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + vertical_traffic_light: { + keywords: [ "transportation", "driving" ], + "char": '\ud83d\udea6', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + traffic_light: { + keywords: [ "transportation", "signal" ], + "char": '\ud83d\udea5', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + checkered_flag: { + keywords: [ "contest", "finishline", "race", "gokart" ], + "char": '\ud83c\udfc1', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + ship: { + keywords: [ "transportation", "titanic", "deploy" ], + "char": '\ud83d\udea2', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + ferris_wheel: { + keywords: [ "photo", "carnival", "londoneye" ], + "char": '\ud83c\udfa1', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + roller_coaster: { + keywords: [ "carnival", "playground", "photo", "fun" ], + "char": '\ud83c\udfa2', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + carousel_horse: { + keywords: [ "photo", "carnival" ], + "char": '\ud83c\udfa0', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + building_construction: { + keywords: [ "wip", "working", "progress" ], + "char": '\ud83c\udfd7', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + foggy: { + keywords: [ "photo", "mountain" ], + "char": '\ud83c\udf01', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + tokyo_tower: { + keywords: [ "photo", "japanese" ], + "char": '\ud83d\uddfc', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + factory: { + keywords: [ "building", "industry", "pollution", "smoke" ], + "char": '\ud83c\udfed', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + fountain: { + keywords: [ "photo", "summer", "water", "fresh" ], + "char": '\u26f2', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + rice_scene: { + keywords: [ "photo", "japan", "asia", "tsukimi" ], + "char": '\ud83c\udf91', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + mountain: { + keywords: [ "photo", "nature", "environment" ], + "char": '\u26f0', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + mountain_snow: { + keywords: [ "photo", "nature", "environment", "winter", "cold" ], + "char": '\ud83c\udfd4', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + mount_fuji: { + keywords: [ "photo", "mountain", "nature", "japanese" ], + "char": '\ud83d\uddfb', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + volcano: { + keywords: [ "photo", "nature", "disaster" ], + "char": '\ud83c\udf0b', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + japan: { + keywords: [ "nation", "country", "japanese", "asia" ], + "char": '\ud83d\uddfe', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + camping: { + keywords: [ "photo", "outdoors", "tent" ], + "char": '\ud83c\udfd5', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + tent: { + keywords: [ "photo", "camping", "outdoors" ], + "char": '\u26fa', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + national_park: { + keywords: [ "photo", "environment", "nature" ], + "char": '\ud83c\udfde', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + motorway: { + keywords: [ "road", "cupertino", "interstate", "highway" ], + "char": '\ud83d\udee3', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + railway_track: { + keywords: [ "train", "transportation" ], + "char": '\ud83d\udee4', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + sunrise: { + keywords: [ "morning", "view", "vacation", "photo" ], + "char": '\ud83c\udf05', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + sunrise_over_mountains: { + keywords: [ "view", "vacation", "photo" ], + "char": '\ud83c\udf04', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + desert: { + keywords: [ "photo", "warm", "saharah" ], + "char": '\ud83c\udfdc', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + beach_umbrella: { + keywords: [ "weather", "summer", "sunny", "sand", "mojito" ], + "char": '\ud83c\udfd6', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + desert_island: { + keywords: [ "photo", "tropical", "mojito" ], + "char": '\ud83c\udfdd', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + city_sunrise: { + keywords: [ "photo", "good morning", "dawn" ], + "char": '\ud83c\udf07', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + city_sunset: { + keywords: [ "photo", "evening", "sky", "buildings" ], + "char": '\ud83c\udf06', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + cityscape: { + keywords: [ "photo", "night life", "urban" ], + "char": '\ud83c\udfd9', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + night_with_stars: { + keywords: [ "evening", "city", "downtown" ], + "char": '\ud83c\udf03', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + bridge_at_night: { + keywords: [ "photo", "sanfrancisco" ], + "char": '\ud83c\udf09', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + milky_way: { + keywords: [ "photo", "space", "stars" ], + "char": '\ud83c\udf0c', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + stars: { + keywords: [ "night", "photo" ], + "char": '\ud83c\udf20', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + sparkler: { + keywords: [ "stars", "night", "shine" ], + "char": '\ud83c\udf87', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + fireworks: { + keywords: [ "photo", "festival", "carnival", "congratulations" ], + "char": '\ud83c\udf86', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + rainbow: { + keywords: [ "nature", "happy", "unicorn_face", "photo", "sky", "spring" ], + "char": '\ud83c\udf08', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + houses: { + keywords: [ "buildings", "photo" ], + "char": '\ud83c\udfd8', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + european_castle: { + keywords: [ "building", "royalty", "history" ], + "char": '\ud83c\udff0', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + japanese_castle: { + keywords: [ "photo", "building" ], + "char": '\ud83c\udfef', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + stadium: { + keywords: [ "photo", "place", "sports", "concert", "venue" ], + "char": '\ud83c\udfdf', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + statue_of_liberty: { + keywords: [ "american", "newyork" ], + "char": '\ud83d\uddfd', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + house: { + keywords: [ "building", "home" ], + "char": '\ud83c\udfe0', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + house_with_garden: { + keywords: [ "home", "plant", "nature" ], + "char": '\ud83c\udfe1', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + derelict_house: { + keywords: [ "abandon", "evict", "broken", "building" ], + "char": '\ud83c\udfda', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + office: { + keywords: [ "building", "bureau", "work" ], + "char": '\ud83c\udfe2', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + department_store: { + keywords: [ "building", "shopping", "mall" ], + "char": '\ud83c\udfec', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + post_office: { + keywords: [ "building", "envelope", "communication" ], + "char": '\ud83c\udfe3', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + european_post_office: { + keywords: [ "building", "email" ], + "char": '\ud83c\udfe4', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + hospital: { + keywords: [ "building", "health", "surgery", "doctor" ], + "char": '\ud83c\udfe5', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + bank: { + keywords: [ "building", "money", "sales", "cash", "business", "enterprise" ], + "char": '\ud83c\udfe6', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + hotel: { + keywords: [ "building", "accomodation", "checkin" ], + "char": '\ud83c\udfe8', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + convenience_store: { + keywords: [ "building", "shopping", "groceries" ], + "char": '\ud83c\udfea', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + school: { + keywords: [ "building", "student", "education", "learn", "teach" ], + "char": '\ud83c\udfeb', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + love_hotel: { + keywords: [ "like", "affection", "dating" ], + "char": '\ud83c\udfe9', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + wedding: { + keywords: [ "love", "like", "affection", "couple", "marriage", "bride", "groom" ], + "char": '\ud83d\udc92', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + classical_building: { + keywords: [ "art", "culture", "history" ], + "char": '\ud83c\udfdb', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + church: { + keywords: [ "building", "religion", "christ" ], + "char": '\u26ea', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + mosque: { + keywords: [ "islam", "worship", "minaret" ], + "char": '\ud83d\udd4c', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + synagogue: { + keywords: [ "judaism", "worship", "temple", "jewish" ], + "char": '\ud83d\udd4d', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + kaaba: { + keywords: [ "mecca", "mosque", "islam" ], + "char": '\ud83d\udd4b', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + shinto_shrine: { + keywords: [ "temple", "japan", "kyoto" ], + "char": '\u26e9', + fitzpatrick_scale: false, + category: "travel_and_places" + }, + watch: { + keywords: [ "time", "accessories" ], + "char": '\u231a', + fitzpatrick_scale: false, + category: "objects" + }, + iphone: { + keywords: [ "technology", "apple", "gadgets", "dial" ], + "char": '\ud83d\udcf1', + fitzpatrick_scale: false, + category: "objects" + }, + calling: { + keywords: [ "iphone", "incoming" ], + "char": '\ud83d\udcf2', + fitzpatrick_scale: false, + category: "objects" + }, + computer: { + keywords: [ "technology", "laptop", "screen", "display", "monitor" ], + "char": '\ud83d\udcbb', + fitzpatrick_scale: false, + category: "objects" + }, + keyboard: { + keywords: [ "technology", "computer", "type", "input", "text" ], + "char": '\u2328', + fitzpatrick_scale: false, + category: "objects" + }, + desktop_computer: { + keywords: [ "technology", "computing", "screen" ], + "char": '\ud83d\udda5', + fitzpatrick_scale: false, + category: "objects" + }, + printer: { + keywords: [ "paper", "ink" ], + "char": '\ud83d\udda8', + fitzpatrick_scale: false, + category: "objects" + }, + computer_mouse: { + keywords: [ "click" ], + "char": '\ud83d\uddb1', + fitzpatrick_scale: false, + category: "objects" + }, + trackball: { + keywords: [ "technology", "trackpad" ], + "char": '\ud83d\uddb2', + fitzpatrick_scale: false, + category: "objects" + }, + joystick: { + keywords: [ "game", "play" ], + "char": '\ud83d\udd79', + fitzpatrick_scale: false, + category: "objects" + }, + clamp: { + keywords: [ "tool" ], + "char": '\ud83d\udddc', + fitzpatrick_scale: false, + category: "objects" + }, + minidisc: { + keywords: [ "technology", "record", "data", "disk", "90s" ], + "char": '\ud83d\udcbd', + fitzpatrick_scale: false, + category: "objects" + }, + floppy_disk: { + keywords: [ "oldschool", "technology", "save", "90s", "80s" ], + "char": '\ud83d\udcbe', + fitzpatrick_scale: false, + category: "objects" + }, + cd: { + keywords: [ "technology", "dvd", "disk", "disc", "90s" ], + "char": '\ud83d\udcbf', + fitzpatrick_scale: false, + category: "objects" + }, + dvd: { + keywords: [ "cd", "disk", "disc" ], + "char": '\ud83d\udcc0', + fitzpatrick_scale: false, + category: "objects" + }, + vhs: { + keywords: [ "record", "video", "oldschool", "90s", "80s" ], + "char": '\ud83d\udcfc', + fitzpatrick_scale: false, + category: "objects" + }, + camera: { + keywords: [ "gadgets", "photography" ], + "char": '\ud83d\udcf7', + fitzpatrick_scale: false, + category: "objects" + }, + camera_flash: { + keywords: [ "photography", "gadgets" ], + "char": '\ud83d\udcf8', + fitzpatrick_scale: false, + category: "objects" + }, + video_camera: { + keywords: [ "film", "record" ], + "char": '\ud83d\udcf9', + fitzpatrick_scale: false, + category: "objects" + }, + movie_camera: { + keywords: [ "film", "record" ], + "char": '\ud83c\udfa5', + fitzpatrick_scale: false, + category: "objects" + }, + film_projector: { + keywords: [ "video", "tape", "record", "movie" ], + "char": '\ud83d\udcfd', + fitzpatrick_scale: false, + category: "objects" + }, + film_strip: { + keywords: [ "movie" ], + "char": '\ud83c\udf9e', + fitzpatrick_scale: false, + category: "objects" + }, + telephone_receiver: { + keywords: [ "technology", "communication", "dial" ], + "char": '\ud83d\udcde', + fitzpatrick_scale: false, + category: "objects" + }, + phone: { + keywords: [ "technology", "communication", "dial", "telephone" ], + "char": '\u260e\ufe0f', + fitzpatrick_scale: false, + category: "objects" + }, + pager: { + keywords: [ "bbcall", "oldschool", "90s" ], + "char": '\ud83d\udcdf', + fitzpatrick_scale: false, + category: "objects" + }, + fax: { + keywords: [ "communication", "technology" ], + "char": '\ud83d\udce0', + fitzpatrick_scale: false, + category: "objects" + }, + tv: { + keywords: [ "technology", "program", "oldschool", "show", "television" ], + "char": '\ud83d\udcfa', + fitzpatrick_scale: false, + category: "objects" + }, + radio: { + keywords: [ "communication", "music", "podcast", "program" ], + "char": '\ud83d\udcfb', + fitzpatrick_scale: false, + category: "objects" + }, + studio_microphone: { + keywords: [ "sing", "recording", "artist", "talkshow" ], + "char": '\ud83c\udf99', + fitzpatrick_scale: false, + category: "objects" + }, + level_slider: { + keywords: [ "scale" ], + "char": '\ud83c\udf9a', + fitzpatrick_scale: false, + category: "objects" + }, + control_knobs: { + keywords: [ "dial" ], + "char": '\ud83c\udf9b', + fitzpatrick_scale: false, + category: "objects" + }, + compass: { + keywords: [ "magnetic", "navigation", "orienteering" ], + "char": '\ud83e\udded', + fitzpatrick_scale: false, + category: "objects" + }, + stopwatch: { + keywords: [ "time", "deadline" ], + "char": '\u23f1', + fitzpatrick_scale: false, + category: "objects" + }, + timer_clock: { + keywords: [ "alarm" ], + "char": '\u23f2', + fitzpatrick_scale: false, + category: "objects" + }, + alarm_clock: { + keywords: [ "time", "wake" ], + "char": '\u23f0', + fitzpatrick_scale: false, + category: "objects" + }, + mantelpiece_clock: { + keywords: [ "time" ], + "char": '\ud83d\udd70', + fitzpatrick_scale: false, + category: "objects" + }, + hourglass_flowing_sand: { + keywords: [ "oldschool", "time", "countdown" ], + "char": '\u23f3', + fitzpatrick_scale: false, + category: "objects" + }, + hourglass: { + keywords: [ "time", "clock", "oldschool", "limit", "exam", "quiz", "test" ], + "char": '\u231b', + fitzpatrick_scale: false, + category: "objects" + }, + satellite: { + keywords: [ "communication", "future", "radio", "space" ], + "char": '\ud83d\udce1', + fitzpatrick_scale: false, + category: "objects" + }, + battery: { + keywords: [ "power", "energy", "sustain" ], + "char": '\ud83d\udd0b', + fitzpatrick_scale: false, + category: "objects" + }, + electric_plug: { + keywords: [ "charger", "power" ], + "char": '\ud83d\udd0c', + fitzpatrick_scale: false, + category: "objects" + }, + bulb: { + keywords: [ "light", "electricity", "idea" ], + "char": '\ud83d\udca1', + fitzpatrick_scale: false, + category: "objects" + }, + flashlight: { + keywords: [ "dark", "camping", "sight", "night" ], + "char": '\ud83d\udd26', + fitzpatrick_scale: false, + category: "objects" + }, + candle: { + keywords: [ "fire", "wax" ], + "char": '\ud83d\udd6f', + fitzpatrick_scale: false, + category: "objects" + }, + fire_extinguisher: { + keywords: [ "quench" ], + "char": '\ud83e\uddef', + fitzpatrick_scale: false, + category: "objects" + }, + wastebasket: { + keywords: [ "bin", "trash", "rubbish", "garbage", "toss" ], + "char": '\ud83d\uddd1', + fitzpatrick_scale: false, + category: "objects" + }, + oil_drum: { + keywords: [ "barrell" ], + "char": '\ud83d\udee2', + fitzpatrick_scale: false, + category: "objects" + }, + money_with_wings: { + keywords: [ "dollar", "bills", "payment", "sale" ], + "char": '\ud83d\udcb8', + fitzpatrick_scale: false, + category: "objects" + }, + dollar: { + keywords: [ "money", "sales", "bill", "currency" ], + "char": '\ud83d\udcb5', + fitzpatrick_scale: false, + category: "objects" + }, + yen: { + keywords: [ "money", "sales", "japanese", "dollar", "currency" ], + "char": '\ud83d\udcb4', + fitzpatrick_scale: false, + category: "objects" + }, + euro: { + keywords: [ "money", "sales", "dollar", "currency" ], + "char": '\ud83d\udcb6', + fitzpatrick_scale: false, + category: "objects" + }, + pound: { + keywords: [ "british", "sterling", "money", "sales", "bills", "uk", "england", "currency" ], + "char": '\ud83d\udcb7', + fitzpatrick_scale: false, + category: "objects" + }, + moneybag: { + keywords: [ "dollar", "payment", "coins", "sale" ], + "char": '\ud83d\udcb0', + fitzpatrick_scale: false, + category: "objects" + }, + credit_card: { + keywords: [ "money", "sales", "dollar", "bill", "payment", "shopping" ], + "char": '\ud83d\udcb3', + fitzpatrick_scale: false, + category: "objects" + }, + gem: { + keywords: [ "blue", "ruby", "diamond", "jewelry" ], + "char": '\ud83d\udc8e', + fitzpatrick_scale: false, + category: "objects" + }, + balance_scale: { + keywords: [ "law", "fairness", "weight" ], + "char": '\u2696', + fitzpatrick_scale: false, + category: "objects" + }, + toolbox: { + keywords: [ "tools", "diy", "fix", "maintainer", "mechanic" ], + "char": '\ud83e\uddf0', + fitzpatrick_scale: false, + category: "objects" + }, + wrench: { + keywords: [ "tools", "diy", "ikea", "fix", "maintainer" ], + "char": '\ud83d\udd27', + fitzpatrick_scale: false, + category: "objects" + }, + hammer: { + keywords: [ "tools", "build", "create" ], + "char": '\ud83d\udd28', + fitzpatrick_scale: false, + category: "objects" + }, + hammer_and_pick: { + keywords: [ "tools", "build", "create" ], + "char": '\u2692', + fitzpatrick_scale: false, + category: "objects" + }, + hammer_and_wrench: { + keywords: [ "tools", "build", "create" ], + "char": '\ud83d\udee0', + fitzpatrick_scale: false, + category: "objects" + }, + pick: { + keywords: [ "tools", "dig" ], + "char": '\u26cf', + fitzpatrick_scale: false, + category: "objects" + }, + nut_and_bolt: { + keywords: [ "handy", "tools", "fix" ], + "char": '\ud83d\udd29', + fitzpatrick_scale: false, + category: "objects" + }, + gear: { + keywords: [ "cog" ], + "char": '\u2699', + fitzpatrick_scale: false, + category: "objects" + }, + brick: { + keywords: [ "bricks" ], + "char": '\ud83e\uddf1', + fitzpatrick_scale: false, + category: "objects" + }, + chains: { + keywords: [ "lock", "arrest" ], + "char": '\u26d3', + fitzpatrick_scale: false, + category: "objects" + }, + magnet: { + keywords: [ "attraction", "magnetic" ], + "char": '\ud83e\uddf2', + fitzpatrick_scale: false, + category: "objects" + }, + gun: { + keywords: [ "violence", "weapon", "pistol", "revolver" ], + "char": '\ud83d\udd2b', + fitzpatrick_scale: false, + category: "objects" + }, + bomb: { + keywords: [ "boom", "explode", "explosion", "terrorism" ], + "char": '\ud83d\udca3', + fitzpatrick_scale: false, + category: "objects" + }, + firecracker: { + keywords: [ "dynamite", "boom", "explode", "explosion", "explosive" ], + "char": '\ud83e\udde8', + fitzpatrick_scale: false, + category: "objects" + }, + hocho: { + keywords: [ "knife", "blade", "cutlery", "kitchen", "weapon" ], + "char": '\ud83d\udd2a', + fitzpatrick_scale: false, + category: "objects" + }, + dagger: { + keywords: [ "weapon" ], + "char": '\ud83d\udde1', + fitzpatrick_scale: false, + category: "objects" + }, + crossed_swords: { + keywords: [ "weapon" ], + "char": '\u2694', + fitzpatrick_scale: false, + category: "objects" + }, + shield: { + keywords: [ "protection", "security" ], + "char": '\ud83d\udee1', + fitzpatrick_scale: false, + category: "objects" + }, + smoking: { + keywords: [ "kills", "tobacco", "cigarette", "joint", "smoke" ], + "char": '\ud83d\udeac', + fitzpatrick_scale: false, + category: "objects" + }, + skull_and_crossbones: { + keywords: [ "poison", "danger", "deadly", "scary", "death", "pirate", "evil" ], + "char": '\u2620', + fitzpatrick_scale: false, + category: "objects" + }, + coffin: { + keywords: [ "vampire", "dead", "die", "death", "rip", "graveyard", "cemetery", "casket", "funeral", "box" ], + "char": '\u26b0', + fitzpatrick_scale: false, + category: "objects" + }, + funeral_urn: { + keywords: [ "dead", "die", "death", "rip", "ashes" ], + "char": '\u26b1', + fitzpatrick_scale: false, + category: "objects" + }, + amphora: { + keywords: [ "vase", "jar" ], + "char": '\ud83c\udffa', + fitzpatrick_scale: false, + category: "objects" + }, + crystal_ball: { + keywords: [ "disco", "party", "magic", "circus", "fortune_teller" ], + "char": '\ud83d\udd2e', + fitzpatrick_scale: false, + category: "objects" + }, + prayer_beads: { + keywords: [ "dhikr", "religious" ], + "char": '\ud83d\udcff', + fitzpatrick_scale: false, + category: "objects" + }, + nazar_amulet: { + keywords: [ "bead", "charm" ], + "char": '\ud83e\uddff', + fitzpatrick_scale: false, + category: "objects" + }, + barber: { + keywords: [ "hair", "salon", "style" ], + "char": '\ud83d\udc88', + fitzpatrick_scale: false, + category: "objects" + }, + alembic: { + keywords: [ "distilling", "science", "experiment", "chemistry" ], + "char": '\u2697', + fitzpatrick_scale: false, + category: "objects" + }, + telescope: { + keywords: [ "stars", "space", "zoom", "science", "astronomy" ], + "char": '\ud83d\udd2d', + fitzpatrick_scale: false, + category: "objects" + }, + microscope: { + keywords: [ "laboratory", "experiment", "zoomin", "science", "study" ], + "char": '\ud83d\udd2c', + fitzpatrick_scale: false, + category: "objects" + }, + hole: { + keywords: [ "embarrassing" ], + "char": '\ud83d\udd73', + fitzpatrick_scale: false, + category: "objects" + }, + pill: { + keywords: [ "health", "medicine", "doctor", "pharmacy", "drug" ], + "char": '\ud83d\udc8a', + fitzpatrick_scale: false, + category: "objects" + }, + syringe: { + keywords: [ "health", "hospital", "drugs", "blood", "medicine", "needle", "doctor", "nurse" ], + "char": '\ud83d\udc89', + fitzpatrick_scale: false, + category: "objects" + }, + dna: { + keywords: [ "biologist", "genetics", "life" ], + "char": '\ud83e\uddec', + fitzpatrick_scale: false, + category: "objects" + }, + microbe: { + keywords: [ "amoeba", "bacteria", "germs" ], + "char": '\ud83e\udda0', + fitzpatrick_scale: false, + category: "objects" + }, + petri_dish: { + keywords: [ "bacteria", "biology", "culture", "lab" ], + "char": '\ud83e\uddeb', + fitzpatrick_scale: false, + category: "objects" + }, + test_tube: { + keywords: [ "chemistry", "experiment", "lab", "science" ], + "char": '\ud83e\uddea', + fitzpatrick_scale: false, + category: "objects" + }, + thermometer: { + keywords: [ "weather", "temperature", "hot", "cold" ], + "char": '\ud83c\udf21', + fitzpatrick_scale: false, + category: "objects" + }, + broom: { + keywords: [ "cleaning", "sweeping", "witch" ], + "char": '\ud83e\uddf9', + fitzpatrick_scale: false, + category: "objects" + }, + basket: { + keywords: [ "laundry" ], + "char": '\ud83e\uddfa', + fitzpatrick_scale: false, + category: "objects" + }, + toilet_paper: { + keywords: [ "roll" ], + "char": '\ud83e\uddfb', + fitzpatrick_scale: false, + category: "objects" + }, + label: { + keywords: [ "sale", "tag" ], + "char": '\ud83c\udff7', + fitzpatrick_scale: false, + category: "objects" + }, + bookmark: { + keywords: [ "favorite", "label", "save" ], + "char": '\ud83d\udd16', + fitzpatrick_scale: false, + category: "objects" + }, + toilet: { + keywords: [ "restroom", "wc", "washroom", "bathroom", "potty" ], + "char": '\ud83d\udebd', + fitzpatrick_scale: false, + category: "objects" + }, + shower: { + keywords: [ "clean", "water", "bathroom" ], + "char": '\ud83d\udebf', + fitzpatrick_scale: false, + category: "objects" + }, + bathtub: { + keywords: [ "clean", "shower", "bathroom" ], + "char": '\ud83d\udec1', + fitzpatrick_scale: false, + category: "objects" + }, + soap: { + keywords: [ "bar", "bathing", "cleaning", "lather" ], + "char": '\ud83e\uddfc', + fitzpatrick_scale: false, + category: "objects" + }, + sponge: { + keywords: [ "absorbing", "cleaning", "porous" ], + "char": '\ud83e\uddfd', + fitzpatrick_scale: false, + category: "objects" + }, + lotion_bottle: { + keywords: [ "moisturizer", "sunscreen" ], + "char": '\ud83e\uddf4', + fitzpatrick_scale: false, + category: "objects" + }, + key: { + keywords: [ "lock", "door", "password" ], + "char": '\ud83d\udd11', + fitzpatrick_scale: false, + category: "objects" + }, + old_key: { + keywords: [ "lock", "door", "password" ], + "char": '\ud83d\udddd', + fitzpatrick_scale: false, + category: "objects" + }, + couch_and_lamp: { + keywords: [ "read", "chill" ], + "char": '\ud83d\udecb', + fitzpatrick_scale: false, + category: "objects" + }, + sleeping_bed: { + keywords: [ "bed", "rest" ], + "char": '\ud83d\udecc', + fitzpatrick_scale: true, + category: "objects" + }, + bed: { + keywords: [ "sleep", "rest" ], + "char": '\ud83d\udecf', + fitzpatrick_scale: false, + category: "objects" + }, + door: { + keywords: [ "house", "entry", "exit" ], + "char": '\ud83d\udeaa', + fitzpatrick_scale: false, + category: "objects" + }, + bellhop_bell: { + keywords: [ "service" ], + "char": '\ud83d\udece', + fitzpatrick_scale: false, + category: "objects" + }, + teddy_bear: { + keywords: [ "plush", "stuffed" ], + "char": '\ud83e\uddf8', + fitzpatrick_scale: false, + category: "objects" + }, + framed_picture: { + keywords: [ "photography" ], + "char": '\ud83d\uddbc', + fitzpatrick_scale: false, + category: "objects" + }, + world_map: { + keywords: [ "location", "direction" ], + "char": '\ud83d\uddfa', + fitzpatrick_scale: false, + category: "objects" + }, + parasol_on_ground: { + keywords: [ "weather", "summer" ], + "char": '\u26f1', + fitzpatrick_scale: false, + category: "objects" + }, + moyai: { + keywords: [ "rock", "easter island", "moai" ], + "char": '\ud83d\uddff', + fitzpatrick_scale: false, + category: "objects" + }, + shopping: { + keywords: [ "mall", "buy", "purchase" ], + "char": '\ud83d\udecd', + fitzpatrick_scale: false, + category: "objects" + }, + shopping_cart: { + keywords: [ "trolley" ], + "char": '\ud83d\uded2', + fitzpatrick_scale: false, + category: "objects" + }, + balloon: { + keywords: [ "party", "celebration", "birthday", "circus" ], + "char": '\ud83c\udf88', + fitzpatrick_scale: false, + category: "objects" + }, + flags: { + keywords: [ "fish", "japanese", "koinobori", "carp", "banner" ], + "char": '\ud83c\udf8f', + fitzpatrick_scale: false, + category: "objects" + }, + ribbon: { + keywords: [ "decoration", "pink", "girl", "bowtie" ], + "char": '\ud83c\udf80', + fitzpatrick_scale: false, + category: "objects" + }, + gift: { + keywords: [ "present", "birthday", "christmas", "xmas" ], + "char": '\ud83c\udf81', + fitzpatrick_scale: false, + category: "objects" + }, + confetti_ball: { + keywords: [ "festival", "party", "birthday", "circus" ], + "char": '\ud83c\udf8a', + fitzpatrick_scale: false, + category: "objects" + }, + tada: { + keywords: [ "party", "congratulations", "birthday", "magic", "circus", "celebration" ], + "char": '\ud83c\udf89', + fitzpatrick_scale: false, + category: "objects" + }, + dolls: { + keywords: [ "japanese", "toy", "kimono" ], + "char": '\ud83c\udf8e', + fitzpatrick_scale: false, + category: "objects" + }, + wind_chime: { + keywords: [ "nature", "ding", "spring", "bell" ], + "char": '\ud83c\udf90', + fitzpatrick_scale: false, + category: "objects" + }, + crossed_flags: { + keywords: [ "japanese", "nation", "country", "border" ], + "char": '\ud83c\udf8c', + fitzpatrick_scale: false, + category: "objects" + }, + izakaya_lantern: { + keywords: [ "light", "paper", "halloween", "spooky" ], + "char": '\ud83c\udfee', + fitzpatrick_scale: false, + category: "objects" + }, + red_envelope: { + keywords: [ "gift" ], + "char": '\ud83e\udde7', + fitzpatrick_scale: false, + category: "objects" + }, + email: { + keywords: [ "letter", "postal", "inbox", "communication" ], + "char": '\u2709\ufe0f', + fitzpatrick_scale: false, + category: "objects" + }, + envelope_with_arrow: { + keywords: [ "email", "communication" ], + "char": '\ud83d\udce9', + fitzpatrick_scale: false, + category: "objects" + }, + incoming_envelope: { + keywords: [ "email", "inbox" ], + "char": '\ud83d\udce8', + fitzpatrick_scale: false, + category: "objects" + }, + "e-mail": { + keywords: [ "communication", "inbox" ], + "char": '\ud83d\udce7', + fitzpatrick_scale: false, + category: "objects" + }, + love_letter: { + keywords: [ "email", "like", "affection", "envelope", "valentines" ], + "char": '\ud83d\udc8c', + fitzpatrick_scale: false, + category: "objects" + }, + postbox: { + keywords: [ "email", "letter", "envelope" ], + "char": '\ud83d\udcee', + fitzpatrick_scale: false, + category: "objects" + }, + mailbox_closed: { + keywords: [ "email", "communication", "inbox" ], + "char": '\ud83d\udcea', + fitzpatrick_scale: false, + category: "objects" + }, + mailbox: { + keywords: [ "email", "inbox", "communication" ], + "char": '\ud83d\udceb', + fitzpatrick_scale: false, + category: "objects" + }, + mailbox_with_mail: { + keywords: [ "email", "inbox", "communication" ], + "char": '\ud83d\udcec', + fitzpatrick_scale: false, + category: "objects" + }, + mailbox_with_no_mail: { + keywords: [ "email", "inbox" ], + "char": '\ud83d\udced', + fitzpatrick_scale: false, + category: "objects" + }, + "package": { + keywords: [ "mail", "gift", "cardboard", "box", "moving" ], + "char": '\ud83d\udce6', + fitzpatrick_scale: false, + category: "objects" + }, + postal_horn: { + keywords: [ "instrument", "music" ], + "char": '\ud83d\udcef', + fitzpatrick_scale: false, + category: "objects" + }, + inbox_tray: { + keywords: [ "email", "documents" ], + "char": '\ud83d\udce5', + fitzpatrick_scale: false, + category: "objects" + }, + outbox_tray: { + keywords: [ "inbox", "email" ], + "char": '\ud83d\udce4', + fitzpatrick_scale: false, + category: "objects" + }, + scroll: { + keywords: [ "documents", "ancient", "history", "paper" ], + "char": '\ud83d\udcdc', + fitzpatrick_scale: false, + category: "objects" + }, + page_with_curl: { + keywords: [ "documents", "office", "paper" ], + "char": '\ud83d\udcc3', + fitzpatrick_scale: false, + category: "objects" + }, + bookmark_tabs: { + keywords: [ "favorite", "save", "order", "tidy" ], + "char": '\ud83d\udcd1', + fitzpatrick_scale: false, + category: "objects" + }, + receipt: { + keywords: [ "accounting", "expenses" ], + "char": '\ud83e\uddfe', + fitzpatrick_scale: false, + category: "objects" + }, + bar_chart: { + keywords: [ "graph", "presentation", "stats" ], + "char": '\ud83d\udcca', + fitzpatrick_scale: false, + category: "objects" + }, + chart_with_upwards_trend: { + keywords: [ "graph", "presentation", "stats", "recovery", "business", "economics", "money", "sales", "good", "success" ], + "char": '\ud83d\udcc8', + fitzpatrick_scale: false, + category: "objects" + }, + chart_with_downwards_trend: { + keywords: [ "graph", "presentation", "stats", "recession", "business", "economics", "money", "sales", "bad", "failure" ], + "char": '\ud83d\udcc9', + fitzpatrick_scale: false, + category: "objects" + }, + page_facing_up: { + keywords: [ "documents", "office", "paper", "information" ], + "char": '\ud83d\udcc4', + fitzpatrick_scale: false, + category: "objects" + }, + date: { + keywords: [ "calendar", "schedule" ], + "char": '\ud83d\udcc5', + fitzpatrick_scale: false, + category: "objects" + }, + calendar: { + keywords: [ "schedule", "date", "planning" ], + "char": '\ud83d\udcc6', + fitzpatrick_scale: false, + category: "objects" + }, + spiral_calendar: { + keywords: [ "date", "schedule", "planning" ], + "char": '\ud83d\uddd3', + fitzpatrick_scale: false, + category: "objects" + }, + card_index: { + keywords: [ "business", "stationery" ], + "char": '\ud83d\udcc7', + fitzpatrick_scale: false, + category: "objects" + }, + card_file_box: { + keywords: [ "business", "stationery" ], + "char": '\ud83d\uddc3', + fitzpatrick_scale: false, + category: "objects" + }, + ballot_box: { + keywords: [ "election", "vote" ], + "char": '\ud83d\uddf3', + fitzpatrick_scale: false, + category: "objects" + }, + file_cabinet: { + keywords: [ "filing", "organizing" ], + "char": '\ud83d\uddc4', + fitzpatrick_scale: false, + category: "objects" + }, + clipboard: { + keywords: [ "stationery", "documents" ], + "char": '\ud83d\udccb', + fitzpatrick_scale: false, + category: "objects" + }, + spiral_notepad: { + keywords: [ "memo", "stationery" ], + "char": '\ud83d\uddd2', + fitzpatrick_scale: false, + category: "objects" + }, + file_folder: { + keywords: [ "documents", "business", "office" ], + "char": '\ud83d\udcc1', + fitzpatrick_scale: false, + category: "objects" + }, + open_file_folder: { + keywords: [ "documents", "load" ], + "char": '\ud83d\udcc2', + fitzpatrick_scale: false, + category: "objects" + }, + card_index_dividers: { + keywords: [ "organizing", "business", "stationery" ], + "char": '\ud83d\uddc2', + fitzpatrick_scale: false, + category: "objects" + }, + newspaper_roll: { + keywords: [ "press", "headline" ], + "char": '\ud83d\uddde', + fitzpatrick_scale: false, + category: "objects" + }, + newspaper: { + keywords: [ "press", "headline" ], + "char": '\ud83d\udcf0', + fitzpatrick_scale: false, + category: "objects" + }, + notebook: { + keywords: [ "stationery", "record", "notes", "paper", "study" ], + "char": '\ud83d\udcd3', + fitzpatrick_scale: false, + category: "objects" + }, + closed_book: { + keywords: [ "read", "library", "knowledge", "textbook", "learn" ], + "char": '\ud83d\udcd5', + fitzpatrick_scale: false, + category: "objects" + }, + green_book: { + keywords: [ "read", "library", "knowledge", "study" ], + "char": '\ud83d\udcd7', + fitzpatrick_scale: false, + category: "objects" + }, + blue_book: { + keywords: [ "read", "library", "knowledge", "learn", "study" ], + "char": '\ud83d\udcd8', + fitzpatrick_scale: false, + category: "objects" + }, + orange_book: { + keywords: [ "read", "library", "knowledge", "textbook", "study" ], + "char": '\ud83d\udcd9', + fitzpatrick_scale: false, + category: "objects" + }, + notebook_with_decorative_cover: { + keywords: [ "classroom", "notes", "record", "paper", "study" ], + "char": '\ud83d\udcd4', + fitzpatrick_scale: false, + category: "objects" + }, + ledger: { + keywords: [ "notes", "paper" ], + "char": '\ud83d\udcd2', + fitzpatrick_scale: false, + category: "objects" + }, + books: { + keywords: [ "literature", "library", "study" ], + "char": '\ud83d\udcda', + fitzpatrick_scale: false, + category: "objects" + }, + open_book: { + keywords: [ "book", "read", "library", "knowledge", "literature", "learn", "study" ], + "char": '\ud83d\udcd6', + fitzpatrick_scale: false, + category: "objects" + }, + safety_pin: { + keywords: [ "diaper" ], + "char": '\ud83e\uddf7', + fitzpatrick_scale: false, + category: "objects" + }, + link: { + keywords: [ "rings", "url" ], + "char": '\ud83d\udd17', + fitzpatrick_scale: false, + category: "objects" + }, + paperclip: { + keywords: [ "documents", "stationery" ], + "char": '\ud83d\udcce', + fitzpatrick_scale: false, + category: "objects" + }, + paperclips: { + keywords: [ "documents", "stationery" ], + "char": '\ud83d\udd87', + fitzpatrick_scale: false, + category: "objects" + }, + scissors: { + keywords: [ "stationery", "cut" ], + "char": '\u2702\ufe0f', + fitzpatrick_scale: false, + category: "objects" + }, + triangular_ruler: { + keywords: [ "stationery", "math", "architect", "sketch" ], + "char": '\ud83d\udcd0', + fitzpatrick_scale: false, + category: "objects" + }, + straight_ruler: { + keywords: [ "stationery", "calculate", "length", "math", "school", "drawing", "architect", "sketch" ], + "char": '\ud83d\udccf', + fitzpatrick_scale: false, + category: "objects" + }, + abacus: { + keywords: [ "calculation" ], + "char": '\ud83e\uddee', + fitzpatrick_scale: false, + category: "objects" + }, + pushpin: { + keywords: [ "stationery", "mark", "here" ], + "char": '\ud83d\udccc', + fitzpatrick_scale: false, + category: "objects" + }, + round_pushpin: { + keywords: [ "stationery", "location", "map", "here" ], + "char": '\ud83d\udccd', + fitzpatrick_scale: false, + category: "objects" + }, + triangular_flag_on_post: { + keywords: [ "mark", "milestone", "place" ], + "char": '\ud83d\udea9', + fitzpatrick_scale: false, + category: "objects" + }, + white_flag: { + keywords: [ "losing", "loser", "lost", "surrender", "give up", "fail" ], + "char": '\ud83c\udff3', + fitzpatrick_scale: false, + category: "objects" + }, + black_flag: { + keywords: [ "pirate" ], + "char": '\ud83c\udff4', + fitzpatrick_scale: false, + category: "objects" + }, + rainbow_flag: { + keywords: [ "flag", "rainbow", "pride", "gay", "lgbt", "glbt", "queer", "homosexual", "lesbian", "bisexual", "transgender" ], + "char": '\ud83c\udff3\ufe0f\u200d\ud83c\udf08', + fitzpatrick_scale: false, + category: "objects" + }, + closed_lock_with_key: { + keywords: [ "security", "privacy" ], + "char": '\ud83d\udd10', + fitzpatrick_scale: false, + category: "objects" + }, + lock: { + keywords: [ "security", "password", "padlock" ], + "char": '\ud83d\udd12', + fitzpatrick_scale: false, + category: "objects" + }, + unlock: { + keywords: [ "privacy", "security" ], + "char": '\ud83d\udd13', + fitzpatrick_scale: false, + category: "objects" + }, + lock_with_ink_pen: { + keywords: [ "security", "secret" ], + "char": '\ud83d\udd0f', + fitzpatrick_scale: false, + category: "objects" + }, + pen: { + keywords: [ "stationery", "writing", "write" ], + "char": '\ud83d\udd8a', + fitzpatrick_scale: false, + category: "objects" + }, + fountain_pen: { + keywords: [ "stationery", "writing", "write" ], + "char": '\ud83d\udd8b', + fitzpatrick_scale: false, + category: "objects" + }, + black_nib: { + keywords: [ "pen", "stationery", "writing", "write" ], + "char": '\u2712\ufe0f', + fitzpatrick_scale: false, + category: "objects" + }, + memo: { + keywords: [ "write", "documents", "stationery", "pencil", "paper", "writing", "legal", "exam", "quiz", "test", "study", "compose" ], + "char": '\ud83d\udcdd', + fitzpatrick_scale: false, + category: "objects" + }, + pencil2: { + keywords: [ "stationery", "write", "paper", "writing", "school", "study" ], + "char": '\u270f\ufe0f', + fitzpatrick_scale: false, + category: "objects" + }, + crayon: { + keywords: [ "drawing", "creativity" ], + "char": '\ud83d\udd8d', + fitzpatrick_scale: false, + category: "objects" + }, + paintbrush: { + keywords: [ "drawing", "creativity", "art" ], + "char": '\ud83d\udd8c', + fitzpatrick_scale: false, + category: "objects" + }, + mag: { + keywords: [ "search", "zoom", "find", "detective" ], + "char": '\ud83d\udd0d', + fitzpatrick_scale: false, + category: "objects" + }, + mag_right: { + keywords: [ "search", "zoom", "find", "detective" ], + "char": '\ud83d\udd0e', + fitzpatrick_scale: false, + category: "objects" + }, + heart: { + keywords: [ "love", "like", "valentines" ], + "char": '\u2764\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + orange_heart: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": '\ud83e\udde1', + fitzpatrick_scale: false, + category: "symbols" + }, + yellow_heart: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": '\ud83d\udc9b', + fitzpatrick_scale: false, + category: "symbols" + }, + green_heart: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": '\ud83d\udc9a', + fitzpatrick_scale: false, + category: "symbols" + }, + blue_heart: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": '\ud83d\udc99', + fitzpatrick_scale: false, + category: "symbols" + }, + purple_heart: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": '\ud83d\udc9c', + fitzpatrick_scale: false, + category: "symbols" + }, + black_heart: { + keywords: [ "evil" ], + "char": '\ud83d\udda4', + fitzpatrick_scale: false, + category: "symbols" + }, + broken_heart: { + keywords: [ "sad", "sorry", "break", "heart", "heartbreak" ], + "char": '\ud83d\udc94', + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_heart_exclamation: { + keywords: [ "decoration", "love" ], + "char": '\u2763', + fitzpatrick_scale: false, + category: "symbols" + }, + two_hearts: { + keywords: [ "love", "like", "affection", "valentines", "heart" ], + "char": '\ud83d\udc95', + fitzpatrick_scale: false, + category: "symbols" + }, + revolving_hearts: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": '\ud83d\udc9e', + fitzpatrick_scale: false, + category: "symbols" + }, + heartbeat: { + keywords: [ "love", "like", "affection", "valentines", "pink", "heart" ], + "char": '\ud83d\udc93', + fitzpatrick_scale: false, + category: "symbols" + }, + heartpulse: { + keywords: [ "like", "love", "affection", "valentines", "pink" ], + "char": '\ud83d\udc97', + fitzpatrick_scale: false, + category: "symbols" + }, + sparkling_heart: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": '\ud83d\udc96', + fitzpatrick_scale: false, + category: "symbols" + }, + cupid: { + keywords: [ "love", "like", "heart", "affection", "valentines" ], + "char": '\ud83d\udc98', + fitzpatrick_scale: false, + category: "symbols" + }, + gift_heart: { + keywords: [ "love", "valentines" ], + "char": '\ud83d\udc9d', + fitzpatrick_scale: false, + category: "symbols" + }, + heart_decoration: { + keywords: [ "purple-square", "love", "like" ], + "char": '\ud83d\udc9f', + fitzpatrick_scale: false, + category: "symbols" + }, + peace_symbol: { + keywords: [ "hippie" ], + "char": '\u262e', + fitzpatrick_scale: false, + category: "symbols" + }, + latin_cross: { + keywords: [ "christianity" ], + "char": '\u271d', + fitzpatrick_scale: false, + category: "symbols" + }, + star_and_crescent: { + keywords: [ "islam" ], + "char": '\u262a', + fitzpatrick_scale: false, + category: "symbols" + }, + om: { + keywords: [ "hinduism", "buddhism", "sikhism", "jainism" ], + "char": '\ud83d\udd49', + fitzpatrick_scale: false, + category: "symbols" + }, + wheel_of_dharma: { + keywords: [ "hinduism", "buddhism", "sikhism", "jainism" ], + "char": '\u2638', + fitzpatrick_scale: false, + category: "symbols" + }, + star_of_david: { + keywords: [ "judaism" ], + "char": '\u2721', + fitzpatrick_scale: false, + category: "symbols" + }, + six_pointed_star: { + keywords: [ "purple-square", "religion", "jewish", "hexagram" ], + "char": '\ud83d\udd2f', + fitzpatrick_scale: false, + category: "symbols" + }, + menorah: { + keywords: [ "hanukkah", "candles", "jewish" ], + "char": '\ud83d\udd4e', + fitzpatrick_scale: false, + category: "symbols" + }, + yin_yang: { + keywords: [ "balance" ], + "char": '\u262f', + fitzpatrick_scale: false, + category: "symbols" + }, + orthodox_cross: { + keywords: [ "suppedaneum", "religion" ], + "char": '\u2626', + fitzpatrick_scale: false, + category: "symbols" + }, + place_of_worship: { + keywords: [ "religion", "church", "temple", "prayer" ], + "char": '\ud83d\uded0', + fitzpatrick_scale: false, + category: "symbols" + }, + ophiuchus: { + keywords: [ "sign", "purple-square", "constellation", "astrology" ], + "char": '\u26ce', + fitzpatrick_scale: false, + category: "symbols" + }, + aries: { + keywords: [ "sign", "purple-square", "zodiac", "astrology" ], + "char": '\u2648', + fitzpatrick_scale: false, + category: "symbols" + }, + taurus: { + keywords: [ "purple-square", "sign", "zodiac", "astrology" ], + "char": '\u2649', + fitzpatrick_scale: false, + category: "symbols" + }, + gemini: { + keywords: [ "sign", "zodiac", "purple-square", "astrology" ], + "char": '\u264a', + fitzpatrick_scale: false, + category: "symbols" + }, + cancer: { + keywords: [ "sign", "zodiac", "purple-square", "astrology" ], + "char": '\u264b', + fitzpatrick_scale: false, + category: "symbols" + }, + leo: { + keywords: [ "sign", "purple-square", "zodiac", "astrology" ], + "char": '\u264c', + fitzpatrick_scale: false, + category: "symbols" + }, + virgo: { + keywords: [ "sign", "zodiac", "purple-square", "astrology" ], + "char": '\u264d', + fitzpatrick_scale: false, + category: "symbols" + }, + libra: { + keywords: [ "sign", "purple-square", "zodiac", "astrology" ], + "char": '\u264e', + fitzpatrick_scale: false, + category: "symbols" + }, + scorpius: { + keywords: [ "sign", "zodiac", "purple-square", "astrology", "scorpio" ], + "char": '\u264f', + fitzpatrick_scale: false, + category: "symbols" + }, + sagittarius: { + keywords: [ "sign", "zodiac", "purple-square", "astrology" ], + "char": '\u2650', + fitzpatrick_scale: false, + category: "symbols" + }, + capricorn: { + keywords: [ "sign", "zodiac", "purple-square", "astrology" ], + "char": '\u2651', + fitzpatrick_scale: false, + category: "symbols" + }, + aquarius: { + keywords: [ "sign", "purple-square", "zodiac", "astrology" ], + "char": '\u2652', + fitzpatrick_scale: false, + category: "symbols" + }, + pisces: { + keywords: [ "purple-square", "sign", "zodiac", "astrology" ], + "char": '\u2653', + fitzpatrick_scale: false, + category: "symbols" + }, + id: { + keywords: [ "purple-square", "words" ], + "char": '\ud83c\udd94', + fitzpatrick_scale: false, + category: "symbols" + }, + atom_symbol: { + keywords: [ "science", "physics", "chemistry" ], + "char": '\u269b', + fitzpatrick_scale: false, + category: "symbols" + }, + u7a7a: { + keywords: [ "kanji", "japanese", "chinese", "empty", "sky", "blue-square" ], + "char": '\ud83c\ude33', + fitzpatrick_scale: false, + category: "symbols" + }, + u5272: { + keywords: [ "cut", "divide", "chinese", "kanji", "pink-square" ], + "char": '\ud83c\ude39', + fitzpatrick_scale: false, + category: "symbols" + }, + radioactive: { + keywords: [ "nuclear", "danger" ], + "char": '\u2622', + fitzpatrick_scale: false, + category: "symbols" + }, + biohazard: { + keywords: [ "danger" ], + "char": '\u2623', + fitzpatrick_scale: false, + category: "symbols" + }, + mobile_phone_off: { + keywords: [ "mute", "orange-square", "silence", "quiet" ], + "char": '\ud83d\udcf4', + fitzpatrick_scale: false, + category: "symbols" + }, + vibration_mode: { + keywords: [ "orange-square", "phone" ], + "char": '\ud83d\udcf3', + fitzpatrick_scale: false, + category: "symbols" + }, + u6709: { + keywords: [ "orange-square", "chinese", "have", "kanji" ], + "char": '\ud83c\ude36', + fitzpatrick_scale: false, + category: "symbols" + }, + u7121: { + keywords: [ "nothing", "chinese", "kanji", "japanese", "orange-square" ], + "char": '\ud83c\ude1a', + fitzpatrick_scale: false, + category: "symbols" + }, + u7533: { + keywords: [ "chinese", "japanese", "kanji", "orange-square" ], + "char": '\ud83c\ude38', + fitzpatrick_scale: false, + category: "symbols" + }, + u55b6: { + keywords: [ "japanese", "opening hours", "orange-square" ], + "char": '\ud83c\ude3a', + fitzpatrick_scale: false, + category: "symbols" + }, + u6708: { + keywords: [ "chinese", "month", "moon", "japanese", "orange-square", "kanji" ], + "char": '\ud83c\ude37\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + eight_pointed_black_star: { + keywords: [ "orange-square", "shape", "polygon" ], + "char": '\u2734\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + vs: { + keywords: [ "words", "orange-square" ], + "char": '\ud83c\udd9a', + fitzpatrick_scale: false, + category: "symbols" + }, + accept: { + keywords: [ "ok", "good", "chinese", "kanji", "agree", "yes", "orange-circle" ], + "char": '\ud83c\ude51', + fitzpatrick_scale: false, + category: "symbols" + }, + white_flower: { + keywords: [ "japanese", "spring" ], + "char": '\ud83d\udcae', + fitzpatrick_scale: false, + category: "symbols" + }, + ideograph_advantage: { + keywords: [ "chinese", "kanji", "obtain", "get", "circle" ], + "char": '\ud83c\ude50', + fitzpatrick_scale: false, + category: "symbols" + }, + secret: { + keywords: [ "privacy", "chinese", "sshh", "kanji", "red-circle" ], + "char": '\u3299\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + congratulations: { + keywords: [ "chinese", "kanji", "japanese", "red-circle" ], + "char": '\u3297\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + u5408: { + keywords: [ "japanese", "chinese", "join", "kanji", "red-square" ], + "char": '\ud83c\ude34', + fitzpatrick_scale: false, + category: "symbols" + }, + u6e80: { + keywords: [ "full", "chinese", "japanese", "red-square", "kanji" ], + "char": '\ud83c\ude35', + fitzpatrick_scale: false, + category: "symbols" + }, + u7981: { + keywords: [ "kanji", "japanese", "chinese", "forbidden", "limit", "restricted", "red-square" ], + "char": '\ud83c\ude32', + fitzpatrick_scale: false, + category: "symbols" + }, + a: { + keywords: [ "red-square", "alphabet", "letter" ], + "char": '\ud83c\udd70\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + b: { + keywords: [ "red-square", "alphabet", "letter" ], + "char": '\ud83c\udd71\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + ab: { + keywords: [ "red-square", "alphabet" ], + "char": '\ud83c\udd8e', + fitzpatrick_scale: false, + category: "symbols" + }, + cl: { + keywords: [ "alphabet", "words", "red-square" ], + "char": '\ud83c\udd91', + fitzpatrick_scale: false, + category: "symbols" + }, + o2: { + keywords: [ "alphabet", "red-square", "letter" ], + "char": '\ud83c\udd7e\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + sos: { + keywords: [ "help", "red-square", "words", "emergency", "911" ], + "char": '\ud83c\udd98', + fitzpatrick_scale: false, + category: "symbols" + }, + no_entry: { + keywords: [ "limit", "security", "privacy", "bad", "denied", "stop", "circle" ], + "char": '\u26d4', + fitzpatrick_scale: false, + category: "symbols" + }, + name_badge: { + keywords: [ "fire", "forbid" ], + "char": '\ud83d\udcdb', + fitzpatrick_scale: false, + category: "symbols" + }, + no_entry_sign: { + keywords: [ "forbid", "stop", "limit", "denied", "disallow", "circle" ], + "char": '\ud83d\udeab', + fitzpatrick_scale: false, + category: "symbols" + }, + x: { + keywords: [ "no", "delete", "remove", "cancel", "red" ], + "char": '\u274c', + fitzpatrick_scale: false, + category: "symbols" + }, + o: { + keywords: [ "circle", "round" ], + "char": '\u2b55', + fitzpatrick_scale: false, + category: "symbols" + }, + stop_sign: { + keywords: [ "stop" ], + "char": '\ud83d\uded1', + fitzpatrick_scale: false, + category: "symbols" + }, + anger: { + keywords: [ "angry", "mad" ], + "char": '\ud83d\udca2', + fitzpatrick_scale: false, + category: "symbols" + }, + hotsprings: { + keywords: [ "bath", "warm", "relax" ], + "char": '\u2668\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + no_pedestrians: { + keywords: [ "rules", "crossing", "walking", "circle" ], + "char": '\ud83d\udeb7', + fitzpatrick_scale: false, + category: "symbols" + }, + do_not_litter: { + keywords: [ "trash", "bin", "garbage", "circle" ], + "char": '\ud83d\udeaf', + fitzpatrick_scale: false, + category: "symbols" + }, + no_bicycles: { + keywords: [ "cyclist", "prohibited", "circle" ], + "char": '\ud83d\udeb3', + fitzpatrick_scale: false, + category: "symbols" + }, + "non-potable_water": { + keywords: [ "drink", "faucet", "tap", "circle" ], + "char": '\ud83d\udeb1', + fitzpatrick_scale: false, + category: "symbols" + }, + underage: { + keywords: [ "18", "drink", "pub", "night", "minor", "circle" ], + "char": '\ud83d\udd1e', + fitzpatrick_scale: false, + category: "symbols" + }, + no_mobile_phones: { + keywords: [ "iphone", "mute", "circle" ], + "char": '\ud83d\udcf5', + fitzpatrick_scale: false, + category: "symbols" + }, + exclamation: { + keywords: [ "heavy_exclamation_mark", "danger", "surprise", "punctuation", "wow", "warning" ], + "char": '\u2757', + fitzpatrick_scale: false, + category: "symbols" + }, + grey_exclamation: { + keywords: [ "surprise", "punctuation", "gray", "wow", "warning" ], + "char": '\u2755', + fitzpatrick_scale: false, + category: "symbols" + }, + question: { + keywords: [ "doubt", "confused" ], + "char": '\u2753', + fitzpatrick_scale: false, + category: "symbols" + }, + grey_question: { + keywords: [ "doubts", "gray", "huh", "confused" ], + "char": '\u2754', + fitzpatrick_scale: false, + category: "symbols" + }, + bangbang: { + keywords: [ "exclamation", "surprise" ], + "char": '\u203c\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + interrobang: { + keywords: [ "wat", "punctuation", "surprise" ], + "char": '\u2049\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + low_brightness: { + keywords: [ "sun", "afternoon", "warm", "summer" ], + "char": '\ud83d\udd05', + fitzpatrick_scale: false, + category: "symbols" + }, + high_brightness: { + keywords: [ "sun", "light" ], + "char": '\ud83d\udd06', + fitzpatrick_scale: false, + category: "symbols" + }, + trident: { + keywords: [ "weapon", "spear" ], + "char": '\ud83d\udd31', + fitzpatrick_scale: false, + category: "symbols" + }, + fleur_de_lis: { + keywords: [ "decorative", "scout" ], + "char": '\u269c', + fitzpatrick_scale: false, + category: "symbols" + }, + part_alternation_mark: { + keywords: [ "graph", "presentation", "stats", "business", "economics", "bad" ], + "char": '\u303d\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + warning: { + keywords: [ "exclamation", "wip", "alert", "error", "problem", "issue" ], + "char": '\u26a0\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + children_crossing: { + keywords: [ "school", "warning", "danger", "sign", "driving", "yellow-diamond" ], + "char": '\ud83d\udeb8', + fitzpatrick_scale: false, + category: "symbols" + }, + beginner: { + keywords: [ "badge", "shield" ], + "char": '\ud83d\udd30', + fitzpatrick_scale: false, + category: "symbols" + }, + recycle: { + keywords: [ "arrow", "environment", "garbage", "trash" ], + "char": '\u267b\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + u6307: { + keywords: [ "chinese", "point", "green-square", "kanji" ], + "char": '\ud83c\ude2f', + fitzpatrick_scale: false, + category: "symbols" + }, + chart: { + keywords: [ "green-square", "graph", "presentation", "stats" ], + "char": '\ud83d\udcb9', + fitzpatrick_scale: false, + category: "symbols" + }, + sparkle: { + keywords: [ "stars", "green-square", "awesome", "good", "fireworks" ], + "char": '\u2747\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + eight_spoked_asterisk: { + keywords: [ "star", "sparkle", "green-square" ], + "char": '\u2733\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + negative_squared_cross_mark: { + keywords: [ "x", "green-square", "no", "deny" ], + "char": '\u274e', + fitzpatrick_scale: false, + category: "symbols" + }, + white_check_mark: { + keywords: [ "green-square", "ok", "agree", "vote", "election", "answer", "tick" ], + "char": '\u2705', + fitzpatrick_scale: false, + category: "symbols" + }, + diamond_shape_with_a_dot_inside: { + keywords: [ "jewel", "blue", "gem", "crystal", "fancy" ], + "char": '\ud83d\udca0', + fitzpatrick_scale: false, + category: "symbols" + }, + cyclone: { + keywords: [ "weather", "swirl", "blue", "cloud", "vortex", "spiral", "whirlpool", "spin", "tornado", "hurricane", "typhoon" ], + "char": '\ud83c\udf00', + fitzpatrick_scale: false, + category: "symbols" + }, + loop: { + keywords: [ "tape", "cassette" ], + "char": '\u27bf', + fitzpatrick_scale: false, + category: "symbols" + }, + globe_with_meridians: { + keywords: [ "earth", "international", "world", "internet", "interweb", "i18n" ], + "char": '\ud83c\udf10', + fitzpatrick_scale: false, + category: "symbols" + }, + m: { + keywords: [ "alphabet", "blue-circle", "letter" ], + "char": '\u24c2\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + atm: { + keywords: [ "money", "sales", "cash", "blue-square", "payment", "bank" ], + "char": '\ud83c\udfe7', + fitzpatrick_scale: false, + category: "symbols" + }, + sa: { + keywords: [ "japanese", "blue-square", "katakana" ], + "char": '\ud83c\ude02\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + passport_control: { + keywords: [ "custom", "blue-square" ], + "char": '\ud83d\udec2', + fitzpatrick_scale: false, + category: "symbols" + }, + customs: { + keywords: [ "passport", "border", "blue-square" ], + "char": '\ud83d\udec3', + fitzpatrick_scale: false, + category: "symbols" + }, + baggage_claim: { + keywords: [ "blue-square", "airport", "transport" ], + "char": '\ud83d\udec4', + fitzpatrick_scale: false, + category: "symbols" + }, + left_luggage: { + keywords: [ "blue-square", "travel" ], + "char": '\ud83d\udec5', + fitzpatrick_scale: false, + category: "symbols" + }, + wheelchair: { + keywords: [ "blue-square", "disabled", "a11y", "accessibility" ], + "char": '\u267f', + fitzpatrick_scale: false, + category: "symbols" + }, + no_smoking: { + keywords: [ "cigarette", "blue-square", "smell", "smoke" ], + "char": '\ud83d\udead', + fitzpatrick_scale: false, + category: "symbols" + }, + wc: { + keywords: [ "toilet", "restroom", "blue-square" ], + "char": '\ud83d\udebe', + fitzpatrick_scale: false, + category: "symbols" + }, + parking: { + keywords: [ "cars", "blue-square", "alphabet", "letter" ], + "char": '\ud83c\udd7f\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + potable_water: { + keywords: [ "blue-square", "liquid", "restroom", "cleaning", "faucet" ], + "char": '\ud83d\udeb0', + fitzpatrick_scale: false, + category: "symbols" + }, + mens: { + keywords: [ "toilet", "restroom", "wc", "blue-square", "gender", "male" ], + "char": '\ud83d\udeb9', + fitzpatrick_scale: false, + category: "symbols" + }, + womens: { + keywords: [ "purple-square", "woman", "female", "toilet", "loo", "restroom", "gender" ], + "char": '\ud83d\udeba', + fitzpatrick_scale: false, + category: "symbols" + }, + baby_symbol: { + keywords: [ "orange-square", "child" ], + "char": '\ud83d\udebc', + fitzpatrick_scale: false, + category: "symbols" + }, + restroom: { + keywords: [ "blue-square", "toilet", "refresh", "wc", "gender" ], + "char": '\ud83d\udebb', + fitzpatrick_scale: false, + category: "symbols" + }, + put_litter_in_its_place: { + keywords: [ "blue-square", "sign", "human", "info" ], + "char": '\ud83d\udeae', + fitzpatrick_scale: false, + category: "symbols" + }, + cinema: { + keywords: [ "blue-square", "record", "film", "movie", "curtain", "stage", "theater" ], + "char": '\ud83c\udfa6', + fitzpatrick_scale: false, + category: "symbols" + }, + signal_strength: { + keywords: [ "blue-square", "reception", "phone", "internet", "connection", "wifi", "bluetooth", "bars" ], + "char": '\ud83d\udcf6', + fitzpatrick_scale: false, + category: "symbols" + }, + koko: { + keywords: [ "blue-square", "here", "katakana", "japanese", "destination" ], + "char": '\ud83c\ude01', + fitzpatrick_scale: false, + category: "symbols" + }, + ng: { + keywords: [ "blue-square", "words", "shape", "icon" ], + "char": '\ud83c\udd96', + fitzpatrick_scale: false, + category: "symbols" + }, + ok: { + keywords: [ "good", "agree", "yes", "blue-square" ], + "char": '\ud83c\udd97', + fitzpatrick_scale: false, + category: "symbols" + }, + up: { + keywords: [ "blue-square", "above", "high" ], + "char": '\ud83c\udd99', + fitzpatrick_scale: false, + category: "symbols" + }, + cool: { + keywords: [ "words", "blue-square" ], + "char": '\ud83c\udd92', + fitzpatrick_scale: false, + category: "symbols" + }, + "new": { + keywords: [ "blue-square", "words", "start" ], + "char": '\ud83c\udd95', + fitzpatrick_scale: false, + category: "symbols" + }, + free: { + keywords: [ "blue-square", "words" ], + "char": '\ud83c\udd93', + fitzpatrick_scale: false, + category: "symbols" + }, + zero: { + keywords: [ "0", "numbers", "blue-square", "null" ], + "char": '0\ufe0f\u20e3', + fitzpatrick_scale: false, + category: "symbols" + }, + one: { + keywords: [ "blue-square", "numbers", "1" ], + "char": '1\ufe0f\u20e3', + fitzpatrick_scale: false, + category: "symbols" + }, + two: { + keywords: [ "numbers", "2", "prime", "blue-square" ], + "char": '2\ufe0f\u20e3', + fitzpatrick_scale: false, + category: "symbols" + }, + three: { + keywords: [ "3", "numbers", "prime", "blue-square" ], + "char": '3\ufe0f\u20e3', + fitzpatrick_scale: false, + category: "symbols" + }, + four: { + keywords: [ "4", "numbers", "blue-square" ], + "char": '4\ufe0f\u20e3', + fitzpatrick_scale: false, + category: "symbols" + }, + five: { + keywords: [ "5", "numbers", "blue-square", "prime" ], + "char": '5\ufe0f\u20e3', + fitzpatrick_scale: false, + category: "symbols" + }, + six: { + keywords: [ "6", "numbers", "blue-square" ], + "char": '6\ufe0f\u20e3', + fitzpatrick_scale: false, + category: "symbols" + }, + seven: { + keywords: [ "7", "numbers", "blue-square", "prime" ], + "char": '7\ufe0f\u20e3', + fitzpatrick_scale: false, + category: "symbols" + }, + eight: { + keywords: [ "8", "blue-square", "numbers" ], + "char": '8\ufe0f\u20e3', + fitzpatrick_scale: false, + category: "symbols" + }, + nine: { + keywords: [ "blue-square", "numbers", "9" ], + "char": '9\ufe0f\u20e3', + fitzpatrick_scale: false, + category: "symbols" + }, + keycap_ten: { + keywords: [ "numbers", "10", "blue-square" ], + "char": '\ud83d\udd1f', + fitzpatrick_scale: false, + category: "symbols" + }, + asterisk: { + keywords: [ "star", "keycap" ], + "char": '*\u20e3', + fitzpatrick_scale: false, + category: "symbols" + }, + eject_button: { + keywords: [ "blue-square" ], + "char": '\u23cf\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_forward: { + keywords: [ "blue-square", "right", "direction", "play" ], + "char": '\u25b6\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + pause_button: { + keywords: [ "pause", "blue-square" ], + "char": '\u23f8', + fitzpatrick_scale: false, + category: "symbols" + }, + next_track_button: { + keywords: [ "forward", "next", "blue-square" ], + "char": '\u23ed', + fitzpatrick_scale: false, + category: "symbols" + }, + stop_button: { + keywords: [ "blue-square" ], + "char": '\u23f9', + fitzpatrick_scale: false, + category: "symbols" + }, + record_button: { + keywords: [ "blue-square" ], + "char": '\u23fa', + fitzpatrick_scale: false, + category: "symbols" + }, + play_or_pause_button: { + keywords: [ "blue-square", "play", "pause" ], + "char": '\u23ef', + fitzpatrick_scale: false, + category: "symbols" + }, + previous_track_button: { + keywords: [ "backward" ], + "char": '\u23ee', + fitzpatrick_scale: false, + category: "symbols" + }, + fast_forward: { + keywords: [ "blue-square", "play", "speed", "continue" ], + "char": '\u23e9', + fitzpatrick_scale: false, + category: "symbols" + }, + rewind: { + keywords: [ "play", "blue-square" ], + "char": '\u23ea', + fitzpatrick_scale: false, + category: "symbols" + }, + twisted_rightwards_arrows: { + keywords: [ "blue-square", "shuffle", "music", "random" ], + "char": '\ud83d\udd00', + fitzpatrick_scale: false, + category: "symbols" + }, + repeat: { + keywords: [ "loop", "record" ], + "char": '\ud83d\udd01', + fitzpatrick_scale: false, + category: "symbols" + }, + repeat_one: { + keywords: [ "blue-square", "loop" ], + "char": '\ud83d\udd02', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_backward: { + keywords: [ "blue-square", "left", "direction" ], + "char": '\u25c0\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_up_small: { + keywords: [ "blue-square", "triangle", "direction", "point", "forward", "top" ], + "char": '\ud83d\udd3c', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_down_small: { + keywords: [ "blue-square", "direction", "bottom" ], + "char": '\ud83d\udd3d', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_double_up: { + keywords: [ "blue-square", "direction", "top" ], + "char": '\u23eb', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_double_down: { + keywords: [ "blue-square", "direction", "bottom" ], + "char": '\u23ec', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_right: { + keywords: [ "blue-square", "next" ], + "char": '\u27a1\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_left: { + keywords: [ "blue-square", "previous", "back" ], + "char": '\u2b05\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_up: { + keywords: [ "blue-square", "continue", "top", "direction" ], + "char": '\u2b06\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_down: { + keywords: [ "blue-square", "direction", "bottom" ], + "char": '\u2b07\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_upper_right: { + keywords: [ "blue-square", "point", "direction", "diagonal", "northeast" ], + "char": '\u2197\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_lower_right: { + keywords: [ "blue-square", "direction", "diagonal", "southeast" ], + "char": '\u2198\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_lower_left: { + keywords: [ "blue-square", "direction", "diagonal", "southwest" ], + "char": '\u2199\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_upper_left: { + keywords: [ "blue-square", "point", "direction", "diagonal", "northwest" ], + "char": '\u2196\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_up_down: { + keywords: [ "blue-square", "direction", "way", "vertical" ], + "char": '\u2195\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + left_right_arrow: { + keywords: [ "shape", "direction", "horizontal", "sideways" ], + "char": '\u2194\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrows_counterclockwise: { + keywords: [ "blue-square", "sync", "cycle" ], + "char": '\ud83d\udd04', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_right_hook: { + keywords: [ "blue-square", "return", "rotate", "direction" ], + "char": '\u21aa\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + leftwards_arrow_with_hook: { + keywords: [ "back", "return", "blue-square", "undo", "enter" ], + "char": '\u21a9\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_heading_up: { + keywords: [ "blue-square", "direction", "top" ], + "char": '\u2934\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_heading_down: { + keywords: [ "blue-square", "direction", "bottom" ], + "char": '\u2935\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + hash: { + keywords: [ "symbol", "blue-square", "twitter" ], + "char": '#\ufe0f\u20e3', + fitzpatrick_scale: false, + category: "symbols" + }, + information_source: { + keywords: [ "blue-square", "alphabet", "letter" ], + "char": '\u2139\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + abc: { + keywords: [ "blue-square", "alphabet" ], + "char": '\ud83d\udd24', + fitzpatrick_scale: false, + category: "symbols" + }, + abcd: { + keywords: [ "blue-square", "alphabet" ], + "char": '\ud83d\udd21', + fitzpatrick_scale: false, + category: "symbols" + }, + capital_abcd: { + keywords: [ "alphabet", "words", "blue-square" ], + "char": '\ud83d\udd20', + fitzpatrick_scale: false, + category: "symbols" + }, + symbols: { + keywords: [ "blue-square", "music", "note", "ampersand", "percent", "glyphs", "characters" ], + "char": '\ud83d\udd23', + fitzpatrick_scale: false, + category: "symbols" + }, + musical_note: { + keywords: [ "score", "tone", "sound" ], + "char": '\ud83c\udfb5', + fitzpatrick_scale: false, + category: "symbols" + }, + notes: { + keywords: [ "music", "score" ], + "char": '\ud83c\udfb6', + fitzpatrick_scale: false, + category: "symbols" + }, + wavy_dash: { + keywords: [ "draw", "line", "moustache", "mustache", "squiggle", "scribble" ], + "char": '\u3030\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + curly_loop: { + keywords: [ "scribble", "draw", "shape", "squiggle" ], + "char": '\u27b0', + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_check_mark: { + keywords: [ "ok", "nike", "answer", "yes", "tick" ], + "char": '\u2714\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + arrows_clockwise: { + keywords: [ "sync", "cycle", "round", "repeat" ], + "char": '\ud83d\udd03', + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_plus_sign: { + keywords: [ "math", "calculation", "addition", "more", "increase" ], + "char": '\u2795', + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_minus_sign: { + keywords: [ "math", "calculation", "subtract", "less" ], + "char": '\u2796', + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_division_sign: { + keywords: [ "divide", "math", "calculation" ], + "char": '\u2797', + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_multiplication_x: { + keywords: [ "math", "calculation" ], + "char": '\u2716\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + infinity: { + keywords: [ "forever" ], + "char": '\u267e', + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_dollar_sign: { + keywords: [ "money", "sales", "payment", "currency", "buck" ], + "char": '\ud83d\udcb2', + fitzpatrick_scale: false, + category: "symbols" + }, + currency_exchange: { + keywords: [ "money", "sales", "dollar", "travel" ], + "char": '\ud83d\udcb1', + fitzpatrick_scale: false, + category: "symbols" + }, + copyright: { + keywords: [ "ip", "license", "circle", "law", "legal" ], + "char": '\xa9\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + registered: { + keywords: [ "alphabet", "circle" ], + "char": '\xae\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + tm: { + keywords: [ "trademark", "brand", "law", "legal" ], + "char": '\u2122\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + end: { + keywords: [ "words", "arrow" ], + "char": '\ud83d\udd1a', + fitzpatrick_scale: false, + category: "symbols" + }, + back: { + keywords: [ "arrow", "words", "return" ], + "char": '\ud83d\udd19', + fitzpatrick_scale: false, + category: "symbols" + }, + on: { + keywords: [ "arrow", "words" ], + "char": '\ud83d\udd1b', + fitzpatrick_scale: false, + category: "symbols" + }, + top: { + keywords: [ "words", "blue-square" ], + "char": '\ud83d\udd1d', + fitzpatrick_scale: false, + category: "symbols" + }, + soon: { + keywords: [ "arrow", "words" ], + "char": '\ud83d\udd1c', + fitzpatrick_scale: false, + category: "symbols" + }, + ballot_box_with_check: { + keywords: [ "ok", "agree", "confirm", "black-square", "vote", "election", "yes", "tick" ], + "char": '\u2611\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + radio_button: { + keywords: [ "input", "old", "music", "circle" ], + "char": '\ud83d\udd18', + fitzpatrick_scale: false, + category: "symbols" + }, + white_circle: { + keywords: [ "shape", "round" ], + "char": '\u26aa', + fitzpatrick_scale: false, + category: "symbols" + }, + black_circle: { + keywords: [ "shape", "button", "round" ], + "char": '\u26ab', + fitzpatrick_scale: false, + category: "symbols" + }, + red_circle: { + keywords: [ "shape", "error", "danger" ], + "char": '\ud83d\udd34', + fitzpatrick_scale: false, + category: "symbols" + }, + large_blue_circle: { + keywords: [ "shape", "icon", "button" ], + "char": '\ud83d\udd35', + fitzpatrick_scale: false, + category: "symbols" + }, + small_orange_diamond: { + keywords: [ "shape", "jewel", "gem" ], + "char": '\ud83d\udd38', + fitzpatrick_scale: false, + category: "symbols" + }, + small_blue_diamond: { + keywords: [ "shape", "jewel", "gem" ], + "char": '\ud83d\udd39', + fitzpatrick_scale: false, + category: "symbols" + }, + large_orange_diamond: { + keywords: [ "shape", "jewel", "gem" ], + "char": '\ud83d\udd36', + fitzpatrick_scale: false, + category: "symbols" + }, + large_blue_diamond: { + keywords: [ "shape", "jewel", "gem" ], + "char": '\ud83d\udd37', + fitzpatrick_scale: false, + category: "symbols" + }, + small_red_triangle: { + keywords: [ "shape", "direction", "up", "top" ], + "char": '\ud83d\udd3a', + fitzpatrick_scale: false, + category: "symbols" + }, + black_small_square: { + keywords: [ "shape", "icon" ], + "char": '\u25aa\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + white_small_square: { + keywords: [ "shape", "icon" ], + "char": '\u25ab\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + black_large_square: { + keywords: [ "shape", "icon", "button" ], + "char": '\u2b1b', + fitzpatrick_scale: false, + category: "symbols" + }, + white_large_square: { + keywords: [ "shape", "icon", "stone", "button" ], + "char": '\u2b1c', + fitzpatrick_scale: false, + category: "symbols" + }, + small_red_triangle_down: { + keywords: [ "shape", "direction", "bottom" ], + "char": '\ud83d\udd3b', + fitzpatrick_scale: false, + category: "symbols" + }, + black_medium_square: { + keywords: [ "shape", "button", "icon" ], + "char": '\u25fc\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + white_medium_square: { + keywords: [ "shape", "stone", "icon" ], + "char": '\u25fb\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + black_medium_small_square: { + keywords: [ "icon", "shape", "button" ], + "char": '\u25fe', + fitzpatrick_scale: false, + category: "symbols" + }, + white_medium_small_square: { + keywords: [ "shape", "stone", "icon", "button" ], + "char": '\u25fd', + fitzpatrick_scale: false, + category: "symbols" + }, + black_square_button: { + keywords: [ "shape", "input", "frame" ], + "char": '\ud83d\udd32', + fitzpatrick_scale: false, + category: "symbols" + }, + white_square_button: { + keywords: [ "shape", "input" ], + "char": '\ud83d\udd33', + fitzpatrick_scale: false, + category: "symbols" + }, + speaker: { + keywords: [ "sound", "volume", "silence", "broadcast" ], + "char": '\ud83d\udd08', + fitzpatrick_scale: false, + category: "symbols" + }, + sound: { + keywords: [ "volume", "speaker", "broadcast" ], + "char": '\ud83d\udd09', + fitzpatrick_scale: false, + category: "symbols" + }, + loud_sound: { + keywords: [ "volume", "noise", "noisy", "speaker", "broadcast" ], + "char": '\ud83d\udd0a', + fitzpatrick_scale: false, + category: "symbols" + }, + mute: { + keywords: [ "sound", "volume", "silence", "quiet" ], + "char": '\ud83d\udd07', + fitzpatrick_scale: false, + category: "symbols" + }, + mega: { + keywords: [ "sound", "speaker", "volume" ], + "char": '\ud83d\udce3', + fitzpatrick_scale: false, + category: "symbols" + }, + loudspeaker: { + keywords: [ "volume", "sound" ], + "char": '\ud83d\udce2', + fitzpatrick_scale: false, + category: "symbols" + }, + bell: { + keywords: [ "sound", "notification", "christmas", "xmas", "chime" ], + "char": '\ud83d\udd14', + fitzpatrick_scale: false, + category: "symbols" + }, + no_bell: { + keywords: [ "sound", "volume", "mute", "quiet", "silent" ], + "char": '\ud83d\udd15', + fitzpatrick_scale: false, + category: "symbols" + }, + black_joker: { + keywords: [ "poker", "cards", "game", "play", "magic" ], + "char": '\ud83c\udccf', + fitzpatrick_scale: false, + category: "symbols" + }, + mahjong: { + keywords: [ "game", "play", "chinese", "kanji" ], + "char": '\ud83c\udc04', + fitzpatrick_scale: false, + category: "symbols" + }, + spades: { + keywords: [ "poker", "cards", "suits", "magic" ], + "char": '\u2660\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + clubs: { + keywords: [ "poker", "cards", "magic", "suits" ], + "char": '\u2663\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + hearts: { + keywords: [ "poker", "cards", "magic", "suits" ], + "char": '\u2665\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + diamonds: { + keywords: [ "poker", "cards", "magic", "suits" ], + "char": '\u2666\ufe0f', + fitzpatrick_scale: false, + category: "symbols" + }, + flower_playing_cards: { + keywords: [ "game", "sunset", "red" ], + "char": '\ud83c\udfb4', + fitzpatrick_scale: false, + category: "symbols" + }, + thought_balloon: { + keywords: [ "bubble", "cloud", "speech", "thinking", "dream" ], + "char": '\ud83d\udcad', + fitzpatrick_scale: false, + category: "symbols" + }, + right_anger_bubble: { + keywords: [ "caption", "speech", "thinking", "mad" ], + "char": '\ud83d\uddef', + fitzpatrick_scale: false, + category: "symbols" + }, + speech_balloon: { + keywords: [ "bubble", "words", "message", "talk", "chatting" ], + "char": '\ud83d\udcac', + fitzpatrick_scale: false, + category: "symbols" + }, + left_speech_bubble: { + keywords: [ "words", "message", "talk", "chatting" ], + "char": '\ud83d\udde8', + fitzpatrick_scale: false, + category: "symbols" + }, + clock1: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd50', + fitzpatrick_scale: false, + category: "symbols" + }, + clock2: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd51', + fitzpatrick_scale: false, + category: "symbols" + }, + clock3: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd52', + fitzpatrick_scale: false, + category: "symbols" + }, + clock4: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd53', + fitzpatrick_scale: false, + category: "symbols" + }, + clock5: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd54', + fitzpatrick_scale: false, + category: "symbols" + }, + clock6: { + keywords: [ "time", "late", "early", "schedule", "dawn", "dusk" ], + "char": '\ud83d\udd55', + fitzpatrick_scale: false, + category: "symbols" + }, + clock7: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd56', + fitzpatrick_scale: false, + category: "symbols" + }, + clock8: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd57', + fitzpatrick_scale: false, + category: "symbols" + }, + clock9: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd58', + fitzpatrick_scale: false, + category: "symbols" + }, + clock10: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd59', + fitzpatrick_scale: false, + category: "symbols" + }, + clock11: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd5a', + fitzpatrick_scale: false, + category: "symbols" + }, + clock12: { + keywords: [ "time", "noon", "midnight", "midday", "late", "early", "schedule" ], + "char": '\ud83d\udd5b', + fitzpatrick_scale: false, + category: "symbols" + }, + clock130: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd5c', + fitzpatrick_scale: false, + category: "symbols" + }, + clock230: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd5d', + fitzpatrick_scale: false, + category: "symbols" + }, + clock330: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd5e', + fitzpatrick_scale: false, + category: "symbols" + }, + clock430: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd5f', + fitzpatrick_scale: false, + category: "symbols" + }, + clock530: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd60', + fitzpatrick_scale: false, + category: "symbols" + }, + clock630: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd61', + fitzpatrick_scale: false, + category: "symbols" + }, + clock730: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd62', + fitzpatrick_scale: false, + category: "symbols" + }, + clock830: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd63', + fitzpatrick_scale: false, + category: "symbols" + }, + clock930: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd64', + fitzpatrick_scale: false, + category: "symbols" + }, + clock1030: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd65', + fitzpatrick_scale: false, + category: "symbols" + }, + clock1130: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd66', + fitzpatrick_scale: false, + category: "symbols" + }, + clock1230: { + keywords: [ "time", "late", "early", "schedule" ], + "char": '\ud83d\udd67', + fitzpatrick_scale: false, + category: "symbols" + }, + afghanistan: { + keywords: [ "af", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddeb', + fitzpatrick_scale: false, + category: "flags" + }, + aland_islands: { + keywords: [ "\xc5land", "islands", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddfd', + fitzpatrick_scale: false, + category: "flags" + }, + albania: { + keywords: [ "al", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddf1', + fitzpatrick_scale: false, + category: "flags" + }, + algeria: { + keywords: [ "dz", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde9\ud83c\uddff', + fitzpatrick_scale: false, + category: "flags" + }, + american_samoa: { + keywords: [ "american", "ws", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddf8', + fitzpatrick_scale: false, + category: "flags" + }, + andorra: { + keywords: [ "ad", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\udde9', + fitzpatrick_scale: false, + category: "flags" + }, + angola: { + keywords: [ "ao", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddf4', + fitzpatrick_scale: false, + category: "flags" + }, + anguilla: { + keywords: [ "ai", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddee', + fitzpatrick_scale: false, + category: "flags" + }, + antarctica: { + keywords: [ "aq", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddf6', + fitzpatrick_scale: false, + category: "flags" + }, + antigua_barbuda: { + keywords: [ "antigua", "barbuda", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + argentina: { + keywords: [ "ar", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + armenia: { + keywords: [ "am", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + aruba: { + keywords: [ "aw", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddfc', + fitzpatrick_scale: false, + category: "flags" + }, + australia: { + keywords: [ "au", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddfa', + fitzpatrick_scale: false, + category: "flags" + }, + austria: { + keywords: [ "at", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddf9', + fitzpatrick_scale: false, + category: "flags" + }, + azerbaijan: { + keywords: [ "az", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddff', + fitzpatrick_scale: false, + category: "flags" + }, + bahamas: { + keywords: [ "bs", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddf8', + fitzpatrick_scale: false, + category: "flags" + }, + bahrain: { + keywords: [ "bh", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\udded', + fitzpatrick_scale: false, + category: "flags" + }, + bangladesh: { + keywords: [ "bd", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\udde9', + fitzpatrick_scale: false, + category: "flags" + }, + barbados: { + keywords: [ "bb", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\udde7', + fitzpatrick_scale: false, + category: "flags" + }, + belarus: { + keywords: [ "by", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddfe', + fitzpatrick_scale: false, + category: "flags" + }, + belgium: { + keywords: [ "be", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + belize: { + keywords: [ "bz", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddff', + fitzpatrick_scale: false, + category: "flags" + }, + benin: { + keywords: [ "bj", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddef', + fitzpatrick_scale: false, + category: "flags" + }, + bermuda: { + keywords: [ "bm", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + bhutan: { + keywords: [ "bt", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddf9', + fitzpatrick_scale: false, + category: "flags" + }, + bolivia: { + keywords: [ "bo", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddf4', + fitzpatrick_scale: false, + category: "flags" + }, + caribbean_netherlands: { + keywords: [ "bonaire", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddf6', + fitzpatrick_scale: false, + category: "flags" + }, + bosnia_herzegovina: { + keywords: [ "bosnia", "herzegovina", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\udde6', + fitzpatrick_scale: false, + category: "flags" + }, + botswana: { + keywords: [ "bw", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddfc', + fitzpatrick_scale: false, + category: "flags" + }, + brazil: { + keywords: [ "br", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + british_indian_ocean_territory: { + keywords: [ "british", "indian", "ocean", "territory", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddee\ud83c\uddf4', + fitzpatrick_scale: false, + category: "flags" + }, + british_virgin_islands: { + keywords: [ "british", "virgin", "islands", "bvi", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfb\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + brunei: { + keywords: [ "bn", "darussalam", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddf3', + fitzpatrick_scale: false, + category: "flags" + }, + bulgaria: { + keywords: [ "bg", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + burkina_faso: { + keywords: [ "burkina", "faso", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddeb', + fitzpatrick_scale: false, + category: "flags" + }, + burundi: { + keywords: [ "bi", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddee', + fitzpatrick_scale: false, + category: "flags" + }, + cape_verde: { + keywords: [ "cabo", "verde", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddfb', + fitzpatrick_scale: false, + category: "flags" + }, + cambodia: { + keywords: [ "kh", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf0\ud83c\udded', + fitzpatrick_scale: false, + category: "flags" + }, + cameroon: { + keywords: [ "cm", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + canada: { + keywords: [ "ca", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\udde6', + fitzpatrick_scale: false, + category: "flags" + }, + canary_islands: { + keywords: [ "canary", "islands", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddee\ud83c\udde8', + fitzpatrick_scale: false, + category: "flags" + }, + cayman_islands: { + keywords: [ "cayman", "islands", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf0\ud83c\uddfe', + fitzpatrick_scale: false, + category: "flags" + }, + central_african_republic: { + keywords: [ "central", "african", "republic", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddeb', + fitzpatrick_scale: false, + category: "flags" + }, + chad: { + keywords: [ "td", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\udde9', + fitzpatrick_scale: false, + category: "flags" + }, + chile: { + keywords: [ "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddf1', + fitzpatrick_scale: false, + category: "flags" + }, + cn: { + keywords: [ "china", "chinese", "prc", "flag", "country", "nation", "banner" ], + "char": '\ud83c\udde8\ud83c\uddf3', + fitzpatrick_scale: false, + category: "flags" + }, + christmas_island: { + keywords: [ "christmas", "island", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddfd', + fitzpatrick_scale: false, + category: "flags" + }, + cocos_islands: { + keywords: [ "cocos", "keeling", "islands", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\udde8', + fitzpatrick_scale: false, + category: "flags" + }, + colombia: { + keywords: [ "co", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddf4', + fitzpatrick_scale: false, + category: "flags" + }, + comoros: { + keywords: [ "km", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf0\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + congo_brazzaville: { + keywords: [ "congo", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + congo_kinshasa: { + keywords: [ "congo", "democratic", "republic", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\udde9', + fitzpatrick_scale: false, + category: "flags" + }, + cook_islands: { + keywords: [ "cook", "islands", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddf0', + fitzpatrick_scale: false, + category: "flags" + }, + costa_rica: { + keywords: [ "costa", "rica", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + croatia: { + keywords: [ "hr", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udded\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + cuba: { + keywords: [ "cu", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddfa', + fitzpatrick_scale: false, + category: "flags" + }, + curacao: { + keywords: [ "cura\xe7ao", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddfc', + fitzpatrick_scale: false, + category: "flags" + }, + cyprus: { + keywords: [ "cy", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddfe', + fitzpatrick_scale: false, + category: "flags" + }, + czech_republic: { + keywords: [ "cz", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddff', + fitzpatrick_scale: false, + category: "flags" + }, + denmark: { + keywords: [ "dk", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde9\ud83c\uddf0', + fitzpatrick_scale: false, + category: "flags" + }, + djibouti: { + keywords: [ "dj", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde9\ud83c\uddef', + fitzpatrick_scale: false, + category: "flags" + }, + dominica: { + keywords: [ "dm", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde9\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + dominican_republic: { + keywords: [ "dominican", "republic", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde9\ud83c\uddf4', + fitzpatrick_scale: false, + category: "flags" + }, + ecuador: { + keywords: [ "ec", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddea\ud83c\udde8', + fitzpatrick_scale: false, + category: "flags" + }, + egypt: { + keywords: [ "eg", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddea\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + el_salvador: { + keywords: [ "el", "salvador", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddfb', + fitzpatrick_scale: false, + category: "flags" + }, + equatorial_guinea: { + keywords: [ "equatorial", "gn", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddf6', + fitzpatrick_scale: false, + category: "flags" + }, + eritrea: { + keywords: [ "er", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddea\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + estonia: { + keywords: [ "ee", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddea\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + ethiopia: { + keywords: [ "et", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddea\ud83c\uddf9', + fitzpatrick_scale: false, + category: "flags" + }, + eu: { + keywords: [ "european", "union", "flag", "banner" ], + "char": '\ud83c\uddea\ud83c\uddfa', + fitzpatrick_scale: false, + category: "flags" + }, + falkland_islands: { + keywords: [ "falkland", "islands", "malvinas", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddeb\ud83c\uddf0', + fitzpatrick_scale: false, + category: "flags" + }, + faroe_islands: { + keywords: [ "faroe", "islands", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddeb\ud83c\uddf4', + fitzpatrick_scale: false, + category: "flags" + }, + fiji: { + keywords: [ "fj", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddeb\ud83c\uddef', + fitzpatrick_scale: false, + category: "flags" + }, + finland: { + keywords: [ "fi", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddeb\ud83c\uddee', + fitzpatrick_scale: false, + category: "flags" + }, + fr: { + keywords: [ "banner", "flag", "nation", "france", "french", "country" ], + "char": '\ud83c\uddeb\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + french_guiana: { + keywords: [ "french", "guiana", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddeb', + fitzpatrick_scale: false, + category: "flags" + }, + french_polynesia: { + keywords: [ "french", "polynesia", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\uddeb', + fitzpatrick_scale: false, + category: "flags" + }, + french_southern_territories: { + keywords: [ "french", "southern", "territories", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddeb', + fitzpatrick_scale: false, + category: "flags" + }, + gabon: { + keywords: [ "ga", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\udde6', + fitzpatrick_scale: false, + category: "flags" + }, + gambia: { + keywords: [ "gm", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + georgia: { + keywords: [ "ge", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + de: { + keywords: [ "german", "nation", "flag", "country", "banner" ], + "char": '\ud83c\udde9\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + ghana: { + keywords: [ "gh", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\udded', + fitzpatrick_scale: false, + category: "flags" + }, + gibraltar: { + keywords: [ "gi", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddee', + fitzpatrick_scale: false, + category: "flags" + }, + greece: { + keywords: [ "gr", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + greenland: { + keywords: [ "gl", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddf1', + fitzpatrick_scale: false, + category: "flags" + }, + grenada: { + keywords: [ "gd", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\udde9', + fitzpatrick_scale: false, + category: "flags" + }, + guadeloupe: { + keywords: [ "gp", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddf5', + fitzpatrick_scale: false, + category: "flags" + }, + guam: { + keywords: [ "gu", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddfa', + fitzpatrick_scale: false, + category: "flags" + }, + guatemala: { + keywords: [ "gt", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddf9', + fitzpatrick_scale: false, + category: "flags" + }, + guernsey: { + keywords: [ "gg", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + guinea: { + keywords: [ "gn", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddf3', + fitzpatrick_scale: false, + category: "flags" + }, + guinea_bissau: { + keywords: [ "gw", "bissau", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddfc', + fitzpatrick_scale: false, + category: "flags" + }, + guyana: { + keywords: [ "gy", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddfe', + fitzpatrick_scale: false, + category: "flags" + }, + haiti: { + keywords: [ "ht", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udded\ud83c\uddf9', + fitzpatrick_scale: false, + category: "flags" + }, + honduras: { + keywords: [ "hn", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udded\ud83c\uddf3', + fitzpatrick_scale: false, + category: "flags" + }, + hong_kong: { + keywords: [ "hong", "kong", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udded\ud83c\uddf0', + fitzpatrick_scale: false, + category: "flags" + }, + hungary: { + keywords: [ "hu", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udded\ud83c\uddfa', + fitzpatrick_scale: false, + category: "flags" + }, + iceland: { + keywords: [ "is", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddee\ud83c\uddf8', + fitzpatrick_scale: false, + category: "flags" + }, + india: { + keywords: [ "in", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddee\ud83c\uddf3', + fitzpatrick_scale: false, + category: "flags" + }, + indonesia: { + keywords: [ "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddee\ud83c\udde9', + fitzpatrick_scale: false, + category: "flags" + }, + iran: { + keywords: [ "iran,", "islamic", "republic", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddee\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + iraq: { + keywords: [ "iq", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddee\ud83c\uddf6', + fitzpatrick_scale: false, + category: "flags" + }, + ireland: { + keywords: [ "ie", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddee\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + isle_of_man: { + keywords: [ "isle", "man", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddee\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + israel: { + keywords: [ "il", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddee\ud83c\uddf1', + fitzpatrick_scale: false, + category: "flags" + }, + it: { + keywords: [ "italy", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddee\ud83c\uddf9', + fitzpatrick_scale: false, + category: "flags" + }, + cote_divoire: { + keywords: [ "ivory", "coast", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\uddee', + fitzpatrick_scale: false, + category: "flags" + }, + jamaica: { + keywords: [ "jm", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddef\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + jp: { + keywords: [ "japanese", "nation", "flag", "country", "banner" ], + "char": '\ud83c\uddef\ud83c\uddf5', + fitzpatrick_scale: false, + category: "flags" + }, + jersey: { + keywords: [ "je", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddef\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + jordan: { + keywords: [ "jo", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddef\ud83c\uddf4', + fitzpatrick_scale: false, + category: "flags" + }, + kazakhstan: { + keywords: [ "kz", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf0\ud83c\uddff', + fitzpatrick_scale: false, + category: "flags" + }, + kenya: { + keywords: [ "ke", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf0\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + kiribati: { + keywords: [ "ki", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf0\ud83c\uddee', + fitzpatrick_scale: false, + category: "flags" + }, + kosovo: { + keywords: [ "xk", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfd\ud83c\uddf0', + fitzpatrick_scale: false, + category: "flags" + }, + kuwait: { + keywords: [ "kw", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf0\ud83c\uddfc', + fitzpatrick_scale: false, + category: "flags" + }, + kyrgyzstan: { + keywords: [ "kg", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf0\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + laos: { + keywords: [ "lao", "democratic", "republic", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf1\ud83c\udde6', + fitzpatrick_scale: false, + category: "flags" + }, + latvia: { + keywords: [ "lv", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf1\ud83c\uddfb', + fitzpatrick_scale: false, + category: "flags" + }, + lebanon: { + keywords: [ "lb", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf1\ud83c\udde7', + fitzpatrick_scale: false, + category: "flags" + }, + lesotho: { + keywords: [ "ls", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf1\ud83c\uddf8', + fitzpatrick_scale: false, + category: "flags" + }, + liberia: { + keywords: [ "lr", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf1\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + libya: { + keywords: [ "ly", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf1\ud83c\uddfe', + fitzpatrick_scale: false, + category: "flags" + }, + liechtenstein: { + keywords: [ "li", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf1\ud83c\uddee', + fitzpatrick_scale: false, + category: "flags" + }, + lithuania: { + keywords: [ "lt", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf1\ud83c\uddf9', + fitzpatrick_scale: false, + category: "flags" + }, + luxembourg: { + keywords: [ "lu", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf1\ud83c\uddfa', + fitzpatrick_scale: false, + category: "flags" + }, + macau: { + keywords: [ "macao", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddf4', + fitzpatrick_scale: false, + category: "flags" + }, + macedonia: { + keywords: [ "macedonia,", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddf0', + fitzpatrick_scale: false, + category: "flags" + }, + madagascar: { + keywords: [ "mg", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + malawi: { + keywords: [ "mw", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddfc', + fitzpatrick_scale: false, + category: "flags" + }, + malaysia: { + keywords: [ "my", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddfe', + fitzpatrick_scale: false, + category: "flags" + }, + maldives: { + keywords: [ "mv", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddfb', + fitzpatrick_scale: false, + category: "flags" + }, + mali: { + keywords: [ "ml", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddf1', + fitzpatrick_scale: false, + category: "flags" + }, + malta: { + keywords: [ "mt", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddf9', + fitzpatrick_scale: false, + category: "flags" + }, + marshall_islands: { + keywords: [ "marshall", "islands", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\udded', + fitzpatrick_scale: false, + category: "flags" + }, + martinique: { + keywords: [ "mq", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddf6', + fitzpatrick_scale: false, + category: "flags" + }, + mauritania: { + keywords: [ "mr", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + mauritius: { + keywords: [ "mu", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddfa', + fitzpatrick_scale: false, + category: "flags" + }, + mayotte: { + keywords: [ "yt", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfe\ud83c\uddf9', + fitzpatrick_scale: false, + category: "flags" + }, + mexico: { + keywords: [ "mx", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddfd', + fitzpatrick_scale: false, + category: "flags" + }, + micronesia: { + keywords: [ "micronesia,", "federated", "states", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddeb\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + moldova: { + keywords: [ "moldova,", "republic", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\udde9', + fitzpatrick_scale: false, + category: "flags" + }, + monaco: { + keywords: [ "mc", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\udde8', + fitzpatrick_scale: false, + category: "flags" + }, + mongolia: { + keywords: [ "mn", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddf3', + fitzpatrick_scale: false, + category: "flags" + }, + montenegro: { + keywords: [ "me", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + montserrat: { + keywords: [ "ms", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddf8', + fitzpatrick_scale: false, + category: "flags" + }, + morocco: { + keywords: [ "ma", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\udde6', + fitzpatrick_scale: false, + category: "flags" + }, + mozambique: { + keywords: [ "mz", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddff', + fitzpatrick_scale: false, + category: "flags" + }, + myanmar: { + keywords: [ "mm", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + namibia: { + keywords: [ "na", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf3\ud83c\udde6', + fitzpatrick_scale: false, + category: "flags" + }, + nauru: { + keywords: [ "nr", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf3\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + nepal: { + keywords: [ "np", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf3\ud83c\uddf5', + fitzpatrick_scale: false, + category: "flags" + }, + netherlands: { + keywords: [ "nl", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf3\ud83c\uddf1', + fitzpatrick_scale: false, + category: "flags" + }, + new_caledonia: { + keywords: [ "new", "caledonia", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf3\ud83c\udde8', + fitzpatrick_scale: false, + category: "flags" + }, + new_zealand: { + keywords: [ "new", "zealand", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf3\ud83c\uddff', + fitzpatrick_scale: false, + category: "flags" + }, + nicaragua: { + keywords: [ "ni", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf3\ud83c\uddee', + fitzpatrick_scale: false, + category: "flags" + }, + niger: { + keywords: [ "ne", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf3\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + nigeria: { + keywords: [ "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf3\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + niue: { + keywords: [ "nu", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf3\ud83c\uddfa', + fitzpatrick_scale: false, + category: "flags" + }, + norfolk_island: { + keywords: [ "norfolk", "island", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf3\ud83c\uddeb', + fitzpatrick_scale: false, + category: "flags" + }, + northern_mariana_islands: { + keywords: [ "northern", "mariana", "islands", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf2\ud83c\uddf5', + fitzpatrick_scale: false, + category: "flags" + }, + north_korea: { + keywords: [ "north", "korea", "nation", "flag", "country", "banner" ], + "char": '\ud83c\uddf0\ud83c\uddf5', + fitzpatrick_scale: false, + category: "flags" + }, + norway: { + keywords: [ "no", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf3\ud83c\uddf4', + fitzpatrick_scale: false, + category: "flags" + }, + oman: { + keywords: [ "om_symbol", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf4\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + pakistan: { + keywords: [ "pk", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\uddf0', + fitzpatrick_scale: false, + category: "flags" + }, + palau: { + keywords: [ "pw", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\uddfc', + fitzpatrick_scale: false, + category: "flags" + }, + palestinian_territories: { + keywords: [ "palestine", "palestinian", "territories", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\uddf8', + fitzpatrick_scale: false, + category: "flags" + }, + panama: { + keywords: [ "pa", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\udde6', + fitzpatrick_scale: false, + category: "flags" + }, + papua_new_guinea: { + keywords: [ "papua", "new", "guinea", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + paraguay: { + keywords: [ "py", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\uddfe', + fitzpatrick_scale: false, + category: "flags" + }, + peru: { + keywords: [ "pe", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + philippines: { + keywords: [ "ph", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\udded', + fitzpatrick_scale: false, + category: "flags" + }, + pitcairn_islands: { + keywords: [ "pitcairn", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\uddf3', + fitzpatrick_scale: false, + category: "flags" + }, + poland: { + keywords: [ "pl", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\uddf1', + fitzpatrick_scale: false, + category: "flags" + }, + portugal: { + keywords: [ "pt", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\uddf9', + fitzpatrick_scale: false, + category: "flags" + }, + puerto_rico: { + keywords: [ "puerto", "rico", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + qatar: { + keywords: [ "qa", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf6\ud83c\udde6', + fitzpatrick_scale: false, + category: "flags" + }, + reunion: { + keywords: [ "r\xe9union", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf7\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + romania: { + keywords: [ "ro", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf7\ud83c\uddf4', + fitzpatrick_scale: false, + category: "flags" + }, + ru: { + keywords: [ "russian", "federation", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf7\ud83c\uddfa', + fitzpatrick_scale: false, + category: "flags" + }, + rwanda: { + keywords: [ "rw", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf7\ud83c\uddfc', + fitzpatrick_scale: false, + category: "flags" + }, + st_barthelemy: { + keywords: [ "saint", "barth\xe9lemy", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde7\ud83c\uddf1', + fitzpatrick_scale: false, + category: "flags" + }, + st_helena: { + keywords: [ "saint", "helena", "ascension", "tristan", "cunha", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\udded', + fitzpatrick_scale: false, + category: "flags" + }, + st_kitts_nevis: { + keywords: [ "saint", "kitts", "nevis", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf0\ud83c\uddf3', + fitzpatrick_scale: false, + category: "flags" + }, + st_lucia: { + keywords: [ "saint", "lucia", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf1\ud83c\udde8', + fitzpatrick_scale: false, + category: "flags" + }, + st_pierre_miquelon: { + keywords: [ "saint", "pierre", "miquelon", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf5\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + st_vincent_grenadines: { + keywords: [ "saint", "vincent", "grenadines", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfb\ud83c\udde8', + fitzpatrick_scale: false, + category: "flags" + }, + samoa: { + keywords: [ "ws", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfc\ud83c\uddf8', + fitzpatrick_scale: false, + category: "flags" + }, + san_marino: { + keywords: [ "san", "marino", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + sao_tome_principe: { + keywords: [ "sao", "tome", "principe", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddf9', + fitzpatrick_scale: false, + category: "flags" + }, + saudi_arabia: { + keywords: [ "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\udde6', + fitzpatrick_scale: false, + category: "flags" + }, + senegal: { + keywords: [ "sn", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddf3', + fitzpatrick_scale: false, + category: "flags" + }, + serbia: { + keywords: [ "rs", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf7\ud83c\uddf8', + fitzpatrick_scale: false, + category: "flags" + }, + seychelles: { + keywords: [ "sc", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\udde8', + fitzpatrick_scale: false, + category: "flags" + }, + sierra_leone: { + keywords: [ "sierra", "leone", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddf1', + fitzpatrick_scale: false, + category: "flags" + }, + singapore: { + keywords: [ "sg", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + sint_maarten: { + keywords: [ "sint", "maarten", "dutch", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddfd', + fitzpatrick_scale: false, + category: "flags" + }, + slovakia: { + keywords: [ "sk", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddf0', + fitzpatrick_scale: false, + category: "flags" + }, + slovenia: { + keywords: [ "si", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddee', + fitzpatrick_scale: false, + category: "flags" + }, + solomon_islands: { + keywords: [ "solomon", "islands", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\udde7', + fitzpatrick_scale: false, + category: "flags" + }, + somalia: { + keywords: [ "so", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddf4', + fitzpatrick_scale: false, + category: "flags" + }, + south_africa: { + keywords: [ "south", "africa", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddff\ud83c\udde6', + fitzpatrick_scale: false, + category: "flags" + }, + south_georgia_south_sandwich_islands: { + keywords: [ "south", "georgia", "sandwich", "islands", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddec\ud83c\uddf8', + fitzpatrick_scale: false, + category: "flags" + }, + kr: { + keywords: [ "south", "korea", "nation", "flag", "country", "banner" ], + "char": '\ud83c\uddf0\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + south_sudan: { + keywords: [ "south", "sd", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddf8', + fitzpatrick_scale: false, + category: "flags" + }, + es: { + keywords: [ "spain", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddea\ud83c\uddf8', + fitzpatrick_scale: false, + category: "flags" + }, + sri_lanka: { + keywords: [ "sri", "lanka", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf1\ud83c\uddf0', + fitzpatrick_scale: false, + category: "flags" + }, + sudan: { + keywords: [ "sd", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\udde9', + fitzpatrick_scale: false, + category: "flags" + }, + suriname: { + keywords: [ "sr", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + swaziland: { + keywords: [ "sz", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddff', + fitzpatrick_scale: false, + category: "flags" + }, + sweden: { + keywords: [ "se", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + switzerland: { + keywords: [ "ch", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde8\ud83c\udded', + fitzpatrick_scale: false, + category: "flags" + }, + syria: { + keywords: [ "syrian", "arab", "republic", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf8\ud83c\uddfe', + fitzpatrick_scale: false, + category: "flags" + }, + taiwan: { + keywords: [ "tw", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddfc', + fitzpatrick_scale: false, + category: "flags" + }, + tajikistan: { + keywords: [ "tj", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddef', + fitzpatrick_scale: false, + category: "flags" + }, + tanzania: { + keywords: [ "tanzania,", "united", "republic", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddff', + fitzpatrick_scale: false, + category: "flags" + }, + thailand: { + keywords: [ "th", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\udded', + fitzpatrick_scale: false, + category: "flags" + }, + timor_leste: { + keywords: [ "timor", "leste", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddf1', + fitzpatrick_scale: false, + category: "flags" + }, + togo: { + keywords: [ "tg", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + tokelau: { + keywords: [ "tk", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddf0', + fitzpatrick_scale: false, + category: "flags" + }, + tonga: { + keywords: [ "to", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddf4', + fitzpatrick_scale: false, + category: "flags" + }, + trinidad_tobago: { + keywords: [ "trinidad", "tobago", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddf9', + fitzpatrick_scale: false, + category: "flags" + }, + tunisia: { + keywords: [ "tn", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddf3', + fitzpatrick_scale: false, + category: "flags" + }, + tr: { + keywords: [ "turkey", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddf7', + fitzpatrick_scale: false, + category: "flags" + }, + turkmenistan: { + keywords: [ "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + turks_caicos_islands: { + keywords: [ "turks", "caicos", "islands", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\udde8', + fitzpatrick_scale: false, + category: "flags" + }, + tuvalu: { + keywords: [ "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddf9\ud83c\uddfb', + fitzpatrick_scale: false, + category: "flags" + }, + uganda: { + keywords: [ "ug", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfa\ud83c\uddec', + fitzpatrick_scale: false, + category: "flags" + }, + ukraine: { + keywords: [ "ua", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfa\ud83c\udde6', + fitzpatrick_scale: false, + category: "flags" + }, + united_arab_emirates: { + keywords: [ "united", "arab", "emirates", "flag", "nation", "country", "banner" ], + "char": '\ud83c\udde6\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + uk: { + keywords: [ "united", "kingdom", "great", "britain", "northern", "ireland", "flag", "nation", "country", "banner", "british", "UK", "english", "england", "union jack" ], + "char": '\ud83c\uddec\ud83c\udde7', + fitzpatrick_scale: false, + category: "flags" + }, + england: { + keywords: [ "flag", "english" ], + "char": '\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f', + fitzpatrick_scale: false, + category: "flags" + }, + scotland: { + keywords: [ "flag", "scottish" ], + "char": '\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f', + fitzpatrick_scale: false, + category: "flags" + }, + wales: { + keywords: [ "flag", "welsh" ], + "char": '\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f', + fitzpatrick_scale: false, + category: "flags" + }, + us: { + keywords: [ "united", "states", "america", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfa\ud83c\uddf8', + fitzpatrick_scale: false, + category: "flags" + }, + us_virgin_islands: { + keywords: [ "virgin", "islands", "us", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfb\ud83c\uddee', + fitzpatrick_scale: false, + category: "flags" + }, + uruguay: { + keywords: [ "uy", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfa\ud83c\uddfe', + fitzpatrick_scale: false, + category: "flags" + }, + uzbekistan: { + keywords: [ "uz", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfa\ud83c\uddff', + fitzpatrick_scale: false, + category: "flags" + }, + vanuatu: { + keywords: [ "vu", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfb\ud83c\uddfa', + fitzpatrick_scale: false, + category: "flags" + }, + vatican_city: { + keywords: [ "vatican", "city", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfb\ud83c\udde6', + fitzpatrick_scale: false, + category: "flags" + }, + venezuela: { + keywords: [ "ve", "bolivarian", "republic", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfb\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + vietnam: { + keywords: [ "viet", "nam", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfb\ud83c\uddf3', + fitzpatrick_scale: false, + category: "flags" + }, + wallis_futuna: { + keywords: [ "wallis", "futuna", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfc\ud83c\uddeb', + fitzpatrick_scale: false, + category: "flags" + }, + western_sahara: { + keywords: [ "western", "sahara", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddea\ud83c\udded', + fitzpatrick_scale: false, + category: "flags" + }, + yemen: { + keywords: [ "ye", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddfe\ud83c\uddea', + fitzpatrick_scale: false, + category: "flags" + }, + zambia: { + keywords: [ "zm", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddff\ud83c\uddf2', + fitzpatrick_scale: false, + category: "flags" + }, + zimbabwe: { + keywords: [ "zw", "flag", "nation", "country", "banner" ], + "char": '\ud83c\uddff\ud83c\uddfc', + fitzpatrick_scale: false, + category: "flags" + }, + united_nations: { + keywords: [ "un", "flag", "banner" ], + "char": '\ud83c\uddfa\ud83c\uddf3', + fitzpatrick_scale: false, + category: "flags" + }, + pirate_flag: { + keywords: [ "skull", "crossbones", "flag", "banner" ], + "char": '\ud83c\udff4\u200d\u2620\ufe0f', + fitzpatrick_scale: false, + category: "flags" + } +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/js/emojiimages.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/js/emojiimages.min.js new file mode 100644 index 0000000000000000000000000000000000000000..1bc8d72d61228f5541e3d1256c359da0717184ec --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/js/emojiimages.min.js @@ -0,0 +1,3 @@ +// Source: npm package: emojilib +// Images provided by twemoji: https://github.com/twitter/twemoji +window.tinymce.Resource.add("tinymce.plugins.emoticons",{100:{keywords:["score","perfect","numbers","century","exam","quiz","test","pass","hundred"],"char":'\ud83d\udcaf',fitzpatrick_scale:!1,category:"symbols"},1234:{keywords:["numbers","blue-square"],"char":'\ud83d\udd22',fitzpatrick_scale:!1,category:"symbols"},grinning:{keywords:["face","smile","happy","joy",":D","grin"],"char":'\ud83d\ude00',fitzpatrick_scale:!1,category:"people"},grimacing:{keywords:["face","grimace","teeth"],"char":'\ud83d\ude2c',fitzpatrick_scale:!1,category:"people"},grin:{keywords:["face","happy","smile","joy","kawaii"],"char":'\ud83d\ude01',fitzpatrick_scale:!1,category:"people"},joy:{keywords:["face","cry","tears","weep","happy","happytears","haha"],"char":'\ud83d\ude02',fitzpatrick_scale:!1,category:"people"},rofl:{keywords:["face","rolling","floor","laughing","lol","haha"],"char":'\ud83e\udd23',fitzpatrick_scale:!1,category:"people"},partying:{keywords:["face","celebration","woohoo"],"char":'\ud83e\udd73',fitzpatrick_scale:!1,category:"people"},smiley:{keywords:["face","happy","joy","haha",":D",":)","smile","funny"],"char":'\ud83d\ude03',fitzpatrick_scale:!1,category:"people"},smile:{keywords:["face","happy","joy","funny","haha","laugh","like",":D",":)"],"char":'\ud83d\ude04',fitzpatrick_scale:!1,category:"people"},sweat_smile:{keywords:["face","hot","happy","laugh","sweat","smile","relief"],"char":'\ud83d\ude05',fitzpatrick_scale:!1,category:"people"},laughing:{keywords:["happy","joy","lol","satisfied","haha","face","glad","XD","laugh"],"char":'\ud83d\ude06',fitzpatrick_scale:!1,category:"people"},innocent:{keywords:["face","angel","heaven","halo"],"char":'\ud83d\ude07',fitzpatrick_scale:!1,category:"people"},wink:{keywords:["face","happy","mischievous","secret",";)","smile","eye"],"char":'\ud83d\ude09',fitzpatrick_scale:!1,category:"people"},blush:{keywords:["face","smile","happy","flushed","crush","embarrassed","shy","joy"],"char":'\ud83d\ude0a',fitzpatrick_scale:!1,category:"people"},slightly_smiling_face:{keywords:["face","smile"],"char":'\ud83d\ude42',fitzpatrick_scale:!1,category:"people"},upside_down_face:{keywords:["face","flipped","silly","smile"],"char":'\ud83d\ude43',fitzpatrick_scale:!1,category:"people"},relaxed:{keywords:["face","blush","massage","happiness"],"char":'\u263a\ufe0f',fitzpatrick_scale:!1,category:"people"},yum:{keywords:["happy","joy","tongue","smile","face","silly","yummy","nom","delicious","savouring"],"char":'\ud83d\ude0b',fitzpatrick_scale:!1,category:"people"},relieved:{keywords:["face","relaxed","phew","massage","happiness"],"char":'\ud83d\ude0c',fitzpatrick_scale:!1,category:"people"},heart_eyes:{keywords:["face","love","like","affection","valentines","infatuation","crush","heart"],"char":'\ud83d\ude0d',fitzpatrick_scale:!1,category:"people"},smiling_face_with_three_hearts:{keywords:["face","love","like","affection","valentines","infatuation","crush","hearts","adore"],"char":'\ud83e\udd70',fitzpatrick_scale:!1,category:"people"},kissing_heart:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],"char":'\ud83d\ude18',fitzpatrick_scale:!1,category:"people"},kissing:{keywords:["love","like","face","3","valentines","infatuation","kiss"],"char":'\ud83d\ude17',fitzpatrick_scale:!1,category:"people"},kissing_smiling_eyes:{keywords:["face","affection","valentines","infatuation","kiss"],"char":'\ud83d\ude19',fitzpatrick_scale:!1,category:"people"},kissing_closed_eyes:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],"char":'\ud83d\ude1a',fitzpatrick_scale:!1,category:"people"},stuck_out_tongue_winking_eye:{keywords:["face","prank","childish","playful","mischievous","smile","wink","tongue"],"char":'\ud83d\ude1c',fitzpatrick_scale:!1,category:"people"},zany:{keywords:["face","goofy","crazy"],"char":'\ud83e\udd2a',fitzpatrick_scale:!1,category:"people"},raised_eyebrow:{keywords:["face","distrust","scepticism","disapproval","disbelief","surprise"],"char":'\ud83e\udd28',fitzpatrick_scale:!1,category:"people"},monocle:{keywords:["face","stuffy","wealthy"],"char":'\ud83e\uddd0',fitzpatrick_scale:!1,category:"people"},stuck_out_tongue_closed_eyes:{keywords:["face","prank","playful","mischievous","smile","tongue"],"char":'\ud83d\ude1d',fitzpatrick_scale:!1,category:"people"},stuck_out_tongue:{keywords:["face","prank","childish","playful","mischievous","smile","tongue"],"char":'\ud83d\ude1b',fitzpatrick_scale:!1,category:"people"},money_mouth_face:{keywords:["face","rich","dollar","money"],"char":'\ud83e\udd11',fitzpatrick_scale:!1,category:"people"},nerd_face:{keywords:["face","nerdy","geek","dork"],"char":'\ud83e\udd13',fitzpatrick_scale:!1,category:"people"},sunglasses:{keywords:["face","cool","smile","summer","beach","sunglass"],"char":'\ud83d\ude0e',fitzpatrick_scale:!1,category:"people"},star_struck:{keywords:["face","smile","starry","eyes","grinning"],"char":'\ud83e\udd29',fitzpatrick_scale:!1,category:"people"},clown_face:{keywords:["face"],"char":'\ud83e\udd21',fitzpatrick_scale:!1,category:"people"},cowboy_hat_face:{keywords:["face","cowgirl","hat"],"char":'\ud83e\udd20',fitzpatrick_scale:!1,category:"people"},hugs:{keywords:["face","smile","hug"],"char":'\ud83e\udd17',fitzpatrick_scale:!1,category:"people"},smirk:{keywords:["face","smile","mean","prank","smug","sarcasm"],"char":'\ud83d\ude0f',fitzpatrick_scale:!1,category:"people"},no_mouth:{keywords:["face","hellokitty"],"char":'\ud83d\ude36',fitzpatrick_scale:!1,category:"people"},neutral_face:{keywords:["indifference","meh",":|","neutral"],"char":'\ud83d\ude10',fitzpatrick_scale:!1,category:"people"},expressionless:{keywords:["face","indifferent","-_-","meh","deadpan"],"char":'\ud83d\ude11',fitzpatrick_scale:!1,category:"people"},unamused:{keywords:["indifference","bored","straight face","serious","sarcasm","unimpressed","skeptical","dubious","side_eye"],"char":'\ud83d\ude12',fitzpatrick_scale:!1,category:"people"},roll_eyes:{keywords:["face","eyeroll","frustrated"],"char":'\ud83d\ude44',fitzpatrick_scale:!1,category:"people"},thinking:{keywords:["face","hmmm","think","consider"],"char":'\ud83e\udd14',fitzpatrick_scale:!1,category:"people"},lying_face:{keywords:["face","lie","pinocchio"],"char":'\ud83e\udd25',fitzpatrick_scale:!1,category:"people"},hand_over_mouth:{keywords:["face","whoops","shock","surprise"],"char":'\ud83e\udd2d',fitzpatrick_scale:!1,category:"people"},shushing:{keywords:["face","quiet","shhh"],"char":'\ud83e\udd2b',fitzpatrick_scale:!1,category:"people"},symbols_over_mouth:{keywords:["face","swearing","cursing","cussing","profanity","expletive"],"char":'\ud83e\udd2c',fitzpatrick_scale:!1,category:"people"},exploding_head:{keywords:["face","shocked","mind","blown"],"char":'\ud83e\udd2f',fitzpatrick_scale:!1,category:"people"},flushed:{keywords:["face","blush","shy","flattered"],"char":'\ud83d\ude33',fitzpatrick_scale:!1,category:"people"},disappointed:{keywords:["face","sad","upset","depressed",":("],"char":'\ud83d\ude1e',fitzpatrick_scale:!1,category:"people"},worried:{keywords:["face","concern","nervous",":("],"char":'\ud83d\ude1f',fitzpatrick_scale:!1,category:"people"},angry:{keywords:["mad","face","annoyed","frustrated"],"char":'\ud83d\ude20',fitzpatrick_scale:!1,category:"people"},rage:{keywords:["angry","mad","hate","despise"],"char":'\ud83d\ude21',fitzpatrick_scale:!1,category:"people"},pensive:{keywords:["face","sad","depressed","upset"],"char":'\ud83d\ude14',fitzpatrick_scale:!1,category:"people"},confused:{keywords:["face","indifference","huh","weird","hmmm",":/"],"char":'\ud83d\ude15',fitzpatrick_scale:!1,category:"people"},slightly_frowning_face:{keywords:["face","frowning","disappointed","sad","upset"],"char":'\ud83d\ude41',fitzpatrick_scale:!1,category:"people"},frowning_face:{keywords:["face","sad","upset","frown"],"char":'\u2639',fitzpatrick_scale:!1,category:"people"},persevere:{keywords:["face","sick","no","upset","oops"],"char":'\ud83d\ude23',fitzpatrick_scale:!1,category:"people"},confounded:{keywords:["face","confused","sick","unwell","oops",":S"],"char":'\ud83d\ude16',fitzpatrick_scale:!1,category:"people"},tired_face:{keywords:["sick","whine","upset","frustrated"],"char":'\ud83d\ude2b',fitzpatrick_scale:!1,category:"people"},weary:{keywords:["face","tired","sleepy","sad","frustrated","upset"],"char":'\ud83d\ude29',fitzpatrick_scale:!1,category:"people"},pleading:{keywords:["face","begging","mercy"],"char":'\ud83e\udd7a',fitzpatrick_scale:!1,category:"people"},triumph:{keywords:["face","gas","phew","proud","pride"],"char":'\ud83d\ude24',fitzpatrick_scale:!1,category:"people"},open_mouth:{keywords:["face","surprise","impressed","wow","whoa",":O"],"char":'\ud83d\ude2e',fitzpatrick_scale:!1,category:"people"},scream:{keywords:["face","munch","scared","omg"],"char":'\ud83d\ude31',fitzpatrick_scale:!1,category:"people"},fearful:{keywords:["face","scared","terrified","nervous","oops","huh"],"char":'\ud83d\ude28',fitzpatrick_scale:!1,category:"people"},cold_sweat:{keywords:["face","nervous","sweat"],"char":'\ud83d\ude30',fitzpatrick_scale:!1,category:"people"},hushed:{keywords:["face","woo","shh"],"char":'\ud83d\ude2f',fitzpatrick_scale:!1,category:"people"},frowning:{keywords:["face","aw","what"],"char":'\ud83d\ude26',fitzpatrick_scale:!1,category:"people"},anguished:{keywords:["face","stunned","nervous"],"char":'\ud83d\ude27',fitzpatrick_scale:!1,category:"people"},cry:{keywords:["face","tears","sad","depressed","upset",":'("],"char":'\ud83d\ude22',fitzpatrick_scale:!1,category:"people"},disappointed_relieved:{keywords:["face","phew","sweat","nervous"],"char":'\ud83d\ude25',fitzpatrick_scale:!1,category:"people"},drooling_face:{keywords:["face"],"char":'\ud83e\udd24',fitzpatrick_scale:!1,category:"people"},sleepy:{keywords:["face","tired","rest","nap"],"char":'\ud83d\ude2a',fitzpatrick_scale:!1,category:"people"},sweat:{keywords:["face","hot","sad","tired","exercise"],"char":'\ud83d\ude13',fitzpatrick_scale:!1,category:"people"},hot:{keywords:["face","feverish","heat","red","sweating"],"char":'\ud83e\udd75',fitzpatrick_scale:!1,category:"people"},cold:{keywords:["face","blue","freezing","frozen","frostbite","icicles"],"char":'\ud83e\udd76',fitzpatrick_scale:!1,category:"people"},sob:{keywords:["face","cry","tears","sad","upset","depressed"],"char":'\ud83d\ude2d',fitzpatrick_scale:!1,category:"people"},dizzy_face:{keywords:["spent","unconscious","xox","dizzy"],"char":'\ud83d\ude35',fitzpatrick_scale:!1,category:"people"},astonished:{keywords:["face","xox","surprised","poisoned"],"char":'\ud83d\ude32',fitzpatrick_scale:!1,category:"people"},zipper_mouth_face:{keywords:["face","sealed","zipper","secret"],"char":'\ud83e\udd10',fitzpatrick_scale:!1,category:"people"},nauseated_face:{keywords:["face","vomit","gross","green","sick","throw up","ill"],"char":'\ud83e\udd22',fitzpatrick_scale:!1,category:"people"},sneezing_face:{keywords:["face","gesundheit","sneeze","sick","allergy"],"char":'\ud83e\udd27',fitzpatrick_scale:!1,category:"people"},vomiting:{keywords:["face","sick"],"char":'\ud83e\udd2e',fitzpatrick_scale:!1,category:"people"},mask:{keywords:["face","sick","ill","disease"],"char":'\ud83d\ude37',fitzpatrick_scale:!1,category:"people"},face_with_thermometer:{keywords:["sick","temperature","thermometer","cold","fever"],"char":'\ud83e\udd12',fitzpatrick_scale:!1,category:"people"},face_with_head_bandage:{keywords:["injured","clumsy","bandage","hurt"],"char":'\ud83e\udd15',fitzpatrick_scale:!1,category:"people"},woozy:{keywords:["face","dizzy","intoxicated","tipsy","wavy"],"char":'\ud83e\udd74',fitzpatrick_scale:!1,category:"people"},sleeping:{keywords:["face","tired","sleepy","night","zzz"],"char":'\ud83d\ude34',fitzpatrick_scale:!1,category:"people"},zzz:{keywords:["sleepy","tired","dream"],"char":'\ud83d\udca4',fitzpatrick_scale:!1,category:"people"},poop:{keywords:["hankey","shitface","fail","turd","shit"],"char":'\ud83d\udca9',fitzpatrick_scale:!1,category:"people"},smiling_imp:{keywords:["devil","horns"],"char":'\ud83d\ude08',fitzpatrick_scale:!1,category:"people"},imp:{keywords:["devil","angry","horns"],"char":'\ud83d\udc7f',fitzpatrick_scale:!1,category:"people"},japanese_ogre:{keywords:["monster","red","mask","halloween","scary","creepy","devil","demon","japanese","ogre"],"char":'\ud83d\udc79',fitzpatrick_scale:!1,category:"people"},japanese_goblin:{keywords:["red","evil","mask","monster","scary","creepy","japanese","goblin"],"char":'\ud83d\udc7a',fitzpatrick_scale:!1,category:"people"},skull:{keywords:["dead","skeleton","creepy","death"],"char":'\ud83d\udc80',fitzpatrick_scale:!1,category:"people"},ghost:{keywords:["halloween","spooky","scary"],"char":'\ud83d\udc7b',fitzpatrick_scale:!1,category:"people"},alien:{keywords:["UFO","paul","weird","outer_space"],"char":'\ud83d\udc7d',fitzpatrick_scale:!1,category:"people"},robot:{keywords:["computer","machine","bot"],"char":'\ud83e\udd16',fitzpatrick_scale:!1,category:"people"},smiley_cat:{keywords:["animal","cats","happy","smile"],"char":'\ud83d\ude3a',fitzpatrick_scale:!1,category:"people"},smile_cat:{keywords:["animal","cats","smile"],"char":'\ud83d\ude38',fitzpatrick_scale:!1,category:"people"},joy_cat:{keywords:["animal","cats","haha","happy","tears"],"char":'\ud83d\ude39',fitzpatrick_scale:!1,category:"people"},heart_eyes_cat:{keywords:["animal","love","like","affection","cats","valentines","heart"],"char":'\ud83d\ude3b',fitzpatrick_scale:!1,category:"people"},smirk_cat:{keywords:["animal","cats","smirk"],"char":'\ud83d\ude3c',fitzpatrick_scale:!1,category:"people"},kissing_cat:{keywords:["animal","cats","kiss"],"char":'\ud83d\ude3d',fitzpatrick_scale:!1,category:"people"},scream_cat:{keywords:["animal","cats","munch","scared","scream"],"char":'\ud83d\ude40',fitzpatrick_scale:!1,category:"people"},crying_cat_face:{keywords:["animal","tears","weep","sad","cats","upset","cry"],"char":'\ud83d\ude3f',fitzpatrick_scale:!1,category:"people"},pouting_cat:{keywords:["animal","cats"],"char":'\ud83d\ude3e',fitzpatrick_scale:!1,category:"people"},palms_up:{keywords:["hands","gesture","cupped","prayer"],"char":'\ud83e\udd32',fitzpatrick_scale:!0,category:"people"},raised_hands:{keywords:["gesture","hooray","yea","celebration","hands"],"char":'\ud83d\ude4c',fitzpatrick_scale:!0,category:"people"},clap:{keywords:["hands","praise","applause","congrats","yay"],"char":'\ud83d\udc4f',fitzpatrick_scale:!0,category:"people"},wave:{keywords:["hands","gesture","goodbye","solong","farewell","hello","hi","palm"],"char":'\ud83d\udc4b',fitzpatrick_scale:!0,category:"people"},call_me_hand:{keywords:["hands","gesture"],"char":'\ud83e\udd19',fitzpatrick_scale:!0,category:"people"},"+1":{keywords:["thumbsup","yes","awesome","good","agree","accept","cool","hand","like"],"char":'\ud83d\udc4d',fitzpatrick_scale:!0,category:"people"},"-1":{keywords:["thumbsdown","no","dislike","hand"],"char":'\ud83d\udc4e',fitzpatrick_scale:!0,category:"people"},facepunch:{keywords:["angry","violence","fist","hit","attack","hand"],"char":'\ud83d\udc4a',fitzpatrick_scale:!0,category:"people"},fist:{keywords:["fingers","hand","grasp"],"char":'\u270a',fitzpatrick_scale:!0,category:"people"},fist_left:{keywords:["hand","fistbump"],"char":'\ud83e\udd1b',fitzpatrick_scale:!0,category:"people"},fist_right:{keywords:["hand","fistbump"],"char":'\ud83e\udd1c',fitzpatrick_scale:!0,category:"people"},v:{keywords:["fingers","ohyeah","hand","peace","victory","two"],"char":'\u270c',fitzpatrick_scale:!0,category:"people"},ok_hand:{keywords:["fingers","limbs","perfect","ok","okay"],"char":'\ud83d\udc4c',fitzpatrick_scale:!0,category:"people"},raised_hand:{keywords:["fingers","stop","highfive","palm","ban"],"char":'\u270b',fitzpatrick_scale:!0,category:"people"},raised_back_of_hand:{keywords:["fingers","raised","backhand"],"char":'\ud83e\udd1a',fitzpatrick_scale:!0,category:"people"},open_hands:{keywords:["fingers","butterfly","hands","open"],"char":'\ud83d\udc50',fitzpatrick_scale:!0,category:"people"},muscle:{keywords:["arm","flex","hand","summer","strong","biceps"],"char":'\ud83d\udcaa',fitzpatrick_scale:!0,category:"people"},pray:{keywords:["please","hope","wish","namaste","highfive"],"char":'\ud83d\ude4f',fitzpatrick_scale:!0,category:"people"},foot:{keywords:["kick","stomp"],"char":'\ud83e\uddb6',fitzpatrick_scale:!0,category:"people"},leg:{keywords:["kick","limb"],"char":'\ud83e\uddb5',fitzpatrick_scale:!0,category:"people"},handshake:{keywords:["agreement","shake"],"char":'\ud83e\udd1d',fitzpatrick_scale:!1,category:"people"},point_up:{keywords:["hand","fingers","direction","up"],"char":'\u261d',fitzpatrick_scale:!0,category:"people"},point_up_2:{keywords:["fingers","hand","direction","up"],"char":'\ud83d\udc46',fitzpatrick_scale:!0,category:"people"},point_down:{keywords:["fingers","hand","direction","down"],"char":'\ud83d\udc47',fitzpatrick_scale:!0,category:"people"},point_left:{keywords:["direction","fingers","hand","left"],"char":'\ud83d\udc48',fitzpatrick_scale:!0,category:"people"},point_right:{keywords:["fingers","hand","direction","right"],"char":'\ud83d\udc49',fitzpatrick_scale:!0,category:"people"},fu:{keywords:["hand","fingers","rude","middle","flipping"],"char":'\ud83d\udd95',fitzpatrick_scale:!0,category:"people"},raised_hand_with_fingers_splayed:{keywords:["hand","fingers","palm"],"char":'\ud83d\udd90',fitzpatrick_scale:!0,category:"people"},love_you:{keywords:["hand","fingers","gesture"],"char":'\ud83e\udd1f',fitzpatrick_scale:!0,category:"people"},metal:{keywords:["hand","fingers","evil_eye","sign_of_horns","rock_on"],"char":'\ud83e\udd18',fitzpatrick_scale:!0,category:"people"},crossed_fingers:{keywords:["good","lucky"],"char":'\ud83e\udd1e',fitzpatrick_scale:!0,category:"people"},vulcan_salute:{keywords:["hand","fingers","spock","star trek"],"char":'\ud83d\udd96',fitzpatrick_scale:!0,category:"people"},writing_hand:{keywords:["lower_left_ballpoint_pen","stationery","write","compose"],"char":'\u270d',fitzpatrick_scale:!0,category:"people"},selfie:{keywords:["camera","phone"],"char":'\ud83e\udd33',fitzpatrick_scale:!0,category:"people"},nail_care:{keywords:["beauty","manicure","finger","fashion","nail"],"char":'\ud83d\udc85',fitzpatrick_scale:!0,category:"people"},lips:{keywords:["mouth","kiss"],"char":'\ud83d\udc44',fitzpatrick_scale:!1,category:"people"},tooth:{keywords:["teeth","dentist"],"char":'\ud83e\uddb7',fitzpatrick_scale:!1,category:"people"},tongue:{keywords:["mouth","playful"],"char":'\ud83d\udc45',fitzpatrick_scale:!1,category:"people"},ear:{keywords:["face","hear","sound","listen"],"char":'\ud83d\udc42',fitzpatrick_scale:!0,category:"people"},nose:{keywords:["smell","sniff"],"char":'\ud83d\udc43',fitzpatrick_scale:!0,category:"people"},eye:{keywords:["face","look","see","watch","stare"],"char":'\ud83d\udc41',fitzpatrick_scale:!1,category:"people"},eyes:{keywords:["look","watch","stalk","peek","see"],"char":'\ud83d\udc40',fitzpatrick_scale:!1,category:"people"},brain:{keywords:["smart","intelligent"],"char":'\ud83e\udde0',fitzpatrick_scale:!1,category:"people"},bust_in_silhouette:{keywords:["user","person","human"],"char":'\ud83d\udc64',fitzpatrick_scale:!1,category:"people"},busts_in_silhouette:{keywords:["user","person","human","group","team"],"char":'\ud83d\udc65',fitzpatrick_scale:!1,category:"people"},speaking_head:{keywords:["user","person","human","sing","say","talk"],"char":'\ud83d\udde3',fitzpatrick_scale:!1,category:"people"},baby:{keywords:["child","boy","girl","toddler"],"char":'\ud83d\udc76',fitzpatrick_scale:!0,category:"people"},child:{keywords:["gender-neutral","young"],"char":'\ud83e\uddd2',fitzpatrick_scale:!0,category:"people"},boy:{keywords:["man","male","guy","teenager"],"char":'\ud83d\udc66',fitzpatrick_scale:!0,category:"people"},girl:{keywords:["female","woman","teenager"],"char":'\ud83d\udc67',fitzpatrick_scale:!0,category:"people"},adult:{keywords:["gender-neutral","person"],"char":'\ud83e\uddd1',fitzpatrick_scale:!0,category:"people"},man:{keywords:["mustache","father","dad","guy","classy","sir","moustache"],"char":'\ud83d\udc68',fitzpatrick_scale:!0,category:"people"},woman:{keywords:["female","girls","lady"],"char":'\ud83d\udc69',fitzpatrick_scale:!0,category:"people"},blonde_woman:{keywords:["woman","female","girl","blonde","person"],"char":'\ud83d\udc71\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},blonde_man:{keywords:["man","male","boy","blonde","guy","person"],"char":'\ud83d\udc71',fitzpatrick_scale:!0,category:"people"},bearded_person:{keywords:["person","bewhiskered"],"char":'\ud83e\uddd4',fitzpatrick_scale:!0,category:"people"},older_adult:{keywords:["human","elder","senior","gender-neutral"],"char":'\ud83e\uddd3',fitzpatrick_scale:!0,category:"people"},older_man:{keywords:["human","male","men","old","elder","senior"],"char":'\ud83d\udc74',fitzpatrick_scale:!0,category:"people"},older_woman:{keywords:["human","female","women","lady","old","elder","senior"],"char":'\ud83d\udc75',fitzpatrick_scale:!0,category:"people"},man_with_gua_pi_mao:{keywords:["male","boy","chinese"],"char":'\ud83d\udc72',fitzpatrick_scale:!0,category:"people"},woman_with_headscarf:{keywords:["female","hijab","mantilla","tichel"],"char":'\ud83e\uddd5',fitzpatrick_scale:!0,category:"people"},woman_with_turban:{keywords:["female","indian","hinduism","arabs","woman"],"char":'\ud83d\udc73\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_with_turban:{keywords:["male","indian","hinduism","arabs"],"char":'\ud83d\udc73',fitzpatrick_scale:!0,category:"people"},policewoman:{keywords:["woman","police","law","legal","enforcement","arrest","911","female"],"char":'\ud83d\udc6e\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},policeman:{keywords:["man","police","law","legal","enforcement","arrest","911"],"char":'\ud83d\udc6e',fitzpatrick_scale:!0,category:"people"},construction_worker_woman:{keywords:["female","human","wip","build","construction","worker","labor","woman"],"char":'\ud83d\udc77\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},construction_worker_man:{keywords:["male","human","wip","guy","build","construction","worker","labor"],"char":'\ud83d\udc77',fitzpatrick_scale:!0,category:"people"},guardswoman:{keywords:["uk","gb","british","female","royal","woman"],"char":'\ud83d\udc82\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},guardsman:{keywords:["uk","gb","british","male","guy","royal"],"char":'\ud83d\udc82',fitzpatrick_scale:!0,category:"people"},female_detective:{keywords:["human","spy","detective","female","woman"],"char":'\ud83d\udd75\ufe0f\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},male_detective:{keywords:["human","spy","detective"],"char":'\ud83d\udd75',fitzpatrick_scale:!0,category:"people"},woman_health_worker:{keywords:["doctor","nurse","therapist","healthcare","woman","human"],"char":'\ud83d\udc69\u200d\u2695\ufe0f',fitzpatrick_scale:!0,category:"people"},man_health_worker:{keywords:["doctor","nurse","therapist","healthcare","man","human"],"char":'\ud83d\udc68\u200d\u2695\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_farmer:{keywords:["rancher","gardener","woman","human"],"char":'\ud83d\udc69\u200d\ud83c\udf3e',fitzpatrick_scale:!0,category:"people"},man_farmer:{keywords:["rancher","gardener","man","human"],"char":'\ud83d\udc68\u200d\ud83c\udf3e',fitzpatrick_scale:!0,category:"people"},woman_cook:{keywords:["chef","woman","human"],"char":'\ud83d\udc69\u200d\ud83c\udf73',fitzpatrick_scale:!0,category:"people"},man_cook:{keywords:["chef","man","human"],"char":'\ud83d\udc68\u200d\ud83c\udf73',fitzpatrick_scale:!0,category:"people"},woman_student:{keywords:["graduate","woman","human"],"char":'\ud83d\udc69\u200d\ud83c\udf93',fitzpatrick_scale:!0,category:"people"},man_student:{keywords:["graduate","man","human"],"char":'\ud83d\udc68\u200d\ud83c\udf93',fitzpatrick_scale:!0,category:"people"},woman_singer:{keywords:["rockstar","entertainer","woman","human"],"char":'\ud83d\udc69\u200d\ud83c\udfa4',fitzpatrick_scale:!0,category:"people"},man_singer:{keywords:["rockstar","entertainer","man","human"],"char":'\ud83d\udc68\u200d\ud83c\udfa4',fitzpatrick_scale:!0,category:"people"},woman_teacher:{keywords:["instructor","professor","woman","human"],"char":'\ud83d\udc69\u200d\ud83c\udfeb',fitzpatrick_scale:!0,category:"people"},man_teacher:{keywords:["instructor","professor","man","human"],"char":'\ud83d\udc68\u200d\ud83c\udfeb',fitzpatrick_scale:!0,category:"people"},woman_factory_worker:{keywords:["assembly","industrial","woman","human"],"char":'\ud83d\udc69\u200d\ud83c\udfed',fitzpatrick_scale:!0,category:"people"},man_factory_worker:{keywords:["assembly","industrial","man","human"],"char":'\ud83d\udc68\u200d\ud83c\udfed',fitzpatrick_scale:!0,category:"people"},woman_technologist:{keywords:["coder","developer","engineer","programmer","software","woman","human","laptop","computer"],"char":'\ud83d\udc69\u200d\ud83d\udcbb',fitzpatrick_scale:!0,category:"people"},man_technologist:{keywords:["coder","developer","engineer","programmer","software","man","human","laptop","computer"],"char":'\ud83d\udc68\u200d\ud83d\udcbb',fitzpatrick_scale:!0,category:"people"},woman_office_worker:{keywords:["business","manager","woman","human"],"char":'\ud83d\udc69\u200d\ud83d\udcbc',fitzpatrick_scale:!0,category:"people"},man_office_worker:{keywords:["business","manager","man","human"],"char":'\ud83d\udc68\u200d\ud83d\udcbc',fitzpatrick_scale:!0,category:"people"},woman_mechanic:{keywords:["plumber","woman","human","wrench"],"char":'\ud83d\udc69\u200d\ud83d\udd27',fitzpatrick_scale:!0,category:"people"},man_mechanic:{keywords:["plumber","man","human","wrench"],"char":'\ud83d\udc68\u200d\ud83d\udd27',fitzpatrick_scale:!0,category:"people"},woman_scientist:{keywords:["biologist","chemist","engineer","physicist","woman","human"],"char":'\ud83d\udc69\u200d\ud83d\udd2c',fitzpatrick_scale:!0,category:"people"},man_scientist:{keywords:["biologist","chemist","engineer","physicist","man","human"],"char":'\ud83d\udc68\u200d\ud83d\udd2c',fitzpatrick_scale:!0,category:"people"},woman_artist:{keywords:["painter","woman","human"],"char":'\ud83d\udc69\u200d\ud83c\udfa8',fitzpatrick_scale:!0,category:"people"},man_artist:{keywords:["painter","man","human"],"char":'\ud83d\udc68\u200d\ud83c\udfa8',fitzpatrick_scale:!0,category:"people"},woman_firefighter:{keywords:["fireman","woman","human"],"char":'\ud83d\udc69\u200d\ud83d\ude92',fitzpatrick_scale:!0,category:"people"},man_firefighter:{keywords:["fireman","man","human"],"char":'\ud83d\udc68\u200d\ud83d\ude92',fitzpatrick_scale:!0,category:"people"},woman_pilot:{keywords:["aviator","plane","woman","human"],"char":'\ud83d\udc69\u200d\u2708\ufe0f',fitzpatrick_scale:!0,category:"people"},man_pilot:{keywords:["aviator","plane","man","human"],"char":'\ud83d\udc68\u200d\u2708\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_astronaut:{keywords:["space","rocket","woman","human"],"char":'\ud83d\udc69\u200d\ud83d\ude80',fitzpatrick_scale:!0,category:"people"},man_astronaut:{keywords:["space","rocket","man","human"],"char":'\ud83d\udc68\u200d\ud83d\ude80',fitzpatrick_scale:!0,category:"people"},woman_judge:{keywords:["justice","court","woman","human"],"char":'\ud83d\udc69\u200d\u2696\ufe0f',fitzpatrick_scale:!0,category:"people"},man_judge:{keywords:["justice","court","man","human"],"char":'\ud83d\udc68\u200d\u2696\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_superhero:{keywords:["woman","female","good","heroine","superpowers"],"char":'\ud83e\uddb8\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_superhero:{keywords:["man","male","good","hero","superpowers"],"char":'\ud83e\uddb8\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_supervillain:{keywords:["woman","female","evil","bad","criminal","heroine","superpowers"],"char":'\ud83e\uddb9\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_supervillain:{keywords:["man","male","evil","bad","criminal","hero","superpowers"],"char":'\ud83e\uddb9\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},mrs_claus:{keywords:["woman","female","xmas","mother christmas"],"char":'\ud83e\udd36',fitzpatrick_scale:!0,category:"people"},santa:{keywords:["festival","man","male","xmas","father christmas"],"char":'\ud83c\udf85',fitzpatrick_scale:!0,category:"people"},sorceress:{keywords:["woman","female","mage","witch"],"char":'\ud83e\uddd9\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},wizard:{keywords:["man","male","mage","sorcerer"],"char":'\ud83e\uddd9\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_elf:{keywords:["woman","female"],"char":'\ud83e\udddd\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_elf:{keywords:["man","male"],"char":'\ud83e\udddd\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_vampire:{keywords:["woman","female"],"char":'\ud83e\udddb\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_vampire:{keywords:["man","male","dracula"],"char":'\ud83e\udddb\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_zombie:{keywords:["woman","female","undead","walking dead"],"char":'\ud83e\udddf\u200d\u2640\ufe0f',fitzpatrick_scale:!1,category:"people"},man_zombie:{keywords:["man","male","dracula","undead","walking dead"],"char":'\ud83e\udddf\u200d\u2642\ufe0f',fitzpatrick_scale:!1,category:"people"},woman_genie:{keywords:["woman","female"],"char":'\ud83e\uddde\u200d\u2640\ufe0f',fitzpatrick_scale:!1,category:"people"},man_genie:{keywords:["man","male"],"char":'\ud83e\uddde\u200d\u2642\ufe0f',fitzpatrick_scale:!1,category:"people"},mermaid:{keywords:["woman","female","merwoman","ariel"],"char":'\ud83e\udddc\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},merman:{keywords:["man","male","triton"],"char":'\ud83e\udddc\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_fairy:{keywords:["woman","female"],"char":'\ud83e\uddda\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_fairy:{keywords:["man","male"],"char":'\ud83e\uddda\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},angel:{keywords:["heaven","wings","halo"],"char":'\ud83d\udc7c',fitzpatrick_scale:!0,category:"people"},pregnant_woman:{keywords:["baby"],"char":'\ud83e\udd30',fitzpatrick_scale:!0,category:"people"},breastfeeding:{keywords:["nursing","baby"],"char":'\ud83e\udd31',fitzpatrick_scale:!0,category:"people"},princess:{keywords:["girl","woman","female","blond","crown","royal","queen"],"char":'\ud83d\udc78',fitzpatrick_scale:!0,category:"people"},prince:{keywords:["boy","man","male","crown","royal","king"],"char":'\ud83e\udd34',fitzpatrick_scale:!0,category:"people"},bride_with_veil:{keywords:["couple","marriage","wedding","woman","bride"],"char":'\ud83d\udc70',fitzpatrick_scale:!0,category:"people"},man_in_tuxedo:{keywords:["couple","marriage","wedding","groom"],"char":'\ud83e\udd35',fitzpatrick_scale:!0,category:"people"},running_woman:{keywords:["woman","walking","exercise","race","running","female"],"char":'\ud83c\udfc3\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},running_man:{keywords:["man","walking","exercise","race","running"],"char":'\ud83c\udfc3',fitzpatrick_scale:!0,category:"people"},walking_woman:{keywords:["human","feet","steps","woman","female"],"char":'\ud83d\udeb6\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},walking_man:{keywords:["human","feet","steps"],"char":'\ud83d\udeb6',fitzpatrick_scale:!0,category:"people"},dancer:{keywords:["female","girl","woman","fun"],"char":'\ud83d\udc83',fitzpatrick_scale:!0,category:"people"},man_dancing:{keywords:["male","boy","fun","dancer"],"char":'\ud83d\udd7a',fitzpatrick_scale:!0,category:"people"},dancing_women:{keywords:["female","bunny","women","girls"],"char":'\ud83d\udc6f',fitzpatrick_scale:!1,category:"people"},dancing_men:{keywords:["male","bunny","men","boys"],"char":'\ud83d\udc6f\u200d\u2642\ufe0f',fitzpatrick_scale:!1,category:"people"},couple:{keywords:["pair","people","human","love","date","dating","like","affection","valentines","marriage"],"char":'\ud83d\udc6b',fitzpatrick_scale:!1,category:"people"},two_men_holding_hands:{keywords:["pair","couple","love","like","bromance","friendship","people","human"],"char":'\ud83d\udc6c',fitzpatrick_scale:!1,category:"people"},two_women_holding_hands:{keywords:["pair","friendship","couple","love","like","female","people","human"],"char":'\ud83d\udc6d',fitzpatrick_scale:!1,category:"people"},bowing_woman:{keywords:["woman","female","girl"],"char":'\ud83d\ude47\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},bowing_man:{keywords:["man","male","boy"],"char":'\ud83d\ude47',fitzpatrick_scale:!0,category:"people"},man_facepalming:{keywords:["man","male","boy","disbelief"],"char":'\ud83e\udd26\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_facepalming:{keywords:["woman","female","girl","disbelief"],"char":'\ud83e\udd26\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_shrugging:{keywords:["woman","female","girl","confused","indifferent","doubt"],"char":'\ud83e\udd37',fitzpatrick_scale:!0,category:"people"},man_shrugging:{keywords:["man","male","boy","confused","indifferent","doubt"],"char":'\ud83e\udd37\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},tipping_hand_woman:{keywords:["female","girl","woman","human","information"],"char":'\ud83d\udc81',fitzpatrick_scale:!0,category:"people"},tipping_hand_man:{keywords:["male","boy","man","human","information"],"char":'\ud83d\udc81\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},no_good_woman:{keywords:["female","girl","woman","nope"],"char":'\ud83d\ude45',fitzpatrick_scale:!0,category:"people"},no_good_man:{keywords:["male","boy","man","nope"],"char":'\ud83d\ude45\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},ok_woman:{keywords:["women","girl","female","pink","human","woman"],"char":'\ud83d\ude46',fitzpatrick_scale:!0,category:"people"},ok_man:{keywords:["men","boy","male","blue","human","man"],"char":'\ud83d\ude46\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},raising_hand_woman:{keywords:["female","girl","woman"],"char":'\ud83d\ude4b',fitzpatrick_scale:!0,category:"people"},raising_hand_man:{keywords:["male","boy","man"],"char":'\ud83d\ude4b\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},pouting_woman:{keywords:["female","girl","woman"],"char":'\ud83d\ude4e',fitzpatrick_scale:!0,category:"people"},pouting_man:{keywords:["male","boy","man"],"char":'\ud83d\ude4e\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},frowning_woman:{keywords:["female","girl","woman","sad","depressed","discouraged","unhappy"],"char":'\ud83d\ude4d',fitzpatrick_scale:!0,category:"people"},frowning_man:{keywords:["male","boy","man","sad","depressed","discouraged","unhappy"],"char":'\ud83d\ude4d\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},haircut_woman:{keywords:["female","girl","woman"],"char":'\ud83d\udc87',fitzpatrick_scale:!0,category:"people"},haircut_man:{keywords:["male","boy","man"],"char":'\ud83d\udc87\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},massage_woman:{keywords:["female","girl","woman","head"],"char":'\ud83d\udc86',fitzpatrick_scale:!0,category:"people"},massage_man:{keywords:["male","boy","man","head"],"char":'\ud83d\udc86\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_in_steamy_room:{keywords:["female","woman","spa","steamroom","sauna"],"char":'\ud83e\uddd6\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_in_steamy_room:{keywords:["male","man","spa","steamroom","sauna"],"char":'\ud83e\uddd6\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},couple_with_heart_woman_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],"char":'\ud83d\udc91',fitzpatrick_scale:!1,category:"people"},couple_with_heart_woman_woman:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],"char":'\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc69',fitzpatrick_scale:!1,category:"people"},couple_with_heart_man_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],"char":'\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68',fitzpatrick_scale:!1,category:"people"},couplekiss_man_woman:{keywords:["pair","valentines","love","like","dating","marriage"],"char":'\ud83d\udc8f',fitzpatrick_scale:!1,category:"people"},couplekiss_woman_woman:{keywords:["pair","valentines","love","like","dating","marriage"],"char":'\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69',fitzpatrick_scale:!1,category:"people"},couplekiss_man_man:{keywords:["pair","valentines","love","like","dating","marriage"],"char":'\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68',fitzpatrick_scale:!1,category:"people"},family_man_woman_boy:{keywords:["home","parents","child","mom","dad","father","mother","people","human"],"char":'\ud83d\udc6a',fitzpatrick_scale:!1,category:"people"},family_man_woman_girl:{keywords:["home","parents","people","human","child"],"char":'\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67',fitzpatrick_scale:!1,category:"people"},family_man_woman_girl_boy:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_man_woman_boy_boy:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_man_woman_girl_girl:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67',fitzpatrick_scale:!1,category:"people"},family_woman_woman_boy:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67',fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl_boy:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_woman_woman_boy_boy:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl_girl:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67',fitzpatrick_scale:!1,category:"people"},family_man_man_boy:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_man_man_girl:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67',fitzpatrick_scale:!1,category:"people"},family_man_man_girl_boy:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_man_man_boy_boy:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_man_man_girl_girl:{keywords:["home","parents","people","human","children"],"char":'\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67',fitzpatrick_scale:!1,category:"people"},family_woman_boy:{keywords:["home","parent","people","human","child"],"char":'\ud83d\udc69\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_woman_girl:{keywords:["home","parent","people","human","child"],"char":'\ud83d\udc69\u200d\ud83d\udc67',fitzpatrick_scale:!1,category:"people"},family_woman_girl_boy:{keywords:["home","parent","people","human","children"],"char":'\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_woman_boy_boy:{keywords:["home","parent","people","human","children"],"char":'\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_woman_girl_girl:{keywords:["home","parent","people","human","children"],"char":'\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67',fitzpatrick_scale:!1,category:"people"},family_man_boy:{keywords:["home","parent","people","human","child"],"char":'\ud83d\udc68\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_man_girl:{keywords:["home","parent","people","human","child"],"char":'\ud83d\udc68\u200d\ud83d\udc67',fitzpatrick_scale:!1,category:"people"},family_man_girl_boy:{keywords:["home","parent","people","human","children"],"char":'\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_man_boy_boy:{keywords:["home","parent","people","human","children"],"char":'\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66',fitzpatrick_scale:!1,category:"people"},family_man_girl_girl:{keywords:["home","parent","people","human","children"],"char":'\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67',fitzpatrick_scale:!1,category:"people"},yarn:{keywords:["ball","crochet","knit"],"char":'\ud83e\uddf6',fitzpatrick_scale:!1,category:"people"},thread:{keywords:["needle","sewing","spool","string"],"char":'\ud83e\uddf5',fitzpatrick_scale:!1,category:"people"},coat:{keywords:["jacket"],"char":'\ud83e\udde5',fitzpatrick_scale:!1,category:"people"},labcoat:{keywords:["doctor","experiment","scientist","chemist"],"char":'\ud83e\udd7c',fitzpatrick_scale:!1,category:"people"},womans_clothes:{keywords:["fashion","shopping_bags","female"],"char":'\ud83d\udc5a',fitzpatrick_scale:!1,category:"people"},tshirt:{keywords:["fashion","cloth","casual","shirt","tee"],"char":'\ud83d\udc55',fitzpatrick_scale:!1,category:"people"},jeans:{keywords:["fashion","shopping"],"char":'\ud83d\udc56',fitzpatrick_scale:!1,category:"people"},necktie:{keywords:["shirt","suitup","formal","fashion","cloth","business"],"char":'\ud83d\udc54',fitzpatrick_scale:!1,category:"people"},dress:{keywords:["clothes","fashion","shopping"],"char":'\ud83d\udc57',fitzpatrick_scale:!1,category:"people"},bikini:{keywords:["swimming","female","woman","girl","fashion","beach","summer"],"char":'\ud83d\udc59',fitzpatrick_scale:!1,category:"people"},kimono:{keywords:["dress","fashion","women","female","japanese"],"char":'\ud83d\udc58',fitzpatrick_scale:!1,category:"people"},lipstick:{keywords:["female","girl","fashion","woman"],"char":'\ud83d\udc84',fitzpatrick_scale:!1,category:"people"},kiss:{keywords:["face","lips","love","like","affection","valentines"],"char":'\ud83d\udc8b',fitzpatrick_scale:!1,category:"people"},footprints:{keywords:["feet","tracking","walking","beach"],"char":'\ud83d\udc63',fitzpatrick_scale:!1,category:"people"},flat_shoe:{keywords:["ballet","slip-on","slipper"],"char":'\ud83e\udd7f',fitzpatrick_scale:!1,category:"people"},high_heel:{keywords:["fashion","shoes","female","pumps","stiletto"],"char":'\ud83d\udc60',fitzpatrick_scale:!1,category:"people"},sandal:{keywords:["shoes","fashion","flip flops"],"char":'\ud83d\udc61',fitzpatrick_scale:!1,category:"people"},boot:{keywords:["shoes","fashion"],"char":'\ud83d\udc62',fitzpatrick_scale:!1,category:"people"},mans_shoe:{keywords:["fashion","male"],"char":'\ud83d\udc5e',fitzpatrick_scale:!1,category:"people"},athletic_shoe:{keywords:["shoes","sports","sneakers"],"char":'\ud83d\udc5f',fitzpatrick_scale:!1,category:"people"},hiking_boot:{keywords:["backpacking","camping","hiking"],"char":'\ud83e\udd7e',fitzpatrick_scale:!1,category:"people"},socks:{keywords:["stockings","clothes"],"char":'\ud83e\udde6',fitzpatrick_scale:!1,category:"people"},gloves:{keywords:["hands","winter","clothes"],"char":'\ud83e\udde4',fitzpatrick_scale:!1,category:"people"},scarf:{keywords:["neck","winter","clothes"],"char":'\ud83e\udde3',fitzpatrick_scale:!1,category:"people"},womans_hat:{keywords:["fashion","accessories","female","lady","spring"],"char":'\ud83d\udc52',fitzpatrick_scale:!1,category:"people"},tophat:{keywords:["magic","gentleman","classy","circus"],"char":'\ud83c\udfa9',fitzpatrick_scale:!1,category:"people"},billed_hat:{keywords:["cap","baseball"],"char":'\ud83e\udde2',fitzpatrick_scale:!1,category:"people"},rescue_worker_helmet:{keywords:["construction","build"],"char":'\u26d1',fitzpatrick_scale:!1,category:"people"},mortar_board:{keywords:["school","college","degree","university","graduation","cap","hat","legal","learn","education"],"char":'\ud83c\udf93',fitzpatrick_scale:!1,category:"people"},crown:{keywords:["king","kod","leader","royalty","lord"],"char":'\ud83d\udc51',fitzpatrick_scale:!1,category:"people"},school_satchel:{keywords:["student","education","bag","backpack"],"char":'\ud83c\udf92',fitzpatrick_scale:!1,category:"people"},luggage:{keywords:["packing","travel"],"char":'\ud83e\uddf3',fitzpatrick_scale:!1,category:"people"},pouch:{keywords:["bag","accessories","shopping"],"char":'\ud83d\udc5d',fitzpatrick_scale:!1,category:"people"},purse:{keywords:["fashion","accessories","money","sales","shopping"],"char":'\ud83d\udc5b',fitzpatrick_scale:!1,category:"people"},handbag:{keywords:["fashion","accessory","accessories","shopping"],"char":'\ud83d\udc5c',fitzpatrick_scale:!1,category:"people"},briefcase:{keywords:["business","documents","work","law","legal","job","career"],"char":'\ud83d\udcbc',fitzpatrick_scale:!1,category:"people"},eyeglasses:{keywords:["fashion","accessories","eyesight","nerdy","dork","geek"],"char":'\ud83d\udc53',fitzpatrick_scale:!1,category:"people"},dark_sunglasses:{keywords:["face","cool","accessories"],"char":'\ud83d\udd76',fitzpatrick_scale:!1,category:"people"},goggles:{keywords:["eyes","protection","safety"],"char":'\ud83e\udd7d',fitzpatrick_scale:!1,category:"people"},ring:{keywords:["wedding","propose","marriage","valentines","diamond","fashion","jewelry","gem","engagement"],"char":'\ud83d\udc8d',fitzpatrick_scale:!1,category:"people"},closed_umbrella:{keywords:["weather","rain","drizzle"],"char":'\ud83c\udf02',fitzpatrick_scale:!1,category:"people"},dog:{keywords:["animal","friend","nature","woof","puppy","pet","faithful"],"char":'\ud83d\udc36',fitzpatrick_scale:!1,category:"animals_and_nature"},cat:{keywords:["animal","meow","nature","pet","kitten"],"char":'\ud83d\udc31',fitzpatrick_scale:!1,category:"animals_and_nature"},mouse:{keywords:["animal","nature","cheese_wedge","rodent"],"char":'\ud83d\udc2d',fitzpatrick_scale:!1,category:"animals_and_nature"},hamster:{keywords:["animal","nature"],"char":'\ud83d\udc39',fitzpatrick_scale:!1,category:"animals_and_nature"},rabbit:{keywords:["animal","nature","pet","spring","magic","bunny"],"char":'\ud83d\udc30',fitzpatrick_scale:!1,category:"animals_and_nature"},fox_face:{keywords:["animal","nature","face"],"char":'\ud83e\udd8a',fitzpatrick_scale:!1,category:"animals_and_nature"},bear:{keywords:["animal","nature","wild"],"char":'\ud83d\udc3b',fitzpatrick_scale:!1,category:"animals_and_nature"},panda_face:{keywords:["animal","nature","panda"],"char":'\ud83d\udc3c',fitzpatrick_scale:!1,category:"animals_and_nature"},koala:{keywords:["animal","nature"],"char":'\ud83d\udc28',fitzpatrick_scale:!1,category:"animals_and_nature"},tiger:{keywords:["animal","cat","danger","wild","nature","roar"],"char":'\ud83d\udc2f',fitzpatrick_scale:!1,category:"animals_and_nature"},lion:{keywords:["animal","nature"],"char":'\ud83e\udd81',fitzpatrick_scale:!1,category:"animals_and_nature"},cow:{keywords:["beef","ox","animal","nature","moo","milk"],"char":'\ud83d\udc2e',fitzpatrick_scale:!1,category:"animals_and_nature"},pig:{keywords:["animal","oink","nature"],"char":'\ud83d\udc37',fitzpatrick_scale:!1,category:"animals_and_nature"},pig_nose:{keywords:["animal","oink"],"char":'\ud83d\udc3d',fitzpatrick_scale:!1,category:"animals_and_nature"},frog:{keywords:["animal","nature","croak","toad"],"char":'\ud83d\udc38',fitzpatrick_scale:!1,category:"animals_and_nature"},squid:{keywords:["animal","nature","ocean","sea"],"char":'\ud83e\udd91',fitzpatrick_scale:!1,category:"animals_and_nature"},octopus:{keywords:["animal","creature","ocean","sea","nature","beach"],"char":'\ud83d\udc19',fitzpatrick_scale:!1,category:"animals_and_nature"},shrimp:{keywords:["animal","ocean","nature","seafood"],"char":'\ud83e\udd90',fitzpatrick_scale:!1,category:"animals_and_nature"},monkey_face:{keywords:["animal","nature","circus"],"char":'\ud83d\udc35',fitzpatrick_scale:!1,category:"animals_and_nature"},gorilla:{keywords:["animal","nature","circus"],"char":'\ud83e\udd8d',fitzpatrick_scale:!1,category:"animals_and_nature"},see_no_evil:{keywords:["monkey","animal","nature","haha"],"char":'\ud83d\ude48',fitzpatrick_scale:!1,category:"animals_and_nature"},hear_no_evil:{keywords:["animal","monkey","nature"],"char":'\ud83d\ude49',fitzpatrick_scale:!1,category:"animals_and_nature"},speak_no_evil:{keywords:["monkey","animal","nature","omg"],"char":'\ud83d\ude4a',fitzpatrick_scale:!1,category:"animals_and_nature"},monkey:{keywords:["animal","nature","banana","circus"],"char":'\ud83d\udc12',fitzpatrick_scale:!1,category:"animals_and_nature"},chicken:{keywords:["animal","cluck","nature","bird"],"char":'\ud83d\udc14',fitzpatrick_scale:!1,category:"animals_and_nature"},penguin:{keywords:["animal","nature"],"char":'\ud83d\udc27',fitzpatrick_scale:!1,category:"animals_and_nature"},bird:{keywords:["animal","nature","fly","tweet","spring"],"char":'\ud83d\udc26',fitzpatrick_scale:!1,category:"animals_and_nature"},baby_chick:{keywords:["animal","chicken","bird"],"char":'\ud83d\udc24',fitzpatrick_scale:!1,category:"animals_and_nature"},hatching_chick:{keywords:["animal","chicken","egg","born","baby","bird"],"char":'\ud83d\udc23',fitzpatrick_scale:!1,category:"animals_and_nature"},hatched_chick:{keywords:["animal","chicken","baby","bird"],"char":'\ud83d\udc25',fitzpatrick_scale:!1,category:"animals_and_nature"},duck:{keywords:["animal","nature","bird","mallard"],"char":'\ud83e\udd86',fitzpatrick_scale:!1,category:"animals_and_nature"},eagle:{keywords:["animal","nature","bird"],"char":'\ud83e\udd85',fitzpatrick_scale:!1,category:"animals_and_nature"},owl:{keywords:["animal","nature","bird","hoot"],"char":'\ud83e\udd89',fitzpatrick_scale:!1,category:"animals_and_nature"},bat:{keywords:["animal","nature","blind","vampire"],"char":'\ud83e\udd87',fitzpatrick_scale:!1,category:"animals_and_nature"},wolf:{keywords:["animal","nature","wild"],"char":'\ud83d\udc3a',fitzpatrick_scale:!1,category:"animals_and_nature"},boar:{keywords:["animal","nature"],"char":'\ud83d\udc17',fitzpatrick_scale:!1,category:"animals_and_nature"},horse:{keywords:["animal","brown","nature"],"char":'\ud83d\udc34',fitzpatrick_scale:!1,category:"animals_and_nature"},unicorn:{keywords:["animal","nature","mystical"],"char":'\ud83e\udd84',fitzpatrick_scale:!1,category:"animals_and_nature"},honeybee:{keywords:["animal","insect","nature","bug","spring","honey"],"char":'\ud83d\udc1d',fitzpatrick_scale:!1,category:"animals_and_nature"},bug:{keywords:["animal","insect","nature","worm"],"char":'\ud83d\udc1b',fitzpatrick_scale:!1,category:"animals_and_nature"},butterfly:{keywords:["animal","insect","nature","caterpillar"],"char":'\ud83e\udd8b',fitzpatrick_scale:!1,category:"animals_and_nature"},snail:{keywords:["slow","animal","shell"],"char":'\ud83d\udc0c',fitzpatrick_scale:!1,category:"animals_and_nature"},beetle:{keywords:["animal","insect","nature","ladybug"],"char":'\ud83d\udc1e',fitzpatrick_scale:!1,category:"animals_and_nature"},ant:{keywords:["animal","insect","nature","bug"],"char":'\ud83d\udc1c',fitzpatrick_scale:!1,category:"animals_and_nature"},grasshopper:{keywords:["animal","cricket","chirp"],"char":'\ud83e\udd97',fitzpatrick_scale:!1,category:"animals_and_nature"},spider:{keywords:["animal","arachnid"],"char":'\ud83d\udd77',fitzpatrick_scale:!1,category:"animals_and_nature"},scorpion:{keywords:["animal","arachnid"],"char":'\ud83e\udd82',fitzpatrick_scale:!1,category:"animals_and_nature"},crab:{keywords:["animal","crustacean"],"char":'\ud83e\udd80',fitzpatrick_scale:!1,category:"animals_and_nature"},snake:{keywords:["animal","evil","nature","hiss","python"],"char":'\ud83d\udc0d',fitzpatrick_scale:!1,category:"animals_and_nature"},lizard:{keywords:["animal","nature","reptile"],"char":'\ud83e\udd8e',fitzpatrick_scale:!1,category:"animals_and_nature"},"t-rex":{keywords:["animal","nature","dinosaur","tyrannosaurus","extinct"],"char":'\ud83e\udd96',fitzpatrick_scale:!1,category:"animals_and_nature"},sauropod:{keywords:["animal","nature","dinosaur","brachiosaurus","brontosaurus","diplodocus","extinct"],"char":'\ud83e\udd95',fitzpatrick_scale:!1,category:"animals_and_nature"},turtle:{keywords:["animal","slow","nature","tortoise"],"char":'\ud83d\udc22',fitzpatrick_scale:!1,category:"animals_and_nature"},tropical_fish:{keywords:["animal","swim","ocean","beach","nemo"],"char":'\ud83d\udc20',fitzpatrick_scale:!1,category:"animals_and_nature"},fish:{keywords:["animal","food","nature"],"char":'\ud83d\udc1f',fitzpatrick_scale:!1,category:"animals_and_nature"},blowfish:{keywords:["animal","nature","food","sea","ocean"],"char":'\ud83d\udc21',fitzpatrick_scale:!1,category:"animals_and_nature"},dolphin:{keywords:["animal","nature","fish","sea","ocean","flipper","fins","beach"],"char":'\ud83d\udc2c',fitzpatrick_scale:!1,category:"animals_and_nature"},shark:{keywords:["animal","nature","fish","sea","ocean","jaws","fins","beach"],"char":'\ud83e\udd88',fitzpatrick_scale:!1,category:"animals_and_nature"},whale:{keywords:["animal","nature","sea","ocean"],"char":'\ud83d\udc33',fitzpatrick_scale:!1,category:"animals_and_nature"},whale2:{keywords:["animal","nature","sea","ocean"],"char":'\ud83d\udc0b',fitzpatrick_scale:!1,category:"animals_and_nature"},crocodile:{keywords:["animal","nature","reptile","lizard","alligator"],"char":'\ud83d\udc0a',fitzpatrick_scale:!1,category:"animals_and_nature"},leopard:{keywords:["animal","nature"],"char":'\ud83d\udc06',fitzpatrick_scale:!1,category:"animals_and_nature"},zebra:{keywords:["animal","nature","stripes","safari"],"char":'\ud83e\udd93',fitzpatrick_scale:!1,category:"animals_and_nature"},tiger2:{keywords:["animal","nature","roar"],"char":'\ud83d\udc05',fitzpatrick_scale:!1,category:"animals_and_nature"},water_buffalo:{keywords:["animal","nature","ox","cow"],"char":'\ud83d\udc03',fitzpatrick_scale:!1,category:"animals_and_nature"},ox:{keywords:["animal","cow","beef"],"char":'\ud83d\udc02',fitzpatrick_scale:!1,category:"animals_and_nature"},cow2:{keywords:["beef","ox","animal","nature","moo","milk"],"char":'\ud83d\udc04',fitzpatrick_scale:!1,category:"animals_and_nature"},deer:{keywords:["animal","nature","horns","venison"],"char":'\ud83e\udd8c',fitzpatrick_scale:!1,category:"animals_and_nature"},dromedary_camel:{keywords:["animal","hot","desert","hump"],"char":'\ud83d\udc2a',fitzpatrick_scale:!1,category:"animals_and_nature"},camel:{keywords:["animal","nature","hot","desert","hump"],"char":'\ud83d\udc2b',fitzpatrick_scale:!1,category:"animals_and_nature"},giraffe:{keywords:["animal","nature","spots","safari"],"char":'\ud83e\udd92',fitzpatrick_scale:!1,category:"animals_and_nature"},elephant:{keywords:["animal","nature","nose","th","circus"],"char":'\ud83d\udc18',fitzpatrick_scale:!1,category:"animals_and_nature"},rhinoceros:{keywords:["animal","nature","horn"],"char":'\ud83e\udd8f',fitzpatrick_scale:!1,category:"animals_and_nature"},goat:{keywords:["animal","nature"],"char":'\ud83d\udc10',fitzpatrick_scale:!1,category:"animals_and_nature"},ram:{keywords:["animal","sheep","nature"],"char":'\ud83d\udc0f',fitzpatrick_scale:!1,category:"animals_and_nature"},sheep:{keywords:["animal","nature","wool","shipit"],"char":'\ud83d\udc11',fitzpatrick_scale:!1,category:"animals_and_nature"},racehorse:{keywords:["animal","gamble","luck"],"char":'\ud83d\udc0e',fitzpatrick_scale:!1,category:"animals_and_nature"},pig2:{keywords:["animal","nature"],"char":'\ud83d\udc16',fitzpatrick_scale:!1,category:"animals_and_nature"},rat:{keywords:["animal","mouse","rodent"],"char":'\ud83d\udc00',fitzpatrick_scale:!1,category:"animals_and_nature"},mouse2:{keywords:["animal","nature","rodent"],"char":'\ud83d\udc01',fitzpatrick_scale:!1,category:"animals_and_nature"},rooster:{keywords:["animal","nature","chicken"],"char":'\ud83d\udc13',fitzpatrick_scale:!1,category:"animals_and_nature"},turkey:{keywords:["animal","bird"],"char":'\ud83e\udd83',fitzpatrick_scale:!1,category:"animals_and_nature"},dove:{keywords:["animal","bird"],"char":'\ud83d\udd4a',fitzpatrick_scale:!1,category:"animals_and_nature"},dog2:{keywords:["animal","nature","friend","doge","pet","faithful"],"char":'\ud83d\udc15',fitzpatrick_scale:!1,category:"animals_and_nature"},poodle:{keywords:["dog","animal","101","nature","pet"],"char":'\ud83d\udc29',fitzpatrick_scale:!1,category:"animals_and_nature"},cat2:{keywords:["animal","meow","pet","cats"],"char":'\ud83d\udc08',fitzpatrick_scale:!1,category:"animals_and_nature"},rabbit2:{keywords:["animal","nature","pet","magic","spring"],"char":'\ud83d\udc07',fitzpatrick_scale:!1,category:"animals_and_nature"},chipmunk:{keywords:["animal","nature","rodent","squirrel"],"char":'\ud83d\udc3f',fitzpatrick_scale:!1,category:"animals_and_nature"},hedgehog:{keywords:["animal","nature","spiny"],"char":'\ud83e\udd94',fitzpatrick_scale:!1,category:"animals_and_nature"},raccoon:{keywords:["animal","nature"],"char":'\ud83e\udd9d',fitzpatrick_scale:!1,category:"animals_and_nature"},llama:{keywords:["animal","nature","alpaca"],"char":'\ud83e\udd99',fitzpatrick_scale:!1,category:"animals_and_nature"},hippopotamus:{keywords:["animal","nature"],"char":'\ud83e\udd9b',fitzpatrick_scale:!1,category:"animals_and_nature"},kangaroo:{keywords:["animal","nature","australia","joey","hop","marsupial"],"char":'\ud83e\udd98',fitzpatrick_scale:!1,category:"animals_and_nature"},badger:{keywords:["animal","nature","honey"],"char":'\ud83e\udda1',fitzpatrick_scale:!1,category:"animals_and_nature"},swan:{keywords:["animal","nature","bird"],"char":'\ud83e\udda2',fitzpatrick_scale:!1,category:"animals_and_nature"},peacock:{keywords:["animal","nature","peahen","bird"],"char":'\ud83e\udd9a',fitzpatrick_scale:!1,category:"animals_and_nature"},parrot:{keywords:["animal","nature","bird","pirate","talk"],"char":'\ud83e\udd9c',fitzpatrick_scale:!1,category:"animals_and_nature"},lobster:{keywords:["animal","nature","bisque","claws","seafood"],"char":'\ud83e\udd9e',fitzpatrick_scale:!1,category:"animals_and_nature"},mosquito:{keywords:["animal","nature","insect","malaria"],"char":'\ud83e\udd9f',fitzpatrick_scale:!1,category:"animals_and_nature"},paw_prints:{keywords:["animal","tracking","footprints","dog","cat","pet","feet"],"char":'\ud83d\udc3e',fitzpatrick_scale:!1,category:"animals_and_nature"},dragon:{keywords:["animal","myth","nature","chinese","green"],"char":'\ud83d\udc09',fitzpatrick_scale:!1,category:"animals_and_nature"},dragon_face:{keywords:["animal","myth","nature","chinese","green"],"char":'\ud83d\udc32',fitzpatrick_scale:!1,category:"animals_and_nature"},cactus:{keywords:["vegetable","plant","nature"],"char":'\ud83c\udf35',fitzpatrick_scale:!1,category:"animals_and_nature"},christmas_tree:{keywords:["festival","vacation","december","xmas","celebration"],"char":'\ud83c\udf84',fitzpatrick_scale:!1,category:"animals_and_nature"},evergreen_tree:{keywords:["plant","nature"],"char":'\ud83c\udf32',fitzpatrick_scale:!1,category:"animals_and_nature"},deciduous_tree:{keywords:["plant","nature"],"char":'\ud83c\udf33',fitzpatrick_scale:!1,category:"animals_and_nature"},palm_tree:{keywords:["plant","vegetable","nature","summer","beach","mojito","tropical"],"char":'\ud83c\udf34',fitzpatrick_scale:!1,category:"animals_and_nature"},seedling:{keywords:["plant","nature","grass","lawn","spring"],"char":'\ud83c\udf31',fitzpatrick_scale:!1,category:"animals_and_nature"},herb:{keywords:["vegetable","plant","medicine","weed","grass","lawn"],"char":'\ud83c\udf3f',fitzpatrick_scale:!1,category:"animals_and_nature"},shamrock:{keywords:["vegetable","plant","nature","irish","clover"],"char":'\u2618',fitzpatrick_scale:!1,category:"animals_and_nature"},four_leaf_clover:{keywords:["vegetable","plant","nature","lucky","irish"],"char":'\ud83c\udf40',fitzpatrick_scale:!1,category:"animals_and_nature"},bamboo:{keywords:["plant","nature","vegetable","panda","pine_decoration"],"char":'\ud83c\udf8d',fitzpatrick_scale:!1,category:"animals_and_nature"},tanabata_tree:{keywords:["plant","nature","branch","summer"],"char":'\ud83c\udf8b',fitzpatrick_scale:!1,category:"animals_and_nature"},leaves:{keywords:["nature","plant","tree","vegetable","grass","lawn","spring"],"char":'\ud83c\udf43',fitzpatrick_scale:!1,category:"animals_and_nature"},fallen_leaf:{keywords:["nature","plant","vegetable","leaves"],"char":'\ud83c\udf42',fitzpatrick_scale:!1,category:"animals_and_nature"},maple_leaf:{keywords:["nature","plant","vegetable","ca","fall"],"char":'\ud83c\udf41',fitzpatrick_scale:!1,category:"animals_and_nature"},ear_of_rice:{keywords:["nature","plant"],"char":'\ud83c\udf3e',fitzpatrick_scale:!1,category:"animals_and_nature"},hibiscus:{keywords:["plant","vegetable","flowers","beach"],"char":'\ud83c\udf3a',fitzpatrick_scale:!1,category:"animals_and_nature"},sunflower:{keywords:["nature","plant","fall"],"char":'\ud83c\udf3b',fitzpatrick_scale:!1,category:"animals_and_nature"},rose:{keywords:["flowers","valentines","love","spring"],"char":'\ud83c\udf39',fitzpatrick_scale:!1,category:"animals_and_nature"},wilted_flower:{keywords:["plant","nature","flower"],"char":'\ud83e\udd40',fitzpatrick_scale:!1,category:"animals_and_nature"},tulip:{keywords:["flowers","plant","nature","summer","spring"],"char":'\ud83c\udf37',fitzpatrick_scale:!1,category:"animals_and_nature"},blossom:{keywords:["nature","flowers","yellow"],"char":'\ud83c\udf3c',fitzpatrick_scale:!1,category:"animals_and_nature"},cherry_blossom:{keywords:["nature","plant","spring","flower"],"char":'\ud83c\udf38',fitzpatrick_scale:!1,category:"animals_and_nature"},bouquet:{keywords:["flowers","nature","spring"],"char":'\ud83d\udc90',fitzpatrick_scale:!1,category:"animals_and_nature"},mushroom:{keywords:["plant","vegetable"],"char":'\ud83c\udf44',fitzpatrick_scale:!1,category:"animals_and_nature"},chestnut:{keywords:["food","squirrel"],"char":'\ud83c\udf30',fitzpatrick_scale:!1,category:"animals_and_nature"},jack_o_lantern:{keywords:["halloween","light","pumpkin","creepy","fall"],"char":'\ud83c\udf83',fitzpatrick_scale:!1,category:"animals_and_nature"},shell:{keywords:["nature","sea","beach"],"char":'\ud83d\udc1a',fitzpatrick_scale:!1,category:"animals_and_nature"},spider_web:{keywords:["animal","insect","arachnid","silk"],"char":'\ud83d\udd78',fitzpatrick_scale:!1,category:"animals_and_nature"},earth_americas:{keywords:["globe","world","USA","international"],"char":'\ud83c\udf0e',fitzpatrick_scale:!1,category:"animals_and_nature"},earth_africa:{keywords:["globe","world","international"],"char":'\ud83c\udf0d',fitzpatrick_scale:!1,category:"animals_and_nature"},earth_asia:{keywords:["globe","world","east","international"],"char":'\ud83c\udf0f',fitzpatrick_scale:!1,category:"animals_and_nature"},full_moon:{keywords:["nature","yellow","twilight","planet","space","night","evening","sleep"],"char":'\ud83c\udf15',fitzpatrick_scale:!1,category:"animals_and_nature"},waning_gibbous_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep","waxing_gibbous_moon"],"char":'\ud83c\udf16',fitzpatrick_scale:!1,category:"animals_and_nature"},last_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":'\ud83c\udf17',fitzpatrick_scale:!1,category:"animals_and_nature"},waning_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":'\ud83c\udf18',fitzpatrick_scale:!1,category:"animals_and_nature"},new_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":'\ud83c\udf11',fitzpatrick_scale:!1,category:"animals_and_nature"},waxing_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":'\ud83c\udf12',fitzpatrick_scale:!1,category:"animals_and_nature"},first_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":'\ud83c\udf13',fitzpatrick_scale:!1,category:"animals_and_nature"},waxing_gibbous_moon:{keywords:["nature","night","sky","gray","twilight","planet","space","evening","sleep"],"char":'\ud83c\udf14',fitzpatrick_scale:!1,category:"animals_and_nature"},new_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":'\ud83c\udf1a',fitzpatrick_scale:!1,category:"animals_and_nature"},full_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":'\ud83c\udf1d',fitzpatrick_scale:!1,category:"animals_and_nature"},first_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":'\ud83c\udf1b',fitzpatrick_scale:!1,category:"animals_and_nature"},last_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":'\ud83c\udf1c',fitzpatrick_scale:!1,category:"animals_and_nature"},sun_with_face:{keywords:["nature","morning","sky"],"char":'\ud83c\udf1e',fitzpatrick_scale:!1,category:"animals_and_nature"},crescent_moon:{keywords:["night","sleep","sky","evening","magic"],"char":'\ud83c\udf19',fitzpatrick_scale:!1,category:"animals_and_nature"},star:{keywords:["night","yellow"],"char":'\u2b50',fitzpatrick_scale:!1,category:"animals_and_nature"},star2:{keywords:["night","sparkle","awesome","good","magic"],"char":'\ud83c\udf1f',fitzpatrick_scale:!1,category:"animals_and_nature"},dizzy:{keywords:["star","sparkle","shoot","magic"],"char":'\ud83d\udcab',fitzpatrick_scale:!1,category:"animals_and_nature"},sparkles:{keywords:["stars","shine","shiny","cool","awesome","good","magic"],"char":'\u2728',fitzpatrick_scale:!1,category:"animals_and_nature"},comet:{keywords:["space"],"char":'\u2604',fitzpatrick_scale:!1,category:"animals_and_nature"},sunny:{keywords:["weather","nature","brightness","summer","beach","spring"],"char":'\u2600\ufe0f',fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_small_cloud:{keywords:["weather"],"char":'\ud83c\udf24',fitzpatrick_scale:!1,category:"animals_and_nature"},partly_sunny:{keywords:["weather","nature","cloudy","morning","fall","spring"],"char":'\u26c5',fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_large_cloud:{keywords:["weather"],"char":'\ud83c\udf25',fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_rain_cloud:{keywords:["weather"],"char":'\ud83c\udf26',fitzpatrick_scale:!1,category:"animals_and_nature"},cloud:{keywords:["weather","sky"],"char":'\u2601\ufe0f',fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_rain:{keywords:["weather"],"char":'\ud83c\udf27',fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_lightning_and_rain:{keywords:["weather","lightning"],"char":'\u26c8',fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_lightning:{keywords:["weather","thunder"],"char":'\ud83c\udf29',fitzpatrick_scale:!1,category:"animals_and_nature"},zap:{keywords:["thunder","weather","lightning bolt","fast"],"char":'\u26a1',fitzpatrick_scale:!1,category:"animals_and_nature"},fire:{keywords:["hot","cook","flame"],"char":'\ud83d\udd25',fitzpatrick_scale:!1,category:"animals_and_nature"},boom:{keywords:["bomb","explode","explosion","collision","blown"],"char":'\ud83d\udca5',fitzpatrick_scale:!1,category:"animals_and_nature"},snowflake:{keywords:["winter","season","cold","weather","christmas","xmas"],"char":'\u2744\ufe0f',fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_snow:{keywords:["weather"],"char":'\ud83c\udf28',fitzpatrick_scale:!1,category:"animals_and_nature"},snowman:{keywords:["winter","season","cold","weather","christmas","xmas","frozen","without_snow"],"char":'\u26c4',fitzpatrick_scale:!1,category:"animals_and_nature"},snowman_with_snow:{keywords:["winter","season","cold","weather","christmas","xmas","frozen"],"char":'\u2603',fitzpatrick_scale:!1,category:"animals_and_nature"},wind_face:{keywords:["gust","air"],"char":'\ud83c\udf2c',fitzpatrick_scale:!1,category:"animals_and_nature"},dash:{keywords:["wind","air","fast","shoo","fart","smoke","puff"],"char":'\ud83d\udca8',fitzpatrick_scale:!1,category:"animals_and_nature"},tornado:{keywords:["weather","cyclone","twister"],"char":'\ud83c\udf2a',fitzpatrick_scale:!1,category:"animals_and_nature"},fog:{keywords:["weather"],"char":'\ud83c\udf2b',fitzpatrick_scale:!1,category:"animals_and_nature"},open_umbrella:{keywords:["weather","spring"],"char":'\u2602',fitzpatrick_scale:!1,category:"animals_and_nature"},umbrella:{keywords:["rainy","weather","spring"],"char":'\u2614',fitzpatrick_scale:!1,category:"animals_and_nature"},droplet:{keywords:["water","drip","faucet","spring"],"char":'\ud83d\udca7',fitzpatrick_scale:!1,category:"animals_and_nature"},sweat_drops:{keywords:["water","drip","oops"],"char":'\ud83d\udca6',fitzpatrick_scale:!1,category:"animals_and_nature"},ocean:{keywords:["sea","water","wave","nature","tsunami","disaster"],"char":'\ud83c\udf0a',fitzpatrick_scale:!1,category:"animals_and_nature"},green_apple:{keywords:["fruit","nature"],"char":'\ud83c\udf4f',fitzpatrick_scale:!1,category:"food_and_drink"},apple:{keywords:["fruit","mac","school"],"char":'\ud83c\udf4e',fitzpatrick_scale:!1,category:"food_and_drink"},pear:{keywords:["fruit","nature","food"],"char":'\ud83c\udf50',fitzpatrick_scale:!1,category:"food_and_drink"},tangerine:{keywords:["food","fruit","nature","orange"],"char":'\ud83c\udf4a',fitzpatrick_scale:!1,category:"food_and_drink"},lemon:{keywords:["fruit","nature"],"char":'\ud83c\udf4b',fitzpatrick_scale:!1,category:"food_and_drink"},banana:{keywords:["fruit","food","monkey"],"char":'\ud83c\udf4c',fitzpatrick_scale:!1,category:"food_and_drink"},watermelon:{keywords:["fruit","food","picnic","summer"],"char":'\ud83c\udf49',fitzpatrick_scale:!1,category:"food_and_drink"},grapes:{keywords:["fruit","food","wine"],"char":'\ud83c\udf47',fitzpatrick_scale:!1,category:"food_and_drink"},strawberry:{keywords:["fruit","food","nature"],"char":'\ud83c\udf53',fitzpatrick_scale:!1,category:"food_and_drink"},melon:{keywords:["fruit","nature","food"],"char":'\ud83c\udf48',fitzpatrick_scale:!1,category:"food_and_drink"},cherries:{keywords:["food","fruit"],"char":'\ud83c\udf52',fitzpatrick_scale:!1,category:"food_and_drink"},peach:{keywords:["fruit","nature","food"],"char":'\ud83c\udf51',fitzpatrick_scale:!1,category:"food_and_drink"},pineapple:{keywords:["fruit","nature","food"],"char":'\ud83c\udf4d',fitzpatrick_scale:!1,category:"food_and_drink"},coconut:{keywords:["fruit","nature","food","palm"],"char":'\ud83e\udd65',fitzpatrick_scale:!1,category:"food_and_drink"},kiwi_fruit:{keywords:["fruit","food"],"char":'\ud83e\udd5d',fitzpatrick_scale:!1,category:"food_and_drink"},mango:{keywords:["fruit","food","tropical"],"char":'\ud83e\udd6d',fitzpatrick_scale:!1,category:"food_and_drink"},avocado:{keywords:["fruit","food"],"char":'\ud83e\udd51',fitzpatrick_scale:!1,category:"food_and_drink"},broccoli:{keywords:["fruit","food","vegetable"],"char":'\ud83e\udd66',fitzpatrick_scale:!1,category:"food_and_drink"},tomato:{keywords:["fruit","vegetable","nature","food"],"char":'\ud83c\udf45',fitzpatrick_scale:!1,category:"food_and_drink"},eggplant:{keywords:["vegetable","nature","food","aubergine"],"char":'\ud83c\udf46',fitzpatrick_scale:!1,category:"food_and_drink"},cucumber:{keywords:["fruit","food","pickle"],"char":'\ud83e\udd52',fitzpatrick_scale:!1,category:"food_and_drink"},carrot:{keywords:["vegetable","food","orange"],"char":'\ud83e\udd55',fitzpatrick_scale:!1,category:"food_and_drink"},hot_pepper:{keywords:["food","spicy","chilli","chili"],"char":'\ud83c\udf36',fitzpatrick_scale:!1,category:"food_and_drink"},potato:{keywords:["food","tuber","vegatable","starch"],"char":'\ud83e\udd54',fitzpatrick_scale:!1,category:"food_and_drink"},corn:{keywords:["food","vegetable","plant"],"char":'\ud83c\udf3d',fitzpatrick_scale:!1,category:"food_and_drink"},leafy_greens:{keywords:["food","vegetable","plant","bok choy","cabbage","kale","lettuce"],"char":'\ud83e\udd6c',fitzpatrick_scale:!1,category:"food_and_drink"},sweet_potato:{keywords:["food","nature"],"char":'\ud83c\udf60',fitzpatrick_scale:!1,category:"food_and_drink"},peanuts:{keywords:["food","nut"],"char":'\ud83e\udd5c',fitzpatrick_scale:!1,category:"food_and_drink"},honey_pot:{keywords:["bees","sweet","kitchen"],"char":'\ud83c\udf6f',fitzpatrick_scale:!1,category:"food_and_drink"},croissant:{keywords:["food","bread","french"],"char":'\ud83e\udd50',fitzpatrick_scale:!1,category:"food_and_drink"},bread:{keywords:["food","wheat","breakfast","toast"],"char":'\ud83c\udf5e',fitzpatrick_scale:!1,category:"food_and_drink"},baguette_bread:{keywords:["food","bread","french"],"char":'\ud83e\udd56',fitzpatrick_scale:!1,category:"food_and_drink"},bagel:{keywords:["food","bread","bakery","schmear"],"char":'\ud83e\udd6f',fitzpatrick_scale:!1,category:"food_and_drink"},pretzel:{keywords:["food","bread","twisted"],"char":'\ud83e\udd68',fitzpatrick_scale:!1,category:"food_and_drink"},cheese:{keywords:["food","chadder"],"char":'\ud83e\uddc0',fitzpatrick_scale:!1,category:"food_and_drink"},egg:{keywords:["food","chicken","breakfast"],"char":'\ud83e\udd5a',fitzpatrick_scale:!1,category:"food_and_drink"},bacon:{keywords:["food","breakfast","pork","pig","meat"],"char":'\ud83e\udd53',fitzpatrick_scale:!1,category:"food_and_drink"},steak:{keywords:["food","cow","meat","cut","chop","lambchop","porkchop"],"char":'\ud83e\udd69',fitzpatrick_scale:!1,category:"food_and_drink"},pancakes:{keywords:["food","breakfast","flapjacks","hotcakes"],"char":'\ud83e\udd5e',fitzpatrick_scale:!1,category:"food_and_drink"},poultry_leg:{keywords:["food","meat","drumstick","bird","chicken","turkey"],"char":'\ud83c\udf57',fitzpatrick_scale:!1,category:"food_and_drink"},meat_on_bone:{keywords:["good","food","drumstick"],"char":'\ud83c\udf56',fitzpatrick_scale:!1,category:"food_and_drink"},bone:{keywords:["skeleton"],"char":'\ud83e\uddb4',fitzpatrick_scale:!1,category:"food_and_drink"},fried_shrimp:{keywords:["food","animal","appetizer","summer"],"char":'\ud83c\udf64',fitzpatrick_scale:!1,category:"food_and_drink"},fried_egg:{keywords:["food","breakfast","kitchen","egg"],"char":'\ud83c\udf73',fitzpatrick_scale:!1,category:"food_and_drink"},hamburger:{keywords:["meat","fast food","beef","cheeseburger","mcdonalds","burger king"],"char":'\ud83c\udf54',fitzpatrick_scale:!1,category:"food_and_drink"},fries:{keywords:["chips","snack","fast food"],"char":'\ud83c\udf5f',fitzpatrick_scale:!1,category:"food_and_drink"},stuffed_flatbread:{keywords:["food","flatbread","stuffed","gyro"],"char":'\ud83e\udd59',fitzpatrick_scale:!1,category:"food_and_drink"},hotdog:{keywords:["food","frankfurter"],"char":'\ud83c\udf2d',fitzpatrick_scale:!1,category:"food_and_drink"},pizza:{keywords:["food","party"],"char":'\ud83c\udf55',fitzpatrick_scale:!1,category:"food_and_drink"},sandwich:{keywords:["food","lunch","bread"],"char":'\ud83e\udd6a',fitzpatrick_scale:!1,category:"food_and_drink"},canned_food:{keywords:["food","soup"],"char":'\ud83e\udd6b',fitzpatrick_scale:!1,category:"food_and_drink"},spaghetti:{keywords:["food","italian","noodle"],"char":'\ud83c\udf5d',fitzpatrick_scale:!1,category:"food_and_drink"},taco:{keywords:["food","mexican"],"char":'\ud83c\udf2e',fitzpatrick_scale:!1,category:"food_and_drink"},burrito:{keywords:["food","mexican"],"char":'\ud83c\udf2f',fitzpatrick_scale:!1,category:"food_and_drink"},green_salad:{keywords:["food","healthy","lettuce"],"char":'\ud83e\udd57',fitzpatrick_scale:!1,category:"food_and_drink"},shallow_pan_of_food:{keywords:["food","cooking","casserole","paella"],"char":'\ud83e\udd58',fitzpatrick_scale:!1,category:"food_and_drink"},ramen:{keywords:["food","japanese","noodle","chopsticks"],"char":'\ud83c\udf5c',fitzpatrick_scale:!1,category:"food_and_drink"},stew:{keywords:["food","meat","soup"],"char":'\ud83c\udf72',fitzpatrick_scale:!1,category:"food_and_drink"},fish_cake:{keywords:["food","japan","sea","beach","narutomaki","pink","swirl","kamaboko","surimi","ramen"],"char":'\ud83c\udf65',fitzpatrick_scale:!1,category:"food_and_drink"},fortune_cookie:{keywords:["food","prophecy"],"char":'\ud83e\udd60',fitzpatrick_scale:!1,category:"food_and_drink"},sushi:{keywords:["food","fish","japanese","rice"],"char":'\ud83c\udf63',fitzpatrick_scale:!1,category:"food_and_drink"},bento:{keywords:["food","japanese","box"],"char":'\ud83c\udf71',fitzpatrick_scale:!1,category:"food_and_drink"},curry:{keywords:["food","spicy","hot","indian"],"char":'\ud83c\udf5b',fitzpatrick_scale:!1,category:"food_and_drink"},rice_ball:{keywords:["food","japanese"],"char":'\ud83c\udf59',fitzpatrick_scale:!1,category:"food_and_drink"},rice:{keywords:["food","china","asian"],"char":'\ud83c\udf5a',fitzpatrick_scale:!1,category:"food_and_drink"},rice_cracker:{keywords:["food","japanese"],"char":'\ud83c\udf58',fitzpatrick_scale:!1,category:"food_and_drink"},oden:{keywords:["food","japanese"],"char":'\ud83c\udf62',fitzpatrick_scale:!1,category:"food_and_drink"},dango:{keywords:["food","dessert","sweet","japanese","barbecue","meat"],"char":'\ud83c\udf61',fitzpatrick_scale:!1,category:"food_and_drink"},shaved_ice:{keywords:["hot","dessert","summer"],"char":'\ud83c\udf67',fitzpatrick_scale:!1,category:"food_and_drink"},ice_cream:{keywords:["food","hot","dessert"],"char":'\ud83c\udf68',fitzpatrick_scale:!1,category:"food_and_drink"},icecream:{keywords:["food","hot","dessert","summer"],"char":'\ud83c\udf66',fitzpatrick_scale:!1,category:"food_and_drink"},pie:{keywords:["food","dessert","pastry"],"char":'\ud83e\udd67',fitzpatrick_scale:!1,category:"food_and_drink"},cake:{keywords:["food","dessert"],"char":'\ud83c\udf70',fitzpatrick_scale:!1,category:"food_and_drink"},cupcake:{keywords:["food","dessert","bakery","sweet"],"char":'\ud83e\uddc1',fitzpatrick_scale:!1,category:"food_and_drink"},moon_cake:{keywords:["food","autumn"],"char":'\ud83e\udd6e',fitzpatrick_scale:!1,category:"food_and_drink"},birthday:{keywords:["food","dessert","cake"],"char":'\ud83c\udf82',fitzpatrick_scale:!1,category:"food_and_drink"},custard:{keywords:["dessert","food"],"char":'\ud83c\udf6e',fitzpatrick_scale:!1,category:"food_and_drink"},candy:{keywords:["snack","dessert","sweet","lolly"],"char":'\ud83c\udf6c',fitzpatrick_scale:!1,category:"food_and_drink"},lollipop:{keywords:["food","snack","candy","sweet"],"char":'\ud83c\udf6d',fitzpatrick_scale:!1,category:"food_and_drink"},chocolate_bar:{keywords:["food","snack","dessert","sweet"],"char":'\ud83c\udf6b',fitzpatrick_scale:!1,category:"food_and_drink"},popcorn:{keywords:["food","movie theater","films","snack"],"char":'\ud83c\udf7f',fitzpatrick_scale:!1,category:"food_and_drink"},dumpling:{keywords:["food","empanada","pierogi","potsticker"],"char":'\ud83e\udd5f',fitzpatrick_scale:!1,category:"food_and_drink"},doughnut:{keywords:["food","dessert","snack","sweet","donut"],"char":'\ud83c\udf69',fitzpatrick_scale:!1,category:"food_and_drink"},cookie:{keywords:["food","snack","oreo","chocolate","sweet","dessert"],"char":'\ud83c\udf6a',fitzpatrick_scale:!1,category:"food_and_drink"},milk_glass:{keywords:["beverage","drink","cow"],"char":'\ud83e\udd5b',fitzpatrick_scale:!1,category:"food_and_drink"},beer:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],"char":'\ud83c\udf7a',fitzpatrick_scale:!1,category:"food_and_drink"},beers:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],"char":'\ud83c\udf7b',fitzpatrick_scale:!1,category:"food_and_drink"},clinking_glasses:{keywords:["beverage","drink","party","alcohol","celebrate","cheers","wine","champagne","toast"],"char":'\ud83e\udd42',fitzpatrick_scale:!1,category:"food_and_drink"},wine_glass:{keywords:["drink","beverage","drunk","alcohol","booze"],"char":'\ud83c\udf77',fitzpatrick_scale:!1,category:"food_and_drink"},tumbler_glass:{keywords:["drink","beverage","drunk","alcohol","liquor","booze","bourbon","scotch","whisky","glass","shot"],"char":'\ud83e\udd43',fitzpatrick_scale:!1,category:"food_and_drink"},cocktail:{keywords:["drink","drunk","alcohol","beverage","booze","mojito"],"char":'\ud83c\udf78',fitzpatrick_scale:!1,category:"food_and_drink"},tropical_drink:{keywords:["beverage","cocktail","summer","beach","alcohol","booze","mojito"],"char":'\ud83c\udf79',fitzpatrick_scale:!1,category:"food_and_drink"},champagne:{keywords:["drink","wine","bottle","celebration"],"char":'\ud83c\udf7e',fitzpatrick_scale:!1,category:"food_and_drink"},sake:{keywords:["wine","drink","drunk","beverage","japanese","alcohol","booze"],"char":'\ud83c\udf76',fitzpatrick_scale:!1,category:"food_and_drink"},tea:{keywords:["drink","bowl","breakfast","green","british"],"char":'\ud83c\udf75',fitzpatrick_scale:!1,category:"food_and_drink"},cup_with_straw:{keywords:["drink","soda"],"char":'\ud83e\udd64',fitzpatrick_scale:!1,category:"food_and_drink"},coffee:{keywords:["beverage","caffeine","latte","espresso"],"char":'\u2615',fitzpatrick_scale:!1,category:"food_and_drink"},baby_bottle:{keywords:["food","container","milk"],"char":'\ud83c\udf7c',fitzpatrick_scale:!1,category:"food_and_drink"},salt:{keywords:["condiment","shaker"],"char":'\ud83e\uddc2',fitzpatrick_scale:!1,category:"food_and_drink"},spoon:{keywords:["cutlery","kitchen","tableware"],"char":'\ud83e\udd44',fitzpatrick_scale:!1,category:"food_and_drink"},fork_and_knife:{keywords:["cutlery","kitchen"],"char":'\ud83c\udf74',fitzpatrick_scale:!1,category:"food_and_drink"},plate_with_cutlery:{keywords:["food","eat","meal","lunch","dinner","restaurant"],"char":'\ud83c\udf7d',fitzpatrick_scale:!1,category:"food_and_drink"},bowl_with_spoon:{keywords:["food","breakfast","cereal","oatmeal","porridge"],"char":'\ud83e\udd63',fitzpatrick_scale:!1,category:"food_and_drink"},takeout_box:{keywords:["food","leftovers"],"char":'\ud83e\udd61',fitzpatrick_scale:!1,category:"food_and_drink"},chopsticks:{keywords:["food"],"char":'\ud83e\udd62',fitzpatrick_scale:!1,category:"food_and_drink"},soccer:{keywords:["sports","football"],"char":'\u26bd',fitzpatrick_scale:!1,category:"activity"},basketball:{keywords:["sports","balls","NBA"],"char":'\ud83c\udfc0',fitzpatrick_scale:!1,category:"activity"},football:{keywords:["sports","balls","NFL"],"char":'\ud83c\udfc8',fitzpatrick_scale:!1,category:"activity"},baseball:{keywords:["sports","balls"],"char":'\u26be',fitzpatrick_scale:!1,category:"activity"},softball:{keywords:["sports","balls"],"char":'\ud83e\udd4e',fitzpatrick_scale:!1,category:"activity"},tennis:{keywords:["sports","balls","green"],"char":'\ud83c\udfbe',fitzpatrick_scale:!1,category:"activity"},volleyball:{keywords:["sports","balls"],"char":'\ud83c\udfd0',fitzpatrick_scale:!1,category:"activity"},rugby_football:{keywords:["sports","team"],"char":'\ud83c\udfc9',fitzpatrick_scale:!1,category:"activity"},flying_disc:{keywords:["sports","frisbee","ultimate"],"char":'\ud83e\udd4f',fitzpatrick_scale:!1,category:"activity"},"8ball":{keywords:["pool","hobby","game","luck","magic"],"char":'\ud83c\udfb1',fitzpatrick_scale:!1,category:"activity"},golf:{keywords:["sports","business","flag","hole","summer"],"char":'\u26f3',fitzpatrick_scale:!1,category:"activity"},golfing_woman:{keywords:["sports","business","woman","female"],"char":'\ud83c\udfcc\ufe0f\u200d\u2640\ufe0f',fitzpatrick_scale:!1,category:"activity"},golfing_man:{keywords:["sports","business"],"char":'\ud83c\udfcc',fitzpatrick_scale:!0,category:"activity"},ping_pong:{keywords:["sports","pingpong"],"char":'\ud83c\udfd3',fitzpatrick_scale:!1,category:"activity"},badminton:{keywords:["sports"],"char":'\ud83c\udff8',fitzpatrick_scale:!1,category:"activity"},goal_net:{keywords:["sports"],"char":'\ud83e\udd45',fitzpatrick_scale:!1,category:"activity"},ice_hockey:{keywords:["sports"],"char":'\ud83c\udfd2',fitzpatrick_scale:!1,category:"activity"},field_hockey:{keywords:["sports"],"char":'\ud83c\udfd1',fitzpatrick_scale:!1,category:"activity"},lacrosse:{keywords:["sports","ball","stick"],"char":'\ud83e\udd4d',fitzpatrick_scale:!1,category:"activity"},cricket:{keywords:["sports"],"char":'\ud83c\udfcf',fitzpatrick_scale:!1,category:"activity"},ski:{keywords:["sports","winter","cold","snow"],"char":'\ud83c\udfbf',fitzpatrick_scale:!1,category:"activity"},skier:{keywords:["sports","winter","snow"],"char":'\u26f7',fitzpatrick_scale:!1,category:"activity"},snowboarder:{keywords:["sports","winter"],"char":'\ud83c\udfc2',fitzpatrick_scale:!0,category:"activity"},person_fencing:{keywords:["sports","fencing","sword"],"char":'\ud83e\udd3a',fitzpatrick_scale:!1,category:"activity"},women_wrestling:{keywords:["sports","wrestlers"],"char":'\ud83e\udd3c\u200d\u2640\ufe0f',fitzpatrick_scale:!1,category:"activity"},men_wrestling:{keywords:["sports","wrestlers"],"char":'\ud83e\udd3c\u200d\u2642\ufe0f',fitzpatrick_scale:!1,category:"activity"},woman_cartwheeling:{keywords:["gymnastics"],"char":'\ud83e\udd38\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_cartwheeling:{keywords:["gymnastics"],"char":'\ud83e\udd38\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},woman_playing_handball:{keywords:["sports"],"char":'\ud83e\udd3e\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_playing_handball:{keywords:["sports"],"char":'\ud83e\udd3e\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},ice_skate:{keywords:["sports"],"char":'\u26f8',fitzpatrick_scale:!1,category:"activity"},curling_stone:{keywords:["sports"],"char":'\ud83e\udd4c',fitzpatrick_scale:!1,category:"activity"},skateboard:{keywords:["board"],"char":'\ud83d\udef9',fitzpatrick_scale:!1,category:"activity"},sled:{keywords:["sleigh","luge","toboggan"],"char":'\ud83d\udef7',fitzpatrick_scale:!1,category:"activity"},bow_and_arrow:{keywords:["sports"],"char":'\ud83c\udff9',fitzpatrick_scale:!1,category:"activity"},fishing_pole_and_fish:{keywords:["food","hobby","summer"],"char":'\ud83c\udfa3',fitzpatrick_scale:!1,category:"activity"},boxing_glove:{keywords:["sports","fighting"],"char":'\ud83e\udd4a',fitzpatrick_scale:!1,category:"activity"},martial_arts_uniform:{keywords:["judo","karate","taekwondo"],"char":'\ud83e\udd4b',fitzpatrick_scale:!1,category:"activity"},rowing_woman:{keywords:["sports","hobby","water","ship","woman","female"],"char":'\ud83d\udea3\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},rowing_man:{keywords:["sports","hobby","water","ship"],"char":'\ud83d\udea3',fitzpatrick_scale:!0,category:"activity"},climbing_woman:{keywords:["sports","hobby","woman","female","rock"],"char":'\ud83e\uddd7\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},climbing_man:{keywords:["sports","hobby","man","male","rock"],"char":'\ud83e\uddd7\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},swimming_woman:{keywords:["sports","exercise","human","athlete","water","summer","woman","female"],"char":'\ud83c\udfca\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},swimming_man:{keywords:["sports","exercise","human","athlete","water","summer"],"char":'\ud83c\udfca',fitzpatrick_scale:!0,category:"activity"},woman_playing_water_polo:{keywords:["sports","pool"],"char":'\ud83e\udd3d\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_playing_water_polo:{keywords:["sports","pool"],"char":'\ud83e\udd3d\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},woman_in_lotus_position:{keywords:["woman","female","meditation","yoga","serenity","zen","mindfulness"],"char":'\ud83e\uddd8\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_in_lotus_position:{keywords:["man","male","meditation","yoga","serenity","zen","mindfulness"],"char":'\ud83e\uddd8\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},surfing_woman:{keywords:["sports","ocean","sea","summer","beach","woman","female"],"char":'\ud83c\udfc4\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},surfing_man:{keywords:["sports","ocean","sea","summer","beach"],"char":'\ud83c\udfc4',fitzpatrick_scale:!0,category:"activity"},bath:{keywords:["clean","shower","bathroom"],"char":'\ud83d\udec0',fitzpatrick_scale:!0,category:"activity"},basketball_woman:{keywords:["sports","human","woman","female"],"char":'\u26f9\ufe0f\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},basketball_man:{keywords:["sports","human"],"char":'\u26f9',fitzpatrick_scale:!0,category:"activity"},weight_lifting_woman:{keywords:["sports","training","exercise","woman","female"],"char":'\ud83c\udfcb\ufe0f\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},weight_lifting_man:{keywords:["sports","training","exercise"],"char":'\ud83c\udfcb',fitzpatrick_scale:!0,category:"activity"},biking_woman:{keywords:["sports","bike","exercise","hipster","woman","female"],"char":'\ud83d\udeb4\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},biking_man:{keywords:["sports","bike","exercise","hipster"],"char":'\ud83d\udeb4',fitzpatrick_scale:!0,category:"activity"},mountain_biking_woman:{keywords:["transportation","sports","human","race","bike","woman","female"],"char":'\ud83d\udeb5\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},mountain_biking_man:{keywords:["transportation","sports","human","race","bike"],"char":'\ud83d\udeb5',fitzpatrick_scale:!0,category:"activity"},horse_racing:{keywords:["animal","betting","competition","gambling","luck"],"char":'\ud83c\udfc7',fitzpatrick_scale:!0,category:"activity"},business_suit_levitating:{keywords:["suit","business","levitate","hover","jump"],"char":'\ud83d\udd74',fitzpatrick_scale:!0,category:"activity"},trophy:{keywords:["win","award","contest","place","ftw","ceremony"],"char":'\ud83c\udfc6',fitzpatrick_scale:!1,category:"activity"},running_shirt_with_sash:{keywords:["play","pageant"],"char":'\ud83c\udfbd',fitzpatrick_scale:!1,category:"activity"},medal_sports:{keywords:["award","winning"],"char":'\ud83c\udfc5',fitzpatrick_scale:!1,category:"activity"},medal_military:{keywords:["award","winning","army"],"char":'\ud83c\udf96',fitzpatrick_scale:!1,category:"activity"},"1st_place_medal":{keywords:["award","winning","first"],"char":'\ud83e\udd47',fitzpatrick_scale:!1,category:"activity"},"2nd_place_medal":{keywords:["award","second"],"char":'\ud83e\udd48',fitzpatrick_scale:!1,category:"activity"},"3rd_place_medal":{keywords:["award","third"],"char":'\ud83e\udd49',fitzpatrick_scale:!1,category:"activity"},reminder_ribbon:{keywords:["sports","cause","support","awareness"],"char":'\ud83c\udf97',fitzpatrick_scale:!1,category:"activity"},rosette:{keywords:["flower","decoration","military"],"char":'\ud83c\udff5',fitzpatrick_scale:!1,category:"activity"},ticket:{keywords:["event","concert","pass"],"char":'\ud83c\udfab',fitzpatrick_scale:!1,category:"activity"},tickets:{keywords:["sports","concert","entrance"],"char":'\ud83c\udf9f',fitzpatrick_scale:!1,category:"activity"},performing_arts:{keywords:["acting","theater","drama"],"char":'\ud83c\udfad',fitzpatrick_scale:!1,category:"activity"},art:{keywords:["design","paint","draw","colors"],"char":'\ud83c\udfa8',fitzpatrick_scale:!1,category:"activity"},circus_tent:{keywords:["festival","carnival","party"],"char":'\ud83c\udfaa',fitzpatrick_scale:!1,category:"activity"},woman_juggling:{keywords:["juggle","balance","skill","multitask"],"char":'\ud83e\udd39\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_juggling:{keywords:["juggle","balance","skill","multitask"],"char":'\ud83e\udd39\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},microphone:{keywords:["sound","music","PA","sing","talkshow"],"char":'\ud83c\udfa4',fitzpatrick_scale:!1,category:"activity"},headphones:{keywords:["music","score","gadgets"],"char":'\ud83c\udfa7',fitzpatrick_scale:!1,category:"activity"},musical_score:{keywords:["treble","clef","compose"],"char":'\ud83c\udfbc',fitzpatrick_scale:!1,category:"activity"},musical_keyboard:{keywords:["piano","instrument","compose"],"char":'\ud83c\udfb9',fitzpatrick_scale:!1,category:"activity"},drum:{keywords:["music","instrument","drumsticks","snare"],"char":'\ud83e\udd41',fitzpatrick_scale:!1,category:"activity"},saxophone:{keywords:["music","instrument","jazz","blues"],"char":'\ud83c\udfb7',fitzpatrick_scale:!1,category:"activity"},trumpet:{keywords:["music","brass"],"char":'\ud83c\udfba',fitzpatrick_scale:!1,category:"activity"},guitar:{keywords:["music","instrument"],"char":'\ud83c\udfb8',fitzpatrick_scale:!1,category:"activity"},violin:{keywords:["music","instrument","orchestra","symphony"],"char":'\ud83c\udfbb',fitzpatrick_scale:!1,category:"activity"},clapper:{keywords:["movie","film","record"],"char":'\ud83c\udfac',fitzpatrick_scale:!1,category:"activity"},video_game:{keywords:["play","console","PS4","controller"],"char":'\ud83c\udfae',fitzpatrick_scale:!1,category:"activity"},space_invader:{keywords:["game","arcade","play"],"char":'\ud83d\udc7e',fitzpatrick_scale:!1,category:"activity"},dart:{keywords:["game","play","bar","target","bullseye"],"char":'\ud83c\udfaf',fitzpatrick_scale:!1,category:"activity"},game_die:{keywords:["dice","random","tabletop","play","luck"],"char":'\ud83c\udfb2',fitzpatrick_scale:!1,category:"activity"},chess_pawn:{keywords:["expendable"],"char":"\u265f",fitzpatrick_scale:!1,category:"activity"},slot_machine:{keywords:["bet","gamble","vegas","fruit machine","luck","casino"],"char":'\ud83c\udfb0',fitzpatrick_scale:!1,category:"activity"},jigsaw:{keywords:["interlocking","puzzle","piece"],"char":'\ud83e\udde9',fitzpatrick_scale:!1,category:"activity"},bowling:{keywords:["sports","fun","play"],"char":'\ud83c\udfb3',fitzpatrick_scale:!1,category:"activity"},red_car:{keywords:["red","transportation","vehicle"],"char":'\ud83d\ude97',fitzpatrick_scale:!1,category:"travel_and_places"},taxi:{keywords:["uber","vehicle","cars","transportation"],"char":'\ud83d\ude95',fitzpatrick_scale:!1,category:"travel_and_places"},blue_car:{keywords:["transportation","vehicle"],"char":'\ud83d\ude99',fitzpatrick_scale:!1,category:"travel_and_places"},bus:{keywords:["car","vehicle","transportation"],"char":'\ud83d\ude8c',fitzpatrick_scale:!1,category:"travel_and_places"},trolleybus:{keywords:["bart","transportation","vehicle"],"char":'\ud83d\ude8e',fitzpatrick_scale:!1,category:"travel_and_places"},racing_car:{keywords:["sports","race","fast","formula","f1"],"char":'\ud83c\udfce',fitzpatrick_scale:!1,category:"travel_and_places"},police_car:{keywords:["vehicle","cars","transportation","law","legal","enforcement"],"char":'\ud83d\ude93',fitzpatrick_scale:!1,category:"travel_and_places"},ambulance:{keywords:["health","911","hospital"],"char":'\ud83d\ude91',fitzpatrick_scale:!1,category:"travel_and_places"},fire_engine:{keywords:["transportation","cars","vehicle"],"char":'\ud83d\ude92',fitzpatrick_scale:!1,category:"travel_and_places"},minibus:{keywords:["vehicle","car","transportation"],"char":'\ud83d\ude90',fitzpatrick_scale:!1,category:"travel_and_places"},truck:{keywords:["cars","transportation"],"char":'\ud83d\ude9a',fitzpatrick_scale:!1,category:"travel_and_places"},articulated_lorry:{keywords:["vehicle","cars","transportation","express"],"char":'\ud83d\ude9b',fitzpatrick_scale:!1,category:"travel_and_places"},tractor:{keywords:["vehicle","car","farming","agriculture"],"char":'\ud83d\ude9c',fitzpatrick_scale:!1,category:"travel_and_places"},kick_scooter:{keywords:["vehicle","kick","razor"],"char":'\ud83d\udef4',fitzpatrick_scale:!1,category:"travel_and_places"},motorcycle:{keywords:["race","sports","fast"],"char":'\ud83c\udfcd',fitzpatrick_scale:!1,category:"travel_and_places"},bike:{keywords:["sports","bicycle","exercise","hipster"],"char":'\ud83d\udeb2',fitzpatrick_scale:!1,category:"travel_and_places"},motor_scooter:{keywords:["vehicle","vespa","sasha"],"char":'\ud83d\udef5',fitzpatrick_scale:!1,category:"travel_and_places"},rotating_light:{keywords:["police","ambulance","911","emergency","alert","error","pinged","law","legal"],"char":'\ud83d\udea8',fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_police_car:{keywords:["vehicle","law","legal","enforcement","911"],"char":'\ud83d\ude94',fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_bus:{keywords:["vehicle","transportation"],"char":'\ud83d\ude8d',fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_automobile:{keywords:["car","vehicle","transportation"],"char":'\ud83d\ude98',fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_taxi:{keywords:["vehicle","cars","uber"],"char":'\ud83d\ude96',fitzpatrick_scale:!1,category:"travel_and_places"},aerial_tramway:{keywords:["transportation","vehicle","ski"],"char":'\ud83d\udea1',fitzpatrick_scale:!1,category:"travel_and_places"},mountain_cableway:{keywords:["transportation","vehicle","ski"],"char":'\ud83d\udea0',fitzpatrick_scale:!1,category:"travel_and_places"},suspension_railway:{keywords:["vehicle","transportation"],"char":'\ud83d\ude9f',fitzpatrick_scale:!1,category:"travel_and_places"},railway_car:{keywords:["transportation","vehicle"],"char":'\ud83d\ude83',fitzpatrick_scale:!1,category:"travel_and_places"},train:{keywords:["transportation","vehicle","carriage","public","travel"],"char":'\ud83d\ude8b',fitzpatrick_scale:!1,category:"travel_and_places"},monorail:{keywords:["transportation","vehicle"],"char":'\ud83d\ude9d',fitzpatrick_scale:!1,category:"travel_and_places"},bullettrain_side:{keywords:["transportation","vehicle"],"char":'\ud83d\ude84',fitzpatrick_scale:!1,category:"travel_and_places"},bullettrain_front:{keywords:["transportation","vehicle","speed","fast","public","travel"],"char":'\ud83d\ude85',fitzpatrick_scale:!1,category:"travel_and_places"},light_rail:{keywords:["transportation","vehicle"],"char":'\ud83d\ude88',fitzpatrick_scale:!1,category:"travel_and_places"},mountain_railway:{keywords:["transportation","vehicle"],"char":'\ud83d\ude9e',fitzpatrick_scale:!1,category:"travel_and_places"},steam_locomotive:{keywords:["transportation","vehicle","train"],"char":'\ud83d\ude82',fitzpatrick_scale:!1,category:"travel_and_places"},train2:{keywords:["transportation","vehicle"],"char":'\ud83d\ude86',fitzpatrick_scale:!1,category:"travel_and_places"},metro:{keywords:["transportation","blue-square","mrt","underground","tube"],"char":'\ud83d\ude87',fitzpatrick_scale:!1,category:"travel_and_places"},tram:{keywords:["transportation","vehicle"],"char":'\ud83d\ude8a',fitzpatrick_scale:!1,category:"travel_and_places"},station:{keywords:["transportation","vehicle","public"],"char":'\ud83d\ude89',fitzpatrick_scale:!1,category:"travel_and_places"},flying_saucer:{keywords:["transportation","vehicle","ufo"],"char":'\ud83d\udef8',fitzpatrick_scale:!1,category:"travel_and_places"},helicopter:{keywords:["transportation","vehicle","fly"],"char":'\ud83d\ude81',fitzpatrick_scale:!1,category:"travel_and_places"},small_airplane:{keywords:["flight","transportation","fly","vehicle"],"char":'\ud83d\udee9',fitzpatrick_scale:!1,category:"travel_and_places"},airplane:{keywords:["vehicle","transportation","flight","fly"],"char":'\u2708\ufe0f',fitzpatrick_scale:!1,category:"travel_and_places"},flight_departure:{keywords:["airport","flight","landing"],"char":'\ud83d\udeeb',fitzpatrick_scale:!1,category:"travel_and_places"},flight_arrival:{keywords:["airport","flight","boarding"],"char":'\ud83d\udeec',fitzpatrick_scale:!1,category:"travel_and_places"},sailboat:{keywords:["ship","summer","transportation","water","sailing"],"char":'\u26f5',fitzpatrick_scale:!1,category:"travel_and_places"},motor_boat:{keywords:["ship"],"char":'\ud83d\udee5',fitzpatrick_scale:!1,category:"travel_and_places"},speedboat:{keywords:["ship","transportation","vehicle","summer"],"char":'\ud83d\udea4',fitzpatrick_scale:!1,category:"travel_and_places"},ferry:{keywords:["boat","ship","yacht"],"char":'\u26f4',fitzpatrick_scale:!1,category:"travel_and_places"},passenger_ship:{keywords:["yacht","cruise","ferry"],"char":'\ud83d\udef3',fitzpatrick_scale:!1,category:"travel_and_places"},rocket:{keywords:["launch","ship","staffmode","NASA","outer space","outer_space","fly"],"char":'\ud83d\ude80',fitzpatrick_scale:!1,category:"travel_and_places"},artificial_satellite:{keywords:["communication","gps","orbit","spaceflight","NASA","ISS"],"char":'\ud83d\udef0',fitzpatrick_scale:!1,category:"travel_and_places"},seat:{keywords:["sit","airplane","transport","bus","flight","fly"],"char":'\ud83d\udcba',fitzpatrick_scale:!1,category:"travel_and_places"},canoe:{keywords:["boat","paddle","water","ship"],"char":'\ud83d\udef6',fitzpatrick_scale:!1,category:"travel_and_places"},anchor:{keywords:["ship","ferry","sea","boat"],"char":'\u2693',fitzpatrick_scale:!1,category:"travel_and_places"},construction:{keywords:["wip","progress","caution","warning"],"char":'\ud83d\udea7',fitzpatrick_scale:!1,category:"travel_and_places"},fuelpump:{keywords:["gas station","petroleum"],"char":'\u26fd',fitzpatrick_scale:!1,category:"travel_and_places"},busstop:{keywords:["transportation","wait"],"char":'\ud83d\ude8f',fitzpatrick_scale:!1,category:"travel_and_places"},vertical_traffic_light:{keywords:["transportation","driving"],"char":'\ud83d\udea6',fitzpatrick_scale:!1,category:"travel_and_places"},traffic_light:{keywords:["transportation","signal"],"char":'\ud83d\udea5',fitzpatrick_scale:!1,category:"travel_and_places"},checkered_flag:{keywords:["contest","finishline","race","gokart"],"char":'\ud83c\udfc1',fitzpatrick_scale:!1,category:"travel_and_places"},ship:{keywords:["transportation","titanic","deploy"],"char":'\ud83d\udea2',fitzpatrick_scale:!1,category:"travel_and_places"},ferris_wheel:{keywords:["photo","carnival","londoneye"],"char":'\ud83c\udfa1',fitzpatrick_scale:!1,category:"travel_and_places"},roller_coaster:{keywords:["carnival","playground","photo","fun"],"char":'\ud83c\udfa2',fitzpatrick_scale:!1,category:"travel_and_places"},carousel_horse:{keywords:["photo","carnival"],"char":'\ud83c\udfa0',fitzpatrick_scale:!1,category:"travel_and_places"},building_construction:{keywords:["wip","working","progress"],"char":'\ud83c\udfd7',fitzpatrick_scale:!1,category:"travel_and_places"},foggy:{keywords:["photo","mountain"],"char":'\ud83c\udf01',fitzpatrick_scale:!1,category:"travel_and_places"},tokyo_tower:{keywords:["photo","japanese"],"char":'\ud83d\uddfc',fitzpatrick_scale:!1,category:"travel_and_places"},factory:{keywords:["building","industry","pollution","smoke"],"char":'\ud83c\udfed',fitzpatrick_scale:!1,category:"travel_and_places"},fountain:{keywords:["photo","summer","water","fresh"],"char":'\u26f2',fitzpatrick_scale:!1,category:"travel_and_places"},rice_scene:{keywords:["photo","japan","asia","tsukimi"],"char":'\ud83c\udf91',fitzpatrick_scale:!1,category:"travel_and_places"},mountain:{keywords:["photo","nature","environment"],"char":'\u26f0',fitzpatrick_scale:!1,category:"travel_and_places"},mountain_snow:{keywords:["photo","nature","environment","winter","cold"],"char":'\ud83c\udfd4',fitzpatrick_scale:!1,category:"travel_and_places"},mount_fuji:{keywords:["photo","mountain","nature","japanese"],"char":'\ud83d\uddfb',fitzpatrick_scale:!1,category:"travel_and_places"},volcano:{keywords:["photo","nature","disaster"],"char":'\ud83c\udf0b',fitzpatrick_scale:!1,category:"travel_and_places"},japan:{keywords:["nation","country","japanese","asia"],"char":'\ud83d\uddfe',fitzpatrick_scale:!1,category:"travel_and_places"},camping:{keywords:["photo","outdoors","tent"],"char":'\ud83c\udfd5',fitzpatrick_scale:!1,category:"travel_and_places"},tent:{keywords:["photo","camping","outdoors"],"char":'\u26fa',fitzpatrick_scale:!1,category:"travel_and_places"},national_park:{keywords:["photo","environment","nature"],"char":'\ud83c\udfde',fitzpatrick_scale:!1,category:"travel_and_places"},motorway:{keywords:["road","cupertino","interstate","highway"],"char":'\ud83d\udee3',fitzpatrick_scale:!1,category:"travel_and_places"},railway_track:{keywords:["train","transportation"],"char":'\ud83d\udee4',fitzpatrick_scale:!1,category:"travel_and_places"},sunrise:{keywords:["morning","view","vacation","photo"],"char":'\ud83c\udf05',fitzpatrick_scale:!1,category:"travel_and_places"},sunrise_over_mountains:{keywords:["view","vacation","photo"],"char":'\ud83c\udf04',fitzpatrick_scale:!1,category:"travel_and_places"},desert:{keywords:["photo","warm","saharah"],"char":'\ud83c\udfdc',fitzpatrick_scale:!1,category:"travel_and_places"},beach_umbrella:{keywords:["weather","summer","sunny","sand","mojito"],"char":'\ud83c\udfd6',fitzpatrick_scale:!1,category:"travel_and_places"},desert_island:{keywords:["photo","tropical","mojito"],"char":'\ud83c\udfdd',fitzpatrick_scale:!1,category:"travel_and_places"},city_sunrise:{keywords:["photo","good morning","dawn"],"char":'\ud83c\udf07',fitzpatrick_scale:!1,category:"travel_and_places"},city_sunset:{keywords:["photo","evening","sky","buildings"],"char":'\ud83c\udf06',fitzpatrick_scale:!1,category:"travel_and_places"},cityscape:{keywords:["photo","night life","urban"],"char":'\ud83c\udfd9',fitzpatrick_scale:!1,category:"travel_and_places"},night_with_stars:{keywords:["evening","city","downtown"],"char":'\ud83c\udf03',fitzpatrick_scale:!1,category:"travel_and_places"},bridge_at_night:{keywords:["photo","sanfrancisco"],"char":'\ud83c\udf09',fitzpatrick_scale:!1,category:"travel_and_places"},milky_way:{keywords:["photo","space","stars"],"char":'\ud83c\udf0c',fitzpatrick_scale:!1,category:"travel_and_places"},stars:{keywords:["night","photo"],"char":'\ud83c\udf20',fitzpatrick_scale:!1,category:"travel_and_places"},sparkler:{keywords:["stars","night","shine"],"char":'\ud83c\udf87',fitzpatrick_scale:!1,category:"travel_and_places"},fireworks:{keywords:["photo","festival","carnival","congratulations"],"char":'\ud83c\udf86',fitzpatrick_scale:!1,category:"travel_and_places"},rainbow:{keywords:["nature","happy","unicorn_face","photo","sky","spring"],"char":'\ud83c\udf08',fitzpatrick_scale:!1,category:"travel_and_places"},houses:{keywords:["buildings","photo"],"char":'\ud83c\udfd8',fitzpatrick_scale:!1,category:"travel_and_places"},european_castle:{keywords:["building","royalty","history"],"char":'\ud83c\udff0',fitzpatrick_scale:!1,category:"travel_and_places"},japanese_castle:{keywords:["photo","building"],"char":'\ud83c\udfef',fitzpatrick_scale:!1,category:"travel_and_places"},stadium:{keywords:["photo","place","sports","concert","venue"],"char":'\ud83c\udfdf',fitzpatrick_scale:!1,category:"travel_and_places"},statue_of_liberty:{keywords:["american","newyork"],"char":'\ud83d\uddfd',fitzpatrick_scale:!1,category:"travel_and_places"},house:{keywords:["building","home"],"char":'\ud83c\udfe0',fitzpatrick_scale:!1,category:"travel_and_places"},house_with_garden:{keywords:["home","plant","nature"],"char":'\ud83c\udfe1',fitzpatrick_scale:!1,category:"travel_and_places"},derelict_house:{keywords:["abandon","evict","broken","building"],"char":'\ud83c\udfda',fitzpatrick_scale:!1,category:"travel_and_places"},office:{keywords:["building","bureau","work"],"char":'\ud83c\udfe2',fitzpatrick_scale:!1,category:"travel_and_places"},department_store:{keywords:["building","shopping","mall"],"char":'\ud83c\udfec',fitzpatrick_scale:!1,category:"travel_and_places"},post_office:{keywords:["building","envelope","communication"],"char":'\ud83c\udfe3',fitzpatrick_scale:!1,category:"travel_and_places"},european_post_office:{keywords:["building","email"],"char":'\ud83c\udfe4',fitzpatrick_scale:!1,category:"travel_and_places"},hospital:{keywords:["building","health","surgery","doctor"],"char":'\ud83c\udfe5',fitzpatrick_scale:!1,category:"travel_and_places"},bank:{keywords:["building","money","sales","cash","business","enterprise"],"char":'\ud83c\udfe6',fitzpatrick_scale:!1,category:"travel_and_places"},hotel:{keywords:["building","accomodation","checkin"],"char":'\ud83c\udfe8',fitzpatrick_scale:!1,category:"travel_and_places"},convenience_store:{keywords:["building","shopping","groceries"],"char":'\ud83c\udfea',fitzpatrick_scale:!1,category:"travel_and_places"},school:{keywords:["building","student","education","learn","teach"],"char":'\ud83c\udfeb',fitzpatrick_scale:!1,category:"travel_and_places"},love_hotel:{keywords:["like","affection","dating"],"char":'\ud83c\udfe9',fitzpatrick_scale:!1,category:"travel_and_places"},wedding:{keywords:["love","like","affection","couple","marriage","bride","groom"],"char":'\ud83d\udc92',fitzpatrick_scale:!1,category:"travel_and_places"},classical_building:{keywords:["art","culture","history"],"char":'\ud83c\udfdb',fitzpatrick_scale:!1,category:"travel_and_places"},church:{keywords:["building","religion","christ"],"char":'\u26ea',fitzpatrick_scale:!1,category:"travel_and_places"},mosque:{keywords:["islam","worship","minaret"],"char":'\ud83d\udd4c',fitzpatrick_scale:!1,category:"travel_and_places"},synagogue:{keywords:["judaism","worship","temple","jewish"],"char":'\ud83d\udd4d',fitzpatrick_scale:!1,category:"travel_and_places"},kaaba:{keywords:["mecca","mosque","islam"],"char":'\ud83d\udd4b',fitzpatrick_scale:!1,category:"travel_and_places"},shinto_shrine:{keywords:["temple","japan","kyoto"],"char":'\u26e9',fitzpatrick_scale:!1,category:"travel_and_places"},watch:{keywords:["time","accessories"],"char":'\u231a',fitzpatrick_scale:!1,category:"objects"},iphone:{keywords:["technology","apple","gadgets","dial"],"char":'\ud83d\udcf1',fitzpatrick_scale:!1,category:"objects"},calling:{keywords:["iphone","incoming"],"char":'\ud83d\udcf2',fitzpatrick_scale:!1,category:"objects"},computer:{keywords:["technology","laptop","screen","display","monitor"],"char":'\ud83d\udcbb',fitzpatrick_scale:!1,category:"objects"},keyboard:{keywords:["technology","computer","type","input","text"],"char":'\u2328',fitzpatrick_scale:!1,category:"objects"},desktop_computer:{keywords:["technology","computing","screen"],"char":'\ud83d\udda5',fitzpatrick_scale:!1,category:"objects"},printer:{keywords:["paper","ink"],"char":'\ud83d\udda8',fitzpatrick_scale:!1,category:"objects"},computer_mouse:{keywords:["click"],"char":'\ud83d\uddb1',fitzpatrick_scale:!1,category:"objects"},trackball:{keywords:["technology","trackpad"],"char":'\ud83d\uddb2',fitzpatrick_scale:!1,category:"objects"},joystick:{keywords:["game","play"],"char":'\ud83d\udd79',fitzpatrick_scale:!1,category:"objects"},clamp:{keywords:["tool"],"char":'\ud83d\udddc',fitzpatrick_scale:!1,category:"objects"},minidisc:{keywords:["technology","record","data","disk","90s"],"char":'\ud83d\udcbd',fitzpatrick_scale:!1,category:"objects"},floppy_disk:{keywords:["oldschool","technology","save","90s","80s"],"char":'\ud83d\udcbe',fitzpatrick_scale:!1,category:"objects"},cd:{keywords:["technology","dvd","disk","disc","90s"],"char":'\ud83d\udcbf',fitzpatrick_scale:!1,category:"objects"},dvd:{keywords:["cd","disk","disc"],"char":'\ud83d\udcc0',fitzpatrick_scale:!1,category:"objects"},vhs:{keywords:["record","video","oldschool","90s","80s"],"char":'\ud83d\udcfc',fitzpatrick_scale:!1,category:"objects"},camera:{keywords:["gadgets","photography"],"char":'\ud83d\udcf7',fitzpatrick_scale:!1,category:"objects"},camera_flash:{keywords:["photography","gadgets"],"char":'\ud83d\udcf8',fitzpatrick_scale:!1,category:"objects"},video_camera:{keywords:["film","record"],"char":'\ud83d\udcf9',fitzpatrick_scale:!1,category:"objects"},movie_camera:{keywords:["film","record"],"char":'\ud83c\udfa5',fitzpatrick_scale:!1,category:"objects"},film_projector:{keywords:["video","tape","record","movie"],"char":'\ud83d\udcfd',fitzpatrick_scale:!1,category:"objects"},film_strip:{keywords:["movie"],"char":'\ud83c\udf9e',fitzpatrick_scale:!1,category:"objects"},telephone_receiver:{keywords:["technology","communication","dial"],"char":'\ud83d\udcde',fitzpatrick_scale:!1,category:"objects"},phone:{keywords:["technology","communication","dial","telephone"],"char":'\u260e\ufe0f',fitzpatrick_scale:!1,category:"objects"},pager:{keywords:["bbcall","oldschool","90s"],"char":'\ud83d\udcdf',fitzpatrick_scale:!1,category:"objects"},fax:{keywords:["communication","technology"],"char":'\ud83d\udce0',fitzpatrick_scale:!1,category:"objects"},tv:{keywords:["technology","program","oldschool","show","television"],"char":'\ud83d\udcfa',fitzpatrick_scale:!1,category:"objects"},radio:{keywords:["communication","music","podcast","program"],"char":'\ud83d\udcfb',fitzpatrick_scale:!1,category:"objects"},studio_microphone:{keywords:["sing","recording","artist","talkshow"],"char":'\ud83c\udf99',fitzpatrick_scale:!1,category:"objects"},level_slider:{keywords:["scale"],"char":'\ud83c\udf9a',fitzpatrick_scale:!1,category:"objects"},control_knobs:{keywords:["dial"],"char":'\ud83c\udf9b',fitzpatrick_scale:!1,category:"objects"},compass:{keywords:["magnetic","navigation","orienteering"],"char":'\ud83e\udded',fitzpatrick_scale:!1,category:"objects"},stopwatch:{keywords:["time","deadline"],"char":'\u23f1',fitzpatrick_scale:!1,category:"objects"},timer_clock:{keywords:["alarm"],"char":'\u23f2',fitzpatrick_scale:!1,category:"objects"},alarm_clock:{keywords:["time","wake"],"char":'\u23f0',fitzpatrick_scale:!1,category:"objects"},mantelpiece_clock:{keywords:["time"],"char":'\ud83d\udd70',fitzpatrick_scale:!1,category:"objects"},hourglass_flowing_sand:{keywords:["oldschool","time","countdown"],"char":'\u23f3',fitzpatrick_scale:!1,category:"objects"},hourglass:{keywords:["time","clock","oldschool","limit","exam","quiz","test"],"char":'\u231b',fitzpatrick_scale:!1,category:"objects"},satellite:{keywords:["communication","future","radio","space"],"char":'\ud83d\udce1',fitzpatrick_scale:!1,category:"objects"},battery:{keywords:["power","energy","sustain"],"char":'\ud83d\udd0b',fitzpatrick_scale:!1,category:"objects"},electric_plug:{keywords:["charger","power"],"char":'\ud83d\udd0c',fitzpatrick_scale:!1,category:"objects"},bulb:{keywords:["light","electricity","idea"],"char":'\ud83d\udca1',fitzpatrick_scale:!1,category:"objects"},flashlight:{keywords:["dark","camping","sight","night"],"char":'\ud83d\udd26',fitzpatrick_scale:!1,category:"objects"},candle:{keywords:["fire","wax"],"char":'\ud83d\udd6f',fitzpatrick_scale:!1,category:"objects"},fire_extinguisher:{keywords:["quench"],"char":'\ud83e\uddef',fitzpatrick_scale:!1,category:"objects"},wastebasket:{keywords:["bin","trash","rubbish","garbage","toss"],"char":'\ud83d\uddd1',fitzpatrick_scale:!1,category:"objects"},oil_drum:{keywords:["barrell"],"char":'\ud83d\udee2',fitzpatrick_scale:!1,category:"objects"},money_with_wings:{keywords:["dollar","bills","payment","sale"],"char":'\ud83d\udcb8',fitzpatrick_scale:!1,category:"objects"},dollar:{keywords:["money","sales","bill","currency"],"char":'\ud83d\udcb5',fitzpatrick_scale:!1,category:"objects"},yen:{keywords:["money","sales","japanese","dollar","currency"],"char":'\ud83d\udcb4',fitzpatrick_scale:!1,category:"objects"},euro:{keywords:["money","sales","dollar","currency"],"char":'\ud83d\udcb6',fitzpatrick_scale:!1,category:"objects"},pound:{keywords:["british","sterling","money","sales","bills","uk","england","currency"],"char":'\ud83d\udcb7',fitzpatrick_scale:!1,category:"objects"},moneybag:{keywords:["dollar","payment","coins","sale"],"char":'\ud83d\udcb0',fitzpatrick_scale:!1,category:"objects"},credit_card:{keywords:["money","sales","dollar","bill","payment","shopping"],"char":'\ud83d\udcb3',fitzpatrick_scale:!1,category:"objects"},gem:{keywords:["blue","ruby","diamond","jewelry"],"char":'\ud83d\udc8e',fitzpatrick_scale:!1,category:"objects"},balance_scale:{keywords:["law","fairness","weight"],"char":'\u2696',fitzpatrick_scale:!1,category:"objects"},toolbox:{keywords:["tools","diy","fix","maintainer","mechanic"],"char":'\ud83e\uddf0',fitzpatrick_scale:!1,category:"objects"},wrench:{keywords:["tools","diy","ikea","fix","maintainer"],"char":'\ud83d\udd27',fitzpatrick_scale:!1,category:"objects"},hammer:{keywords:["tools","build","create"],"char":'\ud83d\udd28',fitzpatrick_scale:!1,category:"objects"},hammer_and_pick:{keywords:["tools","build","create"],"char":'\u2692',fitzpatrick_scale:!1,category:"objects"},hammer_and_wrench:{keywords:["tools","build","create"],"char":'\ud83d\udee0',fitzpatrick_scale:!1,category:"objects"},pick:{keywords:["tools","dig"],"char":'\u26cf',fitzpatrick_scale:!1,category:"objects"},nut_and_bolt:{keywords:["handy","tools","fix"],"char":'\ud83d\udd29',fitzpatrick_scale:!1,category:"objects"},gear:{keywords:["cog"],"char":'\u2699',fitzpatrick_scale:!1,category:"objects"},brick:{keywords:["bricks"],"char":'\ud83e\uddf1',fitzpatrick_scale:!1,category:"objects"},chains:{keywords:["lock","arrest"],"char":'\u26d3',fitzpatrick_scale:!1,category:"objects"},magnet:{keywords:["attraction","magnetic"],"char":'\ud83e\uddf2',fitzpatrick_scale:!1,category:"objects"},gun:{keywords:["violence","weapon","pistol","revolver"],"char":'\ud83d\udd2b',fitzpatrick_scale:!1,category:"objects"},bomb:{keywords:["boom","explode","explosion","terrorism"],"char":'\ud83d\udca3',fitzpatrick_scale:!1,category:"objects"},firecracker:{keywords:["dynamite","boom","explode","explosion","explosive"],"char":'\ud83e\udde8',fitzpatrick_scale:!1,category:"objects"},hocho:{keywords:["knife","blade","cutlery","kitchen","weapon"],"char":'\ud83d\udd2a',fitzpatrick_scale:!1,category:"objects"},dagger:{keywords:["weapon"],"char":'\ud83d\udde1',fitzpatrick_scale:!1,category:"objects"},crossed_swords:{keywords:["weapon"],"char":'\u2694',fitzpatrick_scale:!1,category:"objects"},shield:{keywords:["protection","security"],"char":'\ud83d\udee1',fitzpatrick_scale:!1,category:"objects"},smoking:{keywords:["kills","tobacco","cigarette","joint","smoke"],"char":'\ud83d\udeac',fitzpatrick_scale:!1,category:"objects"},skull_and_crossbones:{keywords:["poison","danger","deadly","scary","death","pirate","evil"],"char":'\u2620',fitzpatrick_scale:!1,category:"objects"},coffin:{keywords:["vampire","dead","die","death","rip","graveyard","cemetery","casket","funeral","box"],"char":'\u26b0',fitzpatrick_scale:!1,category:"objects"},funeral_urn:{keywords:["dead","die","death","rip","ashes"],"char":'\u26b1',fitzpatrick_scale:!1,category:"objects"},amphora:{keywords:["vase","jar"],"char":'\ud83c\udffa',fitzpatrick_scale:!1,category:"objects"},crystal_ball:{keywords:["disco","party","magic","circus","fortune_teller"],"char":'\ud83d\udd2e',fitzpatrick_scale:!1,category:"objects"},prayer_beads:{keywords:["dhikr","religious"],"char":'\ud83d\udcff',fitzpatrick_scale:!1,category:"objects"},nazar_amulet:{keywords:["bead","charm"],"char":'\ud83e\uddff',fitzpatrick_scale:!1,category:"objects"},barber:{keywords:["hair","salon","style"],"char":'\ud83d\udc88',fitzpatrick_scale:!1,category:"objects"},alembic:{keywords:["distilling","science","experiment","chemistry"],"char":'\u2697',fitzpatrick_scale:!1,category:"objects"},telescope:{keywords:["stars","space","zoom","science","astronomy"],"char":'\ud83d\udd2d',fitzpatrick_scale:!1,category:"objects"},microscope:{keywords:["laboratory","experiment","zoomin","science","study"],"char":'\ud83d\udd2c',fitzpatrick_scale:!1,category:"objects"},hole:{keywords:["embarrassing"],"char":'\ud83d\udd73',fitzpatrick_scale:!1,category:"objects"},pill:{keywords:["health","medicine","doctor","pharmacy","drug"],"char":'\ud83d\udc8a',fitzpatrick_scale:!1,category:"objects"},syringe:{keywords:["health","hospital","drugs","blood","medicine","needle","doctor","nurse"],"char":'\ud83d\udc89',fitzpatrick_scale:!1,category:"objects"},dna:{keywords:["biologist","genetics","life"],"char":'\ud83e\uddec',fitzpatrick_scale:!1,category:"objects"},microbe:{keywords:["amoeba","bacteria","germs"],"char":'\ud83e\udda0',fitzpatrick_scale:!1,category:"objects"},petri_dish:{keywords:["bacteria","biology","culture","lab"],"char":'\ud83e\uddeb',fitzpatrick_scale:!1,category:"objects"},test_tube:{keywords:["chemistry","experiment","lab","science"],"char":'\ud83e\uddea',fitzpatrick_scale:!1,category:"objects"},thermometer:{keywords:["weather","temperature","hot","cold"],"char":'\ud83c\udf21',fitzpatrick_scale:!1,category:"objects"},broom:{keywords:["cleaning","sweeping","witch"],"char":'\ud83e\uddf9',fitzpatrick_scale:!1,category:"objects"},basket:{keywords:["laundry"],"char":'\ud83e\uddfa',fitzpatrick_scale:!1,category:"objects"},toilet_paper:{keywords:["roll"],"char":'\ud83e\uddfb',fitzpatrick_scale:!1,category:"objects"},label:{keywords:["sale","tag"],"char":'\ud83c\udff7',fitzpatrick_scale:!1,category:"objects"},bookmark:{keywords:["favorite","label","save"],"char":'\ud83d\udd16',fitzpatrick_scale:!1,category:"objects"},toilet:{keywords:["restroom","wc","washroom","bathroom","potty"],"char":'\ud83d\udebd',fitzpatrick_scale:!1,category:"objects"},shower:{keywords:["clean","water","bathroom"],"char":'\ud83d\udebf',fitzpatrick_scale:!1,category:"objects"},bathtub:{keywords:["clean","shower","bathroom"],"char":'\ud83d\udec1',fitzpatrick_scale:!1,category:"objects"},soap:{keywords:["bar","bathing","cleaning","lather"],"char":'\ud83e\uddfc',fitzpatrick_scale:!1,category:"objects"},sponge:{keywords:["absorbing","cleaning","porous"],"char":'\ud83e\uddfd',fitzpatrick_scale:!1,category:"objects"},lotion_bottle:{keywords:["moisturizer","sunscreen"],"char":'\ud83e\uddf4',fitzpatrick_scale:!1,category:"objects"},key:{keywords:["lock","door","password"],"char":'\ud83d\udd11',fitzpatrick_scale:!1,category:"objects"},old_key:{keywords:["lock","door","password"],"char":'\ud83d\udddd',fitzpatrick_scale:!1,category:"objects"},couch_and_lamp:{keywords:["read","chill"],"char":'\ud83d\udecb',fitzpatrick_scale:!1,category:"objects"},sleeping_bed:{keywords:["bed","rest"],"char":'\ud83d\udecc',fitzpatrick_scale:!0,category:"objects"},bed:{keywords:["sleep","rest"],"char":'\ud83d\udecf',fitzpatrick_scale:!1,category:"objects"},door:{keywords:["house","entry","exit"],"char":'\ud83d\udeaa',fitzpatrick_scale:!1,category:"objects"},bellhop_bell:{keywords:["service"],"char":'\ud83d\udece',fitzpatrick_scale:!1,category:"objects"},teddy_bear:{keywords:["plush","stuffed"],"char":'\ud83e\uddf8',fitzpatrick_scale:!1,category:"objects"},framed_picture:{keywords:["photography"],"char":'\ud83d\uddbc',fitzpatrick_scale:!1,category:"objects"},world_map:{keywords:["location","direction"],"char":'\ud83d\uddfa',fitzpatrick_scale:!1,category:"objects"},parasol_on_ground:{keywords:["weather","summer"],"char":'\u26f1',fitzpatrick_scale:!1,category:"objects"},moyai:{keywords:["rock","easter island","moai"],"char":'\ud83d\uddff',fitzpatrick_scale:!1,category:"objects"},shopping:{keywords:["mall","buy","purchase"],"char":'\ud83d\udecd',fitzpatrick_scale:!1,category:"objects"},shopping_cart:{keywords:["trolley"],"char":'\ud83d\uded2',fitzpatrick_scale:!1,category:"objects"},balloon:{keywords:["party","celebration","birthday","circus"],"char":'\ud83c\udf88',fitzpatrick_scale:!1,category:"objects"},flags:{keywords:["fish","japanese","koinobori","carp","banner"],"char":'\ud83c\udf8f',fitzpatrick_scale:!1,category:"objects"},ribbon:{keywords:["decoration","pink","girl","bowtie"],"char":'\ud83c\udf80',fitzpatrick_scale:!1,category:"objects"},gift:{keywords:["present","birthday","christmas","xmas"],"char":'\ud83c\udf81',fitzpatrick_scale:!1,category:"objects"},confetti_ball:{keywords:["festival","party","birthday","circus"],"char":'\ud83c\udf8a',fitzpatrick_scale:!1,category:"objects"},tada:{keywords:["party","congratulations","birthday","magic","circus","celebration"],"char":'\ud83c\udf89',fitzpatrick_scale:!1,category:"objects"},dolls:{keywords:["japanese","toy","kimono"],"char":'\ud83c\udf8e',fitzpatrick_scale:!1,category:"objects"},wind_chime:{keywords:["nature","ding","spring","bell"],"char":'\ud83c\udf90',fitzpatrick_scale:!1,category:"objects"},crossed_flags:{keywords:["japanese","nation","country","border"],"char":'\ud83c\udf8c',fitzpatrick_scale:!1,category:"objects"},izakaya_lantern:{keywords:["light","paper","halloween","spooky"],"char":'\ud83c\udfee',fitzpatrick_scale:!1,category:"objects"},red_envelope:{keywords:["gift"],"char":'\ud83e\udde7',fitzpatrick_scale:!1,category:"objects"},email:{keywords:["letter","postal","inbox","communication"],"char":'\u2709\ufe0f',fitzpatrick_scale:!1,category:"objects"},envelope_with_arrow:{keywords:["email","communication"],"char":'\ud83d\udce9',fitzpatrick_scale:!1,category:"objects"},incoming_envelope:{keywords:["email","inbox"],"char":'\ud83d\udce8',fitzpatrick_scale:!1,category:"objects"},"e-mail":{keywords:["communication","inbox"],"char":'\ud83d\udce7',fitzpatrick_scale:!1,category:"objects"},love_letter:{keywords:["email","like","affection","envelope","valentines"],"char":'\ud83d\udc8c',fitzpatrick_scale:!1,category:"objects"},postbox:{keywords:["email","letter","envelope"],"char":'\ud83d\udcee',fitzpatrick_scale:!1,category:"objects"},mailbox_closed:{keywords:["email","communication","inbox"],"char":'\ud83d\udcea',fitzpatrick_scale:!1,category:"objects"},mailbox:{keywords:["email","inbox","communication"],"char":'\ud83d\udceb',fitzpatrick_scale:!1,category:"objects"},mailbox_with_mail:{keywords:["email","inbox","communication"],"char":'\ud83d\udcec',fitzpatrick_scale:!1,category:"objects"},mailbox_with_no_mail:{keywords:["email","inbox"],"char":'\ud83d\udced',fitzpatrick_scale:!1,category:"objects"},"package":{keywords:["mail","gift","cardboard","box","moving"],"char":'\ud83d\udce6',fitzpatrick_scale:!1,category:"objects"},postal_horn:{keywords:["instrument","music"],"char":'\ud83d\udcef',fitzpatrick_scale:!1,category:"objects"},inbox_tray:{keywords:["email","documents"],"char":'\ud83d\udce5',fitzpatrick_scale:!1,category:"objects"},outbox_tray:{keywords:["inbox","email"],"char":'\ud83d\udce4',fitzpatrick_scale:!1,category:"objects"},scroll:{keywords:["documents","ancient","history","paper"],"char":'\ud83d\udcdc',fitzpatrick_scale:!1,category:"objects"},page_with_curl:{keywords:["documents","office","paper"],"char":'\ud83d\udcc3',fitzpatrick_scale:!1,category:"objects"},bookmark_tabs:{keywords:["favorite","save","order","tidy"],"char":'\ud83d\udcd1',fitzpatrick_scale:!1,category:"objects"},receipt:{keywords:["accounting","expenses"],"char":'\ud83e\uddfe',fitzpatrick_scale:!1,category:"objects"},bar_chart:{keywords:["graph","presentation","stats"],"char":'\ud83d\udcca',fitzpatrick_scale:!1,category:"objects"},chart_with_upwards_trend:{keywords:["graph","presentation","stats","recovery","business","economics","money","sales","good","success"],"char":'\ud83d\udcc8',fitzpatrick_scale:!1,category:"objects"},chart_with_downwards_trend:{keywords:["graph","presentation","stats","recession","business","economics","money","sales","bad","failure"],"char":'\ud83d\udcc9',fitzpatrick_scale:!1,category:"objects"},page_facing_up:{keywords:["documents","office","paper","information"],"char":'\ud83d\udcc4',fitzpatrick_scale:!1,category:"objects"},date:{keywords:["calendar","schedule"],"char":'\ud83d\udcc5',fitzpatrick_scale:!1,category:"objects"},calendar:{keywords:["schedule","date","planning"],"char":'\ud83d\udcc6',fitzpatrick_scale:!1,category:"objects"},spiral_calendar:{keywords:["date","schedule","planning"],"char":'\ud83d\uddd3',fitzpatrick_scale:!1,category:"objects"},card_index:{keywords:["business","stationery"],"char":'\ud83d\udcc7',fitzpatrick_scale:!1,category:"objects"},card_file_box:{keywords:["business","stationery"],"char":'\ud83d\uddc3',fitzpatrick_scale:!1,category:"objects"},ballot_box:{keywords:["election","vote"],"char":'\ud83d\uddf3',fitzpatrick_scale:!1,category:"objects"},file_cabinet:{keywords:["filing","organizing"],"char":'\ud83d\uddc4',fitzpatrick_scale:!1,category:"objects"},clipboard:{keywords:["stationery","documents"],"char":'\ud83d\udccb',fitzpatrick_scale:!1,category:"objects"},spiral_notepad:{keywords:["memo","stationery"],"char":'\ud83d\uddd2',fitzpatrick_scale:!1,category:"objects"},file_folder:{keywords:["documents","business","office"],"char":'\ud83d\udcc1',fitzpatrick_scale:!1,category:"objects"},open_file_folder:{keywords:["documents","load"],"char":'\ud83d\udcc2',fitzpatrick_scale:!1,category:"objects"},card_index_dividers:{keywords:["organizing","business","stationery"],"char":'\ud83d\uddc2',fitzpatrick_scale:!1,category:"objects"},newspaper_roll:{keywords:["press","headline"],"char":'\ud83d\uddde',fitzpatrick_scale:!1,category:"objects"},newspaper:{keywords:["press","headline"],"char":'\ud83d\udcf0',fitzpatrick_scale:!1,category:"objects"},notebook:{keywords:["stationery","record","notes","paper","study"],"char":'\ud83d\udcd3',fitzpatrick_scale:!1,category:"objects"},closed_book:{keywords:["read","library","knowledge","textbook","learn"],"char":'\ud83d\udcd5',fitzpatrick_scale:!1,category:"objects"},green_book:{keywords:["read","library","knowledge","study"],"char":'\ud83d\udcd7',fitzpatrick_scale:!1,category:"objects"},blue_book:{keywords:["read","library","knowledge","learn","study"],"char":'\ud83d\udcd8',fitzpatrick_scale:!1,category:"objects"},orange_book:{keywords:["read","library","knowledge","textbook","study"],"char":'\ud83d\udcd9',fitzpatrick_scale:!1,category:"objects"},notebook_with_decorative_cover:{keywords:["classroom","notes","record","paper","study"],"char":'\ud83d\udcd4',fitzpatrick_scale:!1,category:"objects"},ledger:{keywords:["notes","paper"],"char":'\ud83d\udcd2',fitzpatrick_scale:!1,category:"objects"},books:{keywords:["literature","library","study"],"char":'\ud83d\udcda',fitzpatrick_scale:!1,category:"objects"},open_book:{keywords:["book","read","library","knowledge","literature","learn","study"],"char":'\ud83d\udcd6',fitzpatrick_scale:!1,category:"objects"},safety_pin:{keywords:["diaper"],"char":'\ud83e\uddf7',fitzpatrick_scale:!1,category:"objects"},link:{keywords:["rings","url"],"char":'\ud83d\udd17',fitzpatrick_scale:!1,category:"objects"},paperclip:{keywords:["documents","stationery"],"char":'\ud83d\udcce',fitzpatrick_scale:!1,category:"objects"},paperclips:{keywords:["documents","stationery"],"char":'\ud83d\udd87',fitzpatrick_scale:!1,category:"objects"},scissors:{keywords:["stationery","cut"],"char":'\u2702\ufe0f',fitzpatrick_scale:!1,category:"objects"},triangular_ruler:{keywords:["stationery","math","architect","sketch"],"char":'\ud83d\udcd0',fitzpatrick_scale:!1,category:"objects"},straight_ruler:{keywords:["stationery","calculate","length","math","school","drawing","architect","sketch"],"char":'\ud83d\udccf',fitzpatrick_scale:!1,category:"objects"},abacus:{keywords:["calculation"],"char":'\ud83e\uddee',fitzpatrick_scale:!1,category:"objects"},pushpin:{keywords:["stationery","mark","here"],"char":'\ud83d\udccc',fitzpatrick_scale:!1,category:"objects"},round_pushpin:{keywords:["stationery","location","map","here"],"char":'\ud83d\udccd',fitzpatrick_scale:!1,category:"objects"},triangular_flag_on_post:{keywords:["mark","milestone","place"],"char":'\ud83d\udea9',fitzpatrick_scale:!1,category:"objects"},white_flag:{keywords:["losing","loser","lost","surrender","give up","fail"],"char":'\ud83c\udff3',fitzpatrick_scale:!1,category:"objects"},black_flag:{keywords:["pirate"],"char":'\ud83c\udff4',fitzpatrick_scale:!1,category:"objects"},rainbow_flag:{keywords:["flag","rainbow","pride","gay","lgbt","glbt","queer","homosexual","lesbian","bisexual","transgender"],"char":'\ud83c\udff3\ufe0f\u200d\ud83c\udf08',fitzpatrick_scale:!1,category:"objects"},closed_lock_with_key:{keywords:["security","privacy"],"char":'\ud83d\udd10',fitzpatrick_scale:!1,category:"objects"},lock:{keywords:["security","password","padlock"],"char":'\ud83d\udd12',fitzpatrick_scale:!1,category:"objects"},unlock:{keywords:["privacy","security"],"char":'\ud83d\udd13',fitzpatrick_scale:!1,category:"objects"},lock_with_ink_pen:{keywords:["security","secret"],"char":'\ud83d\udd0f',fitzpatrick_scale:!1,category:"objects"},pen:{keywords:["stationery","writing","write"],"char":'\ud83d\udd8a',fitzpatrick_scale:!1,category:"objects"},fountain_pen:{keywords:["stationery","writing","write"],"char":'\ud83d\udd8b',fitzpatrick_scale:!1,category:"objects"},black_nib:{keywords:["pen","stationery","writing","write"],"char":'\u2712\ufe0f',fitzpatrick_scale:!1,category:"objects"},memo:{keywords:["write","documents","stationery","pencil","paper","writing","legal","exam","quiz","test","study","compose"],"char":'\ud83d\udcdd',fitzpatrick_scale:!1,category:"objects"},pencil2:{keywords:["stationery","write","paper","writing","school","study"],"char":'\u270f\ufe0f',fitzpatrick_scale:!1,category:"objects"},crayon:{keywords:["drawing","creativity"],"char":'\ud83d\udd8d',fitzpatrick_scale:!1,category:"objects"},paintbrush:{keywords:["drawing","creativity","art"],"char":'\ud83d\udd8c',fitzpatrick_scale:!1,category:"objects"},mag:{keywords:["search","zoom","find","detective"],"char":'\ud83d\udd0d',fitzpatrick_scale:!1,category:"objects"},mag_right:{keywords:["search","zoom","find","detective"],"char":'\ud83d\udd0e',fitzpatrick_scale:!1,category:"objects"},heart:{keywords:["love","like","valentines"],"char":'\u2764\ufe0f',fitzpatrick_scale:!1,category:"symbols"},orange_heart:{keywords:["love","like","affection","valentines"],"char":'\ud83e\udde1',fitzpatrick_scale:!1,category:"symbols"},yellow_heart:{keywords:["love","like","affection","valentines"],"char":'\ud83d\udc9b',fitzpatrick_scale:!1,category:"symbols"},green_heart:{keywords:["love","like","affection","valentines"],"char":'\ud83d\udc9a',fitzpatrick_scale:!1,category:"symbols"},blue_heart:{keywords:["love","like","affection","valentines"],"char":'\ud83d\udc99',fitzpatrick_scale:!1,category:"symbols"},purple_heart:{keywords:["love","like","affection","valentines"],"char":'\ud83d\udc9c',fitzpatrick_scale:!1,category:"symbols"},black_heart:{keywords:["evil"],"char":'\ud83d\udda4',fitzpatrick_scale:!1,category:"symbols"},broken_heart:{keywords:["sad","sorry","break","heart","heartbreak"],"char":'\ud83d\udc94',fitzpatrick_scale:!1,category:"symbols"},heavy_heart_exclamation:{keywords:["decoration","love"],"char":'\u2763',fitzpatrick_scale:!1,category:"symbols"},two_hearts:{keywords:["love","like","affection","valentines","heart"],"char":'\ud83d\udc95',fitzpatrick_scale:!1,category:"symbols"},revolving_hearts:{keywords:["love","like","affection","valentines"],"char":'\ud83d\udc9e',fitzpatrick_scale:!1,category:"symbols"},heartbeat:{keywords:["love","like","affection","valentines","pink","heart"],"char":'\ud83d\udc93',fitzpatrick_scale:!1,category:"symbols"},heartpulse:{keywords:["like","love","affection","valentines","pink"],"char":'\ud83d\udc97',fitzpatrick_scale:!1,category:"symbols"},sparkling_heart:{keywords:["love","like","affection","valentines"],"char":'\ud83d\udc96',fitzpatrick_scale:!1,category:"symbols"},cupid:{keywords:["love","like","heart","affection","valentines"],"char":'\ud83d\udc98',fitzpatrick_scale:!1,category:"symbols"},gift_heart:{keywords:["love","valentines"],"char":'\ud83d\udc9d',fitzpatrick_scale:!1,category:"symbols"},heart_decoration:{keywords:["purple-square","love","like"],"char":'\ud83d\udc9f',fitzpatrick_scale:!1,category:"symbols"},peace_symbol:{keywords:["hippie"],"char":'\u262e',fitzpatrick_scale:!1,category:"symbols"},latin_cross:{keywords:["christianity"],"char":'\u271d',fitzpatrick_scale:!1,category:"symbols"},star_and_crescent:{keywords:["islam"],"char":'\u262a',fitzpatrick_scale:!1,category:"symbols"},om:{keywords:["hinduism","buddhism","sikhism","jainism"],"char":'\ud83d\udd49',fitzpatrick_scale:!1,category:"symbols"},wheel_of_dharma:{keywords:["hinduism","buddhism","sikhism","jainism"],"char":'\u2638',fitzpatrick_scale:!1,category:"symbols"},star_of_david:{keywords:["judaism"],"char":'\u2721',fitzpatrick_scale:!1,category:"symbols"},six_pointed_star:{keywords:["purple-square","religion","jewish","hexagram"],"char":'\ud83d\udd2f',fitzpatrick_scale:!1,category:"symbols"},menorah:{keywords:["hanukkah","candles","jewish"],"char":'\ud83d\udd4e',fitzpatrick_scale:!1,category:"symbols"},yin_yang:{keywords:["balance"],"char":'\u262f',fitzpatrick_scale:!1,category:"symbols"},orthodox_cross:{keywords:["suppedaneum","religion"],"char":'\u2626',fitzpatrick_scale:!1,category:"symbols"},place_of_worship:{keywords:["religion","church","temple","prayer"],"char":'\ud83d\uded0',fitzpatrick_scale:!1,category:"symbols"},ophiuchus:{keywords:["sign","purple-square","constellation","astrology"],"char":'\u26ce',fitzpatrick_scale:!1,category:"symbols"},aries:{keywords:["sign","purple-square","zodiac","astrology"],"char":'\u2648',fitzpatrick_scale:!1,category:"symbols"},taurus:{keywords:["purple-square","sign","zodiac","astrology"],"char":'\u2649',fitzpatrick_scale:!1,category:"symbols"},gemini:{keywords:["sign","zodiac","purple-square","astrology"],"char":'\u264a',fitzpatrick_scale:!1,category:"symbols"},cancer:{keywords:["sign","zodiac","purple-square","astrology"],"char":'\u264b',fitzpatrick_scale:!1,category:"symbols"},leo:{keywords:["sign","purple-square","zodiac","astrology"],"char":'\u264c',fitzpatrick_scale:!1,category:"symbols"},virgo:{keywords:["sign","zodiac","purple-square","astrology"],"char":'\u264d',fitzpatrick_scale:!1,category:"symbols"},libra:{keywords:["sign","purple-square","zodiac","astrology"],"char":'\u264e',fitzpatrick_scale:!1,category:"symbols"},scorpius:{keywords:["sign","zodiac","purple-square","astrology","scorpio"],"char":'\u264f',fitzpatrick_scale:!1,category:"symbols"},sagittarius:{keywords:["sign","zodiac","purple-square","astrology"],"char":'\u2650',fitzpatrick_scale:!1,category:"symbols"},capricorn:{keywords:["sign","zodiac","purple-square","astrology"],"char":'\u2651',fitzpatrick_scale:!1,category:"symbols"},aquarius:{keywords:["sign","purple-square","zodiac","astrology"],"char":'\u2652',fitzpatrick_scale:!1,category:"symbols"},pisces:{keywords:["purple-square","sign","zodiac","astrology"],"char":'\u2653',fitzpatrick_scale:!1,category:"symbols"},id:{keywords:["purple-square","words"],"char":'\ud83c\udd94',fitzpatrick_scale:!1,category:"symbols"},atom_symbol:{keywords:["science","physics","chemistry"],"char":'\u269b',fitzpatrick_scale:!1,category:"symbols"},u7a7a:{keywords:["kanji","japanese","chinese","empty","sky","blue-square"],"char":'\ud83c\ude33',fitzpatrick_scale:!1,category:"symbols"},u5272:{keywords:["cut","divide","chinese","kanji","pink-square"],"char":'\ud83c\ude39',fitzpatrick_scale:!1,category:"symbols"},radioactive:{keywords:["nuclear","danger"],"char":'\u2622',fitzpatrick_scale:!1,category:"symbols"},biohazard:{keywords:["danger"],"char":'\u2623',fitzpatrick_scale:!1,category:"symbols"},mobile_phone_off:{keywords:["mute","orange-square","silence","quiet"],"char":'\ud83d\udcf4',fitzpatrick_scale:!1,category:"symbols"},vibration_mode:{keywords:["orange-square","phone"],"char":'\ud83d\udcf3',fitzpatrick_scale:!1,category:"symbols"},u6709:{keywords:["orange-square","chinese","have","kanji"],"char":'\ud83c\ude36',fitzpatrick_scale:!1,category:"symbols"},u7121:{keywords:["nothing","chinese","kanji","japanese","orange-square"],"char":'\ud83c\ude1a',fitzpatrick_scale:!1,category:"symbols"},u7533:{keywords:["chinese","japanese","kanji","orange-square"],"char":'\ud83c\ude38',fitzpatrick_scale:!1,category:"symbols"},u55b6:{keywords:["japanese","opening hours","orange-square"],"char":'\ud83c\ude3a',fitzpatrick_scale:!1,category:"symbols"},u6708:{keywords:["chinese","month","moon","japanese","orange-square","kanji"],"char":'\ud83c\ude37\ufe0f',fitzpatrick_scale:!1,category:"symbols"},eight_pointed_black_star:{keywords:["orange-square","shape","polygon"],"char":'\u2734\ufe0f',fitzpatrick_scale:!1,category:"symbols"},vs:{keywords:["words","orange-square"],"char":'\ud83c\udd9a',fitzpatrick_scale:!1,category:"symbols"},accept:{keywords:["ok","good","chinese","kanji","agree","yes","orange-circle"],"char":'\ud83c\ude51',fitzpatrick_scale:!1,category:"symbols"},white_flower:{keywords:["japanese","spring"],"char":'\ud83d\udcae',fitzpatrick_scale:!1,category:"symbols"},ideograph_advantage:{keywords:["chinese","kanji","obtain","get","circle"],"char":'\ud83c\ude50',fitzpatrick_scale:!1,category:"symbols"},secret:{keywords:["privacy","chinese","sshh","kanji","red-circle"],"char":'\u3299\ufe0f',fitzpatrick_scale:!1,category:"symbols"},congratulations:{keywords:["chinese","kanji","japanese","red-circle"],"char":'\u3297\ufe0f',fitzpatrick_scale:!1,category:"symbols"},u5408:{keywords:["japanese","chinese","join","kanji","red-square"],"char":'\ud83c\ude34',fitzpatrick_scale:!1,category:"symbols"},u6e80:{keywords:["full","chinese","japanese","red-square","kanji"],"char":'\ud83c\ude35',fitzpatrick_scale:!1,category:"symbols"},u7981:{keywords:["kanji","japanese","chinese","forbidden","limit","restricted","red-square"],"char":'\ud83c\ude32',fitzpatrick_scale:!1,category:"symbols"},a:{keywords:["red-square","alphabet","letter"],"char":'\ud83c\udd70\ufe0f',fitzpatrick_scale:!1,category:"symbols"},b:{keywords:["red-square","alphabet","letter"],"char":'\ud83c\udd71\ufe0f',fitzpatrick_scale:!1,category:"symbols"},ab:{keywords:["red-square","alphabet"],"char":'\ud83c\udd8e',fitzpatrick_scale:!1,category:"symbols"},cl:{keywords:["alphabet","words","red-square"],"char":'\ud83c\udd91',fitzpatrick_scale:!1,category:"symbols"},o2:{keywords:["alphabet","red-square","letter"],"char":'\ud83c\udd7e\ufe0f',fitzpatrick_scale:!1,category:"symbols"},sos:{keywords:["help","red-square","words","emergency","911"],"char":'\ud83c\udd98',fitzpatrick_scale:!1,category:"symbols"},no_entry:{keywords:["limit","security","privacy","bad","denied","stop","circle"],"char":'\u26d4',fitzpatrick_scale:!1,category:"symbols"},name_badge:{keywords:["fire","forbid"],"char":'\ud83d\udcdb',fitzpatrick_scale:!1,category:"symbols"},no_entry_sign:{keywords:["forbid","stop","limit","denied","disallow","circle"],"char":'\ud83d\udeab',fitzpatrick_scale:!1,category:"symbols"},x:{keywords:["no","delete","remove","cancel","red"],"char":'\u274c',fitzpatrick_scale:!1,category:"symbols"},o:{keywords:["circle","round"],"char":'\u2b55',fitzpatrick_scale:!1,category:"symbols"},stop_sign:{keywords:["stop"],"char":'\ud83d\uded1',fitzpatrick_scale:!1,category:"symbols"},anger:{keywords:["angry","mad"],"char":'\ud83d\udca2',fitzpatrick_scale:!1,category:"symbols"},hotsprings:{keywords:["bath","warm","relax"],"char":'\u2668\ufe0f',fitzpatrick_scale:!1,category:"symbols"},no_pedestrians:{keywords:["rules","crossing","walking","circle"],"char":'\ud83d\udeb7',fitzpatrick_scale:!1,category:"symbols"},do_not_litter:{keywords:["trash","bin","garbage","circle"],"char":'\ud83d\udeaf',fitzpatrick_scale:!1,category:"symbols"},no_bicycles:{keywords:["cyclist","prohibited","circle"],"char":'\ud83d\udeb3',fitzpatrick_scale:!1,category:"symbols"},"non-potable_water":{keywords:["drink","faucet","tap","circle"],"char":'\ud83d\udeb1',fitzpatrick_scale:!1,category:"symbols"},underage:{keywords:["18","drink","pub","night","minor","circle"],"char":'\ud83d\udd1e',fitzpatrick_scale:!1,category:"symbols"},no_mobile_phones:{keywords:["iphone","mute","circle"],"char":'\ud83d\udcf5',fitzpatrick_scale:!1,category:"symbols"},exclamation:{keywords:["heavy_exclamation_mark","danger","surprise","punctuation","wow","warning"],"char":'\u2757',fitzpatrick_scale:!1,category:"symbols"},grey_exclamation:{keywords:["surprise","punctuation","gray","wow","warning"],"char":'\u2755',fitzpatrick_scale:!1,category:"symbols"},question:{keywords:["doubt","confused"],"char":'\u2753',fitzpatrick_scale:!1,category:"symbols"},grey_question:{keywords:["doubts","gray","huh","confused"],"char":'\u2754',fitzpatrick_scale:!1,category:"symbols"},bangbang:{keywords:["exclamation","surprise"],"char":'\u203c\ufe0f',fitzpatrick_scale:!1,category:"symbols"},interrobang:{keywords:["wat","punctuation","surprise"],"char":'\u2049\ufe0f',fitzpatrick_scale:!1,category:"symbols"},low_brightness:{keywords:["sun","afternoon","warm","summer"],"char":'\ud83d\udd05',fitzpatrick_scale:!1,category:"symbols"},high_brightness:{keywords:["sun","light"],"char":'\ud83d\udd06',fitzpatrick_scale:!1,category:"symbols"},trident:{keywords:["weapon","spear"],"char":'\ud83d\udd31',fitzpatrick_scale:!1,category:"symbols"},fleur_de_lis:{keywords:["decorative","scout"],"char":'\u269c',fitzpatrick_scale:!1,category:"symbols"},part_alternation_mark:{keywords:["graph","presentation","stats","business","economics","bad"],"char":'\u303d\ufe0f',fitzpatrick_scale:!1,category:"symbols"},warning:{keywords:["exclamation","wip","alert","error","problem","issue"],"char":'\u26a0\ufe0f',fitzpatrick_scale:!1,category:"symbols"},children_crossing:{keywords:["school","warning","danger","sign","driving","yellow-diamond"],"char":'\ud83d\udeb8',fitzpatrick_scale:!1,category:"symbols"},beginner:{keywords:["badge","shield"],"char":'\ud83d\udd30',fitzpatrick_scale:!1,category:"symbols"},recycle:{keywords:["arrow","environment","garbage","trash"],"char":'\u267b\ufe0f',fitzpatrick_scale:!1,category:"symbols"},u6307:{keywords:["chinese","point","green-square","kanji"],"char":'\ud83c\ude2f',fitzpatrick_scale:!1,category:"symbols"},chart:{keywords:["green-square","graph","presentation","stats"],"char":'\ud83d\udcb9',fitzpatrick_scale:!1,category:"symbols"},sparkle:{keywords:["stars","green-square","awesome","good","fireworks"],"char":'\u2747\ufe0f',fitzpatrick_scale:!1,category:"symbols"},eight_spoked_asterisk:{keywords:["star","sparkle","green-square"],"char":'\u2733\ufe0f',fitzpatrick_scale:!1,category:"symbols"},negative_squared_cross_mark:{keywords:["x","green-square","no","deny"],"char":'\u274e',fitzpatrick_scale:!1,category:"symbols"},white_check_mark:{keywords:["green-square","ok","agree","vote","election","answer","tick"],"char":'\u2705',fitzpatrick_scale:!1,category:"symbols"},diamond_shape_with_a_dot_inside:{keywords:["jewel","blue","gem","crystal","fancy"],"char":'\ud83d\udca0',fitzpatrick_scale:!1,category:"symbols"},cyclone:{keywords:["weather","swirl","blue","cloud","vortex","spiral","whirlpool","spin","tornado","hurricane","typhoon"],"char":'\ud83c\udf00',fitzpatrick_scale:!1,category:"symbols"},loop:{keywords:["tape","cassette"],"char":'\u27bf',fitzpatrick_scale:!1,category:"symbols"},globe_with_meridians:{keywords:["earth","international","world","internet","interweb","i18n"],"char":'\ud83c\udf10',fitzpatrick_scale:!1,category:"symbols"},m:{keywords:["alphabet","blue-circle","letter"],"char":'\u24c2\ufe0f',fitzpatrick_scale:!1,category:"symbols"},atm:{keywords:["money","sales","cash","blue-square","payment","bank"],"char":'\ud83c\udfe7',fitzpatrick_scale:!1,category:"symbols"},sa:{keywords:["japanese","blue-square","katakana"],"char":'\ud83c\ude02\ufe0f',fitzpatrick_scale:!1,category:"symbols"},passport_control:{keywords:["custom","blue-square"],"char":'\ud83d\udec2',fitzpatrick_scale:!1,category:"symbols"},customs:{keywords:["passport","border","blue-square"],"char":'\ud83d\udec3',fitzpatrick_scale:!1,category:"symbols"},baggage_claim:{keywords:["blue-square","airport","transport"],"char":'\ud83d\udec4',fitzpatrick_scale:!1,category:"symbols"},left_luggage:{keywords:["blue-square","travel"],"char":'\ud83d\udec5',fitzpatrick_scale:!1,category:"symbols"},wheelchair:{keywords:["blue-square","disabled","a11y","accessibility"],"char":'\u267f',fitzpatrick_scale:!1,category:"symbols"},no_smoking:{keywords:["cigarette","blue-square","smell","smoke"],"char":'\ud83d\udead',fitzpatrick_scale:!1,category:"symbols"},wc:{keywords:["toilet","restroom","blue-square"],"char":'\ud83d\udebe',fitzpatrick_scale:!1,category:"symbols"},parking:{keywords:["cars","blue-square","alphabet","letter"],"char":'\ud83c\udd7f\ufe0f',fitzpatrick_scale:!1,category:"symbols"},potable_water:{keywords:["blue-square","liquid","restroom","cleaning","faucet"],"char":'\ud83d\udeb0',fitzpatrick_scale:!1,category:"symbols"},mens:{keywords:["toilet","restroom","wc","blue-square","gender","male"],"char":'\ud83d\udeb9',fitzpatrick_scale:!1,category:"symbols"},womens:{keywords:["purple-square","woman","female","toilet","loo","restroom","gender"],"char":'\ud83d\udeba',fitzpatrick_scale:!1,category:"symbols"},baby_symbol:{keywords:["orange-square","child"],"char":'\ud83d\udebc',fitzpatrick_scale:!1,category:"symbols"},restroom:{keywords:["blue-square","toilet","refresh","wc","gender"],"char":'\ud83d\udebb',fitzpatrick_scale:!1,category:"symbols"},put_litter_in_its_place:{keywords:["blue-square","sign","human","info"],"char":'\ud83d\udeae',fitzpatrick_scale:!1,category:"symbols"},cinema:{keywords:["blue-square","record","film","movie","curtain","stage","theater"],"char":'\ud83c\udfa6',fitzpatrick_scale:!1,category:"symbols"},signal_strength:{keywords:["blue-square","reception","phone","internet","connection","wifi","bluetooth","bars"],"char":'\ud83d\udcf6',fitzpatrick_scale:!1,category:"symbols"},koko:{keywords:["blue-square","here","katakana","japanese","destination"],"char":'\ud83c\ude01',fitzpatrick_scale:!1,category:"symbols"},ng:{keywords:["blue-square","words","shape","icon"],"char":'\ud83c\udd96',fitzpatrick_scale:!1,category:"symbols"},ok:{keywords:["good","agree","yes","blue-square"],"char":'\ud83c\udd97',fitzpatrick_scale:!1,category:"symbols"},up:{keywords:["blue-square","above","high"],"char":'\ud83c\udd99',fitzpatrick_scale:!1,category:"symbols"},cool:{keywords:["words","blue-square"],"char":'\ud83c\udd92',fitzpatrick_scale:!1,category:"symbols"},"new":{keywords:["blue-square","words","start"],"char":'\ud83c\udd95',fitzpatrick_scale:!1,category:"symbols"},free:{keywords:["blue-square","words"],"char":'\ud83c\udd93',fitzpatrick_scale:!1,category:"symbols"},zero:{keywords:["0","numbers","blue-square","null"],"char":'0\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},one:{keywords:["blue-square","numbers","1"],"char":'1\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},two:{keywords:["numbers","2","prime","blue-square"],"char":'2\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},three:{keywords:["3","numbers","prime","blue-square"],"char":'3\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},four:{keywords:["4","numbers","blue-square"],"char":'4\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},five:{keywords:["5","numbers","blue-square","prime"],"char":'5\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},six:{keywords:["6","numbers","blue-square"],"char":'6\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},seven:{keywords:["7","numbers","blue-square","prime"],"char":'7\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},eight:{keywords:["8","blue-square","numbers"],"char":'8\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},nine:{keywords:["blue-square","numbers","9"],"char":'9\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},keycap_ten:{keywords:["numbers","10","blue-square"],"char":'\ud83d\udd1f',fitzpatrick_scale:!1,category:"symbols"},asterisk:{keywords:["star","keycap"],"char":'*\u20e3',fitzpatrick_scale:!1,category:"symbols"},eject_button:{keywords:["blue-square"],"char":'\u23cf\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_forward:{keywords:["blue-square","right","direction","play"],"char":'\u25b6\ufe0f',fitzpatrick_scale:!1,category:"symbols"},pause_button:{keywords:["pause","blue-square"],"char":'\u23f8',fitzpatrick_scale:!1,category:"symbols"},next_track_button:{keywords:["forward","next","blue-square"],"char":'\u23ed',fitzpatrick_scale:!1,category:"symbols"},stop_button:{keywords:["blue-square"],"char":'\u23f9',fitzpatrick_scale:!1,category:"symbols"},record_button:{keywords:["blue-square"],"char":'\u23fa',fitzpatrick_scale:!1,category:"symbols"},play_or_pause_button:{keywords:["blue-square","play","pause"],"char":'\u23ef',fitzpatrick_scale:!1,category:"symbols"},previous_track_button:{keywords:["backward"],"char":'\u23ee',fitzpatrick_scale:!1,category:"symbols"},fast_forward:{keywords:["blue-square","play","speed","continue"],"char":'\u23e9',fitzpatrick_scale:!1,category:"symbols"},rewind:{keywords:["play","blue-square"],"char":'\u23ea',fitzpatrick_scale:!1,category:"symbols"},twisted_rightwards_arrows:{keywords:["blue-square","shuffle","music","random"],"char":'\ud83d\udd00',fitzpatrick_scale:!1,category:"symbols"},repeat:{keywords:["loop","record"],"char":'\ud83d\udd01',fitzpatrick_scale:!1,category:"symbols"},repeat_one:{keywords:["blue-square","loop"],"char":'\ud83d\udd02',fitzpatrick_scale:!1,category:"symbols"},arrow_backward:{keywords:["blue-square","left","direction"],"char":'\u25c0\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_up_small:{keywords:["blue-square","triangle","direction","point","forward","top"],"char":'\ud83d\udd3c',fitzpatrick_scale:!1,category:"symbols"},arrow_down_small:{keywords:["blue-square","direction","bottom"],"char":'\ud83d\udd3d',fitzpatrick_scale:!1,category:"symbols"},arrow_double_up:{keywords:["blue-square","direction","top"],"char":'\u23eb',fitzpatrick_scale:!1,category:"symbols"},arrow_double_down:{keywords:["blue-square","direction","bottom"],"char":'\u23ec',fitzpatrick_scale:!1,category:"symbols"},arrow_right:{keywords:["blue-square","next"],"char":'\u27a1\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_left:{keywords:["blue-square","previous","back"],"char":'\u2b05\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_up:{keywords:["blue-square","continue","top","direction"],"char":'\u2b06\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_down:{keywords:["blue-square","direction","bottom"],"char":'\u2b07\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_upper_right:{keywords:["blue-square","point","direction","diagonal","northeast"],"char":'\u2197\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_lower_right:{keywords:["blue-square","direction","diagonal","southeast"],"char":'\u2198\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_lower_left:{keywords:["blue-square","direction","diagonal","southwest"],"char":'\u2199\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_upper_left:{keywords:["blue-square","point","direction","diagonal","northwest"],"char":'\u2196\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_up_down:{keywords:["blue-square","direction","way","vertical"],"char":'\u2195\ufe0f',fitzpatrick_scale:!1,category:"symbols"},left_right_arrow:{keywords:["shape","direction","horizontal","sideways"],"char":'\u2194\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrows_counterclockwise:{keywords:["blue-square","sync","cycle"],"char":'\ud83d\udd04',fitzpatrick_scale:!1,category:"symbols"},arrow_right_hook:{keywords:["blue-square","return","rotate","direction"],"char":'\u21aa\ufe0f',fitzpatrick_scale:!1,category:"symbols"},leftwards_arrow_with_hook:{keywords:["back","return","blue-square","undo","enter"],"char":'\u21a9\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_heading_up:{keywords:["blue-square","direction","top"],"char":'\u2934\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_heading_down:{keywords:["blue-square","direction","bottom"],"char":'\u2935\ufe0f',fitzpatrick_scale:!1,category:"symbols"},hash:{keywords:["symbol","blue-square","twitter"],"char":'#\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},information_source:{keywords:["blue-square","alphabet","letter"],"char":'\u2139\ufe0f',fitzpatrick_scale:!1,category:"symbols"},abc:{keywords:["blue-square","alphabet"],"char":'\ud83d\udd24',fitzpatrick_scale:!1,category:"symbols"},abcd:{keywords:["blue-square","alphabet"],"char":'\ud83d\udd21',fitzpatrick_scale:!1,category:"symbols"},capital_abcd:{keywords:["alphabet","words","blue-square"],"char":'\ud83d\udd20',fitzpatrick_scale:!1,category:"symbols"},symbols:{keywords:["blue-square","music","note","ampersand","percent","glyphs","characters"],"char":'\ud83d\udd23',fitzpatrick_scale:!1,category:"symbols"},musical_note:{keywords:["score","tone","sound"],"char":'\ud83c\udfb5',fitzpatrick_scale:!1,category:"symbols"},notes:{keywords:["music","score"],"char":'\ud83c\udfb6',fitzpatrick_scale:!1,category:"symbols"},wavy_dash:{keywords:["draw","line","moustache","mustache","squiggle","scribble"],"char":'\u3030\ufe0f',fitzpatrick_scale:!1,category:"symbols"},curly_loop:{keywords:["scribble","draw","shape","squiggle"],"char":'\u27b0',fitzpatrick_scale:!1,category:"symbols"},heavy_check_mark:{keywords:["ok","nike","answer","yes","tick"],"char":'\u2714\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrows_clockwise:{keywords:["sync","cycle","round","repeat"],"char":'\ud83d\udd03',fitzpatrick_scale:!1,category:"symbols"},heavy_plus_sign:{keywords:["math","calculation","addition","more","increase"],"char":'\u2795',fitzpatrick_scale:!1,category:"symbols"},heavy_minus_sign:{keywords:["math","calculation","subtract","less"],"char":'\u2796',fitzpatrick_scale:!1,category:"symbols"},heavy_division_sign:{keywords:["divide","math","calculation"],"char":'\u2797',fitzpatrick_scale:!1,category:"symbols"},heavy_multiplication_x:{keywords:["math","calculation"],"char":'\u2716\ufe0f',fitzpatrick_scale:!1,category:"symbols"},infinity:{keywords:["forever"],"char":'\u267e',fitzpatrick_scale:!1,category:"symbols"},heavy_dollar_sign:{keywords:["money","sales","payment","currency","buck"],"char":'\ud83d\udcb2',fitzpatrick_scale:!1,category:"symbols"},currency_exchange:{keywords:["money","sales","dollar","travel"],"char":'\ud83d\udcb1',fitzpatrick_scale:!1,category:"symbols"},copyright:{keywords:["ip","license","circle","law","legal"],"char":'\xa9\ufe0f',fitzpatrick_scale:!1,category:"symbols"},registered:{keywords:["alphabet","circle"],"char":'\xae\ufe0f',fitzpatrick_scale:!1,category:"symbols"},tm:{keywords:["trademark","brand","law","legal"],"char":'\u2122\ufe0f',fitzpatrick_scale:!1,category:"symbols"},end:{keywords:["words","arrow"],"char":'\ud83d\udd1a',fitzpatrick_scale:!1,category:"symbols"},back:{keywords:["arrow","words","return"],"char":'\ud83d\udd19',fitzpatrick_scale:!1,category:"symbols"},on:{keywords:["arrow","words"],"char":'\ud83d\udd1b',fitzpatrick_scale:!1,category:"symbols"},top:{keywords:["words","blue-square"],"char":'\ud83d\udd1d',fitzpatrick_scale:!1,category:"symbols"},soon:{keywords:["arrow","words"],"char":'\ud83d\udd1c',fitzpatrick_scale:!1,category:"symbols"},ballot_box_with_check:{keywords:["ok","agree","confirm","black-square","vote","election","yes","tick"],"char":'\u2611\ufe0f',fitzpatrick_scale:!1,category:"symbols"},radio_button:{keywords:["input","old","music","circle"],"char":'\ud83d\udd18',fitzpatrick_scale:!1,category:"symbols"},white_circle:{keywords:["shape","round"],"char":'\u26aa',fitzpatrick_scale:!1,category:"symbols"},black_circle:{keywords:["shape","button","round"],"char":'\u26ab',fitzpatrick_scale:!1,category:"symbols"},red_circle:{keywords:["shape","error","danger"],"char":'\ud83d\udd34',fitzpatrick_scale:!1,category:"symbols"},large_blue_circle:{keywords:["shape","icon","button"],"char":'\ud83d\udd35',fitzpatrick_scale:!1,category:"symbols"},small_orange_diamond:{keywords:["shape","jewel","gem"],"char":'\ud83d\udd38',fitzpatrick_scale:!1,category:"symbols"},small_blue_diamond:{keywords:["shape","jewel","gem"],"char":'\ud83d\udd39',fitzpatrick_scale:!1,category:"symbols"},large_orange_diamond:{keywords:["shape","jewel","gem"],"char":'\ud83d\udd36',fitzpatrick_scale:!1,category:"symbols"},large_blue_diamond:{keywords:["shape","jewel","gem"],"char":'\ud83d\udd37',fitzpatrick_scale:!1,category:"symbols"},small_red_triangle:{keywords:["shape","direction","up","top"],"char":'\ud83d\udd3a',fitzpatrick_scale:!1,category:"symbols"},black_small_square:{keywords:["shape","icon"],"char":'\u25aa\ufe0f',fitzpatrick_scale:!1,category:"symbols"},white_small_square:{keywords:["shape","icon"],"char":'\u25ab\ufe0f',fitzpatrick_scale:!1,category:"symbols"},black_large_square:{keywords:["shape","icon","button"],"char":'\u2b1b',fitzpatrick_scale:!1,category:"symbols"},white_large_square:{keywords:["shape","icon","stone","button"],"char":'\u2b1c',fitzpatrick_scale:!1,category:"symbols"},small_red_triangle_down:{keywords:["shape","direction","bottom"],"char":'\ud83d\udd3b',fitzpatrick_scale:!1,category:"symbols"},black_medium_square:{keywords:["shape","button","icon"],"char":'\u25fc\ufe0f',fitzpatrick_scale:!1,category:"symbols"},white_medium_square:{keywords:["shape","stone","icon"],"char":'\u25fb\ufe0f',fitzpatrick_scale:!1,category:"symbols"},black_medium_small_square:{keywords:["icon","shape","button"],"char":'\u25fe',fitzpatrick_scale:!1,category:"symbols"},white_medium_small_square:{keywords:["shape","stone","icon","button"],"char":'\u25fd',fitzpatrick_scale:!1,category:"symbols"},black_square_button:{keywords:["shape","input","frame"],"char":'\ud83d\udd32',fitzpatrick_scale:!1,category:"symbols"},white_square_button:{keywords:["shape","input"],"char":'\ud83d\udd33',fitzpatrick_scale:!1,category:"symbols"},speaker:{keywords:["sound","volume","silence","broadcast"],"char":'\ud83d\udd08',fitzpatrick_scale:!1,category:"symbols"},sound:{keywords:["volume","speaker","broadcast"],"char":'\ud83d\udd09',fitzpatrick_scale:!1,category:"symbols"},loud_sound:{keywords:["volume","noise","noisy","speaker","broadcast"],"char":'\ud83d\udd0a',fitzpatrick_scale:!1,category:"symbols"},mute:{keywords:["sound","volume","silence","quiet"],"char":'\ud83d\udd07',fitzpatrick_scale:!1,category:"symbols"},mega:{keywords:["sound","speaker","volume"],"char":'\ud83d\udce3',fitzpatrick_scale:!1,category:"symbols"},loudspeaker:{keywords:["volume","sound"],"char":'\ud83d\udce2',fitzpatrick_scale:!1,category:"symbols"},bell:{keywords:["sound","notification","christmas","xmas","chime"],"char":'\ud83d\udd14',fitzpatrick_scale:!1,category:"symbols"},no_bell:{keywords:["sound","volume","mute","quiet","silent"],"char":'\ud83d\udd15',fitzpatrick_scale:!1,category:"symbols"},black_joker:{keywords:["poker","cards","game","play","magic"],"char":'\ud83c\udccf',fitzpatrick_scale:!1,category:"symbols"},mahjong:{keywords:["game","play","chinese","kanji"],"char":'\ud83c\udc04',fitzpatrick_scale:!1,category:"symbols"},spades:{keywords:["poker","cards","suits","magic"],"char":'\u2660\ufe0f',fitzpatrick_scale:!1,category:"symbols"},clubs:{keywords:["poker","cards","magic","suits"],"char":'\u2663\ufe0f',fitzpatrick_scale:!1,category:"symbols"},hearts:{keywords:["poker","cards","magic","suits"],"char":'\u2665\ufe0f',fitzpatrick_scale:!1,category:"symbols"},diamonds:{keywords:["poker","cards","magic","suits"],"char":'\u2666\ufe0f',fitzpatrick_scale:!1,category:"symbols"},flower_playing_cards:{keywords:["game","sunset","red"],"char":'\ud83c\udfb4',fitzpatrick_scale:!1,category:"symbols"},thought_balloon:{keywords:["bubble","cloud","speech","thinking","dream"],"char":'\ud83d\udcad',fitzpatrick_scale:!1,category:"symbols"},right_anger_bubble:{keywords:["caption","speech","thinking","mad"],"char":'\ud83d\uddef',fitzpatrick_scale:!1,category:"symbols"},speech_balloon:{keywords:["bubble","words","message","talk","chatting"],"char":'\ud83d\udcac',fitzpatrick_scale:!1,category:"symbols"},left_speech_bubble:{keywords:["words","message","talk","chatting"],"char":'\ud83d\udde8',fitzpatrick_scale:!1,category:"symbols"},clock1:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd50',fitzpatrick_scale:!1,category:"symbols"},clock2:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd51',fitzpatrick_scale:!1,category:"symbols"},clock3:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd52',fitzpatrick_scale:!1,category:"symbols"},clock4:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd53',fitzpatrick_scale:!1,category:"symbols"},clock5:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd54',fitzpatrick_scale:!1,category:"symbols"},clock6:{keywords:["time","late","early","schedule","dawn","dusk"],"char":'\ud83d\udd55',fitzpatrick_scale:!1,category:"symbols"},clock7:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd56',fitzpatrick_scale:!1,category:"symbols"},clock8:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd57',fitzpatrick_scale:!1,category:"symbols"},clock9:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd58',fitzpatrick_scale:!1,category:"symbols"},clock10:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd59',fitzpatrick_scale:!1,category:"symbols"},clock11:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd5a',fitzpatrick_scale:!1,category:"symbols"},clock12:{keywords:["time","noon","midnight","midday","late","early","schedule"],"char":'\ud83d\udd5b',fitzpatrick_scale:!1,category:"symbols"},clock130:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd5c',fitzpatrick_scale:!1,category:"symbols"},clock230:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd5d',fitzpatrick_scale:!1,category:"symbols"},clock330:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd5e',fitzpatrick_scale:!1,category:"symbols"},clock430:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd5f',fitzpatrick_scale:!1,category:"symbols"},clock530:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd60',fitzpatrick_scale:!1,category:"symbols"},clock630:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd61',fitzpatrick_scale:!1,category:"symbols"},clock730:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd62',fitzpatrick_scale:!1,category:"symbols"},clock830:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd63',fitzpatrick_scale:!1,category:"symbols"},clock930:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd64',fitzpatrick_scale:!1,category:"symbols"},clock1030:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd65',fitzpatrick_scale:!1,category:"symbols"},clock1130:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd66',fitzpatrick_scale:!1,category:"symbols"},clock1230:{keywords:["time","late","early","schedule"],"char":'\ud83d\udd67',fitzpatrick_scale:!1,category:"symbols"},afghanistan:{keywords:["af","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddeb',fitzpatrick_scale:!1,category:"flags"},aland_islands:{keywords:["\xc5land","islands","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddfd',fitzpatrick_scale:!1,category:"flags"},albania:{keywords:["al","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddf1',fitzpatrick_scale:!1,category:"flags"},algeria:{keywords:["dz","flag","nation","country","banner"],"char":'\ud83c\udde9\ud83c\uddff',fitzpatrick_scale:!1,category:"flags"},american_samoa:{keywords:["american","ws","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddf8',fitzpatrick_scale:!1,category:"flags"},andorra:{keywords:["ad","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\udde9',fitzpatrick_scale:!1,category:"flags"},angola:{keywords:["ao","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddf4',fitzpatrick_scale:!1,category:"flags"},anguilla:{keywords:["ai","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddee',fitzpatrick_scale:!1,category:"flags"},antarctica:{keywords:["aq","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddf6',fitzpatrick_scale:!1,category:"flags"},antigua_barbuda:{keywords:["antigua","barbuda","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},argentina:{keywords:["ar","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},armenia:{keywords:["am","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},aruba:{keywords:["aw","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddfc',fitzpatrick_scale:!1,category:"flags"},australia:{keywords:["au","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddfa',fitzpatrick_scale:!1,category:"flags"},austria:{keywords:["at","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddf9',fitzpatrick_scale:!1,category:"flags"},azerbaijan:{keywords:["az","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddff',fitzpatrick_scale:!1,category:"flags"},bahamas:{keywords:["bs","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddf8',fitzpatrick_scale:!1,category:"flags"},bahrain:{keywords:["bh","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\udded',fitzpatrick_scale:!1,category:"flags"},bangladesh:{keywords:["bd","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\udde9',fitzpatrick_scale:!1,category:"flags"},barbados:{keywords:["bb","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\udde7',fitzpatrick_scale:!1,category:"flags"},belarus:{keywords:["by","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddfe',fitzpatrick_scale:!1,category:"flags"},belgium:{keywords:["be","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},belize:{keywords:["bz","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddff',fitzpatrick_scale:!1,category:"flags"},benin:{keywords:["bj","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddef',fitzpatrick_scale:!1,category:"flags"},bermuda:{keywords:["bm","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},bhutan:{keywords:["bt","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddf9',fitzpatrick_scale:!1,category:"flags"},bolivia:{keywords:["bo","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddf4',fitzpatrick_scale:!1,category:"flags"},caribbean_netherlands:{keywords:["bonaire","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddf6',fitzpatrick_scale:!1,category:"flags"},bosnia_herzegovina:{keywords:["bosnia","herzegovina","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\udde6',fitzpatrick_scale:!1,category:"flags"},botswana:{keywords:["bw","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddfc',fitzpatrick_scale:!1,category:"flags"},brazil:{keywords:["br","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},british_indian_ocean_territory:{keywords:["british","indian","ocean","territory","flag","nation","country","banner"],"char":'\ud83c\uddee\ud83c\uddf4',fitzpatrick_scale:!1,category:"flags"},british_virgin_islands:{keywords:["british","virgin","islands","bvi","flag","nation","country","banner"],"char":'\ud83c\uddfb\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},brunei:{keywords:["bn","darussalam","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddf3',fitzpatrick_scale:!1,category:"flags"},bulgaria:{keywords:["bg","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},burkina_faso:{keywords:["burkina","faso","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddeb',fitzpatrick_scale:!1,category:"flags"},burundi:{keywords:["bi","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddee',fitzpatrick_scale:!1,category:"flags"},cape_verde:{keywords:["cabo","verde","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddfb',fitzpatrick_scale:!1,category:"flags"},cambodia:{keywords:["kh","flag","nation","country","banner"],"char":'\ud83c\uddf0\ud83c\udded',fitzpatrick_scale:!1,category:"flags"},cameroon:{keywords:["cm","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},canada:{keywords:["ca","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\udde6',fitzpatrick_scale:!1,category:"flags"},canary_islands:{keywords:["canary","islands","flag","nation","country","banner"],"char":'\ud83c\uddee\ud83c\udde8',fitzpatrick_scale:!1,category:"flags"},cayman_islands:{keywords:["cayman","islands","flag","nation","country","banner"],"char":'\ud83c\uddf0\ud83c\uddfe',fitzpatrick_scale:!1,category:"flags"},central_african_republic:{keywords:["central","african","republic","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddeb',fitzpatrick_scale:!1,category:"flags"},chad:{keywords:["td","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\udde9',fitzpatrick_scale:!1,category:"flags"},chile:{keywords:["flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddf1',fitzpatrick_scale:!1,category:"flags"},cn:{keywords:["china","chinese","prc","flag","country","nation","banner"],"char":'\ud83c\udde8\ud83c\uddf3',fitzpatrick_scale:!1,category:"flags"},christmas_island:{keywords:["christmas","island","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddfd',fitzpatrick_scale:!1,category:"flags"},cocos_islands:{keywords:["cocos","keeling","islands","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\udde8',fitzpatrick_scale:!1,category:"flags"},colombia:{keywords:["co","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddf4',fitzpatrick_scale:!1,category:"flags"},comoros:{keywords:["km","flag","nation","country","banner"],"char":'\ud83c\uddf0\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},congo_brazzaville:{keywords:["congo","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},congo_kinshasa:{keywords:["congo","democratic","republic","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\udde9',fitzpatrick_scale:!1,category:"flags"},cook_islands:{keywords:["cook","islands","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddf0',fitzpatrick_scale:!1,category:"flags"},costa_rica:{keywords:["costa","rica","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},croatia:{keywords:["hr","flag","nation","country","banner"],"char":'\ud83c\udded\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},cuba:{keywords:["cu","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddfa',fitzpatrick_scale:!1,category:"flags"},curacao:{keywords:["cura\xe7ao","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddfc',fitzpatrick_scale:!1,category:"flags"},cyprus:{keywords:["cy","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddfe',fitzpatrick_scale:!1,category:"flags"},czech_republic:{keywords:["cz","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddff',fitzpatrick_scale:!1,category:"flags"},denmark:{keywords:["dk","flag","nation","country","banner"],"char":'\ud83c\udde9\ud83c\uddf0',fitzpatrick_scale:!1,category:"flags"},djibouti:{keywords:["dj","flag","nation","country","banner"],"char":'\ud83c\udde9\ud83c\uddef',fitzpatrick_scale:!1,category:"flags"},dominica:{keywords:["dm","flag","nation","country","banner"],"char":'\ud83c\udde9\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},dominican_republic:{keywords:["dominican","republic","flag","nation","country","banner"],"char":'\ud83c\udde9\ud83c\uddf4',fitzpatrick_scale:!1,category:"flags"},ecuador:{keywords:["ec","flag","nation","country","banner"],"char":'\ud83c\uddea\ud83c\udde8',fitzpatrick_scale:!1,category:"flags"},egypt:{keywords:["eg","flag","nation","country","banner"],"char":'\ud83c\uddea\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},el_salvador:{keywords:["el","salvador","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddfb',fitzpatrick_scale:!1,category:"flags"},equatorial_guinea:{keywords:["equatorial","gn","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddf6',fitzpatrick_scale:!1,category:"flags"},eritrea:{keywords:["er","flag","nation","country","banner"],"char":'\ud83c\uddea\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},estonia:{keywords:["ee","flag","nation","country","banner"],"char":'\ud83c\uddea\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},ethiopia:{keywords:["et","flag","nation","country","banner"],"char":'\ud83c\uddea\ud83c\uddf9',fitzpatrick_scale:!1,category:"flags"},eu:{keywords:["european","union","flag","banner"],"char":'\ud83c\uddea\ud83c\uddfa',fitzpatrick_scale:!1,category:"flags"},falkland_islands:{keywords:["falkland","islands","malvinas","flag","nation","country","banner"],"char":'\ud83c\uddeb\ud83c\uddf0',fitzpatrick_scale:!1,category:"flags"},faroe_islands:{keywords:["faroe","islands","flag","nation","country","banner"],"char":'\ud83c\uddeb\ud83c\uddf4',fitzpatrick_scale:!1,category:"flags"},fiji:{keywords:["fj","flag","nation","country","banner"],"char":'\ud83c\uddeb\ud83c\uddef',fitzpatrick_scale:!1,category:"flags"},finland:{keywords:["fi","flag","nation","country","banner"],"char":'\ud83c\uddeb\ud83c\uddee',fitzpatrick_scale:!1,category:"flags"},fr:{keywords:["banner","flag","nation","france","french","country"],"char":'\ud83c\uddeb\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},french_guiana:{keywords:["french","guiana","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddeb',fitzpatrick_scale:!1,category:"flags"},french_polynesia:{keywords:["french","polynesia","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\uddeb',fitzpatrick_scale:!1,category:"flags"},french_southern_territories:{keywords:["french","southern","territories","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddeb',fitzpatrick_scale:!1,category:"flags"},gabon:{keywords:["ga","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\udde6',fitzpatrick_scale:!1,category:"flags"},gambia:{keywords:["gm","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},georgia:{keywords:["ge","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},de:{keywords:["german","nation","flag","country","banner"],"char":'\ud83c\udde9\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},ghana:{keywords:["gh","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\udded',fitzpatrick_scale:!1,category:"flags"},gibraltar:{keywords:["gi","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddee',fitzpatrick_scale:!1,category:"flags"},greece:{keywords:["gr","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},greenland:{keywords:["gl","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddf1',fitzpatrick_scale:!1,category:"flags"},grenada:{keywords:["gd","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\udde9',fitzpatrick_scale:!1,category:"flags"},guadeloupe:{keywords:["gp","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddf5',fitzpatrick_scale:!1,category:"flags"},guam:{keywords:["gu","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddfa',fitzpatrick_scale:!1,category:"flags"},guatemala:{keywords:["gt","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddf9',fitzpatrick_scale:!1,category:"flags"},guernsey:{keywords:["gg","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},guinea:{keywords:["gn","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddf3',fitzpatrick_scale:!1,category:"flags"},guinea_bissau:{keywords:["gw","bissau","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddfc',fitzpatrick_scale:!1,category:"flags"},guyana:{keywords:["gy","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddfe',fitzpatrick_scale:!1,category:"flags"},haiti:{keywords:["ht","flag","nation","country","banner"],"char":'\ud83c\udded\ud83c\uddf9',fitzpatrick_scale:!1,category:"flags"},honduras:{keywords:["hn","flag","nation","country","banner"],"char":'\ud83c\udded\ud83c\uddf3',fitzpatrick_scale:!1,category:"flags"},hong_kong:{keywords:["hong","kong","flag","nation","country","banner"],"char":'\ud83c\udded\ud83c\uddf0',fitzpatrick_scale:!1,category:"flags"},hungary:{keywords:["hu","flag","nation","country","banner"],"char":'\ud83c\udded\ud83c\uddfa',fitzpatrick_scale:!1,category:"flags"},iceland:{keywords:["is","flag","nation","country","banner"],"char":'\ud83c\uddee\ud83c\uddf8',fitzpatrick_scale:!1,category:"flags"},india:{keywords:["in","flag","nation","country","banner"],"char":'\ud83c\uddee\ud83c\uddf3',fitzpatrick_scale:!1,category:"flags"},indonesia:{keywords:["flag","nation","country","banner"],"char":'\ud83c\uddee\ud83c\udde9',fitzpatrick_scale:!1,category:"flags"},iran:{keywords:["iran,","islamic","republic","flag","nation","country","banner"],"char":'\ud83c\uddee\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},iraq:{keywords:["iq","flag","nation","country","banner"],"char":'\ud83c\uddee\ud83c\uddf6',fitzpatrick_scale:!1,category:"flags"},ireland:{keywords:["ie","flag","nation","country","banner"],"char":'\ud83c\uddee\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},isle_of_man:{keywords:["isle","man","flag","nation","country","banner"],"char":'\ud83c\uddee\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},israel:{keywords:["il","flag","nation","country","banner"],"char":'\ud83c\uddee\ud83c\uddf1',fitzpatrick_scale:!1,category:"flags"},it:{keywords:["italy","flag","nation","country","banner"],"char":'\ud83c\uddee\ud83c\uddf9',fitzpatrick_scale:!1,category:"flags"},cote_divoire:{keywords:["ivory","coast","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\uddee',fitzpatrick_scale:!1,category:"flags"},jamaica:{keywords:["jm","flag","nation","country","banner"],"char":'\ud83c\uddef\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},jp:{keywords:["japanese","nation","flag","country","banner"],"char":'\ud83c\uddef\ud83c\uddf5',fitzpatrick_scale:!1,category:"flags"},jersey:{keywords:["je","flag","nation","country","banner"],"char":'\ud83c\uddef\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},jordan:{keywords:["jo","flag","nation","country","banner"],"char":'\ud83c\uddef\ud83c\uddf4',fitzpatrick_scale:!1,category:"flags"},kazakhstan:{keywords:["kz","flag","nation","country","banner"],"char":'\ud83c\uddf0\ud83c\uddff',fitzpatrick_scale:!1,category:"flags"},kenya:{keywords:["ke","flag","nation","country","banner"],"char":'\ud83c\uddf0\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},kiribati:{keywords:["ki","flag","nation","country","banner"],"char":'\ud83c\uddf0\ud83c\uddee',fitzpatrick_scale:!1,category:"flags"},kosovo:{keywords:["xk","flag","nation","country","banner"],"char":'\ud83c\uddfd\ud83c\uddf0',fitzpatrick_scale:!1,category:"flags"},kuwait:{keywords:["kw","flag","nation","country","banner"],"char":'\ud83c\uddf0\ud83c\uddfc',fitzpatrick_scale:!1,category:"flags"},kyrgyzstan:{keywords:["kg","flag","nation","country","banner"],"char":'\ud83c\uddf0\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},laos:{keywords:["lao","democratic","republic","flag","nation","country","banner"],"char":'\ud83c\uddf1\ud83c\udde6',fitzpatrick_scale:!1,category:"flags"},latvia:{keywords:["lv","flag","nation","country","banner"],"char":'\ud83c\uddf1\ud83c\uddfb',fitzpatrick_scale:!1,category:"flags"},lebanon:{keywords:["lb","flag","nation","country","banner"],"char":'\ud83c\uddf1\ud83c\udde7',fitzpatrick_scale:!1,category:"flags"},lesotho:{keywords:["ls","flag","nation","country","banner"],"char":'\ud83c\uddf1\ud83c\uddf8',fitzpatrick_scale:!1,category:"flags"},liberia:{keywords:["lr","flag","nation","country","banner"],"char":'\ud83c\uddf1\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},libya:{keywords:["ly","flag","nation","country","banner"],"char":'\ud83c\uddf1\ud83c\uddfe',fitzpatrick_scale:!1,category:"flags"},liechtenstein:{keywords:["li","flag","nation","country","banner"],"char":'\ud83c\uddf1\ud83c\uddee',fitzpatrick_scale:!1,category:"flags"},lithuania:{keywords:["lt","flag","nation","country","banner"],"char":'\ud83c\uddf1\ud83c\uddf9',fitzpatrick_scale:!1,category:"flags"},luxembourg:{keywords:["lu","flag","nation","country","banner"],"char":'\ud83c\uddf1\ud83c\uddfa',fitzpatrick_scale:!1,category:"flags"},macau:{keywords:["macao","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddf4',fitzpatrick_scale:!1,category:"flags"},macedonia:{keywords:["macedonia,","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddf0',fitzpatrick_scale:!1,category:"flags"},madagascar:{keywords:["mg","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},malawi:{keywords:["mw","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddfc',fitzpatrick_scale:!1,category:"flags"},malaysia:{keywords:["my","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddfe',fitzpatrick_scale:!1,category:"flags"},maldives:{keywords:["mv","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddfb',fitzpatrick_scale:!1,category:"flags"},mali:{keywords:["ml","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddf1',fitzpatrick_scale:!1,category:"flags"},malta:{keywords:["mt","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddf9',fitzpatrick_scale:!1,category:"flags"},marshall_islands:{keywords:["marshall","islands","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\udded',fitzpatrick_scale:!1,category:"flags"},martinique:{keywords:["mq","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddf6',fitzpatrick_scale:!1,category:"flags"},mauritania:{keywords:["mr","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},mauritius:{keywords:["mu","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddfa',fitzpatrick_scale:!1,category:"flags"},mayotte:{keywords:["yt","flag","nation","country","banner"],"char":'\ud83c\uddfe\ud83c\uddf9',fitzpatrick_scale:!1,category:"flags"},mexico:{keywords:["mx","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddfd',fitzpatrick_scale:!1,category:"flags"},micronesia:{keywords:["micronesia,","federated","states","flag","nation","country","banner"],"char":'\ud83c\uddeb\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},moldova:{keywords:["moldova,","republic","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\udde9',fitzpatrick_scale:!1,category:"flags"},monaco:{keywords:["mc","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\udde8',fitzpatrick_scale:!1,category:"flags"},mongolia:{keywords:["mn","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddf3',fitzpatrick_scale:!1,category:"flags"},montenegro:{keywords:["me","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},montserrat:{keywords:["ms","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddf8',fitzpatrick_scale:!1,category:"flags"},morocco:{keywords:["ma","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\udde6',fitzpatrick_scale:!1,category:"flags"},mozambique:{keywords:["mz","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddff',fitzpatrick_scale:!1,category:"flags"},myanmar:{keywords:["mm","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},namibia:{keywords:["na","flag","nation","country","banner"],"char":'\ud83c\uddf3\ud83c\udde6',fitzpatrick_scale:!1,category:"flags"},nauru:{keywords:["nr","flag","nation","country","banner"],"char":'\ud83c\uddf3\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},nepal:{keywords:["np","flag","nation","country","banner"],"char":'\ud83c\uddf3\ud83c\uddf5',fitzpatrick_scale:!1,category:"flags"},netherlands:{keywords:["nl","flag","nation","country","banner"],"char":'\ud83c\uddf3\ud83c\uddf1',fitzpatrick_scale:!1,category:"flags"},new_caledonia:{keywords:["new","caledonia","flag","nation","country","banner"],"char":'\ud83c\uddf3\ud83c\udde8',fitzpatrick_scale:!1,category:"flags"},new_zealand:{keywords:["new","zealand","flag","nation","country","banner"],"char":'\ud83c\uddf3\ud83c\uddff',fitzpatrick_scale:!1,category:"flags"},nicaragua:{keywords:["ni","flag","nation","country","banner"],"char":'\ud83c\uddf3\ud83c\uddee',fitzpatrick_scale:!1,category:"flags"},niger:{keywords:["ne","flag","nation","country","banner"],"char":'\ud83c\uddf3\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},nigeria:{keywords:["flag","nation","country","banner"],"char":'\ud83c\uddf3\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},niue:{keywords:["nu","flag","nation","country","banner"],"char":'\ud83c\uddf3\ud83c\uddfa',fitzpatrick_scale:!1,category:"flags"},norfolk_island:{keywords:["norfolk","island","flag","nation","country","banner"],"char":'\ud83c\uddf3\ud83c\uddeb',fitzpatrick_scale:!1,category:"flags"},northern_mariana_islands:{keywords:["northern","mariana","islands","flag","nation","country","banner"],"char":'\ud83c\uddf2\ud83c\uddf5',fitzpatrick_scale:!1,category:"flags"},north_korea:{keywords:["north","korea","nation","flag","country","banner"],"char":'\ud83c\uddf0\ud83c\uddf5',fitzpatrick_scale:!1,category:"flags"},norway:{keywords:["no","flag","nation","country","banner"],"char":'\ud83c\uddf3\ud83c\uddf4',fitzpatrick_scale:!1,category:"flags"},oman:{keywords:["om_symbol","flag","nation","country","banner"],"char":'\ud83c\uddf4\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},pakistan:{keywords:["pk","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\uddf0',fitzpatrick_scale:!1,category:"flags"},palau:{keywords:["pw","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\uddfc',fitzpatrick_scale:!1,category:"flags"},palestinian_territories:{keywords:["palestine","palestinian","territories","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\uddf8',fitzpatrick_scale:!1,category:"flags"},panama:{keywords:["pa","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\udde6',fitzpatrick_scale:!1,category:"flags"},papua_new_guinea:{keywords:["papua","new","guinea","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},paraguay:{keywords:["py","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\uddfe',fitzpatrick_scale:!1,category:"flags"},peru:{keywords:["pe","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},philippines:{keywords:["ph","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\udded',fitzpatrick_scale:!1,category:"flags"},pitcairn_islands:{keywords:["pitcairn","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\uddf3',fitzpatrick_scale:!1,category:"flags"},poland:{keywords:["pl","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\uddf1',fitzpatrick_scale:!1,category:"flags"},portugal:{keywords:["pt","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\uddf9',fitzpatrick_scale:!1,category:"flags"},puerto_rico:{keywords:["puerto","rico","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},qatar:{keywords:["qa","flag","nation","country","banner"],"char":'\ud83c\uddf6\ud83c\udde6',fitzpatrick_scale:!1,category:"flags"},reunion:{keywords:["r\xe9union","flag","nation","country","banner"],"char":'\ud83c\uddf7\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},romania:{keywords:["ro","flag","nation","country","banner"],"char":'\ud83c\uddf7\ud83c\uddf4',fitzpatrick_scale:!1,category:"flags"},ru:{keywords:["russian","federation","flag","nation","country","banner"],"char":'\ud83c\uddf7\ud83c\uddfa',fitzpatrick_scale:!1,category:"flags"},rwanda:{keywords:["rw","flag","nation","country","banner"],"char":'\ud83c\uddf7\ud83c\uddfc',fitzpatrick_scale:!1,category:"flags"},st_barthelemy:{keywords:["saint","barth\xe9lemy","flag","nation","country","banner"],"char":'\ud83c\udde7\ud83c\uddf1',fitzpatrick_scale:!1,category:"flags"},st_helena:{keywords:["saint","helena","ascension","tristan","cunha","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\udded',fitzpatrick_scale:!1,category:"flags"},st_kitts_nevis:{keywords:["saint","kitts","nevis","flag","nation","country","banner"],"char":'\ud83c\uddf0\ud83c\uddf3',fitzpatrick_scale:!1,category:"flags"},st_lucia:{keywords:["saint","lucia","flag","nation","country","banner"],"char":'\ud83c\uddf1\ud83c\udde8',fitzpatrick_scale:!1,category:"flags"},st_pierre_miquelon:{keywords:["saint","pierre","miquelon","flag","nation","country","banner"],"char":'\ud83c\uddf5\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},st_vincent_grenadines:{keywords:["saint","vincent","grenadines","flag","nation","country","banner"],"char":'\ud83c\uddfb\ud83c\udde8',fitzpatrick_scale:!1,category:"flags"},samoa:{keywords:["ws","flag","nation","country","banner"],"char":'\ud83c\uddfc\ud83c\uddf8',fitzpatrick_scale:!1,category:"flags"},san_marino:{keywords:["san","marino","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},sao_tome_principe:{keywords:["sao","tome","principe","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddf9',fitzpatrick_scale:!1,category:"flags"},saudi_arabia:{keywords:["flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\udde6',fitzpatrick_scale:!1,category:"flags"},senegal:{keywords:["sn","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddf3',fitzpatrick_scale:!1,category:"flags"},serbia:{keywords:["rs","flag","nation","country","banner"],"char":'\ud83c\uddf7\ud83c\uddf8',fitzpatrick_scale:!1,category:"flags"},seychelles:{keywords:["sc","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\udde8',fitzpatrick_scale:!1,category:"flags"},sierra_leone:{keywords:["sierra","leone","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddf1',fitzpatrick_scale:!1,category:"flags"},singapore:{keywords:["sg","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},sint_maarten:{keywords:["sint","maarten","dutch","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddfd',fitzpatrick_scale:!1,category:"flags"},slovakia:{keywords:["sk","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddf0',fitzpatrick_scale:!1,category:"flags"},slovenia:{keywords:["si","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddee',fitzpatrick_scale:!1,category:"flags"},solomon_islands:{keywords:["solomon","islands","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\udde7',fitzpatrick_scale:!1,category:"flags"},somalia:{keywords:["so","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddf4',fitzpatrick_scale:!1,category:"flags"},south_africa:{keywords:["south","africa","flag","nation","country","banner"],"char":'\ud83c\uddff\ud83c\udde6',fitzpatrick_scale:!1,category:"flags"},south_georgia_south_sandwich_islands:{keywords:["south","georgia","sandwich","islands","flag","nation","country","banner"],"char":'\ud83c\uddec\ud83c\uddf8',fitzpatrick_scale:!1,category:"flags"},kr:{keywords:["south","korea","nation","flag","country","banner"],"char":'\ud83c\uddf0\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},south_sudan:{keywords:["south","sd","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddf8',fitzpatrick_scale:!1,category:"flags"},es:{keywords:["spain","flag","nation","country","banner"],"char":'\ud83c\uddea\ud83c\uddf8',fitzpatrick_scale:!1,category:"flags"},sri_lanka:{keywords:["sri","lanka","flag","nation","country","banner"],"char":'\ud83c\uddf1\ud83c\uddf0',fitzpatrick_scale:!1,category:"flags"},sudan:{keywords:["sd","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\udde9',fitzpatrick_scale:!1,category:"flags"},suriname:{keywords:["sr","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},swaziland:{keywords:["sz","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddff',fitzpatrick_scale:!1,category:"flags"},sweden:{keywords:["se","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},switzerland:{keywords:["ch","flag","nation","country","banner"],"char":'\ud83c\udde8\ud83c\udded',fitzpatrick_scale:!1,category:"flags"},syria:{keywords:["syrian","arab","republic","flag","nation","country","banner"],"char":'\ud83c\uddf8\ud83c\uddfe',fitzpatrick_scale:!1,category:"flags"},taiwan:{keywords:["tw","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddfc',fitzpatrick_scale:!1,category:"flags"},tajikistan:{keywords:["tj","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddef',fitzpatrick_scale:!1,category:"flags"},tanzania:{keywords:["tanzania,","united","republic","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddff',fitzpatrick_scale:!1,category:"flags"},thailand:{keywords:["th","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\udded',fitzpatrick_scale:!1,category:"flags"},timor_leste:{keywords:["timor","leste","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddf1',fitzpatrick_scale:!1,category:"flags"},togo:{keywords:["tg","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},tokelau:{keywords:["tk","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddf0',fitzpatrick_scale:!1,category:"flags"},tonga:{keywords:["to","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddf4',fitzpatrick_scale:!1,category:"flags"},trinidad_tobago:{keywords:["trinidad","tobago","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddf9',fitzpatrick_scale:!1,category:"flags"},tunisia:{keywords:["tn","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddf3',fitzpatrick_scale:!1,category:"flags"},tr:{keywords:["turkey","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddf7',fitzpatrick_scale:!1,category:"flags"},turkmenistan:{keywords:["flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},turks_caicos_islands:{keywords:["turks","caicos","islands","flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\udde8',fitzpatrick_scale:!1,category:"flags"},tuvalu:{keywords:["flag","nation","country","banner"],"char":'\ud83c\uddf9\ud83c\uddfb',fitzpatrick_scale:!1,category:"flags"},uganda:{keywords:["ug","flag","nation","country","banner"],"char":'\ud83c\uddfa\ud83c\uddec',fitzpatrick_scale:!1,category:"flags"},ukraine:{keywords:["ua","flag","nation","country","banner"],"char":'\ud83c\uddfa\ud83c\udde6',fitzpatrick_scale:!1,category:"flags"},united_arab_emirates:{keywords:["united","arab","emirates","flag","nation","country","banner"],"char":'\ud83c\udde6\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},uk:{keywords:["united","kingdom","great","britain","northern","ireland","flag","nation","country","banner","british","UK","english","england","union jack"],"char":'\ud83c\uddec\ud83c\udde7',fitzpatrick_scale:!1,category:"flags"},england:{keywords:["flag","english"],"char":'\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f',fitzpatrick_scale:!1,category:"flags"},scotland:{keywords:["flag","scottish"],"char":'\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f',fitzpatrick_scale:!1,category:"flags"},wales:{keywords:["flag","welsh"],"char":'\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f',fitzpatrick_scale:!1,category:"flags"},us:{keywords:["united","states","america","flag","nation","country","banner"],"char":'\ud83c\uddfa\ud83c\uddf8',fitzpatrick_scale:!1,category:"flags"},us_virgin_islands:{keywords:["virgin","islands","us","flag","nation","country","banner"],"char":'\ud83c\uddfb\ud83c\uddee',fitzpatrick_scale:!1,category:"flags"},uruguay:{keywords:["uy","flag","nation","country","banner"],"char":'\ud83c\uddfa\ud83c\uddfe',fitzpatrick_scale:!1,category:"flags"},uzbekistan:{keywords:["uz","flag","nation","country","banner"],"char":'\ud83c\uddfa\ud83c\uddff',fitzpatrick_scale:!1,category:"flags"},vanuatu:{keywords:["vu","flag","nation","country","banner"],"char":'\ud83c\uddfb\ud83c\uddfa',fitzpatrick_scale:!1,category:"flags"},vatican_city:{keywords:["vatican","city","flag","nation","country","banner"],"char":'\ud83c\uddfb\ud83c\udde6',fitzpatrick_scale:!1,category:"flags"},venezuela:{keywords:["ve","bolivarian","republic","flag","nation","country","banner"],"char":'\ud83c\uddfb\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},vietnam:{keywords:["viet","nam","flag","nation","country","banner"],"char":'\ud83c\uddfb\ud83c\uddf3',fitzpatrick_scale:!1,category:"flags"},wallis_futuna:{keywords:["wallis","futuna","flag","nation","country","banner"],"char":'\ud83c\uddfc\ud83c\uddeb',fitzpatrick_scale:!1,category:"flags"},western_sahara:{keywords:["western","sahara","flag","nation","country","banner"],"char":'\ud83c\uddea\ud83c\udded',fitzpatrick_scale:!1,category:"flags"},yemen:{keywords:["ye","flag","nation","country","banner"],"char":'\ud83c\uddfe\ud83c\uddea',fitzpatrick_scale:!1,category:"flags"},zambia:{keywords:["zm","flag","nation","country","banner"],"char":'\ud83c\uddff\ud83c\uddf2',fitzpatrick_scale:!1,category:"flags"},zimbabwe:{keywords:["zw","flag","nation","country","banner"],"char":'\ud83c\uddff\ud83c\uddfc',fitzpatrick_scale:!1,category:"flags"},united_nations:{keywords:["un","flag","banner"],"char":'\ud83c\uddfa\ud83c\uddf3',fitzpatrick_scale:!1,category:"flags"},pirate_flag:{keywords:["skull","crossbones","flag","banner"],"char":'\ud83c\udff4\u200d\u2620\ufe0f',fitzpatrick_scale:!1,category:"flags"}}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/js/emojis.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/js/emojis.js new file mode 100644 index 0000000000000000000000000000000000000000..4adb59b0cf764289b4f86f4ecd4e82f1d71713bf --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/js/emojis.js @@ -0,0 +1,9423 @@ +// Source: npm package: emojilib, file:emojis.json +window.tinymce.Resource.add("tinymce.plugins.emoticons", { + grinning: { + keywords: [ "face", "smile", "happy", "joy", ":D", "grin" ], + "char": "\ud83d\ude00", + fitzpatrick_scale: false, + category: "people" + }, + grimacing: { + keywords: [ "face", "grimace", "teeth" ], + "char": "\ud83d\ude2c", + fitzpatrick_scale: false, + category: "people" + }, + grin: { + keywords: [ "face", "happy", "smile", "joy", "kawaii" ], + "char": "\ud83d\ude01", + fitzpatrick_scale: false, + category: "people" + }, + joy: { + keywords: [ "face", "cry", "tears", "weep", "happy", "happytears", "haha" ], + "char": "\ud83d\ude02", + fitzpatrick_scale: false, + category: "people" + }, + rofl: { + keywords: [ "face", "rolling", "floor", "laughing", "lol", "haha" ], + "char": "\ud83e\udd23", + fitzpatrick_scale: false, + category: "people" + }, + partying: { + keywords: [ "face", "celebration", "woohoo" ], + "char": "\ud83e\udd73", + fitzpatrick_scale: false, + category: "people" + }, + smiley: { + keywords: [ "face", "happy", "joy", "haha", ":D", ":)", "smile", "funny" ], + "char": "\ud83d\ude03", + fitzpatrick_scale: false, + category: "people" + }, + smile: { + keywords: [ "face", "happy", "joy", "funny", "haha", "laugh", "like", ":D", ":)" ], + "char": "\ud83d\ude04", + fitzpatrick_scale: false, + category: "people" + }, + sweat_smile: { + keywords: [ "face", "hot", "happy", "laugh", "sweat", "smile", "relief" ], + "char": "\ud83d\ude05", + fitzpatrick_scale: false, + category: "people" + }, + laughing: { + keywords: [ "happy", "joy", "lol", "satisfied", "haha", "face", "glad", "XD", "laugh" ], + "char": "\ud83d\ude06", + fitzpatrick_scale: false, + category: "people" + }, + innocent: { + keywords: [ "face", "angel", "heaven", "halo" ], + "char": "\ud83d\ude07", + fitzpatrick_scale: false, + category: "people" + }, + wink: { + keywords: [ "face", "happy", "mischievous", "secret", ";)", "smile", "eye" ], + "char": "\ud83d\ude09", + fitzpatrick_scale: false, + category: "people" + }, + blush: { + keywords: [ "face", "smile", "happy", "flushed", "crush", "embarrassed", "shy", "joy" ], + "char": "\ud83d\ude0a", + fitzpatrick_scale: false, + category: "people" + }, + slightly_smiling_face: { + keywords: [ "face", "smile" ], + "char": "\ud83d\ude42", + fitzpatrick_scale: false, + category: "people" + }, + upside_down_face: { + keywords: [ "face", "flipped", "silly", "smile" ], + "char": "\ud83d\ude43", + fitzpatrick_scale: false, + category: "people" + }, + relaxed: { + keywords: [ "face", "blush", "massage", "happiness" ], + "char": "\u263a\ufe0f", + fitzpatrick_scale: false, + category: "people" + }, + yum: { + keywords: [ "happy", "joy", "tongue", "smile", "face", "silly", "yummy", "nom", "delicious", "savouring" ], + "char": "\ud83d\ude0b", + fitzpatrick_scale: false, + category: "people" + }, + relieved: { + keywords: [ "face", "relaxed", "phew", "massage", "happiness" ], + "char": "\ud83d\ude0c", + fitzpatrick_scale: false, + category: "people" + }, + heart_eyes: { + keywords: [ "face", "love", "like", "affection", "valentines", "infatuation", "crush", "heart" ], + "char": "\ud83d\ude0d", + fitzpatrick_scale: false, + category: "people" + }, + smiling_face_with_three_hearts: { + keywords: [ "face", "love", "like", "affection", "valentines", "infatuation", "crush", "hearts", "adore" ], + "char": "\ud83e\udd70", + fitzpatrick_scale: false, + category: "people" + }, + kissing_heart: { + keywords: [ "face", "love", "like", "affection", "valentines", "infatuation", "kiss" ], + "char": "\ud83d\ude18", + fitzpatrick_scale: false, + category: "people" + }, + kissing: { + keywords: [ "love", "like", "face", "3", "valentines", "infatuation", "kiss" ], + "char": "\ud83d\ude17", + fitzpatrick_scale: false, + category: "people" + }, + kissing_smiling_eyes: { + keywords: [ "face", "affection", "valentines", "infatuation", "kiss" ], + "char": "\ud83d\ude19", + fitzpatrick_scale: false, + category: "people" + }, + kissing_closed_eyes: { + keywords: [ "face", "love", "like", "affection", "valentines", "infatuation", "kiss" ], + "char": "\ud83d\ude1a", + fitzpatrick_scale: false, + category: "people" + }, + stuck_out_tongue_winking_eye: { + keywords: [ "face", "prank", "childish", "playful", "mischievous", "smile", "wink", "tongue" ], + "char": "\ud83d\ude1c", + fitzpatrick_scale: false, + category: "people" + }, + zany: { + keywords: [ "face", "goofy", "crazy" ], + "char": "\ud83e\udd2a", + fitzpatrick_scale: false, + category: "people" + }, + raised_eyebrow: { + keywords: [ "face", "distrust", "scepticism", "disapproval", "disbelief", "surprise" ], + "char": "\ud83e\udd28", + fitzpatrick_scale: false, + category: "people" + }, + monocle: { + keywords: [ "face", "stuffy", "wealthy" ], + "char": "\ud83e\uddd0", + fitzpatrick_scale: false, + category: "people" + }, + stuck_out_tongue_closed_eyes: { + keywords: [ "face", "prank", "playful", "mischievous", "smile", "tongue" ], + "char": "\ud83d\ude1d", + fitzpatrick_scale: false, + category: "people" + }, + stuck_out_tongue: { + keywords: [ "face", "prank", "childish", "playful", "mischievous", "smile", "tongue" ], + "char": "\ud83d\ude1b", + fitzpatrick_scale: false, + category: "people" + }, + money_mouth_face: { + keywords: [ "face", "rich", "dollar", "money" ], + "char": "\ud83e\udd11", + fitzpatrick_scale: false, + category: "people" + }, + nerd_face: { + keywords: [ "face", "nerdy", "geek", "dork" ], + "char": "\ud83e\udd13", + fitzpatrick_scale: false, + category: "people" + }, + sunglasses: { + keywords: [ "face", "cool", "smile", "summer", "beach", "sunglass" ], + "char": "\ud83d\ude0e", + fitzpatrick_scale: false, + category: "people" + }, + star_struck: { + keywords: [ "face", "smile", "starry", "eyes", "grinning" ], + "char": "\ud83e\udd29", + fitzpatrick_scale: false, + category: "people" + }, + clown_face: { + keywords: [ "face" ], + "char": "\ud83e\udd21", + fitzpatrick_scale: false, + category: "people" + }, + cowboy_hat_face: { + keywords: [ "face", "cowgirl", "hat" ], + "char": "\ud83e\udd20", + fitzpatrick_scale: false, + category: "people" + }, + hugs: { + keywords: [ "face", "smile", "hug" ], + "char": "\ud83e\udd17", + fitzpatrick_scale: false, + category: "people" + }, + smirk: { + keywords: [ "face", "smile", "mean", "prank", "smug", "sarcasm" ], + "char": "\ud83d\ude0f", + fitzpatrick_scale: false, + category: "people" + }, + no_mouth: { + keywords: [ "face", "hellokitty" ], + "char": "\ud83d\ude36", + fitzpatrick_scale: false, + category: "people" + }, + neutral_face: { + keywords: [ "indifference", "meh", ":|", "neutral" ], + "char": "\ud83d\ude10", + fitzpatrick_scale: false, + category: "people" + }, + expressionless: { + keywords: [ "face", "indifferent", "-_-", "meh", "deadpan" ], + "char": "\ud83d\ude11", + fitzpatrick_scale: false, + category: "people" + }, + unamused: { + keywords: [ "indifference", "bored", "straight face", "serious", "sarcasm", "unimpressed", "skeptical", "dubious", "side_eye" ], + "char": "\ud83d\ude12", + fitzpatrick_scale: false, + category: "people" + }, + roll_eyes: { + keywords: [ "face", "eyeroll", "frustrated" ], + "char": "\ud83d\ude44", + fitzpatrick_scale: false, + category: "people" + }, + thinking: { + keywords: [ "face", "hmmm", "think", "consider" ], + "char": "\ud83e\udd14", + fitzpatrick_scale: false, + category: "people" + }, + lying_face: { + keywords: [ "face", "lie", "pinocchio" ], + "char": "\ud83e\udd25", + fitzpatrick_scale: false, + category: "people" + }, + hand_over_mouth: { + keywords: [ "face", "whoops", "shock", "surprise" ], + "char": "\ud83e\udd2d", + fitzpatrick_scale: false, + category: "people" + }, + shushing: { + keywords: [ "face", "quiet", "shhh" ], + "char": "\ud83e\udd2b", + fitzpatrick_scale: false, + category: "people" + }, + symbols_over_mouth: { + keywords: [ "face", "swearing", "cursing", "cussing", "profanity", "expletive" ], + "char": "\ud83e\udd2c", + fitzpatrick_scale: false, + category: "people" + }, + exploding_head: { + keywords: [ "face", "shocked", "mind", "blown" ], + "char": "\ud83e\udd2f", + fitzpatrick_scale: false, + category: "people" + }, + flushed: { + keywords: [ "face", "blush", "shy", "flattered" ], + "char": "\ud83d\ude33", + fitzpatrick_scale: false, + category: "people" + }, + disappointed: { + keywords: [ "face", "sad", "upset", "depressed", ":(" ], + "char": "\ud83d\ude1e", + fitzpatrick_scale: false, + category: "people" + }, + worried: { + keywords: [ "face", "concern", "nervous", ":(" ], + "char": "\ud83d\ude1f", + fitzpatrick_scale: false, + category: "people" + }, + angry: { + keywords: [ "mad", "face", "annoyed", "frustrated" ], + "char": "\ud83d\ude20", + fitzpatrick_scale: false, + category: "people" + }, + rage: { + keywords: [ "angry", "mad", "hate", "despise" ], + "char": "\ud83d\ude21", + fitzpatrick_scale: false, + category: "people" + }, + pensive: { + keywords: [ "face", "sad", "depressed", "upset" ], + "char": "\ud83d\ude14", + fitzpatrick_scale: false, + category: "people" + }, + confused: { + keywords: [ "face", "indifference", "huh", "weird", "hmmm", ":/" ], + "char": "\ud83d\ude15", + fitzpatrick_scale: false, + category: "people" + }, + slightly_frowning_face: { + keywords: [ "face", "frowning", "disappointed", "sad", "upset" ], + "char": "\ud83d\ude41", + fitzpatrick_scale: false, + category: "people" + }, + frowning_face: { + keywords: [ "face", "sad", "upset", "frown" ], + "char": "\u2639", + fitzpatrick_scale: false, + category: "people" + }, + persevere: { + keywords: [ "face", "sick", "no", "upset", "oops" ], + "char": "\ud83d\ude23", + fitzpatrick_scale: false, + category: "people" + }, + confounded: { + keywords: [ "face", "confused", "sick", "unwell", "oops", ":S" ], + "char": "\ud83d\ude16", + fitzpatrick_scale: false, + category: "people" + }, + tired_face: { + keywords: [ "sick", "whine", "upset", "frustrated" ], + "char": "\ud83d\ude2b", + fitzpatrick_scale: false, + category: "people" + }, + weary: { + keywords: [ "face", "tired", "sleepy", "sad", "frustrated", "upset" ], + "char": "\ud83d\ude29", + fitzpatrick_scale: false, + category: "people" + }, + pleading: { + keywords: [ "face", "begging", "mercy" ], + "char": "\ud83e\udd7a", + fitzpatrick_scale: false, + category: "people" + }, + triumph: { + keywords: [ "face", "gas", "phew", "proud", "pride" ], + "char": "\ud83d\ude24", + fitzpatrick_scale: false, + category: "people" + }, + open_mouth: { + keywords: [ "face", "surprise", "impressed", "wow", "whoa", ":O" ], + "char": "\ud83d\ude2e", + fitzpatrick_scale: false, + category: "people" + }, + scream: { + keywords: [ "face", "munch", "scared", "omg" ], + "char": "\ud83d\ude31", + fitzpatrick_scale: false, + category: "people" + }, + fearful: { + keywords: [ "face", "scared", "terrified", "nervous", "oops", "huh" ], + "char": "\ud83d\ude28", + fitzpatrick_scale: false, + category: "people" + }, + cold_sweat: { + keywords: [ "face", "nervous", "sweat" ], + "char": "\ud83d\ude30", + fitzpatrick_scale: false, + category: "people" + }, + hushed: { + keywords: [ "face", "woo", "shh" ], + "char": "\ud83d\ude2f", + fitzpatrick_scale: false, + category: "people" + }, + frowning: { + keywords: [ "face", "aw", "what" ], + "char": "\ud83d\ude26", + fitzpatrick_scale: false, + category: "people" + }, + anguished: { + keywords: [ "face", "stunned", "nervous" ], + "char": "\ud83d\ude27", + fitzpatrick_scale: false, + category: "people" + }, + cry: { + keywords: [ "face", "tears", "sad", "depressed", "upset", ":'(" ], + "char": "\ud83d\ude22", + fitzpatrick_scale: false, + category: "people" + }, + disappointed_relieved: { + keywords: [ "face", "phew", "sweat", "nervous" ], + "char": "\ud83d\ude25", + fitzpatrick_scale: false, + category: "people" + }, + drooling_face: { + keywords: [ "face" ], + "char": "\ud83e\udd24", + fitzpatrick_scale: false, + category: "people" + }, + sleepy: { + keywords: [ "face", "tired", "rest", "nap" ], + "char": "\ud83d\ude2a", + fitzpatrick_scale: false, + category: "people" + }, + sweat: { + keywords: [ "face", "hot", "sad", "tired", "exercise" ], + "char": "\ud83d\ude13", + fitzpatrick_scale: false, + category: "people" + }, + hot: { + keywords: [ "face", "feverish", "heat", "red", "sweating" ], + "char": "\ud83e\udd75", + fitzpatrick_scale: false, + category: "people" + }, + cold: { + keywords: [ "face", "blue", "freezing", "frozen", "frostbite", "icicles" ], + "char": "\ud83e\udd76", + fitzpatrick_scale: false, + category: "people" + }, + sob: { + keywords: [ "face", "cry", "tears", "sad", "upset", "depressed" ], + "char": "\ud83d\ude2d", + fitzpatrick_scale: false, + category: "people" + }, + dizzy_face: { + keywords: [ "spent", "unconscious", "xox", "dizzy" ], + "char": "\ud83d\ude35", + fitzpatrick_scale: false, + category: "people" + }, + astonished: { + keywords: [ "face", "xox", "surprised", "poisoned" ], + "char": "\ud83d\ude32", + fitzpatrick_scale: false, + category: "people" + }, + zipper_mouth_face: { + keywords: [ "face", "sealed", "zipper", "secret" ], + "char": "\ud83e\udd10", + fitzpatrick_scale: false, + category: "people" + }, + nauseated_face: { + keywords: [ "face", "vomit", "gross", "green", "sick", "throw up", "ill" ], + "char": "\ud83e\udd22", + fitzpatrick_scale: false, + category: "people" + }, + sneezing_face: { + keywords: [ "face", "gesundheit", "sneeze", "sick", "allergy" ], + "char": "\ud83e\udd27", + fitzpatrick_scale: false, + category: "people" + }, + vomiting: { + keywords: [ "face", "sick" ], + "char": "\ud83e\udd2e", + fitzpatrick_scale: false, + category: "people" + }, + mask: { + keywords: [ "face", "sick", "ill", "disease" ], + "char": "\ud83d\ude37", + fitzpatrick_scale: false, + category: "people" + }, + face_with_thermometer: { + keywords: [ "sick", "temperature", "thermometer", "cold", "fever" ], + "char": "\ud83e\udd12", + fitzpatrick_scale: false, + category: "people" + }, + face_with_head_bandage: { + keywords: [ "injured", "clumsy", "bandage", "hurt" ], + "char": "\ud83e\udd15", + fitzpatrick_scale: false, + category: "people" + }, + woozy: { + keywords: [ "face", "dizzy", "intoxicated", "tipsy", "wavy" ], + "char": "\ud83e\udd74", + fitzpatrick_scale: false, + category: "people" + }, + sleeping: { + keywords: [ "face", "tired", "sleepy", "night", "zzz" ], + "char": "\ud83d\ude34", + fitzpatrick_scale: false, + category: "people" + }, + zzz: { + keywords: [ "sleepy", "tired", "dream" ], + "char": "\ud83d\udca4", + fitzpatrick_scale: false, + category: "people" + }, + poop: { + keywords: [ "hankey", "shitface", "fail", "turd", "shit" ], + "char": "\ud83d\udca9", + fitzpatrick_scale: false, + category: "people" + }, + smiling_imp: { + keywords: [ "devil", "horns" ], + "char": "\ud83d\ude08", + fitzpatrick_scale: false, + category: "people" + }, + imp: { + keywords: [ "devil", "angry", "horns" ], + "char": "\ud83d\udc7f", + fitzpatrick_scale: false, + category: "people" + }, + japanese_ogre: { + keywords: [ "monster", "red", "mask", "halloween", "scary", "creepy", "devil", "demon", "japanese", "ogre" ], + "char": "\ud83d\udc79", + fitzpatrick_scale: false, + category: "people" + }, + japanese_goblin: { + keywords: [ "red", "evil", "mask", "monster", "scary", "creepy", "japanese", "goblin" ], + "char": "\ud83d\udc7a", + fitzpatrick_scale: false, + category: "people" + }, + skull: { + keywords: [ "dead", "skeleton", "creepy", "death" ], + "char": "\ud83d\udc80", + fitzpatrick_scale: false, + category: "people" + }, + ghost: { + keywords: [ "halloween", "spooky", "scary" ], + "char": "\ud83d\udc7b", + fitzpatrick_scale: false, + category: "people" + }, + alien: { + keywords: [ "UFO", "paul", "weird", "outer_space" ], + "char": "\ud83d\udc7d", + fitzpatrick_scale: false, + category: "people" + }, + robot: { + keywords: [ "computer", "machine", "bot" ], + "char": "\ud83e\udd16", + fitzpatrick_scale: false, + category: "people" + }, + smiley_cat: { + keywords: [ "animal", "cats", "happy", "smile" ], + "char": "\ud83d\ude3a", + fitzpatrick_scale: false, + category: "people" + }, + smile_cat: { + keywords: [ "animal", "cats", "smile" ], + "char": "\ud83d\ude38", + fitzpatrick_scale: false, + category: "people" + }, + joy_cat: { + keywords: [ "animal", "cats", "haha", "happy", "tears" ], + "char": "\ud83d\ude39", + fitzpatrick_scale: false, + category: "people" + }, + heart_eyes_cat: { + keywords: [ "animal", "love", "like", "affection", "cats", "valentines", "heart" ], + "char": "\ud83d\ude3b", + fitzpatrick_scale: false, + category: "people" + }, + smirk_cat: { + keywords: [ "animal", "cats", "smirk" ], + "char": "\ud83d\ude3c", + fitzpatrick_scale: false, + category: "people" + }, + kissing_cat: { + keywords: [ "animal", "cats", "kiss" ], + "char": "\ud83d\ude3d", + fitzpatrick_scale: false, + category: "people" + }, + scream_cat: { + keywords: [ "animal", "cats", "munch", "scared", "scream" ], + "char": "\ud83d\ude40", + fitzpatrick_scale: false, + category: "people" + }, + crying_cat_face: { + keywords: [ "animal", "tears", "weep", "sad", "cats", "upset", "cry" ], + "char": "\ud83d\ude3f", + fitzpatrick_scale: false, + category: "people" + }, + pouting_cat: { + keywords: [ "animal", "cats" ], + "char": "\ud83d\ude3e", + fitzpatrick_scale: false, + category: "people" + }, + palms_up: { + keywords: [ "hands", "gesture", "cupped", "prayer" ], + "char": "\ud83e\udd32", + fitzpatrick_scale: true, + category: "people" + }, + raised_hands: { + keywords: [ "gesture", "hooray", "yea", "celebration", "hands" ], + "char": "\ud83d\ude4c", + fitzpatrick_scale: true, + category: "people" + }, + clap: { + keywords: [ "hands", "praise", "applause", "congrats", "yay" ], + "char": "\ud83d\udc4f", + fitzpatrick_scale: true, + category: "people" + }, + wave: { + keywords: [ "hands", "gesture", "goodbye", "solong", "farewell", "hello", "hi", "palm" ], + "char": "\ud83d\udc4b", + fitzpatrick_scale: true, + category: "people" + }, + call_me_hand: { + keywords: [ "hands", "gesture" ], + "char": "\ud83e\udd19", + fitzpatrick_scale: true, + category: "people" + }, + "+1": { + keywords: [ "thumbsup", "yes", "awesome", "good", "agree", "accept", "cool", "hand", "like" ], + "char": "\ud83d\udc4d", + fitzpatrick_scale: true, + category: "people" + }, + "-1": { + keywords: [ "thumbsdown", "no", "dislike", "hand" ], + "char": "\ud83d\udc4e", + fitzpatrick_scale: true, + category: "people" + }, + facepunch: { + keywords: [ "angry", "violence", "fist", "hit", "attack", "hand" ], + "char": "\ud83d\udc4a", + fitzpatrick_scale: true, + category: "people" + }, + fist: { + keywords: [ "fingers", "hand", "grasp" ], + "char": "\u270a", + fitzpatrick_scale: true, + category: "people" + }, + fist_left: { + keywords: [ "hand", "fistbump" ], + "char": "\ud83e\udd1b", + fitzpatrick_scale: true, + category: "people" + }, + fist_right: { + keywords: [ "hand", "fistbump" ], + "char": "\ud83e\udd1c", + fitzpatrick_scale: true, + category: "people" + }, + v: { + keywords: [ "fingers", "ohyeah", "hand", "peace", "victory", "two" ], + "char": "\u270c", + fitzpatrick_scale: true, + category: "people" + }, + ok_hand: { + keywords: [ "fingers", "limbs", "perfect", "ok", "okay" ], + "char": "\ud83d\udc4c", + fitzpatrick_scale: true, + category: "people" + }, + raised_hand: { + keywords: [ "fingers", "stop", "highfive", "palm", "ban" ], + "char": "\u270b", + fitzpatrick_scale: true, + category: "people" + }, + raised_back_of_hand: { + keywords: [ "fingers", "raised", "backhand" ], + "char": "\ud83e\udd1a", + fitzpatrick_scale: true, + category: "people" + }, + open_hands: { + keywords: [ "fingers", "butterfly", "hands", "open" ], + "char": "\ud83d\udc50", + fitzpatrick_scale: true, + category: "people" + }, + muscle: { + keywords: [ "arm", "flex", "hand", "summer", "strong", "biceps" ], + "char": "\ud83d\udcaa", + fitzpatrick_scale: true, + category: "people" + }, + pray: { + keywords: [ "please", "hope", "wish", "namaste", "highfive" ], + "char": "\ud83d\ude4f", + fitzpatrick_scale: true, + category: "people" + }, + foot: { + keywords: [ "kick", "stomp" ], + "char": "\ud83e\uddb6", + fitzpatrick_scale: true, + category: "people" + }, + leg: { + keywords: [ "kick", "limb" ], + "char": "\ud83e\uddb5", + fitzpatrick_scale: true, + category: "people" + }, + handshake: { + keywords: [ "agreement", "shake" ], + "char": "\ud83e\udd1d", + fitzpatrick_scale: false, + category: "people" + }, + point_up: { + keywords: [ "hand", "fingers", "direction", "up" ], + "char": "\u261d", + fitzpatrick_scale: true, + category: "people" + }, + point_up_2: { + keywords: [ "fingers", "hand", "direction", "up" ], + "char": "\ud83d\udc46", + fitzpatrick_scale: true, + category: "people" + }, + point_down: { + keywords: [ "fingers", "hand", "direction", "down" ], + "char": "\ud83d\udc47", + fitzpatrick_scale: true, + category: "people" + }, + point_left: { + keywords: [ "direction", "fingers", "hand", "left" ], + "char": "\ud83d\udc48", + fitzpatrick_scale: true, + category: "people" + }, + point_right: { + keywords: [ "fingers", "hand", "direction", "right" ], + "char": "\ud83d\udc49", + fitzpatrick_scale: true, + category: "people" + }, + fu: { + keywords: [ "hand", "fingers", "rude", "middle", "flipping" ], + "char": "\ud83d\udd95", + fitzpatrick_scale: true, + category: "people" + }, + raised_hand_with_fingers_splayed: { + keywords: [ "hand", "fingers", "palm" ], + "char": "\ud83d\udd90", + fitzpatrick_scale: true, + category: "people" + }, + love_you: { + keywords: [ "hand", "fingers", "gesture" ], + "char": "\ud83e\udd1f", + fitzpatrick_scale: true, + category: "people" + }, + metal: { + keywords: [ "hand", "fingers", "evil_eye", "sign_of_horns", "rock_on" ], + "char": "\ud83e\udd18", + fitzpatrick_scale: true, + category: "people" + }, + crossed_fingers: { + keywords: [ "good", "lucky" ], + "char": "\ud83e\udd1e", + fitzpatrick_scale: true, + category: "people" + }, + vulcan_salute: { + keywords: [ "hand", "fingers", "spock", "star trek" ], + "char": "\ud83d\udd96", + fitzpatrick_scale: true, + category: "people" + }, + writing_hand: { + keywords: [ "lower_left_ballpoint_pen", "stationery", "write", "compose" ], + "char": "\u270d", + fitzpatrick_scale: true, + category: "people" + }, + selfie: { + keywords: [ "camera", "phone" ], + "char": "\ud83e\udd33", + fitzpatrick_scale: true, + category: "people" + }, + nail_care: { + keywords: [ "beauty", "manicure", "finger", "fashion", "nail" ], + "char": "\ud83d\udc85", + fitzpatrick_scale: true, + category: "people" + }, + lips: { + keywords: [ "mouth", "kiss" ], + "char": "\ud83d\udc44", + fitzpatrick_scale: false, + category: "people" + }, + tooth: { + keywords: [ "teeth", "dentist" ], + "char": "\ud83e\uddb7", + fitzpatrick_scale: false, + category: "people" + }, + tongue: { + keywords: [ "mouth", "playful" ], + "char": "\ud83d\udc45", + fitzpatrick_scale: false, + category: "people" + }, + ear: { + keywords: [ "face", "hear", "sound", "listen" ], + "char": "\ud83d\udc42", + fitzpatrick_scale: true, + category: "people" + }, + nose: { + keywords: [ "smell", "sniff" ], + "char": "\ud83d\udc43", + fitzpatrick_scale: true, + category: "people" + }, + eye: { + keywords: [ "face", "look", "see", "watch", "stare" ], + "char": "\ud83d\udc41", + fitzpatrick_scale: false, + category: "people" + }, + eyes: { + keywords: [ "look", "watch", "stalk", "peek", "see" ], + "char": "\ud83d\udc40", + fitzpatrick_scale: false, + category: "people" + }, + brain: { + keywords: [ "smart", "intelligent" ], + "char": "\ud83e\udde0", + fitzpatrick_scale: false, + category: "people" + }, + bust_in_silhouette: { + keywords: [ "user", "person", "human" ], + "char": "\ud83d\udc64", + fitzpatrick_scale: false, + category: "people" + }, + busts_in_silhouette: { + keywords: [ "user", "person", "human", "group", "team" ], + "char": "\ud83d\udc65", + fitzpatrick_scale: false, + category: "people" + }, + speaking_head: { + keywords: [ "user", "person", "human", "sing", "say", "talk" ], + "char": "\ud83d\udde3", + fitzpatrick_scale: false, + category: "people" + }, + baby: { + keywords: [ "child", "boy", "girl", "toddler" ], + "char": "\ud83d\udc76", + fitzpatrick_scale: true, + category: "people" + }, + child: { + keywords: [ "gender-neutral", "young" ], + "char": "\ud83e\uddd2", + fitzpatrick_scale: true, + category: "people" + }, + boy: { + keywords: [ "man", "male", "guy", "teenager" ], + "char": "\ud83d\udc66", + fitzpatrick_scale: true, + category: "people" + }, + girl: { + keywords: [ "female", "woman", "teenager" ], + "char": "\ud83d\udc67", + fitzpatrick_scale: true, + category: "people" + }, + adult: { + keywords: [ "gender-neutral", "person" ], + "char": "\ud83e\uddd1", + fitzpatrick_scale: true, + category: "people" + }, + man: { + keywords: [ "mustache", "father", "dad", "guy", "classy", "sir", "moustache" ], + "char": "\ud83d\udc68", + fitzpatrick_scale: true, + category: "people" + }, + woman: { + keywords: [ "female", "girls", "lady" ], + "char": "\ud83d\udc69", + fitzpatrick_scale: true, + category: "people" + }, + blonde_woman: { + keywords: [ "woman", "female", "girl", "blonde", "person" ], + "char": "\ud83d\udc71\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + blonde_man: { + keywords: [ "man", "male", "boy", "blonde", "guy", "person" ], + "char": "\ud83d\udc71", + fitzpatrick_scale: true, + category: "people" + }, + bearded_person: { + keywords: [ "person", "bewhiskered" ], + "char": "\ud83e\uddd4", + fitzpatrick_scale: true, + category: "people" + }, + older_adult: { + keywords: [ "human", "elder", "senior", "gender-neutral" ], + "char": "\ud83e\uddd3", + fitzpatrick_scale: true, + category: "people" + }, + older_man: { + keywords: [ "human", "male", "men", "old", "elder", "senior" ], + "char": "\ud83d\udc74", + fitzpatrick_scale: true, + category: "people" + }, + older_woman: { + keywords: [ "human", "female", "women", "lady", "old", "elder", "senior" ], + "char": "\ud83d\udc75", + fitzpatrick_scale: true, + category: "people" + }, + man_with_gua_pi_mao: { + keywords: [ "male", "boy", "chinese" ], + "char": "\ud83d\udc72", + fitzpatrick_scale: true, + category: "people" + }, + woman_with_headscarf: { + keywords: [ "female", "hijab", "mantilla", "tichel" ], + "char": "\ud83e\uddd5", + fitzpatrick_scale: true, + category: "people" + }, + woman_with_turban: { + keywords: [ "female", "indian", "hinduism", "arabs", "woman" ], + "char": "\ud83d\udc73\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + man_with_turban: { + keywords: [ "male", "indian", "hinduism", "arabs" ], + "char": "\ud83d\udc73", + fitzpatrick_scale: true, + category: "people" + }, + policewoman: { + keywords: [ "woman", "police", "law", "legal", "enforcement", "arrest", "911", "female" ], + "char": "\ud83d\udc6e\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + policeman: { + keywords: [ "man", "police", "law", "legal", "enforcement", "arrest", "911" ], + "char": "\ud83d\udc6e", + fitzpatrick_scale: true, + category: "people" + }, + construction_worker_woman: { + keywords: [ "female", "human", "wip", "build", "construction", "worker", "labor", "woman" ], + "char": "\ud83d\udc77\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + construction_worker_man: { + keywords: [ "male", "human", "wip", "guy", "build", "construction", "worker", "labor" ], + "char": "\ud83d\udc77", + fitzpatrick_scale: true, + category: "people" + }, + guardswoman: { + keywords: [ "uk", "gb", "british", "female", "royal", "woman" ], + "char": "\ud83d\udc82\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + guardsman: { + keywords: [ "uk", "gb", "british", "male", "guy", "royal" ], + "char": "\ud83d\udc82", + fitzpatrick_scale: true, + category: "people" + }, + female_detective: { + keywords: [ "human", "spy", "detective", "female", "woman" ], + "char": "\ud83d\udd75\ufe0f\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + male_detective: { + keywords: [ "human", "spy", "detective" ], + "char": "\ud83d\udd75", + fitzpatrick_scale: true, + category: "people" + }, + woman_health_worker: { + keywords: [ "doctor", "nurse", "therapist", "healthcare", "woman", "human" ], + "char": "\ud83d\udc69\u200d\u2695\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + man_health_worker: { + keywords: [ "doctor", "nurse", "therapist", "healthcare", "man", "human" ], + "char": "\ud83d\udc68\u200d\u2695\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + woman_farmer: { + keywords: [ "rancher", "gardener", "woman", "human" ], + "char": "\ud83d\udc69\u200d\ud83c\udf3e", + fitzpatrick_scale: true, + category: "people" + }, + man_farmer: { + keywords: [ "rancher", "gardener", "man", "human" ], + "char": "\ud83d\udc68\u200d\ud83c\udf3e", + fitzpatrick_scale: true, + category: "people" + }, + woman_cook: { + keywords: [ "chef", "woman", "human" ], + "char": "\ud83d\udc69\u200d\ud83c\udf73", + fitzpatrick_scale: true, + category: "people" + }, + man_cook: { + keywords: [ "chef", "man", "human" ], + "char": "\ud83d\udc68\u200d\ud83c\udf73", + fitzpatrick_scale: true, + category: "people" + }, + woman_student: { + keywords: [ "graduate", "woman", "human" ], + "char": "\ud83d\udc69\u200d\ud83c\udf93", + fitzpatrick_scale: true, + category: "people" + }, + man_student: { + keywords: [ "graduate", "man", "human" ], + "char": "\ud83d\udc68\u200d\ud83c\udf93", + fitzpatrick_scale: true, + category: "people" + }, + woman_singer: { + keywords: [ "rockstar", "entertainer", "woman", "human" ], + "char": "\ud83d\udc69\u200d\ud83c\udfa4", + fitzpatrick_scale: true, + category: "people" + }, + man_singer: { + keywords: [ "rockstar", "entertainer", "man", "human" ], + "char": "\ud83d\udc68\u200d\ud83c\udfa4", + fitzpatrick_scale: true, + category: "people" + }, + woman_teacher: { + keywords: [ "instructor", "professor", "woman", "human" ], + "char": "\ud83d\udc69\u200d\ud83c\udfeb", + fitzpatrick_scale: true, + category: "people" + }, + man_teacher: { + keywords: [ "instructor", "professor", "man", "human" ], + "char": "\ud83d\udc68\u200d\ud83c\udfeb", + fitzpatrick_scale: true, + category: "people" + }, + woman_factory_worker: { + keywords: [ "assembly", "industrial", "woman", "human" ], + "char": "\ud83d\udc69\u200d\ud83c\udfed", + fitzpatrick_scale: true, + category: "people" + }, + man_factory_worker: { + keywords: [ "assembly", "industrial", "man", "human" ], + "char": "\ud83d\udc68\u200d\ud83c\udfed", + fitzpatrick_scale: true, + category: "people" + }, + woman_technologist: { + keywords: [ "coder", "developer", "engineer", "programmer", "software", "woman", "human", "laptop", "computer" ], + "char": "\ud83d\udc69\u200d\ud83d\udcbb", + fitzpatrick_scale: true, + category: "people" + }, + man_technologist: { + keywords: [ "coder", "developer", "engineer", "programmer", "software", "man", "human", "laptop", "computer" ], + "char": "\ud83d\udc68\u200d\ud83d\udcbb", + fitzpatrick_scale: true, + category: "people" + }, + woman_office_worker: { + keywords: [ "business", "manager", "woman", "human" ], + "char": "\ud83d\udc69\u200d\ud83d\udcbc", + fitzpatrick_scale: true, + category: "people" + }, + man_office_worker: { + keywords: [ "business", "manager", "man", "human" ], + "char": "\ud83d\udc68\u200d\ud83d\udcbc", + fitzpatrick_scale: true, + category: "people" + }, + woman_mechanic: { + keywords: [ "plumber", "woman", "human", "wrench" ], + "char": "\ud83d\udc69\u200d\ud83d\udd27", + fitzpatrick_scale: true, + category: "people" + }, + man_mechanic: { + keywords: [ "plumber", "man", "human", "wrench" ], + "char": "\ud83d\udc68\u200d\ud83d\udd27", + fitzpatrick_scale: true, + category: "people" + }, + woman_scientist: { + keywords: [ "biologist", "chemist", "engineer", "physicist", "woman", "human" ], + "char": "\ud83d\udc69\u200d\ud83d\udd2c", + fitzpatrick_scale: true, + category: "people" + }, + man_scientist: { + keywords: [ "biologist", "chemist", "engineer", "physicist", "man", "human" ], + "char": "\ud83d\udc68\u200d\ud83d\udd2c", + fitzpatrick_scale: true, + category: "people" + }, + woman_artist: { + keywords: [ "painter", "woman", "human" ], + "char": "\ud83d\udc69\u200d\ud83c\udfa8", + fitzpatrick_scale: true, + category: "people" + }, + man_artist: { + keywords: [ "painter", "man", "human" ], + "char": "\ud83d\udc68\u200d\ud83c\udfa8", + fitzpatrick_scale: true, + category: "people" + }, + woman_firefighter: { + keywords: [ "fireman", "woman", "human" ], + "char": "\ud83d\udc69\u200d\ud83d\ude92", + fitzpatrick_scale: true, + category: "people" + }, + man_firefighter: { + keywords: [ "fireman", "man", "human" ], + "char": "\ud83d\udc68\u200d\ud83d\ude92", + fitzpatrick_scale: true, + category: "people" + }, + woman_pilot: { + keywords: [ "aviator", "plane", "woman", "human" ], + "char": "\ud83d\udc69\u200d\u2708\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + man_pilot: { + keywords: [ "aviator", "plane", "man", "human" ], + "char": "\ud83d\udc68\u200d\u2708\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + woman_astronaut: { + keywords: [ "space", "rocket", "woman", "human" ], + "char": "\ud83d\udc69\u200d\ud83d\ude80", + fitzpatrick_scale: true, + category: "people" + }, + man_astronaut: { + keywords: [ "space", "rocket", "man", "human" ], + "char": "\ud83d\udc68\u200d\ud83d\ude80", + fitzpatrick_scale: true, + category: "people" + }, + woman_judge: { + keywords: [ "justice", "court", "woman", "human" ], + "char": "\ud83d\udc69\u200d\u2696\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + man_judge: { + keywords: [ "justice", "court", "man", "human" ], + "char": "\ud83d\udc68\u200d\u2696\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + woman_superhero: { + keywords: [ "woman", "female", "good", "heroine", "superpowers" ], + "char": "\ud83e\uddb8\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + man_superhero: { + keywords: [ "man", "male", "good", "hero", "superpowers" ], + "char": "\ud83e\uddb8\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + woman_supervillain: { + keywords: [ "woman", "female", "evil", "bad", "criminal", "heroine", "superpowers" ], + "char": "\ud83e\uddb9\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + man_supervillain: { + keywords: [ "man", "male", "evil", "bad", "criminal", "hero", "superpowers" ], + "char": "\ud83e\uddb9\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + mrs_claus: { + keywords: [ "woman", "female", "xmas", "mother christmas" ], + "char": "\ud83e\udd36", + fitzpatrick_scale: true, + category: "people" + }, + santa: { + keywords: [ "festival", "man", "male", "xmas", "father christmas" ], + "char": "\ud83c\udf85", + fitzpatrick_scale: true, + category: "people" + }, + sorceress: { + keywords: [ "woman", "female", "mage", "witch" ], + "char": "\ud83e\uddd9\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + wizard: { + keywords: [ "man", "male", "mage", "sorcerer" ], + "char": "\ud83e\uddd9\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + woman_elf: { + keywords: [ "woman", "female" ], + "char": "\ud83e\udddd\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + man_elf: { + keywords: [ "man", "male" ], + "char": "\ud83e\udddd\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + woman_vampire: { + keywords: [ "woman", "female" ], + "char": "\ud83e\udddb\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + man_vampire: { + keywords: [ "man", "male", "dracula" ], + "char": "\ud83e\udddb\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + woman_zombie: { + keywords: [ "woman", "female", "undead", "walking dead" ], + "char": "\ud83e\udddf\u200d\u2640\ufe0f", + fitzpatrick_scale: false, + category: "people" + }, + man_zombie: { + keywords: [ "man", "male", "dracula", "undead", "walking dead" ], + "char": "\ud83e\udddf\u200d\u2642\ufe0f", + fitzpatrick_scale: false, + category: "people" + }, + woman_genie: { + keywords: [ "woman", "female" ], + "char": "\ud83e\uddde\u200d\u2640\ufe0f", + fitzpatrick_scale: false, + category: "people" + }, + man_genie: { + keywords: [ "man", "male" ], + "char": "\ud83e\uddde\u200d\u2642\ufe0f", + fitzpatrick_scale: false, + category: "people" + }, + mermaid: { + keywords: [ "woman", "female", "merwoman", "ariel" ], + "char": "\ud83e\udddc\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + merman: { + keywords: [ "man", "male", "triton" ], + "char": "\ud83e\udddc\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + woman_fairy: { + keywords: [ "woman", "female" ], + "char": "\ud83e\uddda\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + man_fairy: { + keywords: [ "man", "male" ], + "char": "\ud83e\uddda\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + angel: { + keywords: [ "heaven", "wings", "halo" ], + "char": "\ud83d\udc7c", + fitzpatrick_scale: true, + category: "people" + }, + pregnant_woman: { + keywords: [ "baby" ], + "char": "\ud83e\udd30", + fitzpatrick_scale: true, + category: "people" + }, + breastfeeding: { + keywords: [ "nursing", "baby" ], + "char": "\ud83e\udd31", + fitzpatrick_scale: true, + category: "people" + }, + princess: { + keywords: [ "girl", "woman", "female", "blond", "crown", "royal", "queen" ], + "char": "\ud83d\udc78", + fitzpatrick_scale: true, + category: "people" + }, + prince: { + keywords: [ "boy", "man", "male", "crown", "royal", "king" ], + "char": "\ud83e\udd34", + fitzpatrick_scale: true, + category: "people" + }, + bride_with_veil: { + keywords: [ "couple", "marriage", "wedding", "woman", "bride" ], + "char": "\ud83d\udc70", + fitzpatrick_scale: true, + category: "people" + }, + man_in_tuxedo: { + keywords: [ "couple", "marriage", "wedding", "groom" ], + "char": "\ud83e\udd35", + fitzpatrick_scale: true, + category: "people" + }, + running_woman: { + keywords: [ "woman", "walking", "exercise", "race", "running", "female" ], + "char": "\ud83c\udfc3\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + running_man: { + keywords: [ "man", "walking", "exercise", "race", "running" ], + "char": "\ud83c\udfc3", + fitzpatrick_scale: true, + category: "people" + }, + walking_woman: { + keywords: [ "human", "feet", "steps", "woman", "female" ], + "char": "\ud83d\udeb6\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + walking_man: { + keywords: [ "human", "feet", "steps" ], + "char": "\ud83d\udeb6", + fitzpatrick_scale: true, + category: "people" + }, + dancer: { + keywords: [ "female", "girl", "woman", "fun" ], + "char": "\ud83d\udc83", + fitzpatrick_scale: true, + category: "people" + }, + man_dancing: { + keywords: [ "male", "boy", "fun", "dancer" ], + "char": "\ud83d\udd7a", + fitzpatrick_scale: true, + category: "people" + }, + dancing_women: { + keywords: [ "female", "bunny", "women", "girls" ], + "char": "\ud83d\udc6f", + fitzpatrick_scale: false, + category: "people" + }, + dancing_men: { + keywords: [ "male", "bunny", "men", "boys" ], + "char": "\ud83d\udc6f\u200d\u2642\ufe0f", + fitzpatrick_scale: false, + category: "people" + }, + couple: { + keywords: [ "pair", "people", "human", "love", "date", "dating", "like", "affection", "valentines", "marriage" ], + "char": "\ud83d\udc6b", + fitzpatrick_scale: false, + category: "people" + }, + two_men_holding_hands: { + keywords: [ "pair", "couple", "love", "like", "bromance", "friendship", "people", "human" ], + "char": "\ud83d\udc6c", + fitzpatrick_scale: false, + category: "people" + }, + two_women_holding_hands: { + keywords: [ "pair", "friendship", "couple", "love", "like", "female", "people", "human" ], + "char": "\ud83d\udc6d", + fitzpatrick_scale: false, + category: "people" + }, + bowing_woman: { + keywords: [ "woman", "female", "girl" ], + "char": "\ud83d\ude47\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + bowing_man: { + keywords: [ "man", "male", "boy" ], + "char": "\ud83d\ude47", + fitzpatrick_scale: true, + category: "people" + }, + man_facepalming: { + keywords: [ "man", "male", "boy", "disbelief" ], + "char": "\ud83e\udd26\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + woman_facepalming: { + keywords: [ "woman", "female", "girl", "disbelief" ], + "char": "\ud83e\udd26\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + woman_shrugging: { + keywords: [ "woman", "female", "girl", "confused", "indifferent", "doubt" ], + "char": "\ud83e\udd37", + fitzpatrick_scale: true, + category: "people" + }, + man_shrugging: { + keywords: [ "man", "male", "boy", "confused", "indifferent", "doubt" ], + "char": "\ud83e\udd37\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + tipping_hand_woman: { + keywords: [ "female", "girl", "woman", "human", "information" ], + "char": "\ud83d\udc81", + fitzpatrick_scale: true, + category: "people" + }, + tipping_hand_man: { + keywords: [ "male", "boy", "man", "human", "information" ], + "char": "\ud83d\udc81\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + no_good_woman: { + keywords: [ "female", "girl", "woman", "nope" ], + "char": "\ud83d\ude45", + fitzpatrick_scale: true, + category: "people" + }, + no_good_man: { + keywords: [ "male", "boy", "man", "nope" ], + "char": "\ud83d\ude45\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + ok_woman: { + keywords: [ "women", "girl", "female", "pink", "human", "woman" ], + "char": "\ud83d\ude46", + fitzpatrick_scale: true, + category: "people" + }, + ok_man: { + keywords: [ "men", "boy", "male", "blue", "human", "man" ], + "char": "\ud83d\ude46\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + raising_hand_woman: { + keywords: [ "female", "girl", "woman" ], + "char": "\ud83d\ude4b", + fitzpatrick_scale: true, + category: "people" + }, + raising_hand_man: { + keywords: [ "male", "boy", "man" ], + "char": "\ud83d\ude4b\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + pouting_woman: { + keywords: [ "female", "girl", "woman" ], + "char": "\ud83d\ude4e", + fitzpatrick_scale: true, + category: "people" + }, + pouting_man: { + keywords: [ "male", "boy", "man" ], + "char": "\ud83d\ude4e\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + frowning_woman: { + keywords: [ "female", "girl", "woman", "sad", "depressed", "discouraged", "unhappy" ], + "char": "\ud83d\ude4d", + fitzpatrick_scale: true, + category: "people" + }, + frowning_man: { + keywords: [ "male", "boy", "man", "sad", "depressed", "discouraged", "unhappy" ], + "char": "\ud83d\ude4d\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + haircut_woman: { + keywords: [ "female", "girl", "woman" ], + "char": "\ud83d\udc87", + fitzpatrick_scale: true, + category: "people" + }, + haircut_man: { + keywords: [ "male", "boy", "man" ], + "char": "\ud83d\udc87\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + massage_woman: { + keywords: [ "female", "girl", "woman", "head" ], + "char": "\ud83d\udc86", + fitzpatrick_scale: true, + category: "people" + }, + massage_man: { + keywords: [ "male", "boy", "man", "head" ], + "char": "\ud83d\udc86\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + woman_in_steamy_room: { + keywords: [ "female", "woman", "spa", "steamroom", "sauna" ], + "char": "\ud83e\uddd6\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + man_in_steamy_room: { + keywords: [ "male", "man", "spa", "steamroom", "sauna" ], + "char": "\ud83e\uddd6\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "people" + }, + couple_with_heart_woman_man: { + keywords: [ "pair", "love", "like", "affection", "human", "dating", "valentines", "marriage" ], + "char": "\ud83d\udc91", + fitzpatrick_scale: false, + category: "people" + }, + couple_with_heart_woman_woman: { + keywords: [ "pair", "love", "like", "affection", "human", "dating", "valentines", "marriage" ], + "char": "\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc69", + fitzpatrick_scale: false, + category: "people" + }, + couple_with_heart_man_man: { + keywords: [ "pair", "love", "like", "affection", "human", "dating", "valentines", "marriage" ], + "char": "\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68", + fitzpatrick_scale: false, + category: "people" + }, + couplekiss_man_woman: { + keywords: [ "pair", "valentines", "love", "like", "dating", "marriage" ], + "char": "\ud83d\udc8f", + fitzpatrick_scale: false, + category: "people" + }, + couplekiss_woman_woman: { + keywords: [ "pair", "valentines", "love", "like", "dating", "marriage" ], + "char": "\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69", + fitzpatrick_scale: false, + category: "people" + }, + couplekiss_man_man: { + keywords: [ "pair", "valentines", "love", "like", "dating", "marriage" ], + "char": "\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68", + fitzpatrick_scale: false, + category: "people" + }, + family_man_woman_boy: { + keywords: [ "home", "parents", "child", "mom", "dad", "father", "mother", "people", "human" ], + "char": "\ud83d\udc6a", + fitzpatrick_scale: false, + category: "people" + }, + family_man_woman_girl: { + keywords: [ "home", "parents", "people", "human", "child" ], + "char": "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67", + fitzpatrick_scale: false, + category: "people" + }, + family_man_woman_girl_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_man_woman_boy_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_man_woman_girl_girl: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67", + fitzpatrick_scale: false, + category: "people" + }, + family_woman_woman_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_woman_woman_girl: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67", + fitzpatrick_scale: false, + category: "people" + }, + family_woman_woman_girl_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_woman_woman_boy_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_woman_woman_girl_girl: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67", + fitzpatrick_scale: false, + category: "people" + }, + family_man_man_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_man_man_girl: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67", + fitzpatrick_scale: false, + category: "people" + }, + family_man_man_girl_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_man_man_boy_boy: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_man_man_girl_girl: { + keywords: [ "home", "parents", "people", "human", "children" ], + "char": "\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67", + fitzpatrick_scale: false, + category: "people" + }, + family_woman_boy: { + keywords: [ "home", "parent", "people", "human", "child" ], + "char": "\ud83d\udc69\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_woman_girl: { + keywords: [ "home", "parent", "people", "human", "child" ], + "char": "\ud83d\udc69\u200d\ud83d\udc67", + fitzpatrick_scale: false, + category: "people" + }, + family_woman_girl_boy: { + keywords: [ "home", "parent", "people", "human", "children" ], + "char": "\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_woman_boy_boy: { + keywords: [ "home", "parent", "people", "human", "children" ], + "char": "\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_woman_girl_girl: { + keywords: [ "home", "parent", "people", "human", "children" ], + "char": "\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67", + fitzpatrick_scale: false, + category: "people" + }, + family_man_boy: { + keywords: [ "home", "parent", "people", "human", "child" ], + "char": "\ud83d\udc68\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_man_girl: { + keywords: [ "home", "parent", "people", "human", "child" ], + "char": "\ud83d\udc68\u200d\ud83d\udc67", + fitzpatrick_scale: false, + category: "people" + }, + family_man_girl_boy: { + keywords: [ "home", "parent", "people", "human", "children" ], + "char": "\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_man_boy_boy: { + keywords: [ "home", "parent", "people", "human", "children" ], + "char": "\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66", + fitzpatrick_scale: false, + category: "people" + }, + family_man_girl_girl: { + keywords: [ "home", "parent", "people", "human", "children" ], + "char": "\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67", + fitzpatrick_scale: false, + category: "people" + }, + yarn: { + keywords: [ "ball", "crochet", "knit" ], + "char": "\ud83e\uddf6", + fitzpatrick_scale: false, + category: "people" + }, + thread: { + keywords: [ "needle", "sewing", "spool", "string" ], + "char": "\ud83e\uddf5", + fitzpatrick_scale: false, + category: "people" + }, + coat: { + keywords: [ "jacket" ], + "char": "\ud83e\udde5", + fitzpatrick_scale: false, + category: "people" + }, + labcoat: { + keywords: [ "doctor", "experiment", "scientist", "chemist" ], + "char": "\ud83e\udd7c", + fitzpatrick_scale: false, + category: "people" + }, + womans_clothes: { + keywords: [ "fashion", "shopping_bags", "female" ], + "char": "\ud83d\udc5a", + fitzpatrick_scale: false, + category: "people" + }, + tshirt: { + keywords: [ "fashion", "cloth", "casual", "shirt", "tee" ], + "char": "\ud83d\udc55", + fitzpatrick_scale: false, + category: "people" + }, + jeans: { + keywords: [ "fashion", "shopping" ], + "char": "\ud83d\udc56", + fitzpatrick_scale: false, + category: "people" + }, + necktie: { + keywords: [ "shirt", "suitup", "formal", "fashion", "cloth", "business" ], + "char": "\ud83d\udc54", + fitzpatrick_scale: false, + category: "people" + }, + dress: { + keywords: [ "clothes", "fashion", "shopping" ], + "char": "\ud83d\udc57", + fitzpatrick_scale: false, + category: "people" + }, + bikini: { + keywords: [ "swimming", "female", "woman", "girl", "fashion", "beach", "summer" ], + "char": "\ud83d\udc59", + fitzpatrick_scale: false, + category: "people" + }, + kimono: { + keywords: [ "dress", "fashion", "women", "female", "japanese" ], + "char": "\ud83d\udc58", + fitzpatrick_scale: false, + category: "people" + }, + lipstick: { + keywords: [ "female", "girl", "fashion", "woman" ], + "char": "\ud83d\udc84", + fitzpatrick_scale: false, + category: "people" + }, + kiss: { + keywords: [ "face", "lips", "love", "like", "affection", "valentines" ], + "char": "\ud83d\udc8b", + fitzpatrick_scale: false, + category: "people" + }, + footprints: { + keywords: [ "feet", "tracking", "walking", "beach" ], + "char": "\ud83d\udc63", + fitzpatrick_scale: false, + category: "people" + }, + flat_shoe: { + keywords: [ "ballet", "slip-on", "slipper" ], + "char": "\ud83e\udd7f", + fitzpatrick_scale: false, + category: "people" + }, + high_heel: { + keywords: [ "fashion", "shoes", "female", "pumps", "stiletto" ], + "char": "\ud83d\udc60", + fitzpatrick_scale: false, + category: "people" + }, + sandal: { + keywords: [ "shoes", "fashion", "flip flops" ], + "char": "\ud83d\udc61", + fitzpatrick_scale: false, + category: "people" + }, + boot: { + keywords: [ "shoes", "fashion" ], + "char": "\ud83d\udc62", + fitzpatrick_scale: false, + category: "people" + }, + mans_shoe: { + keywords: [ "fashion", "male" ], + "char": "\ud83d\udc5e", + fitzpatrick_scale: false, + category: "people" + }, + athletic_shoe: { + keywords: [ "shoes", "sports", "sneakers" ], + "char": "\ud83d\udc5f", + fitzpatrick_scale: false, + category: "people" + }, + hiking_boot: { + keywords: [ "backpacking", "camping", "hiking" ], + "char": "\ud83e\udd7e", + fitzpatrick_scale: false, + category: "people" + }, + socks: { + keywords: [ "stockings", "clothes" ], + "char": "\ud83e\udde6", + fitzpatrick_scale: false, + category: "people" + }, + gloves: { + keywords: [ "hands", "winter", "clothes" ], + "char": "\ud83e\udde4", + fitzpatrick_scale: false, + category: "people" + }, + scarf: { + keywords: [ "neck", "winter", "clothes" ], + "char": "\ud83e\udde3", + fitzpatrick_scale: false, + category: "people" + }, + womans_hat: { + keywords: [ "fashion", "accessories", "female", "lady", "spring" ], + "char": "\ud83d\udc52", + fitzpatrick_scale: false, + category: "people" + }, + tophat: { + keywords: [ "magic", "gentleman", "classy", "circus" ], + "char": "\ud83c\udfa9", + fitzpatrick_scale: false, + category: "people" + }, + billed_hat: { + keywords: [ "cap", "baseball" ], + "char": "\ud83e\udde2", + fitzpatrick_scale: false, + category: "people" + }, + rescue_worker_helmet: { + keywords: [ "construction", "build" ], + "char": "\u26d1", + fitzpatrick_scale: false, + category: "people" + }, + mortar_board: { + keywords: [ "school", "college", "degree", "university", "graduation", "cap", "hat", "legal", "learn", "education" ], + "char": "\ud83c\udf93", + fitzpatrick_scale: false, + category: "people" + }, + crown: { + keywords: [ "king", "kod", "leader", "royalty", "lord" ], + "char": "\ud83d\udc51", + fitzpatrick_scale: false, + category: "people" + }, + school_satchel: { + keywords: [ "student", "education", "bag", "backpack" ], + "char": "\ud83c\udf92", + fitzpatrick_scale: false, + category: "people" + }, + luggage: { + keywords: [ "packing", "travel" ], + "char": "\ud83e\uddf3", + fitzpatrick_scale: false, + category: "people" + }, + pouch: { + keywords: [ "bag", "accessories", "shopping" ], + "char": "\ud83d\udc5d", + fitzpatrick_scale: false, + category: "people" + }, + purse: { + keywords: [ "fashion", "accessories", "money", "sales", "shopping" ], + "char": "\ud83d\udc5b", + fitzpatrick_scale: false, + category: "people" + }, + handbag: { + keywords: [ "fashion", "accessory", "accessories", "shopping" ], + "char": "\ud83d\udc5c", + fitzpatrick_scale: false, + category: "people" + }, + briefcase: { + keywords: [ "business", "documents", "work", "law", "legal", "job", "career" ], + "char": "\ud83d\udcbc", + fitzpatrick_scale: false, + category: "people" + }, + eyeglasses: { + keywords: [ "fashion", "accessories", "eyesight", "nerdy", "dork", "geek" ], + "char": "\ud83d\udc53", + fitzpatrick_scale: false, + category: "people" + }, + dark_sunglasses: { + keywords: [ "face", "cool", "accessories" ], + "char": "\ud83d\udd76", + fitzpatrick_scale: false, + category: "people" + }, + goggles: { + keywords: [ "eyes", "protection", "safety" ], + "char": "\ud83e\udd7d", + fitzpatrick_scale: false, + category: "people" + }, + ring: { + keywords: [ "wedding", "propose", "marriage", "valentines", "diamond", "fashion", "jewelry", "gem", "engagement" ], + "char": "\ud83d\udc8d", + fitzpatrick_scale: false, + category: "people" + }, + closed_umbrella: { + keywords: [ "weather", "rain", "drizzle" ], + "char": "\ud83c\udf02", + fitzpatrick_scale: false, + category: "people" + }, + dog: { + keywords: [ "animal", "friend", "nature", "woof", "puppy", "pet", "faithful" ], + "char": "\ud83d\udc36", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cat: { + keywords: [ "animal", "meow", "nature", "pet", "kitten" ], + "char": "\ud83d\udc31", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + mouse: { + keywords: [ "animal", "nature", "cheese_wedge", "rodent" ], + "char": "\ud83d\udc2d", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hamster: { + keywords: [ "animal", "nature" ], + "char": "\ud83d\udc39", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + rabbit: { + keywords: [ "animal", "nature", "pet", "spring", "magic", "bunny" ], + "char": "\ud83d\udc30", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + fox_face: { + keywords: [ "animal", "nature", "face" ], + "char": "\ud83e\udd8a", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + bear: { + keywords: [ "animal", "nature", "wild" ], + "char": "\ud83d\udc3b", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + panda_face: { + keywords: [ "animal", "nature", "panda" ], + "char": "\ud83d\udc3c", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + koala: { + keywords: [ "animal", "nature" ], + "char": "\ud83d\udc28", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + tiger: { + keywords: [ "animal", "cat", "danger", "wild", "nature", "roar" ], + "char": "\ud83d\udc2f", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + lion: { + keywords: [ "animal", "nature" ], + "char": "\ud83e\udd81", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cow: { + keywords: [ "beef", "ox", "animal", "nature", "moo", "milk" ], + "char": "\ud83d\udc2e", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + pig: { + keywords: [ "animal", "oink", "nature" ], + "char": "\ud83d\udc37", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + pig_nose: { + keywords: [ "animal", "oink" ], + "char": "\ud83d\udc3d", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + frog: { + keywords: [ "animal", "nature", "croak", "toad" ], + "char": "\ud83d\udc38", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + squid: { + keywords: [ "animal", "nature", "ocean", "sea" ], + "char": "\ud83e\udd91", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + octopus: { + keywords: [ "animal", "creature", "ocean", "sea", "nature", "beach" ], + "char": "\ud83d\udc19", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + shrimp: { + keywords: [ "animal", "ocean", "nature", "seafood" ], + "char": "\ud83e\udd90", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + monkey_face: { + keywords: [ "animal", "nature", "circus" ], + "char": "\ud83d\udc35", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + gorilla: { + keywords: [ "animal", "nature", "circus" ], + "char": "\ud83e\udd8d", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + see_no_evil: { + keywords: [ "monkey", "animal", "nature", "haha" ], + "char": "\ud83d\ude48", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hear_no_evil: { + keywords: [ "animal", "monkey", "nature" ], + "char": "\ud83d\ude49", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + speak_no_evil: { + keywords: [ "monkey", "animal", "nature", "omg" ], + "char": "\ud83d\ude4a", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + monkey: { + keywords: [ "animal", "nature", "banana", "circus" ], + "char": "\ud83d\udc12", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + chicken: { + keywords: [ "animal", "cluck", "nature", "bird" ], + "char": "\ud83d\udc14", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + penguin: { + keywords: [ "animal", "nature" ], + "char": "\ud83d\udc27", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + bird: { + keywords: [ "animal", "nature", "fly", "tweet", "spring" ], + "char": "\ud83d\udc26", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + baby_chick: { + keywords: [ "animal", "chicken", "bird" ], + "char": "\ud83d\udc24", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hatching_chick: { + keywords: [ "animal", "chicken", "egg", "born", "baby", "bird" ], + "char": "\ud83d\udc23", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hatched_chick: { + keywords: [ "animal", "chicken", "baby", "bird" ], + "char": "\ud83d\udc25", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + duck: { + keywords: [ "animal", "nature", "bird", "mallard" ], + "char": "\ud83e\udd86", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + eagle: { + keywords: [ "animal", "nature", "bird" ], + "char": "\ud83e\udd85", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + owl: { + keywords: [ "animal", "nature", "bird", "hoot" ], + "char": "\ud83e\udd89", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + bat: { + keywords: [ "animal", "nature", "blind", "vampire" ], + "char": "\ud83e\udd87", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + wolf: { + keywords: [ "animal", "nature", "wild" ], + "char": "\ud83d\udc3a", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + boar: { + keywords: [ "animal", "nature" ], + "char": "\ud83d\udc17", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + horse: { + keywords: [ "animal", "brown", "nature" ], + "char": "\ud83d\udc34", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + unicorn: { + keywords: [ "animal", "nature", "mystical" ], + "char": "\ud83e\udd84", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + honeybee: { + keywords: [ "animal", "insect", "nature", "bug", "spring", "honey" ], + "char": "\ud83d\udc1d", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + bug: { + keywords: [ "animal", "insect", "nature", "worm" ], + "char": "\ud83d\udc1b", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + butterfly: { + keywords: [ "animal", "insect", "nature", "caterpillar" ], + "char": "\ud83e\udd8b", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + snail: { + keywords: [ "slow", "animal", "shell" ], + "char": "\ud83d\udc0c", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + beetle: { + keywords: [ "animal", "insect", "nature", "ladybug" ], + "char": "\ud83d\udc1e", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + ant: { + keywords: [ "animal", "insect", "nature", "bug" ], + "char": "\ud83d\udc1c", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + grasshopper: { + keywords: [ "animal", "cricket", "chirp" ], + "char": "\ud83e\udd97", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + spider: { + keywords: [ "animal", "arachnid" ], + "char": "\ud83d\udd77", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + scorpion: { + keywords: [ "animal", "arachnid" ], + "char": "\ud83e\udd82", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + crab: { + keywords: [ "animal", "crustacean" ], + "char": "\ud83e\udd80", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + snake: { + keywords: [ "animal", "evil", "nature", "hiss", "python" ], + "char": "\ud83d\udc0d", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + lizard: { + keywords: [ "animal", "nature", "reptile" ], + "char": "\ud83e\udd8e", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + "t-rex": { + keywords: [ "animal", "nature", "dinosaur", "tyrannosaurus", "extinct" ], + "char": "\ud83e\udd96", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sauropod: { + keywords: [ "animal", "nature", "dinosaur", "brachiosaurus", "brontosaurus", "diplodocus", "extinct" ], + "char": "\ud83e\udd95", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + turtle: { + keywords: [ "animal", "slow", "nature", "tortoise" ], + "char": "\ud83d\udc22", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + tropical_fish: { + keywords: [ "animal", "swim", "ocean", "beach", "nemo" ], + "char": "\ud83d\udc20", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + fish: { + keywords: [ "animal", "food", "nature" ], + "char": "\ud83d\udc1f", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + blowfish: { + keywords: [ "animal", "nature", "food", "sea", "ocean" ], + "char": "\ud83d\udc21", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dolphin: { + keywords: [ "animal", "nature", "fish", "sea", "ocean", "flipper", "fins", "beach" ], + "char": "\ud83d\udc2c", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + shark: { + keywords: [ "animal", "nature", "fish", "sea", "ocean", "jaws", "fins", "beach" ], + "char": "\ud83e\udd88", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + whale: { + keywords: [ "animal", "nature", "sea", "ocean" ], + "char": "\ud83d\udc33", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + whale2: { + keywords: [ "animal", "nature", "sea", "ocean" ], + "char": "\ud83d\udc0b", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + crocodile: { + keywords: [ "animal", "nature", "reptile", "lizard", "alligator" ], + "char": "\ud83d\udc0a", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + leopard: { + keywords: [ "animal", "nature" ], + "char": "\ud83d\udc06", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + zebra: { + keywords: [ "animal", "nature", "stripes", "safari" ], + "char": "\ud83e\udd93", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + tiger2: { + keywords: [ "animal", "nature", "roar" ], + "char": "\ud83d\udc05", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + water_buffalo: { + keywords: [ "animal", "nature", "ox", "cow" ], + "char": "\ud83d\udc03", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + ox: { + keywords: [ "animal", "cow", "beef" ], + "char": "\ud83d\udc02", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cow2: { + keywords: [ "beef", "ox", "animal", "nature", "moo", "milk" ], + "char": "\ud83d\udc04", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + deer: { + keywords: [ "animal", "nature", "horns", "venison" ], + "char": "\ud83e\udd8c", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dromedary_camel: { + keywords: [ "animal", "hot", "desert", "hump" ], + "char": "\ud83d\udc2a", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + camel: { + keywords: [ "animal", "nature", "hot", "desert", "hump" ], + "char": "\ud83d\udc2b", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + giraffe: { + keywords: [ "animal", "nature", "spots", "safari" ], + "char": "\ud83e\udd92", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + elephant: { + keywords: [ "animal", "nature", "nose", "th", "circus" ], + "char": "\ud83d\udc18", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + rhinoceros: { + keywords: [ "animal", "nature", "horn" ], + "char": "\ud83e\udd8f", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + goat: { + keywords: [ "animal", "nature" ], + "char": "\ud83d\udc10", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + ram: { + keywords: [ "animal", "sheep", "nature" ], + "char": "\ud83d\udc0f", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sheep: { + keywords: [ "animal", "nature", "wool", "shipit" ], + "char": "\ud83d\udc11", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + racehorse: { + keywords: [ "animal", "gamble", "luck" ], + "char": "\ud83d\udc0e", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + pig2: { + keywords: [ "animal", "nature" ], + "char": "\ud83d\udc16", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + rat: { + keywords: [ "animal", "mouse", "rodent" ], + "char": "\ud83d\udc00", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + mouse2: { + keywords: [ "animal", "nature", "rodent" ], + "char": "\ud83d\udc01", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + rooster: { + keywords: [ "animal", "nature", "chicken" ], + "char": "\ud83d\udc13", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + turkey: { + keywords: [ "animal", "bird" ], + "char": "\ud83e\udd83", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dove: { + keywords: [ "animal", "bird" ], + "char": "\ud83d\udd4a", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dog2: { + keywords: [ "animal", "nature", "friend", "doge", "pet", "faithful" ], + "char": "\ud83d\udc15", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + poodle: { + keywords: [ "dog", "animal", "101", "nature", "pet" ], + "char": "\ud83d\udc29", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cat2: { + keywords: [ "animal", "meow", "pet", "cats" ], + "char": "\ud83d\udc08", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + rabbit2: { + keywords: [ "animal", "nature", "pet", "magic", "spring" ], + "char": "\ud83d\udc07", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + chipmunk: { + keywords: [ "animal", "nature", "rodent", "squirrel" ], + "char": "\ud83d\udc3f", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hedgehog: { + keywords: [ "animal", "nature", "spiny" ], + "char": "\ud83e\udd94", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + raccoon: { + keywords: [ "animal", "nature" ], + "char": "\ud83e\udd9d", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + llama: { + keywords: [ "animal", "nature", "alpaca" ], + "char": "\ud83e\udd99", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hippopotamus: { + keywords: [ "animal", "nature" ], + "char": "\ud83e\udd9b", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + kangaroo: { + keywords: [ "animal", "nature", "australia", "joey", "hop", "marsupial" ], + "char": "\ud83e\udd98", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + badger: { + keywords: [ "animal", "nature", "honey" ], + "char": "\ud83e\udda1", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + swan: { + keywords: [ "animal", "nature", "bird" ], + "char": "\ud83e\udda2", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + peacock: { + keywords: [ "animal", "nature", "peahen", "bird" ], + "char": "\ud83e\udd9a", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + parrot: { + keywords: [ "animal", "nature", "bird", "pirate", "talk" ], + "char": "\ud83e\udd9c", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + lobster: { + keywords: [ "animal", "nature", "bisque", "claws", "seafood" ], + "char": "\ud83e\udd9e", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + mosquito: { + keywords: [ "animal", "nature", "insect", "malaria" ], + "char": "\ud83e\udd9f", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + paw_prints: { + keywords: [ "animal", "tracking", "footprints", "dog", "cat", "pet", "feet" ], + "char": "\ud83d\udc3e", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dragon: { + keywords: [ "animal", "myth", "nature", "chinese", "green" ], + "char": "\ud83d\udc09", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dragon_face: { + keywords: [ "animal", "myth", "nature", "chinese", "green" ], + "char": "\ud83d\udc32", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cactus: { + keywords: [ "vegetable", "plant", "nature" ], + "char": "\ud83c\udf35", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + christmas_tree: { + keywords: [ "festival", "vacation", "december", "xmas", "celebration" ], + "char": "\ud83c\udf84", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + evergreen_tree: { + keywords: [ "plant", "nature" ], + "char": "\ud83c\udf32", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + deciduous_tree: { + keywords: [ "plant", "nature" ], + "char": "\ud83c\udf33", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + palm_tree: { + keywords: [ "plant", "vegetable", "nature", "summer", "beach", "mojito", "tropical" ], + "char": "\ud83c\udf34", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + seedling: { + keywords: [ "plant", "nature", "grass", "lawn", "spring" ], + "char": "\ud83c\udf31", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + herb: { + keywords: [ "vegetable", "plant", "medicine", "weed", "grass", "lawn" ], + "char": "\ud83c\udf3f", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + shamrock: { + keywords: [ "vegetable", "plant", "nature", "irish", "clover" ], + "char": "\u2618", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + four_leaf_clover: { + keywords: [ "vegetable", "plant", "nature", "lucky", "irish" ], + "char": "\ud83c\udf40", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + bamboo: { + keywords: [ "plant", "nature", "vegetable", "panda", "pine_decoration" ], + "char": "\ud83c\udf8d", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + tanabata_tree: { + keywords: [ "plant", "nature", "branch", "summer" ], + "char": "\ud83c\udf8b", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + leaves: { + keywords: [ "nature", "plant", "tree", "vegetable", "grass", "lawn", "spring" ], + "char": "\ud83c\udf43", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + fallen_leaf: { + keywords: [ "nature", "plant", "vegetable", "leaves" ], + "char": "\ud83c\udf42", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + maple_leaf: { + keywords: [ "nature", "plant", "vegetable", "ca", "fall" ], + "char": "\ud83c\udf41", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + ear_of_rice: { + keywords: [ "nature", "plant" ], + "char": "\ud83c\udf3e", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + hibiscus: { + keywords: [ "plant", "vegetable", "flowers", "beach" ], + "char": "\ud83c\udf3a", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sunflower: { + keywords: [ "nature", "plant", "fall" ], + "char": "\ud83c\udf3b", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + rose: { + keywords: [ "flowers", "valentines", "love", "spring" ], + "char": "\ud83c\udf39", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + wilted_flower: { + keywords: [ "plant", "nature", "flower" ], + "char": "\ud83e\udd40", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + tulip: { + keywords: [ "flowers", "plant", "nature", "summer", "spring" ], + "char": "\ud83c\udf37", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + blossom: { + keywords: [ "nature", "flowers", "yellow" ], + "char": "\ud83c\udf3c", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cherry_blossom: { + keywords: [ "nature", "plant", "spring", "flower" ], + "char": "\ud83c\udf38", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + bouquet: { + keywords: [ "flowers", "nature", "spring" ], + "char": "\ud83d\udc90", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + mushroom: { + keywords: [ "plant", "vegetable" ], + "char": "\ud83c\udf44", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + chestnut: { + keywords: [ "food", "squirrel" ], + "char": "\ud83c\udf30", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + jack_o_lantern: { + keywords: [ "halloween", "light", "pumpkin", "creepy", "fall" ], + "char": "\ud83c\udf83", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + shell: { + keywords: [ "nature", "sea", "beach" ], + "char": "\ud83d\udc1a", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + spider_web: { + keywords: [ "animal", "insect", "arachnid", "silk" ], + "char": "\ud83d\udd78", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + earth_americas: { + keywords: [ "globe", "world", "USA", "international" ], + "char": "\ud83c\udf0e", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + earth_africa: { + keywords: [ "globe", "world", "international" ], + "char": "\ud83c\udf0d", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + earth_asia: { + keywords: [ "globe", "world", "east", "international" ], + "char": "\ud83c\udf0f", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + full_moon: { + keywords: [ "nature", "yellow", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": "\ud83c\udf15", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + waning_gibbous_moon: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep", "waxing_gibbous_moon" ], + "char": "\ud83c\udf16", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + last_quarter_moon: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": "\ud83c\udf17", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + waning_crescent_moon: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": "\ud83c\udf18", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + new_moon: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": "\ud83c\udf11", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + waxing_crescent_moon: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": "\ud83c\udf12", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + first_quarter_moon: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": "\ud83c\udf13", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + waxing_gibbous_moon: { + keywords: [ "nature", "night", "sky", "gray", "twilight", "planet", "space", "evening", "sleep" ], + "char": "\ud83c\udf14", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + new_moon_with_face: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": "\ud83c\udf1a", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + full_moon_with_face: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": "\ud83c\udf1d", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + first_quarter_moon_with_face: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": "\ud83c\udf1b", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + last_quarter_moon_with_face: { + keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ], + "char": "\ud83c\udf1c", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sun_with_face: { + keywords: [ "nature", "morning", "sky" ], + "char": "\ud83c\udf1e", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + crescent_moon: { + keywords: [ "night", "sleep", "sky", "evening", "magic" ], + "char": "\ud83c\udf19", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + star: { + keywords: [ "night", "yellow" ], + "char": "\u2b50", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + star2: { + keywords: [ "night", "sparkle", "awesome", "good", "magic" ], + "char": "\ud83c\udf1f", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dizzy: { + keywords: [ "star", "sparkle", "shoot", "magic" ], + "char": "\ud83d\udcab", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sparkles: { + keywords: [ "stars", "shine", "shiny", "cool", "awesome", "good", "magic" ], + "char": "\u2728", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + comet: { + keywords: [ "space" ], + "char": "\u2604", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sunny: { + keywords: [ "weather", "nature", "brightness", "summer", "beach", "spring" ], + "char": "\u2600\ufe0f", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sun_behind_small_cloud: { + keywords: [ "weather" ], + "char": "\ud83c\udf24", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + partly_sunny: { + keywords: [ "weather", "nature", "cloudy", "morning", "fall", "spring" ], + "char": "\u26c5", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sun_behind_large_cloud: { + keywords: [ "weather" ], + "char": "\ud83c\udf25", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sun_behind_rain_cloud: { + keywords: [ "weather" ], + "char": "\ud83c\udf26", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cloud: { + keywords: [ "weather", "sky" ], + "char": "\u2601\ufe0f", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cloud_with_rain: { + keywords: [ "weather" ], + "char": "\ud83c\udf27", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cloud_with_lightning_and_rain: { + keywords: [ "weather", "lightning" ], + "char": "\u26c8", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cloud_with_lightning: { + keywords: [ "weather", "thunder" ], + "char": "\ud83c\udf29", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + zap: { + keywords: [ "thunder", "weather", "lightning bolt", "fast" ], + "char": "\u26a1", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + fire: { + keywords: [ "hot", "cook", "flame" ], + "char": "\ud83d\udd25", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + boom: { + keywords: [ "bomb", "explode", "explosion", "collision", "blown" ], + "char": "\ud83d\udca5", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + snowflake: { + keywords: [ "winter", "season", "cold", "weather", "christmas", "xmas" ], + "char": "\u2744\ufe0f", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + cloud_with_snow: { + keywords: [ "weather" ], + "char": "\ud83c\udf28", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + snowman: { + keywords: [ "winter", "season", "cold", "weather", "christmas", "xmas", "frozen", "without_snow" ], + "char": "\u26c4", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + snowman_with_snow: { + keywords: [ "winter", "season", "cold", "weather", "christmas", "xmas", "frozen" ], + "char": "\u2603", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + wind_face: { + keywords: [ "gust", "air" ], + "char": "\ud83c\udf2c", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + dash: { + keywords: [ "wind", "air", "fast", "shoo", "fart", "smoke", "puff" ], + "char": "\ud83d\udca8", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + tornado: { + keywords: [ "weather", "cyclone", "twister" ], + "char": "\ud83c\udf2a", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + fog: { + keywords: [ "weather" ], + "char": "\ud83c\udf2b", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + open_umbrella: { + keywords: [ "weather", "spring" ], + "char": "\u2602", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + umbrella: { + keywords: [ "rainy", "weather", "spring" ], + "char": "\u2614", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + droplet: { + keywords: [ "water", "drip", "faucet", "spring" ], + "char": "\ud83d\udca7", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + sweat_drops: { + keywords: [ "water", "drip", "oops" ], + "char": "\ud83d\udca6", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + ocean: { + keywords: [ "sea", "water", "wave", "nature", "tsunami", "disaster" ], + "char": "\ud83c\udf0a", + fitzpatrick_scale: false, + category: "animals_and_nature" + }, + green_apple: { + keywords: [ "fruit", "nature" ], + "char": "\ud83c\udf4f", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + apple: { + keywords: [ "fruit", "mac", "school" ], + "char": "\ud83c\udf4e", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + pear: { + keywords: [ "fruit", "nature", "food" ], + "char": "\ud83c\udf50", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + tangerine: { + keywords: [ "food", "fruit", "nature", "orange" ], + "char": "\ud83c\udf4a", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + lemon: { + keywords: [ "fruit", "nature" ], + "char": "\ud83c\udf4b", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + banana: { + keywords: [ "fruit", "food", "monkey" ], + "char": "\ud83c\udf4c", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + watermelon: { + keywords: [ "fruit", "food", "picnic", "summer" ], + "char": "\ud83c\udf49", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + grapes: { + keywords: [ "fruit", "food", "wine" ], + "char": "\ud83c\udf47", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + strawberry: { + keywords: [ "fruit", "food", "nature" ], + "char": "\ud83c\udf53", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + melon: { + keywords: [ "fruit", "nature", "food" ], + "char": "\ud83c\udf48", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cherries: { + keywords: [ "food", "fruit" ], + "char": "\ud83c\udf52", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + peach: { + keywords: [ "fruit", "nature", "food" ], + "char": "\ud83c\udf51", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + pineapple: { + keywords: [ "fruit", "nature", "food" ], + "char": "\ud83c\udf4d", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + coconut: { + keywords: [ "fruit", "nature", "food", "palm" ], + "char": "\ud83e\udd65", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + kiwi_fruit: { + keywords: [ "fruit", "food" ], + "char": "\ud83e\udd5d", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + mango: { + keywords: [ "fruit", "food", "tropical" ], + "char": "\ud83e\udd6d", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + avocado: { + keywords: [ "fruit", "food" ], + "char": "\ud83e\udd51", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + broccoli: { + keywords: [ "fruit", "food", "vegetable" ], + "char": "\ud83e\udd66", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + tomato: { + keywords: [ "fruit", "vegetable", "nature", "food" ], + "char": "\ud83c\udf45", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + eggplant: { + keywords: [ "vegetable", "nature", "food", "aubergine" ], + "char": "\ud83c\udf46", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cucumber: { + keywords: [ "fruit", "food", "pickle" ], + "char": "\ud83e\udd52", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + carrot: { + keywords: [ "vegetable", "food", "orange" ], + "char": "\ud83e\udd55", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + hot_pepper: { + keywords: [ "food", "spicy", "chilli", "chili" ], + "char": "\ud83c\udf36", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + potato: { + keywords: [ "food", "tuber", "vegatable", "starch" ], + "char": "\ud83e\udd54", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + corn: { + keywords: [ "food", "vegetable", "plant" ], + "char": "\ud83c\udf3d", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + leafy_greens: { + keywords: [ "food", "vegetable", "plant", "bok choy", "cabbage", "kale", "lettuce" ], + "char": "\ud83e\udd6c", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + sweet_potato: { + keywords: [ "food", "nature" ], + "char": "\ud83c\udf60", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + peanuts: { + keywords: [ "food", "nut" ], + "char": "\ud83e\udd5c", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + honey_pot: { + keywords: [ "bees", "sweet", "kitchen" ], + "char": "\ud83c\udf6f", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + croissant: { + keywords: [ "food", "bread", "french" ], + "char": "\ud83e\udd50", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + bread: { + keywords: [ "food", "wheat", "breakfast", "toast" ], + "char": "\ud83c\udf5e", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + baguette_bread: { + keywords: [ "food", "bread", "french" ], + "char": "\ud83e\udd56", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + bagel: { + keywords: [ "food", "bread", "bakery", "schmear" ], + "char": "\ud83e\udd6f", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + pretzel: { + keywords: [ "food", "bread", "twisted" ], + "char": "\ud83e\udd68", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cheese: { + keywords: [ "food", "chadder" ], + "char": "\ud83e\uddc0", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + egg: { + keywords: [ "food", "chicken", "breakfast" ], + "char": "\ud83e\udd5a", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + bacon: { + keywords: [ "food", "breakfast", "pork", "pig", "meat" ], + "char": "\ud83e\udd53", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + steak: { + keywords: [ "food", "cow", "meat", "cut", "chop", "lambchop", "porkchop" ], + "char": "\ud83e\udd69", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + pancakes: { + keywords: [ "food", "breakfast", "flapjacks", "hotcakes" ], + "char": "\ud83e\udd5e", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + poultry_leg: { + keywords: [ "food", "meat", "drumstick", "bird", "chicken", "turkey" ], + "char": "\ud83c\udf57", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + meat_on_bone: { + keywords: [ "good", "food", "drumstick" ], + "char": "\ud83c\udf56", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + bone: { + keywords: [ "skeleton" ], + "char": "\ud83e\uddb4", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + fried_shrimp: { + keywords: [ "food", "animal", "appetizer", "summer" ], + "char": "\ud83c\udf64", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + fried_egg: { + keywords: [ "food", "breakfast", "kitchen", "egg" ], + "char": "\ud83c\udf73", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + hamburger: { + keywords: [ "meat", "fast food", "beef", "cheeseburger", "mcdonalds", "burger king" ], + "char": "\ud83c\udf54", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + fries: { + keywords: [ "chips", "snack", "fast food" ], + "char": "\ud83c\udf5f", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + stuffed_flatbread: { + keywords: [ "food", "flatbread", "stuffed", "gyro" ], + "char": "\ud83e\udd59", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + hotdog: { + keywords: [ "food", "frankfurter" ], + "char": "\ud83c\udf2d", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + pizza: { + keywords: [ "food", "party" ], + "char": "\ud83c\udf55", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + sandwich: { + keywords: [ "food", "lunch", "bread" ], + "char": "\ud83e\udd6a", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + canned_food: { + keywords: [ "food", "soup" ], + "char": "\ud83e\udd6b", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + spaghetti: { + keywords: [ "food", "italian", "noodle" ], + "char": "\ud83c\udf5d", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + taco: { + keywords: [ "food", "mexican" ], + "char": "\ud83c\udf2e", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + burrito: { + keywords: [ "food", "mexican" ], + "char": "\ud83c\udf2f", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + green_salad: { + keywords: [ "food", "healthy", "lettuce" ], + "char": "\ud83e\udd57", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + shallow_pan_of_food: { + keywords: [ "food", "cooking", "casserole", "paella" ], + "char": "\ud83e\udd58", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + ramen: { + keywords: [ "food", "japanese", "noodle", "chopsticks" ], + "char": "\ud83c\udf5c", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + stew: { + keywords: [ "food", "meat", "soup" ], + "char": "\ud83c\udf72", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + fish_cake: { + keywords: [ "food", "japan", "sea", "beach", "narutomaki", "pink", "swirl", "kamaboko", "surimi", "ramen" ], + "char": "\ud83c\udf65", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + fortune_cookie: { + keywords: [ "food", "prophecy" ], + "char": "\ud83e\udd60", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + sushi: { + keywords: [ "food", "fish", "japanese", "rice" ], + "char": "\ud83c\udf63", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + bento: { + keywords: [ "food", "japanese", "box" ], + "char": "\ud83c\udf71", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + curry: { + keywords: [ "food", "spicy", "hot", "indian" ], + "char": "\ud83c\udf5b", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + rice_ball: { + keywords: [ "food", "japanese" ], + "char": "\ud83c\udf59", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + rice: { + keywords: [ "food", "china", "asian" ], + "char": "\ud83c\udf5a", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + rice_cracker: { + keywords: [ "food", "japanese" ], + "char": "\ud83c\udf58", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + oden: { + keywords: [ "food", "japanese" ], + "char": "\ud83c\udf62", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + dango: { + keywords: [ "food", "dessert", "sweet", "japanese", "barbecue", "meat" ], + "char": "\ud83c\udf61", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + shaved_ice: { + keywords: [ "hot", "dessert", "summer" ], + "char": "\ud83c\udf67", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + ice_cream: { + keywords: [ "food", "hot", "dessert" ], + "char": "\ud83c\udf68", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + icecream: { + keywords: [ "food", "hot", "dessert", "summer" ], + "char": "\ud83c\udf66", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + pie: { + keywords: [ "food", "dessert", "pastry" ], + "char": "\ud83e\udd67", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cake: { + keywords: [ "food", "dessert" ], + "char": "\ud83c\udf70", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cupcake: { + keywords: [ "food", "dessert", "bakery", "sweet" ], + "char": "\ud83e\uddc1", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + moon_cake: { + keywords: [ "food", "autumn" ], + "char": "\ud83e\udd6e", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + birthday: { + keywords: [ "food", "dessert", "cake" ], + "char": "\ud83c\udf82", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + custard: { + keywords: [ "dessert", "food" ], + "char": "\ud83c\udf6e", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + candy: { + keywords: [ "snack", "dessert", "sweet", "lolly" ], + "char": "\ud83c\udf6c", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + lollipop: { + keywords: [ "food", "snack", "candy", "sweet" ], + "char": "\ud83c\udf6d", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + chocolate_bar: { + keywords: [ "food", "snack", "dessert", "sweet" ], + "char": "\ud83c\udf6b", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + popcorn: { + keywords: [ "food", "movie theater", "films", "snack" ], + "char": "\ud83c\udf7f", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + dumpling: { + keywords: [ "food", "empanada", "pierogi", "potsticker" ], + "char": "\ud83e\udd5f", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + doughnut: { + keywords: [ "food", "dessert", "snack", "sweet", "donut" ], + "char": "\ud83c\udf69", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cookie: { + keywords: [ "food", "snack", "oreo", "chocolate", "sweet", "dessert" ], + "char": "\ud83c\udf6a", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + milk_glass: { + keywords: [ "beverage", "drink", "cow" ], + "char": "\ud83e\udd5b", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + beer: { + keywords: [ "relax", "beverage", "drink", "drunk", "party", "pub", "summer", "alcohol", "booze" ], + "char": "\ud83c\udf7a", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + beers: { + keywords: [ "relax", "beverage", "drink", "drunk", "party", "pub", "summer", "alcohol", "booze" ], + "char": "\ud83c\udf7b", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + clinking_glasses: { + keywords: [ "beverage", "drink", "party", "alcohol", "celebrate", "cheers", "wine", "champagne", "toast" ], + "char": "\ud83e\udd42", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + wine_glass: { + keywords: [ "drink", "beverage", "drunk", "alcohol", "booze" ], + "char": "\ud83c\udf77", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + tumbler_glass: { + keywords: [ "drink", "beverage", "drunk", "alcohol", "liquor", "booze", "bourbon", "scotch", "whisky", "glass", "shot" ], + "char": "\ud83e\udd43", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cocktail: { + keywords: [ "drink", "drunk", "alcohol", "beverage", "booze", "mojito" ], + "char": "\ud83c\udf78", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + tropical_drink: { + keywords: [ "beverage", "cocktail", "summer", "beach", "alcohol", "booze", "mojito" ], + "char": "\ud83c\udf79", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + champagne: { + keywords: [ "drink", "wine", "bottle", "celebration" ], + "char": "\ud83c\udf7e", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + sake: { + keywords: [ "wine", "drink", "drunk", "beverage", "japanese", "alcohol", "booze" ], + "char": "\ud83c\udf76", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + tea: { + keywords: [ "drink", "bowl", "breakfast", "green", "british" ], + "char": "\ud83c\udf75", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + cup_with_straw: { + keywords: [ "drink", "soda" ], + "char": "\ud83e\udd64", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + coffee: { + keywords: [ "beverage", "caffeine", "latte", "espresso" ], + "char": "\u2615", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + baby_bottle: { + keywords: [ "food", "container", "milk" ], + "char": "\ud83c\udf7c", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + salt: { + keywords: [ "condiment", "shaker" ], + "char": "\ud83e\uddc2", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + spoon: { + keywords: [ "cutlery", "kitchen", "tableware" ], + "char": "\ud83e\udd44", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + fork_and_knife: { + keywords: [ "cutlery", "kitchen" ], + "char": "\ud83c\udf74", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + plate_with_cutlery: { + keywords: [ "food", "eat", "meal", "lunch", "dinner", "restaurant" ], + "char": "\ud83c\udf7d", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + bowl_with_spoon: { + keywords: [ "food", "breakfast", "cereal", "oatmeal", "porridge" ], + "char": "\ud83e\udd63", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + takeout_box: { + keywords: [ "food", "leftovers" ], + "char": "\ud83e\udd61", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + chopsticks: { + keywords: [ "food" ], + "char": "\ud83e\udd62", + fitzpatrick_scale: false, + category: "food_and_drink" + }, + soccer: { + keywords: [ "sports", "football" ], + "char": "\u26bd", + fitzpatrick_scale: false, + category: "activity" + }, + basketball: { + keywords: [ "sports", "balls", "NBA" ], + "char": "\ud83c\udfc0", + fitzpatrick_scale: false, + category: "activity" + }, + football: { + keywords: [ "sports", "balls", "NFL" ], + "char": "\ud83c\udfc8", + fitzpatrick_scale: false, + category: "activity" + }, + baseball: { + keywords: [ "sports", "balls" ], + "char": "\u26be", + fitzpatrick_scale: false, + category: "activity" + }, + softball: { + keywords: [ "sports", "balls" ], + "char": "\ud83e\udd4e", + fitzpatrick_scale: false, + category: "activity" + }, + tennis: { + keywords: [ "sports", "balls", "green" ], + "char": "\ud83c\udfbe", + fitzpatrick_scale: false, + category: "activity" + }, + volleyball: { + keywords: [ "sports", "balls" ], + "char": "\ud83c\udfd0", + fitzpatrick_scale: false, + category: "activity" + }, + rugby_football: { + keywords: [ "sports", "team" ], + "char": "\ud83c\udfc9", + fitzpatrick_scale: false, + category: "activity" + }, + flying_disc: { + keywords: [ "sports", "frisbee", "ultimate" ], + "char": "\ud83e\udd4f", + fitzpatrick_scale: false, + category: "activity" + }, + "8ball": { + keywords: [ "pool", "hobby", "game", "luck", "magic" ], + "char": "\ud83c\udfb1", + fitzpatrick_scale: false, + category: "activity" + }, + golf: { + keywords: [ "sports", "business", "flag", "hole", "summer" ], + "char": "\u26f3", + fitzpatrick_scale: false, + category: "activity" + }, + golfing_woman: { + keywords: [ "sports", "business", "woman", "female" ], + "char": "\ud83c\udfcc\ufe0f\u200d\u2640\ufe0f", + fitzpatrick_scale: false, + category: "activity" + }, + golfing_man: { + keywords: [ "sports", "business" ], + "char": "\ud83c\udfcc", + fitzpatrick_scale: true, + category: "activity" + }, + ping_pong: { + keywords: [ "sports", "pingpong" ], + "char": "\ud83c\udfd3", + fitzpatrick_scale: false, + category: "activity" + }, + badminton: { + keywords: [ "sports" ], + "char": "\ud83c\udff8", + fitzpatrick_scale: false, + category: "activity" + }, + goal_net: { + keywords: [ "sports" ], + "char": "\ud83e\udd45", + fitzpatrick_scale: false, + category: "activity" + }, + ice_hockey: { + keywords: [ "sports" ], + "char": "\ud83c\udfd2", + fitzpatrick_scale: false, + category: "activity" + }, + field_hockey: { + keywords: [ "sports" ], + "char": "\ud83c\udfd1", + fitzpatrick_scale: false, + category: "activity" + }, + lacrosse: { + keywords: [ "sports", "ball", "stick" ], + "char": "\ud83e\udd4d", + fitzpatrick_scale: false, + category: "activity" + }, + cricket: { + keywords: [ "sports" ], + "char": "\ud83c\udfcf", + fitzpatrick_scale: false, + category: "activity" + }, + ski: { + keywords: [ "sports", "winter", "cold", "snow" ], + "char": "\ud83c\udfbf", + fitzpatrick_scale: false, + category: "activity" + }, + skier: { + keywords: [ "sports", "winter", "snow" ], + "char": "\u26f7", + fitzpatrick_scale: false, + category: "activity" + }, + snowboarder: { + keywords: [ "sports", "winter" ], + "char": "\ud83c\udfc2", + fitzpatrick_scale: true, + category: "activity" + }, + person_fencing: { + keywords: [ "sports", "fencing", "sword" ], + "char": "\ud83e\udd3a", + fitzpatrick_scale: false, + category: "activity" + }, + women_wrestling: { + keywords: [ "sports", "wrestlers" ], + "char": "\ud83e\udd3c\u200d\u2640\ufe0f", + fitzpatrick_scale: false, + category: "activity" + }, + men_wrestling: { + keywords: [ "sports", "wrestlers" ], + "char": "\ud83e\udd3c\u200d\u2642\ufe0f", + fitzpatrick_scale: false, + category: "activity" + }, + woman_cartwheeling: { + keywords: [ "gymnastics" ], + "char": "\ud83e\udd38\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + man_cartwheeling: { + keywords: [ "gymnastics" ], + "char": "\ud83e\udd38\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + woman_playing_handball: { + keywords: [ "sports" ], + "char": "\ud83e\udd3e\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + man_playing_handball: { + keywords: [ "sports" ], + "char": "\ud83e\udd3e\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + ice_skate: { + keywords: [ "sports" ], + "char": "\u26f8", + fitzpatrick_scale: false, + category: "activity" + }, + curling_stone: { + keywords: [ "sports" ], + "char": "\ud83e\udd4c", + fitzpatrick_scale: false, + category: "activity" + }, + skateboard: { + keywords: [ "board" ], + "char": "\ud83d\udef9", + fitzpatrick_scale: false, + category: "activity" + }, + sled: { + keywords: [ "sleigh", "luge", "toboggan" ], + "char": "\ud83d\udef7", + fitzpatrick_scale: false, + category: "activity" + }, + bow_and_arrow: { + keywords: [ "sports" ], + "char": "\ud83c\udff9", + fitzpatrick_scale: false, + category: "activity" + }, + fishing_pole_and_fish: { + keywords: [ "food", "hobby", "summer" ], + "char": "\ud83c\udfa3", + fitzpatrick_scale: false, + category: "activity" + }, + boxing_glove: { + keywords: [ "sports", "fighting" ], + "char": "\ud83e\udd4a", + fitzpatrick_scale: false, + category: "activity" + }, + martial_arts_uniform: { + keywords: [ "judo", "karate", "taekwondo" ], + "char": "\ud83e\udd4b", + fitzpatrick_scale: false, + category: "activity" + }, + rowing_woman: { + keywords: [ "sports", "hobby", "water", "ship", "woman", "female" ], + "char": "\ud83d\udea3\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + rowing_man: { + keywords: [ "sports", "hobby", "water", "ship" ], + "char": "\ud83d\udea3", + fitzpatrick_scale: true, + category: "activity" + }, + climbing_woman: { + keywords: [ "sports", "hobby", "woman", "female", "rock" ], + "char": "\ud83e\uddd7\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + climbing_man: { + keywords: [ "sports", "hobby", "man", "male", "rock" ], + "char": "\ud83e\uddd7\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + swimming_woman: { + keywords: [ "sports", "exercise", "human", "athlete", "water", "summer", "woman", "female" ], + "char": "\ud83c\udfca\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + swimming_man: { + keywords: [ "sports", "exercise", "human", "athlete", "water", "summer" ], + "char": "\ud83c\udfca", + fitzpatrick_scale: true, + category: "activity" + }, + woman_playing_water_polo: { + keywords: [ "sports", "pool" ], + "char": "\ud83e\udd3d\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + man_playing_water_polo: { + keywords: [ "sports", "pool" ], + "char": "\ud83e\udd3d\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + woman_in_lotus_position: { + keywords: [ "woman", "female", "meditation", "yoga", "serenity", "zen", "mindfulness" ], + "char": "\ud83e\uddd8\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + man_in_lotus_position: { + keywords: [ "man", "male", "meditation", "yoga", "serenity", "zen", "mindfulness" ], + "char": "\ud83e\uddd8\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + surfing_woman: { + keywords: [ "sports", "ocean", "sea", "summer", "beach", "woman", "female" ], + "char": "\ud83c\udfc4\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + surfing_man: { + keywords: [ "sports", "ocean", "sea", "summer", "beach" ], + "char": "\ud83c\udfc4", + fitzpatrick_scale: true, + category: "activity" + }, + bath: { + keywords: [ "clean", "shower", "bathroom" ], + "char": "\ud83d\udec0", + fitzpatrick_scale: true, + category: "activity" + }, + basketball_woman: { + keywords: [ "sports", "human", "woman", "female" ], + "char": "\u26f9\ufe0f\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + basketball_man: { + keywords: [ "sports", "human" ], + "char": "\u26f9", + fitzpatrick_scale: true, + category: "activity" + }, + weight_lifting_woman: { + keywords: [ "sports", "training", "exercise", "woman", "female" ], + "char": "\ud83c\udfcb\ufe0f\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + weight_lifting_man: { + keywords: [ "sports", "training", "exercise" ], + "char": "\ud83c\udfcb", + fitzpatrick_scale: true, + category: "activity" + }, + biking_woman: { + keywords: [ "sports", "bike", "exercise", "hipster", "woman", "female" ], + "char": "\ud83d\udeb4\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + biking_man: { + keywords: [ "sports", "bike", "exercise", "hipster" ], + "char": "\ud83d\udeb4", + fitzpatrick_scale: true, + category: "activity" + }, + mountain_biking_woman: { + keywords: [ "transportation", "sports", "human", "race", "bike", "woman", "female" ], + "char": "\ud83d\udeb5\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + mountain_biking_man: { + keywords: [ "transportation", "sports", "human", "race", "bike" ], + "char": "\ud83d\udeb5", + fitzpatrick_scale: true, + category: "activity" + }, + horse_racing: { + keywords: [ "animal", "betting", "competition", "gambling", "luck" ], + "char": "\ud83c\udfc7", + fitzpatrick_scale: true, + category: "activity" + }, + business_suit_levitating: { + keywords: [ "suit", "business", "levitate", "hover", "jump" ], + "char": "\ud83d\udd74", + fitzpatrick_scale: true, + category: "activity" + }, + trophy: { + keywords: [ "win", "award", "contest", "place", "ftw", "ceremony" ], + "char": "\ud83c\udfc6", + fitzpatrick_scale: false, + category: "activity" + }, + running_shirt_with_sash: { + keywords: [ "play", "pageant" ], + "char": "\ud83c\udfbd", + fitzpatrick_scale: false, + category: "activity" + }, + medal_sports: { + keywords: [ "award", "winning" ], + "char": "\ud83c\udfc5", + fitzpatrick_scale: false, + category: "activity" + }, + medal_military: { + keywords: [ "award", "winning", "army" ], + "char": "\ud83c\udf96", + fitzpatrick_scale: false, + category: "activity" + }, + "1st_place_medal": { + keywords: [ "award", "winning", "first" ], + "char": "\ud83e\udd47", + fitzpatrick_scale: false, + category: "activity" + }, + "2nd_place_medal": { + keywords: [ "award", "second" ], + "char": "\ud83e\udd48", + fitzpatrick_scale: false, + category: "activity" + }, + "3rd_place_medal": { + keywords: [ "award", "third" ], + "char": "\ud83e\udd49", + fitzpatrick_scale: false, + category: "activity" + }, + reminder_ribbon: { + keywords: [ "sports", "cause", "support", "awareness" ], + "char": "\ud83c\udf97", + fitzpatrick_scale: false, + category: "activity" + }, + rosette: { + keywords: [ "flower", "decoration", "military" ], + "char": "\ud83c\udff5", + fitzpatrick_scale: false, + category: "activity" + }, + ticket: { + keywords: [ "event", "concert", "pass" ], + "char": "\ud83c\udfab", + fitzpatrick_scale: false, + category: "activity" + }, + tickets: { + keywords: [ "sports", "concert", "entrance" ], + "char": "\ud83c\udf9f", + fitzpatrick_scale: false, + category: "activity" + }, + performing_arts: { + keywords: [ "acting", "theater", "drama" ], + "char": "\ud83c\udfad", + fitzpatrick_scale: false, + category: "activity" + }, + art: { + keywords: [ "design", "paint", "draw", "colors" ], + "char": "\ud83c\udfa8", + fitzpatrick_scale: false, + category: "activity" + }, + circus_tent: { + keywords: [ "festival", "carnival", "party" ], + "char": "\ud83c\udfaa", + fitzpatrick_scale: false, + category: "activity" + }, + woman_juggling: { + keywords: [ "juggle", "balance", "skill", "multitask" ], + "char": "\ud83e\udd39\u200d\u2640\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + man_juggling: { + keywords: [ "juggle", "balance", "skill", "multitask" ], + "char": "\ud83e\udd39\u200d\u2642\ufe0f", + fitzpatrick_scale: true, + category: "activity" + }, + microphone: { + keywords: [ "sound", "music", "PA", "sing", "talkshow" ], + "char": "\ud83c\udfa4", + fitzpatrick_scale: false, + category: "activity" + }, + headphones: { + keywords: [ "music", "score", "gadgets" ], + "char": "\ud83c\udfa7", + fitzpatrick_scale: false, + category: "activity" + }, + musical_score: { + keywords: [ "treble", "clef", "compose" ], + "char": "\ud83c\udfbc", + fitzpatrick_scale: false, + category: "activity" + }, + musical_keyboard: { + keywords: [ "piano", "instrument", "compose" ], + "char": "\ud83c\udfb9", + fitzpatrick_scale: false, + category: "activity" + }, + drum: { + keywords: [ "music", "instrument", "drumsticks", "snare" ], + "char": "\ud83e\udd41", + fitzpatrick_scale: false, + category: "activity" + }, + saxophone: { + keywords: [ "music", "instrument", "jazz", "blues" ], + "char": "\ud83c\udfb7", + fitzpatrick_scale: false, + category: "activity" + }, + trumpet: { + keywords: [ "music", "brass" ], + "char": "\ud83c\udfba", + fitzpatrick_scale: false, + category: "activity" + }, + guitar: { + keywords: [ "music", "instrument" ], + "char": "\ud83c\udfb8", + fitzpatrick_scale: false, + category: "activity" + }, + violin: { + keywords: [ "music", "instrument", "orchestra", "symphony" ], + "char": "\ud83c\udfbb", + fitzpatrick_scale: false, + category: "activity" + }, + clapper: { + keywords: [ "movie", "film", "record" ], + "char": "\ud83c\udfac", + fitzpatrick_scale: false, + category: "activity" + }, + video_game: { + keywords: [ "play", "console", "PS4", "controller" ], + "char": "\ud83c\udfae", + fitzpatrick_scale: false, + category: "activity" + }, + space_invader: { + keywords: [ "game", "arcade", "play" ], + "char": "\ud83d\udc7e", + fitzpatrick_scale: false, + category: "activity" + }, + dart: { + keywords: [ "game", "play", "bar", "target", "bullseye" ], + "char": "\ud83c\udfaf", + fitzpatrick_scale: false, + category: "activity" + }, + game_die: { + keywords: [ "dice", "random", "tabletop", "play", "luck" ], + "char": "\ud83c\udfb2", + fitzpatrick_scale: false, + category: "activity" + }, + chess_pawn: { + keywords: [ "expendable" ], + "char": "\u265f", + fitzpatrick_scale: false, + category: "activity" + }, + slot_machine: { + keywords: [ "bet", "gamble", "vegas", "fruit machine", "luck", "casino" ], + "char": "\ud83c\udfb0", + fitzpatrick_scale: false, + category: "activity" + }, + jigsaw: { + keywords: [ "interlocking", "puzzle", "piece" ], + "char": "\ud83e\udde9", + fitzpatrick_scale: false, + category: "activity" + }, + bowling: { + keywords: [ "sports", "fun", "play" ], + "char": "\ud83c\udfb3", + fitzpatrick_scale: false, + category: "activity" + }, + red_car: { + keywords: [ "red", "transportation", "vehicle" ], + "char": "\ud83d\ude97", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + taxi: { + keywords: [ "uber", "vehicle", "cars", "transportation" ], + "char": "\ud83d\ude95", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + blue_car: { + keywords: [ "transportation", "vehicle" ], + "char": "\ud83d\ude99", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + bus: { + keywords: [ "car", "vehicle", "transportation" ], + "char": "\ud83d\ude8c", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + trolleybus: { + keywords: [ "bart", "transportation", "vehicle" ], + "char": "\ud83d\ude8e", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + racing_car: { + keywords: [ "sports", "race", "fast", "formula", "f1" ], + "char": "\ud83c\udfce", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + police_car: { + keywords: [ "vehicle", "cars", "transportation", "law", "legal", "enforcement" ], + "char": "\ud83d\ude93", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + ambulance: { + keywords: [ "health", "911", "hospital" ], + "char": "\ud83d\ude91", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + fire_engine: { + keywords: [ "transportation", "cars", "vehicle" ], + "char": "\ud83d\ude92", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + minibus: { + keywords: [ "vehicle", "car", "transportation" ], + "char": "\ud83d\ude90", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + truck: { + keywords: [ "cars", "transportation" ], + "char": "\ud83d\ude9a", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + articulated_lorry: { + keywords: [ "vehicle", "cars", "transportation", "express" ], + "char": "\ud83d\ude9b", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + tractor: { + keywords: [ "vehicle", "car", "farming", "agriculture" ], + "char": "\ud83d\ude9c", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + kick_scooter: { + keywords: [ "vehicle", "kick", "razor" ], + "char": "\ud83d\udef4", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + motorcycle: { + keywords: [ "race", "sports", "fast" ], + "char": "\ud83c\udfcd", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + bike: { + keywords: [ "sports", "bicycle", "exercise", "hipster" ], + "char": "\ud83d\udeb2", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + motor_scooter: { + keywords: [ "vehicle", "vespa", "sasha" ], + "char": "\ud83d\udef5", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + rotating_light: { + keywords: [ "police", "ambulance", "911", "emergency", "alert", "error", "pinged", "law", "legal" ], + "char": "\ud83d\udea8", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + oncoming_police_car: { + keywords: [ "vehicle", "law", "legal", "enforcement", "911" ], + "char": "\ud83d\ude94", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + oncoming_bus: { + keywords: [ "vehicle", "transportation" ], + "char": "\ud83d\ude8d", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + oncoming_automobile: { + keywords: [ "car", "vehicle", "transportation" ], + "char": "\ud83d\ude98", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + oncoming_taxi: { + keywords: [ "vehicle", "cars", "uber" ], + "char": "\ud83d\ude96", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + aerial_tramway: { + keywords: [ "transportation", "vehicle", "ski" ], + "char": "\ud83d\udea1", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + mountain_cableway: { + keywords: [ "transportation", "vehicle", "ski" ], + "char": "\ud83d\udea0", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + suspension_railway: { + keywords: [ "vehicle", "transportation" ], + "char": "\ud83d\ude9f", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + railway_car: { + keywords: [ "transportation", "vehicle" ], + "char": "\ud83d\ude83", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + train: { + keywords: [ "transportation", "vehicle", "carriage", "public", "travel" ], + "char": "\ud83d\ude8b", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + monorail: { + keywords: [ "transportation", "vehicle" ], + "char": "\ud83d\ude9d", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + bullettrain_side: { + keywords: [ "transportation", "vehicle" ], + "char": "\ud83d\ude84", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + bullettrain_front: { + keywords: [ "transportation", "vehicle", "speed", "fast", "public", "travel" ], + "char": "\ud83d\ude85", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + light_rail: { + keywords: [ "transportation", "vehicle" ], + "char": "\ud83d\ude88", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + mountain_railway: { + keywords: [ "transportation", "vehicle" ], + "char": "\ud83d\ude9e", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + steam_locomotive: { + keywords: [ "transportation", "vehicle", "train" ], + "char": "\ud83d\ude82", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + train2: { + keywords: [ "transportation", "vehicle" ], + "char": "\ud83d\ude86", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + metro: { + keywords: [ "transportation", "blue-square", "mrt", "underground", "tube" ], + "char": "\ud83d\ude87", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + tram: { + keywords: [ "transportation", "vehicle" ], + "char": "\ud83d\ude8a", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + station: { + keywords: [ "transportation", "vehicle", "public" ], + "char": "\ud83d\ude89", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + flying_saucer: { + keywords: [ "transportation", "vehicle", "ufo" ], + "char": "\ud83d\udef8", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + helicopter: { + keywords: [ "transportation", "vehicle", "fly" ], + "char": "\ud83d\ude81", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + small_airplane: { + keywords: [ "flight", "transportation", "fly", "vehicle" ], + "char": "\ud83d\udee9", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + airplane: { + keywords: [ "vehicle", "transportation", "flight", "fly" ], + "char": "\u2708\ufe0f", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + flight_departure: { + keywords: [ "airport", "flight", "landing" ], + "char": "\ud83d\udeeb", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + flight_arrival: { + keywords: [ "airport", "flight", "boarding" ], + "char": "\ud83d\udeec", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + sailboat: { + keywords: [ "ship", "summer", "transportation", "water", "sailing" ], + "char": "\u26f5", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + motor_boat: { + keywords: [ "ship" ], + "char": "\ud83d\udee5", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + speedboat: { + keywords: [ "ship", "transportation", "vehicle", "summer" ], + "char": "\ud83d\udea4", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + ferry: { + keywords: [ "boat", "ship", "yacht" ], + "char": "\u26f4", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + passenger_ship: { + keywords: [ "yacht", "cruise", "ferry" ], + "char": "\ud83d\udef3", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + rocket: { + keywords: [ "launch", "ship", "staffmode", "NASA", "outer space", "outer_space", "fly" ], + "char": "\ud83d\ude80", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + artificial_satellite: { + keywords: [ "communication", "gps", "orbit", "spaceflight", "NASA", "ISS" ], + "char": "\ud83d\udef0", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + seat: { + keywords: [ "sit", "airplane", "transport", "bus", "flight", "fly" ], + "char": "\ud83d\udcba", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + canoe: { + keywords: [ "boat", "paddle", "water", "ship" ], + "char": "\ud83d\udef6", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + anchor: { + keywords: [ "ship", "ferry", "sea", "boat" ], + "char": "\u2693", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + construction: { + keywords: [ "wip", "progress", "caution", "warning" ], + "char": "\ud83d\udea7", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + fuelpump: { + keywords: [ "gas station", "petroleum" ], + "char": "\u26fd", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + busstop: { + keywords: [ "transportation", "wait" ], + "char": "\ud83d\ude8f", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + vertical_traffic_light: { + keywords: [ "transportation", "driving" ], + "char": "\ud83d\udea6", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + traffic_light: { + keywords: [ "transportation", "signal" ], + "char": "\ud83d\udea5", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + checkered_flag: { + keywords: [ "contest", "finishline", "race", "gokart" ], + "char": "\ud83c\udfc1", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + ship: { + keywords: [ "transportation", "titanic", "deploy" ], + "char": "\ud83d\udea2", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + ferris_wheel: { + keywords: [ "photo", "carnival", "londoneye" ], + "char": "\ud83c\udfa1", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + roller_coaster: { + keywords: [ "carnival", "playground", "photo", "fun" ], + "char": "\ud83c\udfa2", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + carousel_horse: { + keywords: [ "photo", "carnival" ], + "char": "\ud83c\udfa0", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + building_construction: { + keywords: [ "wip", "working", "progress" ], + "char": "\ud83c\udfd7", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + foggy: { + keywords: [ "photo", "mountain" ], + "char": "\ud83c\udf01", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + tokyo_tower: { + keywords: [ "photo", "japanese" ], + "char": "\ud83d\uddfc", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + factory: { + keywords: [ "building", "industry", "pollution", "smoke" ], + "char": "\ud83c\udfed", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + fountain: { + keywords: [ "photo", "summer", "water", "fresh" ], + "char": "\u26f2", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + rice_scene: { + keywords: [ "photo", "japan", "asia", "tsukimi" ], + "char": "\ud83c\udf91", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + mountain: { + keywords: [ "photo", "nature", "environment" ], + "char": "\u26f0", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + mountain_snow: { + keywords: [ "photo", "nature", "environment", "winter", "cold" ], + "char": "\ud83c\udfd4", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + mount_fuji: { + keywords: [ "photo", "mountain", "nature", "japanese" ], + "char": "\ud83d\uddfb", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + volcano: { + keywords: [ "photo", "nature", "disaster" ], + "char": "\ud83c\udf0b", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + japan: { + keywords: [ "nation", "country", "japanese", "asia" ], + "char": "\ud83d\uddfe", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + camping: { + keywords: [ "photo", "outdoors", "tent" ], + "char": "\ud83c\udfd5", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + tent: { + keywords: [ "photo", "camping", "outdoors" ], + "char": "\u26fa", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + national_park: { + keywords: [ "photo", "environment", "nature" ], + "char": "\ud83c\udfde", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + motorway: { + keywords: [ "road", "cupertino", "interstate", "highway" ], + "char": "\ud83d\udee3", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + railway_track: { + keywords: [ "train", "transportation" ], + "char": "\ud83d\udee4", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + sunrise: { + keywords: [ "morning", "view", "vacation", "photo" ], + "char": "\ud83c\udf05", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + sunrise_over_mountains: { + keywords: [ "view", "vacation", "photo" ], + "char": "\ud83c\udf04", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + desert: { + keywords: [ "photo", "warm", "saharah" ], + "char": "\ud83c\udfdc", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + beach_umbrella: { + keywords: [ "weather", "summer", "sunny", "sand", "mojito" ], + "char": "\ud83c\udfd6", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + desert_island: { + keywords: [ "photo", "tropical", "mojito" ], + "char": "\ud83c\udfdd", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + city_sunrise: { + keywords: [ "photo", "good morning", "dawn" ], + "char": "\ud83c\udf07", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + city_sunset: { + keywords: [ "photo", "evening", "sky", "buildings" ], + "char": "\ud83c\udf06", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + cityscape: { + keywords: [ "photo", "night life", "urban" ], + "char": "\ud83c\udfd9", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + night_with_stars: { + keywords: [ "evening", "city", "downtown" ], + "char": "\ud83c\udf03", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + bridge_at_night: { + keywords: [ "photo", "sanfrancisco" ], + "char": "\ud83c\udf09", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + milky_way: { + keywords: [ "photo", "space", "stars" ], + "char": "\ud83c\udf0c", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + stars: { + keywords: [ "night", "photo" ], + "char": "\ud83c\udf20", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + sparkler: { + keywords: [ "stars", "night", "shine" ], + "char": "\ud83c\udf87", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + fireworks: { + keywords: [ "photo", "festival", "carnival", "congratulations" ], + "char": "\ud83c\udf86", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + rainbow: { + keywords: [ "nature", "happy", "unicorn_face", "photo", "sky", "spring" ], + "char": "\ud83c\udf08", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + houses: { + keywords: [ "buildings", "photo" ], + "char": "\ud83c\udfd8", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + european_castle: { + keywords: [ "building", "royalty", "history" ], + "char": "\ud83c\udff0", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + japanese_castle: { + keywords: [ "photo", "building" ], + "char": "\ud83c\udfef", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + stadium: { + keywords: [ "photo", "place", "sports", "concert", "venue" ], + "char": "\ud83c\udfdf", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + statue_of_liberty: { + keywords: [ "american", "newyork" ], + "char": "\ud83d\uddfd", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + house: { + keywords: [ "building", "home" ], + "char": "\ud83c\udfe0", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + house_with_garden: { + keywords: [ "home", "plant", "nature" ], + "char": "\ud83c\udfe1", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + derelict_house: { + keywords: [ "abandon", "evict", "broken", "building" ], + "char": "\ud83c\udfda", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + office: { + keywords: [ "building", "bureau", "work" ], + "char": "\ud83c\udfe2", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + department_store: { + keywords: [ "building", "shopping", "mall" ], + "char": "\ud83c\udfec", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + post_office: { + keywords: [ "building", "envelope", "communication" ], + "char": "\ud83c\udfe3", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + european_post_office: { + keywords: [ "building", "email" ], + "char": "\ud83c\udfe4", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + hospital: { + keywords: [ "building", "health", "surgery", "doctor" ], + "char": "\ud83c\udfe5", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + bank: { + keywords: [ "building", "money", "sales", "cash", "business", "enterprise" ], + "char": "\ud83c\udfe6", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + hotel: { + keywords: [ "building", "accomodation", "checkin" ], + "char": "\ud83c\udfe8", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + convenience_store: { + keywords: [ "building", "shopping", "groceries" ], + "char": "\ud83c\udfea", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + school: { + keywords: [ "building", "student", "education", "learn", "teach" ], + "char": "\ud83c\udfeb", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + love_hotel: { + keywords: [ "like", "affection", "dating" ], + "char": "\ud83c\udfe9", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + wedding: { + keywords: [ "love", "like", "affection", "couple", "marriage", "bride", "groom" ], + "char": "\ud83d\udc92", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + classical_building: { + keywords: [ "art", "culture", "history" ], + "char": "\ud83c\udfdb", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + church: { + keywords: [ "building", "religion", "christ" ], + "char": "\u26ea", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + mosque: { + keywords: [ "islam", "worship", "minaret" ], + "char": "\ud83d\udd4c", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + synagogue: { + keywords: [ "judaism", "worship", "temple", "jewish" ], + "char": "\ud83d\udd4d", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + kaaba: { + keywords: [ "mecca", "mosque", "islam" ], + "char": "\ud83d\udd4b", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + shinto_shrine: { + keywords: [ "temple", "japan", "kyoto" ], + "char": "\u26e9", + fitzpatrick_scale: false, + category: "travel_and_places" + }, + watch: { + keywords: [ "time", "accessories" ], + "char": "\u231a", + fitzpatrick_scale: false, + category: "objects" + }, + iphone: { + keywords: [ "technology", "apple", "gadgets", "dial" ], + "char": "\ud83d\udcf1", + fitzpatrick_scale: false, + category: "objects" + }, + calling: { + keywords: [ "iphone", "incoming" ], + "char": "\ud83d\udcf2", + fitzpatrick_scale: false, + category: "objects" + }, + computer: { + keywords: [ "technology", "laptop", "screen", "display", "monitor" ], + "char": "\ud83d\udcbb", + fitzpatrick_scale: false, + category: "objects" + }, + keyboard: { + keywords: [ "technology", "computer", "type", "input", "text" ], + "char": "\u2328", + fitzpatrick_scale: false, + category: "objects" + }, + desktop_computer: { + keywords: [ "technology", "computing", "screen" ], + "char": "\ud83d\udda5", + fitzpatrick_scale: false, + category: "objects" + }, + printer: { + keywords: [ "paper", "ink" ], + "char": "\ud83d\udda8", + fitzpatrick_scale: false, + category: "objects" + }, + computer_mouse: { + keywords: [ "click" ], + "char": "\ud83d\uddb1", + fitzpatrick_scale: false, + category: "objects" + }, + trackball: { + keywords: [ "technology", "trackpad" ], + "char": "\ud83d\uddb2", + fitzpatrick_scale: false, + category: "objects" + }, + joystick: { + keywords: [ "game", "play" ], + "char": "\ud83d\udd79", + fitzpatrick_scale: false, + category: "objects" + }, + clamp: { + keywords: [ "tool" ], + "char": "\ud83d\udddc", + fitzpatrick_scale: false, + category: "objects" + }, + minidisc: { + keywords: [ "technology", "record", "data", "disk", "90s" ], + "char": "\ud83d\udcbd", + fitzpatrick_scale: false, + category: "objects" + }, + floppy_disk: { + keywords: [ "oldschool", "technology", "save", "90s", "80s" ], + "char": "\ud83d\udcbe", + fitzpatrick_scale: false, + category: "objects" + }, + cd: { + keywords: [ "technology", "dvd", "disk", "disc", "90s" ], + "char": "\ud83d\udcbf", + fitzpatrick_scale: false, + category: "objects" + }, + dvd: { + keywords: [ "cd", "disk", "disc" ], + "char": "\ud83d\udcc0", + fitzpatrick_scale: false, + category: "objects" + }, + vhs: { + keywords: [ "record", "video", "oldschool", "90s", "80s" ], + "char": "\ud83d\udcfc", + fitzpatrick_scale: false, + category: "objects" + }, + camera: { + keywords: [ "gadgets", "photography" ], + "char": "\ud83d\udcf7", + fitzpatrick_scale: false, + category: "objects" + }, + camera_flash: { + keywords: [ "photography", "gadgets" ], + "char": "\ud83d\udcf8", + fitzpatrick_scale: false, + category: "objects" + }, + video_camera: { + keywords: [ "film", "record" ], + "char": "\ud83d\udcf9", + fitzpatrick_scale: false, + category: "objects" + }, + movie_camera: { + keywords: [ "film", "record" ], + "char": "\ud83c\udfa5", + fitzpatrick_scale: false, + category: "objects" + }, + film_projector: { + keywords: [ "video", "tape", "record", "movie" ], + "char": "\ud83d\udcfd", + fitzpatrick_scale: false, + category: "objects" + }, + film_strip: { + keywords: [ "movie" ], + "char": "\ud83c\udf9e", + fitzpatrick_scale: false, + category: "objects" + }, + telephone_receiver: { + keywords: [ "technology", "communication", "dial" ], + "char": "\ud83d\udcde", + fitzpatrick_scale: false, + category: "objects" + }, + phone: { + keywords: [ "technology", "communication", "dial", "telephone" ], + "char": "\u260e\ufe0f", + fitzpatrick_scale: false, + category: "objects" + }, + pager: { + keywords: [ "bbcall", "oldschool", "90s" ], + "char": "\ud83d\udcdf", + fitzpatrick_scale: false, + category: "objects" + }, + fax: { + keywords: [ "communication", "technology" ], + "char": "\ud83d\udce0", + fitzpatrick_scale: false, + category: "objects" + }, + tv: { + keywords: [ "technology", "program", "oldschool", "show", "television" ], + "char": "\ud83d\udcfa", + fitzpatrick_scale: false, + category: "objects" + }, + radio: { + keywords: [ "communication", "music", "podcast", "program" ], + "char": "\ud83d\udcfb", + fitzpatrick_scale: false, + category: "objects" + }, + studio_microphone: { + keywords: [ "sing", "recording", "artist", "talkshow" ], + "char": "\ud83c\udf99", + fitzpatrick_scale: false, + category: "objects" + }, + level_slider: { + keywords: [ "scale" ], + "char": "\ud83c\udf9a", + fitzpatrick_scale: false, + category: "objects" + }, + control_knobs: { + keywords: [ "dial" ], + "char": "\ud83c\udf9b", + fitzpatrick_scale: false, + category: "objects" + }, + compass: { + keywords: [ "magnetic", "navigation", "orienteering" ], + "char": "\ud83e\udded", + fitzpatrick_scale: false, + category: "objects" + }, + stopwatch: { + keywords: [ "time", "deadline" ], + "char": "\u23f1", + fitzpatrick_scale: false, + category: "objects" + }, + timer_clock: { + keywords: [ "alarm" ], + "char": "\u23f2", + fitzpatrick_scale: false, + category: "objects" + }, + alarm_clock: { + keywords: [ "time", "wake" ], + "char": "\u23f0", + fitzpatrick_scale: false, + category: "objects" + }, + mantelpiece_clock: { + keywords: [ "time" ], + "char": "\ud83d\udd70", + fitzpatrick_scale: false, + category: "objects" + }, + hourglass_flowing_sand: { + keywords: [ "oldschool", "time", "countdown" ], + "char": "\u23f3", + fitzpatrick_scale: false, + category: "objects" + }, + hourglass: { + keywords: [ "time", "clock", "oldschool", "limit", "exam", "quiz", "test" ], + "char": "\u231b", + fitzpatrick_scale: false, + category: "objects" + }, + satellite: { + keywords: [ "communication", "future", "radio", "space" ], + "char": "\ud83d\udce1", + fitzpatrick_scale: false, + category: "objects" + }, + battery: { + keywords: [ "power", "energy", "sustain" ], + "char": "\ud83d\udd0b", + fitzpatrick_scale: false, + category: "objects" + }, + electric_plug: { + keywords: [ "charger", "power" ], + "char": "\ud83d\udd0c", + fitzpatrick_scale: false, + category: "objects" + }, + bulb: { + keywords: [ "light", "electricity", "idea" ], + "char": "\ud83d\udca1", + fitzpatrick_scale: false, + category: "objects" + }, + flashlight: { + keywords: [ "dark", "camping", "sight", "night" ], + "char": "\ud83d\udd26", + fitzpatrick_scale: false, + category: "objects" + }, + candle: { + keywords: [ "fire", "wax" ], + "char": "\ud83d\udd6f", + fitzpatrick_scale: false, + category: "objects" + }, + fire_extinguisher: { + keywords: [ "quench" ], + "char": "\ud83e\uddef", + fitzpatrick_scale: false, + category: "objects" + }, + wastebasket: { + keywords: [ "bin", "trash", "rubbish", "garbage", "toss" ], + "char": "\ud83d\uddd1", + fitzpatrick_scale: false, + category: "objects" + }, + oil_drum: { + keywords: [ "barrell" ], + "char": "\ud83d\udee2", + fitzpatrick_scale: false, + category: "objects" + }, + money_with_wings: { + keywords: [ "dollar", "bills", "payment", "sale" ], + "char": "\ud83d\udcb8", + fitzpatrick_scale: false, + category: "objects" + }, + dollar: { + keywords: [ "money", "sales", "bill", "currency" ], + "char": "\ud83d\udcb5", + fitzpatrick_scale: false, + category: "objects" + }, + yen: { + keywords: [ "money", "sales", "japanese", "dollar", "currency" ], + "char": "\ud83d\udcb4", + fitzpatrick_scale: false, + category: "objects" + }, + euro: { + keywords: [ "money", "sales", "dollar", "currency" ], + "char": "\ud83d\udcb6", + fitzpatrick_scale: false, + category: "objects" + }, + pound: { + keywords: [ "british", "sterling", "money", "sales", "bills", "uk", "england", "currency" ], + "char": "\ud83d\udcb7", + fitzpatrick_scale: false, + category: "objects" + }, + moneybag: { + keywords: [ "dollar", "payment", "coins", "sale" ], + "char": "\ud83d\udcb0", + fitzpatrick_scale: false, + category: "objects" + }, + credit_card: { + keywords: [ "money", "sales", "dollar", "bill", "payment", "shopping" ], + "char": "\ud83d\udcb3", + fitzpatrick_scale: false, + category: "objects" + }, + gem: { + keywords: [ "blue", "ruby", "diamond", "jewelry" ], + "char": "\ud83d\udc8e", + fitzpatrick_scale: false, + category: "objects" + }, + balance_scale: { + keywords: [ "law", "fairness", "weight" ], + "char": "\u2696", + fitzpatrick_scale: false, + category: "objects" + }, + toolbox: { + keywords: [ "tools", "diy", "fix", "maintainer", "mechanic" ], + "char": "\ud83e\uddf0", + fitzpatrick_scale: false, + category: "objects" + }, + wrench: { + keywords: [ "tools", "diy", "ikea", "fix", "maintainer" ], + "char": "\ud83d\udd27", + fitzpatrick_scale: false, + category: "objects" + }, + hammer: { + keywords: [ "tools", "build", "create" ], + "char": "\ud83d\udd28", + fitzpatrick_scale: false, + category: "objects" + }, + hammer_and_pick: { + keywords: [ "tools", "build", "create" ], + "char": "\u2692", + fitzpatrick_scale: false, + category: "objects" + }, + hammer_and_wrench: { + keywords: [ "tools", "build", "create" ], + "char": "\ud83d\udee0", + fitzpatrick_scale: false, + category: "objects" + }, + pick: { + keywords: [ "tools", "dig" ], + "char": "\u26cf", + fitzpatrick_scale: false, + category: "objects" + }, + nut_and_bolt: { + keywords: [ "handy", "tools", "fix" ], + "char": "\ud83d\udd29", + fitzpatrick_scale: false, + category: "objects" + }, + gear: { + keywords: [ "cog" ], + "char": "\u2699", + fitzpatrick_scale: false, + category: "objects" + }, + brick: { + keywords: [ "bricks" ], + "char": "\ud83e\uddf1", + fitzpatrick_scale: false, + category: "objects" + }, + chains: { + keywords: [ "lock", "arrest" ], + "char": "\u26d3", + fitzpatrick_scale: false, + category: "objects" + }, + magnet: { + keywords: [ "attraction", "magnetic" ], + "char": "\ud83e\uddf2", + fitzpatrick_scale: false, + category: "objects" + }, + gun: { + keywords: [ "violence", "weapon", "pistol", "revolver" ], + "char": "\ud83d\udd2b", + fitzpatrick_scale: false, + category: "objects" + }, + bomb: { + keywords: [ "boom", "explode", "explosion", "terrorism" ], + "char": "\ud83d\udca3", + fitzpatrick_scale: false, + category: "objects" + }, + firecracker: { + keywords: [ "dynamite", "boom", "explode", "explosion", "explosive" ], + "char": "\ud83e\udde8", + fitzpatrick_scale: false, + category: "objects" + }, + hocho: { + keywords: [ "knife", "blade", "cutlery", "kitchen", "weapon" ], + "char": "\ud83d\udd2a", + fitzpatrick_scale: false, + category: "objects" + }, + dagger: { + keywords: [ "weapon" ], + "char": "\ud83d\udde1", + fitzpatrick_scale: false, + category: "objects" + }, + crossed_swords: { + keywords: [ "weapon" ], + "char": "\u2694", + fitzpatrick_scale: false, + category: "objects" + }, + shield: { + keywords: [ "protection", "security" ], + "char": "\ud83d\udee1", + fitzpatrick_scale: false, + category: "objects" + }, + smoking: { + keywords: [ "kills", "tobacco", "cigarette", "joint", "smoke" ], + "char": "\ud83d\udeac", + fitzpatrick_scale: false, + category: "objects" + }, + skull_and_crossbones: { + keywords: [ "poison", "danger", "deadly", "scary", "death", "pirate", "evil" ], + "char": "\u2620", + fitzpatrick_scale: false, + category: "objects" + }, + coffin: { + keywords: [ "vampire", "dead", "die", "death", "rip", "graveyard", "cemetery", "casket", "funeral", "box" ], + "char": "\u26b0", + fitzpatrick_scale: false, + category: "objects" + }, + funeral_urn: { + keywords: [ "dead", "die", "death", "rip", "ashes" ], + "char": "\u26b1", + fitzpatrick_scale: false, + category: "objects" + }, + amphora: { + keywords: [ "vase", "jar" ], + "char": "\ud83c\udffa", + fitzpatrick_scale: false, + category: "objects" + }, + crystal_ball: { + keywords: [ "disco", "party", "magic", "circus", "fortune_teller" ], + "char": "\ud83d\udd2e", + fitzpatrick_scale: false, + category: "objects" + }, + prayer_beads: { + keywords: [ "dhikr", "religious" ], + "char": "\ud83d\udcff", + fitzpatrick_scale: false, + category: "objects" + }, + nazar_amulet: { + keywords: [ "bead", "charm" ], + "char": "\ud83e\uddff", + fitzpatrick_scale: false, + category: "objects" + }, + barber: { + keywords: [ "hair", "salon", "style" ], + "char": "\ud83d\udc88", + fitzpatrick_scale: false, + category: "objects" + }, + alembic: { + keywords: [ "distilling", "science", "experiment", "chemistry" ], + "char": "\u2697", + fitzpatrick_scale: false, + category: "objects" + }, + telescope: { + keywords: [ "stars", "space", "zoom", "science", "astronomy" ], + "char": "\ud83d\udd2d", + fitzpatrick_scale: false, + category: "objects" + }, + microscope: { + keywords: [ "laboratory", "experiment", "zoomin", "science", "study" ], + "char": "\ud83d\udd2c", + fitzpatrick_scale: false, + category: "objects" + }, + hole: { + keywords: [ "embarrassing" ], + "char": "\ud83d\udd73", + fitzpatrick_scale: false, + category: "objects" + }, + pill: { + keywords: [ "health", "medicine", "doctor", "pharmacy", "drug" ], + "char": "\ud83d\udc8a", + fitzpatrick_scale: false, + category: "objects" + }, + syringe: { + keywords: [ "health", "hospital", "drugs", "blood", "medicine", "needle", "doctor", "nurse" ], + "char": "\ud83d\udc89", + fitzpatrick_scale: false, + category: "objects" + }, + dna: { + keywords: [ "biologist", "genetics", "life" ], + "char": "\ud83e\uddec", + fitzpatrick_scale: false, + category: "objects" + }, + microbe: { + keywords: [ "amoeba", "bacteria", "germs" ], + "char": "\ud83e\udda0", + fitzpatrick_scale: false, + category: "objects" + }, + petri_dish: { + keywords: [ "bacteria", "biology", "culture", "lab" ], + "char": "\ud83e\uddeb", + fitzpatrick_scale: false, + category: "objects" + }, + test_tube: { + keywords: [ "chemistry", "experiment", "lab", "science" ], + "char": "\ud83e\uddea", + fitzpatrick_scale: false, + category: "objects" + }, + thermometer: { + keywords: [ "weather", "temperature", "hot", "cold" ], + "char": "\ud83c\udf21", + fitzpatrick_scale: false, + category: "objects" + }, + broom: { + keywords: [ "cleaning", "sweeping", "witch" ], + "char": "\ud83e\uddf9", + fitzpatrick_scale: false, + category: "objects" + }, + basket: { + keywords: [ "laundry" ], + "char": "\ud83e\uddfa", + fitzpatrick_scale: false, + category: "objects" + }, + toilet_paper: { + keywords: [ "roll" ], + "char": "\ud83e\uddfb", + fitzpatrick_scale: false, + category: "objects" + }, + label: { + keywords: [ "sale", "tag" ], + "char": "\ud83c\udff7", + fitzpatrick_scale: false, + category: "objects" + }, + bookmark: { + keywords: [ "favorite", "label", "save" ], + "char": "\ud83d\udd16", + fitzpatrick_scale: false, + category: "objects" + }, + toilet: { + keywords: [ "restroom", "wc", "washroom", "bathroom", "potty" ], + "char": "\ud83d\udebd", + fitzpatrick_scale: false, + category: "objects" + }, + shower: { + keywords: [ "clean", "water", "bathroom" ], + "char": "\ud83d\udebf", + fitzpatrick_scale: false, + category: "objects" + }, + bathtub: { + keywords: [ "clean", "shower", "bathroom" ], + "char": "\ud83d\udec1", + fitzpatrick_scale: false, + category: "objects" + }, + soap: { + keywords: [ "bar", "bathing", "cleaning", "lather" ], + "char": "\ud83e\uddfc", + fitzpatrick_scale: false, + category: "objects" + }, + sponge: { + keywords: [ "absorbing", "cleaning", "porous" ], + "char": "\ud83e\uddfd", + fitzpatrick_scale: false, + category: "objects" + }, + lotion_bottle: { + keywords: [ "moisturizer", "sunscreen" ], + "char": "\ud83e\uddf4", + fitzpatrick_scale: false, + category: "objects" + }, + key: { + keywords: [ "lock", "door", "password" ], + "char": "\ud83d\udd11", + fitzpatrick_scale: false, + category: "objects" + }, + old_key: { + keywords: [ "lock", "door", "password" ], + "char": "\ud83d\udddd", + fitzpatrick_scale: false, + category: "objects" + }, + couch_and_lamp: { + keywords: [ "read", "chill" ], + "char": "\ud83d\udecb", + fitzpatrick_scale: false, + category: "objects" + }, + sleeping_bed: { + keywords: [ "bed", "rest" ], + "char": "\ud83d\udecc", + fitzpatrick_scale: true, + category: "objects" + }, + bed: { + keywords: [ "sleep", "rest" ], + "char": "\ud83d\udecf", + fitzpatrick_scale: false, + category: "objects" + }, + door: { + keywords: [ "house", "entry", "exit" ], + "char": "\ud83d\udeaa", + fitzpatrick_scale: false, + category: "objects" + }, + bellhop_bell: { + keywords: [ "service" ], + "char": "\ud83d\udece", + fitzpatrick_scale: false, + category: "objects" + }, + teddy_bear: { + keywords: [ "plush", "stuffed" ], + "char": "\ud83e\uddf8", + fitzpatrick_scale: false, + category: "objects" + }, + framed_picture: { + keywords: [ "photography" ], + "char": "\ud83d\uddbc", + fitzpatrick_scale: false, + category: "objects" + }, + world_map: { + keywords: [ "location", "direction" ], + "char": "\ud83d\uddfa", + fitzpatrick_scale: false, + category: "objects" + }, + parasol_on_ground: { + keywords: [ "weather", "summer" ], + "char": "\u26f1", + fitzpatrick_scale: false, + category: "objects" + }, + moyai: { + keywords: [ "rock", "easter island", "moai" ], + "char": "\ud83d\uddff", + fitzpatrick_scale: false, + category: "objects" + }, + shopping: { + keywords: [ "mall", "buy", "purchase" ], + "char": "\ud83d\udecd", + fitzpatrick_scale: false, + category: "objects" + }, + shopping_cart: { + keywords: [ "trolley" ], + "char": "\ud83d\uded2", + fitzpatrick_scale: false, + category: "objects" + }, + balloon: { + keywords: [ "party", "celebration", "birthday", "circus" ], + "char": "\ud83c\udf88", + fitzpatrick_scale: false, + category: "objects" + }, + flags: { + keywords: [ "fish", "japanese", "koinobori", "carp", "banner" ], + "char": "\ud83c\udf8f", + fitzpatrick_scale: false, + category: "objects" + }, + ribbon: { + keywords: [ "decoration", "pink", "girl", "bowtie" ], + "char": "\ud83c\udf80", + fitzpatrick_scale: false, + category: "objects" + }, + gift: { + keywords: [ "present", "birthday", "christmas", "xmas" ], + "char": "\ud83c\udf81", + fitzpatrick_scale: false, + category: "objects" + }, + confetti_ball: { + keywords: [ "festival", "party", "birthday", "circus" ], + "char": "\ud83c\udf8a", + fitzpatrick_scale: false, + category: "objects" + }, + tada: { + keywords: [ "party", "congratulations", "birthday", "magic", "circus", "celebration" ], + "char": "\ud83c\udf89", + fitzpatrick_scale: false, + category: "objects" + }, + dolls: { + keywords: [ "japanese", "toy", "kimono" ], + "char": "\ud83c\udf8e", + fitzpatrick_scale: false, + category: "objects" + }, + wind_chime: { + keywords: [ "nature", "ding", "spring", "bell" ], + "char": "\ud83c\udf90", + fitzpatrick_scale: false, + category: "objects" + }, + crossed_flags: { + keywords: [ "japanese", "nation", "country", "border" ], + "char": "\ud83c\udf8c", + fitzpatrick_scale: false, + category: "objects" + }, + izakaya_lantern: { + keywords: [ "light", "paper", "halloween", "spooky" ], + "char": "\ud83c\udfee", + fitzpatrick_scale: false, + category: "objects" + }, + red_envelope: { + keywords: [ "gift" ], + "char": "\ud83e\udde7", + fitzpatrick_scale: false, + category: "objects" + }, + email: { + keywords: [ "letter", "postal", "inbox", "communication" ], + "char": "\u2709\ufe0f", + fitzpatrick_scale: false, + category: "objects" + }, + envelope_with_arrow: { + keywords: [ "email", "communication" ], + "char": "\ud83d\udce9", + fitzpatrick_scale: false, + category: "objects" + }, + incoming_envelope: { + keywords: [ "email", "inbox" ], + "char": "\ud83d\udce8", + fitzpatrick_scale: false, + category: "objects" + }, + "e-mail": { + keywords: [ "communication", "inbox" ], + "char": "\ud83d\udce7", + fitzpatrick_scale: false, + category: "objects" + }, + love_letter: { + keywords: [ "email", "like", "affection", "envelope", "valentines" ], + "char": "\ud83d\udc8c", + fitzpatrick_scale: false, + category: "objects" + }, + postbox: { + keywords: [ "email", "letter", "envelope" ], + "char": "\ud83d\udcee", + fitzpatrick_scale: false, + category: "objects" + }, + mailbox_closed: { + keywords: [ "email", "communication", "inbox" ], + "char": "\ud83d\udcea", + fitzpatrick_scale: false, + category: "objects" + }, + mailbox: { + keywords: [ "email", "inbox", "communication" ], + "char": "\ud83d\udceb", + fitzpatrick_scale: false, + category: "objects" + }, + mailbox_with_mail: { + keywords: [ "email", "inbox", "communication" ], + "char": "\ud83d\udcec", + fitzpatrick_scale: false, + category: "objects" + }, + mailbox_with_no_mail: { + keywords: [ "email", "inbox" ], + "char": "\ud83d\udced", + fitzpatrick_scale: false, + category: "objects" + }, + "package": { + keywords: [ "mail", "gift", "cardboard", "box", "moving" ], + "char": "\ud83d\udce6", + fitzpatrick_scale: false, + category: "objects" + }, + postal_horn: { + keywords: [ "instrument", "music" ], + "char": "\ud83d\udcef", + fitzpatrick_scale: false, + category: "objects" + }, + inbox_tray: { + keywords: [ "email", "documents" ], + "char": "\ud83d\udce5", + fitzpatrick_scale: false, + category: "objects" + }, + outbox_tray: { + keywords: [ "inbox", "email" ], + "char": "\ud83d\udce4", + fitzpatrick_scale: false, + category: "objects" + }, + scroll: { + keywords: [ "documents", "ancient", "history", "paper" ], + "char": "\ud83d\udcdc", + fitzpatrick_scale: false, + category: "objects" + }, + page_with_curl: { + keywords: [ "documents", "office", "paper" ], + "char": "\ud83d\udcc3", + fitzpatrick_scale: false, + category: "objects" + }, + bookmark_tabs: { + keywords: [ "favorite", "save", "order", "tidy" ], + "char": "\ud83d\udcd1", + fitzpatrick_scale: false, + category: "objects" + }, + receipt: { + keywords: [ "accounting", "expenses" ], + "char": "\ud83e\uddfe", + fitzpatrick_scale: false, + category: "objects" + }, + bar_chart: { + keywords: [ "graph", "presentation", "stats" ], + "char": "\ud83d\udcca", + fitzpatrick_scale: false, + category: "objects" + }, + chart_with_upwards_trend: { + keywords: [ "graph", "presentation", "stats", "recovery", "business", "economics", "money", "sales", "good", "success" ], + "char": "\ud83d\udcc8", + fitzpatrick_scale: false, + category: "objects" + }, + chart_with_downwards_trend: { + keywords: [ "graph", "presentation", "stats", "recession", "business", "economics", "money", "sales", "bad", "failure" ], + "char": "\ud83d\udcc9", + fitzpatrick_scale: false, + category: "objects" + }, + page_facing_up: { + keywords: [ "documents", "office", "paper", "information" ], + "char": "\ud83d\udcc4", + fitzpatrick_scale: false, + category: "objects" + }, + date: { + keywords: [ "calendar", "schedule" ], + "char": "\ud83d\udcc5", + fitzpatrick_scale: false, + category: "objects" + }, + calendar: { + keywords: [ "schedule", "date", "planning" ], + "char": "\ud83d\udcc6", + fitzpatrick_scale: false, + category: "objects" + }, + spiral_calendar: { + keywords: [ "date", "schedule", "planning" ], + "char": "\ud83d\uddd3", + fitzpatrick_scale: false, + category: "objects" + }, + card_index: { + keywords: [ "business", "stationery" ], + "char": "\ud83d\udcc7", + fitzpatrick_scale: false, + category: "objects" + }, + card_file_box: { + keywords: [ "business", "stationery" ], + "char": "\ud83d\uddc3", + fitzpatrick_scale: false, + category: "objects" + }, + ballot_box: { + keywords: [ "election", "vote" ], + "char": "\ud83d\uddf3", + fitzpatrick_scale: false, + category: "objects" + }, + file_cabinet: { + keywords: [ "filing", "organizing" ], + "char": "\ud83d\uddc4", + fitzpatrick_scale: false, + category: "objects" + }, + clipboard: { + keywords: [ "stationery", "documents" ], + "char": "\ud83d\udccb", + fitzpatrick_scale: false, + category: "objects" + }, + spiral_notepad: { + keywords: [ "memo", "stationery" ], + "char": "\ud83d\uddd2", + fitzpatrick_scale: false, + category: "objects" + }, + file_folder: { + keywords: [ "documents", "business", "office" ], + "char": "\ud83d\udcc1", + fitzpatrick_scale: false, + category: "objects" + }, + open_file_folder: { + keywords: [ "documents", "load" ], + "char": "\ud83d\udcc2", + fitzpatrick_scale: false, + category: "objects" + }, + card_index_dividers: { + keywords: [ "organizing", "business", "stationery" ], + "char": "\ud83d\uddc2", + fitzpatrick_scale: false, + category: "objects" + }, + newspaper_roll: { + keywords: [ "press", "headline" ], + "char": "\ud83d\uddde", + fitzpatrick_scale: false, + category: "objects" + }, + newspaper: { + keywords: [ "press", "headline" ], + "char": "\ud83d\udcf0", + fitzpatrick_scale: false, + category: "objects" + }, + notebook: { + keywords: [ "stationery", "record", "notes", "paper", "study" ], + "char": "\ud83d\udcd3", + fitzpatrick_scale: false, + category: "objects" + }, + closed_book: { + keywords: [ "read", "library", "knowledge", "textbook", "learn" ], + "char": "\ud83d\udcd5", + fitzpatrick_scale: false, + category: "objects" + }, + green_book: { + keywords: [ "read", "library", "knowledge", "study" ], + "char": "\ud83d\udcd7", + fitzpatrick_scale: false, + category: "objects" + }, + blue_book: { + keywords: [ "read", "library", "knowledge", "learn", "study" ], + "char": "\ud83d\udcd8", + fitzpatrick_scale: false, + category: "objects" + }, + orange_book: { + keywords: [ "read", "library", "knowledge", "textbook", "study" ], + "char": "\ud83d\udcd9", + fitzpatrick_scale: false, + category: "objects" + }, + notebook_with_decorative_cover: { + keywords: [ "classroom", "notes", "record", "paper", "study" ], + "char": "\ud83d\udcd4", + fitzpatrick_scale: false, + category: "objects" + }, + ledger: { + keywords: [ "notes", "paper" ], + "char": "\ud83d\udcd2", + fitzpatrick_scale: false, + category: "objects" + }, + books: { + keywords: [ "literature", "library", "study" ], + "char": "\ud83d\udcda", + fitzpatrick_scale: false, + category: "objects" + }, + open_book: { + keywords: [ "book", "read", "library", "knowledge", "literature", "learn", "study" ], + "char": "\ud83d\udcd6", + fitzpatrick_scale: false, + category: "objects" + }, + safety_pin: { + keywords: [ "diaper" ], + "char": "\ud83e\uddf7", + fitzpatrick_scale: false, + category: "objects" + }, + link: { + keywords: [ "rings", "url" ], + "char": "\ud83d\udd17", + fitzpatrick_scale: false, + category: "objects" + }, + paperclip: { + keywords: [ "documents", "stationery" ], + "char": "\ud83d\udcce", + fitzpatrick_scale: false, + category: "objects" + }, + paperclips: { + keywords: [ "documents", "stationery" ], + "char": "\ud83d\udd87", + fitzpatrick_scale: false, + category: "objects" + }, + scissors: { + keywords: [ "stationery", "cut" ], + "char": "\u2702\ufe0f", + fitzpatrick_scale: false, + category: "objects" + }, + triangular_ruler: { + keywords: [ "stationery", "math", "architect", "sketch" ], + "char": "\ud83d\udcd0", + fitzpatrick_scale: false, + category: "objects" + }, + straight_ruler: { + keywords: [ "stationery", "calculate", "length", "math", "school", "drawing", "architect", "sketch" ], + "char": "\ud83d\udccf", + fitzpatrick_scale: false, + category: "objects" + }, + abacus: { + keywords: [ "calculation" ], + "char": "\ud83e\uddee", + fitzpatrick_scale: false, + category: "objects" + }, + pushpin: { + keywords: [ "stationery", "mark", "here" ], + "char": "\ud83d\udccc", + fitzpatrick_scale: false, + category: "objects" + }, + round_pushpin: { + keywords: [ "stationery", "location", "map", "here" ], + "char": "\ud83d\udccd", + fitzpatrick_scale: false, + category: "objects" + }, + triangular_flag_on_post: { + keywords: [ "mark", "milestone", "place" ], + "char": "\ud83d\udea9", + fitzpatrick_scale: false, + category: "objects" + }, + white_flag: { + keywords: [ "losing", "loser", "lost", "surrender", "give up", "fail" ], + "char": "\ud83c\udff3", + fitzpatrick_scale: false, + category: "objects" + }, + black_flag: { + keywords: [ "pirate" ], + "char": "\ud83c\udff4", + fitzpatrick_scale: false, + category: "objects" + }, + rainbow_flag: { + keywords: [ "flag", "rainbow", "pride", "gay", "lgbt", "glbt", "queer", "homosexual", "lesbian", "bisexual", "transgender" ], + "char": "\ud83c\udff3\ufe0f\u200d\ud83c\udf08", + fitzpatrick_scale: false, + category: "objects" + }, + closed_lock_with_key: { + keywords: [ "security", "privacy" ], + "char": "\ud83d\udd10", + fitzpatrick_scale: false, + category: "objects" + }, + lock: { + keywords: [ "security", "password", "padlock" ], + "char": "\ud83d\udd12", + fitzpatrick_scale: false, + category: "objects" + }, + unlock: { + keywords: [ "privacy", "security" ], + "char": "\ud83d\udd13", + fitzpatrick_scale: false, + category: "objects" + }, + lock_with_ink_pen: { + keywords: [ "security", "secret" ], + "char": "\ud83d\udd0f", + fitzpatrick_scale: false, + category: "objects" + }, + pen: { + keywords: [ "stationery", "writing", "write" ], + "char": "\ud83d\udd8a", + fitzpatrick_scale: false, + category: "objects" + }, + fountain_pen: { + keywords: [ "stationery", "writing", "write" ], + "char": "\ud83d\udd8b", + fitzpatrick_scale: false, + category: "objects" + }, + black_nib: { + keywords: [ "pen", "stationery", "writing", "write" ], + "char": "\u2712\ufe0f", + fitzpatrick_scale: false, + category: "objects" + }, + memo: { + keywords: [ "write", "documents", "stationery", "pencil", "paper", "writing", "legal", "exam", "quiz", "test", "study", "compose" ], + "char": "\ud83d\udcdd", + fitzpatrick_scale: false, + category: "objects" + }, + pencil2: { + keywords: [ "stationery", "write", "paper", "writing", "school", "study" ], + "char": "\u270f\ufe0f", + fitzpatrick_scale: false, + category: "objects" + }, + crayon: { + keywords: [ "drawing", "creativity" ], + "char": "\ud83d\udd8d", + fitzpatrick_scale: false, + category: "objects" + }, + paintbrush: { + keywords: [ "drawing", "creativity", "art" ], + "char": "\ud83d\udd8c", + fitzpatrick_scale: false, + category: "objects" + }, + mag: { + keywords: [ "search", "zoom", "find", "detective" ], + "char": "\ud83d\udd0d", + fitzpatrick_scale: false, + category: "objects" + }, + mag_right: { + keywords: [ "search", "zoom", "find", "detective" ], + "char": "\ud83d\udd0e", + fitzpatrick_scale: false, + category: "objects" + }, + heart: { + keywords: [ "love", "like", "valentines" ], + "char": "\u2764\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + orange_heart: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": "\ud83e\udde1", + fitzpatrick_scale: false, + category: "symbols" + }, + yellow_heart: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": "\ud83d\udc9b", + fitzpatrick_scale: false, + category: "symbols" + }, + green_heart: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": "\ud83d\udc9a", + fitzpatrick_scale: false, + category: "symbols" + }, + blue_heart: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": "\ud83d\udc99", + fitzpatrick_scale: false, + category: "symbols" + }, + purple_heart: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": "\ud83d\udc9c", + fitzpatrick_scale: false, + category: "symbols" + }, + black_heart: { + keywords: [ "evil" ], + "char": "\ud83d\udda4", + fitzpatrick_scale: false, + category: "symbols" + }, + broken_heart: { + keywords: [ "sad", "sorry", "break", "heart", "heartbreak" ], + "char": "\ud83d\udc94", + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_heart_exclamation: { + keywords: [ "decoration", "love" ], + "char": "\u2763", + fitzpatrick_scale: false, + category: "symbols" + }, + two_hearts: { + keywords: [ "love", "like", "affection", "valentines", "heart" ], + "char": "\ud83d\udc95", + fitzpatrick_scale: false, + category: "symbols" + }, + revolving_hearts: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": "\ud83d\udc9e", + fitzpatrick_scale: false, + category: "symbols" + }, + heartbeat: { + keywords: [ "love", "like", "affection", "valentines", "pink", "heart" ], + "char": "\ud83d\udc93", + fitzpatrick_scale: false, + category: "symbols" + }, + heartpulse: { + keywords: [ "like", "love", "affection", "valentines", "pink" ], + "char": "\ud83d\udc97", + fitzpatrick_scale: false, + category: "symbols" + }, + sparkling_heart: { + keywords: [ "love", "like", "affection", "valentines" ], + "char": "\ud83d\udc96", + fitzpatrick_scale: false, + category: "symbols" + }, + cupid: { + keywords: [ "love", "like", "heart", "affection", "valentines" ], + "char": "\ud83d\udc98", + fitzpatrick_scale: false, + category: "symbols" + }, + gift_heart: { + keywords: [ "love", "valentines" ], + "char": "\ud83d\udc9d", + fitzpatrick_scale: false, + category: "symbols" + }, + heart_decoration: { + keywords: [ "purple-square", "love", "like" ], + "char": "\ud83d\udc9f", + fitzpatrick_scale: false, + category: "symbols" + }, + peace_symbol: { + keywords: [ "hippie" ], + "char": "\u262e", + fitzpatrick_scale: false, + category: "symbols" + }, + latin_cross: { + keywords: [ "christianity" ], + "char": "\u271d", + fitzpatrick_scale: false, + category: "symbols" + }, + star_and_crescent: { + keywords: [ "islam" ], + "char": "\u262a", + fitzpatrick_scale: false, + category: "symbols" + }, + om: { + keywords: [ "hinduism", "buddhism", "sikhism", "jainism" ], + "char": "\ud83d\udd49", + fitzpatrick_scale: false, + category: "symbols" + }, + wheel_of_dharma: { + keywords: [ "hinduism", "buddhism", "sikhism", "jainism" ], + "char": "\u2638", + fitzpatrick_scale: false, + category: "symbols" + }, + star_of_david: { + keywords: [ "judaism" ], + "char": "\u2721", + fitzpatrick_scale: false, + category: "symbols" + }, + six_pointed_star: { + keywords: [ "purple-square", "religion", "jewish", "hexagram" ], + "char": "\ud83d\udd2f", + fitzpatrick_scale: false, + category: "symbols" + }, + menorah: { + keywords: [ "hanukkah", "candles", "jewish" ], + "char": "\ud83d\udd4e", + fitzpatrick_scale: false, + category: "symbols" + }, + yin_yang: { + keywords: [ "balance" ], + "char": "\u262f", + fitzpatrick_scale: false, + category: "symbols" + }, + orthodox_cross: { + keywords: [ "suppedaneum", "religion" ], + "char": "\u2626", + fitzpatrick_scale: false, + category: "symbols" + }, + place_of_worship: { + keywords: [ "religion", "church", "temple", "prayer" ], + "char": "\ud83d\uded0", + fitzpatrick_scale: false, + category: "symbols" + }, + ophiuchus: { + keywords: [ "sign", "purple-square", "constellation", "astrology" ], + "char": "\u26ce", + fitzpatrick_scale: false, + category: "symbols" + }, + aries: { + keywords: [ "sign", "purple-square", "zodiac", "astrology" ], + "char": "\u2648", + fitzpatrick_scale: false, + category: "symbols" + }, + taurus: { + keywords: [ "purple-square", "sign", "zodiac", "astrology" ], + "char": "\u2649", + fitzpatrick_scale: false, + category: "symbols" + }, + gemini: { + keywords: [ "sign", "zodiac", "purple-square", "astrology" ], + "char": "\u264a", + fitzpatrick_scale: false, + category: "symbols" + }, + cancer: { + keywords: [ "sign", "zodiac", "purple-square", "astrology" ], + "char": "\u264b", + fitzpatrick_scale: false, + category: "symbols" + }, + leo: { + keywords: [ "sign", "purple-square", "zodiac", "astrology" ], + "char": "\u264c", + fitzpatrick_scale: false, + category: "symbols" + }, + virgo: { + keywords: [ "sign", "zodiac", "purple-square", "astrology" ], + "char": "\u264d", + fitzpatrick_scale: false, + category: "symbols" + }, + libra: { + keywords: [ "sign", "purple-square", "zodiac", "astrology" ], + "char": "\u264e", + fitzpatrick_scale: false, + category: "symbols" + }, + scorpius: { + keywords: [ "sign", "zodiac", "purple-square", "astrology", "scorpio" ], + "char": "\u264f", + fitzpatrick_scale: false, + category: "symbols" + }, + sagittarius: { + keywords: [ "sign", "zodiac", "purple-square", "astrology" ], + "char": "\u2650", + fitzpatrick_scale: false, + category: "symbols" + }, + capricorn: { + keywords: [ "sign", "zodiac", "purple-square", "astrology" ], + "char": "\u2651", + fitzpatrick_scale: false, + category: "symbols" + }, + aquarius: { + keywords: [ "sign", "purple-square", "zodiac", "astrology" ], + "char": "\u2652", + fitzpatrick_scale: false, + category: "symbols" + }, + pisces: { + keywords: [ "purple-square", "sign", "zodiac", "astrology" ], + "char": "\u2653", + fitzpatrick_scale: false, + category: "symbols" + }, + id: { + keywords: [ "purple-square", "words" ], + "char": "\ud83c\udd94", + fitzpatrick_scale: false, + category: "symbols" + }, + atom_symbol: { + keywords: [ "science", "physics", "chemistry" ], + "char": "\u269b", + fitzpatrick_scale: false, + category: "symbols" + }, + u7a7a: { + keywords: [ "kanji", "japanese", "chinese", "empty", "sky", "blue-square" ], + "char": "\ud83c\ude33", + fitzpatrick_scale: false, + category: "symbols" + }, + u5272: { + keywords: [ "cut", "divide", "chinese", "kanji", "pink-square" ], + "char": "\ud83c\ude39", + fitzpatrick_scale: false, + category: "symbols" + }, + radioactive: { + keywords: [ "nuclear", "danger" ], + "char": "\u2622", + fitzpatrick_scale: false, + category: "symbols" + }, + biohazard: { + keywords: [ "danger" ], + "char": "\u2623", + fitzpatrick_scale: false, + category: "symbols" + }, + mobile_phone_off: { + keywords: [ "mute", "orange-square", "silence", "quiet" ], + "char": "\ud83d\udcf4", + fitzpatrick_scale: false, + category: "symbols" + }, + vibration_mode: { + keywords: [ "orange-square", "phone" ], + "char": "\ud83d\udcf3", + fitzpatrick_scale: false, + category: "symbols" + }, + u6709: { + keywords: [ "orange-square", "chinese", "have", "kanji" ], + "char": "\ud83c\ude36", + fitzpatrick_scale: false, + category: "symbols" + }, + u7121: { + keywords: [ "nothing", "chinese", "kanji", "japanese", "orange-square" ], + "char": "\ud83c\ude1a", + fitzpatrick_scale: false, + category: "symbols" + }, + u7533: { + keywords: [ "chinese", "japanese", "kanji", "orange-square" ], + "char": "\ud83c\ude38", + fitzpatrick_scale: false, + category: "symbols" + }, + u55b6: { + keywords: [ "japanese", "opening hours", "orange-square" ], + "char": "\ud83c\ude3a", + fitzpatrick_scale: false, + category: "symbols" + }, + u6708: { + keywords: [ "chinese", "month", "moon", "japanese", "orange-square", "kanji" ], + "char": "\ud83c\ude37\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + eight_pointed_black_star: { + keywords: [ "orange-square", "shape", "polygon" ], + "char": "\u2734\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + vs: { + keywords: [ "words", "orange-square" ], + "char": "\ud83c\udd9a", + fitzpatrick_scale: false, + category: "symbols" + }, + accept: { + keywords: [ "ok", "good", "chinese", "kanji", "agree", "yes", "orange-circle" ], + "char": "\ud83c\ude51", + fitzpatrick_scale: false, + category: "symbols" + }, + white_flower: { + keywords: [ "japanese", "spring" ], + "char": "\ud83d\udcae", + fitzpatrick_scale: false, + category: "symbols" + }, + ideograph_advantage: { + keywords: [ "chinese", "kanji", "obtain", "get", "circle" ], + "char": "\ud83c\ude50", + fitzpatrick_scale: false, + category: "symbols" + }, + secret: { + keywords: [ "privacy", "chinese", "sshh", "kanji", "red-circle" ], + "char": "\u3299\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + congratulations: { + keywords: [ "chinese", "kanji", "japanese", "red-circle" ], + "char": "\u3297\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + u5408: { + keywords: [ "japanese", "chinese", "join", "kanji", "red-square" ], + "char": "\ud83c\ude34", + fitzpatrick_scale: false, + category: "symbols" + }, + u6e80: { + keywords: [ "full", "chinese", "japanese", "red-square", "kanji" ], + "char": "\ud83c\ude35", + fitzpatrick_scale: false, + category: "symbols" + }, + u7981: { + keywords: [ "kanji", "japanese", "chinese", "forbidden", "limit", "restricted", "red-square" ], + "char": "\ud83c\ude32", + fitzpatrick_scale: false, + category: "symbols" + }, + a: { + keywords: [ "red-square", "alphabet", "letter" ], + "char": "\ud83c\udd70\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + b: { + keywords: [ "red-square", "alphabet", "letter" ], + "char": "\ud83c\udd71\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + ab: { + keywords: [ "red-square", "alphabet" ], + "char": "\ud83c\udd8e", + fitzpatrick_scale: false, + category: "symbols" + }, + cl: { + keywords: [ "alphabet", "words", "red-square" ], + "char": "\ud83c\udd91", + fitzpatrick_scale: false, + category: "symbols" + }, + o2: { + keywords: [ "alphabet", "red-square", "letter" ], + "char": "\ud83c\udd7e\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + sos: { + keywords: [ "help", "red-square", "words", "emergency", "911" ], + "char": "\ud83c\udd98", + fitzpatrick_scale: false, + category: "symbols" + }, + no_entry: { + keywords: [ "limit", "security", "privacy", "bad", "denied", "stop", "circle" ], + "char": "\u26d4", + fitzpatrick_scale: false, + category: "symbols" + }, + name_badge: { + keywords: [ "fire", "forbid" ], + "char": "\ud83d\udcdb", + fitzpatrick_scale: false, + category: "symbols" + }, + no_entry_sign: { + keywords: [ "forbid", "stop", "limit", "denied", "disallow", "circle" ], + "char": "\ud83d\udeab", + fitzpatrick_scale: false, + category: "symbols" + }, + x: { + keywords: [ "no", "delete", "remove", "cancel", "red" ], + "char": "\u274c", + fitzpatrick_scale: false, + category: "symbols" + }, + o: { + keywords: [ "circle", "round" ], + "char": "\u2b55", + fitzpatrick_scale: false, + category: "symbols" + }, + stop_sign: { + keywords: [ "stop" ], + "char": "\ud83d\uded1", + fitzpatrick_scale: false, + category: "symbols" + }, + anger: { + keywords: [ "angry", "mad" ], + "char": "\ud83d\udca2", + fitzpatrick_scale: false, + category: "symbols" + }, + hotsprings: { + keywords: [ "bath", "warm", "relax" ], + "char": "\u2668\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + no_pedestrians: { + keywords: [ "rules", "crossing", "walking", "circle" ], + "char": "\ud83d\udeb7", + fitzpatrick_scale: false, + category: "symbols" + }, + do_not_litter: { + keywords: [ "trash", "bin", "garbage", "circle" ], + "char": "\ud83d\udeaf", + fitzpatrick_scale: false, + category: "symbols" + }, + no_bicycles: { + keywords: [ "cyclist", "prohibited", "circle" ], + "char": "\ud83d\udeb3", + fitzpatrick_scale: false, + category: "symbols" + }, + "non-potable_water": { + keywords: [ "drink", "faucet", "tap", "circle" ], + "char": "\ud83d\udeb1", + fitzpatrick_scale: false, + category: "symbols" + }, + underage: { + keywords: [ "18", "drink", "pub", "night", "minor", "circle" ], + "char": "\ud83d\udd1e", + fitzpatrick_scale: false, + category: "symbols" + }, + no_mobile_phones: { + keywords: [ "iphone", "mute", "circle" ], + "char": "\ud83d\udcf5", + fitzpatrick_scale: false, + category: "symbols" + }, + exclamation: { + keywords: [ "heavy_exclamation_mark", "danger", "surprise", "punctuation", "wow", "warning" ], + "char": "\u2757", + fitzpatrick_scale: false, + category: "symbols" + }, + grey_exclamation: { + keywords: [ "surprise", "punctuation", "gray", "wow", "warning" ], + "char": "\u2755", + fitzpatrick_scale: false, + category: "symbols" + }, + question: { + keywords: [ "doubt", "confused" ], + "char": "\u2753", + fitzpatrick_scale: false, + category: "symbols" + }, + grey_question: { + keywords: [ "doubts", "gray", "huh", "confused" ], + "char": "\u2754", + fitzpatrick_scale: false, + category: "symbols" + }, + bangbang: { + keywords: [ "exclamation", "surprise" ], + "char": "\u203c\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + interrobang: { + keywords: [ "wat", "punctuation", "surprise" ], + "char": "\u2049\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + 100: { + keywords: [ "score", "perfect", "numbers", "century", "exam", "quiz", "test", "pass", "hundred" ], + "char": "\ud83d\udcaf", + fitzpatrick_scale: false, + category: "symbols" + }, + low_brightness: { + keywords: [ "sun", "afternoon", "warm", "summer" ], + "char": "\ud83d\udd05", + fitzpatrick_scale: false, + category: "symbols" + }, + high_brightness: { + keywords: [ "sun", "light" ], + "char": "\ud83d\udd06", + fitzpatrick_scale: false, + category: "symbols" + }, + trident: { + keywords: [ "weapon", "spear" ], + "char": "\ud83d\udd31", + fitzpatrick_scale: false, + category: "symbols" + }, + fleur_de_lis: { + keywords: [ "decorative", "scout" ], + "char": "\u269c", + fitzpatrick_scale: false, + category: "symbols" + }, + part_alternation_mark: { + keywords: [ "graph", "presentation", "stats", "business", "economics", "bad" ], + "char": "\u303d\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + warning: { + keywords: [ "exclamation", "wip", "alert", "error", "problem", "issue" ], + "char": "\u26a0\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + children_crossing: { + keywords: [ "school", "warning", "danger", "sign", "driving", "yellow-diamond" ], + "char": "\ud83d\udeb8", + fitzpatrick_scale: false, + category: "symbols" + }, + beginner: { + keywords: [ "badge", "shield" ], + "char": "\ud83d\udd30", + fitzpatrick_scale: false, + category: "symbols" + }, + recycle: { + keywords: [ "arrow", "environment", "garbage", "trash" ], + "char": "\u267b\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + u6307: { + keywords: [ "chinese", "point", "green-square", "kanji" ], + "char": "\ud83c\ude2f", + fitzpatrick_scale: false, + category: "symbols" + }, + chart: { + keywords: [ "green-square", "graph", "presentation", "stats" ], + "char": "\ud83d\udcb9", + fitzpatrick_scale: false, + category: "symbols" + }, + sparkle: { + keywords: [ "stars", "green-square", "awesome", "good", "fireworks" ], + "char": "\u2747\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + eight_spoked_asterisk: { + keywords: [ "star", "sparkle", "green-square" ], + "char": "\u2733\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + negative_squared_cross_mark: { + keywords: [ "x", "green-square", "no", "deny" ], + "char": "\u274e", + fitzpatrick_scale: false, + category: "symbols" + }, + white_check_mark: { + keywords: [ "green-square", "ok", "agree", "vote", "election", "answer", "tick" ], + "char": "\u2705", + fitzpatrick_scale: false, + category: "symbols" + }, + diamond_shape_with_a_dot_inside: { + keywords: [ "jewel", "blue", "gem", "crystal", "fancy" ], + "char": "\ud83d\udca0", + fitzpatrick_scale: false, + category: "symbols" + }, + cyclone: { + keywords: [ "weather", "swirl", "blue", "cloud", "vortex", "spiral", "whirlpool", "spin", "tornado", "hurricane", "typhoon" ], + "char": "\ud83c\udf00", + fitzpatrick_scale: false, + category: "symbols" + }, + loop: { + keywords: [ "tape", "cassette" ], + "char": "\u27bf", + fitzpatrick_scale: false, + category: "symbols" + }, + globe_with_meridians: { + keywords: [ "earth", "international", "world", "internet", "interweb", "i18n" ], + "char": "\ud83c\udf10", + fitzpatrick_scale: false, + category: "symbols" + }, + m: { + keywords: [ "alphabet", "blue-circle", "letter" ], + "char": "\u24c2\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + atm: { + keywords: [ "money", "sales", "cash", "blue-square", "payment", "bank" ], + "char": "\ud83c\udfe7", + fitzpatrick_scale: false, + category: "symbols" + }, + sa: { + keywords: [ "japanese", "blue-square", "katakana" ], + "char": "\ud83c\ude02\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + passport_control: { + keywords: [ "custom", "blue-square" ], + "char": "\ud83d\udec2", + fitzpatrick_scale: false, + category: "symbols" + }, + customs: { + keywords: [ "passport", "border", "blue-square" ], + "char": "\ud83d\udec3", + fitzpatrick_scale: false, + category: "symbols" + }, + baggage_claim: { + keywords: [ "blue-square", "airport", "transport" ], + "char": "\ud83d\udec4", + fitzpatrick_scale: false, + category: "symbols" + }, + left_luggage: { + keywords: [ "blue-square", "travel" ], + "char": "\ud83d\udec5", + fitzpatrick_scale: false, + category: "symbols" + }, + wheelchair: { + keywords: [ "blue-square", "disabled", "a11y", "accessibility" ], + "char": "\u267f", + fitzpatrick_scale: false, + category: "symbols" + }, + no_smoking: { + keywords: [ "cigarette", "blue-square", "smell", "smoke" ], + "char": "\ud83d\udead", + fitzpatrick_scale: false, + category: "symbols" + }, + wc: { + keywords: [ "toilet", "restroom", "blue-square" ], + "char": "\ud83d\udebe", + fitzpatrick_scale: false, + category: "symbols" + }, + parking: { + keywords: [ "cars", "blue-square", "alphabet", "letter" ], + "char": "\ud83c\udd7f\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + potable_water: { + keywords: [ "blue-square", "liquid", "restroom", "cleaning", "faucet" ], + "char": "\ud83d\udeb0", + fitzpatrick_scale: false, + category: "symbols" + }, + mens: { + keywords: [ "toilet", "restroom", "wc", "blue-square", "gender", "male" ], + "char": "\ud83d\udeb9", + fitzpatrick_scale: false, + category: "symbols" + }, + womens: { + keywords: [ "purple-square", "woman", "female", "toilet", "loo", "restroom", "gender" ], + "char": "\ud83d\udeba", + fitzpatrick_scale: false, + category: "symbols" + }, + baby_symbol: { + keywords: [ "orange-square", "child" ], + "char": "\ud83d\udebc", + fitzpatrick_scale: false, + category: "symbols" + }, + restroom: { + keywords: [ "blue-square", "toilet", "refresh", "wc", "gender" ], + "char": "\ud83d\udebb", + fitzpatrick_scale: false, + category: "symbols" + }, + put_litter_in_its_place: { + keywords: [ "blue-square", "sign", "human", "info" ], + "char": "\ud83d\udeae", + fitzpatrick_scale: false, + category: "symbols" + }, + cinema: { + keywords: [ "blue-square", "record", "film", "movie", "curtain", "stage", "theater" ], + "char": "\ud83c\udfa6", + fitzpatrick_scale: false, + category: "symbols" + }, + signal_strength: { + keywords: [ "blue-square", "reception", "phone", "internet", "connection", "wifi", "bluetooth", "bars" ], + "char": "\ud83d\udcf6", + fitzpatrick_scale: false, + category: "symbols" + }, + koko: { + keywords: [ "blue-square", "here", "katakana", "japanese", "destination" ], + "char": "\ud83c\ude01", + fitzpatrick_scale: false, + category: "symbols" + }, + ng: { + keywords: [ "blue-square", "words", "shape", "icon" ], + "char": "\ud83c\udd96", + fitzpatrick_scale: false, + category: "symbols" + }, + ok: { + keywords: [ "good", "agree", "yes", "blue-square" ], + "char": "\ud83c\udd97", + fitzpatrick_scale: false, + category: "symbols" + }, + up: { + keywords: [ "blue-square", "above", "high" ], + "char": "\ud83c\udd99", + fitzpatrick_scale: false, + category: "symbols" + }, + cool: { + keywords: [ "words", "blue-square" ], + "char": "\ud83c\udd92", + fitzpatrick_scale: false, + category: "symbols" + }, + "new": { + keywords: [ "blue-square", "words", "start" ], + "char": "\ud83c\udd95", + fitzpatrick_scale: false, + category: "symbols" + }, + free: { + keywords: [ "blue-square", "words" ], + "char": "\ud83c\udd93", + fitzpatrick_scale: false, + category: "symbols" + }, + zero: { + keywords: [ "0", "numbers", "blue-square", "null" ], + "char": "0\ufe0f\u20e3", + fitzpatrick_scale: false, + category: "symbols" + }, + one: { + keywords: [ "blue-square", "numbers", "1" ], + "char": "1\ufe0f\u20e3", + fitzpatrick_scale: false, + category: "symbols" + }, + two: { + keywords: [ "numbers", "2", "prime", "blue-square" ], + "char": "2\ufe0f\u20e3", + fitzpatrick_scale: false, + category: "symbols" + }, + three: { + keywords: [ "3", "numbers", "prime", "blue-square" ], + "char": "3\ufe0f\u20e3", + fitzpatrick_scale: false, + category: "symbols" + }, + four: { + keywords: [ "4", "numbers", "blue-square" ], + "char": "4\ufe0f\u20e3", + fitzpatrick_scale: false, + category: "symbols" + }, + five: { + keywords: [ "5", "numbers", "blue-square", "prime" ], + "char": "5\ufe0f\u20e3", + fitzpatrick_scale: false, + category: "symbols" + }, + six: { + keywords: [ "6", "numbers", "blue-square" ], + "char": "6\ufe0f\u20e3", + fitzpatrick_scale: false, + category: "symbols" + }, + seven: { + keywords: [ "7", "numbers", "blue-square", "prime" ], + "char": "7\ufe0f\u20e3", + fitzpatrick_scale: false, + category: "symbols" + }, + eight: { + keywords: [ "8", "blue-square", "numbers" ], + "char": "8\ufe0f\u20e3", + fitzpatrick_scale: false, + category: "symbols" + }, + nine: { + keywords: [ "blue-square", "numbers", "9" ], + "char": "9\ufe0f\u20e3", + fitzpatrick_scale: false, + category: "symbols" + }, + keycap_ten: { + keywords: [ "numbers", "10", "blue-square" ], + "char": "\ud83d\udd1f", + fitzpatrick_scale: false, + category: "symbols" + }, + asterisk: { + keywords: [ "star", "keycap" ], + "char": "*\u20e3", + fitzpatrick_scale: false, + category: "symbols" + }, + 1234: { + keywords: [ "numbers", "blue-square" ], + "char": "\ud83d\udd22", + fitzpatrick_scale: false, + category: "symbols" + }, + eject_button: { + keywords: [ "blue-square" ], + "char": "\u23cf\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_forward: { + keywords: [ "blue-square", "right", "direction", "play" ], + "char": "\u25b6\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + pause_button: { + keywords: [ "pause", "blue-square" ], + "char": "\u23f8", + fitzpatrick_scale: false, + category: "symbols" + }, + next_track_button: { + keywords: [ "forward", "next", "blue-square" ], + "char": "\u23ed", + fitzpatrick_scale: false, + category: "symbols" + }, + stop_button: { + keywords: [ "blue-square" ], + "char": "\u23f9", + fitzpatrick_scale: false, + category: "symbols" + }, + record_button: { + keywords: [ "blue-square" ], + "char": "\u23fa", + fitzpatrick_scale: false, + category: "symbols" + }, + play_or_pause_button: { + keywords: [ "blue-square", "play", "pause" ], + "char": "\u23ef", + fitzpatrick_scale: false, + category: "symbols" + }, + previous_track_button: { + keywords: [ "backward" ], + "char": "\u23ee", + fitzpatrick_scale: false, + category: "symbols" + }, + fast_forward: { + keywords: [ "blue-square", "play", "speed", "continue" ], + "char": "\u23e9", + fitzpatrick_scale: false, + category: "symbols" + }, + rewind: { + keywords: [ "play", "blue-square" ], + "char": "\u23ea", + fitzpatrick_scale: false, + category: "symbols" + }, + twisted_rightwards_arrows: { + keywords: [ "blue-square", "shuffle", "music", "random" ], + "char": "\ud83d\udd00", + fitzpatrick_scale: false, + category: "symbols" + }, + repeat: { + keywords: [ "loop", "record" ], + "char": "\ud83d\udd01", + fitzpatrick_scale: false, + category: "symbols" + }, + repeat_one: { + keywords: [ "blue-square", "loop" ], + "char": "\ud83d\udd02", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_backward: { + keywords: [ "blue-square", "left", "direction" ], + "char": "\u25c0\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_up_small: { + keywords: [ "blue-square", "triangle", "direction", "point", "forward", "top" ], + "char": "\ud83d\udd3c", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_down_small: { + keywords: [ "blue-square", "direction", "bottom" ], + "char": "\ud83d\udd3d", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_double_up: { + keywords: [ "blue-square", "direction", "top" ], + "char": "\u23eb", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_double_down: { + keywords: [ "blue-square", "direction", "bottom" ], + "char": "\u23ec", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_right: { + keywords: [ "blue-square", "next" ], + "char": "\u27a1\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_left: { + keywords: [ "blue-square", "previous", "back" ], + "char": "\u2b05\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_up: { + keywords: [ "blue-square", "continue", "top", "direction" ], + "char": "\u2b06\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_down: { + keywords: [ "blue-square", "direction", "bottom" ], + "char": "\u2b07\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_upper_right: { + keywords: [ "blue-square", "point", "direction", "diagonal", "northeast" ], + "char": "\u2197\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_lower_right: { + keywords: [ "blue-square", "direction", "diagonal", "southeast" ], + "char": "\u2198\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_lower_left: { + keywords: [ "blue-square", "direction", "diagonal", "southwest" ], + "char": "\u2199\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_upper_left: { + keywords: [ "blue-square", "point", "direction", "diagonal", "northwest" ], + "char": "\u2196\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_up_down: { + keywords: [ "blue-square", "direction", "way", "vertical" ], + "char": "\u2195\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + left_right_arrow: { + keywords: [ "shape", "direction", "horizontal", "sideways" ], + "char": "\u2194\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrows_counterclockwise: { + keywords: [ "blue-square", "sync", "cycle" ], + "char": "\ud83d\udd04", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_right_hook: { + keywords: [ "blue-square", "return", "rotate", "direction" ], + "char": "\u21aa\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + leftwards_arrow_with_hook: { + keywords: [ "back", "return", "blue-square", "undo", "enter" ], + "char": "\u21a9\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_heading_up: { + keywords: [ "blue-square", "direction", "top" ], + "char": "\u2934\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrow_heading_down: { + keywords: [ "blue-square", "direction", "bottom" ], + "char": "\u2935\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + hash: { + keywords: [ "symbol", "blue-square", "twitter" ], + "char": "#\ufe0f\u20e3", + fitzpatrick_scale: false, + category: "symbols" + }, + information_source: { + keywords: [ "blue-square", "alphabet", "letter" ], + "char": "\u2139\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + abc: { + keywords: [ "blue-square", "alphabet" ], + "char": "\ud83d\udd24", + fitzpatrick_scale: false, + category: "symbols" + }, + abcd: { + keywords: [ "blue-square", "alphabet" ], + "char": "\ud83d\udd21", + fitzpatrick_scale: false, + category: "symbols" + }, + capital_abcd: { + keywords: [ "alphabet", "words", "blue-square" ], + "char": "\ud83d\udd20", + fitzpatrick_scale: false, + category: "symbols" + }, + symbols: { + keywords: [ "blue-square", "music", "note", "ampersand", "percent", "glyphs", "characters" ], + "char": "\ud83d\udd23", + fitzpatrick_scale: false, + category: "symbols" + }, + musical_note: { + keywords: [ "score", "tone", "sound" ], + "char": "\ud83c\udfb5", + fitzpatrick_scale: false, + category: "symbols" + }, + notes: { + keywords: [ "music", "score" ], + "char": "\ud83c\udfb6", + fitzpatrick_scale: false, + category: "symbols" + }, + wavy_dash: { + keywords: [ "draw", "line", "moustache", "mustache", "squiggle", "scribble" ], + "char": "\u3030\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + curly_loop: { + keywords: [ "scribble", "draw", "shape", "squiggle" ], + "char": "\u27b0", + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_check_mark: { + keywords: [ "ok", "nike", "answer", "yes", "tick" ], + "char": "\u2714\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + arrows_clockwise: { + keywords: [ "sync", "cycle", "round", "repeat" ], + "char": "\ud83d\udd03", + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_plus_sign: { + keywords: [ "math", "calculation", "addition", "more", "increase" ], + "char": "\u2795", + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_minus_sign: { + keywords: [ "math", "calculation", "subtract", "less" ], + "char": "\u2796", + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_division_sign: { + keywords: [ "divide", "math", "calculation" ], + "char": "\u2797", + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_multiplication_x: { + keywords: [ "math", "calculation" ], + "char": "\u2716\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + infinity: { + keywords: [ "forever" ], + "char": "\u267e", + fitzpatrick_scale: false, + category: "symbols" + }, + heavy_dollar_sign: { + keywords: [ "money", "sales", "payment", "currency", "buck" ], + "char": "\ud83d\udcb2", + fitzpatrick_scale: false, + category: "symbols" + }, + currency_exchange: { + keywords: [ "money", "sales", "dollar", "travel" ], + "char": "\ud83d\udcb1", + fitzpatrick_scale: false, + category: "symbols" + }, + copyright: { + keywords: [ "ip", "license", "circle", "law", "legal" ], + "char": "\xa9\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + registered: { + keywords: [ "alphabet", "circle" ], + "char": "\xae\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + tm: { + keywords: [ "trademark", "brand", "law", "legal" ], + "char": "\u2122\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + end: { + keywords: [ "words", "arrow" ], + "char": "\ud83d\udd1a", + fitzpatrick_scale: false, + category: "symbols" + }, + back: { + keywords: [ "arrow", "words", "return" ], + "char": "\ud83d\udd19", + fitzpatrick_scale: false, + category: "symbols" + }, + on: { + keywords: [ "arrow", "words" ], + "char": "\ud83d\udd1b", + fitzpatrick_scale: false, + category: "symbols" + }, + top: { + keywords: [ "words", "blue-square" ], + "char": "\ud83d\udd1d", + fitzpatrick_scale: false, + category: "symbols" + }, + soon: { + keywords: [ "arrow", "words" ], + "char": "\ud83d\udd1c", + fitzpatrick_scale: false, + category: "symbols" + }, + ballot_box_with_check: { + keywords: [ "ok", "agree", "confirm", "black-square", "vote", "election", "yes", "tick" ], + "char": "\u2611\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + radio_button: { + keywords: [ "input", "old", "music", "circle" ], + "char": "\ud83d\udd18", + fitzpatrick_scale: false, + category: "symbols" + }, + white_circle: { + keywords: [ "shape", "round" ], + "char": "\u26aa", + fitzpatrick_scale: false, + category: "symbols" + }, + black_circle: { + keywords: [ "shape", "button", "round" ], + "char": "\u26ab", + fitzpatrick_scale: false, + category: "symbols" + }, + red_circle: { + keywords: [ "shape", "error", "danger" ], + "char": "\ud83d\udd34", + fitzpatrick_scale: false, + category: "symbols" + }, + large_blue_circle: { + keywords: [ "shape", "icon", "button" ], + "char": "\ud83d\udd35", + fitzpatrick_scale: false, + category: "symbols" + }, + small_orange_diamond: { + keywords: [ "shape", "jewel", "gem" ], + "char": "\ud83d\udd38", + fitzpatrick_scale: false, + category: "symbols" + }, + small_blue_diamond: { + keywords: [ "shape", "jewel", "gem" ], + "char": "\ud83d\udd39", + fitzpatrick_scale: false, + category: "symbols" + }, + large_orange_diamond: { + keywords: [ "shape", "jewel", "gem" ], + "char": "\ud83d\udd36", + fitzpatrick_scale: false, + category: "symbols" + }, + large_blue_diamond: { + keywords: [ "shape", "jewel", "gem" ], + "char": "\ud83d\udd37", + fitzpatrick_scale: false, + category: "symbols" + }, + small_red_triangle: { + keywords: [ "shape", "direction", "up", "top" ], + "char": "\ud83d\udd3a", + fitzpatrick_scale: false, + category: "symbols" + }, + black_small_square: { + keywords: [ "shape", "icon" ], + "char": "\u25aa\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + white_small_square: { + keywords: [ "shape", "icon" ], + "char": "\u25ab\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + black_large_square: { + keywords: [ "shape", "icon", "button" ], + "char": "\u2b1b", + fitzpatrick_scale: false, + category: "symbols" + }, + white_large_square: { + keywords: [ "shape", "icon", "stone", "button" ], + "char": "\u2b1c", + fitzpatrick_scale: false, + category: "symbols" + }, + small_red_triangle_down: { + keywords: [ "shape", "direction", "bottom" ], + "char": "\ud83d\udd3b", + fitzpatrick_scale: false, + category: "symbols" + }, + black_medium_square: { + keywords: [ "shape", "button", "icon" ], + "char": "\u25fc\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + white_medium_square: { + keywords: [ "shape", "stone", "icon" ], + "char": "\u25fb\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + black_medium_small_square: { + keywords: [ "icon", "shape", "button" ], + "char": "\u25fe", + fitzpatrick_scale: false, + category: "symbols" + }, + white_medium_small_square: { + keywords: [ "shape", "stone", "icon", "button" ], + "char": "\u25fd", + fitzpatrick_scale: false, + category: "symbols" + }, + black_square_button: { + keywords: [ "shape", "input", "frame" ], + "char": "\ud83d\udd32", + fitzpatrick_scale: false, + category: "symbols" + }, + white_square_button: { + keywords: [ "shape", "input" ], + "char": "\ud83d\udd33", + fitzpatrick_scale: false, + category: "symbols" + }, + speaker: { + keywords: [ "sound", "volume", "silence", "broadcast" ], + "char": "\ud83d\udd08", + fitzpatrick_scale: false, + category: "symbols" + }, + sound: { + keywords: [ "volume", "speaker", "broadcast" ], + "char": "\ud83d\udd09", + fitzpatrick_scale: false, + category: "symbols" + }, + loud_sound: { + keywords: [ "volume", "noise", "noisy", "speaker", "broadcast" ], + "char": "\ud83d\udd0a", + fitzpatrick_scale: false, + category: "symbols" + }, + mute: { + keywords: [ "sound", "volume", "silence", "quiet" ], + "char": "\ud83d\udd07", + fitzpatrick_scale: false, + category: "symbols" + }, + mega: { + keywords: [ "sound", "speaker", "volume" ], + "char": "\ud83d\udce3", + fitzpatrick_scale: false, + category: "symbols" + }, + loudspeaker: { + keywords: [ "volume", "sound" ], + "char": "\ud83d\udce2", + fitzpatrick_scale: false, + category: "symbols" + }, + bell: { + keywords: [ "sound", "notification", "christmas", "xmas", "chime" ], + "char": "\ud83d\udd14", + fitzpatrick_scale: false, + category: "symbols" + }, + no_bell: { + keywords: [ "sound", "volume", "mute", "quiet", "silent" ], + "char": "\ud83d\udd15", + fitzpatrick_scale: false, + category: "symbols" + }, + black_joker: { + keywords: [ "poker", "cards", "game", "play", "magic" ], + "char": "\ud83c\udccf", + fitzpatrick_scale: false, + category: "symbols" + }, + mahjong: { + keywords: [ "game", "play", "chinese", "kanji" ], + "char": "\ud83c\udc04", + fitzpatrick_scale: false, + category: "symbols" + }, + spades: { + keywords: [ "poker", "cards", "suits", "magic" ], + "char": "\u2660\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + clubs: { + keywords: [ "poker", "cards", "magic", "suits" ], + "char": "\u2663\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + hearts: { + keywords: [ "poker", "cards", "magic", "suits" ], + "char": "\u2665\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + diamonds: { + keywords: [ "poker", "cards", "magic", "suits" ], + "char": "\u2666\ufe0f", + fitzpatrick_scale: false, + category: "symbols" + }, + flower_playing_cards: { + keywords: [ "game", "sunset", "red" ], + "char": "\ud83c\udfb4", + fitzpatrick_scale: false, + category: "symbols" + }, + thought_balloon: { + keywords: [ "bubble", "cloud", "speech", "thinking", "dream" ], + "char": "\ud83d\udcad", + fitzpatrick_scale: false, + category: "symbols" + }, + right_anger_bubble: { + keywords: [ "caption", "speech", "thinking", "mad" ], + "char": "\ud83d\uddef", + fitzpatrick_scale: false, + category: "symbols" + }, + speech_balloon: { + keywords: [ "bubble", "words", "message", "talk", "chatting" ], + "char": "\ud83d\udcac", + fitzpatrick_scale: false, + category: "symbols" + }, + left_speech_bubble: { + keywords: [ "words", "message", "talk", "chatting" ], + "char": "\ud83d\udde8", + fitzpatrick_scale: false, + category: "symbols" + }, + clock1: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd50", + fitzpatrick_scale: false, + category: "symbols" + }, + clock2: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd51", + fitzpatrick_scale: false, + category: "symbols" + }, + clock3: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd52", + fitzpatrick_scale: false, + category: "symbols" + }, + clock4: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd53", + fitzpatrick_scale: false, + category: "symbols" + }, + clock5: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd54", + fitzpatrick_scale: false, + category: "symbols" + }, + clock6: { + keywords: [ "time", "late", "early", "schedule", "dawn", "dusk" ], + "char": "\ud83d\udd55", + fitzpatrick_scale: false, + category: "symbols" + }, + clock7: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd56", + fitzpatrick_scale: false, + category: "symbols" + }, + clock8: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd57", + fitzpatrick_scale: false, + category: "symbols" + }, + clock9: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd58", + fitzpatrick_scale: false, + category: "symbols" + }, + clock10: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd59", + fitzpatrick_scale: false, + category: "symbols" + }, + clock11: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd5a", + fitzpatrick_scale: false, + category: "symbols" + }, + clock12: { + keywords: [ "time", "noon", "midnight", "midday", "late", "early", "schedule" ], + "char": "\ud83d\udd5b", + fitzpatrick_scale: false, + category: "symbols" + }, + clock130: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd5c", + fitzpatrick_scale: false, + category: "symbols" + }, + clock230: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd5d", + fitzpatrick_scale: false, + category: "symbols" + }, + clock330: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd5e", + fitzpatrick_scale: false, + category: "symbols" + }, + clock430: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd5f", + fitzpatrick_scale: false, + category: "symbols" + }, + clock530: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd60", + fitzpatrick_scale: false, + category: "symbols" + }, + clock630: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd61", + fitzpatrick_scale: false, + category: "symbols" + }, + clock730: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd62", + fitzpatrick_scale: false, + category: "symbols" + }, + clock830: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd63", + fitzpatrick_scale: false, + category: "symbols" + }, + clock930: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd64", + fitzpatrick_scale: false, + category: "symbols" + }, + clock1030: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd65", + fitzpatrick_scale: false, + category: "symbols" + }, + clock1130: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd66", + fitzpatrick_scale: false, + category: "symbols" + }, + clock1230: { + keywords: [ "time", "late", "early", "schedule" ], + "char": "\ud83d\udd67", + fitzpatrick_scale: false, + category: "symbols" + }, + afghanistan: { + keywords: [ "af", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddeb", + fitzpatrick_scale: false, + category: "flags" + }, + aland_islands: { + keywords: [ "\xc5land", "islands", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddfd", + fitzpatrick_scale: false, + category: "flags" + }, + albania: { + keywords: [ "al", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddf1", + fitzpatrick_scale: false, + category: "flags" + }, + algeria: { + keywords: [ "dz", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde9\ud83c\uddff", + fitzpatrick_scale: false, + category: "flags" + }, + american_samoa: { + keywords: [ "american", "ws", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddf8", + fitzpatrick_scale: false, + category: "flags" + }, + andorra: { + keywords: [ "ad", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\udde9", + fitzpatrick_scale: false, + category: "flags" + }, + angola: { + keywords: [ "ao", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddf4", + fitzpatrick_scale: false, + category: "flags" + }, + anguilla: { + keywords: [ "ai", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddee", + fitzpatrick_scale: false, + category: "flags" + }, + antarctica: { + keywords: [ "aq", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddf6", + fitzpatrick_scale: false, + category: "flags" + }, + antigua_barbuda: { + keywords: [ "antigua", "barbuda", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + argentina: { + keywords: [ "ar", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + armenia: { + keywords: [ "am", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + aruba: { + keywords: [ "aw", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddfc", + fitzpatrick_scale: false, + category: "flags" + }, + australia: { + keywords: [ "au", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddfa", + fitzpatrick_scale: false, + category: "flags" + }, + austria: { + keywords: [ "at", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddf9", + fitzpatrick_scale: false, + category: "flags" + }, + azerbaijan: { + keywords: [ "az", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddff", + fitzpatrick_scale: false, + category: "flags" + }, + bahamas: { + keywords: [ "bs", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddf8", + fitzpatrick_scale: false, + category: "flags" + }, + bahrain: { + keywords: [ "bh", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\udded", + fitzpatrick_scale: false, + category: "flags" + }, + bangladesh: { + keywords: [ "bd", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\udde9", + fitzpatrick_scale: false, + category: "flags" + }, + barbados: { + keywords: [ "bb", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\udde7", + fitzpatrick_scale: false, + category: "flags" + }, + belarus: { + keywords: [ "by", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddfe", + fitzpatrick_scale: false, + category: "flags" + }, + belgium: { + keywords: [ "be", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + belize: { + keywords: [ "bz", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddff", + fitzpatrick_scale: false, + category: "flags" + }, + benin: { + keywords: [ "bj", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddef", + fitzpatrick_scale: false, + category: "flags" + }, + bermuda: { + keywords: [ "bm", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + bhutan: { + keywords: [ "bt", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddf9", + fitzpatrick_scale: false, + category: "flags" + }, + bolivia: { + keywords: [ "bo", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddf4", + fitzpatrick_scale: false, + category: "flags" + }, + caribbean_netherlands: { + keywords: [ "bonaire", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddf6", + fitzpatrick_scale: false, + category: "flags" + }, + bosnia_herzegovina: { + keywords: [ "bosnia", "herzegovina", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\udde6", + fitzpatrick_scale: false, + category: "flags" + }, + botswana: { + keywords: [ "bw", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddfc", + fitzpatrick_scale: false, + category: "flags" + }, + brazil: { + keywords: [ "br", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + british_indian_ocean_territory: { + keywords: [ "british", "indian", "ocean", "territory", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddee\ud83c\uddf4", + fitzpatrick_scale: false, + category: "flags" + }, + british_virgin_islands: { + keywords: [ "british", "virgin", "islands", "bvi", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfb\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + brunei: { + keywords: [ "bn", "darussalam", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddf3", + fitzpatrick_scale: false, + category: "flags" + }, + bulgaria: { + keywords: [ "bg", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + burkina_faso: { + keywords: [ "burkina", "faso", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddeb", + fitzpatrick_scale: false, + category: "flags" + }, + burundi: { + keywords: [ "bi", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddee", + fitzpatrick_scale: false, + category: "flags" + }, + cape_verde: { + keywords: [ "cabo", "verde", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddfb", + fitzpatrick_scale: false, + category: "flags" + }, + cambodia: { + keywords: [ "kh", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf0\ud83c\udded", + fitzpatrick_scale: false, + category: "flags" + }, + cameroon: { + keywords: [ "cm", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + canada: { + keywords: [ "ca", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\udde6", + fitzpatrick_scale: false, + category: "flags" + }, + canary_islands: { + keywords: [ "canary", "islands", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddee\ud83c\udde8", + fitzpatrick_scale: false, + category: "flags" + }, + cayman_islands: { + keywords: [ "cayman", "islands", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf0\ud83c\uddfe", + fitzpatrick_scale: false, + category: "flags" + }, + central_african_republic: { + keywords: [ "central", "african", "republic", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddeb", + fitzpatrick_scale: false, + category: "flags" + }, + chad: { + keywords: [ "td", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\udde9", + fitzpatrick_scale: false, + category: "flags" + }, + chile: { + keywords: [ "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddf1", + fitzpatrick_scale: false, + category: "flags" + }, + cn: { + keywords: [ "china", "chinese", "prc", "flag", "country", "nation", "banner" ], + "char": "\ud83c\udde8\ud83c\uddf3", + fitzpatrick_scale: false, + category: "flags" + }, + christmas_island: { + keywords: [ "christmas", "island", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddfd", + fitzpatrick_scale: false, + category: "flags" + }, + cocos_islands: { + keywords: [ "cocos", "keeling", "islands", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\udde8", + fitzpatrick_scale: false, + category: "flags" + }, + colombia: { + keywords: [ "co", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddf4", + fitzpatrick_scale: false, + category: "flags" + }, + comoros: { + keywords: [ "km", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf0\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + congo_brazzaville: { + keywords: [ "congo", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + congo_kinshasa: { + keywords: [ "congo", "democratic", "republic", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\udde9", + fitzpatrick_scale: false, + category: "flags" + }, + cook_islands: { + keywords: [ "cook", "islands", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddf0", + fitzpatrick_scale: false, + category: "flags" + }, + costa_rica: { + keywords: [ "costa", "rica", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + croatia: { + keywords: [ "hr", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udded\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + cuba: { + keywords: [ "cu", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddfa", + fitzpatrick_scale: false, + category: "flags" + }, + curacao: { + keywords: [ "cura\xe7ao", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddfc", + fitzpatrick_scale: false, + category: "flags" + }, + cyprus: { + keywords: [ "cy", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddfe", + fitzpatrick_scale: false, + category: "flags" + }, + czech_republic: { + keywords: [ "cz", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddff", + fitzpatrick_scale: false, + category: "flags" + }, + denmark: { + keywords: [ "dk", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde9\ud83c\uddf0", + fitzpatrick_scale: false, + category: "flags" + }, + djibouti: { + keywords: [ "dj", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde9\ud83c\uddef", + fitzpatrick_scale: false, + category: "flags" + }, + dominica: { + keywords: [ "dm", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde9\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + dominican_republic: { + keywords: [ "dominican", "republic", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde9\ud83c\uddf4", + fitzpatrick_scale: false, + category: "flags" + }, + ecuador: { + keywords: [ "ec", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddea\ud83c\udde8", + fitzpatrick_scale: false, + category: "flags" + }, + egypt: { + keywords: [ "eg", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddea\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + el_salvador: { + keywords: [ "el", "salvador", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddfb", + fitzpatrick_scale: false, + category: "flags" + }, + equatorial_guinea: { + keywords: [ "equatorial", "gn", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddf6", + fitzpatrick_scale: false, + category: "flags" + }, + eritrea: { + keywords: [ "er", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddea\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + estonia: { + keywords: [ "ee", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddea\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + ethiopia: { + keywords: [ "et", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddea\ud83c\uddf9", + fitzpatrick_scale: false, + category: "flags" + }, + eu: { + keywords: [ "european", "union", "flag", "banner" ], + "char": "\ud83c\uddea\ud83c\uddfa", + fitzpatrick_scale: false, + category: "flags" + }, + falkland_islands: { + keywords: [ "falkland", "islands", "malvinas", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddeb\ud83c\uddf0", + fitzpatrick_scale: false, + category: "flags" + }, + faroe_islands: { + keywords: [ "faroe", "islands", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddeb\ud83c\uddf4", + fitzpatrick_scale: false, + category: "flags" + }, + fiji: { + keywords: [ "fj", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddeb\ud83c\uddef", + fitzpatrick_scale: false, + category: "flags" + }, + finland: { + keywords: [ "fi", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddeb\ud83c\uddee", + fitzpatrick_scale: false, + category: "flags" + }, + fr: { + keywords: [ "banner", "flag", "nation", "france", "french", "country" ], + "char": "\ud83c\uddeb\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + french_guiana: { + keywords: [ "french", "guiana", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddeb", + fitzpatrick_scale: false, + category: "flags" + }, + french_polynesia: { + keywords: [ "french", "polynesia", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\uddeb", + fitzpatrick_scale: false, + category: "flags" + }, + french_southern_territories: { + keywords: [ "french", "southern", "territories", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddeb", + fitzpatrick_scale: false, + category: "flags" + }, + gabon: { + keywords: [ "ga", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\udde6", + fitzpatrick_scale: false, + category: "flags" + }, + gambia: { + keywords: [ "gm", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + georgia: { + keywords: [ "ge", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + de: { + keywords: [ "german", "nation", "flag", "country", "banner" ], + "char": "\ud83c\udde9\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + ghana: { + keywords: [ "gh", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\udded", + fitzpatrick_scale: false, + category: "flags" + }, + gibraltar: { + keywords: [ "gi", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddee", + fitzpatrick_scale: false, + category: "flags" + }, + greece: { + keywords: [ "gr", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + greenland: { + keywords: [ "gl", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddf1", + fitzpatrick_scale: false, + category: "flags" + }, + grenada: { + keywords: [ "gd", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\udde9", + fitzpatrick_scale: false, + category: "flags" + }, + guadeloupe: { + keywords: [ "gp", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddf5", + fitzpatrick_scale: false, + category: "flags" + }, + guam: { + keywords: [ "gu", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddfa", + fitzpatrick_scale: false, + category: "flags" + }, + guatemala: { + keywords: [ "gt", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddf9", + fitzpatrick_scale: false, + category: "flags" + }, + guernsey: { + keywords: [ "gg", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + guinea: { + keywords: [ "gn", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddf3", + fitzpatrick_scale: false, + category: "flags" + }, + guinea_bissau: { + keywords: [ "gw", "bissau", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddfc", + fitzpatrick_scale: false, + category: "flags" + }, + guyana: { + keywords: [ "gy", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddfe", + fitzpatrick_scale: false, + category: "flags" + }, + haiti: { + keywords: [ "ht", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udded\ud83c\uddf9", + fitzpatrick_scale: false, + category: "flags" + }, + honduras: { + keywords: [ "hn", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udded\ud83c\uddf3", + fitzpatrick_scale: false, + category: "flags" + }, + hong_kong: { + keywords: [ "hong", "kong", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udded\ud83c\uddf0", + fitzpatrick_scale: false, + category: "flags" + }, + hungary: { + keywords: [ "hu", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udded\ud83c\uddfa", + fitzpatrick_scale: false, + category: "flags" + }, + iceland: { + keywords: [ "is", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddee\ud83c\uddf8", + fitzpatrick_scale: false, + category: "flags" + }, + india: { + keywords: [ "in", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddee\ud83c\uddf3", + fitzpatrick_scale: false, + category: "flags" + }, + indonesia: { + keywords: [ "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddee\ud83c\udde9", + fitzpatrick_scale: false, + category: "flags" + }, + iran: { + keywords: [ "iran,", "islamic", "republic", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddee\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + iraq: { + keywords: [ "iq", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddee\ud83c\uddf6", + fitzpatrick_scale: false, + category: "flags" + }, + ireland: { + keywords: [ "ie", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddee\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + isle_of_man: { + keywords: [ "isle", "man", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddee\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + israel: { + keywords: [ "il", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddee\ud83c\uddf1", + fitzpatrick_scale: false, + category: "flags" + }, + it: { + keywords: [ "italy", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddee\ud83c\uddf9", + fitzpatrick_scale: false, + category: "flags" + }, + cote_divoire: { + keywords: [ "ivory", "coast", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\uddee", + fitzpatrick_scale: false, + category: "flags" + }, + jamaica: { + keywords: [ "jm", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddef\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + jp: { + keywords: [ "japanese", "nation", "flag", "country", "banner" ], + "char": "\ud83c\uddef\ud83c\uddf5", + fitzpatrick_scale: false, + category: "flags" + }, + jersey: { + keywords: [ "je", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddef\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + jordan: { + keywords: [ "jo", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddef\ud83c\uddf4", + fitzpatrick_scale: false, + category: "flags" + }, + kazakhstan: { + keywords: [ "kz", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf0\ud83c\uddff", + fitzpatrick_scale: false, + category: "flags" + }, + kenya: { + keywords: [ "ke", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf0\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + kiribati: { + keywords: [ "ki", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf0\ud83c\uddee", + fitzpatrick_scale: false, + category: "flags" + }, + kosovo: { + keywords: [ "xk", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfd\ud83c\uddf0", + fitzpatrick_scale: false, + category: "flags" + }, + kuwait: { + keywords: [ "kw", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf0\ud83c\uddfc", + fitzpatrick_scale: false, + category: "flags" + }, + kyrgyzstan: { + keywords: [ "kg", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf0\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + laos: { + keywords: [ "lao", "democratic", "republic", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf1\ud83c\udde6", + fitzpatrick_scale: false, + category: "flags" + }, + latvia: { + keywords: [ "lv", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf1\ud83c\uddfb", + fitzpatrick_scale: false, + category: "flags" + }, + lebanon: { + keywords: [ "lb", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf1\ud83c\udde7", + fitzpatrick_scale: false, + category: "flags" + }, + lesotho: { + keywords: [ "ls", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf1\ud83c\uddf8", + fitzpatrick_scale: false, + category: "flags" + }, + liberia: { + keywords: [ "lr", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf1\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + libya: { + keywords: [ "ly", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf1\ud83c\uddfe", + fitzpatrick_scale: false, + category: "flags" + }, + liechtenstein: { + keywords: [ "li", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf1\ud83c\uddee", + fitzpatrick_scale: false, + category: "flags" + }, + lithuania: { + keywords: [ "lt", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf1\ud83c\uddf9", + fitzpatrick_scale: false, + category: "flags" + }, + luxembourg: { + keywords: [ "lu", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf1\ud83c\uddfa", + fitzpatrick_scale: false, + category: "flags" + }, + macau: { + keywords: [ "macao", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddf4", + fitzpatrick_scale: false, + category: "flags" + }, + macedonia: { + keywords: [ "macedonia,", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddf0", + fitzpatrick_scale: false, + category: "flags" + }, + madagascar: { + keywords: [ "mg", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + malawi: { + keywords: [ "mw", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddfc", + fitzpatrick_scale: false, + category: "flags" + }, + malaysia: { + keywords: [ "my", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddfe", + fitzpatrick_scale: false, + category: "flags" + }, + maldives: { + keywords: [ "mv", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddfb", + fitzpatrick_scale: false, + category: "flags" + }, + mali: { + keywords: [ "ml", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddf1", + fitzpatrick_scale: false, + category: "flags" + }, + malta: { + keywords: [ "mt", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddf9", + fitzpatrick_scale: false, + category: "flags" + }, + marshall_islands: { + keywords: [ "marshall", "islands", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\udded", + fitzpatrick_scale: false, + category: "flags" + }, + martinique: { + keywords: [ "mq", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddf6", + fitzpatrick_scale: false, + category: "flags" + }, + mauritania: { + keywords: [ "mr", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + mauritius: { + keywords: [ "mu", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddfa", + fitzpatrick_scale: false, + category: "flags" + }, + mayotte: { + keywords: [ "yt", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfe\ud83c\uddf9", + fitzpatrick_scale: false, + category: "flags" + }, + mexico: { + keywords: [ "mx", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddfd", + fitzpatrick_scale: false, + category: "flags" + }, + micronesia: { + keywords: [ "micronesia,", "federated", "states", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddeb\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + moldova: { + keywords: [ "moldova,", "republic", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\udde9", + fitzpatrick_scale: false, + category: "flags" + }, + monaco: { + keywords: [ "mc", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\udde8", + fitzpatrick_scale: false, + category: "flags" + }, + mongolia: { + keywords: [ "mn", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddf3", + fitzpatrick_scale: false, + category: "flags" + }, + montenegro: { + keywords: [ "me", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + montserrat: { + keywords: [ "ms", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddf8", + fitzpatrick_scale: false, + category: "flags" + }, + morocco: { + keywords: [ "ma", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\udde6", + fitzpatrick_scale: false, + category: "flags" + }, + mozambique: { + keywords: [ "mz", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddff", + fitzpatrick_scale: false, + category: "flags" + }, + myanmar: { + keywords: [ "mm", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + namibia: { + keywords: [ "na", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf3\ud83c\udde6", + fitzpatrick_scale: false, + category: "flags" + }, + nauru: { + keywords: [ "nr", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf3\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + nepal: { + keywords: [ "np", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf3\ud83c\uddf5", + fitzpatrick_scale: false, + category: "flags" + }, + netherlands: { + keywords: [ "nl", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf3\ud83c\uddf1", + fitzpatrick_scale: false, + category: "flags" + }, + new_caledonia: { + keywords: [ "new", "caledonia", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf3\ud83c\udde8", + fitzpatrick_scale: false, + category: "flags" + }, + new_zealand: { + keywords: [ "new", "zealand", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf3\ud83c\uddff", + fitzpatrick_scale: false, + category: "flags" + }, + nicaragua: { + keywords: [ "ni", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf3\ud83c\uddee", + fitzpatrick_scale: false, + category: "flags" + }, + niger: { + keywords: [ "ne", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf3\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + nigeria: { + keywords: [ "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf3\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + niue: { + keywords: [ "nu", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf3\ud83c\uddfa", + fitzpatrick_scale: false, + category: "flags" + }, + norfolk_island: { + keywords: [ "norfolk", "island", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf3\ud83c\uddeb", + fitzpatrick_scale: false, + category: "flags" + }, + northern_mariana_islands: { + keywords: [ "northern", "mariana", "islands", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf2\ud83c\uddf5", + fitzpatrick_scale: false, + category: "flags" + }, + north_korea: { + keywords: [ "north", "korea", "nation", "flag", "country", "banner" ], + "char": "\ud83c\uddf0\ud83c\uddf5", + fitzpatrick_scale: false, + category: "flags" + }, + norway: { + keywords: [ "no", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf3\ud83c\uddf4", + fitzpatrick_scale: false, + category: "flags" + }, + oman: { + keywords: [ "om_symbol", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf4\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + pakistan: { + keywords: [ "pk", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\uddf0", + fitzpatrick_scale: false, + category: "flags" + }, + palau: { + keywords: [ "pw", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\uddfc", + fitzpatrick_scale: false, + category: "flags" + }, + palestinian_territories: { + keywords: [ "palestine", "palestinian", "territories", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\uddf8", + fitzpatrick_scale: false, + category: "flags" + }, + panama: { + keywords: [ "pa", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\udde6", + fitzpatrick_scale: false, + category: "flags" + }, + papua_new_guinea: { + keywords: [ "papua", "new", "guinea", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + paraguay: { + keywords: [ "py", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\uddfe", + fitzpatrick_scale: false, + category: "flags" + }, + peru: { + keywords: [ "pe", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + philippines: { + keywords: [ "ph", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\udded", + fitzpatrick_scale: false, + category: "flags" + }, + pitcairn_islands: { + keywords: [ "pitcairn", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\uddf3", + fitzpatrick_scale: false, + category: "flags" + }, + poland: { + keywords: [ "pl", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\uddf1", + fitzpatrick_scale: false, + category: "flags" + }, + portugal: { + keywords: [ "pt", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\uddf9", + fitzpatrick_scale: false, + category: "flags" + }, + puerto_rico: { + keywords: [ "puerto", "rico", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + qatar: { + keywords: [ "qa", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf6\ud83c\udde6", + fitzpatrick_scale: false, + category: "flags" + }, + reunion: { + keywords: [ "r\xe9union", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf7\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + romania: { + keywords: [ "ro", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf7\ud83c\uddf4", + fitzpatrick_scale: false, + category: "flags" + }, + ru: { + keywords: [ "russian", "federation", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf7\ud83c\uddfa", + fitzpatrick_scale: false, + category: "flags" + }, + rwanda: { + keywords: [ "rw", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf7\ud83c\uddfc", + fitzpatrick_scale: false, + category: "flags" + }, + st_barthelemy: { + keywords: [ "saint", "barth\xe9lemy", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde7\ud83c\uddf1", + fitzpatrick_scale: false, + category: "flags" + }, + st_helena: { + keywords: [ "saint", "helena", "ascension", "tristan", "cunha", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\udded", + fitzpatrick_scale: false, + category: "flags" + }, + st_kitts_nevis: { + keywords: [ "saint", "kitts", "nevis", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf0\ud83c\uddf3", + fitzpatrick_scale: false, + category: "flags" + }, + st_lucia: { + keywords: [ "saint", "lucia", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf1\ud83c\udde8", + fitzpatrick_scale: false, + category: "flags" + }, + st_pierre_miquelon: { + keywords: [ "saint", "pierre", "miquelon", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf5\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + st_vincent_grenadines: { + keywords: [ "saint", "vincent", "grenadines", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfb\ud83c\udde8", + fitzpatrick_scale: false, + category: "flags" + }, + samoa: { + keywords: [ "ws", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfc\ud83c\uddf8", + fitzpatrick_scale: false, + category: "flags" + }, + san_marino: { + keywords: [ "san", "marino", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + sao_tome_principe: { + keywords: [ "sao", "tome", "principe", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddf9", + fitzpatrick_scale: false, + category: "flags" + }, + saudi_arabia: { + keywords: [ "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\udde6", + fitzpatrick_scale: false, + category: "flags" + }, + senegal: { + keywords: [ "sn", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddf3", + fitzpatrick_scale: false, + category: "flags" + }, + serbia: { + keywords: [ "rs", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf7\ud83c\uddf8", + fitzpatrick_scale: false, + category: "flags" + }, + seychelles: { + keywords: [ "sc", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\udde8", + fitzpatrick_scale: false, + category: "flags" + }, + sierra_leone: { + keywords: [ "sierra", "leone", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddf1", + fitzpatrick_scale: false, + category: "flags" + }, + singapore: { + keywords: [ "sg", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + sint_maarten: { + keywords: [ "sint", "maarten", "dutch", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddfd", + fitzpatrick_scale: false, + category: "flags" + }, + slovakia: { + keywords: [ "sk", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddf0", + fitzpatrick_scale: false, + category: "flags" + }, + slovenia: { + keywords: [ "si", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddee", + fitzpatrick_scale: false, + category: "flags" + }, + solomon_islands: { + keywords: [ "solomon", "islands", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\udde7", + fitzpatrick_scale: false, + category: "flags" + }, + somalia: { + keywords: [ "so", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddf4", + fitzpatrick_scale: false, + category: "flags" + }, + south_africa: { + keywords: [ "south", "africa", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddff\ud83c\udde6", + fitzpatrick_scale: false, + category: "flags" + }, + south_georgia_south_sandwich_islands: { + keywords: [ "south", "georgia", "sandwich", "islands", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddec\ud83c\uddf8", + fitzpatrick_scale: false, + category: "flags" + }, + kr: { + keywords: [ "south", "korea", "nation", "flag", "country", "banner" ], + "char": "\ud83c\uddf0\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + south_sudan: { + keywords: [ "south", "sd", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddf8", + fitzpatrick_scale: false, + category: "flags" + }, + es: { + keywords: [ "spain", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddea\ud83c\uddf8", + fitzpatrick_scale: false, + category: "flags" + }, + sri_lanka: { + keywords: [ "sri", "lanka", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf1\ud83c\uddf0", + fitzpatrick_scale: false, + category: "flags" + }, + sudan: { + keywords: [ "sd", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\udde9", + fitzpatrick_scale: false, + category: "flags" + }, + suriname: { + keywords: [ "sr", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + swaziland: { + keywords: [ "sz", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddff", + fitzpatrick_scale: false, + category: "flags" + }, + sweden: { + keywords: [ "se", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + switzerland: { + keywords: [ "ch", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde8\ud83c\udded", + fitzpatrick_scale: false, + category: "flags" + }, + syria: { + keywords: [ "syrian", "arab", "republic", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf8\ud83c\uddfe", + fitzpatrick_scale: false, + category: "flags" + }, + taiwan: { + keywords: [ "tw", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddfc", + fitzpatrick_scale: false, + category: "flags" + }, + tajikistan: { + keywords: [ "tj", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddef", + fitzpatrick_scale: false, + category: "flags" + }, + tanzania: { + keywords: [ "tanzania,", "united", "republic", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddff", + fitzpatrick_scale: false, + category: "flags" + }, + thailand: { + keywords: [ "th", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\udded", + fitzpatrick_scale: false, + category: "flags" + }, + timor_leste: { + keywords: [ "timor", "leste", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddf1", + fitzpatrick_scale: false, + category: "flags" + }, + togo: { + keywords: [ "tg", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + tokelau: { + keywords: [ "tk", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddf0", + fitzpatrick_scale: false, + category: "flags" + }, + tonga: { + keywords: [ "to", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddf4", + fitzpatrick_scale: false, + category: "flags" + }, + trinidad_tobago: { + keywords: [ "trinidad", "tobago", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddf9", + fitzpatrick_scale: false, + category: "flags" + }, + tunisia: { + keywords: [ "tn", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddf3", + fitzpatrick_scale: false, + category: "flags" + }, + tr: { + keywords: [ "turkey", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddf7", + fitzpatrick_scale: false, + category: "flags" + }, + turkmenistan: { + keywords: [ "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + turks_caicos_islands: { + keywords: [ "turks", "caicos", "islands", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\udde8", + fitzpatrick_scale: false, + category: "flags" + }, + tuvalu: { + keywords: [ "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddf9\ud83c\uddfb", + fitzpatrick_scale: false, + category: "flags" + }, + uganda: { + keywords: [ "ug", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfa\ud83c\uddec", + fitzpatrick_scale: false, + category: "flags" + }, + ukraine: { + keywords: [ "ua", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfa\ud83c\udde6", + fitzpatrick_scale: false, + category: "flags" + }, + united_arab_emirates: { + keywords: [ "united", "arab", "emirates", "flag", "nation", "country", "banner" ], + "char": "\ud83c\udde6\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + uk: { + keywords: [ "united", "kingdom", "great", "britain", "northern", "ireland", "flag", "nation", "country", "banner", "british", "UK", "english", "england", "union jack" ], + "char": "\ud83c\uddec\ud83c\udde7", + fitzpatrick_scale: false, + category: "flags" + }, + england: { + keywords: [ "flag", "english" ], + "char": "\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f", + fitzpatrick_scale: false, + category: "flags" + }, + scotland: { + keywords: [ "flag", "scottish" ], + "char": "\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f", + fitzpatrick_scale: false, + category: "flags" + }, + wales: { + keywords: [ "flag", "welsh" ], + "char": "\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f", + fitzpatrick_scale: false, + category: "flags" + }, + us: { + keywords: [ "united", "states", "america", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfa\ud83c\uddf8", + fitzpatrick_scale: false, + category: "flags" + }, + us_virgin_islands: { + keywords: [ "virgin", "islands", "us", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfb\ud83c\uddee", + fitzpatrick_scale: false, + category: "flags" + }, + uruguay: { + keywords: [ "uy", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfa\ud83c\uddfe", + fitzpatrick_scale: false, + category: "flags" + }, + uzbekistan: { + keywords: [ "uz", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfa\ud83c\uddff", + fitzpatrick_scale: false, + category: "flags" + }, + vanuatu: { + keywords: [ "vu", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfb\ud83c\uddfa", + fitzpatrick_scale: false, + category: "flags" + }, + vatican_city: { + keywords: [ "vatican", "city", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfb\ud83c\udde6", + fitzpatrick_scale: false, + category: "flags" + }, + venezuela: { + keywords: [ "ve", "bolivarian", "republic", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfb\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + vietnam: { + keywords: [ "viet", "nam", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfb\ud83c\uddf3", + fitzpatrick_scale: false, + category: "flags" + }, + wallis_futuna: { + keywords: [ "wallis", "futuna", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfc\ud83c\uddeb", + fitzpatrick_scale: false, + category: "flags" + }, + western_sahara: { + keywords: [ "western", "sahara", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddea\ud83c\udded", + fitzpatrick_scale: false, + category: "flags" + }, + yemen: { + keywords: [ "ye", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddfe\ud83c\uddea", + fitzpatrick_scale: false, + category: "flags" + }, + zambia: { + keywords: [ "zm", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddff\ud83c\uddf2", + fitzpatrick_scale: false, + category: "flags" + }, + zimbabwe: { + keywords: [ "zw", "flag", "nation", "country", "banner" ], + "char": "\ud83c\uddff\ud83c\uddfc", + fitzpatrick_scale: false, + category: "flags" + }, + united_nations: { + keywords: [ "un", "flag", "banner" ], + "char": "\ud83c\uddfa\ud83c\uddf3", + fitzpatrick_scale: false, + category: "flags" + }, + pirate_flag: { + keywords: [ "skull", "crossbones", "flag", "banner" ], + "char": "\ud83c\udff4\u200d\u2620\ufe0f", + fitzpatrick_scale: false, + category: "flags" + } +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/js/emojis.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/js/emojis.min.js new file mode 100644 index 0000000000000000000000000000000000000000..8295d5a5c94225301212eb5078236cc7000ac2b9 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/js/emojis.min.js @@ -0,0 +1,2 @@ +// Source: npm package: emojilib, file:emojis.json +window.tinymce.Resource.add("tinymce.plugins.emoticons",{grinning:{keywords:["face","smile","happy","joy",":D","grin"],"char":"\ud83d\ude00",fitzpatrick_scale:!1,category:"people"},grimacing:{keywords:["face","grimace","teeth"],"char":"\ud83d\ude2c",fitzpatrick_scale:!1,category:"people"},grin:{keywords:["face","happy","smile","joy","kawaii"],"char":"\ud83d\ude01",fitzpatrick_scale:!1,category:"people"},joy:{keywords:["face","cry","tears","weep","happy","happytears","haha"],"char":"\ud83d\ude02",fitzpatrick_scale:!1,category:"people"},rofl:{keywords:["face","rolling","floor","laughing","lol","haha"],"char":"\ud83e\udd23",fitzpatrick_scale:!1,category:"people"},partying:{keywords:["face","celebration","woohoo"],"char":"\ud83e\udd73",fitzpatrick_scale:!1,category:"people"},smiley:{keywords:["face","happy","joy","haha",":D",":)","smile","funny"],"char":"\ud83d\ude03",fitzpatrick_scale:!1,category:"people"},smile:{keywords:["face","happy","joy","funny","haha","laugh","like",":D",":)"],"char":"\ud83d\ude04",fitzpatrick_scale:!1,category:"people"},sweat_smile:{keywords:["face","hot","happy","laugh","sweat","smile","relief"],"char":"\ud83d\ude05",fitzpatrick_scale:!1,category:"people"},laughing:{keywords:["happy","joy","lol","satisfied","haha","face","glad","XD","laugh"],"char":"\ud83d\ude06",fitzpatrick_scale:!1,category:"people"},innocent:{keywords:["face","angel","heaven","halo"],"char":"\ud83d\ude07",fitzpatrick_scale:!1,category:"people"},wink:{keywords:["face","happy","mischievous","secret",";)","smile","eye"],"char":"\ud83d\ude09",fitzpatrick_scale:!1,category:"people"},blush:{keywords:["face","smile","happy","flushed","crush","embarrassed","shy","joy"],"char":"\ud83d\ude0a",fitzpatrick_scale:!1,category:"people"},slightly_smiling_face:{keywords:["face","smile"],"char":"\ud83d\ude42",fitzpatrick_scale:!1,category:"people"},upside_down_face:{keywords:["face","flipped","silly","smile"],"char":"\ud83d\ude43",fitzpatrick_scale:!1,category:"people"},relaxed:{keywords:["face","blush","massage","happiness"],"char":"\u263a\ufe0f",fitzpatrick_scale:!1,category:"people"},yum:{keywords:["happy","joy","tongue","smile","face","silly","yummy","nom","delicious","savouring"],"char":"\ud83d\ude0b",fitzpatrick_scale:!1,category:"people"},relieved:{keywords:["face","relaxed","phew","massage","happiness"],"char":"\ud83d\ude0c",fitzpatrick_scale:!1,category:"people"},heart_eyes:{keywords:["face","love","like","affection","valentines","infatuation","crush","heart"],"char":"\ud83d\ude0d",fitzpatrick_scale:!1,category:"people"},smiling_face_with_three_hearts:{keywords:["face","love","like","affection","valentines","infatuation","crush","hearts","adore"],"char":"\ud83e\udd70",fitzpatrick_scale:!1,category:"people"},kissing_heart:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],"char":"\ud83d\ude18",fitzpatrick_scale:!1,category:"people"},kissing:{keywords:["love","like","face","3","valentines","infatuation","kiss"],"char":"\ud83d\ude17",fitzpatrick_scale:!1,category:"people"},kissing_smiling_eyes:{keywords:["face","affection","valentines","infatuation","kiss"],"char":"\ud83d\ude19",fitzpatrick_scale:!1,category:"people"},kissing_closed_eyes:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],"char":"\ud83d\ude1a",fitzpatrick_scale:!1,category:"people"},stuck_out_tongue_winking_eye:{keywords:["face","prank","childish","playful","mischievous","smile","wink","tongue"],"char":"\ud83d\ude1c",fitzpatrick_scale:!1,category:"people"},zany:{keywords:["face","goofy","crazy"],"char":"\ud83e\udd2a",fitzpatrick_scale:!1,category:"people"},raised_eyebrow:{keywords:["face","distrust","scepticism","disapproval","disbelief","surprise"],"char":"\ud83e\udd28",fitzpatrick_scale:!1,category:"people"},monocle:{keywords:["face","stuffy","wealthy"],"char":"\ud83e\uddd0",fitzpatrick_scale:!1,category:"people"},stuck_out_tongue_closed_eyes:{keywords:["face","prank","playful","mischievous","smile","tongue"],"char":"\ud83d\ude1d",fitzpatrick_scale:!1,category:"people"},stuck_out_tongue:{keywords:["face","prank","childish","playful","mischievous","smile","tongue"],"char":"\ud83d\ude1b",fitzpatrick_scale:!1,category:"people"},money_mouth_face:{keywords:["face","rich","dollar","money"],"char":"\ud83e\udd11",fitzpatrick_scale:!1,category:"people"},nerd_face:{keywords:["face","nerdy","geek","dork"],"char":"\ud83e\udd13",fitzpatrick_scale:!1,category:"people"},sunglasses:{keywords:["face","cool","smile","summer","beach","sunglass"],"char":"\ud83d\ude0e",fitzpatrick_scale:!1,category:"people"},star_struck:{keywords:["face","smile","starry","eyes","grinning"],"char":"\ud83e\udd29",fitzpatrick_scale:!1,category:"people"},clown_face:{keywords:["face"],"char":"\ud83e\udd21",fitzpatrick_scale:!1,category:"people"},cowboy_hat_face:{keywords:["face","cowgirl","hat"],"char":"\ud83e\udd20",fitzpatrick_scale:!1,category:"people"},hugs:{keywords:["face","smile","hug"],"char":"\ud83e\udd17",fitzpatrick_scale:!1,category:"people"},smirk:{keywords:["face","smile","mean","prank","smug","sarcasm"],"char":"\ud83d\ude0f",fitzpatrick_scale:!1,category:"people"},no_mouth:{keywords:["face","hellokitty"],"char":"\ud83d\ude36",fitzpatrick_scale:!1,category:"people"},neutral_face:{keywords:["indifference","meh",":|","neutral"],"char":"\ud83d\ude10",fitzpatrick_scale:!1,category:"people"},expressionless:{keywords:["face","indifferent","-_-","meh","deadpan"],"char":"\ud83d\ude11",fitzpatrick_scale:!1,category:"people"},unamused:{keywords:["indifference","bored","straight face","serious","sarcasm","unimpressed","skeptical","dubious","side_eye"],"char":"\ud83d\ude12",fitzpatrick_scale:!1,category:"people"},roll_eyes:{keywords:["face","eyeroll","frustrated"],"char":"\ud83d\ude44",fitzpatrick_scale:!1,category:"people"},thinking:{keywords:["face","hmmm","think","consider"],"char":"\ud83e\udd14",fitzpatrick_scale:!1,category:"people"},lying_face:{keywords:["face","lie","pinocchio"],"char":"\ud83e\udd25",fitzpatrick_scale:!1,category:"people"},hand_over_mouth:{keywords:["face","whoops","shock","surprise"],"char":"\ud83e\udd2d",fitzpatrick_scale:!1,category:"people"},shushing:{keywords:["face","quiet","shhh"],"char":"\ud83e\udd2b",fitzpatrick_scale:!1,category:"people"},symbols_over_mouth:{keywords:["face","swearing","cursing","cussing","profanity","expletive"],"char":"\ud83e\udd2c",fitzpatrick_scale:!1,category:"people"},exploding_head:{keywords:["face","shocked","mind","blown"],"char":"\ud83e\udd2f",fitzpatrick_scale:!1,category:"people"},flushed:{keywords:["face","blush","shy","flattered"],"char":"\ud83d\ude33",fitzpatrick_scale:!1,category:"people"},disappointed:{keywords:["face","sad","upset","depressed",":("],"char":"\ud83d\ude1e",fitzpatrick_scale:!1,category:"people"},worried:{keywords:["face","concern","nervous",":("],"char":"\ud83d\ude1f",fitzpatrick_scale:!1,category:"people"},angry:{keywords:["mad","face","annoyed","frustrated"],"char":"\ud83d\ude20",fitzpatrick_scale:!1,category:"people"},rage:{keywords:["angry","mad","hate","despise"],"char":"\ud83d\ude21",fitzpatrick_scale:!1,category:"people"},pensive:{keywords:["face","sad","depressed","upset"],"char":"\ud83d\ude14",fitzpatrick_scale:!1,category:"people"},confused:{keywords:["face","indifference","huh","weird","hmmm",":/"],"char":"\ud83d\ude15",fitzpatrick_scale:!1,category:"people"},slightly_frowning_face:{keywords:["face","frowning","disappointed","sad","upset"],"char":"\ud83d\ude41",fitzpatrick_scale:!1,category:"people"},frowning_face:{keywords:["face","sad","upset","frown"],"char":"\u2639",fitzpatrick_scale:!1,category:"people"},persevere:{keywords:["face","sick","no","upset","oops"],"char":"\ud83d\ude23",fitzpatrick_scale:!1,category:"people"},confounded:{keywords:["face","confused","sick","unwell","oops",":S"],"char":"\ud83d\ude16",fitzpatrick_scale:!1,category:"people"},tired_face:{keywords:["sick","whine","upset","frustrated"],"char":"\ud83d\ude2b",fitzpatrick_scale:!1,category:"people"},weary:{keywords:["face","tired","sleepy","sad","frustrated","upset"],"char":"\ud83d\ude29",fitzpatrick_scale:!1,category:"people"},pleading:{keywords:["face","begging","mercy"],"char":"\ud83e\udd7a",fitzpatrick_scale:!1,category:"people"},triumph:{keywords:["face","gas","phew","proud","pride"],"char":"\ud83d\ude24",fitzpatrick_scale:!1,category:"people"},open_mouth:{keywords:["face","surprise","impressed","wow","whoa",":O"],"char":"\ud83d\ude2e",fitzpatrick_scale:!1,category:"people"},scream:{keywords:["face","munch","scared","omg"],"char":"\ud83d\ude31",fitzpatrick_scale:!1,category:"people"},fearful:{keywords:["face","scared","terrified","nervous","oops","huh"],"char":"\ud83d\ude28",fitzpatrick_scale:!1,category:"people"},cold_sweat:{keywords:["face","nervous","sweat"],"char":"\ud83d\ude30",fitzpatrick_scale:!1,category:"people"},hushed:{keywords:["face","woo","shh"],"char":"\ud83d\ude2f",fitzpatrick_scale:!1,category:"people"},frowning:{keywords:["face","aw","what"],"char":"\ud83d\ude26",fitzpatrick_scale:!1,category:"people"},anguished:{keywords:["face","stunned","nervous"],"char":"\ud83d\ude27",fitzpatrick_scale:!1,category:"people"},cry:{keywords:["face","tears","sad","depressed","upset",":'("],"char":"\ud83d\ude22",fitzpatrick_scale:!1,category:"people"},disappointed_relieved:{keywords:["face","phew","sweat","nervous"],"char":"\ud83d\ude25",fitzpatrick_scale:!1,category:"people"},drooling_face:{keywords:["face"],"char":"\ud83e\udd24",fitzpatrick_scale:!1,category:"people"},sleepy:{keywords:["face","tired","rest","nap"],"char":"\ud83d\ude2a",fitzpatrick_scale:!1,category:"people"},sweat:{keywords:["face","hot","sad","tired","exercise"],"char":"\ud83d\ude13",fitzpatrick_scale:!1,category:"people"},hot:{keywords:["face","feverish","heat","red","sweating"],"char":"\ud83e\udd75",fitzpatrick_scale:!1,category:"people"},cold:{keywords:["face","blue","freezing","frozen","frostbite","icicles"],"char":"\ud83e\udd76",fitzpatrick_scale:!1,category:"people"},sob:{keywords:["face","cry","tears","sad","upset","depressed"],"char":"\ud83d\ude2d",fitzpatrick_scale:!1,category:"people"},dizzy_face:{keywords:["spent","unconscious","xox","dizzy"],"char":"\ud83d\ude35",fitzpatrick_scale:!1,category:"people"},astonished:{keywords:["face","xox","surprised","poisoned"],"char":"\ud83d\ude32",fitzpatrick_scale:!1,category:"people"},zipper_mouth_face:{keywords:["face","sealed","zipper","secret"],"char":"\ud83e\udd10",fitzpatrick_scale:!1,category:"people"},nauseated_face:{keywords:["face","vomit","gross","green","sick","throw up","ill"],"char":"\ud83e\udd22",fitzpatrick_scale:!1,category:"people"},sneezing_face:{keywords:["face","gesundheit","sneeze","sick","allergy"],"char":"\ud83e\udd27",fitzpatrick_scale:!1,category:"people"},vomiting:{keywords:["face","sick"],"char":"\ud83e\udd2e",fitzpatrick_scale:!1,category:"people"},mask:{keywords:["face","sick","ill","disease"],"char":"\ud83d\ude37",fitzpatrick_scale:!1,category:"people"},face_with_thermometer:{keywords:["sick","temperature","thermometer","cold","fever"],"char":"\ud83e\udd12",fitzpatrick_scale:!1,category:"people"},face_with_head_bandage:{keywords:["injured","clumsy","bandage","hurt"],"char":"\ud83e\udd15",fitzpatrick_scale:!1,category:"people"},woozy:{keywords:["face","dizzy","intoxicated","tipsy","wavy"],"char":"\ud83e\udd74",fitzpatrick_scale:!1,category:"people"},sleeping:{keywords:["face","tired","sleepy","night","zzz"],"char":"\ud83d\ude34",fitzpatrick_scale:!1,category:"people"},zzz:{keywords:["sleepy","tired","dream"],"char":"\ud83d\udca4",fitzpatrick_scale:!1,category:"people"},poop:{keywords:["hankey","shitface","fail","turd","shit"],"char":"\ud83d\udca9",fitzpatrick_scale:!1,category:"people"},smiling_imp:{keywords:["devil","horns"],"char":"\ud83d\ude08",fitzpatrick_scale:!1,category:"people"},imp:{keywords:["devil","angry","horns"],"char":"\ud83d\udc7f",fitzpatrick_scale:!1,category:"people"},japanese_ogre:{keywords:["monster","red","mask","halloween","scary","creepy","devil","demon","japanese","ogre"],"char":"\ud83d\udc79",fitzpatrick_scale:!1,category:"people"},japanese_goblin:{keywords:["red","evil","mask","monster","scary","creepy","japanese","goblin"],"char":"\ud83d\udc7a",fitzpatrick_scale:!1,category:"people"},skull:{keywords:["dead","skeleton","creepy","death"],"char":"\ud83d\udc80",fitzpatrick_scale:!1,category:"people"},ghost:{keywords:["halloween","spooky","scary"],"char":"\ud83d\udc7b",fitzpatrick_scale:!1,category:"people"},alien:{keywords:["UFO","paul","weird","outer_space"],"char":"\ud83d\udc7d",fitzpatrick_scale:!1,category:"people"},robot:{keywords:["computer","machine","bot"],"char":"\ud83e\udd16",fitzpatrick_scale:!1,category:"people"},smiley_cat:{keywords:["animal","cats","happy","smile"],"char":"\ud83d\ude3a",fitzpatrick_scale:!1,category:"people"},smile_cat:{keywords:["animal","cats","smile"],"char":"\ud83d\ude38",fitzpatrick_scale:!1,category:"people"},joy_cat:{keywords:["animal","cats","haha","happy","tears"],"char":"\ud83d\ude39",fitzpatrick_scale:!1,category:"people"},heart_eyes_cat:{keywords:["animal","love","like","affection","cats","valentines","heart"],"char":"\ud83d\ude3b",fitzpatrick_scale:!1,category:"people"},smirk_cat:{keywords:["animal","cats","smirk"],"char":"\ud83d\ude3c",fitzpatrick_scale:!1,category:"people"},kissing_cat:{keywords:["animal","cats","kiss"],"char":"\ud83d\ude3d",fitzpatrick_scale:!1,category:"people"},scream_cat:{keywords:["animal","cats","munch","scared","scream"],"char":"\ud83d\ude40",fitzpatrick_scale:!1,category:"people"},crying_cat_face:{keywords:["animal","tears","weep","sad","cats","upset","cry"],"char":"\ud83d\ude3f",fitzpatrick_scale:!1,category:"people"},pouting_cat:{keywords:["animal","cats"],"char":"\ud83d\ude3e",fitzpatrick_scale:!1,category:"people"},palms_up:{keywords:["hands","gesture","cupped","prayer"],"char":"\ud83e\udd32",fitzpatrick_scale:!0,category:"people"},raised_hands:{keywords:["gesture","hooray","yea","celebration","hands"],"char":"\ud83d\ude4c",fitzpatrick_scale:!0,category:"people"},clap:{keywords:["hands","praise","applause","congrats","yay"],"char":"\ud83d\udc4f",fitzpatrick_scale:!0,category:"people"},wave:{keywords:["hands","gesture","goodbye","solong","farewell","hello","hi","palm"],"char":"\ud83d\udc4b",fitzpatrick_scale:!0,category:"people"},call_me_hand:{keywords:["hands","gesture"],"char":"\ud83e\udd19",fitzpatrick_scale:!0,category:"people"},"+1":{keywords:["thumbsup","yes","awesome","good","agree","accept","cool","hand","like"],"char":"\ud83d\udc4d",fitzpatrick_scale:!0,category:"people"},"-1":{keywords:["thumbsdown","no","dislike","hand"],"char":"\ud83d\udc4e",fitzpatrick_scale:!0,category:"people"},facepunch:{keywords:["angry","violence","fist","hit","attack","hand"],"char":"\ud83d\udc4a",fitzpatrick_scale:!0,category:"people"},fist:{keywords:["fingers","hand","grasp"],"char":"\u270a",fitzpatrick_scale:!0,category:"people"},fist_left:{keywords:["hand","fistbump"],"char":"\ud83e\udd1b",fitzpatrick_scale:!0,category:"people"},fist_right:{keywords:["hand","fistbump"],"char":"\ud83e\udd1c",fitzpatrick_scale:!0,category:"people"},v:{keywords:["fingers","ohyeah","hand","peace","victory","two"],"char":"\u270c",fitzpatrick_scale:!0,category:"people"},ok_hand:{keywords:["fingers","limbs","perfect","ok","okay"],"char":"\ud83d\udc4c",fitzpatrick_scale:!0,category:"people"},raised_hand:{keywords:["fingers","stop","highfive","palm","ban"],"char":"\u270b",fitzpatrick_scale:!0,category:"people"},raised_back_of_hand:{keywords:["fingers","raised","backhand"],"char":"\ud83e\udd1a",fitzpatrick_scale:!0,category:"people"},open_hands:{keywords:["fingers","butterfly","hands","open"],"char":"\ud83d\udc50",fitzpatrick_scale:!0,category:"people"},muscle:{keywords:["arm","flex","hand","summer","strong","biceps"],"char":"\ud83d\udcaa",fitzpatrick_scale:!0,category:"people"},pray:{keywords:["please","hope","wish","namaste","highfive"],"char":"\ud83d\ude4f",fitzpatrick_scale:!0,category:"people"},foot:{keywords:["kick","stomp"],"char":"\ud83e\uddb6",fitzpatrick_scale:!0,category:"people"},leg:{keywords:["kick","limb"],"char":"\ud83e\uddb5",fitzpatrick_scale:!0,category:"people"},handshake:{keywords:["agreement","shake"],"char":"\ud83e\udd1d",fitzpatrick_scale:!1,category:"people"},point_up:{keywords:["hand","fingers","direction","up"],"char":"\u261d",fitzpatrick_scale:!0,category:"people"},point_up_2:{keywords:["fingers","hand","direction","up"],"char":"\ud83d\udc46",fitzpatrick_scale:!0,category:"people"},point_down:{keywords:["fingers","hand","direction","down"],"char":"\ud83d\udc47",fitzpatrick_scale:!0,category:"people"},point_left:{keywords:["direction","fingers","hand","left"],"char":"\ud83d\udc48",fitzpatrick_scale:!0,category:"people"},point_right:{keywords:["fingers","hand","direction","right"],"char":"\ud83d\udc49",fitzpatrick_scale:!0,category:"people"},fu:{keywords:["hand","fingers","rude","middle","flipping"],"char":"\ud83d\udd95",fitzpatrick_scale:!0,category:"people"},raised_hand_with_fingers_splayed:{keywords:["hand","fingers","palm"],"char":"\ud83d\udd90",fitzpatrick_scale:!0,category:"people"},love_you:{keywords:["hand","fingers","gesture"],"char":"\ud83e\udd1f",fitzpatrick_scale:!0,category:"people"},metal:{keywords:["hand","fingers","evil_eye","sign_of_horns","rock_on"],"char":"\ud83e\udd18",fitzpatrick_scale:!0,category:"people"},crossed_fingers:{keywords:["good","lucky"],"char":"\ud83e\udd1e",fitzpatrick_scale:!0,category:"people"},vulcan_salute:{keywords:["hand","fingers","spock","star trek"],"char":"\ud83d\udd96",fitzpatrick_scale:!0,category:"people"},writing_hand:{keywords:["lower_left_ballpoint_pen","stationery","write","compose"],"char":"\u270d",fitzpatrick_scale:!0,category:"people"},selfie:{keywords:["camera","phone"],"char":"\ud83e\udd33",fitzpatrick_scale:!0,category:"people"},nail_care:{keywords:["beauty","manicure","finger","fashion","nail"],"char":"\ud83d\udc85",fitzpatrick_scale:!0,category:"people"},lips:{keywords:["mouth","kiss"],"char":"\ud83d\udc44",fitzpatrick_scale:!1,category:"people"},tooth:{keywords:["teeth","dentist"],"char":"\ud83e\uddb7",fitzpatrick_scale:!1,category:"people"},tongue:{keywords:["mouth","playful"],"char":"\ud83d\udc45",fitzpatrick_scale:!1,category:"people"},ear:{keywords:["face","hear","sound","listen"],"char":"\ud83d\udc42",fitzpatrick_scale:!0,category:"people"},nose:{keywords:["smell","sniff"],"char":"\ud83d\udc43",fitzpatrick_scale:!0,category:"people"},eye:{keywords:["face","look","see","watch","stare"],"char":"\ud83d\udc41",fitzpatrick_scale:!1,category:"people"},eyes:{keywords:["look","watch","stalk","peek","see"],"char":"\ud83d\udc40",fitzpatrick_scale:!1,category:"people"},brain:{keywords:["smart","intelligent"],"char":"\ud83e\udde0",fitzpatrick_scale:!1,category:"people"},bust_in_silhouette:{keywords:["user","person","human"],"char":"\ud83d\udc64",fitzpatrick_scale:!1,category:"people"},busts_in_silhouette:{keywords:["user","person","human","group","team"],"char":"\ud83d\udc65",fitzpatrick_scale:!1,category:"people"},speaking_head:{keywords:["user","person","human","sing","say","talk"],"char":"\ud83d\udde3",fitzpatrick_scale:!1,category:"people"},baby:{keywords:["child","boy","girl","toddler"],"char":"\ud83d\udc76",fitzpatrick_scale:!0,category:"people"},child:{keywords:["gender-neutral","young"],"char":"\ud83e\uddd2",fitzpatrick_scale:!0,category:"people"},boy:{keywords:["man","male","guy","teenager"],"char":"\ud83d\udc66",fitzpatrick_scale:!0,category:"people"},girl:{keywords:["female","woman","teenager"],"char":"\ud83d\udc67",fitzpatrick_scale:!0,category:"people"},adult:{keywords:["gender-neutral","person"],"char":"\ud83e\uddd1",fitzpatrick_scale:!0,category:"people"},man:{keywords:["mustache","father","dad","guy","classy","sir","moustache"],"char":"\ud83d\udc68",fitzpatrick_scale:!0,category:"people"},woman:{keywords:["female","girls","lady"],"char":"\ud83d\udc69",fitzpatrick_scale:!0,category:"people"},blonde_woman:{keywords:["woman","female","girl","blonde","person"],"char":"\ud83d\udc71\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},blonde_man:{keywords:["man","male","boy","blonde","guy","person"],"char":"\ud83d\udc71",fitzpatrick_scale:!0,category:"people"},bearded_person:{keywords:["person","bewhiskered"],"char":"\ud83e\uddd4",fitzpatrick_scale:!0,category:"people"},older_adult:{keywords:["human","elder","senior","gender-neutral"],"char":"\ud83e\uddd3",fitzpatrick_scale:!0,category:"people"},older_man:{keywords:["human","male","men","old","elder","senior"],"char":"\ud83d\udc74",fitzpatrick_scale:!0,category:"people"},older_woman:{keywords:["human","female","women","lady","old","elder","senior"],"char":"\ud83d\udc75",fitzpatrick_scale:!0,category:"people"},man_with_gua_pi_mao:{keywords:["male","boy","chinese"],"char":"\ud83d\udc72",fitzpatrick_scale:!0,category:"people"},woman_with_headscarf:{keywords:["female","hijab","mantilla","tichel"],"char":"\ud83e\uddd5",fitzpatrick_scale:!0,category:"people"},woman_with_turban:{keywords:["female","indian","hinduism","arabs","woman"],"char":"\ud83d\udc73\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_with_turban:{keywords:["male","indian","hinduism","arabs"],"char":"\ud83d\udc73",fitzpatrick_scale:!0,category:"people"},policewoman:{keywords:["woman","police","law","legal","enforcement","arrest","911","female"],"char":"\ud83d\udc6e\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},policeman:{keywords:["man","police","law","legal","enforcement","arrest","911"],"char":"\ud83d\udc6e",fitzpatrick_scale:!0,category:"people"},construction_worker_woman:{keywords:["female","human","wip","build","construction","worker","labor","woman"],"char":"\ud83d\udc77\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},construction_worker_man:{keywords:["male","human","wip","guy","build","construction","worker","labor"],"char":"\ud83d\udc77",fitzpatrick_scale:!0,category:"people"},guardswoman:{keywords:["uk","gb","british","female","royal","woman"],"char":"\ud83d\udc82\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},guardsman:{keywords:["uk","gb","british","male","guy","royal"],"char":"\ud83d\udc82",fitzpatrick_scale:!0,category:"people"},female_detective:{keywords:["human","spy","detective","female","woman"],"char":"\ud83d\udd75\ufe0f\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},male_detective:{keywords:["human","spy","detective"],"char":"\ud83d\udd75",fitzpatrick_scale:!0,category:"people"},woman_health_worker:{keywords:["doctor","nurse","therapist","healthcare","woman","human"],"char":"\ud83d\udc69\u200d\u2695\ufe0f",fitzpatrick_scale:!0,category:"people"},man_health_worker:{keywords:["doctor","nurse","therapist","healthcare","man","human"],"char":"\ud83d\udc68\u200d\u2695\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_farmer:{keywords:["rancher","gardener","woman","human"],"char":"\ud83d\udc69\u200d\ud83c\udf3e",fitzpatrick_scale:!0,category:"people"},man_farmer:{keywords:["rancher","gardener","man","human"],"char":"\ud83d\udc68\u200d\ud83c\udf3e",fitzpatrick_scale:!0,category:"people"},woman_cook:{keywords:["chef","woman","human"],"char":"\ud83d\udc69\u200d\ud83c\udf73",fitzpatrick_scale:!0,category:"people"},man_cook:{keywords:["chef","man","human"],"char":"\ud83d\udc68\u200d\ud83c\udf73",fitzpatrick_scale:!0,category:"people"},woman_student:{keywords:["graduate","woman","human"],"char":"\ud83d\udc69\u200d\ud83c\udf93",fitzpatrick_scale:!0,category:"people"},man_student:{keywords:["graduate","man","human"],"char":"\ud83d\udc68\u200d\ud83c\udf93",fitzpatrick_scale:!0,category:"people"},woman_singer:{keywords:["rockstar","entertainer","woman","human"],"char":"\ud83d\udc69\u200d\ud83c\udfa4",fitzpatrick_scale:!0,category:"people"},man_singer:{keywords:["rockstar","entertainer","man","human"],"char":"\ud83d\udc68\u200d\ud83c\udfa4",fitzpatrick_scale:!0,category:"people"},woman_teacher:{keywords:["instructor","professor","woman","human"],"char":"\ud83d\udc69\u200d\ud83c\udfeb",fitzpatrick_scale:!0,category:"people"},man_teacher:{keywords:["instructor","professor","man","human"],"char":"\ud83d\udc68\u200d\ud83c\udfeb",fitzpatrick_scale:!0,category:"people"},woman_factory_worker:{keywords:["assembly","industrial","woman","human"],"char":"\ud83d\udc69\u200d\ud83c\udfed",fitzpatrick_scale:!0,category:"people"},man_factory_worker:{keywords:["assembly","industrial","man","human"],"char":"\ud83d\udc68\u200d\ud83c\udfed",fitzpatrick_scale:!0,category:"people"},woman_technologist:{keywords:["coder","developer","engineer","programmer","software","woman","human","laptop","computer"],"char":"\ud83d\udc69\u200d\ud83d\udcbb",fitzpatrick_scale:!0,category:"people"},man_technologist:{keywords:["coder","developer","engineer","programmer","software","man","human","laptop","computer"],"char":"\ud83d\udc68\u200d\ud83d\udcbb",fitzpatrick_scale:!0,category:"people"},woman_office_worker:{keywords:["business","manager","woman","human"],"char":"\ud83d\udc69\u200d\ud83d\udcbc",fitzpatrick_scale:!0,category:"people"},man_office_worker:{keywords:["business","manager","man","human"],"char":"\ud83d\udc68\u200d\ud83d\udcbc",fitzpatrick_scale:!0,category:"people"},woman_mechanic:{keywords:["plumber","woman","human","wrench"],"char":"\ud83d\udc69\u200d\ud83d\udd27",fitzpatrick_scale:!0,category:"people"},man_mechanic:{keywords:["plumber","man","human","wrench"],"char":"\ud83d\udc68\u200d\ud83d\udd27",fitzpatrick_scale:!0,category:"people"},woman_scientist:{keywords:["biologist","chemist","engineer","physicist","woman","human"],"char":"\ud83d\udc69\u200d\ud83d\udd2c",fitzpatrick_scale:!0,category:"people"},man_scientist:{keywords:["biologist","chemist","engineer","physicist","man","human"],"char":"\ud83d\udc68\u200d\ud83d\udd2c",fitzpatrick_scale:!0,category:"people"},woman_artist:{keywords:["painter","woman","human"],"char":"\ud83d\udc69\u200d\ud83c\udfa8",fitzpatrick_scale:!0,category:"people"},man_artist:{keywords:["painter","man","human"],"char":"\ud83d\udc68\u200d\ud83c\udfa8",fitzpatrick_scale:!0,category:"people"},woman_firefighter:{keywords:["fireman","woman","human"],"char":"\ud83d\udc69\u200d\ud83d\ude92",fitzpatrick_scale:!0,category:"people"},man_firefighter:{keywords:["fireman","man","human"],"char":"\ud83d\udc68\u200d\ud83d\ude92",fitzpatrick_scale:!0,category:"people"},woman_pilot:{keywords:["aviator","plane","woman","human"],"char":"\ud83d\udc69\u200d\u2708\ufe0f",fitzpatrick_scale:!0,category:"people"},man_pilot:{keywords:["aviator","plane","man","human"],"char":"\ud83d\udc68\u200d\u2708\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_astronaut:{keywords:["space","rocket","woman","human"],"char":"\ud83d\udc69\u200d\ud83d\ude80",fitzpatrick_scale:!0,category:"people"},man_astronaut:{keywords:["space","rocket","man","human"],"char":"\ud83d\udc68\u200d\ud83d\ude80",fitzpatrick_scale:!0,category:"people"},woman_judge:{keywords:["justice","court","woman","human"],"char":"\ud83d\udc69\u200d\u2696\ufe0f",fitzpatrick_scale:!0,category:"people"},man_judge:{keywords:["justice","court","man","human"],"char":"\ud83d\udc68\u200d\u2696\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_superhero:{keywords:["woman","female","good","heroine","superpowers"],"char":"\ud83e\uddb8\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_superhero:{keywords:["man","male","good","hero","superpowers"],"char":"\ud83e\uddb8\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_supervillain:{keywords:["woman","female","evil","bad","criminal","heroine","superpowers"],"char":"\ud83e\uddb9\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_supervillain:{keywords:["man","male","evil","bad","criminal","hero","superpowers"],"char":"\ud83e\uddb9\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},mrs_claus:{keywords:["woman","female","xmas","mother christmas"],"char":"\ud83e\udd36",fitzpatrick_scale:!0,category:"people"},santa:{keywords:["festival","man","male","xmas","father christmas"],"char":"\ud83c\udf85",fitzpatrick_scale:!0,category:"people"},sorceress:{keywords:["woman","female","mage","witch"],"char":"\ud83e\uddd9\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},wizard:{keywords:["man","male","mage","sorcerer"],"char":"\ud83e\uddd9\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_elf:{keywords:["woman","female"],"char":"\ud83e\udddd\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_elf:{keywords:["man","male"],"char":"\ud83e\udddd\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_vampire:{keywords:["woman","female"],"char":"\ud83e\udddb\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_vampire:{keywords:["man","male","dracula"],"char":"\ud83e\udddb\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_zombie:{keywords:["woman","female","undead","walking dead"],"char":"\ud83e\udddf\u200d\u2640\ufe0f",fitzpatrick_scale:!1,category:"people"},man_zombie:{keywords:["man","male","dracula","undead","walking dead"],"char":"\ud83e\udddf\u200d\u2642\ufe0f",fitzpatrick_scale:!1,category:"people"},woman_genie:{keywords:["woman","female"],"char":"\ud83e\uddde\u200d\u2640\ufe0f",fitzpatrick_scale:!1,category:"people"},man_genie:{keywords:["man","male"],"char":"\ud83e\uddde\u200d\u2642\ufe0f",fitzpatrick_scale:!1,category:"people"},mermaid:{keywords:["woman","female","merwoman","ariel"],"char":"\ud83e\udddc\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},merman:{keywords:["man","male","triton"],"char":"\ud83e\udddc\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_fairy:{keywords:["woman","female"],"char":"\ud83e\uddda\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_fairy:{keywords:["man","male"],"char":"\ud83e\uddda\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},angel:{keywords:["heaven","wings","halo"],"char":"\ud83d\udc7c",fitzpatrick_scale:!0,category:"people"},pregnant_woman:{keywords:["baby"],"char":"\ud83e\udd30",fitzpatrick_scale:!0,category:"people"},breastfeeding:{keywords:["nursing","baby"],"char":"\ud83e\udd31",fitzpatrick_scale:!0,category:"people"},princess:{keywords:["girl","woman","female","blond","crown","royal","queen"],"char":"\ud83d\udc78",fitzpatrick_scale:!0,category:"people"},prince:{keywords:["boy","man","male","crown","royal","king"],"char":"\ud83e\udd34",fitzpatrick_scale:!0,category:"people"},bride_with_veil:{keywords:["couple","marriage","wedding","woman","bride"],"char":"\ud83d\udc70",fitzpatrick_scale:!0,category:"people"},man_in_tuxedo:{keywords:["couple","marriage","wedding","groom"],"char":"\ud83e\udd35",fitzpatrick_scale:!0,category:"people"},running_woman:{keywords:["woman","walking","exercise","race","running","female"],"char":"\ud83c\udfc3\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},running_man:{keywords:["man","walking","exercise","race","running"],"char":"\ud83c\udfc3",fitzpatrick_scale:!0,category:"people"},walking_woman:{keywords:["human","feet","steps","woman","female"],"char":"\ud83d\udeb6\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},walking_man:{keywords:["human","feet","steps"],"char":"\ud83d\udeb6",fitzpatrick_scale:!0,category:"people"},dancer:{keywords:["female","girl","woman","fun"],"char":"\ud83d\udc83",fitzpatrick_scale:!0,category:"people"},man_dancing:{keywords:["male","boy","fun","dancer"],"char":"\ud83d\udd7a",fitzpatrick_scale:!0,category:"people"},dancing_women:{keywords:["female","bunny","women","girls"],"char":"\ud83d\udc6f",fitzpatrick_scale:!1,category:"people"},dancing_men:{keywords:["male","bunny","men","boys"],"char":"\ud83d\udc6f\u200d\u2642\ufe0f",fitzpatrick_scale:!1,category:"people"},couple:{keywords:["pair","people","human","love","date","dating","like","affection","valentines","marriage"],"char":"\ud83d\udc6b",fitzpatrick_scale:!1,category:"people"},two_men_holding_hands:{keywords:["pair","couple","love","like","bromance","friendship","people","human"],"char":"\ud83d\udc6c",fitzpatrick_scale:!1,category:"people"},two_women_holding_hands:{keywords:["pair","friendship","couple","love","like","female","people","human"],"char":"\ud83d\udc6d",fitzpatrick_scale:!1,category:"people"},bowing_woman:{keywords:["woman","female","girl"],"char":"\ud83d\ude47\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},bowing_man:{keywords:["man","male","boy"],"char":"\ud83d\ude47",fitzpatrick_scale:!0,category:"people"},man_facepalming:{keywords:["man","male","boy","disbelief"],"char":"\ud83e\udd26\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_facepalming:{keywords:["woman","female","girl","disbelief"],"char":"\ud83e\udd26\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_shrugging:{keywords:["woman","female","girl","confused","indifferent","doubt"],"char":"\ud83e\udd37",fitzpatrick_scale:!0,category:"people"},man_shrugging:{keywords:["man","male","boy","confused","indifferent","doubt"],"char":"\ud83e\udd37\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},tipping_hand_woman:{keywords:["female","girl","woman","human","information"],"char":"\ud83d\udc81",fitzpatrick_scale:!0,category:"people"},tipping_hand_man:{keywords:["male","boy","man","human","information"],"char":"\ud83d\udc81\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},no_good_woman:{keywords:["female","girl","woman","nope"],"char":"\ud83d\ude45",fitzpatrick_scale:!0,category:"people"},no_good_man:{keywords:["male","boy","man","nope"],"char":"\ud83d\ude45\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},ok_woman:{keywords:["women","girl","female","pink","human","woman"],"char":"\ud83d\ude46",fitzpatrick_scale:!0,category:"people"},ok_man:{keywords:["men","boy","male","blue","human","man"],"char":"\ud83d\ude46\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},raising_hand_woman:{keywords:["female","girl","woman"],"char":"\ud83d\ude4b",fitzpatrick_scale:!0,category:"people"},raising_hand_man:{keywords:["male","boy","man"],"char":"\ud83d\ude4b\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},pouting_woman:{keywords:["female","girl","woman"],"char":"\ud83d\ude4e",fitzpatrick_scale:!0,category:"people"},pouting_man:{keywords:["male","boy","man"],"char":"\ud83d\ude4e\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},frowning_woman:{keywords:["female","girl","woman","sad","depressed","discouraged","unhappy"],"char":"\ud83d\ude4d",fitzpatrick_scale:!0,category:"people"},frowning_man:{keywords:["male","boy","man","sad","depressed","discouraged","unhappy"],"char":"\ud83d\ude4d\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},haircut_woman:{keywords:["female","girl","woman"],"char":"\ud83d\udc87",fitzpatrick_scale:!0,category:"people"},haircut_man:{keywords:["male","boy","man"],"char":"\ud83d\udc87\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},massage_woman:{keywords:["female","girl","woman","head"],"char":"\ud83d\udc86",fitzpatrick_scale:!0,category:"people"},massage_man:{keywords:["male","boy","man","head"],"char":"\ud83d\udc86\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_in_steamy_room:{keywords:["female","woman","spa","steamroom","sauna"],"char":"\ud83e\uddd6\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_in_steamy_room:{keywords:["male","man","spa","steamroom","sauna"],"char":"\ud83e\uddd6\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},couple_with_heart_woman_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],"char":"\ud83d\udc91",fitzpatrick_scale:!1,category:"people"},couple_with_heart_woman_woman:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],"char":"\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc69",fitzpatrick_scale:!1,category:"people"},couple_with_heart_man_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],"char":"\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68",fitzpatrick_scale:!1,category:"people"},couplekiss_man_woman:{keywords:["pair","valentines","love","like","dating","marriage"],"char":"\ud83d\udc8f",fitzpatrick_scale:!1,category:"people"},couplekiss_woman_woman:{keywords:["pair","valentines","love","like","dating","marriage"],"char":"\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69",fitzpatrick_scale:!1,category:"people"},couplekiss_man_man:{keywords:["pair","valentines","love","like","dating","marriage"],"char":"\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68",fitzpatrick_scale:!1,category:"people"},family_man_woman_boy:{keywords:["home","parents","child","mom","dad","father","mother","people","human"],"char":"\ud83d\udc6a",fitzpatrick_scale:!1,category:"people"},family_man_woman_girl:{keywords:["home","parents","people","human","child"],"char":"\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67",fitzpatrick_scale:!1,category:"people"},family_man_woman_girl_boy:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_man_woman_boy_boy:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_man_woman_girl_girl:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67",fitzpatrick_scale:!1,category:"people"},family_woman_woman_boy:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67",fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl_boy:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_woman_woman_boy_boy:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl_girl:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67",fitzpatrick_scale:!1,category:"people"},family_man_man_boy:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_man_man_girl:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67",fitzpatrick_scale:!1,category:"people"},family_man_man_girl_boy:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_man_man_boy_boy:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_man_man_girl_girl:{keywords:["home","parents","people","human","children"],"char":"\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67",fitzpatrick_scale:!1,category:"people"},family_woman_boy:{keywords:["home","parent","people","human","child"],"char":"\ud83d\udc69\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_woman_girl:{keywords:["home","parent","people","human","child"],"char":"\ud83d\udc69\u200d\ud83d\udc67",fitzpatrick_scale:!1,category:"people"},family_woman_girl_boy:{keywords:["home","parent","people","human","children"],"char":"\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_woman_boy_boy:{keywords:["home","parent","people","human","children"],"char":"\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_woman_girl_girl:{keywords:["home","parent","people","human","children"],"char":"\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67",fitzpatrick_scale:!1,category:"people"},family_man_boy:{keywords:["home","parent","people","human","child"],"char":"\ud83d\udc68\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_man_girl:{keywords:["home","parent","people","human","child"],"char":"\ud83d\udc68\u200d\ud83d\udc67",fitzpatrick_scale:!1,category:"people"},family_man_girl_boy:{keywords:["home","parent","people","human","children"],"char":"\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_man_boy_boy:{keywords:["home","parent","people","human","children"],"char":"\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66",fitzpatrick_scale:!1,category:"people"},family_man_girl_girl:{keywords:["home","parent","people","human","children"],"char":"\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67",fitzpatrick_scale:!1,category:"people"},yarn:{keywords:["ball","crochet","knit"],"char":"\ud83e\uddf6",fitzpatrick_scale:!1,category:"people"},thread:{keywords:["needle","sewing","spool","string"],"char":"\ud83e\uddf5",fitzpatrick_scale:!1,category:"people"},coat:{keywords:["jacket"],"char":"\ud83e\udde5",fitzpatrick_scale:!1,category:"people"},labcoat:{keywords:["doctor","experiment","scientist","chemist"],"char":"\ud83e\udd7c",fitzpatrick_scale:!1,category:"people"},womans_clothes:{keywords:["fashion","shopping_bags","female"],"char":"\ud83d\udc5a",fitzpatrick_scale:!1,category:"people"},tshirt:{keywords:["fashion","cloth","casual","shirt","tee"],"char":"\ud83d\udc55",fitzpatrick_scale:!1,category:"people"},jeans:{keywords:["fashion","shopping"],"char":"\ud83d\udc56",fitzpatrick_scale:!1,category:"people"},necktie:{keywords:["shirt","suitup","formal","fashion","cloth","business"],"char":"\ud83d\udc54",fitzpatrick_scale:!1,category:"people"},dress:{keywords:["clothes","fashion","shopping"],"char":"\ud83d\udc57",fitzpatrick_scale:!1,category:"people"},bikini:{keywords:["swimming","female","woman","girl","fashion","beach","summer"],"char":"\ud83d\udc59",fitzpatrick_scale:!1,category:"people"},kimono:{keywords:["dress","fashion","women","female","japanese"],"char":"\ud83d\udc58",fitzpatrick_scale:!1,category:"people"},lipstick:{keywords:["female","girl","fashion","woman"],"char":"\ud83d\udc84",fitzpatrick_scale:!1,category:"people"},kiss:{keywords:["face","lips","love","like","affection","valentines"],"char":"\ud83d\udc8b",fitzpatrick_scale:!1,category:"people"},footprints:{keywords:["feet","tracking","walking","beach"],"char":"\ud83d\udc63",fitzpatrick_scale:!1,category:"people"},flat_shoe:{keywords:["ballet","slip-on","slipper"],"char":"\ud83e\udd7f",fitzpatrick_scale:!1,category:"people"},high_heel:{keywords:["fashion","shoes","female","pumps","stiletto"],"char":"\ud83d\udc60",fitzpatrick_scale:!1,category:"people"},sandal:{keywords:["shoes","fashion","flip flops"],"char":"\ud83d\udc61",fitzpatrick_scale:!1,category:"people"},boot:{keywords:["shoes","fashion"],"char":"\ud83d\udc62",fitzpatrick_scale:!1,category:"people"},mans_shoe:{keywords:["fashion","male"],"char":"\ud83d\udc5e",fitzpatrick_scale:!1,category:"people"},athletic_shoe:{keywords:["shoes","sports","sneakers"],"char":"\ud83d\udc5f",fitzpatrick_scale:!1,category:"people"},hiking_boot:{keywords:["backpacking","camping","hiking"],"char":"\ud83e\udd7e",fitzpatrick_scale:!1,category:"people"},socks:{keywords:["stockings","clothes"],"char":"\ud83e\udde6",fitzpatrick_scale:!1,category:"people"},gloves:{keywords:["hands","winter","clothes"],"char":"\ud83e\udde4",fitzpatrick_scale:!1,category:"people"},scarf:{keywords:["neck","winter","clothes"],"char":"\ud83e\udde3",fitzpatrick_scale:!1,category:"people"},womans_hat:{keywords:["fashion","accessories","female","lady","spring"],"char":"\ud83d\udc52",fitzpatrick_scale:!1,category:"people"},tophat:{keywords:["magic","gentleman","classy","circus"],"char":"\ud83c\udfa9",fitzpatrick_scale:!1,category:"people"},billed_hat:{keywords:["cap","baseball"],"char":"\ud83e\udde2",fitzpatrick_scale:!1,category:"people"},rescue_worker_helmet:{keywords:["construction","build"],"char":"\u26d1",fitzpatrick_scale:!1,category:"people"},mortar_board:{keywords:["school","college","degree","university","graduation","cap","hat","legal","learn","education"],"char":"\ud83c\udf93",fitzpatrick_scale:!1,category:"people"},crown:{keywords:["king","kod","leader","royalty","lord"],"char":"\ud83d\udc51",fitzpatrick_scale:!1,category:"people"},school_satchel:{keywords:["student","education","bag","backpack"],"char":"\ud83c\udf92",fitzpatrick_scale:!1,category:"people"},luggage:{keywords:["packing","travel"],"char":"\ud83e\uddf3",fitzpatrick_scale:!1,category:"people"},pouch:{keywords:["bag","accessories","shopping"],"char":"\ud83d\udc5d",fitzpatrick_scale:!1,category:"people"},purse:{keywords:["fashion","accessories","money","sales","shopping"],"char":"\ud83d\udc5b",fitzpatrick_scale:!1,category:"people"},handbag:{keywords:["fashion","accessory","accessories","shopping"],"char":"\ud83d\udc5c",fitzpatrick_scale:!1,category:"people"},briefcase:{keywords:["business","documents","work","law","legal","job","career"],"char":"\ud83d\udcbc",fitzpatrick_scale:!1,category:"people"},eyeglasses:{keywords:["fashion","accessories","eyesight","nerdy","dork","geek"],"char":"\ud83d\udc53",fitzpatrick_scale:!1,category:"people"},dark_sunglasses:{keywords:["face","cool","accessories"],"char":"\ud83d\udd76",fitzpatrick_scale:!1,category:"people"},goggles:{keywords:["eyes","protection","safety"],"char":"\ud83e\udd7d",fitzpatrick_scale:!1,category:"people"},ring:{keywords:["wedding","propose","marriage","valentines","diamond","fashion","jewelry","gem","engagement"],"char":"\ud83d\udc8d",fitzpatrick_scale:!1,category:"people"},closed_umbrella:{keywords:["weather","rain","drizzle"],"char":"\ud83c\udf02",fitzpatrick_scale:!1,category:"people"},dog:{keywords:["animal","friend","nature","woof","puppy","pet","faithful"],"char":"\ud83d\udc36",fitzpatrick_scale:!1,category:"animals_and_nature"},cat:{keywords:["animal","meow","nature","pet","kitten"],"char":"\ud83d\udc31",fitzpatrick_scale:!1,category:"animals_and_nature"},mouse:{keywords:["animal","nature","cheese_wedge","rodent"],"char":"\ud83d\udc2d",fitzpatrick_scale:!1,category:"animals_and_nature"},hamster:{keywords:["animal","nature"],"char":"\ud83d\udc39",fitzpatrick_scale:!1,category:"animals_and_nature"},rabbit:{keywords:["animal","nature","pet","spring","magic","bunny"],"char":"\ud83d\udc30",fitzpatrick_scale:!1,category:"animals_and_nature"},fox_face:{keywords:["animal","nature","face"],"char":"\ud83e\udd8a",fitzpatrick_scale:!1,category:"animals_and_nature"},bear:{keywords:["animal","nature","wild"],"char":"\ud83d\udc3b",fitzpatrick_scale:!1,category:"animals_and_nature"},panda_face:{keywords:["animal","nature","panda"],"char":"\ud83d\udc3c",fitzpatrick_scale:!1,category:"animals_and_nature"},koala:{keywords:["animal","nature"],"char":"\ud83d\udc28",fitzpatrick_scale:!1,category:"animals_and_nature"},tiger:{keywords:["animal","cat","danger","wild","nature","roar"],"char":"\ud83d\udc2f",fitzpatrick_scale:!1,category:"animals_and_nature"},lion:{keywords:["animal","nature"],"char":"\ud83e\udd81",fitzpatrick_scale:!1,category:"animals_and_nature"},cow:{keywords:["beef","ox","animal","nature","moo","milk"],"char":"\ud83d\udc2e",fitzpatrick_scale:!1,category:"animals_and_nature"},pig:{keywords:["animal","oink","nature"],"char":"\ud83d\udc37",fitzpatrick_scale:!1,category:"animals_and_nature"},pig_nose:{keywords:["animal","oink"],"char":"\ud83d\udc3d",fitzpatrick_scale:!1,category:"animals_and_nature"},frog:{keywords:["animal","nature","croak","toad"],"char":"\ud83d\udc38",fitzpatrick_scale:!1,category:"animals_and_nature"},squid:{keywords:["animal","nature","ocean","sea"],"char":"\ud83e\udd91",fitzpatrick_scale:!1,category:"animals_and_nature"},octopus:{keywords:["animal","creature","ocean","sea","nature","beach"],"char":"\ud83d\udc19",fitzpatrick_scale:!1,category:"animals_and_nature"},shrimp:{keywords:["animal","ocean","nature","seafood"],"char":"\ud83e\udd90",fitzpatrick_scale:!1,category:"animals_and_nature"},monkey_face:{keywords:["animal","nature","circus"],"char":"\ud83d\udc35",fitzpatrick_scale:!1,category:"animals_and_nature"},gorilla:{keywords:["animal","nature","circus"],"char":"\ud83e\udd8d",fitzpatrick_scale:!1,category:"animals_and_nature"},see_no_evil:{keywords:["monkey","animal","nature","haha"],"char":"\ud83d\ude48",fitzpatrick_scale:!1,category:"animals_and_nature"},hear_no_evil:{keywords:["animal","monkey","nature"],"char":"\ud83d\ude49",fitzpatrick_scale:!1,category:"animals_and_nature"},speak_no_evil:{keywords:["monkey","animal","nature","omg"],"char":"\ud83d\ude4a",fitzpatrick_scale:!1,category:"animals_and_nature"},monkey:{keywords:["animal","nature","banana","circus"],"char":"\ud83d\udc12",fitzpatrick_scale:!1,category:"animals_and_nature"},chicken:{keywords:["animal","cluck","nature","bird"],"char":"\ud83d\udc14",fitzpatrick_scale:!1,category:"animals_and_nature"},penguin:{keywords:["animal","nature"],"char":"\ud83d\udc27",fitzpatrick_scale:!1,category:"animals_and_nature"},bird:{keywords:["animal","nature","fly","tweet","spring"],"char":"\ud83d\udc26",fitzpatrick_scale:!1,category:"animals_and_nature"},baby_chick:{keywords:["animal","chicken","bird"],"char":"\ud83d\udc24",fitzpatrick_scale:!1,category:"animals_and_nature"},hatching_chick:{keywords:["animal","chicken","egg","born","baby","bird"],"char":"\ud83d\udc23",fitzpatrick_scale:!1,category:"animals_and_nature"},hatched_chick:{keywords:["animal","chicken","baby","bird"],"char":"\ud83d\udc25",fitzpatrick_scale:!1,category:"animals_and_nature"},duck:{keywords:["animal","nature","bird","mallard"],"char":"\ud83e\udd86",fitzpatrick_scale:!1,category:"animals_and_nature"},eagle:{keywords:["animal","nature","bird"],"char":"\ud83e\udd85",fitzpatrick_scale:!1,category:"animals_and_nature"},owl:{keywords:["animal","nature","bird","hoot"],"char":"\ud83e\udd89",fitzpatrick_scale:!1,category:"animals_and_nature"},bat:{keywords:["animal","nature","blind","vampire"],"char":"\ud83e\udd87",fitzpatrick_scale:!1,category:"animals_and_nature"},wolf:{keywords:["animal","nature","wild"],"char":"\ud83d\udc3a",fitzpatrick_scale:!1,category:"animals_and_nature"},boar:{keywords:["animal","nature"],"char":"\ud83d\udc17",fitzpatrick_scale:!1,category:"animals_and_nature"},horse:{keywords:["animal","brown","nature"],"char":"\ud83d\udc34",fitzpatrick_scale:!1,category:"animals_and_nature"},unicorn:{keywords:["animal","nature","mystical"],"char":"\ud83e\udd84",fitzpatrick_scale:!1,category:"animals_and_nature"},honeybee:{keywords:["animal","insect","nature","bug","spring","honey"],"char":"\ud83d\udc1d",fitzpatrick_scale:!1,category:"animals_and_nature"},bug:{keywords:["animal","insect","nature","worm"],"char":"\ud83d\udc1b",fitzpatrick_scale:!1,category:"animals_and_nature"},butterfly:{keywords:["animal","insect","nature","caterpillar"],"char":"\ud83e\udd8b",fitzpatrick_scale:!1,category:"animals_and_nature"},snail:{keywords:["slow","animal","shell"],"char":"\ud83d\udc0c",fitzpatrick_scale:!1,category:"animals_and_nature"},beetle:{keywords:["animal","insect","nature","ladybug"],"char":"\ud83d\udc1e",fitzpatrick_scale:!1,category:"animals_and_nature"},ant:{keywords:["animal","insect","nature","bug"],"char":"\ud83d\udc1c",fitzpatrick_scale:!1,category:"animals_and_nature"},grasshopper:{keywords:["animal","cricket","chirp"],"char":"\ud83e\udd97",fitzpatrick_scale:!1,category:"animals_and_nature"},spider:{keywords:["animal","arachnid"],"char":"\ud83d\udd77",fitzpatrick_scale:!1,category:"animals_and_nature"},scorpion:{keywords:["animal","arachnid"],"char":"\ud83e\udd82",fitzpatrick_scale:!1,category:"animals_and_nature"},crab:{keywords:["animal","crustacean"],"char":"\ud83e\udd80",fitzpatrick_scale:!1,category:"animals_and_nature"},snake:{keywords:["animal","evil","nature","hiss","python"],"char":"\ud83d\udc0d",fitzpatrick_scale:!1,category:"animals_and_nature"},lizard:{keywords:["animal","nature","reptile"],"char":"\ud83e\udd8e",fitzpatrick_scale:!1,category:"animals_and_nature"},"t-rex":{keywords:["animal","nature","dinosaur","tyrannosaurus","extinct"],"char":"\ud83e\udd96",fitzpatrick_scale:!1,category:"animals_and_nature"},sauropod:{keywords:["animal","nature","dinosaur","brachiosaurus","brontosaurus","diplodocus","extinct"],"char":"\ud83e\udd95",fitzpatrick_scale:!1,category:"animals_and_nature"},turtle:{keywords:["animal","slow","nature","tortoise"],"char":"\ud83d\udc22",fitzpatrick_scale:!1,category:"animals_and_nature"},tropical_fish:{keywords:["animal","swim","ocean","beach","nemo"],"char":"\ud83d\udc20",fitzpatrick_scale:!1,category:"animals_and_nature"},fish:{keywords:["animal","food","nature"],"char":"\ud83d\udc1f",fitzpatrick_scale:!1,category:"animals_and_nature"},blowfish:{keywords:["animal","nature","food","sea","ocean"],"char":"\ud83d\udc21",fitzpatrick_scale:!1,category:"animals_and_nature"},dolphin:{keywords:["animal","nature","fish","sea","ocean","flipper","fins","beach"],"char":"\ud83d\udc2c",fitzpatrick_scale:!1,category:"animals_and_nature"},shark:{keywords:["animal","nature","fish","sea","ocean","jaws","fins","beach"],"char":"\ud83e\udd88",fitzpatrick_scale:!1,category:"animals_and_nature"},whale:{keywords:["animal","nature","sea","ocean"],"char":"\ud83d\udc33",fitzpatrick_scale:!1,category:"animals_and_nature"},whale2:{keywords:["animal","nature","sea","ocean"],"char":"\ud83d\udc0b",fitzpatrick_scale:!1,category:"animals_and_nature"},crocodile:{keywords:["animal","nature","reptile","lizard","alligator"],"char":"\ud83d\udc0a",fitzpatrick_scale:!1,category:"animals_and_nature"},leopard:{keywords:["animal","nature"],"char":"\ud83d\udc06",fitzpatrick_scale:!1,category:"animals_and_nature"},zebra:{keywords:["animal","nature","stripes","safari"],"char":"\ud83e\udd93",fitzpatrick_scale:!1,category:"animals_and_nature"},tiger2:{keywords:["animal","nature","roar"],"char":"\ud83d\udc05",fitzpatrick_scale:!1,category:"animals_and_nature"},water_buffalo:{keywords:["animal","nature","ox","cow"],"char":"\ud83d\udc03",fitzpatrick_scale:!1,category:"animals_and_nature"},ox:{keywords:["animal","cow","beef"],"char":"\ud83d\udc02",fitzpatrick_scale:!1,category:"animals_and_nature"},cow2:{keywords:["beef","ox","animal","nature","moo","milk"],"char":"\ud83d\udc04",fitzpatrick_scale:!1,category:"animals_and_nature"},deer:{keywords:["animal","nature","horns","venison"],"char":"\ud83e\udd8c",fitzpatrick_scale:!1,category:"animals_and_nature"},dromedary_camel:{keywords:["animal","hot","desert","hump"],"char":"\ud83d\udc2a",fitzpatrick_scale:!1,category:"animals_and_nature"},camel:{keywords:["animal","nature","hot","desert","hump"],"char":"\ud83d\udc2b",fitzpatrick_scale:!1,category:"animals_and_nature"},giraffe:{keywords:["animal","nature","spots","safari"],"char":"\ud83e\udd92",fitzpatrick_scale:!1,category:"animals_and_nature"},elephant:{keywords:["animal","nature","nose","th","circus"],"char":"\ud83d\udc18",fitzpatrick_scale:!1,category:"animals_and_nature"},rhinoceros:{keywords:["animal","nature","horn"],"char":"\ud83e\udd8f",fitzpatrick_scale:!1,category:"animals_and_nature"},goat:{keywords:["animal","nature"],"char":"\ud83d\udc10",fitzpatrick_scale:!1,category:"animals_and_nature"},ram:{keywords:["animal","sheep","nature"],"char":"\ud83d\udc0f",fitzpatrick_scale:!1,category:"animals_and_nature"},sheep:{keywords:["animal","nature","wool","shipit"],"char":"\ud83d\udc11",fitzpatrick_scale:!1,category:"animals_and_nature"},racehorse:{keywords:["animal","gamble","luck"],"char":"\ud83d\udc0e",fitzpatrick_scale:!1,category:"animals_and_nature"},pig2:{keywords:["animal","nature"],"char":"\ud83d\udc16",fitzpatrick_scale:!1,category:"animals_and_nature"},rat:{keywords:["animal","mouse","rodent"],"char":"\ud83d\udc00",fitzpatrick_scale:!1,category:"animals_and_nature"},mouse2:{keywords:["animal","nature","rodent"],"char":"\ud83d\udc01",fitzpatrick_scale:!1,category:"animals_and_nature"},rooster:{keywords:["animal","nature","chicken"],"char":"\ud83d\udc13",fitzpatrick_scale:!1,category:"animals_and_nature"},turkey:{keywords:["animal","bird"],"char":"\ud83e\udd83",fitzpatrick_scale:!1,category:"animals_and_nature"},dove:{keywords:["animal","bird"],"char":"\ud83d\udd4a",fitzpatrick_scale:!1,category:"animals_and_nature"},dog2:{keywords:["animal","nature","friend","doge","pet","faithful"],"char":"\ud83d\udc15",fitzpatrick_scale:!1,category:"animals_and_nature"},poodle:{keywords:["dog","animal","101","nature","pet"],"char":"\ud83d\udc29",fitzpatrick_scale:!1,category:"animals_and_nature"},cat2:{keywords:["animal","meow","pet","cats"],"char":"\ud83d\udc08",fitzpatrick_scale:!1,category:"animals_and_nature"},rabbit2:{keywords:["animal","nature","pet","magic","spring"],"char":"\ud83d\udc07",fitzpatrick_scale:!1,category:"animals_and_nature"},chipmunk:{keywords:["animal","nature","rodent","squirrel"],"char":"\ud83d\udc3f",fitzpatrick_scale:!1,category:"animals_and_nature"},hedgehog:{keywords:["animal","nature","spiny"],"char":"\ud83e\udd94",fitzpatrick_scale:!1,category:"animals_and_nature"},raccoon:{keywords:["animal","nature"],"char":"\ud83e\udd9d",fitzpatrick_scale:!1,category:"animals_and_nature"},llama:{keywords:["animal","nature","alpaca"],"char":"\ud83e\udd99",fitzpatrick_scale:!1,category:"animals_and_nature"},hippopotamus:{keywords:["animal","nature"],"char":"\ud83e\udd9b",fitzpatrick_scale:!1,category:"animals_and_nature"},kangaroo:{keywords:["animal","nature","australia","joey","hop","marsupial"],"char":"\ud83e\udd98",fitzpatrick_scale:!1,category:"animals_and_nature"},badger:{keywords:["animal","nature","honey"],"char":"\ud83e\udda1",fitzpatrick_scale:!1,category:"animals_and_nature"},swan:{keywords:["animal","nature","bird"],"char":"\ud83e\udda2",fitzpatrick_scale:!1,category:"animals_and_nature"},peacock:{keywords:["animal","nature","peahen","bird"],"char":"\ud83e\udd9a",fitzpatrick_scale:!1,category:"animals_and_nature"},parrot:{keywords:["animal","nature","bird","pirate","talk"],"char":"\ud83e\udd9c",fitzpatrick_scale:!1,category:"animals_and_nature"},lobster:{keywords:["animal","nature","bisque","claws","seafood"],"char":"\ud83e\udd9e",fitzpatrick_scale:!1,category:"animals_and_nature"},mosquito:{keywords:["animal","nature","insect","malaria"],"char":"\ud83e\udd9f",fitzpatrick_scale:!1,category:"animals_and_nature"},paw_prints:{keywords:["animal","tracking","footprints","dog","cat","pet","feet"],"char":"\ud83d\udc3e",fitzpatrick_scale:!1,category:"animals_and_nature"},dragon:{keywords:["animal","myth","nature","chinese","green"],"char":"\ud83d\udc09",fitzpatrick_scale:!1,category:"animals_and_nature"},dragon_face:{keywords:["animal","myth","nature","chinese","green"],"char":"\ud83d\udc32",fitzpatrick_scale:!1,category:"animals_and_nature"},cactus:{keywords:["vegetable","plant","nature"],"char":"\ud83c\udf35",fitzpatrick_scale:!1,category:"animals_and_nature"},christmas_tree:{keywords:["festival","vacation","december","xmas","celebration"],"char":"\ud83c\udf84",fitzpatrick_scale:!1,category:"animals_and_nature"},evergreen_tree:{keywords:["plant","nature"],"char":"\ud83c\udf32",fitzpatrick_scale:!1,category:"animals_and_nature"},deciduous_tree:{keywords:["plant","nature"],"char":"\ud83c\udf33",fitzpatrick_scale:!1,category:"animals_and_nature"},palm_tree:{keywords:["plant","vegetable","nature","summer","beach","mojito","tropical"],"char":"\ud83c\udf34",fitzpatrick_scale:!1,category:"animals_and_nature"},seedling:{keywords:["plant","nature","grass","lawn","spring"],"char":"\ud83c\udf31",fitzpatrick_scale:!1,category:"animals_and_nature"},herb:{keywords:["vegetable","plant","medicine","weed","grass","lawn"],"char":"\ud83c\udf3f",fitzpatrick_scale:!1,category:"animals_and_nature"},shamrock:{keywords:["vegetable","plant","nature","irish","clover"],"char":"\u2618",fitzpatrick_scale:!1,category:"animals_and_nature"},four_leaf_clover:{keywords:["vegetable","plant","nature","lucky","irish"],"char":"\ud83c\udf40",fitzpatrick_scale:!1,category:"animals_and_nature"},bamboo:{keywords:["plant","nature","vegetable","panda","pine_decoration"],"char":"\ud83c\udf8d",fitzpatrick_scale:!1,category:"animals_and_nature"},tanabata_tree:{keywords:["plant","nature","branch","summer"],"char":"\ud83c\udf8b",fitzpatrick_scale:!1,category:"animals_and_nature"},leaves:{keywords:["nature","plant","tree","vegetable","grass","lawn","spring"],"char":"\ud83c\udf43",fitzpatrick_scale:!1,category:"animals_and_nature"},fallen_leaf:{keywords:["nature","plant","vegetable","leaves"],"char":"\ud83c\udf42",fitzpatrick_scale:!1,category:"animals_and_nature"},maple_leaf:{keywords:["nature","plant","vegetable","ca","fall"],"char":"\ud83c\udf41",fitzpatrick_scale:!1,category:"animals_and_nature"},ear_of_rice:{keywords:["nature","plant"],"char":"\ud83c\udf3e",fitzpatrick_scale:!1,category:"animals_and_nature"},hibiscus:{keywords:["plant","vegetable","flowers","beach"],"char":"\ud83c\udf3a",fitzpatrick_scale:!1,category:"animals_and_nature"},sunflower:{keywords:["nature","plant","fall"],"char":"\ud83c\udf3b",fitzpatrick_scale:!1,category:"animals_and_nature"},rose:{keywords:["flowers","valentines","love","spring"],"char":"\ud83c\udf39",fitzpatrick_scale:!1,category:"animals_and_nature"},wilted_flower:{keywords:["plant","nature","flower"],"char":"\ud83e\udd40",fitzpatrick_scale:!1,category:"animals_and_nature"},tulip:{keywords:["flowers","plant","nature","summer","spring"],"char":"\ud83c\udf37",fitzpatrick_scale:!1,category:"animals_and_nature"},blossom:{keywords:["nature","flowers","yellow"],"char":"\ud83c\udf3c",fitzpatrick_scale:!1,category:"animals_and_nature"},cherry_blossom:{keywords:["nature","plant","spring","flower"],"char":"\ud83c\udf38",fitzpatrick_scale:!1,category:"animals_and_nature"},bouquet:{keywords:["flowers","nature","spring"],"char":"\ud83d\udc90",fitzpatrick_scale:!1,category:"animals_and_nature"},mushroom:{keywords:["plant","vegetable"],"char":"\ud83c\udf44",fitzpatrick_scale:!1,category:"animals_and_nature"},chestnut:{keywords:["food","squirrel"],"char":"\ud83c\udf30",fitzpatrick_scale:!1,category:"animals_and_nature"},jack_o_lantern:{keywords:["halloween","light","pumpkin","creepy","fall"],"char":"\ud83c\udf83",fitzpatrick_scale:!1,category:"animals_and_nature"},shell:{keywords:["nature","sea","beach"],"char":"\ud83d\udc1a",fitzpatrick_scale:!1,category:"animals_and_nature"},spider_web:{keywords:["animal","insect","arachnid","silk"],"char":"\ud83d\udd78",fitzpatrick_scale:!1,category:"animals_and_nature"},earth_americas:{keywords:["globe","world","USA","international"],"char":"\ud83c\udf0e",fitzpatrick_scale:!1,category:"animals_and_nature"},earth_africa:{keywords:["globe","world","international"],"char":"\ud83c\udf0d",fitzpatrick_scale:!1,category:"animals_and_nature"},earth_asia:{keywords:["globe","world","east","international"],"char":"\ud83c\udf0f",fitzpatrick_scale:!1,category:"animals_and_nature"},full_moon:{keywords:["nature","yellow","twilight","planet","space","night","evening","sleep"],"char":"\ud83c\udf15",fitzpatrick_scale:!1,category:"animals_and_nature"},waning_gibbous_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep","waxing_gibbous_moon"],"char":"\ud83c\udf16",fitzpatrick_scale:!1,category:"animals_and_nature"},last_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":"\ud83c\udf17",fitzpatrick_scale:!1,category:"animals_and_nature"},waning_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":"\ud83c\udf18",fitzpatrick_scale:!1,category:"animals_and_nature"},new_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":"\ud83c\udf11",fitzpatrick_scale:!1,category:"animals_and_nature"},waxing_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":"\ud83c\udf12",fitzpatrick_scale:!1,category:"animals_and_nature"},first_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":"\ud83c\udf13",fitzpatrick_scale:!1,category:"animals_and_nature"},waxing_gibbous_moon:{keywords:["nature","night","sky","gray","twilight","planet","space","evening","sleep"],"char":"\ud83c\udf14",fitzpatrick_scale:!1,category:"animals_and_nature"},new_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":"\ud83c\udf1a",fitzpatrick_scale:!1,category:"animals_and_nature"},full_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":"\ud83c\udf1d",fitzpatrick_scale:!1,category:"animals_and_nature"},first_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":"\ud83c\udf1b",fitzpatrick_scale:!1,category:"animals_and_nature"},last_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],"char":"\ud83c\udf1c",fitzpatrick_scale:!1,category:"animals_and_nature"},sun_with_face:{keywords:["nature","morning","sky"],"char":"\ud83c\udf1e",fitzpatrick_scale:!1,category:"animals_and_nature"},crescent_moon:{keywords:["night","sleep","sky","evening","magic"],"char":"\ud83c\udf19",fitzpatrick_scale:!1,category:"animals_and_nature"},star:{keywords:["night","yellow"],"char":"\u2b50",fitzpatrick_scale:!1,category:"animals_and_nature"},star2:{keywords:["night","sparkle","awesome","good","magic"],"char":"\ud83c\udf1f",fitzpatrick_scale:!1,category:"animals_and_nature"},dizzy:{keywords:["star","sparkle","shoot","magic"],"char":"\ud83d\udcab",fitzpatrick_scale:!1,category:"animals_and_nature"},sparkles:{keywords:["stars","shine","shiny","cool","awesome","good","magic"],"char":"\u2728",fitzpatrick_scale:!1,category:"animals_and_nature"},comet:{keywords:["space"],"char":"\u2604",fitzpatrick_scale:!1,category:"animals_and_nature"},sunny:{keywords:["weather","nature","brightness","summer","beach","spring"],"char":"\u2600\ufe0f",fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_small_cloud:{keywords:["weather"],"char":"\ud83c\udf24",fitzpatrick_scale:!1,category:"animals_and_nature"},partly_sunny:{keywords:["weather","nature","cloudy","morning","fall","spring"],"char":"\u26c5",fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_large_cloud:{keywords:["weather"],"char":"\ud83c\udf25",fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_rain_cloud:{keywords:["weather"],"char":"\ud83c\udf26",fitzpatrick_scale:!1,category:"animals_and_nature"},cloud:{keywords:["weather","sky"],"char":"\u2601\ufe0f",fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_rain:{keywords:["weather"],"char":"\ud83c\udf27",fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_lightning_and_rain:{keywords:["weather","lightning"],"char":"\u26c8",fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_lightning:{keywords:["weather","thunder"],"char":"\ud83c\udf29",fitzpatrick_scale:!1,category:"animals_and_nature"},zap:{keywords:["thunder","weather","lightning bolt","fast"],"char":"\u26a1",fitzpatrick_scale:!1,category:"animals_and_nature"},fire:{keywords:["hot","cook","flame"],"char":"\ud83d\udd25",fitzpatrick_scale:!1,category:"animals_and_nature"},boom:{keywords:["bomb","explode","explosion","collision","blown"],"char":"\ud83d\udca5",fitzpatrick_scale:!1,category:"animals_and_nature"},snowflake:{keywords:["winter","season","cold","weather","christmas","xmas"],"char":"\u2744\ufe0f",fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_snow:{keywords:["weather"],"char":"\ud83c\udf28",fitzpatrick_scale:!1,category:"animals_and_nature"},snowman:{keywords:["winter","season","cold","weather","christmas","xmas","frozen","without_snow"],"char":"\u26c4",fitzpatrick_scale:!1,category:"animals_and_nature"},snowman_with_snow:{keywords:["winter","season","cold","weather","christmas","xmas","frozen"],"char":"\u2603",fitzpatrick_scale:!1,category:"animals_and_nature"},wind_face:{keywords:["gust","air"],"char":"\ud83c\udf2c",fitzpatrick_scale:!1,category:"animals_and_nature"},dash:{keywords:["wind","air","fast","shoo","fart","smoke","puff"],"char":"\ud83d\udca8",fitzpatrick_scale:!1,category:"animals_and_nature"},tornado:{keywords:["weather","cyclone","twister"],"char":"\ud83c\udf2a",fitzpatrick_scale:!1,category:"animals_and_nature"},fog:{keywords:["weather"],"char":"\ud83c\udf2b",fitzpatrick_scale:!1,category:"animals_and_nature"},open_umbrella:{keywords:["weather","spring"],"char":"\u2602",fitzpatrick_scale:!1,category:"animals_and_nature"},umbrella:{keywords:["rainy","weather","spring"],"char":"\u2614",fitzpatrick_scale:!1,category:"animals_and_nature"},droplet:{keywords:["water","drip","faucet","spring"],"char":"\ud83d\udca7",fitzpatrick_scale:!1,category:"animals_and_nature"},sweat_drops:{keywords:["water","drip","oops"],"char":"\ud83d\udca6",fitzpatrick_scale:!1,category:"animals_and_nature"},ocean:{keywords:["sea","water","wave","nature","tsunami","disaster"],"char":"\ud83c\udf0a",fitzpatrick_scale:!1,category:"animals_and_nature"},green_apple:{keywords:["fruit","nature"],"char":"\ud83c\udf4f",fitzpatrick_scale:!1,category:"food_and_drink"},apple:{keywords:["fruit","mac","school"],"char":"\ud83c\udf4e",fitzpatrick_scale:!1,category:"food_and_drink"},pear:{keywords:["fruit","nature","food"],"char":"\ud83c\udf50",fitzpatrick_scale:!1,category:"food_and_drink"},tangerine:{keywords:["food","fruit","nature","orange"],"char":"\ud83c\udf4a",fitzpatrick_scale:!1,category:"food_and_drink"},lemon:{keywords:["fruit","nature"],"char":"\ud83c\udf4b",fitzpatrick_scale:!1,category:"food_and_drink"},banana:{keywords:["fruit","food","monkey"],"char":"\ud83c\udf4c",fitzpatrick_scale:!1,category:"food_and_drink"},watermelon:{keywords:["fruit","food","picnic","summer"],"char":"\ud83c\udf49",fitzpatrick_scale:!1,category:"food_and_drink"},grapes:{keywords:["fruit","food","wine"],"char":"\ud83c\udf47",fitzpatrick_scale:!1,category:"food_and_drink"},strawberry:{keywords:["fruit","food","nature"],"char":"\ud83c\udf53",fitzpatrick_scale:!1,category:"food_and_drink"},melon:{keywords:["fruit","nature","food"],"char":"\ud83c\udf48",fitzpatrick_scale:!1,category:"food_and_drink"},cherries:{keywords:["food","fruit"],"char":"\ud83c\udf52",fitzpatrick_scale:!1,category:"food_and_drink"},peach:{keywords:["fruit","nature","food"],"char":"\ud83c\udf51",fitzpatrick_scale:!1,category:"food_and_drink"},pineapple:{keywords:["fruit","nature","food"],"char":"\ud83c\udf4d",fitzpatrick_scale:!1,category:"food_and_drink"},coconut:{keywords:["fruit","nature","food","palm"],"char":"\ud83e\udd65",fitzpatrick_scale:!1,category:"food_and_drink"},kiwi_fruit:{keywords:["fruit","food"],"char":"\ud83e\udd5d",fitzpatrick_scale:!1,category:"food_and_drink"},mango:{keywords:["fruit","food","tropical"],"char":"\ud83e\udd6d",fitzpatrick_scale:!1,category:"food_and_drink"},avocado:{keywords:["fruit","food"],"char":"\ud83e\udd51",fitzpatrick_scale:!1,category:"food_and_drink"},broccoli:{keywords:["fruit","food","vegetable"],"char":"\ud83e\udd66",fitzpatrick_scale:!1,category:"food_and_drink"},tomato:{keywords:["fruit","vegetable","nature","food"],"char":"\ud83c\udf45",fitzpatrick_scale:!1,category:"food_and_drink"},eggplant:{keywords:["vegetable","nature","food","aubergine"],"char":"\ud83c\udf46",fitzpatrick_scale:!1,category:"food_and_drink"},cucumber:{keywords:["fruit","food","pickle"],"char":"\ud83e\udd52",fitzpatrick_scale:!1,category:"food_and_drink"},carrot:{keywords:["vegetable","food","orange"],"char":"\ud83e\udd55",fitzpatrick_scale:!1,category:"food_and_drink"},hot_pepper:{keywords:["food","spicy","chilli","chili"],"char":"\ud83c\udf36",fitzpatrick_scale:!1,category:"food_and_drink"},potato:{keywords:["food","tuber","vegatable","starch"],"char":"\ud83e\udd54",fitzpatrick_scale:!1,category:"food_and_drink"},corn:{keywords:["food","vegetable","plant"],"char":"\ud83c\udf3d",fitzpatrick_scale:!1,category:"food_and_drink"},leafy_greens:{keywords:["food","vegetable","plant","bok choy","cabbage","kale","lettuce"],"char":"\ud83e\udd6c",fitzpatrick_scale:!1,category:"food_and_drink"},sweet_potato:{keywords:["food","nature"],"char":"\ud83c\udf60",fitzpatrick_scale:!1,category:"food_and_drink"},peanuts:{keywords:["food","nut"],"char":"\ud83e\udd5c",fitzpatrick_scale:!1,category:"food_and_drink"},honey_pot:{keywords:["bees","sweet","kitchen"],"char":"\ud83c\udf6f",fitzpatrick_scale:!1,category:"food_and_drink"},croissant:{keywords:["food","bread","french"],"char":"\ud83e\udd50",fitzpatrick_scale:!1,category:"food_and_drink"},bread:{keywords:["food","wheat","breakfast","toast"],"char":"\ud83c\udf5e",fitzpatrick_scale:!1,category:"food_and_drink"},baguette_bread:{keywords:["food","bread","french"],"char":"\ud83e\udd56",fitzpatrick_scale:!1,category:"food_and_drink"},bagel:{keywords:["food","bread","bakery","schmear"],"char":"\ud83e\udd6f",fitzpatrick_scale:!1,category:"food_and_drink"},pretzel:{keywords:["food","bread","twisted"],"char":"\ud83e\udd68",fitzpatrick_scale:!1,category:"food_and_drink"},cheese:{keywords:["food","chadder"],"char":"\ud83e\uddc0",fitzpatrick_scale:!1,category:"food_and_drink"},egg:{keywords:["food","chicken","breakfast"],"char":"\ud83e\udd5a",fitzpatrick_scale:!1,category:"food_and_drink"},bacon:{keywords:["food","breakfast","pork","pig","meat"],"char":"\ud83e\udd53",fitzpatrick_scale:!1,category:"food_and_drink"},steak:{keywords:["food","cow","meat","cut","chop","lambchop","porkchop"],"char":"\ud83e\udd69",fitzpatrick_scale:!1,category:"food_and_drink"},pancakes:{keywords:["food","breakfast","flapjacks","hotcakes"],"char":"\ud83e\udd5e",fitzpatrick_scale:!1,category:"food_and_drink"},poultry_leg:{keywords:["food","meat","drumstick","bird","chicken","turkey"],"char":"\ud83c\udf57",fitzpatrick_scale:!1,category:"food_and_drink"},meat_on_bone:{keywords:["good","food","drumstick"],"char":"\ud83c\udf56",fitzpatrick_scale:!1,category:"food_and_drink"},bone:{keywords:["skeleton"],"char":"\ud83e\uddb4",fitzpatrick_scale:!1,category:"food_and_drink"},fried_shrimp:{keywords:["food","animal","appetizer","summer"],"char":"\ud83c\udf64",fitzpatrick_scale:!1,category:"food_and_drink"},fried_egg:{keywords:["food","breakfast","kitchen","egg"],"char":"\ud83c\udf73",fitzpatrick_scale:!1,category:"food_and_drink"},hamburger:{keywords:["meat","fast food","beef","cheeseburger","mcdonalds","burger king"],"char":"\ud83c\udf54",fitzpatrick_scale:!1,category:"food_and_drink"},fries:{keywords:["chips","snack","fast food"],"char":"\ud83c\udf5f",fitzpatrick_scale:!1,category:"food_and_drink"},stuffed_flatbread:{keywords:["food","flatbread","stuffed","gyro"],"char":"\ud83e\udd59",fitzpatrick_scale:!1,category:"food_and_drink"},hotdog:{keywords:["food","frankfurter"],"char":"\ud83c\udf2d",fitzpatrick_scale:!1,category:"food_and_drink"},pizza:{keywords:["food","party"],"char":"\ud83c\udf55",fitzpatrick_scale:!1,category:"food_and_drink"},sandwich:{keywords:["food","lunch","bread"],"char":"\ud83e\udd6a",fitzpatrick_scale:!1,category:"food_and_drink"},canned_food:{keywords:["food","soup"],"char":"\ud83e\udd6b",fitzpatrick_scale:!1,category:"food_and_drink"},spaghetti:{keywords:["food","italian","noodle"],"char":"\ud83c\udf5d",fitzpatrick_scale:!1,category:"food_and_drink"},taco:{keywords:["food","mexican"],"char":"\ud83c\udf2e",fitzpatrick_scale:!1,category:"food_and_drink"},burrito:{keywords:["food","mexican"],"char":"\ud83c\udf2f",fitzpatrick_scale:!1,category:"food_and_drink"},green_salad:{keywords:["food","healthy","lettuce"],"char":"\ud83e\udd57",fitzpatrick_scale:!1,category:"food_and_drink"},shallow_pan_of_food:{keywords:["food","cooking","casserole","paella"],"char":"\ud83e\udd58",fitzpatrick_scale:!1,category:"food_and_drink"},ramen:{keywords:["food","japanese","noodle","chopsticks"],"char":"\ud83c\udf5c",fitzpatrick_scale:!1,category:"food_and_drink"},stew:{keywords:["food","meat","soup"],"char":"\ud83c\udf72",fitzpatrick_scale:!1,category:"food_and_drink"},fish_cake:{keywords:["food","japan","sea","beach","narutomaki","pink","swirl","kamaboko","surimi","ramen"],"char":"\ud83c\udf65",fitzpatrick_scale:!1,category:"food_and_drink"},fortune_cookie:{keywords:["food","prophecy"],"char":"\ud83e\udd60",fitzpatrick_scale:!1,category:"food_and_drink"},sushi:{keywords:["food","fish","japanese","rice"],"char":"\ud83c\udf63",fitzpatrick_scale:!1,category:"food_and_drink"},bento:{keywords:["food","japanese","box"],"char":"\ud83c\udf71",fitzpatrick_scale:!1,category:"food_and_drink"},curry:{keywords:["food","spicy","hot","indian"],"char":"\ud83c\udf5b",fitzpatrick_scale:!1,category:"food_and_drink"},rice_ball:{keywords:["food","japanese"],"char":"\ud83c\udf59",fitzpatrick_scale:!1,category:"food_and_drink"},rice:{keywords:["food","china","asian"],"char":"\ud83c\udf5a",fitzpatrick_scale:!1,category:"food_and_drink"},rice_cracker:{keywords:["food","japanese"],"char":"\ud83c\udf58",fitzpatrick_scale:!1,category:"food_and_drink"},oden:{keywords:["food","japanese"],"char":"\ud83c\udf62",fitzpatrick_scale:!1,category:"food_and_drink"},dango:{keywords:["food","dessert","sweet","japanese","barbecue","meat"],"char":"\ud83c\udf61",fitzpatrick_scale:!1,category:"food_and_drink"},shaved_ice:{keywords:["hot","dessert","summer"],"char":"\ud83c\udf67",fitzpatrick_scale:!1,category:"food_and_drink"},ice_cream:{keywords:["food","hot","dessert"],"char":"\ud83c\udf68",fitzpatrick_scale:!1,category:"food_and_drink"},icecream:{keywords:["food","hot","dessert","summer"],"char":"\ud83c\udf66",fitzpatrick_scale:!1,category:"food_and_drink"},pie:{keywords:["food","dessert","pastry"],"char":"\ud83e\udd67",fitzpatrick_scale:!1,category:"food_and_drink"},cake:{keywords:["food","dessert"],"char":"\ud83c\udf70",fitzpatrick_scale:!1,category:"food_and_drink"},cupcake:{keywords:["food","dessert","bakery","sweet"],"char":"\ud83e\uddc1",fitzpatrick_scale:!1,category:"food_and_drink"},moon_cake:{keywords:["food","autumn"],"char":"\ud83e\udd6e",fitzpatrick_scale:!1,category:"food_and_drink"},birthday:{keywords:["food","dessert","cake"],"char":"\ud83c\udf82",fitzpatrick_scale:!1,category:"food_and_drink"},custard:{keywords:["dessert","food"],"char":"\ud83c\udf6e",fitzpatrick_scale:!1,category:"food_and_drink"},candy:{keywords:["snack","dessert","sweet","lolly"],"char":"\ud83c\udf6c",fitzpatrick_scale:!1,category:"food_and_drink"},lollipop:{keywords:["food","snack","candy","sweet"],"char":"\ud83c\udf6d",fitzpatrick_scale:!1,category:"food_and_drink"},chocolate_bar:{keywords:["food","snack","dessert","sweet"],"char":"\ud83c\udf6b",fitzpatrick_scale:!1,category:"food_and_drink"},popcorn:{keywords:["food","movie theater","films","snack"],"char":"\ud83c\udf7f",fitzpatrick_scale:!1,category:"food_and_drink"},dumpling:{keywords:["food","empanada","pierogi","potsticker"],"char":"\ud83e\udd5f",fitzpatrick_scale:!1,category:"food_and_drink"},doughnut:{keywords:["food","dessert","snack","sweet","donut"],"char":"\ud83c\udf69",fitzpatrick_scale:!1,category:"food_and_drink"},cookie:{keywords:["food","snack","oreo","chocolate","sweet","dessert"],"char":"\ud83c\udf6a",fitzpatrick_scale:!1,category:"food_and_drink"},milk_glass:{keywords:["beverage","drink","cow"],"char":"\ud83e\udd5b",fitzpatrick_scale:!1,category:"food_and_drink"},beer:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],"char":"\ud83c\udf7a",fitzpatrick_scale:!1,category:"food_and_drink"},beers:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],"char":"\ud83c\udf7b",fitzpatrick_scale:!1,category:"food_and_drink"},clinking_glasses:{keywords:["beverage","drink","party","alcohol","celebrate","cheers","wine","champagne","toast"],"char":"\ud83e\udd42",fitzpatrick_scale:!1,category:"food_and_drink"},wine_glass:{keywords:["drink","beverage","drunk","alcohol","booze"],"char":"\ud83c\udf77",fitzpatrick_scale:!1,category:"food_and_drink"},tumbler_glass:{keywords:["drink","beverage","drunk","alcohol","liquor","booze","bourbon","scotch","whisky","glass","shot"],"char":"\ud83e\udd43",fitzpatrick_scale:!1,category:"food_and_drink"},cocktail:{keywords:["drink","drunk","alcohol","beverage","booze","mojito"],"char":"\ud83c\udf78",fitzpatrick_scale:!1,category:"food_and_drink"},tropical_drink:{keywords:["beverage","cocktail","summer","beach","alcohol","booze","mojito"],"char":"\ud83c\udf79",fitzpatrick_scale:!1,category:"food_and_drink"},champagne:{keywords:["drink","wine","bottle","celebration"],"char":"\ud83c\udf7e",fitzpatrick_scale:!1,category:"food_and_drink"},sake:{keywords:["wine","drink","drunk","beverage","japanese","alcohol","booze"],"char":"\ud83c\udf76",fitzpatrick_scale:!1,category:"food_and_drink"},tea:{keywords:["drink","bowl","breakfast","green","british"],"char":"\ud83c\udf75",fitzpatrick_scale:!1,category:"food_and_drink"},cup_with_straw:{keywords:["drink","soda"],"char":"\ud83e\udd64",fitzpatrick_scale:!1,category:"food_and_drink"},coffee:{keywords:["beverage","caffeine","latte","espresso"],"char":"\u2615",fitzpatrick_scale:!1,category:"food_and_drink"},baby_bottle:{keywords:["food","container","milk"],"char":"\ud83c\udf7c",fitzpatrick_scale:!1,category:"food_and_drink"},salt:{keywords:["condiment","shaker"],"char":"\ud83e\uddc2",fitzpatrick_scale:!1,category:"food_and_drink"},spoon:{keywords:["cutlery","kitchen","tableware"],"char":"\ud83e\udd44",fitzpatrick_scale:!1,category:"food_and_drink"},fork_and_knife:{keywords:["cutlery","kitchen"],"char":"\ud83c\udf74",fitzpatrick_scale:!1,category:"food_and_drink"},plate_with_cutlery:{keywords:["food","eat","meal","lunch","dinner","restaurant"],"char":"\ud83c\udf7d",fitzpatrick_scale:!1,category:"food_and_drink"},bowl_with_spoon:{keywords:["food","breakfast","cereal","oatmeal","porridge"],"char":"\ud83e\udd63",fitzpatrick_scale:!1,category:"food_and_drink"},takeout_box:{keywords:["food","leftovers"],"char":"\ud83e\udd61",fitzpatrick_scale:!1,category:"food_and_drink"},chopsticks:{keywords:["food"],"char":"\ud83e\udd62",fitzpatrick_scale:!1,category:"food_and_drink"},soccer:{keywords:["sports","football"],"char":"\u26bd",fitzpatrick_scale:!1,category:"activity"},basketball:{keywords:["sports","balls","NBA"],"char":"\ud83c\udfc0",fitzpatrick_scale:!1,category:"activity"},football:{keywords:["sports","balls","NFL"],"char":"\ud83c\udfc8",fitzpatrick_scale:!1,category:"activity"},baseball:{keywords:["sports","balls"],"char":"\u26be",fitzpatrick_scale:!1,category:"activity"},softball:{keywords:["sports","balls"],"char":"\ud83e\udd4e",fitzpatrick_scale:!1,category:"activity"},tennis:{keywords:["sports","balls","green"],"char":"\ud83c\udfbe",fitzpatrick_scale:!1,category:"activity"},volleyball:{keywords:["sports","balls"],"char":"\ud83c\udfd0",fitzpatrick_scale:!1,category:"activity"},rugby_football:{keywords:["sports","team"],"char":"\ud83c\udfc9",fitzpatrick_scale:!1,category:"activity"},flying_disc:{keywords:["sports","frisbee","ultimate"],"char":"\ud83e\udd4f",fitzpatrick_scale:!1,category:"activity"},"8ball":{keywords:["pool","hobby","game","luck","magic"],"char":"\ud83c\udfb1",fitzpatrick_scale:!1,category:"activity"},golf:{keywords:["sports","business","flag","hole","summer"],"char":"\u26f3",fitzpatrick_scale:!1,category:"activity"},golfing_woman:{keywords:["sports","business","woman","female"],"char":"\ud83c\udfcc\ufe0f\u200d\u2640\ufe0f",fitzpatrick_scale:!1,category:"activity"},golfing_man:{keywords:["sports","business"],"char":"\ud83c\udfcc",fitzpatrick_scale:!0,category:"activity"},ping_pong:{keywords:["sports","pingpong"],"char":"\ud83c\udfd3",fitzpatrick_scale:!1,category:"activity"},badminton:{keywords:["sports"],"char":"\ud83c\udff8",fitzpatrick_scale:!1,category:"activity"},goal_net:{keywords:["sports"],"char":"\ud83e\udd45",fitzpatrick_scale:!1,category:"activity"},ice_hockey:{keywords:["sports"],"char":"\ud83c\udfd2",fitzpatrick_scale:!1,category:"activity"},field_hockey:{keywords:["sports"],"char":"\ud83c\udfd1",fitzpatrick_scale:!1,category:"activity"},lacrosse:{keywords:["sports","ball","stick"],"char":"\ud83e\udd4d",fitzpatrick_scale:!1,category:"activity"},cricket:{keywords:["sports"],"char":"\ud83c\udfcf",fitzpatrick_scale:!1,category:"activity"},ski:{keywords:["sports","winter","cold","snow"],"char":"\ud83c\udfbf",fitzpatrick_scale:!1,category:"activity"},skier:{keywords:["sports","winter","snow"],"char":"\u26f7",fitzpatrick_scale:!1,category:"activity"},snowboarder:{keywords:["sports","winter"],"char":"\ud83c\udfc2",fitzpatrick_scale:!0,category:"activity"},person_fencing:{keywords:["sports","fencing","sword"],"char":"\ud83e\udd3a",fitzpatrick_scale:!1,category:"activity"},women_wrestling:{keywords:["sports","wrestlers"],"char":"\ud83e\udd3c\u200d\u2640\ufe0f",fitzpatrick_scale:!1,category:"activity"},men_wrestling:{keywords:["sports","wrestlers"],"char":"\ud83e\udd3c\u200d\u2642\ufe0f",fitzpatrick_scale:!1,category:"activity"},woman_cartwheeling:{keywords:["gymnastics"],"char":"\ud83e\udd38\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_cartwheeling:{keywords:["gymnastics"],"char":"\ud83e\udd38\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},woman_playing_handball:{keywords:["sports"],"char":"\ud83e\udd3e\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_playing_handball:{keywords:["sports"],"char":"\ud83e\udd3e\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},ice_skate:{keywords:["sports"],"char":"\u26f8",fitzpatrick_scale:!1,category:"activity"},curling_stone:{keywords:["sports"],"char":"\ud83e\udd4c",fitzpatrick_scale:!1,category:"activity"},skateboard:{keywords:["board"],"char":"\ud83d\udef9",fitzpatrick_scale:!1,category:"activity"},sled:{keywords:["sleigh","luge","toboggan"],"char":"\ud83d\udef7",fitzpatrick_scale:!1,category:"activity"},bow_and_arrow:{keywords:["sports"],"char":"\ud83c\udff9",fitzpatrick_scale:!1,category:"activity"},fishing_pole_and_fish:{keywords:["food","hobby","summer"],"char":"\ud83c\udfa3",fitzpatrick_scale:!1,category:"activity"},boxing_glove:{keywords:["sports","fighting"],"char":"\ud83e\udd4a",fitzpatrick_scale:!1,category:"activity"},martial_arts_uniform:{keywords:["judo","karate","taekwondo"],"char":"\ud83e\udd4b",fitzpatrick_scale:!1,category:"activity"},rowing_woman:{keywords:["sports","hobby","water","ship","woman","female"],"char":"\ud83d\udea3\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},rowing_man:{keywords:["sports","hobby","water","ship"],"char":"\ud83d\udea3",fitzpatrick_scale:!0,category:"activity"},climbing_woman:{keywords:["sports","hobby","woman","female","rock"],"char":"\ud83e\uddd7\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},climbing_man:{keywords:["sports","hobby","man","male","rock"],"char":"\ud83e\uddd7\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},swimming_woman:{keywords:["sports","exercise","human","athlete","water","summer","woman","female"],"char":"\ud83c\udfca\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},swimming_man:{keywords:["sports","exercise","human","athlete","water","summer"],"char":"\ud83c\udfca",fitzpatrick_scale:!0,category:"activity"},woman_playing_water_polo:{keywords:["sports","pool"],"char":"\ud83e\udd3d\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_playing_water_polo:{keywords:["sports","pool"],"char":"\ud83e\udd3d\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},woman_in_lotus_position:{keywords:["woman","female","meditation","yoga","serenity","zen","mindfulness"],"char":"\ud83e\uddd8\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_in_lotus_position:{keywords:["man","male","meditation","yoga","serenity","zen","mindfulness"],"char":"\ud83e\uddd8\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},surfing_woman:{keywords:["sports","ocean","sea","summer","beach","woman","female"],"char":"\ud83c\udfc4\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},surfing_man:{keywords:["sports","ocean","sea","summer","beach"],"char":"\ud83c\udfc4",fitzpatrick_scale:!0,category:"activity"},bath:{keywords:["clean","shower","bathroom"],"char":"\ud83d\udec0",fitzpatrick_scale:!0,category:"activity"},basketball_woman:{keywords:["sports","human","woman","female"],"char":"\u26f9\ufe0f\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},basketball_man:{keywords:["sports","human"],"char":"\u26f9",fitzpatrick_scale:!0,category:"activity"},weight_lifting_woman:{keywords:["sports","training","exercise","woman","female"],"char":"\ud83c\udfcb\ufe0f\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},weight_lifting_man:{keywords:["sports","training","exercise"],"char":"\ud83c\udfcb",fitzpatrick_scale:!0,category:"activity"},biking_woman:{keywords:["sports","bike","exercise","hipster","woman","female"],"char":"\ud83d\udeb4\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},biking_man:{keywords:["sports","bike","exercise","hipster"],"char":"\ud83d\udeb4",fitzpatrick_scale:!0,category:"activity"},mountain_biking_woman:{keywords:["transportation","sports","human","race","bike","woman","female"],"char":"\ud83d\udeb5\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},mountain_biking_man:{keywords:["transportation","sports","human","race","bike"],"char":"\ud83d\udeb5",fitzpatrick_scale:!0,category:"activity"},horse_racing:{keywords:["animal","betting","competition","gambling","luck"],"char":"\ud83c\udfc7",fitzpatrick_scale:!0,category:"activity"},business_suit_levitating:{keywords:["suit","business","levitate","hover","jump"],"char":"\ud83d\udd74",fitzpatrick_scale:!0,category:"activity"},trophy:{keywords:["win","award","contest","place","ftw","ceremony"],"char":"\ud83c\udfc6",fitzpatrick_scale:!1,category:"activity"},running_shirt_with_sash:{keywords:["play","pageant"],"char":"\ud83c\udfbd",fitzpatrick_scale:!1,category:"activity"},medal_sports:{keywords:["award","winning"],"char":"\ud83c\udfc5",fitzpatrick_scale:!1,category:"activity"},medal_military:{keywords:["award","winning","army"],"char":"\ud83c\udf96",fitzpatrick_scale:!1,category:"activity"},"1st_place_medal":{keywords:["award","winning","first"],"char":"\ud83e\udd47",fitzpatrick_scale:!1,category:"activity"},"2nd_place_medal":{keywords:["award","second"],"char":"\ud83e\udd48",fitzpatrick_scale:!1,category:"activity"},"3rd_place_medal":{keywords:["award","third"],"char":"\ud83e\udd49",fitzpatrick_scale:!1,category:"activity"},reminder_ribbon:{keywords:["sports","cause","support","awareness"],"char":"\ud83c\udf97",fitzpatrick_scale:!1,category:"activity"},rosette:{keywords:["flower","decoration","military"],"char":"\ud83c\udff5",fitzpatrick_scale:!1,category:"activity"},ticket:{keywords:["event","concert","pass"],"char":"\ud83c\udfab",fitzpatrick_scale:!1,category:"activity"},tickets:{keywords:["sports","concert","entrance"],"char":"\ud83c\udf9f",fitzpatrick_scale:!1,category:"activity"},performing_arts:{keywords:["acting","theater","drama"],"char":"\ud83c\udfad",fitzpatrick_scale:!1,category:"activity"},art:{keywords:["design","paint","draw","colors"],"char":"\ud83c\udfa8",fitzpatrick_scale:!1,category:"activity"},circus_tent:{keywords:["festival","carnival","party"],"char":"\ud83c\udfaa",fitzpatrick_scale:!1,category:"activity"},woman_juggling:{keywords:["juggle","balance","skill","multitask"],"char":"\ud83e\udd39\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_juggling:{keywords:["juggle","balance","skill","multitask"],"char":"\ud83e\udd39\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},microphone:{keywords:["sound","music","PA","sing","talkshow"],"char":"\ud83c\udfa4",fitzpatrick_scale:!1,category:"activity"},headphones:{keywords:["music","score","gadgets"],"char":"\ud83c\udfa7",fitzpatrick_scale:!1,category:"activity"},musical_score:{keywords:["treble","clef","compose"],"char":"\ud83c\udfbc",fitzpatrick_scale:!1,category:"activity"},musical_keyboard:{keywords:["piano","instrument","compose"],"char":"\ud83c\udfb9",fitzpatrick_scale:!1,category:"activity"},drum:{keywords:["music","instrument","drumsticks","snare"],"char":"\ud83e\udd41",fitzpatrick_scale:!1,category:"activity"},saxophone:{keywords:["music","instrument","jazz","blues"],"char":"\ud83c\udfb7",fitzpatrick_scale:!1,category:"activity"},trumpet:{keywords:["music","brass"],"char":"\ud83c\udfba",fitzpatrick_scale:!1,category:"activity"},guitar:{keywords:["music","instrument"],"char":"\ud83c\udfb8",fitzpatrick_scale:!1,category:"activity"},violin:{keywords:["music","instrument","orchestra","symphony"],"char":"\ud83c\udfbb",fitzpatrick_scale:!1,category:"activity"},clapper:{keywords:["movie","film","record"],"char":"\ud83c\udfac",fitzpatrick_scale:!1,category:"activity"},video_game:{keywords:["play","console","PS4","controller"],"char":"\ud83c\udfae",fitzpatrick_scale:!1,category:"activity"},space_invader:{keywords:["game","arcade","play"],"char":"\ud83d\udc7e",fitzpatrick_scale:!1,category:"activity"},dart:{keywords:["game","play","bar","target","bullseye"],"char":"\ud83c\udfaf",fitzpatrick_scale:!1,category:"activity"},game_die:{keywords:["dice","random","tabletop","play","luck"],"char":"\ud83c\udfb2",fitzpatrick_scale:!1,category:"activity"},chess_pawn:{keywords:["expendable"],"char":"\u265f",fitzpatrick_scale:!1,category:"activity"},slot_machine:{keywords:["bet","gamble","vegas","fruit machine","luck","casino"],"char":"\ud83c\udfb0",fitzpatrick_scale:!1,category:"activity"},jigsaw:{keywords:["interlocking","puzzle","piece"],"char":"\ud83e\udde9",fitzpatrick_scale:!1,category:"activity"},bowling:{keywords:["sports","fun","play"],"char":"\ud83c\udfb3",fitzpatrick_scale:!1,category:"activity"},red_car:{keywords:["red","transportation","vehicle"],"char":"\ud83d\ude97",fitzpatrick_scale:!1,category:"travel_and_places"},taxi:{keywords:["uber","vehicle","cars","transportation"],"char":"\ud83d\ude95",fitzpatrick_scale:!1,category:"travel_and_places"},blue_car:{keywords:["transportation","vehicle"],"char":"\ud83d\ude99",fitzpatrick_scale:!1,category:"travel_and_places"},bus:{keywords:["car","vehicle","transportation"],"char":"\ud83d\ude8c",fitzpatrick_scale:!1,category:"travel_and_places"},trolleybus:{keywords:["bart","transportation","vehicle"],"char":"\ud83d\ude8e",fitzpatrick_scale:!1,category:"travel_and_places"},racing_car:{keywords:["sports","race","fast","formula","f1"],"char":"\ud83c\udfce",fitzpatrick_scale:!1,category:"travel_and_places"},police_car:{keywords:["vehicle","cars","transportation","law","legal","enforcement"],"char":"\ud83d\ude93",fitzpatrick_scale:!1,category:"travel_and_places"},ambulance:{keywords:["health","911","hospital"],"char":"\ud83d\ude91",fitzpatrick_scale:!1,category:"travel_and_places"},fire_engine:{keywords:["transportation","cars","vehicle"],"char":"\ud83d\ude92",fitzpatrick_scale:!1,category:"travel_and_places"},minibus:{keywords:["vehicle","car","transportation"],"char":"\ud83d\ude90",fitzpatrick_scale:!1,category:"travel_and_places"},truck:{keywords:["cars","transportation"],"char":"\ud83d\ude9a",fitzpatrick_scale:!1,category:"travel_and_places"},articulated_lorry:{keywords:["vehicle","cars","transportation","express"],"char":"\ud83d\ude9b",fitzpatrick_scale:!1,category:"travel_and_places"},tractor:{keywords:["vehicle","car","farming","agriculture"],"char":"\ud83d\ude9c",fitzpatrick_scale:!1,category:"travel_and_places"},kick_scooter:{keywords:["vehicle","kick","razor"],"char":"\ud83d\udef4",fitzpatrick_scale:!1,category:"travel_and_places"},motorcycle:{keywords:["race","sports","fast"],"char":"\ud83c\udfcd",fitzpatrick_scale:!1,category:"travel_and_places"},bike:{keywords:["sports","bicycle","exercise","hipster"],"char":"\ud83d\udeb2",fitzpatrick_scale:!1,category:"travel_and_places"},motor_scooter:{keywords:["vehicle","vespa","sasha"],"char":"\ud83d\udef5",fitzpatrick_scale:!1,category:"travel_and_places"},rotating_light:{keywords:["police","ambulance","911","emergency","alert","error","pinged","law","legal"],"char":"\ud83d\udea8",fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_police_car:{keywords:["vehicle","law","legal","enforcement","911"],"char":"\ud83d\ude94",fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_bus:{keywords:["vehicle","transportation"],"char":"\ud83d\ude8d",fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_automobile:{keywords:["car","vehicle","transportation"],"char":"\ud83d\ude98",fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_taxi:{keywords:["vehicle","cars","uber"],"char":"\ud83d\ude96",fitzpatrick_scale:!1,category:"travel_and_places"},aerial_tramway:{keywords:["transportation","vehicle","ski"],"char":"\ud83d\udea1",fitzpatrick_scale:!1,category:"travel_and_places"},mountain_cableway:{keywords:["transportation","vehicle","ski"],"char":"\ud83d\udea0",fitzpatrick_scale:!1,category:"travel_and_places"},suspension_railway:{keywords:["vehicle","transportation"],"char":"\ud83d\ude9f",fitzpatrick_scale:!1,category:"travel_and_places"},railway_car:{keywords:["transportation","vehicle"],"char":"\ud83d\ude83",fitzpatrick_scale:!1,category:"travel_and_places"},train:{keywords:["transportation","vehicle","carriage","public","travel"],"char":"\ud83d\ude8b",fitzpatrick_scale:!1,category:"travel_and_places"},monorail:{keywords:["transportation","vehicle"],"char":"\ud83d\ude9d",fitzpatrick_scale:!1,category:"travel_and_places"},bullettrain_side:{keywords:["transportation","vehicle"],"char":"\ud83d\ude84",fitzpatrick_scale:!1,category:"travel_and_places"},bullettrain_front:{keywords:["transportation","vehicle","speed","fast","public","travel"],"char":"\ud83d\ude85",fitzpatrick_scale:!1,category:"travel_and_places"},light_rail:{keywords:["transportation","vehicle"],"char":"\ud83d\ude88",fitzpatrick_scale:!1,category:"travel_and_places"},mountain_railway:{keywords:["transportation","vehicle"],"char":"\ud83d\ude9e",fitzpatrick_scale:!1,category:"travel_and_places"},steam_locomotive:{keywords:["transportation","vehicle","train"],"char":"\ud83d\ude82",fitzpatrick_scale:!1,category:"travel_and_places"},train2:{keywords:["transportation","vehicle"],"char":"\ud83d\ude86",fitzpatrick_scale:!1,category:"travel_and_places"},metro:{keywords:["transportation","blue-square","mrt","underground","tube"],"char":"\ud83d\ude87",fitzpatrick_scale:!1,category:"travel_and_places"},tram:{keywords:["transportation","vehicle"],"char":"\ud83d\ude8a",fitzpatrick_scale:!1,category:"travel_and_places"},station:{keywords:["transportation","vehicle","public"],"char":"\ud83d\ude89",fitzpatrick_scale:!1,category:"travel_and_places"},flying_saucer:{keywords:["transportation","vehicle","ufo"],"char":"\ud83d\udef8",fitzpatrick_scale:!1,category:"travel_and_places"},helicopter:{keywords:["transportation","vehicle","fly"],"char":"\ud83d\ude81",fitzpatrick_scale:!1,category:"travel_and_places"},small_airplane:{keywords:["flight","transportation","fly","vehicle"],"char":"\ud83d\udee9",fitzpatrick_scale:!1,category:"travel_and_places"},airplane:{keywords:["vehicle","transportation","flight","fly"],"char":"\u2708\ufe0f",fitzpatrick_scale:!1,category:"travel_and_places"},flight_departure:{keywords:["airport","flight","landing"],"char":"\ud83d\udeeb",fitzpatrick_scale:!1,category:"travel_and_places"},flight_arrival:{keywords:["airport","flight","boarding"],"char":"\ud83d\udeec",fitzpatrick_scale:!1,category:"travel_and_places"},sailboat:{keywords:["ship","summer","transportation","water","sailing"],"char":"\u26f5",fitzpatrick_scale:!1,category:"travel_and_places"},motor_boat:{keywords:["ship"],"char":"\ud83d\udee5",fitzpatrick_scale:!1,category:"travel_and_places"},speedboat:{keywords:["ship","transportation","vehicle","summer"],"char":"\ud83d\udea4",fitzpatrick_scale:!1,category:"travel_and_places"},ferry:{keywords:["boat","ship","yacht"],"char":"\u26f4",fitzpatrick_scale:!1,category:"travel_and_places"},passenger_ship:{keywords:["yacht","cruise","ferry"],"char":"\ud83d\udef3",fitzpatrick_scale:!1,category:"travel_and_places"},rocket:{keywords:["launch","ship","staffmode","NASA","outer space","outer_space","fly"],"char":"\ud83d\ude80",fitzpatrick_scale:!1,category:"travel_and_places"},artificial_satellite:{keywords:["communication","gps","orbit","spaceflight","NASA","ISS"],"char":"\ud83d\udef0",fitzpatrick_scale:!1,category:"travel_and_places"},seat:{keywords:["sit","airplane","transport","bus","flight","fly"],"char":"\ud83d\udcba",fitzpatrick_scale:!1,category:"travel_and_places"},canoe:{keywords:["boat","paddle","water","ship"],"char":"\ud83d\udef6",fitzpatrick_scale:!1,category:"travel_and_places"},anchor:{keywords:["ship","ferry","sea","boat"],"char":"\u2693",fitzpatrick_scale:!1,category:"travel_and_places"},construction:{keywords:["wip","progress","caution","warning"],"char":"\ud83d\udea7",fitzpatrick_scale:!1,category:"travel_and_places"},fuelpump:{keywords:["gas station","petroleum"],"char":"\u26fd",fitzpatrick_scale:!1,category:"travel_and_places"},busstop:{keywords:["transportation","wait"],"char":"\ud83d\ude8f",fitzpatrick_scale:!1,category:"travel_and_places"},vertical_traffic_light:{keywords:["transportation","driving"],"char":"\ud83d\udea6",fitzpatrick_scale:!1,category:"travel_and_places"},traffic_light:{keywords:["transportation","signal"],"char":"\ud83d\udea5",fitzpatrick_scale:!1,category:"travel_and_places"},checkered_flag:{keywords:["contest","finishline","race","gokart"],"char":"\ud83c\udfc1",fitzpatrick_scale:!1,category:"travel_and_places"},ship:{keywords:["transportation","titanic","deploy"],"char":"\ud83d\udea2",fitzpatrick_scale:!1,category:"travel_and_places"},ferris_wheel:{keywords:["photo","carnival","londoneye"],"char":"\ud83c\udfa1",fitzpatrick_scale:!1,category:"travel_and_places"},roller_coaster:{keywords:["carnival","playground","photo","fun"],"char":"\ud83c\udfa2",fitzpatrick_scale:!1,category:"travel_and_places"},carousel_horse:{keywords:["photo","carnival"],"char":"\ud83c\udfa0",fitzpatrick_scale:!1,category:"travel_and_places"},building_construction:{keywords:["wip","working","progress"],"char":"\ud83c\udfd7",fitzpatrick_scale:!1,category:"travel_and_places"},foggy:{keywords:["photo","mountain"],"char":"\ud83c\udf01",fitzpatrick_scale:!1,category:"travel_and_places"},tokyo_tower:{keywords:["photo","japanese"],"char":"\ud83d\uddfc",fitzpatrick_scale:!1,category:"travel_and_places"},factory:{keywords:["building","industry","pollution","smoke"],"char":"\ud83c\udfed",fitzpatrick_scale:!1,category:"travel_and_places"},fountain:{keywords:["photo","summer","water","fresh"],"char":"\u26f2",fitzpatrick_scale:!1,category:"travel_and_places"},rice_scene:{keywords:["photo","japan","asia","tsukimi"],"char":"\ud83c\udf91",fitzpatrick_scale:!1,category:"travel_and_places"},mountain:{keywords:["photo","nature","environment"],"char":"\u26f0",fitzpatrick_scale:!1,category:"travel_and_places"},mountain_snow:{keywords:["photo","nature","environment","winter","cold"],"char":"\ud83c\udfd4",fitzpatrick_scale:!1,category:"travel_and_places"},mount_fuji:{keywords:["photo","mountain","nature","japanese"],"char":"\ud83d\uddfb",fitzpatrick_scale:!1,category:"travel_and_places"},volcano:{keywords:["photo","nature","disaster"],"char":"\ud83c\udf0b",fitzpatrick_scale:!1,category:"travel_and_places"},japan:{keywords:["nation","country","japanese","asia"],"char":"\ud83d\uddfe",fitzpatrick_scale:!1,category:"travel_and_places"},camping:{keywords:["photo","outdoors","tent"],"char":"\ud83c\udfd5",fitzpatrick_scale:!1,category:"travel_and_places"},tent:{keywords:["photo","camping","outdoors"],"char":"\u26fa",fitzpatrick_scale:!1,category:"travel_and_places"},national_park:{keywords:["photo","environment","nature"],"char":"\ud83c\udfde",fitzpatrick_scale:!1,category:"travel_and_places"},motorway:{keywords:["road","cupertino","interstate","highway"],"char":"\ud83d\udee3",fitzpatrick_scale:!1,category:"travel_and_places"},railway_track:{keywords:["train","transportation"],"char":"\ud83d\udee4",fitzpatrick_scale:!1,category:"travel_and_places"},sunrise:{keywords:["morning","view","vacation","photo"],"char":"\ud83c\udf05",fitzpatrick_scale:!1,category:"travel_and_places"},sunrise_over_mountains:{keywords:["view","vacation","photo"],"char":"\ud83c\udf04",fitzpatrick_scale:!1,category:"travel_and_places"},desert:{keywords:["photo","warm","saharah"],"char":"\ud83c\udfdc",fitzpatrick_scale:!1,category:"travel_and_places"},beach_umbrella:{keywords:["weather","summer","sunny","sand","mojito"],"char":"\ud83c\udfd6",fitzpatrick_scale:!1,category:"travel_and_places"},desert_island:{keywords:["photo","tropical","mojito"],"char":"\ud83c\udfdd",fitzpatrick_scale:!1,category:"travel_and_places"},city_sunrise:{keywords:["photo","good morning","dawn"],"char":"\ud83c\udf07",fitzpatrick_scale:!1,category:"travel_and_places"},city_sunset:{keywords:["photo","evening","sky","buildings"],"char":"\ud83c\udf06",fitzpatrick_scale:!1,category:"travel_and_places"},cityscape:{keywords:["photo","night life","urban"],"char":"\ud83c\udfd9",fitzpatrick_scale:!1,category:"travel_and_places"},night_with_stars:{keywords:["evening","city","downtown"],"char":"\ud83c\udf03",fitzpatrick_scale:!1,category:"travel_and_places"},bridge_at_night:{keywords:["photo","sanfrancisco"],"char":"\ud83c\udf09",fitzpatrick_scale:!1,category:"travel_and_places"},milky_way:{keywords:["photo","space","stars"],"char":"\ud83c\udf0c",fitzpatrick_scale:!1,category:"travel_and_places"},stars:{keywords:["night","photo"],"char":"\ud83c\udf20",fitzpatrick_scale:!1,category:"travel_and_places"},sparkler:{keywords:["stars","night","shine"],"char":"\ud83c\udf87",fitzpatrick_scale:!1,category:"travel_and_places"},fireworks:{keywords:["photo","festival","carnival","congratulations"],"char":"\ud83c\udf86",fitzpatrick_scale:!1,category:"travel_and_places"},rainbow:{keywords:["nature","happy","unicorn_face","photo","sky","spring"],"char":"\ud83c\udf08",fitzpatrick_scale:!1,category:"travel_and_places"},houses:{keywords:["buildings","photo"],"char":"\ud83c\udfd8",fitzpatrick_scale:!1,category:"travel_and_places"},european_castle:{keywords:["building","royalty","history"],"char":"\ud83c\udff0",fitzpatrick_scale:!1,category:"travel_and_places"},japanese_castle:{keywords:["photo","building"],"char":"\ud83c\udfef",fitzpatrick_scale:!1,category:"travel_and_places"},stadium:{keywords:["photo","place","sports","concert","venue"],"char":"\ud83c\udfdf",fitzpatrick_scale:!1,category:"travel_and_places"},statue_of_liberty:{keywords:["american","newyork"],"char":"\ud83d\uddfd",fitzpatrick_scale:!1,category:"travel_and_places"},house:{keywords:["building","home"],"char":"\ud83c\udfe0",fitzpatrick_scale:!1,category:"travel_and_places"},house_with_garden:{keywords:["home","plant","nature"],"char":"\ud83c\udfe1",fitzpatrick_scale:!1,category:"travel_and_places"},derelict_house:{keywords:["abandon","evict","broken","building"],"char":"\ud83c\udfda",fitzpatrick_scale:!1,category:"travel_and_places"},office:{keywords:["building","bureau","work"],"char":"\ud83c\udfe2",fitzpatrick_scale:!1,category:"travel_and_places"},department_store:{keywords:["building","shopping","mall"],"char":"\ud83c\udfec",fitzpatrick_scale:!1,category:"travel_and_places"},post_office:{keywords:["building","envelope","communication"],"char":"\ud83c\udfe3",fitzpatrick_scale:!1,category:"travel_and_places"},european_post_office:{keywords:["building","email"],"char":"\ud83c\udfe4",fitzpatrick_scale:!1,category:"travel_and_places"},hospital:{keywords:["building","health","surgery","doctor"],"char":"\ud83c\udfe5",fitzpatrick_scale:!1,category:"travel_and_places"},bank:{keywords:["building","money","sales","cash","business","enterprise"],"char":"\ud83c\udfe6",fitzpatrick_scale:!1,category:"travel_and_places"},hotel:{keywords:["building","accomodation","checkin"],"char":"\ud83c\udfe8",fitzpatrick_scale:!1,category:"travel_and_places"},convenience_store:{keywords:["building","shopping","groceries"],"char":"\ud83c\udfea",fitzpatrick_scale:!1,category:"travel_and_places"},school:{keywords:["building","student","education","learn","teach"],"char":"\ud83c\udfeb",fitzpatrick_scale:!1,category:"travel_and_places"},love_hotel:{keywords:["like","affection","dating"],"char":"\ud83c\udfe9",fitzpatrick_scale:!1,category:"travel_and_places"},wedding:{keywords:["love","like","affection","couple","marriage","bride","groom"],"char":"\ud83d\udc92",fitzpatrick_scale:!1,category:"travel_and_places"},classical_building:{keywords:["art","culture","history"],"char":"\ud83c\udfdb",fitzpatrick_scale:!1,category:"travel_and_places"},church:{keywords:["building","religion","christ"],"char":"\u26ea",fitzpatrick_scale:!1,category:"travel_and_places"},mosque:{keywords:["islam","worship","minaret"],"char":"\ud83d\udd4c",fitzpatrick_scale:!1,category:"travel_and_places"},synagogue:{keywords:["judaism","worship","temple","jewish"],"char":"\ud83d\udd4d",fitzpatrick_scale:!1,category:"travel_and_places"},kaaba:{keywords:["mecca","mosque","islam"],"char":"\ud83d\udd4b",fitzpatrick_scale:!1,category:"travel_and_places"},shinto_shrine:{keywords:["temple","japan","kyoto"],"char":"\u26e9",fitzpatrick_scale:!1,category:"travel_and_places"},watch:{keywords:["time","accessories"],"char":"\u231a",fitzpatrick_scale:!1,category:"objects"},iphone:{keywords:["technology","apple","gadgets","dial"],"char":"\ud83d\udcf1",fitzpatrick_scale:!1,category:"objects"},calling:{keywords:["iphone","incoming"],"char":"\ud83d\udcf2",fitzpatrick_scale:!1,category:"objects"},computer:{keywords:["technology","laptop","screen","display","monitor"],"char":"\ud83d\udcbb",fitzpatrick_scale:!1,category:"objects"},keyboard:{keywords:["technology","computer","type","input","text"],"char":"\u2328",fitzpatrick_scale:!1,category:"objects"},desktop_computer:{keywords:["technology","computing","screen"],"char":"\ud83d\udda5",fitzpatrick_scale:!1,category:"objects"},printer:{keywords:["paper","ink"],"char":"\ud83d\udda8",fitzpatrick_scale:!1,category:"objects"},computer_mouse:{keywords:["click"],"char":"\ud83d\uddb1",fitzpatrick_scale:!1,category:"objects"},trackball:{keywords:["technology","trackpad"],"char":"\ud83d\uddb2",fitzpatrick_scale:!1,category:"objects"},joystick:{keywords:["game","play"],"char":"\ud83d\udd79",fitzpatrick_scale:!1,category:"objects"},clamp:{keywords:["tool"],"char":"\ud83d\udddc",fitzpatrick_scale:!1,category:"objects"},minidisc:{keywords:["technology","record","data","disk","90s"],"char":"\ud83d\udcbd",fitzpatrick_scale:!1,category:"objects"},floppy_disk:{keywords:["oldschool","technology","save","90s","80s"],"char":"\ud83d\udcbe",fitzpatrick_scale:!1,category:"objects"},cd:{keywords:["technology","dvd","disk","disc","90s"],"char":"\ud83d\udcbf",fitzpatrick_scale:!1,category:"objects"},dvd:{keywords:["cd","disk","disc"],"char":"\ud83d\udcc0",fitzpatrick_scale:!1,category:"objects"},vhs:{keywords:["record","video","oldschool","90s","80s"],"char":"\ud83d\udcfc",fitzpatrick_scale:!1,category:"objects"},camera:{keywords:["gadgets","photography"],"char":"\ud83d\udcf7",fitzpatrick_scale:!1,category:"objects"},camera_flash:{keywords:["photography","gadgets"],"char":"\ud83d\udcf8",fitzpatrick_scale:!1,category:"objects"},video_camera:{keywords:["film","record"],"char":"\ud83d\udcf9",fitzpatrick_scale:!1,category:"objects"},movie_camera:{keywords:["film","record"],"char":"\ud83c\udfa5",fitzpatrick_scale:!1,category:"objects"},film_projector:{keywords:["video","tape","record","movie"],"char":"\ud83d\udcfd",fitzpatrick_scale:!1,category:"objects"},film_strip:{keywords:["movie"],"char":"\ud83c\udf9e",fitzpatrick_scale:!1,category:"objects"},telephone_receiver:{keywords:["technology","communication","dial"],"char":"\ud83d\udcde",fitzpatrick_scale:!1,category:"objects"},phone:{keywords:["technology","communication","dial","telephone"],"char":"\u260e\ufe0f",fitzpatrick_scale:!1,category:"objects"},pager:{keywords:["bbcall","oldschool","90s"],"char":"\ud83d\udcdf",fitzpatrick_scale:!1,category:"objects"},fax:{keywords:["communication","technology"],"char":"\ud83d\udce0",fitzpatrick_scale:!1,category:"objects"},tv:{keywords:["technology","program","oldschool","show","television"],"char":"\ud83d\udcfa",fitzpatrick_scale:!1,category:"objects"},radio:{keywords:["communication","music","podcast","program"],"char":"\ud83d\udcfb",fitzpatrick_scale:!1,category:"objects"},studio_microphone:{keywords:["sing","recording","artist","talkshow"],"char":"\ud83c\udf99",fitzpatrick_scale:!1,category:"objects"},level_slider:{keywords:["scale"],"char":"\ud83c\udf9a",fitzpatrick_scale:!1,category:"objects"},control_knobs:{keywords:["dial"],"char":"\ud83c\udf9b",fitzpatrick_scale:!1,category:"objects"},compass:{keywords:["magnetic","navigation","orienteering"],"char":"\ud83e\udded",fitzpatrick_scale:!1,category:"objects"},stopwatch:{keywords:["time","deadline"],"char":"\u23f1",fitzpatrick_scale:!1,category:"objects"},timer_clock:{keywords:["alarm"],"char":"\u23f2",fitzpatrick_scale:!1,category:"objects"},alarm_clock:{keywords:["time","wake"],"char":"\u23f0",fitzpatrick_scale:!1,category:"objects"},mantelpiece_clock:{keywords:["time"],"char":"\ud83d\udd70",fitzpatrick_scale:!1,category:"objects"},hourglass_flowing_sand:{keywords:["oldschool","time","countdown"],"char":"\u23f3",fitzpatrick_scale:!1,category:"objects"},hourglass:{keywords:["time","clock","oldschool","limit","exam","quiz","test"],"char":"\u231b",fitzpatrick_scale:!1,category:"objects"},satellite:{keywords:["communication","future","radio","space"],"char":"\ud83d\udce1",fitzpatrick_scale:!1,category:"objects"},battery:{keywords:["power","energy","sustain"],"char":"\ud83d\udd0b",fitzpatrick_scale:!1,category:"objects"},electric_plug:{keywords:["charger","power"],"char":"\ud83d\udd0c",fitzpatrick_scale:!1,category:"objects"},bulb:{keywords:["light","electricity","idea"],"char":"\ud83d\udca1",fitzpatrick_scale:!1,category:"objects"},flashlight:{keywords:["dark","camping","sight","night"],"char":"\ud83d\udd26",fitzpatrick_scale:!1,category:"objects"},candle:{keywords:["fire","wax"],"char":"\ud83d\udd6f",fitzpatrick_scale:!1,category:"objects"},fire_extinguisher:{keywords:["quench"],"char":"\ud83e\uddef",fitzpatrick_scale:!1,category:"objects"},wastebasket:{keywords:["bin","trash","rubbish","garbage","toss"],"char":"\ud83d\uddd1",fitzpatrick_scale:!1,category:"objects"},oil_drum:{keywords:["barrell"],"char":"\ud83d\udee2",fitzpatrick_scale:!1,category:"objects"},money_with_wings:{keywords:["dollar","bills","payment","sale"],"char":"\ud83d\udcb8",fitzpatrick_scale:!1,category:"objects"},dollar:{keywords:["money","sales","bill","currency"],"char":"\ud83d\udcb5",fitzpatrick_scale:!1,category:"objects"},yen:{keywords:["money","sales","japanese","dollar","currency"],"char":"\ud83d\udcb4",fitzpatrick_scale:!1,category:"objects"},euro:{keywords:["money","sales","dollar","currency"],"char":"\ud83d\udcb6",fitzpatrick_scale:!1,category:"objects"},pound:{keywords:["british","sterling","money","sales","bills","uk","england","currency"],"char":"\ud83d\udcb7",fitzpatrick_scale:!1,category:"objects"},moneybag:{keywords:["dollar","payment","coins","sale"],"char":"\ud83d\udcb0",fitzpatrick_scale:!1,category:"objects"},credit_card:{keywords:["money","sales","dollar","bill","payment","shopping"],"char":"\ud83d\udcb3",fitzpatrick_scale:!1,category:"objects"},gem:{keywords:["blue","ruby","diamond","jewelry"],"char":"\ud83d\udc8e",fitzpatrick_scale:!1,category:"objects"},balance_scale:{keywords:["law","fairness","weight"],"char":"\u2696",fitzpatrick_scale:!1,category:"objects"},toolbox:{keywords:["tools","diy","fix","maintainer","mechanic"],"char":"\ud83e\uddf0",fitzpatrick_scale:!1,category:"objects"},wrench:{keywords:["tools","diy","ikea","fix","maintainer"],"char":"\ud83d\udd27",fitzpatrick_scale:!1,category:"objects"},hammer:{keywords:["tools","build","create"],"char":"\ud83d\udd28",fitzpatrick_scale:!1,category:"objects"},hammer_and_pick:{keywords:["tools","build","create"],"char":"\u2692",fitzpatrick_scale:!1,category:"objects"},hammer_and_wrench:{keywords:["tools","build","create"],"char":"\ud83d\udee0",fitzpatrick_scale:!1,category:"objects"},pick:{keywords:["tools","dig"],"char":"\u26cf",fitzpatrick_scale:!1,category:"objects"},nut_and_bolt:{keywords:["handy","tools","fix"],"char":"\ud83d\udd29",fitzpatrick_scale:!1,category:"objects"},gear:{keywords:["cog"],"char":"\u2699",fitzpatrick_scale:!1,category:"objects"},brick:{keywords:["bricks"],"char":"\ud83e\uddf1",fitzpatrick_scale:!1,category:"objects"},chains:{keywords:["lock","arrest"],"char":"\u26d3",fitzpatrick_scale:!1,category:"objects"},magnet:{keywords:["attraction","magnetic"],"char":"\ud83e\uddf2",fitzpatrick_scale:!1,category:"objects"},gun:{keywords:["violence","weapon","pistol","revolver"],"char":"\ud83d\udd2b",fitzpatrick_scale:!1,category:"objects"},bomb:{keywords:["boom","explode","explosion","terrorism"],"char":"\ud83d\udca3",fitzpatrick_scale:!1,category:"objects"},firecracker:{keywords:["dynamite","boom","explode","explosion","explosive"],"char":"\ud83e\udde8",fitzpatrick_scale:!1,category:"objects"},hocho:{keywords:["knife","blade","cutlery","kitchen","weapon"],"char":"\ud83d\udd2a",fitzpatrick_scale:!1,category:"objects"},dagger:{keywords:["weapon"],"char":"\ud83d\udde1",fitzpatrick_scale:!1,category:"objects"},crossed_swords:{keywords:["weapon"],"char":"\u2694",fitzpatrick_scale:!1,category:"objects"},shield:{keywords:["protection","security"],"char":"\ud83d\udee1",fitzpatrick_scale:!1,category:"objects"},smoking:{keywords:["kills","tobacco","cigarette","joint","smoke"],"char":"\ud83d\udeac",fitzpatrick_scale:!1,category:"objects"},skull_and_crossbones:{keywords:["poison","danger","deadly","scary","death","pirate","evil"],"char":"\u2620",fitzpatrick_scale:!1,category:"objects"},coffin:{keywords:["vampire","dead","die","death","rip","graveyard","cemetery","casket","funeral","box"],"char":"\u26b0",fitzpatrick_scale:!1,category:"objects"},funeral_urn:{keywords:["dead","die","death","rip","ashes"],"char":"\u26b1",fitzpatrick_scale:!1,category:"objects"},amphora:{keywords:["vase","jar"],"char":"\ud83c\udffa",fitzpatrick_scale:!1,category:"objects"},crystal_ball:{keywords:["disco","party","magic","circus","fortune_teller"],"char":"\ud83d\udd2e",fitzpatrick_scale:!1,category:"objects"},prayer_beads:{keywords:["dhikr","religious"],"char":"\ud83d\udcff",fitzpatrick_scale:!1,category:"objects"},nazar_amulet:{keywords:["bead","charm"],"char":"\ud83e\uddff",fitzpatrick_scale:!1,category:"objects"},barber:{keywords:["hair","salon","style"],"char":"\ud83d\udc88",fitzpatrick_scale:!1,category:"objects"},alembic:{keywords:["distilling","science","experiment","chemistry"],"char":"\u2697",fitzpatrick_scale:!1,category:"objects"},telescope:{keywords:["stars","space","zoom","science","astronomy"],"char":"\ud83d\udd2d",fitzpatrick_scale:!1,category:"objects"},microscope:{keywords:["laboratory","experiment","zoomin","science","study"],"char":"\ud83d\udd2c",fitzpatrick_scale:!1,category:"objects"},hole:{keywords:["embarrassing"],"char":"\ud83d\udd73",fitzpatrick_scale:!1,category:"objects"},pill:{keywords:["health","medicine","doctor","pharmacy","drug"],"char":"\ud83d\udc8a",fitzpatrick_scale:!1,category:"objects"},syringe:{keywords:["health","hospital","drugs","blood","medicine","needle","doctor","nurse"],"char":"\ud83d\udc89",fitzpatrick_scale:!1,category:"objects"},dna:{keywords:["biologist","genetics","life"],"char":"\ud83e\uddec",fitzpatrick_scale:!1,category:"objects"},microbe:{keywords:["amoeba","bacteria","germs"],"char":"\ud83e\udda0",fitzpatrick_scale:!1,category:"objects"},petri_dish:{keywords:["bacteria","biology","culture","lab"],"char":"\ud83e\uddeb",fitzpatrick_scale:!1,category:"objects"},test_tube:{keywords:["chemistry","experiment","lab","science"],"char":"\ud83e\uddea",fitzpatrick_scale:!1,category:"objects"},thermometer:{keywords:["weather","temperature","hot","cold"],"char":"\ud83c\udf21",fitzpatrick_scale:!1,category:"objects"},broom:{keywords:["cleaning","sweeping","witch"],"char":"\ud83e\uddf9",fitzpatrick_scale:!1,category:"objects"},basket:{keywords:["laundry"],"char":"\ud83e\uddfa",fitzpatrick_scale:!1,category:"objects"},toilet_paper:{keywords:["roll"],"char":"\ud83e\uddfb",fitzpatrick_scale:!1,category:"objects"},label:{keywords:["sale","tag"],"char":"\ud83c\udff7",fitzpatrick_scale:!1,category:"objects"},bookmark:{keywords:["favorite","label","save"],"char":"\ud83d\udd16",fitzpatrick_scale:!1,category:"objects"},toilet:{keywords:["restroom","wc","washroom","bathroom","potty"],"char":"\ud83d\udebd",fitzpatrick_scale:!1,category:"objects"},shower:{keywords:["clean","water","bathroom"],"char":"\ud83d\udebf",fitzpatrick_scale:!1,category:"objects"},bathtub:{keywords:["clean","shower","bathroom"],"char":"\ud83d\udec1",fitzpatrick_scale:!1,category:"objects"},soap:{keywords:["bar","bathing","cleaning","lather"],"char":"\ud83e\uddfc",fitzpatrick_scale:!1,category:"objects"},sponge:{keywords:["absorbing","cleaning","porous"],"char":"\ud83e\uddfd",fitzpatrick_scale:!1,category:"objects"},lotion_bottle:{keywords:["moisturizer","sunscreen"],"char":"\ud83e\uddf4",fitzpatrick_scale:!1,category:"objects"},key:{keywords:["lock","door","password"],"char":"\ud83d\udd11",fitzpatrick_scale:!1,category:"objects"},old_key:{keywords:["lock","door","password"],"char":"\ud83d\udddd",fitzpatrick_scale:!1,category:"objects"},couch_and_lamp:{keywords:["read","chill"],"char":"\ud83d\udecb",fitzpatrick_scale:!1,category:"objects"},sleeping_bed:{keywords:["bed","rest"],"char":"\ud83d\udecc",fitzpatrick_scale:!0,category:"objects"},bed:{keywords:["sleep","rest"],"char":"\ud83d\udecf",fitzpatrick_scale:!1,category:"objects"},door:{keywords:["house","entry","exit"],"char":"\ud83d\udeaa",fitzpatrick_scale:!1,category:"objects"},bellhop_bell:{keywords:["service"],"char":"\ud83d\udece",fitzpatrick_scale:!1,category:"objects"},teddy_bear:{keywords:["plush","stuffed"],"char":"\ud83e\uddf8",fitzpatrick_scale:!1,category:"objects"},framed_picture:{keywords:["photography"],"char":"\ud83d\uddbc",fitzpatrick_scale:!1,category:"objects"},world_map:{keywords:["location","direction"],"char":"\ud83d\uddfa",fitzpatrick_scale:!1,category:"objects"},parasol_on_ground:{keywords:["weather","summer"],"char":"\u26f1",fitzpatrick_scale:!1,category:"objects"},moyai:{keywords:["rock","easter island","moai"],"char":"\ud83d\uddff",fitzpatrick_scale:!1,category:"objects"},shopping:{keywords:["mall","buy","purchase"],"char":"\ud83d\udecd",fitzpatrick_scale:!1,category:"objects"},shopping_cart:{keywords:["trolley"],"char":"\ud83d\uded2",fitzpatrick_scale:!1,category:"objects"},balloon:{keywords:["party","celebration","birthday","circus"],"char":"\ud83c\udf88",fitzpatrick_scale:!1,category:"objects"},flags:{keywords:["fish","japanese","koinobori","carp","banner"],"char":"\ud83c\udf8f",fitzpatrick_scale:!1,category:"objects"},ribbon:{keywords:["decoration","pink","girl","bowtie"],"char":"\ud83c\udf80",fitzpatrick_scale:!1,category:"objects"},gift:{keywords:["present","birthday","christmas","xmas"],"char":"\ud83c\udf81",fitzpatrick_scale:!1,category:"objects"},confetti_ball:{keywords:["festival","party","birthday","circus"],"char":"\ud83c\udf8a",fitzpatrick_scale:!1,category:"objects"},tada:{keywords:["party","congratulations","birthday","magic","circus","celebration"],"char":"\ud83c\udf89",fitzpatrick_scale:!1,category:"objects"},dolls:{keywords:["japanese","toy","kimono"],"char":"\ud83c\udf8e",fitzpatrick_scale:!1,category:"objects"},wind_chime:{keywords:["nature","ding","spring","bell"],"char":"\ud83c\udf90",fitzpatrick_scale:!1,category:"objects"},crossed_flags:{keywords:["japanese","nation","country","border"],"char":"\ud83c\udf8c",fitzpatrick_scale:!1,category:"objects"},izakaya_lantern:{keywords:["light","paper","halloween","spooky"],"char":"\ud83c\udfee",fitzpatrick_scale:!1,category:"objects"},red_envelope:{keywords:["gift"],"char":"\ud83e\udde7",fitzpatrick_scale:!1,category:"objects"},email:{keywords:["letter","postal","inbox","communication"],"char":"\u2709\ufe0f",fitzpatrick_scale:!1,category:"objects"},envelope_with_arrow:{keywords:["email","communication"],"char":"\ud83d\udce9",fitzpatrick_scale:!1,category:"objects"},incoming_envelope:{keywords:["email","inbox"],"char":"\ud83d\udce8",fitzpatrick_scale:!1,category:"objects"},"e-mail":{keywords:["communication","inbox"],"char":"\ud83d\udce7",fitzpatrick_scale:!1,category:"objects"},love_letter:{keywords:["email","like","affection","envelope","valentines"],"char":"\ud83d\udc8c",fitzpatrick_scale:!1,category:"objects"},postbox:{keywords:["email","letter","envelope"],"char":"\ud83d\udcee",fitzpatrick_scale:!1,category:"objects"},mailbox_closed:{keywords:["email","communication","inbox"],"char":"\ud83d\udcea",fitzpatrick_scale:!1,category:"objects"},mailbox:{keywords:["email","inbox","communication"],"char":"\ud83d\udceb",fitzpatrick_scale:!1,category:"objects"},mailbox_with_mail:{keywords:["email","inbox","communication"],"char":"\ud83d\udcec",fitzpatrick_scale:!1,category:"objects"},mailbox_with_no_mail:{keywords:["email","inbox"],"char":"\ud83d\udced",fitzpatrick_scale:!1,category:"objects"},"package":{keywords:["mail","gift","cardboard","box","moving"],"char":"\ud83d\udce6",fitzpatrick_scale:!1,category:"objects"},postal_horn:{keywords:["instrument","music"],"char":"\ud83d\udcef",fitzpatrick_scale:!1,category:"objects"},inbox_tray:{keywords:["email","documents"],"char":"\ud83d\udce5",fitzpatrick_scale:!1,category:"objects"},outbox_tray:{keywords:["inbox","email"],"char":"\ud83d\udce4",fitzpatrick_scale:!1,category:"objects"},scroll:{keywords:["documents","ancient","history","paper"],"char":"\ud83d\udcdc",fitzpatrick_scale:!1,category:"objects"},page_with_curl:{keywords:["documents","office","paper"],"char":"\ud83d\udcc3",fitzpatrick_scale:!1,category:"objects"},bookmark_tabs:{keywords:["favorite","save","order","tidy"],"char":"\ud83d\udcd1",fitzpatrick_scale:!1,category:"objects"},receipt:{keywords:["accounting","expenses"],"char":"\ud83e\uddfe",fitzpatrick_scale:!1,category:"objects"},bar_chart:{keywords:["graph","presentation","stats"],"char":"\ud83d\udcca",fitzpatrick_scale:!1,category:"objects"},chart_with_upwards_trend:{keywords:["graph","presentation","stats","recovery","business","economics","money","sales","good","success"],"char":"\ud83d\udcc8",fitzpatrick_scale:!1,category:"objects"},chart_with_downwards_trend:{keywords:["graph","presentation","stats","recession","business","economics","money","sales","bad","failure"],"char":"\ud83d\udcc9",fitzpatrick_scale:!1,category:"objects"},page_facing_up:{keywords:["documents","office","paper","information"],"char":"\ud83d\udcc4",fitzpatrick_scale:!1,category:"objects"},date:{keywords:["calendar","schedule"],"char":"\ud83d\udcc5",fitzpatrick_scale:!1,category:"objects"},calendar:{keywords:["schedule","date","planning"],"char":"\ud83d\udcc6",fitzpatrick_scale:!1,category:"objects"},spiral_calendar:{keywords:["date","schedule","planning"],"char":"\ud83d\uddd3",fitzpatrick_scale:!1,category:"objects"},card_index:{keywords:["business","stationery"],"char":"\ud83d\udcc7",fitzpatrick_scale:!1,category:"objects"},card_file_box:{keywords:["business","stationery"],"char":"\ud83d\uddc3",fitzpatrick_scale:!1,category:"objects"},ballot_box:{keywords:["election","vote"],"char":"\ud83d\uddf3",fitzpatrick_scale:!1,category:"objects"},file_cabinet:{keywords:["filing","organizing"],"char":"\ud83d\uddc4",fitzpatrick_scale:!1,category:"objects"},clipboard:{keywords:["stationery","documents"],"char":"\ud83d\udccb",fitzpatrick_scale:!1,category:"objects"},spiral_notepad:{keywords:["memo","stationery"],"char":"\ud83d\uddd2",fitzpatrick_scale:!1,category:"objects"},file_folder:{keywords:["documents","business","office"],"char":"\ud83d\udcc1",fitzpatrick_scale:!1,category:"objects"},open_file_folder:{keywords:["documents","load"],"char":"\ud83d\udcc2",fitzpatrick_scale:!1,category:"objects"},card_index_dividers:{keywords:["organizing","business","stationery"],"char":"\ud83d\uddc2",fitzpatrick_scale:!1,category:"objects"},newspaper_roll:{keywords:["press","headline"],"char":"\ud83d\uddde",fitzpatrick_scale:!1,category:"objects"},newspaper:{keywords:["press","headline"],"char":"\ud83d\udcf0",fitzpatrick_scale:!1,category:"objects"},notebook:{keywords:["stationery","record","notes","paper","study"],"char":"\ud83d\udcd3",fitzpatrick_scale:!1,category:"objects"},closed_book:{keywords:["read","library","knowledge","textbook","learn"],"char":"\ud83d\udcd5",fitzpatrick_scale:!1,category:"objects"},green_book:{keywords:["read","library","knowledge","study"],"char":"\ud83d\udcd7",fitzpatrick_scale:!1,category:"objects"},blue_book:{keywords:["read","library","knowledge","learn","study"],"char":"\ud83d\udcd8",fitzpatrick_scale:!1,category:"objects"},orange_book:{keywords:["read","library","knowledge","textbook","study"],"char":"\ud83d\udcd9",fitzpatrick_scale:!1,category:"objects"},notebook_with_decorative_cover:{keywords:["classroom","notes","record","paper","study"],"char":"\ud83d\udcd4",fitzpatrick_scale:!1,category:"objects"},ledger:{keywords:["notes","paper"],"char":"\ud83d\udcd2",fitzpatrick_scale:!1,category:"objects"},books:{keywords:["literature","library","study"],"char":"\ud83d\udcda",fitzpatrick_scale:!1,category:"objects"},open_book:{keywords:["book","read","library","knowledge","literature","learn","study"],"char":"\ud83d\udcd6",fitzpatrick_scale:!1,category:"objects"},safety_pin:{keywords:["diaper"],"char":"\ud83e\uddf7",fitzpatrick_scale:!1,category:"objects"},link:{keywords:["rings","url"],"char":"\ud83d\udd17",fitzpatrick_scale:!1,category:"objects"},paperclip:{keywords:["documents","stationery"],"char":"\ud83d\udcce",fitzpatrick_scale:!1,category:"objects"},paperclips:{keywords:["documents","stationery"],"char":"\ud83d\udd87",fitzpatrick_scale:!1,category:"objects"},scissors:{keywords:["stationery","cut"],"char":"\u2702\ufe0f",fitzpatrick_scale:!1,category:"objects"},triangular_ruler:{keywords:["stationery","math","architect","sketch"],"char":"\ud83d\udcd0",fitzpatrick_scale:!1,category:"objects"},straight_ruler:{keywords:["stationery","calculate","length","math","school","drawing","architect","sketch"],"char":"\ud83d\udccf",fitzpatrick_scale:!1,category:"objects"},abacus:{keywords:["calculation"],"char":"\ud83e\uddee",fitzpatrick_scale:!1,category:"objects"},pushpin:{keywords:["stationery","mark","here"],"char":"\ud83d\udccc",fitzpatrick_scale:!1,category:"objects"},round_pushpin:{keywords:["stationery","location","map","here"],"char":"\ud83d\udccd",fitzpatrick_scale:!1,category:"objects"},triangular_flag_on_post:{keywords:["mark","milestone","place"],"char":"\ud83d\udea9",fitzpatrick_scale:!1,category:"objects"},white_flag:{keywords:["losing","loser","lost","surrender","give up","fail"],"char":"\ud83c\udff3",fitzpatrick_scale:!1,category:"objects"},black_flag:{keywords:["pirate"],"char":"\ud83c\udff4",fitzpatrick_scale:!1,category:"objects"},rainbow_flag:{keywords:["flag","rainbow","pride","gay","lgbt","glbt","queer","homosexual","lesbian","bisexual","transgender"],"char":"\ud83c\udff3\ufe0f\u200d\ud83c\udf08",fitzpatrick_scale:!1,category:"objects"},closed_lock_with_key:{keywords:["security","privacy"],"char":"\ud83d\udd10",fitzpatrick_scale:!1,category:"objects"},lock:{keywords:["security","password","padlock"],"char":"\ud83d\udd12",fitzpatrick_scale:!1,category:"objects"},unlock:{keywords:["privacy","security"],"char":"\ud83d\udd13",fitzpatrick_scale:!1,category:"objects"},lock_with_ink_pen:{keywords:["security","secret"],"char":"\ud83d\udd0f",fitzpatrick_scale:!1,category:"objects"},pen:{keywords:["stationery","writing","write"],"char":"\ud83d\udd8a",fitzpatrick_scale:!1,category:"objects"},fountain_pen:{keywords:["stationery","writing","write"],"char":"\ud83d\udd8b",fitzpatrick_scale:!1,category:"objects"},black_nib:{keywords:["pen","stationery","writing","write"],"char":"\u2712\ufe0f",fitzpatrick_scale:!1,category:"objects"},memo:{keywords:["write","documents","stationery","pencil","paper","writing","legal","exam","quiz","test","study","compose"],"char":"\ud83d\udcdd",fitzpatrick_scale:!1,category:"objects"},pencil2:{keywords:["stationery","write","paper","writing","school","study"],"char":"\u270f\ufe0f",fitzpatrick_scale:!1,category:"objects"},crayon:{keywords:["drawing","creativity"],"char":"\ud83d\udd8d",fitzpatrick_scale:!1,category:"objects"},paintbrush:{keywords:["drawing","creativity","art"],"char":"\ud83d\udd8c",fitzpatrick_scale:!1,category:"objects"},mag:{keywords:["search","zoom","find","detective"],"char":"\ud83d\udd0d",fitzpatrick_scale:!1,category:"objects"},mag_right:{keywords:["search","zoom","find","detective"],"char":"\ud83d\udd0e",fitzpatrick_scale:!1,category:"objects"},heart:{keywords:["love","like","valentines"],"char":"\u2764\ufe0f",fitzpatrick_scale:!1,category:"symbols"},orange_heart:{keywords:["love","like","affection","valentines"],"char":"\ud83e\udde1",fitzpatrick_scale:!1,category:"symbols"},yellow_heart:{keywords:["love","like","affection","valentines"],"char":"\ud83d\udc9b",fitzpatrick_scale:!1,category:"symbols"},green_heart:{keywords:["love","like","affection","valentines"],"char":"\ud83d\udc9a",fitzpatrick_scale:!1,category:"symbols"},blue_heart:{keywords:["love","like","affection","valentines"],"char":"\ud83d\udc99",fitzpatrick_scale:!1,category:"symbols"},purple_heart:{keywords:["love","like","affection","valentines"],"char":"\ud83d\udc9c",fitzpatrick_scale:!1,category:"symbols"},black_heart:{keywords:["evil"],"char":"\ud83d\udda4",fitzpatrick_scale:!1,category:"symbols"},broken_heart:{keywords:["sad","sorry","break","heart","heartbreak"],"char":"\ud83d\udc94",fitzpatrick_scale:!1,category:"symbols"},heavy_heart_exclamation:{keywords:["decoration","love"],"char":"\u2763",fitzpatrick_scale:!1,category:"symbols"},two_hearts:{keywords:["love","like","affection","valentines","heart"],"char":"\ud83d\udc95",fitzpatrick_scale:!1,category:"symbols"},revolving_hearts:{keywords:["love","like","affection","valentines"],"char":"\ud83d\udc9e",fitzpatrick_scale:!1,category:"symbols"},heartbeat:{keywords:["love","like","affection","valentines","pink","heart"],"char":"\ud83d\udc93",fitzpatrick_scale:!1,category:"symbols"},heartpulse:{keywords:["like","love","affection","valentines","pink"],"char":"\ud83d\udc97",fitzpatrick_scale:!1,category:"symbols"},sparkling_heart:{keywords:["love","like","affection","valentines"],"char":"\ud83d\udc96",fitzpatrick_scale:!1,category:"symbols"},cupid:{keywords:["love","like","heart","affection","valentines"],"char":"\ud83d\udc98",fitzpatrick_scale:!1,category:"symbols"},gift_heart:{keywords:["love","valentines"],"char":"\ud83d\udc9d",fitzpatrick_scale:!1,category:"symbols"},heart_decoration:{keywords:["purple-square","love","like"],"char":"\ud83d\udc9f",fitzpatrick_scale:!1,category:"symbols"},peace_symbol:{keywords:["hippie"],"char":"\u262e",fitzpatrick_scale:!1,category:"symbols"},latin_cross:{keywords:["christianity"],"char":"\u271d",fitzpatrick_scale:!1,category:"symbols"},star_and_crescent:{keywords:["islam"],"char":"\u262a",fitzpatrick_scale:!1,category:"symbols"},om:{keywords:["hinduism","buddhism","sikhism","jainism"],"char":"\ud83d\udd49",fitzpatrick_scale:!1,category:"symbols"},wheel_of_dharma:{keywords:["hinduism","buddhism","sikhism","jainism"],"char":"\u2638",fitzpatrick_scale:!1,category:"symbols"},star_of_david:{keywords:["judaism"],"char":"\u2721",fitzpatrick_scale:!1,category:"symbols"},six_pointed_star:{keywords:["purple-square","religion","jewish","hexagram"],"char":"\ud83d\udd2f",fitzpatrick_scale:!1,category:"symbols"},menorah:{keywords:["hanukkah","candles","jewish"],"char":"\ud83d\udd4e",fitzpatrick_scale:!1,category:"symbols"},yin_yang:{keywords:["balance"],"char":"\u262f",fitzpatrick_scale:!1,category:"symbols"},orthodox_cross:{keywords:["suppedaneum","religion"],"char":"\u2626",fitzpatrick_scale:!1,category:"symbols"},place_of_worship:{keywords:["religion","church","temple","prayer"],"char":"\ud83d\uded0",fitzpatrick_scale:!1,category:"symbols"},ophiuchus:{keywords:["sign","purple-square","constellation","astrology"],"char":"\u26ce",fitzpatrick_scale:!1,category:"symbols"},aries:{keywords:["sign","purple-square","zodiac","astrology"],"char":"\u2648",fitzpatrick_scale:!1,category:"symbols"},taurus:{keywords:["purple-square","sign","zodiac","astrology"],"char":"\u2649",fitzpatrick_scale:!1,category:"symbols"},gemini:{keywords:["sign","zodiac","purple-square","astrology"],"char":"\u264a",fitzpatrick_scale:!1,category:"symbols"},cancer:{keywords:["sign","zodiac","purple-square","astrology"],"char":"\u264b",fitzpatrick_scale:!1,category:"symbols"},leo:{keywords:["sign","purple-square","zodiac","astrology"],"char":"\u264c",fitzpatrick_scale:!1,category:"symbols"},virgo:{keywords:["sign","zodiac","purple-square","astrology"],"char":"\u264d",fitzpatrick_scale:!1,category:"symbols"},libra:{keywords:["sign","purple-square","zodiac","astrology"],"char":"\u264e",fitzpatrick_scale:!1,category:"symbols"},scorpius:{keywords:["sign","zodiac","purple-square","astrology","scorpio"],"char":"\u264f",fitzpatrick_scale:!1,category:"symbols"},sagittarius:{keywords:["sign","zodiac","purple-square","astrology"],"char":"\u2650",fitzpatrick_scale:!1,category:"symbols"},capricorn:{keywords:["sign","zodiac","purple-square","astrology"],"char":"\u2651",fitzpatrick_scale:!1,category:"symbols"},aquarius:{keywords:["sign","purple-square","zodiac","astrology"],"char":"\u2652",fitzpatrick_scale:!1,category:"symbols"},pisces:{keywords:["purple-square","sign","zodiac","astrology"],"char":"\u2653",fitzpatrick_scale:!1,category:"symbols"},id:{keywords:["purple-square","words"],"char":"\ud83c\udd94",fitzpatrick_scale:!1,category:"symbols"},atom_symbol:{keywords:["science","physics","chemistry"],"char":"\u269b",fitzpatrick_scale:!1,category:"symbols"},u7a7a:{keywords:["kanji","japanese","chinese","empty","sky","blue-square"],"char":"\ud83c\ude33",fitzpatrick_scale:!1,category:"symbols"},u5272:{keywords:["cut","divide","chinese","kanji","pink-square"],"char":"\ud83c\ude39",fitzpatrick_scale:!1,category:"symbols"},radioactive:{keywords:["nuclear","danger"],"char":"\u2622",fitzpatrick_scale:!1,category:"symbols"},biohazard:{keywords:["danger"],"char":"\u2623",fitzpatrick_scale:!1,category:"symbols"},mobile_phone_off:{keywords:["mute","orange-square","silence","quiet"],"char":"\ud83d\udcf4",fitzpatrick_scale:!1,category:"symbols"},vibration_mode:{keywords:["orange-square","phone"],"char":"\ud83d\udcf3",fitzpatrick_scale:!1,category:"symbols"},u6709:{keywords:["orange-square","chinese","have","kanji"],"char":"\ud83c\ude36",fitzpatrick_scale:!1,category:"symbols"},u7121:{keywords:["nothing","chinese","kanji","japanese","orange-square"],"char":"\ud83c\ude1a",fitzpatrick_scale:!1,category:"symbols"},u7533:{keywords:["chinese","japanese","kanji","orange-square"],"char":"\ud83c\ude38",fitzpatrick_scale:!1,category:"symbols"},u55b6:{keywords:["japanese","opening hours","orange-square"],"char":"\ud83c\ude3a",fitzpatrick_scale:!1,category:"symbols"},u6708:{keywords:["chinese","month","moon","japanese","orange-square","kanji"],"char":"\ud83c\ude37\ufe0f",fitzpatrick_scale:!1,category:"symbols"},eight_pointed_black_star:{keywords:["orange-square","shape","polygon"],"char":"\u2734\ufe0f",fitzpatrick_scale:!1,category:"symbols"},vs:{keywords:["words","orange-square"],"char":"\ud83c\udd9a",fitzpatrick_scale:!1,category:"symbols"},accept:{keywords:["ok","good","chinese","kanji","agree","yes","orange-circle"],"char":"\ud83c\ude51",fitzpatrick_scale:!1,category:"symbols"},white_flower:{keywords:["japanese","spring"],"char":"\ud83d\udcae",fitzpatrick_scale:!1,category:"symbols"},ideograph_advantage:{keywords:["chinese","kanji","obtain","get","circle"],"char":"\ud83c\ude50",fitzpatrick_scale:!1,category:"symbols"},secret:{keywords:["privacy","chinese","sshh","kanji","red-circle"],"char":"\u3299\ufe0f",fitzpatrick_scale:!1,category:"symbols"},congratulations:{keywords:["chinese","kanji","japanese","red-circle"],"char":"\u3297\ufe0f",fitzpatrick_scale:!1,category:"symbols"},u5408:{keywords:["japanese","chinese","join","kanji","red-square"],"char":"\ud83c\ude34",fitzpatrick_scale:!1,category:"symbols"},u6e80:{keywords:["full","chinese","japanese","red-square","kanji"],"char":"\ud83c\ude35",fitzpatrick_scale:!1,category:"symbols"},u7981:{keywords:["kanji","japanese","chinese","forbidden","limit","restricted","red-square"],"char":"\ud83c\ude32",fitzpatrick_scale:!1,category:"symbols"},a:{keywords:["red-square","alphabet","letter"],"char":"\ud83c\udd70\ufe0f",fitzpatrick_scale:!1,category:"symbols"},b:{keywords:["red-square","alphabet","letter"],"char":"\ud83c\udd71\ufe0f",fitzpatrick_scale:!1,category:"symbols"},ab:{keywords:["red-square","alphabet"],"char":"\ud83c\udd8e",fitzpatrick_scale:!1,category:"symbols"},cl:{keywords:["alphabet","words","red-square"],"char":"\ud83c\udd91",fitzpatrick_scale:!1,category:"symbols"},o2:{keywords:["alphabet","red-square","letter"],"char":"\ud83c\udd7e\ufe0f",fitzpatrick_scale:!1,category:"symbols"},sos:{keywords:["help","red-square","words","emergency","911"],"char":"\ud83c\udd98",fitzpatrick_scale:!1,category:"symbols"},no_entry:{keywords:["limit","security","privacy","bad","denied","stop","circle"],"char":"\u26d4",fitzpatrick_scale:!1,category:"symbols"},name_badge:{keywords:["fire","forbid"],"char":"\ud83d\udcdb",fitzpatrick_scale:!1,category:"symbols"},no_entry_sign:{keywords:["forbid","stop","limit","denied","disallow","circle"],"char":"\ud83d\udeab",fitzpatrick_scale:!1,category:"symbols"},x:{keywords:["no","delete","remove","cancel","red"],"char":"\u274c",fitzpatrick_scale:!1,category:"symbols"},o:{keywords:["circle","round"],"char":"\u2b55",fitzpatrick_scale:!1,category:"symbols"},stop_sign:{keywords:["stop"],"char":"\ud83d\uded1",fitzpatrick_scale:!1,category:"symbols"},anger:{keywords:["angry","mad"],"char":"\ud83d\udca2",fitzpatrick_scale:!1,category:"symbols"},hotsprings:{keywords:["bath","warm","relax"],"char":"\u2668\ufe0f",fitzpatrick_scale:!1,category:"symbols"},no_pedestrians:{keywords:["rules","crossing","walking","circle"],"char":"\ud83d\udeb7",fitzpatrick_scale:!1,category:"symbols"},do_not_litter:{keywords:["trash","bin","garbage","circle"],"char":"\ud83d\udeaf",fitzpatrick_scale:!1,category:"symbols"},no_bicycles:{keywords:["cyclist","prohibited","circle"],"char":"\ud83d\udeb3",fitzpatrick_scale:!1,category:"symbols"},"non-potable_water":{keywords:["drink","faucet","tap","circle"],"char":"\ud83d\udeb1",fitzpatrick_scale:!1,category:"symbols"},underage:{keywords:["18","drink","pub","night","minor","circle"],"char":"\ud83d\udd1e",fitzpatrick_scale:!1,category:"symbols"},no_mobile_phones:{keywords:["iphone","mute","circle"],"char":"\ud83d\udcf5",fitzpatrick_scale:!1,category:"symbols"},exclamation:{keywords:["heavy_exclamation_mark","danger","surprise","punctuation","wow","warning"],"char":"\u2757",fitzpatrick_scale:!1,category:"symbols"},grey_exclamation:{keywords:["surprise","punctuation","gray","wow","warning"],"char":"\u2755",fitzpatrick_scale:!1,category:"symbols"},question:{keywords:["doubt","confused"],"char":"\u2753",fitzpatrick_scale:!1,category:"symbols"},grey_question:{keywords:["doubts","gray","huh","confused"],"char":"\u2754",fitzpatrick_scale:!1,category:"symbols"},bangbang:{keywords:["exclamation","surprise"],"char":"\u203c\ufe0f",fitzpatrick_scale:!1,category:"symbols"},interrobang:{keywords:["wat","punctuation","surprise"],"char":"\u2049\ufe0f",fitzpatrick_scale:!1,category:"symbols"},100:{keywords:["score","perfect","numbers","century","exam","quiz","test","pass","hundred"],"char":"\ud83d\udcaf",fitzpatrick_scale:!1,category:"symbols"},low_brightness:{keywords:["sun","afternoon","warm","summer"],"char":"\ud83d\udd05",fitzpatrick_scale:!1,category:"symbols"},high_brightness:{keywords:["sun","light"],"char":"\ud83d\udd06",fitzpatrick_scale:!1,category:"symbols"},trident:{keywords:["weapon","spear"],"char":"\ud83d\udd31",fitzpatrick_scale:!1,category:"symbols"},fleur_de_lis:{keywords:["decorative","scout"],"char":"\u269c",fitzpatrick_scale:!1,category:"symbols"},part_alternation_mark:{keywords:["graph","presentation","stats","business","economics","bad"],"char":"\u303d\ufe0f",fitzpatrick_scale:!1,category:"symbols"},warning:{keywords:["exclamation","wip","alert","error","problem","issue"],"char":"\u26a0\ufe0f",fitzpatrick_scale:!1,category:"symbols"},children_crossing:{keywords:["school","warning","danger","sign","driving","yellow-diamond"],"char":"\ud83d\udeb8",fitzpatrick_scale:!1,category:"symbols"},beginner:{keywords:["badge","shield"],"char":"\ud83d\udd30",fitzpatrick_scale:!1,category:"symbols"},recycle:{keywords:["arrow","environment","garbage","trash"],"char":"\u267b\ufe0f",fitzpatrick_scale:!1,category:"symbols"},u6307:{keywords:["chinese","point","green-square","kanji"],"char":"\ud83c\ude2f",fitzpatrick_scale:!1,category:"symbols"},chart:{keywords:["green-square","graph","presentation","stats"],"char":"\ud83d\udcb9",fitzpatrick_scale:!1,category:"symbols"},sparkle:{keywords:["stars","green-square","awesome","good","fireworks"],"char":"\u2747\ufe0f",fitzpatrick_scale:!1,category:"symbols"},eight_spoked_asterisk:{keywords:["star","sparkle","green-square"],"char":"\u2733\ufe0f",fitzpatrick_scale:!1,category:"symbols"},negative_squared_cross_mark:{keywords:["x","green-square","no","deny"],"char":"\u274e",fitzpatrick_scale:!1,category:"symbols"},white_check_mark:{keywords:["green-square","ok","agree","vote","election","answer","tick"],"char":"\u2705",fitzpatrick_scale:!1,category:"symbols"},diamond_shape_with_a_dot_inside:{keywords:["jewel","blue","gem","crystal","fancy"],"char":"\ud83d\udca0",fitzpatrick_scale:!1,category:"symbols"},cyclone:{keywords:["weather","swirl","blue","cloud","vortex","spiral","whirlpool","spin","tornado","hurricane","typhoon"],"char":"\ud83c\udf00",fitzpatrick_scale:!1,category:"symbols"},loop:{keywords:["tape","cassette"],"char":"\u27bf",fitzpatrick_scale:!1,category:"symbols"},globe_with_meridians:{keywords:["earth","international","world","internet","interweb","i18n"],"char":"\ud83c\udf10",fitzpatrick_scale:!1,category:"symbols"},m:{keywords:["alphabet","blue-circle","letter"],"char":"\u24c2\ufe0f",fitzpatrick_scale:!1,category:"symbols"},atm:{keywords:["money","sales","cash","blue-square","payment","bank"],"char":"\ud83c\udfe7",fitzpatrick_scale:!1,category:"symbols"},sa:{keywords:["japanese","blue-square","katakana"],"char":"\ud83c\ude02\ufe0f",fitzpatrick_scale:!1,category:"symbols"},passport_control:{keywords:["custom","blue-square"],"char":"\ud83d\udec2",fitzpatrick_scale:!1,category:"symbols"},customs:{keywords:["passport","border","blue-square"],"char":"\ud83d\udec3",fitzpatrick_scale:!1,category:"symbols"},baggage_claim:{keywords:["blue-square","airport","transport"],"char":"\ud83d\udec4",fitzpatrick_scale:!1,category:"symbols"},left_luggage:{keywords:["blue-square","travel"],"char":"\ud83d\udec5",fitzpatrick_scale:!1,category:"symbols"},wheelchair:{keywords:["blue-square","disabled","a11y","accessibility"],"char":"\u267f",fitzpatrick_scale:!1,category:"symbols"},no_smoking:{keywords:["cigarette","blue-square","smell","smoke"],"char":"\ud83d\udead",fitzpatrick_scale:!1,category:"symbols"},wc:{keywords:["toilet","restroom","blue-square"],"char":"\ud83d\udebe",fitzpatrick_scale:!1,category:"symbols"},parking:{keywords:["cars","blue-square","alphabet","letter"],"char":"\ud83c\udd7f\ufe0f",fitzpatrick_scale:!1,category:"symbols"},potable_water:{keywords:["blue-square","liquid","restroom","cleaning","faucet"],"char":"\ud83d\udeb0",fitzpatrick_scale:!1,category:"symbols"},mens:{keywords:["toilet","restroom","wc","blue-square","gender","male"],"char":"\ud83d\udeb9",fitzpatrick_scale:!1,category:"symbols"},womens:{keywords:["purple-square","woman","female","toilet","loo","restroom","gender"],"char":"\ud83d\udeba",fitzpatrick_scale:!1,category:"symbols"},baby_symbol:{keywords:["orange-square","child"],"char":"\ud83d\udebc",fitzpatrick_scale:!1,category:"symbols"},restroom:{keywords:["blue-square","toilet","refresh","wc","gender"],"char":"\ud83d\udebb",fitzpatrick_scale:!1,category:"symbols"},put_litter_in_its_place:{keywords:["blue-square","sign","human","info"],"char":"\ud83d\udeae",fitzpatrick_scale:!1,category:"symbols"},cinema:{keywords:["blue-square","record","film","movie","curtain","stage","theater"],"char":"\ud83c\udfa6",fitzpatrick_scale:!1,category:"symbols"},signal_strength:{keywords:["blue-square","reception","phone","internet","connection","wifi","bluetooth","bars"],"char":"\ud83d\udcf6",fitzpatrick_scale:!1,category:"symbols"},koko:{keywords:["blue-square","here","katakana","japanese","destination"],"char":"\ud83c\ude01",fitzpatrick_scale:!1,category:"symbols"},ng:{keywords:["blue-square","words","shape","icon"],"char":"\ud83c\udd96",fitzpatrick_scale:!1,category:"symbols"},ok:{keywords:["good","agree","yes","blue-square"],"char":"\ud83c\udd97",fitzpatrick_scale:!1,category:"symbols"},up:{keywords:["blue-square","above","high"],"char":"\ud83c\udd99",fitzpatrick_scale:!1,category:"symbols"},cool:{keywords:["words","blue-square"],"char":"\ud83c\udd92",fitzpatrick_scale:!1,category:"symbols"},"new":{keywords:["blue-square","words","start"],"char":"\ud83c\udd95",fitzpatrick_scale:!1,category:"symbols"},free:{keywords:["blue-square","words"],"char":"\ud83c\udd93",fitzpatrick_scale:!1,category:"symbols"},zero:{keywords:["0","numbers","blue-square","null"],"char":"0\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},one:{keywords:["blue-square","numbers","1"],"char":"1\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},two:{keywords:["numbers","2","prime","blue-square"],"char":"2\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},three:{keywords:["3","numbers","prime","blue-square"],"char":"3\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},four:{keywords:["4","numbers","blue-square"],"char":"4\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},five:{keywords:["5","numbers","blue-square","prime"],"char":"5\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},six:{keywords:["6","numbers","blue-square"],"char":"6\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},seven:{keywords:["7","numbers","blue-square","prime"],"char":"7\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},eight:{keywords:["8","blue-square","numbers"],"char":"8\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},nine:{keywords:["blue-square","numbers","9"],"char":"9\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},keycap_ten:{keywords:["numbers","10","blue-square"],"char":"\ud83d\udd1f",fitzpatrick_scale:!1,category:"symbols"},asterisk:{keywords:["star","keycap"],"char":"*\u20e3",fitzpatrick_scale:!1,category:"symbols"},1234:{keywords:["numbers","blue-square"],"char":"\ud83d\udd22",fitzpatrick_scale:!1,category:"symbols"},eject_button:{keywords:["blue-square"],"char":"\u23cf\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_forward:{keywords:["blue-square","right","direction","play"],"char":"\u25b6\ufe0f",fitzpatrick_scale:!1,category:"symbols"},pause_button:{keywords:["pause","blue-square"],"char":"\u23f8",fitzpatrick_scale:!1,category:"symbols"},next_track_button:{keywords:["forward","next","blue-square"],"char":"\u23ed",fitzpatrick_scale:!1,category:"symbols"},stop_button:{keywords:["blue-square"],"char":"\u23f9",fitzpatrick_scale:!1,category:"symbols"},record_button:{keywords:["blue-square"],"char":"\u23fa",fitzpatrick_scale:!1,category:"symbols"},play_or_pause_button:{keywords:["blue-square","play","pause"],"char":"\u23ef",fitzpatrick_scale:!1,category:"symbols"},previous_track_button:{keywords:["backward"],"char":"\u23ee",fitzpatrick_scale:!1,category:"symbols"},fast_forward:{keywords:["blue-square","play","speed","continue"],"char":"\u23e9",fitzpatrick_scale:!1,category:"symbols"},rewind:{keywords:["play","blue-square"],"char":"\u23ea",fitzpatrick_scale:!1,category:"symbols"},twisted_rightwards_arrows:{keywords:["blue-square","shuffle","music","random"],"char":"\ud83d\udd00",fitzpatrick_scale:!1,category:"symbols"},repeat:{keywords:["loop","record"],"char":"\ud83d\udd01",fitzpatrick_scale:!1,category:"symbols"},repeat_one:{keywords:["blue-square","loop"],"char":"\ud83d\udd02",fitzpatrick_scale:!1,category:"symbols"},arrow_backward:{keywords:["blue-square","left","direction"],"char":"\u25c0\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_up_small:{keywords:["blue-square","triangle","direction","point","forward","top"],"char":"\ud83d\udd3c",fitzpatrick_scale:!1,category:"symbols"},arrow_down_small:{keywords:["blue-square","direction","bottom"],"char":"\ud83d\udd3d",fitzpatrick_scale:!1,category:"symbols"},arrow_double_up:{keywords:["blue-square","direction","top"],"char":"\u23eb",fitzpatrick_scale:!1,category:"symbols"},arrow_double_down:{keywords:["blue-square","direction","bottom"],"char":"\u23ec",fitzpatrick_scale:!1,category:"symbols"},arrow_right:{keywords:["blue-square","next"],"char":"\u27a1\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_left:{keywords:["blue-square","previous","back"],"char":"\u2b05\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_up:{keywords:["blue-square","continue","top","direction"],"char":"\u2b06\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_down:{keywords:["blue-square","direction","bottom"],"char":"\u2b07\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_upper_right:{keywords:["blue-square","point","direction","diagonal","northeast"],"char":"\u2197\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_lower_right:{keywords:["blue-square","direction","diagonal","southeast"],"char":"\u2198\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_lower_left:{keywords:["blue-square","direction","diagonal","southwest"],"char":"\u2199\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_upper_left:{keywords:["blue-square","point","direction","diagonal","northwest"],"char":"\u2196\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_up_down:{keywords:["blue-square","direction","way","vertical"],"char":"\u2195\ufe0f",fitzpatrick_scale:!1,category:"symbols"},left_right_arrow:{keywords:["shape","direction","horizontal","sideways"],"char":"\u2194\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrows_counterclockwise:{keywords:["blue-square","sync","cycle"],"char":"\ud83d\udd04",fitzpatrick_scale:!1,category:"symbols"},arrow_right_hook:{keywords:["blue-square","return","rotate","direction"],"char":"\u21aa\ufe0f",fitzpatrick_scale:!1,category:"symbols"},leftwards_arrow_with_hook:{keywords:["back","return","blue-square","undo","enter"],"char":"\u21a9\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_heading_up:{keywords:["blue-square","direction","top"],"char":"\u2934\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_heading_down:{keywords:["blue-square","direction","bottom"],"char":"\u2935\ufe0f",fitzpatrick_scale:!1,category:"symbols"},hash:{keywords:["symbol","blue-square","twitter"],"char":"#\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},information_source:{keywords:["blue-square","alphabet","letter"],"char":"\u2139\ufe0f",fitzpatrick_scale:!1,category:"symbols"},abc:{keywords:["blue-square","alphabet"],"char":"\ud83d\udd24",fitzpatrick_scale:!1,category:"symbols"},abcd:{keywords:["blue-square","alphabet"],"char":"\ud83d\udd21",fitzpatrick_scale:!1,category:"symbols"},capital_abcd:{keywords:["alphabet","words","blue-square"],"char":"\ud83d\udd20",fitzpatrick_scale:!1,category:"symbols"},symbols:{keywords:["blue-square","music","note","ampersand","percent","glyphs","characters"],"char":"\ud83d\udd23",fitzpatrick_scale:!1,category:"symbols"},musical_note:{keywords:["score","tone","sound"],"char":"\ud83c\udfb5",fitzpatrick_scale:!1,category:"symbols"},notes:{keywords:["music","score"],"char":"\ud83c\udfb6",fitzpatrick_scale:!1,category:"symbols"},wavy_dash:{keywords:["draw","line","moustache","mustache","squiggle","scribble"],"char":"\u3030\ufe0f",fitzpatrick_scale:!1,category:"symbols"},curly_loop:{keywords:["scribble","draw","shape","squiggle"],"char":"\u27b0",fitzpatrick_scale:!1,category:"symbols"},heavy_check_mark:{keywords:["ok","nike","answer","yes","tick"],"char":"\u2714\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrows_clockwise:{keywords:["sync","cycle","round","repeat"],"char":"\ud83d\udd03",fitzpatrick_scale:!1,category:"symbols"},heavy_plus_sign:{keywords:["math","calculation","addition","more","increase"],"char":"\u2795",fitzpatrick_scale:!1,category:"symbols"},heavy_minus_sign:{keywords:["math","calculation","subtract","less"],"char":"\u2796",fitzpatrick_scale:!1,category:"symbols"},heavy_division_sign:{keywords:["divide","math","calculation"],"char":"\u2797",fitzpatrick_scale:!1,category:"symbols"},heavy_multiplication_x:{keywords:["math","calculation"],"char":"\u2716\ufe0f",fitzpatrick_scale:!1,category:"symbols"},infinity:{keywords:["forever"],"char":"\u267e",fitzpatrick_scale:!1,category:"symbols"},heavy_dollar_sign:{keywords:["money","sales","payment","currency","buck"],"char":"\ud83d\udcb2",fitzpatrick_scale:!1,category:"symbols"},currency_exchange:{keywords:["money","sales","dollar","travel"],"char":"\ud83d\udcb1",fitzpatrick_scale:!1,category:"symbols"},copyright:{keywords:["ip","license","circle","law","legal"],"char":"\xa9\ufe0f",fitzpatrick_scale:!1,category:"symbols"},registered:{keywords:["alphabet","circle"],"char":"\xae\ufe0f",fitzpatrick_scale:!1,category:"symbols"},tm:{keywords:["trademark","brand","law","legal"],"char":"\u2122\ufe0f",fitzpatrick_scale:!1,category:"symbols"},end:{keywords:["words","arrow"],"char":"\ud83d\udd1a",fitzpatrick_scale:!1,category:"symbols"},back:{keywords:["arrow","words","return"],"char":"\ud83d\udd19",fitzpatrick_scale:!1,category:"symbols"},on:{keywords:["arrow","words"],"char":"\ud83d\udd1b",fitzpatrick_scale:!1,category:"symbols"},top:{keywords:["words","blue-square"],"char":"\ud83d\udd1d",fitzpatrick_scale:!1,category:"symbols"},soon:{keywords:["arrow","words"],"char":"\ud83d\udd1c",fitzpatrick_scale:!1,category:"symbols"},ballot_box_with_check:{keywords:["ok","agree","confirm","black-square","vote","election","yes","tick"],"char":"\u2611\ufe0f",fitzpatrick_scale:!1,category:"symbols"},radio_button:{keywords:["input","old","music","circle"],"char":"\ud83d\udd18",fitzpatrick_scale:!1,category:"symbols"},white_circle:{keywords:["shape","round"],"char":"\u26aa",fitzpatrick_scale:!1,category:"symbols"},black_circle:{keywords:["shape","button","round"],"char":"\u26ab",fitzpatrick_scale:!1,category:"symbols"},red_circle:{keywords:["shape","error","danger"],"char":"\ud83d\udd34",fitzpatrick_scale:!1,category:"symbols"},large_blue_circle:{keywords:["shape","icon","button"],"char":"\ud83d\udd35",fitzpatrick_scale:!1,category:"symbols"},small_orange_diamond:{keywords:["shape","jewel","gem"],"char":"\ud83d\udd38",fitzpatrick_scale:!1,category:"symbols"},small_blue_diamond:{keywords:["shape","jewel","gem"],"char":"\ud83d\udd39",fitzpatrick_scale:!1,category:"symbols"},large_orange_diamond:{keywords:["shape","jewel","gem"],"char":"\ud83d\udd36",fitzpatrick_scale:!1,category:"symbols"},large_blue_diamond:{keywords:["shape","jewel","gem"],"char":"\ud83d\udd37",fitzpatrick_scale:!1,category:"symbols"},small_red_triangle:{keywords:["shape","direction","up","top"],"char":"\ud83d\udd3a",fitzpatrick_scale:!1,category:"symbols"},black_small_square:{keywords:["shape","icon"],"char":"\u25aa\ufe0f",fitzpatrick_scale:!1,category:"symbols"},white_small_square:{keywords:["shape","icon"],"char":"\u25ab\ufe0f",fitzpatrick_scale:!1,category:"symbols"},black_large_square:{keywords:["shape","icon","button"],"char":"\u2b1b",fitzpatrick_scale:!1,category:"symbols"},white_large_square:{keywords:["shape","icon","stone","button"],"char":"\u2b1c",fitzpatrick_scale:!1,category:"symbols"},small_red_triangle_down:{keywords:["shape","direction","bottom"],"char":"\ud83d\udd3b",fitzpatrick_scale:!1,category:"symbols"},black_medium_square:{keywords:["shape","button","icon"],"char":"\u25fc\ufe0f",fitzpatrick_scale:!1,category:"symbols"},white_medium_square:{keywords:["shape","stone","icon"],"char":"\u25fb\ufe0f",fitzpatrick_scale:!1,category:"symbols"},black_medium_small_square:{keywords:["icon","shape","button"],"char":"\u25fe",fitzpatrick_scale:!1,category:"symbols"},white_medium_small_square:{keywords:["shape","stone","icon","button"],"char":"\u25fd",fitzpatrick_scale:!1,category:"symbols"},black_square_button:{keywords:["shape","input","frame"],"char":"\ud83d\udd32",fitzpatrick_scale:!1,category:"symbols"},white_square_button:{keywords:["shape","input"],"char":"\ud83d\udd33",fitzpatrick_scale:!1,category:"symbols"},speaker:{keywords:["sound","volume","silence","broadcast"],"char":"\ud83d\udd08",fitzpatrick_scale:!1,category:"symbols"},sound:{keywords:["volume","speaker","broadcast"],"char":"\ud83d\udd09",fitzpatrick_scale:!1,category:"symbols"},loud_sound:{keywords:["volume","noise","noisy","speaker","broadcast"],"char":"\ud83d\udd0a",fitzpatrick_scale:!1,category:"symbols"},mute:{keywords:["sound","volume","silence","quiet"],"char":"\ud83d\udd07",fitzpatrick_scale:!1,category:"symbols"},mega:{keywords:["sound","speaker","volume"],"char":"\ud83d\udce3",fitzpatrick_scale:!1,category:"symbols"},loudspeaker:{keywords:["volume","sound"],"char":"\ud83d\udce2",fitzpatrick_scale:!1,category:"symbols"},bell:{keywords:["sound","notification","christmas","xmas","chime"],"char":"\ud83d\udd14",fitzpatrick_scale:!1,category:"symbols"},no_bell:{keywords:["sound","volume","mute","quiet","silent"],"char":"\ud83d\udd15",fitzpatrick_scale:!1,category:"symbols"},black_joker:{keywords:["poker","cards","game","play","magic"],"char":"\ud83c\udccf",fitzpatrick_scale:!1,category:"symbols"},mahjong:{keywords:["game","play","chinese","kanji"],"char":"\ud83c\udc04",fitzpatrick_scale:!1,category:"symbols"},spades:{keywords:["poker","cards","suits","magic"],"char":"\u2660\ufe0f",fitzpatrick_scale:!1,category:"symbols"},clubs:{keywords:["poker","cards","magic","suits"],"char":"\u2663\ufe0f",fitzpatrick_scale:!1,category:"symbols"},hearts:{keywords:["poker","cards","magic","suits"],"char":"\u2665\ufe0f",fitzpatrick_scale:!1,category:"symbols"},diamonds:{keywords:["poker","cards","magic","suits"],"char":"\u2666\ufe0f",fitzpatrick_scale:!1,category:"symbols"},flower_playing_cards:{keywords:["game","sunset","red"],"char":"\ud83c\udfb4",fitzpatrick_scale:!1,category:"symbols"},thought_balloon:{keywords:["bubble","cloud","speech","thinking","dream"],"char":"\ud83d\udcad",fitzpatrick_scale:!1,category:"symbols"},right_anger_bubble:{keywords:["caption","speech","thinking","mad"],"char":"\ud83d\uddef",fitzpatrick_scale:!1,category:"symbols"},speech_balloon:{keywords:["bubble","words","message","talk","chatting"],"char":"\ud83d\udcac",fitzpatrick_scale:!1,category:"symbols"},left_speech_bubble:{keywords:["words","message","talk","chatting"],"char":"\ud83d\udde8",fitzpatrick_scale:!1,category:"symbols"},clock1:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd50",fitzpatrick_scale:!1,category:"symbols"},clock2:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd51",fitzpatrick_scale:!1,category:"symbols"},clock3:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd52",fitzpatrick_scale:!1,category:"symbols"},clock4:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd53",fitzpatrick_scale:!1,category:"symbols"},clock5:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd54",fitzpatrick_scale:!1,category:"symbols"},clock6:{keywords:["time","late","early","schedule","dawn","dusk"],"char":"\ud83d\udd55",fitzpatrick_scale:!1,category:"symbols"},clock7:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd56",fitzpatrick_scale:!1,category:"symbols"},clock8:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd57",fitzpatrick_scale:!1,category:"symbols"},clock9:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd58",fitzpatrick_scale:!1,category:"symbols"},clock10:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd59",fitzpatrick_scale:!1,category:"symbols"},clock11:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd5a",fitzpatrick_scale:!1,category:"symbols"},clock12:{keywords:["time","noon","midnight","midday","late","early","schedule"],"char":"\ud83d\udd5b",fitzpatrick_scale:!1,category:"symbols"},clock130:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd5c",fitzpatrick_scale:!1,category:"symbols"},clock230:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd5d",fitzpatrick_scale:!1,category:"symbols"},clock330:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd5e",fitzpatrick_scale:!1,category:"symbols"},clock430:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd5f",fitzpatrick_scale:!1,category:"symbols"},clock530:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd60",fitzpatrick_scale:!1,category:"symbols"},clock630:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd61",fitzpatrick_scale:!1,category:"symbols"},clock730:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd62",fitzpatrick_scale:!1,category:"symbols"},clock830:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd63",fitzpatrick_scale:!1,category:"symbols"},clock930:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd64",fitzpatrick_scale:!1,category:"symbols"},clock1030:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd65",fitzpatrick_scale:!1,category:"symbols"},clock1130:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd66",fitzpatrick_scale:!1,category:"symbols"},clock1230:{keywords:["time","late","early","schedule"],"char":"\ud83d\udd67",fitzpatrick_scale:!1,category:"symbols"},afghanistan:{keywords:["af","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddeb",fitzpatrick_scale:!1,category:"flags"},aland_islands:{keywords:["\xc5land","islands","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddfd",fitzpatrick_scale:!1,category:"flags"},albania:{keywords:["al","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddf1",fitzpatrick_scale:!1,category:"flags"},algeria:{keywords:["dz","flag","nation","country","banner"],"char":"\ud83c\udde9\ud83c\uddff",fitzpatrick_scale:!1,category:"flags"},american_samoa:{keywords:["american","ws","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddf8",fitzpatrick_scale:!1,category:"flags"},andorra:{keywords:["ad","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\udde9",fitzpatrick_scale:!1,category:"flags"},angola:{keywords:["ao","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddf4",fitzpatrick_scale:!1,category:"flags"},anguilla:{keywords:["ai","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddee",fitzpatrick_scale:!1,category:"flags"},antarctica:{keywords:["aq","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddf6",fitzpatrick_scale:!1,category:"flags"},antigua_barbuda:{keywords:["antigua","barbuda","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},argentina:{keywords:["ar","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},armenia:{keywords:["am","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},aruba:{keywords:["aw","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddfc",fitzpatrick_scale:!1,category:"flags"},australia:{keywords:["au","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddfa",fitzpatrick_scale:!1,category:"flags"},austria:{keywords:["at","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddf9",fitzpatrick_scale:!1,category:"flags"},azerbaijan:{keywords:["az","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddff",fitzpatrick_scale:!1,category:"flags"},bahamas:{keywords:["bs","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddf8",fitzpatrick_scale:!1,category:"flags"},bahrain:{keywords:["bh","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\udded",fitzpatrick_scale:!1,category:"flags"},bangladesh:{keywords:["bd","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\udde9",fitzpatrick_scale:!1,category:"flags"},barbados:{keywords:["bb","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\udde7",fitzpatrick_scale:!1,category:"flags"},belarus:{keywords:["by","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddfe",fitzpatrick_scale:!1,category:"flags"},belgium:{keywords:["be","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},belize:{keywords:["bz","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddff",fitzpatrick_scale:!1,category:"flags"},benin:{keywords:["bj","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddef",fitzpatrick_scale:!1,category:"flags"},bermuda:{keywords:["bm","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},bhutan:{keywords:["bt","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddf9",fitzpatrick_scale:!1,category:"flags"},bolivia:{keywords:["bo","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddf4",fitzpatrick_scale:!1,category:"flags"},caribbean_netherlands:{keywords:["bonaire","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddf6",fitzpatrick_scale:!1,category:"flags"},bosnia_herzegovina:{keywords:["bosnia","herzegovina","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\udde6",fitzpatrick_scale:!1,category:"flags"},botswana:{keywords:["bw","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddfc",fitzpatrick_scale:!1,category:"flags"},brazil:{keywords:["br","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},british_indian_ocean_territory:{keywords:["british","indian","ocean","territory","flag","nation","country","banner"],"char":"\ud83c\uddee\ud83c\uddf4",fitzpatrick_scale:!1,category:"flags"},british_virgin_islands:{keywords:["british","virgin","islands","bvi","flag","nation","country","banner"],"char":"\ud83c\uddfb\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},brunei:{keywords:["bn","darussalam","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddf3",fitzpatrick_scale:!1,category:"flags"},bulgaria:{keywords:["bg","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},burkina_faso:{keywords:["burkina","faso","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddeb",fitzpatrick_scale:!1,category:"flags"},burundi:{keywords:["bi","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddee",fitzpatrick_scale:!1,category:"flags"},cape_verde:{keywords:["cabo","verde","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddfb",fitzpatrick_scale:!1,category:"flags"},cambodia:{keywords:["kh","flag","nation","country","banner"],"char":"\ud83c\uddf0\ud83c\udded",fitzpatrick_scale:!1,category:"flags"},cameroon:{keywords:["cm","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},canada:{keywords:["ca","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\udde6",fitzpatrick_scale:!1,category:"flags"},canary_islands:{keywords:["canary","islands","flag","nation","country","banner"],"char":"\ud83c\uddee\ud83c\udde8",fitzpatrick_scale:!1,category:"flags"},cayman_islands:{keywords:["cayman","islands","flag","nation","country","banner"],"char":"\ud83c\uddf0\ud83c\uddfe",fitzpatrick_scale:!1,category:"flags"},central_african_republic:{keywords:["central","african","republic","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddeb",fitzpatrick_scale:!1,category:"flags"},chad:{keywords:["td","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\udde9",fitzpatrick_scale:!1,category:"flags"},chile:{keywords:["flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddf1",fitzpatrick_scale:!1,category:"flags"},cn:{keywords:["china","chinese","prc","flag","country","nation","banner"],"char":"\ud83c\udde8\ud83c\uddf3",fitzpatrick_scale:!1,category:"flags"},christmas_island:{keywords:["christmas","island","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddfd",fitzpatrick_scale:!1,category:"flags"},cocos_islands:{keywords:["cocos","keeling","islands","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\udde8",fitzpatrick_scale:!1,category:"flags"},colombia:{keywords:["co","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddf4",fitzpatrick_scale:!1,category:"flags"},comoros:{keywords:["km","flag","nation","country","banner"],"char":"\ud83c\uddf0\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},congo_brazzaville:{keywords:["congo","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},congo_kinshasa:{keywords:["congo","democratic","republic","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\udde9",fitzpatrick_scale:!1,category:"flags"},cook_islands:{keywords:["cook","islands","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddf0",fitzpatrick_scale:!1,category:"flags"},costa_rica:{keywords:["costa","rica","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},croatia:{keywords:["hr","flag","nation","country","banner"],"char":"\ud83c\udded\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},cuba:{keywords:["cu","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddfa",fitzpatrick_scale:!1,category:"flags"},curacao:{keywords:["cura\xe7ao","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddfc",fitzpatrick_scale:!1,category:"flags"},cyprus:{keywords:["cy","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddfe",fitzpatrick_scale:!1,category:"flags"},czech_republic:{keywords:["cz","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddff",fitzpatrick_scale:!1,category:"flags"},denmark:{keywords:["dk","flag","nation","country","banner"],"char":"\ud83c\udde9\ud83c\uddf0",fitzpatrick_scale:!1,category:"flags"},djibouti:{keywords:["dj","flag","nation","country","banner"],"char":"\ud83c\udde9\ud83c\uddef",fitzpatrick_scale:!1,category:"flags"},dominica:{keywords:["dm","flag","nation","country","banner"],"char":"\ud83c\udde9\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},dominican_republic:{keywords:["dominican","republic","flag","nation","country","banner"],"char":"\ud83c\udde9\ud83c\uddf4",fitzpatrick_scale:!1,category:"flags"},ecuador:{keywords:["ec","flag","nation","country","banner"],"char":"\ud83c\uddea\ud83c\udde8",fitzpatrick_scale:!1,category:"flags"},egypt:{keywords:["eg","flag","nation","country","banner"],"char":"\ud83c\uddea\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},el_salvador:{keywords:["el","salvador","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddfb",fitzpatrick_scale:!1,category:"flags"},equatorial_guinea:{keywords:["equatorial","gn","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddf6",fitzpatrick_scale:!1,category:"flags"},eritrea:{keywords:["er","flag","nation","country","banner"],"char":"\ud83c\uddea\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},estonia:{keywords:["ee","flag","nation","country","banner"],"char":"\ud83c\uddea\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},ethiopia:{keywords:["et","flag","nation","country","banner"],"char":"\ud83c\uddea\ud83c\uddf9",fitzpatrick_scale:!1,category:"flags"},eu:{keywords:["european","union","flag","banner"],"char":"\ud83c\uddea\ud83c\uddfa",fitzpatrick_scale:!1,category:"flags"},falkland_islands:{keywords:["falkland","islands","malvinas","flag","nation","country","banner"],"char":"\ud83c\uddeb\ud83c\uddf0",fitzpatrick_scale:!1,category:"flags"},faroe_islands:{keywords:["faroe","islands","flag","nation","country","banner"],"char":"\ud83c\uddeb\ud83c\uddf4",fitzpatrick_scale:!1,category:"flags"},fiji:{keywords:["fj","flag","nation","country","banner"],"char":"\ud83c\uddeb\ud83c\uddef",fitzpatrick_scale:!1,category:"flags"},finland:{keywords:["fi","flag","nation","country","banner"],"char":"\ud83c\uddeb\ud83c\uddee",fitzpatrick_scale:!1,category:"flags"},fr:{keywords:["banner","flag","nation","france","french","country"],"char":"\ud83c\uddeb\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},french_guiana:{keywords:["french","guiana","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddeb",fitzpatrick_scale:!1,category:"flags"},french_polynesia:{keywords:["french","polynesia","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\uddeb",fitzpatrick_scale:!1,category:"flags"},french_southern_territories:{keywords:["french","southern","territories","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddeb",fitzpatrick_scale:!1,category:"flags"},gabon:{keywords:["ga","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\udde6",fitzpatrick_scale:!1,category:"flags"},gambia:{keywords:["gm","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},georgia:{keywords:["ge","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},de:{keywords:["german","nation","flag","country","banner"],"char":"\ud83c\udde9\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},ghana:{keywords:["gh","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\udded",fitzpatrick_scale:!1,category:"flags"},gibraltar:{keywords:["gi","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddee",fitzpatrick_scale:!1,category:"flags"},greece:{keywords:["gr","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},greenland:{keywords:["gl","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddf1",fitzpatrick_scale:!1,category:"flags"},grenada:{keywords:["gd","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\udde9",fitzpatrick_scale:!1,category:"flags"},guadeloupe:{keywords:["gp","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddf5",fitzpatrick_scale:!1,category:"flags"},guam:{keywords:["gu","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddfa",fitzpatrick_scale:!1,category:"flags"},guatemala:{keywords:["gt","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddf9",fitzpatrick_scale:!1,category:"flags"},guernsey:{keywords:["gg","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},guinea:{keywords:["gn","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddf3",fitzpatrick_scale:!1,category:"flags"},guinea_bissau:{keywords:["gw","bissau","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddfc",fitzpatrick_scale:!1,category:"flags"},guyana:{keywords:["gy","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddfe",fitzpatrick_scale:!1,category:"flags"},haiti:{keywords:["ht","flag","nation","country","banner"],"char":"\ud83c\udded\ud83c\uddf9",fitzpatrick_scale:!1,category:"flags"},honduras:{keywords:["hn","flag","nation","country","banner"],"char":"\ud83c\udded\ud83c\uddf3",fitzpatrick_scale:!1,category:"flags"},hong_kong:{keywords:["hong","kong","flag","nation","country","banner"],"char":"\ud83c\udded\ud83c\uddf0",fitzpatrick_scale:!1,category:"flags"},hungary:{keywords:["hu","flag","nation","country","banner"],"char":"\ud83c\udded\ud83c\uddfa",fitzpatrick_scale:!1,category:"flags"},iceland:{keywords:["is","flag","nation","country","banner"],"char":"\ud83c\uddee\ud83c\uddf8",fitzpatrick_scale:!1,category:"flags"},india:{keywords:["in","flag","nation","country","banner"],"char":"\ud83c\uddee\ud83c\uddf3",fitzpatrick_scale:!1,category:"flags"},indonesia:{keywords:["flag","nation","country","banner"],"char":"\ud83c\uddee\ud83c\udde9",fitzpatrick_scale:!1,category:"flags"},iran:{keywords:["iran,","islamic","republic","flag","nation","country","banner"],"char":"\ud83c\uddee\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},iraq:{keywords:["iq","flag","nation","country","banner"],"char":"\ud83c\uddee\ud83c\uddf6",fitzpatrick_scale:!1,category:"flags"},ireland:{keywords:["ie","flag","nation","country","banner"],"char":"\ud83c\uddee\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},isle_of_man:{keywords:["isle","man","flag","nation","country","banner"],"char":"\ud83c\uddee\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},israel:{keywords:["il","flag","nation","country","banner"],"char":"\ud83c\uddee\ud83c\uddf1",fitzpatrick_scale:!1,category:"flags"},it:{keywords:["italy","flag","nation","country","banner"],"char":"\ud83c\uddee\ud83c\uddf9",fitzpatrick_scale:!1,category:"flags"},cote_divoire:{keywords:["ivory","coast","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\uddee",fitzpatrick_scale:!1,category:"flags"},jamaica:{keywords:["jm","flag","nation","country","banner"],"char":"\ud83c\uddef\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},jp:{keywords:["japanese","nation","flag","country","banner"],"char":"\ud83c\uddef\ud83c\uddf5",fitzpatrick_scale:!1,category:"flags"},jersey:{keywords:["je","flag","nation","country","banner"],"char":"\ud83c\uddef\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},jordan:{keywords:["jo","flag","nation","country","banner"],"char":"\ud83c\uddef\ud83c\uddf4",fitzpatrick_scale:!1,category:"flags"},kazakhstan:{keywords:["kz","flag","nation","country","banner"],"char":"\ud83c\uddf0\ud83c\uddff",fitzpatrick_scale:!1,category:"flags"},kenya:{keywords:["ke","flag","nation","country","banner"],"char":"\ud83c\uddf0\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},kiribati:{keywords:["ki","flag","nation","country","banner"],"char":"\ud83c\uddf0\ud83c\uddee",fitzpatrick_scale:!1,category:"flags"},kosovo:{keywords:["xk","flag","nation","country","banner"],"char":"\ud83c\uddfd\ud83c\uddf0",fitzpatrick_scale:!1,category:"flags"},kuwait:{keywords:["kw","flag","nation","country","banner"],"char":"\ud83c\uddf0\ud83c\uddfc",fitzpatrick_scale:!1,category:"flags"},kyrgyzstan:{keywords:["kg","flag","nation","country","banner"],"char":"\ud83c\uddf0\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},laos:{keywords:["lao","democratic","republic","flag","nation","country","banner"],"char":"\ud83c\uddf1\ud83c\udde6",fitzpatrick_scale:!1,category:"flags"},latvia:{keywords:["lv","flag","nation","country","banner"],"char":"\ud83c\uddf1\ud83c\uddfb",fitzpatrick_scale:!1,category:"flags"},lebanon:{keywords:["lb","flag","nation","country","banner"],"char":"\ud83c\uddf1\ud83c\udde7",fitzpatrick_scale:!1,category:"flags"},lesotho:{keywords:["ls","flag","nation","country","banner"],"char":"\ud83c\uddf1\ud83c\uddf8",fitzpatrick_scale:!1,category:"flags"},liberia:{keywords:["lr","flag","nation","country","banner"],"char":"\ud83c\uddf1\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},libya:{keywords:["ly","flag","nation","country","banner"],"char":"\ud83c\uddf1\ud83c\uddfe",fitzpatrick_scale:!1,category:"flags"},liechtenstein:{keywords:["li","flag","nation","country","banner"],"char":"\ud83c\uddf1\ud83c\uddee",fitzpatrick_scale:!1,category:"flags"},lithuania:{keywords:["lt","flag","nation","country","banner"],"char":"\ud83c\uddf1\ud83c\uddf9",fitzpatrick_scale:!1,category:"flags"},luxembourg:{keywords:["lu","flag","nation","country","banner"],"char":"\ud83c\uddf1\ud83c\uddfa",fitzpatrick_scale:!1,category:"flags"},macau:{keywords:["macao","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddf4",fitzpatrick_scale:!1,category:"flags"},macedonia:{keywords:["macedonia,","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddf0",fitzpatrick_scale:!1,category:"flags"},madagascar:{keywords:["mg","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},malawi:{keywords:["mw","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddfc",fitzpatrick_scale:!1,category:"flags"},malaysia:{keywords:["my","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddfe",fitzpatrick_scale:!1,category:"flags"},maldives:{keywords:["mv","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddfb",fitzpatrick_scale:!1,category:"flags"},mali:{keywords:["ml","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddf1",fitzpatrick_scale:!1,category:"flags"},malta:{keywords:["mt","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddf9",fitzpatrick_scale:!1,category:"flags"},marshall_islands:{keywords:["marshall","islands","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\udded",fitzpatrick_scale:!1,category:"flags"},martinique:{keywords:["mq","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddf6",fitzpatrick_scale:!1,category:"flags"},mauritania:{keywords:["mr","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},mauritius:{keywords:["mu","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddfa",fitzpatrick_scale:!1,category:"flags"},mayotte:{keywords:["yt","flag","nation","country","banner"],"char":"\ud83c\uddfe\ud83c\uddf9",fitzpatrick_scale:!1,category:"flags"},mexico:{keywords:["mx","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddfd",fitzpatrick_scale:!1,category:"flags"},micronesia:{keywords:["micronesia,","federated","states","flag","nation","country","banner"],"char":"\ud83c\uddeb\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},moldova:{keywords:["moldova,","republic","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\udde9",fitzpatrick_scale:!1,category:"flags"},monaco:{keywords:["mc","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\udde8",fitzpatrick_scale:!1,category:"flags"},mongolia:{keywords:["mn","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddf3",fitzpatrick_scale:!1,category:"flags"},montenegro:{keywords:["me","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},montserrat:{keywords:["ms","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddf8",fitzpatrick_scale:!1,category:"flags"},morocco:{keywords:["ma","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\udde6",fitzpatrick_scale:!1,category:"flags"},mozambique:{keywords:["mz","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddff",fitzpatrick_scale:!1,category:"flags"},myanmar:{keywords:["mm","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},namibia:{keywords:["na","flag","nation","country","banner"],"char":"\ud83c\uddf3\ud83c\udde6",fitzpatrick_scale:!1,category:"flags"},nauru:{keywords:["nr","flag","nation","country","banner"],"char":"\ud83c\uddf3\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},nepal:{keywords:["np","flag","nation","country","banner"],"char":"\ud83c\uddf3\ud83c\uddf5",fitzpatrick_scale:!1,category:"flags"},netherlands:{keywords:["nl","flag","nation","country","banner"],"char":"\ud83c\uddf3\ud83c\uddf1",fitzpatrick_scale:!1,category:"flags"},new_caledonia:{keywords:["new","caledonia","flag","nation","country","banner"],"char":"\ud83c\uddf3\ud83c\udde8",fitzpatrick_scale:!1,category:"flags"},new_zealand:{keywords:["new","zealand","flag","nation","country","banner"],"char":"\ud83c\uddf3\ud83c\uddff",fitzpatrick_scale:!1,category:"flags"},nicaragua:{keywords:["ni","flag","nation","country","banner"],"char":"\ud83c\uddf3\ud83c\uddee",fitzpatrick_scale:!1,category:"flags"},niger:{keywords:["ne","flag","nation","country","banner"],"char":"\ud83c\uddf3\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},nigeria:{keywords:["flag","nation","country","banner"],"char":"\ud83c\uddf3\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},niue:{keywords:["nu","flag","nation","country","banner"],"char":"\ud83c\uddf3\ud83c\uddfa",fitzpatrick_scale:!1,category:"flags"},norfolk_island:{keywords:["norfolk","island","flag","nation","country","banner"],"char":"\ud83c\uddf3\ud83c\uddeb",fitzpatrick_scale:!1,category:"flags"},northern_mariana_islands:{keywords:["northern","mariana","islands","flag","nation","country","banner"],"char":"\ud83c\uddf2\ud83c\uddf5",fitzpatrick_scale:!1,category:"flags"},north_korea:{keywords:["north","korea","nation","flag","country","banner"],"char":"\ud83c\uddf0\ud83c\uddf5",fitzpatrick_scale:!1,category:"flags"},norway:{keywords:["no","flag","nation","country","banner"],"char":"\ud83c\uddf3\ud83c\uddf4",fitzpatrick_scale:!1,category:"flags"},oman:{keywords:["om_symbol","flag","nation","country","banner"],"char":"\ud83c\uddf4\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},pakistan:{keywords:["pk","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\uddf0",fitzpatrick_scale:!1,category:"flags"},palau:{keywords:["pw","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\uddfc",fitzpatrick_scale:!1,category:"flags"},palestinian_territories:{keywords:["palestine","palestinian","territories","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\uddf8",fitzpatrick_scale:!1,category:"flags"},panama:{keywords:["pa","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\udde6",fitzpatrick_scale:!1,category:"flags"},papua_new_guinea:{keywords:["papua","new","guinea","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},paraguay:{keywords:["py","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\uddfe",fitzpatrick_scale:!1,category:"flags"},peru:{keywords:["pe","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},philippines:{keywords:["ph","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\udded",fitzpatrick_scale:!1,category:"flags"},pitcairn_islands:{keywords:["pitcairn","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\uddf3",fitzpatrick_scale:!1,category:"flags"},poland:{keywords:["pl","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\uddf1",fitzpatrick_scale:!1,category:"flags"},portugal:{keywords:["pt","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\uddf9",fitzpatrick_scale:!1,category:"flags"},puerto_rico:{keywords:["puerto","rico","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},qatar:{keywords:["qa","flag","nation","country","banner"],"char":"\ud83c\uddf6\ud83c\udde6",fitzpatrick_scale:!1,category:"flags"},reunion:{keywords:["r\xe9union","flag","nation","country","banner"],"char":"\ud83c\uddf7\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},romania:{keywords:["ro","flag","nation","country","banner"],"char":"\ud83c\uddf7\ud83c\uddf4",fitzpatrick_scale:!1,category:"flags"},ru:{keywords:["russian","federation","flag","nation","country","banner"],"char":"\ud83c\uddf7\ud83c\uddfa",fitzpatrick_scale:!1,category:"flags"},rwanda:{keywords:["rw","flag","nation","country","banner"],"char":"\ud83c\uddf7\ud83c\uddfc",fitzpatrick_scale:!1,category:"flags"},st_barthelemy:{keywords:["saint","barth\xe9lemy","flag","nation","country","banner"],"char":"\ud83c\udde7\ud83c\uddf1",fitzpatrick_scale:!1,category:"flags"},st_helena:{keywords:["saint","helena","ascension","tristan","cunha","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\udded",fitzpatrick_scale:!1,category:"flags"},st_kitts_nevis:{keywords:["saint","kitts","nevis","flag","nation","country","banner"],"char":"\ud83c\uddf0\ud83c\uddf3",fitzpatrick_scale:!1,category:"flags"},st_lucia:{keywords:["saint","lucia","flag","nation","country","banner"],"char":"\ud83c\uddf1\ud83c\udde8",fitzpatrick_scale:!1,category:"flags"},st_pierre_miquelon:{keywords:["saint","pierre","miquelon","flag","nation","country","banner"],"char":"\ud83c\uddf5\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},st_vincent_grenadines:{keywords:["saint","vincent","grenadines","flag","nation","country","banner"],"char":"\ud83c\uddfb\ud83c\udde8",fitzpatrick_scale:!1,category:"flags"},samoa:{keywords:["ws","flag","nation","country","banner"],"char":"\ud83c\uddfc\ud83c\uddf8",fitzpatrick_scale:!1,category:"flags"},san_marino:{keywords:["san","marino","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},sao_tome_principe:{keywords:["sao","tome","principe","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddf9",fitzpatrick_scale:!1,category:"flags"},saudi_arabia:{keywords:["flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\udde6",fitzpatrick_scale:!1,category:"flags"},senegal:{keywords:["sn","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddf3",fitzpatrick_scale:!1,category:"flags"},serbia:{keywords:["rs","flag","nation","country","banner"],"char":"\ud83c\uddf7\ud83c\uddf8",fitzpatrick_scale:!1,category:"flags"},seychelles:{keywords:["sc","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\udde8",fitzpatrick_scale:!1,category:"flags"},sierra_leone:{keywords:["sierra","leone","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddf1",fitzpatrick_scale:!1,category:"flags"},singapore:{keywords:["sg","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},sint_maarten:{keywords:["sint","maarten","dutch","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddfd",fitzpatrick_scale:!1,category:"flags"},slovakia:{keywords:["sk","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddf0",fitzpatrick_scale:!1,category:"flags"},slovenia:{keywords:["si","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddee",fitzpatrick_scale:!1,category:"flags"},solomon_islands:{keywords:["solomon","islands","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\udde7",fitzpatrick_scale:!1,category:"flags"},somalia:{keywords:["so","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddf4",fitzpatrick_scale:!1,category:"flags"},south_africa:{keywords:["south","africa","flag","nation","country","banner"],"char":"\ud83c\uddff\ud83c\udde6",fitzpatrick_scale:!1,category:"flags"},south_georgia_south_sandwich_islands:{keywords:["south","georgia","sandwich","islands","flag","nation","country","banner"],"char":"\ud83c\uddec\ud83c\uddf8",fitzpatrick_scale:!1,category:"flags"},kr:{keywords:["south","korea","nation","flag","country","banner"],"char":"\ud83c\uddf0\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},south_sudan:{keywords:["south","sd","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddf8",fitzpatrick_scale:!1,category:"flags"},es:{keywords:["spain","flag","nation","country","banner"],"char":"\ud83c\uddea\ud83c\uddf8",fitzpatrick_scale:!1,category:"flags"},sri_lanka:{keywords:["sri","lanka","flag","nation","country","banner"],"char":"\ud83c\uddf1\ud83c\uddf0",fitzpatrick_scale:!1,category:"flags"},sudan:{keywords:["sd","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\udde9",fitzpatrick_scale:!1,category:"flags"},suriname:{keywords:["sr","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},swaziland:{keywords:["sz","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddff",fitzpatrick_scale:!1,category:"flags"},sweden:{keywords:["se","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},switzerland:{keywords:["ch","flag","nation","country","banner"],"char":"\ud83c\udde8\ud83c\udded",fitzpatrick_scale:!1,category:"flags"},syria:{keywords:["syrian","arab","republic","flag","nation","country","banner"],"char":"\ud83c\uddf8\ud83c\uddfe",fitzpatrick_scale:!1,category:"flags"},taiwan:{keywords:["tw","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddfc",fitzpatrick_scale:!1,category:"flags"},tajikistan:{keywords:["tj","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddef",fitzpatrick_scale:!1,category:"flags"},tanzania:{keywords:["tanzania,","united","republic","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddff",fitzpatrick_scale:!1,category:"flags"},thailand:{keywords:["th","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\udded",fitzpatrick_scale:!1,category:"flags"},timor_leste:{keywords:["timor","leste","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddf1",fitzpatrick_scale:!1,category:"flags"},togo:{keywords:["tg","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},tokelau:{keywords:["tk","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddf0",fitzpatrick_scale:!1,category:"flags"},tonga:{keywords:["to","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddf4",fitzpatrick_scale:!1,category:"flags"},trinidad_tobago:{keywords:["trinidad","tobago","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddf9",fitzpatrick_scale:!1,category:"flags"},tunisia:{keywords:["tn","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddf3",fitzpatrick_scale:!1,category:"flags"},tr:{keywords:["turkey","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddf7",fitzpatrick_scale:!1,category:"flags"},turkmenistan:{keywords:["flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},turks_caicos_islands:{keywords:["turks","caicos","islands","flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\udde8",fitzpatrick_scale:!1,category:"flags"},tuvalu:{keywords:["flag","nation","country","banner"],"char":"\ud83c\uddf9\ud83c\uddfb",fitzpatrick_scale:!1,category:"flags"},uganda:{keywords:["ug","flag","nation","country","banner"],"char":"\ud83c\uddfa\ud83c\uddec",fitzpatrick_scale:!1,category:"flags"},ukraine:{keywords:["ua","flag","nation","country","banner"],"char":"\ud83c\uddfa\ud83c\udde6",fitzpatrick_scale:!1,category:"flags"},united_arab_emirates:{keywords:["united","arab","emirates","flag","nation","country","banner"],"char":"\ud83c\udde6\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},uk:{keywords:["united","kingdom","great","britain","northern","ireland","flag","nation","country","banner","british","UK","english","england","union jack"],"char":"\ud83c\uddec\ud83c\udde7",fitzpatrick_scale:!1,category:"flags"},england:{keywords:["flag","english"],"char":"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f",fitzpatrick_scale:!1,category:"flags"},scotland:{keywords:["flag","scottish"],"char":"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f",fitzpatrick_scale:!1,category:"flags"},wales:{keywords:["flag","welsh"],"char":"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f",fitzpatrick_scale:!1,category:"flags"},us:{keywords:["united","states","america","flag","nation","country","banner"],"char":"\ud83c\uddfa\ud83c\uddf8",fitzpatrick_scale:!1,category:"flags"},us_virgin_islands:{keywords:["virgin","islands","us","flag","nation","country","banner"],"char":"\ud83c\uddfb\ud83c\uddee",fitzpatrick_scale:!1,category:"flags"},uruguay:{keywords:["uy","flag","nation","country","banner"],"char":"\ud83c\uddfa\ud83c\uddfe",fitzpatrick_scale:!1,category:"flags"},uzbekistan:{keywords:["uz","flag","nation","country","banner"],"char":"\ud83c\uddfa\ud83c\uddff",fitzpatrick_scale:!1,category:"flags"},vanuatu:{keywords:["vu","flag","nation","country","banner"],"char":"\ud83c\uddfb\ud83c\uddfa",fitzpatrick_scale:!1,category:"flags"},vatican_city:{keywords:["vatican","city","flag","nation","country","banner"],"char":"\ud83c\uddfb\ud83c\udde6",fitzpatrick_scale:!1,category:"flags"},venezuela:{keywords:["ve","bolivarian","republic","flag","nation","country","banner"],"char":"\ud83c\uddfb\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},vietnam:{keywords:["viet","nam","flag","nation","country","banner"],"char":"\ud83c\uddfb\ud83c\uddf3",fitzpatrick_scale:!1,category:"flags"},wallis_futuna:{keywords:["wallis","futuna","flag","nation","country","banner"],"char":"\ud83c\uddfc\ud83c\uddeb",fitzpatrick_scale:!1,category:"flags"},western_sahara:{keywords:["western","sahara","flag","nation","country","banner"],"char":"\ud83c\uddea\ud83c\udded",fitzpatrick_scale:!1,category:"flags"},yemen:{keywords:["ye","flag","nation","country","banner"],"char":"\ud83c\uddfe\ud83c\uddea",fitzpatrick_scale:!1,category:"flags"},zambia:{keywords:["zm","flag","nation","country","banner"],"char":"\ud83c\uddff\ud83c\uddf2",fitzpatrick_scale:!1,category:"flags"},zimbabwe:{keywords:["zw","flag","nation","country","banner"],"char":"\ud83c\uddff\ud83c\uddfc",fitzpatrick_scale:!1,category:"flags"},united_nations:{keywords:["un","flag","banner"],"char":"\ud83c\uddfa\ud83c\uddf3",fitzpatrick_scale:!1,category:"flags"},pirate_flag:{keywords:["skull","crossbones","flag","banner"],"char":"\ud83c\udff4\u200d\u2620\ufe0f",fitzpatrick_scale:!1,category:"flags"}}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..e939611e2eb8f80c0244498e8c0ee911f71c24c5 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/plugin.js @@ -0,0 +1,605 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var DEFAULT_ID = 'tinymce.plugins.emoticons'; + var getEmoticonDatabase = function (editor) { + return editor.getParam('emoticons_database', 'emojis', 'string'); + }; + var getEmoticonDatabaseUrl = function (editor, pluginUrl) { + var database = getEmoticonDatabase(editor); + return editor.getParam('emoticons_database_url', pluginUrl + '/js/' + database + editor.suffix + '.js', 'string'); + }; + var getEmoticonDatabaseId = function (editor) { + return editor.getParam('emoticons_database_id', DEFAULT_ID, 'string'); + }; + var getAppendedEmoticons = function (editor) { + return editor.getParam('emoticons_append', {}, 'object'); + }; + var getEmotionsImageUrl = function (editor) { + return editor.getParam('emoticons_images_url', 'https://twemoji.maxcdn.com/v/13.0.1/72x72/', 'string'); + }; + + var __assign = function () { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + var Cell = function (initial) { + var value = initial; + var get = function () { + return value; + }; + var set = function (v) { + value = v; + }; + return { + get: get, + set: set + }; + }; + + var hasOwnProperty = Object.prototype.hasOwnProperty; + var shallow = function (old, nu) { + return nu; + }; + var baseMerge = function (merger) { + return function () { + var objects = new Array(arguments.length); + for (var i = 0; i < objects.length; i++) { + objects[i] = arguments[i]; + } + if (objects.length === 0) { + throw new Error('Can\'t merge zero objects'); + } + var ret = {}; + for (var j = 0; j < objects.length; j++) { + var curObject = objects[j]; + for (var key in curObject) { + if (hasOwnProperty.call(curObject, key)) { + ret[key] = merger(ret[key], curObject[key]); + } + } + } + return ret; + }; + }; + var merge = baseMerge(shallow); + + var noop = function () { + }; + var constant = function (value) { + return function () { + return value; + }; + }; + var never = constant(false); + var always = constant(true); + + var none = function () { + return NONE; + }; + var NONE = function () { + var eq = function (o) { + return o.isNone(); + }; + var call = function (thunk) { + return thunk(); + }; + var id = function (n) { + return n; + }; + var me = { + fold: function (n, _s) { + return n(); + }, + is: never, + isSome: never, + isNone: always, + getOr: id, + getOrThunk: call, + getOrDie: function (msg) { + throw new Error(msg || 'error: getOrDie called on none.'); + }, + getOrNull: constant(null), + getOrUndefined: constant(undefined), + or: id, + orThunk: call, + map: none, + each: noop, + bind: none, + exists: never, + forall: always, + filter: none, + equals: eq, + equals_: eq, + toArray: function () { + return []; + }, + toString: constant('none()') + }; + return me; + }(); + var some = function (a) { + var constant_a = constant(a); + var self = function () { + return me; + }; + var bind = function (f) { + return f(a); + }; + var me = { + fold: function (n, s) { + return s(a); + }, + is: function (v) { + return a === v; + }, + isSome: always, + isNone: never, + getOr: constant_a, + getOrThunk: constant_a, + getOrDie: constant_a, + getOrNull: constant_a, + getOrUndefined: constant_a, + or: self, + orThunk: self, + map: function (f) { + return some(f(a)); + }, + each: function (f) { + f(a); + }, + bind: bind, + exists: bind, + forall: bind, + filter: function (f) { + return f(a) ? me : NONE; + }, + toArray: function () { + return [a]; + }, + toString: function () { + return 'some(' + a + ')'; + }, + equals: function (o) { + return o.is(a); + }, + equals_: function (o, elementEq) { + return o.fold(never, function (b) { + return elementEq(a, b); + }); + } + }; + return me; + }; + var from = function (value) { + return value === null || value === undefined ? NONE : some(value); + }; + var Optional = { + some: some, + none: none, + from: from + }; + + var keys = Object.keys; + var hasOwnProperty$1 = Object.hasOwnProperty; + var each = function (obj, f) { + var props = keys(obj); + for (var k = 0, len = props.length; k < len; k++) { + var i = props[k]; + var x = obj[i]; + f(x, i); + } + }; + var map = function (obj, f) { + return tupleMap(obj, function (x, i) { + return { + k: i, + v: f(x, i) + }; + }); + }; + var tupleMap = function (obj, f) { + var r = {}; + each(obj, function (x, i) { + var tuple = f(x, i); + r[tuple.k] = tuple.v; + }); + return r; + }; + var has = function (obj, key) { + return hasOwnProperty$1.call(obj, key); + }; + + var checkRange = function (str, substr, start) { + return substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr; + }; + var contains = function (str, substr) { + return str.indexOf(substr) !== -1; + }; + var startsWith = function (str, prefix) { + return checkRange(str, prefix, 0); + }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.Resource'); + + var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay'); + + var global$3 = tinymce.util.Tools.resolve('tinymce.util.Promise'); + + var ALL_CATEGORY = 'All'; + var categoryNameMap = { + symbols: 'Symbols', + people: 'People', + animals_and_nature: 'Animals and Nature', + food_and_drink: 'Food and Drink', + activity: 'Activity', + travel_and_places: 'Travel and Places', + objects: 'Objects', + flags: 'Flags', + user: 'User Defined' + }; + var translateCategory = function (categories, name) { + return has(categories, name) ? categories[name] : name; + }; + var getUserDefinedEmoticons = function (editor) { + var userDefinedEmoticons = getAppendedEmoticons(editor); + return map(userDefinedEmoticons, function (value) { + return __assign({ + keywords: [], + category: 'user' + }, value); + }); + }; + var initDatabase = function (editor, databaseUrl, databaseId) { + var categories = Cell(Optional.none()); + var all = Cell(Optional.none()); + var emojiImagesUrl = getEmotionsImageUrl(editor); + var getEmoji = function (lib) { + if (startsWith(lib.char, '= max; + }; + }); + for (var i = 0; i < list.length; i++) { + if (pattern.length === 0 || emojiMatches(list[i], lowerCasePattern)) { + matches.push({ + value: list[i].char, + text: list[i].title, + icon: list[i].char + }); + if (reachedLimit(matches.length)) { + break; + } + } + } + return matches; + }; + + var init = function (editor, database) { + editor.ui.registry.addAutocompleter('emoticons', { + ch: ':', + columns: 'auto', + minChars: 2, + fetch: function (pattern, maxResults) { + return database.waitForLoad().then(function () { + var candidates = database.listAll(); + return emojisFrom(candidates, pattern, Optional.some(maxResults)); + }); + }, + onAction: function (autocompleteApi, rng, value) { + editor.selection.setRng(rng); + editor.insertContent(value); + autocompleteApi.hide(); + } + }); + }; + + var last = function (fn, rate) { + var timer = null; + var cancel = function () { + if (timer !== null) { + clearTimeout(timer); + timer = null; + } + }; + var throttle = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + if (timer !== null) { + clearTimeout(timer); + } + timer = setTimeout(function () { + fn.apply(null, args); + timer = null; + }, rate); + }; + return { + cancel: cancel, + throttle: throttle + }; + }; + + var insertEmoticon = function (editor, ch) { + editor.insertContent(ch); + }; + + var patternName = 'pattern'; + var open = function (editor, database) { + var initialState = { + pattern: '', + results: emojisFrom(database.listAll(), '', Optional.some(300)) + }; + var currentTab = Cell(ALL_CATEGORY); + var scan = function (dialogApi) { + var dialogData = dialogApi.getData(); + var category = currentTab.get(); + var candidates = database.listCategory(category); + var results = emojisFrom(candidates, dialogData[patternName], category === ALL_CATEGORY ? Optional.some(300) : Optional.none()); + dialogApi.setData({ results: results }); + }; + var updateFilter = last(function (dialogApi) { + scan(dialogApi); + }, 200); + var searchField = { + label: 'Search', + type: 'input', + name: patternName + }; + var resultsField = { + type: 'collection', + name: 'results' + }; + var getInitialState = function () { + var body = { + type: 'tabpanel', + tabs: map$1(database.listCategories(), function (cat) { + return { + title: cat, + name: cat, + items: [ + searchField, + resultsField + ] + }; + }) + }; + return { + title: 'Emoticons', + size: 'normal', + body: body, + initialData: initialState, + onTabChange: function (dialogApi, details) { + currentTab.set(details.newTabName); + updateFilter.throttle(dialogApi); + }, + onChange: updateFilter.throttle, + onAction: function (dialogApi, actionData) { + if (actionData.name === 'results') { + insertEmoticon(editor, actionData.value); + dialogApi.close(); + } + }, + buttons: [{ + type: 'cancel', + text: 'Close', + primary: true + }] + }; + }; + var dialogApi = editor.windowManager.open(getInitialState()); + dialogApi.focus(patternName); + if (!database.hasLoaded()) { + dialogApi.block('Loading emoticons...'); + database.waitForLoad().then(function () { + dialogApi.redial(getInitialState()); + updateFilter.throttle(dialogApi); + dialogApi.focus(patternName); + dialogApi.unblock(); + }).catch(function (_err) { + dialogApi.redial({ + title: 'Emoticons', + body: { + type: 'panel', + items: [{ + type: 'alertbanner', + level: 'error', + icon: 'warning', + text: '

                                                                                          Could not load emoticons

                                                                                          ' + }] + }, + buttons: [{ + type: 'cancel', + text: 'Close', + primary: true + }], + initialData: { + pattern: '', + results: [] + } + }); + dialogApi.focus(patternName); + dialogApi.unblock(); + }); + } + }; + + var register = function (editor, database) { + var onAction = function () { + return open(editor, database); + }; + editor.ui.registry.addButton('emoticons', { + tooltip: 'Emoticons', + icon: 'emoji', + onAction: onAction + }); + editor.ui.registry.addMenuItem('emoticons', { + text: 'Emoticons...', + icon: 'emoji', + onAction: onAction + }); + }; + + function Plugin () { + global.add('emoticons', function (editor, pluginUrl) { + var databaseUrl = getEmoticonDatabaseUrl(editor, pluginUrl); + var databaseId = getEmoticonDatabaseId(editor); + var database = initDatabase(editor, databaseUrl, databaseId); + register(editor, database); + init(editor, database); + setup(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..250d78655840f3c41d07243eed6ca3514c17a54b --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/emoticons/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var u,t,n,e,r=tinymce.util.Tools.resolve("tinymce.PluginManager"),o=function(){return(o=Object.assign||function(t){for(var n,e=1,r=arguments.length;e=i.length&&o.substr(u,u+i.length)===i?e["char"].replace(/src="([^"]+)"/,function(t,n){return'src="'+f+n+'"'}):e["char"]),category:_(A,t.category)},c=l[a.category]!==undefined?l[a.category]:[];l[a.category]=c.concat([a]),s.push(a)}),r.set(h.some(l)),n.set(h.some(s))};e.on("init",function(){O.load(t,o).then(function(t){var n=T(e);i(c(t,n))},function(t){console.log("Failed to load emoticons: "+t),r.set(h.some({})),n.set(h.some([]))})});var u=function(){return n.get().getOr([])},a=function(){return r.get().isSome()&&n.get().isSome()};return{listCategories:function(){return[k].concat(y(r.get().getOr({})))},hasLoaded:a,waitForLoad:function(){return a()?j.resolve(!0):new j(function(t,n){var e=15,r=C.setInterval(function(){a()?(C.clearInterval(r),t(!0)):--e<0&&(console.log("Could not load emojis from url: "+o),C.clearInterval(r),n(!1))},100)})},listAll:u,listCategory:function(n){return n===k?u():r.get().bind(function(t){return h.from(t[n])}).getOr([])}}},x=function(t,n,e){for(var r=[],o=n.toLowerCase(),i=e.fold(function(){return l},function(n){return function(t){return n<=t}}),u=0;uCould not load emoticons

                                                                                          "}]},buttons:[{type:"cancel",text:"Close",primary:!0}],initialData:{pattern:"",results:[]}}),f.focus(D),f.unblock()}))};r.add("emoticons",function(t,n){var e,r,o,i,u,a,c,l,s,f=(r=n,o=(e=t).getParam("emoticons_database","emojis","string"),e.getParam("emoticons_database_url",r+"/js/"+o+e.suffix+".js","string")),m=t.getParam("emoticons_database_id","tinymce.plugins.emoticons","string"),g=P(t,f,m);u=g,a=function(){return L(i,u)},(i=t).ui.registry.addButton("emoticons",{tooltip:"Emoticons",icon:"emoji",onAction:a}),i.ui.registry.addMenuItem("emoticons",{text:"Emoticons...",icon:"emoji",onAction:a}),l=g,(c=t).ui.registry.addAutocompleter("emoticons",{ch:":",columns:"auto",minChars:2,fetch:function(n,e){return l.waitForLoad().then(function(){var t=l.listAll();return x(t,n,h.some(e))})},onAction:function(t,n,e){c.selection.setRng(n),c.insertContent(e),t.hide()}}),(s=t).on("PreInit",function(){s.parser.addAttributeFilter("data-emoticon",function(t){!function(t,n){for(var e=0,r=t.length;e'); + }; + var getProtect = function (editor) { + return editor.getParam('protect'); + }; + + var parseHeader = function (head) { + return global$2({ + validate: false, + root_name: '#document' + }).parse(head, { format: 'xhtml' }); + }; + var htmlToData = function (editor, head) { + var headerFragment = parseHeader(head); + var data = {}; + var elm, matches; + function getAttr(elm, name) { + var value = elm.attr(name); + return value || ''; + } + data.fontface = getDefaultFontFamily(editor); + data.fontsize = getDefaultFontSize(editor); + elm = headerFragment.firstChild; + if (elm.type === 7) { + data.xml_pi = true; + matches = /encoding="([^"]+)"/.exec(elm.value); + if (matches) { + data.docencoding = matches[1]; + } + } + elm = headerFragment.getAll('#doctype')[0]; + if (elm) { + data.doctype = ''; + } + elm = headerFragment.getAll('title')[0]; + if (elm && elm.firstChild) { + data.title = elm.firstChild.value; + } + global$1.each(headerFragment.getAll('meta'), function (meta) { + var name = meta.attr('name'); + var httpEquiv = meta.attr('http-equiv'); + var matches; + if (name) { + data[name.toLowerCase()] = meta.attr('content'); + } else if (httpEquiv === 'Content-Type') { + matches = /charset\s*=\s*(.*)\s*/gi.exec(meta.attr('content')); + if (matches) { + data.docencoding = matches[1]; + } + } + }); + elm = headerFragment.getAll('html')[0]; + if (elm) { + data.langcode = getAttr(elm, 'lang') || getAttr(elm, 'xml:lang'); + } + data.stylesheets = []; + global$1.each(headerFragment.getAll('link'), function (link) { + if (link.attr('rel') === 'stylesheet') { + data.stylesheets.push(link.attr('href')); + } + }); + elm = headerFragment.getAll('body')[0]; + if (elm) { + data.langdir = getAttr(elm, 'dir'); + data.style = getAttr(elm, 'style'); + data.visited_color = getAttr(elm, 'vlink'); + data.link_color = getAttr(elm, 'link'); + data.active_color = getAttr(elm, 'alink'); + } + return data; + }; + var dataToHtml = function (editor, data, head) { + var headElement, elm, value; + var dom = editor.dom; + function setAttr(elm, name, value) { + elm.attr(name, value ? value : undefined); + } + function addHeadNode(node) { + if (headElement.firstChild) { + headElement.insert(node, headElement.firstChild); + } else { + headElement.append(node); + } + } + var headerFragment = parseHeader(head); + headElement = headerFragment.getAll('head')[0]; + if (!headElement) { + elm = headerFragment.getAll('html')[0]; + headElement = new global$3('head', 1); + if (elm.firstChild) { + elm.insert(headElement, elm.firstChild, true); + } else { + elm.append(headElement); + } + } + elm = headerFragment.firstChild; + if (data.xml_pi) { + value = 'version="1.0"'; + if (data.docencoding) { + value += ' encoding="' + data.docencoding + '"'; + } + if (elm.type !== 7) { + elm = new global$3('xml', 7); + headerFragment.insert(elm, headerFragment.firstChild, true); + } + elm.value = value; + } else if (elm && elm.type === 7) { + elm.remove(); + } + elm = headerFragment.getAll('#doctype')[0]; + if (data.doctype) { + if (!elm) { + elm = new global$3('#doctype', 10); + if (data.xml_pi) { + headerFragment.insert(elm, headerFragment.firstChild); + } else { + addHeadNode(elm); + } + } + elm.value = data.doctype.substring(9, data.doctype.length - 1); + } else if (elm) { + elm.remove(); + } + elm = null; + global$1.each(headerFragment.getAll('meta'), function (meta) { + if (meta.attr('http-equiv') === 'Content-Type') { + elm = meta; + } + }); + if (data.docencoding) { + if (!elm) { + elm = new global$3('meta', 1); + elm.attr('http-equiv', 'Content-Type'); + elm.shortEnded = true; + addHeadNode(elm); + } + elm.attr('content', 'text/html; charset=' + data.docencoding); + } else if (elm) { + elm.remove(); + } + elm = headerFragment.getAll('title')[0]; + if (data.title) { + if (!elm) { + elm = new global$3('title', 1); + addHeadNode(elm); + } else { + elm.empty(); + } + elm.append(new global$3('#text', 3)).value = data.title; + } else if (elm) { + elm.remove(); + } + global$1.each('keywords,description,author,copyright,robots'.split(','), function (name) { + var nodes = headerFragment.getAll('meta'); + var i, meta; + var value = data[name]; + for (i = 0; i < nodes.length; i++) { + meta = nodes[i]; + if (meta.attr('name') === name) { + if (value) { + meta.attr('content', value); + } else { + meta.remove(); + } + return; + } + } + if (value) { + elm = new global$3('meta', 1); + elm.attr('name', name); + elm.attr('content', value); + elm.shortEnded = true; + addHeadNode(elm); + } + }); + var currentStyleSheetsMap = {}; + global$1.each(headerFragment.getAll('link'), function (stylesheet) { + if (stylesheet.attr('rel') === 'stylesheet') { + currentStyleSheetsMap[stylesheet.attr('href')] = stylesheet; + } + }); + global$1.each(data.stylesheets, function (stylesheet) { + if (!currentStyleSheetsMap[stylesheet]) { + elm = new global$3('link', 1); + elm.attr({ + rel: 'stylesheet', + text: 'text/css', + href: stylesheet + }); + elm.shortEnded = true; + addHeadNode(elm); + } + delete currentStyleSheetsMap[stylesheet]; + }); + global$1.each(currentStyleSheetsMap, function (stylesheet) { + stylesheet.remove(); + }); + elm = headerFragment.getAll('body')[0]; + if (elm) { + setAttr(elm, 'dir', data.langdir); + setAttr(elm, 'style', data.style); + setAttr(elm, 'vlink', data.visited_color); + setAttr(elm, 'link', data.link_color); + setAttr(elm, 'alink', data.active_color); + dom.setAttribs(editor.getBody(), { + style: data.style, + dir: data.dir, + vLink: data.visited_color, + link: data.link_color, + aLink: data.active_color + }); + } + elm = headerFragment.getAll('html')[0]; + if (elm) { + setAttr(elm, 'lang', data.langcode); + setAttr(elm, 'xml:lang', data.langcode); + } + if (!headElement.firstChild) { + headElement.remove(); + } + var html = global$4({ + validate: false, + indent: true, + indent_before: 'head,html,body,meta,title,script,link,style', + indent_after: 'head,html,body,meta,title,script,link,style' + }).serialize(headerFragment); + return html.substring(0, html.indexOf('')); + }; + + var open = function (editor, headState) { + var data = htmlToData(editor, headState.get()); + var defaultData = { + title: '', + keywords: '', + description: '', + robots: '', + author: '', + docencoding: '' + }; + var initialData = __assign(__assign({}, defaultData), data); + editor.windowManager.open({ + title: 'Metadata and Document Properties', + size: 'normal', + body: { + type: 'panel', + items: [ + { + name: 'title', + type: 'input', + label: 'Title' + }, + { + name: 'keywords', + type: 'input', + label: 'Keywords' + }, + { + name: 'description', + type: 'input', + label: 'Description' + }, + { + name: 'robots', + type: 'input', + label: 'Robots' + }, + { + name: 'author', + type: 'input', + label: 'Author' + }, + { + name: 'docencoding', + type: 'input', + label: 'Encoding' + } + ] + }, + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true + } + ], + initialData: initialData, + onSubmit: function (api) { + var nuData = api.getData(); + var headHtml = dataToHtml(editor, global$1.extend(data, nuData), headState.get()); + headState.set(headHtml); + api.close(); + } + }); + }; + + var register = function (editor, headState) { + editor.addCommand('mceFullPageProperties', function () { + open(editor, headState); + }); + }; + + var protectHtml = function (protect, html) { + global$1.each(protect, function (pattern) { + html = html.replace(pattern, function (str) { + return ''; + }); + }); + return html; + }; + var unprotectHtml = function (html) { + return html.replace(//g, function (a, m) { + return unescape(m); + }); + }; + + var each = global$1.each; + var low = function (s) { + return s.replace(/<\/?[A-Z]+/g, function (a) { + return a.toLowerCase(); + }); + }; + var handleSetContent = function (editor, headState, footState, evt) { + var startPos, endPos, content, styles = ''; + var dom = editor.dom; + if (evt.selection) { + return; + } + content = protectHtml(getProtect(editor), evt.content); + if (evt.format === 'raw' && headState.get()) { + return; + } + if (evt.source_view && shouldHideInSourceView(editor)) { + return; + } + if (content.length === 0 && !evt.source_view) { + content = global$1.trim(headState.get()) + '\n' + global$1.trim(content) + '\n' + global$1.trim(footState.get()); + } + content = content.replace(/<(\/?)BODY/gi, '<$1body'); + startPos = content.indexOf('', startPos); + headState.set(low(content.substring(0, startPos + 1))); + endPos = content.indexOf('\n'); + } + var headerFragment = parseHeader(headState.get()); + each(headerFragment.getAll('style'), function (node) { + if (node.firstChild) { + styles += node.firstChild.value; + } + }); + var bodyElm = headerFragment.getAll('body')[0]; + if (bodyElm) { + dom.setAttribs(editor.getBody(), { + style: bodyElm.attr('style') || '', + dir: bodyElm.attr('dir') || '', + vLink: bodyElm.attr('vlink') || '', + link: bodyElm.attr('link') || '', + aLink: bodyElm.attr('alink') || '' + }); + } + dom.remove('fullpage_styles'); + var headElm = editor.getDoc().getElementsByTagName('head')[0]; + if (styles) { + var styleElm = dom.add(headElm, 'style', { id: 'fullpage_styles' }); + styleElm.appendChild(document.createTextNode(styles)); + } + var currentStyleSheetsMap = {}; + global$1.each(headElm.getElementsByTagName('link'), function (stylesheet) { + if (stylesheet.rel === 'stylesheet' && stylesheet.getAttribute('data-mce-fullpage')) { + currentStyleSheetsMap[stylesheet.href] = stylesheet; + } + }); + global$1.each(headerFragment.getAll('link'), function (stylesheet) { + var href = stylesheet.attr('href'); + if (!href) { + return true; + } + if (!currentStyleSheetsMap[href] && stylesheet.attr('rel') === 'stylesheet') { + dom.add(headElm, 'link', { + 'rel': 'stylesheet', + 'text': 'text/css', + href: href, + 'data-mce-fullpage': '1' + }); + } + delete currentStyleSheetsMap[href]; + }); + global$1.each(currentStyleSheetsMap, function (stylesheet) { + stylesheet.parentNode.removeChild(stylesheet); + }); + }; + var getDefaultHeader = function (editor) { + var header = '', value, styles = ''; + if (getDefaultXmlPi(editor)) { + var piEncoding = getDefaultEncoding(editor); + header += '\n'; + } + header += getDefaultDocType(editor); + header += '\n\n\n'; + if (value = getDefaultTitle(editor)) { + header += '' + value + '\n'; + } + if (value = getDefaultEncoding(editor)) { + header += '\n'; + } + if (value = getDefaultFontFamily(editor)) { + styles += 'font-family: ' + value + ';'; + } + if (value = getDefaultFontSize(editor)) { + styles += 'font-size: ' + value + ';'; + } + if (value = getDefaultTextColor(editor)) { + styles += 'color: ' + value + ';'; + } + header += '\n\n'; + return header; + }; + var handleGetContent = function (editor, head, foot, evt) { + if (evt.format === 'html' && !evt.selection && (!evt.source_view || !shouldHideInSourceView(editor))) { + evt.content = unprotectHtml(global$1.trim(head) + '\n' + global$1.trim(evt.content) + '\n' + global$1.trim(foot)); + } + }; + var setup = function (editor, headState, footState) { + editor.on('BeforeSetContent', function (evt) { + handleSetContent(editor, headState, footState, evt); + }); + editor.on('GetContent', function (evt) { + handleGetContent(editor, headState.get(), footState.get(), evt); + }); + }; + + var register$1 = function (editor) { + editor.ui.registry.addButton('fullpage', { + tooltip: 'Metadata and document properties', + icon: 'document-properties', + onAction: function () { + editor.execCommand('mceFullPageProperties'); + } + }); + editor.ui.registry.addMenuItem('fullpage', { + text: 'Metadata and document properties', + icon: 'document-properties', + onAction: function () { + editor.execCommand('mceFullPageProperties'); + } + }); + }; + + function Plugin () { + global.add('fullpage', function (editor) { + var headState = Cell(''), footState = Cell(''); + register(editor, headState); + register$1(editor); + setup(editor, headState, footState); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/fullpage/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/fullpage/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..2592f73cf86618453a95b62b7d29e38d2ebbfb02 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/fullpage/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var s=function(e){var t=e;return{get:function(){return t},set:function(e){t=e}}},e=tinymce.util.Tools.resolve("tinymce.PluginManager"),u=function(){return(u=Object.assign||function(e){for(var t,n=1,l=arguments.length;n"),(n=r.getAll("title")[0])&&n.firstChild&&(a.title=n.firstChild.value),p.each(r.getAll("meta"),function(e){var t,n=e.attr("name"),l=e.attr("http-equiv");n?a[n.toLowerCase()]=e.attr("content"):"Content-Type"===l&&(t=/charset\s*=\s*(.*)\s*/gi.exec(e.attr("content")))&&(a.docencoding=t[1])}),(n=r.getAll("html")[0])&&(a.langcode=s(n,"lang")||s(n,"xml:lang")),a.stylesheets=[],p.each(r.getAll("link"),function(e){"stylesheet"===e.attr("rel")&&a.stylesheets.push(e.attr("href"))}),(n=r.getAll("body")[0])&&(a.langdir=s(n,"dir"),a.style=s(n,"style"),a.visited_color=s(n,"vlink"),a.link_color=s(n,"link"),a.active_color=s(n,"alink")),a);function s(e,t){return e.attr(t)||""}var d=u(u({},{title:"",keywords:"",description:"",robots:"",author:"",docencoding:""}),c);l.windowManager.open({title:"Metadata and Document Properties",size:"normal",body:{type:"panel",items:[{name:"title",type:"input",label:"Title"},{name:"keywords",type:"input",label:"Keywords"},{name:"description",type:"input",label:"Description"},{name:"robots",type:"input",label:"Robots"},{name:"author",type:"input",label:"Author"},{name:"docencoding",type:"input",label:"Encoding"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:d,onSubmit:function(e){var t=e.getData(),n=function(e,o,t){var r,n,l=e.dom;function i(e,t,n){e.attr(t,n||undefined)}function a(e){c.firstChild?c.insert(e,c.firstChild):c.append(e)}var c,s=v(t);(c=s.getAll("head")[0])||(r=s.getAll("html")[0],c=new m("head",1),r.firstChild?r.insert(c,r.firstChild,!0):r.append(c)),r=s.firstChild,o.xml_pi?(n='version="1.0"',o.docencoding&&(n+=' encoding="'+o.docencoding+'"'),7!==r.type&&(r=new m("xml",7),s.insert(r,s.firstChild,!0)),r.value=n):r&&7===r.type&&r.remove(),r=s.getAll("#doctype")[0],o.doctype?(r||(r=new m("#doctype",10),o.xml_pi?s.insert(r,s.firstChild):a(r)),r.value=o.doctype.substring(9,o.doctype.length-1)):r&&r.remove(),r=null,p.each(s.getAll("meta"),function(e){"Content-Type"===e.attr("http-equiv")&&(r=e)}),o.docencoding?(r||((r=new m("meta",1)).attr("http-equiv","Content-Type"),r.shortEnded=!0,a(r)),r.attr("content","text/html; charset="+o.docencoding)):r&&r.remove(),r=s.getAll("title")[0],o.title?(r?r.empty():a(r=new m("title",1)),r.append(new m("#text",3)).value=o.title):r&&r.remove(),p.each("keywords,description,author,copyright,robots".split(","),function(e){for(var t,n=s.getAll("meta"),l=o[e],i=0;i"))}(l,p.extend(c,t),i.get());i.set(n),e.close()}})},_=p.each,b=function(e){return e.replace(/<\/?[A-Z]+/g,function(e){return e.toLowerCase()})},x=function(e,t,n,l){var i,o,r,a,c,s,d,u,m,f="",g=e.dom;l.selection||(a=e.getParam("protect"),c=l.content,p.each(a,function(e){c=c.replace(e,function(e){return"\x3c!--mce:protected "+escape(e)+"--\x3e"})}),r=c,"raw"===l.format&&t.get()||l.source_view&&h(e)||(0!==r.length||l.source_view||(r=p.trim(t.get())+"\n"+p.trim(r)+"\n"+p.trim(n.get())),-1!==(i=(r=r.replace(/<(\/?)BODY/gi,"<$1body")).indexOf("",i),t.set(b(r.substring(0,i+1))),-1===(o=r.indexOf("\n")),s=v(t.get()),_(s.getAll("style"),function(e){e.firstChild&&(f+=e.firstChild.value)}),(d=s.getAll("body")[0])&&g.setAttribs(e.getBody(),{style:d.attr("style")||"",dir:d.attr("dir")||"",vLink:d.attr("vlink")||"",link:d.attr("link")||"",aLink:d.attr("alink")||""}),g.remove("fullpage_styles"),u=e.getDoc().getElementsByTagName("head")[0],f&&g.add(u,"style",{id:"fullpage_styles"}).appendChild(document.createTextNode(f)),m={},p.each(u.getElementsByTagName("link"),function(e){"stylesheet"===e.rel&&e.getAttribute("data-mce-fullpage")&&(m[e.href]=e)}),p.each(s.getAll("link"),function(e){var t=e.attr("href");if(!t)return!0;m[t]||"stylesheet"!==e.attr("rel")||g.add(u,"link",{rel:"stylesheet",text:"text/css",href:t,"data-mce-fullpage":"1"}),delete m[t]}),p.each(m,function(e){e.parentNode.removeChild(e)})))},k=function(e){var t,n="",l="";return e.getParam("fullpage_default_xml_pi")&&(n+='\n'),n+=e.getParam("fullpage_default_doctype",""),n+="\n\n\n",(t=e.getParam("fullpage_default_title"))&&(n+=""+t+"\n"),(t=i(e))&&(n+='\n'),(t=g(e))&&(l+="font-family: "+t+";"),(t=y(e))&&(l+="font-size: "+t+";"),(t=e.getParam("fullpage_default_text_color"))&&(l+="color: "+t+";"),n+="\n\n"},C=function(e,t,n,l){"html"!==l.format||l.selection||l.source_view&&h(e)||(l.content=(p.trim(t)+"\n"+p.trim(l.content)+"\n"+p.trim(n)).replace(//g,function(e,t){return unescape(t)}))};e.add("fullpage",function(e){var t,n,l,i,o,r,a=s(""),c=s("");n=a,(t=e).addCommand("mceFullPageProperties",function(){d(t,n)}),(l=e).ui.registry.addButton("fullpage",{tooltip:"Metadata and document properties",icon:"document-properties",onAction:function(){l.execCommand("mceFullPageProperties")}}),l.ui.registry.addMenuItem("fullpage",{text:"Metadata and document properties",icon:"document-properties",onAction:function(){l.execCommand("mceFullPageProperties")}}),o=a,r=c,(i=e).on("BeforeSetContent",function(e){x(i,o,r,e)}),i.on("GetContent",function(e){C(i,o.get(),r.get(),e)})})}(); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/fullscreen/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/fullscreen/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..deb9dde6471bdbdf50b70f79b2d787acd741ee2f --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/fullscreen/plugin.js @@ -0,0 +1,979 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +(function () { + 'use strict'; + + var Cell = function (initial) { + var value = initial; + var get = function () { + return value; + }; + var set = function (v) { + value = v; + }; + return { + get: get, + set: set + }; + }; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var get = function (fullscreenState) { + return { + isFullscreen: function () { + return fullscreenState.get() !== null; + } + }; + }; + + var noop = function () { + }; + var compose = function (fa, fb) { + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + return fa(fb.apply(null, args)); + }; + }; + var compose1 = function (fbc, fab) { + return function (a) { + return fbc(fab(a)); + }; + }; + var constant = function (value) { + return function () { + return value; + }; + }; + function curry(fn) { + var initialArgs = []; + for (var _i = 1; _i < arguments.length; _i++) { + initialArgs[_i - 1] = arguments[_i]; + } + return function () { + var restArgs = []; + for (var _i = 0; _i < arguments.length; _i++) { + restArgs[_i] = arguments[_i]; + } + var all = initialArgs.concat(restArgs); + return fn.apply(null, all); + }; + } + var never = constant(false); + var always = constant(true); + + var none = function () { + return NONE; + }; + var NONE = function () { + var eq = function (o) { + return o.isNone(); + }; + var call = function (thunk) { + return thunk(); + }; + var id = function (n) { + return n; + }; + var me = { + fold: function (n, _s) { + return n(); + }, + is: never, + isSome: never, + isNone: always, + getOr: id, + getOrThunk: call, + getOrDie: function (msg) { + throw new Error(msg || 'error: getOrDie called on none.'); + }, + getOrNull: constant(null), + getOrUndefined: constant(undefined), + or: id, + orThunk: call, + map: none, + each: noop, + bind: none, + exists: never, + forall: always, + filter: none, + equals: eq, + equals_: eq, + toArray: function () { + return []; + }, + toString: constant('none()') + }; + return me; + }(); + var some = function (a) { + var constant_a = constant(a); + var self = function () { + return me; + }; + var bind = function (f) { + return f(a); + }; + var me = { + fold: function (n, s) { + return s(a); + }, + is: function (v) { + return a === v; + }, + isSome: always, + isNone: never, + getOr: constant_a, + getOrThunk: constant_a, + getOrDie: constant_a, + getOrNull: constant_a, + getOrUndefined: constant_a, + or: self, + orThunk: self, + map: function (f) { + return some(f(a)); + }, + each: function (f) { + f(a); + }, + bind: bind, + exists: bind, + forall: bind, + filter: function (f) { + return f(a) ? me : NONE; + }, + toArray: function () { + return [a]; + }, + toString: function () { + return 'some(' + a + ')'; + }, + equals: function (o) { + return o.is(a); + }, + equals_: function (o, elementEq) { + return o.fold(never, function (b) { + return elementEq(a, b); + }); + } + }; + return me; + }; + var from = function (value) { + return value === null || value === undefined ? NONE : some(value); + }; + var Optional = { + some: some, + none: none, + from: from + }; + + var revocable = function (doRevoke) { + var subject = Cell(Optional.none()); + var revoke = function () { + return subject.get().each(doRevoke); + }; + var clear = function () { + revoke(); + subject.set(Optional.none()); + }; + var isSet = function () { + return subject.get().isSome(); + }; + var set = function (s) { + revoke(); + subject.set(Optional.some(s)); + }; + return { + clear: clear, + isSet: isSet, + set: set + }; + }; + var unbindable = function () { + return revocable(function (s) { + return s.unbind(); + }); + }; + var value = function () { + var subject = Cell(Optional.none()); + var clear = function () { + return subject.set(Optional.none()); + }; + var set = function (s) { + return subject.set(Optional.some(s)); + }; + var isSet = function () { + return subject.get().isSome(); + }; + var on = function (f) { + return subject.get().each(f); + }; + return { + clear: clear, + set: set, + isSet: isSet, + on: on + }; + }; + + var typeOf = function (x) { + var t = typeof x; + if (x === null) { + return 'null'; + } else if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { + return 'array'; + } else if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { + return 'string'; + } else { + return t; + } + }; + var isType = function (type) { + return function (value) { + return typeOf(value) === type; + }; + }; + var isSimpleType = function (type) { + return function (value) { + return typeof value === type; + }; + }; + var isString = isType('string'); + var isArray = isType('array'); + var isBoolean = isSimpleType('boolean'); + var isNullable = function (a) { + return a === null || a === undefined; + }; + var isNonNullable = function (a) { + return !isNullable(a); + }; + var isFunction = isSimpleType('function'); + var isNumber = isSimpleType('number'); + + var nativePush = Array.prototype.push; + var map = function (xs, f) { + var len = xs.length; + var r = new Array(len); + for (var i = 0; i < len; i++) { + var x = xs[i]; + r[i] = f(x, i); + } + return r; + }; + var each = function (xs, f) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + f(x, i); + } + }; + var filter = function (xs, pred) { + var r = []; + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i)) { + r.push(x); + } + } + return r; + }; + var flatten = function (xs) { + var r = []; + for (var i = 0, len = xs.length; i < len; ++i) { + if (!isArray(xs[i])) { + throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs); + } + nativePush.apply(r, xs[i]); + } + return r; + }; + var bind = function (xs, f) { + return flatten(map(xs, f)); + }; + var get$1 = function (xs, i) { + return i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none(); + }; + var head = function (xs) { + return get$1(xs, 0); + }; + + var keys = Object.keys; + var each$1 = function (obj, f) { + var props = keys(obj); + for (var k = 0, len = props.length; k < len; k++) { + var i = props[k]; + var x = obj[i]; + f(x, i); + } + }; + + var isSupported = function (dom) { + return dom.style !== undefined && isFunction(dom.style.getPropertyValue); + }; + + var fromHtml = function (html, scope) { + var doc = scope || document; + var div = doc.createElement('div'); + div.innerHTML = html; + if (!div.hasChildNodes() || div.childNodes.length > 1) { + console.error('HTML does not have a single root node', html); + throw new Error('HTML must have a single root node'); + } + return fromDom(div.childNodes[0]); + }; + var fromTag = function (tag, scope) { + var doc = scope || document; + var node = doc.createElement(tag); + return fromDom(node); + }; + var fromText = function (text, scope) { + var doc = scope || document; + var node = doc.createTextNode(text); + return fromDom(node); + }; + var fromDom = function (node) { + if (node === null || node === undefined) { + throw new Error('Node cannot be null or undefined'); + } + return { dom: node }; + }; + var fromPoint = function (docElm, x, y) { + return Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom); + }; + var SugarElement = { + fromHtml: fromHtml, + fromTag: fromTag, + fromText: fromText, + fromDom: fromDom, + fromPoint: fromPoint + }; + + var Global = typeof window !== 'undefined' ? window : Function('return this;')(); + + var DOCUMENT = 9; + var DOCUMENT_FRAGMENT = 11; + var ELEMENT = 1; + var TEXT = 3; + + var type = function (element) { + return element.dom.nodeType; + }; + var isType$1 = function (t) { + return function (element) { + return type(element) === t; + }; + }; + var isElement = isType$1(ELEMENT); + var isText = isType$1(TEXT); + var isDocument = isType$1(DOCUMENT); + var isDocumentFragment = isType$1(DOCUMENT_FRAGMENT); + + var is = function (element, selector) { + var dom = element.dom; + if (dom.nodeType !== ELEMENT) { + return false; + } else { + var elem = dom; + if (elem.matches !== undefined) { + return elem.matches(selector); + } else if (elem.msMatchesSelector !== undefined) { + return elem.msMatchesSelector(selector); + } else if (elem.webkitMatchesSelector !== undefined) { + return elem.webkitMatchesSelector(selector); + } else if (elem.mozMatchesSelector !== undefined) { + return elem.mozMatchesSelector(selector); + } else { + throw new Error('Browser lacks native selectors'); + } + } + }; + var bypassSelector = function (dom) { + return dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0; + }; + var all = function (selector, scope) { + var base = scope === undefined ? document : scope.dom; + return bypassSelector(base) ? [] : map(base.querySelectorAll(selector), SugarElement.fromDom); + }; + + var eq = function (e1, e2) { + return e1.dom === e2.dom; + }; + + var owner = function (element) { + return SugarElement.fromDom(element.dom.ownerDocument); + }; + var documentOrOwner = function (dos) { + return isDocument(dos) ? dos : owner(dos); + }; + var parent = function (element) { + return Optional.from(element.dom.parentNode).map(SugarElement.fromDom); + }; + var parents = function (element, isRoot) { + var stop = isFunction(isRoot) ? isRoot : never; + var dom = element.dom; + var ret = []; + while (dom.parentNode !== null && dom.parentNode !== undefined) { + var rawParent = dom.parentNode; + var p = SugarElement.fromDom(rawParent); + ret.push(p); + if (stop(p) === true) { + break; + } else { + dom = rawParent; + } + } + return ret; + }; + var siblings = function (element) { + var filterSelf = function (elements) { + return filter(elements, function (x) { + return !eq(element, x); + }); + }; + return parent(element).map(children).map(filterSelf).getOr([]); + }; + var children = function (element) { + return map(element.dom.childNodes, SugarElement.fromDom); + }; + + var isShadowRoot = function (dos) { + return isDocumentFragment(dos); + }; + var supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode); + var isSupported$1 = constant(supported); + var getRootNode = supported ? function (e) { + return SugarElement.fromDom(e.dom.getRootNode()); + } : documentOrOwner; + var getShadowRoot = function (e) { + var r = getRootNode(e); + return isShadowRoot(r) ? Optional.some(r) : Optional.none(); + }; + var getShadowHost = function (e) { + return SugarElement.fromDom(e.dom.host); + }; + var getOriginalEventTarget = function (event) { + if (isSupported$1() && isNonNullable(event.target)) { + var el = SugarElement.fromDom(event.target); + if (isElement(el) && isOpenShadowHost(el)) { + if (event.composed && event.composedPath) { + var composedPath = event.composedPath(); + if (composedPath) { + return head(composedPath); + } + } + } + } + return Optional.from(event.target); + }; + var isOpenShadowHost = function (element) { + return isNonNullable(element.dom.shadowRoot); + }; + + var inBody = function (element) { + var dom = isText(element) ? element.dom.parentNode : element.dom; + if (dom === undefined || dom === null || dom.ownerDocument === null) { + return false; + } + var doc = dom.ownerDocument; + return getShadowRoot(SugarElement.fromDom(dom)).fold(function () { + return doc.body.contains(dom); + }, compose1(inBody, getShadowHost)); + }; + var getBody = function (doc) { + var b = doc.dom.body; + if (b === null || b === undefined) { + throw new Error('Body is not available yet'); + } + return SugarElement.fromDom(b); + }; + + var rawSet = function (dom, key, value) { + if (isString(value) || isBoolean(value) || isNumber(value)) { + dom.setAttribute(key, value + ''); + } else { + console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom); + throw new Error('Attribute value was not simple'); + } + }; + var set = function (element, key, value) { + rawSet(element.dom, key, value); + }; + var get$2 = function (element, key) { + var v = element.dom.getAttribute(key); + return v === null ? undefined : v; + }; + var remove = function (element, key) { + element.dom.removeAttribute(key); + }; + + var internalSet = function (dom, property, value) { + if (!isString(value)) { + console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom); + throw new Error('CSS value must be a string: ' + value); + } + if (isSupported(dom)) { + dom.style.setProperty(property, value); + } + }; + var setAll = function (element, css) { + var dom = element.dom; + each$1(css, function (v, k) { + internalSet(dom, k, v); + }); + }; + var get$3 = function (element, property) { + var dom = element.dom; + var styles = window.getComputedStyle(dom); + var r = styles.getPropertyValue(property); + return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r; + }; + var getUnsafeProperty = function (dom, property) { + return isSupported(dom) ? dom.style.getPropertyValue(property) : ''; + }; + + var mkEvent = function (target, x, y, stop, prevent, kill, raw) { + return { + target: target, + x: x, + y: y, + stop: stop, + prevent: prevent, + kill: kill, + raw: raw + }; + }; + var fromRawEvent = function (rawEvent) { + var target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target)); + var stop = function () { + return rawEvent.stopPropagation(); + }; + var prevent = function () { + return rawEvent.preventDefault(); + }; + var kill = compose(prevent, stop); + return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent); + }; + var handle = function (filter, handler) { + return function (rawEvent) { + if (filter(rawEvent)) { + handler(fromRawEvent(rawEvent)); + } + }; + }; + var binder = function (element, event, filter, handler, useCapture) { + var wrapped = handle(filter, handler); + element.dom.addEventListener(event, wrapped, useCapture); + return { unbind: curry(unbind, element, event, wrapped, useCapture) }; + }; + var bind$1 = function (element, event, filter, handler) { + return binder(element, event, filter, handler, false); + }; + var unbind = function (element, event, handler, useCapture) { + element.dom.removeEventListener(event, handler, useCapture); + }; + + var filter$1 = always; + var bind$2 = function (element, event, handler) { + return bind$1(element, event, filter$1, handler); + }; + + var r = function (left, top) { + var translate = function (x, y) { + return r(left + x, top + y); + }; + return { + left: left, + top: top, + translate: translate + }; + }; + var SugarPosition = r; + + var get$4 = function (_DOC) { + var doc = _DOC !== undefined ? _DOC.dom : document; + var x = doc.body.scrollLeft || doc.documentElement.scrollLeft; + var y = doc.body.scrollTop || doc.documentElement.scrollTop; + return SugarPosition(x, y); + }; + + var get$5 = function (_win) { + var win = _win === undefined ? window : _win; + return Optional.from(win['visualViewport']); + }; + var bounds = function (x, y, width, height) { + return { + x: x, + y: y, + width: width, + height: height, + right: x + width, + bottom: y + height + }; + }; + var getBounds = function (_win) { + var win = _win === undefined ? window : _win; + var doc = win.document; + var scroll = get$4(SugarElement.fromDom(doc)); + return get$5(win).fold(function () { + var html = win.document.documentElement; + var width = html.clientWidth; + var height = html.clientHeight; + return bounds(scroll.left, scroll.top, width, height); + }, function (visualViewport) { + return bounds(Math.max(visualViewport.pageLeft, scroll.left), Math.max(visualViewport.pageTop, scroll.top), visualViewport.width, visualViewport.height); + }); + }; + var bind$3 = function (name, callback, _win) { + return get$5(_win).map(function (visualViewport) { + var handler = function (e) { + return callback(fromRawEvent(e)); + }; + visualViewport.addEventListener(name, handler); + return { + unbind: function () { + return visualViewport.removeEventListener(name, handler); + } + }; + }).getOrThunk(function () { + return { unbind: noop }; + }); + }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils'); + + var global$2 = tinymce.util.Tools.resolve('tinymce.Env'); + + var global$3 = tinymce.util.Tools.resolve('tinymce.util.Delay'); + + var fireFullscreenStateChanged = function (editor, state) { + editor.fire('FullscreenStateChanged', { state: state }); + }; + + var getFullscreenNative = function (editor) { + return editor.getParam('fullscreen_native', false, 'boolean'); + }; + + var getFullscreenRoot = function (editor) { + var elem = SugarElement.fromDom(editor.getElement()); + return getShadowRoot(elem).map(getShadowHost).getOrThunk(function () { + return getBody(owner(elem)); + }); + }; + var getFullscreenElement = function (root) { + if (root.fullscreenElement !== undefined) { + return root.fullscreenElement; + } else if (root.msFullscreenElement !== undefined) { + return root.msFullscreenElement; + } else if (root.webkitFullscreenElement !== undefined) { + return root.webkitFullscreenElement; + } else { + return null; + } + }; + var getFullscreenchangeEventName = function () { + if (document.fullscreenElement !== undefined) { + return 'fullscreenchange'; + } else if (document.msFullscreenElement !== undefined) { + return 'MSFullscreenChange'; + } else if (document.webkitFullscreenElement !== undefined) { + return 'webkitfullscreenchange'; + } else { + return 'fullscreenchange'; + } + }; + var requestFullscreen = function (sugarElem) { + var elem = sugarElem.dom; + if (elem.requestFullscreen) { + elem.requestFullscreen(); + } else if (elem.msRequestFullscreen) { + elem.msRequestFullscreen(); + } else if (elem.webkitRequestFullScreen) { + elem.webkitRequestFullScreen(); + } + }; + var exitFullscreen = function (sugarDoc) { + var doc = sugarDoc.dom; + if (doc.exitFullscreen) { + doc.exitFullscreen(); + } else if (doc.msExitFullscreen) { + doc.msExitFullscreen(); + } else if (doc.webkitCancelFullScreen) { + doc.webkitCancelFullScreen(); + } + }; + var isFullscreenElement = function (elem) { + return elem.dom === getFullscreenElement(owner(elem).dom); + }; + + var ancestors = function (scope, predicate, isRoot) { + return filter(parents(scope, isRoot), predicate); + }; + var siblings$1 = function (scope, predicate) { + return filter(siblings(scope), predicate); + }; + + var all$1 = function (selector) { + return all(selector); + }; + var ancestors$1 = function (scope, selector, isRoot) { + return ancestors(scope, function (e) { + return is(e, selector); + }, isRoot); + }; + var siblings$2 = function (scope, selector) { + return siblings$1(scope, function (e) { + return is(e, selector); + }); + }; + + var attr = 'data-ephox-mobile-fullscreen-style'; + var siblingStyles = 'display:none!important;'; + var ancestorPosition = 'position:absolute!important;'; + var ancestorStyles = 'top:0!important;left:0!important;margin:0!important;padding:0!important;width:100%!important;height:100%!important;overflow:visible!important;'; + var bgFallback = 'background-color:rgb(255,255,255)!important;'; + var isAndroid = global$2.os.isAndroid(); + var matchColor = function (editorBody) { + var color = get$3(editorBody, 'background-color'); + return color !== undefined && color !== '' ? 'background-color:' + color + '!important' : bgFallback; + }; + var clobberStyles = function (dom, container, editorBody) { + var gatherSiblings = function (element) { + return siblings$2(element, '*:not(.tox-silver-sink)'); + }; + var clobber = function (clobberStyle) { + return function (element) { + var styles = get$2(element, 'style'); + var backup = styles === undefined ? 'no-styles' : styles.trim(); + if (backup === clobberStyle) { + return; + } else { + set(element, attr, backup); + setAll(element, dom.parseStyle(clobberStyle)); + } + }; + }; + var ancestors = ancestors$1(container, '*'); + var siblings = bind(ancestors, gatherSiblings); + var bgColor = matchColor(editorBody); + each(siblings, clobber(siblingStyles)); + each(ancestors, clobber(ancestorPosition + ancestorStyles + bgColor)); + var containerStyles = isAndroid === true ? '' : ancestorPosition; + clobber(containerStyles + ancestorStyles + bgColor)(container); + }; + var restoreStyles = function (dom) { + var clobberedEls = all$1('[' + attr + ']'); + each(clobberedEls, function (element) { + var restore = get$2(element, attr); + if (restore !== 'no-styles') { + setAll(element, dom.parseStyle(restore)); + } else { + remove(element, 'style'); + } + remove(element, attr); + }); + }; + + var DOM = global$1.DOM; + var getScrollPos = function () { + var vp = getBounds(window); + return { + x: vp.x, + y: vp.y + }; + }; + var setScrollPos = function (pos) { + window.scrollTo(pos.x, pos.y); + }; + var viewportUpdate = get$5().fold(function () { + return { + bind: noop, + unbind: noop + }; + }, function (visualViewport) { + var editorContainer = value(); + var resizeBinder = unbindable(); + var scrollBinder = unbindable(); + var refreshScroll = function () { + document.body.scrollTop = 0; + document.documentElement.scrollTop = 0; + }; + var refreshVisualViewport = function () { + window.requestAnimationFrame(function () { + editorContainer.on(function (container) { + return setAll(container, { + top: visualViewport.offsetTop + 'px', + left: visualViewport.offsetLeft + 'px', + height: visualViewport.height + 'px', + width: visualViewport.width + 'px' + }); + }); + }); + }; + var update = global$3.throttle(function () { + refreshScroll(); + refreshVisualViewport(); + }, 50); + var bind = function (element) { + editorContainer.set(element); + update(); + resizeBinder.set(bind$3('resize', update)); + scrollBinder.set(bind$3('scroll', update)); + }; + var unbind = function () { + editorContainer.on(function () { + resizeBinder.clear(); + scrollBinder.clear(); + }); + editorContainer.clear(); + }; + return { + bind: bind, + unbind: unbind + }; + }); + var toggleFullscreen = function (editor, fullscreenState) { + var body = document.body; + var documentElement = document.documentElement; + var editorContainer = editor.getContainer(); + var editorContainerS = SugarElement.fromDom(editorContainer); + var fullscreenRoot = getFullscreenRoot(editor); + var fullscreenInfo = fullscreenState.get(); + var editorBody = SugarElement.fromDom(editor.getBody()); + var isTouch = global$2.deviceType.isTouch(); + var editorContainerStyle = editorContainer.style; + var iframe = editor.iframeElement; + var iframeStyle = iframe.style; + var handleClasses = function (handler) { + handler(body, 'tox-fullscreen'); + handler(documentElement, 'tox-fullscreen'); + handler(editorContainer, 'tox-fullscreen'); + getShadowRoot(editorContainerS).map(function (root) { + return getShadowHost(root).dom; + }).each(function (host) { + handler(host, 'tox-fullscreen'); + handler(host, 'tox-shadowhost'); + }); + }; + var cleanup = function () { + if (isTouch) { + restoreStyles(editor.dom); + } + handleClasses(DOM.removeClass); + viewportUpdate.unbind(); + Optional.from(fullscreenState.get()).each(function (info) { + return info.fullscreenChangeHandler.unbind(); + }); + }; + if (!fullscreenInfo) { + var fullscreenChangeHandler = bind$2(owner(fullscreenRoot), getFullscreenchangeEventName(), function (_evt) { + if (getFullscreenNative(editor)) { + if (!isFullscreenElement(fullscreenRoot) && fullscreenState.get() !== null) { + toggleFullscreen(editor, fullscreenState); + } + } + }); + var newFullScreenInfo = { + scrollPos: getScrollPos(), + containerWidth: editorContainerStyle.width, + containerHeight: editorContainerStyle.height, + containerTop: editorContainerStyle.top, + containerLeft: editorContainerStyle.left, + iframeWidth: iframeStyle.width, + iframeHeight: iframeStyle.height, + fullscreenChangeHandler: fullscreenChangeHandler + }; + if (isTouch) { + clobberStyles(editor.dom, editorContainerS, editorBody); + } + iframeStyle.width = iframeStyle.height = '100%'; + editorContainerStyle.width = editorContainerStyle.height = ''; + handleClasses(DOM.addClass); + viewportUpdate.bind(editorContainerS); + editor.on('remove', cleanup); + fullscreenState.set(newFullScreenInfo); + if (getFullscreenNative(editor)) { + requestFullscreen(fullscreenRoot); + } + fireFullscreenStateChanged(editor, true); + } else { + fullscreenInfo.fullscreenChangeHandler.unbind(); + if (getFullscreenNative(editor) && isFullscreenElement(fullscreenRoot)) { + exitFullscreen(owner(fullscreenRoot)); + } + iframeStyle.width = fullscreenInfo.iframeWidth; + iframeStyle.height = fullscreenInfo.iframeHeight; + editorContainerStyle.width = fullscreenInfo.containerWidth; + editorContainerStyle.height = fullscreenInfo.containerHeight; + editorContainerStyle.top = fullscreenInfo.containerTop; + editorContainerStyle.left = fullscreenInfo.containerLeft; + setScrollPos(fullscreenInfo.scrollPos); + fullscreenState.set(null); + fireFullscreenStateChanged(editor, false); + cleanup(); + editor.off('remove', cleanup); + } + }; + + var register = function (editor, fullscreenState) { + editor.addCommand('mceFullScreen', function () { + toggleFullscreen(editor, fullscreenState); + }); + }; + + var makeSetupHandler = function (editor, fullscreenState) { + return function (api) { + api.setActive(fullscreenState.get() !== null); + var editorEventCallback = function (e) { + return api.setActive(e.state); + }; + editor.on('FullscreenStateChanged', editorEventCallback); + return function () { + return editor.off('FullscreenStateChanged', editorEventCallback); + }; + }; + }; + var register$1 = function (editor, fullscreenState) { + editor.ui.registry.addToggleMenuItem('fullscreen', { + text: 'Fullscreen', + icon: 'fullscreen', + shortcut: 'Meta+Shift+F', + onAction: function () { + return editor.execCommand('mceFullScreen'); + }, + onSetup: makeSetupHandler(editor, fullscreenState) + }); + editor.ui.registry.addToggleButton('fullscreen', { + tooltip: 'Fullscreen', + icon: 'fullscreen', + onAction: function () { + return editor.execCommand('mceFullScreen'); + }, + onSetup: makeSetupHandler(editor, fullscreenState) + }); + }; + + function Plugin () { + global.add('fullscreen', function (editor) { + var fullscreenState = Cell(null); + if (editor.inline) { + return get(fullscreenState); + } + register(editor, fullscreenState); + register$1(editor, fullscreenState); + editor.addShortcut('Meta+Shift+F', '', 'mceFullScreen'); + return get(fullscreenState); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/fullscreen/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/fullscreen/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..7dee35d74320d20e26a1be372c74fe0a25080e30 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/fullscreen/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var c=function(n){var e=n;return{get:function(){return e},set:function(n){e=n}}},n=tinymce.util.Tools.resolve("tinymce.PluginManager"),i=function(n){return{isFullscreen:function(){return null!==n.get()}}},e=function(){},u=function(n){return function(){return n}};var t,r,o,l=u(!1),f=u(!0),a=function(){return d},d=(t=function(n){return n.isNone()},{fold:function(n,e){return n()},is:l,isSome:l,isNone:f,getOr:o=function(n){return n},getOrThunk:r=function(n){return n()},getOrDie:function(n){throw new Error(n||"error: getOrDie called on none.")},getOrNull:u(null),getOrUndefined:u(undefined),or:o,orThunk:r,map:a,each:e,bind:a,exists:l,forall:f,filter:a,equals:t,equals_:t,toArray:function(){return[]},toString:u("none()")}),s=function(t){var n=u(t),e=function(){return o},r=function(n){return n(t)},o={fold:function(n,e){return e(t)},is:function(n){return t===n},isSome:f,isNone:l,getOr:n,getOrThunk:n,getOrDie:n,getOrNull:n,getOrUndefined:n,or:e,orThunk:e,map:function(n){return s(n(t))},each:function(n){n(t)},bind:r,exists:r,forall:r,filter:function(n){return n(t)?o:d},toArray:function(){return[t]},toString:function(){return"some("+t+")"},equals:function(n){return n.is(t)},equals_:function(n,e){return n.fold(l,function(n){return e(t,n)})}};return o},S={some:s,none:a,from:function(n){return null===n||n===undefined?d:s(n)}},m=function(){return n=function(n){return n.unbind()},e=c(S.none()),t=function(){return e.get().each(n)},{clear:function(){t(),e.set(S.none())},isSet:function(){return e.get().isSome()},set:function(n){t(),e.set(S.some(n))}};var n,e,t},h=function(r){return function(n){return t=typeof(e=n),(null===e?"null":"object"==t&&(Array.prototype.isPrototypeOf(e)||e.constructor&&"Array"===e.constructor.name)?"array":"object"==t&&(String.prototype.isPrototypeOf(e)||e.constructor&&"String"===e.constructor.name)?"string":t)===r;var e,t}},g=function(e){return function(n){return typeof n===e}},p=h("string"),v=h("array"),y=g("boolean"),w=function(n){return!(null===(e=n)||e===undefined);var e},b=g("function"),E=g("number"),F=Array.prototype.push,T=function(n,e){for(var t=n.length,r=new Array(t),o=0;o -1; + }; + var map = function (xs, f) { + var len = xs.length; + var r = new Array(len); + for (var i = 0; i < len; i++) { + var x = xs[i]; + r[i] = f(x, i); + } + return r; + }; + var filter = function (xs, pred) { + var r = []; + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i)) { + r.push(x); + } + } + return r; + }; + var findUntil = function (xs, pred, until) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i)) { + return Optional.some(x); + } else if (until(x, i)) { + break; + } + } + return Optional.none(); + }; + var find = function (xs, pred) { + return findUntil(xs, pred, never); + }; + + var keys = Object.keys; + var hasOwnProperty = Object.hasOwnProperty; + var get$1 = function (obj, key) { + return has(obj, key) ? Optional.from(obj[key]) : Optional.none(); + }; + var has = function (obj, key) { + return hasOwnProperty.call(obj, key); + }; + + var cat = function (arr) { + var r = []; + var push = function (x) { + r.push(x); + }; + for (var i = 0; i < arr.length; i++) { + arr[i].each(push); + } + return r; + }; + + var getHelpTabs = function (editor) { + return Optional.from(editor.getParam('help_tabs')); + }; + var getForcedPlugins = function (editor) { + return editor.getParam('forced_plugins'); + }; + + var description = '

                                                                                          Editor UI keyboard navigation

                                                                                          \n\n

                                                                                          Activating keyboard navigation

                                                                                          \n\n

                                                                                          The sections of the outer UI of the editor - the menubar, toolbar, sidebar and footer - are all keyboard navigable. As such, there are multiple ways to activate keyboard navigation:

                                                                                          \n
                                                                                            \n
                                                                                          • Focus the menubar: Alt + F9 (Windows) or ⌥F9 (MacOS)
                                                                                          • \n
                                                                                          • Focus the toolbar: Alt + F10 (Windows) or ⌥F10 (MacOS)
                                                                                          • \n
                                                                                          • Focus the footer: Alt + F11 (Windows) or ⌥F11 (MacOS)
                                                                                          • \n
                                                                                          \n\n

                                                                                          Focusing the menubar or toolbar will start keyboard navigation at the first item in the menubar or toolbar, which will be highlighted with a gray background. Focusing the footer will start keyboard navigation at the first item in the element path, which will be highlighted with an underline.

                                                                                          \n\n

                                                                                          Moving between UI sections

                                                                                          \n\n

                                                                                          When keyboard navigation is active, pressing tab will move the focus to the next major section of the UI, where applicable. These sections are:

                                                                                          \n
                                                                                            \n
                                                                                          • the menubar
                                                                                          • \n
                                                                                          • each group of the toolbar
                                                                                          • \n
                                                                                          • the sidebar
                                                                                          • \n
                                                                                          • the element path in the footer
                                                                                          • \n
                                                                                          • the wordcount toggle button in the footer
                                                                                          • \n
                                                                                          • the branding link in the footer
                                                                                          • \n
                                                                                          \n\n

                                                                                          Pressing shift + tab will move backwards through the same sections, except when moving from the footer to the toolbar. Focusing the element path then pressing shift + tab will move focus to the first toolbar group, not the last.

                                                                                          \n\n

                                                                                          Moving within UI sections

                                                                                          \n\n

                                                                                          Keyboard navigation within UI sections can usually be achieved using the left and right arrow keys. This includes:

                                                                                          \n
                                                                                            \n
                                                                                          • moving between menus in the menubar
                                                                                          • \n
                                                                                          • moving between buttons in a toolbar group
                                                                                          • \n
                                                                                          • moving between items in the element path
                                                                                          • \n
                                                                                          \n\n

                                                                                          In all these UI sections, keyboard navigation will cycle within the section. For example, focusing the last button in a toolbar group then pressing right arrow will move focus to the first item in the same toolbar group.

                                                                                          \n\n

                                                                                          Executing buttons

                                                                                          \n\n

                                                                                          To execute a button, navigate the selection to the desired button and hit space or enter.

                                                                                          \n\n

                                                                                          Opening, navigating and closing menus

                                                                                          \n\n

                                                                                          When focusing a menubar button or a toolbar button with a menu, pressing space, enter or down arrow will open the menu. When the menu opens the first item will be selected. To move up or down the menu, press the up or down arrow key respectively. This is the same for submenus, which can also be opened and closed using the left and right arrow keys.

                                                                                          \n\n

                                                                                          To close any active menu, hit the escape key. When a menu is closed the selection will be restored to its previous selection. This also works for closing submenus.

                                                                                          \n\n

                                                                                          Context toolbars and menus

                                                                                          \n\n

                                                                                          To focus an open context toolbar such as the table context toolbar, press Ctrl + F9 (Windows) or ⌃F9 (MacOS).

                                                                                          \n\n

                                                                                          Context toolbar navigation is the same as toolbar navigation, and context menu navigation is the same as standard menu navigation.

                                                                                          \n\n

                                                                                          Dialog navigation

                                                                                          \n\n

                                                                                          There are two types of dialog UIs in TinyMCE: tabbed dialogs and non-tabbed dialogs.

                                                                                          \n\n

                                                                                          When a non-tabbed dialog is opened, the first interactive component in the dialog will be focused. Users can navigate between interactive components by pressing tab. This includes any footer buttons. Navigation will cycle back to the first dialog component if tab is pressed while focusing the last component in the dialog. Pressing shift + tab will navigate backwards.

                                                                                          \n\n

                                                                                          When a tabbed dialog is opened, the first button in the tab menu is focused. Pressing tab will navigate to the first interactive component in that tab, and will cycle through the tab\u2019s components, the footer buttons, then back to the tab button. To switch to another tab, focus the tab button for the current tab, then use the arrow keys to cycle through the tab buttons.

                                                                                          '; + var tab = function () { + var body = { + type: 'htmlpanel', + presets: 'document', + html: description + }; + return { + name: 'keyboardnav', + title: 'Keyboard Navigation', + items: [body] + }; + }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.Env'); + + var convertText = function (source) { + var mac = { + alt: '⌥', + ctrl: '⌃', + shift: '⇧', + meta: '⌘', + access: '⌃⌥' + }; + var other = { + meta: 'Ctrl ', + access: 'Shift + Alt ' + }; + var replace = global$1.mac ? mac : other; + var shortcut = source.split('+'); + var updated = map(shortcut, function (segment) { + var search = segment.toLowerCase().trim(); + return has(replace, search) ? replace[search] : segment; + }); + return global$1.mac ? updated.join('').replace(/\s/, '') : updated.join('+'); + }; + + var shortcuts = [ + { + shortcuts: ['Meta + B'], + action: 'Bold' + }, + { + shortcuts: ['Meta + I'], + action: 'Italic' + }, + { + shortcuts: ['Meta + U'], + action: 'Underline' + }, + { + shortcuts: ['Meta + A'], + action: 'Select all' + }, + { + shortcuts: [ + 'Meta + Y', + 'Meta + Shift + Z' + ], + action: 'Redo' + }, + { + shortcuts: ['Meta + Z'], + action: 'Undo' + }, + { + shortcuts: ['Access + 1'], + action: 'Heading 1' + }, + { + shortcuts: ['Access + 2'], + action: 'Heading 2' + }, + { + shortcuts: ['Access + 3'], + action: 'Heading 3' + }, + { + shortcuts: ['Access + 4'], + action: 'Heading 4' + }, + { + shortcuts: ['Access + 5'], + action: 'Heading 5' + }, + { + shortcuts: ['Access + 6'], + action: 'Heading 6' + }, + { + shortcuts: ['Access + 7'], + action: 'Paragraph' + }, + { + shortcuts: ['Access + 8'], + action: 'Div' + }, + { + shortcuts: ['Access + 9'], + action: 'Address' + }, + { + shortcuts: ['Alt + 0'], + action: 'Open help dialog' + }, + { + shortcuts: ['Alt + F9'], + action: 'Focus to menubar' + }, + { + shortcuts: ['Alt + F10'], + action: 'Focus to toolbar' + }, + { + shortcuts: ['Alt + F11'], + action: 'Focus to element path' + }, + { + shortcuts: ['Ctrl + F9'], + action: 'Focus to contextual toolbar' + }, + { + shortcuts: ['Shift + Enter'], + action: 'Open popup menu for split buttons' + }, + { + shortcuts: ['Meta + K'], + action: 'Insert link (if link plugin activated)' + }, + { + shortcuts: ['Meta + S'], + action: 'Save (if save plugin activated)' + }, + { + shortcuts: ['Meta + F'], + action: 'Find (if searchreplace plugin activated)' + }, + { + shortcuts: ['Meta + Shift + F'], + action: 'Switch to or from fullscreen mode' + } + ]; + + var tab$1 = function () { + var shortcutList = map(shortcuts, function (shortcut) { + var shortcutText = map(shortcut.shortcuts, convertText).join(' or '); + return [ + shortcut.action, + shortcutText + ]; + }); + var tablePanel = { + type: 'table', + header: [ + 'Action', + 'Shortcut' + ], + cells: shortcutList + }; + return { + name: 'shortcuts', + title: 'Handy Shortcuts', + items: [tablePanel] + }; + }; + + var global$2 = tinymce.util.Tools.resolve('tinymce.util.I18n'); + + var urls = [ + { + key: 'advlist', + name: 'Advanced List' + }, + { + key: 'anchor', + name: 'Anchor' + }, + { + key: 'autolink', + name: 'Autolink' + }, + { + key: 'autoresize', + name: 'Autoresize' + }, + { + key: 'autosave', + name: 'Autosave' + }, + { + key: 'bbcode', + name: 'BBCode' + }, + { + key: 'charmap', + name: 'Character Map' + }, + { + key: 'code', + name: 'Code' + }, + { + key: 'codesample', + name: 'Code Sample' + }, + { + key: 'colorpicker', + name: 'Color Picker' + }, + { + key: 'directionality', + name: 'Directionality' + }, + { + key: 'emoticons', + name: 'Emoticons' + }, + { + key: 'fullpage', + name: 'Full Page' + }, + { + key: 'fullscreen', + name: 'Full Screen' + }, + { + key: 'help', + name: 'Help' + }, + { + key: 'hr', + name: 'Horizontal Rule' + }, + { + key: 'image', + name: 'Image' + }, + { + key: 'imagetools', + name: 'Image Tools' + }, + { + key: 'importcss', + name: 'Import CSS' + }, + { + key: 'insertdatetime', + name: 'Insert Date/Time' + }, + { + key: 'legacyoutput', + name: 'Legacy Output' + }, + { + key: 'link', + name: 'Link' + }, + { + key: 'lists', + name: 'Lists' + }, + { + key: 'media', + name: 'Media' + }, + { + key: 'nonbreaking', + name: 'Nonbreaking' + }, + { + key: 'noneditable', + name: 'Noneditable' + }, + { + key: 'pagebreak', + name: 'Page Break' + }, + { + key: 'paste', + name: 'Paste' + }, + { + key: 'preview', + name: 'Preview' + }, + { + key: 'print', + name: 'Print' + }, + { + key: 'save', + name: 'Save' + }, + { + key: 'searchreplace', + name: 'Search and Replace' + }, + { + key: 'spellchecker', + name: 'Spell Checker' + }, + { + key: 'tabfocus', + name: 'Tab Focus' + }, + { + key: 'table', + name: 'Table' + }, + { + key: 'template', + name: 'Template' + }, + { + key: 'textcolor', + name: 'Text Color' + }, + { + key: 'textpattern', + name: 'Text Pattern' + }, + { + key: 'toc', + name: 'Table of Contents' + }, + { + key: 'visualblocks', + name: 'Visual Blocks' + }, + { + key: 'visualchars', + name: 'Visual Characters' + }, + { + key: 'wordcount', + name: 'Word Count' + }, + { + key: 'advcode', + name: 'Advanced Code Editor*' + }, + { + key: 'formatpainter', + name: 'Format Painter*' + }, + { + key: 'powerpaste', + name: 'PowerPaste*' + }, + { + key: 'tinydrive', + name: 'Tiny Drive*', + slug: 'drive' + }, + { + key: 'tinymcespellchecker', + name: 'Spell Checker Pro*' + }, + { + key: 'a11ychecker', + name: 'Accessibility Checker*' + }, + { + key: 'linkchecker', + name: 'Link Checker*' + }, + { + key: 'mentions', + name: 'Mentions*' + }, + { + key: 'mediaembed', + name: 'Enhanced Media Embed*' + }, + { + key: 'checklist', + name: 'Checklist*' + }, + { + key: 'casechange', + name: 'Case Change*' + }, + { + key: 'permanentpen', + name: 'Permanent Pen*' + }, + { + key: 'pageembed', + name: 'Page Embed*' + }, + { + key: 'tinycomments', + name: 'Tiny Comments*', + slug: 'comments' + }, + { + key: 'advtable', + name: 'Advanced Tables*' + }, + { + key: 'autocorrect', + name: 'Autocorrect*' + } + ]; + + var tab$2 = function (editor) { + var availablePlugins = function () { + var premiumPlugins = [ + 'Accessibility Checker', + 'Advanced Code Editor', + 'Advanced Tables', + 'Case Change', + 'Checklist', + 'Tiny Comments', + 'Tiny Drive', + 'Enhanced Media Embed', + 'Format Painter', + 'Link Checker', + 'Mentions', + 'MoxieManager', + 'Page Embed', + 'Permanent Pen', + 'PowerPaste', + 'Spell Checker Pro' + ]; + var premiumPluginList = map(premiumPlugins, function (plugin) { + return '
                                                                                        • ' + global$2.translate(plugin) + '
                                                                                        • '; + }).join(''); + return '
                                                                                          ' + '

                                                                                          ' + global$2.translate('Premium plugins:') + '

                                                                                          ' + '' + '
                                                                                          '; + }; + var makeLink = function (p) { + return '' + p.name + ''; + }; + var maybeUrlize = function (editor, key) { + return find(urls, function (x) { + return x.key === key; + }).fold(function () { + var getMetadata = editor.plugins[key].getMetadata; + return typeof getMetadata === 'function' ? makeLink(getMetadata()) : key; + }, function (x) { + var urlSlug = x.slug || x.key; + return makeLink({ + name: x.name, + url: 'https://www.tiny.cloud/docs/plugins/' + urlSlug + }); + }); + }; + var getPluginKeys = function (editor) { + var keys$1 = keys(editor.plugins); + var forced_plugins = getForcedPlugins(editor); + return forced_plugins === undefined ? keys$1 : filter(keys$1, function (k) { + return !contains(forced_plugins, k); + }); + }; + var pluginLister = function (editor) { + var pluginKeys = getPluginKeys(editor); + var pluginLis = map(pluginKeys, function (key) { + return '
                                                                                        • ' + maybeUrlize(editor, key) + '
                                                                                        • '; + }); + var count = pluginLis.length; + var pluginsString = pluginLis.join(''); + var html = '

                                                                                          ' + global$2.translate([ + 'Plugins installed ({0}):', + count + ]) + '

                                                                                          ' + '
                                                                                            ' + pluginsString + '
                                                                                          '; + return html; + }; + var installedPlugins = function (editor) { + if (editor == null) { + return ''; + } + return '
                                                                                          ' + pluginLister(editor) + '
                                                                                          '; + }; + var htmlPanel = { + type: 'htmlpanel', + presets: 'document', + html: [ + installedPlugins(editor), + availablePlugins() + ].join('') + }; + return { + name: 'plugins', + title: 'Plugins', + items: [htmlPanel] + }; + }; + + var global$3 = tinymce.util.Tools.resolve('tinymce.EditorManager'); + + var tab$3 = function () { + var getVersion = function (major, minor) { + return major.indexOf('@') === 0 ? 'X.X.X' : major + '.' + minor; + }; + var version = getVersion(global$3.majorVersion, global$3.minorVersion); + var changeLogLink = 'TinyMCE ' + version + ''; + var htmlPanel = { + type: 'htmlpanel', + html: '

                                                                                          ' + global$2.translate([ + 'You are using {0}', + changeLogLink + ]) + '

                                                                                          ', + presets: 'document' + }; + return { + name: 'versions', + title: 'Version', + items: [htmlPanel] + }; + }; + + var parseHelpTabsSetting = function (tabsFromSettings, tabs) { + var newTabs = {}; + var names = map(tabsFromSettings, function (t) { + if (typeof t === 'string') { + if (has(tabs, t)) { + newTabs[t] = tabs[t]; + } + return t; + } else { + newTabs[t.name] = t; + return t.name; + } + }); + return { + tabs: newTabs, + names: names + }; + }; + var getNamesFromTabs = function (tabs) { + var names = keys(tabs); + var idx = names.indexOf('versions'); + if (idx !== -1) { + names.splice(idx, 1); + names.push('versions'); + } + return { + tabs: tabs, + names: names + }; + }; + var parseCustomTabs = function (editor, customTabs) { + var _a; + var shortcuts = tab$1(); + var nav = tab(); + var plugins = tab$2(editor); + var versions = tab$3(); + var tabs = __assign((_a = {}, _a[shortcuts.name] = shortcuts, _a[nav.name] = nav, _a[plugins.name] = plugins, _a[versions.name] = versions, _a), customTabs.get()); + return getHelpTabs(editor).fold(function () { + return getNamesFromTabs(tabs); + }, function (tabsFromSettings) { + return parseHelpTabsSetting(tabsFromSettings, tabs); + }); + }; + var init = function (editor, customTabs) { + return function () { + var _a = parseCustomTabs(editor, customTabs), tabs = _a.tabs, names = _a.names; + var foundTabs = map(names, function (name) { + return get$1(tabs, name); + }); + var dialogTabs = cat(foundTabs); + var body = { + type: 'tabpanel', + tabs: dialogTabs + }; + editor.windowManager.open({ + title: 'Help', + size: 'medium', + body: body, + buttons: [{ + type: 'cancel', + name: 'close', + text: 'Close', + primary: true + }], + initialData: {} + }); + }; + }; + + function Plugin () { + global.add('help', function (editor) { + var customTabs = Cell({}); + var api = get(customTabs); + var dialogOpener = init(editor, customTabs); + register$1(editor, dialogOpener); + register(editor, dialogOpener); + editor.shortcuts.add('Alt+0', 'Open help dialog', 'mceHelp'); + return api; + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/help/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/help/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..6b4b4143ca6f322f8b37f685f084da1e453e1325 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/help/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var e,t,n,a=tinymce.util.Tools.resolve("tinymce.PluginManager"),m=function(){return(m=Object.assign||function(e){for(var t,n=1,a=arguments.length;n'+e.name+""};return{name:"plugins",title:"Plugins",items:[{type:"htmlpanel",presets:"document",html:[null==(n=e)?"":'
                                                                                          '+function(a){var e,t,n,o=(t=f((e=a).plugins),(n=e.getParam("forced_plugins"))===undefined?t:function(e,t){for(var n=[],a=0,o=e.length;a"+(t=a,n=e,g(C,function(e){return e.key===n}).fold(function(){var e=t.plugins[n].getMetadata;return"function"==typeof e?l(e()):n},function(e){var t=e.slug||e.key;return l({name:e.name,url:"https://www.tiny.cloud/docs/plugins/"+t})}))+"";var t,n}),r=i.length,s=i.join("");return"

                                                                                          "+A.translate(["Plugins installed ({0}):",r])+"

                                                                                            "+s+"
                                                                                          "}(n)+"
                                                                                          ",(t=p(["Accessibility Checker","Advanced Code Editor","Advanced Tables","Case Change","Checklist","Tiny Comments","Tiny Drive","Enhanced Media Embed","Format Painter","Link Checker","Mentions","MoxieManager","Page Embed","Permanent Pen","PowerPaste","Spell Checker Pro"],function(e){return"
                                                                                        • "+A.translate(e)+"
                                                                                        • "}).join(""),'

                                                                                          '+A.translate("Premium plugins:")+"

                                                                                          ")].join("")}]}},x=tinymce.util.Tools.resolve("tinymce.EditorManager"),P=function(e,t){var n,a,o,i,r,s={name:"shortcuts",title:"Handy Shortcuts",items:[{type:"table",header:["Action","Shortcut"],cells:p(w,function(e){var t=p(e.shortcuts,v).join(" or ");return[e.action,t]})}]},l={name:"keyboardnav",title:"Keyboard Navigation",items:[{type:"htmlpanel",presets:"document",html:"

                                                                                          Editor UI keyboard navigation

                                                                                          \n\n

                                                                                          Activating keyboard navigation

                                                                                          \n\n

                                                                                          The sections of the outer UI of the editor - the menubar, toolbar, sidebar and footer - are all keyboard navigable. As such, there are multiple ways to activate keyboard navigation:

                                                                                          \n
                                                                                            \n
                                                                                          • Focus the menubar: Alt + F9 (Windows) or ⌥F9 (MacOS)
                                                                                          • \n
                                                                                          • Focus the toolbar: Alt + F10 (Windows) or ⌥F10 (MacOS)
                                                                                          • \n
                                                                                          • Focus the footer: Alt + F11 (Windows) or ⌥F11 (MacOS)
                                                                                          • \n
                                                                                          \n\n

                                                                                          Focusing the menubar or toolbar will start keyboard navigation at the first item in the menubar or toolbar, which will be highlighted with a gray background. Focusing the footer will start keyboard navigation at the first item in the element path, which will be highlighted with an underline.

                                                                                          \n\n

                                                                                          Moving between UI sections

                                                                                          \n\n

                                                                                          When keyboard navigation is active, pressing tab will move the focus to the next major section of the UI, where applicable. These sections are:

                                                                                          \n
                                                                                            \n
                                                                                          • the menubar
                                                                                          • \n
                                                                                          • each group of the toolbar
                                                                                          • \n
                                                                                          • the sidebar
                                                                                          • \n
                                                                                          • the element path in the footer
                                                                                          • \n
                                                                                          • the wordcount toggle button in the footer
                                                                                          • \n
                                                                                          • the branding link in the footer
                                                                                          • \n
                                                                                          \n\n

                                                                                          Pressing shift + tab will move backwards through the same sections, except when moving from the footer to the toolbar. Focusing the element path then pressing shift + tab will move focus to the first toolbar group, not the last.

                                                                                          \n\n

                                                                                          Moving within UI sections

                                                                                          \n\n

                                                                                          Keyboard navigation within UI sections can usually be achieved using the left and right arrow keys. This includes:

                                                                                          \n
                                                                                            \n
                                                                                          • moving between menus in the menubar
                                                                                          • \n
                                                                                          • moving between buttons in a toolbar group
                                                                                          • \n
                                                                                          • moving between items in the element path
                                                                                          • \n
                                                                                          \n\n

                                                                                          In all these UI sections, keyboard navigation will cycle within the section. For example, focusing the last button in a toolbar group then pressing right arrow will move focus to the first item in the same toolbar group.

                                                                                          \n\n

                                                                                          Executing buttons

                                                                                          \n\n

                                                                                          To execute a button, navigate the selection to the desired button and hit space or enter.

                                                                                          \n\n

                                                                                          Opening, navigating and closing menus

                                                                                          \n\n

                                                                                          When focusing a menubar button or a toolbar button with a menu, pressing space, enter or down arrow will open the menu. When the menu opens the first item will be selected. To move up or down the menu, press the up or down arrow key respectively. This is the same for submenus, which can also be opened and closed using the left and right arrow keys.

                                                                                          \n\n

                                                                                          To close any active menu, hit the escape key. When a menu is closed the selection will be restored to its previous selection. This also works for closing submenus.

                                                                                          \n\n

                                                                                          Context toolbars and menus

                                                                                          \n\n

                                                                                          To focus an open context toolbar such as the table context toolbar, press Ctrl + F9 (Windows) or ⌃F9 (MacOS).

                                                                                          \n\n

                                                                                          Context toolbar navigation is the same as toolbar navigation, and context menu navigation is the same as standard menu navigation.

                                                                                          \n\n

                                                                                          Dialog navigation

                                                                                          \n\n

                                                                                          There are two types of dialog UIs in TinyMCE: tabbed dialogs and non-tabbed dialogs.

                                                                                          \n\n

                                                                                          When a non-tabbed dialog is opened, the first interactive component in the dialog will be focused. Users can navigate between interactive components by pressing tab. This includes any footer buttons. Navigation will cycle back to the first dialog component if tab is pressed while focusing the last component in the dialog. Pressing shift + tab will navigate backwards.

                                                                                          \n\n

                                                                                          When a tabbed dialog is opened, the first button in the tab menu is focused. Pressing tab will navigate to the first interactive component in that tab, and will cycle through the tab\u2019s components, the footer buttons, then back to the tab button. To switch to another tab, focus the tab button for the current tab, then use the arrow keys to cycle through the tab buttons.

                                                                                          "}]},c=T(e),u=(i='TinyMCE '+(a=x.majorVersion,o=x.minorVersion,0===a.indexOf("@")?"X.X.X":a+"."+o)+"",{name:"versions",title:"Version",items:[{type:"htmlpanel",html:"

                                                                                          "+A.translate(["You are using {0}",i])+"

                                                                                          ",presets:"document"}]}),h=m(((n={})[s.name]=s,n[l.name]=l,n[c.name]=c,n[u.name]=u,n),t.get());return r=e,d.from(r.getParam("help_tabs")).fold(function(){return t=f(e=h),-1!==(n=t.indexOf("versions"))&&(t.splice(n,1),t.push("versions")),{tabs:e,names:t};var e,t,n},function(e){return t=h,n={},a=p(e,function(e){return"string"==typeof e?(y(t,e)&&(n[e]=t[e]),e):(n[e.name]=e).name}),{tabs:n,names:a};var t,n,a})},M=function(o,i){return function(){var e=P(o,i),a=e.tabs,t=e.names,n={type:"tabpanel",tabs:function(e){for(var t=[],n=function(e){t.push(e)},a=0;a'); + }); + }; + + var register$1 = function (editor) { + editor.ui.registry.addButton('hr', { + icon: 'horizontal-rule', + tooltip: 'Horizontal line', + onAction: function () { + return editor.execCommand('InsertHorizontalRule'); + } + }); + editor.ui.registry.addMenuItem('hr', { + icon: 'horizontal-rule', + text: 'Horizontal line', + onAction: function () { + return editor.execCommand('InsertHorizontalRule'); + } + }); + }; + + function Plugin () { + global.add('hr', function (editor) { + register(editor); + register$1(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/hr/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/hr/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..dfeca9e08f3d98834e6766dcfc4eccdd3f34d5fb --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/hr/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager");n.add("hr",function(n){var o,t;(o=n).addCommand("InsertHorizontalRule",function(){o.execCommand("mceInsertContent",!1,"
                                                                                          ")}),(t=n).ui.registry.addButton("hr",{icon:"horizontal-rule",tooltip:"Horizontal line",onAction:function(){return t.execCommand("InsertHorizontalRule")}}),t.ui.registry.addMenuItem("hr",{icon:"horizontal-rule",text:"Horizontal line",onAction:function(){return t.execCommand("InsertHorizontalRule")}})})}(); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/image/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/image/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..d7b1cf18bcf44ec44417f54fca44fd00ae49e857 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/image/plugin.js @@ -0,0 +1,1664 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var __assign = function () { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + var typeOf = function (x) { + var t = typeof x; + if (x === null) { + return 'null'; + } else if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { + return 'array'; + } else if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { + return 'string'; + } else { + return t; + } + }; + var isType = function (type) { + return function (value) { + return typeOf(value) === type; + }; + }; + var isSimpleType = function (type) { + return function (value) { + return typeof value === type; + }; + }; + var eq = function (t) { + return function (a) { + return t === a; + }; + }; + var isString = isType('string'); + var isObject = isType('object'); + var isArray = isType('array'); + var isNull = eq(null); + var isBoolean = isSimpleType('boolean'); + var isNumber = isSimpleType('number'); + + var noop = function () { + }; + var constant = function (value) { + return function () { + return value; + }; + }; + var never = constant(false); + var always = constant(true); + + var none = function () { + return NONE; + }; + var NONE = function () { + var eq = function (o) { + return o.isNone(); + }; + var call = function (thunk) { + return thunk(); + }; + var id = function (n) { + return n; + }; + var me = { + fold: function (n, _s) { + return n(); + }, + is: never, + isSome: never, + isNone: always, + getOr: id, + getOrThunk: call, + getOrDie: function (msg) { + throw new Error(msg || 'error: getOrDie called on none.'); + }, + getOrNull: constant(null), + getOrUndefined: constant(undefined), + or: id, + orThunk: call, + map: none, + each: noop, + bind: none, + exists: never, + forall: always, + filter: none, + equals: eq, + equals_: eq, + toArray: function () { + return []; + }, + toString: constant('none()') + }; + return me; + }(); + var some = function (a) { + var constant_a = constant(a); + var self = function () { + return me; + }; + var bind = function (f) { + return f(a); + }; + var me = { + fold: function (n, s) { + return s(a); + }, + is: function (v) { + return a === v; + }, + isSome: always, + isNone: never, + getOr: constant_a, + getOrThunk: constant_a, + getOrDie: constant_a, + getOrNull: constant_a, + getOrUndefined: constant_a, + or: self, + orThunk: self, + map: function (f) { + return some(f(a)); + }, + each: function (f) { + f(a); + }, + bind: bind, + exists: bind, + forall: bind, + filter: function (f) { + return f(a) ? me : NONE; + }, + toArray: function () { + return [a]; + }, + toString: function () { + return 'some(' + a + ')'; + }, + equals: function (o) { + return o.is(a); + }, + equals_: function (o, elementEq) { + return o.fold(never, function (b) { + return elementEq(a, b); + }); + } + }; + return me; + }; + var from = function (value) { + return value === null || value === undefined ? NONE : some(value); + }; + var Optional = { + some: some, + none: none, + from: from + }; + + var nativePush = Array.prototype.push; + var flatten = function (xs) { + var r = []; + for (var i = 0, len = xs.length; i < len; ++i) { + if (!isArray(xs[i])) { + throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs); + } + nativePush.apply(r, xs[i]); + } + return r; + }; + var get = function (xs, i) { + return i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none(); + }; + var head = function (xs) { + return get(xs, 0); + }; + var findMap = function (arr, f) { + for (var i = 0; i < arr.length; i++) { + var r = f(arr[i], i); + if (r.isSome()) { + return r; + } + } + return Optional.none(); + }; + + var Global = typeof window !== 'undefined' ? window : Function('return this;')(); + + var rawSet = function (dom, key, value) { + if (isString(value) || isBoolean(value) || isNumber(value)) { + dom.setAttribute(key, value + ''); + } else { + console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom); + throw new Error('Attribute value was not simple'); + } + }; + var set = function (element, key, value) { + rawSet(element.dom, key, value); + }; + var remove = function (element, key) { + element.dom.removeAttribute(key); + }; + + var fromHtml = function (html, scope) { + var doc = scope || document; + var div = doc.createElement('div'); + div.innerHTML = html; + if (!div.hasChildNodes() || div.childNodes.length > 1) { + console.error('HTML does not have a single root node', html); + throw new Error('HTML must have a single root node'); + } + return fromDom(div.childNodes[0]); + }; + var fromTag = function (tag, scope) { + var doc = scope || document; + var node = doc.createElement(tag); + return fromDom(node); + }; + var fromText = function (text, scope) { + var doc = scope || document; + var node = doc.createTextNode(text); + return fromDom(node); + }; + var fromDom = function (node) { + if (node === null || node === undefined) { + throw new Error('Node cannot be null or undefined'); + } + return { dom: node }; + }; + var fromPoint = function (docElm, x, y) { + return Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom); + }; + var SugarElement = { + fromHtml: fromHtml, + fromTag: fromTag, + fromText: fromText, + fromDom: fromDom, + fromPoint: fromPoint + }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils'); + + var global$2 = tinymce.util.Tools.resolve('tinymce.util.Promise'); + + var global$3 = tinymce.util.Tools.resolve('tinymce.util.XHR'); + + var hasDimensions = function (editor) { + return editor.getParam('image_dimensions', true, 'boolean'); + }; + var hasAdvTab = function (editor) { + return editor.getParam('image_advtab', false, 'boolean'); + }; + var hasUploadTab = function (editor) { + return editor.getParam('image_uploadtab', true, 'boolean'); + }; + var getPrependUrl = function (editor) { + return editor.getParam('image_prepend_url', '', 'string'); + }; + var getClassList = function (editor) { + return editor.getParam('image_class_list'); + }; + var hasDescription = function (editor) { + return editor.getParam('image_description', true, 'boolean'); + }; + var hasImageTitle = function (editor) { + return editor.getParam('image_title', false, 'boolean'); + }; + var hasImageCaption = function (editor) { + return editor.getParam('image_caption', false, 'boolean'); + }; + var getImageList = function (editor) { + return editor.getParam('image_list', false); + }; + var hasUploadUrl = function (editor) { + return !!getUploadUrl(editor); + }; + var hasUploadHandler = function (editor) { + return !!getUploadHandler(editor); + }; + var getUploadUrl = function (editor) { + return editor.getParam('images_upload_url', '', 'string'); + }; + var getUploadHandler = function (editor) { + return editor.getParam('images_upload_handler', undefined, 'function'); + }; + var getUploadBasePath = function (editor) { + return editor.getParam('images_upload_base_path', undefined, 'string'); + }; + var getUploadCredentials = function (editor) { + return editor.getParam('images_upload_credentials', false, 'boolean'); + }; + var showAccessibilityOptions = function (editor) { + return editor.getParam('a11y_advanced_options', false, 'boolean'); + }; + var isAutomaticUploadsEnabled = function (editor) { + return editor.getParam('automatic_uploads', true, 'boolean'); + }; + + var parseIntAndGetMax = function (val1, val2) { + return Math.max(parseInt(val1, 10), parseInt(val2, 10)); + }; + var getImageSize = function (url) { + return new global$2(function (callback) { + var img = document.createElement('img'); + var done = function (dimensions) { + if (img.parentNode) { + img.parentNode.removeChild(img); + } + callback(dimensions); + }; + img.onload = function () { + var width = parseIntAndGetMax(img.width, img.clientWidth); + var height = parseIntAndGetMax(img.height, img.clientHeight); + var dimensions = { + width: width, + height: height + }; + done(global$2.resolve(dimensions)); + }; + img.onerror = function () { + done(global$2.reject('Failed to get image dimensions for: ' + url)); + }; + var style = img.style; + style.visibility = 'hidden'; + style.position = 'fixed'; + style.bottom = style.left = '0px'; + style.width = style.height = 'auto'; + document.body.appendChild(img); + img.src = url; + }); + }; + var removePixelSuffix = function (value) { + if (value) { + value = value.replace(/px$/, ''); + } + return value; + }; + var addPixelSuffix = function (value) { + if (value.length > 0 && /^[0-9]+$/.test(value)) { + value += 'px'; + } + return value; + }; + var mergeMargins = function (css) { + if (css.margin) { + var splitMargin = String(css.margin).split(' '); + switch (splitMargin.length) { + case 1: + css['margin-top'] = css['margin-top'] || splitMargin[0]; + css['margin-right'] = css['margin-right'] || splitMargin[0]; + css['margin-bottom'] = css['margin-bottom'] || splitMargin[0]; + css['margin-left'] = css['margin-left'] || splitMargin[0]; + break; + case 2: + css['margin-top'] = css['margin-top'] || splitMargin[0]; + css['margin-right'] = css['margin-right'] || splitMargin[1]; + css['margin-bottom'] = css['margin-bottom'] || splitMargin[0]; + css['margin-left'] = css['margin-left'] || splitMargin[1]; + break; + case 3: + css['margin-top'] = css['margin-top'] || splitMargin[0]; + css['margin-right'] = css['margin-right'] || splitMargin[1]; + css['margin-bottom'] = css['margin-bottom'] || splitMargin[2]; + css['margin-left'] = css['margin-left'] || splitMargin[1]; + break; + case 4: + css['margin-top'] = css['margin-top'] || splitMargin[0]; + css['margin-right'] = css['margin-right'] || splitMargin[1]; + css['margin-bottom'] = css['margin-bottom'] || splitMargin[2]; + css['margin-left'] = css['margin-left'] || splitMargin[3]; + } + delete css.margin; + } + return css; + }; + var createImageList = function (editor, callback) { + var imageList = getImageList(editor); + if (typeof imageList === 'string') { + global$3.send({ + url: imageList, + success: function (text) { + callback(JSON.parse(text)); + } + }); + } else if (typeof imageList === 'function') { + imageList(callback); + } else { + callback(imageList); + } + }; + var waitLoadImage = function (editor, data, imgElm) { + var selectImage = function () { + imgElm.onload = imgElm.onerror = null; + if (editor.selection) { + editor.selection.select(imgElm); + editor.nodeChanged(); + } + }; + imgElm.onload = function () { + if (!data.width && !data.height && hasDimensions(editor)) { + editor.dom.setAttribs(imgElm, { + width: String(imgElm.clientWidth), + height: String(imgElm.clientHeight) + }); + } + selectImage(); + }; + imgElm.onerror = selectImage; + }; + var blobToDataUri = function (blob) { + return new global$2(function (resolve, reject) { + var reader = new FileReader(); + reader.onload = function () { + resolve(reader.result); + }; + reader.onerror = function () { + reject(reader.error.message); + }; + reader.readAsDataURL(blob); + }); + }; + var isPlaceholderImage = function (imgElm) { + return imgElm.nodeName === 'IMG' && (imgElm.hasAttribute('data-mce-object') || imgElm.hasAttribute('data-mce-placeholder')); + }; + + var DOM = global$1.DOM; + var getHspace = function (image) { + if (image.style.marginLeft && image.style.marginRight && image.style.marginLeft === image.style.marginRight) { + return removePixelSuffix(image.style.marginLeft); + } else { + return ''; + } + }; + var getVspace = function (image) { + if (image.style.marginTop && image.style.marginBottom && image.style.marginTop === image.style.marginBottom) { + return removePixelSuffix(image.style.marginTop); + } else { + return ''; + } + }; + var getBorder = function (image) { + if (image.style.borderWidth) { + return removePixelSuffix(image.style.borderWidth); + } else { + return ''; + } + }; + var getAttrib = function (image, name) { + if (image.hasAttribute(name)) { + return image.getAttribute(name); + } else { + return ''; + } + }; + var getStyle = function (image, name) { + return image.style[name] ? image.style[name] : ''; + }; + var hasCaption = function (image) { + return image.parentNode !== null && image.parentNode.nodeName === 'FIGURE'; + }; + var updateAttrib = function (image, name, value) { + if (value === '') { + image.removeAttribute(name); + } else { + image.setAttribute(name, value); + } + }; + var wrapInFigure = function (image) { + var figureElm = DOM.create('figure', { class: 'image' }); + DOM.insertAfter(figureElm, image); + figureElm.appendChild(image); + figureElm.appendChild(DOM.create('figcaption', { contentEditable: 'true' }, 'Caption')); + figureElm.contentEditable = 'false'; + }; + var removeFigure = function (image) { + var figureElm = image.parentNode; + DOM.insertAfter(image, figureElm); + DOM.remove(figureElm); + }; + var toggleCaption = function (image) { + if (hasCaption(image)) { + removeFigure(image); + } else { + wrapInFigure(image); + } + }; + var normalizeStyle = function (image, normalizeCss) { + var attrValue = image.getAttribute('style'); + var value = normalizeCss(attrValue !== null ? attrValue : ''); + if (value.length > 0) { + image.setAttribute('style', value); + image.setAttribute('data-mce-style', value); + } else { + image.removeAttribute('style'); + } + }; + var setSize = function (name, normalizeCss) { + return function (image, name, value) { + if (image.style[name]) { + image.style[name] = addPixelSuffix(value); + normalizeStyle(image, normalizeCss); + } else { + updateAttrib(image, name, value); + } + }; + }; + var getSize = function (image, name) { + if (image.style[name]) { + return removePixelSuffix(image.style[name]); + } else { + return getAttrib(image, name); + } + }; + var setHspace = function (image, value) { + var pxValue = addPixelSuffix(value); + image.style.marginLeft = pxValue; + image.style.marginRight = pxValue; + }; + var setVspace = function (image, value) { + var pxValue = addPixelSuffix(value); + image.style.marginTop = pxValue; + image.style.marginBottom = pxValue; + }; + var setBorder = function (image, value) { + var pxValue = addPixelSuffix(value); + image.style.borderWidth = pxValue; + }; + var setBorderStyle = function (image, value) { + image.style.borderStyle = value; + }; + var getBorderStyle = function (image) { + return getStyle(image, 'borderStyle'); + }; + var isFigure = function (elm) { + return elm.nodeName === 'FIGURE'; + }; + var isImage = function (elm) { + return elm.nodeName === 'IMG'; + }; + var getIsDecorative = function (image) { + return DOM.getAttrib(image, 'alt').length === 0 && DOM.getAttrib(image, 'role') === 'presentation'; + }; + var getAlt = function (image) { + if (getIsDecorative(image)) { + return ''; + } else { + return getAttrib(image, 'alt'); + } + }; + var defaultData = function () { + return { + src: '', + alt: '', + title: '', + width: '', + height: '', + class: '', + style: '', + caption: false, + hspace: '', + vspace: '', + border: '', + borderStyle: '', + isDecorative: false + }; + }; + var getStyleValue = function (normalizeCss, data) { + var image = document.createElement('img'); + updateAttrib(image, 'style', data.style); + if (getHspace(image) || data.hspace !== '') { + setHspace(image, data.hspace); + } + if (getVspace(image) || data.vspace !== '') { + setVspace(image, data.vspace); + } + if (getBorder(image) || data.border !== '') { + setBorder(image, data.border); + } + if (getBorderStyle(image) || data.borderStyle !== '') { + setBorderStyle(image, data.borderStyle); + } + return normalizeCss(image.getAttribute('style')); + }; + var create = function (normalizeCss, data) { + var image = document.createElement('img'); + write(normalizeCss, __assign(__assign({}, data), { caption: false }), image); + setAlt(image, data.alt, data.isDecorative); + if (data.caption) { + var figure = DOM.create('figure', { class: 'image' }); + figure.appendChild(image); + figure.appendChild(DOM.create('figcaption', { contentEditable: 'true' }, 'Caption')); + figure.contentEditable = 'false'; + return figure; + } else { + return image; + } + }; + var read = function (normalizeCss, image) { + return { + src: getAttrib(image, 'src'), + alt: getAlt(image), + title: getAttrib(image, 'title'), + width: getSize(image, 'width'), + height: getSize(image, 'height'), + class: getAttrib(image, 'class'), + style: normalizeCss(getAttrib(image, 'style')), + caption: hasCaption(image), + hspace: getHspace(image), + vspace: getVspace(image), + border: getBorder(image), + borderStyle: getStyle(image, 'borderStyle'), + isDecorative: getIsDecorative(image) + }; + }; + var updateProp = function (image, oldData, newData, name, set) { + if (newData[name] !== oldData[name]) { + set(image, name, newData[name]); + } + }; + var setAlt = function (image, alt, isDecorative) { + if (isDecorative) { + DOM.setAttrib(image, 'role', 'presentation'); + var sugarImage = SugarElement.fromDom(image); + set(sugarImage, 'alt', ''); + } else { + if (isNull(alt)) { + var sugarImage = SugarElement.fromDom(image); + remove(sugarImage, 'alt'); + } else { + var sugarImage = SugarElement.fromDom(image); + set(sugarImage, 'alt', alt); + } + if (DOM.getAttrib(image, 'role') === 'presentation') { + DOM.setAttrib(image, 'role', ''); + } + } + }; + var updateAlt = function (image, oldData, newData) { + if (newData.alt !== oldData.alt || newData.isDecorative !== oldData.isDecorative) { + setAlt(image, newData.alt, newData.isDecorative); + } + }; + var normalized = function (set, normalizeCss) { + return function (image, name, value) { + set(image, value); + normalizeStyle(image, normalizeCss); + }; + }; + var write = function (normalizeCss, newData, image) { + var oldData = read(normalizeCss, image); + updateProp(image, oldData, newData, 'caption', function (image, _name, _value) { + return toggleCaption(image); + }); + updateProp(image, oldData, newData, 'src', updateAttrib); + updateProp(image, oldData, newData, 'title', updateAttrib); + updateProp(image, oldData, newData, 'width', setSize('width', normalizeCss)); + updateProp(image, oldData, newData, 'height', setSize('height', normalizeCss)); + updateProp(image, oldData, newData, 'class', updateAttrib); + updateProp(image, oldData, newData, 'style', normalized(function (image, value) { + return updateAttrib(image, 'style', value); + }, normalizeCss)); + updateProp(image, oldData, newData, 'hspace', normalized(setHspace, normalizeCss)); + updateProp(image, oldData, newData, 'vspace', normalized(setVspace, normalizeCss)); + updateProp(image, oldData, newData, 'border', normalized(setBorder, normalizeCss)); + updateProp(image, oldData, newData, 'borderStyle', normalized(setBorderStyle, normalizeCss)); + updateAlt(image, oldData, newData); + }; + + var normalizeCss = function (editor, cssText) { + var css = editor.dom.styles.parse(cssText); + var mergedCss = mergeMargins(css); + var compressed = editor.dom.styles.parse(editor.dom.styles.serialize(mergedCss)); + return editor.dom.styles.serialize(compressed); + }; + var getSelectedImage = function (editor) { + var imgElm = editor.selection.getNode(); + var figureElm = editor.dom.getParent(imgElm, 'figure.image'); + if (figureElm) { + return editor.dom.select('img', figureElm)[0]; + } + if (imgElm && (imgElm.nodeName !== 'IMG' || isPlaceholderImage(imgElm))) { + return null; + } + return imgElm; + }; + var splitTextBlock = function (editor, figure) { + var dom = editor.dom; + var textBlock = dom.getParent(figure.parentNode, function (node) { + return !!editor.schema.getTextBlockElements()[node.nodeName]; + }, editor.getBody()); + if (textBlock) { + return dom.split(textBlock, figure); + } else { + return figure; + } + }; + var readImageDataFromSelection = function (editor) { + var image = getSelectedImage(editor); + return image ? read(function (css) { + return normalizeCss(editor, css); + }, image) : defaultData(); + }; + var insertImageAtCaret = function (editor, data) { + var elm = create(function (css) { + return normalizeCss(editor, css); + }, data); + editor.dom.setAttrib(elm, 'data-mce-id', '__mcenew'); + editor.focus(); + editor.selection.setContent(elm.outerHTML); + var insertedElm = editor.dom.select('*[data-mce-id="__mcenew"]')[0]; + editor.dom.setAttrib(insertedElm, 'data-mce-id', null); + if (isFigure(insertedElm)) { + var figure = splitTextBlock(editor, insertedElm); + editor.selection.select(figure); + } else { + editor.selection.select(insertedElm); + } + }; + var syncSrcAttr = function (editor, image) { + editor.dom.setAttrib(image, 'src', image.getAttribute('src')); + }; + var deleteImage = function (editor, image) { + if (image) { + var elm = editor.dom.is(image.parentNode, 'figure.image') ? image.parentNode : image; + editor.dom.remove(elm); + editor.focus(); + editor.nodeChanged(); + if (editor.dom.isEmpty(editor.getBody())) { + editor.setContent(''); + editor.selection.setCursorLocation(); + } + } + }; + var writeImageDataToSelection = function (editor, data) { + var image = getSelectedImage(editor); + write(function (css) { + return normalizeCss(editor, css); + }, data, image); + syncSrcAttr(editor, image); + if (isFigure(image.parentNode)) { + var figure = image.parentNode; + splitTextBlock(editor, figure); + editor.selection.select(image.parentNode); + } else { + editor.selection.select(image); + waitLoadImage(editor, data, image); + } + }; + var insertOrUpdateImage = function (editor, partialData) { + var image = getSelectedImage(editor); + if (image) { + var selectedImageData = read(function (css) { + return normalizeCss(editor, css); + }, image); + var data = __assign(__assign({}, selectedImageData), partialData); + if (data.src) { + writeImageDataToSelection(editor, data); + } else { + deleteImage(editor, image); + } + } else if (partialData.src) { + insertImageAtCaret(editor, __assign(__assign({}, defaultData()), partialData)); + } + }; + + var hasOwnProperty = Object.prototype.hasOwnProperty; + var deep = function (old, nu) { + var bothObjects = isObject(old) && isObject(nu); + return bothObjects ? deepMerge(old, nu) : nu; + }; + var baseMerge = function (merger) { + return function () { + var objects = new Array(arguments.length); + for (var i = 0; i < objects.length; i++) { + objects[i] = arguments[i]; + } + if (objects.length === 0) { + throw new Error('Can\'t merge zero objects'); + } + var ret = {}; + for (var j = 0; j < objects.length; j++) { + var curObject = objects[j]; + for (var key in curObject) { + if (hasOwnProperty.call(curObject, key)) { + ret[key] = merger(ret[key], curObject[key]); + } + } + } + return ret; + }; + }; + var deepMerge = baseMerge(deep); + + var global$4 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var getValue = function (item) { + return isString(item.value) ? item.value : ''; + }; + var getText = function (item) { + if (isString(item.text)) { + return item.text; + } else if (isString(item.title)) { + return item.title; + } else { + return ''; + } + }; + var sanitizeList = function (list, extractValue) { + var out = []; + global$4.each(list, function (item) { + var text = getText(item); + if (item.menu !== undefined) { + var items = sanitizeList(item.menu, extractValue); + out.push({ + text: text, + items: items + }); + } else { + var value = extractValue(item); + out.push({ + text: text, + value: value + }); + } + }); + return out; + }; + var sanitizer = function (extracter) { + if (extracter === void 0) { + extracter = getValue; + } + return function (list) { + if (list) { + return Optional.from(list).map(function (list) { + return sanitizeList(list, extracter); + }); + } else { + return Optional.none(); + } + }; + }; + var sanitize = function (list) { + return sanitizer(getValue)(list); + }; + var isGroup = function (item) { + return Object.prototype.hasOwnProperty.call(item, 'items'); + }; + var findEntryDelegate = function (list, value) { + return findMap(list, function (item) { + if (isGroup(item)) { + return findEntryDelegate(item.items, value); + } else if (item.value === value) { + return Optional.some(item); + } else { + return Optional.none(); + } + }); + }; + var findEntry = function (optList, value) { + return optList.bind(function (list) { + return findEntryDelegate(list, value); + }); + }; + var ListUtils = { + sanitizer: sanitizer, + sanitize: sanitize, + findEntry: findEntry + }; + + var pathJoin = function (path1, path2) { + if (path1) { + return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, ''); + } + return path2; + }; + function Uploader (settings) { + var defaultHandler = function (blobInfo, success, failure, progress) { + var xhr = new XMLHttpRequest(); + xhr.open('POST', settings.url); + xhr.withCredentials = settings.credentials; + xhr.upload.onprogress = function (e) { + progress(e.loaded / e.total * 100); + }; + xhr.onerror = function () { + failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status); + }; + xhr.onload = function () { + if (xhr.status < 200 || xhr.status >= 300) { + failure('HTTP Error: ' + xhr.status); + return; + } + var json = JSON.parse(xhr.responseText); + if (!json || typeof json.location !== 'string') { + failure('Invalid JSON: ' + xhr.responseText); + return; + } + success(pathJoin(settings.basePath, json.location)); + }; + var formData = new FormData(); + formData.append('file', blobInfo.blob(), blobInfo.filename()); + xhr.send(formData); + }; + var uploadBlob = function (blobInfo, handler) { + return new global$2(function (resolve, reject) { + try { + handler(blobInfo, resolve, reject, noop); + } catch (ex) { + reject(ex.message); + } + }); + }; + var isDefaultHandler = function (handler) { + return handler === defaultHandler; + }; + var upload = function (blobInfo) { + return !settings.url && isDefaultHandler(settings.handler) ? global$2.reject('Upload url missing from the settings.') : uploadBlob(blobInfo, settings.handler); + }; + settings = global$4.extend({ + credentials: false, + handler: defaultHandler + }, settings); + return { upload: upload }; + } + + var makeTab = function (_info) { + return { + title: 'Advanced', + name: 'advanced', + items: [ + { + type: 'input', + label: 'Style', + name: 'style' + }, + { + type: 'grid', + columns: 2, + items: [ + { + type: 'input', + label: 'Vertical space', + name: 'vspace', + inputMode: 'numeric' + }, + { + type: 'input', + label: 'Horizontal space', + name: 'hspace', + inputMode: 'numeric' + }, + { + type: 'input', + label: 'Border width', + name: 'border', + inputMode: 'numeric' + }, + { + type: 'listbox', + name: 'borderstyle', + label: 'Border style', + items: [ + { + text: 'Select...', + value: '' + }, + { + text: 'Solid', + value: 'solid' + }, + { + text: 'Dotted', + value: 'dotted' + }, + { + text: 'Dashed', + value: 'dashed' + }, + { + text: 'Double', + value: 'double' + }, + { + text: 'Groove', + value: 'groove' + }, + { + text: 'Ridge', + value: 'ridge' + }, + { + text: 'Inset', + value: 'inset' + }, + { + text: 'Outset', + value: 'outset' + }, + { + text: 'None', + value: 'none' + }, + { + text: 'Hidden', + value: 'hidden' + } + ] + } + ] + } + ] + }; + }; + var AdvTab = { makeTab: makeTab }; + + var collect = function (editor) { + var urlListSanitizer = ListUtils.sanitizer(function (item) { + return editor.convertURL(item.value || item.url, 'src'); + }); + var futureImageList = new global$2(function (completer) { + createImageList(editor, function (imageList) { + completer(urlListSanitizer(imageList).map(function (items) { + return flatten([ + [{ + text: 'None', + value: '' + }], + items + ]); + })); + }); + }); + var classList = ListUtils.sanitize(getClassList(editor)); + var hasAdvTab$1 = hasAdvTab(editor); + var hasUploadTab$1 = hasUploadTab(editor); + var hasUploadUrl$1 = hasUploadUrl(editor); + var hasUploadHandler$1 = hasUploadHandler(editor); + var image = readImageDataFromSelection(editor); + var hasDescription$1 = hasDescription(editor); + var hasImageTitle$1 = hasImageTitle(editor); + var hasDimensions$1 = hasDimensions(editor); + var hasImageCaption$1 = hasImageCaption(editor); + var hasAccessibilityOptions = showAccessibilityOptions(editor); + var url = getUploadUrl(editor); + var basePath = getUploadBasePath(editor); + var credentials = getUploadCredentials(editor); + var handler = getUploadHandler(editor); + var automaticUploads = isAutomaticUploadsEnabled(editor); + var prependURL = Optional.some(getPrependUrl(editor)).filter(function (preUrl) { + return isString(preUrl) && preUrl.length > 0; + }); + return futureImageList.then(function (imageList) { + return { + image: image, + imageList: imageList, + classList: classList, + hasAdvTab: hasAdvTab$1, + hasUploadTab: hasUploadTab$1, + hasUploadUrl: hasUploadUrl$1, + hasUploadHandler: hasUploadHandler$1, + hasDescription: hasDescription$1, + hasImageTitle: hasImageTitle$1, + hasDimensions: hasDimensions$1, + hasImageCaption: hasImageCaption$1, + url: url, + basePath: basePath, + credentials: credentials, + handler: handler, + prependURL: prependURL, + hasAccessibilityOptions: hasAccessibilityOptions, + automaticUploads: automaticUploads + }; + }); + }; + + var makeItems = function (info) { + var imageUrl = { + name: 'src', + type: 'urlinput', + filetype: 'image', + label: 'Source' + }; + var imageList = info.imageList.map(function (items) { + return { + name: 'images', + type: 'listbox', + label: 'Image list', + items: items + }; + }); + var imageDescription = { + name: 'alt', + type: 'input', + label: 'Alternative description', + disabled: info.hasAccessibilityOptions && info.image.isDecorative + }; + var imageTitle = { + name: 'title', + type: 'input', + label: 'Image title' + }; + var imageDimensions = { + name: 'dimensions', + type: 'sizeinput' + }; + var isDecorative = { + type: 'label', + label: 'Accessibility', + items: [{ + name: 'isDecorative', + type: 'checkbox', + label: 'Image is decorative' + }] + }; + var classList = info.classList.map(function (items) { + return { + name: 'classes', + type: 'listbox', + label: 'Class', + items: items + }; + }); + var caption = { + type: 'label', + label: 'Caption', + items: [{ + type: 'checkbox', + name: 'caption', + label: 'Show caption' + }] + }; + return flatten([ + [imageUrl], + imageList.toArray(), + info.hasAccessibilityOptions && info.hasDescription ? [isDecorative] : [], + info.hasDescription ? [imageDescription] : [], + info.hasImageTitle ? [imageTitle] : [], + info.hasDimensions ? [imageDimensions] : [], + [{ + type: 'grid', + columns: 2, + items: flatten([ + classList.toArray(), + info.hasImageCaption ? [caption] : [] + ]) + }] + ]); + }; + var makeTab$1 = function (info) { + return { + title: 'General', + name: 'general', + items: makeItems(info) + }; + }; + var MainTab = { + makeTab: makeTab$1, + makeItems: makeItems + }; + + var makeTab$2 = function (_info) { + var items = [{ + type: 'dropzone', + name: 'fileinput' + }]; + return { + title: 'Upload', + name: 'upload', + items: items + }; + }; + var UploadTab = { makeTab: makeTab$2 }; + + var createState = function (info) { + return { + prevImage: ListUtils.findEntry(info.imageList, info.image.src), + prevAlt: info.image.alt, + open: true + }; + }; + var fromImageData = function (image) { + return { + src: { + value: image.src, + meta: {} + }, + images: image.src, + alt: image.alt, + title: image.title, + dimensions: { + width: image.width, + height: image.height + }, + classes: image.class, + caption: image.caption, + style: image.style, + vspace: image.vspace, + border: image.border, + hspace: image.hspace, + borderstyle: image.borderStyle, + fileinput: [], + isDecorative: image.isDecorative + }; + }; + var toImageData = function (data, removeEmptyAlt) { + return { + src: data.src.value, + alt: data.alt.length === 0 && removeEmptyAlt ? null : data.alt, + title: data.title, + width: data.dimensions.width, + height: data.dimensions.height, + class: data.classes, + style: data.style, + caption: data.caption, + hspace: data.hspace, + vspace: data.vspace, + border: data.border, + borderStyle: data.borderstyle, + isDecorative: data.isDecorative + }; + }; + var addPrependUrl2 = function (info, srcURL) { + if (!/^(?:[a-zA-Z]+:)?\/\//.test(srcURL)) { + return info.prependURL.bind(function (prependUrl) { + if (srcURL.substring(0, prependUrl.length) !== prependUrl) { + return Optional.some(prependUrl + srcURL); + } + return Optional.none(); + }); + } + return Optional.none(); + }; + var addPrependUrl = function (info, api) { + var data = api.getData(); + addPrependUrl2(info, data.src.value).each(function (srcURL) { + api.setData({ + src: { + value: srcURL, + meta: data.src.meta + } + }); + }); + }; + var formFillFromMeta2 = function (info, data, meta) { + if (info.hasDescription && isString(meta.alt)) { + data.alt = meta.alt; + } + if (info.hasAccessibilityOptions) { + data.isDecorative = meta.isDecorative || data.isDecorative || false; + } + if (info.hasImageTitle && isString(meta.title)) { + data.title = meta.title; + } + if (info.hasDimensions) { + if (isString(meta.width)) { + data.dimensions.width = meta.width; + } + if (isString(meta.height)) { + data.dimensions.height = meta.height; + } + } + if (isString(meta.class)) { + ListUtils.findEntry(info.classList, meta.class).each(function (entry) { + data.classes = entry.value; + }); + } + if (info.hasImageCaption) { + if (isBoolean(meta.caption)) { + data.caption = meta.caption; + } + } + if (info.hasAdvTab) { + if (isString(meta.style)) { + data.style = meta.style; + } + if (isString(meta.vspace)) { + data.vspace = meta.vspace; + } + if (isString(meta.border)) { + data.border = meta.border; + } + if (isString(meta.hspace)) { + data.hspace = meta.hspace; + } + if (isString(meta.borderstyle)) { + data.borderstyle = meta.borderstyle; + } + } + }; + var formFillFromMeta = function (info, api) { + var data = api.getData(); + var meta = data.src.meta; + if (meta !== undefined) { + var newData = deepMerge({}, data); + formFillFromMeta2(info, newData, meta); + api.setData(newData); + } + }; + var calculateImageSize = function (helpers, info, state, api) { + var data = api.getData(); + var url = data.src.value; + var meta = data.src.meta || {}; + if (!meta.width && !meta.height && info.hasDimensions) { + helpers.imageSize(url).then(function (size) { + if (state.open) { + api.setData({ dimensions: size }); + } + }); + } + }; + var updateImagesDropdown = function (info, state, api) { + var data = api.getData(); + var image = ListUtils.findEntry(info.imageList, data.src.value); + state.prevImage = image; + api.setData({ + images: image.map(function (entry) { + return entry.value; + }).getOr('') + }); + }; + var changeSrc = function (helpers, info, state, api) { + addPrependUrl(info, api); + formFillFromMeta(info, api); + calculateImageSize(helpers, info, state, api); + updateImagesDropdown(info, state, api); + }; + var changeImages = function (helpers, info, state, api) { + var data = api.getData(); + var image = ListUtils.findEntry(info.imageList, data.images); + image.each(function (img) { + var updateAlt = data.alt === '' || state.prevImage.map(function (image) { + return image.text === data.alt; + }).getOr(false); + if (updateAlt) { + if (img.value === '') { + api.setData({ + src: img, + alt: state.prevAlt + }); + } else { + api.setData({ + src: img, + alt: img.text + }); + } + } else { + api.setData({ src: img }); + } + }); + state.prevImage = image; + changeSrc(helpers, info, state, api); + }; + var calcVSpace = function (css) { + var matchingTopBottom = css['margin-top'] && css['margin-bottom'] && css['margin-top'] === css['margin-bottom']; + return matchingTopBottom ? removePixelSuffix(String(css['margin-top'])) : ''; + }; + var calcHSpace = function (css) { + var matchingLeftRight = css['margin-right'] && css['margin-left'] && css['margin-right'] === css['margin-left']; + return matchingLeftRight ? removePixelSuffix(String(css['margin-right'])) : ''; + }; + var calcBorderWidth = function (css) { + return css['border-width'] ? removePixelSuffix(String(css['border-width'])) : ''; + }; + var calcBorderStyle = function (css) { + return css['border-style'] ? String(css['border-style']) : ''; + }; + var calcStyle = function (parseStyle, serializeStyle, css) { + return serializeStyle(parseStyle(serializeStyle(css))); + }; + var changeStyle2 = function (parseStyle, serializeStyle, data) { + var css = mergeMargins(parseStyle(data.style)); + var dataCopy = deepMerge({}, data); + dataCopy.vspace = calcVSpace(css); + dataCopy.hspace = calcHSpace(css); + dataCopy.border = calcBorderWidth(css); + dataCopy.borderstyle = calcBorderStyle(css); + dataCopy.style = calcStyle(parseStyle, serializeStyle, css); + return dataCopy; + }; + var changeStyle = function (helpers, api) { + var data = api.getData(); + var newData = changeStyle2(helpers.parseStyle, helpers.serializeStyle, data); + api.setData(newData); + }; + var changeAStyle = function (helpers, info, api) { + var data = deepMerge(fromImageData(info.image), api.getData()); + var style = getStyleValue(helpers.normalizeCss, toImageData(data, false)); + api.setData({ style: style }); + }; + var changeFileInput = function (helpers, info, state, api) { + var data = api.getData(); + api.block('Uploading image'); + head(data.fileinput).fold(function () { + api.unblock(); + }, function (file) { + var blobUri = URL.createObjectURL(file); + var uploader = Uploader({ + url: info.url, + basePath: info.basePath, + credentials: info.credentials, + handler: info.handler + }); + var finalize = function () { + api.unblock(); + URL.revokeObjectURL(blobUri); + }; + var updateSrcAndSwitchTab = function (url) { + api.setData({ + src: { + value: url, + meta: {} + } + }); + api.showTab('general'); + changeSrc(helpers, info, state, api); + }; + blobToDataUri(file).then(function (dataUrl) { + var blobInfo = helpers.createBlobCache(file, blobUri, dataUrl); + if (info.automaticUploads) { + uploader.upload(blobInfo).then(function (url) { + updateSrcAndSwitchTab(url); + finalize(); + }).catch(function (err) { + finalize(); + helpers.alertErr(err); + }); + } else { + helpers.addToBlobCache(blobInfo); + updateSrcAndSwitchTab(blobInfo.blobUri()); + api.unblock(); + } + }); + }); + }; + var changeHandler = function (helpers, info, state) { + return function (api, evt) { + if (evt.name === 'src') { + changeSrc(helpers, info, state, api); + } else if (evt.name === 'images') { + changeImages(helpers, info, state, api); + } else if (evt.name === 'alt') { + state.prevAlt = api.getData().alt; + } else if (evt.name === 'style') { + changeStyle(helpers, api); + } else if (evt.name === 'vspace' || evt.name === 'hspace' || evt.name === 'border' || evt.name === 'borderstyle') { + changeAStyle(helpers, info, api); + } else if (evt.name === 'fileinput') { + changeFileInput(helpers, info, state, api); + } else if (evt.name === 'isDecorative') { + if (api.getData().isDecorative) { + api.disable('alt'); + } else { + api.enable('alt'); + } + } + }; + }; + var closeHandler = function (state) { + return function () { + state.open = false; + }; + }; + var makeDialogBody = function (info) { + if (info.hasAdvTab || info.hasUploadUrl || info.hasUploadHandler) { + var tabPanel = { + type: 'tabpanel', + tabs: flatten([ + [MainTab.makeTab(info)], + info.hasAdvTab ? [AdvTab.makeTab(info)] : [], + info.hasUploadTab && (info.hasUploadUrl || info.hasUploadHandler) ? [UploadTab.makeTab(info)] : [] + ]) + }; + return tabPanel; + } else { + var panel = { + type: 'panel', + items: MainTab.makeItems(info) + }; + return panel; + } + }; + var makeDialog = function (helpers) { + return function (info) { + var state = createState(info); + return { + title: 'Insert/Edit Image', + size: 'normal', + body: makeDialogBody(info), + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true + } + ], + initialData: fromImageData(info.image), + onSubmit: helpers.onSubmit(info), + onChange: changeHandler(helpers, info, state), + onClose: closeHandler(state) + }; + }; + }; + var submitHandler = function (editor) { + return function (info) { + return function (api) { + var data = deepMerge(fromImageData(info.image), api.getData()); + editor.execCommand('mceUpdateImage', false, toImageData(data, info.hasAccessibilityOptions)); + editor.editorUpload.uploadImagesAuto(); + api.close(); + }; + }; + }; + var imageSize = function (editor) { + return function (url) { + return getImageSize(editor.documentBaseURI.toAbsolute(url)).then(function (dimensions) { + return { + width: String(dimensions.width), + height: String(dimensions.height) + }; + }); + }; + }; + var createBlobCache = function (editor) { + return function (file, blobUri, dataUrl) { + return editor.editorUpload.blobCache.create({ + blob: file, + blobUri: blobUri, + name: file.name ? file.name.replace(/\.[^\.]+$/, '') : null, + filename: file.name, + base64: dataUrl.split(',')[1] + }); + }; + }; + var addToBlobCache = function (editor) { + return function (blobInfo) { + editor.editorUpload.blobCache.add(blobInfo); + }; + }; + var alertErr = function (editor) { + return function (message) { + editor.windowManager.alert(message); + }; + }; + var normalizeCss$1 = function (editor) { + return function (cssText) { + return normalizeCss(editor, cssText); + }; + }; + var parseStyle = function (editor) { + return function (cssText) { + return editor.dom.parseStyle(cssText); + }; + }; + var serializeStyle = function (editor) { + return function (stylesArg, name) { + return editor.dom.serializeStyle(stylesArg, name); + }; + }; + var Dialog = function (editor) { + var helpers = { + onSubmit: submitHandler(editor), + imageSize: imageSize(editor), + addToBlobCache: addToBlobCache(editor), + createBlobCache: createBlobCache(editor), + alertErr: alertErr(editor), + normalizeCss: normalizeCss$1(editor), + parseStyle: parseStyle(editor), + serializeStyle: serializeStyle(editor) + }; + var open = function () { + collect(editor).then(makeDialog(helpers)).then(editor.windowManager.open); + }; + return { open: open }; + }; + + var register = function (editor) { + editor.addCommand('mceImage', Dialog(editor).open); + editor.addCommand('mceUpdateImage', function (_ui, data) { + editor.undoManager.transact(function () { + return insertOrUpdateImage(editor, data); + }); + }); + }; + + var hasImageClass = function (node) { + var className = node.attr('class'); + return className && /\bimage\b/.test(className); + }; + var toggleContentEditableState = function (state) { + return function (nodes) { + var i = nodes.length; + var toggleContentEditable = function (node) { + node.attr('contenteditable', state ? 'true' : null); + }; + while (i--) { + var node = nodes[i]; + if (hasImageClass(node)) { + node.attr('contenteditable', state ? 'false' : null); + global$4.each(node.getAll('figcaption'), toggleContentEditable); + } + } + }; + }; + var setup = function (editor) { + editor.on('PreInit', function () { + editor.parser.addNodeFilter('figure', toggleContentEditableState(true)); + editor.serializer.addNodeFilter('figure', toggleContentEditableState(false)); + }); + }; + + var register$1 = function (editor) { + editor.ui.registry.addToggleButton('image', { + icon: 'image', + tooltip: 'Insert/edit image', + onAction: Dialog(editor).open, + onSetup: function (buttonApi) { + return editor.selection.selectorChangedWithUnbind('img:not([data-mce-object],[data-mce-placeholder]),figure.image', buttonApi.setActive).unbind; + } + }); + editor.ui.registry.addMenuItem('image', { + icon: 'image', + text: 'Image...', + onAction: Dialog(editor).open + }); + editor.ui.registry.addContextMenu('image', { + update: function (element) { + return isFigure(element) || isImage(element) && !isPlaceholderImage(element) ? ['image'] : []; + } + }); + }; + + function Plugin () { + global.add('image', function (editor) { + setup(editor); + register$1(editor); + register(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/image/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/image/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..7b454364ab5f282caedd5935be003b1d99c8dfe9 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/image/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var t,e,n,r,o,a=tinymce.util.Tools.resolve("tinymce.PluginManager"),c=function(){return(c=Object.assign||function(e){for(var t,n=1,r=arguments.length;n 1) { + console.error('HTML does not have a single root node', html); + throw new Error('HTML must have a single root node'); + } + return fromDom(div.childNodes[0]); + }; + var fromTag = function (tag, scope) { + var doc = scope || document; + var node = doc.createElement(tag); + return fromDom(node); + }; + var fromText = function (text, scope) { + var doc = scope || document; + var node = doc.createTextNode(text); + return fromDom(node); + }; + var fromDom = function (node) { + if (node === null || node === undefined) { + throw new Error('Node cannot be null or undefined'); + } + return { dom: node }; + }; + var fromPoint = function (docElm, x, y) { + return Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom); + }; + var SugarElement = { + fromHtml: fromHtml, + fromTag: fromTag, + fromText: fromText, + fromDom: fromDom, + fromPoint: fromPoint + }; + + var is = function (element, selector) { + var dom = element.dom; + if (dom.nodeType !== ELEMENT) { + return false; + } else { + var elem = dom; + if (elem.matches !== undefined) { + return elem.matches(selector); + } else if (elem.msMatchesSelector !== undefined) { + return elem.msMatchesSelector(selector); + } else if (elem.webkitMatchesSelector !== undefined) { + return elem.webkitMatchesSelector(selector); + } else if (elem.mozMatchesSelector !== undefined) { + return elem.mozMatchesSelector(selector); + } else { + throw new Error('Browser lacks native selectors'); + } + } + }; + + var Global = typeof window !== 'undefined' ? window : Function('return this;')(); + + var child = function (scope, predicate) { + var pred = function (node) { + return predicate(SugarElement.fromDom(node)); + }; + var result = find(scope.dom.childNodes, pred); + return result.map(SugarElement.fromDom); + }; + + var child$1 = function (scope, selector) { + return child(scope, function (e) { + return is(e, selector); + }); + }; + + var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay'); + + var global$3 = tinymce.util.Tools.resolve('tinymce.util.Promise'); + + var global$4 = tinymce.util.Tools.resolve('tinymce.util.URI'); + + var getToolbarItems = function (editor) { + return editor.getParam('imagetools_toolbar', 'rotateleft rotateright flipv fliph editimage imageoptions'); + }; + var getProxyUrl = function (editor) { + return editor.getParam('imagetools_proxy'); + }; + var getCorsHosts = function (editor) { + return editor.getParam('imagetools_cors_hosts', [], 'string[]'); + }; + var getCredentialsHosts = function (editor) { + return editor.getParam('imagetools_credentials_hosts', [], 'string[]'); + }; + var getFetchImage = function (editor) { + return Optional.from(editor.getParam('imagetools_fetch_image', null, 'function')); + }; + var getApiKey = function (editor) { + return editor.getParam('api_key', editor.getParam('imagetools_api_key', '', 'string'), 'string'); + }; + var getUploadTimeout = function (editor) { + return editor.getParam('images_upload_timeout', 30000, 'number'); + }; + var shouldReuseFilename = function (editor) { + return editor.getParam('images_reuse_filename', false, 'boolean'); + }; + + function getImageSize(img) { + var width, height; + function isPxValue(value) { + return /^[0-9\.]+px$/.test(value); + } + width = img.style.width; + height = img.style.height; + if (width || height) { + if (isPxValue(width) && isPxValue(height)) { + return { + w: parseInt(width, 10), + h: parseInt(height, 10) + }; + } + return null; + } + width = img.width; + height = img.height; + if (width && height) { + return { + w: parseInt(width, 10), + h: parseInt(height, 10) + }; + } + return null; + } + function setImageSize(img, size) { + var width, height; + if (size) { + width = img.style.width; + height = img.style.height; + if (width || height) { + img.style.width = size.w + 'px'; + img.style.height = size.h + 'px'; + img.removeAttribute('data-mce-style'); + } + width = img.width; + height = img.height; + if (width || height) { + img.setAttribute('width', String(size.w)); + img.setAttribute('height', String(size.h)); + } + } + } + function getNaturalImageSize(img) { + return { + w: img.naturalWidth, + h: img.naturalHeight + }; + } + + var count = 0; + var getFigureImg = function (elem) { + return child$1(SugarElement.fromDom(elem), 'img'); + }; + var isFigure = function (editor, elem) { + return editor.dom.is(elem, 'figure'); + }; + var isImage = function (editor, imgNode) { + return editor.dom.is(imgNode, 'img:not([data-mce-object],[data-mce-placeholder])'); + }; + var getEditableImage = function (editor, node) { + var isEditable = function (imgNode) { + return isImage(editor, imgNode) && (isLocalImage(editor, imgNode) || isCorsImage(editor, imgNode) || isNonNullable(getProxyUrl(editor))); + }; + if (isFigure(editor, node)) { + return getFigureImg(node).bind(function (img) { + return isEditable(img.dom) ? Optional.some(img.dom) : Optional.none(); + }); + } else { + return isEditable(node) ? Optional.some(node) : Optional.none(); + } + }; + var displayError = function (editor, error) { + editor.notificationManager.open({ + text: error, + type: 'error' + }); + }; + var getSelectedImage = function (editor) { + var elem = editor.selection.getNode(); + var figureElm = editor.dom.getParent(elem, 'figure.image'); + if (figureElm !== null && isFigure(editor, figureElm)) { + return getFigureImg(figureElm); + } else if (isImage(editor, elem)) { + return Optional.some(SugarElement.fromDom(elem)); + } else { + return Optional.none(); + } + }; + var extractFilename = function (editor, url, group) { + var m = url.match(/(?:\/|^)(([^\/\?]+)\.(?:[a-z0-9.]+))(?:\?|$)/i); + return isNonNullable(m) ? editor.dom.encode(m[group]) : null; + }; + var createId = function () { + return 'imagetools' + count++; + }; + var isLocalImage = function (editor, img) { + var url = img.src; + return url.indexOf('data:') === 0 || url.indexOf('blob:') === 0 || new global$4(url).host === editor.documentBaseURI.host; + }; + var isCorsImage = function (editor, img) { + return global$1.inArray(getCorsHosts(editor), new global$4(img.src).host) !== -1; + }; + var isCorsWithCredentialsImage = function (editor, img) { + return global$1.inArray(getCredentialsHosts(editor), new global$4(img.src).host) !== -1; + }; + var defaultFetchImage = function (editor, img) { + if (isCorsImage(editor, img)) { + return getUrl(img.src, null, isCorsWithCredentialsImage(editor, img)); + } + if (!isLocalImage(editor, img)) { + var proxyUrl = getProxyUrl(editor); + var src = proxyUrl + (proxyUrl.indexOf('?') === -1 ? '?' : '&') + 'url=' + encodeURIComponent(img.src); + var apiKey = getApiKey(editor); + return getUrl(src, apiKey, false); + } + return imageToBlob$1(img); + }; + var imageToBlob$2 = function (editor, img) { + return getFetchImage(editor).fold(function () { + return defaultFetchImage(editor, img); + }, function (customFetchImage) { + return customFetchImage(img); + }); + }; + var findBlob = function (editor, img) { + var blobInfo = editor.editorUpload.blobCache.getByUri(img.src); + if (blobInfo) { + return global$3.resolve(blobInfo.blob()); + } + return imageToBlob$2(editor, img); + }; + var startTimedUpload = function (editor, imageUploadTimerState) { + var imageUploadTimer = global$2.setEditorTimeout(editor, function () { + editor.editorUpload.uploadImagesAuto(); + }, getUploadTimeout(editor)); + imageUploadTimerState.set(imageUploadTimer); + }; + var cancelTimedUpload = function (imageUploadTimerState) { + global$2.clearTimeout(imageUploadTimerState.get()); + }; + var updateSelectedImage = function (editor, origBlob, ir, uploadImmediately, imageUploadTimerState, selectedImage, size) { + return ir.toBlob().then(function (blob) { + var uri, name, filename, blobInfo; + var blobCache = editor.editorUpload.blobCache; + uri = selectedImage.src; + var useFilename = origBlob.type === blob.type; + if (shouldReuseFilename(editor)) { + blobInfo = blobCache.getByUri(uri); + if (isNonNullable(blobInfo)) { + uri = blobInfo.uri(); + name = blobInfo.name(); + filename = blobInfo.filename(); + } else { + name = extractFilename(editor, uri, 2); + filename = extractFilename(editor, uri, 1); + } + } + blobInfo = blobCache.create({ + id: createId(), + blob: blob, + base64: ir.toBase64(), + uri: uri, + name: name, + filename: useFilename ? filename : undefined + }); + blobCache.add(blobInfo); + editor.undoManager.transact(function () { + function imageLoadedHandler() { + editor.$(selectedImage).off('load', imageLoadedHandler); + editor.nodeChanged(); + if (uploadImmediately) { + editor.editorUpload.uploadImagesAuto(); + } else { + cancelTimedUpload(imageUploadTimerState); + startTimedUpload(editor, imageUploadTimerState); + } + } + editor.$(selectedImage).on('load', imageLoadedHandler); + if (size) { + editor.$(selectedImage).attr({ + width: size.w, + height: size.h + }); + } + editor.$(selectedImage).attr({ src: blobInfo.blobUri() }).removeAttr('data-mce-src'); + }); + return blobInfo; + }); + }; + var selectedImageOperation = function (editor, imageUploadTimerState, fn, size) { + return function () { + var imgOpt = getSelectedImage(editor); + return imgOpt.fold(function () { + displayError(editor, 'Could not find selected image'); + }, function (img) { + return editor._scanForImages().then(function () { + return findBlob(editor, img.dom); + }).then(function (blob) { + return blobToImageResult(blob).then(fn).then(function (imageResult) { + return updateSelectedImage(editor, blob, imageResult, false, imageUploadTimerState, img.dom, size); + }); + }).catch(function (error) { + displayError(editor, error); + }); + }); + }; + }; + var rotate$2 = function (editor, imageUploadTimerState, angle) { + return function () { + var imgOpt = getSelectedImage(editor); + var flippedSize = imgOpt.fold(function () { + return null; + }, function (img) { + var size = getImageSize(img.dom); + return size ? { + w: size.h, + h: size.w + } : null; + }); + return selectedImageOperation(editor, imageUploadTimerState, function (imageResult) { + return rotate$1(imageResult, angle); + }, flippedSize)(); + }; + }; + var flip$2 = function (editor, imageUploadTimerState, axis) { + return function () { + return selectedImageOperation(editor, imageUploadTimerState, function (imageResult) { + return flip$1(imageResult, axis); + })(); + }; + }; + var handleDialogBlob = function (editor, imageUploadTimerState, img, originalSize, blob) { + return blobToImage$1(blob).then(function (newImage) { + var newSize = getNaturalImageSize(newImage); + if (originalSize.w !== newSize.w || originalSize.h !== newSize.h) { + if (getImageSize(img)) { + setImageSize(img, newSize); + } + } + URL.revokeObjectURL(newImage.src); + return blob; + }).then(blobToImageResult).then(function (imageResult) { + return updateSelectedImage(editor, blob, imageResult, true, imageUploadTimerState, img); + }).catch(function () { + }); + }; + + var saveState = 'save-state'; + var disable = 'disable'; + var enable = 'enable'; + + var createState = function (blob) { + return { + blob: blob, + url: URL.createObjectURL(blob) + }; + }; + var makeOpen = function (editor, imageUploadTimerState) { + return function () { + var getLoadedSpec = function (currentState) { + return { + title: 'Edit Image', + size: 'large', + body: { + type: 'panel', + items: [{ + type: 'imagetools', + name: 'imagetools', + label: 'Edit Image', + currentState: currentState + }] + }, + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true, + disabled: true + } + ], + onSubmit: function (api) { + var blob = api.getData().imagetools.blob; + originalImgOpt.each(function (originalImg) { + originalSizeOpt.each(function (originalSize) { + handleDialogBlob(editor, imageUploadTimerState, originalImg.dom, originalSize, blob); + }); + }); + api.close(); + }, + onCancel: function () { + }, + onAction: function (api, details) { + switch (details.name) { + case saveState: + if (details.value) { + api.enable('save'); + } else { + api.disable('save'); + } + break; + case disable: + api.disable('save'); + api.disable('cancel'); + break; + case enable: + api.enable('cancel'); + break; + } + } + }; + }; + var originalImgOpt = getSelectedImage(editor); + var originalSizeOpt = originalImgOpt.map(function (origImg) { + return getNaturalImageSize(origImg.dom); + }); + originalImgOpt.each(function (img) { + getEditableImage(editor, img.dom).each(function (_) { + findBlob(editor, img.dom).then(function (blob) { + var state = createState(blob); + editor.windowManager.open(getLoadedSpec(state)); + }); + }); + }); + }; + }; + + var register = function (editor, imageUploadTimerState) { + global$1.each({ + mceImageRotateLeft: rotate$2(editor, imageUploadTimerState, -90), + mceImageRotateRight: rotate$2(editor, imageUploadTimerState, 90), + mceImageFlipVertical: flip$2(editor, imageUploadTimerState, 'v'), + mceImageFlipHorizontal: flip$2(editor, imageUploadTimerState, 'h'), + mceEditImage: makeOpen(editor, imageUploadTimerState) + }, function (fn, cmd) { + editor.addCommand(cmd, fn); + }); + }; + + var setup = function (editor, imageUploadTimerState, lastSelectedImageState) { + editor.on('NodeChange', function (e) { + var lastSelectedImage = lastSelectedImageState.get(); + var selectedImage = getEditableImage(editor, e.element); + if (lastSelectedImage && !selectedImage.exists(function (img) { + return lastSelectedImage.src === img.src; + })) { + cancelTimedUpload(imageUploadTimerState); + editor.editorUpload.uploadImagesAuto(); + lastSelectedImageState.set(null); + } + selectedImage.each(lastSelectedImageState.set); + }); + }; + + var register$1 = function (editor) { + var cmd = function (command) { + return function () { + return editor.execCommand(command); + }; + }; + editor.ui.registry.addButton('rotateleft', { + tooltip: 'Rotate counterclockwise', + icon: 'rotate-left', + onAction: cmd('mceImageRotateLeft') + }); + editor.ui.registry.addButton('rotateright', { + tooltip: 'Rotate clockwise', + icon: 'rotate-right', + onAction: cmd('mceImageRotateRight') + }); + editor.ui.registry.addButton('flipv', { + tooltip: 'Flip vertically', + icon: 'flip-vertically', + onAction: cmd('mceImageFlipVertical') + }); + editor.ui.registry.addButton('fliph', { + tooltip: 'Flip horizontally', + icon: 'flip-horizontally', + onAction: cmd('mceImageFlipHorizontal') + }); + editor.ui.registry.addButton('editimage', { + tooltip: 'Edit image', + icon: 'edit-image', + onAction: cmd('mceEditImage'), + onSetup: function (buttonApi) { + var setDisabled = function () { + var disabled = getSelectedImage(editor).forall(function (element) { + return getEditableImage(editor, element.dom).isNone(); + }); + buttonApi.setDisabled(disabled); + }; + editor.on('NodeChange', setDisabled); + return function () { + editor.off('NodeChange', setDisabled); + }; + } + }); + editor.ui.registry.addButton('imageoptions', { + tooltip: 'Image options', + icon: 'image', + onAction: cmd('mceImage') + }); + editor.ui.registry.addContextMenu('imagetools', { + update: function (element) { + return getEditableImage(editor, element).fold(function () { + return []; + }, function (_) { + return [{ + text: 'Edit image', + icon: 'edit-image', + onAction: cmd('mceEditImage') + }]; + }); + } + }); + }; + + var register$2 = function (editor) { + editor.ui.registry.addContextToolbar('imagetools', { + items: getToolbarItems(editor), + predicate: function (elem) { + return getEditableImage(editor, elem).isSome(); + }, + position: 'node', + scope: 'node' + }); + }; + + function Plugin () { + global.add('imagetools', function (editor) { + var imageUploadTimerState = Cell(0); + var lastSelectedImageState = Cell(null); + register(editor, imageUploadTimerState); + register$1(editor); + register$2(editor); + setup(editor, imageUploadTimerState, lastSelectedImageState); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/imagetools/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/imagetools/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..8e4fb2535046f51e858e147941b114f19d36a8f2 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/imagetools/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var t,e,n,r,l=function(t){var e=t;return{get:function(){return e},set:function(t){e=t}}},o=tinymce.util.Tools.resolve("tinymce.PluginManager"),d=tinymce.util.Tools.resolve("tinymce.util.Tools"),i=function(){},u=function(t){return function(){return t}},a=u(!1),c=u(!0),f=function(){return s},s=(t=function(t){return t.isNone()},{fold:function(t,e){return t()},is:a,isSome:a,isNone:c,getOr:n=function(t){return t},getOrThunk:e=function(t){return t()},getOrDie:function(t){throw new Error(t||"error: getOrDie called on none.")},getOrNull:u(null),getOrUndefined:u(undefined),or:n,orThunk:e,map:f,each:i,bind:f,exists:a,forall:c,filter:f,equals:t,equals_:t,toArray:function(){return[]},toString:u("none()")}),m=function(n){var t=u(n),e=function(){return o},r=function(t){return t(n)},o={fold:function(t,e){return e(n)},is:function(t){return n===t},isSome:c,isNone:a,getOr:t,getOrThunk:t,getOrDie:t,getOrNull:t,getOrUndefined:t,or:e,orThunk:e,map:function(t){return m(t(n))},each:function(t){t(n)},bind:r,exists:r,forall:r,filter:function(t){return t(n)?o:s},toArray:function(){return[n]},toString:function(){return"some("+n+")"},equals:function(t){return t.is(n)},equals_:function(t,e){return t.fold(a,function(t){return e(n,t)})}};return o},g={some:m,none:f,from:function(t){return null===t||t===undefined?s:m(t)}},h=function(t){return!(null===(e=t)||e===undefined);var e},v=(r="function",function(t){return typeof t===r});function p(t,e){return b(document.createElement("canvas"),t,e)}function y(t){var e=p(t.width,t.height);return w(e).drawImage(t,0,0),e}function w(t){return t.getContext("2d")}function b(t,e,n){return t.width=e,t.height=n,t}var I,T,_,R,U=window.Promise?window.Promise:(I=function(t){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof t)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],C(t,A(E,this),A(L,this))},T=window,_=I.immediateFn||"function"==typeof T.setImmediate&&T.setImmediate||function(t){setTimeout(t,1)},R=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)},I.prototype["catch"]=function(t){return this.then(null,t)},I.prototype.then=function(n,r){var o=this;return new I(function(t,e){x.call(o,new k(n,r,t,e))})},I.all=function(){for(var t=[],e=0;e 0) { + global$4.each(selectorGroups, function (group) { + var menuItem = processSelector(selector, group); + if (menuItem) { + model.addItemToGroup(group.title, menuItem); + } + }); + } else { + var menuItem = processSelector(selector, null); + if (menuItem) { + model.addItem(menuItem); + } + } + } + } + }); + var items = model.toFormats(); + editor.fire('addStyleModifications', { + items: items, + replace: !shouldAppend(editor) + }); + }); + }; + + var get = function (editor) { + var convertSelectorToFormat = function (selectorText) { + return defaultConvertSelectorToFormat(editor, selectorText); + }; + return { convertSelectorToFormat: convertSelectorToFormat }; + }; + + function Plugin () { + global.add('importcss', function (editor) { + setup(editor); + return get(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/importcss/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/importcss/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..1c9dab9316c12688ee69b954a7354df5d3965341 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/importcss/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var n,t=tinymce.util.Tools.resolve("tinymce.PluginManager"),v=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),f=tinymce.util.Tools.resolve("tinymce.EditorManager"),m=tinymce.util.Tools.resolve("tinymce.Env"),h=tinymce.util.Tools.resolve("tinymce.util.Tools"),d=function(t){return t.getParam("importcss_selector_converter")},o=(n="array",function(t){return r=typeof(e=t),(null===e?"null":"object"==r&&(Array.prototype.isPrototypeOf(e)||e.constructor&&"Array"===e.constructor.name)?"array":"object"==r&&(String.prototype.isPrototypeOf(e)||e.constructor&&"String"===e.constructor.name)?"string":r)===n;var e,r}),i=Array.prototype.push,l=function(t,e){return function(t){for(var e=[],r=0,n=t.length;r'); + + var stateSelectorAdapter = function (editor, selector) { + return function (buttonApi) { + return editor.selection.selectorChangedWithUnbind(selector.join(','), buttonApi.setActive).unbind; + }; + }; + + editor.ui.registry.addToggleButton('indent2em', { + icon: 'indent2em', + tooltip: pluginName, + onAction: function () { + doAct(); + }, + onSetup: stateSelectorAdapter(editor, [ + '*[style*="text-indent"]', + '*[data-mce-style*="text-indent"]', + ]) + }); + + editor.ui.registry.addMenuItem('indent2em', { + text: pluginName, + onAction: function() { + doAct(); + } + }); + + editor.addCommand('indent2em', doAct ); + + return { + getMetadata: function () { + return { + name: pluginName, + url: "http://tinymce.ax-z.cn/more-plugins/indent2em.php", + }; + } + }; +}); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/indent2em/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/indent2em/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..b9d8382587e2851bef1a0ef0ae2866ae5b779011 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/indent2em/plugin.min.js @@ -0,0 +1,62 @@ +tinymce.PluginManager.add('indent2em', function(editor, url) { + var pluginName='首行缩进'; + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + var indent2em_val = editor.getParam('indent2em_val', '2em'); + var doAct = function () { + var dom = editor.dom; + var blocks = editor.selection.getSelectedBlocks(); + var act = ''; + global$1.each(blocks, function (block) { + if(act==''){ + act = dom.getStyle(block,'text-indent')==indent2em_val ? 'remove' : 'add'; + } + if( act=='add' ){ + dom.setStyle(block, 'text-indent', indent2em_val); + }else{ + var style=dom.getAttrib(block,'style'); + var reg = new RegExp('text-indent:[\\s]*' + indent2em_val + ';', 'ig'); + style = style.replace(reg, ''); + dom.setAttrib(block,'style',style); + } + + }); + }; + + editor.ui.registry.getAll().icons.indent2em || editor.ui.registry.addIcon('indent2em',''); + + var stateSelectorAdapter = function (editor, selector) { + return function (buttonApi) { + return editor.selection.selectorChangedWithUnbind(selector.join(','), buttonApi.setActive).unbind; + }; + }; + + editor.ui.registry.addToggleButton('indent2em', { + icon: 'indent2em', + tooltip: pluginName, + onAction: function () { + doAct(); + }, + onSetup: stateSelectorAdapter(editor, [ + '*[style*="text-indent"]', + '*[data-mce-style*="text-indent"]', + ]) + }); + + editor.ui.registry.addMenuItem('indent2em', { + text: pluginName, + onAction: function() { + doAct(); + } + }); + + editor.addCommand('indent2em', doAct ); + + return { + getMetadata: function () { + return { + name: pluginName, + url: "http://tinymce.ax-z.cn/more-plugins/indent2em.php", + }; + } + }; +}); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/insertdatetime/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/insertdatetime/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..b8ae4bc4921ff4803eb76abb2906540b0d4b3cdd --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/insertdatetime/plugin.js @@ -0,0 +1,177 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var getDateFormat = function (editor) { + return editor.getParam('insertdatetime_dateformat', editor.translate('%Y-%m-%d')); + }; + var getTimeFormat = function (editor) { + return editor.getParam('insertdatetime_timeformat', editor.translate('%H:%M:%S')); + }; + var getFormats = function (editor) { + return editor.getParam('insertdatetime_formats', [ + '%H:%M:%S', + '%Y-%m-%d', + '%I:%M:%S %p', + '%D' + ]); + }; + var getDefaultDateTime = function (editor) { + var formats = getFormats(editor); + return formats.length > 0 ? formats[0] : getTimeFormat(editor); + }; + var shouldInsertTimeElement = function (editor) { + return editor.getParam('insertdatetime_element', false); + }; + + var daysShort = 'Sun Mon Tue Wed Thu Fri Sat Sun'.split(' '); + var daysLong = 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday'.split(' '); + var monthsShort = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' '); + var monthsLong = 'January February March April May June July August September October November December'.split(' '); + var addZeros = function (value, len) { + value = '' + value; + if (value.length < len) { + for (var i = 0; i < len - value.length; i++) { + value = '0' + value; + } + } + return value; + }; + var getDateTime = function (editor, fmt, date) { + date = date || new Date(); + fmt = fmt.replace('%D', '%m/%d/%Y'); + fmt = fmt.replace('%r', '%I:%M:%S %p'); + fmt = fmt.replace('%Y', '' + date.getFullYear()); + fmt = fmt.replace('%y', '' + date.getYear()); + fmt = fmt.replace('%m', addZeros(date.getMonth() + 1, 2)); + fmt = fmt.replace('%d', addZeros(date.getDate(), 2)); + fmt = fmt.replace('%H', '' + addZeros(date.getHours(), 2)); + fmt = fmt.replace('%M', '' + addZeros(date.getMinutes(), 2)); + fmt = fmt.replace('%S', '' + addZeros(date.getSeconds(), 2)); + fmt = fmt.replace('%I', '' + ((date.getHours() + 11) % 12 + 1)); + fmt = fmt.replace('%p', '' + (date.getHours() < 12 ? 'AM' : 'PM')); + fmt = fmt.replace('%B', '' + editor.translate(monthsLong[date.getMonth()])); + fmt = fmt.replace('%b', '' + editor.translate(monthsShort[date.getMonth()])); + fmt = fmt.replace('%A', '' + editor.translate(daysLong[date.getDay()])); + fmt = fmt.replace('%a', '' + editor.translate(daysShort[date.getDay()])); + fmt = fmt.replace('%%', '%'); + return fmt; + }; + var updateElement = function (editor, timeElm, computerTime, userTime) { + var newTimeElm = editor.dom.create('time', { datetime: computerTime }, userTime); + timeElm.parentNode.insertBefore(newTimeElm, timeElm); + editor.dom.remove(timeElm); + editor.selection.select(newTimeElm, true); + editor.selection.collapse(false); + }; + var insertDateTime = function (editor, format) { + if (shouldInsertTimeElement(editor)) { + var userTime = getDateTime(editor, format); + var computerTime = void 0; + if (/%[HMSIp]/.test(format)) { + computerTime = getDateTime(editor, '%Y-%m-%dT%H:%M'); + } else { + computerTime = getDateTime(editor, '%Y-%m-%d'); + } + var timeElm = editor.dom.getParent(editor.selection.getStart(), 'time'); + if (timeElm) { + updateElement(editor, timeElm, computerTime, userTime); + } else { + editor.insertContent(''); + } + } else { + editor.insertContent(getDateTime(editor, format)); + } + }; + + var register = function (editor) { + editor.addCommand('mceInsertDate', function () { + insertDateTime(editor, getDateFormat(editor)); + }); + editor.addCommand('mceInsertTime', function () { + insertDateTime(editor, getTimeFormat(editor)); + }); + }; + + var Cell = function (initial) { + var value = initial; + var get = function () { + return value; + }; + var set = function (v) { + value = v; + }; + return { + get: get, + set: set + }; + }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var register$1 = function (editor) { + var formats = getFormats(editor); + var defaultFormat = Cell(getDefaultDateTime(editor)); + editor.ui.registry.addSplitButton('insertdatetime', { + icon: 'insert-time', + tooltip: 'Insert date/time', + select: function (value) { + return value === defaultFormat.get(); + }, + fetch: function (done) { + done(global$1.map(formats, function (format) { + return { + type: 'choiceitem', + text: getDateTime(editor, format), + value: format + }; + })); + }, + onAction: function (_api) { + insertDateTime(editor, defaultFormat.get()); + }, + onItemAction: function (_api, value) { + defaultFormat.set(value); + insertDateTime(editor, value); + } + }); + var makeMenuItemHandler = function (format) { + return function () { + defaultFormat.set(format); + insertDateTime(editor, format); + }; + }; + editor.ui.registry.addNestedMenuItem('insertdatetime', { + icon: 'insert-time', + text: 'Date/time', + getSubmenuItems: function () { + return global$1.map(formats, function (format) { + return { + type: 'menuitem', + text: getDateTime(editor, format), + onAction: makeMenuItemHandler(format) + }; + }); + } + }); + }; + + function Plugin () { + global.add('insertdatetime', function (editor) { + register(editor); + register$1(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/insertdatetime/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/insertdatetime/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..478f4a309121936e8bb3a3e53cb4d10c69d37fa7 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/insertdatetime/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),u=function(e){return e.getParam("insertdatetime_timeformat",e.translate("%H:%M:%S"))},c=function(e){return e.getParam("insertdatetime_formats",["%H:%M:%S","%Y-%m-%d","%I:%M:%S %p","%D"])},r="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),a="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),i="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),o="January February March April May June July August September October November December".split(" "),m=function(e,t){if((e=""+e).length'+n+"")):e.insertContent(s(e,t))},t=function(t){t.addCommand("mceInsertDate",function(){var e;l(t,(e=t).getParam("insertdatetime_dateformat",e.translate("%Y-%m-%d")))}),t.addCommand("mceInsertTime",function(){l(t,u(t))})},d=tinymce.util.Tools.resolve("tinymce.util.Tools"),n=function(n){var e,t,r,a,i=c(n),o=(a=c(r=n),e=0 + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityFormula.html b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityFormula.html new file mode 100644 index 0000000000000000000000000000000000000000..bb73a1054f982c88c638e62ce486b52b9f005ba3 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityFormula.html @@ -0,0 +1,116 @@ + + + + + + + + + + + + +
                                                                                          +
                                                                                          + sorry! Beta版本仅支持IE9及以上版本的浏览器,正式版本将会支持低版本浏览器,谢谢您的关注! +
                                                                                          +
                                                                                          + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/bar-bg.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/bar-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..9dedcc678245832448f459c712e72039d36a2d03 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/bar-bg.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/bar.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/bar.png new file mode 100644 index 0000000000000000000000000000000000000000..f98ded737e1ec99b2daf3b72dd53012f84a6439d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/bar.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/bg.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..214744181ce35a8679e439448df4467814013368 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/bg.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/bottom.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..e3df3d1c4a4291c9f812ac4a35ad4592e1cc671e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/bottom.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/btn.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/btn.png new file mode 100644 index 0000000000000000000000000000000000000000..31c0b52f0662a08b3265963960c222f5e72ddda5 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/btn.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/down.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/down.png new file mode 100644 index 0000000000000000000000000000000000000000..31c0b52f0662a08b3265963960c222f5e72ddda5 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/down.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/top.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/top.png new file mode 100644 index 0000000000000000000000000000000000000000..ecda0704e84186b1f8088cc3a81f0050780b663f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/top.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/up.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/up.png new file mode 100644 index 0000000000000000000000000000000000000000..31c0b52f0662a08b3265963960c222f5e72ddda5 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/custom/up.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/bar-bg.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/bar-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..4f9db6bee66f6ae920fbb433cc772c840a723437 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/bar-bg.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/bar-left.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/bar-left.png new file mode 100644 index 0000000000000000000000000000000000000000..2f8c46ee09d0ff24cf64b524f9ad08792278bfa1 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/bar-left.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/bar-right.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/bar-right.png new file mode 100644 index 0000000000000000000000000000000000000000..9772c54a68519446ef3c4a307c7c6477f390086c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/bar-right.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/thumb-bg.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/thumb-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..450faa2763dc0392583e797081f2ddb2be0c94c3 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/thumb-bg.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/thumb-left.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/thumb-left.png new file mode 100644 index 0000000000000000000000000000000000000000..01b9255a2b102faaf4f70ff8a54aad65b71bcfae Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/thumb-left.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/thumb-right.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/thumb-right.png new file mode 100644 index 0000000000000000000000000000000000000000..f74673a3a57b3b421d8c0310a992e3f73e804980 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/scrollbar/edit/thumb-right.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/aleph.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/aleph.png new file mode 100644 index 0000000000000000000000000000000000000000..fa895d86ab81cf79137307c0eeadbedc1d9ba68c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/aleph.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/bbbk.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/bbbk.png new file mode 100644 index 0000000000000000000000000000000000000000..a793366065a08f1d8e1e50ff1f2a7b20e3e8d94f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/bbbk.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/beth.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/beth.png new file mode 100644 index 0000000000000000000000000000000000000000..c8cb723c1e99bf47ec8a70199d56edb36971323d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/beth.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/circleds.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/circleds.png new file mode 100644 index 0000000000000000000000000000000000000000..7f455e85c607d3634d43780d2c1ef6f6789364f9 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/circleds.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/complement.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/complement.png new file mode 100644 index 0000000000000000000000000000000000000000..f128598ff8f0639f3822e65341c95d85c8f5dd9e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/complement.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/daleth.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/daleth.png new file mode 100644 index 0000000000000000000000000000000000000000..ac705c36d25fcf682b8c89de7e79535b0d49978b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/daleth.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/ell.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/ell.png new file mode 100644 index 0000000000000000000000000000000000000000..ccc6ee32611d8493acdfe134a360c176a6de43be Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/ell.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/eth.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/eth.png new file mode 100644 index 0000000000000000000000000000000000000000..501dbb12992d6d920f7c99a497cb833d3b23eaa7 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/eth.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/finv.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/finv.png new file mode 100644 index 0000000000000000000000000000000000000000..a838bc049826494997d266f6417389f4a697dcfb Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/finv.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/game.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/game.png new file mode 100644 index 0000000000000000000000000000000000000000..c0a5edcdb84ada370a68a3699306b9627d7c0df6 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/game.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/gimel.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/gimel.png new file mode 100644 index 0000000000000000000000000000000000000000..e4fd84081e800c0d18b57e4efe8b2b0fa8aa7094 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/gimel.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/hbar.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/hbar.png new file mode 100644 index 0000000000000000000000000000000000000000..8809ef3681740ad6cba9eaf95f4746247111061c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/hbar.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/hslash.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/hslash.png new file mode 100644 index 0000000000000000000000000000000000000000..a1e4e681936236c08d3dab451778423e36b5f1c4 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/hslash.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/im.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/im.png new file mode 100644 index 0000000000000000000000000000000000000000..201ec05e4bb3069cfc4cfb6853f389e5bb63bdbe Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/im.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/mho.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/mho.png new file mode 100644 index 0000000000000000000000000000000000000000..291f75054e0feea3b0bdb119589c534eca78aec0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/mho.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/partial.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/partial.png new file mode 100644 index 0000000000000000000000000000000000000000..f3b46a06892fd6ca547725867240e12702685e63 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/partial.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/re.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/re.png new file mode 100644 index 0000000000000000000000000000000000000000..9c96096c5e0246b5dc274ebc7f01ab69c1422be1 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/re.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/wp.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/wp.png new file mode 100644 index 0000000000000000000000000000000000000000..23f6541296fc04941c3eb652a55349b9b7cd8a70 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/alphabetic/wp.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/circlearrowleft.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/circlearrowleft.png new file mode 100644 index 0000000000000000000000000000000000000000..26a9213f79e6eb81dd4cf505f602d9e839ff835b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/circlearrowleft.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/circlearrowright.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/circlearrowright.png new file mode 100644 index 0000000000000000000000000000000000000000..d29116286697f520bbbecf48c4710b0ef7a81164 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/circlearrowright.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/curvearrowleft.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/curvearrowleft.png new file mode 100644 index 0000000000000000000000000000000000000000..3cc06b90832d9ed31ee65827e1f8ff1a56a7ed4a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/curvearrowleft.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/curvearrowright.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/curvearrowright.png new file mode 100644 index 0000000000000000000000000000000000000000..265e1e018eba5388b2fce042a9b5ae1b271b7d9e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/curvearrowright.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/downarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/downarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..1b5c375b66c0c741fbe0ed352e8a954f28c352f1 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/downarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/downdownarrows.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/downdownarrows.png new file mode 100644 index 0000000000000000000000000000000000000000..457598cdfa6d802453d64fe782bd0d52ec574524 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/downdownarrows.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/downharpoonleft.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/downharpoonleft.png new file mode 100644 index 0000000000000000000000000000000000000000..f1de8a25bcc216fa1f6ad507e3ec99e304071537 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/downharpoonleft.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/downharpoonright.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/downharpoonright.png new file mode 100644 index 0000000000000000000000000000000000000000..b94a0b8643e221b70bf529188b36e5df8afd79be Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/downharpoonright.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/gets.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/gets.png new file mode 100644 index 0000000000000000000000000000000000000000..8d659f01a2c3ecc6e43c8a15337b137d15785a00 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/gets.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftarrowtail.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftarrowtail.png new file mode 100644 index 0000000000000000000000000000000000000000..d36a75aaa41615c556991242053ac2fdcb60086f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftarrowtail.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftharpoondown.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftharpoondown.png new file mode 100644 index 0000000000000000000000000000000000000000..882f6e0307b8a657fbe3881d8487da76471ef3b7 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftharpoondown.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftharpoonup.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftharpoonup.png new file mode 100644 index 0000000000000000000000000000000000000000..d9fd9f2d0636c9af03a1c431494c0e13c2283411 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftharpoonup.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftleftarrows.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftleftarrows.png new file mode 100644 index 0000000000000000000000000000000000000000..f4cd7c07b31aee31c45fe8438fdcea03acb4c3ed Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftleftarrows.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftrightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftrightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..4d8d86b40de8628cb7e90267bc2d6a2c529edab7 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftrightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftrightarrows.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftrightarrows.png new file mode 100644 index 0000000000000000000000000000000000000000..6f0717c7237f5b2bec9a988fbfb65d0e326b2586 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftrightarrows.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftrightharpoons.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftrightharpoons.png new file mode 100644 index 0000000000000000000000000000000000000000..10a057fd01d2a79f6b691eabe4126aeeac1bd24a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftrightharpoons.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftrightsquigarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftrightsquigarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..d515001e032b759a11508f71ca4c26085d3e2ac3 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/leftrightsquigarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/longleftarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/longleftarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..ab5a64e957fec6d9d670341d2304f1c468d9b766 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/longleftarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/longleftrightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/longleftrightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..fe3141daa36519f3ffeec6c0adb5b1e11997cc2e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/longleftrightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/longrightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/longrightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..ec988e1dfdb85a9d4fbcd926301d305a6f431d43 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/longrightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/looparrowleft.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/looparrowleft.png new file mode 100644 index 0000000000000000000000000000000000000000..a4dee7a11c8ba76a032b0480645e8d5948e0a346 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/looparrowleft.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/looparrowright.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/looparrowright.png new file mode 100644 index 0000000000000000000000000000000000000000..67885fb9851c3963d4235fbb5c73ee510078843e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/looparrowright.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/multimap.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/multimap.png new file mode 100644 index 0000000000000000000000000000000000000000..c7a0bb8acf9fd2ddd635b1fe25894f80cb369d41 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/multimap.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/nearrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/nearrow.png new file mode 100644 index 0000000000000000000000000000000000000000..d5891e0d994071f14b583737d60013e4f2777e0c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/nearrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/nleftarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/nleftarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..df714e174f027fa32dd9eefda881425fda6fc707 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/nleftarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/nrightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/nrightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..b29d923b4ade77c41efefd6922a9355a89b6c4f6 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/nrightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/nwarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/nwarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..bf7b7d23d8897a32cec3900c15a438c4a85ced3b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/nwarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightarrowtail.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightarrowtail.png new file mode 100644 index 0000000000000000000000000000000000000000..27cdc5bf6850ee18e46d9717e72d5e82ba6d21b2 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightarrowtail.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightharpoondown.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightharpoondown.png new file mode 100644 index 0000000000000000000000000000000000000000..e384cf845a1a22e8d2297cc59074f3fd7091f31f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightharpoondown.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightharpoonup.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightharpoonup.png new file mode 100644 index 0000000000000000000000000000000000000000..187e1eb24d08e9fdcf342cc78cd033850ce7741a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightharpoonup.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightleftarrows.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightleftarrows.png new file mode 100644 index 0000000000000000000000000000000000000000..cdec5d9e416f3e0e851b00cefcd52a767e51e9b8 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightleftarrows.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightleftharpoons.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightleftharpoons.png new file mode 100644 index 0000000000000000000000000000000000000000..73385cbbc4c92635d026d5a9125752ee508c2d66 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightleftharpoons.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightrightarrows.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightrightarrows.png new file mode 100644 index 0000000000000000000000000000000000000000..52a7f0f0f1769315be59ac067bd19238f51e4431 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightrightarrows.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightsquigarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightsquigarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..f471054f45716f22ed94250302c27b14d2c2f3f1 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/rightsquigarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/searrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/searrow.png new file mode 100644 index 0000000000000000000000000000000000000000..7d887fb787e144b0d3db54d5e63d2c5f50733961 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/searrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/swarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/swarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..448b686517a2fb7fa1c6609c7bc43041e10ffc59 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/swarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/to.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/to.png new file mode 100644 index 0000000000000000000000000000000000000000..0053655d6189dce30b9d45e78bd37680f8562d4e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/to.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/twoheadleftarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/twoheadleftarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..17bcb5495654a163529f8e598d950b3e52032cda Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/twoheadleftarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/twoheadrightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/twoheadrightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..9242bc210394005cb0fe00eedc55db71bc428cbe Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/twoheadrightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-downarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-downarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..b2264cbfb669bc614780abe35eb65829ba425b92 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-downarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-leftarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-leftarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..84bf7a58fb6cc1cc6f59a0827af43366679da6f7 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-leftarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-leftrightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-leftrightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..288dcc11f9b080ae207cc642d315848fb0e14d9e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-leftrightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-lftarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-lftarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..8ecff745b8aab6129ddabd489df0de188a4271c4 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-lftarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-lleftarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-lleftarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..6bed12114c738d03186804fb5a466c7e6d4ffb67 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-lleftarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-longleftarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-longleftarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..1cdf790c4c7db1e59dc59b0764293b86d6c5d0cd Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-longleftarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-longleftrightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-longleftrightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..def0c9ee946544160a53d1c1e7984b11d7f6fa3b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-longleftrightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-longrightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-longrightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..c21e68ce4b92ad1f166e694a9f172c4ae8517ad9 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-longrightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-lsh.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-lsh.png new file mode 100644 index 0000000000000000000000000000000000000000..1f617890d2c94223581a9ad9e70457c42235ce68 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-lsh.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-nleftarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-nleftarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..07657c0f378bdf9fe9b282e035d94323d66ab8ce Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-nleftarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-nleftrightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-nleftrightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..daf4e65b22b699befa850064fcfce8aeda24aee9 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-nleftrightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-nrightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-nrightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..902826c0bd0090b49cc1792b3185e315d27e0c7c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-nrightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-rightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-rightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..39bc77715838468777d2b722ca21bc664848832f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-rightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-rrightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-rrightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..7aed67df499ddf7aae2fc1e4a47eca71b7ff0a1e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-rrightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-rsh.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-rsh.png new file mode 100644 index 0000000000000000000000000000000000000000..05e8974d689ec6b008136cc9ad3d43c6309be6d0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-rsh.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-uparrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-uparrow.png new file mode 100644 index 0000000000000000000000000000000000000000..e539f6517c5518046effd7267c2912b3faf608fe Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-uparrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-updownarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-updownarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..4aa9faa2793f21f080054d1849dc7574deda8119 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/u-updownarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/uparrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/uparrow.png new file mode 100644 index 0000000000000000000000000000000000000000..aa8f571aed79db6f7609092ff43a3117d91d4f45 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/uparrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/updownarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/updownarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..2235860bb71ee75eb2166239c686a50ab9f0abe4 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/updownarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/upharpoonleft.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/upharpoonleft.png new file mode 100644 index 0000000000000000000000000000000000000000..72d093d219db4183e4f06a8ac1ff25b5476f00a8 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/upharpoonleft.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/upharpoonright.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/upharpoonright.png new file mode 100644 index 0000000000000000000000000000000000000000..76c7335543e8cbc93d1e41d6c4ea90941c510d07 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/upharpoonright.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/upuparrows.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/upuparrows.png new file mode 100644 index 0000000000000000000000000000000000000000..129a3383587a640f46949c70667330b9abfc7c52 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/arrow/upuparrows.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/brackets/1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/brackets/1.png new file mode 100644 index 0000000000000000000000000000000000000000..3b1ed2604fd80a290eb50c70dd88ab817998ba27 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/brackets/1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/brackets/2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/brackets/2.png new file mode 100644 index 0000000000000000000000000000000000000000..07cf41b7a0c64153f42702045dac32007b435d3e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/brackets/2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/brackets/3.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/brackets/3.png new file mode 100644 index 0000000000000000000000000000000000000000..8abe1967dd22b51f7d729b9bca875f27b29be623 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/brackets/3.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/brackets/4.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/brackets/4.png new file mode 100644 index 0000000000000000000000000000000000000000..31ad7f74479356eabf76a76e8bb97454a87d3834 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/brackets/4.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/btn.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/btn.png new file mode 100644 index 0000000000000000000000000000000000000000..77d7c10b296c249d3d557fc6a29a5221b4173d9a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/btn.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/brackets.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/brackets.png new file mode 100644 index 0000000000000000000000000000000000000000..b05c1ca3d45749e57e57dd786989f3e37b3ba8ce Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/brackets.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/down.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/down.png new file mode 100644 index 0000000000000000000000000000000000000000..00a8a3ab0c9dd89b1d6228c27709a09955e4bedb Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/down.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/frac.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/frac.png new file mode 100644 index 0000000000000000000000000000000000000000..104818284c7626883b9ecec14fc55cf4308c5916 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/frac.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/fx.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/fx.png new file mode 100644 index 0000000000000000000000000000000000000000..2482b867f306766d743cfd68e698692ac36fcc1b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/fx.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/int.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/int.png new file mode 100644 index 0000000000000000000000000000000000000000..baafcaa48d1b86a83698d37ea534e95b9c11ccce Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/int.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/lim.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/lim.png new file mode 100644 index 0000000000000000000000000000000000000000..4547302d62d33498160d342759158c324fe1b37c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/lim.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/open.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/open.png new file mode 100644 index 0000000000000000000000000000000000000000..24026c9babf871c94d4a6382bf45787b942ebd12 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/open.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/script.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/script.png new file mode 100644 index 0000000000000000000000000000000000000000..e29e594005eca1fc12b32117e9da1e6d277f8f7c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/script.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/sin.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/sin.png new file mode 100644 index 0000000000000000000000000000000000000000..e5b8295752eb2fd13f19d4f576b9c83ac3dc0f4d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/sin.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/sqrt.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/sqrt.png new file mode 100644 index 0000000000000000000000000000000000000000..782a0daaf169f6983552d82fbe6215c45dc7866e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/sqrt.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/sum.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/sum.png new file mode 100644 index 0000000000000000000000000000000000000000..8c663e2bc0b315ae98a5892227b9bd27c4a393a9 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/sum.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/tick.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/tick.png new file mode 100644 index 0000000000000000000000000000000000000000..6e874f43bfe31eb8b342b26aef70d25f08a33404 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/tick.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/up.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/up.png new file mode 100644 index 0000000000000000000000000000000000000000..6eabcad30a9da3cf55745b7ffccd68203be26105 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/button/up.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char.png new file mode 100644 index 0000000000000000000000000000000000000000..4eef3c380b0f322363f83f032d27ff8367f54a71 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/a.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/a.png new file mode 100644 index 0000000000000000000000000000000000000000..1fc074ebd4a0099359ec951ad1cb485eca93ef8e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/a.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/b.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/b.png new file mode 100644 index 0000000000000000000000000000000000000000..cc75c7d20cc48c337e251efffd52093c306f721b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/b.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/c.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/c.png new file mode 100644 index 0000000000000000000000000000000000000000..b407a1b2873f2d0cf871c0e2ec6285638e107907 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/c.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/d.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/d.png new file mode 100644 index 0000000000000000000000000000000000000000..66e23a897c4a97b2da18e9c2db42d91b51ec0ce3 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/d.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/e.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/e.png new file mode 100644 index 0000000000000000000000000000000000000000..0ef98d17dae047821e027d2e282daf0e042a861d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/e.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/f.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/f.png new file mode 100644 index 0000000000000000000000000000000000000000..e0f76fc95c9bef8111333e5973497f492d23bdd6 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/f.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/g.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/g.png new file mode 100644 index 0000000000000000000000000000000000000000..bbf855fd3bb8a87c3856ef1288cc408c467314d6 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/g.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/h.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/h.png new file mode 100644 index 0000000000000000000000000000000000000000..0347c9327748445a525e29c28e8a6698f30bcee9 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/h.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/i.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/i.png new file mode 100644 index 0000000000000000000000000000000000000000..cfb5814f9dbb7f3899168e5c54dfbbbbeab42d65 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/i.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/j.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/j.png new file mode 100644 index 0000000000000000000000000000000000000000..c9ad651dd102a424bfe686e6c5eeedde9b72d871 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/j.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/k.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/k.png new file mode 100644 index 0000000000000000000000000000000000000000..032f29d812212e649f5a830f51e0b7d81fd90e6d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/k.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/l.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/l.png new file mode 100644 index 0000000000000000000000000000000000000000..72015ab4143687e0e4434d81ba4ea3b25e7dcc94 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/l.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/m.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/m.png new file mode 100644 index 0000000000000000000000000000000000000000..d9c072c81af28d766fd33f93a08bf27c0af82f77 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/m.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/n.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/n.png new file mode 100644 index 0000000000000000000000000000000000000000..a39869801dd4c129abac0fe9e3044f046103acf9 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/n.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/o.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/o.png new file mode 100644 index 0000000000000000000000000000000000000000..9acb05bca0176f38e7d5c05289467fc080e64f98 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/o.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/p.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/p.png new file mode 100644 index 0000000000000000000000000000000000000000..8c11f94f87e425abae2a4e8be63b2e5372b530c8 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/p.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/q.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/q.png new file mode 100644 index 0000000000000000000000000000000000000000..e47c32ea6b18aa30d7b9285a958a28dcb5bdb234 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/q.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/r.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/r.png new file mode 100644 index 0000000000000000000000000000000000000000..44ae3c0d6484ff0336f451432bd3a86bc819ed40 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/r.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/s.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/s.png new file mode 100644 index 0000000000000000000000000000000000000000..93dd1c61d6ac04beca23465cf78704952acf934f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/s.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/t.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/t.png new file mode 100644 index 0000000000000000000000000000000000000000..c359ccd2717878d307dc9f28b9f42a92dd293680 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/t.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/u.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/u.png new file mode 100644 index 0000000000000000000000000000000000000000..c5b6158764cb8ea6a945f7070168e088c40f153d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/u.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/v.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/v.png new file mode 100644 index 0000000000000000000000000000000000000000..2bba8a820679c3ea7416e32326b42b0d35980257 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/v.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/w.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/w.png new file mode 100644 index 0000000000000000000000000000000000000000..82518bb6ae0db6619a0c750c69741fb775fdee2a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/w.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/x.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/x.png new file mode 100644 index 0000000000000000000000000000000000000000..58bb03c3431bdd878a0ab1046675c9d034864ebc Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/x.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/y.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/y.png new file mode 100644 index 0000000000000000000000000000000000000000..7b1ecf62a2ea93f55a5b60180258324b5b9e1b5f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/y.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/z.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/z.png new file mode 100644 index 0000000000000000000000000000000000000000..d8ad9de74b774ab71dd0721fb7be2f203019ea31 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/bb/z.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/a.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/a.png new file mode 100644 index 0000000000000000000000000000000000000000..bbbc10267ecf51ec4f06128c516b65cd9d887fe5 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/a.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/b.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/b.png new file mode 100644 index 0000000000000000000000000000000000000000..1f2d08ac31c91b8c8f480920fd8fe6eb1c54e709 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/b.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/c.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/c.png new file mode 100644 index 0000000000000000000000000000000000000000..21c7817937be4194eb1cf59379c7c1103ba347bb Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/c.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/d.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/d.png new file mode 100644 index 0000000000000000000000000000000000000000..b6cd5a38fb8db6ffaaf83d60e919c17b509bc190 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/d.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/e.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/e.png new file mode 100644 index 0000000000000000000000000000000000000000..5b6d59db9cbfcbfcf2e31a21b214a54a357445e3 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/e.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/f.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/f.png new file mode 100644 index 0000000000000000000000000000000000000000..28a6cffc0febaf5fd4e7a82b7abb382242902dca Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/f.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/g.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/g.png new file mode 100644 index 0000000000000000000000000000000000000000..a8f1999bdd520beec47c4aa1e5d9b06e4641ad8a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/g.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/h.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/h.png new file mode 100644 index 0000000000000000000000000000000000000000..8592859be72c6614e3c1712b4b6dcdb784774139 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/h.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/i.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/i.png new file mode 100644 index 0000000000000000000000000000000000000000..a149116cbd55f5ad964efc2d6aab15facc6967ba Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/i.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/j.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/j.png new file mode 100644 index 0000000000000000000000000000000000000000..cf94ff276a68cbaedf599779e91267d3e4780547 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/j.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/k.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/k.png new file mode 100644 index 0000000000000000000000000000000000000000..35b3656538e97e81fb3cc14c9e074af7a5742a5a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/k.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/l.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/l.png new file mode 100644 index 0000000000000000000000000000000000000000..058d85db7d17728e115ee7288ca4be1d7a3c0c21 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/l.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/m.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/m.png new file mode 100644 index 0000000000000000000000000000000000000000..08eccac594fe14fe65d7acb9fe63d5d9768ad626 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/m.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/n.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/n.png new file mode 100644 index 0000000000000000000000000000000000000000..f8c62c3ba1edaa30681f8cac0418e10156134a30 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/n.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/o.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/o.png new file mode 100644 index 0000000000000000000000000000000000000000..a6568588bc3bbbc1fce0a8fb0be937f6745ca252 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/o.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/p.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/p.png new file mode 100644 index 0000000000000000000000000000000000000000..fc24a272aa555adf2dcf027c43951fa314447876 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/p.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/q.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/q.png new file mode 100644 index 0000000000000000000000000000000000000000..44ebb8de0dd2921149e440d6ab387fbc5b272093 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/q.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/r.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/r.png new file mode 100644 index 0000000000000000000000000000000000000000..be3017a4a29fdcc6487596b1e22941f08da6e039 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/r.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/s.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/s.png new file mode 100644 index 0000000000000000000000000000000000000000..3942b715626334385c37dd00a9a72a466d33a71e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/s.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/t.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/t.png new file mode 100644 index 0000000000000000000000000000000000000000..5d41fd071db99a0232ea1054c18afda2274ab9ed Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/t.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/u.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/u.png new file mode 100644 index 0000000000000000000000000000000000000000..8ebf4439dbdf74c3ef30326542cc124b71cc0299 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/u.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/v.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/v.png new file mode 100644 index 0000000000000000000000000000000000000000..2c51c10dfa13fca1efc357fb580242dcd2710820 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/v.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/w.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/w.png new file mode 100644 index 0000000000000000000000000000000000000000..33ef1d5ba0ecab821e74c787481d80fcebfb5df7 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/w.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/x.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/x.png new file mode 100644 index 0000000000000000000000000000000000000000..fc7dd0b79ea122973e7b93d7165a51e5187e5444 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/x.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/y.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/y.png new file mode 100644 index 0000000000000000000000000000000000000000..6670417a7b73caadb525e084ca2ae229364529fb Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/y.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/z.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/z.png new file mode 100644 index 0000000000000000000000000000000000000000..2489eda0e59883c60371ad2540319227c3d509e9 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/cal/z.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/a.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/a.png new file mode 100644 index 0000000000000000000000000000000000000000..e8a6950a011de8bed9b29907242982b6529a26bd Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/a.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/b.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/b.png new file mode 100644 index 0000000000000000000000000000000000000000..5bc50aae08765dc121272b26a13ecc81308f0a44 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/b.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/c.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/c.png new file mode 100644 index 0000000000000000000000000000000000000000..e0417c53e7b25ceec69b85978b9d0101db7e512a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/c.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/d.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/d.png new file mode 100644 index 0000000000000000000000000000000000000000..a267b36f09f3e6c909e071a0cf3f2c342626adb5 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/d.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/e.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/e.png new file mode 100644 index 0000000000000000000000000000000000000000..be71bf646121f468a6d5bd4b406be5af33d9bd8a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/e.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/f.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/f.png new file mode 100644 index 0000000000000000000000000000000000000000..2c170114f02e55bf06e6e8f08c5d74578c961aef Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/f.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/g.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/g.png new file mode 100644 index 0000000000000000000000000000000000000000..d05843d601fd4bcfa5e37c9c3a86cfccedf5e640 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/g.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/h.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/h.png new file mode 100644 index 0000000000000000000000000000000000000000..41d958e53c772d9fff56fd14e053d559d3027f8d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/h.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/i.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/i.png new file mode 100644 index 0000000000000000000000000000000000000000..1e9bd348a4c199913a67c4a1081c61a42591c12b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/i.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/j.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/j.png new file mode 100644 index 0000000000000000000000000000000000000000..fc66b892b3fd754a8afcb4a3257a4f7a982de5cc Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/j.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/k.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/k.png new file mode 100644 index 0000000000000000000000000000000000000000..49dbc27324937a64387bca7d9b7e093fd91faac0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/k.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/l.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/l.png new file mode 100644 index 0000000000000000000000000000000000000000..8e23844bd2d6ffcb64423967ffbd83b1959c9e38 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/l.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/m.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/m.png new file mode 100644 index 0000000000000000000000000000000000000000..f5a79ce813b0201e6d0d42c8f5f95f54cb233065 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/m.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/n.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/n.png new file mode 100644 index 0000000000000000000000000000000000000000..e9b7491a7bd9b8187349d4e03009094b6a941a73 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/n.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/o.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/o.png new file mode 100644 index 0000000000000000000000000000000000000000..f386683e561d8ac0d040377c8b1202885217a541 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/o.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/p.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/p.png new file mode 100644 index 0000000000000000000000000000000000000000..334a11890098e231dbe0f3f9177f05d084a231a0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/p.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/q.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/q.png new file mode 100644 index 0000000000000000000000000000000000000000..205df6aa1f8e3dec251846aa059302cd22e353bb Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/q.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/r.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/r.png new file mode 100644 index 0000000000000000000000000000000000000000..fc8bc8b0ae880e53cfe630bc7e2ccfd49d80129a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/r.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/s.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/s.png new file mode 100644 index 0000000000000000000000000000000000000000..bd6c50c094f3539b1a895fe0d07706d20fab5f25 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/s.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/t.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/t.png new file mode 100644 index 0000000000000000000000000000000000000000..76de18523f78d27246445583f39c8aef36342770 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/t.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/u.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/u.png new file mode 100644 index 0000000000000000000000000000000000000000..8c1dfbcf105e9f02883f4d6a0f9a286af94a0fbf Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/u.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ua.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ua.png new file mode 100644 index 0000000000000000000000000000000000000000..cc049efe2a4f36ffb323bb03540b0987ac409e90 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ua.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ub.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ub.png new file mode 100644 index 0000000000000000000000000000000000000000..841e8cc19703f08479e5897f3d0129f7312f0db0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ub.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uc.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uc.png new file mode 100644 index 0000000000000000000000000000000000000000..f15063d45aaf4fe710097b2fa36bd19e6631da92 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uc.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ud.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ud.png new file mode 100644 index 0000000000000000000000000000000000000000..8671415ea5d457b8788e00e5eb19d5b50416ead5 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ud.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ue.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ue.png new file mode 100644 index 0000000000000000000000000000000000000000..69b1f086851cfdf496a42485fd301fa1e05a1599 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ue.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uf.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uf.png new file mode 100644 index 0000000000000000000000000000000000000000..9fd1e6a1f73ad2c54f5e4f9c399f48732dc3052e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uf.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ug.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ug.png new file mode 100644 index 0000000000000000000000000000000000000000..3fc5ede03722c1e920df918ce88c83f06371a38a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ug.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uh.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uh.png new file mode 100644 index 0000000000000000000000000000000000000000..45e18a9a41382a6e6fdec8cf200822da78e6d809 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uh.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ui.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ui.png new file mode 100644 index 0000000000000000000000000000000000000000..6e9a03a702e4947c62449f691beb54825722bf48 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ui.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uj.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uj.png new file mode 100644 index 0000000000000000000000000000000000000000..855aaa921d0986ea68c25a0284e044f6521bfcc9 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uj.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uk.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uk.png new file mode 100644 index 0000000000000000000000000000000000000000..adb3b00ae8019b75416edd3e0f2028ec1cf1f47d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uk.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ul.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ul.png new file mode 100644 index 0000000000000000000000000000000000000000..9f138ee71d6febb585fc3233651a826de42a1c6c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ul.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/um.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/um.png new file mode 100644 index 0000000000000000000000000000000000000000..64d7bd4607f03b4ef9576f58a27fea89c4bebe90 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/um.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/un.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/un.png new file mode 100644 index 0000000000000000000000000000000000000000..37c4bfd665a5014d1e2e440d1ef60686805abe21 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/un.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uo.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uo.png new file mode 100644 index 0000000000000000000000000000000000000000..0340b6d03416fa966c0b2e8970395e09e140558d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uo.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/up.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/up.png new file mode 100644 index 0000000000000000000000000000000000000000..f5a1d38d7583f7516237fe38ebb33ecf0a919c43 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/up.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uq.png new file mode 100644 index 0000000000000000000000000000000000000000..bfb7f505109971e0bd98e5fcdc2f59c943f658d4 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ur.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ur.png new file mode 100644 index 0000000000000000000000000000000000000000..959804cd94498599d5e680a83343f22cf101af42 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ur.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/us.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/us.png new file mode 100644 index 0000000000000000000000000000000000000000..1d77b1d70537a413d909b19e7f4c6b201bc15c9d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/us.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ut.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ut.png new file mode 100644 index 0000000000000000000000000000000000000000..5ebab869a308986ae6e5719d98a3ba1714a01eff Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ut.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uu.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uu.png new file mode 100644 index 0000000000000000000000000000000000000000..fa9d8554db087962b15efa577321e38d958c0714 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uu.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uv.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uv.png new file mode 100644 index 0000000000000000000000000000000000000000..8c346f1602eb24b5eff1473edb57aa3872249e4d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uv.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uw.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uw.png new file mode 100644 index 0000000000000000000000000000000000000000..223543dd561bef2af966294430c9bdd9bc92ecc1 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uw.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ux.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ux.png new file mode 100644 index 0000000000000000000000000000000000000000..e87b75546c5db940206bcf3b68534f1875d8b56b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/ux.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uy.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uy.png new file mode 100644 index 0000000000000000000000000000000000000000..b51e8ee870f14ae9c5f76bc8060982c49f44225f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uy.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uz.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uz.png new file mode 100644 index 0000000000000000000000000000000000000000..58ee470185ca5a4a093d49efdd61cb7a1aeda038 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/uz.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/v.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/v.png new file mode 100644 index 0000000000000000000000000000000000000000..3aed0031cacf3ad6303d9435a42333a56835ca9d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/v.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/w.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/w.png new file mode 100644 index 0000000000000000000000000000000000000000..008b3613484ed1bbb12f6f0be6630cdcced5fe67 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/w.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/x.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/x.png new file mode 100644 index 0000000000000000000000000000000000000000..b73a3c3a230cdfd39813eed77f6214388df24571 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/x.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/y.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/y.png new file mode 100644 index 0000000000000000000000000000000000000000..158863bafe50962c5d267285da77924d6711dd6a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/y.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/z.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/z.png new file mode 100644 index 0000000000000000000000000000000000000000..d3907d2aeb3a77e501d597ec4937d654acba6cfc Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/frak/z.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/alpha.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/alpha.png new file mode 100644 index 0000000000000000000000000000000000000000..91907f256e28c86774b8ce4260234f5ca0cdac6d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/alpha.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/beta.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/beta.png new file mode 100644 index 0000000000000000000000000000000000000000..95edb82f59d4cda867805b03112ad4ba60a4a6a5 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/beta.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/chi.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/chi.png new file mode 100644 index 0000000000000000000000000000000000000000..2c5f2f28f499555ec79523d8adf36a3b5c09f88d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/chi.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/delta.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/delta.png new file mode 100644 index 0000000000000000000000000000000000000000..847f5c1469dbb348de397f17e25dd88cfaaf9779 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/delta.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/epsilon.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/epsilon.png new file mode 100644 index 0000000000000000000000000000000000000000..d9fa6c2c997df92549fabf1e78560c036ca55d18 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/epsilon.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/eta.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/eta.png new file mode 100644 index 0000000000000000000000000000000000000000..206d0142761401395213686294b78561c25d17ae Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/eta.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/gamma.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/gamma.png new file mode 100644 index 0000000000000000000000000000000000000000..97a09a08c45a6c7f9ce729f9de7844ed8af47eb0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/gamma.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/iota.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/iota.png new file mode 100644 index 0000000000000000000000000000000000000000..7eaad513fc19cbcd72ad8edcdffa50a1fce7c37e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/iota.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/kappa.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/kappa.png new file mode 100644 index 0000000000000000000000000000000000000000..7a8571dd2749b7e6bbc3c1969576a2e0aff20a03 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/kappa.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/lambda.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/lambda.png new file mode 100644 index 0000000000000000000000000000000000000000..b619ecd3dcc1a19882a61eb13d65f76104b3f25b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/lambda.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/mu.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/mu.png new file mode 100644 index 0000000000000000000000000000000000000000..016d4642008c5a2eea36b59f2d63c38f85160b10 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/mu.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/nu.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/nu.png new file mode 100644 index 0000000000000000000000000000000000000000..0f00fc4117d938236eb5eb6c32ba21c43106016f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/nu.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/omega.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/omega.png new file mode 100644 index 0000000000000000000000000000000000000000..3c0220f4d0cd21495d0de45a33d6a0f5b87e0024 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/omega.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/omicron.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/omicron.png new file mode 100644 index 0000000000000000000000000000000000000000..c5511b285f5cefc0e743e35554de62cae7e35aec Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/omicron.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/phi.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/phi.png new file mode 100644 index 0000000000000000000000000000000000000000..5b6fc9e50b7ea1a2a986346a8321bca119f08884 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/phi.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/pi.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/pi.png new file mode 100644 index 0000000000000000000000000000000000000000..30bc20c1797cdc284d2359a2614ac7feeb562fe3 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/pi.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/psi.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/psi.png new file mode 100644 index 0000000000000000000000000000000000000000..92054d2b8e0b687eed39d9c0ff6a64c4813f7fc1 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/psi.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/rho.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/rho.png new file mode 100644 index 0000000000000000000000000000000000000000..48cc456e69b154f92b63299cd8a3ed8376448c3a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/rho.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/sigma.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/sigma.png new file mode 100644 index 0000000000000000000000000000000000000000..349fb3bfc1e127122383fa23e9eec33fd9cace35 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/sigma.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/tau.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/tau.png new file mode 100644 index 0000000000000000000000000000000000000000..235468fccbef6f8780486a6e0b4c8f40f9d838bc Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/tau.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/theta.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/theta.png new file mode 100644 index 0000000000000000000000000000000000000000..6540af2531f6ba74fed6564a54a8410f966ecb7d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/theta.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/upsilon.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/upsilon.png new file mode 100644 index 0000000000000000000000000000000000000000..0d88ee0efbc54626066dee63d2d47a9f7be5f6b2 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/upsilon.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/xi.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/xi.png new file mode 100644 index 0000000000000000000000000000000000000000..a00c3829d177de5ea599de8145998680341975ce Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/xi.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/zeta.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/zeta.png new file mode 100644 index 0000000000000000000000000000000000000000..683d9bca83ea455961ba22637f470c94fb8b68c7 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/lower/zeta.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/digamma.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/digamma.png new file mode 100644 index 0000000000000000000000000000000000000000..b9ab6f1448fe0eba3714206132e00a1b3ce0d9ed Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/digamma.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varepsilon.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varepsilon.png new file mode 100644 index 0000000000000000000000000000000000000000..2f3ae9c94835bd79f04304c5b68e39be5c712940 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varepsilon.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varkappa.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varkappa.png new file mode 100644 index 0000000000000000000000000000000000000000..ddc85a22758f76099117875787aeeacbbb86e3b3 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varkappa.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varphi.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varphi.png new file mode 100644 index 0000000000000000000000000000000000000000..a198b26921f9af5f8e825491313443f073105e4c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varphi.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varpi.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varpi.png new file mode 100644 index 0000000000000000000000000000000000000000..788c350bf8b7cb29fd5db4649b73653d66ab3626 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varpi.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varrho.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varrho.png new file mode 100644 index 0000000000000000000000000000000000000000..d88476754e0729f925a8344009c56fb42cdc8f4d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varrho.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varsigma.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varsigma.png new file mode 100644 index 0000000000000000000000000000000000000000..a5409dd4b923662dd2b59335466910ad94a801dc Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/varsigma.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/vartheta.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/vartheta.png new file mode 100644 index 0000000000000000000000000000000000000000..4729b1537572a0c744dcc280aa45ecb92e87830d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/misc/vartheta.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/alpha.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/alpha.png new file mode 100644 index 0000000000000000000000000000000000000000..22dfae19bbed0a26772f9e1ce3bc006491a9e9b7 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/alpha.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/beta.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/beta.png new file mode 100644 index 0000000000000000000000000000000000000000..c95d79be594db75c538dc9a004e1b1d53f99b4b6 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/beta.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/chi.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/chi.png new file mode 100644 index 0000000000000000000000000000000000000000..774804af196fa73fe550b41b349f228a05914a47 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/chi.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/delta.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/delta.png new file mode 100644 index 0000000000000000000000000000000000000000..c3baf6253586ab872c62ccae51d725760af5ec11 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/delta.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/epsilon.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/epsilon.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f85ef3fbef563dd92dd43417f489a61ac84ecb Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/epsilon.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/eta.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/eta.png new file mode 100644 index 0000000000000000000000000000000000000000..c02a78af3eeba4366aa30e51fb4c7732fd6d6e76 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/eta.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/gamma.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/gamma.png new file mode 100644 index 0000000000000000000000000000000000000000..1f6ccb0e2f559fce512a5ac6245cb44c64484031 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/gamma.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/iota.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/iota.png new file mode 100644 index 0000000000000000000000000000000000000000..10777c943bb658ccf9fc1afb5e183bb832e77bc8 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/iota.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/kappa.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/kappa.png new file mode 100644 index 0000000000000000000000000000000000000000..44aa91f3c746c532ba9456a24e136b884d30a70d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/kappa.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/lambda.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/lambda.png new file mode 100644 index 0000000000000000000000000000000000000000..cf67ea5de45ba58bbf2a9fc0fbcfc1b490b9ed33 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/lambda.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/mu.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/mu.png new file mode 100644 index 0000000000000000000000000000000000000000..7284125d1d9b94b23b811982b93e41cb8e463bdd Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/mu.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/nu.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/nu.png new file mode 100644 index 0000000000000000000000000000000000000000..2dcc1c3af3c892912b65f4245f5a8c70fbe4b8d6 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/nu.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/omega.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/omega.png new file mode 100644 index 0000000000000000000000000000000000000000..3b9466db6b0cf618d1ba1359d750ae3afc6535c1 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/omega.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/omicron.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/omicron.png new file mode 100644 index 0000000000000000000000000000000000000000..6d31fbd95e6ace84ef6f1b317ac700c9da502a09 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/omicron.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/phi.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/phi.png new file mode 100644 index 0000000000000000000000000000000000000000..1a928d65d4f45299b2b7bd405b61624d49db8367 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/phi.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/pi.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/pi.png new file mode 100644 index 0000000000000000000000000000000000000000..a1e1314b03fe7c4c585d9699e614dfce48f123ac Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/pi.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/psi.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/psi.png new file mode 100644 index 0000000000000000000000000000000000000000..fdc032186025b8d7673d7ddc473eeba49cfb5b69 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/psi.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/rho.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/rho.png new file mode 100644 index 0000000000000000000000000000000000000000..27d8c36656595da765c24f0d5c8808a3985add35 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/rho.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/sigma.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/sigma.png new file mode 100644 index 0000000000000000000000000000000000000000..dd4ad4bbc33601964aa78551b2123e7fe08beda0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/sigma.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/tau.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/tau.png new file mode 100644 index 0000000000000000000000000000000000000000..7ad430550b442ecdcc55b7995c1e2fac5f05729a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/tau.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/theta.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/theta.png new file mode 100644 index 0000000000000000000000000000000000000000..b5d78300c31402f09f77c5ca91245b8ebf36b22c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/theta.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/upsilon.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/upsilon.png new file mode 100644 index 0000000000000000000000000000000000000000..ff1fd88c4476f89ce0e9885e66bdec498aeda966 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/upsilon.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/xi.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/xi.png new file mode 100644 index 0000000000000000000000000000000000000000..a478d75912ca67133ab024ee8ea449bb68968c23 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/xi.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/zeta.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/zeta.png new file mode 100644 index 0000000000000000000000000000000000000000..4052d0963220f8a3f3f63c2a1e054691cff7fe19 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/greek/upper/zeta.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/aleph.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/aleph.png new file mode 100644 index 0000000000000000000000000000000000000000..49631118f59fd251f779372b8e2f21de2a6e3025 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/aleph.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/approx.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/approx.png new file mode 100644 index 0000000000000000000000000000000000000000..7ef6f5dab254b82b474171509f3743e7f5995ac3 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/approx.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/ast.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/ast.png new file mode 100644 index 0000000000000000000000000000000000000000..8b4deaddc3712ad96808f24c5b6a00e82257fcff Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/ast.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/baifenhao.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/baifenhao.png new file mode 100644 index 0000000000000000000000000000000000000000..624539c19693627bc2a55f333ef657a165abf1db Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/baifenhao.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/because.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/because.png new file mode 100644 index 0000000000000000000000000000000000000000..51070efc10f886dc762a36d25e73749c6655b905 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/because.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/beth.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/beth.png new file mode 100644 index 0000000000000000000000000000000000000000..90fa4e238647069acc3eb58f22de6019e653eeb6 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/beth.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/blacksquare.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/blacksquare.png new file mode 100644 index 0000000000000000000000000000000000000000..4221d79b3c7cd50c80833135f2fd9bea9bd795bd Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/blacksquare.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/cap.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/cap.png new file mode 100644 index 0000000000000000000000000000000000000000..59d6a754347ad2e7fb94068e40e71eade8447ce1 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/cap.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/cdot.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/cdot.png new file mode 100644 index 0000000000000000000000000000000000000000..4f923c17780c032655a7aa14dc94f1a709565e07 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/cdot.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/circ.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/circ.png new file mode 100644 index 0000000000000000000000000000000000000000..a27d47748e475c55a752c387bcb6a86bcf633a81 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/circ.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/cong.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/cong.png new file mode 100644 index 0000000000000000000000000000000000000000..46abcf09ee215e3330208cf5a3f4597126338b86 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/cong.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/cup.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/cup.png new file mode 100644 index 0000000000000000000000000000000000000000..f321d24a12644d883b23ed53560ee41d9c51ab1c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/cup.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/ddots.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/ddots.png new file mode 100644 index 0000000000000000000000000000000000000000..c609835e5a42f761cd4139dfc7b6e93904c4a017 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/ddots.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/div.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/div.png new file mode 100644 index 0000000000000000000000000000000000000000..8c11435ce09d150956788d8ab1a34cbc4c8de62d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/div.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/downarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/downarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..fe285ddba4ab2b6092b93113f114fb899d96f899 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/downarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/eq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/eq.png new file mode 100644 index 0000000000000000000000000000000000000000..21820cadf2fc50656cc6abac4a4f3b6e0f357db3 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/eq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/equiv.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/equiv.png new file mode 100644 index 0000000000000000000000000000000000000000..d21d2b61212da0b32bdcab2da57b12019866d3fd Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/equiv.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/exists.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/exists.png new file mode 100644 index 0000000000000000000000000000000000000000..291cead95d512541f4af49eca3e945b64245c961 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/exists.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/forall.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/forall.png new file mode 100644 index 0000000000000000000000000000000000000000..c2a01c859c410ff2d669a4cd0c8c09283079ca79 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/forall.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/geq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/geq.png new file mode 100644 index 0000000000000000000000000000000000000000..0ccd75280bdd57359521ad6492661adac15d4a35 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/geq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/gets.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/gets.png new file mode 100644 index 0000000000000000000000000000000000000000..702b6da64d3590519fd342b1d443265210f123a3 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/gets.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/gg.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/gg.png new file mode 100644 index 0000000000000000000000000000000000000000..7dcdea84ec5ac33f3bbd86839a5743962e35db81 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/gg.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/gt.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/gt.png new file mode 100644 index 0000000000000000000000000000000000000000..cc057299b059410e746a74bb14d7ddd63bbbcb17 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/gt.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/in.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/in.png new file mode 100644 index 0000000000000000000000000000000000000000..271d61905f992c930cbf76769743ffdf71b501dc Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/in.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/infty.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/infty.png new file mode 100644 index 0000000000000000000000000000000000000000..8db988c4facc90b7c6be1fcba251e4d802263220 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/infty.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/leftrightarrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/leftrightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..989a47dc39a40d1cfceb4012d77213382f9eb980 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/leftrightarrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/leq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/leq.png new file mode 100644 index 0000000000000000000000000000000000000000..01255b2933529b50d78392405d552e18061c909e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/leq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/ll.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/ll.png new file mode 100644 index 0000000000000000000000000000000000000000..d0cc99f3daaeaead992b145969645ce4d285359b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/ll.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/lt.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/lt.png new file mode 100644 index 0000000000000000000000000000000000000000..f11edc8f5649bf37a673dcc5e9cc97342c6d9bf4 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/lt.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/minus.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..0f845a285ad36f358cdf60c3f31b0649233777ab Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/minus.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/mp.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/mp.png new file mode 100644 index 0000000000000000000000000000000000000000..1cf38f07dfd3c65dbe6ff39df2544ececf077b09 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/mp.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/neg.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/neg.png new file mode 100644 index 0000000000000000000000000000000000000000..164bfa842c13b5e45098b4c1d81ab2a7ec846d03 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/neg.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/nexists.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/nexists.png new file mode 100644 index 0000000000000000000000000000000000000000..e4523e1cc595f3897d635b81d26ece4596a589ab Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/nexists.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/ni.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/ni.png new file mode 100644 index 0000000000000000000000000000000000000000..5b3da5768f191d8597f6a19a25048d96073c923c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/ni.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/partial.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/partial.png new file mode 100644 index 0000000000000000000000000000000000000000..28253fa6e7366d2dcc4d146727dd16b3f2839a7f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/partial.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/plus.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..7055190c44bfa7f28cd4ee6f59f8c92199efd112 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/plus.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/pm.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/pm.png new file mode 100644 index 0000000000000000000000000000000000000000..881665584f034bad863d2caa9dbaa10983e4cf5f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/pm.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/propto.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/propto.png new file mode 100644 index 0000000000000000000000000000000000000000..4ba04fdc5516d8fffa7b66116b65839fe96c8162 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/propto.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/sim.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/sim.png new file mode 100644 index 0000000000000000000000000000000000000000..4a5264bcc2e773fab9d7fb0966a1e60be9f40d48 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/sim.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/simeq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/simeq.png new file mode 100644 index 0000000000000000000000000000000000000000..ac4b64b65c6a1e93dea9b3d3f317f0676fdcbbef Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/simeq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/surd.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/surd.png new file mode 100644 index 0000000000000000000000000000000000000000..9ddfd4db77f349593e7d2eee602b0f83acfa7fcf Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/surd.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/tanhao.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/tanhao.png new file mode 100644 index 0000000000000000000000000000000000000000..35a33468a1c630b4984ffde5cac4f5b816966f40 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/tanhao.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/therefore.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/therefore.png new file mode 100644 index 0000000000000000000000000000000000000000..7fd47cf7f8c60d97f3fdeb2ee00d85886a46dc76 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/therefore.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/times.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/times.png new file mode 100644 index 0000000000000000000000000000000000000000..1018224ef25c23424f7d958d0f00c3de03607cea Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/times.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/to.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/to.png new file mode 100644 index 0000000000000000000000000000000000000000..12609e4f4619c06a6a6893da2a479b091c26fc02 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/to.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/uparrow.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/uparrow.png new file mode 100644 index 0000000000000000000000000000000000000000..0c619451ae4cf406ac66c39ca6662f3cfd395802 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/uparrow.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/varnothing.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/varnothing.png new file mode 100644 index 0000000000000000000000000000000000000000..ea1b6c1d9e5035dee7006127814bf632eb5bd878 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/varnothing.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/vdots.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/vdots.png new file mode 100644 index 0000000000000000000000000000000000000000..0ce84f2ce5101f555f01cc11f3f9bbc1e6ccdf6d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/math/vdots.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/gneqq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/gneqq.png new file mode 100644 index 0000000000000000000000000000000000000000..b299d23031ec9249af036beb8a18214c36b3fb28 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/gneqq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/gnsim.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/gnsim.png new file mode 100644 index 0000000000000000000000000000000000000000..683af6bf93b6f1e8230dc1f4f8f831b52616effe Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/gnsim.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/lneqq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/lneqq.png new file mode 100644 index 0000000000000000000000000000000000000000..56440637b9b06b7fdc90c63f00b29e8647d0de61 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/lneqq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/lnsim.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/lnsim.png new file mode 100644 index 0000000000000000000000000000000000000000..1365188a04e6085031a6046ccf2e296cf6d7aa3e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/lnsim.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nbdash-1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nbdash-1.png new file mode 100644 index 0000000000000000000000000000000000000000..07cce702f4abfb4d7d235f5e19449aea32fa5672 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nbdash-1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ncong.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ncong.png new file mode 100644 index 0000000000000000000000000000000000000000..156f8befa8d5ef018742db4fc93b14c26f415f81 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ncong.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/neq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/neq.png new file mode 100644 index 0000000000000000000000000000000000000000..feb442f4ce94122870baa66edf89d51978be6aab Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/neq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nequiv.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nequiv.png new file mode 100644 index 0000000000000000000000000000000000000000..83427dc84ec60897226f5ac9be13a5a6a0f8086c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nequiv.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nexists.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nexists.png new file mode 100644 index 0000000000000000000000000000000000000000..c5e3e583c6d81cdb274f5d83ad06160c578d37e7 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nexists.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ngeq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ngeq.png new file mode 100644 index 0000000000000000000000000000000000000000..d3385e4cd6dce61f029f9b76541095347ec01231 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ngeq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ngtr.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ngtr.png new file mode 100644 index 0000000000000000000000000000000000000000..033a1d168126cf8e29d8b725a10ba0434d57e7ef Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ngtr.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nleq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nleq.png new file mode 100644 index 0000000000000000000000000000000000000000..16347a168a6df4b47d5b8bf28e61d9c781269560 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nleq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nless.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nless.png new file mode 100644 index 0000000000000000000000000000000000000000..11c947238910fb33a64c4f61f86f48e32f0de0f5 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nless.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nmid.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nmid.png new file mode 100644 index 0000000000000000000000000000000000000000..c63688e23115612366fb96f2ad264688591fee8d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nmid.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/notin.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/notin.png new file mode 100644 index 0000000000000000000000000000000000000000..d0012918e033082e4f727ec48169322da7fa3c5c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/notin.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nparallel.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nparallel.png new file mode 100644 index 0000000000000000000000000000000000000000..76887ca0c8135247c6c345b0a1b88c2bcbb8fa1d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nparallel.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nprec.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nprec.png new file mode 100644 index 0000000000000000000000000000000000000000..a929e3b024b53f8a690da1c901403673d44d83ae Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nprec.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nsim.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nsim.png new file mode 100644 index 0000000000000000000000000000000000000000..45cf001ba2db9f9eb517fd43489e89288706377e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nsim.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nsubseteq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nsubseteq.png new file mode 100644 index 0000000000000000000000000000000000000000..9e530e2767f3d70ea8ca7dbf8c2324b50852367f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nsubseteq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nsucc.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nsucc.png new file mode 100644 index 0000000000000000000000000000000000000000..b975eaf8b9c96e897b9e5802514238c982e9b297 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nsucc.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nsupseteq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nsupseteq.png new file mode 100644 index 0000000000000000000000000000000000000000..4c1866b401e2fa89deb23d995a79a4f8e04cc3f5 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nsupseteq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ntriangleleft.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ntriangleleft.png new file mode 100644 index 0000000000000000000000000000000000000000..39ecc4dd30744d35fefdb457437b512aee853911 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ntriangleleft.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ntrianglelefteq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ntrianglelefteq.png new file mode 100644 index 0000000000000000000000000000000000000000..9b8f737d1a182b5876875a60dfd6fc2ede3480fc Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ntrianglelefteq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ntriangleright.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ntriangleright.png new file mode 100644 index 0000000000000000000000000000000000000000..751acf0d12d70bc4551f3ca0c85a872c45520072 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ntriangleright.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ntrianglerighteq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ntrianglerighteq.png new file mode 100644 index 0000000000000000000000000000000000000000..abff3af7dcdb933014f0be241e50dba2a5827422 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/ntrianglerighteq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nvdash-1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nvdash-1.png new file mode 100644 index 0000000000000000000000000000000000000000..dc641d92e2266751d8510ea780529bd01394079d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nvdash-1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nvdash-2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nvdash-2.png new file mode 100644 index 0000000000000000000000000000000000000000..4079f6fba03da755909ea184176debbd6bfe8b31 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nvdash-2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nvdash-3.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nvdash-3.png new file mode 100644 index 0000000000000000000000000000000000000000..3d872b42e1f3d1b8c0e098c8069eeb50ac7c2506 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nvdash-3.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nvdash.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nvdash.png new file mode 100644 index 0000000000000000000000000000000000000000..4f4fb1f2e91b0d3c523f84f4e909e1f85fea3cd2 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/nvdash.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/precnsim.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/precnsim.png new file mode 100644 index 0000000000000000000000000000000000000000..e6c148b2e06a11adccdad29045fab4d65f65c57b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/precnsim.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/subsetneq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/subsetneq.png new file mode 100644 index 0000000000000000000000000000000000000000..cc3383553606f6561afd9394131fb04707d5b573 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/subsetneq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/succnsim.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/succnsim.png new file mode 100644 index 0000000000000000000000000000000000000000..7eafb5bd473d4db551059509427c895ec984db19 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/succnsim.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/supsetneq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/supsetneq.png new file mode 100644 index 0000000000000000000000000000000000000000..b43f091926deaaf19d55f0a596f49a512a1c6a61 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/not/supsetneq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/a.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/a.png new file mode 100644 index 0000000000000000000000000000000000000000..9da4fafe5aeab01be22acaaf52aa64c6229129c0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/a.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/b.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/b.png new file mode 100644 index 0000000000000000000000000000000000000000..c14fe4f1dac6ab7d710dc32043867d2824a980b0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/b.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/c.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/c.png new file mode 100644 index 0000000000000000000000000000000000000000..08015b74a0f4222ae88d4540435052509280ad93 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/c.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/d.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/d.png new file mode 100644 index 0000000000000000000000000000000000000000..2c9a95d8df8530ebcb7a5893e59960da4a457e46 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/d.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/e.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/e.png new file mode 100644 index 0000000000000000000000000000000000000000..e966a241d3205884ad9a719c9fc4b5a292ec6761 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/e.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/f.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/f.png new file mode 100644 index 0000000000000000000000000000000000000000..76d3d370acb70576be0f112e993dc7c3d95fde31 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/f.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/g.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/g.png new file mode 100644 index 0000000000000000000000000000000000000000..8ea577546586ec3619015e3cc53c2b04486f94fd Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/g.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/h.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/h.png new file mode 100644 index 0000000000000000000000000000000000000000..fa3c006d3324d8d6e96bde3eb5431e84a6b9be44 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/h.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/i.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/i.png new file mode 100644 index 0000000000000000000000000000000000000000..58e2a69325c503ece628a44281d8f3f31322f4ce Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/i.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/j.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/j.png new file mode 100644 index 0000000000000000000000000000000000000000..592148aa81b4deca5fe1021338f129399c805f1d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/j.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/k.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/k.png new file mode 100644 index 0000000000000000000000000000000000000000..e2daf2e56154174a51fef2078d029b1093729bab Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/k.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/l.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/l.png new file mode 100644 index 0000000000000000000000000000000000000000..691a92fbf73b9fb239adc9692bd43bb1e1c0a232 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/l.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/m.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/m.png new file mode 100644 index 0000000000000000000000000000000000000000..9f020cc1b7d489578334cee644e972473ff7ab32 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/m.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/n.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/n.png new file mode 100644 index 0000000000000000000000000000000000000000..30be2cc6829882f14dad932854787a127b3e1c52 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/n.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/o.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/o.png new file mode 100644 index 0000000000000000000000000000000000000000..16c83a08f7f9251333f8595d8ed78c2ed5fc98f1 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/o.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/p.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/p.png new file mode 100644 index 0000000000000000000000000000000000000000..b3e837cd82eb88546ceb17b73624dbff1683e838 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/p.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/q.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/q.png new file mode 100644 index 0000000000000000000000000000000000000000..203bb204fb3c4a81e01b9b4fd4894e30179764c1 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/q.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/r.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/r.png new file mode 100644 index 0000000000000000000000000000000000000000..763f81e9976985858b771a9318b68c4b31b98397 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/r.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/s.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/s.png new file mode 100644 index 0000000000000000000000000000000000000000..7510702eee0b636d2b783a3b207df8476ca37a2c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/s.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/t.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/t.png new file mode 100644 index 0000000000000000000000000000000000000000..00432047f5efe9ce1711d81a8f11162336eba2bf Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/t.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/u.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/u.png new file mode 100644 index 0000000000000000000000000000000000000000..f495f3d116181db5956ca2ea815227d569f2bf37 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/u.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ua.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ua.png new file mode 100644 index 0000000000000000000000000000000000000000..7d36a0e98a63a6fd1968e086ae446731a4585e2f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ua.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ub.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ub.png new file mode 100644 index 0000000000000000000000000000000000000000..d1eacb7ef8cd2dcb0d0c6fb4d7f2ad23e18424fc Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ub.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uc.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uc.png new file mode 100644 index 0000000000000000000000000000000000000000..e1f8bb9e0e7e3950f920b95f633e496466f4f1f0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uc.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ud.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ud.png new file mode 100644 index 0000000000000000000000000000000000000000..a5d2343dcfe16517550e55bbc0f8feee106bbb29 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ud.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ue.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ue.png new file mode 100644 index 0000000000000000000000000000000000000000..974322c69f5280bd2b88512e5d688b18474f9938 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ue.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uf.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uf.png new file mode 100644 index 0000000000000000000000000000000000000000..253244e6002ffc49dd28a84f6a071cca1a7136aa Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uf.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ug.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ug.png new file mode 100644 index 0000000000000000000000000000000000000000..3fd2e08a28a94f8cb8d94bf83e013c5a34c06f4e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ug.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uh.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uh.png new file mode 100644 index 0000000000000000000000000000000000000000..c72d3192c1a469d87ca568bf86cc2a3ed012a441 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uh.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ui.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ui.png new file mode 100644 index 0000000000000000000000000000000000000000..f69e3f857e6a7c7e11ecaed284b3bd53d33a5e8e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ui.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uj.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uj.png new file mode 100644 index 0000000000000000000000000000000000000000..ffefb31042c96f3fdd04d151cfe32eb1f9007674 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uj.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uk.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uk.png new file mode 100644 index 0000000000000000000000000000000000000000..07a569dc9ceda3da096ef09ab21bbb363fe85cc2 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uk.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ul.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ul.png new file mode 100644 index 0000000000000000000000000000000000000000..47d868a0cbacd1e3148c7fca84eb9a9f820e9b73 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ul.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/um.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/um.png new file mode 100644 index 0000000000000000000000000000000000000000..c45333e6034076b8fabc626ab19d9e2314ee5655 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/um.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/un.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/un.png new file mode 100644 index 0000000000000000000000000000000000000000..c3ba37c37f26ccdcd0c20722c65f4a7448b970fe Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/un.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uo.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uo.png new file mode 100644 index 0000000000000000000000000000000000000000..cac7b4ff2079b8d9954b83675da302bd1d6f75e0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uo.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/up.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/up.png new file mode 100644 index 0000000000000000000000000000000000000000..d48be7b8cfb41d25ad1e53532bd9c29a7dc776bc Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/up.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uq.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uq.png new file mode 100644 index 0000000000000000000000000000000000000000..d20612bf0e3f1f77cf23b2f812d1e18c0b5b66d6 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uq.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ur.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ur.png new file mode 100644 index 0000000000000000000000000000000000000000..e812c3186f8143411f9e41e603b163045099ea97 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ur.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/us.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/us.png new file mode 100644 index 0000000000000000000000000000000000000000..32042572115e3aa5bcd62cfd0e211660a6547f20 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/us.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ut.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ut.png new file mode 100644 index 0000000000000000000000000000000000000000..d897d27c64780aa6b2917b04be971d4991fb5c21 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ut.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uu.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uu.png new file mode 100644 index 0000000000000000000000000000000000000000..87ca6cec4eee8eddfcae7680b87d5691448dabba Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uu.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uv.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uv.png new file mode 100644 index 0000000000000000000000000000000000000000..8d6cd3bbdea1f593e8b09140f47ea859542679af Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uv.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uw.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uw.png new file mode 100644 index 0000000000000000000000000000000000000000..0d5f3890cb01ceade5bb9d1b17eb32a5feb383ae Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uw.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ux.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ux.png new file mode 100644 index 0000000000000000000000000000000000000000..024bade9b32aa3d20452de9f458bc00beba8f155 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/ux.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uy.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uy.png new file mode 100644 index 0000000000000000000000000000000000000000..cfa70de56d26d1a4158a9fb9759877fd01d17a68 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uy.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uz.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uz.png new file mode 100644 index 0000000000000000000000000000000000000000..8d1fcc83fe1d05564a170ac03ede1fc843b345e8 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/uz.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/v.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/v.png new file mode 100644 index 0000000000000000000000000000000000000000..0ad4cd8a334f33a21d9548486e4f6c2a2129e8bf Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/v.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/w.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/w.png new file mode 100644 index 0000000000000000000000000000000000000000..c6edcb49b5f460c2664587157b62cd46b45ed5ba Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/w.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/x.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/x.png new file mode 100644 index 0000000000000000000000000000000000000000..f299eeb12ce136b0b1ea8e07e023adf0085dd982 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/x.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/y.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/y.png new file mode 100644 index 0000000000000000000000000000000000000000..98c8626b14f31920ca63cb8c34911db9b173174d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/y.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/z.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/z.png new file mode 100644 index 0000000000000000000000000000000000000000..644a5b3158bab6d2441751b15836855112cc0d58 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/char/rm/z.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/1.png new file mode 100644 index 0000000000000000000000000000000000000000..3894249db8e513cde9912875bba551de948fdb46 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/2.png new file mode 100644 index 0000000000000000000000000000000000000000..c378fdce0806e48e96b716fbe655d93081f29af6 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/3.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/3.png new file mode 100644 index 0000000000000000000000000000000000000000..fad9d20cfe5e5b62a221a7ce9847dca79eae0e80 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/3.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/c1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/c1.png new file mode 100644 index 0000000000000000000000000000000000000000..a032d706d31c6cd9c38da923113a8345826ed9bd Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/c1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/c2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/c2.png new file mode 100644 index 0000000000000000000000000000000000000000..a8c95a87123b926713695f00e1ccf64b5821debb Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/c2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/c4.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/c4.png new file mode 100644 index 0000000000000000000000000000000000000000..74c5cdfe2e677593d0fd24cc0f6d506a0a9ca6f5 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/c4.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/c5.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/c5.png new file mode 100644 index 0000000000000000000000000000000000000000..05e6adfc38355d71e977905dfd661c4d8a9c5f8c Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/frac/c5.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/1.png new file mode 100644 index 0000000000000000000000000000000000000000..3654ff91c867daf6eabdb97f02ee3ac19116b676 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/2.png new file mode 100644 index 0000000000000000000000000000000000000000..a33c1dc13bdc3fcfbbbbc65422fe4e01fab424cf Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/3.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/3.png new file mode 100644 index 0000000000000000000000000000000000000000..3fc2186ac8cbb7ae187e6b1f41a990feb3a1dc60 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/3.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/4.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/4.png new file mode 100644 index 0000000000000000000000000000000000000000..6f528dbf975e917eadde81809ad3ab663a78e272 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/4.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/5.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/5.png new file mode 100644 index 0000000000000000000000000000000000000000..e22d59278cf4d3e295d481848a2ec245d5281ecd Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/5.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/6.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/6.png new file mode 100644 index 0000000000000000000000000000000000000000..2eed1bcd0533a3b6ecfc54f6f9d1cab3ef4c81f7 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/6.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/c1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/c1.png new file mode 100644 index 0000000000000000000000000000000000000000..d797cb8341215b0d5ec100495ae914f7f342f376 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/c1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/c2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/c2.png new file mode 100644 index 0000000000000000000000000000000000000000..4eb6c8f97db9305afdeca4956f320563a9e40e30 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/c2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/c3.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/c3.png new file mode 100644 index 0000000000000000000000000000000000000000..0f55b7e17fa552ec9a97f0624582e5c8ab9c1c74 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/func/c3.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/1.png new file mode 100644 index 0000000000000000000000000000000000000000..a08ab60d21cb2294337efc5017eec95d180b13a5 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/2.png new file mode 100644 index 0000000000000000000000000000000000000000..09cb7f882c266d4f44fa14fd9e9d01009ded3ffd Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/3.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/3.png new file mode 100644 index 0000000000000000000000000000000000000000..8898b845cadbea6308e115d76820120cefce16de Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/3.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/4.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/4.png new file mode 100644 index 0000000000000000000000000000000000000000..483092e69a6bd7acc836a05ef1cfd97870c578c6 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/4.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/5.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/5.png new file mode 100644 index 0000000000000000000000000000000000000000..604128ceda81954571b399706eec20a83e427dbe Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/5.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/6.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/6.png new file mode 100644 index 0000000000000000000000000000000000000000..287b6ca3da36e44daef8c3baa8ed58678a40ded8 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/int/6.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/large/1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/large/1.png new file mode 100644 index 0000000000000000000000000000000000000000..a83bf8ecbe0b70c109d0b01c91d01e848127eaf0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/large/1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/large/2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/large/2.png new file mode 100644 index 0000000000000000000000000000000000000000..705255335169d5d135e41a155067ac3caaf57cc2 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/large/2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/large/3.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/large/3.png new file mode 100644 index 0000000000000000000000000000000000000000..70b0f3e1d0603800b7411651fb2172f01955bb46 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/large/3.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/other.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/other.png new file mode 100644 index 0000000000000000000000000000000000000000..a5796aa82861db92a8d248df72c151f187032dd9 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/other.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/1.png new file mode 100644 index 0000000000000000000000000000000000000000..a40b79a60db45bd8ae0cf019f75f56612bab70bf Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/2.png new file mode 100644 index 0000000000000000000000000000000000000000..1eac155aae83d21adcf8317a8dcf8f80d0d964bd Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/3.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/3.png new file mode 100644 index 0000000000000000000000000000000000000000..3425abeb66f4ba54251eccc115ab990994e38888 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/3.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/4.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/4.png new file mode 100644 index 0000000000000000000000000000000000000000..fad9d20cfe5e5b62a221a7ce9847dca79eae0e80 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/4.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/c1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/c1.png new file mode 100644 index 0000000000000000000000000000000000000000..24cbd1bed5c5a1b6d637cd2779d580ebe44edf1a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/c1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/c2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/c2.png new file mode 100644 index 0000000000000000000000000000000000000000..572ad1ffba49478afcee3e46fee8198be363a0f6 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/c2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/c3.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/c3.png new file mode 100644 index 0000000000000000000000000000000000000000..d557b777e3a805de5d8a60b06cd6dae8752529ba Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/script/c3.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/1.png new file mode 100644 index 0000000000000000000000000000000000000000..f6d0f2e56f9112404f1e0371b7c6de48d3056e20 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/2.png new file mode 100644 index 0000000000000000000000000000000000000000..0ffbabb3fa71bdd73b484cd258268b3d294b4e75 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/3.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/3.png new file mode 100644 index 0000000000000000000000000000000000000000..1f1015648fed0dd3895cf3ccf8b84cacac2f3f9f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/3.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/4.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/4.png new file mode 100644 index 0000000000000000000000000000000000000000..66470a6b0d6767dbe7e4b9d716d09a6e32ee3256 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/4.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/c1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/c1.png new file mode 100644 index 0000000000000000000000000000000000000000..cf7beba696997e7c85b3a8883f5e0c4570d1c320 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/c1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/c2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/c2.png new file mode 100644 index 0000000000000000000000000000000000000000..35a5baeebbbd4bb8e941beb61d3b58724328b437 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/sqrt/c2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/ys/1.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/ys/1.png new file mode 100644 index 0000000000000000000000000000000000000000..f7c7d178e4c8187206da6934633424132e721cd0 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/ys/1.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/ys/2.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/ys/2.png new file mode 100644 index 0000000000000000000000000000000000000000..ee9586da60a286df2d113884f3c6b2dbc66201a4 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/ys/2.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/ys/3.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/ys/3.png new file mode 100644 index 0000000000000000000000000000000000000000..93f7d9c8a6d9e97b545fae0a2c91da23ee560767 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/images/toolbar/ys/3.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/styles/base.css b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/styles/base.css new file mode 100644 index 0000000000000000000000000000000000000000..355d9b0b8cfffb39715927b8783f3bf3c52659b0 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/styles/base.css @@ -0,0 +1,40 @@ + +.kf-editor { + width: 100%; + height: 100%; + border: 1px solid #e0e0e0; + position: relative; + top: 0; + left: 0; + + overflow: hidden; + z-index: 2; + background-color: #f6f5ee; +} + +.kf-editor-edit-area { + position: relative; + top: 0; + left: 0; + + z-index: 1; + height: 0; + background-color: white; + /*background-color: white;*/ + /*background-size: 21px 21px;*/ + /*background-position: 0 0,10px 10px;*/ + /*background-image: -webkit-linear-gradient(45deg,#efefef 25%,transparent 25%,transparent 75%,#efefef 75%,#efefef),-webkit-linear-gradient(45deg,#efefef 25%,transparent 25%,transparent 75%,#efefef 75%,#efefef);*/ + /*background-image: linear-gradient(45deg,#efefef 25%,transparent 25%,transparent 75%,#efefef 75%,#efefef),linear-gradient(45deg,#efefef 25%,transparent 25%,transparent 75%,#efefef 75%,#efefef);*/ +} + +.kf-editor-canvas-container { + width: 100%; + height: 100%; +} + +.kf-editor-input-box { + position: fixed; + top: 0; + left: -99999999px; + z-index: 999999; +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/styles/page.css b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/styles/page.css new file mode 100644 index 0000000000000000000000000000000000000000..8026403bb234793eb236712ac181b4e3c6393aac --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/styles/page.css @@ -0,0 +1,12 @@ + +html, body { + width: 100%; + height: 100%; + padding: 0; + margin: 0; + background: rgba( 48, 48, 48, 0.5 ); +} + +body { + height: 1000px; +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/styles/scrollbar.css b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/styles/scrollbar.css new file mode 100644 index 0000000000000000000000000000000000000000..b8254b0c9d9abb0a875f5ce7b5ac04070380fe8b --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/styles/scrollbar.css @@ -0,0 +1,78 @@ +/*! + * 滚动条 + **/ + +.kf-editor-edit-scrollbar { + width: 100%; + height: 16px; + position: absolute; + bottom: 0; + left: 0; + z-index: 994; + border-top: 1px solid #ddd; +} + +.kf-editor-ui-left-button { + position: absolute; + top: 0; + left: 0; + width: 5px; + height: 100%; + background: white; +} + +.kf-editor-ui-right-button { + position: absolute; + top: 0; + right: 0; + width: 5px; + height: 100%; + background: white; +} + +.kf-editor-ui-track { + position: absolute; + top: 0; + left: 5px; + width: 0; + height: 100%; + background-image: url(../images/scrollbar/edit/bar-left.png), url(../images/scrollbar/edit/bar-right.png), url(../images/scrollbar/edit/bar-bg.png); + background-repeat: no-repeat, no-repeat, repeat-x; + background-position: 0 0, right 0, 0 0; +} + +.kf-editor-ui-thumb { + position: absolute; + top: 0; + left: 0; + width: 0; + height: 100%; +} + +.kf-editor-ui-thumb-left { + width: 5px; + height: 100%; + position: absolute; + top: 0; + left: 0; + background: url(../images/scrollbar/edit/thumb-left.png) no-repeat 0 0; + z-index: 1; +} + +.kf-editor-ui-thumb-right { + width: 5px; + height: 100%; + position: absolute; + top: 0; + right: 0; + background: url(../images/scrollbar/edit/thumb-right.png) no-repeat 0 0; +} + +.kf-editor-ui-thumb-body { + position: absolute; + top: 0; + left: 5px; + width: 0; + height: 100%; + background: url(../images/scrollbar/edit/thumb-bg.png) repeat-x 0 0; +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/styles/ui.css b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/styles/ui.css new file mode 100644 index 0000000000000000000000000000000000000000..e8ac47083a99743511bc8f21e9d4e719ecf19885 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/styles/ui.css @@ -0,0 +1,536 @@ +/* 工具栏 */ +.kf-editor-toolbar { + width: 100%; + padding: 1px 10px; + position: relative; + top: 0; + left: 0; + z-index: 2; + background-color: #f6f5ee; + border-bottom: 1px solid #ccc; + -moz-box-shadow:1px 1px 1px rgba( 0, 0, 0, 0.1 ); + -webkit-box-shadow:1px 1px 1px rgba( 0, 0, 0, 0.1 ); + box-shadow:1px 1px 1px rgba( 0, 0, 0, 0.1 ); + color: #000; + font-family: Helvetica, Arial, "微软雅黑", "Microsoft YaHei", "宋体", sans-serif; +} + +/* 按钮 */ +.kf-editor-ui-button { + padding: 8px 6px; + height: 79px; + font-size: 12px; + display: inline-block; + border: 1px solid transparent; + border-radius: 3px; + cursor: default; + position: relative; + top: 0; + left: 0; + z-index: 3; + vertical-align: top; + opacity: 0.5; + margin-right: 1px; +} + +.kf-editor-toolbar .kf-editor-ui-overlap-button { + width: 100%; + height: 25px; + background: #53b856; + border-radius: 0; +} + +.kf-editor-ui-button-icon { + width: 32px; + height: 32px; + margin: 2px auto; +} + +.kf-editor-ui-button-label { + color: #666; + text-align: center; + display: block; + font-size: 12px; + line-height: 20px; +} + +.kf-editor-ui-overlap-button .kf-editor-ui-button-label { + padding: 3px 5px; + text-align: left; + color: white; + font-size: 12px; +} + +.kf-editor-ui-button-sign { + border: 4px solid transparent; + border-top-color: #2d2d2d; + width: 0; + height: 0; + display: inline-block; + margin: 8px auto; + vertical-align: top; +} + +.kf-editor-ui-button-mount-point { + display: none; + position: absolute; + bottom: -2px; + left: -1px; +} + +.kf-editor-ui-overlap-button .kf-editor-ui-button-mount-point { + width: 100%; + height: 10000px; +} + +.kf-editor-ui-wrap-group { + overflow-x: hidden; + overflow-y: auto; +} + +.kf-editor-ui-overlap-button .kf-editor-ui-button-mount-point { + top: 27px; +} + +.kf-editor-toolbar .kf-editor-ui-button-in { + border-color: #8fcc91!important; + background: #e0f0dd!important; +} + +.kf-editor-toolbar .kf-editor-ui-overlap-button { + padding-top: 0; + padding-bottom: 0; + border-color: #61b864!important; + background: #61b864!important; +} + +/* 分割符 */ +.kf-editor-ui-delimiter { + width: 11px; + height: 100%; + display: none; +} + +.kf-editor-ui-enabled.kf-editor-ui-button:HOVER { + border: 1px solid #a9d9ab; + background: #ebf7e6; +} + +.kf-editor-ui-enabled.kf-editor-ui-overlap-button:HOVER { + border: 1px solid #53b856; + background: #53b856; +} + +.kf-editor-ui-delimiter-line { + width: 1px; + height: 100%; + margin: 0 auto; + background: -webkit-linear-gradient(top, rgba(233, 233, 233, 0.11), rgba(92, 92, 92, 0.20) 60%, rgba(92, 92, 92, 0.41) 80%, rgba(123, 123, 123, 0.50)); +} + +/* box */ +.kf-editor-ui-box { + border: 1px solid #b3aead; + border-radius: 3px; + box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.11); + background: white; + position: absolute; + top: 0; + left: -1px; + overflow-x: hidden; + overflow-y: auto; +} + +.kf-editor-ui-area .kf-editor-ui-box { + border-color: #61b864; +} + +.kf-editor-ui-box-container { + font-size: 12px; +} + +.kf-editor-ui-box-group-title { + background-color: #f7f6f0; + height: 23px; + line-height: 23px; + font-size: 12px; + border: 1px solid #ebeae4; + border-width: 1px 0; + padding-left: 12px; +} + +.kf-editor-ui-box-group-item-container { + padding: 7px 9px 17px 9px; +} + +.kf-editor-ui-overlap-container { + overflow: hidden; +} + +.kf-editor-ui-area .kf-editor-ui-box { + top: -1px; +} + +.kf-editor-ui-overlap-container .kf-editor-ui-button-sign { + border-top-color: white; + border-width: 4px; + margin-left: 10px; + margin-top: 8px; +} + +.kf-editor-ui-yushe-btn .kf-editor-ui-box-item { + border: 1px solid transparent; + padding: 5px; +} + +.kf-editor-ui-box-item { + display: inline-block; + margin: 4px; +} + +.kf-editor-ui-box-item-content:HOVER { + border-color: #dff3df; +} + +.kf-editor-ui-box-item-content:HOVER .kf-editor-ui-box-item-val { + border-color: #6eb864; +} + +.kf-editor-ui-area .kf-editor-ui-box-item { + position: relative; + top: 0; + left: 0; + width: 32px; + height: 32px; + border: 0; + margin: 3px; + padding: 0; + z-index: 1; +} + +.kf-editor-ui-area .kf-editor-ui-box-item img { + width: 32px; + height: 32px; +} + + +.kf-editor-ui-box-item-label { + margin-bottom: 5px; +} + +.kf-editor-ui-box-item-content { + background: white; + border: 1px solid white; +} + +.kf-editor-ui-area .kf-editor-ui-box-item-content { + position: absolute; + top: 0; + left: 0; +} + +.kf-editor-ui-area .kf-editor-ui-box-item-content:HOVER { + border: 1px solid #dff3df; +} + +.kf-editor-ui-box-item-val { + padding: 5px; + line-height: 0; + border: 1px solid #808080; +} + +.kf-editor-ui-area .kf-editor-ui-box-item-val { + padding: 0; + margin: 0; +} + +/* area */ +.kf-editor-ui-area { + height: 79px; + display: inline-block; + cursor: default; + position: relative; + top: 0; + left: 0; + vertical-align: top; + opacity: 0.5; + z-index: 4; + border: 1px solid #e0dfd5; + border-radius: 4px; + background: white; + margin: 8px 10px; +} + +.kf-editor-ui-area-container { + width: 293px; + height: 70px; + /*margin: 7px 5px 5px 5px;*/ + margin: 5px; + display: inline-block; + border-right: 0; + vertical-align: top; + position: relative; + top: 0; + left: 0; + overflow: hidden; +} + +.kf-editor-ui-area-panel { + position: absolute; + top: 0; + left: 0; + line-height: 0; + background: white; + -webkit-transition: top 0.5s linear; + -moz-transition: top 0.5s linear; + transition: top 0.5s linear; +} + +.kf-editor-ui-area-button-container { + display: inline-block; + width: 16px; + height: 100%; + overflow: hidden; + text-align: center; + border: 0 solid #D3D3D3; + border-left-width: 1px; + background-color: #f2f0e6; +} + +.kf-editor-ui-moveup-button, .kf-editor-ui-movedown-button { + line-height: 25px; + height: 30px; +} + +.kf-editor-ui-moveup-button { + background: url("../images/toolbar/btn.png") -304px 9px no-repeat; +} + +.kf-editor-ui-movedown-button { + border: 1px solid #D3D3D3; + border-width: 1px 0; + background: url("../images/toolbar/btn.png") -325px 9px no-repeat; +} + +.kf-editor-ui-area-button { + width: 100%; + height: 50px; + line-height: 26px; + background: url("../images/toolbar/btn.png") -346px 0 no-repeat; +} + +.kf-editor-ui-enabled .kf-editor-ui-area-button:HOVER { + background-color: #e5e4e1; +} + +.kf-editor-ui-enabled .kf-editor-ui-moveup-button:HOVER { + background-color: #e5e4e1; +} + +.kf-editor-ui-enabled .kf-editor-ui-movedown-button:HOVER { + background-color: #e5e4e1; +} + +.kf-editor-ui-area-button-container .kf-editor-ui-disabled { + opacity: 0.25; + background-color: transparent!important; +} + +.kf-editor-ui-area-mount { + position: absolute; + top: 0; + left: 0; + display: none; +} + +.kf-editor-ui-overlap-title { + width: 100%; + line-height: 1.5; +} + +/* list */ +.kf-editor-ui-list { + background: #f9f8f5; + border: 1px solid #b3aead; + border-radius: 3px; + position: fixed; + top: 0; + left: 0; + box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.11); +} + +.kf-editor-ui-list-bg { + display: none; +} + +.kf-editor-ui-list-item-container { + position: relative; + top: 0; + left: 0; + z-index: 2; +} + +.kf-editor-ui-list-item { + line-height: 24px; + padding: 2px 6px; + border: 1px solid transparent; + border-width: 1px 0; +} + +.kf-editor-ui-list-item-select { + color: #61b864; + font-weight: bold; +} + +.kf-editor-ui-list-item-select .kf-editor-ui-list-item-icon { + visibility: visible; + width: 16px; + height: 16px; + background: url(../images/toolbar/btn.png) no-repeat -367px 0; +} + +.kf-editor-ui-list-item:HOVER { + border-color: #beddbf; + background-color: #ecf3e9; +} + +.kf-editor-ui-list-item-icon { + width: 16px; + height: 16px; + display: inline-block; + vertical-align: middle; + margin-top: -2px; + margin-right: 4px; + visibility: hidden; +} + +/* area 内容区 */ +.kf-editor-ui-area-item { + width: 26px; + height: 26px; + position: absolute; + top: 0; + left: 0; +} + +.kf-editor-ui-area-item-inner { + width: 34px; + height: 34px; + border: 1px solid white; + position: absolute; + top: -4px; + left: -4px; + -webkit-transition: all 0.1s linear; + -moz-transition: all 0.1s linear; + transition: all 0.1s linear; + + -webkit-transform: scale( 0.76 ); + -moz-transform: scale( 0.76 ); + transform: scale( 0.76 ); +} + +.kf-editor-ui-enabled .kf-editor-ui-area-item-inner:HOVER { + border-color: #dff3df; + + -webkit-transform: scale( 1 ); + -moz-transform: scale( 1 ); + transform: scale( 1 ); +} + +.kf-editor-ui-area-item-img { + width: 32px; + height: 32px; + border: 1px solid #808080; + -webkit-transition: all 0.1s linear; + -moz-transition: all 0.1s linear; + transition: all 0.1s linear; +} + +.kf-editor-ui-enabled .kf-editor-ui-area-item-inner:HOVER .kf-editor-ui-area-item-img { + border-color: #6eb864; +} + +.kf-editor-ui-enabled { + opacity: 1; +} + +.kf-editor-ui-overlap-container .kf-editor-ui-box-item { + width: 34px; + height: 34px; + border: 1px solid white; +} + +.kf-editor-ui-overlap-container .kf-editor-ui-box-item-content:HOVER { +} + +.kf-editor-ui-overlap-container .kf-editor-ui-box-item-val { + width: 32px; + height: 32px; +} + +/* scrollbar */ +.kf-editor-ui-box::-webkit-scrollbar { + width: 17px; + background: url(../images/scrollbar/custom/bg.png) 0 0 repeat-y white; +} + +.kf-editor-ui-box::-webkit-scrollbar-button:end:increment { + height: 5px; + background: url(../images/scrollbar/custom/down.png) 0 0 repeat-y white; +} +/*定义滚动条渐减按扭的样式 */ +.kf-editor-ui-box::-webkit-scrollbar-button:start:decrement { + height: 5px; + background: url(../images/scrollbar/custom/up.png) 0 0 repeat-y white; +} + +/* 垂直滚动条的第三层轨道的上段 */ +.kf-editor-ui-box::-webkit-scrollbar-track-piece:vertical:start { + background-image: url(../images/scrollbar/custom/top.png), url(../images/scrollbar/custom/bg.png); + background-repeat: no-repeat, repeat-y; +} +/* 垂直滚动条的第三层轨道的下段 */ +.kf-editor-ui-box::-webkit-scrollbar-track-piece:vertical:end { + background-image: url(../images/scrollbar/custom/bottom.png), url(../images/scrollbar/custom/bg.png); + background-repeat: no-repeat, repeat-y; + background-position: 0 bottom, 0 0; +} +/* 垂直滚动条的滑动块 */ +.kf-editor-ui-box::-webkit-scrollbar-thumb:vertical { + /*background: url(./images2/bar.png) 6px 0 no-repeat;*/ + /*background-size: 6px;*/ + -webkit-border-image: url(../images/scrollbar/custom/bar.png) 8; + border-width: 10px; +} + +.kf-editor-ui-wrap-group::-webkit-scrollbar { + width: 17px; + background: url(../images/scrollbar/custom/bg.png) 0 0 repeat-y white; +} + +.kf-editor-ui-wrap-group::-webkit-scrollbar-button:end:increment { + height: 5px; + background: url(../images/scrollbar/custom/down.png) 0 0 repeat-y white; +} +/*定义滚动条渐减按扭的样式 */ +.kf-editor-ui-wrap-group::-webkit-scrollbar-button:start:decrement { + height: 5px; + background: url(../images/scrollbar/custom/up.png) 0 0 repeat-y white; +} + +/* 垂直滚动条的第三层轨道的上段 */ +.kf-editor-ui-wrap-group::-webkit-scrollbar-track-piece:vertical:start { + background-image: url(../images/scrollbar/custom/top.png), url(../images/scrollbar/custom/bg.png); + background-repeat: no-repeat, repeat-y; +} +/* 垂直滚动条的第三层轨道的下段 */ +.kf-editor-ui-wrap-group::-webkit-scrollbar-track-piece:vertical:end { + background-image: url(../images/scrollbar/custom/bottom.png), url(../images/scrollbar/custom/bg.png); + background-repeat: no-repeat, repeat-y; + background-position: 0 bottom, 0 0; +} +/* 垂直滚动条的滑动块 */ +.kf-editor-ui-wrap-group::-webkit-scrollbar-thumb:vertical { + -webkit-border-image: url(../images/scrollbar/custom/bar.png) 8; + border-width: 10px; +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/fui.css b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/fui.css new file mode 100644 index 0000000000000000000000000000000000000000..de07bba550fb8ebfbf732e4a1990cb6c19f7854b --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/fui.css @@ -0,0 +1,540 @@ +/** + * 所有构件样式规则 + **/ +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-widget { + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-user-drag: none; + color: #000000; + line-height: 1.5; + font-size: 12px; + font-family: "ff-tisa-web-pro-1", "ff-tisa-web-pro-2", "Lucida Grande", "Hiragino Sans GB", "Hiragino Sans GB W3", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; + -webkit-font-smoothing: antialiased; + outline: none; + display: inline-block; + vertical-align: top; + position: relative; + top: 0; + left: 0; +} +.fui-widget.fui-selectable { + -webkit-user-select: text; + -khtml-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; + -webkit-user-drag: text; +} +.fui-widget * { + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-user-drag: none; +} +.fui-widget.fui-disabled { + opacity: 0.3!important; +} +.fui-widget.fui-hide { + display: none!important; +} +.fui-widget.fui-mask-animate { + -webkit-transition: all 0.2s; +} +.fui-widget.fui-mask-hint { + -webkit-transform: perspective(600px) translateZ(30px); +} + +/** + * 容器类通用样式 + **/ +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-container { + overflow: hidden; + position: relative; + top: 0; + left: 0; +} +.fui-container.fui-disabled { + opacity: 1!important; +} + +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-button-menu { + border: 1px solid white; +} +.fui-button-menu:HOVER { + border-color: #d5e1f2; +} +.fui-button-menu.fui-button-active { + border-color: #d5e1f2; + background: #d5e1f2; +} +.fui-button-menu.fui-button-active .fui-button { + background: #d5e1f2; +} +.fui-button-menu.fui-layout-top, +.fui-button-menu.fui-layout-bottom { + text-align: center; +} +.fui-button-menu.fui-layout-top .fui-open-btn, +.fui-button-menu.fui-layout-bottom .fui-open-btn { + display: block; +} + +/** + * 通用button + */ +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-button { + overflow: hidden; + cursor: default; + font-size: 0; +} +.fui-button ._layout .fui-label { + display: block; +} +.fui-button ._layout .fui-icon { + display: block; +} +.fui-button .fui-icon { + display: inline-block; + vertical-align: middle; +} +.fui-button .fui-label { + display: inline-block; + vertical-align: middle; +} +.fui-button.fui-button-layout-top .fui-label { + display: block; +} +.fui-button.fui-button-layout-top .fui-icon { + display: block; +} +.fui-button.fui-button-layout-bottom .fui-label { + display: block; +} +.fui-button.fui-button-layout-bottom .fui-icon { + display: block; +} +.fui-button:HOVER { + background-color: #d5e1f2 !important; + color: #000000 !important; +} +.fui-button:ACTIVE { + background-color: #87a9da !important; + color: #000000 !important; +} +.fui-button.fui-disabled:HOVER { + background-color: #ffffff !important; + color: #000000 !important; +} +.fui-button.fui-disabled:ACTIVE { + background-color: #ffffff !important; + color: #000000 !important; +} + +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-colorpicker { + background-color: #fff; +} +.fui-colorpicker-container { + border: 1px solid #d3d3d3; +} +.fui-colorpicker-container .fui-colorpicker-title { + background: #eee; + padding: 2px 4px; +} +.fui-colorpicker-container .fui-colorpicker-colors { + margin: 0; + padding: 0; + font-size: 0; + line-height: 0; +} +.fui-colorpicker-container .fui-colorpicker-colors-line0 { + margin-bottom: 3px; +} +.fui-colorpicker-container .fui-colorpicker-item { + display: inline-block; + margin: 0 2px; + width: 13px; + height: 13px; + border-style: solid; + border-width: 1px; +} +.fui-colorpicker-container .fui-colorpicker-commoncolor, +.fui-colorpicker-container .fui-colorpicker-standardcolor { + margin: 4px 3px; + white-space: nowrap; +} +.fui-colorpicker-container .fui-colorpicker-toolbar { + margin: 4px; + height: 27px; +} +.fui-colorpicker-container .fui-colorpicker-toolbar .fui-colorpicker-preview { + display: inline-block; + height: 25px; + line-height: 25px; + width: 120px; + border: 1px solid #d3d3d3; +} +.fui-colorpicker-container .fui-colorpicker-toolbar .fui-colorpicker-clear { + display: inline-block; + height: 25px; + line-height: 25px; + width: 60px; + border: 1px solid #d3d3d3; + font-size: 12px; + text-align: center; + position: absolute; + right: 5px; + cursor: pointer; +} + +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ + +/** + * 通用button + */ +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-dialog { + position: fixed; + top: -1000000px; + left: -100000px; + border: 1px solid #B1B1B1; + background: #fff; +} +.fui-dialog .fui-panel-content { + width: auto!important; + height: auto!important; + padding: 2px; +} +.fui-dialog .fui-dialog-caption { + margin: 0; + padding: 5px; + font-size: 16px; + font-weight: normal; + line-height: 1; + display: inline-block; +} +.fui-dialog .fui-dialog-head .fui-close-button { + float: right; +} +.fui-dialog .fui-dialog-head .fui-close-button .fui-close-button-icon { + width: 16px; + height: 16px; + background: url("images/close.png") no-repeat 0 0; +} + +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-drop-panel { + border: 1px solid #d3d3d3; + overflow: hidden; + position: relative; +} +.fui-drop-panel .fui-drop-panel-content { + display: inline-block; +} +.fui-drop-panel .fui-drop-panel-placeholder { + display: none; +} +.fui-drop-panel .fui-drop-panel-button { + border-left: 1px solid #d3d3d3; + visibility: visible; +} +.fui-drop-panel .fui-drop-panel-button:HOVER { + border-color: #d5e1f2; +} +.fui-drop-panel .fui-drop-panel-button:ACTIVE { + border-color: #87a9da; +} +.fui-drop-panel:HOVER { + border-color: #d5e1f2; +} +.fui-drop-panel:HOVER .fui-drop-panel-button { + border-left-color: #d5e1f2; +} +.fui-drop-panel:ACTIVE { + border-color: #87a9da; +} +.fui-drop-panel:ACTIVE .fui-drop-panel-button { + border-left-color: #d5e1f2; +} +.fui-drop-panel.fui-drop-panel-open { + overflow: visible; +} +.fui-drop-panel.fui-drop-panel-open .fui-drop-panel-content { + border: 1px solid #d3d3d3; + position: absolute; + top: -1px; + left: -1px; +} +.fui-drop-panel.fui-drop-panel-open .fui-drop-panel-button { + visibility: hidden; +} +.fui-drop-panel.fui-drop-panel-open .fui-drop-panel-placeholder { + display: inline-block; +} +.fui-drop-panel-popup { + border: 1px solid #d3d3d3; +} +.fui-drop-panel-popup:HOVER { + border-color: #d5e1f2; +} +.fui-drop-panel-popup:HOVER .fui-drop-panel-button { + border-left-color: #d5e1f2; +} +.fui-drop-panel-popup:ACTIVE { + border-color: #87a9da; +} +.fui-drop-panel-popup:ACTIVE .fui-drop-panel-button { + border-left-color: #d5e1f2; +} + +.fui-icon { + text-align: center; + font-size: 0; +} +.fui-icon img { + display: inline-block; +} + +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-input-button { + border: 1px solid #ababab; +} +.fui-input-button .fui-input { + vertical-align: middle; + border: none!important; +} +.fui-input-button .fui-button { + vertical-align: middle; +} +.fui-input-button:HOVER { + border-color: #87a9da; +} +.fui-input-button:ACTIVE { + border-color: #87a9da; +} + +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-input { + border: 1px solid #d3d3d3; + padding: 1px; + margin: 0; +} +.fui-input:HOVER, +.fui-input:FOCUS { + border-color: #4d90fe!important; +} + +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-item { + font-size: 0; +} +.fui-item .fui-icon { + vertical-align: middle; +} +.fui-item .fui-label { + vertical-align: middle; +} +.fui-item.fui-item-selected { + background: #87a9da; +} + +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-label-panel .fui-label-panel-label { + width: 100%; + color: #666; +} +.fui-label-panel.fui-no-position .fui-label-panel-label { + position: static!important; +} +.fui-label-panel.fui-layout-bottom .fui-label-panel-label { + position: absolute; + bottom: 0; + left: 0; + top: auto; + z-index: 2; +} + +.fui-label { + cursor: default; + display: inline-block; + white-space: nowrap; +} + +/** + * 通用button + */ +.fui-mask { + position: fixed; + z-index: 99998; +} + +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-menu { + background-color: #fff; + border: 1px solid #d3d3d3; +} +.fui-menu .fui-item { + padding: 2px 5px; + display: block!important; +} +.fui-menu .fui-item:HOVER { + background: #d5e1f2; +} + +/** + * 通用button + */ +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-panel { + display: inline-block; + vertical-align: top; + overflow-y: auto; + overflow-x: hidden; +} +.fui-panel .fui-panel-content { + position: relative; + top: 0; + left: 0; +} +.fui-panel .fui-panel-content { + width: 100%; + height: 100%; +} +.fui-panel.fui-container-column { + font-size: 0; +} +.fui-panel.fui-container-column .fui-column { + display: block; +} + +/** + * 通用button + */ +.fui-ppanel::-webkit-scrollbar { + width: 15px; +} +.fui-ppanel::-webkit-scrollbar-button:start:decrement, +.fui-ppanel::-webkit-scrollbar-button:end:decrement, +.fui-ppanel::-webkit-scrollbar-button:start:increment, +.fui-ppanel::-webkit-scrollbar-button:end:increment, +.fui-ppanel::-webkit-scrollbar-thumb { + border: 1px solid #e7e7e7; +} +.fui-ppanel.fui-ppanel-position { + position: fixed; + z-index: 99999; +} + +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-separator { + background: #6d6d6d; +} + +/** + * Spin-button + */ +.fui-spin-button .fui-spin-up-btn .fui-icon, +.fui-spin-button .fui-spin-down-btn .fui-icon { + width: 16px; + height: 9px; + background: url("images/up.png") no-repeat 3px 1.5px; +} +.fui-spin-button .fui-spin-down-btn .fui-icon { + background-image: url("images/down.png"); +} + +/** + * 通用button + */ +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-tabs .fui-selected { + background-color: #d5e1f2; +} + +/** + * 可切换Button (ToggleButton) + */ +/** + * FUI 通用样式定义 + */ +/*------------ var*/ +/*------------ mixin*/ +.fui-toggle-button.fui-button-pressed { + background-color: #aec5e6; +} +.fui-toggle-button.fui-button-pressed.fui-disabled { + background-color: #aec5e6 !important; +} diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/fui.min.css b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/fui.min.css new file mode 100644 index 0000000000000000000000000000000000000000..3faab2ac1ea32991c667e6ff208385bbb4f6a06b --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/fui.min.css @@ -0,0 +1,10 @@ +/*! + * ==================================================== + * Themes file * Flex UI - v1.0.0 - 2014-07-28 + * https://github.com/fex-team/fui + * GitHub: https://github.com/fex-team/fui.git + * Copyright (c) 2014 Baidu Kity Group; Licensed MIT + * ==================================================== + */ + +.fui-widget{-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-user-drag:none;color:#000;line-height:1.5;font-size:12px;font-family:ff-tisa-web-pro-1,ff-tisa-web-pro-2,"Lucida Grande","Hiragino Sans GB","Hiragino Sans GB W3","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;-webkit-font-smoothing:antialiased;outline:0;display:inline-block;vertical-align:top;position:relative;top:0;left:0}.fui-widget.fui-selectable{-webkit-user-select:text;-khtml-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;-webkit-user-drag:text}.fui-widget *{-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-user-drag:none}.fui-widget.fui-disabled{opacity:.3!important}.fui-widget.fui-hide{display:none!important}.fui-widget.fui-mask-animate{-webkit-transition:all .2s}.fui-widget.fui-mask-hint{-webkit-transform:perspective(600px) translateZ(30px)}.fui-container{overflow:hidden;position:relative;top:0;left:0}.fui-container.fui-disabled{opacity:1!important}.fui-button-menu{border:1px solid #fff}.fui-button-menu:HOVER{border-color:#d5e1f2}.fui-button-menu.fui-button-active{border-color:#d5e1f2;background:#d5e1f2}.fui-button-menu.fui-button-active .fui-button{background:#d5e1f2}.fui-button-menu.fui-layout-bottom,.fui-button-menu.fui-layout-top{text-align:center}.fui-button-menu.fui-layout-bottom .fui-open-btn,.fui-button-menu.fui-layout-top .fui-open-btn{display:block}.fui-button{overflow:hidden;cursor:default;font-size:0}.fui-button ._layout .fui-icon,.fui-button ._layout .fui-label{display:block}.fui-button .fui-icon,.fui-button .fui-label{display:inline-block;vertical-align:middle}.fui-button.fui-button-layout-bottom .fui-icon,.fui-button.fui-button-layout-bottom .fui-label,.fui-button.fui-button-layout-top .fui-icon,.fui-button.fui-button-layout-top .fui-label{display:block}.fui-button:HOVER{background-color:#d5e1f2!important;color:#000!important}.fui-button:ACTIVE{background-color:#87a9da!important;color:#000!important}.fui-button.fui-disabled:ACTIVE,.fui-button.fui-disabled:HOVER{background-color:#fff!important;color:#000!important}.fui-colorpicker{background-color:#fff}.fui-colorpicker-container{border:1px solid #d3d3d3}.fui-colorpicker-container .fui-colorpicker-title{background:#eee;padding:2px 4px}.fui-colorpicker-container .fui-colorpicker-colors{margin:0;padding:0;font-size:0;line-height:0}.fui-colorpicker-container .fui-colorpicker-colors-line0{margin-bottom:3px}.fui-colorpicker-container .fui-colorpicker-item{display:inline-block;margin:0 2px;width:13px;height:13px;border-style:solid;border-width:1px}.fui-colorpicker-container .fui-colorpicker-commoncolor,.fui-colorpicker-container .fui-colorpicker-standardcolor{margin:4px 3px;white-space:nowrap}.fui-colorpicker-container .fui-colorpicker-toolbar{margin:4px;height:27px}.fui-colorpicker-container .fui-colorpicker-toolbar .fui-colorpicker-preview{display:inline-block;height:25px;line-height:25px;width:120px;border:1px solid #d3d3d3}.fui-colorpicker-container .fui-colorpicker-toolbar .fui-colorpicker-clear{display:inline-block;height:25px;line-height:25px;width:60px;border:1px solid #d3d3d3;font-size:12px;text-align:center;position:absolute;right:5px;cursor:pointer}.fui-dialog{position:fixed;top:-1000000px;left:-100000px;border:1px solid #B1B1B1;background:#fff}.fui-dialog .fui-panel-content{width:auto!important;height:auto!important;padding:2px}.fui-dialog .fui-dialog-caption{margin:0;padding:5px;font-size:16px;font-weight:400;line-height:1;display:inline-block}.fui-dialog .fui-dialog-head .fui-close-button{float:right}.fui-dialog .fui-dialog-head .fui-close-button .fui-close-button-icon{width:16px;height:16px;background:url(images/close.png) no-repeat}.fui-drop-panel{border:1px solid #d3d3d3;overflow:hidden;position:relative}.fui-drop-panel .fui-drop-panel-content{display:inline-block}.fui-drop-panel .fui-drop-panel-placeholder{display:none}.fui-drop-panel .fui-drop-panel-button{border-left:1px solid #d3d3d3;visibility:visible}.fui-drop-panel .fui-drop-panel-button:HOVER{border-color:#d5e1f2}.fui-drop-panel .fui-drop-panel-button:ACTIVE{border-color:#87a9da}.fui-drop-panel:HOVER{border-color:#d5e1f2}.fui-drop-panel:HOVER .fui-drop-panel-button{border-left-color:#d5e1f2}.fui-drop-panel:ACTIVE{border-color:#87a9da}.fui-drop-panel:ACTIVE .fui-drop-panel-button{border-left-color:#d5e1f2}.fui-drop-panel.fui-drop-panel-open{overflow:visible}.fui-drop-panel.fui-drop-panel-open .fui-drop-panel-content{border:1px solid #d3d3d3;position:absolute;top:-1px;left:-1px}.fui-drop-panel.fui-drop-panel-open .fui-drop-panel-button{visibility:hidden}.fui-drop-panel.fui-drop-panel-open .fui-drop-panel-placeholder{display:inline-block}.fui-drop-panel-popup{border:1px solid #d3d3d3}.fui-drop-panel-popup:HOVER{border-color:#d5e1f2}.fui-drop-panel-popup:HOVER .fui-drop-panel-button{border-left-color:#d5e1f2}.fui-drop-panel-popup:ACTIVE{border-color:#87a9da}.fui-drop-panel-popup:ACTIVE .fui-drop-panel-button{border-left-color:#d5e1f2}.fui-icon{text-align:center;font-size:0}.fui-icon img{display:inline-block}.fui-input-button{border:1px solid #ababab}.fui-input-button .fui-input{vertical-align:middle;border:none!important}.fui-input-button .fui-button{vertical-align:middle}.fui-input-button:ACTIVE,.fui-input-button:HOVER{border-color:#87a9da}.fui-input{border:1px solid #d3d3d3;padding:1px;margin:0}.fui-input:FOCUS,.fui-input:HOVER{border-color:#4d90fe!important}.fui-item{font-size:0}.fui-item .fui-icon,.fui-item .fui-label{vertical-align:middle}.fui-item.fui-item-selected{background:#87a9da}.fui-label-panel .fui-label-panel-label{width:100%;color:#666}.fui-label-panel.fui-no-position .fui-label-panel-label{position:static!important}.fui-label-panel.fui-layout-bottom .fui-label-panel-label{position:absolute;bottom:0;left:0;top:auto;z-index:2}.fui-label{cursor:default;display:inline-block;white-space:nowrap}.fui-mask{position:fixed;z-index:99998}.fui-menu{background-color:#fff;border:1px solid #d3d3d3}.fui-menu .fui-item{padding:2px 5px;display:block!important}.fui-menu .fui-item:HOVER{background:#d5e1f2}.fui-panel{display:inline-block;vertical-align:top;overflow-y:auto;overflow-x:hidden}.fui-panel .fui-panel-content{position:relative;top:0;left:0;width:100%;height:100%}.fui-panel.fui-container-column{font-size:0}.fui-panel.fui-container-column .fui-column{display:block}.fui-ppanel::-webkit-scrollbar{width:15px}.fui-ppanel::-webkit-scrollbar-button:end:decrement,.fui-ppanel::-webkit-scrollbar-button:end:increment,.fui-ppanel::-webkit-scrollbar-button:start:decrement,.fui-ppanel::-webkit-scrollbar-button:start:increment,.fui-ppanel::-webkit-scrollbar-thumb{border:1px solid #e7e7e7}.fui-ppanel.fui-ppanel-position{position:fixed;z-index:99999}.fui-separator{background:#6d6d6d}.fui-spin-button .fui-spin-down-btn .fui-icon,.fui-spin-button .fui-spin-up-btn .fui-icon{width:16px;height:9px;background:url(images/up.png) 3px 1.5px no-repeat}.fui-spin-button .fui-spin-down-btn .fui-icon{background-image:url(images/down.png)}.fui-tabs .fui-selected{background-color:#d5e1f2}.fui-toggle-button.fui-button-pressed{background-color:#aec5e6}.fui-toggle-button.fui-button-pressed.fui-disabled{background-color:#aec5e6!important} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/images/close.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/images/close.png new file mode 100644 index 0000000000000000000000000000000000000000..4f8885f47e0ce084c2a963bad9a3d9998e4c292d Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/images/close.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/images/down.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/images/down.png new file mode 100644 index 0000000000000000000000000000000000000000..cf92db68069cad3c42ef007f543f905fe00fb2b3 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/images/down.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/images/open.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/images/open.png new file mode 100644 index 0000000000000000000000000000000000000000..861a04e883c7eeabda06bf1ea385218b2c34ff3e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/images/open.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/images/up.png b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/images/up.png new file mode 100644 index 0000000000000000000000000000000000000000..4e4a6d1f9831b280fc99774f19b835ae0ff96c7e Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/assets/theme/default/images/up.png differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/js/jquery-3.6.0.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/js/jquery-3.6.0.min.js new file mode 100644 index 0000000000000000000000000000000000000000..c4c6022f2982e8dae64cebd6b9a2b59f2547faad --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/js/jquery-3.6.0.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
                                                                                          "],col:[2,"","
                                                                                          "],tr:[2,"","
                                                                                          "],td:[3,"","
                                                                                          "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
                                                                                          ",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0p;p++)k=n[p],k!==h?k?"string"==typeof k?(n[p]="brackets"===e.name&&2>p?k:"function"===e.name&&0===p?k:c("text",k),f.operand.push(n[p])):(f.operand.push({}),n[p]=b(a.operand[p],k,f.operand[f.operand.length-1],g,i)):(n[p]=c("empty"),f.operand.push(n[p])):(m.push(p),i.hasOwnProperty("startOffset")||(i.startOffset=p),i.endOffset=p,e.attr&&e.attr.id&&(i.groupId=e.attr.id));for(2===m.length&&(i.endOffset-=1);p=m.length;)p=m[p-1],n.splice(p,1),m.length--,a.operand.splice(p,1)}if(o=d(e.name),!o)throw new Error("operator type error: not found "+e.operator);j=function(){},j.prototype=o.prototype,l=new j,o.apply(l,n),f.func=l;for(var r in e.callFn)e.callFn.hasOwnProperty(r)&&l[r]&&l[r].apply(l,e.callFn[r]);return e.attr&&(e.attr.id&&(g[e.attr.id]={objGroup:l,strGroup:a}),e.attr["data-root"]&&(g.root={objGroup:l,strGroup:a}),l.setAttr(e.attr)),l}function c(a,b){switch(a){case"empty":return new kf.EmptyExpression;case"text":return new kf.TextExpression(b)}}function d(a){return g[a]||kf[a.replace(/^[a-z]/i,function(a){return a.toUpperCase()}).replace(/-([a-z])/gi,function(a,b){return b.toUpperCase()})+"Expression"]}function e(a){var b={};if("[object Array]"==={}.toString.call(a)){b=[];for(var c=0,d=a.length;d>c;c++)b[c]=f(a[c])}else for(var e in a)a.hasOwnProperty(e)&&(b[e]=f(a[e]));return b}function f(a){return a?"object"!=typeof a?a:e(a):a}var g={},h="\uf155";return a.prototype.generateBy=function(a){var c=a.tree,d={},f={},g={};if("string"==typeof c)throw new Error("Unhandled error");return this.formula.appendExpression(b(c,e(c),d,g,f)),{select:f,parsedTree:c,tree:d,mapping:g}},a.prototype.regenerateBy=function(a){return this.formula.clearExpressions(),this.generateBy(a)},a}},b[1]={value:function(){return{toRPNExpression:b.r(2),generateTree:b.r(3)}}},b[2]={value:function(){function a(b){var e=[],f=null;for(b=c(b);f=b.shift();)"combination"===f.name&&1===f.operand.length&&"brackets"===f.operand[0].name&&(f=f.operand[0]),e.push(d.isArray(f)?a(f):f);return e}function c(a){for(var b=[],c=null;void 0!==(c=a.pop());)if(!c||"object"!=typeof c||c.sign!==!1&&"function"!==c.name)b.push(c);else{var d=c.handler(c,[],b.reverse());b.unshift(d),b.reverse()}return b.reverse()}var d=b.r(4);return a}},b[3]={value:function(){function a(b){for(var e=null,f=[],g=0,h=b.length;h>g;g++)d.isArray(b[g])&&(b[g]=a(b[g]));for(;e=b.shift();)f.push("object"==typeof e&&e.handler?e.handler(e,f,b):e);return c(f)}var c=b.r(13),d=b.r(4);return a}},b[4]={value:function(){var a=b.r(7),c=b.r(6),d=b.r(15),e={getLatexType:function(b){return b=b.replace(/^\\/,""),a[b]?"operator":c[b]?"function":"text"},isArray:function(a){return a&&"[object Array]"===Object.prototype.toString.call(a)},getDefine:function(b){return e.extend({},a[b.replace("\\","")])},getFuncDefine:function(a){return{name:"function",params:a.replace(/^\\/,""),handler:d}},getBracketsDefine:function(b,c){return e.extend({params:[b,c]},a.brackets)},extend:function(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}};return e}},b[5]={value:function(){var a=!0;return{".":a,"{":a,"}":a,"[":a,"]":a,"(":a,")":a,"|":a}}},b[6]={value:function(){return{sin:1,cos:1,arccos:1,cosh:1,det:1,inf:1,limsup:1,Pr:1,tan:1,arcsin:1,cot:1,dim:1,ker:1,ln:1,sec:1,tanh:1,arctan:1,coth:1,exp:1,lg:1,log:1,arg:1,csc:1,gcd:1,lim:1,max:1,sinh:1,deg:1,hom:1,liminf:1,min:1,sup:1}}},b[7]={value:function(){var a=b.r(22),c=b.r(11);return{"^":{name:"superscript",type:c.OP,handler:a},_:{name:"subscript",type:c.OP,handler:a},frac:{name:"fraction",type:c.FN,sign:!1,handler:b.r(14)},sqrt:{name:"radical",type:c.FN,sign:!1,handler:b.r(23)},sum:{name:"summation",type:c.FN,traversal:"rtl",handler:b.r(24)},"int":{name:"integration",type:c.FN,traversal:"rtl",handler:b.r(16)},brackets:{name:"brackets",type:c.FN,handler:b.r(12)},mathcal:{name:"mathcal",type:c.FN,sign:!1,handler:b.r(19)},mathfrak:{name:"mathfrak",type:c.FN,sign:!1,handler:b.r(20)},mathbb:{name:"mathbb",type:c.FN,sign:!1,handler:b.r(18)},mathrm:{name:"mathrm",type:c.FN,sign:!1,handler:b.r(21)}}}},b[8]={value:function(){return{"int":b.r(26),quot:b.r(27)}}},b[9]={value:function(){return{combination:b.r(29),fraction:b.r(30),"function":b.r(31),integration:b.r(32),subscript:b.r(39),superscript:b.r(41),script:b.r(37),radical:b.r(38),summation:b.r(40),brackets:b.r(28),mathcal:b.r(34),mathfrak:b.r(35),mathbb:b.r(33),mathrm:b.r(36)}}},b[10]={value:function(){return{"#":1,$:1,"%":1,_:1,"&":1,"{":1,"}":1,"^":1,"~":1}}},b[11]={value:function(){return{OP:1,FN:2}}},b[12]={value:function(){var a=b.r(5);return function(b,c,d){for(var e=0,f=b.params.length;f>e;e++)if(!(b.params[e]in a))throw new Error("Brackets: invalid params");return b.operand=b.params,b.params[2]=d.shift(),delete b.handler,delete b.params,b}}},b[13]={value:function(){return function(){return{name:"combination",operand:arguments[0]||[]}}}},b[14]={value:function(){return function(a,b,c){var d=c.shift(),e=c.shift();if(void 0===d||void 0===e)throw new Error("Frac: Syntax Error");return d.handler&&"integration"===d.name?(d=d.handler(d,b,[e]),e=c.shift()):e.handler&&"integration"===e.name&&(e=e.handler(e,b,[c.shift()])),a.operand=[d,e],delete a.handler,a}}},b[15]={value:function(){var a=b.r(17);return function(b,c,d){var e=a.exec(d);return e.expr&&e.expr.handler&&"integration"===e.expr.name&&(e.expr=e.expr.handler(e.expr,c,[d.shift()])),b.operand=[b.params,e.expr,e.superscript,e.subscript],delete b.params,delete b.handler,b}}},b[16]={value:function(){var a=b.r(17),c=b.r(11).FN;return function(b,d,e){var f=e.shift(),g=a.exec(e);return g.expr&&g.expr.type===c&&g.expr.handler&&"integration"===g.expr.name&&(g.expr=g.expr.handler(g.expr,d,[e.shift()])),b.operand=[g.expr,g.superscript,g.subscript],b.callFn={setType:[0|f]},delete b.handler,b}}},b[17]={value:function(){function a(a){var c=b(a),d=null,e={superscript:null,subscript:null};if(!c)return e;if(d=b(a),e[c.type]=c.value||null,d){if(d.type===c.type)throw new Error("Script: syntax error!");e[d.type]=d.value||null}return e}function b(a){var b=a.shift();return b?"subscript"===b.name||"superscript"===b.name?{type:b.name,value:a.shift()}:(a.unshift(b),null):null}return{exec:function(b){var c=a(b),d=b.shift();if(d&&d.name&&-1!==d.name.indexOf("script"))throw new Error("Script: syntax error!");return c.expr=d||null,c}}}},b[18]={value:function(){return function(a,b,c){var d=c.shift();return"object"==typeof d&&"combination"===d.name&&(d=d.operand.join("")),a.name="text",a.attr={_reverse:"mathbb"},a.callFn={setFamily:["KF AMS BB"]},a.operand=[d],delete a.handler,a}}},b[19]={value:function(){return function(a,b,c){var d=c.shift();return"object"==typeof d&&"combination"===d.name&&(d=d.operand.join("")),a.name="text",a.attr={_reverse:"mathcal"},a.callFn={setFamily:["KF AMS CAL"]},a.operand=[d],delete a.handler,a}}},b[20]={value:function(){return function(a,b,c){var d=c.shift();return"object"==typeof d&&"combination"===d.name&&(d=d.operand.join("")),a.name="text",a.attr={_reverse:"mathfrak"},a.callFn={setFamily:["KF AMS FRAK"]},a.operand=[d],delete a.handler,a}}},b[21]={value:function(){return function(a,b,c){var d=c.shift();return"object"==typeof d&&"combination"===d.name&&(d=d.operand.join("")),a.name="text",a.attr={_reverse:"mathrm"},a.callFn={setFamily:["KF AMS ROMAN"]},a.operand=[d],delete a.handler,a}}},b[22]={value:function(){return function(a,b,c){var d=b.pop(),e=c.shift()||null;if(!e)throw new Error("Missing script");if(d=d||"",d.name===a.name||"script"===d.name)throw new Error("script error");return"subscript"===d.name?(d.name="script",d.operand[2]=d.operand[1],d.operand[1]=e,d):"superscript"===d.name?(d.name="script",d.operand[2]=e,d):(a.operand=[d,e],delete a.handler,a)}}},b[23]={value:function(){var a=b.r(13);return function(b,c,d){var e=d.shift(),f=null,g=null;if("["===e){for(e=[];(f=d.shift())&&"]"!==f;)e.push(f);e=0===e.length?null:a(e),g=d.shift()}else g=e,e=null;return b.operand=[g,e],delete b.handler,b}}},b[24]={value:function(){var a=b.r(17),c=b.r(11).FN;return function(b,d,e){var f=a.exec(e);return f.expr&&f.expr.type===c&&f.expr.handler&&"integration"===f.expr.name&&(f.expr=f.expr.handler(f.expr,d,[e.shift()])),b.operand=[f.expr,f.superscript,f.subscript],delete b.handler,b}}},b[25]={value:function(){function a(a){if(d(a))return a.substring(1);switch(m.getLatexType(a)){case"operator":return m.getDefine(a);case"function":return m.getFuncDefine(a);default:return c(a)}}function c(a){return 0===a.indexOf("\\")?a+"\\":a}function d(a){return 0===a.indexOf("\\")?!!l[a.substring(1)]:!1}function e(a){return a.replace(/\\\s+/,"").replace(/\s*([^a-z0-9\s])\s*/gi,function(a,b){return b})}var f=b.r(43).Parser,g=b.r(1),h=b.r(8),i=b.r(42),j=b.r(7),k=b.r(9),l=b.r(10),m=b.r(4),n="\ufff8",o="\ufffc",p=new RegExp(n+"|"+o,"g"),q=new RegExp(n,"g"),r=new RegExp(o,"g");f.register("latex",f.implement({parse:function(a){var b=this.split(this.format(a));return b=this.parseToGroup(b),b=this.parseToStruct(b),this.generateTree(b)},serialization:function(a,b){return i(a,b)},expand:function(a){var b=a.parse,c=null,d=a.pre,e=a.reverse;for(var f in b)b.hasOwnProperty(f)&&(c=f.replace(/\\/g,""),j[c]=b[f]);for(var f in e)e.hasOwnProperty(f)&&(k[f.replace(/\\/g,"")]=e[f]);if(d)for(var f in d)d.hasOwnProperty(f)&&(h[f.replace(/\\/g,"")]=d[f])},format:function(a){a=e(a),a=a.replace(p,"").replace(/\\{/gi,n).replace(/\\}/gi,o);for(var b in h)h.hasOwnProperty(b)&&(a=h[b](a));return a},split:function(a){var b=[],c=/(?:\\[^a-z]\s*)|(?:\\[a-z]+\s*)|(?:[{}]\s*)|(?:[^\\{}]\s*)/gi,d=/^\s+|\s+$/g,e=null;for(a=a.replace(d,"");e=c.exec(a);)e=e[0].replace(d,""),e&&b.push(e);return b},generateTree:function(a){for(var b=[],c=null;c=a.shift();)b.push(m.isArray(c)?this.generateTree(c):c);return b=g.toRPNExpression(b),g.generateTree(b)},parseToGroup:function(a){for(var b=[],c=[b],d=0,e=0,f=0,g=a.length;g>f;f++)switch(a[f]){case"{":d++,c.push(b),b.push([]),b=b[b.length-1];break;case"}":d--,b=c.pop();break;case"\\left":e++,c.push(b),b.push([[]]),b=b[b.length-1][0],b.type="brackets",f++,b.leftBrackets=a[f].replace(q,"{").replace(r,"}");break;case"\\right":e--,f++,b.rightBrackets=a[f].replace(q,"{").replace(r,"}"),b=c.pop();break;default:b.push(a[f].replace(q,"\\{").replace(r,"\\}"))}if(0!==d)throw new Error("Group Error!");if(0!==e)throw new Error("Brackets Error!");return c[0]},parseToStruct:function(b){for(var c=[],d=0,e=b.length;e>d;d++)m.isArray(b[d])?"brackets"===b[d].type?(c.push(m.getBracketsDefine(b[d].leftBrackets,b[d].rightBrackets)),c.push(this.parseToStruct(b[d]))):c.push(this.parseToStruct(b[d])):c.push(a(b[d]));return c}}))}},b[26]={value:function(){return function(a){return a.replace(/\\(i+)nt(\b|[^a-zA-Z])/g,function(a,b,c){return"\\int "+b.length+c})}}},b[27]={value:function(){return function(a){return a.replace(/``/g,"\u201c")}}},b[28]={value:function(){return function(a){return("{"===a[0]||"}"===a[0])&&(a[0]="\\"+a[0]),("{"===a[1]||"}"===a[1])&&(a[1]="\\"+a[1]),["\\left",a[0],a[2],"\\right",a[1]].join(" ")}}},b[29]={value:function(){return function(a){return this.attr["data-root"]||this.attr["data-placeholder"]?a.join(""):"{"+a.join("")+"}"}}},b[30]={value:function(){return function(a){return"\\frac "+a[0]+" "+a[1]}}},b[31]={value:function(){return function(a){var b=["\\"+a[0]];return a[2]&&b.push("^"+a[2]),a[3]&&b.push("_"+a[3]),a[1]&&b.push(" "+a[1]),b.join("")}}},b[32]={value:function(){return function(a){var b=["\\int "];if(this.callFn&&this.callFn.setType){b=["\\"];for(var c=0,d=this.callFn.setType;d>c;c++)b.push("i");b.push("nt ")}return a[1]&&b.push("^"+a[1]),a[2]&&b.push("_"+a[2]),a[0]&&b.push(" "+a[0]),b.join("")}}},b[33]={value:function(){return function(a){return"\\mathbb{"+a[0]+"}"}}},b[34]={value:function(){return function(a){return"\\mathcal{"+a[0]+"}"}}},b[35]={value:function(){return function(a){return"\\mathfrak{"+a[0]+"}"}}},b[36]={value:function(){return function(a){return"\\mathrm{"+a[0]+"}"}}},b[37]={value:function(){return function(a){return a[0]+"^"+a[1]+"_"+a[2]}}},b[38]={value:function(){return function(a){var b=["\\sqrt"];return a[1]&&b.push("["+a[1]+"]"),b.push(" "+a[0]),b.join("")}}},b[39]={value:function(){return function(a){return a[0]+"_"+a[1]}}},b[40]={value:function(){return function(a){var b=["\\sum "];return a[1]&&b.push("^"+a[1]),a[2]&&b.push("_"+a[2]),a[0]&&b.push(" "+a[0]),b.join("")}}},b[41]={value:function(){return function(a){return a[0]+"^"+a[1]}}},b[42]={value:function(){function a(b,e){var g=[],h=null,i=null;if("object"!=typeof b)return c(b)?"\\"+b+" ":b.replace(f,function(a,b){return b+" "});"combination"===b.name&&1===b.operand.length&&"combination"===b.operand[0].name&&(b=b.operand[0]),i=b.operand;for(var j=0,k=i.length;k>j;j++)g.push(i[j]?a(i[j]):i[j]);return h=b.attr&&b.attr._reverse?b.attr._reverse:b.name,d[h].call(b,g,e)}function c(a){return!!e[a]}var d=b.r(9),e=b.r(10),f=/(\\(?:[\w]+)|(?:[^a-z]))\\/gi;return function(b,c){return a(b,c)}}},b[43]={value:function(a,b,c){function d(a){this.impl=new a,this.conf={}}function e(){this.conf={}}var f={},g={},h={extend:function(a,b){var c=null;b=[].slice.call(arguments,1);for(var d=0,e=b.length;e>d;d++){c=b[d];for(var f in c)c.hasOwnProperty(f)&&(a[f]=c[f])}},setData:function(a,b,c){if("string"==typeof b)a[b]=c;else{if("object"!=typeof b)throw new Error("invalid option");for(c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}}},i={use:function(a){if(!g[a])throw new Error("unknown parser type");return this.proxy(g[a])},config:function(a,b){return h.setData(f,a,b),this},register:function(a,b){return g[a.toLowerCase()]=b,this},implement:function(a){var b=function(){},c=a.constructor||function(){},d=function(){e.call(this),c.call(this)};b.prototype=e.prototype,d.prototype=new b,delete a.constructor;for(var f in a)"constructor"!==f&&a.hasOwnProperty(f)&&(d.prototype[f]=a[f]);return d},proxy:function(a){return new d(a)}};h.extend(d.prototype,{config:function(a,b){h.setData(this.conf,a,b)},set:function(a,b){this.impl.set(a,b)},parse:function(a){var b={config:{},tree:this.impl.parse(a)};return h.extend(b.config,f,this.conf),b},serialization:function(a,b){return this.impl.serialization(a,b)},expand:function(a){this.impl.expand(a)}}),h.extend(e.prototype,{set:function(a,b){h.extend(this.conf,a,b)},parse:function(){throw new Error("Abstract function")}}),c.exports={Parser:i,ParserInterface:e}}},b[44]={value:function(){var a=b.r(43).Parser;b.r(25),window.kf.Parser=a,window.kf.Assembly=b.r(0)}};var c={"kf.start":44};!function(){try{a("kf.start")}catch(b){}}(this)}(); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/js/kity-formula-render.all.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/js/kity-formula-render.all.js new file mode 100644 index 0000000000000000000000000000000000000000..80665993b6bfe5d26925a5599cecac437f88a1e7 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/js/kity-formula-render.all.js @@ -0,0 +1,5757 @@ +/*! + * ==================================================== + * Kity Formula Render - v1.0.0 - 2014-07-30 + * https://github.com/kitygraph/formula + * GitHub: https://github.com/kitygraph/formula.git + * Copyright (c) 2014 Baidu Kity Group; Licensed MIT + * ==================================================== + */ + +(function () { +var _p = { + r: function(index) { + if (_p[index].inited) { + return _p[index].value; + } + if (typeof _p[index].value === "function") { + var module = { + exports: {} + }, returnValue = _p[index].value(null, module.exports, module); + _p[index].inited = true; + _p[index].value = returnValue; + if (returnValue !== undefined) { + return returnValue; + } else { + for (var key in module.exports) { + if (module.exports.hasOwnProperty(key)) { + _p[index].inited = true; + _p[index].value = module.exports; + return module.exports; + } + } + } + } else { + _p[index].inited = true; + return _p[index].value; + } + } +}; + +/*! + * canvg库封装 + * canvg官网: https://code.google.com/p/canvg/ + */ +_p[0] = { + value: function(require) { + /** + * A class to parse color values + * @author Stoyan Stefanov + * @link http://www.phpied.com/rgb-color-parser-in-javascript/ + * @license Use it if you like it + */ + function RGBColor(color_string) { + this.ok = false; + // strip any leading # + if (color_string.charAt(0) == "#") { + // remove # if any + color_string = color_string.substr(1, 6); + } + color_string = color_string.replace(/ /g, ""); + color_string = color_string.toLowerCase(); + // before getting into regexps, try simple matches + // and overwrite the input + var simple_colors = { + aliceblue: "f0f8ff", + antiquewhite: "faebd7", + aqua: "00ffff", + aquamarine: "7fffd4", + azure: "f0ffff", + beige: "f5f5dc", + bisque: "ffe4c4", + black: "000000", + blanchedalmond: "ffebcd", + blue: "0000ff", + blueviolet: "8a2be2", + brown: "a52a2a", + burlywood: "deb887", + cadetblue: "5f9ea0", + chartreuse: "7fff00", + chocolate: "d2691e", + coral: "ff7f50", + cornflowerblue: "6495ed", + cornsilk: "fff8dc", + crimson: "dc143c", + cyan: "00ffff", + darkblue: "00008b", + darkcyan: "008b8b", + darkgoldenrod: "b8860b", + darkgray: "a9a9a9", + darkgreen: "006400", + darkkhaki: "bdb76b", + darkmagenta: "8b008b", + darkolivegreen: "556b2f", + darkorange: "ff8c00", + darkorchid: "9932cc", + darkred: "8b0000", + darksalmon: "e9967a", + darkseagreen: "8fbc8f", + darkslateblue: "483d8b", + darkslategray: "2f4f4f", + darkturquoise: "00ced1", + darkviolet: "9400d3", + deeppink: "ff1493", + deepskyblue: "00bfff", + dimgray: "696969", + dodgerblue: "1e90ff", + feldspar: "d19275", + firebrick: "b22222", + floralwhite: "fffaf0", + forestgreen: "228b22", + fuchsia: "ff00ff", + gainsboro: "dcdcdc", + ghostwhite: "f8f8ff", + gold: "ffd700", + goldenrod: "daa520", + gray: "808080", + green: "008000", + greenyellow: "adff2f", + honeydew: "f0fff0", + hotpink: "ff69b4", + indianred: "cd5c5c", + indigo: "4b0082", + ivory: "fffff0", + khaki: "f0e68c", + lavender: "e6e6fa", + lavenderblush: "fff0f5", + lawngreen: "7cfc00", + lemonchiffon: "fffacd", + lightblue: "add8e6", + lightcoral: "f08080", + lightcyan: "e0ffff", + lightgoldenrodyellow: "fafad2", + lightgrey: "d3d3d3", + lightgreen: "90ee90", + lightpink: "ffb6c1", + lightsalmon: "ffa07a", + lightseagreen: "20b2aa", + lightskyblue: "87cefa", + lightslateblue: "8470ff", + lightslategray: "778899", + lightsteelblue: "b0c4de", + lightyellow: "ffffe0", + lime: "00ff00", + limegreen: "32cd32", + linen: "faf0e6", + magenta: "ff00ff", + maroon: "800000", + mediumaquamarine: "66cdaa", + mediumblue: "0000cd", + mediumorchid: "ba55d3", + mediumpurple: "9370d8", + mediumseagreen: "3cb371", + mediumslateblue: "7b68ee", + mediumspringgreen: "00fa9a", + mediumturquoise: "48d1cc", + mediumvioletred: "c71585", + midnightblue: "191970", + mintcream: "f5fffa", + mistyrose: "ffe4e1", + moccasin: "ffe4b5", + navajowhite: "ffdead", + navy: "000080", + oldlace: "fdf5e6", + olive: "808000", + olivedrab: "6b8e23", + orange: "ffa500", + orangered: "ff4500", + orchid: "da70d6", + palegoldenrod: "eee8aa", + palegreen: "98fb98", + paleturquoise: "afeeee", + palevioletred: "d87093", + papayawhip: "ffefd5", + peachpuff: "ffdab9", + peru: "cd853f", + pink: "ffc0cb", + plum: "dda0dd", + powderblue: "b0e0e6", + purple: "800080", + red: "ff0000", + rosybrown: "bc8f8f", + royalblue: "4169e1", + saddlebrown: "8b4513", + salmon: "fa8072", + sandybrown: "f4a460", + seagreen: "2e8b57", + seashell: "fff5ee", + sienna: "a0522d", + silver: "c0c0c0", + skyblue: "87ceeb", + slateblue: "6a5acd", + slategray: "708090", + snow: "fffafa", + springgreen: "00ff7f", + steelblue: "4682b4", + tan: "d2b48c", + teal: "008080", + thistle: "d8bfd8", + tomato: "ff6347", + turquoise: "40e0d0", + violet: "ee82ee", + violetred: "d02090", + wheat: "f5deb3", + white: "ffffff", + whitesmoke: "f5f5f5", + yellow: "ffff00", + yellowgreen: "9acd32" + }; + for (var key in simple_colors) { + if (color_string == key) { + color_string = simple_colors[key]; + } + } + // emd of simple type-in colors + // array of color definition objects + var color_defs = [ { + re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, + example: [ "rgb(123, 234, 45)", "rgb(255,234,245)" ], + process: function(bits) { + return [ parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]) ]; + } + }, { + re: /^(\w{2})(\w{2})(\w{2})$/, + example: [ "#00ff00", "336699" ], + process: function(bits) { + return [ parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16) ]; + } + }, { + re: /^(\w{1})(\w{1})(\w{1})$/, + example: [ "#fb0", "f0f" ], + process: function(bits) { + return [ parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16) ]; + } + } ]; + // search through the definitions to find a match + for (var i = 0; i < color_defs.length; i++) { + var re = color_defs[i].re; + var processor = color_defs[i].process; + var bits = re.exec(color_string); + if (bits) { + channels = processor(bits); + this.r = channels[0]; + this.g = channels[1]; + this.b = channels[2]; + this.ok = true; + } + } + // validate/cleanup values + this.r = this.r < 0 || isNaN(this.r) ? 0 : this.r > 255 ? 255 : this.r; + this.g = this.g < 0 || isNaN(this.g) ? 0 : this.g > 255 ? 255 : this.g; + this.b = this.b < 0 || isNaN(this.b) ? 0 : this.b > 255 ? 255 : this.b; + // some getters + this.toRGB = function() { + return "rgb(" + this.r + ", " + this.g + ", " + this.b + ")"; + }; + this.toHex = function() { + var r = this.r.toString(16); + var g = this.g.toString(16); + var b = this.b.toString(16); + if (r.length == 1) r = "0" + r; + if (g.length == 1) g = "0" + g; + if (b.length == 1) b = "0" + b; + return "#" + r + g + b; + }; + // help + this.getHelpXML = function() { + var examples = new Array(); + // add regexps + for (var i = 0; i < color_defs.length; i++) { + var example = color_defs[i].example; + for (var j = 0; j < example.length; j++) { + examples[examples.length] = example[j]; + } + } + // add type-in colors + for (var sc in simple_colors) { + examples[examples.length] = sc; + } + var xml = document.createElement("ul"); + xml.setAttribute("id", "rgbcolor-examples"); + for (var i = 0; i < examples.length; i++) { + try { + var list_item = document.createElement("li"); + var list_color = new RGBColor(examples[i]); + var example_div = document.createElement("div"); + example_div.style.cssText = "margin: 3px; " + "border: 1px solid black; " + "background:" + list_color.toHex() + "; " + "color:" + list_color.toHex(); + example_div.appendChild(document.createTextNode("test")); + var list_item_value = document.createTextNode(" " + examples[i] + " -> " + list_color.toRGB() + " -> " + list_color.toHex()); + list_item.appendChild(example_div); + list_item.appendChild(list_item_value); + xml.appendChild(list_item); + } catch (e) {} + } + return xml; + }; + } + /* + + StackBlur - a fast almost Gaussian Blur For Canvas + + Version: 0.5 + Author: Mario Klingemann + Contact: mario@quasimondo.com + Website: http://www.quasimondo.com/StackBlurForCanvas + Twitter: @quasimondo + + In case you find this class useful - especially in commercial projects - + I am not totally unhappy for a small donation to my PayPal account + mario@quasimondo.de + + Or support me on flattr: + https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript + + Copyright (c) 2010 Mario Klingemann + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + */ + var mul_table = [ 512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259 ]; + var shg_table = [ 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 ]; + function stackBlurImage(imageID, canvasID, radius, blurAlphaChannel) { + var img = document.getElementById(imageID); + var w = img.naturalWidth; + var h = img.naturalHeight; + var canvas = document.getElementById(canvasID); + canvas.style.width = w + "px"; + canvas.style.height = h + "px"; + canvas.width = w; + canvas.height = h; + var context = canvas.getContext("2d"); + context.clearRect(0, 0, w, h); + context.drawImage(img, 0, 0); + if (isNaN(radius) || radius < 1) return; + if (blurAlphaChannel) stackBlurCanvasRGBA(canvasID, 0, 0, w, h, radius); else stackBlurCanvasRGB(canvasID, 0, 0, w, h, radius); + } + function stackBlurCanvasRGBA(id, top_x, top_y, width, height, radius) { + if (isNaN(radius) || radius < 1) return; + radius |= 0; + var canvas = document.getElementById(id); + var context = canvas.getContext("2d"); + var imageData; + try { + try { + imageData = context.getImageData(top_x, top_y, width, height); + } catch (e) { + // NOTE: this part is supposedly only needed if you want to work with local files + // so it might be okay to remove the whole try/catch block and just use + // imageData = context.getImageData( top_x, top_y, width, height ); + try { + netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); + imageData = context.getImageData(top_x, top_y, width, height); + } catch (e) { + alert("Cannot access local image"); + throw new Error("unable to access local image data: " + e); + return; + } + } + } catch (e) { + alert("Cannot access image"); + throw new Error("unable to access image data: " + e); + } + var pixels = imageData.data; + var x, y, i, p, yp, yi, yw, r_sum, g_sum, b_sum, a_sum, r_out_sum, g_out_sum, b_out_sum, a_out_sum, r_in_sum, g_in_sum, b_in_sum, a_in_sum, pr, pg, pb, pa, rbs; + var div = radius + radius + 1; + var w4 = width << 2; + var widthMinus1 = width - 1; + var heightMinus1 = height - 1; + var radiusPlus1 = radius + 1; + var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2; + var stackStart = new BlurStack(); + var stack = stackStart; + for (i = 1; i < div; i++) { + stack = stack.next = new BlurStack(); + if (i == radiusPlus1) var stackEnd = stack; + } + stack.next = stackStart; + var stackIn = null; + var stackOut = null; + yw = yi = 0; + var mul_sum = mul_table[radius]; + var shg_sum = shg_table[radius]; + for (y = 0; y < height; y++) { + r_in_sum = g_in_sum = b_in_sum = a_in_sum = r_sum = g_sum = b_sum = a_sum = 0; + r_out_sum = radiusPlus1 * (pr = pixels[yi]); + g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]); + b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]); + a_out_sum = radiusPlus1 * (pa = pixels[yi + 3]); + r_sum += sumFactor * pr; + g_sum += sumFactor * pg; + b_sum += sumFactor * pb; + a_sum += sumFactor * pa; + stack = stackStart; + for (i = 0; i < radiusPlus1; i++) { + stack.r = pr; + stack.g = pg; + stack.b = pb; + stack.a = pa; + stack = stack.next; + } + for (i = 1; i < radiusPlus1; i++) { + p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2); + r_sum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - i); + g_sum += (stack.g = pg = pixels[p + 1]) * rbs; + b_sum += (stack.b = pb = pixels[p + 2]) * rbs; + a_sum += (stack.a = pa = pixels[p + 3]) * rbs; + r_in_sum += pr; + g_in_sum += pg; + b_in_sum += pb; + a_in_sum += pa; + stack = stack.next; + } + stackIn = stackStart; + stackOut = stackEnd; + for (x = 0; x < width; x++) { + pixels[yi + 3] = pa = a_sum * mul_sum >> shg_sum; + if (pa != 0) { + pa = 255 / pa; + pixels[yi] = (r_sum * mul_sum >> shg_sum) * pa; + pixels[yi + 1] = (g_sum * mul_sum >> shg_sum) * pa; + pixels[yi + 2] = (b_sum * mul_sum >> shg_sum) * pa; + } else { + pixels[yi] = pixels[yi + 1] = pixels[yi + 2] = 0; + } + r_sum -= r_out_sum; + g_sum -= g_out_sum; + b_sum -= b_out_sum; + a_sum -= a_out_sum; + r_out_sum -= stackIn.r; + g_out_sum -= stackIn.g; + b_out_sum -= stackIn.b; + a_out_sum -= stackIn.a; + p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2; + r_in_sum += stackIn.r = pixels[p]; + g_in_sum += stackIn.g = pixels[p + 1]; + b_in_sum += stackIn.b = pixels[p + 2]; + a_in_sum += stackIn.a = pixels[p + 3]; + r_sum += r_in_sum; + g_sum += g_in_sum; + b_sum += b_in_sum; + a_sum += a_in_sum; + stackIn = stackIn.next; + r_out_sum += pr = stackOut.r; + g_out_sum += pg = stackOut.g; + b_out_sum += pb = stackOut.b; + a_out_sum += pa = stackOut.a; + r_in_sum -= pr; + g_in_sum -= pg; + b_in_sum -= pb; + a_in_sum -= pa; + stackOut = stackOut.next; + yi += 4; + } + yw += width; + } + for (x = 0; x < width; x++) { + g_in_sum = b_in_sum = a_in_sum = r_in_sum = g_sum = b_sum = a_sum = r_sum = 0; + yi = x << 2; + r_out_sum = radiusPlus1 * (pr = pixels[yi]); + g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]); + b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]); + a_out_sum = radiusPlus1 * (pa = pixels[yi + 3]); + r_sum += sumFactor * pr; + g_sum += sumFactor * pg; + b_sum += sumFactor * pb; + a_sum += sumFactor * pa; + stack = stackStart; + for (i = 0; i < radiusPlus1; i++) { + stack.r = pr; + stack.g = pg; + stack.b = pb; + stack.a = pa; + stack = stack.next; + } + yp = width; + for (i = 1; i <= radius; i++) { + yi = yp + x << 2; + r_sum += (stack.r = pr = pixels[yi]) * (rbs = radiusPlus1 - i); + g_sum += (stack.g = pg = pixels[yi + 1]) * rbs; + b_sum += (stack.b = pb = pixels[yi + 2]) * rbs; + a_sum += (stack.a = pa = pixels[yi + 3]) * rbs; + r_in_sum += pr; + g_in_sum += pg; + b_in_sum += pb; + a_in_sum += pa; + stack = stack.next; + if (i < heightMinus1) { + yp += width; + } + } + yi = x; + stackIn = stackStart; + stackOut = stackEnd; + for (y = 0; y < height; y++) { + p = yi << 2; + pixels[p + 3] = pa = a_sum * mul_sum >> shg_sum; + if (pa > 0) { + pa = 255 / pa; + pixels[p] = (r_sum * mul_sum >> shg_sum) * pa; + pixels[p + 1] = (g_sum * mul_sum >> shg_sum) * pa; + pixels[p + 2] = (b_sum * mul_sum >> shg_sum) * pa; + } else { + pixels[p] = pixels[p + 1] = pixels[p + 2] = 0; + } + r_sum -= r_out_sum; + g_sum -= g_out_sum; + b_sum -= b_out_sum; + a_sum -= a_out_sum; + r_out_sum -= stackIn.r; + g_out_sum -= stackIn.g; + b_out_sum -= stackIn.b; + a_out_sum -= stackIn.a; + p = x + ((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2; + r_sum += r_in_sum += stackIn.r = pixels[p]; + g_sum += g_in_sum += stackIn.g = pixels[p + 1]; + b_sum += b_in_sum += stackIn.b = pixels[p + 2]; + a_sum += a_in_sum += stackIn.a = pixels[p + 3]; + stackIn = stackIn.next; + r_out_sum += pr = stackOut.r; + g_out_sum += pg = stackOut.g; + b_out_sum += pb = stackOut.b; + a_out_sum += pa = stackOut.a; + r_in_sum -= pr; + g_in_sum -= pg; + b_in_sum -= pb; + a_in_sum -= pa; + stackOut = stackOut.next; + yi += width; + } + } + context.putImageData(imageData, top_x, top_y); + } + function stackBlurCanvasRGB(id, top_x, top_y, width, height, radius) { + if (isNaN(radius) || radius < 1) return; + radius |= 0; + var canvas = document.getElementById(id); + var context = canvas.getContext("2d"); + var imageData; + try { + try { + imageData = context.getImageData(top_x, top_y, width, height); + } catch (e) { + // NOTE: this part is supposedly only needed if you want to work with local files + // so it might be okay to remove the whole try/catch block and just use + // imageData = context.getImageData( top_x, top_y, width, height ); + try { + netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); + imageData = context.getImageData(top_x, top_y, width, height); + } catch (e) { + alert("Cannot access local image"); + throw new Error("unable to access local image data: " + e); + return; + } + } + } catch (e) { + alert("Cannot access image"); + throw new Error("unable to access image data: " + e); + } + var pixels = imageData.data; + var x, y, i, p, yp, yi, yw, r_sum, g_sum, b_sum, r_out_sum, g_out_sum, b_out_sum, r_in_sum, g_in_sum, b_in_sum, pr, pg, pb, rbs; + var div = radius + radius + 1; + var w4 = width << 2; + var widthMinus1 = width - 1; + var heightMinus1 = height - 1; + var radiusPlus1 = radius + 1; + var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2; + var stackStart = new BlurStack(); + var stack = stackStart; + for (i = 1; i < div; i++) { + stack = stack.next = new BlurStack(); + if (i == radiusPlus1) var stackEnd = stack; + } + stack.next = stackStart; + var stackIn = null; + var stackOut = null; + yw = yi = 0; + var mul_sum = mul_table[radius]; + var shg_sum = shg_table[radius]; + for (y = 0; y < height; y++) { + r_in_sum = g_in_sum = b_in_sum = r_sum = g_sum = b_sum = 0; + r_out_sum = radiusPlus1 * (pr = pixels[yi]); + g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]); + b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]); + r_sum += sumFactor * pr; + g_sum += sumFactor * pg; + b_sum += sumFactor * pb; + stack = stackStart; + for (i = 0; i < radiusPlus1; i++) { + stack.r = pr; + stack.g = pg; + stack.b = pb; + stack = stack.next; + } + for (i = 1; i < radiusPlus1; i++) { + p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2); + r_sum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - i); + g_sum += (stack.g = pg = pixels[p + 1]) * rbs; + b_sum += (stack.b = pb = pixels[p + 2]) * rbs; + r_in_sum += pr; + g_in_sum += pg; + b_in_sum += pb; + stack = stack.next; + } + stackIn = stackStart; + stackOut = stackEnd; + for (x = 0; x < width; x++) { + pixels[yi] = r_sum * mul_sum >> shg_sum; + pixels[yi + 1] = g_sum * mul_sum >> shg_sum; + pixels[yi + 2] = b_sum * mul_sum >> shg_sum; + r_sum -= r_out_sum; + g_sum -= g_out_sum; + b_sum -= b_out_sum; + r_out_sum -= stackIn.r; + g_out_sum -= stackIn.g; + b_out_sum -= stackIn.b; + p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2; + r_in_sum += stackIn.r = pixels[p]; + g_in_sum += stackIn.g = pixels[p + 1]; + b_in_sum += stackIn.b = pixels[p + 2]; + r_sum += r_in_sum; + g_sum += g_in_sum; + b_sum += b_in_sum; + stackIn = stackIn.next; + r_out_sum += pr = stackOut.r; + g_out_sum += pg = stackOut.g; + b_out_sum += pb = stackOut.b; + r_in_sum -= pr; + g_in_sum -= pg; + b_in_sum -= pb; + stackOut = stackOut.next; + yi += 4; + } + yw += width; + } + for (x = 0; x < width; x++) { + g_in_sum = b_in_sum = r_in_sum = g_sum = b_sum = r_sum = 0; + yi = x << 2; + r_out_sum = radiusPlus1 * (pr = pixels[yi]); + g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]); + b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]); + r_sum += sumFactor * pr; + g_sum += sumFactor * pg; + b_sum += sumFactor * pb; + stack = stackStart; + for (i = 0; i < radiusPlus1; i++) { + stack.r = pr; + stack.g = pg; + stack.b = pb; + stack = stack.next; + } + yp = width; + for (i = 1; i <= radius; i++) { + yi = yp + x << 2; + r_sum += (stack.r = pr = pixels[yi]) * (rbs = radiusPlus1 - i); + g_sum += (stack.g = pg = pixels[yi + 1]) * rbs; + b_sum += (stack.b = pb = pixels[yi + 2]) * rbs; + r_in_sum += pr; + g_in_sum += pg; + b_in_sum += pb; + stack = stack.next; + if (i < heightMinus1) { + yp += width; + } + } + yi = x; + stackIn = stackStart; + stackOut = stackEnd; + for (y = 0; y < height; y++) { + p = yi << 2; + pixels[p] = r_sum * mul_sum >> shg_sum; + pixels[p + 1] = g_sum * mul_sum >> shg_sum; + pixels[p + 2] = b_sum * mul_sum >> shg_sum; + r_sum -= r_out_sum; + g_sum -= g_out_sum; + b_sum -= b_out_sum; + r_out_sum -= stackIn.r; + g_out_sum -= stackIn.g; + b_out_sum -= stackIn.b; + p = x + ((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2; + r_sum += r_in_sum += stackIn.r = pixels[p]; + g_sum += g_in_sum += stackIn.g = pixels[p + 1]; + b_sum += b_in_sum += stackIn.b = pixels[p + 2]; + stackIn = stackIn.next; + r_out_sum += pr = stackOut.r; + g_out_sum += pg = stackOut.g; + b_out_sum += pb = stackOut.b; + r_in_sum -= pr; + g_in_sum -= pg; + b_in_sum -= pb; + stackOut = stackOut.next; + yi += width; + } + } + context.putImageData(imageData, top_x, top_y); + } + function BlurStack() { + this.r = 0; + this.g = 0; + this.b = 0; + this.a = 0; + this.next = null; + } + /* + * canvg.js - Javascript SVG parser and renderer on Canvas + * MIT Licensed + * Gabe Lerner (gabelerner@gmail.com) + * http://code.google.com/p/canvg/ + * + * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/ + */ + (function() { + // canvg(target, s) + // empty parameters: replace all 'svg' elements on page with 'canvas' elements + // target: canvas element or the id of a canvas element + // s: svg string, url to svg file, or xml document + // opts: optional hash of options + // ignoreMouse: true => ignore mouse events + // ignoreAnimation: true => ignore animations + // ignoreDimensions: true => does not try to resize canvas + // ignoreClear: true => does not clear canvas + // offsetX: int => draws at a x offset + // offsetY: int => draws at a y offset + // scaleWidth: int => scales horizontally to width + // scaleHeight: int => scales vertically to height + // renderCallback: function => will call the function after the first render is completed + // forceRedraw: function => will call the function on every frame, if it returns true, will redraw + this.canvg = function(target, s, opts) { + // no parameters + if (target == null && s == null && opts == null) { + var svgTags = document.getElementsByTagName("svg"); + for (var i = 0; i < svgTags.length; i++) { + var svgTag = svgTags[i]; + var c = document.createElement("canvas"); + c.width = svgTag.clientWidth; + c.height = svgTag.clientHeight; + svgTag.parentNode.insertBefore(c, svgTag); + svgTag.parentNode.removeChild(svgTag); + var div = document.createElement("div"); + div.appendChild(svgTag); + canvg(c, div.innerHTML); + } + return; + } + opts = opts || {}; + if (typeof target == "string") { + target = document.getElementById(target); + } + // store class on canvas + if (target.svg != null) target.svg.stop(); + var svg = build(); + // on i.e. 8 for flash canvas, we can't assign the property so check for it + if (!(target.childNodes.length == 1 && target.childNodes[0].nodeName == "OBJECT")) target.svg = svg; + svg.opts = opts; + var ctx = target.getContext("2d"); + if (typeof s.documentElement != "undefined") { + // load from xml doc + svg.loadXmlDoc(ctx, s); + } else if (s.substr(0, 1) == "<") { + // load from xml string + svg.loadXml(ctx, s); + } else { + // load from url + svg.load(ctx, s); + } + }; + function build() { + var svg = {}; + svg.FRAMERATE = 30; + svg.MAX_VIRTUAL_PIXELS = 3e4; + // globals + svg.init = function(ctx) { + var uniqueId = 0; + svg.UniqueId = function() { + uniqueId++; + return "canvg" + uniqueId; + }; + svg.Definitions = {}; + svg.Styles = {}; + svg.Animations = []; + svg.Images = []; + svg.ctx = ctx; + svg.ViewPort = new function() { + this.viewPorts = []; + this.Clear = function() { + this.viewPorts = []; + }; + this.SetCurrent = function(width, height) { + this.viewPorts.push({ + width: width, + height: height + }); + }; + this.RemoveCurrent = function() { + this.viewPorts.pop(); + }; + this.Current = function() { + return this.viewPorts[this.viewPorts.length - 1]; + }; + this.width = function() { + return this.Current().width; + }; + this.height = function() { + return this.Current().height; + }; + this.ComputeSize = function(d) { + if (d != null && typeof d == "number") return d; + if (d == "x") return this.width(); + if (d == "y") return this.height(); + return Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2); + }; + }(); + }; + svg.init(); + // images loaded + svg.ImagesLoaded = function() { + for (var i = 0; i < svg.Images.length; i++) { + if (!svg.Images[i].loaded) return false; + } + return true; + }; + // trim + svg.trim = function(s) { + return s.replace(/^\s+|\s+$/g, ""); + }; + // compress spaces + svg.compressSpaces = function(s) { + return s.replace(/[\s\r\t\n]+/gm, " "); + }; + // ajax + svg.ajax = function(url) { + var AJAX; + if (window.XMLHttpRequest) { + AJAX = new XMLHttpRequest(); + } else { + AJAX = new ActiveXObject("Microsoft.XMLHTTP"); + } + if (AJAX) { + AJAX.open("GET", url, false); + AJAX.send(null); + return AJAX.responseText; + } + return null; + }; + // parse xml + svg.parseXml = function(xml) { + if (window.DOMParser) { + var parser = new DOMParser(); + return parser.parseFromString(xml, "text/xml"); + } else { + xml = xml.replace(/]*>/, ""); + var xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async = "false"; + xmlDoc.loadXML(xml); + return xmlDoc; + } + }; + svg.Property = function(name, value) { + this.name = name; + this.value = value; + }; + svg.Property.prototype.getValue = function() { + return this.value; + }; + svg.Property.prototype.hasValue = function() { + return this.value != null && this.value !== ""; + }; + // return the numerical value of the property + svg.Property.prototype.numValue = function() { + if (!this.hasValue()) return 0; + var n = parseFloat(this.value); + if ((this.value + "").match(/%$/)) { + n = n / 100; + } + return n; + }; + svg.Property.prototype.valueOrDefault = function(def) { + if (this.hasValue()) return this.value; + return def; + }; + svg.Property.prototype.numValueOrDefault = function(def) { + if (this.hasValue()) return this.numValue(); + return def; + }; + // color extensions + // augment the current color value with the opacity + svg.Property.prototype.addOpacity = function(opacity) { + var newValue = this.value; + if (opacity != null && opacity != "" && typeof this.value == "string") { + // can only add opacity to colors, not patterns + var color = new RGBColor(this.value); + if (color.ok) { + newValue = "rgba(" + color.r + ", " + color.g + ", " + color.b + ", " + opacity + ")"; + } + } + return new svg.Property(this.name, newValue); + }; + // definition extensions + // get the definition from the definitions table + svg.Property.prototype.getDefinition = function() { + var name = this.value.match(/#([^\)'"]+)/); + if (name) { + name = name[1]; + } + if (!name) { + name = this.value; + } + return svg.Definitions[name]; + }; + svg.Property.prototype.isUrlDefinition = function() { + return this.value.indexOf("url(") == 0; + }; + svg.Property.prototype.getFillStyleDefinition = function(e, opacityProp) { + var def = this.getDefinition(); + // gradient + if (def != null && def.createGradient) { + return def.createGradient(svg.ctx, e, opacityProp); + } + // pattern + if (def != null && def.createPattern) { + if (def.getHrefAttribute().hasValue()) { + var pt = def.attribute("patternTransform"); + def = def.getHrefAttribute().getDefinition(); + if (pt.hasValue()) { + def.attribute("patternTransform", true).value = pt.value; + } + } + return def.createPattern(svg.ctx, e); + } + return null; + }; + // length extensions + svg.Property.prototype.getDPI = function(viewPort) { + return 96; + }; + svg.Property.prototype.getEM = function(viewPort) { + var em = 12; + var fontSize = new svg.Property("fontSize", svg.Font.Parse(svg.ctx.font).fontSize); + if (fontSize.hasValue()) em = fontSize.toPixels(viewPort); + return em; + }; + svg.Property.prototype.getUnits = function() { + var s = this.value + ""; + return s.replace(/[0-9\.\-]/g, ""); + }; + // get the length as pixels + svg.Property.prototype.toPixels = function(viewPort, processPercent) { + if (!this.hasValue()) return 0; + var s = this.value + ""; + if (s.match(/em$/)) return this.numValue() * this.getEM(viewPort); + if (s.match(/ex$/)) return this.numValue() * this.getEM(viewPort) / 2; + if (s.match(/px$/)) return this.numValue(); + if (s.match(/pt$/)) return this.numValue() * this.getDPI(viewPort) * (1 / 72); + if (s.match(/pc$/)) return this.numValue() * 15; + if (s.match(/cm$/)) return this.numValue() * this.getDPI(viewPort) / 2.54; + if (s.match(/mm$/)) return this.numValue() * this.getDPI(viewPort) / 25.4; + if (s.match(/in$/)) return this.numValue() * this.getDPI(viewPort); + if (s.match(/%$/)) return this.numValue() * svg.ViewPort.ComputeSize(viewPort); + var n = this.numValue(); + if (processPercent && n < 1) return n * svg.ViewPort.ComputeSize(viewPort); + return n; + }; + // time extensions + // get the time as milliseconds + svg.Property.prototype.toMilliseconds = function() { + if (!this.hasValue()) return 0; + var s = this.value + ""; + if (s.match(/s$/)) return this.numValue() * 1e3; + if (s.match(/ms$/)) return this.numValue(); + return this.numValue(); + }; + // angle extensions + // get the angle as radians + svg.Property.prototype.toRadians = function() { + if (!this.hasValue()) return 0; + var s = this.value + ""; + if (s.match(/deg$/)) return this.numValue() * (Math.PI / 180); + if (s.match(/grad$/)) return this.numValue() * (Math.PI / 200); + if (s.match(/rad$/)) return this.numValue(); + return this.numValue() * (Math.PI / 180); + }; + // fonts + svg.Font = new function() { + this.Styles = "normal|italic|oblique|inherit"; + this.Variants = "normal|small-caps|inherit"; + this.Weights = "normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit"; + this.CreateFont = function(fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) { + var f = inherit != null ? this.Parse(inherit) : this.CreateFont("", "", "", "", "", svg.ctx.font); + return { + fontFamily: fontFamily || f.fontFamily, + fontSize: fontSize || f.fontSize, + fontStyle: fontStyle || f.fontStyle, + fontWeight: fontWeight || f.fontWeight, + fontVariant: fontVariant || f.fontVariant, + toString: function() { + return [ this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily ].join(" "); + } + }; + }; + var that = this; + this.Parse = function(s) { + var f = {}; + var d = svg.trim(svg.compressSpaces(s || "")).split(" "); + var set = { + fontSize: false, + fontStyle: false, + fontWeight: false, + fontVariant: false + }; + var ff = ""; + for (var i = 0; i < d.length; i++) { + if (!set.fontStyle && that.Styles.indexOf(d[i]) != -1) { + if (d[i] != "inherit") f.fontStyle = d[i]; + set.fontStyle = true; + } else if (!set.fontVariant && that.Variants.indexOf(d[i]) != -1) { + if (d[i] != "inherit") f.fontVariant = d[i]; + set.fontStyle = set.fontVariant = true; + } else if (!set.fontWeight && that.Weights.indexOf(d[i]) != -1) { + if (d[i] != "inherit") f.fontWeight = d[i]; + set.fontStyle = set.fontVariant = set.fontWeight = true; + } else if (!set.fontSize) { + if (d[i] != "inherit") f.fontSize = d[i].split("/")[0]; + set.fontStyle = set.fontVariant = set.fontWeight = set.fontSize = true; + } else { + if (d[i] != "inherit") ff += d[i]; + } + } + if (ff != "") f.fontFamily = ff; + return f; + }; + }(); + // points and paths + svg.ToNumberArray = function(s) { + var a = svg.trim(svg.compressSpaces((s || "").replace(/,/g, " "))).split(" "); + for (var i = 0; i < a.length; i++) { + a[i] = parseFloat(a[i]); + } + return a; + }; + svg.Point = function(x, y) { + this.x = x; + this.y = y; + }; + svg.Point.prototype.angleTo = function(p) { + return Math.atan2(p.y - this.y, p.x - this.x); + }; + svg.Point.prototype.applyTransform = function(v) { + var xp = this.x * v[0] + this.y * v[2] + v[4]; + var yp = this.x * v[1] + this.y * v[3] + v[5]; + this.x = xp; + this.y = yp; + }; + svg.CreatePoint = function(s) { + var a = svg.ToNumberArray(s); + return new svg.Point(a[0], a[1]); + }; + svg.CreatePath = function(s) { + var a = svg.ToNumberArray(s); + var path = []; + for (var i = 0; i < a.length; i += 2) { + path.push(new svg.Point(a[i], a[i + 1])); + } + return path; + }; + // bounding box + svg.BoundingBox = function(x1, y1, x2, y2) { + // pass in initial points if you want + this.x1 = Number.NaN; + this.y1 = Number.NaN; + this.x2 = Number.NaN; + this.y2 = Number.NaN; + this.x = function() { + return this.x1; + }; + this.y = function() { + return this.y1; + }; + this.width = function() { + return this.x2 - this.x1; + }; + this.height = function() { + return this.y2 - this.y1; + }; + this.addPoint = function(x, y) { + if (x != null) { + if (isNaN(this.x1) || isNaN(this.x2)) { + this.x1 = x; + this.x2 = x; + } + if (x < this.x1) this.x1 = x; + if (x > this.x2) this.x2 = x; + } + if (y != null) { + if (isNaN(this.y1) || isNaN(this.y2)) { + this.y1 = y; + this.y2 = y; + } + if (y < this.y1) this.y1 = y; + if (y > this.y2) this.y2 = y; + } + }; + this.addX = function(x) { + this.addPoint(x, null); + }; + this.addY = function(y) { + this.addPoint(null, y); + }; + this.addBoundingBox = function(bb) { + this.addPoint(bb.x1, bb.y1); + this.addPoint(bb.x2, bb.y2); + }; + this.addQuadraticCurve = function(p0x, p0y, p1x, p1y, p2x, p2y) { + var cp1x = p0x + 2 / 3 * (p1x - p0x); + // CP1 = QP0 + 2/3 *(QP1-QP0) + var cp1y = p0y + 2 / 3 * (p1y - p0y); + // CP1 = QP0 + 2/3 *(QP1-QP0) + var cp2x = cp1x + 1 / 3 * (p2x - p0x); + // CP2 = CP1 + 1/3 *(QP2-QP0) + var cp2y = cp1y + 1 / 3 * (p2y - p0y); + // CP2 = CP1 + 1/3 *(QP2-QP0) + this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y, cp2y, p2x, p2y); + }; + this.addBezierCurve = function(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) { + // from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html + var p0 = [ p0x, p0y ], p1 = [ p1x, p1y ], p2 = [ p2x, p2y ], p3 = [ p3x, p3y ]; + this.addPoint(p0[0], p0[1]); + this.addPoint(p3[0], p3[1]); + for (i = 0; i <= 1; i++) { + var f = function(t) { + return Math.pow(1 - t, 3) * p0[i] + 3 * Math.pow(1 - t, 2) * t * p1[i] + 3 * (1 - t) * Math.pow(t, 2) * p2[i] + Math.pow(t, 3) * p3[i]; + }; + var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i]; + var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i]; + var c = 3 * p1[i] - 3 * p0[i]; + if (a == 0) { + if (b == 0) continue; + var t = -c / b; + if (0 < t && t < 1) { + if (i == 0) this.addX(f(t)); + if (i == 1) this.addY(f(t)); + } + continue; + } + var b2ac = Math.pow(b, 2) - 4 * c * a; + if (b2ac < 0) continue; + var t1 = (-b + Math.sqrt(b2ac)) / (2 * a); + if (0 < t1 && t1 < 1) { + if (i == 0) this.addX(f(t1)); + if (i == 1) this.addY(f(t1)); + } + var t2 = (-b - Math.sqrt(b2ac)) / (2 * a); + if (0 < t2 && t2 < 1) { + if (i == 0) this.addX(f(t2)); + if (i == 1) this.addY(f(t2)); + } + } + }; + this.isPointInBox = function(x, y) { + return this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2; + }; + this.addPoint(x1, y1); + this.addPoint(x2, y2); + }; + // transforms + svg.Transform = function(v) { + var that = this; + this.Type = {}; + // translate + this.Type.translate = function(s) { + this.p = svg.CreatePoint(s); + this.apply = function(ctx) { + ctx.translate(this.p.x || 0, this.p.y || 0); + }; + this.unapply = function(ctx) { + ctx.translate(-1 * this.p.x || 0, -1 * this.p.y || 0); + }; + this.applyToPoint = function(p) { + p.applyTransform([ 1, 0, 0, 1, this.p.x || 0, this.p.y || 0 ]); + }; + }; + // rotate + this.Type.rotate = function(s) { + var a = svg.ToNumberArray(s); + this.angle = new svg.Property("angle", a[0]); + this.cx = a[1] || 0; + this.cy = a[2] || 0; + this.apply = function(ctx) { + ctx.translate(this.cx, this.cy); + ctx.rotate(this.angle.toRadians()); + ctx.translate(-this.cx, -this.cy); + }; + this.unapply = function(ctx) { + ctx.translate(this.cx, this.cy); + ctx.rotate(-1 * this.angle.toRadians()); + ctx.translate(-this.cx, -this.cy); + }; + this.applyToPoint = function(p) { + var a = this.angle.toRadians(); + p.applyTransform([ 1, 0, 0, 1, this.p.x || 0, this.p.y || 0 ]); + p.applyTransform([ Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0 ]); + p.applyTransform([ 1, 0, 0, 1, -this.p.x || 0, -this.p.y || 0 ]); + }; + }; + this.Type.scale = function(s) { + this.p = svg.CreatePoint(s); + this.apply = function(ctx) { + ctx.scale(this.p.x || 1, this.p.y || this.p.x || 1); + }; + this.unapply = function(ctx) { + ctx.scale(1 / this.p.x || 1, 1 / this.p.y || this.p.x || 1); + }; + this.applyToPoint = function(p) { + p.applyTransform([ this.p.x || 0, 0, 0, this.p.y || 0, 0, 0 ]); + }; + }; + this.Type.matrix = function(s) { + this.m = svg.ToNumberArray(s); + this.apply = function(ctx) { + ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]); + }; + this.applyToPoint = function(p) { + p.applyTransform(this.m); + }; + }; + this.Type.SkewBase = function(s) { + this.base = that.Type.matrix; + this.base(s); + this.angle = new svg.Property("angle", s); + }; + this.Type.SkewBase.prototype = new this.Type.matrix(); + this.Type.skewX = function(s) { + this.base = that.Type.SkewBase; + this.base(s); + this.m = [ 1, 0, Math.tan(this.angle.toRadians()), 1, 0, 0 ]; + }; + this.Type.skewX.prototype = new this.Type.SkewBase(); + this.Type.skewY = function(s) { + this.base = that.Type.SkewBase; + this.base(s); + this.m = [ 1, Math.tan(this.angle.toRadians()), 0, 1, 0, 0 ]; + }; + this.Type.skewY.prototype = new this.Type.SkewBase(); + this.transforms = []; + this.apply = function(ctx) { + for (var i = 0; i < this.transforms.length; i++) { + this.transforms[i].apply(ctx); + } + }; + this.unapply = function(ctx) { + for (var i = this.transforms.length - 1; i >= 0; i--) { + this.transforms[i].unapply(ctx); + } + }; + this.applyToPoint = function(p) { + for (var i = 0; i < this.transforms.length; i++) { + this.transforms[i].applyToPoint(p); + } + }; + var data = svg.trim(svg.compressSpaces(v)).replace(/\)(\s?,\s?)/g, ") ").split(/\s(?=[a-z])/); + for (var i = 0; i < data.length; i++) { + var type = svg.trim(data[i].split("(")[0]); + var s = data[i].split("(")[1].replace(")", ""); + var transform = new this.Type[type](s); + transform.type = type; + this.transforms.push(transform); + } + }; + // aspect ratio + svg.AspectRatio = function(ctx, aspectRatio, width, desiredWidth, height, desiredHeight, minX, minY, refX, refY) { + // aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute + aspectRatio = svg.compressSpaces(aspectRatio); + aspectRatio = aspectRatio.replace(/^defer\s/, ""); + // ignore defer + var align = aspectRatio.split(" ")[0] || "xMidYMid"; + var meetOrSlice = aspectRatio.split(" ")[1] || "meet"; + // calculate scale + var scaleX = width / desiredWidth; + var scaleY = height / desiredHeight; + var scaleMin = Math.min(scaleX, scaleY); + var scaleMax = Math.max(scaleX, scaleY); + if (meetOrSlice == "meet") { + desiredWidth *= scaleMin; + desiredHeight *= scaleMin; + } + if (meetOrSlice == "slice") { + desiredWidth *= scaleMax; + desiredHeight *= scaleMax; + } + refX = new svg.Property("refX", refX); + refY = new svg.Property("refY", refY); + if (refX.hasValue() && refY.hasValue()) { + ctx.translate(-scaleMin * refX.toPixels("x"), -scaleMin * refY.toPixels("y")); + } else { + // align + if (align.match(/^xMid/) && (meetOrSlice == "meet" && scaleMin == scaleY || meetOrSlice == "slice" && scaleMax == scaleY)) ctx.translate(width / 2 - desiredWidth / 2, 0); + if (align.match(/YMid$/) && (meetOrSlice == "meet" && scaleMin == scaleX || meetOrSlice == "slice" && scaleMax == scaleX)) ctx.translate(0, height / 2 - desiredHeight / 2); + if (align.match(/^xMax/) && (meetOrSlice == "meet" && scaleMin == scaleY || meetOrSlice == "slice" && scaleMax == scaleY)) ctx.translate(width - desiredWidth, 0); + if (align.match(/YMax$/) && (meetOrSlice == "meet" && scaleMin == scaleX || meetOrSlice == "slice" && scaleMax == scaleX)) ctx.translate(0, height - desiredHeight); + } + // scale + if (align == "none") ctx.scale(scaleX, scaleY); else if (meetOrSlice == "meet") ctx.scale(scaleMin, scaleMin); else if (meetOrSlice == "slice") ctx.scale(scaleMax, scaleMax); + // translate + ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY); + }; + // elements + svg.Element = {}; + svg.EmptyProperty = new svg.Property("EMPTY", ""); + svg.Element.ElementBase = function(node) { + this.attributes = {}; + this.styles = {}; + this.children = []; + // get or create attribute + this.attribute = function(name, createIfNotExists) { + var a = this.attributes[name]; + if (a != null) return a; + if (createIfNotExists == true) { + a = new svg.Property(name, ""); + this.attributes[name] = a; + } + return a || svg.EmptyProperty; + }; + this.getHrefAttribute = function() { + for (var a in this.attributes) { + if (a.match(/:href$/)) { + return this.attributes[a]; + } + } + return svg.EmptyProperty; + }; + // get or create style, crawls up node tree + this.style = function(name, createIfNotExists) { + var s = this.styles[name]; + if (s != null) return s; + var a = this.attribute(name); + if (a != null && a.hasValue()) { + this.styles[name] = a; + // move up to me to cache + return a; + } + var p = this.parent; + if (p != null) { + var ps = p.style(name); + if (ps != null && ps.hasValue()) { + return ps; + } + } + if (createIfNotExists == true) { + s = new svg.Property(name, ""); + this.styles[name] = s; + } + return s || svg.EmptyProperty; + }; + // base render + this.render = function(ctx) { + // don't render display=none + if (this.style("display").value == "none") return; + // don't render visibility=hidden + if (this.attribute("visibility").value == "hidden") return; + ctx.save(); + if (this.attribute("mask").hasValue()) { + // mask + var mask = this.attribute("mask").getDefinition(); + if (mask != null) mask.apply(ctx, this); + } else if (this.style("filter").hasValue()) { + // filter + var filter = this.style("filter").getDefinition(); + if (filter != null) filter.apply(ctx, this); + } else { + this.setContext(ctx); + this.renderChildren(ctx); + this.clearContext(ctx); + } + ctx.restore(); + }; + // base set context + this.setContext = function(ctx) {}; + // base clear context + this.clearContext = function(ctx) {}; + // base render children + this.renderChildren = function(ctx) { + for (var i = 0; i < this.children.length; i++) { + this.children[i].render(ctx); + } + }; + this.addChild = function(childNode, create) { + var child = childNode; + if (create) child = svg.CreateElement(childNode); + child.parent = this; + this.children.push(child); + }; + if (node != null && node.nodeType == 1) { + //ELEMENT_NODE + // add children + for (var i = 0; i < node.childNodes.length; i++) { + var childNode = node.childNodes[i]; + if (childNode.nodeType == 1) this.addChild(childNode, true); + //ELEMENT_NODE + if (this.captureTextNodes && childNode.nodeType == 3) { + var text = childNode.nodeValue || childNode.text || ""; + if (svg.trim(svg.compressSpaces(text)) != "") { + this.addChild(new svg.Element.tspan(childNode), false); + } + } + } + // add attributes + for (var i = 0; i < node.attributes.length; i++) { + var attribute = node.attributes[i]; + this.attributes[attribute.nodeName] = new svg.Property(attribute.nodeName, attribute.nodeValue); + } + // add tag styles + var styles = svg.Styles[node.nodeName]; + if (styles != null) { + for (var name in styles) { + this.styles[name] = styles[name]; + } + } + // add class styles + if (this.attribute("class").hasValue()) { + var classes = svg.compressSpaces(this.attribute("class").value).split(" "); + for (var j = 0; j < classes.length; j++) { + styles = svg.Styles["." + classes[j]]; + if (styles != null) { + for (var name in styles) { + this.styles[name] = styles[name]; + } + } + styles = svg.Styles[node.nodeName + "." + classes[j]]; + if (styles != null) { + for (var name in styles) { + this.styles[name] = styles[name]; + } + } + } + } + // add id styles + if (this.attribute("id").hasValue()) { + var styles = svg.Styles["#" + this.attribute("id").value]; + if (styles != null) { + for (var name in styles) { + this.styles[name] = styles[name]; + } + } + } + // add inline styles + if (this.attribute("style").hasValue()) { + var styles = this.attribute("style").value.split(";"); + for (var i = 0; i < styles.length; i++) { + if (svg.trim(styles[i]) != "") { + var style = styles[i].split(":"); + var name = svg.trim(style[0]); + var value = svg.trim(style[1]); + this.styles[name] = new svg.Property(name, value); + } + } + } + // add id + if (this.attribute("id").hasValue()) { + if (svg.Definitions[this.attribute("id").value] == null) { + svg.Definitions[this.attribute("id").value] = this; + } + } + } + }; + svg.Element.RenderedElementBase = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.setContext = function(ctx) { + // fill + if (this.style("fill").isUrlDefinition()) { + var fs = this.style("fill").getFillStyleDefinition(this, this.style("fill-opacity")); + if (fs != null) ctx.fillStyle = fs; + } else if (this.style("fill").hasValue()) { + var fillStyle = this.style("fill"); + if (fillStyle.value == "currentColor") fillStyle.value = this.style("color").value; + ctx.fillStyle = fillStyle.value == "none" ? "rgba(0,0,0,0)" : fillStyle.value; + } + if (this.style("fill-opacity").hasValue()) { + var fillStyle = new svg.Property("fill", ctx.fillStyle); + fillStyle = fillStyle.addOpacity(this.style("fill-opacity").value); + ctx.fillStyle = fillStyle.value; + } + // stroke + if (this.style("stroke").isUrlDefinition()) { + var fs = this.style("stroke").getFillStyleDefinition(this, this.style("stroke-opacity")); + if (fs != null) ctx.strokeStyle = fs; + } else if (this.style("stroke").hasValue()) { + var strokeStyle = this.style("stroke"); + if (strokeStyle.value == "currentColor") strokeStyle.value = this.style("color").value; + ctx.strokeStyle = strokeStyle.value == "none" ? "rgba(0,0,0,0)" : strokeStyle.value; + } + if (this.style("stroke-opacity").hasValue()) { + var strokeStyle = new svg.Property("stroke", ctx.strokeStyle); + strokeStyle = strokeStyle.addOpacity(this.style("stroke-opacity").value); + ctx.strokeStyle = strokeStyle.value; + } + if (this.style("stroke-width").hasValue()) { + var newLineWidth = this.style("stroke-width").toPixels(); + ctx.lineWidth = newLineWidth == 0 ? .001 : newLineWidth; + } + if (this.style("stroke-linecap").hasValue()) ctx.lineCap = this.style("stroke-linecap").value; + if (this.style("stroke-linejoin").hasValue()) ctx.lineJoin = this.style("stroke-linejoin").value; + if (this.style("stroke-miterlimit").hasValue()) ctx.miterLimit = this.style("stroke-miterlimit").value; + if (this.style("stroke-dasharray").hasValue()) { + var gaps = svg.ToNumberArray(this.style("stroke-dasharray").value); + if (typeof ctx.setLineDash != "undefined") { + ctx.setLineDash(gaps); + } else if (typeof ctx.webkitLineDash != "undefined") { + ctx.webkitLineDash = gaps; + } else if (typeof ctx.mozDash != "undefined") { + ctx.mozDash = gaps; + } + var offset = this.style("stroke-dashoffset").numValueOrDefault(1); + if (typeof ctx.lineDashOffset != "undefined") { + ctx.lineDashOffset = offset; + } else if (typeof ctx.webkitLineDashOffset != "undefined") { + ctx.webkitLineDashOffset = offset; + } else if (typeof ctx.mozDashOffset != "undefined") { + ctx.mozDashOffset = offset; + } + } + // font + if (typeof ctx.font != "undefined") { + ctx.font = svg.Font.CreateFont(this.style("font-style").value, this.style("font-variant").value, this.style("font-weight").value, this.style("font-size").hasValue() ? this.style("font-size").toPixels() + "px" : "", this.style("font-family").value).toString(); + } + // transform + if (this.attribute("transform").hasValue()) { + var transform = new svg.Transform(this.attribute("transform").value); + transform.apply(ctx); + } + // clip + if (this.style("clip-path").hasValue()) { + var clip = this.style("clip-path").getDefinition(); + if (clip != null) clip.apply(ctx); + } + // opacity + if (this.style("opacity").hasValue()) { + ctx.globalAlpha = this.style("opacity").numValue(); + } + }; + }; + svg.Element.RenderedElementBase.prototype = new svg.Element.ElementBase(); + svg.Element.PathElementBase = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + this.path = function(ctx) { + if (ctx != null) ctx.beginPath(); + return new svg.BoundingBox(); + }; + this.renderChildren = function(ctx) { + this.path(ctx); + svg.Mouse.checkPath(this, ctx); + if (ctx.fillStyle != "") { + if (this.attribute("fill-rule").hasValue()) { + ctx.fill(this.attribute("fill-rule").value); + } else { + ctx.fill(); + } + } + if (ctx.strokeStyle != "") ctx.stroke(); + var markers = this.getMarkers(); + if (markers != null) { + if (this.style("marker-start").isUrlDefinition()) { + var marker = this.style("marker-start").getDefinition(); + marker.render(ctx, markers[0][0], markers[0][1]); + } + if (this.style("marker-mid").isUrlDefinition()) { + var marker = this.style("marker-mid").getDefinition(); + for (var i = 1; i < markers.length - 1; i++) { + marker.render(ctx, markers[i][0], markers[i][1]); + } + } + if (this.style("marker-end").isUrlDefinition()) { + var marker = this.style("marker-end").getDefinition(); + marker.render(ctx, markers[markers.length - 1][0], markers[markers.length - 1][1]); + } + } + }; + this.getBoundingBox = function() { + return this.path(); + }; + this.getMarkers = function() { + return null; + }; + }; + svg.Element.PathElementBase.prototype = new svg.Element.RenderedElementBase(); + // svg element + svg.Element.svg = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + this.baseClearContext = this.clearContext; + this.clearContext = function(ctx) { + this.baseClearContext(ctx); + svg.ViewPort.RemoveCurrent(); + }; + this.baseSetContext = this.setContext; + this.setContext = function(ctx) { + // initial values + ctx.strokeStyle = "rgba(0,0,0,0)"; + ctx.lineCap = "butt"; + ctx.lineJoin = "miter"; + ctx.miterLimit = 4; + this.baseSetContext(ctx); + // create new view port + if (!this.attribute("x").hasValue()) this.attribute("x", true).value = 0; + if (!this.attribute("y").hasValue()) this.attribute("y", true).value = 0; + ctx.translate(this.attribute("x").toPixels("x"), this.attribute("y").toPixels("y")); + var width = svg.ViewPort.width(); + var height = svg.ViewPort.height(); + if (!this.attribute("width").hasValue()) this.attribute("width", true).value = "100%"; + if (!this.attribute("height").hasValue()) this.attribute("height", true).value = "100%"; + if (typeof this.root == "undefined") { + width = this.attribute("width").toPixels("x"); + height = this.attribute("height").toPixels("y"); + var x = 0; + var y = 0; + if (this.attribute("refX").hasValue() && this.attribute("refY").hasValue()) { + x = -this.attribute("refX").toPixels("x"); + y = -this.attribute("refY").toPixels("y"); + } + ctx.beginPath(); + ctx.moveTo(x, y); + ctx.lineTo(width, y); + ctx.lineTo(width, height); + ctx.lineTo(x, height); + ctx.closePath(); + ctx.clip(); + } + svg.ViewPort.SetCurrent(width, height); + // viewbox + if (this.attribute("viewBox").hasValue()) { + var viewBox = svg.ToNumberArray(this.attribute("viewBox").value); + var minX = viewBox[0]; + var minY = viewBox[1]; + width = viewBox[2]; + height = viewBox[3]; + svg.AspectRatio(ctx, this.attribute("preserveAspectRatio").value, svg.ViewPort.width(), width, svg.ViewPort.height(), height, minX, minY, this.attribute("refX").value, this.attribute("refY").value); + svg.ViewPort.RemoveCurrent(); + svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]); + } + }; + }; + svg.Element.svg.prototype = new svg.Element.RenderedElementBase(); + // rect element + svg.Element.rect = function(node) { + this.base = svg.Element.PathElementBase; + this.base(node); + this.path = function(ctx) { + var x = this.attribute("x").toPixels("x"); + var y = this.attribute("y").toPixels("y"); + var width = this.attribute("width").toPixels("x"); + var height = this.attribute("height").toPixels("y"); + var rx = this.attribute("rx").toPixels("x"); + var ry = this.attribute("ry").toPixels("y"); + if (this.attribute("rx").hasValue() && !this.attribute("ry").hasValue()) ry = rx; + if (this.attribute("ry").hasValue() && !this.attribute("rx").hasValue()) rx = ry; + rx = Math.min(rx, width / 2); + ry = Math.min(ry, height / 2); + if (ctx != null) { + ctx.beginPath(); + ctx.moveTo(x + rx, y); + ctx.lineTo(x + width - rx, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + ry); + ctx.lineTo(x + width, y + height - ry); + ctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height); + ctx.lineTo(x + rx, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - ry); + ctx.lineTo(x, y + ry); + ctx.quadraticCurveTo(x, y, x + rx, y); + ctx.closePath(); + } + return new svg.BoundingBox(x, y, x + width, y + height); + }; + }; + svg.Element.rect.prototype = new svg.Element.PathElementBase(); + // circle element + svg.Element.circle = function(node) { + this.base = svg.Element.PathElementBase; + this.base(node); + this.path = function(ctx) { + var cx = this.attribute("cx").toPixels("x"); + var cy = this.attribute("cy").toPixels("y"); + var r = this.attribute("r").toPixels(); + if (ctx != null) { + ctx.beginPath(); + ctx.arc(cx, cy, r, 0, Math.PI * 2, true); + ctx.closePath(); + } + return new svg.BoundingBox(cx - r, cy - r, cx + r, cy + r); + }; + }; + svg.Element.circle.prototype = new svg.Element.PathElementBase(); + // ellipse element + svg.Element.ellipse = function(node) { + this.base = svg.Element.PathElementBase; + this.base(node); + this.path = function(ctx) { + var KAPPA = 4 * ((Math.sqrt(2) - 1) / 3); + var rx = this.attribute("rx").toPixels("x"); + var ry = this.attribute("ry").toPixels("y"); + var cx = this.attribute("cx").toPixels("x"); + var cy = this.attribute("cy").toPixels("y"); + if (ctx != null) { + ctx.beginPath(); + ctx.moveTo(cx, cy - ry); + ctx.bezierCurveTo(cx + KAPPA * rx, cy - ry, cx + rx, cy - KAPPA * ry, cx + rx, cy); + ctx.bezierCurveTo(cx + rx, cy + KAPPA * ry, cx + KAPPA * rx, cy + ry, cx, cy + ry); + ctx.bezierCurveTo(cx - KAPPA * rx, cy + ry, cx - rx, cy + KAPPA * ry, cx - rx, cy); + ctx.bezierCurveTo(cx - rx, cy - KAPPA * ry, cx - KAPPA * rx, cy - ry, cx, cy - ry); + ctx.closePath(); + } + return new svg.BoundingBox(cx - rx, cy - ry, cx + rx, cy + ry); + }; + }; + svg.Element.ellipse.prototype = new svg.Element.PathElementBase(); + // line element + svg.Element.line = function(node) { + this.base = svg.Element.PathElementBase; + this.base(node); + this.getPoints = function() { + return [ new svg.Point(this.attribute("x1").toPixels("x"), this.attribute("y1").toPixels("y")), new svg.Point(this.attribute("x2").toPixels("x"), this.attribute("y2").toPixels("y")) ]; + }; + this.path = function(ctx) { + var points = this.getPoints(); + if (ctx != null) { + ctx.beginPath(); + ctx.moveTo(points[0].x, points[0].y); + ctx.lineTo(points[1].x, points[1].y); + } + return new svg.BoundingBox(points[0].x, points[0].y, points[1].x, points[1].y); + }; + this.getMarkers = function() { + var points = this.getPoints(); + var a = points[0].angleTo(points[1]); + return [ [ points[0], a ], [ points[1], a ] ]; + }; + }; + svg.Element.line.prototype = new svg.Element.PathElementBase(); + // polyline element + svg.Element.polyline = function(node) { + this.base = svg.Element.PathElementBase; + this.base(node); + this.points = svg.CreatePath(this.attribute("points").value); + this.path = function(ctx) { + var bb = new svg.BoundingBox(this.points[0].x, this.points[0].y); + if (ctx != null) { + ctx.beginPath(); + ctx.moveTo(this.points[0].x, this.points[0].y); + } + for (var i = 1; i < this.points.length; i++) { + bb.addPoint(this.points[i].x, this.points[i].y); + if (ctx != null) ctx.lineTo(this.points[i].x, this.points[i].y); + } + return bb; + }; + this.getMarkers = function() { + var markers = []; + for (var i = 0; i < this.points.length - 1; i++) { + markers.push([ this.points[i], this.points[i].angleTo(this.points[i + 1]) ]); + } + markers.push([ this.points[this.points.length - 1], markers[markers.length - 1][1] ]); + return markers; + }; + }; + svg.Element.polyline.prototype = new svg.Element.PathElementBase(); + // polygon element + svg.Element.polygon = function(node) { + this.base = svg.Element.polyline; + this.base(node); + this.basePath = this.path; + this.path = function(ctx) { + var bb = this.basePath(ctx); + if (ctx != null) { + ctx.lineTo(this.points[0].x, this.points[0].y); + ctx.closePath(); + } + return bb; + }; + }; + svg.Element.polygon.prototype = new svg.Element.polyline(); + // path element + svg.Element.path = function(node) { + this.base = svg.Element.PathElementBase; + this.base(node); + var d = this.attribute("d").value; + // TODO: convert to real lexer based on http://www.w3.org/TR/SVG11/paths.html#PathDataBNF + d = d.replace(/,/gm, " "); + // get rid of all commas + d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2"); + // separate commands from commands + d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2"); + // separate commands from commands + d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm, "$1 $2"); + // separate commands from points + d = d.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2"); + // separate commands from points + d = d.replace(/([0-9])([+\-])/gm, "$1 $2"); + // separate digits when no comma + d = d.replace(/(\.[0-9]*)(\.)/gm, "$1 $2"); + // separate digits when no comma + d = d.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm, "$1 $3 $4 "); + // shorthand elliptical arc path syntax + d = svg.compressSpaces(d); + // compress multiple spaces + d = svg.trim(d); + this.PathParser = new function(d) { + this.tokens = d.split(" "); + this.reset = function() { + this.i = -1; + this.command = ""; + this.previousCommand = ""; + this.start = new svg.Point(0, 0); + this.control = new svg.Point(0, 0); + this.current = new svg.Point(0, 0); + this.points = []; + this.angles = []; + }; + this.isEnd = function() { + return this.i >= this.tokens.length - 1; + }; + this.isCommandOrEnd = function() { + if (this.isEnd()) return true; + return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null; + }; + this.isRelativeCommand = function() { + switch (this.command) { + case "m": + case "l": + case "h": + case "v": + case "c": + case "s": + case "q": + case "t": + case "a": + case "z": + return true; + break; + } + return false; + }; + this.getToken = function() { + this.i++; + return this.tokens[this.i]; + }; + this.getScalar = function() { + return parseFloat(this.getToken()); + }; + this.nextCommand = function() { + this.previousCommand = this.command; + this.command = this.getToken(); + }; + this.getPoint = function() { + var p = new svg.Point(this.getScalar(), this.getScalar()); + return this.makeAbsolute(p); + }; + this.getAsControlPoint = function() { + var p = this.getPoint(); + this.control = p; + return p; + }; + this.getAsCurrentPoint = function() { + var p = this.getPoint(); + this.current = p; + return p; + }; + this.getReflectedControlPoint = function() { + if (this.previousCommand.toLowerCase() != "c" && this.previousCommand.toLowerCase() != "s" && this.previousCommand.toLowerCase() != "q" && this.previousCommand.toLowerCase() != "t") { + return this.current; + } + // reflect point + var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y); + return p; + }; + this.makeAbsolute = function(p) { + if (this.isRelativeCommand()) { + p.x += this.current.x; + p.y += this.current.y; + } + return p; + }; + this.addMarker = function(p, from, priorTo) { + // if the last angle isn't filled in because we didn't have this point yet ... + if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length - 1] == null) { + this.angles[this.angles.length - 1] = this.points[this.points.length - 1].angleTo(priorTo); + } + this.addMarkerAngle(p, from == null ? null : from.angleTo(p)); + }; + this.addMarkerAngle = function(p, a) { + this.points.push(p); + this.angles.push(a); + }; + this.getMarkerPoints = function() { + return this.points; + }; + this.getMarkerAngles = function() { + for (var i = 0; i < this.angles.length; i++) { + if (this.angles[i] == null) { + for (var j = i + 1; j < this.angles.length; j++) { + if (this.angles[j] != null) { + this.angles[i] = this.angles[j]; + break; + } + } + } + } + return this.angles; + }; + }(d); + this.path = function(ctx) { + var pp = this.PathParser; + pp.reset(); + var bb = new svg.BoundingBox(); + if (ctx != null) ctx.beginPath(); + while (!pp.isEnd()) { + pp.nextCommand(); + switch (pp.command) { + case "M": + case "m": + var p = pp.getAsCurrentPoint(); + pp.addMarker(p); + bb.addPoint(p.x, p.y); + if (ctx != null) ctx.moveTo(p.x, p.y); + pp.start = pp.current; + while (!pp.isCommandOrEnd()) { + var p = pp.getAsCurrentPoint(); + pp.addMarker(p, pp.start); + bb.addPoint(p.x, p.y); + if (ctx != null) ctx.lineTo(p.x, p.y); + } + break; + + case "L": + case "l": + while (!pp.isCommandOrEnd()) { + var c = pp.current; + var p = pp.getAsCurrentPoint(); + pp.addMarker(p, c); + bb.addPoint(p.x, p.y); + if (ctx != null) ctx.lineTo(p.x, p.y); + } + break; + + case "H": + case "h": + while (!pp.isCommandOrEnd()) { + var newP = new svg.Point((pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar(), pp.current.y); + pp.addMarker(newP, pp.current); + pp.current = newP; + bb.addPoint(pp.current.x, pp.current.y); + if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y); + } + break; + + case "V": + case "v": + while (!pp.isCommandOrEnd()) { + var newP = new svg.Point(pp.current.x, (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar()); + pp.addMarker(newP, pp.current); + pp.current = newP; + bb.addPoint(pp.current.x, pp.current.y); + if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y); + } + break; + + case "C": + case "c": + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var p1 = pp.getPoint(); + var cntrl = pp.getAsControlPoint(); + var cp = pp.getAsCurrentPoint(); + pp.addMarker(cp, cntrl, p1); + bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y); + if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y); + } + break; + + case "S": + case "s": + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var p1 = pp.getReflectedControlPoint(); + var cntrl = pp.getAsControlPoint(); + var cp = pp.getAsCurrentPoint(); + pp.addMarker(cp, cntrl, p1); + bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y); + if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y); + } + break; + + case "Q": + case "q": + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var cntrl = pp.getAsControlPoint(); + var cp = pp.getAsCurrentPoint(); + pp.addMarker(cp, cntrl, cntrl); + bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y); + if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y); + } + break; + + case "T": + case "t": + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var cntrl = pp.getReflectedControlPoint(); + pp.control = cntrl; + var cp = pp.getAsCurrentPoint(); + pp.addMarker(cp, cntrl, cntrl); + bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y); + if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y); + } + break; + + case "A": + case "a": + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var rx = pp.getScalar(); + var ry = pp.getScalar(); + var xAxisRotation = pp.getScalar() * (Math.PI / 180); + var largeArcFlag = pp.getScalar(); + var sweepFlag = pp.getScalar(); + var cp = pp.getAsCurrentPoint(); + // Conversion from endpoint to center parameterization + // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes + // x1', y1' + var currp = new svg.Point(Math.cos(xAxisRotation) * (curr.x - cp.x) / 2 + Math.sin(xAxisRotation) * (curr.y - cp.y) / 2, -Math.sin(xAxisRotation) * (curr.x - cp.x) / 2 + Math.cos(xAxisRotation) * (curr.y - cp.y) / 2); + // adjust radii + var l = Math.pow(currp.x, 2) / Math.pow(rx, 2) + Math.pow(currp.y, 2) / Math.pow(ry, 2); + if (l > 1) { + rx *= Math.sqrt(l); + ry *= Math.sqrt(l); + } + // cx', cy' + var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt((Math.pow(rx, 2) * Math.pow(ry, 2) - Math.pow(rx, 2) * Math.pow(currp.y, 2) - Math.pow(ry, 2) * Math.pow(currp.x, 2)) / (Math.pow(rx, 2) * Math.pow(currp.y, 2) + Math.pow(ry, 2) * Math.pow(currp.x, 2))); + if (isNaN(s)) s = 0; + var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx); + // cx, cy + var centp = new svg.Point((curr.x + cp.x) / 2 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y, (curr.y + cp.y) / 2 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y); + // vector magnitude + var m = function(v) { + return Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2)); + }; + // ratio between two vectors + var r = function(u, v) { + return (u[0] * v[0] + u[1] * v[1]) / (m(u) * m(v)); + }; + // angle between two vectors + var a = function(u, v) { + return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(r(u, v)); + }; + // initial angle + var a1 = a([ 1, 0 ], [ (currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry ]); + // angle delta + var u = [ (currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry ]; + var v = [ (-currp.x - cpp.x) / rx, (-currp.y - cpp.y) / ry ]; + var ad = a(u, v); + if (r(u, v) <= -1) ad = Math.PI; + if (r(u, v) >= 1) ad = 0; + // for markers + var dir = 1 - sweepFlag ? 1 : -1; + var ah = a1 + dir * (ad / 2); + var halfWay = new svg.Point(centp.x + rx * Math.cos(ah), centp.y + ry * Math.sin(ah)); + pp.addMarkerAngle(halfWay, ah - dir * Math.PI / 2); + pp.addMarkerAngle(cp, ah - dir * Math.PI); + bb.addPoint(cp.x, cp.y); + // TODO: this is too naive, make it better + if (ctx != null) { + var r = rx > ry ? rx : ry; + var sx = rx > ry ? 1 : rx / ry; + var sy = rx > ry ? ry / rx : 1; + ctx.translate(centp.x, centp.y); + ctx.rotate(xAxisRotation); + ctx.scale(sx, sy); + ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag); + ctx.scale(1 / sx, 1 / sy); + ctx.rotate(-xAxisRotation); + ctx.translate(-centp.x, -centp.y); + } + } + break; + + case "Z": + case "z": + if (ctx != null) ctx.closePath(); + pp.current = pp.start; + } + } + return bb; + }; + this.getMarkers = function() { + var points = this.PathParser.getMarkerPoints(); + var angles = this.PathParser.getMarkerAngles(); + var markers = []; + for (var i = 0; i < points.length; i++) { + markers.push([ points[i], angles[i] ]); + } + return markers; + }; + }; + svg.Element.path.prototype = new svg.Element.PathElementBase(); + // pattern element + svg.Element.pattern = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.createPattern = function(ctx, element) { + var width = this.attribute("width").toPixels("x", true); + var height = this.attribute("height").toPixels("y", true); + // render me using a temporary svg element + var tempSvg = new svg.Element.svg(); + tempSvg.attributes["viewBox"] = new svg.Property("viewBox", this.attribute("viewBox").value); + tempSvg.attributes["width"] = new svg.Property("width", width + "px"); + tempSvg.attributes["height"] = new svg.Property("height", height + "px"); + tempSvg.attributes["transform"] = new svg.Property("transform", this.attribute("patternTransform").value); + tempSvg.children = this.children; + var c = document.createElement("canvas"); + c.width = width; + c.height = height; + var cctx = c.getContext("2d"); + if (this.attribute("x").hasValue() && this.attribute("y").hasValue()) { + cctx.translate(this.attribute("x").toPixels("x", true), this.attribute("y").toPixels("y", true)); + } + // render 3x3 grid so when we transform there's no white space on edges + for (var x = -1; x <= 1; x++) { + for (var y = -1; y <= 1; y++) { + cctx.save(); + cctx.translate(x * c.width, y * c.height); + tempSvg.render(cctx); + cctx.restore(); + } + } + var pattern = ctx.createPattern(c, "repeat"); + return pattern; + }; + }; + svg.Element.pattern.prototype = new svg.Element.ElementBase(); + // marker element + svg.Element.marker = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.baseRender = this.render; + this.render = function(ctx, point, angle) { + ctx.translate(point.x, point.y); + if (this.attribute("orient").valueOrDefault("auto") == "auto") ctx.rotate(angle); + if (this.attribute("markerUnits").valueOrDefault("strokeWidth") == "strokeWidth") ctx.scale(ctx.lineWidth, ctx.lineWidth); + ctx.save(); + // render me using a temporary svg element + var tempSvg = new svg.Element.svg(); + tempSvg.attributes["viewBox"] = new svg.Property("viewBox", this.attribute("viewBox").value); + tempSvg.attributes["refX"] = new svg.Property("refX", this.attribute("refX").value); + tempSvg.attributes["refY"] = new svg.Property("refY", this.attribute("refY").value); + tempSvg.attributes["width"] = new svg.Property("width", this.attribute("markerWidth").value); + tempSvg.attributes["height"] = new svg.Property("height", this.attribute("markerHeight").value); + tempSvg.attributes["fill"] = new svg.Property("fill", this.attribute("fill").valueOrDefault("black")); + tempSvg.attributes["stroke"] = new svg.Property("stroke", this.attribute("stroke").valueOrDefault("none")); + tempSvg.children = this.children; + tempSvg.render(ctx); + ctx.restore(); + if (this.attribute("markerUnits").valueOrDefault("strokeWidth") == "strokeWidth") ctx.scale(1 / ctx.lineWidth, 1 / ctx.lineWidth); + if (this.attribute("orient").valueOrDefault("auto") == "auto") ctx.rotate(-angle); + ctx.translate(-point.x, -point.y); + }; + }; + svg.Element.marker.prototype = new svg.Element.ElementBase(); + // definitions element + svg.Element.defs = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.render = function(ctx) {}; + }; + svg.Element.defs.prototype = new svg.Element.ElementBase(); + // base for gradients + svg.Element.GradientBase = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.gradientUnits = this.attribute("gradientUnits").valueOrDefault("objectBoundingBox"); + this.stops = []; + for (var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if (child.type == "stop") this.stops.push(child); + } + this.getGradient = function() {}; + this.createGradient = function(ctx, element, parentOpacityProp) { + var stopsContainer = this; + if (this.getHrefAttribute().hasValue()) { + stopsContainer = this.getHrefAttribute().getDefinition(); + } + var addParentOpacity = function(color) { + if (parentOpacityProp.hasValue()) { + var p = new svg.Property("color", color); + return p.addOpacity(parentOpacityProp.value).value; + } + return color; + }; + var g = this.getGradient(ctx, element); + if (g == null) return addParentOpacity(stopsContainer.stops[stopsContainer.stops.length - 1].color); + for (var i = 0; i < stopsContainer.stops.length; i++) { + g.addColorStop(stopsContainer.stops[i].offset, addParentOpacity(stopsContainer.stops[i].color)); + } + if (this.attribute("gradientTransform").hasValue()) { + // render as transformed pattern on temporary canvas + var rootView = svg.ViewPort.viewPorts[0]; + var rect = new svg.Element.rect(); + rect.attributes["x"] = new svg.Property("x", -svg.MAX_VIRTUAL_PIXELS / 3); + rect.attributes["y"] = new svg.Property("y", -svg.MAX_VIRTUAL_PIXELS / 3); + rect.attributes["width"] = new svg.Property("width", svg.MAX_VIRTUAL_PIXELS); + rect.attributes["height"] = new svg.Property("height", svg.MAX_VIRTUAL_PIXELS); + var group = new svg.Element.g(); + group.attributes["transform"] = new svg.Property("transform", this.attribute("gradientTransform").value); + group.children = [ rect ]; + var tempSvg = new svg.Element.svg(); + tempSvg.attributes["x"] = new svg.Property("x", 0); + tempSvg.attributes["y"] = new svg.Property("y", 0); + tempSvg.attributes["width"] = new svg.Property("width", rootView.width); + tempSvg.attributes["height"] = new svg.Property("height", rootView.height); + tempSvg.children = [ group ]; + var c = document.createElement("canvas"); + c.width = rootView.width; + c.height = rootView.height; + var tempCtx = c.getContext("2d"); + tempCtx.fillStyle = g; + tempSvg.render(tempCtx); + return tempCtx.createPattern(c, "no-repeat"); + } + return g; + }; + }; + svg.Element.GradientBase.prototype = new svg.Element.ElementBase(); + // linear gradient element + svg.Element.linearGradient = function(node) { + this.base = svg.Element.GradientBase; + this.base(node); + this.getGradient = function(ctx, element) { + var bb = element.getBoundingBox(); + if (!this.attribute("x1").hasValue() && !this.attribute("y1").hasValue() && !this.attribute("x2").hasValue() && !this.attribute("y2").hasValue()) { + this.attribute("x1", true).value = 0; + this.attribute("y1", true).value = 0; + this.attribute("x2", true).value = 1; + this.attribute("y2", true).value = 0; + } + var x1 = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("x1").numValue() : this.attribute("x1").toPixels("x"); + var y1 = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("y1").numValue() : this.attribute("y1").toPixels("y"); + var x2 = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("x2").numValue() : this.attribute("x2").toPixels("x"); + var y2 = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("y2").numValue() : this.attribute("y2").toPixels("y"); + if (x1 == x2 && y1 == y2) return null; + return ctx.createLinearGradient(x1, y1, x2, y2); + }; + }; + svg.Element.linearGradient.prototype = new svg.Element.GradientBase(); + // radial gradient element + svg.Element.radialGradient = function(node) { + this.base = svg.Element.GradientBase; + this.base(node); + this.getGradient = function(ctx, element) { + var bb = element.getBoundingBox(); + if (!this.attribute("cx").hasValue()) this.attribute("cx", true).value = "50%"; + if (!this.attribute("cy").hasValue()) this.attribute("cy", true).value = "50%"; + if (!this.attribute("r").hasValue()) this.attribute("r", true).value = "50%"; + var cx = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("cx").numValue() : this.attribute("cx").toPixels("x"); + var cy = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("cy").numValue() : this.attribute("cy").toPixels("y"); + var fx = cx; + var fy = cy; + if (this.attribute("fx").hasValue()) { + fx = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("fx").numValue() : this.attribute("fx").toPixels("x"); + } + if (this.attribute("fy").hasValue()) { + fy = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("fy").numValue() : this.attribute("fy").toPixels("y"); + } + var r = this.gradientUnits == "objectBoundingBox" ? (bb.width() + bb.height()) / 2 * this.attribute("r").numValue() : this.attribute("r").toPixels(); + return ctx.createRadialGradient(fx, fy, 0, cx, cy, r); + }; + }; + svg.Element.radialGradient.prototype = new svg.Element.GradientBase(); + // gradient stop element + svg.Element.stop = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.offset = this.attribute("offset").numValue(); + if (this.offset < 0) this.offset = 0; + if (this.offset > 1) this.offset = 1; + var stopColor = this.style("stop-color"); + if (this.style("stop-opacity").hasValue()) stopColor = stopColor.addOpacity(this.style("stop-opacity").value); + this.color = stopColor.value; + }; + svg.Element.stop.prototype = new svg.Element.ElementBase(); + // animation base element + svg.Element.AnimateBase = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + svg.Animations.push(this); + this.duration = 0; + this.begin = this.attribute("begin").toMilliseconds(); + this.maxDuration = this.begin + this.attribute("dur").toMilliseconds(); + this.getProperty = function() { + var attributeType = this.attribute("attributeType").value; + var attributeName = this.attribute("attributeName").value; + if (attributeType == "CSS") { + return this.parent.style(attributeName, true); + } + return this.parent.attribute(attributeName, true); + }; + this.initialValue = null; + this.initialUnits = ""; + this.removed = false; + this.calcValue = function() { + // OVERRIDE ME! + return ""; + }; + this.update = function(delta) { + // set initial value + if (this.initialValue == null) { + this.initialValue = this.getProperty().value; + this.initialUnits = this.getProperty().getUnits(); + } + // if we're past the end time + if (this.duration > this.maxDuration) { + // loop for indefinitely repeating animations + if (this.attribute("repeatCount").value == "indefinite" || this.attribute("repeatDur").value == "indefinite") { + this.duration = 0; + } else if (this.attribute("fill").valueOrDefault("remove") == "remove" && !this.removed) { + this.removed = true; + this.getProperty().value = this.initialValue; + return true; + } else { + return false; + } + } + this.duration = this.duration + delta; + // if we're past the begin time + var updated = false; + if (this.begin < this.duration) { + var newValue = this.calcValue(); + // tween + if (this.attribute("type").hasValue()) { + // for transform, etc. + var type = this.attribute("type").value; + newValue = type + "(" + newValue + ")"; + } + this.getProperty().value = newValue; + updated = true; + } + return updated; + }; + this.from = this.attribute("from"); + this.to = this.attribute("to"); + this.values = this.attribute("values"); + if (this.values.hasValue()) this.values.value = this.values.value.split(";"); + // fraction of duration we've covered + this.progress = function() { + var ret = { + progress: (this.duration - this.begin) / (this.maxDuration - this.begin) + }; + if (this.values.hasValue()) { + var p = ret.progress * (this.values.value.length - 1); + var lb = Math.floor(p), ub = Math.ceil(p); + ret.from = new svg.Property("from", parseFloat(this.values.value[lb])); + ret.to = new svg.Property("to", parseFloat(this.values.value[ub])); + ret.progress = (p - lb) / (ub - lb); + } else { + ret.from = this.from; + ret.to = this.to; + } + return ret; + }; + }; + svg.Element.AnimateBase.prototype = new svg.Element.ElementBase(); + // animate element + svg.Element.animate = function(node) { + this.base = svg.Element.AnimateBase; + this.base(node); + this.calcValue = function() { + var p = this.progress(); + // tween value linearly + var newValue = p.from.numValue() + (p.to.numValue() - p.from.numValue()) * p.progress; + return newValue + this.initialUnits; + }; + }; + svg.Element.animate.prototype = new svg.Element.AnimateBase(); + // animate color element + svg.Element.animateColor = function(node) { + this.base = svg.Element.AnimateBase; + this.base(node); + this.calcValue = function() { + var p = this.progress(); + var from = new RGBColor(p.from.value); + var to = new RGBColor(p.to.value); + if (from.ok && to.ok) { + // tween color linearly + var r = from.r + (to.r - from.r) * p.progress; + var g = from.g + (to.g - from.g) * p.progress; + var b = from.b + (to.b - from.b) * p.progress; + return "rgb(" + parseInt(r, 10) + "," + parseInt(g, 10) + "," + parseInt(b, 10) + ")"; + } + return this.attribute("from").value; + }; + }; + svg.Element.animateColor.prototype = new svg.Element.AnimateBase(); + // animate transform element + svg.Element.animateTransform = function(node) { + this.base = svg.Element.AnimateBase; + this.base(node); + this.calcValue = function() { + var p = this.progress(); + // tween value linearly + var from = svg.ToNumberArray(p.from.value); + var to = svg.ToNumberArray(p.to.value); + var newValue = ""; + for (var i = 0; i < from.length; i++) { + newValue += from[i] + (to[i] - from[i]) * p.progress + " "; + } + return newValue; + }; + }; + svg.Element.animateTransform.prototype = new svg.Element.animate(); + // font element + svg.Element.font = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.horizAdvX = this.attribute("horiz-adv-x").numValue(); + this.isRTL = false; + this.isArabic = false; + this.fontFace = null; + this.missingGlyph = null; + this.glyphs = []; + for (var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if (child.type == "font-face") { + this.fontFace = child; + if (child.style("font-family").hasValue()) { + svg.Definitions[child.style("font-family").value] = this; + } + } else if (child.type == "missing-glyph") this.missingGlyph = child; else if (child.type == "glyph") { + if (child.arabicForm != "") { + this.isRTL = true; + this.isArabic = true; + if (typeof this.glyphs[child.unicode] == "undefined") this.glyphs[child.unicode] = []; + this.glyphs[child.unicode][child.arabicForm] = child; + } else { + this.glyphs[child.unicode] = child; + } + } + } + }; + svg.Element.font.prototype = new svg.Element.ElementBase(); + // font-face element + svg.Element.fontface = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.ascent = this.attribute("ascent").value; + this.descent = this.attribute("descent").value; + this.unitsPerEm = this.attribute("units-per-em").numValue(); + }; + svg.Element.fontface.prototype = new svg.Element.ElementBase(); + // missing-glyph element + svg.Element.missingglyph = function(node) { + this.base = svg.Element.path; + this.base(node); + this.horizAdvX = 0; + }; + svg.Element.missingglyph.prototype = new svg.Element.path(); + // glyph element + svg.Element.glyph = function(node) { + this.base = svg.Element.path; + this.base(node); + this.horizAdvX = this.attribute("horiz-adv-x").numValue(); + this.unicode = this.attribute("unicode").value; + this.arabicForm = this.attribute("arabic-form").value; + }; + svg.Element.glyph.prototype = new svg.Element.path(); + // text element + svg.Element.text = function(node) { + this.captureTextNodes = true; + this.base = svg.Element.RenderedElementBase; + this.base(node); + this.baseSetContext = this.setContext; + this.setContext = function(ctx) { + this.baseSetContext(ctx); + if (this.style("dominant-baseline").hasValue()) ctx.textBaseline = this.style("dominant-baseline").value; + if (this.style("alignment-baseline").hasValue()) ctx.textBaseline = this.style("alignment-baseline").value; + }; + this.getBoundingBox = function() { + // TODO: implement + return new svg.BoundingBox(this.attribute("x").toPixels("x"), this.attribute("y").toPixels("y"), 0, 0); + }; + this.renderChildren = function(ctx) { + this.x = this.attribute("x").toPixels("x"); + this.y = this.attribute("y").toPixels("y"); + this.x += this.getAnchorDelta(ctx, this, 0); + for (var i = 0; i < this.children.length; i++) { + this.renderChild(ctx, this, i); + } + }; + this.getAnchorDelta = function(ctx, parent, startI) { + var textAnchor = this.style("text-anchor").valueOrDefault("start"); + if (textAnchor != "start") { + var width = 0; + for (var i = startI; i < parent.children.length; i++) { + var child = parent.children[i]; + if (i > startI && child.attribute("x").hasValue()) break; + // new group + width += child.measureTextRecursive(ctx); + } + return -1 * (textAnchor == "end" ? width : width / 2); + } + return 0; + }; + this.renderChild = function(ctx, parent, i) { + var child = parent.children[i]; + if (child.attribute("x").hasValue()) { + child.x = child.attribute("x").toPixels("x") + this.getAnchorDelta(ctx, parent, i); + } else { + if (this.attribute("dx").hasValue()) this.x += this.attribute("dx").toPixels("x"); + if (child.attribute("dx").hasValue()) this.x += child.attribute("dx").toPixels("x"); + child.x = this.x; + } + this.x = child.x + child.measureText(ctx); + if (child.attribute("y").hasValue()) { + child.y = child.attribute("y").toPixels("y"); + } else { + if (this.attribute("dy").hasValue()) this.y += this.attribute("dy").toPixels("y"); + if (child.attribute("dy").hasValue()) this.y += child.attribute("dy").toPixels("y"); + child.y = this.y; + } + this.y = child.y; + child.render(ctx); + for (var i = 0; i < child.children.length; i++) { + this.renderChild(ctx, child, i); + } + }; + }; + svg.Element.text.prototype = new svg.Element.RenderedElementBase(); + // text base + svg.Element.TextElementBase = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + this.getGlyph = function(font, text, i) { + var c = text[i]; + var glyph = null; + if (font.isArabic) { + var arabicForm = "isolated"; + if ((i == 0 || text[i - 1] == " ") && i < text.length - 2 && text[i + 1] != " ") arabicForm = "terminal"; + if (i > 0 && text[i - 1] != " " && i < text.length - 2 && text[i + 1] != " ") arabicForm = "medial"; + if (i > 0 && text[i - 1] != " " && (i == text.length - 1 || text[i + 1] == " ")) arabicForm = "initial"; + if (typeof font.glyphs[c] != "undefined") { + glyph = font.glyphs[c][arabicForm]; + if (glyph == null && font.glyphs[c].type == "glyph") glyph = font.glyphs[c]; + } + } else { + glyph = font.glyphs[c]; + } + if (glyph == null) glyph = font.missingGlyph; + return glyph; + }; + this.renderChildren = function(ctx) { + var customFont = this.parent.style("font-family").getDefinition(); + if (customFont != null) { + var fontSize = this.parent.style("font-size").numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize); + var fontStyle = this.parent.style("font-style").valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle); + var text = this.getText(); + if (customFont.isRTL) text = text.split("").reverse().join(""); + var dx = svg.ToNumberArray(this.parent.attribute("dx").value); + for (var i = 0; i < text.length; i++) { + var glyph = this.getGlyph(customFont, text, i); + var scale = fontSize / customFont.fontFace.unitsPerEm; + ctx.translate(this.x, this.y); + ctx.scale(scale, -scale); + var lw = ctx.lineWidth; + ctx.lineWidth = ctx.lineWidth * customFont.fontFace.unitsPerEm / fontSize; + if (fontStyle == "italic") ctx.transform(1, 0, .4, 1, 0, 0); + glyph.render(ctx); + if (fontStyle == "italic") ctx.transform(1, 0, -.4, 1, 0, 0); + ctx.lineWidth = lw; + ctx.scale(1 / scale, -1 / scale); + ctx.translate(-this.x, -this.y); + this.x += fontSize * (glyph.horizAdvX || customFont.horizAdvX) / customFont.fontFace.unitsPerEm; + if (typeof dx[i] != "undefined" && !isNaN(dx[i])) { + this.x += dx[i]; + } + } + return; + } + if (ctx.fillStyle != "") ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y); + if (ctx.strokeStyle != "") ctx.strokeText(svg.compressSpaces(this.getText()), this.x, this.y); + }; + this.getText = function() {}; + this.measureTextRecursive = function(ctx) { + var width = this.measureText(ctx); + for (var i = 0; i < this.children.length; i++) { + width += this.children[i].measureTextRecursive(ctx); + } + return width; + }; + this.measureText = function(ctx) { + var customFont = this.parent.style("font-family").getDefinition(); + if (customFont != null) { + var fontSize = this.parent.style("font-size").numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize); + var measure = 0; + var text = this.getText(); + if (customFont.isRTL) text = text.split("").reverse().join(""); + var dx = svg.ToNumberArray(this.parent.attribute("dx").value); + for (var i = 0; i < text.length; i++) { + var glyph = this.getGlyph(customFont, text, i); + measure += (glyph.horizAdvX || customFont.horizAdvX) * fontSize / customFont.fontFace.unitsPerEm; + if (typeof dx[i] != "undefined" && !isNaN(dx[i])) { + measure += dx[i]; + } + } + return measure; + } + var textToMeasure = svg.compressSpaces(this.getText()); + if (!ctx.measureText) return textToMeasure.length * 10; + ctx.save(); + this.setContext(ctx); + var width = ctx.measureText(textToMeasure).width; + ctx.restore(); + return width; + }; + }; + svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase(); + // tspan + svg.Element.tspan = function(node) { + this.captureTextNodes = true; + this.base = svg.Element.TextElementBase; + this.base(node); + this.text = node.nodeValue || node.text || ""; + this.getText = function() { + return this.text; + }; + }; + svg.Element.tspan.prototype = new svg.Element.TextElementBase(); + // tref + svg.Element.tref = function(node) { + this.base = svg.Element.TextElementBase; + this.base(node); + this.getText = function() { + var element = this.getHrefAttribute().getDefinition(); + if (element != null) return element.children[0].getText(); + }; + }; + svg.Element.tref.prototype = new svg.Element.TextElementBase(); + // a element + svg.Element.a = function(node) { + this.base = svg.Element.TextElementBase; + this.base(node); + this.hasText = true; + for (var i = 0; i < node.childNodes.length; i++) { + if (node.childNodes[i].nodeType != 3) this.hasText = false; + } + // this might contain text + this.text = this.hasText ? node.childNodes[0].nodeValue : ""; + this.getText = function() { + return this.text; + }; + this.baseRenderChildren = this.renderChildren; + this.renderChildren = function(ctx) { + if (this.hasText) { + // render as text element + this.baseRenderChildren(ctx); + var fontSize = new svg.Property("fontSize", svg.Font.Parse(svg.ctx.font).fontSize); + svg.Mouse.checkBoundingBox(this, new svg.BoundingBox(this.x, this.y - fontSize.toPixels("y"), this.x + this.measureText(ctx), this.y)); + } else { + // render as temporary group + var g = new svg.Element.g(); + g.children = this.children; + g.parent = this; + g.render(ctx); + } + }; + this.onclick = function() { + window.open(this.getHrefAttribute().value); + }; + this.onmousemove = function() { + svg.ctx.canvas.style.cursor = "pointer"; + }; + }; + svg.Element.a.prototype = new svg.Element.TextElementBase(); + // image element + svg.Element.image = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + var href = this.getHrefAttribute().value; + var isSvg = href.match(/\.svg$/); + svg.Images.push(this); + this.loaded = false; + if (!isSvg) { + this.img = document.createElement("img"); + var self = this; + this.img.onload = function() { + self.loaded = true; + }; + this.img.onerror = function() { + if (typeof console != "undefined") { + console.log('ERROR: image "' + href + '" not found'); + self.loaded = true; + } + }; + this.img.src = href; + } else { + this.img = svg.ajax(href); + this.loaded = true; + } + this.renderChildren = function(ctx) { + var x = this.attribute("x").toPixels("x"); + var y = this.attribute("y").toPixels("y"); + var width = this.attribute("width").toPixels("x"); + var height = this.attribute("height").toPixels("y"); + if (width == 0 || height == 0) return; + ctx.save(); + if (isSvg) { + ctx.drawSvg(this.img, x, y, width, height); + } else { + ctx.translate(x, y); + svg.AspectRatio(ctx, this.attribute("preserveAspectRatio").value, width, this.img.width, height, this.img.height, 0, 0); + ctx.drawImage(this.img, 0, 0); + } + ctx.restore(); + }; + this.getBoundingBox = function() { + var x = this.attribute("x").toPixels("x"); + var y = this.attribute("y").toPixels("y"); + var width = this.attribute("width").toPixels("x"); + var height = this.attribute("height").toPixels("y"); + return new svg.BoundingBox(x, y, x + width, y + height); + }; + }; + svg.Element.image.prototype = new svg.Element.RenderedElementBase(); + // group element + svg.Element.g = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + this.getBoundingBox = function() { + var bb = new svg.BoundingBox(); + for (var i = 0; i < this.children.length; i++) { + bb.addBoundingBox(this.children[i].getBoundingBox()); + } + return bb; + }; + }; + svg.Element.g.prototype = new svg.Element.RenderedElementBase(); + // symbol element + svg.Element.symbol = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + this.baseSetContext = this.setContext; + this.setContext = function(ctx) { + this.baseSetContext(ctx); + // viewbox + if (this.attribute("viewBox").hasValue()) { + var viewBox = svg.ToNumberArray(this.attribute("viewBox").value); + var minX = viewBox[0]; + var minY = viewBox[1]; + width = viewBox[2]; + height = viewBox[3]; + svg.AspectRatio(ctx, this.attribute("preserveAspectRatio").value, this.attribute("width").toPixels("x"), width, this.attribute("height").toPixels("y"), height, minX, minY); + svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]); + } + }; + }; + svg.Element.symbol.prototype = new svg.Element.RenderedElementBase(); + // style element + svg.Element.style = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + // text, or spaces then CDATA + var css = ""; + for (var i = 0; i < node.childNodes.length; i++) { + css += node.childNodes[i].nodeValue; + } + css = css.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm, ""); + // remove comments + css = svg.compressSpaces(css); + // replace whitespace + var cssDefs = css.split("}"); + for (var i = 0; i < cssDefs.length; i++) { + if (svg.trim(cssDefs[i]) != "") { + var cssDef = cssDefs[i].split("{"); + var cssClasses = cssDef[0].split(","); + var cssProps = cssDef[1].split(";"); + for (var j = 0; j < cssClasses.length; j++) { + var cssClass = svg.trim(cssClasses[j]); + if (cssClass != "") { + var props = {}; + for (var k = 0; k < cssProps.length; k++) { + var prop = cssProps[k].indexOf(":"); + var name = cssProps[k].substr(0, prop); + var value = cssProps[k].substr(prop + 1, cssProps[k].length - prop); + if (name != null && value != null) { + props[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value)); + } + } + svg.Styles[cssClass] = props; + if (cssClass == "@font-face") { + var fontFamily = props["font-family"].value.replace(/"/g, ""); + var srcs = props["src"].value.split(","); + for (var s = 0; s < srcs.length; s++) { + if (srcs[s].indexOf('format("svg")') > 0) { + var urlStart = srcs[s].indexOf("url"); + var urlEnd = srcs[s].indexOf(")", urlStart); + var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6); + var doc = svg.parseXml(svg.ajax(url)); + var fonts = doc.getElementsByTagName("font"); + for (var f = 0; f < fonts.length; f++) { + var font = svg.CreateElement(fonts[f]); + svg.Definitions[fontFamily] = font; + } + } + } + } + } + } + } + } + }; + svg.Element.style.prototype = new svg.Element.ElementBase(); + // use element + svg.Element.use = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + this.baseSetContext = this.setContext; + this.setContext = function(ctx) { + this.baseSetContext(ctx); + if (this.attribute("x").hasValue()) ctx.translate(this.attribute("x").toPixels("x"), 0); + if (this.attribute("y").hasValue()) ctx.translate(0, this.attribute("y").toPixels("y")); + }; + this.getDefinition = function() { + var element = this.getHrefAttribute().getDefinition(); + if (this.attribute("width").hasValue()) element.attribute("width", true).value = this.attribute("width").value; + if (this.attribute("height").hasValue()) element.attribute("height", true).value = this.attribute("height").value; + return element; + }; + this.path = function(ctx) { + var element = this.getDefinition(); + if (element != null) element.path(ctx); + }; + this.getBoundingBox = function() { + var element = this.getDefinition(); + if (element != null) return element.getBoundingBox(); + }; + this.renderChildren = function(ctx) { + var element = this.getDefinition(); + if (element != null) { + // temporarily detach from parent and render + var oldParent = element.parent; + element.parent = null; + element.render(ctx); + element.parent = oldParent; + } + }; + }; + svg.Element.use.prototype = new svg.Element.RenderedElementBase(); + // mask element + svg.Element.mask = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.apply = function(ctx, element) { + // render as temp svg + var x = this.attribute("x").toPixels("x"); + var y = this.attribute("y").toPixels("y"); + var width = this.attribute("width").toPixels("x"); + var height = this.attribute("height").toPixels("y"); + if (width == 0 && height == 0) { + var bb = new svg.BoundingBox(); + for (var i = 0; i < this.children.length; i++) { + bb.addBoundingBox(this.children[i].getBoundingBox()); + } + var x = Math.floor(bb.x1); + var y = Math.floor(bb.y1); + var width = Math.floor(bb.width()); + var height = Math.floor(bb.height()); + } + // temporarily remove mask to avoid recursion + var mask = element.attribute("mask").value; + element.attribute("mask").value = ""; + var cMask = document.createElement("canvas"); + cMask.width = x + width; + cMask.height = y + height; + var maskCtx = cMask.getContext("2d"); + this.renderChildren(maskCtx); + var c = document.createElement("canvas"); + c.width = x + width; + c.height = y + height; + var tempCtx = c.getContext("2d"); + element.render(tempCtx); + tempCtx.globalCompositeOperation = "destination-in"; + tempCtx.fillStyle = maskCtx.createPattern(cMask, "no-repeat"); + tempCtx.fillRect(0, 0, x + width, y + height); + ctx.fillStyle = tempCtx.createPattern(c, "no-repeat"); + ctx.fillRect(0, 0, x + width, y + height); + // reassign mask + element.attribute("mask").value = mask; + }; + this.render = function(ctx) {}; + }; + svg.Element.mask.prototype = new svg.Element.ElementBase(); + // clip element + svg.Element.clipPath = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.apply = function(ctx) { + for (var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if (typeof child.path != "undefined") { + var transform = null; + if (child.attribute("transform").hasValue()) { + transform = new svg.Transform(child.attribute("transform").value); + transform.apply(ctx); + } + child.path(ctx); + ctx.clip(); + if (transform) { + transform.unapply(ctx); + } + } + } + }; + this.render = function(ctx) {}; + }; + svg.Element.clipPath.prototype = new svg.Element.ElementBase(); + // filters + svg.Element.filter = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.apply = function(ctx, element) { + // render as temp svg + var bb = element.getBoundingBox(); + var x = Math.floor(bb.x1); + var y = Math.floor(bb.y1); + var width = Math.floor(bb.width()); + var height = Math.floor(bb.height()); + // temporarily remove filter to avoid recursion + var filter = element.style("filter").value; + element.style("filter").value = ""; + var px = 0, py = 0; + for (var i = 0; i < this.children.length; i++) { + var efd = this.children[i].extraFilterDistance || 0; + px = Math.max(px, efd); + py = Math.max(py, efd); + } + var c = document.createElement("canvas"); + c.width = width + 2 * px; + c.height = height + 2 * py; + var tempCtx = c.getContext("2d"); + tempCtx.translate(-x + px, -y + py); + element.render(tempCtx); + // apply filters + for (var i = 0; i < this.children.length; i++) { + this.children[i].apply(tempCtx, 0, 0, width + 2 * px, height + 2 * py); + } + // render on me + ctx.drawImage(c, 0, 0, width + 2 * px, height + 2 * py, x - px, y - py, width + 2 * px, height + 2 * py); + // reassign filter + element.style("filter", true).value = filter; + }; + this.render = function(ctx) {}; + }; + svg.Element.filter.prototype = new svg.Element.ElementBase(); + svg.Element.feMorphology = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.apply = function(ctx, x, y, width, height) {}; + }; + svg.Element.feMorphology.prototype = new svg.Element.ElementBase(); + svg.Element.feColorMatrix = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + function imGet(img, x, y, width, height, rgba) { + return img[y * width * 4 + x * 4 + rgba]; + } + function imSet(img, x, y, width, height, rgba, val) { + img[y * width * 4 + x * 4 + rgba] = val; + } + this.apply = function(ctx, x, y, width, height) { + // only supporting grayscale for now per Issue 195, need to extend to all matrix + // assuming x==0 && y==0 for now + var srcData = ctx.getImageData(0, 0, width, height); + for (var y = 0; y < height; y++) { + for (var x = 0; x < width; x++) { + var r = imGet(srcData.data, x, y, width, height, 0); + var g = imGet(srcData.data, x, y, width, height, 1); + var b = imGet(srcData.data, x, y, width, height, 2); + var gray = (r + g + b) / 3; + imSet(srcData.data, x, y, width, height, 0, gray); + imSet(srcData.data, x, y, width, height, 1, gray); + imSet(srcData.data, x, y, width, height, 2, gray); + } + } + ctx.clearRect(0, 0, width, height); + ctx.putImageData(srcData, 0, 0); + }; + }; + svg.Element.feColorMatrix.prototype = new svg.Element.ElementBase(); + svg.Element.feGaussianBlur = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + this.blurRadius = Math.floor(this.attribute("stdDeviation").numValue()); + this.extraFilterDistance = this.blurRadius; + this.apply = function(ctx, x, y, width, height) { + if (typeof stackBlurCanvasRGBA == "undefined") { + if (typeof console != "undefined") { + console.log("ERROR: StackBlur.js must be included for blur to work"); + } + return; + } + // StackBlur requires canvas be on document + ctx.canvas.id = svg.UniqueId(); + ctx.canvas.style.display = "none"; + document.body.appendChild(ctx.canvas); + stackBlurCanvasRGBA(ctx.canvas.id, x, y, width, height, this.blurRadius); + document.body.removeChild(ctx.canvas); + }; + }; + svg.Element.feGaussianBlur.prototype = new svg.Element.ElementBase(); + // title element, do nothing + svg.Element.title = function(node) {}; + svg.Element.title.prototype = new svg.Element.ElementBase(); + // desc element, do nothing + svg.Element.desc = function(node) {}; + svg.Element.desc.prototype = new svg.Element.ElementBase(); + svg.Element.MISSING = function(node) { + if (typeof console != "undefined") { + console.log("ERROR: Element '" + node.nodeName + "' not yet implemented."); + } + }; + svg.Element.MISSING.prototype = new svg.Element.ElementBase(); + // element factory + svg.CreateElement = function(node) { + var className = node.nodeName.replace(/^[^:]+:/, ""); + // remove namespace + className = className.replace(/\-/g, ""); + // remove dashes + var e = null; + if (typeof svg.Element[className] != "undefined") { + e = new svg.Element[className](node); + } else { + e = new svg.Element.MISSING(node); + } + e.type = node.nodeName; + return e; + }; + // load from url + svg.load = function(ctx, url) { + svg.loadXml(ctx, svg.ajax(url)); + }; + // load from xml + svg.loadXml = function(ctx, xml) { + svg.loadXmlDoc(ctx, svg.parseXml(xml)); + }; + svg.loadXmlDoc = function(ctx, dom) { + svg.init(ctx); + var mapXY = function(p) { + var e = ctx.canvas; + while (e) { + p.x -= e.offsetLeft; + p.y -= e.offsetTop; + e = e.offsetParent; + } + if (window.scrollX) p.x += window.scrollX; + if (window.scrollY) p.y += window.scrollY; + return p; + }; + // bind mouse + if (svg.opts["ignoreMouse"] != true) { + ctx.canvas.onclick = function(e) { + var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY)); + svg.Mouse.onclick(p.x, p.y); + }; + ctx.canvas.onmousemove = function(e) { + var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY)); + svg.Mouse.onmousemove(p.x, p.y); + }; + } + var e = svg.CreateElement(dom.documentElement); + e.root = true; + // render loop + var isFirstRender = true; + var draw = function() { + svg.ViewPort.Clear(); + if (ctx.canvas.parentNode) svg.ViewPort.SetCurrent(ctx.canvas.parentNode.clientWidth, ctx.canvas.parentNode.clientHeight); + if (svg.opts["ignoreDimensions"] != true) { + // set canvas size + if (e.style("width").hasValue()) { + ctx.canvas.width = e.style("width").toPixels("x"); + ctx.canvas.style.width = ctx.canvas.width + "px"; + } + if (e.style("height").hasValue()) { + ctx.canvas.height = e.style("height").toPixels("y"); + ctx.canvas.style.height = ctx.canvas.height + "px"; + } + } + var cWidth = ctx.canvas.clientWidth || ctx.canvas.width; + var cHeight = ctx.canvas.clientHeight || ctx.canvas.height; + if (svg.opts["ignoreDimensions"] == true && e.style("width").hasValue() && e.style("height").hasValue()) { + cWidth = e.style("width").toPixels("x"); + cHeight = e.style("height").toPixels("y"); + } + svg.ViewPort.SetCurrent(cWidth, cHeight); + if (svg.opts["offsetX"] != null) e.attribute("x", true).value = svg.opts["offsetX"]; + if (svg.opts["offsetY"] != null) e.attribute("y", true).value = svg.opts["offsetY"]; + if (svg.opts["scaleWidth"] != null && svg.opts["scaleHeight"] != null) { + var xRatio = 1, yRatio = 1, viewBox = svg.ToNumberArray(e.attribute("viewBox").value); + if (e.attribute("width").hasValue()) xRatio = e.attribute("width").toPixels("x") / svg.opts["scaleWidth"]; else if (!isNaN(viewBox[2])) xRatio = viewBox[2] / svg.opts["scaleWidth"]; + if (e.attribute("height").hasValue()) yRatio = e.attribute("height").toPixels("y") / svg.opts["scaleHeight"]; else if (!isNaN(viewBox[3])) yRatio = viewBox[3] / svg.opts["scaleHeight"]; + e.attribute("width", true).value = svg.opts["scaleWidth"]; + e.attribute("height", true).value = svg.opts["scaleHeight"]; + e.attribute("viewBox", true).value = "0 0 " + cWidth * xRatio + " " + cHeight * yRatio; + e.attribute("preserveAspectRatio", true).value = "none"; + } + // clear and render + if (svg.opts["ignoreClear"] != true) { + ctx.clearRect(0, 0, cWidth, cHeight); + } + e.render(ctx); + if (isFirstRender) { + isFirstRender = false; + if (typeof svg.opts["renderCallback"] == "function") svg.opts["renderCallback"](dom); + } + }; + var waitingForImages = true; + if (svg.ImagesLoaded()) { + waitingForImages = false; + draw(); + } + svg.intervalID = setInterval(function() { + var needUpdate = false; + if (waitingForImages && svg.ImagesLoaded()) { + waitingForImages = false; + needUpdate = true; + } + // need update from mouse events? + if (svg.opts["ignoreMouse"] != true) { + needUpdate = needUpdate | svg.Mouse.hasEvents(); + } + // need update from animations? + if (svg.opts["ignoreAnimation"] != true) { + for (var i = 0; i < svg.Animations.length; i++) { + needUpdate = needUpdate | svg.Animations[i].update(1e3 / svg.FRAMERATE); + } + } + // need update from redraw? + if (typeof svg.opts["forceRedraw"] == "function") { + if (svg.opts["forceRedraw"]() == true) needUpdate = true; + } + // render if needed + if (needUpdate) { + draw(); + svg.Mouse.runEvents(); + } + }, 1e3 / svg.FRAMERATE); + }; + svg.stop = function() { + if (svg.intervalID) { + clearInterval(svg.intervalID); + } + }; + svg.Mouse = new function() { + this.events = []; + this.hasEvents = function() { + return this.events.length != 0; + }; + this.onclick = function(x, y) { + this.events.push({ + type: "onclick", + x: x, + y: y, + run: function(e) { + if (e.onclick) e.onclick(); + } + }); + }; + this.onmousemove = function(x, y) { + this.events.push({ + type: "onmousemove", + x: x, + y: y, + run: function(e) { + if (e.onmousemove) e.onmousemove(); + } + }); + }; + this.eventElements = []; + this.checkPath = function(element, ctx) { + for (var i = 0; i < this.events.length; i++) { + var e = this.events[i]; + if (ctx.isPointInPath && ctx.isPointInPath(e.x, e.y)) this.eventElements[i] = element; + } + }; + this.checkBoundingBox = function(element, bb) { + for (var i = 0; i < this.events.length; i++) { + var e = this.events[i]; + if (bb.isPointInBox(e.x, e.y)) this.eventElements[i] = element; + } + }; + this.runEvents = function() { + svg.ctx.canvas.style.cursor = ""; + for (var i = 0; i < this.events.length; i++) { + var e = this.events[i]; + var element = this.eventElements[i]; + while (element) { + e.run(element); + element = element.parent; + } + } + // done running, clear + this.events = []; + this.eventElements = []; + }; + }(); + return svg; + } + })(); + if (typeof CanvasRenderingContext2D != "undefined") { + CanvasRenderingContext2D.prototype.drawSvg = function(s, dx, dy, dw, dh) { + canvg(this.canvas, s, { + ignoreMouse: true, + ignoreAnimation: true, + ignoreDimensions: true, + ignoreClear: true, + offsetX: dx, + offsetY: dy, + scaleWidth: dw, + scaleHeight: dh + }); + }; + } + return canvg; + } +}; + +/*! + * 输出转换器,提供输出支持 + */ +_p[1] = { + value: function(require) { + var kity = _p.r(34), canvg = _p.r(0); + return kity.createClass("Output", { + constructor: function(formula) { + this.formula = formula; + }, + toJPG: function(cb) { + toImage(this.formula, "image/jpeg", cb); + }, + toPNG: function(cb) { + toImage(this.formula, "image/png", cb); + } + }); + function toImage(formula, type, cb) { + var rectSpace = formula.container.getRenderBox(); + return getBase64DataURL(formula.node.ownerDocument, { + width: rectSpace.width, + height: rectSpace.height, + content: getSVGContent(formula.node) + }, type, cb); + } + function getBase64DataURL(doc, data, type, cb) { + var canvas = null, args = arguments, ctx = null; + if (true) { + drawToCanvas.apply(null, args); + } else { + canvas = getImageCanvas(doc, data.width, data.height, type); + ctx = canvas.getContext("2d"); + var image = new Image(); + image.onload = function() { + try { + ctx.drawImage(image, 0, 0); + cb(canvas.toDataURL(type)); + } catch (e) { + drawToCanvas.apply(null, args); + } + }; + image.src = getSVGDataURL(data.content); + } + } + function getSVGContent(svgNode) { + var tmp = svgNode.ownerDocument.createElement("div"), start = [ '' ]; + tmp.appendChild(svgNode.cloneNode(true)); + return tmp.innerHTML.replace(/]+?>/i, start.join("")).replace(/ /g, ""); + } + function getSVGDataURL(data) { + return "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(data))); + } + function getImageCanvas(doc, width, height, type) { + var canvas = doc.createElement("canvas"), ctx = canvas.getContext("2d"); + canvas.width = width; + canvas.height = height; + if (type !== "image/png") { + ctx.fillStyle = "white"; + ctx.fillRect(0, 0, canvas.width, canvas.height); + } + return canvas; + } + function drawToCanvas(doc, data, type, cb) { + var canvas = getImageCanvas(doc, data.width, data.height, type); + canvas.style.cssText = "position: absolute; top: 0; left: 100000px; z-index: -1;"; + window.setTimeout(function() { + doc.body.appendChild(canvas); + canvg(canvas, data.content); + doc.body.removeChild(canvas); + cb(canvas.toDataURL(type)); + }, 0); + } + } +}; + +/*! + * 所有字符的列表 + */ +_p[2] = { + value: function() { + return [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "ȷ", "ı", "α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ", "λ", "μ", "ν", "ξ", "ο", "π", "ρ", "ς", "σ", "τ", "υ", "φ", "χ", "ψ", "ω", "ϑ", "ϕ", "ϖ", "Ϟ", "Ϝ", "ϵ", "ϱ", "Ϲ", "ℜ", "ℵ", "ℑ", "℧", "ℶ", "ℷ", "ℸ", "ð", "ℏ", "⅁", "ℎ", "∂", "℘", "⅌", "Ⅎ", "∁", "ℓ", "Ⓢ", "(", ")", "Γ", "Δ", "Ε", "Ζ", "Η", "Θ", "Ι", "Κ", "Λ", "Μ", "Ν", "Ξ", "Ο", "Π", "Ρ", "Σ", "Τ", "Υ", "Φ", "Χ", "Ψ", "Ω", "Α", "Β", "#", "!", "$", "%", "&", "∠", "′", "‵", "★", "◆", "■", "▲", "▼", "⊤", "⊥", "♣", "♠", "♢", "♡", "∃", "∄", "♭", "♮", "♯", "∀", "∞", "∡", "∇", "¬", "∢", "√", "△", "▽", "∅", "ø", "◇", "◀", "▸", "[", "]", "{", "}", "〈", "〉", "ϰ", ",", ".", "/", ":", ";", "?", "\\", "⋮", "⋯", "⋰", "…", "@", """, "'", "|", "^", "`", "“", "_", "*", "+", "-", "∐", "⊼", "⊻", "◯", "⊡", "⊟", "⊞", "⊠", "•", "∩", "∪", "⋒", "⋓", "⋐", "⋑", "·", "▪", "◦", "⊛", "⊚", "⊖", "⊙", "⊝", "⊕", "⊗", "⊘", "±", "∓", "⋏", "⋎", "†", "‡", "⋄", "÷", "⋇", "∔", "⌭", "⋗", "⋖", "⋉", "⋊", "⋋", "⋌", "⊓", "⊔", "⊑", "⊒", "⊏", "⊐", "⋆", "×", "⊳", "⊲", "⊵", "⊴", "⊎", "∨", "∧", "≀", "<", "=", ">", "≈", "≇", "≍", "≒", "≓", "≊", "∽", "≁", "≂", "≃", "⋍", "≏", "≎", "≗", "≅", "⋞", "⋟", "≐", "≑", "≖", "⪖", "⪕", "≡", "≥", "≤", "≦", "≧", "⩾", "⩽", "≫", "≪", "≨", "≩", "⋘", "⋙", "⪇", "⪈", "⪉", "⪊", "⋧", "⋦", "⪆", "⪅", "⋛", "⋚", "⪋", "⪌", "≷", "≶", "≳", "≲", "⌮", "⌯", "≯", "≱", "≰", "≮", "⌱", "⌰", "⌲", "⌳", "≬", "⊀", "⊁", "⋠", "⋡", "≺", "≻", "≼", "≽", "≾", "≿", "⊂", "⊃", "⊈", "⊉", "⊆", "⊇", "⊊", "⊋", "⪷", "⪸", "⪯", "⪰", "⪹", "⪺", "⪵", "⪶", "⋨", "⋩", "∼", "≜", "↶", "↷", "↺", "↻", "↾", "↿", "⇂", "⇃", "⇄", "⇆", "⇈", "⇊", "⇋", "⇌", "⇍", "⇎", "⇏", "⇐", "⇑", "⇒", "⇓", "⇔", "⇕", "⇚", "⇛", "⇝", "↫", "↬", "↭", "↮", "←", "↑", "→", "↓", "↔", "↕", "↖", "↗", "↘", "↙", "↞", "↠", "↢", "↣", "↰", "↱", "⊢", "⊣", "⊨", "⊩", "⊪", "⊭", "⊯", "⊸", "⊺", "⋔", "⋪", "⋫", "⋬", "⋭", "⌈", "⌉", "⌊", "⌋", "⫋", "⫌", "⫅", "⫆", "∈", "∋", "∝", "∤", "∦", "∴", "∵", "∍", "⋈", "⌢", "⌣", "∣", "∥", "⏐", "⏑", "⏒", "⏓", "⫇", "⫈", "⊮", "⊬", "⫉", "⏔", "⏕", "⏖", "⏗", "⇇", "⇉", "↼", "↽", "⇀", "⇁", "↚", "↛", "⟵", "⟶", "⟷", "⟹", "⟸", "⟺", "≢", "≠", "∉" ]; + } +}; + +/*! + * 字符配置 + */ +_p[3] = { + value: function() { + return { + // 默认字体 + defaultFont: "KF AMS MAIN" + }; + } +}; + +/*! + * 工厂方法,创建兼容各浏览器的text实现 + */ +_p[4] = { + value: function(require) { + var kity = _p.r(34), divNode = document.createElement("div"), NAMESPACE = "http://www.w3.org/XML/1998/namespace"; + function createText(content) { + var text = new kity.Text(); + // Non-IE + if ("innerHTML" in text.node) { + text.node.setAttributeNS(NAMESPACE, "xml:space", "preserve"); + } else { + if (content.indexOf(" ") != -1) { + content = convertContent(content); + } + } + text.setContent(content); + return text; + } + /** + * 构建节点来转换内容 + */ + function convertContent(content) { + divNode.innerHTML = '' + content.replace(/\s/gi, " ") + ""; + return divNode.firstChild.firstChild.textContent; + } + return { + create: function(content) { + return createText(content); + } + }; + } +}; + +/** + * 文本 + */ +_p[5] = { + value: function(require) { + var kity = _p.r(34), FONT_CONF = _p.r(47).font, FontManager = _p.r(25), TextFactory = _p.r(4); + return kity.createClass("Text", { + base: _p.r(46), + constructor: function(content, fontFamily) { + this.callBase(); + this.fontFamily = fontFamily; + this.fontSize = 50; + this.content = content || ""; + // 移除多余的节点 + this.box.remove(); + this.translationContent = this.translation(this.content); + this.contentShape = new kity.Group(); + this.contentNode = this.createContent(); + this.contentShape.addShape(this.contentNode); + this.addShape(this.contentShape); + }, + createContent: function() { + var contentNode = TextFactory.create(this.translationContent); + contentNode.setAttr({ + "font-family": this.fontFamily, + "font-size": 50, + x: 0, + y: FONT_CONF.offset + }); + return contentNode; + }, + setFamily: function(fontFamily) { + this.fontFamily = fontFamily; + this.contentNode.setAttr("font-family", fontFamily); + }, + setFontSize: function(fontSize) { + this.fontSize = fontSize; + this.contentNode.setAttr("font-size", fontSize + "px"); + this.contentNode.setAttr("y", fontSize / 50 * FONT_CONF.offset); + }, + getBaseHeight: function() { + var chars = this.contentShape.getItems(), currentChar = null, index = 0, height = 0; + while (currentChar = chars[index]) { + height = Math.max(height, currentChar.getHeight()); + index++; + } + return height; + }, + translation: function(content) { + var fontFamily = this.fontFamily; + // 首先特殊处理掉两个相连的"`"符号 + return content.replace(/``/g, "“").replace(/\\([a-zA-Z,]+)\\/g, function(match, input) { + if (input === ",") { + return " "; + } + var data = FontManager.getCharacterValue(input, fontFamily); + if (!data) { + return ""; + } + return data; + }); + } + }); + } +}; + +/** + * 定义公式中各种对象的类型 + */ +_p[6] = { + value: function() { + return { + UNKNOWN: -1, + EXP: 0, + COMPOUND_EXP: 1, + OP: 2 + }; + } +}; + +/** + * 定义公式中上下标的类型 + */ +_p[7] = { + value: function() { + return { + SIDE: "side", + FOLLOW: "follow" + }; + } +}; + +/** + * 下标表达式 + */ +_p[8] = { + value: function(require) { + var kity = _p.r(34); + return kity.createClass("SubscriptExpression", { + base: _p.r(17), + constructor: function(operand, subscript) { + this.callBase(operand, null, subscript); + this.setFlag("Subscript"); + } + }); + } +}; + +/** + * 上标表达式 + */ +_p[9] = { + value: function(require) { + var kity = _p.r(34); + return kity.createClass("SuperscriptExpression", { + base: _p.r(17), + constructor: function(operand, superscript) { + this.callBase(operand, superscript, null); + this.setFlag("Superscript"); + } + }); + } +}; + +/** + * 二元操作表达式 + */ +_p[10] = { + value: function(require) { + var kity = _p.r(34); + return kity.createClass("BinaryExpression", { + base: _p.r(19), + constructor: function(firstOperand, lastOperand) { + this.callBase(); + this.setFirstOperand(firstOperand); + this.setLastOperand(lastOperand); + }, + setFirstOperand: function(operand) { + return this.setOperand(operand, 0); + }, + getFirstOperand: function() { + return this.getOperand(0); + }, + setLastOperand: function(operand) { + return this.setOperand(operand, 1); + }, + getLastOperand: function() { + return this.getOperand(1); + } + }); + } +}; + +/** + * 自动增长括号表达式 + */ +_p[11] = { + value: function(require) { + var kity = _p.r(34), BracketsOperator = _p.r(35); + return kity.createClass("BracketsExpression", { + base: _p.r(19), + /** + * 构造函数调用方式: + * new Constructor( 左括号, 右括号, 表达式 ) + * 或者 + * new Constructor( 括号, 表达式 ), 该构造函数转换成上面的构造函数,是: new Constructor( 括号, 括号, 表达式 ) + * @param left 左括号 + * @param right 右括号 + * @param exp 表达式 + */ + constructor: function(left, right, exp) { + this.callBase(); + this.setFlag("Brackets"); + // 参数整理 + if (arguments.length === 2) { + exp = right; + right = left; + } + this.leftSymbol = left; + this.rightSymbol = right; + this.setOperator(new BracketsOperator()); + this.setOperand(exp, 0); + }, + getLeftSymbol: function() { + return this.leftSymbol; + }, + getRightSymbol: function() { + return this.rightSymbol; + } + }); + } +}; + +/** + * 组合表达式 + * 可以组合多个表达式 + */ +_p[12] = { + value: function(require) { + var kity = _p.r(34), FONT_CONF = _p.r(47).font, CombinationOperator = _p.r(36); + return kity.createClass("CombinationExpression", { + base: _p.r(19), + constructor: function() { + this.callBase(); + this.setFlag("Combination"); + this.setOperator(new CombinationOperator()); + kity.Utils.each(arguments, function(operand, index) { + this.setOperand(operand, index); + }, this); + }, + getRenderBox: function(refer) { + var rectBox = this.callBase(refer); + if (this.getOperands().length === 0) { + rectBox.height = FONT_CONF.spaceHeight; + } + return rectBox; + }, + getBaseline: function(refer) { + var maxBaseline = 0, operands = this.getOperands(); + if (operands.length === 0) { + return this.callBase(refer); + } + kity.Utils.each(operands, function(operand) { + maxBaseline = Math.max(operand.getBaseline(refer), maxBaseline); + }); + return maxBaseline; + }, + getMeanline: function(refer) { + var minMeanline = 1e7, operands = this.getOperands(); + if (operands.length === 0) { + return this.callBase(refer); + } + kity.Utils.each(operands, function(operand) { + minMeanline = Math.min(operand.getMeanline(refer), minMeanline); + }); + return minMeanline; + } + }); + } +}; + +/** + * 分数表达式 + */ +_p[13] = { + value: function(require) { + var kity = _p.r(34), FractionOperator = _p.r(38); + return kity.createClass("FractionExpression", { + base: _p.r(10), + constructor: function(upOperand, downOperand) { + this.callBase(upOperand, downOperand); + this.setFlag("Fraction"); + this.setOperator(new FractionOperator()); + }, + /*------- 重写分数结构的baseline和mealine计算方式 */ + getBaseline: function(refer) { + var downOperand = this.getOperand(1), rectBox = downOperand.getRenderBox(refer); + return rectBox.y + downOperand.getBaselineProportion() * rectBox.height; + }, + getMeanline: function(refer) { + var upOperand = this.getOperand(0), rectBox = upOperand.getRenderBox(refer); + return upOperand.getMeanlineProportion() * rectBox.height; + } + }); + } +}; + +/** + * 函数表达式 + */ +_p[14] = { + value: function(require) { + var kity = _p.r(34), FUNC_CONF = _p.r(47).func, FunctionOperator = _p.r(39); + return kity.createClass("FunctionExpression", { + base: _p.r(19), + /** + * function表达式构造函数 + * @param funcName function名称 + * @param expr 函数表达式 + * @param sup 上标 + * @param sub 下标 + */ + constructor: function(funcName, expr, sup, sub) { + this.callBase(); + this.setFlag("Func"); + this.funcName = funcName; + this.setOperator(new FunctionOperator(funcName)); + this.setExpr(expr); + this.setSuperscript(sup); + this.setSubscript(sub); + }, + // 当前函数应用的script位置是否是在侧面 + isSideScript: function() { + return !FUNC_CONF["ud-script"][this.funcName]; + }, + setExpr: function(expr) { + return this.setOperand(expr, 0); + }, + setSuperscript: function(sub) { + return this.setOperand(sub, 1); + }, + setSubscript: function(sub) { + return this.setOperand(sub, 2); + } + }); + } +}; + +/** + * 积分表达式 + */ +_p[15] = { + value: function(require) { + var kity = _p.r(34), IntegrationOperator = _p.r(40), IntegrationExpression = kity.createClass("IntegrationExpression", { + base: _p.r(19), + /** + * 构造积分表达式 + * @param integrand 被积函数 + * @param supOperand 上限 + * @param subOperand 下限 + */ + constructor: function(integrand, superscript, subscript) { + this.callBase(); + this.setFlag("Integration"); + this.setOperator(new IntegrationOperator()); + this.setIntegrand(integrand); + this.setSuperscript(superscript); + this.setSubscript(subscript); + }, + setType: function(type) { + this.getOperator().setType(type); + return this; + }, + resetType: function() { + this.getOperator().resetType(); + return this; + }, + setIntegrand: function(integrand) { + this.setOperand(integrand, 0); + }, + setSuperscript: function(sup) { + this.setOperand(sup, 1); + }, + setSubscript: function(sub) { + this.setOperand(sub, 2); + } + }); + return IntegrationExpression; + } +}; + +/** + * 方根表达式 + */ +_p[16] = { + value: function(require) { + var kity = _p.r(34), RadicalOperator = _p.r(42); + return kity.createClass("RadicalExpression", { + base: _p.r(10), + /** + * 构造开方表达式 + * @param radicand 被开方数 + * @param exponent 指数 + */ + constructor: function(radicand, exponent) { + this.callBase(radicand, exponent); + this.setFlag("Radicand"); + this.setOperator(new RadicalOperator()); + }, + setRadicand: function(operand) { + return this.setFirstOperand(operand); + }, + getRadicand: function() { + return this.getFirstOperand(); + }, + setExponent: function(operand) { + return this.setLastOperand(operand); + }, + getExponent: function() { + return this.getLastOperand(); + } + }); + } +}; + +/** + * 上标表达式 + */ +_p[17] = { + value: function(require) { + var kity = _p.r(34), ScriptOperator = _p.r(43); + return kity.createClass("ScriptExpression", { + base: _p.r(19), + constructor: function(operand, superscript, subscript) { + this.callBase(); + this.setFlag("Script"); + this.setOperator(new ScriptOperator()); + this.setOpd(operand); + this.setSuperscript(superscript); + this.setSubscript(subscript); + }, + setOpd: function(operand) { + this.setOperand(operand, 0); + }, + setSuperscript: function(sup) { + this.setOperand(sup, 1); + }, + setSubscript: function(sub) { + this.setOperand(sub, 2); + } + }); + } +}; + +/** + * 求和表达式 + */ +_p[18] = { + value: function(require) { + var kity = _p.r(34), SummationOperator = _p.r(44); + return kity.createClass("SummationExpression", { + base: _p.r(19), + /** + * 构造求和表达式 + * @param expr 求和表达式 + * @param upOperand 上标 + * @param downOperand 下标 + */ + constructor: function(expr, superscript, subscript) { + this.callBase(); + this.setFlag("Summation"); + this.setOperator(new SummationOperator()); + this.setExpr(expr); + this.setSuperscript(superscript); + this.setSubscript(subscript); + }, + setExpr: function(expr) { + this.setOperand(expr, 0); + }, + setSuperscript: function(sup) { + this.setOperand(sup, 1); + }, + setSubscript: function(sub) { + this.setOperand(sub, 2); + } + }); + } +}; + +/** + * 复合表达式 + * @abstract + */ +_p[19] = { + value: function(require) { + var kity = _p.r(34), GTYPE = _p.r(6), Expression = _p.r(21); + return kity.createClass("CompoundExpression", { + base: _p.r(21), + constructor: function() { + this.callBase(); + this.type = GTYPE.COMPOUND_EXP; + this.operands = []; + this.operator = null; + this.operatorBox = new kity.Group(); + this.operatorBox.setAttr("data-type", "kf-editor-exp-op-box"); + this.operandBox = new kity.Group(); + this.operandBox.setAttr("data-type", "kf-editor-exp-operand-box"); + this.setChildren(0, this.operatorBox); + this.setChildren(1, this.operandBox); + }, + // 操作符存储在第1位置 + setOperator: function(operator) { + if (operator === undefined) { + return this; + } + if (this.operator) { + this.operator.remove(); + } + this.operatorBox.addShape(operator); + this.operator = operator; + this.operator.setParentExpression(this); + // 表达式关联到操作符 + operator.expression = this; + return this; + }, + getOperator: function() { + return this.operator; + }, + // 操作数存储位置是从1开始 + setOperand: function(operand, index, isWrap) { + // 不包装操作数 + if (isWrap === false) { + this.operands[index] = operand; + return this; + } + operand = Expression.wrap(operand); + if (this.operands[index]) { + this.operands[index].remove(); + } + this.operands[index] = operand; + this.operandBox.addShape(operand); + return this; + }, + getOperand: function(index) { + return this.operands[index]; + }, + getOperands: function() { + return this.operands; + }, + addedCall: function() { + this.operator.applyOperand.apply(this.operator, this.operands); + return this; + } + }); + } +}; + +/** + * 空表达式 + * 该表达式主要用途是用于站位 + */ +_p[20] = { + value: function(require) { + var kity = _p.r(34), FONT_CONF = _p.r(47).font, Expression = _p.r(21), EmptyExpression = kity.createClass("EmptyExpression", { + base: Expression, + constructor: function() { + this.callBase(); + this.setFlag("Empty"); + }, + getRenderBox: function() { + return { + width: 0, + height: FONT_CONF.spaceHeight, + x: 0, + y: 0 + }; + } + }); + EmptyExpression.isEmpty = function(target) { + return target instanceof EmptyExpression; + }; + // 注册打包函数 + Expression.registerWrap("empty", function(operand) { + if (operand === null || operand === undefined) { + return new EmptyExpression(); + } + }); + return EmptyExpression; + } +}; + +/** + * 基础表达式, 该类是表达式和操作数的高层抽象 + * @abstract + */ +_p[21] = { + value: function(require) { + var kity = _p.r(34), GTYPE = _p.r(6), FONT_CONF = _p.r(47).font, // 打包函数列表 + WRAP_FN = [], // 注册的打包函数的名称与其在注册器列表中的索引之间的对应关系 + WRAP_FN_INDEX = {}, Expression = kity.createClass("Expression", { + base: _p.r(46), + constructor: function() { + this.callBase(); + this.type = GTYPE.EXP; + // 表达式的上下偏移 + this._offset = { + top: 0, + bottom: 0 + }; + this.children = []; + this.box.fill("transparent").setAttr("data-type", "kf-editor-exp-box"); + this.box.setAttr("data-type", "kf-editor-exp-bg-box"); + this.expContent = new kity.Group(); + this.expContent.setAttr("data-type", "kf-editor-exp-content-box"); + this.addShape(this.expContent); + }, + getChildren: function() { + return this.children; + }, + getChild: function(index) { + return this.children[index] || null; + }, + getTopOffset: function() { + return this._offset.top; + }, + getBottomOffset: function() { + return this._offset.bottom; + }, + getOffset: function() { + return this._offset; + }, + setTopOffset: function(val) { + this._offset.top = val; + }, + setBottomOffset: function(val) { + this._offset.bottom = val; + }, + setOffset: function(top, bottom) { + this._offset.top = top; + this._offset.bottom = bottom; + }, + setFlag: function(flag) { + this.setAttr("data-flag", flag || "Expression"); + }, + setChildren: function(index, exp) { + // 首先清理掉之前的表达式 + if (this.children[index]) { + this.children[index].remove(); + } + this.children[index] = exp; + this.expContent.addShape(exp); + }, + getBaselineProportion: function() { + return FONT_CONF.baselinePosition; + }, + getMeanlineProportion: function() { + return FONT_CONF.meanlinePosition; + }, + getBaseline: function(refer) { + // 上偏移3px + return this.getRenderBox(refer).height * FONT_CONF.baselinePosition - 3; + }, + getMeanline: function(refer) { + // 上偏移1px + return this.getRenderBox(refer).height * FONT_CONF.meanlinePosition - 1; + }, + getAscenderline: function() { + return this.getFixRenderBox().height * FONT_CONF.ascenderPosition; + }, + getDescenderline: function() { + return this.getFixRenderBox().height * FONT_CONF.descenderPosition; + }, + translateElement: function(x, y) { + this.expContent.translate(x, y); + }, + expand: function(width, height) { + var renderBox = this.getFixRenderBox(); + this.setBoxSize(renderBox.width + width, renderBox.height + height); + }, + getBaseWidth: function() { + return this.getWidth(); + }, + getBaseHeight: function() { + return this.getHeight(); + }, + updateBoxSize: function() { + var renderBox = this.expContent.getFixRenderBox(); + this.setBoxSize(renderBox.width, renderBox.height); + }, + getBox: function() { + return this.box; + } + }); + // 表达式自动打包 + kity.Utils.extend(Expression, { + registerWrap: function(name, fn) { + WRAP_FN_INDEX[name] = WRAP_FN.length; + WRAP_FN.push(fn); + }, + revokeWrap: function(name) { + var fn = null; + if (name in WRAP_FN_INDEX) { + fn = WRAP_FN[WRAP_FN_INDEX[name]]; + WRAP_FN[WRAP_FN_INDEX[name]] = null; + delete WRAP_FN_INDEX[name]; + } + return fn; + }, + // 打包函数 + wrap: function(operand) { + var result; + kity.Utils.each(WRAP_FN, function(fn) { + if (!fn) { + return; + } + result = fn(operand); + if (result) { + return false; + } + }); + return result; + } + }); + return Expression; + } +}; + +/** + * Text表达式 + */ +_p[22] = { + value: function(require) { + var Text = _p.r(5), kity = _p.r(34), FONT_CONF = _p.r(3), Expression = _p.r(21), TextExpression = kity.createClass("TextExpression", { + base: _p.r(21), + constructor: function(content, fontFamily) { + this.callBase(); + this.fontFamily = fontFamily || FONT_CONF.defaultFont; + this.setFlag("Text"); + this.content = content + ""; + this.textContent = new Text(this.content, this.fontFamily); + this.setChildren(0, this.textContent); + this.setChildren(1, new kity.Rect(0, 0, 0, 0).fill("transparent")); + }, + setFamily: function(fontFamily) { + this.textContent.setFamily(fontFamily); + }, + setFontSize: function(fontSize) { + this.textContent.setFontSize(fontSize); + }, + addedCall: function() { + var box = this.textContent.getFixRenderBox(); + this.getChild(1).setSize(box.width, box.height); + this.updateBoxSize(); + return this; + } + }); + // 注册文本表达式的打包函数 + Expression.registerWrap("text", function(operand) { + var operandType = typeof operand; + if (operandType === "number" || operandType === "string") { + operand = new TextExpression(operand); + } + return operand; + }); + return TextExpression; + } +}; + +/*! + * 字体信息检测模板,用于检测浏览器的字体信息 + */ +_p[23] = { + value: function() { + return [ '', 'x', "" ]; + } +}; + +/*! + * 字体安装器 + */ +_p[24] = { + value: function(require) { + var kity = _p.r(34), FontManager = _p.r(25), $ = _p.r(33), FONT_CONF = _p.r(47).font, CHAR_LIST = _p.r(2), NODE_LIST = []; + return kity.createClass("FontInstaller", { + constructor: function(doc, resource) { + this.callBase(); + this.resource = resource || "../src/resource/"; + this.doc = doc; + }, + // 挂载字体 + mount: function(callback) { + var fontList = FontManager.getFontList(), count = 0, _self = this; + kity.Utils.each(fontList, function(fontInfo) { + count++; + fontInfo.meta.src = _self.resource + fontInfo.meta.src; + _self.createFontStyle(fontInfo); + preload(_self.doc, fontInfo, function() { + count--; + if (count === 0) { + complete(_self.doc, callback); + } + }); + }); + }, + createFontStyle: function(fontInfo) { + var stylesheet = this.doc.createElement("style"), tpl = '@font-face{\nfont-family: "${fontFamily}";\nsrc: url("${src}");\n}'; + stylesheet.setAttribute("type", "text/css"); + stylesheet.innerHTML = tpl.replace("${fontFamily}", fontInfo.meta.fontFamily).replace("${src}", fontInfo.meta.src); + this.doc.head.appendChild(stylesheet); + } + }); + function preload(doc, fontInfo, callback) { + $.get(fontInfo.meta.src, function(data, state) { + if (state === "success") { + applyFonts(doc, fontInfo); + } + callback(); + }); + } + function complete(doc, callback) { + window.setTimeout(function() { + initFontSystemInfo(doc); + removeTmpNode(); + callback(); + }, 100); + } + function applyFonts(doc, fontInfo) { + var node = document.createElement("div"), fontFamily = fontInfo.meta.fontFamily; + node.style.cssText = "position: absolute; top: -10000px; left: -100000px;"; + node.style.fontFamily = fontFamily; + node.innerHTML = CHAR_LIST.join(""); + doc.body.appendChild(node); + NODE_LIST.push(node); + } + /** + * 计算字体系统信息 + */ + function initFontSystemInfo(doc) { + var tmpNode = doc.createElement("div"); + tmpNode.style.cssText = "position: absolute; top: 0; left: -100000px;"; + tmpNode.innerHTML = _p.r(23).join(""); + doc.body.appendChild(tmpNode); + var rectBox = tmpNode.getElementsByTagName("text")[0].getBBox(); + // text实际占用空间 + FONT_CONF.spaceHeight = rectBox.height; + // text顶部空间 + FONT_CONF.topSpace = -rectBox.y - FONT_CONF.baseline; + FONT_CONF.bottomSpace = FONT_CONF.spaceHeight - FONT_CONF.topSpace - FONT_CONF.baseHeight; + // text偏移值 + FONT_CONF.offset = FONT_CONF.baseline + FONT_CONF.topSpace; + // baseline比例 + FONT_CONF.baselinePosition = (FONT_CONF.topSpace + FONT_CONF.baseline) / FONT_CONF.spaceHeight; + // meanline比例 + FONT_CONF.meanlinePosition = (FONT_CONF.topSpace + FONT_CONF.meanline) / FONT_CONF.spaceHeight; + // 上下延伸性比例 + FONT_CONF.ascenderPosition = FONT_CONF.topSpace / FONT_CONF.spaceHeight; + FONT_CONF.descenderPosition = (FONT_CONF.topSpace + FONT_CONF.baseHeight) / FONT_CONF.spaceHeight; + doc.body.removeChild(tmpNode); + } + function removeTmpNode() { + kity.Utils.each(NODE_LIST, function(node) { + node.parentNode.removeChild(node); + }); + NODE_LIST = []; + } + } +}; + +/*! + * 字体管理器 + */ +_p[25] = { + value: function(require) { + var FONT_LIST = {}, kity = _p.r(34), CONF = _p.r(47).font.list; + // init + (function() { + kity.Utils.each(CONF, function(fontData) { + FONT_LIST[fontData.meta.fontFamily] = fontData; + }); + })(); + return { + getFontList: function() { + return FONT_LIST; + }, + getCharacterValue: function(key, fontFamily) { + if (!FONT_LIST[fontFamily]) { + return null; + } + return FONT_LIST[fontFamily].map[key] || null; + } + }; + } +}; + +/*! + * 双线字体 + */ +_p[26] = { + value: function() { + return { + meta: { + fontFamily: "KF AMS BB", + src: "KF_AMS_BB.woff" + } + }; + } +}; + +/*! + * 手写体 + */ +_p[27] = { + value: function() { + return { + meta: { + fontFamily: "KF AMS CAL", + src: "KF_AMS_CAL.woff" + } + }; + } +}; + +/*! + * 花体 + */ +_p[28] = { + value: function() { + return { + meta: { + fontFamily: "KF AMS FRAK", + src: "KF_AMS_FRAK.woff" + } + }; + } +}; + +/*! + * 字体主文件 + */ +_p[29] = { + value: function() { + return { + meta: { + fontFamily: "KF AMS MAIN", + src: "KF_AMS_MAIN.woff" + }, + map: { + // char + Alpha: "Α", + Beta: "Β", + Gamma: "Γ", + Delta: "Δ", + Epsilon: "Ε", + Zeta: "Ζ", + Eta: "Η", + Theta: "Θ", + Iota: "Ι", + Kappa: "Κ", + Lambda: "Λ", + Mu: "Μ", + Nu: "Ν", + Xi: "Ξ", + Omicron: "Ο", + Pi: "Π", + Rho: "Ρ", + Sigma: "Σ", + Tau: "Τ", + Upsilon: "Υ", + Phi: "Φ", + Chi: "Χ", + Psi: "Ψ", + Omega: "Ω", + alpha: "α", + beta: "β", + gamma: "γ", + delta: "δ", + epsilon: "ε", + zeta: "ζ", + eta: "η", + theta: "θ", + iota: "ι", + kappa: "κ", + lambda: "λ", + mu: "μ", + nu: "ν", + xi: "ξ", + omicron: "ο", + pi: "π", + rho: "ρ", + sigma: "σ", + tau: "τ", + upsilon: "υ", + phi: "φ", + varkappa: "ϰ", + chi: "χ", + psi: "ψ", + omega: "ω", + digamma: "Ϝ", + varepsilon: "ϵ", + varrho: "ϱ", + varphi: "ϕ", + vartheta: "ϑ", + varpi: "ϖ", + varsigma: "Ϲ", + aleph: "ℵ", + beth: "ℶ", + daleth: "ℸ", + gimel: "ℷ", + eth: "ð", + hbar: "ℎ", + hslash: "ℏ", + mho: "℧", + partial: "∂", + wp: "℘", + Game: "⅁", + Bbbk: "⅌", + Finv: "Ⅎ", + Im: "ℑ", + Re: "ℜ", + complement: "∁", + ell: "ℓ", + circledS: "Ⓢ", + imath: "ı", + jmath: "ȷ", + // symbol + doublecap: "⋒", + Cap: "⋒", + doublecup: "⋓", + Cup: "⋓", + ast: "*", + divideontimes: "⋇", + rightthreetimes: "⋌", + leftthreetimes: "⋋", + cdot: "·", + odot: "⊙", + dotplus: "∔", + rtimes: "⋊", + ltimes: "⋉", + centerdot: "▪", + doublebarwedge: "⌭", + setminus: "⒁", + amalg: "∐", + circ: "◦", + bigcirc: "◯", + gtrdot: "⋗", + lessdot: "⋖", + smallsetminus: "⒅", + circledast: "⊛", + circledcirc: "⊚", + sqcap: "⊓", + sqcup: "⊔", + barwedge: "⊼", + circleddash: "⊝", + star: "⋆", + bigtriangledown: "▽", + bigtriangleup: "△", + cup: "∪", + cap: "∩", + times: "×", + mp: "∓", + pm: "±", + triangleleft: "⊲", + triangleright: "⊳", + boxdot: "⊡", + curlyvee: "⋏", + curlywedge: "⋎", + boxminus: "⊟", + boxtimes: "⊠", + ominus: "⊖", + oplus: "⊕", + oslash: "⊘", + otimes: "⊗", + uplus: "⊎", + boxplus: "⊞", + dagger: "†", + ddagger: "‡", + vee: "∨", + lor: "∨", + veebar: "⊻", + bullet: "•", + diamond: "⋄", + wedge: "∧", + land: "∧", + div: "÷", + wr: "≀", + geqq: "≧", + lll: "⋘", + llless: "⋘", + ggg: "⋙", + gggtr: "⋙", + preccurlyeq: "≼", + geqslant: "⩾", + lnapprox: "⪉", + preceq: "⪯", + gg: "≫", + lneq: "⪇", + precnapprox: "⪹", + approx: "≈", + lneqq: "≨", + precneqq: "⪵", + approxeq: "≊", + gnapprox: "⪊", + lnsim: "⋦", + precnsim: "⋨", + asymp: "≍", + gneq: "⪈", + lvertneqq: "⌮", + precsim: "≾", + backsim: "∽", + gneqq: "≩", + ncong: "≇", + risingdotseq: "≓", + backsimeq: "⋍", + gnsim: "⋧", + sim: "∼", + simeq: "≃", + bumpeq: "≏", + gtrapprox: "⪆", + ngeq: "≱", + Bumpeq: "≎", + gtreqless: "⋛", + ngeqq: "⌱", + succ: "≻", + circeq: "≗", + gtreqqless: "⪌", + ngeqslant: "⌳", + succapprox: "⪸", + cong: "≅", + gtrless: "≷", + ngtr: "≯", + succcurlyeq: "≽", + curlyeqprec: "⋞", + gtrsim: "≳", + nleq: "≰", + succeq: "⪰", + curlyeqsucc: "⋟", + gvertneqq: "⌯", + neq: "≠", + ne: "≠", + nequiv: "≢", + nleqq: "⌰", + succnapprox: "⪺", + doteq: "≐", + leq: "≤", + le: "≤", + nleqslant: "⌲", + succneqq: "⪶", + doteqdot: "≑", + Doteq: "≑", + leqq: "≦", + nless: "≮", + succnsim: "⋩", + leqslant: "⩽", + nprec: "⊀", + succsim: "≿", + eqsim: "≂", + lessapprox: "⪅", + npreceq: "⋠", + eqslantgtr: "⪖", + lesseqgtr: "⋚", + nsim: "≁", + eqslantless: "⪕", + lesseqqgtr: "⪋", + nsucc: "⊁", + triangleq: "≜", + eqcirc: "≖", + equiv: "≡", + lessgtr: "≶", + nsucceq: "⋡", + fallingdotseq: "≒", + lesssim: "≲", + prec: "≺", + geq: "≥", + ge: "≥", + ll: "≪", + precapprox: "⪷", + // arrows + uparrow: "↑", + downarrow: "↓", + updownarrow: "↕", + Uparrow: "⇑", + Downarrow: "⇓", + Updownarrow: "⇕", + circlearrowleft: "↺", + circlearrowright: "↻", + curvearrowleft: "↶", + curvearrowright: "↷", + downdownarrows: "⇊", + downharpoonleft: "⇃", + downharpoonright: "⇂", + leftarrow: "←", + gets: "←", + Leftarrow: "⇐", + leftarrowtail: "↢", + leftharpoondown: "↽", + leftharpoonup: "↼", + leftleftarrows: "⇇", + leftrightarrow: "↔", + Leftrightarrow: "⇔", + leftrightarrows: "⇄", + leftrightharpoons: "⇋", + leftrightsquigarrow: "↭", + Lleftarrow: "⇚", + looparrowleft: "↫", + looparrowright: "↬", + multimap: "⊸", + nLeftarrow: "⇍", + nRightarrow: "⇏", + nLeftrightarrow: "⇎", + nearrow: "↗", + nleftarrow: "↚", + nleftrightarrow: "↮", + nrightarrow: "↛", + nwarrow: "↖", + rightarrow: "→", + to: "→", + Rightarrow: "⇒", + rightarrowtail: "↣", + rightharpoondown: "⇁", + rightharpoonup: "⇀", + rightleftarrows: "⇆", + rightleftharpoons: "⇌", + rightrightarrows: "⇉", + rightsquigarrow: "⇝", + Rrightarrow: "⇛", + searrow: "↘", + swarrow: "↙", + twoheadleftarrow: "↞", + twoheadrightarrow: "↠", + upharpoonleft: "↿", + upharpoonright: "↾", + restriction: "↾", + upuparrows: "⇈", + Lsh: "↰", + Rsh: "↱", + longleftarrow: "⟵", + longrightarrow: "⟶", + Longleftarrow: "⟸", + Longrightarrow: "⟹", + implies: "⟹", + longleftrightarrow: "⟷", + Longleftrightarrow: "⟺", + // relation + backepsilon: "∍", + because: "∵", + therefore: "∴", + between: "≬", + blacktriangleleft: "◀", + blacktriangleright: "▸", + dashv: "⊣", + bowtie: "⋈", + frown: "⌢", + "in": "∈", + notin: "∉", + mid: "∣", + parallel: "∥", + models: "⊨", + ni: "∋", + owns: "∋", + nmid: "∤", + nparallel: "∦", + nshortmid: "⏒", + nshortparallel: "⏓", + nsubseteq: "⊈", + nsubseteqq: "⫇", + nsupseteq: "⊉", + nsupseteqq: "⫈", + ntriangleleft: "⋪", + ntrianglelefteq: "⋬", + ntriangleright: "⋫", + ntrianglerighteq: "⋭", + nvdash: "⊬", + nVdash: "⊮", + nvDash: "⊭", + nVDash: "⊯", + perp: "⊥", + pitchfork: "⋔", + propto: "∝", + shortmid: "⏐", + shortparallel: "⏑", + smile: "⌣", + sqsubset: "⊏", + sqsubseteq: "⊑", + sqsupset: "⊐", + sqsupseteq: "⊒", + subset: "⊂", + Subset: "⋐", + subseteq: "⊆", + subseteqq: "⫅", + subsetneq: "⊊", + subsetneqq: "⫋", + supset: "⊃", + Supset: "⋑", + supseteq: "⊇", + supseteqq: "⫆", + supsetneq: "⊋", + supsetneqq: "⫌", + trianglelefteq: "⊴", + trianglerighteq: "⊵", + varpropto: "⫉", + varsubsetneq: "⏔", + varsubsetneqq: "⏖", + varsupsetneq: "⏕", + varsupsetneqq: "⏗", + vdash: "⊢", + Vdash: "⊩", + vDash: "⊨", + Vvdash: "⊪", + vert: "|", + Vert: "ǁ", + "|": "ǁ", + "{": "{", + "}": "}", + backslash: "\\", + langle: "〈", + rangle: "〉", + lceil: "⌈", + rceil: "⌉", + lbrace: "{", + rbrace: "}", + lfloor: "⌊", + rfloor: "⌋", + cdots: "⋯", + ddots: "⋰", + vdots: "⋮", + dots: "…", + ldots: "…", + "#": "#", + bot: "⊥", + angle: "∠", + backprime: "‵", + bigstar: "★", + blacklozenge: "◆", + blacksquare: "■", + blacktriangle: "▲", + blacktriangledown: "▼", + clubsuit: "♣", + diagdown: "⒁", + diagup: "⒂", + diamondsuit: "♢", + emptyset: "ø", + exists: "∃", + flat: "♭", + forall: "∀", + heartsuit: "♡", + infty: "∞", + lozenge: "◇", + measuredangle: "∡", + nabla: "∇", + natural: "♮", + neg: "¬", + lnot: "¬", + nexists: "∄", + prime: "′", + sharp: "♯", + spadesuit: "♠", + sphericalangle: "∢", + surd: "√", + top: "⊤", + varnothing: "∅", + triangle: "△", + triangledown: "▽" + } + }; + } +}; + +/*! + * 罗马字体 + */ +_p[30] = { + value: function() { + return { + meta: { + fontFamily: "KF AMS ROMAN", + src: "KF_AMS_ROMAN.woff" + } + }; + } +}; + +/** + * 公式对象,表达式容器 + */ +_p[31] = { + value: function(require) { + var kity = _p.r(34), GTYPE = _p.r(6), FontManager = _p.r(25), FontInstaller = _p.r(24), DEFAULT_OPTIONS = { + fontsize: 50, + autoresize: true, + padding: [ 0 ] + }, Output = _p.r(1), EXPRESSION_INTERVAL = 10, ExpressionWrap = kity.createClass("ExpressionWrap", { + constructor: function(exp, config) { + this.wrap = new kity.Group(); + this.bg = new kity.Rect(0, 0, 0, 0).fill("transparent"); + this.exp = exp; + this.config = config; + this.wrap.setAttr("data-type", "kf-exp-wrap"); + this.bg.setAttr("data-type", "kf-exp-wrap-bg"); + this.wrap.addShape(this.bg); + this.wrap.addShape(this.exp); + }, + getWrapShape: function() { + return this.wrap; + }, + getExpression: function() { + return this.exp; + }, + getBackground: function() { + return this.bg; + }, + resize: function() { + var padding = this.config.padding, expBox = this.exp.getFixRenderBox(); + if (padding.length === 1) { + padding[1] = padding[0]; + } + this.bg.setSize(padding[1] * 2 + expBox.width, padding[0] * 2 + expBox.height); + this.exp.translate(padding[1], padding[0]); + } + }), Formula = kity.createClass("Formula", { + base: _p.r(32), + constructor: function(container, config) { + this.callBase(container); + this.expressions = []; + this.fontInstaller = new FontInstaller(this); + this.config = kity.Utils.extend({}, DEFAULT_OPTIONS, config); + this.initEnvironment(); + this.initInnerFont(); + }, + getContentContainer: function() { + return this.container; + }, + initEnvironment: function() { + this.zoom = this.config.fontsize / 50; + if ("width" in this.config) { + this.setWidth(this.config.width); + } + if ("height" in this.config) { + this.setHeight(this.config.height); + } + this.node.setAttribute("font-size", DEFAULT_OPTIONS.fontsize); + }, + initInnerFont: function() { + var fontList = FontManager.getFontList(), _self = this; + kity.Utils.each(fontList, function(fontInfo) { + createFontStyle(fontInfo); + }); + function createFontStyle(fontInfo) { + var stylesheet = _self.doc.createElement("style"), tpl = '@font-face{font-family: "${fontFamily}";font-style: normal;src: url("${src}") format("woff");}'; + stylesheet.setAttribute("type", "text/css"); + stylesheet.innerHTML = tpl.replace("${fontFamily}", fontInfo.meta.fontFamily).replace("${src}", fontInfo.meta.src); + _self.resourceNode.appendChild(stylesheet); + } + }, + insertExpression: function(expression, index) { + var expWrap = this.wrap(expression); + // clear zoom + this.container.clearTransform(); + this.expressions.splice(index, 0, expWrap.getWrapShape()); + this.addShape(expWrap.getWrapShape()); + notifyExpression.call(this, expWrap.getExpression()); + expWrap.resize(); + correctOffset.call(this); + this.resetZoom(); + this.config.autoresize && this.resize(); + }, + appendExpression: function(expression) { + this.insertExpression(expression, this.expressions.length); + }, + resize: function() { + var renderBox = this.container.getRenderBox("paper"); + this.node.setAttribute("width", renderBox.width); + this.node.setAttribute("height", renderBox.height); + }, + resetZoom: function() { + var zoomLevel = this.zoom / this.getBaseZoom(); + if (zoomLevel !== 0) { + this.container.scale(zoomLevel); + } + }, + wrap: function(exp) { + return new ExpressionWrap(exp, this.config); + }, + clear: function() { + this.callBase(); + this.expressions = []; + }, + clearExpressions: function() { + kity.Utils.each(this.expressions, function(exp) { + exp.remove(); + }); + this.expressions = []; + }, + toJPG: function(cb) { + new Output(this).toJPG(cb); + }, + toPNG: function(cb) { + new Output(this).toPNG(cb); + } + }); + kity.Utils.extend(Formula, { + registerFont: function(fontData) { + FontManager.registerFont(fontData); + } + }); + // 调整表达式之间的偏移 + function correctOffset() { + var exprOffset = 0; + kity.Utils.each(this.expressions, function(expr) { + var box = null; + if (!expr) { + return; + } + expr.setMatrix(new kity.Matrix(1, 0, 0, 1, 0, 0)); + box = expr.getFixRenderBox(); + expr.translate(0 - box.x, exprOffset); + exprOffset += box.height + EXPRESSION_INTERVAL; + }); + return this; + } + // 通知表达式已接入到paper + function notifyExpression(expression) { + var len = 0; + if (!expression) { + return; + } + if (expression.getType() === GTYPE.EXP) { + for (var i = 0, len = expression.getChildren().length; i < len; i++) { + notifyExpression(expression.getChild(i)); + } + } else if (expression.getType() === GTYPE.COMPOUND_EXP) { + // 操作数处理 + for (var i = 0, len = expression.getOperands().length; i < len; i++) { + notifyExpression(expression.getOperand(i)); + } + // 处理操作符 + notifyExpression(expression.getOperator()); + } + expression.addedCall && expression.addedCall(); + } + return Formula; + } +}; + +/** + * 公式专用paper + */ +_p[32] = { + value: function(require) { + var kity = _p.r(34); + return kity.createClass("FPaper", { + base: kity.Paper, + constructor: function(container) { + this.callBase(container); + this.doc = container.ownerDocument; + this.container = new kity.Group(); + this.container.setAttr("data-type", "kf-container"); + this.background = new kity.Group(); + this.background.setAttr("data-type", "kf-bg"); + this.baseZoom = 1; + this.zoom = 1; + this.base("addShape", this.background); + this.base("addShape", this.container); + }, + getZoom: function() { + return this.zoom; + }, + getBaseZoom: function() { + return this.baseZoom; + }, + addShape: function(shape, pos) { + return this.container.addShape(shape, pos); + }, + getBackground: function() { + return this.background; + }, + removeShape: function(pos) { + return this.container.removeShape(pos); + }, + clear: function() { + return this.container.clear(); + } + }); + } +}; + +/** + * jquery + */ +_p[33] = { + value: function() { + if (!window.jQuery) { + throw new Error("Missing jQuery"); + } + return window.jQuery; + } +}; + +/** + * kity库封包 + */ +_p[34] = { + value: function() { + if (!window.kity) { + throw new Error("Missing Kity Graphic Lib"); + } + return window.kity; + } +}; + +/** + * 小括号操作符:() + */ +_p[35] = { + value: function(require) { + var kity = _p.r(34), Text = _p.r(5); + return kity.createClass("BracketsOperator", { + base: _p.r(41), + constructor: function() { + this.callBase("Brackets"); + }, + applyOperand: function(exp) { + generate.call(this, exp); + } + }); + function generate(exp) { + var left = this.getParentExpression().getLeftSymbol(), right = this.getParentExpression().getRightSymbol(), fontSize = exp.getFixRenderBox().height, group = new kity.Group(), offset = 0, leftOp = new Text(left, "KF AMS MAIN").fill("black"), rightOp = new Text(right, "KF AMS MAIN").fill("black"); + leftOp.setFontSize(fontSize); + rightOp.setFontSize(fontSize); + this.addOperatorShape(group.addShape(leftOp).addShape(rightOp)); + offset += leftOp.getFixRenderBox().width; + exp.translate(offset, 0); + offset += exp.getFixRenderBox().width; + rightOp.translate(offset, 0); + } + } +}; + +/** + * 组合操作符 + * 操作多个表达式组合在一起 + */ +_p[36] = { + value: function(require) { + var kity = _p.r(34); + return kity.createClass("CombinationOperator", { + base: _p.r(41), + constructor: function() { + this.callBase("Combination"); + }, + applyOperand: function() { + // 偏移量 + var offsetX = 0, // 操作数 + operands = arguments, // 操作对象最大高度 + maxHeight = 0, // 垂直距离最大偏移 + maxOffsetTop = 0, maxOffsetBottom = 0, cached = [], // 偏移集合 + offsets = []; + kity.Utils.each(operands, function(operand) { + var box = operand.getFixRenderBox(), offsetY = operand.getOffset(); + box.height -= offsetY.top + offsetY.bottom; + cached.push(box); + offsets.push(offsetY); + maxOffsetTop = Math.max(offsetY.top, maxOffsetTop); + maxOffsetBottom = Math.max(offsetY.bottom, maxOffsetBottom); + maxHeight = Math.max(box.height, maxHeight); + }); + kity.Utils.each(operands, function(operand, index) { + var box = cached[index]; + operand.translate(offsetX - box.x, (maxHeight - (box.y + box.height)) / 2 + maxOffsetBottom - offsets[index].bottom); + offsetX += box.width; + }); + this.parentExpression.setOffset(maxOffsetTop, maxOffsetBottom); + this.parentExpression.updateBoxSize(); + } + }); + } +}; + +/*! + * 上下标控制器 + */ +_p[37] = { + value: function(require) { + var kity = _p.r(34), EmptyExpression = _p.r(20), defaultOptions = { + subOffset: 0, + supOffset: 0, + // 上下标的默认缩放值 + zoom: .66 + }; + return kity.createClass("ScriptController", { + constructor: function(opObj, target, sup, sub, options) { + this.observer = opObj.getParentExpression(); + this.target = target; + this.sup = sup; + this.sub = sub; + this.options = kity.Utils.extend({}, defaultOptions, options); + }, + // 上下标记 + applyUpDown: function() { + var target = this.target, sup = this.sup, sub = this.sub, options = this.options; + sup.scale(options.zoom); + sub.scale(options.zoom); + var targetBox = target.getFixRenderBox(); + if (EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) { + return { + width: targetBox.width, + height: targetBox.height, + top: 0, + bottom: 0 + }; + } else { + // 上标 + if (!EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) { + return this.applyUp(target, sup); + } else if (EmptyExpression.isEmpty(sup) && !EmptyExpression.isEmpty(sub)) { + return this.applyDown(target, sub); + } else { + return this.applyUpDownScript(target, sup, sub); + } + } + }, + /** + * 返回应用上下标后的空间占用情况,其中的key各自的意义是: + * top: 上空间偏移 + * bottom: 下空间偏移 + * width: 当前整个图形的实际占用空间的width + * height: 当前整个图形的实际占用空间的height + * @returns {*} + */ + applySide: function() { + var target = this.target, sup = this.sup, sub = this.sub; + if (EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) { + var targetRectBox = target.getRenderBox(this.observer); + return { + width: targetRectBox.width, + height: targetRectBox.height, + top: 0, + bottom: 0 + }; + } else { + // 下标处理 + if (EmptyExpression.isEmpty(sup) && !EmptyExpression.isEmpty(sub)) { + return this.applySideSub(target, sub); + } else if (!EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) { + return this.applySideSuper(target, sup); + } else { + return this.applySideScript(target, sup, sub); + } + } + }, + applySideSuper: function(target, sup) { + sup.scale(this.options.zoom); + var targetRectBox = target.getRenderBox(this.observer), supRectBox = sup.getRenderBox(this.observer), targetMeanline = target.getMeanline(this.observer), supBaseline = sup.getBaseline(this.observer), positionline = targetMeanline, diff = supBaseline - positionline, space = { + top: 0, + bottom: 0, + width: targetRectBox.width + supRectBox.width, + height: targetRectBox.height + }; + sup.translate(targetRectBox.width, 0); + if (this.options.supOffset) { + sup.translate(this.options.supOffset, 0); + } + if (diff > 0) { + target.translate(0, diff); + space.bottom = diff; + space.height += diff; + } else { + sup.translate(0, -diff); + } + return space; + }, + applySideSub: function(target, sub) { + sub.scale(this.options.zoom); + var targetRectBox = target.getRenderBox(this.observer), subRectBox = sub.getRenderBox(this.observer), subOffset = sub.getOffset(), targetBaseline = target.getBaseline(this.observer), // 下标定位线 + subPosition = (subRectBox.height + subOffset.top + subOffset.bottom) / 2, diff = targetRectBox.height - targetBaseline - subPosition, space = { + top: 0, + bottom: 0, + width: targetRectBox.width + subRectBox.width, + height: targetRectBox.height + }; + // 定位下标位置 + sub.translate(targetRectBox.width, subOffset.top + targetBaseline - subPosition); + if (this.options.subOffset) { + sub.translate(this.options.subOffset, 0); + } + if (diff < 0) { + space.top = -diff; + space.height -= diff; + } + return space; + }, + applySideScript: function(target, sup, sub) { + sup.scale(this.options.zoom); + sub.scale(this.options.zoom); + var targetRectBox = target.getRenderBox(this.observer), subRectBox = sub.getRenderBox(this.observer), supRectBox = sup.getRenderBox(this.observer), targetMeanline = target.getMeanline(this.observer), targetBaseline = target.getBaseline(this.observer), supBaseline = sup.getBaseline(this.observer), // 上下标都存在时, 下标的定位以上伸线为准 + subAscenderline = sub.getAscenderline(this.observer), supPosition = targetMeanline, subPosition = targetMeanline + (targetBaseline - targetMeanline) * 2 / 3, topDiff = supPosition - supBaseline, bottomDiff = targetRectBox.height - subPosition - (subRectBox.height - subAscenderline), space = { + top: 0, + bottom: 0, + width: targetRectBox.width + Math.max(subRectBox.width, supRectBox.width), + height: targetRectBox.height + }; + sup.translate(targetRectBox.width, topDiff); + sub.translate(targetRectBox.width, subPosition - subAscenderline); + if (this.options.supOffset) { + sup.translate(this.options.supOffset, 0); + } + if (this.options.subOffset) { + sub.translate(this.options.subOffset, 0); + } + // 定位纠正 + if (topDiff > 0) { + if (bottomDiff < 0) { + targetRectBox.height -= bottomDiff; + space.top = -bottomDiff; + } + } else { + target.translate(0, -topDiff); + sup.translate(0, -topDiff); + sub.translate(0, -topDiff); + space.height -= topDiff; + if (bottomDiff > 0) { + space.bottom = -topDiff; + } else { + space.height -= bottomDiff; + // 比较上下偏移, 获取正确的偏移值 + topDiff = -topDiff; + bottomDiff = -bottomDiff; + if (topDiff > bottomDiff) { + space.bottom = topDiff - bottomDiff; + } else { + space.top = bottomDiff - topDiff; + } + } + } + return space; + }, + applyUp: function(target, sup) { + var supBox = sup.getFixRenderBox(), targetBox = target.getFixRenderBox(), space = { + width: Math.max(targetBox.width, supBox.width), + height: supBox.height + targetBox.height, + top: 0, + bottom: supBox.height + }; + sup.translate((space.width - supBox.width) / 2, 0); + target.translate((space.width - targetBox.width) / 2, supBox.height); + return space; + }, + applyDown: function(target, sub) { + var subBox = sub.getFixRenderBox(), targetBox = target.getFixRenderBox(), space = { + width: Math.max(targetBox.width, subBox.width), + height: subBox.height + targetBox.height, + top: subBox.height, + bottom: 0 + }; + sub.translate((space.width - subBox.width) / 2, targetBox.height); + target.translate((space.width - targetBox.width) / 2, 0); + return space; + }, + applyUpDownScript: function(target, sup, sub) { + var supBox = sup.getFixRenderBox(), subBox = sub.getFixRenderBox(), targetBox = target.getFixRenderBox(), space = { + width: Math.max(targetBox.width, supBox.width, subBox.width), + height: supBox.height + subBox.height + targetBox.height, + top: 0, + bottom: 0 + }; + sup.translate((space.width - supBox.width) / 2, 0); + target.translate((space.width - targetBox.width) / 2, supBox.height); + sub.translate((space.width - subBox.width) / 2, supBox.height + targetBox.height); + return space; + } + }); + } +}; + +/** + * 分数操作符 + */ +_p[38] = { + value: function(require) { + var kity = _p.r(34), ZOOM = _p.r(47).zoom; + return kity.createClass("FractionOperator", { + base: _p.r(41), + constructor: function() { + this.callBase("Fraction"); + }, + applyOperand: function(upOperand, downOperand) { + upOperand.scale(ZOOM); + downOperand.scale(ZOOM); + var upWidth = Math.ceil(upOperand.getWidth()), downWidth = Math.ceil(downOperand.getWidth()), upHeight = Math.ceil(upOperand.getHeight()), downHeight = Math.ceil(downOperand.getHeight()), // 分数线overflow值 + overflow = 3, // 整体padding + padding = 1, maxWidth = Math.max(upWidth, downWidth), maxHeight = Math.max(upHeight, downHeight), operatorShape = generateOperator(maxWidth, overflow); + this.addOperatorShape(operatorShape); + upOperand.translate((maxWidth - upWidth) / 2 + overflow, 0); + operatorShape.translate(0, upHeight + 1); + // 下部不需要偏移 + downOperand.translate((maxWidth - downWidth) / 2 + overflow, upHeight + operatorShape.getHeight() + 1 * 2); + this.parentExpression.setOffset(maxHeight - upHeight, maxHeight - downHeight); + this.parentExpression.expand(padding * 2, padding * 2); + this.parentExpression.translateElement(padding, padding); + } + }); + function generateOperator(width, overflow) { + return new kity.Rect(width + overflow * 2, 1).fill("black"); + } + } +}; + +/** + * 函数操作符 + */ +_p[39] = { + value: function(require) { + var kity = _p.r(34), Text = _p.r(5), ScriptController = _p.r(37); + return kity.createClass("FunctionOperator", { + base: _p.r(41), + constructor: function(funcName) { + this.callBase("Function: " + funcName); + this.funcName = funcName; + }, + /* + * 积分操作符应用操作数 + * @param expr 函数表达式 + * @param sup 上限 + * @param sub 下限 + */ + applyOperand: function(expr, sup, sub) { + var opShape = generateOperator.call(this), expBox = expr.getFixRenderBox(), scriptHanlder = this.parentExpression.isSideScript() ? "applySide" : "applyUpDown", space = new ScriptController(this, opShape, sup, sub, { + zoom: .5 + })[scriptHanlder](), padding = 5, diff = (space.height + space.top + space.bottom - expBox.height) / 2; + // 应用偏移, 使图形在正确的位置上 + opShape.translate(0, space.top); + sup.translate(0, space.top); + sub.translate(0, space.top); + if (diff >= 0) { + expr.translate(space.width + padding, diff); + } else { + diff = -diff; + opShape.translate(0, diff); + sup.translate(0, diff); + sub.translate(0, diff); + expr.translate(space.width + padding, 0); + } + // 只扩展左边, 不扩展右边, 所以padding不 *2 + this.parentExpression.expand(padding, padding * 2); + this.parentExpression.translateElement(padding, padding); + } + }); + /* 返回操作符对象 */ + function generateOperator() { + var opShape = new Text(this.funcName, "KF AMS ROMAN"); + this.addOperatorShape(opShape); + // 为操作符图形创建baseline和meanline方法 + opShape.getBaseline = function() { + return opShape.getFixRenderBox().height; + }; + opShape.getMeanline = function() { + return 0; + }; + return opShape; + } + } +}; + +/** + * 积分操作符:∫ + */ +_p[40] = { + value: function(require) { + var kity = _p.r(34), ScriptController = _p.r(37); + return kity.createClass("IntegrationOperator", { + base: _p.r(41), + constructor: function(type) { + this.callBase("Integration"); + // 默认是普通单重积分 + this.opType = type || 1; + }, + setType: function(type) { + this.opType = type | 0; + }, + // 重置类型 + resetType: function() { + this.opType = 1; + }, + applyOperand: function(exp, sup, sub) { + var opShape = this.getOperatorShape(), padding = 3, expBox = exp.getFixRenderBox(), space = new ScriptController(this, opShape, sup, sub, { + supOffset: 3, + subOffset: -15 + }).applySide(), diff = (space.height + space.top - expBox.height) / 2; + opShape.translate(0, space.top); + sup.translate(0, space.top); + sub.translate(0, space.top); + if (diff >= 0) { + exp.translate(space.width + padding, diff); + } else { + diff = -diff; + opShape.translate(0, diff); + sup.translate(0, diff); + sub.translate(0, diff); + exp.translate(space.width + padding, 0); + } + this.parentExpression.expand(padding, padding * 2); + this.parentExpression.translateElement(padding, padding); + }, + getOperatorShape: function() { + var pathData = "M1.318,48.226c0,0,0.044,0.066,0.134,0.134c0.292,0.313,0.626,0.447,1.006,0.447c0.246,0.022,0.358-0.044,0.604-0.268 c0.782-0.782,1.497-2.838,2.324-6.727c0.514-2.369,0.938-4.693,1.586-8.448C8.559,24.068,9.9,17.878,11.978,9.52 c0.917-3.553,1.922-7.576,3.866-8.983C16.247,0.246,16.739,0,17.274,0c1.564,0,2.503,1.162,2.592,2.57 c0,0.827-0.424,1.386-1.273,1.386c-0.671,0-1.229-0.514-1.229-1.251c0-0.805,0.514-1.095,1.185-1.274 c0.022,0-0.291-0.29-0.425-0.379c-0.201-0.134-0.514-0.224-0.737-0.224c-0.067,0-0.112,0-0.157,0.022 c-0.469,0.134-0.983,0.939-1.453,2.234c-0.537,1.475-0.961,3.174-1.631,6.548c-0.424,2.101-0.693,3.464-1.229,6.727 c-1.608,9.185-2.949,15.487-5.006,23.756c-0.514,2.034-0.849,3.24-1.207,4.335c-0.559,1.698-1.162,2.95-1.811,3.799 c-0.514,0.715-1.385,1.408-2.436,1.408c-1.363,0-2.391-1.185-2.458-2.592c0-0.804,0.447-1.363,1.273-1.363 c0.671,0,1.229,0.514,1.229,1.251C2.503,47.757,1.989,48.047,1.318,48.226z", group = new kity.Group(), opGroup = new kity.Group(), opShape = new kity.Path(pathData).fill("black"), opBox = new kity.Rect(0, 0, 0, 0).fill("transparent"), tmpShape = null; + opGroup.addShape(opShape); + group.addShape(opBox); + group.addShape(opGroup); + this.addOperatorShape(group); + for (var i = 1; i < this.opType; i++) { + tmpShape = new kity.Use(opShape).translate(opShape.getWidth() / 2 * i, 0); + opGroup.addShape(tmpShape); + } + opGroup.scale(1.6); + tmpShape = null; + // 为操作符图形创建baseline和meanline方法 + group.getBaseline = function() { + return opGroup.getFixRenderBox().height; + }; + group.getMeanline = function() { + return 10; + }; + return group; + } + }); + } +}; + +/** + * 操作符抽象类 + * @abstract + */ +_p[41] = { + value: function(require) { + var kity = _p.r(34), GTYPE = _p.r(6); + return kity.createClass("Operator", { + base: _p.r(46), + constructor: function(operatorName) { + this.callBase(); + this.type = GTYPE.OP; + // 该操作符所属的表达式 + this.parentExpression = null; + // 操作符名称 + this.operatorName = operatorName; + // 操作符图形 + this.operatorShape = new kity.Group(); + this.addShape(this.operatorShape); + }, + applyOperand: function() { + throw new Error("applyOperand is abstract"); + }, + setParentExpression: function(exp) { + this.parentExpression = exp; + }, + getParentExpression: function() { + return this.parentExpression; + }, + clearParentExpression: function() { + this.parentExpression = null; + }, + // 提供给具体实现类附加其绘制的操作符图形的接口 + addOperatorShape: function(shpae) { + return this.operatorShape.addShape(shpae); + }, + getOperatorShape: function() { + return this.operatorShape; + } + }); + } +}; + +/** + * 开方操作符 + */ +_p[42] = { + value: function(require) { + var kity = _p.r(34), // 符号图形属性 + // 线条宽度 + SHAPE_DATA_WIDTH = 1, // 计算公式 + radians = 2 * Math.PI / 360, sin15 = Math.sin(15 * radians), cos15 = Math.cos(15 * radians), tan15 = Math.tan(15 * radians); + return kity.createClass("RadicalOperator", { + base: _p.r(41), + constructor: function() { + this.callBase("Radical"); + }, + applyOperand: function(radicand, exponent) { + generateOperator.call(this, radicand, exponent); + } + }); + // 根据给定的操作数生成操作符的pathData + // radicand 表示被开方数 + // exponent 表示指数 + function generateOperator(radicand, exponent) { + var decoration = generateDecoration(radicand), vLine = generateVLine(radicand), padding = 5, hLine = generateHLine(radicand); + this.addOperatorShape(decoration); + this.addOperatorShape(vLine); + this.addOperatorShape(hLine); + adjustmentPosition.call(this, mergeShape(decoration, vLine, hLine), this.operatorShape, radicand, exponent); + this.parentExpression.expand(0, padding * 2); + this.parentExpression.translateElement(0, padding); + } + // 生成根号中的左边装饰部分 + function generateDecoration(radicand) { + var shape = new kity.Path(), // 命名为a以便于精简表达式 + a = SHAPE_DATA_WIDTH, h = radicand.getHeight() / 3, drawer = shape.getDrawer(); + // 根号尾部左上角开始 + drawer.moveTo(0, cos15 * a * 6); + drawer.lineBy(sin15 * a, cos15 * a); + drawer.lineBy(cos15 * a * 3, -sin15 * a * 3); + drawer.lineBy(tan15 * h, h); + drawer.lineBy(sin15 * a * 3, -cos15 * a * 3); + drawer.lineBy(-sin15 * h, -h); + drawer.close(); + return shape.fill("black"); + } + // 根据操作数生成根号的竖直线部分 + function generateVLine(operand) { + var shape = new kity.Path(), // * 0.9 是为了在视觉上使斜线部分不至于太高 + h = operand.getHeight() * .9, drawer = shape.getDrawer(); + drawer.moveTo(tan15 * h, 0); + drawer.lineTo(0, h); + drawer.lineBy(sin15 * SHAPE_DATA_WIDTH * 3, cos15 * SHAPE_DATA_WIDTH * 3); + drawer.lineBy(tan15 * h + sin15 * SHAPE_DATA_WIDTH * 3, -(h + 3 * SHAPE_DATA_WIDTH * cos15)); + drawer.close(); + return shape.fill("black"); + } + // 根据操作数生成根号的水平线部分 + function generateHLine(operand) { + // 表达式宽度 + var w = operand.getWidth() + 2 * SHAPE_DATA_WIDTH; + return new kity.Rect(w, 2 * SHAPE_DATA_WIDTH).fill("black"); + } + // 合并根号的各个部分, 并返回根号的关键点位置数据 + function mergeShape(decoration, vLine, hLine) { + var decoBox = decoration.getFixRenderBox(), vLineBox = vLine.getFixRenderBox(); + vLine.translate(decoBox.width - sin15 * SHAPE_DATA_WIDTH * 3, 0); + decoration.translate(0, vLineBox.height - decoBox.height); + vLineBox = vLine.getFixRenderBox(); + hLine.translate(vLineBox.x + vLineBox.width - SHAPE_DATA_WIDTH / cos15, 0); + // 返回关键点数据 + return { + x: vLineBox.x + vLineBox.width - SHAPE_DATA_WIDTH / cos15, + y: 0 + }; + } + // 调整整个根号表达式的各个部分: 位置、操作符、被开方数、指数 + function adjustmentPosition(position, operator, radicand, exponent) { + var exponentBox = null, opOffset = { + x: 0, + y: 0 + }, opBox = operator.getFixRenderBox(); + exponent.scale(.66); + exponentBox = exponent.getFixRenderBox(); + if (exponentBox.width > 0 && exponentBox.height > 0) { + opOffset.y = exponentBox.height - opBox.height / 2; + // 指数不超出根号, 则移动指数 + if (opOffset.y < 0) { + exponent.translate(0, -opOffset.y); + opOffset.y = 0; + } + opOffset.x = exponentBox.width + opBox.height / 2 * tan15 - position.x; + } + operator.translate(opOffset.x, opOffset.y); + radicand.translate(opOffset.x + position.x + SHAPE_DATA_WIDTH, opOffset.y + 2 * SHAPE_DATA_WIDTH); + } + } +}; + +/** + * 上下标操作符 + */ +_p[43] = { + value: function(require) { + var kity = _p.r(34), ScriptController = _p.r(37); + return kity.createClass("ScriptOperator", { + base: _p.r(41), + constructor: function(operatorName) { + this.callBase(operatorName || "Script"); + }, + applyOperand: function(operand, sup, sub) { + var padding = 1, parent = this.parentExpression, space = new ScriptController(this, operand, sup, sub).applySide(); + this.getOperatorShape(); + space && parent.setOffset(space.top, space.bottom); + parent.expand(4, padding * 2); + parent.translateElement(2, padding); + } + }); + } +}; + +/** + * 求和操作符:∑ + */ +_p[44] = { + value: function(require) { + var kity = _p.r(34), ScriptController = _p.r(37); + return kity.createClass("SummationOperator", { + base: _p.r(41), + constructor: function() { + this.callBase("Summation"); + this.displayType = "equation"; + }, + applyOperand: function(expr, sup, sub) { + var opShape = this.getOperatorShape(), expBox = expr.getFixRenderBox(), padding = 0, space = new ScriptController(this, opShape, sup, sub).applyUpDown(), diff = (space.height - space.top - space.bottom - expBox.height) / 2; + if (diff >= 0) { + expr.translate(space.width + padding, diff + space.bottom); + } else { + diff = -diff; + opShape.translate(0, diff); + sup.translate(0, diff); + sub.translate(0, diff); + expr.translate(space.width + padding, space.bottom); + } + this.parentExpression.setOffset(space.top, space.bottom); + this.parentExpression.expand(padding, padding * 2); + this.parentExpression.translateElement(padding, padding); + }, + getOperatorShape: function() { + var pathData = "M0.672,33.603c-0.432,0-0.648,0-0.648-0.264c0-0.024,0-0.144,0.24-0.432l12.433-14.569L0,0.96c0-0.264,0-0.72,0.024-0.792 C0.096,0.024,0.12,0,0.672,0h28.371l2.904,6.745h-0.6C30.531,4.8,28.898,3.72,28.298,3.336c-1.896-1.2-3.984-1.608-5.28-1.8 c-0.216-0.048-2.4-0.384-5.617-0.384H4.248l11.185,15.289c0.168,0.24,0.168,0.312,0.168,0.36c0,0.12-0.048,0.192-0.216,0.384 L3.168,31.515h14.474c4.608,0,6.96-0.624,7.464-0.744c2.76-0.72,5.305-2.352,6.241-4.848h0.6l-2.904,7.681H0.672z", operatorShape = new kity.Path(pathData).fill("black"), opBgShape = new kity.Rect(0, 0, 0, 0).fill("transparent"), group = new kity.Group(), opRenderBox = null; + group.addShape(opBgShape); + group.addShape(operatorShape); + operatorShape.scale(1.6); + this.addOperatorShape(group); + opRenderBox = operatorShape.getFixRenderBox(); + if (this.displayType === "inline") { + operatorShape.translate(5, 15); + opBgShape.setSize(opRenderBox.width + 10, opRenderBox.height + 25); + } else { + operatorShape.translate(2, 5); + opBgShape.setSize(opRenderBox.width + 4, opRenderBox.height + 8); + } + return group; + } + }); + } +}; + +/*! + * 资源管理器 + * 负责管理资源的加载,并在资源ready之后提供Formula构造器 + */ +_p[45] = { + value: function(require) { + var kity = _p.r(34), cbList = [], RES_CONF = _p.r(47).resource, FontInstall = _p.r(24), Formula = _p.r(31), // 资源管理器就绪状态 + __readyState = false, // 资源管理器是否已启动 + inited = false; + return { + // 初始化 + ready: function(cb, options) { + if (!inited) { + inited = true; + init(options); + } + if (__readyState) { + window.setTimeout(function() { + cb(Formula); + }, 0); + } else { + cbList.push(cb); + } + } + }; + /** + * 资源初始化 + */ + function init(options) { + options = kity.Utils.extend({}, RES_CONF, options); + if (!/^(https?:)?\/\//.test(options.path)) { + options.path = getFullPath(options.path); + } + new FontInstall(document, options.path).mount(complete); + } + function complete() { + kity.Utils.each(cbList, function(cb) { + cb(Formula); + }); + } + function getFullPath(path) { + var pathname = location.pathname.split("/"), pathPart; + pathname.length -= 1; + pathname = pathname.join("/") + "/"; + pathPart = [ location.protocol, "//", location.host, pathname, path.replace(/^\//, "") ]; + return pathPart.join(""); + } + } +}; + +/*! + * 所有符号的基类 + * @abstract + */ +_p[46] = { + value: function(require) { + var kity = _p.r(34), GTYPE = _p.r(6); + return kity.createClass("SignGroup", { + base: kity.Group, + constructor: function() { + this.callBase(); + this.box = new kity.Rect(0, 0, 0, 0); + this.type = GTYPE.UNKNOWN; + this.addShape(this.box); + this.zoom = 1; + }, + setZoom: function(zoom) { + this.zoom = zoom; + }, + getZoom: function() { + return this.zoom; + }, + setBoxSize: function(w, h) { + return this.box.setSize(w, h); + }, + setBoxWidth: function(w) { + return this.box.setWidth(w); + }, + setBoxHeight: function(h) { + return this.box.setHeight(h); + }, + getType: function() { + return this.type; + }, + getBaseHeight: function() { + return this.getHeight(); + }, + getBaseWidth: function() { + return this.getWidth(); + }, + addedCall: function() {} + }); + } +}; + +/*! + * 系统项目配置文件. + */ +_p[47] = { + value: function(require) { + return { + zoom: .66, + font: { + meanline: Math.round(380 / 1e3 * 50), + baseline: Math.round(800 / 1e3 * 50), + baseHeight: 50, + // 系统字体列表 + list: [ _p.r(29), _p.r(27), _p.r(28), _p.r(26), _p.r(30) ] + }, + /*------------------------- 资源配置*/ + resource: { + path: "src/resource/" + }, + // 函数相关配置 + func: { + // 上下标在函数名上下两侧的函数列表 + "ud-script": { + lim: true + } + } + }; + } +}; + +/*! + * 启动代码 + */ +_p[48] = { + value: function(require) { + window.kf = { + // base + ResourceManager: _p.r(45), + Operator: _p.r(41), + // expression + Expression: _p.r(21), + CompoundExpression: _p.r(19), + TextExpression: _p.r(22), + EmptyExpression: _p.r(20), + CombinationExpression: _p.r(12), + FunctionExpression: _p.r(14), + FractionExpression: _p.r(13), + IntegrationExpression: _p.r(15), + RadicalExpression: _p.r(16), + ScriptExpression: _p.r(17), + SuperscriptExpression: _p.r(9), + SubscriptExpression: _p.r(8), + SummationExpression: _p.r(18), + // Brackets expressoin + BracketsExpression: _p.r(11) + }; + } +}; + +var moduleMapping = { + "kf.start": 48 +}; + +function use(name) { + _p.r([ moduleMapping[name] ]); +} +/** + * 模块暴露 + */ + +( function ( global ) { + + var oldGetRenderBox = kity.Shape.getRenderBox; + + kity.extendClass(kity.Shape, { + getFixRenderBox: function () { + return this.getRenderBox( this.container.container ); + }, + + getTranslate: function () { + return this.transform.translate; + } + }); + + // build环境中才含有use + try { + use( 'kf.start' ); + } catch ( e ) { + } + +} )( this ); +})(); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/js/kityformula-editor.all.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/js/kityformula-editor.all.min.js new file mode 100644 index 0000000000000000000000000000000000000000..332ca588656b6f81d45da1189e5e5194b57c7361 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/js/kityformula-editor.all.min.js @@ -0,0 +1,12 @@ +/*! + * ==================================================== + * Kity Formula Editor - v1.0.0 - 2014-09-03 + * https://github.com/kitygraph/formula + * GitHub: https://github.com/kitygraph/formula.git + * Copyright (c) 2014 Baidu Kity Group; Licensed MIT + * ==================================================== + */ +!function(){function a(a){b.r([c[a]])}var b={r:function(a){if(b[a].inited)return b[a].value;if("function"!=typeof b[a].value)return b[a].inited=!0,b[a].value;var c={exports:{}},d=b[a].value(null,c.exports,c);if(b[a].inited=!0,b[a].value=d,void 0!==d)return d;for(var e in c.exports)if(c.exports.hasOwnProperty(e))return b[a].inited=!0,b[a].value=c.exports,c.exports}};b[0]={value:function(){function a(d,e,f,g){return g=0|g,g>b?f:(g++,c.each(f,function(b,f){d?!b||"object"!=typeof b&&"function"!=typeof b?e[f]=b:(e[f]=e[f]||(c.isArray(b)?[]:{}),e[f]=a(d,e[f],b,g)):e[f]=b}),e)}var b=10,c={extend:function(b,d){var e=!1;if("boolean"==typeof b?(e=b,b=d,d=[].splice.call(arguments,2)):d=[].splice.call(arguments,1),!b)throw new Error("Utils: extend, target can not be empty");return c.each(d,function(c){(c&&"object"==typeof c||"function"==typeof c)&&a(e,b,c)}),b},contains:function(a,b){return a.contains?a.contains(b):a.compareDocumentPosition?!!(16&a.compareDocumentPosition(b)):void 0},getRect:function(a){return a.getBoundingClientRect()},isArray:function(a){return a&&"[object Array]"==={}.toString.call(a)},isString:function(a){return"string"==typeof a},proxy:function(a,b){return function(){return a.apply(b,arguments)}},each:function(a,b){if(a)if("length"in a&&"number"==typeof a.length)for(var c=0,d=a.length;d>c&&b.call(null,a[c],c,a)!==!1;c++);else for(var e in a)if(a.hasOwnProperty(e)&&b.call(null,a[e],e,a)===!1)break}};return c}},b[1]={value:function(){var a=b.r(20);return a.createClass("Component",{constructor:function(){}})}},b[2]={value:function(){function a(){return++d}var c={},d=0,e=!0,f=b.r(3),g=b.r(0),h=function(a){var b=a.type,d=a.target,f=this.__kfe_eid,h=/^(?:before|after)/.test(b),j=c[f][b];return h||(i.trigger(d,"before"+b),e!==!1)?(g.each(j,function(b){return b&&b.call(d,a)===!1?e=!1:void 0}),void(h||i.trigger(d,"after"+b))):(e=!0,!1)},i={addEvent:function(b,d,e){var f=!0,g=null;b.__kfe_eid||(f=!1,b.__kfe_eid=a(),c[b.__kfe_eid]={}),g=c[b.__kfe_eid],g[d]||(f=!1,g[d]=[]),g[d].push(e),f||b.addEventListener(d,h,!1)},trigger:function(a,b,c){c=c||f.createEvent(b,c),a.dispatchEvent(c)}};return i}},b[3]={value:function(){return{createEvent:function(a){var b=document.createEvent("Event");return b.initEvent(a,!0,!0),b}}}},b[4]={value:function(){var a={},c=b.r(0);return c.extend(a,c,b.r(2)),a}},b[5]={value:function(){var a=b.r(20),c=b.r(8),d=a.createClass("ControllerComponent",{constructor:function(a){this.kfEditor=a,this.components={},this.initComponents()},initComponents:function(){this.components.listener=new c(this,this.kfEditor)}});return d}},b[6]={value:function(){var a={32:"\\,","s+219":"\\{","s+221":"\\}",220:"\\backslash","s+51":"\\#","s+52":"\\$","s+53":"\\%","s+54":"\\^","s+55":"\\&","s+189":"\\_","s+192":"\\~"};return{getReplaceString:function(b){return a[b]||null}}}},b[7]={value:function(){var a=b.r(20),c=b.r(4),d=b.r(6),e={LEFT:37,RIGHT:39,DELETE:8,INPUT:229};return a.createClass("InputComponent",{constructor:function(a,b){this.parentComponent=a,this.kfEditor=b,this.inputBox=this.createInputBox(),this.initServices(),this.initCommands(),this.initEvent()},initServices:function(){this.kfEditor.registerService("control.update.input",this,{updateInput:this.updateInput}),this.kfEditor.registerService("control.insert.string",this,{insertStr:this.insertStr})},initCommands:function(){this.kfEditor.registerCommand("focus",this,this.focus)},createInputBox:function(){var a=this.kfEditor.getContainer(),b=this.kfEditor.getDocument().createElement("input");return b.className="kf-editor-input-box",b.type="text",b.isTrusted=!1,a.appendChild(b),b},focus:function(){var a=null;this.inputBox.focus(),this.kfEditor.requestService("syntax.has.cursor.info")||(a=this.kfEditor.requestService("syntax.get.root.group.info"),this.kfEditor.requestService("syntax.update.record.cursor",{groupId:a.id,startOffset:0,endOffset:a.content.length}),this.kfEditor.requestService("control.update.input")),this.kfEditor.requestService("control.reselect")},setUntrusted:function(){this.inputBox.isTrusted=!1},setTrusted:function(){this.inputBox.isTrusted=!0},updateInput:function(){var a=this.kfEditor.requestService("syntax.serialization");this.setUntrusted(),this.inputBox.value=a.str,this.inputBox.selectionStart=a.startOffset,this.inputBox.selectionEnd=a.endOffset,this.inputBox.focus(),this.setTrusted()},insertStr:function(a){var b=this.kfEditor.requestService("syntax.serialization"),c=b.str;c=c.substring(0,b.startOffset)+" "+a+" "+c.substring(b.endOffset),this.restruct(c),this.updateInput(),this.kfEditor.requestService("ui.update.canvas.view")},initEvent:function(){var a=this;c.addEvent(this.inputBox,"keydown",function(b){var c=!1;if(b.ctrlKey)return void a.processUserCtrl(b);switch(b.keyCode){case e.INPUT:return;case e.LEFT:b.preventDefault(),a.leftMove(),c=!0;break;case e.RIGHT:b.preventDefault(),a.rightMove(),c=!0;break;case e.DELETE:b.preventDefault(),a.delete(),c=!0}c&&a.kfEditor.requestService("ui.update.canvas.view"),a.pretreatmentInput(b)||b.preventDefault()}),c.addEvent(this.inputBox,"input",function(){a.processingInput()}),c.addEvent(this.inputBox,"blur",function(){a.kfEditor.requestService("ui.toolbar.disable"),a.kfEditor.requestService("ui.toolbar.close"),a.kfEditor.requestService("control.cursor.hide"),a.kfEditor.requestService("render.clear.select")}),c.addEvent(this.inputBox,"focus",function(){a.kfEditor.requestService("ui.toolbar.enable"),this.isTrusted&&a.kfEditor.requestService("control.reselect")}),c.addEvent(this.inputBox,"paste",function(a){a.preventDefault()})},hasRootplaceholder:function(){return this.kfEditor.requestService("syntax.has.root.placeholder")},leftMove:function(){this.hasRootplaceholder()||(this.kfEditor.requestService("syntax.cursor.move.left"),this.update())},rightMove:function(){this.hasRootplaceholder()||(this.kfEditor.requestService("syntax.cursor.move.right"),this.update())},"delete":function(){var a=null;this.hasRootplaceholder()||(a=this.kfEditor.requestService("syntax.delete.group"),a?(this.updateInput(),this.processingInput()):(this.updateInput(),this.kfEditor.requestService("control.reselect")))},processUserCtrl:function(a){switch(a.preventDefault(),a.keyCode){case 65:this.kfEditor.requestService("control.select.all");break;case 83:this.kfEditor.requestService("print.image")}},pretreatmentInput:function(a){var b=this.getKeyCode(a),c=d.getReplaceString(b);return null===c?!0:(this.insertStr(c),!1)},getKeyCode:function(a){return(a.shiftKey?"s+":"")+a.keyCode},processingInput:function(){this.restruct(this.inputBox.value),this.kfEditor.requestService("ui.update.canvas.view")},restruct:function(a){this.kfEditor.requestService("render.draw",a),this.kfEditor.requestService("control.reselect")},update:function(){this.updateInput(),this.kfEditor.requestService("control.reselect")}})}},b[8]={value:function(){var a=b.r(20),c=b.r(9),d=b.r(7),e=b.r(10);return a.createClass("MoveComponent",{constructor:function(a,b){this.parentComponent=a,this.kfEditor=b,this.components={},this.initComponents()},initComponents:function(){this.components.location=new c(this,this.kfEditor),this.components.selection=new e(this,this.kfEditor),this.components.input=new d(this,this.kfEditor)}})}},b[9]={value:function(){function a(a){return a.getBoundingClientRect()}var c=b.r(20);return c.createClass("LocationComponent",{constructor:function(a,b){this.parentComponent=a,this.kfEditor=b,this.paper=this.getPaper(),this.cursorShape=this.createCursor(),this.initServices(),this.initEvent()},getPaper:function(){return this.kfEditor.requestService("render.get.paper")},initServices:function(){this.kfEditor.registerService("control.cursor.relocation",this,{relocationCursor:this.updateCursor}),this.kfEditor.registerService("control.cursor.hide",this,{hideCursor:this.hideCursor}),this.kfEditor.registerService("control.reselect",this,{reselect:this.reselect}),this.kfEditor.registerService("control.get.cursor.location",this,{getCursorLocation:this.getCursorLocation})},createCursor:function(){var a=new c.Rect(1,0,0,0).fill("black");return a.setAttr("style","display: none"),this.paper.addShape(a),a},initEvent:function(){var a=this.kfEditor.request("ui.canvas.container.event"),b=this;a.on("mousedown",function(a){a.preventDefault(),b.updateCursorInfo(a),b.kfEditor.requestService("control.update.input"),b.reselect()})},updateCursorInfo:function(a){var b=null,c=null,d=-1;return this.kfEditor.requestService("syntax.has.root.placeholder")?(this.kfEditor.requestService("syntax.update.record.cursor",{groupId:this.kfEditor.requestService("syntax.get.root.group.info").id,startOffset:0,endOffset:1}),!1):(b=this.kfEditor.requestService("position.get.wrap",a.target),b&&this.kfEditor.requestService("syntax.is.placeholder.node",b.id)?(c=this.kfEditor.requestService("position.get.group.info",b),void this.kfEditor.requestService("syntax.update.record.cursor",c.group.id,c.index,c.index+1)):(c=this.kfEditor.requestService("position.get.group",a.target),null===c&&(c=this.kfEditor.requestService("syntax.get.root.group.info")),d=this.getIndex(a.clientX,c),void this.kfEditor.requestService("syntax.update.record.cursor",c.id,d)))},hideCursor:function(){this.cursorShape.setAttr("style","display: none")},reselect:function(){var a=this.kfEditor.requestService("syntax.get.record.cursor"),b=null;return this.hideCursor(),this.kfEditor.requestService("syntax.is.select.placeholder")?(b=this.kfEditor.requestService("syntax.get.group.content",a.groupId),void this.kfEditor.requestService("render.select.group",b.content[a.startOffset].id)):void(a.startOffset===a.endOffset?(this.updateCursor(),this.kfEditor.requestService("render.tint.current.cursor")):this.kfEditor.requestService("render.select.current.cursor"))},updateCursor:function(){var b=this.kfEditor.requestService("syntax.get.record.cursor");if(b.startOffset!==b.endOffset)return void this.hideCursor();var c=this.kfEditor.requestService("syntax.get.group.content",b.groupId),d=0===b.endOffset,e=d?0:b.endOffset-1,f=c.content[e],g=a(this.paper.container.node),h=0,i=a(f),j=this.cursorShape.getTransform(this.cursorShape),k=this.kfEditor.requestService("render.get.canvas.zoom"),l=this.paper.getZoom();this.cursorShape.setHeight(i.height/k/l),h=d?i.left-2:i.left+i.width-2,h-=g.left,j.m.e=Math.floor(h/k/l)+.5,j.m.f=(i.top-g.top)/k/l,this.cursorShape.setMatrix(j),this.cursorShape.setAttr("style","display: block")},getCursorLocation:function(){var a=this.cursorShape.getRenderBox("paper");return{x:a.x,y:a.y}},getIndex:function(b,c){for(var d=-1,e=c.content,f=null,g=e.length-1,h=null;g>=0;g--)if(d=g,h=e[g],f=a(h),f.leftthis.startPoint.x,e={},f=null,g=!1,h=this.startGroup,i=null,j=this.getGroupInof(b,a);j.groupInfo.id===h.groupInfo.id?(e={groupId:j.groupInfo.id,startOffset:h.offset,endOffset:j.offset},this.startGroupIsPlaceholder&&(d?e.startOffset===e.endOffset&&(e.endOffset+=1):e.startOffset+=1)):c.contains(h.groupInfo.groupObj,j.groupInfo.groupObj)?e={groupId:h.groupInfo.id,startOffset:h.offset,endOffset:this.getIndex(h.groupInfo.groupObj,a,b)}:c.contains(j.groupInfo.groupObj,h.groupInfo.groupObj)?(e={groupId:j.groupInfo.id,startOffset:this.kfEditor.requestService("position.get.index",j.groupInfo.groupObj,h.groupInfo.groupObj),endOffset:j.offset},d||(e.startOffset+=1)):(f=this.getCommunityGroup(h.groupInfo,j.groupInfo),f.startOffset===f.endOffset?f.endOffset+=1:(i=f.group.content[f.endOffset],g=this.kfEditor.requestService("position.get.area",i,b),g&&(f.endOffset+=1),d||(f.startOffset+=1)),e={groupId:f.group.id,startOffset:f.startOffset,endOffset:f.endOffset}),this.kfEditor.requestService("syntax.update.record.cursor",e.groupId,e.startOffset,e.endOffset),this.kfEditor.requestService("control.reselect")},updateSelectionByTarget:function(a){var b=this.kfEditor.requestService("position.get.parent.group",a),c=null,d={};if(null!==b){if(this.kfEditor.requestService("syntax.is.root.node",b.id))return void this.selectAll();this.kfEditor.requestService("syntax.is.virtual.node",b.id)?(c=this.kfEditor.requestService("position.get.group.info",b.groupObj),d={groupId:c.group.id,startOffset:c.index,endOffset:c.index+1}):d={groupId:b.id,startOffset:0,endOffset:b.content.length},this.kfEditor.requestService("syntax.update.record.cursor",d),this.kfEditor.requestService("control.reselect"),this.kfEditor.requestService("control.update.input")}},selectAll:function(){var a=this.kfEditor.requestService("syntax.get.root.group.info"),b={groupId:a.id,startOffset:0,endOffset:a.content.length};this.kfEditor.requestService("syntax.update.record.cursor",b),this.kfEditor.requestService("control.reselect"),this.kfEditor.requestService("control.update.input")},getGroupInof:function(a,b){var c=this.kfEditor.requestService("position.get.group",b);null===c&&(c=this.kfEditor.requestService("syntax.get.root.group.info"));var d=this.kfEditor.requestService("position.get.location.info",a,c);return{groupInfo:c,offset:d}},getIndex:function(a,b,d){var e=this.kfEditor.requestService("position.get.index",a,b),f=this.kfEditor.requestService("syntax.get.group.content",a.id),g=f.content[e],h=c.getRect(g);return h.left+h.width/2k;k++)i=b.operand[k],h(b)?e(a,k,b,i):f(a,k,b,i);return b}function c(){return q+ ++s}function d(a,b){a.isResetId?b.attr["data-root"]="true":b.attr["data-type"]=r.VIRTUAL}function e(b,c,d,e){"brackets"===d.name&&2>c||("function"!==d.name||0!==c)&&(d.attr["data-type"]=r.VIRTUAL,e?"string"==typeof e?(d.operand[c]=j(b),d.operand[c].operand[0]=e):i(e)?(d.operand[c]=j(b),d.operand[c].operand[0]=a(b,e,d.operand[c])):d.operand[c]=a(b,e,d):d.operand[c]=e)}function f(b,c,d,e){d.attr["data-type"]=r.GROUP,d.operand[c]=e&&"string"!=typeof e?"text"===e.name?e:a(b,e,d):e}function g(a){var b=1;if(a.length>3)return!1;for(var c=0,d=a.length;d>c;c++)a[c]!==m&&a[c]&&"placeholder"===a[c].name&&b--;return!b}function h(a){return!!n[a.name]}function i(a){return"placeholder"===a.name}function j(a){return{name:p,attr:{"data-type":r.GROUP,id:a.getGroupId()},operand:[]}}var k=b.r(19).Parser,l=b.r(20),m=b.r(29).cursorCharacter,n=b.r(22),o=b.r(29).rootPlaceholder.content,p="combination",q="_kf_editor_",r=b.r(11),s=0,t=l.createClass("Parser",{constructor:function(a){this.kfEditor=a,this.callBase(),this.kfParser=k.use("latex"),this.initKFormulExtension(),this.pid=c(),this.groupRecord=0,this.tree=null,this.isResetId=!0,this.initServices()},parse:function(b,c){var d=null;return this.isResetId=!!c,this.isResetId&&this.resetGroupId(),d=this.kfParser.parse(b),a(this,d.tree),d},serialization:function(a){return this.kfParser.serialization(a)},initServices:function(){this.kfEditor.registerService("parser.parse",this,{parse:this.parse}),this.kfEditor.registerService("parser.latex.serialization",this,{serialization:this.serialization})},getKFParser:function(){return this.kfParser},initKFormulExtension:function(){b.r(17).ext(this)},resetGroupId:function(){this.groupRecord=0},getGroupId:function(){return this.pid+"_"+ ++this.groupRecord}});return t}},b[22]={value:function(){return{radical:!0,fraction:!0,summation:!0,integration:!0,placeholder:!0,script:!0,superscript:!0,subscript:!0,brackets:!0,"function":!0}}},b[23]={value:function(){function a(b,c,d){var e=null;return b.ownerSVGElement?(b=b.parentNode,e=b.tagName.toLowerCase(),b&&"body"!==e&&"svg"!==e?"kf-editor-group"===b.getAttribute("data-type")?b:c&&"kf-editor-virtual-group"===b.getAttribute("data-type")?b:d&&null!==b.getAttribute("data-flag")?b:a(b,c,d):null):null}var c=b.r(20),d=b.r(4),e=c.createClass("PositionComponenet",{constructor:function(a){this.kfEditor=a,this.initServices()},initServices:function(){this.kfEditor.registerService("position.get.group",this,{getGroupByTarget:this.getGroupByTarget}),this.kfEditor.registerService("position.get.index",this,{getIndexByTargetInGroup:this.getIndexByTargetInGroup}),this.kfEditor.registerService("position.get.location.info",this,{getLocationInfo:this.getLocationInfo}),this.kfEditor.registerService("position.get.parent.group",this,{getParentGroupByTarget:this.getParentGroupByTarget}),this.kfEditor.registerService("position.get.wrap",this,{getWrap:this.getWrap}),this.kfEditor.registerService("position.get.area",this,{getAreaByCursorInGroup:this.getAreaByCursorInGroup}),this.kfEditor.registerService("position.get.group.info",this,{getGroupInfoByNode:this.getGroupInfoByNode}),this.kfEditor.registerService("position.get.parent.info",this,{getParentInfoByNode:this.getParentInfoByNode})},getGroupByTarget:function(b){var c=a(b,!1,!1);return c?this.kfEditor.requestService("syntax.get.group.content",c.id):null},getIndexByTargetInGroup:function(a,b){var e=this.kfEditor.requestService("syntax.get.group.content",a.id),f=-1;return c.Utils.each(e.content,function(a,c){return f=c,d.contains(a,b)?!1:void 0}),f},getAreaByCursorInGroup:function(a,b){var c=d.getRect(a);return c.left+c.width/2=0;g--)if(c=g,h=e[g],f=d.getRect(h),f.leftg&&(c.index=g,!d.contains(f.content[g],b));g++);return c.group=f,c},getParentInfoByNode:function(b){var c=a(b,!0,!1);return c=this.kfEditor.requestService("syntax.get.group.content",c.id),{group:c,index:c.content.indexOf(b)}}});return e}},b[24]={value:function(){var a=b.r(20);return a.createClass("Printer",{constructor:function(a){this.kfEditor=a,this.initServices(),this.initCommands()},initServices:function(){this.kfEditor.registerService("print.image",this,{printImage:this.printImage})},initCommands:function(){this.kfEditor.registerCommand("get.image.data",this,this.getImageData)},printImage:function(){var a=this.kfEditor.requestService("render.get.paper");this._formatCanvas(),a.toPNG(function(a){document.body.innerHTML=''}),this._restoreCanvas()},getImageData:function(a){var b=this.kfEditor.requestService("render.get.canvas"),c=this.kfEditor.requestService("render.get.paper");this._formatCanvas(),c.toPNG(function(c){a({width:b.width,height:b.height,img:c})}),this._restoreCanvas()},_formatCanvas:function(){var a=this.kfEditor.requestService("render.get.canvas"),b=a.container.getRenderBox();a.node.setAttribute("width",b.width),a.node.setAttribute("height",b.height),this.kfEditor.requestService("render.clear.canvas.transform"),this.kfEditor.requestService("control.cursor.hide"),this.kfEditor.requestService("render.clear.select")},_restoreCanvas:function(){var a=this.kfEditor.requestService("render.get.canvas");a.node.setAttribute("width","100%"),a.node.setAttribute("height","100%"),this.kfEditor.requestService("render.revert.canvas.transform"),this.kfEditor.requestService("control.cursor.relocation"),this.kfEditor.requestService("render.reselect")}})}},b[25]={value:function(){var a=b.r(20),c=b.r(19).Assembly,d={autoresize:!1,fontsize:50,padding:[20,50]},e=a.createClass("RenderComponent",{base:b.r(1),constructor:function(b,c){this.callBase(),this.options=a.Utils.extend({},d,c),this.kfEditor=b,this.assembly=null,this.formula=null,this.relDisabled=!1,this.canvasZoom=1,this.record={select:{},cursor:{},canvas:{}},this.initCanvas(),this.initServices(),this.initCommands()},initCanvas:function(){var a=this.kfEditor.requestService("ui.get.canvas.container"),b=this.kfEditor.getFormulaClass();this.assembly=new c(new b(a,this.options)),this.formula=this.assembly.formula,this.setCanvasToCenter()},setCanvasOffset:function(a,b){var c=this.formula.getViewBox();b=void 0!==b?b:-c.height/2,this.formula.setViewBox(a,b,c.width,c.height)},setCanvasToCenter:function(){var a=this.formula.getViewBox();this.formula.setViewBox(-a.width/2,-a.height/2,a.width,a.height)},initServices:function(){this.kfEditor.registerService("render.get.canvas",this,{getCanvas:this.getCanvas}),this.kfEditor.registerService("render.get.content.size",this,{getContentSize:this.getContentSize}),this.kfEditor.registerService("render.clear.canvas.transform",this,{clearCanvasOffset:this.clearCanvasTransform}),this.kfEditor.registerService("render.set.canvas.offset",this,{setCanvasOffset:this.setCanvasOffset}),this.kfEditor.registerService("render.set.canvas.to.center",this,{setCanvasToCenter:this.setCanvasToCenter}),this.kfEditor.registerService("render.revert.canvas.transform",this,{revertCanvasTransform:this.revertCanvasTransform}),this.kfEditor.registerService("render.relocation",this,{relocation:this.relocation}),this.kfEditor.registerService("render.disable.relocation",this,{disableRelocation:this.disableRelocation}),this.kfEditor.registerService("render.enable.relocation",this,{enableRelocation:this.enableRelocation}),this.kfEditor.registerService("render.select.group.content",this,{selectGroupContent:this.selectGroupContent}),this.kfEditor.registerService("render.select.group",this,{selectGroup:this.selectGroup}),this.kfEditor.registerService("render.select.group.all",this,{selectAllGroup:this.selectAllGroup}),this.kfEditor.registerService("render.tint.current.cursor",this,{tintCurrentGroup:this.tintCurrentGroup}),this.kfEditor.registerService("render.select.current.cursor",this,{selectCurrentCursor:this.selectCurrentCursor}),this.kfEditor.registerService("render.reselect",this,{reselect:this.reselect}),this.kfEditor.registerService("render.clear.select",this,{clearSelect:this.clearSelect}),this.kfEditor.registerService("render.set.canvas.zoom",this,{setCanvasZoom:this.setCanvasZoom}),this.kfEditor.registerService("render.get.canvas.zoom",this,{getCanvasZoom:this.getCanvasZoom}),this.kfEditor.registerService("render.get.paper.offset",this,{getPaperOffset:this.getPaperOffset}),this.kfEditor.registerService("render.draw",this,{render:this.render}),this.kfEditor.registerService("render.insert.string",this,{insertString:this.insertString}),this.kfEditor.registerService("render.insert.group",this,{insertGroup:this.insertGroup}),this.kfEditor.registerService("render.get.paper",this,{getPaper:this.getPaper})},initCommands:function(){this.kfEditor.registerCommand("render",this,function(a){this.render(a),this.kfEditor.requestService("ui.update.canvas.view")}),this.kfEditor.registerCommand("getPaper",this,this.getPaper)},relocation:function(){this.relDisabled?this.relocationToLeft():this.relocationToCenter()},relocationToCenter:function(){var a=this.formula.container.getRenderBox();this.formula.container.setTranslate(-a.width/2,-a.height/2),this.setCanvasToCenter()},relocationToLeft:function(){var a=this.formula.container.getRenderBox();this.formula.container.setTranslate(0,-a.height/2),this.setCanvasOffset(0)},selectGroup:function(a){var b=this.kfEditor.requestService("syntax.get.group.object",a);this.clearSelect(),b.node.getAttribute("data-root")||(this.record.select.lastSelect=b,b.select())},selectGroupContent:function(a){null!==a.groupObj.getAttribute("data-placeholder")&&(a={id:a.content[0].id});var b=this.kfEditor.requestService("syntax.get.group.object",a.id);this.clearSelect(),this.record.select.lastSelect=b,b.node.getAttribute("data-root")||b.select()},selectAllGroup:function(a){null!==a.groupObj.getAttribute("data-placeholder")&&(a={id:a.content[0].id});var b=this.kfEditor.requestService("syntax.get.group.object",a.id);this.clearSelect(),this.record.select.lastSelect=b,b.selectAll()},selectCurrentCursor:function(){var a=this.kfEditor.requestService("syntax.get.record.cursor"),b=this.kfEditor.requestService("syntax.get.group.object",a.groupId),c=null,d=-1,e=0,f=Math.min(a.startOffset,a.endOffset),g=Math.max(a.startOffset,a.endOffset);this.clearSelect(),this.record.select.lastSelect=b;for(var h=f,i=g;i>h;h++)c=b.getOperand(h).getRenderBox(b),-1==d&&(d=c.x),e+=c.width;b.setBoxWidth(e),b.selectAll(),b.getBox().setTranslate(d,0)},tintCurrentGroup:function(){var a=this.kfEditor.requestService("syntax.get.record.cursor").groupId,b=this.kfEditor.requestService("syntax.get.group.object",a),c=this.kfEditor.requestService("syntax.is.placeholder.node",a);this.clearSelect(),b.node.getAttribute("data-root")||(c&&(b=this.kfEditor.requestService("syntax.get.group.object",b.operands[0].node.id)),this.record.select.lastSelect=b,b.select())},reselect:function(){var a=this.kfEditor.requestService("syntax.get.record.cursor"),b=null;b=this.kfEditor.requestService("syntax.get.group.object",a.groupId),this.clearSelect(),this.record.select.lastSelect=b,b.node.getAttribute("data-root")||b.select() +},clearSelect:function(){var a=null,b=this.record.select.lastSelect;b&&b.node.ownerSVGElement&&(b.unselect(),a=b.getRenderBox(b),b.setBoxWidth(a.width),b.getBox().setTranslate(0,0))},getPaper:function(){return this.formula},render:function(a){var b=this.kfEditor.requestService("parser.parse",a,!0),c=this.assembly.regenerateBy(b);this.kfEditor.requestService("syntax.update.objtree",c)},enableRelocation:function(){this.relDisabled=!1},disableRelocation:function(){this.relDisabled=!0},setCanvasZoom:function(a){var b=this.formula.getViewPort();this.canvasZoom=a,b.zoom=a,this.formula.setViewPort(b)},getCanvas:function(){return this.formula},getContentSize:function(){return this.formula.container.getRenderBox()},clearCanvasTransform:function(){var a=this.record.canvas;a.viewBox=this.formula.getViewBox(),a.contentOffset=this.formula.container.getTranslate(),this.setCanvasToCenter(),this.formula.node.removeAttribute("viewBox"),this.formula.container.setTranslate(0,0)},revertCanvasTransform:function(){var a=this.record.canvas,b=a.viewBox;return b?(this.formula.setViewBox(b.x,b.y,b.width,b.height),this.formula.container.setTranslate(a.contentOffset),a.viewBox=null,void(a.contentOffset=null)):!1},getCanvasZoom:function(){return this.canvasZoom}});return e}},b[26]={value:function(){var a=b.r(20);return a.createClass("DeleteComponent",{constructor:function(a,b){this.parentComponent=a,this.kfEditor=b},deleteGroup:function(){var a=this.parentComponent.getCursorRecord(),b=this.parentComponent.getObjectTree(),c=b.mapping[a.groupId].strGroup;return a.startOffset!==a.endOffset?this.parentComponent.isSelectPlaceholder()?this.parentComponent.isRootTree(c)?!1:(a=this.selectParentContainer(a.groupId),this.parentComponent.updateCursor(a),!1):this.deleteSelection(c,a):0===a.startOffset?this.parentComponent.isRootTree(c)?!1:(a=this.selectParentContainer(a.groupId),this.parentComponent.updateCursor(a),!1):c.operand.length>1?(a=this.deletePrevGroup(c,a),this.parentComponent.updateCursor(a),a.startOffset===a.endOffset?!0:!1):(a.startOffset=0,a.endOffset=1,c.operand[0].attr&&this.parentComponent.isGroupNode(c.operand[0].attr.id)?(this.parentComponent.updateCursor(a),!1):(c.operand[0]={name:"placeholder",operand:[]},this.parentComponent.updateCursor(a),!0))},deletePrevGroup:function(a,b){var c=b.startOffset-1,d=a.operand[c];return this.parentComponent.isLeafTree(d)?(a.operand.splice(c,1),b.startOffset-=1,b.endOffset-=1):b.startOffset-=1,b},deleteSelection:function(a,b){return 0===b.startOffset&&b.endOffset===a.operand.length?(a.operand.length=1,a.operand[0]={name:"placeholder",operand:[]},b.endOffset=1):(a.operand.splice(b.startOffset,b.endOffset-b.startOffset),b.endOffset=b.startOffset),this.parentComponent.updateCursor(b),!0},selectParentContainer:function(a){var b=this.parentComponent.getGroupObject(a).node,c=this.kfEditor.requestService("position.get.group",b),d=this.kfEditor.requestService("position.get.index",c.groupObj,b);return{groupId:c.id,startOffset:d,endOffset:d+1}}})}},b[27]={value:function(){function a(a){var b=null,c=this.parentComponent,f=null;return f=c.getGroupContent(a.groupId),c.isSelectPlaceholder()?e(this,f.content[a.startOffset],p.LEFT):(a.startOffset===a.endOffset?a.startOffset>0?(b=f.content[a.startOffset-1],l(b)?a=d(this,b,p.LEFT):(a.startOffset-=1,m(b)||(a.endOffset=a.startOffset))):a=e(this,f.groupObj,p.LEFT):(a.startOffset=Math.min(a.startOffset,a.endOffset),a.endOffset=a.startOffset),a)}function c(a){var b=null,c=this.parentComponent,f=null;return f=c.getGroupContent(a.groupId),c.isSelectPlaceholder()?e(this,f.content[a.startOffset],p.RIGHT):(a.startOffset===a.endOffset?a.startOffset1)return{groupId:d.group.id,startOffset:0,endOffset:0};d=c.requestService("position.get.parent.info",d.group.groupObj)}return k(d.group.groupObj)?{groupId:d.group.id,startOffset:d.index,endOffset:d.index}:(b=d.group.content[d.index-1],l(b)?k(b)?f(a,b):f(a,b):n(b)?g(a,b):{groupId:d.group.id,startOffset:d.index,endOffset:d.index})}function h(a,b){var c=a.parentComponent,d=null,e=null;if(l(b)){if(d=c.getGroupContent(b.id),e=d.content[0],k(b))return k(e)?h(a,e):m(e)?{groupId:b.id,startOffset:0,endOffset:1}:{groupId:b.id,startOffset:0,endOffset:0};for(;!k(e)&&!m(e)&&!n(e);)d=c.getGroupContent(e.id),e=d.content[0];return m(e)?{groupId:e.id,startOffset:0,endOffset:0}:n(e)?i(a,e):h(a,e)}return null}function i(a,b){var c=a.kfEditor,d=a.parentComponent,e=null,f=null;if(j(b))return null;for(e=c.requestService("position.get.parent.info",b);e.index===e.group.content.length-1;){if(j(e.group.groupObj))return{groupId:e.group.id,startOffset:e.group.content.length,endOffset:e.group.content.length};if(k(e.group.groupObj)&&e.group.content.length>1)return{groupId:e.group.id,startOffset:e.group.content.length,endOffset:e.group.content.length};e=c.requestService("position.get.parent.info",e.group.groupObj)}return b=e.group.content[e.index+1],n(b)?i(a,b):k(b)?(f=d.getGroupContent(b.id),d.isPlaceholder(f.content[0].id)?{groupId:b.id,startOffset:0,endOffset:1}:{groupId:b.id,startOffset:0,endOffset:0}):{groupId:e.group.id,startOffset:e.index+1,endOffset:e.index+1}}function j(a){return!!a.getAttribute("data-root")}function k(a){return"kf-editor-group"===a.getAttribute("data-type")}function l(a){var b=a.getAttribute("data-type");return"kf-editor-group"===b||"kf-editor-virtual-group"===b}function m(a){return"Placeholder"===a.getAttribute("data-flag")}function n(a){return"Empty"===a.getAttribute("data-flag")}var o=b.r(20),p={LEFT:"left",RIGHT:"right"};return o.createClass("MoveComponent",{constructor:function(a,b){this.parentComponent=a,this.kfEditor=b},leftMove:function(){var b=this.parentComponent.getCursorRecord();b=a.call(this,b),b&&this.parentComponent.updateCursor(b)},rightMove:function(){var a=this.parentComponent.getCursorRecord();a=c.call(this,a),a&&this.parentComponent.updateCursor(a)}})}},b[28]={value:function(){var a=b.r(20),c=b.r(27),d=b.r(26),e=b.r(29).cursorCharacter,f=b.r(11),g=a.createClass("SyntaxComponenet",{constructor:function(a){this.kfEditor=a,this.record={cursor:{group:null,startOffset:-1,endOffset:-1}},this.components={},this.objTree=null,this.initComponents(),this.initServices(),this.initCommands()},initComponents:function(){this.components.move=new c(this,this.kfEditor),this.components.delete=new d(this,this.kfEditor)},initServices:function(){this.kfEditor.registerService("syntax.update.objtree",this,{updateObjTree:this.updateObjTree}),this.kfEditor.registerService("syntax.get.objtree",this,{getObjectTree:this.getObjectTree}),this.kfEditor.registerService("syntax.get.group.object",this,{getGroupObject:this.getGroupObject}),this.kfEditor.registerService("syntax.is.root.node",this,{isRootNode:this.isRootNode}),this.kfEditor.registerService("syntax.is.group.node",this,{isGroupNode:this.isGroupNode}),this.kfEditor.registerService("syntax.is.virtual.node",this,{isVirtualNode:this.isVirtualNode}),this.kfEditor.registerService("syntax.is.placeholder.node",this,{isPlaceholder:this.isPlaceholder}),this.kfEditor.registerService("syntax.is.select.placeholder",this,{isSelectPlaceholder:this.isSelectPlaceholder}),this.kfEditor.registerService("syntax.has.root.placeholder",this,{hasRootplaceholder:this.hasRootplaceholder}),this.kfEditor.registerService("syntax.valid.brackets",this,{isBrackets:this.isBrackets}),this.kfEditor.registerService("syntax.get.group.content",this,{getGroupContent:this.getGroupContent}),this.kfEditor.registerService("syntax.get.root.group.info",this,{getRootGroupInfo:this.getRootGroupInfo}),this.kfEditor.registerService("syntax.get.root",this,{getRootObject:this.getRootObject}),this.kfEditor.registerService("syntax.update.record.cursor",this,{updateCursor:this.updateCursor}),this.kfEditor.registerService("syntax.update.selection",this,{updateSelection:this.updateSelection}),this.kfEditor.registerService("syntax.get.record.cursor",this,{getCursorRecord:this.getCursorRecord}),this.kfEditor.registerService("syntax.has.cursor.info",this,{hasCursorInfo:this.hasCursorInfo}),this.kfEditor.registerService("syntax.serialization",this,{serialization:this.serialization}),this.kfEditor.registerService("syntax.cursor.move.left",this,{leftMove:this.leftMove}),this.kfEditor.registerService("syntax.cursor.move.right",this,{rightMove:this.rightMove}),this.kfEditor.registerService("syntax.delete.group",this,{deleteGroup:this.deleteGroup})},initCommands:function(){this.kfEditor.registerCommand("get.source",this,this.getSource),this.kfEditor.registerCommand("content.is.empty",this,this.isEmpty)},updateObjTree:function(a){var b=a.select;b&&b.groupId&&this.updateCursor(b.groupId,b.startOffset,b.endOffset),this.objTree=a},hasCursorInfo:function(){return null!==this.record.cursor.group},isRootNode:function(a){return this.objTree.mapping.root.strGroup.attr.id===a},isGroupNode:function(a){var b=this.objTree.mapping[a].strGroup.attr["data-type"];return b===f.GROUP||b===f.VIRTUAL},isVirtualNode:function(a){return this.objTree.mapping[a].strGroup.attr["data-type"]===f.VIRTUAL},isPlaceholder:function(a){var b=this.objTree.mapping[a];return b?(b=b.objGroup.node,"Placeholder"===b.getAttribute("data-flag")):!1},isBrackets:function(a){return!!this.objTree.mapping[a].objGroup.node.getAttribute("data-brackets")},hasRootplaceholder:function(){return"placeholder"===this.objTree.mapping.root.strGroup.operand[0].name},isSelectPlaceholder:function(){var a=this.record.cursor,b=null;return a.endOffset-a.startOffset!==1?!1:(b=this.getGroupContent(a.groupId),this.isPlaceholder(b.content[a.startOffset].id)?!0:!1)},isLeafTree:function(a){return"string"==typeof a},isRootTree:function(a){return a.attr&&a.attr["data-root"]},getObjectTree:function(){return this.objTree},getGroupObject:function(a){return this.objTree.mapping[a].objGroup||null},getCursorRecord:function(){return a.Utils.extend({},this.record.cursor)||null},getGroupContent:function(b){var c=this.objTree.mapping[b],d=[],e=c.objGroup.operands,f=e.length-1,g="rtl"!==c.strGroup.traversal;return a.Utils.each(e,function(a,b){g?d.push(a.node):d[f-b]=a.node}),{id:b,traversal:c.strGroup.traversal||"ltr",groupObj:c.objGroup.node,content:d}},getRootObject:function(){return this.objTree.mapping.root.objGroup},getRootGroupInfo:function(){var a=this.objTree.mapping.root.strGroup.attr.id;return this.getGroupContent(a)},updateSelection:function(a){var b=this.objTree.mapping[a.id],c=b.strGroup,d=null,f=null,g=null,h=-1,i=-1;if(d=a,f=b,"combination"===c.name)this.record.cursor={groupId:d.id,startOffset:0,endOffset:c.operand.length},c.operand.unshift(e),c.operand.push(e);else{for(;"combination"!==f.strGroup.name||1===d.content;)a=d,b=f,d=this.kfEditor.requestService("position.get.parent.group",b.objGroup.node),f=this.objTree.mapping[d.id];var j=[].indexOf.call(d.content,a.groupObj);this.record.cursor={groupId:d.id,startOffset:j,endOffset:j+1},f.strGroup.operand.splice(j+1,0,e),f.strGroup.operand.splice(j,0,e)}return g=this.kfEditor.requestService("parser.latex.serialization",this.objTree.parsedTree),h=g.indexOf(e),g=g.replace(e,""),i=g.indexOf(e),f.strGroup.operand.splice(this.record.cursor.startOffset,1),f.strGroup.operand.splice(this.record.cursor.endOffset,1),{str:g,startOffset:h,endOffset:i}},getSource:function(){return this.serialization().str.replace(e,"").replace(e,"")},isEmpty:function(){return this.hasRootplaceholder()},serialization:function(){var a=this.record.cursor,b=this.objTree.mapping[a.groupId],c=b.strGroup,d=null,f=-1,g=-1;return f=Math.min(a.endOffset,a.startOffset),g=Math.max(a.endOffset,a.startOffset),c.operand.splice(g,0,e),c.operand.splice(f,0,e),g+=1,d=this.kfEditor.requestService("parser.latex.serialization",this.objTree.parsedTree),c.operand.splice(g,1),c.operand.splice(f,1),f=d.indexOf(e),a.startOffset===a.endOffset&&(d=d.replace(e,"")),g=d.lastIndexOf(e),{str:d,startOffset:f,endOffset:g}},updateCursor:function(a,b,c){var d=null;1===arguments.length&&(c=a.endOffset,b=a.startOffset,a=a.groupId),void 0===c&&(c=b),b>c&&(d=c,c=b,b=d),this.record.cursor={groupId:a,startOffset:b,endOffset:c}},leftMove:function(){this.components.move.leftMove()},rightMove:function(){this.components.move.rightMove()},deleteGroup:function(){return this.components.delete.deleteGroup()},insertSubtree:function(a){var b=this.record.cursor,c=0,d=0,e=null,f=0;this.isPlaceholder(b.groupId)?this.replaceTree(a):(c=Math.min(b.startOffset,b.endOffset),d=Math.max(b.startOffset,b.endOffset),f=d-c,e=this.objTree.mapping[b.groupId].strGroup,e.operand.splice(c,f,a),b.startOffset+=1,b.endOffset=b.startOffset)},replaceTree:function(a){var b=this.record.cursor,c=this.objTree.mapping[b.groupId].objGroup.node,d=this.kfEditor.requestService("position.get.parent.info",c),e=this.objTree.mapping[d.group.id].strGroup;e.operand[d.index]=a,b.groupId=d.group.id,b.startOffset=d.index+1,b.endOffset=d.index+1}});return g}},b[29]={value:function(){return{cursorCharacter:"\uf155",rootPlaceholder:{color:"#666",content:"\u5728\u6b64\u5904\u952e\u5165\u516c\u5f0f",fontsize:16},scrollbar:{padding:5,step:150}}}},b[30]={value:function(){return{"\\pm":{x:5,y:0},"\\infty":{x:42,y:0},"=":{x:79,y:0},"\\sim":{x:116,y:0},"\\times":{x:153,y:0},"\\div":{x:190,y:0},"!":{x:227,y:0},"<":{x:264,y:0},"\\ll":{x:301,y:0},">":{x:338,y:0},"\\gg":{x:375,y:0},"\\leq":{x:412,y:0},"\\geq":{x:449,y:0},"\\mp":{x:486,y:0},"\\cong":{x:523,y:0},"\\equiv":{x:560,y:0},"\\propto":{x:597,y:0},"\\approx":{x:634,y:0},"\\forall":{x:671,y:0},"\\partial":{x:708,y:0},"\\surd":{x:745,y:0},"\\cup":{x:782,y:0},"\\cap":{x:819,y:0},"\\varnothing":{x:856,y:0},"%":{x:893,y:0},"\\circ":{x:930,y:0},"\\exists":{x:967,y:0},"\\nexists":{x:1004,y:0},"\\in":{x:1041,y:0},"\\ni":{x:1078,y:0},"\\gets":{x:5,y:37},"\\uparrow":{x:42,y:37},"\\to":{x:79,y:37},"\\downarrow":{x:116,y:37},"\\leftrightarrow":{x:153,y:37},"\\therefore":{x:190,y:37},"\\because":{x:227,y:37},"+":{x:264,y:37},"-":{x:301,y:37},"\\neg":{x:338,y:37},"\\ast":{x:375,y:37},"\\cdot":{x:412,y:37},"\\vdots":{x:449,y:37},"\\ddots":{x:486,y:37},"\\aleph":{x:523,y:37},"\\beth":{x:560,y:37},"\\blacksquare":{x:597,y:37},"\\alpha":{x:634,y:37},"\\beta":{x:671,y:37},"\\gamma":{x:708,y:37},"\\delta":{x:745,y:37},"\\epsilon":{x:782,y:37},"\\zeta":{x:819,y:37},"\\eta":{x:856,y:37},"\\theta":{x:893,y:37},"\\iota":{x:930,y:37},"\\kappa":{x:967,y:37},"\\lambda":{x:1004,y:37},"\\mu":{x:1041,y:37},"\\nu":{x:1078,y:37},"\\xi":{x:5,y:74},"\\omicron":{x:42,y:74},"\\pi":{x:79,y:74},"\\rho":{x:116,y:74},"\\sigma":{x:153,y:74},"\\tau":{x:190,y:74},"\\upsilon":{x:227,y:74},"\\phi":{x:264,y:74},"\\chi":{x:301,y:74},"\\psi":{x:338,y:74},"\\omega":{x:375,y:74},"\\Alpha":{x:412,y:74},"\\Beta":{x:449,y:74},"\\Gamma":{x:486,y:74},"\\Delta":{x:523,y:74},"\\Epsilon":{x:560,y:74},"\\Zeta":{x:597,y:74},"\\Eta":{x:634,y:74},"\\Theta":{x:671,y:74},"\\Iota":{x:708,y:74},"\\Kappa":{x:745,y:74},"\\Lambda":{x:782,y:74},"\\Mu":{x:819,y:74},"\\Nu":{x:856,y:74},"\\Xi":{x:893,y:74},"\\Omicron":{x:930,y:74},"\\Pi":{x:967,y:74},"\\Rho":{x:1004,y:74},"\\Sigma":{x:1041,y:74},"\\Tau":{x:1078,y:74},"\\Upsilon":{x:5,y:111},"\\Phi":{x:42,y:111},"\\Chi":{x:79,y:111},"\\Psi":{x:116,y:111},"\\Omega":{x:153,y:111},"\\digamma":{x:190,y:111},"\\varepsilon":{x:227,y:111},"\\varkappa":{x:264,y:111},"\\varphi":{x:301,y:111},"\\varpi":{x:338,y:111},"\\varrho":{x:375,y:111},"\\varsigma":{x:412,y:111},"\\vartheta":{x:449,y:111},"\\neq":{x:486,y:111},"\\nless":{x:523,y:111},"\\ngtr":{x:560,y:111},"\\nleq":{x:597,y:111},"\\ngeq":{x:634,y:111},"\\nsim":{x:671,y:111},"\\lneqq":{x:708,y:111},"\\gneqq":{x:745,y:111},"\\nprec":{x:782,y:111},"\\nsucc":{x:819,y:111},"\\notin":{x:856,y:111},"\\nsubseteq":{x:893,y:111},"\\nsupseteq":{x:930,y:111},"\\subsetneq":{x:967,y:111},"\\supsetneq":{x:1004,y:111},"\\lnsim":{x:1041,y:111},"\\gnsim":{x:1078,y:111},"\\precnsim":{x:5,y:148},"\\succnsim":{x:42,y:148},"\\ntriangleleft":{x:79,y:148},"\\ntriangleright":{x:116,y:148},"\\ntrianglelefteq":{x:153,y:148},"\\ntrianglerighteq":{x:190,y:148},"\\nmid":{x:227,y:148},"\\nparallel":{x:264,y:148},"\\nvdash":{x:301,y:148},"\\nVdash":{x:338,y:148},"\\nvDash":{x:375,y:148},"\\nVDash":{x:412,y:148},"\\daleth":{x:449,y:148},"\\gimel":{x:486,y:148},"\\complement":{x:523,y:148},"\\ell":{x:560,y:148},"\\eth":{x:597,y:148},"\\hbar":{x:634,y:148},"\\hslash":{x:671,y:148},"\\mho":{x:708,y:148},"\\wp":{x:745,y:148},"\\circledS":{x:782,y:148},"\\Bbbk":{x:819,y:148},"\\Finv":{x:856,y:148},"\\Game":{x:893,y:148},"\\Im":{x:930,y:148},"\\Re":{x:967,y:148},"\\updownarrow":{x:1004,y:148},"\\Leftarrow":{x:1041,y:148},"\\Rightarrow":{x:1078,y:148},"\\Uparrow":{x:5,y:185},"\\Downarrow":{x:42,y:185},"\\Leftrightarrow":{x:79,y:185},"\\Updownarrow":{x:116,y:185},"\\longleftarrow":{x:153,y:185},"\\longrightarrow":{x:190,y:185},"\\longleftrightarrow":{x:227,y:185},"\\Longleftarrow":{x:264,y:185},"\\Longrightarrow":{x:301,y:185},"\\Longleftrightarrow":{x:338,y:185},"\\nearrow":{x:375,y:185},"\\nwarrow":{x:412,y:185},"\\searrow":{x:449,y:185},"\\swarrow":{x:486,y:185},"\\nleftarrow":{x:523,y:185},"\\nrightarrow":{x:560,y:185},"\\nLeftarrow":{x:597,y:185},"\\nRightarrow":{x:634,y:185},"\\nLeftrightarrow":{x:671,y:185},"\\leftharpoonup":{x:708,y:185},"\\leftharpoondown":{x:745,y:185},"\\rightharpoonup":{x:782,y:185},"\\rightharpoondown":{x:819,y:185},"\\upharpoonleft":{x:856,y:185},"\\upharpoonright":{x:893,y:185},"\\downharpoonleft":{x:930,y:185},"\\downharpoonright":{x:967,y:185},"\\leftrightharpoons":{x:1004,y:185},"\\rightleftharpoons":{x:1041,y:185},"\\leftleftarrows":{x:1078,y:185},"\\rightrightarrows":{x:5,y:222},"\\upuparrows":{x:42,y:222},"\\downdownarrows":{x:79,y:222},"\\leftrightarrows":{x:116,y:222},"\\rightleftarrows":{x:153,y:222},"\\looparrowleft":{x:190,y:222},"\\looparrowright":{x:227,y:222},"\\leftarrowtail":{x:264,y:222},"\\rightarrowtail":{x:301,y:222},"\\Lsh":{x:338,y:222},"\\Rsh":{x:375,y:222},"\\Lleftarrow":{x:412,y:222},"\\Rrightarrow":{x:449,y:222},"\\curvearrowleft":{x:486,y:222},"\\curvearrowright":{x:523,y:222},"\\circlearrowleft":{x:560,y:222},"\\circlearrowright":{x:597,y:222},"\\multimap":{x:634,y:222},"\\leftrightsquigarrow":{x:671,y:222},"\\twoheadleftarrow":{x:708,y:222},"\\twoheadrightarrow":{x:745,y:222},"\\rightsquigarrow":{x:782,y:222},"\\mathcal{A}":{x:819,y:222},"\\mathcal{B}":{x:856,y:222},"\\mathcal{C}":{x:893,y:222},"\\mathcal{D}":{x:930,y:222},"\\mathcal{E}":{x:967,y:222},"\\mathcal{F}":{x:1004,y:222},"\\mathcal{G}":{x:1041,y:222},"\\mathcal{H}":{x:1078,y:222},"\\mathcal{I}":{x:5,y:259},"\\mathcal{J}":{x:42,y:259},"\\mathcal{K}":{x:79,y:259},"\\mathcal{L}":{x:116,y:259},"\\mathcal{M}":{x:153,y:259},"\\mathcal{N}":{x:190,y:259},"\\mathcal{O}":{x:227,y:259},"\\mathcal{P}":{x:264,y:259},"\\mathcal{Q}":{x:301,y:259},"\\mathcal{R}":{x:338,y:259},"\\mathcal{S}":{x:375,y:259},"\\mathcal{T}":{x:412,y:259},"\\mathcal{U}":{x:449,y:259},"\\mathcal{V}":{x:486,y:259},"\\mathcal{W}":{x:523,y:259},"\\mathcal{X}":{x:560,y:259},"\\mathcal{Y}":{x:597,y:259},"\\mathcal{Z}":{x:634,y:259},"\\mathfrak{A}":{x:671,y:259},"\\mathfrak{B}":{x:708,y:259},"\\mathfrak{C}":{x:745,y:259},"\\mathfrak{D}":{x:782,y:259},"\\mathfrak{E}":{x:819,y:259},"\\mathfrak{F}":{x:856,y:259},"\\mathfrak{G}":{x:893,y:259},"\\mathfrak{H}":{x:930,y:259},"\\mathfrak{I}":{x:967,y:259},"\\mathfrak{J}":{x:1004,y:259},"\\mathfrak{K}":{x:1041,y:259},"\\mathfrak{L}":{x:1078,y:259},"\\mathfrak{M}":{x:5,y:296},"\\mathfrak{N}":{x:42,y:296},"\\mathfrak{O}":{x:79,y:296},"\\mathfrak{P}":{x:116,y:296},"\\mathfrak{Q}":{x:153,y:296},"\\mathfrak{R}":{x:190,y:296},"\\mathfrak{S}":{x:227,y:296},"\\mathfrak{T}":{x:264,y:296},"\\mathfrak{U}":{x:301,y:296},"\\mathfrak{V}":{x:338,y:296},"\\mathfrak{W}":{x:375,y:296},"\\mathfrak{X}":{x:412,y:296},"\\mathfrak{Y}":{x:449,y:296},"\\mathfrak{Z}":{x:486,y:296},"\\mathfrak{a}":{x:523,y:296},"\\mathfrak{b}":{x:560,y:296},"\\mathfrak{c}":{x:597,y:296},"\\mathfrak{d}":{x:634,y:296},"\\mathfrak{e}":{x:671,y:296},"\\mathfrak{f}":{x:708,y:296},"\\mathfrak{g}":{x:745,y:296},"\\mathfrak{h}":{x:782,y:296},"\\mathfrak{i}":{x:819,y:296},"\\mathfrak{j}":{x:856,y:296},"\\mathfrak{k}":{x:893,y:296},"\\mathfrak{l}":{x:930,y:296},"\\mathfrak{m}":{x:967,y:296},"\\mathfrak{n}":{x:1004,y:296},"\\mathfrak{o}":{x:1041,y:296},"\\mathfrak{p}":{x:1078,y:296},"\\mathfrak{q}":{x:5,y:333},"\\mathfrak{r}":{x:42,y:333},"\\mathfrak{s}":{x:79,y:333},"\\mathfrak{t}":{x:116,y:333},"\\mathfrak{u}":{x:153,y:333},"\\mathfrak{v}":{x:190,y:333},"\\mathfrak{w}":{x:227,y:333},"\\mathfrak{x}":{x:264,y:333},"\\mathfrak{y}":{x:301,y:333},"\\mathfrak{z}":{x:338,y:333},"\\mathbb{A}":{x:375,y:333},"\\mathbb{B}":{x:412,y:333},"\\mathbb{C}":{x:449,y:333},"\\mathbb{D}":{x:486,y:333},"\\mathbb{E}":{x:523,y:333},"\\mathbb{F}":{x:560,y:333},"\\mathbb{G}":{x:597,y:333},"\\mathbb{H}":{x:634,y:333},"\\mathbb{I}":{x:671,y:333},"\\mathbb{J}":{x:708,y:333},"\\mathbb{K}":{x:745,y:333},"\\mathbb{L}":{x:782,y:333},"\\mathbb{M}":{x:819,y:333},"\\mathbb{N}":{x:856,y:333},"\\mathbb{O}":{x:893,y:333},"\\mathbb{P}":{x:930,y:333},"\\mathbb{Q}":{x:967,y:333},"\\mathbb{R}":{x:1004,y:333},"\\mathbb{S}":{x:1041,y:333},"\\mathbb{T}":{x:1078,y:333},"\\mathbb{U}":{x:5,y:370},"\\mathbb{V}":{x:42,y:370},"\\mathbb{W}":{x:79,y:370},"\\mathbb{X}":{x:116,y:370},"\\mathbb{Y}":{x:153,y:370},"\\mathbb{Z}":{x:190,y:370},"\\mathrm{A}":{x:227,y:370},"\\mathrm{B}":{x:264,y:370},"\\mathrm{C}":{x:301,y:370},"\\mathrm{D}":{x:338,y:370},"\\mathrm{E}":{x:375,y:370},"\\mathrm{F}":{x:412,y:370},"\\mathrm{G}":{x:449,y:370},"\\mathrm{H}":{x:486,y:370},"\\mathrm{I}":{x:523,y:370},"\\mathrm{J}":{x:560,y:370},"\\mathrm{K}":{x:597,y:370},"\\mathrm{L}":{x:634,y:370},"\\mathrm{M}":{x:671,y:370},"\\mathrm{N}":{x:708,y:370},"\\mathrm{O}":{x:745,y:370},"\\mathrm{P}":{x:782,y:370},"\\mathrm{Q}":{x:819,y:370},"\\mathrm{R}":{x:856,y:370},"\\mathrm{S}":{x:893,y:370},"\\mathrm{T}":{x:930,y:370},"\\mathrm{U}":{x:967,y:370},"\\mathrm{V}":{x:1004,y:370},"\\mathrm{W}":{x:1041,y:370},"\\mathrm{X}":{x:1078,y:370},"\\mathrm{Y}":{x:5,y:407},"\\mathrm{Z}":{x:42,y:407},"\\mathrm{a}":{x:79,y:407},"\\mathrm{b}":{x:116,y:407},"\\mathrm{c}":{x:153,y:407},"\\mathrm{d}":{x:190,y:407},"\\mathrm{e}":{x:227,y:407},"\\mathrm{f}":{x:264,y:407},"\\mathrm{g}":{x:301,y:407},"\\mathrm{h}":{x:338,y:407},"\\mathrm{i}":{x:375,y:407},"\\mathrm{j}":{x:412,y:407},"\\mathrm{k}":{x:449,y:407},"\\mathrm{l}":{x:486,y:407},"\\mathrm{m}":{x:523,y:407},"\\mathrm{n}":{x:560,y:407},"\\mathrm{o}":{x:597,y:407},"\\mathrm{p}":{x:634,y:407},"\\mathrm{q}":{x:671,y:407},"\\mathrm{r}":{x:708,y:407},"\\mathrm{s}":{x:745,y:407},"\\mathrm{t}":{x:782,y:407},"\\mathrm{u}":{x:819,y:407},"\\mathrm{v}":{x:856,y:407},"\\mathrm{w}":{x:893,y:407},"\\mathrm{x}":{x:930,y:407},"\\mathrm{y}":{x:967,y:407},"\\mathrm{z}":{x:1004,y:407}}}},b[31]={value:function(){var a=b.r(4),c=b.r(20),d={min:1,max:2},e=c.createClass("ScrollZoomController",{constructor:function(b,c,e,f){this.kfEditor=c,this.target=e,this.zoom=1,this.step=.05,this.options=a.extend({},d,f),this.initEvent()},initEvent:function(){var b=this.kfEditor,c=this,d=this.options.min,e=this.options.max,f=this.step;a.addEvent(this.target,"mousewheel",function(a){a.preventDefault(),a.wheelDelta<0?c.zoom-=c.zoom*f:c.zoom+=c.zoom*f,c.zoom=Math.max(c.zoom,d),c.zoom=Math.min(c.zoom,e),b.requestService("render.set.canvas.zoom",c.zoom)})}});return e}},b[32]={value:function(){return{VIEW_STATE:{NO_OVERFLOW:0,OVERFLOW:1},scrollbar:{step:50,thumbMinSize:50}}}},b[33]={value:function(){return{"x=\\frac {-b\\pm\\sqrt {b^2-4ac}}{2a}":{pos:{x:0,y:0},size:{width:310,height:73}},"{\\placeholder/\\placeholder}":{pos:{x:315,y:0},size:{width:56,height:75}},"\\frac \\placeholder\\placeholder":{pos:{x:376,y:0},size:{width:56,height:75}},"a^2+b^2=c^2":{pos:{x:437,y:0},size:{width:310,height:73}},"{\\left(x+a\\right)}^2=\\sum^n_{k=0}{\\left(^n_k\\right)x^ka^{n-k}}":{pos:{x:752,y:0},size:{width:310,height:73}},"\\frac {dy}{dx}":{pos:{x:1067,y:0},size:{width:56,height:75}},"\\frac {\\Delta y}{\\Delta x}":{pos:{x:1128,y:0},size:{width:56,height:75}},"\\frac {\\delta y}{\\delta x}":{pos:{x:1189,y:0},size:{width:56,height:75}},"\\frac \\pi 2":{pos:{x:1250,y:0},size:{width:56,height:75}},"\\placeholder^\\placeholder":{pos:{x:1311,y:0},size:{width:56,height:75}},"\\placeholder^\\placeholder_\\placeholder":{pos:{x:1372,y:0},size:{width:56,height:75}},"\\placeholder_\\placeholder":{pos:{x:1433,y:0},size:{width:56,height:75}},"{^\\placeholder_\\placeholder\\placeholder}":{pos:{x:1494,y:0},size:{width:56,height:75}},"e^{-i\\omega t}":{pos:{x:1555,y:0},size:{width:56,height:75}},"x^2":{pos:{x:1616,y:0},size:{width:56,height:75}},"{}^n_1Y":{pos:{x:1677,y:0},size:{width:56,height:75}},"\\sqrt \\placeholder":{pos:{x:1738,y:0},size:{width:56,height:75}},"\\sqrt [\\placeholder] \\placeholder":{pos:{x:1799,y:0},size:{width:56,height:75}},"\\sqrt [2] \\placeholder":{pos:{x:1860,y:0},size:{width:56,height:75}},"\\sqrt [3] \\placeholder":{pos:{x:1921,y:0},size:{width:56,height:75}},"\\frac {-b\\pm\\sqrt{b^2-4ac}}{2a}":{pos:{x:1982,y:0},size:{width:137,height:75}},"\\sqrt {a^2+b^2}":{pos:{x:2124,y:0},size:{width:137,height:75}},"\\int \\placeholder":{pos:{x:2266,y:0},size:{width:56,height:75}},"\\int^\\placeholder_\\placeholder\\placeholder":{pos:{x:2327,y:0},size:{width:56,height:75}},"\\iint\\placeholder":{pos:{x:2388,y:0},size:{width:56,height:75}},"\\iint^\\placeholder_\\placeholder\\placeholder":{pos:{x:2449,y:0},size:{width:56,height:75}},"\\iiint\\placeholder":{pos:{x:2510,y:0},size:{width:56,height:75}},"\\iiint^\\placeholder_\\placeholder\\placeholder":{pos:{x:2571,y:0},size:{width:56,height:75}},"\\sum\\placeholder":{pos:{x:2632,y:0},size:{width:56,height:75}},"\\sum^\\placeholder_\\placeholder\\placeholder":{pos:{x:2693,y:0},size:{width:56,height:75}},"\\sum_\\placeholder\\placeholder":{pos:{x:2754,y:0},size:{width:56,height:75}},"\\left(\\placeholder\\right)":{pos:{x:2815,y:0},size:{width:56,height:75}},"\\left[\\placeholder\\right]":{pos:{x:2876,y:0},size:{width:56,height:75}},"\\left\\{\\placeholder\\right\\}":{pos:{x:2937,y:0},size:{width:56,height:75}},"\\left|\\placeholder\\right|":{pos:{x:2998,y:0},size:{width:56,height:75}},"\\sin\\placeholder":{pos:{x:3059,y:0},size:{width:56,height:75}},"\\cos\\placeholder":{pos:{x:3120,y:0},size:{width:56,height:75}},"\\tan\\placeholder":{pos:{x:3181,y:0},size:{width:56,height:75}},"\\csc\\placeholder":{pos:{x:3242,y:0},size:{width:56,height:75}},"\\sec\\placeholder":{pos:{x:3303,y:0},size:{width:56,height:75}},"\\cot\\placeholder":{pos:{x:3364,y:0},size:{width:56,height:75}},"\\sin\\theta":{pos:{x:3425,y:0},size:{width:56,height:75}},"\\cos{2x}":{pos:{x:3486,y:0},size:{width:56,height:75}},"\\tan\\theta=\\frac {\\sin\\theta}{\\cos\\theta}":{pos:{x:3547,y:0},size:{width:137,height:75}}}}},b[34]={value:function(){function a(a){var b=[],c=a.path,d=a.values;return e.Utils.each(d,function(a){var d=a,e=a;"string"!=typeof a?(d=a.img,e=a.key):e="\\"+a,b.push({item:{show:""+c+d.toLowerCase()+".png",val:e}})}),b}var c=b.r(41),d=b.r(40),e=b.r(20),f=[{type:c.DRAPDOWN_BOX,options:{button:{label:"\u9884\u8bbe
                                                                                          ",className:"yushe-btn",icon:"assets/images/toolbar/button/fx.png",iconSize:{w:40}},box:{width:367,group:[{title:"\u9884\u8bbe\u516c\u5f0f",items:[{title:"\u9884\u8bbe\u516c\u5f0f",content:[{label:"\u4e8c\u6b21\u516c\u5f0f",item:{show:"assets/images/toolbar/ys/1.png",val:"x=\\frac {-b\\pm\\sqrt {b^2-4ac}}{2a}"}},{label:"\u4e8c\u9879\u5f0f\u5b9a\u7406",item:{show:"assets/images/toolbar/ys/2.png",val:"{\\left(x+a\\right)}^2=\\sum^n_{k=0}{\\left(^n_k\\right)x^ka^{n-k}}"}},{label:"\u52fe\u80a1\u5b9a\u7406",item:{show:"assets/images/toolbar/ys/3.png",val:"a^2+b^2=c^2"}}]}]}]}}},{type:c.DELIMITER},{type:c.AREA,options:{box:{fixOffset:!0,width:527,type:d.OVERLAP,group:[{title:"\u57fa\u7840\u6570\u5b66",items:[]},{title:"\u5e0c\u814a\u5b57\u6bcd",items:[]},{title:"\u6c42\u53cd\u5173\u7cfb\u8fd0\u7b97\u7b26",items:[]},{title:"\u5b57\u6bcd\u7c7b\u7b26\u53f7",items:[]},{title:"\u7bad\u5934",items:[]},{title:"\u624b\u5199\u4f53",items:[]}]}}},{type:c.DELIMITER},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u5206\u6570
                                                                                          ",icon:"assets/images/toolbar/button/frac.png"},box:{width:332,group:[{title:"\u5206\u6570",items:[{title:"\u5206\u6570",content:[{item:{show:"assets/images/toolbar/frac/1.png",val:"\\frac \\placeholder\\placeholder"}},{item:{show:"assets/images/toolbar/frac/2.png",val:"{\\placeholder/\\placeholder}"}}]},{title:"\u5e38\u7528\u5206\u6570",content:[{item:{show:"assets/images/toolbar/frac/c1.png",val:"\\frac {dy}{dx}"}},{item:{show:"assets/images/toolbar/frac/c2.png",val:"\\frac {\\Delta y}{\\Delta x}"}},{item:{show:"assets/images/toolbar/frac/c4.png",val:"\\frac {\\delta y}{\\delta x}"}},{item:{show:"assets/images/toolbar/frac/c5.png",val:"\\frac \\pi 2"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u4e0a\u4e0b\u6807
                                                                                          ",icon:"assets/images/toolbar/button/script.png"},box:{width:332,group:[{title:"\u4e0a\u6807\u548c\u4e0b\u6807",items:[{title:"\u4e0a\u6807\u548c\u4e0b\u6807",content:[{item:{show:"assets/images/toolbar/script/1.png",val:"\\placeholder^\\placeholder"}},{item:{show:"assets/images/toolbar/script/2.png",val:"\\placeholder_\\placeholder"}},{item:{show:"assets/images/toolbar/script/3.png",val:"\\placeholder^\\placeholder_\\placeholder"}},{item:{show:"assets/images/toolbar/script/4.png",val:"{^\\placeholder_\\placeholder\\placeholder}"}}]},{title:"\u5e38\u7528\u7684\u4e0a\u6807\u548c\u4e0b\u6807",content:[{item:{show:"assets/images/toolbar/script/c1.png",val:"e^{-i\\omega t}"}},{item:{show:"assets/images/toolbar/script/c2.png",val:"x^2"}},{item:{show:"assets/images/toolbar/script/c3.png",val:"{}^n_1Y"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u6839\u5f0f
                                                                                          ",icon:"assets/images/toolbar/button/sqrt.png"},box:{width:342,group:[{title:"\u6839\u5f0f",items:[{title:"\u6839\u5f0f",content:[{item:{show:"assets/images/toolbar/sqrt/1.png",val:"\\sqrt \\placeholder"}},{item:{show:"assets/images/toolbar/sqrt/2.png",val:"\\sqrt [\\placeholder] \\placeholder"}},{item:{show:"assets/images/toolbar/sqrt/3.png",val:"\\sqrt [2] \\placeholder"}},{item:{show:"assets/images/toolbar/sqrt/4.png",val:"\\sqrt [3] \\placeholder"}}]},{title:"\u5e38\u7528\u6839\u5f0f",content:[{item:{show:"assets/images/toolbar/sqrt/c1.png",val:"\\frac {-b\\pm\\sqrt{b^2-4ac}}{2a}"}},{item:{show:"assets/images/toolbar/sqrt/c2.png",val:"\\sqrt {a^2+b^2}"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u79ef\u5206
                                                                                          ",icon:"assets/images/toolbar/button/int.png"},box:{width:332,group:[{title:"\u79ef\u5206",items:[{title:"\u79ef\u5206",content:[{item:{show:"assets/images/toolbar/int/1.png",val:"\\int \\placeholder"}},{item:{show:"assets/images/toolbar/int/2.png",val:"\\int^\\placeholder_\\placeholder\\placeholder"}},{item:{show:"assets/images/toolbar/int/3.png",val:"\\iint\\placeholder"}},{item:{show:"assets/images/toolbar/int/4.png",val:"\\iint^\\placeholder_\\placeholder\\placeholder"}},{item:{show:"assets/images/toolbar/int/5.png",val:"\\iiint\\placeholder"}},{item:{show:"assets/images/toolbar/int/6.png",val:"\\iiint^\\placeholder_\\placeholder\\placeholder"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u5927\u578b
                                                                                          \u8fd0\u7b97\u7b26",icon:"assets/images/toolbar/button/sum.png"},box:{width:332,group:[{title:"\u6c42\u548c",items:[{title:"\u6c42\u548c",content:[{item:{show:"assets/images/toolbar/large/1.png",val:"\\sum\\placeholder"}},{item:{show:"assets/images/toolbar/large/2.png",val:"\\sum^\\placeholder_\\placeholder\\placeholder"}},{item:{show:"assets/images/toolbar/large/3.png",val:"\\sum_\\placeholder\\placeholder"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u62ec\u53f7
                                                                                          ",icon:"assets/images/toolbar/button/brackets.png"},box:{width:332,group:[{title:"\u65b9\u62ec\u53f7",items:[{title:"\u65b9\u62ec\u53f7",content:[{item:{show:"assets/images/toolbar/brackets/1.png",val:"\\left(\\placeholder\\right)"}},{item:{show:"assets/images/toolbar/brackets/2.png",val:"\\left[\\placeholder\\right]"}},{item:{show:"assets/images/toolbar/brackets/3.png",val:"\\left\\{\\placeholder\\right\\}"}},{item:{show:"assets/images/toolbar/brackets/4.png",val:"\\left|\\placeholder\\right|"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u51fd\u6570
                                                                                          ",icon:"assets/images/toolbar/button/sin.png"},box:{width:340,group:[{title:"\u51fd\u6570",items:[{title:"\u4e09\u89d2\u51fd\u6570",content:[{item:{show:"assets/images/toolbar/func/1.png",val:"\\sin\\placeholder"}},{item:{show:"assets/images/toolbar/func/2.png",val:"\\cos\\placeholder"}},{item:{show:"assets/images/toolbar/func/3.png",val:"\\tan\\placeholder"}},{item:{show:"assets/images/toolbar/func/4.png",val:"\\csc\\placeholder"}},{item:{show:"assets/images/toolbar/func/5.png",val:"\\sec\\placeholder"}},{item:{show:"assets/images/toolbar/func/6.png",val:"\\cot\\placeholder"}}]},{title:"\u5e38\u7528\u51fd\u6570",content:[{item:{show:"assets/images/toolbar/func/c1.png",val:"\\sin\\theta"}},{item:{show:"assets/images/toolbar/func/c2.png",val:"\\sin{2x}"}},{item:{show:"assets/images/toolbar/func/c3.png",val:"\\tan\\theta=\\frac {\\sin\\theta}{\\cos\\theta}"}}]}]}]}}}]; +return function(){var b=["pm","infty",{key:"=",img:"eq"},"sim","times","div",{key:"!",img:"tanhao"},{key:"<",img:"lt"},"ll",{key:">",img:"gt"},"gg","leq","geq","mp","cong","equiv","propto","approx","forall","partial","surd","cup","cap","varnothing",{key:"%",img:"baifenhao"},"circ","exists","nexists","in","ni","gets","uparrow","to","downarrow","leftrightarrow","therefore","because",{key:"+",img:"plus"},{key:"-",img:"minus"},"neg","ast","cdot","vdots","ddots","aleph","beth","blacksquare"],c=f[2].options.box.group[0].items;c.push({title:"\u57fa\u7840\u6570\u5b66",content:a({path:"assets/images/toolbar/char/math/",values:b})})}(),function(){var b=[{title:"\u5c0f\u5199",values:["alpha","beta","gamma","delta","epsilon","zeta","eta","theta","iota","kappa","lambda","mu","nu","xi","omicron","pi","rho","sigma","tau","upsilon","phi","chi","psi","omega"]},{title:"\u5927\u5199",values:["Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega"]},{title:"\u53d8\u4f53",values:["digamma","varepsilon","varkappa","varphi","varpi","varrho","varsigma","vartheta"]}],c=f[2].options.box.group[1].items;c.push({title:b[0].title,content:a({path:"assets/images/toolbar/char/greek/lower/",values:b[0].values})}),c.push({title:b[1].title,content:a({path:"assets/images/toolbar/char/greek/upper/",values:b[1].values})}),c.push({title:b[2].title,content:a({path:"assets/images/toolbar/char/greek/misc/",values:b[2].values})})}(),function(){var b=[{title:"\u6c42\u53cd\u5173\u7cfb\u8fd0\u7b97\u7b26",values:["neq","nless","ngtr","nleq","ngeq","nsim","lneqq","gneqq","nprec","nsucc","notin","nsubseteq","nsupseteq","subsetneq","supsetneq","lnsim","gnsim","precnsim","succnsim","ntriangleleft","ntriangleright","ntrianglelefteq","ntrianglerighteq","nmid","nparallel","nvdash",{key:"\\nVdash",img:"nvdash-1"},{key:"\\nvDash",img:"nvdash-2"},{key:"\\nVDash",img:"nvdash-3"},"nexists"]}],c=f[2].options.box.group[2].items;c.push({title:b[0].title,content:a({path:"assets/images/toolbar/char/not/",values:b[0].values})})}(),function(){var b=["aleph","beth","daleth","gimel","complement","ell","eth","hbar","hslash","mho","partial","wp","circledS","Bbbk","Finv","Game","Im","Re"],c=f[2].options.box.group[3].items;c.push({title:"\u5b57\u6bcd\u7c7b\u7b26\u53f7",content:a({path:"assets/images/toolbar/alphabetic/",values:b})})}(),function(){var b=["gets","to","uparrow","downarrow","leftrightarrow","updownarrow",{key:"\\Leftarrow",img:"u-leftarrow"},{key:"\\Rightarrow",img:"u-rightarrow"},{key:"\\Uparrow",img:"u-uparrow"},{key:"\\Downarrow",img:"u-downarrow"},{key:"\\Leftrightarrow",img:"u-leftrightarrow"},{key:"\\Updownarrow",img:"u-updownarrow"},"longleftarrow","longrightarrow","longleftrightarrow",{key:"\\Longleftarrow",img:"u-longleftarrow"},{key:"\\Longrightarrow",img:"u-longrightarrow"},{key:"\\Longleftrightarrow",img:"u-longleftrightarrow"},"nearrow","nwarrow","searrow","swarrow","nleftarrow","nrightarrow",{key:"\\nLeftarrow",img:"u-nleftarrow"},{key:"\\nRightarrow",img:"u-nrightarrow"},{key:"\\nLeftrightarrow",img:"u-nleftrightarrow"},"leftharpoonup","leftharpoondown","rightharpoonup","rightharpoondown","upharpoonleft","upharpoonright","downharpoonleft","downharpoonright","leftrightharpoons","rightleftharpoons","leftleftarrows","rightrightarrows","upuparrows","downdownarrows","leftrightarrows","rightleftarrows","looparrowleft","looparrowright","leftarrowtail","rightarrowtail",{key:"\\Lsh",img:"u-lsh"},{key:"\\Rsh",img:"u-rsh"},{key:"\\Lleftarrow",img:"u-lleftarrow"},{key:"\\Rrightarrow",img:"u-rrightarrow"},"curvearrowleft","curvearrowright","circlearrowleft","circlearrowright","multimap","leftrightsquigarrow","twoheadleftarrow","twoheadrightarrow","rightsquigarrow"],c=f[2].options.box.group[4].items;c.push({title:"\u7bad\u5934",content:a({path:"assets/images/toolbar/arrow/",values:b})})}(),function(){var b=[{title:"\u624b\u5199\u4f53",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]},{title:"\u82b1\u4f53",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]},{title:"\u53cc\u7ebf",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]},{title:"\u7f57\u9a6c",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]}],c=f[2].options.box.group[5].items;e.Utils.each(b[0].values,function(a,c){b[0].values[c]={key:"\\mathcal{"+a+"}",img:a.toLowerCase()}}),e.Utils.each(b[1].values,function(a,c){b[1].values[c]={key:"\\mathfrak{"+a+"}",img:a.replace(/[A-Z]/,function(a){return"u"+a.toLowerCase()})}}),e.Utils.each(b[2].values,function(a,c){b[2].values[c]={key:"\\mathbb{"+a+"}",img:a.toLowerCase()}}),e.Utils.each(b[3].values,function(a,c){b[3].values[c]={key:"\\mathrm{"+a+"}",img:a.replace(/[A-Z]/,function(a){return"u"+a.toLowerCase()})}}),c.push({title:b[0].title,content:a({path:"assets/images/toolbar/char/cal/",values:b[0].values})}),c.push({title:b[1].title,content:a({path:"assets/images/toolbar/char/frak/",values:b[1].values})}),c.push({title:b[2].title,content:a({path:"assets/images/toolbar/char/bb/",values:b[2].values})}),c.push({title:b[3].title,content:a({path:"assets/images/toolbar/char/rm/",values:b[3].values})})}(),window.iconConfig=f,f}},b[35]={value:function(){function a(a,b){var c=[];return g.Utils.each(a,function(a){a.length>1&&(a="\\"+a),c.push({key:a,img:b,pos:e[a]})}),c}var c=b.r(41),d=b.r(40),e=b.r(30),f=b.r(33),g=b.r(20),h=[{type:c.DRAPDOWN_BOX,options:{button:{label:"\u9884\u8bbe
                                                                                          ",className:"yushe-btn",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:0,y:0},iconSize:{w:40}},box:{width:367,group:[{title:"\u9884\u8bbe\u516c\u5f0f",items:[{title:"\u9884\u8bbe\u516c\u5f0f",content:[{label:"\u4e8c\u6b21\u516c\u5f0f",item:{val:"x=\\frac {-b\\pm\\sqrt {b^2-4ac}}{2a}"}},{label:"\u4e8c\u9879\u5f0f\u5b9a\u7406",item:{val:"{\\left(x+a\\right)}^2=\\sum^n_{k=0}{\\left(^n_k\\right)x^ka^{n-k}}"}},{label:"\u52fe\u80a1\u5b9a\u7406",item:{val:"a^2+b^2=c^2"}}]}]}]}}},{type:c.DELIMITER},{type:c.AREA,options:{box:{fixOffset:!0,width:527,type:d.OVERLAP,group:[{title:"\u57fa\u7840\u6570\u5b66",items:[]},{title:"\u5e0c\u814a\u5b57\u6bcd",items:[]},{title:"\u6c42\u53cd\u5173\u7cfb\u8fd0\u7b97\u7b26",items:[]},{title:"\u5b57\u6bcd\u7c7b\u7b26\u53f7",items:[]},{title:"\u7bad\u5934",items:[]},{title:"\u624b\u5199\u4f53",items:[]}]}}},{type:c.DELIMITER},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u5206\u6570
                                                                                          ",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:45,y:0}},box:{width:332,group:[{title:"\u5206\u6570",items:[{title:"\u5206\u6570",content:[{item:{val:"\\frac \\placeholder\\placeholder"}},{item:{val:"{\\placeholder/\\placeholder}"}}]},{title:"\u5e38\u7528\u5206\u6570",content:[{item:{val:"\\frac {dy}{dx}"}},{item:{val:"\\frac {\\Delta y}{\\Delta x}"}},{item:{val:"\\frac {\\delta y}{\\delta x}"}},{item:{val:"\\frac \\pi 2"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u4e0a\u4e0b\u6807
                                                                                          ",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:82,y:0}},box:{width:332,group:[{title:"\u4e0a\u6807\u548c\u4e0b\u6807",items:[{title:"\u4e0a\u6807\u548c\u4e0b\u6807",content:[{item:{val:"\\placeholder^\\placeholder"}},{item:{val:"\\placeholder_\\placeholder"}},{item:{val:"\\placeholder^\\placeholder_\\placeholder"}},{item:{val:"{^\\placeholder_\\placeholder\\placeholder}"}}]},{title:"\u5e38\u7528\u7684\u4e0a\u6807\u548c\u4e0b\u6807",content:[{item:{val:"e^{-i\\omega t}"}},{item:{val:"x^2"}},{item:{val:"{}^n_1Y"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u6839\u5f0f
                                                                                          ",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:119,y:0}},box:{width:342,group:[{title:"\u6839\u5f0f",items:[{title:"\u6839\u5f0f",content:[{item:{val:"\\sqrt \\placeholder"}},{item:{val:"\\sqrt [\\placeholder] \\placeholder"}},{item:{val:"\\sqrt [2] \\placeholder"}},{item:{val:"\\sqrt [3] \\placeholder"}}]},{title:"\u5e38\u7528\u6839\u5f0f",content:[{item:{val:"\\frac {-b\\pm\\sqrt{b^2-4ac}}{2a}"}},{item:{val:"\\sqrt {a^2+b^2}"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u79ef\u5206
                                                                                          ",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:156,y:0}},box:{width:332,group:[{title:"\u79ef\u5206",items:[{title:"\u79ef\u5206",content:[{item:{val:"\\int \\placeholder"}},{item:{val:"\\int^\\placeholder_\\placeholder\\placeholder"}},{item:{val:"\\iint\\placeholder"}},{item:{val:"\\iint^\\placeholder_\\placeholder\\placeholder"}},{item:{val:"\\iiint\\placeholder"}},{item:{val:"\\iiint^\\placeholder_\\placeholder\\placeholder"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u5927\u578b
                                                                                          \u8fd0\u7b97\u7b26",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:193,y:0}},box:{width:332,group:[{title:"\u6c42\u548c",items:[{title:"\u6c42\u548c",content:[{item:{val:"\\sum\\placeholder"}},{item:{val:"\\sum^\\placeholder_\\placeholder\\placeholder"}},{item:{val:"\\sum_\\placeholder\\placeholder"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u62ec\u53f7
                                                                                          ",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:230,y:0}},box:{width:332,group:[{title:"\u65b9\u62ec\u53f7",items:[{title:"\u65b9\u62ec\u53f7",content:[{item:{val:"\\left(\\placeholder\\right)"}},{item:{val:"\\left[\\placeholder\\right]"}},{item:{val:"\\left\\{\\placeholder\\right\\}"}},{item:{val:"\\left|\\placeholder\\right|"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u51fd\u6570
                                                                                          ",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:267,y:0}},box:{width:340,group:[{title:"\u51fd\u6570",items:[{title:"\u4e09\u89d2\u51fd\u6570",content:[{item:{val:"\\sin\\placeholder"}},{item:{val:"\\cos\\placeholder"}},{item:{val:"\\tan\\placeholder"}},{item:{val:"\\csc\\placeholder"}},{item:{val:"\\sec\\placeholder"}},{item:{val:"\\cot\\placeholder"}}]},{title:"\u5e38\u7528\u51fd\u6570",content:[{item:{val:"\\sin\\theta"}},{item:{val:"\\cos{2x}"}},{item:{val:"\\tan\\theta=\\frac {\\sin\\theta}{\\cos\\theta}"}}]}]}]}}}];return function(){var a=[],b="kityformula/assets/images/toolbar/other.png",d=[];g.Utils.each(h,function(b){b.type!==c.DELIMITER&&(b=b.options.box.group,a=a.concat(b))}),g.Utils.each(a,function(a){a=a.items;for(var b=0,c=a.length;c>b;b++)d=d.concat(a[b].content)}),g.Utils.each(d,function(a){var c=f[a.item.val];c&&(a.item.img=b,a.item.pos=c.pos,a.item.size=c.size)})}(),function(){var b=["pm","infty","=","sim","times","div","!","<","ll",">","gg","leq","geq","mp","cong","equiv","propto","approx","forall","partial","surd","cup","cap","varnothing","%","circ","exists","nexists","in","ni","gets","uparrow","to","downarrow","leftrightarrow","therefore","because","+","-","neg","ast","cdot","vdots","aleph","beth","blacksquare"],c=h[2].options.box.group[0].items;c.push({title:"\u57fa\u7840\u6570\u5b66",content:a(b,"kityformula/assets/images/toolbar/char.png")})}(),function(){var b=[{title:"\u5c0f\u5199",values:["alpha","beta","gamma","delta","epsilon","zeta","eta","theta","iota","kappa","lambda","mu","nu","xi","omicron","pi","rho","sigma","tau","upsilon","phi","chi","psi","omega"]},{title:"\u5927\u5199",values:["Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega"]},{title:"\u53d8\u4f53",values:["digamma","varepsilon","varkappa","varphi","varpi","varrho","varsigma","vartheta"]}],c=h[2].options.box.group[1].items;c.push({title:b[0].title,content:a(b[0].values,"kityformula/assets/images/toolbar/char.png")}),c.push({title:b[1].title,content:a(b[1].values,"kityformula/assets/images/toolbar/char.png")}),c.push({title:b[2].title,content:a(b[2].values,"kityformula/assets/images/toolbar/char.png")})}(),function(){var b=[{title:"\u6c42\u53cd\u5173\u7cfb\u8fd0\u7b97\u7b26",values:["neq","nless","ngtr","nleq","ngeq","nsim","lneqq","gneqq","nprec","nsucc","notin","nsubseteq","nsupseteq","subsetneq","supsetneq","lnsim","gnsim","precnsim","succnsim","ntriangleleft","ntriangleright","ntrianglelefteq","ntrianglerighteq","nmid","nparallel","nvdash","nVdash","nvDash","nVDash","nexists"]}],c=h[2].options.box.group[2].items;c.push({title:b[0].title,content:a(b[0].values,"kityformula/assets/images/toolbar/char.png")})}(),function(){var b=["aleph","beth","daleth","gimel","complement","ell","eth","hbar","hslash","mho","partial","wp","circledS","Bbbk","Finv","Game","Im","Re"],c=h[2].options.box.group[3].items;c.push({title:"\u5b57\u6bcd\u7c7b\u7b26\u53f7",content:a(b,"kityformula/assets/images/toolbar/char.png")})}(),function(){var b=["gets","to","uparrow","downarrow","leftrightarrow","updownarrow","Leftarrow","Rightarrow","Uparrow","Downarrow","Leftrightarrow","Updownarrow","longleftarrow","longrightarrow","longleftrightarrow","Longleftarrow","Longrightarrow","Longleftrightarrow","nearrow","nwarrow","searrow","swarrow","nleftarrow","nrightarrow","nLeftarrow","nRightarrow","nLeftrightarrow","leftharpoonup","leftharpoondown","rightharpoonup","rightharpoondown","upharpoonleft","upharpoonright","downharpoonleft","downharpoonright","leftrightharpoons","rightleftharpoons","leftleftarrows","rightrightarrows","upuparrows","downdownarrows","leftrightarrows","rightleftarrows","looparrowleft","looparrowright","leftarrowtail","rightarrowtail","Lsh","Rsh","Lleftarrow","Rrightarrow","curvearrowleft","curvearrowright","circlearrowleft","circlearrowright","multimap","leftrightsquigarrow","twoheadleftarrow","twoheadrightarrow","rightsquigarrow"],c=h[2].options.box.group[4].items;c.push({title:"\u7bad\u5934",content:a(b,"kityformula/assets/images/toolbar/char.png")})}(),function(){var b=[{title:"\u624b\u5199\u4f53",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]},{title:"\u82b1\u4f53",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]},{title:"\u53cc\u7ebf",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]},{title:"\u7f57\u9a6c",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]}],c=h[2].options.box.group[5].items;g.Utils.each(b[0].values,function(a,c){b[0].values[c]="mathcal{"+a+"}"}),g.Utils.each(b[1].values,function(a,c){b[1].values[c]="mathfrak{"+a+"}"}),g.Utils.each(b[2].values,function(a,c){b[2].values[c]="mathbb{"+a+"}"}),g.Utils.each(b[3].values,function(a,c){b[3].values[c]="mathrm{"+a+"}"}),c.push({title:b[0].title,content:a(b[0].values,"kityformula/assets/images/toolbar/char.png")}),c.push({title:b[1].title,content:a(b[1].values,"kityformula/assets/images/toolbar/char.png")}),c.push({title:b[2].title,content:a(b[2].values,"kityformula/assets/images/toolbar/char.png")}),c.push({title:b[3].title,content:a(b[3].values,"kityformula/assets/images/toolbar/char.png")})}(),h}},b[36]={value:function(){function a(a,b,f){switch(a){case i.DRAPDOWN_BOX:return c(b,f);case i.DELIMITER:return d(b);case i.AREA:return e(b,f)}}function c(a,b){return new g.DrapdownBox(a,b)}function d(a){return new g.Delimiter(a)}function e(a,b){return new g.Area(a,b)}var f=b.r(20),g=b.r(48),h=b.r(47),i=b.r(41),j=f.createClass("Tollbar",{constructor:function(a,b,c){this.kfEditor=b,this.uiComponent=a,this.elementList=c,this.elements=[],this.initToolbarElements(),this.initServices(),this.initEvent()},initServices:function(){this.kfEditor.registerService("ui.toolbar.disable",this,{disableToolbar:this.disableToolbar}),this.kfEditor.registerService("ui.toolbar.enable",this,{enableToolbar:this.enableToolbar}),this.kfEditor.registerService("ui.toolbar.close",this,{closeToolbar:this.closeToolbar})},initEvent:function(){var a=this;h.on(this.uiComponent.toolbarContainer,"mousedown",function(a){a.preventDefault()}),h.on(this.uiComponent.toolbarContainer,"mousewheel",function(a){a.preventDefault()}),h.on(this.kfEditor.getContainer(),"mousedown",function(){a.notify("closeAll")}),h.subscribe("data.select",function(b){a.insertSource(b)})},insertSource:function(a){this.kfEditor.requestService("control.insert.string",a)},disableToolbar:function(){f.Utils.each(this.elements,function(a){a.disable&&a.disable()})},enableToolbar:function(){f.Utils.each(this.elements,function(a){a.enable&&a.enable()})},getContainer:function(){return this.kfEditor.requestService("ui.get.canvas.container")},closeToolbar:function(){this.closeElement()},notify:function(a){switch(a){case"closeAll":case"closeOther":return void this.closeElement(arguments[1])}},closeElement:function(a){f.Utils.each(this.elements,function(b){b!=a&&b.hide&&b.hide()})},initToolbarElements:function(){var b=this.elements,c=this.uiComponent.toolbarContainer.ownerDocument,d=this;f.Utils.each(this.elementList,function(e){var f=a(e.type,c,e.options);b.push(f),d.appendElement(f)})},appendElement:function(a){a.setToolbar(this),a.attachTo(this.uiComponent.toolbarContainer)}});return j}},b[37]={value:function(){var a=b.r(20),c="kf-editor-ui-",d=66,e=b.r(47),f=b.r(38),g=a.createClass("Area",{constructor:function(a,b){this.options=b,this.doc=a,this.toolbar=null,this.disabled=!0,this.panelIndex=0,this.maxPanelIndex=0,this.currentItemCount=0,this.lineMaxCount=9,this.element=this.createArea(),this.container=this.createContainer(),this.panel=this.createPanel(),this.buttonContainer=this.createButtonContainer(),this.button=this.createButton(),this.mountPoint=this.createMountPoint(),this.moveDownButton=this.createMoveDownButton(),this.moveUpButton=this.createMoveUpButton(),this.boxObject=this.createBox(),this.mergeElement(),this.mount(),this.setListener(),this.initEvent()},initEvent:function(){var a=this;e.on(this.button,"mousedown",function(b){b.preventDefault(),b.stopPropagation(),1!==b.which||a.disabled||(a.showMount(),a.toolbar.notify("closeOther",a))}),e.on(this.moveDownButton,"mousedown",function(b){b.preventDefault(),b.stopPropagation(),1!==b.which||a.disabled||(a.nextPanel(),a.toolbar.notify("closeOther",a))}),e.on(this.moveUpButton,"mousedown",function(b){b.preventDefault(),b.stopPropagation(),1!==b.which||a.disabled||(a.prevPanel(),a.toolbar.notify("closeOther",a))}),e.delegate(this.container,".kf-editor-ui-area-item","mousedown",function(b){b.preventDefault(),1!==b.which||a.disabled||e.publish("data.select",this.getAttribute("data-value"))}),this.boxObject.initEvent()},disable:function(){this.disabled=!0,this.boxObject.disable(),e.getClassList(this.element).remove(c+"enabled")},enable:function(){this.disabled=!1,this.boxObject.enable(),e.getClassList(this.element).add(c+"enabled")},setListener:function(){var a=this;this.boxObject.setSelectHandler(function(b){e.publish("data.select",b),a.hide()}),this.boxObject.setChangeHandler(function(){a.updateContent()})},createArea:function(){var a=e.ele(this.doc,"div",{className:c+"area"});return"width"in this.options&&(a.style.width=this.options.width+"px"),a},checkMaxPanelIndex:function(){this.maxPanelIndex=Math.ceil(this.currentItemCount/this.lineMaxCount/2)},updateContent:function(){var b=this.boxObject.getOverlapContent(),d=0,e=null,f=0,g=0,h=this.lineMaxCount,i=[];this.panel.innerHTML="",a.Utils.each(b,function(b){var j=b.content;a.Utils.each(j,function(a){f=Math.floor(d/h),g=d%h,d++,e="top: "+(33*f+5)+"px; left: "+(32*g+5)+"px;",i.push('
                                                                                          ')})}),this.currentItemCount=d,this.panelIndex=0,this.panel.style.top=0,this.panel.innerHTML=i.join(""),this.checkMaxPanelIndex(),this.updatePanelButtonState()},mount:function(){this.boxObject.mountTo(this.mountPoint)},showMount:function(){this.mountPoint.style.display="block",this.boxObject.updateSize()},hideMount:function(){this.mountPoint.style.display="none"},hide:function(){this.hideMount(),this.boxObject.hide()},createButton:function(){return e.ele(this.doc,"div",{className:c+"area-button"})},createMoveDownButton:function(){return e.ele(this.doc,"div",{className:c+"movedown-button",content:""})},createMoveUpButton:function(){return e.ele(this.doc,"div",{className:c+"moveup-button",content:""})},createMountPoint:function(){return e.ele(this.doc,"div",{className:c+"area-mount"})},createBox:function(){return new f(this.doc,this.options.box)},createContainer:function(){return e.ele(this.doc,"div",{className:c+"area-container"})},createPanel:function(){return e.ele(this.doc,"div",{className:c+"area-panel"})},createButtonContainer:function(){return e.ele(this.doc,"div",{className:c+"area-button-container"})},mergeElement:function(){this.buttonContainer.appendChild(this.moveUpButton),this.buttonContainer.appendChild(this.moveDownButton),this.buttonContainer.appendChild(this.button),this.container.appendChild(this.panel),this.element.appendChild(this.container),this.element.appendChild(this.buttonContainer),this.element.appendChild(this.mountPoint)},disablePanelUp:function(){this.disabledUp=!0,e.getClassList(this.moveUpButton).add("kf-editor-ui-disabled")},enablePanelUp:function(){this.disabledUp=!1,e.getClassList(this.moveUpButton).remove("kf-editor-ui-disabled")},disablePanelDown:function(){this.disabledDown=!0,e.getClassList(this.moveDownButton).add("kf-editor-ui-disabled")},enablePanelDown:function(){this.disabledDown=!1,e.getClassList(this.moveDownButton).remove("kf-editor-ui-disabled")},updatePanelButtonState:function(){0===this.panelIndex?this.disablePanelUp():this.enablePanelUp(),this.panelIndex+1>=this.maxPanelIndex?this.disablePanelDown():this.enablePanelDown()},nextPanel:function(){this.disabledDown||this.panelIndex+1>=this.maxPanelIndex||(this.panelIndex++,this.panel.style.top=-this.panelIndex*d+"px",this.updatePanelButtonState())},prevPanel:function(){this.disabledUp||0!==this.panelIndex&&(this.panelIndex--,this.panel.style.top=-this.panelIndex*d+"px",this.updatePanelButtonState())},setToolbar:function(a){this.toolbar=a,this.boxObject.setToolbar(a)},attachTo:function(a){a.appendChild(this.element),this.updateContent(),this.updatePanelButtonState()}});return g}},b[38]={value:function(){function a(a,b,c){var d=[];return h.Utils.each(b,function(b){d.push(new q(c,a,b))}),d}function c(a){return j.ele(a,"div",{className:i+"overlap-container"})}function d(a,b){return new m(a,{className:"overlap-button",label:"",fixOffset:b.fixOffset})}function e(a,b){return new n(a,b)}function f(a){return a.getBoundingClientRect()}function g(a){var b="background: url( "+a.img+" ) no-repeat ";return b+=-a.pos.x+"px ",b+=-a.pos.y+"px;",b+=" width: "+a.size.width+"px;",b+=" height: "+a.size.height+"px;"}var h=b.r(20),i="kf-editor-ui-",j=b.r(47),k=b.r(40),l=b.r(42),m=b.r(39),n=b.r(45),o=20,p=h.createClass("Box",{constructor:function(a,b){this.options=b,this.toolbar=null,this.options.type=this.options.type||k.DETACHED,this.doc=a,this.itemPanels=null,this.overlapButtonObject=null,this.overlapIndex=-1,this.element=this.createBox(),this.groupContainer=this.createGroupContainer(),this.itemGroups=this.createItemGroup(),this.mergeElement()},createBox:function(){var a=j.ele(this.doc,"div",{className:i+"box"});return"width"in this.options&&(a.style.width=this.options.width+"px"),a},setToolbar:function(a){this.toolbar=a,this.overlapButtonObject&&this.overlapButtonObject.setToolbar(a)},updateSize:function(){var a=j.getRectBox(this.toolbar.getContainer()),b=30,c=j.getRectBox(this.element);if(this.options.type===k.DETACHED){if(c.bottom<=a.bottom)return void(this.element.scrollTop=0);this.element.style.height=c.height-(c.bottom-a.bottom+b)+"px"}else{var d=this.getCurrentItemPanel(),e=null;if(d.scrollTop=0,c.bottom<=a.bottom)return;e=f(d),d.style.height=a.bottom-e.top-b+"px"}},initEvent:function(){var a="."+i+"box-item",b=this;j.delegate(this.groupContainer,a,"mousedown",function(a){a.preventDefault(),1===a.which&&b.onselectHandler&&b.onselectHandler(this.getAttribute("data-value"))}),j.on(this.element,"mousedown",function(a){a.stopPropagation(),a.preventDefault()}),j.on(this.element,"mousewheel",function(a){a.preventDefault(),a.stopPropagation(),b.scroll(a.originalEvent.wheelDelta)})},getNode:function(){return this.element},setSelectHandler:function(a){this.onselectHandler=a},scroll:function(a){0>a?this.scrollDown():(this.scrollUp(),this.element.scrollTop-=20)},scrollDown:function(){this.options.type===k.DETACHED?this.element.scrollTop+=o:this.getCurrentItemPanel().scrollTop+=o},scrollUp:function(){this.options.type===k.DETACHED?this.element.scrollTop-=o:this.getCurrentItemPanel().scrollTop-=o},setChangeHandler:function(a){this.onchangeHandler=a},onchangeHandler:function(){},createGroupContainer:function(){return j.ele(this.doc,"div",{className:i+"box-container"})},getPositionInfo:function(){return j.getRectBox(this.element)},createItemGroup:function(){var a=this.createGroup();switch(this.options.type){case k.DETACHED:return a.items[0];case k.OVERLAP:return this.createOverlapGroup(a)}return null},enable:function(){this.overlapButtonObject&&this.overlapButtonObject.enable()},disable:function(){this.overlapButtonObject&&this.overlapButtonObject.disable()},hide:function(){this.overlapButtonObject&&this.overlapButtonObject.hideMount()},getOverlapContent:function(){return this.options.type!==k.OVERLAP?null:this.options.group[this.overlapIndex].items},createOverlapGroup:function(a){var b=a.title,f=this,g=c(this.doc),k=d(this.doc,{fixOffset:this.options.fixOffset}),l=e(this.doc,{width:150,items:b}),m=j.ele(this.doc,"div",{className:i+"wrap-group"});return this.overlapButtonObject=k,k.mount(l),k.initEvent(),l.initEvent(),h.Utils.each(a.items,function(b,c){var d=m.cloneNode(!1);h.Utils.each(b,function(a){d.appendChild(a)}),a.items[c]=d}),this.itemPanels=a.items,l.setSelectHandler(function(c,d){f.overlapIndex=c,k.setLabel(b[c]),k.hideMount(),a.items[d].style.display="none",a.items[c].style.display="block",c!==d&&f.updateSize(),f.onchangeHandler(c)}),g.appendChild(k.getNode()),h.Utils.each(a.items,function(a,b){b>0&&(a.style.display="none"),g.appendChild(a)}),l.select(0),[g]},getCurrentItemPanel:function(){return this.itemPanels[this.overlapIndex]},getGroupList:function(){var a=[];return h.Utils.each(this.options.group,function(b){a.push(b.title)}),{width:150,items:a}},createGroup:function(){var b=this.doc,c=[],d={title:[],items:[]},e=null,f=null,g=k.DETACHED===this.options.type?l.BIG:l.SMALL,m=null;return e=j.ele(this.doc,"div",{className:i+"box-group"}),m=e.cloneNode(!1),m.className=i+"box-group-item-container",h.Utils.each(this.options.group,function(k){d.title.push(k.title||""),c=[],h.Utils.each(k.items,function(d){e=e.cloneNode(!1),m=m.cloneNode(!1),f=j.ele(b,"div",{className:i+"box-group-title",content:d.title}),e.appendChild(f),e.appendChild(m),h.Utils.each(a(b,d.content,g),function(a){a.appendTo(m)}),c.push(e)}),d.items.push(c)}),d},mergeElement:function(){var a=this.groupContainer;this.element.appendChild(a),h.Utils.each(this.itemGroups,function(b){a.appendChild(b)})},mountTo:function(a){a.appendChild(this.element)},appendTo:function(a){a.appendChild(this.element)}}),q=h.createClass("BoxItem",{constructor:function(a,b,c){this.type=a,this.doc=b,this.options=c,this.element=this.createItem(),this.labelNode=this.createLabel(),this.contentNode=this.createContent(),this.mergeElement()},getNode:function(){return this.element},createItem:function(){var a=j.ele(this.doc,"div",{className:i+"box-item"});return a},createLabel:function(){var a=null;if("label"in this.options)return a=j.ele(this.doc,"div",{className:i+"box-item-label",content:this.options.label})},getContent:function(){},createContent:function(){switch(this.type){case l.BIG:return this.createBigContent();case l.SMALL:return this.createSmallContent()}},createBigContent:function(){var a=this.doc,b=j.ele(a,"div",{className:i+"box-item-content"}),c=i+"box-item-val",d=this.options.item,e=null,f=g(d);return e=j.ele(a,"div",{className:c}),e.innerHTML='
                                                                                          ',this.element.setAttribute("data-value",d.val),b.appendChild(e),b},createSmallContent:function(){var a=this.doc,b=j.ele(a,"div",{className:i+"box-item-content"}),c=i+"box-item-val",d=this.options,e=null;return e=j.ele(a,"div",{className:c}),e.style.background="url( "+d.img+" )",e.style.backgroundPosition=-d.pos.x+"px "+-d.pos.y+"px",this.element.setAttribute("data-value",d.key),b.appendChild(e),b},mergeElement:function(){this.labelNode&&this.element.appendChild(this.labelNode),this.element.appendChild(this.contentNode)},appendTo:function(a){a.appendChild(this.element)}});return p}},b[39]={value:function(){function a(a){var b="url( "+a.src+" ) no-repeat ";return b+=-a.x+"px ",b+=-a.y+"px"}var c=b.r(20),d="kf-editor-ui-",e=7,f={iconSize:{w:32,h:32}},g=b.r(47),h=c.createClass("Button",{constructor:function(a,b){this.options=c.Utils.extend({},f,b),this.eventState=!1,this.toolbar=null,this.displayState=!1,this.fixOffset=b.fixOffset||!1,this.doc=a,this.element=this.createButton(),this.disabled=!0,this.mountElement=null,this.icon=this.createIcon(),this.label=this.createLabel(),this.sign=this.createSign(),this.mountPoint=this.createMountPoint(),this.mergeElement()},initEvent:function(){var a=this;this.eventState||(this.eventState=!0,g.on(this.element,"mousedown",function(b){b.preventDefault(),b.stopPropagation(),1===b.which&&(a.disabled||(a.toggleSelect(),a.toggleMountElement()))}))},setToolbar:function(a){this.toolbar=a},toggleMountElement:function(){this.displayState?this.hideMount():this.showMount()},setLabel:function(a){var b="";this.sign&&(b='
                                                                                          '),this.label.innerHTML=a+b},toggleSelect:function(){g.getClassList(this.element).toggle(d+"button-in")},unselect:function(){g.getClassList(this.element).remove(d+"button-in")},select:function(){g.getClassList(this.element).add(d+"button-in")},show:function(){this.select(),this.showMount()},hide:function(){this.unselect(),this.hideMount()},showMount:function(){if(this.displayState=!0,this.mountPoint.style.display="block",this.fixOffset){var a=this.element.getBoundingClientRect();this.mountElement.setOffset(a.left+e,a.bottom)}var b=this.toolbar.getContainer(),c=null,d=g.getRectBox(b),f=this.mountElement.getPositionInfo();f.right>d.right&&(c=g.getRectBox(this.element),this.mountPoint.style.left=c.right-f.right-1+"px"),this.mountElement.updateSize&&this.mountElement.updateSize()},hideMount:function(){this.displayState=!1,this.mountPoint.style.display="none"},getNode:function(){return this.element},mount:function(a){this.mountElement=a,a.mountTo(this.mountPoint)},createButton:function(){var a=g.ele(this.doc,"div",{className:d+"button"});return this.options.className&&(a.className+=" "+d+this.options.className),a},createIcon:function(){if(!this.options.icon)return null;var b=g.ele(this.doc,"div",{className:d+"button-icon"});return"string"==typeof this.options.icon?b.style.backgroundImage="url("+this.options.icon+") no-repeat":b.style.background=a(this.options.icon),this.options.iconSize.w&&(b.style.width=this.options.iconSize.w+"px"),this.options.iconSize.h&&(b.style.height=this.options.iconSize.h+"px"),b},createLabel:function(){var a=g.ele(this.doc,"div",{className:d+"button-label",content:this.options.label});return a},createSign:function(){return this.options.sign===!1?null:g.ele(this.doc,"div",{className:d+"button-sign"})},createMountPoint:function(){return g.ele(this.doc,"div",{className:d+"button-mount-point"})},disable:function(){this.disabled=!0,g.getClassList(this.element).remove(d+"enabled") +},enable:function(){this.disabled=!1,g.getClassList(this.element).add(d+"enabled")},mergeElement:function(){this.icon&&this.element.appendChild(this.icon),this.element.appendChild(this.label),this.sign&&this.label.appendChild(this.sign),this.element.appendChild(this.mountPoint)}});return h}},b[40]={value:function(){return{DETACHED:1,OVERLAP:2}}},b[41]={value:function(){return{DRAPDOWN_BOX:1,AREA:2,DELIMITER:3}}},b[42]={value:function(){return{BIG:1,SMALL:2}}},b[43]={value:function(){var a=b.r(20),c="kf-editor-ui-",d=b.r(47),e=a.createClass("Delimiter",{constructor:function(a){this.doc=a,this.element=this.createDilimiter()},setToolbar:function(){},createDilimiter:function(){var a=d.ele(this.doc,"div",{className:c+"delimiter"});return a.appendChild(d.ele(this.doc,"div",{className:c+"delimiter-line"})),a},attachTo:function(a){a.appendChild(this.element)}});return e}},b[44]={value:function(){var a=b.r(20),c=b.r(47),d=b.r(39),e=b.r(38),f=a.createClass("DrapdownBox",{constructor:function(a,b){this.options=b,this.toolbar=null,this.doc=a,this.buttonElement=this.createButton(),this.element=this.buttonElement.getNode(),this.boxElement=this.createBox(),this.buttonElement.mount(this.boxElement),this.initEvent()},initEvent:function(){var a=this;c.on(this.element,"mousedown",function(b){b.preventDefault(),b.stopPropagation(),a.toolbar.notify("closeOther",a)}),this.buttonElement.initEvent(),this.boxElement.initEvent(),this.boxElement.setSelectHandler(function(b){c.publish("data.select",b),a.buttonElement.hide()})},disable:function(){this.buttonElement.disable()},enable:function(){this.buttonElement.enable()},setToolbar:function(a){this.toolbar=a,this.buttonElement.setToolbar(a),this.boxElement.setToolbar(a)},createButton:function(){return new d(this.doc,this.options.button)},show:function(){this.buttonElement.show()},hide:function(){this.buttonElement.hide()},createBox:function(){return new e(this.doc,this.options.box)},attachTo:function(a){a.appendChild(this.element)}});return f}},b[45]={value:function(){var a=b.r(20),c="kf-editor-ui-",d=b.r(47),e=a.createClass("List",{constructor:function(a,b){this.options=b,this.doc=a,this.onselectHandler=null,this.currentSelect=-1,this.element=this.createBox(),this.itemGroups=this.createItems(),this.mergeElement()},onselectHandler:function(){},setSelectHandler:function(a){this.onselectHandler=a},createBox:function(){var a=d.ele(this.doc,"div",{className:c+"list"}),b=d.ele(this.doc,"div",{className:c+"list-bg"});return"width"in this.options&&(a.style.width=this.options.width+"px"),a.appendChild(b),a},select:function(a){var b=this.currentSelect;-1===b&&(b=a),this.unselect(b),this.currentSelect=a,d.getClassList(this.itemGroups.items[a]).add(c+"list-item-select"),this.onselectHandler(a,b)},unselect:function(a){d.getClassList(this.itemGroups.items[a]).remove(c+"list-item-select")},setOffset:function(a,b){this.element.style.left=a+"px",this.element.style.top=b+"px"},initEvent:function(){var a="."+c+"list-item",b=this;d.delegate(this.itemGroups.container,a,"mousedown",function(a){a.preventDefault(),1===a.which&&b.select(this.getAttribute("data-index"))}),d.on(this.element,"mousedown",function(a){a.stopPropagation(),a.preventDefault()})},getPositionInfo:function(){return d.getRectBox(this.element)},createItems:function(){var b=this.doc,e=null,f=null,g=null,h=[],i=null;return e=d.ele(this.doc,"div",{className:c+"list-item"}),i=e.cloneNode(!1),i.className=c+"list-item-container",a.Utils.each(this.options.items,function(a,j){f=e.cloneNode(!1),g=e.cloneNode(!1),g.className=c+"list-item-icon",f.appendChild(g),f.appendChild(d.ele(b,"text",a)),f.setAttribute("data-index",j),h.push(f),i.appendChild(f)}),{container:i,items:h}},mergeElement:function(){this.element.appendChild(this.itemGroups.container)},mountTo:function(a){a.appendChild(this.element)}});return e}},b[46]={value:function(){function a(a,b,c){var d=a.createElement(b),e='
                                                                                          ';return d.className=r+c,"thumb"===c&&(c=r+c,d.innerHTML=e.replace("$1",c+"-left").replace("$2",c+"-right")),d}function c(a){return a.getBoundingClientRect()}function d(a){q.addEvent(a,"mousedown",function(a){a.preventDefault()})}function d(a){q.addEvent(a.container,"mousedown",function(a){a.preventDefault()})}function e(a){q.addEvent(a.widgets.track,"mousedown",function(b){h(this,a,b)})}function f(a){q.addEvent(a.widgets.leftButton,"mousedown",function(){j(a,-p.step)}),q.addEvent(a.widgets.rightButton,"mousedown",function(){j(a,p.step)})}function g(a){var b=!1,c=0,d=0,e=a.values.trackWidth;q.addEvent(a.widgets.thumb,"mousedown",function(e){e.preventDefault(),e.stopPropagation(),b=!0,c=e.clientX,d=a.thumbLocationX}),q.addEvent(a.container.ownerDocument,"mouseup",function(){b=!1,c=0,d=0}),q.addEvent(a.container.ownerDocument,"mousemove",function(f){if(b){var g=f.clientX-c,h=d+g,j=a.values.thumbWidth;0>h?h=0:h+j>e&&(h=e-j),i(a,h)}})}function h(a,b,d){var e=c(a),f=b.values,g=f.viewWidth/(f.contentWidth-f.viewWidth)*f.trackWidth,h=d.clientX-e.left;h>f.offset?f.offset+g>f.trackWidth?k(b,f.trackWidth):k(b,f.offset+g):f.offset-g<0?k(b,0):k(b,f.offset-g)}function i(a,b){var c=a.values,d=c.trackWidth-c.thumbWidth,e=Math.floor(b/d*c.trackWidth);a.updateOffset(e),a.thumbLocationX=b,a.widgets.thumb.style.left=b+"px"}function j(a,b){var c=a.leftOverflow+b;0>c?c=0:c>a.values.scrollWidth&&(c=a.values.scrollWidth),m(a,c)}function k(a,b){var c=a.values,d=b/c.trackWidth,e=c.trackWidth-c.thumbWidth,f=0;f=Math.floor(d*e),0>b&&(b=0,f=0),a.updateOffset(b),a.widgets.thumb.style.left=f+"px",a.thumbLocationX=f}function l(a,b){var c=a.values,d=0,e=0;d=b/(c.contentWidth-c.viewWidth),e=Math.floor(d*c.trackWidth),k(a,e)}function m(a,b){var c=a.values,d=b/(c.contentWidth-c.viewWidth);k(a,d*c.trackWidth)}var n=b.r(20),o=b.r(32).scrollbar,p=b.r(29).scrollbar,q=b.r(4),r="kf-editor-ui-";return n.createClass("Scrollbar",{constructor:function(a,b){this.uiComponent=a,this.kfEditor=b,this.widgets=null,this.container=this.uiComponent.scrollbarContainer,this.state=!1,this.values={offset:0,left:0,viewWidth:0,contentWidth:0,trackWidth:0,thumbWidth:0,scrollWidth:0},this.thumbLocationX=0,this.leftOverflow=0,this.rightOverflow=0,this.isExpand=!0,this.initWidget(),this.mountWidget(),this.initSize(),this.hide(),this.initServices(),this.initEvent(),this.updateHandler=function(){}},initWidget:function(){var b=this.container.ownerDocument;this.widgets={leftButton:a(b,"div","left-button"),rightButton:a(b,"div","right-button"),track:a(b,"div","track"),thumb:a(b,"div","thumb"),thumbBody:a(b,"div","thumb-body")}},initSize:function(){var a=c(this.widgets.leftButton).width,b=c(this.widgets.rightButton).width;this.values.viewWidth=c(this.container).width,this.values.trackWidth=this.values.viewWidth-a-b,this.widgets.track.style.width=this.values.trackWidth+"px"},initServices:function(){this.kfEditor.registerService("ui.show.scrollbar",this,{showScrollbar:this.show}),this.kfEditor.registerService("ui.hide.scrollbar",this,{hideScrollbar:this.hide}),this.kfEditor.registerService("ui.update.scrollbar",this,{updateScrollbar:this.update}),this.kfEditor.registerService("ui.set.scrollbar.update.handler",this,{setUpdateHandler:this.setUpdateHandler}),this.kfEditor.registerService("ui.relocation.scrollbar",this,{relocation:this.relocation})},initEvent:function(){d(this),e(this),g(this),f(this)},mountWidget:function(){var a=this.widgets,b=this.container;for(var c in a)a.hasOwnProperty(c)&&b.appendChild(a[c]);a.thumb.appendChild(a.thumbBody),a.track.appendChild(a.thumb)},show:function(){this.state=!0,this.container.style.display="block"},hide:function(){this.state=!1,this.container.style.display="none"},update:function(a){var b=this.values.trackWidth,c=0;return this.isExpand=a>this.values.contentWidth,this.values.contentWidth=a,this.values.scrollWidth=a-this.values.viewWidth,b>=a?void this.hide():(c=Math.max(Math.ceil(b*b/a),o.thumbMinSize),this.values.thumbWidth=c,this.widgets.thumb.style.width=c+"px",void(this.widgets.thumbBody.style.width=c-10+"px"))},setUpdateHandler:function(a){this.updateHandler=a},updateOffset:function(a){var b=this.values;b.offset=a,b.left=a/b.trackWidth,this.leftOverflow=b.left*(b.contentWidth-b.viewWidth),this.rightOverflow=b.contentWidth-b.viewWidth-this.leftOverflow,this.updateHandler(b.left,b.offset,b)},relocation:function(){var a=this.kfEditor.requestService("control.get.cursor.location"),b=p.padding,c=this.values.contentWidth,d=this.values.viewWidth,e=this.values.left*(c-d),f=0;a.xe+d?(a.x+=b,a.x>c&&(a.x=c),f=a.x-d,l(this,f)):this.isExpand?m(this,this.leftOverflow):m(this,c-d-this.rightOverflow)}})}},b[47]={value:function(){function a(a){this.node=a,this.classes=a.className.replace(/^\s+|\s+$/g,"").split(/\s+/)}var c=b.r(14),d=b.r(20),e={},f={ele:function(a,b,c){var d=null;return"text"===b?a.createTextNode(c):(d=a.createElement(b),c.className&&(d.className=c.className),c.content&&(d.innerHTML=c.content),d)},getRectBox:function(a){return a.getBoundingClientRect()},on:function(a,b,d){return c(a).on(b,d),this},delegate:function(a,b,d,e){return c(a).delegate(b,d,e),this},publish:function(a,b){var c=e[a];c&&(b=[].slice.call(arguments,1),d.Utils.each(c,function(a){a.apply(null,b)}))},subscribe:function(a,b){e[a]||(e[a]=[]),e[a].push(b)},getClassList:function(b){return b.classList||new a(b)}};return a.prototype={constructor:a,contains:function(a){return-1!==this.classes.indexOf(a)},add:function(a){return-1==this.classes.indexOf(a)&&this.classes.push(a),this._update(),this},remove:function(a){var b=this.classes.indexOf(a);return-1!==b&&(this.classes.splice(b,1),this._update()),this},toggle:function(a){var b=this.contains(a)?"remove":"add";return this[b](a)},_update:function(){this.node.className=this.classes.join(" ")}},f}},b[48]={value:function(){return{DrapdownBox:b.r(44),Delimiter:b.r(43),Area:b.r(37)}}},b[49]={value:function(){function a(a){return h.ele(a,"div",{className:"kf-editor-toolbar"})}function c(a){return h.ele(a,"div",{className:"kf-editor-inner-toolbar"})}function d(a){var b=a.createElement("div");return b.className="kf-editor-edit-area",b.style.width="80%",b.style.height="800px",b}function e(a){var b=a.createElement("div");return b.className="kf-editor-canvas-container",b}function f(a){var b=a.createElement("div");return b.className="kf-editor-edit-scrollbar",b}var g=b.r(20),h=b.r(47),i=b.r(4),j=b.r(32).VIEW_STATE,k=b.r(46),l=b.r(36),m=(b.r(31),b.r(35)),n=g.createClass("UIComponent",{constructor:function(b,g){var h=null;this.options=g,this.container=b.getContainer(),h=this.container.ownerDocument,this.components={},this.canvasRect=null,this.viewState=j.NO_OVERFLOW,this.kfEditor=b,this.toolbarWrap=a(h),this.toolbarContainer=c(h),this.editArea=d(h),this.canvasContainer=e(h),this.scrollbarContainer=f(h),this.toolbarWrap.appendChild(this.toolbarContainer),this.container.appendChild(this.toolbarWrap),this.editArea.appendChild(this.canvasContainer),this.container.appendChild(this.editArea),this.container.appendChild(this.scrollbarContainer),this.initComponents(),this.initServices(),this.initEvent(),this.updateContainerSize(this.container,this.toolbarWrap,this.editArea,this.canvasContainer),this.initScrollEvent()},initComponents:function(){this.components.toolbar=new l(this,this.kfEditor,m),this.components.scrollbar=new k(this,this.kfEditor)},updateContainerSize:function(a,b,c){var d=a.getBoundingClientRect(),e=b.getBoundingClientRect();c.style.width=d.width+"px",c.style.height=d.bottom-e.bottom+"px"},initServices:function(){this.kfEditor.registerService("ui.get.canvas.container",this,{getCanvasContainer:this.getCanvasContainer}),this.kfEditor.registerService("ui.update.canvas.view",this,{updateCanvasView:this.updateCanvasView}),this.kfEditor.registerService("ui.canvas.container.event",this,{on:this.addEvent,off:this.removeEvent,trigger:this.trigger,fire:this.trigger})},initEvent:function(){},initScrollEvent:function(){var a=this;this.kfEditor.requestService("ui.set.scrollbar.update.handler",function(b,c,d){c=Math.floor(b*(d.contentWidth-d.viewWidth)),a.kfEditor.requestService("render.set.canvas.offset",c)})},getCanvasContainer:function(){return this.canvasContainer},addEvent:function(a,b){i.addEvent(this.canvasContainer,a,b)},removeEvent:function(){},trigger:function(a){i.trigger(this.canvasContainer,a)},updateCanvasView:function(){var a=this.kfEditor.requestService("render.get.canvas"),b=a.getContentContainer(),c=null;null===this.canvasRect&&(this.canvasRect=this.canvasContainer.getBoundingClientRect()),c=b.getRenderBox("paper"),c.width>this.canvasRect.width?(this.viewState===j.NO_OVERFLOW&&(this.toggleViewState(),this.kfEditor.requestService("ui.show.scrollbar"),this.kfEditor.requestService("render.disable.relocation")),this.kfEditor.requestService("render.relocation"),this.kfEditor.requestService("ui.update.scrollbar",c.width),this.kfEditor.requestService("ui.relocation.scrollbar")):(this.viewState===j.OVERFLOW&&(this.toggleViewState(),this.kfEditor.requestService("ui.hide.scrollbar"),this.kfEditor.requestService("render.enable.relocation")),this.kfEditor.requestService("render.relocation"))},toggleViewState:function(){this.viewState=this.viewState===j.NO_OVERFLOW?j.OVERFLOW:j.NO_OVERFLOW}});return n}},b[50]={value:function(){var a=b.r(12),c=b.r(13);a.registerComponents("ui",b.r(49)),a.registerComponents("parser",b.r(21)),a.registerComponents("render",b.r(25)),a.registerComponents("position",b.r(23)),a.registerComponents("syntax",b.r(28)),a.registerComponents("control",b.r(5)),a.registerComponents("print",b.r(24)),kf.EditorFactory=c}};var c={"kf.start":50};!function(){try{a("kf.start")}catch(b){}}(this)}(); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/js/kitygraph.all.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/js/kitygraph.all.js new file mode 100644 index 0000000000000000000000000000000000000000..153d6e18047ca1f68de81fd548a842f7ec15f580 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/js/kitygraph.all.js @@ -0,0 +1,8572 @@ +/*! + * ==================================================== + * kity - v2.0.5 - 2015-11-12 + * https://github.com/fex-team/kity + * GitHub: https://github.com/fex-team/kity.git + * Copyright (c) 2015 Baidu FEX; Licensed BSD + * ==================================================== + */ + +(function () { +var _p = { + r: function(index) { + if (_p[index].inited) { + return _p[index].value; + } + if (typeof _p[index].value === "function") { + var module = { + exports: {} + }, returnValue = _p[index].value(null, module.exports, module); + _p[index].inited = true; + _p[index].value = returnValue; + if (returnValue !== undefined) { + return returnValue; + } else { + for (var key in module.exports) { + if (module.exports.hasOwnProperty(key)) { + _p[index].inited = true; + _p[index].value = module.exports; + return module.exports; + } + } + } + } else { + _p[index].inited = true; + return _p[index].value; + } + } +}; + +//src/animate/animator.js +/** + * @fileOverview + * + * 提供基本的动画支持 + */ +_p[0] = { + value: function(require) { + function parseTime(str) { + var value = parseFloat(str, 10); + if (/ms/.test(str)) { + return value; + } + if (/s/.test(str)) { + return value * 1e3; + } + if (/min/.test(str)) { + return value * 60 * 1e3; + } + return value; + } + var Timeline = _p.r(8); + var easingTable = _p.r(1); + /** + * @class kity.Animator + * @catalog animate + * @description 表示一个动画启动器,可以作用于不同的对象进行动画 + */ + var Animator = _p.r(11).createClass("Animator", { + /** + * @constructor + * @for kity.Animator + * @catalog animate + * + * @grammar new kity.Animator(beginValue, finishValue, setter) + * @grammar new kity.Animator(option) + * + * @param {any} beginValue|opt.beginValue + * 动画的起始值,允许的类型有数字、数组、字面量、kity.Point、kity.Vector、kity.Box、kity.Matrix + * + * @param {any} finishValue|opt.beginValue + * 动画的结束值,类型应于起始值相同 + * + * @param {Function} setter|opt.setter + * 值的使用函数,接受三个参数: function(target, value, timeline) + * target {object} 动画的目标 + * value {any} 动画的当前值 + * timeline {kity.Timeline} 动画当前的时间线对象 + */ + constructor: function(beginValue, finishValue, setter) { + if (arguments.length == 1) { + var opt = arguments[0]; + this.beginValue = opt.beginValue; + this.finishValue = opt.finishValue; + this.setter = opt.setter; + } else { + this.beginValue = beginValue; + this.finishValue = finishValue; + this.setter = setter; + } + }, + /** + * @method start() + * @for kity.Animator + * @description 使用当前的动画器启动在指定目标上启动动画 + * + * @grammar start(target, duration, easing, delay, callback) => {kity.Timeline} + * @grammar start(target, option) => {kity.Timeline} + * + * @param {object} target + * 启动动画的目标 + * + * @param {Number|String} duration|option.duration + * [Optional] 动画的持续时间,如 300、"300ms"、"1.5min" + * + * @param {String|Function} easing|option.easing + * [Optional] 动画使用的缓动函数,如 "ease"、"linear"、"swing" + * + * @param {Number|String} delay|option.delay + * [Optional] 动画的播放延迟时间 + * + * @param {Function} callback|option.callback + * [Optional] 动画结束后的回调函数 + * + * @example + * + * ```js + * var turnRed = new kity.Animator( + * new kity.Color('yellow'), + * new kity.Color('red'), + * function(target, value) { + * target.fill(value); + * }); + * + * turnRed.start(rect, 300, 'ease', function() { + * console.log('I am red!'); + * }); + * ``` + */ + start: function(target, duration, easing, delay, callback) { + if (arguments.length === 2 && typeof duration == "object") { + easing = duration.easing; + delay = duration.delay; + callback = duration.callback; + duration = duration.duration; + } + if (arguments.length === 4 && typeof delay == "function") { + callback = delay; + delay = 0; + } + var timeline = this.create(target, duration, easing, callback); + delay = parseTime(delay); + if (delay > 0) { + setTimeout(function() { + timeline.play(); + }, delay); + } else { + timeline.play(); + } + return timeline; + }, + /** + * @method create() + * @for kity.Animator + * @description 使用当前的动画器为指定目标创建时间线 + * + * @grammar create(target, duration, easing, callback) => {kity.Timeline} + * + * @param {object} target 要创建的时间线的目标 + * @param {Number|String} duration 要创建的时间线的长度,如 300、"5s"、"0.5min" + * @param {String|Function} easing 要创建的时间线的缓动函数,如 'ease'、'linear'、'swing' + * @param {Function} callback 时间线播放结束之后的回调函数 + * + * @example + * + * ```js + * var expand = new kity.Animator({ + * beginValue: function(target) { + * return target.getBox(); + * }, + * finishValue: function(target) { + * return target.getBox().expand(100, 100, 100, 100); + * }, + * setter: function(target, value) { + * target.setBox(value) + * } + * }); + * + * var timeline = expand.create(rect, 300); + * timeline.repeat(3).play(); + * ``` + */ + create: function(target, duration, easing, callback) { + var timeline; + duration = duration && parseTime(duration) || Animator.DEFAULT_DURATION; + easing = easing || Animator.DEFAULT_EASING; + if (typeof easing == "string") { + easing = easingTable[easing]; + } + timeline = new Timeline(this, target, duration, easing); + if (typeof callback == "function") { + timeline.on("finish", callback); + } + return timeline; + }, + /** + * @method reverse() + * @for kity.Animator + * @grammar reverse() => {kity.Animator} + * @description 创建一个与当前动画器相反的动画器 + * + * @example + * + * ```js + * var turnYellow = turnRed.reverse(); + * ``` + */ + reverse: function() { + return new Animator(this.finishValue, this.beginValue, this.setter); + } + }); + Animator.DEFAULT_DURATION = 300; + Animator.DEFAULT_EASING = "linear"; + var Shape = _p.r(60); + _p.r(11).extendClass(Shape, { + /** + * @method animate() + * @for kity.Shape + * @description 在图形上播放使用指定的动画器播放动画,如果图形当前有动画正在播放,则会加入播放队列 + * + * @grammar animate(animator, duration, easing, delay, callback) + * + * @param {object} animator 播放动画使用的动画器 + * @param {Number|String} duration 动画的播放长度,如 300、"5s"、"0.5min" + * @param {Number|String} delay 动画播放前的延时 + * @param {String|Function} easing 动画播放使用的缓动函数,如 'ease'、'linear'、'swing' + * @param {Function} callback 播放结束之后的回调函数 + * + * @example + * + * ```js + * rect.animate(turnRed, 300); // turnRect 是一个动画器 + * rect.animate(expand, 500); // turnRect 播放结束后播放 expand + * ``` + */ + animate: function(animator, duration, easing, delay, callback) { + var queue = this._KityAnimateQueue = this._KityAnimateQueue || []; + var timeline = animator.create(this, duration, easing, callback); + function dequeue() { + queue.shift(); + if (queue.length) { + setTimeout(queue[0].t.play.bind(queue[0].t), queue[0].d); + } + } + timeline.on("finish", dequeue); + queue.push({ + t: timeline, + d: delay + }); + if (queue.length == 1) { + setTimeout(timeline.play.bind(timeline), delay); + } + return this; + }, + /** + * @method timeline() + * @for kity.Shape + * @description 获得当前正在播放的动画的时间线 + * + * @grammar timeline() => {kity.Timeline} + * + * @example + * + * ```js + * rect.timeline().repeat(2); + * ``` + */ + timeline: function() { + return this._KityAnimateQueue[0].t; + }, + /** + * @method stop() + * @for kity.Shape + * @description 停止当前正在播放的动画 + * + * @grammar stop() => {this} + * + * @example + * + * ```js + * rect.stop(); // 停止 rect 上的动画 + * ``` + */ + stop: function() { + var queue = this._KityAnimateQueue; + if (queue) { + while (queue.length) { + queue.shift().t.stop(); + } + } + return this; + } + }); + return Animator; + } +}; + +//src/animate/easing.js +/** + * Kity Animate Easing modified from jQuery Easing + * Author: techird + * Changes: + * 1. make easing functions standalone + * 2. remove the 'x' parameter + */ +/* ============================================================ + * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ + * + * Open source under the BSD License. + * + * Copyright © 2008 George McGinley Smith + * All rights reserved. + * https://raw.github.com/danro/jquery-easing/master/LICENSE + * ======================================================== */ +_p[1] = { + value: function(require, exports, module) { + var easings = { + // t: current_time, b: begin_value, c: change_value, d: duration + linear: function(t, b, c, d) { + return c * (t / d) + b; + }, + swing: function(t, b, c, d) { + return easings.easeOutQuad(t, b, c, d); + }, + ease: function(t, b, c, d) { + return easings.easeInOutCubic(t, b, c, d); + }, + easeInQuad: function(t, b, c, d) { + return c * (t /= d) * t + b; + }, + easeOutQuad: function(t, b, c, d) { + return -c * (t /= d) * (t - 2) + b; + }, + easeInOutQuad: function(t, b, c, d) { + if ((t /= d / 2) < 1) return c / 2 * t * t + b; + return -c / 2 * (--t * (t - 2) - 1) + b; + }, + easeInCubic: function(t, b, c, d) { + return c * (t /= d) * t * t + b; + }, + easeOutCubic: function(t, b, c, d) { + return c * ((t = t / d - 1) * t * t + 1) + b; + }, + easeInOutCubic: function(t, b, c, d) { + if ((t /= d / 2) < 1) return c / 2 * t * t * t + b; + return c / 2 * ((t -= 2) * t * t + 2) + b; + }, + easeInQuart: function(t, b, c, d) { + return c * (t /= d) * t * t * t + b; + }, + easeOutQuart: function(t, b, c, d) { + return -c * ((t = t / d - 1) * t * t * t - 1) + b; + }, + easeInOutQuart: function(t, b, c, d) { + if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b; + return -c / 2 * ((t -= 2) * t * t * t - 2) + b; + }, + easeInQuint: function(t, b, c, d) { + return c * (t /= d) * t * t * t * t + b; + }, + easeOutQuint: function(t, b, c, d) { + return c * ((t = t / d - 1) * t * t * t * t + 1) + b; + }, + easeInOutQuint: function(t, b, c, d) { + if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b; + return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; + }, + easeInSine: function(t, b, c, d) { + return -c * Math.cos(t / d * (Math.PI / 2)) + c + b; + }, + easeOutSine: function(t, b, c, d) { + return c * Math.sin(t / d * (Math.PI / 2)) + b; + }, + easeInOutSine: function(t, b, c, d) { + return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b; + }, + easeInExpo: function(t, b, c, d) { + return t === 0 ? b : c * Math.pow(2, 10 * (t / d - 1)) + b; + }, + easeOutExpo: function(t, b, c, d) { + return t == d ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b; + }, + easeInOutExpo: function(t, b, c, d) { + if (t === 0) return b; + if (t == d) return b + c; + if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b; + return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b; + }, + easeInCirc: function(t, b, c, d) { + return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b; + }, + easeOutCirc: function(t, b, c, d) { + return c * Math.sqrt(1 - (t = t / d - 1) * t) + b; + }, + easeInOutCirc: function(t, b, c, d) { + if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b; + return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b; + }, + easeInElastic: function(t, b, c, d) { + var s = 1.70158; + var p = 0; + var a = c; + if (t === 0) return b; + if ((t /= d) == 1) return b + c; + if (!p) p = d * .3; + if (a < Math.abs(c)) { + a = c; + s = p / 4; + } else s = p / (2 * Math.PI) * Math.asin(c / a); + return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b; + }, + easeOutElastic: function(t, b, c, d) { + var s = 1.70158; + var p = 0; + var a = c; + if (t === 0) return b; + if ((t /= d) == 1) return b + c; + if (!p) p = d * .3; + if (a < Math.abs(c)) { + a = c; + s = p / 4; + } else s = p / (2 * Math.PI) * Math.asin(c / a); + return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b; + }, + easeInOutElastic: function(t, b, c, d) { + var s = 1.70158; + var p = 0; + var a = c; + if (t === 0) return b; + if ((t /= d / 2) == 2) return b + c; + if (!p) p = d * (.3 * 1.5); + if (a < Math.abs(c)) { + a = c; + var s = p / 4; + } else var s = p / (2 * Math.PI) * Math.asin(c / a); + if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b; + return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b; + }, + easeInBack: function(t, b, c, d, s) { + if (s == undefined) s = 1.70158; + return c * (t /= d) * t * ((s + 1) * t - s) + b; + }, + easeOutBack: function(t, b, c, d, s) { + if (s == undefined) s = 1.70158; + return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; + }, + easeInOutBack: function(t, b, c, d, s) { + if (s == undefined) s = 1.70158; + if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= 1.525) + 1) * t - s)) + b; + return c / 2 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2) + b; + }, + easeInBounce: function(t, b, c, d) { + return c - easings.easeOutBounce(d - t, 0, c, d) + b; + }, + easeOutBounce: function(t, b, c, d) { + if ((t /= d) < 1 / 2.75) { + return c * (7.5625 * t * t) + b; + } else if (t < 2 / 2.75) { + return c * (7.5625 * (t -= 1.5 / 2.75) * t + .75) + b; + } else if (t < 2.5 / 2.75) { + return c * (7.5625 * (t -= 2.25 / 2.75) * t + .9375) + b; + } else { + return c * (7.5625 * (t -= 2.625 / 2.75) * t + .984375) + b; + } + }, + easeInOutBounce: function(t, b, c, d) { + if (t < d / 2) return easings.easeInBounce(t * 2, 0, c, d) * .5 + b; + return easings.easeOutBounce(t * 2 - d, 0, c, d) * .5 + c * .5 + b; + } + }; + return easings; + } +}; + +/* + * + * TERMS OF USE - EASING EQUATIONS + * + * Open source under the BSD License. + * + * Copyright © 2001 Robert Penner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the author nor the names of contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +//src/animate/frame.js +/** + * @fileOverview + * + * 提供动画帧的基本支持 + */ +_p[2] = { + value: function(require, exports) { + // 原生动画帧方法 polyfill + var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function(fn) { + return setTimeout(fn, 1e3 / 60); + }; + var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame || window.clearTimeout; + // 上一个请求的原生动画帧 id + var frameRequestId; + // 等待执行的帧动作的集合,这些帧的方法将在下个原生动画帧同步执行 + var pendingFrames = []; + /** + * 添加一个帧到等待集合中 + * + * 如果添加的帧是序列的第一个,至少有一个帧需要被执行,则会请求一个原生动画帧来执行 + */ + function pushFrame(frame) { + if (pendingFrames.push(frame) === 1) { + frameRequestId = requestAnimationFrame(executePendingFrames); + } + } + /** + * 执行所有等待帧 + */ + function executePendingFrames() { + var frames = pendingFrames; + pendingFrames = []; + while (frames.length) { + executeFrame(frames.pop()); + } + frameRequestId = 0; + } + /** + * @method kity.requestFrame + * @catalog animate + * @grammar kity.requestFrame(action) => {frame} + * @description 请求一个帧,执行指定的动作。动作回调提供一些有用的信息 + * + * @param {Function} action + * + * 要执行的动作,该动作回调有一个参数 frame,其中: + * + * frame.time {Number} + * 动作执行时的时间戳(ms) + * + * frame.index {Number} + * 当前执行的帧的编号(首帧为 0) + * + * frame.dur {Number} + * 上一帧至当前帧经过的时间,单位 ms + * + * frame.elapsed {Number} + * 从首帧开始到当前帧经过的时间,单位 ms + * + * frame.action {Number} + * 指向当前的帧处理函数 + * + * frame.next() + * 表示下一帧继续执行。如果不调用该方法,将不会执行下一帧。 + * + * @example + * + * ```js + * kity.requestFrame(function(frame) { + * console.log('平均帧率:' + frame.elapsed / (frame.index + 1)); + * + * // 更新或渲染动作 + * + * frame.next(); //继续执行下一帧 + * }); + * ``` + */ + function requestFrame(action) { + var frame = initFrame(action); + pushFrame(frame); + return frame; + } + /** + * @method kity.releaseFrame + * @catalog animate + * @grammar kity.releaseFrame(frame) + * @description 释放一个已经请求过的帧,如果该帧在等待集合里,将移除,下个动画帧不会执行释放的帧 + * + * @param {frame} frame 使用 kity.requestFrame() 返回的帧 + * + * @example + * + * ```js + * var frame = kity.requestFrame(function() {....}); + * kity.releaseFrame(frame); + * ``` + */ + function releaseFrame(frame) { + var index = pendingFrames.indexOf(frame); + if (~index) { + pendingFrames.splice(index, 1); + } + if (pendingFrames.length === 0) { + cancelAnimationFrame(frameRequestId); + } + } + /** + * 初始化一个帧,主要用于后续计算 + */ + function initFrame(action) { + var frame = { + index: 0, + time: +new Date(), + elapsed: 0, + action: action, + next: function() { + pushFrame(frame); + } + }; + return frame; + } + /** + * 执行一个帧动作 + */ + function executeFrame(frame) { + // 当前帧时间错 + var time = +new Date(); + // 当上一帧到当前帧经过的时间 + var dur = time - frame.time; + // + // http://stackoverflow.com/questions/13133434/requestanimationframe-detect-stop + // 浏览器最小化或切换标签,requestAnimationFrame 不会执行。 + // 检测时间超过 200 ms(频率小于 5Hz ) 判定为计时器暂停,重置为一帧长度 + // + if (dur > 200) { + dur = 1e3 / 60; + } + frame.dur = dur; + frame.elapsed += dur; + frame.time = time; + frame.action.call(null, frame); + frame.index++; + } + // 暴露 + exports.requestFrame = requestFrame; + exports.releaseFrame = releaseFrame; + } +}; + +//src/animate/motionanimator.js +/** + * @fileOverview + * + * 路径动画器,可以让一个物体沿着某个轨迹运动 + */ +_p[3] = { + value: function(require) { + var Animator = _p.r(0); + var g = _p.r(34); + var Path = _p.r(46); + var Shape = _p.r(60); + /** + * @class kity.MotionAnimator + * @catalog animate + * @base kity.Animator + * @description 路径动画器,可以让一个物体沿着某个轨迹运动 + * + * @example + * + * ```js + * var motionAnimator = new MotionAnimator('M0,0C100,0,100,0,100,100L200,200'); + * motionAnimator.start(rect, 3000); + * ``` + */ + var MotionAnimator = _p.r(11).createClass("MotionAnimator", { + base: Animator, + /** + * @constructor + * @for kity.MotionAnimator + * @grammar new kity.MotionAnimator(path, doRotate) + * @param {kity.Path|String|PathSegment} path 运动的轨迹,或者是 kity.Path 对象 + * @param {boolean} doRotate 是否让运动的目标沿着路径的切线方向旋转 + */ + constructor: function(path, doRotate) { + var me = this; + this.callBase({ + beginValue: 0, + finishValue: 1, + setter: function(target, value) { + var path = me.motionPath instanceof Path ? me.motionPath.getPathData() : me.motionPath; + var point = g.pointAtPath(path, value); + target.setTranslate(point.x, point.y); + if (this.doRotate) target.setRotate(point.tan.getAngle()); + } + }); + /** + * @property doRotate + * @for kity.MotionAnimator + * @type {boolean} + * @description 是否让运动的目标沿着路径的切线方向旋转 + * + * @example + * + * ```js + * motionAnimator.doRotate = true; // 目标沿着切线方向旋转 + * ``` + */ + this.doRotate = doRotate; + /** + * @property motionPath + * @for kity.MotionAnimator + * @type {kity.Path|String|PathSegment} + * @description 运动沿着的路径,可以在动画过程中更新 + */ + this.motionPath = path; + } + }); + _p.r(11).extendClass(Shape, { + /** + * @method motion() + * @catalog animate + * @for kity.Shape + * @description 让图形沿着指定的路径运动 + * + * @grammar motion(path, duration, easing, delay, callback) => this + * + * @param {kity.Path|String|PathSegment} path 运动的轨迹,或者是 kity.Path 对象 + * @param {Number|String} duration 动画的播放长度,如 300、"5s"、"0.5min" + * @param {Number|String} delay 动画播放前的延时 + * @param {String|Function} easing 动画播放使用的缓动函数,如 'ease'、'linear'、'swing' + * @param {Function} callback 播放结束之后的回调函数 + */ + motion: function(path, duration, easing, delay, callback) { + return this.animate(new MotionAnimator(path), duration, easing, delay, callback); + } + }); + return MotionAnimator; + } +}; + +//src/animate/opacityanimator.js +/** + * @fileOverview + * + * 透明度动画器,让图形动画过度到指定的透明度。 + */ +_p[4] = { + value: function(require) { + var Animator = _p.r(0); + /** + * @class kity.OpacityAnimator + * @catalog animate + * @base kity.Animator + * @description 透明度动画器,让图形动画过度到指定的透明度 + */ + var OpacityAnimator = _p.r(11).createClass("OpacityAnimator", { + base: Animator, + /** + * @constructor + * @for kity.OpacityAnimator + * @grammar new kity.OpacityAnimator(opacity) + * + * @param {Number} opacity 目标透明度,取值范围 0 - 1 + */ + constructor: function(opacity) { + this.callBase({ + beginValue: function(target) { + return target.getOpacity(); + }, + finishValue: opacity, + setter: function(target, value) { + target.setOpacity(value); + } + }); + } + }); + var Shape = _p.r(60); + _p.r(11).extendClass(Shape, { + /** + * @method fxOpacity() + * @catalog animate + * @for kity.Shape + * @description 让图形的透明度以动画的形式过渡到指定的值 + * + * @grammar fxOpacity(opacity, duration, easing, delay, callback) => {this} + * + * @param {Number} opacity 动画的目标透明度 + * @param {Number|String} duration 动画的播放长度,如 300、"5s"、"0.5min" + * @param {Number|String} delay 动画播放前的延时 + * @param {String|Function} easing 动画播放使用的缓动函数,如 'ease'、'linear'、'swing' + * @param {Function} callback 播放结束之后的回调函数 + */ + fxOpacity: function(opacity, duration, easing, delay, callback) { + return this.animate(new OpacityAnimator(opacity), duration, easing, delay, callback); + }, + /** + * @method fadeTo() + * @catalog animate + * @for kity.Shape + * @description 让图形的透明度以动画的形式过渡到指定的值 + * + * @grammar fadeTo(opacity, duration, easing, delay, callback) => {this} + * + * @param {Number} opacity 动画的目标透明度 + * @param {Number|String} duration 动画的播放长度,如 300、"5s"、"0.5min" + * @param {Number|String} delay 动画播放前的延时 + * @param {String|Function} easing 动画播放使用的缓动函数,如 'ease'、'linear'、'swing' + * @param {Function} callback 播放结束之后的回调函数 + */ + fadeTo: function() { + return this.fxOpacity.apply(this, arguments); + }, + /** + * @method fadeIn() + * @catalog animate + * @for kity.Shape + * @description 让图形淡入 + * + * @grammar fadeIn(duration, easing, delay, callback) => {this} + * + * @param {Number|String} duration 动画的播放长度,如 300、"5s"、"0.5min" + * @param {Number|String} delay 动画播放前的延时 + * @param {String|Function} easing 动画播放使用的缓动函数,如 'ease'、'linear'、'swing' + * @param {Function} callback 播放结束之后的回调函数 + */ + fadeIn: function() { + return this.fxOpacity.apply(this, [ 1 ].concat([].slice.call(arguments))); + }, + /** + * @method fadeOut() + * @catalog animate + * @for kity.Shape + * @description 让图形淡出 + * + * @grammar fadeIn(duration, easing, delay, callback) => {this} + * + * @param {Number|String} duration 动画的播放长度,如 300、"5s"、"0.5min" + * @param {Number|String} delay 动画播放前的延时 + * @param {String|Function} easing 动画播放使用的缓动函数,如 'ease'、'linear'、'swing' + * @param {Function} callback 播放结束之后的回调函数 + */ + fadeOut: function() { + return this.fxOpacity.apply(this, [ 0 ].concat([].slice.call(arguments))); + } + }); + return OpacityAnimator; + } +}; + +//src/animate/pathanimator.js +/** + * @fileOverview + * + * 路径补间动画器,让图形从一个形状变为另一个形状 + */ +_p[5] = { + value: function(require) { + var Animator = _p.r(0); + var g = _p.r(34); + /** + * @catalog animate + * + * @class kity.PathAnimator + * @base kity.Animator + * @description 路径补间动画器,让图形从一个形状变为另一个形状 + * + * @example + * + * ```js + * var path = new kity.Path('M0,0L0,100'); + * var pa = new kity.PathAnimator('M0,0C100,0,100,0,100,100'); + * pa.start(path, 300); + * ``` + */ + var PathAnimator = _p.r(11).createClass("OpacityAnimator", { + base: Animator, + /** + * @constructor + * @for kity.PathAnimator + * + * @grammar new kity.Path.Animator(path) + * + * @param {String|PathSegment} path 目标形状的路径数据 + * + */ + constructor: function(path) { + this.callBase({ + beginValue: function(target) { + this.beginPath = target.getPathData(); + return 0; + }, + finishValue: 1, + setter: function(target, value) { + target.setPathData(g.pathTween(this.beginPath, path, value)); + } + }); + } + }); + var Path = _p.r(46); + _p.r(11).extendClass(Path, { + /** + * @catalog animate + * + * @method fxPath() + * @for kity.Shape + * @description 以动画的形式把路径变换为新路径 + * + * @grammar fxPath(path, duration, easing, delay, callback) => {this} + * + * @param {String|PathSegment} path 要变换新路径 + * @param {Number|String} duration 动画的播放长度,如 300、"5s"、"0.5min" + * @param {Number|String} delay 动画播放前的延时 + * @param {String|Function} easing 动画播放使用的缓动函数,如 'ease'、'linear'、'swing' + * @param {Function} callback 播放结束之后的回调函数 + */ + fxPath: function(path, duration, easing, delay, callback) { + return this.animate(new PathAnimator(path), duration, easing, delay, callback); + } + }); + return PathAnimator; + } +}; + +//src/animate/rotateanimator.js +/** + * @fileOverview + * + * 提供支持目标旋转的动画器 + */ +_p[6] = { + value: function(require) { + var Animator = _p.r(0); + /** + * @class kity.RotateAnimator + * @base Animator + * @description 提供支持目标旋转的动画器 + */ + var RotateAnimator = _p.r(11).createClass("RotateAnimator", { + base: Animator, + /** + * @constructor + * @for kity.RotateAnimator + * + * @grammar new kity.RotateAnimator(deg, ax, ay) + * + * @param {Number} deg 要旋转的角度 + */ + constructor: function(deg) { + this.callBase({ + beginValue: 0, + finishValue: deg, + setter: function(target, value, timeline) { + var delta = timeline.getDelta(); + target.rotate(delta, ax, ay); + } + }); + } + }); + var Shape = _p.r(60); + _p.r(11).extendClass(Shape, { + /** + * @method fxRotate() + * @for kity.Shape + * @description 让目标以动画旋转指定的角度 + * + * @grammar fxRotate(deg, duration, easing, delay) => {this} + * + * @param {Number} deg 要旋转的角度 + * @param {Number|String} duration 动画的播放长度,如 300、"5s"、"0.5min" + * @param {Number|String} delay 动画播放前的延时 + * @param {String|Function} easing 动画播放使用的缓动函数,如 'ease'、'linear'、'swing' + * @param {Function} callback 播放结束之后的回调函数 + */ + fxRotate: function(deg, duration, easing, delay, callback) { + return this.animate(new RotateAnimator(deg), duration, easing, delay, callback); + } + }); + return RotateAnimator; + } +}; + +//src/animate/scaleanimator.js +/** + * @fileOverview + * + * 提供支持目标缩放的动画器 + */ +_p[7] = { + value: function(require) { + var Animator = _p.r(0); + /** + * @class kity.ScaleAnimator + * @base kity.Animator + * @description 提供支持目标缩放的动画器 + */ + var ScaleAnimator = _p.r(11).createClass("ScaleAnimator", { + base: Animator, + /** + * @constructor + * @for kity.ScaleAnimator + * + * @grammar new kity.ScaleAnimator(sx, sy) + * @param {Number} sx x 轴的缩放比例 + * @param {Number} sy y 轴的缩放比例 + */ + constructor: function(sx, sy) { + this.callBase({ + beginValue: 0, + finishValue: 1, + setter: function(target, value, timeline) { + var delta = timeline.getDelta(); + var kx = Math.pow(sx, delta); + var ky = Math.pow(sy, delta); + target.scale(ky, kx); + } + }); + } + }); + var Shape = _p.r(60); + _p.r(11).extendClass(Shape, { + /** + * @method fxScale + * @for kity.Shape + * @description 动画缩放当前的图形 + * + * @grammar fxScale(sx, sy, duration, easing, delay, callback) => {this} + * + * @param {Number} sx x 轴的缩放比例 + * @param {Number} sy y 轴的缩放比例 + * @param {Number|String} duration 动画的播放长度,如 300、"5s"、"0.5min" + * @param {Number|String} delay 动画播放前的延时 + * @param {String|Function} easing 动画播放使用的缓动函数,如 'ease'、'linear'、'swing' + * @param {Function} callback 播放结束之后的回调函数 + */ + fxScale: function(sx, sy, duration, easing, delay, callback) { + return this.animate(new ScaleAnimator(sx, sy), duration, easing, delay, callback); + } + }); + return ScaleAnimator; + } +}; + +//src/animate/timeline.js +/** + * @fileOverview + * + * 动画时间线的实现 + */ +_p[8] = { + value: function(require) { + var EventHandler = _p.r(33); + var utils = _p.r(12); + var frame = _p.r(2); + function getPercentValue(b, f, p) { + return utils.paralle(b, f, function(b, f) { + return b + (f - b) * p; + }); + } + function getDelta(v1, v2) { + return utils.paralle(v1, v2, function(v1, v2) { + return v2 - v1; + }); + } + function TimelineEvent(timeline, type, param) { + this.timeline = timeline; + this.target = timeline.target; + this.type = type; + for (var name in param) { + if (param.hasOwnProperty(name)) { + this[name] = param[name]; + } + } + } + /** + * @class kity.Timeline + * @catalog animate + * @mixins EventHandler + * @description 动画时间线 + */ + var Timeline = _p.r(11).createClass("Timeline", { + mixins: [ EventHandler ], + /** + * @constructor + * @for kity.Timeline + * @private + * @description 时间线应该由动画器进行构造,不应手动创建 + * + */ + constructor: function(animator, target, duration, easing) { + this.callMixin(); + this.target = target; + this.time = 0; + this.duration = duration; + this.easing = easing; + this.animator = animator; + this.beginValue = animator.beginValue; + this.finishValue = animator.finishValue; + this.setter = animator.setter; + this.status = "ready"; + }, + /** + * @private + * + * 让时间线进入下一帧 + */ + nextFrame: function(frame) { + if (this.status != "playing") { + return; + } + this.time += frame.dur; + this.setValue(this.getValue()); + if (this.time >= this.duration) { + this.timeUp(); + } + frame.next(); + }, + /** + * @method getPlayTime() + * @for kity.Timeline + * @grammar getPlayTime() => {Number} + * @description 获得当前播放的时间,取值区间为 [0, duration] + */ + getPlayTime: function() { + return this.rollbacking ? this.duration - this.time : this.time; + }, + /** + * @method getTimeProportion() + * @for kity.Timeline + * @grammar getTimeProportion() => {Number} + * @description 获得当前播放时间的比例,取值区间为 [0, 1] + */ + getTimeProportion: function() { + return this.getPlayTime() / this.duration; + }, + /** + * @method getValueProportion() + * @for kity.Timeline + * @grammar getValueProportion() => {Number} + * @description 获得当前播放时间对应值的比例,取值区间为 [0, 1];该值实际上是时间比例值经过缓动函数计算之后的值。 + */ + getValueProportion: function() { + return this.easing(this.getPlayTime(), 0, 1, this.duration); + }, + /** + * @method getValue() + * @for kity.Timeline + * @grammar getValue() => {any} + * @description 返回当前播放时间对应的值。 + */ + getValue: function() { + var b = this.beginValue; + var f = this.finishValue; + var p = this.getValueProportion(); + return getPercentValue(b, f, p); + }, + /** + * @private + * + * 把值通过动画器的 setter 设置到目标上 + */ + setValue: function(value) { + this.lastValue = this.currentValue; + this.currentValue = value; + this.setter.call(this.target, this.target, value, this); + }, + /** + * @method getDelta() + * @for kity.Timeline + * @grammar getDelta() => {any} + * @description 返回当前值和上一帧的值的差值 + */ + getDelta: function() { + this.lastValue = this.lastValue === undefined ? this.beginValue : this.lastValue; + return getDelta(this.lastValue, this.currentValue); + }, + /** + * @method play() + * @for kity.Timeline + * @grammar play() => {this} + * @description 让时间线播放,如果时间线还没开始,或者已停止、已结束,则重头播放;如果是已暂停,从暂停的位置继续播放 + */ + play: function() { + var lastStatus = this.status; + this.status = "playing"; + switch (lastStatus) { + case "ready": + if (utils.isFunction(this.beginValue)) { + this.beginValue = this.beginValue.call(this.target, this.target); + } + if (utils.isFunction(this.finishValue)) { + this.finishValue = this.finishValue.call(this.target, this.target); + } + this.time = 0; + this.setValue(this.beginValue); + this.frame = frame.requestFrame(this.nextFrame.bind(this)); + break; + + case "finished": + case "stoped": + this.time = 0; + this.frame = frame.requestFrame(this.nextFrame.bind(this)); + break; + + case "paused": + this.frame.next(); + } + /** + * @event play + * @for kity.Timeline + * @description 在时间线播放后触发 + * + * @param {String} event.lastStatus + * 表示播放前的上一个状态,可能取值为 'ready'、'finished'、'stoped'、'paused' + */ + this.fire("play", new TimelineEvent(this, "play", { + lastStatus: lastStatus + })); + return this; + }, + /** + * @method pause() + * @for kity.Timeline + * @description 暂停当前的时间线 + * + * @grammar pause() => {this} + */ + pause: function() { + this.status = "paused"; + /** + * @event pause + * @for kity.Timeline + * @description 暂停事件,在时间线暂停时触发 + */ + this.fire("pause", new TimelineEvent(this, "pause")); + frame.releaseFrame(this.frame); + return this; + }, + /** + * @method stop() + * @for kity.Timeline + * @description 停止当前时间线 + * + * @grammar stop() => {this} + */ + stop: function() { + this.status = "stoped"; + this.setValue(this.finishValue); + this.rollbacking = false; + /** + * @event stop + * @for kity.Timeline + * @description 停止时间,在时间线停止时触发 + */ + this.fire("stop", new TimelineEvent(this, "stop")); + frame.releaseFrame(this.frame); + return this; + }, + /** + * @private + * + * 播放结束之后的处理 + */ + timeUp: function() { + if (this.repeatOption) { + this.time = 0; + if (this.rollback) { + if (this.rollbacking) { + this.decreaseRepeat(); + this.rollbacking = false; + } else { + this.rollbacking = true; + /** + * @event rollback + * @for kity.Timeline + * @description 回滚事件,在时间线回滚播放开始的时候触发 + */ + this.fire("rollback", new TimelineEvent(this, "rollback")); + } + } else { + this.decreaseRepeat(); + } + if (!this.repeatOption) { + this.finish(); + } else { + /** + * @event repeat + * @for kity.Timeline + * @description 循环事件,在时间线循环播放开始的时候触发 + */ + this.fire("repeat", new TimelineEvent(this, "repeat")); + } + } else { + this.finish(); + } + }, + /** + * @private + * + * 决定播放结束的处理 + */ + finish: function() { + this.setValue(this.finishValue); + this.status = "finished"; + /** + * @event finish + * @for kity.Timeline + * @description 结束事件,在时间线播放结束后触发(包括重复和回滚都结束) + */ + this.fire("finish", new TimelineEvent(this, "finish")); + frame.releaseFrame(this.frame); + }, + /** + * @private + * + * 循环次数递减 + */ + decreaseRepeat: function() { + if (this.repeatOption !== true) { + this.repeatOption--; + } + }, + /** + * @method repeat() + * @for kity.Timeline + * @description 设置时间线的重复选项 + * + * @grammar repeat(repeat, rollback) => {this} + * + * @param {Number|Boolean} repeat + * 是否重复播放,设置为 true 无限循环播放,设置数值则循环指定的次数 + * @param {Boolean} rollback + * 指示是否要回滚播放。 + * 如果设置为真,一次事件到 duration 则一个来回算一次循环次数,否则播放完成一次算一次循环次数 + * + */ + repeat: function(repeat, rollback) { + this.repeatOption = repeat; + this.rollback = rollback; + return this; + } + }); + Timeline.requestFrame = frame.requestFrame; + Timeline.releaseFrame = frame.releaseFrame; + return Timeline; + } +}; + +//src/animate/translateanimator.js +/** + * @fileOverview + * + * 提供让图形移动的动画器 + */ +_p[9] = { + value: function(require) { + var Animator = _p.r(0); + /** + * @class kity.TranslateAnimator + * @base kity.Animator + * @description 提供让图形移动的动画器 + */ + var TranslateAnimator = _p.r(11).createClass("TranslateAnimator", { + base: Animator, + /** + * @constructor + * @for kity.TranslateAnimator + * @grammar new kity.TranslateAnimator(x, y) + * @param {Number} x x 方向上需要移动的距离 + * @param {Number} y y 方向上需要移动的距离 + */ + constructor: function(x, y) { + this.callBase({ + x: 0, + y: 0 + }, { + x: x, + y: y + }, function(target, value, timeline) { + var delta = timeline.getDelta(); + target.translate(delta.x, delta.y); + }); + } + }); + var Shape = _p.r(60); + _p.r(11).extendClass(Shape, { + /** + * @method fxTranslate() + * @for kity.Shape + * @description 让目标以动画平移指定的距离 + * + * @grammar fxTranslate(x, y, duration, easing, delay, callback) => {this} + * + * @param {Number} x x 方向上需要移动的距离 + * @param {Number} y y 方向上需要移动的距离 + * @param {Number|String} duration 动画的播放长度,如 300、"5s"、"0.5min" + * @param {Number|String} delay 动画播放前的延时 + * @param {String|Function} easing 动画播放使用的缓动函数,如 'ease'、'linear'、'swing' + * @param {Function} callback 播放结束之后的回调函数 + */ + fxTranslate: function(x, y, duration, easing, delay, callback) { + return this.animate(new TranslateAnimator(x, y), duration, easing, delay, callback); + } + }); + return TranslateAnimator; + } +}; + +//src/core/browser.js +/** + * @fileOverview + * + * 提供浏览器判断的一些字段 + */ +_p[10] = { + value: function() { + /** + * @class kity.Browser + * @catalog core + * @static + * @description 提供浏览器信息 + */ + var browser = function() { + var agent = navigator.userAgent.toLowerCase(), opera = window.opera, browser; + // 浏览器对象 + browser = { + /** + * @property platform + * @description 获取浏览器所在系统,"Win"->Windows;"Mac"->Mac;"Lux"->Linux + * @type {String} + */ + platform: function(navigator) { + var _p = { + win32: "Win", + macintel: "Mac" + }; + return _p[navigator.platform.toLowerCase()] || "Lux"; + }(navigator), + /** + * 猎豹,区分两种不同内核 + */ + lb: function(agent) { + if (~agent.indexOf("lbbrowser")) { + return ~agent.indexOf("msie") ? "ie" : "chrome"; + } + return false; + }(agent), + /** + * 搜狗 + */ + sg: /se[\s\S]+metasr/.test(agent), + /** + * 百度 + */ + bd: !!~agent.indexOf("bidubrowser"), + /** + * edge浏览器 + */ + edge: !!~agent.indexOf("edge"), + /** + * chrome初始化为false + * @type {Boolean} + */ + chrome: false, + /** + * @property opera + * @for kity.Browser + * @description 判断是否为 Opera 浏览器 + * @type {boolean} + */ + opera: !!opera && opera.version, + /** + * @property webkit + * @for kity.Browser + * @description 判断是否为 Webkit 内核的浏览器 + * @type {boolean} + */ + webkit: agent.indexOf(" applewebkit/") > -1, + /** + * @property mac + * @for kity.Browser + * @description 判断是否为 Mac 下的浏览器 + * @type {boolean} + */ + mac: agent.indexOf("macintosh") > -1 + }; + /** + * @property ie + * @for kity.Browser + * @description 判断是否为 IE 浏览器 + * @type {boolean} + */ + browser.ie = !browser.lb && /(msie\s|trident.*rv:)([\w.]+)/.test(agent); + browser.gecko = navigator.product == "Gecko" && !browser.webkit && !browser.opera && !browser.ie; + var version = 0; + // Internet Explorer 6.0+ + if (browser.ie) { + version = (agent.match(/(msie\s|trident.*rv:)([\w.]+)/)[2] || 0) * 1; + browser.ie11Compat = document.documentMode == 11; + browser.ie9Compat = document.documentMode == 9; + } + // Gecko. + if (browser.gecko) { + var geckoRelease = agent.match(/rv:([\d\.]+)/); + if (geckoRelease) { + geckoRelease = geckoRelease[1].split("."); + version = geckoRelease[0] * 1e4 + (geckoRelease[1] || 0) * 100 + (geckoRelease[2] || 0) * 1; + } + } + // 排除其他chrome内核的浏览器的干扰 + if (/chrome\/(\d+\.\d)/i.test(agent) && !browser.bd && !browser.opera && !browser.lb && !browser.sg && !browser.edge) { + /** + * @property chrome + * @for kity.Browser + * @description 判断是否为 Chrome 浏览器 + * @type {boolean} + */ + browser.chrome = +RegExp["$1"]; + } + if (/(\d+\.\d)?(?:\.\d)?\s+safari\/?(\d+\.\d+)?/i.test(agent) && !/chrome/i.test(agent)) { + browser.safari = +(RegExp["$1"] || RegExp["$2"]); + } + // Opera 9.50+ + if (browser.opera) version = parseFloat(opera.version()); + // WebKit 522+ (Safari 3+) + if (browser.webkit) version = parseFloat(agent.match(/ applewebkit\/(\d+)/)[1]); + // 搜狗版本号无从得知 + // 猎豹版本号无从得知 + // 百度 + if (browser.bd) version = parseFloat(agent.match(/bidubrowser\/(\d+)/)[1]); + // Opera 9.50+ + if (browser.opera) version = parseFloat(agent.match(/opr\/(\d+)/)[1]); + // edge + if (browser.edge) version = parseFloat(agent.match(/edge\/(\d+)/)[1]); + /** + * @property version + * @for kity.Browser + * @description 获取当前浏览器的版本 + * @type {Number} + */ + browser.version = version; + browser.isCompatible = !browser.mobile && (browser.ie && version >= 6 || browser.gecko && version >= 10801 || browser.opera && version >= 9.5 || browser.air && version >= 1 || browser.webkit && version >= 522 || false); + return browser; + }(); + return browser; + } +}; + +//src/core/class.js +/** + * @fileOverview + * + * 提供 Kity 的 OOP 支持 + */ +_p[11] = { + value: function(require, exports) { + /** + * @class kity.Class + * @catalog core + * @description 所有 kity 类的基类 + * @abstract + */ + function Class() {} + exports.Class = Class; + Class.__KityClassName = "Class"; + /** + * @method base() + * @for kity.Class + * @protected + * @grammar base(name, args...) => {any} + * @description 调用父类指定名称的函数 + * @param {string} name 函数的名称 + * @param {parameter} args... 传递给父类函数的参数 + * + * @example + * + * ```js + * var Person = kity.createClass('Person', { + * toString: function() { + * return 'I am a person'; + * } + * }); + * + * var Male = kity.createClass('Male', { + * base: Person, + * + * toString: function() { + * return 'I am a man'; + * }, + * + * speak: function() { + * return this.base('toString') + ',' + this.toString(); + * } + * }) + * ``` + */ + Class.prototype.base = function(name) { + var caller = arguments.callee.caller; + var method = caller.__KityMethodClass.__KityBaseClass.prototype[name]; + return method.apply(this, Array.prototype.slice.call(arguments, 1)); + }; + /** + * @method callBase() + * @for kity.Class + * @protected + * @grammar callBase(args...) => {any} + * @description 调用父类同名函数 + * @param {parameter} args... 传递到父类同名函数的参数 + * + * @example + * + * ```js + * var Animal = kity.createClass('Animal', { + * constructor: function(name) { + * this.name = name; + * }, + * toString: function() { + * return 'I am an animal name ' + this.name; + * } + * }); + * + * var Dog = kity.createClass('Dog', { + * constructor: function(name) { + * this.callBase(name); + * }, + * toString: function() { + * return this.callBase() + ', a dog'; + * } + * }); + * + * var dog = new Dog('Dummy'); + * console.log(dog.toString()); // "I am an animal name Dummy, a dog"; + * ``` + */ + Class.prototype.callBase = function() { + var caller = arguments.callee.caller; + var method = caller.__KityMethodClass.__KityBaseClass.prototype[caller.__KityMethodName]; + return method.apply(this, arguments); + }; + Class.prototype.mixin = function(name) { + var caller = arguments.callee.caller; + var mixins = caller.__KityMethodClass.__KityMixins; + if (!mixins) { + return this; + } + var method = mixins[name]; + return method.apply(this, Array.prototype.slice.call(arguments, 1)); + }; + Class.prototype.callMixin = function() { + var caller = arguments.callee.caller; + var methodName = caller.__KityMethodName; + var mixins = caller.__KityMethodClass.__KityMixins; + if (!mixins) { + return this; + } + var method = mixins[methodName]; + if (methodName == "constructor") { + for (var i = 0, l = method.length; i < l; i++) { + method[i].call(this); + } + return this; + } else { + return method.apply(this, arguments); + } + }; + /** + * @method pipe() + * @for kity.Class + * @grammar pipe() => {this} + * @description 以当前对象为上线文以及管道函数的第一个参数,执行一个管道函数 + * @param {Function} fn 进行管道操作的函数 + * + * @example + * + * ```js + * var rect = new kity.Rect().pipe(function() { + * this.setWidth(500); + * this.setHeight(300); + * }); + * ``` + */ + Class.prototype.pipe = function(fn) { + if (typeof fn == "function") { + fn.call(this, this); + } + return this; + }; + /** + * @method getType() + * @for kity.Class + * @grammar getType() => {string} + * @description 获得对象的类型 + * + * @example + * + * ```js + * var rect = new kity.Rect(); + * var circle = new kity.Circle(); + * + * console.log(rect.getType()); // "Rect" + * console.log(rect.getType()); // "Circle" + * ``` + */ + Class.prototype.getType = function() { + return this.__KityClassName; + }; + /** + * @method getClass() + * @for kity.Class + * @grammar getClass() => {Class} + * @description 获得对象的类 + * + * @example + * + * ```js + * var rect = new kity.Rect(); + * + * console.log(rect.getClass() === kity.Rect); // true + * console.log(rect instanceof kity.Rect); // true + * ``` + */ + Class.prototype.getClass = function() { + return this.constructor; + }; + // 检查基类是否调用了父类的构造函数 + // 该检查是弱检查,假如调用的代码被注释了,同样能检查成功(这个特性可用于知道建议调用,但是出于某些原因不想调用的情况) + function checkBaseConstructorCall(targetClass, classname) { + var code = targetClass.toString(); + if (!/this\.callBase/.test(code)) { + throw new Error(classname + " : 类构造函数没有调用父类的构造函数!为了安全,请调用父类的构造函数"); + } + } + var KITY_INHERIT_FLAG = "__KITY_INHERIT_FLAG_" + +new Date(); + function inherit(constructor, BaseClass, classname) { + var KityClass = eval("(function " + classname + "( __inherit__flag ) {" + "if( __inherit__flag != KITY_INHERIT_FLAG ) {" + "KityClass.__KityConstructor.apply(this, arguments);" + "}" + "this.__KityClassName = KityClass.__KityClassName;" + "})"); + KityClass.__KityConstructor = constructor; + KityClass.prototype = new BaseClass(KITY_INHERIT_FLAG); + for (var methodName in BaseClass.prototype) { + if (BaseClass.prototype.hasOwnProperty(methodName) && methodName.indexOf("__Kity") !== 0) { + KityClass.prototype[methodName] = BaseClass.prototype[methodName]; + } + } + KityClass.prototype.constructor = KityClass; + return KityClass; + } + function mixin(NewClass, mixins) { + if (false === mixins instanceof Array) { + return NewClass; + } + var i, length = mixins.length, proto, method; + NewClass.__KityMixins = { + constructor: [] + }; + for (i = 0; i < length; i++) { + proto = mixins[i].prototype; + for (method in proto) { + if (false === proto.hasOwnProperty(method) || method.indexOf("__Kity") === 0) { + continue; + } + if (method === "constructor") { + // constructor 特殊处理 + NewClass.__KityMixins.constructor.push(proto[method]); + } else { + NewClass.prototype[method] = NewClass.__KityMixins[method] = proto[method]; + } + } + } + return NewClass; + } + function extend(BaseClass, extension) { + if (extension.__KityClassName) { + extension = extension.prototype; + } + for (var methodName in extension) { + if (extension.hasOwnProperty(methodName) && methodName.indexOf("__Kity") && methodName != "constructor") { + var method = BaseClass.prototype[methodName] = extension[methodName]; + method.__KityMethodClass = BaseClass; + method.__KityMethodName = methodName; + } + } + return BaseClass; + } + /** + * @method kity.createClass() + * @grammar kity.createClass(classname, defines) => {Class} + * @description 创建一个类 + * @param {string} classname 类名,用于调试的时候查看,可选 + * @param {object} defines 类定义 + * defines.base {Class} + * 定义的类的基类,如果不配置,则表示基类为 kity.Class + * defines.mixins {Class[]} + * 定义的类要融合的类列表 + * defines.constructor {Function} + * 定义类的构造函数,如果父类显式定义了构造函数,需要在构造函数中使用 callBase() 方法调用父类的构造函数 + * defines.* {Function} + * 定义类的其它函数 + * + * @example 创建一个类 + * + * ```js + * var Animal = kity.createClass('Animal', { + * constructor: function(name) { + * this.name = name; + * }, + * toString: function() { + * return this.name; + * } + * }); + * + * var a = new Animal('kity'); + * console.log(a.toString()); // "kity" + * ``` + * + * @example 继承一个类 + * + * ```js + * var Cat = kity.createClass('Cat', { + * base: Animal, + * constructor: function(name, color) { + * // 调用父类构造函数 + * this.callBase(name); + * }, + * toString: function() { + * return 'A ' + this.color + ' cat, ' + this.callBase(); + * } + * }); + * + * var cat = new Cat('kity', 'black'); + * console.log(cat.toString()); // "A black cat, kity" + * ``` + * + * @example 混合类的能力 + * ```js + * var Walkable = kity.createClass('Walkable', { + * constructor: function() { + * this.speed = 'fast'; + * }, + * walk: function() { + * console.log('I am walking ' + this.speed); + * } + * }); + * + * var Dog = kity.createClass('Dog', { + * base: Animal, + * mixins: [Walkable], + * constructor: function(name) { + * this.callBase(name); + * this.callMixins(); + * } + * }); + * + * var dog = new Dog('doggy'); + * console.log(dog.toString() + ' say:'); + * dog.walk(); + * ``` + */ + exports.createClass = function(classname, defines) { + var constructor, NewClass, BaseClass; + if (arguments.length === 1) { + defines = arguments[0]; + classname = "AnonymousClass"; + } + BaseClass = defines.base || Class; + if (defines.hasOwnProperty("constructor")) { + constructor = defines.constructor; + if (BaseClass != Class) { + checkBaseConstructorCall(constructor, classname); + } + } else { + constructor = function() { + this.callBase.apply(this, arguments); + this.callMixin.apply(this, arguments); + }; + } + NewClass = inherit(constructor, BaseClass, classname); + NewClass = mixin(NewClass, defines.mixins); + NewClass.__KityClassName = constructor.__KityClassName = classname; + NewClass.__KityBaseClass = constructor.__KityBaseClass = BaseClass; + NewClass.__KityMethodName = constructor.__KityMethodName = "constructor"; + NewClass.__KityMethodClass = constructor.__KityMethodClass = NewClass; + // 下面这些不需要拷贝到原型链上 + delete defines.mixins; + delete defines.constructor; + delete defines.base; + NewClass = extend(NewClass, defines); + return NewClass; + }; + /** + * @method kity.extendClass() + * @grammar kity.extendClass(clazz, extension) => {Class} + * @description 拓展一个已有的类 + * + * @example + * + * ```js + * kity.extendClass(Dog, { + * spark: function() { + * console.log('wao wao wao!'); + * } + * }); + * + * new Dog().spark(); // "wao wao wao!"; + * ``` + */ + exports.extendClass = extend; + } +}; + +//src/core/utils.js +/** + * @fileOverview + * + * 一些常用的工具方法 + */ +_p[12] = { + value: function() { + /** + * @class kity.Utils + * @catalog core + * @static + * @description 提供常用的工具方法 + */ + var utils = { + /** + * @method each() + * @for kity.Utils + * @grammar each(obj, interator, context) + * @param {Object|Array} obj 要迭代的对象或数组 + * @param {Function} iterator 迭代函数 + * @param {Any} context 迭代函数的上下文 + * + * @example 迭代数组 + * + * ```js + * kity.Utils.each([1, 2, 3, 4, 5], function(value, index, array) { + * console.log(value, index); + * }); + * // 1, 0 + * // 2, 1 + * // 3, 2 + * // 4, 3 + * // 5, 4 + * ``` + * + * @example 迭代对象 + * + * ```js + * var obj = { + * name: 'kity', + * version: '1.2.1' + * }; + * var param = []; + * kity.Utils.each(obj, function(value, key, obj) { + * param.push(key + '=' + value); + * }); + * console.log(param.join('&')); // "name=kity&version=1.2.1" + * ``` + */ + each: function each(obj, iterator, context) { + if (obj === null) { + return; + } + if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (iterator.call(context, obj[i], i, obj) === false) { + return false; + } + } + } else { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + if (iterator.call(context, obj[key], key, obj) === false) { + return false; + } + } + } + } + }, + /** + * @method extend() + * @for kity.Utils + * @grammar extend(target, sources..., notCover) => {object} + * @description 把源对象的属性合并到目标对象上 + * @param {object} target 目标对象 + * @param {parameter} sources 源对象 + * @param {boolean} notCover 是否不要覆盖源对象已有的属性 + * + * @example + * + * ```js + * var a = { + * key1: 'a1', + * key2: 'a2' + * }; + * + * var b = { + * key2: 'b2', + * key3: 'b3' + * }; + * + * var c = { + * key4: 'c4' + * }; + * + * var d = kity.extend(a, b, c); + * + * console.log(d === a); // true + * console.log(a); // {key1: 'a1', key2: 'b2', key3: 'b3', key4: 'c4'} + * ``` + */ + extend: function extend(t) { + var a = arguments, notCover = this.isBoolean(a[a.length - 1]) ? a[a.length - 1] : false, len = this.isBoolean(a[a.length - 1]) ? a.length - 1 : a.length; + for (var i = 1; i < len; i++) { + var x = a[i]; + for (var k in x) { + if (!notCover || !t.hasOwnProperty(k)) { + t[k] = x[k]; + } + } + } + return t; + }, + /** + * @method deepExtend() + * @for kity.Utils + * @grammar deepExtend(target, sources..., notCover) + * @description 把源对象的属性合并到目标对象上,如果属性是对象,会递归合并 + * @param {object} target 目标对象 + * @param {parameter} sources 源对象 + * @param {boolean} notCover 是否不要覆盖源对象已有的属性 + */ + deepExtend: function(t, s) { + var a = arguments, notCover = this.isBoolean(a[a.length - 1]) ? a[a.length - 1] : false, len = this.isBoolean(a[a.length - 1]) ? a.length - 1 : a.length; + for (var i = 1; i < len; i++) { + var x = a[i]; + for (var k in x) { + if (!notCover || !t.hasOwnProperty(k)) { + if (this.isObject(t[k]) && this.isObject(x[k])) { + this.deepExtend(t[k], x[k], notCover); + } else { + t[k] = x[k]; + } + } + } + } + return t; + }, + /** + * @method clone() + * @for kity.Utils + * @grammar clone(obj) => {object} + * @description 返回一个对象的克隆副本(非深度复制) + * @param {object} obj 要克隆的对象 + * + * @example + * + * ```js + * var source = { + * key1: { + * key2: 'value2' + * }, + * key3: 'value3' + * }; + * + * var target = kity.Utils.clone(source); + * + * console.log(target === source); // false + * console.log(target.key1 === source.key1); // true + * console.log(target.key3 === source.key3); // true + * ``` + */ + clone: function clone(obj) { + var cloned = {}; + for (var m in obj) { + if (obj.hasOwnProperty(m)) { + cloned[m] = obj[m]; + } + } + return cloned; + }, + /** + * @method copy() + * @for kity.Utils + * @grammar copy(obj) => {object} + * @description 返回一个对象的拷贝副本(深度复制) + * @param {object} obj 要拷贝的对象 + * + * @example + * + * ```js + * var source = { + * key1: { + * key2: 'value2' + * }, + * key3: 'value3' + * }; + * + * var target = kity.Utils.copy(source); + * + * console.log(target === source); // false + * console.log(target.key1 === source.key1); // false + * console.log(target.key3 === source.key3); // true,因为是值类型 + * ``` + */ + copy: function copy(obj) { + if (typeof obj !== "object") return obj; + if (typeof obj === "function") return null; + return JSON.parse(JSON.stringify(obj)); + }, + queryPath: function(path, obj) { + var arr = path.split("."); + var i = 0, tmp = obj, l = arr.length; + while (i < l) { + if (arr[i] in tmp) { + tmp = tmp[arr[i]]; + i++; + if (i >= l || tmp === undefined) { + return tmp; + } + } else { + return undefined; + } + } + }, + getValue: function(value, defaultValue) { + return value !== undefined ? value : defaultValue; + }, + /** + * @method flatten() + * @for kity.Utils + * @grammar flatten(arr) => {Array} + * @description 返回给定数组的扁平化版本 + * @param {Array} arr 要扁平化的数组 + * + * @example + * + * ```js + * var flattened = kity.Utils.flatten([[1, 2], [2, 3], [[4, 5], [6, 7]]]); + * console.log(flattened); // [1, 2, 3, 4, 5, 6, 7]; + * ``` + */ + flatten: function flatten(arr) { + var result = [], length = arr.length, i; + for (i = 0; i < length; i++) { + if (arr[i] instanceof Array) { + result = result.concat(utils.flatten(arr[i])); + } else { + result.push(arr[i]); + } + } + return result; + }, + /** + * @method paralle() + * @for kity.Utils + * @grammar paralle() => {Any} + * + * @description 平行地对 v1 和 v2 进行指定的操作 + * + * 如果 v1 是数字,那么直接进行 op 操作 + * 如果 v1 是对象,那么返回一个对象,其元素是 v1 和 v2 同键值的每个元素平行地进行 op 操作的结果 + * 如果 v1 是数组,那么返回一个数组,其元素是 v1 和 v2 同索引的每个元素平行地进行 op 操作的结果 + * + * @param {Number|Object|Array} v1 第一个操作数 + * @param {Number|Object|Array} v2 第二个操作数 + * @param {Function} op 操作函数 + * + * + * + * @example + * + * ```js + * var a = { + * value1: 1, + * value2: 2, + * value3: [3, 4, 5] + * }; + * + * var b = { + * value1: 2, + * value2: 3, + * value3: [4, 5, 6] + * }; + * + * var c = kity.Utils.paralle(a, b, function(v1, v2) { + * return v1 + v2; + * }); + * + * console.log(c.value1); // 3 + * console.log(c.value2); // 5 + * console.log(c.value3); // [7, 9, 11] + * + * ``` + */ + paralle: function paralle(v1, v2, op) { + var Class, field, index, name, value; + // 数组 + if (v1 instanceof Array) { + value = []; + for (index = 0; index < v1.length; index++) { + value.push(utils.paralle(v1[index], v2[index], op)); + } + return value; + } + // 对象 + if (v1 instanceof Object) { + // 如果值是一个支持原始表示的实例,获取其原始表示 + Class = v1.getClass && v1.getClass(); + if (Class && Class.parse) { + v1 = v1.valueOf(); + v2 = v2.valueOf(); + value = utils.paralle(v1, v2, op); + value = Class.parse(value); + } else { + value = {}; + for (name in v1) { + if (v1.hasOwnProperty(name) && v2.hasOwnProperty(name)) { + value[name] = utils.paralle(v1[name], v2[name], op); + } + } + } + return value; + } + // 是否数字 + if (false === isNaN(parseFloat(v1))) { + return op(v1, v2); + } + return value; + }, + /** + * 创建 op 操作的一个平行化版本 + */ + parallelize: function parallelize(op) { + return function(v1, v2) { + return utils.paralle(v1, v2, op); + }; + } + }; + /** + * @method isString() + * @for kity.Utils + * @grammar isString(unknown) => {boolean} + * @description 判断一个值是否为字符串类型 + * @param {any} unknown 要判断的值 + */ + /** + * @method isFunction() + * @for kity.Utils + * @grammar isFunction(unknown) => {boolean} + * @description 判断一个值是否为函数类型 + * @param {any} unknown 要判断的值 + */ + /** + * @method isArray() + * @for kity.Utils + * @grammar isArray(unknown) => {boolean} + * @description 判断一个值是否为数组类型 + * @param {any} unknown 要判断的值 + */ + /** + * @method isNumber() + * @for kity.Utils + * @grammar isNumber(unknown) => {boolean} + * @description 判断一个值是否为数字类型 + * @param {any} unknown 要判断的值 + */ + /** + * @method isRegExp() + * @for kity.Utils + * @grammar isRegExp(unknown) => {boolean} + * @description 判断一个值是否为正则表达式类型 + * @param {any} unknown 要判断的值 + */ + /** + * @method isObject() + * @for kity.Utils + * @grammar isObject(unknown) => {boolean} + * @description 判断一个值是否为对象类型 + * @param {any} unknown 要判断的值 + */ + /** + * @method isBoolean() + * @for kity.Utils + * @grammar isBoolean(unknown) => {boolean} + * @description 判断一个值是否为布尔类型 + * @param {any} unknown 要判断的值 + */ + utils.each([ "String", "Function", "Array", "Number", "RegExp", "Object", "Boolean" ], function(v) { + utils["is" + v] = function typeCheck(obj) { + return Object.prototype.toString.apply(obj) == "[object " + v + "]"; + }; + }); + return utils; + } +}; + +//src/filter/effect/colormatrixeffect.js +/** + * 颜色矩阵运算效果封装 + */ +_p[13] = { + value: function(require, exports, module) { + var Effect = _p.r(16), Utils = _p.r(12); + var ColorMatrixEffect = _p.r(11).createClass("ColorMatrixEffect", { + base: Effect, + constructor: function(type, input) { + this.callBase(Effect.NAME_COLOR_MATRIX); + this.set("type", Utils.getValue(type, ColorMatrixEffect.TYPE_MATRIX)); + this.set("in", Utils.getValue(input, Effect.INPUT_SOURCE_GRAPHIC)); + } + }); + Utils.extend(ColorMatrixEffect, { + // 类型常量 + TYPE_MATRIX: "matrix", + TYPE_SATURATE: "saturate", + TYPE_HUE_ROTATE: "hueRotate", + TYPE_LUMINANCE_TO_ALPHA: "luminanceToAlpha", + // 矩阵常量 + MATRIX_ORIGINAL: "10000010000010000010".split("").join(" "), + MATRIX_EMPTY: "00000000000000000000".split("").join(" ") + }); + return ColorMatrixEffect; + } +}; + +//src/filter/effect/compositeeffect.js +/** + * 高斯模糊效果封装 + */ +_p[14] = { + value: function(require, exports, module) { + var Effect = _p.r(16), Utils = _p.r(12); + var CompositeEffect = _p.r(11).createClass("CompositeEffect", { + base: Effect, + constructor: function(operator, input, input2) { + this.callBase(Effect.NAME_COMPOSITE); + this.set("operator", Utils.getValue(operator, CompositeEffect.OPERATOR_OVER)); + if (input) { + this.set("in", input); + } + if (input2) { + this.set("in2", input2); + } + } + }); + Utils.extend(CompositeEffect, { + // operator 常量 + OPERATOR_OVER: "over", + OPERATOR_IN: "in", + OPERATOR_OUT: "out", + OPERATOR_ATOP: "atop", + OPERATOR_XOR: "xor", + OPERATOR_ARITHMETIC: "arithmetic" + }); + return CompositeEffect; + } +}; + +//src/filter/effect/convolvematrixeffect.js +/** + * 像素级别的矩阵卷积运算效果封装 + */ +_p[15] = { + value: function(require, exports, module) { + var Effect = _p.r(16), Utils = _p.r(12); + var ConvolveMatrixEffect = _p.r(11).createClass("ConvolveMatrixEffect", { + base: Effect, + constructor: function(edgeMode, input) { + this.callBase(Effect.NAME_CONVOLVE_MATRIX); + this.set("edgeMode", Utils.getValue(edgeMode, ConvolveMatrixEffect.MODE_DUPLICATE)); + this.set("in", Utils.getValue(input, Effect.INPUT_SOURCE_GRAPHIC)); + } + }); + Utils.extend(ConvolveMatrixEffect, { + MODE_DUPLICATE: "duplicate", + MODE_WRAP: "wrap", + MODE_NONE: "none" + }); + return ConvolveMatrixEffect; + } +}; + +//src/filter/effect/effect.js +/* + * 效果类 + * 该类型的对象不存储任何内部属性, 所有操作都是针对该类对象所维护的节点进行的 + */ +_p[16] = { + value: function(require, exports, module) { + var svg = _p.r(67), Effect = _p.r(11).createClass("Effect", { + constructor: function(type) { + this.node = svg.createNode(type); + }, + getId: function() { + return this.node.id; + }, + setId: function(id) { + this.node.id = id; + return this; + }, + set: function(key, value) { + this.node.setAttribute(key, value); + return this; + }, + get: function(key) { + return this.node.getAttribute(key); + }, + getNode: function() { + return this.node; + }, + // 返回该效果的result + toString: function() { + return this.node.getAttribute("result") || ""; + } + }); + _p.r(12).extend(Effect, { + // 特效名称常量 + NAME_GAUSSIAN_BLUR: "feGaussianBlur", + NAME_OFFSET: "feOffset", + NAME_COMPOSITE: "feComposite", + NAME_COLOR_MATRIX: "feColorMatrix", + NAME_CONVOLVE_MATRIX: "feConvolveMatrix", + // 输入常量 + INPUT_SOURCE_GRAPHIC: "SourceGraphic", + INPUT_SOURCE_ALPHA: "SourceAlpha", + INPUT_BACKGROUND_IMAGE: "BackgroundImage", + INPUT_BACKGROUND_ALPHA: "BackgroundAlpha", + INPUT_FILL_PAINT: "FillPaint", + INPUT_STROKE_PAINT: "StrokePaint" + }); + return Effect; + } +}; + +//src/filter/effect/gaussianblureffect.js +/** + * 高斯模糊效果封装 + */ +_p[17] = { + value: function(require, exports, module) { + var Effect = _p.r(16), Utils = _p.r(12); + return _p.r(11).createClass("GaussianblurEffect", { + base: Effect, + constructor: function(stdDeviation, input) { + this.callBase(Effect.NAME_GAUSSIAN_BLUR); + this.set("stdDeviation", Utils.getValue(stdDeviation, 1)); + this.set("in", Utils.getValue(input, Effect.INPUT_SOURCE_GRAPHIC)); + } + }); + } +}; + +//src/filter/effect/offseteffect.js +/** + * 偏移效果封装 + */ +_p[18] = { + value: function(require, exports, module) { + var Effect = _p.r(16), Utils = _p.r(12); + return _p.r(11).createClass("OffsetEffect", { + base: Effect, + constructor: function(dx, dy, input) { + this.callBase(Effect.NAME_OFFSET); + this.set("dx", Utils.getValue(dx, 0)); + this.set("dy", Utils.getValue(dy, 0)); + this.set("in", Utils.getValue(input, Effect.INPUT_SOURCE_GRAPHIC)); + } + }); + } +}; + +//src/filter/effectcontainer.js +/* + * Effect所用的container + */ +_p[19] = { + value: function(require) { + return _p.r(11).createClass("EffectContainer", { + base: _p.r(29), + addEffect: function(point, pos) { + return this.addItem.apply(this, arguments); + }, + prependEffect: function() { + return this.prependItem.apply(this, arguments); + }, + appendEffect: function() { + return this.appendItem.apply(this, arguments); + }, + removeEffect: function(pos) { + return this.removeItem.apply(this, arguments); + }, + addEffects: function() { + return this.addItems.apply(this, arguments); + }, + setEffects: function() { + return this.setItems.apply(this, arguments); + }, + getEffect: function() { + return this.getItem.apply(this, arguments); + }, + getEffects: function() { + return this.getItems.apply(this, arguments); + }, + getFirstEffect: function() { + return this.getFirstItem.apply(this, arguments); + }, + getLastEffect: function() { + return this.getLastItem.apply(this, arguments); + }, + handleAdd: function(effectItem, pos) { + var count = this.getEffects().length, nextEffectItem = this.getItem(pos + 1); + // 最后一个节点, 直接追加 + if (count === pos + 1) { + this.node.appendChild(effectItem.getNode()); + return; + } + this.node.insertBefore(effectItem.getNode(), nextEffectItem.getNode()); + } + }); + } +}; + +//src/filter/filter.js +/** + * Filter 基类 + */ +_p[20] = { + value: function(require, exports, module) { + var svg = _p.r(67); + var Class = _p.r(11); + var Filter = Class.createClass("Filter", { + mixins: [ _p.r(19) ], + constructor: function(x, y, width, height) { + this.node = svg.createNode("filter"); + if (x !== undefined) { + this.set("x", x); + } + if (y !== undefined) { + this.set("y", y); + } + if (width !== undefined) { + this.set("width", width); + } + if (height !== undefined) { + this.set("height", height); + } + }, + getId: function() { + return this.id; + }, + setId: function(id) { + this.node.id = id; + return this; + }, + set: function(key, value) { + this.node.setAttribute(key, value); + return this; + }, + get: function(key) { + return this.node.getAttribute(key); + }, + getNode: function() { + return this.node; + } + }); + var Shape = _p.r(60); + Class.extendClass(Shape, { + applyFilter: function(filter) { + var filterId = filter.get("id"); + if (filterId) { + this.node.setAttribute("filter", "url(#" + filterId + ")"); + } + return this; + } + }); + return Filter; + } +}; + +//src/filter/gaussianblurfilter.js +/* + * 高斯模糊滤镜 + */ +_p[21] = { + value: function(require, exports, module) { + var GaussianblurEffect = _p.r(17); + return _p.r(11).createClass("GaussianblurFilter", { + base: _p.r(20), + constructor: function(stdDeviation) { + this.callBase(); + this.addEffect(new GaussianblurEffect(stdDeviation)); + } + }); + } +}; + +//src/filter/projectionfilter.js +/* + * 投影滤镜 + */ +_p[22] = { + value: function(require, exports, module) { + var GaussianblurEffect = _p.r(17), Effect = _p.r(16), ColorMatrixEffect = _p.r(13), Color = _p.r(28), Utils = _p.r(12), CompositeEffect = _p.r(14), OffsetEffect = _p.r(18); + return _p.r(11).createClass("ProjectionFilter", { + base: _p.r(20), + constructor: function(stdDeviation, dx, dy) { + this.callBase(); + this.gaussianblurEffect = new GaussianblurEffect(stdDeviation, Effect.INPUT_SOURCE_ALPHA); + this.gaussianblurEffect.set("result", "gaussianblur"); + this.addEffect(this.gaussianblurEffect); + this.offsetEffect = new OffsetEffect(dx, dy, this.gaussianblurEffect); + this.offsetEffect.set("result", "offsetBlur"); + this.addEffect(this.offsetEffect); + this.colorMatrixEffect = new ColorMatrixEffect(ColorMatrixEffect.TYPE_MATRIX, this.offsetEffect); + this.colorMatrixEffect.set("values", ColorMatrixEffect.MATRIX_ORIGINAL); + this.colorMatrixEffect.set("result", "colorOffsetBlur"); + this.addEffect(this.colorMatrixEffect); + this.compositeEffect = new CompositeEffect(CompositeEffect.OPERATOR_OVER, Effect.INPUT_SOURCE_GRAPHIC, this.colorMatrixEffect); + this.addEffect(this.compositeEffect); + }, + // 设置投影颜色 + setColor: function(color) { + var matrix = null, originMatrix = null, colorValue = []; + if (Utils.isString(color)) { + color = Color.parse(color); + } + if (!color) { + return this; + } + matrix = ColorMatrixEffect.MATRIX_EMPTY.split(" "); + colorValue.push(color.get("r")); + colorValue.push(color.get("g")); + colorValue.push(color.get("b")); + // rgb 分量更改 + for (var i = 0, len = colorValue.length; i < len; i++) { + matrix[i * 5 + 3] = colorValue[i] / 255; + } + // alpha 分量更改 + matrix[18] = color.get("a"); + this.colorMatrixEffect.set("values", matrix.join(" ")); + return this; + }, + // 设置投影透明度 + setOpacity: function(opacity) { + var matrix = this.colorMatrixEffect.get("values").split(" "); + matrix[18] = opacity; + this.colorMatrixEffect.set("values", matrix.join(" ")); + return this; + }, + // 设置阴影偏移量 + setOffset: function(dx, dy) { + this.setOffsetX(dx); + this.setOffsetY(dy); + }, + setOffsetX: function(dx) { + this.offsetEffect.set("dx", dx); + }, + setOffsetY: function(dy) { + this.offsetEffect.set("dy", dy); + }, + setDeviation: function(deviation) { + this.gaussianblurEffect.set("stdDeviation", deviation); + } + }); + } +}; + +//src/graphic/bezier.js +/** + * @fileOverview + * + * 贝塞尔曲线 + */ +_p[23] = { + value: function(require, exports, module) { + /** + * @class kity.Bezier + * @mixins kity.PointContainer + * @base kity.Path + * @description 绘制和使用贝塞尔曲线。贝塞尔曲线作为一个贝塞尔点的容器,任何贝塞尔点的改变都会更改贝塞尔曲线的外观 + */ + return _p.r(11).createClass("Bezier", { + mixins: [ _p.r(51) ], + base: _p.r(46), + /** + * @constructor + * @for kity.Bezier + * + * @grammar new kity.Bezier(bezierPoints) + * + * @param {kity.BezierPoints[]} bezierPoints 贝塞尔点集合,每个元素应该是 {kity.BezierPoint} 类型 + * + * @example + * + * ```js + * var bezier = new kity.Bezier([ + * new kity.BezierPoint(0, 0).setForward(100, 0), + * new kity.BezierPoint(100, 100).setBackward(100, 0) + * ]); + * ``` + */ + constructor: function(bezierPoints) { + this.callBase(); + bezierPoints = bezierPoints || []; + this.changeable = true; + this.setBezierPoints(bezierPoints); + }, + /** + * @method getBezierPoints() + * @for kity.Bezier + * @description 返回当前贝塞尔曲线的贝塞尔点集合 + * + * @grammar getBezierPoints() => {kity.BezierPoints[]} + * + */ + getBezierPoints: function() { + return this.getPoints(); + }, + /** + * @method setBezierPoints() + * @for kity.Bezier + * @description 设置当前贝塞尔曲线的贝塞尔点集合 + * + * @grammar setBeizerPoints(bezierPoints) => {this} + * + * @param {kity.BezierPoint[]} bezierPoints 贝塞尔点集合 + */ + setBezierPoints: function(bezierPoints) { + return this.setPoints(bezierPoints); + }, + //当点集合发生变化时采取的动作 + onContainerChanged: function() { + if (this.changeable) { + this.update(); + } + }, + update: function() { + var drawer = null, bezierPoints = this.getBezierPoints(); + //单独的一个点不画任何图形 + if (bezierPoints.length < 2) { + return; + } + drawer = this.getDrawer(); + drawer.clear(); + var vertex = bezierPoints[0].getVertex(), forward = null, backward = null; + drawer.moveTo(vertex.x, vertex.y); + for (var i = 1, len = bezierPoints.length; i < len; i++) { + vertex = bezierPoints[i].getVertex(); + backward = bezierPoints[i].getBackward(); + forward = bezierPoints[i - 1].getForward(); + drawer.bezierTo(forward.x, forward.y, backward.x, backward.y, vertex.x, vertex.y); + } + return this; + } + }); + } +}; + +//src/graphic/bezierpoint.js +/** + * @fileOverview + * + * 表示一个贝塞尔点 + */ +_p[24] = { + value: function(require, exports, module) { + var ShapePoint = _p.r(63); + var Vector = _p.r(73); + /** + * @class kity.BezierPoint + * + * @description 表示一个贝塞尔点 + * 一个贝塞尔点由顶点坐标(曲线经过的点)、前方控制点、后方控制点表示 + */ + var BezierPoint = _p.r(11).createClass("BezierPoint", { + /** + * @constructor + * @for kity.BezierPoint + * + * @description 创建一个具有默认顶点坐标的贝塞尔点,两个控制点的坐标和顶点一致 + * + * @param {Number} x 顶点的 x 坐标 + * @param {Number} y 顶点的 y 坐标 + * @param {Boolean} isSmooth 指示当前贝塞尔点是否光滑,光滑会约束顶点和两个控制点共线 + */ + constructor: function(x, y, isSmooth) { + //顶点 + this.vertex = new ShapePoint(x, y); + //控制点 + this.forward = new ShapePoint(x, y); + this.backward = new ShapePoint(x, y); + //是否平滑 + this.setSmooth(isSmooth === undefined || isSmooth); + this.setSymReflaction(true); + }, + /** + * @method clone() + * @for kity.BezierPoint + * @description 返回贝塞尔点的一份拷贝 + * + * @grammar clone() => {kity.BezierPoint} + */ + clone: function() { + var newPoint = new BezierPoint(), tmp = null; + tmp = this.getVertex(); + newPoint.setVertex(tmp.x, tmp.y); + tmp = this.getForward(); + newPoint.setForward(tmp.x, tmp.y); + tmp = this.getBackward(); + newPoint.setBackward(tmp.x, tmp.y); + newPoint.setSymReflaction(this.isSymReflaction); + newPoint.setSmooth(this.isSmooth()); + return newPoint; + }, + /** + * @method setVertex() + * @for kity.BezierPoint + * @description 设置贝塞尔点的顶点坐标,注意,控制点的坐标不会跟着变化。希望控制点的坐标跟着变化,请用 moveTo() 方法 + * + * @grammar setVertex(x, y) => {this} + * + * @param {Number} x 顶点的 x 坐标 + * @param {Number} y 顶点的 y 坐标 + */ + setVertex: function(x, y) { + this.vertex.setPoint(x, y); + this.update(); + return this; + }, + /** + * @method moveTo() + * @for kity.BezierPoint + * @description 同步移动整个贝塞尔点,使顶点的移动到指定的坐标中。控制点的位置相对顶点坐标固定。 + * + * @grammar moveTo() => {this} + * + * @param {Number} x 顶点的目标 x 坐标 + * @param {Number} y 顶点的目标 y 坐标 + * + */ + moveTo: function(x, y) { + var oldForward = this.forward.getPoint(), oldBackward = this.backward.getPoint(), oldVertex = this.vertex.getPoint(), //移动距离 + distance = { + left: x - oldVertex.x, + top: y - oldVertex.y + }; + // 更新 + this.forward.setPoint(oldForward.x + distance.left, oldForward.y + distance.top); + this.backward.setPoint(oldBackward.x + distance.left, oldBackward.y + distance.top); + this.vertex.setPoint(x, y); + this.update(); + }, + /** + * @method setForward() + * @for kity.BezierPoint + * @description 设置前方控制点的位置,如果贝塞尔点光滑,后方控制点会跟着联动 + * + * @grammar setForward(x, y) => {this} + * + * @param {Number} x 前方控制点的 x 坐标 + * @param {Number} y 前方控制点的 y 坐标 + */ + setForward: function(x, y) { + this.forward.setPoint(x, y); + //更新后置点 + if (this.smooth) { + this.updateAnother(this.forward, this.backward); + } + this.update(); + this.lastControlPointSet = this.forward; + return this; + }, + /** + * @method setBackward() + * @for kity.BezierPoint + * @description 设置后方控制点的位置,如果贝塞尔点光滑,前方控制点会跟着联动 + * + * @grammar setBackward(x, y) => {this} + * + * @param {Number} x 后方控制点的 x 坐标 + * @param {Number} y 后方控制点的 y 坐标 + */ + setBackward: function(x, y) { + this.backward.setPoint(x, y); + //更新前置点 + if (this.smooth) { + this.updateAnother(this.backward, this.forward); + } + this.update(); + this.lastControlPointSet = this.backward; + return this; + }, + /** + * @method setSymReflaction() + * @for kity.BezierPoint + * @description 设定是否镜像两个控制点的位置 + * + * @grammar setSymReflaction(value) => {this} + * + * @param {boolean} value 如果设置为 true,且贝塞尔点光滑,两个控制点离顶点的距离相等 + */ + setSymReflaction: function(value) { + this.symReflaction = value; + if (this.smooth) this.setSmooth(true); + return this; + }, + /** + * @method isSymReflaction() + * @for kity.BezierPoint + * @description 当前贝塞尔点的两个控制点是否被镜像约束 + * + * @grammar isSymReflaction() => {boolean} + */ + isSymReflaction: function() { + return this.symReflaction; + }, + /** + * @private + * + * 根据前方控制点或后方控制点更新另一方 + */ + updateAnother: function(p, q) { + var v = this.getVertex(), pv = Vector.fromPoints(p.getPoint(), v), vq = Vector.fromPoints(v, q.getPoint()); + vq = pv.normalize(this.isSymReflaction() ? pv.length() : vq.length()); + q.setPoint(v.x + vq.x, v.y + vq.y); + return this; + }, + /** + * @method setSmooth() + * @for kity.BezierPoint + * @description 设置贝塞尔点是否光滑,光滑会约束顶点和两个控制点共线 + * + * @param {Boolean} isSmooth 设置为 true 让贝塞尔点光滑 + */ + setSmooth: function(isSmooth) { + var lc; + this.smooth = !!isSmooth; + if (this.smooth && (lc = this.lastControlPointSet)) { + this.updateAnother(lc, lc == this.forward ? this.backward : this.forward); + } + return this; + }, + /** + * @method isSmooth() + * @for kity.BezierPoint + * @description 判断贝塞尔点是否光滑 + * + * @grammar isSmooth() => {boolean} + */ + isSmooth: function() { + return this.smooth; + }, + /** + * @method getVertex() + * @for kity.BezierPoint + * @description 获得当前贝塞尔点的顶点 + * + * @grammar getVertex() => {kity.ShapePoint} + */ + getVertex: function() { + return this.vertex.getPoint(); + }, + /** + * @method getForward() + * @for kity.BezierPoint + * @description 获得当前贝塞尔点的前方控制点 + * + * @grammar getForward() => {kity.ShapePoint} + */ + getForward: function() { + return this.forward.getPoint(); + }, + /** + * @method getBackward() + * @for kity.BezierPoint + * @description 获得当前贝塞尔点的后方控制点 + * + * @grammar getBackward() => {kity.ShapePoint} + */ + getBackward: function() { + return this.backward.getPoint(); + }, + /** + * @private + * + * 联动更新相关的贝塞尔曲线 + */ + update: function() { + if (!this.container) { + return this; + } + //新增参数 this, 把当前引起变化的点传递过去, 以便有需要的地方可以获取到引起变化的源 + if (this.container.update) this.container.update(this); + } + }); + return BezierPoint; + } +}; + +//src/graphic/box.js +/** + * @fileOverview + * + * 表示一个矩形区域 + */ +_p[25] = { + value: function(require, exports, module) { + /** + * @class kity.Box + * @description 表示一个矩形区域 + */ + var Box = _p.r(11).createClass("Box", { + /** + * @constructor + * @for kity.Box + * + * @grammar new kity.Box(x, y, width, height) + * @grammar new kity.Box(box) + * + * @param {Number} x|box.x 矩形区域的 x 坐标 + * @param {Number} y|box.y 矩形区域的 y 坐标 + * @param {Number} width|box.width 矩形区域的宽度 + * @param {Number} height|box.height 矩形区域的高度 + * + * @example + * + * ```js + * var box = new kity.Box(10, 20, 50, 50); + * var box2 = new kity.Box({x: 10, y: 20, width: 50, height: 50}); + * ``` + */ + constructor: function(x, y, width, height) { + var box = arguments[0]; + if (box && typeof box === "object") { + x = box.x; + y = box.y; + width = box.width; + height = box.height; + } + if (width < 0) { + x -= width = -width; + } + if (height < 0) { + y -= height = -height; + } + /** + * @property x + * @for kity.Box + * @type {Number} + * @readOnly + * @description 矩形区域的 x 坐标 + */ + this.x = x || 0; + /** + * @property y + * @for kity.Box + * @type {Number} + * @readOnly + * @description 矩形区域的 y 坐标 + */ + this.y = y || 0; + /** + * @property width + * @for kity.Box + * @type {Number} + * @readOnly + * @description 矩形区域的宽度 + */ + this.width = width || 0; + /** + * @property height + * @for kity.Box + * @type {Number} + * @readOnly + * @description 矩形区域的高度 + */ + this.height = height || 0; + /** + * @property left + * @for kity.Box + * @type {Number} + * @readOnly + * @description 矩形区域的最左侧坐标,等价于 x 的值 + */ + this.left = this.x; + /** + * @property right + * @for kity.Box + * @type {Number} + * @readOnly + * @description 矩形区域的最右侧坐标,等价于 x + width 的值 + */ + this.right = this.x + this.width; + /** + * @property top + * @for kity.Box + * @type {Number} + * @readOnly + * @description 矩形区域的最上侧坐标,等价于 y 的值 + */ + this.top = this.y; + /** + * @property bottom + * @for kity.Box + * @type {Number} + * @readOnly + * @description 矩形区域的最下侧坐标,等价于 y + height 的值 + */ + this.bottom = this.y + this.height; + /** + * @property cx + * @for kity.Box + * @type {Number} + * @readOnly + * @description 矩形区域的中心 x 坐标 + */ + this.cx = this.x + this.width / 2; + /** + * @property cy + * @for kity.Box + * @type {Number} + * @readOnly + * @description 矩形区域的中心 y 坐标 + */ + this.cy = this.y + this.height / 2; + }, + /** + * @method getRangeX() + * @for kity.Box + * @description 获得矩形区域的 x 值域 + * + * @grammar getRangeX() => {Number[]} + * + * @example + * + * var box = new kity.Box(10, 10, 30, 50); + * console.log(box.getRangeX()); // [10, 40] + */ + getRangeX: function() { + return [ this.left, this.right ]; + }, + /** + * @method getRangeY() + * @for kity.Box + * @description 获得矩形区域的 y 值域 + * + * @grammar getRangeY() => {Number[]} + * + * @example + * + * var box = new kity.Box(10, 10, 30, 50); + * console.log(box.getRangeY()); // [10, 60] + */ + getRangeY: function() { + return [ this.top, this.bottom ]; + }, + /** + * @method merge() + * @for kity.Box + * @description 把当前矩形区域和指定的矩形区域合并,返回一个新的矩形区域(即包含两个源矩形区域的最小矩形区域) + * + * @grammar merge(another) => {kity.Box} + * @param {kity.Box} another 要合并的矩形区域 + * + * @example + * + * ```js + * var box1 = new kity.Box(10, 10, 50, 50); + * var box2 = new kity.Box(30, 30, 50, 50); + * var box3 = box1.merge(box2); + * console.log(box3.valueOf()); // [10, 10, 70, 70] + * ``` + */ + merge: function(another) { + if (this.isEmpty()) { + return new Box(another.x, another.y, another.width, another.height); + } + var left = Math.min(this.left, another.left), right = Math.max(this.right, another.right), top = Math.min(this.top, another.top), bottom = Math.max(this.bottom, another.bottom); + return new Box(left, top, right - left, bottom - top); + }, + /** + * @method intersect() + * @for kity.Box + * @description 求当前矩形区域和指定的矩形区域重叠的矩形区域 + * + * @grammar intersect(another) => {kity.Box} + * @param {kity.Box} another 要求重叠的矩形区域 + * + * @example + * + * ```js + * var box1 = new kity.Box(10, 10, 50, 50); + * var box2 = new kity.Box(30, 30, 50, 50); + * var box3 = box1.intersect(box2); + * console.log(box3.valueOf()); // [30, 30, 20, 20] + * ``` + */ + intersect: function(another) { + if (!another instanceof Box) { + another = new Box(another); + } + var left = Math.max(this.left, another.left), right = Math.min(this.right, another.right), top = Math.max(this.top, another.top), bottom = Math.min(this.bottom, another.bottom); + if (left > right || top > bottom) return new Box(); + return new Box(left, top, right - left, bottom - top); + }, + /** + * @method expand() + * @for kity.Box + * @description 扩展(或收缩)当前的盒子,返回新的盒子 + * + * @param {Number} top + * 矩形区域的上边界往上扩展的值;如果是负数,则上边界往下收缩 + * + * @param {Number} right + * [Optional] 矩形区域的右边界往右拓展的值; + * 如果是负数,则右边界往左收缩; + * 如果不设置该值,使用和 top 同样的值。 + * + * @param {Number} bottom + * [Optional] 矩形区域的下边界往下拓展的值; + * 如果是负数,则下边界往上收缩; + * 如果不设置该值,使用和 top 同样的值。 + * + * @param {Number} left + * [Optional] 矩形区域的左边界往左拓展的值; + * 如果是负数,则左边界往右收缩; + * 如果不设置该值,使用和 right 同样的值。 + * + * @example + * + * ```js + * var box = new kity.Box(10, 10, 20, 20); + * var box1 = box.expand(10); // [0, 0, 40, 40] + * var box2 = box.expand(10, 20); // [0, -10, 40, 60] + * var box3 = box.expand(1, 2, 3, 4); // [9, 8, 24, 26] + * ``` + */ + expand: function(top, right, bottom, left) { + if (arguments.length < 1) { + return new Box(this); + } + if (arguments.length < 2) { + right = top; + } + if (arguments.length < 3) { + bottom = top; + } + if (arguments.length < 4) { + left = right; + } + var x = this.left - left, y = this.top - top, width = this.width + right, height = this.height + top; + return new Box(x, y, width, height); + }, + /** + * @method valueOf() + * @for kity.Box + * @description 返回当前盒子的数组表示 + * + * @grammar valueOf() => {Number[]} + * + * @example + * + * ```js + * var box = new kity.Box(0, 0, 200, 50); + * console.log(box.valueOf()); // [0, 0, 200, 50] + * ``` + */ + valueOf: function() { + return [ this.x, this.y, this.width, this.height ]; + }, + /** + * @method toString() + * @for kity.Box + * @description 返回当前盒子的字符串表示 + * + * @grammar toString() => {String} + * + * @example + * + * ```js + * var box = new kity.Box(0, 0, 200, 50); + * console.log(box.toString()); // "0 0 200 50" + */ + toString: function() { + return this.valueOf().join(" "); + }, + /** + * @method isEmpty() + * @for kity.Box + * @description 判断当前盒子是否具有尺寸(面积大 + * + * @grammar isEmpty() => {boolean} + * + * @example + * ```js + * var box = new kity.Box(0, 0, 0, 100000); + * console.log(box.isEmpty()); // true + * ``` + */ + isEmpty: function() { + return !this.width || !this.height; + } + }); + /** + * @method parse() + * @static + * @for kity.Box + * @description 解析一个字符串或数组为 kity.Box 对象 + * + * @grammar kity.Box.parse(any) => {kity.Box} + * + * @param {Number[]|String} any 要解析的字符串或数组 + * + * @example + * + * ```js + * console.log(kity.Box.parse('0 0 100 200')); + * console.log(kity.Box.parse([0, 0, 100, 200])); + * ``` + */ + Box.parse = function(any) { + if (typeof any == "string") { + return Box.parse(any.split(/[\s,]+/).map(parseFloat)); + } + if (any instanceof Array) { + return new Box(any[0], any[1], any[2], any[3]); + } + if ("x" in any) return new Box(any); + return null; + }; + return Box; + } +}; + +//src/graphic/circle.js +/** + * @fileOverview + * + * 绘制和使用圆形 + */ +_p[26] = { + value: function(require, exports, module) { + /** + * @class kity.Circle + * @base kity.Ellipse + * @description 表示一个圆形 + */ + return _p.r(11).createClass("Circle", { + base: _p.r(32), + /** + * @constructor + * @for kity.Circle + * + * @grammar new kity.Circle(radius, cx, cy) + * + * @param {Number} radius 半径 + * @param {Number} cx 圆心 x 坐标 + * @param {Number} cy 圆心 y 坐标 + */ + constructor: function(radius, cx, cy) { + this.callBase(radius, radius, cx, cy); + }, + /** + * @method + * @for kity.Circle + * @description 获取圆形的半径 + * + * @grammar getRadius() => {Number} + */ + getRadius: function() { + return this.getRadiusX(); + }, + /** + * @method + * @for kity.Circle + * @description 设置圆形的半径 + * + * @grammar setRadius() => {this} + * + * @param {Number} radius 半径大小 + */ + setRadius: function(radius) { + return this.callBase(radius, radius); + } + }); + } +}; + +//src/graphic/clip.js +/** + * @fileOverview + * + * 支持图形裁切 + */ +_p[27] = { + value: function(require, exports, module) { + var Class = _p.r(11); + var Shape = _p.r(60); + /** + * @class kity.Clip + * @base kity.Resource + * @mixins kity.ShapeContainer + * + * @description 创建图形裁切,用于裁切目标图形 + */ + var Clip = Class.createClass("Clip", { + base: Shape, + mixins: [ _p.r(61) ], + /** + * @constructor + * @for kity.Clip + * + * @grammar new kity.Clip(paper) + * + * @param {kity.Paper} paper 资源所属的文档 + * + * @example + * + * ```js + * var circle = paper.put(new kity.Circle(100).fill('yellow')); + * var clip = new kity.Clip(paper); + * clip.addShape(new kity.Circle(100, 50, 0)); + * clip.clip(circle); + * ``` + */ + constructor: function(paper) { + this.callBase("clipPath", paper); + }, + /** + * @method clip() + * @for kity.Clip + * @description 将裁切应用到指定的图形上,应用之后,目标图形将显示与裁切形状重合的部分 + * + * @grammar clip(shape) => {this} + * + * @param {kity.Shape} shape 要应用裁切的图形 + */ + clip: function(shape) { + shape.getNode().setAttribute("clip-path", this); + return this; + } + }); + Class.extendClass(Shape, { + /** + * @method clipWidth() + * @for kity.Shape + * + * @grammar clipWidth(clip) => {this} + * + * @param {kity.Clip|kity.Shape} clip 要用于裁切当前图形的图形; + * 如果 clip 本身是一个裁切对象(kity.Clip 类型),则直接裁切; + * 否则将创建新的裁切包含给定的图形,然后对当前图形进行裁切 + * + * @example + * + * ```js + * var circle = paper.put(new kity.Circle(100)); + * var rect = paper.put(new kity.Rect(100, 100, -100, 0)); + * + * circle.clipWidth(rect); + * ``` + */ + clipWith: function(clip) { + if (clip instanceof Shape) { + clip = new Clip(clip.getPaper()).addShape(clip); + } + clip.clip(this); + return this; + } + }); + return Clip; + } +}; + +//src/graphic/color.js +/** + * @fileOverview + * + * 提供颜色支持 + */ +_p[28] = { + value: function(require, exports, module) { + var Utils = _p.r(12), StandardColor = _p.r(64), ColorUtils = {}, /** + * @class kity.Color + * @description 表示一个颜色 + */ + Color = _p.r(11).createClass("Color", { + /** + * @constructor + * @for kity.Color + * + * @grammar new kity.Color(r, g, b) + * @grammar new kity.Color(r, g, b, a) + * @grammar new kity.Color(colorString) + * + * @param {Number} r 红色分量,取值 0 - 255 + * @param {Number} g 绿色分量,取值 0 - 255 + * @param {Number} b 蓝色分量,取值 0 - 255 + * @param {Number} a 透明度(可选),取值 0 - 100 + * @param {String} colorString 一个代表颜色的字符串,可以是: + * 熟知颜色表:如 'red', 'yellow' + * HEX 表示:如 '#368', '#123456' + * RGB 表示:如 'RGB(200, 200, 0)', 'RGBA(200, 200, 200, .5)' + * HSL 表示:如 'HSL(100, 60%, 80%)', 'HSLA(100, 60%, 80%, .5)' + */ + constructor: function() { + var colorValue = null; + //parse构造 + if (typeof arguments[0] === "string") { + colorValue = ColorUtils.parseToValue(arguments[0]); + //解析失败 + if (colorValue === null) { + colorValue = { + r: 0, + g: 0, + b: 0, + h: 0, + s: 0, + l: 0, + a: 1 + }; + } + } else { + colorValue = { + r: arguments[0] | 0, + g: arguments[1] | 0, + b: arguments[2] | 0, + //alpha 默认为1 + a: arguments[3] === undefined ? 1 : parseFloat(arguments[3]) + }; + colorValue = ColorUtils.overflowFormat(colorValue); + //获取hsl分量 + colorValue = Utils.extend(colorValue, ColorUtils.rgbValueToHslValue(colorValue)); + } + this._color = colorValue; + }, + /** + * @method set() + * @for kity.Color + * + * @description 设置当前颜色某个分量的值 + * + * @grammar set(name, value) => {this} + * + * @param {string} name 要设置的颜色通道的名称 + * r: 红色(Red),取值范围 [0, 255] + * g: 绿色(Green),取值范围 [0, 255] + * b: 蓝色(Blue),取值范围 [0, 255] + * a: 透明度(Alpha),取值范围 [0, 1] + * h: 色环角度(Hue),取值范围 [0, 359] + * s: 饱和度(Saturation),取值范围 [0, 100] + * l: 亮度(Lightness),取值范围 [0, 100] + * r、g、b 值和 h、s、l 值会联动修改 + * @param {number} value 要设置的值 + */ + set: function(name, value) { + var values = null; + //设置的值非法 + if (!Color._MAX_VALUE[name]) { + throw new Error("Color set(): Illegal parameter"); + } + if (name !== "a") { + value = Math.floor(value); + } + if (name == "h") { + value = (value + 360) % 360; + } + this._color[name] = Math.max(Color._MIN_VALUE[name], Math.min(Color._MAX_VALUE[name], value)); + if ("rgb".indexOf(name) !== -1) { + this._color = Utils.extend(this._color, ColorUtils.rgbValueToHslValue(this._color)); + } else if ("hsl".indexOf(name) !== -1) { + this._color = Utils.extend(this._color, ColorUtils.hslValueToRGBValue(this._color)); + } + return this; + }, + /** + * @method inc() + * + * @description 返回新的颜色,表示当前颜色增加指定通道的值之后的颜色 + * + * @grammar inc(name, value) => {this} + * + * @param {string} name 要增加的通道的名称,具体含义请查看 set 方法 + * @param {number} value 增量值 + */ + inc: function(name, value) { + value = this.get(name) + value; + if (name == "h") { + value = (value + 360) % 360; + } else { + value = Math.min(Color._MAX_VALUE[name], value); + value = Math.max(Color._MIN_VALUE[name], value); + } + return this.clone().set(name, value); + }, + /** + * @method dec() + * @for kity.Color + * + * @description 返回新的颜色,表示当前颜色减少指定通道的值之后的颜色 + * + * @grammar dec(name, value) => {this} + * + * @param {string} name 要减少值的通道的名称,具体含义请查看 set 方法 + * @param {number} value 减量值 + */ + dec: function(name, value) { + return this.inc(name, -value); + }, + /** + * @method clone() + * @for kity.Color + * + * @description 返回当前颜色的一个拷贝 + * + * @grammar clone() => {kity.Color} + */ + clone: function() { + return new Color(this.toRGBA()); + }, + /** + * @method get() + * @for kity.Color + * + * @description 返回当前颜色指定的分量 + * + * @grammar get() => {number} + */ + get: function(name) { + if (!Color._MAX_VALUE[name]) { + return null; + } + return this._color[name]; + }, + getValues: function() { + return Utils.clone(this._color); + }, + /** + * @method valueOf() + * @for kity.Color + * + * @description 返回当前颜色的一个字面量表示 + * + * @return {plain} 颜色字面量,其结构为: + * { + * r: 0, + * g: 0, + * b: 0, + * a: 0, + * h: 0, + * s: 0, + * l: 0 + * } + */ + valueOf: function() { + return this.getValues(); + }, + /** + * @method toRGB() + * @for kity.Color + * + * @description 返回当前颜色的 RGB 表示,如果颜色有透明度,将抛弃透明度属性(想要保留请使用 toRGBA())方法。 + * + * @grammar toRGB() => {string} + */ + toRGB: function() { + return ColorUtils.toString(this._color, "rgb"); + }, + /** + * @method toRGBA() + * @for kity.Color + * + * @description 返回当前颜色的 RGBA 表示 + * + * @grammar toRGBA() => {string} + */ + toRGBA: function() { + return ColorUtils.toString(this._color, "rgba"); + }, + /** + * @method toHEX() + * @for kity.Color + * + * @description 返回当前颜色的 HEX 表示,如果颜色有透明度,将抛弃透明度属性(想要保留请使用 toRGBA())方法。 + * + * @grammar toHEX() => {string} + */ + toHEX: function() { + return ColorUtils.toString(this._color, "hex"); + }, + /** + * @method toHSL() + * @for kity.Color + * + * @description 返回当前颜色的 HSL 表示,如果颜色有透明度,将抛弃透明度属性(想要保留请使用 toHSLA())方法。 + * + * @grammar toHSL() => {string} + */ + toHSL: function() { + return ColorUtils.toString(this._color, "hsl"); + }, + /** + * @method toHSLA() + * @for kity.Color + * + * @description 返回当前颜色的 HSLA 表示 + * + * @grammar toHSLA() => {string} + */ + toHSLA: function() { + return ColorUtils.toString(this._color, "hsla"); + }, + /** + * @method toString() + * @for kity.Color + * + * @description 返回当前颜色的 RGB 或 RGBA 表示,如果颜色有透明度,将使用 RGBA 形式,否则是 RGB 形式 + * @grammar toString() => {string} + */ + toString: function() { + if (this._color.a === 1) { + return this.toRGB(); + } + return this.toRGBA(); + } + }); + //Color 静态方法 + Utils.extend(Color, { + //各分量可表示的最大值 + _MAX_VALUE: { + r: 255, + g: 255, + b: 255, + h: 360, + s: 100, + l: 100, + a: 1 + }, + //各分量最小值 + _MIN_VALUE: { + r: 0, + g: 0, + b: 0, + h: 0, + s: 0, + l: 0, + a: 0 + }, + //分量常量 + R: "r", + G: "g", + B: "b", + H: "h", + S: "s", + L: "l", + A: "a", + /** + * @method parse() + * @static + * @for kity.Color + * + * @description 解析一个颜色字符串为 kity.Color 对象 + * + * @grammar kity.Color.parse(valStr) + * + * @param {string} valStr 一个代表颜色的字符串,可以是: + * 熟知颜色表:如 'red', 'yellow' + * HEX 表示:如 '#368', '#123456' + * RGB 表示:如 'RGB(200, 200, 0)', 'RGBA(200, 200, 200, .5)' + * HSL 表示:如 'HSL(100, 60%, 80%)', 'HSLA(100, 60%, 80%, .5)' + */ + parse: function(valStr) { + var rgbValue; + if (Utils.isString(valStr)) { + rgbValue = ColorUtils.parseToValue(valStr); + } + if (Utils.isObject(valStr) && "r" in valStr) { + rgbValue = valStr; + } + //解析失败, 返回一个默认color实例 + if (rgbValue === null) { + return new Color(); + } + return new Color(rgbValue.r, rgbValue.g, rgbValue.b, rgbValue.a); + }, + /** + * @method createHSL() + * @for kity.Color + * @static + * + * @description 创建一个 HSL 颜色 + * + * @grammar kity.Color.createHSL(h, s, l) => {kity.Color} + * + * @param {number} h 色环(Hue)分量值,取值范围 [0, 359] + * @param {number} s 饱和度(Saturation)分量值,取值范围 [0, 100] + * @param {number} l 亮度(Lighteness)分量值,取值范围 [0, 100] + */ + createHSL: function(h, s, l) { + return Color.createHSLA(h, s, l, 1); + }, + /** + * @method createHSLA() + * @for kity.Color + * @static + * + * @description 创建一个 HSLA 颜色 + * + * @grammar kity.Color.createHSLA(h, s, l, a) => {kity.Color} + * + * @param {number} h 色环(Hue)分量值,取值范围 [0, 359] + * @param {number} s 饱和度(Saturation)分量值,取值范围 [0, 100] + * @param {number} l 亮度(Lighteness)分量值,取值范围 [0, 100] + * @param {number} a 透明度(Alpha)分量值,取值范围 [0, 1] + */ + createHSLA: function(h, s, l, a) { + var colorValue = null; + s += "%"; + l += "%"; + colorValue = [ "hsla(" + h, s, l, a + ")" ]; + return Color.parse(colorValue.join(", ")); + }, + /** + * @method createRGB() + * @for kity.Color + * @static + * + * @description 创建一个 RGB 颜色 + * + * @grammar kity.Color.createRGB(r, g, b) => {kity.Color} + * + * @param {number} r 红色(Red)分量值,取值范围 [0, 255] + * @param {number} g 绿色(Green)分量值,取值范围 [0, 255] + * @param {number} b 蓝色(Blue)分量值,取值范围 [0, 255] + */ + createRGB: function(r, g, b) { + return Color.createRGBA(r, g, b, 1); + }, + /** + * @method createRGBA() + * @for kity.Color + * @static + * + * @description 创建一个 RGBA 颜色 + * + * @grammar kity.Color.createRGBA(r, g, b, a) => {kity.Color} + * + * @param {number} r 红色(Red)分量值,取值范围 [0, 255] + * @param {number} g 绿色(Green)分量值,取值范围 [0, 255] + * @param {number} b 蓝色(Blue)分量值,取值范围 [0, 255] + * @param {number} a 透明度(Alpha)分量值,取值范围 [0, 1] + */ + createRGBA: function(r, g, b, a) { + return new Color(r, g, b, a); + } + }); + //内部工具对象 + Utils.extend(ColorUtils, { + parseToValue: function(valStr) { + var rgbaValue = {}; + /* 优先检测在调色板中是否有对应的颜色 */ + valStr = StandardColor.EXTEND_STANDARD[valStr] || StandardColor.COLOR_STANDARD[valStr] || valStr; + /* 颜色转换 */ + //hex格式 + if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(valStr)) { + rgbaValue = ColorUtils.hexToValue(valStr); + } else if (/^(rgba?)/i.test(valStr)) { + rgbaValue = ColorUtils.rgbaToValue(valStr); + } else if (/^(hsla?)/i.test(valStr)) { + rgbaValue = ColorUtils.hslaToValue(valStr); + } else { + return null; + } + return ColorUtils.overflowFormat(rgbaValue); + }, + hexToValue: function(hexStr) { + var result = {}, keys = [ "r", "g", "b" ]; + if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(hexStr)) { + hexStr = RegExp.$1.split(""); + Utils.each(keys, function(key, index) { + if (hexStr.length === 3) { + result[key] = ColorUtils.toNumber(hexStr[index] + hexStr[index]); + } else { + result[key] = ColorUtils.toNumber(hexStr[index * 2] + hexStr[index * 2 + 1]); + } + }); + //转换出hsl值 + result = Utils.extend(result, ColorUtils.rgbValueToHslValue(result)); + result.a = 1; + return result; + } + return null; + }, + rgbaToValue: function(rgbaStr) { + var result = {}, hasAlpha = false, keys = [ "r", "g", "b" ]; + if (/^(rgba?)/i.test(rgbaStr)) { + hasAlpha = RegExp.$1.length === 4; + rgbaStr = rgbaStr.replace(/^rgba?/i, "").replace(/\s+/g, "").replace(/[^0-9,.]/g, "").split(","); + Utils.each(keys, function(key, index) { + result[key] = rgbaStr[index] | 0; + }); + //转换出hsl值 + result = Utils.extend(result, ColorUtils.rgbValueToHslValue(result)); + result.a = hasAlpha ? parseFloat(rgbaStr[3]) : 1; + return result; + } + return null; + }, + hslaToValue: function(hslaStr) { + var result = {}, hasAlpha = false; + if (/^(hsla?)/i.test(hslaStr)) { + hasAlpha = RegExp.$1.length === 4; + hslaStr = hslaStr.replace(/^hsla?/i, "").replace(/\s+/g, "").replace(/[^0-9,.]/g, "").split(","); + //记录hsl值 + result.h = hslaStr[0] | 0; + result.s = hslaStr[1] | 0; + result.l = hslaStr[2] | 0; + //转换出rgb值 + result = Utils.extend(result, ColorUtils.hslValueToRGBValue(result)); + //hsl值转换为rgb值 + result = ColorUtils.hslValueToRGBValue(result); + result.a = hasAlpha ? parseFloat(hslaStr[3]) : 1; + return result; + } + return null; + }, + //hsl值对象转换为rgb值对象 + hslValueToRGBValue: function(hslValue) { + function trans(v1, v2, vH) { + if (vH < 0) { + vH += 1; + } else if (vH > 1) { + vH -= 1; + } + if (6 * vH < 1) { + return v1 + (v2 - v1) * 6 * vH; + } else if (2 * vH < 1) { + return v2; + } else if (3 * vH < 2) { + return v1 + (v2 - v1) * ((2 / 3 - vH) * 6); + } + return v1; + } + var q = null, p = null, result = {}; + hslValue = Utils.extend({}, hslValue); + hslValue.h = hslValue.h / 360; + hslValue.s = hslValue.s / 100; + hslValue.l = hslValue.l / 100; + //分量计算 + if (hslValue.s === 0) { + result.r = result.g = result.b = hslValue.l; + } else { + if (hslValue.l < .5) { + q = hslValue.l * (1 + hslValue.s); + } else { + q = hslValue.l + hslValue.s - hslValue.l * hslValue.s; + } + p = 2 * hslValue.l - q; + result.r = trans(p, q, hslValue.h + 1 / 3); + result.g = trans(p, q, hslValue.h); + result.b = trans(p, q, hslValue.h - 1 / 3); + } + result.r = Math.min(Math.round(result.r * 255), 255); + result.g = Math.min(Math.round(result.g * 255), 255); + result.b = Math.min(Math.round(result.b * 255), 255); + return result; + }, + //rgb值对象转换为hsl值对象 + rgbValueToHslValue: function(rgbValue) { + var max = null, min = null, result = {}; + rgbValue = Utils.extend({}, rgbValue); + rgbValue.r = rgbValue.r / 255; + rgbValue.g = rgbValue.g / 255; + rgbValue.b = rgbValue.b / 255; + max = Math.max(rgbValue.r, rgbValue.g, rgbValue.b); + min = Math.min(rgbValue.r, rgbValue.g, rgbValue.b); + //h分量计算 + if (max === min) { + result.h = 0; + } else if (max === rgbValue.r) { + if (rgbValue.g >= rgbValue.b) { + result.h = 60 * (rgbValue.g - rgbValue.b) / (max - min); + } else { + result.h = 60 * (rgbValue.g - rgbValue.b) / (max - min) + 360; + } + } else if (max === rgbValue.g) { + result.h = 60 * (rgbValue.b - rgbValue.r) / (max - min) + 120; + } else if (max === rgbValue.b) { + result.h = 60 * (rgbValue.r - rgbValue.g) / (max - min) + 240; + } + //l分量计算 + result.l = (max + min) / 2; + //s分量计算 + if (result.l === 0 || max === min) { + result.s = 0; + } else if (result.l > 0 && result.l <= .5) { + result.s = (max - min) / (max + min); + } else { + result.s = (max - min) / (2 - max - min); + } + //格式化hsl结果 + result.h = Math.round(result.h); + result.s = Math.round(result.s * 100); + result.l = Math.round(result.l * 100); + return result; + }, + toString: function(colorValue, type) { + var vals = []; + colorValue = Utils.extend({}, colorValue); + if (type.indexOf("hsl") !== -1) { + colorValue.s += "%"; + colorValue.l += "%"; + } + if (type !== "hex") { + Utils.each(type.split(""), function(key) { + vals.push(colorValue[key]); + }); + return (type + "(" + vals.join(", ") + ")").toLowerCase(); + } else { + vals.push(ColorUtils.toHexValue(+colorValue.r)); + vals.push(ColorUtils.toHexValue(+colorValue.g)); + vals.push(ColorUtils.toHexValue(+colorValue.b)); + return ("#" + vals.join("")).toLowerCase(); + } + }, + //16进制的2个数字转化为10进制, 如果转化失败, 返回0 + toNumber: function(value) { + return Number("0x" + value) | 0; + }, + toHexValue: function(value) { + var result = value.toString(16); + return result.length === 1 ? "0" + result : result; + }, + //溢出控制 + overflowFormat: function(value) { + var tmpValue = Utils.extend({}, value), keys = "rgba"; + Utils.each(keys.split(""), function(key) { + if (!tmpValue.hasOwnProperty(key)) { + return; + } + //上溢出 + tmpValue[key] = Math.min(Color._MAX_VALUE[key], tmpValue[key]); + //下溢出 + tmpValue[key] = Math.max(Color._MIN_VALUE[key], tmpValue[key]); + }); + return tmpValue; + } + }); + return Color; + } +}; + +//src/graphic/container.js +_p[29] = { + value: function(require, exports, module) { + function itemRemove() { + this.container.removeItem(this); + return this; + } + return _p.r(11).createClass("Container", { + getItems: function() { + return this.items || (this.items = []); + }, + getItem: function(index) { + return this.getItems()[index]; + }, + getFirstItem: function() { + return this.getItem(0); + }, + getLastItem: function() { + return this.getItem(this.getItems().length - 1); + }, + indexOf: function(item) { + return this.getItems().indexOf(item); + }, + eachItem: function(fn) { + var items = this.getItems(), length = items.length, i; + for (i = 0; i < length; i++) { + fn.call(this, i, items[i]); + } + return this; + }, + addItem: function(item, pos, noEvent) { + var items = this.getItems(), length = items.length; + if (~items.indexOf(item)) { + return this; + } + if (!(pos >= 0 && pos < length)) { + pos = length; + } + items.splice(pos, 0, item); + if (typeof item === "object") { + item.container = this; + item.remove = itemRemove; + } + this.handleAdd(item, pos); + if (!noEvent) { + this.onContainerChanged("add", [ item ]); + } + return this; + }, + addItems: function(items) { + for (var i = 0, l = items.length; i < l; i++) { + this.addItem(items[i], -1, true); + } + this.onContainerChanged("add", items); + return this; + }, + setItems: function(items) { + return this.clear().addItems(items); + }, + appendItem: function(item) { + return this.addItem(item); + }, + prependItem: function(item) { + return this.addItem(item, 0); + }, + removeItem: function(pos, noEvent) { + if (typeof pos !== "number") { + return this.removeItem(this.indexOf(pos)); + } + var items = this.getItems(), length = items.length, item = items[pos]; + if (item === undefined) { + return this; + } + items.splice(pos, 1); + if (item.container) { + delete item.container; + } + if (item.remove) { + delete item.remove; + } + this.handleRemove(item, pos); + if (!noEvent) { + this.onContainerChanged("remove", [ item ]); + } + return this; + }, + clear: function() { + var removed = []; + var item; + while (item = this.getFirstItem()) { + removed.push(item); + this.removeItem(0, true); + } + this.onContainerChanged("remove", removed); + return this; + }, + onContainerChanged: function(type, items) {}, + handleAdd: function(item, index) {}, + handleRemove: function(item, index) {} + }); + } +}; + +//src/graphic/curve.js +/* + * 曲线 + * */ +_p[30] = { + value: function(require, exports, module) { + var Utils = _p.r(12), CurveUtil = { + /* + * 获取由两个以上的点组成的曲线的平移线 + * @param points 曲线上的点的集合, 集合中的点的数量必须大于2 + * @return 平移线数组 + */ + getCurvePanLines: function(points, smoothFactor) { + //计算原始点的中点坐标 + var centerPoints = CurveUtil.getCenterPoints(points), //注意:计算中点连线的中点坐标, 得出平移线 + panLines = CurveUtil.getPanLine(points.length, centerPoints); + //平移线移动到顶点 + return CurveUtil.getMovedPanLines(points, panLines, smoothFactor); + }, + /* + * 计算给定点集合的连线的中点 + * @param points + */ + getCenterPoints: function(points) { + var centerPoints = {}, key = null; + for (var i = 0, j = 0, len = points.length; i < len; i++) { + //j是下一个点的索引 + j = i === len - 1 ? 0 : i + 1; + key = i + "," + j; + //计算中点坐标 + centerPoints[key] = { + x: (points[i].x + points[j].y) / 2, + y: (points[i].x + points[j].y) / 2 + }; + } + return centerPoints; + }, + /* + * 对getCenterPoints()接口获取到的数据做处理, 计算出各个顶点对应的平移线数据 + * @param length 集合中点的个数 + * @param points 点集合, 该集合应该是getCenterPoints()接口返回的数据 + */ + getPanLine: function(length, points) { + var result = {}, //顶点索引 + pointIndex = null; + for (var i = 0, j; i < length; i++) { + var point1 = null, point2 = null; + //计算当前点 + j = (i + 1) % length; + //保存当前处理的顶点索引 + pointIndex = j; + point1 = points[i + "," + j]; + //计算下一个点 + i = j; + j = (i + 1) % length; + point2 = points[i + "," + j]; + result[pointIndex] = { + points: [ { + x: point1.x, + y: point1.y + }, { + x: point2.x, + y: point2.y + } ], + center: { + x: (point1.x + point2.x) / 2, + y: (point1.y + point2.y) / 2 + } + }; + //还原i值 + i = (pointIndex + length - 1) % length; + } + return result; + }, + /* + * 计算平移线移动到顶点后的位置 + * @param points 顶点集合 + * @param panLines 平移线集合 + */ + getMovedPanLines: function(points, panLines, smoothFactor) { + var result = {}; + Utils.each(points, function(point, index) { + //当前平移线 + var currentPanLine = panLines[index], //平移线中点 + center = currentPanLine.center, //移动距离 + distance = { + x: center.x - point.x, + y: center.y - point.y + }; + var currentResult = result[index] = { + points: [], + center: { + x: point.x, + y: point.y + } + }; + //计算控制点到顶点的距离, 并且应用平滑系数到距离上 + Utils.each(currentPanLine.points, function(controlPoint, index) { + var moved = { + x: controlPoint.x - distance.x, + y: controlPoint.y - distance.y + }; + var vertex = currentResult.center; + var dx = moved.x - vertex.x; + var dy = moved.y - vertex.y; + moved.x = vertex.x + smoothFactor * dx; + moved.y = vertex.y + smoothFactor * dy; + currentResult.points.push(moved); + }); + }); + return result; + } + }; + return _p.r(11).createClass("Curve", { + base: _p.r(46), + mixins: [ _p.r(51) ], + constructor: function(points, isColse) { + this.callBase(); + this.setPoints(points || []); + this.closeState = !!isColse; + this.changeable = true; + this.smoothFactor = 1; + this.update(); + }, + //当点集合发生变化时采取的动作 + onContainerChanged: function() { + if (this.changeable) { + this.update(); + } + }, + setSmoothFactor: function(factor) { + this.smoothFactor = factor < 0 ? 0 : factor; + this.update(); + return this; + }, + getSmoothFactor: function() { + return this.smoothFactor; + }, + update: function() { + var points = this.getPoints(), withControlPoints = null, drawer = this.getDrawer(), curPoint = null, curControlPoint = null, prevControlPoint = null; + drawer.clear(); + if (points.length === 0) { + return this; + } else { + drawer.moveTo(points[0]); + } + if (points.length === 1) { + return this; + } + if (points.length === 2) { + drawer.lineTo(points[1]); + return this; + } + //获取已转换过后的带控制点的所有点 + withControlPoints = CurveUtil.getCurvePanLines(points, this.getSmoothFactor()); + for (var i = 1, len = points.length; i < len; i++) { + //当前顶点 + curPoint = withControlPoints[i].center; + //当前控制点 + if (this.closeState || i != len - 1) { + curControlPoint = withControlPoints[i].points[0]; + } else { + //非闭合状态下最后一个点的处理 + curControlPoint = withControlPoints[i].center; + } + if (this.closeState || i != 1) { + prevControlPoint = withControlPoints[i - 1].points[1]; + } else { + //非闭合状态下第一个点的处理 + prevControlPoint = withControlPoints[i - 1].center; + } + drawer.bezierTo(prevControlPoint.x, prevControlPoint.y, curControlPoint.x, curControlPoint.y, curPoint.x, curPoint.y); + } + //处理闭合 + if (this.closeState) { + curPoint = withControlPoints[0].center; + curControlPoint = withControlPoints[0].points[0]; + prevControlPoint = withControlPoints[points.length - 1].points[1]; + drawer.bezierTo(prevControlPoint.x, prevControlPoint.y, curControlPoint.x, curControlPoint.y, curPoint.x, curPoint.y); + } + return this; + }, + close: function() { + this.closeState = true; + return this.update(); + }, + open: function() { + this.closeState = false; + return this.update(); + }, + isClose: function() { + return !!this.closeState; + } + }); + } +}; + +//src/graphic/data.js +_p[31] = { + value: function(require, exports, module) { + return _p.r(11).createClass("Data", { + constructor: function() { + this._data = {}; + }, + setData: function(name, value) { + this._data[name] = value; + return this; + }, + getData: function(name) { + return this._data[name]; + }, + removeData: function(name) { + delete this._data[name]; + return this; + } + }); + } +}; + +//src/graphic/ellipse.js +_p[32] = { + value: function(require, exports, module) { + var Utils = _p.r(12), Point = _p.r(50); + return _p.r(11).createClass("Ellipse", { + base: _p.r(46), + constructor: function(rx, ry, cx, cy) { + this.callBase(); + this.rx = rx || 0; + this.ry = ry || 0; + this.cx = cx || 0; + this.cy = cy || 0; + this.update(); + }, + update: function() { + var rx = this.rx, ry = this.ry, x1 = this.cx + rx, x2 = this.cx - rx, y = this.cy; + var drawer = this.getDrawer(); + drawer.clear(); + drawer.moveTo(x1, y); + drawer.arcTo(rx, ry, 0, 1, 1, x2, y); + drawer.arcTo(rx, ry, 0, 1, 1, x1, y); + return this; + }, + getRadius: function() { + return { + x: this.rx, + y: this.ry + }; + }, + getRadiusX: function() { + return this.rx; + }, + getRadiusY: function() { + return this.ry; + }, + getCenter: function() { + return new Point(this.cx, this.cy); + }, + getCenterX: function() { + return this.cx; + }, + getCenterY: function() { + return this.cy; + }, + setRadius: function(rx, ry) { + this.rx = rx; + this.ry = ry; + return this.update(); + }, + setRadiusX: function(rx) { + this.rx = rx; + return this.update(); + }, + setRadiusY: function(ry) { + this.ry = ry; + return this.update(); + }, + setCenter: function(cx, cy) { + if (arguments.length == 1) { + var p = Point.parse(arguments[0]); + cx = p.x; + cy = p.y; + } + this.cx = cx; + this.cy = cy; + return this.update(); + }, + setCenterX: function(cx) { + this.cx = cx; + return this.update(); + }, + setCenterY: function(cy) { + this.cy = cy; + return this.update(); + } + }); + } +}; + +//src/graphic/eventhandler.js +/* + * kity event 实现 + */ +_p[33] = { + value: function(require, exports, module) { + // polyfill + (function() { + function CustomEvent(event, params) { + params = params || { + bubbles: false, + cancelable: false, + detail: undefined + }; + var evt = document.createEvent("CustomEvent"); + evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); + return evt; + } + CustomEvent.prototype = window.Event.prototype; + window.CustomEvent = CustomEvent; + })(); + var Utils = _p.r(12), ShapeEvent = _p.r(62); + // 内部处理器缓存 + var INNER_HANDLER_CACHE = {}, // 用户处理器缓存 + USER_HANDLER_CACHE = {}, guid = 0; + // 添加事件统一入口 + function _addEvent(type, handler, isOnce) { + isOnce = !!isOnce; + if (Utils.isString(type)) { + type = type.match(/\S+/g); + } + Utils.each(type, function(currentType) { + listen.call(this, this.node, currentType, handler, isOnce); + }, this); + return this; + } + // 移除事件统一入口 + function _removeEvent(type, handler) { + var userHandlerList = null, eventId = this._EVNET_UID, isRemoveAll = handler === undefined; + userHandlerList = USER_HANDLER_CACHE[eventId][type]; + //移除指定的监听器 + if (!isRemoveAll) { + isRemoveAll = true; + Utils.each(userHandlerList, function removeKityEvent(fn, index) { + if (fn === handler) { + // 不能结束, 需要查找完整个list, 避免丢失移除多次绑定同一个处理器的情况 + delete userHandlerList[index]; + } else { + isRemoveAll = false; + } + }); + } + //删除所有监听器 + if (isRemoveAll) { + deleteDomEvent(this.node, type, INNER_HANDLER_CACHE[eventId][type]); + delete USER_HANDLER_CACHE[eventId][type]; + delete INNER_HANDLER_CACHE[eventId][type]; + } + return this; + } + // 执行绑定, 该方法context为shape或者mixin了eventhandler的对象 + function listen(node, type, handler, isOnce) { + var eid = this._EVNET_UID, targetObject = this; + // 初始化内部监听器 + if (!INNER_HANDLER_CACHE[eid]) { + INNER_HANDLER_CACHE[eid] = {}; + } + if (!INNER_HANDLER_CACHE[eid][type]) { + // 内部监听器 + INNER_HANDLER_CACHE[eid][type] = function kityEventHandler(e) { + e = new ShapeEvent(e || window.event); + Utils.each(USER_HANDLER_CACHE[eid][type], function executeKityEvent(fn) { + var result; + if (fn) { + result = fn.call(targetObject, e); + //once 绑定, 执行完后删除 + if (isOnce) { + targetObject.off(type, fn); + } + } + // 如果用户handler里return了false, 则该节点上的此后的同类型事件将不再执行 + return result; + }, targetObject); + }; + } + // 初始化用户监听器列表 + if (!USER_HANDLER_CACHE[eid]) { + USER_HANDLER_CACHE[eid] = {}; + } + if (!USER_HANDLER_CACHE[eid][type]) { + USER_HANDLER_CACHE[eid][type] = [ handler ]; + // 绑定对应类型的事件 + // dom对象利用dom event进行处理, 非dom对象, 由消息分发机制处理 + if (!!node && "on" + type in node) { + bindDomEvent(node, type, INNER_HANDLER_CACHE[eid][type]); + } + } else { + USER_HANDLER_CACHE[eid][type].push(handler); + } + } + // 绑定dom事件 + function bindDomEvent(node, type, handler) { + if (node.addEventListener) { + node.addEventListener(type, handler, false); + } else { + node.attachEvent("on" + type, handler); + } + } + // 删除dom事件 + function deleteDomEvent(node, type, handler) { + if (node.removeEventListener) { + node.removeEventListener(type, handler, false); + } else { + node.detachEvent(type, handler); + } + } + // 触发dom事件 + function triggerDomEvent(node, type, params) { + var event = new CustomEvent(type, { + bubbles: true, + cancelable: true + }); + event._kityParam = params; + node.dispatchEvent(event); + } + // 发送消息 + function sendMessage(messageObj, type, msg) { + var event = null, handler = null; + var handlers = INNER_HANDLER_CACHE[messageObj._EVNET_UID]; + if (!handlers) return; + handler = handlers[type]; + if (!handler) { + return; + } + event = Utils.extend({ + type: type, + target: messageObj + }, msg || {}); + handler.call(messageObj, event); + } + // 对外接口 + return _p.r(11).createClass("EventHandler", { + constructor: function() { + this._EVNET_UID = ++guid; + }, + addEventListener: function(type, handler) { + return _addEvent.call(this, type, handler, false); + }, + addOnceEventListener: function(type, handler) { + return _addEvent.call(this, type, handler, true); + }, + removeEventListener: function(type, handler) { + return _removeEvent.call(this, type, handler); + }, + on: function(type, handler) { + return this.addEventListener.apply(this, arguments); + }, + once: function(type, handler) { + return this.addOnceEventListener.apply(this, arguments); + }, + off: function() { + return this.removeEventListener.apply(this, arguments); + }, + fire: function(type, params) { + return this.trigger.apply(this, arguments); + }, + trigger: function(type, params) { + sendMessage(this, type, params); + return this; + } + }); + } +}; + +//src/graphic/geometry.js +_p[34] = { + value: function(require) { + var utils = _p.r(12); + var Point = _p.r(50); + var Vector = _p.r(73); + var Matrix = _p.r(43); + var g = {}; + var pathCommand = /([achlmrqstvz])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\s]*,?\s*)+)/gi, pathValues = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)\s*,?\s*/gi, paramCounts = { + a: 7, + c: 6, + h: 1, + l: 2, + m: 2, + q: 4, + s: 4, + t: 2, + v: 1, + z: 0 + }; + function pathClone(path) { + var result, i, j, segment, segmentCopy; + result = []; + for (i = 0; i < path.length; i++) { + segment = path[i]; + result.push(segmentCopy = []); + for (j = 0; j < segment.length; j++) { + segmentCopy.push(segment[j]); + } + } + if (path.isUniform) result.isUniform = true; + if (path.isAbsolute) result.isAbsolute = true; + if (path.isCurve) result.isCurve = true; + return result; + } + // 缓存函数 + // from raphael.js + function cacher(f, scope, postprocessor) { + function repush(array, item) { + for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) { + return array.push(array.splice(i, 1)[0]); + } + } + function newf() { + var arg = Array.prototype.slice.call(arguments, 0), args = arg.join("␀"), cache = newf.cache = newf.cache || {}, count = newf.count = newf.count || []; + if (cache.hasOwnProperty(args)) { + repush(count, args); + return postprocessor ? postprocessor(cache[args]) : cache[args]; + } + if (count.length >= 1e3) { + delete cache[count.shift()]; + } + count.push(args); + cache[args] = f.apply(scope, arg); + return postprocessor ? postprocessor(cache[args]) : cache[args]; + } + return newf; + } + /** + * + * kity.g.pathToString(pathSegment) + * + * 返回表示 PathSegment 的字符串 + * + * @param {Array} pathSegment + * 要表示的 Path Segment + * + * @return {String} 表示该 Path 的字符串 + * + * @example + * + * var pathSegment = [['M', 0, 0], ['L', 10, 10]] + * var pathString = kity.g.pathToString(pathSegment); + * // 返回 'M0,0L10,10' + */ + g.pathToString = function(pathSegment) { + pathSegment = pathSegment || this; + if (typeof pathSegment == "string") return pathSegment; + if (pathSegment instanceof Array) { + pathSegment = utils.flatten(pathSegment); + return pathSegment.join(",").replace(/,?([achlmqrstvxz]),?/gi, "$1"); + } + }; + /** + * kity.g.parsePathString(pathString) + * + * 解析 Path 字符串成 PathSegment + * + * @copyright rapheal.js + * + * @example + * + * var seg = kity.g.parsePathString('M10,12l21-23-21.5,11z'); + * // 返回: [['M', 10, 12], ['l', 21, -23], ['l', -21.5, 11], ['z']] + * + * @param {String} pathString Path 字符串 + * @return {Array} + */ + g.parsePathString = cacher(function(pathString) { + var data = []; + pathString.replace(pathCommand, function(a, b, c) { + var params = [], name = b.toLowerCase(); + c.replace(pathValues, function(a, b) { + if (b) params.push(+b); + }); + if (name == "m" && params.length > 2) { + data.push([ b ].concat(params.splice(0, 2))); + name = "l"; + b = b == "m" ? "l" : "L"; + } + if (name == "r") { + data.push([ b ].concat(params)); + } else { + while (params.length >= paramCounts[name]) { + data.push([ b ].concat(params.splice(0, paramCounts[name]))); + if (!paramCounts[name]) { + break; + } + } + } + }); + data.isUniform = true; + data.toString = g.pathToString; + return data; + }); + /** + * kity.g.pathToAbsolute(path) + * + * 把路径转换为绝对路径的形式 + * + * @param {Array|String} path + * 要转换的 path 路径或者数组 + * + * @return {Array} + * 转换后的 Path Segment + * + * @example + * + * var path = 'M10,10l50,50'; + * var absPath = kity.g.pathToAbsolute(path); + * // 返回 [['M', 10, 10], ['L', 60, 60]] + */ + g.pathToAbsolute = cacher(function(path) { + var pathArray = path.isUniform ? path : g.parsePathString(g.pathToString(path)); + var res = [], x = 0, y = 0, mx = 0, my = 0, start = 0; + var r, pa, i, j, k, ii, jj, kk; + if (pathArray[0][0] == "M") { + x = +pathArray[0][1]; + y = +pathArray[0][2]; + mx = x; + my = y; + start++; + res[0] = [ "M", x, y ]; + } + for (r, pa, i = start, ii = pathArray.length; i < ii; i++) { + res.push(r = []); + pa = pathArray[i]; + if (pa[0] != pa[0].toUpperCase()) { + r[0] = pa[0].toUpperCase(); + switch (r[0]) { + case "A": + r[1] = pa[1]; + r[2] = pa[2]; + r[3] = pa[3]; + r[4] = pa[4]; + r[5] = pa[5]; + r[6] = +(pa[6] + x); + r[7] = +(pa[7] + y); + break; + + case "V": + r[1] = +pa[1] + y; + break; + + case "H": + r[1] = +pa[1] + x; + break; + + case "M": + mx = +pa[1] + x; + my = +pa[2] + y; + break; + + default: + for (j = 1, jj = pa.length; j < jj; j++) { + r[j] = +pa[j] + (j % 2 ? x : y); + } + } + } else { + for (k = 0, kk = pa.length; k < kk; k++) { + r[k] = pa[k]; + } + } + switch (r[0]) { + case "Z": + x = mx; + y = my; + break; + + case "H": + x = r[1]; + break; + + case "V": + y = r[1]; + break; + + case "M": + mx = r[r.length - 2]; + my = r[r.length - 1]; + break; + + default: + x = r[r.length - 2]; + y = r[r.length - 1]; + } + } + res.isUniform = true; + res.isAbsolute = true; + res.toString = g.pathToString; + return res; + }); + // 把圆弧绘制的曲线转化为对应的三次贝塞尔形式 + function a2c(x1, y1, rx, ry, angle, laf, sf, x2, y2, recursive) { + // copy from raphael.js + // for more information of where this math came from visit: + // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes + var math = Math, PI = math.PI, abs = Math.abs, _120 = PI * 120 / 180, rad = PI / 180 * (+angle || 0), res = [], xy, rotate = function(x, y, rad) { + var X = x * math.cos(rad) - y * math.sin(rad), Y = x * math.sin(rad) + y * math.cos(rad); + return { + x: X, + y: Y + }; + }; + var cos, sin, h, x, y, rx2, ry2, k, cx, cy, f1, f2, df, f2old, x2old, y2old, c1, s1, c2, s2, t, hx, hy, m1, m2, m3, m4, newres, i, ii; + if (!recursive) { + xy = rotate(x1, y1, -rad); + x1 = xy.x; + y1 = xy.y; + xy = rotate(x2, y2, -rad); + x2 = xy.x; + y2 = xy.y; + cos = math.cos(PI / 180 * angle); + sin = math.sin(PI / 180 * angle); + x = (x1 - x2) / 2; + y = (y1 - y2) / 2; + h = x * x / (rx * rx) + y * y / (ry * ry); + if (h > 1) { + h = math.sqrt(h); + rx = h * rx; + ry = h * ry; + } + rx2 = rx * rx; + ry2 = ry * ry; + k = (laf == sf ? -1 : 1) * math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))); + cx = k * rx * y / ry + (x1 + x2) / 2; + cy = k * -ry * x / rx + (y1 + y2) / 2; + f1 = math.asin(((y1 - cy) / ry).toFixed(9)); + f2 = math.asin(((y2 - cy) / ry).toFixed(9)); + f1 = x1 < cx ? PI - f1 : f1; + f2 = x2 < cx ? PI - f2 : f2; + if (f1 < 0) f1 = PI * 2 + f1; + if (f2 < 0) f2 = PI * 2 + f2; + if (sf && f1 > f2) { + f1 = f1 - PI * 2; + } + if (!sf && f2 > f1) { + f2 = f2 - PI * 2; + } + } else { + f1 = recursive[0]; + f2 = recursive[1]; + cx = recursive[2]; + cy = recursive[3]; + } + df = f2 - f1; + if (abs(df) > _120) { + f2old = f2; + x2old = x2; + y2old = y2; + f2 = f1 + _120 * (sf && f2 > f1 ? 1 : -1); + x2 = cx + rx * math.cos(f2); + y2 = cy + ry * math.sin(f2); + res = a2c(x2, y2, rx, ry, angle, 0, sf, x2old, y2old, [ f2, f2old, cx, cy ]); + } + df = f2 - f1; + c1 = math.cos(f1); + s1 = math.sin(f1); + c2 = math.cos(f2); + s2 = math.sin(f2); + t = math.tan(df / 4); + hx = 4 / 3 * rx * t; + hy = 4 / 3 * ry * t; + m1 = [ x1, y1 ]; + m2 = [ x1 + hx * s1, y1 - hy * c1 ]; + m3 = [ x2 + hx * s2, y2 - hy * c2 ]; + m4 = [ x2, y2 ]; + m2[0] = 2 * m1[0] - m2[0]; + m2[1] = 2 * m1[1] - m2[1]; + if (recursive) { + return [ m2, m3, m4 ].concat(res); + } else { + res = [ m2, m3, m4 ].concat(res).join().split(","); + newres = []; + for (i = 0, ii = res.length; i < ii; i++) { + newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x; + } + return newres; + } + } + // 把二次贝塞尔曲线参数转化为三次贝塞尔曲线参数 + function q2c(x1, y1, ax, ay, x2, y2) { + // copy from raphael.js + var _13 = 1 / 3, _23 = 2 / 3; + return [ _13 * x1 + _23 * ax, _13 * y1 + _23 * ay, _13 * x2 + _23 * ax, _13 * y2 + _23 * ay, x2, y2 ]; + } + /** + * kity.g.pathToCurve(path) + * + * 把路径转换为贝塞尔路径 + * + * @param {Array|String} path + * 要转换的 path 路径或数组 + * + * @return {Array} + * 转换后的 PathSegment,每一段都是 'C' + */ + g.pathToCurve = cacher(function(path) { + var i, j, command, param; + var initPoint, currentPoint, endPoint, shouldClose, lastControlPoint, aussumedControlPoint; + var controlPoint1, controlPoint2; + var res = []; + // 处理的路径要求是一个绝对路径 + if (!path.isAbsolute) path = g.pathToAbsolute(path); + for (i = 0; i < path.length; i++) { + command = path[i][0]; + param = path[i].slice(1); + // 画笔移动 + if (command == "M") { + initPoint = lastControlPoint = currentPoint = param; + res.push(path[i]); + continue; + } + // 路径闭合 + if (command == "Z") { + shouldClose = true; + command = "L"; + param = initPoint; + } + // 绘制命令的目的位置 + endPoint = param.slice(param.length - 2); + // 对 'H' 命令的修正 + if (command == "H") { + endPoint = [ param[0], currentPoint[1] ]; + command = "L"; + } + // 对 'V' 命令的修正 + if (command == "V") { + endPoint = [ currentPoint[0], param[0] ]; + command = "L"; + } + // 对 'S' 命令求出隐含的控制点位置 + if (command == "S" || command == "T") { + // 隐含控制点是上一个控制点关于当前位置的镜像 + aussumedControlPoint = [ currentPoint[0] + (currentPoint[0] - lastControlPoint[0]), currentPoint[1] + (currentPoint[1] - lastControlPoint[1]) ]; + } + // 针对不同的命令求控制点 + switch (command) { + case "L": + controlPoint1 = currentPoint; + controlPoint2 = endPoint; + break; + + case "C": + controlPoint1 = param.slice(0, 2); + controlPoint2 = param.slice(2, 4); + break; + + case "S": + controlPoint1 = aussumedControlPoint.slice(); + controlPoint2 = param.slice(0, 2); + break; + + case "Q": + lastControlPoint = param.slice(0, 2); + param = q2c.apply(null, currentPoint.concat(param)); + controlPoint1 = param.slice(0, 2); + controlPoint2 = param.slice(2, 4); + break; + + case "T": + param = q2c.apply(null, currentPoint.concat(aussumedControlPoint).concat(param)); + controlPoint1 = param.slice(0, 2); + controlPoint2 = param.slice(2, 4); + break; + + case "A": + param = a2c.apply(null, currentPoint.concat(param)); + j = 0; + while (j in param) { + controlPoint1 = param.slice(j, j + 2); + controlPoint2 = param.slice(j + 2, j + 4); + endPoint = param.slice(j + 4, j + 6); + // 写入当前一段曲线 + res.push([ "C" ].concat(controlPoint1).concat(controlPoint2).concat(endPoint)); + j += 6; + } + break; + } + if (command != "A") { + // 写入当前一段曲线 + res.push([ "C" ].concat(controlPoint1).concat(controlPoint2).concat(endPoint)); + } + // 为下次循环准备当前位置 + currentPoint = endPoint; + // 二次贝塞尔曲线自己已经记录了上个控制点的位置,其它的记录控制点 2 的位置 + if (command != "Q") { + lastControlPoint = controlPoint2; + } + if (shouldClose) { + res.push([ "Z" ]); + shouldClose = false; + } + } + res.isUniform = true; + res.isAbsolute = true; + res.isCurve = true; + res.toString = g.pathToString; + return res; + }); + /** + * 将贝塞尔曲线切成两部分 + * + * @see http://stackoverflow.com/questions/18655135/divide-bezier-curve-into-two-equal-halves + */ + function cutBezier(bezierArray, t) { + function __(t) { + return function(p, q) { + return p + t * (q - p); + }; + } + var _ = __(t || .5), ba = bezierArray, ax = ba[0], ay = ba[1], bx = ba[2], by = ba[3], cx = ba[4], cy = ba[5], dx = ba[6], dy = ba[7], ex = _(ax, bx), ey = _(ay, by), fx = _(bx, cx), fy = _(by, cy), gx = _(cx, dx), gy = _(cy, dy), hx = _(ex, fx), hy = _(ey, fy), jx = _(fx, gx), jy = _(fy, gy), kx = _(hx, jx), ky = _(hy, jy); + return [ [ ax, ay, ex, ey, hx, hy, kx, ky ], [ kx, ky, jx, jy, gx, gy, dx, dy ] ]; + } + /** + * kity.g.cutBezier(bezierArray, t) + * + * 在指定位置把贝塞尔曲线切割为两部分 + * + * @param {Array} bezierArray + * 表示贝塞尔曲线的一个数组 [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y] + * p1 和 p2 是贝塞尔曲线的起点和终点,c1 和 c2 是两个控制点 + * + * @param {Number} t + * 切割的位置(0 到 1) + * + * @return {Array} + * 切割的两个贝塞尔曲线:[ + * [p1x1, p1y1, c1x1, c1y1, c2x1, c2y1, p2x1, p2y1], + * [p1x2, p1y2, c1x2, c1y2, c2x2, c2y2, p2x2, p2y2] + * ] + * + */ + g.cutBezier = cacher(cutBezier); + /** + * 求一段贝塞尔曲线的子段 + * + * @param {Array} bezierArray + * 长度为 8 的数组,表示 [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y] + * + * @param {Number} t + * 子段的结束位置(0 到 1) + * + * @param {Number} t0 + * 字段的开始位置(0 到 t),可不传,默认为 0 + * + * @return {Array} + * 长度为 8 的数组,表示给定贝塞尔曲线的子段 + */ + g.subBezier = function(bezierArray, t, t0) { + var b2t = cutBezier(bezierArray, t)[0]; + return t0 ? cutBezier(b2t, t0 / t)[1] : b2t; + }; + /** + * 求贝塞尔曲线上的一个点 + * + * @param {Array} bezierArray + * 长度为 8 的数组,表示 [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y] + * + * @param {Number} t + * 所求点的开始位置(0 到 1) + * + * @return {Point} p + * p.x: x 坐标 + * p.y: y 坐标 + * p.tan: 在 t 处的切线方向(类型为 kity.Vector,模为 1) + */ + g.pointAtBezier = function(bezierArray, t) { + var b2t = cutBezier(bezierArray, t)[0]; + var p = Point.parse(b2t.slice(6)), c = Point.parse(b2t.slice(4, 2)), v = Vector.fromPoints(c, p); + if (t === 0) { + p.tan = g.pointAtBezier(bezierArray, .01).tan; + } else { + p.tan = v.normalize(); + } + return p; + }; + /** + * 求贝塞尔曲线的长度 + * + * @param {Array} bezierArray + * 长度为 8 的数组,表示 [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y] + * + * @param {Number} tolerate + * 允许的误差,默认是 0.1 + * + * @return {Number} 贝塞尔曲线的长度 + */ + g.bezierLength = cacher(function bezierLength(bezierArray) { + // 表示(c[0]*t^4 + c[1]*t^3 + c[2]*t^2 + c[3]*t^1 + c[4])^(1/2)的函数 + function f(x) { + var m = c0 * Math.pow(x, 4) + c1 * Math.pow(x, 3) + c2 * Math.pow(x, 2) + c3 * x + c4; + if (m < 0) { + m = 0; + } + return Math.pow(m, .5); + } + // 用Newton-Cotes型求积公式 + var arr = bezierArray; + // 三次贝塞尔曲线函数求导后,求出对应的方程系数,用cx[],cy[]表示x`(t)和y`(t)的系数 + var cx0, cx1, cx2; + var cy0, cy1, cy2; + // 用c[]表示x`(t)^2 + y`(t)^2的结果的系数 + var c0, c1, c2, c3, c4; + // 求x`(t) 和 y`(t)的系数 + cx0 = -3 * arr[0] + 9 * arr[2] - 9 * arr[4] + 3 * arr[6]; + cx1 = 6 * arr[0] - 12 * arr[2] + 6 * arr[4]; + cx2 = -3 * arr[0] + 3 * arr[2]; + cy0 = -3 * arr[1] + 9 * arr[3] - 9 * arr[5] + 3 * arr[7]; + cy1 = 6 * arr[1] - 12 * arr[3] + 6 * arr[5]; + cy2 = -3 * arr[1] + 3 * arr[3]; + // 求x`(t)^2 + y`(t)^2的结果的系数 c[] + c0 = Math.pow(cx0, 2) + Math.pow(cy0, 2); + c1 = 2 * (cx0 * cx1 + cy0 * cy1); + c2 = 2 * (cx0 * cx2 + cy0 * cy2) + Math.pow(cx1, 2) + Math.pow(cy1, 2); + c3 = 2 * (cx1 * cx2 + cy1 * cy2); + c4 = Math.pow(cx2, 2) + Math.pow(cy2, 2); + // 用cotes积分公式求值 + return (f(0) + f(1) + 4 * (f(.125) + f(.375) + f(.625) + f(.875)) + 2 * (f(.25) + f(.5) + f(.75))) / 24; + }); + // 计算一个 pathSegment 中每一段的在整体中所占的长度范围,以及总长度 + // 方法要求每一段都是贝塞尔曲线 + var getBezierPathSegmentRanges = cacher(function(pathSegment) { + var i, ii, segment, position, bezierLength, segmentRanges, totalLength; + segmentRanges = []; + // 总长度 + totalLength = 0; + for (i = 0, ii = pathSegment.length; i < ii; i++) { + segment = pathSegment[i]; + if (segment[0] == "M") { + position = segment.slice(1); + segmentRanges.push(null); + continue; + } + if (segment[0] == "Z") { + segmentRanges.push(null); + continue; + } + bezierLength = g.bezierLength(position.concat(segment.slice(1))); + segmentRanges.push([ totalLength, totalLength + bezierLength ]); + totalLength += bezierLength; + // 迭代当前位置 + position = segment.slice(4); + } + segmentRanges.totalLength = totalLength; + return segmentRanges; + }); + /** + * 求一段路径的子路径 + * + * @param {Array|String} path + * 原路径 + * + * @param {Number} t1 + * 要求的子路径的结束位置(0 到 1) + * + * @param {Number} t0 + * 要求的子路径的开始位置(0 到 t1),可不传,默认为 0 + * + * @return {Array} + * 子路径的 PathSegment + */ + g.subPath = function(path, t1, t0) { + var dt; + t0 = t0 || 0; + dt = t1 - t0; + dt = dt - (dt | 0); + t0 = t0 - (t0 | 0); + t1 = t0 + dt; + if (t1 > 1) { + return g.subPath(path, 1, t0).concat(g.subPath(path, t1 - 1)); + } + if (!path.isCurve) { + path = g.pathToCurve(path); + } + // path 每一段在整体中的长度区间 + var segmentRanges = getBezierPathSegmentRanges(path); + // path 总长度 + var totalLength = segmentRanges.totalLength; + // t1 和 t0 位置命中的长度位置 + var t1Length = totalLength * t1, t0Length = totalLength * (t0 || 0); + // 产生的子路径 + var subPath = []; + // 迭代变量,a 是一段的长度区间左值,b 是右值,d 是区间长度 + var i, ii, a, b, d; + var position; + var bezier, subBezier, stared; + for (i = 0, ii = path.length; i < ii; i++) { + if (path[i][0] == "M") { + position = path[i].slice(1); + if (stared) { + subPath.push(path[i].slice()); + } + continue; + } + if (path[i][0] == "Z") { + // subpath 路径不闭合 + continue; + } + a = segmentRanges[i][0]; + b = segmentRanges[i][1]; + d = b - a; + bezier = position.concat(path[i].slice(1)); + if (t0Length > b) { + // t0 和 t1 都右溢出 + // ----------------------------------- + // t0 t1 + // |________| + // + // 需要跳过当前块 + position = bezier.slice(bezier.length - 2); + continue; + } else if (t0Length >= a) { + // 命中 t0;t1 可能命中或右溢出 + // ----------------------------------- + // t0 t1 + // |______|__| + // + // or: |_|____|__| + // + // 取当前块 t0 到 t1 的部分 + subBezier = g.subBezier(bezier, Math.min((t1Length - a) / d, 1), (t0Length - a) / d); + stared = true; + position = subBezier.slice(0, 2); + subPath.push([ "M" ].concat(subBezier.slice(0, 2))); + subPath.push([ "C" ].concat(subBezier.slice(2))); + } else if (t1Length >= b) { + // t0 左溢出;t1 右溢出,整个块是需要的 + // ----------------------------------- + // t0 t1 + // |_________| + // + // 此时取整个块 + subPath.push(path[i].slice()); + } else if (t1Length >= a) { + // t0 左溢出;t1 命中,取当前块 t1 之前的部分 + // ----------------------------------- + // t0 t1 + // |__|______| + // 取当前块 t1 之前的部分 + subBezier = g.subBezier(bezier, (t1Length - a) / d); + subPath.push([ "C" ].concat(subBezier.slice(2))); + stared = false; + } else { + // 没有可以再要的了 + break; + } + position = bezier.slice(bezier.length - 2); + } + subPath.isAbsolute = true; + subPath.isCurve = true; + subPath.isUniform = true; + subPath.toString = g.pathToString; + return subPath; + }; + /** + * 求路径上的一个点 + * + * @param {Array|String} path + * 要求点的路径 + * + * @param {Number} t + * 要求的点的位置(0 到 1) + * + * @return {Point} p + * p.x: x 坐标 + * p.y: y 坐标 + * p.tan: 在 t 处的切线方向(类型为 kity.Vector,模为 1) + */ + g.pointAtPath = function(path, t) { + if (!path.isCurve) { + path = g.pathToCurve(path); + } + var subPath = g.subPath(path, t); + var lastCurve = subPath[subPath.length - 1][0] == "Z" ? subPath[subPath.length - 2] : subPath[subPath.length - 1]; + // 跳过 'C' 命令,只留参数 + lastCurve = lastCurve.slice(1); + var p = Point.parse(lastCurve.slice(4)), c = Point.parse(lastCurve.slice(2, 4)); + p.tan = Vector.fromPoints(c, p).normalize(); + return p; + }; + /** + * 求一段路径的长度 + * + * @param {string|Array} path + * 要求的路径 + * + * @return {Number} + * 路径的长度 + */ + g.pathLength = cacher(function(path) { + if (!path.isCurve) { + path = g.pathToCurve(path); + } + // path 每一段在整体中的长度区间 + var segmentRanges = getBezierPathSegmentRanges(path); + return segmentRanges.totalLength; + }); + /** + * 求一段路径的关键点 + * + * @param {string|Array} path + * 要求的路径 + * + * @return {Array} + * 关键点的集合 + */ + g.pathKeyPoints = cacher(function(path) { + var i, ii, command, keyPoints; + if (!path.isCurve) { + path = g.pathToCurve(path); + } + keyPoints = []; + for (i = 0, ii = path.length; i < ii; i++) { + if (path[i][0] == "z") continue; + keyPoints.push(path[i].slice(path[i].length - 2)); + } + return keyPoints; + }); + // 对比两个路径的关键位置,在合适的位置切割合适的路径,使得两个路径的段数一致 + // TODO: 使用插值算法,使对应点更合理 + var alignCurve = cacher(function(path1, path2) { + if (!path1.isCurve) path1 = g.pathToCurve(path1); + if (!path2.isCurve) path2 = g.pathToCurve(path2); + var p1 = pathClone(path1); + var p2 = pathClone(path2); + p1.i = 0; + p2.i = 0; + p1.o = p2; + p2.o = p1; + function command(p, i) { + return p[i || p.i] && p[i || p.i][0]; + } + function param(p, i) { + return p[i || p.i] && p[i || p.i].slice(1); + } + function point(p, i) { + var _param = param(p, i); + return _param && _param.slice(-2); + } + function fixZ(p) { + if (command(p) == "Z") { + p.splice(p.i, 1); + return true; + } + return false; + } + function fixM(p) { + if (command(p) == "M") { + p.o.splice(p.o.i, 0, [ "M" ].concat(point(p.o, p.o.i - 1))); + p.i++; + p.o.i++; + return true; + } + return false; + } + function fill(p) { + var lastPoint; + var i = 1; + while (!lastPoint) { + lastPoint = point(p, p.length - i++); + } + p.o.i = p.i; + while (p.length < p.o.length) { + if (fixZ(p.o)) continue; + if (fixM(p.o)) continue; + p.push([ "C" ].concat(lastPoint).concat(lastPoint).concat(lastPoint)); + p.i++; + p.o.i++; + } + } + while (p1.i < p1.length && p2.i < p2.length) { + if (fixZ(p1) || fixZ(p2)) continue; + if (command(p1) == command(p2)) { + p1.i++; + p2.i++; + continue; + } + if (fixM(p1) || fixM(p2)) continue; + p1.i++; + p2.i++; + } + if (p1.i == p1.length) fill(p1); + if (p2.i == p2.length) fill(p2); + delete p1.i; + delete p1.o; + delete p2.i; + delete p2.o; + return [ p1, p2 ]; + }); + g.alignCurve = alignCurve; + /** + * 获得两个路径的补间结果 + * + * @param {string|Array} path1 + * 补间起始路径 + * + * @param {string|Array} path2 + * 补间结束路径 + * + * @param {Number} t + * 补间比例,0 返回跟 path1 等效的结果;1 返回跟 path2 等效的结果 + * + * @return {PathSegment} + * 补间的结果 + */ + g.pathTween = function(path1, path2, t) { + if (t === 0) return path1; + if (t === 1) return path2; + var aligned = alignCurve(path1, path2); + var result = [], seg, i, j; + path1 = aligned[0]; + path2 = aligned[1]; + for (i = 0; i < path1.length; i++) { + result.push(seg = []); + seg.push(path1[i][0]); + for (j = 1; j < path1[i].length; j++) { + seg.push(path1[i][j] + t * (path2[i][j] - path1[i][j])); + } + } + result.isUniform = result.isCurve = result.isAbsolute = true; + return result; + }; + /** + * 变换指定的路径 + * + * @param {String|Array} path + * 需要变换的路径 + * + * @param {kity.Matrix} matrix + * 使用的变换矩阵 + * + * @return {Array} + * 变换后的路径 + */ + g.transformPath = cacher(function(path, matrix) { + var i, ii, j, result, seg, pair; + if (!path.isCurve) { + path = g.pathToCurve(path); + } + result = []; + for (i = 0, ii = path.length; i < ii; i++) { + result.push(seg = [ path[i][0] ]); + for (j = 1; j < path[i].length; j += 2) { + pair = path[i].slice(j, j + 2); + pair = matrix.transformPoint(Point.parse(pair)); + result.push(pair); + } + } + return result; + }); + // entend + _p.r(11).extendClass(Matrix, { + transformPath: function(path) { + return g.transformPath(path, this); + } + }); + return g; + } +}; + +//src/graphic/gradient.js +_p[35] = { + value: function(require, exports, module) { + var svg = _p.r(67); + var Resource = _p.r(58); + var Color = _p.r(28); + return _p.r(11).createClass("GradientBrush", { + base: Resource, + constructor: function(gradientNodeType, paper) { + this.callBase(gradientNodeType, paper); + this.stops = []; + }, + addStop: function(offset, color, opacity) { + var gstop = svg.createNode("stop"); + if (!(color instanceof Color)) { + color = Color.parse(color); + } + if (opacity === undefined) { + opacity = color.get("a"); + } + gstop.setAttribute("offset", offset); + gstop.setAttribute("stop-color", color.toRGB()); + if (opacity < 1) { + gstop.setAttribute("stop-opacity", opacity); + } + this.node.appendChild(gstop); + return this; + } + }); + } +}; + +//src/graphic/group.js +_p[36] = { + value: function(require, exports, module) { + var ShapeContainer = _p.r(61); + return _p.r(11).createClass("Group", { + mixins: [ ShapeContainer ], + base: _p.r(60), + constructor: function Group() { + this.callBase("g"); + } + }); + } +}; + +//src/graphic/hyperlink.js +_p[37] = { + value: function(require, exports, module) { + var ShapeContainer = _p.r(61); + return _p.r(11).createClass("HyperLink", { + mixins: [ ShapeContainer ], + base: _p.r(60), + constructor: function(url) { + this.callBase("a"); + this.setHref(url); + }, + setHref: function(href) { + this.node.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", href); + return this; + }, + getHref: function() { + return this.node.getAttributeNS("xlink:href"); + }, + setTarget: function(target) { + this.node.setAttribute("target", target); + return this; + }, + getTarget: function() { + return this.node.getAttribute("target"); + } + }); + } +}; + +//src/graphic/image.js +_p[38] = { + value: function(require, exports, module) { + return _p.r(11).createClass("Image", { + base: _p.r(60), + constructor: function(url, width, height, x, y) { + this.callBase("image"); + this.url = url; + this.width = width || 0; + this.height = height || 0; + this.x = x || 0; + this.y = y || 0; + this.update(); + }, + update: function() { + this.node.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", this.url); + this.node.setAttribute("x", this.x); + this.node.setAttribute("y", this.y); + this.node.setAttribute("width", this.width); + this.node.setAttribute("height", this.height); + return this; + }, + setUrl: function(url) { + this.url = url === "" ? null : url; + return this.update(); + }, + getUrl: function() { + return this.url; + }, + setWidth: function(width) { + this.width = width; + return this.update(); + }, + getWidth: function() { + return this.width; + }, + setHeight: function(height) { + this.height = height; + return this.update(); + }, + getHeight: function() { + return this.height; + }, + setX: function(x) { + this.x = x; + return this.update(); + }, + getX: function() { + return this.x; + }, + setY: function(y) { + this.y = y; + return this.update(); + }, + getY: function() { + return this.y; + } + }); + } +}; + +//src/graphic/line.js +_p[39] = { + value: function(require, exports, module) { + return _p.r(11).createClass("Line", { + base: _p.r(46), + constructor: function(x1, y1, x2, y2) { + this.callBase(); + this.point1 = { + x: x1 || 0, + y: y1 || 0 + }; + this.point2 = { + x: x2 || 0, + y: y2 || 0 + }; + this.update(); + }, + setPoint1: function(x, y) { + this.point1.x = x; + this.point1.y = y; + return this.update(); + }, + setPoint2: function(x, y) { + this.point2.x = x; + this.point2.y = y; + return this.update(); + }, + getPoint1: function() { + return { + x: this.point1.x, + y: this.point1.y + }; + }, + getPoint2: function() { + return { + x: this.point2.x, + y: this.point2.y + }; + }, + update: function() { + var drawer = this.getDrawer(); + drawer.clear(); + drawer.moveTo(this.point1.x, this.point1.y); + drawer.lineTo(this.point2.x, this.point2.y); + return this; + } + }); + } +}; + +//src/graphic/lineargradient.js +_p[40] = { + value: function(require, exports, module) { + var svg = _p.r(67); + var Gradient = _p.r(35); + return _p.r(11).createClass("LinearGradientBrush", { + base: Gradient, + constructor: function(paper) { + this.callBase("linearGradient", paper); + this.setStartPosition(0, 0); + this.setEndPosition(1, 0); + }, + setStartPosition: function(px, py) { + this.node.setAttribute("x1", px); + this.node.setAttribute("y1", py); + return this; + }, + setEndPosition: function(px, py) { + this.node.setAttribute("x2", px); + this.node.setAttribute("y2", py); + return this; + }, + getStartPosition: function() { + return { + x: +this.node.getAttribute("x1"), + y: +this.node.getAttribute("y1") + }; + }, + getEndPosition: function() { + return { + x: +this.node.getAttribute("x2"), + y: +this.node.getAttribute("y2") + }; + } + }); + } +}; + +//src/graphic/marker.js +_p[41] = { + value: function(require, exports, module) { + var Point = _p.r(50); + var Marker = _p.r(11).createClass("Marker", { + base: _p.r(58), + mixins: [ _p.r(61), _p.r(75) ], + constructor: function() { + this.callBase("marker"); + this.setOrient("auto"); + }, + setRef: function(x, y) { + if (arguments.length === 1) { + y = x.y; + x = x.x; + } + this.node.setAttribute("refX", x); + this.node.setAttribute("refY", y); + return this; + }, + getRef: function() { + return new Point(+this.node.getAttribute("refX"), +this.node.getAttribute("refY")); + }, + setWidth: function(width) { + this.node.setAttribute("markerWidth", this.width = width); + return this; + }, + setOrient: function(orient) { + this.node.setAttribute("orient", this.orient = orient); + return this; + }, + getOrient: function() { + return this.orient; + }, + getWidth: function() { + return +this.width; + }, + setHeight: function(height) { + this.node.setAttribute("markerHeight", this.height = height); + return this; + }, + getHeight: function() { + return +this.height; + } + }); + var Path = _p.r(46); + _p.r(11).extendClass(Path, { + setMarker: function(marker, pos) { + pos = pos || "end"; + if (!marker) { + this.node.removeAttribute("marker-" + pos); + } else { + this.node.setAttribute("marker-" + pos, marker.toString()); + } + return this; + } + }); + return Marker; + } +}; + +//src/graphic/mask.js +/** + * 蒙板 + */ +_p[42] = { + value: function(require, exports, module) { + var Class = _p.r(11); + var Shape = _p.r(60); + var Mask = Class.createClass("Mask", { + base: Shape, + mixins: [ _p.r(61) ], + constructor: function() { + this.callBase("mask"); + }, + mask: function(shape) { + shape.getNode().setAttribute("mask", "url(#" + this.getId() + ")"); + return this; + } + }); + Class.extendClass(Shape, { + maskWith: function(mask) { + mask.mask(this); + return this; + } + }); + return Mask; + } +}; + +//src/graphic/matrix.js +_p[43] = { + value: function(require, exports, module) { + var utils = _p.r(12); + var Box = _p.r(25); + var mPattern = /matrix\s*\((.+)\)/i; + var Point = _p.r(50); + // 注意,合并的结果是先执行m2,再执行m1的结果 + function mergeMatrixData(m2, m1) { + return { + a: m1.a * m2.a + m1.c * m2.b, + b: m1.b * m2.a + m1.d * m2.b, + c: m1.a * m2.c + m1.c * m2.d, + d: m1.b * m2.c + m1.d * m2.d, + e: m1.a * m2.e + m1.c * m2.f + m1.e, + f: m1.b * m2.e + m1.d * m2.f + m1.f + }; + } + function d2r(deg) { + return deg * Math.PI / 180; + } + var Matrix = _p.r(11).createClass("Matrix", { + constructor: function() { + if (arguments.length) { + this.setMatrix.apply(this, arguments); + } else { + this.setMatrix(1, 0, 0, 1, 0, 0); + } + }, + translate: function(x, y) { + this.m = mergeMatrixData(this.m, { + a: 1, + c: 0, + e: x, + b: 0, + d: 1, + f: y + }); + return this; + }, + rotate: function(deg) { + var rad = d2r(deg); + var sin = Math.sin(rad), cos = Math.cos(rad); + this.m = mergeMatrixData(this.m, { + a: cos, + c: -sin, + e: 0, + b: sin, + d: cos, + f: 0 + }); + return this; + }, + scale: function(sx, sy) { + if (sy === undefined) { + sy = sx; + } + this.m = mergeMatrixData(this.m, { + a: sx, + c: 0, + e: 0, + b: 0, + d: sy, + f: 0 + }); + return this; + }, + skew: function(degX, degY) { + if (degY === undefined) { + degY = degX; + } + var tx = Math.tan(d2r(degX)), ty = Math.tan(d2r(degY)); + this.m = mergeMatrixData(this.m, { + a: 1, + c: tx, + e: 0, + b: ty, + d: 1, + f: 0 + }); + return this; + }, + /** + * 获得反转矩阵 + * + * 这是我解方程算出来的 + */ + inverse: function() { + var m = this.m, a = m.a, b = m.b, c = m.c, d = m.d, e = m.e, f = m.f, k, aa, bb, cc, dd, ee, ff; + k = a * d - b * c; + aa = d / k; + bb = -b / k; + cc = -c / k; + dd = a / k; + ee = (c * f - e * d) / k; + ff = (b * e - a * f) / k; + return new Matrix(aa, bb, cc, dd, ee, ff); + }, + setMatrix: function(a, b, c, d, e, f) { + if (arguments.length === 1) { + this.m = utils.clone(arguments[0]); + } else { + this.m = { + a: a, + b: b, + c: c, + d: d, + e: e, + f: f + }; + } + return this; + }, + getMatrix: function() { + return utils.clone(this.m); + }, + getTranslate: function() { + var m = this.m; + return { + x: m.e / m.a, + y: m.f / m.d + }; + }, + mergeMatrix: function(matrix) { + return new Matrix(mergeMatrixData(this.m, matrix.m)); + }, + merge: function(matrix) { + return this.mergeMatrix(matrix); + }, + toString: function() { + return this.valueOf().join(" "); + }, + valueOf: function() { + var m = this.m; + return [ m.a, m.b, m.c, m.d, m.e, m.f ]; + }, + equals: function(matrix) { + var m1 = this.m, m2 = matrix.m; + return m1.a == m2.a && m1.b == m2.b && m1.c == m2.c && m1.d == m2.d && m1.e == m2.e && m1.f == m2.f; + }, + transformPoint: function() { + return Matrix.transformPoint.apply(null, [].slice.call(arguments).concat([ this.m ])); + }, + transformBox: function(box) { + return Matrix.transformBox(box, this.m); + }, + clone: function() { + return new Matrix(this.m); + } + }); + Matrix.parse = function(str) { + var match; + var f = parseFloat; + if (str instanceof Array) { + return new Matrix({ + a: str[0], + b: str[1], + c: str[2], + d: str[3], + e: str[4], + f: str[5] + }); + } + if (match = mPattern.exec(str)) { + var values = match[1].split(","); + if (values.length != 6) { + values = match[1].split(" "); + } + return new Matrix({ + a: f(values[0]), + b: f(values[1]), + c: f(values[2]), + d: f(values[3]), + e: f(values[4]), + f: f(values[5]) + }); + } + return new Matrix(); + }; + Matrix.transformPoint = function(x, y, m) { + if (arguments.length === 2) { + m = y; + y = x.y; + x = x.x; + } + return new Point(m.a * x + m.c * y + m.e, m.b * x + m.d * y + m.f); + }; + Matrix.transformBox = function(box, matrix) { + var xMin = Number.MAX_VALUE, xMax = -Number.MAX_VALUE, yMin = Number.MAX_VALUE, yMax = -Number.MAX_VALUE; + var bps = [ [ box.x, box.y ], [ box.x + box.width, box.y ], [ box.x, box.y + box.height ], [ box.x + box.width, box.y + box.height ] ]; + var bp, rp, rps = []; + while (bp = bps.pop()) { + rp = Matrix.transformPoint(bp[0], bp[1], matrix); + rps.push(rp); + xMin = Math.min(xMin, rp.x); + xMax = Math.max(xMax, rp.x); + yMin = Math.min(yMin, rp.y); + yMax = Math.max(yMax, rp.y); + } + box = new Box({ + x: xMin, + y: yMin, + width: xMax - xMin, + height: yMax - yMin + }); + utils.extend(box, { + closurePoints: rps + }); + return box; + }; + // 获得从 node 到 refer 的变换矩阵 + Matrix.getCTM = function(target, refer) { + var ctm = { + a: 1, + b: 0, + c: 0, + d: 1, + e: 0, + f: 0 + }; + var node = target.shapeNode || target.node; + refer = refer || "parent"; + /** + * 由于新版chrome(dev 48.0)移除了getTransformToElement这个方法可能导致报错,这里做兼容处理 + * @Date 2015-11-12 + * @Editor Naixor + */ + function getTransformToElement(target, source) { + var matrix; + try { + matrix = source.getScreenCTM().inverse(); + } catch (e) { + throw new Error("Can not inverse source element' ctm."); + } + return matrix.multiply(target.getScreenCTM()); + } + // 根据参照坐标系选区的不一样,返回不同的结果 + switch (refer) { + case "screen": + // 以浏览器屏幕为参照坐标系 + ctm = node.getScreenCTM(); + break; + + case "doc": + case "paper": + // 以文档(Paper)为参照坐标系 + ctm = node.getCTM(); + break; + + case "view": + case "top": + // 以顶层绘图容器(视野)为参照坐标系 + if (target.getPaper()) { + ctm = node.getTransformToElement !== undefined ? node.getTransformToElement(target.getPaper().shapeNode) : getTransformToElement(node, target.getPaper().shapeNode); + } + break; + + case "parent": + // 以父容器为参照坐标系 + if (target.node.parentNode) { + ctm = node.getTransformToElement !== undefined ? node.getTransformToElement(target.node.parentNode) : getTransformToElement(node, target.node.parentNode); + } + break; + + default: + // 其他情况,指定参照物 + if (refer.node) { + ctm = node.getTransformToElement !== undefined ? node.getTransformToElement(refer.shapeNode || refer.node) : getTransformToElement(node, refer.shapeNode || refer.node); + } + } + return ctm ? new Matrix(ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f) : new Matrix(); + }; + return Matrix; + } +}; + +//src/graphic/palette.js +/** + * 调色板 + */ +_p[44] = { + value: function(require, exports, module) { + //标准color + var StandardColor = _p.r(64), Color = _p.r(28), Utils = _p.r(12); + var Palette = _p.r(11).createClass("Palette", { + constructor: function() { + this.color = {}; + }, + /* + * 获取颜色名称所对应的颜色值的Color对象 + * @param name 需要获取的颜色名称 + * @return 对应颜色名称的color对象, 如果未找到对应的名称, 则返回null + */ + get: function(name) { + var colorValue = this.color[name] || StandardColor.EXTEND_STANDARD[name] || StandardColor.COLOR_STANDARD[name] || ""; + if (colorValue) { + return new Color(colorValue); + } + return null; + }, + /* + * 获取给定名称的颜色的hex值表示 + * @param name 需要获取的颜色名称 + * @return 如果找到对应的名称, 则返回该名称所对应的hex格式的值, 否则, 返回一个空字符串 + */ + getColorValue: function(name) { + return this.color[name] || StandardColor.EXTEND_STANDARD[name] || StandardColor.COLOR_STANDARD[name] || ""; + }, + /* + * 向调色板实例添加自己独有的颜色名称,对已存在的颜色名称, 将会覆盖掉 + * @param name 新添加的颜色名称 + * @param value 新添加的颜色名称所对应的值, 可以是一个合法的颜色字符串或者是一个color对象 + * @return 新添加的颜色的值 + */ + add: function(name, value) { + if (typeof value === "string") { + this.color[name] = new Color(value).toRGBA(); + } else { + this.color[name] = value.toRGBA(); + } + return value; + }, + /* + * 删除调色板实例上用户自己添加的颜色, 该方法不能删除内置的颜色 + * @param name 需要删除的颜色名称 + * @return 删除是否成功的bool值 + */ + remove: function(name) { + if (this.color.hasOwnProperty(name)) { + delete this.color[name]; + return true; + } + return false; + } + }); + Utils.extend(Palette, { + getColor: function(name) { + var colorValue = StandardColor.EXTEND_STANDARD[name] || StandardColor.COLOR_STANDARD[name]; + if (colorValue) { + return new Color(colorValue); + } + return null; + }, + /* + * 通过给定的名字获取标准的颜色值表示, 返回的值以hex的方式提供 + * @param name 需要获取的标准颜色名称 + * @return 名字所对应的颜色值的hex表示, 如果未找到对应名称的值, 则返回一个空字符串 + */ + getColorValue: function(name) { + return StandardColor.EXTEND_STANDARD[name] || StandardColor.COLOR_STANDARD[name] || ""; + }, + /* + * 向调色板添加颜色名称,新添加的颜色对所有的调色板对象都可见 + * 对已存在的颜色名称, 将会覆盖掉 + * @param name 新添加的颜色名称 + * @param value 新添加的颜色名称所对于的值, 应该是一个hex格式的颜色字符串, 如: ”#ff0000“ + * @return 新添加的颜色的值 + */ + addColor: function(name, value) { + if (typeof value === "string") { + StandardColor.EXTEND_STANDARD[name] = new Color(value).toRGBA(); + } else { + StandardColor.EXTEND_STANDARD[name] = value.toRGBA(); + } + return value; + }, + /* + * 删除用户自己添加的颜色, 该方法不能删除内置的颜色, 该方法不会影响调色板实例自由的颜色 + * @param name 需要删除的颜色名称 + * @return 删除是否成功的bool值 + */ + removeColor: function(name) { + if (StandardColor.EXTEND_STANDARD.hasOwnProperty(name)) { + delete StandardColor.EXTEND_STANDARD[name]; + return true; + } + return false; + } + }); + return Palette; + } +}; + +//src/graphic/paper.js +_p[45] = { + value: function(require, exports, module) { + var Class = _p.r(11); + var utils = _p.r(12); + var svg = _p.r(67); + var Container = _p.r(29); + var ShapeContainer = _p.r(61); + var ViewBox = _p.r(75); + var EventHandler = _p.r(33); + var Styled = _p.r(66); + var Matrix = _p.r(43); + var Paper = Class.createClass("Paper", { + mixins: [ ShapeContainer, EventHandler, Styled, ViewBox ], + constructor: function(container) { + this.callBase(); + this.node = this.createSVGNode(); + this.node.paper = this; + this.node.appendChild(this.resourceNode = svg.createNode("defs")); + this.node.appendChild(this.shapeNode = svg.createNode("g")); + this.resources = new Container(); + this.setWidth("100%").setHeight("100%"); + if (container) { + this.renderTo(container); + } + this.callMixin(); + }, + renderTo: function(container) { + if (utils.isString(container)) { + container = document.getElementById(container); + } + this.container = container; + container.appendChild(this.node); + }, + createSVGNode: function() { + var node = svg.createNode("svg"); + node.setAttribute("xmlns", "http://www.w3.org/2000/svg"); + node.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink"); + node.setAttribute("version", "1.1"); + return node; + }, + getNode: function() { + return this.node; + }, + getContainer: function() { + return this.container; + }, + getWidth: function() { + return this.node.clientWidth; + }, + setWidth: function(width) { + this.node.setAttribute("width", width); + return this; + }, + getHeight: function() { + return this.node.clientHeight; + }, + setHeight: function(height) { + this.node.setAttribute("height", height); + return this; + }, + setViewPort: function(cx, cy, zoom) { + var viewport, box; + if (arguments.length == 1) { + viewport = arguments[0]; + cx = viewport.center.x; + cy = viewport.center.y; + zoom = viewport.zoom; + } + zoom = zoom || 1; + box = this.getViewBox(); + var matrix = new Matrix(); + var dx = box.x + box.width / 2 - cx, dy = box.y + box.height / 2 - cy; + matrix.translate(-cx, -cy); + matrix.scale(zoom); + matrix.translate(cx, cy); + matrix.translate(dx, dy); + this.shapeNode.setAttribute("transform", "matrix(" + matrix + ")"); + this.viewport = { + center: { + x: cx, + y: cy + }, + offset: { + x: dx, + y: dy + }, + zoom: zoom + }; + return this; + }, + getViewPort: function() { + if (!this.viewport) { + var box = this.getViewBox(); + return { + zoom: 1, + center: { + x: box.x + box.width / 2, + y: box.y + box.height / 2 + }, + offset: { + x: 0, + y: 0 + } + }; + } + return this.viewport; + }, + getViewPortMatrix: function() { + return Matrix.parse(this.shapeNode.getAttribute("transform")); + }, + getViewPortTransform: function() { + var m = this.shapeNode.getCTM(); + return new Matrix(m.a, m.b, m.c, m.d, m.e, m.f); + }, + getTransform: function() { + return this.getViewPortTransform().reverse(); + }, + addResource: function(resource) { + this.resources.appendItem(resource); + if (resource.node) { + this.resourceNode.appendChild(resource.node); + } + return this; + }, + removeResource: function(resource) { + if (resource.remove) { + resource.remove(); + } + if (resource.node) { + this.resourceNode.removeChild(resource.node); + } + return this; + }, + getPaper: function() { + return this; + } + }); + var Shape = _p.r(60); + Class.extendClass(Shape, { + getPaper: function() { + var parent = this.container; + while (parent && parent instanceof Paper === false) { + parent = parent.container; + } + return parent; + }, + isAttached: function() { + return !!this.getPaper(); + }, + whenPaperReady: function(fn) { + var me = this; + function check() { + var paper = me.getPaper(); + if (paper && fn) { + fn.call(me, paper); + } + return paper; + } + if (!check()) { + this.on("add treeadd", function listen() { + if (check()) { + me.off("add", listen); + me.off("treeadd", listen); + } + }); + } + return this; + } + }); + return Paper; + } +}; + +//src/graphic/path.js +_p[46] = { + value: function(require, exports, module) { + var Utils = _p.r(12); + var createClass = _p.r(11).createClass; + var Shape = _p.r(60); + var svg = _p.r(67); + var g = _p.r(34); + var slice = Array.prototype.slice, flatten = Utils.flatten; + var PathDrawer = createClass("PathDrawer", { + constructor: function(path) { + this.segment = []; + this.path = path; + this.__clear = false; + }, + getPath: function() { + return this.path; + }, + redraw: function() { + this._transation = this._transation || []; + return this.clear(); + }, + done: function() { + var transation = this._transation; + this._transation = null; + this.push(transation); + return this; + }, + clear: function() { + if (this._transation) { + this._transation = []; + } else { + this.path.setPathData("M 0 0"); + } + this._clear = true; + return this; + }, + push: function() { + var segment = slice.call(arguments); + var originData; + if (this._transation) { + this._transation.push(segment); + return this; + } + if (this._clear) { + originData = ""; + this._clear = false; + } else { + originData = this.path.getPathData(); + } + originData = originData || ""; + this.path.setPathData(originData + g.pathToString(segment)); + return this; + }, + moveTo: function(x, y) { + return this.push("M", slice.call(arguments)); + }, + moveBy: function(dx, dy) { + return this.push("m", slice.call(arguments)); + }, + lineTo: function(x, y) { + return this.push("L", slice.call(arguments)); + }, + lineBy: function(dx, dy) { + return this.push("l", slice.call(arguments)); + }, + arcTo: function(rx, ry, xr, laf, sf, x, y) { + return this.push("A", slice.call(arguments)); + }, + arcBy: function(rx, ry, xr, laf, sf, dx, dy) { + return this.push("a", arguments); + }, + carcTo: function(r, laf, sf, x, y) { + return this.push("A", [ r, r, 0 ].concat(slice.call(arguments, 1))); + }, + carcBy: function(r, laf, sf, dx, dy) { + return this.push("a", [ r, r, 0 ].concat(slice.call(arguments, 1))); + }, + bezierTo: function(x1, y1, x2, y2, x, y) { + return this.push("C", slice.call(arguments)); + }, + bezierBy: function(dx1, dy1, dx2, dy2, dx, dy) { + return this.push("c", slice.call(arguments)); + }, + close: function() { + return this.push("z"); + } + }); + return createClass("Path", { + base: Shape, + constructor: function(data) { + this.callBase("path"); + if (data) { + this.setPathData(data); + } + this.node.setAttribute("fill", svg.defaults.fill); + this.node.setAttribute("stroke", svg.defaults.stroke); + }, + setPathData: function(data) { + data = data || "M0,0"; + this.pathdata = g.pathToString(data); + this.node.setAttribute("d", this.pathdata); + this.trigger("shapeupdate", { + type: "pathdata" + }); + return this; + }, + getPathData: function() { + return this.pathdata || ""; + }, + getDrawer: function() { + return new PathDrawer(this); + }, + isClosed: function() { + var data = this.getPathData(); + return !!~data.indexOf("z") || !!~data.indexOf("Z"); + } + }); + } +}; + +//src/graphic/pattern.js +_p[47] = { + value: function(require, exports, module) { + var Resource = _p.r(58); + var ShapeContainer = _p.r(61); + var svg = _p.r(67); + return _p.r(11).createClass("PatternBrush", { + base: Resource, + mixins: [ ShapeContainer ], + constructor: function(paper) { + this.callBase("pattern", paper); + this.node.setAttribute("patternUnits", "userSpaceOnUse"); + }, + setX: function(x) { + this.x = x; + this.node.setAttribute("x", x); + return this; + }, + setY: function(y) { + this.y = y; + this.node.setAttribute("y", y); + return this; + }, + setWidth: function(width) { + this.width = width; + this.node.setAttribute("width", width); + return this; + }, + setHeight: function(height) { + this.height = height; + this.node.setAttribute("height", height); + return this; + }, + getWidth: function() { + return this.width; + }, + getHeight: function() { + return this.height; + } + }); + } +}; + +//src/graphic/pen.js +_p[48] = { + value: function(require, exports, module) { + var Color = _p.r(28); + return _p.r(11).createClass("Pen", { + constructor: function(brush, width) { + this.brush = brush; + this.width = width || 1; + this.linecap = null; + this.linejoin = null; + this.dashArray = null; + this.opacity = 1; + }, + getBrush: function() { + return this.brush; + }, + setBrush: function(brush) { + this.brush = brush; + return this; + }, + setColor: function(color) { + return this.setBrush(color); + }, + getColor: function() { + return this.brush instanceof Color ? this.brush : null; + }, + getWidth: function() { + return this.width; + }, + setWidth: function(width) { + this.width = width; + return this; + }, + getOpacity: function() { + return this.opacity; + }, + setOpacity: function(opacity) { + this.opacity = opacity; + }, + getLineCap: function() { + return this.linecap; + }, + setLineCap: function(linecap) { + this.linecap = linecap; + return this; + }, + getLineJoin: function() { + return this.linejoin; + }, + setLineJoin: function(linejoin) { + this.linejoin = linejoin; + return this; + }, + getDashArray: function() { + return this.dashArray; + }, + setDashArray: function(dashArray) { + this.dashArray = dashArray; + return this; + }, + stroke: function(shape) { + var node = shape.node; + node.setAttribute("stroke", this.brush.toString()); + node.setAttribute("stroke-width", this.getWidth()); + if (this.getOpacity() < 1) { + node.setAttribute("stroke-opacity", this.getOpacity()); + } + if (this.getLineCap()) { + node.setAttribute("stroke-linecap", this.getLineCap()); + } + if (this.getLineJoin()) { + node.setAttribute("stroke-linejoin", this.getLineJoin()); + } + if (this.getDashArray()) { + node.setAttribute("stroke-dasharray", this.getDashArray()); + } + } + }); + } +}; + +//src/graphic/pie.js +_p[49] = { + value: function(require, exports, module) { + return _p.r(11).createClass({ + base: _p.r(68), + constructor: function(radius, angle, angleOffset) { + this.callBase([ 0, radius ], angle, angleOffset); + }, + getRadius: function() { + return this.getSectionArray()[1]; + }, + setRadius: function(radius) { + this.setSectionArray([ 0, radius ]); + } + }); + } +}; + +//src/graphic/point.js +/* + * 点对象抽象 + */ +_p[50] = { + value: function(require, exports, module) { + /** + * @class kity.Point + * @description 表示一个点 + */ + var Point = _p.r(11).createClass("Point", { + /** + * @constructor + * @for kity.Point + * @description 指定默认的 x 和 y 创建一个点 + * + * @param {Number} x 点的 x 坐标 + * @param {Number} y 点的 y 坐标 + */ + constructor: function(x, y) { + /** + * @property + * @for kity.Point + * @description 表示点的 x 坐标 + * @type {Number} + */ + this.x = x || 0; + /** + * @property + * @for kity.Point + * @description 表示点的 y 坐标 + * @type {Number} + */ + this.y = y || 0; + }, + offset: function(dx, dy) { + if (arguments.length == 1) { + dy = dx.y; + dx = dx.x; + } + return new Point(this.x + dx, this.y + dy); + }, + valueOf: function() { + return [ this.x, this.y ]; + }, + toString: function() { + return this.valueOf().join(" "); + }, + spof: function() { + return new Point((this.x | 0) + .5, (this.y | 0) + .5); + }, + round: function() { + return new Point(this.x | 0, this.y | 0); + }, + isOrigin: function() { + return this.x === 0 && this.y === 0; + } + }); + /** + * @static + * @method fromPolar() + * @for kity.Point + * @grammar kity.Point.fromPolar(radius, angle, unit) => kity.Point + * @param {Number} radius 极坐标中的半径 + * @param {Number} angle 极坐标中的角度 + * @param {String} unit 角度使用的单位,默认为 'deg' (角度),可以取值为 'rad',表示传入的是弧度值 + */ + Point.fromPolar = function(radius, angle, unit) { + if (unit != "rad") { + // deg to rad + angle = angle / 180 * Math.PI; + } + return new Point(radius * Math.cos(angle), radius * Math.sin(angle)); + }; + Point.parse = function(unknown) { + if (!unknown) return new Point(); + if (unknown instanceof Point) { + return unknown; + } + if (typeof unknown == "string") { + return Point.parse(unknown.split(/\s*[\s,]\s*/)); + } + if ("0" in unknown && "1" in unknown) { + return new Point(unknown[0], unknown[1]); + } + }; + return Point; + } +}; + +//src/graphic/pointcontainer.js +/** + * 点集合容器 + */ +_p[51] = { + value: function(require, exports, module) { + return _p.r(11).createClass("PointContainer", { + base: _p.r(29), + constructor: function() { + this.callBase(); + }, + addPoint: function(point, pos) { + return this.addItem.apply(this, arguments); + }, + prependPoint: function() { + return this.prependItem.apply(this, arguments); + }, + appendPoint: function() { + return this.appendItem.apply(this, arguments); + }, + removePoint: function(pos) { + return this.removeItem.apply(this, arguments); + }, + addPoints: function() { + return this.addItems.apply(this, arguments); + }, + setPoints: function() { + return this.setItems.apply(this, arguments); + }, + getPoint: function() { + return this.getItem.apply(this, arguments); + }, + getPoints: function() { + return this.getItems.apply(this, arguments); + }, + getFirstPoint: function() { + return this.getFirstItem.apply(this, arguments); + }, + getLastPoint: function() { + return this.getLastItem.apply(this, arguments); + } + }); + } +}; + +//src/graphic/poly.js +/* + * 通过点来决定图形的公共父类 + */ +_p[52] = { + value: function(require, exports, module) { + var Utils = _p.r(12); + return _p.r(11).createClass("Poly", { + base: _p.r(46), + mixins: [ _p.r(51) ], + constructor: function(points, closeable) { + this.callBase(); + //是否可闭合 + this.closeable = !!closeable; + this.setPoints(points || []); + this.changeable = true; + this.update(); + }, + //当点集合发生变化时采取的动作 + onContainerChanged: function() { + if (this.changeable) { + this.update(); + } + }, + update: function() { + var drawer = this.getDrawer(), points = this.getPoints(); + drawer.clear(); + if (!points.length) { + return this; + } + drawer.moveTo(points[0]); + for (var i = 1, point, len = points.length; i < len; i++) { + point = points[i]; + drawer.lineTo(point); + } + if (this.closeable && points.length > 2) { + drawer.close(); + } + return this; + } + }); + } +}; + +//src/graphic/polygon.js +_p[53] = { + value: function(require, exports, module) { + return _p.r(11).createClass("Polygon", { + base: _p.r(52), + constructor: function(points) { + this.callBase(points, true); + } + }); + } +}; + +//src/graphic/polyline.js +_p[54] = { + value: function(require, exports, module) { + return _p.r(11).createClass("Polyline", { + base: _p.r(52), + constructor: function(points) { + this.callBase(points); + } + }); + } +}; + +//src/graphic/radialgradient.js +_p[55] = { + value: function(require, exports, module) { + var Gradient = _p.r(35); + return _p.r(11).createClass("RadialGradientBrush", { + base: Gradient, + constructor: function(paper) { + this.callBase("radialGradient", paper); + this.setCenter(.5, .5); + this.setFocal(.5, .5); + this.setRadius(.5); + }, + setCenter: function(cx, cy) { + this.node.setAttribute("cx", cx); + this.node.setAttribute("cy", cy); + return this; + }, + getCenter: function() { + return { + x: +this.node.getAttribute("cx"), + y: +this.node.getAttribute("cy") + }; + }, + setFocal: function(fx, fy) { + this.node.setAttribute("fx", fx); + this.node.setAttribute("fy", fy); + return this; + }, + getFocal: function() { + return { + x: +this.node.getAttribute("fx"), + y: +this.node.getAttribute("fy") + }; + }, + setRadius: function(r) { + this.node.setAttribute("r", r); + return this; + }, + getRadius: function() { + return +this.node.getAttribute("r"); + } + }); + } +}; + +//src/graphic/rect.js +_p[56] = { + value: function(require, exports, module) { + var RectUtils = {}, Utils = _p.r(12), Point = _p.r(50), Box = _p.r(25); + Utils.extend(RectUtils, { + //根据传递进来的width、height和radius属性, + //获取最适合的radius值 + formatRadius: function(width, height, radius) { + var minValue = Math.floor(Math.min(width / 2, height / 2)); + return Math.min(minValue, radius); + } + }); + /** + * @class kity.Rect + * @description 表示一个矩形 + * @base kity.Path + */ + var Rect = _p.r(11).createClass("Rect", { + base: _p.r(46), + /** + * @constructor + * @for kity.Rect + * @grammar new kity.Rect(width, height, x, y, radius) + * @param {Number} width 矩形的初始化宽度 + * @param {Number} height 矩形的初始化高度 + * @param {Number} x 矩形的初始化 x 坐标 + * @param {Number} y 矩形的初始化 y 坐标 + * @param {Number} radius 矩形的初始化圆角大小 + */ + constructor: function(width, height, x, y, radius) { + this.callBase(); + this.x = x || 0; + this.y = y || 0; + this.width = width || 0; + this.height = height || 0; + this.radius = RectUtils.formatRadius(this.width, this.height, radius || 0); + this.update(); + }, + update: function() { + var x = this.x, y = this.y, w = this.width, h = this.height, r = this.radius; + var drawer = this.getDrawer().redraw(); + if (!r) { + // 直角 + drawer.push("M", x, y); + drawer.push("h", w); + drawer.push("v", h); + drawer.push("h", -w); + drawer.push("z"); + } else { + //圆角 + w -= 2 * r; + h -= 2 * r; + drawer.push("M", x + r, y); + drawer.push("h", w); + drawer.push("a", r, r, 0, 0, 1, r, r); + drawer.push("v", h); + drawer.push("a", r, r, 0, 0, 1, -r, r); + drawer.push("h", -w); + drawer.push("a", r, r, 0, 0, 1, -r, -r); + drawer.push("v", -h); + drawer.push("a", r, r, 0, 0, 1, r, -r); + drawer.push("z"); + } + drawer.done(); + return this; + }, + /** + * @method setWidth + * @for kity.Rect + * @grammar setWidth(width) => kity.Rect + * @description 设置矩形的宽度,设置后返回矩形实例本身 + * @param {Number} width 宽度值 + * + * @example + * ```js + * rect.setWidth(300); + * ``` + */ + setWidth: function(width) { + this.width = width; + return this.update(); + }, + /** + * @method setHeight + * @for kity.Rect + * @grammar setHeight(height) => kity.Rect + * @description 设置矩形的高度,设置后返回矩形实例本身 + * @param {Number} height 高度值 + * + * @example + * ```js + * rect.setHeight(200); + * ``` + */ + setHeight: function(height) { + this.height = height; + return this.update(); + }, + /** + * @method setSize + * @for kity.Rect + * @grammar setSize(width, height) => kity.Rect + * @description 设置矩形的尺寸,设置后返回矩形本身 + * @param {Number} width 矩形的宽度值 + * @param {Number} height 矩形的高度值 + * + * @example + * ```js + * rect.setSize(300, 200); + * ``` + */ + setSize: function(width, height) { + this.width = width; + this.height = height; + return this.update(); + }, + /** + * @method setBox + * @for kity.Rect + * @grammar setBox(box) => kity.Rect + * @description 使用一个 kity 的盒子数据, + * @param {kity.Box} box 盒子数据 + */ + setBox: function(box) { + this.x = box.x; + this.y = box.y; + this.width = box.width; + this.height = box.height; + return this.update(); + }, + getBox: function() { + return new Box(this.x, this.y, this.width, this.height); + }, + getRadius: function() { + return this.radius; + }, + setRadius: function(radius) { + this.radius = RectUtils.formatRadius(this.width, this.height, radius || 0); + return this.update(); + }, + getPosition: function() { + return new Point(this.x, this.y); + }, + setPosition: function(x, y) { + if (arguments.length == 1) { + var p = Point.parse(arguments[0]); + y = p.y; + x = p.x; + } + this.x = x; + this.y = y; + return this.update(); + }, + getWidth: function() { + return this.width; + }, + getHeight: function() { + return this.height; + }, + getPositionX: function() { + return this.x; + }, + getPositionY: function() { + return this.y; + }, + setPositionX: function(x) { + this.x = x; + return this.update(); + }, + setPositionY: function(y) { + this.y = y; + return this.update(); + } + }); + return Rect; + } +}; + +//src/graphic/regularpolygon.js +_p[57] = { + value: function(require, exports, module) { + var Point = _p.r(50); + return _p.r(11).createClass("RegularPolygon", { + base: _p.r(46), + constructor: function(side, radius, x, y) { + this.callBase(); + this.radius = radius || 0; + this.side = Math.max(side || 3, 3); + if (arguments.length > 2) { + if (arguments.length == 3) { + y = x.y; + x = x.x; + } + } + this.center = new Point(x, y); + this.draw(); + }, + getSide: function() { + return this.side; + }, + setSide: function(side) { + this.side = side; + return this.draw(); + }, + getRadius: function() { + return this.radius; + }, + setRadius: function(radius) { + this.radius = radius; + return this.draw(); + }, + draw: function() { + var radius = this.radius, side = this.side, step = Math.PI * 2 / side, drawer = this.getDrawer(), i; + drawer.clear(); + drawer.moveTo(Point.fromPolar(radius, Math.PI / 2, "rad").offset(this.center)); + for (i = 0; i <= side; i++) { + drawer.lineTo(Point.fromPolar(radius, step * i + Math.PI / 2, "rad").offset(this.center)); + } + drawer.close(); + return this; + } + }); + } +}; + +//src/graphic/resource.js +/** + * @fileOverview + * + * 资源节点基类 + * + * @author: techird + * @copyright: Baidu FEX, 2014 + */ +_p[58] = { + value: function(require, exports, module) { + var svg = _p.r(67); + return _p.r(11).createClass("Resource", { + constructor: function(nodeType, paper) { + this.callBase(); + this.node = svg.createNode(nodeType); + if (paper) { + paper.addResource(this); + } + }, + toString: function() { + return "url(#" + this.node.id + ")"; + } + }); + } +}; + +//src/graphic/ring.js +_p[59] = { + value: function(require, exports, module) { + return _p.r(11).createClass({ + base: _p.r(68), + constructor: function(innerRadius, outerRadius) { + this.callBase([ innerRadius, outerRadius ], 360, 0); + }, + getInnerRadius: function() { + return this.getSectionArray()[0]; + }, + getOuterRadius: function() { + return this.getSectionArray()[1]; + }, + setInnerRadius: function(value) { + this.setSectionArray([ value, this.getOuterRadius() ]); + }, + setOuterRadius: function(value) { + this.setSectionArray([ this.getInnerRadius(), value ]); + } + }); + } +}; + +//src/graphic/shape.js +_p[60] = { + value: function(require, exports, module) { + var svg = _p.r(67); + var utils = _p.r(12); + var EventHandler = _p.r(33); + var Styled = _p.r(66); + var Data = _p.r(31); + var Matrix = _p.r(43); + var Pen = _p.r(48); + var slice = Array.prototype.slice; + var Box = _p.r(25); + var Shape = _p.r(11).createClass("Shape", { + mixins: [ EventHandler, Styled, Data ], + constructor: function Shape(tagName) { + this.node = svg.createNode(tagName); + this.node.shape = this; + this.transform = { + translate: null, + rotate: null, + scale: null, + matrix: null + }; + this.callMixin(); + }, + getId: function() { + return this.node.id; + }, + setId: function(id) { + this.node.id = id; + return this; + }, + getNode: function() { + return this.node; + }, + getBoundaryBox: function() { + var box; + try { + box = this.node.getBBox(); + } catch (e) { + box = { + x: this.node.clientLeft, + y: this.node.clientTop, + width: this.node.clientWidth, + height: this.node.clientHeight + }; + } + return new Box(box); + }, + getRenderBox: function(refer) { + var box = this.getBoundaryBox(); + var matrix = this.getTransform(refer); + return matrix.transformBox(box); + }, + getWidth: function() { + return this.getRenderBox().width; + }, + getHeight: function() { + return this.getRenderBox().height; + }, + getSize: function() { + var box = this.getRenderBox(); + delete box.x; + delete box.y; + return box; + }, + setOpacity: function(value) { + this.node.setAttribute("opacity", value); + return this; + }, + getOpacity: function() { + var opacity = this.node.getAttribute("opacity"); + return opacity ? +opacity : 1; + }, + setVisible: function(value) { + if (value) { + this.node.removeAttribute("display"); + } else { + this.node.setAttribute("display", "none"); + } + return this; + }, + getVisible: function() { + this.node.getAttribute("display"); + }, + hasAncestor: function(node) { + var parent = this.container; + while (parent) { + if (parent === node) { + return true; + } + parent = parent.container; + } + return false; + }, + getTransform: function(refer) { + return Matrix.getCTM(this, refer); + }, + clearTransform: function() { + this.node.removeAttribute("transform"); + this.transform = { + translate: null, + rotate: null, + scale: null, + matrix: null + }; + this.trigger("shapeupdate", { + type: "transform" + }); + return this; + }, + _applyTransform: function() { + var t = this.transform, result = []; + if (t.translate) { + result.push([ "translate(", t.translate, ")" ]); + } + if (t.rotate) { + result.push([ "rotate(", t.rotate, ")" ]); + } + if (t.scale) { + result.push([ "scale(", t.scale, ")" ]); + } + if (t.matrix) { + result.push([ "matrix(", t.matrix, ")" ]); + } + this.node.setAttribute("transform", utils.flatten(result).join(" ")); + return this; + }, + setMatrix: function(m) { + this.transform.matrix = m; + return this._applyTransform(); + }, + setTranslate: function(t) { + this.transform.translate = t !== null && slice.call(arguments) || null; + return this._applyTransform(); + }, + setRotate: function(r) { + this.transform.rotate = r !== null && slice.call(arguments) || null; + return this._applyTransform(); + }, + setScale: function(s) { + this.transform.scale = s !== null && slice.call(arguments) || null; + return this._applyTransform(); + }, + translate: function(dx, dy) { + var m = this.transform.matrix || new Matrix(); + if (dy === undefined) { + dy = 0; + } + this.transform.matrix = m.translate(dx, dy); + return this._applyTransform(); + }, + rotate: function(deg) { + var m = this.transform.matrix || new Matrix(); + this.transform.matrix = m.rotate(deg); + return this._applyTransform(); + }, + scale: function(sx, sy) { + var m = this.transform.matrix || new Matrix(); + if (sy === undefined) { + sy = sx; + } + this.transform.matrix = m.scale(sx, sy); + return this._applyTransform(); + }, + skew: function(sx, sy) { + var m = this.transform.matrix || new Matrix(); + if (sy === undefined) { + sy = sx; + } + this.transform.matrix = m.skew(sx, sy); + return this._applyTransform(); + }, + stroke: function(pen, width) { + if (pen && pen.stroke) { + pen.stroke(this); + } else if (pen) { + // 字符串或重写了 toString 的对象 + this.node.setAttribute("stroke", pen.toString()); + if (width) { + this.node.setAttribute("stroke-width", width); + } + } else if (pen === null) { + this.node.removeAttribute("stroe"); + } + return this; + }, + fill: function(brush) { + // 字符串或重写了 toString 的对象 + if (brush) { + this.node.setAttribute("fill", brush.toString()); + } + if (brush === null) { + this.node.removeAttribute("fill"); + } + return this; + }, + setAttr: function(a, v) { + var me = this; + if (utils.isObject(a)) { + utils.each(a, function(val, key) { + me.setAttr(key, val); + }); + } + if (v === undefined || v === null || v === "") { + this.node.removeAttribute(a); + } else { + this.node.setAttribute(a, v); + } + return this; + }, + getAttr: function(a) { + return this.node.getAttribute(a); + } + }); + return Shape; + } +}; + +//src/graphic/shapecontainer.js +_p[61] = { + value: function(require, exports, module) { + var Container = _p.r(29); + var utils = _p.r(12); + var ShapeContainer = _p.r(11).createClass("ShapeContainer", { + base: Container, + isShapeContainer: true, + /* private */ + handleAdd: function(shape, index) { + var parent = this.getShapeNode(); + parent.insertBefore(shape.node, parent.childNodes[index] || null); + shape.trigger("add", { + container: this + }); + if (shape.notifyTreeModification) { + shape.notifyTreeModification("treeadd", this); + } + }, + /* private */ + handleRemove: function(shape, index) { + var parent = this.getShapeNode(); + parent.removeChild(shape.node); + shape.trigger("remove", { + container: this + }); + if (shape.notifyTreeModification) { + shape.notifyTreeModification("treeremove", this); + } + }, + /* private */ + notifyTreeModification: function(type, container) { + this.eachItem(function(index, shape) { + if (shape.notifyTreeModification) { + shape.notifyTreeModification(type, container); + } + shape.trigger(type, { + container: container + }); + }); + }, + /* public */ + getShape: function(index) { + return this.getItem(index); + }, + /* public */ + addShape: function(shape, index) { + return this.addItem(shape, index); + }, + put: function(shape) { + this.addShape(shape); + return shape; + }, + appendShape: function(shape) { + return this.addShape(shape); + }, + prependShape: function(shape) { + return this.addShape(shape, 0); + }, + replaceShape: function(replacer, origin) { + var index = this.indexOf(origin); + if (index === -1) { + return; + } + this.removeShape(index); + this.addShape(replacer, index); + return this; + }, + addShapeBefore: function(shape, refer) { + var index = this.indexOf(refer); + return this.addShape(shape, index); + }, + addShapeAfter: function(shape, refer) { + var index = this.indexOf(refer); + return this.addShape(shape, index === -1 ? undefined : index + 1); + }, + /* public */ + addShapes: function(shapes) { + return this.addItems(shapes); + }, + /* public */ + removeShape: function(index) { + return this.removeItem(index); + }, + getShapes: function() { + return this.getItems(); + }, + getShapesByType: function(name) { + var shapes = []; + function getShapes(shape) { + if (name.toLowerCase() == shape.getType().toLowerCase()) { + shapes.push(shape); + } + if (shape.isShapeContainer) { + utils.each(shape.getShapes(), function(n) { + getShapes(n); + }); + } + } + getShapes(this); + return shapes; + }, + /* public */ + getShapeById: function(id) { + return this.getShapeNode().getElementById(id).shape; + }, + arrangeShape: function(shape, index) { + return this.removeShape(shape).addShape(shape, index); + }, + /* protected */ + getShapeNode: function() { + return this.shapeNode || this.node; + } + }); + var Shape = _p.r(60); + _p.r(11).extendClass(Shape, { + bringTo: function(index) { + this.container.arrangeShape(this, index); + return this; + }, + bringFront: function() { + return this.bringTo(this.container.indexOf(this) + 1); + }, + bringBack: function() { + return this.bringTo(this.container.indexOf(this) - 1); + }, + bringTop: function() { + this.container.removeShape(this).addShape(this); + return this; + }, + bringRear: function() { + return this.bringTo(0); + }, + bringRefer: function(referShape, offset) { + if (referShape.container) { + if (this.remove) { + this.remove(); + } + referShape.container.addShape(this, referShape.container.indexOf(referShape) + (offset || 0)); + } + return this; + }, + bringAbove: function(referShape) { + return this.bringRefer(referShape); + }, + bringBelow: function(referShape) { + return this.bringRefer(referShape, 1); + }, + replaceBy: function(newShape) { + if (this.container) { + newShape.bringAbove(this); + this.remove(); + } + return this; + } + }); + return ShapeContainer; + } +}; + +//src/graphic/shapeevent.js +/* + * 图形事件包装类 + * */ +_p[62] = { + value: function(require, exprots, module) { + var Matrix = _p.r(43), Utils = _p.r(12), Point = _p.r(50); + return _p.r(11).createClass("ShapeEvent", { + constructor: function(event) { + var target = null; + // dom 事件封装对象 + if (!Utils.isObject(event.target)) { + this.type = event.type; + target = event.target; + // use标签有特殊属性, 需要区别对待 + if (target.correspondingUseElement) { + target = target.correspondingUseElement; + } + this.originEvent = event; + this.targetShape = target.shape || target.paper || event.currentTarget && (event.currentTarget.shape || event.currentTarget.paper); + if (event._kityParam) { + Utils.extend(this, event._kityParam); + } + } else { + Utils.extend(this, event); + } + }, + preventDefault: function() { + var evt = this.originEvent; + if (!evt) { + return true; + } + if (evt.preventDefault) { + evt.preventDefault(); + return evt.cancelable; + } else { + evt.returnValue = false; + return true; + } + }, + //当前鼠标事件在用户坐标系中点击的点的坐标位置 + getPosition: function(refer, touchIndex) { + if (!this.originEvent) { + return null; + } + var eventClient = this.originEvent.touches ? this.originEvent.touches[touchIndex || 0] : this.originEvent; + var target = this.targetShape; + var targetNode = target.shapeNode || target.node; + var pScreen = new Point(eventClient && eventClient.clientX || 0, eventClient && eventClient.clientY || 0); + var pTarget = Matrix.transformPoint(pScreen, targetNode.getScreenCTM().inverse()); + var pRefer = Matrix.getCTM(target, refer || "view").transformPoint(pTarget); + return pRefer; + }, + stopPropagation: function() { + var evt = this.originEvent; + if (!evt) { + return true; + } + if (evt.stopPropagation) { + evt.stopPropagation(); + } else { + evt.cancelBubble = false; + } + } + }); + } +}; + +//src/graphic/shapepoint.js +/* + * 图形上的点抽象 + */ +_p[63] = { + value: function(require, exports, module) { + return _p.r(11).createClass("ShapePoint", { + base: _p.r(50), + constructor: function(px, py) { + this.callBase(px, py); + }, + setX: function(x) { + return this.setPoint(x, this.y); + }, + setY: function(y) { + return this.setPoint(this.x, y); + }, + setPoint: function(x, y) { + this.x = x; + this.y = y; + this.update(); + return this; + }, + getPoint: function() { + return this; + }, + update: function() { + if (this.container && this.container.update) { + this.container.update(); + } + return this; + } + }); + } +}; + +//src/graphic/standardcolor.js +/** + * 标准颜色映射 + */ +_p[64] = { + value: { + COLOR_STANDARD: { + aliceblue: "#f0f8ff", + antiquewhite: "#faebd7", + aqua: "#00ffff", + aquamarine: "#7fffd4", + azure: "#f0ffff", + beige: "#f5f5dc", + bisque: "#ffe4c4", + black: "#000000", + blanchedalmond: "#ffebcd", + blue: "#0000ff", + blueviolet: "#8a2be2", + brown: "#a52a2a", + burlywood: "#deb887", + cadetblue: "#5f9ea0", + chartreuse: "#7fff00", + chocolate: "#d2691e", + coral: "#ff7f50", + cornflowerblue: "#6495ed", + cornsilk: "#fff8dc", + crimson: "#dc143c", + cyan: "#00ffff", + darkblue: "#00008b", + darkcyan: "#008b8b", + darkgoldenrod: "#b8860b", + darkgray: "#a9a9a9", + darkgreen: "#006400", + darkgrey: "#a9a9a9", + darkkhaki: "#bdb76b", + darkmagenta: "#8b008b", + darkolivegreen: "#556b2f", + darkorange: "#ff8c00", + darkorchid: "#9932cc", + darkred: "#8b0000", + darksalmon: "#e9967a", + darkseagreen: "#8fbc8f", + darkslateblue: "#483d8b", + darkslategray: "#2f4f4f", + darkslategrey: "#2f4f4f", + darkturquoise: "#00ced1", + darkviolet: "#9400d3", + deeppink: "#ff1493", + deepskyblue: "#00bfff", + dimgray: "#696969", + dimgrey: "#696969", + dodgerblue: "#1e90ff", + firebrick: "#b22222", + floralwhite: "#fffaf0", + forestgreen: "#228b22", + fuchsia: "#ff00ff", + gainsboro: "#dcdcdc", + ghostwhite: "#f8f8ff", + gold: "#ffd700", + goldenrod: "#daa520", + gray: "#808080", + green: "#008000", + greenyellow: "#adff2f", + grey: "#808080", + honeydew: "#f0fff0", + hotpink: "#ff69b4", + indianred: "#cd5c5c", + indigo: "#4b0082", + ivory: "#fffff0", + khaki: "#f0e68c", + lavender: "#e6e6fa", + lavenderblush: "#fff0f5", + lawngreen: "#7cfc00", + lemonchiffon: "#fffacd", + lightblue: "#add8e6", + lightcoral: "#f08080", + lightcyan: "#e0ffff", + lightgoldenrodyellow: "#fafad2", + lightgray: "#d3d3d3", + lightgreen: "#90ee90", + lightgrey: "#d3d3d3", + lightpink: "#ffb6c1", + lightsalmon: "#ffa07a", + lightseagreen: "#20b2aa", + lightskyblue: "#87cefa", + lightslategray: "#778899", + lightslategrey: "#778899", + lightsteelblue: "#b0c4de", + lightyellow: "#ffffe0", + lime: "#00ff00", + limegreen: "#32cd32", + linen: "#faf0e6", + magenta: "#ff00ff", + maroon: "#800000", + mediumaquamarine: "#66cdaa", + mediumblue: "#0000cd", + mediumorchid: "#ba55d3", + mediumpurple: "#9370db", + mediumseagreen: "#3cb371", + mediumslateblue: "#7b68ee", + mediumspringgreen: "#00fa9a", + mediumturquoise: "#48d1cc", + mediumvioletred: "#c71585", + midnightblue: "#191970", + mintcream: "#f5fffa", + mistyrose: "#ffe4e1", + moccasin: "#ffe4b5", + navajowhite: "#ffdead", + navy: "#000080", + oldlace: "#fdf5e6", + olive: "#808000", + olivedrab: "#6b8e23", + orange: "#ffa500", + orangered: "#ff4500", + orchid: "#da70d6", + palegoldenrod: "#eee8aa", + palegreen: "#98fb98", + paleturquoise: "#afeeee", + palevioletred: "#db7093", + papayawhip: "#ffefd5", + peachpuff: "#ffdab9", + peru: "#cd853f", + pink: "#ffc0cb", + plum: "#dda0dd", + powderblue: "#b0e0e6", + purple: "#800080", + red: "#ff0000", + rosybrown: "#bc8f8f", + royalblue: "#4169e1", + saddlebrown: "#8b4513", + salmon: "#fa8072", + sandybrown: "#f4a460", + seagreen: "#2e8b57", + seashell: "#fff5ee", + sienna: "#a0522d", + silver: "#c0c0c0", + skyblue: "#87ceeb", + slateblue: "#6a5acd", + slategray: "#708090", + slategrey: "#708090", + snow: "#fffafa", + springgreen: "#00ff7f", + steelblue: "#4682b4", + tan: "#d2b48c", + teal: "#008080", + thistle: "#d8bfd8", + tomato: "#ff6347", + turquoise: "#40e0d0", + violet: "#ee82ee", + wheat: "#f5deb3", + white: "#ffffff", + whitesmoke: "#f5f5f5", + yellow: "#ffff00" + }, + //标准扩展 + EXTEND_STANDARD: {} + } +}; + +//src/graphic/star.js +_p[65] = { + value: function(require, exports, module) { + /** + * @see http://www.jdawiseman.com/papers/easymath/surds_star_inner_radius.html + */ + var defaultRatioForStar = { + "3": .2, + // yy + "5": .38196601125, + "6": .57735026919, + "8": .541196100146, + "10": .726542528005, + "12": .707106781187 + }; + var Point = _p.r(50); + return _p.r(11).createClass("Star", { + base: _p.r(46), + constructor: function(vertex, radius, shrink, offset, angleOffset) { + this.callBase(); + this.vertex = vertex || 3; + this.radius = radius || 0; + this.shrink = shrink; + this.offset = offset || new Point(0, 0); + this.angleOffset = angleOffset || 0; + this.draw(); + }, + getVertex: function() { + return this.vertex; + }, + setVertex: function(value) { + this.vertex = value; + return this.draw(); + }, + getRadius: function() { + return this.radius; + }, + setRadius: function(value) { + this.radius = value; + return this.draw(); + }, + getShrink: function() { + return this.shrink; + }, + setShrink: function(value) { + this.shrink = value; + return this.draw(); + }, + getOffset: function() { + return this.offset; + }, + setOffset: function(value) { + this.offset = value; + return this.draw(); + }, + getAngleOffset: function() { + return this.angleOffset; + }, + setAngleOffset: function(value) { + this.angleOffset = value; + return this.draw(); + }, + draw: function() { + var innerRadius = this.radius, outerRadius = this.radius * (this.shrink || defaultRatioForStar[this.vertex] || .5), vertex = this.vertex, offset = this.offset, angleStart = 90, angleStep = 180 / vertex, angleOffset = this.angleOffset, drawer = this.getDrawer(), i, angle; + drawer.clear(); + drawer.moveTo(Point.fromPolar(outerRadius, angleStart)); + for (i = 1; i <= vertex * 2; i++) { + angle = angleStart + angleStep * i; + // 绘制内点 + if (i % 2) { + drawer.lineTo(Point.fromPolar(innerRadius, angle + angleOffset).offset(offset)); + } else { + drawer.lineTo(Point.fromPolar(outerRadius, angle)); + } + } + drawer.close(); + } + }); + } +}; + +//src/graphic/styled.js +_p[66] = { + value: function(require, exports, module) { + // polyfill for ie + var ClassList = _p.r(11).createClass("ClassList", { + constructor: function(node) { + this._node = node; + this._list = node.className.toString().split(" "); + }, + _update: function() { + this._node.className = this._list.join(" "); + }, + add: function(name) { + this._list.push(name); + this._update(); + }, + remove: function(name) { + var index = this._list.indexOf(name); + if (~index) { + this._list.splice(index, 1); + } + this._update(); + }, + contains: function(name) { + return !!~this._list.indexOf(name); + } + }); + function getClassList(node) { + if (!node.classList) { + node.classList = new ClassList(node); + } + return node.classList; + } + return _p.r(11).createClass("Styled", { + addClass: function(name) { + getClassList(this.node).add(name); + return this; + }, + removeClass: function(name) { + getClassList(this.node).remove(name); + return this; + }, + hasClass: function(name) { + return getClassList(this.node).contains(name); + }, + setStyle: function(styles) { + if (arguments.length == 2) { + this.node.style[arguments[0]] = arguments[1]; + return this; + } + for (var name in styles) { + if (styles.hasOwnProperty(name)) { + this.node.style[name] = styles[name]; + } + } + return this; + } + }); + } +}; + +//src/graphic/svg.js +_p[67] = { + value: function(require, exports, module) { + var doc = document; + var id = 0; + var svg = { + createNode: function(name) { + var node = doc.createElementNS(svg.ns, name); + node.id = "kity_" + name + "_" + id++; + return node; + }, + defaults: { + stroke: "none", + fill: "none" + }, + xlink: "http://www.w3.org/1999/xlink", + ns: "http://www.w3.org/2000/svg" + }; + return svg; + } +}; + +//src/graphic/sweep.js +_p[68] = { + value: function(require, exports, module) { + var Point = _p.r(50); + return _p.r(11).createClass("Sweep", { + base: _p.r(46), + constructor: function(sectionArray, angle, angleOffset) { + this.callBase(); + this.sectionArray = sectionArray || []; + this.angle = angle || 0; + this.angleOffset = angleOffset || 0; + this.draw(); + }, + getSectionArray: function() { + return this.sectionArray; + }, + setSectionArray: function(value) { + this.sectionArray = value; + return this.draw(); + }, + getAngle: function() { + return this.angle; + }, + setAngle: function(value) { + this.angle = value; + return this.draw(); + }, + getAngleOffset: function() { + return this.angleOffset; + }, + setAngleOffset: function(value) { + this.angleOffset = value; + return this.draw(); + }, + draw: function() { + var sectionArray = this.sectionArray, i; + for (i = 0; i < sectionArray.length; i += 2) { + this.drawSection(sectionArray[i], sectionArray[i + 1]); + } + return this; + }, + drawSection: function(from, to) { + var angleLength = this.angle && (this.angle % 360 ? this.angle % 360 : 360), angleStart = this.angleOffset, angleHalf = angleStart + angleLength / 2, angleEnd = angleStart + angleLength, sweepFlag = angleLength < 0 ? 0 : 1, drawer = this.getDrawer(); + drawer.redraw(); + if (angleLength === 0) { + drawer.done(); + return; + } + drawer.moveTo(Point.fromPolar(from, angleStart)); + drawer.lineTo(Point.fromPolar(to, angleStart)); + if (to) { + drawer.carcTo(to, 0, sweepFlag, Point.fromPolar(to, angleHalf)); + drawer.carcTo(to, 0, sweepFlag, Point.fromPolar(to, angleEnd)); + } + drawer.lineTo(Point.fromPolar(from, angleEnd)); + if (from) { + drawer.carcTo(from, 0, sweepFlag, Point.fromPolar(from, angleHalf)); + drawer.carcTo(from, 0, sweepFlag, Point.fromPolar(from, angleStart)); + } + drawer.close(); + drawer.done(); + } + }); + } +}; + +//src/graphic/text.js +_p[69] = { + value: function(require, exports, module) { + var TextContent = _p.r(70); + var ShapeContainer = _p.r(61); + var svg = _p.r(67); + var utils = _p.r(12); + var offsetHash = {}; + function getTextBoundOffset(text) { + var font = text._cachedFontHash; + if (offsetHash[font]) { + return offsetHash[font]; + } + var textContent = text.getContent(); + text.setContent("百度Fex"); + var bbox = text.getBoundaryBox(), y = text.getY(); + if (!bbox.height) return { + top: 0, + bottom: 0, + middle: 0 + }; + var topOffset = y - bbox.y + +text.node.getAttribute("dy"), bottomOffset = topOffset - bbox.height; + text.setContent(textContent); + return offsetHash[font] = { + top: topOffset, + bottom: bottomOffset, + middle: (topOffset + bottomOffset) / 2 + }; + } + return _p.r(11).createClass("Text", { + base: TextContent, + mixins: [ ShapeContainer ], + constructor: function(content) { + this.callBase("text"); + if (content !== undefined) { + this.setContent(content); + } + this._buildFontHash(); + }, + fixPosition: function() { + if (!this.__fixedPosition) { + this.setVerticalAlign(this.getVerticalAlign()); + } + }, + _buildFontHash: function() { + var style = window.getComputedStyle(this.node); + this._cachedFontHash = [ style.fontFamily, style.fontSize, style.fontStretch, style.fontStyle, style.fontVariant, style.fontWeight ].join("-"); + }, + _fontChanged: function(font) { + var last = this._lastFont; + var current = utils.extend({}, last, font); + if (!last) { + this._lastFont = font; + return true; + } + var changed = last.family != current.family || last.size != current.size || last.style != current.style || last.weight != current.weight; + this._lastFont = current; + return changed; + }, + setX: function(x) { + this.node.setAttribute("x", x); + return this; + }, + setPosition: function(x, y) { + return this.setX(x).setY(y); + }, + setY: function(y) { + this.node.setAttribute("y", y); + return this; + }, + getX: function() { + return +this.node.getAttribute("x") || 0; + }, + getY: function() { + return +this.node.getAttribute("y") || 0; + }, + setFont: function(font) { + this.callBase(font); + if (this._fontChanged(font)) { + this._buildFontHash(); + this.setVerticalAlign(this.getVerticalAlign()); + } + return this; + }, + setTextAnchor: function(anchor) { + this.node.setAttribute("text-anchor", anchor); + return this; + }, + getTextAnchor: function() { + return this.node.getAttribute("text-anchor") || "start"; + }, + // top/bottom/middle/baseline + setVerticalAlign: function(align) { + this.whenPaperReady(function() { + var dy; + switch (align) { + case "top": + dy = getTextBoundOffset(this).top; + break; + + case "bottom": + dy = getTextBoundOffset(this).bottom; + break; + + case "middle": + dy = getTextBoundOffset(this).middle; + break; + + default: + dy = 0; + } + if (dy) this.__fixedPosition = true; + this.node.setAttribute("dy", dy); + }); + this.verticalAlign = align; + return this; + }, + getVerticalAlign: function() { + return this.verticalAlign || "baseline"; + }, + setStartOffset: function(offset) { + // only for text path + if (this.shapeNode != this.node) { + this.shapeNode.setAttribute("startOffset", offset * 100 + "%"); + } + }, + addSpan: function(span) { + this.addShape(span); + return this; + }, + setPath: function(path) { + var textpath = this.shapeNode; + if (this.shapeNode == this.node) { + // 当前还不是 textpath + textpath = this.shapeNode = svg.createNode("textPath"); + while (this.node.firstChild) { + this.shapeNode.appendChild(this.node.firstChild); + } + this.node.appendChild(textpath); + } + textpath.setAttributeNS(svg.xlink, "xlink:href", "#" + path.node.id); + this.setTextAnchor(this.getTextAnchor()); + return this; + } + }); + } +}; + +//src/graphic/textcontent.js +_p[70] = { + value: function(require, exports, module) { + var Shape = _p.r(60); + return _p.r(11).createClass("TextContent", { + base: Shape, + constructor: function(nodeType) { + // call shape constructor + this.callBase(nodeType); + this.shapeNode = this.shapeNode || this.node; + this.shapeNode.setAttribute("text-rendering", "geometricPrecision"); + }, + clearContent: function() { + while (this.shapeNode.firstChild) { + this.shapeNode.removeChild(this.shapeNode.firstChild); + } + return this; + }, + setContent: function(content) { + this.shapeNode.textContent = content; + return this; + }, + getContent: function() { + return this.shapeNode.textContent; + }, + appendContent: function(content) { + this.shapeNode.textContent += content; + return this; + }, + setSize: function(value) { + return this.setFontSize(value); + }, + setFontSize: function(value) { + return this.setFont({ + size: value + }); + }, + setFontFamily: function(value) { + return this.setFont({ + family: value + }); + }, + setFontBold: function(bold) { + return this.setFont({ + weight: bold ? "bold" : "normal" + }); + }, + setFontItalic: function(italic) { + return this.setFont({ + style: italic ? "italic" : "normal" + }); + }, + setFont: function(font) { + var node = this.node; + [ "family", "size", "weight", "style" ].forEach(function(section) { + if (font[section] === null) { + node.removeAttribute("font-" + section); + } else if (font[section]) { + node.setAttribute("font-" + section, font[section]); + } + }); + return this; + }, + getExtentOfChar: function(index) { + return this.node.getExtentOfChar(index); + }, + getRotationOfChar: function(index) { + return this.node.getRotationOfChar(index); + }, + getCharNumAtPosition: function(x, y) { + return this.node.getCharNumAtPosition(this.node.viewportElement.createSVGPoint(x, y)); + } + }); + } +}; + +//src/graphic/textspan.js +_p[71] = { + value: function(require, exports, module) { + var TextContent = _p.r(70); + var Styled = _p.r(66); + return _p.r(11).createClass("TextSpan", { + base: TextContent, + mixins: [ Styled ], + constructor: function(content) { + this.callBase("tspan"); + this.setContent(content); + } + }); + } +}; + +//src/graphic/use.js +/* + * USE 功能 + */ +_p[72] = { + value: function(require, exports, module) { + var Svg = _p.r(67); + var Class = _p.r(11); + var Use = Class.createClass("Use", { + base: _p.r(60), + constructor: function(shape) { + this.callBase("use"); + this.ref(shape); + }, + ref: function(shape) { + if (!shape) { + this.node.removeAttributeNS(Svg.xlink, "xlink:href"); + return this; + } + var shapeId = shape.getId(); + if (shapeId) { + this.node.setAttributeNS(Svg.xlink, "xlink:href", "#" + shapeId); + } + // by techird + // 作为 Use 的图形,如果没有 fill 和 stroke,移除默认的 'none' 值,用于 Use 覆盖 + if (shape.node.getAttribute("fill") === "none") { + shape.node.removeAttribute("fill"); + } + if (shape.node.getAttribute("stroke") === "none") { + shape.node.removeAttribute("stroke"); + } + return this; + } + }); + var Shape = _p.r(60); + Class.extendClass(Shape, { + // fast-use + use: function() { + return new Use(this); + } + }); + return Use; + } +}; + +//src/graphic/vector.js +_p[73] = { + value: function(require, exports, module) { + var Point = _p.r(50); + var Matrix = _p.r(43); + var Vector = _p.r(11).createClass("Vector", { + base: Point, + constructor: function(x, y) { + this.callBase(x, y); + }, + square: function() { + return this.x * this.x + this.y * this.y; + }, + length: function() { + return Math.sqrt(this.square()); + }, + add: function(q) { + return new Vector(this.x + q.x, this.y + q.y); + }, + minus: function(q) { + return new Vector(this.x - q.x, this.y - q.y); + }, + dot: function(q) { + return this.x * q.x + this.y * q.y; + }, + project: function(q) { + return q.multipy(this.dot(q) / q.square()); + }, + normalize: function(length) { + if (length === undefined) { + length = 1; + } + return this.multipy(length / this.length()); + }, + multipy: function(scale) { + return new Vector(this.x * scale, this.y * scale); + }, + rotate: function(angle, unit) { + if (unit == "rad") { + angle = angle / Math.PI * 180; + } + var p = new Matrix().rotate(angle).transformPoint(this); + return new Vector(p.x, p.y); + }, + vertical: function() { + return new Vector(this.y, -this.x); + }, + reverse: function() { + return this.multipy(-1); + }, + getAngle: function() { + var length = this.length(); + if (length === 0) return 0; + var rad = Math.acos(this.x / length); + var sign = this.y > 0 ? 1 : -1; + return sign * 180 * rad / Math.PI; + } + }); + Vector.fromPoints = function(p1, p2) { + return new Vector(p2.x - p1.x, p2.y - p1.y); + }; + Vector.fromPolar = function() { + var p = Point.fromPolar.apply(Point, arguments); + return new Vector(p.x, p.y); + }; + _p.r(11).extendClass(Point, { + asVector: function() { + return new Vector(this.x, this.y); + } + }); + return Vector; + } +}; + +//src/graphic/view.js +_p[74] = { + value: function(require, exports, module) { + var ShapeContainer = _p.r(61); + var ViewBox = _p.r(75); + return _p.r(11).createClass("View", { + mixins: [ ShapeContainer, ViewBox ], + base: _p.r(74), + constructor: function() { + this.callBase("view"); + } + }); + } +}; + +//src/graphic/viewbox.js +_p[75] = { + value: function(require, exports, module) { + return _p.r(11).createClass("ViewBox", { + getViewBox: function() { + var attr = this.node.getAttribute("viewBox"); + if (attr === null) { + // firefox: + // 1. viewBox 没有设置过的时候获得的是 null + // 2. svg 标签没有指定绝对大小的时候 clientWidth 和 clientHeigt 为 0,需要在父容器上查找 + // TODO: 第 2 条取得的不准确(假如有 padding 之类的) + return { + x: 0, + y: 0, + width: this.node.clientWidth || this.node.parentNode.clientWidth, + height: this.node.clientHeight || this.node.parentNode.clientHeight + }; + } else { + attr = attr.split(" "); + return { + x: +attr[0], + y: +attr[1], + width: +attr[2], + height: +attr[3] + }; + } + }, + setViewBox: function(x, y, width, height) { + this.node.setAttribute("viewBox", [ x, y, width, height ].join(" ")); + return this; + } + }); + } +}; + +//src/kity.js +/** + * @fileOverview kity 暴露的方法或对象 + */ +_p[76] = { + value: function(require, exports, module) { + var kity = {}, utils = _p.r(12); + kity.version = "2.0.0"; + utils.extend(kity, { + // core + createClass: _p.r(11).createClass, + extendClass: _p.r(11).extendClass, + Utils: utils, + Browser: _p.r(10), + // shape + Box: _p.r(25), + Bezier: _p.r(23), + BezierPoint: _p.r(24), + Circle: _p.r(26), + Clip: _p.r(27), + Color: _p.r(28), + Container: _p.r(29), + Curve: _p.r(30), + Ellipse: _p.r(32), + Group: _p.r(36), + Gradient: _p.r(35), + HyperLink: _p.r(37), + Image: _p.r(38), + Line: _p.r(39), + LinearGradient: _p.r(40), + Mask: _p.r(42), + Matrix: _p.r(43), + Marker: _p.r(41), + Palette: _p.r(44), + Paper: _p.r(45), + Path: _p.r(46), + Pattern: _p.r(47), + Pen: _p.r(48), + Point: _p.r(50), + PointContainer: _p.r(51), + Polygon: _p.r(53), + Polyline: _p.r(54), + Pie: _p.r(49), + RadialGradient: _p.r(55), + Resource: _p.r(58), + Rect: _p.r(56), + RegularPolygon: _p.r(57), + Ring: _p.r(59), + Shape: _p.r(60), + ShapePoint: _p.r(63), + ShapeContainer: _p.r(61), + Sweep: _p.r(68), + Star: _p.r(65), + Text: _p.r(69), + TextSpan: _p.r(71), + Use: _p.r(72), + Vector: _p.r(73), + g: _p.r(34), + // animate + Animator: _p.r(0), + Easing: _p.r(1), + OpacityAnimator: _p.r(4), + RotateAnimator: _p.r(6), + ScaleAnimator: _p.r(7), + Timeline: _p.r(8), + TranslateAnimator: _p.r(9), + PathAnimator: _p.r(5), + MotionAnimator: _p.r(3), + requestFrame: _p.r(2).requestFrame, + releaseFrame: _p.r(2).releaseFrame, + // filter + Filter: _p.r(20), + GaussianblurFilter: _p.r(21), + ProjectionFilter: _p.r(22), + // effect + ColorMatrixEffect: _p.r(13), + CompositeEffect: _p.r(14), + ConvolveMatrixEffect: _p.r(15), + Effect: _p.r(16), + GaussianblurEffect: _p.r(17), + OffsetEffect: _p.r(18) + }); + return window.kity = kity; + } +}; + +var moduleMapping = { + kity: 76 +}; + +function use(name) { + _p.r([ moduleMapping[name] ]); +} +/* global use, inc: true */ + +/** + * 模块暴露 + */ +use('kity'); +})(); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/loading.gif b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..5bb90fd6a49107a321c35b9cee4a7b810314b51f Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/loading.gif differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_BB.woff b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_BB.woff new file mode 100644 index 0000000000000000000000000000000000000000..51b3cce0cca2aef11b35d287a0077f65bf42cb26 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_BB.woff differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_CAL.woff b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_CAL.woff new file mode 100644 index 0000000000000000000000000000000000000000..f433b03af6a9396146bc669df2a4f74c58b6e61a Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_CAL.woff differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_FRAK.woff b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_FRAK.woff new file mode 100644 index 0000000000000000000000000000000000000000..9c7e9d68e6d48f0e1d67c77d62af1d485cfbeff4 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_FRAK.woff differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_MAIN.woff b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_MAIN.woff new file mode 100644 index 0000000000000000000000000000000000000000..ed93f8e84f307c523934cfea59c18569ec257e4b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_MAIN.woff differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_ROMAN.woff b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_ROMAN.woff new file mode 100644 index 0000000000000000000000000000000000000000..6b5d474dffe13e550788a56ebe4d3f8245388215 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/kityformula/resource/KF_AMS_ROMAN.woff differ diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..9b74d606efa311f760624889eb95bca86ac21006 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/plugin.js @@ -0,0 +1,72 @@ +tinymce.PluginManager.add('kityformula-editor', function(editor, url) { + + var baseURL = tinymce.baseURL+'/plugins/kityformula-editor/kityFormula.html'; + + editor.on('dblclick',function(){ + var sel=editor.selection.getContent(); + var path=/\/g; + var path2=/data-latex="(.*?)"/g; + + if(sel.search(path)==0){ + sel.replace(path2,function($0,$1){ + var param=encodeURIComponent($1); + openDialog(param); + return $0; + }); + }; + }); + + var openDialog = function(param) { + return editor.windowManager.openUrl({ + title: '插入公式', + size: 'large', + width: 785, + height: 475, + url:param?baseURL+"?c="+param:baseURL, + buttons: [ + { + type: 'cancel', + text: 'Close' + }, + { + type: 'custom', + text: 'Save', + name: 'save', + primary: true + }, + ], + onAction: function (api, details) { + switch (details.name) { + case 'save': + api.sendMessage("save"); + break; + default: + break; + }; + } + }); + }; + + + editor.ui.registry.addButton('kityformula-editor', { + text: '公式', + tooltip: '插入公式', + onAction: function() { + openDialog(); + } + }); + editor.ui.registry.addMenuItem('kityformula-editor', { + text: '公式', + onAction: function() { + openDialog(); + } + }); + return { + getMetadata: function() { + return { + name: "公式", + url: "http://hgcserver.gitee.io", + }; + } + }; +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..9b74d606efa311f760624889eb95bca86ac21006 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/kityformula-editor/plugin.min.js @@ -0,0 +1,72 @@ +tinymce.PluginManager.add('kityformula-editor', function(editor, url) { + + var baseURL = tinymce.baseURL+'/plugins/kityformula-editor/kityFormula.html'; + + editor.on('dblclick',function(){ + var sel=editor.selection.getContent(); + var path=/\/g; + var path2=/data-latex="(.*?)"/g; + + if(sel.search(path)==0){ + sel.replace(path2,function($0,$1){ + var param=encodeURIComponent($1); + openDialog(param); + return $0; + }); + }; + }); + + var openDialog = function(param) { + return editor.windowManager.openUrl({ + title: '插入公式', + size: 'large', + width: 785, + height: 475, + url:param?baseURL+"?c="+param:baseURL, + buttons: [ + { + type: 'cancel', + text: 'Close' + }, + { + type: 'custom', + text: 'Save', + name: 'save', + primary: true + }, + ], + onAction: function (api, details) { + switch (details.name) { + case 'save': + api.sendMessage("save"); + break; + default: + break; + }; + } + }); + }; + + + editor.ui.registry.addButton('kityformula-editor', { + text: '公式', + tooltip: '插入公式', + onAction: function() { + openDialog(); + } + }); + editor.ui.registry.addMenuItem('kityformula-editor', { + text: '公式', + onAction: function() { + openDialog(); + } + }); + return { + getMetadata: function() { + return { + name: "公式", + url: "http://hgcserver.gitee.io", + }; + } + }; +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/legacyoutput/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/legacyoutput/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..d96f337f93feb3fc0022c6aa8d3beb80a3326585 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/legacyoutput/plugin.js @@ -0,0 +1,199 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var getFontSizeFormats = function (editor) { + return editor.getParam('fontsize_formats'); + }; + var setFontSizeFormats = function (editor, fontsize_formats) { + editor.settings.fontsize_formats = fontsize_formats; + }; + var getFontFormats = function (editor) { + return editor.getParam('font_formats'); + }; + var setFontFormats = function (editor, font_formats) { + editor.settings.font_formats = font_formats; + }; + var getFontSizeStyleValues = function (editor) { + return editor.getParam('font_size_style_values', 'xx-small,x-small,small,medium,large,x-large,xx-large'); + }; + var setInlineStyles = function (editor, inline_styles) { + editor.settings.inline_styles = inline_styles; + }; + + var overrideFormats = function (editor) { + var alignElements = 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table', fontSizes = global$1.explode(getFontSizeStyleValues(editor)), schema = editor.schema; + editor.formatter.register({ + alignleft: { + selector: alignElements, + attributes: { align: 'left' } + }, + aligncenter: { + selector: alignElements, + attributes: { align: 'center' } + }, + alignright: { + selector: alignElements, + attributes: { align: 'right' } + }, + alignjustify: { + selector: alignElements, + attributes: { align: 'justify' } + }, + bold: [ + { + inline: 'b', + remove: 'all', + preserve_attributes: [ + 'class', + 'style' + ] + }, + { + inline: 'strong', + remove: 'all', + preserve_attributes: [ + 'class', + 'style' + ] + }, + { + inline: 'span', + styles: { fontWeight: 'bold' } + } + ], + italic: [ + { + inline: 'i', + remove: 'all', + preserve_attributes: [ + 'class', + 'style' + ] + }, + { + inline: 'em', + remove: 'all', + preserve_attributes: [ + 'class', + 'style' + ] + }, + { + inline: 'span', + styles: { fontStyle: 'italic' } + } + ], + underline: [ + { + inline: 'u', + remove: 'all', + preserve_attributes: [ + 'class', + 'style' + ] + }, + { + inline: 'span', + styles: { textDecoration: 'underline' }, + exact: true + } + ], + strikethrough: [ + { + inline: 'strike', + remove: 'all', + preserve_attributes: [ + 'class', + 'style' + ] + }, + { + inline: 'span', + styles: { textDecoration: 'line-through' }, + exact: true + } + ], + fontname: { + inline: 'font', + toggle: false, + attributes: { face: '%value' } + }, + fontsize: { + inline: 'font', + toggle: false, + attributes: { + size: function (vars) { + return String(global$1.inArray(fontSizes, vars.value) + 1); + } + } + }, + forecolor: { + inline: 'font', + attributes: { color: '%value' }, + links: true, + remove_similar: true, + clear_child_styles: true + }, + hilitecolor: { + inline: 'font', + styles: { backgroundColor: '%value' }, + links: true, + remove_similar: true, + clear_child_styles: true + } + }); + global$1.each('b,i,u,strike'.split(','), function (name) { + schema.addValidElements(name + '[*]'); + }); + if (!schema.getElementRule('font')) { + schema.addValidElements('font[face|size|color|style]'); + } + global$1.each(alignElements.split(','), function (name) { + var rule = schema.getElementRule(name); + if (rule) { + if (!rule.attributes.align) { + rule.attributes.align = {}; + rule.attributesOrder.push('align'); + } + } + }); + }; + var overrideSettings = function (editor) { + var defaultFontsizeFormats = '8pt=1 10pt=2 12pt=3 14pt=4 18pt=5 24pt=6 36pt=7'; + var defaultFontsFormats = 'Andale Mono=andale mono,monospace;' + 'Arial=arial,helvetica,sans-serif;' + 'Arial Black=arial black,sans-serif;' + 'Book Antiqua=book antiqua,palatino,serif;' + 'Comic Sans MS=comic sans ms,sans-serif;' + 'Courier New=courier new,courier,monospace;' + 'Georgia=georgia,palatino,serif;' + 'Helvetica=helvetica,arial,sans-serif;' + 'Impact=impact,sans-serif;' + 'Symbol=symbol;' + 'Tahoma=tahoma,arial,helvetica,sans-serif;' + 'Terminal=terminal,monaco,monospace;' + 'Times New Roman=times new roman,times,serif;' + 'Trebuchet MS=trebuchet ms,geneva,sans-serif;' + 'Verdana=verdana,geneva,sans-serif;' + 'Webdings=webdings;' + 'Wingdings=wingdings,zapf dingbats'; + setInlineStyles(editor, false); + if (!getFontSizeFormats(editor)) { + setFontSizeFormats(editor, defaultFontsizeFormats); + } + if (!getFontFormats(editor)) { + setFontFormats(editor, defaultFontsFormats); + } + }; + var setup = function (editor) { + overrideSettings(editor); + editor.on('PreInit', function () { + return overrideFormats(editor); + }); + }; + + function Plugin () { + global.add('legacyoutput', function (editor) { + setup(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/legacyoutput/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/legacyoutput/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..c2b04c1e0189c581f1ab8ab926926bd89763e9b5 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/legacyoutput/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),l=tinymce.util.Tools.resolve("tinymce.util.Tools"),t=function(s){var e,t,i,a;t=!1,(e=s).settings.inline_styles=t,e.getParam("fontsize_formats")||(i="8pt=1 10pt=2 12pt=3 14pt=4 18pt=5 24pt=6 36pt=7",e.settings.fontsize_formats=i),e.getParam("font_formats")||(a="Andale Mono=andale mono,monospace;Arial=arial,helvetica,sans-serif;Arial Black=arial black,sans-serif;Book Antiqua=book antiqua,palatino,serif;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,palatino,serif;Helvetica=helvetica,arial,sans-serif;Impact=impact,sans-serif;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco,monospace;Times New Roman=times new roman,times,serif;Trebuchet MS=trebuchet ms,geneva,sans-serif;Verdana=verdana,geneva,sans-serif;Webdings=webdings;Wingdings=wingdings,zapf dingbats",e.settings.font_formats=a),s.on("PreInit",function(){return e=s,t="p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table",i=l.explode(e.getParam("font_size_style_values","xx-small,x-small,small,medium,large,x-large,xx-large")),a=e.schema,e.formatter.register({alignleft:{selector:t,attributes:{align:"left"}},aligncenter:{selector:t,attributes:{align:"center"}},alignright:{selector:t,attributes:{align:"right"}},alignjustify:{selector:t,attributes:{align:"justify"}},bold:[{inline:"b",remove:"all",preserve_attributes:["class","style"]},{inline:"strong",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{fontWeight:"bold"}}],italic:[{inline:"i",remove:"all",preserve_attributes:["class","style"]},{inline:"em",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{fontStyle:"italic"}}],underline:[{inline:"u",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{textDecoration:"underline"},exact:!0}],strikethrough:[{inline:"strike",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{textDecoration:"line-through"},exact:!0}],fontname:{inline:"font",toggle:!1,attributes:{face:"%value"}},fontsize:{inline:"font",toggle:!1,attributes:{size:function(e){return String(l.inArray(i,e.value)+1)}}},forecolor:{inline:"font",attributes:{color:"%value"},links:!0,remove_similar:!0,clear_child_styles:!0},hilitecolor:{inline:"font",styles:{backgroundColor:"%value"},links:!0,remove_similar:!0,clear_child_styles:!0}}),l.each("b,i,u,strike".split(","),function(e){a.addValidElements(e+"[*]")}),a.getElementRule("font")||a.addValidElements("font[face|size|color|style]"),void l.each(t.split(","),function(e){var t=a.getElementRule(e);t&&(t.attributes.align||(t.attributes.align={},t.attributesOrder.push("align")))});var e,t,i,a})};e.add("legacyoutput",function(e){t(e)})}(); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/link/plugin.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/link/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..a5cc018dd66072c52593bb14c0c28e6b25ff2f2f --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/link/plugin.js @@ -0,0 +1,1290 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.VK'); + + var typeOf = function (x) { + var t = typeof x; + if (x === null) { + return 'null'; + } else if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { + return 'array'; + } else if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { + return 'string'; + } else { + return t; + } + }; + var isType = function (type) { + return function (value) { + return typeOf(value) === type; + }; + }; + var isSimpleType = function (type) { + return function (value) { + return typeof value === type; + }; + }; + var eq = function (t) { + return function (a) { + return t === a; + }; + }; + var isString = isType('string'); + var isArray = isType('array'); + var isNull = eq(null); + var isBoolean = isSimpleType('boolean'); + var isFunction = isSimpleType('function'); + + var assumeExternalTargets = function (editor) { + var externalTargets = editor.getParam('link_assume_external_targets', false); + if (isBoolean(externalTargets) && externalTargets) { + return 1; + } else if (isString(externalTargets) && (externalTargets === 'http' || externalTargets === 'https')) { + return externalTargets; + } + return 0; + }; + var hasContextToolbar = function (editor) { + return editor.getParam('link_context_toolbar', false, 'boolean'); + }; + var getLinkList = function (editor) { + return editor.getParam('link_list'); + }; + var getDefaultLinkTarget = function (editor) { + return editor.getParam('default_link_target'); + }; + var getTargetList = function (editor) { + return editor.getParam('target_list', true); + }; + var getRelList = function (editor) { + return editor.getParam('rel_list', [], 'array'); + }; + var getLinkClassList = function (editor) { + return editor.getParam('link_class_list', [], 'array'); + }; + var shouldShowLinkTitle = function (editor) { + return editor.getParam('link_title', true, 'boolean'); + }; + var allowUnsafeLinkTarget = function (editor) { + return editor.getParam('allow_unsafe_link_target', false, 'boolean'); + }; + var useQuickLink = function (editor) { + return editor.getParam('link_quicklink', false, 'boolean'); + }; + var getDefaultLinkProtocol = function (editor) { + return editor.getParam('link_default_protocol', 'http', 'string'); + }; + + var noop = function () { + }; + var constant = function (value) { + return function () { + return value; + }; + }; + var never = constant(false); + var always = constant(true); + + var none = function () { + return NONE; + }; + var NONE = function () { + var eq = function (o) { + return o.isNone(); + }; + var call = function (thunk) { + return thunk(); + }; + var id = function (n) { + return n; + }; + var me = { + fold: function (n, _s) { + return n(); + }, + is: never, + isSome: never, + isNone: always, + getOr: id, + getOrThunk: call, + getOrDie: function (msg) { + throw new Error(msg || 'error: getOrDie called on none.'); + }, + getOrNull: constant(null), + getOrUndefined: constant(undefined), + or: id, + orThunk: call, + map: none, + each: noop, + bind: none, + exists: never, + forall: always, + filter: none, + equals: eq, + equals_: eq, + toArray: function () { + return []; + }, + toString: constant('none()') + }; + return me; + }(); + var some = function (a) { + var constant_a = constant(a); + var self = function () { + return me; + }; + var bind = function (f) { + return f(a); + }; + var me = { + fold: function (n, s) { + return s(a); + }, + is: function (v) { + return a === v; + }, + isSome: always, + isNone: never, + getOr: constant_a, + getOrThunk: constant_a, + getOrDie: constant_a, + getOrNull: constant_a, + getOrUndefined: constant_a, + or: self, + orThunk: self, + map: function (f) { + return some(f(a)); + }, + each: function (f) { + f(a); + }, + bind: bind, + exists: bind, + forall: bind, + filter: function (f) { + return f(a) ? me : NONE; + }, + toArray: function () { + return [a]; + }, + toString: function () { + return 'some(' + a + ')'; + }, + equals: function (o) { + return o.is(a); + }, + equals_: function (o, elementEq) { + return o.fold(never, function (b) { + return elementEq(a, b); + }); + } + }; + return me; + }; + var from = function (value) { + return value === null || value === undefined ? NONE : some(value); + }; + var Optional = { + some: some, + none: none, + from: from + }; + + var nativeIndexOf = Array.prototype.indexOf; + var nativePush = Array.prototype.push; + var rawIndexOf = function (ts, t) { + return nativeIndexOf.call(ts, t); + }; + var contains = function (xs, x) { + return rawIndexOf(xs, x) > -1; + }; + var map = function (xs, f) { + var len = xs.length; + var r = new Array(len); + for (var i = 0; i < len; i++) { + var x = xs[i]; + r[i] = f(x, i); + } + return r; + }; + var each = function (xs, f) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + f(x, i); + } + }; + var foldl = function (xs, f, acc) { + each(xs, function (x) { + acc = f(acc, x); + }); + return acc; + }; + var flatten = function (xs) { + var r = []; + for (var i = 0, len = xs.length; i < len; ++i) { + if (!isArray(xs[i])) { + throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs); + } + nativePush.apply(r, xs[i]); + } + return r; + }; + var bind = function (xs, f) { + return flatten(map(xs, f)); + }; + var findMap = function (arr, f) { + for (var i = 0; i < arr.length; i++) { + var r = f(arr[i], i); + if (r.isSome()) { + return r; + } + } + return Optional.none(); + }; + + var cat = function (arr) { + var r = []; + var push = function (x) { + r.push(x); + }; + for (var i = 0; i < arr.length; i++) { + arr[i].each(push); + } + return r; + }; + var someIf = function (b, a) { + return b ? Optional.some(a) : Optional.none(); + }; + + var global$2 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var getValue = function (item) { + return isString(item.value) ? item.value : ''; + }; + var getText = function (item) { + if (isString(item.text)) { + return item.text; + } else if (isString(item.title)) { + return item.title; + } else { + return ''; + } + }; + var sanitizeList = function (list, extractValue) { + var out = []; + global$2.each(list, function (item) { + var text = getText(item); + if (item.menu !== undefined) { + var items = sanitizeList(item.menu, extractValue); + out.push({ + text: text, + items: items + }); + } else { + var value = extractValue(item); + out.push({ + text: text, + value: value + }); + } + }); + return out; + }; + var sanitizeWith = function (extracter) { + if (extracter === void 0) { + extracter = getValue; + } + return function (list) { + return Optional.from(list).map(function (list) { + return sanitizeList(list, extracter); + }); + }; + }; + var sanitize = function (list) { + return sanitizeWith(getValue)(list); + }; + var createUi = function (name, label) { + return function (items) { + return { + name: name, + type: 'listbox', + label: label, + items: items + }; + }; + }; + var ListOptions = { + sanitize: sanitize, + sanitizeWith: sanitizeWith, + createUi: createUi, + getValue: getValue + }; + + var __assign = function () { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + var keys = Object.keys; + var hasOwnProperty = Object.hasOwnProperty; + var each$1 = function (obj, f) { + var props = keys(obj); + for (var k = 0, len = props.length; k < len; k++) { + var i = props[k]; + var x = obj[i]; + f(x, i); + } + }; + var objAcc = function (r) { + return function (x, i) { + r[i] = x; + }; + }; + var internalFilter = function (obj, pred, onTrue, onFalse) { + var r = {}; + each$1(obj, function (x, i) { + (pred(x, i) ? onTrue : onFalse)(x, i); + }); + return r; + }; + var filter = function (obj, pred) { + var t = {}; + internalFilter(obj, pred, objAcc(t), noop); + return t; + }; + var has = function (obj, key) { + return hasOwnProperty.call(obj, key); + }; + var hasNonNullableKey = function (obj, key) { + return has(obj, key) && obj[key] !== undefined && obj[key] !== null; + }; + + var global$3 = tinymce.util.Tools.resolve('tinymce.dom.TreeWalker'); + + var isAnchor = function (elm) { + return elm && elm.nodeName.toLowerCase() === 'a'; + }; + var isLink = function (elm) { + return isAnchor(elm) && !!getHref(elm); + }; + var collectNodesInRange = function (rng, predicate) { + if (rng.collapsed) { + return []; + } else { + var contents = rng.cloneContents(); + var walker = new global$3(contents.firstChild, contents); + var elements = []; + var current = contents.firstChild; + do { + if (predicate(current)) { + elements.push(current); + } + } while (current = walker.next()); + return elements; + } + }; + var hasProtocol = function (url) { + return /^\w+:/i.test(url); + }; + var getHref = function (elm) { + var href = elm.getAttribute('data-mce-href'); + return href ? href : elm.getAttribute('href'); + }; + var applyRelTargetRules = function (rel, isUnsafe) { + var rules = ['noopener']; + var rels = rel ? rel.split(/\s+/) : []; + var toString = function (rels) { + return global$2.trim(rels.sort().join(' ')); + }; + var addTargetRules = function (rels) { + rels = removeTargetRules(rels); + return rels.length > 0 ? rels.concat(rules) : rules; + }; + var removeTargetRules = function (rels) { + return rels.filter(function (val) { + return global$2.inArray(rules, val) === -1; + }); + }; + var newRels = isUnsafe ? addTargetRules(rels) : removeTargetRules(rels); + return newRels.length > 0 ? toString(newRels) : ''; + }; + var trimCaretContainers = function (text) { + return text.replace(/\uFEFF/g, ''); + }; + var getAnchorElement = function (editor, selectedElm) { + selectedElm = selectedElm || editor.selection.getNode(); + if (isImageFigure(selectedElm)) { + return editor.dom.select('a[href]', selectedElm)[0]; + } else { + return editor.dom.getParent(selectedElm, 'a[href]'); + } + }; + var getAnchorText = function (selection, anchorElm) { + var text = anchorElm ? anchorElm.innerText || anchorElm.textContent : selection.getContent({ format: 'text' }); + return trimCaretContainers(text); + }; + var hasLinks = function (elements) { + return global$2.grep(elements, isLink).length > 0; + }; + var hasLinksInSelection = function (rng) { + return collectNodesInRange(rng, isLink).length > 0; + }; + var isOnlyTextSelected = function (editor) { + var inlineTextElements = editor.schema.getTextInlineElements(); + var isElement = function (elm) { + return elm.nodeType === 1 && !isAnchor(elm) && !has(inlineTextElements, elm.nodeName.toLowerCase()); + }; + var elements = collectNodesInRange(editor.selection.getRng(), isElement); + return elements.length === 0; + }; + var isImageFigure = function (elm) { + return elm && elm.nodeName === 'FIGURE' && /\bimage\b/i.test(elm.className); + }; + var getLinkAttrs = function (data) { + return foldl([ + 'title', + 'rel', + 'class', + 'target' + ], function (acc, key) { + data[key].each(function (value) { + acc[key] = value.length > 0 ? value : null; + }); + return acc; + }, { href: data.href }); + }; + var handleExternalTargets = function (href, assumeExternalTargets) { + if ((assumeExternalTargets === 'http' || assumeExternalTargets === 'https') && !hasProtocol(href)) { + return assumeExternalTargets + '://' + href; + } + return href; + }; + var applyLinkOverrides = function (editor, linkAttrs) { + var newLinkAttrs = __assign({}, linkAttrs); + if (!(getRelList(editor).length > 0) && allowUnsafeLinkTarget(editor) === false) { + var newRel = applyRelTargetRules(newLinkAttrs.rel, newLinkAttrs.target === '_blank'); + newLinkAttrs.rel = newRel ? newRel : null; + } + if (Optional.from(newLinkAttrs.target).isNone() && getTargetList(editor) === false) { + newLinkAttrs.target = getDefaultLinkTarget(editor); + } + newLinkAttrs.href = handleExternalTargets(newLinkAttrs.href, assumeExternalTargets(editor)); + return newLinkAttrs; + }; + var updateLink = function (editor, anchorElm, text, linkAttrs) { + text.each(function (text) { + if (anchorElm.hasOwnProperty('innerText')) { + anchorElm.innerText = text; + } else { + anchorElm.textContent = text; + } + }); + editor.dom.setAttribs(anchorElm, linkAttrs); + editor.selection.select(anchorElm); + }; + var createLink = function (editor, selectedElm, text, linkAttrs) { + if (isImageFigure(selectedElm)) { + linkImageFigure(editor, selectedElm, linkAttrs); + } else { + text.fold(function () { + editor.execCommand('mceInsertLink', false, linkAttrs); + }, function (text) { + editor.insertContent(editor.dom.createHTML('a', linkAttrs, editor.dom.encode(text))); + }); + } + }; + var linkDomMutation = function (editor, attachState, data) { + var selectedElm = editor.selection.getNode(); + var anchorElm = getAnchorElement(editor, selectedElm); + var linkAttrs = applyLinkOverrides(editor, getLinkAttrs(data)); + editor.undoManager.transact(function () { + if (data.href === attachState.href) { + attachState.attach(); + } + if (anchorElm) { + editor.focus(); + updateLink(editor, anchorElm, data.text, linkAttrs); + } else { + createLink(editor, selectedElm, data.text, linkAttrs); + } + }); + }; + var unlinkSelection = function (editor) { + var dom = editor.dom, selection = editor.selection; + var bookmark = selection.getBookmark(); + var rng = selection.getRng().cloneRange(); + var startAnchorElm = dom.getParent(rng.startContainer, 'a[href]', editor.getBody()); + var endAnchorElm = dom.getParent(rng.endContainer, 'a[href]', editor.getBody()); + if (startAnchorElm) { + rng.setStartBefore(startAnchorElm); + } + if (endAnchorElm) { + rng.setEndAfter(endAnchorElm); + } + selection.setRng(rng); + editor.execCommand('unlink'); + selection.moveToBookmark(bookmark); + }; + var unlinkDomMutation = function (editor) { + editor.undoManager.transact(function () { + var node = editor.selection.getNode(); + if (isImageFigure(node)) { + unlinkImageFigure(editor, node); + } else { + unlinkSelection(editor); + } + editor.focus(); + }); + }; + var unwrapOptions = function (data) { + var cls = data.class, href = data.href, rel = data.rel, target = data.target, text = data.text, title = data.title; + return filter({ + class: cls.getOrNull(), + href: href, + rel: rel.getOrNull(), + target: target.getOrNull(), + text: text.getOrNull(), + title: title.getOrNull() + }, function (v, _k) { + return isNull(v) === false; + }); + }; + var link = function (editor, attachState, data) { + editor.hasPlugin('rtc', true) ? editor.execCommand('createlink', false, unwrapOptions(data)) : linkDomMutation(editor, attachState, data); + }; + var unlink = function (editor) { + editor.hasPlugin('rtc', true) ? editor.execCommand('unlink') : unlinkDomMutation(editor); + }; + var unlinkImageFigure = function (editor, fig) { + var img = editor.dom.select('img', fig)[0]; + if (img) { + var a = editor.dom.getParents(img, 'a[href]', fig)[0]; + if (a) { + a.parentNode.insertBefore(img, a); + editor.dom.remove(a); + } + } + }; + var linkImageFigure = function (editor, fig, attrs) { + var img = editor.dom.select('img', fig)[0]; + if (img) { + var a = editor.dom.create('a', attrs); + img.parentNode.insertBefore(a, img); + a.appendChild(img); + } + }; + + var isListGroup = function (item) { + return hasNonNullableKey(item, 'items'); + }; + var findTextByValue = function (value, catalog) { + return findMap(catalog, function (item) { + if (isListGroup(item)) { + return findTextByValue(value, item.items); + } else { + return someIf(item.value === value, item); + } + }); + }; + var getDelta = function (persistentText, fieldName, catalog, data) { + var value = data[fieldName]; + var hasPersistentText = persistentText.length > 0; + return value !== undefined ? findTextByValue(value, catalog).map(function (i) { + return { + url: { + value: i.value, + meta: { + text: hasPersistentText ? persistentText : i.text, + attach: noop + } + }, + text: hasPersistentText ? persistentText : i.text + }; + }) : Optional.none(); + }; + var findCatalog = function (catalogs, fieldName) { + if (fieldName === 'link') { + return catalogs.link; + } else if (fieldName === 'anchor') { + return catalogs.anchor; + } else { + return Optional.none(); + } + }; + var init = function (initialData, linkCatalog) { + var persistentData = { + text: initialData.text, + title: initialData.title + }; + var getTitleFromUrlChange = function (url) { + return someIf(persistentData.title.length <= 0, Optional.from(url.meta.title).getOr('')); + }; + var getTextFromUrlChange = function (url) { + return someIf(persistentData.text.length <= 0, Optional.from(url.meta.text).getOr(url.value)); + }; + var onUrlChange = function (data) { + var text = getTextFromUrlChange(data.url); + var title = getTitleFromUrlChange(data.url); + if (text.isSome() || title.isSome()) { + return Optional.some(__assign(__assign({}, text.map(function (text) { + return { text: text }; + }).getOr({})), title.map(function (title) { + return { title: title }; + }).getOr({}))); + } else { + return Optional.none(); + } + }; + var onCatalogChange = function (data, change) { + var catalog = findCatalog(linkCatalog, change.name).getOr([]); + return getDelta(persistentData.text, change.name, catalog, data); + }; + var onChange = function (getData, change) { + var name = change.name; + if (name === 'url') { + return onUrlChange(getData()); + } else if (contains([ + 'anchor', + 'link' + ], name)) { + return onCatalogChange(getData(), change); + } else if (name === 'text' || name === 'title') { + persistentData[name] = getData()[name]; + return Optional.none(); + } else { + return Optional.none(); + } + }; + return { onChange: onChange }; + }; + var DialogChanges = { + init: init, + getDelta: getDelta + }; + + var global$4 = tinymce.util.Tools.resolve('tinymce.util.Delay'); + + var global$5 = tinymce.util.Tools.resolve('tinymce.util.Promise'); + + var delayedConfirm = function (editor, message, callback) { + var rng = editor.selection.getRng(); + global$4.setEditorTimeout(editor, function () { + editor.windowManager.confirm(message, function (state) { + editor.selection.setRng(rng); + callback(state); + }); + }); + }; + var tryEmailTransform = function (data) { + var url = data.href; + var suggestMailTo = url.indexOf('@') > 0 && url.indexOf('/') === -1 && url.indexOf('mailto:') === -1; + return suggestMailTo ? Optional.some({ + message: 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?', + preprocess: function (oldData) { + return __assign(__assign({}, oldData), { href: 'mailto:' + url }); + } + }) : Optional.none(); + }; + var tryProtocolTransform = function (assumeExternalTargets, defaultLinkProtocol) { + return function (data) { + var url = data.href; + var suggestProtocol = assumeExternalTargets === 1 && !hasProtocol(url) || assumeExternalTargets === 0 && /^\s*www(\.|\d\.)/i.test(url); + return suggestProtocol ? Optional.some({ + message: 'The URL you entered seems to be an external link. Do you want to add the required ' + defaultLinkProtocol + ':// prefix?', + preprocess: function (oldData) { + return __assign(__assign({}, oldData), { href: defaultLinkProtocol + '://' + url }); + } + }) : Optional.none(); + }; + }; + var preprocess = function (editor, data) { + return findMap([ + tryEmailTransform, + tryProtocolTransform(assumeExternalTargets(editor), getDefaultLinkProtocol(editor)) + ], function (f) { + return f(data); + }).fold(function () { + return global$5.resolve(data); + }, function (transform) { + return new global$5(function (callback) { + delayedConfirm(editor, transform.message, function (state) { + callback(state ? transform.preprocess(data) : data); + }); + }); + }); + }; + var DialogConfirms = { preprocess: preprocess }; + + var getAnchors = function (editor) { + var anchorNodes = editor.dom.select('a:not([href])'); + var anchors = bind(anchorNodes, function (anchor) { + var id = anchor.name || anchor.id; + return id ? [{ + text: id, + value: '#' + id + }] : []; + }); + return anchors.length > 0 ? Optional.some([{ + text: 'None', + value: '' + }].concat(anchors)) : Optional.none(); + }; + var AnchorListOptions = { getAnchors: getAnchors }; + + var getClasses = function (editor) { + var list = getLinkClassList(editor); + if (list.length > 0) { + return ListOptions.sanitize(list); + } + return Optional.none(); + }; + var ClassListOptions = { getClasses: getClasses }; + + var global$6 = tinymce.util.Tools.resolve('tinymce.util.XHR'); + + var parseJson = function (text) { + try { + return Optional.some(JSON.parse(text)); + } catch (err) { + return Optional.none(); + } + }; + var getLinks = function (editor) { + var extractor = function (item) { + return editor.convertURL(item.value || item.url, 'href'); + }; + var linkList = getLinkList(editor); + return new global$5(function (callback) { + if (isString(linkList)) { + global$6.send({ + url: linkList, + success: function (text) { + return callback(parseJson(text)); + }, + error: function (_) { + return callback(Optional.none()); + } + }); + } else if (isFunction(linkList)) { + linkList(function (output) { + return callback(Optional.some(output)); + }); + } else { + callback(Optional.from(linkList)); + } + }).then(function (optItems) { + return optItems.bind(ListOptions.sanitizeWith(extractor)).map(function (items) { + if (items.length > 0) { + var noneItem = [{ + text: 'None', + value: '' + }]; + return noneItem.concat(items); + } else { + return items; + } + }); + }); + }; + var LinkListOptions = { getLinks: getLinks }; + + var getRels = function (editor, initialTarget) { + var list = getRelList(editor); + if (list.length > 0) { + var isTargetBlank_1 = initialTarget.is('_blank'); + var enforceSafe = allowUnsafeLinkTarget(editor) === false; + var safeRelExtractor = function (item) { + return applyRelTargetRules(ListOptions.getValue(item), isTargetBlank_1); + }; + var sanitizer = enforceSafe ? ListOptions.sanitizeWith(safeRelExtractor) : ListOptions.sanitize; + return sanitizer(list); + } + return Optional.none(); + }; + var RelOptions = { getRels: getRels }; + + var fallbacks = [ + { + text: 'Current window', + value: '' + }, + { + text: 'New window', + value: '_blank' + } + ]; + var getTargets = function (editor) { + var list = getTargetList(editor); + if (isArray(list)) { + return ListOptions.sanitize(list).orThunk(function () { + return Optional.some(fallbacks); + }); + } else if (list === false) { + return Optional.none(); + } + return Optional.some(fallbacks); + }; + var TargetOptions = { getTargets: getTargets }; + + var nonEmptyAttr = function (dom, elem, name) { + var val = dom.getAttrib(elem, name); + return val !== null && val.length > 0 ? Optional.some(val) : Optional.none(); + }; + var extractFromAnchor = function (editor, anchor) { + var dom = editor.dom; + var onlyText = isOnlyTextSelected(editor); + var text = onlyText ? Optional.some(getAnchorText(editor.selection, anchor)) : Optional.none(); + var url = anchor ? Optional.some(dom.getAttrib(anchor, 'href')) : Optional.none(); + var target = anchor ? Optional.from(dom.getAttrib(anchor, 'target')) : Optional.none(); + var rel = nonEmptyAttr(dom, anchor, 'rel'); + var linkClass = nonEmptyAttr(dom, anchor, 'class'); + var title = nonEmptyAttr(dom, anchor, 'title'); + return { + url: url, + text: text, + title: title, + target: target, + rel: rel, + linkClass: linkClass + }; + }; + var collect = function (editor, linkNode) { + return LinkListOptions.getLinks(editor).then(function (links) { + var anchor = extractFromAnchor(editor, linkNode); + return { + anchor: anchor, + catalogs: { + targets: TargetOptions.getTargets(editor), + rels: RelOptions.getRels(editor, anchor.target), + classes: ClassListOptions.getClasses(editor), + anchor: AnchorListOptions.getAnchors(editor), + link: links + }, + optNode: Optional.from(linkNode), + flags: { titleEnabled: shouldShowLinkTitle(editor) } + }; + }); + }; + var DialogInfo = { collect: collect }; + + var handleSubmit = function (editor, info) { + return function (api) { + var data = api.getData(); + if (!data.url.value) { + unlink(editor); + api.close(); + return; + } + var getChangedValue = function (key) { + return Optional.from(data[key]).filter(function (value) { + return !info.anchor[key].is(value); + }); + }; + var changedData = { + href: data.url.value, + text: getChangedValue('text'), + target: getChangedValue('target'), + rel: getChangedValue('rel'), + class: getChangedValue('linkClass'), + title: getChangedValue('title') + }; + var attachState = { + href: data.url.value, + attach: data.url.meta !== undefined && data.url.meta.attach ? data.url.meta.attach : function () { + } + }; + DialogConfirms.preprocess(editor, changedData).then(function (pData) { + link(editor, attachState, pData); + }); + api.close(); + }; + }; + var collectData = function (editor) { + var anchorNode = getAnchorElement(editor); + return DialogInfo.collect(editor, anchorNode); + }; + var getInitialData = function (info, defaultTarget) { + var anchor = info.anchor; + var url = anchor.url.getOr(''); + return { + url: { + value: url, + meta: { original: { value: url } } + }, + text: anchor.text.getOr(''), + title: anchor.title.getOr(''), + anchor: url, + link: url, + rel: anchor.rel.getOr(''), + target: anchor.target.or(defaultTarget).getOr(''), + linkClass: anchor.linkClass.getOr('') + }; + }; + var makeDialog = function (settings, onSubmit, editor) { + var urlInput = [{ + name: 'url', + type: 'urlinput', + filetype: 'file', + label: 'URL' + }]; + var displayText = settings.anchor.text.map(function () { + return { + name: 'text', + type: 'input', + label: 'Text to display' + }; + }).toArray(); + var titleText = settings.flags.titleEnabled ? [{ + name: 'title', + type: 'input', + label: 'Title' + }] : []; + var defaultTarget = Optional.from(getDefaultLinkTarget(editor)); + var initialData = getInitialData(settings, defaultTarget); + var catalogs = settings.catalogs; + var dialogDelta = DialogChanges.init(initialData, catalogs); + var body = { + type: 'panel', + items: flatten([ + urlInput, + displayText, + titleText, + cat([ + catalogs.anchor.map(ListOptions.createUi('anchor', 'Anchors')), + catalogs.rels.map(ListOptions.createUi('rel', 'Rel')), + catalogs.targets.map(ListOptions.createUi('target', 'Open link in...')), + catalogs.link.map(ListOptions.createUi('link', 'Link list')), + catalogs.classes.map(ListOptions.createUi('linkClass', 'Class')) + ]) + ]) + }; + return { + title: 'Insert/Edit Link', + size: 'normal', + body: body, + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true + } + ], + initialData: initialData, + onChange: function (api, _a) { + var name = _a.name; + dialogDelta.onChange(api.getData, { name: name }).each(function (newData) { + api.setData(newData); + }); + }, + onSubmit: onSubmit + }; + }; + var open = function (editor) { + var data = collectData(editor); + data.then(function (info) { + var onSubmit = handleSubmit(editor, info); + return makeDialog(info, onSubmit, editor); + }).then(function (spec) { + editor.windowManager.open(spec); + }); + }; + + var appendClickRemove = function (link, evt) { + document.body.appendChild(link); + link.dispatchEvent(evt); + document.body.removeChild(link); + }; + var open$1 = function (url) { + var link = document.createElement('a'); + link.target = '_blank'; + link.href = url; + link.rel = 'noreferrer noopener'; + var evt = document.createEvent('MouseEvents'); + evt.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + appendClickRemove(link, evt); + }; + + var getLink = function (editor, elm) { + return editor.dom.getParent(elm, 'a[href]'); + }; + var getSelectedLink = function (editor) { + return getLink(editor, editor.selection.getStart()); + }; + var hasOnlyAltModifier = function (e) { + return e.altKey === true && e.shiftKey === false && e.ctrlKey === false && e.metaKey === false; + }; + var gotoLink = function (editor, a) { + if (a) { + var href = getHref(a); + if (/^#/.test(href)) { + var targetEl = editor.$(href); + if (targetEl.length) { + editor.selection.scrollIntoView(targetEl[0], true); + } + } else { + open$1(a.href); + } + } + }; + var openDialog = function (editor) { + return function () { + open(editor); + }; + }; + var gotoSelectedLink = function (editor) { + return function () { + gotoLink(editor, getSelectedLink(editor)); + }; + }; + var setupGotoLinks = function (editor) { + editor.on('click', function (e) { + var link = getLink(editor, e.target); + if (link && global$1.metaKeyPressed(e)) { + e.preventDefault(); + gotoLink(editor, link); + } + }); + editor.on('keydown', function (e) { + var link = getSelectedLink(editor); + if (link && e.keyCode === 13 && hasOnlyAltModifier(e)) { + e.preventDefault(); + gotoLink(editor, link); + } + }); + }; + var toggleState = function (editor, toggler) { + editor.on('NodeChange', toggler); + return function () { + return editor.off('NodeChange', toggler); + }; + }; + var toggleActiveState = function (editor) { + return function (api) { + return toggleState(editor, function () { + api.setActive(!editor.mode.isReadOnly() && getAnchorElement(editor, editor.selection.getNode()) !== null); + }); + }; + }; + var toggleEnabledState = function (editor) { + return function (api) { + var updateState = function () { + return api.setDisabled(getAnchorElement(editor, editor.selection.getNode()) === null); + }; + updateState(); + return toggleState(editor, updateState); + }; + }; + var toggleUnlinkState = function (editor) { + return function (api) { + var hasLinks$1 = function (parents) { + return hasLinks(parents) || hasLinksInSelection(editor.selection.getRng()); + }; + var parents = editor.dom.getParents(editor.selection.getStart()); + api.setDisabled(!hasLinks$1(parents)); + return toggleState(editor, function (e) { + return api.setDisabled(!hasLinks$1(e.parents)); + }); + }; + }; + + var register = function (editor) { + editor.addCommand('mceLink', function () { + if (useQuickLink(editor)) { + editor.fire('contexttoolbar-show', { toolbarKey: 'quicklink' }); + } else { + openDialog(editor)(); + } + }); + }; + + var setup = function (editor) { + editor.addShortcut('Meta+K', '', function () { + editor.execCommand('mceLink'); + }); + }; + + var setupButtons = function (editor) { + editor.ui.registry.addToggleButton('link', { + icon: 'link', + tooltip: 'Insert/edit link', + onAction: openDialog(editor), + onSetup: toggleActiveState(editor) + }); + editor.ui.registry.addButton('openlink', { + icon: 'new-tab', + tooltip: 'Open link', + onAction: gotoSelectedLink(editor), + onSetup: toggleEnabledState(editor) + }); + editor.ui.registry.addButton('unlink', { + icon: 'unlink', + tooltip: 'Remove link', + onAction: function () { + return unlink(editor); + }, + onSetup: toggleUnlinkState(editor) + }); + }; + var setupMenuItems = function (editor) { + editor.ui.registry.addMenuItem('openlink', { + text: 'Open link', + icon: 'new-tab', + onAction: gotoSelectedLink(editor), + onSetup: toggleEnabledState(editor) + }); + editor.ui.registry.addMenuItem('link', { + icon: 'link', + text: 'Link...', + shortcut: 'Meta+K', + onAction: openDialog(editor) + }); + editor.ui.registry.addMenuItem('unlink', { + icon: 'unlink', + text: 'Remove link', + onAction: function () { + return unlink(editor); + }, + onSetup: toggleUnlinkState(editor) + }); + }; + var setupContextMenu = function (editor) { + var inLink = 'link unlink openlink'; + var noLink = 'link'; + editor.ui.registry.addContextMenu('link', { + update: function (element) { + return hasLinks(editor.dom.getParents(element, 'a')) ? inLink : noLink; + } + }); + }; + var setupContextToolbars = function (editor) { + var collapseSelectionToEnd = function (editor) { + editor.selection.collapse(false); + }; + var onSetupLink = function (buttonApi) { + var node = editor.selection.getNode(); + buttonApi.setDisabled(!getAnchorElement(editor, node)); + return function () { + }; + }; + editor.ui.registry.addContextForm('quicklink', { + launch: { + type: 'contextformtogglebutton', + icon: 'link', + tooltip: 'Link', + onSetup: toggleActiveState(editor) + }, + label: 'Link', + predicate: function (node) { + return !!getAnchorElement(editor, node) && hasContextToolbar(editor); + }, + initValue: function () { + var elm = getAnchorElement(editor); + return !!elm ? getHref(elm) : ''; + }, + commands: [ + { + type: 'contextformtogglebutton', + icon: 'link', + tooltip: 'Link', + primary: true, + onSetup: function (buttonApi) { + var node = editor.selection.getNode(); + buttonApi.setActive(!!getAnchorElement(editor, node)); + return toggleActiveState(editor)(buttonApi); + }, + onAction: function (formApi) { + var anchor = getAnchorElement(editor); + var value = formApi.getValue(); + if (!anchor) { + var attachState = { + href: value, + attach: function () { + } + }; + var onlyText = isOnlyTextSelected(editor); + var text = onlyText ? Optional.some(getAnchorText(editor.selection, anchor)).filter(function (t) { + return t.length > 0; + }).or(Optional.from(value)) : Optional.none(); + link(editor, attachState, { + href: value, + text: text, + title: Optional.none(), + rel: Optional.none(), + target: Optional.none(), + class: Optional.none() + }); + formApi.hide(); + } else { + editor.undoManager.transact(function () { + editor.dom.setAttrib(anchor, 'href', value); + collapseSelectionToEnd(editor); + formApi.hide(); + }); + } + } + }, + { + type: 'contextformbutton', + icon: 'unlink', + tooltip: 'Remove link', + onSetup: onSetupLink, + onAction: function (formApi) { + unlink(editor); + formApi.hide(); + } + }, + { + type: 'contextformbutton', + icon: 'new-tab', + tooltip: 'Open link', + onSetup: onSetupLink, + onAction: function (formApi) { + gotoSelectedLink(editor)(); + formApi.hide(); + } + } + ] + }); + }; + + function Plugin () { + global.add('link', function (editor) { + setupButtons(editor); + setupMenuItems(editor); + setupContextMenu(editor); + setupContextToolbars(editor); + setupGotoLinks(editor); + register(editor); + setup(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/link/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/link/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..bf4586881139227fb394f3ff3934e7e6ba8c2449 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/link/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var n,t,e,r,o=tinymce.util.Tools.resolve("tinymce.PluginManager"),i=tinymce.util.Tools.resolve("tinymce.util.VK"),u=function(r){return function(t){return e=typeof(n=t),(null===n?"null":"object"==e&&(Array.prototype.isPrototypeOf(n)||n.constructor&&"Array"===n.constructor.name)?"array":"object"==e&&(String.prototype.isPrototypeOf(n)||n.constructor&&"String"===n.constructor.name)?"string":e)===r;var n,e}},a=function(n){return function(t){return typeof t===n}},l=u("string"),c=u("array"),f=function(t){return n===t},s=a("boolean"),m=a("function"),g=function(t){var n=t.getParam("link_assume_external_targets",!1);return s(n)&&n?1:!l(n)||"http"!==n&&"https"!==n?0:n},p=function(t){return t.getParam("default_link_target")},d=function(t){return t.getParam("target_list",!0)},h=function(t){return t.getParam("rel_list",[],"array")},v=function(t){return t.getParam("allow_unsafe_link_target",!1,"boolean")},y=function(){},k=function(t){return function(){return t}},x=k(!1),b=k(!(n=null)),O=function(){return w},w=(t=function(t){return t.isNone()},{fold:function(t,n){return t()},is:x,isSome:x,isNone:b,getOr:r=function(t){return t},getOrThunk:e=function(t){return t()},getOrDie:function(t){throw new Error(t||"error: getOrDie called on none.")},getOrNull:k(null),getOrUndefined:k(undefined),or:r,orThunk:e,map:O,each:y,bind:O,exists:x,forall:b,filter:O,equals:t,equals_:t,toArray:function(){return[]},toString:k("none()")}),C=function(e){var t=k(e),n=function(){return o},r=function(t){return t(e)},o={fold:function(t,n){return n(e)},is:function(t){return e===t},isSome:b,isNone:x,getOr:t,getOrThunk:t,getOrDie:t,getOrNull:t,getOrUndefined:t,or:n,orThunk:n,map:function(t){return C(t(e))},each:function(t){t(e)},bind:r,exists:r,forall:r,filter:function(t){return t(e)?o:w},toArray:function(){return[e]},toString:function(){return"some("+e+")"},equals:function(t){return t.is(e)},equals_:function(t,n){return t.fold(x,function(t){return n(e,t)})}};return o},N={some:C,none:O,from:function(t){return null===t||t===undefined?w:C(t)}},A=Array.prototype.indexOf,P=Array.prototype.push,T=function(t,n){return e=t,r=n,-1= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none(); + }; + var head = function (xs) { + return get(xs, 0); + }; + var last = function (xs) { + return get(xs, xs.length - 1); + }; + + var __assign = function () { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + var cached = function (f) { + var called = false; + var r; + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + if (!called) { + called = true; + r = f.apply(null, args); + } + return r; + }; + }; + + var DeviceType = function (os, browser, userAgent, mediaMatch) { + var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true; + var isiPhone = os.isiOS() && !isiPad; + var isMobile = os.isiOS() || os.isAndroid(); + var isTouch = isMobile || mediaMatch('(pointer:coarse)'); + var isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)'); + var isPhone = isiPhone || isMobile && !isTablet; + var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false; + var isDesktop = !isPhone && !isTablet && !iOSwebview; + return { + isiPad: constant(isiPad), + isiPhone: constant(isiPhone), + isTablet: constant(isTablet), + isPhone: constant(isPhone), + isTouch: constant(isTouch), + isAndroid: os.isAndroid, + isiOS: os.isiOS, + isWebView: constant(iOSwebview), + isDesktop: constant(isDesktop) + }; + }; + + var firstMatch = function (regexes, s) { + for (var i = 0; i < regexes.length; i++) { + var x = regexes[i]; + if (x.test(s)) { + return x; + } + } + return undefined; + }; + var find$1 = function (regexes, agent) { + var r = firstMatch(regexes, agent); + if (!r) { + return { + major: 0, + minor: 0 + }; + } + var group = function (i) { + return Number(agent.replace(r, '$' + i)); + }; + return nu(group(1), group(2)); + }; + var detect = function (versionRegexes, agent) { + var cleanedAgent = String(agent).toLowerCase(); + if (versionRegexes.length === 0) { + return unknown(); + } + return find$1(versionRegexes, cleanedAgent); + }; + var unknown = function () { + return nu(0, 0); + }; + var nu = function (major, minor) { + return { + major: major, + minor: minor + }; + }; + var Version = { + nu: nu, + detect: detect, + unknown: unknown + }; + + var detect$1 = function (candidates, userAgent) { + var agent = String(userAgent).toLowerCase(); + return find(candidates, function (candidate) { + return candidate.search(agent); + }); + }; + var detectBrowser = function (browsers, userAgent) { + return detect$1(browsers, userAgent).map(function (browser) { + var version = Version.detect(browser.versionRegexes, userAgent); + return { + current: browser.name, + version: version + }; + }); + }; + var detectOs = function (oses, userAgent) { + return detect$1(oses, userAgent).map(function (os) { + var version = Version.detect(os.versionRegexes, userAgent); + return { + current: os.name, + version: version + }; + }); + }; + var UaString = { + detectBrowser: detectBrowser, + detectOs: detectOs + }; + + var contains = function (str, substr) { + return str.indexOf(substr) !== -1; + }; + + var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/; + var checkContains = function (target) { + return function (uastring) { + return contains(uastring, target); + }; + }; + var browsers = [ + { + name: 'Edge', + versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/], + search: function (uastring) { + return contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit'); + } + }, + { + name: 'Chrome', + versionRegexes: [ + /.*?chrome\/([0-9]+)\.([0-9]+).*/, + normalVersionRegex + ], + search: function (uastring) { + return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe'); + } + }, + { + name: 'IE', + versionRegexes: [ + /.*?msie\ ?([0-9]+)\.([0-9]+).*/, + /.*?rv:([0-9]+)\.([0-9]+).*/ + ], + search: function (uastring) { + return contains(uastring, 'msie') || contains(uastring, 'trident'); + } + }, + { + name: 'Opera', + versionRegexes: [ + normalVersionRegex, + /.*?opera\/([0-9]+)\.([0-9]+).*/ + ], + search: checkContains('opera') + }, + { + name: 'Firefox', + versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/], + search: checkContains('firefox') + }, + { + name: 'Safari', + versionRegexes: [ + normalVersionRegex, + /.*?cpu os ([0-9]+)_([0-9]+).*/ + ], + search: function (uastring) { + return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit'); + } + } + ]; + var oses = [ + { + name: 'Windows', + search: checkContains('win'), + versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/] + }, + { + name: 'iOS', + search: function (uastring) { + return contains(uastring, 'iphone') || contains(uastring, 'ipad'); + }, + versionRegexes: [ + /.*?version\/\ ?([0-9]+)\.([0-9]+).*/, + /.*cpu os ([0-9]+)_([0-9]+).*/, + /.*cpu iphone os ([0-9]+)_([0-9]+).*/ + ] + }, + { + name: 'Android', + search: checkContains('android'), + versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/] + }, + { + name: 'OSX', + search: checkContains('mac os x'), + versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/] + }, + { + name: 'Linux', + search: checkContains('linux'), + versionRegexes: [] + }, + { + name: 'Solaris', + search: checkContains('sunos'), + versionRegexes: [] + }, + { + name: 'FreeBSD', + search: checkContains('freebsd'), + versionRegexes: [] + }, + { + name: 'ChromeOS', + search: checkContains('cros'), + versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/] + } + ]; + var PlatformInfo = { + browsers: constant(browsers), + oses: constant(oses) + }; + + var edge = 'Edge'; + var chrome = 'Chrome'; + var ie = 'IE'; + var opera = 'Opera'; + var firefox = 'Firefox'; + var safari = 'Safari'; + var unknown$1 = function () { + return nu$1({ + current: undefined, + version: Version.unknown() + }); + }; + var nu$1 = function (info) { + var current = info.current; + var version = info.version; + var isBrowser = function (name) { + return function () { + return current === name; + }; + }; + return { + current: current, + version: version, + isEdge: isBrowser(edge), + isChrome: isBrowser(chrome), + isIE: isBrowser(ie), + isOpera: isBrowser(opera), + isFirefox: isBrowser(firefox), + isSafari: isBrowser(safari) + }; + }; + var Browser = { + unknown: unknown$1, + nu: nu$1, + edge: constant(edge), + chrome: constant(chrome), + ie: constant(ie), + opera: constant(opera), + firefox: constant(firefox), + safari: constant(safari) + }; + + var windows = 'Windows'; + var ios = 'iOS'; + var android = 'Android'; + var linux = 'Linux'; + var osx = 'OSX'; + var solaris = 'Solaris'; + var freebsd = 'FreeBSD'; + var chromeos = 'ChromeOS'; + var unknown$2 = function () { + return nu$2({ + current: undefined, + version: Version.unknown() + }); + }; + var nu$2 = function (info) { + var current = info.current; + var version = info.version; + var isOS = function (name) { + return function () { + return current === name; + }; + }; + return { + current: current, + version: version, + isWindows: isOS(windows), + isiOS: isOS(ios), + isAndroid: isOS(android), + isOSX: isOS(osx), + isLinux: isOS(linux), + isSolaris: isOS(solaris), + isFreeBSD: isOS(freebsd), + isChromeOS: isOS(chromeos) + }; + }; + var OperatingSystem = { + unknown: unknown$2, + nu: nu$2, + windows: constant(windows), + ios: constant(ios), + android: constant(android), + linux: constant(linux), + osx: constant(osx), + solaris: constant(solaris), + freebsd: constant(freebsd), + chromeos: constant(chromeos) + }; + + var detect$2 = function (userAgent, mediaMatch) { + var browsers = PlatformInfo.browsers(); + var oses = PlatformInfo.oses(); + var browser = UaString.detectBrowser(browsers, userAgent).fold(Browser.unknown, Browser.nu); + var os = UaString.detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu); + var deviceType = DeviceType(os, browser, userAgent, mediaMatch); + return { + browser: browser, + os: os, + deviceType: deviceType + }; + }; + var PlatformDetection = { detect: detect$2 }; + + var mediaMatch = function (query) { + return window.matchMedia(query).matches; + }; + var platform = cached(function () { + return PlatformDetection.detect(navigator.userAgent, mediaMatch); + }); + var detect$3 = function () { + return platform(); + }; + + var compareDocumentPosition = function (a, b, match) { + return (a.compareDocumentPosition(b) & match) !== 0; + }; + var documentPositionContainedBy = function (a, b) { + return compareDocumentPosition(a, b, Node.DOCUMENT_POSITION_CONTAINED_BY); + }; + + var ELEMENT = 1; + + var fromHtml = function (html, scope) { + var doc = scope || document; + var div = doc.createElement('div'); + div.innerHTML = html; + if (!div.hasChildNodes() || div.childNodes.length > 1) { + console.error('HTML does not have a single root node', html); + throw new Error('HTML must have a single root node'); + } + return fromDom(div.childNodes[0]); + }; + var fromTag = function (tag, scope) { + var doc = scope || document; + var node = doc.createElement(tag); + return fromDom(node); + }; + var fromText = function (text, scope) { + var doc = scope || document; + var node = doc.createTextNode(text); + return fromDom(node); + }; + var fromDom = function (node) { + if (node === null || node === undefined) { + throw new Error('Node cannot be null or undefined'); + } + return { dom: node }; + }; + var fromPoint = function (docElm, x, y) { + return Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom); + }; + var SugarElement = { + fromHtml: fromHtml, + fromTag: fromTag, + fromText: fromText, + fromDom: fromDom, + fromPoint: fromPoint + }; + + var is = function (element, selector) { + var dom = element.dom; + if (dom.nodeType !== ELEMENT) { + return false; + } else { + var elem = dom; + if (elem.matches !== undefined) { + return elem.matches(selector); + } else if (elem.msMatchesSelector !== undefined) { + return elem.msMatchesSelector(selector); + } else if (elem.webkitMatchesSelector !== undefined) { + return elem.webkitMatchesSelector(selector); + } else if (elem.mozMatchesSelector !== undefined) { + return elem.mozMatchesSelector(selector); + } else { + throw new Error('Browser lacks native selectors'); + } + } + }; + + var eq = function (e1, e2) { + return e1.dom === e2.dom; + }; + var regularContains = function (e1, e2) { + var d1 = e1.dom; + var d2 = e2.dom; + return d1 === d2 ? false : d1.contains(d2); + }; + var ieContains = function (e1, e2) { + return documentPositionContainedBy(e1.dom, e2.dom); + }; + var contains$1 = function (e1, e2) { + return detect$3().browser.isIE() ? ieContains(e1, e2) : regularContains(e1, e2); + }; + var is$1 = is; + + var global$1 = tinymce.util.Tools.resolve('tinymce.dom.RangeUtils'); + + var global$2 = tinymce.util.Tools.resolve('tinymce.dom.TreeWalker'); + + var global$3 = tinymce.util.Tools.resolve('tinymce.util.VK'); + + var keys = Object.keys; + var each$1 = function (obj, f) { + var props = keys(obj); + for (var k = 0, len = props.length; k < len; k++) { + var i = props[k]; + var x = obj[i]; + f(x, i); + } + }; + var objAcc = function (r) { + return function (x, i) { + r[i] = x; + }; + }; + var internalFilter = function (obj, pred, onTrue, onFalse) { + var r = {}; + each$1(obj, function (x, i) { + (pred(x, i) ? onTrue : onFalse)(x, i); + }); + return r; + }; + var filter$1 = function (obj, pred) { + var t = {}; + internalFilter(obj, pred, objAcc(t), noop); + return t; + }; + + var Global = typeof window !== 'undefined' ? window : Function('return this;')(); + + var name = function (element) { + var r = element.dom.nodeName; + return r.toLowerCase(); + }; + var type = function (element) { + return element.dom.nodeType; + }; + var isType$1 = function (t) { + return function (element) { + return type(element) === t; + }; + }; + var isElement = isType$1(ELEMENT); + + var rawSet = function (dom, key, value) { + if (isString(value) || isBoolean(value) || isNumber(value)) { + dom.setAttribute(key, value + ''); + } else { + console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom); + throw new Error('Attribute value was not simple'); + } + }; + var setAll = function (element, attrs) { + var dom = element.dom; + each$1(attrs, function (v, k) { + rawSet(dom, k, v); + }); + }; + var clone = function (element) { + return foldl(element.dom.attributes, function (acc, attr) { + acc[attr.name] = attr.value; + return acc; + }, {}); + }; + + var parent = function (element) { + return Optional.from(element.dom.parentNode).map(SugarElement.fromDom); + }; + var children = function (element) { + return map(element.dom.childNodes, SugarElement.fromDom); + }; + var child = function (element, index) { + var cs = element.dom.childNodes; + return Optional.from(cs[index]).map(SugarElement.fromDom); + }; + var firstChild = function (element) { + return child(element, 0); + }; + var lastChild = function (element) { + return child(element, element.dom.childNodes.length - 1); + }; + + var before = function (marker, element) { + var parent$1 = parent(marker); + parent$1.each(function (v) { + v.dom.insertBefore(element.dom, marker.dom); + }); + }; + var append = function (parent, element) { + parent.dom.appendChild(element.dom); + }; + + var before$1 = function (marker, elements) { + each(elements, function (x) { + before(marker, x); + }); + }; + var append$1 = function (parent, elements) { + each(elements, function (x) { + append(parent, x); + }); + }; + + var remove = function (element) { + var dom = element.dom; + if (dom.parentNode !== null) { + dom.parentNode.removeChild(dom); + } + }; + + var clone$1 = function (original, isDeep) { + return SugarElement.fromDom(original.dom.cloneNode(isDeep)); + }; + var deep = function (original) { + return clone$1(original, true); + }; + var shallowAs = function (original, tag) { + var nu = SugarElement.fromTag(tag); + var attributes = clone(original); + setAll(nu, attributes); + return nu; + }; + var mutate = function (original, tag) { + var nu = shallowAs(original, tag); + before(original, nu); + var children$1 = children(original); + append$1(nu, children$1); + remove(original); + return nu; + }; + + var global$4 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils'); + + var global$5 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var matchNodeName = function (name) { + return function (node) { + return node && node.nodeName.toLowerCase() === name; + }; + }; + var matchNodeNames = function (regex) { + return function (node) { + return node && regex.test(node.nodeName); + }; + }; + var isTextNode = function (node) { + return node && node.nodeType === 3; + }; + var isListNode = matchNodeNames(/^(OL|UL|DL)$/); + var isOlUlNode = matchNodeNames(/^(OL|UL)$/); + var isOlNode = matchNodeName('ol'); + var isListItemNode = matchNodeNames(/^(LI|DT|DD)$/); + var isDlItemNode = matchNodeNames(/^(DT|DD)$/); + var isTableCellNode = matchNodeNames(/^(TH|TD)$/); + var isBr = matchNodeName('br'); + var isFirstChild = function (node) { + return node.parentNode.firstChild === node; + }; + var isTextBlock = function (editor, node) { + return node && !!editor.schema.getTextBlockElements()[node.nodeName]; + }; + var isBlock = function (node, blockElements) { + return node && node.nodeName in blockElements; + }; + var isBogusBr = function (dom, node) { + if (!isBr(node)) { + return false; + } + return dom.isBlock(node.nextSibling) && !isBr(node.previousSibling); + }; + var isEmpty = function (dom, elm, keepBookmarks) { + var empty = dom.isEmpty(elm); + if (keepBookmarks && dom.select('span[data-mce-type=bookmark]', elm).length > 0) { + return false; + } + return empty; + }; + var isChildOfBody = function (dom, elm) { + return dom.isChildOf(elm, dom.getRoot()); + }; + + var shouldIndentOnTab = function (editor) { + return editor.getParam('lists_indent_on_tab', true); + }; + var getForcedRootBlock = function (editor) { + var block = editor.getParam('forced_root_block', 'p'); + if (block === false) { + return ''; + } else if (block === true) { + return 'p'; + } else { + return block; + } + }; + var getForcedRootBlockAttrs = function (editor) { + return editor.getParam('forced_root_block_attrs', {}); + }; + + var createTextBlock = function (editor, contentNode) { + var dom = editor.dom; + var blockElements = editor.schema.getBlockElements(); + var fragment = dom.createFragment(); + var blockName = getForcedRootBlock(editor); + var node, textBlock, hasContentNode; + if (blockName) { + textBlock = dom.create(blockName); + if (textBlock.tagName === blockName.toUpperCase()) { + dom.setAttribs(textBlock, getForcedRootBlockAttrs(editor)); + } + if (!isBlock(contentNode.firstChild, blockElements)) { + fragment.appendChild(textBlock); + } + } + if (contentNode) { + while (node = contentNode.firstChild) { + var nodeName = node.nodeName; + if (!hasContentNode && (nodeName !== 'SPAN' || node.getAttribute('data-mce-type') !== 'bookmark')) { + hasContentNode = true; + } + if (isBlock(node, blockElements)) { + fragment.appendChild(node); + textBlock = null; + } else { + if (blockName) { + if (!textBlock) { + textBlock = dom.create(blockName); + fragment.appendChild(textBlock); + } + textBlock.appendChild(node); + } else { + fragment.appendChild(node); + } + } + } + } + if (!blockName) { + fragment.appendChild(dom.create('br')); + } else { + if (!hasContentNode) { + textBlock.appendChild(dom.create('br', { 'data-mce-bogus': '1' })); + } + } + return fragment; + }; + + var DOM = global$4.DOM; + var splitList = function (editor, ul, li) { + var removeAndKeepBookmarks = function (targetNode) { + global$5.each(bookmarks, function (node) { + targetNode.parentNode.insertBefore(node, li.parentNode); + }); + DOM.remove(targetNode); + }; + var bookmarks = DOM.select('span[data-mce-type="bookmark"]', ul); + var newBlock = createTextBlock(editor, li); + var tmpRng = DOM.createRng(); + tmpRng.setStartAfter(li); + tmpRng.setEndAfter(ul); + var fragment = tmpRng.extractContents(); + for (var node = fragment.firstChild; node; node = node.firstChild) { + if (node.nodeName === 'LI' && editor.dom.isEmpty(node)) { + DOM.remove(node); + break; + } + } + if (!editor.dom.isEmpty(fragment)) { + DOM.insertAfter(fragment, ul); + } + DOM.insertAfter(newBlock, ul); + if (isEmpty(editor.dom, li.parentNode)) { + removeAndKeepBookmarks(li.parentNode); + } + DOM.remove(li); + if (isEmpty(editor.dom, ul)) { + DOM.remove(ul); + } + }; + + var outdentDlItem = function (editor, item) { + if (is$1(item, 'dd')) { + mutate(item, 'dt'); + } else if (is$1(item, 'dt')) { + parent(item).each(function (dl) { + return splitList(editor, dl.dom, item.dom); + }); + } + }; + var indentDlItem = function (item) { + if (is$1(item, 'dt')) { + mutate(item, 'dd'); + } + }; + var dlIndentation = function (editor, indentation, dlItems) { + if (indentation === 'Indent') { + each(dlItems, indentDlItem); + } else { + each(dlItems, function (item) { + return outdentDlItem(editor, item); + }); + } + }; + + var getNormalizedPoint = function (container, offset) { + if (isTextNode(container)) { + return { + container: container, + offset: offset + }; + } + var node = global$1.getNode(container, offset); + if (isTextNode(node)) { + return { + container: node, + offset: offset >= container.childNodes.length ? node.data.length : 0 + }; + } else if (node.previousSibling && isTextNode(node.previousSibling)) { + return { + container: node.previousSibling, + offset: node.previousSibling.data.length + }; + } else if (node.nextSibling && isTextNode(node.nextSibling)) { + return { + container: node.nextSibling, + offset: 0 + }; + } + return { + container: container, + offset: offset + }; + }; + var normalizeRange = function (rng) { + var outRng = rng.cloneRange(); + var rangeStart = getNormalizedPoint(rng.startContainer, rng.startOffset); + outRng.setStart(rangeStart.container, rangeStart.offset); + var rangeEnd = getNormalizedPoint(rng.endContainer, rng.endOffset); + outRng.setEnd(rangeEnd.container, rangeEnd.offset); + return outRng; + }; + + var global$6 = tinymce.util.Tools.resolve('tinymce.dom.DomQuery'); + + var getParentList = function (editor, node) { + var selectionStart = node || editor.selection.getStart(true); + return editor.dom.getParent(selectionStart, 'OL,UL,DL', getClosestListRootElm(editor, selectionStart)); + }; + var isParentListSelected = function (parentList, selectedBlocks) { + return parentList && selectedBlocks.length === 1 && selectedBlocks[0] === parentList; + }; + var findSubLists = function (parentList) { + return global$5.grep(parentList.querySelectorAll('ol,ul,dl'), function (elm) { + return isListNode(elm); + }); + }; + var getSelectedSubLists = function (editor) { + var parentList = getParentList(editor); + var selectedBlocks = editor.selection.getSelectedBlocks(); + if (isParentListSelected(parentList, selectedBlocks)) { + return findSubLists(parentList); + } else { + return global$5.grep(selectedBlocks, function (elm) { + return isListNode(elm) && parentList !== elm; + }); + } + }; + var findParentListItemsNodes = function (editor, elms) { + var listItemsElms = global$5.map(elms, function (elm) { + var parentLi = editor.dom.getParent(elm, 'li,dd,dt', getClosestListRootElm(editor, elm)); + return parentLi ? parentLi : elm; + }); + return global$6.unique(listItemsElms); + }; + var getSelectedListItems = function (editor) { + var selectedBlocks = editor.selection.getSelectedBlocks(); + return global$5.grep(findParentListItemsNodes(editor, selectedBlocks), function (block) { + return isListItemNode(block); + }); + }; + var getSelectedDlItems = function (editor) { + return filter(getSelectedListItems(editor), isDlItemNode); + }; + var getClosestListRootElm = function (editor, elm) { + var parentTableCell = editor.dom.getParents(elm, 'TD,TH'); + var root = parentTableCell.length > 0 ? parentTableCell[0] : editor.getBody(); + return root; + }; + var findLastParentListNode = function (editor, elm) { + var parentLists = editor.dom.getParents(elm, 'ol,ul', getClosestListRootElm(editor, elm)); + return last(parentLists); + }; + var getSelectedLists = function (editor) { + var firstList = findLastParentListNode(editor, editor.selection.getStart()); + var subsequentLists = filter(editor.selection.getSelectedBlocks(), isOlUlNode); + return firstList.toArray().concat(subsequentLists); + }; + var getSelectedListRoots = function (editor) { + var selectedLists = getSelectedLists(editor); + return getUniqueListRoots(editor, selectedLists); + }; + var getUniqueListRoots = function (editor, lists) { + var listRoots = map(lists, function (list) { + return findLastParentListNode(editor, list).getOr(list); + }); + return global$6.unique(listRoots); + }; + + var lift2 = function (oa, ob, f) { + return oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none(); + }; + + var fromElements = function (elements, scope) { + var doc = scope || document; + var fragment = doc.createDocumentFragment(); + each(elements, function (element) { + fragment.appendChild(element.dom); + }); + return SugarElement.fromDom(fragment); + }; + + var fireListEvent = function (editor, action, element) { + return editor.fire('ListMutation', { + action: action, + element: element + }); + }; + + var isSupported = function (dom) { + return dom.style !== undefined && isFunction(dom.style.getPropertyValue); + }; + + var internalSet = function (dom, property, value) { + if (!isString(value)) { + console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom); + throw new Error('CSS value must be a string: ' + value); + } + if (isSupported(dom)) { + dom.style.setProperty(property, value); + } + }; + var set = function (element, property, value) { + var dom = element.dom; + internalSet(dom, property, value); + }; + + var joinSegment = function (parent, child) { + append(parent.item, child.list); + }; + var joinSegments = function (segments) { + for (var i = 1; i < segments.length; i++) { + joinSegment(segments[i - 1], segments[i]); + } + }; + var appendSegments = function (head$1, tail) { + lift2(last(head$1), head(tail), joinSegment); + }; + var createSegment = function (scope, listType) { + var segment = { + list: SugarElement.fromTag(listType, scope), + item: SugarElement.fromTag('li', scope) + }; + append(segment.list, segment.item); + return segment; + }; + var createSegments = function (scope, entry, size) { + var segments = []; + for (var i = 0; i < size; i++) { + segments.push(createSegment(scope, entry.listType)); + } + return segments; + }; + var populateSegments = function (segments, entry) { + for (var i = 0; i < segments.length - 1; i++) { + set(segments[i].item, 'list-style-type', 'none'); + } + last(segments).each(function (segment) { + setAll(segment.list, entry.listAttributes); + setAll(segment.item, entry.itemAttributes); + append$1(segment.item, entry.content); + }); + }; + var normalizeSegment = function (segment, entry) { + if (name(segment.list) !== entry.listType) { + segment.list = mutate(segment.list, entry.listType); + } + setAll(segment.list, entry.listAttributes); + }; + var createItem = function (scope, attr, content) { + var item = SugarElement.fromTag('li', scope); + setAll(item, attr); + append$1(item, content); + return item; + }; + var appendItem = function (segment, item) { + append(segment.list, item); + segment.item = item; + }; + var writeShallow = function (scope, cast, entry) { + var newCast = cast.slice(0, entry.depth); + last(newCast).each(function (segment) { + var item = createItem(scope, entry.itemAttributes, entry.content); + appendItem(segment, item); + normalizeSegment(segment, entry); + }); + return newCast; + }; + var writeDeep = function (scope, cast, entry) { + var segments = createSegments(scope, entry, entry.depth - cast.length); + joinSegments(segments); + populateSegments(segments, entry); + appendSegments(cast, segments); + return cast.concat(segments); + }; + var composeList = function (scope, entries) { + var cast = foldl(entries, function (cast, entry) { + return entry.depth > cast.length ? writeDeep(scope, cast, entry) : writeShallow(scope, cast, entry); + }, []); + return head(cast).map(function (segment) { + return segment.list; + }); + }; + + var isList = function (el) { + return is$1(el, 'OL,UL'); + }; + var hasFirstChildList = function (el) { + return firstChild(el).map(isList).getOr(false); + }; + var hasLastChildList = function (el) { + return lastChild(el).map(isList).getOr(false); + }; + + var isIndented = function (entry) { + return entry.depth > 0; + }; + var isSelected = function (entry) { + return entry.isSelected; + }; + var cloneItemContent = function (li) { + var children$1 = children(li); + var content = hasLastChildList(li) ? children$1.slice(0, -1) : children$1; + return map(content, deep); + }; + var createEntry = function (li, depth, isSelected) { + return parent(li).filter(isElement).map(function (list) { + return { + depth: depth, + dirty: false, + isSelected: isSelected, + content: cloneItemContent(li), + itemAttributes: clone(li), + listAttributes: clone(list), + listType: name(list) + }; + }); + }; + + var indentEntry = function (indentation, entry) { + switch (indentation) { + case 'Indent': + entry.depth++; + break; + case 'Outdent': + entry.depth--; + break; + case 'Flatten': + entry.depth = 0; + } + entry.dirty = true; + }; + + var cloneListProperties = function (target, source) { + target.listType = source.listType; + target.listAttributes = __assign({}, source.listAttributes); + }; + var cleanListProperties = function (entry) { + entry.listAttributes = filter$1(entry.listAttributes, function (_value, key) { + return key !== 'start'; + }); + }; + var closestSiblingEntry = function (entries, start) { + var depth = entries[start].depth; + var matches = function (entry) { + return entry.depth === depth && !entry.dirty; + }; + var until = function (entry) { + return entry.depth < depth; + }; + return findUntil(reverse(entries.slice(0, start)), matches, until).orThunk(function () { + return findUntil(entries.slice(start + 1), matches, until); + }); + }; + var normalizeEntries = function (entries) { + each(entries, function (entry, i) { + closestSiblingEntry(entries, i).fold(function () { + if (entry.dirty) { + cleanListProperties(entry); + } + }, function (matchingEntry) { + return cloneListProperties(entry, matchingEntry); + }); + }); + return entries; + }; + + var Cell = function (initial) { + var value = initial; + var get = function () { + return value; + }; + var set = function (v) { + value = v; + }; + return { + get: get, + set: set + }; + }; + + var parseItem = function (depth, itemSelection, selectionState, item) { + return firstChild(item).filter(isList).fold(function () { + itemSelection.each(function (selection) { + if (eq(selection.start, item)) { + selectionState.set(true); + } + }); + var currentItemEntry = createEntry(item, depth, selectionState.get()); + itemSelection.each(function (selection) { + if (eq(selection.end, item)) { + selectionState.set(false); + } + }); + var childListEntries = lastChild(item).filter(isList).map(function (list) { + return parseList(depth, itemSelection, selectionState, list); + }).getOr([]); + return currentItemEntry.toArray().concat(childListEntries); + }, function (list) { + return parseList(depth, itemSelection, selectionState, list); + }); + }; + var parseList = function (depth, itemSelection, selectionState, list) { + return bind(children(list), function (element) { + var parser = isList(element) ? parseList : parseItem; + var newDepth = depth + 1; + return parser(newDepth, itemSelection, selectionState, element); + }); + }; + var parseLists = function (lists, itemSelection) { + var selectionState = Cell(false); + var initialDepth = 0; + return map(lists, function (list) { + return { + sourceList: list, + entries: parseList(initialDepth, itemSelection, selectionState, list) + }; + }); + }; + + var outdentedComposer = function (editor, entries) { + var normalizedEntries = normalizeEntries(entries); + return map(normalizedEntries, function (entry) { + var content = fromElements(entry.content); + return SugarElement.fromDom(createTextBlock(editor, content.dom)); + }); + }; + var indentedComposer = function (editor, entries) { + var normalizedEntries = normalizeEntries(entries); + return composeList(editor.contentDocument, normalizedEntries).toArray(); + }; + var composeEntries = function (editor, entries) { + return bind(groupBy(entries, isIndented), function (entries) { + var groupIsIndented = head(entries).map(isIndented).getOr(false); + return groupIsIndented ? indentedComposer(editor, entries) : outdentedComposer(editor, entries); + }); + }; + var indentSelectedEntries = function (entries, indentation) { + each(filter(entries, isSelected), function (entry) { + return indentEntry(indentation, entry); + }); + }; + var getItemSelection = function (editor) { + var selectedListItems = map(getSelectedListItems(editor), SugarElement.fromDom); + return lift2(find(selectedListItems, not(hasFirstChildList)), find(reverse(selectedListItems), not(hasFirstChildList)), function (start, end) { + return { + start: start, + end: end + }; + }); + }; + var listIndentation = function (editor, lists, indentation) { + var entrySets = parseLists(lists, getItemSelection(editor)); + each(entrySets, function (entrySet) { + indentSelectedEntries(entrySet.entries, indentation); + var composedLists = composeEntries(editor, entrySet.entries); + each(composedLists, function (composedList) { + fireListEvent(editor, indentation === 'Indent' ? 'IndentList' : 'OutdentList', composedList.dom); + }); + before$1(entrySet.sourceList, composedLists); + remove(entrySet.sourceList); + }); + }; + + var selectionIndentation = function (editor, indentation) { + var lists = map(getSelectedListRoots(editor), SugarElement.fromDom); + var dlItems = map(getSelectedDlItems(editor), SugarElement.fromDom); + var isHandled = false; + if (lists.length || dlItems.length) { + var bookmark = editor.selection.getBookmark(); + listIndentation(editor, lists, indentation); + dlIndentation(editor, indentation, dlItems); + editor.selection.moveToBookmark(bookmark); + editor.selection.setRng(normalizeRange(editor.selection.getRng())); + editor.nodeChanged(); + isHandled = true; + } + return isHandled; + }; + var indentListSelection = function (editor) { + return selectionIndentation(editor, 'Indent'); + }; + var outdentListSelection = function (editor) { + return selectionIndentation(editor, 'Outdent'); + }; + var flattenListSelection = function (editor) { + return selectionIndentation(editor, 'Flatten'); + }; + + var global$7 = tinymce.util.Tools.resolve('tinymce.dom.BookmarkManager'); + + var DOM$1 = global$4.DOM; + var createBookmark = function (rng) { + var bookmark = {}; + var setupEndPoint = function (start) { + var offsetNode, container, offset; + container = rng[start ? 'startContainer' : 'endContainer']; + offset = rng[start ? 'startOffset' : 'endOffset']; + if (container.nodeType === 1) { + offsetNode = DOM$1.create('span', { 'data-mce-type': 'bookmark' }); + if (container.hasChildNodes()) { + offset = Math.min(offset, container.childNodes.length - 1); + if (start) { + container.insertBefore(offsetNode, container.childNodes[offset]); + } else { + DOM$1.insertAfter(offsetNode, container.childNodes[offset]); + } + } else { + container.appendChild(offsetNode); + } + container = offsetNode; + offset = 0; + } + bookmark[start ? 'startContainer' : 'endContainer'] = container; + bookmark[start ? 'startOffset' : 'endOffset'] = offset; + }; + setupEndPoint(true); + if (!rng.collapsed) { + setupEndPoint(); + } + return bookmark; + }; + var resolveBookmark = function (bookmark) { + function restoreEndPoint(start) { + var container, offset, node; + var nodeIndex = function (container) { + var node = container.parentNode.firstChild, idx = 0; + while (node) { + if (node === container) { + return idx; + } + if (node.nodeType !== 1 || node.getAttribute('data-mce-type') !== 'bookmark') { + idx++; + } + node = node.nextSibling; + } + return -1; + }; + container = node = bookmark[start ? 'startContainer' : 'endContainer']; + offset = bookmark[start ? 'startOffset' : 'endOffset']; + if (!container) { + return; + } + if (container.nodeType === 1) { + offset = nodeIndex(container); + container = container.parentNode; + DOM$1.remove(node); + if (!container.hasChildNodes() && DOM$1.isBlock(container)) { + container.appendChild(DOM$1.create('br')); + } + } + bookmark[start ? 'startContainer' : 'endContainer'] = container; + bookmark[start ? 'startOffset' : 'endOffset'] = offset; + } + restoreEndPoint(true); + restoreEndPoint(); + var rng = DOM$1.createRng(); + rng.setStart(bookmark.startContainer, bookmark.startOffset); + if (bookmark.endContainer) { + rng.setEnd(bookmark.endContainer, bookmark.endOffset); + } + return normalizeRange(rng); + }; + + var listToggleActionFromListName = function (listName) { + switch (listName) { + case 'UL': + return 'ToggleUlList'; + case 'OL': + return 'ToggleOlList'; + case 'DL': + return 'ToggleDLList'; + } + }; + + var isCustomList = function (list) { + return /\btox\-/.test(list.className); + }; + var listState = function (editor, listName, activate) { + var nodeChangeHandler = function (e) { + var inList = findUntil(e.parents, isListNode, isTableCellNode).filter(function (list) { + return list.nodeName === listName && !isCustomList(list); + }).isSome(); + activate(inList); + }; + var parents = editor.dom.getParents(editor.selection.getNode()); + nodeChangeHandler({ parents: parents }); + editor.on('NodeChange', nodeChangeHandler); + return function () { + return editor.off('NodeChange', nodeChangeHandler); + }; + }; + + var updateListStyle = function (dom, el, detail) { + var type = detail['list-style-type'] ? detail['list-style-type'] : null; + dom.setStyle(el, 'list-style-type', type); + }; + var setAttribs = function (elm, attrs) { + global$5.each(attrs, function (value, key) { + elm.setAttribute(key, value); + }); + }; + var updateListAttrs = function (dom, el, detail) { + setAttribs(el, detail['list-attributes']); + global$5.each(dom.select('li', el), function (li) { + setAttribs(li, detail['list-item-attributes']); + }); + }; + var updateListWithDetails = function (dom, el, detail) { + updateListStyle(dom, el, detail); + updateListAttrs(dom, el, detail); + }; + var removeStyles = function (dom, element, styles) { + global$5.each(styles, function (style) { + var _a; + return dom.setStyle(element, (_a = {}, _a[style] = '', _a)); + }); + }; + var getEndPointNode = function (editor, rng, start, root) { + var container = rng[start ? 'startContainer' : 'endContainer']; + var offset = rng[start ? 'startOffset' : 'endOffset']; + if (container.nodeType === 1) { + container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container; + } + if (!start && isBr(container.nextSibling)) { + container = container.nextSibling; + } + while (container.parentNode !== root) { + if (isTextBlock(editor, container)) { + return container; + } + if (/^(TD|TH)$/.test(container.parentNode.nodeName)) { + return container; + } + container = container.parentNode; + } + return container; + }; + var getSelectedTextBlocks = function (editor, rng, root) { + var textBlocks = [], dom = editor.dom; + var startNode = getEndPointNode(editor, rng, true, root); + var endNode = getEndPointNode(editor, rng, false, root); + var block; + var siblings = []; + for (var node = startNode; node; node = node.nextSibling) { + siblings.push(node); + if (node === endNode) { + break; + } + } + global$5.each(siblings, function (node) { + if (isTextBlock(editor, node)) { + textBlocks.push(node); + block = null; + return; + } + if (dom.isBlock(node) || isBr(node)) { + if (isBr(node)) { + dom.remove(node); + } + block = null; + return; + } + var nextSibling = node.nextSibling; + if (global$7.isBookmarkNode(node)) { + if (isTextBlock(editor, nextSibling) || !nextSibling && node.parentNode === root) { + block = null; + return; + } + } + if (!block) { + block = dom.create('p'); + node.parentNode.insertBefore(block, node); + textBlocks.push(block); + } + block.appendChild(node); + }); + return textBlocks; + }; + var hasCompatibleStyle = function (dom, sib, detail) { + var sibStyle = dom.getStyle(sib, 'list-style-type'); + var detailStyle = detail ? detail['list-style-type'] : ''; + detailStyle = detailStyle === null ? '' : detailStyle; + return sibStyle === detailStyle; + }; + var applyList = function (editor, listName, detail) { + if (detail === void 0) { + detail = {}; + } + var rng = editor.selection.getRng(); + var listItemName = 'LI'; + var root = getClosestListRootElm(editor, editor.selection.getStart(true)); + var dom = editor.dom; + if (dom.getContentEditable(editor.selection.getNode()) === 'false') { + return; + } + listName = listName.toUpperCase(); + if (listName === 'DL') { + listItemName = 'DT'; + } + var bookmark = createBookmark(rng); + global$5.each(getSelectedTextBlocks(editor, rng, root), function (block) { + var listBlock; + var sibling = block.previousSibling; + if (sibling && isListNode(sibling) && sibling.nodeName === listName && hasCompatibleStyle(dom, sibling, detail)) { + listBlock = sibling; + block = dom.rename(block, listItemName); + sibling.appendChild(block); + } else { + listBlock = dom.create(listName); + block.parentNode.insertBefore(listBlock, block); + listBlock.appendChild(block); + block = dom.rename(block, listItemName); + } + removeStyles(dom, block, [ + 'margin', + 'margin-right', + 'margin-bottom', + 'margin-left', + 'margin-top', + 'padding', + 'padding-right', + 'padding-bottom', + 'padding-left', + 'padding-top' + ]); + updateListWithDetails(dom, listBlock, detail); + mergeWithAdjacentLists(editor.dom, listBlock); + }); + editor.selection.setRng(resolveBookmark(bookmark)); + }; + var isValidLists = function (list1, list2) { + return list1 && list2 && isListNode(list1) && list1.nodeName === list2.nodeName; + }; + var hasSameListStyle = function (dom, list1, list2) { + var targetStyle = dom.getStyle(list1, 'list-style-type', true); + var style = dom.getStyle(list2, 'list-style-type', true); + return targetStyle === style; + }; + var hasSameClasses = function (elm1, elm2) { + return elm1.className === elm2.className; + }; + var shouldMerge = function (dom, list1, list2) { + return isValidLists(list1, list2) && hasSameListStyle(dom, list1, list2) && hasSameClasses(list1, list2); + }; + var mergeWithAdjacentLists = function (dom, listBlock) { + var sibling, node; + sibling = listBlock.nextSibling; + if (shouldMerge(dom, listBlock, sibling)) { + while (node = sibling.firstChild) { + listBlock.appendChild(node); + } + dom.remove(sibling); + } + sibling = listBlock.previousSibling; + if (shouldMerge(dom, listBlock, sibling)) { + while (node = sibling.lastChild) { + listBlock.insertBefore(node, listBlock.firstChild); + } + dom.remove(sibling); + } + }; + var updateList = function (editor, list, listName, detail) { + if (list.nodeName !== listName) { + var newList = editor.dom.rename(list, listName); + updateListWithDetails(editor.dom, newList, detail); + fireListEvent(editor, listToggleActionFromListName(listName), newList); + } else { + updateListWithDetails(editor.dom, list, detail); + fireListEvent(editor, listToggleActionFromListName(listName), list); + } + }; + var toggleMultipleLists = function (editor, parentList, lists, listName, detail) { + if (parentList.nodeName === listName && !hasListStyleDetail(detail)) { + flattenListSelection(editor); + } else { + var bookmark = createBookmark(editor.selection.getRng(true)); + global$5.each([parentList].concat(lists), function (elm) { + updateList(editor, elm, listName, detail); + }); + editor.selection.setRng(resolveBookmark(bookmark)); + } + }; + var hasListStyleDetail = function (detail) { + return 'list-style-type' in detail; + }; + var toggleSingleList = function (editor, parentList, listName, detail) { + if (parentList === editor.getBody()) { + return; + } + if (parentList) { + if (parentList.nodeName === listName && !hasListStyleDetail(detail) && !isCustomList(parentList)) { + flattenListSelection(editor); + } else { + var bookmark = createBookmark(editor.selection.getRng(true)); + updateListWithDetails(editor.dom, parentList, detail); + var newList = editor.dom.rename(parentList, listName); + mergeWithAdjacentLists(editor.dom, newList); + editor.selection.setRng(resolveBookmark(bookmark)); + fireListEvent(editor, listToggleActionFromListName(listName), newList); + } + } else { + applyList(editor, listName, detail); + fireListEvent(editor, listToggleActionFromListName(listName), parentList); + } + }; + var toggleList = function (editor, listName, detail) { + var parentList = getParentList(editor); + var selectedSubLists = getSelectedSubLists(editor); + detail = detail ? detail : {}; + if (parentList && selectedSubLists.length > 0) { + toggleMultipleLists(editor, parentList, selectedSubLists, listName, detail); + } else { + toggleSingleList(editor, parentList, listName, detail); + } + }; + + var DOM$2 = global$4.DOM; + var normalizeList = function (dom, ul) { + var sibling; + var parentNode = ul.parentNode; + if (parentNode.nodeName === 'LI' && parentNode.firstChild === ul) { + sibling = parentNode.previousSibling; + if (sibling && sibling.nodeName === 'LI') { + sibling.appendChild(ul); + if (isEmpty(dom, parentNode)) { + DOM$2.remove(parentNode); + } + } else { + DOM$2.setStyle(parentNode, 'listStyleType', 'none'); + } + } + if (isListNode(parentNode)) { + sibling = parentNode.previousSibling; + if (sibling && sibling.nodeName === 'LI') { + sibling.appendChild(ul); + } + } + }; + var normalizeLists = function (dom, element) { + global$5.each(global$5.grep(dom.select('ol,ul', element)), function (ul) { + normalizeList(dom, ul); + }); + }; + + var findNextCaretContainer = function (editor, rng, isForward, root) { + var node = rng.startContainer; + var offset = rng.startOffset; + if (isTextNode(node) && (isForward ? offset < node.data.length : offset > 0)) { + return node; + } + var nonEmptyBlocks = editor.schema.getNonEmptyElements(); + if (node.nodeType === 1) { + node = global$1.getNode(node, offset); + } + var walker = new global$2(node, root); + if (isForward) { + if (isBogusBr(editor.dom, node)) { + walker.next(); + } + } + while (node = walker[isForward ? 'next' : 'prev2']()) { + if (node.nodeName === 'LI' && !node.hasChildNodes()) { + return node; + } + if (nonEmptyBlocks[node.nodeName]) { + return node; + } + if (isTextNode(node) && node.data.length > 0) { + return node; + } + } + }; + var hasOnlyOneBlockChild = function (dom, elm) { + var childNodes = elm.childNodes; + return childNodes.length === 1 && !isListNode(childNodes[0]) && dom.isBlock(childNodes[0]); + }; + var unwrapSingleBlockChild = function (dom, elm) { + if (hasOnlyOneBlockChild(dom, elm)) { + dom.remove(elm.firstChild, true); + } + }; + var moveChildren = function (dom, fromElm, toElm) { + var node; + var targetElm = hasOnlyOneBlockChild(dom, toElm) ? toElm.firstChild : toElm; + unwrapSingleBlockChild(dom, fromElm); + if (!isEmpty(dom, fromElm, true)) { + while (node = fromElm.firstChild) { + targetElm.appendChild(node); + } + } + }; + var mergeLiElements = function (dom, fromElm, toElm) { + var listNode; + var ul = fromElm.parentNode; + if (!isChildOfBody(dom, fromElm) || !isChildOfBody(dom, toElm)) { + return; + } + if (isListNode(toElm.lastChild)) { + listNode = toElm.lastChild; + } + if (ul === toElm.lastChild) { + if (isBr(ul.previousSibling)) { + dom.remove(ul.previousSibling); + } + } + var node = toElm.lastChild; + if (node && isBr(node) && fromElm.hasChildNodes()) { + dom.remove(node); + } + if (isEmpty(dom, toElm, true)) { + dom.$(toElm).empty(); + } + moveChildren(dom, fromElm, toElm); + if (listNode) { + toElm.appendChild(listNode); + } + var contains = contains$1(SugarElement.fromDom(toElm), SugarElement.fromDom(fromElm)); + var nestedLists = contains ? dom.getParents(fromElm, isListNode, toElm) : []; + dom.remove(fromElm); + each(nestedLists, function (list) { + if (isEmpty(dom, list) && list !== dom.getRoot()) { + dom.remove(list); + } + }); + }; + var mergeIntoEmptyLi = function (editor, fromLi, toLi) { + editor.dom.$(toLi).empty(); + mergeLiElements(editor.dom, fromLi, toLi); + editor.selection.setCursorLocation(toLi); + }; + var mergeForward = function (editor, rng, fromLi, toLi) { + var dom = editor.dom; + if (dom.isEmpty(toLi)) { + mergeIntoEmptyLi(editor, fromLi, toLi); + } else { + var bookmark = createBookmark(rng); + mergeLiElements(dom, fromLi, toLi); + editor.selection.setRng(resolveBookmark(bookmark)); + } + }; + var mergeBackward = function (editor, rng, fromLi, toLi) { + var bookmark = createBookmark(rng); + mergeLiElements(editor.dom, fromLi, toLi); + var resolvedBookmark = resolveBookmark(bookmark); + editor.selection.setRng(resolvedBookmark); + }; + var backspaceDeleteFromListToListCaret = function (editor, isForward) { + var dom = editor.dom, selection = editor.selection; + var selectionStartElm = selection.getStart(); + var root = getClosestListRootElm(editor, selectionStartElm); + var li = dom.getParent(selection.getStart(), 'LI', root); + if (li) { + var ul = li.parentNode; + if (ul === editor.getBody() && isEmpty(dom, ul)) { + return true; + } + var rng_1 = normalizeRange(selection.getRng()); + var otherLi_1 = dom.getParent(findNextCaretContainer(editor, rng_1, isForward, root), 'LI', root); + if (otherLi_1 && otherLi_1 !== li) { + editor.undoManager.transact(function () { + if (isForward) { + mergeForward(editor, rng_1, otherLi_1, li); + } else { + if (isFirstChild(li)) { + outdentListSelection(editor); + } else { + mergeBackward(editor, rng_1, li, otherLi_1); + } + } + }); + return true; + } else if (!otherLi_1) { + if (!isForward && rng_1.startOffset === 0 && rng_1.endOffset === 0) { + editor.undoManager.transact(function () { + flattenListSelection(editor); + }); + return true; + } + } + } + return false; + }; + var removeBlock = function (dom, block, root) { + var parentBlock = dom.getParent(block.parentNode, dom.isBlock, root); + dom.remove(block); + if (parentBlock && dom.isEmpty(parentBlock)) { + dom.remove(parentBlock); + } + }; + var backspaceDeleteIntoListCaret = function (editor, isForward) { + var dom = editor.dom; + var selectionStartElm = editor.selection.getStart(); + var root = getClosestListRootElm(editor, selectionStartElm); + var block = dom.getParent(selectionStartElm, dom.isBlock, root); + if (block && dom.isEmpty(block)) { + var rng = normalizeRange(editor.selection.getRng()); + var otherLi_2 = dom.getParent(findNextCaretContainer(editor, rng, isForward, root), 'LI', root); + if (otherLi_2) { + editor.undoManager.transact(function () { + removeBlock(dom, block, root); + mergeWithAdjacentLists(dom, otherLi_2.parentNode); + editor.selection.select(otherLi_2, true); + editor.selection.collapse(isForward); + }); + return true; + } + } + return false; + }; + var backspaceDeleteCaret = function (editor, isForward) { + return backspaceDeleteFromListToListCaret(editor, isForward) || backspaceDeleteIntoListCaret(editor, isForward); + }; + var backspaceDeleteRange = function (editor) { + var selectionStartElm = editor.selection.getStart(); + var root = getClosestListRootElm(editor, selectionStartElm); + var startListParent = editor.dom.getParent(selectionStartElm, 'LI,DT,DD', root); + if (startListParent || getSelectedListItems(editor).length > 0) { + editor.undoManager.transact(function () { + editor.execCommand('Delete'); + normalizeLists(editor.dom, editor.getBody()); + }); + return true; + } + return false; + }; + var backspaceDelete = function (editor, isForward) { + return editor.selection.isCollapsed() ? backspaceDeleteCaret(editor, isForward) : backspaceDeleteRange(editor); + }; + var setup = function (editor) { + editor.on('keydown', function (e) { + if (e.keyCode === global$3.BACKSPACE) { + if (backspaceDelete(editor, false)) { + e.preventDefault(); + } + } else if (e.keyCode === global$3.DELETE) { + if (backspaceDelete(editor, true)) { + e.preventDefault(); + } + } + }); + }; + + var get$1 = function (editor) { + return { + backspaceDelete: function (isForward) { + backspaceDelete(editor, isForward); + } + }; + }; + + var open = function (editor) { + var dom = editor.dom; + var currentList = getParentList(editor); + if (!isOlNode(currentList)) { + return; + } + editor.windowManager.open({ + title: 'List Properties', + body: { + type: 'panel', + items: [{ + type: 'input', + name: 'start', + label: 'Start list at number', + inputMode: 'numeric' + }] + }, + initialData: { start: dom.getAttrib(currentList, 'start') || '1' }, + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true + } + ], + onSubmit: function (api) { + var data = api.getData(); + editor.undoManager.transact(function () { + dom.setAttrib(getParentList(editor), 'start', data.start === '1' ? '' : data.start); + }); + api.close(); + } + }); + }; + + var queryListCommandState = function (editor, listName) { + return function () { + var parentList = editor.dom.getParent(editor.selection.getStart(), 'UL,OL,DL'); + return parentList && parentList.nodeName === listName; + }; + }; + var register = function (editor) { + editor.on('BeforeExecCommand', function (e) { + var cmd = e.command.toLowerCase(); + if (cmd === 'indent') { + indentListSelection(editor); + } else if (cmd === 'outdent') { + outdentListSelection(editor); + } + }); + editor.addCommand('InsertUnorderedList', function (ui, detail) { + toggleList(editor, 'UL', detail); + }); + editor.addCommand('InsertOrderedList', function (ui, detail) { + toggleList(editor, 'OL', detail); + }); + editor.addCommand('InsertDefinitionList', function (ui, detail) { + toggleList(editor, 'DL', detail); + }); + editor.addCommand('RemoveList', function () { + flattenListSelection(editor); + }); + editor.addCommand('mceListProps', function () { + open(editor); + }); + editor.addQueryStateHandler('InsertUnorderedList', queryListCommandState(editor, 'UL')); + editor.addQueryStateHandler('InsertOrderedList', queryListCommandState(editor, 'OL')); + editor.addQueryStateHandler('InsertDefinitionList', queryListCommandState(editor, 'DL')); + }; + + var setupTabKey = function (editor) { + editor.on('keydown', function (e) { + if (e.keyCode !== global$3.TAB || global$3.metaKeyPressed(e)) { + return; + } + editor.undoManager.transact(function () { + if (e.shiftKey ? outdentListSelection(editor) : indentListSelection(editor)) { + e.preventDefault(); + } + }); + }); + }; + var setup$1 = function (editor) { + if (shouldIndentOnTab(editor)) { + setupTabKey(editor); + } + setup(editor); + }; + + var register$1 = function (editor) { + var exec = function (command) { + return function () { + return editor.execCommand(command); + }; + }; + if (!editor.hasPlugin('advlist')) { + editor.ui.registry.addToggleButton('numlist', { + icon: 'ordered-list', + active: false, + tooltip: 'Numbered list', + onAction: exec('InsertOrderedList'), + onSetup: function (api) { + return listState(editor, 'OL', api.setActive); + } + }); + editor.ui.registry.addToggleButton('bullist', { + icon: 'unordered-list', + active: false, + tooltip: 'Bullet list', + onAction: exec('InsertUnorderedList'), + onSetup: function (api) { + return listState(editor, 'UL', api.setActive); + } + }); + } + }; + + var register$2 = function (editor) { + var listProperties = { + text: 'List properties...', + icon: 'ordered-list', + onAction: function () { + return open(editor); + }, + onSetup: function (api) { + return listState(editor, 'OL', function (active) { + return api.setDisabled(!active); + }); + } + }; + editor.ui.registry.addMenuItem('listprops', listProperties); + editor.ui.registry.addContextMenu('lists', { + update: function (node) { + var parentList = getParentList(editor, node); + return isOlNode(parentList) ? ['listprops'] : []; + } + }); + }; + + function Plugin () { + global.add('lists', function (editor) { + if (editor.hasPlugin('rtc', true) === false) { + setup$1(editor); + register(editor); + } + register$1(editor); + register$2(editor); + return get$1(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/lists/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/lists/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..a6a7b66b310796087d71942ab0f2a73398b7897f --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/lists/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var e,n,t,r,o,i,u,a=tinymce.util.Tools.resolve("tinymce.PluginManager"),s=function(){},y=function(e){return function(){return e}},c=function(n){return function(e){return!n(e)}},f=y(!1),d=y(!0),l=function(){return m},m=(e=function(e){return e.isNone()},{fold:function(e,n){return e()},is:f,isSome:f,isNone:d,getOr:t=function(e){return e},getOrThunk:n=function(e){return e()},getOrDie:function(e){throw new Error(e||"error: getOrDie called on none.")},getOrNull:y(null),getOrUndefined:y(undefined),or:t,orThunk:n,map:l,each:s,bind:l,exists:f,forall:d,filter:l,equals:e,equals_:e,toArray:function(){return[]},toString:y("none()")}),p=function(t){var e=y(t),n=function(){return o},r=function(e){return e(t)},o={fold:function(e,n){return n(t)},is:function(e){return t===e},isSome:d,isNone:f,getOr:e,getOrThunk:e,getOrDie:e,getOrNull:e,getOrUndefined:e,or:n,orThunk:n,map:function(e){return p(e(t))},each:function(e){e(t)},bind:r,exists:r,forall:r,filter:function(e){return e(t)?o:m},toArray:function(){return[t]},toString:function(){return"some("+t+")"},equals:function(e){return e.is(t)},equals_:function(e,n){return e.fold(f,function(e){return n(t,e)})}};return o},g={some:p,none:l,from:function(e){return null===e||e===undefined?m:p(e)}},v=function(r){return function(e){return t=typeof(n=e),(null===n?"null":"object"==t&&(Array.prototype.isPrototypeOf(n)||n.constructor&&"Array"===n.constructor.name)?"array":"object"==t&&(String.prototype.isPrototypeOf(n)||n.constructor&&"String"===n.constructor.name)?"string":t)===r;var n,t}},h=function(n){return function(e){return typeof e===n}},S=v("string"),b=v("array"),C=h("boolean"),O=h("function"),N=h("number"),L=Array.prototype.slice,T=Array.prototype.push,D=function(e,n){for(var t=e.length,r=new Array(t),o=0;o=e.childNodes.length?t.data.length:0}:t.previousSibling&&je(t.previousSibling)?{container:t.previousSibling,offset:t.previousSibling.data.length}:t.nextSibling&&je(t.nextSibling)?{container:t.nextSibling,offset:0}:{container:e,offset:n}},un=function(e){var n=e.cloneRange(),t=on(e.startContainer,e.startOffset);n.setStart(t.container,t.offset);var r=on(e.endContainer,e.endOffset);return n.setEnd(r.container,r.offset),n},an=tinymce.util.Tools.resolve("tinymce.dom.DomQuery"),sn=function(e,n){var t=n||e.selection.getStart(!0);return e.dom.getParent(t,"OL,UL,DL",dn(e,t))},cn=function(e){var n,t,r,o=sn(e),i=e.selection.getSelectedBlocks();return r=i,(t=o)&&1===r.length&&r[0]===t?(n=o,Fe.grep(n.querySelectorAll("ol,ul,dl"),function(e){return qe(e)})):Fe.grep(i,function(e){return qe(e)&&o!==e})},fn=function(e){var t,n,r,o=e.selection.getSelectedBlocks();return Fe.grep((t=e,n=o,r=Fe.map(n,function(e){var n=t.dom.getParent(e,"li,dd,dt",dn(t,e));return n||e}),an.unique(r)),function(e){return We(e)})},dn=function(e,n){var t=e.dom.getParents(n,"TD,TH");return 0e.length?On:Cn)(t,e,n)},[]),R(r).map(function(e){return e.list}).toArray()},In=function(a,e,s){var n,t=En(e,(n=D(fn(a),le.fromDom),gn(E(n,c(Ln)),E(B(n),c(Ln)),function(e,n){return{start:e,end:n}})));k(t,function(e){var n,t;n=e.entries,t=s,k(w(n,Dn),function(e){return function(e,n){switch(e){case"Indent":n.depth++;break;case"Outdent":n.depth--;break;case"Flatten":n.depth=0}n.dirty=!0}(t,e),0});var r,o,i,u=(r=a,o=e.entries,P(function(e,n){if(0===e.length)return[];for(var t=n(e[0]),r=[],o=[],i=0,u=e.length;i 1) { + return protocolMatches[1] === 'www.' ? 'https://' : protocolMatches[1]; + } else { + return 'https://'; + } + }; + var getUrl = function (pattern, url) { + var protocol = getProtocol(url); + var match = pattern.regex.exec(url); + var newUrl = protocol + pattern.url; + var _loop_1 = function (i) { + newUrl = newUrl.replace('$' + i, function () { + return match[i] ? match[i] : ''; + }); + }; + for (var i = 0; i < match.length; i++) { + _loop_1(i); + } + return newUrl.replace(/\?$/, ''); + }; + var matchPattern = function (url) { + var patterns = urlPatterns.filter(function (pattern) { + return pattern.regex.test(url); + }); + if (patterns.length > 0) { + return global$1.extend({}, patterns[0], { url: getUrl(patterns[0], url) }); + } else { + return null; + } + }; + + var getIframeHtml = function (data) { + var allowFullscreen = data.allowFullscreen ? ' allowFullscreen="1"' : ''; + return ''; + }; + var getFlashHtml = function (data) { + var html = ''; + if (data.poster) { + html += ''; + } + html += ''; + return html; + }; + var getAudioHtml = function (data, audioTemplateCallback) { + if (audioTemplateCallback) { + return audioTemplateCallback(data); + } else { + return ''; + } + }; + var getVideoHtml = function (data, videoTemplateCallback) { + if (videoTemplateCallback) { + return videoTemplateCallback(data); + } else { + return ''; + } + }; + var getScriptHtml = function (data) { + return ''; + }; + var dataToHtml = function (editor, dataIn) { + var data = global$1.extend({}, dataIn); + if (!data.source) { + global$1.extend(data, htmlToData(getScripts(editor), data.embed)); + if (!data.source) { + return ''; + } + } + if (!data.altsource) { + data.altsource = ''; + } + if (!data.poster) { + data.poster = ''; + } + data.source = editor.convertURL(data.source, 'source'); + data.altsource = editor.convertURL(data.altsource, 'source'); + data.sourcemime = guess(data.source); + data.altsourcemime = guess(data.altsource); + data.poster = editor.convertURL(data.poster, 'poster'); + var pattern = matchPattern(data.source); + if (pattern) { + data.source = pattern.url; + data.type = pattern.type; + data.allowFullscreen = pattern.allowFullscreen; + data.width = data.width || String(pattern.w); + data.height = data.height || String(pattern.h); + } + if (data.embed) { + return updateHtml(data.embed, data, true); + } else { + var videoScript = getVideoScriptMatch(getScripts(editor), data.source); + if (videoScript) { + data.type = 'script'; + data.width = String(videoScript.width); + data.height = String(videoScript.height); + } + var audioTemplateCallback = getAudioTemplateCallback(editor); + var videoTemplateCallback = getVideoTemplateCallback(editor); + data.width = data.width || '300'; + data.height = data.height || '150'; + global$1.each(data, function (value, key) { + data[key] = editor.dom.encode('' + value); + }); + if (data.type === 'iframe') { + return getIframeHtml(data); + } else if (data.sourcemime === 'application/x-shockwave-flash') { + return getFlashHtml(data); + } else if (data.sourcemime.indexOf('audio') !== -1) { + return getAudioHtml(data, audioTemplateCallback); + } else if (data.type === 'script') { + return getScriptHtml(data); + } else { + return getVideoHtml(data, videoTemplateCallback); + } + } + }; + + var global$6 = tinymce.util.Tools.resolve('tinymce.util.Promise'); + + var cache = {}; + var embedPromise = function (data, dataToHtml, handler) { + return new global$6(function (res, rej) { + var wrappedResolve = function (response) { + if (response.html) { + cache[data.source] = response; + } + return res({ + url: data.source, + html: response.html ? response.html : dataToHtml(data) + }); + }; + if (cache[data.source]) { + wrappedResolve(cache[data.source]); + } else { + handler({ url: data.source }, wrappedResolve, rej); + } + }); + }; + var defaultPromise = function (data, dataToHtml) { + return new global$6(function (res) { + res({ + html: dataToHtml(data), + url: data.source + }); + }); + }; + var loadedData = function (editor) { + return function (data) { + return dataToHtml(editor, data); + }; + }; + var getEmbedHtml = function (editor, data) { + var embedHandler = getUrlResolver(editor); + return embedHandler ? embedPromise(data, loadedData(editor), embedHandler) : defaultPromise(data, loadedData(editor)); + }; + var isCached = function (url) { + return cache.hasOwnProperty(url); + }; + + var extractMeta = function (sourceInput, data) { + return get(data, sourceInput).bind(function (mainData) { + return get(mainData, 'meta'); + }); + }; + var getValue = function (data, metaData, sourceInput) { + return function (prop) { + var _a; + var getFromData = function () { + return get(data, prop); + }; + var getFromMetaData = function () { + return get(metaData, prop); + }; + var getNonEmptyValue = function (c) { + return get(c, 'value').bind(function (v) { + return v.length > 0 ? Optional.some(v) : Optional.none(); + }); + }; + var getFromValueFirst = function () { + return getFromData().bind(function (child) { + return isObject(child) ? getNonEmptyValue(child).orThunk(getFromMetaData) : getFromMetaData().orThunk(function () { + return Optional.from(child); + }); + }); + }; + var getFromMetaFirst = function () { + return getFromMetaData().orThunk(function () { + return getFromData().bind(function (child) { + return isObject(child) ? getNonEmptyValue(child) : Optional.from(child); + }); + }); + }; + return _a = {}, _a[prop] = (prop === sourceInput ? getFromValueFirst() : getFromMetaFirst()).getOr(''), _a; + }; + }; + var getDimensions = function (data, metaData) { + var dimensions = {}; + get(data, 'dimensions').each(function (dims) { + each([ + 'width', + 'height' + ], function (prop) { + get(metaData, prop).orThunk(function () { + return get(dims, prop); + }).each(function (value) { + return dimensions[prop] = value; + }); + }); + }); + return dimensions; + }; + var unwrap = function (data, sourceInput) { + var metaData = sourceInput ? extractMeta(sourceInput, data).getOr({}) : {}; + var get = getValue(data, metaData, sourceInput); + return __assign(__assign(__assign(__assign(__assign({}, get('source')), get('altsource')), get('poster')), get('embed')), getDimensions(data, metaData)); + }; + var wrap = function (data) { + var wrapped = __assign(__assign({}, data), { + source: { value: get(data, 'source').getOr('') }, + altsource: { value: get(data, 'altsource').getOr('') }, + poster: { value: get(data, 'poster').getOr('') } + }); + each([ + 'width', + 'height' + ], function (prop) { + get(data, prop).each(function (value) { + var dimensions = wrapped.dimensions || {}; + dimensions[prop] = value; + wrapped.dimensions = dimensions; + }); + }); + return wrapped; + }; + var handleError = function (editor) { + return function (error) { + var errorMessage = error && error.msg ? 'Media embed handler error: ' + error.msg : 'Media embed handler threw unknown error.'; + editor.notificationManager.open({ + type: 'error', + text: errorMessage + }); + }; + }; + var snippetToData = function (editor, embedSnippet) { + return htmlToData(getScripts(editor), embedSnippet); + }; + var isMediaElement = function (element) { + return element.getAttribute('data-mce-object') || element.getAttribute('data-ephox-embed-iri'); + }; + var getEditorData = function (editor) { + var element = editor.selection.getNode(); + var snippet = isMediaElement(element) ? editor.serializer.serialize(element, { selection: true }) : ''; + return __assign({ embed: snippet }, htmlToData(getScripts(editor), snippet)); + }; + var addEmbedHtml = function (api, editor) { + return function (response) { + if (isString(response.url) && response.url.trim().length > 0) { + var html = response.html; + var snippetData = snippetToData(editor, html); + var nuData = __assign(__assign({}, snippetData), { + source: response.url, + embed: html + }); + api.setData(wrap(nuData)); + } + }; + }; + var selectPlaceholder = function (editor, beforeObjects) { + var afterObjects = editor.dom.select('img[data-mce-object]'); + for (var i = 0; i < beforeObjects.length; i++) { + for (var y = afterObjects.length - 1; y >= 0; y--) { + if (beforeObjects[i] === afterObjects[y]) { + afterObjects.splice(y, 1); + } + } + } + editor.selection.select(afterObjects[0]); + }; + var handleInsert = function (editor, html) { + var beforeObjects = editor.dom.select('img[data-mce-object]'); + editor.insertContent(html); + selectPlaceholder(editor, beforeObjects); + editor.nodeChanged(); + }; + var submitForm = function (prevData, newData, editor) { + newData.embed = updateHtml(newData.embed, newData); + if (newData.embed && (prevData.source === newData.source || isCached(newData.source))) { + handleInsert(editor, newData.embed); + } else { + getEmbedHtml(editor, newData).then(function (response) { + handleInsert(editor, response.html); + }).catch(handleError(editor)); + } + }; + var showDialog = function (editor) { + var editorData = getEditorData(editor); + var currentData = Cell(editorData); + var initialData = wrap(editorData); + var handleSource = function (prevData, api) { + var serviceData = unwrap(api.getData(), 'source'); + if (prevData.source !== serviceData.source) { + addEmbedHtml(win, editor)({ + url: serviceData.source, + html: '' + }); + getEmbedHtml(editor, serviceData).then(addEmbedHtml(win, editor)).catch(handleError(editor)); + } + }; + var handleEmbed = function (api) { + var data = unwrap(api.getData()); + var dataFromEmbed = snippetToData(editor, data.embed); + api.setData(wrap(dataFromEmbed)); + }; + var handleUpdate = function (api, sourceInput) { + var data = unwrap(api.getData(), sourceInput); + var embed = dataToHtml(editor, data); + api.setData(wrap(__assign(__assign({}, data), { embed: embed }))); + }; + var mediaInput = [{ + name: 'source', + type: 'urlinput', + filetype: 'media', + label: 'Source' + }]; + var sizeInput = !hasDimensions(editor) ? [] : [{ + type: 'sizeinput', + name: 'dimensions', + label: 'Constrain proportions', + constrain: true + }]; + var generalTab = { + title: 'General', + name: 'general', + items: flatten([ + mediaInput, + sizeInput + ]) + }; + var embedTextarea = { + type: 'textarea', + name: 'embed', + label: 'Paste your embed code below:' + }; + var embedTab = { + title: 'Embed', + items: [embedTextarea] + }; + var advancedFormItems = []; + if (hasAltSource(editor)) { + advancedFormItems.push({ + name: 'altsource', + type: 'urlinput', + filetype: 'media', + label: 'Alternative source URL' + }); + } + if (hasPoster(editor)) { + advancedFormItems.push({ + name: 'poster', + type: 'urlinput', + filetype: 'image', + label: 'Media poster (Image URL)' + }); + } + var advancedTab = { + title: 'Advanced', + name: 'advanced', + items: advancedFormItems + }; + var tabs = [ + generalTab, + embedTab + ]; + if (advancedFormItems.length > 0) { + tabs.push(advancedTab); + } + var body = { + type: 'tabpanel', + tabs: tabs + }; + var win = editor.windowManager.open({ + title: 'Insert/Edit Media', + size: 'normal', + body: body, + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true + } + ], + onSubmit: function (api) { + var serviceData = unwrap(api.getData()); + submitForm(currentData.get(), serviceData, editor); + api.close(); + }, + onChange: function (api, detail) { + switch (detail.name) { + case 'source': + handleSource(currentData.get(), api); + break; + case 'embed': + handleEmbed(api); + break; + case 'dimensions': + case 'altsource': + case 'poster': + handleUpdate(api, detail.name); + break; + } + currentData.set(unwrap(api.getData())); + }, + initialData: initialData + }); + }; + + var get$1 = function (editor) { + var showDialog$1 = function () { + showDialog(editor); + }; + return { showDialog: showDialog$1 }; + }; + + var register = function (editor) { + var showDialog$1 = function () { + showDialog(editor); + }; + editor.addCommand('mceMedia', showDialog$1); + }; + + var global$7 = tinymce.util.Tools.resolve('tinymce.html.Node'); + + var global$8 = tinymce.util.Tools.resolve('tinymce.Env'); + + var sanitize = function (editor, html) { + if (shouldFilterHtml(editor) === false) { + return html; + } + var writer = global$5(); + var blocked; + global$3({ + validate: false, + allow_conditional_comments: false, + comment: function (text) { + writer.comment(text); + }, + cdata: function (text) { + writer.cdata(text); + }, + text: function (text, raw) { + writer.text(text, raw); + }, + start: function (name, attrs, empty) { + blocked = true; + if (name === 'script' || name === 'noscript' || name === 'svg') { + return; + } + for (var i = attrs.length - 1; i >= 0; i--) { + var attrName = attrs[i].name; + if (attrName.indexOf('on') === 0) { + delete attrs.map[attrName]; + attrs.splice(i, 1); + } + if (attrName === 'style') { + attrs[i].value = editor.dom.serializeStyle(editor.dom.parseStyle(attrs[i].value), name); + } + } + writer.start(name, attrs, empty); + blocked = false; + }, + end: function (name) { + if (blocked) { + return; + } + writer.end(name); + } + }, global$4({})).parse(html); + return writer.getContent(); + }; + + var createPlaceholderNode = function (editor, node) { + var name = node.name; + var placeHolder = new global$7('img', 1); + placeHolder.shortEnded = true; + retainAttributesAndInnerHtml(editor, node, placeHolder); + placeHolder.attr({ + 'width': node.attr('width') || '300', + 'height': node.attr('height') || (name === 'audio' ? '30' : '150'), + 'style': node.attr('style'), + 'src': global$8.transparentSrc, + 'data-mce-object': name, + 'class': 'mce-object mce-object-' + name + }); + return placeHolder; + }; + var createPreviewIframeNode = function (editor, node) { + var name = node.name; + var previewWrapper = new global$7('span', 1); + previewWrapper.attr({ + 'contentEditable': 'false', + 'style': node.attr('style'), + 'data-mce-object': name, + 'class': 'mce-preview-object mce-object-' + name + }); + retainAttributesAndInnerHtml(editor, node, previewWrapper); + var previewNode = new global$7(name, 1); + previewNode.attr({ + src: node.attr('src'), + allowfullscreen: node.attr('allowfullscreen'), + style: node.attr('style'), + class: node.attr('class'), + width: node.attr('width'), + height: node.attr('height'), + frameborder: '0' + }); + var shimNode = new global$7('span', 1); + shimNode.attr('class', 'mce-shim'); + previewWrapper.append(previewNode); + previewWrapper.append(shimNode); + return previewWrapper; + }; + var retainAttributesAndInnerHtml = function (editor, sourceNode, targetNode) { + var attrName; + var attrValue; + var ai; + var attribs = sourceNode.attributes; + ai = attribs.length; + while (ai--) { + attrName = attribs[ai].name; + attrValue = attribs[ai].value; + if (attrName !== 'width' && attrName !== 'height' && attrName !== 'style') { + if (attrName === 'data' || attrName === 'src') { + attrValue = editor.convertURL(attrValue, attrName); + } + targetNode.attr('data-mce-p-' + attrName, attrValue); + } + } + var innerHtml = sourceNode.firstChild && sourceNode.firstChild.value; + if (innerHtml) { + targetNode.attr('data-mce-html', escape(sanitize(editor, innerHtml))); + targetNode.firstChild = null; + } + }; + var isPageEmbedWrapper = function (node) { + var nodeClass = node.attr('class'); + return nodeClass && /\btiny-pageembed\b/.test(nodeClass); + }; + var isWithinEmbedWrapper = function (node) { + while (node = node.parent) { + if (node.attr('data-ephox-embed-iri') || isPageEmbedWrapper(node)) { + return true; + } + } + return false; + }; + var placeHolderConverter = function (editor) { + return function (nodes) { + var i = nodes.length; + var node; + var videoScript; + while (i--) { + node = nodes[i]; + if (!node.parent) { + continue; + } + if (node.parent.attr('data-mce-object')) { + continue; + } + if (node.name === 'script') { + videoScript = getVideoScriptMatch(getScripts(editor), node.attr('src')); + if (!videoScript) { + continue; + } + } + if (videoScript) { + if (videoScript.width) { + node.attr('width', videoScript.width.toString()); + } + if (videoScript.height) { + node.attr('height', videoScript.height.toString()); + } + } + if (node.name === 'iframe' && hasLiveEmbeds(editor) && global$8.ceFalse) { + if (!isWithinEmbedWrapper(node)) { + node.replace(createPreviewIframeNode(editor, node)); + } + } else { + if (!isWithinEmbedWrapper(node)) { + node.replace(createPlaceholderNode(editor, node)); + } + } + } + }; + }; + + var setup = function (editor) { + editor.on('preInit', function () { + var specialElements = editor.schema.getSpecialElements(); + global$1.each('video audio iframe object'.split(' '), function (name) { + specialElements[name] = new RegExp(']*>', 'gi'); + }); + var boolAttrs = editor.schema.getBoolAttrs(); + global$1.each('webkitallowfullscreen mozallowfullscreen allowfullscreen'.split(' '), function (name) { + boolAttrs[name] = {}; + }); + editor.parser.addNodeFilter('iframe,video,audio,object,embed,script', placeHolderConverter(editor)); + editor.serializer.addAttributeFilter('data-mce-object', function (nodes, name) { + var i = nodes.length; + var node; + var realElm; + var ai; + var attribs; + var innerHtml; + var innerNode; + var realElmName; + var className; + while (i--) { + node = nodes[i]; + if (!node.parent) { + continue; + } + realElmName = node.attr(name); + realElm = new global$7(realElmName, 1); + if (realElmName !== 'audio' && realElmName !== 'script') { + className = node.attr('class'); + if (className && className.indexOf('mce-preview-object') !== -1) { + realElm.attr({ + width: node.firstChild.attr('width'), + height: node.firstChild.attr('height') + }); + } else { + realElm.attr({ + width: node.attr('width'), + height: node.attr('height') + }); + } + } + realElm.attr({ style: node.attr('style') }); + attribs = node.attributes; + ai = attribs.length; + while (ai--) { + var attrName = attribs[ai].name; + if (attrName.indexOf('data-mce-p-') === 0) { + realElm.attr(attrName.substr(11), attribs[ai].value); + } + } + if (realElmName === 'script') { + realElm.attr('type', 'text/javascript'); + } + innerHtml = node.attr('data-mce-html'); + if (innerHtml) { + innerNode = new global$7('#text', 3); + innerNode.raw = true; + innerNode.value = sanitize(editor, unescape(innerHtml)); + realElm.append(innerNode); + } + node.replace(realElm); + } + }); + }); + editor.on('SetContent', function () { + editor.$('span.mce-preview-object').each(function (index, elm) { + var $elm = editor.$(elm); + if ($elm.find('span.mce-shim').length === 0) { + $elm.append(''); + } + }); + }); + }; + + var setup$1 = function (editor) { + editor.on('ResolveName', function (e) { + var name; + if (e.target.nodeType === 1 && (name = e.target.getAttribute('data-mce-object'))) { + e.name = name; + } + }); + }; + + var setup$2 = function (editor) { + editor.on('click keyup touchend', function () { + var selectedNode = editor.selection.getNode(); + if (selectedNode && editor.dom.hasClass(selectedNode, 'mce-preview-object')) { + if (editor.dom.getAttrib(selectedNode, 'data-mce-selected')) { + selectedNode.setAttribute('data-mce-selected', '2'); + } + } + }); + editor.on('ObjectSelected', function (e) { + var objectType = e.target.getAttribute('data-mce-object'); + if (objectType === 'audio' || objectType === 'script') { + e.preventDefault(); + } + }); + editor.on('ObjectResized', function (e) { + var target = e.target; + var html; + if (target.getAttribute('data-mce-object')) { + html = target.getAttribute('data-mce-html'); + if (html) { + html = unescape(html); + target.setAttribute('data-mce-html', escape(updateHtml(html, { + width: String(e.width), + height: String(e.height) + }))); + } + } + }); + }; + + var stateSelectorAdapter = function (editor, selector) { + return function (buttonApi) { + return editor.selection.selectorChangedWithUnbind(selector.join(','), buttonApi.setActive).unbind; + }; + }; + var register$1 = function (editor) { + editor.ui.registry.addToggleButton('media', { + tooltip: 'Insert/edit media', + icon: 'embed', + onAction: function () { + editor.execCommand('mceMedia'); + }, + onSetup: stateSelectorAdapter(editor, [ + 'img[data-mce-object]', + 'span[data-mce-object]', + 'div[data-ephox-embed-iri]' + ]) + }); + editor.ui.registry.addMenuItem('media', { + icon: 'embed', + text: 'Media...', + onAction: function () { + editor.execCommand('mceMedia'); + } + }); + }; + + function Plugin () { + global.add('media', function (editor) { + register(editor); + register$1(editor); + setup$1(editor); + setup(editor); + setup$2(editor); + return get$1(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/media/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/media/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..a540a82b34388c9fa5a9475406a328202c711975 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/media/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var e,t,r,n=tinymce.util.Tools.resolve("tinymce.PluginManager"),p=function(){return(p=Object.assign||function(e){for(var t,r=1,n=arguments.length;r"):"application/x-shockwave-flash"===n.sourcemime?(l='',s.poster&&(l+=''),l+=""):-1!==n.sourcemime.indexOf("audio")?(c=n,(u=h)?u(c):'"):"script"===n.type?' '; + var directionality = editor.getBody().dir; + var dirAttr = directionality ? ' dir="' + encode(directionality) + '"' : ''; + var previewHtml = '' + '' + '' + headHtml + '' + '' + editor.getContent() + preventClicksOnLinksScript + '' + ''; + return previewHtml; + }; + + var open = function (editor) { + var content = getPreviewHtml(editor); + var dataApi = editor.windowManager.open({ + title: 'Preview', + size: 'large', + body: { + type: 'panel', + items: [{ + name: 'preview', + type: 'iframe', + sandboxed: true + }] + }, + buttons: [{ + type: 'cancel', + name: 'close', + text: 'Close', + primary: true + }], + initialData: { preview: content } + }); + dataApi.focus('close'); + }; + + var register = function (editor) { + editor.addCommand('mcePreview', function () { + open(editor); + }); + }; + + var register$1 = function (editor) { + editor.ui.registry.addButton('preview', { + icon: 'preview', + tooltip: 'Preview', + onAction: function () { + return editor.execCommand('mcePreview'); + } + }); + editor.ui.registry.addMenuItem('preview', { + icon: 'preview', + text: 'Preview', + onAction: function () { + return editor.execCommand('mcePreview'); + } + }); + }; + + function Plugin () { + global.add('preview', function (editor) { + register(editor); + register$1(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/preview/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/preview/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..861aacf59af4bf803f2b1126669594921721fdfa --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/preview/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),f=tinymce.util.Tools.resolve("tinymce.Env"),w=tinymce.util.Tools.resolve("tinymce.util.Tools"),i=function(e){var t=function(t){var n="",i=t.dom.encode,e=t.getParam("content_style","","string");n+='',e&&(n+='");var o=t.getParam("content_css_cors",!1,"boolean")?' crossorigin="anonymous"':"";w.each(t.contentCSS,function(e){n+='"});var r,a,c,s,d,m,l,y=-1===(s=(r=t).getParam("body_id","tinymce","string")).indexOf("=")?s:(c=(a=r).getParam("body_id","","hash"))[a.id]||c,u=-1===(l=(d=t).getParam("body_class","","string")).indexOf("=")?l:(m=d).getParam("body_class","","hash")[m.id]||"",v=' '; + var directionality = editor.getBody().dir; + var dirAttr = directionality ? ' dir="' + encode(directionality) + '"' : ''; + html = '' + '' + '' + '' + contentCssEntries_1 + preventClicksOnLinksScript + '' + '' + html + '' + ''; + } + return replaceTemplateValues(html, getPreviewReplaceValues(editor)); + }; + var open = function (editor, templateList) { + var createTemplates = function () { + if (!templateList || templateList.length === 0) { + var message = editor.translate('No templates defined.'); + editor.notificationManager.open({ + text: message, + type: 'info' + }); + return Optional.none(); + } + return Optional.from(global$1.map(templateList, function (template, index) { + var isUrlTemplate = function (t) { + return t.url !== undefined; + }; + return { + selected: index === 0, + text: template.title, + value: { + url: isUrlTemplate(template) ? Optional.from(template.url) : Optional.none(), + content: !isUrlTemplate(template) ? Optional.from(template.content) : Optional.none(), + description: template.description + } + }; + })); + }; + var createSelectBoxItems = function (templates) { + return map(templates, function (t) { + return { + text: t.text, + value: t.text + }; + }); + }; + var findTemplate = function (templates, templateTitle) { + return find(templates, function (t) { + return t.text === templateTitle; + }); + }; + var loadFailedAlert = function (api) { + editor.windowManager.alert('Could not load the specified template.', function () { + return api.focus('template'); + }); + }; + var getTemplateContent = function (t) { + return new global$4(function (resolve, reject) { + t.value.url.fold(function () { + return resolve(t.value.content.getOr('')); + }, function (url) { + return global$2.send({ + url: url, + success: function (html) { + resolve(html); + }, + error: function (e) { + reject(e); + } + }); + }); + }); + }; + var onChange = function (templates, updateDialog) { + return function (api, change) { + if (change.name === 'template') { + var newTemplateTitle = api.getData().template; + findTemplate(templates, newTemplateTitle).each(function (t) { + api.block('Loading...'); + getTemplateContent(t).then(function (previewHtml) { + updateDialog(api, t, previewHtml); + }).catch(function () { + updateDialog(api, t, ''); + api.disable('save'); + loadFailedAlert(api); + }); + }); + } + }; + }; + var onSubmit = function (templates) { + return function (api) { + var data = api.getData(); + findTemplate(templates, data.template).each(function (t) { + getTemplateContent(t).then(function (previewHtml) { + insertTemplate(editor, false, previewHtml); + api.close(); + }).catch(function () { + api.disable('save'); + loadFailedAlert(api); + }); + }); + }; + }; + var openDialog = function (templates) { + var selectBoxItems = createSelectBoxItems(templates); + var buildDialogSpec = function (bodyItems, initialData) { + return { + title: 'Insert Template', + size: 'large', + body: { + type: 'panel', + items: bodyItems + }, + initialData: initialData, + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true + } + ], + onSubmit: onSubmit(templates), + onChange: onChange(templates, updateDialog) + }; + }; + var updateDialog = function (dialogApi, template, previewHtml) { + var content = getPreviewContent(editor, previewHtml); + var bodyItems = [ + { + type: 'selectbox', + name: 'template', + label: 'Templates', + items: selectBoxItems + }, + { + type: 'htmlpanel', + html: '

                                                                                          ' + htmlEscape(template.value.description) + '

                                                                                          ' + }, + { + label: 'Preview', + type: 'iframe', + name: 'preview', + sandboxed: false + } + ]; + var initialData = { + template: template.text, + preview: content + }; + dialogApi.unblock(); + dialogApi.redial(buildDialogSpec(bodyItems, initialData)); + dialogApi.focus('template'); + }; + var dialogApi = editor.windowManager.open(buildDialogSpec([], { + template: '', + preview: '' + })); + dialogApi.block('Loading...'); + getTemplateContent(templates[0]).then(function (previewHtml) { + updateDialog(dialogApi, templates[0], previewHtml); + }).catch(function () { + updateDialog(dialogApi, templates[0], ''); + dialogApi.disable('save'); + loadFailedAlert(dialogApi); + }); + }; + var optTemplates = createTemplates(); + optTemplates.each(openDialog); + }; + + var showDialog = function (editor) { + return function (templates) { + open(editor, templates); + }; + }; + var register$1 = function (editor) { + editor.ui.registry.addButton('template', { + icon: 'template', + tooltip: 'Insert template', + onAction: createTemplateList(editor, showDialog(editor)) + }); + editor.ui.registry.addMenuItem('template', { + icon: 'template', + text: 'Insert template...', + onAction: createTemplateList(editor, showDialog(editor)) + }); + }; + + function Plugin () { + global.add('template', function (editor) { + register$1(editor); + register(editor); + setup(editor); + }); + } + + Plugin(); + +}()); diff --git a/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/template/plugin.min.js b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/template/plugin.min.js new file mode 100644 index 0000000000000000000000000000000000000000..d6bda48bdcd77c9a317a9472d245db537689673b --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/component/pear/module/tinymce/tinymce/plugins/template/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.6.2 (2020-12-08) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(){},o=function(e){return function(){return e}};var n,r,a,c=o(!1),u=o(!0),_=tinymce.util.Tools.resolve("tinymce.util.Tools"),s=tinymce.util.Tools.resolve("tinymce.util.XHR"),i=function(e){return e.getParam("template_mdate_classes","mdate")},l=function(e){return e.getParam("template_replace_values")},f=function(e){return e.getParam("template_mdate_format",e.translate("%Y-%m-%d"))},m=function(e,t){if((e=""+e).length":">","&":"&","'":"'"},N=function(e){return e.replace(/["'<>&]/g,function(e){return(A(t=C,n=e)?O.from(t[n]):O.none()).getOr(e);var t,n})},I=function(M,t){var e=function(e){return function(e,t){for(var n=e.length,r=new Array(n),a=0;a")&&(o="",(c=r.getParam("content_style","","string"))&&(o+='"),u=r.getParam("content_css_cors",!1,"boolean")?' crossorigin="anonymous"':"",_.each(r.contentCSS,function(e){o+='"}),i=-1===(g=(p=r).getParam("body_class","","string")).indexOf("=")?g:(d=p).getParam("body_class","","hash")[d.id]||"",l=r.dom.encode,s=' + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/console/console2.html b/demo/webman/backend/plugin/admin/public/demos/console/console2.html new file mode 100644 index 0000000000000000000000000000000000000000..a2f4a7c423938f357c77e0b9f4d648b7a8ed54df --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/console/console2.html @@ -0,0 +1,502 @@ + + + + + 数据分析 + + + + + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 快捷菜单 +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + 主页 +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + 弹层 +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + 聊天 +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + 相机 +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + 表单 +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + 安全 +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + 公告 +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + 更多 +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 代办任务 +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          待审评论
                                                                                          +
                                                                                          21
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          待审帖子
                                                                                          +
                                                                                          32
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          待审文章
                                                                                          +
                                                                                          14
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          待审用户
                                                                                          +
                                                                                          63
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 使用记录 +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          留言板
                                                                                          +
                                                                                          +
                                                                                            +
                                                                                          • +

                                                                                            要不要作为我的家人,搬来我家。

                                                                                            + 12月25日 19:92 + 回复 +
                                                                                          • +
                                                                                          • +

                                                                                            快乐的时候不敢尽兴,频繁警戒自己保持清醒。

                                                                                            + 4月30日 22:43 + 回复 +
                                                                                          • +
                                                                                          • +

                                                                                            夏天真的来了,尽管它还有些犹豫。

                                                                                            + 4月30日 22:43 + 回复 +
                                                                                          • +
                                                                                          • +

                                                                                            看似不可达到的高度,只要坚持不懈就可能到达。

                                                                                            + 4月30日 22:43 + 回复 +
                                                                                          • +
                                                                                          • +

                                                                                            当浑浊变成了一种常态,那么清白就成了一种罪过。

                                                                                            + 4月30日 22:43 + 回复 +
                                                                                          • +
                                                                                          • +

                                                                                            那是一种内在的东西,他们到达不了,也无法触及!

                                                                                            + 5月12日 01:25 + 回复 +
                                                                                          • + +
                                                                                          • +

                                                                                            希望是一个好东西,也许是最好的,好东西是不会消亡的!

                                                                                            + 6月11日 15:33 + 回复 +
                                                                                          • +
                                                                                          • +

                                                                                            一切都在不可避免的走向庸俗。

                                                                                            + 2月09日 13:40 + 回复 +
                                                                                          • +
                                                                                          • +

                                                                                            路上没有灯火的时候,就点亮自己的头颅。

                                                                                            + 3月11日 12:30 + 回复 +
                                                                                          • + +
                                                                                          • +

                                                                                            我们应该不虚度一生,应该能够说:"我已经做了我能做的事。"

                                                                                            + 4月30日 22:43 + 回复 +
                                                                                          • + +
                                                                                          • +

                                                                                            接近,是我对一切的态度,是我对一切态度的距离

                                                                                            + 6月11日 15:33 + 回复 +
                                                                                          • +
                                                                                          • +

                                                                                            没有锚的船当然也可以航行,只是紧张充满你的一生。

                                                                                            + 2月09日 13:40 + 回复 +
                                                                                          • +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/css/avatar.jpg b/demo/webman/backend/plugin/admin/public/demos/css/avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..206a8b6c2def8679090c377e433a185dc92c501b Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/demos/css/avatar.jpg differ diff --git a/demo/webman/backend/plugin/admin/public/demos/css/console1.css b/demo/webman/backend/plugin/admin/public/demos/css/console1.css new file mode 100644 index 0000000000000000000000000000000000000000..e175df84c47abe09f33b48fdab50c258d07cb4cf --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/css/console1.css @@ -0,0 +1,141 @@ +.top-panel { + border-radius: 4px; + text-align: center; +} + +.top-panel>.layui-card-body { + height: 60px; +} + +.top-panel-number { + line-height: 60px; + font-size: 29px; + border-right: 1px solid #eceff9; +} + +.top-panel-tips { + padding-left: 8px; + padding-top: 16px; + line-height: 30px; + font-size: 12px; +} + +.pear-container { + background-color: whitesmoke; + margin: 10px; +} + +.card { + width: 100%; + height: 160px; + background-color: whitesmoke; + border-radius: 4px; +} + +.card .header .avatar { + width: 28px; + height: 28px; + margin: 20px; + border-radius: 50px; +} + +.card .header { + color: dimgray; +} + +.card .body { + color: gray; +} + +.card .body { + margin-left: 20px; + margin-right: 20px; +} + +.card .footer { + margin-left: 20px; + margin-right: 20px; + margin-top: 20px; + font-size: 13px; + color: gray; + position: absolute; +} + +.custom-tab .layui-tab-title { + border-bottom-width: 0px; + border-bottom-style: none; +} + +.custom-tab .layui-tab-title li { + margin-left: 10px; +} + +.list .list-item { + height: 31.8px; + line-height: 31.8px; + color: gray; + padding: 5px; + padding-left: 15px; + border-radius: 4px; + margin-top: 5.2px; +} + +.list .list-item:hover { + background-color: whitesmoke; +} + +.list .list-item .title { + font-size: 13px; + width: 100%; +} + +.list .list-item .footer { + position: absolute; + right: 30px; + font-size: 12px; +} + +.top-panel-tips i { + font-size: 33px; +} + +.layuiadmin-card-status { + padding: 0 10px 10px; +} + +.layuiadmin-card-status dd { + padding: 15px 0; + border-bottom: 1px solid #EEE; + display: -webkit-flex; + display: flex; +} + +.layuiadmin-card-status dd div.layui-status-img, +.layuiadmin-card-team .layui-team-img { + width: 32px; + height: 32px; + border-radius: 50%; + margin-right: 15px; +} + +.layuiadmin-card-status dd div.layui-status-img a { + width: 100%; + height: 100%; + display: inline-block; + text-align: center; + line-height: 32px; +} + +.layuiadmin-card-status dd div span { + color: #BBB; +} + +.layuiadmin-card-status dd div a { + color: #01AAED; +} + +.top-panel-tips svg { + margin-top: -12px; + width: 50px; + height: 50px; +} diff --git a/demo/webman/backend/plugin/admin/public/demos/css/console2.css b/demo/webman/backend/plugin/admin/public/demos/css/console2.css new file mode 100644 index 0000000000000000000000000000000000000000..4aaa7e5113af0db16132c5ba96273476a2ede19e --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/css/console2.css @@ -0,0 +1,121 @@ +.pear-container { + background-color: whitesmoke; + margin: 10px; +} + +.pear-card { + width: 100%; + height: 66px; + background-color: #F8F8F8; + display: inline-block; + border-radius: 5px; + text-align: center; + margin-bottom: 3px; +} + +.pear-card:hover, +.pear-card2:hover { + box-shadow: 2px 0 8px 0 lightgray !important; +} + +.pear-card2 { + width: 100%; + height: 90px; + background-color: #F8F8F8; + display: inline-block; + border-radius: 5px; + text-align: center; + margin-bottom: 3px; +} + +.pear-card2 i { + font-size: 30px; + height: 90px; + line-height: 90px; +} + +.pear-card i { + font-size: 30px; + height: 66px; + line-height: 66px; +} + +.layui-col-md3 { + text-align: center; +} + +.pear-card-title { + margin-top: 3px; +} + +.person img { + width: 90px; + height: 90px; + border-radius: 4px; + margin-top: 8px; + margin-left: 8px; +} + +.pear-card2 .count { + color: #51A351; + font-size: 30px; + margin-top: 12px; +} + +.pear-card2 .title { + color: gray; + font-size: 14px; + margin-top: 14px; +} + +.pear-card-status { + padding: 0 10px 10px; +} + +.pear-card-status li { + position: relative; + padding: 10px 0; + border-bottom: 1px solid #EEE; +} + +.pear-card-status li h3 { + padding-bottom: 5px; + font-weight: 700; +} + +.pear-card-status li p { + padding-bottom: 10px; + padding-top: 3px; +} + +.pear-card-status li>span { + color: #999; + height: 24px; + line-height: 24px; +} + +.pear-reply { + position: absolute; + right: 20px; + bottom: 12px; + height: 24px; + line-height: 24px; +} + +.person .title { + font-size: 17px; + font-weight: 600; + margin-left: 18px; + margin-top: 16px; + position: absolute; + display: inline-block; +} + +.person .desc { + font-size: 16px; + font-weight: 600; + margin-left: 115px; + margin-top: -30px; + position: absolute; + display: inline-block; +} diff --git a/demo/webman/backend/plugin/admin/public/demos/css/department.css b/demo/webman/backend/plugin/admin/public/demos/css/department.css new file mode 100644 index 0000000000000000000000000000000000000000..d6898b7d2ef797cd9c989fc7696ae6f68bcb0c00 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/css/department.css @@ -0,0 +1,6 @@ +.organizationTree { + width: 100% !important; + height: -webkit-calc(100vh - 130px); + height: -moz-calc(100vh - 130px); + height: calc(100vh - 130px); +} diff --git a/demo/webman/backend/plugin/admin/public/demos/css/error.css b/demo/webman/backend/plugin/admin/public/demos/css/error.css new file mode 100644 index 0000000000000000000000000000000000000000..37d4c0e667fa8e89d426f1a527a80613c86786fb --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/css/error.css @@ -0,0 +1,76 @@ +* { + padding: 0; + margin: 0; + font-size: 0.38rem; +} + +ul { + list-style: none; +} + +a { + text-decoration: none; + -webkit-tap-highlight-color: transparent +} + +.clearfix:after { + content: ''; + width: 0; + height: 0; + display: block; + clear: both; +} + +html { + height: 100%; + width: 100%; +} + +body { + font-size: 0.28rem; + height: 100%; + width: 100%; + display: flex; + flex-direction: column; + position: relative; + background-color: white !important; +} + +.content { + position: absolute; + top: 50%; + transform: translateY(-50%); + width: 100%; + text-align: center; +} + +.content>img { + height: 300px; + max-width: 370px; + margin-right: 180px; +} + +.content>* { + display: inline-block; +} + +.content-r { + vertical-align: top; +} + +.content-r>h1 { + font-size: 72px; + color: #434e59; + margin-bottom: 24px; + font-weight: 600; +} + +.content-r>p { + font-size: 20px; + color: rgba(0, 0, 0, .45); + margin-bottom: 16px; +} + +button { + margin-top: 20px; +} diff --git a/demo/webman/backend/plugin/admin/public/demos/css/icon.css b/demo/webman/backend/plugin/admin/public/demos/css/icon.css new file mode 100644 index 0000000000000000000000000000000000000000..cd1a6ce30a065a044d6c0e81da136582c72d08a1 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/css/icon.css @@ -0,0 +1,531 @@ +/* Logo 字体 */ +@font-face { + font-family: "iconfont logo"; + src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); + src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); +} + +.logo { + font-family: "iconfont logo"; + font-size: 160px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* tabs */ +.nav-tabs { + position: relative; +} + +.nav-tabs .nav-more { + position: absolute; + right: 0; + bottom: 0; + height: 42px; + line-height: 42px; + color: #666; +} + +#tabs { + border-bottom: 1px solid #eee; +} + +#tabs li { + cursor: pointer; + width: 100px; + height: 40px; + line-height: 40px; + text-align: center; + font-size: 16px; + border-bottom: 2px solid transparent; + position: relative; + z-index: 1; + margin-bottom: -1px; + color: #666; +} + + +#tabs .active { + border-bottom-color: #f00; + color: #222; +} + +.tab-container .content { + display: none; +} + +/* 页面布局 */ +.main { + padding: 30px 100px; + width: 960px; + margin: 0 auto; +} + +.main .logo { + color: #333; + text-align: left; + margin-bottom: 30px; + line-height: 1; + height: 110px; + margin-top: -50px; + overflow: hidden; + *zoom: 1; +} + +.main .logo a { + font-size: 160px; + color: #333; +} + +.helps { + margin-top: 40px; +} + +.helps pre { + padding: 20px; + margin: 10px 0; + border: solid 1px #e7e1cd; + background-color: #fffdef; + overflow: auto; +} + +.icon_lists { + width: 100% !important; + overflow: hidden; + *zoom: 1; +} + +.icon_lists li { + width: 100px; + margin-bottom: 10px; + margin-right: 20px; + text-align: center; + list-style: none !important; + cursor: default; +} + +.icon_lists li .code-name { + line-height: 1.2; +} + +.icon_lists .icon { + display: block; + height: 100px; + line-height: 100px; + font-size: 42px; + margin: 10px auto; + color: #333; + -webkit-transition: font-size 0.25s linear, width 0.25s linear; + -moz-transition: font-size 0.25s linear, width 0.25s linear; + transition: font-size 0.25s linear, width 0.25s linear; +} + +.icon_lists .icon:hover { + font-size: 100px; +} + +.icon_lists .svg-icon { + /* 通过设置 font-size 来改变图标大小 */ + width: 1em; + /* 图标和文字相邻时,垂直对齐 */ + vertical-align: -0.15em; + /* 通过设置 color 来改变 SVG 的颜色/fill */ + fill: currentColor; + /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 + normalize.css 中也包含这行 */ + overflow: hidden; +} + +.icon_lists li .name, +.icon_lists li .code-name { + color: #666; +} + +/* markdown 样式 */ +.markdown { + color: #666; + font-size: 14px; + line-height: 1.8; +} + +.highlight { + line-height: 1.5; +} + +.markdown img { + vertical-align: middle; + max-width: 100%; +} + +.markdown h1 { + color: #404040; + font-weight: 500; + line-height: 40px; + margin-bottom: 24px; +} + +.markdown h2, +.markdown h3, +.markdown h4, +.markdown h5, +.markdown h6 { + color: #404040; + margin: 1.6em 0 0.6em 0; + font-weight: 500; + clear: both; +} + +.markdown h1 { + font-size: 28px; +} + +.markdown h2 { + font-size: 22px; +} + +.markdown h3 { + font-size: 16px; +} + +.markdown h4 { + font-size: 14px; +} + +.markdown h5 { + font-size: 12px; +} + +.markdown h6 { + font-size: 12px; +} + +.markdown hr { + height: 1px; + border: 0; + background: #e9e9e9; + margin: 16px 0; + clear: both; +} + +.markdown p { + margin: 1em 0; +} + +.markdown>p, +.markdown>blockquote, +.markdown>.highlight, +.markdown>ol, +.markdown>ul { + width: 80%; +} + +.markdown ul>li { + list-style: circle; +} + +.markdown>ul li, +.markdown blockquote ul>li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown>ul li p, +.markdown>ol li p { + margin: 0.6em 0; +} + +.markdown ol>li { + list-style: decimal; +} + +.markdown>ol li, +.markdown blockquote ol>li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown code { + margin: 0 3px; + padding: 0 5px; + background: #eee; + border-radius: 3px; +} + +.markdown strong, +.markdown b { + font-weight: 600; +} + +.markdown>table { + border-collapse: collapse; + border-spacing: 0px; + empty-cells: show; + border: 1px solid #e9e9e9; + width: 95%; + margin-bottom: 24px; +} + +.markdown>table th { + white-space: nowrap; + color: #333; + font-weight: 600; +} + +.markdown>table th, +.markdown>table td { + border: 1px solid #e9e9e9; + padding: 8px 16px; + text-align: left; +} + +.markdown>table th { + background: #F7F7F7; +} + +.markdown blockquote { + font-size: 90%; + color: #999; + border-left: 4px solid #e9e9e9; + padding-left: 0.8em; + margin: 1em 0; +} + +.markdown blockquote p { + margin: 0; +} + +.markdown .anchor { + opacity: 0; + transition: opacity 0.3s ease; + margin-left: 8px; +} + +.markdown .waiting { + color: #ccc; +} + +.markdown h1:hover .anchor, +.markdown h2:hover .anchor, +.markdown h3:hover .anchor, +.markdown h4:hover .anchor, +.markdown h5:hover .anchor, +.markdown h6:hover .anchor { + opacity: 1; + display: inline-block; +} + +.markdown>br, +.markdown>p>br { + clear: both; +} + + +.hljs { + display: block; + background: white; + padding: 0.5em; + color: #333333; + overflow-x: auto; +} + +.hljs-comment, +.hljs-meta { + color: #969896; +} + +.hljs-string, +.hljs-variable, +.hljs-template-variable, +.hljs-strong, +.hljs-emphasis, +.hljs-quote { + color: #df5000; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-type { + color: #a71d5d; +} + +.hljs-literal, +.hljs-symbol, +.hljs-bullet, +.hljs-attribute { + color: #0086b3; +} + +.hljs-section, +.hljs-name { + color: #63a35c; +} + +.hljs-tag { + color: #333333; +} + +.hljs-title, +.hljs-attr, +.hljs-selector-id, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #795da3; +} + +.hljs-addition { + color: #55a532; + background-color: #eaffea; +} + +.hljs-deletion { + color: #bd2c00; + background-color: #ffecec; +} + +.hljs-link { + text-decoration: underline; +} + +code[class*="language-"], +pre[class*="language-"] { + color: black; + background: none; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*="language-"]::-moz-selection, +pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, +code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +pre[class*="language-"]::selection, +pre[class*="language-"] ::selection, +code[class*="language-"]::selection, +code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; +} + +@media print { + + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; +} + +:not(pre)>code[class*="language-"], +pre[class*="language-"] { + background: #f5f2f0; +} + +/* Inline code */ +:not(pre)>code[class*="language-"] { + padding: .1em; + border-radius: .3em; + white-space: normal; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #9a6e3a; + background: hsla(0, 0%, 100%, .5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + +.token.function, +.token.class-name { + color: #DD4A68; +} + +.token.regex, +.token.important, +.token.variable { + color: #e90; +} + +.token.important, +.token.bold { + font-weight: bold; +} + +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} diff --git a/demo/webman/backend/plugin/admin/public/demos/css/login.css b/demo/webman/backend/plugin/admin/public/demos/css/login.css new file mode 100644 index 0000000000000000000000000000000000000000..938f05ff3b4a9aa30dc63ba8cafb633a94fcd406 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/css/login.css @@ -0,0 +1,99 @@ +.layui-form { + width: 320px !important; + margin: auto !important; + margin-top: 160px !important; +} + +.layui-form button { + width: 100% !important; + height: 44px !important; + line-height: 44px !important; + font-size: 16px !important; + background-color: #5FB878 !important; + font-weight: 550 !important; +} + +.layui-form-checked[lay-skin=primary] i { + border-color: #5FB878 !important; + background-color: #5FB878 !important; + color: #fff !important; +} + +.layui-tab-content { + margin-top: 15px !important; + padding-left: 0px !important; + padding-right: 0px !important; +} + +.layui-form-item { + margin-top: 20px !important; +} + +.layui-input { + height: 44px !important; + line-height: 44px !important; + padding-left: 15px !important; + border-radius: 3px !important; +} + +.layui-input:focus { + box-shadow: 0px 0px 2px 1px #5FB878 !important; +} + +.layui-form-danger:focus{ + box-shadow: 0px 0px 2px 1px #f56c6c !important; +} + +.logo { + width: 60px !important; + margin-top: 10px !important; + margin-bottom: 10px !important; + margin-left: 20px !important; +} + +.title { + font-size: 30px !important; + font-weight: 550 !important; + margin-left: 20px !important; + color: #5FB878 !important; + display: inline-block !important; + height: 60px !important; + line-height: 60px !important; + margin-top: 10px !important; + position: absolute !important; +} + +.desc { + width: 100% !important; + text-align: center !important; + color: gray !important; + height: 60px !important; + line-height: 60px !important; +} + +body { + background-repeat:no-repeat; + background-color: whitesmoke; + background-size: 100%; + height: 100%; + } + +.code { + float: left; + margin-right: 13px; + margin: 0px !important; + border: #e6e6e6 1px solid; + display: inline-block!important; +} + +.codeImage { + float: right; + height: 42px; + border: #e6e6e6 1px solid; +} + +@media (max-width:768px){ + body{ + background-position:center; + } +} diff --git a/demo/webman/backend/plugin/admin/public/demos/css/person.css b/demo/webman/backend/plugin/admin/public/demos/css/person.css new file mode 100644 index 0000000000000000000000000000000000000000..53c787a7fe42287e3fa0c6f914f768a5cc8c32b2 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/css/person.css @@ -0,0 +1,80 @@ +.pear-container { + background-color: whitesmoke; + margin: 10px; +} +.layui-body { + padding: 25px; +} +.text-center { + text-align: center; +} +.user-info-head { + width: 110px; + height: 110px; + line-height: 110px; + position: relative; + display: inline-block; + border-radius: 50%; + overflow: hidden; + cursor: pointer; + margin: 0 auto; +} +.layui-line-dash { + border-bottom: 1px dashed #ccc; + margin: 15px 0; +} +.comment { + position: absolute; + bottom: 3px; + right: 10px; + font-size: 12px; + color: dimgray; +} +.content { + padding-left: 13px; + font-size: 13px; + color: dimgray; +} +.title { + padding-left: 13.5px; +} +.layui-tab-title { + border-bottom: none; +} +.fl-item { + height: 30px; + font-size: 13.5; +} +.dot { + width: 10px; + height: 10px; + border-radius: 50px; + background-color: gray; + display: inline-block; + margin-right: 10px; +} + +.list .list-item { + height: 32px; + line-height: 32px; + color: gray; + padding: 5px; + padding-left: 15px; + border-radius: 4px; + margin-top: 5.2px; +} + +.list .list-item:hover { + background-color: whitesmoke; +} + +.list .list-item .title { + font-size: 13px; + width: 100%; +} + +.list .list-item .footer { + position: absolute; + right: 30px; + font-size: 12px; +} diff --git a/demo/webman/backend/plugin/admin/public/demos/css/result.css b/demo/webman/backend/plugin/admin/public/demos/css/result.css new file mode 100644 index 0000000000000000000000000000000000000000..d5ccaa3b0d8b8beccbbfe7f532219a1567bd792a --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/css/result.css @@ -0,0 +1,39 @@ +.result { + text-align: center; + +} +.result .success svg { + color: #32C682; + text-align: center; + margin-top: 40px; + +} +.result .error svg { + color: #f56c6c; + text-align: center; + margin-top: 40px; + +} +.result .title { + margin-top: 25px; + +} +.result .desc { + margin-top: 25px; + width: 60%; + margin-left: 20%; + color: rgba(0, 0, 0, .45); +} +.result .content { + margin-top: 20px; + width: 80%; + border-radius: 10px; + background-color: whitesmoke; + height: 200px; + margin-left: 10%; +} +.result .action { + padding-top: 10px; + border-top: 1px whitesmoke solid; + margin-top: 25px; +} diff --git a/demo/webman/backend/plugin/admin/public/demos/data/card.json b/demo/webman/backend/plugin/admin/public/demos/data/card.json new file mode 100644 index 0000000000000000000000000000000000000000..e2385906a4daaff229dc8c4929aed6255e80a2e6 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/card.json @@ -0,0 +1,57 @@ +{ + "msg": "not data", + "count": 30, + "data": [{ + "id": "1", + "image": "https://gw.alipayobjects.com/zos/rmsportal/gLaIAoVWTtLbBWZNYEMg.png", + "title": "Alipay", + "remark": "那是一种内在的东西, 他们到达不了,也无法触及的", + "time": "几秒前" + }, { + "id": "2", + "image": "https://gw.alipayobjects.com/zos/rmsportal/iXjVmWVHbCJAyqvDxdtx.png", + "title": "Layui", + "remark": "生命就像一盒巧克力,结果往往出人意料", + "time": "几秒前" + }, { + "id": "3", + "image": "https://gw.alipayobjects.com/zos/rmsportal/iZBVOIhGJiAnhplqjvZW.png", + "title": "Angular", + "remark": "希望是一个好东西,也许是最好的,好东西是不会消亡的", + "time": "几秒前" + }, + { + "id": "4", + "image": "https://gw.alipayobjects.com/zos/rmsportal/uMfMFlvUuceEyPpotzlq.png", + "title": "React", + "remark": "那是一种内在的东西, 他们到达不了,也无法触及的", + "time": "几秒前" + }, { + "id": "5", + "image": "https://gw.alipayobjects.com/zos/rmsportal/gLaIAoVWTtLbBWZNYEMg.png", + "title": "Alipay", + "remark": "那是一种内在的东西, 他们到达不了,也无法触及的", + "time": "几秒前" + }, { + "id": "6", + "image": "https://gw.alipayobjects.com/zos/rmsportal/iXjVmWVHbCJAyqvDxdtx.png", + "title": "Layui", + "remark": "生命就像一盒巧克力,结果往往出人意料", + "time": "几秒前" + }, { + "id": "7", + "image": "https://gw.alipayobjects.com/zos/rmsportal/iZBVOIhGJiAnhplqjvZW.png", + "title": "Angular", + "remark": "希望是一个好东西,也许是最好的,好东西是不会消亡的", + "time": "几秒前" + }, + { + "id": "8", + "image": "https://gw.alipayobjects.com/zos/rmsportal/uMfMFlvUuceEyPpotzlq.png", + "title": "React", + "remark": "那是一种内在的东西, 他们到达不了,也无法触及的", + "time": "几秒前" + } + ], + "code": 0 +} diff --git a/demo/webman/backend/plugin/admin/public/demos/data/dataMenu.json b/demo/webman/backend/plugin/admin/public/demos/data/dataMenu.json new file mode 100644 index 0000000000000000000000000000000000000000..18c5adb78ef5998cf621a8178e6b196e4194a593 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/dataMenu.json @@ -0,0 +1,377 @@ +{ + "code": 0, + "msg": "ok", + "data": [{ + "id": 1, + "title": "工作空间", + "type": 0, + "icon": "layui-icon layui-icon-console", + "href": "", + "children": [{ + "id": 10, + "title": "控制后台", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_iframe", + "href": "view/console/console1.html" + }, { + "id": 13, + "title": "数据分析", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_iframe", + "href": "view/console/console2.html" + }, { + "id": 14, + "title": "百度一下", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_iframe", + "href": "http://www.baidu.com" + }, { + "id": 15, + "title": "主题预览", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_iframe", + "href": "view/system/theme.html" + }] + }, + { + "id": "component", + "title": "常用组件", + "icon": "layui-icon layui-icon-component", + "type": 0, + "href": "", + "children": [{ + "id": 201, + "title": "基础组件", + "icon": "layui-icon layui-icon-console", + "type": 0, + "children": [{ + "id": 2011, + "title": "功能按钮", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "view/document/button.html" + }, { + "id": 2014, + "title": "表单集合", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/form.html" + }, { + "id": 2010, + "title": "字体图标", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/icon.html" + }, { + "id": 2012, + "title": "多选下拉", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/select.html" + }, { + "id": 2013, + "title": "动态标签", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/tag.html" + }] + }, { + "id": 203, + "title": "进阶组件", + "icon": "layui-icon layui-icon-console", + "type": 0, + "children": [{ + "id": 2031, + "title": "数据表格", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/table.html" + }, { + "id": 2032, + "title": "分布表单", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/step.html" + }, { + "id": 2033, + "title": "树形表格", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/treetable.html" + }, { + "id": 2034, + "title": "树状结构", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/dtree.html" + }, { + "id": 2035, + "title": "文本编辑", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/tinymce.html" + }, { + "id": 2036, + "title": "卡片组件", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/card.html" + }] + }, { + "id": 202, + "title": "弹层组件", + "icon": "layui-icon layui-icon-console", + "type": 0, + "children": [{ + "id": 2021, + "title": "抽屉组件", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/drawer.html" + }, { + "id": 2022, + "title": "消息通知", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/notice.html" + }, { + "id": 2024, + "title": "加载组件", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/loading.html" + }, { + "id": 2023, + "title": "弹层组件", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/popup.html" + }] + }, { + "id": 60331, + "title": "高级组件", + "icon": "layui-icon layui-icon-console", + "type": 0, + "children": [{ + "id": 60131, + "title": "多选项卡", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/tab.html" + }, { + "id": 60132, + "title": "数据菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/menu.html" + }] + }, { + "id": 204, + "title": "其他组件", + "icon": "layui-icon layui-icon-console", + "type": 0, + "children": [{ + "id": 2041, + "title": "哈希加密", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/hash.html" + }, + { + "id": 2042, + "title": "图标选择", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/iconPicker.html" + }, + { + "id": 2043, + "title": "省市级联", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/area.html" + }, + { + "id": 2044, + "title": "数字滚动", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/count.html" + }, + { + "id": 2045, + "title": "顶部返回", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/topBar.html" + } + ] + }] + }, + { + "id": "result", + "title": "结果页面", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "href": "", + "children": [{ + "id": "success", + "title": "成功", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "view/result/success.html" + }, + { + "id": "failure", + "title": "失败", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/result/error.html" + } + ] + }, + { + "id": "error", + "title": "错误页面", + "icon": "layui-icon layui-icon-face-cry", + "type": 0, + "href": "", + "children": [{ + "id": 403, + "title": "403", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "view/error/403.html" + }, + { + "id": 404, + "title": "404", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/error/404.html" + }, + + { + "id": 500, + "title": "500", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/error/500.html" + } + + ] + }, + { + "id": "system", + "title": "系统管理", + "icon": "layui-icon layui-icon-set-fill", + "type": 0, + "href": "", + "children": [{ + "id": 601, + "title": "用户管理", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "view/system/user.html" + }, + { + "id": 602, + "title": "角色管理", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/system/role.html" + }, + + { + "id": 603, + "title": "权限管理", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/system/power.html" + }, + + { + "id": 604, + "title": "部门管理", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/system/deptment.html" + }, + { + "id": 605, + "title": "行为日志", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/system/log.html" + }, { + "id": 606, + "title": "数据字典", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/system/dict.html" + } + + ] + }, + { + "id": "common", + "title": "常用页面", + "icon": "layui-icon layui-icon-template-1", + "type": 0, + "href": "", + "children": [{ + "id": 701, + "title": "登录页面", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "login.html" + }, { + "id": 702, + "title": "空白页面", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "view/system/space.html" + }] + } + ] +} + diff --git a/demo/webman/backend/plugin/admin/public/demos/data/dataTree2.json b/demo/webman/backend/plugin/admin/public/demos/data/dataTree2.json new file mode 100644 index 0000000000000000000000000000000000000000..86e8923c16ab2ca5e74aa798bf0b506f800c315c --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/dataTree2.json @@ -0,0 +1,37 @@ +{ + "status": { + "code": 200, + "message": "操作成功" + }, + "data": [{ + "id": "001", + "title": "湖南省", + "checkArr": "0", + "parentId": "0" + }, + { + "id": "002", + "title": "湖北省", + "checkArr": "0", + "parentId": "0" + }, + { + "id": "003", + "title": "广东省", + "checkArr": "0", + "parentId": "0" + }, + { + "id": "004", + "title": "浙江省", + "checkArr": "0", + "parentId": "0" + }, + { + "id": "005", + "title": "福建省", + "checkArr": "0", + "parentId": "0" + } + ] +} diff --git a/demo/webman/backend/plugin/admin/public/demos/data/dictData.json b/demo/webman/backend/plugin/admin/public/demos/data/dictData.json new file mode 100644 index 0000000000000000000000000000000000000000..db7ae1186b3d62c6b8782dab7aa4ea3740c90c5a --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/dictData.json @@ -0,0 +1,36 @@ +{ + "code": 0, + "msg": null, + "count": 2, + "data": [{ + "createTime": null, + "createBy": null, + "createName": null, + "updateTime": null, + "updateBy": null, + "updateName": null, + "remark": "男 : body", + "params": null, + "dataId": "1317401149287956480", + "dataLabel": "男", + "dataValue": "boy", + "typeCode": "user_sex", + "isDefault": null, + "enable": "0" + }, { + "createTime": null, + "createBy": null, + "createName": null, + "updateTime": null, + "updateBy": null, + "updateName": null, + "remark": "女 : girl", + "params": null, + "dataId": "1317402976670711808", + "dataLabel": "女", + "dataValue": "girl", + "typeCode": "user_sex", + "isDefault": null, + "enable": "0" + }] +} diff --git a/demo/webman/backend/plugin/admin/public/demos/data/dictType.json b/demo/webman/backend/plugin/admin/public/demos/data/dictType.json new file mode 100644 index 0000000000000000000000000000000000000000..3b9ab26e41730c8c8c0bfd5ed813691ccfbd5b90 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/dictType.json @@ -0,0 +1,90 @@ +{ + "code": 0, + "msg": null, + "count": 6, + "data": [{ + "createTime": null, + "createBy": null, + "createName": null, + "updateTime": null, + "updateBy": null, + "updateName": null, + "remark": null, + "params": null, + "id": "1304489072256876544", + "typeName": "用户状态", + "typeCode": "user_status", + "description": "用户状态", + "enable": "0" + }, { + "createTime": null, + "createBy": null, + "createName": null, + "updateTime": null, + "updateBy": null, + "updateName": null, + "remark": null, + "params": null, + "id": "1317360314219495424", + "typeName": "登录类型", + "typeCode": "login", + "description": "登录类型", + "enable": "0" + }, { + "createTime": null, + "createBy": null, + "createName": null, + "updateTime": null, + "updateBy": null, + "updateName": null, + "remark": null, + "params": null, + "id": "1317400519127334912", + "typeName": "用户类型", + "typeCode": "user_status", + "description": "用户类型", + "enable": "0" + }, { + "createTime": null, + "createBy": null, + "createName": null, + "updateTime": null, + "updateBy": null, + "updateName": null, + "remark": null, + "params": null, + "id": "1317400823096934400", + "typeName": "配置类型", + "typeCode": "config_type", + "description": "配置类型", + "enable": "0" + }, { + "createTime": null, + "createBy": null, + "createName": null, + "updateTime": null, + "updateBy": null, + "updateName": null, + "remark": null, + "params": null, + "id": "455184568505470976", + "typeName": "用户性别", + "typeCode": "user_sex", + "description": "用户性别", + "enable": "0" + }, { + "createTime": null, + "createBy": null, + "createName": null, + "updateTime": null, + "updateBy": null, + "updateName": null, + "remark": null, + "params": null, + "id": "455184935989415936", + "typeName": "全局状态", + "typeCode": "sys_status", + "description": "状态描述\n", + "enable": "0" + }] +} diff --git a/demo/webman/backend/plugin/admin/public/demos/data/dtree.json b/demo/webman/backend/plugin/admin/public/demos/data/dtree.json new file mode 100644 index 0000000000000000000000000000000000000000..376d9b0db8cb164973d530eda879fc9ed7d6d2ed --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/dtree.json @@ -0,0 +1,181 @@ +{ + "status": { + "code": 200, + "message": "操作成功" + }, + "data": [{ + "id": "001", + "title": "湖南省", + "parentId": "0", + "children": [{ + "id": "001001", + "title": "长沙市", + "last": true, + "parentId": "001" + }, + { + "id": "001002", + "title": "株洲市", + "last": true, + "parentId": "001" + }, + { + "id": "001003", + "title": "湘潭市", + "last": true, + "parentId": "001" + }, + { + "id": "001004", + "title": "衡阳市", + "last": true, + "parentId": "001" + }, + { + "id": "001005", + "title": "郴州市", + "last": true, + "parentId": "001" + } + ] + }, + { + "id": "002", + "title": "湖北省", + "parentId": "0", + "children": [{ + "id": "002001", + "title": "武汉市", + "last": true, + "parentId": "002" + }, + { + "id": "002002", + "title": "黄冈市", + "last": true, + "parentId": "002" + }, + { + "id": "002003", + "title": "潜江市", + "last": true, + "parentId": "002" + }, + { + "id": "002004", + "title": "荆州市", + "last": true, + "parentId": "002" + }, + { + "id": "002005", + "title": "襄阳市", + "last": true, + "parentId": "002" + } + ] + }, + { + "id": "003", + "title": "广东省", + "parentId": "0", + "children": [{ + "id": "003001", + "title": "广州市", + "last": false, + "parentId": "003", + "children": [{ + "id": "003001001", + "title": "天河区", + "last": true, + "parentId": "003001" + }, + { + "id": "003001002", + "title": "花都区", + "last": true, + "parentId": "003001" + } + ] + }, + { + "id": "003002", + "title": "深圳市", + "last": true, + "parentId": "003" + }, + { + "id": "003003", + "title": "中山市", + "last": true, + "parentId": "003" + }, + { + "id": "003004", + "title": "东莞市", + "last": true, + "parentId": "003" + }, + { + "id": "003005", + "title": "珠海市", + "last": true, + "parentId": "003" + }, + { + "id": "003006", + "title": "韶关市", + "last": true, + "parentId": "003" + } + ] + }, + { + "id": "004", + "title": "浙江省", + "parentId": "0", + "children": [{ + "id": "004001", + "title": "杭州市", + "last": true, + "parentId": "004" + }, + { + "id": "004002", + "title": "温州市", + "last": true, + "parentId": "004" + }, + { + "id": "004003", + "title": "绍兴市", + "last": true, + "parentId": "004" + }, + { + "id": "004004", + "title": "金华市", + "last": true, + "parentId": "004" + }, + { + "id": "004005", + "title": "义乌市", + "last": true, + "parentId": "004" + } + ] + }, + { + "id": "005", + "title": "福建省", + "parentId": "0", + "children": [{ + "id": "005001", + "title": "厦门市", + "last": true, + "parentId": "005" + }] + } + ] +} diff --git a/demo/webman/backend/plugin/admin/public/demos/data/loginLog.json b/demo/webman/backend/plugin/admin/public/demos/data/loginLog.json new file mode 100644 index 0000000000000000000000000000000000000000..eb39552f919a817ff18d2d207914bad9cce7e066 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/loginLog.json @@ -0,0 +1,211 @@ +{ + "createTime": null, + "createBy": null, + "updateTime": null, + "updateBy": null, + "remark": null, + "code": 0, + "msg": null, + "count": 167, + "data": [{ + "id": "1305106851892822016", + "title": "登录", + "description": "登录成功", + "businessType": "OTHER", + "requestMethod": "POST", + "method": "/login", + "operateUrl": "/login", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "LOGIN", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T11:31:36.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305101593019940864", + "title": "登录", + "description": "登录成功", + "businessType": "OTHER", + "requestMethod": "POST", + "method": "/login", + "operateUrl": "/login", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "LOGIN", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T11:10:42.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305101247900024832", + "title": "登录", + "description": "登录成功", + "businessType": "OTHER", + "requestMethod": "POST", + "method": "/login", + "operateUrl": "/login", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "LOGIN", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T11:09:20.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305099674977304576", + "title": "登录", + "description": "登录成功", + "businessType": "OTHER", + "requestMethod": "POST", + "method": "/login", + "operateUrl": "/login", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "LOGIN", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T11:03:05.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305095186061197312", + "title": "登录", + "description": "登录成功", + "businessType": "OTHER", + "requestMethod": "POST", + "method": "/login", + "operateUrl": "/login", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "LOGIN", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T10:45:15.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305092027951611904", + "title": "登录", + "description": "登录成功", + "businessType": "OTHER", + "requestMethod": "POST", + "method": "/login", + "operateUrl": "/login", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "LOGIN", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T10:32:42.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305082862634008576", + "title": "登录", + "description": "登录成功", + "businessType": "OTHER", + "requestMethod": "POST", + "method": "/login", + "operateUrl": "/login", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "LOGIN", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T09:56:16.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305071134877679616", + "title": "登录", + "description": "登录成功", + "businessType": "OTHER", + "requestMethod": "POST", + "method": "/login", + "operateUrl": "/login", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "LOGIN", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T09:09:40.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305070481803575296", + "title": "登录", + "description": "登录成功", + "businessType": "OTHER", + "requestMethod": "POST", + "method": "/login", + "operateUrl": "/login", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "LOGIN", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T09:07:05.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305064691009060864", + "title": "登录", + "description": "登录成功", + "businessType": "OTHER", + "requestMethod": "POST", + "method": "/login", + "operateUrl": "/login", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "LOGIN", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T08:44:04.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }] +} diff --git a/demo/webman/backend/plugin/admin/public/demos/data/menu.json b/demo/webman/backend/plugin/admin/public/demos/data/menu.json new file mode 100644 index 0000000000000000000000000000000000000000..3a20b6e414bc033779d9682016af1608292b8275 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/menu.json @@ -0,0 +1,444 @@ +[{ + "id": 1, + "title": "工作空间", + "icon": "layui-icon layui-icon-console", + "type": 0, + "href": "", + "children": [{ + "id": 10, + "title": "控制后台", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_iframe", + "href": "view/console/console1.html" + }, { + "id": 13, + "title": "数据分析", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_iframe", + "href": "view/console/console2.html" + }, { + "id": 14, + "title": "百度一下", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_iframe", + "href": "http://www.bing.com" + }, { + "id": 15, + "title": "主题预览", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_iframe", + "href": "view/system/theme.html" + }, { + "id": 16, + "title": "酸爽翻倍", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_iframe", + "href": "view/document/core.html" + }] + }, + { + "id": "component", + "title": "常用组件", + "icon": "layui-icon layui-icon-component", + "type": 0, + "href": "", + "children": [{ + "id": 201, + "title": "基础组件", + "icon": "layui-icon layui-icon-console", + "type": 0, + "children": [ + { + "id": 2011, + "title": "功能按钮", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "view/document/button.html" + }, { + "id": 2014, + "title": "表单集合", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/form.html" + }, { + "id": 2010, + "title": "字体图标", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/icon.html" + }, { + "id": 2012, + "title": "多选下拉", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/select.html" + }, { + "id": 2013, + "title": "动态标签", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/tag.html" + }] + }, { + "id": 203, + "title": "进阶组件", + "icon": "layui-icon layui-icon-console", + "type": 0, + "children": [{ + "id": 2031, + "title": "数据表格", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/table.html" + }, { + "id": 2032, + "title": "分布表单", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/step.html" + }, { + "id": 2033, + "title": "树形表格", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/treetable.html" + }, { + "id": 2034, + "title": "树状结构", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/dtree.html" + }, { + "id": 2035, + "title": "文本编辑", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/tinymce.html" + }, { + "id": 2036, + "title": "卡片组件", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/card.html" + }] + }, { + "id": 202, + "title": "弹层组件", + "icon": "layui-icon layui-icon-console", + "type": 0, + "children": [{ + "id": 2021, + "title": "抽屉组件", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/drawer.html" + }, { + "id": 2022, + "title": "消息通知 (过时)", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/notice.html" + }, { + "id": 2025, + "title": "消息通知 (新增)", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/toast.html" + }, { + "id": 2024, + "title": "加载组件", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/loading.html" + }, { + "id": 2023, + "title": "弹层组件", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/popup.html" + }] + },{ + "id": 60331, + "title": "高级组件", + "icon": "layui-icon layui-icon-console", + "type": 0, + "children": [{ + "id": 60131, + "title": "多选项卡", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/tab.html" + },{ + "id": 60132, + "title": "数据菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/menu.html" + }] + }, { + "id": 204, + "title": "其他组件", + "icon": "layui-icon layui-icon-console", + "type": 0, + "children": [{ + "id": 2041, + "title": "哈希加密", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/encrypt.html" + }, + { + "id": 2042, + "title": "图标选择", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/iconPicker.html" + }, + { + "id": 2043, + "title": "省市级联", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/area.html" + }, + { + "id": 2044, + "title": "数字滚动", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/count.html" + }, + { + "id": 2045, + "title": "顶部返回", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/document/topBar.html" + }, + { + "id": 2046, + "title": "水印组件", + "type": 1, + "openType": "_iframe", + "href": "view/document/watermark.html" + }, + { + "id": 2047, + "title": "全屏组件", + "type": 1, + "openType": "_iframe", + "href": "view/document/fullscreen.html" + }, + { + "id": 2048, + "title": "汽泡组件", + "type": 1, + "openType": "_iframe", + "href": "view/document/popover.html" + } + ] + }] + }, + { + "id": "result", + "title": "结果页面", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "href": "", + "children": [{ + "id": "success", + "title": "成功", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "view/result/success.html" + }, + { + "id": "failure", + "title": "失败", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/result/error.html" + } + ] + }, + { + "id": "error", + "title": "错误页面", + "icon": "layui-icon layui-icon-face-cry", + "type": 0, + "href": "", + "children": [{ + "id": 403, + "title": "403", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "view/error/403.html" + }, + { + "id": 404, + "title": "404", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/error/404.html" + }, + + { + "id": 500, + "title": "500", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/error/500.html" + } + + ] + }, + { + "id": "system", + "title": "系统管理", + "icon": "layui-icon layui-icon-set-fill", + "type": 0, + "href": "", + "children": [{ + "id": 601, + "title": "用户管理", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "view/system/user.html" + }, + { + "id": 602, + "title": "角色管理", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/system/role.html" + }, + + { + "id": 603, + "title": "权限管理", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/system/power.html" + }, + + { + "id": 604, + "title": "部门管理", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/system/deptment.html" + }, + { + "id": 605, + "title": "行为日志", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/system/log.html" + }, { + "id": 606, + "title": "数据字典", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "view/system/dict.html" + } + + ] + }, + { + "id": "common", + "title": "常用页面", + "icon": "layui-icon layui-icon-template-1", + "type": 0, + "href": "", + "children": [{ + "id": 701, + "title": "登录页面", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "login.html" + }, { + "id": 702, + "title": "空白页面", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "view/system/space.html" + }] + }, { + "id": "echarts", + "title": "数据图表", + "icon": "layui-icon layui-icon-chart", + "type": 0, + "href": "", + "children": [{ + "id": 12121, + "title": "折线图", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "view/echarts/line.html" + }, { + "id": 121212, + "title": "柱状图", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_iframe", + "href": "view/echarts/column.html" + }] + }, + { + "id": "code", + "title": "开发工具", + "icon": "layui-icon layui-icon-util", + "type": 0, + "href": "", + "children": [{ + "id": 801, + "title": "表单构建", + "icon": "layui-icon layui-icon-util", + "type": 1, + "openType": "_iframe", + "href": "component/code/index.html" + }] + } +] \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/data/message.json b/demo/webman/backend/plugin/admin/public/demos/data/message.json new file mode 100644 index 0000000000000000000000000000000000000000..7cf9263327e3f3e96b62564a0ca35d12a573ab4b --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/message.json @@ -0,0 +1,90 @@ +[{ + "id": 1, + "title": "通知", + "children": [{ + "id": 11, + "avatar":"https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + "title": "你收到了 14 份新周报", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, { + "id": 12, + "avatar":"https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png", + "title": "曲妮妮 已通过第三轮面试", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 11, + "avatar":"https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png", + "title": "可以区分多种通知类型", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, { + "id": 12, + "avatar":"https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png", + "title": "左侧图标用于区分不同的类型", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 11, + "avatar":"https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + "title": "内容不要超过两行字", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }] + }, + { + "id": 2, + "title": "消息", + "children": [{ + "id": 11, + "avatar":"https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + "title": "你收到了 14 份新周报", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, { + "id": 12, + "avatar":"https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png", + "title": "曲妮妮 已通过第三轮面试", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 11, + "avatar":"https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png", + "title": "可以区分多种通知类型", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, { + "id": 12, + "avatar":"https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png", + "title": "左侧图标用于区分不同的类型", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 11, + "avatar":"https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + "title": "内容不要超过两行字", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }] + }, + { + "id": 3, + "title": "代办", + "children": [] + } +] diff --git a/demo/webman/backend/plugin/admin/public/demos/data/operateLog.json b/demo/webman/backend/plugin/admin/public/demos/data/operateLog.json new file mode 100644 index 0000000000000000000000000000000000000000..79e5454bc6e3dbcd6f8a0edeecfc3b13f5de55f7 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/operateLog.json @@ -0,0 +1,211 @@ +{ + "createTime": null, + "createBy": null, + "updateTime": null, + "updateBy": null, + "remark": null, + "code": 0, + "msg": null, + "count": 178, + "data": [{ + "id": "1305106857240559616", + "title": "主页", + "description": "返回 Index 主页视图", + "businessType": "ADD", + "requestMethod": "GET", + "method": "/index", + "operateUrl": "/index", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "OPERATE", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T11:31:37.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305101599714050048", + "title": "主页", + "description": "返回 Index 主页视图", + "businessType": "ADD", + "requestMethod": "GET", + "method": "/index", + "operateUrl": "/index", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "OPERATE", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T11:10:44.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305101253352620032", + "title": "主页", + "description": "返回 Index 主页视图", + "businessType": "ADD", + "requestMethod": "GET", + "method": "/index", + "operateUrl": "/index", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "OPERATE", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T11:09:21.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305099681512030208", + "title": "主页", + "description": "返回 Index 主页视图", + "businessType": "ADD", + "requestMethod": "GET", + "method": "/index", + "operateUrl": "/index", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "OPERATE", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T11:03:06.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305095191291494400", + "title": "主页", + "description": "返回 Index 主页视图", + "businessType": "ADD", + "requestMethod": "GET", + "method": "/index", + "operateUrl": "/index", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "OPERATE", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T10:45:16.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305092034448588800", + "title": "主页", + "description": "返回 Index 主页视图", + "businessType": "ADD", + "requestMethod": "GET", + "method": "/index", + "operateUrl": "/index", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "OPERATE", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T10:32:43.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305082868002717696", + "title": "主页", + "description": "返回 Index 主页视图", + "businessType": "ADD", + "requestMethod": "GET", + "method": "/index", + "operateUrl": "/index", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "OPERATE", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T09:56:18.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305071141362073600", + "title": "主页", + "description": "返回 Index 主页视图", + "businessType": "ADD", + "requestMethod": "GET", + "method": "/index", + "operateUrl": "/index", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "OPERATE", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T09:09:42.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305070488145362944", + "title": "主页", + "description": "返回 Index 主页视图", + "businessType": "ADD", + "requestMethod": "GET", + "method": "/index", + "operateUrl": "/index", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "OPERATE", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T09:07:06.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }, { + "id": "1305064697174687744", + "title": "主页", + "description": "返回 Index 主页视图", + "businessType": "ADD", + "requestMethod": "GET", + "method": "/index", + "operateUrl": "/index", + "operateAddress": "127.0.0.1", + "requestParam": null, + "requestBody": "", + "responseBody": null, + "success": true, + "loggingType": "OPERATE", + "errorMsg": null, + "systemOs": "Windows", + "createTime": "2020-09-13T08:44:05.000+0000", + "operateName": "admin", + "map": {}, + "browser": "谷歌浏览器" + }] +} diff --git a/demo/webman/backend/plugin/admin/public/demos/data/organization.json b/demo/webman/backend/plugin/admin/public/demos/data/organization.json new file mode 100644 index 0000000000000000000000000000000000000000..ff1626b0e265420cc84130fa9833bdcc37e677b8 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/organization.json @@ -0,0 +1,41 @@ +{ + "code": 0, + "msg": "...", + "count": 3, + "data": [{ + "name": "软件部", + "userCount": 324, + "location": "二楼201", + "leader": "皮卡丘" + }, { + "name": "美工部", + "userCount": 98, + "location": "二楼101", + "leader": "皮卡丘" + }, { + "name": "设计部", + "userCount": 43, + "location": "六楼602", + "leader": "皮卡丘" + }, { + "name": "销售部", + "userCount": 12, + "location": "一楼131", + "leader": "皮卡丘" + }, { + "name": "产品部", + "userCount": 128, + "location": "四楼401", + "leader": "皮卡丘" + }, { + "name": "财务部", + "userCount": 23, + "location": "三楼105", + "leader": "皮卡丘" + }, { + "name": "人事部", + "userCount": 67, + "location": "二楼201", + "leader": "皮卡丘" + }] +} diff --git a/demo/webman/backend/plugin/admin/public/demos/data/organizationtree.json b/demo/webman/backend/plugin/admin/public/demos/data/organizationtree.json new file mode 100644 index 0000000000000000000000000000000000000000..262594fe0af1cd4c205e45c5b715f4140c3994f2 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/organizationtree.json @@ -0,0 +1,143 @@ +{ + "status": { + "code": 200, + "message": "操作成功" + }, + "data": [{ + "id": "0", + "title": "济南总部", + "last": false, + "parentId": "9527", + "children": [{ + "id": "001", + "title": "杭州市", + "last": false, + "parentId": "0", + "children": [{ + "id": "001001", + "title": "软件部", + "last": true, + "parentId": "001" + }, + { + "id": "001002", + "title": "销售部", + "last": true, + "parentId": "001" + }, + { + "id": "001003", + "title": "财务部", + "last": true, + "parentId": "001" + }, + { + "id": "001004", + "title": "人事部", + "last": true, + "parentId": "001" + }, + { + "id": "001005", + "title": "行政部", + "last": true, + "parentId": "001" + } + ] + }, + { + "id": "002", + "title": "湖北省", + "last": false, + "parentId": "0", + "children": [{ + "id": "002001", + "title": "武汉市", + "last": true, + "parentId": "002" + }, + { + "id": "002002", + "title": "黄冈市", + "last": true, + "parentId": "002" + }, + { + "id": "002003", + "title": "潜江市", + "last": true, + "parentId": "002" + }, + { + "id": "002004", + "title": "荆州市", + "last": true, + "parentId": "002" + }, + { + "id": "002005", + "title": "襄阳市", + "last": true, + "parentId": "002" + } + ] + }, + { + "id": "003", + "title": "广东省", + "last": false, + "parentId": "0", + "children": [{ + "id": "003001", + "title": "广州市", + "last": false, + "parentId": "003", + "children": [{ + "id": "003001001", + "title": "天河区", + "last": true, + "parentId": "003001" + }, + { + "id": "003001002", + "title": "花都区", + "last": true, + "parentId": "003001" + } + ] + }, + { + "id": "003002", + "title": "深圳市", + "last": true, + "parentId": "003" + }, + { + "id": "003003", + "title": "中山市", + "last": true, + "parentId": "003" + }, + { + "id": "003004", + "title": "东莞市", + "last": true, + "parentId": "003" + }, + { + "id": "003005", + "title": "珠海市", + "last": true, + "parentId": "003" + }, + { + "id": "003006", + "title": "韶关市", + "last": true, + "parentId": "003" + } + ] + } + ] + }] +} \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/data/power.json b/demo/webman/backend/plugin/admin/public/demos/data/power.json new file mode 100644 index 0000000000000000000000000000000000000000..db7ace11b5044d64cf713cd785ccc1b75cf0eb12 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/power.json @@ -0,0 +1,185 @@ +{ + "code": 0, + "msg": "...", + "count": null, + "data": [{ + "powerId": "1", + "powerName": "系统管理", + "powerType": "0", + "powerCode": "", + "powerUrl": "", + "openType": null, + "parentId": "0", + "icon": "layui-icon-set-fill", + "sort": 1, + "enable": 1, + "checkArr": "0" + }, { + "powerId": "2", + "powerName": "用户管理", + "powerType": "1", + "powerCode": "sys:user:main", + "powerUrl": "/system/user/main", + "openType": null, + "parentId": "1", + "icon": "layui-icon-username", + "sort": null, + "enable": 1, + "checkArr": "0" + }, { + "powerId": "3", + "powerName": "角色管理", + "powerType": "1", + "powerCode": "sys:role:main", + "powerUrl": "/system/role/main", + "openType": null, + "parentId": "1", + "icon": "layui-icon-user", + "sort": null, + "enable": 1, + "checkArr": "0" + }, { + "powerId": "4", + "powerName": "权限管理", + "powerType": "1", + "powerCode": "sys:power:main", + "powerUrl": "/system/power/main", + "openType": null, + "parentId": "1", + "icon": "layui-icon-vercode", + "sort": null, + "checkArr": "0" + }, { + "powerId": "442359447487123456", + "powerName": "角色列表", + "powerType": "2", + "powerCode": "sys:role:data", + "powerUrl": "", + "openType": null, + "parentId": "3", + "icon": "layui-icon-rate", + "sort": 1, + "checkArr": "0" + }, { + "powerId": "442417411065516032", + "powerName": "敏捷开发", + "powerType": "0", + "powerCode": "", + "powerUrl": "", + "openType": null, + "parentId": "0", + "icon": "layui-icon-senior", + "sort": 2, + "checkArr": "0" + }, { + "powerId": "442418188639145984", + "powerName": "模板管理", + "powerType": "1", + "powerCode": "exp:template:main", + "powerUrl": "/system/user/main", + "openType": null, + "parentId": "442417411065516032", + "icon": "layui-icon-template-1", + "sort": null, + "checkArr": "0" + }, { + "powerId": "442520236248403968", + "powerName": "数据监控", + "powerType": "1", + "powerCode": "/druid/index.html", + "powerUrl": "/druid/index.html", + "openType": null, + "parentId": "694203021537574912", + "icon": "layui-icon-chart", + "sort": 1, + "checkArr": "0" + }, { + "powerId": "442650387514789888", + "powerName": "定时任务", + "powerType": "0", + "powerCode": "", + "powerUrl": "", + "openType": null, + "parentId": "0", + "icon": "layui-icon-log", + "sort": 5, + "checkArr": "0" + }, { + "powerId": "442650770626711552", + "powerName": "任务管理", + "powerType": "1", + "powerCode": "qrt:task:main", + "powerUrl": "/qrt/task/main", + "openType": null, + "parentId": "442650387514789888", + "icon": "layui-icon-chat", + "sort": 1, + "checkArr": "0" + }, { + "powerId": "442651158935375872", + "powerName": "任务日志", + "powerType": "1", + "powerCode": "qrt:log:main", + "powerUrl": "/qrt/log/main", + "openType": null, + "parentId": "442650387514789888", + "icon": "layui-icon-file", + "sort": 2, + "checkArr": "0" + }, { + "powerId": "442722702474743808", + "powerName": "数据字典", + "powerType": "1", + "powerCode": "system:dictType:main", + "powerUrl": "/system/dictType/main", + "openType": null, + "parentId": "1", + "icon": "layui-icon-form", + "sort": 1, + "checkArr": "0" + }, { + "powerId": "5", + "powerName": "工作流程", + "powerType": "0", + "powerCode": "", + "powerUrl": "", + "openType": null, + "parentId": "0", + "icon": "layui-icon-util", + "sort": 3, + "checkArr": "0" + }, { + "powerId": "6", + "powerName": "模型管理", + "powerType": "1", + "powerCode": null, + "powerUrl": null, + "openType": null, + "parentId": "5", + "icon": "layui-icon layui-icon-edit", + "sort": null, + "checkArr": "0" + }, { + "powerId": "694203021537574912", + "powerName": "系统监控", + "powerType": "0", + "powerCode": "", + "powerUrl": "", + "openType": null, + "parentId": "0", + "icon": "layui-icon-console", + "sort": 4, + "checkArr": "0" + }, { + "powerId": "694203311615639552", + "powerName": "接口文档", + "powerType": "1", + "powerCode": "", + "powerUrl": "/swagger-ui.html", + "openType": null, + "parentId": "694203021537574912", + "icon": "layui-icon-chart", + "sort": 1, + "checkArr": "0" + }] +} diff --git a/demo/webman/backend/plugin/admin/public/demos/data/role.json b/demo/webman/backend/plugin/admin/public/demos/data/role.json new file mode 100644 index 0000000000000000000000000000000000000000..42bd064722599de415f6c9dc21e37453bdd632cf --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/role.json @@ -0,0 +1,42 @@ +{ + "code": 0, + "msg": "...", + "count": 3, + "data": [{ + "createTime": null, + "createBy": null, + "updateTime": null, + "updateBy": null, + "remark": null, + "roleId": "1", + "roleName": "超级管理员", + "roleCode": "admin", + "enable": "1", + "details": "超级管理员", + "checked": false + }, { + "createTime": null, + "createBy": null, + "updateTime": null, + "updateBy": null, + "remark": null, + "roleId": "2", + "roleName": "普通管理员", + "roleCode": "manager", + "enable": "0", + "details": "普通管理员", + "checked": false + }, { + "createTime": null, + "createBy": null, + "updateTime": null, + "updateBy": null, + "remark": null, + "roleId": "3", + "roleName": "普通用户", + "roleCode": "pearson", + "enable": "0", + "details": "普通用户", + "checked": false + }] +} diff --git a/demo/webman/backend/plugin/admin/public/demos/data/table.json b/demo/webman/backend/plugin/admin/public/demos/data/table.json new file mode 100644 index 0000000000000000000000000000000000000000..8f148860d6e8922cc8278016402ec459e2a6c02b --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/table.json @@ -0,0 +1,132 @@ +{ + "code": 0, + "msg": "...", + "count": 3, + "data": [{ + "userId": "1", + "username": "admin", + "password": "$2a$10$1K7E1.IYCrsoZVCb6utOo.5jENtfOzhdKWhc49t2lk.UQd7Oam4FG", + "salt": null, + "status": null, + "realName": "超级'管'理员", + "email": "854085'4@'qq.com", + "avatar": null, + "sex": "1", + "phone": "15543526531", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "2", + "username": "854085467", + "password": null, + "salt": null, + "status": null, + "realName": "就\"眠\"仪式", + "email": null, + "avatar": null, + "sex": "1", + "phone": "1555324324234", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "3", + "username": "970796069", + "password": null, + "salt": null, + "status": null, + "realName": "王二麻子", + "email": null, + "avatar": null, + "sex": "1", + "phone": "1555324324234", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "4", + "username": "admin", + "password": "$2a$10$1K7E1.IYCrsoZVCb6utOo.5jENtfOzhdKWhc49t2lk.UQd7Oam4FG", + "salt": null, + "status": null, + "realName": "超级管理员", + "email": "8540854@qq.com", + "avatar": null, + "sex": "1", + "phone": "15543526531", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "5", + "username": "854085467", + "password": null, + "salt": null, + "status": null, + "realName": "就眠仪式", + "email": null, + "avatar": null, + "sex": "1", + "phone": "1555324324234", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "6", + "username": "970796069", + "password": null, + "salt": null, + "status": null, + "realName": "王二麻子", + "email": null, + "avatar": null, + "sex": "1", + "phone": "1555324324234", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "7", + "username": "admin", + "password": "$2a$10$1K7E1.IYCrsoZVCb6utOo.5jENtfOzhdKWhc49t2lk.UQd7Oam4FG", + "salt": null, + "status": null, + "realName": "超级管理员", + "email": "8540854@qq.com", + "avatar": null, + "sex": "1", + "phone": "15543526531", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "8", + "username": "854085467", + "password": null, + "salt": null, + "status": null, + "realName": "就眠仪式", + "email": null, + "avatar": null, + "sex": "1", + "phone": "1555324324234", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "9", + "username": "970796069", + "password": null, + "salt": null, + "status": null, + "realName": "王二麻子", + "email": null, + "avatar": null, + "sex": "1", + "phone": "1555324324234", + "enable": "1", + "login": "1", + "roleIds": null + }] +} diff --git a/demo/webman/backend/plugin/admin/public/demos/data/user.json b/demo/webman/backend/plugin/admin/public/demos/data/user.json new file mode 100644 index 0000000000000000000000000000000000000000..2e927acc47a225e63b440feaafa34a0595dc8ee2 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/data/user.json @@ -0,0 +1,118 @@ +{ + "code": 0, + "msg": "...", + "count": 3, + "data": [{ + "userId": "1", + "username": "admin", + "password": "$2a$10$1K7E1.IYCrsoZVCb6utOo.5jENtfOzhdKWhc49t2lk.UQd7Oam4FG", + "salt": null, + "status": null, + "realName": "超级管理员", + "email": "8540854@qq.com", + "avatar": null, + "sex": "1", + "phone": "15543526531", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "442488661347536896", + "username": "854085467", + "password": null, + "salt": null, + "status": null, + "realName": "就眠仪式", + "email": null, + "avatar": null, + "sex": "1", + "phone": "1555324324234", + "enable": "0", + "login": "1", + "roleIds": null + }, { + "userId": "442492965651353600", + "username": "970796069", + "password": null, + "salt": null, + "status": null, + "realName": "王二麻子", + "email": null, + "avatar": null, + "sex": "1", + "phone": "1555324324234", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "1", + "username": "admin", + "password": "$2a$10$1K7E1.IYCrsoZVCb6utOo.5jENtfOzhdKWhc49t2lk.UQd7Oam4FG", + "salt": null, + "status": null, + "realName": "超级管理员", + "email": "8540854@qq.com", + "avatar": null, + "sex": "1", + "phone": "15543526531", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "442488661347536896", + "username": "854085467", + "password": null, + "salt": null, + "status": null, + "realName": "就眠仪式", + "email": null, + "avatar": null, + "sex": "1", + "phone": "1555324324234", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "442492965651353600", + "username": "970796069", + "password": null, + "salt": null, + "status": null, + "realName": "王二麻子", + "email": null, + "avatar": null, + "sex": "1", + "phone": "1555324324234", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "1", + "username": "admin", + "password": "$2a$10$1K7E1.IYCrsoZVCb6utOo.5jENtfOzhdKWhc49t2lk.UQd7Oam4FG", + "salt": null, + "status": null, + "realName": "超级管理员", + "email": "8540854@qq.com", + "avatar": null, + "sex": "1", + "phone": "15543526531", + "enable": "1", + "login": "1", + "roleIds": null + }, { + "userId": "442488661347536896", + "username": "854085467", + "password": null, + "salt": null, + "status": null, + "realName": "就眠仪式", + "email": null, + "avatar": null, + "sex": "1", + "phone": "1555324324234", + "enable": "1", + "login": "1", + "roleIds": null + }] +} diff --git a/demo/webman/backend/plugin/admin/public/demos/demo/index.html b/demo/webman/backend/plugin/admin/public/demos/demo/index.html new file mode 100644 index 0000000000000000000000000000000000000000..5525c9bc33b239f2280dd6077139b24b05e412b6 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/demo/index.html @@ -0,0 +1,66 @@ + + + + + + + + + +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/area.html b/demo/webman/backend/plugin/admin/public/demos/document/area.html new file mode 100644 index 0000000000000000000000000000000000000000..87165f1e6120ad5b1add97921917db1b55cced89 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/area.html @@ -0,0 +1,143 @@ + + + + + 区域选择 + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          开发环境
                                                                                          +
                                                                                          + Area 省市级联 选择组件 +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +							    <link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                          +							    并
                                                                                          +							    <script src="component/layui/layui.js"></script>
                                                                                          +						        并
                                                                                          +							    <script src="component/pear/pear.js"></script>
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 基本使用 +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          网点地址
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 基本使用 +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          网点地址
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +							layui.use(['area'], function () {
                                                                                          +							    var area = layui.area;
                                                                                          +								 
                                                                                          +							    area.render({
                                                                                          +							        elem: '#area-picker',
                                                                                          +							        change: function (res) {
                                                                                          +							            console.log(res);
                                                                                          +							        }
                                                                                          +							    });
                                                                                          +							});
                                                                                          +						
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/button.html b/demo/webman/backend/plugin/admin/public/demos/document/button.html new file mode 100644 index 0000000000000000000000000000000000000000..311e7b2895bdbf60eaa478a3628a9ec24d54dc10 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/button.html @@ -0,0 +1,305 @@ + + + + + 按钮组件 + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 开发环境 +
                                                                                          +
                                                                                          + Pear Button 参考 Element UI 样式 ,提供 Button 服务 +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								<link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                          +								或
                                                                                          +								<link rel="stylesheet" href="component/pear/css/pear-module/button.css" />
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 简单使用 +
                                                                                          +
                                                                                          +    +    +
                                                                                          +
                                                                                          +    +    +    +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								
                                                                                          +								
                                                                                          +															
                                                                                          +								
                                                                                          +								
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 简约样式 +
                                                                                          +
                                                                                          +    +    +    +    +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								
                                                                                          +								
                                                                                          +															
                                                                                          +								
                                                                                          +								
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 按钮大小 +
                                                                                          +
                                                                                          +    +    +    +    +
                                                                                          +
                                                                                          +    +    +    +    +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								  
                                                                                          +								  
                                                                                          +								  
                                                                                          +								  
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 按钮组 +
                                                                                          +
                                                                                          +
                                                                                          + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								
                                                                                          + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + Load 自动 +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								layui.use(["button"], function() {
                                                                                          +								    var button = layui.button;
                                                                                          +								    
                                                                                          +									button.load({
                                                                                          +								        elem:'[load]',
                                                                                          +								        time: 600,
                                                                                          +								        done: function(){
                                                                                          +									        popup.success("加载完成");
                                                                                          +								        }
                                                                                          +								    })
                                                                                          +								})
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + Load 手动 +
                                                                                          +
                                                                                          + + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								layui.use(["button"], function() {
                                                                                          +								    var button = layui.button;
                                                                                          +								    
                                                                                          +									var dom = button.load({
                                                                                          +								        elem:'[load]',
                                                                                          +								    })
                                                                                          +									
                                                                                          +								    dom.stop(function() {
                                                                                          +								        popup.failure("已停止");
                                                                                          +								    });
                                                                                          +								})
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 本页跳转 +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								layui.use(["jquery"], function() {
                                                                                          +								    var $ = layui.jquery;
                                                                                          +								    
                                                                                          +								    $("[to]").click(function(){
                                                                                          +								        top.layui.frame.changePageByElement("content","http://www.baidu.com","百度一下",true)
                                                                                          +								    })
                                                                                          +								})
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/card.html b/demo/webman/backend/plugin/admin/public/demos/document/card.html new file mode 100644 index 0000000000000000000000000000000000000000..08ff0fbfc42e2c4715c4d69cc728b79e9ccc0bb6 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/card.html @@ -0,0 +1,78 @@ + + + + + 数据卡片 + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + +
                                                                                          + +
                                                                                          + +
                                                                                          +
                                                                                          + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/core.html b/demo/webman/backend/plugin/admin/public/demos/document/core.html new file mode 100644 index 0000000000000000000000000000000000000000..1c81d15162353bc72ee302fe540972102eccbca6 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/core.html @@ -0,0 +1,219 @@ + + + + + 数据卡片 + + + +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                                                          方法描述参数备注
                                                                                          admin.collapseSide侧边收缩无无模式限制
                                                                                          admin.refreshThis刷新当前无无模式限制
                                                                                          admin.refresh刷新指定id: 编号仅限 TAB 模式
                                                                                          admin.addTab新增卡片id:编号,title:标题,url:路径仅限 TAB 模式
                                                                                          admin.changeTabTitle修改标题id:编号,title:标题仅限 TAB 模式
                                                                                          admin.closeTab关闭卡片id:编号仅限 TAB 模式
                                                                                          admin.closeCurrentTab关闭当前无仅限 TAB 模式
                                                                                          admin.closeAllTab关闭所有无仅限 TAB 模式
                                                                                          admin.closeOtherTab关闭其他无仅限 TAB 模式
                                                                                          admin.changeIframe切换页面id:编号,title:标题,url:路径仅限 IFRAME 模式
                                                                                          admin.jump兼容切换id:编号,title:标题,url:路径无模式限制
                                                                                          admin.fullScreen全屏模式无无模式限制
                                                                                          +
                                                                                          +
                                                                                          + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/count.html b/demo/webman/backend/plugin/admin/public/demos/document/count.html new file mode 100644 index 0000000000000000000000000000000000000000..39f93de44af22de836f5123872822eeaafbb1561 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/count.html @@ -0,0 +1,124 @@ + + + + + 数字滚动 + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 开发环境 +
                                                                                          +
                                                                                          + Pear Count 数据滚动特效 +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								<script src="component/layui/layui.js"></script>
                                                                                          +								 并
                                                                                          +								<script src="component/pear/pear.js"></script>
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 简单使用 +
                                                                                          +
                                                                                          +

                                                                                          0

                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								layui.use(['count'], function() {
                                                                                          +								    var count = layui.count;
                                                                                          +									
                                                                                          +								    count.up("number1", {
                                                                                          +								        time: 8000,
                                                                                          +								        num: 4540.34,
                                                                                          +								        regulator: 100
                                                                                          +								    })
                                                                                          +								})
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 保留小数 +
                                                                                          +
                                                                                          +

                                                                                          0

                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +							layui.use(['count'], function() {
                                                                                          +							    var count = layui.count;
                                                                                          +								
                                                                                          +							    count.up("number2", {
                                                                                          +							        time: 8000,
                                                                                          +							        num: 4540.34,
                                                                                          +							        bit: 2,
                                                                                          +							        regulator: 100
                                                                                          +							    })
                                                                                          +							})
                                                                                          +						
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + + +
                                                                                          + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/drawer.html b/demo/webman/backend/plugin/admin/public/demos/document/drawer.html new file mode 100644 index 0000000000000000000000000000000000000000..a97e4d0f63a298520637cb46dbcbcafd3de89fe9 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/drawer.html @@ -0,0 +1,597 @@ + + + + + 抽屉组件 + + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          开发环境
                                                                                          +
                                                                                          + Drawer 在 弹出层 UI 上带来不一样的体验. +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								<script src="component/layui/layui.js"></script>
                                                                                          +								 并
                                                                                          +								<script src="component/pear/pear.js"></script>
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          抽屉
                                                                                          +
                                                                                          + + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								layui.use(['drawer'], function() {
                                                                                          +									var drawer = layui.drawer;
                                                                                          +
                                                                                          +								    drawer.open({
                                                                                          +								        direction: "right",
                                                                                          +								        dom: ".layer-top",
                                                                                          +								        distance: "30%"
                                                                                          +								    });
                                                                                          +								})
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          进阶
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								var dom;
                                                                                          +
                                                                                          +								$(".drawer-close-mask").click(function() {
                                                                                          +								    dom = drawer.open({
                                                                                          +								        direction: "right",
                                                                                          +								        dom: ".layer-close-mask",
                                                                                          +								        distance: "30%",
                                                                                          +								        maskClose: false
                                                                                          +								    });
                                                                                          +								})
                                                                                          +
                                                                                          +								$("#btnClose").click(function() {
                                                                                          +								    dom.close();
                                                                                          +								})
                                                                                          +
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          扩展
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								layui.use(['drawer'], function() {
                                                                                          +									var drawer = layui.drawer;
                                                                                          +
                                                                                          +								    $(".drawer-auto-close").click(function() {
                                                                                          +								        dom = drawer.open({
                                                                                          +								            direction: "right",
                                                                                          +								            dom: ".layer-auto-close",
                                                                                          +								            distance: "30%",
                                                                                          +								            maskClose: false,
                                                                                          +								            time: 1000
                                                                                          +								        });
                                                                                          +								    })
                                                                                          +								})
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          扩展
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								layui.use(['drawer'], function() {
                                                                                          +									var drawer = layui.drawer;
                                                                                          +
                                                                                          +								    $(".drawer-auto-close").click(function() {
                                                                                          +								        dom = drawer.open({
                                                                                          +								            direction: "right",
                                                                                          +								            dom: ".layer-auto-close",
                                                                                          +								            distance: "30%",
                                                                                          +								            success:function(){
                                                                                          +								                layer.msg("触发回调函数");
                                                                                          +								            }
                                                                                          +								        });
                                                                                          +								    })
                                                                                          +								})
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          扩展
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +									layui.use(['drawer'], function() {
                                                                                          +									  var drawer = layui.drawer;
                                                                                          +									    $("#targetDemo").click(function () {
                                                                                          +									      drawer.open({
                                                                                          +									      // 指定挂载节点
                                                                                          +									      target: "#targetEl"
                                                                                          +									      direction: "right",
                                                                                          +									      dom: ".layer-right",
                                                                                          +									      distance: "50%",
                                                                                          +									      });
                                                                                          +									})
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          基于 layer 的抽屉扩展
                                                                                          +
                                                                                          +

                                                                                          兼容原版 drawer 所有参数,要使用 layer 扩展,设置 legacy 选项为 false 即可

                                                                                          + + + + + + + + +
                                                                                          + +
                                                                                          +
                                                                                          指定容器内打开,需使用 layer 捕获层模式,并设置目标容器 style="overflow: hidden; + position: relative;"
                                                                                          +
                                                                                          + 使用 url 参数指定抽屉代码片段地址,会使用 ajax 请求将代码片段拼接到抽屉中,和原来的页面在同一个页面上, 传值更方便。注意片段和原页面不能出现相同的 ID。 +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +											$("#layerDrawerLeft").click(function(){
                                                                                          +											  drawer.open({
                                                                                          +											    legacy: false,
                                                                                          +											    offset: 'l',
                                                                                          +											    area: "30%",
                                                                                          +											    content: "left内容",
                                                                                          +											  })
                                                                                          +											})
                                                                                          +											$("#layerDrawerRight").click(function () {
                                                                                          +											  drawer.open({
                                                                                          +											    legacy: false,
                                                                                          +											    offset: 'r',
                                                                                          +											    area: "30%",
                                                                                          +											    content: "right内容",
                                                                                          +											  })
                                                                                          +											})
                                                                                          +											$("#layerDrawerTop").click(function () {
                                                                                          +											  drawer.open({
                                                                                          +											    legacy: false,
                                                                                          +										      offset: "t",
                                                                                          +											    content: "top内容",
                                                                                          +											  })
                                                                                          +											})
                                                                                          +											$("#layerDrawerBottom").click(function () {
                                                                                          +											  drawer.open({
                                                                                          +											    legacy: false,
                                                                                          +											    offset: "b",
                                                                                          +											    content: "bottom内容",
                                                                                          +											  })
                                                                                          +											})
                                                                                          +
                                                                                          +											$("#layerDrawer").click(function () {
                                                                                          +											  var index = drawer.open({
                                                                                          +											    legacy: false,
                                                                                          +											    title: ['标题', 'font-size:16px;color:#2d8cf0'],
                                                                                          +											    maxmin: true,
                                                                                          +											    offset: "r",
                                                                                          +											    area: "30%",
                                                                                          +											    content: "抽屉内容",
                                                                                          +											    btn:"关闭",
                                                                                          +											    yes:function(index,layero){
                                                                                          +											      drawer.close(index);
                                                                                          +											      console.log(index,layero);
                                                                                          +											    },
                                                                                          +											    btnAlign: "l",
                                                                                          +											    closeBtn: 1,
                                                                                          +											  })
                                                                                          +											})
                                                                                          +
                                                                                          +											$("#layerDrawerParent").click(function () {
                                                                                          +
                                                                                          +											  var index = parent.layui.drawer.open({
                                                                                          +												    legacy: false,
                                                                                          +												    title: ['标题', 'font-size:16px;color:#2d8cf0'],
                                                                                          +												    maxmin: true,
                                                                                          +												    offset: "r",
                                                                                          +												    area: "30%",
                                                                                          +												    content: "抽屉内容",
                                                                                          +												    btn:"关闭",
                                                                                          +												    yes:function(index,layero){
                                                                                          +												      drawer.close(index);
                                                                                          +												      console.log(index,layero);
                                                                                          +												    },
                                                                                          +												    btnAlign: "l",
                                                                                          +												    closeBtn: 1,
                                                                                          +												})
                                                                                          +											})
                                                                                          +
                                                                                          +											$("#layertargetDemo").click(function () {
                                                                                          +											    drawer.open({
                                                                                          +											    legacy: false,
                                                                                          +											    target: "#layertargetEl",
                                                                                          +											    direction: "right",
                                                                                          +											    dom: ".layer-right",
                                                                                          +											    distance: "50%",
                                                                                          +											    });
                                                                                          +											})
                                                                                          +
                                                                                          +											$("#layerDrawerIframe").click(function () {
                                                                                          +											  drawer.open({
                                                                                          +											  legacy: false,
                                                                                          +											  title: ['用户管理', 'font-size:16px;color:#2d8cf0'],
                                                                                          +											  offset: 'r',
                                                                                          +											  area: "80%",
                                                                                          +											   maxmin: true,
                                                                                          +											   closeBtn: 1,
                                                                                          +											   iframe: window.location.origin + "/view/document/table.html"
                                                                                          +											  })
                                                                                          +											})
                                                                                          +
                                                                                          +											$("#layerDrawerURL").click(function () {
                                                                                          +											   drawer.open({
                                                                                          +										     legacy: false,
                                                                                          +										     title: ['用户管理', 'font-size:16px;color:#2d8cf0'],
                                                                                          +											   offset: 'r',
                                                                                          +											   area: "80%",
                                                                                          +											   maxmin: true,
                                                                                          +											   closeBtn: 1,
                                                                                          +											   url: window.location.origin + "/view/document/drawerFragment.html"
                                                                                          +											   })
                                                                                          +											})
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + + + + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/drawerFragment.html b/demo/webman/backend/plugin/admin/public/demos/document/drawerFragment.html new file mode 100644 index 0000000000000000000000000000000000000000..0630bb86414dd93251fc52a5d0b5ead39d6c1fe1 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/drawerFragment.html @@ -0,0 +1,385 @@ + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          + +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/dtree.html b/demo/webman/backend/plugin/admin/public/demos/document/dtree.html new file mode 100644 index 0000000000000000000000000000000000000000..2560b2fbe0ed7a52473ad33c38b833f4674047a8 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/dtree.html @@ -0,0 +1,165 @@ + + + + + 树形结构 + + + +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          开发环境
                                                                                          +
                                                                                          Dtree 提供 树状态 的数据结构展示
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          显示代码

                                                                                          +
                                                                                          +
                                                                                          +								<link href="component/pear/css/pear.css" rel="stylesheet" />
                                                                                          +								 并
                                                                                          +								<script src="component/layui/layui.js"></script>
                                                                                          +								 并
                                                                                          +								<script src="component/pear/pear.js"></script>
                                                                                          +							
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          +
                                                                                          + 嵌套数据格式 +
                                                                                          +
                                                                                          +
                                                                                            +
                                                                                            +
                                                                                            +
                                                                                            +
                                                                                            +
                                                                                            +
                                                                                            +

                                                                                            显示代码

                                                                                            +
                                                                                            +
                                                                                            +								layui.use(['dtree'], function () {
                                                                                            +								    dtree = layui.dtree;
                                                                                            +								 
                                                                                            +								    dtree.render({
                                                                                            +								        elem: "#demoTree",
                                                                                            +								        initLevel: "1",
                                                                                            +								        method: 'get',
                                                                                            +								        url: "admin/data/dtree.json"
                                                                                            +								    });
                                                                                            +								});
                                                                                            +							
                                                                                            +
                                                                                            +
                                                                                            +
                                                                                            +
                                                                                            +
                                                                                            +
                                                                                            +
                                                                                            + 嵌套数据格式 +
                                                                                            +
                                                                                            +
                                                                                              +
                                                                                              +
                                                                                              +
                                                                                              +
                                                                                              +
                                                                                              +
                                                                                              +

                                                                                              显示代码

                                                                                              +
                                                                                              +
                                                                                              +								layui.use(['dtree'], function () {
                                                                                              +								    dtree = layui.dtree;
                                                                                              +								 
                                                                                              +								    dtree.render({
                                                                                              +								        elem: "#demoTree",
                                                                                              +								        initLevel: "1",
                                                                                              +								        method: 'get',
                                                                                              +								        url: "admin/data/dtree.json",
                                                                                              +								        dataFormat: "list", 
                                                                                              +								        checkbar: true
                                                                                              +								    });
                                                                                              +								});
                                                                                              +							
                                                                                              +
                                                                                              +
                                                                                              +
                                                                                              +
                                                                                              +
                                                                                              +
                                                                                              +
                                                                                              + 下拉树 +
                                                                                              +
                                                                                              +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								layui.use(['dtree'], function () {
                                                                                                +								    dtree = layui.dtree;
                                                                                                +								 
                                                                                                +								    dtree.render({
                                                                                                +								        elem: "#demoTree2",
                                                                                                +								        initLevel: "1",
                                                                                                +								        method: 'get',
                                                                                                +								        url: "admin/data/dtree.json",
                                                                                                +								        select: true
                                                                                                +								    });
                                                                                                +								});
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/document/encrypt.html b/demo/webman/backend/plugin/admin/public/demos/document/encrypt.html new file mode 100644 index 0000000000000000000000000000000000000000..e6054f32d8d94b06e36ec5f0b57c6d28c7b0c7a3 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/encrypt.html @@ -0,0 +1,160 @@ + + + + + 哈希加密 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 开发环境 +
                                                                                                +
                                                                                                + Pear encrypt 为前端开发 提供 加密服务 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								<script src="component/layui/layui.js"></script>
                                                                                                +								 并
                                                                                                +								<script src="component/pear/pear.js"></script>
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                加密操作
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                加密结果
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								layui.use(['encrypt'], function() {
                                                                                                +									var encrypt = layui.encrypt;
                                                                                                +								
                                                                                                +								    encrypt.md5( str );
                                                                                                +									
                                                                                                +								    encrypt.sha1( str );
                                                                                                +									
                                                                                                +								    encrypt.sha256( str );
                                                                                                +								})
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                API 文档
                                                                                                +
                                                                                                +
                                                                                                + encrypt.md5( str ) -- MD5加密 +
                                                                                                +
                                                                                                + encrypt.sha1( str ) -- SHA1加密 +
                                                                                                +
                                                                                                + encrypt.sha256( str ) -- SHA256加密 +
                                                                                                +
                                                                                                + encrypt.sha512( str ) -- SHA512加密 +
                                                                                                +
                                                                                                + encrypt.rmd160( str ) -- RMD160加密 +
                                                                                                +
                                                                                                + encrypt.crc32( str ) -- CRC32加密 +
                                                                                                +
                                                                                                + encrypt.Base64Encode( str ) -- BASE64加密 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/form.html b/demo/webman/backend/plugin/admin/public/demos/document/form.html new file mode 100644 index 0000000000000000000000000000000000000000..0ce7861dfe778e1177d78a1bd298d0eb32f6738c --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/form.html @@ -0,0 +1,180 @@ + + + + + + 表单页面 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开发环境
                                                                                                +
                                                                                                + Pear 基于 Form 的基础上扩展样式 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								<link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                                +								 或
                                                                                                +								<link rel="stylesheet" href="component/pear/css/pear-module/form.css" />
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                输入框
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                下拉选择框
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                复选框
                                                                                                +
                                                                                                +
                                                                                                + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                扩展样式
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                文本域
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开关
                                                                                                +
                                                                                                +
                                                                                                +    +    +    +    +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                单选框
                                                                                                +
                                                                                                +
                                                                                                + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/fullscreen.html b/demo/webman/backend/plugin/admin/public/demos/document/fullscreen.html new file mode 100644 index 0000000000000000000000000000000000000000..adade74a7e70925d0e6cfd641e51bf665b62e07e --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/fullscreen.html @@ -0,0 +1,126 @@ + + + + + 全屏组件 + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开发环境
                                                                                                +
                                                                                                + fullscreen 用于控制页面或元素全屏 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +                <link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                                +                 并
                                                                                                +                <script src="component/layui/layui.js"></script>
                                                                                                +                 并
                                                                                                +                <script src="component/pear/pear.js"></script>
                                                                                                +            
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                全屏控制
                                                                                                +
                                                                                                + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +				layui.use(['fullscreen'], function() {
                                                                                                +    var fullscreen = layui.fullscreen;
                                                                                                +     fullscreen.fullScreen();
                                                                                                +	    fullscreen.fullClose();
                                                                                                +	    fullscreen.fullScreen("#fulltarget");
                                                                                                +	    fullscreen.isFullscreen();
                                                                                                +
                                                                                                +			})
                                                                                                +			
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                指定容器全屏
                                                                                                +
                                                                                                +
                                                                                                + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/icon.html b/demo/webman/backend/plugin/admin/public/demos/document/icon.html new file mode 100644 index 0000000000000000000000000000000000000000..de0009431ad2b671210d91602e86c9251267bf51 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/icon.html @@ -0,0 +1,2195 @@ + + + + + 图标列表 + + + + + + + + + + +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                  + +
                                                                                                • + +
                                                                                                  加载
                                                                                                  +
                                                                                                  &#xe6f0;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  download
                                                                                                  +
                                                                                                  &#xe68d;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  electronics
                                                                                                  +
                                                                                                  &#xe68e;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  drag
                                                                                                  +
                                                                                                  &#xe68f;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  elipsis
                                                                                                  +
                                                                                                  &#xe690;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  export
                                                                                                  +
                                                                                                  &#xe691;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  explain
                                                                                                  +
                                                                                                  &#xe692;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  edit
                                                                                                  +
                                                                                                  &#xe693;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  eye-close
                                                                                                  +
                                                                                                  &#xe694;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  email
                                                                                                  +
                                                                                                  &#xe695;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  error
                                                                                                  +
                                                                                                  &#xe696;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  favorite
                                                                                                  +
                                                                                                  &#xe697;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  file-common
                                                                                                  +
                                                                                                  &#xe698;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  file-delete
                                                                                                  +
                                                                                                  &#xe699;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  file-add
                                                                                                  +
                                                                                                  &#xe69a;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  film
                                                                                                  +
                                                                                                  &#xe69b;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  fabulous
                                                                                                  +
                                                                                                  &#xe69c;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  file
                                                                                                  +
                                                                                                  &#xe69d;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  folder-close
                                                                                                  +
                                                                                                  &#xe69e;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  filter
                                                                                                  +
                                                                                                  &#xe69f;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  good
                                                                                                  +
                                                                                                  &#xe6a0;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  hide
                                                                                                  +
                                                                                                  &#xe6a1;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  home
                                                                                                  +
                                                                                                  &#xe6a2;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  history
                                                                                                  +
                                                                                                  &#xe6a3;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  file-open
                                                                                                  +
                                                                                                  &#xe6a4;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  forward
                                                                                                  +
                                                                                                  &#xe6a5;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  import
                                                                                                  +
                                                                                                  &#xe6a6;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  image-text
                                                                                                  +
                                                                                                  &#xe6a7;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  keyboard-26
                                                                                                  +
                                                                                                  &#xe6a8;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  keyboard-9
                                                                                                  +
                                                                                                  &#xe6a9;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  link
                                                                                                  +
                                                                                                  &#xe6aa;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  layout
                                                                                                  +
                                                                                                  &#xe6ab;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  fullscreen-shrink
                                                                                                  +
                                                                                                  &#xe6ac;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  layers
                                                                                                  +
                                                                                                  &#xe6ad;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  lock
                                                                                                  +
                                                                                                  &#xe6ae;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  fullscreen-expand
                                                                                                  +
                                                                                                  &#xe6af;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  map
                                                                                                  +
                                                                                                  &#xe6b0;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  meh
                                                                                                  +
                                                                                                  &#xe6b1;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  menu
                                                                                                  +
                                                                                                  &#xe6b2;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  loading
                                                                                                  +
                                                                                                  &#xe6b3;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  help
                                                                                                  +
                                                                                                  &#xe6b4;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  minus-circle
                                                                                                  +
                                                                                                  &#xe6b5;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  modular
                                                                                                  +
                                                                                                  &#xe6b6;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  notification
                                                                                                  +
                                                                                                  &#xe6b7;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  mic
                                                                                                  +
                                                                                                  &#xe6b8;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  more
                                                                                                  +
                                                                                                  &#xe6b9;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  pad
                                                                                                  +
                                                                                                  &#xe6ba;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  operation
                                                                                                  +
                                                                                                  &#xe6bb;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  play
                                                                                                  +
                                                                                                  &#xe6bc;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  print
                                                                                                  +
                                                                                                  &#xe6bd;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  mobile-phone
                                                                                                  +
                                                                                                  &#xe6be;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  minus
                                                                                                  +
                                                                                                  &#xe6bf;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  navigation
                                                                                                  +
                                                                                                  &#xe6c0;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  pdf
                                                                                                  +
                                                                                                  &#xe6c1;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  prompt
                                                                                                  +
                                                                                                  &#xe6c2;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  move
                                                                                                  +
                                                                                                  &#xe6c3;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  refresh
                                                                                                  +
                                                                                                  &#xe6c4;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  run-up
                                                                                                  +
                                                                                                  &#xe6c5;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  picture
                                                                                                  +
                                                                                                  &#xe6c6;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  run-in
                                                                                                  +
                                                                                                  &#xe6c7;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  pin
                                                                                                  +
                                                                                                  &#xe6c8;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  save
                                                                                                  +
                                                                                                  &#xe6c9;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  search
                                                                                                  +
                                                                                                  &#xe6ca;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  share
                                                                                                  +
                                                                                                  &#xe6cb;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  scanning
                                                                                                  +
                                                                                                  &#xe6cc;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  security
                                                                                                  +
                                                                                                  &#xe6cd;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  sign-out
                                                                                                  +
                                                                                                  &#xe6ce;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  select
                                                                                                  +
                                                                                                  &#xe6cf;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  stop
                                                                                                  +
                                                                                                  &#xe6d0;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  success
                                                                                                  +
                                                                                                  &#xe6d1;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  smile
                                                                                                  +
                                                                                                  &#xe6d2;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  switch
                                                                                                  +
                                                                                                  &#xe6d3;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  setting
                                                                                                  +
                                                                                                  &#xe6d4;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  survey
                                                                                                  +
                                                                                                  &#xe6d5;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  task
                                                                                                  +
                                                                                                  &#xe6d6;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  skip
                                                                                                  +
                                                                                                  &#xe6d7;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  text
                                                                                                  +
                                                                                                  &#xe6d8;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  time
                                                                                                  +
                                                                                                  &#xe6d9;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  telephone-out
                                                                                                  +
                                                                                                  &#xe6da;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  toggle-left
                                                                                                  +
                                                                                                  &#xe6db;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  toggle-right
                                                                                                  +
                                                                                                  &#xe6dc;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  telephone
                                                                                                  +
                                                                                                  &#xe6dd;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  top
                                                                                                  +
                                                                                                  &#xe6de;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  unlock
                                                                                                  +
                                                                                                  &#xe6df;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  user
                                                                                                  +
                                                                                                  &#xe6e0;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  upload
                                                                                                  +
                                                                                                  &#xe6e1;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  work
                                                                                                  +
                                                                                                  &#xe6e2;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  training
                                                                                                  +
                                                                                                  &#xe6e3;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  warning
                                                                                                  +
                                                                                                  &#xe6e4;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  zoom-in
                                                                                                  +
                                                                                                  &#xe6e5;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  zoom-out
                                                                                                  +
                                                                                                  &#xe6e6;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  add-bold
                                                                                                  +
                                                                                                  &#xe6e7;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  arrow-left-bold
                                                                                                  +
                                                                                                  &#xe6e8;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  arrow-up-bold
                                                                                                  +
                                                                                                  &#xe6e9;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  close-bold
                                                                                                  +
                                                                                                  &#xe6ea;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  arrow-down-bold
                                                                                                  +
                                                                                                  &#xe6eb;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  minus-bold
                                                                                                  +
                                                                                                  &#xe6ec;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  arrow-right-bold
                                                                                                  +
                                                                                                  &#xe6ed;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  select-bold
                                                                                                  +
                                                                                                  &#xe6ee;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  column-3
                                                                                                  +
                                                                                                  &#xe663;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  column-4
                                                                                                  +
                                                                                                  &#xe664;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  add
                                                                                                  +
                                                                                                  &#xe665;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  add-circle
                                                                                                  +
                                                                                                  &#xe666;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  adjust
                                                                                                  +
                                                                                                  &#xe667;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  arrow-up-circle
                                                                                                  +
                                                                                                  &#xe668;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  arrow-right-circle
                                                                                                  +
                                                                                                  &#xe669;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  arrow-down
                                                                                                  +
                                                                                                  &#xe66a;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  ashbin
                                                                                                  +
                                                                                                  &#xe66b;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  arrow-right
                                                                                                  +
                                                                                                  &#xe66c;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  browse
                                                                                                  +
                                                                                                  &#xe66d;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  bottom
                                                                                                  +
                                                                                                  &#xe66e;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  back
                                                                                                  +
                                                                                                  &#xe66f;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  bad
                                                                                                  +
                                                                                                  &#xe670;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  arrow-double-left
                                                                                                  +
                                                                                                  &#xe671;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  arrow-left-circle
                                                                                                  +
                                                                                                  &#xe672;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  arrow-double-right
                                                                                                  +
                                                                                                  &#xe673;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  caps-lock
                                                                                                  +
                                                                                                  &#xe674;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  camera
                                                                                                  +
                                                                                                  &#xe675;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  chart-bar
                                                                                                  +
                                                                                                  &#xe676;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  attachment
                                                                                                  +
                                                                                                  &#xe677;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  code
                                                                                                  +
                                                                                                  &#xe678;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  close
                                                                                                  +
                                                                                                  &#xe679;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  check-item
                                                                                                  +
                                                                                                  &#xe67a;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  calendar
                                                                                                  +
                                                                                                  &#xe67b;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  comment
                                                                                                  +
                                                                                                  &#xe67c;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  column-vertical
                                                                                                  +
                                                                                                  &#xe67d;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  column-horizontal
                                                                                                  +
                                                                                                  &#xe67e;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  complete
                                                                                                  +
                                                                                                  &#xe67f;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  chart-pie
                                                                                                  +
                                                                                                  &#xe680;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  cry
                                                                                                  +
                                                                                                  &#xe681;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  customer-service
                                                                                                  +
                                                                                                  &#xe682;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  delete
                                                                                                  +
                                                                                                  &#xe683;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  direction-down
                                                                                                  +
                                                                                                  &#xe684;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  copy
                                                                                                  +
                                                                                                  &#xe685;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  cut
                                                                                                  +
                                                                                                  &#xe686;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  data-view
                                                                                                  +
                                                                                                  &#xe687;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  direction-down-circle
                                                                                                  +
                                                                                                  &#xe688;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  direction-right
                                                                                                  +
                                                                                                  &#xe689;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  direction-up
                                                                                                  +
                                                                                                  &#xe68a;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  discount
                                                                                                  +
                                                                                                  &#xe68b;
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  direction-left
                                                                                                  +
                                                                                                  &#xe68c;
                                                                                                  +
                                                                                                • +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                  + +
                                                                                                • + +
                                                                                                  + 加载 +
                                                                                                  +
                                                                                                  .pear-icon-load +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + download +
                                                                                                  +
                                                                                                  .pear-icon-download +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + electronics +
                                                                                                  +
                                                                                                  .pear-icon-electronics +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + drag +
                                                                                                  +
                                                                                                  .pear-icon-drag +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + elipsis +
                                                                                                  +
                                                                                                  .pear-icon-elipsis +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + export +
                                                                                                  +
                                                                                                  .pear-icon-export +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + explain +
                                                                                                  +
                                                                                                  .pear-icon-explain +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + edit +
                                                                                                  +
                                                                                                  .pear-icon-edit +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + eye-close +
                                                                                                  +
                                                                                                  .pear-icon-eye-close +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + email +
                                                                                                  +
                                                                                                  .pear-icon-email +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + error +
                                                                                                  +
                                                                                                  .pear-icon-error +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + favorite +
                                                                                                  +
                                                                                                  .pear-icon-favorite +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + file-common +
                                                                                                  +
                                                                                                  .pear-icon-file-common +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + file-delete +
                                                                                                  +
                                                                                                  .pear-icon-file-delete +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + file-add +
                                                                                                  +
                                                                                                  .pear-icon-file-add +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + film +
                                                                                                  +
                                                                                                  .pear-icon-film +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + fabulous +
                                                                                                  +
                                                                                                  .pear-icon-fabulous +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + file +
                                                                                                  +
                                                                                                  .pear-icon-file +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + folder-close +
                                                                                                  +
                                                                                                  .pear-icon-folder-close +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + filter +
                                                                                                  +
                                                                                                  .pear-icon-filter +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + good +
                                                                                                  +
                                                                                                  .pear-icon-good +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + hide +
                                                                                                  +
                                                                                                  .pear-icon-hide +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + home +
                                                                                                  +
                                                                                                  .pear-icon-home +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + history +
                                                                                                  +
                                                                                                  .pear-icon-history +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + file-open +
                                                                                                  +
                                                                                                  .pear-icon-file-open +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + forward +
                                                                                                  +
                                                                                                  .pear-icon-forward +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + import +
                                                                                                  +
                                                                                                  .pear-icon-import +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + image-text +
                                                                                                  +
                                                                                                  .pear-icon-image-text +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + keyboard-26 +
                                                                                                  +
                                                                                                  .pear-icon-keyboard-26 +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + keyboard-9 +
                                                                                                  +
                                                                                                  .pear-icon-keyboard-9 +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + link +
                                                                                                  +
                                                                                                  .pear-icon-link +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + layout +
                                                                                                  +
                                                                                                  .pear-icon-layout +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + fullscreen-shrink +
                                                                                                  +
                                                                                                  .pear-icon-fullscreen-shrink +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + layers +
                                                                                                  +
                                                                                                  .pear-icon-layers +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + lock +
                                                                                                  +
                                                                                                  .pear-icon-lock +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + fullscreen-expand +
                                                                                                  +
                                                                                                  .pear-icon-fullscreen-expand +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + map +
                                                                                                  +
                                                                                                  .pear-icon-map +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + meh +
                                                                                                  +
                                                                                                  .pear-icon-meh +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + menu +
                                                                                                  +
                                                                                                  .pear-icon-menu +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + loading +
                                                                                                  +
                                                                                                  .pear-icon-loading +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + help +
                                                                                                  +
                                                                                                  .pear-icon-help +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + minus-circle +
                                                                                                  +
                                                                                                  .pear-icon-minus-circle +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + modular +
                                                                                                  +
                                                                                                  .pear-icon-modular +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + notification +
                                                                                                  +
                                                                                                  .pear-icon-notification +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + mic +
                                                                                                  +
                                                                                                  .pear-icon-mic +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + more +
                                                                                                  +
                                                                                                  .pear-icon-more +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + pad +
                                                                                                  +
                                                                                                  .pear-icon-pad +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + operation +
                                                                                                  +
                                                                                                  .pear-icon-operation +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + play +
                                                                                                  +
                                                                                                  .pear-icon-play +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + print +
                                                                                                  +
                                                                                                  .pear-icon-print +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + mobile-phone +
                                                                                                  +
                                                                                                  .pear-icon-mobile-phone +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + minus +
                                                                                                  +
                                                                                                  .pear-icon-minus +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + navigation +
                                                                                                  +
                                                                                                  .pear-icon-navigation +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + pdf +
                                                                                                  +
                                                                                                  .pear-icon-pdf +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + prompt +
                                                                                                  +
                                                                                                  .pear-icon-prompt +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + move +
                                                                                                  +
                                                                                                  .pear-icon-move +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + refresh +
                                                                                                  +
                                                                                                  .pear-icon-refresh +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + run-up +
                                                                                                  +
                                                                                                  .pear-icon-run-up +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + picture +
                                                                                                  +
                                                                                                  .pear-icon-picture +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + run-in +
                                                                                                  +
                                                                                                  .pear-icon-run-in +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + pin +
                                                                                                  +
                                                                                                  .pear-icon-pin +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + save +
                                                                                                  +
                                                                                                  .pear-icon-save +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + search +
                                                                                                  +
                                                                                                  .pear-icon-search +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + share +
                                                                                                  +
                                                                                                  .pear-icon-share +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + scanning +
                                                                                                  +
                                                                                                  .pear-icon-scanning +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + security +
                                                                                                  +
                                                                                                  .pear-icon-security +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + sign-out +
                                                                                                  +
                                                                                                  .pear-icon-sign-out +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + select +
                                                                                                  +
                                                                                                  .pear-icon-select +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + stop +
                                                                                                  +
                                                                                                  .pear-icon-stop +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + success +
                                                                                                  +
                                                                                                  .pear-icon-success +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + smile +
                                                                                                  +
                                                                                                  .pear-icon-smile +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + switch +
                                                                                                  +
                                                                                                  .pear-icon-switch +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + setting +
                                                                                                  +
                                                                                                  .pear-icon-setting +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + survey +
                                                                                                  +
                                                                                                  .pear-icon-survey +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + task +
                                                                                                  +
                                                                                                  .pear-icon-task +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + skip +
                                                                                                  +
                                                                                                  .pear-icon-skip +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + text +
                                                                                                  +
                                                                                                  .pear-icon-text +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + time +
                                                                                                  +
                                                                                                  .pear-icon-time +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + telephone-out +
                                                                                                  +
                                                                                                  .pear-icon-telephone-out +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + toggle-left +
                                                                                                  +
                                                                                                  .pear-icon-toggle-left +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + toggle-right +
                                                                                                  +
                                                                                                  .pear-icon-toggle-right +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + telephone +
                                                                                                  +
                                                                                                  .pear-icon-telephone +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + top +
                                                                                                  +
                                                                                                  .pear-icon-top +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + unlock +
                                                                                                  +
                                                                                                  .pear-icon-unlock +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + user +
                                                                                                  +
                                                                                                  .pear-icon-user +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + upload +
                                                                                                  +
                                                                                                  .pear-icon-upload +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + work +
                                                                                                  +
                                                                                                  .pear-icon-work +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + training +
                                                                                                  +
                                                                                                  .pear-icon-training +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + warning +
                                                                                                  +
                                                                                                  .pear-icon-warning +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + zoom-in +
                                                                                                  +
                                                                                                  .pear-icon-zoom-in +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + zoom-out +
                                                                                                  +
                                                                                                  .pear-icon-zoom-out +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + add-bold +
                                                                                                  +
                                                                                                  .pear-icon-add-bold +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + arrow-left-bold +
                                                                                                  +
                                                                                                  .pear-icon-arrow-left-bold +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + arrow-up-bold +
                                                                                                  +
                                                                                                  .pear-icon-arrow-up-bold +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + close-bold +
                                                                                                  +
                                                                                                  .pear-icon-close-bold +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + arrow-down-bold +
                                                                                                  +
                                                                                                  .pear-icon-arrow-down-bold +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + minus-bold +
                                                                                                  +
                                                                                                  .pear-icon-minus-bold +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + arrow-right-bold +
                                                                                                  +
                                                                                                  .pear-icon-arrow-right-bold +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + select-bold +
                                                                                                  +
                                                                                                  .pear-icon-select-bold +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + column-3 +
                                                                                                  +
                                                                                                  .pear-icon-3column +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + column-4 +
                                                                                                  +
                                                                                                  .pear-icon-column-4 +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + add +
                                                                                                  +
                                                                                                  .pear-icon-add +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + add-circle +
                                                                                                  +
                                                                                                  .pear-icon-add-circle +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + adjust +
                                                                                                  +
                                                                                                  .pear-icon-adjust +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + arrow-up-circle +
                                                                                                  +
                                                                                                  .pear-icon-arrow-up-circle +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + arrow-right-circle +
                                                                                                  +
                                                                                                  .pear-icon-arrow-right-circle +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + arrow-down +
                                                                                                  +
                                                                                                  .pear-icon-arrow-down +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + ashbin +
                                                                                                  +
                                                                                                  .pear-icon-ashbin +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + arrow-right +
                                                                                                  +
                                                                                                  .pear-icon-arrow-right +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + browse +
                                                                                                  +
                                                                                                  .pear-icon-browse +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + bottom +
                                                                                                  +
                                                                                                  .pear-icon-bottom +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + back +
                                                                                                  +
                                                                                                  .pear-icon-back +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + bad +
                                                                                                  +
                                                                                                  .pear-icon-bad +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + arrow-double-left +
                                                                                                  +
                                                                                                  .pear-icon-arrow-double-left +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + arrow-left-circle +
                                                                                                  +
                                                                                                  .pear-icon-arrow-left-circle +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + arrow-double-right +
                                                                                                  +
                                                                                                  .pear-icon-arrow-double-right +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + caps-lock +
                                                                                                  +
                                                                                                  .pear-icon-caps-lock +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + camera +
                                                                                                  +
                                                                                                  .pear-icon-camera +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + chart-bar +
                                                                                                  +
                                                                                                  .pear-icon-chart-bar +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + attachment +
                                                                                                  +
                                                                                                  .pear-icon-attachment +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + code +
                                                                                                  +
                                                                                                  .pear-icon-code +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + close +
                                                                                                  +
                                                                                                  .pear-icon-close +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + check-item +
                                                                                                  +
                                                                                                  .pear-icon-check-item +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + calendar +
                                                                                                  +
                                                                                                  .pear-icon-calendar +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + comment +
                                                                                                  +
                                                                                                  .pear-icon-comment +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + column-vertical +
                                                                                                  +
                                                                                                  .pear-icon-column-vertical +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + column-horizontal +
                                                                                                  +
                                                                                                  .pear-icon-column-horizontal +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + complete +
                                                                                                  +
                                                                                                  .pear-icon-complete +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + chart-pie +
                                                                                                  +
                                                                                                  .pear-icon-chart-pie +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + cry +
                                                                                                  +
                                                                                                  .pear-icon-cry +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + customer-service +
                                                                                                  +
                                                                                                  .pear-icon-customer-service +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + delete +
                                                                                                  +
                                                                                                  .pear-icon-delete +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + direction-down +
                                                                                                  +
                                                                                                  .pear-icon-direction-down +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + copy +
                                                                                                  +
                                                                                                  .pear-icon-copy +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + cut +
                                                                                                  +
                                                                                                  .pear-icon-cut +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + data-view +
                                                                                                  +
                                                                                                  .pear-icon-data-view +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + direction-down-circle +
                                                                                                  +
                                                                                                  .pear-icon-direction-down-circle +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + direction-right +
                                                                                                  +
                                                                                                  .pear-icon-direction-right +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + direction-up +
                                                                                                  +
                                                                                                  .pear-icon-direction-up +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + discount +
                                                                                                  +
                                                                                                  .pear-icon-discount +
                                                                                                  +
                                                                                                • + +
                                                                                                • + +
                                                                                                  + direction-left +
                                                                                                  +
                                                                                                  .pear-icon-direction-left +
                                                                                                  +
                                                                                                • + +
                                                                                                + +
                                                                                                +
                                                                                                + + +
                                                                                                + +
                                                                                                +
                                                                                                + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/document/iconPicker.html b/demo/webman/backend/plugin/admin/public/demos/document/iconPicker.html new file mode 100644 index 0000000000000000000000000000000000000000..2c7e926c100ccd6370b16fa02e2b7a30cae38e33 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/iconPicker.html @@ -0,0 +1,244 @@ + + + + + + + Document + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开发环境
                                                                                                +
                                                                                                + IconPicker 提供图标选择功能 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								<link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                                +								 并
                                                                                                +								<script src="component/layui/layui.js"></script>
                                                                                                +								 并
                                                                                                +								<script src="component/pear/pear.js"></script>
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 默认图标 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								layui.use(['iconPicker'], function() {
                                                                                                +								    var iconPicker = layui.iconPicker;
                                                                                                +								
                                                                                                +								    iconPicker.render({
                                                                                                +								        elem: '#iconPicker',
                                                                                                +								        type: 'fontClass',
                                                                                                +								        search: true,
                                                                                                +								        page: true,
                                                                                                +								        limit: 16,
                                                                                                +								        click: function(data) {
                                                                                                +								           console.log(data);
                                                                                                +								        },
                                                                                                +								        success: function(d) {
                                                                                                +								            console.log(d);
                                                                                                +								        }
                                                                                                +								    });
                                                                                                +									
                                                                                                +								});
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                默认选中
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								layui.use(['iconPicker'], function() {
                                                                                                +								    var iconPicker = layui.iconPicker;
                                                                                                +								
                                                                                                +								    iconPicker.render({
                                                                                                +								        elem: '#iconPicker2',
                                                                                                +								        type: 'fontClass',
                                                                                                +								        search: true,
                                                                                                +								        page: true,
                                                                                                +								        limit: 16,
                                                                                                +								        click: function(data) {
                                                                                                +								           console.log(data);
                                                                                                +								        },
                                                                                                +								        success: function(d) {
                                                                                                +								            console.log(d);
                                                                                                +								        }
                                                                                                +								    });
                                                                                                +									
                                                                                                +								});
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                不分页
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								layui.use(['iconPicker'], function() {
                                                                                                +								    var iconPicker = layui.iconPicker;
                                                                                                +								
                                                                                                +								    iconPicker.render({
                                                                                                +								        elem: '#iconPicker',
                                                                                                +								        type: 'fontClass',
                                                                                                +								        search: true,
                                                                                                +								        page: false,
                                                                                                +								        limit: 16,
                                                                                                +								        click: function(data) {
                                                                                                +								           console.log(data);
                                                                                                +								        },
                                                                                                +								        success: function(d) {
                                                                                                +								            console.log(d);
                                                                                                +								        }
                                                                                                +								    });
                                                                                                +									
                                                                                                +								});
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/document/loading.html b/demo/webman/backend/plugin/admin/public/demos/document/loading.html new file mode 100644 index 0000000000000000000000000000000000000000..9140e9d438d958d9709e6bbc20c9da593364858f --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/loading.html @@ -0,0 +1,174 @@ + + + + + 加载组件 + + + + +
                                                                                                +
                                                                                                加载组件
                                                                                                +
                                                                                                +
                                                                                                + loading.Load(1,message); +
                                                                                                +
                                                                                                + loading.Load(2,message); +
                                                                                                +
                                                                                                + loading.Load(3,message); +
                                                                                                +
                                                                                                + loading.Load(4,message); +
                                                                                                +
                                                                                                + loading.Load(5,message); +
                                                                                                +
                                                                                                + loading.remove(time); +
                                                                                                +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                加载组件
                                                                                                +
                                                                                                + + + + + + + + +
                                                                                                + +
                                                                                                +
                                                                                                + +
                                                                                                + +
                                                                                                + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/menu.html b/demo/webman/backend/plugin/admin/public/demos/document/menu.html new file mode 100644 index 0000000000000000000000000000000000000000..49e9272da26f00c9a9eadc13da8f8c6c9ca532ce --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/menu.html @@ -0,0 +1,115 @@ + + + + + 数据菜单 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开发环境
                                                                                                +
                                                                                                + Menu 数据菜单对普通菜单的深度封装 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								<link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                                +								 并
                                                                                                +								<script src="component/layui/layui.js"></script>
                                                                                                +								 并
                                                                                                +								<script src="component/pear/pear.js"></script>
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                实例
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								
                                                                                                +								var sideMenu = menu.render({
                                                                                                +								    elem: 'sideMenu',
                                                                                                +								    async: true,
                                                                                                +								    theme: "light-theme",
                                                                                                +								    height: '300px',
                                                                                                +								    control: false, 
                                                                                                +								    defaultMenu: 0,
                                                                                                +								    accordion: true,
                                                                                                +								    url: "../../demos/data/menu.json",
                                                                                                +								    parseData: false,
                                                                                                +								    done: function() {
                                                                                                +								        layer.msg("加载完成")
                                                                                                +								    }
                                                                                                +								});
                                                                                                +								
                                                                                                +								sideMenu.click(function(dom, data) {
                                                                                                +								    
                                                                                                +									layer.msg("菜单点击 : " + JSON.stringify(data));
                                                                                                +								})
                                                                                                +						
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/notice.html b/demo/webman/backend/plugin/admin/public/demos/document/notice.html new file mode 100644 index 0000000000000000000000000000000000000000..81c420069b62bf3b3d82d50431f3feb433d0f9a6 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/notice.html @@ -0,0 +1,148 @@ + + + + + + + 通知组件 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开发环境
                                                                                                +
                                                                                                + Notice 用于 消息通知 场景 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +									<link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                                +									 或
                                                                                                +									<link rel="stylesheet" href="component/pear/css/pear-module/notice.css" />
                                                                                                +									 并
                                                                                                +									<script src="component/layui/layui.js"></script>
                                                                                                +									 并
                                                                                                +									<script src="component/pear/pear.js"></script>
                                                                                                +								
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                消息提醒
                                                                                                +
                                                                                                +
                                                                                                + notice.success("成功消息") +
                                                                                                +
                                                                                                + notice.error("危险消息") +
                                                                                                +
                                                                                                + notice.warning("警告消息") +
                                                                                                +
                                                                                                + notice.info("通用消息") +
                                                                                                +
                                                                                                +
                                                                                                + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +									layui.use(['notice', 'jquery', 'layer', 'code'], function() {
                                                                                                +									    var notice = layui.notice;
                                                                                                +										                         
                                                                                                +									    notice.success("成功消息")
                                                                                                +									    notice.error("危险消息")
                                                                                                +									    notice.warning("警告消息")
                                                                                                +									    notice.info("通用消息")
                                                                                                +									})
                                                                                                +								
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 消息移除 +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +									layui.use(['notice', 'jquery', 'layer', 'code'], function() {
                                                                                                +									    var notice = layui.notice;
                                                                                                +										                         
                                                                                                +									    notice.clear();
                                                                                                +									})
                                                                                                +								
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/popover.html b/demo/webman/backend/plugin/admin/public/demos/document/popover.html new file mode 100644 index 0000000000000000000000000000000000000000..bb192fb7bfb71b9ceed31d393203be5edbabfabb --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/popover.html @@ -0,0 +1,227 @@ + + + + + + + 汽泡组件 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开发环境
                                                                                                +
                                                                                                + popover 用于 汽泡显示 场景 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +                            <link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                                +                             并
                                                                                                +                            <script src="component/layui/layui.js"></script>
                                                                                                +                             并
                                                                                                +                            <script src="component/pear/pear.js"></script>
                                                                                                +                        
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                汽泡控制
                                                                                                +
                                                                                                + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +									layui.use(['popover', 'jquery', 'layer', 'code'], function() {
                                                                                                +									   var popover = layui.popover;
                                                                                                +    popover.show('#el1');
                                                                                                +    popover.hide('#el1'); //或 $('#el1').webuiPopover('hide');
                                                                                                +
                                                                                                +
                                                                                                +									})
                                                                                                +								
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 不同方式 +
                                                                                                +
                                                                                                + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +									layui.use(['toast', 'jquery', 'layer', 'code'], function() {
                                                                                                +									    var popover = layui.popover;
                                                                                                +    popover.create('#el1',{title:' hello popover-manual',content:'这里显示内容',trigger:'manual',placement:'auto',
                                                                                                +        animation:'pop',
                                                                                                +        closeable:true,
                                                                                                +        delay: {
                                                                                                +            //show and hide delay time of the popover, works only when trigger is 'hover',the value can be number or object
                                                                                                +            show: null,
                                                                                                +            hide: 100
                                                                                                +        },
                                                                                                +        opacity:0.98,
                                                                                                +        type:'html',//content type, values:'html','iframe','async'
                                                                                                +    });
                                                                                                +
                                                                                                +									})
                                                                                                +								
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 隐藏 +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +									layui.use(['popover', 'jquery', 'layer', 'code'], function() {
                                                                                                +									    var popover = layui.popover;
                                                                                                +									    popover.hideAll();
                                                                                                +									})
                                                                                                +								
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/popup.html b/demo/webman/backend/plugin/admin/public/demos/document/popup.html new file mode 100644 index 0000000000000000000000000000000000000000..d99602338629f483a868cab650193fc034b09b15 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/popup.html @@ -0,0 +1,127 @@ + + + + + 封装弹窗 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开发环境
                                                                                                +
                                                                                                + Popup 基于 Layer 的 二次封装, 提供简洁高效的 API 调用 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								<link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                                +								 并
                                                                                                +								<script src="component/layui/layui.js"></script>
                                                                                                +								 并
                                                                                                +								<script src="component/pear/pear.js"></script>
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                提示消息
                                                                                                +
                                                                                                + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								layui.use(['popup'], function() {
                                                                                                +								    var popup = layui.popup;
                                                                                                +								  
                                                                                                +								    popup.success("成功消息")
                                                                                                +								    popup.failure("失败消息")
                                                                                                +								    popup.warning("警告消息")
                                                                                                +								})
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                回调函数
                                                                                                +
                                                                                                + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								layui.use(['popup'], function() {
                                                                                                +								    var popup = layui.popup;
                                                                                                +								  
                                                                                                +								    popup.success("成功消息",callback)
                                                                                                +								    popup.failure("失败消息",callback)
                                                                                                +								    popup.warning("警告消息",callback)
                                                                                                +								})
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/select.html b/demo/webman/backend/plugin/admin/public/demos/document/select.html new file mode 100644 index 0000000000000000000000000000000000000000..e22feb63b686d795561dcc84daffd564ee7dacd9 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/select.html @@ -0,0 +1,218 @@ + + + + + 多选组件 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 开发环境 +
                                                                                                +
                                                                                                + Select 应用于 多选 场景 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								<link href="component/pear/css/pear.css" rel="stylesheet" />
                                                                                                +								 并
                                                                                                +								<script src="component/layui/layui.js"></script>
                                                                                                +								 并
                                                                                                +								<script src="component/pear/pear.js"></script>
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 默认主题 +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +      								
                                                                                                +      							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 绿色主题 +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 通用主题 +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 警告主题 +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 危险主题 +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/step.html b/demo/webman/backend/plugin/admin/public/demos/document/step.html new file mode 100644 index 0000000000000000000000000000000000000000..f1647c4d6a9ac7368e8db5c26ef217b536f9536f --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/step.html @@ -0,0 +1,256 @@ + + + + + 分布表单 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开发环境
                                                                                                +
                                                                                                Step 步骤表单
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								<link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                                +								 并
                                                                                                +								<script src="component/layui/layui.js"></script>
                                                                                                +								 并
                                                                                                +								<script src="component/pear/pear.js"></script>
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +		                        layui.use(['form', 'step','element'], function() {
                                                                                                +		                            var $ = layui.$,
                                                                                                +		                            form = layui.form,
                                                                                                +		                            step = layui.step;
                                                                                                +		                            
                                                                                                +		                            step.render({
                                                                                                +		                                elem: '#stepForm',
                                                                                                +		                                filter: 'stepForm',
                                                                                                +		                                width: '100%',
                                                                                                +		                                stepWidth: '600px',
                                                                                                +		                                height: '500px',
                                                                                                +		                                stepItems: [{
                                                                                                +		                                    title: '填写'
                                                                                                +		                                }, {
                                                                                                +		                                    title: '确认'
                                                                                                +		                                }, {
                                                                                                +		                                    title: '完成'
                                                                                                +		                                }]
                                                                                                +		                            });
                                                                                                +		                         
                                                                                                +		                            form.on('submit(formStep)', function(data) {
                                                                                                +		                                step.next('#stepForm');
                                                                                                +		                                return false;
                                                                                                +		                            });
                                                                                                +		                         
                                                                                                +		                            form.on('submit(formStep2)', function(data) {
                                                                                                +		                                step.next('#stepForm');
                                                                                                +		                                return false;
                                                                                                +		                            });
                                                                                                +		                         
                                                                                                +		                            $('.pre').click(function() {
                                                                                                +		                                step.pre('#stepForm');
                                                                                                +		                                return false;
                                                                                                +		                            });
                                                                                                +		                         
                                                                                                +		                            $('.next').click(function() {
                                                                                                +		                                step.next('#stepForm');
                                                                                                +		                                return false;
                                                                                                +		                            });
                                                                                                +		                        })
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/tab.html b/demo/webman/backend/plugin/admin/public/demos/document/tab.html new file mode 100644 index 0000000000000000000000000000000000000000..f6fcd057a7c7e7822bf97f183d212f4d2fdd2cd4 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/tab.html @@ -0,0 +1,152 @@ + + + + + 多选项卡 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开发环境
                                                                                                +
                                                                                                + Tab.js 是一个多视图组件,你可在任何地方内嵌它,并执行常用操作,Admin 正式使用该组件进行路由切换 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +							    <link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                                +							    并
                                                                                                +							    <script src="component/layui/layui.js"></script>
                                                                                                +							    并
                                                                                                +							    <script src="component/pear/pear.js"></script>
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 常用操作 +
                                                                                                +
                                                                                                + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 基本使用 +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								
                                                                                                +								tab.render({
                                                                                                +								    elem: 'contents',
                                                                                                +								    roll: false,
                                                                                                +								    tool: false,
                                                                                                +								    width: '100%',
                                                                                                +								    height: '480px',
                                                                                                +								    index: 0,
                                                                                                +								    tabMax: 30,
                                                                                                +								    closeEvent: function(id) {
                                                                                                +										
                                                                                                +								        // do something
                                                                                                +								    },
                                                                                                +								    data: [{
                                                                                                +								        id: "1",
                                                                                                +								        title: "首页",
                                                                                                +								        url: "http://www.baidu.com",
                                                                                                +								        close: false
                                                                                                +								    },{
                                                                                                +								        id: "2",
                                                                                                +								        title: "百度一下",
                                                                                                +								        url: "http://www.baidu.com",
                                                                                                +								        close: false
                                                                                                +								    }]
                                                                                                +								});
                                                                                                +								
                                                                                                +								
                                                                                                +						
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/tabContent.html b/demo/webman/backend/plugin/admin/public/demos/document/tabContent.html new file mode 100644 index 0000000000000000000000000000000000000000..d01129bfb16387bca09d89effd5c8db08b611b4c --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/tabContent.html @@ -0,0 +1,38 @@ + + + + + 多选项卡内容 + + + +
                                                                                                +
                                                                                                +
                                                                                                + + +
                                                                                                +
                                                                                                + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/table.html b/demo/webman/backend/plugin/admin/public/demos/document/table.html new file mode 100644 index 0000000000000000000000000000000000000000..8785c3263f27c2d7c9a76ccdbfa7e231b7de7242 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/table.html @@ -0,0 +1,412 @@ + + + + + + 数据表格 + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + + + + + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                上侧弹层内容...

                                                                                                +
                                                                                                +
                                                                                                + + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/tag.html b/demo/webman/backend/plugin/admin/public/demos/document/tag.html new file mode 100644 index 0000000000000000000000000000000000000000..e6478bbdffc92617ea36d097cb52481c24bc9edd --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/tag.html @@ -0,0 +1,265 @@ + + + + + 标签组件 + + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开发环境
                                                                                                +
                                                                                                + Tag 标签组件 +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								<link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                                +								 并
                                                                                                +								<script src="component/layui/layui.js"></script>
                                                                                                +								 并
                                                                                                +								<script src="component/pear/pear.js"></script>
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                主题风格
                                                                                                +
                                                                                                +
                                                                                                + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +							
                                                                                                + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                动态操作
                                                                                                +
                                                                                                +
                                                                                                + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								tag.add('demo', {text: '新选项',id: 12})
                                                                                                +								 
                                                                                                +								tag.delete('demo', '44');
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                圆角风格
                                                                                                +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								
                                                                                                + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                删除功能
                                                                                                +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								
                                                                                                + + + + +
                                                                                                + + tag.on('delete(demo)', function(data) { + console.log('删除'); + console.log(this); + console.log(data.index); + console.log(data.elem); + console.log(data.othis); + }); +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                新建功能
                                                                                                +
                                                                                                +
                                                                                                + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +							
                                                                                                + + + + +
                                                                                                + + tag.on('add(demo)', function(data) { + console.log('新建'); + console.log(this); + console.log(data.index); + console.log(data.elem); + }); +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/tinymce.html b/demo/webman/backend/plugin/admin/public/demos/document/tinymce.html new file mode 100644 index 0000000000000000000000000000000000000000..9ba01e55e6b2e956f5412a10a0b6c1d3af563336 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/tinymce.html @@ -0,0 +1,93 @@ + + + + + + 文本编辑 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 开发环境 +
                                                                                                +
                                                                                                + Tinymce 文本编辑器 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								<link href="component/pear/css/pear.css" rel="stylesheet" />
                                                                                                +								 并
                                                                                                +								<script src="component/layui/layui.js"></script>
                                                                                                +								 并
                                                                                                +								<script src="component/pear/pear.js"></script>
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                富文本编辑器
                                                                                                +
                                                                                                + +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								layui.use(['tinymce'], function() {
                                                                                                +								    var tinymce = layui.tinymce
                                                                                                +								
                                                                                                +								    var edit = tinymce.render({
                                                                                                +								        elem: "#edit",
                                                                                                +								        height: 400
                                                                                                +								    });
                                                                                                +									
                                                                                                +								    edit.getContent()
                                                                                                +								});
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/toast.html b/demo/webman/backend/plugin/admin/public/demos/document/toast.html new file mode 100644 index 0000000000000000000000000000000000000000..eb276cdc1285ec1baf5cc86ee7d7c3b02fd261de --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/toast.html @@ -0,0 +1,291 @@ + + + + + + + 通知组件 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开发环境
                                                                                                +
                                                                                                + toast 用于 消息通知 场景 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +									<link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                                +									 或
                                                                                                +									<link rel="stylesheet" href="component/pear/css/pear-module/toast.css" />
                                                                                                +									 并
                                                                                                +									<script src="component/layui/layui.js"></script>
                                                                                                +									 并
                                                                                                +									<script src="component/pear/pear.js"></script>
                                                                                                +								
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                消息提醒
                                                                                                +
                                                                                                +
                                                                                                + toast.success({title:"成功消息",message:"消息描述"}) +
                                                                                                +
                                                                                                + toast.error({title:"危险消息",message:"消息描述"}) +
                                                                                                +
                                                                                                + toast.warning({title:"警告消息",message:"消息描述"}) +
                                                                                                +
                                                                                                + toast.info({title:"通知消息",message:"消息描述"}) +
                                                                                                +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +									layui.use(['toast', 'jquery', 'layer', 'code'], function() {
                                                                                                +									    var toast = layui.toast;
                                                                                                +										                         
                                                                                                +									    toast.success({title: 'Caution',message: 'You forgot important data',position: 'topRight'});
                                                                                                +									    
                                                                                                +										toast.info({title: 'Caution',message: 'You forgot important data',position: 'topRight'});
                                                                                                +									    
                                                                                                +										toast.warning({title: 'Caution',message: 'You forgot important data',position: 'topRight'});
                                                                                                +									    
                                                                                                +										toast.error({title: 'Caution',message: 'You forgot important data',position: 'topRight'});
                                                                                                +									    
                                                                                                +										toast.question({title: 'Caution',message: 'You forgot important data',position: 'topRight'});
                                                                                                +									})
                                                                                                +								
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 不同位置 +
                                                                                                +
                                                                                                + + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +									layui.use(['toast', 'jquery', 'layer', 'code'], function() {
                                                                                                +									    var toast = layui.toast;
                                                                                                +										                         
                                                                                                +									    $(".toast-top-left-btn").click(function(){
                                                                                                +									        toast.success({title: 'Caution',message: 'You forgot important data',position: 'topLeft'});
                                                                                                +									    })
                                                                                                +									    $(".toast-top-center-btn").click(function(){
                                                                                                +									        toast.success({title: 'Caution',message: 'You forgot important data',position: 'topCenter'});
                                                                                                +									    })
                                                                                                +									    $(".toast-top-right-btn").click(function(){
                                                                                                +									        toast.success({title: 'Caution',message: 'You forgot important data',position: 'topRight'});
                                                                                                +									    })
                                                                                                +									    $(".toast-bottom-left-btn").click(function(){
                                                                                                +									        toast.success({title: 'Caution',message: 'You forgot important data',position: 'bottomLeft'});
                                                                                                +									    })
                                                                                                +									    $(".toast-bottom-center-btn").click(function(){
                                                                                                +									        toast.success({title: 'Caution',message: 'You forgot important data',position: 'bottomCenter'});
                                                                                                +									    })
                                                                                                +									    $(".toast-bottom-right-btn").click(function(){
                                                                                                +									        toast.success({title: 'Caution',message: 'You forgot important data',position: 'bottomRight'});
                                                                                                +									    })
                                                                                                +									})
                                                                                                +								
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + 消息移除 +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +									layui.use(['toast', 'jquery', 'layer', 'code'], function() {
                                                                                                +									    var toast = layui.toast;
                                                                                                +										                         
                                                                                                +									    toast.destroy();
                                                                                                +									})
                                                                                                +								
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/topBar.html b/demo/webman/backend/plugin/admin/public/demos/document/topBar.html new file mode 100644 index 0000000000000000000000000000000000000000..b1a4cf066d9c3352fb32b703eceda29c5dfcbf71 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/topBar.html @@ -0,0 +1,279 @@ + + + + + 回到顶部 + + + + + + + +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                动态
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                七彩枫叶 在 Pear Admin 专区 回答问题

                                                                                                + 几秒前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                简 在 Pear Admin 专区 进行了 提问

                                                                                                + 2天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                恒宇少年 将 Pear Admin 更新至 2.3.0 版本

                                                                                                + 7天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                如花 在 Pear Admin 社区 发布了 建议

                                                                                                + 7天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                就眠仪式 在 Pear Admin 社区 发布了 建议

                                                                                                + 8天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                贤心 在 Pear Admin 专区 进行了 提问

                                                                                                + 8天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                七彩枫叶 在 Pear Admin 专区 回答问题

                                                                                                + 几秒前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                简 在 Pear Admin 专区 进行了 提问

                                                                                                + 2天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                恒宇少年 将 Pear Admin 更新至 2.3.0 版本

                                                                                                + 7天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                如花 在 Pear Admin 社区 发布了 建议

                                                                                                + 7天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                就眠仪式 在 Pear Admin 社区 发布了 建议

                                                                                                + 8天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                贤心 在 Pear Admin 专区 进行了 提问

                                                                                                + 8天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                七彩枫叶 在 Pear Admin 专区 回答问题

                                                                                                + 几秒前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                简 在 Pear Admin 专区 进行了 提问

                                                                                                + 2天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                恒宇少年 将 Pear Admin 更新至 2.3.0 版本

                                                                                                + 7天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                如花 在 Pear Admin 社区 发布了 建议

                                                                                                + 7天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                就眠仪式 在 Pear Admin 社区 发布了 建议

                                                                                                + 8天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                贤心 在 Pear Admin 专区 进行了 提问

                                                                                                + 8天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                七彩枫叶 在 Pear Admin 专区 回答问题

                                                                                                + 几秒前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                简 在 Pear Admin 专区 进行了 提问

                                                                                                + 2天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                恒宇少年 将 Pear Admin 更新至 2.3.0 版本

                                                                                                + 7天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                如花 在 Pear Admin 社区 发布了 建议

                                                                                                + 7天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                就眠仪式 在 Pear Admin 社区 发布了 建议

                                                                                                + 8天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                次等水货 在 Pear Admin 专区 进行了 提问

                                                                                                + 8天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                七彩枫叶 在 Pear Admin 专区 回答问题

                                                                                                + 几秒前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                简 在 Pear Admin 专区 进行了 提问

                                                                                                + 2天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                恒宇少年 将 Pear Admin 更新至 2.3.0 版本

                                                                                                + 7天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                如花 在 Pear Admin 社区 发布了 建议

                                                                                                + 7天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                就眠仪式 在 Pear Admin 社区 发布了 建议

                                                                                                + 8天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                微笑刺客 在 Pear Admin 专区 进行了 提问

                                                                                                + 8天前 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/document/treetable.html b/demo/webman/backend/plugin/admin/public/demos/document/treetable.html new file mode 100644 index 0000000000000000000000000000000000000000..68617fee0356c14e931b30e9e9fb4f6081e053aa --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/treetable.html @@ -0,0 +1,234 @@ + + + + + 树形表格 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                + +
                                                                                                + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/document/watermark.html b/demo/webman/backend/plugin/admin/public/demos/document/watermark.html new file mode 100644 index 0000000000000000000000000000000000000000..a4562e009b6f5e03c6df189e72a4c12bde309e7f --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/document/watermark.html @@ -0,0 +1,161 @@ + + + + + 水印组件 + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                开发环境
                                                                                                +
                                                                                                + watermark 用于水印叠加 +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +                        <link rel="stylesheet" href="component/pear/css/pear.css" />
                                                                                                +                         并
                                                                                                +                        <script src="component/layui/layui.js"></script>
                                                                                                +                         并
                                                                                                +                        <script src="component/pear/pear.js"></script>
                                                                                                +                    
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                水印创建
                                                                                                +
                                                                                                + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								layui.use(['watermark'], function() {
                                                                                                +								    var watermark = layui.watermark;
                                                                                                +
                                                                                                +    var mark_node=new watermark({
                                                                                                +        content: "单行水印"
                                                                                                +    });
                                                                                                +
                                                                                                +    new watermark({
                                                                                                +        content: "多行水印1
                                                                                                多行水印2", + height:40 + }); + + new watermark({ + content: "指定容器上", + appendTo:'#water_div', + }); + + }) +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                指定容器水印
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                移除水印
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                显示代码

                                                                                                +
                                                                                                +
                                                                                                +								layui.use(['watermark'], function() {
                                                                                                +								    var popup = layui.popup;
                                                                                                +                                    mark_node.destroy();
                                                                                                +								})
                                                                                                +							
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/echarts/column.html b/demo/webman/backend/plugin/admin/public/demos/echarts/column.html new file mode 100644 index 0000000000000000000000000000000000000000..44bcb2753bb5c58f55b6a056ae8c53a1cf32a5f4 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/echarts/column.html @@ -0,0 +1,47 @@ + + + + + 条状图表 + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/echarts/line.html b/demo/webman/backend/plugin/admin/public/demos/echarts/line.html new file mode 100644 index 0000000000000000000000000000000000000000..1b5c9cc685296c80a2c5b72ac949d6cff48792de --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/echarts/line.html @@ -0,0 +1,47 @@ + + + + + 折线图表 + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/echarts/script/column1.js b/demo/webman/backend/plugin/admin/public/demos/echarts/script/column1.js new file mode 100644 index 0000000000000000000000000000000000000000..db5e817f795283c3f775767b0790e69cb55749f7 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/echarts/script/column1.js @@ -0,0 +1,137 @@ +layui.use(['echarts'], function() { + let echarts = layui.echarts; + var column1 = echarts.init(document.getElementById('column1'),null, { + width: 600, + height: 400 + }); +option = { + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' , + color: '#fff', + fontSize: '26' + } + }, + legend: { + top:'5%', + right:'10%', + data: ['猕猴桃', '香蕉'], + fontSize:12, + color:'#808080', + icon:'rect' + }, + grid: { + top:60, + left:50, + bottom:60, + right:60 + }, + xAxis: [{ + type: 'category', + axisTick:{ + show:false + }, + axisLine:{ + show:false + }, + axisLabel:{ + color:'#4D4D4D', + fontSize:14, + margin:21, + fontWeight:'bold' + }, + data: ['第一周', '第二周', '第三周', '第四周'], + + }], + yAxis: [{ + name:'单位:万', + nameTextStyle:{ + color:'#808080', + fontSize:12, + padding:[0, 0, 0, -5] + }, + max: function(value) { + if(value.max<5){ + return 5 + }else{ + return value.max + } + }, + type: 'value', + axisLine:{ + show:false + }, + axisLabel:{ + color:'#808080', + fontSize:12, + margin:5 + }, + splitLine:{ + show:false + }, + axisTick:{ + show:false + } + }], + series: [ + { + name: '猕猴桃', + type: 'bar', + label:{ + show:true, + position:'top', + fontSize:14, + color:'#3DC3F0', + fontWeight:'bold' + }, + barMaxWidth:60, + color: { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: '#3DC3F0' // 0% 处的颜色 + }, { + offset: 1, color: '#CCF2FF' // 100% 处的颜色 + }] + }, + data: [60, 110, 180, 100] + }, + { + name: '香蕉', + type: 'bar', + label:{ + show:true, + position:'top', + fontSize:14, + color:'#3D8BF0', + fontWeight:'bold' + }, + barMaxWidth:60, + color: { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: '#3D8BF0' // 0% 处的颜色 + }, { + offset: 1, color: '#CCE2FF' // 100% 处的颜色 + }] + }, + data: [90, 130, 170, 130] + } + ] +}; + + column1.setOption(option); + + window.onresize = function() { + column1.resize(); + } + +}) diff --git a/demo/webman/backend/plugin/admin/public/demos/echarts/script/column2.js b/demo/webman/backend/plugin/admin/public/demos/echarts/script/column2.js new file mode 100644 index 0000000000000000000000000000000000000000..6393cce16d15214183d2ab660efe659588b7e963 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/echarts/script/column2.js @@ -0,0 +1,73 @@ +layui.use(['echarts'], function() { + let echarts = layui.echarts; + var column2 = echarts.init(document.getElementById('column2'),null, { + width: 600, + height: 400 + }); + + var data = [1000, 600, 500, 300]; + option = { + backgroundColor: '#ffffff', + title: { + text: 'ETC交易成功率', + left: 'center', + top: 2, + fontSize: 20 + }, + color: ['#fed46b','#2194ff', ], + tooltip: { + trigger: 'axis', + axisPointer: { // 坐标轴指示器,坐标轴触发有效 + type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' + } + }, + grid: { + left: '3%', + right: '4%', + bottom: '10%', + containLabel: true + }, + legend: { + left: 'center', + bottom: '2%', + data: ['去年', '今年', ] + }, + xAxis: [{ + type: 'category', + data: ['09-22', '09-22', '09-22', '09-22', '09-22', '09-22', '09-22'], + axisTick: { + alignWithLabel: true + } + }], + yAxis: [{ + type: 'value' + }], + barMaxWidth: '30', + label:{ + show:true, + position:'top', + formatter:function(params){ + return params.value+'%' + } + }, + series: [ + + { + name: '去年', + type: 'bar', + data: [90, 52, 90, 80, 90, 70, 90] + }, + { + name: '今年', + type: 'bar', + data: [10, 52, 90, 70, 90, 70, 90] + }, + ] + }; + column2.setOption(option); + + window.onresize = function() { + column2.resize(); + } + +}) diff --git a/demo/webman/backend/plugin/admin/public/demos/echarts/script/column3.js b/demo/webman/backend/plugin/admin/public/demos/echarts/script/column3.js new file mode 100644 index 0000000000000000000000000000000000000000..897e495042d8e8f32e715a858f77bee34fbfd6a3 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/echarts/script/column3.js @@ -0,0 +1,120 @@ +layui.use(['echarts'], function() { + let echarts = layui.echarts; + var column3 = echarts.init(document.getElementById('column3'),null, { + width: 600, + height: 400 + }); + + const colorList = ["#9E87FF", '#73DDFF', '#fe9a8b', '#F56948', '#9E87FF'] + +option = { + backgroundColor: '#fff', + tooltip: { + trigger: "axis", + padding: [8, 10], + backgroundColor: 'rgba(255,255,255,0.5)', + axisPointer: { + type: "shadow", + color: "#fff" + } + }, + legend: { + data: ['新开会员', '激活会员', '关闭会员'], + align: 'left', + right: 0, + + color: "#333", + fontSize: 14, + fontWeight: 200, + + itemWidth: 14, + itemHeight: 14, + itemGap: 35 + }, + grid: { + left: '0', + right: '0', + bottom: '8%', + top: '15%', + containLabel: true + }, + label: { + show: true, + position: 'top', + color: '#333', + fontSize: 14, + fontWeight: 700 + }, + xAxis: [{ + type: 'category', + offset: 10, + data: ['团队1', '团队2', '团队3', '团队4'], + axisLine: { + show: false + }, + axisTick: { + show: false + }, + axisLabel: { + show: true, + color: "#333", + fontSize: 16, + fontWeight: 200 + + }, + }], + yAxis: [{ + type: 'value', + axisLabel: { + show: false + }, + axisTick: { + show: false + }, + axisLine: { + show: false + }, + splitLine: { + show: false + } + }], + series: [{ + name: '新开会员', + type: 'bar', + data: [20, 34, 18, 14, 16], + barWidth: 22, //柱子宽度 + barGap: 1, //柱子之间间距 + itemStyle: { + color: '#0071c8', + opacity: 1, + } + }, { + name: '激活会员', + type: 'bar', + data: [10, 24, 5, 24, 16], + barWidth: 22, + barGap: 1, + itemStyle: { + color: '#fdc508', + opacity: 1, + } + }, { + name: '关闭会员', + type: 'bar', + data: [7, 24, 18, 20, 6], + barWidth: 22, + barGap: 1, + itemStyle: { + color: '#dfeafc', + opacity: 1, + } + }] +}; + + column3.setOption(option); + + window.onresize = function() { + column3.resize(); + } + +}) diff --git a/demo/webman/backend/plugin/admin/public/demos/echarts/script/column4.js b/demo/webman/backend/plugin/admin/public/demos/echarts/script/column4.js new file mode 100644 index 0000000000000000000000000000000000000000..6cd871f4b354afe3b9441d8dc55b58f2fcd5bca8 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/echarts/script/column4.js @@ -0,0 +1,84 @@ +layui.use(['echarts'], function() { + let echarts = layui.echarts; + var column4 = echarts.init(document.getElementById('column4'),null, { + width: 600, + height: 400 + }); + option = { + backgroundColor:'#fff', + title:{ + text:"描边柱状图", + top:10, + left:15, + color:"#35598d", + fontSize:16, + fontWeight:'normal' + }, + tooltip: { + trigger: 'axis', + formatter:'{b}:{c}', + }, + grid: { + left: '5%', + right: '6%', + bottom: '3%', + top: '20%', + containLabel: true + }, + xAxis :{ + type : 'category', + data : ['策略1','策略2','策略3','策略4','策略5','策略6','策略7','策略8','策略9'], + axisLabel:{ //坐标轴字体颜色 + color: '#9eaaba' + }, + axisLine:{ + lineStyle:{ + color:"#e5e5e5" + } + }, + axisTick:{ //y轴刻度线 + show:false + }, + splitLine:{ //网格 + show: false, + } + }, + yAxis :{ + type : 'value', + axisLabel:{ //坐标轴字体颜色 + color: '#9eaaba' + }, + axisLine:{ + show:false, + }, + axisTick:{ //y轴刻度线 + show:false + }, + splitLine:{ //网格 + show: true, + lineStyle:{ + color:'#dadde4', + type:"dashed" //坐标网线类型 + } + } + }, + series:{ + name:'', + type:'bar', + barWidth : '40%', //柱子宽度 + itemStyle:{ //柱子颜色 + borderWidth: 2, + borderColor: 'rgb(79, 116, 223)', + color:'rgba(79, 116, 223, .3)', + }, + data:[320, 332, 301, 334, 390, 330, 320, 230, 156] + } + }; + + column4.setOption(option); + + window.onresize = function() { + column4.resize(); + } + +}) diff --git a/demo/webman/backend/plugin/admin/public/demos/echarts/script/line1.js b/demo/webman/backend/plugin/admin/public/demos/echarts/script/line1.js new file mode 100644 index 0000000000000000000000000000000000000000..1a0ce7b306c24826f182718414885743fb04ffb1 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/echarts/script/line1.js @@ -0,0 +1,236 @@ +layui.use(['echarts'], function() { + let echarts = layui.echarts; + var line2 = echarts.init(document.getElementById('line2'),null, { + width: 600, + height: 400 + }); + + const colorList = ["#9E87FF", '#73DDFF', '#fe9a8b', '#F56948', '#9E87FF'] + option = { + backgroundColor: '#fff', + title: { + text: '全国6月销售统计', + fontSize: 12, + fontWeight: 400, + left: 'center', + top: '5%' + }, + legend: { + icon: 'circle', + top: '5%', + right: '5%', + itemWidth: 6, + itemGap: 20, + color: '#556677' + }, + tooltip: { + trigger: 'axis', + axisPointer: { + label: { + show: true, + backgroundColor: '#fff', + color: '#556677', + borderColor: 'rgba(0,0,0,0)', + shadowColor: 'rgba(0,0,0,0)', + shadowOffsetY: 0 + }, + lineStyle: { + width: 0 + } + }, + backgroundColor: '#fff', + color: '#5c6c7c', + padding: [10, 10], + extraCssText: 'box-shadow: 1px 0 2px 0 rgba(163,163,163,0.5)' + }, + grid: { + top: '15%' + }, + xAxis: [{ + type: 'category', + data: ['北京', '上海', '广州', '深圳', '香港', '澳门', '台湾'], + axisLine: { + lineStyle: { + color: '#DCE2E8' + } + }, + axisTick: { + show: false + }, + axisLabel: { + interval: 0, + color: '#556677', + // 默认x轴字体大小 + fontSize: 12, + // margin:文字到x轴的距离 + margin: 15 + }, + axisPointer: { + label: { + // padding: [11, 5, 7], + padding: [0, 0, 10, 0], + + // 这里的margin和axisLabel的margin要一致! + margin: 15, + // 移入时的字体大小 + fontSize: 12, + backgroundColor: { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, + color: '#fff' // 0% 处的颜色 + }, { + // offset: 0.9, + offset: 0.86, + + color: '#fff' // 0% 处的颜色 + }, { + offset: 0.86, + color: '#33c0cd' // 0% 处的颜色 + }, { + offset: 1, + color: '#33c0cd' // 100% 处的颜色 + }], + global: false // 缺省为 false + } + } + }, + boundaryGap: false + }], + yAxis: [{ + type: 'value', + axisTick: { + show: false + }, + axisLine: { + show: true, + lineStyle: { + color: '#DCE2E8' + } + }, + axisLabel: { + color: '#556677', + }, + splitLine: { + show: false + } + }, { + type: 'value', + position: 'right', + axisTick: { + show: false + }, + axisLabel: { + color: '#556677', + formatter: '{value}' + }, + axisLine: { + show: true, + lineStyle: { + color: '#DCE2E8' + } + }, + splitLine: { + show: false + } + }], + series: [{ + name: 'Adidas', + type: 'line', + data: [10, 10, 30, 12, 15, 3, 7], + symbolSize: 1, + symbol: 'circle', + smooth: true, + yAxisIndex: 0, + showSymbol: true, + lineStyle: { + width: 5, + color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [{ + offset: 0, + color: '#9effff' + }, + { + offset: 1, + color: '#9E87FF' + } + ]), + shadowColor: 'rgba(158,135,255, 0.3)', + shadowBlur: 10, + shadowOffsetY: 20 + }, + itemStyle: { + color: colorList[0], + borderColor: colorList[0] + } + }, { + name: 'Nike', + type: 'line', + data: [5, 12, 11, 14, 25, 16, 10], + symbolSize: 1, + symbol: 'circle', + smooth: true, + yAxisIndex: 0, + showSymbol: true, + lineStyle: { + width: 5, + color: new echarts.graphic.LinearGradient(1, 1, 0, 0, [{ + offset: 0, + color: '#73DD39' + }, + { + offset: 1, + color: '#73DDFF' + } + ]), + shadowColor: 'rgba(115,221,255, 0.3)', + shadowBlur: 10, + shadowOffsetY: 20 + }, + itemStyle: { + color: colorList[1], + borderColor: colorList[1] + } + }, + { + name: '老北京布鞋', + type: 'line', + data: [150, 120, 170, 140, 500, 160, 110], + symbolSize: 1, + yAxisIndex: 1, + symbol: 'circle', + smooth: true, + showSymbol: true, + lineStyle: { + width: 5, + color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [{ + offset: 0, + color: '#fe9a' + }, + { + offset: 1, + color: '#fe9a8b' + } + ]), + shadowColor: 'rgba(254,154,139, 0.3)', + shadowBlur: 10, + shadowOffsetY: 20 + }, + itemStyle: { + color: colorList[2], + borderColor: colorList[2] + } + } + ] + }; + + line2.setOption(option); + + window.onresize = function() { + line2.resize(); + } + +}) diff --git a/demo/webman/backend/plugin/admin/public/demos/echarts/script/line2.js b/demo/webman/backend/plugin/admin/public/demos/echarts/script/line2.js new file mode 100644 index 0000000000000000000000000000000000000000..c0bb5319fe044cc70b0c951268986d9fb82a864a --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/echarts/script/line2.js @@ -0,0 +1,148 @@ +layui.use(['echarts'], function() { + let echarts = layui.echarts; + var line1 = echarts.init(document.getElementById('line1'),null, { + width: 600, + height: 400 + }); + + const colorList = ["#9E87FF", '#73DDFF', '#fe9a8b', '#F56948', '#9E87FF'] + option = { + + backgroundColor: '#fff', + tooltip: { + show: false + }, + grid: { + top: '10%', + bottom: '6%', + left: '6%', + right: '6%', + containLabel: true + }, + xAxis: [{ + type: 'category', + boundaryGap: false, + axisLine: { + show: false + }, + axisTick: { + show: false + }, + axisLabel: { + margin: 10, + fontSize: 14, + color: 'rgba(#999)' + }, + splitLine: { + show: true, + lineStyle: { + color: '#939ab6', + opacity: .15 + } + }, + data: ['10:00', '10:10', '10:10', '10:30', '10:40', '10:50'] + },], + yAxis: [{ + type: 'value', + offset: 15, + max: 100, + min: 0, + axisTick: { + show: false + }, + axisLine: { + show: false + }, + axisLabel: { + margin: 10, + fontSize: 14, + color: '#999' + + }, + splitLine: { + show: false + } + + }], + series: [{ + name: '2', + type: 'line', + z: 3, + showSymbol: false, + smoothMonotone: 'x', + lineStyle: { + width: 3, + color: { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: 'rgba(59,102,246)' // 0% 处的颜色 + }, { + offset: 1, color: 'rgba(118,237,252)' // 100% 处的颜色 + }] + }, + shadowBlur: 4, + shadowColor: 'rgba(69,126,247,.2)', + shadowOffsetY: 4 + }, + areaStyle: { + color: { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: 'rgba(227,233,250,.9)' // 0% 处的颜色 + }, { + offset: 1, color: 'rgba(248,251,252,.3)' // 100% 处的颜色 + }] + } + }, + smooth: true, + data: [20, 56, 17, 40, 68, 42] + },{ + name: '1', + type: 'line', + showSymbol: false, + smoothMonotone: 'x', + + lineStyle: { + width: 3, + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ + offset: 0, + color: 'rgba(255,84,108)' + }, { + offset: 1, + color: 'rgba(252,140,118)' + }], false), + shadowBlur: 4, + shadowColor: 'rgba(253,121,128,.2)', + shadowOffsetY: 4 + }, + areaStyle: { + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ + offset: 0, + color: 'rgba(255,84,108,.15)' + }, { + offset: 1, + color: 'rgba(252,140,118,0)' + }], false), + }, + smooth: true, + data: [20, 71, 8, 50, 57, 32] + } + ] + + }; + + line1.setOption(option); + + window.onresize = function() { + line1.resize(); + } + +}) diff --git a/demo/webman/backend/plugin/admin/public/demos/echarts/script/line3.js b/demo/webman/backend/plugin/admin/public/demos/echarts/script/line3.js new file mode 100644 index 0000000000000000000000000000000000000000..12bfbc7b6496d30d35e9089120acbc5ac3ec24ed --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/echarts/script/line3.js @@ -0,0 +1,102 @@ +layui.use(['echarts'], function() { + let echarts = layui.echarts; + + var line3 = echarts.init(document.getElementById('line3'),null, { + width: 600, + height: 400 + }); + + const colorList = ["#9E87FF", '#73DDFF', '#fe9a8b', '#F56948', '#9E87FF'] + + option = { + backgroundColor: '#fff', + title: { + text: "告警数", + left: "18px", + top: "0", + color: "#999", + fontSize: 12, + fontWeight: '400' + }, + color: ['#73A0FA', '#73DEB3', '#FFB761'], + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + crossStyle: { + color: '#999' + }, + lineStyle: { + type: 'dashed' + } + } + }, + grid: { + left: '25', + right: '25', + bottom: '24', + top: '75', + containLabel: true + }, + legend: { + data: ['上周', '本周'], + orient: 'horizontal', + icon: "rect", + show: true, + left: 20, + top: 25, + }, + xAxis: { + type: 'category', + data: ['爱立信端局', '中兴端局', '爱立信HSS', '中兴HSS', '华为HSS', '华为智能网', '中兴VIMS'], + splitLine: { + show: false + }, + axisTick: { + show: false + }, + axisLine: { + show: false + }, + }, + yAxis: { + type: 'value', + axisLabel: { + color: '#999', + fontSize: 12 + }, + splitLine: { + show: true, + lineStyle: { + color: '#F3F4F4' + } + }, + axisTick: { + show: false + }, + axisLine: { + show: false + }, + }, + series: [{ + name: '上周', + type: 'line', + smooth: true, + data: [1800, 1000, 2000, 1000, 500, 100, 1200] + }, + { + name: '本周', + type: 'line', + smooth: true, + data: [1700, 999, 1100, 899, 199, 99, 1000] + } + ] + }; + + line3.setOption(option); + + window.onresize = function() { + line3.resize(); + } + +}) diff --git a/demo/webman/backend/plugin/admin/public/demos/echarts/script/line4.js b/demo/webman/backend/plugin/admin/public/demos/echarts/script/line4.js new file mode 100644 index 0000000000000000000000000000000000000000..19e9f79050da3bf1dbccbe47b7a58cfe274776f3 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/echarts/script/line4.js @@ -0,0 +1,167 @@ +layui.use(['echarts'], function() { + let echarts = layui.echarts; + + var line4 = echarts.init(document.getElementById('line4'),null, { + width: 600, + height: 400 + }); + + const colorList = ["#9E87FF", '#73DDFF', '#fe9a8b', '#F56948', '#9E87FF'] + option = { + title: { + text: '用电量' + }, + tooltip: { + trigger: 'axis' + }, + legend: { + data: ['2018', '2019'] + }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + toolbox: { + feature: { + saveAsImage: {} + } + }, + xAxis: { + type: 'category', + boundaryGap: false,//坐标轴两边留白 + data: ['12201', '12202', '12203','12204','12301','12302','12303','12304','12401', '12402', '12403','12404'], + axisLabel: { //坐标轴刻度标签的相关设置。 + interval: 0,//设置为 1,表示『隔一个标签显示一个标签』 + // margin:15, + + color: '#1B253A', + fontStyle: 'normal', + fontFamily: '微软雅黑', + fontSize: 12, + + formatter:function(params) { + var newParamsName = ""; + var paramsNameNumber = params.length; + var provideNumber = 4; //一行显示几个字 + var rowNumber = Math.ceil(paramsNameNumber / provideNumber); + if (paramsNameNumber > provideNumber) { + for (var p = 0; p < rowNumber; p++) { + var tempStr = ""; + var start = p * provideNumber; + var end = start + provideNumber; + if (p == rowNumber - 1) { + tempStr = params.substring(start, paramsNameNumber); + } else { + tempStr = params.substring(start, end) + "\n"; + } + newParamsName += tempStr; + } + + } else { + newParamsName = params; + } + return newParamsName + }, + //rotate:50, + }, + axisTick:{//坐标轴刻度相关设置。 + show: false, + }, + axisLine:{//坐标轴轴线相关设置 + lineStyle:{ + color:'#E5E9ED', + // opacity:0.2 + } + }, + splitLine: { //坐标轴在 grid 区域中的分隔线。 + show: true, + lineStyle: { + color: '#E5E9ED', + // opacity:0.1 + } + } + }, + yAxis: [ + { + type: 'value', + splitNumber: 5, + axisLabel: { + + color: '#a8aab0', + fontStyle: 'normal', + fontFamily: '微软雅黑', + fontSize: 12 + + }, + axisLine:{ + show: false + }, + axisTick:{ + show: false + }, + splitLine: { + show: true, + lineStyle: { + color: '#E5E9ED', + // opacity:0.1 + } + } + + } + ], + series: [ + { + name: '2018', + type: 'line', + itemStyle: { + color:'#3A84FF', + lineStyle: { + color: "#3A84FF", + width:1 + }, + areaStyle: { + color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [{ + offset: 0, + color: 'rgba(58,132,255,0)' + }, { + offset: 1, + color: 'rgba(58,132,255,0.35)' + }]), + } + }, + data: [ 1, 2, 3, 3, 5, 6, 5, 3, 6, 5, 5, 4] + }, + { + name: '2019', + type: 'line', + itemStyle: { + color:'rgba(255,80,124,1)', + lineStyle: { + color: "rgba(255,80,124,1)", + width:1 + }, + areaStyle: { + color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [{ + offset: 0, + color: 'rgba(255,80,124,0)' + }, { + offset: 1, + color: 'rgba(255,80,124,0.35)' + }]), + } + }, + data: [9, 5,7,8,6,7,8,7,7,6,8,6] + } + ] + }; + + + line4.setOption(option); + + window.onresize = function() { + line4.resize(); + } + +}) diff --git a/demo/webman/backend/plugin/admin/public/demos/error/403.html b/demo/webman/backend/plugin/admin/public/demos/error/403.html new file mode 100644 index 0000000000000000000000000000000000000000..3c6db3b6d531a8e38104868a58beb608f89e4376 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/error/403.html @@ -0,0 +1,21 @@ + + + + + + + + + +
                                                                                                + +
                                                                                                +

                                                                                                403

                                                                                                +

                                                                                                抱歉,你无权访问该页面

                                                                                                + +
                                                                                                +
                                                                                                + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/error/404.html b/demo/webman/backend/plugin/admin/public/demos/error/404.html new file mode 100644 index 0000000000000000000000000000000000000000..9311a45b500818396e233ad5962f7a87c782f588 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/error/404.html @@ -0,0 +1,21 @@ + + + + + + + + + +
                                                                                                + +
                                                                                                +

                                                                                                404

                                                                                                +

                                                                                                抱歉,你访问的页面不存在或仍在开发中

                                                                                                + +
                                                                                                +
                                                                                                + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/error/500.html b/demo/webman/backend/plugin/admin/public/demos/error/500.html new file mode 100644 index 0000000000000000000000000000000000000000..75e878215a938a3d7d7c6fe00ac6c684e1e5edb7 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/error/500.html @@ -0,0 +1,21 @@ + + + + + + + + + +
                                                                                                + +
                                                                                                +

                                                                                                500

                                                                                                +

                                                                                                抱歉,服务器出错了

                                                                                                + +
                                                                                                +
                                                                                                + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/result/error.html b/demo/webman/backend/plugin/admin/public/demos/result/error.html new file mode 100644 index 0000000000000000000000000000000000000000..e4780483231339c851454ea33201b51f92d4c7e1 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/result/error.html @@ -0,0 +1,45 @@ + + + + + 失败 + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +

                                                                                                提交失败

                                                                                                +

                                                                                                + 请核对并修改以下信息后,再重新提交。如果仅是简单操作,使用 Message 全局提示反馈即可。 + 本文字区域可以展示简单的补充说明,如果有类似展示 + “单据”的需求,下面这个灰色区域可以呈现比较复杂的内容。 +

                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + +     + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/result/success.html b/demo/webman/backend/plugin/admin/public/demos/result/success.html new file mode 100644 index 0000000000000000000000000000000000000000..1010cbeb4190e8acd509327acf8698f85a3e631f --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/result/success.html @@ -0,0 +1,37 @@ + + + + + 成功 + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +

                                                                                                提交成功

                                                                                                +

                                                                                                + 提交结果页用于反馈一系列操作任务的处理结果, + 如果仅是简单操作,使用 Message 全局提示反馈即可。 + 本文字区域可以展示简单的补充说明,如果有类似展示 + “单据”的需求,下面这个灰色区域可以呈现比较复杂的内容。 +

                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + +     + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/system/deptment.html b/demo/webman/backend/plugin/admin/public/demos/system/deptment.html new file mode 100644 index 0000000000000000000000000000000000000000..7d4cc955b7073879a79839c0965372ed644e155b --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/deptment.html @@ -0,0 +1,289 @@ + + + + + 部门管理 + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/system/dict.html b/demo/webman/backend/plugin/admin/public/demos/system/dict.html new file mode 100644 index 0000000000000000000000000000000000000000..e08ee15a607552f356443946265addd064fff2d8 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/dict.html @@ -0,0 +1,341 @@ + + + + + 数据字典 + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + + + + + + + + + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/system/log.html b/demo/webman/backend/plugin/admin/public/demos/system/log.html new file mode 100644 index 0000000000000000000000000000000000000000..100b5edac83d7f6e54d2ca492cb82e7c5e0d3e47 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/log.html @@ -0,0 +1,101 @@ + + + + + 行为日志 + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                    +
                                                                                                  • 登录日志
                                                                                                  • +
                                                                                                  • 操作日志
                                                                                                  • +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/system/operate.html b/demo/webman/backend/plugin/admin/public/demos/system/operate.html new file mode 100644 index 0000000000000000000000000000000000000000..fec1c876632a8c14d693d523358d991fce7f2c1c --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/operate.html @@ -0,0 +1,107 @@ + + + + + 表单页面 + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/system/operate/add.html b/demo/webman/backend/plugin/admin/public/demos/system/operate/add.html new file mode 100644 index 0000000000000000000000000000000000000000..82ecdf3316fa4866701683758d6c6961141e2262 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/operate/add.html @@ -0,0 +1,109 @@ + + + + + 新增页面 + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/system/operate/edit.html b/demo/webman/backend/plugin/admin/public/demos/system/operate/edit.html new file mode 100644 index 0000000000000000000000000000000000000000..82dbce82b8613ae6e30c0ee81c5184b735a10775 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/operate/edit.html @@ -0,0 +1,109 @@ + + + + + 修改页面 + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/system/operate/profile.html b/demo/webman/backend/plugin/admin/public/demos/system/operate/profile.html new file mode 100644 index 0000000000000000000000000000000000000000..6041005540aece88f45c10ee98945e3d5944056d --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/operate/profile.html @@ -0,0 +1,108 @@ + + + + + 头像上传 + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + +
                                                                                                  +
                                                                                                  建议:图片的尺寸宽高比为1:1,大小在5m以内。
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/system/person.html b/demo/webman/backend/plugin/admin/public/demos/system/person.html new file mode 100644 index 0000000000000000000000000000000000000000..a40abc4faa29bce00363c4f7ad5be85624c6319a --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/person.html @@ -0,0 +1,183 @@ + + + + + 个人资料 + + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +

                                                                                                  就眠仪式

                                                                                                  +

                                                                                                  China , 中国

                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + 今日事 ,今日毕 +
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  + 归档 +
                                                                                                  +
                                                                                                  +
                                                                                                    +
                                                                                                  • 优化代码格式2020-06-04 11:28
                                                                                                  • +
                                                                                                  • 新增消息组件2020-06-01 04:23
                                                                                                  • +
                                                                                                  • 移动端兼容2020-05-22 21:38
                                                                                                  • +
                                                                                                  • 系统布局优化2020-05-15 14:26
                                                                                                  • +
                                                                                                  • 兼容多系统菜单模式2020-05-13 16:32
                                                                                                  • +
                                                                                                  • 兼容多标签页切换2019-12-9 14:58
                                                                                                  • +
                                                                                                  • 扩展下拉组件2019-12-7 9:06
                                                                                                  • +
                                                                                                  • 扩展卡片样式2019-12-1 10:26
                                                                                                  • +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + 我的文章 +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?
                                                                                                  +
                                                                                                  + “Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~ +
                                                                                                  +
                                                                                                  2020-06-12        评论 5 点赞 12 转发 4
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?
                                                                                                  +
                                                                                                  + “Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~ +
                                                                                                  +
                                                                                                  2020-06-12        评论 5 点赞 12 转发 4
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?
                                                                                                  +
                                                                                                  + “Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~ +
                                                                                                  +
                                                                                                  2020-06-12        评论 5 点赞 12 转发 4
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?
                                                                                                  +
                                                                                                  + “Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~ +
                                                                                                  +
                                                                                                  2020-06-12        评论 5 点赞 12 转发 4
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?
                                                                                                  +
                                                                                                  + “Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~ +
                                                                                                  +
                                                                                                  2020-06-12        评论 5 点赞 12 转发 4
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?
                                                                                                  +
                                                                                                  + “Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~ +
                                                                                                  +
                                                                                                  2020-06-12        评论 5 点赞 12 转发 4
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?
                                                                                                  +
                                                                                                  + “Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~ +
                                                                                                  +
                                                                                                  2020-06-12        评论 5 点赞 12 转发 4
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/system/power.html b/demo/webman/backend/plugin/admin/public/demos/system/power.html new file mode 100644 index 0000000000000000000000000000000000000000..5535c0c477797f88ea17632ca2c4348ffef2fe16 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/power.html @@ -0,0 +1,241 @@ + + + + + 权限管理 + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/system/profile.html b/demo/webman/backend/plugin/admin/public/demos/system/profile.html new file mode 100644 index 0000000000000000000000000000000000000000..6041005540aece88f45c10ee98945e3d5944056d --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/profile.html @@ -0,0 +1,108 @@ + + + + + 头像上传 + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + +
                                                                                                  +
                                                                                                  建议:图片的尺寸宽高比为1:1,大小在5m以内。
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/demos/system/role.html b/demo/webman/backend/plugin/admin/public/demos/system/role.html new file mode 100644 index 0000000000000000000000000000000000000000..ec3d42b52bbc351c678e54e694fa1ab9cba434ef --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/role.html @@ -0,0 +1,226 @@ + + + + + 角色管理 + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/system/space.html b/demo/webman/backend/plugin/admin/public/demos/system/space.html new file mode 100644 index 0000000000000000000000000000000000000000..8ab19e39c32706d6c96a6517c03b32cb209724e5 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/space.html @@ -0,0 +1,27 @@ + + + + + 空白页面 + + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +

                                                                                                  Space Page

                                                                                                  +
                                                                                                  +
                                                                                                  + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/system/theme.html b/demo/webman/backend/plugin/admin/public/demos/system/theme.html new file mode 100644 index 0000000000000000000000000000000000000000..b5ef672691afb0b19aa27dc16785cfd21fc16590 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/theme.html @@ -0,0 +1,300 @@ + + + + + 主题预览 + + + +
                                                                                                  +
                                                                                                  按钮
                                                                                                  +
                                                                                                  + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  输入框
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  复选框
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  开关
                                                                                                  +
                                                                                                  +
                                                                                                  +    +    +    +    +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  单选框
                                                                                                  +
                                                                                                  +
                                                                                                  + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  下拉
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + + + + + + + + +
                                                                                                  +
                                                                                                  选项卡
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                    +
                                                                                                  • 网站设置
                                                                                                  • +
                                                                                                  • 用户管理
                                                                                                  • +
                                                                                                  • 权限分配
                                                                                                  • +
                                                                                                  • 商品管理
                                                                                                  • +
                                                                                                  • 订单管理
                                                                                                  • +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  进度条
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  分页
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  辅助元素
                                                                                                  +
                                                                                                  +
                                                                                                  快乐的时候不敢尽兴,频繁警戒自己保持清醒.
                                                                                                  +
                                                                                                  路上没有灯火的时候,就点亮自己的头颅.
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                    +
                                                                                                  • + +
                                                                                                    +

                                                                                                    8月18日

                                                                                                    +

                                                                                                    + layui 2.0 的一切准备工作似乎都已到位。发布之弦,一触即发。 +

                                                                                                    +
                                                                                                    +
                                                                                                  • +
                                                                                                  • + +
                                                                                                    +

                                                                                                    8月16日

                                                                                                    +

                                                                                                    杜甫的思想核心是儒家的仁政思想,他有“致君尧舜上,再使风俗淳”的宏伟抱负。个人最爱的名篇有:

                                                                                                    +
                                                                                                    +
                                                                                                  • +
                                                                                                  • + +
                                                                                                    +

                                                                                                    8月15日

                                                                                                    +

                                                                                                    + 中国人民抗日战争胜利72周年 +

                                                                                                    +
                                                                                                    +
                                                                                                  • +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  日期选择
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/demos/system/user.html b/demo/webman/backend/plugin/admin/public/demos/system/user.html new file mode 100644 index 0000000000000000000000000000000000000000..3acd98d74ce207353fe65d3d283e9ad451e9f618 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/demos/system/user.html @@ -0,0 +1,298 @@ + + + + + 用户管理 + + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  + +
                                                                                                  +
                                                                                                  +
                                                                                                  + + +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/backend/plugin/admin/public/favicon.ico b/demo/webman/backend/plugin/admin/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d92e0b8c4963f1ae81021bbed63e94c2699dea66 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/favicon.ico differ diff --git a/demo/webman/backend/plugin/admin/public/resource/img/logo.png b/demo/webman/backend/plugin/admin/public/resource/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6c78db2112bde50291c622200160a6db5dbee348 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/resource/img/logo.png differ diff --git a/demo/webman/backend/plugin/admin/public/resource/img/pwa-192x192.png b/demo/webman/backend/plugin/admin/public/resource/img/pwa-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..67e7b0a3844b281ae57cbc3badbff47d16b34e10 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/resource/img/pwa-192x192.png differ diff --git a/demo/webman/backend/plugin/admin/public/resource/img/pwa-512x512.png b/demo/webman/backend/plugin/admin/public/resource/img/pwa-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..fd6998b9af6be30ad7a475b8126a0b39fc69eaa3 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/resource/img/pwa-512x512.png differ diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/langs/en.js b/demo/webman/backend/plugin/admin/public/resource/tinymce/langs/en.js new file mode 100644 index 0000000000000000000000000000000000000000..27337c3941ffbd7d1745403315987517c7d26303 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/resource/tinymce/langs/en.js @@ -0,0 +1,419 @@ +tinymce.addI18n('es', { + Redo: 'Rehacer', + Undo: 'Deshacer', + Cut: 'Cortar', + Copy: 'Copiar', + Paste: 'Pegar', + 'Select all': 'Seleccionar todo', + 'New document': 'Nuevo documento', + Ok: 'Ok', + Cancel: 'Cancelar', + 'Visual aids': 'Ayudas visuales', + Bold: 'Negrita', + Italic: 'Cursiva', + Underline: 'Subrayado', + Strikethrough: 'Tachado', + Superscript: 'Super\u00edndice', + Subscript: 'Sub\u00edndice', + 'Clear formatting': 'Limpiar formato', + 'Align left': 'Alinear a la izquierda', + 'Align center': 'Alinear al centro', + 'Align right': 'Alinear a la derecha', + Justify: 'Justificar', + 'Bullet list': 'Lista de vi\u00f1etas', + 'Numbered list': 'Lista numerada', + 'Decrease indent': 'Disminuir sangr\u00eda', + 'Increase indent': 'Incrementar sangr\u00eda', + Close: 'Cerrar', + Formats: 'Formatos', + "Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": 'Su navegador no es compatible con el acceso directo al portapapeles. Use las teclas Crtl+X\/C\/V de su teclado.', + Headers: 'Encabezados', + 'Header 1': 'Encabezado 1', + 'Header 2': 'Encabezado 2', + 'Header 3': 'Encabezado 3', + 'Header 4': 'Encabezado 4', + 'Header 5': 'Encabezado 5', + 'Header 6': 'Encabezado 6', + Headings: 'Encabezados', + 'Heading 1': 'Encabezado 1', + 'Heading 2': 'Encabezado 2', + 'Heading 3': 'Encabezado 3', + 'Heading 4': 'Encabezado 4', + 'Heading 5': 'Encabezado 5', + 'Heading 6': 'Encabezado 6', + Preformatted: 'Con formato previo', + Div: 'Div', + Pre: 'Pre', + Code: 'C\u00f3digo', + Paragraph: 'P\u00e1rrafo', + Blockquote: 'Blockquote', + Inline: 'Alineado', + Blocks: 'Bloques', + 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.': 'Pegar est\u00e1 ahora en modo de texto plano. El contenido se pegar\u00e1 como texto plano hasta que desactive esta opci\u00f3n.', + Fonts: 'Fuentes', + 'Font Sizes': 'Tama\u00f1os de fuente', + Class: 'Clase', + 'Browse for an image': 'Buscar una imagen', + OR: 'OR', + 'Drop an image here': 'Arrastre una imagen aqu\u00ed', + Upload: 'Cargar', + Block: 'Bloque', + Align: 'Alinear', + Default: 'Por defecto', + Circle: 'C\u00edrculo', + Disc: 'Disco', + Square: 'Cuadrado', + 'Lower Alpha': 'Inferior Alfa', + 'Lower Greek': 'Inferior Griega', + 'Lower Roman': 'Inferior Romana', + 'Upper Alpha': 'Superior Alfa', + 'Upper Roman': 'Superior Romana', + 'Anchor...': 'Anclaje...', + Name: 'Nombre', + Id: 'Id', + 'Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.': 'Deber\u00eda comenzar por una letra, seguida solo de letras, n\u00fameros, guiones, puntos, dos puntos o guiones bajos.', + 'You have unsaved changes are you sure you want to navigate away?': 'Tiene cambios sin guardar. \u00bfEst\u00e1 seguro de que quiere salir?', + 'Restore last draft': 'Restaurar el \u00faltimo borrador', + 'Special character...': 'Car\u00e1cter especial...', + 'Source code': 'C\u00f3digo fuente', + 'Insert\/Edit code sample': 'Insertar\/editar c\u00f3digo de prueba', + Language: 'Idioma', + 'Code sample...': 'Ejemplo de c\u00f3digo...', + 'Color Picker': 'Selector de colores', + R: 'R', + G: 'V', + B: 'A', + 'Left to right': 'De izquierda a derecha', + 'Right to left': 'De derecha a izquierda', + 'Emoticons...': 'Emoticones...', + 'Metadata and Document Properties': 'Metadatos y propiedades del documento', + Title: 'T\u00edtulo', + Keywords: 'Palabras clave', + Description: 'Descripci\u00f3n', + Robots: 'Robots', + Author: 'Autor', + Encoding: 'Codificaci\u00f3n', + Fullscreen: 'Pantalla completa', + Action: 'Acci\u00f3n', + Shortcut: 'Atajo', + Help: 'Ayuda', + Address: 'Direcci\u00f3n', + 'Focus to menubar': 'Enfocar la barra del men\u00fa', + 'Focus to toolbar': 'Enfocar la barra de herramientas', + 'Focus to element path': 'Enfocar la ruta del elemento', + 'Focus to contextual toolbar': 'Enfocar la barra de herramientas contextual', + 'Insert link (if link plugin activated)': 'Insertar enlace (si el complemento de enlace est\u00e1 activado)', + 'Save (if save plugin activated)': 'Guardar (si el componente de salvar est\u00e1 activado)', + 'Find (if searchreplace plugin activated)': 'Buscar (si el complemento buscar-remplazar est\u00e1 activado)', + 'Plugins installed ({0}):': 'Plugins instalados ({0}):', + 'Premium plugins:': 'Complementos premium:', + 'Learn more...': 'Aprende m\u00e1s...', + 'You are using {0}': 'Estas usando {0}', + Plugins: 'Complementos', + 'Handy Shortcuts': 'Accesos directos', + 'Horizontal line': 'L\u00ednea horizontal', + 'Insert\/edit image': 'Insertar\/editar imagen', + 'Image description': 'Descripci\u00f3n de la imagen', + Source: 'Enlace', + Dimensions: 'Dimensiones', + 'Constrain proportions': 'Restringir proporciones', + General: 'General', + Advanced: 'Avanzado', + Style: 'Estilo', + 'Vertical space': 'Espacio vertical', + 'Horizontal space': 'Espacio horizontal', + Border: 'Borde', + 'Insert image': 'Insertar imagen', + 'Image...': 'Imagen...', + 'Image list': 'Lista de im\u00e1genes', + 'Rotate counterclockwise': 'Girar a la izquierda', + 'Rotate clockwise': 'Girar a la derecha', + 'Flip vertically': 'Invertir verticalmente', + 'Flip horizontally': 'Invertir horizontalmente', + 'Edit image': 'Editar imagen', + 'Image options': 'Opciones de imagen', + 'Zoom in': 'Acercar', + 'Zoom out': 'Alejar', + Crop: 'Recortar', + Resize: 'Redimensionar', + Orientation: 'Orientaci\u00f3n', + Brightness: 'Brillo', + Sharpen: 'Forma', + Contrast: 'Contraste', + 'Color levels': 'Niveles de color', + Gamma: 'Gamma', + Invert: 'Invertir', + Apply: 'Aplicar', + Back: 'Atr\u00e1s', + 'Insert date\/time': 'Insertar fecha\/hora', + 'Date\/time': 'Fecha\/hora', + 'Insert\/Edit Link': 'Insertar\/editar enlace', + 'Insert\/edit link': 'Insertar\/editar enlace', + 'Text to display': 'Texto para mostrar', + Url: 'URL', + 'Open link in...': 'Abrir enlace en...', + 'Current window': 'Ventana actual', + None: 'Ninguno', + 'New window': 'Nueva ventana', + 'Remove link': 'Quitar enlace', + Anchors: 'Anclas', + 'Link...': 'Enlace...', + 'Paste or type a link': 'Pega o introduce un enlace', + 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?': 'El enlace que has introducido no parece ser una direcci\u00f3n de correo electr\u00f3nico. Quieres a\u00f1adir el prefijo necesario mailto: ?', + 'The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?': 'El enlace que has introducido no parece ser una enlace externo. Quieres a\u00f1adir el prefijo necesario http:\/\/ ?', + 'Link list': 'Lista de enlaces', + 'Insert video': 'Insertar video', + 'Insert\/edit video': 'Insertar\/editar video', + 'Insert\/edit media': 'Insertar\/editar medio', + 'Alternative source': 'Enlace alternativo', + 'Alternative source URL': 'Origen de URL alternativo', + 'Media poster (Image URL)': 'P\u00f3ster de medio (URL de imagen)', + 'Paste your embed code below:': 'Pega tu c\u00f3digo embebido debajo', + Embed: 'Incrustado', + 'Media...': 'Medios...', + 'Nonbreaking space': 'Espacio fijo', + 'Page break': 'Salto de p\u00e1gina', + 'Paste as text': 'Pegar como texto', + Preview: 'Previsualizar', + 'Print...': 'Imprimir...', + Save: 'Guardar', + Find: 'Buscar', + 'Replace with': 'Reemplazar con', + Replace: 'Reemplazar', + 'Replace all': 'Reemplazar todo', + Previous: 'Anterior', + Next: 'Siguiente', + 'Find and replace...': 'Buscar y reemplazar...', + 'Could not find the specified string.': 'No se encuentra la cadena de texto especificada', + 'Match case': 'Coincidencia exacta', + 'Find whole words only': 'Solo palabras completas', + 'Spell check': 'Revisar ortograf\u00eda', + Ignore: 'Ignorar', + 'Ignore all': 'Ignorar todos', + Finish: 'Finalizar', + 'Add to Dictionary': 'A\u00f1adir al Diccionario', + 'Insert table': 'Insertar tabla', + 'Table properties': 'Propiedades de la tabla', + 'Delete table': 'Eliminar tabla', + Cell: 'Celda', + Row: 'Fila', + Column: 'Columna', + 'Cell properties': 'Propiedades de la celda', + 'Merge cells': 'Combinar celdas', + 'Split cell': 'Dividir celdas', + 'Insert row before': 'Insertar fila antes', + 'Insert row after': 'Insertar fila despu\u00e9s ', + 'Delete row': 'Eliminar fila', + 'Row properties': 'Propiedades de la fila', + 'Cut row': 'Cortar fila', + 'Copy row': 'Copiar fila', + 'Paste row before': 'Pegar la fila antes', + 'Paste row after': 'Pegar la fila despu\u00e9s', + 'Insert column before': 'Insertar columna antes', + 'Insert column after': 'Insertar columna despu\u00e9s', + 'Delete column': 'Eliminar columna', + Cols: 'Columnas', + Rows: 'Filas', + Width: 'Ancho', + Height: 'Alto', + 'Cell spacing': 'Espacio entre celdas', + 'Cell padding': 'Relleno de celda', + 'Show caption': 'Mostrar t\u00edtulo', + Left: 'Izquierda', + Center: 'Centrado', + Right: 'Derecha', + 'Cell type': 'Tipo de celda', + Scope: '\u00c1mbito', + Alignment: 'Alineaci\u00f3n', + 'H Align': 'Alineamiento Horizontal', + 'V Align': 'Alineamiento Vertical', + Top: 'Arriba', + Middle: 'Centro', + Bottom: 'Abajo', + 'Header cell': 'Celda de la cebecera', + 'Row group': 'Grupo de filas', + 'Column group': 'Grupo de columnas', + 'Row type': 'Tipo de fila', + Header: 'Cabecera', + Body: 'Cuerpo', + Footer: 'Pie de p\u00e1gina', + 'Border color': 'Color del borde', + 'Insert template...': 'Insertar plantilla...', + Templates: 'Plantillas', + Template: 'Plantilla', + 'Text color': 'Color del texto', + 'Background color': 'Color de fondo', + 'Custom...': 'Personalizar...', + 'Custom color': 'Color personalizado', + 'No color': 'Sin color', + 'Remove color': 'Quitar color', + 'Table of Contents': 'Tabla de contenidos', + 'Show blocks': 'Mostrar bloques', + 'Show invisible characters': 'Mostrar caracteres invisibles', + 'Word count': 'Contar palabras', + Count: 'Recuento', + Document: 'Documento', + Selection: 'Selecci\u00f3n', + Words: 'Palabras', + 'Words: {0}': 'Palabras: {0}', + '{0} words': '{0} palabras', + File: 'Archivo', + Edit: 'Editar', + Insert: 'Insertar', + View: 'Ver', + Format: 'Formato', + Table: 'Tabla', + Tools: 'Herramientas', + 'Powered by {0}': 'Desarrollado por {0}', + 'Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help': '\u00c1rea de texto enriquecido. Pulse ALT-F9 para el menu. Pulse ALT-F10 para la barra de herramientas. Pulse ALT-0 para ayuda', + 'Image title': 'Titulo de imagen', + 'Border width': 'Ancho de borde', + 'Border style': 'Estilo de borde', + Error: 'Error', + Warn: 'Advertencia', + Valid: 'V\u00e1lido', + 'To open the popup, press Shift+Enter': 'Para abrir el elemento emergente, pulse May\u00fas+Intro', + 'Rich Text Area. Press ALT-0 for help.': '\u00c1rea de texto enriquecido. Pulse ALT-0 para abrir la ayuda.', + 'System Font': 'Fuente de sistema', + 'Failed to upload image: {0}': 'Fallo al cargar imagen: {0}', + 'Failed to load plugin: {0} from url {1}': 'Fallo al cargar complemento: {0} desde URL {1}', + 'Failed to load plugin url: {0}': 'Fallo al cargar URL del complemento: {0}', + 'Failed to initialize plugin: {0}': 'Fallo al iniciar el complemento: {0}', + example: 'ejemplo', + Search: 'Buscar', + All: 'Todo', + Currency: 'Divisa', + Text: 'Texto', + Quotations: 'Comillas', + Mathematical: 'S\u00edmbolo matem\u00e1tico', + 'Extended Latin': 'Latino extendido A', + Symbols: 'S\u00edmbolos', + Arrows: 'Flechas', + 'User Defined': 'Definido por el usuario', + 'dollar sign': 'signo de d\u00f3lar', + 'currency sign': 'signo de divisa', + 'euro-currency sign': 'signo de euro', + 'colon sign': 'signo de dos puntos', + 'cruzeiro sign': 'signo de cruceiro', + 'french franc sign': 'signo de franco franc\u00e9s', + 'lira sign': 'signo de lira', + 'mill sign': 'signo de mill', + 'naira sign': 'signo de naira', + 'peseta sign': 'signo de peseta', + 'rupee sign': 'signo de rupia', + 'won sign': 'signo de won', + 'new sheqel sign': 'signo de nuevo s\u00e9quel', + 'dong sign': 'signo de dong', + 'kip sign': 'signo de kip', + 'tugrik sign': 'signo de tugrik', + 'drachma sign': 'signo de dracma', + 'german penny symbol': 'signo de penique alem\u00e1n', + 'peso sign': 'signo de peso', + 'guarani sign': 'signo de guaran\u00ed', + 'austral sign': 'signo de austral', + 'hryvnia sign': 'signo de grivna', + 'cedi sign': 'signo de cedi', + 'livre tournois sign': 'signo de libra tornesa', + 'spesmilo sign': 'signo de spesmilo', + 'tenge sign': 'signo de tenge', + 'indian rupee sign': 'signo de rupia india', + 'turkish lira sign': 'signo de lira turca', + 'nordic mark sign': 'signo de marco n\u00f3rdico', + 'manat sign': 'signo de manat', + 'ruble sign': 'signo de rublo', + 'yen character': 'car\u00e1cter de yen', + 'yuan character': 'car\u00e1cter de yuan', + 'yuan character, in hong kong and taiwan': 'car\u00e1cter de yuan en Hong Kong y Taiw\u00e1n', + 'yen\/yuan character variant one': 'Variante uno de car\u00e1cter de yen\/yuan', + 'Loading emoticons...': 'Cargando emoticonos...', + 'Could not load emoticons': 'No se han podido cargar los emoticonos', + People: 'Personas', + 'Animals and Nature': 'Animales y naturaleza', + 'Food and Drink': 'Comida y bebida', + Activity: 'Actividad', + 'Travel and Places': 'Viajes y lugares', + Objects: 'Objetos', + Flags: 'Banderas', + Characters: 'Caracteres', + 'Characters (no spaces)': 'Caracteres (sin espacios)', + '{0} characters': '{0} caracteres', + 'Error: Form submit field collision.': 'Error: Colisi\u00f3n de campo al enviar formulario.', + 'Error: No form element found.': 'Error: No se encuentra ning\u00fan elemento de formulario.', + Update: 'Actualizar', + 'Color swatch': 'Muestrario de colores', + Turquoise: 'Turquesa', + Green: 'Verde', + Blue: 'Azul', + Purple: 'P\u00farpura', + 'Navy Blue': 'Azul marino', + 'Dark Turquoise': 'Turquesa oscuro', + 'Dark Green': 'Verde oscuro', + 'Medium Blue': 'Azul medio', + 'Medium Purple': 'P\u00farpura medio', + 'Midnight Blue': 'Azul medio', + Yellow: 'Amarillo', + Orange: 'Naranja', + Red: 'Rojo', + 'Light Gray': 'Gris claro', + Gray: 'Gris', + 'Dark Yellow': 'Amarillo oscuro', + 'Dark Orange': 'Naranja oscuro', + 'Dark Red': 'Rojo oscuro', + 'Medium Gray': 'Gris medio', + 'Dark Gray': 'Gris oscuro', + 'Light Green': 'Verde claro', + 'Light Yellow': 'Amarillo claro', + 'Light Red': 'Rojo claro', + 'Light Purple': 'Morado claro', + 'Light Blue': 'Azul claro', + 'Dark Purple': 'Morado oscuro', + 'Dark Blue': 'Azul oscuro', + Black: 'Negro', + White: 'Blanco', + 'Switch to or from fullscreen mode': 'Activar o desactivar modo pantalla completa', + 'Open help dialog': 'Abrir di\u00e1logo de ayuda', + history: 'historial', + styles: 'estilos', + formatting: 'formato', + alignment: 'alineaci\u00f3n', + indentation: 'sangr\u00eda', + 'permanent pen': 'bol\u00edgrafo permanente', + comments: 'comentarios', + 'Format Painter': 'Copiar formato', + 'Insert\/edit iframe': 'Insertar\/editar iframe', + Capitalization: 'Uso de may\u00fasculas', + lowercase: 'min\u00fasculas', + UPPERCASE: 'MAY\u00daSCULAS', + 'Title Case': 'Tipo T\u00edtulo', + 'Permanent Pen Properties': 'Propiedades del bol\u00edgrafo permanente', + 'Permanent pen properties...': 'Propiedades del bol\u00edgrafo permanente...', + Font: 'Fuente', + Size: 'Tama\u00f1o', + 'More...': 'M\u00e1s...', + 'Spellcheck Language': 'Corrector', + 'Select...': 'Seleccionar...', + Preferences: 'Preferencias', + Yes: 'S\u00ed', + No: 'No', + 'Keyboard Navigation': 'Navegaci\u00f3n con el teclado', + Version: 'Versi\u00f3n', + Anchor: 'Ancla', + 'Special character': 'Car\u00e1cter especial', + 'Code sample': 'Ejemplo de c\u00f3digo', + Color: 'Color', + Emoticons: 'Emoticonos', + 'Document properties': 'Propiedades del documento', + Image: 'Imagen', + 'Insert link': 'Insertar enlace', + Target: 'Destino', + Link: 'Enlace', + Poster: 'Miniatura', + Media: 'Media', + Print: 'Imprimir', + Prev: 'Anterior', + 'Find and replace': 'Buscar y reemplazar', + 'Whole words': 'Palabras completas', + Spellcheck: 'Corrector ortogr\u00e1fico', + Caption: 'Subt\u00edtulo', + 'Insert template': 'Insertar plantilla' +}) diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/langs/zh_CN.js b/demo/webman/backend/plugin/admin/public/resource/tinymce/langs/zh_CN.js new file mode 100644 index 0000000000000000000000000000000000000000..f9d8b5cfd23f1625038794d2f606337692fc81e8 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/resource/tinymce/langs/zh_CN.js @@ -0,0 +1,389 @@ +tinymce.addI18n('zh_CN',{ +"Redo": "\u91cd\u505a", +"Undo": "\u64a4\u9500", +"Cut": "\u526a\u5207", +"Copy": "\u590d\u5236", +"Paste": "\u7c98\u8d34", +"Select all": "\u5168\u9009", +"New document": "\u65b0\u6587\u4ef6", +"Ok": "\u786e\u5b9a", +"Cancel": "\u53d6\u6d88", +"Visual aids": "\u7f51\u683c\u7ebf", +"Bold": "\u7c97\u4f53", +"Italic": "\u659c\u4f53", +"Underline": "\u4e0b\u5212\u7ebf", +"Strikethrough": "\u5220\u9664\u7ebf", +"Superscript": "\u4e0a\u6807", +"Subscript": "\u4e0b\u6807", +"Clear formatting": "\u6e05\u9664\u683c\u5f0f", +"Align left": "\u5de6\u8fb9\u5bf9\u9f50", +"Align center": "\u4e2d\u95f4\u5bf9\u9f50", +"Align right": "\u53f3\u8fb9\u5bf9\u9f50", +"Justify": "\u4e24\u7aef\u5bf9\u9f50", +"Bullet list": "\u9879\u76ee\u7b26\u53f7", +"Numbered list": "\u7f16\u53f7\u5217\u8868", +"Decrease indent": "\u51cf\u5c11\u7f29\u8fdb", +"Increase indent": "\u589e\u52a0\u7f29\u8fdb", +"Close": "\u5173\u95ed", +"Formats": "\u683c\u5f0f", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u4f60\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u6253\u5f00\u526a\u8d34\u677f\uff0c\u8bf7\u4f7f\u7528Ctrl+X\/C\/V\u7b49\u5feb\u6377\u952e\u3002", +"Headers": "\u6807\u9898", +"Header 1": "\u6807\u98981", +"Header 2": "\u6807\u98982", +"Header 3": "\u6807\u98983", +"Header 4": "\u6807\u98984", +"Header 5": "\u6807\u98985", +"Header 6": "\u6807\u98986", +"Headings": "\u6807\u9898", +"Heading 1": "\u6807\u98981", +"Heading 2": "\u6807\u98982", +"Heading 3": "\u6807\u98983", +"Heading 4": "\u6807\u98984", +"Heading 5": "\u6807\u98985", +"Heading 6": "\u6807\u98986", +"Preformatted": "\u9884\u5148\u683c\u5f0f\u5316\u7684", +"Div": "Div", +"Pre": "Pre", +"Code": "\u4ee3\u7801", +"Paragraph": "\u6bb5\u843d", +"Blockquote": "\u5f15\u6587\u533a\u5757", +"Inline": "\u6587\u672c", +"Blocks": "\u57fa\u5757", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u7c98\u8d34\u6a21\u5f0f\uff0c\u518d\u6b21\u70b9\u51fb\u53ef\u4ee5\u56de\u5230\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002", +"Fonts": "\u5b57\u4f53", +"Font Sizes": "\u5b57\u53f7", +"Class": "\u7c7b\u578b", +"Browse for an image": "\u6d4f\u89c8\u56fe\u50cf", +"OR": "\u6216", +"Drop an image here": "\u62d6\u653e\u4e00\u5f20\u56fe\u50cf\u81f3\u6b64", +"Upload": "\u4e0a\u4f20", +"Block": "\u5757", +"Align": "\u5bf9\u9f50", +"Default": "\u9ed8\u8ba4", +"Circle": "\u7a7a\u5fc3\u5706", +"Disc": "\u5b9e\u5fc3\u5706", +"Square": "\u65b9\u5757", +"Lower Alpha": "\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd", +"Lower Greek": "\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd", +"Lower Roman": "\u5c0f\u5199\u7f57\u9a6c\u5b57\u6bcd", +"Upper Alpha": "\u5927\u5199\u82f1\u6587\u5b57\u6bcd", +"Upper Roman": "\u5927\u5199\u7f57\u9a6c\u5b57\u6bcd", +"Anchor...": "\u951a\u70b9...", +"Name": "\u540d\u79f0", +"Id": "\u6807\u8bc6\u7b26", +"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\u6807\u8bc6\u7b26\u5e94\u8be5\u4ee5\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u8ddf\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002", +"You have unsaved changes are you sure you want to navigate away?": "\u4f60\u8fd8\u6709\u6587\u6863\u5c1a\u672a\u4fdd\u5b58\uff0c\u786e\u5b9a\u8981\u79bb\u5f00\uff1f", +"Restore last draft": "\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f", +"Special characters...": "\u7279\u6b8a\u5b57\u7b26...", +"Source code": "\u6e90\u4ee3\u7801", +"Insert\/Edit code sample": "\u63d2\u5165\/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b", +"Language": "\u8bed\u8a00", +"Code sample...": "\u793a\u4f8b\u4ee3\u7801...", +"Color Picker": "\u9009\u8272\u5668", +"R": "R", +"G": "G", +"B": "B", +"Left to right": "\u4ece\u5de6\u5230\u53f3", +"Right to left": "\u4ece\u53f3\u5230\u5de6", +"Emoticons...": "\u8868\u60c5\u7b26\u53f7...", +"Metadata and Document Properties": "\u5143\u6570\u636e\u548c\u6587\u6863\u5c5e\u6027", +"Title": "\u6807\u9898", +"Keywords": "\u5173\u952e\u8bcd", +"Description": "\u63cf\u8ff0", +"Robots": "\u673a\u5668\u4eba", +"Author": "\u4f5c\u8005", +"Encoding": "\u7f16\u7801", +"Fullscreen": "\u5168\u5c4f", +"Action": "\u64cd\u4f5c", +"Shortcut": "\u5feb\u6377\u952e", +"Help": "\u5e2e\u52a9", +"Address": "\u5730\u5740", +"Focus to menubar": "\u79fb\u52a8\u7126\u70b9\u5230\u83dc\u5355\u680f", +"Focus to toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u5de5\u5177\u680f", +"Focus to element path": "\u79fb\u52a8\u7126\u70b9\u5230\u5143\u7d20\u8def\u5f84", +"Focus to contextual toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u4e0a\u4e0b\u6587\u83dc\u5355", +"Insert link (if link plugin activated)": "\u63d2\u5165\u94fe\u63a5 (\u5982\u679c\u94fe\u63a5\u63d2\u4ef6\u5df2\u6fc0\u6d3b)", +"Save (if save plugin activated)": "\u4fdd\u5b58(\u5982\u679c\u4fdd\u5b58\u63d2\u4ef6\u5df2\u6fc0\u6d3b)", +"Find (if searchreplace plugin activated)": "\u67e5\u627e(\u5982\u679c\u67e5\u627e\u66ff\u6362\u63d2\u4ef6\u5df2\u6fc0\u6d3b)", +"Plugins installed ({0}):": "\u5df2\u5b89\u88c5\u63d2\u4ef6 ({0}):", +"Premium plugins:": "\u4f18\u79c0\u63d2\u4ef6\uff1a", +"Learn more...": "\u4e86\u89e3\u66f4\u591a...", +"You are using {0}": "\u4f60\u6b63\u5728\u4f7f\u7528 {0}", +"Plugins": "\u63d2\u4ef6", +"Handy Shortcuts": "\u5feb\u6377\u952e", +"Horizontal line": "\u6c34\u5e73\u5206\u5272\u7ebf", +"Insert\/edit image": "\u63d2\u5165\/\u7f16\u8f91\u56fe\u7247", +"Image description": "\u56fe\u7247\u63cf\u8ff0", +"Source": "\u5730\u5740", +"Dimensions": "\u5927\u5c0f", +"Constrain proportions": "\u4fdd\u6301\u7eb5\u6a2a\u6bd4", +"General": "\u666e\u901a", +"Advanced": "\u9ad8\u7ea7", +"Style": "\u6837\u5f0f", +"Vertical space": "\u5782\u76f4\u8fb9\u8ddd", +"Horizontal space": "\u6c34\u5e73\u8fb9\u8ddd", +"Border": "\u8fb9\u6846", +"Insert image": "\u63d2\u5165\u56fe\u7247", +"Image...": "\u56fe\u7247...", +"Image list": "\u56fe\u7247\u5217\u8868", +"Rotate counterclockwise": "\u9006\u65f6\u9488\u65cb\u8f6c", +"Rotate clockwise": "\u987a\u65f6\u9488\u65cb\u8f6c", +"Flip vertically": "\u5782\u76f4\u7ffb\u8f6c", +"Flip horizontally": "\u6c34\u5e73\u7ffb\u8f6c", +"Edit image": "\u7f16\u8f91\u56fe\u7247", +"Image options": "\u56fe\u7247\u9009\u9879", +"Zoom in": "\u653e\u5927", +"Zoom out": "\u7f29\u5c0f", +"Crop": "\u88c1\u526a", +"Resize": "\u8c03\u6574\u5927\u5c0f", +"Orientation": "\u65b9\u5411", +"Brightness": "\u4eae\u5ea6", +"Sharpen": "\u9510\u5316", +"Contrast": "\u5bf9\u6bd4\u5ea6", +"Color levels": "\u989c\u8272\u5c42\u6b21", +"Gamma": "\u4f3d\u9a6c\u503c", +"Invert": "\u53cd\u8f6c", +"Apply": "\u5e94\u7528", +"Back": "\u540e\u9000", +"Insert date\/time": "\u63d2\u5165\u65e5\u671f\/\u65f6\u95f4", +"Date\/time": "\u65e5\u671f\/\u65f6\u95f4", +"Insert\/Edit Link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5", +"Insert\/edit link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5", +"Text to display": "\u663e\u793a\u6587\u5b57", +"Url": "\u5730\u5740", +"Open link in...": "\u94fe\u63a5\u6253\u5f00\u4f4d\u7f6e...", +"Current window": "\u5f53\u524d\u7a97\u53e3", +"None": "\u65e0", +"New window": "\u5728\u65b0\u7a97\u53e3\u6253\u5f00", +"Remove link": "\u5220\u9664\u94fe\u63a5", +"Anchors": "\u951a\u70b9", +"Link...": "\u94fe\u63a5...", +"Paste or type a link": "\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u4e3a\u90ae\u4ef6\u5730\u5740\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7f00\u5417\uff1f", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u5c5e\u4e8e\u5916\u90e8\u94fe\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp:\/\/:\u524d\u7f00\u5417\uff1f", +"Link list": "\u94fe\u63a5\u5217\u8868", +"Insert video": "\u63d2\u5165\u89c6\u9891", +"Insert\/edit video": "\u63d2\u5165\/\u7f16\u8f91\u89c6\u9891", +"Insert\/edit media": "\u63d2\u5165\/\u7f16\u8f91\u5a92\u4f53", +"Alternative source": "\u955c\u50cf", +"Alternative source URL": "\u66ff\u4ee3\u6765\u6e90\u7f51\u5740", +"Media poster (Image URL)": "\u5c01\u9762(\u56fe\u7247\u5730\u5740)", +"Paste your embed code below:": "\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:", +"Embed": "\u5185\u5d4c", +"Media...": "\u591a\u5a92\u4f53...", +"Nonbreaking space": "\u4e0d\u95f4\u65ad\u7a7a\u683c", +"Page break": "\u5206\u9875\u7b26", +"Paste as text": "\u7c98\u8d34\u4e3a\u6587\u672c", +"Preview": "\u9884\u89c8", +"Print...": "\u6253\u5370...", +"Save": "\u4fdd\u5b58", +"Find": "\u67e5\u627e", +"Replace with": "\u66ff\u6362\u4e3a", +"Replace": "\u66ff\u6362", +"Replace all": "\u5168\u90e8\u66ff\u6362", +"Previous": "\u4e0a\u4e00\u4e2a", +"Next": "\u4e0b\u4e00\u4e2a", +"Find and replace...": "\u67e5\u627e\u5e76\u66ff\u6362...", +"Could not find the specified string.": "\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9.", +"Match case": "\u533a\u5206\u5927\u5c0f\u5199", +"Find whole words only": "\u5168\u5b57\u5339\u914d", +"Spell check": "\u62fc\u5199\u68c0\u67e5", +"Ignore": "\u5ffd\u7565", +"Ignore all": "\u5168\u90e8\u5ffd\u7565", +"Finish": "\u5b8c\u6210", +"Add to Dictionary": "\u6dfb\u52a0\u5230\u5b57\u5178", +"Insert table": "\u63d2\u5165\u8868\u683c", +"Table properties": "\u8868\u683c\u5c5e\u6027", +"Delete table": "\u5220\u9664\u8868\u683c", +"Cell": "\u5355\u5143\u683c", +"Row": "\u884c", +"Column": "\u5217", +"Cell properties": "\u5355\u5143\u683c\u5c5e\u6027", +"Merge cells": "\u5408\u5e76\u5355\u5143\u683c", +"Split cell": "\u62c6\u5206\u5355\u5143\u683c", +"Insert row before": "\u5728\u4e0a\u65b9\u63d2\u5165", +"Insert row after": "\u5728\u4e0b\u65b9\u63d2\u5165", +"Delete row": "\u5220\u9664\u884c", +"Row properties": "\u884c\u5c5e\u6027", +"Cut row": "\u526a\u5207\u884c", +"Copy row": "\u590d\u5236\u884c", +"Paste row before": "\u7c98\u8d34\u5230\u4e0a\u65b9", +"Paste row after": "\u7c98\u8d34\u5230\u4e0b\u65b9", +"Insert column before": "\u5728\u5de6\u4fa7\u63d2\u5165", +"Insert column after": "\u5728\u53f3\u4fa7\u63d2\u5165", +"Delete column": "\u5220\u9664\u5217", +"Cols": "\u5217", +"Rows": "\u884c", +"Width": "\u5bbd", +"Height": "\u9ad8", +"Cell spacing": "\u5355\u5143\u683c\u5916\u95f4\u8ddd", +"Cell padding": "\u5355\u5143\u683c\u5185\u8fb9\u8ddd", +"Show caption": "\u663e\u793a\u6807\u9898", +"Left": "\u5de6\u5bf9\u9f50", +"Center": "\u5c45\u4e2d", +"Right": "\u53f3\u5bf9\u9f50", +"Cell type": "\u5355\u5143\u683c\u7c7b\u578b", +"Scope": "\u8303\u56f4", +"Alignment": "\u5bf9\u9f50\u65b9\u5f0f", +"H Align": "\u6c34\u5e73\u5bf9\u9f50", +"V Align": "\u5782\u76f4\u5bf9\u9f50", +"Top": "\u9876\u90e8\u5bf9\u9f50", +"Middle": "\u5782\u76f4\u5c45\u4e2d", +"Bottom": "\u5e95\u90e8\u5bf9\u9f50", +"Header cell": "\u8868\u5934\u5355\u5143\u683c", +"Row group": "\u884c\u7ec4", +"Column group": "\u5217\u7ec4", +"Row type": "\u884c\u7c7b\u578b", +"Header": "\u8868\u5934", +"Body": "\u8868\u4f53", +"Footer": "\u8868\u5c3e", +"Border color": "\u8fb9\u6846\u989c\u8272", +"Insert template...": "\u63d2\u5165\u6a21\u677f...", +"Templates": "\u6a21\u677f", +"Template": "\u6a21\u677f", +"Text color": "\u6587\u5b57\u989c\u8272", +"Background color": "\u80cc\u666f\u8272", +"Custom...": "\u81ea\u5b9a\u4e49...", +"Custom color": "\u81ea\u5b9a\u4e49\u989c\u8272", +"No color": "\u65e0", +"Remove color": "\u79fb\u9664\u989c\u8272", +"Table of Contents": "\u5185\u5bb9\u5217\u8868", +"Show blocks": "\u663e\u793a\u533a\u5757\u8fb9\u6846", +"Show invisible characters": "\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26", +"Word count": "\u5b57\u6570", +"Words: {0}": "\u5b57\u6570\uff1a{0}", +"{0} words": "{0} \u5b57", +"File": "\u6587\u4ef6", +"Edit": "\u7f16\u8f91", +"Insert": "\u63d2\u5165", +"View": "\u89c6\u56fe", +"Format": "\u683c\u5f0f", +"Table": "\u8868\u683c", +"Tools": "\u5de5\u5177", +"Powered by {0}": "\u7531{0}\u9a71\u52a8", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u5728\u7f16\u8f91\u533a\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9", +"Image title": "\u56fe\u7247\u6807\u9898", +"Border width": "\u8fb9\u6846\u5bbd\u5ea6", +"Border style": "\u8fb9\u6846\u6837\u5f0f", +"Error": "\u9519\u8bef", +"Warn": "\u8b66\u544a", +"Valid": "\u6709\u6548", +"To open the popup, press Shift+Enter": "\u6309Shitf+Enter\u952e\u6253\u5f00\u5bf9\u8bdd\u6846", +"Rich Text Area. Press ALT-0 for help.": "\u7f16\u8f91\u533a\u3002\u6309Alt+0\u952e\u6253\u5f00\u5e2e\u52a9\u3002", +"System Font": "\u7cfb\u7edf\u5b57\u4f53", +"Failed to upload image: {0}": "\u56fe\u7247\u4e0a\u4f20\u5931\u8d25: {0}", +"Failed to load plugin: {0} from url {1}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25: {0} \u6765\u81ea\u94fe\u63a5 {1}", +"Failed to load plugin url: {0}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25 \u94fe\u63a5: {0}", +"Failed to initialize plugin: {0}": "\u63d2\u4ef6\u521d\u59cb\u5316\u5931\u8d25: {0}", +"example": "\u793a\u4f8b", +"Search": "\u641c\u7d22", +"All": "\u5168\u90e8", +"Currency": "\u8d27\u5e01", +"Text": "\u6587\u5b57", +"Quotations": "\u5f15\u7528", +"Mathematical": "\u6570\u5b66", +"Extended Latin": "\u62c9\u4e01\u8bed\u6269\u5145", +"Symbols": "\u7b26\u53f7", +"Arrows": "\u7bad\u5934", +"User Defined": "\u81ea\u5b9a\u4e49", +"dollar sign": "\u7f8e\u5143\u7b26\u53f7", +"currency sign": "\u8d27\u5e01\u7b26\u53f7", +"euro-currency sign": "\u6b27\u5143\u7b26\u53f7", +"colon sign": "\u5192\u53f7", +"cruzeiro sign": "\u514b\u9c81\u8d5b\u7f57\u5e01\u7b26\u53f7", +"french franc sign": "\u6cd5\u90ce\u7b26\u53f7", +"lira sign": "\u91cc\u62c9\u7b26\u53f7", +"mill sign": "\u5bc6\u5c14\u7b26\u53f7", +"naira sign": "\u5948\u62c9\u7b26\u53f7", +"peseta sign": "\u6bd4\u585e\u5854\u7b26\u53f7", +"rupee sign": "\u5362\u6bd4\u7b26\u53f7", +"won sign": "\u97e9\u5143\u7b26\u53f7", +"new sheqel sign": "\u65b0\u8c22\u514b\u5c14\u7b26\u53f7", +"dong sign": "\u8d8a\u5357\u76fe\u7b26\u53f7", +"kip sign": "\u8001\u631d\u57fa\u666e\u7b26\u53f7", +"tugrik sign": "\u56fe\u683c\u91cc\u514b\u7b26\u53f7", +"drachma sign": "\u5fb7\u62c9\u514b\u9a6c\u7b26\u53f7", +"german penny symbol": "\u5fb7\u56fd\u4fbf\u58eb\u7b26\u53f7", +"peso sign": "\u6bd4\u7d22\u7b26\u53f7", +"guarani sign": "\u74dc\u62c9\u5c3c\u7b26\u53f7", +"austral sign": "\u6fb3\u5143\u7b26\u53f7", +"hryvnia sign": "\u683c\u91cc\u592b\u5c3c\u4e9a\u7b26\u53f7", +"cedi sign": "\u585e\u5730\u7b26\u53f7", +"livre tournois sign": "\u91cc\u5f17\u5f17\u5c14\u7b26\u53f7", +"spesmilo sign": "spesmilo\u7b26\u53f7", +"tenge sign": "\u575a\u6208\u7b26\u53f7", +"indian rupee sign": "\u5370\u5ea6\u5362\u6bd4", +"turkish lira sign": "\u571f\u8033\u5176\u91cc\u62c9", +"nordic mark sign": "\u5317\u6b27\u9a6c\u514b", +"manat sign": "\u9a6c\u7eb3\u7279\u7b26\u53f7", +"ruble sign": "\u5362\u5e03\u7b26\u53f7", +"yen character": "\u65e5\u5143\u5b57\u6837", +"yuan character": "\u4eba\u6c11\u5e01\u5143\u5b57\u6837", +"yuan character, in hong kong and taiwan": "\u5143\u5b57\u6837\uff08\u6e2f\u53f0\u5730\u533a\uff09", +"yen\/yuan character variant one": "\u5143\u5b57\u6837\uff08\u5927\u5199\uff09", +"Loading emoticons...": "\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7...", +"Could not load emoticons": "\u4e0d\u80fd\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7", +"People": "\u4eba\u7c7b", +"Animals and Nature": "\u52a8\u7269\u548c\u81ea\u7136", +"Food and Drink": "\u98df\u7269\u548c\u996e\u54c1", +"Activity": "\u6d3b\u52a8", +"Travel and Places": "\u65c5\u6e38\u548c\u5730\u70b9", +"Objects": "\u7269\u4ef6", +"Flags": "\u65d7\u5e1c", +"Characters": "\u5b57\u7b26", +"Characters (no spaces)": "\u5b57\u7b26(\u65e0\u7a7a\u683c)", +"Error: Form submit field collision.": "\u9519\u8bef: \u8868\u5355\u63d0\u4ea4\u5b57\u6bb5\u51b2\u7a81\u3002", +"Error: No form element found.": "\u9519\u8bef: \u6ca1\u6709\u8868\u5355\u63a7\u4ef6\u3002", +"Update": "\u66f4\u65b0", +"Color swatch": "\u989c\u8272\u6837\u672c", +"Turquoise": "\u9752\u7eff\u8272", +"Green": "\u7eff\u8272", +"Blue": "\u84dd\u8272", +"Purple": "\u7d2b\u8272", +"Navy Blue": "\u6d77\u519b\u84dd", +"Dark Turquoise": "\u6df1\u84dd\u7eff\u8272", +"Dark Green": "\u6df1\u7eff\u8272", +"Medium Blue": "\u4e2d\u84dd\u8272", +"Medium Purple": "\u4e2d\u7d2b\u8272", +"Midnight Blue": "\u6df1\u84dd\u8272", +"Yellow": "\u9ec4\u8272", +"Orange": "\u6a59\u8272", +"Red": "\u7ea2\u8272", +"Light Gray": "\u6d45\u7070\u8272", +"Gray": "\u7070\u8272", +"Dark Yellow": "\u6697\u9ec4\u8272", +"Dark Orange": "\u6df1\u6a59\u8272", +"Dark Red": "\u6df1\u7ea2\u8272", +"Medium Gray": "\u4e2d\u7070\u8272", +"Dark Gray": "\u6df1\u7070\u8272", +"Black": "\u9ed1\u8272", +"White": "\u767d\u8272", +"Switch to or from fullscreen mode": "\u5207\u6362\u5168\u5c4f\u6a21\u5f0f", +"Open help dialog": "\u6253\u5f00\u5e2e\u52a9\u5bf9\u8bdd\u6846", +"history": "\u5386\u53f2", +"styles": "\u6837\u5f0f", +"formatting": "\u683c\u5f0f\u5316", +"alignment": "\u5bf9\u9f50", +"indentation": "\u7f29\u8fdb", +"permanent pen": "\u8bb0\u53f7\u7b14", +"comments": "\u5907\u6ce8", +"Anchor": "\u951a\u70b9", +"Special character": "\u7279\u6b8a\u7b26\u53f7", +"Code sample": "\u4ee3\u7801\u793a\u4f8b", +"Color": "\u989c\u8272", +"Emoticons": "\u8868\u60c5", +"Document properties": "\u6587\u6863\u5c5e\u6027", +"Image": "\u56fe\u7247", +"Insert link": "\u63d2\u5165\u94fe\u63a5", +"Target": "\u6253\u5f00\u65b9\u5f0f", +"Link": "\u94fe\u63a5", +"Poster": "\u5c01\u9762", +"Media": "\u5a92\u4f53", +"Print": "\u6253\u5370", +"Prev": "\u4e0a\u4e00\u4e2a", +"Find and replace": "\u67e5\u627e\u548c\u66ff\u6362", +"Whole words": "\u5168\u5b57\u5339\u914d", +"Spellcheck": "\u62fc\u5199\u68c0\u67e5", +"Caption": "\u6807\u9898", +"Insert template": "\u63d2\u5165\u6a21\u677f" +}); \ No newline at end of file diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/content.inline.min.css b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/content.inline.min.css new file mode 100644 index 0000000000000000000000000000000000000000..748f313bb2324aefb902f5b679a54bbc042d5d60 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/content.inline.min.css @@ -0,0 +1,239 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.mce-content-body .mce-item-anchor{display: inline-block;width: 8px !important;height: 12px !important;padding: 0 2px;cursor: default;background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'8'%20height%3D'12'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20d%3D'M0%200L8%200%208%2012%204.09117821%209%200%2012z'%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;-webkit-user-select: all;-moz-user-select: all;-ms-user-select: all;user-select: all;-webkit-user-modify: read-only;-moz-user-modify: read-only;} + +.mce-content-body .mce-item-anchor[data-mce-selected]{outline-offset: 1px;} + +.tox-comments-visible .tox-comment{background-color: #fff0b7;} + +.tox-comments-visible .tox-comment--active{background-color: #ffe168;} + +.tox-checklist>li:not(.tox-checklist--hidden){margin: .25em 0;list-style: none;} + +.tox-checklist>li:not(.tox-checklist--hidden)::before{position: absolute;width: 1em;height: 1em;margin-top: .125em;margin-left: -1.5em;cursor: pointer;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-unchecked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2215%22%20height%3D%2215%22%20x%3D%22.5%22%20y%3D%22.5%22%20fill-rule%3D%22nonzero%22%20stroke%3D%22%234C4C4C%22%20rx%3D%222%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");background-size: 100%;content: '';} + +.tox-checklist li:not(.tox-checklist--hidden).tox-checklist--checked::before{background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-checked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%234099FF%22%20fill-rule%3D%22nonzero%22%20rx%3D%222%22%2F%3E%3Cpath%20id%3D%22Path%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%20d%3D%22M11.5703186%2C3.14417309%20C11.8516238%2C2.73724603%2012.4164781%2C2.62829933%2012.83558%2C2.89774797%20C13.260121%2C3.17069355%2013.3759736%2C3.72932262%2013.0909105%2C4.14168582%20L7.7580587%2C11.8560195%20C7.43776896%2C12.3193404%206.76483983%2C12.3852142%206.35607322%2C11.9948725%20L3.02491697%2C8.8138662%20C2.66090143%2C8.46625845%202.65798871%2C7.89594698%203.01850234%2C7.54483354%20C3.373942%2C7.19866177%203.94940006%2C7.19592841%204.30829608%2C7.5386474%20L6.85276923%2C9.9684299%20L11.5703186%2C3.14417309%20Z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");} + +[dir=rtl] .tox-checklist>li:not(.tox-checklist--hidden)::before{margin-right: -1.5em;margin-left: 0;} + +code[class*=language-],pre[class*=language-]{font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size: .875rem;-webkit-hyphens: none;-ms-hyphens: none;hyphens: none;line-height: 1.5;word-spacing: normal;color: #000;text-shadow: 0 1px #fff;word-break: normal;word-wrap: normal;white-space: pre;-moz-tab-size: 4;tab-size: 4;} + +code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow: none;background: #b3d4fc;} + +code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow: none;background: #b3d4fc;}@media print{code[class*=language-],pre[class*=language-]{text-shadow: none;}} + +pre[class*=language-]{padding: 1em;margin: .5em 0;overflow: auto;} + +:not(pre)>code[class*=language-],pre[class*=language-]{background: 0 0 !important;border: 1px solid #ccc;} + +:not(pre)>code[class*=language-]{padding: .1em;border-radius: .3em;} + +.token.cdata,.token.comment,.token.doctype,.token.prolog{color: #708090;} + +.token.punctuation{color: #999;} + +.namespace{opacity: .7;} + +.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color: #905;} + +.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color: #690;} + +.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color: #a67f59;background: hsla(0,0%,100%,.5);} + +.token.atrule,.token.attr-value,.token.keyword{color: #07a;} + +.token.function{color: #dd4a68;} + +.token.important,.token.regex,.token.variable{color: #e90;} + +.token.bold,.token.important{font-weight: 700;} + +.token.italic{font-style: italic;} + +.token.entity{cursor: help;} + +:not([dir=rtl]) code[class*=language-],:not([dir=rtl]) pre[class*=language-]{text-align: left;direction: ltr;} + +[dir=rtl] code[class*=language-],[dir=rtl] pre[class*=language-]{text-align: right;direction: rtl;} + +.mce-content-body{overflow-wrap: break-word;word-wrap: break-word;} + +.mce-content-body .mce-visual-caret{position: absolute;background-color: #000;background-color: currentColor;} + +.mce-content-body .mce-visual-caret-hidden{display: none;} + +.mce-content-body [data-mce-caret]{position: absolute;top: 0;right: auto;left: -1000px;padding: 0;margin: 0;} + +.mce-content-body .mce-offscreen-selection{position: absolute;left: -9999999999px;max-width: 1000000px;} + +.mce-content-body [contentEditable=false]{cursor: default;} + +.mce-content-body [contentEditable=true]{cursor: text;} + +.tox-cursor-format-painter{cursor: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"),default;} + +.mce-content-body figure.align-left{float: left;} + +.mce-content-body figure.align-right{float: right;} + +.mce-content-body figure.image.align-center{display: table;margin-right: auto;margin-left: auto;} + +.mce-preview-object{position: relative;display: inline-block;margin: 0 2px 0 2px;line-height: 0;border: 1px solid gray;} + +.mce-preview-object .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.mce-preview-object[data-mce-selected="2"] .mce-shim{display: none;} + +.mce-object{background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;border: 1px dashed #aaa;} + +.mce-pagebreak{display: block;width: 100%;height: 5px;margin-top: 15px;cursor: default;border: 1px dashed #aaa;page-break-before: always;}@media print{.mce-pagebreak{border: 0;}} + +.tiny-pageembed .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.tiny-pageembed[data-mce-selected="2"] .mce-shim{display: none;} + +.tiny-pageembed{position: relative;display: inline-block;} + +.tiny-pageembed--16by9,.tiny-pageembed--1by1,.tiny-pageembed--21by9,.tiny-pageembed--4by3{position: relative;display: block;width: 100%;padding: 0;overflow: hidden;} + +.tiny-pageembed--16by9::before,.tiny-pageembed--1by1::before,.tiny-pageembed--21by9::before,.tiny-pageembed--4by3::before{display: block;content: "";} + +.tiny-pageembed--21by9::before{padding-top: 42.857143%;} + +.tiny-pageembed--16by9::before{padding-top: 56.25%;} + +.tiny-pageembed--4by3::before{padding-top: 75%;} + +.tiny-pageembed--1by1::before{padding-top: 100%;} + +.tiny-pageembed--16by9 iframe,.tiny-pageembed--1by1 iframe,.tiny-pageembed--21by9 iframe,.tiny-pageembed--4by3 iframe{position: absolute;top: 0;left: 0;width: 100%;height: 100%;border: 0;} + +.mce-content-body div.mce-resizehandle{position: absolute;z-index: 10000;width: 10px;height: 10px;background-color: #4099ff;border-color: #4099ff;border-style: solid;border-width: 1px;box-sizing: border-box;} + +.mce-content-body div.mce-resizehandle:hover{background-color: #4099ff;} + +.mce-content-body div.mce-resizehandle:nth-of-type(1){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(2){cursor: nesw-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(3){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(4){cursor: nesw-resize;} + +.mce-content-body .mce-clonedresizable{position: absolute;z-index: 10000;outline: 1px dashed #000;opacity: .5;} + +.mce-content-body .mce-resize-helper{position: absolute;z-index: 10001;display: none;padding: 5px;margin: 5px 10px;font-family: sans-serif;font-size: 12px;line-height: 14px;color: #fff;white-space: nowrap;background: #555;background: rgba(0,0,0,.75);border: 1px;border-radius: 3px;} + +.mce-match-marker{color: #fff;background: #aaa;} + +.mce-match-marker-selected{color: #fff;background: #39f;} + +.mce-content-body img[data-mce-selected],.mce-content-body table[data-mce-selected]{outline: 3px solid #b4d7ff;} + +.mce-content-body hr[data-mce-selected]{outline: 3px solid #b4d7ff;outline-offset: 1px;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:focus{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:hover{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false][data-mce-selected]{cursor: not-allowed;outline: 3px solid #b4d7ff;} + +.mce-content-body.mce-content-readonly [contentEditable=true]:focus,.mce-content-body.mce-content-readonly [contentEditable=true]:hover{outline: 0;} + +.mce-content-body [data-mce-selected=inline-boundary]{background-color: #b4d7ff;} + +.mce-content-body .mce-edit-focus{outline: 3px solid #b4d7ff;} + +.mce-content-body td[data-mce-selected],.mce-content-body th[data-mce-selected]{background-color: #b4d7ff !important;} + +.mce-content-body td[data-mce-selected]::-moz-selection,.mce-content-body th[data-mce-selected]::-moz-selection{background: 0 0;} + +.mce-content-body td[data-mce-selected]::selection,.mce-content-body th[data-mce-selected]::selection{background: 0 0;} + +.mce-content-body td[data-mce-selected] *,.mce-content-body th[data-mce-selected] *{-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;} + +.mce-content-body img::-moz-selection{background: 0 0;} + +.mce-content-body img::selection{background: 0 0;} + +.ephox-snooker-resizer-bar{background-color: #b4d7ff;opacity: 0;} + +.ephox-snooker-resizer-cols{cursor: col-resize;} + +.ephox-snooker-resizer-rows{cursor: row-resize;} + +.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity: 1;} + +.mce-spellchecker-word{height: 2rem;cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23ff0000'%20fill%3D'none'%20stroke-linecap%3D'round'%20stroke-opacity%3D'.5'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-spellchecker-grammar{cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23008800'%20fill%3D'none'%20stroke-linecap%3D'round'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-toc{border: 1px solid gray;} + +.mce-toc h2{margin: 4px;} + +.mce-toc li{list-style-type: none;} + +.mce-item-table,.mce-item-table caption,.mce-item-table td,.mce-item-table th{border: 1px dashed #bbb;} + +.mce-visualblocks address,.mce-visualblocks article,.mce-visualblocks aside,.mce-visualblocks blockquote,.mce-visualblocks div:not([data-mce-bogus]),.mce-visualblocks dl,.mce-visualblocks figcaption,.mce-visualblocks figure,.mce-visualblocks h1,.mce-visualblocks h2,.mce-visualblocks h3,.mce-visualblocks h4,.mce-visualblocks h5,.mce-visualblocks h6,.mce-visualblocks hgroup,.mce-visualblocks ol,.mce-visualblocks p,.mce-visualblocks pre,.mce-visualblocks section,.mce-visualblocks ul{padding-top: 10px;margin-left: 3px;background-repeat: no-repeat;border: 1px dashed #bbb;} + +.mce-visualblocks p{background-image: url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7);} + +.mce-visualblocks h1{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==);} + +.mce-visualblocks h2{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==);} + +.mce-visualblocks h3{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7);} + +.mce-visualblocks h4{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==);} + +.mce-visualblocks h5{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==);} + +.mce-visualblocks h6{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==);} + +.mce-visualblocks div:not([data-mce-bogus]){background-image: url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7);} + +.mce-visualblocks section{background-image: url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=);} + +.mce-visualblocks article{background-image: url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7);} + +.mce-visualblocks blockquote{background-image: url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7);} + +.mce-visualblocks address{background-image: url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=);} + +.mce-visualblocks pre{background-image: url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==);} + +.mce-visualblocks figure{background-image: url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7);} + +.mce-visualblocks figcaption{border: 1px dashed #bbb;} + +.mce-visualblocks hgroup{background-image: url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7);} + +.mce-visualblocks aside{background-image: url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=);} + +.mce-visualblocks ul{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==);} + +.mce-visualblocks ol{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==);} + +.mce-visualblocks dl{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==);} + +.mce-visualblocks:not([dir=rtl]) address,.mce-visualblocks:not([dir=rtl]) article,.mce-visualblocks:not([dir=rtl]) aside,.mce-visualblocks:not([dir=rtl]) blockquote,.mce-visualblocks:not([dir=rtl]) div:not([data-mce-bogus]),.mce-visualblocks:not([dir=rtl]) dl,.mce-visualblocks:not([dir=rtl]) figcaption,.mce-visualblocks:not([dir=rtl]) figure,.mce-visualblocks:not([dir=rtl]) h1,.mce-visualblocks:not([dir=rtl]) h2,.mce-visualblocks:not([dir=rtl]) h3,.mce-visualblocks:not([dir=rtl]) h4,.mce-visualblocks:not([dir=rtl]) h5,.mce-visualblocks:not([dir=rtl]) h6,.mce-visualblocks:not([dir=rtl]) hgroup,.mce-visualblocks:not([dir=rtl]) ol,.mce-visualblocks:not([dir=rtl]) p,.mce-visualblocks:not([dir=rtl]) pre,.mce-visualblocks:not([dir=rtl]) section,.mce-visualblocks:not([dir=rtl]) ul{margin-left: 3px;} + +.mce-visualblocks[dir=rtl] address,.mce-visualblocks[dir=rtl] article,.mce-visualblocks[dir=rtl] aside,.mce-visualblocks[dir=rtl] blockquote,.mce-visualblocks[dir=rtl] div:not([data-mce-bogus]),.mce-visualblocks[dir=rtl] dl,.mce-visualblocks[dir=rtl] figcaption,.mce-visualblocks[dir=rtl] figure,.mce-visualblocks[dir=rtl] h1,.mce-visualblocks[dir=rtl] h2,.mce-visualblocks[dir=rtl] h3,.mce-visualblocks[dir=rtl] h4,.mce-visualblocks[dir=rtl] h5,.mce-visualblocks[dir=rtl] h6,.mce-visualblocks[dir=rtl] hgroup,.mce-visualblocks[dir=rtl] ol,.mce-visualblocks[dir=rtl] p,.mce-visualblocks[dir=rtl] pre,.mce-visualblocks[dir=rtl] section,.mce-visualblocks[dir=rtl] ul{background-position-x: right;margin-right: 3px;} + +.mce-nbsp,.mce-shy{background: #aaa;} + +.mce-shy::after{content: '-';} + +.tox-toolbar-dock-fadeout{opacity: 0;visibility: hidden;} + +.tox-toolbar-dock-fadein{opacity: 1;visibility: visible;} + +.tox-toolbar-dock-transition{transition: visibility 0s linear .3s,opacity .3s ease;} + +.tox-toolbar-dock-transition.tox-toolbar-dock-fadein{transition-delay: 0s;} diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/content.min.css b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/content.min.css new file mode 100644 index 0000000000000000000000000000000000000000..6e7165f097e99dac3a355448bcdb2598763617bf --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/content.min.css @@ -0,0 +1,235 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.mce-content-body .mce-item-anchor{display: inline-block;width: 8px !important;height: 12px !important;padding: 0 2px;cursor: default;background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'8'%20height%3D'12'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20d%3D'M0%200L8%200%208%2012%204.09117821%209%200%2012z'%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;-webkit-user-select: all;-moz-user-select: all;-ms-user-select: all;user-select: all;-webkit-user-modify: read-only;-moz-user-modify: read-only;} + +.mce-content-body .mce-item-anchor[data-mce-selected]{outline-offset: 1px;} + +.tox-comments-visible .tox-comment{background-color: #fff0b7;} + +.tox-comments-visible .tox-comment--active{background-color: #ffe168;} + +.tox-checklist>li:not(.tox-checklist--hidden){margin: .25em 0;list-style: none;} + +.tox-checklist>li:not(.tox-checklist--hidden)::before{position: absolute;width: 1em;height: 1em;margin-top: .125em;margin-left: -1.5em;cursor: pointer;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-unchecked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2215%22%20height%3D%2215%22%20x%3D%22.5%22%20y%3D%22.5%22%20fill-rule%3D%22nonzero%22%20stroke%3D%22%234C4C4C%22%20rx%3D%222%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");background-size: 100%;content: '';} + +.tox-checklist li:not(.tox-checklist--hidden).tox-checklist--checked::before{background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-checked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%234099FF%22%20fill-rule%3D%22nonzero%22%20rx%3D%222%22%2F%3E%3Cpath%20id%3D%22Path%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%20d%3D%22M11.5703186%2C3.14417309%20C11.8516238%2C2.73724603%2012.4164781%2C2.62829933%2012.83558%2C2.89774797%20C13.260121%2C3.17069355%2013.3759736%2C3.72932262%2013.0909105%2C4.14168582%20L7.7580587%2C11.8560195%20C7.43776896%2C12.3193404%206.76483983%2C12.3852142%206.35607322%2C11.9948725%20L3.02491697%2C8.8138662%20C2.66090143%2C8.46625845%202.65798871%2C7.89594698%203.01850234%2C7.54483354%20C3.373942%2C7.19866177%203.94940006%2C7.19592841%204.30829608%2C7.5386474%20L6.85276923%2C9.9684299%20L11.5703186%2C3.14417309%20Z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");} + +[dir=rtl] .tox-checklist>li:not(.tox-checklist--hidden)::before{margin-right: -1.5em;margin-left: 0;} + +code[class*=language-],pre[class*=language-]{font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size: .875rem;-webkit-hyphens: none;-ms-hyphens: none;hyphens: none;line-height: 1.5;word-spacing: normal;color: #000;text-shadow: 0 1px #fff;word-break: normal;word-wrap: normal;white-space: pre;-moz-tab-size: 4;tab-size: 4;} + +code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow: none;background: #b3d4fc;} + +code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow: none;background: #b3d4fc;}@media print{code[class*=language-],pre[class*=language-]{text-shadow: none;}} + +pre[class*=language-]{padding: 1em;margin: .5em 0;overflow: auto;} + +:not(pre)>code[class*=language-],pre[class*=language-]{background: 0 0 !important;border: 1px solid #ccc;} + +:not(pre)>code[class*=language-]{padding: .1em;border-radius: .3em;} + +.token.cdata,.token.comment,.token.doctype,.token.prolog{color: #708090;} + +.token.punctuation{color: #999;} + +.namespace{opacity: .7;} + +.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color: #905;} + +.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color: #690;} + +.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color: #a67f59;background: hsla(0,0%,100%,.5);} + +.token.atrule,.token.attr-value,.token.keyword{color: #07a;} + +.token.function{color: #dd4a68;} + +.token.important,.token.regex,.token.variable{color: #e90;} + +.token.bold,.token.important{font-weight: 700;} + +.token.italic{font-style: italic;} + +.token.entity{cursor: help;} + +:not([dir=rtl]) code[class*=language-],:not([dir=rtl]) pre[class*=language-]{text-align: left;direction: ltr;} + +[dir=rtl] code[class*=language-],[dir=rtl] pre[class*=language-]{text-align: right;direction: rtl;} + +.mce-content-body{overflow-wrap: break-word;word-wrap: break-word;} + +.mce-content-body .mce-visual-caret{position: absolute;background-color: #000;background-color: currentColor;} + +.mce-content-body .mce-visual-caret-hidden{display: none;} + +.mce-content-body [data-mce-caret]{position: absolute;top: 0;right: auto;left: -1000px;padding: 0;margin: 0;} + +.mce-content-body .mce-offscreen-selection{position: absolute;left: -9999999999px;max-width: 1000000px;} + +.mce-content-body [contentEditable=false]{cursor: default;} + +.mce-content-body [contentEditable=true]{cursor: text;} + +.tox-cursor-format-painter{cursor: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"),default;} + +.mce-content-body figure.align-left{float: left;} + +.mce-content-body figure.align-right{float: right;} + +.mce-content-body figure.image.align-center{display: table;margin-right: auto;margin-left: auto;} + +.mce-preview-object{position: relative;display: inline-block;margin: 0 2px 0 2px;line-height: 0;border: 1px solid gray;} + +.mce-preview-object .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.mce-preview-object[data-mce-selected="2"] .mce-shim{display: none;} + +.mce-object{background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;border: 1px dashed #aaa;} + +.mce-pagebreak{display: block;width: 100%;height: 5px;margin-top: 15px;cursor: default;border: 1px dashed #aaa;page-break-before: always;}@media print{.mce-pagebreak{border: 0;}} + +.tiny-pageembed .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.tiny-pageembed[data-mce-selected="2"] .mce-shim{display: none;} + +.tiny-pageembed{position: relative;display: inline-block;} + +.tiny-pageembed--16by9,.tiny-pageembed--1by1,.tiny-pageembed--21by9,.tiny-pageembed--4by3{position: relative;display: block;width: 100%;padding: 0;overflow: hidden;} + +.tiny-pageembed--16by9::before,.tiny-pageembed--1by1::before,.tiny-pageembed--21by9::before,.tiny-pageembed--4by3::before{display: block;content: "";} + +.tiny-pageembed--21by9::before{padding-top: 42.857143%;} + +.tiny-pageembed--16by9::before{padding-top: 56.25%;} + +.tiny-pageembed--4by3::before{padding-top: 75%;} + +.tiny-pageembed--1by1::before{padding-top: 100%;} + +.tiny-pageembed--16by9 iframe,.tiny-pageembed--1by1 iframe,.tiny-pageembed--21by9 iframe,.tiny-pageembed--4by3 iframe{position: absolute;top: 0;left: 0;width: 100%;height: 100%;border: 0;} + +.mce-content-body div.mce-resizehandle{position: absolute;z-index: 10000;width: 10px;height: 10px;background-color: #4099ff;border-color: #4099ff;border-style: solid;border-width: 1px;box-sizing: border-box;} + +.mce-content-body div.mce-resizehandle:hover{background-color: #4099ff;} + +.mce-content-body div.mce-resizehandle:nth-of-type(1){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(2){cursor: nesw-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(3){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(4){cursor: nesw-resize;} + +.mce-content-body .mce-clonedresizable{position: absolute;z-index: 10000;outline: 1px dashed #000;opacity: .5;} + +.mce-content-body .mce-resize-helper{position: absolute;z-index: 10001;display: none;padding: 5px;margin: 5px 10px;font-family: sans-serif;font-size: 12px;line-height: 14px;color: #fff;white-space: nowrap;background: #555;background: rgba(0,0,0,.75);border: 1px;border-radius: 3px;} + +.mce-match-marker{color: #fff;background: #aaa;} + +.mce-match-marker-selected{color: #fff;background: #39f;} + +.mce-content-body img[data-mce-selected],.mce-content-body table[data-mce-selected]{outline: 3px solid #b4d7ff;} + +.mce-content-body hr[data-mce-selected]{outline: 3px solid #b4d7ff;outline-offset: 1px;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:focus{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:hover{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false][data-mce-selected]{cursor: not-allowed;outline: 3px solid #b4d7ff;} + +.mce-content-body.mce-content-readonly [contentEditable=true]:focus,.mce-content-body.mce-content-readonly [contentEditable=true]:hover{outline: 0;} + +.mce-content-body [data-mce-selected=inline-boundary]{background-color: #b4d7ff;} + +.mce-content-body .mce-edit-focus{outline: 3px solid #b4d7ff;} + +.mce-content-body td[data-mce-selected],.mce-content-body th[data-mce-selected]{background-color: #b4d7ff !important;} + +.mce-content-body td[data-mce-selected]::-moz-selection,.mce-content-body th[data-mce-selected]::-moz-selection{background: 0 0;} + +.mce-content-body td[data-mce-selected]::selection,.mce-content-body th[data-mce-selected]::selection{background: 0 0;} + +.mce-content-body td[data-mce-selected] *,.mce-content-body th[data-mce-selected] *{-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;} + +.mce-content-body img::-moz-selection{background: 0 0;} + +.mce-content-body img::selection{background: 0 0;} + +.ephox-snooker-resizer-bar{background-color: #b4d7ff;opacity: 0;} + +.ephox-snooker-resizer-cols{cursor: col-resize;} + +.ephox-snooker-resizer-rows{cursor: row-resize;} + +.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity: 1;} + +.mce-spellchecker-word{height: 2rem;cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23ff0000'%20fill%3D'none'%20stroke-linecap%3D'round'%20stroke-opacity%3D'.5'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-spellchecker-grammar{cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23008800'%20fill%3D'none'%20stroke-linecap%3D'round'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-toc{border: 1px solid gray;} + +.mce-toc h2{margin: 4px;} + +.mce-toc li{list-style-type: none;} + +.mce-item-table,.mce-item-table caption,.mce-item-table td,.mce-item-table th{border: 1px dashed #bbb;} + +.mce-visualblocks address,.mce-visualblocks article,.mce-visualblocks aside,.mce-visualblocks blockquote,.mce-visualblocks div:not([data-mce-bogus]),.mce-visualblocks dl,.mce-visualblocks figcaption,.mce-visualblocks figure,.mce-visualblocks h1,.mce-visualblocks h2,.mce-visualblocks h3,.mce-visualblocks h4,.mce-visualblocks h5,.mce-visualblocks h6,.mce-visualblocks hgroup,.mce-visualblocks ol,.mce-visualblocks p,.mce-visualblocks pre,.mce-visualblocks section,.mce-visualblocks ul{padding-top: 10px;margin-left: 3px;background-repeat: no-repeat;border: 1px dashed #bbb;} + +.mce-visualblocks p{background-image: url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7);} + +.mce-visualblocks h1{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==);} + +.mce-visualblocks h2{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==);} + +.mce-visualblocks h3{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7);} + +.mce-visualblocks h4{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==);} + +.mce-visualblocks h5{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==);} + +.mce-visualblocks h6{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==);} + +.mce-visualblocks div:not([data-mce-bogus]){background-image: url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7);} + +.mce-visualblocks section{background-image: url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=);} + +.mce-visualblocks article{background-image: url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7);} + +.mce-visualblocks blockquote{background-image: url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7);} + +.mce-visualblocks address{background-image: url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=);} + +.mce-visualblocks pre{background-image: url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==);} + +.mce-visualblocks figure{background-image: url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7);} + +.mce-visualblocks figcaption{border: 1px dashed #bbb;} + +.mce-visualblocks hgroup{background-image: url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7);} + +.mce-visualblocks aside{background-image: url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=);} + +.mce-visualblocks ul{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==);} + +.mce-visualblocks ol{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==);} + +.mce-visualblocks dl{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==);} + +.mce-visualblocks:not([dir=rtl]) address,.mce-visualblocks:not([dir=rtl]) article,.mce-visualblocks:not([dir=rtl]) aside,.mce-visualblocks:not([dir=rtl]) blockquote,.mce-visualblocks:not([dir=rtl]) div:not([data-mce-bogus]),.mce-visualblocks:not([dir=rtl]) dl,.mce-visualblocks:not([dir=rtl]) figcaption,.mce-visualblocks:not([dir=rtl]) figure,.mce-visualblocks:not([dir=rtl]) h1,.mce-visualblocks:not([dir=rtl]) h2,.mce-visualblocks:not([dir=rtl]) h3,.mce-visualblocks:not([dir=rtl]) h4,.mce-visualblocks:not([dir=rtl]) h5,.mce-visualblocks:not([dir=rtl]) h6,.mce-visualblocks:not([dir=rtl]) hgroup,.mce-visualblocks:not([dir=rtl]) ol,.mce-visualblocks:not([dir=rtl]) p,.mce-visualblocks:not([dir=rtl]) pre,.mce-visualblocks:not([dir=rtl]) section,.mce-visualblocks:not([dir=rtl]) ul{margin-left: 3px;} + +.mce-visualblocks[dir=rtl] address,.mce-visualblocks[dir=rtl] article,.mce-visualblocks[dir=rtl] aside,.mce-visualblocks[dir=rtl] blockquote,.mce-visualblocks[dir=rtl] div:not([data-mce-bogus]),.mce-visualblocks[dir=rtl] dl,.mce-visualblocks[dir=rtl] figcaption,.mce-visualblocks[dir=rtl] figure,.mce-visualblocks[dir=rtl] h1,.mce-visualblocks[dir=rtl] h2,.mce-visualblocks[dir=rtl] h3,.mce-visualblocks[dir=rtl] h4,.mce-visualblocks[dir=rtl] h5,.mce-visualblocks[dir=rtl] h6,.mce-visualblocks[dir=rtl] hgroup,.mce-visualblocks[dir=rtl] ol,.mce-visualblocks[dir=rtl] p,.mce-visualblocks[dir=rtl] pre,.mce-visualblocks[dir=rtl] section,.mce-visualblocks[dir=rtl] ul{background-position-x: right;margin-right: 3px;} + +.mce-nbsp,.mce-shy{background: #aaa;} + +.mce-shy::after{content: '-';} + +body{font-family: sans-serif;} + +table{border-collapse: collapse;} diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/content.mobile.min.css b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/content.mobile.min.css new file mode 100644 index 0000000000000000000000000000000000000000..c0522520ef7473120f188dda219d918fc43c6a43 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/content.mobile.min.css @@ -0,0 +1,17 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{position: absolute;display: inline-block;background-color: green;opacity: .5;} + +body{-webkit-text-size-adjust: none;} + +body img{max-width: 96vw;} + +body table img{max-width: 95%;} + +body{font-family: sans-serif;} + +table{border-collapse: collapse;} diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/skin.min.css b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/skin.min.css new file mode 100644 index 0000000000000000000000000000000000000000..d8dc9b2dabf10d13a6b4e848b860587c1f5488d1 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/skin.min.css @@ -0,0 +1,875 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tox{font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 16px;font-style: normal;font-weight: 400;line-height: normal;color: #222f3e;text-decoration: none;text-shadow: none;text-transform: none;white-space: normal;vertical-align: initial;cursor: auto;box-sizing: content-box;-webkit-tap-highlight-color: transparent;} + +.tox :not(svg){font-family: inherit;font-size: inherit;font-style: inherit;font-weight: inherit;line-height: inherit;color: inherit;text-align: inherit;text-decoration: inherit;text-shadow: inherit;text-transform: inherit;white-space: inherit;vertical-align: inherit;cursor: inherit;box-sizing: inherit;direction: inherit;-webkit-tap-highlight-color: inherit;} + +.tox :not(svg){position: static;float: none;width: auto;height: auto;max-width: none;padding: 0;margin: 0;background: 0 0;border: 0;outline: 0;} + +.tox:not([dir=rtl]){text-align: left;direction: ltr;} + +.tox[dir=rtl]{text-align: right;direction: rtl;} + +.tox-tinymce{position: relative;display: flex;overflow: hidden;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;border: 1px solid #000;border-radius: 0;visibility: inherit !important;box-shadow: none;box-sizing: border-box;flex-direction: column;} + +.tox-editor-container{display: flex;flex: 1 1 auto;flex-direction: column;overflow: hidden;} + +.tox-editor-container>:first-child{border-top: none !important;} + +.tox-tinymce-aux{font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;} + +.tox-tinymce :focus,.tox-tinymce-aux :focus{outline: 0;} + +button::-moz-focus-inner{border: 0;} + +.tox-silver-sink{z-index: 1300;} + +.tox .tox-anchorbar{display: flex;flex: 0 0 auto;} + +.tox .tox-bar{display: flex;flex: 0 0 auto;} + +.tox .tox-button{display: inline-block;padding: 4px 16px;margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 14px;font-weight: 700;line-height: 24px;letter-spacing: 1;color: #fff;text-align: center;text-decoration: none;text-transform: capitalize;white-space: nowrap;cursor: pointer;background-color: #207ab7;background-image: none;background-position: none;background-repeat: none;border-color: #207ab7;border-style: solid;border-width: 1px;border-radius: 3px;outline: 0;box-shadow: none;box-sizing: border-box;} + +.tox .tox-button[disabled]{color: rgba(255,255,255,.5);cursor: not-allowed;background-color: #207ab7;background-image: none;border-color: #207ab7;box-shadow: none;} + +.tox .tox-button:focus:not(:disabled){color: #fff;background-color: #1c6ca1;background-image: none;border-color: #1c6ca1;box-shadow: none;} + +.tox .tox-button:hover:not(:disabled){color: #fff;background-color: #1c6ca1;background-image: none;border-color: #1c6ca1;box-shadow: none;} + +.tox .tox-button:active:not(:disabled){color: #fff;background-color: #185d8c;background-image: none;border-color: #185d8c;box-shadow: none;} + +.tox .tox-button--secondary{padding: 4px 16px;color: #fff;text-decoration: none;text-transform: capitalize;background-color: #3d546f;background-image: none;background-position: none;background-repeat: none;border-color: #3d546f;border-style: solid;border-width: 1px;border-radius: 3px;outline: 0;box-shadow: none;} + +.tox .tox-button--secondary[disabled]{color: rgba(255,255,255,.5);background-color: #3d546f;background-image: none;border-color: #3d546f;box-shadow: none;} + +.tox .tox-button--secondary:focus:not(:disabled){color: #fff;background-color: #34485f;background-image: none;border-color: #34485f;box-shadow: none;} + +.tox .tox-button--secondary:hover:not(:disabled){color: #fff;background-color: #34485f;background-image: none;border-color: #34485f;box-shadow: none;} + +.tox .tox-button--secondary:active:not(:disabled){color: #fff;background-color: #2b3b4e;background-image: none;border-color: #2b3b4e;box-shadow: none;} + +.tox .tox-button--icon,.tox .tox-button.tox-button--icon,.tox .tox-button.tox-button--secondary.tox-button--icon{padding: 4px;} + +.tox .tox-button--icon .tox-icon svg,.tox .tox-button.tox-button--icon .tox-icon svg,.tox .tox-button.tox-button--secondary.tox-button--icon .tox-icon svg{display: block;fill: currentColor;} + +.tox .tox-button-link{display: inline-block;padding: 0;margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 16px;font-weight: 400;line-height: 1.3;white-space: nowrap;cursor: pointer;background: 0;border: none;box-sizing: border-box;} + +.tox .tox-button-link--sm{font-size: 14px;} + +.tox .tox-button--naked{color: #fff;background-color: transparent;border-color: transparent;box-shadow: unset;} + +.tox .tox-button--naked:hover:not(:disabled){color: #fff;background-color: #34485f;border-color: #34485f;box-shadow: none;} + +.tox .tox-button--naked:focus:not(:disabled){color: #fff;background-color: #34485f;border-color: #34485f;box-shadow: none;} + +.tox .tox-button--naked:active:not(:disabled){color: #fff;background-color: #2b3b4e;border-color: #2b3b4e;box-shadow: none;} + +.tox .tox-button--naked .tox-icon svg{fill: currentColor;} + +.tox .tox-button--naked.tox-button--icon{color: currentColor;} + +.tox .tox-button--naked.tox-button--icon:hover:not(:disabled){color: #fff;} + +.tox .tox-checkbox{display: flex;height: 36px;min-width: 36px;cursor: pointer;border-radius: 3px;align-items: center;} + +.tox .tox-checkbox__input{position: absolute;top: auto;left: -10000px;width: 1px;height: 1px;overflow: hidden;} + +.tox .tox-checkbox__icons{width: 24px;height: 24px;padding: calc(4px - 1px);border-radius: 3px;box-shadow: 0 0 0 2px transparent;box-sizing: content-box;} + +.tox .tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display: block;fill: rgba(255,255,255,.2);} + +.tox .tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{display: none;fill: #207ab7;} + +.tox .tox-checkbox__icons .tox-checkbox-icon__checked svg{display: none;fill: #207ab7;} + +.tox input.tox-checkbox__input:checked+.tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display: none;} + +.tox input.tox-checkbox__input:checked+.tox-checkbox__icons .tox-checkbox-icon__checked svg{display: block;} + +.tox input.tox-checkbox__input:indeterminate+.tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display: none;} + +.tox input.tox-checkbox__input:indeterminate+.tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{display: block;} + +.tox input.tox-checkbox__input:focus+.tox-checkbox__icons{padding: calc(4px - 1px);border-radius: 3px;box-shadow: inset 0 0 0 1px #207ab7;} + +.tox:not([dir=rtl]) .tox-checkbox__label{margin-left: 4px;} + +.tox:not([dir=rtl]) .tox-bar .tox-checkbox{margin-left: 4px;} + +.tox[dir=rtl] .tox-checkbox__label{margin-right: 4px;} + +.tox[dir=rtl] .tox-bar .tox-checkbox{margin-right: 4px;} + +.tox .tox-collection--toolbar .tox-collection__group{display: flex;padding: 0;} + +.tox .tox-collection--grid .tox-collection__group{display: flex;max-height: 208px;padding: 0;overflow-x: hidden;overflow-y: auto;flex-wrap: wrap;} + +.tox .tox-collection--list .tox-collection__group{padding: 4px 0;border-color: #1a1a1a;border-style: solid;border-top-width: 1px;border-right-width: 0;border-bottom-width: 0;border-left-width: 0;} + +.tox .tox-collection--list .tox-collection__group:first-child{border-top-width: 0;} + +.tox .tox-collection__group-heading{padding: 4px 8px;margin-top: -4px;margin-bottom: 4px;font-size: 12px;font-style: normal;font-weight: 400;color: #fff;text-transform: none;cursor: default;background-color: #333;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;-webkit-touch-callout: none;} + +.tox .tox-collection__item{display: flex;color: #fff;cursor: pointer;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;align-items: center;-webkit-touch-callout: none;} + +.tox .tox-collection--list .tox-collection__item{padding: 4px 8px;} + +.tox .tox-collection--toolbar .tox-collection__item{padding: 4px;border-radius: 3px;} + +.tox .tox-collection--grid .tox-collection__item{padding: 4px;border-radius: 3px;} + +.tox .tox-collection--list .tox-collection__item--enabled{color: contrast(inherit,#222f3e,#fff);background-color: inherit;} + +.tox .tox-collection--list .tox-collection__item--active:not(.tox-collection__item--state-disabled){color: #fff;background-color: #434e5b;} + +.tox .tox-collection--toolbar .tox-collection__item--enabled{color: #fff;background-color: #6f7882;} + +.tox .tox-collection--toolbar .tox-collection__item--active:not(.tox-collection__item--state-disabled){color: #fff;background-color: #434e5b;} + +.tox .tox-collection--grid .tox-collection__item--enabled{color: #fff;background-color: #6f7882;} + +.tox .tox-collection--grid .tox-collection__item--active:not(.tox-collection__item--state-disabled){color: #fff;background-color: #434e5b;} + +.tox .tox-collection__item--state-disabled{color: rgba(255,255,255,.5);cursor: default;background-color: transparent;} + +.tox .tox-collection__item-icon{display: flex;width: 24px;height: 24px;align-items: center;justify-content: center;} + +.tox .tox-collection__item-icon svg{fill: currentColor;} + +.tox .tox-collection--toolbar-lg .tox-collection__item-icon{width: 48px;height: 48px;} + +.tox .tox-collection__item[role=menuitemcheckbox]:not(.tox-collection__item--enabled) .tox-collection__item-checkmark svg{display: none;} + +.tox .tox-collection__item-label{display: inline-block;font-size: 14px;font-style: normal;font-weight: 400;line-height: 24px;color: currentColor;text-transform: none;word-break: break-all;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-collection__item-accessory{display: inline-block;height: 24px;font-size: 14px;line-height: 24px;color: rgba(255,255,255,.5);text-transform: normal;} + +.tox .tox-collection__item-caret{align-items: center;display: flex;min-height: 24px;} + +.tox .tox-collection__item-caret::after{min-height: inherit;font-size: 0;content: '';} + +.tox:not([dir=rtl]) .tox-collection--list .tox-collection__item>:not(:first-child){margin-left: 8px;} + +.tox:not([dir=rtl]) .tox-collection--list .tox-collection__item-label:first-child{margin-left: 4px;} + +.tox:not([dir=rtl]) .tox-collection__item-accessory{margin-left: 16px;text-align: right;} + +.tox:not([dir=rtl]) .tox-collection__item-caret{margin-left: 16px;} + +.tox[dir=rtl] .tox-collection--list .tox-collection__item>:not(:first-child){margin-right: 8px;} + +.tox[dir=rtl] .tox-collection--list .tox-collection__item-label:first-child{margin-right: 4px;} + +.tox[dir=rtl] .tox-collection__item-icon-rtl .tox-collection__item-icon svg{transform: rotateY(180deg);} + +.tox[dir=rtl] .tox-collection__item-accessory{margin-right: 16px;text-align: left;} + +.tox[dir=rtl] .tox-collection__item-caret{margin-right: 16px;transform: rotateY(180deg);} + +.tox .tox-color-picker-container{display: flex;flex-direction: row;height: 225px;margin: 0;} + +.tox .tox-sv-palette{display: flex;height: 100%;box-sizing: border-box;} + +.tox .tox-sv-palette-spectrum{height: 100%;} + +.tox .tox-sv-palette,.tox .tox-sv-palette-spectrum{width: 225px;} + +.tox .tox-sv-palette-thumb{position: absolute;width: 12px;height: 12px;background: 0 0;border: 1px solid #000;border-radius: 50%;box-sizing: content-box;} + +.tox .tox-sv-palette-inner-thumb{position: absolute;width: 10px;height: 10px;border: 1px solid #fff;border-radius: 50%;} + +.tox .tox-hue-slider{width: 25px;height: 100%;box-sizing: border-box;} + +.tox .tox-hue-slider-spectrum{width: 100%;height: 100%;background: linear-gradient(to bottom,red,#ff0080,#f0f,#8000ff,#00f,#0080ff,#0ff,#00ff80,#0f0,#80ff00,#ff0,#ff8000,red);} + +.tox .tox-hue-slider,.tox .tox-hue-slider-spectrum{width: 20px;} + +.tox .tox-hue-slider-thumb{width: 100%;height: 4px;background: #fff;border: 1px solid #000;box-sizing: content-box;} + +.tox .tox-rgb-form{display: flex;flex-direction: column;justify-content: space-between;} + +.tox .tox-rgb-form div{display: flex;width: inherit;margin-bottom: 5px;align-items: center;justify-content: space-between;} + +.tox .tox-rgb-form input{width: 6em;} + +.tox .tox-rgb-form input.tox-invalid{border: 1px solid red !important;} + +.tox .tox-rgb-form .tox-rgba-preview{margin-bottom: 0;border: 1px solid #000;flex-grow: 2;} + +.tox:not([dir=rtl]) .tox-sv-palette{margin-right: 15px;} + +.tox:not([dir=rtl]) .tox-hue-slider{margin-right: 15px;} + +.tox:not([dir=rtl]) .tox-hue-slider-thumb{margin-left: -1px;} + +.tox:not([dir=rtl]) .tox-rgb-form label{margin-right: .5em;} + +.tox[dir=rtl] .tox-sv-palette{margin-left: 15px;} + +.tox[dir=rtl] .tox-hue-slider{margin-left: 15px;} + +.tox[dir=rtl] .tox-hue-slider-thumb{margin-right: -1px;} + +.tox[dir=rtl] .tox-rgb-form label{margin-left: .5em;} + +.tox .tox-toolbar .tox-swatches,.tox .tox-toolbar__overflow .tox-swatches,.tox .tox-toolbar__primary .tox-swatches{margin: 2px 0 3px 4px;} + +.tox .tox-collection--list .tox-collection__group .tox-swatches-menu{margin: -4px 0;border: 0;} + +.tox .tox-swatches__row{display: flex;} + +.tox .tox-swatch{width: 30px;height: 30px;transition: transform .15s,box-shadow .15s;} + +.tox .tox-swatch:focus,.tox .tox-swatch:hover{transform: scale(.8);box-shadow: 0 0 0 1px rgba(127,127,127,.3) inset;} + +.tox .tox-swatch--remove{align-items: center;display: flex;justify-content: center;} + +.tox .tox-swatch--remove svg path{stroke: #e74c3c;} + +.tox .tox-swatches__picker-btn{display: flex;width: 30px;height: 30px;padding: 0;cursor: pointer;background-color: transparent;border: 0;outline: 0;align-items: center;justify-content: center;} + +.tox .tox-swatches__picker-btn svg{width: 24px;height: 24px;} + +.tox .tox-swatches__picker-btn:hover{background: #434e5b;} + +.tox:not([dir=rtl]) .tox-swatches__picker-btn{margin-left: auto;} + +.tox[dir=rtl] .tox-swatches__picker-btn{margin-right: auto;} + +.tox .tox-comment-thread{position: relative;background: #2b3b4e;} + +.tox .tox-comment-thread>:not(:first-child){margin-top: 8px;} + +.tox .tox-comment{position: relative;padding: 8px 8px 16px 8px;background: #2b3b4e;border: 1px solid #000;border-radius: 3px;box-shadow: 0 4px 8px 0 rgba(34,47,62,.1);} + +.tox .tox-comment__header{display: flex;color: #fff;align-items: center;justify-content: space-between;} + +.tox .tox-comment__date{font-size: 12px;color: rgba(255,255,255,.5);} + +.tox .tox-comment__body{position: relative;margin-top: 8px;font-size: 14px;font-style: normal;font-weight: 400;line-height: 1.3;color: #fff;text-transform: initial;} + +.tox .tox-comment__body textarea{width: 100%;white-space: normal;resize: none;} + +.tox .tox-comment__expander{padding-top: 8px;} + +.tox .tox-comment__expander p{font-size: 14px;font-style: normal;color: rgba(255,255,255,.5);} + +.tox .tox-comment__body p{margin: 0;} + +.tox .tox-comment__buttonspacing{padding-top: 16px;text-align: center;} + +.tox .tox-comment-thread__overlay::after{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 5;display: flex;background: #2b3b4e;content: "";opacity: .9;} + +.tox .tox-comment__reply{display: flex;flex-shrink: 0;flex-wrap: wrap;justify-content: flex-end;margin-top: 8px;} + +.tox .tox-comment__reply>:first-child{width: 100%;margin-bottom: 8px;} + +.tox .tox-comment__edit{display: flex;flex-wrap: wrap;justify-content: flex-end;margin-top: 16px;} + +.tox .tox-comment__gradient::after{position: absolute;bottom: 0;display: block;width: 100%;height: 5em;margin-top: -40px;background: linear-gradient(rgba(43,59,78,0),#2b3b4e);content: "";} + +.tox .tox-comment__overlay{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 5;display: flex;text-align: center;background: #2b3b4e;opacity: .9;flex-direction: column;flex-grow: 1;} + +.tox .tox-comment__loading-text{position: relative;display: flex;color: #fff;align-items: center;flex-direction: column;} + +.tox .tox-comment__loading-text>div{padding-bottom: 16px;} + +.tox .tox-comment__overlaytext{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 10;padding: 1em;font-size: 14px;flex-direction: column;} + +.tox .tox-comment__overlaytext p{color: #fff;text-align: center;background-color: #2b3b4e;box-shadow: 0 0 8px 8px #2b3b4e;} + +.tox .tox-comment__overlaytext div:nth-of-type(2){font-size: .8em;} + +.tox .tox-comment__busy-spinner{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1103;display: flex;background-color: #2b3b4e;align-items: center;justify-content: center;} + +.tox .tox-comment__scroll{display: flex;flex-direction: column;flex-shrink: 1;overflow: auto;} + +.tox .tox-conversations{margin: 8px;} + +.tox:not([dir=rtl]) .tox-comment__edit{margin-left: 8px;} + +.tox:not([dir=rtl]) .tox-comment__buttonspacing>:last-child,.tox:not([dir=rtl]) .tox-comment__edit>:last-child,.tox:not([dir=rtl]) .tox-comment__reply>:last-child{margin-left: 8px;} + +.tox[dir=rtl] .tox-comment__edit{margin-right: 8px;} + +.tox[dir=rtl] .tox-comment__buttonspacing>:last-child,.tox[dir=rtl] .tox-comment__edit>:last-child,.tox[dir=rtl] .tox-comment__reply>:last-child{margin-right: 8px;} + +.tox .tox-user{align-items: center;display: flex;} + +.tox .tox-user__avatar svg{fill: rgba(255,255,255,.5);} + +.tox .tox-user__name{font-size: 12px;font-style: normal;font-weight: 700;color: rgba(255,255,255,.5);text-transform: uppercase;} + +.tox:not([dir=rtl]) .tox-user__avatar svg{margin-right: 8px;} + +.tox:not([dir=rtl]) .tox-user__avatar+.tox-user__name{margin-left: 8px;} + +.tox[dir=rtl] .tox-user__avatar svg{margin-left: 8px;} + +.tox[dir=rtl] .tox-user__avatar+.tox-user__name{margin-right: 8px;} + +.tox .tox-dialog-wrap{position: fixed;top: 0;right: 0;bottom: 0;left: 0;z-index: 1100;display: flex;align-items: center;justify-content: center;} + +.tox .tox-dialog-wrap__backdrop{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1101;background-color: rgba(34,47,62,.75);} + +.tox .tox-dialog{position: relative;z-index: 1102;display: flex;width: 95vw;max-width: 480px;max-height: 100%;overflow: hidden;background-color: #2b3b4e;border-color: #000;border-style: solid;border-width: 1px;border-radius: 3px;box-shadow: 0 16px 16px -10px rgba(34,47,62,.15),0 0 40px 1px rgba(34,47,62,.15);flex-direction: column;} + +.tox .tox-dialog__header{position: relative;display: flex;padding: 8px 16px 0 16px;margin-bottom: 16px;font-size: 16px;color: #fff;background-color: #2b3b4e;border-bottom: none;align-items: center;justify-content: space-between;} + +.tox .tox-dialog__header .tox-button{z-index: 1;} + +.tox .tox-dialog__draghandle{position: absolute;top: 0;left: 0;width: 100%;height: 100%;cursor: grab;} + +.tox .tox-dialog__draghandle:active{cursor: grabbing;} + +.tox .tox-dialog__dismiss{margin-left: auto;} + +.tox .tox-dialog__title{margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 20px;font-style: normal;font-weight: 400;line-height: 1.3;text-transform: normal;} + +.tox .tox-dialog__body{display: flex;min-width: 0;padding: 0 16px;font-size: 16px;font-style: normal;font-weight: 400;line-height: 1.3;color: #fff;text-align: left;text-transform: normal;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-nav{align-items: flex-start;display: flex;flex-direction: column;} + +.tox .tox-dialog__body-nav-item{display: inline-block;margin-bottom: 8px;font-size: 14px;line-height: 1.3;color: rgba(255,255,255,.5);text-decoration: none;border-bottom: 2px solid transparent;} + +.tox .tox-dialog__body-nav-item--active{color: #207ab7;border-bottom: 2px solid #207ab7;} + +.tox .tox-dialog__body-content{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;max-height: 650px;overflow: auto;} + +.tox .tox-dialog__body-content>*{margin-top: 16px;margin-bottom: 0;} + +.tox .tox-dialog__body-content>:first-child{margin-top: 0;} + +.tox .tox-dialog__body-content>:last-child{margin-bottom: 0;} + +.tox .tox-dialog__body-content>:only-child{margin-top: 0;margin-bottom: 0;} + +.tox .tox-dialog--width-lg{height: 650px;max-width: 1200px;} + +.tox .tox-dialog--width-md{max-width: 800px;} + +.tox .tox-dialog--width-md .tox-dialog__body-content{overflow: auto;} + +.tox .tox-dialog__body-content--centered{text-align: center;} + +.tox .tox-dialog__body-content--spacious{margin-bottom: 16px;} + +.tox .tox-dialog__footer{display: flex;padding: 8px 16px;margin-top: 16px;background-color: #2b3b4e;border-top: 1px solid #000;align-items: center;justify-content: space-between;} + +.tox .tox-dialog__busy-spinner{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1103;display: flex;background-color: rgba(34,47,62,.75);align-items: center;justify-content: center;} + +.tox .tox-dialog__table{width: 100%;border-collapse: collapse;} + +.tox .tox-dialog__table thead th{padding-bottom: 8px;font-weight: 700;} + +.tox .tox-dialog__table tbody tr{border-bottom: 1px solid #000;} + +.tox .tox-dialog__table tbody tr:last-child{border-bottom: none;} + +.tox .tox-dialog__table td{padding-top: 8px;padding-bottom: 8px;} + +.tox .tox-dialog__popups{position: absolute;z-index: 1100;width: 100%;} + +.tox .tox-dialog__body-iframe{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-iframe .tox-navobj{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-iframe .tox-navobj :nth-child(2){flex: 1;-ms-flex-preferred-size: auto;height: 100%;} + +body.tox-dialog__disable-scroll{overflow: hidden;} + +.tox.tox-platform-ie .tox-dialog-wrap{position: -ms-device-fixed;} + +.tox:not([dir=rtl]) .tox-dialog__body-nav{margin-right: 32px;} + +.tox:not([dir=rtl]) .tox-dialog__footer .tox-dialog__footer-end>*,.tox:not([dir=rtl]) .tox-dialog__footer .tox-dialog__footer-start>*{margin-left: 8px;} + +.tox[dir=rtl] .tox-dialog__body{text-align: right;} + +.tox[dir=rtl] .tox-dialog__body-nav{margin-left: 32px;} + +.tox[dir=rtl] .tox-dialog__footer .tox-dialog__footer-end>*,.tox[dir=rtl] .tox-dialog__footer .tox-dialog__footer-start>*{margin-right: 8px;} + +.tox .tox-dropzone-container{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dropzone{display: flex;min-height: 100px;padding: 10px;background: #fff;border: 2px dashed #000;box-sizing: border-box;align-items: center;flex-direction: column;flex-grow: 1;justify-content: center;} + +.tox .tox-dropzone p{margin: 0 0 16px 0;color: rgba(255,255,255,.5);} + +.tox .tox-edit-area{position: relative;display: flex;overflow: hidden;border-top: 1px solid #000;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-edit-area__iframe{position: absolute;width: 100%;height: 100%;background-color: #fff;border: 0;box-sizing: border-box;flex: 1;-ms-flex-preferred-size: auto;} + +.tox.tox-inline-edit-area{border: 1px dotted #000;} + +.tox .tox-control-wrap{flex: 1;position: relative;} + +.tox .tox-control-wrap:not(.tox-control-wrap--status-invalid) .tox-control-wrap__status-icon-invalid,.tox .tox-control-wrap:not(.tox-control-wrap--status-unknown) .tox-control-wrap__status-icon-unknown,.tox .tox-control-wrap:not(.tox-control-wrap--status-valid) .tox-control-wrap__status-icon-valid{display: none;} + +.tox .tox-control-wrap svg{display: block;} + +.tox .tox-control-wrap__status-icon-wrap{position: absolute;top: 50%;transform: translateY(-50%);} + +.tox .tox-control-wrap__status-icon-invalid svg{fill: #c00;} + +.tox .tox-control-wrap__status-icon-unknown svg{fill: orange;} + +.tox .tox-control-wrap__status-icon-valid svg{fill: green;} + +.tox:not([dir=rtl]) .tox-control-wrap--status-invalid .tox-textfield,.tox:not([dir=rtl]) .tox-control-wrap--status-unknown .tox-textfield,.tox:not([dir=rtl]) .tox-control-wrap--status-valid .tox-textfield{padding-right: 32px;} + +.tox:not([dir=rtl]) .tox-control-wrap__status-icon-wrap{right: 4px;} + +.tox[dir=rtl] .tox-control-wrap--status-invalid .tox-textfield,.tox[dir=rtl] .tox-control-wrap--status-unknown .tox-textfield,.tox[dir=rtl] .tox-control-wrap--status-valid .tox-textfield{padding-left: 32px;} + +.tox[dir=rtl] .tox-control-wrap__status-icon-wrap{left: 4px;} + +.tox .tox-autocompleter{max-width: 25em;} + +.tox .tox-autocompleter .tox-menu{max-width: 25em;} + +.tox .tox-color-input{display: flex;} + +.tox .tox-color-input .tox-textfield{display: flex;border-radius: 3px 0 0 3px;} + +.tox .tox-color-input span{display: flex;width: 35px;cursor: pointer;border-color: rgba(34,47,62,.2);border-style: solid;border-width: 1px 1px 1px 0;border-radius: 0 3px 3px 0;box-shadow: none;box-sizing: border-box;} + +.tox .tox-color-input span:focus{border-color: #207ab7;} + +.tox[dir=rtl] .tox-color-input .tox-textfield{border-radius: 0 3px 3px 0;} + +.tox[dir=rtl] .tox-color-input span{border-width: 1px 0 1px 1px;border-radius: 3px 0 0 3px;} + +.tox .tox-label,.tox .tox-toolbar-label{display: block;padding: 0 8px 0 0;font-size: 14px;font-style: normal;font-weight: 400;line-height: 1.3;color: rgba(255,255,255,.5);text-transform: normal;white-space: nowrap;} + +.tox .tox-toolbar-label{padding: 0 8px;} + +.tox[dir=rtl] .tox-label{padding: 0 0 0 8px;} + +.tox .tox-form{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group{margin-bottom: 4px;box-sizing: border-box;} + +.tox .tox-form__group--error{color: #c00;} + +.tox .tox-form__group--collection{display: flex;} + +.tox .tox-form__grid{display: flex;flex-direction: row;flex-wrap: wrap;justify-content: space-between;} + +.tox .tox-form__grid--2col>.tox-form__group{width: calc(50% - (8px / 2));} + +.tox .tox-form__grid--3col>.tox-form__group{width: calc(100% / 3 - (8px / 2));} + +.tox .tox-form__grid--4col>.tox-form__group{width: calc(25% - (8px / 2));} + +.tox .tox-form__controls-h-stack{align-items: center;display: flex;} + +.tox .tox-form__group--inline{align-items: center;display: flex;} + +.tox .tox-form__group--stretched{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group--stretched .tox-textarea{flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group--stretched .tox-navobj{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group--stretched .tox-navobj :nth-child(2){flex: 1;-ms-flex-preferred-size: auto;height: 100%;} + +.tox:not([dir=rtl]) .tox-form__controls-h-stack>:not(:first-child){margin-left: 4px;} + +.tox[dir=rtl] .tox-form__controls-h-stack>:not(:first-child){margin-right: 4px;} + +.tox .tox-lock.tox-locked .tox-lock-icon__unlock,.tox .tox-lock:not(.tox-locked) .tox-lock-icon__lock{display: none;} + +.tox .tox-textarea,.tox .tox-textfield,.tox .tox-toolbar-textfield,.tox:not([dir=rtl]) .tox-selectfield select,.tox[dir=rtl] .tox-selectfield select{width: 100%;padding: 5px 4.75px;margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 16px;line-height: 24px;color: #fff;background-color: #2b3b4e;border-color: #000;border-style: solid;border-width: 1px;border-radius: 3px;outline: 0;box-shadow: none;box-sizing: border-box;resize: none;-webkit-appearance: none;-moz-appearance: none;appearance: none;} + +.tox .tox-selectfield select:focus,.tox .tox-textarea:focus,.tox .tox-textfield:focus{border-color: #207ab7;outline: 0;box-shadow: none;} + +.tox .tox-toolbar-textfield{max-width: 250px;margin-top: 2px;margin-bottom: 3px;border-width: 0;} + +.tox .tox-naked-btn{display: block;padding: 0;margin: 0;color: #207ab7;cursor: pointer;background-color: transparent;border: 0;border-color: transparent;box-shadow: unset;} + +.tox .tox-naked-btn svg{display: block;fill: #fff;} + +.tox:not([dir=rtl]) .tox-toolbar-textfield+*{margin-left: 4px;} + +.tox[dir=rtl] .tox-toolbar-textfield+*{margin-right: 4px;} + +.tox .tox-selectfield{position: relative;cursor: pointer;} + +.tox .tox-selectfield select::-ms-expand{display: none;} + +.tox .tox-selectfield svg{position: absolute;top: 50%;pointer-events: none;transform: translateY(-50%);} + +.tox:not([dir=rtl]) .tox-selectfield select{padding-right: 24px;} + +.tox:not([dir=rtl]) .tox-selectfield svg{right: 8px;} + +.tox[dir=rtl] .tox-selectfield select{padding-left: 24px;} + +.tox[dir=rtl] .tox-selectfield svg{left: 8px;} + +.tox .tox-textarea{white-space: pre-wrap;-webkit-appearance: textarea;-moz-appearance: textarea;appearance: textarea;} + +.tox-fullscreen{position: fixed;top: 0;left: 0;width: 100%;height: 100%;padding: 0;margin: 0;overflow: hidden;border: 0;} + +.tox-fullscreen .tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display: none;} + +.tox-fullscreen .tox.tox-tinymce.tox-fullscreen{z-index: 1200;} + +.tox-fullscreen .tox.tox-tinymce-aux{z-index: 1201;} + +.tox .tox-image-tools{width: 100%;} + +.tox .tox-image-tools__toolbar{align-items: center;display: flex;justify-content: center;} + +.tox .tox-image-tools__image{position: relative;width: 100%;height: 380px;overflow: auto;background-color: #666;} + +.tox .tox-image-tools__image,.tox .tox-image-tools__image+.tox-image-tools__toolbar{margin-top: 8px;} + +.tox .tox-image-tools__image-bg{background: url(data:image/gif;base64,R0lGODdhDAAMAIABAMzMzP///ywAAAAADAAMAAACFoQfqYeabNyDMkBQb81Uat85nxguUAEAOw==);} + +.tox .tox-image-tools__toolbar>.tox-spacer{flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-croprect-block{position: absolute;background: #000;opacity: .5;zoom: 1;} + +.tox .tox-croprect-handle{position: absolute;top: 0;left: 0;width: 20px;height: 20px;border: 2px solid #fff;} + +.tox .tox-croprect-handle-move{position: absolute;cursor: move;border: 0;} + +.tox .tox-croprect-handle-nw{top: 100px;left: 100px;margin: -2px 0 0 -2px;cursor: nw-resize;border-width: 2px 0 0 2px;} + +.tox .tox-croprect-handle-ne{top: 100px;left: 200px;margin: -2px 0 0 -20px;cursor: ne-resize;border-width: 2px 2px 0 0;} + +.tox .tox-croprect-handle-sw{top: 200px;left: 100px;margin: -20px 2px 0 -2px;cursor: sw-resize;border-width: 0 0 2px 2px;} + +.tox .tox-croprect-handle-se{top: 200px;left: 200px;margin: -20px 0 0 -20px;cursor: se-resize;border-width: 0 2px 2px 0;} + +.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-slider:not(:first-of-type){margin-left: 8px;} + +.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-button+.tox-slider{margin-left: 32px;} + +.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-slider+.tox-button{margin-left: 32px;} + +.tox[dir=rtl] .tox-image-tools__toolbar>.tox-slider:not(:first-of-type){margin-right: 8px;} + +.tox[dir=rtl] .tox-image-tools__toolbar>.tox-button+.tox-slider{margin-right: 32px;} + +.tox[dir=rtl] .tox-image-tools__toolbar>.tox-slider+.tox-button{margin-right: 32px;} + +.tox .tox-insert-table-picker{display: flex;flex-wrap: wrap;width: 169px;} + +.tox .tox-insert-table-picker>div{width: 16px;height: 16px;border-color: #070a0d;border-style: solid;border-width: 0 1px 1px 0;box-sizing: content-box;} + +.tox .tox-collection--list .tox-collection__group .tox-insert-table-picker{margin: -4px 0;} + +.tox .tox-insert-table-picker .tox-insert-table-picker__selected{background-color: rgba(32,122,183,.5);border-color: rgba(32,122,183,.5);} + +.tox .tox-insert-table-picker__label{display: block;width: 100%;padding: 4px;font-size: 14px;color: #fff;text-align: center;} + +.tox:not([dir=rtl]) .tox-insert-table-picker>div:nth-child(10n){border-right: 0;} + +.tox[dir=rtl] .tox-insert-table-picker>div:nth-child(10n+1){border-right: 0;} + +.tox .tox-menu{z-index: 1;display: inline-block;overflow: hidden;vertical-align: top;background-color: #2b3b4e;border: 1px solid #000;border-radius: 3px;box-shadow: 0 4px 8px 0 rgba(34,47,62,.1);} + +.tox .tox-menu.tox-collection.tox-collection--list{padding: 0;} + +.tox .tox-menu.tox-collection.tox-collection--toolbar{padding: 4px;} + +.tox .tox-menu.tox-collection.tox-collection--grid{padding: 4px;} + +.tox .tox-menu__label blockquote,.tox .tox-menu__label code,.tox .tox-menu__label h1,.tox .tox-menu__label h2,.tox .tox-menu__label h3,.tox .tox-menu__label h4,.tox .tox-menu__label h5,.tox .tox-menu__label h6,.tox .tox-menu__label p{margin: 0;} + +.tox .tox-menubar{display: flex;padding: 0 4px;margin-bottom: -1px;background: url("data:image/svg+xml;charset=utf8,%3Csvg height='43px' viewBox='0 0 40 43px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='42px' width='100' height='1' fill='%23000000'/%3E%3C/svg%3E") left 0 top 0 #222f3e;background-color: #222f3e;flex: 0 0 auto;flex-shrink: 0;flex-wrap: wrap;} + +.tox .tox-mbtn{display: flex;width: auto;height: 34px;padding: 0 4px;margin: 2px 0 3px 0;overflow: hidden;font-size: 14px;font-style: normal;font-weight: 400;color: #fff;text-transform: normal;background: 0 0;border: 0;border-radius: 3px;outline: 0;box-shadow: none;align-items: center;flex: 0 0 auto;justify-content: center;} + +.tox .tox-mbtn[disabled]{color: rgba(255,255,255,.5);cursor: not-allowed;background-color: none;border-color: none;box-shadow: none;} + +.tox .tox-mbtn:hover:not(:disabled){color: #fff;background: #434e5b;box-shadow: none;} + +.tox .tox-mbtn:focus:not(:disabled){color: #fff;background: #434e5b;box-shadow: none;} + +.tox .tox-mbtn--active{color: #fff;background: #6f7882;box-shadow: none;} + +.tox .tox-mbtn__select-label{margin: 0 4px;font-weight: 400;cursor: default;} + +.tox .tox-mbtn[disabled] .tox-mbtn__select-label{cursor: not-allowed;} + +.tox .tox-mbtn__select-chevron{display: flex;display: none;width: 16px;align-items: center;justify-content: center;} + +.tox .tox-notification{display: grid;padding: 5px;margin-top: 5px;background-color: #fffaea;border-color: #ffe89d;border-style: solid;border-width: 1px;opacity: 0;box-sizing: border-box;transition: transform .1s ease-in,opacity 150ms ease-in;grid-template-columns: minmax(40px,1fr) auto minmax(40px,1fr);} + +.tox .tox-notification--in{opacity: 1;} + +.tox .tox-notification--success{background-color: #dff0d8;border-color: #d6e9c6;} + +.tox .tox-notification--error{background-color: #f2dede;border-color: #ebccd1;} + +.tox .tox-notification--warn{background-color: #fcf8e3;border-color: #faebcc;} + +.tox .tox-notification--info{background-color: #d9edf7;border-color: #779ecb;} + +.tox .tox-notification__body{font-size: 14px;color: #fff;text-align: center;word-break: break-all;word-break: break-word;white-space: normal;align-self: center;grid-column-end: 3;-ms-grid-column-span: 1;grid-column-start: 2;grid-row-end: 2;grid-row-start: 1;} + +.tox .tox-notification__body>*{margin: 0;} + +.tox .tox-notification__body>*+*{margin-top: 1rem;} + +.tox .tox-notification__icon{align-self: center;-ms-grid-column-align: end;grid-column-end: 2;-ms-grid-column-span: 1;grid-column-start: 1;grid-row-end: 2;grid-row-start: 1;justify-self: end;} + +.tox .tox-notification__icon svg{display: block;} + +.tox .tox-notification__dismiss{align-self: start;-ms-grid-column-align: end;grid-column-end: 4;-ms-grid-column-span: 1;grid-column-start: 3;grid-row-end: 2;grid-row-start: 1;justify-self: end;} + +.tox .tox-notification .tox-progress-bar{-ms-grid-column-align: center;grid-column-end: 4;-ms-grid-column-span: 3;grid-column-start: 1;grid-row-end: 3;-ms-grid-row-span: 1;grid-row-start: 2;justify-self: center;} + +.tox .tox-pop{position: relative;display: inline-block;} + +.tox .tox-pop--resizing{transition: width .1s ease;} + +.tox .tox-pop--resizing .tox-toolbar{flex-wrap: nowrap;} + +.tox .tox-pop__dialog{min-width: 0;overflow: hidden;background-color: #222f3e;border: 1px solid #000;border-radius: 3px;box-shadow: 0 1px 3px rgba(0,0,0,.15);} + +.tox .tox-pop__dialog>:not(.tox-toolbar){margin: 4px 4px 4px 8px;} + +.tox .tox-pop__dialog .tox-toolbar{background-color: transparent;} + +.tox .tox-pop::after,.tox .tox-pop::before{position: absolute;display: block;width: 0;height: 0;border-style: solid;content: '';} + +.tox .tox-pop.tox-pop--bottom::after,.tox .tox-pop.tox-pop--bottom::before{top: 100%;left: 50%;} + +.tox .tox-pop.tox-pop--bottom::after{margin-top: -1px;margin-left: -8px;border-color: #222f3e transparent transparent transparent;border-width: 8px;} + +.tox .tox-pop.tox-pop--bottom::before{margin-left: -9px;border-color: #000 transparent transparent transparent;border-width: 9px;} + +.tox .tox-pop.tox-pop--top::after,.tox .tox-pop.tox-pop--top::before{top: 0;left: 50%;transform: translateY(-100%);} + +.tox .tox-pop.tox-pop--top::after{margin-top: 1px;margin-left: -8px;border-color: transparent transparent #222f3e transparent;border-width: 8px;} + +.tox .tox-pop.tox-pop--top::before{margin-left: -9px;border-color: transparent transparent #000 transparent;border-width: 9px;} + +.tox .tox-pop.tox-pop--left::after,.tox .tox-pop.tox-pop--left::before{top: calc(50% - 1px);left: 0;transform: translateY(-50%);} + +.tox .tox-pop.tox-pop--left::after{margin-left: -15px;border-color: transparent #222f3e transparent transparent;border-width: 8px;} + +.tox .tox-pop.tox-pop--left::before{margin-left: -19px;border-color: transparent #000 transparent transparent;border-width: 10px;} + +.tox .tox-pop.tox-pop--right::after,.tox .tox-pop.tox-pop--right::before{top: calc(50% + 1px);left: 100%;transform: translateY(-50%);} + +.tox .tox-pop.tox-pop--right::after{margin-left: -1px;border-color: transparent transparent transparent #222f3e;border-width: 8px;} + +.tox .tox-pop.tox-pop--right::before{margin-left: -1px;border-color: transparent transparent transparent #000;border-width: 10px;} + +.tox .tox-pop.tox-pop--align-left::after,.tox .tox-pop.tox-pop--align-left::before{left: 20px;} + +.tox .tox-pop.tox-pop--align-right::after,.tox .tox-pop.tox-pop--align-right::before{left: calc(100% - 20px);} + +.tox .tox-sidebar-wrap{display: flex;flex-direction: row;flex-grow: 1;min-height: 0;} + +.tox .tox-sidebar{display: flex;flex-direction: row;justify-content: flex-end;} + +.tox .tox-sidebar__slider{display: flex;overflow: hidden;} + +.tox .tox-sidebar__pane-container{display: flex;} + +.tox .tox-sidebar__pane{display: flex;} + +.tox .tox-sidebar--sliding-closed{opacity: 0;} + +.tox .tox-sidebar--sliding-open{opacity: 1;} + +.tox .tox-sidebar--sliding-growing,.tox .tox-sidebar--sliding-shrinking{transition: width .5s ease,opacity .5s ease;} + +.tox .tox-slider{position: relative;display: flex;height: 24px;align-items: center;flex: 1;-ms-flex-preferred-size: auto;justify-content: center;} + +.tox .tox-slider__rail{width: 100%;height: 10px;min-width: 120px;background-color: transparent;border: 1px solid #000;border-radius: 3px;} + +.tox .tox-slider__handle{position: absolute;top: 50%;left: 50%;width: 14px;height: 24px;background-color: #207ab7;border: 2px solid #185d8c;border-radius: 3px;transform: translateX(-50%) translateY(-50%);box-shadow: none;} + +.tox .tox-source-code{overflow: auto;} + +.tox .tox-spinner{display: flex;} + +.tox .tox-spinner>div{width: 8px;height: 8px;background-color: rgba(255,255,255,.5);border-radius: 100%;animation: tam-bouncing-dots 1.5s ease-in-out 0s infinite both;} + +.tox .tox-spinner>div:nth-child(1){animation-delay: -.32s;} + +.tox .tox-spinner>div:nth-child(2){animation-delay: -.16s;}@keyframes tam-bouncing-dots{0%,100%,80%{transform: scale(0);} + +40%{transform: scale(1);}} + +.tox:not([dir=rtl]) .tox-spinner>div:not(:first-child){margin-left: 4px;} + +.tox[dir=rtl] .tox-spinner>div:not(:first-child){margin-right: 4px;} + +.tox .tox-statusbar{position: relative;display: flex;height: 18px;padding: 0 8px;overflow: hidden;font-size: 12px;color: rgba(255,255,255,.5);text-transform: uppercase;background-color: #222f3e;border-top: 1px solid #000;align-items: center;flex: 0 0 auto;} + +.tox .tox-statusbar a{color: rgba(255,255,255,.5);text-decoration: none;} + +.tox .tox-statusbar a:hover{text-decoration: underline;} + +.tox .tox-statusbar__text-container{display: flex;flex: 1 1 auto;justify-content: flex-end;overflow: hidden;} + +.tox .tox-statusbar__path{display: flex;flex: 1 1 auto;margin-right: auto;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;} + +.tox .tox-statusbar__path>*{display: inline;white-space: nowrap;} + +.tox .tox-statusbar__wordcount{flex: 0 0 auto;margin-left: 1ch;} + +.tox .tox-statusbar__resize-handle{display: flex;padding-left: 1ch;margin-right: -8px;margin-left: auto;cursor: nwse-resize;align-items: flex-end;align-self: stretch;flex: 0 0 auto;justify-content: flex-end;} + +.tox .tox-statusbar__resize-handle svg{display: block;fill: rgba(255,255,255,.5);} + +.tox:not([dir=rtl]) .tox-statusbar__path>*{margin-right: 4px;} + +.tox:not([dir=rtl]) .tox-statusbar__branding{margin-left: 1ch;} + +.tox[dir=rtl] .tox-statusbar{flex-direction: row-reverse;} + +.tox[dir=rtl] .tox-statusbar__path>*{margin-left: 4px;} + +.tox .tox-throbber{z-index: 1400;} + +.tox .tox-throbber__busy-spinner{position: absolute;top: 0;right: 0;bottom: 0;left: 0;display: flex;background-color: rgba(34,47,62,.6);align-items: center;justify-content: center;} + +.tox .tox-tbtn{display: flex;width: 34px;height: 34px;padding: 0;margin: 2px 0 3px 0;overflow: hidden;font-size: 14px;font-style: normal;font-weight: 400;color: #fff;text-transform: normal;background: 0 0;border: 0;border-radius: 3px;outline: 0;box-shadow: none;align-items: center;flex: 0 0 auto;justify-content: center;} + +.tox .tox-tbtn svg{display: block;fill: #fff;} + +.tox .tox-tbtn.tox-tbtn-more{width: inherit;padding-right: 5px;padding-left: 5px;} + +.tox .tox-tbtn--enabled{color: #fff;background: #6f7882;box-shadow: none;} + +.tox .tox-tbtn--enabled>*{transform: none;} + +.tox .tox-tbtn--enabled svg{fill: #fff;} + +.tox .tox-tbtn:hover{color: #fff;background: #434e5b;box-shadow: none;} + +.tox .tox-tbtn:hover svg{fill: #fff;} + +.tox .tox-tbtn:focus{color: #fff;background: #434e5b;box-shadow: none;} + +.tox .tox-tbtn:focus svg{fill: #fff;} + +.tox .tox-tbtn:active{color: #fff;background: #6f7882;box-shadow: none;} + +.tox .tox-tbtn:active svg{fill: #fff;} + +.tox .tox-tbtn--disabled,.tox .tox-tbtn--disabled:hover,.tox .tox-tbtn:disabled,.tox .tox-tbtn:disabled:hover{color: rgba(255,255,255,.5);cursor: not-allowed;background: 0 0;box-shadow: none;} + +.tox .tox-tbtn--disabled svg,.tox .tox-tbtn--disabled:hover svg,.tox .tox-tbtn:disabled svg,.tox .tox-tbtn:disabled:hover svg{fill: rgba(255,255,255,.5);} + +.tox .tox-tbtn:active>*{transform: none;} + +.tox .tox-tbtn--md{width: 51px;height: 51px;} + +.tox .tox-tbtn--lg{width: 68px;height: 68px;flex-direction: column;} + +.tox .tox-tbtn--return{width: 16px;height: unset;align-self: stretch;} + +.tox .tox-tbtn--labeled{width: unset;padding: 0 4px;} + +.tox .tox-tbtn__vlabel{display: block;margin-bottom: 4px;font-size: 10px;font-weight: 400;letter-spacing: -.025em;white-space: nowrap;} + +.tox .tox-tbtn--select{width: auto;padding: 0 4px;margin: 2px 0 3px 0;} + +.tox .tox-tbtn__select-label{margin: 0 4px;font-weight: 400;cursor: default;} + +.tox .tox-tbtn__select-chevron{align-items: center;display: flex;justify-content: center;width: 16px;} + +.tox .tox-tbtn__select-chevron svg{fill: rgba(255,255,255,.5);} + +.tox .tox-tbtn--bespoke .tox-tbtn__select-label{width: 7em;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;} + +.tox .tox-split-button{display: flex;margin: 2px 0 3px 0;overflow: hidden;border: 0;border-radius: 3px;box-sizing: border-box;} + +.tox .tox-split-button:hover{box-shadow: 0 0 0 1px #434e5b inset;} + +.tox .tox-split-button:focus{color: #fff;background: #434e5b;box-shadow: none;} + +.tox .tox-split-button>*{border-radius: 0;} + +.tox .tox-split-button__chevron{width: 16px;} + +.tox .tox-split-button__chevron svg{fill: rgba(255,255,255,.5);} + +.tox .tox-pop .tox-split-button__chevron svg{transform: rotate(-90deg);} + +.tox .tox-split-button .tox-tbtn{margin: 0;} + +.tox .tox-split-button.tox-tbtn--disabled .tox-tbtn:focus,.tox .tox-split-button.tox-tbtn--disabled .tox-tbtn:hover,.tox .tox-split-button.tox-tbtn--disabled:focus,.tox .tox-split-button.tox-tbtn--disabled:hover{color: rgba(255,255,255,.5);background: 0 0;box-shadow: none;} + +.tox .tox-toolbar,.tox .tox-toolbar__overflow,.tox .tox-toolbar__primary{display: flex;padding: 0 0;margin-bottom: -1px;background: url("data:image/svg+xml;charset=utf8,%3Csvg height='39px' viewBox='0 0 40 39px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='38px' width='100' height='1' fill='%23000000'/%3E%3C/svg%3E") left 0 top 0 #222f3e;background-color: #222f3e;border-top: 1px solid #000;flex: 0 0 auto;flex-shrink: 0;flex-wrap: wrap;} + +.tox .tox-toolbar__overflow.tox-toolbar__overflow--closed{height: 0;opacity: 0;visibility: hidden;} + +.tox .tox-toolbar__overflow--growing{transition: height .3s ease,opacity .2s linear .1s;} + +.tox .tox-toolbar__overflow--shrinking{transition: opacity .3s ease,height .2s linear .1s,visibility 0s linear .3s;} + +.tox .tox-pop .tox-toolbar{border-width: 0;} + +.tox .tox-toolbar--no-divider{background-image: none;} + +.tox.tox-tinymce-aux .tox-toolbar__overflow{background-color: #222f3e;border: 1px solid #000;border-radius: 3px;box-shadow: 0 1px 3px rgba(0,0,0,.15);} + +.tox.tox-tinymce-aux:not([dir=rtl]) .tox-toolbar__overflow{margin-left: 4px;} + +.tox[dir=rtl] .tox-tbtn__icon-rtl svg{transform: rotateY(180deg);} + +.tox[dir=rtl].tox-tinymce-aux .tox-toolbar__overflow{margin-right: 4px;} + +.tox .tox-toolbar__group{display: flex;padding: 0 4px;margin: 0 0;align-items: center;flex-wrap: wrap;} + +.tox .tox-toolbar__group--pull-right{margin-left: auto;} + +.tox:not([dir=rtl]) .tox-toolbar__group:not(:last-of-type){border-right: 1px solid #000;} + +.tox[dir=rtl] .tox-toolbar__group:not(:last-of-type){border-left: 1px solid #000;} + +.tox .tox-tooltip{position: relative;display: inline-block;padding: 8px;} + +.tox .tox-tooltip__body{padding: 4px 8px;font-size: 14px;font-style: normal;font-weight: 400;color: rgba(255,255,255,.75);text-transform: normal;background-color: #3d546f;border-radius: 3px;box-shadow: 0 2px 4px rgba(34,47,62,.3);} + +.tox .tox-tooltip__arrow{position: absolute;} + +.tox .tox-tooltip--down .tox-tooltip__arrow{position: absolute;bottom: 0;left: 50%;border-top: 8px solid #3d546f;border-right: 8px solid transparent;border-left: 8px solid transparent;transform: translateX(-50%);} + +.tox .tox-tooltip--up .tox-tooltip__arrow{position: absolute;top: 0;left: 50%;border-right: 8px solid transparent;border-bottom: 8px solid #3d546f;border-left: 8px solid transparent;transform: translateX(-50%);} + +.tox .tox-tooltip--right .tox-tooltip__arrow{position: absolute;top: 50%;right: 0;border-top: 8px solid transparent;border-bottom: 8px solid transparent;border-left: 8px solid #3d546f;transform: translateY(-50%);} + +.tox .tox-tooltip--left .tox-tooltip__arrow{position: absolute;top: 50%;left: 0;border-top: 8px solid transparent;border-right: 8px solid #3d546f;border-bottom: 8px solid transparent;transform: translateY(-50%);} + +.tox .tox-well{width: 100%;padding: 8px;border: 1px solid #000;border-radius: 3px;} + +.tox .tox-well>:first-child{margin-top: 0;} + +.tox .tox-well>:last-child{margin-bottom: 0;} + +.tox .tox-well>:only-child{margin: 0;} + +.tox .tox-custom-editor{display: flex;height: 525px;border: 1px solid #000;border-radius: 3px;} + +.tox .tox-dialog-loading::before{position: absolute;z-index: 1000;width: 100%;height: 100%;background-color: rgba(0,0,0,.5);content: "";} + +.tox .tox-tab{cursor: pointer;} + +.tox .tox-dialog__content-js{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-content .tox-collection{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox ul{display: block;list-style-type: disc;-webkit-margin-before: 1em;margin-block-start: 1em;-webkit-margin-after: 1em;margin-block-end: 1em;-webkit-margin-start: 0;margin-inline-start: 0;-webkit-margin-end: 0;margin-inline-end: 0;-webkit-padding-start: 40px;padding-inline-start: 40px;} + +.tox a{color: #2276d2;cursor: pointer;} + +.tox .tox-image-tools-edit-panel{height: 60px;} + +.tox .tox-image-tools__sidebar{height: 60px;} diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/skin.mobile.min.css b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/skin.mobile.min.css new file mode 100644 index 0000000000000000000000000000000000000000..14847d0a2d319e16205b0258b43c0271b5a9d220 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide-dark/skin.mobile.min.css @@ -0,0 +1,239 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tinymce-mobile-outer-container{all: initial;display: block;} + +.tinymce-mobile-outer-container *{float: none;padding: 0;margin: 0;line-height: 1;text-shadow: none;white-space: nowrap;cursor: inherit;border: 0;outline: 0;box-sizing: initial;-webkit-tap-highlight-color: transparent;} + +.tinymce-mobile-icon-arrow-back::before{content: "\e5cd";} + +.tinymce-mobile-icon-image::before{content: "\e412";} + +.tinymce-mobile-icon-cancel-circle::before{content: "\e5c9";} + +.tinymce-mobile-icon-full-dot::before{content: "\e061";} + +.tinymce-mobile-icon-align-center::before{content: "\e234";} + +.tinymce-mobile-icon-align-left::before{content: "\e236";} + +.tinymce-mobile-icon-align-right::before{content: "\e237";} + +.tinymce-mobile-icon-bold::before{content: "\e238";} + +.tinymce-mobile-icon-italic::before{content: "\e23f";} + +.tinymce-mobile-icon-unordered-list::before{content: "\e241";} + +.tinymce-mobile-icon-ordered-list::before{content: "\e242";} + +.tinymce-mobile-icon-font-size::before{content: "\e245";} + +.tinymce-mobile-icon-underline::before{content: "\e249";} + +.tinymce-mobile-icon-link::before{content: "\e157";} + +.tinymce-mobile-icon-unlink::before{content: "\eca2";} + +.tinymce-mobile-icon-color::before{content: "\e891";} + +.tinymce-mobile-icon-previous::before{content: "\e314";} + +.tinymce-mobile-icon-next::before{content: "\e315";} + +.tinymce-mobile-icon-large-font::before,.tinymce-mobile-icon-style-formats::before{content: "\e264";} + +.tinymce-mobile-icon-undo::before{content: "\e166";} + +.tinymce-mobile-icon-redo::before{content: "\e15a";} + +.tinymce-mobile-icon-removeformat::before{content: "\e239";} + +.tinymce-mobile-icon-small-font::before{content: "\e906";} + +.tinymce-mobile-format-matches::after,.tinymce-mobile-icon-readonly-back::before{content: "\e5ca";} + +.tinymce-mobile-icon-small-heading::before{content: "small";} + +.tinymce-mobile-icon-large-heading::before{content: "large";} + +.tinymce-mobile-icon-large-heading::before,.tinymce-mobile-icon-small-heading::before{font-family: sans-serif;font-size: 80%;} + +.tinymce-mobile-mask-edit-icon::before{content: "\e254";} + +.tinymce-mobile-icon-back::before{content: "\e5c4";} + +.tinymce-mobile-icon-heading::before{font-family: sans-serif;font-size: 80%;font-weight: 700;content: "Headings";} + +.tinymce-mobile-icon-h1::before{font-weight: 700;content: "H1";} + +.tinymce-mobile-icon-h2::before{font-weight: 700;content: "H2";} + +.tinymce-mobile-icon-h3::before{font-weight: 700;content: "H3";} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask{position: absolute;top: 0;display: flex;width: 100%;height: 100%;background: rgba(51,51,51,.5);align-items: center;justify-content: center;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container{display: flex;font-family: sans-serif;font-size: 1em;border-radius: 50%;align-items: center;flex-direction: column;justify-content: space-between;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .mixin-menu-item{display: flex;width: 2.1em;height: 2.1em;border-radius: 50%;align-items: center;justify-content: center;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{align-items: center;display: flex;justify-content: center;flex-direction: column;font-size: 1em;}@media only screen and (min-device-width: 700px){.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{font-size: 1.2em;}} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon{display: flex;width: 2.1em;height: 2.1em;color: #207ab7;background-color: #fff;border-radius: 50%;align-items: center;justify-content: center;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon::before{font-family: tinymce-mobile,sans-serif;content: "\e900";} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section:not(.tinymce-mobile-mask-tap-icon-selected) .tinymce-mobile-mask-tap-icon{z-index: 2;} + +.tinymce-mobile-android-container.tinymce-mobile-android-maximized{position: fixed;top: 0;right: 0;bottom: 0;left: 0;display: flex;background: #fff;border: none;flex-direction: column;} + +.tinymce-mobile-android-container:not(.tinymce-mobile-android-maximized){position: relative;} + +.tinymce-mobile-android-container .tinymce-mobile-editor-socket{display: flex;flex-grow: 1;} + +.tinymce-mobile-android-container .tinymce-mobile-editor-socket iframe{display: flex !important;flex-grow: 1;height: auto !important;} + +.tinymce-mobile-android-scroll-reload{overflow: hidden;} + +:not(.tinymce-mobile-readonly-mode)>.tinymce-mobile-android-selection-context-toolbar{margin-top: 23px;} + +.tinymce-mobile-toolstrip{z-index: 1;display: flex;background: #fff;flex: 0 0 auto;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar{display: flex;width: 100%;height: 2.5em;background-color: #fff;border-bottom: 1px solid #ccc;align-items: center;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group{align-items: center;display: flex;height: 100%;flex-shrink: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group>div{align-items: center;display: flex;height: 100%;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-exit-container{background: #f44336;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-toolbar-scrollable-group{flex-grow: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{padding-right: .5em;padding-left: .5em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button{display: flex;height: 80%;margin-right: 2px;margin-left: 2px;align-items: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button.tinymce-mobile-toolbar-button-selected{color: #ccc;background: #c8cbcf;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:first-of-type,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:last-of-type{color: #eceff1;background: #207ab7;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group{display: flex;height: 100%;padding-top: .4em;padding-bottom: .4em;align-items: center;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog{position: relative;display: flex;width: 100%;min-height: 1.5em;padding-right: 0;padding-left: 0;overflow: hidden;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain{display: flex;width: 100%;height: 100%;transition: left cubic-bezier(.4,0,1,1) .15s;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen{display: flex;flex: 0 0 auto;justify-content: space-between;width: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen input{font-family: sans-serif;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container{position: relative;display: flex;flex-grow: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container .tinymce-mobile-input-container-x{position: absolute;right: 0;height: 100%;padding-right: 2px;font-size: .6em;font-weight: 700;color: #888;background: inherit;border: none;border-radius: 50%;align-self: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container.tinymce-mobile-input-container-empty .tinymce-mobile-input-container-x{display: none;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous{align-items: center;display: flex;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous::before{display: flex;height: 100%;padding-right: .5em;padding-left: .5em;font-weight: 700;align-items: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next.tinymce-mobile-toolbar-navigation-disabled::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous.tinymce-mobile-toolbar-navigation-disabled::before{visibility: hidden;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item{padding-top: 3px;margin: 0 2px;font-size: 10px;line-height: 10px;color: #ccc;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item.tinymce-mobile-dot-active{color: #c8cbcf;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-heading::before{margin-right: .9em;margin-left: .5em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-heading::before{margin-right: .5em;margin-left: .9em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider{position: relative;display: flex;padding: .28em 0;margin-right: 0;margin-left: 0;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container{align-items: center;display: flex;flex-grow: 1;height: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container .tinymce-mobile-slider-size-line{display: flex;height: .2em;margin-top: .3em;margin-bottom: .3em;background: #ccc;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container{padding-right: 2em;padding-left: 2em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container{align-items: center;display: flex;flex-grow: 1;height: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container .tinymce-mobile-slider-gradient{display: flex;height: .2em;margin-top: .3em;margin-bottom: .3em;background: linear-gradient(to right,red 0,#feff00 17%,#0f0 33%,#00feff 50%,#00f 67%,#ff00fe 83%,red 100%);flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-black{width: 1.2em;height: .2em;margin-top: .3em;margin-bottom: .3em;background: #000;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-white{width: 1.2em;height: .2em;margin-top: .3em;margin-bottom: .3em;background: #fff;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb{position: absolute;top: 0;bottom: 0;left: -10px;display: flex;width: .5em;height: .5em;margin: auto;color: #fff;background-color: #455a64;border: .5em solid rgba(136,136,136,0);border-radius: 3em;transition: border 120ms cubic-bezier(.39,.58,.57,1);background-clip: padding-box;align-items: center;justify-content: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb.tinymce-mobile-thumb-active{border: .5em solid rgba(136,136,136,.39);} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group>div{align-items: center;display: flex;height: 100%;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper{flex-direction: column;justify-content: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{align-items: center;display: flex;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item:not(.tinymce-mobile-serialised-dialog){height: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-container{display: flex;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input{padding-top: .1em;padding-bottom: .1em;padding-left: 5px;font-size: .85em;color: #455a64;background: #fff;border: none;border-radius: 0;flex-grow: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::-webkit-input-placeholder{color: #888;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::placeholder{color: #888;} + +.tinymce-mobile-dropup{display: flex;width: 100%;overflow: hidden;background: #fff;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-shrinking{transition: height .3s ease-out;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-growing{transition: height .3s ease-in;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-closed{flex-grow: 0;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-open:not(.tinymce-mobile-dropup-growing){flex-grow: 1;} + +.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height: 200px;}@media only screen and (orientation: landscape){.tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height: 200px;}}@media only screen and (min-device-width: 320px) and (max-device-width: 568px) and (orientation: landscape){.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height: 150px;}} + +.tinymce-mobile-styles-menu{position: relative;width: 100%;overflow: hidden;font-family: sans-serif;outline: 4px solid #000;} + +.tinymce-mobile-styles-menu [role=menu]{position: absolute;display: flex;width: 100%;height: 100%;flex-direction: column;} + +.tinymce-mobile-styles-menu [role=menu].transitioning{transition: transform .5s ease-in-out;} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-item{position: relative;display: flex;padding: 1em 1em;color: #455a64;cursor: pointer;border-bottom: 1px solid #ddd;} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser .tinymce-mobile-styles-collapse-icon::before{font-family: tinymce-mobile,sans-serif;color: #455a64;content: "\e314";} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-styles-item-is-menu::after{position: absolute;right: 0;padding-right: 1em;padding-left: 1em;font-family: tinymce-mobile,sans-serif;color: #455a64;content: "\e315";} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-format-matches::after{position: absolute;right: 0;padding-right: 1em;padding-left: 1em;font-family: tinymce-mobile,sans-serif;} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser,.tinymce-mobile-styles-menu .tinymce-mobile-styles-separator{display: flex;min-height: 2.5em;padding-right: 1em;padding-left: 1em;color: #455a64;background: #fff;border-top: #455a64;align-items: center;} + +.tinymce-mobile-styles-menu [data-transitioning-destination=before][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=before]{transform: translate(-100%);} + +.tinymce-mobile-styles-menu [data-transitioning-destination=current][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=current]{transform: translate(0);} + +.tinymce-mobile-styles-menu [data-transitioning-destination=after][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=after]{transform: translate(100%);}@font-face{font-family: tinymce-mobile;font-style: normal;font-weight: 400;src: url(fonts/tinymce-mobile.woff?8x92w3) format('woff');}@media (min-device-width: 700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size: 25px;}}@media (max-device-width: 700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size: 18px;}} + +.tinymce-mobile-icon{font-family: tinymce-mobile,sans-serif;} + +.mixin-flex-and-centre{align-items: center;display: flex;justify-content: center;} + +.mixin-flex-bar{align-items: center;display: flex;height: 100%;} + +.tinymce-mobile-outer-container .tinymce-mobile-editor-socket iframe{width: 100%;background-color: #fff;} + +.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{position: fixed;right: 2em;bottom: 1em;display: flex;width: 2.1em;height: 2.1em;font-size: 1em;color: #fff;background-color: #207ab7;border-radius: 50%;align-items: center;justify-content: center;}@media only screen and (min-device-width: 700px){.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{font-size: 1.2em;}} + +.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket{height: 300px;overflow: hidden;} + +.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket iframe{height: 100%;} + +.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-toolstrip{display: none;} + +input[type=file]::-webkit-file-upload-button{display: none;}@media only screen and (min-device-width: 320px) and (max-device-width: 568px) and (orientation: landscape){.tinymce-mobile-ios-container .tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{bottom: 50%;}} diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/content.inline.min.css b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/content.inline.min.css new file mode 100644 index 0000000000000000000000000000000000000000..748f313bb2324aefb902f5b679a54bbc042d5d60 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/content.inline.min.css @@ -0,0 +1,239 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.mce-content-body .mce-item-anchor{display: inline-block;width: 8px !important;height: 12px !important;padding: 0 2px;cursor: default;background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'8'%20height%3D'12'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20d%3D'M0%200L8%200%208%2012%204.09117821%209%200%2012z'%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;-webkit-user-select: all;-moz-user-select: all;-ms-user-select: all;user-select: all;-webkit-user-modify: read-only;-moz-user-modify: read-only;} + +.mce-content-body .mce-item-anchor[data-mce-selected]{outline-offset: 1px;} + +.tox-comments-visible .tox-comment{background-color: #fff0b7;} + +.tox-comments-visible .tox-comment--active{background-color: #ffe168;} + +.tox-checklist>li:not(.tox-checklist--hidden){margin: .25em 0;list-style: none;} + +.tox-checklist>li:not(.tox-checklist--hidden)::before{position: absolute;width: 1em;height: 1em;margin-top: .125em;margin-left: -1.5em;cursor: pointer;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-unchecked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2215%22%20height%3D%2215%22%20x%3D%22.5%22%20y%3D%22.5%22%20fill-rule%3D%22nonzero%22%20stroke%3D%22%234C4C4C%22%20rx%3D%222%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");background-size: 100%;content: '';} + +.tox-checklist li:not(.tox-checklist--hidden).tox-checklist--checked::before{background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-checked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%234099FF%22%20fill-rule%3D%22nonzero%22%20rx%3D%222%22%2F%3E%3Cpath%20id%3D%22Path%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%20d%3D%22M11.5703186%2C3.14417309%20C11.8516238%2C2.73724603%2012.4164781%2C2.62829933%2012.83558%2C2.89774797%20C13.260121%2C3.17069355%2013.3759736%2C3.72932262%2013.0909105%2C4.14168582%20L7.7580587%2C11.8560195%20C7.43776896%2C12.3193404%206.76483983%2C12.3852142%206.35607322%2C11.9948725%20L3.02491697%2C8.8138662%20C2.66090143%2C8.46625845%202.65798871%2C7.89594698%203.01850234%2C7.54483354%20C3.373942%2C7.19866177%203.94940006%2C7.19592841%204.30829608%2C7.5386474%20L6.85276923%2C9.9684299%20L11.5703186%2C3.14417309%20Z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");} + +[dir=rtl] .tox-checklist>li:not(.tox-checklist--hidden)::before{margin-right: -1.5em;margin-left: 0;} + +code[class*=language-],pre[class*=language-]{font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size: .875rem;-webkit-hyphens: none;-ms-hyphens: none;hyphens: none;line-height: 1.5;word-spacing: normal;color: #000;text-shadow: 0 1px #fff;word-break: normal;word-wrap: normal;white-space: pre;-moz-tab-size: 4;tab-size: 4;} + +code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow: none;background: #b3d4fc;} + +code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow: none;background: #b3d4fc;}@media print{code[class*=language-],pre[class*=language-]{text-shadow: none;}} + +pre[class*=language-]{padding: 1em;margin: .5em 0;overflow: auto;} + +:not(pre)>code[class*=language-],pre[class*=language-]{background: 0 0 !important;border: 1px solid #ccc;} + +:not(pre)>code[class*=language-]{padding: .1em;border-radius: .3em;} + +.token.cdata,.token.comment,.token.doctype,.token.prolog{color: #708090;} + +.token.punctuation{color: #999;} + +.namespace{opacity: .7;} + +.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color: #905;} + +.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color: #690;} + +.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color: #a67f59;background: hsla(0,0%,100%,.5);} + +.token.atrule,.token.attr-value,.token.keyword{color: #07a;} + +.token.function{color: #dd4a68;} + +.token.important,.token.regex,.token.variable{color: #e90;} + +.token.bold,.token.important{font-weight: 700;} + +.token.italic{font-style: italic;} + +.token.entity{cursor: help;} + +:not([dir=rtl]) code[class*=language-],:not([dir=rtl]) pre[class*=language-]{text-align: left;direction: ltr;} + +[dir=rtl] code[class*=language-],[dir=rtl] pre[class*=language-]{text-align: right;direction: rtl;} + +.mce-content-body{overflow-wrap: break-word;word-wrap: break-word;} + +.mce-content-body .mce-visual-caret{position: absolute;background-color: #000;background-color: currentColor;} + +.mce-content-body .mce-visual-caret-hidden{display: none;} + +.mce-content-body [data-mce-caret]{position: absolute;top: 0;right: auto;left: -1000px;padding: 0;margin: 0;} + +.mce-content-body .mce-offscreen-selection{position: absolute;left: -9999999999px;max-width: 1000000px;} + +.mce-content-body [contentEditable=false]{cursor: default;} + +.mce-content-body [contentEditable=true]{cursor: text;} + +.tox-cursor-format-painter{cursor: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"),default;} + +.mce-content-body figure.align-left{float: left;} + +.mce-content-body figure.align-right{float: right;} + +.mce-content-body figure.image.align-center{display: table;margin-right: auto;margin-left: auto;} + +.mce-preview-object{position: relative;display: inline-block;margin: 0 2px 0 2px;line-height: 0;border: 1px solid gray;} + +.mce-preview-object .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.mce-preview-object[data-mce-selected="2"] .mce-shim{display: none;} + +.mce-object{background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;border: 1px dashed #aaa;} + +.mce-pagebreak{display: block;width: 100%;height: 5px;margin-top: 15px;cursor: default;border: 1px dashed #aaa;page-break-before: always;}@media print{.mce-pagebreak{border: 0;}} + +.tiny-pageembed .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.tiny-pageembed[data-mce-selected="2"] .mce-shim{display: none;} + +.tiny-pageembed{position: relative;display: inline-block;} + +.tiny-pageembed--16by9,.tiny-pageembed--1by1,.tiny-pageembed--21by9,.tiny-pageembed--4by3{position: relative;display: block;width: 100%;padding: 0;overflow: hidden;} + +.tiny-pageembed--16by9::before,.tiny-pageembed--1by1::before,.tiny-pageembed--21by9::before,.tiny-pageembed--4by3::before{display: block;content: "";} + +.tiny-pageembed--21by9::before{padding-top: 42.857143%;} + +.tiny-pageembed--16by9::before{padding-top: 56.25%;} + +.tiny-pageembed--4by3::before{padding-top: 75%;} + +.tiny-pageembed--1by1::before{padding-top: 100%;} + +.tiny-pageembed--16by9 iframe,.tiny-pageembed--1by1 iframe,.tiny-pageembed--21by9 iframe,.tiny-pageembed--4by3 iframe{position: absolute;top: 0;left: 0;width: 100%;height: 100%;border: 0;} + +.mce-content-body div.mce-resizehandle{position: absolute;z-index: 10000;width: 10px;height: 10px;background-color: #4099ff;border-color: #4099ff;border-style: solid;border-width: 1px;box-sizing: border-box;} + +.mce-content-body div.mce-resizehandle:hover{background-color: #4099ff;} + +.mce-content-body div.mce-resizehandle:nth-of-type(1){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(2){cursor: nesw-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(3){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(4){cursor: nesw-resize;} + +.mce-content-body .mce-clonedresizable{position: absolute;z-index: 10000;outline: 1px dashed #000;opacity: .5;} + +.mce-content-body .mce-resize-helper{position: absolute;z-index: 10001;display: none;padding: 5px;margin: 5px 10px;font-family: sans-serif;font-size: 12px;line-height: 14px;color: #fff;white-space: nowrap;background: #555;background: rgba(0,0,0,.75);border: 1px;border-radius: 3px;} + +.mce-match-marker{color: #fff;background: #aaa;} + +.mce-match-marker-selected{color: #fff;background: #39f;} + +.mce-content-body img[data-mce-selected],.mce-content-body table[data-mce-selected]{outline: 3px solid #b4d7ff;} + +.mce-content-body hr[data-mce-selected]{outline: 3px solid #b4d7ff;outline-offset: 1px;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:focus{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:hover{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false][data-mce-selected]{cursor: not-allowed;outline: 3px solid #b4d7ff;} + +.mce-content-body.mce-content-readonly [contentEditable=true]:focus,.mce-content-body.mce-content-readonly [contentEditable=true]:hover{outline: 0;} + +.mce-content-body [data-mce-selected=inline-boundary]{background-color: #b4d7ff;} + +.mce-content-body .mce-edit-focus{outline: 3px solid #b4d7ff;} + +.mce-content-body td[data-mce-selected],.mce-content-body th[data-mce-selected]{background-color: #b4d7ff !important;} + +.mce-content-body td[data-mce-selected]::-moz-selection,.mce-content-body th[data-mce-selected]::-moz-selection{background: 0 0;} + +.mce-content-body td[data-mce-selected]::selection,.mce-content-body th[data-mce-selected]::selection{background: 0 0;} + +.mce-content-body td[data-mce-selected] *,.mce-content-body th[data-mce-selected] *{-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;} + +.mce-content-body img::-moz-selection{background: 0 0;} + +.mce-content-body img::selection{background: 0 0;} + +.ephox-snooker-resizer-bar{background-color: #b4d7ff;opacity: 0;} + +.ephox-snooker-resizer-cols{cursor: col-resize;} + +.ephox-snooker-resizer-rows{cursor: row-resize;} + +.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity: 1;} + +.mce-spellchecker-word{height: 2rem;cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23ff0000'%20fill%3D'none'%20stroke-linecap%3D'round'%20stroke-opacity%3D'.5'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-spellchecker-grammar{cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23008800'%20fill%3D'none'%20stroke-linecap%3D'round'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-toc{border: 1px solid gray;} + +.mce-toc h2{margin: 4px;} + +.mce-toc li{list-style-type: none;} + +.mce-item-table,.mce-item-table caption,.mce-item-table td,.mce-item-table th{border: 1px dashed #bbb;} + +.mce-visualblocks address,.mce-visualblocks article,.mce-visualblocks aside,.mce-visualblocks blockquote,.mce-visualblocks div:not([data-mce-bogus]),.mce-visualblocks dl,.mce-visualblocks figcaption,.mce-visualblocks figure,.mce-visualblocks h1,.mce-visualblocks h2,.mce-visualblocks h3,.mce-visualblocks h4,.mce-visualblocks h5,.mce-visualblocks h6,.mce-visualblocks hgroup,.mce-visualblocks ol,.mce-visualblocks p,.mce-visualblocks pre,.mce-visualblocks section,.mce-visualblocks ul{padding-top: 10px;margin-left: 3px;background-repeat: no-repeat;border: 1px dashed #bbb;} + +.mce-visualblocks p{background-image: url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7);} + +.mce-visualblocks h1{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==);} + +.mce-visualblocks h2{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==);} + +.mce-visualblocks h3{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7);} + +.mce-visualblocks h4{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==);} + +.mce-visualblocks h5{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==);} + +.mce-visualblocks h6{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==);} + +.mce-visualblocks div:not([data-mce-bogus]){background-image: url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7);} + +.mce-visualblocks section{background-image: url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=);} + +.mce-visualblocks article{background-image: url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7);} + +.mce-visualblocks blockquote{background-image: url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7);} + +.mce-visualblocks address{background-image: url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=);} + +.mce-visualblocks pre{background-image: url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==);} + +.mce-visualblocks figure{background-image: url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7);} + +.mce-visualblocks figcaption{border: 1px dashed #bbb;} + +.mce-visualblocks hgroup{background-image: url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7);} + +.mce-visualblocks aside{background-image: url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=);} + +.mce-visualblocks ul{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==);} + +.mce-visualblocks ol{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==);} + +.mce-visualblocks dl{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==);} + +.mce-visualblocks:not([dir=rtl]) address,.mce-visualblocks:not([dir=rtl]) article,.mce-visualblocks:not([dir=rtl]) aside,.mce-visualblocks:not([dir=rtl]) blockquote,.mce-visualblocks:not([dir=rtl]) div:not([data-mce-bogus]),.mce-visualblocks:not([dir=rtl]) dl,.mce-visualblocks:not([dir=rtl]) figcaption,.mce-visualblocks:not([dir=rtl]) figure,.mce-visualblocks:not([dir=rtl]) h1,.mce-visualblocks:not([dir=rtl]) h2,.mce-visualblocks:not([dir=rtl]) h3,.mce-visualblocks:not([dir=rtl]) h4,.mce-visualblocks:not([dir=rtl]) h5,.mce-visualblocks:not([dir=rtl]) h6,.mce-visualblocks:not([dir=rtl]) hgroup,.mce-visualblocks:not([dir=rtl]) ol,.mce-visualblocks:not([dir=rtl]) p,.mce-visualblocks:not([dir=rtl]) pre,.mce-visualblocks:not([dir=rtl]) section,.mce-visualblocks:not([dir=rtl]) ul{margin-left: 3px;} + +.mce-visualblocks[dir=rtl] address,.mce-visualblocks[dir=rtl] article,.mce-visualblocks[dir=rtl] aside,.mce-visualblocks[dir=rtl] blockquote,.mce-visualblocks[dir=rtl] div:not([data-mce-bogus]),.mce-visualblocks[dir=rtl] dl,.mce-visualblocks[dir=rtl] figcaption,.mce-visualblocks[dir=rtl] figure,.mce-visualblocks[dir=rtl] h1,.mce-visualblocks[dir=rtl] h2,.mce-visualblocks[dir=rtl] h3,.mce-visualblocks[dir=rtl] h4,.mce-visualblocks[dir=rtl] h5,.mce-visualblocks[dir=rtl] h6,.mce-visualblocks[dir=rtl] hgroup,.mce-visualblocks[dir=rtl] ol,.mce-visualblocks[dir=rtl] p,.mce-visualblocks[dir=rtl] pre,.mce-visualblocks[dir=rtl] section,.mce-visualblocks[dir=rtl] ul{background-position-x: right;margin-right: 3px;} + +.mce-nbsp,.mce-shy{background: #aaa;} + +.mce-shy::after{content: '-';} + +.tox-toolbar-dock-fadeout{opacity: 0;visibility: hidden;} + +.tox-toolbar-dock-fadein{opacity: 1;visibility: visible;} + +.tox-toolbar-dock-transition{transition: visibility 0s linear .3s,opacity .3s ease;} + +.tox-toolbar-dock-transition.tox-toolbar-dock-fadein{transition-delay: 0s;} diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/content.min.css b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/content.min.css new file mode 100644 index 0000000000000000000000000000000000000000..6e7165f097e99dac3a355448bcdb2598763617bf --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/content.min.css @@ -0,0 +1,235 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.mce-content-body .mce-item-anchor{display: inline-block;width: 8px !important;height: 12px !important;padding: 0 2px;cursor: default;background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'8'%20height%3D'12'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20d%3D'M0%200L8%200%208%2012%204.09117821%209%200%2012z'%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;-webkit-user-select: all;-moz-user-select: all;-ms-user-select: all;user-select: all;-webkit-user-modify: read-only;-moz-user-modify: read-only;} + +.mce-content-body .mce-item-anchor[data-mce-selected]{outline-offset: 1px;} + +.tox-comments-visible .tox-comment{background-color: #fff0b7;} + +.tox-comments-visible .tox-comment--active{background-color: #ffe168;} + +.tox-checklist>li:not(.tox-checklist--hidden){margin: .25em 0;list-style: none;} + +.tox-checklist>li:not(.tox-checklist--hidden)::before{position: absolute;width: 1em;height: 1em;margin-top: .125em;margin-left: -1.5em;cursor: pointer;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-unchecked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2215%22%20height%3D%2215%22%20x%3D%22.5%22%20y%3D%22.5%22%20fill-rule%3D%22nonzero%22%20stroke%3D%22%234C4C4C%22%20rx%3D%222%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");background-size: 100%;content: '';} + +.tox-checklist li:not(.tox-checklist--hidden).tox-checklist--checked::before{background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-checked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%234099FF%22%20fill-rule%3D%22nonzero%22%20rx%3D%222%22%2F%3E%3Cpath%20id%3D%22Path%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%20d%3D%22M11.5703186%2C3.14417309%20C11.8516238%2C2.73724603%2012.4164781%2C2.62829933%2012.83558%2C2.89774797%20C13.260121%2C3.17069355%2013.3759736%2C3.72932262%2013.0909105%2C4.14168582%20L7.7580587%2C11.8560195%20C7.43776896%2C12.3193404%206.76483983%2C12.3852142%206.35607322%2C11.9948725%20L3.02491697%2C8.8138662%20C2.66090143%2C8.46625845%202.65798871%2C7.89594698%203.01850234%2C7.54483354%20C3.373942%2C7.19866177%203.94940006%2C7.19592841%204.30829608%2C7.5386474%20L6.85276923%2C9.9684299%20L11.5703186%2C3.14417309%20Z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");} + +[dir=rtl] .tox-checklist>li:not(.tox-checklist--hidden)::before{margin-right: -1.5em;margin-left: 0;} + +code[class*=language-],pre[class*=language-]{font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size: .875rem;-webkit-hyphens: none;-ms-hyphens: none;hyphens: none;line-height: 1.5;word-spacing: normal;color: #000;text-shadow: 0 1px #fff;word-break: normal;word-wrap: normal;white-space: pre;-moz-tab-size: 4;tab-size: 4;} + +code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow: none;background: #b3d4fc;} + +code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow: none;background: #b3d4fc;}@media print{code[class*=language-],pre[class*=language-]{text-shadow: none;}} + +pre[class*=language-]{padding: 1em;margin: .5em 0;overflow: auto;} + +:not(pre)>code[class*=language-],pre[class*=language-]{background: 0 0 !important;border: 1px solid #ccc;} + +:not(pre)>code[class*=language-]{padding: .1em;border-radius: .3em;} + +.token.cdata,.token.comment,.token.doctype,.token.prolog{color: #708090;} + +.token.punctuation{color: #999;} + +.namespace{opacity: .7;} + +.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color: #905;} + +.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color: #690;} + +.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color: #a67f59;background: hsla(0,0%,100%,.5);} + +.token.atrule,.token.attr-value,.token.keyword{color: #07a;} + +.token.function{color: #dd4a68;} + +.token.important,.token.regex,.token.variable{color: #e90;} + +.token.bold,.token.important{font-weight: 700;} + +.token.italic{font-style: italic;} + +.token.entity{cursor: help;} + +:not([dir=rtl]) code[class*=language-],:not([dir=rtl]) pre[class*=language-]{text-align: left;direction: ltr;} + +[dir=rtl] code[class*=language-],[dir=rtl] pre[class*=language-]{text-align: right;direction: rtl;} + +.mce-content-body{overflow-wrap: break-word;word-wrap: break-word;} + +.mce-content-body .mce-visual-caret{position: absolute;background-color: #000;background-color: currentColor;} + +.mce-content-body .mce-visual-caret-hidden{display: none;} + +.mce-content-body [data-mce-caret]{position: absolute;top: 0;right: auto;left: -1000px;padding: 0;margin: 0;} + +.mce-content-body .mce-offscreen-selection{position: absolute;left: -9999999999px;max-width: 1000000px;} + +.mce-content-body [contentEditable=false]{cursor: default;} + +.mce-content-body [contentEditable=true]{cursor: text;} + +.tox-cursor-format-painter{cursor: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"),default;} + +.mce-content-body figure.align-left{float: left;} + +.mce-content-body figure.align-right{float: right;} + +.mce-content-body figure.image.align-center{display: table;margin-right: auto;margin-left: auto;} + +.mce-preview-object{position: relative;display: inline-block;margin: 0 2px 0 2px;line-height: 0;border: 1px solid gray;} + +.mce-preview-object .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.mce-preview-object[data-mce-selected="2"] .mce-shim{display: none;} + +.mce-object{background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;border: 1px dashed #aaa;} + +.mce-pagebreak{display: block;width: 100%;height: 5px;margin-top: 15px;cursor: default;border: 1px dashed #aaa;page-break-before: always;}@media print{.mce-pagebreak{border: 0;}} + +.tiny-pageembed .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.tiny-pageembed[data-mce-selected="2"] .mce-shim{display: none;} + +.tiny-pageembed{position: relative;display: inline-block;} + +.tiny-pageembed--16by9,.tiny-pageembed--1by1,.tiny-pageembed--21by9,.tiny-pageembed--4by3{position: relative;display: block;width: 100%;padding: 0;overflow: hidden;} + +.tiny-pageembed--16by9::before,.tiny-pageembed--1by1::before,.tiny-pageembed--21by9::before,.tiny-pageembed--4by3::before{display: block;content: "";} + +.tiny-pageembed--21by9::before{padding-top: 42.857143%;} + +.tiny-pageembed--16by9::before{padding-top: 56.25%;} + +.tiny-pageembed--4by3::before{padding-top: 75%;} + +.tiny-pageembed--1by1::before{padding-top: 100%;} + +.tiny-pageembed--16by9 iframe,.tiny-pageembed--1by1 iframe,.tiny-pageembed--21by9 iframe,.tiny-pageembed--4by3 iframe{position: absolute;top: 0;left: 0;width: 100%;height: 100%;border: 0;} + +.mce-content-body div.mce-resizehandle{position: absolute;z-index: 10000;width: 10px;height: 10px;background-color: #4099ff;border-color: #4099ff;border-style: solid;border-width: 1px;box-sizing: border-box;} + +.mce-content-body div.mce-resizehandle:hover{background-color: #4099ff;} + +.mce-content-body div.mce-resizehandle:nth-of-type(1){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(2){cursor: nesw-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(3){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(4){cursor: nesw-resize;} + +.mce-content-body .mce-clonedresizable{position: absolute;z-index: 10000;outline: 1px dashed #000;opacity: .5;} + +.mce-content-body .mce-resize-helper{position: absolute;z-index: 10001;display: none;padding: 5px;margin: 5px 10px;font-family: sans-serif;font-size: 12px;line-height: 14px;color: #fff;white-space: nowrap;background: #555;background: rgba(0,0,0,.75);border: 1px;border-radius: 3px;} + +.mce-match-marker{color: #fff;background: #aaa;} + +.mce-match-marker-selected{color: #fff;background: #39f;} + +.mce-content-body img[data-mce-selected],.mce-content-body table[data-mce-selected]{outline: 3px solid #b4d7ff;} + +.mce-content-body hr[data-mce-selected]{outline: 3px solid #b4d7ff;outline-offset: 1px;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:focus{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:hover{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false][data-mce-selected]{cursor: not-allowed;outline: 3px solid #b4d7ff;} + +.mce-content-body.mce-content-readonly [contentEditable=true]:focus,.mce-content-body.mce-content-readonly [contentEditable=true]:hover{outline: 0;} + +.mce-content-body [data-mce-selected=inline-boundary]{background-color: #b4d7ff;} + +.mce-content-body .mce-edit-focus{outline: 3px solid #b4d7ff;} + +.mce-content-body td[data-mce-selected],.mce-content-body th[data-mce-selected]{background-color: #b4d7ff !important;} + +.mce-content-body td[data-mce-selected]::-moz-selection,.mce-content-body th[data-mce-selected]::-moz-selection{background: 0 0;} + +.mce-content-body td[data-mce-selected]::selection,.mce-content-body th[data-mce-selected]::selection{background: 0 0;} + +.mce-content-body td[data-mce-selected] *,.mce-content-body th[data-mce-selected] *{-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;} + +.mce-content-body img::-moz-selection{background: 0 0;} + +.mce-content-body img::selection{background: 0 0;} + +.ephox-snooker-resizer-bar{background-color: #b4d7ff;opacity: 0;} + +.ephox-snooker-resizer-cols{cursor: col-resize;} + +.ephox-snooker-resizer-rows{cursor: row-resize;} + +.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity: 1;} + +.mce-spellchecker-word{height: 2rem;cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23ff0000'%20fill%3D'none'%20stroke-linecap%3D'round'%20stroke-opacity%3D'.5'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-spellchecker-grammar{cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23008800'%20fill%3D'none'%20stroke-linecap%3D'round'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-toc{border: 1px solid gray;} + +.mce-toc h2{margin: 4px;} + +.mce-toc li{list-style-type: none;} + +.mce-item-table,.mce-item-table caption,.mce-item-table td,.mce-item-table th{border: 1px dashed #bbb;} + +.mce-visualblocks address,.mce-visualblocks article,.mce-visualblocks aside,.mce-visualblocks blockquote,.mce-visualblocks div:not([data-mce-bogus]),.mce-visualblocks dl,.mce-visualblocks figcaption,.mce-visualblocks figure,.mce-visualblocks h1,.mce-visualblocks h2,.mce-visualblocks h3,.mce-visualblocks h4,.mce-visualblocks h5,.mce-visualblocks h6,.mce-visualblocks hgroup,.mce-visualblocks ol,.mce-visualblocks p,.mce-visualblocks pre,.mce-visualblocks section,.mce-visualblocks ul{padding-top: 10px;margin-left: 3px;background-repeat: no-repeat;border: 1px dashed #bbb;} + +.mce-visualblocks p{background-image: url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7);} + +.mce-visualblocks h1{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==);} + +.mce-visualblocks h2{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==);} + +.mce-visualblocks h3{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7);} + +.mce-visualblocks h4{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==);} + +.mce-visualblocks h5{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==);} + +.mce-visualblocks h6{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==);} + +.mce-visualblocks div:not([data-mce-bogus]){background-image: url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7);} + +.mce-visualblocks section{background-image: url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=);} + +.mce-visualblocks article{background-image: url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7);} + +.mce-visualblocks blockquote{background-image: url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7);} + +.mce-visualblocks address{background-image: url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=);} + +.mce-visualblocks pre{background-image: url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==);} + +.mce-visualblocks figure{background-image: url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7);} + +.mce-visualblocks figcaption{border: 1px dashed #bbb;} + +.mce-visualblocks hgroup{background-image: url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7);} + +.mce-visualblocks aside{background-image: url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=);} + +.mce-visualblocks ul{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==);} + +.mce-visualblocks ol{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==);} + +.mce-visualblocks dl{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==);} + +.mce-visualblocks:not([dir=rtl]) address,.mce-visualblocks:not([dir=rtl]) article,.mce-visualblocks:not([dir=rtl]) aside,.mce-visualblocks:not([dir=rtl]) blockquote,.mce-visualblocks:not([dir=rtl]) div:not([data-mce-bogus]),.mce-visualblocks:not([dir=rtl]) dl,.mce-visualblocks:not([dir=rtl]) figcaption,.mce-visualblocks:not([dir=rtl]) figure,.mce-visualblocks:not([dir=rtl]) h1,.mce-visualblocks:not([dir=rtl]) h2,.mce-visualblocks:not([dir=rtl]) h3,.mce-visualblocks:not([dir=rtl]) h4,.mce-visualblocks:not([dir=rtl]) h5,.mce-visualblocks:not([dir=rtl]) h6,.mce-visualblocks:not([dir=rtl]) hgroup,.mce-visualblocks:not([dir=rtl]) ol,.mce-visualblocks:not([dir=rtl]) p,.mce-visualblocks:not([dir=rtl]) pre,.mce-visualblocks:not([dir=rtl]) section,.mce-visualblocks:not([dir=rtl]) ul{margin-left: 3px;} + +.mce-visualblocks[dir=rtl] address,.mce-visualblocks[dir=rtl] article,.mce-visualblocks[dir=rtl] aside,.mce-visualblocks[dir=rtl] blockquote,.mce-visualblocks[dir=rtl] div:not([data-mce-bogus]),.mce-visualblocks[dir=rtl] dl,.mce-visualblocks[dir=rtl] figcaption,.mce-visualblocks[dir=rtl] figure,.mce-visualblocks[dir=rtl] h1,.mce-visualblocks[dir=rtl] h2,.mce-visualblocks[dir=rtl] h3,.mce-visualblocks[dir=rtl] h4,.mce-visualblocks[dir=rtl] h5,.mce-visualblocks[dir=rtl] h6,.mce-visualblocks[dir=rtl] hgroup,.mce-visualblocks[dir=rtl] ol,.mce-visualblocks[dir=rtl] p,.mce-visualblocks[dir=rtl] pre,.mce-visualblocks[dir=rtl] section,.mce-visualblocks[dir=rtl] ul{background-position-x: right;margin-right: 3px;} + +.mce-nbsp,.mce-shy{background: #aaa;} + +.mce-shy::after{content: '-';} + +body{font-family: sans-serif;} + +table{border-collapse: collapse;} diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/content.mobile.min.css b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/content.mobile.min.css new file mode 100644 index 0000000000000000000000000000000000000000..c0522520ef7473120f188dda219d918fc43c6a43 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/content.mobile.min.css @@ -0,0 +1,17 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{position: absolute;display: inline-block;background-color: green;opacity: .5;} + +body{-webkit-text-size-adjust: none;} + +body img{max-width: 96vw;} + +body table img{max-width: 95%;} + +body{font-family: sans-serif;} + +table{border-collapse: collapse;} diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff new file mode 100644 index 0000000000000000000000000000000000000000..1e3be038a607cb7c2544ed8ae3d6621f77bf4c38 Binary files /dev/null and b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff differ diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/skin.min.css b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/skin.min.css new file mode 100644 index 0000000000000000000000000000000000000000..5886c594c2e9e5507ce781aaafa7787eed3d20f0 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/skin.min.css @@ -0,0 +1,875 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tox{font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 16px;font-style: normal;font-weight: 400;line-height: normal;color: #222f3e;text-decoration: none;text-shadow: none;text-transform: none;white-space: normal;vertical-align: initial;cursor: auto;box-sizing: content-box;-webkit-tap-highlight-color: transparent;} + +.tox :not(svg){font-family: inherit;font-size: inherit;font-style: inherit;font-weight: inherit;line-height: inherit;color: inherit;text-align: inherit;text-decoration: inherit;text-shadow: inherit;text-transform: inherit;white-space: inherit;vertical-align: inherit;cursor: inherit;box-sizing: inherit;direction: inherit;-webkit-tap-highlight-color: inherit;} + +.tox :not(svg){position: static;float: none;width: auto;height: auto;max-width: none;padding: 0;margin: 0;background: 0 0;border: 0;outline: 0;} + +.tox:not([dir=rtl]){text-align: left;direction: ltr;} + +.tox[dir=rtl]{text-align: right;direction: rtl;} + +.tox-tinymce{position: relative;display: flex;overflow: hidden;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;border: 1px solid #ccc;border-radius: 0;visibility: inherit !important;box-shadow: none;box-sizing: border-box;flex-direction: column;} + +.tox-editor-container{display: flex;flex: 1 1 auto;flex-direction: column;overflow: hidden;} + +.tox-editor-container>:first-child{border-top: none !important;} + +.tox-tinymce-aux{font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;} + +.tox-tinymce :focus,.tox-tinymce-aux :focus{outline: 0;} + +button::-moz-focus-inner{border: 0;} + +.tox-silver-sink{z-index: 1300;} + +.tox .tox-anchorbar{display: flex;flex: 0 0 auto;} + +.tox .tox-bar{display: flex;flex: 0 0 auto;} + +.tox .tox-button{display: inline-block;padding: 4px 16px;margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 14px;font-weight: 700;line-height: 24px;letter-spacing: 1;color: #fff;text-align: center;text-decoration: none;text-transform: capitalize;white-space: nowrap;cursor: pointer;background-color: #207ab7;background-image: none;background-position: none;background-repeat: none;border-color: #207ab7;border-style: solid;border-width: 1px;border-radius: 3px;outline: 0;box-shadow: none;box-sizing: border-box;} + +.tox .tox-button[disabled]{color: rgba(255,255,255,.5);cursor: not-allowed;background-color: #207ab7;background-image: none;border-color: #207ab7;box-shadow: none;} + +.tox .tox-button:focus:not(:disabled){color: #fff;background-color: #1c6ca1;background-image: none;border-color: #1c6ca1;box-shadow: none;} + +.tox .tox-button:hover:not(:disabled){color: #fff;background-color: #1c6ca1;background-image: none;border-color: #1c6ca1;box-shadow: none;} + +.tox .tox-button:active:not(:disabled){color: #fff;background-color: #185d8c;background-image: none;border-color: #185d8c;box-shadow: none;} + +.tox .tox-button--secondary{padding: 4px 16px;color: #222f3e;text-decoration: none;text-transform: capitalize;background-color: #f0f0f0;background-image: none;background-position: none;background-repeat: none;border-color: #f0f0f0;border-style: solid;border-width: 1px;border-radius: 3px;outline: 0;box-shadow: none;} + +.tox .tox-button--secondary[disabled]{color: rgba(34,47,62,.5);background-color: #f0f0f0;background-image: none;border-color: #f0f0f0;box-shadow: none;} + +.tox .tox-button--secondary:focus:not(:disabled){color: #222f3e;background-color: #e3e3e3;background-image: none;border-color: #e3e3e3;box-shadow: none;} + +.tox .tox-button--secondary:hover:not(:disabled){color: #222f3e;background-color: #e3e3e3;background-image: none;border-color: #e3e3e3;box-shadow: none;} + +.tox .tox-button--secondary:active:not(:disabled){color: #222f3e;background-color: #d6d6d6;background-image: none;border-color: #d6d6d6;box-shadow: none;} + +.tox .tox-button--icon,.tox .tox-button.tox-button--icon,.tox .tox-button.tox-button--secondary.tox-button--icon{padding: 4px;} + +.tox .tox-button--icon .tox-icon svg,.tox .tox-button.tox-button--icon .tox-icon svg,.tox .tox-button.tox-button--secondary.tox-button--icon .tox-icon svg{display: block;fill: currentColor;} + +.tox .tox-button-link{display: inline-block;padding: 0;margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 16px;font-weight: 400;line-height: 1.3;white-space: nowrap;cursor: pointer;background: 0;border: none;box-sizing: border-box;} + +.tox .tox-button-link--sm{font-size: 14px;} + +.tox .tox-button--naked{color: #222f3e;background-color: transparent;border-color: transparent;box-shadow: unset;} + +.tox .tox-button--naked:hover:not(:disabled){color: #222f3e;background-color: #e3e3e3;border-color: #e3e3e3;box-shadow: none;} + +.tox .tox-button--naked:focus:not(:disabled){color: #222f3e;background-color: #e3e3e3;border-color: #e3e3e3;box-shadow: none;} + +.tox .tox-button--naked:active:not(:disabled){color: #222f3e;background-color: #d6d6d6;border-color: #d6d6d6;box-shadow: none;} + +.tox .tox-button--naked .tox-icon svg{fill: currentColor;} + +.tox .tox-button--naked.tox-button--icon{color: currentColor;} + +.tox .tox-button--naked.tox-button--icon:hover:not(:disabled){color: #222f3e;} + +.tox .tox-checkbox{display: flex;height: 36px;min-width: 36px;cursor: pointer;border-radius: 3px;align-items: center;} + +.tox .tox-checkbox__input{position: absolute;top: auto;left: -10000px;width: 1px;height: 1px;overflow: hidden;} + +.tox .tox-checkbox__icons{width: 24px;height: 24px;padding: calc(4px - 1px);border-radius: 3px;box-shadow: 0 0 0 2px transparent;box-sizing: content-box;} + +.tox .tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display: block;fill: rgba(34,47,62,.3);} + +.tox .tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{display: none;fill: #207ab7;} + +.tox .tox-checkbox__icons .tox-checkbox-icon__checked svg{display: none;fill: #207ab7;} + +.tox input.tox-checkbox__input:checked+.tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display: none;} + +.tox input.tox-checkbox__input:checked+.tox-checkbox__icons .tox-checkbox-icon__checked svg{display: block;} + +.tox input.tox-checkbox__input:indeterminate+.tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display: none;} + +.tox input.tox-checkbox__input:indeterminate+.tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{display: block;} + +.tox input.tox-checkbox__input:focus+.tox-checkbox__icons{padding: calc(4px - 1px);border-radius: 3px;box-shadow: inset 0 0 0 1px #207ab7;} + +.tox:not([dir=rtl]) .tox-checkbox__label{margin-left: 4px;} + +.tox:not([dir=rtl]) .tox-bar .tox-checkbox{margin-left: 4px;} + +.tox[dir=rtl] .tox-checkbox__label{margin-right: 4px;} + +.tox[dir=rtl] .tox-bar .tox-checkbox{margin-right: 4px;} + +.tox .tox-collection--toolbar .tox-collection__group{display: flex;padding: 0;} + +.tox .tox-collection--grid .tox-collection__group{display: flex;max-height: 208px;padding: 0;overflow-x: hidden;overflow-y: auto;flex-wrap: wrap;} + +.tox .tox-collection--list .tox-collection__group{padding: 4px 0;border-color: #ccc;border-style: solid;border-top-width: 1px;border-right-width: 0;border-bottom-width: 0;border-left-width: 0;} + +.tox .tox-collection--list .tox-collection__group:first-child{border-top-width: 0;} + +.tox .tox-collection__group-heading{padding: 4px 8px;margin-top: -4px;margin-bottom: 4px;font-size: 12px;font-style: normal;font-weight: 400;color: rgba(34,47,62,.7);text-transform: none;cursor: default;background-color: #e6e6e6;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;-webkit-touch-callout: none;} + +.tox .tox-collection__item{display: flex;color: #222f3e;cursor: pointer;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;align-items: center;-webkit-touch-callout: none;} + +.tox .tox-collection--list .tox-collection__item{padding: 4px 8px;} + +.tox .tox-collection--toolbar .tox-collection__item{padding: 4px;border-radius: 3px;} + +.tox .tox-collection--grid .tox-collection__item{padding: 4px;border-radius: 3px;} + +.tox .tox-collection--list .tox-collection__item--enabled{color: contrast(inherit,#222f3e,#fff);background-color: inherit;} + +.tox .tox-collection--list .tox-collection__item--active:not(.tox-collection__item--state-disabled){color: #222f3e;background-color: #dee0e2;} + +.tox .tox-collection--toolbar .tox-collection__item--enabled{color: #222f3e;background-color: #c8cbcf;} + +.tox .tox-collection--toolbar .tox-collection__item--active:not(.tox-collection__item--state-disabled){color: #222f3e;background-color: #dee0e2;} + +.tox .tox-collection--grid .tox-collection__item--enabled{color: #222f3e;background-color: #c8cbcf;} + +.tox .tox-collection--grid .tox-collection__item--active:not(.tox-collection__item--state-disabled){color: #222f3e;background-color: #dee0e2;} + +.tox .tox-collection__item--state-disabled{color: rgba(34,47,62,.5);cursor: default;background-color: transparent;} + +.tox .tox-collection__item-icon{display: flex;width: 24px;height: 24px;align-items: center;justify-content: center;} + +.tox .tox-collection__item-icon svg{fill: currentColor;} + +.tox .tox-collection--toolbar-lg .tox-collection__item-icon{width: 48px;height: 48px;} + +.tox .tox-collection__item[role=menuitemcheckbox]:not(.tox-collection__item--enabled) .tox-collection__item-checkmark svg{display: none;} + +.tox .tox-collection__item-label{display: inline-block;font-size: 14px;font-style: normal;font-weight: 400;line-height: 24px;color: currentColor;text-transform: none;word-break: break-all;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-collection__item-accessory{display: inline-block;height: 24px;font-size: 14px;line-height: 24px;color: rgba(34,47,62,.7);text-transform: normal;} + +.tox .tox-collection__item-caret{align-items: center;display: flex;min-height: 24px;} + +.tox .tox-collection__item-caret::after{min-height: inherit;font-size: 0;content: '';} + +.tox:not([dir=rtl]) .tox-collection--list .tox-collection__item>:not(:first-child){margin-left: 8px;} + +.tox:not([dir=rtl]) .tox-collection--list .tox-collection__item-label:first-child{margin-left: 4px;} + +.tox:not([dir=rtl]) .tox-collection__item-accessory{margin-left: 16px;text-align: right;} + +.tox:not([dir=rtl]) .tox-collection__item-caret{margin-left: 16px;} + +.tox[dir=rtl] .tox-collection--list .tox-collection__item>:not(:first-child){margin-right: 8px;} + +.tox[dir=rtl] .tox-collection--list .tox-collection__item-label:first-child{margin-right: 4px;} + +.tox[dir=rtl] .tox-collection__item-icon-rtl .tox-collection__item-icon svg{transform: rotateY(180deg);} + +.tox[dir=rtl] .tox-collection__item-accessory{margin-right: 16px;text-align: left;} + +.tox[dir=rtl] .tox-collection__item-caret{margin-right: 16px;transform: rotateY(180deg);} + +.tox .tox-color-picker-container{display: flex;flex-direction: row;height: 225px;margin: 0;} + +.tox .tox-sv-palette{display: flex;height: 100%;box-sizing: border-box;} + +.tox .tox-sv-palette-spectrum{height: 100%;} + +.tox .tox-sv-palette,.tox .tox-sv-palette-spectrum{width: 225px;} + +.tox .tox-sv-palette-thumb{position: absolute;width: 12px;height: 12px;background: 0 0;border: 1px solid #000;border-radius: 50%;box-sizing: content-box;} + +.tox .tox-sv-palette-inner-thumb{position: absolute;width: 10px;height: 10px;border: 1px solid #fff;border-radius: 50%;} + +.tox .tox-hue-slider{width: 25px;height: 100%;box-sizing: border-box;} + +.tox .tox-hue-slider-spectrum{width: 100%;height: 100%;background: linear-gradient(to bottom,red,#ff0080,#f0f,#8000ff,#00f,#0080ff,#0ff,#00ff80,#0f0,#80ff00,#ff0,#ff8000,red);} + +.tox .tox-hue-slider,.tox .tox-hue-slider-spectrum{width: 20px;} + +.tox .tox-hue-slider-thumb{width: 100%;height: 4px;background: #fff;border: 1px solid #000;box-sizing: content-box;} + +.tox .tox-rgb-form{display: flex;flex-direction: column;justify-content: space-between;} + +.tox .tox-rgb-form div{display: flex;width: inherit;margin-bottom: 5px;align-items: center;justify-content: space-between;} + +.tox .tox-rgb-form input{width: 6em;} + +.tox .tox-rgb-form input.tox-invalid{border: 1px solid red !important;} + +.tox .tox-rgb-form .tox-rgba-preview{margin-bottom: 0;border: 1px solid #000;flex-grow: 2;} + +.tox:not([dir=rtl]) .tox-sv-palette{margin-right: 15px;} + +.tox:not([dir=rtl]) .tox-hue-slider{margin-right: 15px;} + +.tox:not([dir=rtl]) .tox-hue-slider-thumb{margin-left: -1px;} + +.tox:not([dir=rtl]) .tox-rgb-form label{margin-right: .5em;} + +.tox[dir=rtl] .tox-sv-palette{margin-left: 15px;} + +.tox[dir=rtl] .tox-hue-slider{margin-left: 15px;} + +.tox[dir=rtl] .tox-hue-slider-thumb{margin-right: -1px;} + +.tox[dir=rtl] .tox-rgb-form label{margin-left: .5em;} + +.tox .tox-toolbar .tox-swatches,.tox .tox-toolbar__overflow .tox-swatches,.tox .tox-toolbar__primary .tox-swatches{margin: 2px 0 3px 4px;} + +.tox .tox-collection--list .tox-collection__group .tox-swatches-menu{margin: -4px 0;border: 0;} + +.tox .tox-swatches__row{display: flex;} + +.tox .tox-swatch{width: 30px;height: 30px;transition: transform .15s,box-shadow .15s;} + +.tox .tox-swatch:focus,.tox .tox-swatch:hover{transform: scale(.8);box-shadow: 0 0 0 1px rgba(127,127,127,.3) inset;} + +.tox .tox-swatch--remove{align-items: center;display: flex;justify-content: center;} + +.tox .tox-swatch--remove svg path{stroke: #e74c3c;} + +.tox .tox-swatches__picker-btn{display: flex;width: 30px;height: 30px;padding: 0;cursor: pointer;background-color: transparent;border: 0;outline: 0;align-items: center;justify-content: center;} + +.tox .tox-swatches__picker-btn svg{width: 24px;height: 24px;} + +.tox .tox-swatches__picker-btn:hover{background: #dee0e2;} + +.tox:not([dir=rtl]) .tox-swatches__picker-btn{margin-left: auto;} + +.tox[dir=rtl] .tox-swatches__picker-btn{margin-right: auto;} + +.tox .tox-comment-thread{position: relative;background: #fff;} + +.tox .tox-comment-thread>:not(:first-child){margin-top: 8px;} + +.tox .tox-comment{position: relative;padding: 8px 8px 16px 8px;background: #fff;border: 1px solid #ccc;border-radius: 3px;box-shadow: 0 4px 8px 0 rgba(34,47,62,.1);} + +.tox .tox-comment__header{display: flex;color: #222f3e;align-items: center;justify-content: space-between;} + +.tox .tox-comment__date{font-size: 12px;color: rgba(34,47,62,.7);} + +.tox .tox-comment__body{position: relative;margin-top: 8px;font-size: 14px;font-style: normal;font-weight: 400;line-height: 1.3;color: #222f3e;text-transform: initial;} + +.tox .tox-comment__body textarea{width: 100%;white-space: normal;resize: none;} + +.tox .tox-comment__expander{padding-top: 8px;} + +.tox .tox-comment__expander p{font-size: 14px;font-style: normal;color: rgba(34,47,62,.7);} + +.tox .tox-comment__body p{margin: 0;} + +.tox .tox-comment__buttonspacing{padding-top: 16px;text-align: center;} + +.tox .tox-comment-thread__overlay::after{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 5;display: flex;background: #fff;content: "";opacity: .9;} + +.tox .tox-comment__reply{display: flex;flex-shrink: 0;flex-wrap: wrap;justify-content: flex-end;margin-top: 8px;} + +.tox .tox-comment__reply>:first-child{width: 100%;margin-bottom: 8px;} + +.tox .tox-comment__edit{display: flex;flex-wrap: wrap;justify-content: flex-end;margin-top: 16px;} + +.tox .tox-comment__gradient::after{position: absolute;bottom: 0;display: block;width: 100%;height: 5em;margin-top: -40px;background: linear-gradient(rgba(255,255,255,0),#fff);content: "";} + +.tox .tox-comment__overlay{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 5;display: flex;text-align: center;background: #fff;opacity: .9;flex-direction: column;flex-grow: 1;} + +.tox .tox-comment__loading-text{position: relative;display: flex;color: #222f3e;align-items: center;flex-direction: column;} + +.tox .tox-comment__loading-text>div{padding-bottom: 16px;} + +.tox .tox-comment__overlaytext{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 10;padding: 1em;font-size: 14px;flex-direction: column;} + +.tox .tox-comment__overlaytext p{color: #222f3e;text-align: center;background-color: #fff;box-shadow: 0 0 8px 8px #fff;} + +.tox .tox-comment__overlaytext div:nth-of-type(2){font-size: .8em;} + +.tox .tox-comment__busy-spinner{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1103;display: flex;background-color: #fff;align-items: center;justify-content: center;} + +.tox .tox-comment__scroll{display: flex;flex-direction: column;flex-shrink: 1;overflow: auto;} + +.tox .tox-conversations{margin: 8px;} + +.tox:not([dir=rtl]) .tox-comment__edit{margin-left: 8px;} + +.tox:not([dir=rtl]) .tox-comment__buttonspacing>:last-child,.tox:not([dir=rtl]) .tox-comment__edit>:last-child,.tox:not([dir=rtl]) .tox-comment__reply>:last-child{margin-left: 8px;} + +.tox[dir=rtl] .tox-comment__edit{margin-right: 8px;} + +.tox[dir=rtl] .tox-comment__buttonspacing>:last-child,.tox[dir=rtl] .tox-comment__edit>:last-child,.tox[dir=rtl] .tox-comment__reply>:last-child{margin-right: 8px;} + +.tox .tox-user{align-items: center;display: flex;} + +.tox .tox-user__avatar svg{fill: rgba(34,47,62,.7);} + +.tox .tox-user__name{font-size: 12px;font-style: normal;font-weight: 700;color: rgba(34,47,62,.7);text-transform: uppercase;} + +.tox:not([dir=rtl]) .tox-user__avatar svg{margin-right: 8px;} + +.tox:not([dir=rtl]) .tox-user__avatar+.tox-user__name{margin-left: 8px;} + +.tox[dir=rtl] .tox-user__avatar svg{margin-left: 8px;} + +.tox[dir=rtl] .tox-user__avatar+.tox-user__name{margin-right: 8px;} + +.tox .tox-dialog-wrap{position: fixed;top: 0;right: 0;bottom: 0;left: 0;z-index: 1100;display: flex;align-items: center;justify-content: center;} + +.tox .tox-dialog-wrap__backdrop{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1101;background-color: rgba(255,255,255,.75);} + +.tox .tox-dialog{position: relative;z-index: 1102;display: flex;width: 95vw;max-width: 480px;max-height: 100%;overflow: hidden;background-color: #fff;border-color: #ccc;border-style: solid;border-width: 1px;border-radius: 3px;box-shadow: 0 16px 16px -10px rgba(34,47,62,.15),0 0 40px 1px rgba(34,47,62,.15);flex-direction: column;} + +.tox .tox-dialog__header{position: relative;display: flex;padding: 8px 16px 0 16px;margin-bottom: 16px;font-size: 16px;color: #222f3e;background-color: #fff;border-bottom: none;align-items: center;justify-content: space-between;} + +.tox .tox-dialog__header .tox-button{z-index: 1;} + +.tox .tox-dialog__draghandle{position: absolute;top: 0;left: 0;width: 100%;height: 100%;cursor: grab;} + +.tox .tox-dialog__draghandle:active{cursor: grabbing;} + +.tox .tox-dialog__dismiss{margin-left: auto;} + +.tox .tox-dialog__title{margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 20px;font-style: normal;font-weight: 400;line-height: 1.3;text-transform: normal;} + +.tox .tox-dialog__body{display: flex;min-width: 0;padding: 0 16px;font-size: 16px;font-style: normal;font-weight: 400;line-height: 1.3;color: #222f3e;text-align: left;text-transform: normal;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-nav{align-items: flex-start;display: flex;flex-direction: column;} + +.tox .tox-dialog__body-nav-item{display: inline-block;margin-bottom: 8px;font-size: 14px;line-height: 1.3;color: rgba(34,47,62,.7);text-decoration: none;border-bottom: 2px solid transparent;} + +.tox .tox-dialog__body-nav-item--active{color: #207ab7;border-bottom: 2px solid #207ab7;} + +.tox .tox-dialog__body-content{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;max-height: 650px;overflow: auto;} + +.tox .tox-dialog__body-content>*{margin-top: 16px;margin-bottom: 0;} + +.tox .tox-dialog__body-content>:first-child{margin-top: 0;} + +.tox .tox-dialog__body-content>:last-child{margin-bottom: 0;} + +.tox .tox-dialog__body-content>:only-child{margin-top: 0;margin-bottom: 0;} + +.tox .tox-dialog--width-lg{height: 650px;max-width: 1200px;} + +.tox .tox-dialog--width-md{max-width: 800px;} + +.tox .tox-dialog--width-md .tox-dialog__body-content{overflow: auto;} + +.tox .tox-dialog__body-content--centered{text-align: center;} + +.tox .tox-dialog__body-content--spacious{margin-bottom: 16px;} + +.tox .tox-dialog__footer{display: flex;padding: 8px 16px;margin-top: 16px;background-color: #fff;border-top: 1px solid #ccc;align-items: center;justify-content: space-between;} + +.tox .tox-dialog__busy-spinner{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1103;display: flex;background-color: rgba(255,255,255,.75);align-items: center;justify-content: center;} + +.tox .tox-dialog__table{width: 100%;border-collapse: collapse;} + +.tox .tox-dialog__table thead th{padding-bottom: 8px;font-weight: 700;} + +.tox .tox-dialog__table tbody tr{border-bottom: 1px solid #ccc;} + +.tox .tox-dialog__table tbody tr:last-child{border-bottom: none;} + +.tox .tox-dialog__table td{padding-top: 8px;padding-bottom: 8px;} + +.tox .tox-dialog__popups{position: absolute;z-index: 1100;width: 100%;} + +.tox .tox-dialog__body-iframe{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-iframe .tox-navobj{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-iframe .tox-navobj :nth-child(2){flex: 1;-ms-flex-preferred-size: auto;height: 100%;} + +body.tox-dialog__disable-scroll{overflow: hidden;} + +.tox.tox-platform-ie .tox-dialog-wrap{position: -ms-device-fixed;} + +.tox:not([dir=rtl]) .tox-dialog__body-nav{margin-right: 32px;} + +.tox:not([dir=rtl]) .tox-dialog__footer .tox-dialog__footer-end>*,.tox:not([dir=rtl]) .tox-dialog__footer .tox-dialog__footer-start>*{margin-left: 8px;} + +.tox[dir=rtl] .tox-dialog__body{text-align: right;} + +.tox[dir=rtl] .tox-dialog__body-nav{margin-left: 32px;} + +.tox[dir=rtl] .tox-dialog__footer .tox-dialog__footer-end>*,.tox[dir=rtl] .tox-dialog__footer .tox-dialog__footer-start>*{margin-right: 8px;} + +.tox .tox-dropzone-container{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dropzone{display: flex;min-height: 100px;padding: 10px;background: #fff;border: 2px dashed #ccc;box-sizing: border-box;align-items: center;flex-direction: column;flex-grow: 1;justify-content: center;} + +.tox .tox-dropzone p{margin: 0 0 16px 0;color: rgba(34,47,62,.7);} + +.tox .tox-edit-area{position: relative;display: flex;overflow: hidden;border-top: 1px solid #ccc;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-edit-area__iframe{position: absolute;width: 100%;height: 100%;background-color: #fff;border: 0;box-sizing: border-box;flex: 1;-ms-flex-preferred-size: auto;} + +.tox.tox-inline-edit-area{border: 1px dotted #ccc;} + +.tox .tox-control-wrap{flex: 1;position: relative;} + +.tox .tox-control-wrap:not(.tox-control-wrap--status-invalid) .tox-control-wrap__status-icon-invalid,.tox .tox-control-wrap:not(.tox-control-wrap--status-unknown) .tox-control-wrap__status-icon-unknown,.tox .tox-control-wrap:not(.tox-control-wrap--status-valid) .tox-control-wrap__status-icon-valid{display: none;} + +.tox .tox-control-wrap svg{display: block;} + +.tox .tox-control-wrap__status-icon-wrap{position: absolute;top: 50%;transform: translateY(-50%);} + +.tox .tox-control-wrap__status-icon-invalid svg{fill: #c00;} + +.tox .tox-control-wrap__status-icon-unknown svg{fill: orange;} + +.tox .tox-control-wrap__status-icon-valid svg{fill: green;} + +.tox:not([dir=rtl]) .tox-control-wrap--status-invalid .tox-textfield,.tox:not([dir=rtl]) .tox-control-wrap--status-unknown .tox-textfield,.tox:not([dir=rtl]) .tox-control-wrap--status-valid .tox-textfield{padding-right: 32px;} + +.tox:not([dir=rtl]) .tox-control-wrap__status-icon-wrap{right: 4px;} + +.tox[dir=rtl] .tox-control-wrap--status-invalid .tox-textfield,.tox[dir=rtl] .tox-control-wrap--status-unknown .tox-textfield,.tox[dir=rtl] .tox-control-wrap--status-valid .tox-textfield{padding-left: 32px;} + +.tox[dir=rtl] .tox-control-wrap__status-icon-wrap{left: 4px;} + +.tox .tox-autocompleter{max-width: 25em;} + +.tox .tox-autocompleter .tox-menu{max-width: 25em;} + +.tox .tox-color-input{display: flex;} + +.tox .tox-color-input .tox-textfield{display: flex;border-radius: 3px 0 0 3px;} + +.tox .tox-color-input span{display: flex;width: 35px;cursor: pointer;border-color: rgba(34,47,62,.2);border-style: solid;border-width: 1px 1px 1px 0;border-radius: 0 3px 3px 0;box-shadow: none;box-sizing: border-box;} + +.tox .tox-color-input span:focus{border-color: #207ab7;} + +.tox[dir=rtl] .tox-color-input .tox-textfield{border-radius: 0 3px 3px 0;} + +.tox[dir=rtl] .tox-color-input span{border-width: 1px 0 1px 1px;border-radius: 3px 0 0 3px;} + +.tox .tox-label,.tox .tox-toolbar-label{display: block;padding: 0 8px 0 0;font-size: 14px;font-style: normal;font-weight: 400;line-height: 1.3;color: rgba(34,47,62,.7);text-transform: normal;white-space: nowrap;} + +.tox .tox-toolbar-label{padding: 0 8px;} + +.tox[dir=rtl] .tox-label{padding: 0 0 0 8px;} + +.tox .tox-form{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group{margin-bottom: 4px;box-sizing: border-box;} + +.tox .tox-form__group--error{color: #c00;} + +.tox .tox-form__group--collection{display: flex;} + +.tox .tox-form__grid{display: flex;flex-direction: row;flex-wrap: wrap;justify-content: space-between;} + +.tox .tox-form__grid--2col>.tox-form__group{width: calc(50% - (8px / 2));} + +.tox .tox-form__grid--3col>.tox-form__group{width: calc(100% / 3 - (8px / 2));} + +.tox .tox-form__grid--4col>.tox-form__group{width: calc(25% - (8px / 2));} + +.tox .tox-form__controls-h-stack{align-items: center;display: flex;} + +.tox .tox-form__group--inline{align-items: center;display: flex;} + +.tox .tox-form__group--stretched{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group--stretched .tox-textarea{flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group--stretched .tox-navobj{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group--stretched .tox-navobj :nth-child(2){flex: 1;-ms-flex-preferred-size: auto;height: 100%;} + +.tox:not([dir=rtl]) .tox-form__controls-h-stack>:not(:first-child){margin-left: 4px;} + +.tox[dir=rtl] .tox-form__controls-h-stack>:not(:first-child){margin-right: 4px;} + +.tox .tox-lock.tox-locked .tox-lock-icon__unlock,.tox .tox-lock:not(.tox-locked) .tox-lock-icon__lock{display: none;} + +.tox .tox-textarea,.tox .tox-textfield,.tox .tox-toolbar-textfield,.tox:not([dir=rtl]) .tox-selectfield select,.tox[dir=rtl] .tox-selectfield select{width: 100%;padding: 5px 4.75px;margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 16px;line-height: 24px;color: #222f3e;background-color: #fff;border-color: #ccc;border-style: solid;border-width: 1px;border-radius: 3px;outline: 0;box-shadow: none;box-sizing: border-box;resize: none;-webkit-appearance: none;-moz-appearance: none;appearance: none;} + +.tox .tox-selectfield select:focus,.tox .tox-textarea:focus,.tox .tox-textfield:focus{border-color: #207ab7;outline: 0;box-shadow: none;} + +.tox .tox-toolbar-textfield{max-width: 250px;margin-top: 2px;margin-bottom: 3px;border-width: 0;} + +.tox .tox-naked-btn{display: block;padding: 0;margin: 0;color: #207ab7;cursor: pointer;background-color: transparent;border: 0;border-color: transparent;box-shadow: unset;} + +.tox .tox-naked-btn svg{display: block;fill: #222f3e;} + +.tox:not([dir=rtl]) .tox-toolbar-textfield+*{margin-left: 4px;} + +.tox[dir=rtl] .tox-toolbar-textfield+*{margin-right: 4px;} + +.tox .tox-selectfield{position: relative;cursor: pointer;} + +.tox .tox-selectfield select::-ms-expand{display: none;} + +.tox .tox-selectfield svg{position: absolute;top: 50%;pointer-events: none;transform: translateY(-50%);} + +.tox:not([dir=rtl]) .tox-selectfield select{padding-right: 24px;} + +.tox:not([dir=rtl]) .tox-selectfield svg{right: 8px;} + +.tox[dir=rtl] .tox-selectfield select{padding-left: 24px;} + +.tox[dir=rtl] .tox-selectfield svg{left: 8px;} + +.tox .tox-textarea{white-space: pre-wrap;-webkit-appearance: textarea;-moz-appearance: textarea;appearance: textarea;} + +.tox-fullscreen{position: fixed;top: 0;left: 0;width: 100%;height: 100%;padding: 0;margin: 0;overflow: hidden;border: 0;} + +.tox-fullscreen .tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display: none;} + +.tox-fullscreen .tox.tox-tinymce.tox-fullscreen{z-index: 1200;} + +.tox-fullscreen .tox.tox-tinymce-aux{z-index: 1201;} + +.tox .tox-image-tools{width: 100%;} + +.tox .tox-image-tools__toolbar{align-items: center;display: flex;justify-content: center;} + +.tox .tox-image-tools__image{position: relative;width: 100%;height: 380px;overflow: auto;background-color: #666;} + +.tox .tox-image-tools__image,.tox .tox-image-tools__image+.tox-image-tools__toolbar{margin-top: 8px;} + +.tox .tox-image-tools__image-bg{background: url(data:image/gif;base64,R0lGODdhDAAMAIABAMzMzP///ywAAAAADAAMAAACFoQfqYeabNyDMkBQb81Uat85nxguUAEAOw==);} + +.tox .tox-image-tools__toolbar>.tox-spacer{flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-croprect-block{position: absolute;background: #000;opacity: .5;zoom: 1;} + +.tox .tox-croprect-handle{position: absolute;top: 0;left: 0;width: 20px;height: 20px;border: 2px solid #fff;} + +.tox .tox-croprect-handle-move{position: absolute;cursor: move;border: 0;} + +.tox .tox-croprect-handle-nw{top: 100px;left: 100px;margin: -2px 0 0 -2px;cursor: nw-resize;border-width: 2px 0 0 2px;} + +.tox .tox-croprect-handle-ne{top: 100px;left: 200px;margin: -2px 0 0 -20px;cursor: ne-resize;border-width: 2px 2px 0 0;} + +.tox .tox-croprect-handle-sw{top: 200px;left: 100px;margin: -20px 2px 0 -2px;cursor: sw-resize;border-width: 0 0 2px 2px;} + +.tox .tox-croprect-handle-se{top: 200px;left: 200px;margin: -20px 0 0 -20px;cursor: se-resize;border-width: 0 2px 2px 0;} + +.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-slider:not(:first-of-type){margin-left: 8px;} + +.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-button+.tox-slider{margin-left: 32px;} + +.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-slider+.tox-button{margin-left: 32px;} + +.tox[dir=rtl] .tox-image-tools__toolbar>.tox-slider:not(:first-of-type){margin-right: 8px;} + +.tox[dir=rtl] .tox-image-tools__toolbar>.tox-button+.tox-slider{margin-right: 32px;} + +.tox[dir=rtl] .tox-image-tools__toolbar>.tox-slider+.tox-button{margin-right: 32px;} + +.tox .tox-insert-table-picker{display: flex;flex-wrap: wrap;width: 169px;} + +.tox .tox-insert-table-picker>div{width: 16px;height: 16px;border-color: #ccc;border-style: solid;border-width: 0 1px 1px 0;box-sizing: content-box;} + +.tox .tox-collection--list .tox-collection__group .tox-insert-table-picker{margin: -4px 0;} + +.tox .tox-insert-table-picker .tox-insert-table-picker__selected{background-color: rgba(32,122,183,.5);border-color: rgba(32,122,183,.5);} + +.tox .tox-insert-table-picker__label{display: block;width: 100%;padding: 4px;font-size: 14px;color: rgba(34,47,62,.7);text-align: center;} + +.tox:not([dir=rtl]) .tox-insert-table-picker>div:nth-child(10n){border-right: 0;} + +.tox[dir=rtl] .tox-insert-table-picker>div:nth-child(10n+1){border-right: 0;} + +.tox .tox-menu{z-index: 1;display: inline-block;overflow: hidden;vertical-align: top;background-color: #fff;border: 1px solid #ccc;border-radius: 3px;box-shadow: 0 4px 8px 0 rgba(34,47,62,.1);} + +.tox .tox-menu.tox-collection.tox-collection--list{padding: 0;} + +.tox .tox-menu.tox-collection.tox-collection--toolbar{padding: 4px;} + +.tox .tox-menu.tox-collection.tox-collection--grid{padding: 4px;} + +.tox .tox-menu__label blockquote,.tox .tox-menu__label code,.tox .tox-menu__label h1,.tox .tox-menu__label h2,.tox .tox-menu__label h3,.tox .tox-menu__label h4,.tox .tox-menu__label h5,.tox .tox-menu__label h6,.tox .tox-menu__label p{margin: 0;} + +.tox .tox-menubar{display: flex;padding: 0 4px;margin-bottom: -1px;background: url("data:image/svg+xml;charset=utf8,%3Csvg height='43px' viewBox='0 0 40 43px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='42px' width='100' height='1' fill='%23cccccc'/%3E%3C/svg%3E") left 0 top 0 #fff;background-color: #fff;flex: 0 0 auto;flex-shrink: 0;flex-wrap: wrap;} + +.tox .tox-mbtn{display: flex;width: auto;height: 34px;padding: 0 4px;margin: 2px 0 3px 0;overflow: hidden;font-size: 14px;font-style: normal;font-weight: 400;color: #222f3e;text-transform: normal;background: 0 0;border: 0;border-radius: 3px;outline: 0;box-shadow: none;align-items: center;flex: 0 0 auto;justify-content: center;} + +.tox .tox-mbtn[disabled]{color: rgba(34,47,62,.5);cursor: not-allowed;background-color: none;border-color: none;box-shadow: none;} + +.tox .tox-mbtn:hover:not(:disabled){color: #222f3e;background: #dee0e2;box-shadow: none;} + +.tox .tox-mbtn:focus:not(:disabled){color: #222f3e;background: #dee0e2;box-shadow: none;} + +.tox .tox-mbtn--active{color: #222f3e;background: #c8cbcf;box-shadow: none;} + +.tox .tox-mbtn__select-label{margin: 0 4px;font-weight: 400;cursor: default;} + +.tox .tox-mbtn[disabled] .tox-mbtn__select-label{cursor: not-allowed;} + +.tox .tox-mbtn__select-chevron{display: flex;display: none;width: 16px;align-items: center;justify-content: center;} + +.tox .tox-notification{display: grid;padding: 5px;margin-top: 5px;background-color: #fffaea;border-color: #ffe89d;border-style: solid;border-width: 1px;opacity: 0;box-sizing: border-box;transition: transform .1s ease-in,opacity 150ms ease-in;grid-template-columns: minmax(40px,1fr) auto minmax(40px,1fr);} + +.tox .tox-notification--in{opacity: 1;} + +.tox .tox-notification--success{background-color: #dff0d8;border-color: #d6e9c6;} + +.tox .tox-notification--error{background-color: #f2dede;border-color: #ebccd1;} + +.tox .tox-notification--warn{background-color: #fcf8e3;border-color: #faebcc;} + +.tox .tox-notification--info{background-color: #d9edf7;border-color: #779ecb;} + +.tox .tox-notification__body{font-size: 14px;color: #222f3e;text-align: center;word-break: break-all;word-break: break-word;white-space: normal;align-self: center;grid-column-end: 3;-ms-grid-column-span: 1;grid-column-start: 2;grid-row-end: 2;grid-row-start: 1;} + +.tox .tox-notification__body>*{margin: 0;} + +.tox .tox-notification__body>*+*{margin-top: 1rem;} + +.tox .tox-notification__icon{align-self: center;-ms-grid-column-align: end;grid-column-end: 2;-ms-grid-column-span: 1;grid-column-start: 1;grid-row-end: 2;grid-row-start: 1;justify-self: end;} + +.tox .tox-notification__icon svg{display: block;} + +.tox .tox-notification__dismiss{align-self: start;-ms-grid-column-align: end;grid-column-end: 4;-ms-grid-column-span: 1;grid-column-start: 3;grid-row-end: 2;grid-row-start: 1;justify-self: end;} + +.tox .tox-notification .tox-progress-bar{-ms-grid-column-align: center;grid-column-end: 4;-ms-grid-column-span: 3;grid-column-start: 1;grid-row-end: 3;-ms-grid-row-span: 1;grid-row-start: 2;justify-self: center;} + +.tox .tox-pop{position: relative;display: inline-block;} + +.tox .tox-pop--resizing{transition: width .1s ease;} + +.tox .tox-pop--resizing .tox-toolbar{flex-wrap: nowrap;} + +.tox .tox-pop__dialog{min-width: 0;overflow: hidden;background-color: #fff;border: 1px solid #ccc;border-radius: 3px;box-shadow: 0 1px 3px rgba(0,0,0,.15);} + +.tox .tox-pop__dialog>:not(.tox-toolbar){margin: 4px 4px 4px 8px;} + +.tox .tox-pop__dialog .tox-toolbar{background-color: transparent;} + +.tox .tox-pop::after,.tox .tox-pop::before{position: absolute;display: block;width: 0;height: 0;border-style: solid;content: '';} + +.tox .tox-pop.tox-pop--bottom::after,.tox .tox-pop.tox-pop--bottom::before{top: 100%;left: 50%;} + +.tox .tox-pop.tox-pop--bottom::after{margin-top: -1px;margin-left: -8px;border-color: #fff transparent transparent transparent;border-width: 8px;} + +.tox .tox-pop.tox-pop--bottom::before{margin-left: -9px;border-color: #ccc transparent transparent transparent;border-width: 9px;} + +.tox .tox-pop.tox-pop--top::after,.tox .tox-pop.tox-pop--top::before{top: 0;left: 50%;transform: translateY(-100%);} + +.tox .tox-pop.tox-pop--top::after{margin-top: 1px;margin-left: -8px;border-color: transparent transparent #fff transparent;border-width: 8px;} + +.tox .tox-pop.tox-pop--top::before{margin-left: -9px;border-color: transparent transparent #ccc transparent;border-width: 9px;} + +.tox .tox-pop.tox-pop--left::after,.tox .tox-pop.tox-pop--left::before{top: calc(50% - 1px);left: 0;transform: translateY(-50%);} + +.tox .tox-pop.tox-pop--left::after{margin-left: -15px;border-color: transparent #fff transparent transparent;border-width: 8px;} + +.tox .tox-pop.tox-pop--left::before{margin-left: -19px;border-color: transparent #ccc transparent transparent;border-width: 10px;} + +.tox .tox-pop.tox-pop--right::after,.tox .tox-pop.tox-pop--right::before{top: calc(50% + 1px);left: 100%;transform: translateY(-50%);} + +.tox .tox-pop.tox-pop--right::after{margin-left: -1px;border-color: transparent transparent transparent #fff;border-width: 8px;} + +.tox .tox-pop.tox-pop--right::before{margin-left: -1px;border-color: transparent transparent transparent #ccc;border-width: 10px;} + +.tox .tox-pop.tox-pop--align-left::after,.tox .tox-pop.tox-pop--align-left::before{left: 20px;} + +.tox .tox-pop.tox-pop--align-right::after,.tox .tox-pop.tox-pop--align-right::before{left: calc(100% - 20px);} + +.tox .tox-sidebar-wrap{display: flex;flex-direction: row;flex-grow: 1;min-height: 0;} + +.tox .tox-sidebar{display: flex;flex-direction: row;justify-content: flex-end;} + +.tox .tox-sidebar__slider{display: flex;overflow: hidden;} + +.tox .tox-sidebar__pane-container{display: flex;} + +.tox .tox-sidebar__pane{display: flex;} + +.tox .tox-sidebar--sliding-closed{opacity: 0;} + +.tox .tox-sidebar--sliding-open{opacity: 1;} + +.tox .tox-sidebar--sliding-growing,.tox .tox-sidebar--sliding-shrinking{transition: width .5s ease,opacity .5s ease;} + +.tox .tox-slider{position: relative;display: flex;height: 24px;align-items: center;flex: 1;-ms-flex-preferred-size: auto;justify-content: center;} + +.tox .tox-slider__rail{width: 100%;height: 10px;min-width: 120px;background-color: transparent;border: 1px solid #ccc;border-radius: 3px;} + +.tox .tox-slider__handle{position: absolute;top: 50%;left: 50%;width: 14px;height: 24px;background-color: #207ab7;border: 2px solid #185d8c;border-radius: 3px;transform: translateX(-50%) translateY(-50%);box-shadow: none;} + +.tox .tox-source-code{overflow: auto;} + +.tox .tox-spinner{display: flex;} + +.tox .tox-spinner>div{width: 8px;height: 8px;background-color: rgba(34,47,62,.7);border-radius: 100%;animation: tam-bouncing-dots 1.5s ease-in-out 0s infinite both;} + +.tox .tox-spinner>div:nth-child(1){animation-delay: -.32s;} + +.tox .tox-spinner>div:nth-child(2){animation-delay: -.16s;}@keyframes tam-bouncing-dots{0%,100%,80%{transform: scale(0);} + +40%{transform: scale(1);}} + +.tox:not([dir=rtl]) .tox-spinner>div:not(:first-child){margin-left: 4px;} + +.tox[dir=rtl] .tox-spinner>div:not(:first-child){margin-right: 4px;} + +.tox .tox-statusbar{position: relative;display: flex;height: 18px;padding: 0 8px;overflow: hidden;font-size: 12px;color: rgba(34,47,62,.7);text-transform: uppercase;background-color: #fff;border-top: 1px solid #ccc;align-items: center;flex: 0 0 auto;} + +.tox .tox-statusbar a{color: rgba(34,47,62,.7);text-decoration: none;} + +.tox .tox-statusbar a:hover{text-decoration: underline;} + +.tox .tox-statusbar__text-container{display: flex;flex: 1 1 auto;justify-content: flex-end;overflow: hidden;} + +.tox .tox-statusbar__path{display: flex;flex: 1 1 auto;margin-right: auto;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;} + +.tox .tox-statusbar__path>*{display: inline;white-space: nowrap;} + +.tox .tox-statusbar__wordcount{flex: 0 0 auto;margin-left: 1ch;} + +.tox .tox-statusbar__resize-handle{display: flex;padding-left: 1ch;margin-right: -8px;margin-left: auto;cursor: nwse-resize;align-items: flex-end;align-self: stretch;flex: 0 0 auto;justify-content: flex-end;} + +.tox .tox-statusbar__resize-handle svg{display: block;fill: rgba(34,47,62,.7);} + +.tox:not([dir=rtl]) .tox-statusbar__path>*{margin-right: 4px;} + +.tox:not([dir=rtl]) .tox-statusbar__branding{margin-left: 1ch;} + +.tox[dir=rtl] .tox-statusbar{flex-direction: row-reverse;} + +.tox[dir=rtl] .tox-statusbar__path>*{margin-left: 4px;} + +.tox .tox-throbber{z-index: 1400;} + +.tox .tox-throbber__busy-spinner{position: absolute;top: 0;right: 0;bottom: 0;left: 0;display: flex;background-color: rgba(255,255,255,.6);align-items: center;justify-content: center;} + +.tox .tox-tbtn{display: flex;width: 34px;height: 34px;padding: 0;margin: 2px 0 3px 0;overflow: hidden;font-size: 14px;font-style: normal;font-weight: 400;color: #222f3e;text-transform: normal;background: 0 0;border: 0;border-radius: 3px;outline: 0;box-shadow: none;align-items: center;flex: 0 0 auto;justify-content: center;} + +.tox .tox-tbtn svg{display: block;fill: #222f3e;} + +.tox .tox-tbtn.tox-tbtn-more{width: inherit;padding-right: 5px;padding-left: 5px;} + +.tox .tox-tbtn--enabled{color: #222f3e;background: #c8cbcf;box-shadow: none;} + +.tox .tox-tbtn--enabled>*{transform: none;} + +.tox .tox-tbtn--enabled svg{fill: #222f3e;} + +.tox .tox-tbtn:hover{color: #222f3e;background: #dee0e2;box-shadow: none;} + +.tox .tox-tbtn:hover svg{fill: #222f3e;} + +.tox .tox-tbtn:focus{color: #222f3e;background: #dee0e2;box-shadow: none;} + +.tox .tox-tbtn:focus svg{fill: #222f3e;} + +.tox .tox-tbtn:active{color: #222f3e;background: #c8cbcf;box-shadow: none;} + +.tox .tox-tbtn:active svg{fill: #222f3e;} + +.tox .tox-tbtn--disabled,.tox .tox-tbtn--disabled:hover,.tox .tox-tbtn:disabled,.tox .tox-tbtn:disabled:hover{color: rgba(34,47,62,.5);cursor: not-allowed;background: 0 0;box-shadow: none;} + +.tox .tox-tbtn--disabled svg,.tox .tox-tbtn--disabled:hover svg,.tox .tox-tbtn:disabled svg,.tox .tox-tbtn:disabled:hover svg{fill: rgba(34,47,62,.5);} + +.tox .tox-tbtn:active>*{transform: none;} + +.tox .tox-tbtn--md{width: 51px;height: 51px;} + +.tox .tox-tbtn--lg{width: 68px;height: 68px;flex-direction: column;} + +.tox .tox-tbtn--return{width: 16px;height: unset;align-self: stretch;} + +.tox .tox-tbtn--labeled{width: unset;padding: 0 4px;} + +.tox .tox-tbtn__vlabel{display: block;margin-bottom: 4px;font-size: 10px;font-weight: 400;letter-spacing: -.025em;white-space: nowrap;} + +.tox .tox-tbtn--select{width: auto;padding: 0 4px;margin: 2px 0 3px 0;} + +.tox .tox-tbtn__select-label{margin: 0 4px;font-weight: 400;cursor: default;} + +.tox .tox-tbtn__select-chevron{align-items: center;display: flex;justify-content: center;width: 16px;} + +.tox .tox-tbtn__select-chevron svg{fill: rgba(34,47,62,.7);} + +.tox .tox-tbtn--bespoke .tox-tbtn__select-label{width: 7em;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;} + +.tox .tox-split-button{display: flex;margin: 2px 0 3px 0;overflow: hidden;border: 0;border-radius: 3px;box-sizing: border-box;} + +.tox .tox-split-button:hover{box-shadow: 0 0 0 1px #dee0e2 inset;} + +.tox .tox-split-button:focus{color: #222f3e;background: #dee0e2;box-shadow: none;} + +.tox .tox-split-button>*{border-radius: 0;} + +.tox .tox-split-button__chevron{width: 16px;} + +.tox .tox-split-button__chevron svg{fill: rgba(34,47,62,.7);} + +.tox .tox-pop .tox-split-button__chevron svg{transform: rotate(-90deg);} + +.tox .tox-split-button .tox-tbtn{margin: 0;} + +.tox .tox-split-button.tox-tbtn--disabled .tox-tbtn:focus,.tox .tox-split-button.tox-tbtn--disabled .tox-tbtn:hover,.tox .tox-split-button.tox-tbtn--disabled:focus,.tox .tox-split-button.tox-tbtn--disabled:hover{color: rgba(34,47,62,.5);background: 0 0;box-shadow: none;} + +.tox .tox-toolbar,.tox .tox-toolbar__overflow,.tox .tox-toolbar__primary{display: flex;padding: 0 0;margin-bottom: -1px;background: url("data:image/svg+xml;charset=utf8,%3Csvg height='39px' viewBox='0 0 40 39px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='38px' width='100' height='1' fill='%23cccccc'/%3E%3C/svg%3E") left 0 top 0 #fff;background-color: #fff;border-top: 1px solid #ccc;flex: 0 0 auto;flex-shrink: 0;flex-wrap: wrap;} + +.tox .tox-toolbar__overflow.tox-toolbar__overflow--closed{height: 0;opacity: 0;visibility: hidden;} + +.tox .tox-toolbar__overflow--growing{transition: height .3s ease,opacity .2s linear .1s;} + +.tox .tox-toolbar__overflow--shrinking{transition: opacity .3s ease,height .2s linear .1s,visibility 0s linear .3s;} + +.tox .tox-pop .tox-toolbar{border-width: 0;} + +.tox .tox-toolbar--no-divider{background-image: none;} + +.tox.tox-tinymce-aux .tox-toolbar__overflow{background-color: #fff;border: 1px solid #ccc;border-radius: 3px;box-shadow: 0 1px 3px rgba(0,0,0,.15);} + +.tox.tox-tinymce-aux:not([dir=rtl]) .tox-toolbar__overflow{margin-left: 4px;} + +.tox[dir=rtl] .tox-tbtn__icon-rtl svg{transform: rotateY(180deg);} + +.tox[dir=rtl].tox-tinymce-aux .tox-toolbar__overflow{margin-right: 4px;} + +.tox .tox-toolbar__group{display: flex;padding: 0 4px;margin: 0 0;align-items: center;flex-wrap: wrap;} + +.tox .tox-toolbar__group--pull-right{margin-left: auto;} + +.tox:not([dir=rtl]) .tox-toolbar__group:not(:last-of-type){border-right: 1px solid #ccc;} + +.tox[dir=rtl] .tox-toolbar__group:not(:last-of-type){border-left: 1px solid #ccc;} + +.tox .tox-tooltip{position: relative;display: inline-block;padding: 8px;} + +.tox .tox-tooltip__body{padding: 4px 8px;font-size: 14px;font-style: normal;font-weight: 400;color: rgba(255,255,255,.75);text-transform: normal;background-color: #222f3e;border-radius: 3px;box-shadow: 0 2px 4px rgba(34,47,62,.3);} + +.tox .tox-tooltip__arrow{position: absolute;} + +.tox .tox-tooltip--down .tox-tooltip__arrow{position: absolute;bottom: 0;left: 50%;border-top: 8px solid #222f3e;border-right: 8px solid transparent;border-left: 8px solid transparent;transform: translateX(-50%);} + +.tox .tox-tooltip--up .tox-tooltip__arrow{position: absolute;top: 0;left: 50%;border-right: 8px solid transparent;border-bottom: 8px solid #222f3e;border-left: 8px solid transparent;transform: translateX(-50%);} + +.tox .tox-tooltip--right .tox-tooltip__arrow{position: absolute;top: 50%;right: 0;border-top: 8px solid transparent;border-bottom: 8px solid transparent;border-left: 8px solid #222f3e;transform: translateY(-50%);} + +.tox .tox-tooltip--left .tox-tooltip__arrow{position: absolute;top: 50%;left: 0;border-top: 8px solid transparent;border-right: 8px solid #222f3e;border-bottom: 8px solid transparent;transform: translateY(-50%);} + +.tox .tox-well{width: 100%;padding: 8px;border: 1px solid #ccc;border-radius: 3px;} + +.tox .tox-well>:first-child{margin-top: 0;} + +.tox .tox-well>:last-child{margin-bottom: 0;} + +.tox .tox-well>:only-child{margin: 0;} + +.tox .tox-custom-editor{display: flex;height: 525px;border: 1px solid #ccc;border-radius: 3px;} + +.tox .tox-dialog-loading::before{position: absolute;z-index: 1000;width: 100%;height: 100%;background-color: rgba(0,0,0,.5);content: "";} + +.tox .tox-tab{cursor: pointer;} + +.tox .tox-dialog__content-js{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-content .tox-collection{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox ul{display: block;list-style-type: disc;-webkit-margin-before: 1em;margin-block-start: 1em;-webkit-margin-after: 1em;margin-block-end: 1em;-webkit-margin-start: 0;margin-inline-start: 0;-webkit-margin-end: 0;margin-inline-end: 0;-webkit-padding-start: 40px;padding-inline-start: 40px;} + +.tox a{color: #2276d2;cursor: pointer;} + +.tox .tox-image-tools-edit-panel{height: 60px;} + +.tox .tox-image-tools__sidebar{height: 60px;} diff --git a/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/skin.mobile.min.css b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/skin.mobile.min.css new file mode 100644 index 0000000000000000000000000000000000000000..14847d0a2d319e16205b0258b43c0271b5a9d220 --- /dev/null +++ b/demo/webman/backend/plugin/admin/public/resource/tinymce/skins/ui/oxide/skin.mobile.min.css @@ -0,0 +1,239 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tinymce-mobile-outer-container{all: initial;display: block;} + +.tinymce-mobile-outer-container *{float: none;padding: 0;margin: 0;line-height: 1;text-shadow: none;white-space: nowrap;cursor: inherit;border: 0;outline: 0;box-sizing: initial;-webkit-tap-highlight-color: transparent;} + +.tinymce-mobile-icon-arrow-back::before{content: "\e5cd";} + +.tinymce-mobile-icon-image::before{content: "\e412";} + +.tinymce-mobile-icon-cancel-circle::before{content: "\e5c9";} + +.tinymce-mobile-icon-full-dot::before{content: "\e061";} + +.tinymce-mobile-icon-align-center::before{content: "\e234";} + +.tinymce-mobile-icon-align-left::before{content: "\e236";} + +.tinymce-mobile-icon-align-right::before{content: "\e237";} + +.tinymce-mobile-icon-bold::before{content: "\e238";} + +.tinymce-mobile-icon-italic::before{content: "\e23f";} + +.tinymce-mobile-icon-unordered-list::before{content: "\e241";} + +.tinymce-mobile-icon-ordered-list::before{content: "\e242";} + +.tinymce-mobile-icon-font-size::before{content: "\e245";} + +.tinymce-mobile-icon-underline::before{content: "\e249";} + +.tinymce-mobile-icon-link::before{content: "\e157";} + +.tinymce-mobile-icon-unlink::before{content: "\eca2";} + +.tinymce-mobile-icon-color::before{content: "\e891";} + +.tinymce-mobile-icon-previous::before{content: "\e314";} + +.tinymce-mobile-icon-next::before{content: "\e315";} + +.tinymce-mobile-icon-large-font::before,.tinymce-mobile-icon-style-formats::before{content: "\e264";} + +.tinymce-mobile-icon-undo::before{content: "\e166";} + +.tinymce-mobile-icon-redo::before{content: "\e15a";} + +.tinymce-mobile-icon-removeformat::before{content: "\e239";} + +.tinymce-mobile-icon-small-font::before{content: "\e906";} + +.tinymce-mobile-format-matches::after,.tinymce-mobile-icon-readonly-back::before{content: "\e5ca";} + +.tinymce-mobile-icon-small-heading::before{content: "small";} + +.tinymce-mobile-icon-large-heading::before{content: "large";} + +.tinymce-mobile-icon-large-heading::before,.tinymce-mobile-icon-small-heading::before{font-family: sans-serif;font-size: 80%;} + +.tinymce-mobile-mask-edit-icon::before{content: "\e254";} + +.tinymce-mobile-icon-back::before{content: "\e5c4";} + +.tinymce-mobile-icon-heading::before{font-family: sans-serif;font-size: 80%;font-weight: 700;content: "Headings";} + +.tinymce-mobile-icon-h1::before{font-weight: 700;content: "H1";} + +.tinymce-mobile-icon-h2::before{font-weight: 700;content: "H2";} + +.tinymce-mobile-icon-h3::before{font-weight: 700;content: "H3";} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask{position: absolute;top: 0;display: flex;width: 100%;height: 100%;background: rgba(51,51,51,.5);align-items: center;justify-content: center;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container{display: flex;font-family: sans-serif;font-size: 1em;border-radius: 50%;align-items: center;flex-direction: column;justify-content: space-between;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .mixin-menu-item{display: flex;width: 2.1em;height: 2.1em;border-radius: 50%;align-items: center;justify-content: center;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{align-items: center;display: flex;justify-content: center;flex-direction: column;font-size: 1em;}@media only screen and (min-device-width: 700px){.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{font-size: 1.2em;}} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon{display: flex;width: 2.1em;height: 2.1em;color: #207ab7;background-color: #fff;border-radius: 50%;align-items: center;justify-content: center;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon::before{font-family: tinymce-mobile,sans-serif;content: "\e900";} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section:not(.tinymce-mobile-mask-tap-icon-selected) .tinymce-mobile-mask-tap-icon{z-index: 2;} + +.tinymce-mobile-android-container.tinymce-mobile-android-maximized{position: fixed;top: 0;right: 0;bottom: 0;left: 0;display: flex;background: #fff;border: none;flex-direction: column;} + +.tinymce-mobile-android-container:not(.tinymce-mobile-android-maximized){position: relative;} + +.tinymce-mobile-android-container .tinymce-mobile-editor-socket{display: flex;flex-grow: 1;} + +.tinymce-mobile-android-container .tinymce-mobile-editor-socket iframe{display: flex !important;flex-grow: 1;height: auto !important;} + +.tinymce-mobile-android-scroll-reload{overflow: hidden;} + +:not(.tinymce-mobile-readonly-mode)>.tinymce-mobile-android-selection-context-toolbar{margin-top: 23px;} + +.tinymce-mobile-toolstrip{z-index: 1;display: flex;background: #fff;flex: 0 0 auto;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar{display: flex;width: 100%;height: 2.5em;background-color: #fff;border-bottom: 1px solid #ccc;align-items: center;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group{align-items: center;display: flex;height: 100%;flex-shrink: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group>div{align-items: center;display: flex;height: 100%;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-exit-container{background: #f44336;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-toolbar-scrollable-group{flex-grow: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{padding-right: .5em;padding-left: .5em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button{display: flex;height: 80%;margin-right: 2px;margin-left: 2px;align-items: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button.tinymce-mobile-toolbar-button-selected{color: #ccc;background: #c8cbcf;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:first-of-type,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:last-of-type{color: #eceff1;background: #207ab7;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group{display: flex;height: 100%;padding-top: .4em;padding-bottom: .4em;align-items: center;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog{position: relative;display: flex;width: 100%;min-height: 1.5em;padding-right: 0;padding-left: 0;overflow: hidden;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain{display: flex;width: 100%;height: 100%;transition: left cubic-bezier(.4,0,1,1) .15s;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen{display: flex;flex: 0 0 auto;justify-content: space-between;width: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen input{font-family: sans-serif;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container{position: relative;display: flex;flex-grow: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container .tinymce-mobile-input-container-x{position: absolute;right: 0;height: 100%;padding-right: 2px;font-size: .6em;font-weight: 700;color: #888;background: inherit;border: none;border-radius: 50%;align-self: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container.tinymce-mobile-input-container-empty .tinymce-mobile-input-container-x{display: none;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous{align-items: center;display: flex;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous::before{display: flex;height: 100%;padding-right: .5em;padding-left: .5em;font-weight: 700;align-items: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next.tinymce-mobile-toolbar-navigation-disabled::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous.tinymce-mobile-toolbar-navigation-disabled::before{visibility: hidden;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item{padding-top: 3px;margin: 0 2px;font-size: 10px;line-height: 10px;color: #ccc;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item.tinymce-mobile-dot-active{color: #c8cbcf;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-heading::before{margin-right: .9em;margin-left: .5em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-heading::before{margin-right: .5em;margin-left: .9em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider{position: relative;display: flex;padding: .28em 0;margin-right: 0;margin-left: 0;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container{align-items: center;display: flex;flex-grow: 1;height: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container .tinymce-mobile-slider-size-line{display: flex;height: .2em;margin-top: .3em;margin-bottom: .3em;background: #ccc;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container{padding-right: 2em;padding-left: 2em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container{align-items: center;display: flex;flex-grow: 1;height: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container .tinymce-mobile-slider-gradient{display: flex;height: .2em;margin-top: .3em;margin-bottom: .3em;background: linear-gradient(to right,red 0,#feff00 17%,#0f0 33%,#00feff 50%,#00f 67%,#ff00fe 83%,red 100%);flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-black{width: 1.2em;height: .2em;margin-top: .3em;margin-bottom: .3em;background: #000;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-white{width: 1.2em;height: .2em;margin-top: .3em;margin-bottom: .3em;background: #fff;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb{position: absolute;top: 0;bottom: 0;left: -10px;display: flex;width: .5em;height: .5em;margin: auto;color: #fff;background-color: #455a64;border: .5em solid rgba(136,136,136,0);border-radius: 3em;transition: border 120ms cubic-bezier(.39,.58,.57,1);background-clip: padding-box;align-items: center;justify-content: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb.tinymce-mobile-thumb-active{border: .5em solid rgba(136,136,136,.39);} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group>div{align-items: center;display: flex;height: 100%;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper{flex-direction: column;justify-content: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{align-items: center;display: flex;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item:not(.tinymce-mobile-serialised-dialog){height: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-container{display: flex;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input{padding-top: .1em;padding-bottom: .1em;padding-left: 5px;font-size: .85em;color: #455a64;background: #fff;border: none;border-radius: 0;flex-grow: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::-webkit-input-placeholder{color: #888;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::placeholder{color: #888;} + +.tinymce-mobile-dropup{display: flex;width: 100%;overflow: hidden;background: #fff;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-shrinking{transition: height .3s ease-out;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-growing{transition: height .3s ease-in;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-closed{flex-grow: 0;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-open:not(.tinymce-mobile-dropup-growing){flex-grow: 1;} + +.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height: 200px;}@media only screen and (orientation: landscape){.tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height: 200px;}}@media only screen and (min-device-width: 320px) and (max-device-width: 568px) and (orientation: landscape){.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height: 150px;}} + +.tinymce-mobile-styles-menu{position: relative;width: 100%;overflow: hidden;font-family: sans-serif;outline: 4px solid #000;} + +.tinymce-mobile-styles-menu [role=menu]{position: absolute;display: flex;width: 100%;height: 100%;flex-direction: column;} + +.tinymce-mobile-styles-menu [role=menu].transitioning{transition: transform .5s ease-in-out;} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-item{position: relative;display: flex;padding: 1em 1em;color: #455a64;cursor: pointer;border-bottom: 1px solid #ddd;} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser .tinymce-mobile-styles-collapse-icon::before{font-family: tinymce-mobile,sans-serif;color: #455a64;content: "\e314";} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-styles-item-is-menu::after{position: absolute;right: 0;padding-right: 1em;padding-left: 1em;font-family: tinymce-mobile,sans-serif;color: #455a64;content: "\e315";} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-format-matches::after{position: absolute;right: 0;padding-right: 1em;padding-left: 1em;font-family: tinymce-mobile,sans-serif;} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser,.tinymce-mobile-styles-menu .tinymce-mobile-styles-separator{display: flex;min-height: 2.5em;padding-right: 1em;padding-left: 1em;color: #455a64;background: #fff;border-top: #455a64;align-items: center;} + +.tinymce-mobile-styles-menu [data-transitioning-destination=before][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=before]{transform: translate(-100%);} + +.tinymce-mobile-styles-menu [data-transitioning-destination=current][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=current]{transform: translate(0);} + +.tinymce-mobile-styles-menu [data-transitioning-destination=after][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=after]{transform: translate(100%);}@font-face{font-family: tinymce-mobile;font-style: normal;font-weight: 400;src: url(fonts/tinymce-mobile.woff?8x92w3) format('woff');}@media (min-device-width: 700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size: 25px;}}@media (max-device-width: 700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size: 18px;}} + +.tinymce-mobile-icon{font-family: tinymce-mobile,sans-serif;} + +.mixin-flex-and-centre{align-items: center;display: flex;justify-content: center;} + +.mixin-flex-bar{align-items: center;display: flex;height: 100%;} + +.tinymce-mobile-outer-container .tinymce-mobile-editor-socket iframe{width: 100%;background-color: #fff;} + +.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{position: fixed;right: 2em;bottom: 1em;display: flex;width: 2.1em;height: 2.1em;font-size: 1em;color: #fff;background-color: #207ab7;border-radius: 50%;align-items: center;justify-content: center;}@media only screen and (min-device-width: 700px){.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{font-size: 1.2em;}} + +.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket{height: 300px;overflow: hidden;} + +.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket iframe{height: 100%;} + +.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-toolstrip{display: none;} + +input[type=file]::-webkit-file-upload-button{display: none;}@media only screen and (min-device-width: 320px) and (max-device-width: 568px) and (orientation: landscape){.tinymce-mobile-ios-container .tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{bottom: 50%;}} diff --git a/demo/webman/backend/process/Monitor.php b/demo/webman/backend/process/Monitor.php new file mode 100644 index 0000000000000000000000000000000000000000..92b371643ac4d971c733146d507d66503426d086 --- /dev/null +++ b/demo/webman/backend/process/Monitor.php @@ -0,0 +1,243 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace process; + +use FilesystemIterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use SplFileInfo; +use Workerman\Timer; +use Workerman\Worker; + +/** + * Class FileMonitor + * @package process + */ +class Monitor +{ + /** + * @var array + */ + protected $paths = []; + + /** + * @var array + */ + protected $extensions = []; + + /** + * @var string + */ + public static $lockFile = __DIR__ . '/../runtime/monitor.lock'; + + /** + * Pause monitor + * @return void + */ + public static function pause() + { + file_put_contents(static::$lockFile, time()); + } + + /** + * Resume monitor + * @return void + */ + public static function resume(): void + { + clearstatcache(); + if (is_file(static::$lockFile)) { + unlink(static::$lockFile); + } + } + + /** + * Whether monitor is paused + * @return bool + */ + public static function isPaused(): bool + { + clearstatcache(); + return file_exists(static::$lockFile); + } + + /** + * FileMonitor constructor. + * @param $monitorDir + * @param $monitorExtensions + * @param array $options + */ + public function __construct($monitorDir, $monitorExtensions, array $options = []) + { + static::resume(); + $this->paths = (array)$monitorDir; + $this->extensions = $monitorExtensions; + if (!Worker::getAllWorkers()) { + return; + } + $disableFunctions = explode(',', ini_get('disable_functions')); + if (in_array('exec', $disableFunctions, true)) { + echo "\nMonitor file change turned off because exec() has been disabled by disable_functions setting in " . PHP_CONFIG_FILE_PATH . "/php.ini\n"; + } else { + if ($options['enable_file_monitor'] ?? true) { + Timer::add(1, function () { + $this->checkAllFilesChange(); + }); + } + } + + $memoryLimit = $this->getMemoryLimit($options['memory_limit'] ?? null); + if ($memoryLimit && ($options['enable_memory_monitor'] ?? true)) { + Timer::add(60, [$this, 'checkMemory'], [$memoryLimit]); + } + } + + /** + * @param $monitorDir + * @return bool + */ + public function checkFilesChange($monitorDir): bool + { + static $lastMtime, $tooManyFilesCheck; + if (!$lastMtime) { + $lastMtime = time(); + } + clearstatcache(); + if (!is_dir($monitorDir)) { + if (!is_file($monitorDir)) { + return false; + } + $iterator = [new SplFileInfo($monitorDir)]; + } else { + // recursive traversal directory + $dirIterator = new RecursiveDirectoryIterator($monitorDir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS); + $iterator = new RecursiveIteratorIterator($dirIterator); + } + $count = 0; + foreach ($iterator as $file) { + $count ++; + /** var SplFileInfo $file */ + if (is_dir($file->getRealPath())) { + continue; + } + // check mtime + if (in_array($file->getExtension(), $this->extensions, true) && $lastMtime < $file->getMTime()) { + $var = 0; + exec('"'.PHP_BINARY . '" -l ' . $file, $out, $var); + $lastMtime = $file->getMTime(); + if ($var) { + continue; + } + echo $file . " update and reload\n"; + // send SIGUSR1 signal to master process for reload + if (DIRECTORY_SEPARATOR === '/') { + posix_kill(posix_getppid(), SIGUSR1); + } else { + return true; + } + break; + } + } + if (!$tooManyFilesCheck && $count > 1000) { + echo "Monitor: There are too many files ($count files) in $monitorDir which makes file monitoring very slow\n"; + $tooManyFilesCheck = 1; + } + return false; + } + + /** + * @return bool + */ + public function checkAllFilesChange(): bool + { + if (static::isPaused()) { + return false; + } + foreach ($this->paths as $path) { + if ($this->checkFilesChange($path)) { + return true; + } + } + return false; + } + + /** + * @param $memoryLimit + * @return void + */ + public function checkMemory($memoryLimit) + { + if (static::isPaused() || $memoryLimit <= 0) { + return; + } + $ppid = posix_getppid(); + $childrenFile = "/proc/$ppid/task/$ppid/children"; + if (!is_file($childrenFile) || !($children = file_get_contents($childrenFile))) { + return; + } + foreach (explode(' ', $children) as $pid) { + $pid = (int)$pid; + $statusFile = "/proc/$pid/status"; + if (!is_file($statusFile) || !($status = file_get_contents($statusFile))) { + continue; + } + $mem = 0; + if (preg_match('/VmRSS\s*?:\s*?(\d+?)\s*?kB/', $status, $match)) { + $mem = $match[1]; + } + $mem = (int)($mem / 1024); + if ($mem >= $memoryLimit) { + posix_kill($pid, SIGINT); + } + } + } + + /** + * Get memory limit + * @return float + */ + protected function getMemoryLimit($memoryLimit) + { + if ($memoryLimit === 0) { + return 0; + } + $usePhpIni = false; + if (!$memoryLimit) { + $memoryLimit = ini_get('memory_limit'); + $usePhpIni = true; + } + + if ($memoryLimit == -1) { + return 0; + } + $unit = strtolower($memoryLimit[strlen($memoryLimit) - 1]); + if ($unit === 'g') { + $memoryLimit = 1024 * (int)$memoryLimit; + } else if ($unit === 'm') { + $memoryLimit = (int)$memoryLimit; + } else if ($unit === 'k') { + $memoryLimit = ((int)$memoryLimit / 1024); + } else { + $memoryLimit = ((int)$memoryLimit / (1024 * 1024)); + } + if ($memoryLimit < 30) { + $memoryLimit = 30; + } + if ($usePhpIni) { + $memoryLimit = (int)(0.8 * $memoryLimit); + } + return $memoryLimit; + } +} diff --git a/demo/webman/backend/public/404.html b/demo/webman/backend/public/404.html new file mode 100644 index 0000000000000000000000000000000000000000..2bde119b9f9464d92e606426ded384bc5cd1daed --- /dev/null +++ b/demo/webman/backend/public/404.html @@ -0,0 +1,12 @@ + + + 404 Not Found - webman + + +
                                                                                                  +

                                                                                                  404 Not Found

                                                                                                  +
                                                                                                  +
                                                                                                  +
                                                                                                  webman
                                                                                                  + + diff --git a/demo/webman/backend/public/favicon.ico b/demo/webman/backend/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b9f722e0eeed8dc7f3639bd3295a7b0376b98eca Binary files /dev/null and b/demo/webman/backend/public/favicon.ico differ diff --git a/demo/webman/backend/start.php b/demo/webman/backend/start.php new file mode 100644 index 0000000000000000000000000000000000000000..489e4470a5278bbd892e8fc14fb64a247767e0fe --- /dev/null +++ b/demo/webman/backend/start.php @@ -0,0 +1,4 @@ +#!/usr/bin/env php + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +use Spatie\Macroable\Macroable; + +/** + * Class Request + * + * @package support + */ +class Request extends \Webman\Http\Request +{ + + use Macroable; + + /** + * 不过滤变量名 + * + * @var array + */ + protected array $except = ['menu_path', 'api_url', 'unique_auth', 'description', 'custom_form', 'content']; + + /** + * 获取请求的数据 + * + * @param array $params + * @param bool $suffix + * @param bool $filter + * + * @return array + */ + public function more(array $params, bool $suffix = false, bool $filter = true): array + { + $p = []; + $i = 0; + foreach ($params as $param) { + if (!is_array($param)) { + $p[$suffix == true ? $i++ : $param] = $this->filterWord(is_string($this->input($param)) ? trim($this->input($param)) : $this->input($param), $filter && !in_array($param, $this->except)); + } else { + if (!isset($param[1])) $param[1] = null; + if (!isset($param[2])) $param[2] = ''; + if (is_array($param[0])) { + $name = is_array($param[1]) ? $param[0][0] . '/a' : $param[0][0] . '/' . $param[0][1]; + $keyName = $param[0][0]; + } else { + $name = is_array($param[1]) ? $param[0] . '/a' : $param[0]; + $keyName = $param[0]; + } + $p[$suffix == true ? $i++ : ($param[3] ?? $keyName)] = $this->filterWord(is_string($this->input($name, $param[1], $param[2])) ? trim($this->input($name, $param[1], $param[2])) : $this->input($name, $param[1], $param[2]), $filter && !in_array($keyName, $this->except)); + } + } + return $p; + } + + /** + * 过滤接受的参数 + * + * @param $str + * @param bool $filter + * + * @return array|mixed|string|string[] + */ + public function filterWord($str, bool $filter = true) + { + if (!$str || !$filter) return $str; + // 把数据过滤 + $farr = [ + "/<(\\/?)(script|i?frame|style|html|body|title|link|meta|object|\\?|\\%)([^>]*?)>/isU", + "/(<[^>]*)on[a-zA-Z]+\s*=([^>]*>)/isU", + '/phar/is', + "/select|join|where|drop|like|modify|rename|insert|update|table|database|alter|truncate|\'|\/\*|\.\.\/|\.\/|union|into|load_file|outfile/is", + ]; + if (is_array($str)) { + foreach ($str as &$v) { + if (is_array($v)) { + foreach ($v as &$vv) { + if (!is_array($vv)) $vv = preg_replace($farr, '', $vv); + } + } else { + $v = preg_replace($farr, '', $v); + } + } + } else { + $str = preg_replace($farr, '', $str); + } + return $str; + } + + /** + * 获取get参数 + * + * @param array $params + * @param bool $suffix + * @param bool $filter + * + * @return array + */ + public function getMore(array $params, bool $suffix = false, bool $filter = true): array + { + return $this->more($params, $suffix, $filter); + } + + /** + * 获取post参数 + * + * @param array $params + * @param bool $suffix + * @param bool $filter + * + * @return array + */ + public function postMore(array $params, bool $suffix = false, bool $filter = true): array + { + return $this->more($params, $suffix, $filter); + } + + /** + * 获取请求的数据 + * 获取额外参数和值; + *   type为 1、2 表示 索引数组(1为 Value 的一维数组,2为key、Value的二维数组),0表示 关联数组 + * 每条数据组成: + * 数组/字符串 + * 如果是数组: + * $param[0]:要获取的Key + * 可以为数组:0为key,1为变量修饰符 + * $param[1]:默认值;!!!注意,如果默认值为数组,则这个项的值也会转为数组(索引)!!! + * $param[2]:过滤函数 + * $param[3]:替换的新key + * 已修改为:如果没有 $param 且没有缺省值,则跳过这个; + * 感觉还可以修改 变量修饰符 那部分(去掉 增加变量修饰) + * 返回: + * 索引:二维数组:[[key, 值], [key, 值]。。。],适用于where + * 一维数组[值, 值, 。。。] + * 关联:一维关联数组 + * + * @param array $params + * @param int $type + * + * @return array + */ + public function getParams(array $params, int $type = 0): array + { + $p = []; + $i = 0; + foreach ($params as $param) { + if (!is_array($param)) //如果不是数组 + { + //原来的索引数组没有key + //$p[$suffix == true ? $i++ : $param] = $this->input($param); + if ($type == 0) + $p[$param] = $this->input($param); + else if ($type == 1) + $p[$i++] = $this->input($param); + else { + //修改为 [key, 值] + $p[$i++] = [$param, $this->input($param)]; + } + } else { + //if (!isset($param[1])) $param[1] = null; + if (!isset($param[2])) $param[2] = ''; + if (is_array($param[0])) //如果是数组 + { + if (!array_key_exists('1', $param)) //如果没有默认值 + { + if (!$this->has($param[0][0])) //如果request中没有 + continue; + + $param[1] = null; + } + + //如果默认值为数组,则给param加上变量修饰符(/a);否则手动连接修饰符 + $name = is_array($param[1]) ? $param[0][0] . '/a' : $param[0][0] . '/' . $param[0][1]; + $keyName = $param[0][0]; + } else { + if (!array_key_exists('1', $param)) //如果没有默认值 + { + if (!$this->has($param[0])) //如果request中没有 + continue; + + $param[1] = null; + } + + //如果默认值为数组,则给param加上变量修饰符(/a) + $name = is_array($param[1]) ? $param[0] . '/a' : $param[0]; + $keyName = $param[0]; + } + + //原来的索引数组没有key + //$p[$suffix == true ? $i++ : (isset($param[3]) ? $param[3] : $keyName)] = $this->input($name, $param[1], $param[2]); + if ($type == 0) + $p[(isset($param[3]) ? $param[3] : $keyName)] = $this->input($name, $param[1], $param[2]); + else if ($type == 1) + $p[$i++] = $this->input($name, $param[1], $param[2]); + else { + //修改为 [key, 值] + $p[$i++] = [isset($param[3]) ? $param[3] : $keyName, $this->input($name, $param[1], $param[2])]; + } + } + } + return $p; + } + + /** + * 获取用户访问端 + * + * @return array|string|null + */ + public function getFromType() + { + return $this->header('Form-type', ''); + } + + /** + * 当前访问端 + * + * @param string $terminal + * + * @return bool + */ + public function isTerminal(string $terminal) + { + return strtolower($this->getFromType()) === $terminal; + } + + /** + * 是否是H5端 + * + * @return bool + */ + public function isH5() + { + return $this->isTerminal('h5'); + } + + /** + * 是否是微信端 + * + * @return bool + */ + public function isWechat() + { + return $this->isTerminal('wechat'); + } + + /** + * 是否是小程序端 + * + * @return bool + */ + public function isRoutine() + { + return $this->isTerminal('routine'); + } + + /** + * 是否是app端 + * + * @return bool + */ + public function isApp() + { + return $this->isTerminal('app'); + } + + /** + * 是否是app端 + * + * @return bool + */ + public function isPc() + { + return $this->isTerminal('pc'); + } + +} \ No newline at end of file diff --git a/demo/webman/backend/support/Response.php b/demo/webman/backend/support/Response.php new file mode 100644 index 0000000000000000000000000000000000000000..9bc4e1eb4ee4aa754f0cbca967b75d776567cecd --- /dev/null +++ b/demo/webman/backend/support/Response.php @@ -0,0 +1,24 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +/** + * Class Response + * @package support + */ +class Response extends \Webman\Http\Response +{ + +} \ No newline at end of file diff --git a/demo/webman/backend/support/bootstrap.php b/demo/webman/backend/support/bootstrap.php new file mode 100644 index 0000000000000000000000000000000000000000..d9471e6abca73cc25df84b8083ecfd54f85fcd8f --- /dev/null +++ b/demo/webman/backend/support/bootstrap.php @@ -0,0 +1,133 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use Dotenv\Dotenv; +use support\Log; +use Webman\Bootstrap; +use Webman\Config; +use Webman\Middleware; +use Webman\Route; +use Webman\Util; + +$worker = $worker ?? null; + +set_error_handler(function ($level, $message, $file = '', $line = 0) { + if (error_reporting() & $level) { + throw new ErrorException($message, 0, $level, $file, $line); + } +}); + +if ($worker) { + register_shutdown_function(function ($startTime) { + if (time() - $startTime <= 0.1) { + sleep(1); + } + }, time()); +} + +if (class_exists('Dotenv\Dotenv') && file_exists(base_path(false) . '/.env')) { + if (method_exists('Dotenv\Dotenv', 'createUnsafeMutable')) { + Dotenv::createUnsafeMutable(base_path(false))->load(); + } else { + Dotenv::createMutable(base_path(false))->load(); + } +} + +Config::clear(); +support\App::loadAllConfig(['route']); +if ($timezone = config('app.default_timezone')) { + date_default_timezone_set($timezone); +} + +foreach (config('autoload.files', []) as $file) { + include_once $file; +} +foreach (config('plugin', []) as $firm => $projects) { + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['autoload']['files'] ?? [] as $file) { + include_once $file; + } + } + foreach ($projects['autoload']['files'] ?? [] as $file) { + include_once $file; + } +} + +Middleware::load(config('middleware', [])); +foreach (config('plugin', []) as $firm => $projects) { + foreach ($projects as $name => $project) { + if (!is_array($project) || $name === 'static') { + continue; + } + Middleware::load($project['middleware'] ?? []); + } + Middleware::load($projects['middleware'] ?? [], $firm); + if ($staticMiddlewares = config("plugin.$firm.static.middleware")) { + Middleware::load(['__static__' => $staticMiddlewares], $firm); + } +} +Middleware::load(['__static__' => config('static.middleware', [])]); + +foreach (config('bootstrap', []) as $className) { + if (!class_exists($className)) { + $log = "Warning: Class $className setting in config/bootstrap.php not found\r\n"; + echo $log; + Log::error($log); + continue; + } + /** @var Bootstrap $className */ + $className::start($worker); +} + +foreach (config('plugin', []) as $firm => $projects) { + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['bootstrap'] ?? [] as $className) { + if (!class_exists($className)) { + $log = "Warning: Class $className setting in config/plugin/$firm/$name/bootstrap.php not found\r\n"; + echo $log; + Log::error($log); + continue; + } + /** @var Bootstrap $className */ + $className::start($worker); + } + } + foreach ($projects['bootstrap'] ?? [] as $className) { + /** @var string $className */ + if (!class_exists($className)) { + $log = "Warning: Class $className setting in plugin/$firm/config/bootstrap.php not found\r\n"; + echo $log; + Log::error($log); + continue; + } + /** @var Bootstrap $className */ + $className::start($worker); + } +} + +$directory = base_path() . '/plugin'; +$paths = [config_path()]; +foreach (Util::scanDir($directory) as $path) { + if (is_dir($path = "$path/config")) { + $paths[] = $path; + } +} +Route::load($paths); + diff --git a/demo/webman/backend/support/helpers.php b/demo/webman/backend/support/helpers.php new file mode 100644 index 0000000000000000000000000000000000000000..8de22c00cf64932eb56ccb15e9da4141d062e324 --- /dev/null +++ b/demo/webman/backend/support/helpers.php @@ -0,0 +1,528 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use support\Container; +use support\Request; +use support\Response; +use support\Translation; +use support\view\Blade; +use support\view\Raw; +use support\view\ThinkPHP; +use support\view\Twig; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Error\SyntaxError; +use Webman\App; +use Webman\Config; +use Webman\Route; +use Workerman\Protocols\Http\Session; +use Workerman\Worker; + +// Project base path +define('BASE_PATH', dirname(__DIR__)); + +/** + * return the program execute directory + * @param string $path + * @return string + */ +function run_path(string $path = ''): string +{ + static $runPath = ''; + if (!$runPath) { + $runPath = is_phar() ? dirname(Phar::running(false)) : BASE_PATH; + } + return path_combine($runPath, $path); +} + +/** + * if the param $path equal false,will return this program current execute directory + * @param string|false $path + * @return string + */ +function base_path($path = ''): string +{ + if (false === $path) { + return run_path(); + } + return path_combine(BASE_PATH, $path); +} + +/** + * App path + * @param string $path + * @return string + */ +function app_path(string $path = ''): string +{ + return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'app', $path); +} + +/** + * Public path + * @param string $path + * @return string + */ +function public_path(string $path = ''): string +{ + static $publicPath = ''; + if (!$publicPath) { + $publicPath = \config('app.public_path') ?: run_path('public'); + } + return path_combine($publicPath, $path); +} + +/** + * Config path + * @param string $path + * @return string + */ +function config_path(string $path = ''): string +{ + return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'config', $path); +} + +/** + * Runtime path + * @param string $path + * @return string + */ +function runtime_path(string $path = ''): string +{ + static $runtimePath = ''; + if (!$runtimePath) { + $runtimePath = \config('app.runtime_path') ?: run_path('runtime'); + } + return path_combine($runtimePath, $path); +} + +/** + * Generate paths based on given information + * @param string $front + * @param string $back + * @return string + */ +function path_combine(string $front, string $back): string +{ + return $front . ($back ? (DIRECTORY_SEPARATOR . ltrim($back, DIRECTORY_SEPARATOR)) : $back); +} + +/** + * Response + * @param int $status + * @param array $headers + * @param string $body + * @return Response + */ +function response(string $body = '', int $status = 200, array $headers = []): Response +{ + return new Response($status, $headers, $body); +} + +/** + * Json response + * @param $data + * @param int $options + * @return Response + */ +function json($data, int $options = JSON_UNESCAPED_UNICODE): Response +{ + return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options)); +} + +/** + * Xml response + * @param $xml + * @return Response + */ +function xml($xml): Response +{ + if ($xml instanceof SimpleXMLElement) { + $xml = $xml->asXML(); + } + return new Response(200, ['Content-Type' => 'text/xml'], $xml); +} + +/** + * Jsonp response + * @param $data + * @param string $callbackName + * @return Response + */ +function jsonp($data, string $callbackName = 'callback'): Response +{ + if (!is_scalar($data) && null !== $data) { + $data = json_encode($data); + } + return new Response(200, [], "$callbackName($data)"); +} + +/** + * Redirect response + * @param string $location + * @param int $status + * @param array $headers + * @return Response + */ +function redirect(string $location, int $status = 302, array $headers = []): Response +{ + $response = new Response($status, ['Location' => $location]); + if (!empty($headers)) { + $response->withHeaders($headers); + } + return $response; +} + +/** + * View response + * @param string $template + * @param array $vars + * @param string|null $app + * @param string|null $plugin + * @return Response + */ +function view(string $template, array $vars = [], string $app = null, string $plugin = null): Response +{ + $request = \request(); + $plugin = $plugin === null ? ($request->plugin ?? '') : $plugin; + $handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler'); + return new Response(200, [], $handler::render($template, $vars, $app, $plugin)); +} + +/** + * Raw view response + * @param string $template + * @param array $vars + * @param string|null $app + * @return Response + * @throws Throwable + */ +function raw_view(string $template, array $vars = [], string $app = null): Response +{ + return new Response(200, [], Raw::render($template, $vars, $app)); +} + +/** + * Blade view response + * @param string $template + * @param array $vars + * @param string|null $app + * @return Response + */ +function blade_view(string $template, array $vars = [], string $app = null): Response +{ + return new Response(200, [], Blade::render($template, $vars, $app)); +} + +/** + * Think view response + * @param string $template + * @param array $vars + * @param string|null $app + * @return Response + */ +function think_view(string $template, array $vars = [], string $app = null): Response +{ + return new Response(200, [], ThinkPHP::render($template, $vars, $app)); +} + +/** + * Twig view response + * @param string $template + * @param array $vars + * @param string|null $app + * @return Response + * @throws LoaderError + * @throws RuntimeError + * @throws SyntaxError + */ +function twig_view(string $template, array $vars = [], string $app = null): Response +{ + return new Response(200, [], Twig::render($template, $vars, $app)); +} + +/** + * Get request + * @return \Webman\Http\Request|Request|null + */ +function request() +{ + return App::request(); +} + +/** + * Get config + * @param string|null $key + * @param $default + * @return array|mixed|null + */ +function config(string $key = null, $default = null) +{ + return Config::get($key, $default); +} + +/** + * Create url + * @param string $name + * @param ...$parameters + * @return string + */ +function route(string $name, ...$parameters): string +{ + $route = Route::getByName($name); + if (!$route) { + return ''; + } + + if (!$parameters) { + return $route->url(); + } + + if (is_array(current($parameters))) { + $parameters = current($parameters); + } + + return $route->url($parameters); +} + +/** + * Session + * @param mixed $key + * @param mixed $default + * @return mixed|bool|Session + */ +function session($key = null, $default = null) +{ + $session = \request()->session(); + if (null === $key) { + return $session; + } + if (is_array($key)) { + $session->put($key); + return null; + } + if (strpos($key, '.')) { + $keyArray = explode('.', $key); + $value = $session->all(); + foreach ($keyArray as $index) { + if (!isset($value[$index])) { + return $default; + } + $value = $value[$index]; + } + return $value; + } + return $session->get($key, $default); +} + +/** + * Translation + * @param string $id + * @param array $parameters + * @param string|null $domain + * @param string|null $locale + * @return string + */ +function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string +{ + $res = Translation::trans($id, $parameters, $domain, $locale); + return $res === '' ? $id : $res; +} + +/** + * Locale + * @param string|null $locale + * @return string + */ +function locale(string $locale = null): string +{ + if (!$locale) { + return Translation::getLocale(); + } + Translation::setLocale($locale); + return $locale; +} + +/** + * 404 not found + * @return Response + */ +function not_found(): Response +{ + return new Response(404, [], file_get_contents(public_path() . '/404.html')); +} + +/** + * Copy dir + * @param string $source + * @param string $dest + * @param bool $overwrite + * @return void + */ +function copy_dir(string $source, string $dest, bool $overwrite = false) +{ + if (is_dir($source)) { + if (!is_dir($dest)) { + mkdir($dest); + } + $files = scandir($source); + foreach ($files as $file) { + if ($file !== "." && $file !== "..") { + copy_dir("$source/$file", "$dest/$file", $overwrite); + } + } + } else if (file_exists($source) && ($overwrite || !file_exists($dest))) { + copy($source, $dest); + } +} + +/** + * Remove dir + * @param string $dir + * @return bool + */ +function remove_dir(string $dir): bool +{ + if (is_link($dir) || is_file($dir)) { + return unlink($dir); + } + $files = array_diff(scandir($dir), array('.', '..')); + foreach ($files as $file) { + (is_dir("$dir/$file") && !is_link($dir)) ? remove_dir("$dir/$file") : unlink("$dir/$file"); + } + return rmdir($dir); +} + +/** + * Bind worker + * @param $worker + * @param $class + */ +function worker_bind($worker, $class) +{ + $callbackMap = [ + 'onConnect', + 'onMessage', + 'onClose', + 'onError', + 'onBufferFull', + 'onBufferDrain', + 'onWorkerStop', + 'onWebSocketConnect', + 'onWorkerReload' + ]; + foreach ($callbackMap as $name) { + if (method_exists($class, $name)) { + $worker->$name = [$class, $name]; + } + } + if (method_exists($class, 'onWorkerStart')) { + call_user_func([$class, 'onWorkerStart'], $worker); + } +} + +/** + * Start worker + * @param $processName + * @param $config + * @return void + */ +function worker_start($processName, $config) +{ + $worker = new Worker($config['listen'] ?? null, $config['context'] ?? []); + $propertyMap = [ + 'count', + 'user', + 'group', + 'reloadable', + 'reusePort', + 'transport', + 'protocol', + ]; + $worker->name = $processName; + foreach ($propertyMap as $property) { + if (isset($config[$property])) { + $worker->$property = $config[$property]; + } + } + + $worker->onWorkerStart = function ($worker) use ($config) { + require_once base_path('/support/bootstrap.php'); + if (isset($config['handler'])) { + if (!class_exists($config['handler'])) { + echo "process error: class {$config['handler']} not exists\r\n"; + return; + } + + $instance = Container::make($config['handler'], $config['constructor'] ?? []); + worker_bind($worker, $instance); + } + }; +} + +/** + * Get realpath + * @param string $filePath + * @return string + */ +function get_realpath(string $filePath): string +{ + if (strpos($filePath, 'phar://') === 0) { + return $filePath; + } else { + return realpath($filePath); + } +} + +/** + * Is phar + * @return bool + */ +function is_phar(): bool +{ + return class_exists(Phar::class, false) && Phar::running(); +} + +/** + * Get cpu count + * @return int + */ +function cpu_count(): int +{ + // Windows does not support the number of processes setting. + if (DIRECTORY_SEPARATOR === '\\') { + return 1; + } + $count = 4; + if (is_callable('shell_exec')) { + if (strtolower(PHP_OS) === 'darwin') { + $count = (int)shell_exec('sysctl -n machdep.cpu.core_count'); + } else { + $count = (int)shell_exec('nproc'); + } + } + return $count > 0 ? $count : 4; +} + +/** + * Get request parameters, if no parameter name is passed, an array of all values is returned, default values is supported + * @param string|null $param param's name + * @param mixed|null $default default value + * @return mixed|null + */ +function input(string $param = null, $default = null) +{ + return is_null($param) ? request()->all() : request()->input($param, $default); +} diff --git a/demo/webman/backend/windows.bat b/demo/webman/backend/windows.bat new file mode 100644 index 0000000000000000000000000000000000000000..f07ce5328abd94a22d4aa352598c2c38f99748ba --- /dev/null +++ b/demo/webman/backend/windows.bat @@ -0,0 +1,3 @@ +CHCP 65001 +php windows.php +pause \ No newline at end of file diff --git a/demo/webman/backend/windows.php b/demo/webman/backend/windows.php new file mode 100644 index 0000000000000000000000000000000000000000..21fa888f3d65ede9f8ce5bffd28dc4451391c09f --- /dev/null +++ b/demo/webman/backend/windows.php @@ -0,0 +1,118 @@ +load(); + } else { + Dotenv::createMutable(base_path())->load(); + } +} + +App::loadAllConfig(['route']); + +$errorReporting = config('app.error_reporting'); +if (isset($errorReporting)) { + error_reporting($errorReporting); +} + +$runtimeProcessPath = runtime_path() . DIRECTORY_SEPARATOR . '/windows'; +if (!is_dir($runtimeProcessPath)) { + mkdir($runtimeProcessPath); +} +$processFiles = [ + __DIR__ . DIRECTORY_SEPARATOR . 'start.php' +]; +foreach (config('process', []) as $processName => $config) { + $processFiles[] = write_process_file($runtimeProcessPath, $processName, ''); +} + +foreach (config('plugin', []) as $firm => $projects) { + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['process'] ?? [] as $processName => $config) { + $processFiles[] = write_process_file($runtimeProcessPath, $processName, "$firm.$name"); + } + } + foreach ($projects['process'] ?? [] as $processName => $config) { + $processFiles[] = write_process_file($runtimeProcessPath, $processName, $firm); + } +} + +function write_process_file($runtimeProcessPath, $processName, $firm): string +{ + $processParam = $firm ? "plugin.$firm.$processName" : $processName; + $configParam = $firm ? "config('plugin.$firm.process')['$processName']" : "config('process')['$processName']"; + $fileContent = << true]); + if (!$resource) { + exit("Can not execute $cmd\r\n"); + } + return $resource; +} + +$resource = popen_processes($processFiles); +echo "\r\n"; +while (1) { + sleep(1); + if (!empty($monitor) && $monitor->checkAllFilesChange()) { + $status = proc_get_status($resource); + $pid = $status['pid']; + shell_exec("taskkill /F /T /PID $pid"); + proc_close($resource); + $resource = popen_processes($processFiles); + } +} diff --git a/demo/webman/frontend/layui_admin_flow/.htaccess b/demo/webman/frontend/layui_admin_flow/.htaccess new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/demo/webman/frontend/layui_admin_flow/.idea/.gitignore b/demo/webman/frontend/layui_admin_flow/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..10b731c518c79596ed8690544cfbc87a98cf7e36 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/.idea/.gitignore @@ -0,0 +1,5 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ diff --git a/demo/webman/frontend/layui_admin_flow/.idea/inspectionProfiles/Project_Default.xml b/demo/webman/frontend/layui_admin_flow/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000000000000000000000000000000000..03d9549ea8e4ada36fb3ecbc30fef08175b7d728 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/.idea/layui_admin_flow.iml b/demo/webman/frontend/layui_admin_flow/.idea/layui_admin_flow.iml new file mode 100644 index 0000000000000000000000000000000000000000..0c8867d7e175f46d4bcd66698ac13f4ca00cf592 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/.idea/layui_admin_flow.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/.idea/modules.xml b/demo/webman/frontend/layui_admin_flow/.idea/modules.xml new file mode 100644 index 0000000000000000000000000000000000000000..b5784a37f07ab03191ee293bdfd906046df0c178 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/.idea/php.xml b/demo/webman/frontend/layui_admin_flow/.idea/php.xml new file mode 100644 index 0000000000000000000000000000000000000000..f324872a8ba94b4ec07a8aad82965487b3b15d57 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/.idea/php.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/LICENSE b/demo/webman/frontend/layui_admin_flow/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..2f283ae16ebc0ec888890433bf06b3fea362d626 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 就眠儀式 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/README.md b/demo/webman/frontend/layui_admin_flow/README.md new file mode 100644 index 0000000000000000000000000000000000000000..728aa3fe2ae3c84554fc87bec7658384b937ccfe --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/README.md @@ -0,0 +1,139 @@ +
                                                                                                  + +
                                                                                                  +
                                                                                                  + +

                                                                                                  + Pear Admin Layui +

                                                                                                  +

                                                                                                  + 开 箱 即 用 的 前 后 端 解 决 方 案 +

                                                                                                  + + [预 览](http://layui.pearadmin.com) | [官 网](http://www.pearadmin.com/) | [文档](http://www.pearadmin.com/doc) + +
                                                                                                  + +

                                                                                                  + + Pear Admin Layui Version + + + Jquery Version + + + Layui Version + +

                                                                                                  +
                                                                                                  +
                                                                                                  + +
                                                                                                  +
                                                                                                  + +### 项目介绍 + +

                                                                                                  + +Pear Admin 是一款开箱即用的前端开发模板,提供便捷快速的开发方式,延续 Admin 的设计规范。 + +若你需要更多版本 (Java Go Think 等),请前往 [Pear Admin 社区](https://gitee.com/pear-admin) + +项目不定时更新,建议 Star watch 一份 + +

                                                                                                  + +### 新特性 + +- [重构] frame.js 组件,重命名为 page.js, 移除 iframe 嵌套。 +- [重构] tab.js 组件,重命名为 tabPage.js, 移除 iframe 嵌套。 +- [新增] admin.js 模块 setConfigurationProvider 方法,用于自定义 configuration 来源。 +- [优化] admin.js 模块 logout 方法,返回值由 boolean 调整为 Promise 类型。 +- [新增] 夜间模式适配,目前已完成整体框架兼容,layui 待完成。 +- [新增] menuSearch.js 模块,原有的菜单搜索功能。 + +### Branch 说明 + +

                                                                                                  + +main: 最新的功能,主要维护的版本。 + +package: 通过 gulp.js 提供打包构建,适合对资源加载和编译速度有要求的项目。 + +i18n: 集成 translate.js 提供 i18n 国际化功能的版本。 + +

                                                                                                  + +### 项目结构 + +``` +Pear Admin Layui +│ +├─admin 资源 +│ │ +│ ├─css 样式 +│ │ +│ ├─data 数据 +│ │ +│ └─images 图片 +│ +├─component 组件 +│ │ +│ ├─layui 核心框架 +│ │ +│ └─pear 扩展组件 +│ +├─config 配置 +│ │ +│ ├─pear.config.yml 配置文件 +│ │ +│ └─pear.config.json 配置文件 +│ +├─view 视图 +│ │ +│ ├─analysis 分析页 +│ │ +│ ├─component 组件案例 +│ │ +│ ├─console 控制台 +│ │ +│ ├─exception 错误页 +│ │ +│ ├─listing 列表页 +│ │ +│ └─result 结果页 +│ +├─index.html 入口 +│ +└─login.html 登录 + +``` + +### 项目截图 + +| | | +|---------------------|---------------------| +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/221841_9d135fe6_4835367.png "屏幕截图.png") | ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/221901_b5282417_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/221920_84f71864_4835367.png "屏幕截图.png")| ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/221953_eacb1578_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222007_334b5411_4835367.png "屏幕截图.png")| ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222020_ed5e67ac_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222105_9a1036c6_4835367.png "屏幕截图.png")| ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222116_50936543_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222150_6251bb30_4835367.png "屏幕截图.png")| ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222206_777ccf74_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222315_712d2942_4835367.png "屏幕截图.png")|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222345_2629d03c_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222410_e83792fa_4835367.png "屏幕截图.png")| ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222431_5b884442_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222453_b02034b2_4835367.png "屏幕截图.png")| ![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222508_fec3ad5e_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222533_abda701e_4835367.png "屏幕截图.png")|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222547_db49f0b8_4835367.png "屏幕截图.png") | +|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222611_7ffd378b_4835367.png "屏幕截图.png")|![输入图片说明](https://images.gitee.com/uploads/images/2021/0331/222625_55e092f3_4835367.png "屏幕截图.png") | + +### 开源共建 + +

                                                                                                  + +1. 欢迎提交 [pull request](https://gitee.com/pear-admin/Pear-Admin-Layui/pulls),注意对应提交对应 `main` 分支 + +2. 欢迎提交 [issue](https://gitee.com/pear-admin/Pear-Admin-Layui/issues),请写清楚遇到问题的原因、开发环境、复显步骤。 + +

                                                                                                  + +感谢每一位贡献代码的朋友。 + +如果对您有帮助,您可以点右上角 💘Star💘 支持 diff --git a/demo/webman/frontend/layui_admin_flow/admin/css/admin.css b/demo/webman/frontend/layui_admin_flow/admin/css/admin.css new file mode 100644 index 0000000000000000000000000000000000000000..a96ce163111abc867c276e2588a715d233427efe --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/css/admin.css @@ -0,0 +1,647 @@ +html, +body, +.layui-layout { + height: 100%; +} + +.pear-admin .layui-body, +.pear-admin .layui-logo, +.pear-admin .layui-side, +.pear-admin .layui-header, +.pear-admin .layui-header .layui-layout-left { + transition: all .3s; +} + +.pear-admin.banner-layout .layui-side { + top: 60px !important; +} + +.pear-admin.banner-layout .layui-side .layui-logo { + display: none; +} + +.pear-admin.banner-layout .layui-header .layui-logo { + display: inline-block; +} + +.pear-admin.banner-layout .layui-side .layui-side-scroll { + height: 100% !important; +} + +.pear-admin.banner-layout .layui-side .layui-side-scroll { + height: 100% !important; +} + +.pear-admin .layui-header.dark-theme .layui-layout-control .layui-this * { + background-color: rgba(0, 0, 0, .1) !important; +} + +.pear-admin .layui-header .layui-logo { + display: none; +} + +.pear-admin .layui-logo .title { + font-size: 20px; +} + +.pear-admin .layui-layout-right .layui-nav-child { + border: 1px solid whitesmoke; + border-radius: 4px; + width: auto; + left: auto; + right: -23px; +} + +.pear-admin .layui-header { + left: 230px; + width: calc(100% - 230px); + background-color: white; +} + +.pear-admin .layui-layout-control { + left: 140px; + position: absolute; +} + +.pear-admin .layui-layout-control .layui-nav { + padding: 0px; +} + +.pear-admin .layui-logo { + height: 60px; + line-height: 60px; + border-bottom: 1px solid rgba(0, 0, 0, .12); + box-sizing: border-box; + position: relative; + background-color: #28333E; + width: 230px; +} + +.pear-admin .layui-logo img { + width: 34px; + height: 34px; +} + +.pear-admin .layui-logo .title { + font-size: 21px; + font-weight: 550; + color: var(--global-primary-color); + position: relative; + top: 5px; + margin-left: 5px; +} + +.pear-admin .layui-logo .logo { + display: none; +} + +.pear-admin .layui-side { + top: 0px; + width: 230px; + box-shadow: 2px 0 6px rgba(0, 21, 41, .20); + z-index: 9999; +} + +.pear-admin .layui-side-scroll::-webkit-scrollbar { + width: 0px; + height: 0px; +} + +.pear-admin .layui-side-scroll { + height: calc(100% - 60px) !important; + background-color: #28333E; + width: 247px; + +} + +.pear-admin .layui-header .layui-nav .layui-nav-item>a { + color: black; + font-size: 15px; +} + +.pear-admin .layui-body { + bottom: 0px; + padding-bottom: 0px; + background-color: whitesmoke; + height: calc(100% - 60px); + overflow-y: auto; + left: 230px; +} + +.pear-admin .layui-body>div { + height: 100%; +} + +.pear-admin .layui-layout-left { + left: 0px; +} + +.pear-admin .layui-footer { + position: absolute; + display: flex; + justify-content: space-between; + left: 230px; + background: #fff; + border-top: 1px solid #F2F2F2; + box-shadow: none; + -webkit-transition: left .3s; + transition: left .3s; + overflow: hidden; + color: #3c3c3cb3; + font-weight: 300; + font-size: 13.6px; +} + +.pear-admin .layui-footer.close { + display: none; +} + +/** 通栏布局 */ + +.pear-admin.banner-layout .layui-header { + left: 0px; + z-index: 99999; + width: 100%; +} + +.pear-admin.banner-layout .layui-header.light-theme { + border-bottom: 1px solid whitesmoke; +} + +.pear-admin.banner-layout .layui-header.auto-theme, +.pear-admin.banner-layout .layui-header.dark-theme { + box-shadow: 0 1px 4px rgba(0, 0, 0, .1); +} + +.pear-admin.banner-layout .layui-header .layui-layout-left { + left: 230px; +} + +.pear-admin.banner-layout .layui-header .layui-logo .title { + top: 2px; +} + +.pear-admin.banner-layout .layui-header .layui-layout-control { + display: inline-block; + left: 370px; +} + +/** 头部主题 */ +.pear-admin .auto-theme { + background-color: var(--global-primary-color); + color: white; +} + +.pear-admin .auto-theme .layui-logo { + background-color: var(--global-primary-color); + border: none; +} + +.pear-admin .auto-theme .layui-logo .title { + color: white; +} + +.pear-admin .auto-theme .layui-nav * { + color: white !important; +} + +.pear-admin .auto-theme .layui-nav.pear-nav-control .layui-this * { + color: black !important; +} + +.pear-admin .auto-theme .layui-nav .layui-nav-child a { + color: #5f5f5f !important; + color: rgba(0, 0, 0, .8) !important; +} + +/** 收缩布局 */ +.pear-mini .layui-side .layui-logo .title { + display: none; +} + +.pear-mini .layui-side .layui-logo .logo { + display: inline-block; +} + +.pear-mini .layui-side { + width: 60px; +} + +.pear-mini .layui-header { + left: 60px; + width: calc(100% - 60px); +} + +.pear-mini .layui-body { + left: 60px; +} + +.pear-mini .layui-side .layui-logo { + width: 60px; +} + +.pear-mini .layui-footer { + left: 60px; +} + +.pear-mini .layui-nav-tree .layui-nav-item span { + display: none; +} + +.pear-mini .layui-side-scroll { + height: calc(100% - 60px); +} + +.pear-admin .layui-header .layui-nav .layui-nav-bar { + top: 0px !important; + background-color: var(--global-primary-color); + height: 2px !important; +} + +.pear-admin .layui-header .layui-nav .layui-this:after { + display: none; +} + +.pear-admin .layui-header .layui-nav-more { + display: none; +} + +.pear-collapsed-pe { + right: 30px; + bottom: 30px; + z-index: 400000; + position: absolute; + background-color: var(--global-primary-color) !important; + box-shadow: 2px 0 6px rgba(0, 21, 41, .20); + text-align: center; + border-radius: 4px; + line-height: 50px; + display: none; + height: 50px; + width: 50px; +} + +.pear-collapsed-pe a { + color: white !important; +} + +@media screen and (min-width: 768px) { + .layui-hide-sm { + display: inline-block !important; + } +} + +@media screen and (min-width: 769px) { + .layui-hide-sm { + display: none !important; + } +} + +/** 新增兼容 */ +@media screen and (max-width:768px) { + .collapse { + display: none !important; + } + + .pear-collapsed-pe { + display: inline-block !important; + } + + .layui-layout-control { + left: 45px !important; + } + + .layui-layout-left { + padding-left: 10px; + padding-right: 10px; + } + + .pear-mini .layui-side-scroll { + height: calc(100% - 62px); + } + + .pear-mini .layui-side { + width: 0px; + } + + .pear-mini .layui-header { + left: 0px; + width: 100%; + } + + .pear-mini .layui-body { + left: 0px; + } + + .pear-mini .layui-footer { + left: 0px; + } + + .pear-mini .layui-logo { + width: 0px; + } + + .pear-admin .layui-body { + left: 0px; + } + + .pear-admin .layui-header { + left: 0px; + width: 100%; + } + + .pear-admin .pear-cover { + width: 100%; + height: 100%; + background-color: #1E1E1E; + display: block; + position: absolute; + z-index: 1000; + opacity: 0; + margin-top: -60px; + } + + .pear-mini .pear-cover { + display: none; + } +} + +@-webkit-keyframes am-horizontal-roll_show { + 0% { + opacity: 1; + -webkit-transform: translateX(2000px); + transform: translateX(2000px) + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0) + } +} + +@keyframes am-horizontal-roll_show { + 0% { + opacity: 1; + -webkit-transform: translateX(800px); + -ms-transform: translateX(800px); + transform: translateX(800px) + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0) + } +} + +.layer-anim-right { + -webkit-animation: am-horizontal-roll_show .5s ease-out; + animation: am-horizontal-roll_show .5s ease-out; + +} + +/** 侧边主题 (亮) */ +.light-theme.layui-side { + box-shadow: 2px 0 8px 0 rgba(29, 35, 41, .05) !important; +} + +.light-theme.layui-side .layui-logo { + background-color: white !important; + color: black !important; + border-bottom: 1px whitesmoke solid; +} + +.light-theme.layui-side .layui-side-scroll { + background-color: white !important; + color: black !important; +} + +.dark-theme.layui-header { + border-bottom: none; + background-color: #28333E; + color: whitesmoke; +} + +.dark-theme.layui-header li>a { + color: whitesmoke !important; +} + +.dark-theme.layui-header .layui-logo { + box-shadow: none; + border: none; +} + +/** 顶部主题 (白) */ +.light-theme.layui-header .layui-logo { + background-color: white; + border: none; + box-shadow: none; +} + +/** 主题面板 */ +.pearone-color .set-text { + height: 42px; + line-height: 42px; +} + +.pearone-color .color-title { + padding: 15px 0 0px 20px; + margin-bottom: 4px; +} + +.pearone-color .color-content { + padding: 15px 10px 0 20px; +} + +.pearone-color .color-content ul { + list-style: none; + padding: 0px; +} + +.pearone-color .color-content ul li { + position: relative; + display: inline-block; + vertical-align: top; + width: 70px; + height: 50px; + margin: 0 20px 20px 0; + padding: 2px 2px 2px 2px; + background-color: #f2f2f2; + cursor: pointer; + font-size: 12px; + color: #666; +} + +.pearone-color .color-content li.layui-this:after, +.pearone-color .color-content li:hover:after { + width: 100%; + height: 100%; + padding: 4px; + top: -6px; + left: -6px; + border: var(--global-primary-color) 2px solid; + opacity: 1; + border-radius: 4px; +} + +.pearone-color .color-content li:after { + content: ''; + position: absolute; + z-index: 20; + top: 50%; + left: 50%; + width: 1px; + height: 0; + border: 2px solid #F2F2F2; + transition: all .3s; + -webkit-transition: all .3s; + opacity: 0; +} + +.select-color { + margin-bottom: 30px; +} + +.select-color .select-color-title { + padding: 15px 0 0px 20px; + margin-bottom: 4px; +} + +.select-color .select-color-content { + padding: 20px 0 0px 0px; + margin-bottom: 4px; +} + +.select-color .select-color-content .select-color-item { + width: 24px; + height: 24px; + color: white; + margin-left: 24px; + border-radius: 6px; + background-color: gray; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .15); + text-align: center; + line-height: 24px; + font-size: 12px; + float: left; +} + +.message .layui-tab-title li:not(:last-child) { + border-right: 1px solid #eee; +} + +/** 首屏加载 */ +.loader-wrapper { + position: fixed; + width: 100%; + height: 100%; + background-color: whitesmoke; + z-index: 9999999; +} + +.loader { + width: 50px; + height: 50px; + margin: 30px auto 40px; + margin-top: 20%; + position: relative; + z-index: 999999; + background-color: whitesmoke; +} + +.loader:before { + content: ""; + width: 50px; + height: 7px; + border-radius: 50%; + background: #000; + opacity: 0.1; + position: absolute; + top: 59px; + left: 0; + animation: shadow .5s linear infinite; +} + +.loader:after { + content: ""; + width: 50px; + height: 50px; + border-radius: 10px; + background-color: var(--global-primary-color); + position: absolute; + top: 0; + left: 0; + animation: loading .5s linear infinite; +} + +@-webkit-keyframes loading { + 17% { + border-bottom-right-radius: 3px; + } + + 25% { + transform: translateY(9px) rotate(22.5deg); + } + + 50% { + transform: translateY(18px) scale(1, 0.9) rotate(45deg); + border-bottom-right-radius: 40px; + } + + 75% { + transform: translateY(9px) rotate(67.5deg); + } + + 100% { + transform: translateY(0) rotate(90deg); + } +} + +@keyframes loading { + 17% { + border-bottom-right-radius: 3px; + } + + 25% { + transform: translateY(9px) rotate(22.5deg); + } + + 50% { + transform: translateY(18px) scale(1, 0.9) rotate(45deg); + border-bottom-right-radius: 40px; + } + + 75% { + transform: translateY(9px) rotate(67.5deg); + } + + 100% { + transform: translateY(0) rotate(90deg); + } +} + +@-webkit-keyframes shadow { + + 0%, + 100% { + transform: scale(1, 1); + } + + 50% { + transform: scale(1.2, 1); + } +} + +@keyframes shadow { + + 0%, + 100% { + transform: scale(1, 1); + } + + 50% { + transform: scale(1.2, 1); + } +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/admin/css/admin.dark.css b/demo/webman/frontend/layui_admin_flow/admin/css/admin.dark.css new file mode 100644 index 0000000000000000000000000000000000000000..3898bf216d360735d8fe62cff49278855c72333e --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/css/admin.dark.css @@ -0,0 +1,337 @@ +/** loader */ +.pear-admin-dark .loader-wrapper, +.pear-admin-dark .loader-wrapper .loader { + background-color: #141414; +} + +/** layout */ +.pear-admin-dark .layui-layout { + background-color: #141414; +} + +/** header */ +.pear-admin-dark .layui-header, +.pear-admin-dark .layui-header .layui-logo { + background-color: #141414 !important; + box-shadow: none !important; + border: none !important; +} +.pear-admin-dark .layui-header.auto-theme, +.pear-admin-dark .layui-header.auto-theme .layui-logo { + background-color: var(--global-primary-color) !important; +} + +.pear-admin-dark .layui-header.auto-theme .layui-logo .title { + color: #ffffff !important; +} + +.pear-admin-dark .layui-header { + border: 1px solid rgba(0, 0, 0, .40) !important; +} + +.pear-admin-dark .layui-header .layui-nav * { + color: #ffffff !important; +} + +.pear-admin-dark .layui-header .layui-nav .layui-nav-child { + box-shadow: 0 3px 4px rgba(0, 0, 0, .6) !important; + background-color: #141414; + border-color: #141414; +} + +.pear-admin-dark .layui-header .layui-nav .layui-nav-child dd > a:hover { + background-color: #141414 !important; +} + +.pear-admin-dark .layui-header .pear-nav-control .layui-this a{ + background-color: #0c0c0c !important; +} + +.pear-admin-dark .auto-theme .layui-logo .title{ + color: var(--global-primary-color) !important; +} + +/** side */ +.pear-admin-dark .layui-side { + box-shadow: 0 3px 4px rgba(0, 0, 0, .6) !important; +} + +.pear-admin-dark .layui-logo { + border-color: rgba(0, 0, 0, .30) !important; +} + +.pear-admin-dark .layui-side .layui-logo, +.pear-admin-dark .layui-side .layui-side-scroll, +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav-tree{ + background-color: #141414 !important; +} + +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav-tree .layui-nav-child { + background-color: rgba(0,0,0,.3)!important; +} + +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-item a, +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-item a > .layui-nav-more { + color: rgba(255,255,255,.7) !important; +} + +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-child dd.layui-this a, +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-itemed > a, +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-itemed > a > .layui-nav-more, +.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-item > a:hover { + color: #ffffff !important; +} + +/** body */ +.pear-admin-dark .layui-body, +.pear-admin-dark .layui-body .pear-tab-page-loading, +.pear-admin-dark .layui-body .pear-page-loading { + background-color: #0a0a0a !important; +} + +.pear-admin-dark .layui-body .layui-tab .layui-tab-title, +.pear-admin-dark .layui-body .layui-tab .layui-tab-title li, +.pear-admin-dark .layui-body .layui-tab .layui-tab-control li { + background-color: #141414 !important; + border-color:rgba(0, 0, 0, .30) !important; + color: #ffffff; +} + +.pear-admin-dark .layui-body .layui-tab .layui-tab-title li > span:first-child { + background-color: #434343; +} + +.pear-admin-dark .layui-body .layui-tab .layui-nav-child.layui-anim { + border-color: #141414; + background-color: #141414 !important; +} + +.pear-admin-dark .layui-body .layui-tab .layui-nav-child.layui-anim a { + color: #ffffff; +} + +.pear-admin-dark .layui-body .layui-tab .layui-nav-child.layui-anim a:hover { + background-color: #0a0a0a; +} + +.pear-admin-dark .layui-body .layui-tab .layui-tab-close:hover { + border-radius: 50%; + background-color: #0a0a0a !important; +} + +.pear-admin-dark .pear-tab-page-menu ul li { + color: #ffffff !important; +} + +.pear-admin-dark .layui-footer { + background-color: #141414; + border-top: 1px solid #141414; +} + +/** theme */ +.pear-admin-dark .set-text, +.pear-admin-dark .select-color-title, +.pear-admin-dark .color-title { + color: #ffffff; +} + +/** search */ +.pear-admin-dark .menu-search-no-data { + color: #ffffff; +} + +.pear-admin-dark .menu-search-tips * { + color: #ffffff; +} + +.pear-admin-dark .menu-search-tips kbd { + border-color: rgba(0, 0, 0, .30) !important; +} + + +/** message center */ +.pear-admin-dark .pear-message-center .layui-tab-title, +.pear-admin-dark .pear-message-center .message-item { + border-color: rgba(0, 0, 0, .30) !important; + color: #ffffff; +} + +/** button */ +.pear-admin-dark .layui-btn { + color: #ffffff; + border-color: #4C4D4F; +} + +/** layer */ +.pear-admin-dark .layui-layer { + background-color: #141414; +} + +.pear-admin-dark .layui-layer-msg { + border-color: #141414; +} + +.pear-admin-dark .layui-layer-msg .layui-layer-content { + color: #E5EAF3; +} + +.pear-admin-dark .layui-layer .layui-layer-setwin > span, +.pear-admin-dark .layui-layer .layui-layer-title { + color: #ffffff; +} + +/** card */ +.pear-admin-dark .layui-card { + background-color: #1d1e1f !important; +} + +.pear-admin-dark .layui-card .layui-card-header { + border-bottom-color: #414243; + color: #ffffff; +} + +.pear-admin-dark .layui-card .layui-card-body { + color: #ffffff; +} + +/** input */ +.pear-admin-dark .layui-input { + background-color: transparent; + color: #ffffff; + border-color: rgba(0, 0, 0, .30) !important; +} + +/** switch */ +.pear-admin-dark .layui-form-switch { + border-color: #484849; + background-color: rgba(255,255,255,.08); +} + +/** table */ +.pear-admin-dark .layui-table { + background-color: transparent; +} + +.pear-admin-dark .layui-table tr:hover { + background-color: #141414 !important; +} + +.pear-admin-dark .layui-table td, +.pear-admin-dark .layui-table th, +.pear-admin-dark .layui-table-view, +.pear-admin-dark .layui-table-page, +.pear-admin-dark .layui-table-tool, +.pear-admin-dark .layui-table-header { + border-color: rgba(0, 0, 0, .40) !important; +} + +.pear-admin-dark .layui-laypage select, +.pear-admin-dark .layui-laypage button { + border-color: rgba(0, 0, 0, .40) !important; + color: #ffffff !important; + background-color: transparent; +} + +.pear-admin-dark .layui-table-tool-self > div { + border-color: rgba(0, 0, 0, .40) !important; + color: #ffffff !important; + background-color: transparent; +} + +/** panel */ +.pear-admin-dark .layui-panel { + background-color: #1d1e1f !important; + border-color: #1d1e1f !important; +} + +/** menu */ +.pear-admin-dark .layui-menu { + background-color: #1d1e1f !important; +} + +.pear-admin-dark .layui-menu .layui-menu-body-title, +.pear-admin-dark .layui-menu .layui-menu-body-title:hover { + color: #ffffff; + background-color: #1d1e1f !important; +} + +/** timeline */ +.pear-admin-dark .layui-timeline-axis { + background-color: rgb(29, 30, 31) !important; +} + +.pear-admin-dark .layui-timeline-item:before { + background-color: #414243 !important; +} + + +/** toast */ +.pear-admin-dark .iziToast { + background-color: #1f1f1f !important; +} + +/** console */ + +.pear-admin-dark .deputy, +.pear-admin-dark .shortcut-menu { + background-color: #141414 !important; +} + +.pear-admin-dark .deputy:hover, +.pear-admin-dark .shortcut-menu:hover { + box-shadow: 0 3px 4px rgba(0, 0, 0, .6) !important; +} + +.pear-admin-dark .message-board li { + border-bottom: 1px solid rgba(0, 0, 0, .40) !important; +} + +/** analysis */ +.pear-admin-dark .top-panel-number { + color: #ffffff !important; + border-color: #414243; +} + + +.pear-admin-dark .dynamic-status dd { + border-color: #414243; +} + +/** success failure */ +.pear-admin-dark .pear-result .content { + background-color: rgba(153, 153, 153, 0.12); + color: #E5EAF3; +} + +.pear-admin-dark .pear-result .title{ + color: #ffffff; +} + +.pear-admin-dark .pear-result .description{ + color: #8D9095; +} + +/** 403 404 500*/ +.pear-admin-dark .pear-exception .title p{ + color: #E5EAF3 !important; +} + +/** scroll */ +.pear-admin-dark *::-webkit-scrollbar-thumb { + background: #141414; + border-radius: 4px; +} + +.pear-admin-dark *::-webkit-scrollbar-thumb:hover { + background: #0a0a0a; +} + +/** profile */ +.pear-admin-dark .user-name, +.pear-admin-dark .user-desc { + color: whitesmoke; +} + +.pear-admin-dark .user-desc { + border-top: 1px solid #141414; +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/admin/css/other/analysis.css b/demo/webman/frontend/layui_admin_flow/admin/css/other/analysis.css new file mode 100644 index 0000000000000000000000000000000000000000..3525a21a63b6904d2ea66a9a591306edf1af5d7f --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/css/other/analysis.css @@ -0,0 +1,65 @@ +.top-panel { + border-radius: 4px; + text-align: center; +} + +.top-panel>.layui-card-body { + height: 60px; +} + +.top-panel-number { + line-height: 60px; + font-size: 29px; + border-right: 1px solid #eceff9; +} + +.top-panel-tips { + padding-left: 8px; + padding-top: 16px; + line-height: 30px; + font-size: 12px; +} + +.top-panel-tips i { + font-size: 33px; +} + +.top-panel-tips svg { + margin-top: -12px; + width: 50px; + height: 50px; +} + +.dynamic-status { + padding: 0 10px 10px; +} + +.dynamic-status dd { + padding: 15px 0; + border-bottom: 1px solid #EEE; + display: -webkit-flex; + display: flex; +} + +.dynamic-status dd div.dynamic-status-img { + width: 32px; + height: 32px; + border-radius: 50%; + margin-right: 15px; +} + +.dynamic-status dd div.dynamic-status-img a { + width: 100%; + height: 100%; + display: inline-block; + text-align: center; + line-height: 32px; +} + +.dynamic-status dd div span { + color: #BBB; +} + +.dynamic-status dd div a { + color: #01AAED; +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/admin/css/other/console.css b/demo/webman/frontend/layui_admin_flow/admin/css/other/console.css new file mode 100644 index 0000000000000000000000000000000000000000..af9930ba4d959a0cf2143f0a89d385faac0721c3 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/css/other/console.css @@ -0,0 +1,81 @@ + +.shortcut-menu { + width: 100%; + height: 66px; + background-color: #F8F8F8; + display: inline-block; + border-radius: 5px; + text-align: center; + margin-bottom: 3px; +} + +.shortcut-menu i { + font-size: 30px; + height: 66px; + line-height: 66px; +} + +.shortcut-menu:hover { + box-shadow: 2px 0 8px 0 lightgray !important; +} + +.shortcut-menu-label { + width: 100%; + display: inline-block; + text-align: center; +} + +.deputy { + width: 100%; + height: 90px; + background-color: #F8F8F8; + display: inline-block; + border-radius: 5px; + text-align: center; + margin-bottom: 3px; +} + +.deputy:hover { + box-shadow: 2px 0 8px 0 lightgray !important; +} + +.deputy .deputy-label { + color: gray; + margin-top: 14px; + font-size: 14px; +} + +.deputy .deputy-count { + margin-top: 12px; + color: var(--global-primary-color); + font-size: 30px; +} + +.message-board { + padding: 0 10px 10px; +} + +.message-board li { + position: relative; + padding: 10px 0; + border-bottom: 1px solid #EEE; +} + +.message-board li p { + padding-bottom: 10px; + padding-top: 3px; +} + +.message-board li>span { + color: #999; + height: 24px; + line-height: 24px; +} + +.message-board .message-board-reply { + position: absolute; + right: 20px; + bottom: 12px; + height: 24px; + line-height: 24px; +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/admin/css/other/exception.css b/demo/webman/frontend/layui_admin_flow/admin/css/other/exception.css new file mode 100644 index 0000000000000000000000000000000000000000..e7f2027cfeeb42dd728f1397552c2c1e4cb480b6 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/css/other/exception.css @@ -0,0 +1,28 @@ +.pear-exception { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + text-align: center; + box-sizing: border-box; + padding: 70px 40px +} + +.pear-exception .title { + margin-top: 20px; +} + +.pear-exception .title p { + color: rgb(0, 0, 0); + font-size: 20px; +} + +.pear-exception .description { + margin-top: 10px; + color: #8D9095; + font-size: 14px; +} + +.pear-exception .extra { + margin: 30px; +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/admin/css/other/login.css b/demo/webman/frontend/layui_admin_flow/admin/css/other/login.css new file mode 100644 index 0000000000000000000000000000000000000000..853e09221e47f8f024345c8ee495fb5e77af3490 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/css/other/login.css @@ -0,0 +1,218 @@ +html, +body{ + height: 100%; +} + +.login-page { + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + display: flex; + justify-content: center; + align-items: center; +} + +.layui-row { + width: 1000px; + height: 600px; + box-shadow: 2px 0 6px rgba(0, 21, 41, .20); + border: 3px solid whitesmoke; + border-radius: 15px; +} + +.login-bg { + height: 100%; + box-sizing: border-box; + background-color: rgb(250, 250, 250); + display: flex; + align-items: center; + justify-content: center; + border-bottom-left-radius: 15px; + border-top-left-radius: 15px; +} + +.login-bg-img { + width: 90%; + display: inline-block; + margin: 0 auto; +} + +.login-form { + height: 100%; + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: center; + background-color: #fff; + border-bottom-right-radius: 15px; + border-top-right-radius: 15px; +} + +.form-center { + background: #fff; + box-sizing: border-box; + flex-flow: row wrap; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + text-align: center; +} + +.form-center-box { + width: 360px; +} + +.top-log-title { + align-items: center; + justify-content: center; + display: flex; + margin-bottom: 30px; +} + +.top-log { + width: 50px; + border-radius: 12px; + margin-right: 20px; + height: 50px; +} + +.top-log-title span { + font-size: 32px; + font-weight: 700; + color: var(--global-primary-color); +} + +.top-desc { + font-size: 14px; + color: #808695; + +} + +.tab-log-method { + width: 100%; + display: flex; + padding: 20px 0px; +} + +.tab-log-method-item { + flex: 1; + box-sizing: border-box; + padding: 5px 50px; + text-align: right; + color: #1f2225; + font-size: 16px; +} + +.tab-log-method-item:nth-child(2) { + text-align: left; +} + +.tab-log-method-item>span { + display: inline-block; + width: 40px; + text-align: center; + height: 30px; + border-bottom: 2px solid transparent; +} + +.tab-log-method-item>span:hover { + cursor: pointer; + color: #16baaa; + border-bottom: 2px solid #16baaa; +} + +.tab-log-verification { + width: 100%; + display: flex; +} + +.verification-text { + flex: 2; + box-sizing: border-box; + margin-right: 20px; +} + +.verification-img { + flex: 1; + box-sizing: border-box; + border: 1px solid #eeeeee; + border-radius: 4px; + height: 40px; + overflow: hidden; + text-align: center; +} + +.remember-passsword { + margin: 20px 0; + width: 100%; + display: flex; + box-sizing: border-box; +} + +.remember-cehcked { + flex: 1; + text-align: left; +} + +.greenText { + color: #16baaa; + cursor: pointer; +} + + +.login-btn { + width: 100%; + box-sizing: border-box; +} + +.login-btn>.layui-btn { + width: 100%; +} + +.other-login { + width: 100%; + box-sizing: border-box; + margin: 20px 0 0; + text-align: left; + display: flex; +} + +.other-login-methods { + display: inline-block; + flex: 1; +} + +.layui-input { + border-radius: 4px; + line-height: 40px; + height: 40px; +} + +.layui-btn { + border-radius: 4px; + background-color: var(--global-primary-color); +} + +@media(min-width: 992px) and (max-width:1200px){ + .layui-row{ + width: 900px; + } +} +@media(min-width: 768px) and (max-width:992px){ + .layui-row{ + width: 90%; + } + .form-center{width: 90%;} +} +@media (max-width:768px){ + .layui-row{ + width: 90%; + } + .login-form { + border-bottom-left-radius: 15px; + border-top-left-radius: 15px; + } + .form-center-box{width: 95%;} +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/admin/css/other/profile.css b/demo/webman/frontend/layui_admin_flow/admin/css/other/profile.css new file mode 100644 index 0000000000000000000000000000000000000000..4c779ee44d8963357b2fc438ea65a5207b277ad0 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/css/other/profile.css @@ -0,0 +1,77 @@ +.text-center { + text-align: center; +} + +.user-info { + width: 110px; + height: 110px; + line-height: 110px; + position: relative; + display: inline-block; + border-radius: 50%; + overflow: hidden; + cursor: pointer; + margin: 0 auto; +} + +.user-name { + padding-top: 20px; + font-size: 20px !important; +} + +.user-home { + padding-top: 8px; + margin-top: 10px; + font-size: 13.5px; +} + +.user-desc { + height: 45px; + border-top: 1px whitesmoke solid; + text-align: center; + line-height: 45px; + font-size: 13.5px; +} + +.blog-title { + padding-left: 13.5px; +} + +.blog-content { + padding-left: 13px; + font-size: 13px; + color: dimgray; +} + +.layui-tab-title { + border-bottom: none; +} + +.message-board { + padding: 0 10px 10px; +} + +.message-board li { + position: relative; + padding: 10px 0; + border-bottom: 1px solid #EEE; +} + +.message-board li p { + padding-bottom: 10px; + padding-top: 3px; +} + +.message-board li>span { + color: #999; + height: 24px; + line-height: 24px; +} + +.message-board .message-board-reply { + position: absolute; + right: 20px; + bottom: 12px; + height: 24px; + line-height: 24px; +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/admin/css/other/result.css b/demo/webman/frontend/layui_admin_flow/admin/css/other/result.css new file mode 100644 index 0000000000000000000000000000000000000000..393c464e564a8e38ab6ac592ea4fffde7093a0aa --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/css/other/result.css @@ -0,0 +1,40 @@ +.pear-result { + text-align: center; + +} +.pear-result .success svg { + color: #32C682; + text-align: center; + margin-top: 40px; + +} +.pear-result .error svg { + color: #f56c6c; + text-align: center; + margin-top: 40px; + +} +.pear-result .title { + margin-top: 25px; + +} +.pear-result .description { + margin-top: 25px; + width: 60%; + margin-left: 20%; + color: rgba(0, 0, 0, .45); +} +.pear-result .content { + margin-top: 20px; + width: 80%; + border-radius: 4px; + background-color: whitesmoke; + padding: 20px 32px; + margin-left: 10%; + margin-bottom: 30px; + text-align: left; +} +.pear-result .extra { + padding-top: 10px; + margin-top: 25px; +} diff --git a/demo/webman/frontend/layui_admin_flow/admin/css/reset.css b/demo/webman/frontend/layui_admin_flow/admin/css/reset.css new file mode 100644 index 0000000000000000000000000000000000000000..dbd9d61bbe7a72820f887ff70435471e8a37f396 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/css/reset.css @@ -0,0 +1,387 @@ +.layui-dropdown { + border-radius: var(--global-border-radius); +} + +.layui-input { + border-radius: var(--global-border-radius); +} + +.layui-form-onswitch { + background-color: var(--global-primary-color) !important; +} + +.layui-form-onswitch { + border-color: var(--global-primary-color); +} + +.layui-form-radio:hover>*, +.layui-form-radioed>i, +.layui-form-radioed { + color: var(--global-primary-color) !important; +} + +.layui-form-checked[lay-skin=primary]>i { + border-color: var(--global-primary-color) !important; + background-color: var(--global-primary-color); + color: #fff; +} + +.layui-form-checkbox[lay-skin=primary]>.layui-icon-indeterminate, +.layui-form-checkbox[lay-skin=primary]>.layui-icon-indeterminate:hover { + border-color: var(--global-primary-color); +} + +.layui-form-checkbox[lay-skin=primary]>.layui-icon-indeterminate:before { + background-color: var(--global-primary-color); +} + +.layui-btn { + background-color: var(--global-primary-color); +} + +.layui-btn.layui-btn-primary:hover { + border: 1px solid var(--global-primary-color); +} + +.layui-btn.layui-btn-normal { + background-color: #1e9fff !important; +} + +.layui-btn.layui-btn-danger { + background-color: #ff5722 !important; +} + +.layui-btn.layui-btn-warm { + background-color: #ffb800 !important; +} + +.layui-btn.layui-btn-primary { + background-color: transparent !important; + color: #5f5f5f !important; +} + +.layui-card { + border-radius: var(--global-border-radius); +} + +.layui-timeline-axis { + color: var(--global-primary-color); +} + +.layui-table-checked { + background-color: #f8f8f8; +} + +/* input框选中颜色 */ +.layui-input:focus, .layui-textarea:focus { + border-color: var(--global-primary-color) !important; + /* 这种写法暂时不支持火狐,找不到更好的写法了 */ + box-shadow: 0 0 0 3px rgb(from var(--global-primary-color) r g b / 8%); +} + +/* select框选项颜色 */ +.layui-form-select dl dd.layui-this { + color: var(--global-primary-color); +} + +/* 数字输入框后面的上下角标 */ +.layui-input-wrap .layui-input:focus+.layui-input-split { + border-color: var(--global-primary-color) +} + +/* 标签框文字 */ +.layui-form-checked:hover>div, .layui-form-checked>div { + background-color: var(--global-primary-color); +} + +/* 标签框选中 */ +.layui-form-checked:hover>i, .layui-form-checked>i { + color: var(--global-primary-color); +} + +/* laypage按钮选中颜色 */ +.layui-laypage .layui-laypage-curr .layui-laypage-em { + background-color: var(--global-primary-color); +} + +/* laypage第几页input选中颜色 */ +.layui-laypage input:active { + border-color: var(--global-primary-color); +} + +/* laypage按钮hover颜色 */ +.layui-laypage a:hover { + color: var(--global-primary-color); +} + +/* laypage每页条数select框选中颜色 */ +.layui-laypage input:focus, .layui-laypage select:focus { + border-color: var(--global-primary-color) !important; +} + +/* laydate被选中的元素颜色 */ +.layui-laydate .layui-this, .layui-laydate .layui-this>div { + background-color: var(--global-primary-color) !important; +} + +/* laydate范围按钮hover时的颜色 */ +.layui-laydate-header i:hover, .layui-laydate-header span:hover { + color: var(--global-primary-color); +} + +/* laydate按钮hover时的颜色 */ +.layui-laydate-footer span:hover { + color: var(--global-primary-color); +} + +/* 标签页选中颜色 */ +.layui-tab-brief>.layui-tab-title .layui-this { + color: var(--global-primary-color); +} + +/* 标签页选中下划线颜色 */ +.layui-tab-brief>.layui-tab-more li.layui-this:after, .layui-tab-brief>.layui-tab-title .layui-this:after { + border-bottom: 2px solid var(--global-primary-color); +} + +/* 进度条颜色 */ +.layui-progress-bar { + background-color: var(--global-primary-color); +} + +/* tree选择框hover颜色 */ +.layui-form-checkbox[lay-skin=primary]:hover>i { + border-color: var(--global-primary-color); +} + + + + +/** 表详情顶部搜索框 Start **/ + +.top-search-from .layui-form-item { + position: relative; + display: inline-block; + *display: inline; + *zoom: 1; + vertical-align: middle; +} + +.top-search-from .layui-form-item .layui-input-block { + float: left; + width: 270px; + margin-right: 10px; + margin-left: 0; + display: inline-block; + vertical-align: middle; + position: relative; +} + +.top-search-from .layui-input, .top-search-from .layui-select, .top-search-from .layui-textarea { + width: 270px; +} + +.top-search-from .item-inline .layui-form-item .layui-input-block { + width: 270px; +} + +.top-search-from .layui-form-mid { + margin-left: 7px; + margin-right: 7px; +} + +.top-search-from .layui-form-label { + width: 60px; + white-space: nowrap; +} + +.top-search-from .inline-block { + width: 128px; + display: inline-block +} + +.top-search-from .layui-form-item { + width: 370px; +} + +.top-search-from .toggle-btn { + text-align: center; +} + +.top-search-from .toggle-btn a { + cursor: pointer; + color: #999; +} + +.top-search-from .toggle-btn a:hover { + color: #333; +} + +@media screen and (max-width: 768px) { + .top-search-from .layui-input { + max-width: 234px; + } + + .top-search-from .layui-input.inline-block { + max-width: 110px; + } + + .layui-table-tool-self .layui-inline:nth-child(3) { + display: none; + } +} + + + +/*额外*/ +button { + line-height: 100% !important; +} + +.pear-btn-md, .pear-btn-sm, .pear-btn-xs, .pear-btn { + line-height: 100%; + letter-spacing: 2px; + padding: 0 15px; + font-weight: 400; + font-size: 14px; +} + +.layui-layer-btn { + padding: 0 15px 19px; + letter-spacing: 2px; +} + +.pear-btn i { + font-size: 14px; +} + +.layui-table-cell .pear-btn i { + font-size: 15px; +} + +.layui-table-tips-main { + overflow: hidden; +} + +.layui-table th { + font-weight: 500; +} + +.layui-laypage a, .layui-laypage span { + font-size: 14px; +} + +.layui-table-tool .layui-inline[lay-event], .layui-table-tool .layui-inline[lay-event]:hover { + border: none; +} + +.layui-table-tool-self .layui-icon { + font-size: 18px; +} + +.layui-table, .pear-tab .layui-tab-title li { + color: #333; +} + +.tool-btn.pear-btn-xs { + background: transparent; + font-weight: normal; + font-size: 14px; + color: #333; + border: none; + padding: 0 2px; + height: auto !important; +} + +.layui-iconpicker { + max-width: 290px !important; +} + +.layui-iconpicker .layui-anim { + max-height: 220px !important; +} + +.layui-input:disabled { + color: rgba(0, 0, 0, .25); + background: #f5f5f5; + cursor: not-allowed; +} + +.layui-form-label.required:after { + content: "*"; + color: red; + display: inline-block; + padding: 7px 5px; + line-height: 20px; + text-align: right; + position: absolute; + right: 0; + top: 5px; +} + +.layui-bg-green { + background-color: #36b368 !important; +} + +a { + cursor: pointer; +} + +*[permission] { + display: none; +} + +@media screen and (max-width: 768px) { + /** **/ + .layui-table-tool-self .layui-inline:nth-child(3) { + display: none; + } +} + +/** 右间隔 **/ +.mr-1 { + margin-right: 4px; +} + +.mr-2 { + margin-right: 8px; +} + +.mr-3 { + margin-right: 16px; +} + +.mr-4 { + margin-right: 24px; +} + +.mr-5 { + margin-right: 48px; +} + +/** 图片尺寸 **/ +.img-1 { + max-width: 16px; + max-height: 16px; + border-radius: 6px; +} + +.img-2 { + max-width: 32px; + max-height: 32px; + border-radius: 6px; +} + +.img-3 { + max-width: 64px; + max-height: 64px; + border-radius: 6px; +} + +.img-4 { + max-width: 128px; + max-height: 128px; + border-radius: 6px; +} + + diff --git a/demo/webman/frontend/layui_admin_flow/admin/css/variables.css b/demo/webman/frontend/layui_admin_flow/admin/css/variables.css new file mode 100644 index 0000000000000000000000000000000000000000..a0f467e43a018e41a9b15c320c238a1ec930c3b6 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/css/variables.css @@ -0,0 +1,9 @@ +:root { + + /* 主题颜色 */ + --global-primary-color: #16baaa; + + /** 圆角度数 */ + --global-border-radius: 4px; + +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/admin/data/menu.json b/demo/webman/frontend/layui_admin_flow/admin/data/menu.json new file mode 100644 index 0000000000000000000000000000000000000000..b4dda48e228f18ff446247db0121eb5ab34cf9dc --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/data/menu.json @@ -0,0 +1,314 @@ +{"data":[ + { + "id": 1, + "title": "工作空间", + "icon": "layui-icon layui-icon-console", + "type": 0, + "children": [ + { + "id": "10", + "title": "分析页", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_component", + "href": "view/analysis/index.html" + }, + { + "id": "11", + "title": "工作台", + "icon": "layui-icon layui-icon-console", + "type": 1, + "openType": "_component", + "href": "view/console/index.html" + } + ] + }, + { + "id": 9, + "title": "列表页面", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "children": [ + { + "id": 91, + "title": "查询表格", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/listing/table.html" + } + ] + }, + { + "id": 2, + "title": "扩展组件", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "children": [ + { + "id": 21, + "title": "核心方法", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/component/admin.html" + }, + { + "id": 23, + "title": "高级栅格", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/component/grid.html" + }, + { + "id": 24, + "title": "消息提示", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/component/toast.html" + }, + { + "id": 25, + "title": "路由过渡", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/component/nprogress.html" + } + ] + }, + { + "id": "result", + "title": "结果页面", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "href": "", + "children": [ + { + "id": "success", + "title": "成功页面", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/result/success.html" + }, + { + "id": "failure", + "title": "失败页面", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_component", + "href": "view/result/error.html" + } + ] + }, + { + "id": "exception", + "title": "异常页面", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "href": "", + "children": [ + { + "id": "403", + "title": "403", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/exception/403.html" + }, + { + "id": "404", + "title": "404", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_component", + "href": "view/exception/404.html" + }, + { + "id": "500", + "title": "500", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_component", + "href": "view/exception/500.html" + } + ] + }, + { + "id": "open", + "title": "菜单模式", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "children": [ + { + "id": "a", + "title": "普通路由", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/result/success.html" + }, + { + "id": "b", + "title": "嵌套网页", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_iframe", + "href": "http://www.layui-vue.com" + }, + { + "id": "c", + "title": "新建标签", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_blank", + "href": "http://www.layui-vue.com" + }, + { + "id": "d", + "title": "弹窗网页", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_layer", + "href": "http://www.layui-vue.com" + } + ] + }, + { + "id": "deep", + "title": "深度测试", + "icon": "layui-icon layui-icon-auz", + "type": 0, + "href": "", + "children": [ + { + "id": "deep1-1", + "title": "二级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 0, + "openType": "_component", + "href": "view/result/success.html", + "children": [ + { + "id": "deep1-1-1", + "title": "三级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 0, + "openType": "_component", + "href": "view/result/success.html", + "children": [ + { + "id": "deep1-1-1-1", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/result/success.html" + }, + { + "id": "deep1-1-1-2", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_blank", + "href": "http://www.layui-vue.com" + } + ] + }, + { + "id": "deep1-1-2", + "title": "三级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 0, + "openType": "_blank", + "href": "http://www.layui-vue.com", + "children": [ + { + "id": "deep1-1-2-1", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/result/success.html" + }, + { + "id": "deep1-1-2-2", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_blank", + "href": "http://www.layui-vue.com" + } + ] + } + ] + }, + { + "id": "deep1-2", + "title": "二级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 0, + "openType": "_blank", + "href": "http://www.layui-vue.com", + "children": [ + { + "id": "deep1-2-1", + "title": "三级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 0, + "openType": "_component", + "href": "view/result/success.html", + "children": [ + { + "id": "deep1-2-1-1", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/result/success.html" + }, + { + "id": "deep1-2-1-2", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_blank", + "href": "http://www.layui-vue.com" + } + ] + }, + { + "id": "deep1-2-2", + "title": "三级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 0, + "openType": "_blank", + "href": "http://www.layui-vue.com", + "children": [ + { + "id": "deep1-2-2-1", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-smile", + "type": 1, + "openType": "_component", + "href": "view/result/success.html" + }, + { + "id": "deep1-2-2-2", + "title": "四级菜单", + "icon": "layui-icon layui-icon-face-cry", + "type": 1, + "openType": "_blank", + "href": "http://www.layui-vue.com" + } + ] + } + ] + } + ] + } +] +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/admin/data/message.json b/demo/webman/frontend/layui_admin_flow/admin/data/message.json new file mode 100644 index 0000000000000000000000000000000000000000..b95a924f37b6136c7c9482607c9845bb9a31b1c7 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/data/message.json @@ -0,0 +1,102 @@ +{ + "code": 200, + "data": [ + { + "id": 1, + "title": "通知", + "children": [ + { + "id": 11, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + "title": "你收到了 14 份新周报", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 12, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png", + "title": "曲妮妮 已通过第三轮面试", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 11, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png", + "title": "可以区分多种通知类型", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 12, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png", + "title": "左侧图标用于区分不同的类型", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 11, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + "title": "内容不要超过两行字", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + } + ] + }, + { + "id": 2, + "title": "消息", + "children": [ + { + "id": 11, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + "title": "你收到了 14 份新周报", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 12, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png", + "title": "曲妮妮 已通过第三轮面试", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 11, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png", + "title": "可以区分多种通知类型", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 12, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png", + "title": "左侧图标用于区分不同的类型", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + }, + { + "id": 11, + "avatar": "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + "title": "内容不要超过两行字", + "context": "这是消息内容。", + "form": "就眠仪式", + "time": "刚刚" + } + ] + }, + { + "id": 3, + "title": "代办", + "children": [] + } + ] +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/admin/data/table.json b/demo/webman/frontend/layui_admin_flow/admin/data/table.json new file mode 100644 index 0000000000000000000000000000000000000000..c0249f0cdd8cf4d78eab02d84eb5f8a0fb073440 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/data/table.json @@ -0,0 +1,303 @@ +{ + "code": 0, + "msg": "", + "count": 1000, + "totalRow": { + "era": { + "tang": "2", + "song": "2", + "xian": "20" + } + }, + "data": [ + { + "id": "10001", + "username": "就眠儀式", + "email": "test1@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10002", + "username": "杜甫", + "email": "test2@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "108", + "joinTime": "2016-10-14", + "LAY_CHECKED": true + }, + { + "id": "10003", + "username": "就眠儀式", + "email": "test3@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10004", + "username": "就眠儀式", + "email": "test4@email.com", + "sex": "女", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10005", + "username": "就眠儀式", + "email": "test5@email.com", + "sex": "女", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10006", + "username": "就眠儀式", + "email": "test6@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10007", + "username": "就眠儀式", + "email": "test7@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10008", + "username": "就眠儀式", + "email": "test8@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10009", + "username": "就眠儀式", + "email": "test9@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10010", + "username": "就眠儀式", + "email": "test10@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10011", + "username": "就眠儀式", + "email": "test11@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10012", + "username": "就眠儀式", + "email": "test12@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10013", + "username": "就眠儀式", + "email": "test13@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10014", + "username": "就眠儀式", + "email": "test14@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10015", + "username": "就眠儀式", + "email": "test15@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10016", + "username": "就眠儀式", + "email": "test16@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10017", + "username": "就眠儀式", + "email": "test17@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10018", + "username": "就眠儀式", + "email": "test18@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10019", + "username": "就眠儀式", + "email": "test19@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10020", + "username": "就眠儀式", + "email": "test20@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10021", + "username": "就眠儀式", + "email": "test21@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10022", + "username": "就眠儀式", + "email": "test22@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10023", + "username": "就眠儀式", + "email": "test23@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + }, + { + "id": "10024", + "username": "就眠儀式", + "email": "test24@email.com", + "sex": "男", + "city": "浙江杭州", + "sign": "花开堪折直须折,莫待无花空折枝.", + "experience": "100", + "ip": "192.168.0.8", + "checkin": "106", + "joinTime": "2016-10-14" + } + ] +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/admin/images/avatar.jpg b/demo/webman/frontend/layui_admin_flow/admin/images/avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..206a8b6c2def8679090c377e433a185dc92c501b Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/admin/images/avatar.jpg differ diff --git a/demo/webman/frontend/layui_admin_flow/admin/images/background.svg b/demo/webman/frontend/layui_admin_flow/admin/images/background.svg new file mode 100644 index 0000000000000000000000000000000000000000..1b153e0df5adb683065b92f39a78f1ccc9de7f94 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/admin/images/background.svg @@ -0,0 +1,68 @@ + + + Group 21 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/admin/images/banner.png b/demo/webman/frontend/layui_admin_flow/admin/images/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..a509ca6a55ac9b541d5f43d2a95117487fa5442e Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/admin/images/banner.png differ diff --git a/demo/webman/frontend/layui_admin_flow/admin/images/blog.jpg b/demo/webman/frontend/layui_admin_flow/admin/images/blog.jpg new file mode 100644 index 0000000000000000000000000000000000000000..46eb3da8faccbd3a2d0f025d2e20e5e281ec20d2 Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/admin/images/blog.jpg differ diff --git a/demo/webman/frontend/layui_admin_flow/admin/images/captcha.gif b/demo/webman/frontend/layui_admin_flow/admin/images/captcha.gif new file mode 100644 index 0000000000000000000000000000000000000000..2273bd45ecf14d496c781e8bc8b2442b6b0ecf69 Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/admin/images/captcha.gif differ diff --git a/demo/webman/frontend/layui_admin_flow/admin/images/logo.png b/demo/webman/frontend/layui_admin_flow/admin/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a3dbbf3375012028cee418c22f15249eed58cede Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/admin/images/logo.png differ diff --git a/demo/webman/frontend/layui_admin_flow/component/layui/css/layui.css b/demo/webman/frontend/layui_admin_flow/component/layui/css/layui.css new file mode 100644 index 0000000000000000000000000000000000000000..c075f1073445cd00f946c981b912d9be8ad6800e --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/layui/css/layui.css @@ -0,0 +1 @@ +blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:active,a:hover{outline:0}img{display:inline-block;border:none;vertical-align:middle}li{list-style:none}table{border-collapse:collapse;border-spacing:0}h1,h2,h3,h4{font-weight:700}h5,h6{font-weight:500;font-size:100%}button,input,select,textarea{font-size:100%}button,input,optgroup,option,select,textarea{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;outline:0}pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}body{line-height:1.6;color:#333;color:rgba(0,0,0,.85);font:14px Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif}hr{height:0;line-height:0;margin:10px 0;padding:0;border:none;border-bottom:1px solid #eee;clear:both;overflow:hidden;background:0 0}a{color:#333;text-decoration:none}a:hover{color:#777}a cite{font-style:normal;*cursor:pointer}.layui-border-box,.layui-border-box *{box-sizing:border-box}.layui-box,.layui-box *{box-sizing:content-box}.layui-clear{clear:both;*zoom:1}.layui-clear:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-clear-space{word-spacing:-5px}.layui-inline{position:relative;display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.layui-edge{position:relative;display:inline-block;vertical-align:middle;width:0;height:0;border-width:6px;border-style:dashed;border-color:transparent;overflow:hidden}.layui-edge-top{top:-4px;border-bottom-color:#999;border-bottom-style:solid}.layui-edge-right{border-left-color:#999;border-left-style:solid}.layui-edge-bottom{top:2px;border-top-color:#999;border-top-style:solid}.layui-edge-left{border-right-color:#999;border-right-style:solid}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-disabled,.layui-icon,.layui-unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-disabled,.layui-disabled:hover{color:#d2d2d2!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-show-v{visibility:visible!important}.layui-hide-v{visibility:hidden!important}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=282);src:url(../font/iconfont.eot?v=282#iefix) format('embedded-opentype'),url(../font/iconfont.woff2?v=282) format('woff2'),url(../font/iconfont.woff?v=282) format('woff'),url(../font/iconfont.ttf?v=282) format('truetype'),url(../font/iconfont.svg?v=282#layui-icon) format('svg')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-icon-leaf:before{content:"\e701"}.layui-icon-folder:before{content:"\eabe"}.layui-icon-folder-open:before{content:"\eac1"}.layui-icon-gitee:before{content:"\e69b"}.layui-icon-github:before{content:"\e6a7"}.layui-icon-disabled:before{content:"\e6cc"}.layui-icon-moon:before{content:"\e6c2"}.layui-icon-error:before{content:"\e693"}.layui-icon-success:before{content:"\e697"}.layui-icon-question:before{content:"\e699"}.layui-icon-lock:before{content:"\e69a"}.layui-icon-eye:before{content:"\e695"}.layui-icon-eye-invisible:before{content:"\e696"}.layui-icon-backspace:before{content:"\e694"}.layui-icon-tips-fill:before{content:"\eb2e"}.layui-icon-test:before{content:"\e692"}.layui-icon-clear:before{content:"\e788"}.layui-icon-heart-fill:before{content:"\e68f"}.layui-icon-light:before{content:"\e748"}.layui-icon-music:before{content:"\e690"}.layui-icon-time:before{content:"\e68d"}.layui-icon-ie:before{content:"\e7bb"}.layui-icon-firefox:before{content:"\e686"}.layui-icon-at:before{content:"\e687"}.layui-icon-bluetooth:before{content:"\e689"}.layui-icon-chrome:before{content:"\e68a"}.layui-icon-edge:before{content:"\e68b"}.layui-icon-heart:before{content:"\e68c"}.layui-icon-key:before{content:"\e683"}.layui-icon-android:before{content:"\e684"}.layui-icon-mike:before{content:"\e6dc"}.layui-icon-mute:before{content:"\e685"}.layui-icon-gift:before{content:"\e627"}.layui-icon-windows:before{content:"\e67f"}.layui-icon-ios:before{content:"\e680"}.layui-icon-logout:before{content:"\e682"}.layui-icon-wifi:before{content:"\e7e0"}.layui-icon-rss:before{content:"\e808"}.layui-icon-email:before{content:"\e618"}.layui-icon-reduce-circle:before{content:"\e616"}.layui-icon-transfer:before{content:"\e691"}.layui-icon-service:before{content:"\e626"}.layui-icon-addition:before{content:"\e624"}.layui-icon-subtraction:before{content:"\e67e"}.layui-icon-slider:before{content:"\e714"}.layui-icon-print:before{content:"\e66d"}.layui-icon-export:before{content:"\e67d"}.layui-icon-cols:before{content:"\e610"}.layui-icon-screen-full:before{content:"\e622"}.layui-icon-screen-restore:before{content:"\e758"}.layui-icon-rate-half:before{content:"\e6c9"}.layui-icon-rate-solid:before{content:"\e67a"}.layui-icon-rate:before{content:"\e67b"}.layui-icon-cellphone:before{content:"\e678"}.layui-icon-vercode:before{content:"\e679"}.layui-icon-login-weibo:before{content:"\e675"}.layui-icon-login-qq:before{content:"\e676"}.layui-icon-login-wechat:before{content:"\e677"}.layui-icon-username:before{content:"\e66f"}.layui-icon-password:before{content:"\e673"}.layui-icon-refresh-3:before{content:"\e9aa"}.layui-icon-auz:before{content:"\e672"}.layui-icon-shrink-right:before{content:"\e668"}.layui-icon-spread-left:before{content:"\e66b"}.layui-icon-snowflake:before{content:"\e6b1"}.layui-icon-tips:before{content:"\e702"}.layui-icon-note:before{content:"\e66e"}.layui-icon-senior:before{content:"\e674"}.layui-icon-refresh-1:before{content:"\e666"}.layui-icon-refresh:before{content:"\e669"}.layui-icon-flag:before{content:"\e66c"}.layui-icon-theme:before{content:"\e66a"}.layui-icon-notice:before{content:"\e667"}.layui-icon-console:before{content:"\e665"}.layui-icon-website:before{content:"\e7ae"}.layui-icon-face-surprised:before{content:"\e664"}.layui-icon-set:before{content:"\e716"}.layui-icon-template:before{content:"\e663"}.layui-icon-app:before{content:"\e653"}.layui-icon-template-1:before{content:"\e656"}.layui-icon-home:before{content:"\e68e"}.layui-icon-female:before{content:"\e661"}.layui-icon-male:before{content:"\e662"}.layui-icon-tread:before{content:"\e6c5"}.layui-icon-praise:before{content:"\e6c6"}.layui-icon-rmb:before{content:"\e65e"}.layui-icon-more:before{content:"\e65f"}.layui-icon-camera:before{content:"\e660"}.layui-icon-cart-simple:before{content:"\e698"}.layui-icon-face-cry:before{content:"\e69c"}.layui-icon-face-smile:before{content:"\e6af"}.layui-icon-survey:before{content:"\e6b2"}.layui-icon-read:before{content:"\e705"}.layui-icon-location:before{content:"\e715"}.layui-icon-dollar:before{content:"\e659"}.layui-icon-diamond:before{content:"\e735"}.layui-icon-return:before{content:"\e65c"}.layui-icon-camera-fill:before{content:"\e65d"}.layui-icon-fire:before{content:"\e756"}.layui-icon-more-vertical:before{content:"\e671"}.layui-icon-cart:before{content:"\e657"}.layui-icon-star-fill:before{content:"\e658"}.layui-icon-prev:before{content:"\e65a"}.layui-icon-next:before{content:"\e65b"}.layui-icon-upload:before{content:"\e67c"}.layui-icon-upload-drag:before{content:"\e681"}.layui-icon-user:before{content:"\e770"}.layui-icon-file-b:before{content:"\e655"}.layui-icon-component:before{content:"\e857"}.layui-icon-find-fill:before{content:"\e670"}.layui-icon-loading:before{content:"\e63d"}.layui-icon-loading-1:before{content:"\e63e"}.layui-icon-add-1:before{content:"\e654"}.layui-icon-pause:before{content:"\e651"}.layui-icon-play:before{content:"\e652"}.layui-icon-video:before{content:"\e6ed"}.layui-icon-headset:before{content:"\e6fc"}.layui-icon-voice:before{content:"\e688"}.layui-icon-speaker:before{content:"\e645"}.layui-icon-fonts-del:before{content:"\e64f"}.layui-icon-fonts-html:before{content:"\e64b"}.layui-icon-fonts-code:before{content:"\e64e"}.layui-icon-fonts-strong:before{content:"\e62b"}.layui-icon-unlink:before{content:"\e64d"}.layui-icon-picture:before{content:"\e64a"}.layui-icon-link:before{content:"\e64c"}.layui-icon-face-smile-b:before{content:"\e650"}.layui-icon-align-center:before{content:"\e647"}.layui-icon-align-right:before{content:"\e648"}.layui-icon-align-left:before{content:"\e649"}.layui-icon-fonts-u:before{content:"\e646"}.layui-icon-fonts-i:before{content:"\e644"}.layui-icon-tabs:before{content:"\e62a"}.layui-icon-circle:before{content:"\e63f"}.layui-icon-radio:before{content:"\e643"}.layui-icon-share:before{content:"\e641"}.layui-icon-edit:before{content:"\e642"}.layui-icon-delete:before{content:"\e640"}.layui-icon-engine:before{content:"\e628"}.layui-icon-chart-screen:before{content:"\e629"}.layui-icon-chart:before{content:"\e62c"}.layui-icon-table:before{content:"\e62d"}.layui-icon-tree:before{content:"\e62e"}.layui-icon-upload-circle:before{content:"\e62f"}.layui-icon-templeate-1:before{content:"\e630"}.layui-icon-util:before{content:"\e631"}.layui-icon-layouts:before{content:"\e632"}.layui-icon-prev-circle:before{content:"\e633"}.layui-icon-carousel:before{content:"\e634"}.layui-icon-code-circle:before{content:"\e635"}.layui-icon-water:before{content:"\e636"}.layui-icon-date:before{content:"\e637"}.layui-icon-layer:before{content:"\e638"}.layui-icon-fonts-clear:before{content:"\e639"}.layui-icon-dialogue:before{content:"\e63a"}.layui-icon-cellphone-fine:before{content:"\e63b"}.layui-icon-form:before{content:"\e63c"}.layui-icon-file:before{content:"\e621"}.layui-icon-triangle-r:before{content:"\e623"}.layui-icon-triangle-d:before{content:"\e625"}.layui-icon-set-sm:before{content:"\e620"}.layui-icon-add-circle:before{content:"\e61f"}.layui-icon-layim-download:before{content:"\e61e"}.layui-icon-layim-uploadfile:before{content:"\e61d"}.layui-icon-404:before{content:"\e61c"}.layui-icon-about:before{content:"\e60b"}.layui-icon-layim-theme:before{content:"\e61b"}.layui-icon-down:before{content:"\e61a"}.layui-icon-up:before{content:"\e619"}.layui-icon-circle-dot:before{content:"\e617"}.layui-icon-set-fill:before{content:"\e614"}.layui-icon-search:before{content:"\e615"}.layui-icon-friends:before{content:"\e612"}.layui-icon-group:before{content:"\e613"}.layui-icon-reply-fill:before{content:"\e611"}.layui-icon-menu-fill:before{content:"\e60f"}.layui-icon-face-smile-fine:before{content:"\e60c"}.layui-icon-picture-fine:before{content:"\e60d"}.layui-icon-log:before{content:"\e60e"}.layui-icon-list:before{content:"\e60a"}.layui-icon-release:before{content:"\e609"}.layui-icon-add-circle-fine:before{content:"\e608"}.layui-icon-ok:before{content:"\e605"}.layui-icon-help:before{content:"\e607"}.layui-icon-chat:before{content:"\e606"}.layui-icon-top:before{content:"\e604"}.layui-icon-right:before{content:"\e602"}.layui-icon-left:before{content:"\e603"}.layui-icon-star:before{content:"\e600"}.layui-icon-download-circle:before{content:"\e601"}.layui-icon-close:before{content:"\1006"}.layui-icon-close-fill:before{content:"\1007"}.layui-icon-ok-circle:before{content:"\1005"}.layui-main{position:relative;width:1160px;margin:0 auto}.layui-header{position:relative;z-index:1000;height:60px}.layui-header a:hover{transition:all .5s;-webkit-transition:all .5s}.layui-side{position:fixed;left:0;top:0;bottom:0;z-index:999;width:200px;overflow-x:hidden}.layui-side-scroll{position:relative;width:220px;height:100%;overflow-x:hidden}.layui-body{position:relative;left:200px;right:0;top:0;bottom:0;z-index:900;width:auto;box-sizing:border-box}.layui-layout-body{overflow-x:hidden}.layui-layout-admin .layui-header{position:fixed;top:0;left:0;right:0;background-color:#23292e}.layui-layout-admin .layui-side{top:60px;width:200px;overflow-x:hidden}.layui-layout-admin .layui-body{position:absolute;top:60px;padding-bottom:44px}.layui-layout-admin .layui-main{width:auto;margin:0 15px}.layui-layout-admin .layui-footer{position:fixed;left:200px;right:0;bottom:0;z-index:990;height:44px;line-height:44px;padding:0 15px;box-shadow:-1px 0 4px rgb(0 0 0 / 12%);background-color:#fafafa}.layui-layout-admin .layui-logo{position:absolute;left:0;top:0;width:200px;height:100%;line-height:60px;text-align:center;color:#16baaa;font-size:16px;box-shadow:0 1px 2px 0 rgb(0 0 0 / 15%)}.layui-layout-admin .layui-header .layui-nav{background:0 0}.layui-layout-left{position:absolute!important;left:200px;top:0}.layui-layout-right{position:absolute!important;right:0;top:0}.layui-container{position:relative;margin:0 auto;box-sizing:border-box}.layui-fluid{position:relative;margin:0 auto;padding:0 15px}.layui-row:after,.layui-row:before{content:"";display:block;clear:both}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9,.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9,.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9,.layui-col-xl1,.layui-col-xl10,.layui-col-xl11,.layui-col-xl12,.layui-col-xl2,.layui-col-xl3,.layui-col-xl4,.layui-col-xl5,.layui-col-xl6,.layui-col-xl7,.layui-col-xl8,.layui-col-xl9,.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{position:relative;display:block;box-sizing:border-box}.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{float:left}.layui-col-xs1{width:8.33333333%}.layui-col-xs2{width:16.66666667%}.layui-col-xs3{width:25%}.layui-col-xs4{width:33.33333333%}.layui-col-xs5{width:41.66666667%}.layui-col-xs6{width:50%}.layui-col-xs7{width:58.33333333%}.layui-col-xs8{width:66.66666667%}.layui-col-xs9{width:75%}.layui-col-xs10{width:83.33333333%}.layui-col-xs11{width:91.66666667%}.layui-col-xs12{width:100%}.layui-col-xs-offset1{margin-left:8.33333333%}.layui-col-xs-offset2{margin-left:16.66666667%}.layui-col-xs-offset3{margin-left:25%}.layui-col-xs-offset4{margin-left:33.33333333%}.layui-col-xs-offset5{margin-left:41.66666667%}.layui-col-xs-offset6{margin-left:50%}.layui-col-xs-offset7{margin-left:58.33333333%}.layui-col-xs-offset8{margin-left:66.66666667%}.layui-col-xs-offset9{margin-left:75%}.layui-col-xs-offset10{margin-left:83.33333333%}.layui-col-xs-offset11{margin-left:91.66666667%}.layui-col-xs-offset12{margin-left:100%}@media screen and (max-width:767.98px){.layui-container{padding:0 15px}.layui-hide-xs{display:none!important}.layui-show-xs-block{display:block!important}.layui-show-xs-inline{display:inline!important}.layui-show-xs-inline-block{display:inline-block!important}}@media screen and (min-width:768px){.layui-container{width:720px}.layui-hide-sm{display:none!important}.layui-show-sm-block{display:block!important}.layui-show-sm-inline{display:inline!important}.layui-show-sm-inline-block{display:inline-block!important}.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9{float:left}.layui-col-sm1{width:8.33333333%}.layui-col-sm2{width:16.66666667%}.layui-col-sm3{width:25%}.layui-col-sm4{width:33.33333333%}.layui-col-sm5{width:41.66666667%}.layui-col-sm6{width:50%}.layui-col-sm7{width:58.33333333%}.layui-col-sm8{width:66.66666667%}.layui-col-sm9{width:75%}.layui-col-sm10{width:83.33333333%}.layui-col-sm11{width:91.66666667%}.layui-col-sm12{width:100%}.layui-col-sm-offset1{margin-left:8.33333333%}.layui-col-sm-offset2{margin-left:16.66666667%}.layui-col-sm-offset3{margin-left:25%}.layui-col-sm-offset4{margin-left:33.33333333%}.layui-col-sm-offset5{margin-left:41.66666667%}.layui-col-sm-offset6{margin-left:50%}.layui-col-sm-offset7{margin-left:58.33333333%}.layui-col-sm-offset8{margin-left:66.66666667%}.layui-col-sm-offset9{margin-left:75%}.layui-col-sm-offset10{margin-left:83.33333333%}.layui-col-sm-offset11{margin-left:91.66666667%}.layui-col-sm-offset12{margin-left:100%}}@media screen and (min-width:992px){.layui-container{width:960px}.layui-hide-md{display:none!important}.layui-show-md-block{display:block!important}.layui-show-md-inline{display:inline!important}.layui-show-md-inline-block{display:inline-block!important}.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9{float:left}.layui-col-md1{width:8.33333333%}.layui-col-md2{width:16.66666667%}.layui-col-md3{width:25%}.layui-col-md4{width:33.33333333%}.layui-col-md5{width:41.66666667%}.layui-col-md6{width:50%}.layui-col-md7{width:58.33333333%}.layui-col-md8{width:66.66666667%}.layui-col-md9{width:75%}.layui-col-md10{width:83.33333333%}.layui-col-md11{width:91.66666667%}.layui-col-md12{width:100%}.layui-col-md-offset1{margin-left:8.33333333%}.layui-col-md-offset2{margin-left:16.66666667%}.layui-col-md-offset3{margin-left:25%}.layui-col-md-offset4{margin-left:33.33333333%}.layui-col-md-offset5{margin-left:41.66666667%}.layui-col-md-offset6{margin-left:50%}.layui-col-md-offset7{margin-left:58.33333333%}.layui-col-md-offset8{margin-left:66.66666667%}.layui-col-md-offset9{margin-left:75%}.layui-col-md-offset10{margin-left:83.33333333%}.layui-col-md-offset11{margin-left:91.66666667%}.layui-col-md-offset12{margin-left:100%}}@media screen and (min-width:1200px){.layui-container{width:1150px}.layui-hide-lg{display:none!important}.layui-show-lg-block{display:block!important}.layui-show-lg-inline{display:inline!important}.layui-show-lg-inline-block{display:inline-block!important}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9{float:left}.layui-col-lg1{width:8.33333333%}.layui-col-lg2{width:16.66666667%}.layui-col-lg3{width:25%}.layui-col-lg4{width:33.33333333%}.layui-col-lg5{width:41.66666667%}.layui-col-lg6{width:50%}.layui-col-lg7{width:58.33333333%}.layui-col-lg8{width:66.66666667%}.layui-col-lg9{width:75%}.layui-col-lg10{width:83.33333333%}.layui-col-lg11{width:91.66666667%}.layui-col-lg12{width:100%}.layui-col-lg-offset1{margin-left:8.33333333%}.layui-col-lg-offset2{margin-left:16.66666667%}.layui-col-lg-offset3{margin-left:25%}.layui-col-lg-offset4{margin-left:33.33333333%}.layui-col-lg-offset5{margin-left:41.66666667%}.layui-col-lg-offset6{margin-left:50%}.layui-col-lg-offset7{margin-left:58.33333333%}.layui-col-lg-offset8{margin-left:66.66666667%}.layui-col-lg-offset9{margin-left:75%}.layui-col-lg-offset10{margin-left:83.33333333%}.layui-col-lg-offset11{margin-left:91.66666667%}.layui-col-lg-offset12{margin-left:100%}}@media screen and (min-width:1400px){.layui-container{width:1330px}.layui-hide-xl{display:none!important}.layui-show-xl-block{display:block!important}.layui-show-xl-inline{display:inline!important}.layui-show-xl-inline-block{display:inline-block!important}.layui-col-xl1,.layui-col-xl10,.layui-col-xl11,.layui-col-xl12,.layui-col-xl2,.layui-col-xl3,.layui-col-xl4,.layui-col-xl5,.layui-col-xl6,.layui-col-xl7,.layui-col-xl8,.layui-col-xl9{float:left}.layui-col-xl1{width:8.33333333%}.layui-col-xl2{width:16.66666667%}.layui-col-xl3{width:25%}.layui-col-xl4{width:33.33333333%}.layui-col-xl5{width:41.66666667%}.layui-col-xl6{width:50%}.layui-col-xl7{width:58.33333333%}.layui-col-xl8{width:66.66666667%}.layui-col-xl9{width:75%}.layui-col-xl10{width:83.33333333%}.layui-col-xl11{width:91.66666667%}.layui-col-xl12{width:100%}.layui-col-xl-offset1{margin-left:8.33333333%}.layui-col-xl-offset2{margin-left:16.66666667%}.layui-col-xl-offset3{margin-left:25%}.layui-col-xl-offset4{margin-left:33.33333333%}.layui-col-xl-offset5{margin-left:41.66666667%}.layui-col-xl-offset6{margin-left:50%}.layui-col-xl-offset7{margin-left:58.33333333%}.layui-col-xl-offset8{margin-left:66.66666667%}.layui-col-xl-offset9{margin-left:75%}.layui-col-xl-offset10{margin-left:83.33333333%}.layui-col-xl-offset11{margin-left:91.66666667%}.layui-col-xl-offset12{margin-left:100%}}.layui-col-space1{margin:-.5px}.layui-col-space1>*{padding:.5px}.layui-col-space2{margin:-1px}.layui-col-space2>*{padding:1px}.layui-col-space4{margin:-2px}.layui-col-space4>*{padding:2px}.layui-col-space5{margin:-2.5px}.layui-col-space5>*{padding:2.5px}.layui-col-space6{margin:-3px}.layui-col-space6>*{padding:3px}.layui-col-space8{margin:-4px}.layui-col-space8>*{padding:4px}.layui-col-space10{margin:-5px}.layui-col-space10>*{padding:5px}.layui-col-space12{margin:-6px}.layui-col-space12>*{padding:6px}.layui-col-space14{margin:-7px}.layui-col-space14>*{padding:7px}.layui-col-space15{margin:-7.5px}.layui-col-space15>*{padding:7.5px}.layui-col-space16{margin:-8px}.layui-col-space16>*{padding:8px}.layui-col-space18{margin:-9px}.layui-col-space18>*{padding:9px}.layui-col-space20{margin:-10px}.layui-col-space20>*{padding:10px}.layui-col-space22{margin:-11px}.layui-col-space22>*{padding:11px}.layui-col-space24{margin:-12px}.layui-col-space24>*{padding:12px}.layui-col-space25{margin:-12.5px}.layui-col-space25>*{padding:12.5px}.layui-col-space26{margin:-13px}.layui-col-space26>*{padding:13px}.layui-col-space28{margin:-14px}.layui-col-space28>*{padding:14px}.layui-col-space30{margin:-15px}.layui-col-space30>*{padding:15px}.layui-col-space32{margin:-16px}.layui-col-space32>*{padding:16px}.layui-padding-1{padding:4px!important}.layui-padding-2{padding:8px!important}.layui-padding-3{padding:16px!important}.layui-padding-4{padding:32px!important}.layui-padding-5{padding:48px!important}.layui-margin-1{margin:4px!important}.layui-margin-2{margin:8px!important}.layui-margin-3{margin:16px!important}.layui-margin-4{margin:32px!important}.layui-margin-5{margin:48px!important}.layui-btn,.layui-input,.layui-select,.layui-textarea,.layui-upload-button{outline:0;-webkit-appearance:none;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-elem-quote{margin-bottom:10px;padding:15px;line-height:1.8;border-left:5px solid #16b777;border-radius:0 2px 2px 0;background-color:#fafafa}.layui-quote-nm{border-style:solid;border-width:1px;border-left-width:5px;background:0 0}.layui-elem-field{margin-bottom:10px;padding:0;border-width:1px;border-style:solid}.layui-elem-field legend{margin-left:20px;padding:0 10px;font-size:20px}.layui-field-title{margin:16px 0;border-width:0;border-top-width:1px}.layui-field-box{padding:15px}.layui-field-title .layui-field-box{padding:10px 0}.layui-progress{position:relative;height:6px;border-radius:20px;background-color:#eee}.layui-progress-bar{position:absolute;left:0;top:0;width:0;max-width:100%;height:6px;border-radius:20px;text-align:right;background-color:#16b777;transition:all .3s;-webkit-transition:all .3s}.layui-progress-big,.layui-progress-big .layui-progress-bar{height:18px;line-height:18px}.layui-progress-text{position:relative;top:-20px;line-height:18px;font-size:12px;color:#5f5f5f}.layui-progress-big .layui-progress-text{position:static;padding:0 10px;color:#fff}.layui-collapse{border-width:1px;border-style:solid;border-radius:2px}.layui-colla-content,.layui-colla-item{border-top-width:1px;border-top-style:solid}.layui-colla-item:first-child{border-top:none}.layui-colla-title{position:relative;height:42px;line-height:42px;padding:0 15px 0 35px;color:#333;background-color:#fafafa;cursor:pointer;font-size:14px;overflow:hidden}.layui-colla-content{display:none;padding:10px 15px;line-height:1.6;color:#5f5f5f}.layui-colla-icon{position:absolute;left:15px;top:0;font-size:14px}.layui-card{margin-bottom:15px;border-radius:2px;background-color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.layui-card:last-child{margin-bottom:0}.layui-card-header{position:relative;height:42px;line-height:42px;padding:0 15px;border-bottom:1px solid #f8f8f8;color:#333;border-radius:2px 2px 0 0;font-size:14px}.layui-card-body{position:relative;padding:10px 15px;line-height:24px}.layui-card-body[pad15]{padding:15px}.layui-card-body[pad20]{padding:20px}.layui-card-body .layui-table{margin:5px 0}.layui-card .layui-tab{margin:0}.layui-panel{position:relative;border-width:1px;border-style:solid;border-radius:2px;box-shadow:1px 1px 4px rgb(0 0 0 / 8%);background-color:#fff;color:#5f5f5f}.layui-panel-window{position:relative;padding:15px;border-radius:0;border-top:5px solid #eee;background-color:#fff}.layui-auxiliar-moving{position:fixed;left:0;right:0;top:0;bottom:0;width:100%;height:100%;background:0 0;z-index:9999999999}.layui-scrollbar-hide{overflow:hidden!important}.layui-bg-red{background-color:#ff5722!important;color:#fff!important}.layui-bg-orange{background-color:#ffb800!important;color:#fff!important}.layui-bg-green{background-color:#16baaa!important;color:#fff!important}.layui-bg-cyan{background-color:#2f4056!important;color:#fff!important}.layui-bg-blue{background-color:#1e9fff!important;color:#fff!important}.layui-bg-purple{background-color:#a233c6!important;color:#fff!important}.layui-bg-black{background-color:#2f363c!important;color:#fff!important}.layui-bg-gray{background-color:#fafafa!important;color:#5f5f5f!important}.layui-badge-rim,.layui-border,.layui-colla-content,.layui-colla-item,.layui-collapse,.layui-elem-field,.layui-form-pane .layui-form-item[pane],.layui-form-pane .layui-form-label,.layui-input,.layui-input-split,.layui-panel,.layui-quote-nm,.layui-select,.layui-tab-bar,.layui-tab-card,.layui-tab-title,.layui-tab-title .layui-this:after,.layui-textarea{border-color:#eee}.layui-border{border-width:1px;border-style:solid;color:#5f5f5f!important}.layui-border-red{border-width:1px;border-style:solid;border-color:#ff5722!important;color:#ff5722!important}.layui-border-orange{border-width:1px;border-style:solid;border-color:#ffb800!important;color:#ffb800!important}.layui-border-green{border-width:1px;border-style:solid;border-color:#16baaa!important;color:#16baaa!important}.layui-border-cyan{border-width:1px;border-style:solid;border-color:#2f4056!important;color:#2f4056!important}.layui-border-blue{border-width:1px;border-style:solid;border-color:#1e9fff!important;color:#1e9fff!important}.layui-border-purple{border-width:1px;border-style:solid;border-color:#a233c6!important;color:#a233c6!important}.layui-border-black{border-width:1px;border-style:solid;border-color:#2f363c!important;color:#2f363c!important}hr.layui-border-black,hr.layui-border-blue,hr.layui-border-cyan,hr.layui-border-green,hr.layui-border-orange,hr.layui-border-purple,hr.layui-border-red{border-width:0 0 1px}.layui-timeline-item:before{background-color:#eee}.layui-text{line-height:1.8;font-size:14px}.layui-text h1,.layui-text h2,.layui-text h3,.layui-text h4,.layui-text h5,.layui-text h6{color:#3a3a3a}.layui-text h1{font-size:32px}.layui-text h2{font-size:24px}.layui-text h3{font-size:18px}.layui-text h4{font-size:16px}.layui-text h5{font-size:14px}.layui-text h6{font-size:13px}.layui-text ol,.layui-text ul{padding-left:15px}.layui-text ul li{margin-top:5px;list-style-type:disc}.layui-text ol li{margin-top:5px;list-style-type:decimal}.layui-text-em,.layui-word-aux{color:#999!important;padding-left:5px!important;padding-right:5px!important}.layui-text p{margin:15px 0}.layui-text p:first-child{margin-top:0}.layui-text p:last-child{margin-bottom:0}.layui-text a:not(.layui-btn){color:#01aaed}.layui-text a:not(.layui-btn):hover{text-decoration:underline}.layui-text blockquote:not(.layui-elem-quote){padding:5px 15px;border-left:5px solid #eee}.layui-text pre>code:not(.layui-code){padding:15px;font-family:"Courier New",Consolas,"Lucida Console"}.layui-font-12{font-size:12px!important}.layui-font-13{font-size:13px!important}.layui-font-14{font-size:14px!important}.layui-font-16{font-size:16px!important}.layui-font-18{font-size:18px!important}.layui-font-20{font-size:20px!important}.layui-font-22{font-size:22px!important}.layui-font-24{font-size:24px!important}.layui-font-26{font-size:26px!important}.layui-font-28{font-size:28px!important}.layui-font-30{font-size:30px!important}.layui-font-32{font-size:32px!important}.layui-font-red{color:#ff5722!important}.layui-font-orange{color:#ffb800!important}.layui-font-green{color:#16baaa!important}.layui-font-cyan{color:#2f4056!important}.layui-font-blue{color:#01aaed!important}.layui-font-purple{color:#a233c6!important}.layui-font-black{color:#000!important}.layui-font-gray{color:#c2c2c2!important}.layui-btn{display:inline-block;vertical-align:middle;height:38px;line-height:38px;border:1px solid transparent;padding:0 18px;background-color:#16baaa;color:#fff;white-space:nowrap;text-align:center;font-size:14px;border-radius:2px;cursor:pointer;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-btn:hover{opacity:.8;filter:alpha(opacity=80);color:#fff}.layui-btn:active{opacity:1;filter:alpha(opacity=100)}.layui-btn+.layui-btn{margin-left:10px}.layui-btn-container{word-spacing:-5px}.layui-btn-container .layui-btn{margin-right:10px;margin-bottom:10px;word-spacing:normal}.layui-btn-container .layui-btn+.layui-btn{margin-left:0}.layui-table .layui-btn-container .layui-btn{margin-bottom:9px}.layui-btn-radius{border-radius:100px}.layui-btn .layui-icon{padding:0 2px;vertical-align:middle\0;vertical-align:bottom}.layui-btn-primary{border-color:#d2d2d2;background:0 0;color:#5f5f5f}.layui-btn-primary:hover{border-color:#16baaa;color:#333}.layui-btn-normal{background-color:#1e9fff}.layui-btn-warm{background-color:#ffb800}.layui-btn-danger{background-color:#ff5722}.layui-btn-checked{background-color:#16b777}.layui-btn-disabled,.layui-btn-disabled:active,.layui-btn-disabled:hover{border-color:#eee!important;background-color:#fbfbfb!important;color:#d2d2d2!important;cursor:not-allowed!important;opacity:1}.layui-btn-lg{height:44px;line-height:44px;padding:0 25px;font-size:16px}.layui-btn-sm{height:30px;line-height:30px;padding:0 10px;font-size:12px}.layui-btn-xs{height:22px;line-height:22px;padding:0 5px;font-size:12px}.layui-btn-xs i{font-size:12px!important}.layui-btn-group{display:inline-block;vertical-align:middle;font-size:0}.layui-btn-group .layui-btn{margin-left:0!important;margin-right:0!important;border-left:1px solid rgba(255,255,255,.5);border-radius:0}.layui-btn-group .layui-btn-primary{border-left:none}.layui-btn-group .layui-btn-primary:hover{border-color:#d2d2d2;color:#16baaa}.layui-btn-group .layui-btn:first-child{border-left:none;border-radius:2px 0 0 2px}.layui-btn-group .layui-btn-primary:first-child{border-left:1px solid #d2d2d2}.layui-btn-group .layui-btn:last-child{border-radius:0 2px 2px 0}.layui-btn-group .layui-btn+.layui-btn{margin-left:0}.layui-btn-group+.layui-btn-group{margin-left:10px}.layui-btn-fluid{width:100%}.layui-input,.layui-select,.layui-textarea{height:38px;line-height:1.3;line-height:38px\9;border-width:1px;border-style:solid;background-color:#fff;color:rgba(0,0,0,.85);border-radius:2px}.layui-input::-webkit-input-placeholder,.layui-select::-webkit-input-placeholder,.layui-textarea::-webkit-input-placeholder{line-height:1.3}.layui-input,.layui-textarea{display:block;width:100%;padding-left:10px}.layui-input:hover,.layui-textarea:hover{border-color:#d2d2d2!important}.layui-input:focus,.layui-textarea:focus{border-color:#16b777!important;box-shadow:0 0 0 3px rgba(22,183,119,.08)}.layui-textarea{position:relative;min-height:100px;height:auto;line-height:20px;padding:6px 10px;resize:vertical}.layui-input[disabled],.layui-textarea[disabled]{background-color:#fafafa}.layui-select{padding:0 10px}.layui-form input[type=checkbox],.layui-form input[type=radio],.layui-form select{display:none}.layui-form [lay-ignore]{display:initial}.layui-form-item{position:relative;margin-bottom:15px;clear:both;*zoom:1}.layui-form-item:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-form-label{position:relative;float:left;display:block;padding:9px 15px;width:80px;font-weight:400;line-height:20px;text-align:right}.layui-form-label-col{display:block;float:none;padding:9px 0;line-height:20px;text-align:left}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block,.layui-input-inline{position:relative}.layui-input-block{margin-left:110px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{position:relative;float:left;display:block;padding:9px 0!important;line-height:20px;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border-color:#ff5722!important;box-shadow:0 0 0 3px rgba(255,87,34,.08)}.layui-input-prefix,.layui-input-split,.layui-input-suffix,.layui-input-suffix .layui-input-affix{position:absolute;right:0;top:0;padding:0 10px;width:35px;height:100%;text-align:center;transition:all .3s;box-sizing:border-box}.layui-input-prefix{left:0;border-radius:2px 0 0 2px}.layui-input-suffix{right:0;border-radius:0 2px 2px 0}.layui-input-split{border-width:1px;border-style:solid}.layui-input-prefix .layui-icon,.layui-input-split .layui-icon,.layui-input-suffix .layui-icon{position:relative;font-size:16px;color:#5f5f5f;transition:all .3s}.layui-input-group{position:relative;display:table;box-sizing:border-box}.layui-input-group>*{display:table-cell;vertical-align:middle;position:relative}.layui-input-group .layui-input{padding-right:15px}.layui-input-group>.layui-input-prefix{width:auto;border-right:0}.layui-input-group>.layui-input-suffix{width:auto;border-left:0}.layui-input-group .layui-input-split{white-space:nowrap}.layui-input-wrap{position:relative;line-height:38px}.layui-input-wrap .layui-input{padding-right:35px}.layui-input-wrap .layui-input::-ms-clear,.layui-input-wrap .layui-input::-ms-reveal{display:none}.layui-input-wrap .layui-input-prefix+.layui-input,.layui-input-wrap .layui-input-prefix~* .layui-input{padding-left:35px}.layui-input-wrap .layui-input-split+.layui-input,.layui-input-wrap .layui-input-split~* .layui-input{padding-left:45px}.layui-input-wrap .layui-input-prefix~.layui-form-select{position:static}.layui-input-wrap .layui-input-prefix,.layui-input-wrap .layui-input-split,.layui-input-wrap .layui-input-suffix{pointer-events:none}.layui-input-wrap .layui-input:hover+.layui-input-split{border-color:#d2d2d2}.layui-input-wrap .layui-input:focus+.layui-input-split{border-color:#16b777}.layui-input-wrap .layui-input.layui-form-danger:focus+.layui-input-split{border-color:#ff5722}.layui-input-wrap .layui-input-prefix.layui-input-split{border-width:0;border-right-width:1px}.layui-input-affix{line-height:38px}.layui-input-suffix .layui-input-affix{right:auto;left:-35px}.layui-input-affix .layui-icon{color:rgba(0,0,0,.8);pointer-events:auto!important;cursor:pointer}.layui-input-affix .layui-icon-clear{color:rgba(0,0,0,.3)}.layui-input-affix .layui-icon:hover{color:rgba(0,0,0,.6)}.layui-input-wrap .layui-input-number{width:24px;padding:0}.layui-input-wrap .layui-input-number .layui-icon{position:absolute;right:0;width:100%;height:50%;line-height:normal;font-size:12px}.layui-input-wrap .layui-input-number .layui-icon:before{position:absolute;left:50%;top:50%;margin-top:-6px;margin-left:-6px}.layui-input-wrap .layui-input-number .layui-icon-up{top:0;border-bottom:1px solid #eee}.layui-input-wrap .layui-input-number .layui-icon-down{bottom:0}.layui-input-wrap .layui-input-number .layui-icon:hover{font-weight:700}.layui-input-wrap .layui-input[type=number]::-webkit-inner-spin-button,.layui-input-wrap .layui-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none!important}.layui-input-wrap .layui-input[type=number]{-moz-appearance:textfield}.layui-input-wrap .layui-input[type=number].layui-input-number-out-of-range{color:#ff5722}.layui-form-select{position:relative;color:#5f5f5f}.layui-form-select .layui-input{padding-right:30px;cursor:pointer}.layui-form-select .layui-edge{position:absolute;right:10px;top:50%;margin-top:-3px;cursor:pointer;border-width:6px;border-top-color:#c2c2c2;border-top-style:solid;transition:all .3s;-webkit-transition:all .3s}.layui-form-select dl{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #eee;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:1px 1px 4px rgb(0 0 0 / 8%);box-sizing:border-box}.layui-form-select dl dd,.layui-form-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-form-select dl dt{font-size:12px;color:#999}.layui-form-select dl dd{cursor:pointer}.layui-form-select dl dd:hover{background-color:#f8f8f8;-webkit-transition:.5s all;transition:.5s all}.layui-form-select .layui-select-group dd{padding-left:20px}.layui-form-select dl dd.layui-select-tips{padding-left:10px!important;color:#999}.layui-form-select dl dd.layui-this{background-color:#f8f8f8;color:#16b777;font-weight:700}.layui-form-select dl dd.layui-disabled{background-color:#fff}.layui-form-selected dl{display:block}.layui-form-selected .layui-edge{margin-top:-9px;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.layui-form-selected .layui-edge{margin-top:-3px\0}:root .layui-form-selected .layui-edge{margin-top:-9px\0/IE9}.layui-form-selectup dl{top:auto;bottom:42px}.layui-select-none{margin:5px 0;text-align:center;color:#999}.layui-select-disabled .layui-disabled{border-color:#eee!important}.layui-select-disabled .layui-edge{border-top-color:#d2d2d2}.layui-form-checkbox{position:relative;display:inline-block;vertical-align:middle;height:30px;line-height:30px;margin-right:10px;padding-right:30px;background-color:#fff;cursor:pointer;font-size:0;-webkit-transition:.1s linear;transition:.1s linear;box-sizing:border-box}.layui-form-checkbox>*{display:inline-block;vertical-align:middle}.layui-form-checkbox>div{padding:0 11px;font-size:14px;border-radius:2px 0 0 2px;background-color:#d2d2d2;color:#fff;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.layui-form-checkbox>div>.layui-icon{line-height:normal}.layui-form-checkbox:hover>div{background-color:#c2c2c2}.layui-form-checkbox>i{position:absolute;right:0;top:0;width:30px;height:100%;border:1px solid #d2d2d2;border-left:none;border-radius:0 2px 2px 0;color:#fff;color:rgba(255,255,255,0);font-size:20px;text-align:center;box-sizing:border-box}.layui-form-checkbox:hover>i{border-color:#c2c2c2;color:#c2c2c2}.layui-form-checked,.layui-form-checked:hover{border-color:#16b777}.layui-form-checked:hover>div,.layui-form-checked>div{background-color:#16b777}.layui-form-checked:hover>i,.layui-form-checked>i{color:#16b777}.layui-form-item .layui-form-checkbox{margin-top:4px}.layui-form-checkbox.layui-checkbox-disabled>div{background-color:#eee!important}.layui-form [lay-checkbox]{display:none}.layui-form-checkbox[lay-skin=primary]{height:auto!important;line-height:normal!important;min-width:18px;min-height:18px;border:none!important;margin-right:0;padding-left:24px;padding-right:0;background:0 0}.layui-form-checkbox[lay-skin=primary]>div{margin-top:-1px;padding-left:0;padding-right:15px;line-height:18px;background:0 0;color:#5f5f5f}.layui-form-checkbox[lay-skin=primary]>i{right:auto;left:0;width:16px;height:16px;line-height:14px;border:1px solid #d2d2d2;font-size:12px;border-radius:2px;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-checkbox[lay-skin=primary]:hover>i{border-color:#16b777;color:#fff}.layui-form-checked[lay-skin=primary]>i{border-color:#16b777!important;background-color:#16b777;color:#fff}.layui-checkbox-disabled[lay-skin=primary]>div{background:0 0!important}.layui-form-checked.layui-checkbox-disabled[lay-skin=primary]>i{background:#eee!important;border-color:#eee!important}.layui-checkbox-disabled[lay-skin=primary]:hover>i{border-color:#d2d2d2}.layui-form-item .layui-form-checkbox[lay-skin=primary]{margin-top:10px}.layui-form-checkbox[lay-skin=primary]>.layui-icon-indeterminate{border-color:#16b777}.layui-form-checkbox[lay-skin=primary]>.layui-icon-indeterminate:before{content:'';display:inline-block;vertical-align:middle;position:relative;width:50%;height:1px;margin:-1px auto 0;background-color:#16b777}.layui-form-switch{position:relative;display:inline-block;vertical-align:middle;height:24px;line-height:22px;min-width:44px;padding:0 5px;margin-top:8px;border:1px solid #d2d2d2;border-radius:20px;cursor:pointer;box-sizing:border-box;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch>i{position:absolute;left:5px;top:3px;width:16px;height:16px;border-radius:20px;background-color:#d2d2d2;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch>div{position:relative;top:0;margin-left:21px;padding:0!important;text-align:center!important;color:#999!important;font-style:normal!important;font-size:12px}.layui-form-onswitch{border-color:#16b777;background-color:#16b777}.layui-form-onswitch>i{left:100%;margin-left:-21px;background-color:#fff}.layui-form-onswitch>div{margin-left:0;margin-right:21px;color:#fff!important}.layui-checkbox-disabled{border-color:#eee!important}.layui-checkbox-disabled>div{color:#c2c2c2!important}.layui-checkbox-disabled>i{border-color:#eee!important}.layui-checkbox-disabled:hover>i{color:#fff!important}.layui-form-radio{display:inline-block;vertical-align:middle;line-height:28px;margin:6px 10px 0 0;padding-right:10px;cursor:pointer;font-size:0}.layui-form-radio>*{display:inline-block;vertical-align:middle;font-size:14px}.layui-form-radio>i{margin-right:8px;font-size:22px;color:#c2c2c2}.layui-form-radio:hover>*,.layui-form-radioed,.layui-form-radioed>i{color:#16b777}.layui-radio-disabled>i{color:#eee!important}.layui-radio-disabled>*{color:#c2c2c2!important}.layui-form [lay-radio]{display:none}.layui-form-pane .layui-form-label{width:110px;padding:8px 15px;height:38px;line-height:20px;border-width:1px;border-style:solid;border-radius:2px 0 0 2px;text-align:center;background-color:#fafafa;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;box-sizing:border-box}.layui-form-pane .layui-input-inline{margin-left:-1px}.layui-form-pane .layui-input-block{margin-left:110px;left:-1px}.layui-form-pane .layui-input{border-radius:0 2px 2px 0}.layui-form-pane .layui-form-text .layui-form-label{float:none;width:100%;border-radius:2px;box-sizing:border-box;text-align:left}.layui-form-pane .layui-form-text .layui-input-inline{display:block;margin:0;top:-1px;clear:both}.layui-form-pane .layui-form-text .layui-input-block{margin:0;left:0;top:-1px}.layui-form-pane .layui-form-text .layui-textarea{min-height:100px;border-radius:0 0 2px 2px}.layui-form-pane .layui-form-checkbox{margin:4px 0 4px 10px}.layui-form-pane .layui-form-radio,.layui-form-pane .layui-form-switch{margin-top:6px;margin-left:10px}.layui-form-pane .layui-form-item[pane]{position:relative;border-width:1px;border-style:solid}.layui-form-pane .layui-form-item[pane] .layui-form-label{position:absolute;left:0;top:0;height:100%;border-width:0;border-right-width:1px}.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left:110px}@media screen and (max-width:450px){.layui-form-item .layui-form-label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-form-item .layui-inline{display:block;margin-right:0;margin-bottom:20px;clear:both}.layui-form-item .layui-inline:after{content:'\20';clear:both;display:block;height:0}.layui-form-item .layui-input-inline{display:block;float:none;left:-3px;width:auto!important;margin:0 0 10px 112px}.layui-form-item .layui-input-inline+.layui-form-mid{margin-left:110px;top:-5px;padding:0}.layui-form-item .layui-form-checkbox{margin-right:5px;margin-bottom:5px}}.layui-laypage{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;margin:10px 0;font-size:0}.layui-laypage>a:first-child,.layui-laypage>a:first-child em{border-radius:2px 0 0 2px}.layui-laypage>a:last-child,.layui-laypage>a:last-child em{border-radius:0 2px 2px 0}.layui-laypage>:first-child{margin-left:0!important}.layui-laypage>:last-child{margin-right:0!important}.layui-laypage a,.layui-laypage button,.layui-laypage input,.layui-laypage select,.layui-laypage span{border:1px solid #eee}.layui-laypage a,.layui-laypage span{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding:0 15px;height:28px;line-height:28px;margin:0 -1px 5px 0;background-color:#fff;color:#333;font-size:12px}.layui-laypage a[data-page]{color:#333}.layui-laypage a{text-decoration:none!important;cursor:pointer}.layui-laypage a:hover{color:#16baaa}.layui-laypage em{font-style:normal}.layui-laypage .layui-laypage-spr{color:#999;font-weight:700}.layui-laypage .layui-laypage-curr{position:relative}.layui-laypage .layui-laypage-curr em{position:relative;color:#fff}.layui-laypage .layui-laypage-curr .layui-laypage-em{position:absolute;left:-1px;top:-1px;padding:1px;width:100%;height:100%;background-color:#16baaa}.layui-laypage-em{border-radius:2px}.layui-laypage-next em,.layui-laypage-prev em{font-family:Sim sun;font-size:16px}.layui-laypage .layui-laypage-count,.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh,.layui-laypage .layui-laypage-skip{margin-left:10px;margin-right:10px;padding:0;border:none}.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh{vertical-align:top}.layui-laypage .layui-laypage-refresh i{font-size:18px;cursor:pointer}.layui-laypage select{height:22px;padding:3px;border-radius:2px;cursor:pointer}.layui-laypage .layui-laypage-skip{height:30px;line-height:30px;color:#999}.layui-laypage button,.layui-laypage input{height:30px;line-height:30px;border-radius:2px;vertical-align:top;background-color:#fff;box-sizing:border-box}.layui-laypage input{display:inline-block;width:40px;margin:0 10px;padding:0 3px;text-align:center}.layui-laypage input:focus,.layui-laypage select:focus{border-color:#16baaa!important}.layui-laypage button{margin-left:10px;padding:0 10px;cursor:pointer}.layui-flow-more{margin:10px 0;text-align:center;color:#999;font-size:14px;clear:both}.layui-flow-more a{height:32px;line-height:32px}.layui-flow-more a *{display:inline-block;vertical-align:top}.layui-flow-more a cite{padding:0 20px;border-radius:3px;background-color:#eee;color:#333;font-style:normal}.layui-flow-more a cite:hover{opacity:.8}.layui-flow-more a i{font-size:30px;color:#737383}.layui-table{width:100%;margin:10px 0;background-color:#fff;color:#5f5f5f}.layui-table tr{transition:all .3s;-webkit-transition:all .3s}.layui-table th{text-align:left;font-weight:600}.layui-table-mend{background-color:#fff}.layui-table-click,.layui-table-hover,.layui-table[lay-even] tbody tr:nth-child(even){background-color:#f8f8f8}.layui-table-checked{background-color:#dbfbf0}.layui-table-checked.layui-table-click,.layui-table-checked.layui-table-hover{background-color:#abf8dd}.layui-table td,.layui-table th,.layui-table-col-set,.layui-table-fixed-r,.layui-table-grid-down,.layui-table-header,.layui-table-mend,.layui-table-page,.layui-table-tips-main,.layui-table-tool,.layui-table-total,.layui-table-view,.layui-table[lay-skin=line],.layui-table[lay-skin=row]{border-width:1px;border-style:solid;border-color:#eee}.layui-table td,.layui-table th{position:relative;padding:9px 15px;min-height:20px;line-height:20px;font-size:14px}.layui-table[lay-skin=line] td,.layui-table[lay-skin=line] th{border-width:0;border-bottom-width:1px}.layui-table[lay-skin=row] td,.layui-table[lay-skin=row] th{border-width:0;border-right-width:1px}.layui-table[lay-skin=nob] td,.layui-table[lay-skin=nob] th{border:none}.layui-table img{max-width:100px}.layui-table[lay-size=lg] td,.layui-table[lay-size=lg] th{padding-top:15px;padding-right:30px;padding-bottom:15px;padding-left:30px}.layui-table-view .layui-table[lay-size=lg] .layui-table-cell{height:50px;line-height:40px}.layui-table[lay-size=sm] td,.layui-table[lay-size=sm] th{padding-top:5px;padding-right:10px;padding-bottom:5px;padding-left:10px;font-size:12px}.layui-table-view .layui-table[lay-size=sm] .layui-table-cell{height:30px;line-height:20px;padding-top:5px;padding-left:11px;padding-right:11px}.layui-table[lay-data],.layui-table[lay-options]{display:none}.layui-table-box{position:relative;overflow:hidden}.layui-table-view{clear:both}.layui-table-view .layui-table{position:relative;width:auto;margin:0;border:0;border-collapse:separate}.layui-table-view .layui-table[lay-skin=line]{border-width:0;border-right-width:1px}.layui-table-view .layui-table[lay-skin=row]{border-width:0;border-bottom-width:1px}.layui-table-view .layui-table td,.layui-table-view .layui-table th{padding:0;border-top:none;border-left:none}.layui-table-view .layui-table th [lay-event],.layui-table-view .layui-table th.layui-unselect .layui-table-cell span{cursor:pointer}.layui-table-view .layui-table td,.layui-table-view .layui-table th span{cursor:default}.layui-table-view .layui-table td[data-edit]{cursor:text}.layui-table-view .layui-table td[data-edit]:hover:after{position:absolute;left:0;top:0;width:100%;height:100%;box-sizing:border-box;border:1px solid #16b777;pointer-events:none;content:""}.layui-table-view .layui-form-checkbox[lay-skin=primary] i{width:18px;height:18px;line-height:16px}.layui-table-view .layui-form-radio{line-height:0;padding:0}.layui-table-view .layui-form-radio>i{margin:0;font-size:20px}.layui-table-init{position:absolute;left:0;top:0;width:100%;height:100%;text-align:center;z-index:199}.layui-table-init .layui-icon{position:absolute;left:50%;top:50%;margin:-15px 0 0 -15px;font-size:30px;color:#c2c2c2}.layui-table-header{border-width:0;border-bottom-width:1px;overflow:hidden}.layui-table-header .layui-table{margin-bottom:-1px}.layui-table-column{position:relative;width:100%;min-height:41px;padding:8px 16px;border-width:0;border-bottom-width:1px}.layui-table-column .layui-btn-container{margin-bottom:-8px}.layui-table-column .layui-btn-container .layui-btn{margin-right:8px;margin-bottom:8px}.layui-table-tool .layui-inline[lay-event]{position:relative;width:26px;height:26px;padding:5px;line-height:16px;margin-right:10px;text-align:center;color:#333;border:1px solid #ccc;cursor:pointer;-webkit-transition:.5s all;transition:.5s all}.layui-table-tool .layui-inline[lay-event]:hover{border:1px solid #999}.layui-table-tool-temp{padding-right:120px}.layui-table-tool-self{position:absolute;right:17px;top:10px}.layui-table-tool .layui-table-tool-self .layui-inline[lay-event]{margin:0 0 0 10px}.layui-table-tool-panel{position:absolute;top:29px;left:-1px;z-index:399;padding:5px 0!important;min-width:150px;min-height:40px;border:1px solid #d2d2d2;text-align:left;overflow-y:auto;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-table-tool-panel li{padding:0 10px;margin:0!important;line-height:30px;list-style-type:none!important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-transition:.5s all;transition:.5s all}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary]{width:100%}.layui-table-tool-panel li:hover{background-color:#f8f8f8}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary]{padding-left:28px}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] i{position:absolute;left:0;top:0}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] span{padding:0}.layui-table-tool .layui-table-tool-self .layui-table-tool-panel{left:auto;right:-1px}.layui-table-col-set{position:absolute;right:0;top:0;width:20px;height:100%;border-width:0;border-left-width:1px;background-color:#fff}.layui-table-sort{width:10px;height:20px;margin-left:5px;cursor:pointer!important}.layui-table-sort .layui-edge{position:absolute;left:5px;border-width:5px}.layui-table-sort .layui-table-sort-asc{top:3px;border-top:none;border-bottom-style:solid;border-bottom-color:#b2b2b2}.layui-table-sort .layui-table-sort-asc:hover{border-bottom-color:#5f5f5f}.layui-table-sort .layui-table-sort-desc{bottom:5px;border-bottom:none;border-top-style:solid;border-top-color:#b2b2b2}.layui-table-sort .layui-table-sort-desc:hover{border-top-color:#5f5f5f}.layui-table-sort[lay-sort=asc] .layui-table-sort-asc{border-bottom-color:#000}.layui-table-sort[lay-sort=desc] .layui-table-sort-desc{border-top-color:#000}.layui-table-cell{height:38px;line-height:28px;padding:6px 15px;position:relative;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;box-sizing:border-box}.layui-table-cell .layui-form-checkbox[lay-skin=primary]{top:-1px;padding:0}.layui-table-cell .layui-form-checkbox[lay-skin=primary]>div{padding-left:24px}.layui-table-cell .layui-table-link{color:#01aaed}.layui-table-cell .layui-btn{vertical-align:inherit}.layui-table-cell[align=center]{-webkit-box-pack:center}.layui-table-cell[align=right]{-webkit-box-pack:end}.laytable-cell-checkbox,.laytable-cell-numbers,.laytable-cell-radio,.laytable-cell-space{text-align:center;-webkit-box-pack:center}.layui-table-body{position:relative;overflow:auto;margin-right:-1px;margin-bottom:-1px}.layui-table-body .layui-none{line-height:26px;padding:30px 15px;text-align:center;color:#999}.layui-table-fixed{position:absolute;left:0;top:0;z-index:101}.layui-table-fixed .layui-table-body{overflow:hidden}.layui-table-fixed-l{box-shadow:1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r{left:auto;right:-1px;border-width:0;border-left-width:1px;box-shadow:-1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r .layui-table-header{position:relative;overflow:visible}.layui-table-mend{position:absolute;right:-49px;top:0;height:100%;width:50px;border-width:0;border-left-width:1px}.layui-table-tool{position:relative;width:100%;min-height:50px;line-height:30px;padding:10px 15px;border-width:0;border-bottom-width:1px}.layui-table-tool .layui-btn-container{margin-bottom:-10px}.layui-table-total{margin-bottom:-1px;border-width:0;border-top-width:1px;overflow:hidden}.layui-table-page{border-width:0;border-top-width:1px;margin-bottom:-1px;white-space:nowrap;overflow:hidden}.layui-table-page>div{height:26px}.layui-table-page .layui-laypage{margin:0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span{height:26px;line-height:26px;margin-bottom:10px;border:none;background:0 0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span.layui-laypage-curr{padding:0 12px}.layui-table-page .layui-laypage span{margin-left:0;padding:0}.layui-table-page .layui-laypage .layui-laypage-prev{margin-left:-11px!important}.layui-table-page .layui-laypage .layui-laypage-curr .layui-laypage-em{left:0;top:0;padding:0}.layui-table-page .layui-laypage button,.layui-table-page .layui-laypage input{height:26px;line-height:26px}.layui-table-page .layui-laypage input{width:40px}.layui-table-page .layui-laypage button{padding:0 10px}.layui-table-page select{height:18px}.layui-table-pagebar{float:right;line-height:23px}.layui-table-pagebar .layui-btn-sm{margin-top:-1px}.layui-table-pagebar .layui-btn-xs{margin-top:2px}.layui-table-view select[lay-ignore]{display:inline-block}.layui-table-patch .layui-table-cell{padding:0;width:30px}.layui-table-edit{position:absolute;left:0;top:0;z-index:189;min-width:100%;min-height:100%;padding:5px 14px;border-radius:0;box-shadow:1px 1px 20px rgba(0,0,0,.15);background-color:#fff}.layui-table-edit:focus{border-color:#16b777!important}input.layui-input.layui-table-edit{height:100%}select.layui-table-edit{padding:0 0 0 10px;border-color:#d2d2d2}.layui-table-view .layui-form-checkbox,.layui-table-view .layui-form-radio,.layui-table-view .layui-form-switch{top:0;margin:0}.layui-table-view .layui-form-checkbox{top:-1px;height:26px;line-height:26px}.layui-table-view .layui-form-checkbox i{height:26px}.layui-table-grid .layui-table-cell{overflow:visible}.layui-table-grid-down{position:absolute;top:0;right:0;width:24px;height:100%;padding:5px 0;border-width:0;border-left-width:1px;text-align:center;background-color:#fff;color:#999;cursor:pointer}.layui-table-grid-down .layui-icon{position:absolute;top:50%;left:50%;margin:-8px 0 0 -8px;font-size:14px}.layui-table-grid-down:hover{background-color:#fbfbfb}.layui-table-expanded{height:95px}.layui-table-expanded .layui-table-cell,.layui-table-view .layui-table[lay-size=lg] .layui-table-expanded .layui-table-cell,.layui-table-view .layui-table[lay-size=sm] .layui-table-expanded .layui-table-cell{height:auto;max-height:94px;white-space:normal;text-overflow:clip}.layui-table-cell-c{position:absolute;bottom:-10px;right:50%;margin-right:-9px;width:20px;height:20px;line-height:18px;cursor:pointer;text-align:center;background-color:#fff;border:1px solid #eee;border-radius:50%;z-index:1000;transition:.3s all;font-size:14px}.layui-table-cell-c:hover{border-color:#16b777}.layui-table-expanded td:hover .layui-table-cell{overflow:auto}.layui-table-main>.layui-table>tbody>tr:last-child>td>.layui-table-cell-c{bottom:0}body .layui-table-tips .layui-layer-content{background:0 0;padding:0;box-shadow:0 1px 6px rgba(0,0,0,.12)}.layui-table-tips-main{margin:-49px 0 0 -1px;max-height:150px;padding:8px 15px;font-size:14px;overflow-y:scroll;background-color:#fff;color:#5f5f5f}.layui-table-tips-c{position:absolute;right:-3px;top:-13px;width:20px;height:20px;padding:3px;cursor:pointer;background-color:#5f5f5f;border-radius:50%;color:#fff}.layui-table-tips-c:hover{background-color:#777}.layui-table-tips-c:before{position:relative;right:-2px}.layui-table-tree-nodeIcon{max-width:20px}.layui-table-tree-nodeIcon>*{width:100%}.layui-table-tree-flexIcon,.layui-table-tree-nodeIcon{margin-right:2px}.layui-table-tree-flexIcon{cursor:pointer}.layui-upload-file{display:none!important;opacity:.01;filter:Alpha(opacity=1)}.layui-upload-list{margin:11px 0}.layui-upload-choose{max-width:200px;padding:0 10px;color:#999;font-size:14px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-upload-drag{position:relative;display:inline-block;padding:30px;border:1px dashed #e2e2e2;background-color:#fff;text-align:center;cursor:pointer;color:#999}.layui-upload-drag .layui-icon{font-size:50px;color:#16baaa}.layui-upload-drag[lay-over]{border-color:#16baaa}.layui-upload-form{display:inline-block}.layui-upload-iframe{position:absolute;width:0;height:0;border:0;visibility:hidden}.layui-upload-wrap{position:relative;display:inline-block;vertical-align:middle}.layui-upload-wrap .layui-upload-file{display:block!important;position:absolute;left:0;top:0;z-index:10;font-size:100px;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-btn-container .layui-upload-choose{padding-left:0}.layui-menu{position:relative;margin:5px 0;background-color:#fff;box-sizing:border-box}.layui-menu *{box-sizing:border-box}.layui-menu li,.layui-menu-body-title,.layui-menu-body-title a{padding:5px 15px;color:initial}.layui-menu li{position:relative;margin:0 0 1px;line-height:26px;color:rgba(0,0,0,.8);font-size:14px;white-space:nowrap;cursor:pointer;transition:all .3s}.layui-menu li:hover{background-color:#f8f8f8}.layui-menu li.layui-disabled,.layui-menu li.layui-disabled *{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important}.layui-menu-item-parent:hover>.layui-menu-body-panel{display:block;animation-name:layui-fadein;animation-duration:.3s;animation-fill-mode:both;animation-delay:.2s}.layui-menu-item-group>.layui-menu-body-title,.layui-menu-item-parent>.layui-menu-body-title{padding-right:38px}.layui-menu .layui-menu-item-divider:hover,.layui-menu .layui-menu-item-group:hover,.layui-menu .layui-menu-item-none:hover{background:0 0;cursor:default}.layui-menu .layui-menu-item-group>ul{margin:5px 0 -5px}.layui-menu .layui-menu-item-group>.layui-menu-body-title{color:rgba(0,0,0,.35);user-select:none}.layui-menu .layui-menu-item-none{color:rgba(0,0,0,.35);cursor:default}.layui-menu .layui-menu-item-none{text-align:center}.layui-menu .layui-menu-item-divider{margin:5px 0;padding:0;height:0;line-height:0;border-bottom:1px solid #eee;overflow:hidden}.layui-menu .layui-menu-item-down:hover,.layui-menu .layui-menu-item-up:hover{cursor:pointer}.layui-menu .layui-menu-item-up>.layui-menu-body-title{color:rgba(0,0,0,.8)}.layui-menu .layui-menu-item-up>ul{visibility:hidden;height:0;overflow:hidden}.layui-menu .layui-menu-item-down>.layui-menu-body-title>.layui-icon-down{transform:rotate(180deg)}.layui-menu .layui-menu-item-up>.layui-menu-body-title>.layui-icon-up{transform:rotate(-180deg)}.layui-menu .layui-menu-item-down:hover>.layui-menu-body-title>.layui-icon,.layui-menu .layui-menu-item-up>.layui-menu-body-title:hover>.layui-icon{color:#000}.layui-menu .layui-menu-item-down>ul{visibility:visible;height:auto}.layui-menu .layui-menu-item-checked,.layui-menu .layui-menu-item-checked2{background-color:#f8f8f8!important;color:#16b777}.layui-menu .layui-menu-item-checked a,.layui-menu .layui-menu-item-checked2 a{color:#16b777}.layui-menu .layui-menu-item-checked:after{position:absolute;right:-1px;top:0;bottom:0;border-right:3px solid #16b777;content:""}.layui-menu-body-title{position:relative;margin:-5px -15px;overflow:hidden;text-overflow:ellipsis}.layui-menu-body-title a{display:block;margin:-5px -15px;color:rgba(0,0,0,.8)}.layui-menu-body-title a:hover{transition:all .3s}.layui-menu-body-title>.layui-icon{position:absolute;right:15px;top:50%;margin-top:-6px;line-height:normal;font-size:14px;transition:all .2s;-webkit-transition:all .2s}.layui-menu-body-title>.layui-icon:hover{transition:all .3s}.layui-menu-body-title>.layui-icon-right{right:14px}.layui-menu-body-panel{display:none;position:absolute;top:-7px;left:100%;z-index:1000;margin-left:13px;padding:5px 0}.layui-menu-body-panel:before{content:"";position:absolute;width:20px;left:-16px;top:0;bottom:0}.layui-menu-body-panel-left{left:auto;right:100%;margin:0 13px 0}.layui-menu-body-panel-left:before{left:auto;right:-16px}.layui-menu-lg li{line-height:32px}.layui-menu-lg .layui-menu-body-title a:hover,.layui-menu-lg li:hover{background:0 0;color:#16b777}.layui-menu-lg li .layui-menu-body-panel{margin-left:14px}.layui-menu-lg li .layui-menu-body-panel-left{margin:0 15px 0}.layui-dropdown{position:absolute;left:-999999px;top:-999999px;z-index:77777777;margin:5px 0;min-width:100px}.layui-dropdown:before{content:"";position:absolute;width:100%;height:6px;left:0;top:-6px}.layui-dropdown-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px");position:fixed;_position:absolute;pointer-events:auto}.layui-nav{position:relative;padding:0 15px;background-color:#2f363c;color:#fff;border-radius:2px;font-size:0;box-sizing:border-box}.layui-nav *{font-size:14px}.layui-nav .layui-nav-item{position:relative;display:inline-block;*display:inline;*zoom:1;margin-top:0;list-style:none;vertical-align:middle;line-height:60px}.layui-nav .layui-nav-item a{display:block;padding:0 20px;color:#fff;color:rgba(255,255,255,.7);transition:all .3s;-webkit-transition:all .3s}.layui-nav .layui-this:after,.layui-nav-bar{content:"";position:absolute;left:0;top:0;width:0;height:3px;background-color:#16b777;transition:all .2s;-webkit-transition:all .2s;pointer-events:none}.layui-nav-bar{z-index:1000}.layui-nav[lay-bar=disabled] .layui-nav-bar{display:none}.layui-nav .layui-nav-item a:hover,.layui-nav .layui-this a{color:#fff;text-decoration:none}.layui-nav .layui-this:after{top:auto;bottom:0;width:100%}.layui-nav-img{width:30px;height:30px;margin-right:10px;border-radius:50%}.layui-nav .layui-nav-more{position:absolute;top:0;right:3px;left:auto!important;margin-top:0;font-size:12px;cursor:pointer;transition:all .2s;-webkit-transition:all .2s}.layui-nav .layui-nav-mored,.layui-nav-itemed>a .layui-nav-more{transform:rotate(180deg)}.layui-nav-child{display:none;position:absolute;left:0;top:65px;min-width:100%;line-height:36px;padding:5px 0;box-shadow:0 2px 4px rgba(0,0,0,.12);border:1px solid #eee;background-color:#fff;z-index:100;border-radius:2px;white-space:nowrap;box-sizing:border-box}.layui-nav .layui-nav-child a{color:#5f5f5f;color:rgba(0,0,0,.8)}.layui-nav .layui-nav-child a:hover{background-color:#f8f8f8;color:rgba(0,0,0,.8)}.layui-nav-child dd{margin:1px 0;position:relative}.layui-nav-child dd.layui-this{background-color:#f8f8f8;color:#000}.layui-nav-child dd.layui-this:after{display:none}.layui-nav-child-r{left:auto;right:0}.layui-nav-child-c{text-align:center}.layui-nav.layui-nav-tree{width:200px;padding:0}.layui-nav-tree .layui-nav-item{display:block;width:100%;line-height:40px}.layui-nav-tree .layui-nav-item a{position:relative;height:40px;line-height:40px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-nav-tree .layui-nav-item>a{padding-top:5px;padding-bottom:5px}.layui-nav-tree .layui-nav-more{right:15px}.layui-nav-tree .layui-nav-item>a .layui-nav-more{padding:5px 0}.layui-nav-tree .layui-nav-bar{width:5px;height:0}.layui-side .layui-nav-tree .layui-nav-bar{width:2px}.layui-nav-tree .layui-nav-child dd.layui-this,.layui-nav-tree .layui-nav-child dd.layui-this a,.layui-nav-tree .layui-this,.layui-nav-tree .layui-this>a,.layui-nav-tree .layui-this>a:hover{background-color:#16baaa;color:#fff}.layui-nav-tree .layui-this:after{display:none}.layui-nav-itemed>a,.layui-nav-tree .layui-nav-title a,.layui-nav-tree .layui-nav-title a:hover{color:#fff!important}.layui-nav-tree .layui-nav-bar{background-color:#16baaa}.layui-nav-tree .layui-nav-child{position:relative;z-index:0;top:0;border:none;background:0 0;background-color:rgba(0,0,0,.3);box-shadow:none}.layui-nav-tree .layui-nav-child dd{margin:0}.layui-nav-tree .layui-nav-child a{color:#fff;color:rgba(255,255,255,.7)}.layui-nav-tree .layui-nav-child a:hover{background:0 0;color:#fff}.layui-nav-itemed>.layui-nav-child,.layui-nav-itemed>.layui-nav-child>.layui-this>.layui-nav-child{display:block}.layui-nav-side{position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;z-index:999}.layui-nav-tree.layui-bg-gray a,.layui-nav.layui-bg-gray .layui-nav-item a{color:#373737;color:rgba(0,0,0,.8)}.layui-nav-tree.layui-bg-gray .layui-nav-itemed>a{color:#000!important}.layui-nav.layui-bg-gray .layui-this a{color:#16b777}.layui-nav-tree.layui-bg-gray .layui-nav-child{padding-left:11px;background:0 0}.layui-nav-tree.layui-bg-gray .layui-nav-child dd.layui-this,.layui-nav-tree.layui-bg-gray .layui-nav-child dd.layui-this a,.layui-nav-tree.layui-bg-gray .layui-this,.layui-nav-tree.layui-bg-gray .layui-this>a{background:0 0!important;color:#16b777!important;font-weight:700}.layui-nav-tree.layui-bg-gray .layui-nav-bar{background-color:#16b777}.layui-breadcrumb{visibility:hidden;font-size:0}.layui-breadcrumb>*{font-size:14px}.layui-breadcrumb a{color:#999!important}.layui-breadcrumb a:hover{color:#16b777!important}.layui-breadcrumb a cite{color:#5f5f5f;font-style:normal}.layui-breadcrumb span[lay-separator]{margin:0 10px;color:#999}.layui-tab{margin:10px 0;text-align:left!important}.layui-tab[overflow]>.layui-tab-title{overflow:hidden}.layui-tab .layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom-width:1px;border-bottom-style:solid;transition:all .2s;-webkit-transition:all .2s}.layui-tab .layui-tab-title li{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;font-size:14px;transition:all .2s;-webkit-transition:all .2s}.layui-tab .layui-tab-title li{position:relative;line-height:40px;min-width:65px;margin:0;padding:0 15px;text-align:center;cursor:pointer}.layui-tab .layui-tab-title li a{display:block;padding:0 15px;margin:0 -15px}.layui-tab-title .layui-this{color:#000}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:"";width:100%;height:41px;border-width:1px;border-style:solid;border-bottom-color:#fff;border-radius:2px 2px 0 0;box-sizing:border-box;pointer-events:none}.layui-tab-bar{position:absolute;right:0;top:0;z-index:10;width:30px;height:39px;line-height:39px;border-width:1px;border-style:solid;border-radius:2px;text-align:center;background-color:#fff;cursor:pointer}.layui-tab-bar .layui-icon{position:relative;display:inline-block;top:3px;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item{display:none}.layui-tab-more{padding-right:30px;height:auto!important;white-space:normal!important}.layui-tab-more li.layui-this:after{border-bottom-color:#eee;border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;top:3px\0;-webkit-transform:rotate(180deg);transform:rotate(180deg)}:root .layui-tab-more .layui-tab-bar .layui-icon{top:-2px\0/IE9}.layui-tab-content{padding:15px 0}.layui-tab-title li .layui-tab-close{position:relative;display:inline-block;width:18px;height:18px;line-height:20px;margin-left:8px;top:1px;text-align:center;font-size:14px;color:#c2c2c2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li .layui-tab-close:hover{border-radius:2px;background-color:#ff5722;color:#fff}.layui-tab-brief>.layui-tab-title .layui-this{color:#16baaa}.layui-tab-brief>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-title .layui-this:after{border:none;border-radius:0;border-bottom:2px solid #16b777}.layui-tab-brief[overflow]>.layui-tab-title .layui-this:after{top:-1px}.layui-tab-card{border-width:1px;border-style:solid;border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1)}.layui-tab-card>.layui-tab-title{background-color:#fafafa}.layui-tab-card>.layui-tab-title li{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-title .layui-this{background-color:#fff}.layui-tab-card>.layui-tab-title .layui-this:after{border-top:none;border-width:1px;border-bottom-color:#fff}.layui-tab-card>.layui-tab-title .layui-tab-bar{height:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:#16b777}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-timeline{padding-left:5px}.layui-timeline-item{position:relative;padding-bottom:20px}.layui-timeline-axis{position:absolute;left:-5px;top:0;z-index:10;width:20px;height:20px;line-height:20px;background-color:#fff;color:#16b777;border-radius:50%;text-align:center;cursor:pointer}.layui-timeline-axis:hover{color:#ff5722}.layui-timeline-item:before{content:"";position:absolute;left:5px;top:0;z-index:0;width:1px;height:100%}.layui-timeline-item:first-child:before{display:block}.layui-timeline-item:last-child:before{display:none}.layui-timeline-content{padding-left:25px}.layui-timeline-title{position:relative;margin-bottom:10px;line-height:22px}.layui-badge,.layui-badge-dot,.layui-badge-rim{position:relative;display:inline-block;padding:0 6px;font-size:12px;text-align:center;background-color:#ff5722;color:#fff;border-radius:2px}.layui-badge{height:18px;line-height:18px}.layui-badge-dot{width:8px;height:8px;padding:0;border-radius:50%}.layui-badge-rim{height:18px;line-height:18px;border-width:1px;border-style:solid;background-color:#fff;color:#5f5f5f}.layui-btn .layui-badge,.layui-btn .layui-badge-dot{margin-left:5px}.layui-nav .layui-badge,.layui-nav .layui-badge-dot{position:absolute;top:50%;margin:-5px 6px 0}.layui-nav .layui-badge{margin-top:-10px}.layui-tab-title .layui-badge,.layui-tab-title .layui-badge-dot{left:5px;top:-2px}.layui-carousel{position:relative;left:0;top:0;background-color:#f8f8f8}.layui-carousel>[carousel-item]{position:relative;width:100%;height:100%;overflow:hidden}.layui-carousel>[carousel-item]:before{position:absolute;content:'\e63d';left:50%;top:50%;width:100px;line-height:20px;margin:-10px 0 0 -50px;text-align:center;color:#c2c2c2;font-family:layui-icon!important;font-size:30px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-carousel>[carousel-item]>*{display:none;position:absolute;left:0;top:0;width:100%;height:100%;background-color:#f8f8f8;transition-duration:.3s;-webkit-transition-duration:.3s}.layui-carousel-updown>*{-webkit-transition:.3s ease-in-out up;transition:.3s ease-in-out up}.layui-carousel-arrow{display:none\0;opacity:0;position:absolute;left:10px;top:50%;margin-top:-18px;width:36px;height:36px;line-height:36px;text-align:center;font-size:20px;border:none 0;border-radius:50%;background-color:rgba(0,0,0,.2);color:#fff;-webkit-transition-duration:.3s;transition-duration:.3s;cursor:pointer}.layui-carousel-arrow[lay-type=add]{left:auto!important;right:10px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow{opacity:1;left:20px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel[lay-arrow=none] .layui-carousel-arrow{display:none}.layui-carousel-arrow:hover,.layui-carousel-ind ul:hover{background-color:rgba(0,0,0,.35)}.layui-carousel:hover .layui-carousel-arrow{display:block\0;opacity:1;left:20px}.layui-carousel:hover .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel-ind{position:relative;top:-35px;width:100%;line-height:0!important;text-align:center;font-size:0}.layui-carousel[lay-indicator=outside]{margin-bottom:30px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind{top:10px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind ul{background-color:rgba(0,0,0,.5)}.layui-carousel[lay-indicator=none] .layui-carousel-ind{display:none}.layui-carousel-ind ul{display:inline-block;padding:5px;background-color:rgba(0,0,0,.2);border-radius:10px;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind ul li{display:inline-block;width:10px;height:10px;margin:0 3px;font-size:14px;background-color:#eee;background-color:rgba(255,255,255,.5);border-radius:50%;cursor:pointer;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind ul li:hover{background-color:rgba(255,255,255,.7)}.layui-carousel-ind ul li.layui-this{background-color:#fff}.layui-carousel>[carousel-item]>.layui-carousel-next,.layui-carousel>[carousel-item]>.layui-carousel-prev,.layui-carousel>[carousel-item]>.layui-this{display:block}.layui-carousel>[carousel-item]>.layui-this{left:0}.layui-carousel>[carousel-item]>.layui-carousel-prev{left:-100%}.layui-carousel>[carousel-item]>.layui-carousel-next{left:100%}.layui-carousel>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel>[carousel-item]>.layui-carousel-prev.layui-carousel-right{left:0}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-left{left:-100%}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-right{left:100%}.layui-carousel[lay-anim=updown] .layui-carousel-arrow{left:50%!important;top:20px;margin:0 0 0 -18px}.layui-carousel[lay-anim=updown] .layui-carousel-arrow[lay-type=add]{top:auto!important;bottom:20px}.layui-carousel[lay-anim=updown] .layui-carousel-ind{position:absolute;top:50%;right:20px;width:auto;height:auto}.layui-carousel[lay-anim=updown] .layui-carousel-ind ul{padding:3px 5px}.layui-carousel[lay-anim=updown] .layui-carousel-ind li{display:block;margin:6px 0}.layui-carousel[lay-anim=updown]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next{top:100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-left{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-right{top:100%}.layui-carousel[lay-anim=fade]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev{opacity:0}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{opacity:1}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-right{opacity:0}.layui-fixbar{position:fixed;right:16px;bottom:16px;z-index:999999}.layui-fixbar li{width:50px;height:50px;line-height:50px;margin-bottom:1px;text-align:center;cursor:pointer;font-size:30px;background-color:#9f9f9f;color:#fff;border-radius:2px;opacity:.95}.layui-fixbar li:hover{opacity:.85}.layui-fixbar li:active{opacity:1}.layui-fixbar .layui-fixbar-top{display:none;font-size:40px}body .layui-util-face{border:none;background:0 0}body .layui-util-face .layui-layer-content{padding:0;background-color:#fff;color:#5f5f5f;box-shadow:none}.layui-util-face .layui-layer-TipsG{display:none}.layui-util-face ul{position:relative;width:372px;padding:10px;border:1px solid #d9d9d9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-util-face ul li{cursor:pointer;float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px;text-align:center}.layui-util-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layui-code{display:block;position:relative;padding:15px;line-height:20px;border:1px solid #eee;border-left-width:6px;background-color:#fff;color:#333;font-family:"Courier New",Consolas,"Lucida Console";font-size:12px}.layui-transfer-box,.layui-transfer-header,.layui-transfer-search{border-width:0;border-style:solid;border-color:#eee}.layui-transfer-box{position:relative;display:inline-block;vertical-align:middle;border-width:1px;width:200px;height:360px;border-radius:2px;background-color:#fff}.layui-transfer-box .layui-form-checkbox{width:100%;margin:0!important}.layui-transfer-header{height:38px;line-height:38px;padding:0 11px;border-bottom-width:1px}.layui-transfer-search{position:relative;padding:11px;border-bottom-width:1px}.layui-transfer-search .layui-input{height:32px;padding-left:30px;font-size:12px}.layui-transfer-search .layui-icon-search{position:absolute;left:20px;top:50%;line-height:normal;margin-top:-8px;color:#5f5f5f}.layui-transfer-active{margin:0 15px;display:inline-block;vertical-align:middle}.layui-transfer-active .layui-btn{display:block;margin:0;padding:0 15px;background-color:#16b777;border-color:#16b777;color:#fff}.layui-transfer-active .layui-btn-disabled{background-color:#fbfbfb;border-color:#eee;color:#d2d2d2}.layui-transfer-active .layui-btn:first-child{margin-bottom:15px}.layui-transfer-active .layui-btn .layui-icon{margin:0;font-size:14px!important}.layui-transfer-data{padding:5px 0;overflow:auto}.layui-transfer-data li{height:32px;line-height:32px;margin-top:0!important;padding:0 11px;list-style-type:none!important}.layui-transfer-data li:hover{background-color:#f8f8f8;transition:.5s all}.layui-transfer-data .layui-none{padding:15px 11px;text-align:center;color:#999}.layui-rate,.layui-rate *{display:inline-block;vertical-align:middle}.layui-rate{padding:11px 6px 11px 0;font-size:0}.layui-rate li{margin-top:0!important}.layui-rate li i.layui-icon{font-size:20px;color:#ffb800}.layui-rate li i.layui-icon{margin-right:5px;transition:all .3s;-webkit-transition:all .3s}.layui-rate li i:hover,.layui-rate-hover{cursor:pointer;transform:scale(1.12);-webkit-transform:scale(1.12)}.layui-rate[readonly] li i:hover{cursor:default;transform:scale(1)}.layui-colorpicker{width:38px;height:38px;border:1px solid #eee;padding:5px;border-radius:2px;line-height:24px;display:inline-block;cursor:pointer;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-colorpicker:hover{border-color:#d2d2d2}.layui-colorpicker.layui-colorpicker-lg{width:44px;height:44px;line-height:30px}.layui-colorpicker.layui-colorpicker-sm{width:30px;height:30px;line-height:20px;padding:3px}.layui-colorpicker.layui-colorpicker-xs{width:22px;height:22px;line-height:16px;padding:1px}.layui-colorpicker-trigger-bgcolor{display:block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);border-radius:2px}.layui-colorpicker-trigger-span{display:block;height:100%;box-sizing:border-box;border:1px solid rgba(0,0,0,.15);border-radius:2px;text-align:center}.layui-colorpicker-trigger-i{display:inline-block;color:#fff;font-size:12px}.layui-colorpicker-trigger-i.layui-icon-close{color:#999}.layui-colorpicker-main{position:absolute;left:-999999px;top:-999999px;z-index:77777777;width:280px;margin:5px 0;padding:7px;background:#fff;border:1px solid #d2d2d2;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-colorpicker-main-wrapper{height:180px;position:relative}.layui-colorpicker-basis{width:260px;height:100%;position:relative}.layui-colorpicker-basis-white{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(90deg,#fff,hsla(0,0%,100%,0))}.layui-colorpicker-basis-black{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(0deg,#000,transparent)}.layui-colorpicker-basis-cursor{width:10px;height:10px;border:1px solid #fff;border-radius:50%;position:absolute;top:-3px;right:-3px;cursor:pointer}.layui-colorpicker-side{position:absolute;top:0;right:0;width:12px;height:100%;background:linear-gradient(red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.layui-colorpicker-side-slider{width:100%;height:5px;box-shadow:0 0 1px #888;box-sizing:border-box;background:#fff;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;left:0}.layui-colorpicker-main-alpha{display:none;height:12px;margin-top:7px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-alpha-bgcolor{height:100%;position:relative}.layui-colorpicker-alpha-slider{width:5px;height:100%;box-shadow:0 0 1px #888;box-sizing:border-box;background:#fff;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;top:0}.layui-colorpicker-main-pre{padding-top:7px;font-size:0}.layui-colorpicker-pre{width:20px;height:20px;border-radius:2px;display:inline-block;margin-left:6px;margin-bottom:7px;cursor:pointer}.layui-colorpicker-pre:nth-child(11n+1){margin-left:0}.layui-colorpicker-pre-isalpha{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-pre.layui-this{box-shadow:0 0 3px 2px rgba(0,0,0,.15)}.layui-colorpicker-pre>div{height:100%;border-radius:2px}.layui-colorpicker-main-input{text-align:right;padding-top:7px}.layui-colorpicker-main-input .layui-btn-container .layui-btn{margin:0 0 0 10px}.layui-colorpicker-main-input div.layui-inline{float:left;margin-right:10px;font-size:14px}.layui-colorpicker-main-input input.layui-input{width:150px;height:30px;color:#5f5f5f}.layui-slider{height:4px;background:#eee;border-radius:3px;position:relative;cursor:pointer}.layui-slider-bar{border-radius:3px;position:absolute;height:100%}.layui-slider-step{position:absolute;top:0;width:4px;height:4px;border-radius:50%;background:#fff;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.layui-slider-wrap{width:36px;height:36px;position:absolute;top:-16px;-webkit-transform:translateX(-50%);transform:translateX(-50%);z-index:10;text-align:center}.layui-slider-wrap-btn{width:12px;height:12px;border-radius:50%;background:#fff;display:inline-block;vertical-align:middle;cursor:pointer;transition:.3s}.layui-slider-wrap:after{content:"";height:100%;display:inline-block;vertical-align:middle}.layui-slider-wrap-btn.layui-slider-hover,.layui-slider-wrap-btn:hover{transform:scale(1.2)}.layui-slider-wrap-btn.layui-disabled:hover{transform:scale(1)!important}.layui-slider-tips{position:absolute;top:-42px;z-index:77777777;white-space:nowrap;display:none;-webkit-transform:translateX(-50%);transform:translateX(-50%);color:#fff;background:#000;border-radius:3px;height:25px;line-height:25px;padding:0 10px}.layui-slider-tips:after{content:"";position:absolute;bottom:-12px;left:50%;margin-left:-6px;width:0;height:0;border-width:6px;border-style:solid;border-color:#000 transparent transparent transparent}.layui-slider-input{width:70px;height:32px;border:1px solid #eee;border-radius:3px;font-size:16px;line-height:32px;position:absolute;right:0;top:-14px;box-sizing:border-box}.layui-slider-input-btn{position:absolute;top:0;right:0;width:20px;height:100%;border-left:1px solid #eee}.layui-slider-input-btn i{cursor:pointer;position:absolute;right:0;bottom:0;width:20px;height:50%;font-size:12px;line-height:16px;text-align:center;color:#999}.layui-slider-input-btn i:first-child{top:0;border-bottom:1px solid #eee}.layui-slider-input-txt{height:100%;font-size:14px}.layui-slider-input-txt input{height:100%;border:none;padding-right:21px}.layui-slider-input-btn i:hover{color:#16baaa}.layui-slider-vertical{width:4px;margin-left:33px}.layui-slider-vertical .layui-slider-bar{width:4px}.layui-slider-vertical .layui-slider-step{top:auto;left:0;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-wrap{top:auto;left:-16px;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-tips{top:auto;left:2px}@media \0screen{.layui-slider-wrap-btn{margin-left:-20px}.layui-slider-vertical .layui-slider-wrap-btn{margin-left:0;margin-bottom:-20px}.layui-slider-vertical .layui-slider-tips{margin-left:-8px}.layui-slider>span{margin-left:8px}}.layui-tree{line-height:22px}.layui-tree .layui-form-checkbox{margin:0!important}.layui-tree-set{width:100%;position:relative}.layui-tree-pack{display:none;padding-left:20px;position:relative}.layui-tree-line .layui-tree-pack{padding-left:27px}.layui-tree-line .layui-tree-set .layui-tree-set:after{content:"";position:absolute;top:14px;left:-9px;width:17px;height:0;border-top:1px dotted #c0c4cc}.layui-tree-entry{position:relative;padding:3px 0;height:26px;white-space:nowrap}.layui-tree-entry:hover{background-color:#eee}.layui-tree-line .layui-tree-entry:hover{background-color:rgba(0,0,0,0)}.layui-tree-line .layui-tree-entry:hover .layui-tree-txt{color:#999;text-decoration:underline;transition:.3s}.layui-tree-main{display:inline-block;vertical-align:middle;cursor:pointer;padding-right:10px}.layui-tree-line .layui-tree-set:before{content:"";position:absolute;top:0;left:-9px;width:0;height:100%;border-left:1px dotted #c0c4cc}.layui-tree-line .layui-tree-set.layui-tree-setLineShort:before{height:13px}.layui-tree-line .layui-tree-set.layui-tree-setHide:before{height:0}.layui-tree-iconClick{display:inline-block;vertical-align:middle;position:relative;height:20px;line-height:20px;margin:0 10px;color:#c0c4cc}.layui-tree-icon{height:14px;line-height:12px;width:14px;text-align:center;border:1px solid #c0c4cc}.layui-tree-iconClick .layui-icon{font-size:18px}.layui-tree-icon .layui-icon{font-size:12px;color:#5f5f5f}.layui-tree-iconArrow{padding:0 5px}.layui-tree-iconArrow:after{content:"";position:absolute;left:4px;top:3px;z-index:100;width:0;height:0;border-width:5px;border-style:solid;border-color:transparent transparent transparent #c0c4cc;transition:.5s}.layui-tree-spread>.layui-tree-entry .layui-tree-iconClick>.layui-tree-iconArrow:after{transform:rotate(90deg) translate(3px,4px)}.layui-tree-txt{display:inline-block;vertical-align:middle;color:#555}.layui-tree-search{margin-bottom:15px;color:#5f5f5f}.layui-tree-btnGroup{visibility:hidden;display:inline-block;vertical-align:middle;position:relative}.layui-tree-btnGroup .layui-icon{display:inline-block;vertical-align:middle;padding:0 2px;cursor:pointer}.layui-tree-btnGroup .layui-icon:hover{color:#999;transition:.3s}.layui-tree-entry:hover .layui-tree-btnGroup{visibility:visible}.layui-tree-editInput{position:relative;display:inline-block;vertical-align:middle;height:20px;line-height:20px;padding:0;border:none;background-color:rgba(0,0,0,.05)}.layui-tree-emptyText{text-align:center;color:#999}.layui-anim{-webkit-animation-duration:.3s;-webkit-animation-fill-mode:both;animation-duration:.3s;animation-fill-mode:both}.layui-anim.layui-icon{display:inline-block}.layui-anim-loop{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.layui-trans,.layui-trans a{transition:all .2s;-webkit-transition:all .2s}@-webkit-keyframes layui-rotate{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes layui-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}.layui-anim-rotate{-webkit-animation-name:layui-rotate;animation-name:layui-rotate;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes layui-up{from{-webkit-transform:translate3d(0,100%,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-up{from{transform:translate3d(0,100%,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-up{-webkit-animation-name:layui-up;animation-name:layui-up}@-webkit-keyframes layui-upbit{from{-webkit-transform:translate3d(0,15px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-upbit{from{transform:translate3d(0,15px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-upbit{-webkit-animation-name:layui-upbit;animation-name:layui-upbit}@keyframes layui-down{0%{opacity:.3;transform:translate3d(0,-100%,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-anim-down{animation-name:layui-down}@keyframes layui-downbit{0%{opacity:.3;transform:translate3d(0,-5px,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-anim-downbit{animation-name:layui-downbit}@-webkit-keyframes layui-scale{0%{opacity:.3;-webkit-transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale{0%{opacity:.3;-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scale{-webkit-animation-name:layui-scale;animation-name:layui-scale}@-webkit-keyframes layui-scale-spring{0%{opacity:.5;-webkit-transform:scale(.5)}80%{opacity:.8;-webkit-transform:scale(1.1)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale-spring{0%{opacity:.5;transform:scale(.5)}80%{opacity:.8;transform:scale(1.1)}100%{opacity:1;transform:scale(1)}}.layui-anim-scaleSpring{-webkit-animation-name:layui-scale-spring;animation-name:layui-scale-spring}@keyframes layui-scalesmall{0%{opacity:.3;transform:scale(1.5)}100%{opacity:1;transform:scale(1)}}.layui-anim-scalesmall{animation-name:layui-scalesmall}@keyframes layui-scalesmall-spring{0%{opacity:.3;transform:scale(1.5)}80%{opacity:.8;transform:scale(.9)}100%{opacity:1;transform:scale(1)}}.layui-anim-scalesmall-spring{animation-name:layui-scalesmall-spring}@-webkit-keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}@keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}.layui-anim-fadein{-webkit-animation-name:layui-fadein;animation-name:layui-fadein}@-webkit-keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}@keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}.layui-anim-fadeout{-webkit-animation-name:layui-fadeout;animation-name:layui-fadeout}html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-wrap{font-size:13px;font-family:"Courier New",Consolas,"Lucida Console"}.layui-code-view{display:block;position:relative;padding:0!important;border:1px solid #eee;border-left-width:6px;background-color:#fff;color:#333}.layui-code-view pre{margin:0!important}.layui-code-header{position:relative;z-index:3;padding:0 11px;height:40px;line-height:40px;border-bottom:1px solid #eee;background-color:#fafafa;font-size:12px}.layui-code-header>.layui-code-header-about{position:absolute;right:11px;top:0;color:#b7b7b7}.layui-code-header-about>a{padding-left:10px}.layui-code-wrap{position:relative;display:block;z-index:1;margin:0!important;padding:11px 0!important;overflow-x:hidden;overflow-y:auto}.layui-code-line{position:relative;line-height:19px;margin:0!important}.layui-code-line-number{position:absolute;left:0;top:0;padding:0 8px;min-width:45px;height:100%;text-align:right;user-select:none;white-space:nowrap;overflow:hidden}.layui-code-line-content{padding:0 11px;word-wrap:break-word;white-space:pre-wrap}.layui-code-ln-mode>.layui-code-wrap>.layui-code-line{padding-left:45px}.layui-code-ln-side{position:absolute;left:0;top:0;bottom:0;z-index:0;width:45px;border-right:1px solid #eee;border-color:rgb(126 122 122 / 15%);background-color:#fafafa;pointer-events:none}.layui-code-nowrap>.layui-code-wrap{overflow:auto}.layui-code-nowrap>.layui-code-wrap>.layui-code-line>.layui-code-line-content{white-space:pre;word-wrap:normal}.layui-code-nowrap>.layui-code-ln-side{border-right-width:0!important;background:0 0!important}.layui-code-fixbar{position:absolute;top:8px;right:11px;padding-right:45px;z-index:5}.layui-code-fixbar>span{position:absolute;right:0;top:0;padding:0 8px;color:#777;transition:all .3s}.layui-code-fixbar>span:hover{color:#16b777}.layui-code-copy{display:none;cursor:pointer}.layui-code-preview>.layui-code-view>.layui-code-fixbar .layui-code-copy{display:none!important}.layui-code-view:hover>.layui-code-fixbar .layui-code-copy{display:block}.layui-code-view:hover>.layui-code-fixbar .layui-code-lang-marker{display:none}.layui-code-theme-dark,.layui-code-theme-dark>.layui-code-header{border-color:rgb(126 122 122 / 15%);background-color:#1f1f1f}.layui-code-theme-dark{border-width:1px;color:#ccc}.layui-code-theme-dark>.layui-code-ln-side{border-right-color:#2a2a2a;background:0 0;color:#6e7681}.layui-code textarea{display:none}.layui-code-preview>.layui-code,.layui-code-preview>.layui-code-view{margin:0}.layui-code-preview>.layui-tab{position:relative;z-index:1;margin-bottom:0}.layui-code-preview>.layui-tab>.layui-tab-title{border-width:0}.layui-code-preview .layui-code-item{display:none}.layui-code-item-preview{position:relative;padding:16px}.layui-code-item-preview>iframe{position:absolute;top:0;left:0;width:100%;height:100%;border:none}.layui-code-tools{position:absolute;right:11px;top:8px;line-height:normal}.layui-code-tools>i{display:inline-block;margin-left:6px;padding:3px;cursor:pointer}.layui-code-tools>i.layui-icon-file-b{color:#999}.layui-code-tools>i:hover{color:#16b777}.layui-code-full{position:fixed;left:0;top:0;z-index:1111111;width:100%;height:100%;background-color:#fff}.layui-code-full .layui-code-item{width:100%!important;border-width:0!important;border-top-width:1px!important}.layui-code-full .layui-code-item,.layui-code-full .layui-code-view,.layui-code-full .layui-code-wrap{height:calc(100vh - 51px)!important;box-sizing:border-box}.layui-code-full .layui-code-item-preview{overflow:auto}.layui-code-view.layui-code-hl{line-height:20px!important;border-left-width:1px}.layui-code-view.layui-code-hl>.layui-code-ln-side{background-color:transparent}.layui-code-theme-dark.layui-code-hl,.layui-code-theme-dark.layui-code-hl>.layui-code-ln-side{border-color:rgb(126 122 122 / 15%)}html #layuicss-laydate{display:none;position:absolute;width:1989px}.layui-laydate *{margin:0;padding:0}.layui-laydate,.layui-laydate *{box-sizing:border-box}.layui-laydate{position:absolute;z-index:99999999;margin:5px 0;border-radius:2px;font-size:14px;line-height:normal;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-laydate-main{width:272px}.layui-laydate-content td,.layui-laydate-header *,.layui-laydate-list li{transition-duration:.3s;-webkit-transition-duration:.3s}.layui-laydate-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px");position:fixed;_position:absolute;pointer-events:auto}@keyframes laydate-downbit{0%{opacity:.3;transform:translate3d(0,-5px,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-laydate{animation-name:laydate-downbit}.layui-laydate-static{position:relative;z-index:0;display:inline-block;margin:0;-webkit-animation:none;animation:none}.laydate-ym-show .laydate-next-m,.laydate-ym-show .laydate-prev-m{display:none!important}.laydate-ym-show .laydate-next-y,.laydate-ym-show .laydate-prev-y{display:inline-block!important}.laydate-ym-show .laydate-set-ym span[lay-type=month]{display:none!important}.laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-time-show .layui-laydate-header .layui-icon{display:none!important}.layui-laydate-header{position:relative;line-height:30px;padding:10px 70px 5px}.layui-laydate-header *{display:inline-block;vertical-align:bottom}.layui-laydate-header i{position:absolute;top:10px;padding:0 5px;color:#999;font-size:18px;cursor:pointer}.layui-laydate-header i.laydate-prev-y{left:15px}.layui-laydate-header i.laydate-prev-m{left:45px}.layui-laydate-header i.laydate-next-y{right:15px}.layui-laydate-header i.laydate-next-m{right:45px}.laydate-set-ym{width:100%;text-align:center;box-sizing:border-box;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate-set-ym span{padding:0 10px;cursor:pointer}.laydate-time-text{cursor:default!important}.layui-laydate-content{position:relative;padding:10px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content table{border-collapse:collapse;border-spacing:0}.layui-laydate-content td,.layui-laydate-content th{width:36px;height:30px;padding:0;text-align:center}.layui-laydate-content th{font-weight:400}.layui-laydate-content td{position:relative;cursor:pointer}.laydate-day-mark{position:absolute;left:0;top:0;width:100%;line-height:30px;font-size:12px;overflow:hidden}.laydate-day-mark::after{position:absolute;content:'';right:2px;top:2px;width:5px;height:5px;border-radius:50%}.laydate-day-holidays:before{position:absolute;left:0;top:0;font-size:12px;transform:scale(.7)}.laydate-day-holidays:before{content:'\4F11';color:#ff5722}.laydate-day-holidays[type=work]:before{content:'\73ED';color:inherit}.layui-laydate .layui-this .laydate-day-holidays:before{color:#fff}.layui-laydate-footer{position:relative;height:46px;line-height:26px;padding:10px}.layui-laydate-footer span{display:inline-block;vertical-align:top;height:26px;line-height:24px;padding:0 10px;border:1px solid #c9c9c9;border-radius:2px;background-color:#fff;font-size:12px;cursor:pointer;white-space:nowrap;transition:all .3s}.layui-laydate-footer span:hover{color:#16b777}.layui-laydate-footer span.layui-laydate-preview{cursor:default;border-color:transparent!important}.layui-laydate-footer span.layui-laydate-preview:hover{color:#777}.layui-laydate-footer span:first-child.layui-laydate-preview{padding-left:0}.laydate-footer-btns{position:absolute;right:10px;top:10px}.laydate-footer-btns span{margin:0 0 0 -1px;border-radius:0}.laydate-footer-btns span:first-child{border-radius:2px 0 0 2px}.laydate-footer-btns span:last-child{border-radius:0 2px 2px 0}.layui-laydate-shortcut{width:80px;padding:6px 0;display:inline-block;vertical-align:top;overflow:auto;max-height:276px;text-align:center}.layui-laydate-shortcut+.layui-laydate-main{display:inline-block;border-left:1px solid #e2e2e2}.layui-laydate-shortcut>li{padding:5px 8px;cursor:pointer;line-height:18px}.layui-laydate .layui-laydate-list{position:absolute;left:0;top:0;width:100%;height:100%;padding:10px;box-sizing:border-box;background-color:#fff}.layui-laydate .layui-laydate-list>li{position:relative;display:inline-block;width:33.3%;height:36px;line-height:36px;margin:3px 0;vertical-align:middle;text-align:center;cursor:pointer;list-style:none}.layui-laydate .laydate-month-list>li{width:25%;margin:17px 0}.layui-laydate .laydate-time-list>li{height:100%;margin:0;line-height:normal;cursor:default}.layui-laydate .laydate-time-list p{position:relative;top:-4px;margin:0;line-height:29px}.layui-laydate .laydate-time-list ol{height:181px;overflow:hidden}.layui-laydate .laydate-time-list>li:hover ol{overflow-y:auto}.layui-laydate .laydate-time-list ol li{width:130%;padding-left:33px;height:30px;line-height:30px;text-align:left;cursor:pointer}.layui-laydate-hint{position:absolute;top:115px;left:50%;width:250px;margin-left:-125px;line-height:20px;padding:15px;text-align:center;font-size:12px;color:#ff5722}.layui-laydate-range{width:546px}.layui-laydate-range .layui-laydate-main{display:inline-block;vertical-align:middle;max-width:50%}.layui-laydate-range .laydate-main-list-1 .layui-laydate-content,.layui-laydate-range .laydate-main-list-1 .layui-laydate-header{border-left:1px solid #e2e2e2}.layui-laydate-range.layui-laydate-linkage .laydate-main-list-0 .laydate-next-m,.layui-laydate-range.layui-laydate-linkage .laydate-main-list-0 .laydate-next-y,.layui-laydate-range.layui-laydate-linkage .laydate-main-list-1 .laydate-prev-m,.layui-laydate-range.layui-laydate-linkage .laydate-main-list-1 .laydate-prev-y{display:none}.layui-laydate,.layui-laydate-hint{border:1px solid #d2d2d2;box-shadow:0 2px 4px rgba(0,0,0,.12);background-color:#fff;color:#777}.layui-laydate-header{border-bottom:1px solid #e2e2e2}.layui-laydate-header i:hover,.layui-laydate-header span:hover{color:#16b777}.layui-laydate-content{border-top:none 0;border-bottom:none 0}.layui-laydate-content th{color:#333}.layui-laydate-content td{color:#777}.layui-laydate-content td.laydate-day-now{color:#16b777}.layui-laydate-content td.laydate-day-now:after{content:'';position:absolute;width:100%;height:30px;left:0;top:0;border:1px solid #16b777;box-sizing:border-box}.layui-laydate-linkage .layui-laydate-content td.laydate-selected>div{background-color:#00f7de}.layui-laydate-linkage .laydate-selected:hover>div{background-color:#00f7de!important}.layui-laydate-content td.laydate-selected:after,.layui-laydate-content td:hover:after{content:none}.layui-laydate-content td>div:hover,.layui-laydate-list li:hover,.layui-laydate-shortcut>li:hover{background-color:#eee;color:#333}.laydate-time-list li ol{margin:0;padding:0;border:1px solid #e2e2e2;border-left-width:0}.laydate-time-list li:first-child ol{border-left-width:1px}.laydate-time-list>li:hover{background:0 0}.layui-laydate-content .laydate-day-next,.layui-laydate-content .laydate-day-prev{color:#d2d2d2}.layui-laydate-linkage .laydate-selected.laydate-day-next>div,.layui-laydate-linkage .laydate-selected.laydate-day-prev>div{background-color:#f8f8f8!important}.layui-laydate-footer{border-top:1px solid #e2e2e2}.layui-laydate-hint{color:#ff5722}.laydate-day-mark::after{background-color:#16b777}.layui-laydate-content td.layui-this .laydate-day-mark::after{display:none}.layui-laydate-footer span[lay-type=date]{color:#16b777}.layui-laydate .layui-this,.layui-laydate .layui-this>div{background-color:#16baaa!important;color:#fff!important}.layui-laydate .laydate-disabled,.layui-laydate .laydate-disabled:hover{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content td>div{padding:7px 0;height:100%}.laydate-theme-molv{border:none}.laydate-theme-molv.layui-laydate-range{width:548px}.laydate-theme-molv .layui-laydate-main{width:274px}.laydate-theme-molv .layui-laydate-header{border:none;background-color:#16baaa}.laydate-theme-molv .layui-laydate-header i,.laydate-theme-molv .layui-laydate-header span{color:#f6f6f6}.laydate-theme-molv .layui-laydate-header i:hover,.laydate-theme-molv .layui-laydate-header span:hover{color:#fff}.laydate-theme-molv .layui-laydate-content{border:1px solid #e2e2e2;border-top:none;border-bottom:none}.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content{border-left:none}.laydate-theme-molv .layui-laydate-footer{border:1px solid #e2e2e2}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li,.laydate-theme-grid .layui-laydate-content td,.laydate-theme-grid .layui-laydate-content thead{border:1px solid #e2e2e2}.layui-laydate-linkage.laydate-theme-grid .laydate-selected,.layui-laydate-linkage.laydate-theme-grid .laydate-selected:hover{background-color:#f2f2f2!important;color:#16baaa!important}.layui-laydate-linkage.laydate-theme-grid .laydate-selected.laydate-day-next,.layui-laydate-linkage.laydate-theme-grid .laydate-selected.laydate-day-prev{color:#d2d2d2!important}.laydate-theme-grid .laydate-month-list,.laydate-theme-grid .laydate-year-list{margin:1px 0 0 1px}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li{margin:0 -1px -1px 0}.laydate-theme-grid .laydate-year-list>li{height:43px;line-height:43px}.laydate-theme-grid .laydate-month-list>li{height:71px;line-height:71px}.laydate-theme-grid .layui-laydate-content td>div{height:29px;margin-top:-1px}.laydate-theme-circle .layui-laydate-content td.layui-this>div,.laydate-theme-circle .layui-laydate-content td>div{width:28px;height:28px;line-height:28px;border-radius:14px;margin:0 4px;padding:0}.layui-laydate.laydate-theme-circle .layui-laydate-content table td.layui-this{background-color:transparent!important}.laydate-theme-grid.laydate-theme-circle .layui-laydate-content td>div{margin:0 3.5px}.laydate-theme-fullpanel .layui-laydate-main{width:526px}.laydate-theme-fullpanel .layui-laydate-list{width:252px;left:272px}.laydate-theme-fullpanel .laydate-set-ym span{display:none}.laydate-theme-fullpanel .laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-theme-fullpanel .laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-theme-fullpanel .laydate-time-show .layui-laydate-header .layui-icon{display:inline-block!important}.laydate-theme-fullpanel .laydate-btns-time{display:none}html #layuicss-layer{display:none;position:absolute;width:1989px}.layui-layer,.layui-layer-shade{position:fixed;_position:absolute;pointer-events:auto}.layui-layer-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px")}.layui-layer{-webkit-overflow-scrolling:touch}.layui-layer{top:150px;left:0;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;border-radius:2px;box-shadow:1px 1px 50px rgba(0,0,0,.3)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #b2b2b2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-btn a,.layui-layer-setwin span{display:inline-block;vertical-align:middle;*display:inline;*zoom:1}.layui-layer-move{display:none;position:fixed;*position:absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layer-anim{-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-00{-webkit-animation-name:layer-bounceIn;animation-name:layer-bounceIn}@-webkit-keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:layer-zoomInDown;animation-name:layer-zoomInDown}@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}@-webkit-keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:layer-zoomInLeft;animation-name:layer-zoomInLeft}@-webkit-keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}@keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);-ms-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}.layer-anim-04{-webkit-animation-name:layer-rollIn;animation-name:layer-rollIn}@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}@-webkit-keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layer-anim-06{-webkit-animation-name:layer-shake;animation-name:layer-shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes layer-slide-down{from{transform:translate3d(0,-100%,0)}to{transform:translate3d(0,0,0)}}@keyframes layer-slide-down-out{from{transform:translate3d(0,0,0)}to{transform:translate3d(0,-100%,0)}}.layer-anim-slide-down{animation-name:layer-slide-down}.layer-anim-slide-down-out{animation-name:layer-slide-down-out}@keyframes layer-slide-left{from{transform:translate3d(100%,0,0)}to{transform:translate3d(0,0,0)}}@keyframes layer-slide-left-out{from{transform:translate3d(0,0,0)}to{transform:translate3d(100%,0,0)}}.layer-anim-slide-left{animation-name:layer-slide-left}.layer-anim-slide-left-out{animation-name:layer-slide-left-out}@keyframes layer-slide-up{from{transform:translate3d(0,100%,0)}to{transform:translate3d(0,0,0)}}@keyframes layer-slide-up-out{from{transform:translate3d(0,0,0)}to{transform:translate3d(0,100%,0)}}.layer-anim-slide-up{animation-name:layer-slide-up}.layer-anim-slide-up-out{animation-name:layer-slide-up-out}@keyframes layer-slide-right{from{transform:translate3d(-100%,0,0)}to{transform:translate3d(0,0,0)}}@keyframes layer-slide-right-out{from{transform:translate3d(0,0,0)}to{transform:translate3d(-100%,0,0)}}.layer-anim-slide-right{animation-name:layer-slide-right}.layer-anim-slide-right-out{animation-name:layer-slide-right-out}.layui-layer-title{padding:0 81px 0 16px;height:50px;line-height:50px;border-bottom:1px solid #f0f0f0;font-size:14px;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:2px 2px 0 0}.layui-layer-setwin{position:absolute;right:15px;*right:0;top:16px;font-size:0;line-height:initial}.layui-layer-setwin span{position:relative;width:16px;height:16px;line-height:18px;margin-left:10px;text-align:center;font-size:16px;cursor:pointer;color:#000;_overflow:hidden;box-sizing:border-box}.layui-layer-setwin .layui-layer-min:before{content:'';position:absolute;width:12px;border-bottom:1px solid #2e2d3c;left:50%;top:50%;margin:-.5px 0 0 -6px;cursor:pointer;_overflow:hidden}.layui-layer-setwin .layui-layer-min:hover:before{background-color:#2d93ca}.layui-layer-setwin .layui-layer-max:after,.layui-layer-setwin .layui-layer-max:before{content:'';position:absolute;left:50%;top:50%;z-index:1;width:9px;height:9px;margin:-5px 0 0 -5px;border:1px solid #2e2d3c}.layui-layer-setwin .layui-layer-max:hover:after,.layui-layer-setwin .layui-layer-max:hover:before{border-color:#2d93ca}.layui-layer-setwin .layui-layer-min:hover:before{background-color:#2d93ca}.layui-layer-setwin .layui-layer-maxmin:after,.layui-layer-setwin .layui-layer-maxmin:before{width:7px;height:7px;margin:-3px 0 0 -3px;background-color:#fff}.layui-layer-setwin .layui-layer-maxmin:after{z-index:0;margin:-5px 0 0 -1px}.layui-layer-setwin .layui-layer-close{cursor:pointer}.layui-layer-setwin .layui-layer-close:hover{opacity:.7}.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;color:#fff;background-color:#787878;padding:3px;border:3px solid;width:28px;height:28px;font-size:16px;font-weight:bolder;border-radius:50%;margin-left:0;*right:-18px;_display:none}.layui-layer-setwin .layui-layer-close2:hover{opacity:unset;background-color:#3888f6}.layui-layer-btn{text-align:right;padding:0 15px 12px;pointer-events:auto;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:30px;line-height:30px;margin:5px 5px 0;padding:0 16px;border:1px solid #dedede;background-color:#fff;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none;box-sizing:border-box}.layui-layer-btn a:hover{opacity:.9;text-decoration:none}.layui-layer-btn a:active{opacity:.8}.layui-layer-btn .layui-layer-btn0{border-color:transparent;background-color:#1e9fff;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.layui-layer-dialog{min-width:240px}.layui-layer-dialog .layui-layer-content{position:relative;padding:16px;line-height:24px;word-break:break-all;overflow:hidden;font-size:14px;overflow-x:hidden;overflow-y:auto}.layui-layer-dialog .layui-layer-content .layui-layer-face{position:absolute;top:18px;left:16px;color:#959595;font-size:32px;_left:-40px}.layui-layer-dialog .layui-layer-content .layui-icon-tips{color:#f39b12}.layui-layer-dialog .layui-layer-content .layui-icon-success{color:#16b777}.layui-layer-dialog .layui-layer-content .layui-icon-error{top:19px;color:#ff5722}.layui-layer-dialog .layui-layer-content .layui-icon-question{color:#ffb800}.layui-layer-dialog .layui-layer-content .layui-icon-lock{color:#787878}.layui-layer-dialog .layui-layer-content .layui-icon-face-cry{color:#ff5722}.layui-layer-dialog .layui-layer-content .layui-icon-face-smile{color:#16b777}.layui-layer-rim{border:6px solid #8d8d8d;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #d3d4d3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:rgba(0,0,0,.6);color:#fff;border:none}.layui-layer-hui .layui-layer-close{color:#fff}.layui-layer-hui .layui-layer-content{padding:11px 24px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:18px 24px 18px 58px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-iframe .layui-layer-btn,.layui-layer-page .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:0 0}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:0 0;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:76px;height:38px;line-height:38px;text-align:center}.layui-layer-loading-icon{font-size:38px;color:#959595}.layui-layer-loading2{text-align:center}.layui-layer-loading-2{position:relative;height:38px}.layui-layer-loading-2:after,.layui-layer-loading-2:before{content:'';position:absolute;left:50%;top:50%;width:38px;height:38px;margin:-19px 0 0 -19px;border-radius:50%;border:3px solid #d2d2d2;box-sizing:border-box}.layui-layer-loading-2:after{border-color:transparent;border-left-color:#1e9fff}.layui-layer-tips{background:0 0;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:8px 15px;font-size:12px;_float:left;border-radius:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow:hidden}.layui-layer-tips i.layui-layer-TipsB,.layui-layer-tips i.layui-layer-TipsT{left:5px;border-right-style:solid;border-right-color:#000}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layui-layer-TipsB{top:-8px}.layui-layer-tips i.layui-layer-TipsL,.layui-layer-tips i.layui-layer-TipsR{top:5px;border-bottom-style:solid;border-bottom-color:#000}.layui-layer-tips i.layui-layer-TipsR{left:-8px}.layui-layer-tips i.layui-layer-TipsL{right:-8px}.layui-layer-lan .layui-layer-title{background:#4476a7;color:#fff;border:none}.layui-layer-lan .layui-layer-btn{padding:5px 10px 10px;border-top:1px solid #e9e7e7}.layui-layer-lan .layui-layer-btn a{background:#fff;border-color:#e9e7e7;color:#333}.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#c9c5c5}.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}.layui-layer-molv .layui-layer-btn a{background:#009f95;border-color:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92b8b1}.layui-layer-lan .layui-layer-setwin .layui-icon,.layui-layer-molv .layui-layer-setwin .layui-icon{color:#fff}.layui-layer-win10{border:1px solid #aaa;box-shadow:1px 1px 6px rgba(0,0,0,.3);border-radius:none}.layui-layer-win10 .layui-layer-title{height:32px;line-height:32px;padding-left:8px;border-bottom:none;font-size:12px}.layui-layer-win10 .layui-layer-setwin{right:0;top:0}.layui-layer-win10 .layui-layer-setwin span{margin-left:0;width:32px;height:32px;padding:8px}.layui-layer-win10.layui-layer-page .layui-layer-setwin span{width:38px}.layui-layer-win10 .layui-layer-setwin span:hover{background-color:#e5e5e5}.layui-layer-win10 .layui-layer-setwin span.layui-icon-close:hover{background-color:#e81123;color:#fff}.layui-layer-win10.layui-layer-dialog .layui-layer-content{padding:8px 16px 32px;color:#0033bc}.layui-layer-win10.layui-layer-dialog .layui-layer-padding{padding-top:18px;padding-left:58px}.layui-layer-win10 .layui-layer-btn{padding:5px 5px 10px;border-top:1px solid #dfdfdf;background-color:#f0f0f0}.layui-layer-win10 .layui-layer-btn a{height:20px;line-height:18px;background-color:#e1e1e1;border-color:#adadad;color:#000;font-size:12px;transition:all .3s}.layui-layer-win10 .layui-layer-btn a:hover{border-color:#2a8edd;background-color:#e5f1fb}.layui-layer-win10 .layui-layer-btn .layui-layer-btn0{border-color:#0078d7}.layui-layer-prompt .layui-layer-input{display:block;width:260px;height:36px;margin:0 auto;line-height:30px;padding-left:10px;border:1px solid #e6e6e6;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px;padding:6px 10px}.layui-layer-prompt .layui-layer-content{padding:16px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;display:inline-block;vertical-align:top;border-left:1px solid transparent;border-right:1px solid transparent;min-width:80px;max-width:300px;padding:0 16px;text-align:center;cursor:default;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;cursor:pointer}.layui-layer-tab .layui-layer-title span.layui-this{height:51px;border-left-color:#eee;border-right-color:#eee;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left-color:transparent}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.layui-this{display:block}.layui-layer-photos{background:0 0;box-shadow:none}.layui-layer-photos .layui-layer-content{overflow:visible;text-align:center}.layui-layer-photos .layer-layer-photos-main img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-photos-next,.layui-layer-photos-prev{position:fixed;top:50%;width:52px;height:52px;line-height:52px;margin-top:-26px;cursor:pointer;font-size:52px;color:#717171}.layui-layer-photos-prev{left:32px}.layui-layer-photos-next{right:32px}.layui-layer-photos-next:hover,.layui-layer-photos-prev:hover{color:#959595}.layui-layer-photos-toolbar{position:fixed;left:0;right:0;bottom:0;width:100%;height:52px;line-height:52px;background-color:#000\9;filter:Alpha(opacity=60);background-color:rgba(0,0,0,.32);color:#fff;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;font-size:0}.layui-layer-photos-toolbar>*{display:inline-block;vertical-align:top;padding:0 16px;font-size:12px;color:#fff;*display:inline;*zoom:1}.layui-layer-photos-toolbar *{font-size:12px}.layui-layer-photos-header{top:0;bottom:auto}.layui-layer-photos-header>span{cursor:pointer}.layui-layer-photos-header>span:hover{background-color:rgba(51,51,51,.32)}.layui-layer-photos-header .layui-icon{font-size:18px}.layui-layer-photos-footer>h3{max-width:65%;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-layer-photos-footer a:hover{text-decoration:underline}.layui-layer-photos-footer em{font-style:normal}@-webkit-keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:layer-bounceOut;animation-name:layer-bounceOut;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.eot b/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..3f5e98bb584b80ae0ce0d39b598fb37423ea8220 Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.eot differ diff --git a/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.svg b/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.svg new file mode 100644 index 0000000000000000000000000000000000000000..4f1920deddba24bdb57bdc74a8abcc160f4d960f --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.svg @@ -0,0 +1,405 @@ + + + + Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.ttf b/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6e84a89e031247509801ae5d65cc8d20323cb766 Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.ttf differ diff --git a/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.woff b/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..acd7ed6082729ae968e44aa9f676cd50a37e8eb6 Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.woff differ diff --git a/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.woff2 b/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..5badd6e38ec077cd5b50da3d41f029f7534be086 Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/component/layui/font/iconfont.woff2 differ diff --git a/demo/webman/frontend/layui_admin_flow/component/layui/layui.js b/demo/webman/frontend/layui_admin_flow/component/layui/layui.js new file mode 100644 index 0000000000000000000000000000000000000000..f0ac221c5ad63c5339320416ed2976cb85131506 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/layui/layui.js @@ -0,0 +1 @@ +/** v2.9.2 | MIT Licensed */;!function(d){"use strict";var t,h=d.document,m={modules:{},status:{},timeout:10,event:{}},n=function(){this.v="2.9.2"},e=d.LAYUI_GLOBAL||{},v=(t=h.currentScript?h.currentScript.src:function(){for(var t,e=h.scripts,o=e.length-1,n=o;01e3*m.timeout/4?g(s+" is not a valid module","error"):void(m.status[s]?y():setTimeout(n,4))}())}function y(){e.push(layui[s]),11e3*m.timeout/4?g(s+" is not a valid module","error"):void("string"==typeof m.modules[s]&&m.status[s]?y():setTimeout(f,4))}():((r=h.createElement("script"))["async"]=!0,r.charset="utf-8",r.src=i+((u=!0===m.version?m.v||(new Date).getTime():m.version||"")?"?v="+u:""),l.appendChild(r),!r.attachEvent||r.attachEvent.toString&&r.attachEvent.toString().indexOf("[native code")<0||b?r.addEventListener("load",function(t){p(t,i)},!1):r.attachEvent("onreadystatechange",function(t){p(t,i)}),m.modules[s]=i)),a},n.prototype.disuse=function(t){var o=this;return t=o.isArray(t)?t:[t],o.each(t,function(t,e){m.status[e],delete o[e],delete N[e],delete o.modules[e],delete m.status[e],delete m.modules[e]}),o},n.prototype.getStyle=function(t,e){t=t.currentStyle||d.getComputedStyle(t,null);return t[t.getPropertyValue?"getPropertyValue":"getAttribute"](e)},n.prototype.link=function(o,n,t){var r=this,e=h.getElementsByTagName("head")[0],i=h.createElement("link"),a="layuicss-"+((t="string"==typeof n?n:t)||o).replace(/\.|\//g,""),u="creating",l=0;return i.href=o+(m.debug?"?v="+(new Date).getTime():""),i.rel="stylesheet",i.id=a,i.media="all",h.getElementById(a)||e.appendChild(i),"function"==typeof n&&function s(t){var e=h.getElementById(a);return++l>1e3*m.timeout/100?g(o+" timeout"):void(1989===parseInt(r.getStyle(e,"width"))?(t===u&&e.removeAttribute("lay-status"),e.getAttribute("lay-status")===u?setTimeout(s,100):n()):(e.setAttribute("lay-status",u),setTimeout(function(){s(u)},100)))}(),r},n.prototype.addcss=function(t,e,o){return layui.link(m.dir+"css/"+t,e,o)},m.callback={},n.prototype.factory=function(t){if(layui[t])return"function"==typeof m.callback[t]?m.callback[t]:null},n.prototype.img=function(t,e,o){var n=new Image;if(n.src=t,n.complete)return e(n);n.onload=function(){n.onload=null,"function"==typeof e&&e(n)},n.onerror=function(t){n.onerror=null,"function"==typeof o&&o(t)}},n.prototype.config=function(t){for(var e in t=t||{})m[e]=t[e];return this},n.prototype.modules=function(){var t,e={};for(t in N)e[t]=N[t];return e}(),n.prototype.extend=function(t){for(var e in t=t||{})this[e]||this.modules[e]?g(e+" Module already exists","error"):this.modules[e]=t[e];return this},n.prototype.router=n.prototype.hash=function(t){var o={path:[],search:{},hash:((t=t||location.hash).match(/[^#](#.*$)/)||[])[1]||""};return/^#\//.test(t)&&(t=t.replace(/^#\//,""),o.href="/"+t,t=t.replace(/([^#])(#.*$)/,"$1").split("/")||[],this.each(t,function(t,e){/^\w+=/.test(e)?(e=e.split("="),o.search[e[0]]=e[1]):o.path.push(e)})),o},n.prototype.url=function(t){var r,e,o=this;return{pathname:(t?((t.match(/\.[^.]+?\/.+/)||[])[0]||"").replace(/^[^\/]+/,"").replace(/\?.+/,""):location.pathname).replace(/^\//,"").split("/"),search:(r={},e=(t?((t.match(/\?.+/)||[])[0]||"").replace(/\#.+/,""):location.search).replace(/^\?+/,"").split("&"),o.each(e,function(t,e){var o=e.indexOf("="),n=o<0?e.substr(0,e.length):0!==o&&e.substr(0,o);n&&(r[n]=0(l.innerHeight||h.documentElement.clientHeight)},d.getStyleRules=function(t,n){if(t)return t=(t=t.sheet||t.styleSheet||{}).cssRules||t.rules,"function"==typeof n&&layui.each(t,function(t,e){if(n(e,t))return!0}),t},d.style=function(t){t=t||{};var e=d.elem("style"),n=t.text||"",i=t.target;if(n)return"styleSheet"in e?(e.setAttribute("type","text/css"),e.styleSheet.cssText=n):e.innerHTML=n,e.id="LAY-STYLE-"+(t.id||(n=d.style.index||0,d.style.index++,"DF-"+n)),i&&((t=d(i).find("#"+e.id))[0]&&t.remove(),d(i).append(e)),e},d.position=function(t,e,n){var i,o,r,c,u,a,s,f;e&&(n=n||{},t!==h&&t!==d("body")[0]||(n.clickType="right"),i="right"===n.clickType?{left:(i=n.e||l.event||{}).clientX,top:i.clientY,right:i.clientX,bottom:i.clientY}:t.getBoundingClientRect(),s=e.offsetWidth,f=e.offsetHeight,o=function(t){return h.body[t=t?"scrollLeft":"scrollTop"]|h.documentElement[t]},r=function(t){return h.documentElement[t?"clientWidth":"clientHeight"]},c="margin"in n?n.margin:5,u=i.left,a=i.bottom,"center"===n.align?u-=(s-t.offsetWidth)/2:"right"===n.align&&(u=u-s+t.offsetWidth),(u=u+s+c>r("width")?r("width")-s-c:u)r()&&(i.top>f+c&&i.top<=r()?a=i.top-f-2*c:n.allowBottomOut||(a=r()-f-2*c)<0&&(a=0)),(s=n.position)&&(e.style.position=s),e.style.left=u+("fixed"===s?0:o(1))+"px",e.style.top=a+("fixed"===s?0:o())+"px",d.hasScrollbar()||(f=e.getBoundingClientRect(),!n.SYSTEM_RELOAD&&f.bottom+c>r()&&(n.SYSTEM_RELOAD=!0,setTimeout(function(){d.position(t,e,n)},50))))},d.options=function(t,e){if(e="object"==typeof e?e:{attr:e},t===h)return{};var t=d(t),n=e.attr||"lay-options",t=t.attr(n);try{return new Function("return "+(t||"{}"))()}catch(i){return layui.hint().error(e.errorText||[n+'="'+t+'"',"\n parseerror: "+i].join("\n"),"error"),{}}},d.isTopElem=function(n){var t=[h,d("body")[0]],i=!1;return d.each(t,function(t,e){if(e===n)return i=!0}),i},d.clipboard={writeText:function(n){var i=String(n.text);function t(){var t=h.createElement("textarea");t.value=i,t.style.position="fixed",t.style.opacity="0",t.style.top="0px",t.style.left="0px",h.body.appendChild(t),t.select();try{h.execCommand("copy"),"function"==typeof n.done&&n.done()}catch(e){"function"==typeof n.error&&n.error(e)}finally{t.remove?t.remove():h.body.removeChild(t)}}navigator&&"clipboard"in navigator?navigator.clipboard.writeText(i).then(n.done,function(){t()}):t()}},d.passiveSupported=function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});l.addEventListener("test",null,e),l.removeEventListener("test",null,e)}catch(n){}return t}(),d.touchEventsSupported=function(){return"ontouchstart"in l},d.touchSwipe=function(t,e){var n,i,o,r=e,c=d(t)[0];c&&d.touchEventsSupported()&&(n={pointerStart:{x:0,y:0},pointerEnd:{x:0,y:0},distanceX:0,distanceY:0,direction:"none",timeStart:null},e=function(t){1===t.touches.length&&(c.addEventListener("touchmove",i,!!d.passiveSupported&&{passive:!1}),c.addEventListener("touchend",o),c.addEventListener("touchcancel",o),n.timeStart=Date.now(),n.pointerStart.x=n.pointerEnd.x=t.touches[0].clientX,n.pointerStart.y=n.pointerEnd.y=t.touches[0].clientY,r.onTouchStart)&&r.onTouchStart(t,n)},i=function(t){t.preventDefault(),n.pointerEnd.x=t.touches[0].clientX,n.pointerEnd.y=t.touches[0].clientY,n.distanceX=n.pointerStart.x-n.pointerEnd.x,n.distanceY=n.pointerStart.y-n.pointerEnd.y,Math.abs(n.distanceX)>Math.abs(n.distanceY)?n.direction=0]|&(?=#[a-zA-Z0-9]+)/g.test(e+="")?e.replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,"""):e}},i=function(e){return new RegExp(e,"g")},u=function(e,r){var n="Laytpl Error: ";return"object"==typeof console&&console.error(n+e+"\n"+(r||"")),n+e},n=function(e,r){var n=this,e=(n.config=n.config||{},n.template=e,function(e){for(var r in e)n.config[r]=e[r]});e(c),e(r)},r=(n.prototype.tagExp=function(e,r,n){var c=this.config;return i((r||"")+c.open+["#([\\s\\S])+?","([^{#}])*?"][e||0]+c.close+(n||""))},n.prototype.parse=function(e,r){var n=this,c=n.config,t=e,o=i("^"+c.open+"#",""),p=i(c.close+"$","");if("string"!=typeof e)return e;e='"use strict";var view = "'+(e=e.replace(/\s+|\r|\t|\n/g," ").replace(i(c.open+"#"),c.open+"# ").replace(i(c.close+"}"),"} "+c.close).replace(/\\/g,"\\\\").replace(i(c.open+"!(.+?)!"+c.close),function(e){return e=e.replace(i("^"+c.open+"!"),"").replace(i("!"+c.close),"").replace(i(c.open+"|"+c.close),function(e){return e.replace(/(.)/g,"\\$1")})}).replace(/(?="|')/g,"\\").replace(n.tagExp(),function(e){return'";'+(e=e.replace(o,"").replace(p,"")).replace(/\\(.)/g,"$1")+';view+="'}).replace(n.tagExp(1),function(e){var r='"+laytpl.escape(';return e.replace(/\s/g,"")===c.open+c.close?"":(e=e.replace(i(c.open+"|"+c.close),""),/^=/.test(e)?e=e.replace(/^=/,""):/^-/.test(e)&&(e=e.replace(/^-/,""),r='"+('),r+e.replace(/\\(.)/g,"$1")+')+"')}))+'";return view;';try{return n.cache=e=new Function("d, laytpl",e),e(r,l)}catch(a){return delete n.cache,u(a,t)}},n.prototype.render=function(e,r){e=e||{};var n=this,e=n.cache?n.cache(e,l):n.parse(n.template,e);return"function"==typeof r&&r(e),e},function(e,r){return new n(e,r)});r.config=function(e){for(var r in e=e||{})c[r]=e[r]},r.v="2.0.0",e("laytpl",r)});layui.define(function(e){"use strict";var r=document,u="getElementById",c="getElementsByTagName",a="layui-disabled",t=function(e){var a=this;a.config=e||{},a.config.index=++o.index,a.render(!0)},o=(t.prototype.type=function(){var e=this.config;if("object"==typeof e.elem)return e.elem.length===undefined?2:3},t.prototype.view=function(){var i,e,t,n=this.config,r=n.groups="groups"in n?Number(n.groups)||0:5,u=(n.layout="object"==typeof n.layout?n.layout:["prev","page","next"],n.count=Number(n.count)||0,n.curr=Number(n.curr)||1,n.limits="object"==typeof n.limits?n.limits:[10,20,30,40,50],n.limit=Number(n.limit)||10,n.pages=Math.ceil(n.count/n.limit)||1,n.curr>n.pages?n.curr=n.pages:n.curr<1&&(n.curr=1),r<0?r=1:r>n.pages&&(r=n.pages),n.prev="prev"in n?n.prev:"上一页",n.next="next"in n?n.next:"下一页",n.pages>r?Math.ceil((n.curr+(1'+n.prev+"":"",page:function(){var e=[];if(n.count<1)return"";1'+(n.first||1)+"");var a=Math.floor((r-1)/2),t=1n.pages?n.pages:a:r;for(i-t…');t<=i;t++)t===n.curr?e.push('"+t+""):e.push(''+t+"");return n.pages>r&&n.pages>i&&!1!==n.last&&(i+1…'),0!==r)&&e.push(''+(n.last||n.pages)+""),e.join("")}(),next:n.next?''+n.next+"":"",count:''+(e="object"==typeof n.countText?n.countText:["\u5171 "," \u6761"])[0]+n.count+e[1]+"",limit:(i=['"),refresh:['','',""].join(""),skip:[''+(e="object"==typeof n.skipText?n.skipText:["到第","页","确定"])[0],'',e[1]+'",""].join("")};return['
                                                                                                  ',(t=[],layui.each(n.layout,function(e,a){l[a]&&t.push(l[a])}),t.join("")),"
                                                                                                  "].join("")},t.prototype.jump=function(e,a){if(e){var t=this,i=t.config,n=e.children,r=e[c]("button")[0],u=e[c]("input")[0],e=e[c]("select")[0],l=function(){var e=Number(u.value.replace(/\s|\D/g,""));e&&(i.curr=e,t.render())};if(a)return l();for(var s=0,p=n.length;si.pages||(i.curr=e,t.render())});e&&o.on(e,"change",function(){var e=this.value;i.curr*e>i.count&&(i.curr=Math.ceil(i.count/e)),i.limit=e,t.render()}),r&&o.on(r,"click",function(){l()})}},t.prototype.skip=function(t){var i,e;t&&(i=this,e=t[c]("input")[0])&&o.on(e,"keyup",function(e){var a=this.value,e=e.keyCode;/^(37|38|39|40)$/.test(e)||(/\D/.test(a)&&(this.value=a.replace(/\D/,"")),13===e&&i.jump(t,!0))})},t.prototype.render=function(e){var a=this,t=a.config,i=a.type(),n=a.view(),i=(2===i?t.elem&&(t.elem.innerHTML=n):3===i?t.elem.html(n):r[u](t.elem)&&(r[u](t.elem).innerHTML=n),t.jump&&t.jump(t,e),r[u]("layui-laypage-"+t.index));a.jump(i),t.hash&&!e&&(location.hash="!"+t.hash+"="+t.curr),a.skip(i)},{render:function(e){return new t(e).index},index:layui.laypage?layui.laypage.index+1e4:0,on:function(a,e,t){return a.attachEvent?a.attachEvent("on"+e,function(e){e.target=e.srcElement,t.call(a,e)}):a.addEventListener(e,t,!1),this}});e("laypage",o)});!function(i,v){"use strict";var n=i.layui&&layui.define,l={getPath:i.lay&&lay.getPath?lay.getPath:"",link:function(e,t,a){D.path&&i.lay&&lay.layui&&lay.layui.link(D.path+e,t,a)}},e=i.LAYUI_GLOBAL||{},a="laydate",d="layui-"+a+"-id",D={v:"5.5.0",config:{weekStart:0},index:i.laydate&&i.laydate.v?1e5:0,path:e.laydate_dir||l.getPath,set:function(e){var t=this;return t.config=lay.extend({},t.config,e),t},ready:function(e){var t="laydate",a=(n?"modules/":"")+"laydate.css?v="+D.v;return n?layui["layui.all"]?"function"==typeof e&&e():layui.addcss(a,e,t):l.link(a,e,t),this}},s=function(){var t=this,e=t.config.id;return(s.that[e]=t).inst={hint:function(e){t.hint.call(t,e)},reload:function(e){t.reload.call(t,e)},config:t.config}},x="layui-this",k="laydate-disabled",h=[100,2e5],T="layui-laydate-static",w="layui-laydate-list",o="laydate-selected",r="layui-laydate-hint",y="laydate-day-prev",m="laydate-day-next",C=".laydate-btns-confirm",M="laydate-time-text",L="laydate-btns-time",E="layui-laydate-preview",S="layui-laydate-shade",I=function(e){var t,a=this,n=(a.index=++D.index,a.config=lay.extend({},a.config,D.config,e),lay(e.elem||a.config.elem));return 1\u8bf7\u91cd\u65b0\u9009\u62e9",invalidDate:"\u4e0d\u5728\u6709\u6548\u65e5\u671f\u6216\u65f6\u95f4\u8303\u56f4\u5185",formatError:["\u65e5\u671f\u683c\u5f0f\u4e0d\u5408\u6cd5
                                                                                                  \u5fc5\u987b\u9075\u5faa\u4e0b\u8ff0\u683c\u5f0f\uff1a
                                                                                                  ","
                                                                                                  \u5df2\u4e3a\u4f60\u91cd\u7f6e"],preview:"\u5f53\u524d\u9009\u4e2d\u7684\u7ed3\u679c"},en:{weeks:["Su","Mo","Tu","We","Th","Fr","Sa"],time:["Hours","Minutes","Seconds"],timeTips:"Select Time",startTime:"Start Time",endTime:"End Time",dateTips:"Select Date",month:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],tools:{confirm:"Confirm",clear:"Clear",now:"Now"},timeout:"End time cannot be less than start Time
                                                                                                  Please re-select",invalidDate:"Invalid date",formatError:["The date format error
                                                                                                  Must be followed\uff1a
                                                                                                  ","
                                                                                                  It has been reset"],preview:"The selected result"}};return e[this.config.lang]||e.cn},I.prototype.reload=function(e){this.config=lay.extend({},this.config,e),this.init()},I.prototype.init=function(){var r=this,o=r.config,e="static"===o.position,t={year:"yyyy",month:"yyyy-MM",date:"yyyy-MM-dd",time:"HH:mm:ss",datetime:"yyyy-MM-dd HH:mm:ss"};o.elem=lay(o.elem),o.eventElem=lay(o.eventElem),o.elem[0]&&("array"!==layui.type(o.theme)&&(o.theme=[o.theme]),o.fullPanel&&("datetime"!==o.type||o.range)&&delete o.fullPanel,r.rangeStr=o.range?"string"==typeof o.range?o.range:"-":"",r.rangeLinked=!(!o.range||!o.rangeLinked||"date"!==o.type&&"datetime"!==o.type),r.autoCalendarModel=function(){var e=r.rangeLinked;return r.rangeLinked=o.range&&("date"===o.type||"datetime"===o.type)&&(!r.startDate||!r.endDate||r.startDate&&r.endDate&&r.startDate.year===r.endDate.year&&r.startDate.month===r.endDate.month),lay(r.elem)[r.rangeLinked?"addClass":"removeClass"]("layui-laydate-linkage"),r.rangeLinked!=e},r.autoCalendarModel.auto=r.rangeLinked&&"auto"===o.rangeLinked,"array"===layui.type(o.range)&&(r.rangeElem=[lay(o.range[0]),lay(o.range[1])]),t[o.type]||(i.console&&console.error&&console.error("laydate type error:'"+o.type+"' is not supported"),o.type="date"),o.format===t.date&&(o.format=t[o.type]||t.date),r.format=s.formatArr(o.format),o.weekStart&&!/^[0-6]$/.test(o.weekStart)&&(t=r.lang(),o.weekStart=t.weeks.indexOf(o.weekStart),-1===o.weekStart)&&(o.weekStart=0),r.EXP_IF="",r.EXP_SPLIT="",lay.each(r.format,function(e,t){e=new RegExp(c).test(t)?"\\d{"+(new RegExp(c).test(r.format[0===e?e+1:e-1]||"")?/^yyyy|y$/.test(t)?4:t.length:/^yyyy$/.test(t)?"1,4":/^y$/.test(t)?"1,308":"1,2")+"}":"\\"+t;r.EXP_IF=r.EXP_IF+e,r.EXP_SPLIT=r.EXP_SPLIT+"("+e+")"}),r.EXP_IF_ONE=new RegExp("^"+r.EXP_IF+"$"),r.EXP_IF=new RegExp("^"+(o.range?r.EXP_IF+"\\s\\"+r.rangeStr+"\\s"+r.EXP_IF:r.EXP_IF)+"$"),r.EXP_SPLIT=new RegExp("^"+r.EXP_SPLIT+"$",""),r.isInput(o.elem[0])||"focus"===o.trigger&&(o.trigger="click"),o.elem.attr("lay-key",r.index),o.eventElem.attr("lay-key",r.index),o.elem.attr(d,o.id),o.mark=lay.extend({},o.calendar&&"cn"===o.lang?{"0-1-1":"\u5143\u65e6","0-2-14":"\u60c5\u4eba","0-3-8":"\u5987\u5973","0-3-12":"\u690d\u6811","0-4-1":"\u611a\u4eba","0-5-1":"\u52b3\u52a8","0-5-4":"\u9752\u5e74","0-6-1":"\u513f\u7ae5","0-9-10":"\u6559\u5e08","0-10-1":"\u56fd\u5e86","0-12-25":"\u5723\u8bde"}:{},o.mark),lay.each(["min","max"],function(e,t){var a=[],n=[];if("number"==typeof o[t])var i=o[t],l=new Date,l=r.newDate({year:l.getFullYear(),month:l.getMonth(),date:l.getDate(),hours:e?23:0,minutes:e?59:0,seconds:e?59:0}).getTime(),e=new Date(i?i<864e5?l+864e5*i:i:l),a=[e.getFullYear(),e.getMonth()+1,e.getDate()],n=[e.getHours(),e.getMinutes(),e.getSeconds()];else if("string"==typeof o[t])a=(o[t].match(/\d+-\d+-\d+/)||[""])[0].split("-"),n=(o[t].match(/\d+:\d+:\d+/)||[""])[0].split(":");else if("object"==typeof o[t])return o[t];o[t]={year:0|a[0]||(new Date).getFullYear(),month:a[1]?(0|a[1])-1:(new Date).getMonth(),date:0|a[2]||(new Date).getDate(),hours:0|n[0],minutes:0|n[1],seconds:0|n[2]}}),r.elemID="layui-laydate"+o.elem.attr("lay-key"),(o.show||e)&&r.render(),e||r.events(),o.value)&&o.isInitValue&&("date"===layui.type(o.value)?r.setValue(r.parse(0,r.systemDate(o.value))):r.setValue(o.value))},I.prototype.render=function(){var a,n,i,l,r=this,o=r.config,d=r.lang(),s="static"===o.position,y=r.elem=lay.elem("div",{id:r.elemID,"class":["layui-laydate",o.range?" layui-laydate-range":"",r.rangeLinked?" layui-laydate-linkage":"",s?" "+T:"",o.fullPanel?" laydate-theme-fullpanel":"",(a="",lay.each(o.theme,function(e,t){"default"===t||/^#/.test(t)||(a+=" laydate-theme-"+t)}),a)].join("")}),m=r.elemMain=[],c=r.elemHeader=[],u=r.elemCont=[],h=r.table=[],e=r.footer=lay.elem("div",{"class":"layui-laydate-footer"}),t=r.shortcut=lay.elem("ul",{"class":"layui-laydate-shortcut"}),f=(o.zIndex&&(y.style.zIndex=o.zIndex),lay.each(new Array(2),function(e){if(!o.range&&0'+d.timeTips+""),(o.range||"datetime"!==o.type||o.fullPanel)&&f.push(''),lay.each(o.btns,function(e,t){var a=d.tools[t]||"btn";o.range&&"now"===t||(s&&"clear"===t&&(a="cn"===o.lang?"\u91cd\u7f6e":"Reset"),n.push(''+a+""))}),f.push('"),f.join(""))),o.shortcuts&&(y.appendChild(t),lay(t).html((i=[],lay.each(o.shortcuts,function(e,t){i.push('
                                                                                                • '+t.text+"
                                                                                                • ")}),i.join(""))).find("li").on("click",function(e){var t=o.shortcuts[this.dataset.index]||{},t=("function"==typeof t.value?t.value():t.value)||[],n=(layui.isArray(t)||(t=[t]),o.type),t=(lay.each(t,function(e,t){var a=[o.dateTime,r.endDate][e];"time"===n&&"date"!==layui.type(t)?r.EXP_IF.test(t)&&(t=(t.match(r.EXP_SPLIT)||[]).slice(1),lay.extend(a,{hours:0|t[0],minutes:0|t[2],seconds:0|t[4]})):lay.extend(a,r.systemDate("date"===layui.type(t)?t:new Date(t))),"time"!==n&&"datetime"!==n||(r[["startTime","endTime"][e]]={hours:a.hours,minutes:a.minutes,seconds:a.seconds}),0===e?r.startDate=lay.extend({},a):r.endState=!0,"year"===n||"month"===n||"time"===n?r.listYM[e]=[a.year,a.month+1]:e&&r.autoCalendarModel.auto&&r.autoCalendarModel()}),r.checkDate("limit").calendar(null,null,"init"),lay(r.footer).find("."+L).removeClass(k));t&&"date"===t.attr("lay-type")&&t[0].click(),r.done(null,"change"),lay(this).addClass(x),"static"!==o.position&&r.setValue(r.parse()).done().remove()})),lay.each(m,function(e,t){y.appendChild(t)}),o.showBottom&&y.appendChild(e),lay.elem("style")),p=[],g=!0,t=(lay.each(o.theme,function(e,t){g&&/^#/.test(t)?(g=!(l=!0),p.push(["#{{id}} .layui-laydate-header{background-color:{{theme}};}","#{{id}} li.layui-this,#{{id}} td.layui-this>div{background-color:{{theme}} !important;}",-1!==o.theme.indexOf("circle")?"":"#{{id}} .layui-this{background-color:{{theme}} !important;}","#{{id}} .laydate-day-now{color:{{theme}} !important;}","#{{id}} .laydate-day-now:after{border-color:{{theme}} !important;}"].join("").replace(/{{id}}/g,r.elemID).replace(/{{theme}}/g,t))):!g&&/^#/.test(t)&&p.push(["#{{id}} .laydate-selected>div{background-color:{{theme}} !important;}","#{{id}} .laydate-selected:hover>div{background-color:{{theme}} !important;}"].join("").replace(/{{id}}/g,r.elemID).replace(/{{theme}}/g,t))}),o.shortcuts&&o.range&&p.push("#{{id}}.layui-laydate-range{width: 628px;}".replace(/{{id}}/g,r.elemID)),p.length&&(p=p.join(""),"styleSheet"in f?(f.setAttribute("type","text/css"),f.styleSheet.cssText=p):f.innerHTML=p,l&&lay(y).addClass("laydate-theme-molv"),y.appendChild(f)),r.remove(I.thisElemDate),D.thisId=o.id,s?o.elem.append(y):(v.body.appendChild(y),r.position()),o.shade?'
                                                                                                  ':"");y.insertAdjacentHTML("beforebegin",t),r.checkDate().calendar(null,0,"init"),r.changeEvent(),I.thisElemDate=r.elemID,r.renderAdditional(),"function"==typeof o.ready&&o.ready(lay.extend({},o.dateTime,{month:o.dateTime.month+1})),r.preview()},I.prototype.remove=function(e){var t=this,a=t.config,n=lay("#"+(e||t.elemID));return n[0]&&(n.hasClass(T)||t.checkDate(function(){n.remove(),delete t.startDate,delete t.endDate,delete t.endState,delete t.startTime,delete t.endTime,delete D.thisId,"function"==typeof a.close&&a.close(t)}),lay("."+S).remove()),t},I.prototype.position=function(){var e=this.config;return lay.position(e.elem[0],this.elem,{position:e.position}),this},I.prototype.hint=function(e){var t=this,a=(t.config,lay.elem("div",{"class":r}));t.elem&&(a.innerHTML=(e="object"==typeof e?e||{}:{content:e}).content||"",lay(t.elem).find("."+r).remove(),t.elem.appendChild(a),clearTimeout(t.hinTimer),t.hinTimer=setTimeout(function(){lay(t.elem).find("."+r).remove()},"ms"in e?e.ms:3e3))},I.prototype.getAsYM=function(e,t,a){return a?t--:t++,t<0&&(t=11,e--),11h[1]&&(e.year=h[1],o=!0),11t)&&(e.date=t,o=!0)},u=function(n,i,l){var r=["startTime","endTime"];i=(i.match(d.EXP_SPLIT)||[]).slice(1),l=l||0,s.range&&(d[r[l]]=d[r[l]]||{}),lay.each(d.format,function(e,t){var a=parseFloat(i[e]);i[e].lengthd.getDateTime(s.max)?(r=s.dateTime=lay.extend({},s.max),i=!0):d.getDateTime(r)d.getDateTime(s.max))&&(d.endDate=lay.extend({},s.max),i=!0),d.startTime={hours:s.dateTime.hours,minutes:s.dateTime.minutes,seconds:s.dateTime.seconds},d.endTime={hours:d.endDate.hours,minutes:d.endDate.minutes,seconds:d.endDate.seconds},"month"===s.type)&&(s.dateTime.date=1,d.endDate.date=1),i&&m&&(d.setValue(d.parse()),d.hint("value "+l.invalidDate+l.formatError[1])),d.startDate=d.startDate||m&&lay.extend({},s.dateTime),d.autoCalendarModel.auto&&d.autoCalendarModel(),d.endState=!s.range||!d.rangeLinked||!(!d.startDate||!d.endDate),e&&e()),d},I.prototype.mark=function(e,a){var n,t=this.config;return lay.each(t.mark,function(e,t){e=e.split("-");e[0]!=a[0]&&0!=e[0]||e[1]!=a[1]&&0!=e[1]||e[2]!=a[2]||(n=t||a[2])}),n&&e.find("div").html(''+n+""),this},I.prototype.holidays=function(n,i){var e=this.config,l=["","work"];return"array"===layui.type(e.holidays)&&lay.each(e.holidays,function(a,e){lay.each(e,function(e,t){t===n.attr("lay-ymd")&&n.find("div").html('"+i[2]+"")})}),this},I.prototype.limit=function(t){t=t||{};var i=this,e=i.config,l={},a=t.index>(t.time?0:41)?i.endDate:e.dateTime;return lay.each({now:lay.extend({},a,t.date||{}),min:e.min,max:e.max},function(e,a){var n;l[e]=i.newDate(lay.extend({year:a.year,month:"year"===t.type?0:a.month,date:"year"===t.type||"month"===t.type?1:a.date},(n={},lay.each(t.time,function(e,t){n[t]=a[t]}),n))).getTime()}),a=l.nowh[1]&&(d.year=h[1],o.hint(y.invalidDate)),o.firstDate||(o.firstDate=lay.extend({},d)),s.setFullYear(d.year,d.month,1),i=(s.getDay()+(7-n.weekStart))%7,l=D.getEndDate(d.month||12,d.year),r=D.getEndDate(d.month+1,d.year),lay.each(c,function(e,t){var a,n=[d.year,d.month];(t=lay(t)).removeAttr("class"),e"+n[2]+"
                                                                                                  "),o.mark(t,n).holidays(t,n).limit({elem:t,date:{year:n[0],month:n[1]-1,date:n[2]},index:e})}),lay(u[0]).attr("lay-ym",d.year+"-"+(d.month+1)),lay(u[1]).attr("lay-ym",d.year+"-"+(d.month+1)),"cn"===n.lang?(lay(u[0]).attr("lay-type","year").html(d.year+" \u5e74"),lay(u[1]).attr("lay-type","month").html(d.month+1+" \u6708")):(lay(u[0]).attr("lay-type","month").html(y.month[d.month]),lay(u[1]).attr("lay-type","year").html(d.year)),m&&(n.range?!e&&"init"===a||(o.listYM=[[(o.startDate||n.dateTime).year,(o.startDate||n.dateTime).month+1],[o.endDate.year,o.endDate.month+1]],o.list(n.type,0).list(n.type,1),"time"===n.type?o.setBtnStatus("\u65f6\u95f4",lay.extend({},o.systemDate(),o.startTime),lay.extend({},o.systemDate(),o.endTime)):o.setBtnStatus(!0)):(o.listYM=[[d.year,d.month+1]],o.list(n.type,0))),n.range&&"init"===a&&(o.rangeLinked?(s=o.getAsYM(d.year,d.month,t?"sub":null),o.calendar(lay.extend({},d,{year:s[0],month:s[1]}),1-t)):o.calendar(null,1-t)),n.range||(c=["hours","minutes","seconds"],o.limit({elem:lay(o.footer).find(".laydate-btns-now"),date:o.systemDate(/^(datetime|time)$/.test(n.type)?new Date:null),index:0,time:c}),o.limit({elem:lay(o.footer).find(C),index:0,time:c})),o.setBtnStatus(),lay(o.shortcut).find("li."+x).removeClass(x),n.range&&!m&&"init"!==a&&o.stampRange(),o},I.prototype.list=function(n,i){var l,r,e,o,d=this,s=d.config,y=d.rangeLinked?s.dateTime:[s.dateTime,d.endDate][i],m=d.lang(),t=s.range&&"date"!==s.type&&"datetime"!==s.type,c=lay.elem("ul",{"class":w+" "+{year:"laydate-year-list",month:"laydate-month-list",time:"laydate-time-list"}[n]}),a=d.elemHeader[i],u=lay(a[2]).find("span"),h=d.elemCont[i||0],f=lay(h).find("."+w)[0],p="cn"===s.lang,g=p?"\u5e74":"",v=d.listYM[i]||{},D=["hours","minutes","seconds"],T=["startTime","endTime"][i];return v[0]<1&&(v[0]=1),"year"===n?(e=l=v[0]-7,l<1&&(e=l=1),lay.each(new Array(15),function(e){var t=lay.elem("li",{"lay-ym":l}),a={year:l,month:0,date:1};l==v[0]&&lay(t).addClass(x),t.innerHTML=l+g,c.appendChild(t),d.limit({elem:lay(t),date:a,index:i,type:n}),l++}),lay(u[p?0:1]).attr("lay-ym",l-8+"-"+v[1]).html(e+g+" - "+(l-1)+g)):"month"===n?(lay.each(new Array(12),function(e){var t=lay.elem("li",{"lay-ym":e}),a={year:v[0],month:e,date:1};e+1==v[1]&&lay(t).addClass(x),t.innerHTML=m.month[e]+(p?"\u6708":""),c.appendChild(t),d.limit({elem:lay(t),date:a,index:i,type:n})}),lay(u[p?0:1]).attr("lay-ym",v[0]+"-"+v[1]).html(v[0]+g)):"time"===n&&(r=function(){lay(c).find("ol").each(function(a,e){lay(e).find("li").each(function(e,t){d.limit({elem:lay(t),date:[{hours:e},{hours:d[T].hours,minutes:e},{hours:d[T].hours,minutes:d[T].minutes,seconds:e}][a],index:i,time:[["hours"],["hours","minutes"],["hours","minutes","seconds"]][a]})})}),s.range||d.limit({elem:lay(d.footer).find(C),date:d[T],index:0,time:["hours","minutes","seconds"]})},s.range?d[T]||(d[T]="startTime"===T?y:d.endDate):d[T]=y,lay.each([24,60,60],function(t,e){var a=lay.elem("li"),n=["

                                                                                                  "+m.time[t]+"

                                                                                                    "];lay.each(new Array(e),function(e){n.push(""+lay.digit(e,2)+"")}),a.innerHTML=n.join("")+"
                                                                                                  ",c.appendChild(a)}),r()),f&&h.removeChild(f),h.appendChild(c),"year"===n||"month"===n?(lay(d.elemMain[i]).addClass("laydate-ym-show"),lay(c).find("li").on("click",function(){var e=0|lay(this).attr("lay-ym");lay(this).hasClass(k)||(d.rangeLinked?lay.extend(y,{year:"year"===n?e:v[0],month:"year"===n?v[1]-1:e}):y[n]=e,"year"===s.type||"month"===s.type?(lay(c).find("."+x).removeClass(x),lay(this).addClass(x),"month"===s.type&&"year"===n&&(d.listYM[i][0]=e,t&&((i?d.endDate:y).year=e),d.list("month",i))):(d.checkDate("limit").calendar(y,i,"init"),d.closeList()),d.setBtnStatus(),!s.range&&s.autoConfirm&&("month"===s.type&&"month"===n||"year"===s.type&&"year"===n)&&d.setValue(d.parse()).done().remove(),d.autoCalendarModel.auto&&!d.rangeLinked?d.choose(lay(h).find("td.layui-this"),i):d.endState&&d.done(null,"change"),lay(d.footer).find("."+L).removeClass(k))})):(e=lay.elem("span",{"class":M}),o=function(){lay(c).find("ol").each(function(e){var a=this,t=lay(a).find("li");a.scrollTop=30*(d[T][D[e]]-2),a.scrollTop<=0&&t.each(function(e,t){if(!lay(this).hasClass(k))return a.scrollTop=30*(e-2),!0})})},u=lay(a[2]).find("."+M),o(),e.innerHTML=s.range?[m.startTime,m.endTime][i]:m.timeTips,lay(d.elemMain[i]).addClass("laydate-time-show"),u[0]&&u.remove(),a[2].appendChild(e),(f=lay(c).find("ol")).each(function(t){var a=this;lay(a).find("li").on("click",function(){var e=0|this.innerHTML;lay(this).hasClass(k)||(s.range?d[T][D[t]]=e:y[D[t]]=e,lay(a).find("."+x).removeClass(x),lay(this).addClass(x),r(),o(),(d.endDate||"time"===s.type||"datetime"===s.type&&s.fullPanel)&&d.done(null,"change"),d.setBtnStatus())})}),lay.touchEventsSupported()&&f.on("touchstart",function(){this.style["overflow-y"]="auto"})),d},I.prototype.listYM=[],I.prototype.closeList=function(){var a=this;a.config;lay.each(a.elemCont,function(e,t){lay(this).find("."+w).remove(),lay(a.elemMain[e]).removeClass("laydate-ym-show laydate-time-show")}),lay(a.elem).find("."+M).remove()},I.prototype.setBtnStatus=function(e,t,a){var n=this,i=n.config,l=n.lang(),r=lay(n.footer).find(C);i.range&&"time"!==i.type&&(t=t||(n.rangeLinked?n.startDate:i.dateTime),a=a||n.endDate,i=!n.endState||n.newDate(t).getTime()>n.newDate(a).getTime(),n.limit({date:t})||n.limit({date:a})?r.addClass(k):r[i?"addClass":"removeClass"](k),e)&&i&&n.hint("string"==typeof e?l.timeout.replace(/\u65e5\u671f/g,e):l.timeout)},I.prototype.parse=function(e,t){var a=this,n=a.config,i=a.rangeLinked?a.startDate:n.dateTime,t=t||("end"==e?lay.extend({},a.endDate,a.endTime):n.range?lay.extend({},i||n.dateTime,a.startTime):n.dateTime),i=D.parse(t,a.format,1);return n.range&&e===undefined?i+" "+a.rangeStr+" "+a.parse("end"):i},I.prototype.newDate=function(e){return e=e||{},new Date(e.year||1,e.month||0,e.date||1,e.hours||0,e.minutes||0,e.seconds||0)},I.prototype.getDateTime=function(e){return this.newDate(e).getTime()},I.prototype.setValue=function(e){var t=this,a=t.config,n=a.elem[0];return"static"!==a.position&&(e=e||"",t.isInput(n)?lay(n).val(e):(a=t.rangeElem)?("array"!==layui.type(e)&&(e=e.split(" "+t.rangeStr+" ")),a[0].val(e[0]||""),a[1].val(e[1]||"")):(0===lay(n).find("*").length&&lay(n).html(e),lay(n).attr("lay-date",e))),t},I.prototype.preview=function(){var e,t=this,a=t.config;a.isPreview&&(e=lay(t.elem).find("."+E),a=!a.range||(t.rangeLinked?t.endState:t.endDate)?t.parse():"",e.html(a),e.html())&&(e.css({color:"#16b777"}),setTimeout(function(){e.css({color:"#777"})},300))},I.prototype.renderAdditional=function(){this.config.fullPanel&&this.list("time",0)},I.prototype.stampRange=function(){var n,i=this,l=i.config,r=i.rangeLinked?i.startDate:l.dateTime,e=lay(i.elem).find("td");l.range&&!i.endState&&lay(i.footer).find(C).addClass(k),r=r&&i.newDate({year:r.year,month:r.month,date:r.date}).getTime(),n=i.endState&&i.endDate&&i.newDate({year:i.endDate.year,month:i.endDate.month,date:i.endDate.date}).getTime(),lay.each(e,function(e,t){var a=lay(t).attr("lay-ymd").split("-"),a=i.newDate({year:a[0],month:a[1]-1,date:a[2]}).getTime();l.rangeLinked&&!i.startDate&&a===i.newDate(i.systemDate()).getTime()&&lay(t).addClass(lay(t).hasClass(y)||lay(t).hasClass(m)?"":"laydate-day-now"),lay(t).removeClass(o+" "+x),a!==r&&a!==n||(i.rangeLinked||!i.rangeLinked&&(e<42?a===r:a===n))&&lay(t).addClass(lay(t).hasClass(y)||lay(t).hasClass(m)?o:x),rn.getDateTime(i.max)&&(n[t]={hours:i.max.hours,minutes:i.max.minutes,seconds:i.max.seconds},lay.extend(l,n[t])))}),a||(n.startDate=lay.extend({},l)),n.endState&&!n.limit({date:n.thisDateTime(1-a)})&&(((r=n.endState&&n.autoCalendarModel.auto?n.autoCalendarModel():r)||n.rangeLinked&&n.endState)&&n.newDate(n.startDate)>n.newDate(n.endDate)&&(e=n.startDate.year===n.endDate.year&&n.startDate.month===n.endDate.month&&n.startDate.date===n.endDate.date,o=n.startDate,n.startDate=lay.extend({},n.endDate,e?{}:n.startTime),i.dateTime=lay.extend({},n.startDate),n.endDate=lay.extend({},o,e?{}:n.endTime),e)&&(o=n.startTime,n.startTime=n.endTime,n.endTime=o),r)&&(i.dateTime=lay.extend({},n.startDate)),n.rangeLinked?(e=lay.extend({},l),!t||a||r||(o=n.getAsYM(l.year,l.month,"sub"),lay.extend(i.dateTime,{year:o[0],month:o[1]})),n.calendar(e,t,r?"init":null)):n.calendar(null,a,r?"init":null),n.endState&&n.done(null,"change")):"static"===i.position?n.calendar().done().done(null,"change"):"date"===i.type?i.autoConfirm?n.setValue(n.parse()).done().remove():n.calendar().done(null,"change"):"datetime"===i.type&&n.calendar().done(null,"change"))},I.prototype.tool=function(t,e){var a=this,n=a.config,i=a.lang(),l=n.dateTime,r="static"===n.position,o={datetime:function(){lay(t).hasClass(k)||(a.list("time",0),n.range&&a.list("time",1),lay(t).attr("lay-type","date").html(a.lang().dateTips))},date:function(){a.closeList(),lay(t).attr("lay-type","datetime").html(a.lang().timeTips)},clear:function(){r&&(lay.extend(l,a.firstDate),a.calendar()),n.range&&(delete n.dateTime,delete a.endDate,delete a.startTime,delete a.endTime),a.setValue(""),a.done(null,"onClear").done(["",{},{}]).remove()},now:function(){var e=new Date;if(lay(t).hasClass(k))return a.hint(i.tools.now+", "+i.invalidDate);lay.extend(l,a.systemDate(),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()}),a.setValue(a.parse()),r&&a.calendar(),a.done(null,"onNow").done().remove()},confirm:function(){if(n.range){if(lay(t).hasClass(k))return a.hint("time"===n.type?i.timeout.replace(/\u65e5\u671f/g,"\u65f6\u95f4"):i.timeout)}else if(lay(t).hasClass(k))return a.hint(i.invalidDate);a.setValue(a.parse()),a.done(null,"onConfirm").done().remove()}};o[e]&&o[e]()},I.prototype.change=function(n){var i=this,l=i.config,r=i.thisDateTime(n),o=l.range&&("year"===l.type||"month"===l.type),d=i.elemCont[n||0],s=i.listYM[n],e=function(e){var t=lay(d).find(".laydate-year-list")[0],a=lay(d).find(".laydate-month-list")[0];return t&&(s[0]=e?s[0]-15:s[0]+15,i.list("year",n)),a&&(e?s[0]--:s[0]++,i.list("month",n)),(t||a)&&(lay.extend(r,{year:s[0]}),o&&(r.year=s[0]),l.range||i.done(null,"change"),l.range||i.limit({elem:lay(i.footer).find(C),date:{year:s[0]}})),i.setBtnStatus(),t||a};return{prevYear:function(){e("sub")||(i.rangeLinked?(l.dateTime.year--,i.checkDate("limit").calendar(null,null,"init")):(r.year--,i.checkDate("limit").calendar(null,n),i.autoCalendarModel.auto?i.choose(lay(d).find("td.layui-this"),n):i.done(null,"change")))},prevMonth:function(){i.rangeLinked&&(r=l.dateTime);var e=i.getAsYM(r.year,r.month,"sub");lay.extend(r,{year:e[0],month:e[1]}),i.checkDate("limit").calendar(null,null,"init"),i.rangeLinked||(i.autoCalendarModel.auto?i.choose(lay(d).find("td.layui-this"),n):i.done(null,"change"))},nextMonth:function(){i.rangeLinked&&(r=l.dateTime);var e=i.getAsYM(r.year,r.month);lay.extend(r,{year:e[0],month:e[1]}),i.checkDate("limit").calendar(null,null,"init"),i.rangeLinked||(i.autoCalendarModel.auto?i.choose(lay(d).find("td.layui-this"),n):i.done(null,"change"))},nextYear:function(){e()||(i.rangeLinked?(l.dateTime.year++,i.checkDate("limit").calendar(null,0,"init")):(r.year++,i.checkDate("limit").calendar(null,n),i.autoCalendarModel.auto?i.choose(lay(d).find("td.layui-this"),n):i.done(null,"change")))}}},I.prototype.changeEvent=function(){var i=this;i.config;lay(i.elem).on("click",function(e){lay.stope(e)}).on("mousedown",function(e){lay.stope(e)}),lay.each(i.elemHeader,function(n,e){lay(e[0]).on("click",function(e){i.change(n).prevYear()}),lay(e[1]).on("click",function(e){i.change(n).prevMonth()}),lay(e[2]).find("span").on("click",function(e){var t=lay(this),a=t.attr("lay-ym"),t=t.attr("lay-type");a&&(a=a.split("-"),i.listYM[n]=[0|a[0],0|a[1]],i.list(t,n),lay(i.footer).find("."+L).addClass(k))}),lay(e[3]).on("click",function(e){i.change(n).nextMonth()}),lay(e[4]).on("click",function(e){i.change(n).nextYear()})}),lay.each(i.table,function(e,t){lay(t).find("td").on("click",function(){i.choose(lay(this),e)})}),lay(i.footer).find("span").on("click",function(){var e=lay(this).attr("lay-type");i.tool(this,e)})},I.prototype.isInput=function(e){return/input|textarea/.test(e.tagName.toLocaleLowerCase())||/INPUT|TEXTAREA/.test(e.tagName)},I.prototype.events=function(){var e,t=this,a=t.config;a.elem[0]&&!a.elem[0].eventHandler&&(a.elem.on(a.trigger,e=function(){D.thisId!==a.id&&t.render()}),a.elem[0].eventHandler=!0,a.eventElem.on(a.trigger,e),t.unbind=function(){t.remove(),a.elem.off(a.trigger,e),a.elem.removeAttr("lay-key"),a.elem.removeAttr(d),a.elem[0].eventHandler=!1,a.eventElem.off(a.trigger,e),a.eventElem.removeAttr("lay-key"),delete s.that[a.id]})},s.that={},s.getThis=function(e){var t=s.that[e];return!t&&n&&layui.hint().error(e?a+" instance with ID '"+e+"' not found":"ID argument required"),t},l.run=function(n){n(v).on("mousedown",function(e){var t,a;D.thisId&&(t=s.getThis(D.thisId))&&(a=t.config,e.target===a.elem[0]||e.target===a.eventElem[0]||e.target===n(a.closeStop)[0]||a.elem[0]&&a.elem[0].contains(e.target)||t.remove())}).on("keydown",function(e){var t;D.thisId&&(t=s.getThis(D.thisId))&&"static"!==t.config.position&&13===e.keyCode&&n("#"+t.elemID)[0]&&t.elemID===I.thisElemDate&&(e.preventDefault(),n(t.footer).find(C)[0].click())}),n(i).on("resize",function(){if(D.thisId){var e=s.getThis(D.thisId);if(e)return!(!e.elem||!n(".layui-laydate")[0])&&void e.position()}})},D.render=function(e){e=new I(e);return s.call(e)},D.reload=function(e,t){e=s.getThis(e);if(e)return e.reload(t)},D.getInst=function(e){e=s.getThis(e);if(e)return e.inst},D.hint=function(e,t){e=s.getThis(e);if(e)return e.hint(t)},D.unbind=function(e){e=s.getThis(e);if(e)return e.unbind()},D.close=function(e){e=s.getThis(e||D.thisId);if(e)return e.remove()},D.parse=function(a,n,i){return a=a||{},n=((n="string"==typeof n?s.formatArr(n):n)||[]).concat(),lay.each(n,function(e,t){/yyyy|y/.test(t)?n[e]=lay.digit(a.year,t.length):/MM|M/.test(t)?n[e]=lay.digit(a.month+(i||0),t.length):/dd|d/.test(t)?n[e]=lay.digit(a.date,t.length):/HH|H/.test(t)?n[e]=lay.digit(a.hours,t.length):/mm|m/.test(t)?n[e]=lay.digit(a.minutes,t.length):/ss|s/.test(t)&&(n[e]=lay.digit(a.seconds,t.length))}),n.join("")},D.getEndDate=function(e,t){var a=new Date;return a.setFullYear(t||a.getFullYear(),e||a.getMonth()+1,1),new Date(a.getTime()-864e5).getDate()},n?(D.ready(),layui.define("lay",function(e){D.path=layui.cache.dir,l.run(lay),e(a,D)})):"function"==typeof define&&define.amd?define(function(){return l.run(lay),D}):(D.ready(),l.run(i.lay),i.laydate=D)}(window,window.document);!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e):function(e){if(e.document)return t(e);throw new Error("jQuery requires a window with a document")}:t(e)}("undefined"!=typeof window?window:this,function(T,M){var f=[],g=T.document,c=f.slice,O=f.concat,R=f.push,P=f.indexOf,B={},W=B.toString,m=B.hasOwnProperty,y={},e="1.12.4",C=function(e,t){return new C.fn.init(e,t)},I=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,$=/^-ms-/,z=/-([\da-z])/gi,X=function(e,t){return t.toUpperCase()};function U(e){var t=!!e&&"length"in e&&e.length,n=C.type(e);return"function"!==n&&!C.isWindow(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+a+")"+a+"*"),ee=new RegExp("="+a+"*([^\\]'\"]*?)"+a+"*\\]","g"),te=new RegExp(G),ne=new RegExp("^"+s+"$"),f={ID:new RegExp("^#("+s+")"),CLASS:new RegExp("^\\.("+s+")"),TAG:new RegExp("^("+s+"|[*])"),ATTR:new RegExp("^"+J),PSEUDO:new RegExp("^"+G),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+a+"*(even|odd|(([+-]|)(\\d*)n|)"+a+"*(?:([+-]|)"+a+"*(\\d+)|))"+a+"*\\)|)","i"),bool:new RegExp("^(?:"+Y+")$","i"),needsContext:new RegExp("^"+a+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+a+"*((?:-\\d)?\\d*)"+a+"*\\)|)(?=[^-]|$)","i")},re=/^(?:input|select|textarea|button)$/i,ie=/^h\d$/i,c=/^[^{]+\{\s*\[native \w/,oe=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ae=/[+~]/,se=/'|\\/g,d=new RegExp("\\\\([\\da-f]{1,6}"+a+"?|("+a+")|.)","ig"),p=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(65536+r):String.fromCharCode(r>>10|55296,1023&r|56320)},ue=function(){C()};try{D.apply(n=V.call(v.childNodes),v.childNodes),n[v.childNodes.length].nodeType}catch(F){D={apply:n.length?function(e,t){U.apply(e,V.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function H(e,t,n,r){var i,o,a,s,u,l,c,f,d=t&&t.ownerDocument,p=t?t.nodeType:9;if(n=n||[],"string"!=typeof e||!e||1!==p&&9!==p&&11!==p)return n;if(!r&&((t?t.ownerDocument||t:v)!==E&&C(t),t=t||E,N)){if(11!==p&&(l=oe.exec(e)))if(i=l[1]){if(9===p){if(!(a=t.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(d&&(a=d.getElementById(i))&&y(t,a)&&a.id===i)return n.push(a),n}else{if(l[2])return D.apply(n,t.getElementsByTagName(e)),n;if((i=l[3])&&g.getElementsByClassName&&t.getElementsByClassName)return D.apply(n,t.getElementsByClassName(i)),n}if(g.qsa&&!A[e+" "]&&(!m||!m.test(e))){if(1!==p)d=t,f=e;else if("object"!==t.nodeName.toLowerCase()){for((s=t.getAttribute("id"))?s=s.replace(se,"\\$&"):t.setAttribute("id",s=k),o=(c=w(e)).length,u=ne.test(s)?"#"+s:"[id='"+s+"']";o--;)c[o]=u+" "+_(c[o]);f=c.join(","),d=ae.test(e)&&de(t.parentNode)||t}if(f)try{return D.apply(n,d.querySelectorAll(f)),n}catch(h){}finally{s===k&&t.removeAttribute("id")}}}return P(e.replace(L,"$1"),t,n,r)}function le(){var n=[];function r(e,t){return n.push(e+" ")>b.cacheLength&&delete r[n.shift()],r[e+" "]=t}return r}function q(e){return e[k]=!0,e}function h(e){var t=E.createElement("div");try{return!!e(t)}catch(F){return!1}finally{t.parentNode&&t.parentNode.removeChild(t)}}function ce(e,t){for(var n=e.split("|"),r=n.length;r--;)b.attrHandle[n[r]]=t}function fe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||1<<31)-(~e.sourceIndex||1<<31);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function x(a){return q(function(o){return o=+o,q(function(e,t){for(var n,r=a([],e.length,o),i=r.length;i--;)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function de(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in g=H.support={},O=H.isXML=function(e){e=e&&(e.ownerDocument||e).documentElement;return!!e&&"HTML"!==e.nodeName},C=H.setDocument=function(e){var e=e?e.ownerDocument||e:v;return e!==E&&9===e.nodeType&&e.documentElement&&(t=(E=e).documentElement,N=!O(E),(e=E.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",ue,!1):e.attachEvent&&e.attachEvent("onunload",ue)),g.attributes=h(function(e){return e.className="i",!e.getAttribute("className")}),g.getElementsByTagName=h(function(e){return e.appendChild(E.createComment("")),!e.getElementsByTagName("*").length}),g.getElementsByClassName=c.test(E.getElementsByClassName),g.getById=h(function(e){return t.appendChild(e).id=k,!E.getElementsByName||!E.getElementsByName(k).length}),g.getById?(b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&N)return(e=t.getElementById(e))?[e]:[]},b.filter.ID=function(e){var t=e.replace(d,p);return function(e){return e.getAttribute("id")===t}}):(delete b.find.ID,b.filter.ID=function(e){var t=e.replace(d,p);return function(e){e="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return e&&e.value===t}}),b.find.TAG=g.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):g.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"!==e)return o;for(;n=o[i++];)1===n.nodeType&&r.push(n);return r},b.find.CLASS=g.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&N)return t.getElementsByClassName(e)},r=[],m=[],(g.qsa=c.test(E.querySelectorAll))&&(h(function(e){t.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&m.push("[*^$]="+a+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||m.push("\\["+a+"*(?:value|"+Y+")"),e.querySelectorAll("[id~="+k+"-]").length||m.push("~="),e.querySelectorAll(":checked").length||m.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||m.push(".#.+[+~]")}),h(function(e){var t=E.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&m.push("name"+a+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||m.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),m.push(",.*:")})),(g.matchesSelector=c.test(i=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.msMatchesSelector))&&h(function(e){g.disconnectedMatch=i.call(e,"div"),i.call(e,"[s!='']:x"),r.push("!=",G)}),m=m.length&&new RegExp(m.join("|")),r=r.length&&new RegExp(r.join("|")),e=c.test(t.compareDocumentPosition),y=e||c.test(t.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},$=e?function(e,t){var n;return e===t?(l=!0,0):(n=!e.compareDocumentPosition-!t.compareDocumentPosition)||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!g.sortDetached&&t.compareDocumentPosition(e)===n?e===E||e.ownerDocument===v&&y(v,e)?-1:t===E||t.ownerDocument===v&&y(v,t)?1:u?j(u,e)-j(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===E?-1:t===E?1:i?-1:o?1:u?j(u,e)-j(u,t):0;if(i===o)return fe(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?fe(a[r],s[r]):a[r]===v?-1:s[r]===v?1:0}),E},H.matches=function(e,t){return H(e,null,null,t)},H.matchesSelector=function(e,t){if((e.ownerDocument||e)!==E&&C(e),t=t.replace(ee,"='$1']"),g.matchesSelector&&N&&!A[t+" "]&&(!r||!r.test(t))&&(!m||!m.test(t)))try{var n=i.call(e,t);if(n||g.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(F){}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(d,p),e[3]=(e[3]||e[4]||e[5]||"").replace(d,p),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||H.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&H.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return f.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&te.test(n)&&(t=(t=w(n,!0))&&n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(d,p).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=W[e+" "];return t||(t=new RegExp("(^|"+a+")"+e+"("+a+"|$)"))&&W(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(t,n,r){return function(e){e=H.attr(e,t);return null==e?"!="===n:!n||(e+="","="===n?e===r:"!="===n?e!==r:"^="===n?r&&0===e.indexOf(r):"*="===n?r&&-1(?:<\/\1>|)$/,G=/^.[^:#\[\.,]*$/;function K(e,n,r){if(C.isFunction(n))return C.grep(e,function(e,t){return!!n.call(e,t,e)!==r});if(n.nodeType)return C.grep(e,function(e){return e===n!==r});if("string"==typeof n){if(G.test(n))return C.filter(n,e,r);n=C.filter(n,e)}return C.grep(e,function(e){return-1)[^>]*|#([\w-]*))$/,ee=((C.fn.init=function(e,t,n){if(e){if(n=n||Q,"string"!=typeof e)return e.nodeType?(this.context=this[0]=e,this.length=1,this):C.isFunction(e)?"undefined"!=typeof n.ready?n.ready(e):e(C):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),C.makeArray(e,this));if(!(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&3<=e.length?[null,e,null]:Z.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof C?t[0]:t,C.merge(this,C.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:g,!0)),J.test(r[1])&&C.isPlainObject(t))for(var r in t)C.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r])}else{if((n=g.getElementById(r[2]))&&n.parentNode){if(n.id!==r[2])return Q.find(e);this.length=1,this[0]=n}this.context=g,this.selector=e}}return this}).prototype=C.fn,Q=C(g),/^(?:parents|prev(?:Until|All))/),te={children:!0,contents:!0,next:!0,prev:!0};function ne(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}C.fn.extend({has:function(e){var t,n=C(e,this),r=n.length;return this.filter(function(){for(t=0;t
                                                                                                  a",y.leadingWhitespace=3===S.firstChild.nodeType,y.tbody=!S.getElementsByTagName("tbody").length,y.htmlSerialize=!!S.getElementsByTagName("link").length,y.html5Clone="<:nav>"!==g.createElement("nav").cloneNode(!0).outerHTML,q.type="checkbox",q.checked=!0,k.appendChild(q),y.appendChecked=q.checked,S.innerHTML="",y.noCloneChecked=!!S.cloneNode(!0).lastChild.defaultValue,k.appendChild(S),(q=g.createElement("input")).setAttribute("type","radio"),q.setAttribute("checked","checked"),q.setAttribute("name","t"),S.appendChild(q),y.checkClone=S.cloneNode(!0).cloneNode(!0).lastChild.checked,y.noCloneEvent=!!S.addEventListener,S[C.expando]=1,y.attributes=!S.getAttribute(C.expando);var x={option:[1,""],legend:[1,"
                                                                                                  ","
                                                                                                  "],area:[1,"",""],param:[1,"",""],thead:[1,"","
                                                                                                  "],tr:[2,"","
                                                                                                  "],col:[2,"","
                                                                                                  "],td:[3,"","
                                                                                                  "],_default:y.htmlSerialize?[0,"",""]:[1,"X
                                                                                                  ","
                                                                                                  "]};function b(e,t){var n,r,i=0,o="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):undefined;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||C.nodeName(r,t)?o.push(r):C.merge(o,b(r,t));return t===undefined||t&&C.nodeName(e,t)?C.merge([e],o):o}function we(e,t){for(var n,r=0;null!=(n=e[r]);r++)C._data(n,"globalEval",!t||C._data(t[r],"globalEval"))}x.optgroup=x.option,x.tbody=x.tfoot=x.colgroup=x.caption=x.thead,x.th=x.td;var Te=/<|&#?\w+;/,Ce=/"!==f[1]||Ce.test(a)?0:u:u.firstChild)&&a.childNodes.length;o--;)C.nodeName(c=a.childNodes[o],"tbody")&&!c.childNodes.length&&a.removeChild(c);for(C.merge(h,u.childNodes),u.textContent="";u.firstChild;)u.removeChild(u.firstChild);u=p.lastChild}else h.push(t.createTextNode(a));for(u&&p.removeChild(u),y.appendChecked||C.grep(b(h,"input"),Ee),g=0;a=h[g++];)if(r&&-1]","i"),Pe=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,Be=/\s*$/g,ze=be(g).appendChild(g.createElement("div"));function Xe(e,t){return C.nodeName(e,"table")&&C.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ue(e){return e.type=(null!==C.find.attr(e,"type"))+"/"+e.type,e}function Ve(e){var t=Ie.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Ye(e,t){if(1===t.nodeType&&C.hasData(e)){var n,r,i,e=C._data(e),o=C._data(t,e),a=e.events;if(a)for(n in delete o.handle,o.events={},a)for(r=0,i=a[n].length;r")},clone:function(e,t,n){var r,i,o,a,s,u=C.contains(e.ownerDocument,e);if(y.html5Clone||C.isXMLDoc(e)||!Re.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(ze.innerHTML=e.outerHTML,ze.removeChild(o=ze.firstChild)),!(y.noCloneEvent&&y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||C.isXMLDoc(e)))for(r=b(o),s=b(e),a=0;null!=(i=s[a]);++a)if(r[a]){f=c=l=p=d=void 0;var l,c,f,d=i,p=r[a];if(1===p.nodeType){if(l=p.nodeName.toLowerCase(),!y.noCloneEvent&&p[C.expando]){for(c in(f=C._data(p)).events)C.removeEvent(p,c,f.handle);p.removeAttribute(C.expando)}"script"===l&&p.text!==d.text?(Ue(p).text=d.text,Ve(p)):"object"===l?(p.parentNode&&(p.outerHTML=d.outerHTML),y.html5Clone&&d.innerHTML&&!C.trim(p.innerHTML)&&(p.innerHTML=d.innerHTML)):"input"===l&&ge.test(d.type)?(p.defaultChecked=p.checked=d.checked,p.value!==d.value&&(p.value=d.value)):"option"===l?p.defaultSelected=p.selected=d.defaultSelected:"input"!==l&&"textarea"!==l||(p.defaultValue=d.defaultValue)}}if(t)if(n)for(s=s||b(e),r=r||b(o),a=0;null!=(i=s[a]);a++)Ye(i,r[a]);else Ye(e,o);return 0<(r=b(o,"script")).length&&we(r,!u&&b(e,"script")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=C.expando,u=C.cache,l=y.attributes,c=C.event.special;null!=(n=e[a]);a++)if((t||v(n))&&(o=(i=n[s])&&u[i])){if(o.events)for(r in o.events)c[r]?C.event.remove(n,r):C.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||"undefined"==typeof n.removeAttribute?n[s]=undefined:n.removeAttribute(s),f.push(i))}}}),C.fn.extend({domManip:w,detach:function(e){return Je(this,e,!0)},remove:function(e){return Je(this,e)},text:function(e){return d(this,function(e){return e===undefined?C.text(this):this.empty().append((this[0]&&this[0].ownerDocument||g).createTextNode(e))},null,e,arguments.length)},append:function(){return w(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Xe(this,e).appendChild(e)})},prepend:function(){return w(this,arguments,function(e){var t;1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(t=Xe(this,e)).insertBefore(e,t.firstChild)})},before:function(){return w(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return w(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&C.cleanData(b(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&C.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return C.clone(this,e,t)})},html:function(e){return d(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined)return 1===t.nodeType?t.innerHTML.replace(Oe,""):undefined;if("string"==typeof e&&!Be.test(e)&&(y.htmlSerialize||!Re.test(e))&&(y.leadingWhitespace||!ve.test(e))&&!x[(me.exec(e)||["",""])[1].toLowerCase()]){e=C.htmlPrefilter(e);try{for(;n")).appendTo(t.documentElement))[0].contentWindow||Ge[0].contentDocument).document).write(),t.close(),n=Qe(e,t),Ge.detach()),Ke[e]=n),n}var n,et,tt,nt,rt,it,ot,a,at=/^margin/,st=new RegExp("^("+e+")(?!px)[a-z%]+$","i"),ut=function(e,t,n,r){var i,o={};for(i in t)o[i]=e.style[i],e.style[i]=t[i];for(i in r=n.apply(e,r||[]),t)e.style[i]=o[i];return r},lt=g.documentElement;function t(){var e,t=g.documentElement;t.appendChild(ot),a.style.cssText="-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",n=tt=it=!1,et=rt=!0,T.getComputedStyle&&(e=T.getComputedStyle(a),n="1%"!==(e||{}).top,it="2px"===(e||{}).marginLeft,tt="4px"===(e||{width:"4px"}).width,a.style.marginRight="50%",et="4px"===(e||{marginRight:"4px"}).marginRight,(e=a.appendChild(g.createElement("div"))).style.cssText=a.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",e.style.marginRight=e.style.width="0",a.style.width="1px",rt=!parseFloat((T.getComputedStyle(e)||{}).marginRight),a.removeChild(e)),a.style.display="none",(nt=0===a.getClientRects().length)&&(a.style.display="",a.innerHTML="
                                                                                                  t
                                                                                                  ",a.childNodes[0].style.borderCollapse="separate",(e=a.getElementsByTagName("td"))[0].style.cssText="margin:0;border:0;padding:0;display:none",nt=0===e[0].offsetHeight)&&(e[0].style.display="",e[1].style.display="none",nt=0===e[0].offsetHeight),t.removeChild(ot)}ot=g.createElement("div"),(a=g.createElement("div")).style&&(a.style.cssText="float:left;opacity:.5",y.opacity="0.5"===a.style.opacity,y.cssFloat=!!a.style.cssFloat,a.style.backgroundClip="content-box",a.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===a.style.backgroundClip,(ot=g.createElement("div")).style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",a.innerHTML="",ot.appendChild(a),y.boxSizing=""===a.style.boxSizing||""===a.style.MozBoxSizing||""===a.style.WebkitBoxSizing,C.extend(y,{reliableHiddenOffsets:function(){return null==n&&t(),nt},boxSizingReliable:function(){return null==n&&t(),tt},pixelMarginRight:function(){return null==n&&t(),et},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),rt},reliableMarginLeft:function(){return null==n&&t(),it}}));var l,p,ct=/^(top|right|bottom|left)$/;function ft(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}T.getComputedStyle?(l=function(e){var t=e.ownerDocument.defaultView;return(t=t&&t.opener?t:T).getComputedStyle(e)},p=function(e,t,n){var r,i,o=e.style;return""!==(i=(n=n||l(e))?n.getPropertyValue(t)||n[t]:undefined)&&i!==undefined||C.contains(e.ownerDocument,e)||(i=C.style(e,t)),n&&!y.pixelMarginRight()&&st.test(i)&&at.test(t)&&(e=o.width,t=o.minWidth,r=o.maxWidth,o.minWidth=o.maxWidth=o.width=i,i=n.width,o.width=e,o.minWidth=t,o.maxWidth=r),i===undefined?i:i+""}):lt.currentStyle&&(l=function(e){return e.currentStyle},p=function(e,t,n){var r,i,o,a=e.style;return null==(n=(n=n||l(e))?n[t]:undefined)&&a&&a[t]&&(n=a[t]),st.test(n)&&!ct.test(t)&&(r=a.left,(o=(i=e.runtimeStyle)&&i.left)&&(i.left=e.currentStyle.left),a.left="fontSize"===t?"1em":n,n=a.pixelLeft+"px",a.left=r,o)&&(i.left=o),n===undefined?n:n+""||"auto"});var dt=/alpha\([^)]*\)/i,pt=/opacity\s*=\s*([^)]*)/i,ht=/^(none|table(?!-c[ea]).+)/,gt=new RegExp("^("+e+")(.*)$","i"),mt={position:"absolute",visibility:"hidden",display:"block"},yt={letterSpacing:"0",fontWeight:"400"},vt=["Webkit","O","Moz","ms"],xt=g.createElement("div").style;function bt(e){if(e in xt)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=vt.length;n--;)if((e=vt[n]+t)in xt)return e}function wt(e,t){for(var n,r,i,o=[],a=0,s=e.length;a
                                                                                                  a",F=q.getElementsByTagName("a")[0],k.setAttribute("type","checkbox"),q.appendChild(k),(F=q.getElementsByTagName("a")[0]).style.cssText="top:1px",y.getSetAttribute="t"!==q.className,y.style=/top/.test(F.getAttribute("style")),y.hrefNormalized="/a"===F.getAttribute("href"),y.checkOn=!!k.value,y.optSelected=e.selected,y.enctype=!!g.createElement("form").enctype,S.disabled=!0,y.optDisabled=!e.disabled,(k=g.createElement("input")).setAttribute("value",""),y.input=""===k.getAttribute("value"),k.value="t",k.setAttribute("type","radio"),y.radioValue="t"===k.value;var Lt=/\r/g,Ht=/[\x20\t\r\n\f]+/g;C.fn.extend({val:function(t){var n,e,r,i=this[0];return arguments.length?(r=C.isFunction(t),this.each(function(e){1!==this.nodeType||(null==(e=r?t.call(this,e,C(this).val()):t)?e="":"number"==typeof e?e+="":C.isArray(e)&&(e=C.map(e,function(e){return null==e?"":e+""})),(n=C.valHooks[this.type]||C.valHooks[this.nodeName.toLowerCase()])&&"set"in n&&n.set(this,e,"value")!==undefined)||(this.value=e)})):i?(n=C.valHooks[i.type]||C.valHooks[i.nodeName.toLowerCase()])&&"get"in n&&(e=n.get(i,"value"))!==undefined?e:"string"==typeof(e=i.value)?e.replace(Lt,""):null==e?"":e:void 0}}),C.extend({valHooks:{option:{get:function(e){var t=C.find.attr(e,"value");return null!=t?t:C.trim(C.text(e)).replace(Ht," ")}},select:{get:function(e){for(var t,n=e.options,r=e.selectedIndex,i="select-one"===e.type||r<0,o=i?null:[],a=i?r+1:n.length,s=r<0?a:i?r:0;s").append(C.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this)},C.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){C.fn[t]=function(e){return this.on(t,e)}}),C.expr.filters.animated=function(t){return C.grep(C.timers,function(e){return t===e.elem}).length},C.offset={setOffset:function(e,t,n){var r,i,o,a,s=C.css(e,"position"),u=C(e),l={};"static"===s&&(e.style.position="relative"),o=u.offset(),r=C.css(e,"top"),a=C.css(e,"left"),s=("absolute"===s||"fixed"===s)&&-1'+(s?a.title[0]:a.title)+"
                                                                                                  ":"";return a.zIndex=o,t([a.shade?'
                                                                                                  ':"",'
                                                                                                  '+(e&&2!=a.type?"":s)+"'+(n=["layui-icon-tips","layui-icon-success","layui-icon-error","layui-icon-question","layui-icon-lock","layui-icon-face-cry","layui-icon-face-smile"],o="layui-anim layui-anim-rotate layui-anim-loop",0==a.type&&-1!==a.icon?'':3==a.type?(i=["layui-icon-loading","layui-icon-loading-1"],2==a.icon?'
                                                                                                  ':''):"")+((1!=a.type||!e)&&a.content||"")+'
                                                                                                  '+(n=[],l&&(n.push(''),n.push('')),a.closeBtn&&n.push(''),n.join(""))+"
                                                                                                  "+(a.btn?function(){var e="";"string"==typeof a.btn&&(a.btn=[a.btn]);for(var t,i=0,n=a.btn.length;i'+a.btn[i]+"";return'
                                                                                                  '+e+"
                                                                                                  "}():"")+(a.resize?'':"")+"
                                                                                                  "],s,m('
                                                                                                  ')),this},t.pt.creat=function(){var e,t,i,n,a,o=this,s=o.config,l=o.index,r="object"==typeof(f=s.content),c=m("body");if(s.id&&m("."+u[0]).find("#"+s.id)[0])e=m("#"+s.id).closest("."+u[0]),t=e.attr("times"),i=e.data("config"),n=m("#"+u.SHADE+t),"min"===(e.data("maxminStatus")||{})?g.restore(t):i.hideOnClose&&(n.show(),e.show());else{switch(s.removeFocus&&document.activeElement.blur(),"string"==typeof s.area&&(s.area="auto"===s.area?["",""]:[s.area,""]),s.shift&&(s.anim=s.shift),6==g.ie&&(s.fixed=!1),s.type){case 0:s.btn="btn"in s?s.btn:d.btn[0],g.closeAll("dialog");break;case 2:var f=s.content=r?s.content:[s.content||"","auto"];s.content='';break;case 3:delete s.title,delete s.closeBtn,-1===s.icon&&s.icon,g.closeAll("loading");break;case 4:r||(s.content=[s.content,"body"]),s.follow=s.content[1],s.content=s.content[0]+'',delete s.title,s.tips="object"==typeof s.tips?s.tips:[s.tips,!0],s.tipsMore||g.closeAll("tips")}o.vessel(r,function(e,t,i){c.append(e[0]),r?2==s.type||4==s.type?m("body").append(e[1]):f.parents("."+u[0])[0]||(f.data("display",f.css("display")).show().addClass("layui-layer-wrap").wrap(e[1]),m("#"+u[0]+l).find("."+u[5]).before(t)):c.append(e[1]),m("#"+u.MOVE)[0]||c.append(d.moveElem=i),o.layero=m("#"+u[0]+l),o.shadeo=m("#"+u.SHADE+l),s.scrollbar||d.setScrollbar(l)}).auto(l),o.shadeo.css({"background-color":s.shade[1]||"#000",opacity:s.shade[0]||s.shade}),2==s.type&&6==g.ie&&o.layero.find("iframe").attr("src",f[0]),4==s.type?o.tips():(o.offset(),parseInt(d.getStyle(document.getElementById(u.MOVE),"z-index"))||(o.layero.css("visibility","hidden"),g.ready(function(){o.offset(),o.layero.css("visibility","visible")}))),!s.fixed||d.events.resize[o.index]||(d.events.resize[o.index]=function(){o.resize()},h.on("resize",d.events.resize[o.index])),s.time<=0||setTimeout(function(){g.close(o.index)},s.time),o.move().callback(),u.anim[s.anim]&&(a="layer-anim "+u.anim[s.anim],o.layero.addClass(a).one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){m(this).removeClass(a)})),o.layero.data("config",s)}},t.pt.resize=function(){var e=this,t=e.config;e.offset(),(/^\d+%$/.test(t.area[0])||/^\d+%$/.test(t.area[1]))&&e.auto(e.index),4==t.type&&e.tips()},t.pt.auto=function(e){var t=this.config,i=m("#"+u[0]+e),n=(""===t.area[0]&&0t.maxWidth)&&i.width(t.maxWidth),[i.innerWidth(),i.innerHeight()]),a=i.find(u[1]).outerHeight()||0,o=i.find("."+u[6]).outerHeight()||0,e=function(e){(e=i.find(e)).height(n[1]-a-o-2*(0|parseFloat(e.css("padding-top"))))};return 2===t.type?e("iframe"):""===t.area[1]?0t.maxHeight?(n[1]=t.maxHeight,e("."+u[5])):t.fixed&&n[1]>=h.height()&&(n[1]=h.height(),e("."+u[5])):e("."+u[5]),this},t.pt.offset=function(){var e=this,t=e.config,i=e.layero,n=[i.outerWidth(),i.outerHeight()],a="object"==typeof t.offset;e.offsetTop=(h.height()-n[1])/2,e.offsetLeft=(h.width()-n[0])/2,a?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):"auto"!==t.offset&&("t"===t.offset?e.offsetTop=0:"r"===t.offset?e.offsetLeft=h.width()-n[0]:"b"===t.offset?e.offsetTop=h.height()-n[1]:"l"===t.offset?e.offsetLeft=0:"lt"===t.offset?(e.offsetTop=0,e.offsetLeft=0):"lb"===t.offset?(e.offsetTop=h.height()-n[1],e.offsetLeft=0):"rt"===t.offset?(e.offsetTop=0,e.offsetLeft=h.width()-n[0]):"rb"===t.offset?(e.offsetTop=h.height()-n[1],e.offsetLeft=h.width()-n[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?h.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?h.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=h.scrollTop(),e.offsetLeft+=h.scrollLeft()),"min"===i.data("maxminStatus")&&(e.offsetTop=h.height()-(i.find(u[1]).outerHeight()||0),e.offsetLeft=i.css("left")),i.css({top:e.offsetTop,left:e.offsetLeft})},t.pt.tips=function(){var e=this.config,t=this.layero,i=[t.outerWidth(),t.outerHeight()],n=m(e.follow),a={width:(n=n[0]?n:m("body")).outerWidth(),height:n.outerHeight(),top:n.offset().top,left:n.offset().left},o=t.find(".layui-layer-TipsG"),n=e.tips[0];e.tips[1]||o.remove(),a.autoLeft=function(){0h.width()&&(o=h.width()-180-(d.minStackArr.edgeIndex=d.minStackArr.edgeIndex||0,d.minStackArr.edgeIndex+=3))<0&&(o=0),t.minStack&&(l.left=o,l.top=h.height()-n,a||d.minStackIndex++,r.attr("minLeft",o)),r.attr("position",s),g.style(e,l,!0),i.hide(),"page"===r.attr("type")&&r.find(u[4]).hide(),d.restScrollbar(e),c.hide())},g.restore=function(e){var t=m("#"+u[0]+e),i=m("#"+u.SHADE+e),n=t.attr("area").split(","),a=t.attr("type"),o=t.data("config")||{};t.removeData("maxminStatus"),g.style(e,{width:n[0],height:n[1],top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr("position"),overflow:"visible"},!0),t.find(".layui-layer-max").removeClass("layui-layer-maxmin"),t.find(".layui-layer-min").show(),"page"===a&&t.find(u[4]).show(),o.scrollbar?d.restScrollbar(e):d.setScrollbar(e),i.show()},g.full=function(t){var i=m("#"+u[0]+t),e=i.data("maxminStatus");"max"!==e&&("min"===e&&g.restore(t),i.data("maxminStatus","max"),d.record(i),u.html.attr("layer-full")||d.setScrollbar(t),setTimeout(function(){var e="fixed"===i.css("position");g.style(t,{top:e?0:h.scrollTop(),left:e?0:h.scrollLeft(),width:"100%",height:"100%"},!0),i.find(".layui-layer-min").hide()},100))},g.title=function(e,t){m("#"+u[0]+(t||g.index)).find(u[1]).html(e)},g.close=function(o,s){var l,e,r=(t=m("."+u[0]).children("#"+o).closest("."+u[0]))[0]?(o=t.attr("times"),t):m("#"+u[0]+o),c=r.attr("type"),t=r.data("config")||{},f=t.id&&t.hideOnClose;r[0]&&(l={slideDown:"layer-anim-slide-down-out",slideLeft:"layer-anim-slide-left-out",slideUp:"layer-anim-slide-up-out",slideRight:"layer-anim-slide-right-out"}[t.anim]||"layer-anim-close",e=function(){var e="layui-layer-wrap";if(f)return r.removeClass("layer-anim "+l),r.hide();if(c===d.type[1]&&"object"===r.attr("conType")){r.children(":not(."+u[5]+")").remove();for(var t=r.find("."+e),i=0;i<2;i++)t.unwrap();t.css("display",t.data("display")).removeClass(e)}else{if(c===d.type[2])try{var n=m("#"+u[4]+o)[0];n.contentWindow.document.write(""),n.contentWindow.close(),r.find("."+u[5])[0].removeChild(n)}catch(a){}r[0].innerHTML="",r.remove()}"function"==typeof d.end[o]&&d.end[o](),delete d.end[o],"function"==typeof s&&s(),d.events.resize[o]&&(h.off("resize",d.events.resize[o]),delete d.events.resize[o])},m("#"+u.SHADE+o)[f?"hide":"remove"](),t.isOutAnim&&r.addClass("layer-anim "+l),6==g.ie&&d.reselect(),d.restScrollbar(o),"string"==typeof r.attr("minLeft")&&(d.minStackIndex--,d.minStackArr.push(r.attr("minLeft"))),g.ie&&g.ie<10||!t.isOutAnim?e():setTimeout(function(){e()},200))},g.closeAll=function(n,a){"function"==typeof n&&(a=n,n=null);var o=m("."+u[0]);m.each(o,function(e){var t=m(this),i=n?t.attr("type")===n:1;i&&g.close(t.attr("times"),e===o.length-1?a:null)}),0===o.length&&"function"==typeof a&&a()},g.closeLast=function(e,t){g.close(m(".layui-layer-"+(e=e||"page")+":last").attr("times"),t)},g.cache||{}),v=function(e){return i.skin?" "+i.skin+" "+i.skin+"-"+e:""};g.prompt=function(i,n){var e="",t="";"function"==typeof(i=i||{})&&(n=i),i.area&&(e='style="width: '+(o=i.area)[0]+"; height: "+o[1]+';"',delete i.area),i.placeholder&&(t=' placeholder="'+i.placeholder+'"');var a,o=2==i.formType?'":'",s=i.success;return delete i.success,g.open(m.extend({type:1,btn:["确定","取消"],content:o,skin:"layui-layer-prompt"+v("prompt"),maxWidth:h.width(),success:function(e){(a=e.find(".layui-layer-input")).val(i.value||"").focus(),"function"==typeof s&&s(e)},resize:!1,yes:function(e){var t=a.val();t.length>(i.maxlength||500)?g.tips("最多输入"+(i.maxlength||500)+"个字数",a,{tips:1}):n&&n(t,e,a)}},i))},g.tab=function(n){var a=(n=n||{}).tab||{},o="layui-this",s=n.success;return delete n.success,g.open(m.extend({type:1,skin:"layui-layer-tab"+v("tab"),resize:!1,title:function(){var e=a.length,t=1,i="";if(0'+a[0].title+"";t"+a[t].title+"";return i}(),content:'
                                                                                                    '+function(){var e=a.length,t=1,i="";if(0'+(a[0].content||"no content")+"";t'+(a[t].content||"no content")+"";return i}()+"
                                                                                                  ",success:function(e){var t=e.find(".layui-layer-title").children(),i=e.find(".layui-layer-tabmain").children();t.on("mousedown",function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0;var e=m(this),t=e.index();e.addClass(o).siblings().removeClass(o),i.eq(t).show().siblings().hide(),"function"==typeof n.change&&n.change(t)}),"function"==typeof s&&s(e)}},n))},g.photos=function(n,e,a){var s={};if((n=m.extend(!0,{toolbar:!0,footer:!0},n)).photos){var t=!("string"==typeof n.photos||n.photos instanceof m),i=t?n.photos:{},o=i.data||[],l=i.start||0,r=n.success;if(s.imgIndex=1+(0|l),n.img=n.img||"img",delete n.success,t){if(0===o.length)return g.msg("没有图片")}else{var c=m(n.photos),f=function(){o=[],c.find(n.img).each(function(e){var t=m(this);t.attr("layer-index",e),o.push({alt:t.attr("alt"),pid:t.attr("layer-pid"),src:t.attr("lay-src")||t.attr("layer-src")||t.attr("src"),thumb:t.attr("src")})})};if(f(),0===o.length)return;if(e||c.on("click",n.img,function(){f();var e=m(this).attr("layer-index");g.photos(m.extend(n,{photos:{start:e,data:o,tab:n.tab},full:n.full}),!0)}),!e)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=o.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>o.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){var t;s.end||(t=e.keyCode,e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&g.close(s.index))},s.tabimg=function(e){if(!(o.length<=1))return i.start=s.imgIndex-1,g.close(s.index),g.photos(n,!0,e)},s.isNumber=function(e){return"number"==typeof e&&!isNaN(e)},s.image={},s.getTransform=function(e){var t=[],i=e.rotate,n=e.scaleX,e=e.scale;return s.isNumber(i)&&0!==i&&t.push("rotate("+i+"deg)"),s.isNumber(n)&&1!==n&&t.push("scaleX("+n+")"),s.isNumber(e)&&t.push("scale("+e+")"),t.length?t.join(" "):"none"},s.event=function(e,i,n){var a,o;s.main.find(".layui-layer-photos-prev").on("click",function(e){e.preventDefault(),s.imgprev(!0)}),s.main.find(".layui-layer-photos-next").on("click",function(e){e.preventDefault(),s.imgnext(!0)}),m(document).on("keyup",s.keyup),e.off("click").on("click","*[toolbar-event]",function(){var e=m(this);switch(e.attr("toolbar-event")){case"rotate":s.image.rotate=((s.image.rotate||0)+Number(e.attr("data-option")))%360,s.imgElem.css({transform:s.getTransform(s.image)});break;case"scalex":s.image.scaleX=-1===s.image.scaleX?1:-1,s.imgElem.css({transform:s.getTransform(s.image)});break;case"zoom":var t=Number(e.attr("data-option"));s.image.scale=(s.image.scale||1)+t,t<0&&s.image.scale<0-t&&(s.image.scale=0-t),s.imgElem.css({transform:s.getTransform(s.image)});break;case"reset":s.image.scaleX=1,s.image.scale=1,s.image.rotate=0,s.imgElem.css({transform:"none"});break;case"close":g.close(i)}n.offset(),n.auto(i)}),s.main.on("mousewheel DOMMouseScroll",function(e){var t=e.originalEvent.wheelDelta||-e.originalEvent.detail,i=s.main.find('[toolbar-event="zoom"]');(0n)&&("left"===t.direction?s.imgnext(!0):"right"===t.direction&&s.imgprev(!0))},m.each([n.shadeo,s.main],function(e,t){a.touchSwipe(t,{onTouchEnd:o})}))},s.loadi=g.load(1,{shade:!("shade"in n)&&.9,scrollbar:!1});var t=o[l].src,d=function(e){g.close(s.loadi);var t,i=o[l].alt||"";a&&(n.anim=-1),s.index=g.open(m.extend({type:1,id:"layui-layer-photos",area:(e=[e.width,e.height],t=[m(p).width()-100,m(p).height()-100],!n.full&&(t[0]'+i+''+(t=['
                                                                                                  '],1','','',"
                                                                                                  "].join("")),n.toolbar&&t.push(['
                                                                                                  ','','','','','','',"
                                                                                                  "].join("")),n.footer&&t.push(['"].join("")),t.push("
                                                                                                  "),t.join(""))+"",success:function(e,t,i){s.main=e.find(".layer-layer-photos-main"),s.footer=e.find(".layui-layer-photos-footer"),s.imgElem=s.main.children("img"),s.event(e,t,i),n.tab&&n.tab(o[l],e),"function"==typeof r&&r(e)},end:function(){s.end=!0,m(document).off("keyup",s.keyup)}},n))},u=function(){g.close(s.loadi),g.msg("当前图片地址异常
                                                                                                  是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){1").addClass(r));layui.each(i.bars,function(t,e){var n=s('
                                                                                                • ');n.addClass(e.icon).attr({"lay-type":e.type,style:e.style||(i.bgcolor?"background-color: "+i.bgcolor:"")}).html(e.content),n.on("click",function(){var t=s(this).attr("lay-type");"top"===t&&("body"===i.target?s("html,body"):u).animate({scrollTop:0},i.duration),"function"==typeof i.click&&i.click.call(this,t)}),"object"===layui.type(i.on)&&layui.each(i.on,function(t,e){n.on(t,function(){var t=s(this).attr("lay-type");"function"==typeof e&&e.call(this,t)})}),"top"===e.type&&(n.addClass("layui-fixbar-top"),o=n),l.append(n)}),c.find("."+r).remove(),"object"==typeof i.css&&l.css(i.css),c.append(l),o&&(e=function e(){return u.scrollTop()>=i.margin?t||(o.show(),t=1):t&&(o.hide(),t=0),e}()),u.on("scroll",function(){e&&(clearTimeout(n),n=setTimeout(function(){e()},100))})},countdown:function(i){i=s.extend(!0,{date:new Date,now:new Date},i);var o=arguments,r=(1]|&(?=#[a-zA-Z0-9]+)/g.test(t+="")?t.replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,"""):t},unescape:function(t){return t!==undefined&&null!==t||(t=""),(t+="").replace(/\&/g,"&").replace(/\</g,"<").replace(/\>/g,">").replace(/\'/g,"'").replace(/\"/g,'"')},openWin:function(t){var e=(t=t||{}).window||window.open(t.url||"",t.target,t.specs);t.url||(e.document.open("text/html","replace"),e.document.write(t.content||""),e.document.close())},toVisibleArea:function(t){var e,n,i,o,r,a,c,u;(t=s.extend({margin:160,duration:200,type:"y"},t)).scrollElem[0]&&t.thisElem[0]&&(e=t.scrollElem,c=t.thisElem,i=(r="y"===t.type)?"top":"left",o=e[n=r?"scrollTop":"scrollLeft"](),r=e[r?"height":"width"](),a=e.offset()[i],u={},(c=c.offset()[i]-a)>r-t.margin||c."+v,E=function(e){var i=this;i.index=++h.index,i.config=c.extend({},i.config,h.config,e),i.init()};E.prototype.config={trigger:"click",content:"",className:"",style:"",show:!1,isAllowSpread:!0,isSpreadItem:!0,data:[],delay:[200,300],shade:0,accordion:!1},E.prototype.reload=function(e,i){var t=this;t.config=c.extend({},t.config,e),t.init(!0,i)},E.prototype.init=function(e,i){var t,n=this,a=n.config,l=c(a.elem);return 1');return 0No data
                                                                                                • '),e},u=function(r,e){return layui.each(e,function(e,i){var t,n=i[s.children]&&0",(t="href"in i?''+l+"":l,n?'
                                                                                                  '+t+("parent"===o?'':"group"===o&&d.isAllowSpread?'':"")+"
                                                                                                  ":'
                                                                                                  '+t+"
                                                                                                  "),""].join(""))).data("item",i),n&&(a=c('
                                                                                                  '),t=c("
                                                                                                    "),"parent"===o?(a.append(u(t,i[s.children])),l.append(a)):l.append(u(t,i[s.children]))),r.append(l))}),r},a=['
                                                                                                    ',"
                                                                                                    "].join("");!(e="contextmenu"!==d.trigger&&!lay.isTopElem(d.elem[0])?e:!0)&&d.elem.data(y+"_opened")||(l.elemView=c("."+g+'[lay-id="'+d.id+'"]'),"reloadData"===i&&l.elemView.length?l.elemView.html(d.content||n()):(l.elemView=c(a),l.elemView.append(d.content||n()),d.className&&l.elemView.addClass(d.className),d.style&&l.elemView.attr("style",d.style),h.thisId=d.id,l.remove(),t.append(l.elemView),d.elem.data(y+"_opened",!0),e=d.shade?'
                                                                                                    ':"",l.elemView.before(e),"mouseenter"===d.trigger&&l.elemView.on("mouseenter",function(){clearTimeout(f.timer)}).on("mouseleave",function(){l.delayRemove()})),l.position(),(f.prevElem=l.elemView).data("prevElem",d.elem),l.elemView.find(".layui-menu").on(o,function(e){layui.stope(e)}),l.elemView.find(".layui-menu li").on("click",function(e){var i=c(this),t=i.data("item")||{},n=t[s.children]&&0n.width()&&(t.addClass(x),(i=t[0].getBoundingClientRect()).left<0)&&t.removeClass(x),i.bottom>n.height())&&t.eq(0).css("margin-top",-(i.bottom-n.height()+5))}).on("mouseleave",t,function(e){var i=c(this).children("."+C);i.removeClass(x),i.css("margin-top",0)}),h.close=function(e){e=f.getThis(e);return e?(e.remove(),f.call(e)):this},h.reload=function(e,i,t){e=f.getThis(e);return e?(e.reload(i,t),f.call(e)):this},h.reloadData=function(){var t=c.extend([],arguments),n=(t[2]="reloadData",new RegExp("^("+["data","templet","content"].join("|")+")$"));return layui.each(t[1],function(e,i){n.test(e)||delete t[1][e]}),h.reload.apply(null,t)},h.render=function(e){e=new E(e);return f.call(e)},e(r,h)});layui.define(["jquery","lay"],function(e){"use strict";var g=layui.$,x=layui.lay,c={config:{},index:layui.slider?layui.slider.index+1e4:0,set:function(e){var t=this;return t.config=g.extend({},t.config,e),t},on:function(e,t){return layui.onevent.call(this,i,e,t)}},i="slider",v="layui-disabled",b="layui-slider-bar",T="layui-slider-wrap",w="layui-slider-wrap-btn",M="layui-slider-tips",L="layui-slider-input-txt",E="layui-slider-hover",t=function(e){var t=this;t.index=++c.index,t.config=g.extend({},t.config,c.config,e),t.render()};t.prototype.config={type:"default",min:0,max:100,value:0,step:1,showstep:!1,tips:!0,input:!1,range:!1,height:200,disabled:!1,theme:"#16baaa"},t.prototype.render=function(){var n=this,a=n.config,e=g(a.elem);if(1a.max&&(a.value=a.max),i=Math.floor((a.value-a.min)/(a.max-a.min)*100)+"%");var l,e=a.disabled?"#c2c2c2":a.theme,t='
                                                                                                    '+(a.tips?'
                                                                                                    ':"")+'
                                                                                                    '+(a.range?'
                                                                                                    ':"")+"
                                                                                                    ",i=g(a.elem),s=i.next(".layui-slider");if(s[0]&&s.remove(),n.elemTemp=g(t),a.range?(n.elemTemp.find("."+T).eq(0).data("value",a.value[0]),n.elemTemp.find("."+T).eq(1).data("value",a.value[1])):n.elemTemp.find("."+T).data("value",a.value),i.html(n.elemTemp),"vertical"===a.type&&n.elemTemp.height(a.height+"px"),a.showstep){for(var o=(a.max-a.min)/a.step,r="",u=1;u<1+o;u++){var d=100*u/o;d<100&&(r+='
                                                                                                    ')}n.elemTemp.append(r)}a.input&&!a.range&&(e=g('
                                                                                                    '),i.css("position","relative"),i.append(e),i.find("."+L).children("input").val(a.value),"vertical"===a.type?e.css({left:0,top:-48}):n.elemTemp.css("margin-right",e.outerWidth()+15)),a.disabled?(n.elemTemp.addClass(v),n.elemTemp.find("."+w).addClass(v)):n.slide(),n.elemTemp.find("."+w).on("mouseover",function(){var e="vertical"===a.type?a.height:n.elemTemp[0].offsetWidth,t=n.elemTemp.find("."+T),i=("vertical"===a.type?e-g(this).parent()[0].offsetTop-t.height():g(this).parent()[0].offsetLeft)/e*100,t=g(this).parent().data("value"),e=a.setTips?a.setTips(t):t;n.elemTemp.find("."+M).html(e),clearTimeout(l),l=setTimeout(function(){"vertical"===a.type?n.elemTemp.find("."+M).css({bottom:i+"%","margin-bottom":"20px",display:"inline-block"}):n.elemTemp.find("."+M).css({left:i+"%",display:"inline-block"})},300)}).on("mouseout",function(){clearTimeout(l),n.elemTemp.find("."+M).css("display","none")})},t.prototype.slide=function(e,t,i){var u=this,d=u.config,c=u.elemTemp,v=function(){return"vertical"===d.type?d.height:c[0].offsetWidth},m=c.find("."+T),o=c.next(".layui-slider-input"),r=o.children("."+L).children("input").val(),p=100/((d.max-d.min)/Math.ceil(d.step)),f=function(e,t,i){e=(e=100<(e=100n[1]&&n.reverse(),u.value=d.range?n:l,d.change&&d.change(u.value),"done"===i&&d.done&&d.done(u.value)},h=function(e){var t=e/v()*100/p,i=Math.round(t)*p;return i=e==v()?Math.ceil(t)*p:i},y=g(['
                                                                                                    v()?v():t)/v()*100/p;f(t,o),r.addClass(E),c.find("."+M).show(),e.preventDefault()},n=function(e){r.removeClass(E),setTimeout(function(){c.find("."+M).hide()},e)},a=function(){n&&n(x.touchEventsSupported()?1e3:0),y.remove(),d.done&&d.done(u.value),x.touchEventsSupported()&&(t[0].removeEventListener("touchmove",i,!!x.passiveSupported&&{passive:!1}),t[0].removeEventListener("touchend",a),t[0].removeEventListener("touchcancel",a))},g("#LAY-slider-moving")[0]||g("body").append(y),y.on("mousemove",i),y.on("mouseup",a).on("mouseleave",a),x.touchEventsSupported()&&(t[0].addEventListener("touchmove",i,!!x.passiveSupported&&{passive:!1}),t[0].addEventListener("touchend",a),t[0].addEventListener("touchcancel",a))})}),c.on("click",function(e){var t=g("."+w),i=g(this);!t.is(event.target)&&0===t.has(event.target).length&&t.length&&(i=(t=(t=(t="vertical"===d.type?v()-e.clientY+i.offset().top-g(window).scrollTop():e.clientX-i.offset().left-g(window).scrollLeft())<0?0:t)>v()?v():t)/v()*100/p,t=d.range?"vertical"===d.type?Math.abs(t-parseInt(g(m[0]).css("bottom")))>Math.abs(t-parseInt(g(m[1]).css("bottom")))?1:0:Math.abs(t-m[0].offsetLeft)>Math.abs(t-m[1].offsetLeft)?1:0:0,f(i,t,"done"),e.preventDefault())}),o.children(".layui-slider-input-btn").children("i").each(function(t){g(this).on("click",function(){r=o.children("."+L).children("input").val();var e=((r=1==t?r-d.stepd.max?d.max:Number(r)+d.step)-d.min)/(d.max-d.min)*100/p;f(e,0,"done")})});var n=function(){var e=this.value,e=(e=(e=(e=isNaN(e)?0:e)d.max?d.max:e,((this.value=e)-d.min)/(d.max-d.min)*100/p);f(e,0,"done")};o.children("."+L).children("input").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),n.call(this))}).on("change",n)},t.prototype.events=function(){this.config},c.render=function(e){e=new t(e);return function(){var i=this,n=i.config;return{setValue:function(e,t){return e=(e=e>n.max?n.max:e)',"",'','',"","","
                                                                                                    "].join("")),t=i.elem=k(i.elem);i.size&&o.addClass("layui-colorpicker-"+i.size),t.addClass("layui-inline").html(e.elemColorBox=o),i.id="id"in i?i.id:t.attr("id")||e.index,e.color=e.elemColorBox.find("."+C)[0].style.background,e.events()},d.prototype.renderPicker=function(){var o,e=this,i=e.config,t=e.elemColorBox[0],r=e.elemPicker=k(['
                                                                                                    ','
                                                                                                    ','
                                                                                                    ','
                                                                                                    ','
                                                                                                    ','
                                                                                                    ',"
                                                                                                    ",'
                                                                                                    ','
                                                                                                    ',"
                                                                                                    ","
                                                                                                    ",'
                                                                                                    ','
                                                                                                    ','
                                                                                                    ',"
                                                                                                    ","
                                                                                                    ",i.predefine?(o=['
                                                                                                    '],layui.each(i.colors,function(e,i){o.push(['
                                                                                                    ','
                                                                                                    ',"
                                                                                                    "].join(""))}),o.push("
                                                                                                    "),o.join("")):"",'
                                                                                                    ','
                                                                                                    ','',"
                                                                                                    ",'
                                                                                                    ','','',"","
                                                                                                    "].join(""));e.elemColorBox.find("."+C)[0];k(a)[0]&&k(a).data("index")==e.index?e.removePicker(d.thisElemInd):(e.removePicker(d.thisElemInd),k("body").append(r)),n.thisId=i.id,d.thisElemInd=e.index,d.thisColor=t.style.background,e.position(),e.pickerEvents()},d.prototype.removePicker=function(e){var i=this.config,e=k("#layui-colorpicker"+(e||this.index));return e[0]&&(e.remove(),delete n.thisId,"function"==typeof i.close)&&i.close(this.color),this},d.prototype.position=function(){var e=this,i=e.config;return r.position(e.bindElem||e.elemColorBox[0],e.elemPicker[0],{position:i.position,align:"center"}),e},d.prototype.val=function(){var e,i=this,o=(i.config,i.elemColorBox.find("."+C)),t=i.elemPicker.find("."+M),r=o[0].style.backgroundColor;r?(e=Y(F(r)),o=o.attr("lay-type"),i.select(e.h,e.s,e.b),"torgb"===o?t.find("input").val(r):"rgba"===o?(o=F(r),3===(r.match(/[0-9]{1,3}/g)||[]).length?(t.find("input").val("rgba("+o.r+", "+o.g+", "+o.b+", 1)"),i.elemPicker.find("."+D).css("left",280)):(t.find("input").val(r),r=280*r.slice(r.lastIndexOf(",")+1,r.length-1),i.elemPicker.find("."+D).css("left",r)),i.elemPicker.find("."+T)[0].style.background="linear-gradient(to right, rgba("+o.r+", "+o.g+", "+o.b+", 0), rgb("+o.r+", "+o.g+", "+o.b+"))"):t.find("input").val("#"+j(e))):(i.select(0,100,100),t.find("input").val(""),i.elemPicker.find("."+T)[0].style.background="",i.elemPicker.find("."+D).css("left",280))},d.prototype.side=function(){var n=this,l=n.config,c=n.elemColorBox.find("."+C),a=c.attr("lay-type"),s=n.elemPicker.find(".layui-colorpicker-side"),e=n.elemPicker.find("."+B),d=n.elemPicker.find("."+I),t=n.elemPicker.find("."+E),u=n.elemPicker.find("."+T),f=n.elemPicker.find("."+D),p=e[0].offsetTop/180*360,h=100-(t[0].offsetTop+3)/180*100,g=(t[0].offsetLeft+3)/260*100,v=Math.round(f[0].offsetLeft/280*100)/100,y=n.elemColorBox.find("."+w),i=n.elemPicker.find(".layui-colorpicker-pre").children("div"),m=function(e,i,o,t){n.select(e,i,o);var r=X({h:e,s:i,b:o}),e=j({h:e,s:i,b:o}),i=n.elemPicker.find("."+M).find("input");y.addClass(x).removeClass(P),c[0].style.background="rgb("+r.r+", "+r.g+", "+r.b+")","torgb"===a?i.val("rgb("+r.r+", "+r.g+", "+r.b+")"):"rgba"===a?(f.css("left",280*t),i.val("rgba("+r.r+", "+r.g+", "+r.b+", "+t+")"),c[0].style.background="rgba("+r.r+", "+r.g+", "+r.b+", "+t+")",u[0].style.background="linear-gradient(to right, rgba("+r.r+", "+r.g+", "+r.b+", 0), rgb("+r.r+", "+r.g+", "+r.b+"))"):i.val("#"+e),l.change&&l.change(k.trim(n.elemPicker.find("."+M).find("input").val()))},o=k(['
                                                                                                    '].join("")),b=function(e){k("#LAY-colorpicker-moving")[0]||k("body").append(o),o.on("mousemove",e),o.on("mouseup",function(){o.remove()}).on("mouseleave",function(){o.remove()})};e.on("mousedown",function(e){var t=this.offsetTop,r=e.clientY;b(function(e){var i=t+(e.clientY-r),o=s[0].offsetHeight,o=(i=o<(i=i<0?0:i)?o:i)/180*360;m(p=o,g,h,v),e.preventDefault()}),e.preventDefault()}),s.on("click",function(e){var i=e.clientY-k(this).offset().top+L.scrollTop(),i=(i=(i=i<0?0:i)>this.offsetHeight?this.offsetHeight:i)/180*360;m(p=i,g,h,v),e.preventDefault()}),t.on("mousedown",function(e){var n=this.offsetTop,l=this.offsetLeft,c=e.clientY,a=e.clientX;layui.stope(e),b(function(e){var i=n+(e.clientY-c),o=l+(e.clientX-a),t=d[0].offsetHeight-3,r=d[0].offsetWidth-3,r=((o=r<(o=o<-3?-3:o)?r:o)+3)/260*100,o=100-((i=t<(i=i<-3?-3:i)?t:i)+3)/180*100;m(p,g=r,h=o,v),e.preventDefault()}),e.preventDefault()}),d.on("mousedown",function(e){var i=e.clientY-k(this).offset().top-3+L.scrollTop(),o=e.clientX-k(this).offset().left-3+L.scrollLeft(),o=((i=i<-3?-3:i)>this.offsetHeight-3&&(i=this.offsetHeight-3),((o=(o=o<-3?-3:o)>this.offsetWidth-3?this.offsetWidth-3:o)+3)/260*100),i=100-(i+3)/180*100;m(p,g=o,h=i,v),layui.stope(e),e.preventDefault(),t.trigger(e,"mousedown")}),f.on("mousedown",function(e){var t=this.offsetLeft,r=e.clientX;b(function(e){var i=t+(e.clientX-r),o=u[0].offsetWidth,o=(o<(i=i<0?0:i)&&(i=o),Math.round(i/280*100)/100);m(p,g,h,v=o),e.preventDefault()}),e.preventDefault()}),u.on("click",function(e){var i=e.clientX-k(this).offset().left,i=((i=i<0?0:i)>this.offsetWidth&&(i=this.offsetWidth),Math.round(i/280*100)/100);m(p,g,h,v=i),e.preventDefault()}),i.each(function(){k(this).on("click",function(){k(this).parent(".layui-colorpicker-pre").addClass("selected").siblings().removeClass("selected");var e=this.style.backgroundColor,i=Y(F(e)),o=e.slice(e.lastIndexOf(",")+1,e.length-1);p=i.h,g=i.s,h=i.b,3===(e.match(/[0-9]{1,3}/g)||[]).length&&(o=1),v=o,m(i.h,i.s,i.b,o)})}),r.touchEventsSupported()&&layui.each([{elem:s,eventType:"click"},{elem:u,eventType:"click"},{elem:d,eventType:"mousedown"}],function(e,t){r.touchSwipe(t.elem,{onTouchMove:function(e){var i,o;e=e,i=t.eventType,e=e.touches[0],(o=document.createEvent("MouseEvent")).initMouseEvent(i,!0,!0,window,1,e.screenX,e.screenY,e.clientX,e.clientY,!1,!1,!1,!1,0,null),e.target.dispatchEvent(o)}})})},d.prototype.select=function(e,i,o,t){this.config;var r=j({h:e,s:100,b:100}),e=(j({h:e,s:i,b:o}),e/360*180),o=180-o/100*180-3,i=i/100*260-3;this.elemPicker.find("."+B).css("top",e),this.elemPicker.find("."+I)[0].style.background="#"+r,this.elemPicker.find("."+E).css({top:o,left:i})},d.prototype.pickerEvents=function(){var c=this,a=c.config,s=c.elemColorBox.find("."+C),d=c.elemPicker.find("."+M+" input"),o={clear:function(e){s[0].style.background="",c.elemColorBox.find("."+w).removeClass(x).addClass(P),c.color="",a.done&&a.done(""),c.removePicker()},confirm:function(e,i){var o,t,r,n,l=k.trim(d.val());-1>16,g:(65280&r)>>8,b:255&r},t=Y(n),s[0].style.background=o="#"+j(t),c.elemColorBox.find("."+w).removeClass(P).addClass(x)),"change"===i?(c.select(t.h,t.s,t.b,i),a.change&&a.change(o)):(c.color=l,a.done&&a.done(l),c.removePicker())}};c.elemPicker.on("click","*[colorpicker-events]",function(){var e=k(this),i=e.attr("colorpicker-events");o[i]&&o[i].call(this,e)}),d.on("keyup",function(e){var i=k(this);o.confirm.call(this,i,13===e.keyCode?null:"change")})},d.prototype.events=function(){var e=this;e.config;e.elemColorBox.on("click",function(){e.renderPicker(),k(a)[0]&&(e.val(),e.side())})},s.on(i,function(e){var i,o,t;n.thisId&&(i=l.getThis(n.thisId))&&(o=i.config,t=i.elemColorBox.find("."+C),k(e.target).hasClass(c)||k(e.target).parents("."+c)[0]||k(e.target).hasClass(a.replace(/\./g,""))||k(e.target).parents(a)[0]||i.elemPicker&&(i.color?(e=Y(F(i.color)),i.select(e.h,e.s,e.b)):i.elemColorBox.find("."+w).removeClass(x).addClass(P),t[0].style.background=i.color||"","function"==typeof o.cancel&&o.cancel(i.color),i.removePicker()))}),L.on("resize",function(){if(n.thisId){var e=l.getThis(n.thisId);if(e)return!(!e.elemPicker||!k(a)[0])&&void e.position()}}),l.that={},l.getThis=function(e){var i=l.that[e];return i||o.error(e?t+" instance with ID '"+e+"' not found":"ID argument required"),i},n.render=function(e){e=new d(e);return l.call(e)},e(t,n)});layui.define("jquery",function(t){"use strict";var u=layui.$,d=(layui.hint(),layui.device()),c="element",r="layui-this",h="layui-show",o=".layui-tab-title",i=function(){this.config={}},y=(i.prototype.set=function(t){return u.extend(!0,this.config,t),this},i.prototype.on=function(t,i){return layui.onevent.call(this,c,t,i)},i.prototype.tabAdd=function(t,i){var a,e=u(".layui-tab[lay-filter="+t+"]"),l=e.children(o),n=l.children(".layui-tab-bar"),e=e.children(".layui-tab-content"),s=""+(i.title||"unnaming")+"";return n[0]?n.before(s):l.append(s),e.append('
                                                                                                    '+(i.content||"")+"
                                                                                                    "),i.change&&this.tabChange(t,i.id),l.data("LAY_TAB_CHANGE",i.change),C.tabAuto(i.change?"change":null),this},i.prototype.tabDelete=function(t,i){t=u(".layui-tab[lay-filter="+t+"]").children(o).find('>li[lay-id="'+i+'"]');return C.tabDelete(null,t),this},i.prototype.tabChange=function(t,i){t=u(".layui-tab[lay-filter="+t+"]").children(o).find('>li[lay-id="'+i+'"]');return C.tabClick.call(t[0],{liElem:t}),this},i.prototype.tab=function(a){a=a||{},e.on("click",a.headerElem,function(t){var i=u(this).index();C.tabClick.call(this,{index:i,options:a})})},i.prototype.progress=function(t,i){var a="layui-progress",t=u("."+a+"[lay-filter="+t+"]").find("."+a+"-bar"),a=t.find("."+a+"-text");return t.css("width",function(){return/^.+\/.+$/.test(i)?100*new Function("return "+i)()+"%":i}).attr("lay-percent",i),a.text(i),this},".layui-nav"),f="layui-nav-item",p="layui-nav-bar",b="layui-nav-tree",v="layui-nav-child",m="layui-nav-more",g="layui-anim layui-anim-upbit",C={tabClick:function(t){var i=(t=t||{}).options||{},a=t.liElem||u(this),e=i.headerElem?a.parent():a.parents(".layui-tab").eq(0),i=i.bodyElem?u(i.bodyElem):e.children(".layui-tab-content").children(".layui-tab-item"),l=a.find("a"),l="javascript:;"!==l.attr("href")&&"_blank"===l.attr("target"),n="string"==typeof a.attr("lay-unselect"),s=e.attr("lay-filter"),t="index"in t?t.index:a.parent().children("li").index(a);l||n||(a.addClass(r).siblings().removeClass(r),i.eq(t).addClass(h).siblings().removeClass(h)),layui.event.call(this,c,"tab("+s+")",{elem:e,index:t})},tabDelete:function(t,i){var i=i||u(this).parent(),a=i.parent().children("li").index(i),e=i.closest(".layui-tab"),l=e.children(".layui-tab-content").children(".layui-tab-item"),n=e.attr("lay-filter");i.hasClass(r)&&(i.next()[0]&&i.next().is("li")?C.tabClick.call(i.next()[0],{index:a+1}):i.prev()[0]&&i.prev().is("li")&&C.tabClick.call(i.prev()[0],null,a-1)),i.remove(),l.eq(a).remove(),setTimeout(function(){C.tabAuto()},50),layui.event.call(this,c,"tabDelete("+n+")",{elem:e,index:a})},tabAuto:function(l){var n="layui-tab-more",s="layui-tab-bar",o="layui-tab-close",c=this;u(".layui-tab").each(function(){var t,i=u(this),a=i.children(".layui-tab-title"),e=(i.children(".layui-tab-content").children(".layui-tab-item"),'lay-stope="tabmore"'),e=u('');c===window&&d.ie,i.attr("lay-allowclose")&&a.find("li").each(function(){var t,i=u(this);i.find("."+o)[0]||((t=u('')).on("click",C.tabDelete),i.append(t))}),"string"!=typeof i.attr("lay-unauto")&&(a.prop("scrollWidth")>a.outerWidth()+1||a.find("li").length&&a.height()>(t=a.find("li").eq(0).height())+t/2?("change"===l&&a.data("LAY_TAB_CHANGE")&&a.addClass(n),a.find("."+s)[0]||(a.append(e),i.attr("overflow",""),e.on("click",function(t){var i=a.hasClass(n);a[i?"removeClass":"addClass"](n)}))):(a.find("."+s).remove(),i.removeAttr("overflow")))})},hideTabMore:function(t){var i=u(".layui-tab-title");!0!==t&&"tabmore"===u(t.target).attr("lay-stope")||(i.removeClass("layui-tab-more"),i.find(".layui-tab-bar").attr("title",""))},clickThis:function(){var t=u(this),i=t.closest(y),a=i.attr("lay-filter"),e=t.parent(),l=t.siblings("."+v),n="string"==typeof e.attr("lay-unselect");if("javascript:;"!==t.attr("href")&&"_blank"===t.attr("target")||n||l[0]||(i.find("."+r).removeClass(r),e.addClass(r)),i.hasClass(b)){var n=f+"ed",s=!e.hasClass(n),o=function(){u(this).css({display:""}),i.children("."+p).css({opacity:0})};if(l.is(":animated"))return;l.removeClass(g),l[0]&&(s?(l.slideDown(200,o),e.addClass(n)):(e.removeClass(n),l.show().slideUp(200,o)),"string"!=typeof i.attr("lay-accordion")&&"all"!==i.attr("lay-shrink")||((s=e.siblings("."+n)).removeClass(n),s.children("."+v).show().stop().slideUp(200,o)))}layui.event.call(this,c,"nav("+a+")",t)},collapse:function(){var t=u(this),i=t.find(".layui-colla-icon"),a=t.siblings(".layui-colla-content"),e=t.parents(".layui-collapse").eq(0),l=e.attr("lay-filter"),n="none"===a.css("display");"string"==typeof e.attr("lay-accordion")&&((e=e.children(".layui-colla-item").children("."+h)).siblings(".layui-colla-title").children(".layui-colla-icon").html(""),e.removeClass(h)),a[n?"addClass":"removeClass"](h),i.html(n?"":""),layui.event.call(this,c,"collapse("+l+")",{title:t,content:a,show:n})}},a=(i.prototype.render=i.prototype.init=function(t,i){var a=i?'[lay-filter="'+i+'"]':"",i={tab:function(){C.tabAuto.call({})},nav:function(){var s={},o={},c={},r="layui-nav-title";u(y+a).each(function(t){var i=u(this),a=u(''),e=i.find("."+f);i.find("."+p)[0]||(i.append(a),(i.hasClass(b)?e.find("dd,>."+r):e).on("mouseenter",function(){!function(t,i,a){var e,l=u(this),n=l.find("."+v);i.hasClass(b)?n[0]||(e=l.children("."+r),t.css({top:l.offset().top-i.offset().top,height:(e[0]?e:l).outerHeight(),opacity:1})):(n.addClass(g),n.hasClass("layui-nav-child-c")&&n.css({left:-(n.outerWidth()-l.width())/2}),n[0]?t.css({left:t.position().left+t.width()/2,width:0,opacity:0}):t.css({left:l.position().left+parseFloat(l.css("marginLeft")),top:l.position().top+l.height()-t.height()}),s[a]=setTimeout(function(){t.css({width:n[0]?0:l.width(),opacity:n[0]?0:1})},d.ie&&d.ie<10?0:200),clearTimeout(c[a]),"block"===n.css("display")&&clearTimeout(o[a]),o[a]=setTimeout(function(){n.addClass(h),l.find("."+m).addClass(m+"d")},300))}.call(this,a,i,t)}).on("mouseleave",function(){i.hasClass(b)?a.css({height:0,opacity:0}):(clearTimeout(o[t]),o[t]=setTimeout(function(){i.find("."+v).removeClass(h),i.find("."+m).removeClass(m+"d")},300))}),i.on("mouseleave",function(){clearTimeout(s[t]),c[t]=setTimeout(function(){i.hasClass(b)||a.css({width:0,left:a.position().left+a.width()/2,opacity:0})},200)})),e.find("a").each(function(){var t=u(this);t.parent();t.siblings("."+v)[0]&&!t.children("."+m)[0]&&t.append(''),t.off("click",C.clickThis).on("click",C.clickThis)})})},breadcrumb:function(){u(".layui-breadcrumb"+a).each(function(){var t=u(this),i="lay-separator",a=t.attr(i)||"/",e=t.find("a");e.next("span["+i+"]")[0]||(e.each(function(t){t!==e.length-1&&u(this).after(""+a+"")}),t.css("visibility","visible"))})},progress:function(){var e="layui-progress";u("."+e+a).each(function(){var t=u(this),i=t.find(".layui-progress-bar"),a=i.attr("lay-percent");i.css("width",function(){return/^.+\/.+$/.test(a)?100*new Function("return "+a)()+"%":a}),t.attr("lay-showpercent")&&setTimeout(function(){i.html(''+a+"")},350)})},collapse:function(){u(".layui-collapse"+a).each(function(){u(this).find(".layui-colla-item").each(function(){var t=u(this),i=t.find(".layui-colla-title"),t="none"===t.find(".layui-colla-content").css("display");i.find(".layui-colla-icon").remove(),i.append(''+(t?"":"")+""),i.off("click",C.collapse).on("click",C.collapse)})})}};return i[t]?i[t]():layui.each(i,function(t,i){i()})},new i),e=u(document);u(function(){a.render()}),e.on("click",".layui-tab-title li",C.tabClick),u(window).on("resize",C.tabAuto),t(c,a)});layui.define(["lay","layer"],function(e){"use strict";var x=layui.$,a=layui.lay,i=layui.layer,b=layui.device(),t="upload",r="layui_"+t+"_index",o={config:{},index:layui[t]?layui[t].index+1e4:0,set:function(e){var i=this;return i.config=x.extend({},i.config,e),i},on:function(e,i){return layui.onevent.call(this,t,e,i)}},l=function(){var i=this,e=i.config.id;return{upload:function(e){i.upload.call(i,e)},reload:function(e){i.reload.call(i,e)},config:(l.that[e]=i).config}},u="layui-upload-file",f="layui-upload-form",F="layui-upload-iframe",w="layui-upload-choose",L="UPLOADING",j=function(e){var i=this;i.index=++o.index,i.config=x.extend({},i.config,o.config,e),i.render()};j.prototype.config={accept:"images",exts:"",auto:!0,bindAction:"",url:"",force:"",field:"file",acceptMime:"",method:"post",data:{},drag:!0,size:0,number:0,multiple:!1,text:{"cross-domain":"Cross-domain requests are not supported","data-format-error":"Please return JSON data format","check-error":"",error:"","limit-number":null,"limit-size":null}},j.prototype.reload=function(e){var i=this;i.config=x.extend({},i.config,e),i.render(!0)},j.prototype.render=function(e){var i=this,t=i.config,n=x(t.elem);return 1"].join("")),n=i.elem.next();(n.hasClass(u)||n.hasClass(f))&&n.remove(),b.ie&&b.ie<10&&i.elem.wrap('
                                                                                                    '),e.isFile()?(e.elemFile=i.elem,i.field=i.elem[0].name):i.elem.after(t),b.ie&&b.ie<10&&e.initIE()},j.prototype.initIE=function(){var t,e=this.config,i=x(''),n=x(['
                                                                                                    ',"
                                                                                                    "].join(""));x("#"+F)[0]||x("body").append(i),e.elem.next().hasClass(f)||(this.elemFile.wrap(n),e.elem.next("."+f).append((t=[],layui.each(e.data,function(e,i){i="function"==typeof i?i():i,t.push('')}),t.join(""))))},j.prototype.msg=function(e){return i.msg(e,{icon:2,shift:6})},j.prototype.isFile=function(){var e=this.config.elem[0];if(e)return"input"===e.tagName.toLocaleLowerCase()&&"file"===e.type},j.prototype.preview=function(n){window.FileReader&&layui.each(this.chooseFiles,function(e,i){var t=new FileReader;t.readAsDataURL(i),t.onload=function(){n&&n(e,i,this.result)}})},j.prototype.upload=function(e,i){var t,n,a,o,u=this,f=u.config,c=f.text||{},l=u.elemFile[0],s=function(){return e||u.files||u.chooseFiles||l.files},r=function(){var a=0,o=0,l=s(),r=function(){f.multiple&&a+o===u.fileLength&&"function"==typeof f.allDone&&f.allDone({total:u.fileLength,successful:a,failed:o})},t=function(t){var n=new FormData,i=function(e){t.unified?layui.each(l,function(e,i){delete i[L]}):delete e[L]};if(layui.each(f.data,function(e,i){i="function"==typeof i?i():i,n.append(e,i)}),t.unified)layui.each(l,function(e,i){i[L]||(i[L]=!0,n.append(f.field,i))});else{if(t.file[L])return;n.append(f.field,t.file),t.file[L]=!0}var e={url:f.url,type:"post",data:n,dataType:f.dataType||"json",contentType:!1,processData:!1,headers:f.headers||{},success:function(e){f.unified?a+=u.fileLength:a++,p(t.index,e),r(t.index),i(t.file)},error:function(e){f.unified?o+=u.fileLength:o++,u.msg(c.error||["Upload failed, please try again.","status: "+(e.status||"")+" - "+(e.statusText||"error")].join("
                                                                                                    ")),m(t.index),r(t.index),i(t.file)}};"function"==typeof f.progress&&(e.xhr=function(){var e=x.ajaxSettings.xhr();return e.upload.addEventListener("progress",function(e){var i;e.lengthComputable&&(i=Math.floor(e.loaded/e.total*100),f.progress(i,(f.item||f.elem)[0],e,t.index))}),e}),x.ajax(e)};f.unified?t({unified:!0,index:0}):layui.each(l,function(e,i){t({index:e,file:i})})},d=function(){var n=x("#"+F);u.elemFile.parent().submit(),clearInterval(j.timer),j.timer=setInterval(function(){var e,i=n.contents().find("body");try{e=i.text()}catch(t){u.msg(c["cross-domain"]),clearInterval(j.timer),m()}e&&(clearInterval(j.timer),i.html(""),p(0,e))},30)},p=function(e,i){if(u.elemFile.next("."+w).remove(),l.value="","json"===f.force&&"object"!=typeof i)try{i=JSON.parse(i)}catch(t){return i={},u.msg(c["data-format-error"])}"function"==typeof f.done&&f.done(i,e||0,function(e){u.upload(e)})},m=function(e){f.auto&&(l.value=""),"function"==typeof f.error&&f.error(e||0,function(e){u.upload(e)})},h=f.exts,g=(n=[],layui.each(e||u.chooseFiles,function(e,i){n.push(i.name)}),n),v={preview:function(e){u.preview(e)},upload:function(e,i){var t={};t[e]=i,u.upload(t)},pushFile:function(){return u.files=u.files||{},layui.each(u.chooseFiles,function(e,i){u.files[e]=i}),u.files},resetFile:function(e,i,t){i=new File([i],t);u.files=u.files||{},u.files[e]=i}},y={file:"\u6587\u4ef6",images:"\u56fe\u7247",video:"\u89c6\u9891",audio:"\u97f3\u9891"}[f.accept]||"\u6587\u4ef6",g=0===g.length?l.value.match(/[^\/\\]+\..+/g)||[]:g;if(0!==g.length){switch(f.accept){case"file":layui.each(g,function(e,i){if(h&&!RegExp(".\\.("+h+")$","i").test(escape(i)))return t=!0});break;case"video":layui.each(g,function(e,i){if(!RegExp(".\\.("+(h||"avi|mp4|wma|rmvb|rm|flash|3gp|flv")+")$","i").test(escape(i)))return t=!0});break;case"audio":layui.each(g,function(e,i){if(!RegExp(".\\.("+(h||"mp3|wav|mid")+")$","i").test(escape(i)))return t=!0});break;default:layui.each(g,function(e,i){if(!RegExp(".\\.("+(h||"jpg|png|gif|bmp|jpeg|svg")+")$","i").test(escape(i)))return t=!0})}if(t)return u.msg(c["check-error"]||"\u9009\u62e9\u7684"+y+"\u4e2d\u5305\u542b\u4e0d\u652f\u6301\u7684\u683c\u5f0f"),l.value="";if("choose"!==i&&!f.auto||(f.choose&&f.choose(v),"choose"!==i)){if(u.fileLength=(a=0,y=s(),layui.each(y,function(){a++}),a),f.number&&u.fileLength>f.number)return u.msg("function"==typeof c["limit-number"]?c["limit-number"](f,u.fileLength):"\u540c\u65f6\u6700\u591a\u53ea\u80fd\u4e0a\u4f20: "+f.number+" \u4e2a\u6587\u4ef6
                                                                                                    \u60a8\u5f53\u524d\u5df2\u7ecf\u9009\u62e9\u4e86: "+u.fileLength+" \u4e2a\u6587\u4ef6");if(01024*f.size&&(i=1<=(i=f.size/1024)?i.toFixed(2)+"MB":f.size+"KB",l.value="",o=i)}),o)return u.msg("function"==typeof c["limit-size"]?c["limit-size"](f,o):"\u6587\u4ef6\u5927\u5c0f\u4e0d\u80fd\u8d85\u8fc7 "+o);if(!f.before||!1!==f.before(v))b.ie?(9'+e+"")};a.elem.off("upload.start").on("upload.start",function(){var e=x(this);n.config.item=e,n.elemFile[0].click()}),b.ie&&b.ie<10||a.elem.off("upload.over").on("upload.over",function(){x(this).attr("lay-over","")}).off("upload.leave").on("upload.leave",function(){x(this).removeAttr("lay-over")}).off("upload.drop").on("upload.drop",function(e,i){var t=x(this),i=i.originalEvent.dataTransfer.files||[];t.removeAttr("lay-over"),o(i),a.auto?n.upload():l(i)}),n.elemFile.on("change",function(){var e=this.files||[];0!==e.length&&(o(e),a.auto?n.upload():l(e))}),a.bindAction.off("upload.action").on("upload.action",function(){n.upload()}),a.elem.data(r)||(a.elem.on("click",function(){n.isFile()||x(this).trigger("upload.start")}),a.drag&&a.elem.on("dragover",function(e){e.preventDefault(),x(this).trigger("upload.over")}).on("dragleave",function(e){x(this).trigger("upload.leave")}).on("drop",function(e){e.preventDefault(),x(this).trigger("upload.drop",e)}),a.bindAction.on("click",function(){x(this).trigger("upload.action")}),a.elem.data(r,a.id))},l.that={},l.getThis=function(e){var i=l.that[e];return i||hint.error(e?t+" instance with ID '"+e+"' not found":"ID argument required"),i},o.render=function(e){e=new j(e);return l.call(e)},e(t,o)});layui.define(["lay","layer","util"],function(e){"use strict";var C=layui.$,h=layui.layer,d=layui.util,l=layui.hint(),w=(layui.device(),"form"),o=".layui-form",N="layui-this",T="layui-hide",$="layui-disabled",t=function(){this.config={verify:{required:function(e){if(!/[\S]+/.test(e))return"\u5fc5\u586b\u9879\u4e0d\u80fd\u4e3a\u7a7a"},phone:function(e){if(e&&!/^1\d{10}$/.test(e))return"\u624b\u673a\u53f7\u683c\u5f0f\u4e0d\u6b63\u786e"},email:function(e){if(e&&!/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(e))return"\u90ae\u7bb1\u683c\u5f0f\u4e0d\u6b63\u786e"},url:function(e){if(e&&!/^(#|(http(s?)):\/\/|\/\/)[^\s]+\.[^\s]+$/.test(e))return"\u94fe\u63a5\u683c\u5f0f\u4e0d\u6b63\u786e"},number:function(e){if(e&&isNaN(e))return"\u53ea\u80fd\u586b\u5199\u6570\u5b57"},date:function(e){if(e&&!/^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/.test(e))return"\u65e5\u671f\u683c\u5f0f\u4e0d\u6b63\u786e"},identity:function(e){if(e&&!/(^\d{15}$)|(^\d{17}(x|X|\d)$)/.test(e))return"\u8eab\u4efd\u8bc1\u53f7\u683c\u5f0f\u4e0d\u6b63\u786e"}},autocomplete:null}},i=(t.prototype.set=function(e){return C.extend(!0,this.config,e),this},t.prototype.verify=function(e){return C.extend(!0,this.config.verify,e),this},t.prototype.getFormElem=function(e){return C(o+(e?'[lay-filter="'+e+'"]':""))},t.prototype.on=function(e,t){return layui.onevent.call(this,w,e,t)},t.prototype.val=function(e,i){return this.getFormElem(e).each(function(e,t){var a=C(this);layui.each(i,function(e,t){var i,e=a.find('[name="'+e+'"]');e[0]&&("checkbox"===(i=e[0].type)?e[0].checked=t:"radio"===i?e.each(function(){this.checked=this.value==t}):e.val(t))})}),r.render(null,e),this.getValue(e)},t.prototype.getValue=function(e,t){t=t||this.getFormElem(e);var a={},n={},e=t.find("input,select,textarea");return layui.each(e,function(e,t){var i;C(this);t.name=(t.name||"").replace(/^\s*|\s*&/,""),t.name&&(/^.*\[\]$/.test(t.name)&&(i=t.name.match(/^(.*)\[\]$/g)[0],a[i]=0|a[i],i=t.name.replace(/^(.*)\[\]$/,"$1["+a[i]+++"]")),/^(checkbox|radio)$/.test(t.type)&&!t.checked||(n[i||t.name]=t.value))}),n},t.prototype.render=function(e,t){var i=this.config,a=C(o+(t?'[lay-filter="'+t+'"]':"")),n={input:function(e){var e=e||a.find("input,textarea"),t=(i.autocomplete&&e.attr("autocomplete",i.autocomplete),function(e,t){var i=e.val(),a=Number(i),n=Number(e.attr("step"))||1,l=Number(e.attr("min")),r=Number(e.attr("max")),s=Number(e.attr("lay-precision")),o="click"!==t&&""===i,c="init"===t;isNaN(a)||("click"===t&&(a=!!C(this).index()?a-n:a+n),t=function(e){return((e.toString().match(/\.(\d+$)/)||[])[1]||"").length},s=0<=s?s:Math.max(t(n),t(i)),o||(c||r<=(a=a<=l?l:a)&&(a=r),s&&(a=a.toFixed(s)),e.val(a)),e[(a'),e=layui.isArray(i.value)?i.value:[i.value],e=C((a=[],layui.each(e,function(e,t){a.push('')}),a.join(""))),n=(t.append(e),i.split&&t.addClass("layui-input-split"),i.className&&t.addClass(i.className),r.next("."+u)),l=(n[0]&&n.remove(),r.parent().hasClass(o)||r.wrap('
                                                                                                    '),r.next("."+c));l[0]?((n=l.find("."+u))[0]&&n.remove(),l.prepend(t),r.css("padding-right",function(){return(r.closest(".layui-input-group")[0]?0:l.outerWidth())+t.outerWidth()})):(t.addClass(c),r.after(t)),"auto"===i.show&&d(t,r.val()),"function"==typeof i.init&&i.init.call(this,r,i),r.on("input propertychange",function(){var e=this.value;"auto"===i.show&&d(t,e)}),r.on("blur",function(){"function"==typeof i.blur&&i.blur.call(this,r,i)}),e.on("click",function(){var e=r.attr("lay-filter");C(this).hasClass($)||("function"==typeof i.click&&i.click.call(this,r,i),layui.event.call(this,w,"input-affix("+e+")",{elem:r[0],affix:s,options:i}))})},f={eye:{value:"eye-invisible",click:function(e,t){var i="LAY_FORM_INPUT_AFFIX_SHOW",a=e.data(i);e.attr("type",a?"password":"text").data(i,!a),n({value:a?"eye-invisible":"eye"})}},clear:{value:"clear",click:function(e){e.val("").focus(),d(C(this).parent(),null)},show:"auto",disabled:e},number:{value:["up","down"],split:!0,className:"layui-input-number",disabled:r.is("[disabled]"),init:function(e){t.call(this,e,"init")},click:function(e){t.call(this,e,"click")},blur:function(e){t.call(this,e,"blur")}}};n()})},select:function(e){var p,c="\u8bf7\u9009\u62e9",m="layui-form-select",g="layui-select-title",x="layui-select-none",b="",e=e||a.find("select"),k=function(e,t){C(e.target).parent().hasClass(g)&&!t||(C("."+m).removeClass(m+"ed "+m+"up"),p&&b&&p.val(b)),p=null},u=function(a,e,t){var s,r,i,n,o,l,c=C(this),u=a.find("."+g),d=u.find("input"),f=a.find("dl"),h=f.children("dd"),y=f.children("dt"),v=this.selectedIndex;e||(r=c.attr("lay-search"),i=function(){var e=a.offset().top+a.outerHeight()+5-F.scrollTop(),t=f.outerHeight();v=c[0].selectedIndex,a.addClass(m+"ed"),h.removeClass(T),y.removeClass(T),s=null,h.removeClass(N),0<=v&&h.eq(v).addClass(N),e+t>F.height()&&t<=e&&a.addClass(m+"up"),o()},n=function(e){a.removeClass(m+"ed "+m+"up"),d.blur(),s=null,e||l(d.val(),function(e){var t=c[0].selectedIndex;e&&(b=C(c[0].options[t]).html(),0===t&&b===d.attr("placeholder")&&(b=""),d.val(b||""))})},o=function(){var e,t,i=f.children("dd."+N);i[0]&&(e=i.position().top,t=f.height(),i=i.height(),t\u65e0\u5339\u914d\u9879

                                                                                                    '):f.find("."+x).remove()},"keyup"),""===t&&(c.val(""),f.find("."+N).removeClass(N),(c[0].options[0]||{}).value||f.children("dd:eq(0)").addClass(N),f.find("."+x).remove()),o()}).on("blur",function(e){var t=c[0].selectedIndex;p=d,b=C(c[0].options[t]).text(),0===t&&b===d.attr("placeholder")&&(b=""),setTimeout(function(){l(d.val(),function(e){b||d.val("")},"blur")},200)})),h.on("click",function(){var e=C(this),t=e.attr("lay-value"),i=c.attr("lay-filter");return e.hasClass($)||(e.hasClass("layui-select-tips")?d.val(""):(d.val(e.text()),e.addClass(N)),e.siblings().removeClass(N),c.val(t).removeClass("layui-form-danger"),layui.event.call(this,w,"select("+i+")",{elem:c[0],value:t,othis:a}),n(!0)),!1}),a.find("dl>dt").on("click",function(e){return!1}),C(document).off("click",k).on("click",k))};e.each(function(e,t){var i=C(this),a=i.next("."+m),n=this.disabled,l=t.value,r=C(t.options[t.selectedIndex]),t=t.options[0];if("string"==typeof i.attr("lay-ignore"))return i.show();var s,o="string"==typeof i.attr("lay-search"),t=t&&!t.value&&t.innerHTML||c,r=C(['
                                                                                                    ','
                                                                                                    ','','
                                                                                                    ','
                                                                                                    ',(t=i.find("*"),s=[],layui.each(t,function(e,t){var i=t.tagName.toLowerCase();0!==e||t.value||"optgroup"===i?s.push("optgroup"===i?"
                                                                                                    "+t.label+"
                                                                                                    ":'
                                                                                                    '+C.trim(t.innerHTML)+"
                                                                                                    "):s.push('
                                                                                                    '+C.trim(t.innerHTML||c)+"
                                                                                                    ")}),0===s.length&&s.push('
                                                                                                    \u6ca1\u6709\u9009\u9879
                                                                                                    '),s.join("")+"
                                                                                                    "),"
                                                                                                    "].join(""));a[0]&&a.remove(),i.after(r),u.call(this,r,n,o)})},checkbox:function(e){var o={checkbox:["layui-form-checkbox","layui-form-checked","checkbox"],"switch":["layui-form-switch","layui-form-onswitch","switch"],SUBTRA:"layui-icon-indeterminate"},e=e||a.find("input[type=checkbox]");e.each(function(e,t){var i=C(this),a=i.attr("lay-skin")||"primary",n=d.escape(C.trim(t.title||(t.title=i.attr("lay-text")||""))),l=this.disabled,r=o[a]||o.checkbox,s=i.next("."+r[0]);if(s[0]&&s.remove(),i.next("[lay-checkbox]")[0]&&(n=i.next().html()||""),n="switch"===a?n.split("|"):[n],"string"==typeof i.attr("lay-ignore"))return i.show();l=C(['
                                                                                                    ",(s={checkbox:[n[0]?"
                                                                                                    "+n[0]+"
                                                                                                    ":"primary"===a?"":"
                                                                                                    ",''].join(""),"switch":"
                                                                                                    "+((t.checked?n[0]:n[1])||"")+"
                                                                                                    "})[a]||s.checkbox,"
                                                                                                    "].join(""));i.after(l),function(a,n){var l=C(this);a.on("click",function(){var e=C(this),t=l.attr("lay-filter"),e=e.next("*[lay-checkbox]")[0]?e.next().html():l.attr("title")||"",i=l.attr("lay-skin")||"primary",e="switch"===i?e.split("|"):[e];l[0].disabled||(l[0].indeterminate&&(l[0].indeterminate=!1,a.find("."+o.SUBTRA).removeClass(o.SUBTRA).addClass("layui-icon-ok")),l[0].checked?(l[0].checked=!1,a.removeClass(n[1]),"switch"===i&&a.children("div").html(e[1])):(l[0].checked=!0,a.addClass(n[1]),"switch"===i&&a.children("div").html(e[0])),layui.event.call(l[0],w,n[2]+"("+t+")",{elem:l[0],value:l[0].value,othis:a}))})}.call(this,l,r)})},radio:function(e){var r="layui-form-radio",s=["layui-icon-radio","layui-icon-circle"],e=e||a.find("input[type=radio]");e.each(function(e,t){var i=C(this),a=i.next("."+r),n=this.disabled;if("string"==typeof i.attr("lay-ignore"))return i.show();a[0]&&a.remove();n=C(['
                                                                                                    ','',"
                                                                                                    "+(a=d.escape(t.title||""),a=i.next("[lay-radio]")[0]?i.next().html():a)+"
                                                                                                    ","
                                                                                                    "].join(""));i.after(n),function(a){var n=C(this),l="layui-anim-scaleSpring";a.on("click",function(){var e=n[0].name,t=n.parents(o),i=n.attr("lay-filter"),e=t.find("input[name="+e.replace(/(\.|#|\[|\])/g,"\\$1")+"]");n[0].disabled||(layui.each(e,function(){var e=C(this).next("."+r);this.checked=!1,e.removeClass(r+"ed"),e.children(".layui-icon").removeClass(l+" "+s[0]).addClass(s[1])}),n[0].checked=!0,a.addClass(r+"ed"),a.children(".layui-icon").addClass(l+" "+s[0]),layui.event.call(n[0],w,"radio("+i+")",{elem:n[0],value:n[0].value,othis:a}))})}.call(this,n)})}},t=function(){layui.each(n,function(e,t){t()})};return"object"===layui.type(e)?C(e).is(o)?(a=C(e),t()):e.each(function(e,t){var i=C(t);i.closest(o).length&&("SELECT"===t.tagName?n.select(i):"INPUT"===t.tagName&&("checkbox"===(t=t.type)||"radio"===t?n[t](i):n.input(i)))}):e?n[e]?n[e]():l.error('\u4e0d\u652f\u6301\u7684 "'+e+'" \u8868\u5355\u6e32\u67d3'):t(),this},t.prototype.validate=function(e){var u,d=this.config.verify,f="layui-form-danger";return!(e=C(e))[0]||(e.attr("lay-verify")!==undefined||!1!==this.validate(e.find("*[lay-verify]")))&&(layui.each(e,function(e,r){var s=C(this),t=(s.attr("lay-verify")||"").split("|"),o=s.attr("lay-vertype"),c=C.trim(s.val());if(s.removeClass(f),layui.each(t,function(e,t){var i="",a=d[t];if(a){var n="function"==typeof a?i=a(c,r):!a[0].test(c),l="select"===r.tagName.toLowerCase()||/^(checkbox|radio)$/.test(r.type),i=i||a[1];if("required"===t&&(i=s.attr("lay-reqtext")||i),n)return"tips"===o?h.tips(i,"string"!=typeof s.attr("lay-ignore")&&l?s.next():s,{tips:1}):"alert"===o?h.alert(i,{title:"\u63d0\u793a",shadeClose:!0}):/\b(string|number)\b/.test(typeof i)&&h.msg(i,{icon:5,shift:6}),setTimeout(function(){(l?s.next().find("input"):r).focus()},7),s.addClass(f),u=!0}}),u)return u}),!u)},t.prototype.submit=function(e,t){var i={},a=C(this),e="string"==typeof e?e:a.attr("lay-filter"),n=this.getFormElem?this.getFormElem(e):a.parents(o).eq(0),l=n.find("*[lay-verify]");return!!r.validate(l)&&(i=r.getValue(null,n),l={elem:this.getFormElem?window.event&&window.event.target:this,form:(this.getFormElem?n:a.parents("form"))[0],field:i},"function"==typeof t&&t(l),layui.event.call(this,w,"submit("+e+")",l))}),r=new t,t=C(document),F=C(window);C(function(){r.render()}),t.on("reset",o,function(){var e=C(this).attr("lay-filter");setTimeout(function(){r.render(null,e)},50)}),t.on("submit",o,i).on("click","*[lay-submit]",i),e(w,r)});layui.define(["lay","laytpl","laypage","form","util"],function(n){"use strict";var p=layui.$,r=layui.lay,m=layui.laytpl,O=layui.laypage,f=layui.layer,v=layui.form,g=layui.util,x=layui.hint(),b=layui.device(),k={config:{checkName:"LAY_CHECKED",indexName:"LAY_INDEX",numbersName:"LAY_NUM",disabledName:"LAY_DISABLED"},cache:{},index:layui.table?layui.table.index+1e4:0,set:function(e){return this.config=p.extend({},this.config,e),this},on:function(e,t){return layui.onevent.call(this,N,e,t)}},w=function(){var a=this,e=a.config,i=e.id||e.index;return{config:e,reload:function(e,t){a.reload.call(a,e,t)},reloadData:function(e,t){k.reloadData(i,e,t)},setColsWidth:function(){a.setColsWidth.call(a)},resize:function(){a.resize.call(a)}}},C=function(e){var t=w.that[e];return t||x.error(e?"The table instance with ID '"+e+"' not found":"ID argument required"),t||null},l=function(e){var t=w.config[e];return t||x.error(e?"The table instance with ID '"+e+"' not found":"ID argument required"),t||null},T=function(e){var t=this.config||{},a=(e=e||{}).item3,i=e.content;"numbers"===a.type&&(i=e.tplData[k.config.numbersName]);("escape"in a?a:t).escape&&(i=g.escape(i));t=e.text&&a.exportTemplet||a.templet||a.toolbar;return t&&(i="function"==typeof t?t.call(a,e.tplData,e.obj):m(function(e){try{return r(e).html()}catch(t){return e}}(t)||String(i)).render(p.extend({LAY_COL:a},e.tplData))),e.text?p("
                                                                                                    "+i+"
                                                                                                    ").text():i},N="table",t=".layui-table",R="layui-hide",y="layui-hide-v",h="layui-none",D="layui-table-view",o=".layui-table-header",L=".layui-table-body",u=".layui-table-fixed-r",I=".layui-table-pageview",A=".layui-table-sort",E="layui-table-checked",_="layui-table-edit",M="layui-table-hover",P="laytable-cell-group",W="layui-table-col-special",j="layui-table-tool-panel",H="layui-table-expanded",S="LAY_TABLE_MOVE_DICT",e=function(e){return['',"","{{# layui.each(d.data.cols, function(i1, item1){ }}","","{{# layui.each(item1, function(i2, item2){ }}",'{{# if(item2.fixed && item2.fixed !== "right"){ left = true; } }}','{{# if(item2.fixed === "right"){ right = true; } }}',(e=e||{}).fixed&&"right"!==e.fixed?'{{# if(item2.fixed && item2.fixed !== "right"){ }}':"right"===e.fixed?'{{# if(item2.fixed === "right"){ }}':"","{{# var isSort = !(item2.colGroup) && item2.sort; }}",'",e.fixed?"{{# }; }}":"","{{# }); }}","","{{# }); }}","","
                                                                                                    ','
                                                                                                    ','{{# if(item2.type === "checkbox"){ }}','',"{{# } else { }}",'{{-item2.title||""}}',"{{# if(isSort){ }}",'',"{{# } }}","{{# } }}","
                                                                                                    ","
                                                                                                    "].join("")},a=['',"","
                                                                                                    "].join(""),s=[,"{{# if(d.data.toolbar){ }}",'
                                                                                                    ','
                                                                                                    ','
                                                                                                    ',"
                                                                                                    ","{{# } }}",'
                                                                                                    ',"{{# if(d.data.loading){ }}",'
                                                                                                    ','',"
                                                                                                    ","{{# } }}","{{# var left, right; }}",'
                                                                                                    ',e(),"
                                                                                                    ",'
                                                                                                    ',a,"
                                                                                                    ","{{# if(left){ }}",'
                                                                                                    ','
                                                                                                    ',e({fixed:!0}),"
                                                                                                    ",'
                                                                                                    ',a,"
                                                                                                    ","
                                                                                                    ","{{# }; }}","{{# if(right){ }}",'
                                                                                                    ','
                                                                                                    ',e({fixed:"right"}),'
                                                                                                    ',"
                                                                                                    ",'
                                                                                                    ',a,"
                                                                                                    ","
                                                                                                    ","{{# }; }}","
                                                                                                    ","{{# if(d.data.totalRow){ }}",'
                                                                                                    ','','',"
                                                                                                    ","
                                                                                                    ","{{# } }}",'
                                                                                                    ','
                                                                                                    ',"
                                                                                                    "].join(""),d=p(window),F=p(document),i=function(e){this.index=++k.index,this.config=p.extend({},this.config,k.config,e),this.render()},c=(i.prototype.config={limit:10,loading:!0,escape:!0,cellMinWidth:60,cellMaxWidth:Number.MAX_VALUE,editTrigger:"click",defaultToolbar:["filter","exports","print"],defaultContextmenu:!0,autoSort:!0,text:{none:"\u65e0\u6570\u636e"},cols:[]},i.prototype.render=function(e){var t=this,a=t.config,i=(a.elem=p(a.elem),a.where=a.where||{},a.id="id"in a?a.id:a.elem.attr("id")||t.index);if(w.that[i]=t,(w.config[i]=a).request=p.extend({pageName:"page",limitName:"limit"},a.request),a.response=p.extend({statusName:"code",statusCode:0,msgName:"msg",dataName:"data",totalRowName:"totalRow",countName:"count"},a.response),null!==a.page&&"object"==typeof a.page&&(a.limit=a.page.limit||a.limit,a.limits=a.page.limits||a.limits,t.page=a.page.curr=a.page.curr||1,delete a.page.elem,delete a.page.jump),!a.elem[0])return t;if(a.elem.attr("lay-filter")||a.elem.attr("lay-filter",a.id),"reloadData"===e)return t.pullData(t.page,{type:"reloadData"});a.index=t.index,t.key=a.id||a.index,t.setInit(),a.height&&/^full-.+$/.test(a.height)?(t.fullHeightGap=a.height.split("-")[1],a.height=d.height()-(parseFloat(t.fullHeightGap)||0)):a.height&&/^#\w+\S*-.+$/.test(a.height)?(i=a.height.split("-"),t.parentHeightGap=i.pop(),t.parentDiv=i.join("-"),a.height=p(t.parentDiv).height()-(parseFloat(t.parentHeightGap)||0)):"function"==typeof a.height&&(t.customHeightFunc=a.height,a.height=t.customHeightFunc());var l,e=a.elem,i=e.next("."+D),n=t.elem=p("
                                                                                                    ");n.addClass((l=[D,D+"-"+t.index,"layui-form","layui-border-box"],a.className&&l.push(a.className),l.join(" "))).attr({"lay-filter":"LAY-TABLE-FORM-DF-"+t.index,"lay-id":a.id,style:(l=[],a.width&&l.push("width:"+a.width+"px;"),l.join(""))}).html(m(s,{open:"{{",close:"}}"}).render({data:a,index:t.index})),t.renderStyle(),i[0]&&i.remove(),e.after(n),t.layTool=n.find(".layui-table-tool"),t.layBox=n.find(".layui-table-box"),t.layHeader=n.find(o),t.layMain=n.find(".layui-table-main"),t.layBody=n.find(L),t.layFixed=n.find(".layui-table-fixed"),t.layFixLeft=n.find(".layui-table-fixed-l"),t.layFixRight=n.find(u),t.layTotal=n.find(".layui-table-total"),t.layPage=n.find(".layui-table-page"),t.renderToolbar(),t.renderPagebar(),t.fullSize(),t.pullData(t.page),t.events()},i.prototype.initOpts=function(e){this.config;e.checkbox&&(e.type="checkbox"),e.space&&(e.type="space"),e.type||(e.type="normal"),"normal"!==e.type&&(e.unresize=!0,e.width=e.width||{checkbox:50,radio:50,space:30,numbers:60}[e.type])},i.prototype.setInit=function(e){var l,a,d=this,r=d.config;if(r.clientWidth=r.width||(l=function(e){var t,a=(e=e||r.elem.parent()).width();try{t="none"===e.css("display")}catch(i){}return!e[0]||a&&!t?a:l(e.parent())})(),"width"===e)return r.clientWidth;r.height=r.maxHeight||r.height,r.css&&-1===r.css.indexOf(D)&&(a=r.css.split("}"),layui.each(a,function(e,t){t&&(a[e]="."+D+"-"+d.index+" "+t)}),r.css=a.join("}"));var c=function(a,e,i,l){var n,o;l?(l.key=[r.index,a,i].join("-"),l.colspan=l.colspan||0,l.rowspan=l.rowspan||0,d.initOpts(l),(n=a+(parseInt(l.rowspan)||1)) td:hover > .layui-table-cell{overflow: auto;}"].concat(b.ie?[".layui-table-edit{height: "+i+";}","td[data-edit]:hover:after{height: "+i+";}"]:[]),function(e,t){t&&o.push(a+" "+t)})),l.css&&o.push(l.css),r.style({target:this.elem[0],text:o.join(""),id:"DF-table-"+n})},i.prototype.renderToolbar=function(){var e=this.config,t=['
                                                                                                    ','
                                                                                                    ','
                                                                                                    '].join(""),a=this.layTool.find(".layui-table-tool-temp"),i=("default"===e.toolbar?a.html(t):"string"==typeof e.toolbar&&(t=p(e.toolbar).html()||"")&&a.html(m(t).render(e)),{filter:{title:"\u7b5b\u9009\u5217",layEvent:"LAYTABLE_COLS",icon:"layui-icon-cols"},exports:{title:"\u5bfc\u51fa",layEvent:"LAYTABLE_EXPORT",icon:"layui-icon-export"},print:{title:"\u6253\u5370",layEvent:"LAYTABLE_PRINT",icon:"layui-icon-print"}}),l=[];"object"==typeof e.defaultToolbar&&layui.each(e.defaultToolbar,function(e,t){t="string"==typeof t?i[t]:t;t&&l.push('
                                                                                                    ')}),this.layTool.find(".layui-table-tool-self").html(l.join(""))},i.prototype.renderPagebar=function(){var e,t=this.config,a=this.layPagebar=p('
                                                                                                    ');t.pagebar&&((e=p(t.pagebar).html()||"")&&a.append(m(e).render(t)),this.layPage.append(a))},i.prototype.setParentCol=function(e,t){var a=this.config,i=this.layHeader.find('th[data-key="'+t+'"]'),l=parseInt(i.attr("colspan"))||0;i[0]&&(t=t.split("-"),t=a.cols[t[1]][t[2]],e?l--:l++,i.attr("colspan",l),i[l?"removeClass":"addClass"](R),t.colspan2=l,t.hide=l<1,a=i.data("parentkey"))&&this.setParentCol(e,a)},i.prototype.setColsPatch=function(){var a=this,e=a.config;layui.each(e.cols,function(e,t){layui.each(t,function(e,t){t.hide&&a.setParentCol(t.hide,t.parentKey)})})},i.prototype.setGroupWidth=function(i){var e,l=this;l.config.cols.length<=1||((e=l.layHeader.find((i?"th[data-key="+i.data("parentkey")+"]>":"")+"."+P)).css("width",0),layui.each(e.get().reverse(),function(){var e=p(this),t=e.parent().data("key"),a=0;l.layHeader.eq(0).find("th[data-parentkey="+t+"]").width(function(e,t){p(this).hasClass(R)||0 tr:first-child > th:last-child")).data("field")&&e.prev()[0]?t(e.prev()):e})()).data("key"),n.cssRules(e,function(e){var t=e.style.width||a.outerWidth();e.style.width=parseFloat(t)+l+"px",0'+(e||"Error")+"
                                                                                                    ");a[0]&&(t.layNone.remove(),a.remove()),t.layFixed.addClass(R),t.layMain.find("tbody").html(""),t.layMain.append(t.layNone=e),t.layTotal.addClass(y),t.layPage.find(I).addClass(y),k.cache[t.key]=[],t.syncCheckAll(),t.renderForm(),t.setColsWidth()},i.prototype.page=1,i.prototype.pullData=function(a,t){var e,i,l=this,n=l.config,o=(n.HAS_SET_COLS_PATCH||l.setColsPatch(),n.HAS_SET_COLS_PATCH=!0,n.request),d=n.response,r=function(){"object"==typeof n.initSort&&l.sort({field:n.initSort.field,type:n.initSort.type,reloadType:t.type})},c=function(e,t){l.setColsWidth(),"function"==typeof n.done&&n.done(e,a,e[d.countName],t)};t=t||{},"function"==typeof n.before&&n.before(n),l.startTime=(new Date).getTime(),t.renderData?((e={})[d.dataName]=k.cache[l.key],e[d.countName]=n.url?"object"===layui.type(n.page)?n.page.count:e[d.dataName].length:n.data.length,"object"==typeof n.totalRow&&(e[d.totalRowName]=p.extend({},l.totalRow)),l.renderData({res:e,curr:a,count:e[d.countName],type:t.type,sort:!0}),c(e,"renderData")):n.url?(i={},n.page&&(i[o.pageName]=a,i[o.limitName]=n.limit),o=p.extend(i,n.where),n.contentType&&0==n.contentType.indexOf("application/json")&&(o=JSON.stringify(o)),l.loading(),p.ajax({type:n.method||"get",url:n.url,contentType:n.contentType,data:o,dataType:n.dataType||"json",jsonpCallback:n.jsonpCallback,headers:n.headers||{},complete:"function"==typeof n.complete?n.complete:undefined,success:function(e){(e="function"==typeof n.parseData?n.parseData(e)||e:e)[d.statusName]!=d.statusCode?l.errorView(e[d.msgName]||'\u8fd4\u56de\u7684\u6570\u636e\u4e0d\u7b26\u5408\u89c4\u8303\uff0c\u6b63\u786e\u7684\u6210\u529f\u72b6\u6001\u7801\u5e94\u4e3a\uff1a"'+d.statusName+'": '+d.statusCode):(l.totalRow=e[d.totalRowName],l.renderData({res:e,curr:a,count:e[d.countName],type:t.type}),r(),n.time=(new Date).getTime()-l.startTime+" ms"),c(e)},error:function(e,t){l.errorView("\u8bf7\u6c42\u5f02\u5e38\uff0c\u9519\u8bef\u63d0\u793a\uff1a"+t),"function"==typeof n.error&&n.error(e,t)}})):"array"===layui.type(n.data)&&(e={},i=a*n.limit-n.limit,o=n.data.concat(),e[d.dataName]=n.page?o.splice(i,n.limit):o,e[d.countName]=n.data.length,"object"==typeof n.totalRow&&(e[d.totalRowName]=p.extend({},n.totalRow)),l.totalRow=e[d.totalRowName],l.renderData({res:e,curr:a,count:e[d.countName],type:t.type}),r(),c(e))},i.prototype.eachCols=function(e){return k.eachCols(null,e,this.config.cols),this},i.prototype.col=function(e){try{return e=e.split("-"),this.config.cols[e[1]][e[2]]||{}}catch(t){return x.error(t),{}}},i.prototype.getTrHtml=function(a,l,n,e){var s=this,u=s.config,y=e&&e.trs||[],h=e&&e.trs_fixed||[],f=e&&e.trs_fixed_r||[];return n=n||1,layui.each(a,function(e,o){var i=[],d=[],r=[],c=e+u.limit*(n-1)+1;if("object"!=typeof o){a[e]=o={LAY_KEY:o};try{k.cache[s.key][e]=o}catch(t){}}"array"===layui.type(o)&&0===o.length||(o[k.config.numbersName]=c,l||(o[k.config.indexName]=e),s.eachCols(function(e,l){var t,e=l.field||e,a=l.key,n=o[e];n!==undefined&&null!==n||(n=""),l.colGroup||(e=['','
                                                                                                    "+function(){var e,t=p.extend(!0,{LAY_COL:l},o),a=k.config.checkName,i=k.config.disabledName;switch(l.type){case"checkbox":return'';case"radio":return'';case"numbers":return c}return l.toolbar?m(p(l.toolbar).html()||"").render(t):T.call(s,{item3:l,content:n,tplData:t})}(),"
                                                                                                    "].join(""),i.push(e),l.fixed&&"right"!==l.fixed&&d.push(e),"right"===l.fixed&&r.push(e))}),e=['data-index="'+e+'"'],o[k.config.checkName]&&e.push('class="'+E+'"'),e=e.join(" "),y.push(""+i.join("")+""),h.push(""+d.join("")+""),f.push(""+r.join("")+""))}),{trs:y,trs_fixed:h,trs_fixed_r:f}},k.getTrHtml=function(e,t){e=C(e);return e.getTrHtml(t,null,e.page)},i.prototype.renderData=function(e){var a=this,i=a.config,t=e.res,l=e.curr,n=a.count=e.count,o=e.sort,d=t[i.response.dataName]||[],t=t[i.response.totalRowName],r=[],c=[],s=[],u=function(){if(!o&&a.sortKey)return a.sort({field:a.sortKey.field,type:a.sortKey.sort,pull:!0,reloadType:e.type});a.getTrHtml(d,o,l,{trs:r,trs_fixed:c,trs_fixed_r:s}),"fixed"===i.scrollPos&&"reloadData"===e.type||a.layBody.scrollTop(0),"reset"===i.scrollPos&&a.layBody.scrollLeft(0),a.layMain.find("."+h).remove(),a.layMain.find("tbody").html(r.join("")),a.layFixLeft.find("tbody").html(c.join("")),a.layFixRight.find("tbody").html(s.join("")),a.syncCheckAll(),a.renderForm(),a.fullSize(),a.haveInit?a.scrollPatch():setTimeout(function(){a.scrollPatch()},50),a.haveInit=!0,f.close(a.tipsIndex)};return k.cache[a.key]=d,a.layTotal[0==d.length?"addClass":"removeClass"](y),a.layPage[i.page||i.pagebar?"removeClass":"addClass"](R),a.layPage.find(I)[!i.page||0==n||0===d.length&&1==l?"addClass":"removeClass"](y),0===d.length?a.errorView(i.text.none):(a.layFixLeft.removeClass(R),o?u():(u(),a.renderTotal(d,t),a.layTotal&&a.layTotal.removeClass(R),void(i.page&&(i.page=p.extend({elem:"layui-table-page"+i.index,count:n,limit:i.limit,limits:i.limits||[10,20,30,40,50,60,70,80,90],groups:3,layout:["prev","page","next","skip","count","limit"],prev:'',next:'',jump:function(e,t){t||(a.page=e.curr,i.limit=e.limit,a.pullData(e.curr))}},i.page),i.page.count=n,O.render(i.page)))))},k.renderData=function(e){e=C(e);e&&e.pullData(e.page,{renderData:!0,type:"reloadData"})},i.prototype.renderTotal=function(e,o){var d,r=this,c=r.config,s={};c.totalRow&&(layui.each(e,function(e,i){"array"===layui.type(i)&&0===i.length||r.eachCols(function(e,t){var e=t.field||e,a=i[e];t.totalRow&&(s[e]=(s[e]||0)+(parseFloat(a)||0))})}),r.dataTotal=[],d=[],r.eachCols(function(e,t){var a,e=t.field||e,i=o&&o[t.field],l="totalRowDecimals"in t?t.totalRowDecimals:2,l=s[e]?parseFloat(s[e]||0).toFixed(l):"",l=(a=t.totalRowText||"",(n={LAY_COL:t})[e]=l,n=t.totalRow&&T.call(r,{item3:t,content:l,tplData:n})||a,i||n),n=(t.field&&r.dataTotal.push({field:t.field,total:p("
                                                                                                    "+l+"
                                                                                                    ").text()}),['','
                                                                                                    "+("string"==typeof(a=t.totalRow||c.totalRow)?m(a).render(p.extend({TOTAL_NUMS:i||s[e],TOTAL_ROW:o||{},LAY_COL:t},t)):l),"
                                                                                                    "].join(""));d.push(n)}),e=r.layTotal.find(".layui-table-patch"),r.layTotal.find("tbody").html(""+d.join("")+(e.length?e.get(0).outerHTML:"")+""))},i.prototype.getColElem=function(e,t){return e.eq(0).find(".laytable-cell-"+t+":eq(0)")},i.prototype.renderForm=function(e){this.config;var t=this.elem.attr("lay-filter");v.render(e,t)},i.prototype.syncCheckAll=function(){var a,e=this,i=e.config,t=e.layHeader.find('input[name="layTableCheckbox"]'),l=k.checkStatus(e.key);t[0]&&(a=l.isAll,e.eachCols(function(e,t){"checkbox"===t.type&&(t[i.checkName]=a)}),t.prop({checked:l.isAll,indeterminate:!l.isAll&&l.data.length}),v.render(t))},i.prototype.setRowActive=function(e,t,a){this.config;e=this.layBody.find('tr[data-index="'+e+'"]');if(t=t||"layui-table-click",a)return e.removeClass(t);e.addClass(t),e.siblings("tr").removeClass(t)},i.prototype.setRowChecked=function(i){var e=this,l=e.config,n="all"===i.index,o="array"===layui.type(i.index),d=(t=e.layBody.find("tr"),n?t:t.filter(o?function(){var e=p(this).data("index");return-1!==i.index.indexOf(e)}:'[data-index="'+i.index+'"]')),t=(i=p.extend({type:"checkbox"},i),k.cache[e.key]),a="checked"in i,r=function(e){return"radio"===i.type||(a?i.checked:!e)},t=(layui.each(t,function(e,t){var a;"array"===layui.type(t)||t[l.disabledName]||(n||(o?-1!==i.index.indexOf(e):Number(i.index)===e)?(a=t[l.checkName]=r(t[l.checkName]),(e=d.filter('[data-index="'+e+'"]'))[a?"addClass":"removeClass"](E),"radio"===i.type&&e.siblings().removeClass(E)):"radio"===i.type&&delete t[l.checkName])}),d.find('input[lay-type="'+({radio:"layTableRadio",checkbox:"layTableCheckbox"}[i.type]||"checkbox")+'"]:not(:disabled)')),c=t.last(),s=c.closest(u);("radio"===i.type&&s.hasClass(R)?t.first():t).prop("checked",r(c.prop("checked"))),e.syncCheckAll(),e.renderForm(i.type)},i.prototype.sort=function(l){var e,t=this,a={},i=t.config,n=i.elem.attr("lay-filter"),o=k.cache[t.key];"string"==typeof(l=l||{}).field&&(d=l.field,t.layHeader.find("th").each(function(e,t){var a=p(this),i=a.data("field");if(i===l.field)return l.field=a,d=i,!1}));try{var d=d||l.field.data("field"),r=l.field.data("key");if(t.sortKey&&!l.pull&&d===t.sortKey.field&&l.type===t.sortKey.sort)return;var c=t.layHeader.find("th .laytable-cell-"+r).find(A);t.layHeader.find("th").find(A).removeAttr("lay-sort"),c.attr("lay-sort",l.type||null),t.layFixed.find("th")}catch(s){x.error("Table modules: sort field '"+d+"' not matched")}t.sortKey={field:d,sort:l.type},i.autoSort&&("asc"===l.type?e=layui.sort(o,d,null,!0):"desc"===l.type?e=layui.sort(o,d,!0,!0):(e=layui.sort(o,k.config.indexName,null,!0),delete t.sortKey,delete i.initSort)),a[i.response.dataName]=e||o,t.renderData({res:a,curr:t.page,count:t.count,sort:!0,type:l.reloadType}),l.fromEvent&&(i.initSort={field:d,type:l.type},layui.event.call(l.field,N,"sort("+n+")",p.extend({config:i},i.initSort)))},i.prototype.loading=function(e){var t=this;t.config.loading&&(e?(t.layInit&&t.layInit.remove(),delete t.layInit,t.layBox.find(".layui-table-init").remove()):(t.layInit=p(['
                                                                                                    ','',"
                                                                                                    "].join("")),t.layBox.append(t.layInit)))},i.prototype.cssRules=function(t,a){var e=this.elem.children("style")[0];r.getStyleRules(e,function(e){if(e.selectorText===".laytable-cell-"+t)return a(e),!0})},i.prototype.fullSize=function(){var e,a,i=this,t=i.config,l=t.height;i.fullHeightGap?(l=d.height()-i.fullHeightGap)<135&&(l=135):i.parentDiv&&i.parentHeightGap?(l=p(i.parentDiv).height()-i.parentHeightGap)<135&&(l=135):i.customHeightFunc&&(l=i.customHeightFunc())<135&&(l=135),1
                                                                                                    ')).find("div").css({width:a}),e.find("tr").append(t)):e.find(".layui-table-patch").remove()};n(e.layHeader),n(e.layTotal);n=e.layMain.height()-i;e.layFixed.find(L).css("height",t.height()>=n?n:"auto").scrollTop(e.layMain.scrollTop()),e.layFixRight[k.cache[e.key]&&k.cache[e.key].length&&0');a.html(t),u.height&&a.css("max-height",u.height-(s.layTool.outerHeight()||50)),i.find("."+j)[0]||i.append(a),s.renderForm(),a.on("click",function(e){layui.stope(e)}),e.done&&e.done(a,t)};switch(layui.stope(e),F.trigger("table.tool.panel.remove"),f.close(s.tipsIndex),t){case"LAYTABLE_COLS":n({list:(a=[],s.eachCols(function(e,t){t.field&&"normal"==t.type&&a.push('
                                                                                                  • "+(t.fieldTitle||t.title||t.field)+"
                                                                                                  • ").text())+'" lay-filter="LAY_TABLE_TOOL_COLS">')}),a.join("")),done:function(){v.on("checkbox(LAY_TABLE_TOOL_COLS)",function(e){var e=p(e.elem),t=this.checked,a=e.data("key"),i=s.col(a),l=i.hide,e=e.data("parentkey");i.key&&(i.hide=!t,s.elem.find('*[data-key="'+a+'"]')[t?"removeClass":"addClass"](R),l!=i.hide&&s.setParentCol(!t,e),s.resize(),layui.event.call(this,N,"colToggled("+c+")",{col:i,config:u}))})}});break;case"LAYTABLE_EXPORT":if(!l.length)return f.tips("\u5f53\u524d\u8868\u683c\u65e0\u6570\u636e",this,{tips:3});b.ie?f.tips("\u5bfc\u51fa\u529f\u80fd\u4e0d\u652f\u6301 IE\uff0c\u8bf7\u7528 Chrome \u7b49\u9ad8\u7ea7\u6d4f\u89c8\u5668\u5bfc\u51fa",this,{tips:3}):n({list:['
                                                                                                  • \u5bfc\u51fa csv \u683c\u5f0f\u6587\u4ef6
                                                                                                  • ','
                                                                                                  • \u5bfc\u51fa xls \u683c\u5f0f\u6587\u4ef6
                                                                                                  • '].join(""),done:function(e,t){t.on("click",function(){var e=p(this).data("type");k.exportFile.call(s,u.id,null,e)})}});break;case"LAYTABLE_PRINT":if(!l.length)return f.tips("\u5f53\u524d\u8868\u683c\u65e0\u6570\u636e",this,{tips:3});var o=window.open("about:blank","_blank"),d=[""].join(""),r=p(s.layHeader.html());r.append(s.layMain.find("table").html()),r.append(s.layTotal.find("table").html()),r.find("th.layui-table-patch").remove(),r.find("thead>tr>th."+W).filter(function(e,t){return!p(t).children("."+P).length}).remove(),r.find("tbody>tr>td."+W).remove(),o.document.write(d+r.prop("outerHTML")),o.document.close(),layui.device("edg").edg?(o.onafterprint=o.close,o.print()):(o.print(),o.close())}layui.event.call(this,N,"toolbar("+c+")",p.extend({event:t,config:u},{}))}),s.layHeader.on("click","*[lay-event]",function(e){var t=p(this),a=t.attr("lay-event"),t=t.closest("th").data("key"),t=s.col(t);layui.event.call(this,N,"colTool("+c+")",p.extend({event:a,config:u,col:t},{}))}),s.layPagebar.on("click","*[lay-event]",function(e){var t=p(this).attr("lay-event");layui.event.call(this,N,"pagebar("+c+")",p.extend({event:t,config:u},{}))}),e.on("mousemove",function(e){var t=p(this),a=t.offset().left,e=e.clientX-a;t.data("unresize")||w.eventMoveElem||(d.allowResize=t.width()-e<=10,o.css("cursor",d.allowResize?"col-resize":""))}).on("mouseleave",function(){p(this);w.eventMoveElem||o.css("cursor","")}).on("mousedown",function(e){var t,a=p(this);d.allowResize&&(t=a.data("key"),e.preventDefault(),d.offset=[e.clientX,e.clientY],s.cssRules(t,function(e){var t=e.style.width||a.outerWidth();d.rule=e,d.ruleWidth=parseFloat(t),d.minWidth=a.data("minwidth")||u.cellMinWidth,d.maxWidth=a.data("maxwidth")||u.cellMaxWidth}),a.data(S,d),w.eventMoveElem=a)}),w.docEvent||F.on("mousemove",function(e){var t,a;w.eventMoveElem&&(t=w.eventMoveElem.data(S)||{},w.eventMoveElem.data("resizing",1),e.preventDefault(),t.rule)&&(e=t.ruleWidth+e.clientX-t.offset[0],a=w.eventMoveElem.closest("."+D).attr("lay-id"),a=C(a))&&((e=et.maxWidth&&(e=t.maxWidth),t.rule.style.width=e+"px",a.setGroupWidth(w.eventMoveElem),f.close(s.tipsIndex))}).on("mouseup",function(e){var t,a,i,l,n;w.eventMoveElem&&(i=(t=w.eventMoveElem).closest("."+D).attr("lay-id"),a=C(i))&&(i=t.data("key"),l=a.col(i),n=a.config.elem.attr("lay-filter"),d={},o.css("cursor",""),a.scrollPatch(),t.removeData(S),delete w.eventMoveElem,a.cssRules(i,function(e){l.width=parseFloat(e.style.width),layui.event.call(t[0],N,"colResized("+n+")",{col:l,config:a.config})}))}),w.docEvent=!0,e.on("click",function(e){var t=p(this),a=t.find(A),i=a.attr("lay-sort");if(!a[0]||1===t.data("resizing"))return t.removeData("resizing");s.sort({field:t,type:"asc"===i?"desc":"desc"===i?null:"asc",fromEvent:!0})}).find(A+" .layui-edge ").on("click",function(e){var t=p(this),a=t.index(),t=t.parents("th").eq(0).data("field");layui.stope(e),0===a?s.sort({field:t,type:"asc",fromEvent:!0}):s.sort({field:t,type:"desc",fromEvent:!0})}),s.commonMember=function(e){var t=p(this).parents("tr").eq(0).data("index"),r=s.layBody.find('tr[data-index="'+t+'"]'),c=(c=k.cache[s.key]||[])[t]||{},a={tr:r,config:u,data:k.clearCacheKey(c),dataCache:c,index:t,del:function(){k.cache[s.key][t]=[],r.remove(),s.scrollPatch()},update:function(e,d){e=e||{},layui.each(e,function(i,l){var n=r.children('td[data-field="'+i+'"]'),o=n.children(y);c[i]=a.data[i]=l,s.eachCols(function(e,t){var a;t.field==i?(o.html(T.call(s,{item3:t,content:l,tplData:p.extend({LAY_COL:t},c)})),n.data("content",l)):d&&(t.templet||t.toolbar)&&(e=r.children('td[data-field="'+(t.field||e)+'"]'),a=c[t.field],e.children(y).html(T.call(s,{item3:t,content:a,tplData:p.extend({LAY_COL:t},c)})),e.data("content",a))})}),s.renderForm()},setRowChecked:function(e){s.setRowChecked(p.extend({index:t},e))}};return p.extend(a,e)}),a=(s.elem.on("click",'input[name="layTableCheckbox"]+',function(e){var t=p(this),a=t.closest("td"),t=t.prev(),i=(s.layBody.find('input[name="layTableCheckbox"]'),t.parents("tr").eq(0).data("index")),l=t[0].checked,n="layTableAllChoose"===t.attr("lay-filter");t[0].disabled||(n?s.setRowChecked({index:"all",checked:l}):(s.setRowChecked({index:i,checked:l}),layui.stope(e)),layui.event.call(t[0],N,"checkbox("+c+")",r.call(t[0],{checked:l,type:n?"all":"one",getCol:function(){return s.col(a.data("key"))}})))}),s.elem.on("click",'input[lay-type="layTableRadio"]+',function(e){var t=p(this),a=t.closest("td"),t=t.prev(),i=t[0].checked,l=t.parents("tr").eq(0).data("index");if(layui.stope(e),t[0].disabled)return!1;s.setRowChecked({type:"radio",index:l}),layui.event.call(t[0],N,"radio("+c+")",r.call(t[0],{checked:i,getCol:function(){return s.col(a.data("key"))}}))}),s.layBody.on("mouseenter","tr",function(){var e=p(this),t=e.index();e.data("off")||s.layBody.find("tr:eq("+t+")").addClass(M)}).on("mouseleave","tr",function(){var e=p(this),t=e.index();e.data("off")||s.layBody.find("tr:eq("+t+")").removeClass(M)}).on("click","tr",function(e){var t=[".layui-form-checkbox",".layui-form-switch",".layui-form-radio","[lay-unrow]"].join(",");p(e.target).is(t)||p(e.target).closest(t)[0]||a.call(this,"row")}).on("dblclick","tr",function(){a.call(this,"rowDouble")}).on("contextmenu","tr",function(e){u.defaultContextmenu||e.preventDefault(),a.call(this,"rowContextmenu")}),function(e){var t=p(this);t.data("off")||layui.event.call(this,N,e+"("+c+")",r.call(t.children("td")[0]))}),n=function(e,t){var a,i,l;(e=p(e)).data("off")||(l=e.data("field"),i=e.data("key"),i=s.col(i),a=e.closest("tr").data("index"),a=k.cache[s.key][a],e.children(y),(i="function"==typeof i.edit?i.edit(a):i.edit)&&((i=p("textarea"===i?'':''))[0].value=(l=e.data("content")||a[l])===undefined||null===l?"":l,e.find("."+_)[0]||e.append(i),i.focus(),t)&&layui.stope(t))},i=(s.layBody.on("change","."+_,function(){var e=p(this),t=e.parent(),a=this.value,i=e.parent().data("field"),e=e.closest("tr").data("index"),e=k.cache[s.key][e],l=r.call(t[0],{value:a,field:i,oldValue:e[i],td:t,reedit:function(){setTimeout(function(){n(l.td);var e={};e[i]=l.oldValue,l.update(e)})},getCol:function(){return s.col(t.data("key"))}}),e={};e[i]=a,l.update(e),layui.event.call(t[0],N,"edit("+c+")",l)}).on("blur","."+_,function(){p(this).remove()}),s.layBody.on(u.editTrigger,"td",function(e){n(this,e)}).on("mouseenter","td",function(){t.call(this)}).on("mouseleave","td",function(){t.call(this,"hide")}),s.layTotal.on("mouseenter","td",function(){t.call(this)}).on("mouseleave","td",function(){t.call(this,"hide")}),"layui-table-grid-down"),t=function(e){var t=p(this),a=t.children(y);t.data("off")||t.parent().hasClass(H)||(e?t.find(".layui-table-grid-down").remove():!(a.prop("scrollWidth")>a.outerWidth()||0'))},l=function(e,t){var a=p(this),i=a.parent(),l=i.data("key"),n=s.col(l),o=i.parent().data("index"),i=i.children(y),d="layui-table-cell-c",r=p('');"tips"===(t=t||n.expandedMode||u.cellExpandedMode)?s.tipsIndex=f.tips(['
                                                                                                    ',i.html(),"
                                                                                                    ",''].join(""),i[0],{tips:[3,""],time:-1,anim:-1,maxWidth:b.ios||b.android?300:s.elem.width()/2,isOutAnim:!1,skin:"layui-table-tips",success:function(e,t){e.find(".layui-table-tips-c").on("click",function(){f.close(t)})}}):(s.elem.find("."+d).trigger("click"),s.cssRules(l,function(e){var t=e.style.width,a=n.expandedWidth||u.cellExpandedWidth;atr").each(function(i){n.cols[i]=[],p(this).children().each(function(e){var t=p(this),a=t.attr("lay-data"),a=r.options(this,{attr:a?"lay-data":null,errorText:d+(a||t.attr("lay-options"))}),t=p.extend({title:t.text(),colspan:parseInt(t.attr("colspan"))||1,rowspan:parseInt(t.attr("rowspan"))||1},a);n.cols[i].push(t)})}),e.find("tbody>tr")),t=k.render(n);!a.length||o.data||t.config.url||(l=0,k.eachCols(t.config.id,function(e,i){a.each(function(e){n.data[e]=n.data[e]||{};var t=p(this),a=i.field;n.data[e][a]=t.children("td").eq(l).html()}),l++}),t.reloadData({data:n.data}))}),this},w.that={},w.config={},function(a,i,e,l){var n,o;l.colGroup&&(n=0,a++,l.CHILD_COLS=[],o=e+(parseInt(l.rowspan)||1),layui.each(i[o],function(e,t){t.parentKey?t.parentKey===l.key&&(t.PARENT_COL_INDEX=a,l.CHILD_COLS.push(t),c(a,i,o,t)):t.PARENT_COL_INDEX||1<=n&&n==(l.colspan||1)||(t.PARENT_COL_INDEX=a,l.CHILD_COLS.push(t),n+=parseInt(1td').filter('[data-field="'+e+'"]')}}})).replace(/"/g,'""'),n.push(a='"'+a+'"')))}),d.push(n.join(","))}),c&&layui.each(c.dataTotal,function(e,t){r[t.field]||i.push('"'+(t.total||"")+'"')}),o.join(",")+"\r\n"+d.join("\r\n")+"\r\n"+i.join(","))),u.download=(a.title||n.title||"table_"+(n.index||""))+"."+l,document.body.appendChild(u),u.click(),document.body.removeChild(u)},k.getOptions=l,k.hideCol=function(e,l){var n=C(e);n&&("boolean"===layui.type(l)?n.eachCols(function(e,t){var a=t.key,i=n.col(a),t=t.parentKey;i.hide!=l&&(i=i.hide=l,n.elem.find('*[data-key="'+a+'"]')[i?"addClass":"removeClass"](R),n.setParentCol(i,t))}):(l=layui.isArray(l)?l:[l],layui.each(l,function(e,l){n.eachCols(function(e,t){var a,i;l.field===t.field&&(a=t.key,i=n.col(a),t=t.parentKey,"hide"in l)&&i.hide!=l.hide&&(i=i.hide=!!l.hide,n.elem.find('*[data-key="'+a+'"]')[i?"addClass":"removeClass"](R),n.setParentCol(i,t))})})),p("."+j).remove(),n.resize())},k.reload=function(e,t,a,i){if(l(e))return(e=C(e)).reload(t,a,i),w.call(e)},k.reloadData=function(){var a=p.extend([],arguments),i=(a[3]="reloadData",new RegExp("^("+["elem","id","cols","width","height","maxHeight","toolbar","defaultToolbar","className","css","pagebar"].join("|")+")$"));return layui.each(a[1],function(e,t){i.test(e)&&delete a[1][e]}),k.reload.apply(null,a)},k.render=function(e){e=new i(e);return w.call(e)},k.clearCacheKey=function(e){return delete(e=p.extend({},e))[k.config.checkName],delete e[k.config.indexName],delete e[k.config.numbersName],delete e[k.config.disabledName],e},p(function(){k.init()}),n(N,k)});layui.define(["table"],function(e){"use strict";var E=layui.$,x=layui.form,B=layui.table,y=layui.hint(),j={config:{},on:B.on,eachCols:B.eachCols,index:B.index,set:function(e){var t=this;return t.config=E.extend({},t.config,e),t},resize:B.resize,getOptions:B.getOptions,hideCol:B.hideCol,renderData:B.renderData},i=function(){var a=this,e=a.config,n=e.id||e.index;return{config:e,reload:function(e,t){a.reload.call(a,e,t)},reloadData:function(e,t){j.reloadData(n,e,t)}}},P=function(e){var t=i.that[e];return t||y.error(e?"The treeTable instance with ID '"+e+"' not found":"ID argument required"),t||null},F="layui-hide",L=".layui-table-main",q=".layui-table-fixed-l",R=".layui-table-fixed-r",l="layui-table-checked",h="layui-table-tree",Y="LAY_DATA_INDEX",m="LAY_DATA_INDEX_HISTORY",s="LAY_PARENT_INDEX",b="LAY_CHECKBOX_HALF",H="LAY_EXPAND",z="LAY_HAS_EXPANDED",X="LAY_ASYNC_STATUS",n=["all","parent","children","none"],t=function(e){var t=this;t.index=++j.index,t.config=E.extend(!0,{},t.config,j.config,e),t.init(),t.render()},f=function(n,i,e){var l=B.cache[n];layui.each(e||l,function(e,t){var a=t[Y]||"";-1!==a.indexOf("-")&&(l[a]=t),t[i]&&f(n,i,t[i])})},d=function(l,a,e){var d=P(l),r=("reloadData"!==e&&(d.status={expand:{}}),E.extend(!0,{},d.getOptions(),a)),n=r.tree,o=n.customName.children,i=n.customName.id,c=(delete a.hasNumberCol,delete a.hasChecboxCol,delete a.hasRadioCol,B.eachCols(null,function(e,t){"numbers"===t.type?a.hasNumberCol=!0:"checkbox"===t.type?a.hasChecboxCol=!0:"radio"===t.type&&(a.hasRadioCol=!0)},r.cols),a.parseData),u=a.done;r.url?e&&(!c||c.mod)||(a.parseData=function(){var e=this,t=arguments,a=t[0],t=("function"===layui.type(c)&&(a=c.apply(e,t)||t[0]),e.response.dataName);return n.data.isSimpleData&&!n["async"].enable&&(a[t]=d.flatToTree(a[t])),p(a[t],function(e){e[H]=H in e?e[H]:e[i]!==undefined&&d.status.expand[e[i]]},o),e.autoSort&&e.initSort&&e.initSort.type&&layui.sort(a[t],e.initSort.field,"desc"===e.initSort.type,!0),d.initData(a[t]),a},a.parseData.mod=!0):(a.data=a.data||[],n.data.isSimpleData&&(a.data=d.flatToTree(a.data)),d.initData(a.data)),e&&(!u||u.mod)||(a.done=function(){var e,t=arguments,a=t[3],n=(a||delete d.isExpandAll,this.elem.next()),i=(d.updateStatus(null,{LAY_HAS_EXPANDED:!1}),f(l,o),n.find('[name="layTableCheckbox"][lay-filter="layTableAllChoose"]'));if(i.length&&(e=j.checkStatus(l),i.prop({checked:e.isAll&&e.data.length,indeterminate:!e.isAll&&e.data.length})),!a&&r.autoSort&&r.initSort&&r.initSort.type&&j.sort(l),d.renderTreeTable(n),"function"===layui.type(u))return u.apply(this,t)},a.done.mod=!0)};t.prototype.init=function(){var e=this.config,t=e.tree.data.cascade,t=(-1===n.indexOf(t)&&(e.tree.data.cascade="all"),B.render(E.extend({},e,{data:[],url:"",done:null}))),a=t.config.id;(i.that[a]=this).tableIns=t,d(a,e)},t.prototype.config={tree:{customName:{children:"children",isParent:"isParent",name:"name",id:"id",pid:"parentId",icon:"icon"},view:{indent:14,flexIconClose:'',flexIconOpen:'',showIcon:!0,icon:"",iconClose:'',iconOpen:'',iconLeaf:'',showFlexIconIfNotParent:!1,dblClickExpand:!0,expandAllDefault:!1},data:{isSimpleData:!1,rootPid:null,cascade:"all"},"async":{enable:!1,url:"",type:null,contentType:null,headers:null,where:null,autoParam:[]},callback:{beforeExpand:null,onExpand:null}}},t.prototype.getOptions=function(){return this.tableIns?B.getOptions(this.tableIns.config.id):this.config},t.prototype.flatToTree=function(e){var a,n,i,t,l,d,r,o=this.getOptions(),c=o.tree,u=c.customName,o=o.id;return e=e||B.cache[o],o=e,a=u.id,n=u.pid,i=u.children,t=c.data.rootPid,a=a||"id",n=n||"parentId",i=i||"children",r={},layui.each(o,function(e,t){l=a+t[a],r[l]=E.extend({},t),r[l][i]=[]}),layui.each(r,function(e,t){(d=a+t[n])&&r[d]&&r[d][i].push(t)}),Object.keys(r).map(function(e){return r[e]}).filter(function(e){return t?e[n]===t:!e[n]})},t.prototype.treeToFlat=function(e,n,i){var l=this,d=l.getOptions().tree.customName,r=d.children,o=d.pid,c=[];return layui.each(e,function(e,t){var e=(i?i+"-":"")+e,a=E.extend({},t);a[o]=t[o]||n,c.push(a),c=c.concat(l.treeToFlat(t[r],t[d.id],e))}),c},t.prototype.getTreeNode=function(e){var t,a,n=this;return e?(a=(t=n.getOptions()).tree,t.id,a.customName,{data:e,dataIndex:e[Y],getParentNode:function(){return n.getNodeByIndex(e[s])}}):y.error("\u627e\u4e0d\u5230\u8282\u70b9\u6570\u636e")},t.prototype.getNodeByIndex=function(t){var a,e,n=this,i=n.getNodeDataByIndex(t);return i?((e=n.getOptions()).tree.customName.parent,a=e.id,(e={data:i,dataIndex:i[Y],getParentNode:function(){return n.getNodeByIndex(i[s])},update:function(e){return j.updateNode(a,t,e)},remove:function(){return j.removeNode(a,t)},expand:function(e){return j.expandNode(a,E.extend({},e,{index:t}))},setChecked:function(e){return j.setRowChecked(a,E.extend({},e,{index:t}))}}).dataIndex=t,e):y.error("\u627e\u4e0d\u5230\u8282\u70b9\u6570\u636e")},t.prototype.getNodeById=function(a){var e=this.getOptions(),n=e.tree.customName.id,i="",e=j.getData(e.id,!0);if(layui.each(e,function(e,t){if(t[n]===a)return i=t[Y],!0}),i)return this.getNodeByIndex(i)},t.prototype.getNodeDataByIndex=function(e,t,a){var n=this.getOptions(),i=n.tree,n=n.id,n=B.cache[n],l=n[e];if("delete"!==a&&l)return E.extend(l,a),t?E.extend({},l):l;for(var d=n,r=String(e).split("-"),o=0,c=i.customName.children;o
                                                                                                    '),N=function(e){y[X]="success",y[s.children]=e,c.initData(y[s.children],y[Y]),U(t,!0,!p&&n,i,l)},C=m.format,"function"===layui.type(C)?C(y,o,N):(I=E.extend({},m.where||o.where),C=m.autoParam,layui.each(C,function(e,t){t=t.split("=");I[t[0].trim()]=y[(t[1]||t[0]).trim()]}),(C=m.contentType||o.contentType)&&0==C.indexOf("application/json")&&(I=JSON.stringify(I)),w=m.method||o.method,D=m.dataType||o.dataType,T=m.jsonpCallback||o.jsonpCallback,k=m.headers||o.headers,_=m.parseData||o.parseData,O=m.response||o.response,E.ajax({type:w||"get",url:b,contentType:C,data:I,dataType:D||"json",jsonpCallback:T,headers:k||{},success:function(e){(e="function"==typeof _?_.call(o,e)||e:e)[O.statusName]!=O.statusCode?(y[X]="error",g.html('')):N(e[O.dataName])},error:function(e,t){y[X]="error","function"==typeof o.error&&o.error(e,t)}})),h;y[z]=!0,v.length&&(!o.initSort||o.url&&!o.autoSort||((m=o.initSort).type?layui.sort(v,m.field,"desc"===m.type,!0):layui.sort(v,B.config.indexName,null,!0)),c.initData(y[s.children],y[Y]),w=B.getTrHtml(r,v,null,null,e),S={trs:E(w.trs.join("")),trs_fixed:E(w.trs_fixed.join("")),trs_fixed_r:E(w.trs_fixed_r.join(""))},A=(e.split("-").length-1||0)+1,layui.each(v,function(e,t){S.trs.eq(e).attr({"data-index":t[Y],"lay-data-index":t[Y],"data-level":A}),S.trs_fixed.eq(e).attr({"data-index":t[Y],"lay-data-index":t[Y],"data-level":A}),S.trs_fixed_r.eq(e).attr({"data-index":t[Y],"lay-data-index":t[Y],"data-level":A})}),d.find(L).find('tbody tr[lay-data-index="'+e+'"]').after(S.trs),d.find(q).find('tbody tr[lay-data-index="'+e+'"]').after(S.trs_fixed),d.find(R).find('tbody tr[lay-data-index="'+e+'"]').after(S.trs_fixed_r),c.renderTreeTable(S.trs,A),n)&&!p&&layui.each(v,function(e,t){U({dataIndex:t[Y],trElem:d.find('tr[lay-data-index="'+t[Y]+'"]').first(),tableViewElem:d,tableId:r,options:o},a,n,i,l)})}else c.isExpandAll=!1,(n&&!p?(layui.each(v,function(e,t){U({dataIndex:t[Y],trElem:d.find('tr[lay-data-index="'+t[Y]+'"]').first(),tableViewElem:d,tableId:r,options:o},a,n,i,l)}),d.find(v.map(function(e,t,a){return'tr[lay-data-index="'+e[Y]+'"]'}).join(","))):(b=c.treeToFlat(v,y[s.id],e),d.find(b.map(function(e,t,a){return'tr[lay-data-index="'+e[Y]+'"]'}).join(",")))).addClass(F);V("resize-"+r,function(){j.resize(r)},0)(),l&&"loading"!==y[X]&&(C=u.callback.onExpand,"function"===layui.type(C))&&C(r,y,x)}return h},g=(j.expandNode=function(e,t){var a,n,i,e=P(e);if(e)return a=(t=t||{}).index,n=t.expandFlag,i=t.inherit,t=t.callbackFlag,e=e.getOptions().elem.next(),U({trElem:e.find('tr[lay-data-index="'+a+'"]').first()},n,i,null,t)},j.expandAll=function(a,e){if("boolean"!==layui.type(e))return y.error("expandAll \u7684\u5c55\u5f00\u72b6\u6001\u53c2\u6570\u53ea\u63a5\u6536true/false");var t=P(a);if(t){t.isExpandAll=e;var n=t.getOptions(),i=n.tree,l=n.elem.next(),d=i.customName.isParent,r=i.customName.id,o=i.view.showFlexIconIfNotParent;if(e){e=j.getData(a,!0);if(i["async"].enable){var c=!0;if(layui.each(e,function(e,t){if(t[d]&&!t[X])return!(c=!1)}),!c)return void layui.each(j.getData(a),function(e,t){j.expandNode(a,{index:t[Y],expandFlag:!0,inherit:!0})})}var u=!0;if(layui.each(e,function(e,t){if(t[d]&&!t[z])return!(u=!1)}),u)t.updateStatus(null,function(e){(e[d]||o)&&(e[H]=!0,e[r]!==undefined)&&(t.status.expand[e[r]]=!0)}),l.find('tbody tr[data-level!="0"]').removeClass(F),l.find(".layui-table-tree-flexIcon").html(i.view.flexIconOpen),i.view.showIcon&&l.find(".layui-table-tree-nodeIcon:not(.layui-table-tree-iconCustom,.layui-table-tree-iconLeaf)").html(i.view.iconOpen);else{if(t.updateStatus(null,function(e){(e[d]||o)&&(e[H]=!0,e[z]=!0,e[r]!==undefined)&&(t.status.expand[e[r]]=!0)}),n.initSort&&n.initSort.type&&n.autoSort)return j.sort(a);var s,n=B.getTrHtml(a,e),f={trs:E(n.trs.join("")),trs_fixed:E(n.trs_fixed.join("")),trs_fixed_r:E(n.trs_fixed_r.join(""))};layui.each(e,function(e,t){var a=t[Y].split("-").length-1;s={"data-index":t[Y],"lay-data-index":t[Y],"data-level":a},f.trs.eq(e).attr(s),f.trs_fixed.eq(e).attr(s),f.trs_fixed_r.eq(e).attr(s)}),layui.each(["main","fixed-l","fixed-r"],function(e,t){l.find(".layui-table-"+t+" tbody").html(f[["trs","trs_fixed","trs_fixed_r"][e]])}),t.renderTreeTable(l,0,!1)}}else t.updateStatus(null,function(e){(e[d]||o)&&(e[H]=!1,e[r]!==undefined)&&(t.status.expand[e[r]]=!1)}),l.find('.layui-table-box tbody tr[data-level!="0"]').addClass(F),l.find(".layui-table-tree-flexIcon").html(i.view.flexIconClose),i.view.showIcon&&l.find(".layui-table-tree-nodeIcon:not(.layui-table-tree-iconCustom,.layui-table-tree-iconLeaf)").html(i.view.iconClose);j.resize(a)}},t.prototype.renderTreeTable=function(e,t,a){var n=this,i=n.getOptions(),l=i.elem.next(),d=(l.hasClass(h)||l.addClass(h),i.id),r=i.tree||{},o=(r.data,r.view||{}),c=r.customName||{},u=c.isParent,s=(l.attr("lay-filter"),n),f=((t=t||0)||(l.find(".layui-table-body tr:not([data-level])").attr("data-level",t),layui.each(B.cache[d],function(e,t){l.find('.layui-table-main tbody tr[data-level="0"]:eq('+e+")").attr("lay-data-index",t[Y]),l.find('.layui-table-fixed-l tbody tr[data-level="0"]:eq('+e+")").attr("lay-data-index",t[Y]),l.find('.layui-table-fixed-r tbody tr[data-level="0"]:eq('+e+")").attr("lay-data-index",t[Y])})),null),y=c.name,p=o.indent||14;if(layui.each(e.find('td[data-field="'+y+'"]'),function(e,t){var a,n,i=(t=E(t)).closest("tr"),t=t.children(".layui-table-cell");t.hasClass("layui-table-tree-item")||(n=i.attr("lay-data-index"))&&(i=l.find('tr[lay-data-index="'+n+'"]'),(a=s.getNodeDataByIndex(n))[H]&&a[u]&&((f=f||{})[n]=!0),a[b]&&i.find('input[type="checkbox"][name="layTableCheckbox"]').prop("indeterminate",!0),n=t.html(),(t=i.find('td[data-field="'+y+'"]>div.layui-table-cell')).addClass("layui-table-tree-item"),t.html(['
                                                                                                    ',a[H]?o.flexIconOpen:o.flexIconClose,"
                                                                                                    ",o.showIcon?'
                                                                                                    '+(a[c.icon]||o.icon||(a[u]?a[H]?o.iconOpen:o.iconClose:o.iconLeaf)||"")+"
                                                                                                    ":"",n].join("")).find(".layui-table-tree-flexIcon").on("click",function(e){layui.stope(e),U({trElem:i},null,null,null,!0)}))}),!t&&r.view.expandAllDefault&&n.isExpandAll===undefined)return j.expandAll(d,!0);!1!==a&&f?layui.each(f,function(e,t){e=l.find('tr[lay-data-index="'+e+'"]');e.find(".layui-table-tree-flexIcon").html(o.flexIconOpen),U({trElem:e.first()},!0)}):V("renderTreeTable-"+d,function(){i.hasNumberCol&&g(n),x.render(E('.layui-table-tree[lay-id="'+d+'"]'))},0)()},function(a){var e=a.getOptions(),t=e.elem.next(),n=0,i=t.find(".layui-table-main tbody tr"),l=t.find(".layui-table-fixed-l tbody tr"),d=t.find(".layui-table-fixed-r tbody tr");layui.each(a.treeToFlat(B.cache[e.id]),function(e,t){t.LAY_HIDE||(a.getNodeDataByIndex(t[Y]).LAY_NUM=++n,i.eq(e).find(".laytable-cell-numbers").html(n),l.eq(e).find(".laytable-cell-numbers").html(n),d.eq(e).find(".laytable-cell-numbers").html(n))})}),p=(t.prototype.render=function(e){var t=this;t.tableIns=B["reloadData"===e?"reloadData":"reload"](t.tableIns.config.id,E.extend(!0,{},t.config)),t.config=t.tableIns.config},t.prototype.reload=function(e,t,a){var n=this;e=e||{},delete n.haveInit,layui.each(e,function(e,t){"array"===layui.type(t)&&delete n.config[e]}),d(n.getOptions().id,e,a||!0),n.config=E.extend(t,{},n.config,e),n.render(a)},j.reloadData=function(){var e=E.extend(!0,[],arguments);return e[3]="reloadData",j.reload.apply(null,e)},function(e,a,n,i){var l=[];return layui.each(e,function(e,t){"function"===layui.type(a)?a(t):E.extend(t,a),l.push(E.extend({},t)),i||(l=l.concat(p(t[n],a,n,i)))}),l}),o=(t.prototype.updateStatus=function(e,t,a){var n=this.getOptions(),i=n.tree;return e=e||B.cache[n.id],p(e,t,i.customName.children,a)},t.prototype.getTableData=function(){var e=this.getOptions();return B.cache[e.id]},j.updateStatus=function(e,t,a){var e=P(e),n=e.getOptions();return a=a||(n.url?B.cache[n.id]:n.data),e.updateStatus(a,t)},j.sort=function(e){var t=P(e);t&&t.getOptions().autoSort&&(t.initData(),j.renderData(e))},function(n){var t=n.config.id,i=P(t),a=n.data=j.getNodeDataByIndex(t,n.index),l=a[Y],d=(n.dataIndex=l,n.update);n.update=function(){var e=arguments,t=(E.extend(i.getNodeDataByIndex(l),e[0]),d.apply(this,e)),a=n.config.tree.customName.name;return a in e[0]&&n.tr.find('td[data-field="'+a+'"]').children("div.layui-table-cell").removeClass("layui-table-tree-item"),i.renderTreeTable(n.tr,n.tr.attr("data-level"),!1),t},n.del=function(){j.removeNode(t,a)},n.setRowChecked=function(e){j.setRowChecked(t,{index:a,checked:e})}}),u=(j.updateNode=function(e,a,t){var n,i,l,d,r,o=P(e);o&&((d=o.getOptions()).tree,d=(n=d.elem.next()).find('tr[lay-data-index="'+a+'"]'),i=d.attr("data-index"),l=d.attr("data-level"),t)&&(d=o.getNodeDataByIndex(a,!1,t),r=B.getTrHtml(e,[d]),layui.each(["main","fixed-l","fixed-r"],function(e,t){n.find(".layui-table-"+t+' tbody tr[lay-data-index="'+a+'"]').replaceWith(E(r[["trs","trs_fixed","trs_fixed_r"][e]].join("")).attr({"data-index":i,"lay-data-index":a,"data-level":l}))}),o.renderTreeTable(n.find('tr[lay-data-index="'+a+'"]'),l))},j.removeNode=function(e,t){var a,n,i,l,d,r=P(e);r&&(d=(a=r.getOptions()).tree,n=a.elem.next(),i=[],t=r.getNodeDataByIndex("string"===layui.type(t)?t:t[Y],!1,"delete"),l=r.getNodeDataByIndex(t[s]),r.updateCheckStatus(l),l=r.treeToFlat([t],t[d.customName.pid],t[s]),layui.each(l,function(e,t){i.push('tr[lay-data-index="'+t[Y]+'"]')}),n.find(i.join(",")).remove(),d=r.initData(),layui.each(r.treeToFlat(d),function(e,t){t[m]&&t[m]!==t[Y]&&n.find('tr[lay-data-index="'+t[m]+'"]').attr({"data-index":t[Y],"lay-data-index":t[Y]})}),layui.each(B.cache[e],function(e,t){n.find('tr[data-level="0"][lay-data-index="'+t[Y]+'"]').attr("data-index",e)}),a.hasNumberCol&&g(r),j.resize(e))},j.addNodes=function(e,t){var a=P(e);if(a){var n=a.getOptions(),i=n.tree,l=n.elem.next(),d=B.config.checkName,r=(t=t||{}).parentIndex,o=t.index,c=t.data,t=t.focus,u=(r="number"===layui.type(r)?r.toString():r)?a.getNodeDataByIndex(r):null,o="number"===layui.type(o)?o:-1,c=E.extend(!0,[],layui.isArray(c)?c:[c]);layui.each(c,function(e,t){d in t||!u||(t[d]=u[d])}),a.getTableData();if(u){var s=i.customName.isParent,f=i.customName.children;u[s]=!0;var y=(y=u[f])?(p=y.splice(-1===o?y.length:o),u[f]=y.concat(c,p)):u[f]=c,f=(a.updateStatus(y,function(e){(e[s]||i.view.showFlexIconIfNotParent)&&(e[z]=!1)}),a.treeToFlat(y));l.find(f.map(function(e){return'tr[lay-data-index="'+e[Y]+'"]'}).join(",")).remove(),a.initData(),u[z]=!1,u[X]="local",U({trElem:l.find('tr[lay-data-index="'+r+'"]')},!0)}else{var p=B.cache[e].splice(-1===o?B.cache[e].length:o);if(B.cache[e]=B.cache[e].concat(c,p),n.url||(n.page?(y=n.page,n.data.splice.apply(n.data,[y.limit*(y.curr-1),y.limit].concat(B.cache[e]))):n.data=B.cache[e]),a.initData(),l.find(".layui-none").length)return B.renderData(e),c;var x,f=B.getTrHtml(e,c),h={trs:E(f.trs.join("")),trs_fixed:E(f.trs_fixed.join("")),trs_fixed_r:E(f.trs_fixed_r.join(""))},r=(layui.each(c,function(e,t){x={"data-index":t[Y],"lay-data-index":t[Y],"data-level":"0"},h.trs.eq(e).attr(x),h.trs_fixed.eq(e).attr(x),h.trs_fixed_r.eq(e).attr(x)}),parseInt(c[0][Y])-1),y=l.find(L),n=l.find(q),f=l.find(R);-1==r?(y.find('tr[data-level="0"][data-index="0"]').before(h.trs),n.find('tr[data-level="0"][data-index="0"]').before(h.trs_fixed),f.find('tr[data-level="0"][data-index="0"]').before(h.trs_fixed_r)):-1===o?(y.find("tbody").append(h.trs),n.find("tbody").append(h.trs_fixed),f.find("tbody").append(h.trs_fixed_r)):(r=p[0][m],y.find('tr[data-level="0"][data-index="'+r+'"]').before(h.trs),n.find('tr[data-level="0"][data-index="'+r+'"]').before(h.trs_fixed),f.find('tr[data-level="0"][data-index="'+r+'"]').before(h.trs_fixed_r)),layui.each(B.cache[e],function(e,t){l.find('tr[data-level="0"][lay-data-index="'+t[Y]+'"]').attr("data-index",e)}),a.renderTreeTable(l.find(c.map(function(e,t,a){return'tr[lay-data-index="'+e[Y]+'"]'}).join(",")))}return a.updateCheckStatus(u),j.resize(e),t&&l.find(L).find('tr[lay-data-index="'+c[0][Y]+'"]').get(0).scrollIntoViewIfNeeded(),c}},j.checkStatus=function(e,n){var i,t,a,l=P(e);if(l)return l=l.getOptions().tree,i=B.config.checkName,t=j.getData(e,!0).filter(function(e,t,a){return e[i]||n&&e[b]}),a=!0,layui.each("all"===l.data.cascade?B.cache[e]:j.getData(e,!0),function(e,t){if(!t[i])return!(a=!1)}),{data:t,isAll:a}},j.on("sort",function(e){var e=e.config,t=e.elem.next(),e=e.id;t.hasClass(h)&&j.sort(e)}),j.on("row",function(e){e.config.elem.next().hasClass(h)&&o(e)}),j.on("rowDouble",function(e){var t=e.config,a=t.elem.next();t.id;a.hasClass(h)&&(o(e),(t.tree||{}).view.dblClickExpand)&&U({trElem:e.tr.first()},null,null,null,!0)}),j.on("rowContextmenu",function(e){var t=e.config,a=t.elem.next();t.id;a.hasClass(h)&&o(e)}),j.on("tool",function(e){var t=e.config,a=t.elem.next();t.id;a.hasClass(h)&&o(e)}),j.on("edit",function(e){var t=e.config,a=t.elem.next();t.id;a.hasClass(h)&&(o(e),e.field===t.tree.customName.name)&&((a={})[e.field]=e.value,e.update(a))}),j.on("radio",function(e){var t=e.config,a=t.elem.next(),t=t.id;a.hasClass(h)&&(a=P(t),o(e),u.call(a,e.tr,e.checked))}),t.prototype.setRowCheckedClass=function(e,t){var a=this.getOptions(),n=(e.data("index"),a.elem.next());e[t?"addClass":"removeClass"](l),e.each(function(){var e=E(this).data("index");n.find('.layui-table-fixed-r tbody tr[data-index="'+e+'"]')[t?"addClass":"removeClass"](l)})},t.prototype.updateCheckStatus=function(e,t){var a,n,i,l,d,r,o,c=this,u=c.getOptions();return!!u.hasChecboxCol&&(a=u.tree,n=u.id,i=u.elem.next(),l=B.config.checkName,"all"!==(d=a.data.cascade)&&"parent"!==d||!e||(d=c.updateParentCheckStatus(e,"boolean"===layui.type(t)?t:null),layui.each(d,function(e,t){var a=i.find('tr[lay-data-index="'+t[Y]+'"] input[name="layTableCheckbox"]:not(:disabled)'),n=t[l];c.setRowCheckedClass(a.closest("tr"),n),x.render(a.prop({checked:n,indeterminate:t[b]}))})),o=!(r=!0),e=(e="all"===a.data.cascade?B.cache[n]:j.getData(n,!0)).filter(function(e){return!e[u.disabledName]}),layui.each(e,function(e,t){if((t[l]||t[b])&&(o=!0),t[l]||(r=!1),o&&!r)return!0}),o=o&&!r,x.render(i.find('input[name="layTableCheckbox"][lay-filter="layTableAllChoose"]').prop({checked:r,indeterminate:o})),r)},t.prototype.updateParentCheckStatus=function(a,n){var i,e=this.getOptions(),t=e.tree,e=e.id,l=B.config.checkName,t=t.customName.children,d=[];return!(a[b]=!1)===n?a[t].length?layui.each(a[t],function(e,t){if(!t[l])return n=!1,a[b]=!0}):n=!1:!1===n?layui.each(a[t],function(e,t){if(t[l]||t[b])return a[b]=!0}):(n=!1,i=0,layui.each(a[t],function(e,t){t[l]&&i++}),n=a[t].length?a[t].length===i:a[l],a[b]=!n&&0')),n=(e.tree(a),i.elem=p(i.elem));if(n[0]){if(e.key=i.id||e.index,e.elem=a,e.elemNone=p('
                                                                                                    '+i.text.none+"
                                                                                                    "),n.html(e.elem),0==e.elem.find(".layui-tree-set").length)return e.elem.append(e.elemNone);i.showCheckbox&&e.renderForm("checkbox"),e.elem.find(".layui-tree-set").each(function(){var e=p(this);e.parent(".layui-tree-pack")[0]||e.addClass("layui-tree-setHide"),!e.next()[0]&&e.parents(".layui-tree-pack").eq(1).hasClass("layui-tree-lineExtend")&&e.addClass(T),e.next()[0]||e.parents(".layui-tree-set").eq(0).next()[0]||e.addClass(T)}),e.events()}},l.prototype.renderForm=function(e){i.render(e,"LAY-tree-"+this.index)},l.prototype.tree=function(r,e){var d=this,s=d.config,o=s.customName,e=e||s.data;layui.each(e,function(e,i){var a,n,t=i[o.children]&&0"),c=p(['
                                                                                                    ','
                                                                                                    ','
                                                                                                    ',s.showLine?t?'':'':'',s.showCheckbox?'':"",s.isJump&&i.href?''+(i[o.title]||i.label||s.text.defaultNodeName)+"":''+(i[o.title]||i.label||s.text.defaultNodeName)+"","
                                                                                                    ",s.edit?(a={add:'',update:'',del:''},n=['
                                                                                                    '],!0===s.edit&&(s.edit=["update","del"]),"object"==typeof s.edit?(layui.each(s.edit,function(e,i){n.push(a[i]||"")}),n.join("")+"
                                                                                                    "):void 0):"","
                                                                                                    "].join(""));t&&(c.append(l),d.tree(l,i[o.children])),r.append(c),c.prev("."+k)[0]&&c.prev().children(".layui-tree-pack").addClass("layui-tree-showLine"),t||c.parent(".layui-tree-pack").addClass("layui-tree-lineExtend"),d.spread(c,i),s.showCheckbox&&(i.checked&&d.checkids.push(i[o.id]),d.checkClick(c,i)),s.edit&&d.operate(c,i)})},l.prototype.spread=function(n,t){var l=this,c=l.config,e=n.children("."+b),i=e.children("."+g),a=i.find('input[same="layuiTreeCheck"]'),r=e.find("."+C),e=e.find("."+w),d=c.onlyIconControl?r:i,s="";d.on("click",function(e){var i=n.children("."+N),a=(d.children(".layui-icon")[0]?d:d.find(".layui-tree-icon")).children(".layui-icon");i[0]?n.hasClass(F)?(n.removeClass(F),i.slideUp(200),a.removeClass(x).addClass(v),l.updateFieldValue(t,"spread",!1)):(n.addClass(F),i.slideDown(200),a.addClass(x).removeClass(v),l.updateFieldValue(t,"spread",!0),c.accordion&&((i=n.siblings("."+k)).removeClass(F),i.children("."+N).slideUp(200),i.find(".layui-tree-icon").children(".layui-icon").removeClass(x).addClass(v))):s="normal"}),e.on("click",function(){p(this).hasClass(u)||(s=n.hasClass(F)?c.onlyIconControl?"open":"close":c.onlyIconControl?"close":"open",a[0]&&l.updateFieldValue(t,"checked",a.prop("checked")),c.click&&c.click({elem:n,state:s,data:t}))})},l.prototype.updateFieldValue=function(e,i,a){i in e&&(e[i]=a)},l.prototype.setCheckbox=function(e,i,a){var t,n=this,l=n.config.customName,c=a.prop("checked");a.prop("disabled")||("object"!=typeof i[l.children]&&!e.find("."+N)[0]||e.find("."+N).find('input[same="layuiTreeCheck"]').each(function(e){this.disabled||((e=i[l.children][e])&&n.updateFieldValue(e,"checked",c),n.updateFieldValue(this,"checked",c))}),(t=function(e){var i,a,n;e.parents("."+k)[0]&&(a=(e=e.parent("."+N)).parent(),n=e.prev().find('input[same="layuiTreeCheck"]'),c?n.prop("checked",c):(e.find('input[same="layuiTreeCheck"]').each(function(){this.checked&&(i=!0)}),i||n.prop("checked",!1)),t(a))})(e),n.renderForm("checkbox"))},l.prototype.checkClick=function(a,n){var t=this,l=t.config;a.children("."+b).children("."+g).on("click",'input[same="layuiTreeCheck"]+',function(e){layui.stope(e);var e=p(this).prev(),i=e.prop("checked");e.prop("disabled")||(t.setCheckbox(a,n,e),t.updateFieldValue(n,"checked",i),l.oncheck&&l.oncheck({elem:a,checked:i,data:n}))})},l.prototype.operate=function(r,d){var s=this,o=s.config,u=o.customName,e=r.children("."+b),h=e.children("."+g);e.children(".layui-tree-btnGroup").on("click",".layui-icon",function(e){layui.stope(e);var i,e=p(this).data("type"),n=r.children("."+N),t={data:d,type:e,elem:r};if("add"==e){n[0]||(o.showLine?(h.find("."+C).addClass("layui-tree-icon"),h.find("."+C).children(".layui-icon").addClass(v).removeClass("layui-icon-file")):h.find(".layui-tree-iconArrow").removeClass(m),r.append('
                                                                                                    '));var a,l=o.operate&&o.operate(t),c={};if(c[u.title]=o.text.defaultNodeName,c[u.id]=l,s.tree(r.children("."+N),[c]),o.showLine&&(n[0]?(n.hasClass(S)||n.addClass(S),r.find("."+N).each(function(){p(this).children("."+k).last().addClass(T)}),(n.children("."+k).last().prev().hasClass(T)?n.children("."+k).last().prev():n.children("."+k).last()).removeClass(T),!r.parent("."+N)[0]&&r.next()[0]&&n.children("."+k).last().removeClass(T)):(l=r.siblings("."+k),a=1,c=r.parent("."+N),layui.each(l,function(e,i){p(i).children("."+N)[0]||(a=0)}),(1==a?(l.children("."+N).addClass(L),l.children("."+N).children("."+k).removeClass(T),r.children("."+N).addClass(L),c.removeClass(S),c.children("."+k).last().children("."+N).children("."+k).last()):r.children("."+N).children("."+k)).addClass(T))),!o.showCheckbox)return;h.find('input[same="layuiTreeCheck"]')[0].checked&&(r.children("."+N).children("."+k).last().find('input[same="layuiTreeCheck"]')[0].checked=!0),s.renderForm("checkbox")}else"update"==e?(l=h.children("."+w).html(),h.children("."+w).html(""),h.append(''),h.children(".layui-tree-editInput").val(f.unescape(l)).focus(),i=function(e){var i=e.val().trim()||o.text.defaultNodeName;e.remove(),h.children("."+w).html(i),t.data[u.title]=i,o.operate&&o.operate(t)},h.children(".layui-tree-editInput").blur(function(){i(p(this))}),h.children(".layui-tree-editInput").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),i(p(this)))})):y.confirm('\u786e\u8ba4\u5220\u9664\u8be5\u8282\u70b9 "'+(d[u.title]||"")+'" \u5417\uff1f',function(e){var l,a,i;o.operate&&o.operate(t),t.status="remove",y.close(e),r.prev("."+k)[0]||r.next("."+k)[0]||r.parent("."+N)[0]?(r.siblings("."+k).children("."+b)[0]?(o.showCheckbox&&(l=function(e){var i,a,n,t;e.parents("."+k)[0]&&(i=e.siblings("."+k).children("."+b),a=(e=e.parent("."+N).prev()).find('input[same="layuiTreeCheck"]')[0],n=1,(t=0)==a.checked)&&(i.each(function(e,i){i=p(i).find('input[same="layuiTreeCheck"]')[0];0!=i.checked||i.disabled||(n=0),i.disabled||(t=1)}),1==n)&&1==t&&(a.checked=!0,s.renderForm("checkbox"),l(e.parent("."+k)))})(r),o.showLine&&(e=r.siblings("."+k),a=1,i=r.parent("."+N),layui.each(e,function(e,i){p(i).children("."+N)[0]||(a=0)}),1==a?(n[0]||(i.removeClass(S),e.children("."+N).addClass(L),e.children("."+N).children("."+k).removeClass(T)),(r.next()[0]?i.children("."+k).last():r.prev()).children("."+N).children("."+k).last().addClass(T),r.next()[0]||r.parents("."+k)[1]||r.parents("."+k).eq(0).next()[0]||r.prev("."+k).addClass(T)):!r.next()[0]&&r.hasClass(T)&&r.prev().addClass(T))):(e=r.parent("."+N).prev(),o.showLine?(e.find("."+C).removeClass("layui-tree-icon"),e.find("."+C).children(".layui-icon").removeClass(x).addClass("layui-icon-file"),(i=e.parents("."+N).eq(0)).addClass(S),i.children("."+k).each(function(){p(this).children("."+N).children("."+k).last().addClass(T)})):e.find(".layui-tree-iconArrow").addClass(m),r.parents("."+k).eq(0).removeClass(F),r.parent("."+N).remove()),r.remove()):(r.remove(),s.elem.append(s.elemNone))})})},l.prototype.events=function(){var i=this,t=i.config;i.elem.find(".layui-tree-checkedFirst");i.setChecked(i.checkids),i.elem.find(".layui-tree-search").on("keyup",function(){var e=p(this),a=e.val(),e=e.nextAll(),n=[];e.find("."+w).each(function(){var i,e=p(this).parents("."+b);-1!=p(this).html().indexOf(a)&&(n.push(p(this).parent()),(i=function(e){e.addClass("layui-tree-searchShow"),e.parent("."+N)[0]&&i(e.parent("."+N).parent("."+k))})(e.parent("."+k)))}),e.find("."+b).each(function(){var e=p(this).parent("."+k);e.hasClass("layui-tree-searchShow")||e.addClass(m)}),0==e.find(".layui-tree-searchShow").length&&i.elem.append(i.elemNone),t.onsearch&&t.onsearch({elem:n})}),i.elem.find(".layui-tree-search").on("keydown",function(){p(this).nextAll().find("."+b).each(function(){p(this).parent("."+k).removeClass("layui-tree-searchShow "+m)}),p(".layui-tree-emptyText")[0]&&p(".layui-tree-emptyText").remove()})},l.prototype.getChecked=function(){var t=this,e=t.config,l=e.customName,i=[],a=[],c=(t.elem.find(".layui-form-checked").each(function(){i.push(p(this).prev()[0].value)}),function(e,n){layui.each(e,function(e,a){layui.each(i,function(e,i){if(a[l.id]==i)return t.updateFieldValue(a,"checked",!0),delete(i=p.extend({},a))[l.children],n.push(i),a[l.children]&&(i[l.children]=[],c(a[l.children],i[l.children])),!0})})});return c(p.extend({},e.data),a),a},l.prototype.setChecked=function(l){this.config;this.elem.find("."+k).each(function(e,i){var a=p(this).data("id"),n=p(i).children("."+b).find('input[same="layuiTreeCheck"]'),t=n.next();if("number"==typeof l){if(a.toString()==l.toString())return n[0].checked||t.click(),!1}else"object"==typeof l&&layui.each(l,function(e,i){if(i.toString()==a.toString()&&!n[0].checked)return t.click(),!0})})},n.that={},n.config={},t.reload=function(e,i){e=n.that[e];return e.reload(i),n.call(e)},t.getChecked=function(e){return n.that[e].getChecked()},t.setChecked=function(e,i){return n.that[e].setChecked(i)},t.render=function(e){e=new l(e);return n.call(e)},e(a,t)});layui.define(["laytpl","form"],function(e){"use strict";var s=layui.$,n=layui.laytpl,t=layui.form,a="transfer",i={config:{},index:layui[a]?layui[a].index+1e4:0,set:function(e){var t=this;return t.config=s.extend({},t.config,e),t},on:function(e,t){return layui.onevent.call(this,a,e,t)}},l=function(){var t=this,e=t.config,a=e.id||t.index;return l.that[a]=t,{config:l.config[a]=e,reload:function(e){t.reload.call(t,e)},getData:function(){return t.getData.call(t)}}},d="layui-hide",h="layui-btn-disabled",r="layui-none",c="layui-transfer-box",u="layui-transfer-header",o="layui-transfer-search",f="layui-transfer-data",y=function(e){return['
                                                                                                    ','
                                                                                                    ','","
                                                                                                    ","{{# if(d.data.showSearch){ }}",'","{{# } }}",'
                                                                                                      ',"
                                                                                                      "].join("")},p=['
                                                                                                      ',y({index:0,checkAllName:"layTransferLeftCheckAll"}),'
                                                                                                      ','",'","
                                                                                                      ",y({index:1,checkAllName:"layTransferRightCheckAll"}),"
                                                                                                      "].join(""),v=function(e){var t=this;t.index=++i.index,t.config=s.extend({},t.config,i.config,e),t.render()};v.prototype.config={title:["\u5217\u8868\u4e00","\u5217\u8868\u4e8c"],width:200,height:360,data:[],value:[],showSearch:!1,id:"",text:{none:"\u65e0\u6570\u636e",searchNone:"\u65e0\u5339\u914d\u6570\u636e"}},v.prototype.reload=function(e){var t=this;t.config=s.extend({},t.config,e),t.render()},v.prototype.render=function(){var e=this,t=e.config,a=e.elem=s(n(p,{open:"{{",close:"}}"}).render({data:t,index:e.index})),i=t.elem=s(t.elem);i[0]&&(t.data=t.data||[],t.value=t.value||[],t.id="id"in t?t.id:elem.attr("id")||e.index,e.key=t.id,i.html(e.elem),e.layBox=e.elem.find("."+c),e.layHeader=e.elem.find("."+u),e.laySearch=e.elem.find("."+o),e.layData=a.find("."+f),e.layBtn=a.find(".layui-transfer-active .layui-btn"),e.layBox.css({width:t.width,height:t.height}),e.layData.css({height:(i=t.height-e.layHeader.outerHeight(),t.showSearch&&(i-=e.laySearch.outerHeight()),i-2)}),e.renderData(),e.events())},v.prototype.renderData=function(){var e=this,t=e.config,l=[{checkName:"layTransferLeftCheck",views:[]},{checkName:"layTransferRightCheck",views:[]}];e.parseData(function(a){var i=a.selected?1:0,n=["
                                                                                                    • ",'',"
                                                                                                    • "].join("");i?layui.each(t.value,function(e,t){t==a.value&&a.selected&&(l[i].views[e]=n)}):l[i].views.push(n),delete a.selected}),e.layData.eq(0).html(l[0].views.join("")),e.layData.eq(1).html(l[1].views.join("")),e.renderCheckBtn()},v.prototype.renderForm=function(e){t.render(e,"LAY-transfer-"+this.index)},v.prototype.renderCheckBtn=function(r){var c=this,o=c.config;r=r||{},c.layBox.each(function(e){var t=s(this),a=t.find("."+f),t=t.find("."+u).find('input[type="checkbox"]'),i=a.find('input[type="checkbox"]'),n=0,l=!1;i.each(function(){var e=s(this).data("hide");(this.checked||this.disabled||e)&&n++,this.checked&&!e&&(l=!0)}),t.prop("checked",l&&n===i.length),c.layBtn.eq(e)[l?"removeClass":"addClass"](h),r.stopNone||(i=a.children("li:not(."+d+")").length,c.noneView(a,i?"":o.text.none))}),c.renderForm("checkbox")},v.prototype.noneView=function(e,t){var a=s('

                                                                                                      '+(t||"")+"

                                                                                                      ");e.find("."+r)[0]&&e.find("."+r).remove(),t.replace(/\s/g,"")&&e.append(a)},v.prototype.setValue=function(){var e=this.config,t=[];return this.layBox.eq(1).find("."+f+' input[type="checkbox"]').each(function(){s(this).data("hide")||t.push(this.value)}),e.value=t,this},v.prototype.parseData=function(t){var i=this.config,n=[];return layui.each(i.data,function(e,a){a=("function"==typeof i.parseData?i.parseData(a):a)||a,n.push(a=s.extend({},a)),layui.each(i.value,function(e,t){t==a.value&&(a.selected=!0)}),t&&t(a)}),i.data=n,this},v.prototype.getData=function(e){var t=this.config,i=[];return this.setValue(),layui.each(e||t.value,function(e,a){layui.each(t.data,function(e,t){delete t.selected,a==t.value&&i.push(t)})}),i},v.prototype.transfer=function(e,t){var a,i=this,n=i.config,l=i.layBox.eq(e),r=[],t=(t?((a=(t=t).find('input[type="checkbox"]'))[0].checked=!1,l.siblings("."+c).find("."+f).append(t.clone()),t.remove(),r.push(a[0].value),i.setValue()):l.each(function(e){s(this).find("."+f).children("li").each(function(){var e=s(this),t=e.find('input[type="checkbox"]'),a=t.data("hide");t[0].checked&&!a&&(t[0].checked=!1,l.siblings("."+c).find("."+f).append(e.clone()),e.remove(),r.push(t[0].value)),i.setValue()})}),i.renderCheckBtn(),l.siblings("."+c).find("."+o+" input"));""!==t.val()&&t.trigger("keyup"),n.onchange&&n.onchange(i.getData(r),e)},v.prototype.events=function(){var n=this,l=n.config;n.elem.on("click",'input[lay-filter="layTransferCheckbox"]+',function(){var e=s(this).prev(),t=e[0].checked,a=e.parents("."+c).eq(0).find("."+f);e[0].disabled||("all"===e.attr("lay-type")&&a.find('input[type="checkbox"]').each(function(){this.disabled||(this.checked=t)}),setTimeout(function(){n.renderCheckBtn({stopNone:!0})},0))}),n.elem.on("dblclick","."+f+">li",function(e){var t=s(this),a=t.children('input[type="checkbox"]'),i=t.parent().parent();a[0].disabled||n.transfer(i.data("index"),t)}),n.layBtn.on("click",function(){var e=s(this),t=e.data("index");e.hasClass(h)||n.transfer(t)}),n.laySearch.find("input").on("keyup",function(){var i=this.value,e=s(this).parents("."+o).eq(0).siblings("."+f),t=e.children("li"),t=(t.each(function(){var e=s(this),t=e.find('input[type="checkbox"]'),a=t[0].title,a=("cs"!==l.showSearch&&(a=a.toLowerCase(),i=i.toLowerCase()),-1!==a.indexOf(i));e[a?"removeClass":"addClass"](d),t.data("hide",!a)}),n.renderCheckBtn(),t.length===e.children("li."+d).length);n.noneView(e,t?l.text.searchNone:"")})},l.that={},l.config={},i.reload=function(e,t){e=l.that[e];return e.reload(t),l.call(e)},i.getData=function(e){return l.that[e].getData()},i.render=function(e){e=new v(e);return l.call(e)},e(a,i)});layui.define(["jquery","lay"],function(e){"use strict";var a=layui.$,l=layui.lay,t=(layui.hint(),layui.device(),{config:{},set:function(e){var i=this;return i.config=a.extend({},i.config,e),i},on:function(e,i){return layui.onevent.call(this,d,e,i)}}),d="carousel",r="layui-this",s="layui-carousel-left",u="layui-carousel-right",c="layui-carousel-prev",h="layui-carousel-next",o="layui-carousel-arrow",m="layui-carousel-ind",i=function(e){var i=this;i.config=a.extend({},i.config,t.config,e),i.render()};i.prototype.config={width:"600px",height:"280px",full:!1,arrow:"hover",indicator:"inside",autoplay:!0,interval:3e3,anim:"",trigger:"click",index:0},i.prototype.render=function(){var e=this,i=e.config,n=a(i.elem);if(1*[carousel-item]>*"),i.index<0&&(i.index=0),i.index>=e.elemItem.length&&(i.index=e.elemItem.length-1),i.interval<800&&(i.interval=800),i.full?i.elem.css({position:"fixed",width:"100%",height:"100%",zIndex:9999}):i.elem.css({width:i.width,height:i.height}),i.elem.attr("lay-anim",i.anim),e.elemItem.eq(i.index).addClass(r),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},i.prototype.reload=function(e){var i=this;clearInterval(i.timer),i.config=a.extend({},i.config,e),i.render()},i.prototype.prevIndex=function(){var e=this.config.index-1;return e=e<0?this.elemItem.length-1:e},i.prototype.nextIndex=function(){var e=this.config.index+1;return e=e>=this.elemItem.length?0:e},i.prototype.addIndex=function(e){var i=this.config;i.index=i.index+(e=e||1),i.index>=this.elemItem.length&&(i.index=0)},i.prototype.subIndex=function(e){var i=this.config;i.index=i.index-(e=e||1),i.index<0&&(i.index=this.elemItem.length-1)},i.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(clearInterval(e.timer),e.timer=setInterval(function(){e.slide()},i.interval))},i.prototype.arrow=function(){var i=this,e=i.config,n=a(['",'"].join(""));e.elem.attr("lay-arrow",e.arrow),e.elem.find("."+o)[0]&&e.elem.find("."+o).remove(),e.elem.append(n),n.on("click",function(){var e=a(this).attr("lay-type");i.slide(e)})},i.prototype["goto"]=function(e){var i=this,n=i.config;e>n.index?i.slide("add",e-n.index):e
                                                                                                        ',(i=[],layui.each(e.elemItem,function(e){i.push("")}),i.join("")),"
                                                                                                      "].join(""));n.elem.attr("lay-indicator",n.indicator),n.elem.find("."+m)[0]&&n.elem.find("."+m).remove(),n.elem.append(t),"updown"===n.anim&&t.css("margin-top",-t.height()/2),t.find("li").on("hover"===n.trigger?"mouseover":n.trigger,function(){e["goto"](a(this).index())})},i.prototype.slide=function(e,i){var n=this,t=n.elemItem,a=n.config,o=a.index,l=a.elem.attr("lay-filter");n.haveSlide||("sub"===e?(n.subIndex(i),t.eq(a.index).addClass(c),setTimeout(function(){t.eq(o).addClass(u),t.eq(a.index).addClass(u)},50)):(n.addIndex(i),t.eq(a.index).addClass(h),setTimeout(function(){t.eq(o).addClass(s),t.eq(a.index).addClass(s)},50)),setTimeout(function(){t.removeClass(r+" "+c+" "+h+" "+s+" "+u),t.eq(a.index).addClass(r),n.haveSlide=!1},350),n.elemInd.find("li").eq(a.index).addClass(r).siblings().removeClass(r),n.haveSlide=!0,e={index:a.index,prevIndex:o,item:t.eq(a.index)},"function"==typeof a.change&&a.change(e),layui.event.call(this,d,"change("+l+")",e))},i.prototype.events=function(){var t,a,o=this,e=o.config;e.elem.data("haveEvents")||(e.elem.on("mouseenter touchstart",function(){"always"!==o.config.autoplay&&clearInterval(o.timer)}).on("mouseleave touchend",function(){"always"!==o.config.autoplay&&o.autoplay()}),t=e.elem,a="updown"===e.anim,l.touchSwipe(t,{onTouchEnd:function(e,i){var n=Date.now()-i.timeStart,i=a?i.distanceY:i.distanceX;(.25t[a?"height":"width"]()/3)&&o.slide(0a.length&&(a.value=a.length),parseInt(a.value)===a.value||a.half||(a.value=Math.ceil(a.value)-a.value<.5?Math.ceil(a.value):Math.floor(a.value)),'
                                                                                                        "),n=1;n<=a.length;n++){var o='
                                                                                                      • ";a.half&&parseInt(a.value)!==a.value&&n==Math.ceil(a.value)?i=i+'
                                                                                                      • ":i+=o}i+="
                                                                                                      "+(a.text?''+a.value+"\u661f":"")+"";var l=a.elem,s=l.next(".layui-rate");s[0]&&s.remove(),e.elemTemp=u(i),a.span=e.elemTemp.next("span"),a.setText&&a.setText(a.value),l.html(e.elemTemp),l.addClass("layui-inline"),a.readonly||e.action()},a.prototype.setvalue=function(e){this.config.value=e,this.render()},a.prototype.action=function(){var n=this.config,t=this.elemTemp,i=t.find("i").width(),l=t.children("li");l.each(function(e){var a=e+1,l=u(this);l.on("click",function(e){n.value=a,n.half&&e.pageX-u(this).offset().left<=i/2&&(n.value=n.value-.5),n.text&&t.next("span").text(n.value+"\u661f"),n.choose&&n.choose(n.value),n.setText&&n.setText(n.value)}),l.on("mousemove",function(e){t.find("i").each(function(){u(this).addClass(h).removeClass(s)}),t.find("i:lt("+a+")").each(function(){u(this).addClass(f).removeClass(v)}),n.half&&e.pageX-u(this).offset().left<=i/2&&l.children("i").addClass(o).removeClass(f)}),l.on("mouseleave",function(){t.find("i").each(function(){u(this).addClass(h).removeClass(s)}),t.find("i:lt("+Math.floor(n.value)+")").each(function(){u(this).addClass(f).removeClass(v)}),n.half&&parseInt(n.value)!==n.value&&t.children("li:eq("+Math.floor(n.value)+")").children("i").addClass(o).removeClass("layui-icon-rate-solid layui-icon-rate")})}),r.touchSwipe(t,{onTouchMove:function(e,a){var i;Date.now()-a.timeStart<=200||(a=e.touches[0].pageX,e=t.width()/n.length,a=(a-t.offset().left)/e,(i=(i=(e=a%1)<=.5&&n.half?.5+(a-e):Math.ceil(a))>n.length?n.length:i)<0&&(i=0),l.each(function(e){var a=u(this).children("i"),l=Math.ceil(i)-e==1,t=Math.ceil(i)>e,e=i-e==.5;t?(a.addClass(f).removeClass(v),n.half&&e&&a.addClass(o).removeClass(f)):a.addClass(h).removeClass(s),a.toggleClass("layui-rate-hover",l)}),n.value=i,n.setText&&n.setText(n.value))},onTouchEnd:function(e,a){Date.now()-a.timeStart<=200||(t.find("i").removeClass("layui-rate-hover"),n.choose&&n.choose(n.value),n.setText&&n.setText(n.value))}})},a.prototype.events=function(){},c.render=function(e){e=new a(e);return function(){var a=this;return{setvalue:function(e){a.setvalue.call(a,e)},config:a.config}}.call(e)},e(l,c)});layui.define("jquery",function(l){"use strict";var g=layui.$,e=function(l){};e.prototype.load=function(l){var t,i,o,n,e,r,a,c,m,s,u,f,y,d=this,p=0,h=g((l=l||{}).elem);if(h[0])return e=g(l.scrollElem||document),r=l.mb||50,a=!("isAuto"in l)||l.isAuto,c=l.end||"\u6ca1\u6709\u66f4\u591a\u4e86",m=l.scrollElem&&l.scrollElem!==document,u=g('"),h.find(".layui-flow-more")[0]||h.append(u),f=function(l,e){l=g(l),u.before(l),(e=0==e||null)?u.html(c):u.find("a").html(s),i=e,t=null,o&&o()},(y=function(){t=!0,u.find("a").html(''),"function"==typeof l.done&&l.done(++p,f)})(),u.find("a").on("click",function(){g(this);i||t||y()}),l.isLazyimg&&(o=d.lazyimg({elem:l.elem+" img",scrollElem:l.scrollElem})),a&&e.on("scroll",function(){var e=g(this),o=e.scrollTop();n&&clearTimeout(n),!i&&h.width()&&(n=setTimeout(function(){var l=(m?e:g(window)).height();(m?e.prop("scrollHeight"):document.documentElement.scrollHeight)-o-l<=r&&(t||y())},100))}),d},e.prototype.lazyimg=function(l){var e,c=this,m=0,s=g((l=l||{}).scrollElem||document),u=l.elem||"img",f=l.scrollElem&&l.scrollElem!==document,y=function(e,l){var o,t=s.scrollTop(),l=t+l,i=f?e.offset().top-s.offset().top+t:e.offset().top;t<=i&&i<=l&&e.attr("lay-src")&&(o=e.attr("lay-src"),layui.img(o,function(){var l=c.lazyimg.elem.eq(m);e.attr("src",o).removeAttr("lay-src"),l[0]&&n(l),m++},function(){c.lazyimg.elem.eq(m);e.removeAttr("lay-src")}))},n=function(l,e){var o=(f?e||s:g(window)).height(),t=s.scrollTop(),i=t+o;if(c.lazyimg.elem=g(u),l)y(l,o);else for(var n=0;n"),preview:"Preview"},wordWrap:!0,lang:"text",highlighter:!1,langMarker:!1},W=layui.code?layui.code.index+1e4:0,R=function(e){return String(e).replace(/\s+$/,"").replace(/^\n|\n$/,"")};e("code",function(l,e){var o,i,t,a,n,d,c,s,r,u,y,p,E,f,h,v,m,L,_,M,C,g={config:l=x.extend(!0,{},T,l),reload:function(e){layui.code(this.updateOptions(e))},updateOptions:function(e){return delete(e=e||{}).elem,x.extend(!0,l,e)},reloadCode:function(e){layui.code(this.updateOptions(e),"reloadCode")}},w=x(l.elem);return 1',l.ln?['
                                                                                                      ',D.digit(t+1)+".","
                                                                                                      "].join(""):"",'
                                                                                                      ',e||" ","
                                                                                                      ",""].join("")})}},a=l.code,n=function(e){return"function"==typeof l.codeParse?l.codeParse(e,l):e},"reloadCode"===e?o.children(".layui-code-wrap").html(w(n(a)).html):(d=layui.code.index=++W,o.attr("lay-code-index",d),(M=A.CDDE_DATA_CLASS in o.data())&&o.attr("class",o.data(A.CDDE_DATA_CLASS)||""),M||o.data(A.CDDE_DATA_CLASS,o.attr("class")),c={copy:{className:"file-b",title:["\u590d\u5236\u4ee3\u7801"],event:function(e){var t=D.unescape(n(l.code));lay.clipboard.writeText({text:t,done:function(){N.msg("\u5df2\u590d\u5236",{icon:1})},error:function(){N.msg("\u590d\u5236\u5931\u8d25",{icon:2})}}),"function"==typeof l.onCopy&&l.onCopy(t)}}},function b(){var e=o.parent("."+A.ELEM_PREVIEW),t=e.children("."+A.ELEM_TAB),a=e.children("."+A.ELEM_ITEM+"-preview");return t.remove(),a.remove(),e[0]&&o.unwrap(),b}(),l.preview&&(M="LAY-CODE-DF-"+d,f=l.layout||["code","preview"],s="iframe"===l.preview,E=x('
                                                                                                      '),C=x('
                                                                                                      '),r=x('
                                                                                                      '),_=x('
                                                                                                      '),u=x('
                                                                                                      '),l.id&&E.attr("id",l.id),E.addClass(l.className),C.attr("lay-filter",M),layui.each(f,function(e,t){var a=x('
                                                                                                    • ');0===e&&a.addClass("layui-this"),a.html(l.text[t]),r.append(a)}),x.extend(c,{full:{className:"screen-full",title:["\u6700\u5927\u5316\u663e\u793a","\u8fd8\u539f\u663e\u793a"],event:function(e){var e=e.elem,t=e.closest("."+A.ELEM_PREVIEW),a="layui-icon-"+this.className,i="layui-icon-screen-restore",l=this.title,o=x("html,body"),n="layui-scrollbar-hide";e.hasClass(a)?(t.addClass(A.ELEM_FULL),e.removeClass(a).addClass(i),e.attr("title",l[1]),o.addClass(n)):(t.removeClass(A.ELEM_FULL),e.removeClass(i).addClass(a),e.attr("title",l[0]),o.removeClass(n))}},window:{className:"release",title:["\u5728\u65b0\u7a97\u53e3\u9884\u89c8"],event:function(e){D.openWin({content:n(l.code)})}}}),l.copy&&("array"===layui.type(l.tools)?-1===l.tools.indexOf("copy")&&l.tools.unshift("copy"):l.tools=["copy"]),u.on("click",">i",function(){var e=x(this),t=e.data("type"),e={elem:e,type:t,options:l,rawCode:l.code,finalCode:D.unescape(n(l.code))};c[t]&&"function"==typeof c[t].event&&c[t].event(e),"function"==typeof l.toolsEvent&&l.toolsEvent(e)}),l.addTools&&l.tools&&(l.tools=[].concat(l.tools,l.addTools)),layui.each(l.tools,function(e,t){var a="object"==typeof t,i=a?t:c[t]||{className:t,title:[t]},l=i.className||i.type,o=i.title||[""],a=a?i.type||l:t;a&&(c[a]||((t={})[a]=i,x.extend(c,t)),u.append(''))}),o.addClass(A.ELEM_ITEM).wrap(E),C.append(r),l.tools&&C.append(u),o.before(C),s&&_.html(''),y=function(e){var t=e.children("iframe")[0];s&&t?t.srcdoc=n(l.code):e.html(l.code),setTimeout(function(){"function"==typeof l.done&&l.done({container:e,options:l,render:function(){I.render(e.find(".layui-form")),S.render()}})},3)},"preview"===f[0]?(_.addClass(A.ELEM_SHOW),o.before(_),y(_)):o.addClass(A.ELEM_SHOW).after(_),l.previewStyle=[l.style,l.previewStyle].join(""),_.attr("style",l.previewStyle),S.on("tab("+M+")",function(e){var t=x(this),a=x(e.elem).closest("."+A.ELEM_PREVIEW).find("."+A.ELEM_ITEM),e=a.eq(e.index);a.removeClass(A.ELEM_SHOW),e.addClass(A.ELEM_SHOW),"preview"===t.attr("lay-id")&&y(e),L()})),p=x(''),o.addClass((E=["layui-code-view layui-border-box"],l.wordWrap||E.push("layui-code-nowrap"),E.join(" "))),(C=l.theme||l.skin)&&(o.removeClass("layui-code-theme-dark layui-code-theme-light"),o.addClass("layui-code-theme-"+C)),l.highlighter&&o.addClass([l.highlighter,"language-"+l.lang,"layui-code-hl"].join(" ")),f=w(l.encode?D.escape(n(a)):a),h=f.lines,o.html(p.html(f.html)),l.ln&&o.append('
                                                                                                      '),l.height&&p.css("max-height",l.height),l.codeStyle=[l.style,l.codeStyle].join(""),l.codeStyle&&p.attr("style",function(e,t){return(t||"")+l.codeStyle}),v=[{selector:">.layui-code-wrap>.layui-code-line{}",setValue:function(e,t){e.style["padding-left"]=t+"px"}},{selector:">.layui-code-wrap>.layui-code-line>.layui-code-line-number{}",setValue:function(e,t){e.style.width=t+"px"}},{selector:">.layui-code-ln-side{}",setValue:function(e,t){e.style.width=t+"px"}}],m=lay.style({target:o[0],id:"DF-code-"+d,text:x.map(x.map(v,function(e){return e.selector}),function(e,t){return['.layui-code-view[lay-code-index="'+d+'"]',e].join(" ")}).join("")}),L=function b(){var e,i;return l.ln&&(e=Math.floor(h.length/100),i=p.children("."+A.ELEM_LINE).last().children("."+A.ELEM_LINE_NUM).outerWidth(),o.addClass(A.ELEM_LN_MODE),e)&&A.LINE_RAW_WIDTH
                                                                                                    • ')).html(l.title||l.text.code),o.prepend(_)),M=x('
                                                                                                      '),l.copy&&!l.preview&&((C=x(['','',""].join(""))).on("click",function(){c.copy.event()}),M.append(C)),l.langMarker&&M.append(''+l.lang+""),l.about&&M.append(l.about),o.append(M),l.preview||setTimeout(function(){"function"==typeof l.done&&l.done({})},3),l.elem.length===1+d&&"function"==typeof l.allDone&&l.allDone())),g})}),layui["layui.all"]||layui.addcss("modules/code.css?v=6","skincodecss"); \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/component/logicflow/core/README.md b/demo/webman/frontend/layui_admin_flow/component/logicflow/core/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7e564f149bb9befdcf60a9f8cb42324e8c1d8745 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/logicflow/core/README.md @@ -0,0 +1,170 @@ +

                                                                                                      + + LogicFlow logo + +

                                                                                                      + +

                                                                                                      + + Version + + + Download + + + LICENSE + +

                                                                                                      + +LogicFlow 是一款流程图编辑框架,提供了一系列流程图交互、编辑所必需的功能和简单灵活的节点自定义、插件等拓展机制,方便我们快速在业务系统内满足类流程图的需求。 + +## 特性 + + +- 🛠 高拓展性 + + 兼容各种产品自定义的流程编辑需求,绝大部分模块以插件的形式实现,支持各模块自由插拔。 + +- 🚀 重执行 + + 流程图能完备的表达业务逻辑,不受流程引擎限制。 + +- 🎯 专业 + + 专注于业务流程图编辑的框架 + +## 使用 + +### 安装 + +```sh +# npm +$ npm install @logicflow/core --save + + +# yarn +$ yarn add @logicflow/core +``` + +### 代码示例 + +```js +// 创建容器 +
                                                                                                      ; + +// 准备数据 +const data = { + // 节点 + nodes: [ + { + id: 21, + type: 'rect', + x: 100, + y: 200, + text: { + value: '矩形节点', + x: 100, + y: 200, + }, + }, + { + id: 50, + type: 'circle', + x: 300, + y: 400, + text: { + value: '圆形节点', + x: 300, + y: 400, + }, + }, + ], + // 边 + edges: [ + { + type: 'polyline', + sourceNodeId: 50, + targetNodeId: 21, + }, + ], +}; +// 渲染画布 +const lf = new LogicFlow({ + container: document.querySelector('#container'), + width: 700, + height: 600, +}); + +lf.render(data); +``` + +## 文档 + +[官方文档](https://docs.logic-flow.cn) + +- [快速上手](https://docs.logic-flow.cn/docs/#/zh/guide/start) +- [示例](https://docs.logic-flow.cn/examples/#/gallery) + +## 核心能力 + +### 流程图编辑器快速搭建 + +提供了一个流程图编辑所必需的各项能力,这也是 LogicFlow 的基础能力: + +- 图的绘制能力。基于 SVG 来绘制形状各异的节点和线,并提供了基础的节点(矩形、圆形、多边形等)和线(直线、折线、曲线) +- 各类交互能力,让图动起来。根据节点、线、图的各类鼠标事件(hover、点击、拖拽等)做出反应。比如节点拖拽、拖拽创建边、线的调整、双击节点编辑文本等 +- 提升编辑效率的能力。提供网格、对齐线,上一步、下一步,键盘快捷键,图放大缩小等配套能力,帮助用户提升编辑效率 +- 提供了丰富的 API ,宿主研发通过 API 传参调用和监听事件的方式,与 LogicFlow 完成交互 + + 下面是通过 LogicFlow 内置的节点和配套能力,做的流程图示例 + : + + + +### 基于业务场景拓展 + +当基础能力无法满足业务需求的时候,便需要基于业务场景拓展。 + +- 设置图上所有元素的样式,比如各种节点、线、锚点、箭头、对齐线的大小颜色等,满足对前端样式调整的需求 +- API 拓展。支持在 LogicFlow 上注册自定义的方法,比如通过 API 拓展提供图片下载的方法 +- 自定义节点、线。内置的矩形、圆形等图形类节点往往无法满足实际的业务需求,需要定义具有业务意义的节点。LogicFlow 提供了 的方式让用户定制具有自定义图形、业务数据的节点,比如流程审批场景中的 “审批” 节点 +- 拓展组件。LogicFlow 在 SVG 图层上提供了 HTML 层和一系列坐标转换逻辑,并支持在 HTML 层注册组件。宿主研发可以通过 LogicFlow 的 API,基于任何 View 框架开发组件,比如节点的右键菜单、控制面板等 +- 数据转换 adapter。LogicFlow 默认导出的图数据不一定适合所有业务,此时可以通过 adapter API,在图数据从 LogicFlow 输入、输出的时候做自定义转换,比如转换成 BPMN 规范的图数据 +- 内置部分拓展能力。基于上述拓展能力,我们还单独提供了 extension 的包,用来存放当前业务下沉淀出的具有通用性的节点、组件等,比如面向 BPMN 规范的节点和数据 adapter,默认菜单。注意 extension 可以单独安装,并支持按需引入 + +基于上述拓展的能力,前端研发能够根据实际业务场景的需求,灵活的开发出所需的节点、组件等。下面有两个基于 LogicFlow 拓展能力做出的流程图: + +#### BPMN 规范 + +![图片:bpmn](https://dpubstatic.udache.com/static/dpubimg/CS6S6q9Yxf/lfexample2.gif) + +#### 审批流 + +![图片: 审批流](https://dpubstatic.udache.com/static/dpubimg/uBeSlMEytL/lfexample3.gif) + +#### vue 应用 demo + +[代码地址](https://github.com/xinxin93/logicflow_vue_demo) + +![图片:vue应用](https://dpubstatic.udache.com/static/dpubimg/e35cef10-bb7c-4662-a494-f5aac024c092.gif) + + +#### vue3 node-red风格示例 + +[Logic-Flow/logicflow-node-red-vue3](https://github.com/Logic-Flow/logicflow-node-red-vue3) + +![node-red](https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/core/node-red.png) + +## 联系我们 + +### 加入微信群 + +添加微信号:logic-flow 加入用户群 + +### 加入 QQ 群 + + diff --git a/demo/webman/frontend/layui_admin_flow/component/logicflow/core/dist/entry.js b/demo/webman/frontend/layui_admin_flow/component/logicflow/core/dist/entry.js new file mode 100644 index 0000000000000000000000000000000000000000..57127cf01a0108a895bc1f9d580c9f377376e573 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/logicflow/core/dist/entry.js @@ -0,0 +1,7 @@ +'use strict' + +if (process.env.NODE_ENV === 'production') { + module.exports = require('./logic-flow.min.js'); +} else { + module.exports = require('./logic-flow.js'); +} diff --git a/demo/webman/frontend/layui_admin_flow/component/logicflow/core/dist/logic-flow.js b/demo/webman/frontend/layui_admin_flow/component/logicflow/core/dist/logic-flow.js new file mode 100644 index 0000000000000000000000000000000000000000..1e4931036e8ae9fa1869e9ba8fa716703beca580 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/logicflow/core/dist/logic-flow.js @@ -0,0 +1,23282 @@ +!function (t, e) { + if ("object" == typeof exports && "object" == typeof module) module.exports = e(); else if ("function" == typeof define && define.amd) define([], e); else { + var r = e(); + for (var n in r) ("object" == typeof exports ? exports : t)[n] = r[n] + } +}(window, (function () { + return function (t) { + var e = {}; + + function r(n) { + if (e[n]) return e[n].exports; + var o = e[n] = {i: n, l: !1, exports: {}}; + return t[n].call(o.exports, o, o.exports, r), o.l = !0, o.exports + } + + return r.m = t, r.c = e, r.d = function (t, e, n) { + r.o(t, e) || Object.defineProperty(t, e, {enumerable: !0, get: n}) + }, r.r = function (t) { + "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, {value: "Module"}), Object.defineProperty(t, "__esModule", {value: !0}) + }, r.t = function (t, e) { + if (1 & e && (t = r(t)), 8 & e) return t; + if (4 & e && "object" == typeof t && t && t.__esModule) return t; + var n = Object.create(null); + if (r.r(n), Object.defineProperty(n, "default", { + enumerable: !0, + value: t + }), 2 & e && "string" != typeof t) for (var o in t) r.d(n, o, function (e) { + return t[e] + }.bind(null, o)); + return n + }, r.n = function (t) { + var e = t && t.__esModule ? function () { + return t.default + } : function () { + return t + }; + return r.d(e, "a", e), e + }, r.o = function (t, e) { + return Object.prototype.hasOwnProperty.call(t, e) + }, r.p = "", r(r.s = 220) + }([function (t, e, r) { + "use strict"; + r.d(e, "a", (function () { + return m + })), r.d(e, "b", (function () { + return b + })), r.d(e, "c", (function () { + return U + })), r.d(e, "d", (function () { + return F + })), r.d(e, "e", (function () { + return y + })), r.d(e, "f", (function () { + return g + })), r.d(e, "g", (function () { + return y + })), r.d(e, "h", (function () { + return B + })), r.d(e, "i", (function () { + return o + })), r.d(e, "j", (function () { + return z + })), r.d(e, "k", (function () { + return S + })); + var n, o, i, u, a, c, s, l = {}, f = [], + p = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i; + + function d(t, e) { + for (var r in e) t[r] = e[r]; + return t + } + + function h(t) { + var e = t.parentNode; + e && e.removeChild(t) + } + + function y(t, e, r) { + var o, i, u, a = {}; + for (u in e) "key" == u ? o = e[u] : "ref" == u ? i = e[u] : a[u] = e[u]; + if (arguments.length > 2 && (a.children = arguments.length > 3 ? n.call(arguments, 2) : r), "function" == typeof t && null != t.defaultProps) for (u in t.defaultProps) void 0 === a[u] && (a[u] = t.defaultProps[u]); + return v(t, a, o, i, null) + } + + function v(t, e, r, n, u) { + var a = { + type: t, + props: e, + key: r, + ref: n, + __k: null, + __: null, + __b: 0, + __e: null, + __d: void 0, + __c: null, + __h: null, + constructor: void 0, + __v: null == u ? ++i : u + }; + return null == u && null != o.vnode && o.vnode(a), a + } + + function g() { + return {current: null} + } + + function b(t) { + return t.children + } + + function m(t, e) { + this.props = t, this.context = e + } + + function O(t, e) { + if (null == e) return t.__ ? O(t.__, t.__.__k.indexOf(t) + 1) : null; + for (var r; e < t.__k.length; e++) if (null != (r = t.__k[e]) && null != r.__e) return r.__e; + return "function" == typeof t.type ? O(t) : null + } + + function _(t) { + var e, r; + if (null != (t = t.__) && null != t.__c) { + for (t.__e = t.__c.base = null, e = 0; e < t.__k.length; e++) if (null != (r = t.__k[e]) && null != r.__e) { + t.__e = t.__c.base = r.__e; + break + } + return _(t) + } + } + + function w(t) { + (!t.__d && (t.__d = !0) && u.push(t) && !x.__r++ || c !== o.debounceRendering) && ((c = o.debounceRendering) || a)(x) + } + + function x() { + for (var t; x.__r = u.length;) t = u.sort((function (t, e) { + return t.__v.__b - e.__v.__b + })), u = [], t.some((function (t) { + var e, r, n, o, i, u; + t.__d && (i = (o = (e = t).__v).__e, (u = e.__P) && (r = [], (n = d({}, o)).__v = o.__v + 1, M(u, o, n, e.__n, void 0 !== u.ownerSVGElement, null != o.__h ? [i] : null, r, null == i ? O(o) : i, o.__h), N(r, o), o.__e != i && _(o))) + })) + } + + function j(t, e, r, n, o, i, u, a, c, s) { + var p, d, h, y, g, m, _, w = n && n.__k || f, x = w.length; + for (r.__k = [], p = 0; p < e.length; p++) if (null != (y = r.__k[p] = null == (y = e[p]) || "boolean" == typeof y ? null : "string" == typeof y || "number" == typeof y || "bigint" == typeof y ? v(null, y, null, null, y) : Array.isArray(y) ? v(b, {children: y}, null, null, null) : y.__b > 0 ? v(y.type, y.props, y.key, null, y.__v) : y)) { + if (y.__ = r, y.__b = r.__b + 1, null === (h = w[p]) || h && y.key == h.key && y.type === h.type) w[p] = void 0; else for (d = 0; d < x; d++) { + if ((h = w[d]) && y.key == h.key && y.type === h.type) { + w[d] = void 0; + break + } + h = null + } + M(t, y, h = h || l, o, i, u, a, c, s), g = y.__e, (d = y.ref) && h.ref != d && (_ || (_ = []), h.ref && _.push(h.ref, null, y), _.push(d, y.__c || g, y)), null != g ? (null == m && (m = g), "function" == typeof y.type && y.__k === h.__k ? y.__d = c = E(y, c, t) : c = P(t, y, h, w, g, c), "function" == typeof r.type && (r.__d = c)) : c && h.__e == c && c.parentNode != t && (c = O(h)) + } + for (r.__e = m, p = x; p--;) null != w[p] && ("function" == typeof r.type && null != w[p].__e && w[p].__e == r.__d && (r.__d = O(n, p + 1)), I(w[p], w[p])); + if (_) for (p = 0; p < _.length; p++) R(_[p], _[++p], _[++p]) + } + + function E(t, e, r) { + for (var n, o = t.__k, i = 0; o && i < o.length; i++) (n = o[i]) && (n.__ = t, e = "function" == typeof n.type ? E(n, e, r) : P(r, n, n, o, n.__e, e)); + return e + } + + function S(t, e) { + return e = e || [], null == t || "boolean" == typeof t || (Array.isArray(t) ? t.some((function (t) { + S(t, e) + })) : e.push(t)), e + } + + function P(t, e, r, n, o, i) { + var u, a, c; + if (void 0 !== e.__d) u = e.__d, e.__d = void 0; else if (null == r || o != i || null == o.parentNode) t:if (null == i || i.parentNode !== t) t.appendChild(o), u = null; else { + for (a = i, c = 0; (a = a.nextSibling) && c < n.length; c += 2) if (a == o) break t; + t.insertBefore(o, i), u = i + } + return void 0 !== u ? u : o.nextSibling + } + + function A(t, e, r) { + "-" === e[0] ? t.setProperty(e, r) : t[e] = null == r ? "" : "number" != typeof r || p.test(e) ? r : r + "px" + } + + function k(t, e, r, n, o) { + var i; + t:if ("style" === e) if ("string" == typeof r) t.style.cssText = r; else { + if ("string" == typeof n && (t.style.cssText = n = ""), n) for (e in n) r && e in r || A(t.style, e, ""); + if (r) for (e in r) n && r[e] === n[e] || A(t.style, e, r[e]) + } else if ("o" === e[0] && "n" === e[1]) i = e !== (e = e.replace(/Capture$/, "")), e = e.toLowerCase() in t ? e.toLowerCase().slice(2) : e.slice(2), t.l || (t.l = {}), t.l[e + i] = r, r ? n || t.addEventListener(e, i ? T : D, i) : t.removeEventListener(e, i ? T : D, i); else if ("dangerouslySetInnerHTML" !== e) { + if (o) e = e.replace(/xlink[H:h]/, "h").replace(/sName$/, "s"); else if ("href" !== e && "list" !== e && "form" !== e && "tabIndex" !== e && "download" !== e && e in t) try { + t[e] = null == r ? "" : r; + break t + } catch (t) { + } + "function" == typeof r || (null != r && (!1 !== r || "a" === e[0] && "r" === e[1]) ? t.setAttribute(e, r) : t.removeAttribute(e)) + } + } + + function D(t) { + this.l[t.type + !1](o.event ? o.event(t) : t) + } + + function T(t) { + this.l[t.type + !0](o.event ? o.event(t) : t) + } + + function M(t, e, r, n, i, u, a, c, s) { + var l, f, p, h, y, v, g, O, _, w, x, E = e.type; + if (void 0 !== e.constructor) return null; + null != r.__h && (s = r.__h, c = e.__e = r.__e, e.__h = null, u = [c]), (l = o.__b) && l(e); + try { + t:if ("function" == typeof E) { + if (O = e.props, _ = (l = E.contextType) && n[l.__c], w = l ? _ ? _.props.value : l.__ : n, r.__c ? g = (f = e.__c = r.__c).__ = f.__E : ("prototype" in E && E.prototype.render ? e.__c = f = new E(O, w) : (e.__c = f = new m(O, w), f.constructor = E, f.render = L), _ && _.sub(f), f.props = O, f.state || (f.state = {}), f.context = w, f.__n = n, p = f.__d = !0, f.__h = []), null == f.__s && (f.__s = f.state), null != E.getDerivedStateFromProps && (f.__s == f.state && (f.__s = d({}, f.__s)), d(f.__s, E.getDerivedStateFromProps(O, f.__s))), h = f.props, y = f.state, p) null == E.getDerivedStateFromProps && null != f.componentWillMount && f.componentWillMount(), null != f.componentDidMount && f.__h.push(f.componentDidMount); else { + if (null == E.getDerivedStateFromProps && O !== h && null != f.componentWillReceiveProps && f.componentWillReceiveProps(O, w), !f.__e && null != f.shouldComponentUpdate && !1 === f.shouldComponentUpdate(O, f.__s, w) || e.__v === r.__v) { + f.props = O, f.state = f.__s, e.__v !== r.__v && (f.__d = !1), f.__v = e, e.__e = r.__e, e.__k = r.__k, e.__k.forEach((function (t) { + t && (t.__ = e) + })), f.__h.length && a.push(f); + break t + } + null != f.componentWillUpdate && f.componentWillUpdate(O, f.__s, w), null != f.componentDidUpdate && f.__h.push((function () { + f.componentDidUpdate(h, y, v) + })) + } + f.context = w, f.props = O, f.state = f.__s, (l = o.__r) && l(e), f.__d = !1, f.__v = e, f.__P = t, l = f.render(f.props, f.state, f.context), f.state = f.__s, null != f.getChildContext && (n = d(d({}, n), f.getChildContext())), p || null == f.getSnapshotBeforeUpdate || (v = f.getSnapshotBeforeUpdate(h, y)), x = null != l && l.type === b && null == l.key ? l.props.children : l, j(t, Array.isArray(x) ? x : [x], e, r, n, i, u, a, c, s), f.base = e.__e, e.__h = null, f.__h.length && a.push(f), g && (f.__E = f.__ = null), f.__e = !1 + } else null == u && e.__v === r.__v ? (e.__k = r.__k, e.__e = r.__e) : e.__e = C(r.__e, e, r, n, i, u, a, s); + (l = o.diffed) && l(e) + } catch (t) { + e.__v = null, (s || null != u) && (e.__e = c, e.__h = !!s, u[u.indexOf(c)] = null), o.__e(t, e, r) + } + } + + function N(t, e) { + o.__c && o.__c(e, t), t.some((function (e) { + try { + t = e.__h, e.__h = [], t.some((function (t) { + t.call(e) + })) + } catch (t) { + o.__e(t, e.__v) + } + })) + } + + function C(t, e, r, o, i, u, a, c) { + var s, f, p, d = r.props, y = e.props, v = e.type, g = 0; + if ("svg" === v && (i = !0), null != u) for (; g < u.length; g++) if ((s = u[g]) && "setAttribute" in s == !!v && (v ? s.localName === v : 3 === s.nodeType)) { + t = s, u[g] = null; + break + } + if (null == t) { + if (null === v) return document.createTextNode(y); + t = i ? document.createElementNS("http://www.w3.org/2000/svg", v) : document.createElement(v, y.is && y), u = null, c = !1 + } + if (null === v) d === y || c && t.data === y || (t.data = y); else { + if (u = u && n.call(t.childNodes), f = (d = r.props || l).dangerouslySetInnerHTML, p = y.dangerouslySetInnerHTML, !c) { + if (null != u) for (d = {}, g = 0; g < t.attributes.length; g++) d[t.attributes[g].name] = t.attributes[g].value; + (p || f) && (p && (f && p.__html == f.__html || p.__html === t.innerHTML) || (t.innerHTML = p && p.__html || "")) + } + if (function (t, e, r, n, o) { + var i; + for (i in r) "children" === i || "key" === i || i in e || k(t, i, null, r[i], n); + for (i in e) o && "function" != typeof e[i] || "children" === i || "key" === i || "value" === i || "checked" === i || r[i] === e[i] || k(t, i, e[i], r[i], n) + }(t, y, d, i, c), p) e.__k = []; else if (g = e.props.children, j(t, Array.isArray(g) ? g : [g], e, r, o, i && "foreignObject" !== v, u, a, u ? u[0] : r.__k && O(r, 0), c), null != u) for (g = u.length; g--;) null != u[g] && h(u[g]); + c || ("value" in y && void 0 !== (g = y.value) && (g !== d.value || g !== t.value || "progress" === v && !g) && k(t, "value", g, d.value, !1), "checked" in y && void 0 !== (g = y.checked) && g !== t.checked && k(t, "checked", g, d.checked, !1)) + } + return t + } + + function R(t, e, r) { + try { + "function" == typeof t ? t(e) : t.current = e + } catch (t) { + o.__e(t, r) + } + } + + function I(t, e, r) { + var n, i; + if (o.unmount && o.unmount(t), (n = t.ref) && (n.current && n.current !== t.__e || R(n, null, e)), null != (n = t.__c)) { + if (n.componentWillUnmount) try { + n.componentWillUnmount() + } catch (t) { + o.__e(t, e) + } + n.base = n.__P = null + } + if (n = t.__k) for (i = 0; i < n.length; i++) n[i] && I(n[i], e, "function" != typeof t.type); + r || null == t.__e || h(t.__e), t.__e = t.__d = void 0 + } + + function L(t, e, r) { + return this.constructor(t, r) + } + + function z(t, e, r) { + var i, u, a; + o.__ && o.__(t, e), u = (i = "function" == typeof r) ? null : r && r.__k || e.__k, a = [], M(e, t = (!i && r || e).__k = y(b, null, [t]), u || l, l, void 0 !== e.ownerSVGElement, !i && r ? [r] : u ? null : e.firstChild ? n.call(e.childNodes) : null, a, !i && r ? r : u ? u.__e : e.firstChild, i), N(a, t) + } + + function B(t, e) { + z(t, e, B) + } + + function U(t, e, r) { + var o, i, u, a = d({}, t.props); + for (u in e) "key" == u ? o = e[u] : "ref" == u ? i = e[u] : a[u] = e[u]; + return arguments.length > 2 && (a.children = arguments.length > 3 ? n.call(arguments, 2) : r), v(t.type, a, o || t.key, i || t.ref, null) + } + + function F(t, e) { + var r = { + __c: e = "__cC" + s++, __: t, Consumer: function (t, e) { + return t.children(e) + }, Provider: function (t) { + var r, n; + return this.getChildContext || (r = [], (n = {})[e] = this, this.getChildContext = function () { + return n + }, this.shouldComponentUpdate = function (t) { + this.props.value !== t.value && r.some(w) + }, this.sub = function (t) { + r.push(t); + var e = t.componentWillUnmount; + t.componentWillUnmount = function () { + r.splice(r.indexOf(t), 1), e && e.call(t) + } + }), t.children + } + }; + return r.Provider.__ = r.Consumer.contextType = r + } + + n = f.slice, o = { + __e: function (t, e) { + for (var r, n, o; e = e.__;) if ((r = e.__c) && !r.__) try { + if ((n = r.constructor) && null != n.getDerivedStateFromError && (r.setState(n.getDerivedStateFromError(t)), o = r.__d), null != r.componentDidCatch && (r.componentDidCatch(t), o = r.__d), o) return r.__E = r + } catch (e) { + t = e + } + throw t + } + }, i = 0, m.prototype.setState = function (t, e) { + var r; + r = null != this.__s && this.__s !== this.state ? this.__s : this.__s = d({}, this.state), "function" == typeof t && (t = t(d({}, r), this.props)), t && d(r, t), null != t && this.__v && (e && this.__h.push(e), w(this)) + }, m.prototype.forceUpdate = function (t) { + this.__v && (this.__e = !0, t && this.__h.push(t), w(this)) + }, m.prototype.render = b, u = [], a = "function" == typeof Promise ? Promise.prototype.then.bind(Promise.resolve()) : setTimeout, x.__r = 0, s = 0 + }, function (t, e, r) { + "use strict"; + (function (t, n) { + r.d(e, "a", (function () { + return _ + })), r.d(e, "b", (function () { + return or + })), r.d(e, "c", (function () { + return Gt + })), r.d(e, "d", (function () { + return xt + })), r.d(e, "e", (function () { + return ht + })), r.d(e, "f", (function () { + return dt + })), r.d(e, "g", (function () { + return wt + })), r.d(e, "h", (function () { + return gr + })), r.d(e, "i", (function () { + return ut + })), r.d(e, "j", (function () { + return _t + })), r.d(e, "k", (function () { + return te + })), r.d(e, "l", (function () { + return oe + })), r.d(e, "m", (function () { + return rt + })), r.d(e, "n", (function () { + return le + })), r.d(e, "o", (function () { + return j + })), r.d(e, "p", (function () { + return Pe + })), r.d(e, "q", (function () { + return fe + })), r.d(e, "r", (function () { + return be + })), r.d(e, "s", (function () { + return vr + })), r.d(e, "t", (function () { + return he + })), r.d(e, "u", (function () { + return re + })), r.d(e, "v", (function () { + return _e + })), r.d(e, "w", (function () { + return we + })), r.d(e, "x", (function () { + return je + })), r.d(e, "y", (function () { + return er + })), r.d(e, "z", (function () { + return ir + })), r.d(e, "A", (function () { + return yr + })), r.d(e, "B", (function () { + return Ee + })), r.d(e, "C", (function () { + return Z + })), r.d(e, "D", (function () { + return ke + })), r.d(e, "E", (function () { + return ce + })), r.d(e, "F", (function () { + return ae + })), r.d(e, "G", (function () { + return ee + })), r.d(e, "H", (function () { + return Zt + })), r.d(e, "I", (function () { + return Ne + })), r.d(e, "J", (function () { + return Re + })), r.d(e, "K", (function () { + return lt + })), r.d(e, "L", (function () { + return Se + })), r.d(e, "M", (function () { + return Ie + })); + var o = []; + Object.freeze(o); + var i = {}; + + function u() { + return ++Rt.mobxGuid + } + + function a(t) { + throw c(!1, t), "X" + } + + function c(t, e) { + if (!t) throw new Error("[mobx] " + (e || "An invariant failed, however the error is obfuscated because this is a production build.")) + } + + Object.freeze(i); + + function s(t) { + var e = !1; + return function () { + if (!e) return e = !0, t.apply(this, arguments) + } + } + + var l = function () { + }; + + function f(t) { + return null !== t && "object" == typeof t + } + + function p(t) { + if (null === t || "object" != typeof t) return !1; + var e = Object.getPrototypeOf(t); + return e === Object.prototype || null === e + } + + function d(t, e, r) { + Object.defineProperty(t, e, {enumerable: !1, writable: !0, configurable: !0, value: r}) + } + + function h(t, e) { + var r = "isMobX" + t; + return e.prototype[r] = !0, function (t) { + return f(t) && !0 === t[r] + } + } + + function y(t) { + return t instanceof Map + } + + function v(t) { + return t instanceof Set + } + + function g(t) { + var e = new Set; + for (var r in t) e.add(r); + return Object.getOwnPropertySymbols(t).forEach((function (r) { + Object.getOwnPropertyDescriptor(t, r).enumerable && e.add(r) + })), Array.from(e) + } + + function b(t) { + return t && t.toString ? t.toString() : new String(t).toString() + } + + function m(t) { + return null === t ? null : "object" == typeof t ? "" + t : t + } + + var O = "undefined" != typeof Reflect && Reflect.ownKeys ? Reflect.ownKeys : Object.getOwnPropertySymbols ? function (t) { + return Object.getOwnPropertyNames(t).concat(Object.getOwnPropertySymbols(t)) + } : Object.getOwnPropertyNames, _ = Symbol("mobx administration"), w = function () { + function t(t) { + void 0 === t && (t = "Atom@" + u()), this.name = t, this.isPendingUnobservation = !1, this.isBeingObserved = !1, this.observers = new Set, this.diffValue = 0, this.lastAccessedBy = 0, this.lowestObserverState = J.NOT_TRACKING + } + + return t.prototype.onBecomeObserved = function () { + this.onBecomeObservedListeners && this.onBecomeObservedListeners.forEach((function (t) { + return t() + })) + }, t.prototype.onBecomeUnobserved = function () { + this.onBecomeUnobservedListeners && this.onBecomeUnobservedListeners.forEach((function (t) { + return t() + })) + }, t.prototype.reportObserved = function () { + return Ft(this) + }, t.prototype.reportChanged = function () { + Bt(), function (t) { + if (t.lowestObserverState === J.STALE) return; + t.lowestObserverState = J.STALE, t.observers.forEach((function (e) { + e.dependenciesState === J.UP_TO_DATE && (e.isTracing !== Q.NONE && Ht(e, t), e.onBecomeStale()), e.dependenciesState = J.STALE + })) + }(this), Ut() + }, t.prototype.toString = function () { + return this.name + }, t + }(), x = h("Atom", w); + + function j(t, e, r) { + void 0 === e && (e = l), void 0 === r && (r = l); + var n, o = new w(t); + return e !== l && se("onBecomeObserved", o, e, n), r !== l && ce(o, r), o + } + + var E = { + identity: function (t, e) { + return t === e + }, structural: function (t, e) { + return mr(t, e) + }, default: function (t, e) { + return Object.is(t, e) + }, shallow: function (t, e) { + return mr(t, e, 1) + } + }, S = function (t, e) { + return S = Object.setPrototypeOf || {__proto__: []} instanceof Array && function (t, e) { + t.__proto__ = e + } || function (t, e) { + for (var r in e) e.hasOwnProperty(r) && (t[r] = e[r]) + }, S(t, e) + }; + /*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + var P = function () { + return P = Object.assign || function (t) { + for (var e, r = 1, n = arguments.length; r < n; r++) for (var o in e = arguments[r]) Object.prototype.hasOwnProperty.call(e, o) && (t[o] = e[o]); + return t + }, P.apply(this, arguments) + }; + + function A(t) { + var e = "function" == typeof Symbol && t[Symbol.iterator], r = 0; + return e ? e.call(t) : { + next: function () { + return t && r >= t.length && (t = void 0), {value: t && t[r++], done: !t} + } + } + } + + function k(t, e) { + var r = "function" == typeof Symbol && t[Symbol.iterator]; + if (!r) return t; + var n, o, i = r.call(t), u = []; + try { + for (; (void 0 === e || e-- > 0) && !(n = i.next()).done;) u.push(n.value) + } catch (t) { + o = {error: t} + } finally { + try { + n && !n.done && (r = i.return) && r.call(i) + } finally { + if (o) throw o.error + } + } + return u + } + + function D() { + for (var t = [], e = 0; e < arguments.length; e++) t = t.concat(k(arguments[e])); + return t + } + + var T = Symbol("mobx did run lazy initializers"), M = Symbol("mobx pending decorators"), N = {}, C = {}; + + function R(t, e) { + var r = e ? N : C; + return r[t] || (r[t] = { + configurable: !0, enumerable: e, get: function () { + return I(this), this[t] + }, set: function (e) { + I(this), this[t] = e + } + }) + } + + function I(t) { + var e, r; + if (!0 !== t[T]) { + var n = t[M]; + if (n) { + d(t, T, !0); + var o = D(Object.getOwnPropertySymbols(n), Object.keys(n)); + try { + for (var i = A(o), u = i.next(); !u.done; u = i.next()) { + var a = n[u.value]; + a.propertyCreator(t, a.prop, a.descriptor, a.decoratorTarget, a.decoratorArguments) + } + } catch (t) { + e = {error: t} + } finally { + try { + u && !u.done && (r = i.return) && r.call(i) + } finally { + if (e) throw e.error + } + } + } + } + } + + function L(t, e) { + return function () { + var r, n = function (n, o, i, u) { + if (!0 === u) return e(n, o, i, n, r), null; + if (!Object.prototype.hasOwnProperty.call(n, M)) { + var a = n[M]; + d(n, M, P({}, a)) + } + return n[M][o] = { + prop: o, + propertyCreator: e, + descriptor: i, + decoratorTarget: n, + decoratorArguments: r + }, R(o, t) + }; + return z(arguments) ? (r = o, n.apply(null, arguments)) : (r = Array.prototype.slice.call(arguments), n) + } + } + + function z(t) { + return (2 === t.length || 3 === t.length) && ("string" == typeof t[1] || "symbol" == typeof t[1]) || 4 === t.length && !0 === t[3] + } + + function B(t, e, r) { + return je(t) ? t : Array.isArray(t) ? Z.array(t, {name: r}) : p(t) ? Z.object(t, void 0, {name: r}) : y(t) ? Z.map(t, {name: r}) : v(t) ? Z.set(t, {name: r}) : t + } + + function U(t) { + return t + } + + function F(e) { + c(e); + var r = L(!0, (function (t, r, n, o, i) { + var u = n ? n.initializer ? n.initializer.call(t) : n.value : void 0; + lr(t).addObservableProp(r, u, e) + })), n = (void 0 !== t && t.env, r); + return n.enhancer = e, n + } + + var H = {deep: !0, name: void 0, defaultDecorator: void 0, proxy: !0}; + + function X(t) { + return null == t ? H : "string" == typeof t ? {name: t, deep: !0, proxy: !0} : t + } + + Object.freeze(H); + var G = F(B), Y = F((function (t, e, r) { + return null == t || yr(t) || er(t) || ir(t) || cr(t) ? t : Array.isArray(t) ? Z.array(t, { + name: r, + deep: !1 + }) : p(t) ? Z.object(t, void 0, {name: r, deep: !1}) : y(t) ? Z.map(t, { + name: r, + deep: !1 + }) : v(t) ? Z.set(t, {name: r, deep: !1}) : a(!1) + })), V = F(U), W = F((function (t, e, r) { + return mr(t, e) ? e : t + })); + + function K(t) { + return t.defaultDecorator ? t.defaultDecorator.enhancer : !1 === t.deep ? U : B + } + + var $ = { + box: function (t, e) { + arguments.length > 2 && q("box"); + var r = X(e); + return new St(t, K(r), r.name, !0, r.equals) + }, array: function (t, e) { + arguments.length > 2 && q("array"); + var r = X(e); + return Ze(t, K(r), r.name) + }, map: function (t, e) { + arguments.length > 2 && q("map"); + var r = X(e); + return new or(t, K(r), r.name) + }, set: function (t, e) { + arguments.length > 2 && q("set"); + var r = X(e); + return new ar(t, K(r), r.name) + }, object: function (t, e, r) { + "string" == typeof arguments[1] && q("object"); + var n = X(r); + if (!1 === n.proxy) return fe({}, t, e, n); + var o = pe(n), i = fe({}, void 0, void 0, n), u = He(i); + return de(u, t, e, o), u + }, ref: V, shallow: Y, deep: G, struct: W + }, Z = function (t, e, r) { + if ("string" == typeof arguments[1] || "symbol" == typeof arguments[1]) return G.apply(null, arguments); + if (je(t)) return t; + var n = p(t) ? Z.object(t, e, r) : Array.isArray(t) ? Z.array(t, e) : y(t) ? Z.map(t, e) : v(t) ? Z.set(t, e) : t; + if (n !== t) return n; + a(!1) + }; + + function q(t) { + a("Expected one or two arguments to observable." + t + ". Did you accidentally try to use observable." + t + " as decorator?") + } + + Object.keys($).forEach((function (t) { + return Z[t] = $[t] + })); + var J, Q, tt = L(!1, (function (t, e, r, n, o) { + var i = r.get, u = r.set, a = o[0] || {}; + lr(t).addComputedProp(t, e, P({get: i, set: u, context: t}, a)) + })), et = tt({equals: E.structural}), rt = function (t, e, r) { + if ("string" == typeof e) return tt.apply(null, arguments); + if (null !== t && "object" == typeof t && 1 === arguments.length) return tt.apply(null, arguments); + var n = "object" == typeof e ? e : {}; + return n.get = t, n.set = "function" == typeof e ? e : n.set, n.name = n.name || t.name || "", new At(n) + }; + rt.struct = et, function (t) { + t[t.NOT_TRACKING = -1] = "NOT_TRACKING", t[t.UP_TO_DATE = 0] = "UP_TO_DATE", t[t.POSSIBLY_STALE = 1] = "POSSIBLY_STALE", t[t.STALE = 2] = "STALE" + }(J || (J = {})), function (t) { + t[t.NONE = 0] = "NONE", t[t.LOG = 1] = "LOG", t[t.BREAK = 2] = "BREAK" + }(Q || (Q = {})); + var nt = function (t) { + this.cause = t + }; + + function ot(t) { + return t instanceof nt + } + + function it(t) { + switch (t.dependenciesState) { + case J.UP_TO_DATE: + return !1; + case J.NOT_TRACKING: + case J.STALE: + return !0; + case J.POSSIBLY_STALE: + for (var e = dt(!0), r = ft(), n = t.observing, o = n.length, i = 0; i < o; i++) { + var u = n[i]; + if (kt(u)) { + if (Rt.disableErrorBoundaries) u.get(); else try { + u.get() + } catch (t) { + return pt(r), ht(e), !0 + } + if (t.dependenciesState === J.STALE) return pt(r), ht(e), !0 + } + } + return yt(t), pt(r), ht(e), !1 + } + } + + function ut() { + return null !== Rt.trackingDerivation + } + + function at(t) { + var e = t.observers.size > 0; + Rt.computationDepth > 0 && e && a(!1), Rt.allowStateChanges || !e && "strict" !== Rt.enforceActions || a(!1) + } + + function ct(t, e, r) { + var n = dt(!0); + yt(t), t.newObserving = new Array(t.observing.length + 100), t.unboundDepsCount = 0, t.runId = ++Rt.runId; + var o, i = Rt.trackingDerivation; + if (Rt.trackingDerivation = t, !0 === Rt.disableErrorBoundaries) o = e.call(r); else try { + o = e.call(r) + } catch (t) { + o = new nt(t) + } + return Rt.trackingDerivation = i, function (t) { + for (var e = t.observing, r = t.observing = t.newObserving, n = J.UP_TO_DATE, o = 0, i = t.unboundDepsCount, u = 0; u < i; u++) { + 0 === (a = r[u]).diffValue && (a.diffValue = 1, o !== u && (r[o] = a), o++), a.dependenciesState > n && (n = a.dependenciesState) + } + r.length = o, t.newObserving = null, i = e.length; + for (; i--;) { + 0 === (a = e[i]).diffValue && Lt(a, t), a.diffValue = 0 + } + for (; o--;) { + var a; + 1 === (a = r[o]).diffValue && (a.diffValue = 0, It(a, t)) + } + n !== J.UP_TO_DATE && (t.dependenciesState = n, t.onBecomeStale()) + }(t), ht(n), o + } + + function st(t) { + var e = t.observing; + t.observing = []; + for (var r = e.length; r--;) Lt(e[r], t); + t.dependenciesState = J.NOT_TRACKING + } + + function lt(t) { + var e = ft(); + try { + return t() + } finally { + pt(e) + } + } + + function ft() { + var t = Rt.trackingDerivation; + return Rt.trackingDerivation = null, t + } + + function pt(t) { + Rt.trackingDerivation = t + } + + function dt(t) { + var e = Rt.allowStateReads; + return Rt.allowStateReads = t, e + } + + function ht(t) { + Rt.allowStateReads = t + } + + function yt(t) { + if (t.dependenciesState !== J.UP_TO_DATE) { + t.dependenciesState = J.UP_TO_DATE; + for (var e = t.observing, r = e.length; r--;) e[r].lowestObserverState = J.UP_TO_DATE + } + } + + var vt = 0, gt = 1, bt = Object.getOwnPropertyDescriptor((function () { + }), "name"); + bt && bt.configurable; + + function mt(t, e, r) { + var n = function () { + return Ot(t, e, r || this, arguments) + }; + return n.isMobxAction = !0, n + } + + function Ot(t, e, r, n) { + var o = _t(t, r, n); + try { + return e.apply(r, n) + } catch (t) { + throw o.error = t, t + } finally { + wt(o) + } + } + + function _t(t, e, r) { + var n = 0, o = ft(); + Bt(); + var i = { + prevDerivation: o, + prevAllowStateChanges: jt(!0), + prevAllowStateReads: dt(!0), + notifySpy: false, + startTime: n, + actionId: gt++, + parentActionId: vt + }; + return vt = i.actionId, i + } + + function wt(t) { + vt !== t.actionId && a("invalid action stack. did you forget to finish an action?"), vt = t.parentActionId, void 0 !== t.error && (Rt.suppressReactionErrors = !0), Et(t.prevAllowStateChanges), ht(t.prevAllowStateReads), Ut(), pt(t.prevDerivation), t.notifySpy, Rt.suppressReactionErrors = !1 + } + + function xt(t, e) { + var r, n = jt(t); + try { + r = e() + } finally { + Et(n) + } + return r + } + + function jt(t) { + var e = Rt.allowStateChanges; + return Rt.allowStateChanges = t, e + } + + function Et(t) { + Rt.allowStateChanges = t + } + + var St = function (t) { + function e(e, r, n, o, i) { + void 0 === n && (n = "ObservableValue@" + u()), void 0 === o && (o = !0), void 0 === i && (i = E.default); + var a = t.call(this, n) || this; + return a.enhancer = r, a.name = n, a.equals = i, a.hasUnreportedChange = !1, a.value = r(e, void 0, n), a + } + + return function (t, e) { + function r() { + this.constructor = t + } + + S(t, e), t.prototype = null === e ? Object.create(e) : (r.prototype = e.prototype, new r) + }(e, t), e.prototype.dehanceValue = function (t) { + return void 0 !== this.dehancer ? this.dehancer(t) : t + }, e.prototype.set = function (t) { + this.value; + if ((t = this.prepareNewValue(t)) !== Rt.UNCHANGED) { + false, this.setNewValue(t) + } + }, e.prototype.prepareNewValue = function (t) { + if (at(this), Xe(this)) { + var e = Ye(this, {object: this, type: "update", newValue: t}); + if (!e) return Rt.UNCHANGED; + t = e.newValue + } + return t = this.enhancer(t, this.value, this.name), this.equals(this.value, t) ? Rt.UNCHANGED : t + }, e.prototype.setNewValue = function (t) { + var e = this.value; + this.value = t, this.reportChanged(), Ve(this) && Ke(this, { + type: "update", + object: this, + newValue: t, + oldValue: e + }) + }, e.prototype.get = function () { + return this.reportObserved(), this.dehanceValue(this.value) + }, e.prototype.intercept = function (t) { + return Ge(this, t) + }, e.prototype.observe = function (t, e) { + return e && t({object: this, type: "update", newValue: this.value, oldValue: void 0}), We(this, t) + }, e.prototype.toJSON = function () { + return this.get() + }, e.prototype.toString = function () { + return this.name + "[" + this.value + "]" + }, e.prototype.valueOf = function () { + return m(this.get()) + }, e.prototype[Symbol.toPrimitive] = function () { + return this.valueOf() + }, e + }(w), Pt = h("ObservableValue", St), At = function () { + function t(t) { + this.dependenciesState = J.NOT_TRACKING, this.observing = [], this.newObserving = null, this.isBeingObserved = !1, this.isPendingUnobservation = !1, this.observers = new Set, this.diffValue = 0, this.runId = 0, this.lastAccessedBy = 0, this.lowestObserverState = J.UP_TO_DATE, this.unboundDepsCount = 0, this.__mapid = "#" + u(), this.value = new nt(null), this.isComputing = !1, this.isRunningSetter = !1, this.isTracing = Q.NONE, c(t.get, "missing option for computed: get"), this.derivation = t.get, this.name = t.name || "ComputedValue@" + u(), t.set && (this.setter = mt(this.name + "-setter", t.set)), this.equals = t.equals || (t.compareStructural || t.struct ? E.structural : E.default), this.scope = t.context, this.requiresReaction = !!t.requiresReaction, this.keepAlive = !!t.keepAlive + } + + return t.prototype.onBecomeStale = function () { + !function (t) { + if (t.lowestObserverState !== J.UP_TO_DATE) return; + t.lowestObserverState = J.POSSIBLY_STALE, t.observers.forEach((function (e) { + e.dependenciesState === J.UP_TO_DATE && (e.dependenciesState = J.POSSIBLY_STALE, e.isTracing !== Q.NONE && Ht(e, t), e.onBecomeStale()) + })) + }(this) + }, t.prototype.onBecomeObserved = function () { + this.onBecomeObservedListeners && this.onBecomeObservedListeners.forEach((function (t) { + return t() + })) + }, t.prototype.onBecomeUnobserved = function () { + this.onBecomeUnobservedListeners && this.onBecomeUnobservedListeners.forEach((function (t) { + return t() + })) + }, t.prototype.get = function () { + this.isComputing && a("Cycle detected in computation " + this.name + ": " + this.derivation), 0 !== Rt.inBatch || 0 !== this.observers.size || this.keepAlive ? (Ft(this), it(this) && this.trackAndCompute() && function (t) { + if (t.lowestObserverState === J.STALE) return; + t.lowestObserverState = J.STALE, t.observers.forEach((function (e) { + e.dependenciesState === J.POSSIBLY_STALE ? e.dependenciesState = J.STALE : e.dependenciesState === J.UP_TO_DATE && (t.lowestObserverState = J.UP_TO_DATE) + })) + }(this)) : it(this) && (this.warnAboutUntrackedRead(), Bt(), this.value = this.computeValue(!1), Ut()); + var t = this.value; + if (ot(t)) throw t.cause; + return t + }, t.prototype.peek = function () { + var t = this.computeValue(!1); + if (ot(t)) throw t.cause; + return t + }, t.prototype.set = function (t) { + if (this.setter) { + c(!this.isRunningSetter, "The setter of computed value '" + this.name + "' is trying to update itself. Did you intend to update an _observable_ value, instead of the computed property?"), this.isRunningSetter = !0; + try { + this.setter.call(this.scope, t) + } finally { + this.isRunningSetter = !1 + } + } else c(!1, !1) + }, t.prototype.trackAndCompute = function () { + var t = this.value, e = this.dependenciesState === J.NOT_TRACKING, r = this.computeValue(!0), + n = e || ot(t) || ot(r) || !this.equals(t, r); + return n && (this.value = r), n + }, t.prototype.computeValue = function (t) { + var e; + if (this.isComputing = !0, Rt.computationDepth++, t) e = ct(this, this.derivation, this.scope); else if (!0 === Rt.disableErrorBoundaries) e = this.derivation.call(this.scope); else try { + e = this.derivation.call(this.scope) + } catch (t) { + e = new nt(t) + } + return Rt.computationDepth--, this.isComputing = !1, e + }, t.prototype.suspend = function () { + this.keepAlive || (st(this), this.value = void 0) + }, t.prototype.observe = function (t, e) { + var r = this, n = !0, o = void 0; + return oe((function () { + var i = r.get(); + if (!n || e) { + var u = ft(); + t({type: "update", object: r, newValue: i, oldValue: o}), pt(u) + } + n = !1, o = i + })) + }, t.prototype.warnAboutUntrackedRead = function () { + }, t.prototype.toJSON = function () { + return this.get() + }, t.prototype.toString = function () { + return this.name + "[" + this.derivation.toString() + "]" + }, t.prototype.valueOf = function () { + return m(this.get()) + }, t.prototype[Symbol.toPrimitive] = function () { + return this.valueOf() + }, t + }(), kt = h("ComputedValue", At), Dt = function () { + this.version = 5, this.UNCHANGED = {}, this.trackingDerivation = null, this.computationDepth = 0, this.runId = 0, this.mobxGuid = 0, this.inBatch = 0, this.pendingUnobservations = [], this.pendingReactions = [], this.isRunningReactions = !1, this.allowStateChanges = !0, this.allowStateReads = !0, this.enforceActions = !1, this.spyListeners = [], this.globalReactionErrorHandlers = [], this.computedRequiresReaction = !1, this.reactionRequiresObservable = !1, this.observableRequiresReaction = !1, this.computedConfigurable = !1, this.disableErrorBoundaries = !1, this.suppressReactionErrors = !1 + }, Tt = {}; + + function Mt() { + return "undefined" != typeof window ? window : void 0 !== n ? n : "undefined" != typeof self ? self : Tt + } + + var Nt = !0, Ct = !1, Rt = function () { + var t = Mt(); + return t.__mobxInstanceCount > 0 && !t.__mobxGlobals && (Nt = !1), t.__mobxGlobals && t.__mobxGlobals.version !== (new Dt).version && (Nt = !1), Nt ? t.__mobxGlobals ? (t.__mobxInstanceCount += 1, t.__mobxGlobals.UNCHANGED || (t.__mobxGlobals.UNCHANGED = {}), t.__mobxGlobals) : (t.__mobxInstanceCount = 1, t.__mobxGlobals = new Dt) : (setTimeout((function () { + Ct || a("There are multiple, different versions of MobX active. Make sure MobX is loaded only once or use `configure({ isolateGlobalState: true })`") + }), 1), new Dt) + }(); + + function It(t, e) { + t.observers.add(e), t.lowestObserverState > e.dependenciesState && (t.lowestObserverState = e.dependenciesState) + } + + function Lt(t, e) { + t.observers.delete(e), 0 === t.observers.size && zt(t) + } + + function zt(t) { + !1 === t.isPendingUnobservation && (t.isPendingUnobservation = !0, Rt.pendingUnobservations.push(t)) + } + + function Bt() { + Rt.inBatch++ + } + + function Ut() { + if (0 == --Rt.inBatch) { + Vt(); + for (var t = Rt.pendingUnobservations, e = 0; e < t.length; e++) { + var r = t[e]; + r.isPendingUnobservation = !1, 0 === r.observers.size && (r.isBeingObserved && (r.isBeingObserved = !1, r.onBecomeUnobserved()), r instanceof At && r.suspend()) + } + Rt.pendingUnobservations = [] + } + } + + function Ft(t) { + var e = Rt.trackingDerivation; + return null !== e ? (e.runId !== t.lastAccessedBy && (t.lastAccessedBy = e.runId, e.newObserving[e.unboundDepsCount++] = t, t.isBeingObserved || (t.isBeingObserved = !0, t.onBecomeObserved())), !0) : (0 === t.observers.size && Rt.inBatch > 0 && zt(t), !1) + } + + function Ht(t, e) { + if (t.isTracing === Q.BREAK) { + var r = []; + Xt(he(t), r, 1), new Function("debugger;\n/*\nTracing '" + t.name + "'\n\nYou are entering this break point because derivation '" + t.name + "' is being traced and '" + e.name + "' is now forcing it to update.\nJust follow the stacktrace you should now see in the devtools to see precisely what piece of your code is causing this update\nThe stackframe you are looking for is at least ~6-8 stack-frames up.\n\n" + (t instanceof At ? t.derivation.toString().replace(/[*]\//g, "/") : "") + "\n\nThe dependencies for this derivation are:\n\n" + r.join("\n") + "\n*/\n ")() + } + } + + function Xt(t, e, r) { + e.length >= 1e3 ? e.push("(and many more)") : (e.push("" + new Array(r).join("\t") + t.name), t.dependencies && t.dependencies.forEach((function (t) { + return Xt(t, e, r + 1) + }))) + } + + var Gt = function () { + function t(t, e, r, n) { + void 0 === t && (t = "Reaction@" + u()), void 0 === n && (n = !1), this.name = t, this.onInvalidate = e, this.errorHandler = r, this.requiresObservable = n, this.observing = [], this.newObserving = [], this.dependenciesState = J.NOT_TRACKING, this.diffValue = 0, this.runId = 0, this.unboundDepsCount = 0, this.__mapid = "#" + u(), this.isDisposed = !1, this._isScheduled = !1, this._isTrackPending = !1, this._isRunning = !1, this.isTracing = Q.NONE + } + + return t.prototype.onBecomeStale = function () { + this.schedule() + }, t.prototype.schedule = function () { + this._isScheduled || (this._isScheduled = !0, Rt.pendingReactions.push(this), Vt()) + }, t.prototype.isScheduled = function () { + return this._isScheduled + }, t.prototype.runReaction = function () { + if (!this.isDisposed) { + if (Bt(), this._isScheduled = !1, it(this)) { + this._isTrackPending = !0; + try { + this.onInvalidate(), this._isTrackPending + } catch (t) { + this.reportExceptionInDerivation(t) + } + } + Ut() + } + }, t.prototype.track = function (t) { + if (!this.isDisposed) { + Bt(); + false, this._isRunning = !0; + var e = ct(this, t, void 0); + this._isRunning = !1, this._isTrackPending = !1, this.isDisposed && st(this), ot(e) && this.reportExceptionInDerivation(e.cause), Ut() + } + }, t.prototype.reportExceptionInDerivation = function (t) { + var e = this; + if (this.errorHandler) this.errorHandler(t, this); else { + if (Rt.disableErrorBoundaries) throw t; + Rt.suppressReactionErrors, Rt.globalReactionErrorHandlers.forEach((function (r) { + return r(t, e) + })) + } + }, t.prototype.dispose = function () { + this.isDisposed || (this.isDisposed = !0, this._isRunning || (Bt(), st(this), Ut())) + }, t.prototype.getDisposer = function () { + var t = this.dispose.bind(this); + return t[_] = this, t + }, t.prototype.toString = function () { + return "Reaction[" + this.name + "]" + }, t.prototype.trace = function (t) { + void 0 === t && (t = !1), function () { + for (var t = [], e = 0; e < arguments.length; e++) t[e] = arguments[e]; + var r = !1; + "boolean" == typeof t[t.length - 1] && (r = t.pop()); + var n = Ce(t); + if (!n) return a(!1); + n.isTracing, Q.NONE; + n.isTracing = r ? Q.BREAK : Q.LOG + }(this, t) + }, t + }(); + var Yt = function (t) { + return t() + }; + + function Vt() { + Rt.inBatch > 0 || Rt.isRunningReactions || Yt(Wt) + } + + function Wt() { + Rt.isRunningReactions = !0; + for (var t = Rt.pendingReactions, e = 0; t.length > 0;) { + 100 == ++e && t.splice(0); + for (var r = t.splice(0), n = 0, o = r.length; n < o; n++) r[n].runReaction() + } + Rt.isRunningReactions = !1 + } + + var Kt = h("Reaction", Gt); + + function $t(t) { + var e = Yt; + Yt = function (r) { + return t((function () { + return e(r) + })) + } + } + + function Zt(t) { + return function () { + } + } + + function qt() { + a(!1) + } + + function Jt(t) { + return function (e, r, n) { + if (n) { + if (n.value) return {value: mt(t, n.value), enumerable: !1, configurable: !0, writable: !0}; + var o = n.initializer; + return { + enumerable: !1, configurable: !0, writable: !0, initializer: function () { + return mt(t, o.call(this)) + } + } + } + return Qt(t).apply(this, arguments) + } + } + + function Qt(t) { + return function (e, r, n) { + Object.defineProperty(e, r, { + configurable: !0, enumerable: !1, get: function () { + }, set: function (e) { + d(this, r, te(t, e)) + } + }) + } + } + + var te = function (t, e, r, n) { + return 1 === arguments.length && "function" == typeof t ? mt(t.name || "", t) : 2 === arguments.length && "function" == typeof e ? mt(t, e) : 1 === arguments.length && "string" == typeof t ? Jt(t) : !0 !== n ? Jt(e).apply(null, arguments) : void d(t, e, mt(t.name || e, r.value, this)) + }; + + function ee(t, e) { + return Ot("string" == typeof t ? t : t.name || "", "function" == typeof t ? t : e, this, void 0) + } + + function re(t) { + return "function" == typeof t && !0 === t.isMobxAction + } + + function ne(t, e, r) { + d(t, e, mt(e, r.bind(t))) + } + + function oe(t, e) { + void 0 === e && (e = i); + var r, n = e && e.name || t.name || "Autorun@" + u(); + if (!e.scheduler && !e.delay) r = new Gt(n, (function () { + this.track(c) + }), e.onError, e.requiresObservable); else { + var o = ue(e), a = !1; + r = new Gt(n, (function () { + a || (a = !0, o((function () { + a = !1, r.isDisposed || r.track(c) + }))) + }), e.onError, e.requiresObservable) + } + + function c() { + t(r) + } + + return r.schedule(), r.getDisposer() + } + + te.bound = function (t, e, r, n) { + return !0 === n ? (ne(t, e, r.value), null) : r ? { + configurable: !0, enumerable: !1, get: function () { + return ne(this, e, r.value || r.initializer.call(this)), this[e] + }, set: qt + } : { + enumerable: !1, configurable: !0, set: function (t) { + ne(this, e, t) + }, get: function () { + } + } + }; + var ie = function (t) { + return t() + }; + + function ue(t) { + return t.scheduler ? t.scheduler : t.delay ? function (e) { + return setTimeout(e, t.delay) + } : ie + } + + function ae(t, e, r) { + void 0 === r && (r = i); + var n, o, a, c = r.name || "Reaction@" + u(), s = te(c, r.onError ? (n = r.onError, o = e, function () { + try { + return o.apply(this, arguments) + } catch (t) { + n.call(this, t) + } + }) : e), l = !r.scheduler && !r.delay, f = ue(r), p = !0, d = !1, + h = r.compareStructural ? E.structural : r.equals || E.default, y = new Gt(c, (function () { + p || l ? v() : d || (d = !0, f(v)) + }), r.onError, r.requiresObservable); + + function v() { + if (d = !1, !y.isDisposed) { + var e = !1; + y.track((function () { + var r = t(y); + e = p || !h(a, r), a = r + })), p && r.fireImmediately && s(a, y), p || !0 !== e || s(a, y), p && (p = !1) + } + } + + return y.schedule(), y.getDisposer() + } + + function ce(t, e, r) { + return se("onBecomeUnobserved", t, e, r) + } + + function se(t, e, r, n) { + var o = "function" == typeof n ? vr(e, r) : vr(e), i = "function" == typeof n ? n : r, + u = t + "Listeners"; + return o[u] ? o[u].add(i) : o[u] = new Set([i]), "function" != typeof o[t] ? a(!1) : function () { + var t = o[u]; + t && (t.delete(i), 0 === t.size && delete o[u]) + } + } + + function le(t) { + var e = t.enforceActions, r = t.computedRequiresReaction, n = t.computedConfigurable, + o = t.disableErrorBoundaries, i = t.reactionScheduler, u = t.reactionRequiresObservable, + c = t.observableRequiresReaction; + if (!0 === t.isolateGlobalState && ((Rt.pendingReactions.length || Rt.inBatch || Rt.isRunningReactions) && a("isolateGlobalState should be called before MobX is running any reactions"), Ct = !0, Nt && (0 == --Mt().__mobxInstanceCount && (Mt().__mobxGlobals = void 0), Rt = new Dt)), void 0 !== e) { + var s = void 0; + switch (e) { + case!0: + case"observed": + s = !0; + break; + case!1: + case"never": + s = !1; + break; + case"strict": + case"always": + s = "strict"; + break; + default: + a("Invalid value for 'enforceActions': '" + e + "', expected 'never', 'always' or 'observed'") + } + Rt.enforceActions = s, Rt.allowStateChanges = !0 !== s && "strict" !== s + } + void 0 !== r && (Rt.computedRequiresReaction = !!r), void 0 !== u && (Rt.reactionRequiresObservable = !!u), void 0 !== c && (Rt.observableRequiresReaction = !!c, Rt.allowStateReads = !Rt.observableRequiresReaction), void 0 !== n && (Rt.computedConfigurable = !!n), void 0 !== o && (Rt.disableErrorBoundaries = !!o), i && $t(i) + } + + function fe(t, e, r, n) { + var o = pe(n = X(n)); + return I(t), lr(t, n.name, o.enhancer), e && de(t, e, r, o), t + } + + function pe(t) { + return t.defaultDecorator || (!1 === t.deep ? V : G) + } + + function de(t, e, r, n) { + var o, i; + Bt(); + try { + var u = O(e); + try { + for (var a = A(u), c = a.next(); !c.done; c = a.next()) { + var s = c.value, l = Object.getOwnPropertyDescriptor(e, s); + 0; + var f = (r && s in r ? r[s] : l.get ? tt : n)(t, s, l, !0); + f && Object.defineProperty(t, s, f) + } + } catch (t) { + o = {error: t} + } finally { + try { + c && !c.done && (i = a.return) && i.call(a) + } finally { + if (o) throw o.error + } + } + } finally { + Ut() + } + } + + function he(t, e) { + return ye(vr(t, e)) + } + + function ye(t) { + var e, r, n = {name: t.name}; + return t.observing && t.observing.length > 0 && (n.dependencies = (e = t.observing, r = [], e.forEach((function (t) { + -1 === r.indexOf(t) && r.push(t) + })), r).map(ye)), n + } + + var ve = 0; + + function ge() { + this.message = "FLOW_CANCELLED" + } + + function be(t) { + 1 !== arguments.length && a("Flow expects 1 argument and cannot be used as decorator"); + var e = t.name || ""; + return function () { + var r, n = this, o = arguments, i = ++ve, u = te(e + " - runid: " + i + " - init", t).apply(n, o), + a = void 0, c = new Promise((function (t, n) { + var o = 0; + + function c(t) { + var r; + a = void 0; + try { + r = te(e + " - runid: " + i + " - yield " + o++, u.next).call(u, t) + } catch (t) { + return n(t) + } + l(r) + } + + function s(t) { + var r; + a = void 0; + try { + r = te(e + " - runid: " + i + " - yield " + o++, u.throw).call(u, t) + } catch (t) { + return n(t) + } + l(r) + } + + function l(e) { + if (!e || "function" != typeof e.then) return e.done ? t(e.value) : (a = Promise.resolve(e.value)).then(c, s); + e.then(l, n) + } + + r = n, c(void 0) + })); + return c.cancel = te(e + " - runid: " + i + " - cancel", (function () { + try { + a && me(a); + var t = u.return(void 0), e = Promise.resolve(t.value); + e.then(l, l), me(e), r(new ge) + } catch (t) { + r(t) + } + })), c + } + } + + function me(t) { + "function" == typeof t.cancel && t.cancel() + } + + function Oe(t, e) { + if (null == t) return !1; + if (void 0 !== e) { + if (!1 === yr(t)) return !1; + if (!t[_].values.has(e)) return !1; + var r = vr(t, e); + return kt(r) + } + return kt(t) + } + + function _e(t) { + return arguments.length > 1 ? a(!1) : Oe(t) + } + + function we(t, e) { + return "string" != typeof e ? a(!1) : Oe(t, e) + } + + function xe(t, e) { + return null != t && (void 0 !== e ? !!yr(t) && t[_].values.has(e) : yr(t) || !!t[_] || x(t) || Kt(t) || kt(t)) + } + + function je(t) { + return 1 !== arguments.length && a(!1), xe(t) + } + + function Ee(t) { + return yr(t) ? t[_].getKeys() : ir(t) || cr(t) ? Array.from(t.keys()) : er(t) ? t.map((function (t, e) { + return e + })) : a(!1) + } + + function Se(t) { + return yr(t) ? Ee(t).map((function (e) { + return t[e] + })) : ir(t) ? Ee(t).map((function (e) { + return t.get(e) + })) : cr(t) ? Array.from(t.values()) : er(t) ? t.slice() : a(!1) + } + + function Pe(t) { + return yr(t) ? Ee(t).map((function (e) { + return [e, t[e]] + })) : ir(t) ? Ee(t).map((function (e) { + return [e, t.get(e)] + })) : cr(t) ? Array.from(t.entries()) : er(t) ? t.map((function (t, e) { + return [e, t] + })) : a(!1) + } + + function Ae(t, e, r) { + if (2 !== arguments.length || cr(t)) if (yr(t)) { + var n = t[_], o = n.values.get(e); + o ? n.write(e, r) : n.addObservableProp(e, r, n.defaultEnhancer) + } else if (ir(t)) t.set(e, r); else if (cr(t)) t.add(e); else { + if (!er(t)) return a(!1); + "number" != typeof e && (e = parseInt(e, 10)), c(e >= 0, "Not a valid index: '" + e + "'"), Bt(), e >= t.length && (t.length = e + 1), t[e] = r, Ut() + } else { + Bt(); + var i = e; + try { + for (var u in i) Ae(t, u, i[u]) + } finally { + Ut() + } + } + } + + function ke(t, e, r, n) { + return "function" == typeof r ? function (t, e, r, n) { + return gr(t, e).observe(r, n) + }(t, e, r, n) : function (t, e, r) { + return gr(t).observe(e, r) + }(t, e, r) + } + + ge.prototype = Object.create(Error.prototype); + var De = {detectCycles: !0, exportMapsAsObjects: !0, recurseEverything: !1}; + + function Te(t, e, r, n) { + return n.detectCycles && t.set(e, r), r + } + + function Me(t, e, r) { + if (!e.recurseEverything && !je(t)) return t; + if ("object" != typeof t) return t; + if (null === t) return null; + if (t instanceof Date) return t; + if (Pt(t)) return Me(t.get(), e, r); + if (je(t) && Ee(t), !0 === e.detectCycles && null !== t && r.has(t)) return r.get(t); + if (er(t) || Array.isArray(t)) { + var n = Te(r, t, [], e), o = t.map((function (t) { + return Me(t, e, r) + })); + n.length = o.length; + for (var i = 0, u = o.length; i < u; i++) n[i] = o[i]; + return n + } + if (cr(t) || Object.getPrototypeOf(t) === Set.prototype) { + if (!1 === e.exportMapsAsObjects) { + var a = Te(r, t, new Set, e); + return t.forEach((function (t) { + a.add(Me(t, e, r)) + })), a + } + var c = Te(r, t, [], e); + return t.forEach((function (t) { + c.push(Me(t, e, r)) + })), c + } + if (ir(t) || Object.getPrototypeOf(t) === Map.prototype) { + if (!1 === e.exportMapsAsObjects) { + var s = Te(r, t, new Map, e); + return t.forEach((function (t, n) { + s.set(n, Me(t, e, r)) + })), s + } + var l = Te(r, t, {}, e); + return t.forEach((function (t, n) { + l[n] = Me(t, e, r) + })), l + } + var f = Te(r, t, {}, e); + return g(t).forEach((function (n) { + f[n] = Me(t[n], e, r) + })), f + } + + function Ne(t, e) { + var r; + return "boolean" == typeof e && (e = {detectCycles: e}), e || (e = De), e.detectCycles = void 0 === e.detectCycles ? !0 === e.recurseEverything : !0 === e.detectCycles, e.detectCycles && (r = new Map), Me(t, e, r) + } + + function Ce(t) { + switch (t.length) { + case 0: + return Rt.trackingDerivation; + case 1: + return vr(t[0]); + case 2: + return vr(t[0], t[1]) + } + } + + function Re(t, e) { + void 0 === e && (e = void 0), Bt(); + try { + return t.apply(e) + } finally { + Ut() + } + } + + function Ie(t, e, r) { + return 1 === arguments.length || e && "object" == typeof e ? ze(t, e) : Le(t, e, r || {}) + } + + function Le(t, e, r) { + var n; + "number" == typeof r.timeout && (n = setTimeout((function () { + if (!i[_].isDisposed) { + i(); + var t = new Error("WHEN_TIMEOUT"); + if (!r.onError) throw t; + r.onError(t) + } + }), r.timeout)), r.name = r.name || "When@" + u(); + var o = mt(r.name + "-effect", e), i = oe((function (e) { + t() && (e.dispose(), n && clearTimeout(n), o()) + }), r); + return i + } + + function ze(t, e) { + var r; + var n = new Promise((function (n, o) { + var i = Le(t, n, P(P({}, e), {onError: o})); + r = function () { + i(), o("WHEN_CANCELLED") + } + })); + return n.cancel = r, n + } + + function Be(t) { + return t[_] + } + + function Ue(t) { + return "string" == typeof t || "number" == typeof t || "symbol" == typeof t + } + + var Fe = { + has: function (t, e) { + if (e === _ || "constructor" === e || e === T) return !0; + var r = Be(t); + return Ue(e) ? r.has(e) : e in t + }, get: function (t, e) { + if (e === _ || "constructor" === e || e === T) return t[e]; + var r = Be(t), n = r.values.get(e); + if (n instanceof w) { + var o = n.get(); + return void 0 === o && r.has(e), o + } + return Ue(e) && r.has(e), t[e] + }, set: function (t, e, r) { + return !!Ue(e) && (Ae(t, e, r), !0) + }, deleteProperty: function (t, e) { + return !!Ue(e) && (Be(t).remove(e), !0) + }, ownKeys: function (t) { + return Be(t).keysAtom.reportObserved(), Reflect.ownKeys(t) + }, preventExtensions: function (t) { + return a("Dynamic observable objects cannot be frozen"), !1 + } + }; + + function He(t) { + var e = new Proxy(t, Fe); + return t[_].proxy = e, e + } + + function Xe(t) { + return void 0 !== t.interceptors && t.interceptors.length > 0 + } + + function Ge(t, e) { + var r = t.interceptors || (t.interceptors = []); + return r.push(e), s((function () { + var t = r.indexOf(e); + -1 !== t && r.splice(t, 1) + })) + } + + function Ye(t, e) { + var r = ft(); + try { + for (var n = D(t.interceptors || []), o = 0, i = n.length; o < i && (c(!(e = n[o](e)) || e.type, "Intercept handlers should return nothing or a change object"), e); o++) ; + return e + } finally { + pt(r) + } + } + + function Ve(t) { + return void 0 !== t.changeListeners && t.changeListeners.length > 0 + } + + function We(t, e) { + var r = t.changeListeners || (t.changeListeners = []); + return r.push(e), s((function () { + var t = r.indexOf(e); + -1 !== t && r.splice(t, 1) + })) + } + + function Ke(t, e) { + var r = ft(), n = t.changeListeners; + if (n) { + for (var o = 0, i = (n = n.slice()).length; o < i; o++) n[o](e); + pt(r) + } + } + + var $e = { + get: function (t, e) { + return e === _ ? t[_] : "length" === e ? t[_].getArrayLength() : "number" == typeof e ? Je.get.call(t, e) : "string" != typeof e || isNaN(e) ? Je.hasOwnProperty(e) ? Je[e] : t[e] : Je.get.call(t, parseInt(e)) + }, set: function (t, e, r) { + return "length" === e && t[_].setArrayLength(r), "number" == typeof e && Je.set.call(t, e, r), "symbol" == typeof e || isNaN(e) ? t[e] = r : Je.set.call(t, parseInt(e), r), !0 + }, preventExtensions: function (t) { + return a("Observable arrays cannot be frozen"), !1 + } + }; + + function Ze(t, e, r, n) { + void 0 === r && (r = "ObservableArray@" + u()), void 0 === n && (n = !1); + var o, i, a, c = new qe(r, e, n); + o = c.values, i = _, a = c, Object.defineProperty(o, i, { + enumerable: !1, + writable: !1, + configurable: !0, + value: a + }); + var s = new Proxy(c.values, $e); + if (c.proxy = s, t && t.length) { + var l = jt(!0); + c.spliceWithArray(0, 0, t), Et(l) + } + return s + } + + var qe = function () { + function t(t, e, r) { + this.owned = r, this.values = [], this.proxy = void 0, this.lastKnownLength = 0, this.atom = new w(t || "ObservableArray@" + u()), this.enhancer = function (r, n) { + return e(r, n, t + "[..]") + } + } + + return t.prototype.dehanceValue = function (t) { + return void 0 !== this.dehancer ? this.dehancer(t) : t + }, t.prototype.dehanceValues = function (t) { + return void 0 !== this.dehancer && t.length > 0 ? t.map(this.dehancer) : t + }, t.prototype.intercept = function (t) { + return Ge(this, t) + }, t.prototype.observe = function (t, e) { + return void 0 === e && (e = !1), e && t({ + object: this.proxy, + type: "splice", + index: 0, + added: this.values.slice(), + addedCount: this.values.length, + removed: [], + removedCount: 0 + }), We(this, t) + }, t.prototype.getArrayLength = function () { + return this.atom.reportObserved(), this.values.length + }, t.prototype.setArrayLength = function (t) { + if ("number" != typeof t || t < 0) throw new Error("[mobx.array] Out of range: " + t); + var e = this.values.length; + if (t !== e) if (t > e) { + for (var r = new Array(t - e), n = 0; n < t - e; n++) r[n] = void 0; + this.spliceWithArray(e, 0, r) + } else this.spliceWithArray(t, e - t) + }, t.prototype.updateArrayLength = function (t, e) { + if (t !== this.lastKnownLength) throw new Error("[mobx] Modification exception: the internal structure of an observable array was changed."); + this.lastKnownLength += e + }, t.prototype.spliceWithArray = function (t, e, r) { + var n = this; + at(this.atom); + var i = this.values.length; + if (void 0 === t ? t = 0 : t > i ? t = i : t < 0 && (t = Math.max(0, i + t)), e = 1 === arguments.length ? i - t : null == e ? 0 : Math.max(0, Math.min(e, i - t)), void 0 === r && (r = o), Xe(this)) { + var u = Ye(this, {object: this.proxy, type: "splice", index: t, removedCount: e, added: r}); + if (!u) return o; + e = u.removedCount, r = u.added + } + r = 0 === r.length ? r : r.map((function (t) { + return n.enhancer(t, void 0) + })); + var a = this.spliceItemsIntoValues(t, e, r); + return 0 === e && 0 === r.length || this.notifyArraySplice(t, r, a), this.dehanceValues(a) + }, t.prototype.spliceItemsIntoValues = function (t, e, r) { + var n; + if (r.length < 1e4) return (n = this.values).splice.apply(n, D([t, e], r)); + var o = this.values.slice(t, t + e); + return this.values = this.values.slice(0, t).concat(r, this.values.slice(t + e)), o + }, t.prototype.notifyArrayChildUpdate = function (t, e, r) { + var n = !this.owned && !1, o = Ve(this), + i = o || n ? {object: this.proxy, type: "update", index: t, newValue: e, oldValue: r} : null; + this.atom.reportChanged(), o && Ke(this, i) + }, t.prototype.notifyArraySplice = function (t, e, r) { + var n = !this.owned && !1, o = Ve(this), i = o || n ? { + object: this.proxy, + type: "splice", + index: t, + removed: r, + added: e, + removedCount: r.length, + addedCount: e.length + } : null; + this.atom.reportChanged(), o && Ke(this, i) + }, t + }(), Je = { + intercept: function (t) { + return this[_].intercept(t) + }, observe: function (t, e) { + return void 0 === e && (e = !1), this[_].observe(t, e) + }, clear: function () { + return this.splice(0) + }, replace: function (t) { + var e = this[_]; + return e.spliceWithArray(0, e.values.length, t) + }, toJS: function () { + return this.slice() + }, toJSON: function () { + return this.toJS() + }, splice: function (t, e) { + for (var r = [], n = 2; n < arguments.length; n++) r[n - 2] = arguments[n]; + var o = this[_]; + switch (arguments.length) { + case 0: + return []; + case 1: + return o.spliceWithArray(t); + case 2: + return o.spliceWithArray(t, e) + } + return o.spliceWithArray(t, e, r) + }, spliceWithArray: function (t, e, r) { + return this[_].spliceWithArray(t, e, r) + }, push: function () { + for (var t = [], e = 0; e < arguments.length; e++) t[e] = arguments[e]; + var r = this[_]; + return r.spliceWithArray(r.values.length, 0, t), r.values.length + }, pop: function () { + return this.splice(Math.max(this[_].values.length - 1, 0), 1)[0] + }, shift: function () { + return this.splice(0, 1)[0] + }, unshift: function () { + for (var t = [], e = 0; e < arguments.length; e++) t[e] = arguments[e]; + var r = this[_]; + return r.spliceWithArray(0, 0, t), r.values.length + }, reverse: function () { + var t = this.slice(); + return t.reverse.apply(t, arguments) + }, sort: function (t) { + var e = this.slice(); + return e.sort.apply(e, arguments) + }, remove: function (t) { + var e = this[_], r = e.dehanceValues(e.values).indexOf(t); + return r > -1 && (this.splice(r, 1), !0) + }, get: function (t) { + var e = this[_]; + if (e && t < e.values.length) return e.atom.reportObserved(), e.dehanceValue(e.values[t]) + }, set: function (t, e) { + var r = this[_], n = r.values; + if (t < n.length) { + at(r.atom); + var o = n[t]; + if (Xe(r)) { + var i = Ye(r, {type: "update", object: r.proxy, index: t, newValue: e}); + if (!i) return; + e = i.newValue + } + (e = r.enhancer(e, o)) !== o && (n[t] = e, r.notifyArrayChildUpdate(t, e, o)) + } else { + if (t !== n.length) throw new Error("[mobx.array] Index out of bounds, " + t + " is larger than " + n.length); + r.spliceWithArray(t, 0, [e]) + } + } + }; + ["concat", "flat", "includes", "indexOf", "join", "lastIndexOf", "slice", "toString", "toLocaleString"].forEach((function (t) { + "function" == typeof Array.prototype[t] && (Je[t] = function () { + var e = this[_]; + e.atom.reportObserved(); + var r = e.dehanceValues(e.values); + return r[t].apply(r, arguments) + }) + })), ["every", "filter", "find", "findIndex", "flatMap", "forEach", "map", "some"].forEach((function (t) { + "function" == typeof Array.prototype[t] && (Je[t] = function (e, r) { + var n = this, o = this[_]; + return o.atom.reportObserved(), o.dehanceValues(o.values)[t]((function (t, o) { + return e.call(r, t, o, n) + }), r) + }) + })), ["reduce", "reduceRight"].forEach((function (t) { + Je[t] = function () { + var e = this, r = this[_]; + r.atom.reportObserved(); + var n = arguments[0]; + return arguments[0] = function (t, o, i) { + return o = r.dehanceValue(o), n(t, o, i, e) + }, r.values[t].apply(r.values, arguments) + } + })); + var Qe, tr = h("ObservableArrayAdministration", qe); + + function er(t) { + return f(t) && tr(t[_]) + } + + var rr, nr = {}, or = function () { + function t(t, e, r) { + if (void 0 === e && (e = B), void 0 === r && (r = "ObservableMap@" + u()), this.enhancer = e, this.name = r, this[Qe] = nr, this._keysAtom = j(this.name + ".keys()"), this[Symbol.toStringTag] = "Map", "function" != typeof Map) throw new Error("mobx.map requires Map polyfill for the current browser. Check babel-polyfill or core-js/es6/map.js"); + this._data = new Map, this._hasMap = new Map, this.merge(t) + } + + return t.prototype._has = function (t) { + return this._data.has(t) + }, t.prototype.has = function (t) { + var e = this; + if (!Rt.trackingDerivation) return this._has(t); + var r = this._hasMap.get(t); + if (!r) { + var n = r = new St(this._has(t), U, this.name + "." + b(t) + "?", !1); + this._hasMap.set(t, n), ce(n, (function () { + return e._hasMap.delete(t) + })) + } + return r.get() + }, t.prototype.set = function (t, e) { + var r = this._has(t); + if (Xe(this)) { + var n = Ye(this, {type: r ? "update" : "add", object: this, newValue: e, name: t}); + if (!n) return this; + e = n.newValue + } + return r ? this._updateValue(t, e) : this._addValue(t, e), this + }, t.prototype.delete = function (t) { + var e = this; + if ((at(this._keysAtom), Xe(this)) && !(n = Ye(this, { + type: "delete", + object: this, + name: t + }))) return !1; + if (this._has(t)) { + var r = Ve(this), + n = r ? {type: "delete", object: this, oldValue: this._data.get(t).value, name: t} : null; + return Re((function () { + e._keysAtom.reportChanged(), e._updateHasMapEntry(t, !1), e._data.get(t).setNewValue(void 0), e._data.delete(t) + })), r && Ke(this, n), !0 + } + return !1 + }, t.prototype._updateHasMapEntry = function (t, e) { + var r = this._hasMap.get(t); + r && r.setNewValue(e) + }, t.prototype._updateValue = function (t, e) { + var r = this._data.get(t); + if ((e = r.prepareNewValue(e)) !== Rt.UNCHANGED) { + var n = !1, o = Ve(this), + i = o ? {type: "update", object: this, oldValue: r.value, name: t, newValue: e} : null; + n, r.setNewValue(e), o && Ke(this, i) + } + }, t.prototype._addValue = function (t, e) { + var r = this; + at(this._keysAtom), Re((function () { + var n = new St(e, r.enhancer, r.name + "." + b(t), !1); + r._data.set(t, n), e = n.value, r._updateHasMapEntry(t, !0), r._keysAtom.reportChanged() + })); + var n = !1, o = Ve(this), i = o ? {type: "add", object: this, name: t, newValue: e} : null; + o && Ke(this, i) + }, t.prototype.get = function (t) { + return this.has(t) ? this.dehanceValue(this._data.get(t).get()) : this.dehanceValue(void 0) + }, t.prototype.dehanceValue = function (t) { + return void 0 !== this.dehancer ? this.dehancer(t) : t + }, t.prototype.keys = function () { + return this._keysAtom.reportObserved(), this._data.keys() + }, t.prototype.values = function () { + var t = this, e = this.keys(); + return xr({ + next: function () { + var r = e.next(), n = r.done, o = r.value; + return {done: n, value: n ? void 0 : t.get(o)} + } + }) + }, t.prototype.entries = function () { + var t = this, e = this.keys(); + return xr({ + next: function () { + var r = e.next(), n = r.done, o = r.value; + return {done: n, value: n ? void 0 : [o, t.get(o)]} + } + }) + }, t.prototype[(Qe = _, Symbol.iterator)] = function () { + return this.entries() + }, t.prototype.forEach = function (t, e) { + var r, n; + try { + for (var o = A(this), i = o.next(); !i.done; i = o.next()) { + var u = k(i.value, 2), a = u[0], c = u[1]; + t.call(e, c, a, this) + } + } catch (t) { + r = {error: t} + } finally { + try { + i && !i.done && (n = o.return) && n.call(o) + } finally { + if (r) throw r.error + } + } + }, t.prototype.merge = function (t) { + var e = this; + return ir(t) && (t = t.toJS()), Re((function () { + var r = jt(!0); + try { + p(t) ? g(t).forEach((function (r) { + return e.set(r, t[r]) + })) : Array.isArray(t) ? t.forEach((function (t) { + var r = k(t, 2), n = r[0], o = r[1]; + return e.set(n, o) + })) : y(t) ? (t.constructor !== Map && a("Cannot initialize from classes that inherit from Map: " + t.constructor.name), t.forEach((function (t, r) { + return e.set(r, t) + }))) : null != t && a("Cannot initialize map from " + t) + } finally { + Et(r) + } + })), this + }, t.prototype.clear = function () { + var t = this; + Re((function () { + lt((function () { + var e, r; + try { + for (var n = A(t.keys()), o = n.next(); !o.done; o = n.next()) { + var i = o.value; + t.delete(i) + } + } catch (t) { + e = {error: t} + } finally { + try { + o && !o.done && (r = n.return) && r.call(n) + } finally { + if (e) throw e.error + } + } + })) + })) + }, t.prototype.replace = function (t) { + var e = this; + return Re((function () { + var r, n, o, i, u = function (t) { + if (y(t) || ir(t)) return t; + if (Array.isArray(t)) return new Map(t); + if (p(t)) { + var e = new Map; + for (var r in t) e.set(r, t[r]); + return e + } + return a("Cannot convert to map from '" + t + "'") + }(t), c = new Map, s = !1; + try { + for (var l = A(e._data.keys()), f = l.next(); !f.done; f = l.next()) { + var d = f.value; + if (!u.has(d)) if (e.delete(d)) s = !0; else { + var h = e._data.get(d); + c.set(d, h) + } + } + } catch (t) { + r = {error: t} + } finally { + try { + f && !f.done && (n = l.return) && n.call(l) + } finally { + if (r) throw r.error + } + } + try { + for (var v = A(u.entries()), g = v.next(); !g.done; g = v.next()) { + var b = k(g.value, 2), m = (d = b[0], h = b[1], e._data.has(d)); + if (e.set(d, h), e._data.has(d)) { + var O = e._data.get(d); + c.set(d, O), m || (s = !0) + } + } + } catch (t) { + o = {error: t} + } finally { + try { + g && !g.done && (i = v.return) && i.call(v) + } finally { + if (o) throw o.error + } + } + if (!s) if (e._data.size !== c.size) e._keysAtom.reportChanged(); else for (var _ = e._data.keys(), w = c.keys(), x = _.next(), j = w.next(); !x.done;) { + if (x.value !== j.value) { + e._keysAtom.reportChanged(); + break + } + x = _.next(), j = w.next() + } + e._data = c + })), this + }, Object.defineProperty(t.prototype, "size", { + get: function () { + return this._keysAtom.reportObserved(), this._data.size + }, enumerable: !0, configurable: !0 + }), t.prototype.toPOJO = function () { + var t, e, r = {}; + try { + for (var n = A(this), o = n.next(); !o.done; o = n.next()) { + var i = k(o.value, 2), u = i[0], a = i[1]; + r["symbol" == typeof u ? u : b(u)] = a + } + } catch (e) { + t = {error: e} + } finally { + try { + o && !o.done && (e = n.return) && e.call(n) + } finally { + if (t) throw t.error + } + } + return r + }, t.prototype.toJS = function () { + return new Map(this) + }, t.prototype.toJSON = function () { + return this.toPOJO() + }, t.prototype.toString = function () { + var t = this; + return this.name + "[{ " + Array.from(this.keys()).map((function (e) { + return b(e) + ": " + t.get(e) + })).join(", ") + " }]" + }, t.prototype.observe = function (t, e) { + return We(this, t) + }, t.prototype.intercept = function (t) { + return Ge(this, t) + }, t + }(), ir = h("ObservableMap", or), ur = {}, ar = function () { + function t(t, e, r) { + if (void 0 === e && (e = B), void 0 === r && (r = "ObservableSet@" + u()), this.name = r, this[rr] = ur, this._data = new Set, this._atom = j(this.name), this[Symbol.toStringTag] = "Set", "function" != typeof Set) throw new Error("mobx.set requires Set polyfill for the current browser. Check babel-polyfill or core-js/es6/set.js"); + this.enhancer = function (t, n) { + return e(t, n, r) + }, t && this.replace(t) + } + + return t.prototype.dehanceValue = function (t) { + return void 0 !== this.dehancer ? this.dehancer(t) : t + }, t.prototype.clear = function () { + var t = this; + Re((function () { + lt((function () { + var e, r; + try { + for (var n = A(t._data.values()), o = n.next(); !o.done; o = n.next()) { + var i = o.value; + t.delete(i) + } + } catch (t) { + e = {error: t} + } finally { + try { + o && !o.done && (r = n.return) && r.call(n) + } finally { + if (e) throw e.error + } + } + })) + })) + }, t.prototype.forEach = function (t, e) { + var r, n; + try { + for (var o = A(this), i = o.next(); !i.done; i = o.next()) { + var u = i.value; + t.call(e, u, u, this) + } + } catch (t) { + r = {error: t} + } finally { + try { + i && !i.done && (n = o.return) && n.call(o) + } finally { + if (r) throw r.error + } + } + }, Object.defineProperty(t.prototype, "size", { + get: function () { + return this._atom.reportObserved(), this._data.size + }, enumerable: !0, configurable: !0 + }), t.prototype.add = function (t) { + var e = this; + if ((at(this._atom), Xe(this)) && !(o = Ye(this, { + type: "add", + object: this, + newValue: t + }))) return this; + if (!this.has(t)) { + Re((function () { + e._data.add(e.enhancer(t, void 0)), e._atom.reportChanged() + })); + var r = !1, n = Ve(this), o = n ? {type: "add", object: this, newValue: t} : null; + r, n && Ke(this, o) + } + return this + }, t.prototype.delete = function (t) { + var e = this; + if (Xe(this) && !(n = Ye(this, {type: "delete", object: this, oldValue: t}))) return !1; + if (this.has(t)) { + var r = Ve(this), n = r ? {type: "delete", object: this, oldValue: t} : null; + return Re((function () { + e._atom.reportChanged(), e._data.delete(t) + })), r && Ke(this, n), !0 + } + return !1 + }, t.prototype.has = function (t) { + return this._atom.reportObserved(), this._data.has(this.dehanceValue(t)) + }, t.prototype.entries = function () { + var t = 0, e = Array.from(this.keys()), r = Array.from(this.values()); + return xr({ + next: function () { + var n = t; + return t += 1, n < r.length ? {value: [e[n], r[n]], done: !1} : {done: !0} + } + }) + }, t.prototype.keys = function () { + return this.values() + }, t.prototype.values = function () { + this._atom.reportObserved(); + var t = this, e = 0, r = Array.from(this._data.values()); + return xr({ + next: function () { + return e < r.length ? {value: t.dehanceValue(r[e++]), done: !1} : {done: !0} + } + }) + }, t.prototype.replace = function (t) { + var e = this; + return cr(t) && (t = t.toJS()), Re((function () { + var r = jt(!0); + try { + Array.isArray(t) || v(t) ? (e.clear(), t.forEach((function (t) { + return e.add(t) + }))) : null != t && a("Cannot initialize set from " + t) + } finally { + Et(r) + } + })), this + }, t.prototype.observe = function (t, e) { + return We(this, t) + }, t.prototype.intercept = function (t) { + return Ge(this, t) + }, t.prototype.toJS = function () { + return new Set(this) + }, t.prototype.toString = function () { + return this.name + "[ " + Array.from(this).join(", ") + " ]" + }, t.prototype[(rr = _, Symbol.iterator)] = function () { + return this.values() + }, t + }(), cr = h("ObservableSet", ar), sr = function () { + function t(t, e, r, n) { + void 0 === e && (e = new Map), this.target = t, this.values = e, this.name = r, this.defaultEnhancer = n, this.keysAtom = new w(r + ".keys") + } + + return t.prototype.read = function (t) { + return this.values.get(t).get() + }, t.prototype.write = function (t, e) { + var r = this.target, n = this.values.get(t); + if (n instanceof At) n.set(e); else { + if (Xe(this)) { + if (!(u = Ye(this, { + type: "update", + object: this.proxy || r, + name: t, + newValue: e + }))) return; + e = u.newValue + } + if ((e = n.prepareNewValue(e)) !== Rt.UNCHANGED) { + var o = Ve(this), i = !1, u = o ? { + type: "update", + object: this.proxy || r, + oldValue: n.value, + name: t, + newValue: e + } : null; + i, n.setNewValue(e), o && Ke(this, u) + } + } + }, t.prototype.has = function (t) { + var e = this.pendingKeys || (this.pendingKeys = new Map), r = e.get(t); + if (r) return r.get(); + var n = !!this.values.get(t); + return r = new St(n, U, this.name + "." + b(t) + "?", !1), e.set(t, r), r.get() + }, t.prototype.addObservableProp = function (t, e, r) { + void 0 === r && (r = this.defaultEnhancer); + var n = this.target; + if (Xe(this)) { + var o = Ye(this, {object: this.proxy || n, name: t, type: "add", newValue: e}); + if (!o) return; + e = o.newValue + } + var i = new St(e, r, this.name + "." + b(t), !1); + this.values.set(t, i), e = i.value, Object.defineProperty(n, t, function (t) { + return fr[t] || (fr[t] = { + configurable: !0, enumerable: !0, get: function () { + return this[_].read(t) + }, set: function (e) { + this[_].write(t, e) + } + }) + }(t)), this.notifyPropertyAddition(t, e) + }, t.prototype.addComputedProp = function (t, e, r) { + var n, o, i, u = this.target; + r.name = r.name || this.name + "." + b(e), this.values.set(e, new At(r)), (t === u || (n = t, o = e, !(i = Object.getOwnPropertyDescriptor(n, o)) || !1 !== i.configurable && !1 !== i.writable)) && Object.defineProperty(t, e, function (t) { + return pr[t] || (pr[t] = { + configurable: Rt.computedConfigurable, + enumerable: !1, + get: function () { + return dr(this).read(t) + }, + set: function (e) { + dr(this).write(t, e) + } + }) + }(e)) + }, t.prototype.remove = function (t) { + if (this.values.has(t)) { + var e = this.target; + if (Xe(this)) if (!(a = Ye(this, {object: this.proxy || e, name: t, type: "remove"}))) return; + try { + Bt(); + var r = Ve(this), n = !1, o = this.values.get(t), i = o && o.get(); + if (o && o.set(void 0), this.keysAtom.reportChanged(), this.values.delete(t), this.pendingKeys) { + var u = this.pendingKeys.get(t); + u && u.set(!1) + } + delete this.target[t]; + var a = r ? {type: "remove", object: this.proxy || e, oldValue: i, name: t} : null; + n, r && Ke(this, a) + } finally { + Ut() + } + } + }, t.prototype.illegalAccess = function (t, e) { + }, t.prototype.observe = function (t, e) { + return We(this, t) + }, t.prototype.intercept = function (t) { + return Ge(this, t) + }, t.prototype.notifyPropertyAddition = function (t, e) { + var r = Ve(this), + n = r ? {type: "add", object: this.proxy || this.target, name: t, newValue: e} : null; + if (r && Ke(this, n), this.pendingKeys) { + var o = this.pendingKeys.get(t); + o && o.set(!0) + } + this.keysAtom.reportChanged() + }, t.prototype.getKeys = function () { + var t, e; + this.keysAtom.reportObserved(); + var r = []; + try { + for (var n = A(this.values), o = n.next(); !o.done; o = n.next()) { + var i = k(o.value, 2), u = i[0]; + i[1] instanceof St && r.push(u) + } + } catch (e) { + t = {error: e} + } finally { + try { + o && !o.done && (e = n.return) && e.call(n) + } finally { + if (t) throw t.error + } + } + return r + }, t + }(); + + function lr(t, e, r) { + if (void 0 === e && (e = ""), void 0 === r && (r = B), Object.prototype.hasOwnProperty.call(t, _)) return t[_]; + p(t) || (e = (t.constructor.name || "ObservableObject") + "@" + u()), e || (e = "ObservableObject@" + u()); + var n = new sr(t, new Map, b(e), r); + return d(t, _, n), n + } + + var fr = Object.create(null), pr = Object.create(null); + + function dr(t) { + var e = t[_]; + return e || (I(t), t[_]) + } + + var hr = h("ObservableObjectAdministration", sr); + + function yr(t) { + return !!f(t) && (I(t), hr(t[_])) + } + + function vr(t, e) { + if ("object" == typeof t && null !== t) { + if (er(t)) return void 0 !== e && a(!1), t[_].atom; + if (cr(t)) return t[_]; + if (ir(t)) { + var r = t; + return void 0 === e ? r._keysAtom : ((n = r._data.get(e) || r._hasMap.get(e)) || a(!1), n) + } + var n; + if (I(t), e && !t[_] && t[e], yr(t)) return e ? ((n = t[_].values.get(e)) || a(!1), n) : a(!1); + if (x(t) || kt(t) || Kt(t)) return t + } else if ("function" == typeof t && Kt(t[_])) return t[_]; + return a(!1) + } + + function gr(t, e) { + return t || a("Expecting some object"), void 0 !== e ? gr(vr(t, e)) : x(t) || kt(t) || Kt(t) || ir(t) || cr(t) ? t : (I(t), t[_] ? t[_] : void a(!1)) + } + + var br = Object.prototype.toString; + + function mr(t, e, r) { + return void 0 === r && (r = -1), Or(t, e, r) + } + + function Or(t, e, r, n, o) { + if (t === e) return 0 !== t || 1 / t == 1 / e; + if (null == t || null == e) return !1; + if (t != t) return e != e; + var i = typeof t; + if ("function" !== i && "object" !== i && "object" != typeof e) return !1; + var u = br.call(t); + if (u !== br.call(e)) return !1; + switch (u) { + case"[object RegExp]": + case"[object String]": + return "" + t == "" + e; + case"[object Number]": + return +t != +t ? +e != +e : 0 == +t ? 1 / +t == 1 / e : +t == +e; + case"[object Date]": + case"[object Boolean]": + return +t == +e; + case"[object Symbol]": + return "undefined" != typeof Symbol && Symbol.valueOf.call(t) === Symbol.valueOf.call(e); + case"[object Map]": + case"[object Set]": + r >= 0 && r++ + } + t = _r(t), e = _r(e); + var a = "[object Array]" === u; + if (!a) { + if ("object" != typeof t || "object" != typeof e) return !1; + var c = t.constructor, s = e.constructor; + if (c !== s && !("function" == typeof c && c instanceof c && "function" == typeof s && s instanceof s) && "constructor" in t && "constructor" in e) return !1 + } + if (0 === r) return !1; + r < 0 && (r = -1), o = o || []; + for (var l = (n = n || []).length; l--;) if (n[l] === t) return o[l] === e; + if (n.push(t), o.push(e), a) { + if ((l = t.length) !== e.length) return !1; + for (; l--;) if (!Or(t[l], e[l], r - 1, n, o)) return !1 + } else { + var f = Object.keys(t), p = void 0; + if (l = f.length, Object.keys(e).length !== l) return !1; + for (; l--;) if (!wr(e, p = f[l]) || !Or(t[p], e[p], r - 1, n, o)) return !1 + } + return n.pop(), o.pop(), !0 + } + + function _r(t) { + return er(t) ? t.slice() : y(t) || ir(t) || v(t) || cr(t) ? Array.from(t.entries()) : t + } + + function wr(t, e) { + return Object.prototype.hasOwnProperty.call(t, e) + } + + function xr(t) { + return t[Symbol.iterator] = jr, t + } + + function jr() { + return this + } + + if ("undefined" == typeof Proxy || "undefined" == typeof Symbol) throw new Error("[mobx] MobX 5+ requires Proxy and Symbol objects. If your environment doesn't support Symbol or Proxy objects, please downgrade to MobX 4. For React Native Android, consider upgrading JSCore."); + "object" == typeof __MOBX_DEVTOOLS_GLOBAL_HOOK__ && __MOBX_DEVTOOLS_GLOBAL_HOOK__.injectMobx({ + spy: Zt, + extras: { + getDebugName: function (t, e) { + return (void 0 !== e ? vr(t, e) : yr(t) || ir(t) || cr(t) ? gr(t) : vr(t)).name + } + }, + $mobx: _ + }) + }).call(this, r(160), r(66)) + }, function (t, e, r) { + var n = r(113), o = r(42), i = r(179); + n || o(Object.prototype, "toString", i, {unsafe: !0}) + }, function (t, e, r) { + "use strict"; + var n = r(41), o = r(100), i = r(78), u = r(58), a = r(116), c = "Array Iterator", s = u.set, + l = u.getterFor(c); + t.exports = a(Array, "Array", (function (t, e) { + s(this, {type: c, target: n(t), index: 0, kind: e}) + }), (function () { + var t = l(this), e = t.target, r = t.kind, n = t.index++; + return !e || n >= e.length ? (t.target = void 0, {value: void 0, done: !0}) : "keys" == r ? { + value: n, + done: !1 + } : "values" == r ? {value: e[n], done: !1} : {value: [n, e[n]], done: !1} + }), "values"), i.Arguments = i.Array, o("keys"), o("values"), o("entries") + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(7), i = r(46), u = r(74), a = r(34), c = r(15), s = r(69), l = r(36), f = r(108), + p = r(18), d = r(35), h = r(96), y = r(30), v = r(33), g = r(54), b = r(87), m = r(32), O = r(40), + _ = r(41), w = r(86), x = r(39), j = r(67), E = r(60), S = r(75), P = r(72), A = r(139), k = r(112), + D = r(50), T = r(38), M = r(84), N = r(98), C = r(42), R = r(89), I = r(93), L = r(70), z = r(90), + B = r(28), U = r(140), F = r(141), H = r(76), X = r(58), G = r(77).forEach, Y = I("hidden"), V = "Symbol", + W = B("toPrimitive"), K = X.set, $ = X.getterFor(V), Z = Object.prototype, q = o.Symbol, + J = q && q.prototype, Q = o.TypeError, tt = o.QObject, et = i("JSON", "stringify"), rt = D.f, nt = T.f, + ot = A.f, it = M.f, ut = c([].push), at = R("symbols"), ct = R("op-symbols"), + st = R("string-to-symbol-registry"), lt = R("symbol-to-string-registry"), ft = R("wks"), + pt = !tt || !tt.prototype || !tt.prototype.findChild, dt = l && p((function () { + return 7 != E(nt({}, "a", { + get: function () { + return nt(this, "a", {value: 7}).a + } + })).a + })) ? function (t, e, r) { + var n = rt(Z, e); + n && delete Z[e], nt(t, e, r), n && t !== Z && nt(Z, e, n) + } : nt, ht = function (t, e) { + var r = at[t] = E(J); + return K(r, {type: V, tag: t, description: e}), l || (r.description = e), r + }, yt = function (t, e, r) { + t === Z && yt(ct, e, r), m(t); + var n = w(e); + return m(r), d(at, n) ? (r.enumerable ? (d(t, Y) && t[Y][n] && (t[Y][n] = !1), r = E(r, {enumerable: j(0, !1)})) : (d(t, Y) || nt(t, Y, j(1, {})), t[Y][n] = !0), dt(t, n, r)) : nt(t, n, r) + }, vt = function (t, e) { + m(t); + var r = _(e), n = S(r).concat(Ot(r)); + return G(n, (function (e) { + l && !a(gt, r, e) || yt(t, e, r[e]) + })), t + }, gt = function (t) { + var e = w(t), r = a(it, this, e); + return !(this === Z && d(at, e) && !d(ct, e)) && (!(r || !d(this, e) || !d(at, e) || d(this, Y) && this[Y][e]) || r) + }, bt = function (t, e) { + var r = _(t), n = w(e); + if (r !== Z || !d(at, n) || d(ct, n)) { + var o = rt(r, n); + return !o || !d(at, n) || d(r, Y) && r[Y][n] || (o.enumerable = !0), o + } + }, mt = function (t) { + var e = ot(_(t)), r = []; + return G(e, (function (t) { + d(at, t) || d(L, t) || ut(r, t) + })), r + }, Ot = function (t) { + var e = t === Z, r = ot(e ? ct : _(t)), n = []; + return G(r, (function (t) { + !d(at, t) || e && !d(Z, t) || ut(n, at[t]) + })), n + }; + (f || (q = function () { + if (g(J, this)) throw Q("Symbol is not a constructor"); + var t = arguments.length && void 0 !== arguments[0] ? x(arguments[0]) : void 0, e = z(t), r = function (t) { + this === Z && a(r, ct, t), d(this, Y) && d(this[Y], e) && (this[Y][e] = !1), dt(this, e, j(1, t)) + }; + return l && pt && dt(Z, e, {configurable: !0, set: r}), ht(e, t) + }, C(J = q.prototype, "toString", (function () { + return $(this).tag + })), C(q, "withoutSetter", (function (t) { + return ht(z(t), t) + })), M.f = gt, T.f = yt, D.f = bt, P.f = A.f = mt, k.f = Ot, U.f = function (t) { + return ht(B(t), t) + }, l && (nt(J, "description", { + configurable: !0, get: function () { + return $(this).description + } + }), s || C(Z, "propertyIsEnumerable", gt, {unsafe: !0}))), n({ + global: !0, + wrap: !0, + forced: !f, + sham: !f + }, {Symbol: q}), G(S(ft), (function (t) { + F(t) + })), n({target: V, stat: !0, forced: !f}, { + for: function (t) { + var e = x(t); + if (d(st, e)) return st[e]; + var r = q(e); + return st[e] = r, lt[r] = e, r + }, keyFor: function (t) { + if (!b(t)) throw Q(t + " is not a symbol"); + if (d(lt, t)) return lt[t] + }, useSetter: function () { + pt = !0 + }, useSimple: function () { + pt = !1 + } + }), n({target: "Object", stat: !0, forced: !f, sham: !l}, { + create: function (t, e) { + return void 0 === e ? E(t) : vt(E(t), e) + }, defineProperty: yt, defineProperties: vt, getOwnPropertyDescriptor: bt + }), n({target: "Object", stat: !0, forced: !f}, { + getOwnPropertyNames: mt, + getOwnPropertySymbols: Ot + }), n({ + target: "Object", stat: !0, forced: p((function () { + k.f(1) + })) + }, { + getOwnPropertySymbols: function (t) { + return k.f(O(t)) + } + }), et) && n({ + target: "JSON", stat: !0, forced: !f || p((function () { + var t = q(); + return "[null]" != et([t]) || "{}" != et({a: t}) || "{}" != et(Object(t)) + })) + }, { + stringify: function (t, e, r) { + var n = N(arguments), o = e; + if ((v(e) || void 0 !== t) && !b(t)) return h(e) || (e = function (t, e) { + if (y(o) && (e = a(o, this, t, e)), !b(e)) return e + }), n[1] = e, u(et, null, n) + } + }); + if (!J[W]) { + var _t = J.valueOf; + C(J, W, (function (t) { + return a(_t, this) + })) + } + H(q, V), L[Y] = !0 + }, function (t, e, r) { + var n = r(7), o = r(152), i = r(153), u = r(3), a = r(57), c = r(28), s = c("iterator"), l = c("toStringTag"), + f = u.values, p = function (t, e) { + if (t) { + if (t[s] !== f) try { + a(t, s, f) + } catch (e) { + t[s] = f + } + if (t[l] || a(t, l, e), o[e]) for (var r in u) if (t[r] !== u[r]) try { + a(t, r, u[r]) + } catch (e) { + t[r] = u[r] + } + } + }; + for (var d in o) p(n[d] && n[d].prototype, d); + p(i, "DOMTokenList") + }, function (t, e, r) { + "use strict"; + var n = r(151).charAt, o = r(39), i = r(58), u = r(116), a = "String Iterator", c = i.set, s = i.getterFor(a); + u(String, "String", (function (t) { + c(this, {type: a, string: o(t), index: 0}) + }), (function () { + var t, e = s(this), r = e.string, o = e.index; + return o >= r.length ? {value: void 0, done: !0} : (t = n(r, o), e.index += t.length, {value: t, done: !1}) + })) + }, function (t, e, r) { + (function (e) { + var r = function (t) { + return t && t.Math == Math && t + }; + t.exports = r("object" == typeof globalThis && globalThis) || r("object" == typeof window && window) || r("object" == typeof self && self) || r("object" == typeof e && e) || function () { + return this + }() || Function("return this")() + }).call(this, r(66)) + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(36), i = r(7), u = r(15), a = r(35), c = r(30), s = r(54), l = r(39), f = r(38).f, + p = r(134), d = i.Symbol, h = d && d.prototype; + if (o && c(d) && (!("description" in h) || void 0 !== d().description)) { + var y = {}, v = function () { + var t = arguments.length < 1 || void 0 === arguments[0] ? void 0 : l(arguments[0]), + e = s(h, this) ? new d(t) : void 0 === t ? d() : d(t); + return "" === t && (y[e] = !0), e + }; + p(v, d), v.prototype = h, h.constructor = v; + var g = "Symbol(test)" == String(d("test")), b = u(h.toString), m = u(h.valueOf), + O = /^Symbol\((.*)\)[^)]+$/, _ = u("".replace), w = u("".slice); + f(h, "description", { + configurable: !0, get: function () { + var t = m(this), e = b(t); + if (a(y, t)) return ""; + var r = g ? w(e, 7, -1) : _(e, O, "$1"); + return "" === r ? void 0 : r + } + }), n({global: !0, forced: !0}, {Symbol: v}) + } + }, function (t, e, r) { + r(141)("iterator") + }, function (t, e, r) { + "use strict"; + r.d(e, "a", (function () { + return u.a + })), r.d(e, "c", (function () { + return u.e + })), r.d(e, "h", (function () { + return O + })), r.d(e, "i", (function () { + return g + })), r.d(e, "j", (function () { + return y + })), r.d(e, "b", (function () { + return D + })), r.d(e, "e", (function () { + return C + })), r.d(e, "f", (function () { + return T + })), r.d(e, "g", (function () { + return at + })); + var n, o, i, u = r(0), a = 0, c = [], s = u.i.__b, l = u.i.__r, f = u.i.diffed, p = u.i.__c, d = u.i.unmount; + + function h(t, e) { + u.i.__h && u.i.__h(o, t, a || e), a = 0; + var r = o.__H || (o.__H = {__: [], __h: []}); + return t >= r.__.length && r.__.push({}), r.__[t] + } + + function y(t) { + return a = 1, v(P, t) + } + + function v(t, e, r) { + var i = h(n++, 2); + return i.t = t, i.__c || (i.__ = [r ? r(e) : P(void 0, e), function (t) { + var e = i.t(i.__[0], t); + i.__[0] !== e && (i.__ = [e, i.__[1]], i.__c.setState({})) + }], i.__c = o), i.__ + } + + function g(t, e) { + var r = h(n++, 3); + !u.i.__s && S(r.__H, e) && (r.__ = t, r.__H = e, o.__H.__h.push(r)) + } + + function b(t, e) { + var r = h(n++, 4); + !u.i.__s && S(r.__H, e) && (r.__ = t, r.__H = e, o.__h.push(r)) + } + + function m(t, e) { + var r = h(n++, 7); + return S(r.__H, e) && (r.__ = t(), r.__H = e, r.__h = t), r.__ + } + + function O(t, e) { + return a = 8, m((function () { + return t + }), e) + } + + function _() { + var t; + for (c.sort((function (t, e) { + return t.__v.__b - e.__v.__b + })); t = c.pop();) if (t.__P) try { + t.__H.__h.forEach(j), t.__H.__h.forEach(E), t.__H.__h = [] + } catch (e) { + t.__H.__h = [], u.i.__e(e, t.__v) + } + } + + u.i.__b = function (t) { + o = null, s && s(t) + }, u.i.__r = function (t) { + l && l(t), n = 0; + var e = (o = t.__c).__H; + e && (e.__h.forEach(j), e.__h.forEach(E), e.__h = []) + }, u.i.diffed = function (t) { + f && f(t); + var e = t.__c; + e && e.__H && e.__H.__h.length && (1 !== c.push(e) && i === u.i.requestAnimationFrame || ((i = u.i.requestAnimationFrame) || x)(_)), o = null + }, u.i.__c = function (t, e) { + e.some((function (t) { + try { + t.__h.forEach(j), t.__h = t.__h.filter((function (t) { + return !t.__ || E(t) + })) + } catch (r) { + e.some((function (t) { + t.__h && (t.__h = []) + })), e = [], u.i.__e(r, t.__v) + } + })), p && p(t, e) + }, u.i.unmount = function (t) { + d && d(t); + var e, r = t.__c; + r && r.__H && (r.__H.__.forEach((function (t) { + try { + j(t) + } catch (t) { + e = t + } + })), e && u.i.__e(e, r.__v)) + }; + var w = "function" == typeof requestAnimationFrame; + + function x(t) { + var e, r = function () { + clearTimeout(n), w && cancelAnimationFrame(e), setTimeout(t) + }, n = setTimeout(r, 100); + w && (e = requestAnimationFrame(r)) + } + + function j(t) { + var e = o, r = t.__c; + "function" == typeof r && (t.__c = void 0, r()), o = e + } + + function E(t) { + var e = o; + t.__c = t.__(), o = e + } + + function S(t, e) { + return !t || t.length !== e.length || e.some((function (e, r) { + return e !== t[r] + })) + } + + function P(t, e) { + return "function" == typeof e ? e(t) : e + } + + function A(t, e) { + for (var r in e) t[r] = e[r]; + return t + } + + function k(t, e) { + for (var r in t) if ("__source" !== r && !(r in e)) return !0; + for (var n in e) if ("__source" !== n && t[n] !== e[n]) return !0; + return !1 + } + + function D(t) { + this.props = t + } + + function T(t, e) { + function r(t) { + var r = this.props.ref, n = r == t.ref; + return !n && r && (r.call ? r(null) : r.current = null), e ? !e(this.props, t) || !n : k(this.props, t) + } + + function n(e) { + return this.shouldComponentUpdate = r, Object(u.e)(t, e) + } + + return n.displayName = "Memo(" + (t.displayName || t.name) + ")", n.prototype.isReactComponent = !0, n.__f = !0, n + } + + (D.prototype = new u.a).isPureReactComponent = !0, D.prototype.shouldComponentUpdate = function (t, e) { + return k(this.props, t) || k(this.state, e) + }; + var M = u.i.__b; + u.i.__b = function (t) { + t.type && t.type.__f && t.ref && (t.props.ref = t.ref, t.ref = null), M && M(t) + }; + var N = "undefined" != typeof Symbol && Symbol.for && Symbol.for("react.forward_ref") || 3911; + + function C(t) { + function e(e, r) { + var n = A({}, e); + return delete n.ref, t(n, !(r = e.ref || r) || "object" == typeof r && !("current" in r) ? null : r) + } + + return e.$$typeof = N, e.render = e, e.prototype.isReactComponent = e.__f = !0, e.displayName = "ForwardRef(" + (t.displayName || t.name) + ")", e + } + + var R = function (t, e) { + return null == t ? null : Object(u.k)(Object(u.k)(t).map(e)) + }, I = { + map: R, forEach: R, count: function (t) { + return t ? Object(u.k)(t).length : 0 + }, only: function (t) { + var e = Object(u.k)(t); + if (1 !== e.length) throw"Children.only"; + return e[0] + }, toArray: u.k + }, L = u.i.__e; + u.i.__e = function (t, e, r) { + if (t.then) for (var n, o = e; o = o.__;) if ((n = o.__c) && n.__c) return null == e.__e && (e.__e = r.__e, e.__k = r.__k), n.__c(t, e); + L(t, e, r) + }; + var z = u.i.unmount; + + function B(t, e, r) { + return t && (t.__c && t.__c.__H && (t.__c.__H.__.forEach((function (t) { + "function" == typeof t.__c && t.__c() + })), t.__c.__H = null), null != (t = A({}, t)).__c && (t.__c.__P === r && (t.__c.__P = e), t.__c = null), t.__k = t.__k && t.__k.map((function (t) { + return B(t, e, r) + }))), t + } + + function U(t, e, r) { + return t && (t.__v = null, t.__k = t.__k && t.__k.map((function (t) { + return U(t, e, r) + })), t.__c && t.__c.__P === e && (t.__e && r.insertBefore(t.__e, t.__d), t.__c.__e = !0, t.__c.__P = r)), t + } + + function F() { + this.__u = 0, this.t = null, this.__b = null + } + + function H(t) { + var e = t.__.__c; + return e && e.__e && e.__e(t) + } + + function X() { + this.u = null, this.o = null + } + + u.i.unmount = function (t) { + var e = t.__c; + e && e.__R && e.__R(), e && !0 === t.__h && (t.type = null), z && z(t) + }, (F.prototype = new u.a).__c = function (t, e) { + var r = e.__c, n = this; + null == n.t && (n.t = []), n.t.push(r); + var o = H(n.__v), i = !1, u = function () { + i || (i = !0, r.__R = null, o ? o(a) : a()) + }; + r.__R = u; + var a = function () { + if (!--n.__u) { + if (n.state.__e) { + var t = n.state.__e; + n.__v.__k[0] = U(t, t.__c.__P, t.__c.__O) + } + var e; + for (n.setState({__e: n.__b = null}); e = n.t.pop();) e.forceUpdate() + } + }, c = !0 === e.__h; + n.__u++ || c || n.setState({__e: n.__b = n.__v.__k[0]}), t.then(u, u) + }, F.prototype.componentWillUnmount = function () { + this.t = [] + }, F.prototype.render = function (t, e) { + if (this.__b) { + if (this.__v.__k) { + var r = document.createElement("div"), n = this.__v.__k[0].__c; + this.__v.__k[0] = B(this.__b, r, n.__O = n.__P) + } + this.__b = null + } + var o = e.__e && Object(u.e)(u.b, null, t.fallback); + return o && (o.__h = null), [Object(u.e)(u.b, null, e.__e ? null : t.children), o] + }; + var G = function (t, e, r) { + if (++r[1] === r[0] && t.o.delete(e), t.props.revealOrder && ("t" !== t.props.revealOrder[0] || !t.o.size)) for (r = t.u; r;) { + for (; r.length > 3;) r.pop()(); + if (r[1] < r[0]) break; + t.u = r = r[2] + } + }; + + function Y(t) { + return this.getChildContext = function () { + return t.context + }, t.children + } + + function V(t) { + var e = this, r = t.i; + e.componentWillUnmount = function () { + Object(u.j)(null, e.l), e.l = null, e.i = null + }, e.i && e.i !== r && e.componentWillUnmount(), t.__v ? (e.l || (e.i = r, e.l = { + nodeType: 1, + parentNode: r, + childNodes: [], + appendChild: function (t) { + this.childNodes.push(t), e.i.appendChild(t) + }, + insertBefore: function (t, r) { + this.childNodes.push(t), e.i.appendChild(t) + }, + removeChild: function (t) { + this.childNodes.splice(this.childNodes.indexOf(t) >>> 1, 1), e.i.removeChild(t) + } + }), Object(u.j)(Object(u.e)(Y, {context: e.context}, t.__v), e.l)) : e.l && e.componentWillUnmount() + } + + (X.prototype = new u.a).__e = function (t) { + var e = this, r = H(e.__v), n = e.o.get(t); + return n[0]++, function (o) { + var i = function () { + e.props.revealOrder ? (n.push(o), G(e, t, n)) : o() + }; + r ? r(i) : i() + } + }, X.prototype.render = function (t) { + this.u = null, this.o = new Map; + var e = Object(u.k)(t.children); + t.revealOrder && "b" === t.revealOrder[0] && e.reverse(); + for (var r = e.length; r--;) this.o.set(e[r], this.u = [1, 0, this.u]); + return t.children + }, X.prototype.componentDidUpdate = X.prototype.componentDidMount = function () { + var t = this; + this.o.forEach((function (e, r) { + G(t, r, e) + })) + }; + var W = "undefined" != typeof Symbol && Symbol.for && Symbol.for("react.element") || 60103, + K = /^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|marker(?!H|W|U)|overline|paint|stop|strikethrough|stroke|text(?!L)|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/, + $ = "undefined" != typeof document, Z = function (t) { + return ("undefined" != typeof Symbol && "symbol" == typeof Symbol() ? /fil|che|rad/i : /fil|che|ra/i).test(t) + }; + u.a.prototype.isReactComponent = {}, ["componentWillMount", "componentWillReceiveProps", "componentWillUpdate"].forEach((function (t) { + Object.defineProperty(u.a.prototype, t, { + configurable: !0, get: function () { + return this["UNSAFE_" + t] + }, set: function (e) { + Object.defineProperty(this, t, {configurable: !0, writable: !0, value: e}) + } + }) + })); + var q = u.i.event; + + function J() { + } + + function Q() { + return this.cancelBubble + } + + function tt() { + return this.defaultPrevented + } + + u.i.event = function (t) { + return q && (t = q(t)), t.persist = J, t.isPropagationStopped = Q, t.isDefaultPrevented = tt, t.nativeEvent = t + }; + var et, rt = { + configurable: !0, get: function () { + return this.class + } + }, nt = u.i.vnode; + u.i.vnode = function (t) { + var e = t.type, r = t.props, n = r; + if ("string" == typeof e) { + var o = -1 === e.indexOf("-"); + for (var i in n = {}, r) { + var a = r[i]; + $ && "children" === i && "noscript" === e || "value" === i && "defaultValue" in r && null == a || ("defaultValue" === i && "value" in r && null == r.value ? i = "value" : "download" === i && !0 === a ? a = "" : /ondoubleclick/i.test(i) ? i = "ondblclick" : /^onchange(textarea|input)/i.test(i + e) && !Z(r.type) ? i = "oninput" : /^onfocus$/i.test(i) ? i = "onfocusin" : /^onblur$/i.test(i) ? i = "onfocusout" : /^on(Ani|Tra|Tou|BeforeInp)/.test(i) ? i = i.toLowerCase() : o && K.test(i) ? i = i.replace(/[A-Z0-9]/, "-$&").toLowerCase() : null === a && (a = void 0), n[i] = a) + } + "select" == e && n.multiple && Array.isArray(n.value) && (n.value = Object(u.k)(r.children).forEach((function (t) { + t.props.selected = -1 != n.value.indexOf(t.props.value) + }))), "select" == e && null != n.defaultValue && (n.value = Object(u.k)(r.children).forEach((function (t) { + t.props.selected = n.multiple ? -1 != n.defaultValue.indexOf(t.props.value) : n.defaultValue == t.props.value + }))), t.props = n, r.class != r.className && (rt.enumerable = "className" in r, null != r.className && (n.class = r.className), Object.defineProperty(n, "className", rt)) + } + t.$$typeof = W, nt && nt(t) + }; + var ot = u.i.__r; + u.i.__r = function (t) { + ot && ot(t), et = t.__c + }; + var it = { + ReactCurrentDispatcher: { + current: { + readContext: function (t) { + return et.__n[t.__c].props.value + } + } + } + }; + + function ut(t) { + return !!t && t.$$typeof === W + } + + var at = function (t, e) { + return t(e) + }, ct = u.b, st = { + useState: y, useReducer: v, useEffect: g, useLayoutEffect: b, useRef: function (t) { + return a = 5, m((function () { + return {current: t} + }), []) + }, useImperativeHandle: function (t, e, r) { + a = 6, b((function () { + "function" == typeof t ? t(e()) : t && (t.current = e()) + }), null == r ? r : r.concat(t)) + }, useMemo: m, useCallback: O, useContext: function (t) { + var e = o.context[t.__c], r = h(n++, 9); + return r.c = t, e ? (null == r.__ && (r.__ = !0, e.sub(o)), e.props.value) : t.__ + }, useDebugValue: function (t, e) { + u.i.useDebugValue && u.i.useDebugValue(e ? e(t) : t) + }, version: "17.0.2", Children: I, render: function (t, e, r) { + return null == e.__k && (e.textContent = ""), Object(u.j)(t, e), "function" == typeof r && r(), t ? t.__c : null + }, hydrate: function (t, e, r) { + return Object(u.h)(t, e), "function" == typeof r && r(), t ? t.__c : null + }, unmountComponentAtNode: function (t) { + return !!t.__k && (Object(u.j)(null, t), !0) + }, createPortal: function (t, e) { + return Object(u.e)(V, {__v: t, i: e}) + }, createElement: u.e, createContext: u.d, createFactory: function (t) { + return u.e.bind(null, t) + }, cloneElement: function (t) { + return ut(t) ? u.c.apply(null, arguments) : t + }, createRef: u.f, Fragment: u.b, isValidElement: ut, findDOMNode: function (t) { + return t && (t.base || 1 === t.nodeType && t) || null + }, Component: u.a, PureComponent: D, memo: T, forwardRef: C, flushSync: function (t, e) { + return t(e) + }, unstable_batchedUpdates: at, StrictMode: ct, Suspense: F, SuspenseList: X, lazy: function (t) { + var e, r, n; + + function o(o) { + if (e || (e = t()).then((function (t) { + r = t.default || t + }), (function (t) { + n = t + })), n) throw n; + if (!r) throw e; + return Object(u.e)(r, o) + } + + return o.displayName = "Lazy", o.__f = !0, o + }, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: it + }; + e.d = st + }, function (t, e, r) { + var n = r(7), o = r(152), i = r(153), u = r(187), a = r(57), c = function (t) { + if (t && t.forEach !== u) try { + a(t, "forEach", u) + } catch (e) { + t.forEach = u + } + }; + for (var s in o) o[s] && c(n[s] && n[s].prototype); + c(i) + }, function (t, e, r) { + r(17)({target: "Object", stat: !0}, {setPrototypeOf: r(102)}) + }, function (t, e, r) { + var n = r(17), o = r(18), i = r(40), u = r(101), a = r(143); + n({ + target: "Object", stat: !0, forced: o((function () { + u(1) + })), sham: !a + }, { + getPrototypeOf: function (t) { + return u(i(t)) + } + }) + }, function (t, e, r) { + var n = r(17), o = r(46), i = r(74), u = r(202), a = r(162), c = r(32), s = r(33), l = r(60), f = r(18), + p = o("Reflect", "construct"), d = Object.prototype, h = [].push, y = f((function () { + function t() { + } + + return !(p((function () { + }), [], t) instanceof t) + })), v = !f((function () { + p((function () { + })) + })), g = y || v; + n({target: "Reflect", stat: !0, forced: g, sham: g}, { + construct: function (t, e) { + a(t), c(e); + var r = arguments.length < 3 ? t : a(arguments[2]); + if (v && !y) return p(t, e, r); + if (t == r) { + switch (e.length) { + case 0: + return new t; + case 1: + return new t(e[0]); + case 2: + return new t(e[0], e[1]); + case 3: + return new t(e[0], e[1], e[2]); + case 4: + return new t(e[0], e[1], e[2], e[3]) + } + var n = [null]; + return i(h, n, e), new (i(u, t, n)) + } + var o = r.prototype, f = l(s(o) ? o : d), g = i(t, f, e); + return s(g) ? g : f + } + }) + }, function (t, e) { + var r = Function.prototype, n = r.bind, o = r.call, i = n && n.bind(o); + t.exports = n ? function (t) { + return t && i(o, t) + } : function (t) { + return t && function () { + return o.apply(t, arguments) + } + } + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(7), i = r(96), u = r(99), a = r(33), c = r(73), s = r(45), l = r(41), f = r(62), p = r(28), + d = r(79), h = r(98), y = d("slice"), v = p("species"), g = o.Array, b = Math.max; + n({target: "Array", proto: !0, forced: !y}, { + slice: function (t, e) { + var r, n, o, p = l(this), d = s(p), y = c(t, d), m = c(void 0 === e ? d : e, d); + if (i(p) && (r = p.constructor, (u(r) && (r === g || i(r.prototype)) || a(r) && null === (r = r[v])) && (r = void 0), r === g || void 0 === r)) return h(p, y, m); + for (n = new (void 0 === r ? g : r)(b(m - y, 0)), o = 0; y < m; y++, o++) y in p && f(n, o, p[y]); + return n.length = o, n + } + }) + }, function (t, e, r) { + var n = r(7), o = r(50).f, i = r(57), u = r(42), a = r(110), c = r(134), s = r(95); + t.exports = function (t, e) { + var r, l, f, p, d, h = t.target, y = t.global, v = t.stat; + if (r = y ? n : v ? n[h] || a(h, {}) : (n[h] || {}).prototype) for (l in e) { + if (p = e[l], f = t.noTargetGet ? (d = o(r, l)) && d.value : r[l], !s(y ? l : h + (v ? "." : "#") + l, t.forced) && void 0 !== f) { + if (typeof p == typeof f) continue; + c(p, f) + } + (t.sham || f && f.sham) && i(p, "sham", !0), u(r, l, p, t) + } + } + }, function (t, e) { + t.exports = function (t) { + try { + return !!t() + } catch (t) { + return !0 + } + } + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(103); + n({target: "RegExp", proto: !0, forced: /./.exec !== o}, {exec: o}) + }, function (t, e, r) { + var n = r(17), o = r(40), i = r(75); + n({ + target: "Object", stat: !0, forced: r(18)((function () { + i(1) + })) + }, { + keys: function (t) { + return i(o(t)) + } + }) + }, function (t, e, r) { + var n = r(36), o = r(71).EXISTS, i = r(15), u = r(38).f, a = Function.prototype, c = i(a.toString), + s = /function\b(?:\s|\/\*[\S\s]*?\*\/|\/\/[^\n\r]*[\n\r]+)*([^\s(/]*)/, l = i(s.exec); + n && !o && u(a, "name", { + configurable: !0, get: function () { + try { + return l(s, c(this))[1] + } catch (t) { + return "" + } + } + }) + }, function (t, e, r) { + var n = r(17), o = r(18), i = r(41), u = r(50).f, a = r(36), c = o((function () { + u(1) + })); + n({target: "Object", stat: !0, forced: !a || c, sham: !a}, { + getOwnPropertyDescriptor: function (t, e) { + return u(i(t), e) + } + }) + }, function (t, e, r) { + var n = r(17), o = r(188); + n({ + target: "Array", stat: !0, forced: !r(120)((function (t) { + Array.from(t) + })) + }, {from: o}) + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(77).filter; + n({target: "Array", proto: !0, forced: !r(79)("filter")}, { + filter: function (t) { + return o(this, t, arguments.length > 1 ? arguments[1] : void 0) + } + }) + }, function (t, e, r) { + var n = r(17), o = r(36), i = r(135), u = r(41), a = r(50), c = r(62); + n({target: "Object", stat: !0, sham: !o}, { + getOwnPropertyDescriptors: function (t) { + for (var e, r, n = u(t), o = a.f, s = i(n), l = {}, f = 0; s.length > f;) void 0 !== (r = o(n, e = s[f++])) && c(l, e, r); + return l + } + }) + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(7), i = r(18), u = r(96), a = r(33), c = r(40), s = r(45), l = r(62), f = r(115), + p = r(79), d = r(28), h = r(68), y = d("isConcatSpreadable"), v = 9007199254740991, + g = "Maximum allowed index exceeded", b = o.TypeError, m = h >= 51 || !i((function () { + var t = []; + return t[y] = !1, t.concat()[0] !== t + })), O = p("concat"), _ = function (t) { + if (!a(t)) return !1; + var e = t[y]; + return void 0 !== e ? !!e : u(t) + }; + n({target: "Array", proto: !0, forced: !m || !O}, { + concat: function (t) { + var e, r, n, o, i, u = c(this), a = f(u, 0), p = 0; + for (e = -1, n = arguments.length; e < n; e++) if (_(i = -1 === e ? u : arguments[e])) { + if (p + (o = s(i)) > v) throw b(g); + for (r = 0; r < o; r++, p++) r in i && l(a, p, i[r]) + } else { + if (p >= v) throw b(g); + l(a, p++, i) + } + return a.length = p, a + } + }) + }, , function (t, e, r) { + var n = r(7), o = r(89), i = r(35), u = r(90), a = r(108), c = r(132), s = o("wks"), l = n.Symbol, + f = l && l.for, p = c ? l : l && l.withoutSetter || u; + t.exports = function (t) { + if (!i(s, t) || !a && "string" != typeof s[t]) { + var e = "Symbol." + t; + a && i(l, t) ? s[t] = l[t] : s[t] = c && f ? f(e) : p(e) + } + return s[t] + } + }, function (t, e, r) { + var n = r(17), o = r(201); + n({target: "Object", stat: !0, forced: Object.assign !== o}, {assign: o}) + }, function (t, e) { + t.exports = function (t) { + return "function" == typeof t + } + }, function (t, e, r) { + "use strict"; + var n = r(106), o = "object" == typeof self && self && self.Object === Object && self, + i = n.a || o || Function("return this")(); + e.a = i + }, function (t, e, r) { + var n = r(7), o = r(33), i = n.String, u = n.TypeError; + t.exports = function (t) { + if (o(t)) return t; + throw u(i(t) + " is not an object") + } + }, function (t, e, r) { + var n = r(30); + t.exports = function (t) { + return "object" == typeof t ? null !== t : n(t) + } + }, function (t, e) { + var r = Function.prototype.call; + t.exports = r.bind ? r.bind(r) : function () { + return r.apply(r, arguments) + } + }, function (t, e, r) { + var n = r(15), o = r(40), i = n({}.hasOwnProperty); + t.exports = Object.hasOwn || function (t, e) { + return i(o(t), e) + } + }, function (t, e, r) { + var n = r(18); + t.exports = !n((function () { + return 7 != Object.defineProperty({}, 1, { + get: function () { + return 7 + } + })[1] + })) + }, function (t, e, r) { + "use strict"; + var n = r(17), o = r(77).map; + n({target: "Array", proto: !0, forced: !r(79)("map")}, { + map: function (t) { + return o(this, t, arguments.length > 1 ? arguments[1] : void 0) + } + }) + }, function (t, e, r) { + var n = r(7), o = r(36), i = r(133), u = r(32), a = r(86), c = n.TypeError, s = Object.defineProperty; + e.f = o ? s : function (t, e, r) { + if (u(t), e = a(e), u(r), i) try { + return s(t, e, r) + } catch (t) { + } + if ("get" in r || "set" in r) throw c("Accessors not supported"); + return "value" in r && (t[e] = r.value), t + } + }, function (t, e, r) { + var n = r(7), o = r(97), i = n.String; + t.exports = function (t) { + if ("Symbol" === o(t)) throw TypeError("Cannot convert a Symbol value to a string"); + return i(t) + } + }, function (t, e, r) { + var n = r(7), o = r(44), i = n.Object; + t.exports = function (t) { + return i(o(t)) + } + }, function (t, e, r) { + var n = r(85), o = r(44); + t.exports = function (t) { + return n(o(t)) + } + }, function (t, e, r) { + var n = r(7), o = r(30), i = r(35), u = r(57), a = r(110), c = r(92), s = r(58), l = r(71).CONFIGURABLE, + f = s.get, p = s.enforce, d = String(String).split("String"); + (t.exports = function (t, e, r, c) { + var s, f = !!c && !!c.unsafe, h = !!c && !!c.enumerable, y = !!c && !!c.noTargetGet, + v = c && void 0 !== c.name ? c.name : e; + o(r) && ("Symbol(" === String(v).slice(0, 7) && (v = "[" + String(v).replace(/^Symbol\(([^)]*)\)/, "$1") + "]"), (!i(r, "name") || l && r.name !== v) && u(r, "name", v), (s = p(r)).source || (s.source = d.join("string" == typeof v ? v : ""))), t !== n ? (f ? !y && t[e] && (h = !0) : delete t[e], h ? t[e] = r : u(t, e, r)) : h ? t[e] = r : a(e, r) + })(Function.prototype, "toString", (function () { + return o(this) && f(this).source || c(this) + })) + }, function (t, e, r) { + "use strict"; + (function (t) { + r.d(e, "d", (function () { + return i + })), r.d(e, "c", (function () { + return u + })), r.d(e, "b", (function () { + return a + })), r.d(e, "a", (function () { + return s + })); + var n = r(10), o = function (t, e) { + var r = "function" == typeof Symbol && t[Symbol.iterator]; + if (!r) return t; + var n, o, i = r.call(t), u = []; + try { + for (; (void 0 === e || e-- > 0) && !(n = i.next()).done;) u.push(n.value) + } catch (t) { + o = {error: t} + } finally { + try { + n && !n.done && (r = i.return) && r.call(i) + } finally { + if (o) throw o.error + } + } + return u + }; + + function i() { + var t = o(Object(n.j)(0), 2)[1]; + return Object(n.h)((function () { + t((function (t) { + return t + 1 + })) + }), []) + } + + function u(t) { + if (!t || "object" != typeof t) return !1; + var e = Object.getPrototypeOf(t); + return !e || e === Object.prototype + } + + function a(t) { + return "function" == typeof Symbol ? Symbol.for(t) : "__$mobx-react " + t + "__" + } + + var c = {}; + + function s() { + return "undefined" != typeof window ? window : void 0 !== t ? t : "undefined" != typeof self ? self : c + } + }).call(this, r(66)) + }, function (t, e, r) { + var n = r(7).TypeError; + t.exports = function (t) { + if (null == t) throw n("Can't call method on " + t); + return t + } + }, function (t, e, r) { + var n = r(94); + t.exports = function (t) { + return n(t.length) + } + }, function (t, e, r) { + var n = r(7), o = r(30), i = function (t) { + return o(t) ? t : void 0 + }; + t.exports = function (t, e) { + return arguments.length < 2 ? i(n[t]) : n[t] && n[t][e] + } + }, function (t, e, r) { + var n = r(17), o = r(34), i = r(33), u = r(32), a = r(203), c = r(50), s = r(101); + n({target: "Reflect", stat: !0}, { + get: function t(e, r) { + var n, l, f = arguments.length < 3 ? e : arguments[2]; + return u(e) === f ? e[r] : (n = c.f(e, r)) ? a(n) ? n.value : void 0 === n.get ? void 0 : o(n.get, f) : i(l = s(e)) ? t(l, r, f) : void 0 + } + }) + }, function (t, e, r) { + "use strict"; + (function (t) { + var n = r(31), o = r(171), i = "object" == typeof exports && exports && !exports.nodeType && exports, + u = i && "object" == typeof t && t && !t.nodeType && t, a = u && u.exports === i ? n.a.Buffer : void 0, + c = (a ? a.isBuffer : void 0) || o.a; + e.a = c + }).call(this, r(122)(t)) + }, function (t, e, r) { + "use strict"; + (function (t) { + var n = r(106), o = "object" == typeof exports && exports && !exports.nodeType && exports, + i = o && "object" == typeof t && t && !t.nodeType && t, u = i && i.exports === o && n.a.process, + a = function () { + try { + var t = i && i.require && i.require("util").types; + return t || u && u.binding && u.binding("util") + } catch (t) { + } + }(); + e.a = a + }).call(this, r(122)(t)) + }, function (t, e, r) { + var n = r(36), o = r(34), i = r(84), u = r(67), a = r(41), c = r(86), s = r(35), l = r(133), + f = Object.getOwnPropertyDescriptor; + e.f = n ? f : function (t, e) { + if (t = a(t), e = c(e), l) try { + return f(t, e) + } catch (t) { + } + if (s(t, e)) return u(!o(i.f, t, e), t[e]) + } + }, function (t, e, r) { + var n = r(15), o = n({}.toString), i = n("".slice); + t.exports = function (t) { + return i(o(t), 8, -1) + } + }, function (t, e, r) { + "use strict"; + r(182)("Map", (function (t) { + return function () { + return t(this, arguments.length ? arguments[0] : void 0) + } + }), r(186)) + }, function (t, e, r) { + var n = r(17), o = r(218).entries; + n({target: "Object", stat: !0}, { + entries: function (t) { + return o(t) + } + }) + }, function (t, e, r) { + var n = r(15); + t.exports = n({}.isPrototypeOf) + }, function (t, e, r) { + var n = r(46); + t.exports = n("navigator", "userAgent") || "" + }, function (t, e, r) { + var n = r(7), o = r(30), i = r(88), u = n.TypeError; + t.exports = function (t) { + if (o(t)) return t; + throw u(i(t) + " is not a function") + } + }, function (t, e, r) { + var n = r(36), o = r(38), i = r(67); + t.exports = n ? function (t, e, r) { + return o.f(t, e, i(1, r)) + } : function (t, e, r) { + return t[e] = r, t + } + }, function (t, e, r) { + var n, o, i, u = r(175), a = r(7), c = r(15), s = r(33), l = r(57), f = r(35), p = r(109), d = r(93), h = r(70), + y = "Object already initialized", v = a.TypeError, g = a.WeakMap; + if (u || p.state) { + var b = p.state || (p.state = new g), m = c(b.get), O = c(b.has), _ = c(b.set); + n = function (t, e) { + if (O(b, t)) throw new v(y); + return e.facade = t, _(b, t, e), e + }, o = function (t) { + return m(b, t) || {} + }, i = function (t) { + return O(b, t) + } + } else { + var w = d("state"); + h[w] = !0, n = function (t, e) { + if (f(t, w)) throw new v(y); + return e.facade = t, l(t, w, e), e + }, o = function (t) { + return f(t, w) ? t[w] : {} + }, i = function (t) { + return f(t, w) + } + } + t.exports = { + set: n, get: o, has: i, enforce: function (t) { + return i(t) ? o(t) : n(t, {}) + }, getterFor: function (t) { + return function (e) { + var r; + if (!s(e) || (r = o(e)).type !== t) throw v("Incompatible receiver, " + t + " required"); + return r + } + } + } + }, function (t, e) { + var r = Math.ceil, n = Math.floor; + t.exports = function (t) { + var e = +t; + return e != e || 0 === e ? 0 : (e > 0 ? n : r)(e) + } + }, function (t, e, r) { + var n, o = r(32), i = r(176), u = r(111), a = r(70), c = r(138), s = r(91), l = r(93), f = l("IE_PROTO"), + p = function () { + }, d = function (t) { + return "'; + return html; + } + + function randStrName() { + return 'a' + Math.random().toString(36).substr(9); + } + form.on('submit(formDemo)', function(data) { + layer.msg(JSON.stringify(data.field)); + return false; + }); + exports('design', {}); +}); diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/dtree.css b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/dtree.css new file mode 100644 index 0000000000000000000000000000000000000000..3e5364d4d5fa819bd748d4ce91476300482d68f7 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/dtree.css @@ -0,0 +1,112 @@ + +/**************** 主题换肤 ****************/ +/* 默认风格*/ +.dtree-theme-item-this{background-color: #d2d2d2!important;} +.dtree-theme-item:hover{background-color: #eaeceb!important;} +.dtree-theme-item cite{font-size:12px!important;} +.dtree-theme-item:hover cite{color:#fe7786!important;} + +.dtree-theme-dtreefont{font-size: 16px!important;} +.dtree-theme-ficon{color:#000!important;} +.dtree-theme-icon{color:orange!important;} +.dtree-theme-checkbox:hover{color:#fe7786!important;} +.dtree-theme-choose{color:#fe7786!important;} + +/* layui主题风格*/ +.dtree-layui-item-this{background: none!important;} +.dtree-layui-item:hover{background: none!important;} +.dtree-layui-item cite{font-size:14px!important;} +.dtree-layui-item:hover cite{opacity:0.5;filter:Alpha(opacity=50);text-decoration: underline;} + +.dtree-layui-dtreefont{font-size: 18px!important;} +.dtree-layui-ficon{font-size: 18px!important;color:#393D49!important;} +.dtree-layui-icon{color:#666!important;} +.dtree-layui-checkbox:hover{color:#5FB878!important;} +.dtree-layui-choose{color:#5FB878!important;} + +/* laySimple主题风格*/ +.dtree-laySimple-item-this{background-color: #d2d2d2!important;} +.dtree-laySimple-item:hover{background-color: #eaeceb!important;} +.dtree-laySimple-item cite{font-size:12px!important;} +.dtree-laySimple-item:hover cite{color:#01AAED!important;} + +.dtree-laySimple-dtreefont{font-size: 16px!important;} +.dtree-laySimple-ficon{font-size: 14px!important;color:#393D49!important;} +.dtree-laySimple-icon{color:#393D49!important;} +.dtree-laySimple-checkbox:hover{color:#01AAED!important;} +.dtree-laySimple-choose{color:#01AAED!important;} +/**************** 树基础 ****************/ +/* 菜单栏*/ +.dtree-menubar {padding-left: 10px;} +.dtree-menubar .layui-btn-group .layui-btn-sm{height: 20px;line-height: 20px;padding: 0 5px;font-size: 12px;} +.dtree-menubar .layui-btn-group .layui-btn-sm i{font-size: 12px!important;} + +/* 工具栏*/ +.dtree-toolbar{position: absolute;z-index: 940520;padding: 0;background-color: #eceaeb;} +.dtree-toolbar .layui-nav-child{position: static;} +.dtree-toolbar .layui-nav-child dd{cursor: pointer;} +.dtree-toolbar .layui-nav-child dd a i{font-size:16px;display: inline-block;margin: 0px 1px;color:#fe7786;} +.dtree-toolbar .layui-nav-child dd a i:hover{font-weight: bold;} +.dtree-toolbar .layui-nav-bar{display: none!important;} +.dtree-toolbar-tool{padding: 30px;} + +.dtree-toolbar-fixed{position: absolute;right: 5px;top: 2px;font-style: normal;transition: all .3s;-webkit-transition: all .3s;} +/*.dtree-toolbar-fixed a{border:1px solid #fe7786;}*/ +.dtree-toolbar-fixed a i{font-size:14px;display: inline-block;margin: 0px 1px;color:#fe7786;} +.dtree-toolbar-fixed a i:hover{opacity:0.8;filter:Alpha(opacity=80);} + +/* 树基本*/ +.dtree{width:260px;} +.dtree-nav-item{line-height:33px;padding-left:16px;} +.dtree-nav-ul-sid{display: none;} +.dtree-none-text{font-size: 12px;text-align: center;color: gray;} + +/* 树线*/ +.dtree-nav-first-line,.dtree-nav-line,.dtree-nav-last-line{position: relative;} +.dtree-nav-first-line:before{content:"";position: absolute;height: 0;border-left: 1px dotted #c0c4cc;} +.dtree-nav-first-line:after{content:"";position: absolute;height: 0;border-top: 1px dotted #c0c4cc;} + +.dtree-nav-line:before{content:"";position: absolute;top: 0;left: 7px;width: 0;height: 100%;border-left: 1px dotted #c0c4cc;} +.dtree-nav-line:after{content:"";position: absolute;top: 16px;left: 8px;width: 9px;height: 0;border-top: 1px dotted #c0c4cc;} + +.dtree-nav-last-line:before{content:"";position: absolute;top: 0;left: 7px;width: 0;height: 17px;border-left: 1px dotted #c0c4cc;} +.dtree-nav-last-line:after{content:"";position: absolute;top: 16px;left: 8px;width: 9px;height: 0;border-top: 1px dotted #c0c4cc;} + + +/* 图标及复选框*/ +.dtreefont{cursor: pointer;} +.dtreefont-special{margin: 0 4px;} +.dtree-nav-checkbox-div{display: inline-block;} +.dtree-nav-checkbox-div>i{display: inline-block;margin: 0px 1px;} +.dtree-nav-checkbox-div>i:last-child{margin-right: 4px;} +.dtree-nav-checkbox-div>i:hover{opacity:0.8;filter:Alpha(opacity=80);} + +/* 行 文字*/ +.dtree-nav-div{display:block;vertical-align:top;position:relative;} +.dtree-nav-div cite{font-style: normal;cursor: pointer;} +.dtree-nav-div:hover cite{opacity:0.7;filter:Alpha(opacity=70);transition: all .3s;-webkit-transition: all .3s;} + +/* 规则属性*/ +.dtree-nav-show {display: block!important;} +.dtree-nav-hide {display: none!important;} +.dtree-nav-this {} +.dtree-icon-hide {opacity:0;filter:Alpha(opacity=0);} +.dtree-icon-null-open,.dtree-icon-null-close,.dtree-icon-null{margin: 0 2px;} +.dtree-disabled{cursor: not-allowed; color:#c2c2c2!important;} +.dtree-disabled:hover{color:#c2c2c2!important;} +.dtree-nav-div cite.dtree-disabled{font-style: normal; cursor: not-allowed; color:#c2c2c2!important;} +.dtree-nav-div>cite.dtree-disabled:hover{color:#c2c2c2!important;} + + +/** 下拉树属性*/ +.dtree-select{position: absolute;max-height: 500px;height: 350px;overflow: auto;width: 99%;z-index: 123;display: none;border:1px solid silver;top: 42px;} +.dtree-select-show{display: block!important;} + +/* 简单适配*/ +@media screen and (max-width:1700px) and (min-width:1300px){ + .dtree-nav-item {padding-left: 15px;} +} + + + + diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/dtree.js b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/dtree.js new file mode 100644 index 0000000000000000000000000000000000000000..a05b22a8e3798284f8e2f84d4b715d04295a6095 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/dtree.js @@ -0,0 +1,4947 @@ +/** + *@Name dtree 树形组件 + *@Author 智慧的小西瓜 + *@DOCS http://www.wisdomelon.com/DTreeHelper/ + *@License https://www.layui.com/ + *@LASTTIME 2019/10/24 + *@VERSION v2.5.6 + */ +layui.define(['jquery','layer','form'], function(exports) { + var $ = layui.$, + layer = layui.layer, + form = layui.form; + + // 树的公共定义样式汇总 + var LI_NAV_CHILD = "dtree-nav-ul-sid", LI_NAV_ITEM = "dtree-nav-item", + LI_DIV_ITEM = "dtree-nav-div", DTREEFONTSPECIAL="dtreefont-special", NONETITLE="dtree-none-text", + LI_DIV_MENUBAR = "dtree-menubar", + LI_DIV_TOOLBAR = "dtree-toolbar", TOOLBAR_TOOL = "dtree-toolbar-tool", TOOLBAR_TOOL_EM = "dtree-toolbar-fixed", + LI_DIV_CHECKBAR = "dtree-nav-checkbox-div", + LI_CLICK_CHECKBAR = "d-click-checkbar", //绑定点击复选框时需要用到 + LI_DIV_TEXT_CLASS = "t-click", UL_ROOT="dtree", + LI_NAV_FIRST_LINE = "dtree-nav-first-line", LI_NAV_LINE = "dtree-nav-line", LI_NAV_LAST_LINE = "dtree-nav-last-line"; + + + // 树的公共指定 + var NAV_THIS = "dtree-nav-this", //当前节点 + NAV_SHOW = "dtree-nav-show", //显示子节点 + NAV_HIDE = "dtree-nav-hide", //隐藏节点 + NAV_DIS = "dtree-disabled", //禁用节点 + ICON_HIDE = "dtree-icon-hide", //隐藏图标 + $BODY = $("body"), //body选择器 + $WIN = $(window), //window窗口 + $DOC = $(document), //当前文档 + MOD_NAME = "dtree", //模块名称 + VERSION = "v2.5.6", //版本 + OPTIONS = {}, //全局属性配置 + DTrees = {}; //当前被实例化的树的集合 + + // 树的自定义图标 + var DTREEFONT = "dtreefont", //默认使用图标字体 + LI_DIV_CHECKBAR_ON = "dtree-icon-fuxuankuangxuanzhong", //复选框选中图标 + LI_DIV_CHECKBAR_OUT = "dtree-icon-fuxuankuang", //复选框未选中图标 + LI_DIV_CHECKBAR_NOALL = "dtree-icon-fuxuankuang-banxuan", //复选框半选图标 + LI_DIV_MENUBAR_DOWN = "dtree-icon-move-down", //menubar的展开全部的图标 + LI_DIV_MENUBAR_UP = "dtree-icon-move-up", //menubar的收缩全部的图标 + LI_DIV_MENUBAR_REFRESH = "dtree-icon-refresh", //menubar的刷新图标 + LI_DIV_MENUBAR_CHECKALL = "dtree-icon-roundcheckfill", //menubar的全选图标 + LI_DIV_MENUBAR_UNCHECKALL = "dtree-icon-roundclosefill", //menubar的全不选图标 + LI_DIV_MENUBAR_INVERTALL = "dtree-icon-roundcheck", //menubar的反选图标 + LI_DIV_MENUBAR_DELETE = "dtree-icon-delete1", //menubar的删除图标 + LI_DIV_MENUBAR_SEARCH = "dtree-icon-search_list_light", //menubar的搜索图标 + LI_DIV_TOOLBAR_PULLDOWN = "dtree-icon-pulldown", //toolbar的展开图标 + LI_DIV_TOOLBAR_PULLUP = "dtree-icon-pullup", //toolbar的收缩图标 + LI_DIV_TOOLBAR_ADD = "dtree-icon-roundadd", //toolbar的新增图标 + LI_DIV_TOOLBAR_EDIT = "dtree-icon-bianji", //toolbar的编辑图标 + LI_DIV_TOOLBAR_DEL = "dtree-icon-roundclose"; //toolbar的删除图标 + + // 树的非叶子节点图标集合 + var nodeIconArray = { + "-1": {"open": "dtree-icon-null-open", "close": "dtree-icon-null-close"}, //未指定 + "0" : {"open": "dtree-icon-wenjianjiazhankai", "close": "dtree-icon-weibiaoti5"}, //文件夹(二级图标默认样式) + "1" : {"open": "dtree-icon-jian", "close": "dtree-icon-jia"}, //+-图标(一级图标默认样式) + "2" : {"open": "dtree-icon-xiangxia1", "close": "dtree-icon-xiangyou"} //箭头图标 + }; + + // 树的叶子节点图标集合 + var leafIconArray = { + "-1": "dtree-icon-null", //未指定 + "0" : "dtree-icon-weibiaoti5", //文件夹 + "1" : "dtree-icon-yonghu", //人员 + "2" : "dtree-icon-fenzhijigou", //机构 + "3" : "dtree-icon-fenguangbaobiao", //报表 + "4" : "dtree-icon-xinxipilu", //信息 + "5" : "dtree-icon-shuye1", //叶子(二级图标默认样式) + "6" : "dtree-icon-caidan_xunzhang", //勋章 + "7" : "dtree-icon-normal-file", //文件 + "8" : "dtree-icon-dian", //小圆点(一级图标默认样式) + "9" : "dtree-icon-set-sm", //齿轮 + "10" : "dtree-icon-rate" //星星 + }; + + // 树的自定义样式 + var DTREE = "dtree-", //自定义样式前缀 + ITEMTHIS = "-item-this", //自定义样式当前行选中后缀 + ITEM = "-item", //自定义样式当前行后缀 + DFONT = "-dtreefont", //自定义样式图标样式后缀 + FICON = "-ficon", //自定义样式一级图标样式后缀 + ICON = "-icon", //自定义样式二级图标样式后缀 + CBOX = "-checkbox", //自定义样式复选框样式后缀 + CHS = "-choose"; //自定义样式复选框选中样式后缀 + + // 树自定义操作事件名称集合 绑定dtree-click的事件 + var eventName = { + checkNodeClick: "checkNodeClick", //点击复选框 + itemNodeClick: "itemNodeClick" //点击子节点div + }; + + // 树默认toolbar提供的功能集合 绑定dtree-tool的事件 + var defaultTool = { + pulldown: "pulldown", //点击展开当前节点下的全部节点 + pullup: "pullup", //点击收缩当前节点下的全部节点 + addTool: "addToolbar", //点击toolbar新增 + editTool: "editToolbar", //点击toolbar编辑 + delTool: "delToolbar" //点击toolbar删除 + }; + + // 树默认menubar提供的功能集合 绑定dtree-menu的事件 + var defaultMenu = { + moveDown: "moveDown", //menubar展开全部节点 + moveUp: "moveUp", //menubar收缩全部节点 + refresh: "refresh", //menubar刷新树 + checkAll: "checkAll", //menubar全选 + unCheckAll: "unCheckAll", //menubar全不选 + invertAll: "invertAll", //menubar反选 + remove: "remove", //menubar删除选中节点 + searchNode: "searchNode" //menubar查询节点 + }; + + // 树的公共事件 + var event = { + getElemId: function(options){ // 根据传入的参数获取ID + var elem = options.elem || ""; + var obj = options.obj || $(elem); + + if (obj.length == 0) { //页面中未找到绑定id + return ""; + } else { + return $(obj)[0].id; + } + }, + escape: function(html){ + if(typeof html !== 'string') return ''; + return html.replace(entityReg.escape, function(match){return entityMap.escape[match];}); + }, + unescape: function(str){ + if(typeof str !== 'string') return ''; + return str.replace(entityReg.unescape, function(match){return entityMap.unescape[match];}); + }, + cloneObj: function (obj, filter) { //深复制对象方法 + var newObj = {}; + if (obj instanceof Array) { + newObj = []; + } + var str = ""; + if(typeof filter !== 'undefined') {str = filter.join(",");} + for (var key in obj) { + if(str.indexOf(key) == -1){ + var val = obj[key]; + newObj[key] = typeof val === 'object' ? event.cloneObj(val, typeof filter !== undefined ? filter : []): val; + } + + } + return newObj; + }, + trimToDot: function(str){ + return str.replace(/ /g, "."); + } + }; + + // 特殊符号转义 + var keys = Object.keys || function(obj) { + obj = Object(obj); + var arr = []; + for(var a in obj) arr.push(a); + return arr; + }; + var invert = function(obj){ + obj = Object(obj); + var result = {}; + for(var a in obj) result[obj[a]] = a; + return result; + }; + var entityMap = { + escape: { + "&" : "&", + "<" : "<", + ">" : ">", + "'" : "&quo;" + } + }; + entityMap.unescape = invert(entityMap.escape); + var entityReg = { + escape: RegExp('[' + keys(entityMap.escape).join('') + ']', 'g'), + unescape: RegExp('(' + keys(entityMap.unescape).join('|') + ')', 'g') + }; + + //异步加载接口 + var AjaxHelper = { + request : function(config) { + var data = config.data ? config.data : {}; + var async = (typeof (config.async) === "boolean") ? config.async : true; + $.ajax({ + type : config.type ? config.type : "POST", + headers : config.headers, + url : config.url, + dataType : config.dataType ? config.dataType : "json", + data : data, + async : async, + contentType : config.contentType, + xhrFields: {withCredentials: config.withCredentials}, + success : config.success, + error : function(XMLHttpRequest, textStatus, errorThrown) { + if (typeof (config.error) === "function") { + config.error(XMLHttpRequest, textStatus, errorThrown); + } else { + layer.msg("异步加载失败: " + textStatus,{icon:5, shift:6}); + } + }, + statusCode : { + 404 : function() { + layer.msg('未找到指定请求,请检查访问路径!',{icon:5, shift:6}); + }, + 500 : function() { + layer.msg('系统错误!',{icon:5, shift:6}); + } + }, + complete : function(XMLHttpRequest, textStatus) { + if (typeof (config.complete) === "function") { + config.complete(XMLHttpRequest, textStatus); + } + } + }); + }, + serialize: function(param){ //json序列化 key=value&key1=value1 + var p = "?"; + for (var key in param) { + p += key + "=" + param[key] + "&"; + } + p = p.substring(0, p.length-1); + return p; + } + }; + + // 树类 + var DTree = function(options){ + var _this = this; + /** 默认赋值**/ + this.formatter = { // 数据过滤 + title: false // 文字,默认不开启 + }; + this.response = { // 树返回的json格式 + statusName: "code", //返回标识 + statusCode: 200, //返回码 + message: "message", //返回信息 + rootName: "data", //根节点名称 + treeId: "id", //节点ID + parentId: "parentId", //父节点ID + title: "title", //节点名称 + ficonClass: "ficonClass", //自定义一级图标 + iconClass: "iconClass", //自定义二级图标 + childName: "children", //子节点名称 + last: "last", //是否最后一级节点 +// level: "level", //层级 + spread: "spread", //展开 + disabled: "disabled", //禁用 + hide: "hide", //隐藏 + checkArr: "checkArr", //复选框列表 + checked: "checked", //是否选中 + type: "type", //复选框标记 + basicData: "basicData" //表示用户自定义需要存储在树节点中的数据 + }; + this.defaultRequest = { // 树的默认发起请求参数格式,最后会将value作为参数名称传递 + nodeId: "nodeId", //节点ID + parentId: "parentId", //父节点ID + context: "context", //节点内容 + leaf: "leaf", //是否叶子节点 + level: "level", //层级 + spread: "spread", //节点展开状态 + dataType: "dataType", //节点标记 + checked: "checked", //节点复选框选中状态 + initchecked: "initchecked", //节点复选框初始状态 + basicData: "basicData", //用户自定义的记录节点数据 + recordData: "recordData", //当前data数据(排除basicData和children字段) + }; + this.toolbarFun = { + addTreeNode: function(param, $div) { //添加树节点后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + editTreeNode: function(param, $div) { //编辑树节点后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + editTreeLoad: function(param){ // 编辑树的数据回显,用于打开编辑时,回填数据 + return ; + }, + delTreeNode: function(param, $div){ //删除树后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + loadToolbarBefore: function(buttons, param, $div){ // 右键菜单加载前的函数 + return buttons; + } + }; + this.toolbarStyle = { + title: "节点", + area: ["60%","80%"] + }; + this.menubarFun = { + remove: function(checkbarNodes){ //删除复选框选中节点,需要用户自定义,如未指定则树只是页面上做了修改 + return true; + } + }; + this.menubarTips = { + toolbar: [], + group: [defaultMenu.moveDown, defaultMenu.moveUp, defaultMenu.refresh, defaultMenu.checkAll, defaultMenu.unCheckAll, defaultMenu.invertAll, defaultMenu.remove, defaultMenu.searchNode], + freedom: [] + }; + this.checkbarFun = { + chooseBefore: function($i, node){ // 复选框点击前回调 + return true; + }, + chooseDone: function(checkbarNodesParam) { //复选框点击事件完毕后,返回该树关于复选框操作的全部信息,用于用户自定义,如未指定则树只是页面上做了修改 + return ; + } + }; + this.iframeDefaultRequest = { //iframe的默认参数,目的是与加载树的参数不一样 + nodeId: "nodeId", //节点ID + parentId: "parentId", //父节点ID + context: "context", //节点内容 + leaf: "leaf", //是否叶子节点 + level: "level", //层级 + spread: "spread", //节点展开状态 + dataType: "dataType", //节点标记 + checked: "checked", //节点复选框选中状态 + initchecked: "initchecked", //节点复选框初始状态 + basicData: "basicData", //用户自定义的记录节点数据 + recordData: "recordData", //当前data数据(排除basicData和children字段) + }; + + this.iframeFun = { + iframeDone: function(iframeParam){ //iframe加载完毕后,用于用户自定义事件 + return ; + } + }; + this.style = { //树最终使用的样式集合 + item: "", //每一项div的样式 + itemThis: "", //选中div的样式 + dfont: "", //一级图标的样式 + icon: "", //二级图标的样式 + cbox: "", //复选框的样式 + chs: "" //复选框选中的样式 + }; + this.usefontStyle = { //树最终使用的图标集合 + fnode:{ //一级节点 + node:{ //非叶子节点 + open:"", //节点展开 + close:"" //节点关闭 + }, + leaf:"" //叶子节点 + }, + snode:{ //二级节点 + node:{ //非叶子节点 + open:"", //节点展开 + close:"" //节点关闭 + }, + leaf:"" //叶子节点 + }, + checkbox:{ //复选框 + on:"", //复选框选中 + out:"", //未选中 + noall:"" //半选 + }, + menubar:{ //菜单栏 + movedown:"", //全部展开 + moveup:"", //全部收缩 + refresh:"", //刷新 + checkAll:"", //全选 + unCheckAll:"", //全不选 + invertAll:"", //反选 + remove:"", //删除 + search:"" //搜索 + }, + menubarExt:"", //扩展菜单栏 + toolbar:{ //工具栏 + menubar:{ //依附在菜单栏的工具栏 + movedown:"", //全部展开 + moveup:"", //全部收缩 + refresh:"", //刷新 + checkAll:"", //全选 + unCheckAll:"", //全不选 + invertAll:"", //反选 + remove:"", //删除 + search:"" //搜索 + }, + menubarExt:"", //依附在菜单栏的扩展菜单栏 + pulldown:"", //展开 + pullup:"", //收缩 + add:"", //添加 + edit:"", //编辑 + del:"" //删除 + }, + toolbarExt:"" //扩展工具栏 + } + + /** 数据绑定**/ + this.node = { // 树节点选中时,包含当前节点的全部信息 + nodeId: "", //节点ID + parentId: "", //父节点ID + context: "", //节点内容 + leaf: "", //是否叶子节点 + level: "", //层级 + spread: "", //节点展开状态 + dataType: "", //节点标记 + checked: "", //节点复选框选中状态 + initchecked: "", //节点复选框初始状态 + basicData: "", //用户自定义的记录节点数据 + recordData: "", //当前data数据(排除basicData和children字段) + }; + + this.toolbarMenu = {}; // 工具栏右键菜单绑定的所有元素 + this.checkbarNode = []; // 复选框标记的全部节点数据 + this.errData = []; // 记录在渲染节点时有问题的数据 + this.checkArrLen = 0; //添加节点的时判断复选框个数 + this.temp = []; // 临时变量 + this.bak = ""; // 临时变量 + this.setting(options); + }; + + /******************** 初始参数加载 ********************/ + // 设置基本参数值 + DTree.prototype.setting = function(options) { + this.options = options || {}; + + /** 绑定元素参数(必填,2个参数项必填一个)**/ + this.elem = this.options.elem || OPTIONS.elem || ""; //树绑定的元素ID:#elem + if(typeof this.options.obj === 'undefined'){ + if(this.elem) { + if($(this.elem).length > 0) { + this.obj = $(this.elem); + } + } + } else { + this.obj = this.options.obj || OPTIONS.obj || this.obj; //树绑定的jquery元素,用于当元素是延迟加载出来的话,可以用这个找到 + this.elem = "#" + this.obj[0].id; + } + + /** 基本参数**/ + this.scroll = this.options.scroll || OPTIONS.scroll || this.elem; //树的上级div容器,让树可以显示滚动条的div容器的ID + this.accordion = (typeof (this.options.accordion) === "boolean") ? this.options.accordion : (typeof (OPTIONS.accordion) === "boolean") ? OPTIONS.accordion : false; //手风琴加载, 默认false + if(this.accordion) { + this.initLevel = 1; //默认展开节点 1节 + } else { + this.initLevel = this.options.initLevel || OPTIONS.initLevel || 2; //默认展开节点 2节 + } + this.type = this.options.type || OPTIONS.type || "load"; //树的加载方式 all,全量树, load,增量树,默认load + this.cache = (typeof (this.options.cache) === "boolean") ? this.options.cache : (typeof (OPTIONS.cache) === "boolean") ? OPTIONS.cache : true; //数据缓存,默认true + this.record = this.options.record || OPTIONS.record || false; //开启数据记录模式,默认false + this.load = (typeof (this.options.load) === "boolean") ? this.options.load : (typeof (OPTIONS.load) === "boolean") ? OPTIONS.load : true; //开启加载动画,默认true + this.none = this.options.none || OPTIONS.nont || "无数据"; //初始加载无记录时显示文字 + this.tempHeight = this.options.height || OPTIONS.height; //临时转换高度变量 + if(this.tempHeight) { // 设置高度 + if(/^full-\d+$/.test(this.tempHeight)) { + this.fullHeightGap = this.tempHeight.split('-')[1]; + this.height = $WIN.height() - this.fullHeightGap; //设置高度 + } else { + this.fullHeightGap = this.tempHeight; + this.height = this.tempHeight; + } + } else { + this.fullHeightGap = ""; + this.height = ""; + } + this.width = this.options.width || OPTIONS.width || "260"; //宽度 + this.obj.css("width", this.width); + + /** 样式相关参数**/ + this.iconfont = this.options.iconfont || OPTIONS.iconfont || DTREEFONT; //默认图标字体 dtreefont + this.iconfontStyle = this.options.iconfontStyle || OPTIONS.iconfontStyle || {}; //用于自定义树的每个关键部位使用的图标 + this.nodeIconArray = $.extend(nodeIconArray, this.options.nodeIconArray || OPTIONS.nodeIconArray) || nodeIconArray; //用户自定义非叶子节点图标集合,node + this.leafIconArray = $.extend(leafIconArray, this.options.leafIconArray || OPTIONS.leafIconArray) || leafIconArray; //用户自定义叶子节点图标集合,leaf + this.skin = this.options.skin || OPTIONS.skin || "theme"; // 自定义样式 + if(this.skin == "layui"){ // layui主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : (typeof (OPTIONS.line) === "boolean") ? OPTIONS.line : true; //开启树线,默认开启 + this.ficon = this.options.ficon || OPTIONS.ficon || "7"; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'7' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; //一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "-1"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else if(this.skin == "laySimple"){ // laySimple主题 + this.line = this.options.line || OPTIONS.line || false; //开启树线,默认不开启 + this.ficon = this.options.ficon || OPTIONS.ficon || ["2","-1"]; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'-1' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "2") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'2' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "-1"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else { // 默认主题 或者自定义主题 + this.line = this.options.line || OPTIONS.line || false; //开启树线,默认不开启 + this.ficon = this.options.ficon || OPTIONS.ficon || "8"; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'8' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "5"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'5' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "0") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'0' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } + + /** 数据加载参数**/ + this.url = this.options.url || OPTIONS.url || ""; //请求地址 + this.async = (typeof (this.options.async) === "boolean") ? this.options.async : (typeof (OPTIONS.async) === "boolean") ? OPTIONS.async : true; //异步同步加载,默认异步加载 + this.headers = this.options.headers || OPTIONS.headers || {}; //ajax header属性 + this.method = this.options.method || OPTIONS.method || "post"; //请求类型 + this.dataType = this.options.dataType || OPTIONS.dataType || "json"; //参数类型 + this.contentType = this.options.contentType || OPTIONS.contentType || "application/x-www-form-urlencoded"; //发送信息至服务器时内容编码类型 + this.defaultRequest = $.extend(this.defaultRequest, this.options.defaultRequest || OPTIONS.defaultRequest) || this.defaultRequest; //默认请求参数 + this.filterRequest = this.options.filterRequest || OPTIONS.filterRequest || []; //过滤请求参数 + this.request = this.options.request || OPTIONS.request || {}; //用户自定义请求参数 + this.response = $.extend(this.response, this.options.response || OPTIONS.response) || this.response; //返回json格式 + this.data = this.options.data || OPTIONS.data || null; //初始化指定该参数,则不会访问异步接口 + this.dataFormat = this.options.dataFormat || OPTIONS.dataFormat || "levelRelationship"; //用于用户配置的data数据格式,list:列表, levelRelationship:层级关系,默认 + this.dataStyle = this.options.dataStyle || OPTIONS.dataStyle || "defaultStyle"; //用于用户配置layui通用的json数据风格,layuiStyle:layui风格,defaultStyle:默认风格 + this.errDataShow = this.options.errDataShow || OPTIONS.errDataShow || false; //是否在递归数据出现错误后,显示错误信息,默认false + this.withCredentials = this.options.withCredentials || OPTIONS.withCredentials || false; //是否允许跨域请求,默认false + this.success = this.options.success || OPTIONS.success || function(data, obj){}; //树加载完毕后执行解析树之前的回调 + this.done = this.options.done || OPTIONS.done || function(data, obj){}; //树加载完毕后的回调 + this.formatter = $.extend(this.formatter, this.options.formatter || OPTIONS.formatter) || this.formatter; //数据过滤 + this.error = this.options.error || OPTIONS.error || function(XMLHttpRequest, textStatus, errorThrown){}; // 异步加载异常回调 + this.complete = this.options.complete || OPTIONS.complete || function(XMLHttpRequest, textStatus){}; // 异步加载完成回调 + + /** 复选框参数**/ + this.checkbar = this.options.checkbar || OPTIONS.checkbar || false; //是否开启复选框模式 + this.checkbarLoad = this.options.checkbarLoad || OPTIONS.checkbarLoad || "node"; //复选框作用范围,node:所有节点, leaf:最后一级;默认所有节点 + this.checkbarType = this.options.checkbarType || OPTIONS.checkbarType || "all"; //复选框选中形式 all:子集选中父级也选中, no-all:子集选中父级半选中,子集全选父级选中,p-casc:父级选中子集全选,子集无法改变父级选中状态, self:没有任何级联关系,only:只能选中一个复选框。 默认all + this.checkbarData = this.options.checkbarData || OPTIONS.checkbarData || "choose"; //复选框记录数据类型形式, change表示记录变更数据,choose表示记录选中数据,all记录全部数据,halfChoose记录选中和半选中的数据,默认choose + this.checkbarFun = $.extend(this.checkbarFun, this.options.checkbarFun || OPTIONS.checkbarFun) || this.checkbarFun; //checkbar事件加载 + + /** 菜单栏参数**/ + this.menubar = this.options.menubar || OPTIONS.menubar || false; //是否打开菜单栏 + this.menubarTips = $.extend(this.menubarTips, this.options.menubarTips || OPTIONS.menubarTips) || this.menubarTips; //菜单栏吸附, toolbar:依附在工具栏,group:依附在按钮组,freedom,自由 + this.menubarFun = $.extend(this.menubarFun, this.options.menubarFun || OPTIONS.menubarFun) || this.menubarFun; //menubar事件加载 + + /** 工具栏参数**/ + this.toolbar = this.options.toolbar || OPTIONS.toolbar || false; //是否开启可编辑模式 + this.toolbarWay = this.options.toolbarWay || OPTIONS.toolbarWay || "contextmenu"; //工具栏显示方式,contextmenu:右键,follow:跟随节点,fixed:固定在节点右侧 + this.toolbarStyle = $.extend(this.toolbarStyle, this.options.toolbarStyle || OPTIONS.toolbarStyle) || this.toolbarStyle; //toolbar的自定义风格,标题,弹框大小 + this.toolbarLoad = this.options.toolbarLoad || OPTIONS.toolbarLoad || "node"; //toolbar作用范围:node:所有节点,noleaf:非最后一级节点,leaf:最后一级 + this.toolbarShow = this.options.toolbarShow || OPTIONS.toolbarShow || ["add","edit","delete"]; //toolbar三个按钮自定义加载 + this.toolbarBtn = this.options.toolbarBtn || OPTIONS.toolbarBtn || null; //toolbar增删改中内容的自定义加载 + this.toolbarExt = this.options.toolbarExt || OPTIONS.toolbarExt || []; //toolbar按钮扩展 + this.toolbarFun = $.extend(this.toolbarFun, this.options.toolbarFun || OPTIONS.toolbarFun) || this.toolbarFun; //toolbar事件加载 + + /** iframe模式参数**/ + this.useIframe = this.options.useIframe || OPTIONS.useIframe || false; //是否加载iframe 默认false, + this.iframeElem = this.options.iframeElem || OPTIONS.iframeElem || ""; //iframe的ID + this.iframeUrl = this.options.iframeUrl || OPTIONS.iframeUrl || ""; //树关联的iframe地址 + this.iframeLoad = this.options.iframeLoad || OPTIONS.iframeLoad || "leaf"; //点击哪一层加载frame: node:所有节点, leaf:默认,最后一级 + this.iframeDefaultRequest = $.extend(this.iframeDefaultRequest, this.options.iframeDefaultRequest || OPTIONS.iframeDefaultRequest) || this.iframeDefaultRequest; //iframe的默认传递参数 + this.iframeRequest = $.extend(this.iframeRequest, this.options.iframeRequest) || $.extend(this.iframeRequest, OPTIONS.iframeRequest) || this.iframeRequest; //iframe的自定义参数 + this.iframeFun = $.extend(this.iframeFun, this.options.iframeFun) || $.extend(this.iframeFun, OPTIONS.iframeFun) || this.iframeFun; //iframe事件加载 + + /** 下拉树模式参数**/ + this.select = this.options.select || false; + if(this.select) { + // 重置下拉树 + this.selectSetting(); + } + + /** 调用确认最终主题方法*/ + this.ensureTheme(); + }; + + // 设置基本参数值 + DTree.prototype.reloadSetting = function(options) { + this.options = $.extend(this.options, options) || this.options; + + /** 绑定元素参数**/ + this.elem = this.options.elem || this.elem; //树绑定的元素ID:#elem + if(typeof this.options.obj === 'undefined'){ + if(this.elem) { + if($(this.elem).length > 0) { + this.obj = $(this.elem); + } + } + } else { + this.obj = this.options.obj || this.obj; //树绑定的jquery元素,用于当元素是延迟加载出来的话,可以用这个找到 + this.elem = "#" + this.obj[0].id; + } + + /** 基本参数**/ + this.scroll = this.options.scroll || this.scroll; //树的上级div容器,让树可以显示滚动条的div容器 + this.accordion = (typeof (this.options.accordion) === "boolean") ? this.options.accordion : this.accordion; //开启手风琴加载 + if(this.accordion) { + this.initLevel = 1; //默认展开节点 1节 + } else { + this.initLevel = this.options.initLevel || this.initLevel; //默认展开节点 2节 + } + this.type = this.options.type || this.type; //树的加载方式 all,全量树, load,增量树,默认load + this.cache = (typeof (this.options.cache) === "boolean") ? this.options.cache : this.cache; //开启数据缓存 + this.record = (typeof (this.options.record) === "boolean") ? this.options.record : this.record; //开启数据记录模式 + this.load = (typeof (this.options.load) === "boolean") ? this.options.load : this.load; //开启加载动画 + this.none = this.options.none || this.none; //初始节点加载无数据时显示文字 + this.tempHeight = this.options.height || this.height; //临时转换高度变量 + if(this.tempHeight) { //设置高度 + if(/^full-\d+$/.test(this.tempHeight)) { + this.fullHeightGap = this.tempHeight.split('-')[1]; + this.height = $WIN.height() - this.fullHeightGap; + } else { + this.fullHeightGap = this.tempHeight; + this.height = this.tempHeight; + } + } + this.width = this.options.width || this.width; //宽度 + this.obj.css("width", this.width); + + /** 样式相关参数**/ + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : this.line; //开启树线,默认不开启 + this.iconfont = this.options.iconfont || this.iconfont; //默认图标字体 dtreefont + this.iconfontStyle = this.options.iconfontStyle || this.iconfontStyle; //用于自定义树的每个关键部位使用的图标 + this.nodeIconArray = $.extend(nodeIconArray, this.options.nodeIconArray) || this.nodeIconArray; //用户自定义非叶子节点图标集合,node + this.leafIconArray = $.extend(leafIconArray, this.options.leafIconArray) || this.leafIconArray; //用户自定义叶子节点图标集合,leaf + this.skin = this.options.skin || this.skin; //自定义样式 + if(this.skin == "layui"){ //layui主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : true; //开启树线,默认开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'7' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; //一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else if(this.skin == "laySimple"){ //laySimple主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : false; //开启树线,默认不开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'-1' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "2") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'2' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1];//一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else { // 默认主题 或者自定义主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : false; //开启树线,默认不开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'8' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'5' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "0") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'0' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } + + /** 数据加载参数**/ + this.url = this.options.url || this.url; //请求地址 + this.async = (typeof (this.options.async) === "boolean") ? this.options.async : this.async; //异步同步加载,默认异步加载 + this.headers = this.options.headers || this.headers; //ajax header属性 + this.method = this.options.method || this.method; //请求类型 + this.dataType = this.options.dataType || this.dataType; //参数类型 + this.contentType = this.options.contentType || this.contentType; //发送信息至服务器时内容编码类型 + this.defaultRequest = $.extend(this.defaultRequest, this.options.defaultRequest) || this.defaultRequest; //默认请求参数 + this.filterRequest = this.options.filterRequest || this.filterRequest; //过滤请求参数 + this.request = this.options.request || this.request; //用户自定义请求参数 + this.response = $.extend(this.response, this.options.response) || this.response; //返回json格式 + this.data = this.options.data || this.data; //初始化指定该参数,则不会访问异步接口 + this.dataFormat = this.options.dataFormat || this.dataFormat; //用于用户配置的data数据格式,list:列表, levelRelationship:层级关系,默认 + this.dataStyle = this.options.dataStyle || this.dataStyle; //用于用户配置layui通用的json数据风格,layuiStyle:layui风格,defaultStyle:默认风格 + this.errDataShow = (typeof (this.options.errDataShow) === "boolean") ? this.options.errDataShow : this.errDataShow; //是否在使用list模式递归数据出现错误时,显示错误信息 + this.withCredentials = (typeof (this.options.withCredentials) === "boolean") ? this.options.withCredentials : this.withCredentials; //是否允许跨域请求 + this.success = this.options.success || this.success; //树加载完毕后执行解析树之前的回调 + this.done = this.options.done || this.done; //树加载完毕后的回调 + this.formatter = $.extend(this.formatter, this.options.formatter)|| this.formatter; //数据过滤 + this.error = this.options.error || this.error; //异步加载异常回调 + this.complete = this.options.complete || this.complete; //异步加载完成回调 + + /** 复选框参数**/ + this.checkbar = this.options.checkbar || this.checkbar; //是否开启复选框模式 + this.checkbarLoad = this.options.checkbarLoad || this.checkbarLoad; //复选框作用范围,node:所有节点, leaf:最后一级;默认所有节点 + this.checkbarType = this.options.checkbarType || this.checkbarType; //复选框选中形式 all:子集选中父级也选中, no-all:子集选中父级半选中,子集全选父级选中,p-casc:父级选中子集全选,子集无法改变父级选中状态, self:没有任何级联关系,only:只能选中一个复选框。 默认all + this.checkbarData = this.options.checkbarData || this.checkbarData; //复选框记录数据类型形式, change表示记录变更数据,choose表示记录选中数据,all记录全部数据,halfChoose记录选中和半选中的数据,默认choose + this.checkbarFun = $.extend(this.checkbarFun, this.options.checkbarFun)|| this.checkbarFun; //checkbar事件加载 + + /** 菜单栏参数**/ + this.menubar = this.options.menubar || this.menubar; //是否打开菜单栏 + this.menubarTips = $.extend(this.menubarTips, this.options.menubarTips) || this.menubarTips; //菜单栏吸附, toolbar:依附在工具栏,group:依附在按钮组,freedom,自由 + this.menubarFun = $.extend(this.menubarFun, this.options.menubarFun) || this.menubarFun; //menubar事件加载 + + /** 工具栏参数**/ + this.toolbar = this.options.toolbar || this.toolbar; //是否开启工具栏 + this.toolbarWay = this.options.toolbarWay || this.toolbarWay; //工具栏显示方式,contextmenu:右键,follow:跟随节点,fixed:固定在节点右侧 + this.toolbarStyle = $.extend(this.toolbarStyle, this.options.toolbarStyle) || this.toolbarStyle; //toolbar的自定义风格,标题,弹框大小 + this.toolbarLoad = this.options.toolbarLoad || this.toolbarLoad; //toolbar作用范围:node:所有节点,noleaf:非最后一级节点,leaf:最后一级 + this.toolbarShow = this.options.toolbarShow || this.toolbarShow; //toolbar三个按钮 + this.toolbarBtn = this.options.toolbarBtn || this.toolbarBtn; //toolbar增删改中内容的自定义加载 + this.toolbarExt = this.options.toolbarExt || this.toolbarExt; //toolbar按钮扩展 + this.toolbarFun = $.extend(this.toolbarFun, this.options.toolbarFun) || this.toolbarFun; //toolbar事件加载 + + /** iframe模式参数**/ + this.useIframe = this.options.useIframe || this.useIframe;//是否加载iframe 默认false + this.iframeElem = this.options.iframeElem || this.iframeElem; //iframe的ID + this.iframeUrl = this.options.iframeUrl || this.iframeUrl; //树关联的iframe地址 + this.iframeLoad = this.options.iframeLoad || this.iframeLoad; //点击哪一层加载frame: node:所有节点, leaf:默认,最后一级 + this.iframeDefaultRequest = $.extend(this.iframeDefaultRequest, this.options.iframeDefaultRequest) || this.iframeDefaultRequest; //iframe的默认传递参数 + this.iframeRequest = $.extend(this.iframeRequest, this.options.iframeRequest) || this.iframeRequest; //iframe的自定义参数 + this.iframeFun = $.extend(this.iframeFun, this.options.iframeFun) || this.iframeFun; //iframe事件加载 + + /** 下拉树模式参数**/ + if(this.select) { + // 重置下拉树 + this.reloadSelectSetting(); + } + + /** 调用确认最终主题方法*/ + this.ensureTheme(); + + }; + + // 设置下拉树的基本参数值 + DTree.prototype.selectSetting = function() { + /** select模式参数*/ + this.select = true; //配置成select模式 + + this.selectInitVal = this.obj.attr("data-value") || this.options.selectInitVal || ""; //输入框的值 + this.selectTreeDiv = this.obj[0].id + "_tree_div"; // 上级DIV节点 + this.selectCardDiv = this.obj[0].id + "_select_card_div"; // 上级layui卡片节点 + this.selectDiv = this.obj[0].id + "_select_div"; // 模拟的select节点 + this.selectTipsName = this.obj[0].id + "_select_input"; // select的提示输入框名称 + this.selectTips = this.options.selectTips || "请选择"; // 输入框的提示语 + this.selectInputName = this.options.selectInputName || {nodeId: this.obj[0].id + "_select_nodeId"}; // select表单中的元素 + + // 调取下拉树的特殊处理页面元素标识 + this.renderSelectDom(); + } + + // 重新设置下拉树的基本参数值 + DTree.prototype.reloadSelectSetting = function() { + + this.selectInitVal = this.obj.attr("data-value") || this.options.selectInitVal || this.selectInitVal; //输入框的值 + this.selectTips = this.options.selectTips || this.selectTips; // 输入框的提示语 + this.selectInputName = $.extend(this.selectInputName, this.options.selectInputName) || this.selectInputName; // select表单中的元素 + + // 调取下拉树的特殊处理页面元素标识 + this.reloadSelectDom(); + } + + /******************** 下拉树设置区域 ********************/ + // 渲染下拉树的Dom结构 + DTree.prototype.renderSelectDom = function() { + var _this = this; + var rootId = _this.obj[0].id; + + // 设置自定义表单隐藏域 + var selectInputName = _this.selectInputName; + var selectInput = []; + for(var key in selectInputName) { + selectInput.push(''); + } + + // 设置html + var prevHtml = ['
                                                                                                      ', + '
                                                                                                      ', selectInput.join(""), + '', + '', + '
                                                                                                      '].join(''); + + _this.obj.before(prevHtml); + + _this.obj.wrap('
                                                                                                      ').wrap('
                                                                                                      ').wrap('
                                                                                                      '); + + } + + // 重新渲染下拉树的Dom结构 + DTree.prototype.reloadSelectDom = function() { + var _this = this; + var rootId = _this.obj[0].id; + + // 设置自定义表单隐藏域 + var selectInputName = _this.selectInputName; + var selectInput = []; + for(var key in selectInputName) { + selectInput.push(''); + } + + $("div[dtree-id='"+rootId+"'][dtree-select='"+_this.selectDiv+"']").find("div.layui-select-title").html(""); + + // 设置html + var prevHtml = [selectInput.join(""), + '', + ''].join(''); + + $("div[dtree-id='"+rootId+"'][dtree-select='"+_this.selectDiv+"']").find("div.layui-select-title").html(prevHtml); + + } + + // 设置输入框的值 + DTree.prototype.selectVal = function(param) { + var _this = this; + var rootId = _this.obj[0].id; + var selectInputName = _this.selectInputName; + var selectTipsNameValue = ""; + var selectValues = {}; + + // 如果开启了复选框,则此方法用来取值 + if(_this.checkbar) { + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "']").each(function(){ + var name = $(this).attr("name"); + var val = $(this).val(); + selectValues[name] = val; + }); + } else { + if(typeof param === 'undefined') { // 不传,则为当前树中记录的ID + param = _this.getNowParam(); + } + if(typeof param === 'string') { // 传递ID,则查询树节点ID对应的值 + param = _this.getParam(param); + } + + selectTipsNameValue = param["context"]; + for(var key in selectInputName) { + selectValues[selectInputName[key]] = param[key]; + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+selectInputName[key]+"']").val(param[key] || ""); + } + + if(param["nodeId"] && !param["context"]) { + selectTipsNameValue = _this.getParam(param["nodeId"]); + } + + // 返显提示输入框值 + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+_this.selectTipsName+"']").val(selectTipsNameValue || ""); + + } + + + // 返回隐藏域中的值 + return selectValues; + } + + // 设置复选框模式中的下拉树的值 + DTree.prototype.selectCheckboxVal = function() { + var _this = this; + var rootId = _this.obj[0].id; + var selectInputName = _this.selectInputName; + + // 获取全部复选框选中节点 + var param = _this.getCheckbarJsonArrParam(); + + selectTipsNameValue = param["context"]; + var selectValues = {}; + for(var key in selectInputName) { + var value = param[key].join(","); + selectValues[selectInputName[key]] = value; + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+selectInputName[key]+"']").val(value); + } + + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+_this.selectTipsName+"']").val(selectTipsNameValue); + + // 返回隐藏域中的值 + return selectValues; + } + + // 重置下拉树的值 + DTree.prototype.selectResetVal = function() { + var _this = this; + var rootId = _this.obj[0].id; + // 表单清空 + $("input[dtree-id='"+rootId+"']").val(""); + // 节点重置 + _this.cancelNavThis(); + if(_this.checkbar) { + // 复选框重置 + _this.cancelCheckedNode(); + } + } + + + /******************** 字体及图标区域 ********************/ + // 确认最终主题 + DTree.prototype.ensureTheme = function(){ + var _this = this; + + // 确认style + this.style.item = DTREE + this.skin + ITEM; + this.style.itemThis = DTREE + this.skin + ITEMTHIS; + this.style.dfont = DTREE + this.skin + DFONT; + this.style.ficon = DTREE + this.skin + FICON; + this.style.icon = DTREE + this.skin + ICON; + this.style.cbox = DTREE + this.skin + CBOX; + this.style.chs = DTREE + this.skin + CHS; + + // 确认usefontStyle + var iconfont = this.iconfont; + var iconfonts = []; + if(typeof iconfont === 'string') { + iconfonts.push(iconfont); + } else { + iconfonts = iconfont; + } + + var iconfontStyle = this.iconfontStyle; + var iconfontStyles = []; + if(iconfontStyle.length == undefined) { + iconfontStyles.push(iconfontStyle); + } else { + iconfontStyles = iconfontStyle; + } + + for(var i=0; i 0) { + $lis.each(function(){ + _this.showLineLi($(this)); + }); + } else { + _this.obj.find("li[data-id]").each(function(){ + _this.showLineLi($(this)); + }); + } + } + } + + // 真正显示树线的方法 + DTree.prototype.showLineLi = function($li){ + var _this = this; + var $div = $li.children("div"), + $nextLi = $li.next("li"), + $ul = $li.parent("ul"); + if($ul[0].id == _this.obj[0].id) { + // 根节点下的节点 + $li.removeClass(LI_NAV_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_FIRST_LINE); + } else { + // 非根节点下的节点 + var $pnextLi = $ul.parent("li").next("li"); + if($pnextLi.length == 0) { + if($nextLi.length == 0){ + $li.removeClass(LI_NAV_LINE); + $li.removeClass(LI_NAV_FIRST_LINE); + $li.addClass(LI_NAV_LAST_LINE); + } else { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_LINE); + } + }else { + var $pnextdiv = $pnextLi.children("div"); + if($nextLi.length == 0 && $div.children("cite").attr("data-leaf") == "leaf" && $pnextdiv.children("cite").attr("data-leaf") == "leaf") { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LINE); + $li.addClass(LI_NAV_LAST_LINE); + } else { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_LINE); + } + } + } + } + + /******************** 初始化数据区域 ********************/ + // 设置高度 + DTree.prototype.autoHeight = function(){ + var _this = this; + var height = _this.height; + if(height != "") { + if(_this.elem == _this.scroll){ + _this.obj.parent().css("height", height + "px"); + } else { + var $toolbarDiv = _this.obj.closest(_this.scroll); + $toolbarDiv.css("height", height + "px"); + } + } + }; + + // 重载树 + DTree.prototype.reload = function(options){ + var _this = this; + _this.reloadSetting(options); + _this.init(); + }; + + // 初始化树 + DTree.prototype.init = function(){ + var _this = this; + if (typeof _this !== "object") { + //_this.obj.html(_this.getNoneDom().errText("树组件未成功加载,请检查配置")); + layer.msg("树组件未成功加载,请检查配置", {icon:5}); + return ; + } + + // 设置组件高度 + _this.autoHeight(); + + if(_this.data) { + if(typeof _this.data.length === 'undefined'){ + //_this.obj.html(_this.getNoneDom().errText("数据解析异常,data数据格式不正确")); + layer.msg("数据解析异常,data数据格式不正确", {icon:5}); + return ; + } + + if(_this.data.length == 0) { + _this.obj.html(_this.getNoneDom().text()); + return ; + } + + //先将ul中的元素清空 + _this.obj.html(""); + + setTimeout(function () { + // 加载完毕后执行树解析前的回调 + _this.success(_this.data, _this.obj); + + // 第一次解析树 + if (_this.dataFormat == 'list'){ + //1.识别根节点ul中的data-id标签,判断顶级父节点 + var pid = _this.obj.attr("data-id"); + //2.构建一个存放节点的树组 + var rootListData = _this.queryListTreeByPid(pid, _this.data); + _this.loadListTree(rootListData, _this.data, 1); + } else { + _this.loadTree(_this.data, 1); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + // 设置复选框的初始值 + if(_this.select){ + _this.selectVal(_this.selectInitVal); + } + + // 保存树副本 + _this.bak = _this.obj.html(); + + // 加载完毕后的回调 + _this.done(_this.data, _this.obj); + }, 100); + } else { + if (!_this.url) { + //_this.obj.html(_this.getNoneDom().errText("数据请求异常,url参数未指定")); + layer.msg("数据请求异常,url参数未指定", {icon:5}); + return ; + } + + //先将ul中的元素清空 + _this.obj.html(""); + + var index = _this.load ? layer.load(1) : ""; + + AjaxHelper.request({ + async: _this.async, + headers: _this.headers, + type: _this.method, + url: _this.url, + dataType: _this.dataType, + contentType: _this.contentType, + withCredentials: _this.withCredentials, + data: _this.getFilterRequestParam(_this.getRequestParam()), + success: function(result) { + if (typeof result === 'string') { + result = $.parseJSON(result); + } + + // 加载完毕后执行树解析前的回调 + _this.success(result, _this.obj); + + var code = ""; + if (_this.dataStyle == 'layuiStyle'){ + code = result[_this.response.statusName]; + } else { + code = result.status[_this.response.statusName]; + } + + if (code == _this.response.statusCode) { + var d = result[_this.response.rootName]; + + if(typeof d.length === 'undefined'){ + _this.obj.html(_this.getNoneDom().errText("数据解析异常,url回调后的数据格式不正确")); + //layer.msg("数据解析异常,url回调后的数据格式不正确", {icon:5}); + return ; + } + + if(d.length == 0) { + _this.obj.html(_this.getNoneDom().text()); + return ; + } + + // 第一次解析树 + if (_this.dataFormat == 'list'){ + //1.识别根节点ul中的data-id标签,判断顶级父节点 + var pid = _this.obj.attr("data-id"); + //2.构建一个存放节点的树组 + var rootListData = _this.queryListTreeByPid(pid, d); + _this.loadListTree(rootListData, d, 1); + } else { + _this.loadTree(d, 1); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + // 设置复选框的初始值 + if(_this.select){ + _this.selectVal(_this.selectInitVal); + } + + // 保存树副本 + _this.bak = _this.obj.html(); + + // 加载完毕后的回调 + _this.done(result, _this.obj); + } else { + // 如果打印不出任何信息说明是在这里,用了错误的数据格式, 或返回码不正确 + if (_this.dataStyle == 'layuiStyle'){ + _this.obj.html(_this.getNoneDom().errText(result[_this.response.message])); + _this.error(null, code, result[_this.response.message]); + //layer.msg(result[_this.response.message], {icon:2}); + } else { + _this.obj.html(_this.getNoneDom().errText(result.status[_this.response.message])); + _this.error(null, code, result.status[_this.response.message]); + //layer.msg(result.status[_this.response.message], {icon:2}); + } + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown){// 异步加载异常回调 + _this.obj.html(_this.getNoneDom().errText(textStatus + ": " + errorThrown)); + _this.error(XMLHttpRequest, textStatus, errorThrown); + }, + complete: function(XMLHttpRequest, textStatus){// 异步加载完成回调 + if(_this.load){layer.close(index);} + _this.complete(XMLHttpRequest, textStatus); + } + }); + } + }; + + // 加载子节点 + DTree.prototype.getChild = function($div, data) { + var _this = this, $ul = $div.next("ul"); + + _this.setNodeParam($div); + + if(typeof data !== 'undefined') { + if(typeof data.length === 'undefined'){ + //_this.obj.html(_this.getNoneDom().errText("数据解析异常,data数据格式不正确")); + layer.msg("数据解析异常,data数据格式不正确", {icon:5}); + return ; + } + + //先将ul中的元素清空 + $ul.html(""); + + // 解析树 + if (_this.dataFormat == 'list'){ + var pid = _this.node.nodeId; + var level = parseInt(_this.node.level)+1; + + var listData = _this.queryListTreeByPid(pid, data); + _this.loadListTree(listData, _this.data, level); + } else { + _this.loadTree(data, level); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + // 保存树副本 + _this.bak = _this.obj.html(); + + } else { + if (!_this.url) { + //_this.obj.html(_this.getNoneDom().errText("数据请求异常,url参数未指定")); + layer.msg("数据请求异常,url参数未指定", {icon:5}); + return ; + } + + $ul.html(""); + var index = _this.load ? layer.load(1) : ""; + AjaxHelper.request({ + async: _this.async, + headers: _this.headers, + type: _this.method, + url: _this.url, + dataType: _this.dataType, + withCredentials: _this.withCredentials, + data: _this.getFilterRequestParam(_this.getRequestParam()), + success: function(result) { + if (typeof result === 'string') { + result = $.parseJSON(result); + } + var code = ""; + if (_this.dataStyle == 'layuiStyle'){ + code = result[_this.response.statusName]; + } else { + code = result.status[_this.response.statusName]; + } + + if (code == _this.response.statusCode) { + // 解析树 + var pid = _this.node.nodeId; + var level = parseInt(_this.node.level)+1; + if (_this.dataFormat == 'list'){ + var pListData = _this.queryListTreeByPid(pid, result[_this.response.rootName]); + _this.loadListTree(pListData, result[_this.response.rootName], level, $ul); + } else { + _this.loadTree(result[_this.response.rootName], level, $ul); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + $ul.addClass(NAV_SHOW); + + // 保存树副本 + _this.bak = _this.obj.html(); + } else { + if (_this.dataStyle == 'layuiStyle'){ + _this.obj.html(_this.getNoneDom().errText(result[_this.response.message])); + _this.error(null, code, result[_this.response.message]); + //layer.msg(result[_this.response.message], {icon:2}); + } else { + _this.obj.html(_this.getNoneDom().errText(result.status[_this.response.message])); + _this.error(null, code, result.status[_this.response.message]); + //layer.msg(result.status[_this.response.message], {icon:2}); + } + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown){// 异步加载异常回调 + _this.obj.html(_this.getNoneDom().errText(textStatus + ": " + errorThrown)); + _this.error(XMLHttpRequest, textStatus, errorThrown); + }, + complete: function(XMLHttpRequest, textStatus){// 异步加载完成回调 + if(_this.load){layer.close(index);} + _this.complete(XMLHttpRequest, textStatus); + } + }); + } + }; + + // 初始化树或者拼接树 + DTree.prototype.loadListTree = function(pListData, listData, level, $ul){ + var _this = this; + $ul = $ul || _this.getNodeDom().nowOrRootUl(); //当前选中的节点或根节点 + if (pListData.length > 0){ + for (var i = 0; i < pListData.length; i++) { + // 1.获取已知节点的全部数据 + var data = pListData[i]; + if(typeof data !== "object") continue; + var parseData = _this.parseData(data); + var childListData = _this.queryListTreeByPid(parseData.treeId(), listData); // 根据已知数据的id判断该条数据是否还有子数据 + + // 3. 页面元素加载数据 + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(childListData.length), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(level), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), ($ul.hasClass(UL_ROOT) ? "root" : "item"))); + // 4.有子数据的元素加载子节点 + if(childListData.length > 0){ + var cLevel = parseInt(level)+1; + _this.loadListTree(childListData, listData, cLevel, _this.obj.find("ul[data-id='"+parseData.treeId()+"']")); + } + } + } + }; + + // 根据父ID查找list数据中匹配的元素 + DTree.prototype.queryListTreeByPid = function(pid, listData){ + var _this = this; + var rootListData = []; + if (listData) { + for (var i = 0; i < listData.length; i++) { + var data = listData[i]; + if(typeof data !== "object") continue; + if(pid == "null" || pid == null){ + if(data[_this.response.parentId] == null) { rootListData.push(data); } + } else { + if (data[_this.response.parentId] == pid){ + if (data[_this.response.treeId] == pid){ + _this.errData.push(data); + } else { + rootListData.push(data); + } + } + } + } + } + return rootListData; + }; + + // 初始化树或者拼接树 + DTree.prototype.loadTree = function(root, level, $ul){ + var _this = this; + if (root) { + $ul = $ul || _this.getNodeDom().nowOrRootUl(); //当前选中的节点或根节点 + for (var i = 0; i < root.length; i++) { // 遍历跟节点或追加的跟节点 + var data = root[i]; + if(typeof data !== "object") continue; + if(data[_this.response.treeId] == data[_this.response.parentId]) { _this.errData.push(data); } + var parseData = _this.parseData(data); + var children = parseData.children(); + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(children.length), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(level), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), ($ul.hasClass(UL_ROOT) ? "root" : "item"))); + if (children.length != 0) { + var cLevel = parseInt(level)+1; + _this.loadTree(children, cLevel, _this.obj.find("ul[data-id='"+parseData.treeId()+"']")); + } + } + } + }; + + // 判断在数据加载时是否存在错误数据,并是否打印错误数据 + DTree.prototype.msgErrData = function() { + var _this = this; + if(_this.errData.length > 0 && _this.errDataShow) { + var title = ""; + for(var i=0; i<_this.errData.length; i++) { + var edata = _this.errData[i]; + title += "数据:【"+edata[_this.response.title]+"】中节点id和上级id值一致! \n"; + } + layer.msg(title, {icon:2,time:5000}); + } + // 显示之后,将错误数据制空 + _this.errData = []; + }; + + // 解析data数据 + DTree.prototype.parseData = function(data) { + var _this = this; + + return { + treeId: function(){ + return data[_this.response.treeId]; + }, + parentId: function(){ + return data[_this.response.parentId]; + }, + fmtTitle: function(){ + if(typeof _this.formatter.title === 'function'){ + var ftitle = _this.formatter.title(data); + var tt = data[_this.response.title]; + tt = (ftitle == "" || ftitle == undefined || ftitle == null) ? tt : ftitle; + return tt || ""; + } + return data[_this.response.title]; + }, + title: function(){ + return data[_this.response.title]; + }, + level: function(){ + return data[_this.response.level] || ""; + }, + ficonClass: function(){ + return data[_this.response.ficonClass] || ""; + }, + iconClass: function(){ + return data[_this.response.iconClass] || ""; + }, + last: function(len){ + return ((len == 0) ? + ((typeof (data[_this.response.last]) === "boolean") ? data[_this.response.last] : true) : + ((typeof (data[_this.response.last]) === "boolean") ? data[_this.response.last] : false)); + }, + spread: function(level){ + return ((level < _this.initLevel) ? + ((typeof (data[_this.response.spread]) === "boolean") ? data[_this.response.spread] : true) : + ((typeof (data[_this.response.spread]) === "boolean") ? data[_this.response.spread] : false)); + }, + disabled: function(){ + return (typeof (data[_this.response.disabled]) === "boolean") ? data[_this.response.disabled] : false; + }, + hide: function(){ + return (typeof (data[_this.response.hide]) === "boolean") ? data[_this.response.hide] : false; + }, + checkArr: function(){ + var checkArr = []; + var checkArrData = data[_this.response.checkArr]; + if(typeof checkArrData === 'string'){ + if(checkArrData.indexOf("{") > -1 && checkArrData.indexOf("}") > -1){ + checkArrData = JSON.parse(checkArrData); + } else { + checkArrData = {"type":"0","checked":checkArrData}; + } + } + if(typeof checkArrData === 'object'){ + if(typeof checkArrData.length === 'undefined'){ + checkArr.push(checkArrData); + } else { + checkArr = checkArrData; + } + } + + if(checkArr.length > 0 && checkArr.length > _this.checkArrLen){ + _this.checkArrLen = checkArr.length; // 获取复选框个数 + } + return checkArr; + + }, + children: function(){ + return data[_this.response.childName] || []; + }, + basicData: function(){ + return event.escape(JSON.stringify(data[_this.response.basicData])) || JSON.stringify({}); + }, + recordData: function(){ + var recordData = _this.record ? event.cloneObj(data, [_this.response.treeId, + _this.response.parentId, + _this.response.title, + _this.response.iconClass, + _this.response.childName, + _this.response.last, + _this.response.spread, + _this.response.disabled, + _this.response.hide, + _this.response.checkArr, + _this.response.checked, + _this.response.type, + _this.response.basicData]) : {}; + + return event.escape(JSON.stringify(recordData)); + }, + data: function(){ + return data; + } + } + + }; + + //当无节点数据时显示dom + DTree.prototype.getNoneDom = function(){ + var _this = this, + rootId = _this.obj[0].id, + noneTitle = _this.none; + + return { + text: function(){ + return "
                                                                                                      "+noneTitle+"
                                                                                                      "; + }, + errText: function(errInfo){ + return "
                                                                                                      "+errInfo+"
                                                                                                      "; + } + } + }; + + //新增节点的dom值 + DTree.prototype.getDom = function(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide) { + var _this = this, + rootId = _this.obj[0].id, + toolbar = _this.toolbar, + checkbar = _this.checkbar; + + return { + fnode: function() { // + - 图标 + // 获取图标的变量 + var fnodeIcon = _this.fnodeIcon, + fleafIcon = _this.fleafIcon; + + var fleafIconLeaf = _this.usefontStyle.fnode.leaf, + fnodeIconOpen = _this.usefontStyle.fnode.node.open, + fnodeIconClose = _this.usefontStyle.fnode.node.close; + + if(ficonClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + fleafIconLeaf = iconfont + " " + ficonClass; + fnodeIconOpen = iconfont + " " + ficonClass; + fnodeIconClose = iconfont + " " + ficonClass; + } else { + fleafIconLeaf = iconfont[0] + " " + ficonClass; + fnodeIconOpen = iconfont[0] + " " + ficonClass; + fnodeIconClose = iconfont[0] + " " + ficonClass; + } + } + + if(fnodeIcon != "-1" && fleafIcon != "-1"){ // 都加载 + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon != "-1" && fleafIcon == "-1"){ // 加载node 隐藏leaf + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon == "-1" && fleafIcon != "-1"){ // 隐藏node 加载leaf + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon == "-1" && fleafIcon == "-1"){ // 都隐藏 + return last ? "" : + (spread ? "" : ""); + } + }, + node: function() { // 二级图标样式 + // 获取图标的变量 + var nodeIcon = _this.nodeIcon, + leafIcon = _this.leafIcon; + + var sleafIconLeaf = _this.usefontStyle.snode.leaf, + snodeIconOpen = _this.usefontStyle.snode.node.open, + snodeIconClose = _this.usefontStyle.snode.node.close; + if(iconClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + sleafIconLeaf = iconfont + " " + iconClass; + snodeIconOpen = iconfont + " " + iconClass; + snodeIconClose = iconfont + " " + iconClass; + } else { + sleafIconLeaf = iconfont[0] + " " + iconClass; + snodeIconOpen = iconfont[0] + " " + iconClass; + snodeIconClose = iconfont[0] + " " + iconClass; + } + } + + if(nodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + return last ? "" : + (spread ? "" : ""); + } + }, + checkbox: function() { // 复选框 + var flag = false; + if(_this.checkbarLoad == "node"){if (checkbar) {flag = true;}} else {if (last) {if (checkbar) {flag = true;}}} + + if(flag){ + var result = "
                                                                                                      "; + if(checkArr && checkArr.length > 0){ + + for (var i = 0; i < checkArr.length; i++) { + var checkData = checkArr[i]; + var checked = checkData.checked; + var CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + if (checked == "2") { //半选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.noall + " " + _this.style.chs; + } else if (checked == "1") { //选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.on + " " + _this.style.chs; + } else { //未选择或者无值 + CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + } + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + result += ""; + } + } + result += "
                                                                                                      "; + return result; + } + + return ""; + }, + text: function() { // 文字显示 + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + return ""+fmtTitle+""; + }, + ul: function() { //子节点ul + return last ? "
                                                                                                        " : + (spread ? "
                                                                                                          " : "
                                                                                                            "); + } + }; + }; + + //替换节点的dom值,或指定值 + DTree.prototype.replaceDom = function($div, treeId, last, spread, disabled, hide) { + var _this = this, + rootId = _this.obj[0].id, + toolbar = _this.toolbar, + checkbar = _this.checkbar; + + return { + fnode: function(ficonClass) { // + - 图标 + var fnode = ""; + + // 获取图标的变量 + var fnodeIcon = _this.fnodeIcon, + fleafIcon = _this.fleafIcon; + + var fleafIconLeaf = _this.usefontStyle.fnode.leaf, + fnodeIconOpen = _this.usefontStyle.fnode.node.open, + fnodeIconClose = _this.usefontStyle.fnode.node.close; + + if(ficonClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + fleafIconLeaf = iconfont + " " + ficonClass; + fnodeIconOpen = iconfont + " " + ficonClass; + fnodeIconClose = iconfont + " " + ficonClass; + } else { + fleafIconLeaf = iconfont[0] + " " + ficonClass; + fnodeIconOpen = iconfont[0] + " " + ficonClass; + fnodeIconClose = iconfont[0] + " " + ficonClass; + } + } + + if(fnodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + fnode = last ? "" : + (spread ? "" : ""); + } + if(fnode != ""){_this.getNodeDom($div).fnode().replaceWith($(fnode));} + }, + node: function(iconClass) { // 二级图标样式 + var snode = ""; + + // 获取图标的变量 + var nodeIcon = _this.nodeIcon, + leafIcon = _this.leafIcon; + + var sleafIconLeaf = _this.usefontStyle.snode.leaf, + snodeIconOpen = _this.usefontStyle.snode.node.open, + snodeIconClose = _this.usefontStyle.snode.node.close; + if(iconClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + sleafIconLeaf = iconfont + " " + iconClass; + snodeIconOpen = iconfont + " " + iconClass; + snodeIconClose = iconfont + " " + iconClass; + } else { + sleafIconLeaf = iconfont[0] + " " + iconClass; + snodeIconOpen = iconfont[0] + " " + iconClass; + snodeIconClose = iconfont[0] + " " + iconClass; + } + } + + if(nodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + snode = last ? "" : + (spread ? "" : ""); + } + if(snode != ""){_this.getNodeDom($div).snode().replaceWith($(snode));} + }, + checkbox: function(checkArr) { // 复选框 + var flag = false; + if(_this.checkbarLoad == "node"){if (checkbar) {flag = true;}} else {if (last) {if (checkbar) {flag = true;}}} + + if(flag){ + var result = "
                                                                                                            "; + if(checkArr && checkArr.length > 0){ + + for (var i = 0; i < checkArr.length; i++) { + var checkData = checkArr[i]; + var checked = checkData.checked; + var CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + if (checked == "2") { //半选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.noall + " " + _this.style.chs; + } else if (checked == "1") { //选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.on + " " + _this.style.chs; + } else { //未选择或者无值 + CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + } + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + result += ""; + } + } + result += "
                                                                                                            "; + _this.getNodeDom($div).snode().next("div").replaceWith($(result)); + } + }, + text: function(title) { // 文字显示 + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + var cite = ""+title+"" + _this.getNodeDom($div).cite().replaceWith($(cite)); + }, + ul: function() { //子节点ul + var ul = last ? "
                                                                                                              " : + (spread ? "
                                                                                                                " : "
                                                                                                                  "); + _this.getNodeDom($div).nextUl().replaceWith($(ul)); + }, + div: function(){ + $div.attr("data-id", treeId); + }, + basicData: function(basicData){ + basicData = (basicData == "{}") ? "" : basicData; + $div.attr("data-basic", basicData); + }, + recordData: function(recordData){ + recordData = (recordData == "{}") ? "" : recordData; + $div.attr("data-record", recordData); + }, + p_li: function(pId){ + var $li = $div.parent("li"); + $li.attr("data-id", treeId); + if(pId) { + $li.attr("data-pid", pId); + } + return $li; + } + }; + + }; + + // 获取拼接好的li + DTree.prototype.getLiItemDom = function(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide, basicData, recordData, flag) { + var _this = this, + rootId = _this.obj[0].id; + + var dom = _this.getDom(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide); + basicData = (basicData == "{}") ? "" : basicData; + recordData = (recordData == "{}") ? "" : recordData; + var div = "
                                                                                                                  " + + div , + dom.fnode(), + dom.node(), + dom.checkbox(), + dom.text(), + "
                                                                                                                  ", dom.ul(), ""].join(""); + + return li; + }; + + // 初始化节点,用于数据回显 + DTree.prototype.dataInit = function(chooseId){ + var _this = this; + var $div = _this.obj.find("div[data-id='"+chooseId+"']"); + _this.getNodeDom($div).parentLi().find("."+NAV_THIS).removeClass(NAV_THIS); + _this.getNodeDom($div).parentLi().find("."+_this.style.itemThis).removeClass(_this.style.itemThis); + $div.addClass(NAV_THIS); + $div.addClass(_this.style.itemThis); + _this.setNodeParam($div); + // 将该节点的父节点全部展开 + var $li_parents = $div.parents("."+LI_NAV_ITEM); + $li_parents.children("ul").addClass(NAV_SHOW); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.fnode.node.close)).addClass(_this.usefontStyle.fnode.node.open); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.fnode.node.close)).removeClass(_this.usefontStyle.fnode.node.close); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.snode.node.close)).addClass(_this.usefontStyle.snode.node.open); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.snode.node.close)).removeClass(_this.usefontStyle.snode.node.close); + return _this.getNowParam(); + }; + + // 基于备份的Html数据回滚 + DTree.prototype.rollbackHtml = function(chooseId){ + var _this = this; + if(_this.bak) { + _this.obj.html(_this.bak); + // 取消全部选中状态 + _this.cancelNavThis(); + if(_this.checkbar) { + _this.cancelCheckedNode(); + _this.chooseDataInit(chooseId); + } else { + _this.dataInit(chooseId); + } + + _this.bak = _this.obj.html(); + } + }; + + + /******************** 基础事件区域 ********************/ + // 数据格式化 + DTree.prototype.escape = function(html){ + return event.escape(html); + }; + + // 格式化数据转回正常数据 + DTree.prototype.unescape = function(str){ + return event.unescape(str); + }; + + // 取消选中div + DTree.prototype.cancelNavThis = function(){ + var _this = this; + _this.obj.find("div[data-id]").parent().find("."+NAV_THIS).removeClass(NAV_THIS); + _this.obj.find("div[data-id]").parent().find("."+_this.style.itemThis).removeClass(_this.style.itemThis); + } + + // 选中div + DTree.prototype.navThis = function(id){ + var _this = this; + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null) { + _this.cancelNavThis(); + $div.addClass(NAV_THIS); + $div.addClass(_this.style.itemThis); + } + } + + // 手风琴模式操作其他节点 + DTree.prototype.accordionUL = function($ul) { + var _this = this; + if(_this.accordion) { + $ul.closest("li[data-index]").siblings("li[data-index]").children("ul[data-id]").removeClass(NAV_SHOW); + var $divs = $ul.closest("li[data-index]").siblings("li[data-index]").children("ul[data-id]").prev("div"); + if($divs.length && $divs.length > 0) { + for (var i=0; i<$divs.length; i++) { + var $div = $($divs[i]); + var $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(); + if($i_spread.attr("data-spread") != 'last'){ + _this.operateIcon($i_spread, $i_node).close(); + } + } + } + + } + }; + + // 展开或隐藏节点 作用点: div + DTree.prototype.clickSpread = function($div) { + var _this = this; + var $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + $ul = $div.next("ul"); + + if ($ul.length > 0) { + if (spread == "close") { + if (_this.type=="load") { //增加加载 + if (_this.cache) { //开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + _this.accordionUL($ul); + } else { //加载节点 + _this.getChild($div); + _this.accordionUL($ul); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + _this.accordionUL($ul); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + _this.accordionUL($ul); + } + _this.operateIcon($i_spread, $i_node).open(); + } else if (spread == "open") { + $ul.removeClass(NAV_SHOW); + _this.operateIcon($i_spread, $i_node).close(); + } + } + }; + + // 设置节点为disabled + DTree.prototype.setDisabledNodes = function(disabledIds){ + var _this = this; + var disabledId = disabledIds.split(","); + for (var i=0; i 0) { + _this.getChild($div, data); + } else { + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var level = parseInt($div.parent("li").attr("data-index"))+1; + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(0), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), "item")); + + // 建造完毕后,选中该DIV + $thisDiv = $ul.find("div[data-id='"+parseData.treeId()+"']"); + _this.setNodeParam($thisDiv); + + _this.showLine($ul.find("li")); + } else { + layer.msg("添加失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } + } else { + _this.getChild($div); + } + } + + // 局部刷新树--编辑当前节点选中节点时 + DTree.prototype.partialRefreshEdit = function($div, data){ + var _this = this; + $ul = $div.next("ul"), + $p_li = $div.parent("li"); + + if(data) { + if(typeof data === 'object') { + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var replaceDom = _this.replaceDom($div, parseData.treeId(), parseData.last(0), parseData.spread(), parseData.disabled(), parseData.hide()); + replaceDom.div(); + replaceDom.node(parseData.iconClass()); + replaceDom.checkbox(parseData.checkArr()); + replaceDom.text(parseData.title()); + replaceDom.ul(); + replaceDom.basicData(parseData.basicData()); + replaceDom.recordData(parseData.recordData()); + + var parentId = parseData.parentId(); + var oldParentId = $p_li.attr("data-pid"); + if(parentId && parentId != oldParentId) { + // 变更了父节点 + $p_li = replaceDom.p_li(parentId); + + // 根据parentId找到下挂节点的ul + var $goto_div = _this.getNodeDom(parentId).div(), + $goto_ul = _this.getNodeDom(parentId).nextUl(); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($goto_ul.children("li").length == 0){ + var $icon_i = $goto_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).openWithLeaf(); + $goto_ul.addClass(NAV_SHOW); + } + $goto_ul.append($p_li); + } else { + replaceDom.p_li(); + } + _this.setNodeParam($div); + } else { + layer.msg("编辑失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } else { + _this.getNodeDom($div).cite().html(data); + } + } + } + + // 局部刷新树--当前节点选中被删除时 + DTree.prototype.partialRefreshDel = function($div){ + var _this = this; + $p_li = $div.parent("li"); + $p_ul = _this.getNodeDom($div).parentUl(); + $p_div = _this.getNodeDom($div).parentDiv(); + + $p_li.remove(); + _this.showLine($p_ul.find("li")); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($p_ul.children("li").length == 0){ + var $icon_i = $p_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).closeWithLeaf(); + } + _this.initNodeParam(); + } + + /******************** 复选框区域 ********************/ + // 初始化复选框的值 + DTree.prototype.chooseDataInit = function(chooseIds){ + var _this = this; + var chooseId = chooseIds.split(","); + for (var i=0; i."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + if (flag == 0) { + //把父级去掉选中 + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($item_i).noCheck(); + } + } + } else { + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + //把父级选中 + _this.checkStatus($item_i).check(); + } + } + }; + + //实现复选框点击, no-all 子集选中父级半选中,子集全选父级选中 + DTree.prototype.checkAllOrNoallOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag == 0) { + //把父级去掉选中 + _this.checkStatus($item_i).noCheck(); + } else { + //把父级半选 + _this.checkStatus($item_i).noallCheck(); + } + } + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag1 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var flag2 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag1 != flag2) { + // 父级复选框半选 + _this.checkStatus($item_i).noallCheck(); + } else { + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + }; + + //实现复选框点击,p-casc:父级选中子集全选,子集无法改变父级选中状态 + DTree.prototype.checkAllOrPcascOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + } + }; + + //实现复选框点击,self:各自选中互不影响 + DTree.prototype.checkOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + } + }; + + //实现复选框点击,only:只能选中1个复选框 + DTree.prototype.checkOnly = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + var checked = $i.attr("data-checked"); + // 将全部节点全部设为未选中状态 + var $all_i = _this.obj.find("i[data-checked]"); + _this.checkStatus($all_i).noCheck(); + + if (checked != "1") { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + } + }; + + //实现复选框点击 + DTree.prototype.changeCheck = function($i) { + var _this = this; + var temp = _this.temp; + if(typeof $i === 'undefined') { + $i = temp[0]; + } + // 复选框选中事件 + if (_this.checkbarType == "all") { + _this.checkAllOrNot($i); + } else if(_this.checkbarType == "no-all") { + _this.checkAllOrNoallOrNot($i); + } else if(_this.checkbarType == "p-casc") { + _this.checkAllOrPcascOrNot($i); + } else if(_this.checkbarType == "self") { + _this.checkOrNot($i); + } else if(_this.checkbarType == "only") { + _this.checkOnly($i); + } else { + _this.checkAllOrNot($i); + } + + if(_this.select) { + // 设置复选框模式中的下拉树的值 + _this.selectCheckboxVal(); + } + + // 获取复选框选中节点的内容 + var checkbarNodes = _this.setAndGetCheckbarNodesParam(true); + + // 用户自定义想做的事情 + _this.checkbarFun.chooseDone(checkbarNodes); + layui.event.call(this, MOD_NAME, "chooseDone("+$(_this.obj)[0].id+")", {"checkbarParams": checkbarNodes}); + _this.temp = []; + }; + + //复选框半选状态初始化设置 + DTree.prototype.initNoAllCheck = function(){ + var _this = this; + //1.获取所有选中节点 + var $is = _this.obj.find("i[data-checked='1']"); + if($is.length > 0){ + for ( var key = 0; key < $is.length; key++) { + var $i = $($is[key]), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag1 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var flag2 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag1 != flag2) { + // 父级复选框半选 + _this.checkStatus($item_i).noallCheck(); + } else { + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + } + }; + + //复选框选中状态初始化设置 + DTree.prototype.initAllCheck = function(){ + var _this = this; + //1.获取所有选中节点 + var $is = _this.obj.find("i[data-checked='1']"); + if($is.length > 0){ + for ( var key = 0; key < $is.length; key++) { + var $i = $($is[key]), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + }; + + // 设置复选框选中/未选中/半选 _this.checkStatus($i).check(); _this.checkStatus($i).noCheck(); _this.checkStatus($i).noallCheck(); + DTree.prototype.checkStatus = function($i) { + var _this = this; + return { + check: function(){ + $i.removeClass(_this.usefontStyle.checkbox.out); + $i.removeClass(_this.usefontStyle.checkbox.noall); + $i.addClass(_this.usefontStyle.checkbox.on); + $i.addClass(_this.style.chs); + $i.attr("data-checked","1"); + }, + noCheck: function(){ + $i.removeClass(_this.usefontStyle.checkbox.noall); + $i.removeClass(_this.usefontStyle.checkbox.on); + $i.removeClass(_this.style.chs); + $i.addClass(_this.usefontStyle.checkbox.out); + $i.attr("data-checked","0"); + }, + noallCheck: function(){ + $i.removeClass(_this.usefontStyle.checkbox.out); + $i.removeClass(_this.usefontStyle.checkbox.on); + $i.addClass(_this.usefontStyle.checkbox.noall); + $i.addClass(_this.style.chs); + $i.attr("data-checked","2"); + } + } + }; + + // 设置树的复选框操作值的全部参数,并获取 + DTree.prototype.setAndGetCheckbarNodesParam = function(requestParamFlag) { + var _this = this; + //操作前先清空 + _this.checkbarNode = []; + // 选择所有复选框节点 + if (_this.checkbarData == "change"){ //记录变更数据 + _this.obj.find("i[data-par][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if ($i.attr("data-checked") != $i.attr("data-initchecked")) { + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + } + }); + } else if (_this.checkbarData == "all"){ //记录全部数据 + _this.obj.find("i[data-par][data-checked][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } else if (_this.checkbarData == "choose"){ //记录选中数据 + _this.obj.find("i[data-par][data-checked='1'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } else if (_this.checkbarData == "halfChoose"){ //记录选中和半选数据 + _this.obj.find("i[data-par][data-checked='1'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + _this.obj.find("i[data-par][data-checked='2'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } + return _this.checkbarNode; + }; + + // 获取树的复选框操作值的全部参数 + DTree.prototype.getCheckbarNodesParam = function() { + var _this = this; + return _this.setAndGetCheckbarNodesParam(true); + }; + + // 获取树的一个复选框的参数 + DTree.prototype.getCheckbarNodeParam = function($div, $i){ + var _this = this; + var temp_node = {}; + temp_node.nodeId = $div.attr("data-id"); + temp_node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + temp_node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + temp_node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + temp_node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + temp_node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + temp_node.basicData = basicData; + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + temp_node.recordData = recordData; + + temp_node.dataType = $i.attr("data-type"); + temp_node.checked = $i.attr("data-checked"); + temp_node.initchecked = $i.attr("data-initchecked"); + return temp_node; + }; + + // 获取基于返回参数的树的复选框参数 + DTree.prototype.getCheckbarJsonArrParam = function(){ + var _this = this; + var checkbarJsonArr = { + nodeId: [], //节点ID + parentId: [], //父节点ID + context: [], //节点内容 + leaf: [], //是否叶子节点 + level: [], //层级 + spread: [], //节点展开状态 + dataType: [], //节点标记 + checked: [], //节点复选框选中状态 + initchecked: [], //节点复选框初始状态 + basicData: [], //用户自定义的记录节点数据 + recordData: [], //当前data数据(排除basicData和children字段) + }; + // 获取全部复选框选中节点 + var params = _this.setAndGetCheckbarNodesParam(false); + if(params && params.length > 0) { + for(var i=0; i 0) { _this.checkStatus($i).check(); } + } + + //取消全部复选框选中 + DTree.prototype.cancelCheckedNode = function(nodeId){ + var _this = this; + var $i = _this.obj.find("i[data-par][data-checked!='0']"); + if($i.length > 0) { _this.checkStatus($i).noCheck(); } + } + + //反选复选框 + DTree.prototype.invertCheckedNode = function(nodeId){ + var _this = this; + if(_this.obj.find("i[data-par]").length > 0) { + var b = false; + _this.obj.find("i[data-par]").each(function(){ + var $i = $(this); + if($i.attr("data-checked") == '2'){ + b = true; + }else if($i.attr("data-checked") == '0') { + _this.checkStatus($i).check(); + }else if($i.attr("data-checked") == '1') { + _this.checkStatus($i).noCheck(); + } + }); + + if(b) { + _this.initNoAllCheck(); + } else { + _this.initAllCheck(); + } + } + } + + //删除选中节点 + DTree.prototype.removeCheckedNode = function(nodeId){ + var _this = this; + var len = _this.obj.find("i[data-par][data-checked='1']").length; + if(len == 0){ + layer.msg("请至少选中一个节点",{icon:2}); + }else{ + //操作前先清空 + _this.checkbarNode = []; + // 选择所有复选框节点 + var i_node = {}; + _this.obj.find("i[data-par][data-checked='1']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + }); + + layer.confirm('确定要删除选中节点?', {icon: 3, title:'删除选中节点'}, function(index1){ + var flag = _this.menubarFun.remove(_this.checkbarNode); + if(flag){ + _this.obj.find("i[data-par][data-checked='1']").closest("."+LI_DIV_ITEM).next("ul").remove(); + _this.obj.find("i[data-par][data-checked='1']").closest("."+LI_DIV_ITEM).remove(); + _this.checkbarNode=[]; + } + + layer.close(index1); + }); + } + } + + /******************** 工具栏及菜单栏区域 ********************/ + // 初始化菜单栏和工具栏的div + DTree.prototype.initTreePlus = function(){ + var _this = this; + // 初始化菜单栏和工具栏的div + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).remove(); + _this.toolbarMenu = {}; + if(_this.menubar && _this.menubarTips.group && _this.menubarTips.group.length > 0) _this.obj.before("
                                                                                                                  "); + if(_this.toolbar){ + if(_this.toolbarWay == "contextmenu") { + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).remove(); + _this.obj.before("
                                                                                                                  "); + } + } + + }; + + // 开启工具栏和菜单栏 + DTree.prototype.openTreePlus = function(){ + var _this = this; + // 先对工具栏做处理,因为菜单栏可能会与工具栏产生关联。 + var ggMenu = []; + if(_this.toolbar) _this.getToolbarDom(); + + if(_this.menubar) { + var menubarTips = _this.menubarTips, + mtbar = menubarTips.toolbar, + group = menubarTips.group, + freedom = menubarTips.freedom; + if(mtbar && mtbar.length > 0){ + // 菜单栏吸附工具栏上 + for(var i=0; i 0){ + // 菜单栏吸附在上方的按钮组div中 + for(var i=0; i"; + break; + case defaultMenu.moveUp: + gg = ""; + break; + case defaultMenu.refresh: + gg = ""; + break; + case defaultMenu.checkAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.unCheckAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.invertAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.remove: + gg = (_this.checkbar) ? "" : ""; + break; + case defaultMenu.searchNode: + gg = ""; + break; + } + return gg; + }; + + // 获取扩展菜单栏 + DTree.prototype.getExtMenubarDom = function(menu){ + var _this = this; + return ""; + }; + + // 获取依附在工具栏的菜单栏 + DTree.prototype.getMenubarToolDom = function(menu){ + var _this = this; + var rootId = _this.obj[0].id; + switch (menu) { + case defaultMenu.moveDown: + _this.toolbarMenu[defaultMenu.moveDown] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.moveDown, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.movedown, "展开全部"); + break; + case defaultMenu.moveUp: + _this.toolbarMenu[defaultMenu.moveUp] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.moveUp, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.moveup, "收缩全部"); + break; + case defaultMenu.refresh: + _this.toolbarMenu[defaultMenu.refresh] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.refresh, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.refresh, "刷新"); + break; + case defaultMenu.checkAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.checkAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.checkAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.checkAll, "全选节点"); + break; + case defaultMenu.unCheckAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.unCheckAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.unCheckAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.unCheckAll, "全不选节点"); + break; + case defaultMenu.invertAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.invertAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.invertAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.invertAll, "反选节点"); + break; + case defaultMenu.remove: + if(_this.checkbar) + _this.toolbarMenu[defaultMenu.remove] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.remove, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.remove, "删除选中"); + break; + case defaultMenu.searchNode: + _this.toolbarMenu[defaultMenu.searchNode] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.searchNode, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.searchNode, "查询"); + break; + } + }; + + // 获取依附在工具栏的扩展菜单栏 + DTree.prototype.getExtMenubarToolDom = function(menu){ + var _this = this; + _this.toolbarMenu[menu.menubarId] = _this.setToolbarDom().setMenuToolbarOption(menu.menubarId, menu.title, _this.usefontStyle.toolbar.menubarExt+" "+menu.icon, ""); + }; + + // menubar内置方法 + DTree.prototype.menubarMethod = function(){ + var _this = this; + return { + openAllNode: function(obj){ // 展开所有节点 + var $ulNode = obj || _this.obj.children("li").children("ul"); + // 遍历所有ul子节点 + for (var i = 0; i < $ulNode.length; i++) { + // 获取当前节点的信息 + var $ul = $($ulNode[i]), + $div = $ul.prev("div"), + $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + if (leaf == "leaf") { continue; } // 说明是叶子了,则继续循环下一个 + + if (spread == "open") { + // 说明该节点已经展开了,则进行子节点循环 + } else { + if (_this.type=="load") { //是否全量加载 + if (_this.cache) { //是否开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + } else { //加载节点 + _this.getChild($div); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + } + _this.operateIcon($i_spread, $i_node).open(); + + } + var $childUl = $ul.children("li").children("ul"); + _this.menubarMethod().openAllNode($childUl); + } + }, + closeAllNode: function(){ //收缩所有节点 + _this.obj.find("."+LI_NAV_CHILD).each(function(){ + // 获取当前节点的信息 + var $ul = $(this), + $div = $ul.prev("div"), + $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + $ul.removeClass(NAV_SHOW); + _this.operateIcon($i_spread, $i_node).close(); + }); + }, + refreshTree: function(){// 刷新树 + _this.refreshTree(); + }, + checkAll: function(){ // 全选节点 + _this.checkAllNode(); + }, + unCheckAll: function(){ // 全不选节点 + _this.cancelCheckedNode(); + }, + invertAll: function(){ // 反选节点 + _this.invertCheckedNode(); + }, + remove: function(){// 删除选中节点 + _this.removeCheckedNode(); + }, + searchNode: function(){//模糊查询该值,展开该值节点 + layer.prompt({ + formType: 0, + value: "", + title: '查询节点' + }, function(value, index1, elem){ + if (value) { + var flag = _this.searchNode(value); + if (!flag) { + layer.msg("该名称节点不存在!", {icon:5}); + } + } else { + layer.msg("未指定查询节点名称", {icon:5}); + } + layer.close(index1); + }); + }, + extMethod: function(menuId, $div, flag){ + if(_this.menubar && _this.menubarTips.group && _this.menubarTips.group.length > 0 && flag == "group"){ + for(var i=0; i<_this.menubarTips.group.length; i++){ + var ext = _this.menubarTips.group[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + if(_this.menubar && _this.menubarTips.toolbar && _this.menubarTips.toolbar.length > 0 && flag == "toolbar"){ + for(var i=0; i<_this.menubarTips.toolbar.length; i++){ + var ext = _this.menubarTips.toolbar[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + if(_this.menubar && _this.menubarTips.freedom && _this.menubarTips.freedom.length > 0 && flag == "freedom"){ + for(var i=0; i<_this.menubarTips.freedom.length; i++){ + var ext = _this.menubarTips.freedom[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + } + }; + }; + + // menubar监听方法 + DTree.prototype.menubarListener = function(menuId, flag){ + var _this = this; + var $div = _this.getNodeDom().nowDiv(); + switch (menuId) { + case defaultMenu.moveDown: // 展开全部节点 + _this.menubarMethod().openAllNode(); + break; + case defaultMenu.moveUp: // 收缩全部节点 + _this.menubarMethod().closeAllNode(); + break; + case defaultMenu.refresh: + _this.menubarMethod().refreshTree(); // 刷新树 + break; + case defaultMenu.checkAll: + _this.menubarMethod().checkAll(); + break; + case defaultMenu.unCheckAll: + _this.menubarMethod().unCheckAll(); + break; + case defaultMenu.invertAll: + _this.menubarMethod().invertAll(); + break; + case defaultMenu.remove: + _this.menubarMethod().remove(); + break; + case defaultMenu.searchNode: + _this.menubarMethod().searchNode(); + break; + default: + _this.menubarMethod().extMethod(menuId, $div, flag); + break; + } + }; + + //模糊查询该值,展开该值节点 + DTree.prototype.searchNode = function(value){ + var _this = this; + var b = false; + var $lis = []; + _this.obj.find("cite[data-leaf]").each(function(){ + var $nthis = $(this); + var html = $nthis.html(); + if(html.indexOf(value) > -1){ + if($nthis.attr("data-leaf") == "leaf") { + // 叶子节点提供包含父节点的所有信息 + var title = ""; + $nthis.parents("li").each(function(){ + title = "-" + $(this).find("cite[data-leaf]").html() + title; + }); + title = title.substring(1, title.length); + $nthis.attr("title", title); + } + // 保存当前cite所在的li及父li中包含该值,则只保留父的 + var i = 0; + $nthis.parents("li").each(function(){ + var html2 = $(this).find("cite[data-leaf]").html(); + if(html2.indexOf(value) > -1){ + i++; + } + if(i >= 2){ + return true; + } + }); + if (i < 2){ + $lis.push($nthis.closest("li").prop("outerHTML")); + } + } + }); + if($lis.length > 0) { + b = true; + // 1.将树节点清空 + _this.obj.html(""); + // 2.遍历所有cite节点,展开当前cite节点 + for(var i=0; i<$lis.length; i++){ + _this.obj.append($lis[i]); + } + } + return b; + }; + + + /******************** 工具栏区域 ********************/ + // 获取工具栏 + DTree.prototype.getToolbarDom = function(){ + var _this = this; + var toolbarShow = _this.toolbarShow, + toolbarExt = _this.toolbarExt, + toolbarWay = _this.toolbarWay; + + if(toolbarShow.length > 0){ + for(var i=0; i 0){ + for(var i=0; i "+other +title+""; + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + return ""; + } + }, + setMenuToolbarOption: function(menubarId, title, classId, other){ + var rootId = _this.obj[0].id; + if(toolbarWay == "contextmenu") { + return "
                                                                                                                   "+other +title+"
                                                                                                                  "; + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + return ""; + } + }, + setToolbarPlace: function(toolbarMenu){ + if(toolbarWay == "contextmenu") { + if(toolbarMenu){ + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).find('div.layui-nav-item>dl.layui-nav-child').html(""); + for(var key in toolbarMenu){ + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).find('div.layui-nav-item>dl.layui-nav-child').append(toolbarMenu[key]); + } + } + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + _this.obj.find("cite[data-leaf][dtree-disabled='false']").each(function(){ + var $cite = $(this); + _this.dynamicToolbarDom($cite); + }); + } + } + } + }; + + // 在节点后动态绑定fixed和follow条件的工具栏 + DTree.prototype.dynamicToolbarDom = function($cite){ + var _this = this; + var toolbarWay = _this.toolbarWay; + if($cite.next("em."+TOOLBAR_TOOL_EM).length == 0) { + var $div = $cite.parent("div"); + var param = _this.getRequestParam(_this.getTempNodeParam($div)); + var toolbarMenus = _this.toolbarFun.loadToolbarBefore(event.cloneObj(_this.toolbarMenu), param, $div); + var hideCls = (toolbarWay == "follow") ? NAV_HIDE : ""; + var em = [""]; + if(toolbarMenus){ + for(var key in toolbarMenus){ + em.push(toolbarMenus[key]); + } + } + em.push(""); + $cite.after(em.join('')); + } + } + + // 隐藏toolbar + DTree.prototype.toolbarHide = function() { + var _this = this; + if(_this.toolbar && _this.toolbarWay == "contextmenu") { + var $toolBarDiv = _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id); + $toolBarDiv.find(".layui-nav-child").removeClass('layui-anim-fadein layui-show'); + } + } + + // toolbar内置方法 + DTree.prototype.toolbarMethod = function(){ + var _this = this; + return { + pulldown: function(obj){ // 展开当前点击节点的下面全部节点 + if(!obj) return; + var $ulNode = obj; + // 遍历所有ul子节点 + for (var i = 0; i < $ulNode.length; i++) { + // 获取当前节点的信息 + var $ul = $($ulNode[i]), + $div = $ul.prev("div"), + $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + if (leaf == "leaf") { continue; } // 说明是叶子了,则继续循环下一个 + + if (spread == "open") { + // 说明该节点已经展开了,则进行子节点循环 + } else { + if (_this.type=="load") { //是否全量加载 + if (_this.cache) { //是否开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + } else { //加载节点 + _this.getChild($div); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + } + _this.operateIcon($i_spread, $i_node).open(); + + } + var $childUl = $ul.children("li").children("ul"); + _this.toolbarMethod().pulldown($childUl); + } + }, + pullup: function($li){ // 收缩当前点击节点的下面全部节点 + $li.find("."+LI_NAV_CHILD).each(function(){ + // 获取当前节点的信息 + var $ul = $(this), + $div = $ul.prev("div"), + $i_spread = _this.getNodeDom($div).fnode(), + $i_node = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_spread.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + $ul.removeClass(NAV_SHOW); + _this.operateIcon($i_spread, $i_node).close(); + }); + } + } + }; + + // toolbar监听方法 + DTree.prototype.toolbarListener = function(tool, $div) { + var _this = this; + var $cite = $div.children("cite[data-leaf]"), + $ul = $div.next("ul"), + $p_li = $div.parent("li[data-index]"), //当前选中节点的顶级li节点 + $p_ul = $p_li.parent("ul"), //当前选中节点的顶级li节点的父级ul + $p_div = $p_ul.prev("div"), //当前选中节点的顶级li节点的父级ul的前一个div + title = $cite.html(); + switch (tool) { + case defaultTool.pulldown: + _this.toolbarMethod().pulldown($ul); + break; + case defaultTool.pullup: + _this.toolbarMethod().pullup($p_li); + break; + case defaultTool.addTool: + var content = _this.loadToolBar(title, defaultTool.addTool); + + layer.open({ + title: "新增"+_this.toolbarStyle.title, + type: 1, + area: _this.toolbarStyle.area, + content: content, + success: function(layero, index){ + form.render(); + form.on("submit(dtree_addNode_form)",function(data){ + var data = data.field; + var parentId = $div.attr("data-id"), + id = $div.attr("data-id")+"_node_"+$ul[0].childNodes.length, + leaf = true, + checked = "0", + level = parseInt($p_li.attr("data-index"))+1; + + // 创建子节点的DOM,添加子节点 + var checkArr = []; + if (_this.checkArrLen > 0) { + for (var i = 0; i < _this.checkArrLen; i++) { + checkArr.push({"type":i,"checked":"0"}); + } + } + + $ul.append(_this.getLiItemDom(id, parentId, data.addNodeName, data.addNodeName, true, "", "", checkArr, level, false, false, false, "", "", "item")); + // 先将li节点隐藏 + $ul.find("li[data-id='"+id+"']").hide(); + // 重新赋值 + var $addDiv = $ul.find("div[data-id='"+id+"']"); + node = _this.getNodeParam($addDiv); + + //获取组装后的requestNode,组合参数 + var requestNode = _this.getRequestParam(node); + requestNode = $.extend(requestNode, data); + + _this.temp = [id, $ul, $div, level]; + // 用户自定义想做的事情 + _this.toolbarFun.addTreeNode(requestNode, $div); + + layer.close(index); + return false; + }); + } + }); + break; + case defaultTool.editTool: + var content = _this.loadToolBar(title, defaultTool.editTool); + + layer.open({ + title: "编辑"+_this.toolbarStyle.title, + type: 1, + area: _this.toolbarStyle.area, + content: content, + success: function(layero, index){ + _this.toolbarFun.editTreeLoad(_this.getRequestParam(_this.getNodeParam($div))); + form.render(); + form.on("submit(dtree_editNode_form)",function(data){ + var data = data.field; + $cite.html(data.editNodeName); + node = _this.getNodeParam($div); + var requestNode = _this.getRequestParam(node); + requestNode = $.extend(requestNode, data); + _this.temp = [$cite, $div, title, $p_div]; + _this.toolbarFun.editTreeNode(requestNode, $div); + + layer.close(index); + }); + } + }); + break; + case defaultTool.delTool: + layer.confirm('确定要删除该'+_this.toolbarStyle.title+'?', {icon: 3, title:'删除'+_this.toolbarStyle.title}, function(index){ + var node = _this.getNodeParam($div); + _this.temp = [$p_li, $p_div]; + _this.toolbarFun.delTreeNode(_this.getRequestParam(_this.getNodeParam($div)), $div); + + layer.close(index); + }); + break; + default: + if(_this.toolbarExt.length > 0){ + for(var i=0; i<_this.toolbarExt.length; i++){ + var ext = _this.toolbarExt[i]; + if (tool == ext.toolbarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div)), $div); + break; + } + } + } + break; + } + } + + + // 加载toolBar中的内容 + DTree.prototype.loadToolBar = function(title, name){ + var _this = this; + var toolbarShow = _this.toolbarShow; + var nodeBarContents = _this.toolbarBtn; + + var html = ""; + switch (name) { + case defaultTool.addTool: + var addNodeBarDef = [{"label": "当前选中", "name": "nodeTitle", "type": "text", "value": title, "defElem": "nowChoose", "readonly": true}, + {"label": "新增"+_this.toolbarStyle.title, "name": "addNodeName", "type": "text", "value": "", "defElem": "nowChange", "verify": "required"}, + {"type": "submit", "value": "确认添加", "defElem": "btn", "filter": "dtree_addNode_form"}]; + + //2. 用户自定义的节点内容 + var addNodeBar = ['
                                                                                                                  ']; + + if(nodeBarContents != null && nodeBarContents.length > 0){ + if(nodeBarContents[0] != null && nodeBarContents[0] != undefined && nodeBarContents[0].length > 0){ + var addNodeBarContents = nodeBarContents[0]; + // 1. 检查是否包含了now、newly、btn这三个默认项,将其他元素依次排列,将特殊元素至于栈顶 + for(var i=0; i', '
                                                                                                                  ']; + // 3.遍历生成按钮 + for(var j=0; j
                                                                                                                  '); + addNodeBar.push(addBtn.join('')); + addNodeBar.push('
                                                                                                                  '); + html = addNodeBar.join(''); + break; + + case defaultTool.editTool: + var editNodeBarDef = [{"label": "当前选中", "name": "nodeTitle", "type": "text", "value": title, "defElem": "nowChoose", "readonly": true}, + {"label": "编辑"+_this.toolbarStyle.title, "name": "editNodeName", "type": "text", "value": "", "defElem": "nowChange", "verify": "required"}, + {"type": "submit", "value": "确认编辑", "defElem": "btn", "filter": "dtree_editNode_form"}]; + + var editNodeBar = ['
                                                                                                                  ']; + //2. 用户自定义的节点内容 + if(nodeBarContents != null && nodeBarContents.length > 0){ + + if(nodeBarContents[1] != null && nodeBarContents[1] != undefined && nodeBarContents[1].length > 0){ + var editNodeBarContents = nodeBarContents[1]; + // 1. 检查是否包含了now、newly、btn这三个默认项,将其他元素依次排列,将特殊元素至于栈顶 + for(var i=0; i', '
                                                                                                                  ']; + // 3.遍历生成按钮 + for(var j=0; j
                                                                                                                  '); + editNodeBar.push(editBtn.join('')); + editNodeBar.push('
                                                                                                                  '); + html = editNodeBar.join(''); + break; + } + return html; + }; + + // 获取toolbar详细的标签信息 + DTree.prototype.loadToolBarDetail = function(nodeBarContents){ + var _this = this; + var readonly = (typeof (nodeBarContents.readonly) === "boolean") ? nodeBarContents.readonly : false; + var disabled = (typeof (nodeBarContents.disabled) === "boolean") ? nodeBarContents.disabled : false; + var id = nodeBarContents.id ? nodeBarContents.id : ""; + var name = nodeBarContents.name ? nodeBarContents.name : ""; + var val = nodeBarContents.value ? nodeBarContents.value : ""; + var verify = nodeBarContents.verify ? nodeBarContents.verify : ""; + var placeholder = nodeBarContents.placeholder ? nodeBarContents.placeholder : val; + return{ + text: function(){ + return ['
                                                                                                                  ', + '', + '
                                                                                                                  ', + '', + '
                                                                                                                  ', + '
                                                                                                                  '].join(''); + }, + textarea: function(){ + return ['
                                                                                                                  ', + '', + '
                                                                                                                  ', + '', + '
                                                                                                                  ', + '
                                                                                                                  '].join(''); + }, + hidden: function(){ + return [''].join(''); + }, + select: function(){ + var optionsData = (typeof nodeBarContents.optionsData === 'object') ? nodeBarContents.optionsData : nodeBarContents.optionsData(); + var options = ""; + for(var key in optionsData){ + if(val == optionsData[key]){ + options += ""; + } else { + options += ""; + } + } + return ['
                                                                                                                  ', + '', + '
                                                                                                                  ', + '', '
                                                                                                                  ', '
                                                                                                                  '].join(''); + }, + submit: function(){ + var filter = nodeBarContents.filter; + return [''].join(''); + }, + button: function(){ + return [''].join(''); + }, + reset: function(){ + return [''].join(''); + } + } + }; + + // 新增节点后改变节点内容 + DTree.prototype.changeTreeNodeAdd = function(returnID){ + var _this = this; + var temp = _this.temp; + var id = temp[0], $ul = temp[1], $div = temp[2], level = temp[3]; + var flag = false; + if(returnID){ + var $thisDiv = _this.obj.find("[data-id='"+id+"']"); + if(typeof returnID === "object"){ + // 如果是JSON格式数据,则将当前DIV删除,重新建造DIV + $thisDiv.remove(); + var parseData = _this.parseData(returnID); + + if(parseData.treeId()){ + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(0), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), "item")); + + // 建造完毕后,选中该DIV + $thisDiv = $ul.find("div[data-id='"+parseData.treeId()+"']"); + _this.setNodeParam($thisDiv) + } else { + layer.msg("添加失败,节点ID为undefined!",{icon:5}); + // 将li节点删除 + $ul.find("li[data-id='"+id+"']").remove(); + // 重新赋值 + _this.setNodeParam($div); + // 临时变量制空 + _this.temp = []; + return ; + } + }else if(returnID == 'refresh'){ + // 如果是设置为refresh参数,则向后台发送请求,获取新增节点下的真实参数,局部刷新树。 + flag = true; + } else if(typeof returnID === "string" || typeof returnID === 'number' || returnID == true){ + $thisDiv.attr("data-id", returnID); + // 将li节点展示 + $ul.find("li[data-id='"+returnID+"']").show(); + _this.setNodeParam($thisDiv) + } + + // 判断当前点击的节点是否是最后一级节点,如果是,则需要修改节点的样式 + var $icon_i = $div.find("i[data-spread]"); + if ($icon_i.eq(0).attr("data-spread") == "last") { + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).openWithLeaf(); + } else { //如果不是,也要修改节点样式 + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).open(); + } + $ul.addClass(NAV_SHOW); //展开UL + _this.accordionUL($ul); + if(flag) { + _this.getChild($div); + } else { + // _this.showLine(); + _this.showLine($ul.find("li")); + // 这种情况下需要在新增节点后对节点新增工具栏 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.dynamicToolbarDom($thisDiv.find("cite[data-leaf]")); + } + } + + } else { + // 将li节点删除 + $ul.find("li[data-id='"+id+"']").remove(); + // 重新赋值 + _this.setNodeParam($div); + } + + _this.temp = []; // 临时变量制空 + + }; + + // 编辑页打开后显示编辑页内容 + DTree.prototype.changeTreeNodeDone = function(param){ + var _this = this; + form.val('dtree_editNode_form', param); + form.render(); + }; + + // 修改节点后改变节点内容 + DTree.prototype.changeTreeNodeEdit = function(returnID){ + var _this = this; + var temp = _this.temp; + var $cite = temp[0], $div = temp[1], title = temp[2], $p_div = temp[3]; + var flag = false; + if(returnID){ + if(typeof returnID === "object"){ + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var replaceDom = _this.replaceDom($div, parseData.treeId(), parseData.last(0), parseData.spread(), parseData.disabled(), parseData.hide()); + replaceDom.node(parseData.iconClass()); + replaceDom.checkbox(parseData.checkArr()); + replaceDom.text(parseData.title()); + replaceDom.ul(); + replaceDom.basicData(parseData.basicData()); + replaceDom.recordData(parseData.recordData()); + _this.setNodeParam($div); + } else { + layer.msg("编辑失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } + } else { + $cite.html(title); + _this.getNodeParam($div); + } + + _this.temp = []; // 临时变量制空 + }; + + // 删除节点后改变节点内容 + DTree.prototype.changeTreeNodeDel = function(flag){ + var _this = this; + var temp = _this.temp; + var $p_li = temp[0], + $p_ul = $p_li.parent("ul"), + $p_div = temp[1]; + + if(flag){ + $p_li.remove(); + _this.showLine($p_ul.find("li")); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($p_ul.children("li").length == 0){ + var $icon_i = $p_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).closeWithLeaf(); + } + _this.initNodeParam(); + } + + _this.temp = []; // 临时变量制空 + }; + + /******************** iframe区域 ********************/ + // 加载iframe + DTree.prototype.loadIframe = function($div, iframeParam) { + var _this = this; + var $cite = _this.getNodeDom($div).cite(); + if (!_this.useIframe) { // 启用iframe + return false; + } + var iframeElem = _this.iframeElem, + iframeUrl = _this.iframeUrl, + iframeLoad = _this.iframeLoad; + + var flag = iframeLoad == "leaf" ? (($cite.attr("data-leaf") == "leaf") ? true : false) : true; + + if (flag) { + if ($(iframeElem).length > 0) { //iframe存在 + if (!iframeUrl) { + layer.msg("数据请求异常,iframeUrl参数未指定", {icon:5}); + return false; + } + var param = AjaxHelper.serialize(iframeParam); + if(iframeUrl.indexOf("?")> -1){ + param = "&"+param.substring(1, param.length); + } + var url = iframeUrl + param; + $(iframeElem).attr("src", url); + } else { + layer.msg("iframe绑定异常,请确认页面中是否有iframe页对应的容器", {icon:5}); + return false; + } + } + return flag; + }; + + // 获取传递出去的参数,根据iframe.iframeDefaultRequest、iframe.iframeRequest和node拼出发出请求的参数 + DTree.prototype.getIframeRequestParam = function(nodes){ + var _this = this; + var request = _this.iframeRequest, + defaultRequestNames = _this.iframeDefaultRequest, + node = nodes || _this.node, + requestParam = {}; + + // 先拼用户自定义的,在拼树生成的,这样的话用户可以自定义当树未生成时的节点的初始值 + for ( var key in request) { + requestParam[key] = request[key]; + } + for ( var key in defaultRequestNames) { + var paramName = defaultRequestNames[key]; + var paramValue = node[key]; + if(typeof paramValue === "boolean"){ + requestParam[paramName] = paramValue; + }else { + if(paramValue){ + requestParam[paramName] = paramValue; + } + } + } + + // 解决传递中文的乱码问题 + var reg = /[\u4E00-\u9FA5\uF900-\uFA2D]/; //正则匹配中文 + for(var key in requestParam){ + if(reg.test(requestParam[key])) { + var str = requestParam[key]; + requestParam[key] = encodeURI(encodeURI(str)); + } + } + + return requestParam; + }; + + /******************** 数据回调区域 ********************/ + // 根据具体的id获取基于当前id的div以及对应的其他dom元素 + DTree.prototype.getNodeDom = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + return { + div: function(){ // 获取当前div + return $div; + }, + fnode: function(){ // 获取一级图标元素 + return ($div == null) ? null : $div.find("i[data-spread]").eq(0); + }, + snode: function(){ // 获取二级图标元素 + return ($div == null) ? null : $div.find("i[data-spread]").eq(1); + }, + checkbox: function(){ // 获取复选框元素 + return ($div == null) ? null : $div.find("i[data-par]"); + }, + cite: function(){ // 获取cite元素 + return ($div == null) ? null : $div.find("cite[data-leaf]"); + }, + nextUl: function(){ // 获取相邻的ul元素 + return ($div == null) ? null : $div.next("ul"); + }, + parentLi: function(){ // 获取父级li元素 + return ($div == null) ? null : $div.parent("li"); + }, + parentUl: function(){ // 获取基于当前$div的上级$ul + return ($div == null) ? null : $div.parent("li").parent("ul"); + }, + parentDiv: function(){ // 获取基于当前$div的上级$div + return ($div == null) ? null : $div.parent("li").parent("ul").prev("div"); + }, + nowDiv: function(){ // 获取当前选中节点,没有则返回null + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS); + }, + nowOrRootDiv: function(){ // 获取当前选中节点,没有则返回根节点下的第一个div + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? _this.obj.children("li").eq(0).children("div").eq(0) : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS); + }, + nowOrRootUl: function(){ // 获取当前选中节点下一个UL 或根节点。为了将新节点放入ul下 + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? _this.obj : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).next("ul"); + } + } + }; + + // 获取当前选中节点下一个UL 或根节点。为了将新节点放入ul下 + DTree.prototype.getNowNodeUl = function() { + var _this = this; + return _this.getNodeDom().nowOrRootUl(); + }; + + // 获取当前选中节点 或第一个根节点。 + DTree.prototype.getNowNode = function() { + var _this = this; + return _this.getNodeDom().nowOrRootDiv(); + }; + + // 获取当前选中节点 无则返回null。 + DTree.prototype.getNowNodeOrNull = function() { + var _this = this; + return _this.getNodeDom().nowDiv(); + }; + + // 获取指定节点。 + DTree.prototype.getNode = function(id) { + var _this = this; + return _this.getNodeDom(id).div(); + }; + + // 设置当前选中节点的全部参数 + DTree.prototype.setNodeParam = function($div) { + var _this = this; + _this.node.nodeId = $div.attr("data-id"); + _this.node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + _this.node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + _this.node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + _this.node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + _this.node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + _this.node.basicData = basicData; + + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + _this.node.recordData = recordData; + + if (_this.getNodeDom($div).checkbox()) { + var dataTypes = "", checkeds = "", initcheckeds = ""; + _this.getNodeDom($div).checkbox().each(function(){ + dataTypes += $(this).attr("data-type") + ","; + checkeds += $(this).attr("data-checked") + ","; + initcheckeds += $(this).attr("data-initchecked") + ","; + }); + dataTypes = dataTypes.substring(0, dataTypes.length-1); + checkeds = checkeds.substring(0, checkeds.length-1); + initcheckeds = initcheckeds.substring(0, initcheckeds.length-1); + + _this.node.dataType = dataTypes; + _this.node.checked = checkeds; + _this.node.initchecked = initcheckeds; + } + }; + + // 获取当前选中节点的全部参数 + DTree.prototype.getNodeParam = function($div) { + var _this = this; + if ($div) { + _this.setNodeParam($div); + } else { + if(_this.obj.find("div[data-id]").parent().find("."+NAV_THIS).length == 0){ + _this.initNodeParam(); + } + } + return this.node; + }; + + // 获取一个临时的node参数 + DTree.prototype.getTempNodeParam = function($div) { + var _this = this; + var temp_node = {}; + temp_node.nodeId = $div.attr("data-id"); + temp_node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + temp_node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + temp_node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + temp_node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + temp_node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + temp_node.basicData = basicData; + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + temp_node.recordData = recordData; + + if (_this.getNodeDom($div).checkbox()) { + var dataTypes = "", checkeds = "", initcheckeds = ""; + _this.getNodeDom($div).checkbox().each(function(){ + dataTypes += $(this).attr("data-type") + ","; + checkeds += $(this).attr("data-checked") + ","; + initcheckeds += $(this).attr("data-initchecked") + ","; + }); + dataTypes = dataTypes.substring(0, dataTypes.length-1); + checkeds = checkeds.substring(0, checkeds.length-1); + initcheckeds = initcheckeds.substring(0, initcheckeds.length-1); + + temp_node.dataType = dataTypes; + temp_node.checked = checkeds; + temp_node.initchecked = initcheckeds; + } + return temp_node; + }; + + // 重置参数 + DTree.prototype.initNodeParam = function(){ + var _this = this; + _this.node.nodeId = ""; + _this.node.parentId = ""; + _this.node.context = ""; + _this.node.leaf = ""; + _this.node.level = ""; + _this.node.spread = ""; + _this.node.dataType = ""; + _this.node.checked = ""; + _this.node.initchecked = ""; + _this.node.basicData = ""; + _this.node.recordData = ""; + + if(_this.select) { + _this.selectResetVal(); + } + }; + + // 获取传递出去的参数,根据defaultRequest、request和node拼出发出请求的参数 + DTree.prototype.getRequestParam = function(nodes){ + var _this = this; + var request = _this.request, + defaultRequestNames = _this.defaultRequest, + node = nodes || _this.node, + requestParam = {}; + + // 先拼用户自定义的,在拼树生成的,这样的话用户可以自定义当树未生成时的节点的初始值 + for ( var key in request) { + requestParam[key] = request[key]; + } + for ( var key in defaultRequestNames) { + var paramName = defaultRequestNames[key]; + var paramValue = node[key]; + if(typeof paramValue === "boolean"){ + requestParam[paramName] = paramValue; + }else { + if(paramValue){ + requestParam[paramName] = paramValue; + } + } + + } + return requestParam; + }; + + // 获取filterParam过滤后的requestParam + DTree.prototype.getFilterRequestParam = function(requestParam){ + var _this = this; + var filterRequest = _this.filterRequest; + return event.cloneObj(requestParam, filterRequest); + }; + + // 获取当前选中值 + DTree.prototype.getNowParam = function(){ + var _this = this; + + return _this.getRequestParam(_this.getNodeParam()); + }; + + // 获取指定节点选中值 + DTree.prototype.getParam = function(id){ + var _this = this; + + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null){ return _this.callbackData().node(_this.getTempNodeParam($div)); } else { return {}; } + }; + + // 获取参数的上级节点 + DTree.prototype.getParentParam = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null){ return _this.callbackData().parentNode($div); } else { return {}; } + }; + + // 获取参数的全部上级节点 + DTree.prototype.getAllParentParam = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + var arr = []; + if($div != null){ + var level = _this.getTempNodeParam($div).level; + for(var i=1; i 0){ + $childDivs.each(function(){ + var $cDiv = $(this); + childNode.push(_this.getRequestParam(_this.getTempNodeParam($cDiv))); + }); + } + return childNode; + }, + parentNode: function($div){ // 获取上级节点值 + var pId = _this.getNodeDom($div).parentLi().attr("data-pid"); + var $pdiv = _this.obj.find("div[data-id='"+pId+"']"); + if($pdiv.length > 0) {return _this.getRequestParam(_this.getTempNodeParam($pdiv));} else {return {};} + + } + } + }; + + /******************** 事件回调区域 ********************/ + // 绑定浏览器事件 + DTree.prototype.bindBrowserEvent = function(){ + var _this = this; + var rootId = _this.obj[0].id; + + // 绑定文件夹展开/收缩的图标的点击事件,点击时给当前节点的div添加选中class + _this.obj.on("click", "i[data-spread]", function(event) { + event.stopPropagation(); + var $i = $(this), + $div = $i.parent("div"), + node = _this.getNodeParam($div); + + _this.toolbarHide(); + _this.navThis($div); + _this.clickSpread($div); // 展开或隐藏节点 + + // 树状态改变后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "changeTree("+$(_this.obj)[0].id+")", { + dom: _this.callbackData().dom($i), + param: _this.callbackData().node(node), + show: _this.callbackData().dom($i).attr("data-spread") == "open" ? true : false + }); + }); + + // 绑定所有子节点div的单击事件,点击时触发加载iframe或用户自定义想做的事情 + _this.obj.on("click", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event) { + event.stopPropagation(); + var $div = $(this), + $cite = $div.find("cite"), + node = _this.getNodeParam($div); + _this.toolbarHide(); + _this.navThis($div); + + if(_this.select) { + _this.selectVal(node.nodeId); + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").click(); + } + + if (_this.useIframe) { + var iframeParam = _this.getFilterRequestParam(_this.getIframeRequestParam(node)); + var flag = _this.loadIframe($div, iframeParam); // 加载iframe + if (flag) { + // iframe加载完毕后,用户自定义想做的事情 + _this.iframeFun.iframeDone(iframeParam); + + layui.event.call(this, MOD_NAME, "iframeDone("+$(_this.obj)[0].id+")", { + "iframeParam": iframeParam, + dom: _this.callbackData().dom($div) + }); + } + } else { + // 单击事件执行完毕后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "node("+$(_this.obj)[0].id+")", { + param: _this.callbackData().node(node), + childParams: _this.callbackData().childNode($div), + parentParam: _this.callbackData().parentNode($div), + dom: _this.callbackData().dom($div) + }); + } + }); + + // 绑定所有子节点div的双击事件,暴露on给用户自定义 + _this.obj.on("dblclick", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event) { + event.stopPropagation(); + var $div = $(this), + $cite = $div.find("cite"), + node = _this.getNodeParam($div); + _this.toolbarHide(); + _this.navThis($div); + + if(_this.select) { + _this.selectVal(node.nodeId); + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").click(); + } + + // 双击事件执行完毕后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "nodedblclick("+$(_this.obj)[0].id+")", { + param: _this.callbackData().node(node), + childParams: _this.callbackData().childNode($div), + parentParam: _this.callbackData().parentNode($div), + dom: _this.callbackData().dom($div) + }); + }); + + if(_this.checkbar) { + // 绑定cheboxbar的节点复选框 + _this.obj.on("click", "i[dtree-click='"+eventName.checkNodeClick+"'][dtree-disabled='false']", function(event) { + _this.toolbarHide(); + var $i = $(this), + $div = $i.closest("div[dtree-click='"+eventName.itemNodeClick+"']"), + node = _this.getNodeParam($div); + // 复选框选中前的回调 + var flag = _this.checkbarFun.chooseBefore($i, _this.getRequestParam(node)); + _this.temp = [$i]; + if(flag){_this.changeCheck();} + + event.stopPropagation(); + }); + } + + if(_this.menubar) { + // 绑定menubar的点击事件 + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).on("click", "button[d-menu]", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("d-menu"), "group"); + }); + + // 绑定menubar的点击事件 + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).on("click", "a[d-menu]", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("d-menu"), "toolbar"); + }); + + // 绑定menubar的点击按钮事件 + _this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").on("click", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("dtree-menu"), "freedom"); + }); + } + + if(_this.toolbar) { + if(_this.toolbarWay == "contextmenu") { + //绑定所有子节点div的右键点击事件,用于显示toolbar + _this.obj.on("contextmenu", "div[dtree-click='"+eventName.itemNodeClick+"'][d-contextmenu='true'][dtree-disabled='false']", function(e){ + var $div = $(this), + node = _this.getNodeParam($div); + + _this.toolbarHide(); + // toolbar加载前执行的方法,执行完毕之后创建按钮 + _this.setToolbarDom().setToolbarPlace(_this.toolbarFun.loadToolbarBefore(event.cloneObj(_this.toolbarMenu), _this.getRequestParam(node), $div)); + + var e = e || window.event, + mx = e.pageX - $div.offset().left +45 , + my = $div.offset().top - _this.obj.closest(_this.scroll).offset().top +15; + + _this.navThis($div); + var $toolBarDiv = _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id); + $toolBarDiv.find(".layui-nav-child").addClass('layui-anim-fadein layui-show'); + $toolBarDiv.css({'left':mx+'px','top':my+'px'}); + + e.stopPropagation(); + return false; + }); + + // 绑定装载树的上层出现滚动条的容器,让toolbar隐藏 + _this.obj.closest(_this.scroll).scroll(function() { + _this.toolbarHide(); + }); + + // 绑定toolbar的点击事件 + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $div = _this.getNodeDom().nowOrRootDiv(), + node = _this.getNodeParam($div); + _this.toolbarHide(); + var tool = $(this).attr("dtree-tool"); + _this.toolbarListener(tool, $div); + }); + } else if(_this.toolbarWay == "fixed") { + // 绑定toolbar的点击事件 + _this.obj.on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $a = $(this), + $cite = $a.parent("em."+TOOLBAR_TOOL_EM).prev("cite"), //当前选中节点的text + $div = $cite.parent("div"), + node = _this.getNodeParam($div); + var tool = $a.attr("dtree-tool"); + + _this.toolbarHide(); + _this.navThis($div); + _this.toolbarListener(tool, $div); + }); + } else if(_this.toolbarWay == "follow") { + //绑定所有子节点div的mouseover mouseout事件,用于显示或隐藏toolbar + _this.obj.on("mouseover mouseout", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event){ + var $div = $(this), + $toolBarEm = $div.children("em."+TOOLBAR_TOOL_EM); + if(event.type == "mouseover"){ + $toolBarEm.removeClass(NAV_HIDE); + event.stopPropagation(); + } else if(event.type == "mouseout"){ + $toolBarEm.addClass(NAV_HIDE); + event.stopPropagation(); + } + }); + + // 绑定toolbar的点击事件 + _this.obj.on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $a = $(this), + $cite = $a.parent("em."+TOOLBAR_TOOL_EM).prev("cite"), //当前选中节点的text + $div = $cite.parent("div"), + node = _this.getNodeParam($div); + var tool = $a.attr("dtree-tool"); + + _this.toolbarHide(); + _this.navThis($div); + _this.toolbarListener(tool, $div); + }); + } + } + + if(_this.select) { + // 绑定select的点击事件 + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").on("click", function(event){ + event.stopPropagation(); + $(this).toggleClass("layui-form-selected"); + $("div[dtree-id='" + rootId + "'][dtree-card='"+_this.selectCardDiv+"']").toggleClass("dtree-select-show layui-anim layui-anim-upbit"); + + // 下拉树面板开闭状态改变后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "changeSelect("+$(_this.obj)[0].id+")", { + show: $(this).hasClass("layui-form-selected"), + param: _this.selectVal() + }); + }); + + } + }; + + // 绑定body的单击,让本页面所有的toolbar隐藏 + $BODY.on("click", function(event){ + $("div."+LI_DIV_TOOLBAR).find(".layui-show").removeClass('layui-anim-fadein layui-show'); + // $("div[dtree-id][dtree-select]").removeClass("layui-form-selected"); + // $("div[dtree-id][dtree-card]").removeClass("dtree-select-show layui-anim layui-anim-upbit"); + + }); + + // 解绑浏览器事件 + DTree.prototype.unbindBrowserEvent = function(){ + var _this = this; + + // 本身事件解绑 + _this.obj.unbind(); + // 菜单栏解绑 + if(_this.menubar){ + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).unbind(); + if(_this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").length > 0){ + _this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").unbind(); + } + } + + // 工具栏解绑 + if(_this.toolbar){ + if(_this.toolbarWay == "contextmenu") { + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).unbind(); + if(_this.obj.closest(_this.scroll).length > 0){ + _this.obj.closest(_this.scroll).unbind(); + } + } + } + + // 下拉树解绑 + if(_this.select) { + // 解绑select的点击事件 + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-select='"+_this.selectDiv+"']").removeClass("layui-form-selected"); + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-card='"+_this.selectCardDiv+"']").removeClass("dtree-select-show layui-anim layui-anim-upbit"); + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-select='"+_this.selectDiv+"']").unbind(); + } + }; + + + /** 外部访问 **/ + var dtree = { + set: function(options){ //设置全局属性 + if(typeof options !== 'undefined') { + $.extend(OPTIONS, options); + } + }, + render: function(options){ // 初始化树 + var dTree = null; + var id = event.getElemId(options); + if(id == "") { + layer.msg("页面中未找到绑定id", {icon:5}); + } else { + dTree = DTrees[id]; + if(typeof dTree === 'object'){ + dTree.unbindBrowserEvent(); + } + // 创建树 + dTree = new DTree(options); + // 添加到树数组中去 + DTrees[id] = dTree; + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.init(); + dTree.bindBrowserEvent(); + } + + return dTree; + }, + renderSelect: function(options){ // 初始化下拉树 + var dTree = null; + var id = event.getElemId(options); + if(id == "") { + layer.msg("页面中未找到绑定id", {icon:5}); + } else { + dTree = DTrees[id]; + if(typeof dTree === 'object'){ + dTree.unbindBrowserEvent(); + } + // 创建下拉树 + dTree = new DTree(options); + dTree.selectSetting(); + // 添加到树数组中去 + DTrees[id] = dTree; + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.init(); + dTree.bindBrowserEvent(); + } + + return dTree; + }, + reload: function(dTree, options){ // 重新加载树 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + dTree.reloadSetting(options); + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.initNodeParam(); + dTree.init(); + dTree.unbindBrowserEvent(); + dTree.bindBrowserEvent(); + }, + on: function(events, callback) { // 绑定事件 + if(events.indexOf("'") > 0){ + events = events.replace(/'/g,""); + } + if(events.indexOf('"') > 0) { + events = events.replace(/"/g,""); + } + return layui.onevent.call(this, MOD_NAME, events, callback); + }, + click: function(dTree, id) { // 模拟单击事件 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + $("div[dtree-click='"+eventName.itemNodeClick+"'][dtree-id='"+dTree.obj[0].id+"'][data-id='"+id+"']").click(); + }, + getNowParam: function(dTree){ // 获取当前选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getNowParam(); // 获取当前选中值 + }, + getParam: function(dTree, id){ // 获取指定节点值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getParam(id); // 获取指定节点值 + }, + getParentParam: function(dTree, id){ // 获取参数的上级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getParentParam(id); + }, + getAllParentParam: function(dTree, id){ // 获取参数的全部上级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getAllParentParam(id); + }, + getChildParam: function(dTree, id){ // 获取参数的全部下级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getChildParam(id); + }, + getCheckbarNodesParam: function(dTree){ // 获取复选框选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return {}; + } + return dTree.getCheckbarNodesParam(); // 获取复选框选中值 + }, + dataInit: function(dTree, chooseId){ // 初始化选中树,针对数据反选 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + if(chooseId){ + return dTree.dataInit(chooseId); + } + }, + chooseDataInit: function(dTree, chooseIds){ // 初始化复选框选中,针对数据反选 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + if(chooseIds){ + return dTree.chooseDataInit(chooseIds); + } + }, + changeCheckbarNodes: function(dTree){ //判断复选框是否发生变更 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.changeCheckbarNodes(); + }, + initNoAllCheck: function(dTree) { //复选框半选状态初始化设置 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.initNoAllCheck(); + }, + initAllCheck: function(dTree){ // 复选框选中状态初始化设置 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.initAllCheck(); + }, + selectVal: function(dTree, param){ // select模式设置输入框选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.selectVal(param); // select模式设置输入框选中值 + }, + escape: function(html){ // 字符串格式化 + return event.escape(html); + }, + unescape: function(str){ // 字符串反格式化 + return event.unescape(str); + }, + version: function(){ //获取版本号 + return VERSION; + } + }; + + exports('dtree', dtree); +}); \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.css b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.css new file mode 100644 index 0000000000000000000000000000000000000000..df7af65397abb2d2094f986fb08484d58186d2c2 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.css @@ -0,0 +1,229 @@ +@font-face { + font-family: 'dtreefont'; + src: url('dtreefont.eot?x3m8fp'); + src: url('dtreefont.eot?x3m8fp#iefix') format('embedded-opentype'), + url('dtreefont.ttf?x3m8fp') format('truetype'), + url('dtreefont.woff?x3m8fp') format('woff'), + url('dtreefont.svg?x3m8fp#dtreefont') format('svg'); + font-weight: normal; + font-style: normal; +} + +[class^="dtree-icon-"], [class*=" dtree-icon-"] { + /* use !important to prevent issues with browser extensions that change font */ + font-family: 'dtreefont' !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; +} + +.dtree-icon-xiangxia1:before { + content: "\e771"; +} +.dtree-icon-normal-file:before { + content: "\e60c"; +} +.dtree-icon-xiangyou:before { + content: "\e78f"; +} +.dtree-icon-ok-circle:before { + content: "\1005"; +} +.dtree-icon-close1:before { + content: "\1006"; +} +.dtree-icon-close-fill:before { + content: "\1007"; +} +.dtree-icon-jian1:before { + content: "\e600"; +} +.dtree-icon-jia1:before { + content: "\e601"; +} +.dtree-icon-bianji:before { + content: "\e602"; +} +.dtree-icon-yonghu:before { + content: "\e603"; +} +.dtree-icon-shijian:before { + content: "\e606"; +} +.dtree-icon-fuxuankuang-banxuan:before { + content: "\e607"; +} +.dtree-icon-star:before { + content: "\e608"; +} +.dtree-icon-wenjianjiazhankai:before { + content: "\e60e"; +} +.dtree-icon-xiangmuxiaoxi:before { + content: "\e60f"; +} +.dtree-icon-search2:before { + content: "\e615"; +} +.dtree-icon-weibiaoti5:before { + content: "\e618"; +} +.dtree-icon-layim-theme:before { + content: "\e61b"; +} +.dtree-icon-shuye1:before { + content: "\e61e"; +} +.dtree-icon-add-circle:before { + content: "\e61f"; +} +.dtree-icon-xinxipilu:before { + content: "\e620"; +} +.dtree-icon-set-sm:before { + content: "\e621"; +} +.dtree-icon-about:before { + content: "\e623"; +} +.dtree-icon-chart-screen:before { + content: "\e62a"; +} +.dtree-icon-delete1:before { + content: "\e640"; +} +.dtree-icon-share3:before { + content: "\e641"; +} +.dtree-icon-youjian:before { + content: "\e642"; +} +.dtree-icon-check:before { + content: "\e645"; +} +.dtree-icon-close:before { + content: "\e646"; +} +.dtree-icon-favorfill:before { + content: "\e64b"; +} +.dtree-icon-favor:before { + content: "\e64c"; +} +.dtree-icon-fuxuankuangxuanzhong:before { + content: "\e652"; +} +.dtree-icon-fenguangbaobiao:before { + content: "\e655"; +} +.dtree-icon-jian:before { + content: "\e656"; +} +.dtree-icon-jia:before { + content: "\e657"; +} +.dtree-icon-fenzhijigou:before { + content: "\e658"; +} +.dtree-icon-roundcheckfill:before { + content: "\e659"; +} +.dtree-icon-roundcheck:before { + content: "\e65a"; +} +.dtree-icon-roundclosefill:before { + content: "\e65b"; +} +.dtree-icon-roundclose:before { + content: "\e65c"; +} +.dtree-icon-roundrightfill:before { + content: "\e65d"; +} +.dtree-icon-roundright:before { + content: "\e65e"; +} +.dtree-icon-like:before { + content: "\e66c"; +} +.dtree-icon-samefill:before { + content: "\e671"; +} +.dtree-icon-same:before { + content: "\e672"; +} +.dtree-icon-evaluate:before { + content: "\e674"; +} +.dtree-icon-circle1:before { + content: "\e687"; +} +.dtree-icon-radio:before { + content: "\e688"; +} +.dtree-icon-caidan_xunzhang:before { + content: "\e68e"; +} +.dtree-icon-pulldown:before { + content: "\e6a0"; +} +.dtree-icon-pullup:before { + content: "\e6a1"; +} +.dtree-icon-refresh:before { + content: "\e6a4"; +} +.dtree-icon-qrcode1:before { + content: "\e6b0"; +} +.dtree-icon-profile1:before { + content: "\e6b7"; +} +.dtree-icon-home1:before { + content: "\e6b8"; +} +.dtree-icon-homefill:before { + content: "\e6bb"; +} +.dtree-icon-roundaddfill:before { + content: "\e6d8"; +} +.dtree-icon-roundadd:before { + content: "\e6d9"; +} +.dtree-icon-fuxuankuang:before { + content: "\e6f2"; +} +.dtree-icon-wefill:before { + content: "\e6f5"; +} +.dtree-icon-sort:before { + content: "\e701"; +} +.dtree-icon-repair:before { + content: "\e738"; +} +.dtree-icon-shujudaping:before { + content: "\e742"; +} +.dtree-icon-dian:before { + content: "\e7a5"; +} +.dtree-icon-search_list_light:before { + content: "\e807"; +} +.dtree-icon-round_list_light:before { + content: "\e82b"; +} +.dtree-icon-star-fill:before { + content: "\e832"; +} +.dtree-icon-rate:before { + content: "\e833"; +} +.dtree-icon-move-up:before { + content: "\ea47"; +} +.dtree-icon-move-down:before { + content: "\ea48"; +} diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.eot b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.eot new file mode 100644 index 0000000000000000000000000000000000000000..68bf5f2f2dd33daa67373cca102f8ad764d84c22 Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.eot differ diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.svg b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.svg new file mode 100644 index 0000000000000000000000000000000000000000..90fe50f041be2e0433b009a20993ec78c8e4e67f --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.svg @@ -0,0 +1,80 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.ttf b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..78bacd13a0a16b55e6b3be536b35e34e147a396a Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.ttf differ diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.woff b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.woff new file mode 100644 index 0000000000000000000000000000000000000000..2b546450765b8d1368d1858ecc2c353d5529bfa5 Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/dtreefont.woff differ diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/icons.json b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/icons.json new file mode 100644 index 0000000000000000000000000000000000000000..fca4788566c21d9bcfc9e3bf0c4406d17651a211 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/dtree/font/icons.json @@ -0,0 +1,283 @@ +{ + "data": [{ + "cls": "dtree-icon-xiangxia1", + "uncode": "e771" + }, + { + "cls": "dtree-icon-xiangyou", + "uncode": "e78f" + }, + { + "cls": "dtree-icon-jian", + "uncode": "e656" + }, + { + "cls": "dtree-icon-jia", + "uncode": "e657" + }, + { + "cls": "dtree-icon-weibiaoti5", + "uncode": "e618" + }, + { + "cls": "dtree-icon-wenjianjiazhankai", + "uncode": "e60e" + }, + { + "cls": "dtree-icon-dian", + "uncode": "e7a5" + }, + { + "cls": "dtree-icon-yonghu", + "uncode": "e603" + }, + { + "cls": "dtree-icon-fenzhijigou", + "uncode": "e658" + }, + { + "cls": "dtree-icon-fenguangbaobiao", + "uncode": "e655" + }, + { + "cls": "dtree-icon-xinxipilu", + "uncode": "e620" + }, + { + "cls": "dtree-icon-shuye1", + "uncode": "e61e" + }, + { + "cls": "dtree-icon-caidan_xunzhang", + "uncode": "e68e" + }, + { + "cls": "dtree-icon-normal-file", + "uncode": "e60c" + }, + { + "cls": "dtree-icon-roundclose", + "uncode": "e65c" + }, + { + "cls": "dtree-icon-bianji", + "uncode": "e602" + }, + { + "cls": "dtree-icon-roundadd", + "uncode": "e6d9" + }, + { + "cls": "dtree-icon-fuxuankuangxuanzhong", + "uncode": "e652" + }, + { + "cls": "dtree-icon-fuxuankuang", + "uncode": "e6f2" + }, + { + "cls": "dtree-icon-fuxuankuang-banxuan", + "uncode": "e607" + }, + { + "cls": "dtree-icon-search_list_light", + "uncode": "e807" + }, + { + "cls": "dtree-icon-move-up", + "uncode": "ea47" + }, + { + "cls": "dtree-icon-move-down", + "uncode": "ea48" + }, + { + "cls": "dtree-icon-delete1", + "uncode": "e640" + }, + { + "cls": "dtree-icon-refresh", + "uncode": "e6a4" + }, + { + "cls": "dtree-icon-roundcheckfill", + "uncode": "e659" + }, + { + "cls": "dtree-icon-roundclosefill", + "uncode": "e65b" + }, + { + "cls": "dtree-icon-roundcheck", + "uncode": "e65a" + }, + { + "cls": "dtree-icon-pulldown", + "uncode": "e6a0" + }, + { + "cls": "dtree-icon-pullup", + "uncode": "e6a1" + }, + { + "cls": "dtree-icon-set-sm", + "uncode": "e621" + }, + { + "cls": "dtree-icon-rate", + "uncode": "e833" + }, + { + "cls": "dtree-icon-jian1", + "uncode": "e600" + }, + { + "cls": "dtree-icon-jia1", + "uncode": "e601" + }, + { + "cls": "dtree-icon-shijian", + "uncode": "e606" + }, + { + "cls": "dtree-icon-check", + "uncode": "e645" + }, + { + "cls": "dtree-icon-close", + "uncode": "e646" + }, + { + "cls": "dtree-icon-favorfill", + "uncode": "e64b" + }, + { + "cls": "dtree-icon-favor", + "uncode": "e64c" + }, + { + "cls": "dtree-icon-roundrightfill", + "uncode": "e65d" + }, + { + "cls": "dtree-icon-roundright", + "uncode": "e65e" + }, + { + "cls": "dtree-icon-samefill", + "uncode": "e671" + }, + { + "cls": "dtree-icon-same", + "uncode": "e672" + }, + { + "cls": "dtree-icon-qrcode1", + "uncode": "e6b0" + }, + { + "cls": "dtree-icon-profile1", + "uncode": "e6b7" + }, + { + "cls": "dtree-icon-home1", + "uncode": "e6b8" + }, + { + "cls": "dtree-icon-homefill", + "uncode": "e6bb" + }, + { + "cls": "dtree-icon-roundaddfill", + "uncode": "e6d8" + }, + { + "cls": "dtree-icon-wefill", + "uncode": "e6f5" + }, + { + "cls": "dtree-icon-sort", + "uncode": "e701" + }, + { + "cls": "dtree-icon-round_list_light", + "uncode": "e82b" + }, + { + "cls": "dtree-icon-search2", + "uncode": "e615" + }, + { + "cls": "dtree-icon-close1", + "uncode": "1006" + }, + { + "cls": "dtree-icon-close-fill", + "uncode": "1007" + }, + { + "cls": "dtree-icon-chart-screen", + "uncode": "e62a" + }, + { + "cls": "dtree-icon-star", + "uncode": "e608" + }, + { + "cls": "dtree-icon-ok-circle", + "uncode": "1005" + }, + { + "cls": "dtree-icon-add-circle", + "uncode": "e61f" + }, + { + "cls": "dtree-icon-about", + "uncode": "e623" + }, + { + "cls": "dtree-icon-circle1", + "uncode": "e687" + }, + { + "cls": "dtree-icon-radio", + "uncode": "e688" + }, + { + "cls": "dtree-icon-star-fill", + "uncode": "e832" + }, + { + "cls": "dtree-icon-shujudaping", + "uncode": "e742" + }, + { + "cls": "dtree-icon-share3", + "uncode": "e641" + }, + { + "cls": "dtree-icon-youjian", + "uncode": "e642" + }, + { + "cls": "dtree-icon-repair", + "uncode": "e738" + }, + { + "cls": "dtree-icon-evaluate", + "uncode": "e674" + }, + { + "cls": "dtree-icon-like", + "uncode": "e66c" + }, + { + "cls": "dtree-icon-layim-theme", + "uncode": "e61b" + }, + { + "cls": "dtree-icon-xiangmuxiaoxi", + "uncode": "e60f" + } + ] +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/encrypt.js b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/encrypt.js new file mode 100644 index 0000000000000000000000000000000000000000..9594f1a0f1da95d0a13f19d9b332856d711be1cf --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/encrypt.js @@ -0,0 +1,1775 @@ +/** + layui hash extend +**/ + +layui.define(function (exports) { + /** + * jshashes - https://github.com/h2non/jshashes + * Released under the "New BSD" license + * + * Algorithms specification: + * + * MD5 - http://www.ietf.org/rfc/rfc1321.txt + * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html + * SHA1 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + * HMAC - http://www.ietf.org/rfc/rfc2104.txt + */ + var pearHash; + + function utf8Encode(str) { + var x, y, output = '', + i = -1, + l; + + if (str && str.length) { + l = str.length; + while ((i += 1) < l) { + /* Decode utf-16 surrogate pairs */ + x = str.charCodeAt(i); + y = i + 1 < l ? str.charCodeAt(i + 1) : 0; + if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) { + x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); + i += 1; + } + /* Encode output as utf-8 */ + if (x <= 0x7F) { + output += String.fromCharCode(x); + } else if (x <= 0x7FF) { + output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F), + 0x80 | (x & 0x3F)); + } else if (x <= 0xFFFF) { + output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), + 0x80 | ((x >>> 6) & 0x3F), + 0x80 | (x & 0x3F)); + } else if (x <= 0x1FFFFF) { + output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), + 0x80 | ((x >>> 12) & 0x3F), + 0x80 | ((x >>> 6) & 0x3F), + 0x80 | (x & 0x3F)); + } + } + } + return output; + } + + function utf8Decode(str) { + var i, ac, c1, c2, c3, arr = [], + l; + i = ac = c1 = c2 = c3 = 0; + + if (str && str.length) { + l = str.length; + str += ''; + + while (i < l) { + c1 = str.charCodeAt(i); + ac += 1; + if (c1 < 128) { + arr[ac] = String.fromCharCode(c1); + i += 1; + } else if (c1 > 191 && c1 < 224) { + c2 = str.charCodeAt(i + 1); + arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63)); + i += 2; + } else { + c2 = str.charCodeAt(i + 1); + c3 = str.charCodeAt(i + 2); + arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + } + return arr.join(''); + } + + /** + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ + + function safe_add(x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF), + msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); + } + + /** + * Bitwise rotate a 32-bit number to the left. + */ + + function bit_rol(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)); + } + + /** + * Convert a raw string to a hex string + */ + + function rstr2hex(input, hexcase) { + var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef', + output = '', + x, i = 0, + l = input.length; + for (; i < l; i += 1) { + x = input.charCodeAt(i); + output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F); + } + return output; + } + + /** + * Encode a string as utf-16 + */ + + function str2rstr_utf16le(input) { + var i, l = input.length, + output = ''; + for (i = 0; i < l; i += 1) { + output += String.fromCharCode(input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF); + } + return output; + } + + function str2rstr_utf16be(input) { + var i, l = input.length, + output = ''; + for (i = 0; i < l; i += 1) { + output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF); + } + return output; + } + + /** + * Convert an array of big-endian words to a string + */ + + function binb2rstr(input) { + var i, l = input.length * 32, + output = ''; + for (i = 0; i < l; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF); + } + return output; + } + + /** + * Convert an array of little-endian words to a string + */ + + function binl2rstr(input) { + var i, l = input.length * 32, + output = ''; + for (i = 0; i < l; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); + } + return output; + } + + /** + * Convert a raw string to an array of little-endian words + * Characters >255 have their high-byte silently ignored. + */ + + function rstr2binl(input) { + var i, l = input.length * 8, + output = Array(input.length >> 2), + lo = output.length; + for (i = 0; i < lo; i += 1) { + output[i] = 0; + } + for (i = 0; i < l; i += 8) { + output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32); + } + return output; + } + + /** + * Convert a raw string to an array of big-endian words + * Characters >255 have their high-byte silently ignored. + */ + + function rstr2binb(input) { + var i, l = input.length * 8, + output = Array(input.length >> 2), + lo = output.length; + for (i = 0; i < lo; i += 1) { + output[i] = 0; + } + for (i = 0; i < l; i += 8) { + output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32); + } + return output; + } + + /** + * Convert a raw string to an arbitrary string encoding + */ + + function rstr2any(input, encoding) { + var divisor = encoding.length, + remainders = Array(), + i, q, x, ld, quotient, dividend, output, full_length; + + /* Convert to an array of 16-bit big-endian values, forming the dividend */ + dividend = Array(Math.ceil(input.length / 2)); + ld = dividend.length; + for (i = 0; i < ld; i += 1) { + dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); + } + + /** + * Repeatedly perform a long division. The binary array forms the dividend, + * the length of the encoding is the divisor. Once computed, the quotient + * forms the dividend for the next step. We stop when the dividend is zerHashes. + * All remainders are stored for later use. + */ + while (dividend.length > 0) { + quotient = Array(); + x = 0; + for (i = 0; i < dividend.length; i += 1) { + x = (x << 16) + dividend[i]; + q = Math.floor(x / divisor); + x -= q * divisor; + if (quotient.length > 0 || q > 0) { + quotient[quotient.length] = q; + } + } + remainders[remainders.length] = x; + dividend = quotient; + } + + /* Convert the remainders to the output string */ + output = ''; + for (i = remainders.length - 1; i >= 0; i--) { + output += encoding.charAt(remainders[i]); + } + + /* Append leading zero equivalents */ + full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2))); + for (i = output.length; i < full_length; i += 1) { + output = encoding[0] + output; + } + return output; + } + + /** + * Convert a raw string to a base-64 string + */ + + function rstr2b64(input, b64pad) { + var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', + output = '', + len = input.length, + i, j, triplet; + b64pad = b64pad || '='; + for (i = 0; i < len; i += 3) { + triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0); + for (j = 0; j < 4; j += 1) { + if (i * 8 + j * 6 > input.length * 8) { + output += b64pad; + } else { + output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F); + } + } + } + return output; + } + + pearHash = { + /** + * @property {String} version + * @readonly + */ + VERSION: '1.0.6', + /** + * @member Hashes + * @class Base64 + * @constructor + */ + Base64: function () { + // private properties + var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', + pad = '=', // default pad according with the RFC standard + url = false, // URL encoding support @todo + utf8 = true; // by default enable UTF-8 support encoding + + // public method for encoding + this.encode = function (input) { + var i, j, triplet, + output = '', + len = input.length; + + pad = pad || '='; + input = (utf8) ? utf8Encode(input) : input; + + for (i = 0; i < len; i += 3) { + triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0); + for (j = 0; j < 4; j += 1) { + if (i * 8 + j * 6 > len * 8) { + output += pad; + } else { + output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F); + } + } + } + return output; + }; + + // public method for decoding + this.decode = function (input) { + // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + var i, o1, o2, o3, h1, h2, h3, h4, bits, ac, + dec = '', + arr = []; + if (!input) { + return input; + } + + i = ac = 0; + input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '=' + //input += ''; + + do { // unpack four hexets into three octets using index points in b64 + h1 = tab.indexOf(input.charAt(i += 1)); + h2 = tab.indexOf(input.charAt(i += 1)); + h3 = tab.indexOf(input.charAt(i += 1)); + h4 = tab.indexOf(input.charAt(i += 1)); + + bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; + + o1 = bits >> 16 & 0xff; + o2 = bits >> 8 & 0xff; + o3 = bits & 0xff; + ac += 1; + + if (h3 === 64) { + arr[ac] = String.fromCharCode(o1); + } else if (h4 === 64) { + arr[ac] = String.fromCharCode(o1, o2); + } else { + arr[ac] = String.fromCharCode(o1, o2, o3); + } + } while (i < input.length); + + dec = arr.join(''); + dec = (utf8) ? utf8Decode(dec) : dec; + + return dec; + }; + + // set custom pad string + this.setPad = function (str) { + pad = str || pad; + return this; + }; + // set custom tab string characters + this.setTab = function (str) { + tab = str || tab; + return this; + }; + this.setUTF8 = function (bool) { + if (typeof bool === 'boolean') { + utf8 = bool; + } + return this; + }; + }, + + /** + * CRC-32 calculation + * @member Hashes + * @method CRC32 + * @static + * @param {String} str Input String + * @return {String} + */ + CRC32: function (str) { + var crc = 0, + x = 0, + y = 0, + table, i, iTop; + str = utf8Encode(str); + + table = [ + '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ', + '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ', + '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ', + '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ', + 'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ', + '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ', + 'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ', + '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ', + 'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ', + '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ', + 'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ', + '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ', + 'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ', + '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ', + '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ', + '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ', + '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ', + 'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ', + '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ', + 'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ', + '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ', + 'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ', + '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ', + 'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ', + '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ', + 'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D' + ].join(''); + + crc = crc ^ (-1); + for (i = 0, iTop = str.length; i < iTop; i += 1) { + y = (crc ^ str.charCodeAt(i)) & 0xFF; + x = '0x' + table.substr(y * 9, 8); + crc = (crc >>> 8) ^ x; + } + // always return a positive number (that's what >>> 0 does) + return (crc ^ (-1)) >>> 0; + }, + /** + * @member Hashes + * @class MD5 + * @constructor + * @param {Object} [config] + * + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See for more infHashes. + */ + MD5: function (options) { + /** + * Private config properties. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase} + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase + b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding + + // privileged (public) methods + this.hex = function (s) { + return rstr2hex(rstr(s, utf8), hexcase); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s, utf8), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d), hexcase); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * Enable/disable uppercase hexadecimal returned string + * @param {Boolean} + * @return {Object} this + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * Defines a base64 pad string + * @param {String} Pad + * @return {Object} this + */ + this.setPad = function (a) { + b64pad = a || b64pad; + return this; + }; + /** + * Defines a base64 pad string + * @param {Boolean} + * @return {Object} [this] + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + // private methods + + /** + * Calculate the MD5 of a raw string + */ + + function rstr(s) { + s = (utf8) ? utf8Encode(s) : s; + return binl2rstr(binl(rstr2binl(s), s.length * 8)); + } + + /** + * Calculate the HMAC-MD5, of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + var bkey, ipad, opad, hash, i; + + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + bkey = rstr2binl(key); + if (bkey.length > 16) { + bkey = binl(bkey, key.length * 8); + } + + ipad = Array(16), opad = Array(16); + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8); + return binl2rstr(binl(opad.concat(hash), 512 + 128)); + } + + /** + * Calculate the MD5 of an array of little-endian words, and a bit length. + */ + + function binl(x, len) { + var i, olda, oldb, oldc, oldd, + a = 1732584193, + b = -271733879, + c = -1732584194, + d = 271733878; + + /* append padding */ + x[len >> 5] |= 0x80 << ((len) % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + for (i = 0; i < x.length; i += 16) { + olda = a; + oldb = b; + oldc = c; + oldd = d; + + a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936); + d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); + d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); + d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); + b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); + d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); + d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); + c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); + d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); + c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); + d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); + c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); + d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); + c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); + d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); + d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); + d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); + d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844); + d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); + d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); + d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); + d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + } + return Array(a, b, c, d); + } + + /** + * These functions implement the four basic operations the algorithm uses. + */ + + function md5_cmn(q, a, b, x, s, t) { + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); + } + + function md5_ff(a, b, c, d, x, s, t) { + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); + } + + function md5_gg(a, b, c, d, x, s, t) { + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); + } + + function md5_hh(a, b, c, d, x, s, t) { + return md5_cmn(b ^ c ^ d, a, b, x, s, t); + } + + function md5_ii(a, b, c, d, x, s, t) { + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); + } + }, + /** + * @member Hashes + * @class Hashes.SHA1 + * @param {Object} [config] + * @constructor + * + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1 + * Version 2.2 Copyright Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See http://pajhome.org.uk/crypt/md5 for details. + */ + SHA1: function (options) { + /** + * Private config properties. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase} + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase + b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding + + // public methods + this.hex = function (s) { + return rstr2hex(rstr(s, utf8), hexcase); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s, utf8), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s, utf8), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d)); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + * @public + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * @description Enable/disable uppercase hexadecimal returned string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {string} Pad + * @return {Object} this + * @public + */ + this.setPad = function (a) { + b64pad = a || b64pad; + return this; + }; + /** + * @description Defines a base64 pad string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + // private methods + + /** + * Calculate the SHA-512 of a raw string + */ + + function rstr(s) { + s = (utf8) ? utf8Encode(s) : s; + return binb2rstr(binb(rstr2binb(s), s.length * 8)); + } + + /** + * Calculate the HMAC-SHA1 of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + var bkey, ipad, opad, i, hash; + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + bkey = rstr2binb(key); + + if (bkey.length > 16) { + bkey = binb(bkey, key.length * 8); + } + ipad = Array(16), opad = Array(16); + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8); + return binb2rstr(binb(opad.concat(hash), 512 + 160)); + } + + /** + * Calculate the SHA-1 of an array of big-endian words, and a bit length + */ + + function binb(x, len) { + var i, j, t, olda, oldb, oldc, oldd, olde, + w = Array(80), + a = 1732584193, + b = -271733879, + c = -1732584194, + d = 271733878, + e = -1009589776; + + /* append padding */ + x[len >> 5] |= 0x80 << (24 - len % 32); + x[((len + 64 >> 9) << 4) + 15] = len; + + for (i = 0; i < x.length; i += 16) { + olda = a; + oldb = b; + oldc = c; + oldd = d; + olde = e; + + for (j = 0; j < 80; j += 1) { + if (j < 16) { + w[j] = x[i + j]; + } else { + w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); + } + t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), + safe_add(safe_add(e, w[j]), sha1_kt(j))); + e = d; + d = c; + c = bit_rol(b, 30); + b = a; + a = t; + } + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + e = safe_add(e, olde); + } + return Array(a, b, c, d, e); + } + + /** + * Perform the appropriate triplet combination function for the current + * iteration + */ + + function sha1_ft(t, b, c, d) { + if (t < 20) { + return (b & c) | ((~b) & d); + } + if (t < 40) { + return b ^ c ^ d; + } + if (t < 60) { + return (b & c) | (b & d) | (c & d); + } + return b ^ c ^ d; + } + + /** + * Determine the appropriate additive constant for the current iteration + */ + + function sha1_kt(t) { + return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : + (t < 60) ? -1894007588 : -899497514; + } + }, + /** + * @class Hashes.SHA256 + * @param {config} + * + * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2 + * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See http://pajhome.org.uk/crypt/md5 for details. + * Also http://anmar.eu.org/projects/jssha2/ + */ + SHA256: function (options) { + /** + * Private properties configuration variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * @see this.setUpperCase() method + * @see this.setPad() method + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase */ + b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', + /* base-64 pad character. Default '=' for strict RFC compliance */ + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, + /* enable/disable utf8 encoding */ + sha256_K; + + /* privileged (public) methods */ + this.hex = function (s) { + return rstr2hex(rstr(s, utf8)); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s, utf8), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s, utf8), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d)); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + * @public + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * Enable/disable uppercase hexadecimal returned string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {string} Pad + * @return {Object} this + * @public + */ + this.setPad = function (a) { + b64pad = a || b64pad; + return this; + }; + /** + * Defines a base64 pad string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + // private methods + + /** + * Calculate the SHA-512 of a raw string + */ + + function rstr(s, utf8) { + s = (utf8) ? utf8Encode(s) : s; + return binb2rstr(binb(rstr2binb(s), s.length * 8)); + } + + /** + * Calculate the HMAC-sha256 of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + var hash, i = 0, + bkey = rstr2binb(key), + ipad = Array(16), + opad = Array(16); + + if (bkey.length > 16) { + bkey = binb(bkey, key.length * 8); + } + + for (; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8); + return binb2rstr(binb(opad.concat(hash), 512 + 256)); + } + + /* + * Main sha256 function, with its support functions + */ + + function sha256_S(X, n) { + return (X >>> n) | (X << (32 - n)); + } + + function sha256_R(X, n) { + return (X >>> n); + } + + function sha256_Ch(x, y, z) { + return ((x & y) ^ ((~x) & z)); + } + + function sha256_Maj(x, y, z) { + return ((x & y) ^ (x & z) ^ (y & z)); + } + + function sha256_Sigma0256(x) { + return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22)); + } + + function sha256_Sigma1256(x) { + return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25)); + } + + function sha256_Gamma0256(x) { + return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3)); + } + + function sha256_Gamma1256(x) { + return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10)); + } + + function sha256_Sigma0512(x) { + return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39)); + } + + function sha256_Sigma1512(x) { + return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41)); + } + + function sha256_Gamma0512(x) { + return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7)); + } + + function sha256_Gamma1512(x) { + return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6)); + } + + sha256_K = [ + 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, + 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522, + 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585, + 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, + 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, + 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, + 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998 + ]; + + function binb(m, l) { + var HASH = [1779033703, -1150833019, 1013904242, -1521486534, + 1359893119, -1694144372, 528734635, 1541459225 + ]; + var W = new Array(64); + var a, b, c, d, e, f, g, h; + var i, j, T1, T2; + + /* append padding */ + m[l >> 5] |= 0x80 << (24 - l % 32); + m[((l + 64 >> 9) << 4) + 15] = l; + + for (i = 0; i < m.length; i += 16) { + a = HASH[0]; + b = HASH[1]; + c = HASH[2]; + d = HASH[3]; + e = HASH[4]; + f = HASH[5]; + g = HASH[6]; + h = HASH[7]; + + for (j = 0; j < 64; j += 1) { + if (j < 16) { + W[j] = m[j + i]; + } else { + W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]), + sha256_Gamma0256(W[j - 15])), W[j - 16]); + } + + T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)), + sha256_K[j]), W[j]); + T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c)); + h = g; + g = f; + f = e; + e = safe_add(d, T1); + d = c; + c = b; + b = a; + a = safe_add(T1, T2); + } + + HASH[0] = safe_add(a, HASH[0]); + HASH[1] = safe_add(b, HASH[1]); + HASH[2] = safe_add(c, HASH[2]); + HASH[3] = safe_add(d, HASH[3]); + HASH[4] = safe_add(e, HASH[4]); + HASH[5] = safe_add(f, HASH[5]); + HASH[6] = safe_add(g, HASH[6]); + HASH[7] = safe_add(h, HASH[7]); + } + return HASH; + } + + }, + + /** + * @class Hashes.SHA512 + * @param {config} + * + * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2 + * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See http://pajhome.org.uk/crypt/md5 for details. + */ + SHA512: function (options) { + /** + * Private properties configuration variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * @see this.setUpperCase() method + * @see this.setPad() method + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, + /* hexadecimal output case format. false - lowercase; true - uppercase */ + b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', + /* base-64 pad character. Default '=' for strict RFC compliance */ + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, + /* enable/disable utf8 encoding */ + sha512_k; + + /* privileged (public) methods */ + this.hex = function (s) { + return rstr2hex(rstr(s)); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d)); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + * @public + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * @description Enable/disable uppercase hexadecimal returned string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {string} Pad + * @return {Object} this + * @public + */ + this.setPad = function (a) { + b64pad = a || b64pad; + return this; + }; + /** + * @description Defines a base64 pad string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + /* private methods */ + + /** + * Calculate the SHA-512 of a raw string + */ + + function rstr(s) { + s = (utf8) ? utf8Encode(s) : s; + return binb2rstr(binb(rstr2binb(s), s.length * 8)); + } + /* + * Calculate the HMAC-SHA-512 of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + + var hash, i = 0, + bkey = rstr2binb(key), + ipad = Array(32), + opad = Array(32); + + if (bkey.length > 32) { + bkey = binb(bkey, key.length * 8); + } + + for (; i < 32; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8); + return binb2rstr(binb(opad.concat(hash), 1024 + 512)); + } + + /** + * Calculate the SHA-512 of an array of big-endian dwords, and a bit length + */ + + function binb(x, len) { + var j, i, l, + W = new Array(80), + hash = new Array(16), + //Initial hash values + H = [ + new int64(0x6a09e667, -205731576), + new int64(-1150833019, -2067093701), + new int64(0x3c6ef372, -23791573), + new int64(-1521486534, 0x5f1d36f1), + new int64(0x510e527f, -1377402159), + new int64(-1694144372, 0x2b3e6c1f), + new int64(0x1f83d9ab, -79577749), + new int64(0x5be0cd19, 0x137e2179) + ], + T1 = new int64(0, 0), + T2 = new int64(0, 0), + a = new int64(0, 0), + b = new int64(0, 0), + c = new int64(0, 0), + d = new int64(0, 0), + e = new int64(0, 0), + f = new int64(0, 0), + g = new int64(0, 0), + h = new int64(0, 0), + //Temporary variables not specified by the document + s0 = new int64(0, 0), + s1 = new int64(0, 0), + Ch = new int64(0, 0), + Maj = new int64(0, 0), + r1 = new int64(0, 0), + r2 = new int64(0, 0), + r3 = new int64(0, 0); + + if (sha512_k === undefined) { + //SHA512 constants + sha512_k = [ + new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd), + new int64(-1245643825, -330482897), new int64(-373957723, -2121671748), + new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031), + new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736), + new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe), + new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302), + new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1), + new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428), + new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3), + new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65), + new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483), + new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459), + new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210), + new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340), + new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395), + new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70), + new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926), + new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473), + new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8), + new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b), + new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023), + new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30), + new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910), + new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8), + new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53), + new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016), + new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893), + new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397), + new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60), + new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec), + new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047), + new int64(-1090935817, -1295615723), new int64(-965641998, -479046869), + new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207), + new int64(-354779690, -840897762), new int64(-176337025, -294727304), + new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026), + new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b), + new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493), + new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620), + new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430), + new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817) + ]; + } + + for (i = 0; i < 80; i += 1) { + W[i] = new int64(0, 0); + } + + // append padding to the source string. The format is described in the FIPS. + x[len >> 5] |= 0x80 << (24 - (len & 0x1f)); + x[((len + 128 >> 10) << 5) + 31] = len; + l = x.length; + for (i = 0; i < l; i += 32) { //32 dwords is the block size + int64copy(a, H[0]); + int64copy(b, H[1]); + int64copy(c, H[2]); + int64copy(d, H[3]); + int64copy(e, H[4]); + int64copy(f, H[5]); + int64copy(g, H[6]); + int64copy(h, H[7]); + + for (j = 0; j < 16; j += 1) { + W[j].h = x[i + 2 * j]; + W[j].l = x[i + 2 * j + 1]; + } + + for (j = 16; j < 80; j += 1) { + //sigma1 + int64rrot(r1, W[j - 2], 19); + int64revrrot(r2, W[j - 2], 29); + int64shr(r3, W[j - 2], 6); + s1.l = r1.l ^ r2.l ^ r3.l; + s1.h = r1.h ^ r2.h ^ r3.h; + //sigma0 + int64rrot(r1, W[j - 15], 1); + int64rrot(r2, W[j - 15], 8); + int64shr(r3, W[j - 15], 7); + s0.l = r1.l ^ r2.l ^ r3.l; + s0.h = r1.h ^ r2.h ^ r3.h; + + int64add4(W[j], s1, W[j - 7], s0, W[j - 16]); + } + + for (j = 0; j < 80; j += 1) { + //Ch + Ch.l = (e.l & f.l) ^ (~e.l & g.l); + Ch.h = (e.h & f.h) ^ (~e.h & g.h); + + //Sigma1 + int64rrot(r1, e, 14); + int64rrot(r2, e, 18); + int64revrrot(r3, e, 9); + s1.l = r1.l ^ r2.l ^ r3.l; + s1.h = r1.h ^ r2.h ^ r3.h; + + //Sigma0 + int64rrot(r1, a, 28); + int64revrrot(r2, a, 2); + int64revrrot(r3, a, 7); + s0.l = r1.l ^ r2.l ^ r3.l; + s0.h = r1.h ^ r2.h ^ r3.h; + + //Maj + Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l); + Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h); + + int64add5(T1, h, s1, Ch, sha512_k[j], W[j]); + int64add(T2, s0, Maj); + + int64copy(h, g); + int64copy(g, f); + int64copy(f, e); + int64add(e, d, T1); + int64copy(d, c); + int64copy(c, b); + int64copy(b, a); + int64add(a, T1, T2); + } + int64add(H[0], H[0], a); + int64add(H[1], H[1], b); + int64add(H[2], H[2], c); + int64add(H[3], H[3], d); + int64add(H[4], H[4], e); + int64add(H[5], H[5], f); + int64add(H[6], H[6], g); + int64add(H[7], H[7], h); + } + + //represent the hash as an array of 32-bit dwords + for (i = 0; i < 8; i += 1) { + hash[2 * i] = H[i].h; + hash[2 * i + 1] = H[i].l; + } + return hash; + } + + //A constructor for 64-bit numbers + + function int64(h, l) { + this.h = h; + this.l = l; + //this.toString = int64toString; + } + + //Copies src into dst, assuming both are 64-bit numbers + + function int64copy(dst, src) { + dst.h = src.h; + dst.l = src.l; + } + + //Right-rotates a 64-bit number by shift + //Won't handle cases of shift>=32 + //The function revrrot() is for that + + function int64rrot(dst, x, shift) { + dst.l = (x.l >>> shift) | (x.h << (32 - shift)); + dst.h = (x.h >>> shift) | (x.l << (32 - shift)); + } + + //Reverses the dwords of the source and then rotates right by shift. + //This is equivalent to rotation by 32+shift + + function int64revrrot(dst, x, shift) { + dst.l = (x.h >>> shift) | (x.l << (32 - shift)); + dst.h = (x.l >>> shift) | (x.h << (32 - shift)); + } + + //Bitwise-shifts right a 64-bit number by shift + //Won't handle shift>=32, but it's never needed in SHA512 + + function int64shr(dst, x, shift) { + dst.l = (x.l >>> shift) | (x.h << (32 - shift)); + dst.h = (x.h >>> shift); + } + + //Adds two 64-bit numbers + //Like the original implementation, does not rely on 32-bit operations + + function int64add(dst, x, y) { + var w0 = (x.l & 0xffff) + (y.l & 0xffff); + var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16); + var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16); + var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16); + dst.l = (w0 & 0xffff) | (w1 << 16); + dst.h = (w2 & 0xffff) | (w3 << 16); + } + + //Same, except with 4 addends. Works faster than adding them one by one. + + function int64add4(dst, a, b, c, d) { + var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff); + var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16); + var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16); + var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16); + dst.l = (w0 & 0xffff) | (w1 << 16); + dst.h = (w2 & 0xffff) | (w3 << 16); + } + + //Same, except with 5 addends + + function int64add5(dst, a, b, c, d, e) { + var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff), + w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16), + w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16), + w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16); + dst.l = (w0 & 0xffff) | (w1 << 16); + dst.h = (w2 & 0xffff) | (w3 << 16); + } + }, + /** + * @class Hashes.RMD160 + * @constructor + * @param {Object} [config] + * + * A JavaScript implementation of the RIPEMD-160 Algorithm + * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * See http://pajhome.org.uk/crypt/md5 for details. + * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/ + */ + RMD160: function (options) { + /** + * Private properties configuration variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + * @see this.setUpperCase() method + * @see this.setPad() method + */ + var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, + /* hexadecimal output case format. false - lowercase; true - uppercase */ + b64pad = (options && typeof options.pad === 'string') ? options.pa : '=', + /* base-64 pad character. Default '=' for strict RFC compliance */ + utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, + /* enable/disable utf8 encoding */ + rmd160_r1 = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 + ], + rmd160_r2 = [ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 + ], + rmd160_s1 = [ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 + ], + rmd160_s2 = [ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 + ]; + + /* privileged (public) methods */ + this.hex = function (s) { + return rstr2hex(rstr(s, utf8)); + }; + this.b64 = function (s) { + return rstr2b64(rstr(s, utf8), b64pad); + }; + this.any = function (s, e) { + return rstr2any(rstr(s, utf8), e); + }; + this.raw = function (s) { + return rstr(s, utf8); + }; + this.hex_hmac = function (k, d) { + return rstr2hex(rstr_hmac(k, d)); + }; + this.b64_hmac = function (k, d) { + return rstr2b64(rstr_hmac(k, d), b64pad); + }; + this.any_hmac = function (k, d, e) { + return rstr2any(rstr_hmac(k, d), e); + }; + /** + * Perform a simple self-test to see if the VM is working + * @return {String} Hexadecimal hash sample + * @public + */ + this.vm_test = function () { + return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; + }; + /** + * @description Enable/disable uppercase hexadecimal returned string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUpperCase = function (a) { + if (typeof a === 'boolean') { + hexcase = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {string} Pad + * @return {Object} this + * @public + */ + this.setPad = function (a) { + if (typeof a !== 'undefined') { + b64pad = a; + } + return this; + }; + /** + * @description Defines a base64 pad string + * @param {boolean} + * @return {Object} this + * @public + */ + this.setUTF8 = function (a) { + if (typeof a === 'boolean') { + utf8 = a; + } + return this; + }; + + /* private methods */ + + /** + * Calculate the rmd160 of a raw string + */ + + function rstr(s) { + s = (utf8) ? utf8Encode(s) : s; + return binl2rstr(binl(rstr2binl(s), s.length * 8)); + } + + /** + * Calculate the HMAC-rmd160 of a key and some data (raw strings) + */ + + function rstr_hmac(key, data) { + key = (utf8) ? utf8Encode(key) : key; + data = (utf8) ? utf8Encode(data) : data; + var i, hash, + bkey = rstr2binl(key), + ipad = Array(16), + opad = Array(16); + + if (bkey.length > 16) { + bkey = binl(bkey, key.length * 8); + } + + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8); + return binl2rstr(binl(opad.concat(hash), 512 + 160)); + } + + /** + * Convert an array of little-endian words to a string + */ + + function binl2rstr(input) { + var i, output = '', + l = input.length * 32; + for (i = 0; i < l; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); + } + return output; + } + + /** + * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length. + */ + + function binl(x, len) { + var T, j, i, l, + h0 = 0x67452301, + h1 = 0xefcdab89, + h2 = 0x98badcfe, + h3 = 0x10325476, + h4 = 0xc3d2e1f0, + A1, B1, C1, D1, E1, + A2, B2, C2, D2, E2; + + /* append padding */ + x[len >> 5] |= 0x80 << (len % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + l = x.length; + + for (i = 0; i < l; i += 16) { + A1 = A2 = h0; + B1 = B2 = h1; + C1 = C2 = h2; + D1 = D2 = h3; + E1 = E2 = h4; + for (j = 0; j <= 79; j += 1) { + T = safe_add(A1, rmd160_f(j, B1, C1, D1)); + T = safe_add(T, x[i + rmd160_r1[j]]); + T = safe_add(T, rmd160_K1(j)); + T = safe_add(bit_rol(T, rmd160_s1[j]), E1); + A1 = E1; + E1 = D1; + D1 = bit_rol(C1, 10); + C1 = B1; + B1 = T; + T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2)); + T = safe_add(T, x[i + rmd160_r2[j]]); + T = safe_add(T, rmd160_K2(j)); + T = safe_add(bit_rol(T, rmd160_s2[j]), E2); + A2 = E2; + E2 = D2; + D2 = bit_rol(C2, 10); + C2 = B2; + B2 = T; + } + + T = safe_add(h1, safe_add(C1, D2)); + h1 = safe_add(h2, safe_add(D1, E2)); + h2 = safe_add(h3, safe_add(E1, A2)); + h3 = safe_add(h4, safe_add(A1, B2)); + h4 = safe_add(h0, safe_add(B1, C2)); + h0 = T; + } + return [h0, h1, h2, h3, h4]; + } + + // specific algorithm methods + + function rmd160_f(j, x, y, z) { + return (0 <= j && j <= 15) ? (x ^ y ^ z) : + (16 <= j && j <= 31) ? (x & y) | (~x & z) : + (32 <= j && j <= 47) ? (x | ~y) ^ z : + (48 <= j && j <= 63) ? (x & z) | (y & ~z) : + (64 <= j && j <= 79) ? x ^ (y | ~z) : + 'rmd160_f: j out of range'; + } + + function rmd160_K1(j) { + return (0 <= j && j <= 15) ? 0x00000000 : + (16 <= j && j <= 31) ? 0x5a827999 : + (32 <= j && j <= 47) ? 0x6ed9eba1 : + (48 <= j && j <= 63) ? 0x8f1bbcdc : + (64 <= j && j <= 79) ? 0xa953fd4e : + 'rmd160_K1: j out of range'; + } + + function rmd160_K2(j) { + return (0 <= j && j <= 15) ? 0x50a28be6 : + (16 <= j && j <= 31) ? 0x5c4dd124 : + (32 <= j && j <= 47) ? 0x6d703ef3 : + (48 <= j && j <= 63) ? 0x7a6d76e9 : + (64 <= j && j <= 79) ? 0x00000000 : + 'rmd160_K2: j out of range'; + } + } + }; + + // new MD5 instance + var MD5 = new pearHash.MD5 + // new SHA1 instance + var SHA1 = new pearHash.SHA1 + // new SHA256 instance + var SHA256 = new pearHash.SHA256 + // new SHA512 instace + var SHA512 = new pearHash.SHA512 + // new RIPEMD-160 instace + var RMD160 = new pearHash.RMD160 + var Base64 = new pearHash.Base64 + + pearHash.md5 = function (str) { + return MD5.hex(str); + } + pearHash.sha1 = function (str) { + return SHA1.hex(str); + } + pearHash.sha256 = function (str) { + return SHA256.hex(str); + } + pearHash.sha512 = function (str) { + return SHA512.hex(str); + } + pearHash.crc32 = pearHash.CRC32; + pearHash.rmd160 = function (str) { + return RMD160.hex(str); + } + pearHash.Base64Encode = function (str) { + return Base64.encode(str); + } + pearHash.Base64Decode = function (str) { + return Base64.decode(str); + } + exports('encrypt', pearHash); +}); \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/iconPicker.js b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/iconPicker.js new file mode 100644 index 0000000000000000000000000000000000000000..bde668d1e9bab8853c91fc2af88445e87cc81283 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/iconPicker.js @@ -0,0 +1,491 @@ +layui.define(['laypage', 'form'], function(exports) { + "use strict"; + + var IconPicker = function() { + this.v = '1.1'; + }, + _MOD = 'iconPicker', + _this = this, + $ = layui.jquery, + laypage = layui.laypage, + form = layui.form, + BODY = 'body', + TIPS = '请选择图标'; + + /** + * 渲染组件 + */ + IconPicker.prototype.render = function(options) { + var opts = options, + // DOM选择器 + elem = opts.elem, + // 数据类型:fontClass/unicode + type = opts.type == null ? 'fontClass' : opts.type, + // 是否分页:true/false + page = opts.page == null ? true : opts.page, + // 每页显示数量 + limit = opts.limit == null ? 12 : opts.limit, + // 是否开启搜索:true/false + search = opts.search == null ? true : opts.search, + // 每个图标格子的宽度:'43px'或'20%' + cellWidth = opts.cellWidth, + // 点击回调 + click = opts.click, + // 渲染成功后的回调 + success = opts.success, + // json数据 + data = {}, + // 唯一标识 + tmp = new Date().getTime(), + // 是否使用的class数据 + isFontClass = opts.type === 'fontClass', + // 初始化时input的值 + ORIGINAL_ELEM_VALUE = $(elem).val(), + TITLE = 'layui-select-title', + TITLE_ID = 'layui-select-title-' + tmp, + ICON_BODY = 'layui-iconpicker-' + tmp, + PICKER_BODY = 'layui-iconpicker-body-' + tmp, + PAGE_ID = 'layui-iconpicker-page-' + tmp, + LIST_BOX = 'layui-iconpicker-list-box', + selected = 'layui-form-selected', + unselect = 'layui-unselect'; + + var a = { + init: function() { + data = common.getData[type](); + + a.hideElem().createSelect().createBody().toggleSelect(); + a.preventEvent().inputListen(); + common.loadCss(); + + if (success) { + success(this.successHandle()); + } + + return a; + }, + successHandle: function() { + var d = { + options: opts, + data: data, + id: tmp, + elem: $('#' + ICON_BODY) + }; + return d; + }, + /** + * 隐藏elem + */ + hideElem: function() { + $(elem).hide(); + return a; + }, + /** + * 绘制select下拉选择框 + */ + createSelect: function() { + var oriIcon = ''; + + // 默认图标 + if (ORIGINAL_ELEM_VALUE === '') { + if (isFontClass) { + ORIGINAL_ELEM_VALUE = 'layui-icon-circle-dot'; + } else { + ORIGINAL_ELEM_VALUE = ''; + } + } + + if (isFontClass) { + oriIcon = ''; + } else { + oriIcon += ORIGINAL_ELEM_VALUE; + } + oriIcon += ''; + + var selectHtml = + '
                                                                                                                  ' + + '
                                                                                                                  ' + + '
                                                                                                                  ' + + '' + + oriIcon + + '' + + '' + + '
                                                                                                                  ' + + '
                                                                                                                  ' + + '
                                                                                                                  ' + + '123' + + '
                                                                                                                  '; + $(elem).after(selectHtml); + return a; + }, + /** + * 展开/折叠下拉框 + */ + toggleSelect: function() { + var item = '#' + TITLE_ID + ' .layui-iconpicker-item,#' + TITLE_ID + + ' .layui-iconpicker-item .layui-edge'; + a.event('click', item, function(e) { + var $icon = $('#' + ICON_BODY); + if ($icon.hasClass(selected)) { + $icon.removeClass(selected).addClass(unselect); + } else { + // 隐藏其他picker + $('.layui-form-select').removeClass(selected); + // 显示当前picker + $icon.addClass(selected).removeClass(unselect); + } + e.stopPropagation(); + }); + return a; + }, + /** + * 绘制主体部分 + */ + createBody: function() { + // 获取数据 + var searchHtml = ''; + + if (search) { + searchHtml = ''; + } + + // 组合dom + var bodyHtml = '
                                                                                                                  ' + + searchHtml + + '
                                                                                                                  ' + + '
                                                                                                                  '; + $('#' + ICON_BODY).find('.layui-anim').eq(0).html(bodyHtml); + a.search().createList().check().page(); + + return a; + }, + /** + * 绘制图标列表 + * @param text 模糊查询关键字 + * @returns {string} + */ + createList: function(text) { + var d = data, + l = d.length, + pageHtml = '', + listHtml = $( + '
                                                                                                                  ') //'
                                                                                                                  '; + + // 计算分页数据 + var _limit = limit, // 每页显示数量 + _pages = l % _limit === 0 ? l / _limit : parseInt(l / _limit + 1), // 总计多少页 + _id = PAGE_ID; + + // 图标列表 + var icons = []; + + for (var i = 0; i < l; i++) { + var obj = d[i]; + + // 判断是否模糊查询 + if (text && obj.indexOf(text) === -1) { + continue; + } + + // 是否自定义格子宽度 + var style = ''; + if (cellWidth !== null) { + style += ' style="width:' + cellWidth + '"'; + } + + // 每个图标dom + var icon = '
                                                                                                                  '; + if (isFontClass) { + icon += ''; + } else { + icon += '' + obj.replace('amp;', '') + ''; + } + icon += '
                                                                                                                  '; + + icons.push(icon); + } + + // 查询出图标后再分页 + l = icons.length; + _pages = l % _limit === 0 ? l / _limit : parseInt(l / _limit + 1); + for (var i = 0; i < _pages; i++) { + // 按limit分块 + var lm = $( + '
                                                                                                                  '); + + for (var j = i * _limit; j < (i + 1) * _limit && j < l; j++) { + lm.append(icons[j]); + } + + listHtml.append(lm); + } + + // 无数据 + if (l === 0) { + listHtml.append('

                                                                                                                  无数据

                                                                                                                  '); + } + + // 判断是否分页 + if (page) { + $('#' + PICKER_BODY).addClass('layui-iconpicker-body-page'); + pageHtml = '
                                                                                                                  ' + + '
                                                                                                                  ' + + '1/' + + '' + _pages + '' + + ' (' + l + ')' + + '
                                                                                                                  ' + + '
                                                                                                                  ' + + ' ' + + ' ' + + '
                                                                                                                  ' + + '
                                                                                                                  '; + } + + + $('#' + ICON_BODY).find('.layui-anim').find('.' + LIST_BOX).html('').append( + listHtml).append(pageHtml); + return a; + }, + // 阻止Layui的一些默认事件 + preventEvent: function() { + var item = '#' + ICON_BODY + ' .layui-anim'; + a.event('click', item, function(e) { + e.stopPropagation(); + }); + return a; + }, + // 分页 + page: function() { + var icon = '#' + PAGE_ID + ' .layui-iconpicker-page-operate .layui-icon'; + + $(icon).unbind('click'); + a.event('click', icon, function(e) { + var elem = e.currentTarget, + total = parseInt($('#' + PAGE_ID + '-pages').html()), + isPrev = $(elem).attr('prev') !== undefined, + // 按钮上标的页码 + index = parseInt($(elem).attr('data-index')), + $cur = $('#' + PAGE_ID + '-current'), + // 点击时正在显示的页码 + current = parseInt($cur.html()); + + // 分页数据 + if (isPrev && current > 1) { + current = current - 1; + $(icon + '[prev]').attr('data-index', current); + } else if (!isPrev && current < total) { + current = current + 1; + $(icon + '[next]').attr('data-index', current); + } + $cur.html(current); + + // 图标数据 + $('#' + ICON_BODY + ' .layui-iconpicker-icon-limit').hide(); + $('#layui-iconpicker-icon-limit-' + tmp + current).show(); + e.stopPropagation(); + }); + return a; + }, + /** + * 搜索 + */ + search: function() { + var item = '#' + PICKER_BODY + ' .layui-iconpicker-search .layui-input'; + a.event('input propertychange', item, function(e) { + var elem = e.target, + t = $(elem).val(); + a.createList(t); + }); + return a; + }, + /** + * 点击选中图标 + */ + check: function() { + var item = '#' + PICKER_BODY + ' .layui-iconpicker-icon-item'; + a.event('click', item, function(e) { + var el = $(e.currentTarget).find('.layui-icon'), + icon = ''; + if (isFontClass) { + var clsArr = el.attr('class').split(/[\s\n]/), + cls = clsArr[1], + icon = cls; + $('#' + TITLE_ID).find('.layui-iconpicker-item .layui-icon').html( + '').attr('class', clsArr.join(' ')); + } else { + var cls = el.html(), + icon = cls; + $('#' + TITLE_ID).find('.layui-iconpicker-item .layui-icon').html( + icon); + } + + $('#' + ICON_BODY).removeClass(selected).addClass(unselect); + $(elem).val(icon).attr('value', icon); + // 回调 + if (click) { + click({ + icon: icon + }); + } + + }); + return a; + }, + // 监听原始input数值改变 + inputListen: function() { + var el = $(elem); + a.event('change', elem, function() { + var value = el.val(); + }) + // el.change(function(){ + + // }); + return a; + }, + event: function(evt, el, fn) { + $(BODY).on(evt, el, fn); + } + }; + + var common = { + /** + * 加载样式表 + */ + loadCss: function() { + var css = + '.layui-iconpicker {max-width: 280px;}.layui-iconpicker .layui-anim{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box;}.layui-iconpicker-item{border:1px solid #e6e6e6;width:90px;height:38px;border-radius:4px;cursor:pointer;position:relative;}.layui-iconpicker-icon{border-right:1px solid #e6e6e6;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;width:60px;height:100%;float:left;text-align:center;background:#fff;transition:all .3s;}.layui-iconpicker-icon i{line-height:38px;font-size:18px;}.layui-iconpicker-item > .layui-edge{left:70px;}.layui-iconpicker-item:hover{border-color:#D2D2D2!important;}.layui-iconpicker-item:hover .layui-iconpicker-icon{border-color:#D2D2D2!important;}.layui-iconpicker.layui-form-selected .layui-anim{display:block;}.layui-iconpicker-body{padding:6px;}.layui-iconpicker .layui-iconpicker-list{background-color:#fff;border:1px solid #ccc;border-radius:4px;}.layui-iconpicker .layui-iconpicker-icon-item{display:inline-block;width:21.1%;line-height:36px;text-align:center;cursor:pointer;vertical-align:top;height:36px;margin:4px;border:1px solid #ddd;border-radius:2px;transition:300ms;}.layui-iconpicker .layui-iconpicker-icon-item i.layui-icon{font-size:17px;}.layui-iconpicker .layui-iconpicker-icon-item:hover{background-color:#eee;border-color:#ccc;-webkit-box-shadow:0 0 2px #aaa,0 0 2px #fff inset;-moz-box-shadow:0 0 2px #aaa,0 0 2px #fff inset;box-shadow:0 0 2px #aaa,0 0 2px #fff inset;text-shadow:0 0 1px #fff;}.layui-iconpicker-search{position:relative;margin:0 0 6px 0;border:1px solid #e6e6e6;border-radius:2px;transition:300ms;}.layui-iconpicker-search:hover{border-color:#D2D2D2!important;}.layui-iconpicker-search .layui-input{cursor:text;display:inline-block;width:86%;border:none;padding-right:0;margin-top:1px;}.layui-iconpicker-search .layui-icon{position:absolute;top:11px;right:4%;}.layui-iconpicker-tips{text-align:center;padding:8px 0;cursor:not-allowed;}.layui-iconpicker-page{margin-top:6px;margin-bottom:-6px;font-size:12px;padding:0 2px;}.layui-iconpicker-page-count{display:inline-block;}.layui-iconpicker-page-operate{display:inline-block;float:right;cursor:default;}.layui-iconpicker-page-operate .layui-icon{font-size:12px;cursor:pointer;}.layui-iconpicker-body-page .layui-iconpicker-icon-limit{display:none;}.layui-iconpicker-body-page .layui-iconpicker-icon-limit:first-child{display:block;}'; + var $style = $('head').find('style[iconpicker]'); + if ($style.length === 0) { + $('head').append(''); + } + }, + /** + * 获取数据 + */ + getData: { + fontClass: function() { + var arr = ["layui-icon-rate-half", "layui-icon-rate", "layui-icon-rate-solid", + "layui-icon-cellphone", "layui-icon-vercode", "layui-icon-login-wechat", + "layui-icon-login-qq", "layui-icon-login-weibo", "layui-icon-password", + "layui-icon-username", "layui-icon-refresh-3", "layui-icon-auz", + "layui-icon-spread-left", "layui-icon-shrink-right", + "layui-icon-snowflake", "layui-icon-tips", "layui-icon-note", + "layui-icon-home", "layui-icon-senior", "layui-icon-refresh", + "layui-icon-refresh-1", "layui-icon-flag", "layui-icon-theme", + "layui-icon-notice", "layui-icon-website", "layui-icon-console", + "layui-icon-face-surprised", "layui-icon-set", "layui-icon-template-1", + "layui-icon-app", "layui-icon-template", "layui-icon-praise", + "layui-icon-tread", "layui-icon-male", "layui-icon-female", + "layui-icon-camera", "layui-icon-camera-fill", "layui-icon-more", + "layui-icon-more-vertical", "layui-icon-rmb", "layui-icon-dollar", + "layui-icon-diamond", "layui-icon-fire", "layui-icon-return", + "layui-icon-location", "layui-icon-read", "layui-icon-survey", + "layui-icon-face-smile", "layui-icon-face-cry", + "layui-icon-cart-simple", "layui-icon-cart", "layui-icon-next", + "layui-icon-prev", "layui-icon-upload-drag", "layui-icon-upload", + "layui-icon-download-circle", "layui-icon-component", + "layui-icon-file-b", "layui-icon-user", "layui-icon-find-fill", + "layui-icon-loading", "layui-icon-loading-1", "layui-icon-add-1", + "layui-icon-play", "layui-icon-pause", "layui-icon-headset", + "layui-icon-video", "layui-icon-voice", "layui-icon-speaker", + "layui-icon-fonts-del", "layui-icon-fonts-code", + "layui-icon-fonts-html", "layui-icon-fonts-strong", "layui-icon-unlink", + "layui-icon-picture", "layui-icon-link", "layui-icon-face-smile-b", + "layui-icon-align-left", "layui-icon-align-right", + "layui-icon-align-center", "layui-icon-fonts-u", "layui-icon-fonts-i", + "layui-icon-tabs", "layui-icon-radio", "layui-icon-circle", + "layui-icon-edit", "layui-icon-share", "layui-icon-delete", + "layui-icon-form", "layui-icon-cellphone-fine", "layui-icon-dialogue", + "layui-icon-fonts-clear", "layui-icon-layer", "layui-icon-date", + "layui-icon-water", "layui-icon-code-circle", "layui-icon-carousel", + "layui-icon-prev-circle", "layui-icon-layouts", "layui-icon-util", + "layui-icon-templeate-1", "layui-icon-upload-circle", "layui-icon-tree", + "layui-icon-table", "layui-icon-chart", "layui-icon-chart-screen", + "layui-icon-engine", "layui-icon-triangle-d", "layui-icon-triangle-r", + "layui-icon-file", "layui-icon-set-sm", "layui-icon-add-circle", + "layui-icon-404", "layui-icon-about", "layui-icon-up", + "layui-icon-down", "layui-icon-left", "layui-icon-right", + "layui-icon-circle-dot", "layui-icon-search", "layui-icon-set-fill", + "layui-icon-group", "layui-icon-friends", "layui-icon-reply-fill", + "layui-icon-menu-fill", "layui-icon-log", "layui-icon-picture-fine", + "layui-icon-face-smile-fine", "layui-icon-list", "layui-icon-release", + "layui-icon-ok", "layui-icon-help", "layui-icon-chat", "layui-icon-top", + "layui-icon-star", "layui-icon-star-fill", "layui-icon-close-fill", + "layui-icon-close", "layui-icon-ok-circle", "layui-icon-add-circle-fine" + ]; + return arr; + }, + unicode: function() { + return ["&#xe6c9;", "&#xe67b;", "&#xe67a;", "&#xe678;", + "&#xe679;", "&#xe677;", "&#xe676;", "&#xe675;", + "&#xe673;", "&#xe66f;", "&#xe9aa;", "&#xe672;", + "&#xe66b;", "&#xe668;", "&#xe6b1;", "&#xe702;", + "&#xe66e;", "&#xe68e;", "&#xe674;", "&#xe669;", + "&#xe666;", "&#xe66c;", "&#xe66a;", "&#xe667;", + "&#xe7ae;", "&#xe665;", "&#xe664;", "&#xe716;", + "&#xe656;", "&#xe653;", "&#xe663;", "&#xe6c6;", + "&#xe6c5;", "&#xe662;", "&#xe661;", "&#xe660;", + "&#xe65d;", "&#xe65f;", "&#xe671;", "&#xe65e;", + "&#xe659;", "&#xe735;", "&#xe756;", "&#xe65c;", + "&#xe715;", "&#xe705;", "&#xe6b2;", "&#xe6af;", + "&#xe69c;", "&#xe698;", "&#xe657;", "&#xe65b;", + "&#xe65a;", "&#xe681;", "&#xe67c;", "&#xe601;", + "&#xe857;", "&#xe655;", "&#xe770;", "&#xe670;", + "&#xe63d;", "&#xe63e;", "&#xe654;", "&#xe652;", + "&#xe651;", "&#xe6fc;", "&#xe6ed;", "&#xe688;", + "&#xe645;", "&#xe64f;", "&#xe64e;", "&#xe64b;", + "&#xe62b;", "&#xe64d;", "&#xe64a;", "&#xe64c;", + "&#xe650;", "&#xe649;", "&#xe648;", "&#xe647;", + "&#xe646;", "&#xe644;", "&#xe62a;", "&#xe643;", + "&#xe63f;", "&#xe642;", "&#xe641;", "&#xe640;", + "&#xe63c;", "&#xe63b;", "&#xe63a;", "&#xe639;", + "&#xe638;", "&#xe637;", "&#xe636;", "&#xe635;", + "&#xe634;", "&#xe633;", "&#xe632;", "&#xe631;", + "&#xe630;", "&#xe62f;", "&#xe62e;", "&#xe62d;", + "&#xe62c;", "&#xe629;", "&#xe628;", "&#xe625;", + "&#xe623;", "&#xe621;", "&#xe620;", "&#xe61f;", + "&#xe61c;", "&#xe60b;", "&#xe619;", "&#xe61a;", + "&#xe603;", "&#xe602;", "&#xe617;", "&#xe615;", + "&#xe614;", "&#xe613;", "&#xe612;", "&#xe611;", + "&#xe60f;", "&#xe60e;", "&#xe60d;", "&#xe60c;", + "&#xe60a;", "&#xe609;", "&#xe605;", "&#xe607;", + "&#xe606;", "&#xe604;", "&#xe600;", "&#xe658;", + "&#x1007;", "&#x1006;", "&#x1005;", "&#xe608;" + ]; + } + } + }; + + a.init(); + return new IconPicker(); + }; + + /** + * 选中图标 + * @param filter lay-filter + * @param iconName 图标名称,自动识别fontClass/unicode + */ + IconPicker.prototype.checkIcon = function(filter, iconName) { + var el = $('*[lay-filter=' + filter + ']'), + p = el.next().find('.layui-iconpicker-item .layui-icon'), + c = iconName; + + if (c.indexOf('#xe') > 0) { + p.html(c); + } else { + p.html('').attr('class', 'layui-icon ' + c); + } + el.attr('value', c).val(c); + }; + + var iconPicker = new IconPicker(); + exports(_MOD, iconPicker); +}); diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/notice.js b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/notice.js new file mode 100644 index 0000000000000000000000000000000000000000..4ea67ec8b3e784abd5b28d103042bd3499bdaf2d --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/notice.js @@ -0,0 +1,489 @@ + +(function(define) { + define(['jquery'], function($) { + return (function() { + var $container; + var listener; + var toastId = 0; + var toastType = { + error: 'error', + info: 'info', + success: 'success', + warning: 'warning' + }; + + var cssStyle = $( + '' + ); + $("body").append(cssStyle); + + var toastr = { + clear: clear, + remove: remove, + error: error, + getContainer: getContainer, + info: info, + options: {}, + subscribe: subscribe, + success: success, + version: '2.1.4', + warning: warning + }; + + var previousToast; + + return toastr; + + function error(message, title, optionsOverride) { + return notify({ + type: toastType.error, + iconClass: getOptions().iconClasses.error, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function getContainer(options, create) { + if (!options) { + options = getOptions(); + } + $container = $('#' + options.containerId); + if ($container.length) { + return $container; + } + if (create) { + $container = createContainer(options); + } + return $container; + } + + function info(message, title, optionsOverride) { + return notify({ + type: toastType.info, + iconClass: getOptions().iconClasses.info, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function subscribe(callback) { + listener = callback; + } + + function success(message, title, optionsOverride) { + return notify({ + type: toastType.success, + iconClass: getOptions().iconClasses.success, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function warning(message, title, optionsOverride) { + return notify({ + type: toastType.warning, + iconClass: getOptions().iconClasses.warning, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function clear($toastElement, clearOptions) { + var options = getOptions(); + if (!$container) { + getContainer(options); + } + if (!clearToast($toastElement, options, clearOptions)) { + clearContainer(options); + } + } + + function remove($toastElement) { + var options = getOptions(); + if (!$container) { + getContainer(options); + } + if ($toastElement && $(':focus', $toastElement).length === 0) { + removeToast($toastElement); + return; + } + if ($container.children().length) { + $container.remove(); + } + } + + // internal functions + + function clearContainer(options) { + var toastsToClear = $container.children(); + for (var i = toastsToClear.length - 1; i >= 0; i--) { + clearToast($(toastsToClear[i]), options); + } + } + + function clearToast($toastElement, options, clearOptions) { + var force = clearOptions && clearOptions.force ? clearOptions.force : false; + if ($toastElement && (force || $(':focus', $toastElement).length === 0)) { + $toastElement[options.hideMethod]({ + duration: options.hideDuration, + easing: options.hideEasing, + complete: function() { + removeToast($toastElement); + } + }); + return true; + } + return false; + } + + function createContainer(options) { + $container = $('
                                                                                                                  ') + .attr('id', options.containerId) + .addClass(options.positionClass); + + $container.appendTo($(options.target)); + return $container; + } + + function getDefaults() { + return { + tapToDismiss: true, + toastClass: 'toast', + containerId: 'toast-container', + debug: false, + + showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery + showDuration: 300, + showEasing: 'swing', //swing and linear are built into jQuery + onShown: undefined, + hideMethod: 'fadeOut', + hideDuration: 1000, + hideEasing: 'swing', + onHidden: undefined, + closeMethod: false, + closeDuration: false, + closeEasing: false, + closeOnHover: true, + + extendedTimeOut: 1000, + iconClasses: { + error: 'toast-error', + info: 'toast-info', + success: 'toast-success', + warning: 'toast-warning' + }, + iconClass: 'toast-info', + positionClass: 'toast-top-right', + timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky + titleClass: 'toast-title', + messageClass: 'toast-message', + escapeHtml: false, + target: 'body', + closeHtml: '', + closeClass: 'toast-close-button', + newestOnTop: true, + preventDuplicates: false, + progressBar: false, + progressClass: 'toast-progress', + rtl: false + }; + } + + function publish(args) { + if (!listener) { + return; + } + listener(args); + } + + function notify(map) { + var options = getOptions(); + var iconClass = map.iconClass || options.iconClass; + + if (typeof(map.optionsOverride) !== 'undefined') { + options = $.extend(options, map.optionsOverride); + iconClass = map.optionsOverride.iconClass || iconClass; + } + + if (shouldExit(options, map)) { + return; + } + + toastId++; + + $container = getContainer(options, true); + + var intervalId = null; + var $toastElement = $('
                                                                                                                  '); + var $titleElement = $('
                                                                                                                  '); + var $messageElement = $('
                                                                                                                  '); + var $progressElement = $('
                                                                                                                  '); + var $closeElement = $(options.closeHtml); + var progressBar = { + intervalId: null, + hideEta: null, + maxHideTime: null + }; + var response = { + toastId: toastId, + state: 'visible', + startTime: new Date(), + options: options, + map: map + }; + + personalizeToast(); + + displayToast(); + + handleEvents(); + + publish(response); + + if (options.debug && console) { + console.log(response); + } + + return $toastElement; + + function escapeHtml(source) { + if (source == null) { + source = ''; + } + + return source + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); + } + + function personalizeToast() { + setIcon(); + setTitle(); + setMessage(); + setCloseButton(); + setProgressBar(); + setRTL(); + setSequence(); + setAria(); + } + + function setAria() { + var ariaValue = ''; + switch (map.iconClass) { + case 'toast-success': + case 'toast-info': + ariaValue = 'polite'; + break; + default: + ariaValue = 'assertive'; + } + $toastElement.attr('aria-live', ariaValue); + } + + function handleEvents() { + if (options.closeOnHover) { + $toastElement.hover(stickAround, delayedHideToast); + } + + if (!options.onclick && options.tapToDismiss) { + $toastElement.click(hideToast); + } + + if (options.closeButton && $closeElement) { + $closeElement.click(function(event) { + if (event.stopPropagation) { + event.stopPropagation(); + } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) { + event.cancelBubble = true; + } + + if (options.onCloseClick) { + options.onCloseClick(event); + } + + hideToast(true); + }); + } + + if (options.onclick) { + $toastElement.click(function(event) { + options.onclick(event); + hideToast(); + }); + } + } + + function displayToast() { + $toastElement.hide(); + + $toastElement[options.showMethod]({ + duration: options.showDuration, + easing: options.showEasing, + complete: options.onShown + }); + + if (options.timeOut > 0) { + intervalId = setTimeout(hideToast, options.timeOut); + progressBar.maxHideTime = parseFloat(options.timeOut); + progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; + if (options.progressBar) { + progressBar.intervalId = setInterval(updateProgress, 10); + } + } + } + + function setIcon() { + if (map.iconClass) { + $toastElement.addClass(options.toastClass).addClass(iconClass); + } + } + + function setSequence() { + if (options.newestOnTop) { + $container.prepend($toastElement); + } else { + $container.append($toastElement); + } + } + + function setTitle() { + if (map.title) { + var suffix = map.title; + if (options.escapeHtml) { + suffix = escapeHtml(map.title); + } + $titleElement.append(suffix).addClass(options.titleClass); + $toastElement.append($titleElement); + } + } + + function setMessage() { + if (map.message) { + var suffix = map.message; + if (options.escapeHtml) { + suffix = escapeHtml(map.message); + } + $messageElement.append(suffix).addClass(options.messageClass); + $toastElement.append($messageElement); + } + } + + function setCloseButton() { + if (options.closeButton) { + $closeElement.addClass(options.closeClass).attr('role', 'button'); + $toastElement.prepend($closeElement); + } + } + + function setProgressBar() { + if (options.progressBar) { + $progressElement.addClass(options.progressClass); + $toastElement.prepend($progressElement); + } + } + + function setRTL() { + if (options.rtl) { + $toastElement.addClass('rtl'); + } + } + + function shouldExit(options, map) { + if (options.preventDuplicates) { + if (map.message === previousToast) { + return true; + } else { + previousToast = map.message; + } + } + return false; + } + + function hideToast(override) { + var method = override && options.closeMethod !== false ? options.closeMethod : options.hideMethod; + var duration = override && options.closeDuration !== false ? + options.closeDuration : options.hideDuration; + var easing = override && options.closeEasing !== false ? options.closeEasing : options.hideEasing; + if ($(':focus', $toastElement).length && !override) { + return; + } + clearTimeout(progressBar.intervalId); + return $toastElement[method]({ + duration: duration, + easing: easing, + complete: function() { + removeToast($toastElement); + clearTimeout(intervalId); + if (options.onHidden && response.state !== 'hidden') { + options.onHidden(); + } + response.state = 'hidden'; + response.endTime = new Date(); + publish(response); + } + }); + } + + function delayedHideToast() { + if (options.timeOut > 0 || options.extendedTimeOut > 0) { + intervalId = setTimeout(hideToast, options.extendedTimeOut); + progressBar.maxHideTime = parseFloat(options.extendedTimeOut); + progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; + } + } + + function stickAround() { + clearTimeout(intervalId); + progressBar.hideEta = 0; + $toastElement.stop(true, true)[options.showMethod]({ + duration: options.showDuration, + easing: options.showEasing + }); + } + + function updateProgress() { + var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100; + $progressElement.width(percentage + '%'); + } + } + + function getOptions() { + return $.extend({}, getDefaults(), toastr.options); + } + + function removeToast($toastElement) { + if (!$container) { + $container = getContainer(); + } + if ($toastElement.is(':visible')) { + return; + } + $toastElement.remove(); + $toastElement = null; + if ($container.children().length === 0) { + $container.remove(); + previousToast = undefined; + } + } + + })(); + }); +}(typeof define === 'function' && define.amd ? define : function(deps, factory) { + if (typeof module !== 'undefined' && module.exports) { //Node + module.exports = factory(require('jquery')); + } else if (window.layui && layui.define) { + layui.define('jquery', function(exports) { //layui加载 + exports('toastr', factory(layui.jquery)); + exports('notice', factory(layui.jquery)); + }); + } else { + window.toastr = factory(window.jQuery); + } +})); diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/theme.js b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/theme.js new file mode 100644 index 0000000000000000000000000000000000000000..c7b3abfd96bd6be08afdd278d976151552b2f74a --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/theme.js @@ -0,0 +1,110 @@ +layui.define(["jquery","layer"], function (exports) { + var MOD_NAME = 'theme', + $ = layui.jquery; + + var theme = {}; + theme.autoHead = false; + + theme.changeTheme = function (target, autoHead) { + this.autoHead = autoHead; + var color = localStorage.getItem("theme-color-color"); + var second = localStorage.getItem("theme-color-second"); + this.colorSet(color, second); + if (target.frames.length == 0) return; + for (var i = 0; i < target.frames.length; i++) { + try { + if(target.frames[i].layui == undefined) continue; + target.frames[i].layui.theme.changeTheme(target.frames[i], autoHead); + } + catch (error) { + console.log(error); + } + } + } + + theme.colorSet = function(color, second) { + var style = ''; + style += '.light-theme .pear-nav-tree .layui-this a:hover,.light-theme .pear-nav-tree .layui-this,.light-theme .pear-nav-tree .layui-this a,.pear-nav-tree .layui-this a,.pear-nav-tree .layui-this{background-color: ' +color + '!important;}'; + style += '.pear-admin .layui-logo .title{color:' + color + '!important;}'; + style += '.pear-frame-title .dot,.pear-tab .layui-this .pear-tab-active{background-color: ' + color +'!important;}'; + style += '.bottom-nav li a:hover{background-color:' + color + '!important;}'; + style += '.pear-btn-primary {border: 1px solid ' + color + '!important;}'; + style += '.pear-admin .layui-header .layui-nav .layui-nav-bar{background-color: ' + color + '!important;}' + style += '.ball-loader>span,.signal-loader>span {background-color: ' + color + '!important;}'; + style += '.layui-header .layui-nav-child .layui-this a{background-color:' + color +'!important;color:white!important;}'; + style += '#preloader{background-color:' + color + '!important;}'; + style += '.pearone-color .color-content li.layui-this:after, .pearone-color .color-content li:hover:after {border: ' +color + ' 3px solid!important;}'; + style += '.layui-nav .layui-nav-child dd.layui-this a, .layui-nav-child dd.layui-this{background-color:' + color + ';color:white;}'; + style += '.pear-social-entrance {background-color:' + color + '!important}'; + style += '.pear-admin .pe-collapse {background-color:' + color + '!important}'; + style += '.layui-fixbar li {background-color:' + color + '!important}'; + style += '.pear-btn-primary {background-color:' + color + '!important}'; + style += '.layui-input:focus,.layui-textarea:focus {border-color: ' + color + '!important;box-shadow: 0 0 0 3px ' + second + ' !important;}' + style += '.layui-form-checkbox[lay-skin=primary]:hover span {background-color: initial;}' + style += '.layui-form-checked[lay-skin=primary] i {border-color: ' + color + '!important;background-color: ' + color + ';}' + style += '.layui-form-checked,.layui-form-checked:hover {border-color: ' + color + '!important;}' + style += '.layui-form-checked span,.layui-form-checked:hover span {background-color: ' + color + ';}' + style += '.layui-form-checked i,.layui-form-checked:hover i {color: ' + color + ';}' + style += '.layui-form-onswitch { border-color: ' + color + '; background-color: ' + color + ';}' + style += '.layui-form-radio>i:hover, .layui-form-radioed>i {color: ' + color + ';}' + style += '.layui-laypage .layui-laypage-curr .layui-laypage-em{background-color:'+ color +'!important}' + style += '.layui-tab-brief>.layui-tab-more li.layui-this:after, .layui-tab-brief>.layui-tab-title .layui-this:after{border-bottom: 3px solid '+color+'!important}' + style += '.layui-tab-brief>.layui-tab-title .layui-this{color:'+color+'!important}' + style += '.layui-progress-bar{background-color:'+color+'}'; + style += '.layui-elem-quote{border-left: 5px solid '+ color +'}'; + style += '.layui-timeline-axis{color:' + color + '}'; + style += '.layui-laydate .layui-this, .layui-laydate .layui-this div{background-color:'+color+'!important}';//变更 + style += 'xm-select .xm-label .xm-label-block{background-color:'+color+'!important}';//变更 + style += 'xm-select{border-color:#EEE !important}';//变更 + style += 'xm-select .xm-body .xm-option.selected .xm-option-icon{border-color:'+color+'!important;color:'+color+'!important;}';//变更 + style += 'xm-select .xm-body .xm-option .xm-option-icon{border-color:'+color+'!important;}';//变更 + style += 'xm-select > .xm-body .xm-option.selected.hide-icon{background-color:'+color+'!important;}';//变更 + style += 'xm-select > .xm-body .xm-toolbar .toolbar-tag:hover{color:'+color+'!important;}';//变更 + style += '.layui-layer-dialog .layui-layer-content .layui-icon-ok{color:'+color+'!important;}';//变更 + style += '.layui-layer-dialog .layui-layer-content .layui-icon-ok{color:'+color+'!important;}';//变更 + style += 'a{color:'+color+';opacity:.8}';//变更 + style += 'a:hover{color:'+color+';opacity:1}';//变更 + style += '.pear-this,.pear-text{color:' + color + '!important}'; + style += '.pear-back{background-color:'+ color +'!important}'; + style += '.pear-collapsed-pe{background-color:'+color+'!important}' + style += '.layui-form-select dl dd.layui-this{color:'+color+'!important;}' + style += '.tag-item-normal{background:'+color+'!important}'; + style += '.step-item-head.step-item-head-active{background-color:'+color+'}' + style += '.step-item-head{border: 3px solid '+color+';}' + style += '.step-item-tail i{background-color:'+color+'}' + style += '.step-item-head{color:' + color + '}' + style += 'div[xm-select-skin=normal] .xm-select-title div.xm-select-label>span i {background-color:'+color+'!important}' + style += 'div[xm-select-skin=normal] .xm-select-title div.xm-select-label>span{border: 1px solid '+color+'!important;background-color:'+color+'!important}' + style += 'div[xm-select-skin=normal] dl dd:not(.xm-dis-disabled) i{border-color:'+color+'!important}' + style += 'div[xm-select-skin=normal] dl dd.xm-select-this:not(.xm-dis-disabled) i{color:'+color+'!important}' + style += 'div[xm-select-skin=normal].xm-form-selected .xm-select, div[xm-select-skin=normal].xm-form-selected .xm-select:hover{border-color:'+color+'!important}' + style += '.layui-layer-btn a:first-child{border-color:'+color+';background-color:'+color+'!important}'; + style += '.layui-form-checkbox[lay-skin=primary]:hover i{border-color:'+color+'!important}' + style += '.pear-tab-menu .item:hover{background-color:'+color+'!important}' + style += '.layui-form-danger:focus {border-color:#FF5722 !important}' + style += '.pear-admin .user .layui-this a:hover{color:white!important}' + style += '.pear-admin .user a:hover{color:'+color+'!important}' + style += '.pear-notice .layui-this{color:'+color+'!important}' + style += '.layui-form-radio:hover *, .layui-form-radioed, .layui-form-radioed>i{color:' + color + ' !important}'; + style += '.pear-btn:hover {color: '+color+';background-color: ' + second + ';}' + style += '.pear-btn-primary[plain] {color: '+ color +' !important;background: ' + second + ' !important;}' + style += '.pear-btn-primary[plain]:hover {background-color: ' + color + '!important}' + style += '.light-theme .pear-nav-tree .layui-this a:hover,.light-theme .pear-nav-tree .layui-this,.light-theme .pear-nav-tree .layui-this a {background-color:'+second+'!important;color:'+color+'!important;}' + style += '.light-theme .pear-nav-tree .layui-this{ border-right: 3px solid '+color+'!important}' + style += '.loader:after {background:'+color+'}' + if(this.autoHead === true || this.autoHead === "true"){ + style += '.pear-admin.banner-layout .layui-header .layui-logo,.pear-admin .layui-header{border:none;background-color:' + color + '!important;}.pear-admin.banner-layout .layui-header .layui-logo .title,.pear-admin .layui-header .layui-nav .layui-nav-item>a{color:whitesmoke!important;}'; + style += '.pear-admin.banner-layout .layui-header{ box-shadow: 2px 0 6px rgb(0 21 41 / 35%) }' + style += '.pear-admin .layui-header .layui-layout-control .layui-this *,.pear-admin.banner-layout .layui-header .layui-layout-control .layui-this *{ background-color: rgba(0,0,0,.1)!important;}' + } + style += '.menu-search-list li:hover,.menu-search-list li.this{background-color:'+ color +'}' + var colorPane = $("#pear-admin-color"); + if(colorPane.length>0){ + colorPane.html(style); + }else{ + $("head").append("") + } + } + + exports(MOD_NAME, theme); +}); \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/other/xm-select.js b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/xm-select.js new file mode 100644 index 0000000000000000000000000000000000000000..bf44849bf313c152fa1791603e016719ff54e83f --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/other/xm-select.js @@ -0,0 +1,8 @@ +/*! + * @Title: xm-select + * @Version: 1.2.4 + * @Description:基于layui的多选解决方案 + * @Site: https://gitee.com/maplemei/xm-select + * @Author: maplemei + * @License:Apache License 2.0 + */!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="./",n(n.s=214)}({1:function(e,t,n){"use strict";function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e){return function(e){if(Array.isArray(e))return a(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return a(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return a(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,o=new Array(t);n1&&void 0!==arguments[1]?arguments[1]:100,n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],o=this,r=!1;return function(){for(var i=arguments.length,a=new Array(i),l=0;l>>0;for(t&&(n=t),o=new Array(a),r=0;r>>0;if("function"!=typeof e)throw new TypeError(e+" is not a function");for(arguments.length>1&&(n=t),o=0;o>>0;if("function"!=typeof e)throw new TypeError;for(var o=[],r=arguments[1],i=0;i>>0,r=arguments[1],i=0;i .xm-tips {\n color: #999999;\n padding: 0 10px;\n position: absolute;\n display: flex;\n height: 100%;\n align-items: center;\n}\nxm-select > .xm-icon {\n display: inline-block;\n overflow: hidden;\n position: absolute;\n width: 0;\n height: 0;\n right: 10px;\n top: 50%;\n margin-top: -3px;\n cursor: pointer;\n border: 6px dashed transparent;\n border-top-color: #C2C2C2;\n border-top-style: solid;\n transition: all 0.3s;\n -webkit-transition: all 0.3s;\n}\nxm-select > .xm-icon-expand {\n margin-top: -9px;\n transform: rotate(180deg);\n}\nxm-select > .xm-label.single-row {\n position: absolute;\n top: 0;\n bottom: 0px;\n left: 0px;\n right: 30px;\n overflow: auto hidden;\n}\nxm-select > .xm-label.single-row .scroll {\n overflow-y: hidden;\n}\nxm-select > .xm-label.single-row .label-content {\n flex-wrap: nowrap;\n white-space: nowrap;\n}\nxm-select > .xm-label.auto-row .label-content {\n flex-wrap: wrap;\n padding-right: 30px !important;\n}\nxm-select > .xm-label.auto-row .xm-label-block > span {\n white-space: unset;\n height: 100%;\n}\nxm-select > .xm-label .scroll .label-content {\n display: flex;\n padding: 3px 10px;\n}\nxm-select > .xm-label .xm-label-block {\n display: flex;\n position: relative;\n padding: 0px 5px;\n margin: 2px 5px 2px 0;\n border-radius: 3px;\n align-items: baseline;\n color: #FFF;\n}\nxm-select > .xm-label .xm-label-block > span {\n display: flex;\n color: #FFF;\n white-space: nowrap;\n}\nxm-select > .xm-label .xm-label-block > i {\n color: #FFF;\n margin-left: 8px;\n font-size: 12px;\n cursor: pointer;\n display: flex;\n}\nxm-select > .xm-label .xm-label-block.disabled {\n background-color: #C2C2C2 !important;\n cursor: no-drop !important;\n}\nxm-select > .xm-label .xm-label-block.disabled > i {\n cursor: no-drop !important;\n}\nxm-select > .xm-body {\n position: absolute;\n left: 0;\n top: 42px;\n padding: 5px 0;\n z-index: 999;\n width: 100%;\n min-width: fit-content;\n border: 1px solid #E6E6E6;\n background-color: #fff;\n border-radius: 2px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);\n animation-name: xm-upbit;\n animation-duration: 0.3s;\n animation-fill-mode: both;\n}\nxm-select > .xm-body .scroll-body {\n overflow-x: hidden;\n overflow-y: auto;\n}\nxm-select > .xm-body .scroll-body::-webkit-scrollbar {\n width: 8px;\n}\nxm-select > .xm-body .scroll-body::-webkit-scrollbar-track {\n -webkit-border-radius: 2em;\n -moz-border-radius: 2em;\n -ms-border-radius: 2em;\n border-radius: 2em;\n background-color: #FFF;\n}\nxm-select > .xm-body .scroll-body::-webkit-scrollbar-thumb {\n -webkit-border-radius: 2em;\n -moz-border-radius: 2em;\n -ms-border-radius: 2em;\n border-radius: 2em;\n background-color: #C2C2C2;\n}\nxm-select > .xm-body.up {\n top: auto;\n bottom: 42px;\n}\nxm-select > .xm-body.relative {\n position: relative;\n display: block !important;\n top: 0;\n box-shadow: none;\n border: none;\n animation-name: none;\n animation-duration: 0;\n min-width: 100%;\n}\nxm-select > .xm-body .xm-group {\n cursor: default;\n}\nxm-select > .xm-body .xm-group-item {\n display: inline-block;\n cursor: pointer;\n padding: 0 10px;\n color: #999;\n font-size: 12px;\n}\nxm-select > .xm-body .xm-option {\n display: flex;\n align-items: center;\n position: relative;\n padding: 0 10px;\n cursor: pointer;\n}\nxm-select > .xm-body .xm-option-icon {\n color: transparent;\n display: flex;\n border: 1px solid #E6E6E6;\n border-radius: 3px;\n justify-content: center;\n align-items: center;\n}\nxm-select > .xm-body .xm-option-icon.xm-custom-icon {\n color: unset;\n border: unset;\n}\nxm-select > .xm-body .xm-option-icon-hidden {\n margin-right: -10px;\n}\nxm-select > .xm-body .xm-option-icon.xm-icon-danx {\n border-radius: 100%;\n}\nxm-select > .xm-body .xm-option-content {\n display: flex;\n position: relative;\n padding-left: 15px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n color: #666;\n width: calc(100% - 20px);\n}\nxm-select > .xm-body .xm-option.hide-icon .xm-option-content {\n padding-left: 0;\n}\nxm-select > .xm-body .xm-option.selected.hide-icon .xm-option-content {\n color: #FFF !important;\n}\nxm-select > .xm-body .xm-option .loader {\n width: 0.8em;\n height: 0.8em;\n margin-right: 6px;\n color: #C2C2C2;\n}\nxm-select > .xm-body .xm-select-empty {\n text-align: center;\n color: #999;\n}\nxm-select > .xm-body .disabled {\n cursor: no-drop;\n}\nxm-select > .xm-body .disabled:hover {\n background-color: #FFF;\n}\nxm-select > .xm-body .disabled .xm-option-icon {\n border-color: #C2C2C2 !important;\n}\nxm-select > .xm-body .disabled .xm-option-content {\n color: #C2C2C2 !important;\n}\nxm-select > .xm-body .disabled.selected > .xm-option-icon {\n color: #C2C2C2 !important;\n}\nxm-select > .xm-body .xm-search {\n background-color: #FFF !important;\n position: relative;\n padding: 0 10px;\n margin-bottom: 5px;\n cursor: pointer;\n}\nxm-select > .xm-body .xm-search > i {\n position: absolute;\n color: #666;\n}\nxm-select > .xm-body .xm-search-input {\n border: none;\n border-bottom: 1px solid #E6E6E6;\n padding-left: 27px;\n cursor: text;\n}\nxm-select > .xm-body .xm-paging {\n padding: 0 10px;\n display: flex;\n margin-top: 5px;\n}\nxm-select > .xm-body .xm-paging > span:first-child {\n border-radius: 2px 0 0 2px;\n}\nxm-select > .xm-body .xm-paging > span:last-child {\n border-radius: 0 2px 2px 0;\n}\nxm-select > .xm-body .xm-paging > span {\n display: flex;\n flex: auto;\n justify-content: center;\n vertical-align: middle;\n margin: 0 -1px 0 0;\n background-color: #fff;\n color: #333;\n font-size: 12px;\n border: 1px solid #e2e2e2;\n flex-wrap: nowrap;\n width: 100%;\n overflow: hidden;\n min-width: 50px;\n}\nxm-select > .xm-body .xm-toolbar {\n padding: 0 10px;\n display: flex;\n margin: -3px 0;\n cursor: default;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag {\n cursor: pointer;\n display: flex;\n margin-right: 20px;\n color: #666;\n align-items: baseline;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag:hover {\n opacity: 0.8;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag:active {\n opacity: 1;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag > i {\n margin-right: 2px;\n font-size: 14px;\n}\nxm-select > .xm-body .xm-toolbar .toolbar-tag:last-child {\n margin-right: 0;\n}\nxm-select > .xm-body .xm-body-custom {\n line-height: initial;\n cursor: default;\n}\nxm-select > .xm-body .xm-body-custom * {\n box-sizing: initial;\n}\nxm-select > .xm-body .xm-tree {\n position: relative;\n}\nxm-select > .xm-body .xm-tree-icon {\n display: inline-block;\n margin-right: 3px;\n cursor: pointer;\n border: 6px dashed transparent;\n border-left-color: #C2C2C2;\n border-left-style: solid;\n transition: all 0.3s;\n -webkit-transition: all 0.3s;\n z-index: 2;\n visibility: hidden;\n}\nxm-select > .xm-body .xm-tree-icon.expand {\n margin-top: 3px;\n margin-right: 5px;\n margin-left: -2px;\n transform: rotate(90deg);\n}\nxm-select > .xm-body .xm-tree-icon.xm-visible {\n visibility: visible;\n}\nxm-select > .xm-body .xm-tree .left-line {\n position: absolute;\n left: 13px;\n width: 0;\n z-index: 1;\n border-left: 1px dotted #c0c4cc !important;\n}\nxm-select > .xm-body .xm-tree .top-line {\n position: absolute;\n left: 13px;\n height: 0;\n z-index: 1;\n border-top: 1px dotted #c0c4cc !important;\n}\nxm-select > .xm-body .xm-tree .xm-tree-icon + .top-line {\n margin-left: 1px;\n}\nxm-select > .xm-body .scroll-body > .xm-tree > .xm-option > .top-line,\nxm-select > .xm-body .scroll-body > .xm-option > .top-line {\n width: 0 !important;\n}\nxm-select > .xm-body .xm-cascader-box {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n padding: 5px 0;\n border: 1px solid #E6E6E6;\n background-color: #fff;\n border-radius: 2px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);\n margin: -1px;\n}\nxm-select > .xm-body .xm-cascader-box::before {\n content: ' ';\n position: absolute;\n width: 0;\n height: 0;\n border: 6px solid transparent;\n border-right-color: #E6E6E6;\n top: 10px;\n left: -12px;\n}\nxm-select > .xm-body .xm-cascader-box::after {\n content: ' ';\n position: absolute;\n width: 0;\n height: 0;\n border: 6px solid transparent;\n border-right-color: #fff;\n top: 10px;\n left: -11px;\n}\nxm-select > .xm-body .xm-cascader-scroll {\n height: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n}\nxm-select > .xm-body.cascader {\n width: unset;\n min-width: unset;\n}\nxm-select > .xm-body.cascader .xm-option-content {\n padding-left: 8px;\n}\nxm-select > .xm-body.cascader .disabled .xm-right-arrow {\n color: #C2C2C2 !important;\n}\nxm-select > .xm-body.cascader .hide-icon.disabled .xm-right-arrow {\n color: #999 !important;\n}\nxm-select .xm-input {\n cursor: pointer;\n border-radius: 2px;\n border-width: 1px;\n border-style: solid;\n border-color: #E6E6E6;\n display: block;\n width: 100%;\n box-sizing: border-box;\n background-color: #FFF;\n line-height: 1.3;\n padding-left: 10px;\n outline: 0;\n user-select: text;\n -ms-user-select: text;\n -moz-user-select: text;\n -webkit-user-select: text;\n}\nxm-select .dis {\n display: none;\n}\nxm-select .loading {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(255, 255, 255, 0.6);\n display: flex;\n align-items: center;\n justify-content: center;\n}\nxm-select .loader {\n border: 0.2em dotted currentcolor;\n border-radius: 50%;\n -webkit-animation: 1s loader linear infinite;\n animation: 1s loader linear infinite;\n display: inline-block;\n width: 1em;\n height: 1em;\n color: inherit;\n vertical-align: middle;\n pointer-events: none;\n}\nxm-select .xm-select-default {\n position: absolute;\n width: 100%;\n height: 100%;\n border: none;\n visibility: hidden;\n}\nxm-select .xm-select-disabled {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n cursor: no-drop;\n z-index: 2;\n opacity: 0.3;\n background-color: #FFF;\n}\nxm-select .item--divided {\n border-top: 1px solid #ebeef5;\n width: calc(100% - 20px);\n cursor: initial;\n}\nxm-select .xm-right-arrow {\n position: absolute;\n color: #666;\n right: 5px;\n top: -1px;\n font-weight: 700;\n transform: scale(0.6, 1);\n}\nxm-select .xm-right-arrow::after {\n content: '>';\n}\nxm-select[size='large'] {\n min-height: 40px;\n line-height: 40px;\n}\nxm-select[size='large'] .xm-input {\n height: 40px;\n}\nxm-select[size='large'] .xm-label .scroll .label-content {\n line-height: 34px;\n}\nxm-select[size='large'] .xm-label .xm-label-block {\n height: 30px;\n line-height: 30px;\n}\nxm-select[size='large'] .xm-body .xm-option .xm-option-icon {\n height: 20px;\n width: 20px;\n font-size: 20px;\n}\nxm-select[size='large'] .xm-paging > span {\n height: 34px;\n line-height: 34px;\n}\nxm-select[size='large'] .xm-tree .left-line {\n height: 100%;\n bottom: 20px;\n}\nxm-select[size='large'] .xm-tree .left-line-group {\n height: calc(100% - 40px);\n}\nxm-select[size='large'] .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 19px;\n}\nxm-select[size='large'] .item--divided {\n margin: 10px;\n}\nxm-select {\n min-height: 36px;\n line-height: 36px;\n}\nxm-select .xm-input {\n height: 36px;\n}\nxm-select .xm-label .scroll .label-content {\n line-height: 30px;\n}\nxm-select .xm-label .xm-label-block {\n height: 26px;\n line-height: 26px;\n}\nxm-select .xm-body .xm-option .xm-option-icon {\n height: 18px;\n width: 18px;\n font-size: 18px;\n}\nxm-select .xm-paging > span {\n height: 30px;\n line-height: 30px;\n}\nxm-select .xm-tree .left-line {\n height: 100%;\n bottom: 18px;\n}\nxm-select .xm-tree .left-line-group {\n height: calc(100% - 36px);\n}\nxm-select .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 17px;\n}\nxm-select .item--divided {\n margin: 9px;\n}\nxm-select[size='small'] {\n min-height: 32px;\n line-height: 32px;\n}\nxm-select[size='small'] .xm-input {\n height: 32px;\n}\nxm-select[size='small'] .xm-label .scroll .label-content {\n line-height: 26px;\n}\nxm-select[size='small'] .xm-label .xm-label-block {\n height: 22px;\n line-height: 22px;\n}\nxm-select[size='small'] .xm-body .xm-option .xm-option-icon {\n height: 16px;\n width: 16px;\n font-size: 16px;\n}\nxm-select[size='small'] .xm-paging > span {\n height: 26px;\n line-height: 26px;\n}\nxm-select[size='small'] .xm-tree .left-line {\n height: 100%;\n bottom: 16px;\n}\nxm-select[size='small'] .xm-tree .left-line-group {\n height: calc(100% - 32px);\n}\nxm-select[size='small'] .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 15px;\n}\nxm-select[size='small'] .item--divided {\n margin: 8px;\n}\nxm-select[size='mini'] {\n min-height: 28px;\n line-height: 28px;\n}\nxm-select[size='mini'] .xm-input {\n height: 28px;\n}\nxm-select[size='mini'] .xm-label .scroll .label-content {\n line-height: 22px;\n}\nxm-select[size='mini'] .xm-label .xm-label-block {\n height: 18px;\n line-height: 18px;\n}\nxm-select[size='mini'] .xm-body .xm-option .xm-option-icon {\n height: 14px;\n width: 14px;\n font-size: 14px;\n}\nxm-select[size='mini'] .xm-paging > span {\n height: 22px;\n line-height: 22px;\n}\nxm-select[size='mini'] .xm-tree .left-line {\n height: 100%;\n bottom: 14px;\n}\nxm-select[size='mini'] .xm-tree .left-line-group {\n height: calc(100% - 28px);\n}\nxm-select[size='mini'] .xm-tree .xm-tree-icon.xm-hidden + .top-line {\n top: 13px;\n}\nxm-select[size='mini'] .item--divided {\n margin: 7px;\n}\n.layui-form-pane xm-select {\n margin: -1px -1px -1px 0;\n}\n",""]),e.exports=t},221:function(e,t){(function(t){e.exports=t}).call(this,{})},27:function(e,t,n){"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",o=e[3];if(!o)return n;if(t&&"function"==typeof btoa){var r=function(e){var t=btoa(unescape(encodeURIComponent(JSON.stringify(e)))),n="sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(t);return"/*# ".concat(n," */")}(o),i=o.sources.map((function(e){return"/*# sourceURL=".concat(o.sourceRoot||"").concat(e," */")}));return[n].concat(i).concat([r]).join("\n")}return[n].join("\n")}(t,e);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,o){"string"==typeof e&&(e=[[null,e,""]]);var r={};if(o)for(var i=0;i=0&&p.splice(t,1)}function y(e){var t=document.createElement("style");if(void 0===e.attrs.type&&(e.attrs.type="text/css"),void 0===e.attrs.nonce){var o=function(){0;return n.nc}();o&&(e.attrs.nonce=o)}return x(t,e.attrs),m(e,t),t}function x(e,t){Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])}))}function v(e,t){var n,o,r,i;if(t.transform&&e.css){if(!(i="function"==typeof t.transform?t.transform(e.css):t.transform.default(e.css)))return function(){};e.css=i}if(t.singleton){var a=u++;n=c||(c=y(t)),o=w.bind(null,n,a,!1),r=w.bind(null,n,a,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",x(t,e.attrs),m(e,t),t}(t),o=O.bind(null,n,t),r=function(){b(n),n.href&&URL.revokeObjectURL(n.href)}):(n=y(t),o=k.bind(null,n),r=function(){b(n)});return o(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;o(e=t)}else r()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=a()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=h(e,t);return d(n,t),function(e){for(var o=[],r=0;r3)for(n=[n],o=3;o1&&E(r,t,n),t=O(n,r,r,e.__k,null,r.__e,t),"function"==typeof e.type&&(e.__d=t)))}function A(e,t,n,r,i,a,l,s,c){var u,p,f,h,m,b,v,g,_,w,O,C=t.type;if(void 0!==t.constructor)return null;(u=o.__b)&&u(t);try{e:if("function"==typeof C){if(g=t.props,_=(u=C.contextType)&&r[u.__c],w=u?_?_.props.value:u.__:r,n.__c?v=(p=t.__c=n.__c).__=p.__E:("prototype"in C&&C.prototype.render?t.__c=p=new C(g,w):(t.__c=p=new x(g,w),p.constructor=C,p.render=M),_&&_.sub(p),p.props=g,p.state||(p.state={}),p.context=w,p.__n=r,f=p.__d=!0,p.__h=[]),null==p.__s&&(p.__s=p.state),null!=C.getDerivedStateFromProps&&(p.__s==p.state&&(p.__s=d({},p.__s)),d(p.__s,C.getDerivedStateFromProps(g,p.__s))),h=p.props,m=p.state,f)null==C.getDerivedStateFromProps&&null!=p.componentWillMount&&p.componentWillMount(),null!=p.componentDidMount&&p.__h.push(p.componentDidMount);else{if(null==C.getDerivedStateFromProps&&g!==h&&null!=p.componentWillReceiveProps&&p.componentWillReceiveProps(g,w),!p.__e&&null!=p.shouldComponentUpdate&&!1===p.shouldComponentUpdate(g,p.__s,w)||t.__v===n.__v){p.props=g,p.state=p.__s,t.__v!==n.__v&&(p.__d=!1),p.__v=t,t.__e=n.__e,t.__k=n.__k,p.__h.length&&l.push(p),E(t,s,e);break e}null!=p.componentWillUpdate&&p.componentWillUpdate(g,p.__s,w),null!=p.componentDidUpdate&&p.__h.push((function(){p.componentDidUpdate(h,m,b)}))}p.context=w,p.props=g,p.state=p.__s,(u=o.__r)&&u(t),p.__d=!1,p.__v=t,p.__P=e,u=p.render(p.props,p.state,p.context),p.state=p.__s,null!=p.getChildContext&&(r=d(d({},r),p.getChildContext())),f||null==p.getSnapshotBeforeUpdate||(b=p.getSnapshotBeforeUpdate(h,m)),O=null!=u&&u.type==y&&null==u.key?u.props.children:u,k(e,Array.isArray(O)?O:[O],t,n,r,i,a,l,s,c),p.base=t.__e,p.__h.length&&l.push(p),v&&(p.__E=p.__=null),p.__e=!1}else null==a&&t.__v===n.__v?(t.__k=n.__k,t.__e=n.__e):t.__e=P(n.__e,t,n,r,i,a,l,c);(u=o.diffed)&&u(t)}catch(e){t.__v=null,o.__e(e,t,n)}return t.__e}function R(e,t){o.__c&&o.__c(t,e),e.some((function(t){try{e=t.__h,t.__h=[],e.some((function(e){e.call(t)}))}catch(e){o.__e(e,t.__v)}}))}function P(e,t,n,o,r,i,a,l){var s,c,f,d,h,m=n.props,b=t.props;if(r="svg"===t.type||r,null!=i)for(s=0;se.length)&&(t=e.length);for(var n=0,o=new Array(t);nr?n-r:r,a=this.labelRef.scrollLeft+e.deltaY;a<0&&(a=0),a>i&&(a=i),this.labelRef.scrollLeft=a}}},{key:"blur",value:function(){var e=this.base.querySelector(".label-search-input");e&&e.blur()}},{key:"labelDrag",value:function(e,t){for(var n=t.type,o=t.target;;){if(!o||"I"===o.tagName)return;if("DIV"===o.tagName&&"fixed"!==o.style.position)break;o=o.parentNode}if(console.log(t),"mousedown"===n){var r=o.cloneNode(!0),i=t.pageX,a=t.pageY,l=t.offsetX,s=t.offsetY;console.log(i,a,l,s),r.style.position="fixed",r.style.left=i-l+"px",r.style.top=a-s+"px",o.appendChild(r),console.log(r),r.onmousemove=function(e){r.style.left=e.pageX-l+"px",r.style.top=e.pageY-s+"px"},r.mouseup=function(){r.parentNode.removeChild(r),r.onmousemove=null,r.mouseup=null,r.mouseleave=null},r.mouseleave=function(){console.log("mouseleave")}}else if("mouseup"===n)for(var c=o.childNodes,u=0;ue.length)&&(t=e.length);for(var n=0,o=new Array(t);n0&&void 0!==arguments[0]||this.size;var e=this.state.pageIndex;e<=1||(this.changePageIndex(e-1),this.props.pageRemote&&this.postData(e-1,!0))}},{key:"pageNextClick",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.size,t=this.state.pageIndex;t>=e||(this.changePageIndex(t+1),this.props.pageRemote&&this.postData(t+1,!0))}},{key:"changePageIndex",value:function(e){this.setState({pageIndex:e})}},{key:"labelSearch",value:function(e){"input"==e.type?this.searchInput(e):this.handleComposition(e)}},{key:"searchInput",value:function(e){var t=this,n=e.target.value;n!==this.__value&&(this.searchCid&&clearTimeout(this.searchCid),this.inputOver&&(this.__value=n,this.searchCid=setTimeout((function(){t.callback=!0,t.setState({filterValue:t.__value,remote:!0,pageIndex:1})}),this.props.delay)))}},{key:"focus",value:function(){this.searchInputRef&&this.searchInputRef.focus()}},{key:"blur",value:function(){this.searchInputRef&&this.searchInputRef.blur()}},{key:"handleComposition",value:function(e){var t=e.type;"compositionstart"===t?(this.inputOver=!1,this.searchCid&&clearTimeout(this.searchCid)):"compositionend"===t&&(this.inputOver=!0,this.searchInput(e))}},{key:"postData",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.state.pageIndex,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];(this.state.remote||n)&&(this.callback=!1,this.setState({loading:!0,remote:!1}),this.blur(),this.props.remoteMethod(this.state.filterValue,(function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;setTimeout((function(){e.focus(),e.callback=!0,e.setState({loading:!1,totalSize:n}),e.props.onReset(t,"data")}),10)}),this.props.show,t))}},{key:"keydown",value:function(e,t){var n=this,o=t.keyCode;if("div"===e&&(27===o||9===o?this.props.onReset(!1,"close"):37===o?this.pagePrevClick():39===o&&this.pageNextClick()),this.props.enableKeyboard){var r=this.props.prop,i=r.value,a=r.optgroup,l=r.disabled,s=this.tempData.filter((function(e){return!e[a]&&!e[l]})),c=s.length-1;if(-1===c)return;var u=s.findIndex((function(e){return e[i]===n.state.val}));if(38===o){u<=0?u=c:u>0&&(u-=1);var p=s[u][i];this.setState({val:p}),this.viewTo(p)}else if(40===o){-1===u||u===c?u=0:uM&&(T=M),M>0&&T<=0&&(T=1),!x){var z=(T-1)*e.pageSize,L=z+e.pageSize;S=S.slice(z,L)}var V={cursor:"no-drop",color:"#d2d2d2"},F={},U={};T<=1&&(F=V),T==M&&(U=V),this.state.pageIndex!==T&&this.changePageIndex(T),this.size=M,D=m("div",{class:"xm-paging"},m("span",{style:F,onClick:this.pagePrevClick.bind(this,M)},e.languageProp.paging.prev),m("span",null,this.state.pageIndex," / ",M),m("span",{style:U,onClick:this.pageNextClick.bind(this,M)},e.languageProp.paging.next))}else e.showCount>0&&(S=S.slice(0,e.showCount));var N,B,K=[],H={__tmp:!0};H[j]=!0,S.forEach((function(e){var t=I[e.__group__index];delete e.__group__index,N&&!t&&(t=H),t!=N&&(N=t,t&&K.push(N)),K.push(e)})),S=K,t&&null!=(t=y(this.state.filterValue,Object(c.b)([],S)))&&(B=S).splice.apply(B,[0,0].concat(J((Object(c.d)(t)?t:[t]).map((function(e){return Z(Z({},e),{},{__node:{}})})))));var q=Object(c.b)([],S);this.tempData=q;var Y=m("div",{class:"xm-toolbar"},e.toolbar.list.map((function(t){var o,r=e.languageProp.toolbar[t];o="ALL"===t?{icon:"xm-iconfont xm-icon-quanxuan",name:r,method:function(e){var t=i.optgroup,o=i.disabled,r=e.filter((function(e){return!e[t]})).filter((function(e){return!e[o]})),a=u.filter((function(e){return e[i.disabled]})),l=[];l=s?a.length?a:r.slice(0,1):v>0?a.length>=v?a:Object(c.f)(r.slice(0,v-a.length),a,i):Object(c.f)(r,u,i),n.props.onReset(l,"sels")}}:"CLEAR"===t?{icon:"xm-iconfont xm-icon-qingkong",name:r,method:function(e){n.props.onReset(u.filter((function(e){return e[i.disabled]})),"sels")}}:"REVERSE"===t?{icon:"xm-iconfont xm-icon-fanxuan",name:r,method:function(e){var t=i.optgroup,o=i.disabled,r=e.filter((function(e){return!e[t]})).filter((function(e){return!e[o]})),a=[];u.forEach((function(e){var t=r.findIndex((function(t){return t[k]===e[k]}));-1==t?a.push(e):r.splice(t,1)}));var l=a.filter((function(e){return e[i.disabled]})),p=[];p=s?l.length?l:r.slice(0,1):v>0?l.length>=v?l:Object(c.f)(r.slice(0,v-l.length),l,i):Object(c.f)(r,a,i),n.props.onReset(p,"sels")}}:t;var a=function(e){"mouseenter"===e.type&&(e.target.style.color=l.color),"mouseleave"===e.type&&(e.target.style.color="")};return m("div",{class:"toolbar-tag",style:{},onClick:function(){Object(c.e)(o.method)&&o.method(q),n.focus()},onMouseEnter:a,onMouseLeave:a},e.toolbar.showIcon&&m("i",{class:o.icon}),m("span",null,o.name))})).filter((function(e){return e}))),Q="hidden"!=e.model.icon;return(S=S.map((function(t){return t[j]?t.__tmp?m("div",{class:"item--divided"}):m("div",{class:"xm-group"},m("div",{class:"xm-group-item",onClick:n.groupClick.bind(n,t)},t[w])):function(t){var r=!!u.find((function(e){return e[k]==t[k]})),i=r?{color:l.color,border:"none"}:{borderColor:l.color},c={};g&&t[k]===n.state.val&&(c.backgroundColor=l.hover),!Q&&r&&(c.backgroundColor=l.color,t[O]&&(c.backgroundColor="#C2C2C2"));var p,f,d=["xm-option",t[O]?" disabled":"",r?" selected":"",Q?"show-icon":"hide-icon"].join(" "),h=["xm-option-icon",(p=e.iconfont.select,f=e.iconfont.unselect,(p?!r&&f?f+" xm-custom-icon":p:0)||"xm-iconfont "+(s?"xm-icon-danx":"xm-icon-duox"))].join(" "),b=function(e){"mouseenter"===e.type?t[O]||(g?n.setState({val:t[k]}):e.target.style.backgroundColor=l.hover):"mouseleave"===e.type&&(t[O]||g||(e.target.style.backgroundColor=""))};return m("div",{class:d,style:c,value:t[k],onClick:n.optionClick.bind(n,t,r,t[O]),onMouseEnter:b,onMouseLeave:b},Q&&m("i",{class:h,style:i}),m("div",{class:"xm-option-content",dangerouslySetInnerHTML:{__html:a({data:o,item:t,arr:u,name:t[w],value:t[k]})}}))}(t)}))).length?_&&this.state.val==ne&&this.keydown("div",{keyCode:40}):(!e.pageEmptyShow&&(D=""),S.push(m("div",{class:"xm-select-empty"},p))),m("div",{onClick:this.blockClick,tabindex:"1",style:"outline: none;"},m("div",null,e.toolbar.show&&Y,P,m("div",{class:"scroll-body",style:{maxHeight:e.height}},S),e.paging&&D),this.state.loading&&m("div",{class:"loading"},m("span",{class:"loader"})))}},{key:"componentDidMount",value:function(){var e=this.base.querySelector(".xm-search-input");e&&(e.addEventListener("compositionstart",this.handleComposition.bind(this)),e.addEventListener("compositionupdate",this.handleComposition.bind(this)),e.addEventListener("compositionend",this.handleComposition.bind(this)),e.addEventListener("input",this.searchInput.bind(this)),this.searchInputRef=e),this.base.addEventListener("keydown",this.keydown.bind(this,"div"))}},{key:"componentDidUpdate",value:function(){if(this.callback){this.callback=!1;var e=this.props.filterDone;Object(c.e)(e)&&e(this.state.filterValue,this.tempData||[])}}}])&&G(t.prototype,n),o&&G(t,o),i}(x);function re(e){return(re="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function ie(e,t){for(var n=0;n0||p.lazy&&!1!==e.__node.loading)?"xm-visible":"xm-hidden"].join(" "),j=[];p.showFolderIcon&&(j.push(m("i",{class:C,type:"expand"})),p.showLine&&(o&&j.push(m("i",{class:"left-line",style:{left:t-p.indent+3+"px"}})),j.push(m("i",{class:"top-line",style:{left:t-p.indent+3+"px",width:p.indent+(0===o?10:-2)+"px"}}))));var S=function(t){"mouseenter"===t.type?e[g]||(y?n.setState({val:e[v]}):t.target.style.backgroundColor=a.hover):"mouseleave"===t.type&&(e[g]||y||(t.target.style.backgroundColor=""))};return m("div",{class:w,style:h,value:e[v],onClick:n.optionClick.bind(n,e,r,e[g],"line"),onMouseEnter:S,onMouseLeave:S},j,e.__node.loading&&m("span",{class:"loader"}),k&&m("i",{class:O,style:d,onClick:n.optionClick.bind(n,e,r,e[g],"checkbox")}),m("div",{class:"xm-option-content",dangerouslySetInnerHTML:{__html:s({data:u,item:e,arr:i,name:e[x],value:e[v]})}}))};f&&(d?this.postData():this.filterData(u,this.state.filterValue));var C=Object(c.b)([],u),j=Object(c.b)([],i);this.tempData=C;var S=u.map((function(e){return function e(t,o){if(!t.__node.hidn){var r=t[_];if(o+=p.indent,r){var i=-1!==n.state.expandedKeys.findIndex((function(e){return t[v]===e}));return 0===r.length&&(i=!1),m("div",{class:"xm-tree"},p.showFolderIcon&&p.showLine&&i&&r.length>0&&m("i",{class:"left-line left-line-group",style:{left:o+3+"px"}}),O(t,o,0===r.length&&(!p.lazy||p.lazy&&!1===t.__node.loading)?0:i),i&&m("div",{class:"xm-tree-box"},r.map((function(t){return e(t,o)}))))}return O(t,o,0)}}(e,10-p.indent)})).filter((function(e){return e}));function E(e,t){t.forEach((function(t){t[w]?(p.strict||"hidden"===b.parent||e.push(t),E(e,t[_])):e.push(t)}))}var A=m("div",{class:"xm-toolbar"},e.toolbar.list.map((function(t){var r,s=e.languageProp.toolbar[t];r="ALL"===t?{icon:"xm-iconfont xm-icon-quanxuan",name:s,method:function(e){var t=[];E(t,e),t=t.filter((function(e){return!e[g]&&!e.__node.hidn})),n.props.onReset(l?t.slice(0,1):Object(c.f)(t,i,o),"treeData")}}:"CLEAR"===t?{icon:"xm-iconfont xm-icon-qingkong",name:s,method:function(e){n.props.onReset(i.filter((function(e){return e[o.disabled]})),"treeData")}}:"REVERSE"===t?{icon:"xm-iconfont xm-icon-fanxuan",name:s,method:function(e){var t=[];E(t,e),t=t.filter((function(e){return!e[g]&&!e.__node.hidn}));var r=[];i.forEach((function(e){var n=t.findIndex((function(t){return t[v]===e[v]}));-1==n?r.push(e):t.splice(n,1)})),n.props.onReset(l?r.slice(0,1):Object(c.f)(t,r,o),"treeData")}}:t;var u=function(e){"mouseenter"===e.type&&(e.target.style.color=a.color),"mouseleave"===e.type&&(e.target.style.color="")};return m("div",{class:"toolbar-tag",onClick:function(){Object(c.e)(r.method)&&r.method(C,j)},onMouseEnter:u,onMouseLeave:u},e.toolbar.showIcon&&m("i",{class:r.icon}),m("span",null,r.name))})).filter((function(e){return e}))),R=m("div",{class:f?"xm-search":"xm-search dis"},m("i",{class:"xm-iconfont xm-icon-sousuo"}),m("input",{class:"xm-input xm-search-input",placeholder:h}));return S.length||S.push(m("div",{class:"xm-select-empty"},r)),m("div",{onClick:this.blockClick,class:"xm-body-tree"},e.toolbar.show&&A,R,m("div",{class:"scroll-body",style:{maxHeight:e.height}},S),this.state.loading&&m("div",{class:"loading"},m("span",{class:"loader"})))}},{key:"componentDidMount",value:function(){var e=this.base.querySelector(".xm-search-input");e&&(e.addEventListener("compositionstart",this.handleComposition.bind(this)),e.addEventListener("compositionupdate",this.handleComposition.bind(this)),e.addEventListener("compositionend",this.handleComposition.bind(this)),e.addEventListener("input",this.searchInput.bind(this)),this.searchInputRef=e)}},{key:"componentDidUpdate",value:function(){if(this.callback){this.callback=!1;var e=this.props.filterDone;Object(c.e)(e)&&e(this.state.filterValue,this.tempData||[])}}}])&&fe(t.prototype,n),o&&fe(t,o),i}(x);function ve(e){return(ve="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function ge(e,t){for(var n=0;n0,O={backgroundColor:"transparent"},C=["xm-option",g?" disabled":"",v?" selected":"",y?"show-icon":"hide-icon"].join(" "),j=k&&"hidden"===e.iconfont.parent?"xm-option-icon-hidden":["xm-option-icon",(_?e.iconfont.half?e.iconfont.half+" xm-custom-icon":0:k&&e.iconfont.parent?e.iconfont.parent+" xm-custom-icon":v?e.iconfont.select?e.iconfont.select:0:e.iconfont.unselect?e.iconfont.unselect+" xm-custom-icon":0)||"xm-iconfont "+(l?"xm-icon-danx":u.strict&&_?"xm-icon-banxuan":"xm-icon-duox")].join(" ");t[f]===n.state.val&&(O.backgroundColor=a.hover),!y&&v&&(O.backgroundColor=a.color,g&&(O.backgroundColor="#C2C2C2"));var S={},E={};x&&(S.color=a.color,S.fontWeight=700,E.color=a.color);var A=function(e){"mouseenter"===e.type?t[d]||n.setState({val:t[f]}):"mouseleave"===e.type&&n.setState({val:""})};return m("div",{class:C,style:O,value:t[f],onClick:n.optionClick.bind(n,t,v,g,"line",r),onMouseEnter:A,onMouseLeave:A},y&&m("i",{class:j,style:w,onClick:n.optionClick.bind(n,t,v,g,"checkbox",r)}),m("div",{class:"xm-option-content",style:S,dangerouslySetInnerHTML:{__html:s({data:c,item:t,arr:i,name:t[p],value:t[f]})}}),t[b]&&m("div",{class:"xm-right-arrow",style:E}))}(o,0,v,_)},g=c.map((function(e){return v(e,2,0)})).concat(x).filter((function(e){return e}));return g.length||g.push(m("div",{class:"xm-select-empty"},r)),m("div",{onClick:this.blockClick,class:"xm-body-cascader scroll-body",style:{width:u.indent+"px",maxHeight:e.height}},g)}},{key:"componentDidMount",value:function(){this.props.onReset("cascader","class")}}])&&ge(t.prototype,n),o&&ge(t,o),i}(x);function je(){return(je=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,o=new Array(t);n1&&(n=n.slice(0,1),(l.show&&l.strict||s.show&&s.strict)&&this.clearAndReset(o,n,!1)),this.setState({sels:n,dataObj:c,flatData:u})}return this.setState({data:o}),n}},{key:"upDate",value:function(e,t){var n=this.state.dataObj,o=this.props,r=o.prop,i=o.tree,a=o.cascader,l=r.value,s=r.disabled,u=r.children;e.map((function(e){return n["object"===Ie(e)?e[l]:e]})).filter((function(e){return e})).forEach((function(e){if(e[s]=!t,i.show&&i.strict||a.show&&a.strict){if(t)for(var n=e;n;)n[s]=!1,n=n.__node.parent;!function e(n){n[s]=!t;var o=n[u];o&&Object(c.d)(o)&&o.forEach((function(t){return e(t)}))}(e)}})),this.setState({dataObj:n})}},{key:"exchangeValue",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.state.dataObj,o=this.props,r=o.prop,i=o.tree,a=o.cascader,l=(o.data,r.children),s=r.value,u=e.map((function(e){return"object"===Ie(e)?Re(Re({},e),{},{__node:{}}):n[e]})).filter((function(e){return e})),p=Se(u);if(i.show&&i.strict||a.show&&a.strict){var f=function e(t,n){var o=n[l];o&&Object(c.d)(o)&&o.forEach((function(n){-1===u.findIndex((function(e){return e[s]===n[s]}))&&t.push(n),e(t,n)}))},d={};d[l]=u,f(p,d),p=p.filter((function(e){return!0!==e[t.props.prop.optgroup]}))}return p}},{key:"value",value:function(e,t,n,o){var r=!(arguments.length>4&&void 0!==arguments[4])||arguments[4];!1!==t&&!0!==t&&(t=this.state.show);var i=this.props,a=i.prop,l=i.tree,s=i.cascader,c=this.exchangeValue(e);if(!this.checkMax(c,c,!0)){if(l.show&&l.strict||s.show&&s.strict){var u=this.state.data;this.clearAndReset(u,c,!1),c=this.init({data:u,prop:a},!0)}this.resetSelectValue(c,o||c,r,n),this.setState({show:t})}}},{key:"clearAndReset",value:function(e,t,n){var o=this,r=this.props.prop,i=r.selected,a=r.disabled,l=r.children,s=r.value;e.forEach((function(e){e[i]=-1!=t.findIndex((function(t){return t[s]===e[s]}))||n;var r=e[l];if(r&&Object(c.d)(r)&&r.length>0){o.clearAndReset(r,t,e[i]);var u=r.length,p=r.filter((function(e){return!0===e[i]||!0===e.__node.selected})).length;e.__node.selected=p===u,e.__node.half=p>0&&p0,e.__node.disabled=r.filter((function(e){return!0===e[a]||!0===e.__node.disabled})).length===u}}))}},{key:"load",value:function(e,t,n,o){var r=this,i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,a=arguments.length>5?arguments[5]:void 0,l=this.props,s=l.prop,u=l.tree,p=l.cascader,f=s.children,d=s.optgroup,h=s.value,m=s.selected,b=s.disabled;e.forEach((function(e){e.__node={parent:o,level:i,loading:e.__node&&e.__node.loading},a&&(delete e[m],a.find((function(t){return t===e[h]}))&&(e[m]=!0)),t[e[h]]=e,n.push(e);var l=e[f];if(l&&Object(c.d)(l)){var s=l.length;if(s>0){r.load(l,t,n,e,i+1,a),e[d]=!0,(u.show&&u.strict||p.show&&p.strict)&&(!0===e[m]&&(delete e[m],l.forEach((function(e){return e[m]=!0}))),!0===e[b]&&(delete e[b],l.forEach((function(e){return e[b]=!0}))));var y=l.filter((function(e){return!0===e[m]||!0===e.__node.selected})).length;e.__node.selected=y===s,e.__node.half=y>0&&y0,e.__node.disabled=l.filter((function(e){return!0===e[b]||!0===e.__node.disabled})).length===s}}}))}},{key:"resetSelectValue",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2?arguments[2]:void 0,o=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=this.props.on;if(Object(c.e)(r)&&this.prepare&&o){var i=r({arr:e,change:t,isAdd:n});if(Object(c.d)(i))return this.value(i,null,!1)}this.setState({sels:e})}},{key:"updateBorderColor",value:function(e){this.setState({tmpColor:e})}},{key:"treeHandler",value:function(e,t,n,o,r){var i=this,a=this.props.prop,l=a.value,s=(a.selected,a.disabled),c=a.children,u=a.optgroup,p=t[c];if(p.filter((function(e){return!(e[s]||e.__node.disabled)})).forEach((function(t){if(t[u])i.treeHandler(e,t,n,o,r);else{var a=e.findIndex((function(e){return e[l]==t[l]}));"del"===o?-1!=a&&(e.splice(a,1),n.push(t)):"half"!==o&&"add"!==o||-1==a&&(e.push(t),n.push(t))}})),r){var f=p.length,d=p.filter((function(t){return-1!==e.findIndex((function(e){return e[l]===t[l]}))||!0===t.__node.selected})).length;t.__node.selected=d===f,t.__node.half=d>0&&dl;if(l>0&&s)return this.updateBorderColor(a.maxColor),i&&Object(c.e)(i)&&i(t,e),!0}},{key:"itemClick",value:function(e,t,n,o){var r=this.props,i=(r.theme,r.prop),a=r.radio,l=r.repeat,s=r.clickClose,c=(r.max,r.maxMethod,r.tree),u=r.cascader,p=r.data,f=Se(this.state.sels),d=i.value,h=(i.selected,i.disabled,i.children),m=i.optgroup;if(!n){if(e[m]&&(c.show&&c.strict||u.show&&u.strict)){e[h];var b,y=[],x=!0;if(e.__node.selected?(b="del",x=!1):e.__node.half?(b="half",this.treeHandler(f,e,y,b),0===y.length&&(b="del",x=!1)):b="add","half"!=b&&this.treeHandler(f,e,y,b),this.checkMax(y,f))return;f=Se(this.state.sels),y=[],this.treeHandler(f,e,y,b,!0),this.resetSelectValue(f,y,x),this.setState({data:this.state.data})}else if(!t||l&&!o){if(this.checkMax(e,f))return;f=a?[e]:[].concat(Se(f),[e]),this.clearAndReset(p,f,t),this.resetSelectValue(f,[e],!t)}else{var v=f.findIndex((function(t){return t[d]==e[d]}));-1!=v&&(f.splice(v,1),this.resetSelectValue(f,[e],!t))}var g=e.__node.parent;if(g){for(;g;){var _=g[h],w=_.length,k=_.filter((function(e){return-1!==f.findIndex((function(t){return t[d]===e[d]}))||!0===e.__node.selected})).length;g.__node.selected=k===w,g.__node.half=k>0&&k0,g=g.__node.parent}this.setState({data:this.state.data})}s&&!o&&this.onClick()}}},{key:"onClick",value:function(e){var t=this;if("relative"!==this.props.model.type)if(this.props.disabled)!1!==this.state.show&&this.setState({show:!1});else{var n=!this.state.show;if(n){if(this.props.show&&0==this.props.show())return;Object.keys(Xe).filter((function(e){return e!=t.props.el})).forEach((function(e){return Xe[e].closed()}))}else{if(this.props.hide&&0==this.props.hide())return;this.bodyView.scroll&&this.bodyView.scroll(0,0)}this.setState({show:n}),e&&e.stopPropagation()}}},{key:"onReset",value:function(e,t){var n=this;if("data"===t){var o=e.filter((function(e){return!0===e[n.props.prop.selected]}));this.resetSelectValue(Object(c.f)(o,this.state.sels,this.props.prop),o,!0);var r=[];this.load(e,{},r),this.setState({data:e,flatData:r})}else"sels"===t?this.resetSelectValue(e,e,!0):"append"===t?this.append(e):"delete"===t?this.del(e):"auto"===t?this.auto(e):"treeData"===t?this.value(e,null,!0,!1,!1):"close"===t?this.onClick():"class"===t?this.setState({bodyClass:e}):"labelSearchBlur"===t?this.labelRef.blur(e):"labelSearch"===t&&this.generalRef.labelSearch(e)}},{key:"append",value:function(e){var t=this.exchangeValue(e);this.value(Object(c.f)(t,this.state.sels,this.props.prop),this.props.show,!0,t)}},{key:"del",value:function(e){var t=this.props.prop.value,n=this.state.sels,o=this.exchangeValue(e);o.forEach((function(e){var o=n.findIndex((function(n){return n[t]===e[t]}));-1!=o&&n.splice(o,1)})),this.value(n,this.props.show,!0,o,!1)}},{key:"auto",value:function(e){var t=this,n=this.props.prop.value;e.filter((function(e){return-1!=t.state.sels.findIndex((function(t){return t[n]===e[n]}))})).length==e.length?this.del(e):this.append(e)}},{key:"changeExpandedKeys",value:function(e){var t=this.props,n=t.tree,o=t.prop,r=this.state,i=r.dataObj,a=r.flatData;n.show&&this.treeRef.init({dataObj:i,flatData:a,prop:o,tree:{expandedKeys:e}})}},{key:"calcPosition",value:function(){if(this.state.show&&"fixed"===this.props.model.type){var e=this.base.getBoundingClientRect();return Date.now()-this.state.time>10&&this.setState({time:Date.now()}),{position:"fixed",left:e.x,top:e.y+e.height+4,width:e.width}}return{}}},{key:"componentWillReceiveProps",value:function(e){this.init(e,e.updateData)}},{key:"componentWillMount",value:function(){this.init(this.props,!0)}},{key:"render",value:function(e,t){var n=this,o=e.theme,r=e.prop,i=(e.radio,e.repeat,e.clickClose,e.on,e.max,e.maxMethod,e.content),a=e.disabled,l=e.tree,s=e.submitConversion,u={borderColor:o.color},p=t.data,f=t.dataObj,d=t.flatData,h=t.sels,b=t.show,y=t.tmpColor,x=t.bodyClass;a&&(b=!1);var v={style:Re(Re({},e.style),b?u:{}),onClick:this.onClick.bind(this),ua:Object(c.a)(),size:e.size,tabindex:1};y&&(v.style.borderColor=y,setTimeout((function(){v.style.borderColor="",n.updateBorderColor("")}),300)),r.value;var g=Re(Re({},e),{},{data:p,sels:h,ck:this.itemClick.bind(this),title:h.map((function(e){return e[r.name]})).join(","),onReset:this.onReset.bind(this)}),_=Re(Re({},e),{},{data:p,dataObj:f,flatData:d,sels:h,ck:this.itemClick.bind(this),show:b,onReset:this.onReset.bind(this)}),w=i?m(ue,_):l.show?m(xe,je({},_,{ref:function(e){return n.treeRef=e}})):e.cascader.show?m(Ce,_):m(oe,je({},_,{ref:function(e){return n.generalRef=e}})),k=this.calcPosition();return m("xm-select",v,m("input",{class:"xm-select-default","lay-verify":e.layVerify,"lay-verType":e.layVerType,"lay-reqText":e.layReqText,name:e.name,value:s(h,r)}),m("i",{class:b?"xm-icon xm-icon-expand":"xm-icon"}),0===h.length&&m("div",{class:"xm-tips"},e.tips),m(H,je({},g,{ref:function(e){return n.labelRef=e}})),m("div",{class:["xm-body",x,e.model.type,b?"":"dis"].join(" "),style:k,ref:function(e){return n.bodyView=e}},w),a&&m("div",{class:"xm-select-disabled"}))}},{key:"componentDidMount",value:function(){var e=this;this.prepare=!0,this.base.addEventListener("keydown",(function(t){13===t.keyCode&&e.onClick(t)})),this.input=this.base.querySelector(".xm-select-default");var t=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;t&&new t((function(t){t.forEach((function(t){"attributes"==t.type&&"class"===t.attributeName&&-1!==e.input.className.indexOf("layui-form-danger")&&(e.input.className="xm-select-default",e.base.style.borderColor=e.props.theme.maxColor,e.base.scrollIntoView&&e.base.scrollIntoView({behavior:"smooth"}))}))})).observe(this.input,{attributes:!0});for(var n=this.base;n;){if("FORM"===n.tagName){var o=n.querySelector('button[type="reset"]');o&&o.addEventListener("click",(function(t){e.init(e.props,!0)}));break}n=n.parentElement}var r=this.props.done;r&&r()}},{key:"componentDidUpdate",value:function(){var e=this.props,t=e.direction,n=e.model;if("relative"!==n.type&&"fixed"!==n.type){var o=this.base.getBoundingClientRect();if("auto"===t){this.bodyView.style.display="block",this.bodyView.style.visibility="hidden";var r=this.bodyView.getBoundingClientRect().height;this.bodyView.style.display="",this.bodyView.style.visibility="";var i=o.y||o.top||0,a=document.documentElement.clientHeight-i-o.height-20;t=a>r||i0&&void 0!==arguments[0]?arguments[0]:"zn",t=Ne[e]||Ue;return{language:e,languageProp:t,data:[],content:"",name:"select",layVerify:"",layVerType:"",layReqText:"",size:"medium",disabled:!1,initValue:null,create:null,tips:t.tips,empty:t.empty,delay:500,searchTips:t.searchTips,filterable:!1,filterMethod:function(e,t,n,o){return!e||-1!=t[o.name].indexOf(e)},remoteSearch:!1,remoteMethod:function(e,t){t([])},direction:"auto",style:{},height:"200px",autoRow:!1,paging:!1,pageSize:10,pageEmptyShow:!0,pageRemote:!1,radio:!1,repeat:!1,clickClose:!1,max:0,maxMethod:function(e,t){},showCount:0,enableKeyboard:!0,enableHoverFirst:!0,selectedKeyCode:13,toolbar:{show:!1,showIcon:!0,list:["ALL","CLEAR"]},tree:{show:!1,showFolderIcon:!0,showLine:!0,indent:20,expandedKeys:[],strict:!0,lazy:!1,load:null,simple:!1,nodeType:"__node_type",clickExpand:!0,clickCheck:!0},cascader:{show:!1,indent:100,strict:!0},prop:{name:"name",value:"value",selected:"selected",disabled:"disabled",children:"children",optgroup:"optgroup",click:"click"},theme:{color:"#009688",maxColor:"#e54d42",hover:"#f2f2f2"},model:{label:{type:"block",text:{left:"",right:"",separator:", "},block:{showCount:0,showIcon:!0,template:null},count:{template:function(e,t){return"已选中 ".concat(t.length," 项, 共 ").concat(e.length," 项")}}},icon:"show",type:"absolute"},iconfont:{select:"",unselect:"",half:"",parent:""},show:function(){},hide:function(){},template:function(e){e.item,e.sels;var t=e.name;return e.value,t},on:function(e){e.arr,e.item,e.selected},submitConversion:function(e,t){return e.map((function(e){return e[t.value]})).join(",")},done:function(){}}}(e.language),this.update(e)}},{key:"update",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=!!e.data;this.options=Object(c.b)(this.options,e),this.options.__render_success=!1;var n=this.options.dom;if(n){var o=this.options.data||[];if("function"==typeof o&&(o=o(),this.options.data=o),Object(c.d)(o))return T(m(Fe,qe({},this.options,{__update:Date.now(),updateData:t})),n),this.options.__render_success=!0,this;Object(c.k)("data数据必须为数组类型, 不能是".concat("undefined"==typeof data?"undefined":Ye(data),"类型"))}else Object(c.k)("没有找到渲染对象: ".concat(e.el,", 请检查"))}},{key:"reset",value:function(){var e=this.options.el;return this.init($e[e]),et[e].init(this.options,!0),this}},{key:"opened",value:function(){var e=et[this.options.el];return!e.state.show&&e.onClick(),this}},{key:"closed",value:function(){var e=et[this.options.el];return e.state.show&&e.onClick(),this}},{key:"getValue",value:function(e){var t=this,n=this.options,o=n.tree,r=n.prop,i=n.data,a=et[this.options.el].state.sels,l=a;o.show&&o.strict&&o.simple&&(l=[],Object(c.j)(i,a,l,r));var s=Object(c.c)(l,r.children,["__node"]);return"name"===e?s.map((function(e){return e[t.options.prop.name]})):"nameStr"===e?s.map((function(e){return e[t.options.prop.name]})).join(","):"value"===e?s.map((function(e){return e[t.options.prop.value]})):"valueStr"===e?s.map((function(e){return e[t.options.prop.value]})).join(","):s}},{key:"setValue",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(Object(c.d)(e))return et[this.options.el].value(this.options.radio?e.slice(0,1):e,t,n),this;Object(c.k)("请传入数组结构...")}},{key:"append",value:function(e){if(Object(c.d)(e))return et[this.options.el].append(e),this;Object(c.k)("请传入数组结构...")}},{key:"delete",value:function(e){if(Object(c.d)(e))return et[this.options.el].del(e),this;Object(c.k)("请传入数组结构...")}},{key:"warning",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=e||this.options.theme.maxColor;return!0===t?et[this.options.el].base.style.borderColor=n:et[this.options.el].updateBorderColor(n),this}},{key:"getTreeValue",value:function(e,t){var n=this.options,o=n.tree,r=n.cascader,i=n.prop,a=i.value;if(!o.show&&!r.show)return this.getValue(e);for(var l=et[this.options.el].state.sels,s=[],u=o.nodeType,p=function(e,t){s.find((function(t){return t[a]===e[a]}))||((e=Ke({},e))[u]=t,s.push(e))},f=0;fe.length)&&(t=e.length);for(var n=0,o=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"pid",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"id",o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"children",r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,i={};return safety(e).filter((function(e){var a=e[n],l=e[t],s=i[a],c=i[l];return s&&(e[o]=s[o]),i[a]=e,c||(c=Je({},o,[]),i[l]=c),c.push(e),n==r}))}}}}); \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/page.js b/demo/webman/frontend/layui_admin_flow/component/pear/module/page.js new file mode 100644 index 0000000000000000000000000000000000000000..52ff2ef0313154b15ca5e25414513a5d86bb20f6 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/page.js @@ -0,0 +1,119 @@ +layui.define(['jquery', 'element'], function (exports) { + "use strict"; + + var $ = layui.jquery; + var element = layui.element; + + var page = function (opt) { + this.option = opt; + }; + + /** + * @since Pear Admin 4.0 + * + * 创建 Page 页面 + */ + page.prototype.render = function (opt) { + var option = { + elem: opt.elem, + url: opt.url, + width: opt.width || "100%", + height: opt.height || "100%", + title: opt.title + } + renderContent(option); + return new page(option); + } + + /** + * @since Pear Admin 4.0 + * + * 切换 Page 页面 + */ + page.prototype.changePage = function (options) { + const $frame = $(`#${this.option.elem} .pear-page-content`); + if (options.type === "_iframe") { + $frame.html(``); + } else { + $.ajax({ + url: options.href, + type: 'get', + dataType: 'html', + success: function (data) { + $frame.html(data) + }, + error: function (xhr) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + $frame.attr("type", options.type); + $frame.attr("href", options.href); + } + + page.prototype.refresh = function (loading) { + var $frameLoad = $(`#${this.option.elem} .pear-page-loading`); + var $frame = $(`#${this.option.elem} .pear-page-content`); + if (loading) { + $frameLoad.css({ + display: 'block' + }); + } + if ($frame.attr("type") === "_iframe") { + $frame.html(``); + const $contentFrame = $frame.find("iframe"); + $contentFrame.on("load", () => { + $frameLoad.fadeOut(1000); + }) + } else { + $.ajax({ + type: 'get', + url: $frame.attr("href"), + dataType: 'html', + success: function (data) { + $frame.html(data) + $frameLoad.fadeOut(1000); + element.init(); + }, + error: function (xhr) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + } + + function renderContent(option) { + $("#" + option.elem).html(` +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + + + + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  `); + + var $frame = $("#" + option.elem).find(".pear-page-content"); + + if (option.type === "_iframe") { + $frame.html(``); + } else { + $.ajax({ + url: option.url, + type: 'get', + dataType: 'html', + success: function (data) { + $frame.html(data); + }, + error: function (xhr) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + } + + exports('page', new page()); +}); \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/tabPage.js b/demo/webman/frontend/layui_admin_flow/component/pear/module/tabPage.js new file mode 100644 index 0000000000000000000000000000000000000000..44cb83c04e9d15a5de4a3e0a2796994dd00c1322 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/tabPage.js @@ -0,0 +1,649 @@ +layui.define(['jquery', 'element', 'dropdown'], function (exports) { + "use strict"; + + var MOD_NAME = 'tabPage', + $ = layui.jquery, + dropdown = layui.dropdown, + element = layui.element; + + var tabPage = function (opt) { + this.option = opt; + }; + + var tabData = new Array(); + var tabDataCurrent = 0; + var contextTabDOM; + + tabPage.prototype.render = function (opt) { + + var option = { + elem: opt.elem, + data: opt.data, + index: opt.index, + tool: opt.tool || true, + roll: opt.roll || true, + success: opt.success ? opt.success : function (id) { }, + session: opt.session ? opt.session : false, + preload: opt.preload ? opt.preload : false, + height: opt.height || "100%", + width: opt.width || "100%", + closeEvent: opt.closeEvent, + tabMax: opt.tabMax, + } + + if (option.session) { + if (sessionStorage.getItem(option.elem + "-pear-tab-page-data") != null) { + tabData = JSON.parse(sessionStorage.getItem(option.elem + "-pear-tab-page-data")); + option.data = JSON.parse(sessionStorage.getItem(option.elem + "-pear-tab-page-data")); + tabDataCurrent = sessionStorage.getItem(option.elem + "-pear-tab-page-data-current"); + tabData.forEach(function (item, index) { + if (item.id == tabDataCurrent) { + option.index = index; + } + }) + } else { + tabData = opt.data; + } + } + + var lastIndex; + var tab = createTab(option); + $("#" + option.elem).html(tab); + $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-prev").click(function () { + rollPage("left", option); + }) + $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-next").click(function () { + rollPage("right", option); + }) + element.init(); + + $("#" + option.elem).width(opt.width); + $("#" + option.elem).height(opt.height); + $("#" + option.elem).css({ + position: "relative" + }); + + closeEvent(option); + + option.success(sessionStorage.getItem(option.elem + "-pear-tab-page-data-current")); + + dropdown.render({ + elem: `#${option.elem} .layui-tab-control > .layui-icon-down`, + trigger: 'hover', + data: [{ + title: '关 闭 当 前', + id: 1 + }, { + title: '关 闭 其 他', + id: 2 + }, { + title: '关 闭 全 部', + id: 3 + }], + click: function (obj) { + + const id = obj.id; + + if (id === 1) { + var currentTab = $(".layui-tab[lay-filter='" + option.elem + + "'] .layui-tab-title .layui-this"); + if (currentTab.find("span").is(".able-close")) { + var currentId = currentTab.attr("lay-id"); + tabDelete(option.elem, currentId, option.closeEvent, option); + } else { + layer.msg("当前页面不允许关闭", { + icon: 3, + time: 1000 + }) + } + } else if (id === 2) { + var currentId = $(".layui-tab[lay-filter='" + option.elem + + "'] .layui-tab-title .layui-this").attr("lay-id"); + var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li"); + $.each(tabtitle, function (i) { + if ($(this).attr("lay-id") != currentId) { + if ($(this).find("span").is(".able-close")) { + tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, + option); + } + } + }) + } else { + var currentId = $(".layui-tab[lay-filter='" + option.elem + + "'] .layui-tab-title .layui-this").attr("lay-id"); + var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li"); + $.each(tabtitle, function (i) { + if ($(this).find("span").is(".able-close")) { + tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, option); + } + }) + } + + } + }) + + $("body .layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title").on("contextmenu", "li", + function (e) { + var top = e.clientY; + var left = e.clientX; + var menuWidth = 100; + var menu = `
                                                                                                                    +
                                                                                                                  • 关闭当前
                                                                                                                  • +
                                                                                                                  • 关闭其他
                                                                                                                  • +
                                                                                                                  • 关闭所有
                                                                                                                  • +
                                                                                                                  `; + + contextTabDOM = $(this); + var isOutsideBounds = (left + menuWidth) > $(window).width(); + if (isOutsideBounds) { + left = $(window).width() - menuWidth; + } + + layer.open({ + type: 1, + title: false, + shade: false, + skin: 'pear-tab-page-menu', + closeBtn: false, + area: [menuWidth + 'px', '108px'], + fixed: true, + anim: false, + isOutAnim: false, + offset: [top, left], + content: menu, + success: function (layero, index) { + layer.close(lastIndex); + lastIndex = index; + menuEvent(option, index); + var timer; + $(layero).on('mouseout', function () { + timer = setTimeout(function () { + layer.close(index); + }, 30) + }); + + $(layero).on('mouseover', function () { + clearTimeout(timer); + }); + + $(layero).on('contextmenu', function () { + return false; + }) + } + }); + return false; + }) + + mousewheelAndTouchmoveHandler(option) + return new tabPage(option); + } + + tabPage.prototype.click = function (callback) { + var option = this.option; + var elem = this.option.elem; + element.on('tab(' + this.option.elem + ')', function (data) { + var id = $("#" + elem + " .layui-tab-title .layui-this").attr("lay-id"); + sessionStorage.setItem(option.elem + "-pear-tab-page-data-current", id); + callback(id); + }); + } + + tabPage.prototype.positionTab = function () { + var $tabTitle = $('.layui-tab[lay-filter=' + this.option.elem + '] .layui-tab-title'); + var autoLeft = 0; + $tabTitle.children("li").each(function () { + if ($(this).hasClass('layui-this')) { + return false; + } else { + autoLeft += $(this).outerWidth(); + } + }); + $tabTitle.animate({ + scrollLeft: autoLeft - $tabTitle.width() / 3 + }, 200); + } + + tabPage.prototype.clear = function () { + sessionStorage.removeItem(this.option.elem + "-pear-tab-page-data"); + sessionStorage.removeItem(this.option.elem + "-pear-tab-page-data-current"); + } + + tabPage.prototype.changeTabTitleById = function (id, title) { + var currentTab = $(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title [lay-id='" + id + "'] .title"); + currentTab.html(title); + } + + /** + * @since Pear Admin 4.0 + * + * 删除指定选项卡 + * + * @param id 编号 + */ + tabPage.prototype.removeTab = function (id) { + var elem = this.option.elem; + if (id != undefined) { + var currentTab = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title [lay-id='" + id + "']"); + if (currentTab.find("span").is(".able-close")) { + tabDelete(elem, id, () => { }); + } + } else { + var tabtitle = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title li"); + $.each(tabtitle, function () { + if ($(this).find("span").is(".able-close")) { + tabDelete(elem, $(this).attr("lay-id"), () => { }); + } + }) + } + } + + /** + * @since Pear Admin 4.0 + * + * 删除其他选项卡 + */ + tabPage.prototype.removeOtherTab = function () { + var elem = this.option.elem; + var currentId = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title .layui-this").attr("lay-id"); + var tabtitle = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title li"); + $.each(tabtitle, function () { + if ($(this).attr("lay-id") != currentId) { + if ($(this).find("span").is(".able-close")) { + tabDelete(elem, $(this).attr("lay-id"), () => { }); + } + } + }) + } + + /** + * @since Pear Admin 4.0 + * + * 删除选中选项卡 + */ + tabPage.prototype.removeCurrentTab = function () { + var currentTab = $(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title .layui-this"); + if (currentTab.find("span").is(".able-close")) { + var currentId = currentTab.attr("lay-id"); + tabDelete(this.option.elem, currentId, () => { }); + } + } + + /** + * @since Pear Admin 4.0 + * + * 切换选项卡 + * + * @param opt 内容 + */ + tabPage.prototype.changePage = function (opt) { + + var title = ` + ${opt.title} + ဆ`; + + if ($(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title li[lay-id]").length <= + 0) { + + var that = this; + + if (opt.type === "_iframe") { + + element.tabAdd(this.option.elem, { + id: opt.id, + title: title, + content: `` + }); + + } else { + + $.ajax({ + url: opt.url, + type: 'get', + dataType: 'html', + async: false, + success: function (data) { + element.tabAdd(that.option.elem, { + id: opt.id, + title: title, + content: `
                                                                                                                  ${data}
                                                                                                                  `, + }); + }, + error: function (xhr, textstatus, thrown) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + + tabData.push(opt); + sessionStorage.setItem(that.option.elem + "-pear-tab-page-data", JSON.stringify(tabData)); + sessionStorage.setItem(that.option.elem + "-pear-tab-page-data-current", opt.id); + + } else { + + var isData = false; + $.each($(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title li[lay-id]"), + function () { + if ($(this).attr("lay-id") == opt.id) { + isData = true; + } + }) + + if (isData == false) { + + if (this.option.tabMax != false) { + if ($(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title li[lay-id]") + .length >= this.option.tabMax) { + layer.msg("最多打开" + this.option.tabMax + "个标签页", { + icon: 2, + time: 1000, + shift: 6 + }); + return false; + } + } + + var that = this; + if (opt.type === "_iframe") { + element.tabAdd(this.option.elem, { + id: opt.id, + title: title, + content: `` + }); + } else { + $.ajax({ + url: opt.url, + type: 'get', + dataType: 'html', + async: false, + success: function (data) { + element.tabAdd(that.option.elem, { + id: opt.id, + title: title, + content: `
                                                                                                                  ${data}
                                                                                                                  `, + }); + }, + error: function (xhr, textstatus, thrown) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + tabData.push(opt); + sessionStorage.setItem(that.option.elem + "-pear-tab-page-data", JSON.stringify(tabData)); + sessionStorage.setItem(that.option.elem + "-pear-tab-page-data-current", opt.id); + } + } + element.tabChange(this.option.elem, opt.id); + sessionStorage.setItem(this.option.elem + "-pear-tab-page-data-current", opt.id); + } + + /** + * 刷新当前选型卡 + * + * @param time 动画时长 + */ + tabPage.prototype.refresh = function (time) { + + var $iframe = $(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-content .layui-show > *"); + var $iframeLoad; + + if (time != false && time != 0) { + $iframeLoad = $("#" + this.option.elem).find(".pear-tab-page-loading"); + $iframeLoad.css({ + display: "block" + }); + } + + if ($iframe.attr("type") === "_iframe") { + $iframe.attr("src", $iframe.attr("src")); + $iframe.on("load", function () { + $iframeLoad.fadeOut(1000, function () { + $iframeLoad.css({ + display: "none" + }); + }); + }) + } else { + $.ajax({ + url: $iframe.attr("src"), + type: 'get', + dataType: 'html', + success: function (data) { + $iframe.html(data); + if ($iframeLoad != undefined) { + $iframeLoad.fadeOut(1000, function () { + $iframeLoad.css({ + display: "none" + }); + }); + } + }, + error: function (xhr) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + } + + function tabDelete(elem, id, callback) { + var tabTitle = $(".layui-tab[lay-filter='" + elem + "']").find(".layui-tab-title"); + var removeTab = tabTitle.find("li[lay-id='" + id + "']"); + var nextNode = removeTab.next("li"); + if (!removeTab.hasClass("layui-this")) { + removeTab.remove(); + var tabContent = $(".layui-tab[lay-filter='" + elem + "']").find("*[id='" + id + "']") + .parent(); + tabContent.remove(); + + tabData = JSON.parse(sessionStorage.getItem(elem + "-pear-tab-page-data")); + tabDataCurrent = sessionStorage.getItem(elem + "-pear-tab-page-data-current"); + tabData = tabData.filter(function (item) { + return item.id != id; + }) + sessionStorage.setItem(elem + "-pear-tab-page-data", JSON.stringify(tabData)); + return false; + } + + var currId; + if (nextNode.length) { + nextNode.addClass("layui-this"); + currId = nextNode.attr("lay-id"); + $("#" + elem + " [id='" + currId + "']").parent().addClass("layui-show"); + } else { + var prevNode = removeTab.prev("li"); + prevNode.addClass("layui-this"); + currId = prevNode.attr("lay-id"); + $("#" + elem + " [id='" + currId + "']").parent().addClass("layui-show"); + } + callback(currId); + tabData = JSON.parse(sessionStorage.getItem(elem + "-pear-tab-page-data")); + tabDataCurrent = sessionStorage.getItem(elem + "-pear-tab-page-data-current"); + tabData = tabData.filter(function (item) { + return item.id != id; + }) + sessionStorage.setItem(elem + "-pear-tab-page-data", JSON.stringify(tabData)); + sessionStorage.setItem(elem + "-pear-tab-page-data-current", currId); + removeTab.remove(); + var tabContent = $(".layui-tab[lay-filter='" + elem + "']").find("*[id='" + id + "']").parent(); + tabContent.remove(); + } + + /** + * @since Pear Admin 4.0 + */ + function createTab(option) { + + var type = ""; + if (option.roll == true) { + type = "layui-tab-roll"; + } + if (option.tool != false) { + type = "layui-tab-tool"; + } + if (option.roll == true && option.tool != false) { + type = "layui-tab-rollTool"; + } + var tab = '
                                                                                                                  '; + + var headers = '
                                                                                                                    '; + var content = '
                                                                                                                    '; + var loading = '
                                                                                                                    ' + var control = `
                                                                                                                    +
                                                                                                                  • +
                                                                                                                  • +
                                                                                                                  • +
                                                                                                                    `; + + // 处 理 选 项 卡 头 部 + var index = 0; + + $.each(option.data, function (i, item) { + + var titleItem = `
                                                                                                                  • + + + ${item.title} + + ဆ
                                                                                                                  • + `; + + headers += titleItem; + + if (item.type === "_iframe") { + + content += `
                                                                                                                    ` + + } else { + + $.ajax({ + url: item.url, + type: 'get', + dataType: 'html', + async: false, + success: function (data) { + content += `
                                                                                                                    ${data}
                                                                                                                    `; + }, + error: function (xhr) { + return layer.msg('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!'); + } + }); + } + + index++; + }); + + headers += '
                                                                                                                  '; + content += '
                                                                                                                  '; + + tab += headers; + tab += control; + tab += content; + tab += loading; + tab += '
                                                                                                                  '; + tab += '' + return tab; + } + + function rollPage(d, option) { + var $tabTitle = $('#' + option.elem + ' .layui-tab-title'); + var left = $tabTitle.scrollLeft(); + if ('left' === d) { + $tabTitle.animate({ + scrollLeft: left - 450 + }, 200); + } else { + $tabTitle.animate({ + scrollLeft: left + 450 + }, 200); + } + } + + function closeEvent(option) { + $(".layui-tab[lay-filter='" + option.elem + "']").on("click", ".layui-tab-close", function () { + var layid = $(this).parent().attr("lay-id"); + tabDelete(option.elem, layid, option.closeEvent, option); + }) + } + + function menuEvent(option, index) { + + $("#" + option.elem + "closeThis").click(function () { + var currentTab = contextTabDOM; + + if (currentTab.find("span").is(".able-close")) { + var currentId = currentTab.attr("lay-id"); + tabDelete(option.elem, currentId, option.closeEvent, option); + } else { + layer.msg("当前页面不允许关闭", { + icon: 3, + time: 800 + }) + } + layer.close(index); + }) + + $("#" + option.elem + "closeOther").click(function () { + var currentId = contextTabDOM.attr("lay-id"); + var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li"); + $.each(tabtitle, function (i) { + if ($(this).attr("lay-id") != currentId) { + if ($(this).find("span").is(".able-close")) { + tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, + option); + } + } + }) + layer.close(index); + }) + + $("#" + option.elem + "closeAll").click(function () { + var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li"); + $.each(tabtitle, function (i) { + if ($(this).find("span").is(".able-close")) { + tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, option); + } + }) + layer.close(index); + }) + } + + function mousewheelAndTouchmoveHandler(option) { + var $bodyTab = $("body .layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title") + var $tabTitle = $('#' + option.elem + ' .layui-tab-title'); + var mouseScrollStep = 100 + // 鼠标滚轮 + $bodyTab.on("mousewheel DOMMouseScroll", function (e) { + e.originalEvent.preventDefault() + var delta = (e.originalEvent.wheelDelta && (e.originalEvent.wheelDelta > 0 ? "top" : + "down")) || // chrome & ie + (e.originalEvent.detail && (e.originalEvent.detail > 0 ? "down" : "top")); // firefox + var scrollLeft = $tabTitle.scrollLeft(); + + if (delta === "top") { + scrollLeft -= mouseScrollStep + } else if (delta === "down") { + scrollLeft += mouseScrollStep + } + $tabTitle.scrollLeft(scrollLeft) + }); + + // 触摸移动 + var touchX = 0; + $bodyTab.on("touchstart", function (e) { + var touch = e.originalEvent.targetTouches[0]; + touchX = touch.pageX + }) + $bodyTab.on("touchmove", function (e) { + var event = e.originalEvent; + if (event.targetTouches.length > 1) return; + event.preventDefault(); + var touch = event.targetTouches[0]; + var distanceX = touchX - touch.pageX + var scrollLeft = $tabTitle.scrollLeft(); + touchX = touch.pageX + $tabTitle.scrollLeft(scrollLeft += distanceX) + }); + } + + exports(MOD_NAME, new tabPage()); +}) diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/module/tools.js b/demo/webman/frontend/layui_admin_flow/component/pear/module/tools.js new file mode 100644 index 0000000000000000000000000000000000000000..373ac01ed05ba05a01cefb3bd848a84d0a2ec70f --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/module/tools.js @@ -0,0 +1,40 @@ +layui.define(['jquery', 'element'], + function (exports) { + + var $ = layui.jquery; + var tools = new function () { + + /** + * @since 防抖算法 + * + * @param fn 要执行的方法 + * @param time 防抖时间参数 + */ + this.debounce = function (fn, time) { + var timer = null + return function () { + var arguments = arguments[0] + if (timer) { + clearTimeout(timer) + } + timer = setTimeout(function () { + fn(arguments) + }, time) + } + } + + // image 转 base64 + this.imageToBase64 = function (img) { + var canvas = document.createElement("canvas"); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext("2d"); + ctx.drawImage(img, 0, 0, img.width, img.height); + var ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase(); + var dataURL = canvas.toDataURL("image/" + ext); + return dataURL; + } + }; + + exports('tools', tools); + }) diff --git a/demo/webman/frontend/layui_admin_flow/component/pear/pear.js b/demo/webman/frontend/layui_admin_flow/component/pear/pear.js new file mode 100644 index 0000000000000000000000000000000000000000..7acd256a39fc8ca36aa21a19ad520d6e8e5a8979 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/component/pear/pear.js @@ -0,0 +1,37 @@ +window.rootPath = (function (src) { + src = document.currentScript + ? document.currentScript.src + : document.scripts[document.scripts.length - 1].src; + return src.substring(0, src.lastIndexOf("/") + 1); +})(); + +layui.config({ + base: rootPath + "module/", + version: "4.0.3" +}).extend({ + admin: "admin", + page: "page", + tabPage: "tabPage", + menu: "menu", + fullscreen: "fullscreen", + messageCenter: "messageCenter", + menuSearch: "menuSearch", + button: "button", + tools: "tools", + popup: "extends/popup", + count: "extends/count", + toast: "extends/toast", + nprogress: "extends/nprogress", + echarts: "extends/echarts", + echartsTheme: "extends/echartsTheme", + yaml: "extends/yaml", + encrypt:"extends/encrypt", + theme: "other/theme",//主题 + common: "other/common", + dtree: "other/dtree/dtree",// 树结构 + xmSelect: "other/xm-select", // 下拉多选组件 + iconPicker: "other/iconPicker", + notice: "other/notice", // 消息提示组件 + design: "other/design", // 表单设计 + +}).use([], function () { }); \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/config/common.js b/demo/webman/frontend/layui_admin_flow/config/common.js new file mode 100644 index 0000000000000000000000000000000000000000..c5be556ec7f8183ccab0ffd79b793ee1d48849be --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/config/common.js @@ -0,0 +1,307 @@ +function isString(str) { + if (typeof (str) === 'string') return true; + return false; +} + +/** + * 修正中文乱码问题 + * @param name + * @returns {null|string} + */ +function getQueryString(name) { + let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); + let r = window.location.search.substr(1).match(reg); + if (r != null) return decodeURIComponent(r[2]); + return null; +} + +/** + * 数组in + * @param search + * @param array + * @returns {boolean} + */ +function in_array(search, array) { + for (let i in array) { + if (array[i] == search) { + return true; + } + } + return false; +} + + +/** + * 鹰:OK + */ +//保存、获取 用户信息 +const setUserInfo = (userinfo) => { + //localStorage 持久化存储:layui.data(table, settings),数据会永久存在,除非物理删除。 + //sessionStorage 会话性存储:layui.sessionData(table, settings),页面关闭后即失效。注:layui 2.2.5 新增 + if (userinfo === undefined || userinfo === null) layui.data('lms', { + key: 'userInfo', remove: true + }); else layui.data('lms', { + key: 'userInfo', value: userinfo + }); +} +const getUserInfo = () => { + return layui.data('lms').userInfo; +} + +/** + * 检查登录,没有登录返回false,否则返回 用户信息对象 + * 鹰:OK + * options.nav:为true则没有登录时跳转至登录界面。 + * @return {Boolean} + */ +const checkLogin = (options = {}) => { + const userInfo = getUserInfo(); + if (typeof (userInfo) === 'object' && userInfo !== null) { + return userInfo; + } + + //是否需要自动跳转到login页面 + if (options.nav === true) { + options.nav = './login.html'; + } + if (isString(options.nav)) { + location.href = options.nav; + } + return false; +} + + +//制作菜单 +//rules为服务器返回的所有权限数组(平行) +//type为1则只返回 菜单类型 的菜单,否则也返回 菜单和API 的菜单 +//setKeysById:给特定id新增一个key并赋值value。如果为null则忽略 +// 格式:[ids, key, value] //ids是列表,Permission的id只要在这个列表内就赋值 +const fMakeMenu = function (rules, type = 1, setKeysById = null) { + let retMenu = []; // 返回值(也是顶层menu) + let tmpMenu = new Map(); // 按id为key的menu + rules.forEach((r) => { + if (type === 1 && r.auth_type !== 1) { + // api + return; + } + if (r.is_show !== 1) { + // 是否显示 + return; + } + + // 制作菜单: + let menu = tmpMenu.get(r.id) || {type: 1}; + menu.id = r.id; + menu.title = r.menu_name; + menu.icon = 'layui-icon ' + r.icon; + menu.openType = "_iframe"; + menu.href = r.menu_path; + + // 加入额外的keys + if (setKeysById) { + // 如果这个id在给定的Id列表内 + if (setKeysById[0].includes(r.id.toString())) { + menu[setKeysById[1]] = setKeysById[2]; // 给特定key赋值 + } + } + + if (r.pid === '-1') { + // 顶层 + retMenu.push(menu); + } else { + let parentMenu = tmpMenu.get(r.pid) || {children: []}; // 父菜单 + parentMenu.type = 0; // 菜单 + parentMenu.children = parentMenu.children || []; + parentMenu.children.push(menu); // 加入父菜单 children + tmpMenu.set(r.pid, parentMenu); + } + + tmpMenu.set(r.id, menu); + }); + + return retMenu; +}; + + +const fGetLastNodes = function (rules) { + + let parentNodes = []; + let lastNodes = []; + let allNodes = []; + + + for (let r of rules) { + allNodes.push(r.id); + if (parentNodes.indexOf(r.pid) < 0) parentNodes.push(r.pid); + } + + + lastNodes = allNodes.filter(item => { + //差集 + return !parentNodes.includes(item); + //交集 + //return parentNodes.includes(item) + }); + + return lastNodes; +} + + +function screen() { + if (typeof width !== 'number' || width === 0) { + width = $(window).width() * 0.8; + } + if (typeof height !== 'number' || height === 0) { + height = $(window).height() - 20; + } + return [width + 'px', height + 'px']; +} + +function getColumnValues(data, columnName) { + return data.map(function (item) { + return item[columnName]; + }); +} + +/** + * 递归lay-ui Tree 数据 + * @param data + * @param parentId + * @param idField + * @param titleField + * @param parentField + * @returns {*[]} + */ +function convertToLayuiTree(data, parentId = '0', idField = 'id', titleField = 'title', parentField = 'parent_id') { + let result = []; + + for (let i = 0; i < data.length; i++) { + if (data[i][parentField] === parentId) { + let item = { + id: data[i][idField], + parentId: data[i][parentField], + title: data[i][titleField], + children: convertToLayuiTree(data, data[i][idField], idField, titleField, parentField) + }; + result.push(item); + } + } + + return result; +} + +/** + * 返回Lay-uiTree 最后节点IDS + * @param ids + * @param treeData + * @returns {*[]} + */ +const getSelectedLastNodeIds = function (ids, treeData) { + let lastNodeIds = []; + // 递归遍历树节点 + const traverseTree = function (nodes) { + for (let node of nodes) { + // 如果当前节点有子节点,则继续递归遍历子节点 + if (node.children && node.children.length > 0) { + traverseTree(node.children); + } else { + // 如果当前节点是最后一级节点,并且在ids数组中,则将其id添加到lastNodeIds数组中 + if (ids.includes(node.id)) { + lastNodeIds.push(node.id); + } + } + } + }; + + // 遍历树节点 + traverseTree(treeData); + return lastNodeIds; +}; + +/** + * 提取二维数组字段集合v1.11 + * @param array + * @param column + * @returns {*} + */ +const array_column = function (array, column) { + return array.map(item => item[column]); +} + +/** + * 树形数据追加checkArr 适配dtree v1.11 + * @param data + */ +const appendCheckArr = function (data, level = 0) { + if (!Array.isArray(data)) { + return; + } + data.forEach(function (node) { + node.checkArr = [{"type": "0", "checked": level, 'half': false}]; + if (Array.isArray(node.children) && node.children.length > 0) { + appendCheckArr(node.children, level); + } + }); +} + +/** + * 扁平数组转树形v1.11 + * @param data + * @param parentId + * @param idKey + * @param parentKey + * @param childrenKey + * @returns {*[]} + */ +const flattenToTree = function (data, parentId = '-1', idKey = 'id', parentKey = 'pid', childrenKey = 'children') { + let tree = []; + // 遍历数据,将每个节点添加到对应的父节点下 + layui.$.each(data, function (index, item) { + if (item[parentKey] === parentId) { + let children = flattenToTree(data, item[idKey], idKey, parentKey, childrenKey); + if (children.length > 0) { + item[childrenKey] = children; + } + tree.push(item); + } + }); + return tree; +}; + + +/** + * 浏览页面顶部搜索框展开收回控制 + */ +// function toggleSearchFormShow() { +// let $ = layui.$; +// let items = $('.top-search-from .layui-form-item'); +// if (items.length <= 2) { +// if (items.length <= 1) $('.top-search-from').parent().parent().remove(); +// return; +// } +// let btns = $('.top-search-from .toggle-btn a'); +// let toggle = toggleSearchFormShow; +// if (typeof toggle.hide === 'undefined') { +// btns.on('click', function () { +// toggle(); +// }); +// } +// let countPerRow = parseInt($('.top-search-from').width() / $('.layui-form-item').width()); +// if (items.length <= countPerRow) { +// return; +// } +// btns.removeClass('layui-hide'); +// toggle.hide = !toggle.hide; +// if (toggle.hide) { +// for (let i = countPerRow - 1; i < items.length - 1; i++) { +// $(items[i]).hide(); +// } +// return $('.top-search-from .toggle-btn a:last').addClass('layui-hide'); +// } +// items.show(); +// $('.top-search-from .toggle-btn a:first').addClass('layui-hide'); +// } + +// layui.$(function () { +// toggleSearchFormShow(); +// }); diff --git a/demo/webman/frontend/layui_admin_flow/config/config.js b/demo/webman/frontend/layui_admin_flow/config/config.js new file mode 100644 index 0000000000000000000000000000000000000000..2b36bf77c849c08777c3e6193d96d3c2002dac80 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/config/config.js @@ -0,0 +1,22 @@ +const config = { + // api_url: "http://flow.webman.ingenstream.cn", + api_url: "http://127.0.0.1:8787", + base_path: "/layui_admin_flow/", +} + +window.errors = function (html) { + let MODULE_PATH = 'view/exception/' + html; + layer.open({ + type: 2, + title: false, + skin: 'layui-layer-win10', // 2.8+ + shadeClose: true, // 点击遮罩区域,关闭弹层 + closeBtn: false, + maxmin: false, + shade: 0.1, + area: ['100%', '100%'], + content: MODULE_PATH, + cancel: function () { + } + }); +} diff --git a/demo/webman/frontend/layui_admin_flow/config/pear.config.json b/demo/webman/frontend/layui_admin_flow/config/pear.config.json new file mode 100644 index 0000000000000000000000000000000000000000..2c1334d50842bc79dbe8555928018dd96537bbe9 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/config/pear.config.json @@ -0,0 +1,70 @@ +{ + "logo": { + "title": "Pear Admin", + "image": "admin/images/logo.png" + }, + "menu": { + "data": "admin/data/menu.json", + "method": "GET", + "accordion": true, + "collapse": false, + "control": false, + "controlWidth": 500, + "select": "10", + "async": true + }, + "tab": { + "enable": true, + "keepState": true, + "session": true, + "preload": false, + "max": "30", + "index": { + "id": "10", + "href": "view/console/console1.html", + "title": "首页" + } + }, + "theme": { + "defaultColor": "2", + "defaultMenu": "dark-theme", + "defaultHeader": "light-theme", + "allowCustom": true, + "banner": false + }, + "colors": [ + { + "id": "1", + "color": "#2d8cf0", + "second": "#ecf5ff" + }, + { + "id": "2", + "color": "#36b368", + "second": "#f0f9eb" + }, + { + "id": "3", + "color": "#f6ad55", + "second": "#fdf6ec" + }, + { + "id": "4", + "color": "#f56c6c", + "second": "#fef0f0" + }, + { + "id": "5", + "color": "#3963bc", + "second": "#ecf5ff" + } + ], + "other": { + "keepLoad": "1200", + "autoHead": false, + "footer": false + }, + "header": { + "message": "admin/data/message.json" + } +} \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/config/pear.config.yml b/demo/webman/frontend/layui_admin_flow/config/pear.config.yml new file mode 100644 index 0000000000000000000000000000000000000000..0db0d3cd98d01e07888c73c430620ce886c0942e --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/config/pear.config.yml @@ -0,0 +1,85 @@ +## 网站配置 +logo: + ## 网站名称 + title: "Ingenious 工作流引擎" + ## 网站图标 + image: "admin/images/logo.png" +## 菜单配置 +menu: + ## 菜单数据 + data: "http://127.0.0.1:8787/adminapi/setting/permission" + ##data: "admin/data/menu.json" + ## GET / POST + method: "GET" + ## 菜单手风琴 + accordion: true + ## 默认折叠状态 + collapse: false + ## 多菜单模式 + control: false + ## 默认选中的菜单项 + select: "10" + ## 是否开启异步菜单,false 时 data 属性设置为静态数据,true 时为后端接口 + async: false +## 视图内容配置 +tab: + ## 是否开启多选项卡 + enable: true + ## 保持视图状态 + keepState: true + ## 开启选项卡记忆 + session: true + ## 浏览器刷新时是否预加载非激活标签页 + preload: true + ## 可打开的数量, false 不限制极值 + max: "30" + ## 首页 + index: + id: "10" ## 标识 ID , 建议与菜单项中的 ID 一致 + href: "view/console/index.html" ## 页面地址 + title: "首页" ## 标题 +## 主题配置 +theme: + ## 默认主题色,对应 colors 配置中的 ID 标识 + defaultColor: "2" + ## 默认的菜单主题 dark-theme 黑 / light-theme 白 + defaultMenu: "dark-theme" + ## 默认的顶部主题 dark-theme 黑 / light-theme 白 + defaultHeader: "light-theme" + ## 是否允许用户切换主题,false 时关闭自定义主题面板 + allowCustom: true + ## 通栏配置 + banner: false + dark: false +## 主题色配置列表 +colors: +- id: "1" + color: "#16baaa" + second: "#ecf5ff" +- id: "2" + color: "#009688" + second: "#ecf5ff" +- id: "3" + color: "#36b368" + second: "#f0f9eb" +- id: "4" + color: "#f6ad55" + second: "#fdf6ec" +- id: "5" + color: "#f56c6c" + second: "#fef0f0" +- id: "6" + color: "#3963bc" + second: "#ecf5ff" +## 其他配置 +other: + ## 主页动画时长 + keepLoad: "1200" + ## 布局顶部主题 + autoHead: false + ## 页脚 + footer: false +## 头部配置 +header: + ## 站内消息,通过 false 设置关闭 + message: "admin/data/message.json" diff --git a/demo/webman/frontend/layui_admin_flow/config/permission.js b/demo/webman/frontend/layui_admin_flow/config/permission.js new file mode 100644 index 0000000000000000000000000000000000000000..3ac2d7f9b19d8f683f97748bc6d2d423fd76d4fd --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/config/permission.js @@ -0,0 +1,147 @@ +/** + * 获取控制器详细权限,并决定展示哪些按钮或dom元素 + */ +layui.$(function () { + let $ = layui.$; + let userInfo = getUserInfo(); + if (userInfo === undefined) { + return; + } + if (userInfo.isLogin != undefined && userInfo.isLogin === true) { + let style = '' + let isSupperAdmin = false; + let level = userInfo.info.level != undefined && userInfo.info.level === 0 ? true : false; + if (level) { + $("head").append(""); + isSupperAdmin = true; + } + if (isSupperAdmin) return; + + + // 细分权限 + let codes = getUserInfo().unique_auth !== undefined ? getUserInfo().unique_auth : []; + layui.each(codes, function (k, code) { + codes[k] = '*[permission^="' + code + '"]'; + }); + if (codes.length) { + $("head").append(""); + } + } +}); + +const $request = (params) => { + let $ = layui.jquery; + let userinfo = checkLogin({ + nav: true + }); + if (userinfo === false) { + return false; + } + return new Promise((resolve, reject) => { + $.ajax({ + headers: { + "Authori-zation": "Bearer " + userinfo["token"] ?? 'Bearer', + Author: 'Leamus', + 'Access-Control-Allow-Origin': '*', + }, ...params, success(ret) { + // 返回成功 + if (ret && ret.status === 200) { + resolve(ret); + } else { + reject(ret); + } + }, error(ret) { + // 返回Token过期 + if (ret && ret.status === 401) { + if (ret["responseJSON"].code < 0) { + // 需要重新登录 + setUserInfo(null); + location.href = 'login.html'; + } else { + console.log('刷新token'); + // 刷新处理Token + setUserInfo({ + isLogin: true, "token": ret.data.token, info: ret.data.info, rules: ret.data.rules, + }); + // 将原来请求重新发送 + $request(params).then(resolve).catch(reject); + } + } else { + reject(ret); + } + }, + }); + }); +}; + +// 设置请求默认值 +layui.$.ajaxSetup({ + beforeSend: function (xhr) { + if (getUserInfo() == '' || getUserInfo() == null || getUserInfo() == undefined) { + location.href = 'index.html'; + return; + } + }, + headers: { + //自定义标头 + 'Author': 'Leamus', + 'Authorization': getUserInfo() != undefined ? "Bearer " + getUserInfo()["token"] : 'Bearer' + }, + complete: function (xhr) { + // 设置登陆拦截 + if (xhr.status === 401) { + let ret = xhr['responseJSON'] !== undefined ? xhr['responseJSON'] : []; + if (ret['code'] === undefined || ret['code'] != 0) { + setUserInfo(null); + location.href = 'index.html' + } + setUserInfo({ + isLogin: true, "token": ret.data.token, info: ret.data.info, rules: ret.data.rules, + }); + //继续完成当前访问 + layui.$.ajax(this) + } + if (xhr.status === 403) { + window.errors('403.html') + } + if (xhr.status === 404) { + window.errors('404.html') + } + if (xhr.status === 500) { + window.errors('500.html') + } + if (xhr.responseJSON !== undefined && xhr.responseJSON.status !== undefined && xhr.responseJSON.status === 110003) { + setUserInfo(null); + location.href = 'index.html' + } + }, +}); + +/** + * 超时没有操作退出 + * @type {number} + */ +let lastTime = new Date().getTime(); +let currentTime = new Date().getTime(); +let timeOut = 15 * 60 * 1000; //设置超时时间: 15分 + +layui.$(function () { + /* 鼠标移动事件 */ + layui.$(document).mouseover(function () { + lastTime = new Date().getTime(); //更新操作时间 + }); +}); + +function toLoginPage() { + currentTime = new Date().getTime(); //更新当前时间 + if (currentTime - lastTime > timeOut) { //判断是否超时 + window.close();//关闭当前页 + location.href = 'login.html'; + // window.parent.location.replace("toLogin.do");//刷新父级页面; + } +} + +/* 定时器 + * 间隔1秒检测是否长时间未操作页面 + */ +// window.setInterval(toLoginPage, 1000); diff --git a/demo/webman/frontend/layui_admin_flow/favicon.ico b/demo/webman/frontend/layui_admin_flow/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..12b1ca34ac9a0a4d4774d3929adde2fa932a1e99 Binary files /dev/null and b/demo/webman/frontend/layui_admin_flow/favicon.ico differ diff --git a/demo/webman/frontend/layui_admin_flow/index.html b/demo/webman/frontend/layui_admin_flow/index.html new file mode 100644 index 0000000000000000000000000000000000000000..7fc837424f7ef83c8469a178071f289aede814e8 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/index.html @@ -0,0 +1,178 @@ + + + + + Ingenious Admin + + + + + + + + + + + + +
                                                                                                                  + +
                                                                                                                  + + + +
                                                                                                                    +
                                                                                                                  • +
                                                                                                                  • +
                                                                                                                  • +
                                                                                                                  + +
                                                                                                                  + + +
                                                                                                                  + +
                                                                                                                  + + + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  + +
                                                                                                                  +
                                                                                                                  + + + +
                                                                                                                  + +
                                                                                                                  + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  + +
                                                                                                                  + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/login.html b/demo/webman/frontend/layui_admin_flow/login.html new file mode 100644 index 0000000000000000000000000000000000000000..2ade401aefdbde83aab50002a8241bd6f7864f5e --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/login.html @@ -0,0 +1,156 @@ + + + + + + 登录 + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/nginx.htaccess b/demo/webman/frontend/layui_admin_flow/nginx.htaccess new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/demo/webman/frontend/layui_admin_flow/view/console/index.html b/demo/webman/frontend/layui_admin_flow/view/console/index.html new file mode 100644 index 0000000000000000000000000000000000000000..e9f40e0bb9b38ab239135f39833858f0eecc40ae --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/console/index.html @@ -0,0 +1,336 @@ + + + + + + 工作台 + + + + + + + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + 快捷菜单 +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  + 待办 +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  + 已办 +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  + 抄送 +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  + 发起 +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  + 表单 +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  + 设计 +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  + 追踪 +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  + 收藏 +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + 代办任务 +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  我的待办
                                                                                                                  +
                                                                                                                  21
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  我的已办
                                                                                                                  +
                                                                                                                  63
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  我的待阅
                                                                                                                  +
                                                                                                                  32
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  我的申请
                                                                                                                  +
                                                                                                                  14
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + + + + + + + + + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  留言板
                                                                                                                  +
                                                                                                                  +
                                                                                                                    +
                                                                                                                  • +

                                                                                                                    要不要作为我的家人,搬来我家。

                                                                                                                    + +
                                                                                                                  • +
                                                                                                                  • +

                                                                                                                    快乐的时候不敢尽兴,频繁警戒自己保持清醒。

                                                                                                                    +
                                                                                                                  • +
                                                                                                                  • +

                                                                                                                    夏天真的来了,尽管它还有些犹豫。

                                                                                                                    +
                                                                                                                  • +
                                                                                                                  • +

                                                                                                                    Ingenious 工作流引擎,尽管它还有些犹豫。

                                                                                                                    + + +
                                                                                                                  • +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/exception/403.html b/demo/webman/frontend/layui_admin_flow/view/exception/403.html new file mode 100644 index 0000000000000000000000000000000000000000..4b40a775c5be7771fee51321f37d197b1d43f74b --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/exception/403.html @@ -0,0 +1,30 @@ + + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +

                                                                                                                  403

                                                                                                                  +
                                                                                                                  +
                                                                                                                  + 抱歉, 你无权访问该页面. +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + diff --git a/demo/webman/frontend/layui_admin_flow/view/exception/404.html b/demo/webman/frontend/layui_admin_flow/view/exception/404.html new file mode 100644 index 0000000000000000000000000000000000000000..534c2f736cc793d2188749a32d8e82e53c1bb3d2 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/exception/404.html @@ -0,0 +1,30 @@ + + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +

                                                                                                                  404

                                                                                                                  +
                                                                                                                  +
                                                                                                                  + 抱歉, 你访问的页面不存在. +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/exception/500.html b/demo/webman/frontend/layui_admin_flow/view/exception/500.html new file mode 100644 index 0000000000000000000000000000000000000000..50545070af7522219990a2d27d7d827df26a0a83 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/exception/500.html @@ -0,0 +1,30 @@ + + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +

                                                                                                                  500

                                                                                                                  +
                                                                                                                  +
                                                                                                                  + 抱歉, 服务器出错了. +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/file/category/add.html b/demo/webman/frontend/layui_admin_flow/view/file/category/add.html new file mode 100644 index 0000000000000000000000000000000000000000..b3e4d3a77564e52384948b55b63e218d2db125fd --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/file/category/add.html @@ -0,0 +1,226 @@ + + + + + 新增字典 + + + + + +
                                                                                                                  + +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  +
                                                                                                                  + +
                                                                                                                  +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    + +
                                                                                                                    + +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    + +
                                                                                                                    +
                                                                                                                    + +
                                                                                                                    + +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    + +
                                                                                                                    + +
                                                                                                                    + +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    + +
                                                                                                                    +
                                                                                                                    + + +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/file/category/index.html b/demo/webman/frontend/layui_admin_flow/view/file/category/index.html new file mode 100644 index 0000000000000000000000000000000000000000..e68a8f27a9c23066e23dea03ad9ff605db16ed90 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/file/category/index.html @@ -0,0 +1,270 @@ + + + + + 附件分类 + + + + + +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/file/list/add.html b/demo/webman/frontend/layui_admin_flow/view/file/list/add.html new file mode 100644 index 0000000000000000000000000000000000000000..3bd64b87982942a5817361ca6cedf54ccbd85812 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/file/list/add.html @@ -0,0 +1,236 @@ + + + + + + + + + +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    +
                                                                                                                    + +
                                                                                                                    +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      + +
                                                                                                                      + +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      + + + + + + + + + + + + + + + + +
                                                                                                                      文件名大小文件上传进度操作
                                                                                                                      +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      + + +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/file/list/edit.html b/demo/webman/frontend/layui_admin_flow/view/file/list/edit.html new file mode 100644 index 0000000000000000000000000000000000000000..0bd2ddb3d71205e975afb045ebfa065a1d208631 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/file/list/edit.html @@ -0,0 +1,170 @@ + + + + + + + + + +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      +
                                                                                                                      + +
                                                                                                                      +
                                                                                                                        +
                                                                                                                        +
                                                                                                                        +
                                                                                                                        + +
                                                                                                                        + +
                                                                                                                        +
                                                                                                                        +
                                                                                                                        +
                                                                                                                        +
                                                                                                                        +
                                                                                                                        + + +
                                                                                                                        +
                                                                                                                        +
                                                                                                                        + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/file/list/index.html b/demo/webman/frontend/layui_admin_flow/view/file/list/index.html new file mode 100644 index 0000000000000000000000000000000000000000..243bfa911230c3cebab5662478f1dd66abcc84ad --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/file/list/index.html @@ -0,0 +1,393 @@ + + + + + 附件管理 + + + + +
                                                                                                                        +
                                                                                                                        +
                                                                                                                        +
                                                                                                                        + +
                                                                                                                        +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/lang/country/add.html b/demo/webman/frontend/layui_admin_flow/view/setting/lang/country/add.html new file mode 100644 index 0000000000000000000000000000000000000000..3c6c9eb9477fe13b7a0d4e6fd7d111dc2b99237f --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/lang/country/add.html @@ -0,0 +1,166 @@ + + + + + + + + + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          例如:中国、香港、德国
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          浏览器语言识别码
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          请选择关联语言,语言类型是由您自行添加的
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/lang/country/index.html b/demo/webman/frontend/layui_admin_flow/view/setting/lang/country/index.html new file mode 100644 index 0000000000000000000000000000000000000000..a7ae88da6f23fb54d0b19e4e8127460efed599bc --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/lang/country/index.html @@ -0,0 +1,232 @@ + + + + + 地区列表 + + + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + + +
                                                                                                                          +
                                                                                                                          + 展开 + 收起 +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/lang/info/add.html b/demo/webman/frontend/layui_admin_flow/view/setting/lang/info/add.html new file mode 100644 index 0000000000000000000000000000000000000000..4194d18a7d5935f7fe9abd6784ed3559fd57a067 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/lang/info/add.html @@ -0,0 +1,286 @@ + + + + + + + + + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/lang/info/index.html b/demo/webman/frontend/layui_admin_flow/view/setting/lang/info/index.html new file mode 100644 index 0000000000000000000000000000000000000000..4622c937c30f2a5e17c3607b3bd24966c77f858b --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/lang/info/index.html @@ -0,0 +1,369 @@ + + + + + 语言详情 + + + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + + + + + +
                                                                                                                          +
                                                                                                                          + 展开 + 收起 +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/lang/list/add.html b/demo/webman/frontend/layui_admin_flow/view/setting/lang/list/add.html new file mode 100644 index 0000000000000000000000000000000000000000..e1c4063953c0e5a13a6d4bd7622f66c3e48ef98b --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/lang/list/add.html @@ -0,0 +1,182 @@ + + + + + + + + + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/lang/list/index.html b/demo/webman/frontend/layui_admin_flow/view/setting/lang/list/index.html new file mode 100644 index 0000000000000000000000000000000000000000..cadaba7412f1076d566b9155f455e5680bef1d58 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/lang/list/index.html @@ -0,0 +1,277 @@ + + + + + 语言列表 + + + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                          + + +
                                                                                                                          + + + +
                                                                                                                          +
                                                                                                                          + 展开 + 收起 +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/org/dept/add.html b/demo/webman/frontend/layui_admin_flow/view/setting/org/dept/add.html new file mode 100644 index 0000000000000000000000000000000000000000..51deae854e30fd61bc50aaad170ec609337f58b5 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/org/dept/add.html @@ -0,0 +1,261 @@ + + + + + 部门新增 + + + + +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          +
                                                                                                                          + +
                                                                                                                          +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            + +
                                                                                                                            + +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            + +
                                                                                                                            + +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            + +
                                                                                                                            + +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            + +
                                                                                                                            + +
                                                                                                                            +
                                                                                                                            + +
                                                                                                                            + +
                                                                                                                            + + +
                                                                                                                            +
                                                                                                                            + + +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            + +
                                                                                                                            +
                                                                                                                            + +
                                                                                                                            +
                                                                                                                            + 清空 +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            + +
                                                                                                                            + +
                                                                                                                            + +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            + + +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/org/dept/index.html b/demo/webman/frontend/layui_admin_flow/view/setting/org/dept/index.html new file mode 100644 index 0000000000000000000000000000000000000000..9fca87d7dfd2bdc9015a107c0231ebb4ccae09ea --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/org/dept/index.html @@ -0,0 +1,313 @@ + + + + + 组织管理 + + + + + +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/org/post/add.html b/demo/webman/frontend/layui_admin_flow/view/setting/org/post/add.html new file mode 100644 index 0000000000000000000000000000000000000000..311bba861ebc2b5858d4af7a77ad5dda212dbaea --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/org/post/add.html @@ -0,0 +1,314 @@ + + + + + + + + +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            +
                                                                                                                            + +
                                                                                                                            +
                                                                                                                            +
                                                                                                                              +
                                                                                                                              +
                                                                                                                              +
                                                                                                                              +
                                                                                                                              + +
                                                                                                                              +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                + +
                                                                                                                                + +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                + +
                                                                                                                                + +
                                                                                                                                +
                                                                                                                                + + +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                + +
                                                                                                                                +
                                                                                                                                + +
                                                                                                                                +
                                                                                                                                + 清空 +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                + +
                                                                                                                                + +
                                                                                                                                + +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                + + +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/org/post/index.html b/demo/webman/frontend/layui_admin_flow/view/setting/org/post/index.html new file mode 100644 index 0000000000000000000000000000000000000000..2216c9277df68eaa5f5bdcbf94352392a2c6abab --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/org/post/index.html @@ -0,0 +1,394 @@ + + + + + 职位管理 + + + + +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                + +
                                                                                                                                + +
                                                                                                                                + +
                                                                                                                                +
                                                                                                                                + +
                                                                                                                                + +
                                                                                                                                + +
                                                                                                                                +
                                                                                                                                + +
                                                                                                                                + + + +
                                                                                                                                +
                                                                                                                                + 展开 + 收起 +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                + + +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/system_admin/add.html b/demo/webman/frontend/layui_admin_flow/view/setting/system_admin/add.html new file mode 100644 index 0000000000000000000000000000000000000000..8f854c0edee19c568db9ce1443cd0288b6e08899 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/system_admin/add.html @@ -0,0 +1,196 @@ + + + + + + + + + + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + +
                                                                                                                                  + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + +
                                                                                                                                  + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + +
                                                                                                                                  + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + +
                                                                                                                                  + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + +
                                                                                                                                  + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + +
                                                                                                                                  + +
                                                                                                                                  +
                                                                                                                                  + +
                                                                                                                                  + +
                                                                                                                                  + + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + +
                                                                                                                                  + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + +
                                                                                                                                  + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/system_admin/dept.html b/demo/webman/frontend/layui_admin_flow/view/setting/system_admin/dept.html new file mode 100644 index 0000000000000000000000000000000000000000..bbf6614751b40852e4dd12605f7a02bf5fd479aa --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/system_admin/dept.html @@ -0,0 +1,258 @@ + + + + + 管理员部门设置 + + + + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + +
                                                                                                                                  + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + +
                                                                                                                                  + +
                                                                                                                                  +
                                                                                                                                  +
                                                                                                                                  + +
                                                                                                                                  +
                                                                                                                                    +
                                                                                                                                    +
                                                                                                                                    +
                                                                                                                                    + +
                                                                                                                                    +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      + + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/system_admin/index.html b/demo/webman/frontend/layui_admin_flow/view/setting/system_admin/index.html new file mode 100644 index 0000000000000000000000000000000000000000..c7b294f0b9deed99c15bd8f911b6ce31afe5b79c --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/system_admin/index.html @@ -0,0 +1,416 @@ + + + + + 用户管理 + + + + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + + + +
                                                                                                                                      +
                                                                                                                                      + 展开 + 收起 +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + + + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/system_admin/person.html b/demo/webman/frontend/layui_admin_flow/view/setting/system_admin/person.html new file mode 100644 index 0000000000000000000000000000000000000000..470fc22d4e9ded253bc2a562ee01ab91bd5a7698 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/system_admin/person.html @@ -0,0 +1,215 @@ + + + + + 基本资料 + + + + +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                        +
                                                                                                                                      • 基本信息
                                                                                                                                      • +
                                                                                                                                      • 安全设置
                                                                                                                                      • +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/system_menus/add.html b/demo/webman/frontend/layui_admin_flow/view/setting/system_menus/add.html new file mode 100644 index 0000000000000000000000000000000000000000..57217b71342aaa57019186cc8fa5702768452c19 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/system_menus/add.html @@ -0,0 +1,413 @@ + + + + + 新增页面 + + + + +
                                                                                                                                      +
                                                                                                                                      +
                                                                                                                                      + + + + + + + + + +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                      + +
                                                                                                                                      + +
                                                                                                                                      +
                                                                                                                                        +
                                                                                                                                        +
                                                                                                                                        + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                                                                                                        + +
                                                                                                                                        +
                                                                                                                                        + +
                                                                                                                                        +
                                                                                                                                        + 清空 +
                                                                                                                                        +
                                                                                                                                        +
                                                                                                                                        + +
                                                                                                                                        + +
                                                                                                                                        + +
                                                                                                                                        +
                                                                                                                                        + +
                                                                                                                                        + +
                                                                                                                                        + + +
                                                                                                                                        +
                                                                                                                                        + +
                                                                                                                                        + +
                                                                                                                                        + +
                                                                                                                                        +
                                                                                                                                        +
                                                                                                                                        +
                                                                                                                                        + +
                                                                                                                                        +
                                                                                                                                        + + +
                                                                                                                                        +
                                                                                                                                        +
                                                                                                                                        + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/system_menus/index.html b/demo/webman/frontend/layui_admin_flow/view/setting/system_menus/index.html new file mode 100644 index 0000000000000000000000000000000000000000..6f6fb812c54eb021c34aecc2362b1c7fe49a126e --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/system_menus/index.html @@ -0,0 +1,358 @@ + + + + + + 权限管理 + + + + + + +
                                                                                                                                        +
                                                                                                                                        +
                                                                                                                                        +
                                                                                                                                        +
                                                                                                                                        + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/system_role/add.html b/demo/webman/frontend/layui_admin_flow/view/setting/system_role/add.html new file mode 100644 index 0000000000000000000000000000000000000000..de2a044013ab03aeed6a889bd485634828147351 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/system_role/add.html @@ -0,0 +1,294 @@ + + + + + 角色新增 + + + + +
                                                                                                                                        +
                                                                                                                                        +
                                                                                                                                        +
                                                                                                                                        + +
                                                                                                                                        +
                                                                                                                                          +
                                                                                                                                          +
                                                                                                                                          + +
                                                                                                                                          + +
                                                                                                                                          + +
                                                                                                                                          +
                                                                                                                                          + +
                                                                                                                                          + +
                                                                                                                                          + +
                                                                                                                                          +
                                                                                                                                          + +
                                                                                                                                          + +
                                                                                                                                          + + +
                                                                                                                                          +
                                                                                                                                          + + +
                                                                                                                                          +
                                                                                                                                          +
                                                                                                                                          + +
                                                                                                                                          +
                                                                                                                                          + +
                                                                                                                                          +
                                                                                                                                          + 清空 +
                                                                                                                                          +
                                                                                                                                          +
                                                                                                                                          +
                                                                                                                                          +
                                                                                                                                          + +
                                                                                                                                          + +
                                                                                                                                          + +
                                                                                                                                          +
                                                                                                                                          + +
                                                                                                                                          +
                                                                                                                                          + +
                                                                                                                                          +
                                                                                                                                          + + +
                                                                                                                                          +
                                                                                                                                          +
                                                                                                                                          + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/system_role/auth.html b/demo/webman/frontend/layui_admin_flow/view/setting/system_role/auth.html new file mode 100644 index 0000000000000000000000000000000000000000..3fdf138d990fd79714a88aef5be4fa3d3cefd58b --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/system_role/auth.html @@ -0,0 +1,169 @@ + + + + + 角色权限 + + + + +
                                                                                                                                          +
                                                                                                                                          +
                                                                                                                                          +
                                                                                                                                          + +
                                                                                                                                          + +
                                                                                                                                          +
                                                                                                                                          +
                                                                                                                                          + +
                                                                                                                                          +
                                                                                                                                            +
                                                                                                                                            +
                                                                                                                                            +
                                                                                                                                            +
                                                                                                                                            + +
                                                                                                                                            +
                                                                                                                                            + + +
                                                                                                                                            +
                                                                                                                                            +
                                                                                                                                            + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/system_role/dept.html b/demo/webman/frontend/layui_admin_flow/view/setting/system_role/dept.html new file mode 100644 index 0000000000000000000000000000000000000000..5de4a2c0833d2f9684616438c9b4fa8e10c440e5 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/system_role/dept.html @@ -0,0 +1,163 @@ + + + + + 分配组织 + + + + +
                                                                                                                                            +
                                                                                                                                            +
                                                                                                                                            +
                                                                                                                                            + +
                                                                                                                                            + +
                                                                                                                                            +
                                                                                                                                            +
                                                                                                                                            + +
                                                                                                                                            +
                                                                                                                                              +
                                                                                                                                              +
                                                                                                                                              +
                                                                                                                                              +
                                                                                                                                              + +
                                                                                                                                              +
                                                                                                                                              + + +
                                                                                                                                              +
                                                                                                                                              +
                                                                                                                                              + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/system_role/index.html b/demo/webman/frontend/layui_admin_flow/view/setting/system_role/index.html new file mode 100644 index 0000000000000000000000000000000000000000..99ebb7d204476a8095a6dcd489a5784ba0e4e65c --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/system_role/index.html @@ -0,0 +1,371 @@ + + + + + 角色管理 + + + + + +
                                                                                                                                              +
                                                                                                                                              +
                                                                                                                                              +
                                                                                                                                              +
                                                                                                                                              + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/setting/system_role/post.html b/demo/webman/frontend/layui_admin_flow/view/setting/system_role/post.html new file mode 100644 index 0000000000000000000000000000000000000000..f5a596f29a3278629f267f6f866ba55fc83b0890 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/setting/system_role/post.html @@ -0,0 +1,166 @@ + + + + + 分配职位 + + + + +
                                                                                                                                              +
                                                                                                                                              +
                                                                                                                                              +
                                                                                                                                              + +
                                                                                                                                              + +
                                                                                                                                              +
                                                                                                                                              +
                                                                                                                                              + +
                                                                                                                                              +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                + + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/start/index.html b/demo/webman/frontend/layui_admin_flow/view/start/index.html new file mode 100644 index 0000000000000000000000000000000000000000..7da7fa24ff2fa3d2cea0596318bebad863fd8f64 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/start/index.html @@ -0,0 +1,57 @@ + + + + + + 成功 + + + + + +
                                                                                                                                                +
                                                                                                                                                +   项目地址 + 点亮小星星才可以使用演示系统哦(◠‿◠) +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/backend_routing/add.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/backend_routing/add.html new file mode 100644 index 0000000000000000000000000000000000000000..37c7d6391bfdb4b9859d05ef5eeab18a66caa48d --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/backend_routing/add.html @@ -0,0 +1,399 @@ + + + + + 接口维护 + + + + + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                接口信息
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                调用方式
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                + + +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                + + +
                                                                                                                                                + 调用示例 +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                + + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/backend_routing/cate.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/backend_routing/cate.html new file mode 100644 index 0000000000000000000000000000000000000000..0b039003822aa0b4c997e7bd70f9e63297ab8a4d --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/backend_routing/cate.html @@ -0,0 +1,95 @@ + + + + + 添加分类 + + + + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/backend_routing/debug.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/backend_routing/debug.html new file mode 100644 index 0000000000000000000000000000000000000000..dc0b70659475b964d928a6503e84f4490e7f52a9 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/backend_routing/debug.html @@ -0,0 +1,236 @@ + + + + + API 调试页面 + + + + + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                  +
                                                                                                                                                • Params
                                                                                                                                                • +
                                                                                                                                                • Body
                                                                                                                                                • +
                                                                                                                                                • Header
                                                                                                                                                • +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                + +
                                                                                                                                                + +
                                                                                                                                                
                                                                                                                                                +
                                                                                                                                                + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/backend_routing/index.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/backend_routing/index.html new file mode 100644 index 0000000000000000000000000000000000000000..f27308f02b14ee5e14cfb4b6965ccedcdf7bf1b9 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/backend_routing/index.html @@ -0,0 +1,529 @@ + + + + + 接口管理 + + + + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                  +
                                                                                                                                                • 管理端接口
                                                                                                                                                • +
                                                                                                                                                • 用户端接口
                                                                                                                                                • +
                                                                                                                                                • 对外接口
                                                                                                                                                • +
                                                                                                                                                + +
                                                                                                                                                +
                                                                                                                                                + + +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + 调用方式 +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + + +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + + +
                                                                                                                                                  + 调用示例 +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  
                                                                                                                                                  +                                            
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  
                                                                                                                                                  +                                            
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/clear/index.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/clear/index.html new file mode 100644 index 0000000000000000000000000000000000000000..34aa8cfddd53401977c5334fc6b49c27b8b6bff3 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/clear/index.html @@ -0,0 +1,97 @@ + + + + + 刷新缓存 + + + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/crontab/add.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/crontab/add.html new file mode 100644 index 0000000000000000000000000000000000000000..909fc2c23c3b3d7dcfc29eb5b4ad5c4ac4395280 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/crontab/add.html @@ -0,0 +1,548 @@ + + + + + 新增定时任务 + + + + + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  + + 秒 +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  + + 分 +
                                                                                                                                                  +
                                                                                                                                                  + + +
                                                                                                                                                  +
                                                                                                                                                  + + 时 +
                                                                                                                                                  +
                                                                                                                                                  + + 分 +
                                                                                                                                                  +
                                                                                                                                                  + + +
                                                                                                                                                  +
                                                                                                                                                  + + 日 +
                                                                                                                                                  +
                                                                                                                                                  + + 时 +
                                                                                                                                                  +
                                                                                                                                                  + + 分 +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  + + 时 +
                                                                                                                                                  +
                                                                                                                                                  + + 分 +
                                                                                                                                                  +
                                                                                                                                                  + + 秒 +
                                                                                                                                                  +
                                                                                                                                                  + + +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  + + 时 +
                                                                                                                                                  +
                                                                                                                                                  + + 分 +
                                                                                                                                                  +
                                                                                                                                                  + + 秒 +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  + + 日 +
                                                                                                                                                  +
                                                                                                                                                  + + 时 +
                                                                                                                                                  +
                                                                                                                                                  + + 分 +
                                                                                                                                                  +
                                                                                                                                                  + + 秒 +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  + + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/crontab/index.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/crontab/index.html new file mode 100644 index 0000000000000000000000000000000000000000..87ebe70d5ddbf9fb301e20903c2f910ccd84dfc5 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/crontab/index.html @@ -0,0 +1,284 @@ + + + + + 定时任务 + + + + +
                                                                                                                                                  +
                                                                                                                                                  + + 启动定时任务两种方式: +
                                                                                                                                                  + 1、使用命令启动:php think timer start --d;如果更改了执行周期、编辑是否开启、删除定时任务需要重新启动下定时任务确保生效; +
                                                                                                                                                  + 2、使用接口触发定时任务,建议每分钟调用一次,接口地址 https://您的域名/api/crontab/run +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/form_build/index.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/form_build/index.html new file mode 100644 index 0000000000000000000000000000000000000000..dd271b47d990902e69b7be4c3202459890de06b5 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/form_build/index.html @@ -0,0 +1,152 @@ + + + + + + + 表单生成器 + + + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + + + + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + view +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  html
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  code
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_config/category/add.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_config/category/add.html new file mode 100644 index 0000000000000000000000000000000000000000..c8ab8298b99df87aeac038bd1f15bf5e16a00a71 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_config/category/add.html @@ -0,0 +1,276 @@ + + + + + + 新增配置分配 + + + + + +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  +
                                                                                                                                                  + +
                                                                                                                                                  +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    + +
                                                                                                                                                    + +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    + +
                                                                                                                                                    + +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    + +
                                                                                                                                                    +
                                                                                                                                                    + +
                                                                                                                                                    +
                                                                                                                                                    + 清空 +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    + +
                                                                                                                                                    + + +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    + +
                                                                                                                                                    + + +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    + +
                                                                                                                                                    + +
                                                                                                                                                    +
                                                                                                                                                    + +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    + + +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_config/category/index.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_config/category/index.html new file mode 100644 index 0000000000000000000000000000000000000000..11781240ab2b514ca09c05eab0741ed43f560a29 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_config/category/index.html @@ -0,0 +1,289 @@ + + + + + + 配置分类 + + + + + + +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_config/list/add.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_config/list/add.html new file mode 100644 index 0000000000000000000000000000000000000000..76ce465d0ecda09cb68f3a91d9d0501a34a8f12f --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_config/list/add.html @@ -0,0 +1,366 @@ + + + + + + 新增配置分配 + + + + + +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                      +
                                                                                                                                                    • 文本框
                                                                                                                                                    • +
                                                                                                                                                    • 多行文本框
                                                                                                                                                    • +
                                                                                                                                                    • 单选框
                                                                                                                                                    • +
                                                                                                                                                    • 文件上传
                                                                                                                                                    • +
                                                                                                                                                    • 多选框
                                                                                                                                                    • +
                                                                                                                                                    • 下拉框
                                                                                                                                                    • +
                                                                                                                                                    • 开关
                                                                                                                                                    • +
                                                                                                                                                    +
                                                                                                                                                    +
                                                                                                                                                    + +
                                                                                                                                                    + +
                                                                                                                                                    +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + + + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_config/list/index.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_config/list/index.html new file mode 100644 index 0000000000000000000000000000000000000000..417b10984aa36fff604160267fdda4c6c0aefcf9 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_config/list/index.html @@ -0,0 +1,367 @@ + + + + + 字典列表 + + + + + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + + +
                                                                                                                                                      +
                                                                                                                                                      + 展开 + 收起 +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_databackup/details.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_databackup/details.html new file mode 100644 index 0000000000000000000000000000000000000000..333588d4f4745324273212088c645dcecef37adb --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_databackup/details.html @@ -0,0 +1,163 @@ + + + + + 语言列表 + + + + + + + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_databackup/index.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_databackup/index.html new file mode 100644 index 0000000000000000000000000000000000000000..a3af6401cb736bd61e3817277fcbb669dbff4285 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_databackup/index.html @@ -0,0 +1,421 @@ + + + + + 数据库管理 + + + + +
                                                                                                                                                      +
                                                                                                                                                        +
                                                                                                                                                      • 数据库列表
                                                                                                                                                      • +
                                                                                                                                                      • 备份列表
                                                                                                                                                      • +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_dict/add.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_dict/add.html new file mode 100644 index 0000000000000000000000000000000000000000..2df932c3c08601143bca43c300fe796de9bf4c53 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_dict/add.html @@ -0,0 +1,260 @@ + + + + + 新增字典 + + + + + + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + + +
                                                                                                                                                      + + + + + + + +
                                                                                                                                                      + + +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      + + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_dict/index.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_dict/index.html new file mode 100644 index 0000000000000000000000000000000000000000..9df30873ea98b2118c0c64cfda5f042629b8dd9c --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_dict/index.html @@ -0,0 +1,296 @@ + + + + + 字典列表 + + + + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + + + +
                                                                                                                                                      +
                                                                                                                                                      + 展开 + 收起 +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_file/index.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_file/index.html new file mode 100644 index 0000000000000000000000000000000000000000..ff91a15c29a80be51f5322d5a14c0957e785cbdf --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_file/index.html @@ -0,0 +1,11 @@ + + + + + Title + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_log/index.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_log/index.html new file mode 100644 index 0000000000000000000000000000000000000000..9e4df19cf2031105d30129c1fa63a8f08724aa5f --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_log/index.html @@ -0,0 +1,372 @@ + + + + + 系统日志 + + + + + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      + + +
                                                                                                                                                      + + + +
                                                                                                                                                      +
                                                                                                                                                      + 展开 + 收起 +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_menus/add.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_menus/add.html new file mode 100644 index 0000000000000000000000000000000000000000..7acc2ddf15fdc695aa6a154e10fc9cc9016f1bba --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_menus/add.html @@ -0,0 +1,396 @@ + + + + + 新增页面 + + + + +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + + + +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                      + +
                                                                                                                                                      + +
                                                                                                                                                      +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        +
                                                                                                                                                        + 清空 +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        + + +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        + +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        +
                                                                                                                                                        + + +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_menus/index.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_menus/index.html new file mode 100644 index 0000000000000000000000000000000000000000..7c8fe3ea7de3313fef1c0ecdbc66ccca492d8dd5 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_menus/index.html @@ -0,0 +1,368 @@ + + + + + + 权限管理 + + + + + + +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_menus/rule.html b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_menus/rule.html new file mode 100644 index 0000000000000000000000000000000000000000..0a9678023169834d90ac8513974b6bf9c156f4b2 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/system/maintain/system_menus/rule.html @@ -0,0 +1,330 @@ + + + + + 权限列表 + + + + +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        + + 1.接口可多选,可重复添加; +
                                                                                                                                                        + 2.添加路由按照路由规则进行添加,即可在开发工具->接口管理里面点击同步; +
                                                                                                                                                        + 3.同步完成即可在此选择对应的接口; +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        +
                                                                                                                                                        + + +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        + +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                        +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + + +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/carbon/index.html b/demo/webman/frontend/layui_admin_flow/view/wf/carbon/index.html new file mode 100644 index 0000000000000000000000000000000000000000..bbb006c9fa2007d7acdc7d89f24961b3e88a9efe --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/carbon/index.html @@ -0,0 +1,368 @@ + + + + + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + + +
                                                                                                                                                          + + +
                                                                                                                                                          + +
                                                                                                                                                          + 展开 + 收起 +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/category/add.html b/demo/webman/frontend/layui_admin_flow/view/wf/category/add.html new file mode 100644 index 0000000000000000000000000000000000000000..1fbba557fe106bcbb3dc6685542f6f11c5e08723 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/category/add.html @@ -0,0 +1,134 @@ + + + + + 新增流程类型 + + + + + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/category/index.html b/demo/webman/frontend/layui_admin_flow/view/wf/category/index.html new file mode 100644 index 0000000000000000000000000000000000000000..8cf9fdefa2edd853fdaabe866d7ac1c81f8ba693 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/category/index.html @@ -0,0 +1,321 @@ + + + + + 用户管理 + + + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + + +
                                                                                                                                                          + + +
                                                                                                                                                          + 展开 + 收起 +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/approvalProcess.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/approvalProcess.html new file mode 100644 index 0000000000000000000000000000000000000000..feb5a06ffa1b9c90f7ba2907b212bda3109e5e61 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/approvalProcess.html @@ -0,0 +1,294 @@ + + + + + + 审批流程 + + + + + + + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 表单
                                                                                                                                                          • +
                                                                                                                                                          • 流程图
                                                                                                                                                          • +
                                                                                                                                                          • 审批记录
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/approvalProcessHandle.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/approvalProcessHandle.html new file mode 100644 index 0000000000000000000000000000000000000000..27813a5a3f582ddda5c2633dc69aca1351ef0214 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/approvalProcessHandle.html @@ -0,0 +1,385 @@ + + + + + + 审批操作 + + + + + + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          + + + +
                                                                                                                                                          +
                                                                                                                                                          + + + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + + + + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/approvalProcessRecord.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/approvalProcessRecord.html new file mode 100644 index 0000000000000000000000000000000000000000..5bb7045e2fce08b0be7a86a5838477d44271e336 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/approvalProcessRecord.html @@ -0,0 +1,78 @@ + + + + + 审批记录 + + + + + + +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/index.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/index.html new file mode 100644 index 0000000000000000000000000000000000000000..6cec1848ebddd6d326cfc367550bf53702616b01 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/index.html @@ -0,0 +1,723 @@ + + + + + + 模型设计 + + + + + + + + + + + + +
                                                                                                                                                          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/custom.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/custom.html new file mode 100644 index 0000000000000000000000000000000000000000..31178e7d336de002aaec211b3e95b54237157562 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/custom.html @@ -0,0 +1,243 @@ + + + + + + 属性面板 + + + + + + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 节点属性
                                                                                                                                                          • +
                                                                                                                                                          • 自定义设置
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          基本属性
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          样式设置
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          拦截器
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/decision.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/decision.html new file mode 100644 index 0000000000000000000000000000000000000000..a69de278ab8f36b3093f91f0d49c62ccccb95779 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/decision.html @@ -0,0 +1,109 @@ + + + + + + 属性面板 + + + + + + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 节点属性
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          基本属性
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/detail.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/detail.html new file mode 100644 index 0000000000000000000000000000000000000000..3fb3b6960c688931a33286074781338c1c67bb2d --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/detail.html @@ -0,0 +1,104 @@ + + + + + 查看流程数据 + + + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          
                                                                                                                                                          +        
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/end.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/end.html new file mode 100644 index 0000000000000000000000000000000000000000..580f4691296394fcd53c12bee29335ed7eecb176 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/end.html @@ -0,0 +1,194 @@ + + + + + + 属性面板 + + + + + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 节点属性
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          基本属性
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          样式设置
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          拦截器
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/fork.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/fork.html new file mode 100644 index 0000000000000000000000000000000000000000..49a4dcebe3aa230e7f96f0dbac83f5d06e688f34 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/fork.html @@ -0,0 +1,116 @@ + + + + + + 属性面板 + + + + + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 节点属性
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          基本属性
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/import.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/import.html new file mode 100644 index 0000000000000000000000000000000000000000..fe5be2711f8ba9eb0cabbe0120bb20ba1e74cf69 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/import.html @@ -0,0 +1,75 @@ + + + + + 导入流程数据 + + + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/join.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/join.html new file mode 100644 index 0000000000000000000000000000000000000000..49a4dcebe3aa230e7f96f0dbac83f5d06e688f34 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/join.html @@ -0,0 +1,116 @@ + + + + + + 属性面板 + + + + + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 节点属性
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          基本属性
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/process.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/process.html new file mode 100644 index 0000000000000000000000000000000000000000..91ff9cb42723ac3745d5e64575ca7d0e9900b153 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/process.html @@ -0,0 +1,117 @@ + + + + + + 属性面板 + + + + + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 流程属性
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          基本属性
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/start.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/start.html new file mode 100644 index 0000000000000000000000000000000000000000..580f4691296394fcd53c12bee29335ed7eecb176 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/start.html @@ -0,0 +1,194 @@ + + + + + + 属性面板 + + + + + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 节点属性
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          基本属性
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          样式设置
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          拦截器
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/task.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/task.html new file mode 100644 index 0000000000000000000000000000000000000000..a95d359e4c2ab6130424c5c281ccf7f76b6858de --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/task.html @@ -0,0 +1,621 @@ + + + + + + 属性面板 + + + + + + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 节点属性
                                                                                                                                                          • +
                                                                                                                                                          • 流程设置
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          基本属性
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                                                                                                                          拦截器
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          审批设置
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          审批模式
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          扩展属性
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + 添加 + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/transition.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/transition.html new file mode 100644 index 0000000000000000000000000000000000000000..14e19a5d35fde1934d325278a5fa92d3bf7adebb --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/transition.html @@ -0,0 +1,90 @@ + + + + + + 属性面板 + + + + + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 节点属性
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          基本属性
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/wfSubProcess.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/wfSubProcess.html new file mode 100644 index 0000000000000000000000000000000000000000..e69552522ffdec5ebbeed95fc1e2217ded2b1b6a --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/design/panel/wfSubProcess.html @@ -0,0 +1,199 @@ + + + + + + 属性面板 + + + + + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 节点属性
                                                                                                                                                          • +
                                                                                                                                                          • 流程设置
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          基本属性
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          样式设置
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + \ No newline at end of file diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/launchProcess.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/launchProcess.html new file mode 100644 index 0000000000000000000000000000000000000000..69432d568178cd5a245e1b62d81da4a005a8b0c5 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/launchProcess.html @@ -0,0 +1,240 @@ + + + + + + 发起流程 + + + + + + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 表单
                                                                                                                                                          • +
                                                                                                                                                          • 流程图
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + + +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/previewProcess.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/previewProcess.html new file mode 100644 index 0000000000000000000000000000000000000000..e9575450df6767a263771062472b3a7722fd7053 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/previewProcess.html @@ -0,0 +1,177 @@ + + + + + + 查看流程定义 + + + + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                          • 流程图
                                                                                                                                                          • +
                                                                                                                                                          • 流程数据
                                                                                                                                                          • +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/common/surrogate.html b/demo/webman/frontend/layui_admin_flow/view/wf/common/surrogate.html new file mode 100644 index 0000000000000000000000000000000000000000..752da268cccc16fc4332c306b96dff7cd8377a4e --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/common/surrogate.html @@ -0,0 +1,121 @@ + + + + + + + + 委托处理 + + + + + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/definition/index.html b/demo/webman/frontend/layui_admin_flow/view/wf/definition/index.html new file mode 100644 index 0000000000000000000000000000000000000000..036d791933c954ba70a58c531eb89adac5d6f5a0 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/definition/index.html @@ -0,0 +1,340 @@ + + + + + + 流程定义 + + + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          + + + +
                                                                                                                                                          +
                                                                                                                                                          + 展开 + 收起 +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/designer/add.html b/demo/webman/frontend/layui_admin_flow/view/wf/designer/add.html new file mode 100644 index 0000000000000000000000000000000000000000..4b1f7b0e20f42d74b1877c0f7e7dcfb75efe300d --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/designer/add.html @@ -0,0 +1,232 @@ + + + + + 添加流程设计 + + + + + +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                          +
                                                                                                                                                          + +
                                                                                                                                                          +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            + + +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/designer/index.html b/demo/webman/frontend/layui_admin_flow/view/wf/designer/index.html new file mode 100644 index 0000000000000000000000000000000000000000..2519d4f6ca8b1202fa37458abf7eda8a8c4381ee --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/designer/index.html @@ -0,0 +1,485 @@ + + + + + + 用户管理 + + + + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + + + +
                                                                                                                                                            +
                                                                                                                                                            + 展开 + 收起 +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/favorite/add.html b/demo/webman/frontend/layui_admin_flow/view/wf/favorite/add.html new file mode 100644 index 0000000000000000000000000000000000000000..2ce5b8a9e85a84d1f48ee3ccfdf2f2b7c4c470ed --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/favorite/add.html @@ -0,0 +1,240 @@ + + + + + 添加收藏 + + + + + +
                                                                                                                                                            +
                                                                                                                                                            + 集团流程库 +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/favorite/index.html b/demo/webman/frontend/layui_admin_flow/view/wf/favorite/index.html new file mode 100644 index 0000000000000000000000000000000000000000..bea3f5cd05636ae1d2c7bf8804d6986312cbd6ec --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/favorite/index.html @@ -0,0 +1,284 @@ + + + + + + 我的收藏 + + + + +
                                                                                                                                                            +
                                                                                                                                                            + + + +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/instance/index.html b/demo/webman/frontend/layui_admin_flow/view/wf/instance/index.html new file mode 100644 index 0000000000000000000000000000000000000000..0bc886f37f5900fe39b182ad3db93b0ef01f9123 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/instance/index.html @@ -0,0 +1,438 @@ + + + + + + 发起的申请 + + + + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + + + +
                                                                                                                                                            +
                                                                                                                                                            + 展开 + 收起 +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/instance/startProcess.html b/demo/webman/frontend/layui_admin_flow/view/wf/instance/startProcess.html new file mode 100644 index 0000000000000000000000000000000000000000..d5cd5f8f3bd57d37860fcc63c5fcea5c6787a80e --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/instance/startProcess.html @@ -0,0 +1,401 @@ + + + + + + + + 发起申请 + + + + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + +   + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + +ss + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/monitoring/index.html b/demo/webman/frontend/layui_admin_flow/view/wf/monitoring/index.html new file mode 100644 index 0000000000000000000000000000000000000000..124d55b597d14e2e8676f03d1eb47f4cccf1e44d --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/monitoring/index.html @@ -0,0 +1,432 @@ + + + + + + 流程追踪 + + + + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + + + +
                                                                                                                                                            +
                                                                                                                                                            + 展开 + 收起 +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/task/done/index.html b/demo/webman/frontend/layui_admin_flow/view/wf/task/done/index.html new file mode 100644 index 0000000000000000000000000000000000000000..1db8208e7fea4c0742d040dc5e7d9efca0435be7 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/task/done/index.html @@ -0,0 +1,372 @@ + + + + + + 我的已办 + + + + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            + + +
                                                                                                                                                            + + + +
                                                                                                                                                            +
                                                                                                                                                            + 展开 + 收起 +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/task/todo/index.html b/demo/webman/frontend/layui_admin_flow/view/wf/task/todo/index.html new file mode 100644 index 0000000000000000000000000000000000000000..b04ec92075428f66ab80c339f722e83139670662 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/task/todo/index.html @@ -0,0 +1,430 @@ + + + + + + 我的待办 + + + + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            + + +
                                                                                                                                                            + + + +
                                                                                                                                                            +
                                                                                                                                                            + 展开 + 收起 +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/template/leaveForm.html b/demo/webman/frontend/layui_admin_flow/view/wf/template/leaveForm.html new file mode 100644 index 0000000000000000000000000000000000000000..dd51d64f4ba81cd63ab53719eedf6309e5763097 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/template/leaveForm.html @@ -0,0 +1,140 @@ + + + + + + 请假申请表单 + + + + + + +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + + + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/template/reissueForm.html b/demo/webman/frontend/layui_admin_flow/view/wf/template/reissueForm.html new file mode 100644 index 0000000000000000000000000000000000000000..5643e67cef7479f84f48874933ff7f701e8330ea --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/template/reissueForm.html @@ -0,0 +1,120 @@ + + + + + + 补卡审批单 + + + + + + +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + +
                                                                                                                                                            + +
                                                                                                                                                            +
                                                                                                                                                            +
                                                                                                                                                            + + + + + + + + + + + diff --git a/demo/webman/frontend/layui_admin_flow/view/wf/template/test.html b/demo/webman/frontend/layui_admin_flow/view/wf/template/test.html new file mode 100644 index 0000000000000000000000000000000000000000..abc211f16130ba061d555987ad14722c0d7dae31 --- /dev/null +++ b/demo/webman/frontend/layui_admin_flow/view/wf/template/test.html @@ -0,0 +1,28 @@ + + + + + 请假申请单 + + +
                                                                                                                                                            tewagfqadsgfasd测试
                                                                                                                                                            + + + + diff --git "a/demo/webman/\346\226\260\345\273\272\346\226\207\346\234\254\346\226\207\346\241\243.txt" "b/demo/webman/\346\226\260\345\273\272\346\226\207\346\234\254\346\226\207\346\241\243.txt" new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ingenious.sql b/ingenious.sql deleted file mode 100644 index a90b91113cbb6f7ce353e8a1447aa128059b7400..0000000000000000000000000000000000000000 --- a/ingenious.sql +++ /dev/null @@ -1,484 +0,0 @@ -/* - Navicat Premium Data Transfer - - Source Server : 127.0.0.1 - Source Server Type : MySQL - Source Server Version : 80012 - Source Host : localhost:3306 - Source Schema : ingenious - - Target Server Type : MySQL - Target Server Version : 80012 - File Encoding : 65001 - - Date: 22/05/2024 20:25:03 -*/ - -SET NAMES utf8mb4; -SET FOREIGN_KEY_CHECKS = 0; - --- ---------------------------- --- Table structure for wf_process_cc_instance --- ---------------------------- -DROP TABLE IF EXISTS `wf_process_cc_instance`; -CREATE TABLE `wf_process_cc_instance` ( - `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `process_instance_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程实例ID', - `actor_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '被抄送人ID', - `state` int(11) NULL DEFAULT 0 COMMENT '抄送状态(1:已读;0:未读)', - `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', - `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', - `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', - PRIMARY KEY (`id`) USING BTREE, - INDEX `idx_pccins_pinsid`(`process_instance_id`) USING BTREE, - INDEX `idx_pccins_actor_id`(`actor_id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程实例抄送' ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of wf_process_cc_instance --- ---------------------------- -INSERT INTO `wf_process_cc_instance` VALUES ('1732212671122198530', '1732212589287133186', '1686404946814533633', 0, 1706790742, '1686404946814533633', 1706790742, '1686404946814533633'); - --- ---------------------------- --- Table structure for wf_process_define --- ---------------------------- -DROP TABLE IF EXISTS `wf_process_define`; -CREATE TABLE `wf_process_define` ( - `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `type_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程分类', - `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '唯一编码', - `display_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '显示名称', - `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '流程描述', - `state` int(11) NULL DEFAULT 0 COMMENT '流程是否可用(1可用;0不可用)', - `content` json NULL COMMENT '流程模型定义', - `version` int(11) NULL DEFAULT 0 COMMENT '版本', - `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', - `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', - `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', - `is_del` int(1) NULL DEFAULT 0 COMMENT '是否删除0 否1是', - PRIMARY KEY (`id`) USING BTREE, - INDEX `idx_process_define_name`(`name`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程定义' ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of wf_process_define --- ---------------------------- -INSERT INTO `wf_process_define` VALUES ('04bdc3d7-ef71-4749-b71c-98282dfc1263', '4295de01-f687-4c1e-b7ad-20bed8d1eaf5', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}, \"4\": {\"x\": 320, \"y\": 160, \"id\": \"5e5f61e1-f4b9-41f2-a19f-226ff65e28a0\", \"text\": {\"x\": 320, \"y\": 200, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {}}, \"5\": {\"x\": 400, \"y\": 220, \"id\": \"c31bbd6f-5e7b-46df-95a8-3b9fc3868095\", \"text\": {\"x\": 400, \"y\": 220, \"value\": \"用户\"}, \"type\": \"ingenious:task\", \"properties\": {}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 5, 1715670970, '1', 1715671547, '1', 0); -INSERT INTO `wf_process_define` VALUES ('0c5adb5c-4a1b-4868-8081-10ed258b0ae4', '58167035-5c04-42c0-bb08-33cc4eb994c3', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 20, 1715754774, '1', 1715754774, '1', 0); -INSERT INTO `wf_process_define` VALUES ('2b523b6b-50b8-4078-8881-e56ee8e3a395', '4295de01-f687-4c1e-b7ad-20bed8d1eaf5', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": \"admin\", \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 2, 1715151173, '1', 1715151173, NULL, 0); -INSERT INTO `wf_process_define` VALUES ('2ec0f5c4-cb04-4a3a-9e50-6da05a24efef', '4295de01-f687-4c1e-b7ad-20bed8d1eaf5', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 9, 1715741660, '1', 1715741660, '1', 0); -INSERT INTO `wf_process_define` VALUES ('343e7518-6264-4f1e-ba22-5f5853e9412f', '4295de01-f687-4c1e-b7ad-20bed8d1eaf5', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 4, 1715419205, '1', 1715419205, NULL, 0); -INSERT INTO `wf_process_define` VALUES ('45ae3c80-e752-4376-8f63-e2cf2e5c7636', '4295de01-f687-4c1e-b7ad-20bed8d1eaf5', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}, \"4\": {\"x\": 320, \"y\": 160, \"id\": \"5e5f61e1-f4b9-41f2-a19f-226ff65e28a0\", \"text\": {\"x\": 320, \"y\": 200, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"5\": {\"x\": 400, \"y\": 220, \"id\": \"c31bbd6f-5e7b-46df-95a8-3b9fc3868095\", \"text\": {\"x\": 400, \"y\": 220, \"value\": \"用户\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"6\": {\"x\": 620, \"y\": 120, \"id\": \"95888cf5-8fff-4e09-a725-f6a73f671625\", \"text\": {\"x\": 620, \"y\": 120, \"value\": \"用户\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 7, 1715672855, '1', 1715672857, '1', 0); -INSERT INTO `wf_process_define` VALUES ('5f51fd8e-b41a-4f3d-9494-c30182b57d2e', '4295de01-f687-4c1e-b7ad-20bed8d1eaf5', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 8, 1715741658, '1', 1715741658, '1', 0); -INSERT INTO `wf_process_define` VALUES ('67419617-f15f-48e9-aaa8-fed6bf4581c3', '58167035-5c04-42c0-bb08-33cc4eb994c3', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 16, 1715754770, '1', 1715754770, '1', 0); -INSERT INTO `wf_process_define` VALUES ('720744c6-91a9-46e6-b74b-401f55497e79', '58167035-5c04-42c0-bb08-33cc4eb994c3', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 15, 1715754769, '1', 1715754769, '1', 0); -INSERT INTO `wf_process_define` VALUES ('87e9f21c-7c7e-4acd-9fa1-c150202c7836', '58167035-5c04-42c0-bb08-33cc4eb994c3', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 18, 1715754772, '1', 1715754772, '1', 0); -INSERT INTO `wf_process_define` VALUES ('94dcb0cb-bd9b-4cf5-b92e-b5dfc5b9ce9e', '58167035-5c04-42c0-bb08-33cc4eb994c3', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 17, 1715754772, '1', 1715754772, '1', 0); -INSERT INTO `wf_process_define` VALUES ('a2371fa6-f759-48f6-977a-80e0c6a5e597', '4295de01-f687-4c1e-b7ad-20bed8d1eaf5', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": \"admin\", \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 1, 1715151171, '1', 1715151171, NULL, 0); -INSERT INTO `wf_process_define` VALUES ('acfee0d8-bfdc-4fd3-994e-d67fe213286f', '', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40, \"expire_time\": \"2h\", \"reminder_time\": \"2h\", \"reminder_repeat\": \"2h\"}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"expire_time\": \"3h\", \"perform_type\": \"ANY\", \"reminder_time\": \"3h\", \"reminder_repeat\": \"3h\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"15m\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 21, 1715931354, '1', 1715931354, '1', 0); -INSERT INTO `wf_process_define` VALUES ('b5852055-175f-4a28-840a-12862a6aeafa', '58167035-5c04-42c0-bb08-33cc4eb994c3', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 14, 1715754767, '1', 1715754767, '1', 0); -INSERT INTO `wf_process_define` VALUES ('b7936202-2f65-43ca-8611-4f74aec7c91e', '58167035-5c04-42c0-bb08-33cc4eb994c3', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 19, 1715754773, '1', 1715754773, '1', 0); -INSERT INTO `wf_process_define` VALUES ('c84f5427-99a7-4234-ada1-a94189876670', '58167035-5c04-42c0-bb08-33cc4eb994c3', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 13, 1715754766, '1', 1715754766, '1', 0); -INSERT INTO `wf_process_define` VALUES ('e3306d38-f528-4dea-b4da-907ce83c4e43', '4295de01-f687-4c1e-b7ad-20bed8d1eaf5', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}, \"4\": {\"x\": 320, \"y\": 160, \"id\": \"5e5f61e1-f4b9-41f2-a19f-226ff65e28a0\", \"text\": {\"x\": 320, \"y\": 200, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {}}, \"5\": {\"x\": 400, \"y\": 220, \"id\": \"c31bbd6f-5e7b-46df-95a8-3b9fc3868095\", \"text\": {\"x\": 400, \"y\": 220, \"value\": \"用户\"}, \"type\": \"ingenious:task\", \"properties\": {}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 6, 1715672400, '1', 1715672435, '1', 0); -INSERT INTO `wf_process_define` VALUES ('e3904f69-5081-4bb9-a318-11e3032755c1', '4295de01-f687-4c1e-b7ad-20bed8d1eaf5', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 11, 1715741663, '1', 1715741663, '1', 0); -INSERT INTO `wf_process_define` VALUES ('e41ca60a-e290-4994-9c0a-938ebd7d5af9', '58167035-5c04-42c0-bb08-33cc4eb994c3', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 12, 1715754764, '1', 1715754764, '1', 0); -INSERT INTO `wf_process_define` VALUES ('feaca160-cde7-4244-81b8-418bb754bb41', '4295de01-f687-4c1e-b7ad-20bed8d1eaf5', 'leave', '测试流程', NULL, 1, '{\"name\": \"leave\", \"edges\": {\"0\": {\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 138, \"y\": 400}, \"1\": {\"x\": 300, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, \"1\": {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 420, \"y\": 400}, \"1\": {\"x\": 520, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, \"2\": {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": {\"0\": {\"x\": 640, \"y\": 400}, \"1\": {\"x\": 782, \"y\": 400}}, \"properties\": {}, \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}}, \"nodes\": {\"0\": {\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, \"1\": {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {}, \"width\": 120, \"height\": 40}}, \"2\": {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": 1}, \"width\": 120, \"height\": 40, \"assignee\": 1, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, \"3\": {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}}, \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 10, 1715741661, '1', 1715741661, '1', 0); - --- ---------------------------- --- Table structure for wf_process_define_favorite --- ---------------------------- -DROP TABLE IF EXISTS `wf_process_define_favorite`; -CREATE TABLE `wf_process_define_favorite` ( - `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT 'ID', - `user_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '用户ID', - `process_define_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '流程定义ID', - `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', - `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', - `favorite` tinyint(3) NULL DEFAULT 1 COMMENT '收藏1', - `remark` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '备注', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '流程收藏表' ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of wf_process_define_favorite --- ---------------------------- -INSERT INTO `wf_process_define_favorite` VALUES ('067e63dd-b7ad-4115-a2aa-7f95d8117f47', '1', 'e3306d38-f528-4dea-b4da-907ce83c4e43', 1715823506, 1715823506, 0, NULL); -INSERT INTO `wf_process_define_favorite` VALUES ('2bf95acb-61d7-4c7a-babe-e839650cf7ba', '1', '2b523b6b-50b8-4078-8881-e56ee8e3a395', 1715823510, 1715823510, 0, NULL); -INSERT INTO `wf_process_define_favorite` VALUES ('30c39bf8-d17a-44d9-bce3-55d5b0bf7900', '1', '45ae3c80-e752-4376-8f63-e2cf2e5c7636', 1715823505, 1715823505, 0, NULL); -INSERT INTO `wf_process_define_favorite` VALUES ('46b447e9-d297-4f11-9662-936bdfefd460', '1', '87e9f21c-7c7e-4acd-9fa1-c150202c7836', 1715824166, 1715824166, 1, NULL); -INSERT INTO `wf_process_define_favorite` VALUES ('6e91633c-d50f-43ad-b315-670b17f212fa', '1', '2ec0f5c4-cb04-4a3a-9e50-6da05a24efef', 1715823504, 1715823504, 0, NULL); -INSERT INTO `wf_process_define_favorite` VALUES ('72e1f6f7-ccca-405f-8b93-460a86465abc', '1', '343e7518-6264-4f1e-ba22-5f5853e9412f', 1715823509, 1715823509, 0, NULL); -INSERT INTO `wf_process_define_favorite` VALUES ('a93d60e5-a2cc-4d7e-b6be-89e9a5364cff', '1', '0c5adb5c-4a1b-4868-8081-10ed258b0ae4', 1715825145, 1715825145, 1, NULL); -INSERT INTO `wf_process_define_favorite` VALUES ('acf0ed4e-8131-4340-857a-61fc45c733d9', '1', '720744c6-91a9-46e6-b74b-401f55497e79', 1715823500, 1715823500, 0, NULL); -INSERT INTO `wf_process_define_favorite` VALUES ('ad1d300b-d11c-41c4-befb-0eaa869b47c7', '1', '04bdc3d7-ef71-4749-b71c-98282dfc1263', 1715823508, 1715823508, 0, NULL); -INSERT INTO `wf_process_define_favorite` VALUES ('c73b3eeb-9cbb-446d-8514-39d0f13ed046', '1', 'b7936202-2f65-43ca-8611-4f74aec7c91e', 1715825145, 1715825145, 1, NULL); -INSERT INTO `wf_process_define_favorite` VALUES ('e5630c2d-ffde-4b00-a493-7e84f5950b71', '1', 'a2371fa6-f759-48f6-977a-80e0c6a5e597', 1715823510, 1715823510, 0, NULL); -INSERT INTO `wf_process_define_favorite` VALUES ('fc8922af-8069-470d-bf04-4a7139da49cb', '1', '94dcb0cb-bd9b-4cf5-b92e-b5dfc5b9ce9e', 1715824168, 1715824168, 1, NULL); - --- ---------------------------- --- Table structure for wf_process_design --- ---------------------------- -DROP TABLE IF EXISTS `wf_process_design`; -CREATE TABLE `wf_process_design` ( - `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '唯一编码', - `display_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '显示名称', - `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '描述', - `type_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程分类', - `icon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标', - `is_deployed` tinyint(1) NULL DEFAULT 0 COMMENT '是否已部署', - `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', - `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', - `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', - `is_del` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除', - `remark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '备注', - PRIMARY KEY (`id`) USING BTREE, - INDEX `idx_process_designer_name`(`name`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程设计' ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of wf_process_design --- ---------------------------- -INSERT INTO `wf_process_design` VALUES ('373c17e7-54bf-4e2e-8205-87a8818d2bd1', 'test', '测试添加', '启动此流程,抛出信号,触发<请假继承集成>流程,并将数据带入表单。', '58167035-5c04-42c0-bb08-33cc4eb994c3', NULL, 1, 1705891323, '1', 1708217888, '1', 1, 'ads'); -INSERT INTO `wf_process_design` VALUES ('443b9e44-06d1-4660-b974-93e1f53da01d', 'leave', '员工请假', '启动此流程,抛出信号,触发<请假继承集成>流程,并将数据带入表单。', '58167035-5c04-42c0-bb08-33cc4eb994c3', '', 1, 1705327712, '1', 1715931354, '1', 0, ''); -INSERT INTO `wf_process_design` VALUES ('5d97e8e2-1bfa-4448-b415-65e9fd400d49', 'dsaf', 'asdf', '启动此流程,抛出信号,触发<请假继承集成>流程,并将数据带入表单。', '58167035-5c04-42c0-bb08-33cc4eb994c3', NULL, 0, 1706168559, '1', 1706170828, '1', 1, ''); - --- ---------------------------- --- Table structure for wf_process_design_history --- ---------------------------- -DROP TABLE IF EXISTS `wf_process_design_history`; -CREATE TABLE `wf_process_design_history` ( - `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `process_design_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程设计ID', - `content` json NULL COMMENT '流程模型定义', - `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', - `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `versions` float(3, 1) NULL DEFAULT 1.0 COMMENT '版本', - PRIMARY KEY (`id`) USING BTREE, - INDEX `idx_process_design_his_pdid`(`process_design_id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程设计历史' ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of wf_process_design_history --- ---------------------------- -INSERT INTO `wf_process_design_history` VALUES ('0d810fb8-9c3a-4710-8b6b-514f908c1d76', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": [{\"x\": 138, \"y\": 400}, {\"x\": 300, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": [{\"x\": 420, \"y\": 400}, {\"x\": 520, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": [{\"x\": 640, \"y\": 400}, {\"x\": 782, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}], \"nodes\": [{\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"width\": 120, \"height\": 40}}, {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": \"1\"}, \"width\": 120, \"height\": 40, \"assignee\": \"1\", \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 320, \"y\": 160, \"id\": \"5e5f61e1-f4b9-41f2-a19f-226ff65e28a0\", \"text\": {\"x\": 320, \"y\": 200, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": []}, {\"x\": 400, \"y\": 220, \"id\": \"c31bbd6f-5e7b-46df-95a8-3b9fc3868095\", \"text\": {\"x\": 400, \"y\": 220, \"value\": \"用户\"}, \"type\": \"ingenious:task\", \"properties\": []}], \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 1715671173, '1', 1.5); -INSERT INTO `wf_process_design_history` VALUES ('1b513556-0e1e-48df-8936-868770cb97b3', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": [{\"x\": 138, \"y\": 400}, {\"x\": 300, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": [{\"x\": 420, \"y\": 400}, {\"x\": 520, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": [{\"x\": 640, \"y\": 400}, {\"x\": 782, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}], \"nodes\": [{\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"width\": 120, \"height\": 40}}, {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": \"1\"}, \"width\": 120, \"height\": 40, \"assignee\": \"admin\", \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}], \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 1715151285, '1', 1.2); -INSERT INTO `wf_process_design_history` VALUES ('1ef779be-2468-4400-bcc0-1776ad4dc91d', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": [{\"x\": 138, \"y\": 400}, {\"x\": 300, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": [{\"x\": 420, \"y\": 400}, {\"x\": 520, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": [{\"x\": 640, \"y\": 400}, {\"x\": 782, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}], \"nodes\": [{\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"width\": 120, \"height\": 40, \"expire_time\": \"2h\", \"reminder_time\": \"2h\", \"reminder_repeat\": \"2h\"}}, {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": \"1\"}, \"width\": 120, \"height\": 40, \"assignee\": \"1\", \"task_type\": \"Major\", \"expire_time\": \"3h\", \"perform_type\": \"ANY\", \"reminder_time\": \"3h\", \"reminder_repeat\": \"3h\"}}, {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}], \"expire_time\": \"15m\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 1715931349, '1', 1.9); -INSERT INTO `wf_process_design_history` VALUES ('3ef13677-70c1-48f8-b005-205c19e99314', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": [{\"x\": 138, \"y\": 400}, {\"x\": 300, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": [{\"x\": 420, \"y\": 400}, {\"x\": 520, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": [{\"x\": 640, \"y\": 400}, {\"x\": 782, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}], \"nodes\": [{\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"width\": 120, \"height\": 40}}, {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": \"1\"}, \"width\": 120, \"height\": 40, \"assignee\": \"1\", \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}], \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 1715419203, '1', 1.4); -INSERT INTO `wf_process_design_history` VALUES ('56963b53-6408-4313-af70-74fea72ee80e', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": [{\"x\": 138, \"y\": 400}, {\"x\": 300, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": [{\"x\": 420, \"y\": 400}, {\"x\": 520, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": [{\"x\": 640, \"y\": 400}, {\"x\": 782, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}], \"nodes\": [{\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"width\": 120, \"height\": 40}}, {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": \"1\"}, \"width\": 120, \"height\": 40, \"assignee\": \"1\", \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 320, \"y\": 160, \"id\": \"5e5f61e1-f4b9-41f2-a19f-226ff65e28a0\", \"text\": {\"x\": 320, \"y\": 200, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": []}, {\"x\": 400, \"y\": 220, \"id\": \"c31bbd6f-5e7b-46df-95a8-3b9fc3868095\", \"text\": {\"x\": 400, \"y\": 220, \"value\": \"用户\"}, \"type\": \"ingenious:task\", \"properties\": []}, {\"x\": 620, \"y\": 120, \"id\": \"95888cf5-8fff-4e09-a725-f6a73f671625\", \"text\": {\"x\": 620, \"y\": 120, \"value\": \"用户\"}, \"type\": \"ingenious:task\", \"properties\": []}], \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 1715672445, '1', 1.6); -INSERT INTO `wf_process_design_history` VALUES ('7c620b0c-c08e-4030-b552-2df5136420c0', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": [{\"x\": 138, \"y\": 400}, {\"x\": 300, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": [{\"x\": 420, \"y\": 400}, {\"x\": 520, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": [{\"x\": 640, \"y\": 400}, {\"x\": 782, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}], \"nodes\": [{\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"width\": 120, \"height\": 40}}, {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": \"1\"}, \"width\": 120, \"height\": 40, \"assignee\": \"admin\", \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}], \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 1715151294, '1', 1.3); -INSERT INTO `wf_process_design_history` VALUES ('7c8f5bf9-6382-4ed5-94d4-a2f1e4d2efef', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": [{\"x\": 138, \"y\": 400}, {\"x\": 300, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": [{\"x\": 420, \"y\": 400}, {\"x\": 520, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": [{\"x\": 640, \"y\": 400}, {\"x\": 782, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}], \"nodes\": [{\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"width\": 120, \"height\": 40}}, {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": \"1\"}, \"width\": 120, \"height\": 40, \"assignee\": \"1\", \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 320, \"y\": 160, \"id\": \"5e5f61e1-f4b9-41f2-a19f-226ff65e28a0\", \"text\": {\"x\": 320, \"y\": 200, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 400, \"y\": 220, \"id\": \"c31bbd6f-5e7b-46df-95a8-3b9fc3868095\", \"text\": {\"x\": 400, \"y\": 220, \"value\": \"用户\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"width\": 120, \"height\": 40}}, {\"x\": 620, \"y\": 120, \"id\": \"95888cf5-8fff-4e09-a725-f6a73f671625\", \"text\": {\"x\": 620, \"y\": 120, \"value\": \"用户\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"width\": 120, \"height\": 40}}], \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 1715672495, '1', 1.7); -INSERT INTO `wf_process_design_history` VALUES ('910b9857-c29b-4fb6-9531-9979289025a8', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": [{\"x\": 138, \"y\": 400}, {\"x\": 300, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": [{\"x\": 420, \"y\": 400}, {\"x\": 520, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": [{\"x\": 640, \"y\": 400}, {\"x\": 782, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}], \"nodes\": [{\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"width\": 120, \"height\": 40}}, {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": \"1\"}, \"width\": 120, \"height\": 40, \"assignee\": \"1\", \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}], \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 1715741654, '1', 1.8); -INSERT INTO `wf_process_design_history` VALUES ('ac178e33-9ca5-4fef-adff-6e32956a0dbd', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": [{\"x\": 138, \"y\": 400}, {\"x\": 300, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": [{\"x\": 420, \"y\": 400}, {\"x\": 520, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": [{\"x\": 640, \"y\": 400}, {\"x\": 782, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}], \"nodes\": [{\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": {\"width\": 120, \"height\": 40}}, {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"width\": 120, \"height\": 40}}, {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"attr1\": \"1\"}, \"width\": 120, \"height\": 40, \"assignee\": \"admin\", \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": {\"width\": 120, \"height\": 40}}], \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 1715131786, '1', 1.1); -INSERT INTO `wf_process_design_history` VALUES ('cedb447c-0d3b-4225-b64f-4d4502bfb6ce', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"name\": \"leave\", \"edges\": [{\"id\": \"63807753-2fd2-43c3-9133-3989d8c796b5\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 300, \"y\": 400}, \"pointsList\": [{\"x\": 138, \"y\": 400}, {\"x\": 300, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 138, \"y\": 400}, \"sourceNodeId\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"targetNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\"}, {\"id\": \"7140c242-0d60-43aa-a779-a27b0f590315\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 520, \"y\": 400}, \"pointsList\": [{\"x\": 420, \"y\": 400}, {\"x\": 520, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 420, \"y\": 400}, \"sourceNodeId\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"targetNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\"}, {\"id\": \"10a4a9c2-acc5-43e3-9320-93ffa87b448a\", \"type\": \"ingenious:transition\", \"endPoint\": {\"x\": 782, \"y\": 400}, \"pointsList\": [{\"x\": 640, \"y\": 400}, {\"x\": 782, \"y\": 400}], \"properties\": [], \"startPoint\": {\"x\": 640, \"y\": 400}, \"sourceNodeId\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"targetNodeId\": \"108da07b-dd63-482a-a94e-9f933e16edb5\"}], \"nodes\": [{\"x\": 120, \"y\": 400, \"id\": \"49570c11-64ba-44e8-9f6e-ca8846fcad7e\", \"text\": {\"x\": 120, \"y\": 440, \"value\": \"开始\"}, \"type\": \"ingenious:start\", \"properties\": []}, {\"x\": 360, \"y\": 400, \"id\": \"9684bedc-962b-49cb-b17a-a328b9794a21\", \"text\": {\"x\": 360, \"y\": 400, \"value\": \"申请人\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": [], \"width\": 120, \"height\": 40}}, {\"x\": 580, \"y\": 400, \"id\": \"5476df71-a349-4be3-ac67-60b40706d57d\", \"text\": {\"x\": 580, \"y\": 400, \"value\": \"主管审批\"}, \"type\": \"ingenious:task\", \"properties\": {\"field\": {\"user_key\": \"admin\"}, \"width\": 120, \"height\": 40, \"task_type\": \"Major\", \"perform_type\": \"ANY\"}}, {\"x\": 800, \"y\": 400, \"id\": \"108da07b-dd63-482a-a94e-9f933e16edb5\", \"text\": {\"x\": 800, \"y\": 440, \"value\": \"结束节点\"}, \"type\": \"ingenious:end\", \"properties\": []}], \"expire_time\": \"\", \"display_name\": \"测试流程\", \"instance_url\": \"leave\", \"instance_no_class\": \"\"}', 1715096130, '1', 1.0); - --- ---------------------------- --- Table structure for wf_process_form --- ---------------------------- -DROP TABLE IF EXISTS `wf_process_form`; -CREATE TABLE `wf_process_form` ( - `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '唯一编码', - `display_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '显示名称', - `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '描述', - `type_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程分类', - `icon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标', - `is_deployed` tinyint(1) NULL DEFAULT 0 COMMENT '是否已部署', - `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', - `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', - `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', - `is_del` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除', - `remark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '备注', - PRIMARY KEY (`id`) USING BTREE, - INDEX `idx_process_form_name`(`name`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '表单设计' ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of wf_process_form --- ---------------------------- -INSERT INTO `wf_process_form` VALUES ('373c17e7-54bf-4e2e-8205-87a8818d2bd1', 'test', '测试添加', '启动此流程,抛出信号,触发<请假继承集成>流程,并将数据带入表单。', '58167035-5c04-42c0-bb08-33cc4eb994c3', NULL, 1, 1705891323, '1', 1708217888, '1', 1, 'ads'); -INSERT INTO `wf_process_form` VALUES ('443b9e44-06d1-4660-b974-93e1f53da01d', 'leave', '员工请假', '启动此流程,抛出信号,触发<请假继承集成>流程,并将数据带入表单。', '58167035-5c04-42c0-bb08-33cc4eb994c3', '', 1, 1705327712, '1', 1715306604, '1', 0, ''); -INSERT INTO `wf_process_form` VALUES ('5d97e8e2-1bfa-4448-b415-65e9fd400d49', 'dsaf', 'asdf', '启动此流程,抛出信号,触发<请假继承集成>流程,并将数据带入表单。', '58167035-5c04-42c0-bb08-33cc4eb994c3', NULL, 0, 1706168559, '1', 1706170828, '1', 1, ''); - --- ---------------------------- --- Table structure for wf_process_form_history --- ---------------------------- -DROP TABLE IF EXISTS `wf_process_form_history`; -CREATE TABLE `wf_process_form_history` ( - `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `process_form_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', - `content` json NULL COMMENT '模型定义', - `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', - `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `versions` float(3, 1) NULL DEFAULT 1.0 COMMENT '版本', - PRIMARY KEY (`id`) USING BTREE, - INDEX `idx_process_design_his_pdid`(`process_form_id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '表单设计历史' ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of wf_process_form_history --- ---------------------------- -INSERT INTO `wf_process_form_history` VALUES ('1d11669d-df1a-4961-ab46-c60d15fa8eda', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"rule\": [{\"info\": \"\", \"type\": \"input\", \"field\": \"Frla1oskvfgnyl\", \"title\": \"输入框\", \"hidden\": false, \"display\": true, \"$required\": false, \"_fc_drag_tag\": \"input\"}, {\"info\": \"\", \"type\": \"select\", \"field\": \"F04z1oskvfihjs\", \"title\": \"选择器\", \"effect\": {\"fetch\": \"\"}, \"hidden\": false, \"display\": true, \"options\": [{\"label\": \"选项1\", \"value\": 1}, {\"label\": \"选项2\", \"value\": 2}], \"$required\": false, \"_fc_drag_tag\": \"select\"}, {\"info\": \"\", \"type\": \"timePicker\", \"field\": \"Fr2g1oskvflpdb\", \"title\": \"时间选择器\", \"hidden\": false, \"display\": true, \"$required\": false, \"_fc_drag_tag\": \"timePicker\"}, {\"info\": \"\", \"type\": \"slider\", \"field\": \"F2hh1oskxh2hmd\", \"title\": \"滑块\", \"hidden\": false, \"display\": true, \"$required\": false, \"_fc_drag_tag\": \"slider\"}], \"options\": {\"form\": {\"size\": \"small\", \"labelWidth\": \"125px\", \"showMessage\": true, \"inlineMessage\": false, \"labelPosition\": \"right\", \"hideRequiredAsterisk\": false}, \"resetBtn\": {\"show\": false, \"innerText\": \"重置\"}, \"submitBtn\": {\"show\": true, \"innerText\": \"提交\"}}}', 1715063509, '1', 1.4); -INSERT INTO `wf_process_form_history` VALUES ('28fccd88-ee52-41d4-a7df-512a8fba8f3d', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"rule\": [{\"info\": \"\", \"type\": \"input\", \"field\": \"Frla1oskvfgnyl\", \"title\": \"输入框\", \"hidden\": false, \"display\": true, \"$required\": false, \"_fc_drag_tag\": \"input\"}, {\"info\": \"\", \"type\": \"select\", \"field\": \"F04z1oskvfihjs\", \"title\": \"选择器\", \"effect\": {\"fetch\": \"\"}, \"hidden\": false, \"display\": true, \"options\": [{\"label\": \"选项1\", \"value\": 1}, {\"label\": \"选项2\", \"value\": 2}], \"$required\": false, \"_fc_drag_tag\": \"select\"}, {\"info\": \"\", \"type\": \"timePicker\", \"field\": \"Fr2g1oskvflpdb\", \"title\": \"时间选择器\", \"hidden\": false, \"display\": true, \"$required\": false, \"_fc_drag_tag\": \"timePicker\"}], \"options\": {\"form\": {\"size\": \"small\", \"labelWidth\": \"125px\", \"showMessage\": true, \"inlineMessage\": false, \"labelPosition\": \"right\", \"hideRequiredAsterisk\": false}, \"resetBtn\": {\"show\": false, \"innerText\": \"重置\"}, \"submitBtn\": {\"show\": false, \"innerText\": \"提交\"}}}', 1715062635, '1', 1.2); -INSERT INTO `wf_process_form_history` VALUES ('42f3678b-902a-422f-9b30-fbc8a23290d3', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"rule\": [{\"info\": \"\", \"type\": \"input\", \"field\": \"Faw562ug3sjvl\", \"title\": \"选择器\", \"effect\": {\"fetch\": \"\"}, \"hidden\": \"\", \"display\": \"1\", \"options\": [{\"label\": \"选项1\", \"value\": 1}, {\"label\": \"选项2\", \"value\": 2}], \"$required\": \"\", \"_fc_drag_tag\": \"\"}, {\"info\": \"\", \"type\": \"switch\", \"field\": \"Fkqk62ug3sod2\", \"title\": \"开关\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"switch\"}, {\"info\": \"\", \"type\": \"switch\", \"field\": \"Fzme62uiwo4c1\", \"title\": \"开关\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"switch\"}, {\"info\": \"\", \"type\": \"slider\", \"field\": \"F5bt1osh92qeho\", \"title\": \"滑块\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"slider\"}], \"options\": {\"form\": {\"size\": \"small\", \"labelWidth\": \"125px\", \"showMessage\": \"1\", \"inlineMessage\": \"\", \"labelPosition\": \"right\", \"hideRequiredAsterisk\": \"\"}, \"resetBtn\": {\"show\": \"\", \"innerText\": \"重置\"}, \"submitBtn\": {\"show\": \"1\", \"innerText\": \"提交\"}}}', 1714983453, '1', 1.0); -INSERT INTO `wf_process_form_history` VALUES ('6ef4b13b-12ad-490d-81fe-9aa6d8070b59', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"rule\": [{\"info\": \"\", \"type\": \"input\", \"field\": \"Faw562ug3sjvl\", \"title\": \"选择器\", \"effect\": {\"fetch\": \"\"}, \"hidden\": \"\", \"display\": \"1\", \"options\": [{\"label\": \"选项1\", \"value\": 1}, {\"label\": \"选项2\", \"value\": 2}], \"$required\": \"\", \"_fc_drag_tag\": \"input\"}, {\"info\": \"\", \"type\": \"switch\", \"field\": \"Fkqk62ug3sod2\", \"title\": \"开关\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"switch\"}, {\"info\": \"\", \"type\": \"switch\", \"field\": \"Fzme62uiwo4c1\", \"title\": \"开关\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"switch\"}], \"options\": {\"form\": {\"size\": \"small\", \"labelWidth\": \"125px\", \"showMessage\": \"1\", \"inlineMessage\": \"\", \"labelPosition\": \"right\", \"hideRequiredAsterisk\": \"\"}, \"resetBtn\": {\"show\": \"\", \"innerText\": \"重置\"}, \"submitBtn\": {\"show\": \"1\", \"innerText\": \"提交\"}}}', 1714983473, '1', 1.0); -INSERT INTO `wf_process_form_history` VALUES ('70bd8cce-1dff-45f4-b4ec-2be0208fa586', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"rule\": [{\"info\": \"\", \"type\": \"input\", \"field\": \"Fc111osh9aqfid\", \"title\": \"输入框\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"input\"}, {\"info\": \"\", \"type\": \"input\", \"field\": \"Flq21osh9b09u0\", \"title\": \"输入框\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"input\"}, {\"info\": \"\", \"type\": \"timePicker\", \"field\": \"Fo0f1osh9b7rqr\", \"title\": \"时间选择器\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"timePicker\"}, {\"info\": \"\", \"type\": \"upload\", \"field\": \"F2xp1osh9bnsae\", \"props\": {\"action\": \"\"}, \"title\": \"上传\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"upload\"}, {\"info\": \"\", \"type\": \"input\", \"field\": \"Fdjv1osh9bx8vl\", \"props\": {\"type\": \"textarea\"}, \"title\": \"输入框\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"input\"}], \"options\": {\"form\": {\"size\": \"small\", \"labelWidth\": \"125px\", \"showMessage\": \"1\", \"inlineMessage\": \"\", \"labelPosition\": \"right\", \"hideRequiredAsterisk\": \"\"}, \"resetBtn\": {\"show\": \"\", \"innerText\": \"重置\"}, \"submitBtn\": {\"show\": \"1\", \"innerText\": \"提交\"}}}', 1714983621, '1', 1.0); -INSERT INTO `wf_process_form_history` VALUES ('7fa30d6b-33dc-4238-95cc-1eb61c4dc13f', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"rule\": [{\"info\": \"\", \"type\": \"input\", \"field\": \"Frla1oskvfgnyl\", \"title\": \"输入框\", \"hidden\": false, \"display\": true, \"$required\": false, \"_fc_drag_tag\": \"input\"}, {\"info\": \"\", \"type\": \"select\", \"field\": \"F04z1oskvfihjs\", \"title\": \"选择器\", \"effect\": {\"fetch\": \"\"}, \"hidden\": false, \"display\": true, \"options\": [{\"label\": \"选项1\", \"value\": 1}, {\"label\": \"选项2\", \"value\": 2}], \"$required\": false, \"_fc_drag_tag\": \"select\"}, {\"info\": \"\", \"type\": \"timePicker\", \"field\": \"Fr2g1oskvflpdb\", \"title\": \"时间选择器\", \"hidden\": false, \"display\": true, \"$required\": false, \"_fc_drag_tag\": \"timePicker\"}], \"options\": {\"form\": {\"size\": \"small\", \"labelWidth\": \"125px\", \"showMessage\": true, \"inlineMessage\": false, \"labelPosition\": \"right\", \"hideRequiredAsterisk\": false}, \"resetBtn\": {\"show\": false, \"innerText\": \"重置\"}, \"submitBtn\": {\"show\": true, \"innerText\": \"提交\"}}}', 1715063503, '1', 1.3); -INSERT INTO `wf_process_form_history` VALUES ('819dc771-7960-4942-84ec-bbe17cfc8f50', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"rule\": [{\"info\": \"\", \"type\": \"input\", \"field\": \"f_day\", \"props\": {\"rows\": 1, \"type\": \"number\", \"readonly\": false, \"clearable\": true, \"showWordLimit\": true}, \"title\": \"请假天数\", \"hidden\": false, \"display\": true, \"$required\": true, \"_fc_drag_tag\": \"input\"}, {\"info\": \"\", \"type\": \"datePicker\", \"field\": \"f_start_time\", \"props\": {\"align\": \"left\"}, \"title\": \"起始时间\", \"hidden\": false, \"display\": true, \"validate\": [{\"type\": \"number\"}], \"$required\": false, \"_fc_drag_tag\": \"datePicker\"}, {\"info\": \"\", \"type\": \"datePicker\", \"field\": \"f_end_time\", \"title\": \"截止时间\", \"hidden\": false, \"display\": true, \"$required\": false, \"_fc_drag_tag\": \"datePicker\"}, {\"info\": \"\", \"type\": \"select\", \"field\": \"f_vacetsu\", \"props\": {\"multiple\": false, \"filterable\": true}, \"title\": \"假别\", \"value\": \"\", \"effect\": {\"fetch\": \"\"}, \"hidden\": false, \"display\": true, \"options\": [{\"label\": \"事假\", \"value\": 1}, {\"label\": \"年假\", \"value\": 2}, {\"label\": \"病假\", \"value\": \"3\"}, {\"label\": \"产假\", \"value\": \"4\"}, {\"label\": \"丧假\", \"value\": \"5\"}, {\"label\": \"无薪假\", \"value\": \"6\"}], \"$required\": false, \"_fc_drag_tag\": \"select\"}, {\"info\": \"\", \"type\": \"input\", \"field\": \"f_reason\", \"props\": {\"rows\": 8, \"type\": \"textarea\", \"clearable\": true, \"showWordLimit\": false}, \"title\": \"事由\", \"hidden\": false, \"display\": true, \"$required\": true, \"_fc_drag_tag\": \"input\"}], \"options\": {\"form\": {\"size\": \"default\", \"labelWidth\": \"125px\", \"showMessage\": true, \"inlineMessage\": false, \"labelPosition\": \"right\", \"hideRequiredAsterisk\": false}, \"resetBtn\": {\"show\": false, \"innerText\": \"重置\"}, \"submitBtn\": {\"show\": false, \"innerText\": \"提交\"}}}', 1715301644, '1', 1.5); -INSERT INTO `wf_process_form_history` VALUES ('8d023aae-3939-42b9-b80a-ce8e0bd49722', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"rule\": [{\"info\": \"\", \"type\": \"input\", \"field\": \"f_day\", \"props\": {\"rows\": 1, \"type\": \"number\", \"readonly\": false, \"clearable\": true, \"showWordLimit\": true}, \"title\": \"请假天数\", \"hidden\": false, \"display\": true, \"$required\": true, \"_fc_drag_tag\": \"input\"}, {\"info\": \"\", \"type\": \"datePicker\", \"field\": \"f_start_time\", \"props\": {\"type\": \"date\", \"align\": \"left\"}, \"title\": \"起始时间\", \"hidden\": false, \"display\": true, \"validate\": [{\"type\": \"string\"}], \"$required\": false, \"_fc_drag_tag\": \"datePicker\"}, {\"info\": \"\", \"type\": \"datePicker\", \"field\": \"f_end_time\", \"title\": \"截止时间\", \"hidden\": false, \"display\": true, \"$required\": false, \"_fc_drag_tag\": \"datePicker\"}, {\"info\": \"\", \"type\": \"select\", \"field\": \"f_vacetsu\", \"props\": {\"multiple\": false, \"filterable\": true}, \"title\": \"假别\", \"value\": \"\", \"effect\": {\"fetch\": \"\"}, \"hidden\": false, \"display\": true, \"options\": [{\"label\": \"事假\", \"value\": 1}, {\"label\": \"年假\", \"value\": 2}, {\"label\": \"病假\", \"value\": \"3\"}, {\"label\": \"产假\", \"value\": \"4\"}, {\"label\": \"丧假\", \"value\": \"5\"}, {\"label\": \"无薪假\", \"value\": \"6\"}], \"$required\": false, \"_fc_drag_tag\": \"select\"}, {\"info\": \"\", \"type\": \"input\", \"field\": \"f_reason\", \"props\": {\"rows\": 8, \"type\": \"textarea\", \"clearable\": true, \"showWordLimit\": false}, \"title\": \"事由\", \"hidden\": false, \"display\": true, \"$required\": true, \"_fc_drag_tag\": \"input\"}], \"options\": {\"form\": {\"size\": \"small\", \"labelWidth\": \"125px\", \"showMessage\": true, \"inlineMessage\": false, \"labelPosition\": \"right\", \"hideRequiredAsterisk\": false}, \"resetBtn\": {\"show\": false, \"innerText\": \"重置\"}, \"submitBtn\": {\"show\": true, \"innerText\": \"提交\"}}}', 1715306604, '1', 1.6); -INSERT INTO `wf_process_form_history` VALUES ('8dc40e6a-bcd1-4579-b629-074ac4ed17ad', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"rule\": [{\"info\": \"\", \"type\": \"inputNumber\", \"field\": \"Fgij62uudrek9\", \"title\": \"计数器\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"inputNumber\"}, {\"info\": \"\", \"type\": \"switch\", \"field\": \"Fmo762uudrln2\", \"title\": \"开关\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"switch\"}, {\"info\": \"\", \"type\": \"slider\", \"field\": \"Fm1e62uudrtm3\", \"title\": \"滑块\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"slider\"}], \"options\": {\"form\": {\"size\": \"small\", \"labelWidth\": \"125px\", \"showMessage\": \"1\", \"inlineMessage\": \"\", \"labelPosition\": \"right\", \"hideRequiredAsterisk\": \"\"}, \"resetBtn\": {\"show\": \"\", \"innerText\": \"重置\"}, \"submitBtn\": {\"show\": \"1\", \"innerText\": \"提交\"}}}', 1715052843, '1', 1.1); -INSERT INTO `wf_process_form_history` VALUES ('c07cfdad-b01f-4dfe-8d98-92da0821a938', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"rule\": [{\"info\": \"\", \"type\": \"\", \"field\": \"Faw562ug3sjvl\", \"title\": \"选择器\", \"effect\": {\"fetch\": \"\"}, \"hidden\": \"\", \"display\": \"1\", \"options\": [{\"label\": \"选项1\", \"value\": 1}, {\"label\": \"选项2\", \"value\": 2}], \"$required\": \"\", \"_fc_drag_tag\": \"\"}, {\"info\": \"\", \"type\": \"switch\", \"field\": \"Fkqk62ug3sod2\", \"title\": \"开关\", \"hidden\": \"\", \"display\": \"1\", \"$required\": \"\", \"_fc_drag_tag\": \"switch\"}], \"options\": {\"form\": {\"size\": \"small\", \"labelWidth\": \"125px\", \"showMessage\": \"1\", \"inlineMessage\": \"\", \"labelPosition\": \"right\", \"hideRequiredAsterisk\": \"\"}, \"resetBtn\": {\"show\": \"\", \"innerText\": \"重置\"}, \"submitBtn\": {\"show\": \"1\", \"innerText\": \"提交\"}}}', 1714977808, '1', 1.0); -INSERT INTO `wf_process_form_history` VALUES ('f0299078-2fbb-4273-90dc-9aa5ebac227b', '443b9e44-06d1-4660-b974-93e1f53da01d', '{\"rule\": [], \"options\": {\"form\": {\"size\": \"small\", \"labelWidth\": \"125px\", \"showMessage\": \"1\", \"inlineMessage\": \"\", \"labelPosition\": \"right\", \"hideRequiredAsterisk\": \"\"}, \"resetBtn\": {\"show\": \"\", \"innerText\": \"重置\"}, \"submitBtn\": {\"show\": \"1\", \"innerText\": \"提交\"}}}', 1714983580, '1', 1.0); - --- ---------------------------- --- Table structure for wf_process_instance --- ---------------------------- -DROP TABLE IF EXISTS `wf_process_instance`; -CREATE TABLE `wf_process_instance` ( - `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `parent_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父流程ID,子流程实例才有值', - `process_define_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程定义ID', - `state` int(11) NULL DEFAULT NULL COMMENT '流程实例状态(10:进行中;20:已完成;30:已撤回;40:强行中止;50:挂起;99:已废弃)', - `parent_node_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父流程依赖的节点名称', - `business_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '业务编号', - `operator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程发起人', - `variable` json NULL COMMENT '附属变量json存储', - `expire_time` int(10) NULL DEFAULT NULL COMMENT '期望完成时间', - `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', - `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `update_time` int(3) NULL DEFAULT NULL COMMENT '更新时间', - `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', - PRIMARY KEY (`id`) USING BTREE, - INDEX `idx_process_instance_pfid`(`process_define_id`) USING BTREE, - INDEX `idx_process_instance_operator`(`operator`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程实例' ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of wf_process_instance --- ---------------------------- -INSERT INTO `wf_process_instance` VALUES ('061039bd-bb27-408d-98ba-51662b6041b5', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 10, NULL, '202405171722011044', '1', '{\"f_day\": \"1\", \"f_reason\": \"实现\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-19\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-21\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:22\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715938621, 1715937721, NULL, 1715937721, NULL); -INSERT INTO `wf_process_instance` VALUES ('0e93ee57-9073-4224-bae1-065a085f4d15', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 20, NULL, '202405171730416084', '1', '{\"f_day\": \"1\", \"f_reason\": \"现成\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-28\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-20\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:30\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715939141, 1715938241, NULL, 1715938404, NULL); -INSERT INTO `wf_process_instance` VALUES ('159d08b3-34fb-4bd1-9c6e-8d17a5e07cef', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 10, NULL, '202405171635425870', '1', '{\"f_day\": \"1\", \"f_reason\": \"1212\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-09\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-01\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:35\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715935842, 1715934942, NULL, 1715934942, NULL); -INSERT INTO `wf_process_instance` VALUES ('34e1544b-b135-4f2e-b5bf-01d6ef9bd31b', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 20, NULL, '202405171738132662', '1', '{\"f_day\": \"1\", \"f_reason\": \"徐长春\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-21\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-19\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:38\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715939593, 1715938693, NULL, 1715938738, NULL); -INSERT INTO `wf_process_instance` VALUES ('4cc75dbc-8ae9-4e16-a34e-c44e274e0812', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 10, NULL, '202405171721046236', '1', '{\"f_day\": \"1\", \"f_reason\": \"454\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-01\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:21\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715938564, 1715937664, NULL, 1715937664, NULL); -INSERT INTO `wf_process_instance` VALUES ('51574301-ea89-4dee-a6aa-d6dbb0f7ebbc', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 20, NULL, '202405172246562528', '1', '{\"f_day\": \"1\", \"f_reason\": \"222\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-21\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-20\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 22:46\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715958116, 1715957216, NULL, 1715957310, NULL); -INSERT INTO `wf_process_instance` VALUES ('5851a54e-6a30-45ad-9da7-cfcbafdce564', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 10, NULL, '202405172207223709', '1', '{\"f_day\": \"1\", \"f_reason\": \"111\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-22\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-02\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 22:07\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715955742, 1715954842, NULL, 1715954842, NULL); -INSERT INTO `wf_process_instance` VALUES ('88938ae7-9622-4c29-9304-d20d30b1e8e8', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 10, NULL, '202405171650408598', '1', '{\"f_day\": \"1\", \"f_reason\": \"是\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-10\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-01\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:50\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715936740, 1715935840, NULL, 1715935840, NULL); -INSERT INTO `wf_process_instance` VALUES ('8ebdd25f-8ae0-4645-b587-d8d4f046c4d5', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 10, NULL, '202405171722327803', '1', '{\"f_day\": \"1\", \"f_reason\": \"的\", \"f_vacetsu\": \"5\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-13\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-20\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:22\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715938652, 1715937752, NULL, 1715937752, NULL); -INSERT INTO `wf_process_instance` VALUES ('b9a90338-cb79-4737-9cf2-0322d78faac7', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 10, NULL, '202405172214598981', '1', '{\"f_day\": \"1\", \"f_reason\": \"444\", \"f_vacetsu\": \"5\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-07\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-29\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 22:14\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715956199, 1715955299, NULL, 1715955299, NULL); -INSERT INTO `wf_process_instance` VALUES ('c6806df8-994f-47e0-97a8-a4f89bfff53a', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 10, NULL, '202405172244383696', '1', '{\"f_day\": \"1\", \"f_reason\": \"2112\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-14\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-27\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 22:44\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715957978, 1715957078, NULL, 1715957078, NULL); -INSERT INTO `wf_process_instance` VALUES ('da6e964d-c5bf-4dd9-9980-de678d412049', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 10, NULL, '202405171648474396', '1', '{\"f_day\": \"1\", \"f_reason\": \"741\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-04\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-04\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:48\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715936627, 1715935727, NULL, 1715935727, NULL); -INSERT INTO `wf_process_instance` VALUES ('fcbd4096-b6b5-4666-81c3-4223a195fb4c', NULL, 'acfee0d8-bfdc-4fd3-994e-d67fe213286f', 10, NULL, '202405171654104092', '1', '{\"f_day\": \"1\", \"f_reason\": \"121\", \"f_vacetsu\": \"3\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-01\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:54\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\"}', 1715936950, 1715936050, NULL, 1715936050, NULL); - --- ---------------------------- --- Table structure for wf_process_surrogate --- ---------------------------- -DROP TABLE IF EXISTS `wf_process_surrogate`; -CREATE TABLE `wf_process_surrogate` ( - `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `process_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '流程名称', - `operator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '授权人', - `surrogate` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '代理人', - `start_time` int(11) NULL DEFAULT NULL COMMENT '授权开始时间', - `end_time` int(11) NULL DEFAULT NULL COMMENT '授权结束时间', - `enabled` tinyint(1) NULL DEFAULT 1 COMMENT '是否启用', - `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', - `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', - `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程委托代理' ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of wf_process_surrogate --- ---------------------------- -INSERT INTO `wf_process_surrogate` VALUES ('3e8b3850-e724-4b52-9460-a0b314e403d6', 'leave', '1', '136ee2de-bace-4659-b7ae-7e07c0fbbffe', 1714492800, 1716480000, 1, 1715847307, '1', 1715847307, NULL); - --- ---------------------------- --- Table structure for wf_process_task --- ---------------------------- -DROP TABLE IF EXISTS `wf_process_task`; -CREATE TABLE `wf_process_task` ( - `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `process_instance_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程实例ID', - `task_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务名称编码', - `display_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务显示名称', - `task_type` int(11) NULL DEFAULT NULL COMMENT '任务类型(0:主办任务;1:协办任务)', - `perform_type` int(11) NULL DEFAULT NULL COMMENT '参与类型(0:普通参与;1:会签参与)', - `task_state` int(11) NULL DEFAULT NULL COMMENT '任务状态(10:进行中;20:已完成;30:已撤回;40:强行中止;50:挂起;99:已废弃)', - `operator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '任务处理人', - `finish_time` int(10) NULL DEFAULT NULL COMMENT '任务完成时间', - `expire_time` int(10) NULL DEFAULT NULL COMMENT '任务期待完成时间', - `form_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '任务处理表单KEY', - `task_parent_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父任务ID', - `variable` json NULL COMMENT '附属变量json存储', - `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', - `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', - `update_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', - PRIMARY KEY (`id`) USING BTREE, - INDEX `idx_process_task_piid`(`process_instance_id`) USING BTREE, - INDEX `idx_process_task_name`(`task_name`) USING BTREE, - INDEX `idx_process_task_operator`(`operator`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程任务' ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of wf_process_task --- ---------------------------- -INSERT INTO `wf_process_task` VALUES ('0046f743-6489-44ff-9057-dcbd9d9d886f', '4cc75dbc-8ae9-4e16-a34e-c44e274e0812', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, 'cf8c5ccb-8320-436c-be49-41c15c9f7ae0', '{\"f_day\": \"1\", \"f_reason\": \"454\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:21\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715937664, NULL, 1715937664, NULL); -INSERT INTO `wf_process_task` VALUES ('04a77c21-86a5-487a-b408-5599d7a14e04', 'fcbd4096-b6b5-4666-81c3-4223a195fb4c', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715936050, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"121\", \"f_vacetsu\": \"3\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:54\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715936050, NULL, 1715936050, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('167925ac-679c-4bd9-a9c2-757ab449fab9', 'fcbd4096-b6b5-4666-81c3-4223a195fb4c', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, '04a77c21-86a5-487a-b408-5599d7a14e04', '{\"f_day\": \"1\", \"f_reason\": \"121\", \"f_vacetsu\": \"3\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:54\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715936050, NULL, 1715936050, NULL); -INSERT INTO `wf_process_task` VALUES ('1a37449f-e152-4f26-bec5-74dffccb4b85', '88938ae7-9622-4c29-9304-d20d30b1e8e8', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715935840, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"是\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-10\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:50\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715935840, NULL, 1715935840, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('1d310240-91a3-49c2-9d88-b192e479af7f', '8946bce3-9c7f-4ef9-879e-c1748f930650', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715419470, NULL, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"阿斯顿发射点\", \"f_vacetsu\": \"5\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-19\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-13\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-11 17:24\", \"process_define_id\": \"343e7518-6264-4f1e-ba22-5f5853e9412f\", \"is_first_task_node\": true}', 1715419470, NULL, 1715419470, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('1f9590f3-8f62-414f-b55a-4d1073ea7739', 'a4e6307a-a192-491a-870c-9e901a01b226', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715933034, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"454\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:03\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715933034, NULL, 1715933034, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('22760fc4-28ba-4d7a-a022-454aeb6f6a10', '68ec6940-66cb-4384-883a-a7eab4db5411', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715933952, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"4454\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-03\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-03\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:19\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715933952, NULL, 1715933952, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('263b351a-fe27-4113-9a17-0bd11b3e8f1d', '3a3ce76b-dd0d-49b8-a9f8-2c07ebd075e7', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715419345, NULL, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"士大夫擦拭地方\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-21\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-20\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-11 17:22\", \"process_define_id\": \"343e7518-6264-4f1e-ba22-5f5853e9412f\", \"is_first_task_node\": true}', 1715419345, NULL, 1715419345, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('28961dbb-1207-48d4-8ff4-a9bd389d73e4', '51574301-ea89-4dee-a6aa-d6dbb0f7ebbc', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 20, '1', 1715957310, 1715968016, NULL, '5ea71169-263a-4e6e-869d-5d5dd19ea0c0', '{\"task_name\": \"\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"submit_type\": 1, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"tf_cc_actors\": \"\", \"process_task_id\": \"28961dbb-1207-48d4-8ff4-a9bd389d73e4\", \"process_instance_id\": \"51574301-ea89-4dee-a6aa-d6dbb0f7ebbc\", \"tf_approval_comment\": \"888\"}', 1715957216, NULL, 1715957310, '1'); -INSERT INTO `wf_process_task` VALUES ('2d91b932-008d-4908-b9a0-1cb98b44a655', '5851a54e-6a30-45ad-9da7-cfcbafdce564', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, NULL, NULL, '7a7cc10b-e2a3-4f84-ae63-6ecdf7a536a4', '{\"f_day\": \"1\", \"f_reason\": \"111\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-22\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-02\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 22:07\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715954842, NULL, 1715954842, NULL); -INSERT INTO `wf_process_task` VALUES ('34ac3965-3656-47e3-9036-d6ce7da11e37', '411b607a-4ac1-49c2-b53a-98d32889c0c4', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715932399, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"888\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-23\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-09\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 15:53\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715932399, NULL, 1715932399, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('3a287b19-d55b-4326-933b-291ecfee4f42', '8ebdd25f-8ae0-4645-b587-d8d4f046c4d5', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715937752, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"的\", \"f_vacetsu\": \"5\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-13\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-20\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:22\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715937752, NULL, 1715937752, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('3b4c2990-fbae-4abd-8bbe-8b1e02d4efe3', 'b9a90338-cb79-4737-9cf2-0322d78faac7', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715955299, 1715962499, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"444\", \"f_vacetsu\": \"5\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-07\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-29\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 22:14\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715955299, NULL, 1715955299, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('3bc59278-0f79-47c5-aaf2-551cc9054627', '68ec6940-66cb-4384-883a-a7eab4db5411', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, '22760fc4-28ba-4d7a-a022-454aeb6f6a10', '{\"f_day\": \"1\", \"f_reason\": \"4454\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-03\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-03\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:19\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715933952, NULL, 1715933952, NULL); -INSERT INTO `wf_process_task` VALUES ('42fd4c59-a3b6-4318-bd50-85690d66bb6b', 'afb0d159-20c0-4ab1-9c80-a422070b36ed', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 20, '1', 1715419415, NULL, NULL, '8018ad44-12dd-492a-a11e-6934a25f5c7b', '{\"task_name\": \"\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"submit_type\": 1, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"tf_cc_actors\": \"\", \"process_task_id\": \"42fd4c59-a3b6-4318-bd50-85690d66bb6b\", \"process_instance_id\": \"afb0d159-20c0-4ab1-9c80-a422070b36ed\", \"tf_approval_comment\": \"阿斯顿发射点\"}', 1715419401, NULL, 1715419415, '1'); -INSERT INTO `wf_process_task` VALUES ('4ab1ffd4-2a65-4111-944f-8cbacda0b249', '03b52558-29b6-476b-9d19-3a0199cd746e', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715933892, 2, NULL, '0', '{\"f_day\": \"11\", \"f_reason\": \"11\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-15\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-08\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:18\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715933892, NULL, 1715933892, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('50a6e0c7-e827-4ed9-a14c-886296a56e9a', '32a3a834-3d87-40d9-b37b-6291faff41ee', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715933859, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"454\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:17\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715933859, NULL, 1715933859, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('544e603c-32a8-40ea-b0ae-da9688d40b92', 'c6806df8-994f-47e0-97a8-a4f89bfff53a', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715957078, 1715964278, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"2112\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-14\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-27\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 22:44\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715957078, NULL, 1715957078, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('591c26e8-3e03-4852-b106-9a13d90db90e', '5832a141-998a-42c0-a91f-c4dee3f717d6', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 20, '1', 1715931159, NULL, NULL, '7f8327fc-21a5-4659-994e-af0307d2a967', '{\"task_name\": \"\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"submit_type\": 1, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"tf_cc_actors\": \"\", \"process_task_id\": \"591c26e8-3e03-4852-b106-9a13d90db90e\", \"process_instance_id\": \"5832a141-998a-42c0-a91f-c4dee3f717d6\", \"tf_approval_comment\": \"都尴尬的\"}', 1715930258, NULL, 1715931159, '1'); -INSERT INTO `wf_process_task` VALUES ('5dd7ddef-4e71-48f2-a920-6b6c6a2ed0d6', '7140819d-34e7-4a5e-abca-1e73d7f59573', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715419262, NULL, NULL, '0', '{\"f_day\": \"4\", \"f_reason\": \"请假申请\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-31\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-27\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-11 17:21\", \"process_define_id\": \"343e7518-6264-4f1e-ba22-5f5853e9412f\", \"is_first_task_node\": true}', 1715419262, NULL, 1715419262, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('5ea71169-263a-4e6e-869d-5d5dd19ea0c0', '51574301-ea89-4dee-a6aa-d6dbb0f7ebbc', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715957216, 1715964416, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"222\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-21\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-20\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 22:46\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715957216, NULL, 1715957216, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('5fe6b593-6195-4573-93b7-bc75d8fd472d', 'db384afe-de17-43ba-8b6c-d4fb9c1e4c22', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, '7d3e5f31-4b2b-4d23-8ab0-05b99be9bd89', '{\"f_day\": \"1\", \"f_reason\": \"154\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:35\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715934919, NULL, 1715934919, NULL); -INSERT INTO `wf_process_task` VALUES ('60f12269-1b7c-43d2-bceb-9d2078f65710', '898c488e-2f5c-4c1b-90d9-6e13db263f3d', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 20, '1', 1715931128, NULL, NULL, 'b67871ed-3974-4462-afa6-779305712493', '{\"task_name\": \"\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"submit_type\": 1, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"tf_cc_actors\": \"\", \"process_task_id\": \"60f12269-1b7c-43d2-bceb-9d2078f65710\", \"process_instance_id\": \"898c488e-2f5c-4c1b-90d9-6e13db263f3d\", \"tf_approval_comment\": \"46857846\"}', 1715931095, NULL, 1715931128, '1'); -INSERT INTO `wf_process_task` VALUES ('662c670e-7234-40ea-ba0c-7b95f5b1d7fb', 'da6e964d-c5bf-4dd9-9980-de678d412049', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, 'd0c532a5-051c-4b2f-9fb4-80f567cda354', '{\"f_day\": \"1\", \"f_reason\": \"741\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-04\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-04\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:48\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715935727, NULL, 1715935727, NULL); -INSERT INTO `wf_process_task` VALUES ('6d98cc01-8eff-4aa2-8f53-9157990c39bf', 'ecf12a6d-52e3-4d1b-86b5-032213732eb8', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715931541, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"454\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-06-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-17\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 15:39\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715931541, NULL, 1715931541, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('6f39e544-67f4-45c7-bf63-8d94780823e1', '183d6886-2c76-40ce-9ba8-df10302b4bf7', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, NULL, NULL, '90588065-24e5-4689-af08-2754e329d887', '{\"f_day\": \"111\", \"f_reason\": \"的\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-08\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 15:34\", \"reminder_repeat\": \"\", \"process_define_id\": \"0c5adb5c-4a1b-4868-8081-10ed258b0ae4\", \"is_first_task_node\": false}', 1715931269, NULL, 1715931269, NULL); -INSERT INTO `wf_process_task` VALUES ('7186634d-6fe5-488d-9fdc-a64de0f6f85d', '061039bd-bb27-408d-98ba-51662b6041b5', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, 'e739973e-af96-41fd-8b99-55ce07eb6e94', '{\"f_day\": \"1\", \"f_reason\": \"实现\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-19\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-21\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:22\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715937721, NULL, 1715937721, NULL); -INSERT INTO `wf_process_task` VALUES ('722b771b-3271-4cbd-bf6c-90ce1194e0cd', 'b9a90338-cb79-4737-9cf2-0322d78faac7', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 1715966099, NULL, '3b4c2990-fbae-4abd-8bbe-8b1e02d4efe3', '{\"f_day\": \"1\", \"f_reason\": \"444\", \"f_vacetsu\": \"5\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-07\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-29\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 22:14\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715955299, NULL, 1715955299, NULL); -INSERT INTO `wf_process_task` VALUES ('72b0cb15-fdb9-475f-b37e-1c56d79304db', '3a3ce76b-dd0d-49b8-a9f8-2c07ebd075e7', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 20, '1', 1715419363, NULL, NULL, '263b351a-fe27-4113-9a17-0bd11b3e8f1d', '{\"task_name\": \"\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"submit_type\": 1, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"tf_cc_actors\": \"\", \"process_task_id\": \"72b0cb15-fdb9-475f-b37e-1c56d79304db\", \"process_instance_id\": \"3a3ce76b-dd0d-49b8-a9f8-2c07ebd075e7\", \"tf_approval_comment\": \"啊手动阀手动阀\"}', 1715419345, NULL, 1715419363, '1'); -INSERT INTO `wf_process_task` VALUES ('74eb7ea9-172e-4a3a-8f33-ea7c2fdda1cb', 'c6806df8-994f-47e0-97a8-a4f89bfff53a', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 1715967878, NULL, '544e603c-32a8-40ea-b0ae-da9688d40b92', '{\"f_day\": \"1\", \"f_reason\": \"2112\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-14\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-27\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 22:44\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715957078, NULL, 1715957078, NULL); -INSERT INTO `wf_process_task` VALUES ('796df702-dc21-4a22-a096-49f769d21666', 'a4ef67a9-3161-4956-8221-e17f28b0505a', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, 'd430af6e-1428-431d-9482-e7dd5c7d4dda', '{\"f_day\": \"1\", \"f_reason\": \"二十多\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:04\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715933075, NULL, 1715933075, NULL); -INSERT INTO `wf_process_task` VALUES ('7a7cc10b-e2a3-4f84-ae63-6ecdf7a536a4', '5851a54e-6a30-45ad-9da7-cfcbafdce564', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715954842, NULL, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"111\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-22\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-02\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 22:07\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715954842, NULL, 1715954842, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('7d3e5f31-4b2b-4d23-8ab0-05b99be9bd89', 'db384afe-de17-43ba-8b6c-d4fb9c1e4c22', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715934919, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"154\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:35\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715934919, NULL, 1715934919, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('7f8327fc-21a5-4659-994e-af0307d2a967', '5832a141-998a-42c0-a91f-c4dee3f717d6', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715930258, NULL, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"阿斯顿发\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-15\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-20\", \"reminder_time\": \"\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 15:17\", \"reminder_repeat\": \"\", \"process_define_id\": \"0c5adb5c-4a1b-4868-8081-10ed258b0ae4\", \"is_first_task_node\": true}', 1715930258, NULL, 1715930258, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('8018ad44-12dd-492a-a11e-6934a25f5c7b', 'afb0d159-20c0-4ab1-9c80-a422070b36ed', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715419401, NULL, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"啊啊手动阀\", \"f_vacetsu\": \"5\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-13\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-21\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-11 17:23\", \"process_define_id\": \"343e7518-6264-4f1e-ba22-5f5853e9412f\", \"is_first_task_node\": true}', 1715419401, NULL, 1715419401, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('841d9905-0f8c-4b34-ad83-c87f13249bbc', '159d08b3-34fb-4bd1-9c6e-8d17a5e07cef', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715934942, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"1212\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-09\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:35\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715934942, NULL, 1715934942, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('8f647498-eefe-422f-a68c-8c16d2ff10b1', '03b52558-29b6-476b-9d19-3a0199cd746e', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, '4ab1ffd4-2a65-4111-944f-8cbacda0b249', '{\"f_day\": \"11\", \"f_reason\": \"11\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-15\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-08\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:18\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715933892, NULL, 1715933892, NULL); -INSERT INTO `wf_process_task` VALUES ('90588065-24e5-4689-af08-2754e329d887', '183d6886-2c76-40ce-9ba8-df10302b4bf7', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715931269, NULL, NULL, '0', '{\"f_day\": \"111\", \"f_reason\": \"的\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-08\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 15:34\", \"reminder_repeat\": \"\", \"process_define_id\": \"0c5adb5c-4a1b-4868-8081-10ed258b0ae4\", \"is_first_task_node\": true}', 1715931269, NULL, 1715931269, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('99fa7c27-3528-44ed-8c02-e3d1d75e155c', '8ebdd25f-8ae0-4645-b587-d8d4f046c4d5', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, '3a287b19-d55b-4326-933b-291ecfee4f42', '{\"f_day\": \"1\", \"f_reason\": \"的\", \"f_vacetsu\": \"5\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-13\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-20\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:22\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715937752, NULL, 1715937752, NULL); -INSERT INTO `wf_process_task` VALUES ('9ca3d6d3-4d46-40fb-8e19-6fff8d775dc3', 'e5cc596a-0c42-466f-953e-103b7b6ea56b', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715678933, NULL, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"asdf\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-03\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-02\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-14 17:28\", \"process_define_id\": \"2b523b6b-50b8-4078-8881-e56ee8e3a395\", \"is_first_task_node\": true}', 1715678933, NULL, 1715678933, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('a0ac962b-b6e8-45b5-8e8c-94c7c7d91bb3', '059e4485-89a0-416a-bd69-c670923efae5', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 20, '1', 1715418960, NULL, NULL, 'ed6656e9-8027-4c81-b02d-678c900e1cd0', '{\"task_name\": \"\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"submit_type\": 1, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"tf_cc_actors\": \"\", \"process_task_id\": \"a0ac962b-b6e8-45b5-8e8c-94c7c7d91bb3\", \"process_instance_id\": \"059e4485-89a0-416a-bd69-c670923efae5\", \"tf_approval_comment\": \"阿斯顿发射点\"}', 1715311379, NULL, 1715418960, '1'); -INSERT INTO `wf_process_task` VALUES ('a57e6515-8b43-44c4-86c3-ff512fc7d9be', 'bef4bb3c-1192-4059-bdb9-51eba7823d62', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, 'abce0f38-8d21-43a8-9d30-49a6bd0b3ddb', '{\"f_day\": \"1\", \"f_reason\": \"是\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:26\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715934398, NULL, 1715934398, NULL); -INSERT INTO `wf_process_task` VALUES ('a7396032-def9-47ca-8951-88fcf01c1549', '32a3a834-3d87-40d9-b37b-6291faff41ee', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, '50a6e0c7-e827-4ed9-a14c-886296a56e9a', '{\"f_day\": \"1\", \"f_reason\": \"454\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:17\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715933859, NULL, 1715933859, NULL); -INSERT INTO `wf_process_task` VALUES ('abce0f38-8d21-43a8-9d30-49a6bd0b3ddb', 'bef4bb3c-1192-4059-bdb9-51eba7823d62', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715934398, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"是\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:26\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715934398, NULL, 1715934398, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('b1a7d911-a2dc-4649-97c9-f665efd80447', '9c7b9974-0843-41ca-8e84-ced65a3e6c04', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, 'b93a8364-c174-4b18-b505-e4021777bef1', '{\"f_day\": \"11\", \"f_reason\": \"有时间\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-02\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 15:36\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715931379, NULL, 1715931379, NULL); -INSERT INTO `wf_process_task` VALUES ('b2024a15-590f-4068-882c-73bc35fa16cd', '8946bce3-9c7f-4ef9-879e-c1748f930650', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 20, '1', 1715419483, NULL, NULL, '1d310240-91a3-49c2-9d88-b192e479af7f', '{\"task_name\": \"\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"submit_type\": 1, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"tf_cc_actors\": \"\", \"process_task_id\": \"b2024a15-590f-4068-882c-73bc35fa16cd\", \"process_instance_id\": \"8946bce3-9c7f-4ef9-879e-c1748f930650\", \"tf_approval_comment\": \"阿瑟东发\"}', 1715419470, NULL, 1715419483, '1'); -INSERT INTO `wf_process_task` VALUES ('b67871ed-3974-4462-afa6-779305712493', '898c488e-2f5c-4c1b-90d9-6e13db263f3d', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715931095, NULL, NULL, '0', '{\"f_day\": \"11\", \"f_reason\": \"耳放\", \"f_vacetsu\": \"5\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-22\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-20\", \"reminder_time\": \"\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 15:31\", \"reminder_repeat\": \"\", \"process_define_id\": \"0c5adb5c-4a1b-4868-8081-10ed258b0ae4\", \"is_first_task_node\": true}', 1715931095, NULL, 1715931095, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('b93a8364-c174-4b18-b505-e4021777bef1', '9c7b9974-0843-41ca-8e84-ced65a3e6c04', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715931379, 2, NULL, '0', '{\"f_day\": \"11\", \"f_reason\": \"有时间\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-02\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 15:36\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715931379, NULL, 1715931379, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('bad327a8-f268-495f-b089-80107c28cef4', '0e93ee57-9073-4224-bae1-065a085f4d15', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715938241, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"现成\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-28\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-20\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:30\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715938241, NULL, 1715938241, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('c90fa5a5-01fc-443c-822b-2deca41391f9', 'e5cc596a-0c42-466f-953e-103b7b6ea56b', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, NULL, NULL, '9ca3d6d3-4d46-40fb-8e19-6fff8d775dc3', '{\"f_day\": \"1\", \"f_reason\": \"asdf\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-03\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-05-02\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-14 17:28\", \"process_define_id\": \"2b523b6b-50b8-4078-8881-e56ee8e3a395\", \"is_first_task_node\": false}', 1715678933, NULL, 1715678933, NULL); -INSERT INTO `wf_process_task` VALUES ('cf8c5ccb-8320-436c-be49-41c15c9f7ae0', '4cc75dbc-8ae9-4e16-a34e-c44e274e0812', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715937664, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"454\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:21\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715937664, NULL, 1715937664, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('d01520ca-7dd1-4372-ab7c-c17429c95b02', 'a4e6307a-a192-491a-870c-9e901a01b226', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, '1f9590f3-8f62-414f-b55a-4d1073ea7739', '{\"f_day\": \"1\", \"f_reason\": \"454\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:03\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715933034, NULL, 1715933034, NULL); -INSERT INTO `wf_process_task` VALUES ('d0c532a5-051c-4b2f-9fb4-80f567cda354', 'da6e964d-c5bf-4dd9-9980-de678d412049', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715935727, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"741\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-04\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-04\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:48\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715935727, NULL, 1715935727, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('d2a6fe79-471a-46b3-a9ce-955bf3afd7a6', '0e93ee57-9073-4224-bae1-065a085f4d15', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 20, '1', 1715938404, 3, NULL, 'bad327a8-f268-495f-b089-80107c28cef4', '{\"task_name\": \"\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"submit_type\": 1, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"tf_cc_actors\": \"\", \"process_task_id\": \"d2a6fe79-471a-46b3-a9ce-955bf3afd7a6\", \"process_instance_id\": \"0e93ee57-9073-4224-bae1-065a085f4d15\", \"tf_approval_comment\": \"测试移除提醒\"}', 1715938241, NULL, 1715938404, '1'); -INSERT INTO `wf_process_task` VALUES ('d3af9027-9324-46d7-ba3b-9a551ef4bd06', 'd4e9330c-864c-407c-b26f-bdde6c229e6b', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715925278, NULL, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"测试添加变量\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-14\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 13:54\", \"reminder_repeat\": \"\", \"process_define_id\": \"0c5adb5c-4a1b-4868-8081-10ed258b0ae4\", \"is_first_task_node\": true}', 1715925278, NULL, 1715925278, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('d430af6e-1428-431d-9482-e7dd5c7d4dda', 'a4ef67a9-3161-4956-8221-e17f28b0505a', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715933075, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"二十多\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:04\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715933075, NULL, 1715933075, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('d7d98a37-f383-4f09-9dc4-8033b1d78915', '411b607a-4ac1-49c2-b53a-98d32889c0c4', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, '34ac3965-3656-47e3-9036-d6ce7da11e37', '{\"f_day\": \"1\", \"f_reason\": \"888\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-23\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-09\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 15:53\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715932399, NULL, 1715932399, NULL); -INSERT INTO `wf_process_task` VALUES ('dfa6a0af-3d2c-4479-a501-55b9127245a0', '41d19680-2a28-4afa-ad1b-b544e4c63b16', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715932977, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"12452\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-10\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:02\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715932977, NULL, 1715932977, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('e0cbeb82-1761-44f3-b7f6-0f5f5931f559', '34e1544b-b135-4f2e-b5bf-01d6ef9bd31b', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 20, '1', 1715938738, 3, NULL, 'e72ebac4-9fab-4c22-92f4-70eda0040965', '{\"task_name\": \"\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"submit_type\": 1, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"tf_cc_actors\": \"\", \"process_task_id\": \"e0cbeb82-1761-44f3-b7f6-0f5f5931f559\", \"process_instance_id\": \"34e1544b-b135-4f2e-b5bf-01d6ef9bd31b\", \"tf_approval_comment\": \"214\"}', 1715938693, NULL, 1715938738, '1'); -INSERT INTO `wf_process_task` VALUES ('e72ebac4-9fab-4c22-92f4-70eda0040965', '34e1544b-b135-4f2e-b5bf-01d6ef9bd31b', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715938693, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"徐长春\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-21\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-19\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:38\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715938693, NULL, 1715938693, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('e739973e-af96-41fd-8b99-55ce07eb6e94', '061039bd-bb27-408d-98ba-51662b6041b5', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715937721, 2, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"实现\", \"f_vacetsu\": \"6\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-19\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-21\", \"reminder_time\": \"2h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 17:22\", \"reminder_repeat\": \"2h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": true}', 1715937721, NULL, 1715937721, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('ed6656e9-8027-4c81-b02d-678c900e1cd0', '059e4485-89a0-416a-bd69-c670923efae5', '9684bedc-962b-49cb-b17a-a328b9794a21', '申请人', NULL, 0, 20, 'flow_auto', 1715311379, NULL, NULL, '0', '{\"f_day\": \"1\", \"f_reason\": \"测试发起流程\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-23\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"f_start_time\": \"2024-06-01\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-10 11:22\", \"process_define_id\": \"c6c35611-181e-4a2e-804e-77adac06ac0d\", \"is_first_task_node\": true}', 1715311379, NULL, 1715311379, 'flow_auto'); -INSERT INTO `wf_process_task` VALUES ('ef178322-b168-43a2-88f6-0c1ab7c42bf4', '41d19680-2a28-4afa-ad1b-b544e4c63b16', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, 'dfa6a0af-3d2c-4479-a501-55b9127245a0', '{\"f_day\": \"1\", \"f_reason\": \"12452\", \"f_vacetsu\": 2, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-10\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:02\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715932977, NULL, 1715932977, NULL); -INSERT INTO `wf_process_task` VALUES ('f041ed1b-00d3-4906-804d-39292ddcffd7', 'd4e9330c-864c-407c-b26f-bdde6c229e6b', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 20, '1', 1715931181, NULL, NULL, 'd3af9027-9324-46d7-ba3b-9a551ef4bd06', '{\"task_name\": \"\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"submit_type\": 1, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"tf_cc_actors\": \"\", \"process_task_id\": \"f041ed1b-00d3-4906-804d-39292ddcffd7\", \"process_instance_id\": \"d4e9330c-864c-407c-b26f-bdde6c229e6b\", \"tf_approval_comment\": \"阿斯顿发\"}', 1715925278, NULL, 1715931181, '1'); -INSERT INTO `wf_process_task` VALUES ('f356de76-0914-4d8f-baf9-bb260ca5b8f5', 'ecf12a6d-52e3-4d1b-86b5-032213732eb8', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, '6d98cc01-8eff-4aa2-8f53-9157990c39bf', '{\"f_day\": \"1\", \"f_reason\": \"454\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-06-01\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-17\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 15:39\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715931541, NULL, 1715931541, NULL); -INSERT INTO `wf_process_task` VALUES ('f598f86d-9cf5-45ca-944d-2dca79cf6d2d', '7140819d-34e7-4a5e-abca-1e73d7f59573', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 20, '1', 1715419281, NULL, NULL, '5dd7ddef-4e71-48f2-a920-6b6c6a2ed0d6', '{\"task_name\": \"\", \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"submit_type\": 1, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"tf_cc_actors\": \"\", \"process_task_id\": \"f598f86d-9cf5-45ca-944d-2dca79cf6d2d\", \"process_instance_id\": \"7140819d-34e7-4a5e-abca-1e73d7f59573\", \"tf_approval_comment\": \"测试审核\"}', 1715419262, NULL, 1715419281, '1'); -INSERT INTO `wf_process_task` VALUES ('f605e03d-6ff9-426e-bb73-c328ff72ce33', '88938ae7-9622-4c29-9304-d20d30b1e8e8', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, '1a37449f-e152-4f26-bec5-74dffccb4b85', '{\"f_day\": \"1\", \"f_reason\": \"是\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-10\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:50\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715935840, NULL, 1715935840, NULL); -INSERT INTO `wf_process_task` VALUES ('fcb26717-664a-473a-8699-db4f55fa9a40', '159d08b3-34fb-4bd1-9c6e-8d17a5e07cef', '5476df71-a349-4be3-ac67-60b40706d57d', '主管审批', NULL, 0, 10, NULL, NULL, 3, NULL, '841d9905-0f8c-4b34-ad83-c87f13249bbc', '{\"f_day\": \"1\", \"f_reason\": \"1212\", \"f_vacetsu\": 1, \"u_dept_id\": \"\", \"u_post_id\": \"\", \"u_user_id\": \"1\", \"f_end_time\": \"2024-05-09\", \"submit_type\": 0, \"u_dept_name\": \"\", \"u_post_name\": \"\", \"u_real_name\": \"超级管理员\", \"u_user_name\": \"admin\", \"auto_execute\": \"\", \"f_start_time\": \"2024-05-01\", \"reminder_time\": \"3h\", \"auto_gen_title\": \"超级管理员的测试流程-2024-05-17 16:35\", \"reminder_repeat\": \"3h\", \"process_define_id\": \"acfee0d8-bfdc-4fd3-994e-d67fe213286f\", \"is_first_task_node\": false}', 1715934942, NULL, 1715934942, NULL); - --- ---------------------------- --- Table structure for wf_process_task_actor --- ---------------------------- -DROP TABLE IF EXISTS `wf_process_task_actor`; -CREATE TABLE `wf_process_task_actor` ( - `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `process_task_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程任务ID', - `actor_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '参与者ID', - `create_time` int(10) NULL DEFAULT NULL COMMENT '创建时间', - `create_user` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - PRIMARY KEY (`id`) USING BTREE, - INDEX `idx_process_task_actor_ptid`(`process_task_id`) USING BTREE, - INDEX `idx_process_task_actor_aid`(`actor_id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '流程任务和参与人关系' ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of wf_process_task_actor --- ---------------------------- -INSERT INTO `wf_process_task_actor` VALUES ('031d5a23-c5de-4e62-b1b9-e757bfa67e5d', '28961dbb-1207-48d4-8ff4-a9bd389d73e4', '1', 1715957216, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('0cb5dc5b-79e2-4337-8348-38314efd37fb', 'c90fa5a5-01fc-443c-822b-2deca41391f9', 'admin', 1715678933, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('14fd7b7f-c313-48fd-90de-312038b7b938', 'ef178322-b168-43a2-88f6-0c1ab7c42bf4', '1', 1715932977, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('1aaf97f2-3665-4cbf-89d8-5cfd9f7a2513', '6f39e544-67f4-45c7-bf63-8d94780823e1', '1', 1715931269, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('222b6fae-81b5-4b20-9024-75e317d27c24', '42fd4c59-a3b6-4318-bd50-85690d66bb6b', '1', 1715419401, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('2b496883-b025-48b7-9337-b3403b54d782', 'd01520ca-7dd1-4372-ab7c-c17429c95b02', '1', 1715933034, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('2dcd3109-f34e-4003-9055-4f3d5513e704', 'f598f86d-9cf5-45ca-944d-2dca79cf6d2d', '1', 1715419262, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('34a4a14a-f44e-4a08-a403-2c59903fb759', 'a7396032-def9-47ca-8951-88fcf01c1549', '1', 1715933859, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('46d034be-e3ea-49c5-8402-75e159f69f79', 'a57e6515-8b43-44c4-86c3-ff512fc7d9be', '1', 1715934398, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('4a5dcec3-3b24-4901-bb09-48c1bf16b3e1', '2d91b932-008d-4908-b9a0-1cb98b44a655', '1', 1715954842, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('5059bbce-7cc3-40b9-8196-86debc490787', 'd7d98a37-f383-4f09-9dc4-8033b1d78915', '1', 1715932399, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('5307dc6c-4882-447c-80c8-bf8f68cc3aef', 'b2024a15-590f-4068-882c-73bc35fa16cd', '1', 1715419470, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('5528dace-40c7-4d2f-8a77-470ef01fb72b', '99fa7c27-3528-44ed-8c02-e3d1d75e155c', '1', 1715937752, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('5f21bad1-ec30-4282-8b9d-ec7da51ac7d4', 'f356de76-0914-4d8f-baf9-bb260ca5b8f5', '1', 1715931541, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('78206b20-4fa4-4435-b0d0-cb5b22e8efdf', '591c26e8-3e03-4852-b106-9a13d90db90e', '1', 1715930258, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('7aa4d486-014f-4d0b-b041-283bdaeaf954', '796df702-dc21-4a22-a096-49f769d21666', '1', 1715933075, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('80cc9cb2-dabc-45b5-b304-a2afab9dab56', 'f041ed1b-00d3-4906-804d-39292ddcffd7', '1', 1715925278, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('90afa8f7-d7de-4563-bc09-83ec561ed17c', '722b771b-3271-4cbd-bf6c-90ce1194e0cd', '1', 1715955299, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('92108e85-af4a-44ce-8bc6-27c5db3c04aa', '3bc59278-0f79-47c5-aaf2-551cc9054627', '1', 1715933952, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('98186f33-ae8b-4f00-838a-0a9ce0186e24', '74eb7ea9-172e-4a3a-8f33-ea7c2fdda1cb', '1', 1715957078, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('a90a4460-8baf-4355-a0e0-8ff95ee22341', '662c670e-7234-40ea-ba0c-7b95f5b1d7fb', '1', 1715935727, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('adeea099-70db-404e-85d2-b3054e4e910a', 'f605e03d-6ff9-426e-bb73-c328ff72ce33', '1', 1715935840, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('b64a4d59-20fb-47dd-a9ed-edeb27a71494', 'e0cbeb82-1761-44f3-b7f6-0f5f5931f559', '1', 1715938693, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('bb1f85c3-74fc-44a1-a490-11dd23006888', 'b1a7d911-a2dc-4649-97c9-f665efd80447', '1', 1715931379, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('be137312-ab0f-42b2-a79c-4b6d44b959ea', '72b0cb15-fdb9-475f-b37e-1c56d79304db', '1', 1715419345, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('c56c3599-4835-44a1-a299-f5c5bf113496', '8f647498-eefe-422f-a68c-8c16d2ff10b1', '1', 1715933892, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('c674dc33-81a9-4a58-8c0f-83eb43964f61', 'a0ac962b-b6e8-45b5-8e8c-94c7c7d91bb3', '1', 1715311379, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('d0a206db-19b9-4a63-93e7-a2685c010e31', 'd2a6fe79-471a-46b3-a9ce-955bf3afd7a6', '1', 1715938241, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('daefc057-bc35-4e07-a758-8a450b9a1723', '5fe6b593-6195-4573-93b7-bc75d8fd472d', '1', 1715934919, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('ea838f81-9996-465b-b462-6081be691a92', '60f12269-1b7c-43d2-bceb-9d2078f65710', '1', 1715931095, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('eb44c5c1-726d-418b-bbc6-49ebdf4a27cf', '0046f743-6489-44ff-9057-dcbd9d9d886f', '1', 1715937664, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('f9ad01a0-6c61-4359-a650-6ea46f91dba4', 'fcb26717-664a-473a-8699-db4f55fa9a40', '1', 1715934942, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('fa49a1af-4d7d-4607-8537-d5994a522110', '7186634d-6fe5-488d-9fdc-a64de0f6f85d', '1', 1715937721, NULL); -INSERT INTO `wf_process_task_actor` VALUES ('fd68e9ee-56e9-4a01-846a-06878f3cdf4a', '167925ac-679c-4bd9-a9c2-757ab449fab9', '1', 1715936050, NULL); - --- ---------------------------- --- Table structure for wf_process_type --- ---------------------------- -DROP TABLE IF EXISTS `wf_process_type`; -CREATE TABLE `wf_process_type` ( - `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `pid` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0' COMMENT '父id', - `icon` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'icon', - `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '分组名称', - `sort` int(11) NULL DEFAULT 0 COMMENT '排序', - `status` tinyint(3) NULL DEFAULT 1 COMMENT '1启用 2禁用', - `create_time` int(10) NOT NULL COMMENT '创建时间', - `update_time` int(10) NULL DEFAULT NULL COMMENT '更新时间', - `update_user` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', - `create_user` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `is_del` tinyint(3) NOT NULL DEFAULT 0 COMMENT '1删除 默认0', - `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '模型分组' ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of wf_process_type --- ---------------------------- -INSERT INTO `wf_process_type` VALUES ('0a67e17d-7878-47f2-93d2-a960367178cc', '0', 'ele-Folder', '行政', 0, 1, 1706087406, 1706171994, '1', '1', 0, ''); -INSERT INTO `wf_process_type` VALUES ('3606568e-2a81-4cd1-b5f5-0aba6c414746', 'c1bf068a-aec7-4801-9160-d61af713330c', 'ele-Folder', '业务流程', 0, 1, 1706172538, 1706172538, NULL, '1', 0, ''); -INSERT INTO `wf_process_type` VALUES ('4295de01-f687-4c1e-b7ad-20bed8d1eaf5', '0', 'ele-House', 'OA', 10, 1, 1706087453, 1706172391, '1', '1', 0, ''); -INSERT INTO `wf_process_type` VALUES ('58167035-5c04-42c0-bb08-33cc4eb994c3', '0', 'ele-UserFilled', '人事', 0, 1, 1706087412, 1706171963, '1', '1', 0, ''); -INSERT INTO `wf_process_type` VALUES ('c1bf068a-aec7-4801-9160-d61af713330c', '0', 'ele-HomeFilled', '集团流程库', -1, 1, 1706172341, 1706172450, '1', '1', 0, ''); -INSERT INTO `wf_process_type` VALUES ('d7dc0900-1609-44e9-a60c-586d086fb130', '0a67e17d-7878-47f2-93d2-a960367178cc', NULL, '总务', 0, 1, 1706088738, 1706088738, NULL, '1', 0, ''); - -SET FOREIGN_KEY_CHECKS = 1; diff --git a/src/core/Execution.php b/src/core/Execution.php deleted file mode 100644 index 1def92bc38d8973b43dd8e407106084b66082355..0000000000000000000000000000000000000000 --- a/src/core/Execution.php +++ /dev/null @@ -1,154 +0,0 @@ -processTaskList[] = $processTask; - } - - /** - * 添加任务集合 - * - * @param array $processTasks - */ - public function addTasks(array $processTasks): void - { - $this->processTaskList = array_merge($this->processTaskList, $processTasks); - } - - /** - * 获取正在进行中的任务列表 - * - * @return array - */ - public function getDoingTaskList(): array - { - return array_filter($this->processTaskList, function (ProcessTask $task) { - return $task->getData('task_state') === ProcessTaskStateEnum::DOING[0]; - }); - } - - public function setMerged(bool $isMerged): void - { - $this->isMerged = $isMerged; - } - - public function getMerged(): bool - { - return $this->isMerged ?? false; - } - - -} diff --git a/src/core/ProcessEngines.php b/src/core/ProcessEngines.php deleted file mode 100644 index d2837a03684eda1f818c1e265f4288f48c8514da..0000000000000000000000000000000000000000 --- a/src/core/ProcessEngines.php +++ /dev/null @@ -1,271 +0,0 @@ -configure($config); - $this->processTaskService = ServiceContext::find('processTaskService'); - $this->processDefineService = ServiceContext::find('processDefineService'); - $this->processInstanceService = ServiceContext::find('processInstanceService'); - $this->processCcInstanceService = ServiceContext::find('processCcInstanceService'); - $this->processTypesService = ServiceContext::find('processTypesService'); - $this->processDesignService = ServiceContext::find('processDesignService'); - return $this; - } - - public function configure(ConfigurationInterface|array $config = []): void - { - if ($config instanceof ConfigurationInterface) { - $this->configuration = $config; - ServiceContext::put('configure', $config); - } else { - $config = new Configuration($config); - $this->configuration = $config; - ServiceContext::put('configure', $config); - } - } - - public function processDefineService(): ProcessDefineService - { - return $this->processDefineService; - } - - public function processInstanceService(): ProcessInstanceService - { - return $this->processInstanceService; - } - - public function processTaskService(): ProcessTaskService - { - return $this->processTaskService; - } - - public function processTypesService(): ?ProcessTypesService - { - return $this->processTypesService; - } - - public function processCcInstanceService(): ProcessCcInstanceService - { - return $this->processCcInstanceService; - } - - public function processDesignService(): ProcessDesignServiceInterface - { - return $this->processDesignService; - } - - public function startProcessInstanceById(string $id, string $operator, Dict $args, string|null $parentId = null, string|null $parentNodeName = null): ProcessInstance - { - // 1. 根据流程定义ID查询流程定义文件 - $processDefine = $this->processDefineService->getById($id); - if (empty($processDefine)) { - throw new LFlowException('缺少流程定义'); - } - // 2. 将流程定义文件转成流程模型 - $processModel = $this->processDefineService->processDefineToModel($processDefine); - // 3. 根据流程定义对象创建流程实例 - $processInstance = $this->processInstanceService->createProcessInstance($processDefine, $operator, $args, $parentId, $parentNodeName); - // 4. 构建执行参数对象 - $execution = new Execution(); - $execution->setProcessModel($processModel); - $execution->setProcessInstance($processInstance); - $execution->setProcessInstanceId($processInstance->getData('id')); - $execution->setEngine($this); - $execution->setArgs($args); - // 5. 拿到开始节点模型,调用其execute方法 - $processModel->getStart()->execute($execution); - return $processInstance; - } - - public function executeProcessTask(string $processTaskId, string $operator, Dict $args): array - { - $execution = $this->execute($processTaskId, $operator, $args); - if ($execution == null) { - return []; - } - $processModel = $execution->getProcessModel(); - // 7. 根据流程任务名称获取对应的任务节点模型 - $nodeModel = $processModel->getNode($execution->getProcessTask()->getData('task_name')); - - // 8. 调用节点模型执行方法 - $nodeModel->execute($execution); - - return $execution->getProcessTaskList(); - } - - public function executeAndJumpTask(string $processTaskId, string $operator, Dict $args, string $nodeName=''): array - { - $execution = $this->execute($processTaskId, $operator, $args); - if ($execution == null) { - return []; - } - $model = $execution->getProcessModel(); - if (empty($nodeName)) { - $newTask = $this->processTaskService()->rejectTask($model, $execution->getProcessTask()); - $execution->addTask($newTask); - } else { - $nodeModel = $model->getNode($nodeName); - if ($nodeModel == null) { - throw new LFlowException([99999999, "根据节点名称[" . $nodeName . "]无法找到节点模型"]); - } - // 判断是否为第一个任务节点 - if ($nodeModel instanceof TaskModel) { - $taskModel = $nodeModel; - if (ProcessFlowUtils::isFistTaskName($model, $taskModel->getName())) { - // 第一个任务节点为申请节点,处理人等于流程发起人 - $taskModel->setAssignee($execution->getProcessInstance()->getData('operator')); - } - } - //动态创建转移对象,由转移对象执行execution实例 - $tm = new TransitionModel(); - $tm->setTarget($nodeModel); - $tm->setEnabled(true); - $tm->execute($execution); - } - return $execution->getProcessTaskList(); - } - - public function executeAndJumpToEnd(string $processTaskId, string $operator, Dict $args): array - { - $execution = $this->execute($processTaskId, $operator, $args); - if ($execution == null) { - return []; - } - $model = $execution->getProcessModel(); - $endModelList = $model->getModels(EndModel::class); - foreach ($endModelList as $endModel) { - $tm = new TransitionModel(); - $tm->setTarget($endModel); - $tm->setEnabled(true); - $tm->execute($execution); - } - // 将流程状态修改为已拒绝 - $processInstance = new ProcessInstance(); - $processInstance->set('id', $execution->getProcessInstanceId()); - $processInstance->set('state', ProcessInstanceStateEnum::REJECT[0]); - $processInstance->set('update_time', time()); - $processInstance->set('update_user', $operator); - return $execution->getProcessTaskList(); - } - - public function executeAndJumpToFirstTaskNode(string $processTaskId, string $operator, Dict $args): array - { - $execution = $this->execute($processTaskId, $operator, $args); - if ($execution == null) { - return []; - } - $model = $execution->getProcessModel(); - $startModel = $model->getStart(); - foreach ($startModel->getOutputs() as $transitionModel) { - $transitionModel->setEnabled(true); - // 调整参与者为流程发起人 - if ($transitionModel->getTarget() instanceof TaskModel) { - $taskModel = $transitionModel->getTarget(); - $taskModel->setAssignee($execution->getProcessInstance()->getData('operator')); - } - $transitionModel->execute($execution); - } - return $execution->getProcessTaskList(); - } - - private function execute(string $processTaskId, string $operator, Dict $args): ?Execution - { - // 1.1 根据id查询正在进行中的流程任务 - $processTask = $this->processTaskService()->getById($processTaskId); - if ($processTask == null || !StringHelper::equalsIgnoreCase(ProcessTaskStateEnum::DOING[0], $processTask->getData('task_state'))) { - throw new LFlowException(LfErrEnum::NOT_FOUND_DOING_PROCESS_TASK); - } - // 1.2 判断是否可以执行任务 - if (!$this->processTaskService()->isAllowed($processTask, $operator)) { - // 当前参与者不能执行该流程任务 - throw new LFlowException(LfErrEnum::NOT_ALLOWED_EXECUTE); - } - // 2. 根据流程任务查询流程实例 - $processInstance = $this->processInstanceService()->getById($processTask->getData('process_instance_id')); - // 3. 根据流程实例查询流程定义 - $processDefine = $this->processDefineService()->getById($processInstance->getData('process_define_id')); - // 4. 将流程定义文件转成流程模型 - $processModel = ModelParser::parse($processDefine->getData('content')); - // 5. 将流程任务状态修改为已完成 - $this->processTaskService()->finishProcessTask($processTaskId, $operator, $args); - $processTask->set('task_state', ProcessTaskStateEnum::FINISHED[0]); - // 6. 根据流程定义、实例、任务构建执行参数对象 - $execution = new Execution(); - $execution->setProcessModel($processModel); - $execution->setProcessInstance($processInstance); - $execution->setProcessInstanceId($processInstance->getData('id')); - $execution->setProcessTask($processTask); - $execution->setProcessTaskId($processTaskId); - $execution->setOperator($operator); - $execution->setEngine($this); - - $processInstanceVariable = $processInstance->getData('variable'); - $newArgs = ProcessFlowUtils::variableToDict($processInstanceVariable); - $newArgs->putAll($args->getAll()); - $execution->setArgs($newArgs); - // 如果提交参数中存在f_前辍参数,则更新到流程实例变量中 - $prefixArgs = array_filter($args->toArray(), function ($value, $key) { - if (str_starts_with($key, ProcessConst::FORM_DATA_PREFIX)) { - return true; // 返回 false 以便从过滤结果中排除这些键值对 - } - return false; // 其他键值对会被包含在过滤结果中(但在这个上下文中我们不关心它们) - }, ARRAY_FILTER_USE_BOTH); // 使用 ARRAY_FILTER_USE_BOTH 同时传递键和值给回调函数 - - $addsArgs = ProcessFlowUtils::variableToDict($prefixArgs); - if (!empty($addsArgs->getAll())) { - $this->processInstanceService()->addVariable($processInstance->getData('id'), $addsArgs); - } - return $execution; - } -} diff --git a/src/core/ServiceContext.php b/src/core/ServiceContext.php deleted file mode 100644 index dc818c7124ca3d3e6e791c07033fdf4c82fa42af..0000000000000000000000000000000000000000 --- a/src/core/ServiceContext.php +++ /dev/null @@ -1,113 +0,0 @@ - $object) { - if ($object instanceof $clazz) { - $result[] = $object; - } - } - return $result; - } - - public static function findByName($name, $clazz) - { - if (!isset(self::$context)) { - throw new LFlowException("未注册服务上下文"); - } - $object = self::$context[$name]; - if ($object instanceof $clazz) { - return $object; - } - return null; - } - - public static function findAll(string $interfaceName): array - { - $services = []; - foreach (self::$context as $service) { - if ($service instanceof $interfaceName) { - $services[] = $service; - } - } - return $services; - } - - public static function findFirst(string $interfaceName): ?object - { - foreach (self::$context as $service) { - if ($service instanceof $interfaceName) { - return $service; - } - } - return null; // 如果没有找到实现该接口的对象,则返回 null - } -} - diff --git a/src/db/ProcessCcInstance.php b/src/db/ProcessCcInstance.php deleted file mode 100644 index 7570227e0f80e2655faf1c1a57501ff0d450b8c0..0000000000000000000000000000000000000000 --- a/src/db/ProcessCcInstance.php +++ /dev/null @@ -1,118 +0,0 @@ - 'timestamp:Y-m-d H:i:s', - 'update_time' => 'timestamp:Y-m-d H:i:s', - ]; - - /** - * ProcessInstanceId 搜索器 - * - * @param \think\db\Query $query - * @param $value - */ - public function searchProcessInstanceIdAttr($query, $value): void - { - if (!empty($value)) { - $query->where('process_instance_id', $value); - } - } - - /** - * Id 搜索器 - * - * @param \think\db\Query $query - * @param $value - */ - public function searchIdAttr($query, $value): void - { - if (!empty($value)) { - $query->where('id', $value); - } - } - - /** - * State 状态搜索器 - * - * @param \think\db\Query $query - * @param $value - */ - public function searchStateAttr($query, $value): void - { - if (!empty($value)) { - $query->where('state', $value); - } - } - - /** - * ActorId 被抄送人ID 搜索器 - * - * @param \think\db\Query $query - * @param $value - */ - public function searchActorIdAttr($query, $value): void - { - if (!empty($value)) { - $query->where('actor_id', $value); - } - } - - /** - * 流程实例一对一关联 - * @return \think\model\relation\HasOne - */ - public function processInstance(): \think\model\relation\HasOne - { - return $this->hasOne(ProcessInstance::class, 'id', 'process_instance_id'); - } - -} diff --git a/src/db/ProcessDefine.php b/src/db/ProcessDefine.php deleted file mode 100644 index 4ff10db1c7aa8e76901f697ab0ec60f32de5605a..0000000000000000000000000000000000000000 --- a/src/db/ProcessDefine.php +++ /dev/null @@ -1,159 +0,0 @@ - 'timestamp:Y-m-d H:i:s', - 'update_time' => 'timestamp:Y-m-d H:i:s', - ]; - - /** - * 唯一编码 - * - * @param $query - * @param $value - */ - public function searchNameAttr($query, $value) - { - if ($value) { - $query->where('name', $value); - } - } - - /** - * 是否删除搜索器 - * - * @param $query - * @param $value - */ - public function searchIsDelAttr($query, $value) - { - $query->where('is_del', 0); - if ($value) { - $query->where('is_del', $value); - } - } - - /** - * 显示名称搜索器 - * - * @param $query - * @param $value - */ - public function searchDisplayNameAttr($query, $value) - { - if (!empty($value)) { - $query->whereLike('display_name', '%' . $value . '%'); - } - } - - /** - * 状态搜索器 - * - * @param $query - * @param $value - */ - public function searchStateAttr($query, $value) - { - if ($value !== '') { - $query->where('state', $value); - } - } - - /** - * 描述搜索器 - * - * @param $query - * @param $value - */ - public function searchDescriptionAttr($query, $value) - { - if ($value) { - $query->whereLike('description', '%' . $value . '%'); - } - } - - /** - * 分类搜索器 - * - * @param $query - * @param $value - */ - public function searchTypeIdAttr($query, $value) - { - if ($value) { - $query->where('type_id', $value); - } - } - - /** - * 流程版本-搜索器 - * - * @param $query - * @param $value - */ - public function searchVersionAttr($query, $value) - { - if (!empty($value)) { - $query->where('version', $value); - } - } - - /** - * 定义管理一对一流程类型表 - * - * @return \think\model\relation\HasOne - */ -// public function processType(): \think\model\relation\HasOne -// { -// return $this->hasOne(ProcessType::class, 'id', 'type_id'); -// } -// -// public function processDefineFavorite(): \think\model\relation\HasOne -// { -// return $this->hasOne(ProcessDefineFavorite::class, 'process_define_id', 'id'); -// } - -} diff --git a/src/db/ProcessDefineFavorite.php b/src/db/ProcessDefineFavorite.php deleted file mode 100644 index 74b4880c06799d2b3a8a6515f9d18d4edde6ae42..0000000000000000000000000000000000000000 --- a/src/db/ProcessDefineFavorite.php +++ /dev/null @@ -1,88 +0,0 @@ - 'timestamp:Y-m-d H:i:s', - 'update_time' => 'timestamp:Y-m-d H:i:s', - ]; - - /** - * 用户ID搜索器 - * - * @param $query - * @param $value - */ - public function searchUserIdAttr($query, $value) - { - if ($value) { - $query->where('user_id', $value); - } - } - - /** - * 流程定义ID搜索器 - * - * @param $query - * @param $value - */ - public function searchProcessDefineIdAttr($query, $value) - { - if ($value) { - $query->where('process_define_id', $value); - } - } - - /** - * 定义管理一对一流程定义表 - * - * @return \think\model\relation\HasOne - */ - public function processDefine(): \think\model\relation\HasOne - { - return $this->hasOne(ProcessDefine::class, 'id', 'process_define_id')->bind(['display_name','version']); - } - -} diff --git a/src/db/ProcessDesign.php b/src/db/ProcessDesign.php deleted file mode 100644 index ed5969ebc26ea0ae43a105ed38e38650d4294917..0000000000000000000000000000000000000000 --- a/src/db/ProcessDesign.php +++ /dev/null @@ -1,150 +0,0 @@ - 'timestamp:Y-m-d H:i:s', - 'update_time' => 'timestamp:Y-m-d H:i:s', - ]; - - public function searchIdAttr($query, $value) - { - if ($value) { - $query->where('id', $value); - } - } - - public function searchNotIdAttr($query, $value) - { - if ($value) { - $query->where('id', '<>', $value); - } - } - - /** - * 唯一编码 - * - * @param $query - * @param $value - */ - public function searchNameAttr($query, $value) - { - if ($value) { - $query->where('name', $value); - } - } - - /** - * 是否删除搜索器 - * - * @param $query - * @param $value - */ - public function searchIsDelAttr($query, $value) - { - $query->where('is_del', 0); - if ($value) { - $query->where('is_del', $value); - } - } - - /** - * 显示名称搜索器 - * - * @param $query - * @param $value - */ - public function searchDisplayNameAttr($query, $value) - { - if ($value) { - $query->whereLike('display_name', '%' . $value . '%'); - } - } - - /** - * 流程定义描述搜索器 - * - * @param $query - * @param $value + - */ - public function searchDescriptionAttr($query, $value) - { - if ($value) { - $query->whereLike('description', '%' . $value . '%'); - } - } - - /** - * 定义关联一对多历史表 - * - * @return \think\model\relation\HasMany - */ -// public function version(): \think\model\relation\HasMany -// { -// return $this->hasMany(ProcessDesignHis::class, 'process_design_id', 'id'); -// } - - /** - * 定义管理一对一流程类型表 - * - * @return \think\model\relation\HasOne - */ - public function processType(): \think\model\relation\HasOne - { - return $this->hasOne(ProcessType::class, 'id', 'type_id'); - } - - /** - * 定义关联一对多历史表 - * - * @return \think\model\relation\HasMany - */ - public function history(): \think\model\relation\HasMany - { - return $this->hasMany(ProcessDesignHistory::class, 'process_design_id', 'id'); - } - - public function deleteWithHistory(): bool - { - // 删除关联的所有历史记录 - $this->history()->delete(); - // 删除设计本身 - return $this->delete(); - } -} diff --git a/src/db/ProcessDesignHistory.php b/src/db/ProcessDesignHistory.php deleted file mode 100644 index 696e46cccf170bb11505859ebf1dff92a319e986..0000000000000000000000000000000000000000 --- a/src/db/ProcessDesignHistory.php +++ /dev/null @@ -1,74 +0,0 @@ - 'timestamp:Y-m-d H:i:s', - ]; - - // 设置json类型字段 - protected $json = ['content']; - - /** - * ID 搜索器 - * - * @param $query - * @param $value - */ - public function searchIdAttr($query, $value) - { - if ($value) { - $query->where('id', $value); - } - } - - /** - * 流程设计ID搜索器 - * - * @param $query - * @param $value - */ - public function searchProcessDesignIdAttr($query, $value) - { - if ($value) { - $query->where('process_design_id', $value); - } - } -} diff --git a/src/db/ProcessForm.php b/src/db/ProcessForm.php deleted file mode 100644 index 01b1dadd9651f193bd9c4ce63693343d44faa36f..0000000000000000000000000000000000000000 --- a/src/db/ProcessForm.php +++ /dev/null @@ -1,155 +0,0 @@ - 'timestamp:Y-m-d H:i:s', - 'update_time' => 'timestamp:Y-m-d H:i:s', - ]; - - public function searchIdAttr($query, $value) - { - if ($value) { - $query->where('id', $value); - } - } - - public function searchNotIdAttr($query, $value) - { - if ($value) { - $query->where('id', '<>', $value); - } - } - - /** - * 唯一编码 - * - * @param $query - * @param $value - */ - public function searchNameAttr($query, $value) - { - if ($value) { - $query->where('name', $value); - } - } - - /** - * 是否删除搜索器 - * - * @param $query - * @param $value - */ - public function searchIsDelAttr($query, $value) - { - $query->where('is_del', 0); - if ($value) { - $query->where('is_del', $value); - } - } - - /** - * 显示名称搜索器 - * - * @param $query - * @param $value - */ - public function searchDisplayNameAttr($query, $value) - { - if ($value) { - $query->whereLike('display_name', '%' . $value . '%'); - } - } - - /** - * 流程定义描述搜索器 - * - * @param $query - * @param $value + - */ - public function searchDescriptionAttr($query, $value) - { - if ($value) { - $query->whereLike('description', '%' . $value . '%'); - } - } - - /** - * 定义关联一对多历史表 - * - * @return \think\model\relation\HasMany - */ -// public function version(): \think\model\relation\HasMany -// { -// return $this->hasMany(ProcessDesignHis::class, 'process_design_id', 'id'); -// } - - /** - * 定义管理一对一流程类型表 - * - * @return \think\model\relation\HasOne - */ - public function processType(): \think\model\relation\HasOne - { - return $this->hasOne(ProcessType::class, 'id', 'type_id'); - } - - /** - * 定义关联一对多历史表 - * - * @return \think\model\relation\HasMany - */ - public function history(): \think\model\relation\HasMany - { - return $this->hasMany(ProcessFormHistory::class, 'process_form_id', 'id'); - } - - /** - * 删除表单记录 - * - * @return bool - */ - public function deleteWithHistory(): bool - { - // 删除关联的所有历史记录 - $this->history()->delete(); - // 删除设计本身 - return $this->delete(); - } -} diff --git a/src/db/ProcessFormHistory.php b/src/db/ProcessFormHistory.php deleted file mode 100644 index 4a115830cc897e6988cb282f6eccde3543b13652..0000000000000000000000000000000000000000 --- a/src/db/ProcessFormHistory.php +++ /dev/null @@ -1,82 +0,0 @@ - 'timestamp:Y-m-d H:i:s', - ]; - - // 设置json类型字段 - protected $json = ['content']; - - /** - * ID 搜索器 - * - * @param $query - * @param $value - */ - public function searchIdAttr($query, $value) - { - if ($value) { - $query->where('id', $value); - } - } - - /** - * 流程设计ID搜索器 - * - * @param $query - * @param $value - */ - public function searchProcessDesignIdAttr($query, $value) - { - if (!empty($value)) { - $query->where('process_design_id', $value); - } - } - - //版本搜索器 - public function searchVersionsAttr($query,$value) - { - - if (!empty($value)) { - $query->where('versions', $value); - } - } -} diff --git a/src/db/ProcessInstance.php b/src/db/ProcessInstance.php deleted file mode 100644 index 02085b8f28b82739a6863714716b1050f2c19ddf..0000000000000000000000000000000000000000 --- a/src/db/ProcessInstance.php +++ /dev/null @@ -1,170 +0,0 @@ - 'timestamp:Y-m-d H:i:s', - 'update_time' => 'timestamp:Y-m-d H:i:s', - ]; - - // 设置json类型字段 - protected $json = ['variable']; - - /** - * ID-搜索器 - * - * @param $query - * @param $value - */ - public function searchIdAttr($query, $value) - { - if ($value) { - $query->where('id', $value); - } - } - - /** - * 父流程ID-搜索器 - * - * @param $query - * @param $value - */ - public function searchParentIdAttr($query, $value) - { - if ($value) { - $query->where('parent_id', $value); - } - } - - /** - * 流程定义ID-搜索器 - * - * @param $query - * @param $value - */ - public function searchProcessDefineIdAttr($query, $value) - { - if ($value) { - $query->where('process_define_id', $value); - } - } - - /** - * 实例状态搜索器 - * - * @param $query - * @param $value - */ - public function searchStateAttr($query, $value) - { - if ($value) { - $query->where('state', $value); - } - } - - /** - * 父流程依赖节点-搜索器 - * - * @param $query - * @param $value - */ - public function searchParentNodeNameAttr($query, $value) - { - if ($value) { - $query->where('parent_node_name', $value); - } - } - - /** - * 业务编号-搜索器 - * - * @param $query - * @param $value - */ - public function searchBusinessNoAttr($query, $value) - { - if ($value) { - $query->where('business_no', $value); - } - } - - /** - * 流程发起人-搜索器 - * - * @param $query - * @param $value - */ - public function searchOperatorAttr($query, $value) - { - if ($value) { - $query->where('operator', $value); - } - } - - /** - * 流程实例一对一流程定义表 - * - * @return \think\model\relation\HasOne - */ - public function processDefine(): \think\model\relation\HasOne - { - return $this->hasOne(ProcessDefine::class, 'id', 'process_define_id'); - } - - - /** - * 提取实例的表单数据字段属性 - * - * @return \stdClass - */ - public function getFormData(): \stdClass - { - $formData = new \stdClass(); - $ext = $this->getData('variable'); - $formDataKeys = array_filter(array_keys((array)$ext), function ($key) { - return str_starts_with($key, 'f_'); - }); - foreach ($formDataKeys as $key) { - $formData->{$key} = $ext->{$key}; - } - return $formData; - } -} - diff --git a/src/db/ProcessSurrogate.php b/src/db/ProcessSurrogate.php deleted file mode 100644 index fe424d957a9c8eba12bf6794fa2b9ae10ffcaa0d..0000000000000000000000000000000000000000 --- a/src/db/ProcessSurrogate.php +++ /dev/null @@ -1,122 +0,0 @@ - 'timestamp:Y-m-d H:i:s', - 'update_time' => 'timestamp:Y-m-d H:i:s', - 'start_time' => 'timestamp:Y-m-d H:i:s', - 'end_time' => 'timestamp:Y-m-d H:i:s', - ]; - - /** - * ID-搜索器 - * - * @param $query - * @param $value - */ - public function searchIdAttr($query, $value) - { - if ($value) { - $query->where('id', $value); - } - } - - /** - * 流程名称-搜索器 - * - * @param $query - * @param $value - */ - public function searchProcessNameAttr($query, $value) - { - if ($value) { - $query->where('process_name', $value); - } - } - - /** - * 授权人-搜索器 - * - * @param $query - * @param $value - */ - public function searchOperatorAttr($query, $value) - { - if ($value) { - $query->where('operator', $value); - } - } - - /** - * 代理人-搜索器 - * - * @param $query - * @param $value - */ - public function searchSurrogateAttr($query, $value) - { - if ($value) { - $query->where('surrogate', $value); - } - } - - /** - * 启用状态-搜索器 - * - * @param $query - * @param $value - */ - public function searchEnabledAttr($query, $value) - { - if ($value !== '') { - $query->where('enabled', $value); - } - } - - /** - * 流程实例一对一流程定义表 - * - * @return \think\model\relation\HasOne - */ - public function processDefine(): \think\model\relation\HasOne - { - return $this->hasOne(ProcessDefine::class, 'name', 'process_name')->bind(['type_id', 'display_name', 'version']); - } -} diff --git a/src/db/ProcessTask.php b/src/db/ProcessTask.php deleted file mode 100644 index 2a2b029c00b72fef58d5747dcdc0b3e0fadf437c..0000000000000000000000000000000000000000 --- a/src/db/ProcessTask.php +++ /dev/null @@ -1,219 +0,0 @@ - 'timestamp:Y-m-d H:i:s', - 'update_time' => 'timestamp:Y-m-d H:i:s', - 'finish_time' => 'timestamp:Y-m-d H:i:s', - ]; - - - /** - * JSON字段 - * - * @var string[] - */ - protected $json = ['variable']; - - /** - * ID-搜索器 - * - * @param $query - * @param $value - */ - public function searchIdAttr($query, $value) - { - if (!empty($value)) { - $query->where('id', $value); - } - } - - /** - * 流程实例ID-搜索器 - * - * @param $query - * @param $value - */ - public function searchProcessInstanceIdAttr($query, $value) - { - if (!empty($value)) { - $query->where('process_instance_id', $value); - } - } - - /** - * 任务名称自动识别in搜索器 - * - * @param $query - * @param $value - */ - public function searchTaskNameAttr($query, $value) - { - if (!empty($value)) { - if (is_array($value)) { - $query->whereIn('task_name', implode(',', $value)); - } else { - $isTrue = count(explode(',', $value)) > 1; - if ($isTrue) { - $query->whereIn('task_name', $value); - } else { - $query->where('task_name', $value); - } - } - } - } - - public function searchDisplayNameAttr($query, $value) - { - if (!empty($value)) { - $query->where('display_name', $value); - } - } - - /** - * 任务类型-搜索器 - * - * @param $query - * @param $value - */ - public function searchTaskTypeAttr($query, $value) - { - if (!empty($value)) { - $query->where('task_type', $value); - } - } - - /** - * 参与类型-搜索器 - * - * @param $query - * @param $value - */ - public function searchPerformTypeAttr($query, $value) - { - if (!empty($value)) { - $query->where('perform_type', $value); - } - } - - /** - * 任务状态-搜索器 - * - * @param $query - * @param $value - */ - public function searchTaskStateAttr($query, $value) - { - if (!empty($value)) { - $query->where('task_state', $value); - } - } - - /** - * 任务状态自动识别notIn 搜索器 - * - * @param $query - * @param $value - */ - public function searchNotInTaskStateAttr($query, $value) - { - if (!empty($value)) { - if (is_array($value)) { - $query->whereNotIn('task_state', implode(',', $value)); - } else { - $isTrue = count(explode(',', $value)) > 1; - if ($isTrue) { - $query->whereNotIn('task_state', $value); - } else { - $query->where('task_state', '<>', $value); - } - } - } - } - - /** - * 任务处理人 - * - * @param $query - * @param $value - */ - public function searchOperatorAttr($query, $value) - { - if (!empty($value)) { - $query->where('operator', $value); - } - } - - /** - * 父任务ID-搜索器 - * - * @param $query - * @param $value - */ - public function searchTaskParentIdAttr($query, $value) - { - if (!empty($value)) { - $query->where('task_parent_id', $value); - } - } - - /** - * 任务处理表单key-搜索器 - * - * @param $query - * @param $value - */ - public function searchFormKeyAttr($query, $value) - { - if (!empty($value)) { - $query->where('form_key', $value); - } - } - - /** - * 流程任务关联定义 - * - * @return \think\model\relation\HasOne - */ - public function processInstance(): \think\model\relation\HasOne - { - return $this->hasOne(ProcessInstance::class, 'id', 'process_instance_id'); - } - -} diff --git a/src/db/ProcessTaskActor.php b/src/db/ProcessTaskActor.php deleted file mode 100644 index dabcd0f6f8efed16b1bfa39311f524e1d37e7d36..0000000000000000000000000000000000000000 --- a/src/db/ProcessTaskActor.php +++ /dev/null @@ -1,105 +0,0 @@ - 'timestamp:Y-m-d H:i:s', - 'finish_time' => 'timestamp:Y-m-d H:i:s', - ]; - - // 设置字段信息 - protected $schema = [ - 'id' => 'string', - 'process_task_id' => 'string', - 'actor_id' => 'string|int', - 'create_time' => 'int', - 'create_user' => 'string', - ]; - - /** - * ID-搜索器 - * - * @param $query - * @param $value - */ - public function searchIdAttr($query, $value) - { - if (!empty($value)) { - $query->where('id', $value); - } - } - - /** - * 流程任务ID-搜索器 - * - * @param $query - * @param $value - */ - public function searchProcessTaskIdAttr($query, $value) - { - if (!empty($value)) { - $query->where('process_task_id', $value); - } - } - - /** - * 参与者ID-搜索器 - * - * @param $query - * @param $value - */ - public function searchActorIdAttr($query, $value) - { - if (!empty($value)) { - $query->where('actor_id', $value); - } - } - - /** - * 流程任务用户关联任务task - * - * @return \think\model\relation\HasOne - */ - public function processTask(): \think\model\relation\HasOne - { - return $this->hasOne(ProcessTask::class, 'id', 'process_task_id')->bind(['task_name','display_name','task_state']); - } -} diff --git a/src/db/ProcessType.php b/src/db/ProcessType.php deleted file mode 100644 index 9971fd86e26e113b8e68342eb07d4ee49025fef1..0000000000000000000000000000000000000000 --- a/src/db/ProcessType.php +++ /dev/null @@ -1,114 +0,0 @@ - 'timestamp:Y-m-d H:i:s', - 'update_time' => 'timestamp:Y-m-d H:i:s', - ]; - - public function searchPidAttr($query, $value) - { - if (!empty($value)) { - $query->where('pid', $value); - } - } - - /** - * 类型名称 - * - * @param $query - * @param $value - */ - public function searchNameAttr($query, $value) - { - - if (!empty($value)) { - $query->whereLike('name', '%' . $value . '%'); - } - } - - /** - * 是否删除搜索器 - * - * @param $query - * @param $value - */ - public function searchIsDelAttr($query, $value) - { - if (!empty($value)) { - $query->where('is_del', $value); - } else { - $query->where('is_del', 0); - } - } - - /** - * 状态搜索器 - * - * @param $query - * @param $value - */ - public function searchStatusAttr($query, $value) - { - if (!empty($value)) { - $query->where('status', $value); - } - } - - public function parent(): \think\model\relation\HasOne - { - return $this->hasOne(ProcessType::class, 'id', 'pid'); - } - - /** - * 类型关联流程定义 - * @return \think\model\relation\HasMany - */ - public function processDefine() - { - return $this->hasMany(ProcessDefine::class, 'type_id', 'id')->where('state', 1); - } -} diff --git a/src/db/virtual/HighLightVirtual.php b/src/db/virtual/HighLightVirtual.php deleted file mode 100644 index 13ea980f0a64d81234e99ea44c0dc08c564845dd..0000000000000000000000000000000000000000 --- a/src/db/virtual/HighLightVirtual.php +++ /dev/null @@ -1,78 +0,0 @@ -{$propertyName}; - if (empty($property)) { - return false; - } - return in_array($value, $property); - } - - public function add(string $propertyName, string $value): self - { - $this->{$propertyName}[] = $value; - return $this; - } - - public function get(string $propertyName) - { - if (property_exists($this, $propertyName)) { - return $this->{$propertyName}; - } - return null; - } - - public function remove(string $propertyName, string $value): self - { - if (property_exists($this, $propertyName)) { - $property = &$this->{$propertyName}; // 使用引用,以便直接修改原数组 - $key = array_search($value, $property); // 查找值的键 - if ($key !== false) { - unset($property[$key]); // 如果找到键,则删除它 - $property = array_values($property); // 重新索引数组 - } - } - return $this; - } - - /** - * 重写toArray - * - * @return array - */ - public function toArray(): array - { - return [ - 'history_node_names' => $this->history_node_names ?? [], - 'history_edge_names' => $this->history_edge_names ?? [], - 'active_node_names' => $this->active_node_names ?? [], - ]; - } -} - - diff --git a/src/domain/DefaultNoGenerator.php b/src/domain/DefaultNoGenerator.php deleted file mode 100644 index fe6a53c1f466a05c22114a7fcb65cfdff660a38f..0000000000000000000000000000000000000000 --- a/src/domain/DefaultNoGenerator.php +++ /dev/null @@ -1,36 +0,0 @@ -format('YmdHis'); - return $dateTime . rand(1000, 9999); - } -} diff --git a/src/domain/SurrogateInterceptor.php b/src/domain/SurrogateInterceptor.php deleted file mode 100644 index 58ec7b95aec3521a1c64de6c96ba6dd5a3a081e4..0000000000000000000000000000000000000000 --- a/src/domain/SurrogateInterceptor.php +++ /dev/null @@ -1,40 +0,0 @@ -getProcessTaskList(); - foreach ($processTaskList as $processTask) { - $actorList = $execution->getEngine()->processTaskService()->getTaskActors($processTask->getData('id')); - foreach ($actorList as $actor) { - $agent = $execution->getEngine()->processTaskService()->getSurrogate($actor, $execution->getProcessModel()->getName()); - if (!empty($agent)) { - $execution->getEngine()->processTaskService()->addTaskActor($processTask->getData('id'), $agent); - } - } - } - } -} diff --git a/src/enums/CountersignTypeEnum.php b/src/enums/CountersignTypeEnum.php deleted file mode 100644 index afe331c2d360132e70c94a7727b9f8a692a76abd..0000000000000000000000000000000000000000 --- a/src/enums/CountersignTypeEnum.php +++ /dev/null @@ -1,31 +0,0 @@ -eventType = $eventType; - $this->sourceId = $sourceId; - } - - public function getEventType(): int|string|null - { - return $this->eventType ?? null; - } - - public function getSourceId(): int|string|null - { - return $this->sourceId ?? null; - } - -} diff --git a/src/event/ProcessEventHandler.php b/src/event/ProcessEventHandler.php deleted file mode 100644 index 7892c858b2e72e335b00588eb8550e9b97d6fa92..0000000000000000000000000000000000000000 --- a/src/event/ProcessEventHandler.php +++ /dev/null @@ -1,30 +0,0 @@ -onEvent($event); - } - } - -} diff --git a/src/event/ProcessEventListener.php b/src/event/ProcessEventListener.php deleted file mode 100644 index 81d4f33f21eaf0526eea5e5748ca6a5f47ff4612..0000000000000000000000000000000000000000 --- a/src/event/ProcessEventListener.php +++ /dev/null @@ -1,21 +0,0 @@ -onEvent($event); -// } - // 调用处理类处理事件 - $eventHandler = new ProcessEventHandler(); - $eventHandler->handle($event); - } - - /** - * 发布通知 - * - * @param string $eventType 事件类型 - * @param mixed $sourceId 事件源 - * @return void - */ - public static function publishNotification(string $eventType, mixed $sourceId): void { - $event = new ProcessEvent($eventType, $sourceId); - self::triggerEvent($event); - } - - /** - * 获取所有事件列表 - * - * @return array - */ - public static function getAllEvents(): array { - return self::$events; - } - - /** - * 获取指定类型的事件列表 - * - * @param string $eventType 事件类型 - * @return array - */ - public static function getEventsByType(string $eventType): array { - $filteredEvents = []; - foreach (self::$events as $event) { - if ($event->getEventType() === $eventType) { - $filteredEvents[] = $event; - } - } - return $filteredEvents; - } -} - diff --git a/src/ex/LFlowException.php b/src/ex/LFlowException.php deleted file mode 100644 index e42de9796dc6f048c92f58a5d77878a6d31779b6..0000000000000000000000000000000000000000 --- a/src/ex/LFlowException.php +++ /dev/null @@ -1,35 +0,0 @@ -defaultValue($this->getPropertyType($propertyName)); - return $this->$propertyName ?? $defaultValue; - } elseif (property_exists($this, $this->camelCaseToUnderscore($propertyName))) { - $defaultValue = $this->defaultValue($this->getPropertyType($this->camelCaseToUnderscore($propertyName))); - return $this->{$this->camelCaseToUnderscore($propertyName)} ?? $defaultValue; - } - } elseif (str_starts_with($name, 'set')) { // 检查方法名是否以 "set" 开头 - // 提取属性名 - $propertyName = lcfirst(substr($name, 3)); - - // 检查属性是否存在,并根据属性名的不同形式进行设置 - if (property_exists($this, $propertyName)) { - $this->{$propertyName} = $arguments[0]; - } elseif (property_exists($this, $this->camelCaseToUnderscore($propertyName))) { - $this->{$this->camelCaseToUnderscore($propertyName)} = $arguments[0]; - } - } - } - - private function camelCaseToUnderscore($input): string - { - return strtolower(preg_replace('/(?getProperty($propertyName); - $property->setAccessible(true); // 设置属性为可访问,以便获取类型信息 - // 获取属性的类型 - $type = $property->getType(); - if ($type !== null) { - // 如果类型是联合类型,则获取所有可能的类型名称 - if ($type instanceof ReflectionUnionType) { - $typeNames = []; - foreach ($type->getTypes() as $subType) { - $typeNames[] = $subType->getName(); - } - return implode(',', $typeNames); - } else { - return $type->getName(); - } - } - return null; - } - - /** - * 默认值 - * - * @param string $type - * @param \ingenious\libs\traits\mixed|null $default - * - * @return object|string|null - */ - private function defaultValue(string $type, mixed $default = null) - { - switch ($type) { - case 'string': - $default = ''; - break; - case 'array': - $default = []; - case 'object': - $default = (object)[]; - break; - default: - $default = null; - break; - } - return $default; - } - -} diff --git a/src/libs/traits/EnumTrait.php b/src/libs/traits/EnumTrait.php deleted file mode 100644 index 34c053e3f5eb0ec83a1aa5d9677a6d1e795558c4..0000000000000000000000000000000000000000 --- a/src/libs/traits/EnumTrait.php +++ /dev/null @@ -1,66 +0,0 @@ -getConstants(); - static::$enumValues = array_values($constants); - } - return static::$enumValues; - } -} diff --git a/src/libs/utils/ArrayHelper.php b/src/libs/utils/ArrayHelper.php deleted file mode 100644 index c49644647a86d09752b93d8c32349a694e5d2477..0000000000000000000000000000000000000000 --- a/src/libs/utils/ArrayHelper.php +++ /dev/null @@ -1,236 +0,0 @@ - $item) { - if (is_array($item) || is_object($item)) { - $result[self::humpToLine($key)] = self::convertHumpToLine((array)$item); - } else { - $result[self::humpToLine($key)] = trim($item); - } - } - return $result; - } - - /** - * toLineHumpConvert - * - * @param array $data - * - * @return array - */ - public static function toLineHumpConvert(array $data): array - { - $result = []; - foreach ($data as $key => $item) { - if (is_array($item) || is_object($item)) { - $result[self::humpCamelize($key)] = self::toLineHumpConvert((array)$item); - } else { - $result[self::humpCamelize($key)] = trim($item); - } - } - return $result; - } - - /** - * humpToLine 字符串大写转下划线 - * - * @param $str - * - * @return string|null - */ - public static function humpToLine($str): string|null - { - $str = preg_replace_callback('/([A-Z]{1})/', function ($matches) { - return '_' . strtolower($matches[0]); - }, $str); - return $str; - } - - /** - * humpToLine 字符串大写转下划线 - * - * @param string $str - * @param string $separator - * - * @return array|string|string[]|null - */ - public static function humpCamelize(string $str, string $separator = '_'): string|null - { - $str = $separator . str_replace($separator, " ", strtolower($str)); - return ltrim(str_replace(" ", "", ucwords($str)), $separator); - } - - /** - * 数组转换实体对象 - * - * @param array $arr - * @param string $className - * - * @return object - * @throws \ingenious\lib\util\WorkFlowException - */ - public static function arrayToSimpleObj(array $arr, string $className): object - { - try { - //传递类名或对象进来 - $reflectionClass = new ReflectionClass($className); - $obj = $reflectionClass->newInstance(); - foreach ($arr as $key => $value) { - //过滤验证class 是否包含key - if ($reflectionClass->hasProperty($key)) { - $property = $reflectionClass->getProperty($key); - $property->setAccessible(true);//私有属性需要设置允许访问 - $property->setValue($obj, $value); - } - } - return $obj; - } catch (\ReflectionException $e) { - throw new LFlowException($e->getMessage()); - } - } - - /** - * 多维数组转对象 - * - * @param object|array $array - * - * @return \stdClass - */ - public static function arrayToObject(object|array $array): stdClass - { - $object = new stdClass(); - foreach ($array as $key => $value) { - if (is_array($value)) { - if (isset($value[0])) { // 处理下标数组 - $object->$key = self::arrayToObject($value); // 递归处理子数组 - } else { - $object->$key = self::arrayToObject($value); // 处理关联数组 - } - } else { - if (is_numeric($value)) { - $object->$key = $value + 0; // 将字符串转换为数字类型 - } else { - $object->$key = $value; - } - - } - } - - return $object; - } - - /** - * 参数过滤处理 - * - * @param array|object $params - * @param array $rules 【'输入key','默认值','过滤值','重命名key'】 - * - * @return array - */ - public static function paramsFilter(array|object $params, array $rules): array - { - $params = is_object($params) ? (array)$params : $params;//兼容数组对象参数 - /** @var TYPE_NAME $filteredParams */ - $filteredParams = []; - foreach ($rules as $rule) { - $inputKey = $rule[0] ?? null; - $defaultValue = $rule[1] ?? null; - $filterValue = $rule[2] ?? null; - $replaceKey = $rule[3] ?? null; - if (empty($inputKey)) { - continue; - } - //优先传入参数 - if (array_key_exists($inputKey, $params)) { - $paramValue = $params[$inputKey]; - } else { - $paramValue = $defaultValue; - } - - // 参数值过滤 - if (isset($filterValue) && !empty($filterValue)) { - switch ($filterValue) { - case 'string': - $paramValue = (string)$paramValue; - break; - case 'int': - $paramValue = (int)$paramValue; - break; - case 'float': - $paramValue = (float)$paramValue; - break; - case 'bool': - $paramValue = filter_var($paramValue, FILTER_VALIDATE_BOOLEAN); - break; - default: - // 自定义过滤器函数 - if (is_callable($filterValue)) { - $paramValue = call_user_func($filterValue, $paramValue); - } else { - throw new InvalidArgumentException("Invalid filter specified for param {$inputKey}."); - } - } - } - - // 替换参数键名(可选) - $outputKey = $replaceKey ?? $inputKey; - $filteredParams[$outputKey] = $paramValue; - } - - return $filteredParams; - } - - public static function sortItems(array $items, string $key, bool $reverse = false) - { - usort($items, function ($a, $b) use ($key, $reverse) { - $valueA = is_object($a) ? $a->$key : $a[$key] ?? null; - $valueB = is_object($b) ? $b->$key : $b[$key] ?? null; - - if ($valueA === $valueB) { - return 0; - } - - return ($valueA < $valueB) ? ($reverse ? 1 : -1) : ($reverse ? -1 : 1); - }); - - return $items; - - } - -} diff --git a/src/libs/utils/AssertHelper.php b/src/libs/utils/AssertHelper.php deleted file mode 100644 index 526aa224f49964edac67835671d3828adc601309..0000000000000000000000000000000000000000 --- a/src/libs/utils/AssertHelper.php +++ /dev/null @@ -1,100 +0,0 @@ -getTimestamp(); - } - } -} diff --git a/src/libs/utils/Dict.php b/src/libs/utils/Dict.php deleted file mode 100644 index be2a4fd7d68c46fe8d8b40213af18f00eb8e21b0..0000000000000000000000000000000000000000 --- a/src/libs/utils/Dict.php +++ /dev/null @@ -1,84 +0,0 @@ - $value) { - $this->offsetSet($key, $value); - } - } - - public function get(string $key, $default = null): mixed - { - return $this->offsetExists($key) ? $this[$key] : $default; - } - - public function remove(string $key): void - { - unset($this[$key]); - } - - public function clear(): void - { - $this->exchangeArray([]); - } - - public function toArray(): array - { - return $this->getArrayCopy(); - } - - public function getAll(): \stdClass - { - $object = new \stdClass(); - foreach ($this as $key => $value) { - $object->$key = $value; - } - return $object; - } - - public function containsKey(string $key): bool - { - return isset($this[$key]) ?? false; - } - - public static function of(array $entries): self - { - $dict = new self(); - foreach ($entries as $key => $value) { - $dict->put($key, $value); - } - return $dict; - } -} - - diff --git a/src/libs/utils/ExpressionUtil.php b/src/libs/utils/ExpressionUtil.php deleted file mode 100644 index e0d6d567b1755e12155543da06668ac95f7ab841..0000000000000000000000000000000000000000 --- a/src/libs/utils/ExpressionUtil.php +++ /dev/null @@ -1,40 +0,0 @@ - 'strlen'])]); - - // 应用规则到对象 - $result = $rulerZ->satisfies($args, $expr); - return $result ?? false; - } catch (\Exception $e) { - return false; - } - } -} diff --git a/src/libs/utils/Logger.php b/src/libs/utils/Logger.php deleted file mode 100644 index 07dc306a9ebbf79a5666e26d50bb24c32a5da1bf..0000000000000000000000000000000000000000 --- a/src/libs/utils/Logger.php +++ /dev/null @@ -1,141 +0,0 @@ -getConfig('log_path', dirname(__DIR__, 2) . '/log/'); - - $currentLogPath = self::$logBasePath; - - // Ensure the logs directory exists - if (!is_dir($currentLogPath)) { - mkdir($currentLogPath, 0755, true); - } - - $date = new DateTime(); - $currentDate = $date->format('Ymd'); - self::$logger = new Logs('ingenious'); - self::$logger->pushHandler(new StreamHandler($currentLogPath . $currentDate . '_debug.log', Logs::DEBUG, false, 0777)); - self::$logger->pushHandler(new StreamHandler($currentLogPath . $currentDate . '_info.log', Logs::INFO, false, 0777)); - self::$logger->pushHandler(new StreamHandler($currentLogPath . $currentDate . '_notice.log', Logs::NOTICE, false, 0777)); - self::$logger->pushHandler(new StreamHandler($currentLogPath . $currentDate . '_warning.log', Logs::WARNING, false, 0777)); - self::$logger->pushHandler(new StreamHandler($currentLogPath . $currentDate . '_error.log', Logs::ERROR, false, 0777)); - self::$logger->pushHandler(new StreamHandler($currentLogPath . $currentDate . '_critical.log', Logs::CRITICAL, false, 0777)); - self::$logger->pushHandler(new StreamHandler($currentLogPath . $currentDate . '_alert.log', Logs::ALERT, false, 0777)); - self::$logger->pushHandler(new StreamHandler($currentLogPath . $currentDate . '_emergency.log', Logs::EMERGENCY, false, 0777)); - } - - /** - * 静态调用 - * - * @param $name - * @param $arguments - * - * @return void - */ - public static function __callStatic($name, $arguments) - { - if ($name == 'debug' && !self::isDeBug()) { - //如果非调试模式拦截 - return; - } - if (self::$logBasePath === null) { - self::initLogger(); - } - if (in_array($name, ['debug', 'info', 'notice', 'warning', 'error', 'critical', 'alert', 'emergency'])) { - self::$logger->$name($arguments[0]); - } - } - - /** - * 删除非当天日志 - */ - public static function deleteOldLogs(): void - { - if (self::$logBasePath === null) { - self::initLogger(); - } - $currentDate = date('Ymd'); - $directory = new RecursiveDirectoryIterator(self::$logBasePath, RecursiveDirectoryIterator::SKIP_DOTS); - $iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::CHILD_FIRST); - - foreach ($iterator as $file) { - if (!$file->isFile()) { - continue; - } - - $filePath = $file->getRealPath(); - $fileName = $file->getFilename(); - - if (!str_contains($fileName, $currentDate)) { - unlink($filePath); // Delete the log file - } - } - } - - public static function isDeBug(): bool - { - $list = ServiceContext::findList(ConfigurationInterface::class); - $config = end($list); - try { - return $config->getConfig('is_debug', false); - } catch (LFlowException $e) { - return false; - } - } -} - - - - - - - - diff --git a/src/libs/utils/ModelUtils.php b/src/libs/utils/ModelUtils.php deleted file mode 100644 index d56a560da445ee35bfa98eee1ff1b820bc44c891..0000000000000000000000000000000000000000 --- a/src/libs/utils/ModelUtils.php +++ /dev/null @@ -1,136 +0,0 @@ -getFields() ?? []; - foreach ($paramProps as $key => $value) { - if (in_array($key, $fields)) { - $src->{$key} = $value; - } - } - } - - /** - * 给对象类赋值私有属性 - * - * @param object $data - * @param string $className - * @param bool $strictMode 是否严格模式 - * - * @return object - * @throws \ReflectionException - */ - public static function jsonObjToLfModel(object $data, string $className, bool $strictMode = false): object - { - $reflection = new ReflectionClass($className); - $instance = $reflection->newInstanceWithoutConstructor(); // 假设无参构造函数或需要绕过构造函数 - - while ($reflection) { - // 对public private protected 类型属性赋值 - $properties = $reflection->getProperties(ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PUBLIC); - - foreach ($properties as $property) { - $property->setAccessible(true); - $name = $property->getName(); - $value = $data->{$name} ?? ''; - - // 统一处理属性名,支持下划线和驼峰命名 - $camelCaseName = self::convertToCamelCase($name); - $underscoreName = self::convertToUnderscore($name); - - // 检查属性类型和数据中的值,避免将数组类型的属性设置为 null - if (is_array($property->getType()) && !isset($data->{$name})) { - continue; // 如果属性类型为数组且数据中没有对应的值,跳过此次循环 - } - - // 根据数据中的属性名赋值 - if (isset($data->{$name})) { - $property->setValue($instance, $value); - } elseif (isset($data->{$camelCaseName}) && !$strictMode) { - $property->setValue($instance, $data->{$camelCaseName}); - } elseif (isset($data->{$underscoreName}) && !$strictMode) { - $property->setValue($instance, $data->{$underscoreName}); - } - } - $reflection = $reflection->getParentClass(); - } - return $instance; - } - - /** - * @param array $data - * - * @return array[] - */ - public static function getSearchData(array $data): array - { - $search = []; - $where = []; - foreach ($data as $key => $value) { - if (!empty($value)) { - $search[] = $key; - $where[$key] = $value; - } - } - return [$search, $where]; - } - - /** - * 下划线转驼峰(首字母大写) - * - * @param $string - * - * @return string - */ - public static function underscoreToCamelCase($string): string - { - $str = str_replace(' ', '', ucwords(str_replace('_', ' ', $string))); - return ucfirst($str); - } - - private static function convertToCamelCase($propertyName): string - { - $propertyName = str_replace('_', ' ', $propertyName); - $propertyName = ucwords($propertyName); - $propertyName = str_replace(' ', '', $propertyName); - return lcfirst($propertyName); - } - - private static function convertToUnderscore($propertyName): string - { - $underscoreName = preg_replace('/(?page ?? 0; - $limit = $input->limit ?? 0; - } - $limitMax = 1000; - $defaultLimit = 10; - if ($limit > $limitMax) { - $limit = $limitMax; - } - return [(int)$page, (int)$limit, (int)$defaultLimit]; - } -} diff --git a/src/libs/utils/ProcessFlowUtils.php b/src/libs/utils/ProcessFlowUtils.php deleted file mode 100644 index ed3479b13c64f69e845c76a26e67132b5938a933..0000000000000000000000000000000000000000 --- a/src/libs/utils/ProcessFlowUtils.php +++ /dev/null @@ -1,166 +0,0 @@ -findUser($operator); - AssertHelper::notNull($api, '未知用户请核对后重试'); - $args->put(ProcessConst::USER_USER_ID, $operator); - $args->put(ProcessConst::USER_USER_NAME, $api->user_name ?? ''); - $args->put(ProcessConst::USER_REAL_NAME, $api->real_name ?? ''); - $args->put(ProcessConst::USER_DEPT_ID, $api->dept_id ?? ''); - $args->put(ProcessConst::USER_DEPT_NAME, $api->dept_name ?? ''); - $args->put(ProcessConst::USER_POST_ID, $api->post_id ?? ''); - $args->put(ProcessConst::USER_POST_NAME, $api->post_name ?? ''); - } - - /** - * 添加自动生成标题 - * - * @param string $processDefineDisplayName - * @param \ingenious\libs\utils\Dict $args - */ - public static function addAutoGenTitle(string $processDefineDisplayName, Dict &$args): void - { - // 申请人的xx流程-日期 - $format = "%s的%s-%s"; - $args->put(ProcessConst::AUTO_GEN_TITLE, sprintf($format, $args->get(ProcessConst::USER_REAL_NAME), $processDefineDisplayName, date("Y-m-d H:i"))); - } - - /** - * 将参数转换为字典 - * - * @param object|array $variable - * - * @return \ingenious\libs\utils\Dict|null - */ - public static function variableToDict(object|array $variable): ?Dict - { - $dict = new Dict(); - $dict->putAll($variable); - return $dict; - } - - /** - * 判断是否为第一个任务节点 - * - * @param \ingenious\model\ProcessModel $processModel - * @param string $taskName - * - * @return bool - */ - public static function isFistTaskName(ProcessModel $processModel, string $taskName): bool - { - $isFirst = false; - foreach ($processModel->getStart()->getOutputs() as $nodeModel) { - if (strcasecmp($nodeModel->getTo(), $taskName) === 0) { - $isFirst = true; - break; - } - } - return $isFirst; - } - - /** - * 筛选数组指定前缀list - * - * @param array $data - * @param string $prefix - * - * @return array - */ - public static function filterByPrefix(array $data, string $prefix): array - { - return array_filter($data, function ($value, $key) use ($prefix) { - return str_starts_with($key, $prefix); - }, ARRAY_FILTER_USE_BOTH); - } - - /** - * @param object $data - * @param string $prefix - * - * @return object - */ - public static function filterObjectByPrefix(object $data, string $prefix): object - { - $result = []; - foreach (get_object_vars($data) as $key => $value) { - if (str_starts_with($key, $prefix)) { - $result[$key] = $value; - } - } - return (object)$result; - } - - /** - * 解析日期 - * - * @param string|int $expireTime - * @param \ingenious\libs\utils\Dict $args - * - * @return \DateTime|null - * @throws \Exception - */ - public static function processTime(string|int $expireTime, Dict $args): ?DateTime - { - - // 如果变量中存在,则使用变量中的时间 - if ($args->containsKey($expireTime) !== false) { - $obj = $args->get($expireTime); - if ($obj instanceof DateTime) { - return $obj; - } else if (is_int($obj)) { - return new DateTime("@$obj"); - } else if (is_string($obj)) { - return new DateTime($obj); - } - } - - if (!empty($expireTime)) { - if (str_contains($expireTime, 's')) { - return (new DateTime())->modify('+' . (int)substr($expireTime, 0, -1) . ' second'); - } else if (str_contains($expireTime, 'm')) { - return (new DateTime())->modify('+' . (int)substr($expireTime, 0, -1) . ' minute'); - } else if (str_contains($expireTime, 'h')) { - return (new DateTime())->modify('+' . (int)substr($expireTime, 0, -1) . ' hour'); - } else if (str_contains($expireTime, 'd')) { - return (new DateTime())->modify('+' . (int)substr($expireTime, 0, -1) . ' day'); - } - return new DateTime($expireTime); - } - return null; - } -} diff --git a/src/libs/utils/RedisCache.php b/src/libs/utils/RedisCache.php deleted file mode 100644 index ed57c65bdc08533bed5fc8fe38e50be79ca061f1..0000000000000000000000000000000000000000 --- a/src/libs/utils/RedisCache.php +++ /dev/null @@ -1,129 +0,0 @@ - '127.0.0.1', - 'port' => '6379', - 'password' => '', - 'expire' => 0, - 'prefix' => 'l:', - 'tag_prefix' => 'Lflow:', - 'select' => 0, - 'timeout' => 0, - ]; - - private static function connect(): Redis - { - - $list = ServiceContext::findList(ConfigurationInterface::class); - $handle = end($list); - $config = $handle->getConfig('redis', self::$config); - self::$prefix = $config['prefix'] ?? ''; - self::$defaultExpiration = $config['defaultExpiration'] ?? 0; - self::$host = $config['host']; - self::$port = $config['port']; - self::$timeout = $config['timeout'] ?? 0; - - $redis = new Redis(); - $redis->connect(self::$host, self::$port, self::$timeout); - return $redis; - } - - private static function disconnect(): void - { - self::$redis->close(); - } - - private static function serializeData($data): string - { - return serialize($data); - } - - private static function unserializeData($data) - { - return unserialize($data); - } - - public static function set($key, $value, $expiration = 0): void - { - self::$redis = self::connect(); - $key = self::$prefix . $key; - $value = self::serializeData($value); // 序列化数据 - self::$redis->set($key, $value); - if ($expiration > 0) { - self::$redis->expire($key, $expiration); - } elseif ($expiration == 0) { - self::$redis->persist($key); - } - self::disconnect(); - } - - public static function get($key): mixed - { - self::$redis = self::connect(); - $key = self::$prefix . $key; - $value = self::$redis->get($key); - $value = self::unserializeData($value); // 反序列化数据 - self::disconnect(); - return $value; - } - - public static function delete($key): bool|int|Redis - { - self::$redis = self::connect(); - $key = self::$prefix . $key; - $result = self::$redis->del($key); - self::disconnect(); - return $result; - } - - public static function flush(): bool|Redis - { - self::$redis = self::connect(); - $result = self::$redis->flushDB(); - self::disconnect(); - return $result; - } - - public static function getCached($key, $default = null, $expiration = 0, callable $callback = null) - { - $value = self::get($key); - if ($value === false) { - if ($callback !== null && is_callable($callback)) { - $value = call_user_func($callback); - self::set($key, $value, $expiration); - } else { - $value = $default; - self::set($key, $value, $expiration); - } - } - return $value; - } -} - diff --git a/src/libs/utils/ReflectUtil.php b/src/libs/utils/ReflectUtil.php deleted file mode 100644 index 8e92671680667f857480cbad167ae3813ee0f901..0000000000000000000000000000000000000000 --- a/src/libs/utils/ReflectUtil.php +++ /dev/null @@ -1,39 +0,0 @@ -newInstanceArgs($constructorArgs); - } catch (\ReflectionException $e) { - return null; - } - } - -} diff --git a/src/libs/utils/Str.php b/src/libs/utils/Str.php deleted file mode 100644 index 473883dcc9ac8843b3d2422b47c7bf53af6c738d..0000000000000000000000000000000000000000 --- a/src/libs/utils/Str.php +++ /dev/null @@ -1,236 +0,0 @@ - 10) { - $chars = $type == 1 ? str_repeat($chars, $length) : str_repeat($chars, 5); - } - if ($type != 4) { - $chars = str_shuffle($chars); - $str = substr($chars, 0, $length); - } else { - for ($i = 0; $i < $length; $i++) { - $str .= mb_substr($chars, floor(mt_rand(0, mb_strlen($chars, 'utf-8') - 1)), 1); - } - } - return $str; - } - - /** - * 字符串转小写 - * - * @param string $value - * @return string - */ - public static function lower(string $value): string - { - return mb_strtolower($value, 'UTF-8'); - } - - /** - * 字符串转大写 - * - * @param string $value - * @return string - */ - public static function upper(string $value): string - { - return mb_strtoupper($value, 'UTF-8'); - } - - /** - * 获取字符串的长度 - * - * @param string $value - * @return int - */ - public static function length(string $value): int - { - return mb_strlen($value); - } - - /** - * 截取字符串 - * - * @param string $string - * @param int $start - * @param int|null $length - * @return string - */ - public static function substr(string $string, int $start, int $length = null): string - { - return mb_substr($string, $start, $length, 'UTF-8'); - } - - /** - * 驼峰转下划线 - * - * @param string $value - * @param string $delimiter - * @return string - */ - public static function snake(string $value, string $delimiter = '_'): string - { - $key = $value; - - if (isset(static::$snakeCache[$key][$delimiter])) { - return static::$snakeCache[$key][$delimiter]; - } - - if (!ctype_lower($value)) { - $value = preg_replace('/\s+/u', '', ucwords($value)); - - $value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value)); - } - - return static::$snakeCache[$key][$delimiter] = $value; - } - - /** - * 下划线转驼峰(首字母小写) - * - * @param string $value - * @return string - */ - public static function camel(string $value): string - { - if (isset(static::$camelCache[$value])) { - return static::$camelCache[$value]; - } - - return static::$camelCache[$value] = lcfirst(static::studly($value)); - } - - /** - * 下划线转驼峰(首字母大写) - * - * @param string $value - * @return string - */ - public static function studly(string $value): string - { - $key = $value; - - if (isset(static::$studlyCache[$key])) { - return static::$studlyCache[$key]; - } - - $value = ucwords(str_replace(['-', '_'], ' ', $value)); - - return static::$studlyCache[$key] = str_replace(' ', '', $value); - } - - /** - * 转为首字母大写的标题格式 - * - * @param string $value - * @return string - */ - public static function title(string $value): string - { - return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8'); - } -} diff --git a/src/libs/utils/StringBuilder.php b/src/libs/utils/StringBuilder.php deleted file mode 100644 index 0a54a351e176411619bb7a4b767db06599158b1b..0000000000000000000000000000000000000000 --- a/src/libs/utils/StringBuilder.php +++ /dev/null @@ -1,54 +0,0 @@ -string = ''; // 使用空格初始化字符串 - } - - public function append($value): static - { - $this->string .= $value; - return $this; // 允许链式调用 - } - - public function toString(): string - { - return $this->string; - } - - public function toArray(): array - { - $length = strlen($this->string); - if ($length > 0 && $this->string[$length - 1] === ',') { - return explode(',', substr($this->string, 0, $length - 1)); - } - return []; - - } - - function removeTrailingComma(): static - { - $length = strlen($this->string); - if ($length > 0 && $this->string[$length - 1] === ',') { - $this->string = substr($this->string, 0, $length - 1); - } - return $this; - } -} diff --git a/src/libs/utils/StringHelper.php b/src/libs/utils/StringHelper.php deleted file mode 100644 index e2ca410353ec76766e841514ff01256a558c32c7..0000000000000000000000000000000000000000 --- a/src/libs/utils/StringHelper.php +++ /dev/null @@ -1,125 +0,0 @@ -handle($execution); - } - -} diff --git a/src/model/CustomModel.php b/src/model/CustomModel.php deleted file mode 100644 index 0a30e58fea4e4a867e5146b7cd46e71050da1659..0000000000000000000000000000000000000000 --- a/src/model/CustomModel.php +++ /dev/null @@ -1,78 +0,0 @@ -clazz = $clazz; - $this->methodName = $methodName; - $this->args = $args; - $this->var = $var; - } - - public function exec(array $execArgs) { - if ($this->invokeObject == null) { - $this->invokeObject = new $this->clazz(); - } - - if ($this->invokeObject instanceof IHandler) { - $handler = $this->invokeObject; - $handler->handle($execArgs); - } else { - $objects = $this->getArgs($execArgs, $this->args); - $paramTypes = array_map(function($obj) { return get_class($obj); }, $objects); - $method = self::getMethod($this->invokeObject, $this->methodName, $paramTypes); - - if ($method == null) { - throw new LFlowException("无法找到方法名称: " . $this->methodName); - } - - $returnValue = call_user_func_array(array($this->invokeObject, $this->methodName), $objects); - - if ($this->var != null) { - $execArgs[$this->var] = $returnValue; - } - } - // 这里可以调用其他服务或方法处理历史记录和过渡等逻辑 - } - - private function getArgs(array $execArgs, string $args) { - if (empty($args)) { - return []; - } - $argArray = explode(",", $args); - $objects = []; - foreach ($argArray as $arg) { - if (isset($execArgs[$arg])) { - $objects[] = $execArgs[$arg]; - } else { - throw new Exception("参数缺失: " . $arg); - } - } - return $objects; - } -} diff --git a/src/model/DecisionModel.php b/src/model/DecisionModel.php deleted file mode 100644 index 9eaa07265b836f42ee482924662d529b8e7bf106..0000000000000000000000000000000000000000 --- a/src/model/DecisionModel.php +++ /dev/null @@ -1,68 +0,0 @@ -expr) && !empty($this->expr)) { - $obj = ExpressionUtil::eval($this->expr, $execution->getArgs()); - $nextNodeName = (string)$obj; - } else if (isset($this->handleClass) && !empty($this->handleClass)) { - $decisionHandler = ServiceContext::find($this->handleClass); - $nextNodeName = $decisionHandler->decide($execution); - } - - //边线表达式处理 - foreach ($this->outputs as $transitionModel) { - if ($transitionModel->getExpr() !== null && (bool)ExpressionUtil::eval($transitionModel->getExpr(), $execution->getArgs())) { - // 决策节点输出边存在表达式,则使用输出边的表达式,true则执行 - $isFound = true; - $transitionModel->setEnabled(true); - $transitionModel->execute($execution); - } else if ($transitionModel->getTo() === $nextNodeName) { - // 找到对应的下一个节点 - $isFound = true; - $transitionModel->setEnabled(true); - $transitionModel->execute($execution); - } - } - - if (!$isFound) { - // 找不到下一个可执行路线 - throw new LFlowException('Not found next node', LfErrEnum::NOT_FOUND_NEXT_NODE[1]); - } - } -} diff --git a/src/model/EndModel.php b/src/model/EndModel.php deleted file mode 100644 index d36249f4d8ee26d3b7a2cbb40c335ee636080d92..0000000000000000000000000000000000000000 --- a/src/model/EndModel.php +++ /dev/null @@ -1,34 +0,0 @@ -getProcessInstanceId() ?? ''; - Logger::debug('endModel:' . ' 执行流程实例ID=' . $sourceId . '节点=' . $this->getName() ?? ''); - // 执行结束节点自定义执行逻辑 - $this->fire(new EndProcessHandler($this), $execution); - } - -} diff --git a/src/model/ForkModel.php b/src/model/ForkModel.php deleted file mode 100644 index f609413cacedbd1d795ae3ab4f992aa2d7613390..0000000000000000000000000000000000000000 --- a/src/model/ForkModel.php +++ /dev/null @@ -1,34 +0,0 @@ -runOutTransition($execution); - } -} diff --git a/src/model/JoinModel.php b/src/model/JoinModel.php deleted file mode 100644 index 1b3262e7b0f1bd384b307d94c22755511ba92a06..0000000000000000000000000000000000000000 --- a/src/model/JoinModel.php +++ /dev/null @@ -1,39 +0,0 @@ -fire(new MergeBranchHandler($this), $execution); - if ($execution->isMerged()) { - $this->runOutTransition($execution); - } - } - -} diff --git a/src/model/NodeModel.php b/src/model/NodeModel.php deleted file mode 100644 index 844a73b50414bdd7034eb7ca9e7b76dcee38e1ca..0000000000000000000000000000000000000000 --- a/src/model/NodeModel.php +++ /dev/null @@ -1,222 +0,0 @@ -setNodeModel($this); - // 1. 调用前置拦截器 - $this->execPreInterceptors($execution); - // 2. 调用子类的exec方法 - $this->exec($execution); - // 3. 调用后置拦截器 - $this->execPostInterceptors($execution); - } - - /** - * 执行输出边 - * - * @param \ingenious\core\Execution $execution - */ - protected function runOutTransition(Execution $execution): void - { - foreach ($this->outputs as $Transition) { - $Transition->setEnabled(true); - $Transition->execute($execution); - } - } - - /** - * 执行节点前置拦截器 - * - * @param \ingenious\core\Execution $execution - * - * @throws \ReflectionException - */ - private function execPreInterceptors(Execution $execution): void - { - if (empty($this->preInterceptors)) { - $this->preInterceptors = $execution->getProcessModel()->getPreInterceptors(); - } - $this->execInterceptors($this->preInterceptors, $execution); - } - - /** - * 执行后置拦截器 - * - * @param \ingenious\core\Execution $execution - */ - private function execPostInterceptors(Execution $execution): void - { - if (empty($this->postInterceptors)) { - $this->postInterceptors = $execution->getProcessModel()->getPostInterceptors(); - } - $this->execInterceptors($this->postInterceptors, $execution); - } - - /** - * 执行节点拦截器 - * - * @param string $interceptors - * @param \ingenious\core\Execution $execution - * - * @throws \ReflectionException - */ - private function execInterceptors(string $interceptors, Execution $execution) - { - if (empty($interceptors)) { - return; - } - // 存在多个,英文逗号分割 - $interceptorArr = explode(',', $interceptors); - try { - foreach ($interceptorArr as $interceptor) { - $newInstance = ReflectUtil::newInstance($interceptor); - if (!empty($newInstance)) { - $newInstance->intercept($execution); - } - } - } catch (LFlowException $e) { - Logger:: error("拦截器执行失败=" . json_encode($e->getMessage())); - throw new LFlowException($e->getMessage()); - } - } - - public function getNextModels(object $clazz): array - { - //记录已递归项,防止死循环 - $temp = []; - $models = []; - foreach ($this->getOutputs() as $tm) { - $this->addNextModels($models, $tm, $clazz, $temp); - } - return $models; - } - - protected function addNextModels(array &$models, TransitionModel $tm, NodeModel|string $clazz, array &$temp): void - { - if (isset($temp[$tm->getTo()])) { - return; - } - // 检查 clazz 参数的类型 - if (is_string($clazz)) { - // clazz 是字符串,使用反射来创建类的实例 - try { - $reflection = new ReflectionClass($clazz); - $clazz = $reflection->newInstance(); - } catch (\ReflectionException $e) { - throw new LFlowException($clazz . '未注册服务'); - } - } - if (is_a($tm->getTarget(), get_class($clazz))) { - $models[] = $tm->getTarget(); - } else { - foreach ($tm->getTarget()->getOutputs() as $tm2) { - $temp[$tm->getTo()] = $tm->getTarget(); - $this->addNextModels($models, $tm2, $clazz, $temp); - } - } - } - - /** - * * 根据父节点模型、当前节点模型判断是否可退回。可退回条件: - * 1、满足中间无fork、join、subprocess模型 - * 2、满足父节点模型如果为任务模型时,参与类型为any - * - * @param \ingenious\model\NodeModel $current - * @param \ingenious\model\NodeModel $parent - * - * @return bool - */ - public static function canRejected(NodeModel $current, NodeModel $parent): bool - { - $result = false; - foreach ($current->getInputs() as $tm) { - $source = $tm->getSource(); - if ($source === $parent) { - return true; - } - if ($source instanceof ForkModel || - $source instanceof JoinModel || - // $source instanceof SubProcessModel || - $source instanceof StartModel) { - continue; - } - $result = $result || canRejected($source, $parent); - } - return $result; - } -} diff --git a/src/model/ProcessModel.php b/src/model/ProcessModel.php deleted file mode 100644 index 8088f3dd7abbfe5abbe45bbc856377686fd01bb5..0000000000000000000000000000000000000000 --- a/src/model/ProcessModel.php +++ /dev/null @@ -1,205 +0,0 @@ -nodes as $node) { - if ($node instanceof StartModel) { - $startModel = $node; - break; - } - } - return $startModel; - } - - /** - * 获取process定义的指定节点名称的节点模型 - * - * @param string $nodeName - * - * @return \ingenious\model\NodeModel|null - */ - public function getNode(string $nodeName): ?NodeModel - { - foreach ($this->nodes as $node) { - if (StringHelper::equalsIgnoreCase($node->getName(), $nodeName)) { - return $node; - } - } - return null; - } - - /** - * 获取下一个任务节点模型集合 - * - * @param string $nodeName - * - * @return array - */ - public function getNextTaskModels(string $nodeName): array - { - $res = []; - $nodeModel = $this->getNode($nodeName); - if (empty($nodeModel)) return $res; - - // 获取所有输出边的目标节点 - $nextNodeModelList = array_map(function ($item) { - return $item->getTarget(); - }, $nodeModel->getOutputs()); - - foreach ($nextNodeModelList as $item) { - if ($item instanceof TaskModel) { - $res[] = $item; - } - } - - if (empty($res)) { - // 如果下一个节点不存在任务节点,递归往下找 - foreach ($nextNodeModelList as $item) { - $taskModelList = $this->getNextTaskModels($item->getName()); - $res = array_merge($res, $taskModelList); - } - } - return $res; - } - - /** - * 获取下一个任务节点的候选人 - * - * @param string $nodeName - * - * @return array - */ - public function getNextTaskModelCandidates(string $nodeName): array - { - $res = []; - $nextTaskModels = $this->getNextTaskModels($nodeName); - foreach ($nextTaskModels as $item) { - $res = array_merge($res, $this->getCandidates($item)); - } - return $res; - } - - /** - * 根据任务模型获取候选人 - * - * @param \ingenious\model\TaskModel $taskModel - * - * @return array - */ - public function getCandidates(TaskModel $taskModel): array - { - $res = []; - // 从上下文中查找候选人处理人 - $handlerList = ServiceContext::findList(CandidateHandler::class); - foreach ($handlerList as $handler) { - // 通过候选从处理类获取候选人集合 - $candidateList = $handler->handle($taskModel); - if (!empty($candidateList)) { - $res = array_merge($res, $candidateList); - } - } - // 通过候选人处理类获取筛选人 - $candidateHandler = $taskModel->getCandidateHandler(); - if (!empty($candidateHandler)) { - $candidateHandlerClass = ReflectUtil::newInstance($candidateHandler); - $candidateList = $candidateHandlerClass->handle($taskModel); - if (!empty($candidateList)) { - $res = array_merge($res, $candidateList); - } - } - // 去重 - $res = array_unique($res, SORT_REGULAR); - return array_values($res); - } - - /** - * 根据指定的节点类型返回流程定义中所有模型对象 - * - * @param object|string $clazz - * - * @return array - * @throws \ReflectionException - */ - public function getModels(object|string $clazz): array - { - // 检查 clazz 参数的类型 - if (is_string($clazz)) { - // clazz 是字符串,使用反射来创建类的实例 - $reflection = new ReflectionClass($clazz); - $clazz = $reflection->newInstance(); - } - - if (!$clazz instanceof NodeModel) { - throw new LFlowException('The provided clazz must be a string representing a class name or an instance of NodeMode.'); - } - $models = []; - $this->buildModels($models, $this->getStart()->getNextModels($clazz), $clazz); - return $models; - } - - private function buildModels(array &$models, array $nextModels, object $clazz): void - { - foreach ($nextModels as $nextModel) { - $models[] = $nextModel; - } - } -} diff --git a/src/model/StartModel.php b/src/model/StartModel.php deleted file mode 100644 index 02cb015d72804ec267c42c4cc0d982007db2fe14..0000000000000000000000000000000000000000 --- a/src/model/StartModel.php +++ /dev/null @@ -1,46 +0,0 @@ -getProcessInstanceId(); - Logger::debug('starModel:' . ' 执行流程实例ID=' . $sourceId . '节点=' . $this->getName() ?? ''); - - //执行开始节点事件 - ProcessEventService::publishNotification(ProcessEventTypeEnum::PROCESS_INSTANCE_START[0], $execution->getProcessInstanceId()); - $this->runOutTransition($execution); - } - -} diff --git a/src/model/SubProcessModel.php b/src/model/SubProcessModel.php deleted file mode 100644 index 6edda893e58cfad553f010d0dd9831169ea849a8..0000000000000000000000000000000000000000 --- a/src/model/SubProcessModel.php +++ /dev/null @@ -1,39 +0,0 @@ -runOutTransition($execution); - } - -} diff --git a/src/model/TaskModel.php b/src/model/TaskModel.php deleted file mode 100644 index 232be7e4136ec2c74977f7d4f808f7d3e547887e..0000000000000000000000000000000000000000 --- a/src/model/TaskModel.php +++ /dev/null @@ -1,82 +0,0 @@ -getProcessInstanceId() ?? ''; - Logger::debug('taskModel:' . ' 执行流程实例ID=' . $sourceId . '节点=' . $this->getName() ?? ''); - if ($this->performType == null || StringHelper::equalsIgnoreCase(ProcessTaskPerformTypeEnum::COUNTERSIGN[0], $this->getPerformType()[0] ?? 0)) { - // 会签任务处理 - $this->fire(new CountersignHandler($this), $execution); - if ($execution->getMerged()) { - $this->runOutTransition($execution); - } - } else { - $this->runOutTransition($execution); - } - } -} diff --git a/src/model/TransitionModel.php b/src/model/TransitionModel.php deleted file mode 100644 index 5c37de248581d275a2f08c44ebe409d2c281e2ca..0000000000000000000000000000000000000000 --- a/src/model/TransitionModel.php +++ /dev/null @@ -1,60 +0,0 @@ -enabled) return; - if ($this->target instanceof TaskModel) { - // 创建阻塞任务 - $this->fire(new CreateTaskHandler($this->target), $execution); - } else if ($this->target instanceof SubProcessModel) { - // 如果为子流程,则启动子流程 - $this->fire(new StartSubProcessHandler($this->target), $execution); - } else { - $this->target->execute($execution); - } - } -} diff --git a/src/model/logicflow/LfEdge.php b/src/model/logicflow/LfEdge.php deleted file mode 100644 index 715d792f3c63cb25db4e2eae9b32c9630ffd89c2..0000000000000000000000000000000000000000 --- a/src/model/logicflow/LfEdge.php +++ /dev/null @@ -1,32 +0,0 @@ -nodeModel = $this->newModel(); - - // 解析基本信息 - $this->nodeModel->setName($lfNode->getId()); - - $nodeType = StringHelper::substringAfterColon($lfNode->getType()); - //针对部分节点添加节点显示名称 - if (in_array($nodeType, ['start', 'task', 'custom', 'end'])) { - $textData = $lfNode->getText() !== null && !empty($lfNode->getText()) ? $lfNode->getText() : (object)[]; - $textDict = ProcessFlowUtils::variableToDict($textData); - if (!empty($textDict) && $textDict instanceof Dict) { - $this->nodeModel->setDisplayName($textDict->get(NodeParser::TEXT_VALUE_KEY, '')); - } - } - - $properties = $lfNode->getProperties(); - // 解析布局属性 - $x = $lfNode->getX(); - $y = $lfNode->getY(); - $w = !empty($properties->get(NodeParser::WIDTH_KEY)) ? $properties->get(NodeParser::WIDTH_KEY) : 0; - $h = !empty($properties->get(NodeParser::HEIGHT_KEY)) ? $properties->get(NodeParser::HEIGHT_KEY) : 0; - $this->nodeModel->setLayout(sprintf("%s,%s;%s,%s", $x, $y, $w, $h)); - // 解析拦截器 - $this->nodeModel->setPreInterceptors($properties->get(NodeParser::PRE_INTERCEPTORS_KEY)); - $this->nodeModel->setPostInterceptors($properties->get(NodeParser::POST_INTERCEPTORS_KEY)); - // 解析输出边 - $nodeEdges = $this->getEdgeBySourceNodeId($lfNode->getId(), $edges); - foreach ($nodeEdges as $edge) { - $transitionModel = new TransitionModel(); - $transitionModel->setName($edge->getId()); - $transitionModel->setTo($edge->getTargetNodeId()); - $transitionModel->setSource($this->nodeModel); - if (!empty($edge->getProperties())) { - //边表输出正则表达式 - $transitionModel->setExpr($edge->getProperties()->get(NodeParser::EXPR_KEY)); - } - if (!empty($edge->getPointsList())) { - // x1,y1;x2,y2;x3,y3…… - $pointsList = $edge->getPointsList(); - $gValues = []; - foreach ($pointsList as $point) { - $gValues[] = $point->x . "," . $point->y; - } - $transitionModel->setG(implode(";", $gValues)); - } else { - if (!empty($edge->getStartPoint()) && !empty($edge->getEndPoint())) { - $startPointX = $edge->getStartPoint()->getX(); - $startPointY = $edge->getStartPoint()->getY(); - $endPointX = $edge->getEndPoint()->getX(); - $endPointY = $edge->getEndPoint()->getY(); - $transitionModel->setG(sprintf("%s,%s;%s,%s", $startPointX, $startPointY, $endPointX, $endPointY)); - } - } - $output = $this->nodeModel->getOutputs(); - $output[] = $transitionModel; - $this->nodeModel->setOutputs($output); - } - // 调用子类特定解析方法 - $this->parseNode($lfNode); - } - - /** - * 子类实现此类完成特定解析 - * - * @param \ingenious\model\logicflow\LfNode $lfNode - */ - abstract function parseNode(LfNode $lfNode): void; - - /** - * 由子类各自创建节点模型对象 - * - * @return \ingenious\model\NodeModel - */ - abstract function newModel(): NodeModel; - - public function getModel(): NodeModel - { - return $this->nodeModel; - } - - /** - * 获取节点输入 - * - * @param $targetNodeId - * @param $edges - * - * @return array - */ - private function getEdgeByTargetNodeId($targetNodeId, $edges): array - { - return array_filter($edges, function ($edge) use ($targetNodeId) { - return $edge->getTargetNodeId() === $targetNodeId; - }); - } - - /** - * 获取节点输出 - * - * @param $sourceNodeId - * @param $edges - * - * @return array - */ - private function getEdgeBySourceNodeId($sourceNodeId, $edges): array - { - return array_filter($edges, function ($edge) use ($sourceNodeId) { - return $edge->getSourceNodeId() === $sourceNodeId; - }); - } - -} diff --git a/src/parser/ModelParser.php b/src/parser/ModelParser.php deleted file mode 100644 index 9b6b6fbd2f83218507be9af0cbfc659ae0cda66d..0000000000000000000000000000000000000000 --- a/src/parser/ModelParser.php +++ /dev/null @@ -1,113 +0,0 @@ -getNodes() as $node) { - $properties = new Dict(); - $properties->putAll($node->properties ?? (object)[]); - $node->properties = $properties; - $nodes[] = ModelUtils::jsonObjToLfModel($node, LfNode::class);; - } - - foreach ($lfModel->getEdges() as $edge) { - $properties = new Dict(); - $properties->putAll($edge->properties ?? (object)[]); - $edge->properties = $properties; - $edges[] = ModelUtils::jsonObjToLfModel($edge, LfEdge::class); - } - - if (empty($nodes) || empty($edges)) { - return $processModel; - } - // 流程定义基本信息 - $processModel->setName($lfModel->getName()); - $processModel->setDisplayName($lfModel->getDisplayName()); - $processModel->setType($lfModel->getType()); - $processModel->setInstanceUrl($lfModel->getInstanceUrl()); - $processModel->setExpireTime($lfModel->getExpireTime()); - $processModel->setInstanceNoClass($lfModel->getInstanceNoClass()); - $processModel->setPostInterceptors($lfModel->getPostInterceptors()); - $processModel->setPreInterceptors($lfModel->getPreInterceptors()); - // 流程节点信息 - foreach ($nodes as $node) { - $type = str_replace(NodeParser::NODE_NAME_PREFIX, "", $node->getType()); - $nodeParser = ServiceContext::findByName($type, NodeParser::class); - if ($nodeParser != null) { - $nodeParser->parse($node, $edges); - $nodeModel = $nodeParser->getModel() ?? []; - $nodeAppend = $processModel->getNodes(); - //追加新的任务nodes - $nodeAppend[] = $nodeParser->getModel(); - $processModel->setNodes($nodeAppend); - //如果是Task任务节点追加到tasks list - if ($nodeModel instanceof TaskModel) { - $tasksAppend = $processModel->getTasks() ?? []; - $tasksAppend[] = $nodeModel; - $processModel->setTasks($tasksAppend); - } - } - } - // 循环节点模型,构造输入边、输出边的source、target - foreach ($processModel->getNodes() as $node) { - foreach ($node->getOutputs() as $transition) { - $to = $transition->getTo(); - foreach ($processModel->getNodes() as $node2) { - if (strcasecmp($to, $node2->getName()) === 0) { - $inputsAppend = $node2->getInputs() ?? []; - $inputsAppend[] = $transition; - $node2->setInputs($inputsAppend); - $transition->setTarget($node2); - } - } - } - } - return $processModel; - } -} diff --git a/src/parser/NodeParser.php b/src/parser/NodeParser.php deleted file mode 100644 index 345b51ba37b2dc47cae24c9d39d7cf391059cb1f..0000000000000000000000000000000000000000 --- a/src/parser/NodeParser.php +++ /dev/null @@ -1,65 +0,0 @@ -nodeModel; // 假设 nodeModel 是类的一个属性 - $properties = $lfNode->getProperties(); // 假设 getProperties 是 LfNode 类的一个方法 - //自定义方法如果有参数进行设置 - $model->setClazz($properties->get(NodeParser::CLASS_KEY)); // 假设 getStr 是 Properties 类的一个方法 - $model->setMethodName($properties->get(NodeParser::METHOD_NAME_KEY)); - $model->setArgs($properties->get(NodeParser::ARGS_KEY)); - $model->setVar($properties->get(NodeParser::RETURN_VAL_KEY, ProcessConst::CUSTOM_RETURN_VAL)); - - } - - public function newModel(): NodeModel - { - return new CustomModel(); - - } -} diff --git a/src/parser/handler/DecisionParser.php b/src/parser/handler/DecisionParser.php deleted file mode 100644 index 710a16f2da7734af581acbc7587a612a3f5a3aa1..0000000000000000000000000000000000000000 --- a/src/parser/handler/DecisionParser.php +++ /dev/null @@ -1,37 +0,0 @@ -nodeModel; // 假设 nodeModel 是类的一个属性 - $properties = $lfNode->getProperties(); // 假设 getProperties 是 LfNode 类的一个方法 - $model->setExpr($properties->get(NodeParser::EXPR_KEY)); - $model->setHandleClass($properties->get(NodeParser::HANDLE_CLASS_KEY)); - } - - public function newModel(): NodeModel - { - return new DecisionModel(); - } - -} diff --git a/src/parser/handler/EndParser.php b/src/parser/handler/EndParser.php deleted file mode 100644 index 5c42f1448dbc43df6ca369999abef1de7ad4188f..0000000000000000000000000000000000000000 --- a/src/parser/handler/EndParser.php +++ /dev/null @@ -1,34 +0,0 @@ -nodeModel; - $properties = $lfNode->getProperties(); - if (!empty($properties)) { - $model->setForm($properties->get(NodeParser::FORM_KEY)); - $model->setAssignee($properties->get(NodeParser::ASSIGNEE_KEY)); - $model->setAssignmentHandler($properties->get(NodeParser::ASSIGNMENT_HANDLE_KEY)); - $model->setTaskType(ProcessTaskTypeEnum::codeOf($properties->get(NodeParser::TASK_TYPE_KEY), ProcessTaskTypeEnum::MAJOR)); - $model->setPerformType(ProcessTaskPerformTypeEnum::codeOf($properties->get(NodeParser::PERFORM_TYPE_KEY) ?? 0, ProcessTaskPerformTypeEnum::NORMAL)); - $model->setReminderTime($properties->get(NodeParser::REMINDER_TIME_KEY)); - $model->setReminderRepeat($properties->get(NodeParser::REMINDER_REPEAT_KEY)); - $model->setExpireTime($properties->get(NodeParser::EXPIRE_TIME_KEY)); - $model->setAutoExecute($properties->get(NodeParser::AUTH_EXECUTE_KEY)); - $model->setCallback($properties->get(NodeParser::CALLBACK_KEY)); - // 解析候选人属性 - $model->setCandidateUsers($properties->get(NodeParser::EXT_FIELD_CANDIDATE_USERS_KET)); - $model->setCandidateGroups($properties->get(NodeParser::EXT_FIELD_CANDIDATE_GROUPS_KEY)); - $model->setCandidateHandler($properties->get(NodeParser::EXT_FIELD_CANDIDATE_HANDLER_KEY)); - // 解析会签属性 - $model->setCountersignType(CountersignTypeEnum::codeOf($properties->get(NodeParser::EXT_FIELD_COUNTERSIGN_TYPE_KEY), CountersignTypeEnum::PARALLEL)); - $model->setCountersignCompletionCondition($properties->get(NodeParser::EXT_FIELD_COUNTERSIGN_COMPLETION_CONDITION_KEY)); - // 自定义扩展属性 - $field = $properties->get(NodeParser::EXT_FIELD_KEY); - if ($field != null) { - $ext = new Dict(); - $ext->putAll($field); - $model->setExt($ext); - // 解析候选人属性 - $model->setCandidateUsers($properties->get(NodeParser::EXT_FIELD_CANDIDATE_USERS_KET, $ext->get(NodeParser::EXT_FIELD_CANDIDATE_USERS_KET, ''))); - $model->setCandidateGroups($properties->get(NodeParser::EXT_FIELD_CANDIDATE_GROUPS_KEY, $ext->get(NodeParser::EXT_FIELD_CANDIDATE_GROUPS_KEY, ''))); - $model->setCandidateHandler($properties->get(NodeParser::EXT_FIELD_CANDIDATE_HANDLER_KEY, $ext->get(NodeParser::EXT_FIELD_CANDIDATE_HANDLER_KEY, ''))); - // 解析会签属性 - $model->setCountersignType(CountersignTypeEnum::codeOf($properties->get(NodeParser::EXT_FIELD_COUNTERSIGN_TYPE_KEY, $ext->get(NodeParser::EXT_FIELD_COUNTERSIGN_TYPE_KEY, '')))); - $model->setCountersignCompletionCondition($properties->get(NodeParser::EXT_FIELD_COUNTERSIGN_COMPLETION_CONDITION_KEY, $ext->get(NodeParser::EXT_FIELD_COUNTERSIGN_COMPLETION_CONDITION_KEY, ''))); - } - } - } - - public function newModel(): NodeModel - { - return new TaskModel(); - } - -} diff --git a/src/parser/handler/WfSubProcessParser.php b/src/parser/handler/WfSubProcessParser.php deleted file mode 100644 index aa2a3c93888ff52d35c5e2a90f6d74c0e279aefc..0000000000000000000000000000000000000000 --- a/src/parser/handler/WfSubProcessParser.php +++ /dev/null @@ -1,37 +0,0 @@ -nodeModel; - $properties = $lfNode->getProperties(); - $subProcessModel->setForm($properties->get(NodeParser::FORM_KEY)); - $subProcessModel->setVersion($properties->get(NodeParser::VERSION_KEY)); - } - - public function newModel(): NodeModel - { - return new SubProcessModel(); - } - -} diff --git a/src/processor/IHandler.php b/src/processor/IHandler.php deleted file mode 100644 index 67a88dc8562bb1a20a2cc816ae9d364afeb93a1b..0000000000000000000000000000000000000000 --- a/src/processor/IHandler.php +++ /dev/null @@ -1,34 +0,0 @@ -taskModel = $taskModel; - } - - public function handle(Execution $execution): void - { - $isMerged = false; - $countersignType = $this->taskModel->getExt()->get("countersign_type", "PARALLEL");//会签类型 - $countersignCompletionCondition = $this->taskModel->getExt()->get("countersign_completion_condition", "");//会签完成条件 - $isRejected = $this->taskModel->getExt()->get('countersignatureRejected', false);//会签拒绝是否驳回未实现功能 - $prefix = ProcessConst::COUNTERSIGN_VARIABLE_PREFIX . $this->taskModel->getName() . "_"; - // 会签办理人列表 - $operatorList = $execution->getArgs()->get($prefix . ProcessConst:: COUNTERSIGN_OPERATOR_LIST, []); - // 循环计数器,办理人在列表中的索引 - $loopCounter = array_search($execution->getOperator(), $operatorList); - // 追加计数器 - if ($loopCounter) { - $execution->getArgs()->put($prefix . ProcessConst:: LOOP_COUNTER, $loopCounter); - } - // 追加已完成数量 - $execution->getArgs()->put($prefix . ProcessConst:: NR_OF_COMPLETED_INSTANCES, $execution->getArgs()->get($prefix . ProcessConst:: NR_OF_COMPLETED_INSTANCES, 0) + 1); - /** - * ● 全部通过:为空 - * ● 按数量通过:#nrOfCompletedInstances==n,这里表示n人完成任务,会签结束。 - * ● 按比例通过:#nrOfCompletedInstances/nrOfInstances==n,这里表示已完成会签数与总实例数达到一定比例时,会签结束 - * ● 一票通过:#nrOfCompletedInstances==1,这里表示1人完成任务,会签结束。 - * ● 一票否决:ONE_VOTE_VETO - */ - if (StringHelper::equalsIgnoreCase('ONE_VOTE_VETO', $countersignCompletionCondition)) { - // 一票否决 - if ($execution->getArgs()->containsKey(ProcessConst::COUNTERSIGN_DISAGREE_FLAG)) { - // 存在拒绝标识,则直接通过 - $isMerged = true; - } - } else if (!empty($countersignCompletionCondition)) { - // 根据条件判断是否通过 - $dict = new Dict(); - foreach ($execution->getArgs()->getAll() as $key => $value) { - $newKey = str_replace($prefix, '', $key); - $dict->put($newKey, $value); - } - //表达式条件 - $isMerged = ExpressionUtil:: eval($countersignCompletionCondition, $dict->getAll()); - } - if (!$isMerged && StringHelper::equalsIgnoreCase(CountersignTypeEnum::SEQUENTIAL[0], $countersignType)) { - // 串行未通过,则判断是否为最后一个 - if ($loopCounter == end($operatorList)) { - $isMerged = true; - } else { - // 非最后一个,则继续创建会签任务 - $execution->getEngine()->processTaskService()->createCountersignTask($this->taskModel, $execution); - } - } - - - if (!$isMerged && StringHelper::equalsIgnoreCase(CountersignTypeEnum::PARALLEL[0], $countersignType)) { - // 是否所有会签任务已完成 - $isMerged = $execution->getEngine()->processTaskService()->getDoingTaskList($execution->getProcessInstanceId(), ''); - if (!$isMerged) { - // 未通过,更新已完成实例数量 - $addVariable = new Dict (); - $addVariable->put($prefix . ProcessConst:: NR_OF_COMPLETED_INSTANCES, $execution->getArgs()->get($prefix . ProcessConst:: NR_OF_COMPLETED_INSTANCES)); - $execution->getEngine()->processInstanceService()->addVariable($execution->getProcessInstanceId(), $addVariable); - } - } - if ($isMerged) { - //筛选会签变量key - $keys = []; - foreach ($execution->getArgs()->getAll() as $key => $value) { - if (str_starts_with($key, $prefix)) { - // 如果是,则添加到 $keys 数组中 - $keys[] = $key; - } - } - // 如果可以合并,则把流程实例中的会签参数清空 - $execution->getEngine()->processInstanceService()->removeVariable($execution->getProcessInstanceId(), $keys); - // 如果为并行会签,需将其他会签任务设置为废弃 - if (StringHelper::equalsIgnoreCase(CountersignTypeEnum::PARALLEL[0], $countersignType)) { - $t = $execution->getEngine()->processTaskService()->getDoingTaskList($execution->getProcessInstanceId(), $this->taskModel->getName()); - foreach ($t as $value) { - $execution->getEngine()->processTaskService()->abandonProcessTask($t->getData('id'), ProcessConst::AUTO_ID, $execution->getArgs()); - } - } - } - $execution->setMerged($isMerged); - } -} diff --git a/src/processor/handler/CreateTaskHandler.php b/src/processor/handler/CreateTaskHandler.php deleted file mode 100644 index ff3a46da3f56f78547b397b6b041b807f3cc7a00..0000000000000000000000000000000000000000 --- a/src/processor/handler/CreateTaskHandler.php +++ /dev/null @@ -1,72 +0,0 @@ -taskModel = $taskModel; - } - - /** - * handle - * - * @param \ingenious\core\Execution $execution - */ - public function handle(Execution $execution): void - { - $processTaskList = []; - // 根据任务类型创建任务 - if (strcasecmp((string)ProcessTaskPerformTypeEnum::COUNTERSIGN[0], (string)$this->taskModel->getPerformType()[0] ?? '') === 0) { - $processTaskList = $execution->getEngine()->processTaskService()->createCountersignTask($this->taskModel, $execution); - //会签任务 - } else { - //创建普通任务 - $processTaskList = $execution->getEngine()->processTaskService()->createTask($this->taskModel, $execution); - } - // 将任务添加到执行对象中 - $execution->addTasks($processTaskList); - - // 从服务容器中获取拦截器并执行 - $interceptors = ServiceContext::findAll(ProcessNodeInterceptor::class); - foreach ($interceptors as $interceptor) { - $interceptor->intercept($execution); - } - - // 发布流程任务开始事件 - foreach ($processTaskList as $processTask) { - ProcessEventService::publishNotification(ProcessEventTypeEnum::PROCESS_TASK_START[0], $processTask ->getData('id')); - } - } -} diff --git a/src/processor/handler/EndProcessHandler.php b/src/processor/handler/EndProcessHandler.php deleted file mode 100644 index 0538a1989ea4717265d6bd436e72697e066eecac..0000000000000000000000000000000000000000 --- a/src/processor/handler/EndProcessHandler.php +++ /dev/null @@ -1,62 +0,0 @@ -endModel = $endModel; - } - - public function handle(Execution $execution): void - { - // 1.把实例任务修改为完成 - $execution->getEngine()->processInstanceService()->finishProcessInstance($execution->getProcessInstanceId()); - // 2.发布流程结束事件 - ProcessEventService::publishNotification(ProcessEventTypeEnum::PROCESS_INSTANCE_END[0], $execution->getProcessInstanceId()); - // 3.如果子流程存在父流程实例,则执行父流程的子流程节点模型方法 - $processInstance = $execution->getProcessInstance(); - if (!empty($processInstance->getData('parent_id'))) { - $parentInstance = $execution->getEngine()->processInstanceService()->getById($processInstance->getData('parent_id')); - if ($parentInstance == null) return; - $pm = $execution->getEngine()->processDefineService()->getProcessModel($parentInstance->getData('process_define_id')); - if ($pm == null) return; - $spm = $pm->getNode($processInstance->getData('parent_node_name')); - $newExecution = new Execution(); - $newExecution->setEngine($execution->getEngine()); - $newExecution->setProcessModel($pm); - $newExecution->setProcessInstance($parentInstance); - $newExecution->setProcessInstanceId($parentInstance->getData('id')); - $newExecution->setArgs($execution->getArgs()); - $spm->execute($newExecution); - $execution->addTasks($newExecution->getProcessTaskList()); - } - } -} diff --git a/src/processor/handler/MergeBranchHandler.php b/src/processor/handler/MergeBranchHandler.php deleted file mode 100644 index 33cfb942b145ee5d340051ac81fce5f0fa35cc0c..0000000000000000000000000000000000000000 --- a/src/processor/handler/MergeBranchHandler.php +++ /dev/null @@ -1,102 +0,0 @@ -joinModel = $joinModel; - } - - public function handle(Execution $execution): void - { - $engine = $execution->getEngine(); - - $processTaskService = $engine->processTaskService(); - - // 判断是否存在正在执行的任务,存在则不允许合并 - $execution->setMerged(empty($processTaskService->getDoingTaskList($execution->getProcessInstanceId(), $this->findActiveNodes()))); - } - - /** - * 对join节点的所有输入变迁进行递归,查找join至fork节点的所有中间task元素 - * - * @return array - */ - public function findActiveNodes(): array - { - $buffer = new StringBuilder(); - self::findForkTaskNames($this->joinModel, $buffer); - return $buffer->toArray(); - } - - /** - * 对join节点的所有输入变迁进行递归,查找join至fork节点的所有中间task元素 - * - * @param \ingenious\model\NodeModel $node - * @param $buffer - */ - public static function findForkTaskNames(NodeModel $node, &$buffer) - { - if ($node instanceof ForkModel) { - return; // 跳过ForkModel类型的节点 - } - - $inputs = $node->getInputs(); - foreach ($inputs as $tm) { - if ($tm->getSource() instanceof TaskModel) { - $buffer->append($tm->getSource()->getName())->append(","); - } - self::findForkTaskNames($tm->getSource(), $buffer); // 递归调用 - } - } - - /** - * 判断流程是否可合并 - * - * @param string|int $processInstanceId - * @param \ingenious\model\NodeModel $nodeModel - * - * @return bool - */ - public static function isMerged(string|int $processInstanceId, NodeModel $nodeModel): bool - { - // 合并节点 - $buffer = new StringBuilder(); - MergeBranchHandler::findForkTaskNames($nodeModel, $buffer); - $taskNames = $buffer->toArray(); - $processTaskService = ServiceContext::findFirst(ProcessTaskServiceInterface::class); - $result = $processTaskService->getDoingTaskList($processInstanceId, $taskNames); - return empty($result); - } -} diff --git a/src/processor/handler/StartSubProcessHandler.php b/src/processor/handler/StartSubProcessHandler.php deleted file mode 100644 index 9b93166830e6837fc35b201a40849bdb84f3d74e..0000000000000000000000000000000000000000 --- a/src/processor/handler/StartSubProcessHandler.php +++ /dev/null @@ -1,41 +0,0 @@ -model = $model; - } - - public function handle(Execution $execution): void - { - $processDefine = $execution->getEngine()->processDefineService()->getProcessDefineByVersion($this->model->getName(), $this->model->getVersion()); - if ($processDefine == null) { - throw new LFlowException("子流程" . $this->model->getName() . "定义不存在"); - } - $parentId = $execution->getProcessInstanceId(); - $parentNodeName = $this->model->getName(); - $execution->getEngine()->startProcessInstanceById($processDefine->getData('id'), $execution->getOperator(), $execution->getArgs(), $parentId, $parentNodeName); - } -} diff --git a/src/scheduling/IScheduler.php b/src/scheduling/IScheduler.php deleted file mode 100644 index 817eb96fc5677afff8765e406d5ce2a9e827e26e..0000000000000000000000000000000000000000 --- a/src/scheduling/IScheduler.php +++ /dev/null @@ -1,44 +0,0 @@ -getEventType(), [ - ProcessEventTypeEnum::PROCESS_INSTANCE_START[0],//流程开始 - ProcessEventTypeEnum::PROCESS_TASK_START[0],//任务开始 - ])) { - // 流程实例开始事件、流程任务开始事件,添加作业到调度器 - foreach ($schedulerList as $scheduler) { - $scheduler->addJob($event->getSourceId(), - Dict::of([ - IScheduler::SOURCE_ID_KEY => $event->getSourceId(), - IScheduler::SOURCE_TYPE_KEY => $event->getEventType(), - ])); - } - } else if (in_array($event->getEventType(), [ - ProcessEventTypeEnum::PROCESS_INSTANCE_END[0], - ProcessEventTypeEnum::PROCESS_TASK_END[0], - ])) { - // 流程实例结束事件、流程任务结束事件,从调度器移除作业 - foreach ($schedulerList as $scheduler) { - $scheduler->removeJob($event->getSourceId()); - } - } - } -} diff --git a/src/service/ProcessCcInstanceService.php b/src/service/ProcessCcInstanceService.php deleted file mode 100644 index 4b8f80c5a495fa013e9b2b409e520c9b12012b1a..0000000000000000000000000000000000000000 --- a/src/service/ProcessCcInstanceService.php +++ /dev/null @@ -1,114 +0,0 @@ -id); - $processCcInstance = new ProcessCcInstance(); - ModelUtils::copyProperties((object)$param, $processCcInstance); - return $processCcInstance->save(); - } - - public function update($param): bool - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - $processCcInstance = new ProcessCcInstance(); - ModelUtils::copyProperties((object)$param, $processCcInstance); - return $processCcInstance->save(); - } - - public function findById(string $id): ProcessCcInstance - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - return $this->get($id); - } - - public function page($param): array - { - $map1 = [ - ['pci.state', '=', $param->state], - ['pci.actor_id', '=', $param->actor_id], - ]; - if (!empty($param->name)) { - $map1[] = ['pd.name', '=', $param->name]; - } - if (!empty($param->display_name)) { - $map1[] = ['pd.display_name', 'like', $param->display_name.'%']; - } - if (!empty($param->business_no)) { - $map1[] = ['pi.business_no', '=', $param->business_no]; - } - [$page, $limit] = PageParam::getPageValue($param); - $processInstance = ProcessInstance::getTableName(); - $processCcInstance = ProcessCcInstance::getTableName(); - $processDefine = ProcessDefine::getTableName(); - - $list = Db::table($processCcInstance) - ->alias('pci') - ->where($map1) - ->field('pi.*,pci.id,actor_id,pci.actor_id,pci.state as is_cc,pci.process_instance_id,pd.name,pd.display_name,pd.version') - ->join([$processInstance => 'pi'], 'pci.process_instance_id = pi.id') - ->join([$processDefine => 'pd'], 'pd.id = pi.process_define_id') - ->order('pci.create_time', 'desc') - ->page($page, $limit) - ->select() - ->toArray(); - $count = Db::table($processCcInstance) - ->alias('pci') - ->where($map1) - ->join([$processInstance => 'pi'], 'pci.process_instance_id = pi.id') - ->join([$processDefine => 'pd'], 'pd.id = pi.process_define_id') - ->count(); - - foreach ($list as $key => $value) { - $list[$key]['create_time'] = DateTimeHelper::timestampToString($value['create_time']); - $list[$key]['ext'] = json_decode($value['variable']); - if (!empty($value['variable'])) { - //提前f_前缀的表单数据 - $list[$key]['form_data'] = ProcessFlowUtils::filterObjectByPrefix(json_decode($value['variable'], false), 'f_'); - } - } - return compact('list', 'count'); - } -} diff --git a/src/service/ProcessDefineFavoriteService.php b/src/service/ProcessDefineFavoriteService.php deleted file mode 100644 index 3a37fb45c306e8dae4fbaa36413525ba89eb731e..0000000000000000000000000000000000000000 --- a/src/service/ProcessDefineFavoriteService.php +++ /dev/null @@ -1,102 +0,0 @@ -id); - $processDefineFavorite = new ProcessDefineFavorite(); - ModelUtils::copyProperties($param, $processDefineFavorite); - return $processDefineFavorite->save(); - } - - public function del(string|array|int $id): bool - { - $processType = new ProcessDefineFavorite(); - AssertHelper::notNull($id, '参数ID不能为空'); - $map1 = []; - if (is_array($id)) { - $map1[] = ['id', 'in', $id]; - } else { - $map1[] = ['id', '=', $id]; - } - return $processType->where($map1)->delete(); - } - - public function update(object $param): bool - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - $processTaskActor = $this->get($param->id); - ModelUtils::copyProperties($param, $processTaskActor); - return $processTaskActor->save(); - } - - public function page(object $param): array - { - $map1 = [['pdf.favorite', '=', 1], ['pd.state', '=', 1], ['is_del', '=', 0]]; - if (!empty($param->user_id)) { - $map1[] = ['pdf.user_id', '=', $param->user_id]; - } - if (!empty($param->process_instance_id)) { - $map1[] = ['pdf.process_define_id', '=', $param->process_define_id]; - } - if (!empty($param->id)) { - $map1[] = ['pdf.id', '=', $param->id]; - } - $processDefineFavoriteTable = ProcessDefineFavorite::getTableName(); - $processDefineTable = ProcessDefine::getTableName(); - [$page, $limit] = PageParam::getPageValue($param); - $list = Db::table($processDefineFavoriteTable) - ->alias('pdf') - ->where($map1) - ->field('pdf.*,pd.type_id,pd.name,pd.display_name,pd.description,pd.state,pd.content,pd.version') - ->join([$processDefineTable => 'pd'], 'pdf.process_define_id = pd.id') - ->order('pdf.create_time', 'desc'); - if ($page > 0 && $limit > 0) { - $list = $list->page($page, $limit); - } - $list = $list->select()->toArray(); - $count = Db::table($processDefineFavoriteTable) - ->alias('pdf') - ->where($map1) - ->join([$processDefineTable => 'pd'], 'pdf.process_define_id = pd.id') - ->count(); - return compact('list', 'count'); - } - - public function findById(string $id): ?ProcessDefineFavorite - { - return $this->get($id); - } -} diff --git a/src/service/ProcessDefineService.php b/src/service/ProcessDefineService.php deleted file mode 100644 index ef69aa89cdf2fde3dbb1310ba90c5d7417f44cd2..0000000000000000000000000000000000000000 --- a/src/service/ProcessDefineService.php +++ /dev/null @@ -1,285 +0,0 @@ -id); - $processDefine = new ProcessDefine(); - ModelUtils::copyProperties($param, $processDefine); - return $processDefine->save(); - } - - public function update(object $param): bool - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - $processDefine = $this->get($param->id); - ModelUtils::copyProperties((object)$param, $processDefine); - return $processDefine->save(); - } - - public function del(string $processDefineId): bool - { - $processDefine = $this->get($processDefineId); - AssertHelper::notNull($processDefine, '删除失败找不到资源'); - return $processDefine->delete(); - } - - public function page(object $param): array - { - $where = ArrayHelper::paramsFilter($param, [ - ['name', ''], - ['display_name', ''], - ['type_id', ''], - ['state', 1], - ['version', ''], - ['is_del', 0], - ]); - [$page, $limit] = PageParam::getPageValue($param); - $list = $this->selectList($where, '*', $page, $limit, 'name desc,version desc', [], true)->toArray(); - $count = $this->count($where); - return compact('list', 'count'); - } - - public function findById(string $id): ?ProcessDefine - { - AssertHelper::notNull($id, '参数process_define_id不能为空'); - $processDefine = $this->get($id); - AssertHelper::notNull($processDefine, '流程定义不存在或被删除'); - if (!empty($processDefine->getData('content'))) { - $graph_data = $processDefine->getData('content'); - //使用表单key获取表单JSON数据 - $processDefine->set('form', (object)[]); - if (isset($graph_data->instance_url) && !empty($graph_data->instance_url)) { - $processFormService = new ProcessFormService(); - $processForm = $processFormService->findByName($graph_data->instance_url); - if (!empty($processForm)) { - $processDefine->set('form', $processForm->getData('form')); - } - } - } - return $processDefine; - } - - public function deploy($param, string $operation): string - { - // 1. json定义文件转成流程模型 - $processModel = ModelParser::parse($param); - // 2. 根据名称查询,取最新版本的流程定义记录 - $map1 = [ - 'name' => $param->name, - 'is_del' => 0, - ]; - $processDesign = new ProcessDesignService(); - $processDesignData = $processDesign->get($map1); - AssertHelper::notNull($processDesignData, '请先定义流程'); - $processDesignDataHis = $processDesignData->history()->order('create_time', 'desc')->find(); - AssertHelper::notNull($processDesignDataHis, '请先定义流程'); - $processDefine = $this->selectList($map1, '*', 0, 0, 'version', [], true)->last(); - if ($processDefine !== null) { - // 3.1 如果存在,则版本+1,并插入一条新的流程定义记录 - $processDefine->set('id', null); - $processDefine->set('version', $processDefine->version + 1); - } else { - // 3.2 如果不存在,则版本默认为1,并插入一条新的流程定义记录 - $processDefine = new ProcessDefine(); - $processDefine->set('version', 1); - } - $processDefine->set('name', $processModel->getName()); - $processDefine->set('display_name', $processModel->getDisplayName()); - $processDefine->set('type_id', $param->type_id ?? ''); - $processDefine->set('create_time', time()); - $processDefine->set('update_time', time()); - $processDefine->set('create_user', $operation); - $processDefine->set('state', ProcessDefineStateEnum::getCode(ProcessDefineStateEnum::ENABLE[1])); - $processDefine->set('content', $param); - $result = $processDefine::create($processDefine->toArray()); - return $result->getData('id'); - } - - public function redeploy(string $processDefineId, object $inputStream, string|int $operation): void - { - $processModel = ModelParser::parse($inputStream); - $processDefine = $this->get($processDefineId); - $processDefine->set('name', $processModel->getName()); - $processDefine->set('display_name', $processModel->getDisplayName()); - $processDefine->set('type_id', $param->type_id ?? ''); - $processDefine->set('update_time', time()); - $processDefine->set('update_user', $operation); - $processDefine->set('content', $inputStream); - $processDefine->save(); - } - - public function unDeploy(string $processDefineId, string|int $operation): void - { - $processDefine = $this->get($processDefineId); - $processDefine->set('state', ProcessDefineStateEnum::DISABLE[0]); - $processDefine->set('update_user', $operation); - $processDefine->save(); - } - - public function updateType(string $processDefineId, string $type, string|int $operation): void - { - AssertHelper::notEmpty($processDefineId, '参数 processDefineId 不能为空'); - $processDefine = $this->get($processDefineId); - AssertHelper::notNull($processDefineId, '流程定义不存在或被删除'); - $processDefine->type_id = $type; - $processDefine->save(); - } - - public function updateState(string $processDefineId, string|int $state, string|int $operation): void - { - AssertHelper::notEmpty($processDefineId, '参数 processDefineId 不能为空'); - $processDefine = $this->get($processDefineId); - AssertHelper::notNull($processDefineId, '流程定义不存在或被删除'); - $processDefine->state = $state; - $processDefine->save(); - } - - public function getById(string $processDefineId): ?ProcessDefine - { - AssertHelper::notEmpty($processDefineId, '参数 processDefineId 不能为空'); - return $this->get($processDefineId); - } - - public function getProcessModel(string $processDefineId): ?ProcessModel - { - AssertHelper::notEmpty($processDefineId, '参数 processDefineId 不能为空'); - //如果缓存有则使用缓存 - return RedisCache::getCached(md5($processDefineId), null, 3600, function () use ($processDefineId) { - return $this->processDefineToModel($this->get($processDefineId)); - }); - } - - public function processDefineToModel(ProcessDefine $processDefine): ?ProcessModel - { - if (empty($processDefine)) return null; - $content = $processDefine->getData('content'); - if (empty($content)) return null; - return ModelParser::parse($content); - } - - public function getDefineJsonStr(string $processDefineId): string|null - { - AssertHelper::notEmpty($processDefineId, '参数ID不能为空'); - $processDefine = $this->get($processDefineId); - if (empty($processDefine)) { - return json_encode((object)[]); - } - $content = $processDefine->getData('content'); - return json_encode(ArrayHelper::arrayToObject($content)); - } - - public function getDefineJsonObject(string $processDefineId): \stdClass|string|bool - { - AssertHelper::notEmpty($processDefineId, '参数ID不能为空'); - $processDefine = $this->get($processDefineId); - if (empty($processDefine)) { - return json_encode((object)[]); - } - $content = $processDefine->getData('content') ?? (object)[]; - return ArrayHelper::arrayToObject($content); - } - - public function upAndDown($param): void - { - if ($param->is_open === true) { - foreach (explode(',', $param->ids ?? '') as $id) { - $processDefine = (new ProcessDefine())->where(['id' => $id])->find(); - if (empty($processDefine)) { - continue; - } - $processDefine->set('state', ProcessDefineStateEnum::DISABLE[0]); - $processDefine->set('update_user', $param->operation); - $processDefine->save(); - } - } else { - foreach (explode(',', $param->ids ?? '') as $id) { - $this->unDeploy($id, $param->operation); - } - } - } - - public function getLastByName(string $name): ?ProcessDefine - { - return $this->selectList(['name' => $name, 'is_del' => 0], '*', 0, 0, 'version', [], true)->last(); - } - - public function getProcessDefineByVersion(string $name, int $version): ?ProcessDefine - { - return $this->selectList(['name' => $name, 'version' => $version, 'is_del' => 0], '*', 0, 0, '', [], true)->last(); - } - - public function favoritePage(object $param): array - { - $processDefineFavoriteService = new ProcessDefineFavoriteService(); - return $processDefineFavoriteService->page($param); - } - - public function definitionFavorite(object $param): bool - { - $processDefineFavoriteService = new ProcessDefineFavoriteService(); - AssertHelper::notNull($param->user_id, '用户ID不能为空'); - AssertHelper::notNull($param->process_define_id, '流程定义ID不能为空'); - $map1 = [ - 'user_id' => $param->user_id, - 'process_define_id' => $param->process_define_id, - ]; - $favorite = $processDefineFavoriteService->get($map1); - if ($favorite == null) { - return $processDefineFavoriteService->create($param); - } else { - if ($favorite->delete()) { - //如果是取消收藏不用再次创建了 - if (empty($param->favorite) || $param->favorite == 0 || $param->favorite == '0') { - return true; - } - return $processDefineFavoriteService->create($param); - } - } - return false; - } - - public function favoriteDel(string|int|array $param): bool - { - $processDefineFavoriteService = new ProcessDefineFavoriteService(); - return $processDefineFavoriteService->del($param); - } -} diff --git a/src/service/ProcessDesignHistoryService.php b/src/service/ProcessDesignHistoryService.php deleted file mode 100644 index 0c4f1f1cde0340a982de7a0869efd33ee8e7b323..0000000000000000000000000000000000000000 --- a/src/service/ProcessDesignHistoryService.php +++ /dev/null @@ -1,72 +0,0 @@ -id); - $processDesignFlow = new ProcessDesignHistory(); - ModelUtils::copyProperties($param, $processDesignFlow); - return $processDesignFlow->save(); - } - - public function update(object $param): bool - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - $processDefine = $this->get($param->id); - ModelUtils::copyProperties($param, $processDefine); - return $processDefine->save(); - } - - public function page(object $param): array - { - $where = ArrayHelper::paramsFilter($param, [ - ['name', ''], - ['display_name', ''], - ['is_del', '0'], - ]); - [$page, $limit] = PageParam::getPageValue($param); - $list = $this->selectList($where, '*', $page, $limit, 'create_time asc', [], true)->toArray(); - $count = $this->count($where); - return compact('list', 'count'); - } - - public function findById(string $id): ?ProcessDesignHistory - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - return $this->get($id); - } - - public function getLatestByProcessDesignId(string $processDesignId): ?ProcessDesignHistory - { - AssertHelper::notNull($processDesignId, '参数process_design_id不能为空'); - return $this->selectList(['process_design_id' => $processDesignId], '*', 0, 0, 'create_time asc', [], true)->last(); - } -} diff --git a/src/service/ProcessDesignService.php b/src/service/ProcessDesignService.php deleted file mode 100644 index 83a6ef23b53f8972ecea3acfa4b217c830ece1e6..0000000000000000000000000000000000000000 --- a/src/service/ProcessDesignService.php +++ /dev/null @@ -1,188 +0,0 @@ -id); - AssertHelper::notTrue($this->checkUniqueName(['name' => $param->name]), '唯一编码已存在,请检查name参数'); - $processDesign = new ProcessDesign(); - ModelUtils::copyProperties($param, $processDesign); - return $processDesign->save(); - - } - - /** - * update - * - * @param object $param - * - * @return bool - * @throws \ReflectionException - * @throws \think\db\exception\DataNotFoundException - * @throws \think\db\exception\DbException - * @throws \think\db\exception\ModelNotFoundException - */ - public function update(object $param): bool - { - AssertHelper::notNull($param->id ?? '', '参数异常,请检查ID参数'); - AssertHelper::notNull($param->name ?? '', '参数异常,唯一编码不能为空'); - AssertHelper::notTrue($this->checkUniqueName(['notId' => $param->id, 'name' => $param->name]), '唯一编码已存在,请检查name参数'); - $processDesign = $this->get($param->id); - AssertHelper::notNull($processDesign, '资源不存在'); - ModelUtils::copyProperties($param, $processDesign); - return $processDesign->save(); - } - - public function del(string $id): bool - { - $processDesign = $this->get($id); - if ($processDesign !== null) { - return $processDesign->deleteWithHistory(); - } - return false; - } - - public function page(object $param): array - { - $where = ArrayHelper::paramsFilter($param, [ - ['name', ''], - ['display_name', ''], - ['is_del', '0'], - ]); - [$page, $limit] = PageParam::getPageValue($param); - $list = $this->selectList($where, '*', $page, $limit, 'create_time asc', ['processType'], true); - foreach ($list as $item) { - $item->type_name = $item->processType->name ?? '顶层'; - } - $list = $list->hidden(['processType'])->toArray(); - $count = $this->count($where); - return compact('list', 'count'); - } - - public function findById(string $id): ?ProcessDesign - { - AssertHelper::notNull($id, '参数ID不能为空'); - $processDesign = $this->get($id); - if ($processDesign !== null) { - $processDesignHistory = (new ProcessDesignHistory())->where(['process_design_id' => $id])->order('create_time', 'desc')->find(); - $graph_data = $processDesignHistory->content ?? (object)[]; - $processDesign->content = $graph_data; - } - return $processDesign; - } - - public function updateDefine(object $jsonObject): bool - { - $processDesignFlow = new ProcessDesignHistory(); - $data = new \stdClass(); - $data->process_design_id = $jsonObject->{ProcessConst::PROCESS_DESIGN_ID_KEY}; - $data->create_user = $jsonObject->{ProcessConst::CREATE_USER}; - $processDesign = $this->get($data->process_design_id); - $processDesign->set('update_time', time()); - $processDesign->set('update_user', $data->create_user); - $processDesign->save(); - unset($jsonObject->{ProcessConst::CREATE_USER}); - unset($jsonObject->{ProcessConst::PROCESS_DESIGN_ID_KEY}); - $data->content = $jsonObject; - // 获取当前版本号并转换为浮点数 - $processDesignHistoryService = new ProcessDesignHistoryService(); - $newVersion = 1.0;//默认版本 - $history = $processDesignHistoryService->selectList(['process_design_id' => $data->process_design_id], 'versions', 0, 0, 'create_time asc', [], true)->last(); - if (!empty($history)) { - $currentVersion = (float)$history->getData('versions'); - $newVersion = round($currentVersion + 0.1, 1); - } - - $data->versions = $newVersion; - ModelUtils::copyProperties($data, $processDesignFlow); - return $processDesignFlow->save(); - } - - public function deploy(string $processDesignId, string|int $operation): void - { - $processDesign = $this->findById($processDesignId); - AssertHelper::notNull($processDesign, '部署失败,流程设计不存在或被删除'); - AssertHelper::notNull($processDesign, 'operation 不能为空'); - $processDesign->set('is_deployed', 1); - $processDesign->set('update_user', $operation); - if ($processDesign->save()) { - // 先更新状态,更新成功,再部署 - $processDefineService = new ProcessDefineService(); - $content = $processDesign->getData('content'); - if (!empty($content)) { - AssertHelper::notNull('instance_url', '部署失败,缺少表单信息'); - } - $processDefineService->deploy(ArrayHelper::arrayToObject($content), $operation); - } - } - - public function redeploy(string $processDesignId, string|int $operation): void - { - $processDesign = $this->findById($processDesignId); - $processDesign->set('is_deployed', 1); - $processDesign->set('update_user', $operation); - if ($processDesign->save()) { - // 先更新状态,更新成功,再部署 - $processDefineService = new ProcessDefineService(); - $processDefine = $processDefineService->selectList(['name' => $processDesign->getData('name')], '*', 0, 0, 'version', [], true)->last(); - AssertHelper::notNull($processDefine, '该流程未部署,请先部署流程'); - $content = $processDesign->getData('content'); - if (!empty($content)) { - AssertHelper::notNull('instance_url', '部署失败,缺少表单信息'); - } - $processDefineService->redeploy($processDefine->getData('id'), ArrayHelper::arrayToObject($processDesign->getData('content')), $operation); - } - } - - public function listByType(): ?ProcessType - { - - } - - private function checkUniqueName(array $where): bool - { - $result = $this->selectList($where, '*', 0, 0, '', [], true)->toArray(); - return !empty($result) ?? false; - } -} diff --git a/src/service/ProcessFormHistoryService.php b/src/service/ProcessFormHistoryService.php deleted file mode 100644 index 1acc2d51bd08299f2825b0fabee38bebb11385e2..0000000000000000000000000000000000000000 --- a/src/service/ProcessFormHistoryService.php +++ /dev/null @@ -1,73 +0,0 @@ -id); - $processFormBuilder = new ProcessDesignForm(); - ModelUtils::copyProperties($param, $processFormBuilder); - return $processFormBuilder->save(); - } - - public function update(object $param): bool - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - $processDefine = $this->get($param->id); - ModelUtils::copyProperties($param, $processDefine); - return $processDefine->save(); - } - - public function page(object $param): array - { - $where = ArrayHelper::paramsFilter($param, [ - ['name', ''], - ['display_name', ''], - ['is_del', '0'], - ]); - [$page, $limit] = PageParam::getPageValue($param); - $list = $this->selectList($where, '*', $page, $limit, 'create_time asc', [], true)->toArray(); - $count = $this->count($where); - return compact('list', 'count'); - } - - public function findById(string $id): ?ProcessFormHistory - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - return $this->get($id); - } - - public function getLatestByProcessDesignId(string $processDesignId): mixed - { - AssertHelper::notNull($processDesignId, '参数process_design_id不能为空'); - return $this->selectList(['process_design_id' => $processDesignId], '*', 0, 0, 'create_time asc', [], true)->last(); - } -} diff --git a/src/service/ProcessFormService.php b/src/service/ProcessFormService.php deleted file mode 100644 index f0b6728d90da5c77438beb9e5489708350136e7d..0000000000000000000000000000000000000000 --- a/src/service/ProcessFormService.php +++ /dev/null @@ -1,165 +0,0 @@ -id); - AssertHelper::notTrue($this->checkUniqueName(['name' => $param->name]), '唯一编码已存在,请检查name参数'); - $processDesign = new ProcessForm(); - ModelUtils::copyProperties($param, $processDesign); - return $processDesign->save(); - - } - - /** - * update - * - * @param object $param - * - * @return bool - * @throws \ReflectionException - * @throws \think\db\exception\DataNotFoundException - * @throws \think\db\exception\DbException - * @throws \think\db\exception\ModelNotFoundException - */ - public function update(object $param): bool - { - AssertHelper::notNull($param->id ?? '', '参数异常,请检查ID参数'); - AssertHelper::notNull($param->name ?? '', '参数异常,唯一编码不能为空'); - AssertHelper::notTrue($this->checkUniqueName(['notId' => $param->id, 'name' => $param->name]), '唯一编码已存在,请检查name参数'); - $processDesign = $this->get($param->id); - AssertHelper::notNull($processDesign, '资源不存在'); - ModelUtils::copyProperties($param, $processDesign); - return $processDesign->save(); - } - - public function del(string $id): bool - { - $processForm = $this->get($id); - if ($processForm != null) { - return $processForm->deleteWithHistory(); - } - return false; - } - - public function page(object $param): array - { - $where = ArrayHelper::paramsFilter($param, [ - ['name', ''], - ['display_name', ''], - ['is_del', '0'], - ]); - [$page, $limit] = PageParam::getPageValue($param); - $list = $this->selectList($where, '*', $page, $limit, 'create_time asc', ['processType'], true); - foreach ($list as $item) { - $item->type_name = $item->processType->name ?? '顶层'; - } - $list = $list->hidden(['processType'])->toArray(); - $count = $this->count($where); - return compact('list', 'count'); - } - - public function findById(string $id): ?ProcessForm - { - AssertHelper::notNull($id, '参数ID不能为空'); - $processForm = $this->get($id); - if ($processForm !== null) { - $processFormHistory = (new ProcessFormHistory())->where(['process_form_id' => $id])->order('create_time', 'desc')->find(); - $processForm->form = (object)[]; - $processForm->versions = (float)1.0; - if ($processFormHistory != null) { - $processForm->form = $processFormHistory->getData('content'); - $processForm->versions = $processFormHistory->getData('versions'); - } - } - return $processForm; - } - - public function findByName(string $name): ?ProcessForm - { - AssertHelper::notNull($name, '参数name不能为空'); - $processForm = $this->get(['name' => $name]); - if ($processForm !== null) { - $processFormHistory = (new ProcessFormHistory())->where(['process_form_id' => $processForm->getData('id')])->order('create_time', 'desc')->find(); - $processForm->form = (object)[]; - $processForm->versions = (float)1.0; - if ($processFormHistory != null) { - $processForm->form = $processFormHistory->getData('content'); - $processForm->versions = $processFormHistory->getData('versions'); - } - } - return $processForm; - } - - public function updateForm(object $jsonObject): bool - { - $processFormHistory = new ProcessFormHistory(); - $data = new \stdClass(); - $data->process_form_id = $jsonObject->{ProcessConst::PROCESS_FORM_ID_KEY}; - $data->create_user = $jsonObject->{ProcessConst::CREATE_USER}; - $processDesign = $this->get($data->process_form_id); - $processDesign->set('update_time', time()); - $processDesign->set('update_user', $data->create_user); - $processDesign->save(); - unset($jsonObject->{ProcessConst::CREATE_USER}); - unset($jsonObject->{ProcessConst::PROCESS_FORM_ID_KEY}); - $data->content = $jsonObject; - // 获取当前版本号并转换为浮点数 - $processFormHistoryService = new ProcessFormHistoryService(); - $newVersion = 1.0;//默认版本 - $history = $processFormHistoryService->selectList(['process_form_id' => $data->process_form_id], 'versions', 0, 0, 'create_time asc', [], true)->last(); - if (!empty($history)) { - $currentVersion = (float)$history->getData('versions'); - $newVersion = round($currentVersion + 0.1, 1); - } - $data->versions = $newVersion; - ModelUtils::copyProperties($data, $processFormHistory); - return $processFormHistory->save(); - } - - private function checkUniqueName(array $where): bool - { - $result = $this->selectList($where, '*', 0, 0, '', [], true)->toArray(); - return !empty($result) ?? false; - } -} diff --git a/src/service/ProcessInstanceService.php b/src/service/ProcessInstanceService.php deleted file mode 100644 index 9f5578a90097d7f8dd63bf9094f19bcde03119a8..0000000000000000000000000000000000000000 --- a/src/service/ProcessInstanceService.php +++ /dev/null @@ -1,587 +0,0 @@ -id); - $processInstance = new ProcessInstance(); - ModelUtils::copyProperties($param, $processInstance); - return $processInstance->save(); - } - - public function update(object $param): bool - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - $processInstance = $this->get($param->id); - ModelUtils::copyProperties($param, $processInstance); - return $processInstance->save(); - } - - public function page(object $param): array - { - $where = ArrayHelper::paramsFilter($param, [ - ['parent_id', ''], - ['process_define_id', ''], - ['state', ''], - ['parent_node_name', ''], - ['business_no', ''], - ['operator', ''], - ]); - [$page, $limit] = PageParam::getPageValue($param); - $list = $this->selectList($where, '*', $page, $limit, 'create_time asc', ['processDefine'], true)->toArray(); - $count = $this->count($where); - foreach ($list as $key => $value) { - $list[$key]['process_name'] = $value['processDefine']['display_name'] ?? ''; - $list[$key]['ext'] = $value['variable']; - $list[$key]['form_data'] = ProcessFlowUtils::filterObjectByPrefix((object)$value['variable'], 'f_'); - $list[$key]['variable'] = json_encode($value['variable']); - unset($value['processDefine']); - } - return compact('list', 'count'); - } - - public function findById(string $id): ?ProcessInstance - { - AssertHelper::notNull($id, '参数ID不能为空'); - $processInstance = $this->get($id, ['*'], ['processDefine']); - if ($processInstance != null) { - $processDefine = $processInstance->getData('processDefine'); - $content = ArrayHelper::arrayToObject($processDefine->getData('content') ?? []); - $processInstance->set('version', $processDefine->getData('version')); - $processInstance->set('json_object', $content); - $processInstance->set('ext', $processInstance->getData('variable')); - $processInstance->set('form_data', ProcessFlowUtils::filterObjectByPrefix($processInstance->getData('variable'), 'f_')); - $processInstance->set('variable', json_encode($processInstance->getData('variable'))); - $processInstance->hidden(['processDefine']); - } - - return $processInstance; - } - - public function finishProcessInstance(string $processInstanceId): void - { - $processInstance = $this->get($processInstanceId); - AssertHelper::notNull($processInstance, '实例不存在或被删除'); - $processInstance->set('state', ProcessInstanceStateEnum::FINISHED[0]); - $processInstance->save(); - } - - public function createProcessInstance(ProcessDefine $processDefine, string $operator, Dict $args, string|null $parentId = '', string|null $parentNodeName = ''): ProcessInstance - { - $processInstance = new ProcessInstance(); - $processInstance->set('parent_id', $parentId); - $processInstance->set('parent_node_name', $parentNodeName); - $processInstance->set('process_define_id', $processDefine->getData('id')); - $processInstance->set('operator', $operator); - $processInstance->set('state', ProcessInstanceStateEnum::DOING[0]); - // 业务流水号从流程变量中获取 - $processInstance->set('business_no', $args->{ProcessConst::BUSINESS_NO} ?? ''); - if (empty($args->get(ProcessConst::BUSINESS_NO))) { - //外面没有传单据编号使用内置默认编号生成器 - $processInstance->set('business_no', (new DefaultNoGenerator())->generate(null)); - } - //添加期望时间 - $processModel = (new ProcessDefineService())->processDefineToModel($processDefine); - $expireTime = $processModel->getExpireTime(); - if (!empty($expireTime)) { - $dateTime = ProcessFlowUtils::processTime($expireTime, $args); - if ($dateTime !== null) { - $processInstance->set('expire_time', $dateTime->getTimestamp()); - } - } - - // 追加用户信息到参数 - ProcessFlowUtils::addUserInfoToArgs($operator, $args); - // 追加自动构造标题 - ProcessFlowUtils::addAutoGenTitle($processDefine->getData('display_name'), $args); - $processInstance->set('variable', $args->getAll()); - return $this->saveProcessInstance($processInstance); - } - - public function addVariable(string $processInstanceId, Dict $args): void - { - $processInstance = $this->get($processInstanceId); - AssertHelper::notNull($processInstance, '流程实例不存在'); - $variable = $processInstance->getData('variable') ?? (object)[]; - $newDict = new Dict(); - $newDict->putAll($variable); - $newDict->putAll($args->getAll()); - $processInstance->set('variable', $newDict->getAll()); - $processInstance->save(); - } - - public function removeVariable(string $processInstanceId, string|array $keys): void - { - $processInstance = $this->get($processInstanceId); - AssertHelper::notNull($processInstance, '流程实例不存在'); - $variable = $processInstance->getData('variable') ?? (object)[]; - $oldDict = new Dict(); - $oldDict->putAll($variable); - foreach (is_array($keys) ? $keys : explode(',', $keys) as $value) { - $oldDict->remove($value); - } - $processInstance->set('variable', $oldDict->getAll()); - $processInstance->save(); - } - - public function saveProcessInstance(ProcessInstance $processInstance): ?ProcessInstance - { - $processInstance->set('create_time', time()); - $processInstance->set('update_time', time()); - return $processInstance::create($processInstance->toArray()); - } - - public function interrupt(string $processInstanceId, string $operator): void - { - // 1. 将该流程实例产生的任务状态修改为终止 - $processTaskService = new ProcessTaskService(); - $map1 = [ - 'id' => $processInstanceId, - 'task_state' => ProcessTaskStateEnum::DOING[0], - ]; - $processTask = $processTaskService->get($map1); - if (!empty($processTask)) { - $processTask->set('task_state', ProcessTaskStateEnum::INTERRUPT[0]); - $processTask->set('update_time', time()); - $processTask->set('update_user', $operator); - $processTask->save(); - } - // 2. 将该流程实例状态修改为终止 - $map2 = [ - 'id' => $processInstanceId, - 'state' => ProcessInstanceStateEnum::DOING[0], - ]; - $processInstance = $this->get($map2); - if (!empty($processInstance)) { - $processInstance->set('state', ProcessInstanceStateEnum::INTERRUPT[0]); - $processInstance->set('update_time', time()); - $processInstance->set('update_user', $operator); - $processInstance->save(); - } - } - - public function resume(string $processInstanceId, string $operator): void - { - // 1. 更新流程实例状态为进行中 - $processInstance = $this->get($processInstanceId); - AssertHelper::notNull($processInstance, '唤醒失败,流程实例不存在'); - $processInstance->set('state', ProcessInstanceStateEnum::DOING[0]); - $processInstance->set('update_time', time()); - $processInstance->set('update_user', $operator); - $processInstance->save(); - // 2.被终止的任务状态修改为进行中 - $processTaskService = new ProcessTaskService(); - $map1 = [ - 'process_instance_id' => $processInstanceId, - 'task_state' => ProcessTaskStateEnum::INTERRUPT[0], - ]; - $processTask = $processTaskService->get($map1); - AssertHelper::notNull($processTask, '唤醒失败,查找终止任务失败'); - $processTask->set('task_state', ProcessTaskStateEnum::DOING[0]); - $processInstance->set('update_time', time()); - $processInstance->set('update_user', $operator); - $processInstance->save(); - } - - public function cascadeDelete(string $processInstanceId, ?string $operator = null): void - { - // 1. 将该流程实例状态修改为撤回 - $map1 = [ - ['id', '=', $processInstanceId], - ['state', 'notIn', [ProcessInstanceStateEnum::DOING[0], ProcessInstanceStateEnum::PENDING[0], ProcessInstanceStateEnum::FINISHED[0]]], - ]; - $processInstance = $this->get($map1); - AssertHelper::notNull($processInstance, '流程实例不存在或已完成,撤回失败'); - if ($processInstance != null) { - //1.删除task - $map1 = ['process_instance_id' => $processInstance->getData('id')]; - $processTaskService = new ProcessTaskService(); - $taskList = $processTaskService->selectList($map1, '*', 0, 0, '', [], true); - //2.删除actions - foreach ($taskList as $task) { - $map2 = ['process_task_id' => $task->getData('id')]; - $processTaskActorService = new ProcessTaskActorService(); - $actorList = $processTaskActorService->selectList($map2, '*', 0, 0, '', [], true); - foreach ($actorList as $actor) { - $actor->delete(); - } - $task->delete(); - } - } - $processInstance->delete(); - } - - public function pending(string $processInstanceId, string $operator): void - { - // 1. 将该流程实例产生的任务状态修改为挂起 - $processTaskService = new ProcessTaskService(); - $map1 = [ - 'process_instance_id' => $processInstanceId, - 'task_state' => ProcessTaskStateEnum::DOING[0], - ]; - $processTask = $processTaskService->get($map1); - AssertHelper::notNull($processTask, '挂起失败,没有进行中的任务'); - $processTask->set('task_state', ProcessTaskStateEnum::PENDING[0]); - $processTask->set('update_time', time()); - $processTask->set('update_user', $operator); - $processTask->save(); - // 2. 将该流程实例状态修改为挂起 - $map2 = [ - 'id' => $processInstanceId, - 'state' => ProcessInstanceStateEnum::DOING[0], - ]; - $processInstance = $this->get($map2); - AssertHelper::notNull($processInstance, '挂起失败,流程实例不存在'); - $processInstance->set('state', ProcessInstanceStateEnum::PENDING[0]); - $processInstance->set('update_time', time()); - $processInstance->set('update_user', $operator); - $processInstance->save(); - } - - public function activate(string $processInstanceId, string $operator): void - { - // 1. 更新流程实例状态为进行中 - $processInstance = $this->get($processInstanceId); - AssertHelper::notNull($processInstance, '激活失败,流程实例不存在'); - $processInstance->set('state', ProcessInstanceStateEnum::PENDING[0]); - $processInstance->set('update_time', time()); - $processInstance->set('update_user', $operator); - $processInstance->save(); - // 2.被终止的任务状态修改为进行中 - $processTaskService = new ProcessTaskService(); - $map1 = [ - 'process_instance_id' => $processInstanceId, - 'task_state' => ProcessTaskStateEnum::INTERRUPT[0], - ]; - $processTask = $processTaskService->get($map1); - AssertHelper::notNull($processTask, '挂起失败,没有进行中的任务'); - $processTask->set('task_state', ProcessTaskStateEnum::DOING[0]); - $processTask->set('update_time', time()); - $processTask->set('update_user', $operator); - $processTask->save(); - } - - public function updateProcessInstance(ProcessInstance $processInstance): void - { - $processInstance->set('update_time', time()); - $processInstance->save(); - } - - public function getById(string $id): ?ProcessInstance - { - return $this->get($id); - } - - public function startAndExecute(string $processDefineId, Dict $args): void - { - $config = ServiceContext::findAll(ConfigurationInterface::class); - if (empty($config)) { - throw new LFlowException('没有找到上下文引擎配置类'); - } - $operator = $args->get(ProcessConst::USER_USER_ID); - $processEngines = new ProcessEngines(end($config)); - $processInstance = $processEngines->startProcessInstanceById($processDefineId, $operator, $args); - $processTaskList = $processEngines->processTaskService()->getDoingTaskList($processInstance->getData('id'), ''); - - // 取任务自动执行 - foreach ($processTaskList as $processTask) { - $args->put(ProcessConst::SUBMIT_TYPE, ProcessSubmitTypeEnum::APPLY[0]); - $processEngines->executeProcessTask($processTask->getData('id'), ProcessConst::AUTO_ID, $args); - } - } - - public function highLight(string $processInstanceId): array - { - $vo = new HighLightVirtual(); - $config = ServiceContext::findAll(ConfigurationInterface::class); - if (empty($config)) { - throw new LFlowException('没有找到上下文引擎配置类'); - } - $processInstance = $this->findById($processInstanceId); - $processEngines = new ProcessEngines(end($config)); - Logger::debug('highLight 开始【process_instance_id=' . $processInstanceId . '】'); - - if ($processInstance != null) { - Logger::debug('highLight 【process_instance_id=' . $processInstanceId . ' 拿到正在进行中的任务活跃节点】'); - $processModel = $processEngines->processDefineService()->getProcessModel($processInstance->getData('process_define_id')); - // 拿到正在进行中的任务==>活跃节点 - $processTaskList = $processEngines->processTaskService()->getDoingTaskList($processInstanceId, '');//进行中的 - $finishTasksList = $processEngines->processTaskService()->getDoneTaskList($processInstanceId, '');//已完成的 - foreach ($processTaskList as $task) { - if (!$vo->contains('active_node_names', $task->getData('task_name'))) { - $vo->add('active_node_names', $task->getData('task_name')); - $this->recursionModel($processModel->getStart(), $processInstance, $processTaskList, $finishTasksList, $task->getData('task_name'), $vo); - } - } - // 拿到非正常结束的流程实例状态值 - $filteredEnums = array_filter(ProcessInstanceStateEnum::getEnumValues(), function ($enum) { - $inProgressCode = ProcessInstanceStateEnum::getCode('进行中'); - $completedCode = ProcessInstanceStateEnum::getCode('已完成'); - return $enum[0] != $inProgressCode && $enum[0] != $completedCode; - }); - $orderStatusList = array_map(function ($enum) { - return $enum[0]; - }, $filteredEnums); - //非正常结束特殊处理 - if (in_array($processInstance->getData('state'), $orderStatusList)) { - Logger::debug('highLight 非正常结束特殊处理【process_instance_id=' . $processInstanceId . ' 】'); - $hisProcessTaskList = $processEngines->processTaskService()->getDoneTaskList($processInstanceId, ''); - if (!empty($hisProcessTaskList)) { - $lastProcessTask = $hisProcessTaskList[count($hisProcessTaskList) - 1]; - $nodeModel = $processModel->getNode($lastProcessTask->getData('task_name')); - Logger::debug('highLight 非正常结束处理开始递归'); - $this->recursionModel($processModel->getStart(), $processInstance, $hisProcessTaskList, $finishTasksList, $nodeModel->getOutputs()[0]->getTo(), $vo); - } - } else { - Logger::debug('highLight 其他特殊处理【process_instance_id=' . $processInstanceId . ' 】'); - $endModels = $processModel->getModels(EndModel::class); - foreach ($endModels as $endModel) { - $this->recursionModel($processModel->getStart(), $processInstance, $processTaskList, $finishTasksList, $endModel->getName(), $vo); - } - } - } - Logger::debug('highLight 结束【process_instance_id=' . $processInstanceId . '】'); - return $vo->toArray(); - } - - public function approvalRecord(string $processInstanceId): array - { - $processTaskService = new ProcessTaskService(); - $map1 = [ - 'process_instance_id' => $processInstanceId, - 'not_in_task_state' => implode(',', [ProcessTaskStateEnum::DOING[0], ProcessTaskStateEnum::WITHDRAW[0], ProcessTaskStateEnum::ABANDON[0]]),//不包括“进行中 已撤回 已废弃” 任务 - ]; - $processTaskList = $processTaskService->selectList($map1, '*', 0, 0, 'finish_time asc', [], true); - foreach ($processTaskList as $task) { - $task->set('ext', $task->getData('variable')); - } - if ($processTaskList == null) { - return []; - } - return $processTaskList->toArray(); - } - - public function withdraw(string $processInstanceId, string $operator): void - { - // 1. 将该流程实例状态修改为撤回 - $map1 = [ - 'id' => $processInstanceId, - 'state' => ProcessInstanceStateEnum::DOING[0], - ]; - $processInstance = $this->get($map1); - AssertHelper::notNull($processInstance, '流程实例不存在或已完成,撤回失败'); - $processInstance->set('state', ProcessInstanceStateEnum::WITHDRAW[0]); - $processInstance->set('update_time', time()); - $processInstance->set('update_user', $operator); - if ($processInstance->save()) { - // 2. 将该流程实例产生的任务状态修改为撤回 - $processTaskService = new ProcessTaskService(); - $map2 = [ - 'process_instance_id' => $processInstanceId, - 'task_state' => ProcessTaskStateEnum::DOING[0], - ]; - $upData = [ - 'task_state' => ProcessTaskStateEnum::WITHDRAW[0], - 'updata_time' => time(), - 'update_user' => $operator, - ]; - $processTaskService->updated($map2, $upData); - } - } - - public function updateCountersignVariable(TaskModel $taskModel, Execution $execution, array $taskActors): void - { - /** - * ● nrOfActivateInstances:当前活动的实例数量,即还没有完成的实例数量 - * ● loopCounter :循环计数器,办理人在列表中的索引 - * ● nrOfInstances:会签中总共的实例数 - * ● nrOfCompletedInstances:已经完成的实例数量 - * ● operatorList:会签办理人列表 - */ - // 会签任务变量前缀 - $prefix = ProcessConst::COUNTERSIGN_VARIABLE_PREFIX . $taskModel->getName() . "_"; - $addVariable = new Dict(); - // 更新会签总实例数,nrOfInstances - $addVariable->put($prefix . ProcessConst::NR_OF_INSTANCES, count($taskActors)); - // 更新会签当前活动实例数,nrOfActivateInstances - $addVariable->put($prefix . ProcessConst::NR_OF_ACTIVATE_INSTANCES, count($execution->getDoingTaskList())); - // 更新会签已完成的实例数,nrOfCompletedInstances - $addVariable->put($prefix . ProcessConst::NR_OF_COMPLETED_INSTANCES, $execution->getArgs()->get($prefix . ProcessConst::NR_OF_COMPLETED_INSTANCES)); - // 更新会签操作人列表 countersignOperatorList - $addVariable->put($prefix . ProcessConst::COUNTERSIGN_OPERATOR_LIST, $taskActors); - $this->addVariable($execution->getProcessInstanceId(), $addVariable); - } - - /** - * @inheritDoc - */ - public function createCCInstance(string $processInstanceId, string $creator, string $actorIds): void - { - foreach (explode(',', $actorIds) as $actorId) { - // 查询数据库中是否存在具有相同流程实例ID和演员ID的记录 - $processCcInstanceService = new ProcessCcInstanceService(); - $count = $processCcInstanceService->count(['process_instance_id' => $processInstanceId, 'actor_id' => $actorId], true); - // 如果不存在记录(count为0) - if ($count === 0) { - // 创建新的 ProcessCcInstance 实例 - $processCcInstance = new ProcessCcInstance(); - $processCcInstance->set('process_instance_id', $processInstanceId); - $processCcInstance->set('actor_id', $actorId); - $processCcInstance->set('state', YourEnum::NO[0]); // 假设 YourEnumClass 是枚举类,且有一个 NO 常量 - $processCcInstance->set('create_user', $creator); - $processCcInstance->set('create_time', time()); - $processCcInstance->set('update_user', $creator); - $processCcInstance->set('update_time', time()); - $processCcInstance->save(); - } - } - } - - public function updateCCStatus(string $processInstanceId, string $actorId): void - { - AssertHelper::notNull($processInstanceId, '参数 process_instance_id 不能为空'); - AssertHelper::notNull($actorId, '参数 actor_id 不能为空'); - $processCcInstanceService = new ProcessCcInstanceService(); - $map1 = [ - 'process_instance_id' => $processInstanceId, - 'actor_id' => $actorId, - ]; - $processCcInstance = $processCcInstanceService->get($map1); - AssertHelper::notNull($processCcInstance, '操作异常请刷新后重试'); - $processCcInstance->set('state', YourEnum::YES[0]); - $processCcInstance->set('update_time', time()); - $processCcInstance->set('update_user', $actorId); - $processCcInstance->save(); - } - - public function ccInstancePage(object $param): array - { - $param->state = YourEnum::NO[0]; - $processCcInstanceService = new ProcessCcInstanceService(); - return $processCcInstanceService->page($param); - } - - private function recursionModel($nodeModel, $processInstance, $processTaskList, $finishTasksList, $taskName, $vo): void - { - if ($nodeModel->getName() === $taskName) { - if ($nodeModel instanceof EndModel) { - $vo->add('history_node_names', $nodeModel->getName()); - } - return; - } - - if (!$vo->contains('history_node_names', $nodeModel->getName())) { - $vo->add('history_node_names', $nodeModel->getName()); - $filteredOutputs = array_filter($nodeModel->getOutputs(), function ($output) use ($nodeModel, $processInstance, $processTaskList, $finishTasksList, $vo) { - $defaultDecisionInputModel = null; - $historyTask = null; - if ($nodeModel instanceof DecisionModel) { - Logger::debug('highLight DecisionModel 决策表达式处理'); - $defaultDecisionInputModel = $nodeModel->getInputs()[0]->getSource(); - // 使用查询构建器对模型对象列表进行过0 - $filteredTasks = []; - foreach ($processTaskList as $hisTask) { - if ($defaultDecisionInputModel->getName() === $hisTask->getData('task_name')) { - $filteredTasks[] = $hisTask; - } - } - $historyTask = reset($filteredTasks); // 获取筛选后的第一个元素 - } - - $args = new Dict(); - $args->putAll($processInstance->getData('ext')); - if ($historyTask) { - $args->putAll($historyTask->getData('variable')); - } - if (!empty($output->getExpr()) && $nodeModel instanceof DecisionModel && $defaultDecisionInputModel !== null) { - //表达式处理 - return ExpressionUtil::eval($output->getExpr(), $args); - } - if ($nodeModel instanceof DecisionModel) { - $expr = $nodeModel->getExpr(); - if (!empty($expr)) { - return true; - } - } - - //合并节点处理 - if ($nodeModel instanceof JoinModel) { - Logger::debug('highLight JoinModel 合并节点处理'); - $isMerged = MergeBranchHandler::isMerged($processInstance->getData('id'), $nodeModel); - if (!$isMerged) { - //未能合并,要把已加入历史的节点和边删除 - $vo->remove('history_node_names', $nodeModel->getName()); - foreach ($nodeModel->getInputs() as $input) { - $vo->remove('history_edge_names', $input->getName()); - } - } - return $isMerged; - } - return true; - }); - - // 对过滤后的结果进行遍历操作 - foreach ($filteredOutputs as $transitionModel) { - if (!$vo->contains('history_edge_names', $transitionModel->getName())) { - $vo->add('history_edge_names', $transitionModel->getName()); - $this->recursionModel($transitionModel->getTarget(), $processInstance, $processTaskList, $finishTasksList, $taskName, $vo); - } - } - } - } -} diff --git a/src/service/ProcessSurrogateService.php b/src/service/ProcessSurrogateService.php deleted file mode 100644 index 7e6ef9e1f507b5c97cefa470f62b6f13ea26aad9..0000000000000000000000000000000000000000 --- a/src/service/ProcessSurrogateService.php +++ /dev/null @@ -1,135 +0,0 @@ -id); - $processSurrogate = new ProcessSurrogate(); - ModelUtils::copyProperties($param, $processSurrogate); - return $processSurrogate->save(); - } - - public function update(object $param): bool - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - $processSurrogate = $this->get($param->id); - ModelUtils::copyProperties($param, $processSurrogate); - return $processSurrogate->save(); - } - - public function del(string|array|int $id): bool - { - $processType = new ProcessSurrogate(); - $map1 = []; - if (is_array($id)) { - $map1[] = ['id', 'in', $id]; - } else { - $map1[] = ['id', '=', $id]; - } - return $processType->where($map1)->delete(); - } - - public function page(object $param): array - { - - $where = ArrayHelper::paramsFilter($param, [ - ['process_name', ''], - ['operator', $param->{ProcessConst::CREATE_USER} ?? ''], - ['surrogate', ''], - ['enabled', ''], - ]); - [$page, $limit] = PageParam::getPageValue($param); - $list = $this->selectList($where, '*', $page, $limit, 'create_time asc', ['processDefine' => function (Query $query) { - $query->where('state', ProcessDefineStateEnum::ENABLE[0]); - $query->where('is_del', IsDeleteEnum::NO[0]); - }], true)->toArray(); - $count = $this->count($where); - return compact('list', 'count'); - } - - public function findById(string $id): ?ProcessSurrogate - { - return $this->get($id); - } - - public function getSurrogate(string $operator, string $processName): ?string - { - $map1 = [ - 'operator' => $operator, - 'process_name' => $processName, - 'enabled' => IsEnabledEnum::YES[0], - ]; - $processSurrogateList = $this->selectList($map1, '*', 0, 0, 'create_time desc', [], true); - if (empty($processSurrogateList)) { - return null; - } - foreach ($processSurrogateList as $processSurrogate) { - // 为空表示全部,优先级最高,直接返回 - if (empty($processSurrogate->getData('process_name'))) { - // 开始时间判断 - if (!is_null($processSurrogate->getData('start_time')) && $processSurrogate->getData('start_time') > time()) { - continue; - } - // 结束时间判断 - if (!is_null($processSurrogate->getData('end_time')) && $processSurrogate->getData('end_time') < time()) { - continue; - } - return $processSurrogate->getData('surrogate'); - } - } - // 取满足条件的最新一条 - $filteredSurrogates = array_filter($processSurrogateList->all(), function ($processSurrogate) use ($processName) { - // 只查询流程名称一样的 - if ($processSurrogate->getData('process_name') !== $processName) { - return false; - } - // 开始时间判断 - if (!is_null($processSurrogate->getData('start_time')) && $processSurrogate->getData('start_time') > time()) { - return false; - } - // 结束时间判断 - if (!is_null($processSurrogate->getData('end_time')) && $processSurrogate->getData('end_time') < time()) { - return false; - } - return true; - }); - if (!empty($filteredSurrogates)) { - $filteredSurrogate = reset($filteredSurrogates); // 获取第一个满足条件的元素 - return $filteredSurrogate->getData('surrogate'); - } - return null; - } -} diff --git a/src/service/ProcessTaskActorService.php b/src/service/ProcessTaskActorService.php deleted file mode 100644 index 8296d9af14daeb411b39161a9745eddb64c5ba65..0000000000000000000000000000000000000000 --- a/src/service/ProcessTaskActorService.php +++ /dev/null @@ -1,53 +0,0 @@ -id); - $processTaskActor = new ProcessTaskActor(); - ModelUtils::copyProperties($param, $processTaskActor); - return $processTaskActor->save(); - } - - public function update(object $param): bool - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - $processTaskActor = $this->get($param->id); - ModelUtils::copyProperties($param, $processTaskActor); - return $processTaskActor->save(); - } - - public function page(object $param): array - {} - - public function findById(string $id): ?ProcessTaskActor - { - return $this->get($id); - } -} diff --git a/src/service/ProcessTaskService.php b/src/service/ProcessTaskService.php deleted file mode 100644 index 3c840329487eba69a30c7e5f9c9d89658c65fed0..0000000000000000000000000000000000000000 --- a/src/service/ProcessTaskService.php +++ /dev/null @@ -1,590 +0,0 @@ -id); - $processTask = new ProcessTask(); - ModelUtils::copyProperties($param, $processTask); - return $processTask->save(); - } - - public function update($param): bool - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - $processTask = $this->get($param->id); - ModelUtils::copyProperties($param, $processTask); - return $processTask->save(); - } - - public function findById(string|int $id): ?ProcessTask - { - $processTask = $this->get($id); - if ($processTask != null) { - $processTask->set('ext', $processTask->getData('variable')); - $processTask->set('variable', json_encode($processTask->getData('variable'))); - } - return $processTask; - } - - public function saveProcessTask(ProcessTask $processTask): void - { - $processTask->save(); - } - - public function updateProcessTask(ProcessTask $processTask): void - { - $processTask->save(); - } - - public function getDoingTaskList(string $processInstanceId, string|array $taskNames): ?array - { - $map1 = [ - 'process_instance_id' => $processInstanceId, - 'task_state' => ProcessTaskStateEnum::DOING[0], - ]; - if (!empty($taskNames)) { - $map1['task_name'] = $taskNames; - } - return $this->selectList($map1, '*', 0, 0, '', [], true)->all(); - } - - public function getDoneTaskList(string $processInstanceId, string|array $taskNames): ?array - { - $map1 = [ - 'process_instance_id' => $processInstanceId, - 'not_in_task_state' => ProcessTaskStateEnum::DOING[0], - ]; - if (!empty($taskNames)) { - $map1['task_name'] = $taskNames; - } - return $this->selectList($map1, '*', 0, 0, '', [], true)->all(); - } - - public function finishProcessTask(string $processTaskId, string $operator, Dict $args): void - { - $processTask = $this->get($processTaskId); - AssertHelper::notNull($processTask, '任务节点不存在或被删除'); - $processTask->set('task_state', ProcessTaskStateEnum::FINISHED[0]); - $processTask->set('update_time', time()); - $processTask->set('update_user', $operator); - $processTask->set('operator', $operator); - $processTask->set('finish_time', time()); - $newArgs = new Dict(); - if (!empty($processTask->getData('variable'))) { - $newArgs->putAll((object)[]); - } - $newArgs->putAll($args->getAll()); - if (StringHelper::equalsIgnoreCase(ProcessConst::AUTO_ID, $operator)) { - //获取当前系统登录用户 - $login = ServiceContext::findFirst(LoginUserHolderInterface::class); - AssertHelper::notNull($login, '未找到当前系统登录用户接口'); - $sysUserId = $login->getUserId(); - AssertHelper::notNull($sysUserId, '获取当前系统登录用户失败'); - ProcessFlowUtils::addUserInfoToArgs($sysUserId, $newArgs); - } else { - ProcessFlowUtils::addUserInfoToArgs($operator, $newArgs); - } - $processTask->set('variable', $newArgs); - $processTask->save(); - //发布流程结束结束事件 - ProcessEventService::publishNotification(ProcessEventTypeEnum::PROCESS_TASK_END[0], $processTask->getData('id')); - } - - public function abandonProcessTask(string $processTaskId, string $operator, Dict $args): void - { - $processTask = $this->get($processTaskId); - AssertHelper::notNull($processTask, '任务节点不存在或被删除'); - $processTask->set('task_state', ProcessTaskStateEnum::ABANDON[0]); - $processTask->set('update_time', time()); - $processTask->set('update_user', $operator); - $processTask->set('operator', $operator); - $processTask->set('finish_time', time()); - $newArgs = new Dict(); - $newArgs->putAll($processTask->getData('variable')); - $newArgs->putAll($args->getAll()); - if (StringHelper::equalsIgnoreCase(ProcessConst::AUTO_ID, $operator)) { - ProcessFlowUtils::addUserInfoToArgs(ProcessConst::AUTO_ID, $newArgs); - } else { - ProcessFlowUtils::addUserInfoToArgs($operator, $newArgs); - } - $processTask->set('variable', $newArgs); - $processTask->save(); - //发布流程结束结束事件 - ProcessEventService::publishNotification(ProcessEventTypeEnum::PROCESS_TASK_END[0], $processTask->getData('id')); - } - - public function createTask(TaskModel $taskModel, Execution $execution): ?array - { - $processTaskList = []; - $processTask = new ProcessTask(); - $processTask->set('perform_type', ProcessTaskPerformTypeEnum::NORMAL[0]); - $processTask->set('task_name', $taskModel->getName()); - $processTask->set('display_name', $taskModel->getDisplayName()); - $processTask->set('task_state', ProcessTaskStateEnum::DOING[0]); - $processTask->set('process_instance_id', $execution->getProcessInstanceId()); - $execution->getArgs()->put(ProcessConst::IS_FIRST_TASK_NODE, ProcessFlowUtils::isFistTaskName($execution->getProcessModel(), $taskModel->getName())); - //添加消息提醒间隔时间是否自动执行参数到变量 - $execution->getArgs()->put(NodeParser::REMINDER_TIME_KEY, $taskModel->getReminderTime()); - $execution->getArgs()->put(NodeParser::REMINDER_REPEAT_KEY, $taskModel->getReminderRepeat()); - $execution->getArgs()->put(NodeParser::AUTH_EXECUTE_KEY, $taskModel->getAutoExecute()); - - $processTask->set('variable', $execution->getArgs()->getAll()); - $processTask->set('create_time', time()); - $processTask->set('update_time', time()); - $processTask->set('task_parent_id', $execution->getProcessTaskId()); - $expireTime = $taskModel->getExpireTime(); - if (!empty($expireTime)) { - $dateTime = ProcessFlowUtils::processTime($expireTime, $execution->getArgs()); - if ($dateTime !== null) { - $processTask->set('expire_time', $dateTime->getTimestamp()); - } - } - $processTask->save(); - $execution->setProcessTask($processTask); - $processTaskList[] = $processTask; - $this->addTaskActor($processTask->getData('id'), $this->getTaskActors($taskModel, $execution)); - return $processTaskList; - - } - - public function getById(string $id): ?ProcessTask - { - return $this->get($id); - } - - public function addTaskActor($processTaskId, array|string $actors,): void - { - if (empty($actors)) { - return; - } - $actors = is_array($actors) ? $actors : explode(',', $actors); - $processTaskActorService = new ProcessTaskActorService(); - $dbActors = $processTaskActorService->getColumn(['process_task_id' => $processTaskId], 'actor_id'); - $filteredActors = array_filter($actors, function ($actor) use ($dbActors) { - return !in_array($actor, $dbActors); - }); - foreach ($filteredActors as $actor) { - $insertData = (object)[ - 'process_task_id' => $processTaskId, - 'actor_id' => (string)$actor, - 'create_time' => time(), - ]; - $processTaskActorService->create($insertData); - } - } - - public function addCandidateActor(string $processTaskId, array|string $actors): void - { - if (empty($actors)) { - return; - } - $processTask = $this->get($processTaskId); - if (empty($processTask)) { - return; - } - // 主要调整流程变量中的参与者 - $processInstanceService = new ProcessInstanceService(); - $processInstance = $processInstanceService->get($processTask->getData('process_instance_id')); - $prefix = ProcessConst::COUNTERSIGN_VARIABLE_PREFIX . $processTask->getData('task_name') . "_"; - if ($processInstance != null) { - $args = ProcessFlowUtils::variableToDict($processInstance->getData('variable')); - // 会签办理人列表 - $operatorList = $args->get($prefix . ProcessConst::COUNTERSIGN_OPERATOR_LIST, []); - $operatorList = array_unique(array_merge($operatorList, is_array($actors) ? $actors : explode(',', $actors))); - $args->put($prefix . ProcessConst::COUNTERSIGN_OPERATOR_LIST, $operatorList); - $processInstance->set('variable', $args->getAll()); - $processInstance->save(); - } - } - - public function removeTaskActor(string $processTaskId, array|string $actors): void - { - if (empty($processTaskId) || empty($actors)) { - return; - } - $processTaskActor = new ProcessTaskActor(); - $processTaskActor->where('process_task_id', $processTaskId) - ->whereIn('actor_id', is_array($actors) ? implode(',', $actors) : $actors) - ->delete(); - - } - - public function isAllowed(ProcessTask $task, string $operator): bool - { - // 执行者为超级管理员或自动执行用户 - if (strcasecmp(ProcessConst::ADMIN_ID, $operator) === 0 || strcasecmp(ProcessConst::AUTO_ID, $operator) === 0) { - return true; - } - // 任务操作者==执行者 - if (strcasecmp($task->getData('operator'), $operator) === 0) { - return true; - } - // 任务参考者==执行者 - $actorsList = $this->getTaskActor($task->getData('id')); - if (!empty($actorsList)) { - return in_array($operator, $actorsList); - } - return false; - } - - public function getTaskActor($processTaskId): array - { - $processTaskActorService = new ProcessTaskActorService(); - return $processTaskActorService->getColumn(['process_task_id' => $processTaskId], 'actor_id'); - } - - public function getTaskActors(TaskModel $model, Execution $execution): array - { - $nextNodeOperator = $execution->getArgs()->get(ProcessConst::NEXT_NODE_OPERATOR); - if (!empty($nextNodeOperator)) { - return is_array($nextNodeOperator) ? $nextNodeOperator : explode(',', $nextNodeOperator); - } - $result = []; - $assignee = $model->getAssignee(); - if (!empty($assignee)) { - // 多个使用英文逗号分割 - $assigneeArr = explode(",", $assignee); - foreach ($assigneeArr as $assigneeItem) { - // 如果args中存在assigneeArr[i]为key的数据 - $argsArr = (array)$execution->getArgs()->getAll(); - if (array_key_exists($assigneeItem, $argsArr)) { - $result[] = $argsArr[$assigneeItem]; - } else { - // 如果args中不存在assigneeArr[i]为key的数据 - $result[] = $assigneeItem; - } - } - } else { - $assignmentHandler = $model->getAssignmentHandler(); - if (!empty($assignmentHandler)) { - $assignmentHandlerObj = new $assignmentHandler(); - $result = array_merge($result, $assignmentHandlerObj->assign($model, $execution)); - } - } - return $result; - } - - public function todoList(object $param): array - { - - AssertHelper::notNull($param->actor_id ?? '', '参数actor_id 不能为空'); - [$page, $limit] = PageParam::getPageValue($param); - $processTaskActorTable = ProcessTaskActor::getTableName(); - $processTaskTable = ProcessTask::getTableName(); - $processInstanceTable = ProcessInstance::getTableName(); - $processDefineTable = ProcessDefine::getTableName(); - $map1 = [ - ['pt.task_state', '=', ProcessTaskStateEnum::DOING[0]], - ['pta.actor_id', '=', $param->actor_id], - ]; - if (isset($param->business_no) && !empty($param->business_no)) { - $map1[] = ['pi.business_no', '=', $param->business_no]; - } - if (isset($param->task_name) && !empty($param->task_name)) { - $map1[] = ['pt.task_name', '=', $param->task_name]; - } - if (isset($param->display_name) && !empty($param->display_name)) { - $map1[] = ['pt.display_name', 'like', $param->display_name . '%']; - } - if (isset($param->process_define_name) && !empty($param->process_define_name)) { - $map1[] = ['pd.name', '=', $param->process_define_name]; - } - if (isset($param->process_define_display_name) && !empty($param->process_define_display_name)) { - $map1[] = ['pd.display_name', 'like', $param->process_define_display_name . '%']; - } - $list = Db::table($processTaskActorTable) - ->alias('pta') - ->where($map1) - ->field('pta.*, pt.task_name,pt.display_name,pt.task_type,pt.perform_type,pt.task_state,pt.variable as ext,pt.create_time,pt.update_time, pi.id as process_instance_id, pd.id as process_define_id,pi.create_time as instance_create_time,pi.variable as instance_ext,pi.business_no,pd.name as process_define_name,pd.display_name as process_define_display_name,pd.description as process_define_description') - ->join([$processTaskTable => 'pt'], 'pta.process_task_id = pt.id') - ->join([$processInstanceTable => 'pi'], 'pt.process_instance_id = pi.id') - ->join([$processDefineTable => 'pd'], 'pi.process_define_id = pd.id') - ->order('pta.create_time', 'desc') - ->page($page, $limit) - ->select() - ->toArray(); - $count = Db::table($processTaskActorTable) - ->alias('pta') - ->where($map1) - ->join([$processTaskTable => 'pt'], 'pta.process_task_id = pt.id') - ->join([$processInstanceTable => 'pi'], 'pt.process_instance_id = pi.id') - ->join([$processDefineTable => 'pd'], 'pi.process_define_id = pd.id') - ->order('pta.create_time', 'desc') - ->count(); - foreach ($list as $key => $value) { - $list[$key]['ext'] = json_decode($value['ext']) ?? (object)[]; - $list[$key]['create_date'] = !empty($value['create_time']) ? DateTimeHelper::timestampToString($value['create_time']) : ''; - $list[$key]['update_date'] = !empty($value['update_time']) ? DateTimeHelper::timestampToString($value['update_time']) : ''; - $list[$key]['instance_create_date'] = !empty($value['instance_create_time']) ? DateTimeHelper::timestampToString($value['instance_create_time']) : ''; - $list[$key]['instance_ext'] = json_decode($value['instance_ext']) ?? (object)[]; - } - return compact('list', 'count'); - } - - public function doneList(object $param): array - { - AssertHelper::notNull($param->actor_id ?? '', '参数actor_id 不能为空'); - [$page, $limit] = PageParam::getPageValue($param); - $processTaskActorTable = ProcessTaskActor::getTableName(); - $processTaskTable = ProcessTask::getTableName(); - $processInstanceTable = ProcessInstance::getTableName(); - $processDefineTable = ProcessDefine::getTableName(); - $map1 = [ - ['pta.actor_id', '=', $param->actor_id], - ['pt.task_state', 'not in', [ProcessTaskStateEnum::DOING[0], ProcessTaskStateEnum::WITHDRAW[0]]], - ['pt.operator', '<>', ProcessConst::AUTO_ID], - ]; - if (isset($param->business_no) && !empty($param->business_no)) { - $map1[] = ['pi.business_no', '=', $param->business_no]; - } - if (isset($param->task_name) && !empty($param->task_name)) { - $map1[] = ['pt.task_name', '=', $param->task_name]; - } - if (isset($param->display_name) && !empty($param->display_name)) { - $map1[] = ['pt.display_name', 'like', $param->display_name . '%']; - } - if (isset($param->process_define_name) && !empty($param->process_define_name)) { - $map1[] = ['pd.name', '=', $param->process_define_name]; - } - if (isset($param->process_define_display_name) && !empty($param->process_define_display_name)) { - $map1[] = ['pd.display_name', 'like', $param->process_define_display_name . '%']; - } - $list = Db::table($processTaskActorTable) - ->alias('pta') - ->where($map1) - ->field('pta.*, pt.task_name,pt.display_name,pt.task_type,pt.perform_type,pt.task_state,pt.variable as ext,pt.create_time,pt.update_time, pi.id as process_instance_id, pd.id as process_define_id,pi.create_time as instance_create_time,pi.variable as instance_ext,pi.business_no,pd.name as process_define_name,pd.display_name as process_define_display_name,pd.description as process_define_description') - ->join([$processTaskTable => 'pt'], 'pta.process_task_id = pt.id') - ->join([$processInstanceTable => 'pi'], 'pt.process_instance_id = pi.id') - ->join([$processDefineTable => 'pd'], 'pi.process_define_id = pd.id') - ->order('pta.create_time', 'desc') - ->page($page, $limit) - ->select() - ->toArray(); - $count = Db::table($processTaskActorTable) - ->alias('pta') - ->where($map1) - ->join([$processTaskTable => 'pt'], 'pta.process_task_id = pt.id') - ->join([$processInstanceTable => 'pi'], 'pt.process_instance_id = pi.id') - ->join([$processDefineTable => 'pd'], 'pi.process_define_id = pd.id') - ->order('pta.create_time', 'desc') - ->count(); - foreach ($list as $key => $value) { - $list[$key]['ext'] = json_decode($value['ext']) ?? (object)[]; - $list[$key]['create_date'] = !empty($value['create_time']) ? DateTimeHelper::timestampToString($value['create_time']) : ''; - $list[$key]['update_date'] = !empty($value['update_time']) ? DateTimeHelper::timestampToString($value['update_time']) : ''; - $list[$key]['finish_date'] = !empty($value['finish_time']) ? DateTimeHelper::timestampToString($value['finish_time']) : ''; - $list[$key]['instance_create_date'] = !empty($value['instance_create_time']) ? DateTimeHelper::timestampToString($value['instance_create_time']) : ''; - $list[$key]['instance_ext'] = json_decode($value['instance_ext']) ?? (object)[]; - } - return compact('list', 'count'); - } - - public function rejectTask(ProcessModel $model, ProcessTask $currentTask): ?ProcessTask - { - $taskParentId = $currentTask->getData('task_parent_id'); - AssertHelper::notNull($taskParentId, '上一步任务ID为空,无法驳回至上一步处理'); - $current = $model->getNode($currentTask->getData('task_name')); - $history = $this->get($taskParentId); - - $parent = $model->getNode($history->getData('task_name')); - if (!NodeModel::canRejected($current, $parent)) { - throw new LFlowException("无法驳回至上一步处理,请确认上一步骤并非fork、join、suprocess以及会签任务", '', 99999999); - } - $task = new ProcessTask(); - ModelUtils::copyProperties((object)$history->toArray(), $task); - $task->set('id', null); - $task->set('task_tate', ProcessTaskStateEnum::DOING[0]); - $task->set('create_time', null); - $task->set('create_user', null); - $task->set('update_time', null); - $task->set('update_user', null); - $task->set('finish_time', null); - $operator = $history->getData('operator'); - $hisVariable = ProcessFlowUtils::variableToDict($history->getData('variable')); - if ($hisVariable->get(ProcessConst::IS_FIRST_TASK_NODE, false)) { - // 第一个节点的操作人从任务变量中获取 - $operator = $hisVariable->get(ProcessConst::USER_USER_ID); - } - $task->set('variable', $hisVariable->getAll()); - $task->set('operator', $operator); - $task->set('expire_time', $history->getData('expire_time')); - $this->saveProcessTask($task); - $this->addTaskActor($task->getData('id'), $task->getData('operator')); - return $task; - } - - public function jumpAbleTaskNameList(string $processInstanceId): array - { - $taskNames = []; - $result = []; - $processTaskList = $this->getDoneTaskList($processInstanceId, ''); - $processTaskList = array_filter($processTaskList, function ($task) { - return !(ProcessTaskPerformTypeEnum::COUNTERSIGN[0] === $task->getData('perform_type')); - }); - foreach ($processTaskList as $processTask) { - $taskName = $processTask->getData('task_name'); - if (!in_array($taskName, $taskNames)) { - $taskNames[] = $taskName; - $result[] = (object)['label' => $processTask->getData('display_name'), 'value' => $processTask->getData('task_name'), 'ext' => null]; - } - } - return $result; - } - -// public function candidatePage($query): object -// { -// -// } - - public function candidatePage(Dict $query): object|array - { - $processTaskId = $query->get(ProcessConst::PROCESS_TASK_ID_KEY); - $processTask = null; - $processInstance = null; - $processModel = null; - if ($processTaskId) { - $processTask = $this->get($processTaskId); - } - if ($processTask) { - $processInstanceService = new ProcessInstanceService(); - $processInstance = $processInstanceService->get($processTask->getData('process_instance_id')); - } - if ($processInstance) { - $processDefineService = new ProcessDefineService(); - $processModel = $processDefineService->getProcessModel($processInstance->getData('process_define_id')); - } - $candidateList = null; - if (!empty($processModel)) { - $candidateList = $processModel->getNextTaskModelCandidates($processTask->getData('task_name')); - } - //通过id in查询用户列表 - $list = []; - $count = 0; - return compact('list', 'count'); - } - - public function createCountersignTask(TaskModel $taskModel, Execution $execution): ProcessTask|array|null - { - $processTaskList = []; - $taskActors = $this->getTaskActors($taskModel, $execution); - $createTaskActors = []; - - if ($taskModel->getCountersignType()[0] === CountersignTypeEnum::PARALLEL[0]) { - // 并行:一个参与者一个任务,同时创建 - $createTaskActors = $taskActors; - // 追加会签类型参数 - $execution->getArgs()->put(ProcessConst::COUNTERSIGN_VARIABLE_PREFIX . ProcessConst::COUNTERSIGN_TYPE, CountersignTypeEnum::PARALLEL[0]); - } else { - // 串行:一个参与者一个任务,顺序创建,默认只创建第一个,其他等执行完一个后再创建 - $prefix = ProcessConst::COUNTERSIGN_VARIABLE_PREFIX . $taskModel->getName() . "_"; - // 获取循环计数器,默认值为-1 - $loopCounter = $execution->getArgs()->get($prefix . ProcessConst::LOOP_COUNTER, -1); - if ($loopCounter === -1) { - $createTaskActors[] = $taskActors[0]; - } else { - $createTaskActors[] = $taskActors[$loopCounter + 1]; - // 更新计数器为最后的下标值 - $execution->getArgs()->put($prefix . ProcessConst::LOOP_COUNTER, $loopCounter + 1); - } - // 追加会签类型参数 - $execution->getArgs()->put(ProcessConst::COUNTERSIGN_VARIABLE_PREFIX . ProcessConst::COUNTERSIGN_TYPE, CountersignTypeEnum::SEQUENTIAL[0]); - } - - foreach ($createTaskActors as $taskActor) { - $processTask = new ProcessTask(); - $processTask->set('perform_type', ProcessTaskPerformTypeEnum::COUNTERSIGN[0]); - $processTask->set('task_name', $taskModel->getName()); - $processTask->set('display_name', $taskModel->getDisplayName()); - $processTask->set('task_state', ProcessTaskStateEnum::DOING[0]); - $processTask->set('task_type', $taskModel->getTaskType()[0] ?? 0); - $processTask->set('process_instance_id', $execution->getProcessInstanceId()); - $execution->getArgs()->put(ProcessConst::IS_FIRST_TASK_NODE, ProcessFlowUtils::isFistTaskName($execution->getProcessModel(), $taskModel->getName())); - $processTask->set('Variable', $execution->getArgs()->getAll()); - $processTask->set('task_parent_id', $execution->getProcessTaskId() ?? 0); - $expireTime = $taskModel->getExpireTime(); - if (!empty($expireTime)) { - $processTask->set('expire_time', ProcessFlowUtils::processTime($expireTime, $execution->getArgs())); - } - $processTask->save(); - $execution->setProcessTask($processTask); - Logger::debug("创建会签任务" . $processTask->getData('task_name') . "," . $processTask->getData('display_name')); - $processTaskList[] = $processTask; - $this->addTaskActor($processTask->getData('id'), [$taskActor]); - } - - $processInstanceService = $execution->getEngine()->processInstanceService(); - // 更新会签变量到流程实例参数中 - $processInstanceService->updateCountersignVariable($taskModel, $execution, $taskActors); - return $processTaskList; - } - - public function history(Execution $execution, CustomModel $model): ?ProcessTask - { - $processTask = new ProcessTask(); - $processTask->set('process_instance_id', $execution->getProcessInstanceId()); - $processTask->set('create_time', time()); - $processTask->set('finish_time', time()); - $processTask->set('display_name', $model->getDisplayName()); - $processTask->set('task_name', $model->getNmae()); - $processTask->set('task_state', ProcessTaskStateEnum::FINISHED[0]); - $processTask->set('task_type', ProcessTaskTypeEnum::RECORD[0]); - $processTask->set('parent_id', $execution->getProcessTaskId()); - $processTask->set('variable', $execution->getArgs()); - return $processTask::create($processTask->toArray()); - } - -} diff --git a/src/service/ProcessTypesService.php b/src/service/ProcessTypesService.php deleted file mode 100644 index 7e7d9e4609b0d0fdfbf5a203a680b654c525c8cc..0000000000000000000000000000000000000000 --- a/src/service/ProcessTypesService.php +++ /dev/null @@ -1,133 +0,0 @@ -id); - $processType = new ProcessType(); - ModelUtils::copyProperties($param, $processType); - return $processType->save(); - } - - public function del(string|array|int $id): bool - { - $processType = new ProcessType(); - $map1 = []; - if (is_array($id)) { - $map1[] = ['id', 'in', $id]; - } else { - $map1[] = ['id', '=', $id]; - } - return $processType->where($map1)->delete(); - } - - public function update(object $param): bool - { - AssertHelper::notNull($param->id ?? '', '参数ID不能为空'); - $processType = $this->get($param->id); - ModelUtils::copyProperties($param, $processType); - return $processType->save(); - } - - public function page(object $param): array - { - /** @var TYPE_NAME $where */ - $where = ArrayHelper::paramsFilter($param, [ - ['is_del', 0], - ['name', ''], - ['status', ''], - ['pid', ''], - ]); - - [$page, $limit] = PageParam::getPageValue($param); - $list = $this->selectList($where, '*', $page, $limit, 'sort desc', ['parent','processDefine'], true)->toArray(); - foreach ($list as $key => $value) { - if (isset($value['parent']) && isset($value['parent']['name'])) { - $list[$key]['pid_name'] = $value['parent']['name']; - } else { - $list[$key]['pid_name'] = '顶级'; - } - unset($list[$key]['parent']); - } - $count = $this->count($where); - return compact('list', 'count'); - } - - public function findById(string $id): ?ProcessType - { - return $this->get($id); - } - - public function selectOptions(object $param): array - { - $where = ArrayHelper::paramsFilter($param, [ - ['is_del', 0], - ['name', ''], - ['status', ''], - ['pid', ''], - ]); - return $this->selectList($where, 'id as value,name as label', 0, 0, 'name', [], true)->toArray(); - } - - public function selectTree(object $param): array - { - $where = ArrayHelper::paramsFilter($param, [ - ['is_del', 0], - ['name', ''], - ['status', ''], - ['pid', ''], - ]); - // 获取根节点数据,并递归获取所有子节点数据 - $list = $this->selectList($where, '*', 0, 0, 'sort desc', ['parent'], true)->toArray(); - $count = count($list); - // 处理树形数据,将其转换为嵌套结构 - $list = $this->buildNestedTree($list); - return compact('list', 'count'); - } - - private function buildNestedTree($data, $parentId = '0'): array - { - $tree = []; - foreach ($data as $key => $value) { - if ($value['pid'] == $parentId) { - $value['pid_name'] = $value['parent']['name'] ?? '顶级'; - unset($value['parent']); - - $children = $this->buildNestedTree($data, $value['id']); - if (!empty($children)) { - $value['children'] = $children; - } - $tree[] = $value; - } - } - return $tree; - } -} diff --git a/src/service/interface/ProcessCcInstanceServiceInterface.php b/src/service/interface/ProcessCcInstanceServiceInterface.php deleted file mode 100644 index b1793017ec6a443102e7a1f23f35d2f63b2944e8..0000000000000000000000000000000000000000 --- a/src/service/interface/ProcessCcInstanceServiceInterface.php +++ /dev/null @@ -1,59 +0,0 @@ -process_design_id = '373c17e7-54bf-4e2e-8205-87a8818d2bd1'; - $param->content = (object)[]; - $param->create_user = '123'; - $processDesignHisService = new ProcessDesignHisService(); - return $processDesignHisService->create($param); - } - - //更新流程设计历史记录 - public function updateDesignHis($param): bool - { - $param->process_design_id = '373c17e7-54bf-4e2e-8205-87a8818d2bd1'; - $param->content = (object)[]; - $param->create_user = '1234'; - $param->id = '0ef9b6c4-1c3a-4ea5-8f5c-555bb8231aba'; - $processDesignHisService = new ProcessDesignHisService(); - return $processDesignHisService->update($param); - } - - public function designHisPage($param): array - { - $processDesignHisService = new ProcessDesignHisService(); - return $processDesignHisService->page($param); - } - - public function designHisLast($param): db\ProcessDesignHis|model\ProcessDesignHis|null - { - $processDesignId = $param->id; - $processDesignHisService = new ProcessDesignHisService(); - return $processDesignHisService->getLatestByProcessDesignId($processDesignId); - } - - /**流程定义******************************************************************************************************************/ - - public function defineCreate($param): bool - { - $param->type_id = ''; - $param->name = 'test'; - $param->display_name = '测试添加'; - $param->description = '描述'; - $param->state = 0; - $param->content = (object)[]; - $param->create_user = '123'; - $processDefineService = new ProcessDefineService(); - return $processDefineService->create($param); - } - - public function defineUpdate($param): bool - { - $param->id = 'a8a81338-49cd-49f1-be84-9e0c6a4149f2'; - $param->name = 'test'; - $param->display_name = '测试添加更新'; - $param->description = '描述'; - $param->state = 0; - $param->content = (object)[]; - $param->create_user = '1235'; - $processDefineService = new ProcessDefineService(); - return $processDefineService->update($param); - - } - - public function definePage($param): array - { - $processDefineService = new ProcessDefineService(); - return $processDefineService->page($param); - - } - - public function defineFindById($param): db\ProcessDefine - { - $processDefineService = new ProcessDefineService(); - return $processDefineService->findById($param->id); - } - - public function defineUnDeploy($param) - { - $processDefineService = new ProcessDefineService(); - $operation = '123'; - return $processDefineService->unDeploy($param->id, $operation); - } - - public function defineGetDefineJsonStr($param) - { - $processDefineService = new ProcessDefineService(); - return $processDefineService->getDefineJsonStr($param->id); - } - - public function defineUpAndDown($param) - { - $processDefineService = new ProcessDefineService(); - return $processDefineService->upAndDown($param); - } - - public function defineGetLastByName($param) - { - $processDefineService = new ProcessDefineService(); - return $processDefineService->getLastByName($param->name); - } - - public function defineGetProcessDefineByVersion($param) - { - $processDefineService = new ProcessDefineService(); - return $processDefineService->getProcessDefineByVersion($param->name, 4); - } - - /**流程实例*****************************************************************************************************************/ - - public function instancePage($param): array - { - $processDefineService = new ProcessInstanceService(); - return $processDefineService->page($param); - } - - public function instanceFinishProcessInstance($param) - { - $processDefineService = new ProcessInstanceService(); - return $processDefineService->finishProcessInstance($param->id); - } - - public function instanceCreateProcessInstance($param): db\ProcessInstance - { - $processDefineService = new ProcessDefineService(); - $processInstanceService = new ProcessInstanceService(); - $processDefine = $processDefineService->findById($param->id); - $args = (object)[ - 'test' => '12', - ]; - return $processInstanceService->createProcessInstance($processDefine, '123', $args, '', ''); - } - - public function instanceAddVariable($param): db\ProcessInstance - { - $processInstanceService = new ProcessInstanceService(); - $args = new Dict(); - $args->putAll([ - 'test' => '12', - 'name' => '测试', - ]); - return $processInstanceService->addVariable($param->id, $args); - } - - public function instanceRemoveVariable($param): db\ProcessInstance - { - $processInstanceService = new ProcessInstanceService(); - return $processInstanceService->removeVariable($param->id, 'u_deptId,f_title,aaaa'); - } - - public function instanceInterrupt($param) - { - $processInstanceService = new ProcessInstanceService(); - return $processInstanceService->interrupt($param->id, 'admin'); - } - - public function instanceResume($param) - { - $processInstanceService = new ProcessInstanceService(); - return $processInstanceService->resume($param->id, 'admin'); - } - - public function instancePending($param) - { - $processInstanceService = new ProcessInstanceService(); - return $processInstanceService->Pending($param->id, 'admin'); - } - - public function instanceActivate($param) - { - $processInstanceService = new ProcessInstanceService(); - return $processInstanceService->activate($param->id, 'admin'); - } - - public function startAndExecute($param) - { - $processInstanceService = new ProcessInstanceService(); - $args = new Dict(); - $args->putAll([ - ProcessConst::USER_USER_ID => 'admin',//用户id - 'f_uid' => '001', - ]); - return $processInstanceService->startAndExecute($param->id, $args); - } - - public function instanceHighLight($param) - { - $processInstanceService = new ProcessInstanceService(); - return $processInstanceService->highLight((string)$param->id); - } - - public function instanceApprovalRecord($param) - { - $processInstanceService = new ProcessInstanceService(); - return $processInstanceService->approvalRecord((string)$param->id); - } - - public function instanceWithdraw($param) - { - $processInstanceService = new ProcessInstanceService(); - return $processInstanceService->withdraw((string)$param->id, 'test'); - } - - public function instanceUpdateCCStatus($param) - { - $processInstanceService = new ProcessInstanceService(); - return $processInstanceService->updateCCStatus((string)$param->id, 'test'); - } - - public function instanceCreateCCInstance($param) - { - $processInstanceService = new ProcessInstanceService(); - return $processInstanceService->createCCInstance((string)$param->id, '1', 'test,admin'); - } - - public function instanceUpdateCountersignVariable($param) - { - - $processInstanceService = new ProcessInstanceService(); - return $processInstanceService->updateCountersignVariable((string)$param->id, '1', 'test,admin'); - } - - /**流程代理*****************************************************************************************************************/ - public function surrogatePage($param) - { - $processSurrogateService = new ProcessSurrogateService(); - return $processSurrogateService->page($param); - } - - public function surrogateGetSurrogate($param) - { - $processSurrogateService = new ProcessSurrogateService(); - return $processSurrogateService->getSurrogate('admin', 'leave'); - } - - /** 流程任务*****************************************************************************************************************/ - - public function taskFindById($param) - { - $processTaskService = new ProcessTaskService(); - return $processTaskService->findById('1729326781630730241'); - } - - public function addTaskActor($param) - { - $processTaskService = new ProcessTaskService(); - return $processTaskService->addTaskActor('1729326781630730241', ['admin', '1686404946814533633']); - } - - public function addCandidateActor($param) - { - $processTaskService = new ProcessTaskService(); - return $processTaskService->addCandidateActor('1729326781630730241', ['admin', '1686404946814533633']); - } - - public function removeTaskActor($param) - { - $processTaskService = new ProcessTaskService(); - return $processTaskService->removeTaskActor('1729326781630730241', 'admin'); - } - - public function getTaskActors($param) - { - $processTaskService = new ProcessTaskService(); - return $processTaskService->getTaskActors('1729326781630730241'); - } - - public function todoList($param) - { - $processTaskService = new ProcessTaskService(); - return $processTaskService->todoList($param); - } - - public function doneList($param) - { - $processTaskService = new ProcessTaskService(); - return $processTaskService->doneList($param); - } - - /*接口测试*******************************************************************************************/ - - public function startProcessInstanceById($param) - { - $processEngines = new ProcessEngines(); - $args = ProcessFlowUtils::variableToDict((object)['uid' => '1']); - return $processEngines->startProcessInstanceById($param['id'], $param['operator'], $args, '', ''); - } - - public function executeAndJumpTask($param) - { - $processEngines = new ProcessEngines(); - $args = ProcessFlowUtils::variableToDict((object)['f_uid' => '1', 'f_day' => 3, 'u_udd' => 're']); - return $processEngines->executeAndJumpTask($param['id'], $param['operator'], $args, '', ''); - } - - public function executeProcessTask($param) - { - $processEngines = new ProcessEngines(); - $args = ProcessFlowUtils::variableToDict((object)['f_uid' => '1', 'f_day' => 3, 'u_udd' => 're']); - return $processEngines->executeProcessTask($param['id'], $param['operator'], $args); - } - - public function executeAndJumpToEnd($param) - { -// $config = ['getUser' => new UserAssign()]; - $processEngines = new ProcessEngines([]); - $args = ProcessFlowUtils::variableToDict((object)['f_uid' => '1', 'f_day' => 3, 'u_udd' => 're']); - return $processEngines->executeAndJumpToEnd($param['id'], $param['operator'], $args); - } - - public function index($param, $operation) - { -// $param = (object)$param; - $engines = new ProcessEngines(); -// dump($engines);exit; -// $testClass = new ProcessDesignService(); -// return $testClass->redeploy($param->id, $operation); - Db::startTrans(); -// $result = $this->executeAndJumpToEnd($param); - -// $result = new StringBuilder(); -// $result->append('123,'); -// $result->append('321,'); - -// dump($result->toArray()); - -// $logFilePath = __DIR__ . '/logs'; -// $logLevel = Logger::DEBUG; -// $monthsToKeep = 3; -// -// $log = Log::getLogger('debug', $logFilePath, $logLevel); -// $log->info('This is an info message.'); -// $log=new Log(); -//CustomLogger::getInstance()->deleteOldLogs(); -// Logs::getInstance()->deleteOldLogs(); -// Logs::getInstance()->info('This is an info message.'); - -// CustomLogger::getInstance()->info('This is an info message.'); - -// 删除旧的跨月日志 -// Log::deleteOldLogs($logFilePath, $monthsToKeep); -// Logs::log('debug','测试'); -// Logs::log('info','infooo'); -// Logger::info('message'); - Logger::debug('message'); -// Logger::notice('notice'); -// Logger::deleteOldLogs(); - -// Db::commit(); - dump('启动成功12'); - exit; - } - - - -} -